mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 10:44:42 +00:00
feat(core/preference): Add Darwin implementation
Yoinked from my college final project
This commit is contained in:
parent
97417d175f
commit
93962b2649
4 changed files with 227 additions and 2 deletions
|
@ -8,8 +8,11 @@ plugins {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
androidTarget()
|
androidTarget()
|
||||||
|
iosX64()
|
||||||
|
iosArm64()
|
||||||
|
iosSimulatorArm64()
|
||||||
sourceSets {
|
sourceSets {
|
||||||
val commonMain by getting {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(projects.i18n)
|
implementation(projects.i18n)
|
||||||
|
|
||||||
|
@ -27,7 +30,7 @@ kotlin {
|
||||||
implementation(libs.jsoup)
|
implementation(libs.jsoup)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val androidMain by getting {
|
androidMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
// Dependency injection
|
// Dependency injection
|
||||||
api(libs.injekt.core)
|
api(libs.injekt.core)
|
||||||
|
@ -47,6 +50,10 @@ kotlin {
|
||||||
implementation(libs.libarchive)
|
implementation(libs.libarchive)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
iosMain {
|
||||||
|
dependencies {
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,161 @@
|
||||||
|
package eu.kanade.tachiyomi.core.preference
|
||||||
|
|
||||||
|
import co.touchlab.kermit.Logger
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
|
import kotlinx.coroutines.flow.*
|
||||||
|
import platform.Foundation.NSNotification
|
||||||
|
import platform.Foundation.NSNotificationCenter
|
||||||
|
import platform.Foundation.NSUserDefaults
|
||||||
|
import platform.Foundation.NSUserDefaultsDidChangeNotification
|
||||||
|
|
||||||
|
sealed class DarwinPreference<T>(
|
||||||
|
private val userDefaults: NSUserDefaults,
|
||||||
|
private val key: String,
|
||||||
|
private val defaultValue: T,
|
||||||
|
) : Preference<T> {
|
||||||
|
|
||||||
|
private fun flowForKey(key: String) = callbackFlow {
|
||||||
|
val observer = NSNotificationCenter.defaultCenter.addObserverForName(
|
||||||
|
name = NSUserDefaultsDidChangeNotification,
|
||||||
|
`object` = userDefaults,
|
||||||
|
queue = null,
|
||||||
|
) { _: NSNotification? ->
|
||||||
|
trySend(key)
|
||||||
|
}
|
||||||
|
awaitClose {
|
||||||
|
NSNotificationCenter.defaultCenter.removeObserver(observer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract fun read(userDefaults: NSUserDefaults, key: String, defaultValue: T): T
|
||||||
|
|
||||||
|
override fun key(): String {
|
||||||
|
return key
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun get(): T {
|
||||||
|
return try {
|
||||||
|
read(userDefaults, key, defaultValue)
|
||||||
|
} catch (e: ClassCastException) {
|
||||||
|
Logger.i { "Invalid value for $key; deleting" }
|
||||||
|
delete()
|
||||||
|
defaultValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun set(value: T) {
|
||||||
|
userDefaults.setObject(value, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isSet(): Boolean {
|
||||||
|
return userDefaults.objectForKey(key) != null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun delete() {
|
||||||
|
userDefaults.removeObjectForKey(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun defaultValue(): T {
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun changes(): Flow<T> {
|
||||||
|
return flowForKey(key)
|
||||||
|
.onStart { emit("ignition") }
|
||||||
|
.map { get() }
|
||||||
|
.conflate()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun stateIn(scope: CoroutineScope): StateFlow<T> {
|
||||||
|
return changes().stateIn(scope, SharingStarted.Eagerly, get())
|
||||||
|
}
|
||||||
|
|
||||||
|
class StringPrimitive(
|
||||||
|
userDefaults: NSUserDefaults,
|
||||||
|
key: String,
|
||||||
|
defaultValue: String,
|
||||||
|
) : DarwinPreference<String>(userDefaults, key, defaultValue) {
|
||||||
|
override fun read(
|
||||||
|
userDefaults: NSUserDefaults,
|
||||||
|
key: String,
|
||||||
|
defaultValue: String,
|
||||||
|
): String {
|
||||||
|
return userDefaults.stringForKey(key) ?: defaultValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LongPrimitive(
|
||||||
|
userDefaults: NSUserDefaults,
|
||||||
|
key: String,
|
||||||
|
defaultValue: Long,
|
||||||
|
) : DarwinPreference<Long>(userDefaults, key, defaultValue) {
|
||||||
|
override fun read(userDefaults: NSUserDefaults, key: String, defaultValue: Long): Long {
|
||||||
|
return userDefaults.objectForKey(key) as? Long ?: defaultValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IntPrimitive(
|
||||||
|
userDefaults: NSUserDefaults,
|
||||||
|
key: String,
|
||||||
|
defaultValue: Int,
|
||||||
|
) : DarwinPreference<Int>(userDefaults, key, defaultValue) {
|
||||||
|
override fun read(userDefaults: NSUserDefaults, key: String, defaultValue: Int): Int {
|
||||||
|
return userDefaults.objectForKey(key) as? Int ?: defaultValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FloatPrimitive(
|
||||||
|
userDefaults: NSUserDefaults,
|
||||||
|
key: String,
|
||||||
|
defaultValue: Float,
|
||||||
|
) : DarwinPreference<Float>(userDefaults, key, defaultValue) {
|
||||||
|
override fun read(userDefaults: NSUserDefaults, key: String, defaultValue: Float): Float {
|
||||||
|
return userDefaults.objectForKey(key) as? Float ?: defaultValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class BooleanPrimitive(
|
||||||
|
userDefaults: NSUserDefaults,
|
||||||
|
key: String,
|
||||||
|
defaultValue: Boolean,
|
||||||
|
) : DarwinPreference<Boolean>(userDefaults, key, defaultValue) {
|
||||||
|
override fun read(
|
||||||
|
userDefaults: NSUserDefaults,
|
||||||
|
key: String,
|
||||||
|
defaultValue: Boolean,
|
||||||
|
): Boolean {
|
||||||
|
return userDefaults.objectForKey(key) as? Boolean ?: defaultValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class StringSetPrimitive(
|
||||||
|
userDefaults: NSUserDefaults,
|
||||||
|
key: String,
|
||||||
|
defaultValue: Set<String>,
|
||||||
|
) : DarwinPreference<Set<String>>(userDefaults, key, defaultValue) {
|
||||||
|
override fun read(
|
||||||
|
userDefaults: NSUserDefaults,
|
||||||
|
key: String,
|
||||||
|
defaultValue: Set<String>,
|
||||||
|
): Set<String> {
|
||||||
|
return userDefaults.stringArrayForKey(key) as? Set<String>? ?: defaultValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Object<T>(
|
||||||
|
userDefaults: NSUserDefaults,
|
||||||
|
key: String,
|
||||||
|
defaultValue: T,
|
||||||
|
val serializer: (T) -> String,
|
||||||
|
val deserializer: (String) -> T,
|
||||||
|
) : DarwinPreference<T>(userDefaults, key, defaultValue) {
|
||||||
|
override fun read(userDefaults: NSUserDefaults, key: String, defaultValue: T): T {
|
||||||
|
return try {
|
||||||
|
userDefaults.stringForKey(key)?.let(deserializer) ?: defaultValue
|
||||||
|
} catch (e: Exception) {
|
||||||
|
defaultValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package eu.kanade.tachiyomi.core.preference
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.core.preference.DarwinPreference.*
|
||||||
|
import platform.Foundation.NSUserDefaults
|
||||||
|
|
||||||
|
class DarwinPreferenceStore(
|
||||||
|
private val userDefaults: NSUserDefaults = NSUserDefaults.standardUserDefaults(),
|
||||||
|
) : PreferenceStore {
|
||||||
|
|
||||||
|
override fun getString(key: String, defaultValue: String): Preference<String> {
|
||||||
|
return StringPrimitive(userDefaults, key, defaultValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getLong(key: String, defaultValue: Long): Preference<Long> {
|
||||||
|
return LongPrimitive(userDefaults, key, defaultValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getInt(key: String, defaultValue: Int): Preference<Int> {
|
||||||
|
return IntPrimitive(userDefaults, key, defaultValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getFloat(key: String, defaultValue: Float): Preference<Float> {
|
||||||
|
return FloatPrimitive(userDefaults, key, defaultValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getBoolean(key: String, defaultValue: Boolean): Preference<Boolean> {
|
||||||
|
return BooleanPrimitive(userDefaults, key, defaultValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getStringSet(key: String, defaultValue: Set<String>): Preference<Set<String>> {
|
||||||
|
return StringSetPrimitive(userDefaults, key, defaultValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <T> getObject(
|
||||||
|
key: String,
|
||||||
|
defaultValue: T,
|
||||||
|
serializer: (T) -> String,
|
||||||
|
deserializer: (String) -> T,
|
||||||
|
): Preference<T> {
|
||||||
|
return Object(
|
||||||
|
userDefaults = userDefaults,
|
||||||
|
key = key,
|
||||||
|
defaultValue = defaultValue,
|
||||||
|
serializer = serializer,
|
||||||
|
deserializer = deserializer,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAll(): Map<String, *> {
|
||||||
|
return userDefaults.dictionaryRepresentation() as? Map<String, *> ?: emptyMap<String, Any>()
|
||||||
|
}
|
||||||
|
}
|
|
@ -8,6 +8,9 @@ plugins {
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
androidTarget()
|
androidTarget()
|
||||||
|
iosX64()
|
||||||
|
iosArm64()
|
||||||
|
iosSimulatorArm64()
|
||||||
|
|
||||||
applyDefaultHierarchyTemplate()
|
applyDefaultHierarchyTemplate()
|
||||||
|
|
||||||
|
@ -20,6 +23,8 @@ kotlin {
|
||||||
}
|
}
|
||||||
androidMain {
|
androidMain {
|
||||||
}
|
}
|
||||||
|
iosMain {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue