change (preferences) : hide invite avatars (room and sender)

This commit is contained in:
ganfra 2025-04-09 21:06:36 +02:00
parent 119d09c494
commit e231ef7a0e
17 changed files with 74 additions and 10 deletions

View file

@ -35,6 +35,7 @@ dependencies {
implementation(projects.features.invite.api) implementation(projects.features.invite.api)
implementation(projects.features.roomdirectory.api) implementation(projects.features.roomdirectory.api)
implementation(projects.services.analytics.api) implementation(projects.services.analytics.api)
implementation(projects.libraries.preferences.api)
testImplementation(libs.test.junit) testImplementation(libs.test.junit)
testImplementation(libs.coroutines.test) testImplementation(libs.coroutines.test)
@ -45,5 +46,7 @@ dependencies {
testImplementation(projects.libraries.matrix.test) testImplementation(projects.libraries.matrix.test)
testImplementation(projects.tests.testutils) testImplementation(projects.tests.testutils)
testImplementation(libs.androidx.compose.ui.test.junit) testImplementation(libs.androidx.compose.ui.test.junit)
testImplementation(projects.libraries.preferences.test)
testReleaseImplementation(libs.androidx.compose.ui.test.manifest) testReleaseImplementation(libs.androidx.compose.ui.test.manifest)
} }

View file

@ -50,6 +50,7 @@ import io.element.android.libraries.matrix.api.room.join.JoinRoom
import io.element.android.libraries.matrix.api.room.join.JoinRule import io.element.android.libraries.matrix.api.room.join.JoinRule
import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo import io.element.android.libraries.matrix.api.room.preview.RoomPreviewInfo
import io.element.android.libraries.matrix.ui.model.toInviteSender import io.element.android.libraries.matrix.ui.model.toInviteSender
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.Optional import java.util.Optional
@ -67,6 +68,7 @@ class JoinRoomPresenter @AssistedInject constructor(
private val forgetRoom: ForgetRoom, private val forgetRoom: ForgetRoom,
private val acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>, private val acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>,
private val buildMeta: BuildMeta, private val buildMeta: BuildMeta,
private val appPreferencesStore: AppPreferencesStore,
) : Presenter<JoinRoomState> { ) : Presenter<JoinRoomState> {
interface Factory { interface Factory {
fun create( fun create(
@ -89,6 +91,7 @@ class JoinRoomPresenter @AssistedInject constructor(
val forgetRoomAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) } val forgetRoomAction: MutableState<AsyncAction<Unit>> = remember { mutableStateOf(AsyncAction.Uninitialized) }
var knockMessage by rememberSaveable { mutableStateOf("") } var knockMessage by rememberSaveable { mutableStateOf("") }
var isDismissingContent by remember { mutableStateOf(false) } var isDismissingContent by remember { mutableStateOf(false) }
val shouldHideAvatars by appPreferencesStore.getHideInviteAvatarsFlow().collectAsState(initial = false)
val contentState by produceState<ContentState>( val contentState by produceState<ContentState>(
initialValue = ContentState.Loading, initialValue = ContentState.Loading,
key1 = roomInfo, key1 = roomInfo,
@ -193,6 +196,7 @@ class JoinRoomPresenter @AssistedInject constructor(
cancelKnockAction = cancelKnockAction.value, cancelKnockAction = cancelKnockAction.value,
applicationName = buildMeta.applicationName, applicationName = buildMeta.applicationName,
knockMessage = knockMessage, knockMessage = knockMessage,
shouldHideAvatars = shouldHideAvatars,
eventSink = ::handleEvents eventSink = ::handleEvents
) )
} }

View file

@ -31,6 +31,7 @@ data class JoinRoomState(
val cancelKnockAction: AsyncAction<Unit>, val cancelKnockAction: AsyncAction<Unit>,
private val applicationName: String, private val applicationName: String,
val knockMessage: String, val knockMessage: String,
val shouldHideAvatars: Boolean,
val eventSink: (JoinRoomEvents) -> Unit val eventSink: (JoinRoomEvents) -> Unit
) { ) {
val isJoinActionUnauthorized = joinAction is AsyncAction.Failure && joinAction.error is JoinRoomFailures.UnauthorizedJoin val isJoinActionUnauthorized = joinAction is AsyncAction.Failure && joinAction.error is JoinRoomFailures.UnauthorizedJoin

View file

@ -171,6 +171,7 @@ fun aJoinRoomState(
forgetAction: AsyncAction<Unit> = AsyncAction.Uninitialized, forgetAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
cancelKnockAction: AsyncAction<Unit> = AsyncAction.Uninitialized, cancelKnockAction: AsyncAction<Unit> = AsyncAction.Uninitialized,
knockMessage: String = "", knockMessage: String = "",
shouldHideAvatars: Boolean = false,
eventSink: (JoinRoomEvents) -> Unit = {} eventSink: (JoinRoomEvents) -> Unit = {}
) = JoinRoomState( ) = JoinRoomState(
roomIdOrAlias = roomIdOrAlias, roomIdOrAlias = roomIdOrAlias,
@ -182,6 +183,7 @@ fun aJoinRoomState(
forgetAction = forgetAction, forgetAction = forgetAction,
applicationName = "AppName", applicationName = "AppName",
knockMessage = knockMessage, knockMessage = knockMessage,
shouldHideAvatars = shouldHideAvatars,
eventSink = eventSink eventSink = eventSink
) )

View file

@ -97,6 +97,7 @@ fun JoinRoomView(
roomIdOrAlias = state.roomIdOrAlias, roomIdOrAlias = state.roomIdOrAlias,
contentState = state.contentState, contentState = state.contentState,
knockMessage = state.knockMessage, knockMessage = state.knockMessage,
shouldHideAvatars = state.shouldHideAvatars,
onKnockMessageUpdate = { state.eventSink(JoinRoomEvents.UpdateKnockMessage(it)) }, onKnockMessageUpdate = { state.eventSink(JoinRoomEvents.UpdateKnockMessage(it)) },
) )
}, },
@ -371,6 +372,7 @@ private fun JoinRoomContent(
roomIdOrAlias: RoomIdOrAlias, roomIdOrAlias: RoomIdOrAlias,
contentState: ContentState, contentState: ContentState,
knockMessage: String, knockMessage: String,
shouldHideAvatars: Boolean,
onKnockMessageUpdate: (String) -> Unit, onKnockMessageUpdate: (String) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
@ -385,13 +387,14 @@ private fun JoinRoomContent(
Column(horizontalAlignment = Alignment.CenterHorizontally) { Column(horizontalAlignment = Alignment.CenterHorizontally) {
val inviteSender = (contentState.joinAuthorisationStatus as? JoinAuthorisationStatus.IsInvited)?.inviteSender val inviteSender = (contentState.joinAuthorisationStatus as? JoinAuthorisationStatus.IsInvited)?.inviteSender
if (inviteSender != null) { if (inviteSender != null) {
InviteSenderView(inviteSender = inviteSender) InviteSenderView(inviteSender = inviteSender, hideAvatarImage = shouldHideAvatars)
Spacer(modifier = Modifier.height(32.dp)) Spacer(modifier = Modifier.height(32.dp))
} }
DefaultLoadedContent( DefaultLoadedContent(
modifier = Modifier.verticalScroll(rememberScrollState()), modifier = Modifier.verticalScroll(rememberScrollState()),
contentState = contentState, contentState = contentState,
knockMessage = knockMessage, knockMessage = knockMessage,
shouldHideAvatars = shouldHideAvatars,
onKnockMessageUpdate = onKnockMessageUpdate onKnockMessageUpdate = onKnockMessageUpdate
) )
} }
@ -474,13 +477,14 @@ private fun IsKnockedLoadedContent(modifier: Modifier = Modifier) {
private fun DefaultLoadedContent( private fun DefaultLoadedContent(
contentState: ContentState.Loaded, contentState: ContentState.Loaded,
knockMessage: String, knockMessage: String,
shouldHideAvatars: Boolean,
onKnockMessageUpdate: (String) -> Unit, onKnockMessageUpdate: (String) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
RoomPreviewOrganism( RoomPreviewOrganism(
modifier = modifier, modifier = modifier,
avatar = { avatar = {
Avatar(contentState.avatarData(AvatarSize.RoomHeader)) Avatar(contentState.avatarData(AvatarSize.RoomHeader), hideImage = shouldHideAvatars)
}, },
title = { title = {
if (contentState.name != null) { if (contentState.name != null) {

View file

@ -21,6 +21,7 @@ import io.element.android.libraries.matrix.api.MatrixClient
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.core.RoomIdOrAlias import io.element.android.libraries.matrix.api.core.RoomIdOrAlias
import io.element.android.libraries.matrix.api.room.join.JoinRoom import io.element.android.libraries.matrix.api.room.join.JoinRoom
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import java.util.Optional import java.util.Optional
@Module @Module
@ -35,6 +36,7 @@ object JoinRoomModule {
forgetRoom: ForgetRoom, forgetRoom: ForgetRoom,
acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>, acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState>,
buildMeta: BuildMeta, buildMeta: BuildMeta,
appPreferencesStore: AppPreferencesStore,
): JoinRoomPresenter.Factory { ): JoinRoomPresenter.Factory {
return object : JoinRoomPresenter.Factory { return object : JoinRoomPresenter.Factory {
override fun create( override fun create(
@ -57,6 +59,7 @@ object JoinRoomModule {
cancelKnockRoom = cancelKnockRoom, cancelKnockRoom = cancelKnockRoom,
acceptDeclineInvitePresenter = acceptDeclineInvitePresenter, acceptDeclineInvitePresenter = acceptDeclineInvitePresenter,
buildMeta = buildMeta, buildMeta = buildMeta,
appPreferencesStore = appPreferencesStore,
) )
} }
} }

View file

@ -45,6 +45,8 @@ import io.element.android.libraries.matrix.test.room.aRoomPreviewInfo
import io.element.android.libraries.matrix.test.room.aRoomSummary import io.element.android.libraries.matrix.test.room.aRoomSummary
import io.element.android.libraries.matrix.test.room.join.FakeJoinRoom import io.element.android.libraries.matrix.test.room.join.FakeJoinRoom
import io.element.android.libraries.matrix.ui.model.toInviteSender import io.element.android.libraries.matrix.ui.model.toInviteSender
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
import io.element.android.tests.testutils.WarmUpRule import io.element.android.tests.testutils.WarmUpRule
import io.element.android.tests.testutils.lambda.any import io.element.android.tests.testutils.lambda.any
import io.element.android.tests.testutils.lambda.assert import io.element.android.tests.testutils.lambda.assert
@ -759,7 +761,8 @@ class JoinRoomPresenterTest {
cancelKnockRoom: CancelKnockRoom = FakeCancelKnockRoom(), cancelKnockRoom: CancelKnockRoom = FakeCancelKnockRoom(),
forgetRoom: ForgetRoom = FakeForgetRoom(), forgetRoom: ForgetRoom = FakeForgetRoom(),
buildMeta: BuildMeta = aBuildMeta(applicationName = "AppName"), buildMeta: BuildMeta = aBuildMeta(applicationName = "AppName"),
acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState> = Presenter { anAcceptDeclineInviteState() } acceptDeclineInvitePresenter: Presenter<AcceptDeclineInviteState> = Presenter { anAcceptDeclineInviteState() },
appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore()
): JoinRoomPresenter { ): JoinRoomPresenter {
return JoinRoomPresenter( return JoinRoomPresenter(
roomId = roomId, roomId = roomId,
@ -773,7 +776,8 @@ class JoinRoomPresenterTest {
cancelKnockRoom = cancelKnockRoom, cancelKnockRoom = cancelKnockRoom,
forgetRoom = forgetRoom, forgetRoom = forgetRoom,
buildMeta = buildMeta, buildMeta = buildMeta,
acceptDeclineInvitePresenter = acceptDeclineInvitePresenter acceptDeclineInvitePresenter = acceptDeclineInvitePresenter,
appPreferencesStore = appPreferencesStore,
) )
} }

View file

@ -117,6 +117,9 @@ class RoomListPresenter @Inject constructor(
// Avatar indicator // Avatar indicator
val showAvatarIndicator by indicatorService.showRoomListTopBarIndicator() val showAvatarIndicator by indicatorService.showRoomListTopBarIndicator()
val hideInvitesAvatar by remember {
appPreferencesStore.getHideInviteAvatarsFlow()
}.collectAsState(initial = false)
val contextMenu = remember { mutableStateOf<RoomListState.ContextMenu>(RoomListState.ContextMenu.Hidden) } val contextMenu = remember { mutableStateOf<RoomListState.ContextMenu>(RoomListState.ContextMenu.Hidden) }
@ -171,6 +174,7 @@ class RoomListPresenter @Inject constructor(
contentState = contentState, contentState = contentState,
acceptDeclineInviteState = acceptDeclineInviteState, acceptDeclineInviteState = acceptDeclineInviteState,
directLogoutState = directLogoutState, directLogoutState = directLogoutState,
hideInvitesAvatars = hideInvitesAvatar,
eventSink = ::handleEvents, eventSink = ::handleEvents,
) )
} }

View file

@ -34,6 +34,7 @@ data class RoomListState(
val contentState: RoomListContentState, val contentState: RoomListContentState,
val acceptDeclineInviteState: AcceptDeclineInviteState, val acceptDeclineInviteState: AcceptDeclineInviteState,
val directLogoutState: DirectLogoutState, val directLogoutState: DirectLogoutState,
val hideInvitesAvatars: Boolean,
val eventSink: (RoomListEvents) -> Unit, val eventSink: (RoomListEvents) -> Unit,
) { ) {
val displayFilters = contentState is RoomListContentState.Rooms val displayFilters = contentState is RoomListContentState.Rooms

View file

@ -61,6 +61,7 @@ internal fun aRoomListState(
contentState: RoomListContentState = aRoomsContentState(), contentState: RoomListContentState = aRoomsContentState(),
acceptDeclineInviteState: AcceptDeclineInviteState = anAcceptDeclineInviteState(), acceptDeclineInviteState: AcceptDeclineInviteState = anAcceptDeclineInviteState(),
directLogoutState: DirectLogoutState = aDirectLogoutState(), directLogoutState: DirectLogoutState = aDirectLogoutState(),
hideInvitesAvatars: Boolean = false,
eventSink: (RoomListEvents) -> Unit = {} eventSink: (RoomListEvents) -> Unit = {}
) = RoomListState( ) = RoomListState(
matrixUser = matrixUser, matrixUser = matrixUser,
@ -75,6 +76,7 @@ internal fun aRoomListState(
contentState = contentState, contentState = contentState,
acceptDeclineInviteState = acceptDeclineInviteState, acceptDeclineInviteState = acceptDeclineInviteState,
directLogoutState = directLogoutState, directLogoutState = directLogoutState,
hideInvitesAvatars = hideInvitesAvatars,
eventSink = eventSink, eventSink = eventSink,
) )

View file

@ -81,6 +81,7 @@ fun RoomListView(
RoomListSearchView( RoomListSearchView(
state = state.searchState, state = state.searchState,
eventSink = state.eventSink, eventSink = state.eventSink,
hideInvitesAvatars = state.hideInvitesAvatars,
onRoomClick = onRoomClick, onRoomClick = onRoomClick,
modifier = Modifier modifier = Modifier
.statusBarsPadding() .statusBarsPadding()
@ -134,6 +135,7 @@ private fun RoomListScaffold(
RoomListContentView( RoomListContentView(
contentState = state.contentState, contentState = state.contentState,
filtersState = state.filtersState, filtersState = state.filtersState,
hideInvitesAvatars = state.hideInvitesAvatars,
eventSink = state.eventSink, eventSink = state.eventSink,
onSetUpRecoveryClick = onSetUpRecoveryClick, onSetUpRecoveryClick = onSetUpRecoveryClick,
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick, onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,

View file

@ -59,6 +59,7 @@ import kotlinx.collections.immutable.ImmutableList
fun RoomListContentView( fun RoomListContentView(
contentState: RoomListContentState, contentState: RoomListContentState,
filtersState: RoomListFiltersState, filtersState: RoomListFiltersState,
hideInvitesAvatars: Boolean,
eventSink: (RoomListEvents) -> Unit, eventSink: (RoomListEvents) -> Unit,
onSetUpRecoveryClick: () -> Unit, onSetUpRecoveryClick: () -> Unit,
onConfirmRecoveryKeyClick: () -> Unit, onConfirmRecoveryKeyClick: () -> Unit,
@ -85,6 +86,7 @@ fun RoomListContentView(
is RoomListContentState.Rooms -> { is RoomListContentState.Rooms -> {
RoomsView( RoomsView(
state = contentState, state = contentState,
hideInvitesAvatars = hideInvitesAvatars,
filtersState = filtersState, filtersState = filtersState,
eventSink = eventSink, eventSink = eventSink,
onSetUpRecoveryClick = onSetUpRecoveryClick, onSetUpRecoveryClick = onSetUpRecoveryClick,
@ -155,6 +157,7 @@ private fun EmptyView(
@Composable @Composable
private fun RoomsView( private fun RoomsView(
state: RoomListContentState.Rooms, state: RoomListContentState.Rooms,
hideInvitesAvatars: Boolean,
filtersState: RoomListFiltersState, filtersState: RoomListFiltersState,
eventSink: (RoomListEvents) -> Unit, eventSink: (RoomListEvents) -> Unit,
onSetUpRecoveryClick: () -> Unit, onSetUpRecoveryClick: () -> Unit,
@ -170,6 +173,7 @@ private fun RoomsView(
} else { } else {
RoomsViewList( RoomsViewList(
state = state, state = state,
hideInvitesAvatars = hideInvitesAvatars,
eventSink = eventSink, eventSink = eventSink,
onSetUpRecoveryClick = onSetUpRecoveryClick, onSetUpRecoveryClick = onSetUpRecoveryClick,
onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick, onConfirmRecoveryKeyClick = onConfirmRecoveryKeyClick,
@ -182,6 +186,7 @@ private fun RoomsView(
@Composable @Composable
private fun RoomsViewList( private fun RoomsViewList(
state: RoomListContentState.Rooms, state: RoomListContentState.Rooms,
hideInvitesAvatars: Boolean,
eventSink: (RoomListEvents) -> Unit, eventSink: (RoomListEvents) -> Unit,
onSetUpRecoveryClick: () -> Unit, onSetUpRecoveryClick: () -> Unit,
onConfirmRecoveryKeyClick: () -> Unit, onConfirmRecoveryKeyClick: () -> Unit,
@ -239,6 +244,7 @@ private fun RoomsViewList(
) { index, room -> ) { index, room ->
RoomSummaryRow( RoomSummaryRow(
room = room, room = room,
hideInviteAvatars = hideInvitesAvatars,
onClick = onRoomClick, onClick = onRoomClick,
eventSink = eventSink, eventSink = eventSink,
) )
@ -300,6 +306,7 @@ internal fun RoomListContentViewPreview(@PreviewParameter(RoomListContentStatePr
filtersState = aRoomListFiltersState( filtersState = aRoomListFiltersState(
filterSelectionStates = RoomListFilter.entries.map { FilterSelectionState(it, isSelected = true) } filterSelectionStates = RoomListFilter.entries.map { FilterSelectionState(it, isSelected = true) }
), ),
hideInvitesAvatars = false,
eventSink = {}, eventSink = {},
onSetUpRecoveryClick = {}, onSetUpRecoveryClick = {},
onConfirmRecoveryKeyClick = {}, onConfirmRecoveryKeyClick = {},

View file

@ -68,10 +68,12 @@ internal val minHeight = 84.dp
@Composable @Composable
internal fun RoomSummaryRow( internal fun RoomSummaryRow(
room: RoomListRoomSummary, room: RoomListRoomSummary,
hideInviteAvatars: Boolean,
onClick: (RoomListRoomSummary) -> Unit, onClick: (RoomListRoomSummary) -> Unit,
eventSink: (RoomListEvents) -> Unit, eventSink: (RoomListEvents) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
Box(modifier = modifier) { Box(modifier = modifier) {
when (room.displayType) { when (room.displayType) {
RoomSummaryDisplayType.PLACEHOLDER -> { RoomSummaryDisplayType.PLACEHOLDER -> {
@ -80,6 +82,7 @@ internal fun RoomSummaryRow(
RoomSummaryDisplayType.INVITE -> { RoomSummaryDisplayType.INVITE -> {
RoomSummaryScaffoldRow( RoomSummaryScaffoldRow(
room = room, room = room,
hideAvatarImage = hideInviteAvatars,
onClick = onClick, onClick = onClick,
onLongClick = { onLongClick = {
Timber.d("Long click on invite room") Timber.d("Long click on invite room")
@ -92,6 +95,7 @@ internal fun RoomSummaryRow(
InviteSenderView( InviteSenderView(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
inviteSender = room.inviteSender, inviteSender = room.inviteSender,
hideAvatarImage = hideInviteAvatars
) )
} }
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(12.dp))
@ -164,6 +168,7 @@ private fun RoomSummaryScaffoldRow(
onClick: (RoomListRoomSummary) -> Unit, onClick: (RoomListRoomSummary) -> Unit,
onLongClick: (RoomListRoomSummary) -> Unit, onLongClick: (RoomListRoomSummary) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
hideAvatarImage: Boolean = false,
content: @Composable ColumnScope.() -> Unit content: @Composable ColumnScope.() -> Unit
) { ) {
val clickModifier = Modifier.combinedClickable( val clickModifier = Modifier.combinedClickable(
@ -184,6 +189,7 @@ private fun RoomSummaryScaffoldRow(
CompositeAvatar( CompositeAvatar(
avatarData = room.avatarData, avatarData = room.avatarData,
heroes = room.heroes, heroes = room.heroes,
hideAvatarImages = hideAvatarImage,
) )
Spacer(modifier = Modifier.width(16.dp)) Spacer(modifier = Modifier.width(16.dp))
Column( Column(
@ -384,6 +390,7 @@ private fun MentionIndicatorAtom() {
internal fun RoomSummaryRowPreview(@PreviewParameter(RoomListRoomSummaryProvider::class) data: RoomListRoomSummary) = ElementPreview { internal fun RoomSummaryRowPreview(@PreviewParameter(RoomListRoomSummaryProvider::class) data: RoomListRoomSummary) = ElementPreview {
RoomSummaryRow( RoomSummaryRow(
room = data, room = data,
hideInviteAvatars = false,
onClick = {}, onClick = {},
eventSink = {}, eventSink = {},
) )

View file

@ -54,6 +54,7 @@ import io.element.android.libraries.ui.strings.CommonStrings
@Composable @Composable
internal fun RoomListSearchView( internal fun RoomListSearchView(
state: RoomListSearchState, state: RoomListSearchState,
hideInvitesAvatars: Boolean,
eventSink: (RoomListEvents) -> Unit, eventSink: (RoomListEvents) -> Unit,
onRoomClick: (RoomId) -> Unit, onRoomClick: (RoomId) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
@ -80,6 +81,7 @@ internal fun RoomListSearchView(
if (state.isSearchActive) { if (state.isSearchActive) {
RoomListSearchContent( RoomListSearchContent(
state = state, state = state,
hideInvitesAvatars = hideInvitesAvatars,
onRoomClick = onRoomClick, onRoomClick = onRoomClick,
eventSink = eventSink, eventSink = eventSink,
) )
@ -92,6 +94,7 @@ internal fun RoomListSearchView(
@Composable @Composable
private fun RoomListSearchContent( private fun RoomListSearchContent(
state: RoomListSearchState, state: RoomListSearchState,
hideInvitesAvatars: Boolean,
eventSink: (RoomListEvents) -> Unit, eventSink: (RoomListEvents) -> Unit,
onRoomClick: (RoomId) -> Unit, onRoomClick: (RoomId) -> Unit,
) { ) {
@ -173,6 +176,7 @@ private fun RoomListSearchContent(
) { room -> ) { room ->
RoomSummaryRow( RoomSummaryRow(
room = room, room = room,
hideInviteAvatars = hideInvitesAvatars,
onClick = ::onRoomClick, onClick = ::onRoomClick,
eventSink = eventSink, eventSink = eventSink,
) )
@ -187,6 +191,7 @@ private fun RoomListSearchContent(
internal fun RoomListSearchContentPreview(@PreviewParameter(RoomListSearchStateProvider::class) state: RoomListSearchState) = ElementPreview { internal fun RoomListSearchContentPreview(@PreviewParameter(RoomListSearchStateProvider::class) state: RoomListSearchState) = ElementPreview {
RoomListSearchContent( RoomListSearchContent(
state = state, state = state,
hideInvitesAvatars = false,
onRoomClick = {}, onRoomClick = {},
eventSink = {}, eventSink = {},
) )

View file

@ -48,11 +48,13 @@ fun Avatar(
contentDescription: String? = null, contentDescription: String? = null,
// If not null, will be used instead of the size from avatarData // If not null, will be used instead of the size from avatarData
forcedAvatarSize: Dp? = null, forcedAvatarSize: Dp? = null,
// If true, will show initials even if avatarData.url is not null
hideImage: Boolean = false,
) { ) {
val commonModifier = modifier val commonModifier = modifier
.size(forcedAvatarSize ?: avatarData.size.dp) .size(forcedAvatarSize ?: avatarData.size.dp)
.clip(CircleShape) .clip(CircleShape)
if (avatarData.url.isNullOrBlank()) { if (avatarData.url.isNullOrBlank() || hideImage) {
InitialsAvatar( InitialsAvatar(
avatarData = avatarData, avatarData = avatarData,
forcedAvatarSize = forcedAvatarSize, forcedAvatarSize = forcedAvatarSize,

View file

@ -33,10 +33,16 @@ fun CompositeAvatar(
avatarData: AvatarData, avatarData: AvatarData,
heroes: ImmutableList<AvatarData>, heroes: ImmutableList<AvatarData>,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
hideAvatarImages: Boolean = false,
contentDescription: String? = null, contentDescription: String? = null,
) { ) {
if (avatarData.url != null || heroes.isEmpty()) { if (avatarData.url != null || heroes.isEmpty()) {
Avatar(avatarData, modifier, contentDescription) Avatar(
avatarData = avatarData,
modifier = modifier,
contentDescription = contentDescription,
hideImage = hideAvatarImages
)
} else { } else {
val limitedHeroes = heroes.take(4) val limitedHeroes = heroes.take(4)
val numberOfHeroes = limitedHeroes.size val numberOfHeroes = limitedHeroes.size
@ -49,7 +55,12 @@ fun CompositeAvatar(
error("Unsupported number of heroes: 0") error("Unsupported number of heroes: 0")
} }
1 -> { 1 -> {
Avatar(heroes[0], modifier, contentDescription) Avatar(
avatarData = heroes[0],
modifier = modifier,
contentDescription = contentDescription,
hideImage = hideAvatarImages
)
} }
else -> { else -> {
val angle = 2 * Math.PI / numberOfHeroes val angle = 2 * Math.PI / numberOfHeroes
@ -91,8 +102,9 @@ fun CompositeAvatar(
) )
) { ) {
Avatar( Avatar(
heroAvatar, avatarData = heroAvatar,
forcedAvatarSize = heroAvatarSize, forcedAvatarSize = heroAvatarSize,
hideImage = hideAvatarImages,
) )
} }
} }

View file

@ -27,14 +27,15 @@ import io.element.android.libraries.matrix.ui.model.InviteSender
@Composable @Composable
fun InviteSenderView( fun InviteSenderView(
inviteSender: InviteSender, inviteSender: InviteSender,
modifier: Modifier = Modifier modifier: Modifier = Modifier,
hideAvatarImage: Boolean = false,
) { ) {
Row( Row(
horizontalArrangement = Arrangement.spacedBy(8.dp), horizontalArrangement = Arrangement.spacedBy(8.dp),
modifier = modifier, modifier = modifier,
) { ) {
Box(modifier = Modifier.padding(vertical = 2.dp)) { Box(modifier = Modifier.padding(vertical = 2.dp)) {
Avatar(avatarData = inviteSender.avatarData) Avatar(avatarData = inviteSender.avatarData, hideImage = hideAvatarImage)
} }
Text( Text(
text = inviteSender.annotatedString(), text = inviteSender.annotatedString(),