From 8ed69c03d24111a14c8a1075e907883a6636e64b Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Mon, 2 Feb 2026 17:32:46 +0000 Subject: [PATCH] Update icon shown for world_readable rooms (#6111) * Update icon shown for world_readable rooms Followup to #6090: having discussed this in the team, we want to show a different icon (with different text) for rooms where the history_visibility is `world_readable` rather than `shared`. * delint * Update screenshots --------- Co-authored-by: ElementBot --- .../messages/impl/MessagesPresenter.kt | 19 +++++++++++---- .../features/messages/impl/MessagesState.kt | 16 +++++++++++-- .../messages/impl/MessagesStateProvider.kt | 4 ++-- .../features/messages/impl/MessagesView.kt | 2 +- .../impl/topbars/MessagesViewTopBar.kt | 24 ++++++++++++++----- .../messages/impl/MessagesPresenterTest.kt | 23 +++++++++++++++++- ...pl.topbars_MessagesViewTopBar_Day_0_en.png | 4 ++-- ....topbars_MessagesViewTopBar_Night_0_en.png | 4 ++-- 8 files changed, 75 insertions(+), 21 deletions(-) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt index 22c4cdbda1..d9c3d17afa 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt @@ -210,10 +210,7 @@ class MessagesPresenter( // * History sharing is enabled, // * The room is encrypted, and: // * The room's history_visibility allows future users to see content. - val showSharedHistoryIcon = isKeyShareOnInviteEnabled && - roomInfo.isEncrypted == true && - (roomInfo.historyVisibility == RoomHistoryVisibility.Shared || - roomInfo.historyVisibility == RoomHistoryVisibility.WorldReadable) + val topBarSharedHistoryIcon = if (isKeyShareOnInviteEnabled) roomInfo.sharedHistoryIcon() else SharedHistoryIcon.NONE LifecycleResumeEffect(dmRoomMember, roomInfo.isEncrypted) { if (roomInfo.isEncrypted == true) { @@ -297,12 +294,24 @@ class MessagesPresenter( pinnedMessagesBannerState = pinnedMessagesBannerState, dmUserVerificationState = dmUserVerificationState, roomMemberModerationState = roomMemberModerationState, - showSharedHistoryIcon = showSharedHistoryIcon, + topBarSharedHistoryIcon = topBarSharedHistoryIcon, successorRoom = roomInfo.successorRoom, eventSink = ::handleEvent, ) } + private fun RoomInfo.sharedHistoryIcon(): SharedHistoryIcon { + if (isEncrypted == true) { + if (historyVisibility == RoomHistoryVisibility.Shared) { + return SharedHistoryIcon.SHARED + } else if (historyVisibility == RoomHistoryVisibility.WorldReadable) { + return SharedHistoryIcon.WORLD_READABLE + } + } + + return SharedHistoryIcon.NONE + } + private fun RoomInfo.avatarData(): AvatarData { return AvatarData( id = id.value, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt index b37a916b2e..c18fb461e0 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt @@ -54,10 +54,22 @@ data class MessagesState( val pinnedMessagesBannerState: PinnedMessagesBannerState, val dmUserVerificationState: IdentityState?, val roomMemberModerationState: RoomMemberModerationState, - /** Should the top bar include the "history" icon? */ - val showSharedHistoryIcon: Boolean, + /** Type of "shared history" icon to show in the top bar. */ + val topBarSharedHistoryIcon: SharedHistoryIcon, val successorRoom: SuccessorRoom?, val eventSink: (MessagesEvent) -> Unit ) { val isTombstoned = successorRoom != null } + +/** Type of "shared history" icon to show in the top bar. */ +enum class SharedHistoryIcon { + /** Show no icon at all. */ + NONE, + + /** history_visibility: shared. */ + SHARED, + + /** history_visibility: world_readable. */ + WORLD_READABLE +} diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt index b657b4bbb4..d969ae1491 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt @@ -120,7 +120,7 @@ fun aMessagesState( pinnedMessagesBannerState: PinnedMessagesBannerState = aLoadedPinnedMessagesBannerState(), dmUserVerificationState: IdentityState? = null, roomMemberModerationState: RoomMemberModerationState = aRoomMemberModerationState(), - showSharedHistoryIcon: Boolean = false, + topBarSharedHistoryIcon: SharedHistoryIcon = SharedHistoryIcon.NONE, successorRoom: SuccessorRoom? = null, eventSink: (MessagesEvent) -> Unit = {}, ) = MessagesState( @@ -148,7 +148,7 @@ fun aMessagesState( pinnedMessagesBannerState = pinnedMessagesBannerState, dmUserVerificationState = dmUserVerificationState, roomMemberModerationState = roomMemberModerationState, - showSharedHistoryIcon = showSharedHistoryIcon, + topBarSharedHistoryIcon = topBarSharedHistoryIcon, successorRoom = successorRoom, eventSink = eventSink, ) diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt index 5d4ccf2d78..559392583f 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt @@ -225,7 +225,7 @@ fun MessagesView( heroes = state.heroes, roomCallState = state.roomCallState, dmUserIdentityState = state.dmUserVerificationState, - showSharedHistoryIcon = state.showSharedHistoryIcon, + sharedHistoryIcon = state.topBarSharedHistoryIcon, onBackClick = { hidingKeyboard { onBackClick() } }, onRoomDetailsClick = { hidingKeyboard { onRoomDetailsClick() } }, onJoinCallClick = onJoinCallClick, diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt index eb756a7369..5d3746f82e 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/topbars/MessagesViewTopBar.kt @@ -30,6 +30,7 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme import io.element.android.compound.tokens.generated.CompoundIcons +import io.element.android.features.messages.impl.SharedHistoryIcon import io.element.android.features.messages.impl.timeline.components.CallMenuItem import io.element.android.features.roomcall.api.RoomCallState import io.element.android.features.roomcall.api.aStandByCallState @@ -63,7 +64,7 @@ internal fun MessagesViewTopBar( heroes: ImmutableList, roomCallState: RoomCallState, dmUserIdentityState: IdentityState?, - showSharedHistoryIcon: Boolean, + sharedHistoryIcon: SharedHistoryIcon, onRoomDetailsClick: () -> Unit, onJoinCallClick: () -> Unit, onBackClick: () -> Unit, @@ -110,12 +111,18 @@ internal fun MessagesViewTopBar( else -> Unit } - if (showSharedHistoryIcon) { - Icon( + when (sharedHistoryIcon) { + SharedHistoryIcon.NONE -> Unit + SharedHistoryIcon.SHARED -> Icon( imageVector = CompoundIcons.History(), tint = ElementTheme.colors.iconInfoPrimary, contentDescription = stringResource(CommonStrings.common_shared_history), ) + SharedHistoryIcon.WORLD_READABLE -> Icon( + imageVector = CompoundIcons.UserProfileSolid(), + tint = ElementTheme.colors.iconInfoPrimary, + contentDescription = stringResource(CommonStrings.common_world_readable_history), + ) } } }, @@ -178,7 +185,7 @@ internal fun MessagesViewTopBarPreview() = ElementPreview { heroes: ImmutableList = persistentListOf(), roomCallState: RoomCallState = RoomCallState.Unavailable, dmUserIdentityState: IdentityState? = null, - showSharedHistoryIcon: Boolean = false, + sharedHistoryIcon: SharedHistoryIcon = SharedHistoryIcon.NONE, ) = MessagesViewTopBar( roomName = roomName, roomAvatar = roomAvatar, @@ -186,7 +193,7 @@ internal fun MessagesViewTopBarPreview() = ElementPreview { heroes = heroes, roomCallState = roomCallState, dmUserIdentityState = dmUserIdentityState, - showSharedHistoryIcon = showSharedHistoryIcon, + sharedHistoryIcon = sharedHistoryIcon, onRoomDetailsClick = {}, onJoinCallClick = {}, onBackClick = {}, @@ -223,7 +230,12 @@ internal fun MessagesViewTopBarPreview() = ElementPreview { AMessagesViewTopBar( roomName = "A DM with shared history", dmUserIdentityState = IdentityState.Verified, - showSharedHistoryIcon = true, + sharedHistoryIcon = SharedHistoryIcon.SHARED, + ) + HorizontalDivider() + AMessagesViewTopBar( + roomName = "A room with world_readable history", + sharedHistoryIcon = SharedHistoryIcon.WORLD_READABLE, ) } } diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt index 99d1448bcb..d52179f3ef 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt @@ -1233,7 +1233,28 @@ class MessagesPresenterTest { awaitItem() runCurrent() val state = awaitItem() - assertThat(state.showSharedHistoryIcon).isTrue() + assertThat(state.topBarSharedHistoryIcon).isEqualTo(SharedHistoryIcon.SHARED) + } + } + + @Test + fun `present - shows a "world_readable" icon if the room is encrypted and history is world_readable`() = runTest { + val presenter = createMessagesPresenter( + joinedRoom = FakeJoinedRoom( + baseRoom = FakeBaseRoom( + roomPermissions = roomPermissions(), + initialRoomInfo = aRoomInfo(isEncrypted = true, historyVisibility = RoomHistoryVisibility.WorldReadable), + ), + ), + featureFlagService = FakeFeatureFlagService( + initialState = mapOf(FeatureFlags.EnableKeyShareOnInvite.key to true) + ) + ) + presenter.testWithLifecycleOwner { + awaitItem() + runCurrent() + val state = awaitItem() + assertThat(state.topBarSharedHistoryIcon).isEqualTo(SharedHistoryIcon.WORLD_READABLE) } } diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Day_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Day_0_en.png index 4f36513ee3..b582a4edca 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Day_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Day_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2ca04a8092b40b50f3724bca9213ac2be4742c6b754ef949566fd23b052ab808 -size 46501 +oid sha256:6e4d063c70dcfa2e882c7c1305b22975d1f91f9e1495b7cf75550277309dd6b7 +size 53365 diff --git a/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Night_0_en.png b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Night_0_en.png index 84dcdeb6a6..0028cc506b 100644 --- a/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Night_0_en.png +++ b/tests/uitests/src/test/snapshots/images/features.messages.impl.topbars_MessagesViewTopBar_Night_0_en.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cbca529b51092d41afbd772cb2ed207709423c5590588a128a7c48bfad64917b -size 45275 +oid sha256:3c9aea00c853d6f34988bd46b33275d6f6fe682c7e85c7ef3b87c4d4b45cbb63 +size 51969