Ver código fonte

Reset lastPageRead when chapter is marked unread (#7475)

* Reset lastPageRead when chapter is marked unread

* Remove a bit of repetition in SetReadStatus
Andreas 2 anos atrás
pai
commit
5159eabc5d

+ 5 - 0
app/src/main/java/eu/kanade/domain/DomainModule.kt

@@ -14,11 +14,13 @@ import eu.kanade.domain.category.interactor.UpdateCategory
 import eu.kanade.domain.category.repository.CategoryRepository
 import eu.kanade.domain.chapter.interactor.GetChapter
 import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
+import eu.kanade.domain.chapter.interactor.SetReadStatus
 import eu.kanade.domain.chapter.interactor.ShouldUpdateDbChapter
 import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
 import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
 import eu.kanade.domain.chapter.interactor.UpdateChapter
 import eu.kanade.domain.chapter.repository.ChapterRepository
+import eu.kanade.domain.download.interactor.DeleteDownload
 import eu.kanade.domain.extension.interactor.GetExtensionLanguages
 import eu.kanade.domain.extension.interactor.GetExtensionSources
 import eu.kanade.domain.extension.interactor.GetExtensionUpdates
@@ -94,6 +96,7 @@ class DomainModule : InjektModule {
         addFactory { GetChapter(get()) }
         addFactory { GetChapterByMangaId(get()) }
         addFactory { UpdateChapter(get()) }
+        addFactory { SetReadStatus(get(), get(), get(), get()) }
         addFactory { ShouldUpdateDbChapter() }
         addFactory { SyncChaptersWithSource(get(), get(), get(), get()) }
         addFactory { SyncChaptersWithTrackServiceTwoWay(get(), get()) }
@@ -105,6 +108,8 @@ class DomainModule : InjektModule {
         addFactory { RemoveHistoryById(get()) }
         addFactory { RemoveHistoryByMangaId(get()) }
 
+        addFactory { DeleteDownload(get(), get()) }
+
         addFactory { GetExtensions(get(), get()) }
         addFactory { GetExtensionSources(get()) }
         addFactory { GetExtensionUpdates(get(), get()) }

+ 86 - 0
app/src/main/java/eu/kanade/domain/chapter/interactor/SetReadStatus.kt

@@ -0,0 +1,86 @@
+package eu.kanade.domain.chapter.interactor
+
+import eu.kanade.domain.chapter.model.Chapter
+import eu.kanade.domain.chapter.model.ChapterUpdate
+import eu.kanade.domain.chapter.repository.ChapterRepository
+import eu.kanade.domain.download.interactor.DeleteDownload
+import eu.kanade.domain.manga.model.Manga
+import eu.kanade.domain.manga.repository.MangaRepository
+import eu.kanade.tachiyomi.data.preference.PreferencesHelper
+import eu.kanade.tachiyomi.util.system.logcat
+import kotlinx.coroutines.NonCancellable
+import kotlinx.coroutines.withContext
+import logcat.LogPriority
+
+class SetReadStatus(
+    private val preferences: PreferencesHelper,
+    private val deleteDownload: DeleteDownload,
+    private val mangaRepository: MangaRepository,
+    private val chapterRepository: ChapterRepository,
+) {
+
+    private val mapper = { chapter: Chapter, read: Boolean ->
+        ChapterUpdate(
+            read = read,
+            lastPageRead = if (!read) 0 else null,
+            id = chapter.id,
+        )
+    }
+
+    suspend fun await(read: Boolean, vararg values: Chapter): Result = withContext(NonCancellable) f@{
+        val chapters = values.filterNot { it.read == read }
+
+        if (chapters.isEmpty()) {
+            return@f Result.NoChapters
+        }
+
+        val manga = chapters.fold(mutableSetOf<Manga>()) { acc, chapter ->
+            if (acc.all { it.id != chapter.mangaId }) {
+                acc += mangaRepository.getMangaById(chapter.mangaId)
+            }
+            acc
+        }
+
+        try {
+            chapterRepository.updateAll(
+                chapters.map { chapter ->
+                    mapper(chapter, read)
+                },
+            )
+        } catch (e: Exception) {
+            logcat(LogPriority.ERROR, e)
+            return@f Result.InternalError(e)
+        }
+
+        if (read && preferences.removeAfterMarkedAsRead()) {
+            manga.forEach { manga ->
+                deleteDownload.awaitAll(
+                    manga = manga,
+                    values = chapters
+                        .filter { manga.id == it.mangaId }
+                        .toTypedArray(),
+                )
+            }
+        }
+
+        Result.Success
+    }
+
+    suspend fun await(mangaId: Long, read: Boolean): Result = withContext(NonCancellable) f@{
+        return@f await(
+            read = read,
+            values = chapterRepository
+                .getChapterByMangaId(mangaId)
+                .toTypedArray(),
+        )
+    }
+
+    suspend fun await(manga: Manga, read: Boolean) =
+        await(manga.id, read)
+
+    sealed class Result {
+        object Success : Result()
+        object NoChapters : Result()
+        data class InternalError(val error: Throwable) : Result()
+    }
+}

+ 21 - 0
app/src/main/java/eu/kanade/domain/download/interactor/DeleteDownload.kt

@@ -0,0 +1,21 @@
+package eu.kanade.domain.download.interactor
+
+import eu.kanade.domain.chapter.model.Chapter
+import eu.kanade.domain.chapter.model.toDbChapter
+import eu.kanade.domain.manga.model.Manga
+import eu.kanade.tachiyomi.data.download.DownloadManager
+import eu.kanade.tachiyomi.source.SourceManager
+import kotlinx.coroutines.NonCancellable
+import kotlinx.coroutines.withContext
+
+class DeleteDownload(
+    private val sourceManager: SourceManager,
+    private val downloadManager: DownloadManager,
+) {
+
+    suspend fun awaitAll(manga: Manga, vararg values: Chapter) = withContext(NonCancellable) {
+        sourceManager.get(manga.source)?.let { source ->
+            downloadManager.deleteChapters(values.map { it.toDbChapter() }, manga, source)
+        }
+    }
+}

+ 6 - 23
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt

@@ -8,9 +8,8 @@ import eu.kanade.domain.category.interactor.GetCategories
 import eu.kanade.domain.category.interactor.SetMangaCategories
 import eu.kanade.domain.category.model.Category
 import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
+import eu.kanade.domain.chapter.interactor.SetReadStatus
 import eu.kanade.domain.chapter.interactor.UpdateChapter
-import eu.kanade.domain.chapter.model.Chapter
-import eu.kanade.domain.chapter.model.ChapterUpdate
 import eu.kanade.domain.chapter.model.toDbChapter
 import eu.kanade.domain.manga.interactor.GetLibraryManga
 import eu.kanade.domain.manga.interactor.UpdateManga
@@ -65,6 +64,7 @@ class LibraryPresenter(
     private val getTracks: GetTracks = Injekt.get(),
     private val getCategories: GetCategories = Injekt.get(),
     private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
+    private val setReadStatus: SetReadStatus = Injekt.get(),
     private val updateChapter: UpdateChapter = Injekt.get(),
     private val updateManga: UpdateManga = Injekt.get(),
     private val setMangaCategories: SetMangaCategories = Injekt.get(),
@@ -533,31 +533,14 @@ class LibraryPresenter(
     fun markReadStatus(mangas: List<Manga>, read: Boolean) {
         mangas.forEach { manga ->
             launchIO {
-                val chapters = getChapterByMangaId.await(manga.id)
-
-                val toUpdate = chapters
-                    .map { chapter ->
-                        ChapterUpdate(
-                            read = read,
-                            lastPageRead = if (read) 0 else null,
-                            id = chapter.id,
-                        )
-                    }
-                updateChapter.awaitAll(toUpdate)
-
-                if (read && preferences.removeAfterMarkedAsRead()) {
-                    deleteChapters(manga, chapters)
-                }
+                setReadStatus.await(
+                    manga = manga,
+                    read = read,
+                )
             }
         }
     }
 
-    private fun deleteChapters(manga: Manga, chapters: List<Chapter>) {
-        sourceManager.get(manga.source)?.let { source ->
-            downloadManager.deleteChapters(chapters.map { it.toDbChapter() }, manga, source)
-        }
-    }
-
     /**
      * Remove the selected manga.
      *

+ 6 - 7
app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt

@@ -5,6 +5,7 @@ import androidx.compose.runtime.Immutable
 import eu.kanade.domain.category.interactor.GetCategories
 import eu.kanade.domain.category.interactor.SetMangaCategories
 import eu.kanade.domain.category.model.Category
+import eu.kanade.domain.chapter.interactor.SetReadStatus
 import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
 import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
 import eu.kanade.domain.chapter.interactor.UpdateChapter
@@ -79,6 +80,7 @@ class MangaPresenter(
     private val getMangaAndChapters: GetMangaWithChapters = Injekt.get(),
     private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(),
     private val setMangaChapterFlags: SetMangaChapterFlags = Injekt.get(),
+    private val setReadStatus: SetReadStatus = Injekt.get(),
     private val updateChapter: UpdateChapter = Injekt.get(),
     private val updateManga: UpdateManga = Injekt.get(),
     private val syncChaptersWithSource: SyncChaptersWithSource = Injekt.get(),
@@ -525,13 +527,10 @@ class MangaPresenter(
      */
     fun markChaptersRead(chapters: List<DomainChapter>, read: Boolean) {
         presenterScope.launchIO {
-            val modified = chapters.filterNot { it.read == read }
-            modified
-                .map { ChapterUpdate(id = it.id, read = read) }
-                .let { updateChapter.awaitAll(it) }
-            if (read && preferences.removeAfterMarkedAsRead()) {
-                deleteChapters(modified)
-            }
+            setReadStatus.await(
+                read = read,
+                values = chapters.toTypedArray(),
+            )
         }
     }
 

+ 0 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesController.kt

@@ -249,9 +249,6 @@ class UpdatesController :
      */
     private fun markAsRead(chapters: List<UpdatesItem>) {
         presenter.markChapterRead(chapters, true)
-        if (presenter.preferences.removeAfterMarkedAsRead()) {
-            deleteChapters(chapters)
-        }
         destroyActionModeIfNeeded()
     }
 

+ 8 - 8
app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesPresenter.kt

@@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.recent.updates
 import android.os.Bundle
 import eu.kanade.data.DatabaseHandler
 import eu.kanade.data.manga.mangaChapterMapper
+import eu.kanade.domain.chapter.interactor.SetReadStatus
 import eu.kanade.domain.chapter.interactor.UpdateChapter
 import eu.kanade.domain.chapter.model.Chapter
 import eu.kanade.domain.chapter.model.ChapterUpdate
@@ -40,6 +41,7 @@ class UpdatesPresenter : BasePresenter<UpdatesController>() {
 
     private val handler: DatabaseHandler by injectLazy()
     private val updateChapter: UpdateChapter by injectLazy()
+    private val setReadStatus: SetReadStatus by injectLazy()
 
     private val relativeTime: Int = preferences.relativeTime().get()
     private val dateFormat: DateFormat = preferences.dateFormat()
@@ -167,14 +169,12 @@ class UpdatesPresenter : BasePresenter<UpdatesController>() {
      */
     fun markChapterRead(items: List<UpdatesItem>, read: Boolean) {
         presenterScope.launchIO {
-            val toUpdate = items.map {
-                ChapterUpdate(
-                    read = read,
-                    lastPageRead = if (!read) 0 else null,
-                    id = it.chapter.id,
-                )
-            }
-            updateChapter.awaitAll(toUpdate)
+            setReadStatus.await(
+                read = read,
+                values = items
+                    .map { it.chapter }
+                    .toTypedArray(),
+            )
         }
     }