Merge branch 'develop' into feature/bma/leaveSpace

This commit is contained in:
Benoit Marty 2025-09-26 15:46:57 +02:00 committed by GitHub
commit 0e3efafa6d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
117 changed files with 2158 additions and 287 deletions

View file

@ -235,7 +235,6 @@ class RustMatrixClient(
private val _userProfile: MutableStateFlow<MatrixUser> = MutableStateFlow(
MatrixUser(
userId = sessionId,
// TODO cache for displayName?
displayName = null,
avatarUrl = null,
)
@ -264,6 +263,16 @@ class RustMatrixClient(
// Start notification settings
notificationSettingsService.start()
// Update the user profile in the session store if needed
sessionStore.getSession(sessionId.value)?.let { sessionData ->
_userProfile.emit(
MatrixUser(
userId = sessionId,
displayName = sessionData.userDisplayName,
avatarUrl = sessionData.userAvatarUrl,
)
)
}
// Force a refresh of the profile
getUserProfile()
}
@ -399,7 +408,15 @@ class RustMatrixClient(
}
override suspend fun getUserProfile(): Result<MatrixUser> = getProfile(sessionId)
.onSuccess { _userProfile.tryEmit(it) }
.onSuccess { matrixUser ->
_userProfile.emit(matrixUser)
// Also update our session storage
sessionStore.updateUserProfile(
sessionId = sessionId.value,
displayName = matrixUser.displayName,
avatarUrl = matrixUser.avatarUrl,
)
}
override suspend fun searchUsers(searchTerm: String, limit: Long): Result<MatrixSearchUserResults> =
withContext(sessionDispatcher) {

View file

@ -14,6 +14,7 @@ import org.matrix.rustcomponents.sdk.OidcException
fun Throwable.mapAuthenticationException(): AuthenticationException {
val message = this.message ?: "Unknown error"
return when (this) {
is AuthenticationException -> this
is ClientBuildException -> when (this) {
is ClientBuildException.Generic -> AuthenticationException.Generic(message)
is ClientBuildException.InvalidServerName -> AuthenticationException.InvalidServerName(message)

View file

@ -15,6 +15,7 @@ import io.element.android.libraries.core.coroutine.CoroutineDispatchers
import io.element.android.libraries.core.extensions.mapFailure
import io.element.android.libraries.core.extensions.runCatchingExceptions
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.MatrixHomeServerDetails
import io.element.android.libraries.matrix.api.auth.OidcDetails
@ -139,6 +140,8 @@ class RustMatrixAuthenticationService(
val client = currentClient ?: error("You need to call `setHomeserver()` first")
val currentSessionPaths = sessionPaths ?: error("You need to call `setHomeserver()` first")
client.login(username, password, "Element X Android", null)
// Ensure that the user is not already logged in with the same account
ensureNotAlreadyLoggedIn(client)
val sessionData = client.session()
.toSessionData(
isTokenValid = true,
@ -227,17 +230,19 @@ class RustMatrixAuthenticationService(
val client = currentClient ?: error("You need to call `setHomeserver()` first")
val currentSessionPaths = sessionPaths ?: error("You need to call `setHomeserver()` first")
client.loginWithOidcCallback(callbackUrl)
// Free the pending data since we won't use it to abort the flow anymore
pendingOAuthAuthorizationData?.close()
pendingOAuthAuthorizationData = null
// Ensure that the user is not already logged in with the same account
ensureNotAlreadyLoggedIn(client)
val sessionData = client.session().toSessionData(
isTokenValid = true,
loginType = LoginType.OIDC,
passphrase = pendingPassphrase,
sessionPaths = currentSessionPaths,
)
// Free the pending data since we won't use it to abort the flow anymore
pendingOAuthAuthorizationData?.close()
pendingOAuthAuthorizationData = null
val matrixClient = rustMatrixClientFactory.create(client)
newMatrixClientObservers.forEach { it.invoke(matrixClient) }
sessionStore.addSession(sessionData)
@ -253,6 +258,21 @@ class RustMatrixAuthenticationService(
}
}
@Throws(AuthenticationException.AccountAlreadyLoggedIn::class)
private suspend fun ensureNotAlreadyLoggedIn(client: Client) {
val newUserId = client.userId()
val accountAlreadyLoggedIn = sessionStore.getAllSessions().any {
it.userId == newUserId
}
if (accountAlreadyLoggedIn) {
// Sign out the client, ignoring any error
runCatchingExceptions {
client.logout()
}
throw AuthenticationException.AccountAlreadyLoggedIn(newUserId)
}
}
override suspend fun loginWithQrCode(qrCodeData: MatrixQrCodeLoginData, progress: (QrCodeLoginStep) -> Unit) =
withContext(coroutineDispatchers.io) {
val sdkQrCodeLoginData = (qrCodeData as SdkQrCodeLoginData).rustQrCodeData
@ -275,7 +295,8 @@ class RustMatrixAuthenticationService(
oidcConfiguration = oidcConfiguration,
progressListener = progressListener,
)
// Ensure that the user is not already logged in with the same account
ensureNotAlreadyLoggedIn(client)
val sessionData = client.session()
.toSessionData(
isTokenValid = true,

View file

@ -34,6 +34,11 @@ internal fun Session.toSessionData(
passphrase = passphrase,
sessionPath = sessionPaths.fileDirectory.absolutePath,
cachePath = sessionPaths.cacheDirectory.absolutePath,
// Note: position and lastUsageIndex will be set by the SessionStore when adding the session
position = 0,
lastUsageIndex = 0,
userDisplayName = null,
userAvatarUrl = null,
)
internal fun ExternalSession.toSessionData(
@ -55,4 +60,8 @@ internal fun ExternalSession.toSessionData(
passphrase = passphrase,
sessionPath = sessionPaths.fileDirectory.absolutePath,
cachePath = sessionPaths.cacheDirectory.absolutePath,
position = 0,
lastUsageIndex = 0,
userDisplayName = null,
userAvatarUrl = null,
)