mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-03 06:55:41 +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.launchIn
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.flow.runningFold
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
@@ -138,6 +139,7 @@ class RootFlowNode(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
observeIncomingVerificationRequests()
|
observeIncomingVerificationRequests()
|
||||||
|
observeRemovedSessions()
|
||||||
super.onBuilt()
|
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() {
|
private fun observeIncomingVerificationRequests() {
|
||||||
incomingVerificationRequestObserver.incomingVerificationRequests()
|
incomingVerificationRequestObserver.incomingVerificationRequests()
|
||||||
.onEach(::onIncomingVerificationRequest)
|
.onEach(::onIncomingVerificationRequest)
|
||||||
|
|||||||
+8
-2
@@ -9,6 +9,7 @@ package io.element.android.appnav.verification
|
|||||||
|
|
||||||
import dev.zacsweers.metro.Inject
|
import dev.zacsweers.metro.Inject
|
||||||
import io.element.android.appnav.session.MatrixSessionCache
|
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.core.SessionId
|
||||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationServiceListener
|
import io.element.android.libraries.matrix.api.verification.SessionVerificationServiceListener
|
||||||
import io.element.android.libraries.matrix.api.verification.VerificationRequest
|
import io.element.android.libraries.matrix.api.verification.VerificationRequest
|
||||||
@@ -41,8 +42,13 @@ class IncomingVerificationRequestObserver(
|
|||||||
*/
|
*/
|
||||||
fun incomingVerificationRequests(): Flow<IncomingVerificationRequestData> = channelFlow {
|
fun incomingVerificationRequests(): Flow<IncomingVerificationRequestData> = channelFlow {
|
||||||
launch {
|
launch {
|
||||||
matrixSessionCache.matrixClients.collect { matrixClients ->
|
matrixSessionCache.matrixClients.withPreviousValue().collect { (previousMatrixClients, matrixClients) ->
|
||||||
matrixClients.forEach { matrixClient ->
|
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
|
val sessionId = matrixClient.sessionId
|
||||||
matrixClient.sessionVerificationService.setListener(
|
matrixClient.sessionVerificationService.setListener(
|
||||||
object : SessionVerificationServiceListener {
|
object : SessionVerificationServiceListener {
|
||||||
|
|||||||
+20
@@ -63,6 +63,26 @@ class IncomingVerificationRequestObserverTest {
|
|||||||
assertThat(sessionVerificationService2.listener).isNull()
|
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
|
@Test
|
||||||
fun `incoming verification request is emitted when the app goes to foreground`() = runTest {
|
fun `incoming verification request is emitted when the app goes to foreground`() = runTest {
|
||||||
val matrixSessionCache = createMatrixSessionCache()
|
val matrixSessionCache = createMatrixSessionCache()
|
||||||
|
|||||||
+1
@@ -245,6 +245,7 @@ class RustSessionVerificationService(
|
|||||||
|
|
||||||
fun destroy() {
|
fun destroy() {
|
||||||
Timber.d("Destroying RustSessionVerificationService")
|
Timber.d("Destroying RustSessionVerificationService")
|
||||||
|
listener = null
|
||||||
verificationStateListenerTaskHandle.cancelAndDestroy()
|
verificationStateListenerTaskHandle.cancelAndDestroy()
|
||||||
recoveryStateListenerTaskHandle.cancelAndDestroy()
|
recoveryStateListenerTaskHandle.cancelAndDestroy()
|
||||||
if (this::verificationController.isInitialized) {
|
if (this::verificationController.isInitialized) {
|
||||||
|
|||||||
Reference in New Issue
Block a user