Wire user status through the Rust SDK and refresh profile after change

# Conflicts:
#	libraries/matrix/impl/src/main/kotlin/io/element/android/libraries/matrix/impl/RustMatrixClient.kt
This commit is contained in:
ganfra
2026-06-30 18:46:56 +02:00
parent 98c686dd5b
commit 38102747ad
9 changed files with 59 additions and 32 deletions
@@ -13,6 +13,10 @@ import kotlinx.parcelize.Parcelize
@Immutable
sealed interface DisplayedStatus : Parcelable {
/** Useful for adding extension methods. */
companion object
/** Status set manually by the user via m.status. */
@Parcelize
data class UserSet(val status: UserStatus) : DisplayedStatus
@@ -21,6 +25,6 @@ sealed interface DisplayedStatus : Parcelable {
@Parcelize
data class InCall(
/** Unix timestamp in seconds when the call was joined (from m.call.call_joined_ts). */
val callJoinedTs: Long,
val callJoinedTs: Long?,
) : DisplayedStatus
}
@@ -49,7 +49,6 @@ import io.element.android.libraries.matrix.api.scanner.ContentScanner
import io.element.android.libraries.matrix.api.spaces.SpaceService
import io.element.android.libraries.matrix.api.sync.SlidingSyncVersion
import io.element.android.libraries.matrix.api.sync.SyncState
import io.element.android.libraries.matrix.api.user.DisplayedStatus
import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.api.user.UserStatus
@@ -58,7 +57,8 @@ import io.element.android.libraries.matrix.impl.exception.mapClientException
import io.element.android.libraries.matrix.impl.linknewdevice.RustLinkDesktopHandler
import io.element.android.libraries.matrix.impl.linknewdevice.RustLinkMobileHandler
import io.element.android.libraries.matrix.impl.linknewdevice.RustQrCodeDataParser
import io.element.android.libraries.matrix.impl.mapper.map
import io.element.android.libraries.matrix.impl.user.into
import io.element.android.libraries.matrix.impl.user.map
import io.element.android.libraries.matrix.impl.media.RustMediaLoader
import io.element.android.libraries.matrix.impl.media.RustMediaPreviewService
import io.element.android.libraries.matrix.impl.notification.RustNotificationService
@@ -85,7 +85,7 @@ import io.element.android.libraries.matrix.impl.search.RustMessageSearchService
import io.element.android.libraries.matrix.impl.spaces.RustSpaceService
import io.element.android.libraries.matrix.impl.sync.RustSyncService
import io.element.android.libraries.matrix.impl.sync.map
import io.element.android.libraries.matrix.impl.usersearch.UserSearchResultMapper
import io.element.android.libraries.matrix.impl.user.UserSearchResultMapper
import io.element.android.libraries.matrix.impl.util.cancelAndDestroy
import io.element.android.libraries.matrix.impl.util.mxCallbackFlow
import io.element.android.libraries.matrix.impl.verification.RustSessionVerificationService
@@ -271,8 +271,6 @@ class RustMatrixClient(
private var clientDelegateTaskHandle: TaskHandle? = innerClient.setDelegate(sessionDelegate)
@Volatile private var localUserStatus: UserStatus? = null
private val _userProfile: MutableStateFlow<MatrixUser> = MutableStateFlow(
MatrixUser(
userId = sessionId,
@@ -458,13 +456,8 @@ class RustMatrixClient(
override suspend fun getUserProfile(): Result<MatrixUser> = getProfile(sessionId)
.onSuccess { matrixUser ->
_userProfile.emit(
matrixUser.copy(
rawStatus = localUserStatus,
displayedStatus = localUserStatus?.let { DisplayedStatus.UserSet(it) },
)
)
// Also update our session storage
_userProfile.emit(matrixUser)
sessionStore.updateUserProfile(
sessionId = sessionId.value,
displayName = matrixUser.displayName,
@@ -495,25 +488,21 @@ class RustMatrixClient(
}
override suspend fun setUserStatus(status: UserStatus): Result<Unit> = withContext(sessionDispatcher) {
localUserStatus = status
_userProfile.emit(
_userProfile.value.copy(
rawStatus = status,
displayedStatus = DisplayedStatus.UserSet(status),
)
)
Result.success(Unit)
runCatchingExceptions {
innerClient.setUserStatus(status.into())
}.onSuccess {
// try to refresh data once it's updated
getUserProfile()
}
}
override suspend fun clearUserStatus(): Result<Unit> = withContext(sessionDispatcher) {
localUserStatus = null
_userProfile.emit(
_userProfile.value.copy(
rawStatus = null,
displayedStatus = null,
)
)
Result.success(Unit)
runCatchingExceptions {
innerClient.clearUserStatus()
}.onSuccess {
// try to refresh data once it's updated
getUserProfile()
}
}
override suspend fun joinRoom(roomId: RoomId): Result<RoomInfo?> = withContext(sessionDispatcher) {
@@ -42,6 +42,7 @@ import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
import io.element.android.libraries.matrix.impl.core.RustSendHandle
import io.element.android.libraries.matrix.impl.mapper.map
import io.element.android.libraries.matrix.impl.user.map
import io.element.android.libraries.matrix.impl.room.history.map
import io.element.android.libraries.matrix.impl.room.join.map
import io.element.android.libraries.matrix.impl.room.knock.RustKnockRequest
@@ -6,9 +6,10 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.mapper
package io.element.android.libraries.matrix.impl.user
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.user.DisplayedStatus
import io.element.android.libraries.matrix.api.user.MatrixUser
import org.matrix.rustcomponents.sdk.UserProfile
@@ -16,4 +17,6 @@ fun UserProfile.map() = MatrixUser(
userId = UserId(userId),
displayName = displayName,
avatarUrl = avatarUrl,
rawStatus = status?.into(),
displayedStatus = DisplayedStatus.from(status, call)
)
@@ -6,10 +6,9 @@
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.usersearch
package io.element.android.libraries.matrix.impl.user
import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults
import io.element.android.libraries.matrix.impl.mapper.map
import kotlinx.collections.immutable.toImmutableList
import org.matrix.rustcomponents.sdk.SearchUsersResults
@@ -0,0 +1,29 @@
/*
* Copyright (c) 2026 Element Creations Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
* Please see LICENSE files in the repository root for full details.
*/
package io.element.android.libraries.matrix.impl.user
import io.element.android.libraries.matrix.api.user.DisplayedStatus
import io.element.android.libraries.matrix.api.user.UserStatus
import org.matrix.rustcomponents.sdk.UserCall
import org.matrix.rustcomponents.sdk.UserStatus as RustUserStatus
fun UserStatus.into(): RustUserStatus {
return RustUserStatus(emoji = emoji, text = text)
}
fun RustUserStatus.into(): UserStatus {
return UserStatus(emoji = emoji, text = text)
}
fun DisplayedStatus.Companion.from(userStatus: RustUserStatus?, userCall: UserCall?): DisplayedStatus? {
return when {
userStatus != null -> DisplayedStatus.UserSet(userStatus.into())
userCall != null -> DisplayedStatus.InCall(userCall.callJoinedTs?.toLong())
else -> null
}
}
@@ -13,7 +13,7 @@ import io.element.android.libraries.matrix.api.core.FlowId
import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.verification.SessionVerificationRequestDetails
import io.element.android.libraries.matrix.api.verification.VerificationRequest
import io.element.android.libraries.matrix.impl.mapper.map
import io.element.android.libraries.matrix.impl.user.map
import org.matrix.rustcomponents.sdk.SessionVerificationRequestDetails as RustSessionVerificationRequestDetails
fun RustSessionVerificationRequestDetails.map() = SessionVerificationRequestDetails(
@@ -11,6 +11,7 @@ package io.element.android.libraries.matrix.impl.mapper
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustUserProfile
import io.element.android.libraries.matrix.impl.user.map
import io.element.android.libraries.matrix.test.A_USER_ID
import org.junit.Test
@@ -13,6 +13,7 @@ import io.element.android.libraries.matrix.api.user.MatrixSearchUserResults
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustSearchUsersResults
import io.element.android.libraries.matrix.impl.fixtures.factories.aRustUserProfile
import io.element.android.libraries.matrix.impl.user.UserSearchResultMapper
import io.element.android.libraries.matrix.test.A_USER_ID
import kotlinx.collections.immutable.toImmutableList
import org.junit.Test