Add history sharing badges to room details (#6132)

* feat: Add history sharing badges to room details view

* tests: Add snapshots for history sharing room details badges

* fix: Disable soft-wrapping in badges, use FlowRow

* tests: Add unit test for `RoomDetailsState` and history sharing badges.

* tests: Add `MatrixBadgeAtomNeutralWrappingPreview` to exceptions

* chore: Re-order `MatrixBadgeAtom` previews

* fix: Add `Immutable` annotation to `RoomHistoryVisibility`.

* fix: Correct translation for shared badge
This commit is contained in:
Skye Elliot
2026-02-06 19:03:52 +00:00
committed by GitHub
parent db310e42d4
commit 028ec221b0
20 changed files with 156 additions and 3 deletions

View File

@@ -168,6 +168,8 @@ class RoomDetailsPresenter(
val canReportRoom by produceState(false) { value = client.canReportRoom() }
val enableKeyShareOnInvite by featureFlagService.isFeatureEnabledFlow(FeatureFlags.EnableKeyShareOnInvite).collectAsState(initial = false)
return RoomDetailsState(
roomId = room.roomId,
roomName = roomName,
@@ -197,6 +199,8 @@ class RoomDetailsPresenter(
isTombstoned = roomInfo.successorRoom != null,
showDebugInfo = isDeveloperModeEnabled,
roomVersion = roomInfo.roomVersion,
enableKeyShareOnInvite = enableKeyShareOnInvite,
roomHistoryVisibility = roomInfo.historyVisibility,
eventSink = ::handleEvent,
)
}

View File

@@ -17,6 +17,7 @@ import io.element.android.libraries.matrix.api.core.RoomAlias
import io.element.android.libraries.matrix.api.core.RoomId
import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomNotificationSettings
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
import io.element.android.libraries.matrix.api.user.MatrixUser
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.toImmutableList
@@ -50,6 +51,8 @@ data class RoomDetailsState(
val isTombstoned: Boolean,
val showDebugInfo: Boolean,
val roomVersion: String?,
val enableKeyShareOnInvite: Boolean,
val roomHistoryVisibility: RoomHistoryVisibility,
val eventSink: (RoomDetailsEvent) -> Unit
) {
val roomBadges = buildList {
@@ -61,6 +64,14 @@ data class RoomDetailsState(
if (isPublic) {
add(RoomBadge.PUBLIC)
}
if (enableKeyShareOnInvite && isEncrypted) {
when (roomHistoryVisibility) {
RoomHistoryVisibility.Invited, RoomHistoryVisibility.Joined -> add(RoomBadge.SHARED_HISTORY_HIDDEN)
RoomHistoryVisibility.Shared -> add(RoomBadge.SHARED_HISTORY_SHARED)
RoomHistoryVisibility.WorldReadable -> add(RoomBadge.SHARED_HISTORY_WORLD_READABLE)
else -> {}
}
}
}.toImmutableList()
}
@@ -84,4 +95,7 @@ enum class RoomBadge {
ENCRYPTED,
NOT_ENCRYPTED,
PUBLIC,
SHARED_HISTORY_HIDDEN,
SHARED_HISTORY_SHARED,
SHARED_HISTORY_WORLD_READABLE
}

View File

@@ -26,6 +26,7 @@ import io.element.android.libraries.matrix.api.room.RoomMember
import io.element.android.libraries.matrix.api.room.RoomMembershipState
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
import io.element.android.libraries.matrix.api.room.RoomNotificationSettings
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
import io.element.android.libraries.matrix.api.user.MatrixUser
import io.element.android.libraries.matrix.ui.components.aMatrixUserList
import kotlinx.collections.immutable.toImmutableList
@@ -57,6 +58,9 @@ open class RoomDetailsStateProvider : PreviewParameterProvider<RoomDetailsState>
aRoomDetailsState(isTombstoned = true),
aDmRoomDetailsState(dmRoomMemberVerificationState = UserProfileVerificationState.VERIFIED),
aDmRoomDetailsState(dmRoomMemberVerificationState = UserProfileVerificationState.VERIFICATION_VIOLATION),
aSharedHistoryRoomDetailsState(roomHistoryVisibility = RoomHistoryVisibility.Joined),
aSharedHistoryRoomDetailsState(roomHistoryVisibility = RoomHistoryVisibility.Shared),
aSharedHistoryRoomDetailsState(roomHistoryVisibility = RoomHistoryVisibility.WorldReadable),
// Add other state here
)
}
@@ -117,6 +121,8 @@ fun aRoomDetailsState(
canReportRoom: Boolean = true,
isTombstoned: Boolean = false,
showDebugInfo: Boolean = false,
enableKeyShareOnInvite: Boolean = false,
roomHistoryVisibility: RoomHistoryVisibility = RoomHistoryVisibility.Shared,
eventSink: (RoomDetailsEvent) -> Unit = {},
) = RoomDetailsState(
roomId = roomId,
@@ -147,6 +153,8 @@ fun aRoomDetailsState(
isTombstoned = isTombstoned,
showDebugInfo = showDebugInfo,
roomVersion = "12",
enableKeyShareOnInvite = enableKeyShareOnInvite,
roomHistoryVisibility = roomHistoryVisibility,
eventSink = eventSink,
)
@@ -182,3 +190,11 @@ fun aDmRoomDetailsState(
verificationState = dmRoomMemberVerificationState,
)
)
fun aSharedHistoryRoomDetailsState(
roomHistoryVisibility: RoomHistoryVisibility
) = aRoomDetailsState(
isEncrypted = true,
enableKeyShareOnInvite = true,
roomHistoryVisibility = roomHistoryVisibility,
)

View File

@@ -518,6 +518,27 @@ private fun RoomBadge.toMatrixBadgeData(): MatrixBadgeAtom.MatrixBadgeData {
type = MatrixBadgeAtom.Type.Info,
)
}
RoomBadge.SHARED_HISTORY_HIDDEN -> {
MatrixBadgeAtom.MatrixBadgeData(
text = stringResource(R.string.crypto_history_sharing_room_info_hidden_badge_content),
icon = CompoundIcons.VisibilityOff(),
type = MatrixBadgeAtom.Type.Info
)
}
RoomBadge.SHARED_HISTORY_SHARED -> {
MatrixBadgeAtom.MatrixBadgeData(
text = stringResource(R.string.crypto_history_sharing_room_info_shared_badge_content),
icon = CompoundIcons.History(),
type = MatrixBadgeAtom.Type.Info
)
}
RoomBadge.SHARED_HISTORY_WORLD_READABLE -> {
MatrixBadgeAtom.MatrixBadgeData(
text = stringResource(R.string.crypto_history_sharing_room_info_world_readable_badge_content),
icon = CompoundIcons.UserProfileSolid(),
type = MatrixBadgeAtom.Type.Info
)
}
}
}

View File

@@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="crypto_history_sharing_room_info_hidden_badge_content">"New members don\'t see history"</string>
<string name="crypto_history_sharing_room_info_shared_badge_content">"New members see history"</string>
<string name="crypto_history_sharing_room_info_world_readable_badge_content">"Anyone can see history"</string>
<string name="screen_edit_room_address_room_address_section_footer">"Youll need an address in order to make it visible in the public directory."</string>
<string name="screen_edit_room_address_title">"Edit address"</string>
<string name="screen_notification_settings_edit_failed_updating_default_mode">"An error occurred while updating the notification setting."</string>

View File

@@ -9,6 +9,7 @@
package io.element.android.features.roomdetails.impl
import com.google.common.truth.Truth.assertThat
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
import kotlinx.collections.immutable.persistentListOf
import org.junit.Test
@@ -56,4 +57,52 @@ class RoomDetailsStateTest {
persistentListOf(RoomBadge.ENCRYPTED)
)
}
@Test
fun `room public not encrypted should not have history sharing badges`() {
val sut = aRoomDetailsState(
isEncrypted = false,
enableKeyShareOnInvite = true,
roomHistoryVisibility = RoomHistoryVisibility.Shared
)
assertThat(sut.roomBadges).isEqualTo(
persistentListOf(RoomBadge.NOT_ENCRYPTED, RoomBadge.PUBLIC)
)
}
@Test
fun `room public encrypted should have history sharing hidden badge`() {
val sut = aRoomDetailsState(
isEncrypted = true,
enableKeyShareOnInvite = true,
roomHistoryVisibility = RoomHistoryVisibility.Joined
)
assertThat(sut.roomBadges).isEqualTo(
persistentListOf(RoomBadge.ENCRYPTED, RoomBadge.PUBLIC, RoomBadge.SHARED_HISTORY_HIDDEN)
)
}
@Test
fun `room public encrypted should have history sharing shared badge`() {
val sut = aRoomDetailsState(
isEncrypted = true,
enableKeyShareOnInvite = true,
roomHistoryVisibility = RoomHistoryVisibility.Shared
)
assertThat(sut.roomBadges).isEqualTo(
persistentListOf(RoomBadge.ENCRYPTED, RoomBadge.PUBLIC, RoomBadge.SHARED_HISTORY_SHARED)
)
}
@Test
fun `room public encrypted should have history sharing world_readable badge`() {
val sut = aRoomDetailsState(
isEncrypted = true,
enableKeyShareOnInvite = true,
roomHistoryVisibility = RoomHistoryVisibility.WorldReadable
)
assertThat(sut.roomBadges).isEqualTo(
persistentListOf(RoomBadge.ENCRYPTED, RoomBadge.PUBLIC, RoomBadge.SHARED_HISTORY_WORLD_READABLE)
)
}
}