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:
@@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
|
||||
@@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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">"You’ll 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>
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,6 +98,18 @@ internal fun MatrixBadgeAtomNegativePreview() = ElementPreview {
|
||||
)
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun MatrixBadgeAtomNeutralWrappingPreview() = ElementPreview {
|
||||
MatrixBadgeAtom.View(
|
||||
MatrixBadgeAtom.MatrixBadgeData(
|
||||
text = "How much wood could a wood chuck chuck if a wood chuck could chuck wood",
|
||||
icon = CompoundIcons.LockOff(),
|
||||
type = MatrixBadgeAtom.Type.Info,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@PreviewsDayNight
|
||||
@Composable
|
||||
internal fun MatrixBadgeAtomInfoPreview() = ElementPreview {
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
package io.element.android.libraries.designsystem.atomic.molecules
|
||||
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.FlowRow
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.libraries.designsystem.atomic.atoms.MatrixBadgeAtom
|
||||
@@ -22,10 +23,11 @@ fun MatrixBadgeRowMolecule(
|
||||
data: ImmutableList<MatrixBadgeAtom.MatrixBadgeData>,
|
||||
modifier: Modifier = Modifier,
|
||||
) {
|
||||
Row(
|
||||
FlowRow(
|
||||
modifier = modifier
|
||||
.padding(start = 16.dp, end = 16.dp, top = 8.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp),
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.CenterHorizontally),
|
||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
for (badge in data) {
|
||||
MatrixBadgeAtom.View(badge)
|
||||
|
||||
@@ -21,6 +21,7 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.Shape
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
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
|
||||
@@ -63,6 +64,8 @@ fun Badge(
|
||||
text = text,
|
||||
style = ElementTheme.typography.fontBodySmRegular,
|
||||
color = textColor,
|
||||
overflow = TextOverflow.Ellipsis,
|
||||
softWrap = false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
|
||||
package io.element.android.libraries.matrix.api.room.history
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
@Immutable
|
||||
sealed interface RoomHistoryVisibility {
|
||||
/**
|
||||
* Previous events are accessible to newly joined members from the point
|
||||
|
||||
@@ -97,6 +97,7 @@ class KonsistPreviewTest {
|
||||
"MatrixBadgeAtomInfoPreview",
|
||||
"MatrixBadgeAtomNegativePreview",
|
||||
"MatrixBadgeAtomNeutralPreview",
|
||||
"MatrixBadgeAtomNeutralWrappingPreview",
|
||||
"MatrixBadgeAtomPositivePreview",
|
||||
"MentionSpanThemeInTimelinePreview",
|
||||
"MessageComposerViewVoicePreview",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -206,6 +206,7 @@
|
||||
{
|
||||
"name" : ":features:roomdetails:impl",
|
||||
"includeRegex" : [
|
||||
"crypto\\.history_sharing\\.room_info_.*",
|
||||
"screen_room_details_.*",
|
||||
"screen\\.room_details\\..*",
|
||||
"screen_room_member_list_.*",
|
||||
|
||||
Reference in New Issue
Block a user