Reset lastPageRead when chapter is marked unread (#7475)
* Reset lastPageRead when chapter is marked unread * Remove a bit of repetition in SetReadStatus
This commit is contained in:
parent
9357af2bcf
commit
5159eabc5d
7 changed files with 132 additions and 41 deletions
|
@ -14,11 +14,13 @@ import eu.kanade.domain.category.interactor.UpdateCategory
|
||||||
import eu.kanade.domain.category.repository.CategoryRepository
|
import eu.kanade.domain.category.repository.CategoryRepository
|
||||||
import eu.kanade.domain.chapter.interactor.GetChapter
|
import eu.kanade.domain.chapter.interactor.GetChapter
|
||||||
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
|
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.ShouldUpdateDbChapter
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
|
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
|
||||||
import eu.kanade.domain.chapter.interactor.UpdateChapter
|
import eu.kanade.domain.chapter.interactor.UpdateChapter
|
||||||
import eu.kanade.domain.chapter.repository.ChapterRepository
|
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.GetExtensionLanguages
|
||||||
import eu.kanade.domain.extension.interactor.GetExtensionSources
|
import eu.kanade.domain.extension.interactor.GetExtensionSources
|
||||||
import eu.kanade.domain.extension.interactor.GetExtensionUpdates
|
import eu.kanade.domain.extension.interactor.GetExtensionUpdates
|
||||||
|
@ -94,6 +96,7 @@ class DomainModule : InjektModule {
|
||||||
addFactory { GetChapter(get()) }
|
addFactory { GetChapter(get()) }
|
||||||
addFactory { GetChapterByMangaId(get()) }
|
addFactory { GetChapterByMangaId(get()) }
|
||||||
addFactory { UpdateChapter(get()) }
|
addFactory { UpdateChapter(get()) }
|
||||||
|
addFactory { SetReadStatus(get(), get(), get(), get()) }
|
||||||
addFactory { ShouldUpdateDbChapter() }
|
addFactory { ShouldUpdateDbChapter() }
|
||||||
addFactory { SyncChaptersWithSource(get(), get(), get(), get()) }
|
addFactory { SyncChaptersWithSource(get(), get(), get(), get()) }
|
||||||
addFactory { SyncChaptersWithTrackServiceTwoWay(get(), get()) }
|
addFactory { SyncChaptersWithTrackServiceTwoWay(get(), get()) }
|
||||||
|
@ -105,6 +108,8 @@ class DomainModule : InjektModule {
|
||||||
addFactory { RemoveHistoryById(get()) }
|
addFactory { RemoveHistoryById(get()) }
|
||||||
addFactory { RemoveHistoryByMangaId(get()) }
|
addFactory { RemoveHistoryByMangaId(get()) }
|
||||||
|
|
||||||
|
addFactory { DeleteDownload(get(), get()) }
|
||||||
|
|
||||||
addFactory { GetExtensions(get(), get()) }
|
addFactory { GetExtensions(get(), get()) }
|
||||||
addFactory { GetExtensionSources(get()) }
|
addFactory { GetExtensionSources(get()) }
|
||||||
addFactory { GetExtensionUpdates(get(), get()) }
|
addFactory { GetExtensionUpdates(get(), get()) }
|
||||||
|
|
|
@ -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()
|
||||||
|
}
|
||||||
|
}
|
|
@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,9 +8,8 @@ import eu.kanade.domain.category.interactor.GetCategories
|
||||||
import eu.kanade.domain.category.interactor.SetMangaCategories
|
import eu.kanade.domain.category.interactor.SetMangaCategories
|
||||||
import eu.kanade.domain.category.model.Category
|
import eu.kanade.domain.category.model.Category
|
||||||
import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
|
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.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.chapter.model.toDbChapter
|
||||||
import eu.kanade.domain.manga.interactor.GetLibraryManga
|
import eu.kanade.domain.manga.interactor.GetLibraryManga
|
||||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||||
|
@ -65,6 +64,7 @@ class LibraryPresenter(
|
||||||
private val getTracks: GetTracks = Injekt.get(),
|
private val getTracks: GetTracks = Injekt.get(),
|
||||||
private val getCategories: GetCategories = Injekt.get(),
|
private val getCategories: GetCategories = Injekt.get(),
|
||||||
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
|
private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(),
|
||||||
|
private val setReadStatus: SetReadStatus = Injekt.get(),
|
||||||
private val updateChapter: UpdateChapter = Injekt.get(),
|
private val updateChapter: UpdateChapter = Injekt.get(),
|
||||||
private val updateManga: UpdateManga = Injekt.get(),
|
private val updateManga: UpdateManga = Injekt.get(),
|
||||||
private val setMangaCategories: SetMangaCategories = Injekt.get(),
|
private val setMangaCategories: SetMangaCategories = Injekt.get(),
|
||||||
|
@ -533,31 +533,14 @@ class LibraryPresenter(
|
||||||
fun markReadStatus(mangas: List<Manga>, read: Boolean) {
|
fun markReadStatus(mangas: List<Manga>, read: Boolean) {
|
||||||
mangas.forEach { manga ->
|
mangas.forEach { manga ->
|
||||||
launchIO {
|
launchIO {
|
||||||
val chapters = getChapterByMangaId.await(manga.id)
|
setReadStatus.await(
|
||||||
|
manga = manga,
|
||||||
val toUpdate = chapters
|
read = read,
|
||||||
.map { chapter ->
|
)
|
||||||
ChapterUpdate(
|
|
||||||
read = read,
|
|
||||||
lastPageRead = if (read) 0 else null,
|
|
||||||
id = chapter.id,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
updateChapter.awaitAll(toUpdate)
|
|
||||||
|
|
||||||
if (read && preferences.removeAfterMarkedAsRead()) {
|
|
||||||
deleteChapters(manga, chapters)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
* Remove the selected manga.
|
||||||
*
|
*
|
||||||
|
|
|
@ -5,6 +5,7 @@ import androidx.compose.runtime.Immutable
|
||||||
import eu.kanade.domain.category.interactor.GetCategories
|
import eu.kanade.domain.category.interactor.GetCategories
|
||||||
import eu.kanade.domain.category.interactor.SetMangaCategories
|
import eu.kanade.domain.category.interactor.SetMangaCategories
|
||||||
import eu.kanade.domain.category.model.Category
|
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.SyncChaptersWithSource
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
|
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
|
||||||
import eu.kanade.domain.chapter.interactor.UpdateChapter
|
import eu.kanade.domain.chapter.interactor.UpdateChapter
|
||||||
|
@ -79,6 +80,7 @@ class MangaPresenter(
|
||||||
private val getMangaAndChapters: GetMangaWithChapters = Injekt.get(),
|
private val getMangaAndChapters: GetMangaWithChapters = Injekt.get(),
|
||||||
private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(),
|
private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(),
|
||||||
private val setMangaChapterFlags: SetMangaChapterFlags = Injekt.get(),
|
private val setMangaChapterFlags: SetMangaChapterFlags = Injekt.get(),
|
||||||
|
private val setReadStatus: SetReadStatus = Injekt.get(),
|
||||||
private val updateChapter: UpdateChapter = Injekt.get(),
|
private val updateChapter: UpdateChapter = Injekt.get(),
|
||||||
private val updateManga: UpdateManga = Injekt.get(),
|
private val updateManga: UpdateManga = Injekt.get(),
|
||||||
private val syncChaptersWithSource: SyncChaptersWithSource = Injekt.get(),
|
private val syncChaptersWithSource: SyncChaptersWithSource = Injekt.get(),
|
||||||
|
@ -525,13 +527,10 @@ class MangaPresenter(
|
||||||
*/
|
*/
|
||||||
fun markChaptersRead(chapters: List<DomainChapter>, read: Boolean) {
|
fun markChaptersRead(chapters: List<DomainChapter>, read: Boolean) {
|
||||||
presenterScope.launchIO {
|
presenterScope.launchIO {
|
||||||
val modified = chapters.filterNot { it.read == read }
|
setReadStatus.await(
|
||||||
modified
|
read = read,
|
||||||
.map { ChapterUpdate(id = it.id, read = read) }
|
values = chapters.toTypedArray(),
|
||||||
.let { updateChapter.awaitAll(it) }
|
)
|
||||||
if (read && preferences.removeAfterMarkedAsRead()) {
|
|
||||||
deleteChapters(modified)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -249,9 +249,6 @@ class UpdatesController :
|
||||||
*/
|
*/
|
||||||
private fun markAsRead(chapters: List<UpdatesItem>) {
|
private fun markAsRead(chapters: List<UpdatesItem>) {
|
||||||
presenter.markChapterRead(chapters, true)
|
presenter.markChapterRead(chapters, true)
|
||||||
if (presenter.preferences.removeAfterMarkedAsRead()) {
|
|
||||||
deleteChapters(chapters)
|
|
||||||
}
|
|
||||||
destroyActionModeIfNeeded()
|
destroyActionModeIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.recent.updates
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import eu.kanade.data.DatabaseHandler
|
import eu.kanade.data.DatabaseHandler
|
||||||
import eu.kanade.data.manga.mangaChapterMapper
|
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.interactor.UpdateChapter
|
||||||
import eu.kanade.domain.chapter.model.Chapter
|
import eu.kanade.domain.chapter.model.Chapter
|
||||||
import eu.kanade.domain.chapter.model.ChapterUpdate
|
import eu.kanade.domain.chapter.model.ChapterUpdate
|
||||||
|
@ -40,6 +41,7 @@ class UpdatesPresenter : BasePresenter<UpdatesController>() {
|
||||||
|
|
||||||
private val handler: DatabaseHandler by injectLazy()
|
private val handler: DatabaseHandler by injectLazy()
|
||||||
private val updateChapter: UpdateChapter by injectLazy()
|
private val updateChapter: UpdateChapter by injectLazy()
|
||||||
|
private val setReadStatus: SetReadStatus by injectLazy()
|
||||||
|
|
||||||
private val relativeTime: Int = preferences.relativeTime().get()
|
private val relativeTime: Int = preferences.relativeTime().get()
|
||||||
private val dateFormat: DateFormat = preferences.dateFormat()
|
private val dateFormat: DateFormat = preferences.dateFormat()
|
||||||
|
@ -167,14 +169,12 @@ class UpdatesPresenter : BasePresenter<UpdatesController>() {
|
||||||
*/
|
*/
|
||||||
fun markChapterRead(items: List<UpdatesItem>, read: Boolean) {
|
fun markChapterRead(items: List<UpdatesItem>, read: Boolean) {
|
||||||
presenterScope.launchIO {
|
presenterScope.launchIO {
|
||||||
val toUpdate = items.map {
|
setReadStatus.await(
|
||||||
ChapterUpdate(
|
read = read,
|
||||||
read = read,
|
values = items
|
||||||
lastPageRead = if (!read) 0 else null,
|
.map { it.chapter }
|
||||||
id = it.chapter.id,
|
.toTypedArray(),
|
||||||
)
|
)
|
||||||
}
|
|
||||||
updateChapter.awaitAll(toUpdate)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in a new issue