skyline/app/src/main/java/emu/skyline/utils/SharedPreferencesDelegate.kt

62 lines
2.9 KiB
Kotlin

/*
* SPDX-License-Identifier: MPL-2.0
* Copyright © 2020 Skyline Team and Contributors (https://github.com/skyline-emu/)
*/
package emu.skyline.utils
import android.content.Context
import android.util.Log
import androidx.preference.PreferenceManager
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
inline fun <reified T> sharedPreferences(context : Context, default : T, prefix : String = "", prefName : String? = null) = SharedPreferencesDelegate(context, T::class.java, default, prefix, prefName)
@Suppress("UNCHECKED_CAST")
class SharedPreferencesDelegate<T>(context : Context, private val clazz : Class<T>, private val default : T, private val prefix : String, prefName : String?) : ReadWriteProperty<Any, T> {
private val prefs = prefName?.let { context.getSharedPreferences(prefName, Context.MODE_PRIVATE) } ?: PreferenceManager.getDefaultSharedPreferences(context)
override fun setValue(thisRef : Any, property : KProperty<*>, value : T) = (prefix + camelToSnakeCase(property.name)).let { keyName ->
prefs.edit().apply {
when (clazz) {
Float::class.java, java.lang.Float::class.java -> putFloat(keyName, value as Float)
Boolean::class.java, java.lang.Boolean::class.java -> putBoolean(keyName, value as Boolean)
String::class.java, java.lang.String::class.java -> putString(keyName, value as String)
Int::class.java, java.lang.Integer::class.java -> putInt(keyName, value as Int)
else -> error("Unsupported type $clazz")
}
}.apply()
}
override fun getValue(thisRef : Any, property : KProperty<*>) : T = (prefix + camelToSnakeCase(property.name)).let { keyName ->
prefs.let {
try {
@Suppress("IMPLICIT_CAST_TO_ANY")
when (clazz) {
Float::class.java, java.lang.Float::class.java -> it.getFloat(keyName, default as Float)
Boolean::class.java, java.lang.Boolean::class.java -> it.getBoolean(keyName, default as Boolean)
String::class.java, java.lang.String::class.java -> it.getString(keyName, default as String)
Int::class.java, java.lang.Integer::class.java -> it.getInt(keyName, default as Int)
else -> error("Unsupported type $clazz")
}
} catch (e : ClassCastException) {
Log.w(TAG, "Found preference '$keyName' of unexpected type, removing it")
it.edit().remove(keyName).apply()
default
}
} as T
}
private fun camelToSnakeCase(text : String) = StringBuilder().apply {
text.forEachIndexed { index, c ->
if (index != 0 && c.isUpperCase()) append('_')
append(c.lowercase())
}
}.toString()
companion object {
private val TAG = SharedPreferencesDelegate::class.java.simpleName
}
}