From b5dca2eb09c008563e6e977fb3379fb7548d1144 Mon Sep 17 00:00:00 2001 From: Andreas Date: Sat, 24 Sep 2022 16:14:16 +0200 Subject: [PATCH] Move chapter preferences from PreferencesHelper to LibraryPrefrences (#8061) --- app/build.gradle.kts | 2 +- .../java/eu/kanade/domain/DomainModule.kt | 2 + .../interactor/SetDefaultChapterSettings.kt | 36 ++++++++++++ .../library/service/LibraryPreferences.kt | 27 +++++++++ .../java/eu/kanade/tachiyomi/Migrations.kt | 20 +++++++ .../data/preference/PreferencesHelper.kt | 24 -------- .../source/browse/BrowseSourcePresenter.kt | 5 +- .../tachiyomi/ui/library/LibraryPresenter.kt | 10 ++-- .../tachiyomi/ui/manga/MangaPresenter.kt | 33 ++++++----- .../manga/chapter/SetChapterSettingsDialog.kt | 24 +++++++- .../tachiyomi/ui/reader/ReaderPresenter.kt | 20 +++---- .../ui/recent/updates/UpdatesPresenter.kt | 8 +-- .../ui/setting/SettingsAdvancedController.kt | 8 +-- .../util/chapter/ChapterSettingsHelper.kt | 58 ------------------- .../util/lang/CoroutinesExtensions.kt | 5 +- 15 files changed, 154 insertions(+), 128 deletions(-) create mode 100644 app/src/main/java/eu/kanade/domain/chapter/interactor/SetDefaultChapterSettings.kt delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSettingsHelper.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index aa61d6b6f6..f1353765bd 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -27,7 +27,7 @@ android { applicationId = "eu.kanade.tachiyomi" minSdk = AndroidConfig.minSdk targetSdk = AndroidConfig.targetSdk - versionCode = 84 + versionCode = 85 versionName = "0.13.6" buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"") diff --git a/app/src/main/java/eu/kanade/domain/DomainModule.kt b/app/src/main/java/eu/kanade/domain/DomainModule.kt index eccee1c59b..c5ed27867c 100644 --- a/app/src/main/java/eu/kanade/domain/DomainModule.kt +++ b/app/src/main/java/eu/kanade/domain/DomainModule.kt @@ -21,6 +21,7 @@ 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.SetMangaDefaultChapterFlags import eu.kanade.domain.chapter.interactor.SetReadStatus import eu.kanade.domain.chapter.interactor.ShouldUpdateDbChapter import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource @@ -95,6 +96,7 @@ class DomainModule : InjektModule { addFactory { GetNextChapter(get()) } addFactory { ResetViewerFlags(get()) } addFactory { SetMangaChapterFlags(get()) } + addFactory { SetMangaDefaultChapterFlags(get(), get(), get()) } addFactory { SetMangaViewerFlags(get()) } addFactory { InsertManga(get()) } addFactory { UpdateManga(get()) } diff --git a/app/src/main/java/eu/kanade/domain/chapter/interactor/SetDefaultChapterSettings.kt b/app/src/main/java/eu/kanade/domain/chapter/interactor/SetDefaultChapterSettings.kt new file mode 100644 index 0000000000..45432c5d55 --- /dev/null +++ b/app/src/main/java/eu/kanade/domain/chapter/interactor/SetDefaultChapterSettings.kt @@ -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) } + } + } +} diff --git a/app/src/main/java/eu/kanade/domain/library/service/LibraryPreferences.kt b/app/src/main/java/eu/kanade/domain/library/service/LibraryPreferences.kt index 99498ee262..7132d2357a 100644 --- a/app/src/main/java/eu/kanade/domain/library/service/LibraryPreferences.kt +++ b/app/src/main/java/eu/kanade/domain/library/service/LibraryPreferences.kt @@ -2,6 +2,7 @@ package eu.kanade.domain.library.service import eu.kanade.domain.library.model.LibraryDisplayMode 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.data.preference.DEVICE_ONLY_ON_WIFI import eu.kanade.tachiyomi.data.preference.MANGA_HAS_UNREAD @@ -77,4 +78,30 @@ class LibraryPreferences( fun libraryUpdateCategoriesExclude() = preferenceStore.getStringSet("library_update_categories_exclude", emptySet()) // 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 } diff --git a/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt b/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt index f7fdf11cb5..365bb14ee4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt @@ -306,6 +306,26 @@ object Migrations { 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 } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 0be9e6c92d..24d942850f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -4,13 +4,11 @@ import android.content.Context import android.os.Build import eu.kanade.tachiyomi.core.preference.PreferenceStore 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.isDynamicColorAvailable import java.text.DateFormat import java.text.SimpleDateFormat 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.PreferenceValues as Values @@ -53,19 +51,6 @@ class PreferencesHelper( 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 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 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()) - } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt index 3cc6321d7c..7f348d347c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt @@ -22,6 +22,7 @@ import eu.kanade.core.prefs.mapAsCheckboxState import eu.kanade.domain.category.interactor.GetCategories import eu.kanade.domain.category.interactor.SetMangaCategories 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.library.service.LibraryPreferences 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.TriStateItem 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.withIOContext import eu.kanade.tachiyomi.util.removeCovers @@ -97,6 +97,7 @@ open class BrowseSourcePresenter( private val getCategories: GetCategories = Injekt.get(), private val getChapterByMangaId: GetChapterByMangaId = Injekt.get(), private val setMangaCategories: SetMangaCategories = Injekt.get(), + private val setMangaDefaultChapterFlags: SetMangaDefaultChapterFlags = Injekt.get(), private val insertManga: InsertManga = Injekt.get(), private val updateManga: UpdateManga = Injekt.get(), private val insertTrack: InsertTrack = Injekt.get(), @@ -246,7 +247,7 @@ open class BrowseSourcePresenter( if (!new.favorite) { new = new.removeCovers(coverCache) } else { - ChapterSettingsHelper.applySettingDefaults(manga.id) + setMangaDefaultChapterFlags.await(manga) autoAddTrack(manga) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt index f09fd4471a..1300cbdb33 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt @@ -48,7 +48,7 @@ import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.util.lang.combineLatest 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.widget.ExtendedNavigationView.Item.TriStateGroup.State import kotlinx.coroutines.Job @@ -524,7 +524,7 @@ class LibraryPresenter( * @param mangas the list of manga. */ fun downloadUnreadChapters(mangas: List) { - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { mangas.forEach { manga -> val chapters = getChapterByMangaId.await(manga.id) .filter { !it.read } @@ -541,7 +541,7 @@ class LibraryPresenter( * @param mangas the list of manga. */ fun markReadStatus(mangas: List, read: Boolean) { - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { mangas.forEach { manga -> setReadStatus.await( manga = manga, @@ -559,7 +559,7 @@ class LibraryPresenter( * @param deleteChapters whether to delete downloaded chapters. */ fun removeMangas(mangaList: List, deleteFromLibrary: Boolean, deleteChapters: Boolean) { - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { val mangaToDelete = mangaList.distinctBy { it.id } if (deleteFromLibrary) { @@ -592,7 +592,7 @@ class LibraryPresenter( * @param removeCategories the categories to remove in all mangas. */ fun setMangaCategories(mangaList: List, addCategories: List, removeCategories: List) { - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { mangaList.map { manga -> val categoryIds = getCategories.await(manga.id) .map { it.id } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt index ca770eafbc..3eed4df0ed 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt @@ -9,6 +9,7 @@ import eu.kanade.core.prefs.mapAsCheckboxState 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.SetMangaDefaultChapterFlags import eu.kanade.domain.chapter.interactor.SetReadStatus import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource 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.ui.base.presenter.BasePresenter 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.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.withUIContext import eu.kanade.tachiyomi.util.preference.asHotFlow @@ -91,6 +91,7 @@ class MangaPresenter( private val getMangaAndChapters: GetMangaWithChapters = Injekt.get(), private val getDuplicateLibraryManga: GetDuplicateLibraryManga = Injekt.get(), private val setMangaChapterFlags: SetMangaChapterFlags = Injekt.get(), + private val setMangaDefaultChapterFlags: SetMangaDefaultChapterFlags = Injekt.get(), private val setReadStatus: SetReadStatus = Injekt.get(), private val updateChapter: UpdateChapter = Injekt.get(), private val updateManga: UpdateManga = Injekt.get(), @@ -162,7 +163,7 @@ class MangaPresenter( val manga = getMangaAndChapters.awaitManga(mangaId) if (!manga.favorite) { - ChapterSettingsHelper.applySettingDefaults(mangaId) + setMangaDefaultChapterFlags.await(manga) } // Show what we have earlier. @@ -646,7 +647,7 @@ class MangaPresenter( * @param chapters the list of chapters to delete. */ fun deleteChapters(chapters: List) { - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { val chapters2 = chapters.map { it.toDbChapter() } try { updateSuccessState { successState -> @@ -678,10 +679,10 @@ class MangaPresenter( } private fun downloadNewChapters(chapters: List) { - presenterScope.launchNonCancellableIO { - val manga = successState?.manga ?: return@launchNonCancellableIO + presenterScope.launchNonCancellable { + val manga = successState?.manga ?: return@launchNonCancellable 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) } } @@ -698,7 +699,7 @@ class MangaPresenter( State.INCLUDE -> DomainManga.CHAPTER_SHOW_UNREAD State.EXCLUDE -> DomainManga.CHAPTER_SHOW_READ } - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { setMangaChapterFlags.awaitSetUnreadFilter(manga, flag) } } @@ -716,7 +717,7 @@ class MangaPresenter( State.EXCLUDE -> DomainManga.CHAPTER_SHOW_NOT_DOWNLOADED } - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { setMangaChapterFlags.awaitSetDownloadedFilter(manga, flag) } } @@ -734,7 +735,7 @@ class MangaPresenter( State.EXCLUDE -> DomainManga.CHAPTER_SHOW_NOT_BOOKMARKED } - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { setMangaChapterFlags.awaitSetBookmarkFilter(manga, flag) } } @@ -746,7 +747,7 @@ class MangaPresenter( fun setDisplayMode(mode: Long) { val manga = successState?.manga ?: return - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { setMangaChapterFlags.awaitSetDisplayMode(manga, mode) } } @@ -758,7 +759,7 @@ class MangaPresenter( fun setSorting(sort: Long) { val manga = successState?.manga ?: return - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { setMangaChapterFlags.awaitSetSortingModeOrFlipOrder(manga, sort) } } @@ -873,7 +874,7 @@ class MangaPresenter( fun refreshTrackers() { refreshTrackersJob?.cancel() - refreshTrackersJob = presenterScope.launchNonCancellableIO { + refreshTrackersJob = presenterScope.launchNonCancellable { supervisorScope { try { trackList @@ -921,7 +922,7 @@ class MangaPresenter( val successState = successState ?: return if (item != null) { item.manga_id = successState.manga.id - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { try { val allChapters = successState.chapters.map { it.chapter } val hasReadChapters = allChapters.any { it.read } @@ -962,13 +963,13 @@ class MangaPresenter( fun unregisterTracking(service: TrackService) { val manga = successState?.manga ?: return - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { deleteTrack.await(manga.id, service.id) } } private fun updateRemote(track: Track, service: TrackService) { - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { try { service.update(track) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/SetChapterSettingsDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/SetChapterSettingsDialog.kt index 7403d21346..73637770d1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/SetChapterSettingsDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/SetChapterSettingsDialog.kt @@ -4,16 +4,27 @@ import android.app.Dialog import android.os.Bundle import androidx.core.os.bundleOf 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.tachiyomi.R 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.toast 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) { + private val scope = CoroutineScope(Dispatchers.IO) + + private val libraryPreferences: LibraryPreferences by injectLazy() + private val setMangaDefaultChapterFlags: SetMangaDefaultChapterFlags by injectLazy() + constructor(manga: Manga) : this( bundleOf(MANGA_KEY to manga), ) @@ -28,9 +39,11 @@ class SetChapterSettingsDialog(bundle: Bundle? = null) : DialogController(bundle .setTitle(R.string.chapter_settings) .setView(view) .setPositiveButton(android.R.string.ok) { _, _ -> - ChapterSettingsHelper.setGlobalSettings(args.getSerializableCompat(MANGA_KEY)!!) + libraryPreferences.setChapterSettingsDefault(args.getSerializableCompat(MANGA_KEY)!!) if (view.isChecked()) { - ChapterSettingsHelper.updateAllMangasWithGlobalDefaults() + scope.launch { + setMangaDefaultChapterFlags.awaitAll() + } } 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) .create() } + + override fun onDestroy() { + super.onDestroy() + scope.cancel() + } } private const val MANGA_KEY = "manga" diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt index d85a316f4f..5d7fbfa753 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt @@ -50,7 +50,7 @@ import eu.kanade.tachiyomi.util.chapter.getChapterSort import eu.kanade.tachiyomi.util.editCover import eu.kanade.tachiyomi.util.lang.byteSize 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.withUIContext import eu.kanade.tachiyomi.util.storage.DiskUtil @@ -239,7 +239,7 @@ class ReaderPresenter( */ fun onSaveInstanceStateNonConfigurationChange() { val currentChapter = getCurrentChapter() ?: return - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { saveChapterProgress(currentChapter) } } @@ -530,7 +530,7 @@ class ReaderPresenter( * Called when reader chapter is changed in reader or when activity is paused. */ private fun saveReadingProgress(readerChapter: ReaderChapter) { - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { saveChapterProgress(readerChapter) saveChapterHistory(readerChapter) } @@ -611,7 +611,7 @@ class ReaderPresenter( fun bookmarkCurrentChapter(bookmarked: Boolean) { val chapter = getCurrentChapter()?.chapter ?: return chapter.bookmark = bookmarked // Otherwise the bookmark icon doesn't update - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { updateChapter.await( ChapterUpdate( id = chapter.id!!.toLong(), @@ -724,7 +724,7 @@ class ReaderPresenter( // Copy file in background. try { - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { val uri = imageSaver.save( image = Image.Page( inputStream = page.stream!!, @@ -760,7 +760,7 @@ class ReaderPresenter( val filename = generateFilename(manga, page) try { - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { destDir.deleteRecursively() val uri = imageSaver.save( image = Image.Page( @@ -786,7 +786,7 @@ class ReaderPresenter( val manga = manga?.toDomainManga() ?: return val stream = page.stream ?: return - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { try { manga.editCover(context, stream()) withUIContext { @@ -832,7 +832,7 @@ class ReaderPresenter( val trackManager = Injekt.get() val context = Injekt.get() - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { getTracks.await(manga.id!!) .mapNotNull { track -> val service = trackManager.getService(track.syncId) @@ -870,7 +870,7 @@ class ReaderPresenter( if (!chapter.chapter.read) return val manga = manga ?: return - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { downloadManager.enqueueDeleteChapters(listOf(chapter.chapter), manga.toDomainManga()!!) } } @@ -880,7 +880,7 @@ class ReaderPresenter( * are ignored. */ private fun deletePendingChapters() { - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { downloadManager.deletePendingChapters() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesPresenter.kt index e243b232ac..d800076112 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesPresenter.kt @@ -23,7 +23,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter 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.system.logcat import kotlinx.coroutines.Job @@ -236,7 +236,7 @@ class UpdatesPresenter( * @param updatesItem the list of chapters to download. */ fun downloadChapters(updatesItem: List) { - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { val groupedUpdates = updatesItem.groupBy { it.update.mangaId }.values for (updates in groupedUpdates) { val mangaId = updates.first().update.mangaId @@ -255,7 +255,7 @@ class UpdatesPresenter( * @param updatesItem list of chapters */ fun deleteChapters(updatesItem: List) { - presenterScope.launchNonCancellableIO { + presenterScope.launchNonCancellable { val groupedUpdates = updatesItem.groupBy { it.update.mangaId }.values val deletedIds = groupedUpdates.flatMap { updates -> val mangaId = updates.first().update.mangaId @@ -268,7 +268,7 @@ class UpdatesPresenter( val deletedUpdates = items.filter { deletedIds.contains(it.update.chapterId) } - if (deletedUpdates.isEmpty()) return@launchNonCancellableIO + if (deletedUpdates.isEmpty()) return@launchNonCancellable // TODO: Don't do this fake status update state.items = items.toMutableList().apply { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt index a3a8cf6abd..4c3d72b4b5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt @@ -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.setting.database.ClearDatabaseController 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.preference.bindTo import eu.kanade.tachiyomi.util.preference.defaultValue @@ -90,7 +90,7 @@ class SettingsAdvancedController( summaryRes = R.string.pref_dump_crash_logs_summary onClick { - viewScope.launchNonCancellableIO { + viewScope.launchNonCancellable { CrashLogUtil(context).dumpLogs() } } @@ -343,7 +343,7 @@ class SettingsAdvancedController( private fun clearChapterCache() { val activity = activity ?: return - viewScope.launchNonCancellableIO { + viewScope.launchNonCancellable { try { val deletedFiles = chapterCache.clear() withUIContext { @@ -379,7 +379,7 @@ class SettingsAdvancedController( private fun resetViewerFlags() { val activity = activity ?: return - viewScope.launchNonCancellableIO { + viewScope.launchNonCancellable { val success = mangaRepository.resetViewerFlags() withUIContext { val message = if (success) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSettingsHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSettingsHelper.kt deleted file mode 100644 index 134c388c59..0000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSettingsHelper.kt +++ /dev/null @@ -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(), - ) - } - } - } -} diff --git a/core/src/main/java/eu/kanade/tachiyomi/util/lang/CoroutinesExtensions.kt b/core/src/main/java/eu/kanade/tachiyomi/util/lang/CoroutinesExtensions.kt index 31eef3cff6..41d6970244 100644 --- a/core/src/main/java/eu/kanade/tachiyomi/util/lang/CoroutinesExtensions.kt +++ b/core/src/main/java/eu/kanade/tachiyomi/util/lang/CoroutinesExtensions.kt @@ -49,9 +49,12 @@ fun CoroutineScope.launchUI(block: suspend CoroutineScope.() -> Unit): Job = fun CoroutineScope.launchIO(block: suspend CoroutineScope.() -> Unit): Job = 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) } suspend fun withUIContext(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.Main, block) suspend fun withIOContext(block: suspend CoroutineScope.() -> T) = withContext(Dispatchers.IO, block) + +suspend fun withNonCancellableContext(block: suspend CoroutineScope.() -> T) = + withContext(NonCancellable, block)