mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-10-31 08:15:02 +00:00
Remove verification listeners of logged out sessions
- Clear the listener when RustSessionVerificationService is destroyed. - IncomingVerificationRequestObserver removes the listener of the clients which are not in the MatrixSessionCache anymore. - Remove the sessions from the MatrixSessionCache when they are removed from the SessionStore (logout, account deactivation). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -84,6 +84,7 @@ import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.runningFold
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withTimeoutOrNull
|
||||
import kotlinx.parcelize.Parcelize
|
||||
@@ -138,6 +139,7 @@ class RootFlowNode(
|
||||
}
|
||||
}
|
||||
observeIncomingVerificationRequests()
|
||||
observeRemovedSessions()
|
||||
super.onBuilt()
|
||||
}
|
||||
|
||||
@@ -230,6 +232,22 @@ class RootFlowNode(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove from the cache the sessions which have been removed from the session store, for instance after a logout.
|
||||
*/
|
||||
private fun observeRemovedSessions() {
|
||||
sessionStore.sessionsFlow()
|
||||
.map { sessions -> sessions.map { SessionId(it.userId) }.toSet() }
|
||||
.runningFold(emptySet<SessionId>() to emptySet<SessionId>()) { (_, previous), current -> previous to current }
|
||||
.onEach { (previous, current) ->
|
||||
(previous - current).forEach { sessionId ->
|
||||
Timber.d("Session $sessionId removed, remove it from the cache")
|
||||
matrixSessionCache.remove(sessionId)
|
||||
}
|
||||
}
|
||||
.launchIn(lifecycleScope)
|
||||
}
|
||||
|
||||
private fun observeIncomingVerificationRequests() {
|
||||
incomingVerificationRequestObserver.incomingVerificationRequests()
|
||||
.onEach(::onIncomingVerificationRequest)
|
||||
|
||||
+8
-2
@@ -9,6 +9,7 @@ package io.element.android.appnav.verification
|
||||
|
||||
import dev.zacsweers.metro.Inject
|
||||
import io.element.android.appnav.session.MatrixSessionCache
|
||||
import io.element.android.libraries.core.coroutine.withPreviousValue
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationServiceListener
|
||||
import io.element.android.libraries.matrix.api.verification.VerificationRequest
|
||||
@@ -41,8 +42,13 @@ class IncomingVerificationRequestObserver(
|
||||
*/
|
||||
fun incomingVerificationRequests(): Flow<IncomingVerificationRequestData> = channelFlow {
|
||||
launch {
|
||||
matrixSessionCache.matrixClients.collect { matrixClients ->
|
||||
matrixClients.forEach { matrixClient ->
|
||||
matrixSessionCache.matrixClients.withPreviousValue().collect { (previousMatrixClients, matrixClients) ->
|
||||
val previousMatrixClientSet = previousMatrixClients.orEmpty().toSet()
|
||||
// Remove the listener of the clients which are not in the cache anymore
|
||||
(previousMatrixClientSet - matrixClients.toSet()).forEach { matrixClient ->
|
||||
matrixClient.sessionVerificationService.setListener(null)
|
||||
}
|
||||
(matrixClients - previousMatrixClientSet).forEach { matrixClient ->
|
||||
val sessionId = matrixClient.sessionId
|
||||
matrixClient.sessionVerificationService.setListener(
|
||||
object : SessionVerificationServiceListener {
|
||||
|
||||
+20
@@ -63,6 +63,26 @@ class IncomingVerificationRequestObserverTest {
|
||||
assertThat(sessionVerificationService2.listener).isNull()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `listener is removed when the session is removed from the cache`() = runTest {
|
||||
val matrixSessionCache = createMatrixSessionCache()
|
||||
val observer = IncomingVerificationRequestObserver(
|
||||
matrixSessionCache = matrixSessionCache,
|
||||
appForegroundStateService = FakeAppForegroundStateService(),
|
||||
)
|
||||
observer.incomingVerificationRequests().test {
|
||||
matrixSessionCache.getOrRestore(A_SESSION_ID)
|
||||
matrixSessionCache.getOrRestore(A_SESSION_ID_2)
|
||||
runCurrent()
|
||||
assertThat(sessionVerificationService1.listener).isNotNull()
|
||||
assertThat(sessionVerificationService2.listener).isNotNull()
|
||||
matrixSessionCache.remove(A_SESSION_ID)
|
||||
runCurrent()
|
||||
assertThat(sessionVerificationService1.listener).isNull()
|
||||
assertThat(sessionVerificationService2.listener).isNotNull()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `incoming verification request is emitted when the app goes to foreground`() = runTest {
|
||||
val matrixSessionCache = createMatrixSessionCache()
|
||||
|
||||
Reference in New Issue
Block a user