diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 4f85e4cc53..aa61d6b6f6 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -226,7 +226,6 @@ dependencies { // Preferences implementation(libs.preferencektx) - implementation(libs.flowpreferences) // Model View Presenter implementation(libs.bundles.nucleus) diff --git a/app/src/main/java/eu/kanade/core/prefs/PreferenceMutableState.kt b/app/src/main/java/eu/kanade/core/prefs/PreferenceMutableState.kt index ba73475d60..4efd955392 100644 --- a/app/src/main/java/eu/kanade/core/prefs/PreferenceMutableState.kt +++ b/app/src/main/java/eu/kanade/core/prefs/PreferenceMutableState.kt @@ -2,9 +2,8 @@ package eu.kanade.core.prefs import androidx.compose.runtime.MutableState import androidx.compose.runtime.mutableStateOf -import com.fredporciuncula.flow.preferences.Preference +import eu.kanade.tachiyomi.core.preference.Preference import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -16,8 +15,7 @@ class PreferenceMutableState( private val state = mutableStateOf(preference.get()) init { - preference.asFlow() - .distinctUntilChanged() + preference.changes() .onEach { state.value = it } .launchIn(scope) } diff --git a/app/src/main/java/eu/kanade/domain/chapter/interactor/SetReadStatus.kt b/app/src/main/java/eu/kanade/domain/chapter/interactor/SetReadStatus.kt index 69503cbaed..9813b7325e 100644 --- a/app/src/main/java/eu/kanade/domain/chapter/interactor/SetReadStatus.kt +++ b/app/src/main/java/eu/kanade/domain/chapter/interactor/SetReadStatus.kt @@ -52,7 +52,7 @@ class SetReadStatus( return@withContext Result.InternalError(e) } - if (read && preferences.removeAfterMarkedAsRead()) { + if (read && preferences.removeAfterMarkedAsRead().get()) { manga.forEach { deleteDownload.awaitAll( manga = it, diff --git a/app/src/main/java/eu/kanade/domain/extension/interactor/GetExtensionLanguages.kt b/app/src/main/java/eu/kanade/domain/extension/interactor/GetExtensionLanguages.kt index f906d4e3e9..ff277f832f 100644 --- a/app/src/main/java/eu/kanade/domain/extension/interactor/GetExtensionLanguages.kt +++ b/app/src/main/java/eu/kanade/domain/extension/interactor/GetExtensionLanguages.kt @@ -12,7 +12,7 @@ class GetExtensionLanguages( ) { fun subscribe(): Flow> { return combine( - preferences.enabledLanguages().asFlow(), + preferences.enabledLanguages().changes(), extensionManager.getAvailableExtensionsFlow(), ) { enabledLanguage, availableExtensions -> availableExtensions diff --git a/app/src/main/java/eu/kanade/domain/extension/interactor/GetExtensionSources.kt b/app/src/main/java/eu/kanade/domain/extension/interactor/GetExtensionSources.kt index a2acb4bed6..b28de4a134 100644 --- a/app/src/main/java/eu/kanade/domain/extension/interactor/GetExtensionSources.kt +++ b/app/src/main/java/eu/kanade/domain/extension/interactor/GetExtensionSources.kt @@ -16,7 +16,7 @@ class GetExtensionSources( val isMultiLangSingleSource = isMultiSource && extension.sources.map { it.name }.distinct().size == 1 - return preferences.disabledSources().asFlow().map { disabledSources -> + return preferences.disabledSources().changes().map { disabledSources -> fun Source.isEnabled() = id.toString() !in disabledSources extension.sources diff --git a/app/src/main/java/eu/kanade/domain/extension/interactor/GetExtensionsByType.kt b/app/src/main/java/eu/kanade/domain/extension/interactor/GetExtensionsByType.kt index b884e5f180..76fbcda7e8 100644 --- a/app/src/main/java/eu/kanade/domain/extension/interactor/GetExtensionsByType.kt +++ b/app/src/main/java/eu/kanade/domain/extension/interactor/GetExtensionsByType.kt @@ -16,7 +16,7 @@ class GetExtensionsByType( val showNsfwSources = preferences.showNsfwSource().get() return combine( - preferences.enabledLanguages().asFlow(), + preferences.enabledLanguages().changes(), extensionManager.getInstalledExtensionsFlow(), extensionManager.getUntrustedExtensionsFlow(), extensionManager.getAvailableExtensionsFlow(), diff --git a/app/src/main/java/eu/kanade/domain/source/interactor/GetEnabledSources.kt b/app/src/main/java/eu/kanade/domain/source/interactor/GetEnabledSources.kt index 5ed938a320..acc2bf583f 100644 --- a/app/src/main/java/eu/kanade/domain/source/interactor/GetEnabledSources.kt +++ b/app/src/main/java/eu/kanade/domain/source/interactor/GetEnabledSources.kt @@ -17,10 +17,10 @@ class GetEnabledSources( fun subscribe(): Flow> { return combine( - preferences.pinnedSources().asFlow(), - preferences.enabledLanguages().asFlow(), - preferences.disabledSources().asFlow(), - preferences.lastUsedSource().asFlow(), + preferences.pinnedSources().changes(), + preferences.enabledLanguages().changes(), + preferences.disabledSources().changes(), + preferences.lastUsedSource().changes(), repository.getSources(), ) { pinnedSourceIds, enabledLanguages, disabledSources, lastUsedSource, sources -> val duplicatePins = preferences.duplicatePinnedSources().get() diff --git a/app/src/main/java/eu/kanade/domain/source/interactor/GetLanguagesWithSources.kt b/app/src/main/java/eu/kanade/domain/source/interactor/GetLanguagesWithSources.kt index 3feef0a3a1..44c4bea85a 100644 --- a/app/src/main/java/eu/kanade/domain/source/interactor/GetLanguagesWithSources.kt +++ b/app/src/main/java/eu/kanade/domain/source/interactor/GetLanguagesWithSources.kt @@ -14,8 +14,8 @@ class GetLanguagesWithSources( fun subscribe(): Flow>> { return combine( - preferences.enabledLanguages().asFlow(), - preferences.disabledSources().asFlow(), + preferences.enabledLanguages().changes(), + preferences.disabledSources().changes(), repository.getOnlineSources(), ) { enabledLanguage, disabledSource, onlineSources -> val sortedSources = onlineSources.sortedWith( diff --git a/app/src/main/java/eu/kanade/domain/source/interactor/GetSourcesWithFavoriteCount.kt b/app/src/main/java/eu/kanade/domain/source/interactor/GetSourcesWithFavoriteCount.kt index 6af6bd4a81..c60bac7bd1 100644 --- a/app/src/main/java/eu/kanade/domain/source/interactor/GetSourcesWithFavoriteCount.kt +++ b/app/src/main/java/eu/kanade/domain/source/interactor/GetSourcesWithFavoriteCount.kt @@ -16,8 +16,8 @@ class GetSourcesWithFavoriteCount( fun subscribe(): Flow>> { return combine( - preferences.migrationSortingDirection().asFlow(), - preferences.migrationSortingMode().asFlow(), + preferences.migrationSortingDirection().changes(), + preferences.migrationSortingMode().changes(), repository.getSourcesWithFavoriteCount(), ) { direction, mode, list -> list.sortedWith(sortFn(direction, mode)) diff --git a/app/src/main/java/eu/kanade/domain/source/interactor/ToggleLanguage.kt b/app/src/main/java/eu/kanade/domain/source/interactor/ToggleLanguage.kt index 508bc7335b..846690c2a6 100644 --- a/app/src/main/java/eu/kanade/domain/source/interactor/ToggleLanguage.kt +++ b/app/src/main/java/eu/kanade/domain/source/interactor/ToggleLanguage.kt @@ -1,5 +1,6 @@ package eu.kanade.domain.source.interactor +import eu.kanade.tachiyomi.core.preference.getAndSet import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.util.preference.minusAssign import eu.kanade.tachiyomi.util.preference.plusAssign @@ -9,11 +10,9 @@ class ToggleLanguage( ) { fun await(language: String) { - val enabled = language in preferences.enabledLanguages().get() - if (enabled) { - preferences.enabledLanguages() -= language - } else { - preferences.enabledLanguages() += language + val isEnabled = language in preferences.enabledLanguages().get() + preferences.enabledLanguages().getAndSet { enabled -> + if (isEnabled) enabled.minus(language) else enabled.plus(language) } } } diff --git a/app/src/main/java/eu/kanade/domain/source/interactor/ToggleSource.kt b/app/src/main/java/eu/kanade/domain/source/interactor/ToggleSource.kt index 585d20b993..8416206672 100644 --- a/app/src/main/java/eu/kanade/domain/source/interactor/ToggleSource.kt +++ b/app/src/main/java/eu/kanade/domain/source/interactor/ToggleSource.kt @@ -1,6 +1,7 @@ package eu.kanade.domain.source.interactor import eu.kanade.domain.source.model.Source +import eu.kanade.tachiyomi.core.preference.getAndSet import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.util.preference.minusAssign import eu.kanade.tachiyomi.util.preference.plusAssign @@ -14,10 +15,8 @@ class ToggleSource( } fun await(sourceId: Long, enable: Boolean = sourceId.toString() in preferences.disabledSources().get()) { - if (enable) { - preferences.disabledSources() -= sourceId.toString() - } else { - preferences.disabledSources() += sourceId.toString() + preferences.disabledSources().getAndSet { disabled -> + if (enable) disabled.minus("$sourceId") else disabled.plus("$sourceId") } } } diff --git a/app/src/main/java/eu/kanade/domain/source/interactor/ToggleSourcePin.kt b/app/src/main/java/eu/kanade/domain/source/interactor/ToggleSourcePin.kt index d7229ab468..c5d360848a 100644 --- a/app/src/main/java/eu/kanade/domain/source/interactor/ToggleSourcePin.kt +++ b/app/src/main/java/eu/kanade/domain/source/interactor/ToggleSourcePin.kt @@ -1,6 +1,7 @@ package eu.kanade.domain.source.interactor import eu.kanade.domain.source.model.Source +import eu.kanade.tachiyomi.core.preference.getAndSet import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.util.preference.minusAssign import eu.kanade.tachiyomi.util.preference.plusAssign @@ -11,10 +12,8 @@ class ToggleSourcePin( fun await(source: Source) { val isPinned = source.id.toString() in preferences.pinnedSources().get() - if (isPinned) { - preferences.pinnedSources() -= source.id.toString() - } else { - preferences.pinnedSources() += source.id.toString() + preferences.pinnedSources().getAndSet { pinned -> + if (isPinned) pinned.minus("${source.id}") else pinned.plus("${source.id}") } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/App.kt b/app/src/main/java/eu/kanade/tachiyomi/App.kt index 37a88933cf..94b7117fe0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/App.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/App.kt @@ -37,6 +37,7 @@ import eu.kanade.tachiyomi.data.preference.PreferenceValues import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.glance.UpdatesGridGlanceWidget import eu.kanade.tachiyomi.network.NetworkHelper +import eu.kanade.tachiyomi.network.NetworkPreferences import eu.kanade.tachiyomi.ui.base.delegate.SecureActivityDelegate import eu.kanade.tachiyomi.util.preference.asHotFlow import eu.kanade.tachiyomi.util.system.WebViewUtil @@ -63,6 +64,7 @@ import java.security.Security class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory { private val preferences: PreferencesHelper by injectLazy() + private val networkPreferences: NetworkPreferences by injectLazy() private val disableIncognitoReceiver = DisableIncognitoReceiver() @@ -82,6 +84,7 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory { } Injekt.importModule(AppModule(this)) + Injekt.importModule(PreferenceModule(this)) Injekt.importModule(DomainModule()) setupAcra() @@ -90,7 +93,7 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory { ProcessLifecycleOwner.get().lifecycle.addObserver(this) // Show notification to disable Incognito Mode when it's enabled - preferences.incognitoMode().asFlow() + preferences.incognitoMode().changes() .onEach { enabled -> val notificationManager = NotificationManagerCompat.from(this) if (enabled) { @@ -141,7 +144,7 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory { } .launchIn(ProcessLifecycleOwner.get().lifecycleScope) - if (!LogcatLogger.isInstalled && preferences.verboseLogging()) { + if (!LogcatLogger.isInstalled && networkPreferences.verboseLogging().get()) { LogcatLogger.install(AndroidLogcatLogger(LogPriority.VERBOSE)) } } @@ -168,7 +171,7 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory { diskCache(diskCacheInit) crossfade((300 * this@App.animatorDurationScale).toInt()) allowRgb565(getSystemService()!!.isLowRamDevice) - if (preferences.verboseLogging()) logger(DebugLogger()) + if (networkPreferences.verboseLogging().get()) logger(DebugLogger()) }.build() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt b/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt index e1253c8896..ff7278054c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt @@ -13,6 +13,8 @@ import eu.kanade.data.AndroidDatabaseHandler import eu.kanade.data.DatabaseHandler import eu.kanade.data.dateAdapter import eu.kanade.data.listOfStringsAdapter +import eu.kanade.tachiyomi.core.preference.AndroidPreferenceStore +import eu.kanade.tachiyomi.core.preference.PreferenceStore import eu.kanade.tachiyomi.data.cache.ChapterCache import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.download.DownloadManager @@ -22,7 +24,9 @@ import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.data.track.job.DelayedTrackingStore import eu.kanade.tachiyomi.extension.ExtensionManager import eu.kanade.tachiyomi.network.NetworkHelper +import eu.kanade.tachiyomi.network.NetworkPreferences import eu.kanade.tachiyomi.source.SourceManager +import eu.kanade.tachiyomi.util.system.isDevFlavor import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory import kotlinx.serialization.json.Json import uy.kohesive.injekt.api.InjektModule @@ -84,8 +88,6 @@ class AppModule(val app: Application) : InjektModule { } } - addSingletonFactory { PreferencesHelper(app) } - addSingletonFactory { ChapterCache(app) } addSingletonFactory { CoverCache(app) } @@ -106,8 +108,6 @@ class AppModule(val app: Application) : InjektModule { // Asynchronously init expensive components for a faster cold start ContextCompat.getMainExecutor(app).execute { - get() - get() get() @@ -118,3 +118,23 @@ class AppModule(val app: Application) : InjektModule { } } } + +class PreferenceModule(val application: Application) : InjektModule { + override fun InjektRegistrar.registerInjectables() { + addSingletonFactory { + AndroidPreferenceStore(application) + } + addSingletonFactory { + NetworkPreferences( + preferenceStore = get(), + verboseLogging = isDevFlavor, + ) + } + addSingletonFactory { + PreferencesHelper( + context = application, + preferenceStore = get(), + ) + } + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt b/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt index 40af4ce18e..b5911fb46a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt @@ -1,5 +1,6 @@ package eu.kanade.tachiyomi +import android.content.Context import android.os.Build import androidx.core.content.edit import androidx.preference.PreferenceManager @@ -12,6 +13,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.data.updater.AppUpdateJob import eu.kanade.tachiyomi.extension.ExtensionUpdateJob +import eu.kanade.tachiyomi.network.NetworkPreferences import eu.kanade.tachiyomi.network.PREF_DOH_CLOUDFLARE import eu.kanade.tachiyomi.ui.reader.setting.OrientationType import eu.kanade.tachiyomi.util.preference.minusAssign @@ -31,9 +33,11 @@ object Migrations { * @param preferences Preferences of the application. * @return true if a migration is performed, false otherwise. */ - fun upgrade(preferences: PreferencesHelper): Boolean { - val context = preferences.context - + fun upgrade( + context: Context, + preferences: PreferencesHelper, + networkPreferences: NetworkPreferences, + ): Boolean { val oldVersion = preferences.lastVersionCode().get() if (oldVersion < BuildConfig.VERSION_CODE) { preferences.lastVersionCode().set(BuildConfig.VERSION_CODE) @@ -143,7 +147,7 @@ object Migrations { val wasDohEnabled = prefs.getBoolean("enable_doh", false) if (wasDohEnabled) { prefs.edit { - putInt(PreferenceKeys.dohProvider, PREF_DOH_CLOUDFLARE) + putInt(networkPreferences.dohProvider().key(), PREF_DOH_CLOUDFLARE) remove("enable_doh") } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupNotifier.kt index 3ab6366df8..b730cba50b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupNotifier.kt @@ -84,7 +84,7 @@ class BackupNotifier(private val context: Context) { val builder = with(progressNotificationBuilder) { setContentTitle(context.getString(R.string.restoring_backup)) - if (!preferences.hideNotificationContent()) { + if (!preferences.hideNotificationContent().get()) { setContentText(content) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt index ac1954a1ec..931f011763 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt @@ -47,7 +47,7 @@ class DownloadCache( private var rootDir = RootDirectory(getDirectoryFromPreference()) init { - preferences.downloadsDirectory().asFlow() + preferences.downloadsDirectory().changes() .onEach { lastRenew = 0L // invalidate cache rootDir = RootDirectory(getDirectoryFromPreference()) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt index 1c478e91ee..ebc0c1b338 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.kt @@ -414,7 +414,7 @@ class DownloadManager( return if (categoriesForManga.intersect(categoriesToExclude).isNotEmpty()) { chapters.filterNot { it.read } - } else if (!preferences.removeBookmarkedChapters()) { + } else if (!preferences.removeBookmarkedChapters().get()) { chapters.filterNot { it.bookmark } } else { chapters diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadNotifier.kt index 9c5f376993..230acaca97 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadNotifier.kt @@ -104,7 +104,7 @@ internal class DownloadNotifier(private val context: Context) { download.pages!!.size, ) - if (preferences.hideNotificationContent()) { + if (preferences.hideNotificationContent().get()) { setContentTitle(downloadingProgressText) setContentText(null) } else { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt index b2d9e9dcdd..395692f44c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadProvider.kt @@ -39,7 +39,7 @@ class DownloadProvider(private val context: Context) { } init { - preferences.downloadsDirectory().asFlow() + preferences.downloadsDirectory().changes() .onEach { downloadsDir = UniFile.fromUri(context, it.toUri()) } .launchIn(scope) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadService.kt index 7c2a126305..4da0263730 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadService.kt @@ -164,7 +164,7 @@ class DownloadService : Service() { */ private fun onNetworkStateChanged() { if (isOnline()) { - if (preferences.downloadOnlyOverWifi() && !isConnectedToWifi()) { + if (preferences.downloadOnlyOverWifi().get() && !isConnectedToWifi()) { stopDownloads(R.string.download_notifier_text_only_wifi) } else { val started = downloadManager.startDownloads() diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt index 645cc37c21..c0e633fa91 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt @@ -71,7 +71,7 @@ class LibraryUpdateNotifier(private val context: Context) { * @param total the total progress. */ fun showProgressNotification(manga: List, current: Int, total: Int) { - if (preferences.hideNotificationContent()) { + if (preferences.hideNotificationContent().get()) { progressNotificationBuilder .setContentTitle(context.getString(R.string.notification_check_updates)) .setContentText("($current/$total)") @@ -167,12 +167,12 @@ class LibraryUpdateNotifier(private val context: Context) { Notifications.ID_NEW_CHAPTERS, context.notification(Notifications.CHANNEL_NEW_CHAPTERS) { setContentTitle(context.getString(R.string.notification_new_chapters)) - if (updates.size == 1 && !preferences.hideNotificationContent()) { + if (updates.size == 1 && !preferences.hideNotificationContent().get()) { setContentText(updates.first().first.title.chop(NOTIF_TITLE_MAX_LEN)) } else { setContentText(context.resources.getQuantityString(R.plurals.notification_new_chapters_summary, updates.size, updates.size)) - if (!preferences.hideNotificationContent()) { + if (!preferences.hideNotificationContent().get()) { setStyle( NotificationCompat.BigTextStyle().bigText( updates.joinToString("\n") { @@ -197,7 +197,7 @@ class LibraryUpdateNotifier(private val context: Context) { ) // Per-manga notification - if (!preferences.hideNotificationContent()) { + if (!preferences.hideNotificationContent().get()) { launchUI { updates.forEach { (manga, chapters) -> notify(manga.id.hashCode(), createNewChaptersNotification(manga, chapters)) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt index c548c458a8..70a807292f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt @@ -380,7 +380,7 @@ class LibraryUpdateService( failedUpdates.add(mangaWithNotif to errorMessage) } - if (preferences.autoUpdateTrackers()) { + if (preferences.autoUpdateTrackers().get()) { updateTrackings(mangaWithNotif, loggedServices) } } @@ -430,7 +430,7 @@ class LibraryUpdateService( val source = sourceManager.getOrStub(manga.source) // Update manga metadata if needed - if (preferences.autoUpdateMetadata()) { + if (preferences.autoUpdateMetadata().get()) { val networkManga = source.getMangaDetails(manga.toSManga()) updateManga.awaitUpdateFromSource(manga, networkManga, manualFetch = false, coverCache) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt index db5bd65dad..f8d2323976 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt @@ -248,7 +248,7 @@ class NotificationReceiver : BroadcastReceiver() { val toUpdate = chapterUrls.mapNotNull { getChapter.await(it, mangaId) } .map { val chapter = it.copy(read = true) - if (preferences.removeAfterMarkedAsRead()) { + if (preferences.removeAfterMarkedAsRead().get()) { val manga = getManga.await(mangaId) if (manga != null) { val source = sourceManager.get(manga.source) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt index 0e2bdab360..4cd39dd8ba 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt @@ -56,10 +56,6 @@ object PreferenceKeys { const val searchPinnedSourcesOnly = "search_pinned_sources_only" - const val dohProvider = "doh_provider" - - const val defaultUserAgent = "default_user_agent" - const val defaultChapterFilterByRead = "default_chapter_filter_by_read" const val defaultChapterFilterByDownloaded = "default_chapter_filter_by_downloaded" @@ -72,8 +68,6 @@ object PreferenceKeys { const val defaultChapterDisplayByNameOrNumber = "default_chapter_display_by_name_or_number" - const val verboseLogging = "verbose_logging" - const val autoClearChapterCache = "auto_clear_chapter_cache" fun trackUsername(syncId: Long) = "pref_mangasync_username_$syncId" 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 b9e85c0b59..5a6faceadb 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 @@ -3,12 +3,11 @@ package eu.kanade.tachiyomi.data.preference import android.content.Context import android.os.Build import android.os.Environment -import androidx.core.content.edit import androidx.core.net.toUri -import androidx.preference.PreferenceManager -import com.fredporciuncula.flow.preferences.FlowSharedPreferences import eu.kanade.domain.source.interactor.SetMigrateSorting import eu.kanade.tachiyomi.R +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.data.track.TrackService import eu.kanade.tachiyomi.data.track.anilist.Anilist @@ -18,7 +17,6 @@ import eu.kanade.tachiyomi.ui.reader.setting.OrientationType import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType import eu.kanade.tachiyomi.util.system.DeviceUtil import eu.kanade.tachiyomi.util.system.LocaleHelper -import eu.kanade.tachiyomi.util.system.isDevFlavor import eu.kanade.tachiyomi.util.system.isDynamicColorAvailable import eu.kanade.tachiyomi.widget.ExtendedNavigationView import java.io.File @@ -29,10 +27,10 @@ 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 -class PreferencesHelper(val context: Context) { - - private val prefs = PreferenceManager.getDefaultSharedPreferences(context) - private val flowPrefs = FlowSharedPreferences(prefs) +class PreferencesHelper( + val context: Context, + private val preferenceStore: PreferenceStore, +) { private val defaultDownloadsDir = File( Environment.getExternalStorageDirectory().absolutePath + File.separator + @@ -46,300 +44,290 @@ class PreferencesHelper(val context: Context) { "backup", ).toUri() - fun confirmExit() = prefs.getBoolean(Keys.confirmExit, false) + fun confirmExit() = this.preferenceStore.getBoolean(Keys.confirmExit, false) - fun sideNavIconAlignment() = flowPrefs.getInt("pref_side_nav_icon_alignment", 0) + fun sideNavIconAlignment() = this.preferenceStore.getInt("pref_side_nav_icon_alignment", 0) - fun useAuthenticator() = flowPrefs.getBoolean("use_biometric_lock", false) + fun useAuthenticator() = this.preferenceStore.getBoolean("use_biometric_lock", false) - fun lockAppAfter() = flowPrefs.getInt("lock_app_after", 0) + fun lockAppAfter() = this.preferenceStore.getInt("lock_app_after", 0) /** * For app lock. Will be set when there is a pending timed lock. * Otherwise this pref should be deleted. */ - fun lastAppClosed() = flowPrefs.getLong("last_app_closed", 0) + fun lastAppClosed() = this.preferenceStore.getLong("last_app_closed", 0) - fun secureScreen() = flowPrefs.getEnum("secure_screen_v2", Values.SecureScreenMode.INCOGNITO) + fun secureScreen() = this.preferenceStore.getEnum("secure_screen_v2", Values.SecureScreenMode.INCOGNITO) - fun hideNotificationContent() = prefs.getBoolean(Keys.hideNotificationContent, false) + fun hideNotificationContent() = this.preferenceStore.getBoolean(Keys.hideNotificationContent, false) - fun autoUpdateMetadata() = prefs.getBoolean(Keys.autoUpdateMetadata, false) + fun autoUpdateMetadata() = this.preferenceStore.getBoolean(Keys.autoUpdateMetadata, false) - fun autoUpdateTrackers() = prefs.getBoolean(Keys.autoUpdateTrackers, false) + fun autoUpdateTrackers() = this.preferenceStore.getBoolean(Keys.autoUpdateTrackers, false) - fun themeMode() = flowPrefs.getEnum( + fun themeMode() = this.preferenceStore.getEnum( "pref_theme_mode_key", if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { Values.ThemeMode.system } else { Values.ThemeMode.light }, ) - fun appTheme() = flowPrefs.getEnum( + fun appTheme() = this.preferenceStore.getEnum( "pref_app_theme", if (DeviceUtil.isDynamicColorAvailable) { Values.AppTheme.MONET } else { Values.AppTheme.DEFAULT }, ) - fun themeDarkAmoled() = flowPrefs.getBoolean("pref_theme_dark_amoled_key", false) + fun themeDarkAmoled() = this.preferenceStore.getBoolean("pref_theme_dark_amoled_key", false) - fun pageTransitions() = flowPrefs.getBoolean("pref_enable_transitions_key", true) + fun pageTransitions() = this.preferenceStore.getBoolean("pref_enable_transitions_key", true) - fun doubleTapAnimSpeed() = flowPrefs.getInt("pref_double_tap_anim_speed", 500) + fun doubleTapAnimSpeed() = this.preferenceStore.getInt("pref_double_tap_anim_speed", 500) - fun showPageNumber() = flowPrefs.getBoolean("pref_show_page_number_key", true) + fun showPageNumber() = this.preferenceStore.getBoolean("pref_show_page_number_key", true) - fun dualPageSplitPaged() = flowPrefs.getBoolean("pref_dual_page_split", false) + fun dualPageSplitPaged() = this.preferenceStore.getBoolean("pref_dual_page_split", false) - fun dualPageInvertPaged() = flowPrefs.getBoolean("pref_dual_page_invert", false) + fun dualPageInvertPaged() = this.preferenceStore.getBoolean("pref_dual_page_invert", false) - fun dualPageSplitWebtoon() = flowPrefs.getBoolean("pref_dual_page_split_webtoon", false) + fun dualPageSplitWebtoon() = this.preferenceStore.getBoolean("pref_dual_page_split_webtoon", false) - fun dualPageInvertWebtoon() = flowPrefs.getBoolean("pref_dual_page_invert_webtoon", false) + fun dualPageInvertWebtoon() = this.preferenceStore.getBoolean("pref_dual_page_invert_webtoon", false) - fun longStripSplitWebtoon() = flowPrefs.getBoolean("pref_long_strip_split_webtoon", true) + fun longStripSplitWebtoon() = this.preferenceStore.getBoolean("pref_long_strip_split_webtoon", true) - fun showReadingMode() = prefs.getBoolean(Keys.showReadingMode, true) + fun showReadingMode() = this.preferenceStore.getBoolean(Keys.showReadingMode, true) - fun trueColor() = flowPrefs.getBoolean("pref_true_color_key", false) + fun trueColor() = this.preferenceStore.getBoolean("pref_true_color_key", false) - fun fullscreen() = flowPrefs.getBoolean("fullscreen", true) + fun fullscreen() = this.preferenceStore.getBoolean("fullscreen", true) - fun cutoutShort() = flowPrefs.getBoolean("cutout_short", true) + fun cutoutShort() = this.preferenceStore.getBoolean("cutout_short", true) - fun keepScreenOn() = flowPrefs.getBoolean("pref_keep_screen_on_key", true) + fun keepScreenOn() = this.preferenceStore.getBoolean("pref_keep_screen_on_key", true) - fun customBrightness() = flowPrefs.getBoolean("pref_custom_brightness_key", false) + fun customBrightness() = this.preferenceStore.getBoolean("pref_custom_brightness_key", false) - fun customBrightnessValue() = flowPrefs.getInt("custom_brightness_value", 0) + fun customBrightnessValue() = this.preferenceStore.getInt("custom_brightness_value", 0) - fun colorFilter() = flowPrefs.getBoolean("pref_color_filter_key", false) + fun colorFilter() = this.preferenceStore.getBoolean("pref_color_filter_key", false) - fun colorFilterValue() = flowPrefs.getInt("color_filter_value", 0) + fun colorFilterValue() = this.preferenceStore.getInt("color_filter_value", 0) - fun colorFilterMode() = flowPrefs.getInt("color_filter_mode", 0) + fun colorFilterMode() = this.preferenceStore.getInt("color_filter_mode", 0) - fun grayscale() = flowPrefs.getBoolean("pref_grayscale", false) + fun grayscale() = this.preferenceStore.getBoolean("pref_grayscale", false) - fun invertedColors() = flowPrefs.getBoolean("pref_inverted_colors", false) + fun invertedColors() = this.preferenceStore.getBoolean("pref_inverted_colors", false) - fun defaultReadingMode() = prefs.getInt(Keys.defaultReadingMode, ReadingModeType.RIGHT_TO_LEFT.flagValue) + fun defaultReadingMode() = this.preferenceStore.getInt(Keys.defaultReadingMode, ReadingModeType.RIGHT_TO_LEFT.flagValue) - fun defaultOrientationType() = prefs.getInt(Keys.defaultOrientationType, OrientationType.FREE.flagValue) + fun defaultOrientationType() = this.preferenceStore.getInt(Keys.defaultOrientationType, OrientationType.FREE.flagValue) - fun imageScaleType() = flowPrefs.getInt("pref_image_scale_type_key", 1) + fun imageScaleType() = this.preferenceStore.getInt("pref_image_scale_type_key", 1) - fun zoomStart() = flowPrefs.getInt("pref_zoom_start_key", 1) + fun zoomStart() = this.preferenceStore.getInt("pref_zoom_start_key", 1) - fun readerTheme() = flowPrefs.getInt("pref_reader_theme_key", 1) + fun readerTheme() = this.preferenceStore.getInt("pref_reader_theme_key", 1) - fun alwaysShowChapterTransition() = flowPrefs.getBoolean("always_show_chapter_transition", true) + fun alwaysShowChapterTransition() = this.preferenceStore.getBoolean("always_show_chapter_transition", true) - fun cropBorders() = flowPrefs.getBoolean("crop_borders", false) + fun cropBorders() = this.preferenceStore.getBoolean("crop_borders", false) - fun navigateToPan() = flowPrefs.getBoolean("navigate_pan", true) + fun navigateToPan() = this.preferenceStore.getBoolean("navigate_pan", true) - fun landscapeZoom() = flowPrefs.getBoolean("landscape_zoom", true) + fun landscapeZoom() = this.preferenceStore.getBoolean("landscape_zoom", true) - fun cropBordersWebtoon() = flowPrefs.getBoolean("crop_borders_webtoon", false) + fun cropBordersWebtoon() = this.preferenceStore.getBoolean("crop_borders_webtoon", false) - fun webtoonSidePadding() = flowPrefs.getInt("webtoon_side_padding", 0) + fun webtoonSidePadding() = this.preferenceStore.getInt("webtoon_side_padding", 0) - fun pagerNavInverted() = flowPrefs.getEnum("reader_tapping_inverted", Values.TappingInvertMode.NONE) + fun pagerNavInverted() = this.preferenceStore.getEnum("reader_tapping_inverted", Values.TappingInvertMode.NONE) - fun webtoonNavInverted() = flowPrefs.getEnum("reader_tapping_inverted_webtoon", Values.TappingInvertMode.NONE) + fun webtoonNavInverted() = this.preferenceStore.getEnum("reader_tapping_inverted_webtoon", Values.TappingInvertMode.NONE) - fun readWithLongTap() = flowPrefs.getBoolean("reader_long_tap", true) + fun readWithLongTap() = this.preferenceStore.getBoolean("reader_long_tap", true) - fun readWithVolumeKeys() = flowPrefs.getBoolean("reader_volume_keys", false) + fun readWithVolumeKeys() = this.preferenceStore.getBoolean("reader_volume_keys", false) - fun readWithVolumeKeysInverted() = flowPrefs.getBoolean("reader_volume_keys_inverted", false) + fun readWithVolumeKeysInverted() = this.preferenceStore.getBoolean("reader_volume_keys_inverted", false) - fun navigationModePager() = flowPrefs.getInt("reader_navigation_mode_pager", 0) + fun navigationModePager() = this.preferenceStore.getInt("reader_navigation_mode_pager", 0) - fun navigationModeWebtoon() = flowPrefs.getInt("reader_navigation_mode_webtoon", 0) + fun navigationModeWebtoon() = this.preferenceStore.getInt("reader_navigation_mode_webtoon", 0) - fun showNavigationOverlayNewUser() = flowPrefs.getBoolean("reader_navigation_overlay_new_user", true) + fun showNavigationOverlayNewUser() = this.preferenceStore.getBoolean("reader_navigation_overlay_new_user", true) - fun showNavigationOverlayOnStart() = flowPrefs.getBoolean("reader_navigation_overlay_on_start", false) + fun showNavigationOverlayOnStart() = this.preferenceStore.getBoolean("reader_navigation_overlay_on_start", false) - fun readerHideThreshold() = flowPrefs.getEnum("reader_hide_threshold", Values.ReaderHideThreshold.LOW) + fun readerHideThreshold() = this.preferenceStore.getEnum("reader_hide_threshold", Values.ReaderHideThreshold.LOW) - fun portraitColumns() = flowPrefs.getInt("pref_library_columns_portrait_key", 0) + fun portraitColumns() = this.preferenceStore.getInt("pref_library_columns_portrait_key", 0) - fun landscapeColumns() = flowPrefs.getInt("pref_library_columns_landscape_key", 0) + fun landscapeColumns() = this.preferenceStore.getInt("pref_library_columns_landscape_key", 0) - fun autoUpdateTrack() = prefs.getBoolean(Keys.autoUpdateTrack, true) + fun autoUpdateTrack() = this.preferenceStore.getBoolean(Keys.autoUpdateTrack, true) - fun lastUsedSource() = flowPrefs.getLong("last_catalogue_source", -1) + fun lastUsedSource() = this.preferenceStore.getLong("last_catalogue_source", -1) - fun lastUsedCategory() = flowPrefs.getInt("last_used_category", 0) + fun lastUsedCategory() = this.preferenceStore.getInt("last_used_category", 0) - fun lastVersionCode() = flowPrefs.getInt("last_version_code", 0) + fun lastVersionCode() = this.preferenceStore.getInt("last_version_code", 0) - fun sourceDisplayMode() = flowPrefs.getObject("pref_display_mode_catalogue", LibraryDisplayMode.Serializer, LibraryDisplayMode.default) + fun sourceDisplayMode() = this.preferenceStore.getObject("pref_display_mode_catalogue", LibraryDisplayMode.default, LibraryDisplayMode.Serializer::serialize, LibraryDisplayMode.Serializer::deserialize) - fun enabledLanguages() = flowPrefs.getStringSet("source_languages", LocaleHelper.getDefaultEnabledLanguages()) + fun enabledLanguages() = this.preferenceStore.getStringSet("source_languages", LocaleHelper.getDefaultEnabledLanguages()) - fun trackUsername(sync: TrackService) = prefs.getString(Keys.trackUsername(sync.id), "") + fun trackUsername(sync: TrackService) = this.preferenceStore.getString(Keys.trackUsername(sync.id), "") - fun trackPassword(sync: TrackService) = prefs.getString(Keys.trackPassword(sync.id), "") + fun trackPassword(sync: TrackService) = this.preferenceStore.getString(Keys.trackPassword(sync.id), "") fun setTrackCredentials(sync: TrackService, username: String, password: String) { - prefs.edit { - putString(Keys.trackUsername(sync.id), username) - putString(Keys.trackPassword(sync.id), password) - } + trackUsername(sync).set(username) + trackPassword(sync).set(password) } - fun trackToken(sync: TrackService) = flowPrefs.getString(Keys.trackToken(sync.id), "") + fun trackToken(sync: TrackService) = this.preferenceStore.getString(Keys.trackToken(sync.id), "") - fun anilistScoreType() = flowPrefs.getString("anilist_score_type", Anilist.POINT_10) + fun anilistScoreType() = this.preferenceStore.getString("anilist_score_type", Anilist.POINT_10) - fun backupsDirectory() = flowPrefs.getString("backup_directory", defaultBackupDir.toString()) + fun backupsDirectory() = this.preferenceStore.getString("backup_directory", defaultBackupDir.toString()) - fun relativeTime() = flowPrefs.getInt("relative_time", 7) + fun relativeTime() = this.preferenceStore.getInt("relative_time", 7) - fun dateFormat(format: String = flowPrefs.getString(Keys.dateFormat, "").get()): DateFormat = when (format) { + fun dateFormat(format: String = this.preferenceStore.getString(Keys.dateFormat, "").get()): DateFormat = when (format) { "" -> DateFormat.getDateInstance(DateFormat.SHORT) else -> SimpleDateFormat(format, Locale.getDefault()) } - fun downloadsDirectory() = flowPrefs.getString("download_directory", defaultDownloadsDir.toString()) + fun downloadsDirectory() = this.preferenceStore.getString("download_directory", defaultDownloadsDir.toString()) - fun downloadOnlyOverWifi() = prefs.getBoolean(Keys.downloadOnlyOverWifi, true) + fun downloadOnlyOverWifi() = this.preferenceStore.getBoolean(Keys.downloadOnlyOverWifi, true) - fun saveChaptersAsCBZ() = flowPrefs.getBoolean("save_chapter_as_cbz", true) + fun saveChaptersAsCBZ() = this.preferenceStore.getBoolean("save_chapter_as_cbz", true) - fun splitTallImages() = flowPrefs.getBoolean("split_tall_images", false) + fun splitTallImages() = this.preferenceStore.getBoolean("split_tall_images", false) - fun folderPerManga() = prefs.getBoolean(Keys.folderPerManga, false) + fun folderPerManga() = this.preferenceStore.getBoolean(Keys.folderPerManga, false) - fun numberOfBackups() = flowPrefs.getInt("backup_slots", 2) + fun numberOfBackups() = this.preferenceStore.getInt("backup_slots", 2) - fun backupInterval() = flowPrefs.getInt("backup_interval", 12) + fun backupInterval() = this.preferenceStore.getInt("backup_interval", 12) - fun removeAfterReadSlots() = prefs.getInt(Keys.removeAfterReadSlots, -1) + fun removeAfterReadSlots() = this.preferenceStore.getInt(Keys.removeAfterReadSlots, -1) - fun removeAfterMarkedAsRead() = prefs.getBoolean(Keys.removeAfterMarkedAsRead, false) + fun removeAfterMarkedAsRead() = this.preferenceStore.getBoolean(Keys.removeAfterMarkedAsRead, false) - fun removeBookmarkedChapters() = prefs.getBoolean(Keys.removeBookmarkedChapters, false) + fun removeBookmarkedChapters() = this.preferenceStore.getBoolean(Keys.removeBookmarkedChapters, false) - fun removeExcludeCategories() = flowPrefs.getStringSet("remove_exclude_categories", emptySet()) + fun removeExcludeCategories() = this.preferenceStore.getStringSet("remove_exclude_categories", emptySet()) - fun libraryUpdateInterval() = flowPrefs.getInt("pref_library_update_interval_key", 24) - fun libraryUpdateLastTimestamp() = flowPrefs.getLong("library_update_last_timestamp", 0L) + fun libraryUpdateInterval() = this.preferenceStore.getInt("pref_library_update_interval_key", 24) + fun libraryUpdateLastTimestamp() = this.preferenceStore.getLong("library_update_last_timestamp", 0L) - fun libraryUpdateDeviceRestriction() = flowPrefs.getStringSet("library_update_restriction", setOf(DEVICE_ONLY_ON_WIFI)) - fun libraryUpdateMangaRestriction() = flowPrefs.getStringSet("library_update_manga_restriction", setOf(MANGA_HAS_UNREAD, MANGA_NON_COMPLETED, MANGA_NON_READ)) + fun libraryUpdateDeviceRestriction() = this.preferenceStore.getStringSet("library_update_restriction", setOf(DEVICE_ONLY_ON_WIFI)) + fun libraryUpdateMangaRestriction() = this.preferenceStore.getStringSet("library_update_manga_restriction", setOf(MANGA_HAS_UNREAD, MANGA_NON_COMPLETED, MANGA_NON_READ)) - fun showUpdatesNavBadge() = flowPrefs.getBoolean("library_update_show_tab_badge", false) - fun unreadUpdatesCount() = flowPrefs.getInt("library_unread_updates_count", 0) + fun showUpdatesNavBadge() = this.preferenceStore.getBoolean("library_update_show_tab_badge", false) + fun unreadUpdatesCount() = this.preferenceStore.getInt("library_unread_updates_count", 0) - fun libraryUpdateCategories() = flowPrefs.getStringSet("library_update_categories", emptySet()) - fun libraryUpdateCategoriesExclude() = flowPrefs.getStringSet("library_update_categories_exclude", emptySet()) + fun libraryUpdateCategories() = this.preferenceStore.getStringSet("library_update_categories", emptySet()) + fun libraryUpdateCategoriesExclude() = this.preferenceStore.getStringSet("library_update_categories_exclude", emptySet()) - fun libraryDisplayMode() = flowPrefs.getObject("pref_display_mode_library", LibraryDisplayMode.Serializer, LibraryDisplayMode.default) + fun libraryDisplayMode() = this.preferenceStore.getObject("pref_display_mode_library", LibraryDisplayMode.default, LibraryDisplayMode.Serializer::serialize, LibraryDisplayMode.Serializer::deserialize) - fun downloadBadge() = flowPrefs.getBoolean("display_download_badge", false) + fun downloadBadge() = this.preferenceStore.getBoolean("display_download_badge", false) - fun localBadge() = flowPrefs.getBoolean("display_local_badge", true) + fun localBadge() = this.preferenceStore.getBoolean("display_local_badge", true) - fun downloadedOnly() = flowPrefs.getBoolean("pref_downloaded_only", false) + fun downloadedOnly() = this.preferenceStore.getBoolean("pref_downloaded_only", false) - fun unreadBadge() = flowPrefs.getBoolean("display_unread_badge", true) + fun unreadBadge() = this.preferenceStore.getBoolean("display_unread_badge", true) - fun languageBadge() = flowPrefs.getBoolean("display_language_badge", false) + fun languageBadge() = this.preferenceStore.getBoolean("display_language_badge", false) - fun categoryTabs() = flowPrefs.getBoolean("display_category_tabs", true) + fun categoryTabs() = this.preferenceStore.getBoolean("display_category_tabs", true) - fun categoryNumberOfItems() = flowPrefs.getBoolean("display_number_of_items", false) + fun categoryNumberOfItems() = this.preferenceStore.getBoolean("display_number_of_items", false) - fun filterDownloaded() = flowPrefs.getInt(Keys.filterDownloaded, ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value) + fun filterDownloaded() = this.preferenceStore.getInt(Keys.filterDownloaded, ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value) - fun filterUnread() = flowPrefs.getInt(Keys.filterUnread, ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value) + fun filterUnread() = this.preferenceStore.getInt(Keys.filterUnread, ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value) - fun filterStarted() = flowPrefs.getInt(Keys.filterStarted, ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value) + fun filterStarted() = this.preferenceStore.getInt(Keys.filterStarted, ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value) - fun filterCompleted() = flowPrefs.getInt(Keys.filterCompleted, ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value) + fun filterCompleted() = this.preferenceStore.getInt(Keys.filterCompleted, ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value) - fun filterTracking(name: Int) = flowPrefs.getInt("${Keys.filterTracked}_$name", ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value) + fun filterTracking(name: Int) = this.preferenceStore.getInt("${Keys.filterTracked}_$name", ExtendedNavigationView.Item.TriStateGroup.State.IGNORE.value) - fun librarySortingMode() = flowPrefs.getObject(Keys.librarySortingMode, LibrarySort.Serializer, LibrarySort.default) + fun librarySortingMode() = this.preferenceStore.getObject(Keys.librarySortingMode, LibrarySort.default, LibrarySort.Serializer::serialize, LibrarySort.Serializer::deserialize) - fun migrationSortingMode() = flowPrefs.getEnum(Keys.migrationSortingMode, SetMigrateSorting.Mode.ALPHABETICAL) - fun migrationSortingDirection() = flowPrefs.getEnum(Keys.migrationSortingDirection, SetMigrateSorting.Direction.ASCENDING) + fun migrationSortingMode() = this.preferenceStore.getEnum(Keys.migrationSortingMode, SetMigrateSorting.Mode.ALPHABETICAL) + fun migrationSortingDirection() = this.preferenceStore.getEnum(Keys.migrationSortingDirection, SetMigrateSorting.Direction.ASCENDING) - fun automaticExtUpdates() = flowPrefs.getBoolean("automatic_ext_updates", true) + fun automaticExtUpdates() = this.preferenceStore.getBoolean("automatic_ext_updates", true) - fun showNsfwSource() = flowPrefs.getBoolean("show_nsfw_source", true) + fun showNsfwSource() = this.preferenceStore.getBoolean("show_nsfw_source", true) - fun extensionUpdatesCount() = flowPrefs.getInt("ext_updates_count", 0) + fun extensionUpdatesCount() = this.preferenceStore.getInt("ext_updates_count", 0) - fun lastAppCheck() = flowPrefs.getLong("last_app_check", 0) - fun lastExtCheck() = flowPrefs.getLong("last_ext_check", 0) + fun lastAppCheck() = this.preferenceStore.getLong("last_app_check", 0) + fun lastExtCheck() = this.preferenceStore.getLong("last_ext_check", 0) - fun searchPinnedSourcesOnly() = prefs.getBoolean(Keys.searchPinnedSourcesOnly, false) + fun searchPinnedSourcesOnly() = this.preferenceStore.getBoolean(Keys.searchPinnedSourcesOnly, false) - fun disabledSources() = flowPrefs.getStringSet("hidden_catalogues", emptySet()) + fun disabledSources() = this.preferenceStore.getStringSet("hidden_catalogues", emptySet()) - fun pinnedSources() = flowPrefs.getStringSet("pinned_catalogues", emptySet()) + fun pinnedSources() = this.preferenceStore.getStringSet("pinned_catalogues", emptySet()) - fun downloadNewChapters() = flowPrefs.getBoolean("download_new", false) + fun downloadNewChapters() = this.preferenceStore.getBoolean("download_new", false) - fun downloadNewChapterCategories() = flowPrefs.getStringSet("download_new_categories", emptySet()) - fun downloadNewChapterCategoriesExclude() = flowPrefs.getStringSet("download_new_categories_exclude", emptySet()) + fun downloadNewChapterCategories() = this.preferenceStore.getStringSet("download_new_categories", emptySet()) + fun downloadNewChapterCategoriesExclude() = this.preferenceStore.getStringSet("download_new_categories_exclude", emptySet()) - fun autoDownloadWhileReading() = flowPrefs.getInt("auto_download_while_reading", 0) + fun autoDownloadWhileReading() = this.preferenceStore.getInt("auto_download_while_reading", 0) - fun defaultCategory() = prefs.getInt(Keys.defaultCategory, -1) + fun defaultCategory() = this.preferenceStore.getInt(Keys.defaultCategory, -1) - fun categorizedDisplaySettings() = flowPrefs.getBoolean("categorized_display", false) + fun categorizedDisplaySettings() = this.preferenceStore.getBoolean("categorized_display", false) - fun skipRead() = prefs.getBoolean(Keys.skipRead, false) + fun skipRead() = this.preferenceStore.getBoolean(Keys.skipRead, false) - fun skipFiltered() = prefs.getBoolean(Keys.skipFiltered, true) + fun skipFiltered() = this.preferenceStore.getBoolean(Keys.skipFiltered, true) - fun migrateFlags() = flowPrefs.getInt("migrate_flags", Int.MAX_VALUE) + fun migrateFlags() = this.preferenceStore.getInt("migrate_flags", Int.MAX_VALUE) - fun trustedSignatures() = flowPrefs.getStringSet("trusted_signatures", emptySet()) + fun trustedSignatures() = this.preferenceStore.getStringSet("trusted_signatures", emptySet()) - fun dohProvider() = prefs.getInt(Keys.dohProvider, -1) + fun filterChapterByRead() = this.preferenceStore.getInt(Keys.defaultChapterFilterByRead, DomainManga.SHOW_ALL.toInt()) - fun defaultUserAgent() = flowPrefs.getString(Keys.defaultUserAgent, "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:104.0) Gecko/20100101 Firefox/104.0") + fun filterChapterByDownloaded() = this.preferenceStore.getInt(Keys.defaultChapterFilterByDownloaded, DomainManga.SHOW_ALL.toInt()) - fun filterChapterByRead() = prefs.getInt(Keys.defaultChapterFilterByRead, DomainManga.SHOW_ALL.toInt()) + fun filterChapterByBookmarked() = this.preferenceStore.getInt(Keys.defaultChapterFilterByBookmarked, DomainManga.SHOW_ALL.toInt()) - fun filterChapterByDownloaded() = prefs.getInt(Keys.defaultChapterFilterByDownloaded, DomainManga.SHOW_ALL.toInt()) + fun sortChapterBySourceOrNumber() = this.preferenceStore.getInt(Keys.defaultChapterSortBySourceOrNumber, DomainManga.CHAPTER_SORTING_SOURCE.toInt()) - fun filterChapterByBookmarked() = prefs.getInt(Keys.defaultChapterFilterByBookmarked, DomainManga.SHOW_ALL.toInt()) + fun displayChapterByNameOrNumber() = this.preferenceStore.getInt(Keys.defaultChapterDisplayByNameOrNumber, DomainManga.CHAPTER_DISPLAY_NAME.toInt()) - fun sortChapterBySourceOrNumber() = prefs.getInt(Keys.defaultChapterSortBySourceOrNumber, DomainManga.CHAPTER_SORTING_SOURCE.toInt()) + fun sortChapterByAscendingOrDescending() = this.preferenceStore.getInt(Keys.defaultChapterSortByAscendingOrDescending, DomainManga.CHAPTER_SORT_DESC.toInt()) - fun displayChapterByNameOrNumber() = prefs.getInt(Keys.defaultChapterDisplayByNameOrNumber, DomainManga.CHAPTER_DISPLAY_NAME.toInt()) + fun incognitoMode() = this.preferenceStore.getBoolean("incognito_mode", false) - fun sortChapterByAscendingOrDescending() = prefs.getInt(Keys.defaultChapterSortByAscendingOrDescending, DomainManga.CHAPTER_SORT_DESC.toInt()) + fun tabletUiMode() = this.preferenceStore.getEnum("tablet_ui_mode", Values.TabletUiMode.AUTOMATIC) - fun incognitoMode() = flowPrefs.getBoolean("incognito_mode", false) - - fun tabletUiMode() = flowPrefs.getEnum("tablet_ui_mode", Values.TabletUiMode.AUTOMATIC) - - fun extensionInstaller() = flowPrefs.getEnum( + fun extensionInstaller() = this.preferenceStore.getEnum( "extension_installer", if (DeviceUtil.isMiui) Values.ExtensionInstaller.LEGACY else Values.ExtensionInstaller.PACKAGEINSTALLER, ) - fun verboseLogging() = prefs.getBoolean(Keys.verboseLogging, isDevFlavor) + fun autoClearChapterCache() = this.preferenceStore.getBoolean(Keys.autoClearChapterCache, false) - fun autoClearChapterCache() = prefs.getBoolean(Keys.autoClearChapterCache, false) - - fun duplicatePinnedSources() = flowPrefs.getBoolean("duplicate_pinned_sources", false) + fun duplicatePinnedSources() = this.preferenceStore.getBoolean("duplicate_pinned_sources", false) fun setChapterSettingsDefault(manga: Manga) { - prefs.edit { - putInt(Keys.defaultChapterFilterByRead, manga.readFilter) - putInt(Keys.defaultChapterFilterByDownloaded, manga.downloadedFilter) - putInt(Keys.defaultChapterFilterByBookmarked, manga.bookmarkedFilter) - putInt(Keys.defaultChapterSortBySourceOrNumber, manga.sorting) - putInt(Keys.defaultChapterDisplayByNameOrNumber, manga.displayMode) - putInt(Keys.defaultChapterSortByAscendingOrDescending, if (manga.sortDescending()) DomainManga.CHAPTER_SORT_DESC.toInt() else DomainManga.CHAPTER_SORT_ASC.toInt()) - } + 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/data/track/TrackService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/TrackService.kt index 4bdbfc8517..bc918ca02e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/TrackService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/TrackService.kt @@ -69,9 +69,9 @@ abstract class TrackService(val id: Long) { get() = getUsername().isNotEmpty() && getPassword().isNotEmpty() - fun getUsername() = preferences.trackUsername(this)!! + fun getUsername() = preferences.trackUsername(this).get() - fun getPassword() = preferences.trackPassword(this)!! + fun getPassword() = preferences.trackPassword(this).get() fun saveCredentials(username: String, password: String) { preferences.setTrackCredentials(this, username, password) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/MangaUpdates.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/MangaUpdates.kt index 8c64ba4c82..f64b900881 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/MangaUpdates.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/mangaupdates/MangaUpdates.kt @@ -99,6 +99,6 @@ class MangaUpdates(private val context: Context, id: Long) : TrackService(id) { } fun restoreSession(): String? { - return preferences.trackPassword(this) + return preferences.trackPassword(this).get() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionManager.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionManager.kt index b2a06ed154..53fba35fa5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionManager.kt @@ -193,7 +193,7 @@ class ExtensionManager( .map(AvailableSources::lang) val deviceLanguage = Locale.getDefault().language - val defaultLanguages = preferences.enabledLanguages().defaultValue + val defaultLanguages = preferences.enabledLanguages().defaultValue() val languagesToEnable = availableLanguages.filter { it != deviceLanguage && it.startsWith(deviceLanguage) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/delegate/SecureActivityDelegate.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/delegate/SecureActivityDelegate.kt index 03822c7611..4d3370b5cc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/delegate/SecureActivityDelegate.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/delegate/SecureActivityDelegate.kt @@ -82,8 +82,8 @@ class SecureActivityDelegateImpl : SecureActivityDelegate, DefaultLifecycleObser } private fun setSecureScreen() { - val secureScreenFlow = preferences.secureScreen().asFlow() - val incognitoModeFlow = preferences.incognitoMode().asFlow() + val secureScreenFlow = preferences.secureScreen().changes() + val incognitoModeFlow = preferences.incognitoMode().changes() combine(secureScreenFlow, incognitoModeFlow) { secureScreen, incognitoMode -> secureScreen == PreferenceValues.SecureScreenMode.ALWAYS || secureScreen == PreferenceValues.SecureScreenMode.INCOGNITO && incognitoMode diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/BasePresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/BasePresenter.kt index f1da3b693c..edc2a77525 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/BasePresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/presenter/BasePresenter.kt @@ -1,8 +1,8 @@ package eu.kanade.tachiyomi.ui.base.presenter import android.os.Bundle -import com.fredporciuncula.flow.preferences.Preference import eu.kanade.core.prefs.PreferenceMutableState +import eu.kanade.tachiyomi.core.preference.Preference import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.MainScope import kotlinx.coroutines.cancel diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsPresenter.kt index a4868a703f..acc8bb97d5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionsPresenter.kt @@ -123,7 +123,7 @@ class ExtensionsPresenter( presenterScope.launchIO { findAvailableExtensions() } - preferences.extensionUpdatesCount().asFlow() + preferences.extensionUpdatesCount().changes() .onEach { state.updates = it } .launchIn(presenterScope) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrationSourcesPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrationSourcesPresenter.kt index c8754b43db..b543c24fb5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrationSourcesPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrationSourcesPresenter.kt @@ -42,11 +42,11 @@ class MigrationSourcesPresenter( } } - preferences.migrationSortingDirection().asFlow() + preferences.migrationSortingDirection().changes() .onEach { state.sortingDirection = it } .launchIn(presenterScope) - preferences.migrationSortingMode().asFlow() + preferences.migrationSortingMode().changes() .onEach { state.sortingMode = it } .launchIn(presenterScope) } 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 e53bd91487..84a6d68914 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 @@ -111,7 +111,7 @@ open class BrowseSourcePresenter( val isLandscape = LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE return produceState(initialValue = GridCells.Adaptive(128.dp), isLandscape) { (if (isLandscape) preferences.landscapeColumns() else preferences.portraitColumns()) - .asFlow() + .changes() .collectLatest { columns -> value = if (columns == 0) GridCells.Adaptive(128.dp) else GridCells.Fixed(columns) } @@ -257,7 +257,7 @@ open class BrowseSourcePresenter( fun addFavorite(manga: DomainManga) { presenterScope.launch { val categories = getCategories() - val defaultCategoryId = preferences.defaultCategory() + val defaultCategoryId = preferences.defaultCategory().get() val defaultCategory = categories.find { it.id == defaultCategoryId.toLong() } when { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchController.kt index ca27c6f2b9..d400fe072c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchController.kt @@ -174,7 +174,7 @@ open class GlobalSearchController( * @param searchResult result of search. */ fun setItems(searchResult: List) { - if (searchResult.isEmpty() && preferences.searchPinnedSourcesOnly()) { + if (searchResult.isEmpty() && preferences.searchPinnedSourcesOnly().get()) { binding.emptyView.show(R.string.no_pinned_sources) } else { binding.emptyView.hide() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt index 65ae912132..7b2ba18a09 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt @@ -123,7 +123,7 @@ open class GlobalSearchPresenter( return filteredSources } - val onlyPinnedSources = preferences.searchPinnedSourcesOnly() + val onlyPinnedSources = preferences.searchPinnedSourcesOnly().get() val pinnedSourceIds = preferences.pinnedSources().get() return enabledSources diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/setting/LibraryDisplayMode.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/setting/LibraryDisplayMode.kt index 5f5b0b15ba..bcb0d7bd5f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/setting/LibraryDisplayMode.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/setting/LibraryDisplayMode.kt @@ -1,7 +1,6 @@ package eu.kanade.tachiyomi.ui.library.setting import eu.kanade.domain.category.model.Category -import com.fredporciuncula.flow.preferences.Serializer as PreferencesSerializer sealed class LibraryDisplayMode( override val flag: Long, @@ -14,12 +13,12 @@ sealed class LibraryDisplayMode( object List : LibraryDisplayMode(0b00000010) object CoverOnlyGrid : LibraryDisplayMode(0b00000011) - object Serializer : PreferencesSerializer { - override fun deserialize(serialized: String): LibraryDisplayMode { + object Serializer { + fun deserialize(serialized: String): LibraryDisplayMode { return LibraryDisplayMode.deserialize(serialized) } - override fun serialize(value: LibraryDisplayMode): String { + fun serialize(value: LibraryDisplayMode): String { return value.serialize() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/setting/LibrarySort.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/setting/LibrarySort.kt index 1eb81d5c05..dd54bd9993 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/setting/LibrarySort.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/setting/LibrarySort.kt @@ -1,7 +1,6 @@ package eu.kanade.tachiyomi.ui.library.setting import eu.kanade.domain.category.model.Category -import com.fredporciuncula.flow.preferences.Serializer as PreferencesSerializer data class LibrarySort( val type: Type, @@ -57,12 +56,12 @@ data class LibrarySort( } } - object Serializer : PreferencesSerializer { - override fun deserialize(serialized: String): LibrarySort { + object Serializer { + fun deserialize(serialized: String): LibrarySort { return LibrarySort.deserialize(serialized) } - override fun serialize(value: LibrarySort): String { + fun serialize(value: LibrarySort): String { return value.serialize() } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index 66d95ae033..d7909e248e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -72,6 +72,8 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.merge import kotlinx.coroutines.flow.onEach import logcat.LogPriority +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy class MainActivity : BaseActivity() { @@ -105,7 +107,15 @@ class MainActivity : BaseActivity() { super.onCreate(savedInstanceState) - val didMigration = if (savedInstanceState == null) Migrations.upgrade(preferences) else false + val didMigration = if (savedInstanceState == null) { + Migrations.upgrade( + context = applicationContext, + preferences = preferences, + networkPreferences = Injekt.get(), + ) + } else { + false + } binding = MainActivityBinding.inflate(layoutInflater) @@ -240,7 +250,7 @@ class MainActivity : BaseActivity() { } } - merge(preferences.showUpdatesNavBadge().asFlow(), preferences.unreadUpdatesCount().asFlow()) + merge(preferences.showUpdatesNavBadge().changes(), preferences.unreadUpdatesCount().changes()) .onEach { setUnreadUpdatesBadge() } .launchIn(lifecycleScope) @@ -253,7 +263,7 @@ class MainActivity : BaseActivity() { .launchIn(lifecycleScope) binding.incognitoMode.isVisible = preferences.incognitoMode().get() - preferences.incognitoMode().asFlow() + preferences.incognitoMode().changes() .drop(1) .onEach { binding.incognitoMode.isVisible = it @@ -490,7 +500,7 @@ class MainActivity : BaseActivity() { lifecycleScope.launchUI { resetExitConfirmation() } } else if (backstackSize == 1 || !router.handleBack()) { // Regular back (i.e. closing the app) - if (preferences.autoClearChapterCache()) { + if (preferences.autoClearChapterCache().get()) { chapterCache.clear() } super.onBackPressed() @@ -534,7 +544,7 @@ class MainActivity : BaseActivity() { private fun shouldHandleExitConfirmation(): Boolean { return router.backstackSize == 1 && router.getControllerWithTag("$startScreenId") != null && - preferences.confirmExit() && + preferences.confirmExit().get() && !isConfirmingExit } 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 14ba887032..fea2c52d58 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 @@ -283,7 +283,7 @@ class MangaPresenter( // Now check if user previously set categories, when available val categories = getCategories() - val defaultCategoryId = preferences.defaultCategory().toLong() + val defaultCategoryId = preferences.defaultCategory().get().toLong() val defaultCategory = categories.find { it.id == defaultCategoryId } when { // Default category set diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt index d993104ed5..3d39f020fd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt @@ -194,7 +194,7 @@ class ReaderActivity : BaseRxActivity() { initializeMenu() // Finish when incognito mode is disabled - preferences.incognitoMode().asFlow() + preferences.incognitoMode().changes() .drop(1) .onEach { if (!it) finish() } .launchIn(lifecycleScope) @@ -446,7 +446,7 @@ class ReaderActivity : BaseRxActivity() { presenter.setMangaReadingMode(newReadingMode.flagValue) menuToggleToast?.cancel() - if (!preferences.showReadingMode()) { + if (!preferences.showReadingMode().get()) { menuToggleToast = toast(newReadingMode.stringRes) } @@ -480,7 +480,7 @@ class ReaderActivity : BaseRxActivity() { updateCropBordersShortcut() listOf(preferences.cropBorders(), preferences.cropBordersWebtoon()) .forEach { pref -> - pref.asFlow() + pref.changes() .onEach { updateCropBordersShortcut() } .launchIn(lifecycleScope) } @@ -493,7 +493,7 @@ class ReaderActivity : BaseRxActivity() { popupMenu( items = OrientationType.values().map { it.flagValue to it.stringRes }, selectedItemId = presenter.manga?.orientationType - ?: preferences.defaultOrientationType(), + ?: preferences.defaultOrientationType().get(), ) { val newOrientation = OrientationType.fromPreference(itemId) @@ -635,7 +635,7 @@ class ReaderActivity : BaseRxActivity() { updateViewerInset(preferences.fullscreen().get()) binding.viewerContainer.addView(newViewer.getView()) - if (preferences.showReadingMode()) { + if (preferences.showReadingMode().get()) { showReadingModeToast(presenter.getMangaReadingMode()) } @@ -949,7 +949,7 @@ class ReaderActivity : BaseRxActivity() { * Initializes the reader subscriptions. */ init { - preferences.readerTheme().asFlow() + preferences.readerTheme().changes() .onEach { binding.readerContainer.setBackgroundResource( when (preferences.readerTheme().get()) { @@ -962,41 +962,41 @@ class ReaderActivity : BaseRxActivity() { } .launchIn(lifecycleScope) - preferences.showPageNumber().asFlow() + preferences.showPageNumber().changes() .onEach { setPageNumberVisibility(it) } .launchIn(lifecycleScope) - preferences.trueColor().asFlow() + preferences.trueColor().changes() .onEach { setTrueColor(it) } .launchIn(lifecycleScope) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - preferences.cutoutShort().asFlow() + preferences.cutoutShort().changes() .onEach { setCutoutShort(it) } .launchIn(lifecycleScope) } - preferences.keepScreenOn().asFlow() + preferences.keepScreenOn().changes() .onEach { setKeepScreenOn(it) } .launchIn(lifecycleScope) - preferences.customBrightness().asFlow() + preferences.customBrightness().changes() .onEach { setCustomBrightness(it) } .launchIn(lifecycleScope) - preferences.colorFilter().asFlow() + preferences.colorFilter().changes() .onEach { setColorFilter(it) } .launchIn(lifecycleScope) - preferences.colorFilterMode().asFlow() + preferences.colorFilterMode().changes() .onEach { setColorFilter(preferences.colorFilter().get()) } .launchIn(lifecycleScope) - merge(preferences.grayscale().asFlow(), preferences.invertedColors().asFlow()) + merge(preferences.grayscale().changes(), preferences.invertedColors().changes()) .onEach { setLayerPaint(preferences.grayscale().get(), preferences.invertedColors().get()) } .launchIn(lifecycleScope) - preferences.fullscreen().asFlow() + preferences.fullscreen().changes() .onEach { WindowCompat.setDecorFitsSystemWindows(window, !it) updateViewerInset(it) @@ -1060,7 +1060,7 @@ class ReaderActivity : BaseRxActivity() { */ private fun setCustomBrightness(enabled: Boolean) { if (enabled) { - preferences.customBrightnessValue().asFlow() + preferences.customBrightnessValue().changes() .sample(100) .onEach { setCustomBrightnessValue(it) } .launchIn(lifecycleScope) @@ -1074,7 +1074,7 @@ class ReaderActivity : BaseRxActivity() { */ private fun setColorFilter(enabled: Boolean) { if (enabled) { - preferences.colorFilterValue().asFlow() + preferences.colorFilterValue().changes() .sample(100) .onEach { setColorFilterValue(it) } .launchIn(lifecycleScope) 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 88d4235180..e9e2e33dd6 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 @@ -140,11 +140,11 @@ class ReaderPresenter( ?: error("Requested chapter of id $chapterId not found in chapter list") val chaptersForReader = when { - (preferences.skipRead() || preferences.skipFiltered()) -> { + (preferences.skipRead().get() || preferences.skipFiltered().get()) -> { val filteredChapters = chapters.filterNot { when { - preferences.skipRead() && it.read -> true - preferences.skipFiltered() -> { + preferences.skipRead().get() && it.read -> true + preferences.skipFiltered().get() -> { (manga.readFilter == DomainManga.CHAPTER_SHOW_READ.toInt() && !it.read) || (manga.readFilter == DomainManga.CHAPTER_SHOW_UNREAD.toInt() && it.read) || (manga.downloadedFilter == DomainManga.CHAPTER_SHOW_DOWNLOADED.toInt() && !downloadManager.isChapterDownloaded(it.name, it.scanlator, manga.title, manga.source)) || @@ -502,7 +502,7 @@ class ReaderPresenter( private fun deleteChapterIfNeeded(currentChapter: ReaderChapter) { // Determine which chapter should be deleted and enqueue val currentChapterPosition = chapterList.indexOf(currentChapter) - val removeAfterReadSlots = preferences.removeAfterReadSlots() + val removeAfterReadSlots = preferences.removeAfterReadSlots().get() val chapterToDelete = chapterList.getOrNull(currentChapterPosition - removeAfterReadSlots) if (removeAfterReadSlots != 0 && chapterDownload != null) { @@ -619,7 +619,7 @@ class ReaderPresenter( * Returns the viewer position used by this manga or the default one. */ fun getMangaReadingMode(resolveDefault: Boolean = true): Int { - val default = preferences.defaultReadingMode() + val default = preferences.defaultReadingMode().get() val readingMode = ReadingModeType.fromPreference(manga?.readingModeType) return when { resolveDefault && readingMode == ReadingModeType.DEFAULT -> default @@ -656,7 +656,7 @@ class ReaderPresenter( * Returns the orientation type used by this manga or the default one. */ fun getMangaOrientationType(resolveDefault: Boolean = true): Int { - val default = preferences.defaultOrientationType() + val default = preferences.defaultOrientationType().get() val orientation = OrientationType.fromPreference(manga?.orientationType) return when { resolveDefault && orientation == OrientationType.DEFAULT -> default @@ -714,7 +714,7 @@ class ReaderPresenter( val filename = generateFilename(manga, page) // Pictures directory. - val relativePath = if (preferences.folderPerManga()) DiskUtil.buildValidFilename(manga.title) else "" + val relativePath = if (preferences.folderPerManga().get()) DiskUtil.buildValidFilename(manga.title) else "" // Copy file in background. try { @@ -818,7 +818,7 @@ class ReaderPresenter( * will run in a background thread and errors are ignored. */ private fun updateTrackChapterRead(readerChapter: ReaderChapter) { - if (!preferences.autoUpdateTrack()) return + if (!preferences.autoUpdateTrack().get()) return val manga = manga ?: return val chapterRead = readerChapter.chapter.chapter_number.toDouble() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderColorFilterSettings.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderColorFilterSettings.kt index 37396e1b07..40b0ef5f0e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderColorFilterSettings.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderColorFilterSettings.kt @@ -32,15 +32,15 @@ class ReaderColorFilterSettings @JvmOverloads constructor(context: Context, attr init { addView(binding.root) - preferences.colorFilter().asFlow() + preferences.colorFilter().changes() .onEach { setColorFilter(it) } .launchIn((context as ReaderActivity).lifecycleScope) - preferences.colorFilterMode().asFlow() + preferences.colorFilterMode().changes() .onEach { setColorFilter(preferences.colorFilter().get()) } .launchIn(context.lifecycleScope) - preferences.customBrightness().asFlow() + preferences.customBrightness().changes() .onEach { setCustomBrightness(it) } .launchIn(context.lifecycleScope) @@ -139,7 +139,7 @@ class ReaderColorFilterSettings @JvmOverloads constructor(context: Context, attr */ private fun setCustomBrightness(enabled: Boolean) { if (enabled) { - preferences.customBrightnessValue().asFlow() + preferences.customBrightnessValue().changes() .sample(100) .onEach { setCustomBrightnessValue(it) } .launchIn((context as ReaderActivity).lifecycleScope) @@ -167,7 +167,7 @@ class ReaderColorFilterSettings @JvmOverloads constructor(context: Context, attr */ private fun setColorFilter(enabled: Boolean) { if (enabled) { - preferences.colorFilterValue().asFlow() + preferences.colorFilterValue().changes() .sample(100) .onEach { setColorFilterValue(it) } .launchIn((context as ReaderActivity).lifecycleScope) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerConfig.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerConfig.kt index 42c594b006..e62cb33266 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerConfig.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ViewerConfig.kt @@ -1,6 +1,6 @@ package eu.kanade.tachiyomi.ui.reader.viewer -import com.fredporciuncula.flow.preferences.Preference +import eu.kanade.tachiyomi.core.preference.Preference import eu.kanade.tachiyomi.data.preference.PreferenceValues.TappingInvertMode import eu.kanade.tachiyomi.data.preference.PreferencesHelper import kotlinx.coroutines.CoroutineScope @@ -80,7 +80,7 @@ abstract class ViewerConfig(preferences: PreferencesHelper, private val scope: C valueAssignment: (T) -> Unit, onChanged: (T) -> Unit = {}, ) { - asFlow() + changes() .onEach { valueAssignment(it) } .distinctUntilChanged() .onEach { onChanged(it) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerConfig.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerConfig.kt index 0ad374363c..d5c0179417 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerConfig.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerConfig.kt @@ -78,7 +78,7 @@ class PagerConfig( preferences.pagerNavInverted() .register({ tappingInverted = it }, { navigator.invertMode = it }) - preferences.pagerNavInverted().asFlow() + preferences.pagerNavInverted().changes() .drop(1) .onEach { navigationModeChangedListener?.invoke() } .launchIn(scope) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonConfig.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonConfig.kt index 07964b8f97..87032a1d91 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonConfig.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonConfig.kt @@ -51,7 +51,7 @@ class WebtoonConfig( preferences.webtoonNavInverted() .register({ tappingInverted = it }, { navigator.invertMode = it }) - preferences.webtoonNavInverted().asFlow() + preferences.webtoonNavInverted().changes() .drop(1) .onEach { navigationModeChangedListener?.invoke() } .launchIn(scope) @@ -71,7 +71,7 @@ class WebtoonConfig( }, ) - preferences.readerTheme().asFlow() + preferences.readerTheme().changes() .drop(1) .distinctUntilChanged() .onEach { themeChangedListener?.invoke() } 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 240d79a284..c7a33480c4 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 @@ -17,6 +17,7 @@ import eu.kanade.tachiyomi.data.library.LibraryUpdateService.Target import eu.kanade.tachiyomi.data.preference.PreferenceValues import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.network.NetworkHelper +import eu.kanade.tachiyomi.network.NetworkPreferences import eu.kanade.tachiyomi.network.PREF_DOH_360 import eu.kanade.tachiyomi.network.PREF_DOH_ADGUARD import eu.kanade.tachiyomi.network.PREF_DOH_ALIDNS @@ -69,6 +70,7 @@ class SettingsAdvancedController( private val network: NetworkHelper by injectLazy() private val chapterCache: ChapterCache by injectLazy() private val trackManager: TrackManager by injectLazy() + private val networkPreferences: NetworkPreferences by injectLazy() @SuppressLint("BatteryLife") override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply { @@ -96,7 +98,7 @@ class SettingsAdvancedController( } switchPreference { - key = Keys.verboseLogging + key = networkPreferences.verboseLogging().key() titleRes = R.string.pref_verbose_logging summaryRes = R.string.pref_verbose_logging_summary defaultValue = isDevFlavor @@ -189,7 +191,7 @@ class SettingsAdvancedController( onClick { clearWebViewData() } } intListPreference { - key = Keys.dohProvider + key = networkPreferences.dohProvider().key() titleRes = R.string.pref_dns_over_https entries = arrayOf( context.getString(R.string.disabled), @@ -227,10 +229,11 @@ class SettingsAdvancedController( true } } + val defaultUserAgent = networkPreferences.defaultUserAgent() editTextPreference { - key = Keys.defaultUserAgent + key = defaultUserAgent.key() titleRes = R.string.pref_user_agent_string - text = preferences.defaultUserAgent().get() + text = defaultUserAgent.get() summary = network.defaultUserAgent onChange { @@ -247,10 +250,10 @@ class SettingsAdvancedController( key = "pref_reset_user_agent" titleRes = R.string.pref_reset_user_agent_string - visibleIf(preferences.defaultUserAgent()) { it != preferences.defaultUserAgent().defaultValue } + visibleIf(defaultUserAgent) { it != defaultUserAgent.defaultValue() } onClick { - preferences.defaultUserAgent().delete() + defaultUserAgent.delete() activity?.toast(R.string.requires_app_restart) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt index 3c5fa434fb..788cc9ea8b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt @@ -136,7 +136,7 @@ class SettingsBackupController : SettingsController() { } } - preferences.backupsDirectory().asFlow() + preferences.backupsDirectory().changes() .onEach { path -> val dir = UniFile.fromUri(context, path.toUri()) summary = dir.filePath + "/automatic" diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsController.kt index 24c4ed648e..a2e20a57d5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsController.kt @@ -130,7 +130,7 @@ abstract class SettingsController : PreferenceController() { (activity as? AppCompatActivity)?.supportActionBar?.title = getTitle() } - inline fun Preference.visibleIf(preference: com.fredporciuncula.flow.preferences.Preference, crossinline block: (T) -> Boolean) { + inline fun Preference.visibleIf(preference: eu.kanade.tachiyomi.core.preference.Preference, crossinline block: (T) -> Boolean) { preference.asHotFlow { isVisible = block(it) } .launchIn(viewScope) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt index c0b7ad20fc..fcf6ae3685 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt @@ -58,7 +58,7 @@ class SettingsDownloadController : SettingsController() { ctrl.showDialog(router) } - preferences.downloadsDirectory().asFlow() + preferences.downloadsDirectory().changes() .onEach { path -> val dir = UniFile.fromUri(context, path.toUri()) summary = dir.filePath ?: path @@ -114,7 +114,7 @@ class SettingsDownloadController : SettingsController() { entries = categories.map { it.visualName(context) }.toTypedArray() entryValues = categories.map { it.id.toString() }.toTypedArray() - preferences.removeExcludeCategories().asFlow() + preferences.removeExcludeCategories().changes() .onEach { mutable -> val selected = mutable .mapNotNull { id -> categories.find { it.id == id.toLong() } } @@ -171,10 +171,10 @@ class SettingsDownloadController : SettingsController() { } } - preferences.downloadNewChapterCategories().asFlow() + preferences.downloadNewChapterCategories().changes() .onEach { updateSummary() } .launchIn(viewScope) - preferences.downloadNewChapterCategoriesExclude().asFlow() + preferences.downloadNewChapterCategoriesExclude().changes() .onEach { updateSummary() } .launchIn(viewScope) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt index 18c12b85ad..eb9e87d550 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt @@ -79,7 +79,7 @@ class SettingsLibraryController : SettingsController() { } } - combine(preferences.portraitColumns().asFlow(), preferences.landscapeColumns().asFlow()) { portraitCols, landscapeCols -> Pair(portraitCols, landscapeCols) } + combine(preferences.portraitColumns().changes(), preferences.landscapeColumns().changes()) { portraitCols, landscapeCols -> Pair(portraitCols, landscapeCols) } .onEach { (portraitCols, landscapeCols) -> val portrait = getColumnValue(portraitCols) val landscape = getColumnValue(landscapeCols) @@ -114,7 +114,7 @@ class SettingsLibraryController : SettingsController() { entryValues = arrayOf("-1") + allCategories.map { it.id.toString() }.toTypedArray() defaultValue = "-1" - val selectedCategory = allCategories.find { it.id == preferences.defaultCategory().toLong() } + val selectedCategory = allCategories.find { it.id == preferences.defaultCategory().get().toLong() } summary = selectedCategory?.visualName(context) ?: context.getString(R.string.default_category_summary) onChange { newValue -> @@ -129,7 +129,7 @@ class SettingsLibraryController : SettingsController() { bindTo(preferences.categorizedDisplaySettings()) titleRes = R.string.categorized_display_settings - preferences.categorizedDisplaySettings().asFlow() + preferences.categorizedDisplaySettings().changes() .onEach { if (it.not()) { resetCategoryFlags.await() @@ -197,7 +197,7 @@ class SettingsLibraryController : SettingsController() { summary = context.getString(R.string.restrictions, restrictionsText) } - preferences.libraryUpdateDeviceRestriction().asFlow() + preferences.libraryUpdateDeviceRestriction().changes() .onEach { updateSummary() } .launchIn(viewScope) } @@ -226,7 +226,7 @@ class SettingsLibraryController : SettingsController() { summary = restrictionsText } - preferences.libraryUpdateMangaRestriction().asFlow() + preferences.libraryUpdateMangaRestriction().changes() .onEach { updateSummary() } .launchIn(viewScope) } @@ -269,10 +269,10 @@ class SettingsLibraryController : SettingsController() { } } - preferences.libraryUpdateCategories().asFlow() + preferences.libraryUpdateCategories().changes() .onEach { updateSummary() } .launchIn(viewScope) - preferences.libraryUpdateCategoriesExclude().asFlow() + preferences.libraryUpdateCategoriesExclude().changes() .onEach { updateSummary() } .launchIn(viewScope) } 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 index dbef6ab2fb..134c388c59 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSettingsHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSettingsHelper.kt @@ -27,12 +27,12 @@ object ChapterSettingsHelper { suspend fun applySettingDefaults(mangaId: Long) { setMangaChapterFlags.awaitSetAllFlags( mangaId = mangaId, - unreadFilter = preferences.filterChapterByRead().toLong(), - downloadedFilter = preferences.filterChapterByDownloaded().toLong(), - bookmarkedFilter = preferences.filterChapterByBookmarked().toLong(), - sortingMode = preferences.sortChapterBySourceOrNumber().toLong(), - sortingDirection = preferences.sortChapterByAscendingOrDescending().toLong(), - displayMode = preferences.displayChapterByNameOrNumber().toLong(), + 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(), ) } @@ -45,12 +45,12 @@ object ChapterSettingsHelper { .map { manga -> setMangaChapterFlags.awaitSetAllFlags( mangaId = manga.id, - unreadFilter = preferences.filterChapterByRead().toLong(), - downloadedFilter = preferences.filterChapterByDownloaded().toLong(), - bookmarkedFilter = preferences.filterChapterByBookmarked().toLong(), - sortingMode = preferences.sortChapterBySourceOrNumber().toLong(), - sortingDirection = preferences.sortChapterByAscendingOrDescending().toLong(), - displayMode = preferences.displayChapterByNameOrNumber().toLong(), + 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/app/src/main/java/eu/kanade/tachiyomi/util/preference/PreferenceDSL.kt b/app/src/main/java/eu/kanade/tachiyomi/util/preference/PreferenceDSL.kt index 7ecd1ae8b8..d8f9b1f2b5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/preference/PreferenceDSL.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/preference/PreferenceDSL.kt @@ -106,15 +106,14 @@ inline fun

PreferenceGroup.addThenInit(p: P, block: P.() -> Uni } } -inline fun Preference.bindTo(preference: com.fredporciuncula.flow.preferences.Preference) { - key = preference.key - defaultValue = preference.defaultValue +inline fun Preference.bindTo(preference: eu.kanade.tachiyomi.core.preference.Preference) { + key = preference.key() + defaultValue = preference.defaultValue() } -inline fun ListPreference.bindTo(preference: com.fredporciuncula.flow.preferences.Preference) { - key = preference.key - // ListPreferences persist values as strings, even when we're using our IntListPreference - defaultValue = preference.defaultValue.toString() +inline fun ListPreference.bindTo(preference: eu.kanade.tachiyomi.core.preference.Preference) { + key = preference.key() + defaultValue = preference.defaultValue().toString() } inline fun Preference.onClick(crossinline block: () -> Unit) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/preference/PreferenceExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/preference/PreferenceExtensions.kt index 1c7db68e07..213c94f274 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/preference/PreferenceExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/preference/PreferenceExtensions.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.util.preference import android.widget.CompoundButton -import com.fredporciuncula.flow.preferences.Preference +import eu.kanade.tachiyomi.core.preference.Preference import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.onEach @@ -15,7 +15,7 @@ fun CompoundButton.bindToPreference(pref: Preference) { fun Preference.asHotFlow(block: (T) -> Unit): Flow { block(get()) - return asFlow() + return changes() .onEach { block(it) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/MaterialSpinnerView.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/MaterialSpinnerView.kt index f294fe5cd8..38d0218723 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/MaterialSpinnerView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/MaterialSpinnerView.kt @@ -14,8 +14,8 @@ import androidx.appcompat.widget.PopupMenu import androidx.core.content.withStyledAttributes import androidx.core.view.forEach import androidx.core.view.get -import com.fredporciuncula.flow.preferences.Preference import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.core.preference.Preference import eu.kanade.tachiyomi.databinding.PrefSpinnerBinding import eu.kanade.tachiyomi.util.system.getResourceColor diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiSearchView.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiSearchView.kt index aa5e6705f3..5c77eca76a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiSearchView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiSearchView.kt @@ -31,13 +31,15 @@ class TachiyomiSearchView @JvmOverloads constructor( override fun onAttachedToWindow() { super.onAttachedToWindow() scope = CoroutineScope(SupervisorJob() + Dispatchers.Main) - Injekt.get().incognitoMode().asHotFlow { - imeOptions = if (it) { - imeOptions or EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING - } else { - imeOptions and EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING.inv() + Injekt.get().incognitoMode() + .asHotFlow { + imeOptions = if (it) { + imeOptions or EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING + } else { + imeOptions and EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING.inv() + } } - }.launchIn(scope!!) + .launchIn(scope!!) } override fun setOnQueryTextListener(listener: OnQueryTextListener?) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiTextInputEditText.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiTextInputEditText.kt index 7951062db7..4c227efd01 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiTextInputEditText.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiTextInputEditText.kt @@ -49,13 +49,15 @@ class TachiyomiTextInputEditText @JvmOverloads constructor( * if [PreferencesHelper.incognitoMode] is true. Some IMEs may not respect this flag. */ fun EditText.setIncognito(viewScope: CoroutineScope) { - Injekt.get().incognitoMode().asHotFlow { - imeOptions = if (it) { - imeOptions or EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING - } else { - imeOptions and EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING.inv() + Injekt.get().incognitoMode() + .asHotFlow { + imeOptions = if (it) { + imeOptions or EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING + } else { + imeOptions and EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING.inv() + } } - }.launchIn(viewScope) + .launchIn(viewScope) } } } diff --git a/core/src/main/java/eu/kanade/tachiyomi/core/preference/AndroidPreference.kt b/core/src/main/java/eu/kanade/tachiyomi/core/preference/AndroidPreference.kt new file mode 100644 index 0000000000..4c2e6c0f5f --- /dev/null +++ b/core/src/main/java/eu/kanade/tachiyomi/core/preference/AndroidPreference.kt @@ -0,0 +1,178 @@ +package eu.kanade.tachiyomi.core.preference + +import android.content.SharedPreferences +import android.content.SharedPreferences.Editor +import androidx.core.content.edit +import eu.kanade.tachiyomi.util.system.logcat +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.SharingStarted +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.conflate +import kotlinx.coroutines.flow.filter +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.onStart +import kotlinx.coroutines.flow.stateIn + +sealed class AndroidPreference( + private val preferences: SharedPreferences, + private val keyFlow: Flow, + private val key: String, + private val defaultValue: T, +) : Preference { + + abstract fun read(preferences: SharedPreferences, key: String, defaultValue: T): T + + abstract fun write(key: String, value: T): Editor.() -> Unit + + override fun key(): String { + return key + } + + override fun get(): T { + return read(preferences, key, defaultValue) + } + + override fun set(value: T) { + preferences.edit(action = write(key, value)) + } + + override fun isSet(): Boolean { + return preferences.contains(key) + } + + override fun delete() { + preferences.edit { + remove(key) + } + } + + override fun defaultValue(): T { + return defaultValue + } + + override fun changes(): Flow { + return keyFlow + .filter { it == key || it == null } + .onStart { emit("ignition") } + .map { get() } + .conflate() + } + + override fun stateIn(scope: CoroutineScope): StateFlow { + return changes().stateIn(scope, SharingStarted.Eagerly, get()) + } + + class StringPrimitive( + preferences: SharedPreferences, + keyFlow: Flow, + key: String, + defaultValue: String + ) : AndroidPreference(preferences, keyFlow, key, defaultValue) { + override fun read(preferences: SharedPreferences, key: String, defaultValue: String): String { + return preferences.getString(key, defaultValue) ?: defaultValue + } + + override fun write(key: String, value: String): Editor.() -> Unit = { + putString(key, value) + } + } + + class LongPrimitive( + preferences: SharedPreferences, + keyFlow: Flow, + key: String, + defaultValue: Long + ) : AndroidPreference(preferences, keyFlow, key, defaultValue) { + override fun read(preferences: SharedPreferences, key: String, defaultValue: Long): Long { + return preferences.getLong(key, defaultValue) + } + + override fun write(key: String, value: Long): Editor.() -> Unit = { + putLong(key, value) + } + } + + class IntPrimitive( + preferences: SharedPreferences, + keyFlow: Flow, + key: String, + defaultValue: Int + ) : AndroidPreference(preferences, keyFlow, key, defaultValue) { + override fun read(preferences: SharedPreferences, key: String, defaultValue: Int): Int { + return preferences.getInt(key, defaultValue) + } + + override fun write(key: String, value: Int): Editor.() -> Unit = { + putInt(key, value) + } + } + + class FloatPrimitive( + preferences: SharedPreferences, + keyFlow: Flow, + key: String, + defaultValue: Float + ) : AndroidPreference(preferences, keyFlow, key, defaultValue) { + override fun read(preferences: SharedPreferences, key: String, defaultValue: Float): Float { + return preferences.getFloat(key, defaultValue) + } + + override fun write(key: String, value: Float): Editor.() -> Unit = { + putFloat(key, value) + } + } + + class BooleanPrimitive( + preferences: SharedPreferences, + keyFlow: Flow, + key: String, + defaultValue: Boolean + ) : AndroidPreference(preferences, keyFlow, key, defaultValue) { + override fun read(preferences: SharedPreferences, key: String, defaultValue: Boolean): Boolean { + return preferences.getBoolean(key, defaultValue) + } + + override fun write(key: String, value: Boolean): Editor.() -> Unit = { + putBoolean(key, value) + } + } + + class StringSetPrimitive( + preferences: SharedPreferences, + keyFlow: Flow, + key: String, + defaultValue: Set + ) : AndroidPreference>(preferences, keyFlow, key, defaultValue) { + override fun read(preferences: SharedPreferences, key: String, defaultValue: Set): Set { + return preferences.getStringSet(key, defaultValue) ?: defaultValue + } + + override fun write(key: String, value: Set): Editor.() -> Unit = { + putStringSet(key, value) + } + } + + class Object( + preferences: SharedPreferences, + keyFlow: Flow, + key: String, + defaultValue: T, + val serializer: (T) -> String, + val deserializer: (String) -> T + ) : AndroidPreference(preferences, keyFlow, key, defaultValue) { + override fun read(preferences: SharedPreferences, key: String, defaultValue: T): T { + return try { + preferences.getString(key, null)?.let(deserializer) ?: defaultValue + } catch (e: Exception) { + defaultValue + } + } + + override fun write(key: String, value: T): Editor.() -> Unit = { + putString(key, serializer(value)) + } + } + +} diff --git a/core/src/main/java/eu/kanade/tachiyomi/core/preference/AndroidPreferenceStore.kt b/core/src/main/java/eu/kanade/tachiyomi/core/preference/AndroidPreferenceStore.kt new file mode 100644 index 0000000000..49fa9d7144 --- /dev/null +++ b/core/src/main/java/eu/kanade/tachiyomi/core/preference/AndroidPreferenceStore.kt @@ -0,0 +1,72 @@ +package eu.kanade.tachiyomi.core.preference + +import android.content.Context +import android.content.SharedPreferences +import androidx.preference.PreferenceManager +import eu.kanade.tachiyomi.core.preference.AndroidPreference.BooleanPrimitive +import eu.kanade.tachiyomi.core.preference.AndroidPreference.FloatPrimitive +import eu.kanade.tachiyomi.core.preference.AndroidPreference.IntPrimitive +import eu.kanade.tachiyomi.core.preference.AndroidPreference.LongPrimitive +import eu.kanade.tachiyomi.core.preference.AndroidPreference.Object +import eu.kanade.tachiyomi.core.preference.AndroidPreference.StringPrimitive +import eu.kanade.tachiyomi.core.preference.AndroidPreference.StringSetPrimitive +import kotlinx.coroutines.channels.awaitClose +import kotlinx.coroutines.flow.callbackFlow + +class AndroidPreferenceStore( + context: Context +) : PreferenceStore { + + private val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context) + + private val keyFlow = sharedPreferences.keyFlow + + override fun getString(key: String, defaultValue: String): Preference { + return StringPrimitive(sharedPreferences, keyFlow, key, defaultValue) + } + + override fun getLong(key: String, defaultValue: Long): Preference { + return LongPrimitive(sharedPreferences, keyFlow,key, defaultValue) + } + + override fun getInt(key: String, defaultValue: Int): Preference { + return IntPrimitive(sharedPreferences, keyFlow,key, defaultValue) + } + + override fun getFloat(key: String, defaultValue: Float): Preference { + return FloatPrimitive(sharedPreferences, keyFlow,key, defaultValue) + } + + override fun getBoolean(key: String, defaultValue: Boolean): Preference { + return BooleanPrimitive(sharedPreferences, keyFlow, key, defaultValue) + } + + override fun getStringSet(key: String, defaultValue: Set): Preference> { + return StringSetPrimitive(sharedPreferences, keyFlow, key, defaultValue) + } + + override fun getObject( + key: String, + defaultValue: T, + serializer: (T) -> String, + deserializer: (String) -> T, + ): Preference { + return Object( + preferences = sharedPreferences, + keyFlow = keyFlow, + key = key, + defaultValue = defaultValue, + serializer = serializer, + deserializer = deserializer + ) +} +} + +private val SharedPreferences.keyFlow + get() = callbackFlow { + val listener = SharedPreferences.OnSharedPreferenceChangeListener { _, key: String? -> trySend(key) } + registerOnSharedPreferenceChangeListener(listener) + awaitClose { + unregisterOnSharedPreferenceChangeListener(listener) + } + } diff --git a/core/src/main/java/eu/kanade/tachiyomi/core/preference/Preference.kt b/core/src/main/java/eu/kanade/tachiyomi/core/preference/Preference.kt new file mode 100644 index 0000000000..a88bbc51a0 --- /dev/null +++ b/core/src/main/java/eu/kanade/tachiyomi/core/preference/Preference.kt @@ -0,0 +1,27 @@ +package eu.kanade.tachiyomi.core.preference + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.StateFlow + +interface Preference { + + fun key(): String + + fun get(): T + + fun set(value: T) + + fun isSet(): Boolean + + fun delete() + + fun defaultValue(): T + + fun changes(): Flow + + fun stateIn(scope: CoroutineScope): StateFlow + +} + +inline fun Preference.getAndSet(crossinline block: (T) -> R) = set(block(get())) diff --git a/core/src/main/java/eu/kanade/tachiyomi/core/preference/PreferenceStore.kt b/core/src/main/java/eu/kanade/tachiyomi/core/preference/PreferenceStore.kt new file mode 100644 index 0000000000..374368c7d0 --- /dev/null +++ b/core/src/main/java/eu/kanade/tachiyomi/core/preference/PreferenceStore.kt @@ -0,0 +1,42 @@ +package eu.kanade.tachiyomi.core.preference + +interface PreferenceStore { + + fun getString(key: String, defaultValue: String = ""): Preference + + fun getLong(key: String, defaultValue: Long = 0): Preference + + fun getInt(key: String, defaultValue: Int = 0): Preference + + fun getFloat(key: String, defaultValue: Float = 0f): Preference + + fun getBoolean(key: String, defaultValue: Boolean = false): Preference + + fun getStringSet(key: String, defaultValue: Set = emptySet()): Preference> + + fun getObject( + key: String, + defaultValue: T, + serializer: (T) -> String, + deserializer: (String) -> T + ): Preference + +} + +inline fun > PreferenceStore.getEnum( + key: String, + defaultValue: T +) : Preference { + return getObject( + key = key, + defaultValue = defaultValue, + serializer = { it.name }, + deserializer = { + try { + enumValueOf(it) + } catch (e: IllegalArgumentException) { + defaultValue + } + } + ) +} diff --git a/core/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt b/core/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt index 84b4039534..3c69671ccc 100644 --- a/core/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt +++ b/core/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt @@ -8,13 +8,13 @@ import eu.kanade.tachiyomi.network.interceptor.UserAgentInterceptor import okhttp3.Cache import okhttp3.OkHttpClient import okhttp3.logging.HttpLoggingInterceptor +import uy.kohesive.injekt.injectLazy import java.io.File import java.util.concurrent.TimeUnit class NetworkHelper(context: Context) { - // TODO: Abstract preferences similar to 1.x - private val preferences = PreferenceManager.getDefaultSharedPreferences(context) + private val preferences: NetworkPreferences by injectLazy() private val cacheDir = File(context.cacheDir, "network_cache") private val cacheSize = 5L * 1024 * 1024 // 5 MiB @@ -36,14 +36,14 @@ class NetworkHelper(context: Context) { .addInterceptor(userAgentInterceptor) .addNetworkInterceptor(http103Interceptor) - if (preferences.getBoolean("verbose_logging", false)) { + if (preferences.verboseLogging().get()) { val httpLoggingInterceptor = HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.HEADERS } builder.addNetworkInterceptor(httpLoggingInterceptor) } - when (preferences.getInt("doh_provider", -1)) { + when (preferences.dohProvider().get()) { PREF_DOH_CLOUDFLARE -> builder.dohCloudflare() PREF_DOH_GOOGLE -> builder.dohGoogle() PREF_DOH_ADGUARD -> builder.dohAdGuard() @@ -70,6 +70,6 @@ class NetworkHelper(context: Context) { } val defaultUserAgent by lazy { - preferences.getString("default_user_agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:104.0) Gecko/20100101 Firefox/104.0")!! + preferences.defaultUserAgent().get() } } diff --git a/core/src/main/java/eu/kanade/tachiyomi/network/NetworkPreferences.kt b/core/src/main/java/eu/kanade/tachiyomi/network/NetworkPreferences.kt new file mode 100644 index 0000000000..37d92a5a69 --- /dev/null +++ b/core/src/main/java/eu/kanade/tachiyomi/network/NetworkPreferences.kt @@ -0,0 +1,23 @@ +package eu.kanade.tachiyomi.network + +import eu.kanade.tachiyomi.core.preference.Preference +import eu.kanade.tachiyomi.core.preference.PreferenceStore + +class NetworkPreferences( + private val preferenceStore: PreferenceStore, + private val verboseLogging: Boolean = false +) { + + fun verboseLogging(): Preference { + return preferenceStore.getBoolean("verbose_logging", verboseLogging) + } + + fun dohProvider(): Preference { + return preferenceStore.getInt("doh_provider", -1) + } + + fun defaultUserAgent(): Preference { + return preferenceStore.getString("default_user_agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:104.0) Gecko/20100101 Firefox/104.0") + } + +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 791b18e326..9ea3e57870 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -37,7 +37,6 @@ sqlitektx = "androidx.sqlite:sqlite-ktx:2.3.0-alpha05" sqlite-android = "com.github.requery:sqlite-android:3.36.0" preferencektx = "androidx.preference:preference-ktx:1.2.0" -flowpreferences = "com.fredporciuncula:flow-preferences:1.8.0" nucleus-core = { module = "info.android15.nucleus:nucleus", version.ref = "nucleus_version" } nucleus-supportv7 = { module = "info.android15.nucleus:nucleus-support-v7", version.ref = "nucleus_version" }