providing the onboarding store via session extension

- avoids needing to know about the user id for each read/write
This commit is contained in:
Adam Brown 2022-01-25 17:03:13 +00:00
parent b91b9cb973
commit 73b80b1c7d
4 changed files with 25 additions and 20 deletions

View file

@ -21,6 +21,7 @@ import androidx.core.content.ContextCompat
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.ProcessLifecycleOwner import androidx.lifecycle.ProcessLifecycleOwner
import im.vector.app.core.services.VectorSyncService import im.vector.app.core.services.VectorSyncService
import im.vector.app.features.onboarding.store.OnboardingStore
import org.matrix.android.sdk.api.session.Session import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState import org.matrix.android.sdk.api.session.crypto.keysbackup.KeysBackupState
import org.matrix.android.sdk.api.session.sync.FilterService import org.matrix.android.sdk.api.session.sync.FilterService
@ -76,3 +77,5 @@ fun Session.cannotLogoutSafely(): Boolean {
// That are not backed up // That are not backed up
!sharedSecretStorageService.isRecoverySetup()) !sharedSecretStorageService.isRecoverySetup())
} }
fun Session.onboardingStore(context: Context) = OnboardingStore(context, myUserId)

View file

@ -28,6 +28,7 @@ import dagger.hilt.android.AndroidEntryPoint
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.error.ErrorFormatter import im.vector.app.core.error.ErrorFormatter
import im.vector.app.core.extensions.onboardingStore
import im.vector.app.core.extensions.startSyncing import im.vector.app.core.extensions.startSyncing
import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.utils.deleteAllFiles import im.vector.app.core.utils.deleteAllFiles
@ -99,7 +100,6 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity
@Inject lateinit var pinLocker: PinLocker @Inject lateinit var pinLocker: PinLocker
@Inject lateinit var popupAlertManager: PopupAlertManager @Inject lateinit var popupAlertManager: PopupAlertManager
@Inject lateinit var vectorAnalytics: VectorAnalytics @Inject lateinit var vectorAnalytics: VectorAnalytics
@Inject lateinit var onboardingStore: OnboardingStore
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
@ -145,13 +145,15 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity
startNextActivityAndFinish() startNextActivityAndFinish()
return return
} }
val onboardingStore = session.onboardingStore(this)
when { when {
args.isAccountDeactivated -> { args.isAccountDeactivated -> {
lifecycleScope.launch { lifecycleScope.launch {
// Just do the local cleanup // Just do the local cleanup
Timber.w("Account deactivated, start app") Timber.w("Account deactivated, start app")
sessionHolder.clearActiveSession() sessionHolder.clearActiveSession()
doLocalCleanup(clearPreferences = true, userId = session.myUserId) doLocalCleanup(clearPreferences = true, onboardingStore)
startNextActivityAndFinish() startNextActivityAndFinish()
} }
} }
@ -165,14 +167,14 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity
} }
Timber.w("SIGN_OUT: success, start app") Timber.w("SIGN_OUT: success, start app")
sessionHolder.clearActiveSession() sessionHolder.clearActiveSession()
doLocalCleanup(clearPreferences = true, userId = session.myUserId) doLocalCleanup(clearPreferences = true, onboardingStore)
startNextActivityAndFinish() startNextActivityAndFinish()
} }
} }
args.clearCache -> { args.clearCache -> {
lifecycleScope.launch { lifecycleScope.launch {
session.clearCache() session.clearCache()
doLocalCleanup(clearPreferences = false, userId = session.myUserId) doLocalCleanup(clearPreferences = false, onboardingStore)
session.startSyncing(applicationContext) session.startSyncing(applicationContext)
startNextActivityAndFinish() startNextActivityAndFinish()
} }
@ -185,7 +187,7 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity
Timber.w("Ignoring invalid token global error") Timber.w("Ignoring invalid token global error")
} }
private suspend fun doLocalCleanup(clearPreferences: Boolean, userId: String) { private suspend fun doLocalCleanup(clearPreferences: Boolean, onboardingStore: OnboardingStore) {
// On UI Thread // On UI Thread
Glide.get(this@MainActivity).clearMemory() Glide.get(this@MainActivity).clearMemory()
@ -195,7 +197,7 @@ class MainActivity : VectorBaseActivity<ActivityMainBinding>(), UnlockedActivity
pinLocker.unlock() pinLocker.unlock()
pinCodeStore.deleteEncodedPin() pinCodeStore.deleteEncodedPin()
vectorAnalytics.onSignOut() vectorAnalytics.onSignOut()
onboardingStore.clear(userId) onboardingStore.clear()
} }
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
// On BG thread // On BG thread

View file

@ -32,6 +32,7 @@ import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.extensions.configureAndStart import im.vector.app.core.extensions.configureAndStart
import im.vector.app.core.extensions.exhaustive import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.onboardingStore
import im.vector.app.core.platform.VectorViewModel import im.vector.app.core.platform.VectorViewModel
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
import im.vector.app.core.utils.ensureTrailingSlash import im.vector.app.core.utils.ensureTrailingSlash
@ -45,7 +46,6 @@ import im.vector.app.features.login.LoginMode
import im.vector.app.features.login.ReAuthHelper import im.vector.app.features.login.ReAuthHelper
import im.vector.app.features.login.ServerType import im.vector.app.features.login.ServerType
import im.vector.app.features.login.SignMode import im.vector.app.features.login.SignMode
import im.vector.app.features.onboarding.store.OnboardingStore
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.MatrixPatterns.getDomain import org.matrix.android.sdk.api.MatrixPatterns.getDomain
@ -78,7 +78,6 @@ class OnboardingViewModel @AssistedInject constructor(
private val stringProvider: StringProvider, private val stringProvider: StringProvider,
private val homeServerHistoryService: HomeServerHistoryService, private val homeServerHistoryService: HomeServerHistoryService,
private val vectorFeatures: VectorFeatures, private val vectorFeatures: VectorFeatures,
private val onboardingStore: OnboardingStore,
private val analyticsTracker: AnalyticsTracker private val analyticsTracker: AnalyticsTracker
) : VectorViewModel<OnboardingViewState, OnboardingAction, OnboardingViewEvents>(initialState) { ) : VectorViewModel<OnboardingViewState, OnboardingAction, OnboardingViewEvents>(initialState) {
@ -754,7 +753,7 @@ class OnboardingViewModel @AssistedInject constructor(
private suspend fun onSessionCreated(session: Session) { private suspend fun onSessionCreated(session: Session) {
awaitState().useCase?.let { useCase -> awaitState().useCase?.let { useCase ->
onboardingStore.setUseCase(userId = session.myUserId, useCase) session.onboardingStore(applicationContext).setUseCase(useCase)
} }
activeSessionHolder.setActiveSession(session) activeSessionHolder.setActiveSession(session)

View file

@ -25,7 +25,6 @@ import androidx.datastore.preferences.preferencesDataStore
import im.vector.app.core.extensions.removeKeysWithPrefix import im.vector.app.core.extensions.removeKeysWithPrefix
import im.vector.app.features.onboarding.FtueUseCase import im.vector.app.features.onboarding.FtueUseCase
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import javax.inject.Inject
private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "vector_onboarding") private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = "vector_onboarding")
@ -33,27 +32,29 @@ private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(na
* Local storage for: * Local storage for:
* - messaging use case (Enum/String) * - messaging use case (Enum/String)
*/ */
class OnboardingStore @Inject constructor( class OnboardingStore constructor(
private val context: Context private val context: Context,
private val myUserId: String
) { ) {
suspend fun readUseCase(userId: String) = context.dataStore.data.first().let { preferences ->
preferences[userId.toUseCaseKey()]?.let { FtueUseCase.from(it) } suspend fun readUseCase() = context.dataStore.data.first().let { preferences ->
preferences[myUserId.toUseCaseKey()]?.let { FtueUseCase.from(it) }
} }
suspend fun setUseCase(userId: String, useCase: FtueUseCase) { suspend fun setUseCase(useCase: FtueUseCase) {
context.dataStore.edit { settings -> context.dataStore.edit { settings ->
settings[userId.toUseCaseKey()] = useCase.persistableValue settings[myUserId.toUseCaseKey()] = useCase.persistableValue
} }
} }
suspend fun resetUseCase(userId: String) { suspend fun resetUseCase() {
context.dataStore.edit { settings -> context.dataStore.edit { settings ->
settings.remove(userId.toUseCaseKey()) settings.remove(myUserId.toUseCaseKey())
} }
} }
suspend fun clear(userId: String) { suspend fun clear() {
context.dataStore.removeKeysWithPrefix(userId) context.dataStore.removeKeysWithPrefix(myUserId)
} }
private fun String.toUseCaseKey() = stringPreferencesKey("$this-use_case") private fun String.toUseCaseKey() = stringPreferencesKey("$this-use_case")