Browse Source

Close the client before deleting data, and ensure the app is restarted, using a cache Index.

feature/julioromano/geocoding_api
Benoit Marty 1 year ago committed by Benoit Marty
parent
commit
979ebe4adb
  1. 21
      appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt
  2. 5
      features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt
  3. 4
      libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt
  4. 7
      libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt
  5. 6
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt
  6. 10
      libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt

21
appnav/src/main/kotlin/io/element/android/appnav/RootFlowNode.kt

@ -54,7 +54,9 @@ import io.element.android.libraries.di.AppScope @@ -54,7 +54,9 @@ import io.element.android.libraries.di.AppScope
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
import io.element.android.libraries.matrix.api.core.SessionId
import io.element.android.libraries.matrix.api.core.UserId
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.parcelize.Parcelize
@ -88,11 +90,17 @@ class RootFlowNode @AssistedInject constructor( @@ -88,11 +90,17 @@ class RootFlowNode @AssistedInject constructor(
private fun observeLoggedInState() {
authenticationService.isLoggedIn()
.distinctUntilChanged()
.combine(
authenticationService.cacheIdx().onEach {
Timber.v("cacheIdx=$it")
matrixClientsHolder.removeAll()
}
) { isLoggedIn, cacheIdx -> isLoggedIn to cacheIdx }
.onEach { isLoggedIn ->
Timber.v("isLoggedIn=$isLoggedIn")
if (isLoggedIn) {
if (isLoggedIn.first) {
tryToRestoreLatestSession(
onSuccess = { switchToLoggedInFlow(it) },
onSuccess = { switchToLoggedInFlow(it, isLoggedIn.second) },
onFailure = { switchToNotLoggedInFlow() }
)
} else {
@ -102,8 +110,8 @@ class RootFlowNode @AssistedInject constructor( @@ -102,8 +110,8 @@ class RootFlowNode @AssistedInject constructor(
.launchIn(lifecycleScope)
}
private fun switchToLoggedInFlow(sessionId: SessionId) {
backstack.safeRoot(NavTarget.LoggedInFlow(sessionId))
private fun switchToLoggedInFlow(sessionId: SessionId, cacheIndex: Int) {
backstack.safeRoot(NavTarget.LoggedInFlow(sessionId, cacheIndex))
}
private fun switchToNotLoggedInFlow() {
@ -163,7 +171,7 @@ class RootFlowNode @AssistedInject constructor( @@ -163,7 +171,7 @@ class RootFlowNode @AssistedInject constructor(
object NotLoggedInFlow : NavTarget
@Parcelize
data class LoggedInFlow(val sessionId: SessionId) : NavTarget
data class LoggedInFlow(val sessionId: SessionId, val cacheIndex: Int) : NavTarget
@Parcelize
object BugReport : NavTarget
@ -235,8 +243,9 @@ class RootFlowNode @AssistedInject constructor( @@ -235,8 +243,9 @@ class RootFlowNode @AssistedInject constructor(
}
private suspend fun attachSession(sessionId: SessionId): LoggedInFlowNode {
val cacheIdx = authenticationService.cacheIdx().first()
return attachChild {
backstack.newRoot(NavTarget.LoggedInFlow(sessionId))
backstack.newRoot(NavTarget.LoggedInFlow(sessionId, cacheIdx))
}
}
}

5
features/preferences/impl/src/main/kotlin/io/element/android/features/preferences/impl/tasks/ClearCacheUseCase.kt

@ -22,6 +22,7 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers @@ -22,6 +22,7 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.di.ApplicationContext
import io.element.android.libraries.di.SessionScope
import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
import kotlinx.coroutines.withContext
import javax.inject.Inject
@ -34,11 +35,11 @@ class DefaultClearCacheUseCase @Inject constructor( @@ -34,11 +35,11 @@ class DefaultClearCacheUseCase @Inject constructor(
@ApplicationContext private val context: Context,
private val matrixClient: MatrixClient,
private val coroutineDispatchers: CoroutineDispatchers,
private val authenticationService: MatrixAuthenticationService,
) : ClearCacheUseCase {
override suspend fun execute() = withContext(coroutineDispatchers.io) {
matrixClient.stopSync()
matrixClient.clearCache()
context.cacheDir.deleteRecursively()
matrixClient.startSync()
authenticationService.incrementCacheIdx()
}
}

4
libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/MatrixClient.kt

@ -51,6 +51,10 @@ interface MatrixClient : Closeable { @@ -51,6 +51,10 @@ interface MatrixClient : Closeable {
fun pushersService(): PushersService
fun notificationService(): NotificationService
suspend fun getCacheSize(): Long
/**
* Will close the client and delete the cache data.
*/
suspend fun clearCache()
suspend fun logout()
suspend fun loadUserDisplayName(): Result<String>

7
libraries/matrix/api/src/main/kotlin/io/element/android/libraries/matrix/api/auth/MatrixAuthenticationService.kt

@ -29,6 +29,13 @@ interface MatrixAuthenticationService { @@ -29,6 +29,13 @@ interface MatrixAuthenticationService {
suspend fun setHomeserver(homeserver: String): Result<Unit>
suspend fun login(username: String, password: String): Result<SessionId>
/*
* Cache index
*/
fun cacheIdx(): Flow<Int>
fun incrementCacheIdx()
/*
* OIDC part.
*/

6
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt

@ -339,11 +339,13 @@ class RustMatrixClient constructor( @@ -339,11 +339,13 @@ class RustMatrixClient constructor(
}
override suspend fun getCacheSize(): Long {
return baseDirectory.getCacheSize(userID = client.userId())
// Do not use client.userId since it can throw if client has been closed (during clear cache)
return baseDirectory.getCacheSize(userID = sessionId.value)
}
override suspend fun clearCache() {
baseDirectory.deleteSessionDirectory(userID = client.userId())
close()
baseDirectory.deleteSessionDirectory(userID = sessionId.value, deleteCryptoDb = false)
}
override suspend fun logout() = withContext(dispatchers.io) {

10
libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/auth/RustMatrixAuthenticationService.kt

@ -58,6 +58,8 @@ class RustMatrixAuthenticationService @Inject constructor( @@ -58,6 +58,8 @@ class RustMatrixAuthenticationService @Inject constructor(
private val clock: SystemClock,
) : MatrixAuthenticationService {
private val cacheIdxState = MutableStateFlow(0)
private val authService: RustAuthenticationService = RustAuthenticationService(
basePath = baseDirectory.absolutePath,
passphrase = null,
@ -71,6 +73,14 @@ class RustMatrixAuthenticationService @Inject constructor( @@ -71,6 +73,14 @@ class RustMatrixAuthenticationService @Inject constructor(
return sessionStore.isLoggedIn()
}
override fun incrementCacheIdx() {
cacheIdxState.value++
}
override fun cacheIdx(): Flow<Int> {
return cacheIdxState
}
override suspend fun getLatestSessionId(): SessionId? = withContext(coroutineDispatchers.io) {
sessionStore.getLatestSession()?.userId?.let { SessionId(it) }
}

Loading…
Cancel
Save