Ver Fonte

Split the rest of the preferences in PreferencesHelper (#8074)

* Split the reset of the preferences in PreferencesHelper

* Capitalize ThemeMode
Andreas há 2 anos atrás
pai
commit
29fa93e829
51 ficheiros alterados com 319 adições e 275 exclusões
  1. 1 1
      app/build.gradle.kts
  2. 26 0
      app/src/main/java/eu/kanade/domain/base/BasePreferences.kt
  3. 2 0
      app/src/main/java/eu/kanade/domain/library/service/LibraryPreferences.kt
  4. 2 2
      app/src/main/java/eu/kanade/domain/manga/model/Manga.kt
  5. 45 0
      app/src/main/java/eu/kanade/domain/ui/UiPreferences.kt
  6. 22 0
      app/src/main/java/eu/kanade/domain/ui/model/AppTheme.kt
  7. 10 0
      app/src/main/java/eu/kanade/domain/ui/model/TabletUiMode.kt
  8. 7 0
      app/src/main/java/eu/kanade/domain/ui/model/ThemeMode.kt
  9. 3 3
      app/src/main/java/eu/kanade/presentation/history/components/HistoryContent.kt
  10. 11 9
      app/src/main/java/eu/kanade/tachiyomi/App.kt
  11. 6 5
      app/src/main/java/eu/kanade/tachiyomi/AppModule.kt
  12. 19 6
      app/src/main/java/eu/kanade/tachiyomi/Migrations.kt
  13. 0 9
      app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt
  14. 0 39
      app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceValues.kt
  15. 0 64
      app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt
  16. 2 2
      app/src/main/java/eu/kanade/tachiyomi/data/track/TrackService.kt
  17. 8 4
      app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateChecker.kt
  18. 2 2
      app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionUpdateJob.kt
  19. 8 4
      app/src/main/java/eu/kanade/tachiyomi/extension/api/ExtensionGithubApi.kt
  20. 3 3
      app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstaller.kt
  21. 2 2
      app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt
  22. 2 2
      app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.kt
  23. 2 2
      app/src/main/java/eu/kanade/tachiyomi/ui/base/delegate/SecureActivityDelegate.kt
  24. 15 15
      app/src/main/java/eu/kanade/tachiyomi/ui/base/delegate/ThemingDelegate.kt
  25. 2 2
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowsePresenter.kt
  26. 3 6
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchController.kt
  27. 8 1
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchPresenter.kt
  28. 2 2
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesPresenter.kt
  29. 3 3
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt
  30. 2 2
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchController.kt
  31. 2 2
      app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt
  32. 2 2
      app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt
  33. 2 2
      app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt
  34. 7 3
      app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt
  35. 8 6
      app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt
  36. 3 3
      app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackHolder.kt
  37. 3 3
      app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt
  38. 3 2
      app/src/main/java/eu/kanade/tachiyomi/ui/more/MorePresenter.kt
  39. 2 2
      app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt
  40. 2 2
      app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryPresenter.kt
  41. 9 6
      app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesPresenter.kt
  42. 9 4
      app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt
  43. 20 19
      app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAppearanceController.kt
  44. 2 2
      app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsController.kt
  45. 2 2
      app/src/main/java/eu/kanade/tachiyomi/ui/setting/search/SettingsSearchPresenter.kt
  46. 8 8
      app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt
  47. 3 3
      app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiSearchView.kt
  48. 4 4
      app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiTextInputEditText.kt
  49. 2 2
      app/src/main/java/eu/kanade/tachiyomi/widget/preference/LoginDialogPreference.kt
  50. 2 2
      app/src/main/java/eu/kanade/tachiyomi/widget/preference/ThemesPreference.kt
  51. 6 6
      app/src/main/java/eu/kanade/tachiyomi/widget/preference/ThemesPreferenceAdapter.kt

+ 1 - 1
app/build.gradle.kts

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

+ 26 - 0
app/src/main/java/eu/kanade/domain/base/BasePreferences.kt

@@ -0,0 +1,26 @@
+package eu.kanade.domain.base
+
+import android.content.Context
+import eu.kanade.tachiyomi.core.preference.PreferenceStore
+import eu.kanade.tachiyomi.core.preference.getEnum
+import eu.kanade.tachiyomi.data.preference.PreferenceValues
+import eu.kanade.tachiyomi.util.system.DeviceUtil
+
+class BasePreferences(
+    val context: Context,
+    private val preferenceStore: PreferenceStore,
+) {
+
+    fun confirmExit() = preferenceStore.getBoolean("pref_confirm_exit", false)
+
+    fun downloadedOnly() = preferenceStore.getBoolean("pref_downloaded_only", false)
+
+    fun incognitoMode() = preferenceStore.getBoolean("incognito_mode", false)
+
+    fun automaticExtUpdates() = preferenceStore.getBoolean("automatic_ext_updates", true)
+
+    fun extensionInstaller() = preferenceStore.getEnum(
+        "extension_installer",
+        if (DeviceUtil.isMiui) PreferenceValues.ExtensionInstaller.LEGACY else PreferenceValues.ExtensionInstaller.PACKAGEINSTALLER,
+    )
+}

+ 2 - 0
app/src/main/java/eu/kanade/domain/library/service/LibraryPreferences.kt

@@ -103,5 +103,7 @@ class LibraryPreferences(
         sortChapterByAscendingOrDescending().set(if (manga.sortDescending()) Manga.CHAPTER_SORT_DESC else Manga.CHAPTER_SORT_ASC)
     }
 
+    fun autoClearChapterCache() = preferenceStore.getBoolean("auto_clear_chapter_cache", false)
+
     // endregion
 }

+ 2 - 2
app/src/main/java/eu/kanade/domain/manga/model/Manga.kt

@@ -1,9 +1,9 @@
 package eu.kanade.domain.manga.model
 
 import eu.kanade.data.listOfStringsAdapter
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.tachiyomi.data.cache.CoverCache
 import eu.kanade.tachiyomi.data.database.models.MangaImpl
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.source.LocalSource
 import eu.kanade.tachiyomi.source.model.SManga
 import eu.kanade.tachiyomi.widget.ExtendedNavigationView
@@ -78,7 +78,7 @@ data class Manga(
     }
 
     fun forceDownloaded(): Boolean {
-        return favorite && Injekt.get<PreferencesHelper>().downloadedOnly().get()
+        return favorite && Injekt.get<BasePreferences>().downloadedOnly().get()
     }
 
     fun sortDescending(): Boolean {

+ 45 - 0
app/src/main/java/eu/kanade/domain/ui/UiPreferences.kt

@@ -0,0 +1,45 @@
+package eu.kanade.domain.ui
+
+import android.os.Build
+import eu.kanade.domain.ui.model.AppTheme
+import eu.kanade.domain.ui.model.TabletUiMode
+import eu.kanade.domain.ui.model.ThemeMode
+import eu.kanade.tachiyomi.core.preference.PreferenceStore
+import eu.kanade.tachiyomi.core.preference.getEnum
+import eu.kanade.tachiyomi.util.system.DeviceUtil
+import eu.kanade.tachiyomi.util.system.isDynamicColorAvailable
+import java.text.DateFormat
+import java.text.SimpleDateFormat
+import java.util.Locale
+
+class UiPreferences(
+    private val preferenceStore: PreferenceStore,
+) {
+
+    fun sideNavIconAlignment() = preferenceStore.getInt("pref_side_nav_icon_alignment", 0)
+
+    fun themeMode() = preferenceStore.getEnum(
+        "pref_theme_mode_key",
+        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { ThemeMode.SYSTEM } else { ThemeMode.LIGHT },
+    )
+
+    fun appTheme() = preferenceStore.getEnum(
+        "pref_app_theme",
+        if (DeviceUtil.isDynamicColorAvailable) { AppTheme.MONET } else { AppTheme.DEFAULT },
+    )
+
+    fun themeDarkAmoled() = preferenceStore.getBoolean("pref_theme_dark_amoled_key", false)
+
+    fun relativeTime() = preferenceStore.getInt("relative_time", 7)
+
+    fun dateFormat() = preferenceStore.getString("app_date_format", "")
+
+    fun tabletUiMode() = preferenceStore.getEnum("tablet_ui_mode", TabletUiMode.AUTOMATIC)
+
+    companion object {
+        fun dateFormat(format: String): DateFormat = when (format) {
+            "" -> DateFormat.getDateInstance(DateFormat.SHORT)
+            else -> SimpleDateFormat(format, Locale.getDefault())
+        }
+    }
+}

+ 22 - 0
app/src/main/java/eu/kanade/domain/ui/model/AppTheme.kt

@@ -0,0 +1,22 @@
+package eu.kanade.domain.ui.model
+
+import eu.kanade.tachiyomi.R
+
+enum class AppTheme(val titleResId: Int?) {
+    DEFAULT(R.string.label_default),
+    MONET(R.string.theme_monet),
+    GREEN_APPLE(R.string.theme_greenapple),
+    LAVENDER(R.string.theme_lavender),
+    MIDNIGHT_DUSK(R.string.theme_midnightdusk),
+    STRAWBERRY_DAIQUIRI(R.string.theme_strawberrydaiquiri),
+    TAKO(R.string.theme_tako),
+    TEALTURQUOISE(R.string.theme_tealturquoise),
+    TIDAL_WAVE(R.string.theme_tidalwave),
+    YINYANG(R.string.theme_yinyang),
+    YOTSUBA(R.string.theme_yotsuba),
+
+    // Deprecated
+    DARK_BLUE(null),
+    HOT_PINK(null),
+    BLUE(null),
+}

+ 10 - 0
app/src/main/java/eu/kanade/domain/ui/model/TabletUiMode.kt

@@ -0,0 +1,10 @@
+package eu.kanade.domain.ui.model
+
+import eu.kanade.tachiyomi.R
+
+enum class TabletUiMode(val titleResId: Int) {
+    AUTOMATIC(R.string.automatic_background),
+    ALWAYS(R.string.lock_always),
+    LANDSCAPE(R.string.landscape),
+    NEVER(R.string.lock_never),
+}

+ 7 - 0
app/src/main/java/eu/kanade/domain/ui/model/ThemeMode.kt

@@ -0,0 +1,7 @@
+package eu.kanade.domain.ui.model
+
+enum class ThemeMode {
+    LIGHT,
+    DARK,
+    SYSTEM,
+}

+ 3 - 3
app/src/main/java/eu/kanade/presentation/history/components/HistoryContent.kt

@@ -15,6 +15,7 @@ import androidx.compose.ui.graphics.Brush
 import androidx.paging.compose.LazyPagingItems
 import androidx.paging.compose.items
 import eu.kanade.domain.history.model.HistoryWithRelations
+import eu.kanade.domain.ui.UiPreferences
 import eu.kanade.presentation.components.RelativeDateHeader
 import eu.kanade.presentation.components.ScrollbarLazyColumn
 import eu.kanade.presentation.history.HistoryUiModel
@@ -22,7 +23,6 @@ import eu.kanade.presentation.util.bottomNavPaddingValues
 import eu.kanade.presentation.util.plus
 import eu.kanade.presentation.util.shimmerGradient
 import eu.kanade.presentation.util.topPaddingValues
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
 import java.text.DateFormat
@@ -34,10 +34,10 @@ fun HistoryContent(
     onClickCover: (HistoryWithRelations) -> Unit,
     onClickResume: (HistoryWithRelations) -> Unit,
     onClickDelete: (HistoryWithRelations) -> Unit,
-    preferences: PreferencesHelper = Injekt.get(),
+    preferences: UiPreferences = Injekt.get(),
 ) {
     val relativeTime: Int = remember { preferences.relativeTime().get() }
-    val dateFormat: DateFormat = remember { preferences.dateFormat() }
+    val dateFormat: DateFormat = remember { UiPreferences.dateFormat(preferences.dateFormat().get()) }
 
     ScrollbarLazyColumn(
         contentPadding = contentPadding + bottomNavPaddingValues + topPaddingValues,

+ 11 - 9
app/src/main/java/eu/kanade/tachiyomi/App.kt

@@ -27,14 +27,15 @@ import coil.disk.DiskCache
 import coil.util.DebugLogger
 import eu.kanade.data.DatabaseHandler
 import eu.kanade.domain.DomainModule
+import eu.kanade.domain.base.BasePreferences
+import eu.kanade.domain.ui.UiPreferences
+import eu.kanade.domain.ui.model.ThemeMode
 import eu.kanade.tachiyomi.data.coil.DomainMangaKeyer
 import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
 import eu.kanade.tachiyomi.data.coil.MangaCoverKeyer
 import eu.kanade.tachiyomi.data.coil.MangaKeyer
 import eu.kanade.tachiyomi.data.coil.TachiyomiImageDecoder
 import eu.kanade.tachiyomi.data.notification.Notifications
-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
@@ -63,7 +64,8 @@ import java.security.Security
 
 class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
 
-    private val preferences: PreferencesHelper by injectLazy()
+    private val basePreferences: BasePreferences by injectLazy()
+    private val uiPreferences: UiPreferences by injectLazy()
     private val networkPreferences: NetworkPreferences by injectLazy()
 
     private val disableIncognitoReceiver = DisableIncognitoReceiver()
@@ -93,7 +95,7 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
         ProcessLifecycleOwner.get().lifecycle.addObserver(this)
 
         // Show notification to disable Incognito Mode when it's enabled
-        preferences.incognitoMode().changes()
+        basePreferences.incognitoMode().changes()
             .onEach { enabled ->
                 val notificationManager = NotificationManagerCompat.from(this)
                 if (enabled) {
@@ -120,13 +122,13 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
             }
             .launchIn(ProcessLifecycleOwner.get().lifecycleScope)
 
-        preferences.themeMode()
+        uiPreferences.themeMode()
             .asHotFlow {
                 AppCompatDelegate.setDefaultNightMode(
                     when (it) {
-                        PreferenceValues.ThemeMode.light -> AppCompatDelegate.MODE_NIGHT_NO
-                        PreferenceValues.ThemeMode.dark -> AppCompatDelegate.MODE_NIGHT_YES
-                        PreferenceValues.ThemeMode.system -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
+                        ThemeMode.LIGHT -> AppCompatDelegate.MODE_NIGHT_NO
+                        ThemeMode.DARK -> AppCompatDelegate.MODE_NIGHT_YES
+                        ThemeMode.SYSTEM -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
                     },
                 )
             }.launchIn(ProcessLifecycleOwner.get().lifecycleScope)
@@ -230,7 +232,7 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
         private var registered = false
 
         override fun onReceive(context: Context, intent: Intent) {
-            preferences.incognitoMode().set(false)
+            basePreferences.incognitoMode().set(false)
         }
 
         fun register() {

+ 6 - 5
app/src/main/java/eu/kanade/tachiyomi/AppModule.kt

@@ -14,10 +14,12 @@ import eu.kanade.data.DatabaseHandler
 import eu.kanade.data.dateAdapter
 import eu.kanade.data.listOfStringsAdapter
 import eu.kanade.domain.backup.service.BackupPreferences
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.domain.download.service.DownloadPreferences
 import eu.kanade.domain.library.service.LibraryPreferences
 import eu.kanade.domain.source.service.SourcePreferences
 import eu.kanade.domain.track.service.TrackPreferences
+import eu.kanade.domain.ui.UiPreferences
 import eu.kanade.tachiyomi.core.preference.AndroidPreferenceStore
 import eu.kanade.tachiyomi.core.preference.PreferenceStore
 import eu.kanade.tachiyomi.core.provider.AndroidBackupFolderProvider
@@ -26,7 +28,6 @@ import eu.kanade.tachiyomi.core.security.SecurityPreferences
 import eu.kanade.tachiyomi.data.cache.ChapterCache
 import eu.kanade.tachiyomi.data.cache.CoverCache
 import eu.kanade.tachiyomi.data.download.DownloadManager
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.saver.ImageSaver
 import eu.kanade.tachiyomi.data.track.TrackManager
 import eu.kanade.tachiyomi.data.track.job.DelayedTrackingStore
@@ -182,10 +183,10 @@ class PreferenceModule(val application: Application) : InjektModule {
             )
         }
         addSingletonFactory {
-            PreferencesHelper(
-                context = application,
-                preferenceStore = get(),
-            )
+            UiPreferences(get())
+        }
+        addSingletonFactory {
+            BasePreferences(application, get())
         }
     }
 }

+ 19 - 6
app/src/main/java/eu/kanade/tachiyomi/Migrations.kt

@@ -5,14 +5,16 @@ import android.os.Build
 import androidx.core.content.edit
 import androidx.preference.PreferenceManager
 import eu.kanade.domain.backup.service.BackupPreferences
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.domain.library.service.LibraryPreferences
 import eu.kanade.domain.source.service.SourcePreferences
+import eu.kanade.domain.ui.UiPreferences
+import eu.kanade.tachiyomi.core.preference.PreferenceStore
 import eu.kanade.tachiyomi.core.security.SecurityPreferences
 import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
 import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
 import eu.kanade.tachiyomi.data.preference.MANGA_NON_COMPLETED
 import eu.kanade.tachiyomi.data.preference.PreferenceValues
-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
@@ -39,7 +41,9 @@ object Migrations {
      */
     fun upgrade(
         context: Context,
-        preferences: PreferencesHelper,
+        preferenceStore: PreferenceStore,
+        basePreferences: BasePreferences,
+        uiPreferences: UiPreferences,
         networkPreferences: NetworkPreferences,
         sourcePreferences: SourcePreferences,
         securityPreferences: SecurityPreferences,
@@ -47,9 +51,10 @@ object Migrations {
         readerPreferences: ReaderPreferences,
         backupPreferences: BackupPreferences,
     ): Boolean {
-        val oldVersion = preferences.lastVersionCode().get()
+        val lastVersionCode = preferenceStore.getInt("last_version_code", 0)
+        val oldVersion = lastVersionCode.get()
         if (oldVersion < BuildConfig.VERSION_CODE) {
-            preferences.lastVersionCode().set(BuildConfig.VERSION_CODE)
+            lastVersionCode.set(BuildConfig.VERSION_CODE)
 
             // Always set up background tasks to ensure they're running
             if (BuildConfig.INCLUDE_UPDATER) {
@@ -263,8 +268,8 @@ object Migrations {
                 if (oldSecureScreen) {
                     securityPreferences.secureScreen().set(SecurityPreferences.SecureScreenMode.ALWAYS)
                 }
-                if (DeviceUtil.isMiui && preferences.extensionInstaller().get() == PreferenceValues.ExtensionInstaller.PACKAGEINSTALLER) {
-                    preferences.extensionInstaller().set(PreferenceValues.ExtensionInstaller.LEGACY)
+                if (DeviceUtil.isMiui && basePreferences.extensionInstaller().get() == PreferenceValues.ExtensionInstaller.PACKAGEINSTALLER) {
+                    basePreferences.extensionInstaller().set(PreferenceValues.ExtensionInstaller.LEGACY)
                 }
             }
             if (oldVersion < 76) {
@@ -326,6 +331,14 @@ object Migrations {
                     }
                 }
             }
+            if (oldVersion < 86) {
+                if (uiPreferences.themeMode().isSet()) {
+                    prefs.edit {
+                        val themeMode = prefs.getString(uiPreferences.themeMode().key(), null) ?: return@edit
+                        putString(uiPreferences.themeMode().key(), themeMode.uppercase())
+                    }
+                }
+            }
             return true
         }
 

+ 0 - 9
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt

@@ -1,9 +0,0 @@
-package eu.kanade.tachiyomi.data.preference
-
-/**
- * This class stores the keys for the preferences in the application.
- */
-object PreferenceKeys {
-
-    const val dateFormat = "app_date_format"
-}

+ 0 - 39
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceValues.kt

@@ -16,38 +16,6 @@ const val MANGA_NON_READ = "manga_started"
  */
 object PreferenceValues {
 
-    /* ktlint-disable experimental:enum-entry-name-case */
-
-    // Keys are lowercase to match legacy string values
-    /* ktlint-disable enum-entry-name-case */
-    enum class ThemeMode {
-        light,
-        dark,
-        system,
-    }
-    /* ktlint-enable enum-entry-name-case */
-
-    /* ktlint-enable experimental:enum-entry-name-case */
-
-    enum class AppTheme(val titleResId: Int?) {
-        DEFAULT(R.string.label_default),
-        MONET(R.string.theme_monet),
-        GREEN_APPLE(R.string.theme_greenapple),
-        LAVENDER(R.string.theme_lavender),
-        MIDNIGHT_DUSK(R.string.theme_midnightdusk),
-        STRAWBERRY_DAIQUIRI(R.string.theme_strawberrydaiquiri),
-        TAKO(R.string.theme_tako),
-        TEALTURQUOISE(R.string.theme_tealturquoise),
-        TIDAL_WAVE(R.string.theme_tidalwave),
-        YINYANG(R.string.theme_yinyang),
-        YOTSUBA(R.string.theme_yotsuba),
-
-        // Deprecated
-        DARK_BLUE(null),
-        HOT_PINK(null),
-        BLUE(null),
-    }
-
     enum class TappingInvertMode(val shouldInvertHorizontal: Boolean = false, val shouldInvertVertical: Boolean = false) {
         NONE,
         HORIZONTAL(shouldInvertHorizontal = true),
@@ -62,13 +30,6 @@ object PreferenceValues {
         LOWEST(47),
     }
 
-    enum class TabletUiMode(val titleResId: Int) {
-        AUTOMATIC(R.string.automatic_background),
-        ALWAYS(R.string.lock_always),
-        LANDSCAPE(R.string.landscape),
-        NEVER(R.string.lock_never),
-    }
-
     enum class ExtensionInstaller(val titleResId: Int) {
         LEGACY(R.string.ext_installer_legacy),
         PACKAGEINSTALLER(R.string.ext_installer_packageinstaller),

+ 0 - 64
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt

@@ -1,64 +0,0 @@
-package eu.kanade.tachiyomi.data.preference
-
-import android.content.Context
-import android.os.Build
-import eu.kanade.tachiyomi.core.preference.PreferenceStore
-import eu.kanade.tachiyomi.core.preference.getEnum
-import eu.kanade.tachiyomi.util.system.DeviceUtil
-import eu.kanade.tachiyomi.util.system.isDynamicColorAvailable
-import java.text.DateFormat
-import java.text.SimpleDateFormat
-import java.util.Locale
-import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
-import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values
-
-class PreferencesHelper(
-    val context: Context,
-    private val preferenceStore: PreferenceStore,
-) {
-
-    fun confirmExit() = preferenceStore.getBoolean("pref_confirm_exit", false)
-
-    fun sideNavIconAlignment() = preferenceStore.getInt("pref_side_nav_icon_alignment", 0)
-
-    fun themeMode() = preferenceStore.getEnum(
-        "pref_theme_mode_key",
-        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { Values.ThemeMode.system } else { Values.ThemeMode.light },
-    )
-
-    fun appTheme() = preferenceStore.getEnum(
-        "pref_app_theme",
-        if (DeviceUtil.isDynamicColorAvailable) { Values.AppTheme.MONET } else { Values.AppTheme.DEFAULT },
-    )
-
-    fun themeDarkAmoled() = preferenceStore.getBoolean("pref_theme_dark_amoled_key", false)
-
-    fun lastVersionCode() = preferenceStore.getInt("last_version_code", 0)
-
-    fun relativeTime() = preferenceStore.getInt("relative_time", 7)
-
-    fun dateFormat(format: String = preferenceStore.getString(Keys.dateFormat, "").get()): DateFormat = when (format) {
-        "" -> DateFormat.getDateInstance(DateFormat.SHORT)
-        else -> SimpleDateFormat(format, Locale.getDefault())
-    }
-
-    fun downloadedOnly() = preferenceStore.getBoolean("pref_downloaded_only", false)
-
-    fun automaticExtUpdates() = preferenceStore.getBoolean("automatic_ext_updates", true)
-
-    fun lastAppCheck() = preferenceStore.getLong("last_app_check", 0)
-    fun lastExtCheck() = preferenceStore.getLong("last_ext_check", 0)
-
-    fun migrateFlags() = preferenceStore.getInt("migrate_flags", Int.MAX_VALUE)
-
-    fun incognitoMode() = preferenceStore.getBoolean("incognito_mode", false)
-
-    fun tabletUiMode() = preferenceStore.getEnum("tablet_ui_mode", Values.TabletUiMode.AUTOMATIC)
-
-    fun extensionInstaller() = preferenceStore.getEnum(
-        "extension_installer",
-        if (DeviceUtil.isMiui) Values.ExtensionInstaller.LEGACY else Values.ExtensionInstaller.PACKAGEINSTALLER,
-    )
-
-    fun autoClearChapterCache() = preferenceStore.getBoolean("auto_clear_chapter_cache", false)
-}

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/data/track/TrackService.kt

@@ -4,9 +4,9 @@ import androidx.annotation.CallSuper
 import androidx.annotation.ColorInt
 import androidx.annotation.DrawableRes
 import androidx.annotation.StringRes
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.domain.track.service.TrackPreferences
 import eu.kanade.tachiyomi.data.database.models.Track
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.track.model.TrackSearch
 import eu.kanade.tachiyomi.network.NetworkHelper
 import okhttp3.OkHttpClient
@@ -14,7 +14,7 @@ import uy.kohesive.injekt.injectLazy
 
 abstract class TrackService(val id: Long) {
 
-    val preferences: PreferencesHelper by injectLazy()
+    val preferences: BasePreferences by injectLazy()
     val trackPreferences: TrackPreferences by injectLazy()
     val networkService: NetworkHelper by injectLazy()
 

+ 8 - 4
app/src/main/java/eu/kanade/tachiyomi/data/updater/AppUpdateChecker.kt

@@ -2,7 +2,8 @@ package eu.kanade.tachiyomi.data.updater
 
 import android.content.Context
 import eu.kanade.tachiyomi.BuildConfig
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
+import eu.kanade.tachiyomi.core.preference.Preference
+import eu.kanade.tachiyomi.core.preference.PreferenceStore
 import eu.kanade.tachiyomi.network.GET
 import eu.kanade.tachiyomi.network.NetworkHelper
 import eu.kanade.tachiyomi.network.await
@@ -16,11 +17,14 @@ import java.util.concurrent.TimeUnit
 class AppUpdateChecker {
 
     private val networkService: NetworkHelper by injectLazy()
-    private val preferences: PreferencesHelper by injectLazy()
+    private val preferenceStore: PreferenceStore by injectLazy()
+    private val lastAppCheck: Preference<Long> by lazy {
+        preferenceStore.getLong("last_app_check", 0)
+    }
 
     suspend fun checkForUpdate(context: Context, isUserPrompt: Boolean = false): AppUpdateResult {
         // Limit checks to once a day at most
-        if (isUserPrompt.not() && Date().time < preferences.lastAppCheck().get() + TimeUnit.DAYS.toMillis(1)) {
+        if (isUserPrompt.not() && Date().time < lastAppCheck.get() + TimeUnit.DAYS.toMillis(1)) {
             return AppUpdateResult.NoNewUpdate
         }
 
@@ -30,7 +34,7 @@ class AppUpdateChecker {
                 .await()
                 .parseAs<GithubRelease>()
                 .let {
-                    preferences.lastAppCheck().set(Date().time)
+                    lastAppCheck.set(Date().time)
 
                     // Check if latest version is different from current version
                     if (isNewVersion(it.version)) {

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionUpdateJob.kt

@@ -10,10 +10,10 @@ import androidx.work.NetworkType
 import androidx.work.PeriodicWorkRequestBuilder
 import androidx.work.WorkManager
 import androidx.work.WorkerParameters
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.notification.NotificationReceiver
 import eu.kanade.tachiyomi.data.notification.Notifications
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.extension.api.ExtensionGithubApi
 import eu.kanade.tachiyomi.util.system.logcat
 import eu.kanade.tachiyomi.util.system.notification
@@ -68,7 +68,7 @@ class ExtensionUpdateJob(private val context: Context, workerParams: WorkerParam
         private const val TAG = "ExtensionUpdate"
 
         fun setupTask(context: Context, forceAutoUpdateJob: Boolean? = null) {
-            val preferences = Injekt.get<PreferencesHelper>()
+            val preferences = Injekt.get<BasePreferences>()
             val autoUpdateJob = forceAutoUpdateJob ?: preferences.automaticExtUpdates().get()
             if (autoUpdateJob) {
                 val constraints = Constraints.Builder()

+ 8 - 4
app/src/main/java/eu/kanade/tachiyomi/extension/api/ExtensionGithubApi.kt

@@ -1,7 +1,8 @@
 package eu.kanade.tachiyomi.extension.api
 
 import android.content.Context
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
+import eu.kanade.tachiyomi.core.preference.Preference
+import eu.kanade.tachiyomi.core.preference.PreferenceStore
 import eu.kanade.tachiyomi.extension.ExtensionManager
 import eu.kanade.tachiyomi.extension.model.AvailableSources
 import eu.kanade.tachiyomi.extension.model.Extension
@@ -22,7 +23,10 @@ import java.util.concurrent.TimeUnit
 internal class ExtensionGithubApi {
 
     private val networkService: NetworkHelper by injectLazy()
-    private val preferences: PreferencesHelper by injectLazy()
+    private val preferenceStore: PreferenceStore by injectLazy()
+    private val lastExtCheck: Preference<Long> by lazy {
+        preferenceStore.getLong("last_ext_check", 0)
+    }
     private val extensionManager: ExtensionManager by injectLazy()
 
     private var requiresFallbackSource = false
@@ -65,14 +69,14 @@ internal class ExtensionGithubApi {
 
     suspend fun checkForUpdates(context: Context, fromAvailableExtensionList: Boolean = false): List<Extension.Installed>? {
         // Limit checks to once a day at most
-        if (fromAvailableExtensionList.not() && Date().time < preferences.lastExtCheck().get() + TimeUnit.DAYS.toMillis(1)) {
+        if (fromAvailableExtensionList.not() && Date().time < lastExtCheck.get() + TimeUnit.DAYS.toMillis(1)) {
             return null
         }
 
         val extensions = if (fromAvailableExtensionList) {
             extensionManager.availableExtensions
         } else {
-            findExtensions().also { preferences.lastExtCheck().set(Date().time) }
+            findExtensions().also { lastExtCheck.set(Date().time) }
         }
 
         val installedExtensions = ExtensionLoader.loadExtensions(context)

+ 3 - 3
app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstaller.kt

@@ -11,8 +11,8 @@ import androidx.core.content.ContextCompat
 import androidx.core.content.getSystemService
 import androidx.core.net.toUri
 import com.jakewharton.rxrelay.PublishRelay
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.tachiyomi.data.preference.PreferenceValues
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.extension.installer.Installer
 import eu.kanade.tachiyomi.extension.model.Extension
 import eu.kanade.tachiyomi.extension.model.InstallStep
@@ -54,7 +54,7 @@ internal class ExtensionInstaller(private val context: Context) {
      */
     private val downloadsRelay = PublishRelay.create<Pair<Long, InstallStep>>()
 
-    private val installerPref = Injekt.get<PreferencesHelper>().extensionInstaller()
+    private val extensionInstaller = Injekt.get<BasePreferences>().extensionInstaller()
 
     /**
      * Adds the given extension to the downloads queue and returns an observable containing its
@@ -133,7 +133,7 @@ internal class ExtensionInstaller(private val context: Context) {
      * @param uri The uri of the extension to install.
      */
     fun installApk(downloadId: Long, uri: Uri) {
-        when (val installer = installerPref.get()) {
+        when (val installer = extensionInstaller.get()) {
             PreferenceValues.ExtensionInstaller.LEGACY -> {
                 val intent = Intent(context, ExtensionInstallActivity::class.java)
                     .setDataAndType(uri, APK_MIME)

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt

@@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.base.activity
 import android.content.Context
 import android.os.Bundle
 import androidx.appcompat.app.AppCompatActivity
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.tachiyomi.ui.base.delegate.SecureActivityDelegate
 import eu.kanade.tachiyomi.ui.base.delegate.SecureActivityDelegateImpl
 import eu.kanade.tachiyomi.ui.base.delegate.ThemingDelegate
@@ -16,7 +16,7 @@ open class BaseActivity :
     SecureActivityDelegate by SecureActivityDelegateImpl(),
     ThemingDelegate by ThemingDelegateImpl() {
 
-    protected val preferences: PreferencesHelper by injectLazy()
+    protected val preferences: BasePreferences by injectLazy()
 
     override fun attachBaseContext(newBase: Context) {
         super.attachBaseContext(newBase.prepareTabletUiContext())

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseRxActivity.kt

@@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.base.activity
 
 import android.content.Context
 import android.os.Bundle
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.tachiyomi.ui.base.delegate.SecureActivityDelegate
 import eu.kanade.tachiyomi.ui.base.delegate.SecureActivityDelegateImpl
 import eu.kanade.tachiyomi.ui.base.delegate.ThemingDelegate
@@ -17,7 +17,7 @@ open class BaseRxActivity<P : BasePresenter<*>> :
     SecureActivityDelegate by SecureActivityDelegateImpl(),
     ThemingDelegate by ThemingDelegateImpl() {
 
-    protected val preferences: PreferencesHelper by injectLazy()
+    protected val preferences: BasePreferences by injectLazy()
 
     override fun attachBaseContext(newBase: Context) {
         super.attachBaseContext(newBase.prepareTabletUiContext())

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/base/delegate/SecureActivityDelegate.kt

@@ -5,8 +5,8 @@ import androidx.appcompat.app.AppCompatActivity
 import androidx.lifecycle.DefaultLifecycleObserver
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.lifecycleScope
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.tachiyomi.core.security.SecurityPreferences
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.ui.security.UnlockActivity
 import eu.kanade.tachiyomi.util.system.AuthenticatorUtil
 import eu.kanade.tachiyomi.util.system.AuthenticatorUtil.isAuthenticationSupported
@@ -70,7 +70,7 @@ class SecureActivityDelegateImpl : SecureActivityDelegate, DefaultLifecycleObser
 
     private lateinit var activity: AppCompatActivity
 
-    private val preferences: PreferencesHelper by injectLazy()
+    private val preferences: BasePreferences by injectLazy()
     private val securityPreferences: SecurityPreferences by injectLazy()
 
     override fun registerSecureActivity(activity: AppCompatActivity) {

+ 15 - 15
app/src/main/java/eu/kanade/tachiyomi/ui/base/delegate/ThemingDelegate.kt

@@ -1,9 +1,9 @@
 package eu.kanade.tachiyomi.ui.base.delegate
 
 import android.app.Activity
+import eu.kanade.domain.ui.UiPreferences
+import eu.kanade.domain.ui.model.AppTheme
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.data.preference.PreferenceValues
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
 
@@ -11,37 +11,37 @@ interface ThemingDelegate {
     fun applyAppTheme(activity: Activity)
 
     companion object {
-        fun getThemeResIds(appTheme: PreferenceValues.AppTheme, isAmoled: Boolean): List<Int> {
+        fun getThemeResIds(appTheme: AppTheme, isAmoled: Boolean): List<Int> {
             val resIds = mutableListOf<Int>()
             when (appTheme) {
-                PreferenceValues.AppTheme.MONET -> {
+                AppTheme.MONET -> {
                     resIds += R.style.Theme_Tachiyomi_Monet
                 }
-                PreferenceValues.AppTheme.GREEN_APPLE -> {
+                AppTheme.GREEN_APPLE -> {
                     resIds += R.style.Theme_Tachiyomi_GreenApple
                 }
-                PreferenceValues.AppTheme.LAVENDER -> {
+                AppTheme.LAVENDER -> {
                     resIds += R.style.Theme_Tachiyomi_Lavender
                 }
-                PreferenceValues.AppTheme.MIDNIGHT_DUSK -> {
+                AppTheme.MIDNIGHT_DUSK -> {
                     resIds += R.style.Theme_Tachiyomi_MidnightDusk
                 }
-                PreferenceValues.AppTheme.STRAWBERRY_DAIQUIRI -> {
+                AppTheme.STRAWBERRY_DAIQUIRI -> {
                     resIds += R.style.Theme_Tachiyomi_StrawberryDaiquiri
                 }
-                PreferenceValues.AppTheme.TAKO -> {
+                AppTheme.TAKO -> {
                     resIds += R.style.Theme_Tachiyomi_Tako
                 }
-                PreferenceValues.AppTheme.TEALTURQUOISE -> {
+                AppTheme.TEALTURQUOISE -> {
                     resIds += R.style.Theme_Tachiyomi_TealTurquoise
                 }
-                PreferenceValues.AppTheme.YINYANG -> {
+                AppTheme.YINYANG -> {
                     resIds += R.style.Theme_Tachiyomi_YinYang
                 }
-                PreferenceValues.AppTheme.YOTSUBA -> {
+                AppTheme.YOTSUBA -> {
                     resIds += R.style.Theme_Tachiyomi_Yotsuba
                 }
-                PreferenceValues.AppTheme.TIDAL_WAVE -> {
+                AppTheme.TIDAL_WAVE -> {
                     resIds += R.style.Theme_Tachiyomi_TidalWave
                 }
                 else -> {
@@ -60,8 +60,8 @@ interface ThemingDelegate {
 
 class ThemingDelegateImpl : ThemingDelegate {
     override fun applyAppTheme(activity: Activity) {
-        val preferences = Injekt.get<PreferencesHelper>()
-        ThemingDelegate.getThemeResIds(preferences.appTheme().get(), preferences.themeDarkAmoled().get())
+        val uiPreferences = Injekt.get<UiPreferences>()
+        ThemingDelegate.getThemeResIds(uiPreferences.appTheme().get(), uiPreferences.themeDarkAmoled().get())
             .forEach { activity.setTheme(it) }
     }
 }

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowsePresenter.kt

@@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse
 
 import android.os.Bundle
 import androidx.compose.runtime.getValue
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
 import eu.kanade.tachiyomi.ui.browse.extension.ExtensionsPresenter
 import eu.kanade.tachiyomi.ui.browse.migration.sources.MigrationSourcesPresenter
@@ -11,7 +11,7 @@ import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
 
 class BrowsePresenter(
-    preferences: PreferencesHelper = Injekt.get(),
+    preferences: BasePreferences = Injekt.get(),
 ) : BasePresenter<BrowseController>() {
 
     val isDownloadOnly: Boolean by preferences.downloadedOnly().asState()

+ 3 - 6
app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchController.kt

@@ -9,7 +9,6 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
 import eu.kanade.domain.manga.interactor.GetManga
 import eu.kanade.domain.manga.model.Manga
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.source.CatalogueSource
 import eu.kanade.tachiyomi.ui.base.controller.DialogController
 import eu.kanade.tachiyomi.ui.base.controller.pushController
@@ -21,7 +20,6 @@ import eu.kanade.tachiyomi.util.system.getSerializableCompat
 import kotlinx.coroutines.runBlocking
 import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
-import uy.kohesive.injekt.injectLazy
 
 class SearchController(
     private var manga: Manga? = null,
@@ -101,11 +99,10 @@ class SearchController(
 
     class MigrationDialog(private val manga: Manga? = null, private val newManga: Manga? = null, private val callingController: Controller? = null) : DialogController() {
 
-        private val preferences: PreferencesHelper by injectLazy()
-
         @Suppress("DEPRECATION")
         override fun onCreateDialog(savedViewState: Bundle?): Dialog {
-            val prefValue = preferences.migrateFlags().get()
+            val migrateFlags = ((targetController as SearchController).presenter as SearchPresenter).migrateFlags
+            val prefValue = migrateFlags.get()
             val enabledFlagsPositions = MigrationFlags.getEnabledFlagsPositions(prefValue)
             val items = MigrationFlags.titles(manga)
                 .map { resources?.getString(it) }
@@ -124,7 +121,7 @@ class SearchController(
                     val selectedIndices = mutableListOf<Int>()
                     selected.forEachIndexed { i, b -> if (b) selectedIndices.add(i) }
                     val newValue = MigrationFlags.getFlagsFromPositions(selectedIndices.toTypedArray())
-                    preferences.migrateFlags().set(newValue)
+                    migrateFlags.set(newValue)
 
                     if (callingController != null) {
                         if (callingController.javaClass == SourceSearchController::class.java) {

+ 8 - 1
app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchPresenter.kt

@@ -15,6 +15,8 @@ import eu.kanade.domain.manga.model.hasCustomCover
 import eu.kanade.domain.manga.model.toDbManga
 import eu.kanade.domain.track.interactor.GetTracks
 import eu.kanade.domain.track.interactor.InsertTrack
+import eu.kanade.tachiyomi.core.preference.Preference
+import eu.kanade.tachiyomi.core.preference.PreferenceStore
 import eu.kanade.tachiyomi.data.cache.CoverCache
 import eu.kanade.tachiyomi.data.track.EnhancedTrackService
 import eu.kanade.tachiyomi.data.track.TrackManager
@@ -45,12 +47,17 @@ class SearchPresenter(
     private val getTracks: GetTracks = Injekt.get(),
     private val insertTrack: InsertTrack = Injekt.get(),
     private val setMangaCategories: SetMangaCategories = Injekt.get(),
+    preferenceStore: PreferenceStore = Injekt.get(),
 ) : GlobalSearchPresenter(initialQuery) {
 
     private val replacingMangaRelay = BehaviorRelay.create<Pair<Boolean, Manga?>>()
     private val coverCache: CoverCache by injectLazy()
     private val enhancedServices by lazy { Injekt.get<TrackManager>().services.filterIsInstance<EnhancedTrackService>() }
 
+    val migrateFlags: Preference<Int> by lazy {
+        preferenceStore.getInt("migrate_flags", Int.MAX_VALUE)
+    }
+
     override fun onCreate(savedState: Bundle?) {
         super.onCreate(savedState)
 
@@ -106,7 +113,7 @@ class SearchPresenter(
         manga: Manga,
         replace: Boolean,
     ) {
-        val flags = preferences.migrateFlags().get()
+        val flags = migrateFlags.get()
 
         val migrateChapters = MigrationFlags.hasChapters(flags)
         val migrateCategories = MigrationFlags.hasCategories(flags)

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcesPresenter.kt

@@ -1,5 +1,6 @@
 package eu.kanade.tachiyomi.ui.browse.source
 
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.domain.source.interactor.GetEnabledSources
 import eu.kanade.domain.source.interactor.ToggleSource
 import eu.kanade.domain.source.interactor.ToggleSourcePin
@@ -9,7 +10,6 @@ import eu.kanade.domain.source.service.SourcePreferences
 import eu.kanade.presentation.browse.SourceUiModel
 import eu.kanade.presentation.browse.SourcesState
 import eu.kanade.presentation.browse.SourcesStateImpl
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.util.lang.launchIO
 import eu.kanade.tachiyomi.util.system.logcat
 import kotlinx.coroutines.CoroutineScope
@@ -25,7 +25,7 @@ import java.util.TreeMap
 class SourcesPresenter(
     private val presenterScope: CoroutineScope,
     private val state: SourcesStateImpl = SourcesState() as SourcesStateImpl,
-    private val preferences: PreferencesHelper = Injekt.get(),
+    private val preferences: BasePreferences = Injekt.get(),
     private val sourcePreferences: SourcePreferences = Injekt.get(),
     private val getEnabledSources: GetEnabledSources = Injekt.get(),
     private val toggleSource: ToggleSource = Injekt.get(),

+ 3 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt

@@ -19,6 +19,7 @@ import androidx.paging.map
 import eu.davidea.flexibleadapter.items.IFlexible
 import eu.kanade.core.prefs.CheckboxState
 import eu.kanade.core.prefs.mapAsCheckboxState
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.domain.category.interactor.GetCategories
 import eu.kanade.domain.category.interactor.SetMangaCategories
 import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
@@ -40,7 +41,6 @@ import eu.kanade.presentation.browse.BrowseSourceStateImpl
 import eu.kanade.tachiyomi.data.cache.CoverCache
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.database.models.toDomainManga
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.track.EnhancedTrackService
 import eu.kanade.tachiyomi.data.track.TrackManager
 import eu.kanade.tachiyomi.data.track.TrackService
@@ -87,8 +87,8 @@ open class BrowseSourcePresenter(
     searchQuery: String? = null,
     private val state: BrowseSourceStateImpl = BrowseSourceState(searchQuery) as BrowseSourceStateImpl,
     private val sourceManager: SourceManager = Injekt.get(),
-    private val preferences: PreferencesHelper = Injekt.get(),
-    private val sourcePreferences: SourcePreferences = Injekt.get(),
+    preferences: BasePreferences = Injekt.get(),
+    sourcePreferences: SourcePreferences = Injekt.get(),
     private val libraryPreferences: LibraryPreferences = Injekt.get(),
     private val coverCache: CoverCache = Injekt.get(),
     private val getRemoteManga: GetRemoteManga = Injekt.get(),

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchController.kt

@@ -10,10 +10,10 @@ import androidx.appcompat.widget.SearchView
 import androidx.core.view.isVisible
 import androidx.recyclerview.widget.LinearLayoutManager
 import dev.chrisbanes.insetter.applyInsetter
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.domain.manga.model.Manga
 import eu.kanade.domain.source.service.SourcePreferences
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.databinding.GlobalSearchControllerBinding
 import eu.kanade.tachiyomi.source.CatalogueSource
 import eu.kanade.tachiyomi.ui.base.controller.SearchableNucleusController
@@ -34,7 +34,7 @@ open class GlobalSearchController(
     GlobalSearchCardAdapter.OnMangaClickListener,
     GlobalSearchAdapter.OnTitleClickListener {
 
-    private val preferences: PreferencesHelper by injectLazy()
+    private val preferences: BasePreferences by injectLazy()
     private val sourcePreferences: SourcePreferences by injectLazy()
 
     /**

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt

@@ -1,6 +1,7 @@
 package eu.kanade.tachiyomi.ui.browse.source.globalsearch
 
 import android.os.Bundle
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.domain.manga.interactor.GetManga
 import eu.kanade.domain.manga.interactor.InsertManga
 import eu.kanade.domain.manga.interactor.UpdateManga
@@ -9,7 +10,6 @@ import eu.kanade.domain.manga.model.toMangaUpdate
 import eu.kanade.domain.source.service.SourcePreferences
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.data.database.models.toDomainManga
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.extension.ExtensionManager
 import eu.kanade.tachiyomi.source.CatalogueSource
 import eu.kanade.tachiyomi.source.Source
@@ -35,7 +35,7 @@ open class GlobalSearchPresenter(
     private val initialQuery: String? = "",
     private val initialExtensionFilter: String? = null,
     val sourceManager: SourceManager = Injekt.get(),
-    val preferences: PreferencesHelper = Injekt.get(),
+    val preferences: BasePreferences = Injekt.get(),
     val sourcePreferences: SourcePreferences = Injekt.get(),
     private val getManga: GetManga = Injekt.get(),
     private val insertManga: InsertManga = Injekt.get(),

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt

@@ -16,6 +16,7 @@ import eu.kanade.core.prefs.PreferenceMutableState
 import eu.kanade.core.util.asFlow
 import eu.kanade.core.util.asObservable
 import eu.kanade.data.DatabaseHandler
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.domain.category.interactor.GetCategories
 import eu.kanade.domain.category.interactor.SetMangaCategories
 import eu.kanade.domain.category.model.Category
@@ -40,7 +41,6 @@ import eu.kanade.tachiyomi.data.cache.CoverCache
 import eu.kanade.tachiyomi.data.database.models.LibraryManga
 import eu.kanade.tachiyomi.data.database.models.toDomainManga
 import eu.kanade.tachiyomi.data.download.DownloadManager
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.track.TrackManager
 import eu.kanade.tachiyomi.source.SourceManager
 import eu.kanade.tachiyomi.source.model.SManga
@@ -90,7 +90,7 @@ class LibraryPresenter(
     private val setReadStatus: SetReadStatus = Injekt.get(),
     private val updateManga: UpdateManga = Injekt.get(),
     private val setMangaCategories: SetMangaCategories = Injekt.get(),
-    private val preferences: PreferencesHelper = Injekt.get(),
+    private val preferences: BasePreferences = Injekt.get(),
     private val libraryPreferences: LibraryPreferences = Injekt.get(),
     private val coverCache: CoverCache = Injekt.get(),
     private val sourceManager: SourceManager = Injekt.get(),

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt

@@ -4,6 +4,7 @@ import android.content.Context
 import android.util.AttributeSet
 import android.view.View
 import com.bluelinelabs.conductor.Router
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.domain.category.interactor.SetDisplayModeForCategory
 import eu.kanade.domain.category.interactor.SetSortModeForCategory
 import eu.kanade.domain.category.model.Category
@@ -13,7 +14,6 @@ import eu.kanade.domain.library.model.display
 import eu.kanade.domain.library.model.sort
 import eu.kanade.domain.library.service.LibraryPreferences
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.track.TrackManager
 import eu.kanade.tachiyomi.data.track.TrackService
 import eu.kanade.tachiyomi.util.lang.launchIO
@@ -410,7 +410,7 @@ class LibrarySettingsSheet(
     open inner class Settings(context: Context, attrs: AttributeSet?) :
         ExtendedNavigationView(context, attrs) {
 
-        val preferences: PreferencesHelper by injectLazy()
+        val preferences: BasePreferences by injectLazy()
         val libraryPreferences: LibraryPreferences by injectLazy()
         lateinit var adapter: Adapter
 

+ 7 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt

@@ -33,6 +33,7 @@ import com.google.android.material.transition.platform.MaterialContainerTransfor
 import dev.chrisbanes.insetter.applyInsetter
 import eu.kanade.domain.library.service.LibraryPreferences
 import eu.kanade.domain.source.service.SourcePreferences
+import eu.kanade.domain.ui.UiPreferences
 import eu.kanade.tachiyomi.BuildConfig
 import eu.kanade.tachiyomi.Migrations
 import eu.kanade.tachiyomi.R
@@ -82,6 +83,7 @@ class MainActivity : BaseActivity() {
 
     private val sourcePreferences: SourcePreferences by injectLazy()
     private val libraryPreferences: LibraryPreferences by injectLazy()
+    private val uiPreferences: UiPreferences by injectLazy()
 
     lateinit var binding: MainActivityBinding
 
@@ -115,7 +117,9 @@ class MainActivity : BaseActivity() {
         val didMigration = if (savedInstanceState == null) {
             Migrations.upgrade(
                 context = applicationContext,
-                preferences = preferences,
+                basePreferences = preferences,
+                uiPreferences = uiPreferences,
+                preferenceStore = Injekt.get(),
                 networkPreferences = Injekt.get(),
                 sourcePreferences = sourcePreferences,
                 securityPreferences = Injekt.get(),
@@ -154,7 +158,7 @@ class MainActivity : BaseActivity() {
         setSplashScreenExitAnimation(splashScreen)
 
         if (binding.sideNav != null) {
-            preferences.sideNavIconAlignment()
+            uiPreferences.sideNavIconAlignment()
                 .asHotFlow {
                     binding.sideNav?.menuGravity = when (it) {
                         1 -> Gravity.CENTER
@@ -510,7 +514,7 @@ class MainActivity : BaseActivity() {
             lifecycleScope.launchUI { resetExitConfirmation() }
         } else if (backstackSize == 1 || !router.handleBack()) {
             // Regular back (i.e. closing the app)
-            if (preferences.autoClearChapterCache().get()) {
+            if (libraryPreferences.autoClearChapterCache().get()) {
                 chapterCache.clear()
             }
             super.onBackPressed()

+ 8 - 6
app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt

@@ -6,6 +6,7 @@ import android.os.Bundle
 import androidx.compose.runtime.Immutable
 import eu.kanade.core.prefs.CheckboxState
 import eu.kanade.core.prefs.mapAsCheckboxState
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.domain.category.interactor.GetCategories
 import eu.kanade.domain.category.interactor.SetMangaCategories
 import eu.kanade.domain.category.model.Category
@@ -30,11 +31,11 @@ import eu.kanade.domain.track.interactor.GetTracks
 import eu.kanade.domain.track.interactor.InsertTrack
 import eu.kanade.domain.track.model.toDbTrack
 import eu.kanade.domain.track.model.toDomainTrack
+import eu.kanade.domain.ui.UiPreferences
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.database.models.Track
 import eu.kanade.tachiyomi.data.download.DownloadManager
 import eu.kanade.tachiyomi.data.download.model.Download
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.track.EnhancedTrackService
 import eu.kanade.tachiyomi.data.track.TrackManager
 import eu.kanade.tachiyomi.data.track.TrackService
@@ -82,7 +83,8 @@ import eu.kanade.domain.manga.model.Manga as DomainManga
 class MangaPresenter(
     val mangaId: Long,
     val isFromSource: Boolean,
-    private val preferences: PreferencesHelper = Injekt.get(),
+    private val basePreferences: BasePreferences = Injekt.get(),
+    private val uiPreferences: UiPreferences = Injekt.get(),
     private val downloadPreferences: DownloadPreferences = Injekt.get(),
     private val libraryPreferences: LibraryPreferences = Injekt.get(),
     private val trackManager: TrackManager = Injekt.get(),
@@ -189,8 +191,8 @@ class MangaPresenter(
                     val chapterItems = chapters.toChapterItems(
                         context = view?.activity ?: Injekt.get<Application>(),
                         manga = manga,
-                        dateRelativeTime = preferences.relativeTime().get(),
-                        dateFormat = preferences.dateFormat(),
+                        dateRelativeTime = uiPreferences.relativeTime().get(),
+                        dateFormat = UiPreferences.dateFormat(uiPreferences.dateFormat().get()),
                     )
                     updateSuccessState {
                         it.copy(
@@ -213,11 +215,11 @@ class MangaPresenter(
                 }
         }
 
-        preferences.incognitoMode()
+        basePreferences.incognitoMode()
             .asHotFlow { incognitoMode = it }
             .launchIn(presenterScope)
 
-        preferences.downloadedOnly()
+        basePreferences.downloadedOnly()
             .asHotFlow { downloadedOnlyMode = it }
             .launchIn(presenterScope)
     }

+ 3 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackHolder.kt

@@ -3,8 +3,8 @@ package eu.kanade.tachiyomi.ui.manga.track
 import android.annotation.SuppressLint
 import androidx.core.view.isVisible
 import androidx.recyclerview.widget.RecyclerView
+import eu.kanade.domain.ui.UiPreferences
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.databinding.TrackItemBinding
 import eu.kanade.tachiyomi.util.view.popupMenu
 import uy.kohesive.injekt.injectLazy
@@ -12,10 +12,10 @@ import java.text.DateFormat
 
 class TrackHolder(private val binding: TrackItemBinding, adapter: TrackAdapter) : RecyclerView.ViewHolder(binding.root) {
 
-    private val preferences: PreferencesHelper by injectLazy()
+    private val preferences: UiPreferences by injectLazy()
 
     private val dateFormat: DateFormat by lazy {
-        preferences.dateFormat()
+        UiPreferences.dateFormat(preferences.dateFormat().get())
     }
 
     private val listener = adapter.rowClickListener

+ 3 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt

@@ -1,10 +1,10 @@
 package eu.kanade.tachiyomi.ui.more
 
 import androidx.compose.runtime.Composable
+import eu.kanade.domain.ui.UiPreferences
 import eu.kanade.presentation.more.about.AboutScreen
 import eu.kanade.tachiyomi.BuildConfig
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.updater.AppUpdateChecker
 import eu.kanade.tachiyomi.data.updater.AppUpdateResult
 import eu.kanade.tachiyomi.ui.base.controller.BasicFullComposeController
@@ -23,7 +23,7 @@ import java.util.TimeZone
 
 class AboutController : BasicFullComposeController() {
 
-    private val preferences: PreferencesHelper by injectLazy()
+    private val preferences: UiPreferences by injectLazy()
     private val updateChecker by lazy { AppUpdateChecker() }
 
     @Composable
@@ -78,7 +78,7 @@ class AboutController : BasicFullComposeController() {
             )
             outputDf.timeZone = TimeZone.getDefault()
 
-            buildTime!!.toDateTimestampString(preferences.dateFormat())
+            buildTime!!.toDateTimestampString(UiPreferences.dateFormat(preferences.dateFormat().get()))
         } catch (e: Exception) {
             BuildConfig.BUILD_TIME
         }

+ 3 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/more/MorePresenter.kt

@@ -1,9 +1,9 @@
 package eu.kanade.tachiyomi.ui.more
 
 import android.os.Bundle
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.tachiyomi.data.download.DownloadManager
 import eu.kanade.tachiyomi.data.download.DownloadService
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
 import eu.kanade.tachiyomi.util.lang.launchIO
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -18,7 +18,8 @@ import uy.kohesive.injekt.api.get
 
 class MorePresenter(
     private val downloadManager: DownloadManager = Injekt.get(),
-    preferences: PreferencesHelper = Injekt.get(),
+    preferences: BasePreferences = Injekt.get(),
+
 ) : BasePresenter<MoreController>() {
 
     val downloadedOnly = preferences.downloadedOnly().asState()

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt

@@ -5,6 +5,7 @@ import android.content.Context
 import android.net.Uri
 import android.os.Bundle
 import com.jakewharton.rxrelay.BehaviorRelay
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.domain.chapter.interactor.GetChapterByMangaId
 import eu.kanade.domain.chapter.interactor.UpdateChapter
 import eu.kanade.domain.chapter.model.ChapterUpdate
@@ -25,7 +26,6 @@ import eu.kanade.tachiyomi.data.database.models.toDomainChapter
 import eu.kanade.tachiyomi.data.database.models.toDomainManga
 import eu.kanade.tachiyomi.data.download.DownloadManager
 import eu.kanade.tachiyomi.data.download.model.Download
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.data.saver.Image
 import eu.kanade.tachiyomi.data.saver.ImageSaver
 import eu.kanade.tachiyomi.data.saver.Location
@@ -80,7 +80,7 @@ import eu.kanade.tachiyomi.data.database.models.Chapter as DbChapter
 class ReaderPresenter(
     private val sourceManager: SourceManager = Injekt.get(),
     private val downloadManager: DownloadManager = Injekt.get(),
-    private val preferences: PreferencesHelper = Injekt.get(),
+    preferences: BasePreferences = Injekt.get(),
     private val downloadPreferences: DownloadPreferences = Injekt.get(),
     private val readerPreferences: ReaderPreferences = Injekt.get(),
     private val trackPreferences: TrackPreferences = Injekt.get(),

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryPresenter.kt

@@ -13,6 +13,7 @@ import androidx.paging.compose.LazyPagingItems
 import androidx.paging.compose.collectAsLazyPagingItems
 import androidx.paging.insertSeparators
 import androidx.paging.map
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.domain.chapter.model.Chapter
 import eu.kanade.domain.history.interactor.DeleteHistoryTable
 import eu.kanade.domain.history.interactor.GetHistory
@@ -22,7 +23,6 @@ import eu.kanade.domain.history.interactor.RemoveHistoryByMangaId
 import eu.kanade.domain.history.model.HistoryWithRelations
 import eu.kanade.presentation.history.HistoryUiModel
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
 import eu.kanade.tachiyomi.util.lang.launchIO
 import eu.kanade.tachiyomi.util.lang.toDateKey
@@ -46,7 +46,7 @@ class HistoryPresenter(
     private val deleteHistoryTable: DeleteHistoryTable = Injekt.get(),
     private val removeHistoryById: RemoveHistoryById = Injekt.get(),
     private val removeHistoryByMangaId: RemoveHistoryByMangaId = Injekt.get(),
-    preferences: PreferencesHelper = Injekt.get(),
+    preferences: BasePreferences = Injekt.get(),
 ) : BasePresenter<HistoryController>(), HistoryState by state {
 
     private val _events: Channel<Event> = Channel(Int.MAX_VALUE)

+ 9 - 6
app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesPresenter.kt

@@ -4,6 +4,7 @@ import android.os.Bundle
 import androidx.compose.runtime.Immutable
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.domain.chapter.interactor.GetChapter
 import eu.kanade.domain.chapter.interactor.SetReadStatus
 import eu.kanade.domain.chapter.interactor.UpdateChapter
@@ -11,6 +12,7 @@ import eu.kanade.domain.chapter.model.ChapterUpdate
 import eu.kanade.domain.chapter.model.toDbChapter
 import eu.kanade.domain.library.service.LibraryPreferences
 import eu.kanade.domain.manga.interactor.GetManga
+import eu.kanade.domain.ui.UiPreferences
 import eu.kanade.domain.updates.interactor.GetUpdates
 import eu.kanade.domain.updates.model.UpdatesWithRelations
 import eu.kanade.presentation.components.ChapterDownloadAction
@@ -19,7 +21,6 @@ import eu.kanade.presentation.updates.UpdatesStateImpl
 import eu.kanade.tachiyomi.data.download.DownloadManager
 import eu.kanade.tachiyomi.data.download.DownloadService
 import eu.kanade.tachiyomi.data.download.model.Download
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.source.SourceManager
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
 import eu.kanade.tachiyomi.util.lang.launchIO
@@ -32,6 +33,7 @@ import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.catch
 import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.receiveAsFlow
 import kotlinx.coroutines.launch
 import logcat.LogPriority
@@ -50,17 +52,18 @@ class UpdatesPresenter(
     private val sourceManager: SourceManager = Injekt.get(),
     private val downloadManager: DownloadManager = Injekt.get(),
     private val getChapter: GetChapter = Injekt.get(),
-    preferences: PreferencesHelper = Injekt.get(),
+    basePreferences: BasePreferences = Injekt.get(),
+    uiPreferences: UiPreferences = Injekt.get(),
     libraryPreferences: LibraryPreferences = Injekt.get(),
 ) : BasePresenter<UpdatesController>(), UpdatesState by state {
 
-    val isDownloadOnly: Boolean by preferences.downloadedOnly().asState()
-    val isIncognitoMode: Boolean by preferences.incognitoMode().asState()
+    val isDownloadOnly: Boolean by basePreferences.downloadedOnly().asState()
+    val isIncognitoMode: Boolean by basePreferences.incognitoMode().asState()
 
     val lastUpdated by libraryPreferences.libraryUpdateLastTimestamp().asState()
 
-    val relativeTime: Int by preferences.relativeTime().asState()
-    val dateFormat: DateFormat by mutableStateOf(preferences.dateFormat())
+    val relativeTime: Int by uiPreferences.relativeTime().asState()
+    val dateFormat: DateFormat by mutableStateOf(UiPreferences.dateFormat(uiPreferences.dateFormat().get()))
 
     private val _events: Channel<Event> = Channel(Int.MAX_VALUE)
     val events: Flow<Event> = _events.receiveAsFlow()

+ 9 - 4
app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt

@@ -9,7 +9,10 @@ import android.webkit.WebView
 import androidx.core.net.toUri
 import androidx.preference.PreferenceScreen
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import eu.kanade.domain.library.service.LibraryPreferences
 import eu.kanade.domain.manga.repository.MangaRepository
+import eu.kanade.domain.ui.UiPreferences
+import eu.kanade.domain.ui.model.TabletUiMode
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.cache.ChapterCache
 import eu.kanade.tachiyomi.data.library.LibraryUpdateService
@@ -70,6 +73,8 @@ class SettingsAdvancedController(
     private val chapterCache: ChapterCache by injectLazy()
     private val trackManager: TrackManager by injectLazy()
     private val networkPreferences: NetworkPreferences by injectLazy()
+    private val libraryPreferences: LibraryPreferences by injectLazy()
+    private val uiPreferences: UiPreferences by injectLazy()
 
     @SuppressLint("BatteryLife")
     override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
@@ -156,7 +161,7 @@ class SettingsAdvancedController(
                 onClick { clearChapterCache() }
             }
             switchPreference {
-                bindTo(preferences.autoClearChapterCache())
+                bindTo(libraryPreferences.autoClearChapterCache())
                 titleRes = R.string.pref_auto_clear_chapter_cache
             }
             preference {
@@ -327,11 +332,11 @@ class SettingsAdvancedController(
             titleRes = R.string.pref_category_display
 
             listPreference {
-                bindTo(preferences.tabletUiMode())
+                bindTo(uiPreferences.tabletUiMode())
                 titleRes = R.string.pref_tablet_ui_mode
                 summary = "%s"
-                entriesRes = PreferenceValues.TabletUiMode.values().map { it.titleResId }.toTypedArray()
-                entryValues = PreferenceValues.TabletUiMode.values().map { it.name }.toTypedArray()
+                entriesRes = TabletUiMode.values().map { it.titleResId }.toTypedArray()
+                entryValues = TabletUiMode.values().map { it.name }.toTypedArray()
 
                 onChange {
                     activity?.toast(R.string.requires_app_restart)

+ 20 - 19
app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAppearanceController.kt

@@ -5,9 +5,11 @@ import android.os.Bundle
 import android.view.View
 import androidx.core.app.ActivityCompat
 import androidx.preference.PreferenceScreen
+import eu.kanade.domain.ui.UiPreferences
+import eu.kanade.domain.ui.model.AppTheme
+import eu.kanade.domain.ui.model.ThemeMode
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.util.preference.bindTo
-import eu.kanade.tachiyomi.util.preference.defaultValue
 import eu.kanade.tachiyomi.util.preference.entriesRes
 import eu.kanade.tachiyomi.util.preference.initThenAdd
 import eu.kanade.tachiyomi.util.preference.intListPreference
@@ -20,13 +22,13 @@ import eu.kanade.tachiyomi.util.system.DeviceUtil
 import eu.kanade.tachiyomi.util.system.isDynamicColorAvailable
 import eu.kanade.tachiyomi.util.system.isTablet
 import eu.kanade.tachiyomi.widget.preference.ThemesPreference
+import uy.kohesive.injekt.injectLazy
 import java.util.Date
-import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
-import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values
 
 class SettingsAppearanceController : SettingsController() {
 
     private var themesPreference: ThemesPreference? = null
+    private val uiPreferences: UiPreferences by injectLazy()
 
     override fun setupPreferenceScreen(screen: PreferenceScreen) = screen.apply {
         titleRes = R.string.pref_category_appearance
@@ -35,7 +37,7 @@ class SettingsAppearanceController : SettingsController() {
             titleRes = R.string.pref_category_theme
 
             listPreference {
-                bindTo(preferences.themeMode())
+                bindTo(uiPreferences.themeMode())
                 titleRes = R.string.pref_theme_mode
 
                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
@@ -45,9 +47,9 @@ class SettingsAppearanceController : SettingsController() {
                         R.string.theme_dark,
                     )
                     entryValues = arrayOf(
-                        Values.ThemeMode.system.name,
-                        Values.ThemeMode.light.name,
-                        Values.ThemeMode.dark.name,
+                        ThemeMode.SYSTEM.name,
+                        ThemeMode.LIGHT.name,
+                        ThemeMode.DARK.name,
                     )
                 } else {
                     entriesRes = arrayOf(
@@ -55,19 +57,19 @@ class SettingsAppearanceController : SettingsController() {
                         R.string.theme_dark,
                     )
                     entryValues = arrayOf(
-                        Values.ThemeMode.light.name,
-                        Values.ThemeMode.dark.name,
+                        ThemeMode.LIGHT.name,
+                        ThemeMode.DARK.name,
                     )
                 }
 
                 summary = "%s"
             }
             themesPreference = initThenAdd(ThemesPreference(context)) {
-                bindTo(preferences.appTheme())
+                bindTo(uiPreferences.appTheme())
                 titleRes = R.string.pref_app_theme
 
-                val appThemes = Values.AppTheme.values().filter {
-                    val monetFilter = if (it == Values.AppTheme.MONET) {
+                val appThemes = AppTheme.values().filter {
+                    val monetFilter = if (it == AppTheme.MONET) {
                         DeviceUtil.isDynamicColorAvailable
                     } else {
                         true
@@ -82,10 +84,10 @@ class SettingsAppearanceController : SettingsController() {
                 }
             }
             switchPreference {
-                bindTo(preferences.themeDarkAmoled())
+                bindTo(uiPreferences.themeDarkAmoled())
                 titleRes = R.string.pref_dark_theme_pure_black
 
-                visibleIf(preferences.themeMode()) { it != Values.ThemeMode.light }
+                visibleIf(uiPreferences.themeMode()) { it != ThemeMode.LIGHT }
 
                 onChange {
                     activity?.let { ActivityCompat.recreate(it) }
@@ -99,7 +101,7 @@ class SettingsAppearanceController : SettingsController() {
                 titleRes = R.string.pref_category_navigation
 
                 intListPreference {
-                    bindTo(preferences.sideNavIconAlignment())
+                    bindTo(uiPreferences.sideNavIconAlignment())
                     titleRes = R.string.pref_side_nav_icon_alignment
                     entriesRes = arrayOf(
                         R.string.alignment_top,
@@ -116,7 +118,7 @@ class SettingsAppearanceController : SettingsController() {
             titleRes = R.string.pref_category_timestamps
 
             intListPreference {
-                bindTo(preferences.relativeTime())
+                bindTo(uiPreferences.relativeTime())
                 titleRes = R.string.pref_relative_format
                 val values = arrayOf("0", "2", "7")
                 entryValues = values
@@ -131,13 +133,13 @@ class SettingsAppearanceController : SettingsController() {
             }
 
             listPreference {
-                key = Keys.dateFormat
+                bindTo(uiPreferences.dateFormat())
                 titleRes = R.string.pref_date_format
                 entryValues = arrayOf("", "MM/dd/yy", "dd/MM/yy", "yyyy-MM-dd", "dd MMM yyyy", "MMM dd, yyyy")
 
                 val now = Date().time
                 entries = entryValues.map { value ->
-                    val formattedDate = preferences.dateFormat(value.toString()).format(now)
+                    val formattedDate = UiPreferences.dateFormat(value.toString()).format(now)
                     if (value == "") {
                         "${context.getString(R.string.label_default)} ($formattedDate)"
                     } else {
@@ -145,7 +147,6 @@ class SettingsAppearanceController : SettingsController() {
                     }
                 }.toTypedArray()
 
-                defaultValue = ""
                 summary = "%s"
             }
         }

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsController.kt

@@ -19,8 +19,8 @@ import androidx.preference.PreferenceScreen
 import com.bluelinelabs.conductor.ControllerChangeHandler
 import com.bluelinelabs.conductor.ControllerChangeType
 import dev.chrisbanes.insetter.applyInsetter
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.util.preference.asHotFlow
 import eu.kanade.tachiyomi.util.system.getResourceColor
 import kotlinx.coroutines.CoroutineScope
@@ -33,7 +33,7 @@ import uy.kohesive.injekt.api.get
 abstract class SettingsController : PreferenceController() {
 
     var preferenceKey: String? = null
-    val preferences: PreferencesHelper = Injekt.get()
+    val preferences: BasePreferences = Injekt.get()
     val viewScope: CoroutineScope = MainScope()
     private var themedContext: Context? = null
 

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/ui/setting/search/SettingsSearchPresenter.kt

@@ -1,7 +1,7 @@
 package eu.kanade.tachiyomi.ui.setting.search
 
 import android.os.Bundle
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
@@ -10,7 +10,7 @@ import uy.kohesive.injekt.Injekt
 import uy.kohesive.injekt.api.get
 
 class SettingsSearchPresenter(
-    private val preferences: PreferencesHelper = Injekt.get(),
+    private val preferences: BasePreferences = Injekt.get(),
 ) : BasePresenter<SettingsSearchController>() {
 
     private val _state: MutableStateFlow<List<SettingsSearchHelper.SettingsSearchResult>> =

+ 8 - 8
app/src/main/java/eu/kanade/tachiyomi/util/system/ContextExtensions.kt

@@ -36,9 +36,9 @@ import androidx.core.graphics.green
 import androidx.core.graphics.red
 import androidx.core.net.toUri
 import com.hippo.unifile.UniFile
+import eu.kanade.domain.ui.UiPreferences
+import eu.kanade.domain.ui.model.TabletUiMode
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.data.preference.PreferenceValues
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.ui.base.delegate.ThemingDelegate
 import eu.kanade.tachiyomi.ui.reader.setting.ReaderPreferences
 import eu.kanade.tachiyomi.util.lang.truncateCenter
@@ -262,11 +262,11 @@ fun Context.isTablet(): Boolean {
 
 fun Context.prepareTabletUiContext(): Context {
     val configuration = resources.configuration
-    val expected = when (Injekt.get<PreferencesHelper>().tabletUiMode().get()) {
-        PreferenceValues.TabletUiMode.AUTOMATIC -> isTablet()
-        PreferenceValues.TabletUiMode.ALWAYS -> true
-        PreferenceValues.TabletUiMode.LANDSCAPE -> configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
-        PreferenceValues.TabletUiMode.NEVER -> false
+    val expected = when (Injekt.get<UiPreferences>().tabletUiMode().get()) {
+        TabletUiMode.AUTOMATIC -> isTablet()
+        TabletUiMode.ALWAYS -> true
+        TabletUiMode.LANDSCAPE -> configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
+        TabletUiMode.NEVER -> false
     }
     if (configuration.smallestScreenWidthDp >= TABLET_UI_MIN_SCREEN_WIDTH_DP != expected) {
         val overrideConf = Configuration()
@@ -295,7 +295,7 @@ fun Context.isNightMode(): Boolean {
  * https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:appcompat/appcompat/src/main/java/androidx/appcompat/app/AppCompatDelegateImpl.java;l=348;drc=e28752c96fc3fb4d3354781469a1af3dbded4898
  */
 fun Context.createReaderThemeContext(): Context {
-    val preferences = Injekt.get<PreferencesHelper>()
+    val preferences = Injekt.get<UiPreferences>()
     val readerPreferences = Injekt.get<ReaderPreferences>()
     val isDarkBackground = when (readerPreferences.readerTheme().get()) {
         1, 2 -> true // Black, Gray

+ 3 - 3
app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiSearchView.kt

@@ -5,8 +5,8 @@ import android.util.AttributeSet
 import android.view.inputmethod.EditorInfo
 import androidx.appcompat.widget.SearchView
 import androidx.core.view.inputmethod.EditorInfoCompat
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.util.preference.asHotFlow
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
@@ -18,7 +18,7 @@ import uy.kohesive.injekt.api.get
 
 /**
  * A custom [SearchView] that sets [EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING] to imeOptions
- * if [PreferencesHelper.incognitoMode] is true. Some IMEs may not respect this flag.
+ * if [BasePreferences.incognitoMode] is true. Some IMEs may not respect this flag.
  */
 class TachiyomiSearchView @JvmOverloads constructor(
     context: Context,
@@ -31,7 +31,7 @@ class TachiyomiSearchView @JvmOverloads constructor(
     override fun onAttachedToWindow() {
         super.onAttachedToWindow()
         scope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
-        Injekt.get<PreferencesHelper>().incognitoMode()
+        Injekt.get<BasePreferences>().incognitoMode()
             .asHotFlow {
                 imeOptions = if (it) {
                     imeOptions or EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING

+ 4 - 4
app/src/main/java/eu/kanade/tachiyomi/widget/TachiyomiTextInputEditText.kt

@@ -5,8 +5,8 @@ import android.util.AttributeSet
 import android.widget.EditText
 import androidx.core.view.inputmethod.EditorInfoCompat
 import com.google.android.material.textfield.TextInputEditText
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.util.preference.asHotFlow
 import eu.kanade.tachiyomi.widget.TachiyomiTextInputEditText.Companion.setIncognito
 import kotlinx.coroutines.CoroutineScope
@@ -19,7 +19,7 @@ import uy.kohesive.injekt.api.get
 
 /**
  * A custom [TextInputEditText] that sets [EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING] to imeOptions
- * if [PreferencesHelper.incognitoMode] is true. Some IMEs may not respect this flag.
+ * if [BasePreferences.incognitoMode] is true. Some IMEs may not respect this flag.
  *
  * @see setIncognito
  */
@@ -46,10 +46,10 @@ class TachiyomiTextInputEditText @JvmOverloads constructor(
     companion object {
         /**
          * Sets Flow to this [EditText] that sets [EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING] to imeOptions
-         * if [PreferencesHelper.incognitoMode] is true. Some IMEs may not respect this flag.
+         * if [BasePreferences.incognitoMode] is true. Some IMEs may not respect this flag.
          */
         fun EditText.setIncognito(viewScope: CoroutineScope) {
-            Injekt.get<PreferencesHelper>().incognitoMode()
+            Injekt.get<BasePreferences>().incognitoMode()
                 .asHotFlow {
                     imeOptions = if (it) {
                         imeOptions or EditorInfoCompat.IME_FLAG_NO_PERSONALIZED_LEARNING

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/widget/preference/LoginDialogPreference.kt

@@ -9,8 +9,8 @@ import com.bluelinelabs.conductor.ControllerChangeHandler
 import com.bluelinelabs.conductor.ControllerChangeType
 import com.dd.processbutton.iml.ActionProcessButton
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import eu.kanade.domain.base.BasePreferences
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.databinding.PrefAccountLoginBinding
 import eu.kanade.tachiyomi.ui.base.controller.DialogController
 import uy.kohesive.injekt.injectLazy
@@ -23,7 +23,7 @@ abstract class LoginDialogPreference(
     var binding: PrefAccountLoginBinding? = null
         private set
 
-    val preferences: PreferencesHelper by injectLazy()
+    val preferences: BasePreferences by injectLazy()
 
     override fun onCreateDialog(savedViewState: Bundle?): Dialog {
         binding = PrefAccountLoginBinding.inflate(LayoutInflater.from(activity!!))

+ 2 - 2
app/src/main/java/eu/kanade/tachiyomi/widget/preference/ThemesPreference.kt

@@ -6,8 +6,8 @@ import androidx.preference.ListPreference
 import androidx.preference.PreferenceViewHolder
 import androidx.recyclerview.widget.LinearLayoutManager
 import androidx.recyclerview.widget.RecyclerView
+import eu.kanade.domain.ui.model.AppTheme
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.data.preference.PreferenceValues
 import eu.kanade.tachiyomi.util.system.dpToPx
 
 class ThemesPreference @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
@@ -19,7 +19,7 @@ class ThemesPreference @JvmOverloads constructor(context: Context, attrs: Attrib
 
     var lastScrollPosition: Int? = null
 
-    var entries: List<PreferenceValues.AppTheme> = emptyList()
+    var entries: List<AppTheme> = emptyList()
         set(value) {
             field = value
             adapter.setItems(value)

+ 6 - 6
app/src/main/java/eu/kanade/tachiyomi/widget/preference/ThemesPreferenceAdapter.kt

@@ -5,9 +5,9 @@ import android.view.View
 import android.view.ViewGroup
 import androidx.appcompat.view.ContextThemeWrapper
 import androidx.recyclerview.widget.RecyclerView
+import eu.kanade.domain.ui.UiPreferences
+import eu.kanade.domain.ui.model.AppTheme
 import eu.kanade.tachiyomi.R
-import eu.kanade.tachiyomi.data.preference.PreferenceValues
-import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.databinding.PrefThemeItemBinding
 import eu.kanade.tachiyomi.ui.base.delegate.ThemingDelegate
 import eu.kanade.tachiyomi.util.system.getResourceColor
@@ -16,9 +16,9 @@ import uy.kohesive.injekt.injectLazy
 class ThemesPreferenceAdapter(private val clickListener: OnItemClickListener) :
     RecyclerView.Adapter<ThemesPreferenceAdapter.ThemeViewHolder>() {
 
-    private val preferences: PreferencesHelper by injectLazy()
+    private val preferences: UiPreferences by injectLazy()
 
-    private var themes = emptyList<PreferenceValues.AppTheme>()
+    private var themes = emptyList<AppTheme>()
 
     private lateinit var binding: PrefThemeItemBinding
 
@@ -41,7 +41,7 @@ class ThemesPreferenceAdapter(private val clickListener: OnItemClickListener) :
         holder.bind(themes[position])
     }
 
-    fun setItems(themes: List<PreferenceValues.AppTheme>) {
+    fun setItems(themes: List<AppTheme>) {
         this.themes = themes
         notifyDataSetChanged()
     }
@@ -51,7 +51,7 @@ class ThemesPreferenceAdapter(private val clickListener: OnItemClickListener) :
         private val selectedColor = view.context.getResourceColor(R.attr.colorAccent)
         private val unselectedColor = view.context.getResourceColor(android.R.attr.divider)
 
-        fun bind(appTheme: PreferenceValues.AppTheme) {
+        fun bind(appTheme: AppTheme) {
             binding.name.text = view.context.getString(appTheme.titleResId!!)
 
             // For rounded corners