Use the stored avatar thumbnail as a fallback for other accounts

Add an optional thumbnail to `MatrixUser` and `AvatarData`, filled from the session
database for the other accounts in the room list header, the settings and the account
selection screen. `ImageAvatar` renders this thumbnail instead of the initial letter while
the avatar is loading or when it fails to load, for instance when the homeserver of the
current account is not federated with the one of the other account.

Fixes #5571

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Benoit Marty
2026-09-28 11:38:45 +02:00
parent db23023eda
commit c2a2e16f46
12 changed files with 100 additions and 3 deletions
@@ -36,6 +36,7 @@ class CurrentUserWithNeighborsBuilder {
userId = UserId(it.userId),
displayName = it.userDisplayName,
avatarUrl = it.userAvatarUrl,
avatarThumbnail = it.userAvatarData,
)
}
}
@@ -220,4 +220,30 @@ class CurrentUserWithNeighborsBuilderTest {
)
)
}
@Test
fun `other accounts use the data from db, including the avatar thumbnail`() {
val sut = CurrentUserWithNeighborsBuilder()
val matrixUser = aMatrixUser(id = A_USER_ID.value)
val list = listOf(
aSessionData(
sessionId = A_USER_ID.value,
),
aSessionData(
sessionId = A_USER_ID_2.value,
userDisplayName = "Carol",
userAvatarUrl = "avatarUrl",
userAvatarData = "avatarData",
),
)
val result = sut.build(matrixUser, list)
assertThat(result[0]).isEqualTo(
MatrixUser(
userId = A_USER_ID_2,
displayName = "Carol",
avatarUrl = "avatarUrl",
avatarThumbnail = "avatarData",
)
)
}
}
@@ -90,6 +90,7 @@ class PreferencesRootPresenter(
userId = UserId(it.userId),
displayName = it.userDisplayName,
avatarUrl = it.userAvatarUrl,
avatarThumbnail = it.userAvatarData,
)
}
.toImmutableList()
@@ -234,6 +234,7 @@ class PreferencesRootPresenterTest {
sessionId = A_SESSION_ID_2.value,
userDisplayName = "Bob",
userAvatarUrl = "avatarUrl",
userAvatarData = "avatarData",
),
)
)
@@ -241,7 +242,14 @@ class PreferencesRootPresenterTest {
val state = awaitFirstItem()
assertThat(state.isMultiAccountEnabled).isTrue()
assertThat(state.otherSessions).hasSize(1)
assertThat(state.otherSessions[0]).isEqualTo(MatrixUser(userId = A_SESSION_ID_2, displayName = "Bob", avatarUrl = "avatarUrl"))
assertThat(state.otherSessions[0]).isEqualTo(
MatrixUser(
userId = A_SESSION_ID_2,
displayName = "Bob",
avatarUrl = "avatarUrl",
avatarThumbnail = "avatarData",
)
)
}
}