refactor(client/kotlin): remove interface layer that seemed redundant (#6102)

I'm opening PRs for small refactors around the code I'm changing for
adding the Favorites menu.

Just anything where I read it and, as a Kotlin noobie, took longer than
expected to understand
This commit is contained in:
Reactor Scram
2024-07-31 11:04:19 -05:00
committed by GitHub
parent 7c6567c969
commit ad64de7206
4 changed files with 147 additions and 207 deletions

View File

@@ -1,59 +1,174 @@
/* Licensed under Apache 2.0 (C) 2024 Firezone, Inc. */
package dev.firezone.android.core.data
import android.content.Context
import android.content.SharedPreferences
import dev.firezone.android.BuildConfig
import dev.firezone.android.core.data.model.Config
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import java.security.MessageDigest
import javax.inject.Inject
interface Repository {
fun getConfigSync(): Config
internal class Repository
@Inject
constructor(
private val context: Context,
private val coroutineDispatcher: CoroutineDispatcher,
private val sharedPreferences: SharedPreferences,
) {
fun getConfigSync(): Config {
return Config(
sharedPreferences.getString(AUTH_BASE_URL_KEY, null)
?: BuildConfig.AUTH_BASE_URL,
sharedPreferences.getString(API_URL_KEY, null)
?: BuildConfig.API_URL,
sharedPreferences.getString(LOG_FILTER_KEY, null)
?: BuildConfig.LOG_FILTER,
)
}
fun getConfig(): Flow<Config>
fun getConfig(): Flow<Config> =
flow {
emit(getConfigSync())
}.flowOn(coroutineDispatcher)
fun getDefaultConfigSync(): Config
fun getDefaultConfigSync(): Config =
Config(
BuildConfig.AUTH_BASE_URL,
BuildConfig.API_URL,
BuildConfig.LOG_FILTER,
)
fun getDefaultConfig(): Flow<Config>
fun getDefaultConfig(): Flow<Config> =
flow {
emit(getDefaultConfigSync())
}.flowOn(coroutineDispatcher)
fun saveSettings(
authBaseUrl: String,
apiUrl: String,
logFilter: String,
): Flow<Unit>
fun saveSettings(
authBaseUrl: String,
apiUrl: String,
logFilter: String,
): Flow<Unit> =
flow {
emit(
sharedPreferences
.edit()
.putString(AUTH_BASE_URL_KEY, authBaseUrl)
.putString(API_URL_KEY, apiUrl)
.putString(LOG_FILTER_KEY, logFilter)
.apply(),
)
}.flowOn(coroutineDispatcher)
fun saveDeviceIdSync(value: String): Unit
fun getDeviceIdSync(): String? = sharedPreferences.getString(DEVICE_ID_KEY, null)
fun getToken(): Flow<String?>
fun getToken(): Flow<String?> =
flow {
emit(sharedPreferences.getString(TOKEN_KEY, null))
}.flowOn(coroutineDispatcher)
fun getTokenSync(): String?
fun getTokenSync(): String? = sharedPreferences.getString(TOKEN_KEY, null)
fun getStateSync(): String?
fun getStateSync(): String? = sharedPreferences.getString(STATE_KEY, null)
fun getNonceSync(): String?
fun getActorName(): Flow<String?> =
flow {
emit(getActorNameSync())
}.flowOn(coroutineDispatcher)
fun getDeviceIdSync(): String?
fun getActorNameSync(): String? =
sharedPreferences.getString(ACTOR_NAME_KEY, null)?.let {
if (it.isNotEmpty()) "Signed in as $it" else "Signed in"
}
fun getActorName(): Flow<String?>
fun getNonceSync(): String? = sharedPreferences.getString(NONCE_KEY, null)
fun getActorNameSync(): String?
fun saveDeviceIdSync(value: String): Unit =
sharedPreferences
.edit()
.putString(DEVICE_ID_KEY, value)
.apply()
fun saveNonce(value: String): Flow<Unit>
fun saveNonce(value: String): Flow<Unit> =
flow {
emit(saveNonceSync(value))
}.flowOn(coroutineDispatcher)
fun saveState(value: String): Flow<Unit>
fun saveNonceSync(value: String) = sharedPreferences.edit().putString(NONCE_KEY, value).apply()
fun saveStateSync(value: String): Unit
fun saveState(value: String): Flow<Unit> =
flow {
emit(saveStateSync(value))
}.flowOn(coroutineDispatcher)
fun saveNonceSync(value: String): Unit
fun saveStateSync(value: String) = sharedPreferences.edit().putString(STATE_KEY, value).apply()
fun saveToken(value: String): Flow<Unit>
fun saveToken(value: String): Flow<Unit> =
flow {
val nonce = sharedPreferences.getString(NONCE_KEY, "").orEmpty()
emit(
sharedPreferences
.edit()
.putString(TOKEN_KEY, nonce.plus(value))
.apply(),
)
}.flowOn(coroutineDispatcher)
fun saveActorName(value: String): Flow<Unit>
fun saveActorName(value: String): Flow<Unit> =
flow {
emit(
sharedPreferences
.edit()
.putString(ACTOR_NAME_KEY, value)
.apply(),
)
}.flowOn(coroutineDispatcher)
fun validateState(value: String): Flow<Boolean>
fun validateState(value: String): Flow<Boolean> =
flow {
val state = sharedPreferences.getString(STATE_KEY, "").orEmpty()
emit(MessageDigest.isEqual(state.toByteArray(), value.toByteArray()))
}.flowOn(coroutineDispatcher)
fun clearToken()
fun clearToken() {
sharedPreferences.edit().apply {
remove(TOKEN_KEY)
apply()
}
}
fun clearNonce()
fun clearNonce() {
sharedPreferences.edit().apply {
remove(NONCE_KEY)
apply()
}
}
fun clearState()
fun clearState() {
sharedPreferences.edit().apply {
remove(STATE_KEY)
apply()
}
}
fun clearActorName()
}
fun clearActorName() {
sharedPreferences.edit().apply {
remove(ACTOR_NAME_KEY)
apply()
}
}
companion object {
private const val AUTH_BASE_URL_KEY = "authBaseUrl"
private const val ACTOR_NAME_KEY = "actorName"
private const val API_URL_KEY = "apiUrl"
private const val LOG_FILTER_KEY = "logFilter"
private const val TOKEN_KEY = "token"
private const val NONCE_KEY = "nonce"
private const val STATE_KEY = "state"
private const val DEVICE_ID_KEY = "deviceId"
}
}

View File

@@ -1,174 +0,0 @@
/* Licensed under Apache 2.0 (C) 2024 Firezone, Inc. */
package dev.firezone.android.core.data
import android.content.Context
import android.content.SharedPreferences
import dev.firezone.android.BuildConfig
import dev.firezone.android.core.data.model.Config
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import java.security.MessageDigest
import javax.inject.Inject
internal class RepositoryImpl
@Inject
constructor(
private val context: Context,
private val coroutineDispatcher: CoroutineDispatcher,
private val sharedPreferences: SharedPreferences,
) : Repository {
override fun getConfigSync(): Config {
return Config(
sharedPreferences.getString(AUTH_BASE_URL_KEY, null)
?: BuildConfig.AUTH_BASE_URL,
sharedPreferences.getString(API_URL_KEY, null)
?: BuildConfig.API_URL,
sharedPreferences.getString(LOG_FILTER_KEY, null)
?: BuildConfig.LOG_FILTER,
)
}
override fun getConfig(): Flow<Config> =
flow {
emit(getConfigSync())
}.flowOn(coroutineDispatcher)
override fun getDefaultConfigSync(): Config =
Config(
BuildConfig.AUTH_BASE_URL,
BuildConfig.API_URL,
BuildConfig.LOG_FILTER,
)
override fun getDefaultConfig(): Flow<Config> =
flow {
emit(getDefaultConfigSync())
}.flowOn(coroutineDispatcher)
override fun saveSettings(
authBaseUrl: String,
apiUrl: String,
logFilter: String,
): Flow<Unit> =
flow {
emit(
sharedPreferences
.edit()
.putString(AUTH_BASE_URL_KEY, authBaseUrl)
.putString(API_URL_KEY, apiUrl)
.putString(LOG_FILTER_KEY, logFilter)
.apply(),
)
}.flowOn(coroutineDispatcher)
override fun getDeviceIdSync(): String? = sharedPreferences.getString(DEVICE_ID_KEY, null)
override fun getToken(): Flow<String?> =
flow {
emit(sharedPreferences.getString(TOKEN_KEY, null))
}.flowOn(coroutineDispatcher)
override fun getTokenSync(): String? = sharedPreferences.getString(TOKEN_KEY, null)
override fun getStateSync(): String? = sharedPreferences.getString(STATE_KEY, null)
override fun getActorName(): Flow<String?> =
flow {
emit(getActorNameSync())
}.flowOn(coroutineDispatcher)
override fun getActorNameSync(): String? =
sharedPreferences.getString(ACTOR_NAME_KEY, null)?.let {
if (it.isNotEmpty()) "Signed in as $it" else "Signed in"
}
override fun getNonceSync(): String? = sharedPreferences.getString(NONCE_KEY, null)
override fun saveDeviceIdSync(value: String): Unit =
sharedPreferences
.edit()
.putString(DEVICE_ID_KEY, value)
.apply()
override fun saveNonce(value: String): Flow<Unit> =
flow {
emit(saveNonceSync(value))
}.flowOn(coroutineDispatcher)
override fun saveNonceSync(value: String) = sharedPreferences.edit().putString(NONCE_KEY, value).apply()
override fun saveState(value: String): Flow<Unit> =
flow {
emit(saveStateSync(value))
}.flowOn(coroutineDispatcher)
override fun saveStateSync(value: String) = sharedPreferences.edit().putString(STATE_KEY, value).apply()
override fun saveToken(value: String): Flow<Unit> =
flow {
val nonce = sharedPreferences.getString(NONCE_KEY, "").orEmpty()
emit(
sharedPreferences
.edit()
.putString(TOKEN_KEY, nonce.plus(value))
.apply(),
)
}.flowOn(coroutineDispatcher)
override fun saveActorName(value: String): Flow<Unit> =
flow {
emit(
sharedPreferences
.edit()
.putString(ACTOR_NAME_KEY, value)
.apply(),
)
}.flowOn(coroutineDispatcher)
override fun validateState(value: String): Flow<Boolean> =
flow {
val state = sharedPreferences.getString(STATE_KEY, "").orEmpty()
emit(MessageDigest.isEqual(state.toByteArray(), value.toByteArray()))
}.flowOn(coroutineDispatcher)
override fun clearToken() {
sharedPreferences.edit().apply {
remove(TOKEN_KEY)
apply()
}
}
override fun clearNonce() {
sharedPreferences.edit().apply {
remove(NONCE_KEY)
apply()
}
}
override fun clearState() {
sharedPreferences.edit().apply {
remove(STATE_KEY)
apply()
}
}
override fun clearActorName() {
sharedPreferences.edit().apply {
remove(ACTOR_NAME_KEY)
apply()
}
}
companion object {
private const val AUTH_BASE_URL_KEY = "authBaseUrl"
private const val ACTOR_NAME_KEY = "actorName"
private const val API_URL_KEY = "apiUrl"
private const val LOG_FILTER_KEY = "logFilter"
private const val TOKEN_KEY = "token"
private const val NONCE_KEY = "nonce"
private const val STATE_KEY = "state"
private const val DEVICE_ID_KEY = "deviceId"
}
}

View File

@@ -11,7 +11,6 @@ import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import dev.firezone.android.core.data.Repository
import dev.firezone.android.core.data.RepositoryImpl
import kotlinx.coroutines.CoroutineDispatcher
@Module
@@ -28,7 +27,7 @@ class DataModule {
@IoDispatcher coroutineDispatcher: CoroutineDispatcher,
sharedPreferences: SharedPreferences,
): Repository =
RepositoryImpl(
Repository(
context,
coroutineDispatcher,
sharedPreferences,

View File

@@ -28,7 +28,7 @@ internal class AuthViewModel
val nonce = generateRandomString(NONCE_LENGTH)
repo.saveNonceSync(nonce)
repo.saveStateSync(state)
val config = repo.getConfigSync()!!
val config = repo.getConfigSync()
val token = repo.getTokenSync()
actionMutableLiveData.postValue(