Add support for the pull-to-refresh in settings (#615)

This commit is contained in:
David Perez
2024-01-15 09:41:14 -06:00
committed by Álison Fernandes
parent 82b174168e
commit 561aabc528
10 changed files with 246 additions and 17 deletions

View File

@@ -10,6 +10,37 @@ import androidx.core.content.edit
abstract class BaseDiskSource(
private val sharedPreferences: SharedPreferences,
) {
/**
* Gets the [Boolean] for the given [key] from [SharedPreferences], or return the [default]
* value if that key is not present.
*/
protected fun getBoolean(
key: String,
default: Boolean? = null,
): Boolean? =
if (sharedPreferences.contains(key)) {
sharedPreferences.getBoolean(key, false)
} else {
// Make sure we can return a null value as a default if necessary
default
}
/**
* Puts the [value] in [SharedPreferences] for the given [key] (or removes the key when the
* value is `null`).
*/
protected fun putBoolean(
key: String,
value: Boolean?,
): Unit =
sharedPreferences.edit {
if (value != null) {
putBoolean(key, value)
} else {
remove(key)
}
}
/**
* Gets the [Int] for the given [key] from [SharedPreferences], or return the [default] value
* if that key is not present.

View File

@@ -53,4 +53,20 @@ interface SettingsDiskSource {
userId: String,
vaultTimeoutAction: VaultTimeoutAction?,
)
/**
* Gets the current state of the pull to refresh feature for the given [userId].
*/
fun getPullToRefreshEnabled(userId: String): Boolean?
/**
* Emits updates that track [getPullToRefreshEnabled] for the given [userId]. This will replay
* the last known value, if any.
*/
fun getPullToRefreshEnabledFlow(userId: String): Flow<Boolean?>
/**
* Stores the given [isPullToRefreshEnabled] for the given [userId].
*/
fun storePullToRefreshEnabled(userId: String, isPullToRefreshEnabled: Boolean?)
}

View File

@@ -10,6 +10,7 @@ import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.onSubscription
private const val APP_LANGUAGE_KEY = "$BASE_KEY:appLocale"
private const val PULL_TO_REFRESH_KEY = "$BASE_KEY:syncOnRefresh"
private const val VAULT_TIMEOUT_ACTION_KEY = "$BASE_KEY:vaultTimeoutAction"
private const val VAULT_TIME_IN_MINUTES_KEY = "$BASE_KEY:vaultTimeout"
@@ -27,6 +28,9 @@ class SettingsDiskSourceImpl(
private val mutableVaultTimeoutInMinutesFlowMap =
mutableMapOf<String, MutableSharedFlow<Int?>>()
private val mutablePullToRefreshEnabledFlowMap =
mutableMapOf<String, MutableSharedFlow<Boolean?>>()
override var appLanguage: AppLanguage?
get() = getString(key = APP_LANGUAGE_KEY)
?.let { storedValue ->
@@ -82,6 +86,18 @@ class SettingsDiskSourceImpl(
getMutableVaultTimeoutActionFlow(userId = userId).tryEmit(vaultTimeoutAction)
}
override fun getPullToRefreshEnabled(userId: String): Boolean? =
getBoolean(key = "${PULL_TO_REFRESH_KEY}_$userId")
override fun getPullToRefreshEnabledFlow(userId: String): Flow<Boolean?> =
getMutablePullToRefreshEnabledFlowMap(userId = userId)
.onSubscription { emit(getPullToRefreshEnabled(userId = userId)) }
override fun storePullToRefreshEnabled(userId: String, isPullToRefreshEnabled: Boolean?) {
putBoolean(key = "${PULL_TO_REFRESH_KEY}_$userId", value = isPullToRefreshEnabled)
getMutablePullToRefreshEnabledFlowMap(userId = userId).tryEmit(isPullToRefreshEnabled)
}
private fun getMutableVaultTimeoutActionFlow(
userId: String,
): MutableSharedFlow<VaultTimeoutAction?> =
@@ -95,4 +111,11 @@ class SettingsDiskSourceImpl(
mutableVaultTimeoutInMinutesFlowMap.getOrPut(userId) {
bufferedMutableSharedFlow(replay = 1)
}
private fun getMutablePullToRefreshEnabledFlowMap(
userId: String,
): MutableSharedFlow<Boolean?> =
mutablePullToRefreshEnabledFlowMap.getOrPut(userId) {
bufferedMutableSharedFlow(replay = 1)
}
}

View File

@@ -63,4 +63,14 @@ interface SettingsRepository {
* Stores the given [VaultTimeoutAction] for the given [userId].
*/
fun storeVaultTimeoutAction(userId: String, vaultTimeoutAction: VaultTimeoutAction?)
/**
* Gets updates for the pull to refresh enabled.
*/
fun getPullToRefreshEnabledFlow(): StateFlow<Boolean>
/**
* Stores the given [isPullToRefreshEnabled] for the active user.
*/
fun storePullToRefreshEnabled(isPullToRefreshEnabled: Boolean)
}

View File

@@ -7,6 +7,7 @@ import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeout
import com.x8bit.bitwarden.data.platform.repository.model.VaultTimeoutAction
import com.x8bit.bitwarden.ui.platform.feature.settings.appearance.model.AppLanguage
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.map
@@ -116,6 +117,29 @@ class SettingsRepositoryImpl(
vaultTimeoutAction = vaultTimeoutAction,
)
}
override fun getPullToRefreshEnabledFlow(): StateFlow<Boolean> {
val userId = activeUserId ?: return MutableStateFlow(false)
return settingsDiskSource
.getPullToRefreshEnabledFlow(userId = userId)
.map { it ?: false }
.stateIn(
scope = unconfinedScope,
started = SharingStarted.Eagerly,
initialValue = settingsDiskSource
.getPullToRefreshEnabled(userId = userId)
?: false,
)
}
override fun storePullToRefreshEnabled(isPullToRefreshEnabled: Boolean) {
activeUserId?.let {
settingsDiskSource.storePullToRefreshEnabled(
userId = it,
isPullToRefreshEnabled = isPullToRefreshEnabled,
)
}
}
}
/**

View File

@@ -3,6 +3,7 @@ package com.x8bit.bitwarden.ui.platform.feature.settings.other
import android.os.Parcelable
import androidx.lifecycle.SavedStateHandle
import com.x8bit.bitwarden.R
import com.x8bit.bitwarden.data.platform.repository.SettingsRepository
import com.x8bit.bitwarden.data.vault.repository.VaultRepository
import com.x8bit.bitwarden.ui.platform.base.BaseViewModel
import com.x8bit.bitwarden.ui.platform.base.util.Text
@@ -19,13 +20,14 @@ private const val KEY_STATE = "state"
*/
@HiltViewModel
class OtherViewModel @Inject constructor(
private val settingsRepo: SettingsRepository,
private val vaultRepo: VaultRepository,
savedStateHandle: SavedStateHandle,
) : BaseViewModel<OtherState, OtherEvent, OtherAction>(
initialState = savedStateHandle[KEY_STATE]
?: OtherState(
allowScreenCapture = false,
allowSyncOnRefresh = false,
allowSyncOnRefresh = settingsRepo.getPullToRefreshEnabledFlow().value,
clearClipboardFrequency = OtherState.ClearClipboardFrequency.DEFAULT,
lastSyncTime = "5/14/2023 4:52 PM",
),
@@ -44,7 +46,7 @@ class OtherViewModel @Inject constructor(
}
private fun handleAllowSyncToggled(action: OtherAction.AllowSyncToggle) {
// TODO BIT-461 hook up to pull-to-refresh feature
settingsRepo.storePullToRefreshEnabled(action.isSyncEnabled)
mutableStateFlow.update { it.copy(allowSyncOnRefresh = action.isSyncEnabled) }
}