ui: update datastore and rework api

Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
Jason A. Donenfeld 2021-05-06 16:55:29 +02:00
parent 6008efcd95
commit 94ecb13d2f
4 changed files with 38 additions and 34 deletions

View File

@ -10,7 +10,7 @@ buildscript {
coordinatorLayoutVersion = '1.1.0' coordinatorLayoutVersion = '1.1.0'
coreKtxVersion = '1.3.2' coreKtxVersion = '1.3.2'
coroutinesVersion = '1.4.3' coroutinesVersion = '1.4.3'
datastoreVersion = '1.0.0-alpha02' datastoreVersion = '1.0.0-beta01'
desugarVersion = '1.0.10' desugarVersion = '1.0.10'
fragmentVersion = '1.3.3' fragmentVersion = '1.3.3'
jsr305Version = '3.0.2' jsr305Version = '3.0.2'

View File

@ -12,9 +12,10 @@ import android.os.StrictMode.ThreadPolicy
import android.os.StrictMode.VmPolicy import android.os.StrictMode.VmPolicy
import android.util.Log import android.util.Log
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
import androidx.datastore.DataStore import androidx.datastore.core.DataStore
import androidx.datastore.preferences.Preferences import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.createDataStore import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.preferencesDataStoreFile
import com.wireguard.android.backend.Backend import com.wireguard.android.backend.Backend
import com.wireguard.android.backend.GoBackend import com.wireguard.android.backend.GoBackend
import com.wireguard.android.backend.WgQuickBackend import com.wireguard.android.backend.WgQuickBackend
@ -100,7 +101,7 @@ class Application : android.app.Application() {
rootShell = RootShell(applicationContext) rootShell = RootShell(applicationContext)
toolsInstaller = ToolsInstaller(applicationContext, rootShell) toolsInstaller = ToolsInstaller(applicationContext, rootShell)
moduleLoader = ModuleLoader(applicationContext, rootShell, USER_AGENT) moduleLoader = ModuleLoader(applicationContext, rootShell, USER_AGENT)
preferencesDataStore = applicationContext.createDataStore(name = "settings") preferencesDataStore = PreferenceDataStoreFactory.create { applicationContext.preferencesDataStoreFile("settings") }
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
coroutineScope.launch { coroutineScope.launch {
AppCompatDelegate.setDefaultNightMode( AppCompatDelegate.setDefaultNightMode(

View File

@ -5,12 +5,15 @@
package com.wireguard.android.preference package com.wireguard.android.preference
import androidx.datastore.DataStore import androidx.datastore.core.DataStore
import androidx.datastore.preferences.Preferences import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.edit import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.preferencesKey import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.preferencesSetKey import androidx.datastore.preferences.core.floatPreferencesKey
import androidx.datastore.preferences.remove import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.longPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.core.stringSetPreferencesKey
import androidx.preference.PreferenceDataStore import androidx.preference.PreferenceDataStore
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
@ -21,7 +24,7 @@ import kotlinx.coroutines.runBlocking
class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope, private val dataStore: DataStore<Preferences>) : PreferenceDataStore() { class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope, private val dataStore: DataStore<Preferences>) : PreferenceDataStore() {
override fun putString(key: String?, value: String?) { override fun putString(key: String?, value: String?) {
if (key == null) return if (key == null) return
val pk = preferencesKey<String>(key) val pk = stringPreferencesKey(key)
coroutineScope.launch { coroutineScope.launch {
dataStore.edit { dataStore.edit {
if (value == null) it.remove(pk) if (value == null) it.remove(pk)
@ -32,7 +35,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
override fun putStringSet(key: String?, values: Set<String?>?) { override fun putStringSet(key: String?, values: Set<String?>?) {
if (key == null) return if (key == null) return
val pk = preferencesSetKey<String>(key) val pk = stringSetPreferencesKey(key)
val filteredValues = values?.filterNotNull()?.toSet() val filteredValues = values?.filterNotNull()?.toSet()
coroutineScope.launch { coroutineScope.launch {
dataStore.edit { dataStore.edit {
@ -44,7 +47,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
override fun putInt(key: String?, value: Int) { override fun putInt(key: String?, value: Int) {
if (key == null) return if (key == null) return
val pk = preferencesKey<Int>(key) val pk = intPreferencesKey(key)
coroutineScope.launch { coroutineScope.launch {
dataStore.edit { dataStore.edit {
it[pk] = value it[pk] = value
@ -54,7 +57,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
override fun putLong(key: String?, value: Long) { override fun putLong(key: String?, value: Long) {
if (key == null) return if (key == null) return
val pk = preferencesKey<Long>(key) val pk = longPreferencesKey(key)
coroutineScope.launch { coroutineScope.launch {
dataStore.edit { dataStore.edit {
it[pk] = value it[pk] = value
@ -64,7 +67,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
override fun putFloat(key: String?, value: Float) { override fun putFloat(key: String?, value: Float) {
if (key == null) return if (key == null) return
val pk = preferencesKey<Float>(key) val pk = floatPreferencesKey(key)
coroutineScope.launch { coroutineScope.launch {
dataStore.edit { dataStore.edit {
it[pk] = value it[pk] = value
@ -74,7 +77,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
override fun putBoolean(key: String?, value: Boolean) { override fun putBoolean(key: String?, value: Boolean) {
if (key == null) return if (key == null) return
val pk = preferencesKey<Boolean>(key) val pk = booleanPreferencesKey(key)
coroutineScope.launch { coroutineScope.launch {
dataStore.edit { dataStore.edit {
it[pk] = value it[pk] = value
@ -84,7 +87,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
override fun getString(key: String?, defValue: String?): String? { override fun getString(key: String?, defValue: String?): String? {
if (key == null) return defValue if (key == null) return defValue
val pk = preferencesKey<String>(key) val pk = stringPreferencesKey(key)
return runBlocking { return runBlocking {
dataStore.data.map { it[pk] ?: defValue }.first() dataStore.data.map { it[pk] ?: defValue }.first()
} }
@ -92,7 +95,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
override fun getStringSet(key: String?, defValues: Set<String?>?): Set<String?>? { override fun getStringSet(key: String?, defValues: Set<String?>?): Set<String?>? {
if (key == null) return defValues if (key == null) return defValues
val pk = preferencesSetKey<String>(key) val pk = stringSetPreferencesKey(key)
return runBlocking { return runBlocking {
dataStore.data.map { it[pk] ?: defValues }.first() dataStore.data.map { it[pk] ?: defValues }.first()
} }
@ -100,7 +103,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
override fun getInt(key: String?, defValue: Int): Int { override fun getInt(key: String?, defValue: Int): Int {
if (key == null) return defValue if (key == null) return defValue
val pk = preferencesKey<Int>(key) val pk = intPreferencesKey(key)
return runBlocking { return runBlocking {
dataStore.data.map { it[pk] ?: defValue }.first() dataStore.data.map { it[pk] ?: defValue }.first()
} }
@ -108,7 +111,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
override fun getLong(key: String?, defValue: Long): Long { override fun getLong(key: String?, defValue: Long): Long {
if (key == null) return defValue if (key == null) return defValue
val pk = preferencesKey<Long>(key) val pk = longPreferencesKey(key)
return runBlocking { return runBlocking {
dataStore.data.map { it[pk] ?: defValue }.first() dataStore.data.map { it[pk] ?: defValue }.first()
} }
@ -116,7 +119,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
override fun getFloat(key: String?, defValue: Float): Float { override fun getFloat(key: String?, defValue: Float): Float {
if (key == null) return defValue if (key == null) return defValue
val pk = preferencesKey<Float>(key) val pk = floatPreferencesKey(key)
return runBlocking { return runBlocking {
dataStore.data.map { it[pk] ?: defValue }.first() dataStore.data.map { it[pk] ?: defValue }.first()
} }
@ -124,7 +127,7 @@ class PreferencesPreferenceDataStore(private val coroutineScope: CoroutineScope,
override fun getBoolean(key: String?, defValue: Boolean): Boolean { override fun getBoolean(key: String?, defValue: Boolean): Boolean {
if (key == null) return defValue if (key == null) return defValue
val pk = preferencesKey<Boolean>(key) val pk = booleanPreferencesKey(key)
return runBlocking { return runBlocking {
dataStore.data.map { it[pk] ?: defValue }.first() dataStore.data.map { it[pk] ?: defValue }.first()
} }

View File

@ -5,16 +5,16 @@
package com.wireguard.android.util package com.wireguard.android.util
import androidx.datastore.preferences.edit import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.preferencesKey import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.preferencesSetKey import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.remove import androidx.datastore.preferences.core.stringSetPreferencesKey
import com.wireguard.android.Application import com.wireguard.android.Application
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
object UserKnobs { object UserKnobs {
private val DISABLE_KERNEL_MODULE = preferencesKey<Boolean>("disable_kernel_module") private val DISABLE_KERNEL_MODULE = booleanPreferencesKey("disable_kernel_module")
val disableKernelModule: Flow<Boolean> val disableKernelModule: Flow<Boolean>
get() = Application.getPreferencesDataStore().data.map { get() = Application.getPreferencesDataStore().data.map {
it[DISABLE_KERNEL_MODULE] ?: false it[DISABLE_KERNEL_MODULE] ?: false
@ -29,31 +29,31 @@ object UserKnobs {
} }
} }
private val MULTIPLE_TUNNELS = preferencesKey<Boolean>("multiple_tunnels") private val MULTIPLE_TUNNELS = booleanPreferencesKey("multiple_tunnels")
val multipleTunnels: Flow<Boolean> val multipleTunnels: Flow<Boolean>
get() = Application.getPreferencesDataStore().data.map { get() = Application.getPreferencesDataStore().data.map {
it[MULTIPLE_TUNNELS] ?: false it[MULTIPLE_TUNNELS] ?: false
} }
private val DARK_THEME = preferencesKey<Boolean>("dark_theme") private val DARK_THEME = booleanPreferencesKey("dark_theme")
val darkTheme: Flow<Boolean> val darkTheme: Flow<Boolean>
get() = Application.getPreferencesDataStore().data.map { get() = Application.getPreferencesDataStore().data.map {
it[DARK_THEME] ?: false it[DARK_THEME] ?: false
} }
private val ALLOW_REMOTE_CONTROL_INTENTS = preferencesKey<Boolean>("allow_remote_control_intents") private val ALLOW_REMOTE_CONTROL_INTENTS = booleanPreferencesKey("allow_remote_control_intents")
val allowRemoteControlIntents: Flow<Boolean> val allowRemoteControlIntents: Flow<Boolean>
get() = Application.getPreferencesDataStore().data.map { get() = Application.getPreferencesDataStore().data.map {
it[ALLOW_REMOTE_CONTROL_INTENTS] ?: false it[ALLOW_REMOTE_CONTROL_INTENTS] ?: false
} }
private val RESTORE_ON_BOOT = preferencesKey<Boolean>("restore_on_boot") private val RESTORE_ON_BOOT = booleanPreferencesKey("restore_on_boot")
val restoreOnBoot: Flow<Boolean> val restoreOnBoot: Flow<Boolean>
get() = Application.getPreferencesDataStore().data.map { get() = Application.getPreferencesDataStore().data.map {
it[RESTORE_ON_BOOT] ?: false it[RESTORE_ON_BOOT] ?: false
} }
private val LAST_USED_TUNNEL = preferencesKey<String>("last_used_tunnel") private val LAST_USED_TUNNEL = stringPreferencesKey("last_used_tunnel")
val lastUsedTunnel: Flow<String?> val lastUsedTunnel: Flow<String?>
get() = Application.getPreferencesDataStore().data.map { get() = Application.getPreferencesDataStore().data.map {
it[LAST_USED_TUNNEL] it[LAST_USED_TUNNEL]
@ -68,7 +68,7 @@ object UserKnobs {
} }
} }
private val RUNNING_TUNNELS = preferencesSetKey<String>("enabled_configs") private val RUNNING_TUNNELS = stringSetPreferencesKey("enabled_configs")
val runningTunnels: Flow<Set<String>> val runningTunnels: Flow<Set<String>>
get() = Application.getPreferencesDataStore().data.map { get() = Application.getPreferencesDataStore().data.map {
it[RUNNING_TUNNELS] ?: emptySet() it[RUNNING_TUNNELS] ?: emptySet()