重构上传
This commit is contained in:
@@ -1,65 +1,116 @@
|
||||
package net.bluemangoo.indpjsk.data
|
||||
|
||||
import android.content.Context
|
||||
import android.content.SharedPreferences
|
||||
import androidx.compose.runtime.MutableState
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.core.content.edit
|
||||
import net.bluemangoo.indpjsk.App
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
object SettingsStore {
|
||||
private fun prefs() =
|
||||
App.appContext.getSharedPreferences("settings", Context.MODE_PRIVATE)
|
||||
|
||||
private const val PREFS = "settings"
|
||||
private const val KEY_UPLOAD_CODE = "upload_code"
|
||||
private const val KEY_USE_UPLOAD = "use_upload"
|
||||
private const val KEY_PROXY = "upstream_proxy"
|
||||
private const val KEY_USE_PROXY = "use_proxy"
|
||||
private const val KEY_BYPASS = "bypass_packages"
|
||||
private const val KEY_PROFILE = "selected_profile"
|
||||
private inline fun <reified T> pref(
|
||||
default: T? = null,
|
||||
key: String? = null
|
||||
) = PrefProperty(
|
||||
clazz = T::class,
|
||||
customDefault = default,
|
||||
customKey = key,
|
||||
prefs = { prefs() }
|
||||
)
|
||||
|
||||
private fun prefs(context: Context) =
|
||||
context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
|
||||
var uploadProfilesJson by pref<String>()
|
||||
var upstreamProxy by pref<String>()
|
||||
var useProxy by pref<Boolean>()
|
||||
var bypassPackages by pref<Set<String>>()
|
||||
var selectedProfileId by pref<String?>(default = null)
|
||||
var continueRun by pref<Boolean>()
|
||||
|
||||
fun loadUploadCode(context: Context): String =
|
||||
prefs(context).getString(KEY_UPLOAD_CODE, "").orEmpty()
|
||||
|
||||
fun saveUploadCode(context: Context, code: String) {
|
||||
prefs(context).edit { putString(KEY_UPLOAD_CODE, code) }
|
||||
}
|
||||
|
||||
fun loadUseUpload(context: Context): Boolean {
|
||||
return loadUploadCode(context).isNotBlank() && prefs(context).getBoolean(KEY_USE_UPLOAD, true)
|
||||
}
|
||||
|
||||
fun saveUseUpload(context: Context, enabled: Boolean) {
|
||||
prefs(context).edit { putBoolean(KEY_USE_UPLOAD, enabled) }
|
||||
}
|
||||
|
||||
|
||||
fun loadProxy(context: Context): String =
|
||||
prefs(context).getString(KEY_PROXY, "").orEmpty()
|
||||
|
||||
fun saveProxy(context: Context, proxy: String) {
|
||||
prefs(context).edit { putString(KEY_PROXY, proxy.trim()) }
|
||||
}
|
||||
|
||||
fun loadUseProxy(context: Context): Boolean {
|
||||
return loadProxy(context).isNotBlank() && prefs(context).getBoolean(KEY_USE_PROXY, true)
|
||||
}
|
||||
|
||||
fun saveUseProxy(context: Context, enabled: Boolean) {
|
||||
prefs(context).edit { putBoolean(KEY_USE_PROXY, enabled) }
|
||||
}
|
||||
|
||||
|
||||
fun loadBypassPackages(context: Context): Set<String> =
|
||||
prefs(context).getStringSet(KEY_BYPASS, emptySet())?.toSet() ?: emptySet()
|
||||
|
||||
fun saveBypassPackages(context: Context, packages: Set<String>) {
|
||||
prefs(context).edit { putStringSet(KEY_BYPASS, packages) }
|
||||
}
|
||||
|
||||
|
||||
fun loadSelectedProfileId(context: Context): String? =
|
||||
prefs(context).getString(KEY_PROFILE, null)
|
||||
|
||||
fun saveSelectedProfileId(context: Context, id: String) {
|
||||
prefs(context).edit { putString(KEY_PROFILE, id) }
|
||||
}
|
||||
}
|
||||
|
||||
class PrefProperty<T>(
|
||||
private val clazz: KClass<*>,
|
||||
private val customDefault: T? = null,
|
||||
private val customKey: String? = null,
|
||||
private val prefs: () -> SharedPreferences
|
||||
) : ReadWriteProperty<Any?, T> {
|
||||
|
||||
private var internalState: MutableState<T>? = null
|
||||
private var resolvedKey: String? = null
|
||||
|
||||
private fun getKey(property: KProperty<*>): String =
|
||||
resolvedKey ?: (customKey ?: property.name).also { resolvedKey = it }
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun getDefault(): T {
|
||||
if (customDefault != null) return customDefault
|
||||
return when {
|
||||
clazz == String::class -> "" as T
|
||||
clazz == Boolean::class -> false as T
|
||||
clazz == Int::class -> 0 as T
|
||||
clazz == Long::class -> 0L as T
|
||||
clazz == Float::class -> 0f as T
|
||||
clazz == Double::class -> 0.0 as T
|
||||
Set::class.java.isAssignableFrom(clazz.java) -> emptySet<String>() as T
|
||||
else -> throw IllegalArgumentException("Unsupported type: ${clazz.simpleName}")
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun getOrCreateState(property: KProperty<*>): MutableState<T> {
|
||||
return internalState ?: run {
|
||||
val key = getKey(property)
|
||||
val sp = prefs()
|
||||
val fallback = getDefault()
|
||||
|
||||
val initialVal: T = when {
|
||||
clazz == String::class -> sp.getString(key, fallback as String) as T
|
||||
clazz == Boolean::class -> sp.getBoolean(key, fallback as Boolean) as T
|
||||
clazz == Int::class -> sp.getInt(key, fallback as Int) as T
|
||||
clazz == Long::class -> sp.getLong(key, fallback as Long) as T
|
||||
clazz == Float::class -> sp.getFloat(key, fallback as Float) as T
|
||||
Set::class.java.isAssignableFrom(clazz.java) -> {
|
||||
(sp.getStringSet(key, fallback as? Set<String>)?.toSet() ?: emptySet<String>()) as T
|
||||
}
|
||||
|
||||
else -> fallback
|
||||
}
|
||||
mutableStateOf(initialVal).also { internalState = it }
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun saveToSp(value: T) {
|
||||
val key = checkNotNull(resolvedKey) { "Property has not been initialized yet" }
|
||||
prefs().edit {
|
||||
when (value) {
|
||||
is String -> putString(key, value)
|
||||
is Boolean -> putBoolean(key, value)
|
||||
is Int -> putInt(key, value)
|
||||
is Long -> putLong(key, value)
|
||||
is Float -> putFloat(key, value)
|
||||
is Set<*> -> putStringSet(key, HashSet(value as Set<String>))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
|
||||
return getOrCreateState(property).value
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
|
||||
getOrCreateState(property).value = value
|
||||
saveToSp(value)
|
||||
}
|
||||
|
||||
operator fun provideDelegate(thisRef: Any?, property: KProperty<*>): PrefProperty<T> {
|
||||
resolvedKey = customKey ?: property.name
|
||||
getOrCreateState(property)
|
||||
return this
|
||||
}
|
||||
}
|
||||
@@ -4,12 +4,6 @@ import android.content.Context
|
||||
import org.json.JSONObject
|
||||
import androidx.core.content.edit
|
||||
|
||||
/**
|
||||
* 每个 profile 下每个步骤「要不要抓」的持久化。
|
||||
*
|
||||
* 就一个 JSON 字符串塞进 SharedPreferences,键是 "profileId/stepId",值 Boolean,
|
||||
* 没存过的默认 true(全抓)。
|
||||
*/
|
||||
object StepSelectionStore {
|
||||
|
||||
private const val PREFS = "step_selection"
|
||||
|
||||
Reference in New Issue
Block a user