Replace 'leave room' text with 'leave conversation' for DMs (#2231)

* Replace 'leave room' text with 'leave conversation' for DMs

* Add `isDm` property to both `RoomSummary` and `RoomListRoomSummary`

* Remove redundant `leave_conversation_alert_subtitle_*` texts

* Fix maestro flow

---------

Co-authored-by: ElementBot <benoitm+elementbot@element.io>
This commit is contained in:
Jorge Martin Espinosa
2024-01-16 15:49:44 +01:00
committed by GitHub
parent a9776f9fcb
commit 64a18afc1b
77 changed files with 115 additions and 19 deletions

View File

@@ -9,5 +9,5 @@ appId: ${APP_ID}
index: 1
- takeScreenshot: build/maestro/330-createAndDeleteDM
- tapOn: "maestroelement2"
- tapOn: "Leave room"
- tapOn: "Leave conversation"
- tapOn: "Leave"

1
changelog.d/2218.misc Normal file
View File

@@ -0,0 +1 @@
Replace 'leave room' text with 'leave conversation' for DMs.

View File

@@ -26,6 +26,7 @@ data class LeaveRoomState(
) {
sealed interface Confirmation {
data object Hidden : Confirmation
data class Dm(val roomId: RoomId) : Confirmation
data class Generic(val roomId: RoomId) : Confirmation
data class PrivateRoom(val roomId: RoomId) : Confirmation
data class LastUserInRoom(val roomId: RoomId) : Confirmation

View File

@@ -28,17 +28,17 @@ class LeaveRoomStateProvider : PreviewParameterProvider<LeaveRoomState> {
error = LeaveRoomState.Error.Hidden,
),
aLeaveRoomState(
confirmation = LeaveRoomState.Confirmation.Generic(A_ROOM_ID),
confirmation = LeaveRoomState.Confirmation.Generic(roomId = A_ROOM_ID),
progress = LeaveRoomState.Progress.Hidden,
error = LeaveRoomState.Error.Hidden,
),
aLeaveRoomState(
confirmation = LeaveRoomState.Confirmation.PrivateRoom(A_ROOM_ID),
confirmation = LeaveRoomState.Confirmation.PrivateRoom(roomId = A_ROOM_ID),
progress = LeaveRoomState.Progress.Hidden,
error = LeaveRoomState.Error.Hidden,
),
aLeaveRoomState(
confirmation = LeaveRoomState.Confirmation.LastUserInRoom(A_ROOM_ID),
confirmation = LeaveRoomState.Confirmation.LastUserInRoom(roomId = A_ROOM_ID),
progress = LeaveRoomState.Progress.Hidden,
error = LeaveRoomState.Error.Hidden,
),
@@ -52,6 +52,11 @@ class LeaveRoomStateProvider : PreviewParameterProvider<LeaveRoomState> {
progress = LeaveRoomState.Progress.Hidden,
error = LeaveRoomState.Error.Shown,
),
aLeaveRoomState(
confirmation = LeaveRoomState.Confirmation.Dm(roomId = A_ROOM_ID),
progress = LeaveRoomState.Progress.Hidden,
error = LeaveRoomState.Error.Hidden,
),
)
}

View File

@@ -47,21 +47,32 @@ private fun LeaveRoomConfirmationDialog(
) {
when (state.confirmation) {
is LeaveRoomState.Confirmation.Hidden -> {}
is LeaveRoomState.Confirmation.Dm -> LeaveRoomConfirmationDialog(
text = R.string.leave_conversation_alert_subtitle,
roomId = state.confirmation.roomId,
isDm = true,
eventSink = state.eventSink,
)
is LeaveRoomState.Confirmation.PrivateRoom -> LeaveRoomConfirmationDialog(
text = R.string.leave_room_alert_private_subtitle,
roomId = state.confirmation.roomId,
isDm = false,
eventSink = state.eventSink,
)
is LeaveRoomState.Confirmation.LastUserInRoom -> LeaveRoomConfirmationDialog(
text = R.string.leave_room_alert_empty_subtitle,
roomId = state.confirmation.roomId,
isDm = false,
eventSink = state.eventSink,
)
is LeaveRoomState.Confirmation.Generic -> LeaveRoomConfirmationDialog(
text = R.string.leave_room_alert_subtitle,
roomId = state.confirmation.roomId,
isDm = false,
eventSink = state.eventSink,
)
}
@@ -71,10 +82,11 @@ private fun LeaveRoomConfirmationDialog(
private fun LeaveRoomConfirmationDialog(
@StringRes text: Int,
roomId: RoomId,
isDm: Boolean,
eventSink: (LeaveRoomEvent) -> Unit,
) {
ConfirmationDialog(
title = stringResource(CommonStrings.action_leave_room),
title = stringResource(if (isDm) CommonStrings.action_leave_conversation else CommonStrings.action_leave_room),
content = stringResource(text),
submitText = stringResource(CommonStrings.action_leave),
onSubmitClicked = { eventSink(LeaveRoomEvent.LeaveRoom(roomId)) },

View File

@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<string name="leave_conversation_alert_subtitle">"Are you sure that you want to leave this conversation? This conversation is not public and you won\'t be able to rejoin without an invite."</string>
<string name="leave_room_alert_empty_subtitle">"Are you sure that you want to leave this room? You\'re the only person here. If you leave, no one will be able to join in the future, including you."</string>
<string name="leave_room_alert_private_subtitle">"Are you sure that you want to leave this room? This room is not public and you won\'t be able to rejoin without an invite."</string>
<string name="leave_room_alert_subtitle">"Are you sure that you want to leave the room?"</string>

View File

@@ -24,6 +24,7 @@ import androidx.compose.runtime.rememberCoroutineScope
import io.element.android.features.leaveroom.api.LeaveRoomEvent
import io.element.android.features.leaveroom.api.LeaveRoomPresenter
import io.element.android.features.leaveroom.api.LeaveRoomState
import io.element.android.features.leaveroom.api.LeaveRoomState.Confirmation.Dm
import io.element.android.features.leaveroom.api.LeaveRoomState.Confirmation.Generic
import io.element.android.features.leaveroom.api.LeaveRoomState.Confirmation.LastUserInRoom
import io.element.android.features.leaveroom.api.LeaveRoomState.Confirmation.PrivateRoom
@@ -85,6 +86,7 @@ private suspend fun showLeaveRoomAlert(
) {
matrixClient.getRoom(roomId)?.use { room ->
confirmation.value = when {
room.isDm -> Dm(roomId)
!room.isPublic -> PrivateRoom(roomId)
room.joinedMemberCount == 1L -> LastUserInRoom(roomId)
else -> Generic(roomId)

View File

@@ -114,6 +114,26 @@ class LeaveRoomPresenterImplTest {
}
}
@Test
fun `present - show DM confirmation`() = runTest {
val presenter = createLeaveRoomPresenter(
client = FakeMatrixClient().apply {
givenGetRoomResult(
roomId = A_ROOM_ID,
result = FakeMatrixRoom(activeMemberCount = 2, isDirect = true, isOneToOne = true),
)
}
)
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
initialState.eventSink(LeaveRoomEvent.ShowConfirmation(A_ROOM_ID))
val confirmationState = awaitItem()
assertThat(confirmationState.confirmation).isEqualTo(LeaveRoomState.Confirmation.Dm(A_ROOM_ID))
}
}
@Test
fun `present - leaving a room leaves the room`() = runTest {
val roomMembershipObserver = RoomMembershipObserver()

View File

@@ -183,9 +183,8 @@ class MessageComposerPresenter @Inject constructor(
val currentUserId = currentSessionIdHolder.current
suspend fun canSendRoomMention(): Boolean {
val roomIsDm = room.isDirect && room.isOneToOne
val userCanSendAtRoom = room.canUserTriggerRoomNotification(currentUserId).getOrDefault(false)
return !roomIsDm && userCanSendAtRoom
return !room.isDm && userCanSendAtRoom
}
// This will trigger a search immediately when `@` is typed

View File

@@ -190,9 +190,10 @@ fun RoomDetailsView(
BlockUserDialogs(roomMemberState)
}
OtherActionsSection(onLeaveRoom = {
state.eventSink(RoomDetailsEvent.LeaveRoom)
})
OtherActionsSection(
isDm = state.roomType is RoomDetailsType.Dm,
onLeaveRoom = { state.eventSink(RoomDetailsEvent.LeaveRoom) }
)
}
}
}
@@ -410,10 +411,17 @@ private fun SecuritySection(modifier: Modifier = Modifier) {
}
@Composable
private fun OtherActionsSection(onLeaveRoom: () -> Unit, modifier: Modifier = Modifier) {
private fun OtherActionsSection(isDm: Boolean, onLeaveRoom: () -> Unit, modifier: Modifier = Modifier) {
PreferenceCategory(showDivider = false, modifier = modifier) {
ListItem(
headlineContent = { Text(stringResource(R.string.screen_room_details_leave_room_title)) },
headlineContent = {
val leaveText = stringResource(id = if (isDm) {
R.string.screen_room_details_leave_conversation_title
} else {
R.string.screen_room_details_leave_room_title
})
Text(leaveText)
},
leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Leave)),
style = ListItemStyle.Destructive,
onClick = onLeaveRoom,

View File

@@ -47,6 +47,7 @@
<string name="screen_dm_details_unblock_alert_action">"Unblock"</string>
<string name="screen_dm_details_unblock_alert_description">"You\'ll be able to see all messages from them again."</string>
<string name="screen_dm_details_unblock_user">"Unblock user"</string>
<string name="screen_room_details_leave_conversation_title">"Leave conversation"</string>
<string name="screen_room_details_leave_room_title">"Leave room"</string>
<string name="screen_room_details_security_title">"Security"</string>
<string name="screen_room_details_topic_title">"Topic"</string>

View File

@@ -95,7 +95,14 @@ private fun RoomListModalBottomSheetContent(
style = ListItemStyle.Primary,
)
ListItem(
headlineContent = { Text(text = stringResource(id = CommonStrings.action_leave_room)) },
headlineContent = {
val leaveText = stringResource(id = if (contextMenu.isDm) {
CommonStrings.action_leave_conversation
} else {
CommonStrings.action_leave_room
})
Text(text = leaveText)
},
modifier = Modifier.clickable { onLeaveRoomClicked(contextMenu.roomId) },
leadingContent = ListItemContent.Icon(
iconSource = IconSource.Vector(
@@ -117,7 +124,22 @@ internal fun RoomListModalBottomSheetContentPreview() = ElementPreview {
RoomListModalBottomSheetContent(
contextMenu = RoomListState.ContextMenu.Shown(
roomId = RoomId(value = "!aRoom:aDomain"),
roomName = "aRoom"
roomName = "aRoom",
isDm = false,
),
onRoomSettingsClicked = {},
onLeaveRoomClicked = {}
)
}
@PreviewsDayNight
@Composable
internal fun RoomListModalBottomSheetContentForDmPreview() = ElementPreview {
RoomListModalBottomSheetContent(
contextMenu = RoomListState.ContextMenu.Shown(
roomId = RoomId(value = "!aRoom:aDomain"),
roomName = "aRoom",
isDm = true,
),
onRoomSettingsClicked = {},
onLeaveRoomClicked = {}

View File

@@ -119,7 +119,8 @@ class RoomListPresenter @Inject constructor(
is RoomListEvents.ShowContextMenu -> {
contextMenu = RoomListState.ContextMenu.Shown(
roomId = event.roomListRoomSummary.roomId,
roomName = event.roomListRoomSummary.name
roomName = event.roomListRoomSummary.name,
isDm = event.roomListRoomSummary.isDm,
)
}
is RoomListEvents.HideContextMenu -> contextMenu = RoomListState.ContextMenu.Hidden

View File

@@ -46,6 +46,7 @@ data class RoomListState(
data class Shown(
val roomId: RoomId,
val roomName: String,
val isDm: Boolean,
) : ContextMenu
}
}

View File

@@ -44,7 +44,8 @@ open class RoomListStateProvider : PreviewParameterProvider<RoomListState> {
aRoomListState().copy(
contextMenu = RoomListState.ContextMenu.Shown(
roomId = RoomId("!aRoom:aDomain"),
roomName = "A nice room name"
roomName = "A nice room name",
isDm = false,
)
),
aRoomListState().copy(displayRecoveryKeyPrompt = true),

View File

@@ -162,6 +162,7 @@ class RoomListDataSource @Inject constructor(
avatarData = avatarData,
notificationMode = roomSummary.details.notificationMode,
hasOngoingCall = roomSummary.details.hasOngoingCall,
isDm = roomSummary.details.isDm,
)
}
null -> null

View File

@@ -34,4 +34,5 @@ data class RoomListRoomSummary(
val isPlaceholder: Boolean = false,
val notificationMode: RoomNotificationMode? = null,
val hasOngoingCall: Boolean = false,
val isDm: Boolean = false,
)

View File

@@ -321,7 +321,7 @@ class RoomListPresenterTests {
val shownState = awaitItem()
assertThat(shownState.contextMenu)
.isEqualTo(RoomListState.ContextMenu.Shown(summary.roomId, summary.name))
.isEqualTo(RoomListState.ContextMenu.Shown(summary.roomId, summary.name, false))
scope.cancel()
}
}
@@ -341,7 +341,7 @@ class RoomListPresenterTests {
val shownState = awaitItem()
assertThat(shownState.contextMenu)
.isEqualTo(RoomListState.ContextMenu.Shown(summary.roomId, summary.name))
.isEqualTo(RoomListState.ContextMenu.Shown(summary.roomId, summary.name, false))
shownState.eventSink(RoomListEvents.HideContextMenu)
val hiddenState = awaitItem()

View File

@@ -52,6 +52,9 @@ interface MatrixRoom : Closeable {
val activeMemberCount: Long
val joinedMemberCount: Long
/** Whether the room is a direct message. */
val isDm: Boolean get() = isDirect && isOneToOne
val roomInfoFlow: Flow<MatrixRoomInfo>
/**

View File

@@ -45,4 +45,5 @@ data class RoomSummaryDetails(
val inviter: RoomMember? = null,
val notificationMode: RoomNotificationMode? = null,
val hasOngoingCall: Boolean = false,
val isDm: Boolean = false,
)

View File

@@ -41,6 +41,7 @@ class RoomSummaryDetailsFactory(private val roomMessageFactory: RoomMessageFacto
inviter = roomInfo.inviter?.let(RoomMemberMapper::map),
notificationMode = roomInfo.userDefinedNotificationMode?.let(RoomNotificationSettingsMapper::mapMode),
hasOngoingCall = roomInfo.hasRoomCall,
isDm = roomInfo.isDirect && roomInfo.activeMembersCount.toLong() == 2L,
)
}
}

View File

@@ -57,6 +57,7 @@
<string name="action_join">"Join"</string>
<string name="action_learn_more">"Learn more"</string>
<string name="action_leave">"Leave"</string>
<string name="action_leave_conversation">"Leave conversation"</string>
<string name="action_leave_room">"Leave room"</string>
<string name="action_manage_account">"Manage account"</string>
<string name="action_manage_devices">"Manage devices"</string>

View File

@@ -97,7 +97,8 @@
{
"name" : ":features:leaveroom:api",
"includeRegex" : [
"leave_room_alert_.*"
"leave_room_alert_.*",
"leave_conversation_alert_.*"
]
},
{