mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 14:27:57 +01:00 
			
		
		
		
	Use 1.x preference abstraction (#8020)
* Use 1.x preference abstraction - Uses SharedPreferences compared to 1.x impl which uses DataStore but it breaks all settings screens currently - Move PreferencesHelper to new PreferenceStore - PreferencesHelper should be split into smaller preference stores and be in core or domain - Remove flow preferences as new PreferenceStore handles changes for us Co-authored-by: inorichi <3521738+inorichi@users.noreply.github.com> * Fix PreferenceMutableState not updating * Fix changes not emitting on first subscription Co-authored-by: inorichi <3521738+inorichi@users.noreply.github.com>
This commit is contained in:
		| @@ -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<T>( | ||||
|     private val state = mutableStateOf(preference.get()) | ||||
|  | ||||
|     init { | ||||
|         preference.asFlow() | ||||
|             .distinctUntilChanged() | ||||
|         preference.changes() | ||||
|             .onEach { state.value = it } | ||||
|             .launchIn(scope) | ||||
|     } | ||||
|   | ||||
| @@ -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, | ||||
|   | ||||
| @@ -12,7 +12,7 @@ class GetExtensionLanguages( | ||||
| ) { | ||||
|     fun subscribe(): Flow<List<String>> { | ||||
|         return combine( | ||||
|             preferences.enabledLanguages().asFlow(), | ||||
|             preferences.enabledLanguages().changes(), | ||||
|             extensionManager.getAvailableExtensionsFlow(), | ||||
|         ) { enabledLanguage, availableExtensions -> | ||||
|             availableExtensions | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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(), | ||||
|   | ||||
| @@ -17,10 +17,10 @@ class GetEnabledSources( | ||||
|  | ||||
|     fun subscribe(): Flow<List<Source>> { | ||||
|         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() | ||||
|   | ||||
| @@ -14,8 +14,8 @@ class GetLanguagesWithSources( | ||||
|  | ||||
|     fun subscribe(): Flow<Map<String, List<Source>>> { | ||||
|         return combine( | ||||
|             preferences.enabledLanguages().asFlow(), | ||||
|             preferences.disabledSources().asFlow(), | ||||
|             preferences.enabledLanguages().changes(), | ||||
|             preferences.disabledSources().changes(), | ||||
|             repository.getOnlineSources(), | ||||
|         ) { enabledLanguage, disabledSource, onlineSources -> | ||||
|             val sortedSources = onlineSources.sortedWith( | ||||
|   | ||||
| @@ -16,8 +16,8 @@ class GetSourcesWithFavoriteCount( | ||||
|  | ||||
|     fun subscribe(): Flow<List<Pair<Source, Long>>> { | ||||
|         return combine( | ||||
|             preferences.migrationSortingDirection().asFlow(), | ||||
|             preferences.migrationSortingMode().asFlow(), | ||||
|             preferences.migrationSortingDirection().changes(), | ||||
|             preferences.migrationSortingMode().changes(), | ||||
|             repository.getSourcesWithFavoriteCount(), | ||||
|         ) { direction, mode, list -> | ||||
|             list.sortedWith(sortFn(direction, mode)) | ||||
|   | ||||
| @@ -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) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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") | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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}") | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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<ActivityManager>()!!.isLowRamDevice) | ||||
|             if (preferences.verboseLogging()) logger(DebugLogger()) | ||||
|             if (networkPreferences.verboseLogging().get()) logger(DebugLogger()) | ||||
|         }.build() | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -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<PreferencesHelper>() | ||||
|  | ||||
|             get<NetworkHelper>() | ||||
|  | ||||
|             get<SourceManager>() | ||||
| @@ -118,3 +118,23 @@ class AppModule(val app: Application) : InjektModule { | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| class PreferenceModule(val application: Application) : InjektModule { | ||||
|     override fun InjektRegistrar.registerInjectables() { | ||||
|         addSingletonFactory<PreferenceStore> { | ||||
|             AndroidPreferenceStore(application) | ||||
|         } | ||||
|         addSingletonFactory { | ||||
|             NetworkPreferences( | ||||
|                 preferenceStore = get(), | ||||
|                 verboseLogging = isDevFlavor, | ||||
|             ) | ||||
|         } | ||||
|         addSingletonFactory { | ||||
|             PreferencesHelper( | ||||
|                 context = application, | ||||
|                 preferenceStore = get(), | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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") | ||||
|                     } | ||||
|                 } | ||||
|   | ||||
| @@ -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) | ||||
|             } | ||||
|  | ||||
|   | ||||
| @@ -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()) | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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) | ||||
|     } | ||||
|   | ||||
| @@ -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() | ||||
|   | ||||
| @@ -71,7 +71,7 @@ class LibraryUpdateNotifier(private val context: Context) { | ||||
|      * @param total the total progress. | ||||
|      */ | ||||
|     fun showProgressNotification(manga: List<Manga>, 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)) | ||||
|   | ||||
| @@ -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) | ||||
|         } | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
| @@ -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()) | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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() | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -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) | ||||
|         } | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -123,7 +123,7 @@ class ExtensionsPresenter( | ||||
|  | ||||
|         presenterScope.launchIO { findAvailableExtensions() } | ||||
|  | ||||
|         preferences.extensionUpdatesCount().asFlow() | ||||
|         preferences.extensionUpdatesCount().changes() | ||||
|             .onEach { state.updates = it } | ||||
|             .launchIn(presenterScope) | ||||
|     } | ||||
|   | ||||
| @@ -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) | ||||
|     } | ||||
|   | ||||
| @@ -111,7 +111,7 @@ open class BrowseSourcePresenter( | ||||
|         val isLandscape = LocalConfiguration.current.orientation == Configuration.ORIENTATION_LANDSCAPE | ||||
|         return produceState<GridCells>(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 { | ||||
|   | ||||
| @@ -174,7 +174,7 @@ open class GlobalSearchController( | ||||
|      * @param searchResult result of search. | ||||
|      */ | ||||
|     fun setItems(searchResult: List<GlobalSearchItem>) { | ||||
|         if (searchResult.isEmpty() && preferences.searchPinnedSourcesOnly()) { | ||||
|         if (searchResult.isEmpty() && preferences.searchPinnedSourcesOnly().get()) { | ||||
|             binding.emptyView.show(R.string.no_pinned_sources) | ||||
|         } else { | ||||
|             binding.emptyView.hide() | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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<LibraryDisplayMode> { | ||||
|         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() | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -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<LibrarySort> { | ||||
|         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() | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -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 | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -194,7 +194,7 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>() { | ||||
|         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<ReaderPresenter>() { | ||||
|                     presenter.setMangaReadingMode(newReadingMode.flagValue) | ||||
|  | ||||
|                     menuToggleToast?.cancel() | ||||
|                     if (!preferences.showReadingMode()) { | ||||
|                     if (!preferences.showReadingMode().get()) { | ||||
|                         menuToggleToast = toast(newReadingMode.stringRes) | ||||
|                     } | ||||
|  | ||||
| @@ -480,7 +480,7 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>() { | ||||
|         updateCropBordersShortcut() | ||||
|         listOf(preferences.cropBorders(), preferences.cropBordersWebtoon()) | ||||
|             .forEach { pref -> | ||||
|                 pref.asFlow() | ||||
|                 pref.changes() | ||||
|                     .onEach { updateCropBordersShortcut() } | ||||
|                     .launchIn(lifecycleScope) | ||||
|             } | ||||
| @@ -493,7 +493,7 @@ class ReaderActivity : BaseRxActivity<ReaderPresenter>() { | ||||
|                 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<ReaderPresenter>() { | ||||
|         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<ReaderPresenter>() { | ||||
|          * 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<ReaderPresenter>() { | ||||
|                 } | ||||
|                 .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<ReaderPresenter>() { | ||||
|          */ | ||||
|         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<ReaderPresenter>() { | ||||
|          */ | ||||
|         private fun setColorFilter(enabled: Boolean) { | ||||
|             if (enabled) { | ||||
|                 preferences.colorFilterValue().asFlow() | ||||
|                 preferences.colorFilterValue().changes() | ||||
|                     .sample(100) | ||||
|                     .onEach { setColorFilterValue(it) } | ||||
|                     .launchIn(lifecycleScope) | ||||
|   | ||||
| @@ -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() | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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) } | ||||
|   | ||||
| @@ -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) | ||||
|   | ||||
| @@ -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() } | ||||
|   | ||||
| @@ -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) | ||||
|                 } | ||||
|             } | ||||
|   | ||||
| @@ -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" | ||||
|   | ||||
| @@ -130,7 +130,7 @@ abstract class SettingsController : PreferenceController() { | ||||
|         (activity as? AppCompatActivity)?.supportActionBar?.title = getTitle() | ||||
|     } | ||||
|  | ||||
|     inline fun <T> Preference.visibleIf(preference: com.fredporciuncula.flow.preferences.Preference<T>, crossinline block: (T) -> Boolean) { | ||||
|     inline fun <T> Preference.visibleIf(preference: eu.kanade.tachiyomi.core.preference.Preference<T>, crossinline block: (T) -> Boolean) { | ||||
|         preference.asHotFlow { isVisible = block(it) } | ||||
|             .launchIn(viewScope) | ||||
|     } | ||||
|   | ||||
| @@ -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) | ||||
|             } | ||||
|   | ||||
| @@ -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) | ||||
|             } | ||||
|   | ||||
| @@ -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(), | ||||
|                     ) | ||||
|                 } | ||||
|         } | ||||
|   | ||||
| @@ -106,15 +106,14 @@ inline fun <P : Preference> PreferenceGroup.addThenInit(p: P, block: P.() -> Uni | ||||
|     } | ||||
| } | ||||
|  | ||||
| inline fun <T> Preference.bindTo(preference: com.fredporciuncula.flow.preferences.Preference<T>) { | ||||
|     key = preference.key | ||||
|     defaultValue = preference.defaultValue | ||||
| inline fun <T> Preference.bindTo(preference: eu.kanade.tachiyomi.core.preference.Preference<T>) { | ||||
|     key = preference.key() | ||||
|     defaultValue = preference.defaultValue() | ||||
| } | ||||
|  | ||||
| inline fun <T> ListPreference.bindTo(preference: com.fredporciuncula.flow.preferences.Preference<T>) { | ||||
|     key = preference.key | ||||
|     // ListPreferences persist values as strings, even when we're using our IntListPreference | ||||
|     defaultValue = preference.defaultValue.toString() | ||||
| inline fun <T> ListPreference.bindTo(preference: eu.kanade.tachiyomi.core.preference.Preference<T>) { | ||||
|     key = preference.key() | ||||
|     defaultValue = preference.defaultValue().toString() | ||||
| } | ||||
|  | ||||
| inline fun Preference.onClick(crossinline block: () -> Unit) { | ||||
|   | ||||
| @@ -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<Boolean>) { | ||||
|  | ||||
| fun <T> Preference<T>.asHotFlow(block: (T) -> Unit): Flow<T> { | ||||
|     block(get()) | ||||
|     return asFlow() | ||||
|     return changes() | ||||
|         .onEach { block(it) } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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 | ||||
|  | ||||
|   | ||||
| @@ -31,13 +31,15 @@ class TachiyomiSearchView @JvmOverloads constructor( | ||||
|     override fun onAttachedToWindow() { | ||||
|         super.onAttachedToWindow() | ||||
|         scope = CoroutineScope(SupervisorJob() + Dispatchers.Main) | ||||
|         Injekt.get<PreferencesHelper>().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<PreferencesHelper>().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?) { | ||||
|   | ||||
| @@ -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<PreferencesHelper>().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<PreferencesHelper>().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) | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user