Try to centralise session restoration through MatrixClientsHolder
This commit is contained in:
parent
d69dea6608
commit
ded1518f0b
5 changed files with 36 additions and 21 deletions
|
|
@ -145,14 +145,10 @@ class RootFlowNode @AssistedInject constructor(
|
||||||
onFailure: () -> Unit = {},
|
onFailure: () -> Unit = {},
|
||||||
onSuccess: (SessionId) -> Unit = {},
|
onSuccess: (SessionId) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
// If the session is already known it'll be restored by the node hierarchy
|
runCatching {
|
||||||
if (matrixClientsHolder.knowSession(sessionId)) {
|
matrixClientsHolder.requireSession(sessionId)
|
||||||
Timber.v("Session $sessionId already alive, no need to restore.")
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
authenticationService.restoreSession(sessionId)
|
.onSuccess {
|
||||||
.onSuccess { matrixClient ->
|
|
||||||
matrixClientsHolder.add(matrixClient)
|
|
||||||
Timber.v("Succeed to restore session $sessionId")
|
Timber.v("Succeed to restore session $sessionId")
|
||||||
onSuccess(sessionId)
|
onSuccess(sessionId)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,6 +35,6 @@ fun Throwable.mapAuthenticationException(): Throwable {
|
||||||
is RustAuthenticationException.OidcNotSupported -> AuthenticationException.OidcError("OidcNotSupported", message!!)
|
is RustAuthenticationException.OidcNotSupported -> AuthenticationException.OidcError("OidcNotSupported", message!!)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
else -> this
|
else -> AuthenticationException.Generic(this.message ?: "Unknown error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -21,12 +21,16 @@ import com.bumble.appyx.core.state.SavedStateMap
|
||||||
import io.element.android.libraries.di.AppScope
|
import io.element.android.libraries.di.AppScope
|
||||||
import io.element.android.libraries.di.SingleIn
|
import io.element.android.libraries.di.SingleIn
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
import io.element.android.libraries.matrix.api.auth.AuthenticationException
|
||||||
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 kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
import kotlinx.coroutines.sync.withLock
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlin.jvm.Throws
|
||||||
|
|
||||||
private const val SAVE_INSTANCE_KEY = "io.element.android.x.di.MatrixClientsHolder.SaveInstanceKey"
|
private const val SAVE_INSTANCE_KEY = "io.element.android.x.di.MatrixClientsHolder.SaveInstanceKey"
|
||||||
|
|
||||||
|
|
@ -34,8 +38,9 @@ private const val SAVE_INSTANCE_KEY = "io.element.android.x.di.MatrixClientsHold
|
||||||
class MatrixClientsHolder @Inject constructor(private val authenticationService: MatrixAuthenticationService) {
|
class MatrixClientsHolder @Inject constructor(private val authenticationService: MatrixAuthenticationService) {
|
||||||
|
|
||||||
private val sessionIdsToMatrixClient = ConcurrentHashMap<SessionId, MatrixClient>()
|
private val sessionIdsToMatrixClient = ConcurrentHashMap<SessionId, MatrixClient>()
|
||||||
|
private val restoreMutex = Mutex()
|
||||||
|
|
||||||
fun add(matrixClient: MatrixClient) {
|
private fun add(matrixClient: MatrixClient) {
|
||||||
sessionIdsToMatrixClient[matrixClient.sessionId] = matrixClient
|
sessionIdsToMatrixClient[matrixClient.sessionId] = matrixClient
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -55,6 +60,27 @@ class MatrixClientsHolder @Inject constructor(private val authenticationService:
|
||||||
return sessionIdsToMatrixClient[sessionId]
|
return sessionIdsToMatrixClient[sessionId]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Throws(AuthenticationException::class)
|
||||||
|
suspend fun requireSession(sessionId: SessionId): MatrixClient {
|
||||||
|
return restoreMutex.withLock {
|
||||||
|
when (val matrixClient = sessionIdsToMatrixClient[sessionId]) {
|
||||||
|
null -> restore(sessionId).getOrThrow()
|
||||||
|
else -> matrixClient
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun restore(sessionId: SessionId): Result<MatrixClient> {
|
||||||
|
Timber.d("Restore matrix session: $sessionId")
|
||||||
|
return authenticationService.restoreSession(sessionId)
|
||||||
|
.onSuccess { matrixClient ->
|
||||||
|
add(matrixClient)
|
||||||
|
}
|
||||||
|
.onFailure {
|
||||||
|
Timber.e("Fail to restore session")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
fun restore(state: SavedStateMap?) {
|
fun restore(state: SavedStateMap?) {
|
||||||
Timber.d("Restore state")
|
Timber.d("Restore state")
|
||||||
|
|
@ -67,14 +93,7 @@ class MatrixClientsHolder @Inject constructor(private val authenticationService:
|
||||||
// Not ideal but should only happens in case of process recreation. This ensure we restore all the active sessions before restoring the node graphs.
|
// Not ideal but should only happens in case of process recreation. This ensure we restore all the active sessions before restoring the node graphs.
|
||||||
runBlocking {
|
runBlocking {
|
||||||
sessionIds.forEach { sessionId ->
|
sessionIds.forEach { sessionId ->
|
||||||
Timber.d("Restore matrix session: $sessionId")
|
restore(sessionId)
|
||||||
authenticationService.restoreSession(sessionId)
|
|
||||||
.onSuccess { matrixClient ->
|
|
||||||
add(matrixClient)
|
|
||||||
}
|
|
||||||
.onFailure {
|
|
||||||
Timber.e("Fail to restore session")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -257,11 +257,11 @@ class DefaultNotificationDrawerManager @Inject constructor(
|
||||||
val currentUser = tryOrNull(
|
val currentUser = tryOrNull(
|
||||||
onError = { Timber.e(it, "Unable to retrieve info for user ${sessionId.value}") },
|
onError = { Timber.e(it, "Unable to retrieve info for user ${sessionId.value}") },
|
||||||
operation = {
|
operation = {
|
||||||
val client = matrixClientsHolder.getOrNull(sessionId)
|
val client = matrixClientsHolder.requireSession(sessionId)
|
||||||
|
|
||||||
// myUserDisplayName cannot be empty else NotificationCompat.MessagingStyle() will crash
|
// myUserDisplayName cannot be empty else NotificationCompat.MessagingStyle() will crash
|
||||||
val myUserDisplayName = client?.loadUserDisplayName()?.getOrNull() ?: sessionId.value
|
val myUserDisplayName = client.loadUserDisplayName().getOrNull() ?: sessionId.value
|
||||||
val userAvatarUrl = client?.loadUserAvatarURLString()?.getOrNull()
|
val userAvatarUrl = client.loadUserAvatarURLString().getOrNull()
|
||||||
MatrixUser(
|
MatrixUser(
|
||||||
userId = sessionId,
|
userId = sessionId,
|
||||||
displayName = myUserDisplayName,
|
displayName = myUserDisplayName,
|
||||||
|
|
|
||||||
|
|
@ -68,7 +68,7 @@ class NotifiableEventResolver @Inject constructor(
|
||||||
|
|
||||||
suspend fun resolveEvent(sessionId: SessionId, roomId: RoomId, eventId: EventId): NotifiableEvent? {
|
suspend fun resolveEvent(sessionId: SessionId, roomId: RoomId, eventId: EventId): NotifiableEvent? {
|
||||||
// Restore session
|
// Restore session
|
||||||
val client = matrixClientsHolder.getOrNull(sessionId) ?: return null
|
val client = matrixClientsHolder.requireSession(sessionId)
|
||||||
val notificationService = client.notificationService()
|
val notificationService = client.notificationService()
|
||||||
val notificationData = notificationService.getNotification(
|
val notificationData = notificationService.getNotification(
|
||||||
userId = sessionId,
|
userId = sessionId,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue