|
|
@@ -0,0 +1,152 @@
|
|
|
+package io.legado.app.data.repository
|
|
|
+
|
|
|
+import android.content.Context
|
|
|
+import androidx.datastore.core.DataStore
|
|
|
+import androidx.datastore.preferences.SharedPreferencesMigration
|
|
|
+import androidx.datastore.preferences.core.*
|
|
|
+import androidx.datastore.preferences.preferencesDataStore
|
|
|
+import io.legado.app.utils.putPrefBoolean
|
|
|
+import io.legado.app.utils.putPrefFloat
|
|
|
+import io.legado.app.utils.putPrefInt
|
|
|
+import io.legado.app.utils.putPrefLong
|
|
|
+import io.legado.app.utils.putPrefString
|
|
|
+import io.legado.app.utils.putPrefStringSet
|
|
|
+import io.legado.app.utils.removePref
|
|
|
+import kotlinx.coroutines.flow.Flow
|
|
|
+import kotlinx.coroutines.flow.catch
|
|
|
+import kotlinx.coroutines.flow.map
|
|
|
+import java.io.IOException
|
|
|
+
|
|
|
+val Context.dataStore: DataStore<Preferences> by preferencesDataStore(
|
|
|
+ name = "settings",
|
|
|
+ produceMigrations = { context ->
|
|
|
+ listOf(
|
|
|
+ SharedPreferencesMigration(
|
|
|
+ context,
|
|
|
+ "${context.packageName}_preferences"
|
|
|
+ )
|
|
|
+ )
|
|
|
+ }
|
|
|
+)
|
|
|
+
|
|
|
+/**
|
|
|
+ * 设置仓储
|
|
|
+ * 采用 DataStore + SharedPreferences 桥接模式
|
|
|
+ * 写入时同时写入两者,读取时以 DataStore 为准
|
|
|
+ * 这样可以保持现有的基于 SP 的备份恢复功能正常工作
|
|
|
+ */
|
|
|
+class SettingsRepository(private val context: Context) {
|
|
|
+
|
|
|
+ private val dataStore = context.dataStore
|
|
|
+
|
|
|
+ fun <T> getPreference(key: Preferences.Key<T>, defaultValue: T): Flow<T> {
|
|
|
+ return dataStore.data
|
|
|
+ .catch { exception ->
|
|
|
+ if (exception is IOException) {
|
|
|
+ emit(emptyPreferences())
|
|
|
+ } else {
|
|
|
+ throw exception
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .map { preferences ->
|
|
|
+ preferences[key] ?: defaultValue
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ suspend fun <T> updatePreference(key: Preferences.Key<T>, value: T) {
|
|
|
+ // 1. 写入 DataStore (UI 响应式来源)
|
|
|
+ dataStore.edit { preferences ->
|
|
|
+ preferences[key] = value
|
|
|
+ }
|
|
|
+ // 2. 桥接:写回 SharedPreferences (保证备份功能正常)
|
|
|
+ syncToSharedPrefs(key.name, value)
|
|
|
+ }
|
|
|
+
|
|
|
+ private fun syncToSharedPrefs(key: String, value: Any?) {
|
|
|
+ when (value) {
|
|
|
+ is String -> context.putPrefString(key, value)
|
|
|
+ is Int -> context.putPrefInt(key, value)
|
|
|
+ is Boolean -> context.putPrefBoolean(key, value)
|
|
|
+ is Long -> context.putPrefLong(key, value)
|
|
|
+ is Float -> context.putPrefFloat(key, value)
|
|
|
+ is Set<*> -> {
|
|
|
+ @Suppress("UNCHECKED_CAST")
|
|
|
+ context.putPrefStringSet(key, value as MutableSet<String>)
|
|
|
+ }
|
|
|
+ null -> context.removePref(key)
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // String 类型的快捷访问
|
|
|
+ fun getString(key: String, defaultValue: String = ""): Flow<String> =
|
|
|
+ getPreference(stringPreferencesKey(key), defaultValue)
|
|
|
+
|
|
|
+ suspend fun putString(key: String, value: String) =
|
|
|
+ updatePreference(stringPreferencesKey(key), value)
|
|
|
+
|
|
|
+ // Int 类型的快捷访问
|
|
|
+ fun getInt(key: String, defaultValue: Int = 0): Flow<Int> =
|
|
|
+ getPreference(intPreferencesKey(key), defaultValue)
|
|
|
+
|
|
|
+ suspend fun putInt(key: String, value: Int) =
|
|
|
+ updatePreference(intPreferencesKey(key), value)
|
|
|
+
|
|
|
+ // Boolean 类型的快捷访问
|
|
|
+ fun getBoolean(key: String, defaultValue: Boolean = false): Flow<Boolean> =
|
|
|
+ getPreference(booleanPreferencesKey(key), defaultValue)
|
|
|
+
|
|
|
+ suspend fun putBoolean(key: String, value: Boolean) =
|
|
|
+ updatePreference(booleanPreferencesKey(key), value)
|
|
|
+
|
|
|
+ // Long 类型的快捷访问
|
|
|
+ fun getLong(key: String, defaultValue: Long = 0L): Flow<Long> =
|
|
|
+ getPreference(longPreferencesKey(key), defaultValue)
|
|
|
+
|
|
|
+ suspend fun putLong(key: String, value: Long) =
|
|
|
+ updatePreference(longPreferencesKey(key), value)
|
|
|
+
|
|
|
+ // Float 类型的快捷访问
|
|
|
+ fun getFloat(key: String, defaultValue: Float = 0f): Flow<Float> =
|
|
|
+ getPreference(floatPreferencesKey(key), defaultValue)
|
|
|
+
|
|
|
+ suspend fun putFloat(key: String, value: Float) =
|
|
|
+ updatePreference(floatPreferencesKey(key), value)
|
|
|
+
|
|
|
+ // Set<String> 类型的快捷访问
|
|
|
+ fun getStringSet(key: String, defaultValue: Set<String> = emptySet()): Flow<Set<String>> =
|
|
|
+ getPreference(stringSetPreferencesKey(key), defaultValue)
|
|
|
+
|
|
|
+ suspend fun putStringSet(key: String, value: Set<String>) =
|
|
|
+ updatePreference(stringSetPreferencesKey(key), value)
|
|
|
+
|
|
|
+ // 批量从 Map 恢复到 DataStore (用于兼容 Restore 逻辑)
|
|
|
+ suspend fun batchPutFromMap(map: Map<String, *>) {
|
|
|
+ dataStore.edit { preferences ->
|
|
|
+ map.forEach { (key, value) ->
|
|
|
+ when (value) {
|
|
|
+ is String -> preferences[stringPreferencesKey(key)] = value
|
|
|
+ is Int -> preferences[intPreferencesKey(key)] = value
|
|
|
+ is Boolean -> preferences[booleanPreferencesKey(key)] = value
|
|
|
+ is Long -> preferences[longPreferencesKey(key)] = value
|
|
|
+ is Float -> preferences[floatPreferencesKey(key)] = value
|
|
|
+ is Set<*> -> {
|
|
|
+ @Suppress("UNCHECKED_CAST")
|
|
|
+ preferences[stringSetPreferencesKey(key)] = value as Set<String>
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 移除配置
|
|
|
+ suspend fun remove(key: String) {
|
|
|
+ dataStore.edit { preferences ->
|
|
|
+ preferences.remove(stringPreferencesKey(key))
|
|
|
+ preferences.remove(intPreferencesKey(key))
|
|
|
+ preferences.remove(booleanPreferencesKey(key))
|
|
|
+ preferences.remove(longPreferencesKey(key))
|
|
|
+ preferences.remove(floatPreferencesKey(key))
|
|
|
+ }
|
|
|
+ context.removePref(key)
|
|
|
+ }
|
|
|
+}
|