Close the client before deleting data, and ensure the app is restarted, using a cache Index.
This commit is contained in:
parent
4b8d11b7e4
commit
58860a9440
6 changed files with 43 additions and 10 deletions
|
|
@ -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.auth.MatrixAuthenticationService
|
||||||
import io.element.android.libraries.matrix.api.core.SessionId
|
import io.element.android.libraries.matrix.api.core.SessionId
|
||||||
import io.element.android.libraries.matrix.api.core.UserId
|
import io.element.android.libraries.matrix.api.core.UserId
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
|
@ -88,11 +90,17 @@ class RootFlowNode @AssistedInject constructor(
|
||||||
private fun observeLoggedInState() {
|
private fun observeLoggedInState() {
|
||||||
authenticationService.isLoggedIn()
|
authenticationService.isLoggedIn()
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
|
.combine(
|
||||||
|
authenticationService.cacheIdx().onEach {
|
||||||
|
Timber.v("cacheIdx=$it")
|
||||||
|
matrixClientsHolder.removeAll()
|
||||||
|
}
|
||||||
|
) { isLoggedIn, cacheIdx -> isLoggedIn to cacheIdx }
|
||||||
.onEach { isLoggedIn ->
|
.onEach { isLoggedIn ->
|
||||||
Timber.v("isLoggedIn=$isLoggedIn")
|
Timber.v("isLoggedIn=$isLoggedIn")
|
||||||
if (isLoggedIn) {
|
if (isLoggedIn.first) {
|
||||||
tryToRestoreLatestSession(
|
tryToRestoreLatestSession(
|
||||||
onSuccess = { switchToLoggedInFlow(it) },
|
onSuccess = { switchToLoggedInFlow(it, isLoggedIn.second) },
|
||||||
onFailure = { switchToNotLoggedInFlow() }
|
onFailure = { switchToNotLoggedInFlow() }
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -102,8 +110,8 @@ class RootFlowNode @AssistedInject constructor(
|
||||||
.launchIn(lifecycleScope)
|
.launchIn(lifecycleScope)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun switchToLoggedInFlow(sessionId: SessionId) {
|
private fun switchToLoggedInFlow(sessionId: SessionId, cacheIndex: Int) {
|
||||||
backstack.safeRoot(NavTarget.LoggedInFlow(sessionId))
|
backstack.safeRoot(NavTarget.LoggedInFlow(sessionId, cacheIndex))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun switchToNotLoggedInFlow() {
|
private fun switchToNotLoggedInFlow() {
|
||||||
|
|
@ -163,7 +171,7 @@ class RootFlowNode @AssistedInject constructor(
|
||||||
object NotLoggedInFlow : NavTarget
|
object NotLoggedInFlow : NavTarget
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class LoggedInFlow(val sessionId: SessionId) : NavTarget
|
data class LoggedInFlow(val sessionId: SessionId, val cacheIndex: Int) : NavTarget
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
object BugReport : NavTarget
|
object BugReport : NavTarget
|
||||||
|
|
@ -235,8 +243,9 @@ class RootFlowNode @AssistedInject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun attachSession(sessionId: SessionId): LoggedInFlowNode {
|
private suspend fun attachSession(sessionId: SessionId): LoggedInFlowNode {
|
||||||
|
val cacheIdx = authenticationService.cacheIdx().first()
|
||||||
return attachChild {
|
return attachChild {
|
||||||
backstack.newRoot(NavTarget.LoggedInFlow(sessionId))
|
backstack.newRoot(NavTarget.LoggedInFlow(sessionId, cacheIdx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.ApplicationContext
|
||||||
import io.element.android.libraries.di.SessionScope
|
import io.element.android.libraries.di.SessionScope
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
import io.element.android.libraries.matrix.api.auth.MatrixAuthenticationService
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -34,11 +35,11 @@ class DefaultClearCacheUseCase @Inject constructor(
|
||||||
@ApplicationContext private val context: Context,
|
@ApplicationContext private val context: Context,
|
||||||
private val matrixClient: MatrixClient,
|
private val matrixClient: MatrixClient,
|
||||||
private val coroutineDispatchers: CoroutineDispatchers,
|
private val coroutineDispatchers: CoroutineDispatchers,
|
||||||
|
private val authenticationService: MatrixAuthenticationService,
|
||||||
) : ClearCacheUseCase {
|
) : ClearCacheUseCase {
|
||||||
override suspend fun execute() = withContext(coroutineDispatchers.io) {
|
override suspend fun execute() = withContext(coroutineDispatchers.io) {
|
||||||
matrixClient.stopSync()
|
|
||||||
matrixClient.clearCache()
|
matrixClient.clearCache()
|
||||||
context.cacheDir.deleteRecursively()
|
context.cacheDir.deleteRecursively()
|
||||||
matrixClient.startSync()
|
authenticationService.incrementCacheIdx()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,10 @@ interface MatrixClient : Closeable {
|
||||||
fun pushersService(): PushersService
|
fun pushersService(): PushersService
|
||||||
fun notificationService(): NotificationService
|
fun notificationService(): NotificationService
|
||||||
suspend fun getCacheSize(): Long
|
suspend fun getCacheSize(): Long
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will close the client and delete the cache data.
|
||||||
|
*/
|
||||||
suspend fun clearCache()
|
suspend fun clearCache()
|
||||||
suspend fun logout()
|
suspend fun logout()
|
||||||
suspend fun loadUserDisplayName(): Result<String>
|
suspend fun loadUserDisplayName(): Result<String>
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,13 @@ interface MatrixAuthenticationService {
|
||||||
suspend fun setHomeserver(homeserver: String): Result<Unit>
|
suspend fun setHomeserver(homeserver: String): Result<Unit>
|
||||||
suspend fun login(username: String, password: String): Result<SessionId>
|
suspend fun login(username: String, password: String): Result<SessionId>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cache index
|
||||||
|
*/
|
||||||
|
|
||||||
|
fun cacheIdx(): Flow<Int>
|
||||||
|
fun incrementCacheIdx()
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* OIDC part.
|
* OIDC part.
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -339,11 +339,13 @@ class RustMatrixClient constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getCacheSize(): Long {
|
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() {
|
override suspend fun clearCache() {
|
||||||
baseDirectory.deleteSessionDirectory(userID = client.userId())
|
close()
|
||||||
|
baseDirectory.deleteSessionDirectory(userID = sessionId.value, deleteCryptoDb = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun logout() = withContext(dispatchers.io) {
|
override suspend fun logout() = withContext(dispatchers.io) {
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,8 @@ class RustMatrixAuthenticationService @Inject constructor(
|
||||||
private val clock: SystemClock,
|
private val clock: SystemClock,
|
||||||
) : MatrixAuthenticationService {
|
) : MatrixAuthenticationService {
|
||||||
|
|
||||||
|
private val cacheIdxState = MutableStateFlow(0)
|
||||||
|
|
||||||
private val authService: RustAuthenticationService = RustAuthenticationService(
|
private val authService: RustAuthenticationService = RustAuthenticationService(
|
||||||
basePath = baseDirectory.absolutePath,
|
basePath = baseDirectory.absolutePath,
|
||||||
passphrase = null,
|
passphrase = null,
|
||||||
|
|
@ -71,6 +73,14 @@ class RustMatrixAuthenticationService @Inject constructor(
|
||||||
return sessionStore.isLoggedIn()
|
return sessionStore.isLoggedIn()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun incrementCacheIdx() {
|
||||||
|
cacheIdxState.value++
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun cacheIdx(): Flow<Int> {
|
||||||
|
return cacheIdxState
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun getLatestSessionId(): SessionId? = withContext(coroutineDispatchers.io) {
|
override suspend fun getLatestSessionId(): SessionId? = withContext(coroutineDispatchers.io) {
|
||||||
sessionStore.getLatestSession()?.userId?.let { SessionId(it) }
|
sessionStore.getLatestSession()?.userId?.let { SessionId(it) }
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue