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:
parent
3faaab407f
commit
8245ad8bc3
30 changed files with 198 additions and 138 deletions
|
|
@ -31,6 +31,7 @@ dependencies {
|
|||
implementation(libs.androidx.activity.activity)
|
||||
implementation(libs.androidx.recyclerview)
|
||||
implementation(libs.androidx.exifinterface)
|
||||
implementation(libs.androidx.datastore.preferences)
|
||||
api(libs.androidx.browser)
|
||||
|
||||
testImplementation(projects.tests.testutils)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.androidutils.preferences
|
||||
|
||||
import androidx.datastore.core.handlers.ReplaceFileCorruptionHandler
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.core.emptyPreferences
|
||||
|
||||
object DefaultPreferencesCorruptionHandlerFactory {
|
||||
/**
|
||||
* Creates a [ReplaceFileCorruptionHandler] that will replace the corrupted preferences file with an empty preferences object.
|
||||
*/
|
||||
fun replaceWithEmpty(): ReplaceFileCorruptionHandler<Preferences> {
|
||||
return ReplaceFileCorruptionHandler(
|
||||
produceNewData = {
|
||||
// If the preferences file is corrupted, we return an empty preferences object
|
||||
emptyPreferences()
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
@ -24,7 +24,9 @@ dependencies {
|
|||
implementation(libs.androidx.datastore.preferences)
|
||||
implementation(projects.appconfig)
|
||||
implementation(projects.libraries.di)
|
||||
implementation(projects.libraries.androidutils)
|
||||
implementation(projects.libraries.core)
|
||||
implementation(projects.libraries.preferences.api)
|
||||
implementation(libs.coroutines.core)
|
||||
testImplementation(libs.test.junit)
|
||||
testImplementation(libs.coroutines.test)
|
||||
|
|
|
|||
|
|
@ -7,30 +7,24 @@
|
|||
|
||||
package io.element.android.libraries.featureflag.impl
|
||||
|
||||
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.preferencesDataStore
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.featureflag.api.Feature
|
||||
import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.map
|
||||
import javax.inject.Inject
|
||||
|
||||
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "elementx_featureflag")
|
||||
|
||||
/**
|
||||
* Note: this will be used only in the nightly and in the debug build.
|
||||
*/
|
||||
class PreferencesFeatureFlagProvider @Inject constructor(
|
||||
@ApplicationContext context: Context,
|
||||
private val buildMeta: BuildMeta,
|
||||
preferenceDataStoreFactory: PreferenceDataStoreFactory,
|
||||
) : MutableFeatureFlagProvider {
|
||||
private val store = context.dataStore
|
||||
private val store = preferenceDataStoreFactory.create("elementx_featureflag")
|
||||
|
||||
override val priority = MEDIUM_PRIORITY
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ dependencies {
|
|||
implementation(projects.libraries.troubleshoot.api)
|
||||
implementation(projects.libraries.designsystem)
|
||||
implementation(projects.libraries.uiStrings)
|
||||
implementation(projects.libraries.preferences.api)
|
||||
implementation(projects.services.toolbox.api)
|
||||
api(projects.libraries.permissions.api)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,28 +7,22 @@
|
|||
|
||||
package io.element.android.libraries.permissions.impl
|
||||
|
||||
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.preferencesDataStore
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.core.bool.orFalse
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.permissions.api.PermissionsStore
|
||||
import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import javax.inject.Inject
|
||||
|
||||
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "permissions_store")
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class DefaultPermissionsStore @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
preferenceDataStoreFactory: PreferenceDataStoreFactory,
|
||||
) : PermissionsStore {
|
||||
private val store = context.dataStore
|
||||
private val store = preferenceDataStoreFactory.create("permissions_store")
|
||||
|
||||
override suspend fun setPermissionDenied(permission: String, value: Boolean) {
|
||||
store.edit { prefs ->
|
||||
|
|
|
|||
|
|
@ -7,28 +7,22 @@
|
|||
|
||||
package io.element.android.libraries.preferences.impl.store
|
||||
|
||||
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.stringPreferencesKey
|
||||
import androidx.datastore.preferences.preferencesDataStore
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.core.meta.BuildMeta
|
||||
import io.element.android.libraries.core.meta.BuildType
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.matrix.api.media.MediaPreviewValue
|
||||
import io.element.android.libraries.matrix.api.tracing.LogLevel
|
||||
import io.element.android.libraries.matrix.api.tracing.TraceLogPack
|
||||
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
|
||||
import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import javax.inject.Inject
|
||||
|
||||
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "elementx_preferences")
|
||||
|
||||
private val developerModeKey = booleanPreferencesKey("developerMode")
|
||||
private val customElementCallBaseUrlKey = stringPreferencesKey("elementCallBaseUrl")
|
||||
private val themeKey = stringPreferencesKey("theme")
|
||||
|
|
@ -39,10 +33,10 @@ private val traceLogPacksKey = stringPreferencesKey("traceLogPacks")
|
|||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class DefaultAppPreferencesStore @Inject constructor(
|
||||
@ApplicationContext context: Context,
|
||||
private val buildMeta: BuildMeta,
|
||||
preferenceDataStoreFactory: PreferenceDataStoreFactory,
|
||||
) : AppPreferencesStore {
|
||||
private val store = context.dataStore
|
||||
private val store = preferenceDataStoreFactory.create("elementx_preferences")
|
||||
|
||||
override suspend fun setDeveloperModeEnabled(enabled: Boolean) {
|
||||
store.edit { prefs ->
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import androidx.datastore.core.DataStore
|
|||
import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.preferencesDataStore
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.androidutils.preferences.DefaultPreferencesCorruptionHandlerFactory
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.di.SingleIn
|
||||
|
|
@ -27,7 +28,10 @@ class DefaultPreferencesDataStoreFactory @Inject constructor(
|
|||
private val dataStoreHolders = ConcurrentHashMap<String, DataStoreHolder>()
|
||||
|
||||
private class DataStoreHolder(name: String) {
|
||||
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = name)
|
||||
val Context.dataStore: DataStore<Preferences> by preferencesDataStore(
|
||||
name = name,
|
||||
corruptionHandler = DefaultPreferencesCorruptionHandlerFactory.replaceWithEmpty(),
|
||||
)
|
||||
}
|
||||
|
||||
override fun create(name: String): DataStore<Preferences> {
|
||||
|
|
|
|||
|
|
@ -7,12 +7,8 @@
|
|||
|
||||
package io.element.android.libraries.push.impl.store
|
||||
|
||||
import android.content.Context
|
||||
import androidx.datastore.core.DataStore
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.core.edit
|
||||
import androidx.datastore.preferences.core.intPreferencesKey
|
||||
import androidx.datastore.preferences.preferencesDataStore
|
||||
import app.cash.sqldelight.coroutines.asFlow
|
||||
import app.cash.sqldelight.coroutines.mapToList
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
|
|
@ -20,29 +16,30 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
|||
import io.element.android.libraries.dateformatter.api.DateFormatter
|
||||
import io.element.android.libraries.dateformatter.api.DateFormatterMode
|
||||
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.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory
|
||||
import io.element.android.libraries.push.api.history.PushHistoryItem
|
||||
import io.element.android.libraries.push.impl.PushDatabase
|
||||
import io.element.android.libraries.push.impl.store.DefaultPushDataStore.Companion.BATTERY_OPTIMIZATION_BANNER_STATE_DISMISSED
|
||||
import io.element.android.libraries.push.impl.store.DefaultPushDataStore.Companion.BATTERY_OPTIMIZATION_BANNER_STATE_INIT
|
||||
import io.element.android.libraries.push.impl.store.DefaultPushDataStore.Companion.BATTERY_OPTIMIZATION_BANNER_STATE_SHOW
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import javax.inject.Inject
|
||||
|
||||
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "push_store")
|
||||
|
||||
@SingleIn(AppScope::class)
|
||||
@ContributesBinding(AppScope::class)
|
||||
class DefaultPushDataStore @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val pushDatabase: PushDatabase,
|
||||
private val dateFormatter: DateFormatter,
|
||||
private val dispatchers: CoroutineDispatchers,
|
||||
preferencesFactory: PreferenceDataStoreFactory,
|
||||
) : PushDataStore {
|
||||
private val pushCounter = intPreferencesKey("push_counter")
|
||||
|
||||
private val dataStore = preferencesFactory.create("push_store")
|
||||
|
||||
/**
|
||||
* Integer preference to track the state of the battery optimization banner.
|
||||
* Possible values:
|
||||
|
|
@ -52,24 +49,24 @@ class DefaultPushDataStore @Inject constructor(
|
|||
*/
|
||||
private val batteryOptimizationBannerState = intPreferencesKey("battery_optimization_banner_state")
|
||||
|
||||
override val pushCounterFlow: Flow<Int> = context.dataStore.data.map { preferences ->
|
||||
override val pushCounterFlow: Flow<Int> = dataStore.data.map { preferences ->
|
||||
preferences[pushCounter] ?: 0
|
||||
}
|
||||
|
||||
@Suppress("UnnecessaryParentheses")
|
||||
override val shouldDisplayBatteryOptimizationBannerFlow: Flow<Boolean> = context.dataStore.data.map { preferences ->
|
||||
override val shouldDisplayBatteryOptimizationBannerFlow: Flow<Boolean> = dataStore.data.map { preferences ->
|
||||
(preferences[batteryOptimizationBannerState] ?: BATTERY_OPTIMIZATION_BANNER_STATE_INIT) == BATTERY_OPTIMIZATION_BANNER_STATE_SHOW
|
||||
}
|
||||
|
||||
suspend fun incrementPushCounter() {
|
||||
context.dataStore.edit { settings ->
|
||||
dataStore.edit { settings ->
|
||||
val currentCounterValue = settings[pushCounter] ?: 0
|
||||
settings[pushCounter] = currentCounterValue + 1
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun setBatteryOptimizationBannerState(newState: Int) {
|
||||
context.dataStore.edit { settings ->
|
||||
dataStore.edit { settings ->
|
||||
val currentValue = settings[batteryOptimizationBannerState] ?: BATTERY_OPTIMIZATION_BANNER_STATE_INIT
|
||||
settings[batteryOptimizationBannerState] = when (currentValue) {
|
||||
BATTERY_OPTIMIZATION_BANNER_STATE_INIT,
|
||||
|
|
@ -106,7 +103,7 @@ class DefaultPushDataStore @Inject constructor(
|
|||
|
||||
override suspend fun reset() {
|
||||
pushDatabase.pushHistoryQueries.removeAll()
|
||||
context.dataStore.edit {
|
||||
dataStore.edit {
|
||||
it.clear()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ dependencies {
|
|||
implementation(projects.libraries.androidutils)
|
||||
implementation(projects.libraries.core)
|
||||
implementation(projects.libraries.matrix.api)
|
||||
implementation(projects.libraries.preferences.api)
|
||||
implementation(projects.libraries.pushstore.api)
|
||||
implementation(libs.androidx.corektx)
|
||||
implementation(libs.androidx.datastore.preferences)
|
||||
|
|
@ -38,6 +39,7 @@ dependencies {
|
|||
testImplementation(libs.test.turbine)
|
||||
testImplementation(libs.coroutines.test)
|
||||
testImplementation(projects.libraries.matrix.test)
|
||||
testImplementation(projects.libraries.preferences.test)
|
||||
testImplementation(projects.services.appnavstate.test)
|
||||
testImplementation(projects.libraries.pushstore.test)
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ 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.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory
|
||||
import io.element.android.libraries.pushstore.api.UserPushStore
|
||||
import io.element.android.libraries.pushstore.api.UserPushStoreFactory
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
|
@ -22,6 +23,7 @@ import javax.inject.Inject
|
|||
@ContributesBinding(AppScope::class)
|
||||
class DefaultUserPushStoreFactory @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
private val preferenceDataStoreFactory: PreferenceDataStoreFactory,
|
||||
) : UserPushStoreFactory {
|
||||
// We can have only one class accessing a single data store, so keep a cache of them.
|
||||
private val cache = ConcurrentHashMap<SessionId, UserPushStore>()
|
||||
|
|
@ -29,7 +31,8 @@ class DefaultUserPushStoreFactory @Inject constructor(
|
|||
return cache.getOrPut(userId) {
|
||||
UserPushStoreDataStore(
|
||||
context = context,
|
||||
userId = userId
|
||||
userId = userId,
|
||||
factory = preferenceDataStoreFactory,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,12 +13,12 @@ import androidx.datastore.preferences.core.Preferences
|
|||
import androidx.datastore.preferences.core.booleanPreferencesKey
|
||||
import androidx.datastore.preferences.core.edit
|
||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import androidx.datastore.preferences.preferencesDataStore
|
||||
import androidx.datastore.preferences.preferencesDataStoreFile
|
||||
import io.element.android.libraries.androidutils.hash.hash
|
||||
import io.element.android.libraries.core.bool.orFalse
|
||||
import io.element.android.libraries.core.bool.orTrue
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory
|
||||
import io.element.android.libraries.pushstore.api.UserPushStore
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.first
|
||||
|
|
@ -31,6 +31,7 @@ import timber.log.Timber
|
|||
class UserPushStoreDataStore(
|
||||
private val context: Context,
|
||||
userId: SessionId,
|
||||
factory: PreferenceDataStoreFactory,
|
||||
) : UserPushStore {
|
||||
// Hash the sessionId to get rid of exotic chars and take only the first 16 chars.
|
||||
// The risk of collision is not high.
|
||||
|
|
@ -49,28 +50,28 @@ class UserPushStoreDataStore(
|
|||
}
|
||||
}
|
||||
|
||||
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = preferenceName)
|
||||
private val store: DataStore<Preferences> = factory.create(preferenceName)
|
||||
private val pushProviderName = stringPreferencesKey("pushProviderName")
|
||||
private val currentPushKey = stringPreferencesKey("currentPushKey")
|
||||
private val notificationEnabled = booleanPreferencesKey("notificationEnabled")
|
||||
private val ignoreRegistrationError = booleanPreferencesKey("ignoreRegistrationError")
|
||||
|
||||
override suspend fun getPushProviderName(): String? {
|
||||
return context.dataStore.data.first()[pushProviderName]
|
||||
return store.data.first()[pushProviderName]
|
||||
}
|
||||
|
||||
override suspend fun setPushProviderName(value: String) {
|
||||
context.dataStore.edit {
|
||||
store.edit {
|
||||
it[pushProviderName] = value
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getCurrentRegisteredPushKey(): String? {
|
||||
return context.dataStore.data.first()[currentPushKey]
|
||||
return store.data.first()[currentPushKey]
|
||||
}
|
||||
|
||||
override suspend fun setCurrentRegisteredPushKey(value: String?) {
|
||||
context.dataStore.edit {
|
||||
store.edit {
|
||||
if (value == null) {
|
||||
it.remove(currentPushKey)
|
||||
} else {
|
||||
|
|
@ -80,11 +81,11 @@ class UserPushStoreDataStore(
|
|||
}
|
||||
|
||||
override fun getNotificationEnabledForDevice(): Flow<Boolean> {
|
||||
return context.dataStore.data.map { it[notificationEnabled].orTrue() }
|
||||
return store.data.map { it[notificationEnabled].orTrue() }
|
||||
}
|
||||
|
||||
override suspend fun setNotificationEnabledForDevice(enabled: Boolean) {
|
||||
context.dataStore.edit {
|
||||
store.edit {
|
||||
it[notificationEnabled] = enabled
|
||||
}
|
||||
}
|
||||
|
|
@ -94,17 +95,17 @@ class UserPushStoreDataStore(
|
|||
}
|
||||
|
||||
override fun ignoreRegistrationError(): Flow<Boolean> {
|
||||
return context.dataStore.data.map { it[ignoreRegistrationError].orFalse() }
|
||||
return store.data.map { it[ignoreRegistrationError].orFalse() }
|
||||
}
|
||||
|
||||
override suspend fun setIgnoreRegistrationError(ignore: Boolean) {
|
||||
context.dataStore.edit {
|
||||
store.edit {
|
||||
it[ignoreRegistrationError] = ignore
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun reset() {
|
||||
context.dataStore.edit {
|
||||
store.edit {
|
||||
it.clear()
|
||||
}
|
||||
// Also delete the file
|
||||
|
|
|
|||
|
|
@ -7,44 +7,40 @@
|
|||
|
||||
package io.element.android.libraries.pushstore.impl.clientsecret
|
||||
|
||||
import android.content.Context
|
||||
import androidx.datastore.core.DataStore
|
||||
import androidx.datastore.preferences.core.Preferences
|
||||
import androidx.datastore.preferences.core.edit
|
||||
import androidx.datastore.preferences.core.stringPreferencesKey
|
||||
import androidx.datastore.preferences.preferencesDataStore
|
||||
import com.squareup.anvil.annotations.ContributesBinding
|
||||
import io.element.android.libraries.di.AppScope
|
||||
import io.element.android.libraries.di.ApplicationContext
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.preferences.api.store.PreferenceDataStoreFactory
|
||||
import io.element.android.libraries.pushstore.api.clientsecret.PushClientSecretStore
|
||||
import kotlinx.coroutines.flow.first
|
||||
import javax.inject.Inject
|
||||
|
||||
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "push_client_secret_store")
|
||||
|
||||
@ContributesBinding(AppScope::class)
|
||||
class DataStorePushClientSecretStore @Inject constructor(
|
||||
@ApplicationContext private val context: Context,
|
||||
preferenceDataStoreFactory: PreferenceDataStoreFactory,
|
||||
) : PushClientSecretStore {
|
||||
private val dataStore = preferenceDataStoreFactory.create("push_client_secret_store")
|
||||
|
||||
override suspend fun storeSecret(userId: SessionId, clientSecret: String) {
|
||||
context.dataStore.edit { settings ->
|
||||
dataStore.edit { settings ->
|
||||
settings[getPreferenceKeyForUser(userId)] = clientSecret
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getSecret(userId: SessionId): String? {
|
||||
return context.dataStore.data.first()[getPreferenceKeyForUser(userId)]
|
||||
return dataStore.data.first()[getPreferenceKeyForUser(userId)]
|
||||
}
|
||||
|
||||
override suspend fun resetSecret(userId: SessionId) {
|
||||
context.dataStore.edit { settings ->
|
||||
dataStore.edit { settings ->
|
||||
settings.remove(getPreferenceKeyForUser(userId))
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getUserIdFromSecret(clientSecret: String): SessionId? {
|
||||
val keyValues = context.dataStore.data.first().asMap()
|
||||
val keyValues = dataStore.data.first().asMap()
|
||||
val matchingKey = keyValues.keys.find {
|
||||
keyValues[it] == clientSecret
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import com.google.common.truth.Truth.assertThat
|
|||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID
|
||||
import io.element.android.libraries.matrix.test.A_SESSION_ID_2
|
||||
import io.element.android.libraries.preferences.test.FakePreferenceDataStoreFactory
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Test
|
||||
|
|
@ -92,5 +93,6 @@ class UserPushStoreDataStoreTest {
|
|||
) = UserPushStoreDataStore(
|
||||
context = InstrumentationRegistry.getInstrumentation().context,
|
||||
userId = sessionId,
|
||||
factory = FakePreferenceDataStoreFactory(),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue