Handle preference stores corruption by clearing them (#5086)
* Handle preference stores corruption by clearing them:
- Use the centralised `PreferenceDataStoreFactory` instead of `preferences by`.
- Add `DefaultPreferencesCorruptionHandlerFactory.replaceWithEmpty` to its `create(name)` method so all preference stores are cleared if they're corrupted.
* Add detekt rule to make sure we use `PreferenceDataStoreFactory` instead of `by preferencesDataStore`
* Remove `@SingleIn` annotations as the annotated class no longer have to be singletons
This commit is contained in:
committed by
GitHub
parent
b54b74a198
commit
2f2e886e9f
@@ -27,6 +27,7 @@ dependencies {
|
||||
implementation(projects.appconfig)
|
||||
implementation(projects.features.enterprise.api)
|
||||
implementation(projects.libraries.core)
|
||||
implementation(projects.libraries.androidutils)
|
||||
implementation(projects.libraries.architecture)
|
||||
implementation(projects.libraries.matrix.api)
|
||||
implementation(projects.libraries.matrixui)
|
||||
|
||||
@@ -7,44 +7,39 @@
|
||||
|
||||
package io.element.android.features.lockscreen.impl.storage
|
||||
|
||||
import android.content.Context
|
||||
import androidx.datastore.core.DataStore
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.core.booleanPreferencesKey
|
||||
import androidx.datastore.preferences.core.edit
|
||||
import androidx.datastore.preferences.core.intPreferencesKey
|
||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import androidx.datastore.preferences.preferencesDataStore
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.features.lockscreen.impl.LockScreenConfig
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.di.SingleIn
|
||||
import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.map
|
||||
import javax.inject.Inject
|
||||
|
||||
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "pin_code_store")
|
||||
|
||||
@SingleIn(AppScope::class)
|
||||
@ContributesBinding(AppScope::class)
|
||||
class PreferencesLockScreenStore @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
preferenceDataStoreFactory: PreferenceDataStoreFactory,
|
||||
private val lockScreenConfig: LockScreenConfig,
|
||||
) : LockScreenStore {
|
||||
private val dataStore = preferenceDataStoreFactory.create("pin_code_store")
|
||||
|
||||
private val pinCodeKey = stringPreferencesKey("encoded_pin_code")
|
||||
private val remainingAttemptsKey = intPreferencesKey("remaining_pin_code_attempts")
|
||||
private val biometricUnlockKey = booleanPreferencesKey("biometric_unlock_enabled")
|
||||
|
||||
override suspend fun getRemainingPinCodeAttemptsNumber(): Int {
|
||||
return context.dataStore.data.map { preferences ->
|
||||
return dataStore.data.map { preferences ->
|
||||
preferences.getRemainingPinCodeAttemptsNumber()
|
||||
}.first()
|
||||
}
|
||||
|
||||
override suspend fun onWrongPin() {
|
||||
context.dataStore.edit { preferences ->
|
||||
dataStore.edit { preferences ->
|
||||
val current = preferences.getRemainingPinCodeAttemptsNumber()
|
||||
val remaining = (current - 1).coerceAtLeast(0)
|
||||
preferences[remainingAttemptsKey] = remaining
|
||||
@@ -52,43 +47,43 @@ class PreferencesLockScreenStore @Inject constructor(
|
||||
}
|
||||
|
||||
override suspend fun resetCounter() {
|
||||
context.dataStore.edit { preferences ->
|
||||
dataStore.edit { preferences ->
|
||||
preferences[remainingAttemptsKey] = lockScreenConfig.maxPinCodeAttemptsBeforeLogout
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getEncryptedCode(): String? {
|
||||
return context.dataStore.data.map { preferences ->
|
||||
return dataStore.data.map { preferences ->
|
||||
preferences[pinCodeKey]
|
||||
}.first()
|
||||
}
|
||||
|
||||
override suspend fun saveEncryptedPinCode(pinCode: String) {
|
||||
context.dataStore.edit { preferences ->
|
||||
dataStore.edit { preferences ->
|
||||
preferences[pinCodeKey] = pinCode
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun deleteEncryptedPinCode() {
|
||||
context.dataStore.edit { preferences ->
|
||||
dataStore.edit { preferences ->
|
||||
preferences.remove(pinCodeKey)
|
||||
}
|
||||
}
|
||||
|
||||
override fun hasPinCode(): Flow<Boolean> {
|
||||
return context.dataStore.data.map { preferences ->
|
||||
return dataStore.data.map { preferences ->
|
||||
preferences[pinCodeKey] != null
|
||||
}
|
||||
}
|
||||
|
||||
override fun isBiometricUnlockAllowed(): Flow<Boolean> {
|
||||
return context.dataStore.data.map { preferences ->
|
||||
return dataStore.data.map { preferences ->
|
||||
preferences[biometricUnlockKey] ?: false
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun setIsBiometricUnlockAllowed(isAllowed: Boolean) {
|
||||
context.dataStore.edit { preferences ->
|
||||
dataStore.edit { preferences ->
|
||||
preferences[biometricUnlockKey] = isAllowed
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user