Move chapter preferences from PreferencesHelper to LibraryPrefrences (#8061)

This commit is contained in:
Andreas 2022-09-24 16:14:16 +02:00 committed by GitHub
parent 747cbd24cb
commit b5dca2eb09
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 154 additions and 128 deletions

View file

@ -27,7 +27,7 @@ android {
applicationId = "eu.kanade.tachiyomi" applicationId = "eu.kanade.tachiyomi"
minSdk = AndroidConfig.minSdk minSdk = AndroidConfig.minSdk
targetSdk = AndroidConfig.targetSdk targetSdk = AndroidConfig.targetSdk
versionCode = 84 versionCode = 85
versionName = "0.13.6" versionName = "0.13.6"
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"") buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")

View file

@ -21,6 +21,7 @@ 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.SetMangaDefaultChapterFlags
import eu.kanade.domain.chapter.interactor.SetReadStatus 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
@ -95,6 +96,7 @@ class DomainModule : InjektModule {
addFactory { GetNextChapter(get()) } addFactory { GetNextChapter(get()) }
addFactory { ResetViewerFlags(get()) } addFactory { ResetViewerFlags(get()) }
addFactory { SetMangaChapterFlags(get()) } addFactory { SetMangaChapterFlags(get()) }
addFactory { SetMangaDefaultChapterFlags(get(), get(), get()) }
addFactory { SetMangaViewerFlags(get()) } addFactory { SetMangaViewerFlags(get()) }
addFactory { InsertManga(get()) } addFactory { InsertManga(get()) }
addFactory { UpdateManga(get()) } addFactory { UpdateManga(get()) }

View file

@ -0,0 +1,36 @@
package eu.kanade.domain.chapter.interactor
import eu.kanade.domain.library.service.LibraryPreferences
import eu.kanade.domain.manga.interactor.GetFavorites
import eu.kanade.domain.manga.interactor.SetMangaChapterFlags
import eu.kanade.domain.manga.model.Manga
import eu.kanade.tachiyomi.util.lang.withNonCancellableContext
class SetMangaDefaultChapterFlags(
private val libraryPreferences: LibraryPreferences,
private val setMangaChapterFlags: SetMangaChapterFlags,
private val getFavorites: GetFavorites,
) {
suspend fun await(manga: Manga) {
withNonCancellableContext {
with(libraryPreferences) {
setMangaChapterFlags.awaitSetAllFlags(
mangaId = manga.id,
unreadFilter = filterChapterByRead().get(),
downloadedFilter = filterChapterByDownloaded().get(),
bookmarkedFilter = filterChapterByBookmarked().get(),
sortingMode = sortChapterBySourceOrNumber().get(),
sortingDirection = sortChapterByAscendingOrDescending().get(),
displayMode = displayChapterByNameOrNumber().get(),
)
}
}
}
suspend fun awaitAll() {
withNonCancellableContext {
getFavorites.await().forEach { await(it) }
}
}
}

View file

@ -2,6 +2,7 @@ package eu.kanade.domain.library.service
import eu.kanade.domain.library.model.LibraryDisplayMode import eu.kanade.domain.library.model.LibraryDisplayMode
import eu.kanade.domain.library.model.LibrarySort import eu.kanade.domain.library.model.LibrarySort
import eu.kanade.domain.manga.model.Manga
import eu.kanade.tachiyomi.core.preference.PreferenceStore import eu.kanade.tachiyomi.core.preference.PreferenceStore
import eu.kanade.tachiyomi.data.preference.DEVICE_ONLY_ON_WIFI import eu.kanade.tachiyomi.data.preference.DEVICE_ONLY_ON_WIFI
import eu.kanade.tachiyomi.data.preference.MANGA_HAS_UNREAD import eu.kanade.tachiyomi.data.preference.MANGA_HAS_UNREAD
@ -77,4 +78,30 @@ class LibraryPreferences(
fun libraryUpdateCategoriesExclude() = preferenceStore.getStringSet("library_update_categories_exclude", emptySet()) fun libraryUpdateCategoriesExclude() = preferenceStore.getStringSet("library_update_categories_exclude", emptySet())
// endregion // endregion
// region Chapter
fun filterChapterByRead() = preferenceStore.getLong("default_chapter_filter_by_read", Manga.SHOW_ALL)
fun filterChapterByDownloaded() = preferenceStore.getLong("default_chapter_filter_by_downloaded", Manga.SHOW_ALL)
fun filterChapterByBookmarked() = preferenceStore.getLong("default_chapter_filter_by_bookmarked", Manga.SHOW_ALL)
// and upload date
fun sortChapterBySourceOrNumber() = preferenceStore.getLong("default_chapter_sort_by_source_or_number", Manga.CHAPTER_SORTING_SOURCE)
fun displayChapterByNameOrNumber() = preferenceStore.getLong("default_chapter_display_by_name_or_number", Manga.CHAPTER_DISPLAY_NAME)
fun sortChapterByAscendingOrDescending() = preferenceStore.getLong("default_chapter_sort_by_ascending_or_descending", Manga.CHAPTER_SORT_DESC)
fun setChapterSettingsDefault(manga: Manga) {
filterChapterByRead().set(manga.unreadFilterRaw)
filterChapterByDownloaded().set(manga.downloadedFilterRaw)
filterChapterByBookmarked().set(manga.bookmarkedFilterRaw)
sortChapterBySourceOrNumber().set(manga.sorting)
displayChapterByNameOrNumber().set(manga.displayMode)
sortChapterByAscendingOrDescending().set(if (manga.sortDescending()) Manga.CHAPTER_SORT_DESC else Manga.CHAPTER_SORT_ASC)
}
// endregion
} }

View file

@ -306,6 +306,26 @@ object Migrations {
BackupCreatorJob.setupTask(context) BackupCreatorJob.setupTask(context)
} }
} }
if (oldVersion < 85) {
val preferences = listOf(
libraryPreferences.filterChapterByRead(),
libraryPreferences.filterChapterByDownloaded(),
libraryPreferences.filterChapterByBookmarked(),
libraryPreferences.sortChapterBySourceOrNumber(),
libraryPreferences.displayChapterByNameOrNumber(),
libraryPreferences.sortChapterByAscendingOrDescending(),
)
prefs.edit {
preferences.forEach { preference ->
val key = preference.key()
val value = prefs.getInt(key, Int.MIN_VALUE)
if (value == Int.MIN_VALUE) return@forEach
remove(key)
putLong(key, value.toLong())
}
}
}
return true return true
} }

View file

@ -4,13 +4,11 @@ import android.content.Context
import android.os.Build import android.os.Build
import eu.kanade.tachiyomi.core.preference.PreferenceStore import eu.kanade.tachiyomi.core.preference.PreferenceStore
import eu.kanade.tachiyomi.core.preference.getEnum import eu.kanade.tachiyomi.core.preference.getEnum
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.util.system.DeviceUtil import eu.kanade.tachiyomi.util.system.DeviceUtil
import eu.kanade.tachiyomi.util.system.isDynamicColorAvailable import eu.kanade.tachiyomi.util.system.isDynamicColorAvailable
import java.text.DateFormat import java.text.DateFormat
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
import eu.kanade.domain.manga.model.Manga as DomainManga
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values
@ -53,19 +51,6 @@ class PreferencesHelper(
fun migrateFlags() = preferenceStore.getInt("migrate_flags", Int.MAX_VALUE) fun migrateFlags() = preferenceStore.getInt("migrate_flags", Int.MAX_VALUE)
fun filterChapterByRead() = preferenceStore.getInt("default_chapter_filter_by_read", DomainManga.SHOW_ALL.toInt())
fun filterChapterByDownloaded() = preferenceStore.getInt("default_chapter_filter_by_downloaded", DomainManga.SHOW_ALL.toInt())
fun filterChapterByBookmarked() = preferenceStore.getInt("default_chapter_filter_by_bookmarked", DomainManga.SHOW_ALL.toInt())
// and upload date
fun sortChapterBySourceOrNumber() = preferenceStore.getInt("default_chapter_sort_by_source_or_number", DomainManga.CHAPTER_SORTING_SOURCE.toInt())
fun displayChapterByNameOrNumber() = preferenceStore.getInt("default_chapter_display_by_name_or_number", DomainManga.CHAPTER_DISPLAY_NAME.toInt())
fun sortChapterByAscendingOrDescending() = preferenceStore.getInt("default_chapter_sort_by_ascending_or_descending", DomainManga.CHAPTER_SORT_DESC.toInt())
fun incognitoMode() = preferenceStore.getBoolean("incognito_mode", false) fun incognitoMode() = preferenceStore.getBoolean("incognito_mode", false)
fun tabletUiMode() = preferenceStore.getEnum("tablet_ui_mode", Values.TabletUiMode.AUTOMATIC) fun tabletUiMode() = preferenceStore.getEnum("tablet_ui_mode", Values.TabletUiMode.AUTOMATIC)
@ -76,13 +61,4 @@ class PreferencesHelper(
) )
fun autoClearChapterCache() = preferenceStore.getBoolean("auto_clear_chapter_cache", false) fun autoClearChapterCache() = preferenceStore.getBoolean("auto_clear_chapter_cache", false)
fun setChapterSettingsDefault(manga: Manga) {
filterChapterByRead().set(manga.readFilter)
filterChapterByDownloaded().set(manga.downloadedFilter)
filterChapterByBookmarked().set(manga.bookmarkedFilter)
sortChapterBySourceOrNumber().set(manga.sorting)
displayChapterByNameOrNumber().set(manga.displayMode)
sortChapterByAscendingOrDescending().set(if (manga.sortDescending()) DomainManga.CHAPTER_SORT_DESC.toInt() else DomainManga.CHAPTER_SORT_ASC.toInt())
}
} }

View file

@ -22,6 +22,7 @@ import eu.kanade.core.prefs.mapAsCheckboxState
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.chapter.interactor.GetChapterByMangaId import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
import eu.kanade.domain.chapter.interactor.SetMangaDefaultChapterFlags
import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay
import eu.kanade.domain.library.service.LibraryPreferences import eu.kanade.domain.library.service.LibraryPreferences
import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga import eu.kanade.domain.manga.interactor.GetDuplicateLibraryManga
@ -63,7 +64,6 @@ import eu.kanade.tachiyomi.ui.browse.source.filter.TextItem
import eu.kanade.tachiyomi.ui.browse.source.filter.TextSectionItem import eu.kanade.tachiyomi.ui.browse.source.filter.TextSectionItem
import eu.kanade.tachiyomi.ui.browse.source.filter.TriStateItem import eu.kanade.tachiyomi.ui.browse.source.filter.TriStateItem
import eu.kanade.tachiyomi.ui.browse.source.filter.TriStateSectionItem import eu.kanade.tachiyomi.ui.browse.source.filter.TriStateSectionItem
import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withIOContext import eu.kanade.tachiyomi.util.lang.withIOContext
import eu.kanade.tachiyomi.util.removeCovers import eu.kanade.tachiyomi.util.removeCovers
@ -97,6 +97,7 @@ open class BrowseSourcePresenter(
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 setMangaCategories: SetMangaCategories = Injekt.get(), private val setMangaCategories: SetMangaCategories = Injekt.get(),
private val setMangaDefaultChapterFlags: SetMangaDefaultChapterFlags = Injekt.get(),
private val insertManga: InsertManga = Injekt.get(), private val insertManga: InsertManga = Injekt.get(),
private val updateManga: UpdateManga = Injekt.get(), private val updateManga: UpdateManga = Injekt.get(),
private val insertTrack: InsertTrack = Injekt.get(), private val insertTrack: InsertTrack = Injekt.get(),
@ -246,7 +247,7 @@ open class BrowseSourcePresenter(
if (!new.favorite) { if (!new.favorite) {
new = new.removeCovers(coverCache) new = new.removeCovers(coverCache)
} else { } else {
ChapterSettingsHelper.applySettingDefaults(manga.id) setMangaDefaultChapterFlags.await(manga)
autoAddTrack(manga) autoAddTrack(manga)
} }

View file

@ -48,7 +48,7 @@ import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.lang.combineLatest import eu.kanade.tachiyomi.util.lang.combineLatest
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchNonCancellableIO import eu.kanade.tachiyomi.util.lang.launchNonCancellable
import eu.kanade.tachiyomi.util.removeCovers import eu.kanade.tachiyomi.util.removeCovers
import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.State
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -524,7 +524,7 @@ class LibraryPresenter(
* @param mangas the list of manga. * @param mangas the list of manga.
*/ */
fun downloadUnreadChapters(mangas: List<Manga>) { fun downloadUnreadChapters(mangas: List<Manga>) {
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
mangas.forEach { manga -> mangas.forEach { manga ->
val chapters = getChapterByMangaId.await(manga.id) val chapters = getChapterByMangaId.await(manga.id)
.filter { !it.read } .filter { !it.read }
@ -541,7 +541,7 @@ class LibraryPresenter(
* @param mangas the list of manga. * @param mangas the list of manga.
*/ */
fun markReadStatus(mangas: List<Manga>, read: Boolean) { fun markReadStatus(mangas: List<Manga>, read: Boolean) {
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
mangas.forEach { manga -> mangas.forEach { manga ->
setReadStatus.await( setReadStatus.await(
manga = manga, manga = manga,
@ -559,7 +559,7 @@ class LibraryPresenter(
* @param deleteChapters whether to delete downloaded chapters. * @param deleteChapters whether to delete downloaded chapters.
*/ */
fun removeMangas(mangaList: List<DbManga>, deleteFromLibrary: Boolean, deleteChapters: Boolean) { fun removeMangas(mangaList: List<DbManga>, deleteFromLibrary: Boolean, deleteChapters: Boolean) {
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
val mangaToDelete = mangaList.distinctBy { it.id } val mangaToDelete = mangaList.distinctBy { it.id }
if (deleteFromLibrary) { if (deleteFromLibrary) {
@ -592,7 +592,7 @@ class LibraryPresenter(
* @param removeCategories the categories to remove in all mangas. * @param removeCategories the categories to remove in all mangas.
*/ */
fun setMangaCategories(mangaList: List<Manga>, addCategories: List<Long>, removeCategories: List<Long>) { fun setMangaCategories(mangaList: List<Manga>, addCategories: List<Long>, removeCategories: List<Long>) {
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
mangaList.map { manga -> mangaList.map { manga ->
val categoryIds = getCategories.await(manga.id) val categoryIds = getCategories.await(manga.id)
.map { it.id } .map { it.id }

View file

@ -9,6 +9,7 @@ import eu.kanade.core.prefs.mapAsCheckboxState
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.SetMangaDefaultChapterFlags
import eu.kanade.domain.chapter.interactor.SetReadStatus 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
@ -41,10 +42,9 @@ import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.manga.track.TrackItem import eu.kanade.tachiyomi.ui.manga.track.TrackItem
import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper
import eu.kanade.tachiyomi.util.chapter.getChapterSort import eu.kanade.tachiyomi.util.chapter.getChapterSort
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchNonCancellableIO import eu.kanade.tachiyomi.util.lang.launchNonCancellable
import eu.kanade.tachiyomi.util.lang.toRelativeString import eu.kanade.tachiyomi.util.lang.toRelativeString
import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.preference.asHotFlow import eu.kanade.tachiyomi.util.preference.asHotFlow
@ -91,6 +91,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 setMangaDefaultChapterFlags: SetMangaDefaultChapterFlags = Injekt.get(),
private val setReadStatus: SetReadStatus = 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(),
@ -162,7 +163,7 @@ class MangaPresenter(
val manga = getMangaAndChapters.awaitManga(mangaId) val manga = getMangaAndChapters.awaitManga(mangaId)
if (!manga.favorite) { if (!manga.favorite) {
ChapterSettingsHelper.applySettingDefaults(mangaId) setMangaDefaultChapterFlags.await(manga)
} }
// Show what we have earlier. // Show what we have earlier.
@ -646,7 +647,7 @@ class MangaPresenter(
* @param chapters the list of chapters to delete. * @param chapters the list of chapters to delete.
*/ */
fun deleteChapters(chapters: List<DomainChapter>) { fun deleteChapters(chapters: List<DomainChapter>) {
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
val chapters2 = chapters.map { it.toDbChapter() } val chapters2 = chapters.map { it.toDbChapter() }
try { try {
updateSuccessState { successState -> updateSuccessState { successState ->
@ -678,10 +679,10 @@ class MangaPresenter(
} }
private fun downloadNewChapters(chapters: List<DomainChapter>) { private fun downloadNewChapters(chapters: List<DomainChapter>) {
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
val manga = successState?.manga ?: return@launchNonCancellableIO val manga = successState?.manga ?: return@launchNonCancellable
val categories = getCategories.await(manga.id).map { it.id } val categories = getCategories.await(manga.id).map { it.id }
if (chapters.isEmpty() || !manga.shouldDownloadNewChapters(categories, downloadPreferences)) return@launchNonCancellableIO if (chapters.isEmpty() || !manga.shouldDownloadNewChapters(categories, downloadPreferences)) return@launchNonCancellable
downloadChapters(chapters) downloadChapters(chapters)
} }
} }
@ -698,7 +699,7 @@ class MangaPresenter(
State.INCLUDE -> DomainManga.CHAPTER_SHOW_UNREAD State.INCLUDE -> DomainManga.CHAPTER_SHOW_UNREAD
State.EXCLUDE -> DomainManga.CHAPTER_SHOW_READ State.EXCLUDE -> DomainManga.CHAPTER_SHOW_READ
} }
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
setMangaChapterFlags.awaitSetUnreadFilter(manga, flag) setMangaChapterFlags.awaitSetUnreadFilter(manga, flag)
} }
} }
@ -716,7 +717,7 @@ class MangaPresenter(
State.EXCLUDE -> DomainManga.CHAPTER_SHOW_NOT_DOWNLOADED State.EXCLUDE -> DomainManga.CHAPTER_SHOW_NOT_DOWNLOADED
} }
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
setMangaChapterFlags.awaitSetDownloadedFilter(manga, flag) setMangaChapterFlags.awaitSetDownloadedFilter(manga, flag)
} }
} }
@ -734,7 +735,7 @@ class MangaPresenter(
State.EXCLUDE -> DomainManga.CHAPTER_SHOW_NOT_BOOKMARKED State.EXCLUDE -> DomainManga.CHAPTER_SHOW_NOT_BOOKMARKED
} }
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
setMangaChapterFlags.awaitSetBookmarkFilter(manga, flag) setMangaChapterFlags.awaitSetBookmarkFilter(manga, flag)
} }
} }
@ -746,7 +747,7 @@ class MangaPresenter(
fun setDisplayMode(mode: Long) { fun setDisplayMode(mode: Long) {
val manga = successState?.manga ?: return val manga = successState?.manga ?: return
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
setMangaChapterFlags.awaitSetDisplayMode(manga, mode) setMangaChapterFlags.awaitSetDisplayMode(manga, mode)
} }
} }
@ -758,7 +759,7 @@ class MangaPresenter(
fun setSorting(sort: Long) { fun setSorting(sort: Long) {
val manga = successState?.manga ?: return val manga = successState?.manga ?: return
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
setMangaChapterFlags.awaitSetSortingModeOrFlipOrder(manga, sort) setMangaChapterFlags.awaitSetSortingModeOrFlipOrder(manga, sort)
} }
} }
@ -873,7 +874,7 @@ class MangaPresenter(
fun refreshTrackers() { fun refreshTrackers() {
refreshTrackersJob?.cancel() refreshTrackersJob?.cancel()
refreshTrackersJob = presenterScope.launchNonCancellableIO { refreshTrackersJob = presenterScope.launchNonCancellable {
supervisorScope { supervisorScope {
try { try {
trackList trackList
@ -921,7 +922,7 @@ class MangaPresenter(
val successState = successState ?: return val successState = successState ?: return
if (item != null) { if (item != null) {
item.manga_id = successState.manga.id item.manga_id = successState.manga.id
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
try { try {
val allChapters = successState.chapters.map { it.chapter } val allChapters = successState.chapters.map { it.chapter }
val hasReadChapters = allChapters.any { it.read } val hasReadChapters = allChapters.any { it.read }
@ -962,13 +963,13 @@ class MangaPresenter(
fun unregisterTracking(service: TrackService) { fun unregisterTracking(service: TrackService) {
val manga = successState?.manga ?: return val manga = successState?.manga ?: return
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
deleteTrack.await(manga.id, service.id) deleteTrack.await(manga.id, service.id)
} }
} }
private fun updateRemote(track: Track, service: TrackService) { private fun updateRemote(track: Track, service: TrackService) {
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
try { try {
service.update(track) service.update(track)

View file

@ -4,16 +4,27 @@ import android.app.Dialog
import android.os.Bundle import android.os.Bundle
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import eu.kanade.domain.chapter.interactor.SetMangaDefaultChapterFlags
import eu.kanade.domain.library.service.LibraryPreferences
import eu.kanade.domain.manga.model.Manga import eu.kanade.domain.manga.model.Manga
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.ui.base.controller.DialogController
import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper
import eu.kanade.tachiyomi.util.system.getSerializableCompat import eu.kanade.tachiyomi.util.system.getSerializableCompat
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.widget.DialogCheckboxView import eu.kanade.tachiyomi.widget.DialogCheckboxView
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import uy.kohesive.injekt.injectLazy
class SetChapterSettingsDialog(bundle: Bundle? = null) : DialogController(bundle) { class SetChapterSettingsDialog(bundle: Bundle? = null) : DialogController(bundle) {
private val scope = CoroutineScope(Dispatchers.IO)
private val libraryPreferences: LibraryPreferences by injectLazy()
private val setMangaDefaultChapterFlags: SetMangaDefaultChapterFlags by injectLazy()
constructor(manga: Manga) : this( constructor(manga: Manga) : this(
bundleOf(MANGA_KEY to manga), bundleOf(MANGA_KEY to manga),
) )
@ -28,9 +39,11 @@ class SetChapterSettingsDialog(bundle: Bundle? = null) : DialogController(bundle
.setTitle(R.string.chapter_settings) .setTitle(R.string.chapter_settings)
.setView(view) .setView(view)
.setPositiveButton(android.R.string.ok) { _, _ -> .setPositiveButton(android.R.string.ok) { _, _ ->
ChapterSettingsHelper.setGlobalSettings(args.getSerializableCompat(MANGA_KEY)!!) libraryPreferences.setChapterSettingsDefault(args.getSerializableCompat(MANGA_KEY)!!)
if (view.isChecked()) { if (view.isChecked()) {
ChapterSettingsHelper.updateAllMangasWithGlobalDefaults() scope.launch {
setMangaDefaultChapterFlags.awaitAll()
}
} }
activity?.toast(activity!!.getString(R.string.chapter_settings_updated)) activity?.toast(activity!!.getString(R.string.chapter_settings_updated))
@ -38,6 +51,11 @@ class SetChapterSettingsDialog(bundle: Bundle? = null) : DialogController(bundle
.setNegativeButton(android.R.string.cancel, null) .setNegativeButton(android.R.string.cancel, null)
.create() .create()
} }
override fun onDestroy() {
super.onDestroy()
scope.cancel()
}
} }
private const val MANGA_KEY = "manga" private const val MANGA_KEY = "manga"

View file

@ -50,7 +50,7 @@ import eu.kanade.tachiyomi.util.chapter.getChapterSort
import eu.kanade.tachiyomi.util.editCover import eu.kanade.tachiyomi.util.editCover
import eu.kanade.tachiyomi.util.lang.byteSize import eu.kanade.tachiyomi.util.lang.byteSize
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchNonCancellableIO import eu.kanade.tachiyomi.util.lang.launchNonCancellable
import eu.kanade.tachiyomi.util.lang.takeBytes import eu.kanade.tachiyomi.util.lang.takeBytes
import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.storage.DiskUtil import eu.kanade.tachiyomi.util.storage.DiskUtil
@ -239,7 +239,7 @@ class ReaderPresenter(
*/ */
fun onSaveInstanceStateNonConfigurationChange() { fun onSaveInstanceStateNonConfigurationChange() {
val currentChapter = getCurrentChapter() ?: return val currentChapter = getCurrentChapter() ?: return
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
saveChapterProgress(currentChapter) saveChapterProgress(currentChapter)
} }
} }
@ -530,7 +530,7 @@ class ReaderPresenter(
* Called when reader chapter is changed in reader or when activity is paused. * Called when reader chapter is changed in reader or when activity is paused.
*/ */
private fun saveReadingProgress(readerChapter: ReaderChapter) { private fun saveReadingProgress(readerChapter: ReaderChapter) {
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
saveChapterProgress(readerChapter) saveChapterProgress(readerChapter)
saveChapterHistory(readerChapter) saveChapterHistory(readerChapter)
} }
@ -611,7 +611,7 @@ class ReaderPresenter(
fun bookmarkCurrentChapter(bookmarked: Boolean) { fun bookmarkCurrentChapter(bookmarked: Boolean) {
val chapter = getCurrentChapter()?.chapter ?: return val chapter = getCurrentChapter()?.chapter ?: return
chapter.bookmark = bookmarked // Otherwise the bookmark icon doesn't update chapter.bookmark = bookmarked // Otherwise the bookmark icon doesn't update
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
updateChapter.await( updateChapter.await(
ChapterUpdate( ChapterUpdate(
id = chapter.id!!.toLong(), id = chapter.id!!.toLong(),
@ -724,7 +724,7 @@ class ReaderPresenter(
// Copy file in background. // Copy file in background.
try { try {
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
val uri = imageSaver.save( val uri = imageSaver.save(
image = Image.Page( image = Image.Page(
inputStream = page.stream!!, inputStream = page.stream!!,
@ -760,7 +760,7 @@ class ReaderPresenter(
val filename = generateFilename(manga, page) val filename = generateFilename(manga, page)
try { try {
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
destDir.deleteRecursively() destDir.deleteRecursively()
val uri = imageSaver.save( val uri = imageSaver.save(
image = Image.Page( image = Image.Page(
@ -786,7 +786,7 @@ class ReaderPresenter(
val manga = manga?.toDomainManga() ?: return val manga = manga?.toDomainManga() ?: return
val stream = page.stream ?: return val stream = page.stream ?: return
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
try { try {
manga.editCover(context, stream()) manga.editCover(context, stream())
withUIContext { withUIContext {
@ -832,7 +832,7 @@ class ReaderPresenter(
val trackManager = Injekt.get<TrackManager>() val trackManager = Injekt.get<TrackManager>()
val context = Injekt.get<Application>() val context = Injekt.get<Application>()
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
getTracks.await(manga.id!!) getTracks.await(manga.id!!)
.mapNotNull { track -> .mapNotNull { track ->
val service = trackManager.getService(track.syncId) val service = trackManager.getService(track.syncId)
@ -870,7 +870,7 @@ class ReaderPresenter(
if (!chapter.chapter.read) return if (!chapter.chapter.read) return
val manga = manga ?: return val manga = manga ?: return
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
downloadManager.enqueueDeleteChapters(listOf(chapter.chapter), manga.toDomainManga()!!) downloadManager.enqueueDeleteChapters(listOf(chapter.chapter), manga.toDomainManga()!!)
} }
} }
@ -880,7 +880,7 @@ class ReaderPresenter(
* are ignored. * are ignored.
*/ */
private fun deletePendingChapters() { private fun deletePendingChapters() {
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
downloadManager.deletePendingChapters() downloadManager.deletePendingChapters()
} }
} }

View file

@ -23,7 +23,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchNonCancellableIO import eu.kanade.tachiyomi.util.lang.launchNonCancellable
import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.system.logcat import eu.kanade.tachiyomi.util.system.logcat
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -236,7 +236,7 @@ class UpdatesPresenter(
* @param updatesItem the list of chapters to download. * @param updatesItem the list of chapters to download.
*/ */
fun downloadChapters(updatesItem: List<UpdatesItem>) { fun downloadChapters(updatesItem: List<UpdatesItem>) {
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
val groupedUpdates = updatesItem.groupBy { it.update.mangaId }.values val groupedUpdates = updatesItem.groupBy { it.update.mangaId }.values
for (updates in groupedUpdates) { for (updates in groupedUpdates) {
val mangaId = updates.first().update.mangaId val mangaId = updates.first().update.mangaId
@ -255,7 +255,7 @@ class UpdatesPresenter(
* @param updatesItem list of chapters * @param updatesItem list of chapters
*/ */
fun deleteChapters(updatesItem: List<UpdatesItem>) { fun deleteChapters(updatesItem: List<UpdatesItem>) {
presenterScope.launchNonCancellableIO { presenterScope.launchNonCancellable {
val groupedUpdates = updatesItem.groupBy { it.update.mangaId }.values val groupedUpdates = updatesItem.groupBy { it.update.mangaId }.values
val deletedIds = groupedUpdates.flatMap { updates -> val deletedIds = groupedUpdates.flatMap { updates ->
val mangaId = updates.first().update.mangaId val mangaId = updates.first().update.mangaId
@ -268,7 +268,7 @@ class UpdatesPresenter(
val deletedUpdates = items.filter { val deletedUpdates = items.filter {
deletedIds.contains(it.update.chapterId) deletedIds.contains(it.update.chapterId)
} }
if (deletedUpdates.isEmpty()) return@launchNonCancellableIO if (deletedUpdates.isEmpty()) return@launchNonCancellable
// TODO: Don't do this fake status update // TODO: Don't do this fake status update
state.items = items.toMutableList().apply { state.items = items.toMutableList().apply {

View file

@ -33,7 +33,7 @@ import eu.kanade.tachiyomi.ui.base.controller.openInBrowser
import eu.kanade.tachiyomi.ui.base.controller.pushController import eu.kanade.tachiyomi.ui.base.controller.pushController
import eu.kanade.tachiyomi.ui.setting.database.ClearDatabaseController import eu.kanade.tachiyomi.ui.setting.database.ClearDatabaseController
import eu.kanade.tachiyomi.util.CrashLogUtil import eu.kanade.tachiyomi.util.CrashLogUtil
import eu.kanade.tachiyomi.util.lang.launchNonCancellableIO import eu.kanade.tachiyomi.util.lang.launchNonCancellable
import eu.kanade.tachiyomi.util.lang.withUIContext import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.preference.bindTo import eu.kanade.tachiyomi.util.preference.bindTo
import eu.kanade.tachiyomi.util.preference.defaultValue import eu.kanade.tachiyomi.util.preference.defaultValue
@ -90,7 +90,7 @@ class SettingsAdvancedController(
summaryRes = R.string.pref_dump_crash_logs_summary summaryRes = R.string.pref_dump_crash_logs_summary
onClick { onClick {
viewScope.launchNonCancellableIO { viewScope.launchNonCancellable {
CrashLogUtil(context).dumpLogs() CrashLogUtil(context).dumpLogs()
} }
} }
@ -343,7 +343,7 @@ class SettingsAdvancedController(
private fun clearChapterCache() { private fun clearChapterCache() {
val activity = activity ?: return val activity = activity ?: return
viewScope.launchNonCancellableIO { viewScope.launchNonCancellable {
try { try {
val deletedFiles = chapterCache.clear() val deletedFiles = chapterCache.clear()
withUIContext { withUIContext {
@ -379,7 +379,7 @@ class SettingsAdvancedController(
private fun resetViewerFlags() { private fun resetViewerFlags() {
val activity = activity ?: return val activity = activity ?: return
viewScope.launchNonCancellableIO { viewScope.launchNonCancellable {
val success = mangaRepository.resetViewerFlags() val success = mangaRepository.resetViewerFlags()
withUIContext { withUIContext {
val message = if (success) { val message = if (success) {

View file

@ -1,58 +0,0 @@
package eu.kanade.tachiyomi.util.chapter
import eu.kanade.domain.manga.interactor.GetFavorites
import eu.kanade.domain.manga.interactor.SetMangaChapterFlags
import eu.kanade.domain.manga.model.Manga
import eu.kanade.domain.manga.model.toDbManga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.util.lang.launchIO
import uy.kohesive.injekt.injectLazy
object ChapterSettingsHelper {
private val preferences: PreferencesHelper by injectLazy()
private val getFavorites: GetFavorites by injectLazy()
private val setMangaChapterFlags: SetMangaChapterFlags by injectLazy()
/**
* Updates the global Chapter Settings in Preferences.
*/
fun setGlobalSettings(manga: Manga) {
preferences.setChapterSettingsDefault(manga.toDbManga())
}
/**
* Updates a single manga's Chapter Settings to match what's set in Preferences.
*/
suspend fun applySettingDefaults(mangaId: Long) {
setMangaChapterFlags.awaitSetAllFlags(
mangaId = mangaId,
unreadFilter = preferences.filterChapterByRead().get().toLong(),
downloadedFilter = preferences.filterChapterByDownloaded().get().toLong(),
bookmarkedFilter = preferences.filterChapterByBookmarked().get().toLong(),
sortingMode = preferences.sortChapterBySourceOrNumber().get().toLong(),
sortingDirection = preferences.sortChapterByAscendingOrDescending().get().toLong(),
displayMode = preferences.displayChapterByNameOrNumber().get().toLong(),
)
}
/**
* Updates all mangas in library with global Chapter Settings.
*/
fun updateAllMangasWithGlobalDefaults() {
launchIO {
getFavorites.await()
.map { manga ->
setMangaChapterFlags.awaitSetAllFlags(
mangaId = manga.id,
unreadFilter = preferences.filterChapterByRead().get().toLong(),
downloadedFilter = preferences.filterChapterByDownloaded().get().toLong(),
bookmarkedFilter = preferences.filterChapterByBookmarked().get().toLong(),
sortingMode = preferences.sortChapterBySourceOrNumber().get().toLong(),
sortingDirection = preferences.sortChapterByAscendingOrDescending().get().toLong(),
displayMode = preferences.displayChapterByNameOrNumber().get().toLong(),
)
}
}
}
}

View file

@ -49,9 +49,12 @@ fun CoroutineScope.launchUI(block: suspend CoroutineScope.() -> Unit): Job =
fun CoroutineScope.launchIO(block: suspend CoroutineScope.() -> Unit): Job = fun CoroutineScope.launchIO(block: suspend CoroutineScope.() -> Unit): Job =
launch(Dispatchers.IO, block = block) launch(Dispatchers.IO, block = block)
fun CoroutineScope.launchNonCancellableIO(block: suspend CoroutineScope.() -> Unit): Job = fun CoroutineScope.launchNonCancellable(block: suspend CoroutineScope.() -> Unit): Job =
launchIO { withContext(NonCancellable, block) } launchIO { withContext(NonCancellable, block) }
suspend fun <T> withUIContext(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.Main, block) suspend fun <T> withUIContext(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.Main, block)
suspend fun <T> withIOContext(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.IO, block) suspend fun <T> withIOContext(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.IO, block)
suspend fun <T> withNonCancellableContext(block: suspend CoroutineScope.() -> T) =
withContext(NonCancellable, block)