Prechádzať zdrojové kódy

fix: dataStore逻辑

HapeLee 5 mesiacov pred
rodič
commit
9189b3dcfc

+ 1 - 1
app/src/main/java/io/legado/app/help/config/AppConfig.kt

@@ -1007,7 +1007,7 @@ object AppConfig : SharedPreferences.OnSharedPreferenceChangeListener {
     var pureBlack
     var pureBlack
         get() = appCtx.getPrefBoolean(PreferKey.pureBlack, false)
         get() = appCtx.getPrefBoolean(PreferKey.pureBlack, false)
         set(value) {
         set(value) {
-            appCtx.getPrefBoolean(PreferKey.pureBlack, value)
+            appCtx.putPrefBoolean(PreferKey.pureBlack, value)
         }
         }
 
 
     val hasLightBg: Boolean
     val hasLightBg: Boolean

+ 1 - 2
app/src/main/java/io/legado/app/lib/prefs/ThemeCardPreference.kt

@@ -19,7 +19,6 @@ import com.google.android.material.card.MaterialCardView
 import io.legado.app.R
 import io.legado.app.R
 import io.legado.app.constant.EventBus
 import io.legado.app.constant.EventBus
 import io.legado.app.constant.PreferKey
 import io.legado.app.constant.PreferKey
-import io.legado.app.help.config.AppConfig
 import io.legado.app.lib.dialogs.alert
 import io.legado.app.lib.dialogs.alert
 import io.legado.app.ui.config.themeConfig.ThemeConfig
 import io.legado.app.ui.config.themeConfig.ThemeConfig
 import io.legado.app.utils.getPrefString
 import io.legado.app.utils.getPrefString
@@ -90,7 +89,7 @@ class ThemeCardPreference(context: Context, attrs: AttributeSet) : Preference(co
                             context.toastOnUi(R.string.transparent_theme_alarm)
                             context.toastOnUi(R.string.transparent_theme_alarm)
                             return@setOnClickListener
                             return@setOnClickListener
                         } else {
                         } else {
-                            AppConfig.containerOpacity = 0
+                            ThemeConfig.containerOpacity = 0
                         }
                         }
                     }
                     }
                     val oldValue = currentValue
                     val oldValue = currentValue

+ 0 - 1
app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt

@@ -2587,7 +2587,6 @@ class ReadBookViewModel(
             else -> "0" // dark → follow system
             else -> "0" // dark → follow system
         }
         }
         ThemeConfig.themeMode = nextMode
         ThemeConfig.themeMode = nextMode
-        AppConfig.themeMode = nextMode
         _uiState.update { it.copy(styleConfig = buildStyleConfig()) }
         _uiState.update { it.copy(styleConfig = buildStyleConfig()) }
         _effects.tryEmit(ReadBookEffect.UpdateReadViewConfig(
         _effects.tryEmit(ReadBookEffect.UpdateReadViewConfig(
             setOf(
             setOf(

+ 58 - 53
app/src/main/java/io/legado/app/ui/config/PrefDelegate.kt

@@ -1,17 +1,10 @@
 package io.legado.app.ui.config
 package io.legado.app.ui.config
 
 
-import android.content.SharedPreferences
 import androidx.compose.runtime.MutableState
 import androidx.compose.runtime.MutableState
 import androidx.compose.runtime.State
 import androidx.compose.runtime.State
 import androidx.compose.runtime.mutableStateOf
 import androidx.compose.runtime.mutableStateOf
 import androidx.lifecycle.DefaultLifecycleObserver
 import androidx.lifecycle.DefaultLifecycleObserver
 import androidx.lifecycle.LifecycleOwner
 import androidx.lifecycle.LifecycleOwner
-import io.legado.app.utils.defaultSharedPreferences
-import io.legado.app.utils.getPrefBoolean
-import io.legado.app.utils.getPrefFloat
-import io.legado.app.utils.getPrefInt
-import io.legado.app.utils.getPrefLong
-import io.legado.app.utils.getPrefString
 import io.legado.app.utils.putPrefBoolean
 import io.legado.app.utils.putPrefBoolean
 import io.legado.app.utils.putPrefFloat
 import io.legado.app.utils.putPrefFloat
 import io.legado.app.utils.putPrefInt
 import io.legado.app.utils.putPrefInt
@@ -24,8 +17,10 @@ import io.legado.app.data.repository.dataStore
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.Dispatchers
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.Job
+import kotlinx.coroutines.runBlocking
 import kotlinx.coroutines.flow.catch
 import kotlinx.coroutines.flow.catch
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.first
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.launch
 import kotlinx.coroutines.launch
 import splitties.init.appCtx
 import splitties.init.appCtx
@@ -49,39 +44,41 @@ fun <T> prefDelegate(
     sync: Boolean = false,
     sync: Boolean = false,
     onValueChange: ((T) -> Unit)? = null
     onValueChange: ((T) -> Unit)? = null
 ): PrefDelegate<T> {
 ): PrefDelegate<T> {
-    return object : PrefDelegate<T>, SharedPreferences.OnSharedPreferenceChangeListener, DefaultLifecycleObserver {
-        private var _value: MutableState<T> = mutableStateOf(readInitialValue())
+    return object : PrefDelegate<T>, DefaultLifecycleObserver {
+        private var _value: MutableState<T> = mutableStateOf(defaultValue)
         override val state: State<T> get() = _value
         override val state: State<T> get() = _value
+        private val scope = CoroutineScope(Dispatchers.IO)
         private var dsObserverJob: Job? = null
         private var dsObserverJob: Job? = null
 
 
         init {
         init {
-            if (lifecycleOwner != null) {
-                lifecycleOwner.lifecycle.addObserver(this)
-            } else {
-                appCtx.defaultSharedPreferences.registerOnSharedPreferenceChangeListener(this)
+            // 从 DataStore 读取初始值(DS 为唯一读取源)
+            scope.launch {
+                val dsValue = readFromDs()
+                if (dsValue != null) {
+                    _value.value = dsValue
+                }
             }
             }
-            // 观察 DataStore,以 DS 为读取权威源
-            dsObserverJob = CoroutineScope(Dispatchers.IO).launch {
+            // 观察 DataStore 变化,用于跨实例同步
+            dsObserverJob = scope.launch {
                 appCtx.dataStore.data
                 appCtx.dataStore.data
                     .catch { if (it is IOException) emit(emptyPreferences()) else throw it }
                     .catch { if (it is IOException) emit(emptyPreferences()) else throw it }
                     .map { prefs ->
                     .map { prefs ->
-                        // 安全读取 String 值,用于类型回退(类型不匹配时返回 null)
                         val strVal = runCatching { prefs[stringPreferencesKey(key)] }.getOrNull()
                         val strVal = runCatching { prefs[stringPreferencesKey(key)] }.getOrNull()
                         @Suppress("UNCHECKED_CAST")
                         @Suppress("UNCHECKED_CAST")
                         when {
                         when {
                             defaultValue is String || defaultValue == null ->
                             defaultValue is String || defaultValue == null ->
                                 strVal as T?
                                 strVal as T?
                             defaultValue is Int ->
                             defaultValue is Int ->
-                                (prefs[intPreferencesKey(key)]
+                                (runCatching { prefs[intPreferencesKey(key)] }.getOrNull()
                                     ?: strVal?.toIntOrNull()) as T?
                                     ?: strVal?.toIntOrNull()) as T?
                             defaultValue is Boolean ->
                             defaultValue is Boolean ->
-                                (prefs[booleanPreferencesKey(key)]
+                                (runCatching { prefs[booleanPreferencesKey(key)] }.getOrNull()
                                     ?: strVal?.toBooleanStrictOrNull()) as T?
                                     ?: strVal?.toBooleanStrictOrNull()) as T?
                             defaultValue is Long ->
                             defaultValue is Long ->
-                                (prefs[longPreferencesKey(key)]
+                                (runCatching { prefs[longPreferencesKey(key)] }.getOrNull()
                                     ?: strVal?.toLongOrNull()) as T?
                                     ?: strVal?.toLongOrNull()) as T?
                             defaultValue is Float ->
                             defaultValue is Float ->
-                                (prefs[floatPreferencesKey(key)]
+                                (runCatching { prefs[floatPreferencesKey(key)] }.getOrNull()
                                     ?: strVal?.toFloatOrNull()) as T?
                                     ?: strVal?.toFloatOrNull()) as T?
                             else -> null
                             else -> null
                         }
                         }
@@ -94,10 +91,10 @@ fun <T> prefDelegate(
                         }
                         }
                     }
                     }
             }
             }
-        }
-
-        override fun onCreate(owner: LifecycleOwner) {
-            appCtx.defaultSharedPreferences.registerOnSharedPreferenceChangeListener(this)
+            // 注册生命周期观察者(如果有)
+            if (lifecycleOwner != null) {
+                lifecycleOwner.lifecycle.addObserver(this)
+            }
         }
         }
 
 
         override fun onDestroy(owner: LifecycleOwner) {
         override fun onDestroy(owner: LifecycleOwner) {
@@ -105,33 +102,17 @@ fun <T> prefDelegate(
         }
         }
 
 
         override fun dispose() {
         override fun dispose() {
-            appCtx.defaultSharedPreferences.unregisterOnSharedPreferenceChangeListener(this)
             dsObserverJob?.cancel()
             dsObserverJob?.cancel()
         }
         }
 
 
-        @Suppress("UNCHECKED_CAST")
-        private fun readInitialValue(): T {
-            val prefs = appCtx.defaultSharedPreferences
-            return when {
-                defaultValue is String -> appCtx.getPrefString(key, defaultValue) as T
-                defaultValue == null && prefs.contains(key) -> {
-                    appCtx.getPrefString(key, null) as T
-                }
-
-                defaultValue is Int -> appCtx.getPrefInt(key, defaultValue) as T
-                defaultValue is Boolean -> appCtx.getPrefBoolean(key, defaultValue) as T
-                defaultValue is Long -> appCtx.getPrefLong(key, defaultValue) as T
-                defaultValue is Float -> appCtx.getPrefFloat(key, defaultValue) as T
-                else -> defaultValue
-            }
-        }
-
         override fun getValue(thisRef: Any?, property: KProperty<*>): T {
         override fun getValue(thisRef: Any?, property: KProperty<*>): T {
             return _value.value
             return _value.value
         }
         }
 
 
         override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
         override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
             if (_value.value != value) {
             if (_value.value != value) {
+                _value.value = value
+                // 同步写入 SP(向后兼容:AppConfig/MainViewModel 等仍直接读 SP)
                 when (value) {
                 when (value) {
                     is String? -> if (sync) appCtx.putPrefStringSync(key, value) else appCtx.putPrefString(key, value)
                     is String? -> if (sync) appCtx.putPrefStringSync(key, value) else appCtx.putPrefString(key, value)
                     is Int -> appCtx.putPrefInt(key, value)
                     is Int -> appCtx.putPrefInt(key, value)
@@ -139,8 +120,8 @@ fun <T> prefDelegate(
                     is Long -> appCtx.putPrefLong(key, value)
                     is Long -> appCtx.putPrefLong(key, value)
                     is Float -> appCtx.putPrefFloat(key, value)
                     is Float -> appCtx.putPrefFloat(key, value)
                 }
                 }
-                // 同步写入 DataStore,保持 SP/DS 一致
-                CoroutineScope(Dispatchers.IO).launch {
+                // 同步写入 DataStore(权威存储),确保持久化后再返回
+                runBlocking(Dispatchers.IO) {
                     when (value) {
                     when (value) {
                         is String? -> DsSync.putString(key, value)
                         is String? -> DsSync.putString(key, value)
                         is Int -> DsSync.putInt(key, value)
                         is Int -> DsSync.putInt(key, value)
@@ -149,18 +130,42 @@ fun <T> prefDelegate(
                         is Float -> DsSync.putFloat(key, value)
                         is Float -> DsSync.putFloat(key, value)
                     }
                     }
                 }
                 }
-                _value.value = value
                 onValueChange?.invoke(value)
                 onValueChange?.invoke(value)
             }
             }
         }
         }
 
 
-        override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, changedKey: String?) {
-            if (changedKey == key) {
-                val newValue = readInitialValue()
-                if (_value.value != newValue) {
-                    _value.value = newValue
-                    onValueChange?.invoke(newValue)
-                }
+        /**
+         * 从 DataStore 读取当前值。
+         * DS 为唯一读取源,类型不匹配时安全回退到 String 解析。
+         */
+        @Suppress("UNCHECKED_CAST")
+        private suspend fun readFromDs(): T? {
+            return try {
+                appCtx.dataStore.data
+                    .catch { if (it is IOException) emit(emptyPreferences()) else throw it }
+                    .map { prefs ->
+                        val strVal = runCatching { prefs[stringPreferencesKey(key)] }.getOrNull()
+                        when {
+                            defaultValue is String || defaultValue == null ->
+                                strVal as T?
+                            defaultValue is Int ->
+                                (runCatching { prefs[intPreferencesKey(key)] }.getOrNull()
+                                    ?: strVal?.toIntOrNull()) as T?
+                            defaultValue is Boolean ->
+                                (runCatching { prefs[booleanPreferencesKey(key)] }.getOrNull()
+                                    ?: strVal?.toBooleanStrictOrNull()) as T?
+                            defaultValue is Long ->
+                                (runCatching { prefs[longPreferencesKey(key)] }.getOrNull()
+                                    ?: strVal?.toLongOrNull()) as T?
+                            defaultValue is Float ->
+                                (runCatching { prefs[floatPreferencesKey(key)] }.getOrNull()
+                                    ?: strVal?.toFloatOrNull()) as T?
+                            else -> null
+                        }
+                    }
+                    .first()
+            } catch (e: Exception) {
+                null
             }
             }
         }
         }
     }
     }
@@ -175,4 +180,4 @@ fun <T> prefStateDelegate(
 ): PrefStateDelegate<T> {
 ): PrefStateDelegate<T> {
     val delegate = prefDelegate(key, defaultValue, lifecycleOwner, sync, onValueChange)
     val delegate = prefDelegate(key, defaultValue, lifecycleOwner, sync, onValueChange)
     return PrefStateDelegate(delegate)
     return PrefStateDelegate(delegate)
-}
+}

+ 1 - 2
app/src/main/java/io/legado/app/ui/config/themeConfig/ThemeConfigScreen.kt

@@ -79,7 +79,6 @@ import io.legado.app.base.AppContextWrapper
 import io.legado.app.constant.EventBus
 import io.legado.app.constant.EventBus
 import io.legado.app.constant.PreferKey
 import io.legado.app.constant.PreferKey
 import io.legado.app.help.LauncherIconHelp
 import io.legado.app.help.LauncherIconHelp
-import io.legado.app.help.config.AppConfig
 import io.legado.app.help.config.ThemeConfigStore
 import io.legado.app.help.config.ThemeConfigStore
 import io.legado.app.help.loadFontFiles
 import io.legado.app.help.loadFontFiles
 import io.legado.app.ui.config.labConfig.LabConfig
 import io.legado.app.ui.config.labConfig.LabConfig
@@ -311,7 +310,7 @@ fun ThemeConfigScreen(
                                         context.toastOnUi(R.string.transparent_theme_alarm)
                                         context.toastOnUi(R.string.transparent_theme_alarm)
                                         return@ThemeColorSelector
                                         return@ThemeColorSelector
                                     } else {
                                     } else {
-                                        AppConfig.containerOpacity = 0
+                                        ThemeConfig.containerOpacity = 0
                                     }
                                     }
                                 }
                                 }
                                 val oldTheme = selectedTheme
                                 val oldTheme = selectedTheme

+ 22 - 48
app/src/main/java/io/legado/app/ui/main/MainViewModel.kt

@@ -1,19 +1,16 @@
 package io.legado.app.ui.main
 package io.legado.app.ui.main
 
 
 import android.app.Application
 import android.app.Application
-import android.content.SharedPreferences
 import androidx.compose.runtime.Stable
 import androidx.compose.runtime.Stable
+import androidx.compose.runtime.snapshotFlow
+import androidx.lifecycle.viewModelScope
 import io.legado.app.base.BaseViewModel
 import io.legado.app.base.BaseViewModel
 import io.legado.app.constant.EventBus
 import io.legado.app.constant.EventBus
-import io.legado.app.constant.PreferKey
 import io.legado.app.domain.usecase.AppStartupMaintenanceUseCase
 import io.legado.app.domain.usecase.AppStartupMaintenanceUseCase
 import io.legado.app.domain.usecase.WebDavBackupUseCase
 import io.legado.app.domain.usecase.WebDavBackupUseCase
 import io.legado.app.ui.config.themeConfig.ThemeConfig
 import io.legado.app.ui.config.themeConfig.ThemeConfig
 import io.legado.app.ui.main.my.PrefClickEvent
 import io.legado.app.ui.main.my.PrefClickEvent
-import io.legado.app.utils.defaultSharedPreferences
 import io.legado.app.utils.eventBus.FlowEventBus
 import io.legado.app.utils.eventBus.FlowEventBus
-import io.legado.app.utils.getPrefBoolean
-import io.legado.app.utils.getPrefString
 import kotlinx.collections.immutable.ImmutableList
 import kotlinx.collections.immutable.ImmutableList
 import kotlinx.collections.immutable.toImmutableList
 import kotlinx.collections.immutable.toImmutableList
 import kotlinx.coroutines.flow.MutableSharedFlow
 import kotlinx.coroutines.flow.MutableSharedFlow
@@ -21,6 +18,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.asSharedFlow
 import kotlinx.coroutines.flow.asSharedFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.update
 import kotlinx.coroutines.flow.update
+import kotlinx.coroutines.launch
 
 
 class MainViewModel(
 class MainViewModel(
     application: Application,
     application: Application,
@@ -28,40 +26,25 @@ class MainViewModel(
     private val webDavBackupUseCase: WebDavBackupUseCase
     private val webDavBackupUseCase: WebDavBackupUseCase
 ) : BaseViewModel(application) {
 ) : BaseViewModel(application) {
 
 
-    private val prefs = context.defaultSharedPreferences
-    private val mainPreferenceKeys = setOf(
-        PreferKey.showDiscovery,
-        PreferKey.showHome,
-        PreferKey.showRss,
-        PreferKey.showBottomView,
-        PreferKey.useFloatingBottomBar,
-        PreferKey.useFloatingBottomBarLiquidGlass,
-        PreferKey.defaultHomePage,
-        PreferKey.labelVisibilityMode,
-        NAV_EXTENDED_KEY
-    )
-    private val preferenceListener =
-        SharedPreferences.OnSharedPreferenceChangeListener { _, key ->
-            if (key in mainPreferenceKeys) {
-                _uiState.value = readMainUiState()
-            }
-        }
-
     private val _uiState = MutableStateFlow(readMainUiState())
     private val _uiState = MutableStateFlow(readMainUiState())
     val uiState = _uiState.asStateFlow()
     val uiState = _uiState.asStateFlow()
     private val _effects = MutableSharedFlow<MainEffect>(extraBufferCapacity = 8)
     private val _effects = MutableSharedFlow<MainEffect>(extraBufferCapacity = 8)
     val effects = _effects.asSharedFlow()
     val effects = _effects.asSharedFlow()
 
 
     init {
     init {
-        prefs.registerOnSharedPreferenceChangeListener(preferenceListener)
+        // 通过 snapshotFlow 直接观察 ThemeConfig 的 Compose State,全链路走 DS
+        viewModelScope.launch {
+            snapshotFlow {
+                readMainUiState()
+            }.collect { newState ->
+                if (_uiState.value != newState) {
+                    _uiState.value = newState
+                }
+            }
+        }
         deleteNotShelfBook()
         deleteNotShelfBook()
     }
     }
 
 
-    override fun onCleared() {
-        prefs.unregisterOnSharedPreferenceChangeListener(preferenceListener)
-        super.onCleared()
-    }
-
     fun upAllBookToc() {
     fun upAllBookToc() {
         FlowEventBus.post(EventBus.UP_ALL_BOOK_TOC, Unit)
         FlowEventBus.post(EventBus.UP_ALL_BOOK_TOC, Unit)
     }
     }
@@ -149,31 +132,22 @@ data class MainUiState(
     val navExtended: Boolean = false
     val navExtended: Boolean = false
 )
 )
 
 
-private const val NAV_EXTENDED_KEY = "navExtended"
-
 private fun MainViewModel.readMainUiState(): MainUiState {
 private fun MainViewModel.readMainUiState(): MainUiState {
-    val showDiscovery = context.getPrefBoolean(PreferKey.showDiscovery, true)
-    val showHome = context.getPrefBoolean(PreferKey.showHome, true)
-    val showRss = context.getPrefBoolean(PreferKey.showRss, true)
     val destinations = MainDestination.mainDestinations.filter {
     val destinations = MainDestination.mainDestinations.filter {
         when (it) {
         when (it) {
-            MainDestination.Explore -> showDiscovery
-            MainDestination.Home -> showHome
-            MainDestination.Rss -> showRss
+            MainDestination.Explore -> ThemeConfig.showDiscovery
+            MainDestination.Home -> ThemeConfig.showHome
+            MainDestination.Rss -> ThemeConfig.showRss
             else -> true
             else -> true
         }
         }
     }.toImmutableList()
     }.toImmutableList()
     return MainUiState(
     return MainUiState(
         destinations = destinations,
         destinations = destinations,
-        defaultHomePage = context.getPrefString(PreferKey.defaultHomePage, "bookshelf")
-            ?: "bookshelf",
-        showBottomView = context.getPrefBoolean(PreferKey.showBottomView, true),
-        useFloatingBottomBar = context.getPrefBoolean(PreferKey.useFloatingBottomBar, false),
-        useFloatingBottomBarLiquidGlass = context.getPrefBoolean(
-            PreferKey.useFloatingBottomBarLiquidGlass,
-            false
-        ),
-        labelVisibilityMode = context.getPrefString(PreferKey.labelVisibilityMode, "auto") ?: "auto",
-        navExtended = context.getPrefBoolean(NAV_EXTENDED_KEY, false)
+        defaultHomePage = ThemeConfig.defaultHomePage,
+        showBottomView = ThemeConfig.showBottomView,
+        useFloatingBottomBar = ThemeConfig.useFloatingBottomBar,
+        useFloatingBottomBarLiquidGlass = ThemeConfig.useFloatingBottomBarLiquidGlass,
+        labelVisibilityMode = ThemeConfig.labelVisibilityMode,
+        navExtended = ThemeConfig.navExtended
     )
     )
 }
 }

+ 0 - 3
app/src/main/java/io/legado/app/utils/ContextExtensions.kt

@@ -36,7 +36,6 @@ import androidx.core.content.ContextCompat
 import androidx.core.content.FileProvider
 import androidx.core.content.FileProvider
 import androidx.core.content.edit
 import androidx.core.content.edit
 import androidx.core.net.toUri
 import androidx.core.net.toUri
-import androidx.datastore.preferences.preferencesDataStore
 import androidx.preference.PreferenceManager
 import androidx.preference.PreferenceManager
 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
 import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel
 import io.legado.app.R
 import io.legado.app.R
@@ -464,8 +463,6 @@ val Context.channel: String
 val Context.isDebuggable: Boolean
 val Context.isDebuggable: Boolean
     get() = applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE != 0
     get() = applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE != 0
 
 
-val Context.dataStore by preferencesDataStore(name = "settings")
-
 val Context.bookshelfLayoutMode: Int
 val Context.bookshelfLayoutMode: Int
     get() = if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
     get() = if (resources.configuration.orientation == Configuration.ORIENTATION_LANDSCAPE) {
         AppConfig.bookshelfLayoutModeLandscape
         AppConfig.bookshelfLayoutModeLandscape

+ 0 - 40
app/src/main/java/io/legado/app/utils/DataStoreUtil.kt

@@ -1,40 +0,0 @@
-package io.legado.app.utils
-
-import android.content.Context
-import androidx.datastore.preferences.core.booleanPreferencesKey
-import androidx.datastore.preferences.core.edit
-import androidx.datastore.preferences.core.floatPreferencesKey
-import androidx.datastore.preferences.core.intPreferencesKey
-import androidx.datastore.preferences.core.longPreferencesKey
-import androidx.datastore.preferences.core.stringPreferencesKey
-import kotlinx.coroutines.flow.first
-import kotlinx.coroutines.flow.map
-
-object DataStoreUtil {
-
-    suspend fun <T> save(context: Context, key: String, value: T) {
-        context.dataStore.edit { preferences ->
-            when (value) {
-                is String -> preferences[stringPreferencesKey(key)] = value
-                is Int -> preferences[intPreferencesKey(key)] = value
-                is Boolean -> preferences[booleanPreferencesKey(key)] = value
-                is Float -> preferences[floatPreferencesKey(key)] = value
-                is Long -> preferences[longPreferencesKey(key)] = value
-            }
-        }
-    }
-
-    @Suppress("UNCHECKED_CAST")
-    suspend fun <T> read(context: Context, key: String, defaultValue: T): T {
-        return context.dataStore.data.map { preferences ->
-            when (defaultValue) {
-                is String -> preferences[stringPreferencesKey(key)] ?: defaultValue
-                is Int -> preferences[intPreferencesKey(key)] ?: defaultValue
-                is Boolean -> preferences[booleanPreferencesKey(key)] ?: defaultValue
-                is Float -> preferences[floatPreferencesKey(key)] ?: defaultValue
-                is Long -> preferences[longPreferencesKey(key)] ?: defaultValue
-                else -> defaultValue
-            } as T
-        }.first()
-    }
-}