mirror of
https://github.com/aniyomiorg/aniyomi.git
synced 2024-11-21 12:17:12 +03:00
crash fix & add forgotten commit
No idea how I didn't add it yet. Commit: efabe801be
This commit is contained in:
parent
18e04b75df
commit
99eea595c0
5 changed files with 132 additions and 82 deletions
|
@ -30,6 +30,10 @@ import eu.kanade.domain.source.manga.interactor.ToggleMangaSource
|
|||
import eu.kanade.domain.source.manga.interactor.ToggleMangaSourcePin
|
||||
import eu.kanade.domain.source.service.SetMigrateSorting
|
||||
import eu.kanade.domain.source.service.ToggleLanguage
|
||||
import eu.kanade.domain.track.anime.interactor.RefreshAnimeTracks
|
||||
import eu.kanade.domain.track.anime.interactor.TrackEpisode
|
||||
import eu.kanade.domain.track.manga.interactor.RefreshMangaTracks
|
||||
import eu.kanade.domain.track.manga.interactor.TrackChapter
|
||||
import tachiyomi.data.category.anime.AnimeCategoryRepositoryImpl
|
||||
import tachiyomi.data.category.manga.MangaCategoryRepositoryImpl
|
||||
import tachiyomi.data.entries.anime.AnimeRepositoryImpl
|
||||
|
@ -217,12 +221,16 @@ class DomainModule : InjektModule {
|
|||
addFactory { GetApplicationRelease(get(), get()) }
|
||||
|
||||
addSingletonFactory<AnimeTrackRepository> { AnimeTrackRepositoryImpl(get()) }
|
||||
addFactory { TrackEpisode(get(), get(), get(), get()) }
|
||||
addFactory { RefreshAnimeTracks(get(), get(), get(), get()) }
|
||||
addFactory { DeleteAnimeTrack(get()) }
|
||||
addFactory { GetTracksPerAnime(get()) }
|
||||
addFactory { GetAnimeTracks(get()) }
|
||||
addFactory { InsertAnimeTrack(get()) }
|
||||
|
||||
addSingletonFactory<MangaTrackRepository> { MangaTrackRepositoryImpl(get()) }
|
||||
addFactory { TrackChapter(get(), get(), get(), get()) }
|
||||
addFactory { RefreshMangaTracks(get(), get(), get(), get()) }
|
||||
addFactory { DeleteMangaTrack(get()) }
|
||||
addFactory { GetTracksPerManga(get()) }
|
||||
addFactory { GetMangaTracks(get()) }
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package eu.kanade.domain.track.anime.interactor
|
||||
|
||||
import android.content.Context
|
||||
import eu.kanade.domain.track.anime.model.toDbTrack
|
||||
import eu.kanade.domain.track.anime.service.DelayedAnimeTrackingUpdateJob
|
||||
import eu.kanade.domain.track.anime.store.DelayedAnimeTrackingStore
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.util.lang.launchNonCancellable
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.domain.track.anime.interactor.GetAnimeTracks
|
||||
import tachiyomi.domain.track.anime.interactor.InsertAnimeTrack
|
||||
|
||||
class TrackEpisode(
|
||||
private val getTracks: GetAnimeTracks,
|
||||
private val trackManager: TrackManager,
|
||||
private val insertTrack: InsertAnimeTrack,
|
||||
private val delayedTrackingStore: DelayedAnimeTrackingStore,
|
||||
) {
|
||||
|
||||
suspend fun await(context: Context, animeId: Long, episodeNumber: Double) = coroutineScope {
|
||||
launchNonCancellable {
|
||||
val tracks = getTracks.await(animeId)
|
||||
|
||||
if (tracks.isEmpty()) return@launchNonCancellable
|
||||
|
||||
tracks.mapNotNull { track ->
|
||||
val service = trackManager.getService(track.syncId)
|
||||
if (service != null && service.isLoggedIn && episodeNumber > track.lastEpisodeSeen) {
|
||||
val updatedTrack = track.copy(lastEpisodeSeen = episodeNumber)
|
||||
|
||||
async {
|
||||
runCatching {
|
||||
try {
|
||||
service.animeService.update(updatedTrack.toDbTrack(), true)
|
||||
insertTrack.await(updatedTrack)
|
||||
} catch (e: Exception) {
|
||||
delayedTrackingStore.addAnimeItem(updatedTrack)
|
||||
DelayedAnimeTrackingUpdateJob.setupTask(context)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
.awaitAll()
|
||||
.mapNotNull { it.exceptionOrNull() }
|
||||
.forEach { logcat(LogPriority.INFO, it) }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package eu.kanade.domain.track.manga.interactor
|
||||
|
||||
import android.content.Context
|
||||
import eu.kanade.domain.track.manga.model.toDbTrack
|
||||
import eu.kanade.domain.track.manga.service.DelayedMangaTrackingUpdateJob
|
||||
import eu.kanade.domain.track.manga.store.DelayedMangaTrackingStore
|
||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.awaitAll
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import logcat.LogPriority
|
||||
import tachiyomi.core.util.lang.launchNonCancellable
|
||||
import tachiyomi.core.util.system.logcat
|
||||
import tachiyomi.domain.track.manga.interactor.GetMangaTracks
|
||||
import tachiyomi.domain.track.manga.interactor.InsertMangaTrack
|
||||
|
||||
class TrackChapter(
|
||||
private val getTracks: GetMangaTracks,
|
||||
private val trackManager: TrackManager,
|
||||
private val insertTrack: InsertMangaTrack,
|
||||
private val delayedTrackingStore: DelayedMangaTrackingStore,
|
||||
) {
|
||||
|
||||
suspend fun await(context: Context, mangaId: Long, chapterNumber: Double) = coroutineScope {
|
||||
launchNonCancellable {
|
||||
val tracks = getTracks.await(mangaId)
|
||||
|
||||
if (tracks.isEmpty()) return@launchNonCancellable
|
||||
|
||||
tracks.mapNotNull { track ->
|
||||
val service = trackManager.getService(track.syncId)
|
||||
if (service != null && service.isLoggedIn && chapterNumber > track.lastChapterRead) {
|
||||
val updatedTrack = track.copy(lastChapterRead = chapterNumber)
|
||||
|
||||
async {
|
||||
runCatching {
|
||||
try {
|
||||
service.mangaService.update(updatedTrack.toDbTrack(), true)
|
||||
insertTrack.await(updatedTrack)
|
||||
} catch (e: Exception) {
|
||||
delayedTrackingStore.addMangaItem(updatedTrack)
|
||||
DelayedMangaTrackingUpdateJob.setupTask(context)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
.awaitAll()
|
||||
.mapNotNull { it.exceptionOrNull() }
|
||||
.forEach { logcat(LogPriority.INFO, it) }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,6 +10,7 @@ import eu.kanade.core.util.asFlow
|
|||
import eu.kanade.domain.base.BasePreferences
|
||||
import eu.kanade.domain.entries.anime.interactor.SetAnimeViewerFlags
|
||||
import eu.kanade.domain.items.episode.model.toDbEpisode
|
||||
import eu.kanade.domain.track.anime.interactor.TrackEpisode
|
||||
import eu.kanade.domain.track.anime.model.toDbTrack
|
||||
import eu.kanade.domain.track.anime.service.DelayedAnimeTrackingUpdateJob
|
||||
import eu.kanade.domain.track.anime.store.DelayedAnimeTrackingStore
|
||||
|
@ -84,12 +85,11 @@ class PlayerViewModel @JvmOverloads constructor(
|
|||
private val imageSaver: ImageSaver = Injekt.get(),
|
||||
private val downloadPreferences: DownloadPreferences = Injekt.get(),
|
||||
private val trackPreferences: TrackPreferences = Injekt.get(),
|
||||
private val delayedTrackingStore: DelayedAnimeTrackingStore = Injekt.get(),
|
||||
private val trackEpisode: TrackEpisode = Injekt.get(),
|
||||
private val getAnime: GetAnime = Injekt.get(),
|
||||
private val getNextEpisodes: GetNextEpisodes = Injekt.get(),
|
||||
private val getEpisodeByAnimeId: GetEpisodeByAnimeId = Injekt.get(),
|
||||
private val getTracks: GetAnimeTracks = Injekt.get(),
|
||||
private val insertTrack: InsertAnimeTrack = Injekt.get(),
|
||||
private val upsertHistory: UpsertAnimeHistory = Injekt.get(),
|
||||
private val updateEpisode: UpdateEpisode = Injekt.get(),
|
||||
private val setAnimeViewerFlags: SetAnimeViewerFlags = Injekt.get(),
|
||||
|
@ -306,7 +306,6 @@ class PlayerViewModel @JvmOverloads constructor(
|
|||
}
|
||||
|
||||
private var hasTrackers: Boolean = false
|
||||
|
||||
private val checkTrackers: (Anime) -> Unit = { anime ->
|
||||
val tracks = runBlocking { getTracks.await(anime.id) }
|
||||
hasTrackers = tracks.isNotEmpty()
|
||||
|
@ -585,38 +584,11 @@ class PlayerViewModel @JvmOverloads constructor(
|
|||
if (!trackPreferences.autoUpdateTrack().get()) return
|
||||
|
||||
val anime = currentAnime ?: return
|
||||
val episodeSeen = episode.episode_number.toDouble()
|
||||
|
||||
val trackManager = Injekt.get<TrackManager>()
|
||||
val context = Injekt.get<Application>()
|
||||
|
||||
viewModelScope.launchNonCancellable {
|
||||
getTracks.await(anime.id)
|
||||
.mapNotNull { track ->
|
||||
val service = trackManager.getService(track.syncId)
|
||||
if (service != null && service.isLoggedIn && episodeSeen > track.lastEpisodeSeen) {
|
||||
val updatedTrack = track.copy(lastEpisodeSeen = episodeSeen)
|
||||
|
||||
// We want these to execute even if the presenter is destroyed and leaks
|
||||
// for a while. The view can still be garbage collected.
|
||||
async {
|
||||
runCatching {
|
||||
if (context.isOnline()) {
|
||||
service.animeService.update(updatedTrack.toDbTrack(), true)
|
||||
insertTrack.await(updatedTrack)
|
||||
} else {
|
||||
delayedTrackingStore.addAnimeItem(updatedTrack)
|
||||
DelayedAnimeTrackingUpdateJob.setupTask(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
.awaitAll()
|
||||
.mapNotNull { it.exceptionOrNull() }
|
||||
.forEach { logcat(LogPriority.INFO, it) }
|
||||
trackEpisode.await(context, anime.id, episode.episode_number.toDouble())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import eu.kanade.domain.entries.manga.interactor.SetMangaViewerFlags
|
|||
import eu.kanade.domain.entries.manga.model.orientationType
|
||||
import eu.kanade.domain.entries.manga.model.readingModeType
|
||||
import eu.kanade.domain.items.chapter.model.toDbChapter
|
||||
import eu.kanade.domain.track.manga.interactor.TrackChapter
|
||||
import eu.kanade.domain.track.manga.model.toDbTrack
|
||||
import eu.kanade.domain.track.manga.service.DelayedMangaTrackingUpdateJob
|
||||
import eu.kanade.domain.track.manga.store.DelayedMangaTrackingStore
|
||||
|
@ -98,12 +99,10 @@ class ReaderViewModel @JvmOverloads constructor(
|
|||
private val basePreferences: BasePreferences = Injekt.get(),
|
||||
private val downloadPreferences: DownloadPreferences = Injekt.get(),
|
||||
private val trackPreferences: TrackPreferences = Injekt.get(),
|
||||
private val delayedTrackingStore: DelayedMangaTrackingStore = Injekt.get(),
|
||||
private val trackChapter: TrackChapter = Injekt.get(),
|
||||
private val getManga: GetManga = Injekt.get(),
|
||||
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
|
||||
private val getNextChapters: GetNextChapters = Injekt.get(),
|
||||
private val getTracks: GetMangaTracks = Injekt.get(),
|
||||
private val insertTrack: InsertMangaTrack = Injekt.get(),
|
||||
private val upsertHistory: UpsertMangaHistory = Injekt.get(),
|
||||
private val updateChapter: UpdateChapter = Injekt.get(),
|
||||
private val setMangaViewerFlags: SetMangaViewerFlags = Injekt.get(),
|
||||
|
@ -222,12 +221,6 @@ class ReaderViewModel @JvmOverloads constructor(
|
|||
.map(::ReaderChapter)
|
||||
}
|
||||
|
||||
private var hasTrackers: Boolean = false
|
||||
private val checkTrackers: (Manga) -> Unit = { manga ->
|
||||
val tracks = runBlocking { getTracks.await(manga.id) }
|
||||
hasTrackers = tracks.isNotEmpty()
|
||||
}
|
||||
|
||||
private val incognitoMode = preferences.incognitoMode().get()
|
||||
private val downloadAheadAmount = downloadPreferences.autoDownloadWhileReading().get()
|
||||
|
||||
|
@ -286,8 +279,6 @@ class ReaderViewModel @JvmOverloads constructor(
|
|||
mutableState.update { it.copy(manga = manga) }
|
||||
if (chapterId == -1L) chapterId = initialChapterId
|
||||
|
||||
checkTrackers(manga)
|
||||
|
||||
val context = Injekt.get<Application>()
|
||||
val source = sourceManager.getOrStub(manga.source)
|
||||
loader = ChapterLoader(
|
||||
|
@ -566,18 +557,19 @@ class ReaderViewModel @JvmOverloads constructor(
|
|||
}
|
||||
|
||||
fun flushReadTimer() {
|
||||
viewModelScope.launchNonCancellable {
|
||||
updateHistory()
|
||||
getCurrentChapter()?.let {
|
||||
viewModelScope.launchNonCancellable {
|
||||
updateHistory(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the chapter last read history if incognito mode isn't on.
|
||||
*/
|
||||
private suspend fun updateHistory() {
|
||||
private suspend fun updateHistory(readerChapter: ReaderChapter) {
|
||||
if (incognitoMode) return
|
||||
|
||||
val readerChapter = getCurrentChapter() ?: return
|
||||
val chapterId = readerChapter.chapter.id!!
|
||||
val readAt = Date()
|
||||
val sessionReadDuration = chapterReadStartTime?.let { readAt.time - it } ?: 0
|
||||
|
@ -887,48 +879,14 @@ class ReaderViewModel @JvmOverloads constructor(
|
|||
* will run in a background thread and errors are ignored.
|
||||
*/
|
||||
private fun updateTrackChapterRead(readerChapter: ReaderChapter) {
|
||||
if (incognitoMode || !hasTrackers) return
|
||||
if (incognitoMode) return
|
||||
if (!trackPreferences.autoUpdateTrack().get()) return
|
||||
|
||||
val manga = manga ?: return
|
||||
val chapterRead = readerChapter.chapter.chapter_number.toDouble()
|
||||
|
||||
val trackManager = Injekt.get<TrackManager>()
|
||||
val context = Injekt.get<Application>()
|
||||
|
||||
viewModelScope.launchNonCancellable {
|
||||
getTracks.await(manga.id)
|
||||
.mapNotNull { track ->
|
||||
val service = trackManager.getService(track.syncId)
|
||||
if (service != null && service.isLoggedIn && chapterRead > track.lastChapterRead) {
|
||||
val updatedTrack = track.copy(lastChapterRead = chapterRead)
|
||||
|
||||
// We want these to execute even if the presenter is destroyed and leaks
|
||||
// for a while. The view can still be garbage collected.
|
||||
async {
|
||||
runCatching {
|
||||
try {
|
||||
if (!context.isOnline()) {
|
||||
error(
|
||||
"Couldn't update tracker as device is offline",
|
||||
)
|
||||
}
|
||||
service.mangaService.update(updatedTrack.toDbTrack(), true)
|
||||
insertTrack.await(updatedTrack)
|
||||
} catch (e: Exception) {
|
||||
delayedTrackingStore.addMangaItem(updatedTrack)
|
||||
DelayedMangaTrackingUpdateJob.setupTask(context)
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
.awaitAll()
|
||||
.mapNotNull { it.exceptionOrNull() }
|
||||
.forEach { logcat(LogPriority.INFO, it) }
|
||||
trackChapter.await(context, manga.id, readerChapter.chapter.chapter_number.toDouble())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue