Show an icon in the room header for shared history (#6090)
Add a decoration to the header for encrypted rooms with `history_visibility:
{shared|public}`.
Fixes: #6070
---------
Co-authored-by: ElementBot <android@element.io>
Co-authored-by: Jorge Martín <jorgem@element.io>
This commit is contained in:
committed by
GitHub
parent
5cfb69f0fa
commit
7dae283874
@@ -75,6 +75,7 @@ import io.element.android.libraries.matrix.api.permalink.PermalinkParser
|
||||
import io.element.android.libraries.matrix.api.room.JoinedRoom
|
||||
import io.element.android.libraries.matrix.api.room.RoomInfo
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembersState
|
||||
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
|
||||
import io.element.android.libraries.matrix.api.room.isDm
|
||||
import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState
|
||||
import io.element.android.libraries.matrix.api.timeline.item.event.EventOrTransactionId
|
||||
@@ -207,6 +208,16 @@ class MessagesPresenter(
|
||||
val dmRoomMember by room.getDirectRoomMember(membersState)
|
||||
val roomMemberIdentityStateChanges = identityChangeState.roomMemberIdentityStateChanges
|
||||
|
||||
val isKeyShareOnInviteEnabled by featureFlagService.isFeatureEnabledFlow(FeatureFlags.EnableKeyShareOnInvite).collectAsState(initial = false)
|
||||
// The top bar should show a "history" icon if:
|
||||
// * 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)
|
||||
|
||||
LifecycleResumeEffect(dmRoomMember, roomInfo.isEncrypted) {
|
||||
if (roomInfo.isEncrypted == true) {
|
||||
val dmRoomMemberId = dmRoomMember?.userId
|
||||
@@ -290,6 +301,7 @@ class MessagesPresenter(
|
||||
pinnedMessagesBannerState = pinnedMessagesBannerState,
|
||||
dmUserVerificationState = dmUserVerificationState,
|
||||
roomMemberModerationState = roomMemberModerationState,
|
||||
showSharedHistoryIcon = showSharedHistoryIcon,
|
||||
successorRoom = roomInfo.successorRoom,
|
||||
eventSink = ::handleEvent,
|
||||
)
|
||||
|
||||
@@ -56,6 +56,8 @@ data class MessagesState(
|
||||
val pinnedMessagesBannerState: PinnedMessagesBannerState,
|
||||
val dmUserVerificationState: IdentityState?,
|
||||
val roomMemberModerationState: RoomMemberModerationState,
|
||||
/** Should the top bar include the "history" icon? */
|
||||
val showSharedHistoryIcon: Boolean,
|
||||
val successorRoom: SuccessorRoom?,
|
||||
val eventSink: (MessagesEvent) -> Unit
|
||||
) {
|
||||
|
||||
@@ -132,6 +132,7 @@ fun aMessagesState(
|
||||
pinnedMessagesBannerState: PinnedMessagesBannerState = aLoadedPinnedMessagesBannerState(),
|
||||
dmUserVerificationState: IdentityState? = null,
|
||||
roomMemberModerationState: RoomMemberModerationState = aRoomMemberModerationState(),
|
||||
showSharedHistoryIcon: Boolean = false,
|
||||
successorRoom: SuccessorRoom? = null,
|
||||
eventSink: (MessagesEvent) -> Unit = {},
|
||||
) = MessagesState(
|
||||
@@ -160,6 +161,7 @@ fun aMessagesState(
|
||||
pinnedMessagesBannerState = pinnedMessagesBannerState,
|
||||
dmUserVerificationState = dmUserVerificationState,
|
||||
roomMemberModerationState = roomMemberModerationState,
|
||||
showSharedHistoryIcon = showSharedHistoryIcon,
|
||||
successorRoom = successorRoom,
|
||||
eventSink = eventSink,
|
||||
)
|
||||
|
||||
@@ -226,6 +226,7 @@ fun MessagesView(
|
||||
heroes = state.heroes,
|
||||
roomCallState = state.roomCallState,
|
||||
dmUserIdentityState = state.dmUserVerificationState,
|
||||
showSharedHistoryIcon = state.showSharedHistoryIcon,
|
||||
onBackClick = { hidingKeyboard { onBackClick() } },
|
||||
onRoomDetailsClick = { hidingKeyboard { onRoomDetailsClick() } },
|
||||
onJoinCallClick = onJoinCallClick,
|
||||
|
||||
@@ -63,6 +63,7 @@ internal fun MessagesViewTopBar(
|
||||
heroes: ImmutableList<AvatarData>,
|
||||
roomCallState: RoomCallState,
|
||||
dmUserIdentityState: IdentityState?,
|
||||
showSharedHistoryIcon: Boolean,
|
||||
onRoomDetailsClick: () -> Unit,
|
||||
onJoinCallClick: () -> Unit,
|
||||
onBackClick: () -> Unit,
|
||||
@@ -108,6 +109,14 @@ internal fun MessagesViewTopBar(
|
||||
}
|
||||
else -> Unit
|
||||
}
|
||||
|
||||
if (showSharedHistoryIcon) {
|
||||
Icon(
|
||||
imageVector = CompoundIcons.History(),
|
||||
tint = ElementTheme.colors.iconInfoPrimary,
|
||||
contentDescription = stringResource(CommonStrings.common_shared_history),
|
||||
)
|
||||
}
|
||||
}
|
||||
},
|
||||
actions = {
|
||||
@@ -169,6 +178,7 @@ internal fun MessagesViewTopBarPreview() = ElementPreview {
|
||||
heroes: ImmutableList<AvatarData> = persistentListOf(),
|
||||
roomCallState: RoomCallState = RoomCallState.Unavailable,
|
||||
dmUserIdentityState: IdentityState? = null,
|
||||
showSharedHistoryIcon: Boolean = false,
|
||||
) = MessagesViewTopBar(
|
||||
roomName = roomName,
|
||||
roomAvatar = roomAvatar,
|
||||
@@ -176,6 +186,7 @@ internal fun MessagesViewTopBarPreview() = ElementPreview {
|
||||
heroes = heroes,
|
||||
roomCallState = roomCallState,
|
||||
dmUserIdentityState = dmUserIdentityState,
|
||||
showSharedHistoryIcon = showSharedHistoryIcon,
|
||||
onRoomDetailsClick = {},
|
||||
onJoinCallClick = {},
|
||||
onBackClick = {},
|
||||
@@ -208,5 +219,11 @@ internal fun MessagesViewTopBarPreview() = ElementPreview {
|
||||
isTombstoned = true,
|
||||
dmUserIdentityState = IdentityState.VerificationViolation
|
||||
)
|
||||
HorizontalDivider()
|
||||
AMessagesViewTopBar(
|
||||
roomName = "A DM with shared history",
|
||||
dmUserIdentityState = IdentityState.Verified,
|
||||
showSharedHistoryIcon = true,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,6 +65,7 @@ import io.element.android.libraries.matrix.api.room.MessageEventType
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembersState
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembershipState
|
||||
import io.element.android.libraries.matrix.api.room.StateEventType
|
||||
import io.element.android.libraries.matrix.api.room.history.RoomHistoryVisibility
|
||||
import io.element.android.libraries.matrix.api.room.tombstone.SuccessorRoom
|
||||
import io.element.android.libraries.matrix.api.timeline.Timeline
|
||||
import io.element.android.libraries.matrix.api.timeline.item.TimelineItemDebugInfo
|
||||
@@ -1216,6 +1217,27 @@ class MessagesPresenterTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - shows a "history" icon if the room is encrypted and history is shared`() = runTest {
|
||||
val presenter = createMessagesPresenter(
|
||||
joinedRoom = FakeJoinedRoom(
|
||||
baseRoom = FakeBaseRoom(
|
||||
roomPermissions = roomPermissions(),
|
||||
initialRoomInfo = aRoomInfo(isEncrypted = true, historyVisibility = RoomHistoryVisibility.Shared),
|
||||
),
|
||||
),
|
||||
featureFlagService = FakeFeatureFlagService(
|
||||
initialState = mapOf(FeatureFlags.EnableKeyShareOnInvite.key to true)
|
||||
)
|
||||
)
|
||||
presenter.testWithLifecycleOwner {
|
||||
awaitItem()
|
||||
runCurrent()
|
||||
val state = awaitItem()
|
||||
assertThat(state.showSharedHistoryIcon).isTrue()
|
||||
}
|
||||
}
|
||||
|
||||
private fun roomPermissions(
|
||||
canStartCall: Boolean = true,
|
||||
canRedactOther: Boolean = true,
|
||||
|
||||
@@ -334,6 +334,7 @@ Reason: %1$s."</string>
|
||||
<string name="common_server_url">"Server URL"</string>
|
||||
<string name="common_settings">"Settings"</string>
|
||||
<string name="common_share_space">"Share space"</string>
|
||||
<string name="common_shared_history">"New members see history"</string>
|
||||
<string name="common_shared_location">"Shared location"</string>
|
||||
<string name="common_shared_space">"Shared space"</string>
|
||||
<string name="common_signing_out">"Signing out"</string>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user