Iterate on indicators on room list #2079
This commit is contained in:
parent
799f351536
commit
e6ad262329
25 changed files with 255 additions and 169 deletions
1
.idea/dictionaries/shared.xml
generated
1
.idea/dictionaries/shared.xml
generated
|
|
@ -16,6 +16,7 @@
|
||||||
<w>snackbar</w>
|
<w>snackbar</w>
|
||||||
<w>swipeable</w>
|
<w>swipeable</w>
|
||||||
<w>textfields</w>
|
<w>textfields</w>
|
||||||
|
<w>tombstoned</w>
|
||||||
</words>
|
</words>
|
||||||
</dictionary>
|
</dictionary>
|
||||||
</component>
|
</component>
|
||||||
|
|
|
||||||
|
|
@ -170,7 +170,7 @@ class InviteListPresenter @Inject constructor(
|
||||||
AvatarData(
|
AvatarData(
|
||||||
id = roomId.value,
|
id = roomId.value,
|
||||||
name = name,
|
name = name,
|
||||||
url = avatarURLString,
|
url = avatarUrl,
|
||||||
size = AvatarSize.RoomInviteItem,
|
size = AvatarSize.RoomInviteItem,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ 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.RoomMember
|
||||||
import io.element.android.libraries.matrix.api.room.RoomMembershipState
|
import io.element.android.libraries.matrix.api.room.RoomMembershipState
|
||||||
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
|
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
|
||||||
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
|
|
||||||
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
||||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||||
import io.element.android.libraries.matrix.test.A_ROOM_ID_2
|
import io.element.android.libraries.matrix.test.A_ROOM_ID_2
|
||||||
|
|
@ -39,6 +38,7 @@ import io.element.android.libraries.matrix.test.A_USER_ID
|
||||||
import io.element.android.libraries.matrix.test.A_USER_NAME
|
import io.element.android.libraries.matrix.test.A_USER_NAME
|
||||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||||
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
||||||
|
import io.element.android.libraries.matrix.test.room.aRoomSummaryDetails
|
||||||
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
|
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
|
||||||
import io.element.android.libraries.push.api.notifications.NotificationDrawerManager
|
import io.element.android.libraries.push.api.notifications.NotificationDrawerManager
|
||||||
import io.element.android.libraries.push.test.notifications.FakeNotificationDrawerManager
|
import io.element.android.libraries.push.test.notifications.FakeNotificationDrawerManager
|
||||||
|
|
@ -425,14 +425,12 @@ class InviteListPresenterTests {
|
||||||
postInviteRooms(
|
postInviteRooms(
|
||||||
listOf(
|
listOf(
|
||||||
RoomSummary.Filled(
|
RoomSummary.Filled(
|
||||||
RoomSummaryDetails(
|
aRoomSummaryDetails(
|
||||||
roomId = A_ROOM_ID,
|
roomId = A_ROOM_ID,
|
||||||
name = A_ROOM_NAME,
|
name = A_ROOM_NAME,
|
||||||
avatarURLString = null,
|
avatarUrl = null,
|
||||||
isDirect = false,
|
isDirect = false,
|
||||||
lastMessage = null,
|
lastMessage = null,
|
||||||
lastMessageTimestamp = null,
|
|
||||||
unreadNotificationCount = 0,
|
|
||||||
inviter = RoomMember(
|
inviter = RoomMember(
|
||||||
userId = A_USER_ID,
|
userId = A_USER_ID,
|
||||||
displayName = A_USER_NAME,
|
displayName = A_USER_NAME,
|
||||||
|
|
@ -454,14 +452,12 @@ class InviteListPresenterTests {
|
||||||
postInviteRooms(
|
postInviteRooms(
|
||||||
listOf(
|
listOf(
|
||||||
RoomSummary.Filled(
|
RoomSummary.Filled(
|
||||||
RoomSummaryDetails(
|
aRoomSummaryDetails(
|
||||||
roomId = A_ROOM_ID,
|
roomId = A_ROOM_ID,
|
||||||
name = A_ROOM_NAME,
|
name = A_ROOM_NAME,
|
||||||
avatarURLString = null,
|
avatarUrl = null,
|
||||||
isDirect = true,
|
isDirect = true,
|
||||||
lastMessage = null,
|
lastMessage = null,
|
||||||
lastMessageTimestamp = null,
|
|
||||||
unreadNotificationCount = 0,
|
|
||||||
inviter = RoomMember(
|
inviter = RoomMember(
|
||||||
userId = A_USER_ID,
|
userId = A_USER_ID,
|
||||||
displayName = A_USER_NAME,
|
displayName = A_USER_NAME,
|
||||||
|
|
@ -480,14 +476,12 @@ class InviteListPresenterTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun aRoomSummary(id: RoomId = A_ROOM_ID) = RoomSummary.Filled(
|
private fun aRoomSummary(id: RoomId = A_ROOM_ID) = RoomSummary.Filled(
|
||||||
RoomSummaryDetails(
|
aRoomSummaryDetails(
|
||||||
roomId = id,
|
roomId = id,
|
||||||
name = A_ROOM_NAME,
|
name = A_ROOM_NAME,
|
||||||
avatarURLString = null,
|
avatarUrl = null,
|
||||||
isDirect = false,
|
isDirect = false,
|
||||||
lastMessage = null,
|
lastMessage = null,
|
||||||
lastMessageTimestamp = null,
|
|
||||||
unreadNotificationCount = 0,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ import com.google.common.truth.Truth.assertThat
|
||||||
import io.element.android.libraries.matrix.api.core.EventId
|
import io.element.android.libraries.matrix.api.core.EventId
|
||||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||||
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
||||||
import io.element.android.libraries.matrix.test.room.aRoomSummaryDetail
|
import io.element.android.libraries.matrix.test.room.aRoomSummaryDetails
|
||||||
import io.element.android.tests.testutils.WarmUpRule
|
import io.element.android.tests.testutils.WarmUpRule
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
|
|
@ -55,7 +55,7 @@ class ForwardMessagesPresenterTests {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
val summary = aRoomSummaryDetail()
|
val summary = aRoomSummaryDetails()
|
||||||
presenter.onRoomSelected(listOf(summary.roomId))
|
presenter.onRoomSelected(listOf(summary.roomId))
|
||||||
val forwardingState = awaitItem()
|
val forwardingState = awaitItem()
|
||||||
assertThat(forwardingState.isForwarding).isTrue()
|
assertThat(forwardingState.isForwarding).isTrue()
|
||||||
|
|
@ -75,7 +75,7 @@ class ForwardMessagesPresenterTests {
|
||||||
// Test failed forwarding
|
// Test failed forwarding
|
||||||
room.givenForwardEventResult(Result.failure(Throwable("error")))
|
room.givenForwardEventResult(Result.failure(Throwable("error")))
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
val summary = aRoomSummaryDetail()
|
val summary = aRoomSummaryDetails()
|
||||||
presenter.onRoomSelected(listOf(summary.roomId))
|
presenter.onRoomSelected(listOf(summary.roomId))
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
val failedForwardState = awaitItem()
|
val failedForwardState = awaitItem()
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import io.element.android.libraries.matrix.api.roomlist.RoomSummary
|
||||||
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
|
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
||||||
open class EditDefaultNotificationSettingStateProvider: PreviewParameterProvider<EditDefaultNotificationSettingState> {
|
open class EditDefaultNotificationSettingStateProvider : PreviewParameterProvider<EditDefaultNotificationSettingState> {
|
||||||
override val values: Sequence<EditDefaultNotificationSettingState>
|
override val values: Sequence<EditDefaultNotificationSettingState>
|
||||||
get() = sequenceOf(
|
get() = sequenceOf(
|
||||||
anEditDefaultNotificationSettingsState(),
|
anEditDefaultNotificationSettingsState(),
|
||||||
|
|
@ -52,11 +52,14 @@ private fun aRoomSummary() = RoomSummary.Filled(
|
||||||
RoomSummaryDetails(
|
RoomSummaryDetails(
|
||||||
roomId = RoomId("!roomId:domain"),
|
roomId = RoomId("!roomId:domain"),
|
||||||
name = "Room",
|
name = "Room",
|
||||||
avatarURLString = null,
|
avatarUrl = null,
|
||||||
isDirect = false,
|
isDirect = false,
|
||||||
lastMessage = null,
|
lastMessage = null,
|
||||||
lastMessageTimestamp = null,
|
userDefinedNotificationMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY,
|
||||||
unreadNotificationCount = 0,
|
canonicalAlias = null,
|
||||||
notificationMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY,
|
inviter = null,
|
||||||
|
hasRoomCall = false,
|
||||||
|
numUnreadMentions = 0,
|
||||||
|
numUnreadMessages = 0,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -86,7 +86,7 @@ fun EditDefaultNotificationSettingView(
|
||||||
if (state.roomsWithUserDefinedMode.isNotEmpty()) {
|
if (state.roomsWithUserDefinedMode.isNotEmpty()) {
|
||||||
PreferenceCategory(title = stringResource(id = R.string.screen_notification_settings_edit_custom_settings_section_title)) {
|
PreferenceCategory(title = stringResource(id = R.string.screen_notification_settings_edit_custom_settings_section_title)) {
|
||||||
state.roomsWithUserDefinedMode.forEach { summary ->
|
state.roomsWithUserDefinedMode.forEach { summary ->
|
||||||
val subtitle = when (summary.details.notificationMode) {
|
val subtitle = when (summary.details.userDefinedNotificationMode) {
|
||||||
RoomNotificationMode.ALL_MESSAGES -> stringResource(id = R.string.screen_notification_settings_edit_mode_all_messages)
|
RoomNotificationMode.ALL_MESSAGES -> stringResource(id = R.string.screen_notification_settings_edit_mode_all_messages)
|
||||||
RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> {
|
RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> {
|
||||||
stringResource(id = R.string.screen_notification_settings_edit_mode_mentions_and_keywords)
|
stringResource(id = R.string.screen_notification_settings_edit_mode_mentions_and_keywords)
|
||||||
|
|
@ -97,7 +97,7 @@ fun EditDefaultNotificationSettingView(
|
||||||
val avatarData = AvatarData(
|
val avatarData = AvatarData(
|
||||||
id = summary.identifier(),
|
id = summary.identifier(),
|
||||||
name = summary.details.name,
|
name = summary.details.name,
|
||||||
url = summary.details.avatarURLString,
|
url = summary.details.avatarUrl,
|
||||||
size = AvatarSize.CustomRoomNotificationSetting,
|
size = AvatarSize.CustomRoomNotificationSetting,
|
||||||
)
|
)
|
||||||
ListItem(
|
ListItem(
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ import io.element.android.libraries.matrix.test.A_THROWABLE
|
||||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||||
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
|
import io.element.android.libraries.matrix.test.notificationsettings.FakeNotificationSettingsService
|
||||||
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
|
||||||
import io.element.android.libraries.matrix.test.room.aRoomSummaryDetail
|
import io.element.android.libraries.matrix.test.room.aRoomSummaryDetails
|
||||||
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
|
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
|
||||||
import io.element.android.tests.testutils.awaitLastSequentialItem
|
import io.element.android.tests.testutils.awaitLastSequentialItem
|
||||||
import io.element.android.tests.testutils.consumeItemsUntilPredicate
|
import io.element.android.tests.testutils.consumeItemsUntilPredicate
|
||||||
|
|
@ -72,11 +72,11 @@ class EditDefaultNotificationSettingsPresenterTests {
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
roomListService.postAllRooms(listOf(RoomSummary.Filled(aRoomSummaryDetail(notificationMode = RoomNotificationMode.ALL_MESSAGES))))
|
roomListService.postAllRooms(listOf(RoomSummary.Filled(aRoomSummaryDetails(notificationMode = RoomNotificationMode.ALL_MESSAGES))))
|
||||||
val loadedState = consumeItemsUntilPredicate { state ->
|
val loadedState = consumeItemsUntilPredicate { state ->
|
||||||
state.roomsWithUserDefinedMode.any { it.details.notificationMode == RoomNotificationMode.ALL_MESSAGES }
|
state.roomsWithUserDefinedMode.any { it.details.userDefinedNotificationMode == RoomNotificationMode.ALL_MESSAGES }
|
||||||
}.last()
|
}.last()
|
||||||
assertThat(loadedState.roomsWithUserDefinedMode.any { it.details.notificationMode == RoomNotificationMode.ALL_MESSAGES }).isTrue()
|
assertThat(loadedState.roomsWithUserDefinedMode.any { it.details.userDefinedNotificationMode == RoomNotificationMode.ALL_MESSAGES }).isTrue()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -71,7 +71,7 @@ internal fun aRoomListRoomSummaryList(): ImmutableList<RoomListRoomSummary> {
|
||||||
return persistentListOf(
|
return persistentListOf(
|
||||||
RoomListRoomSummary(
|
RoomListRoomSummary(
|
||||||
name = "Room",
|
name = "Room",
|
||||||
hasUnread = true,
|
numUnreadMessages = 1,
|
||||||
timestamp = "14:18",
|
timestamp = "14:18",
|
||||||
lastMessage = "A very very very very long message which suites on two lines",
|
lastMessage = "A very very very very long message which suites on two lines",
|
||||||
avatarData = AvatarData("!id", "R", size = AvatarSize.RoomListItem),
|
avatarData = AvatarData("!id", "R", size = AvatarSize.RoomListItem),
|
||||||
|
|
@ -80,7 +80,7 @@ internal fun aRoomListRoomSummaryList(): ImmutableList<RoomListRoomSummary> {
|
||||||
),
|
),
|
||||||
RoomListRoomSummary(
|
RoomListRoomSummary(
|
||||||
name = "Room#2",
|
name = "Room#2",
|
||||||
hasUnread = false,
|
numUnreadMessages = 0,
|
||||||
timestamp = "14:16",
|
timestamp = "14:16",
|
||||||
lastMessage = "A short message",
|
lastMessage = "A short message",
|
||||||
avatarData = AvatarData("!id", "Z", size = AvatarSize.RoomListItem),
|
avatarData = AvatarData("!id", "Z", size = AvatarSize.RoomListItem),
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ import io.element.android.compound.theme.ElementTheme
|
||||||
import io.element.android.compound.tokens.generated.CompoundIcons
|
import io.element.android.compound.tokens.generated.CompoundIcons
|
||||||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
import io.element.android.features.roomlist.impl.model.RoomListRoomSummary
|
||||||
import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryProvider
|
import io.element.android.features.roomlist.impl.model.RoomListRoomSummaryProvider
|
||||||
|
import io.element.android.features.roomlist.impl.model.isTimestampHighlighted
|
||||||
import io.element.android.libraries.core.extensions.orEmpty
|
import io.element.android.libraries.core.extensions.orEmpty
|
||||||
import io.element.android.libraries.designsystem.atomic.atoms.UnreadIndicatorAtom
|
import io.element.android.libraries.designsystem.atomic.atoms.UnreadIndicatorAtom
|
||||||
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
import io.element.android.libraries.designsystem.components.avatar.Avatar
|
||||||
|
|
@ -141,7 +142,7 @@ private fun RowScope.NameAndTimestampRow(room: RoomListRoomSummary) {
|
||||||
Text(
|
Text(
|
||||||
text = room.timestamp ?: "",
|
text = room.timestamp ?: "",
|
||||||
style = ElementTheme.typography.fontBodySmMedium,
|
style = ElementTheme.typography.fontBodySmMedium,
|
||||||
color = if (room.hasUnread) {
|
color = if (room.isTimestampHighlighted()) {
|
||||||
ElementTheme.colors.unreadIndicator
|
ElementTheme.colors.unreadIndicator
|
||||||
} else {
|
} else {
|
||||||
MaterialTheme.roomListRoomMessageDate()
|
MaterialTheme.roomListRoomMessageDate()
|
||||||
|
|
@ -173,40 +174,69 @@ private fun RowScope.LastMessageAndIndicatorRow(room: RoomListRoomSummary) {
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
// Video call
|
// Video call
|
||||||
if (room.hasOngoingCall) {
|
OnGoingCallIcon(room)
|
||||||
Icon(
|
// Other indicators
|
||||||
modifier = Modifier.size(16.dp),
|
NotificationIcons(room)
|
||||||
imageVector = CompoundIcons.VideoCallSolid,
|
|
||||||
contentDescription = null,
|
|
||||||
tint = ElementTheme.colors.unreadIndicator,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
NotificationIcon(room)
|
|
||||||
if (room.hasUnread) {
|
|
||||||
UnreadIndicatorAtom()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun NotificationIcon(room: RoomListRoomSummary) {
|
private fun OnGoingCallIcon(room: RoomListRoomSummary) {
|
||||||
val tint = if (room.hasUnread) ElementTheme.colors.unreadIndicator else ElementTheme.colors.iconQuaternary
|
if (room.hasRoomCall) {
|
||||||
when (room.notificationMode) {
|
Icon(
|
||||||
null, RoomNotificationMode.ALL_MESSAGES -> return
|
modifier = Modifier.size(16.dp),
|
||||||
RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY ->
|
imageVector = CompoundIcons.VideoCallSolid,
|
||||||
Icon(
|
contentDescription = null,
|
||||||
modifier = Modifier.size(16.dp),
|
tint = ElementTheme.colors.unreadIndicator,
|
||||||
contentDescription = null,
|
)
|
||||||
imageVector = CompoundIcons.Mention,
|
}
|
||||||
tint = tint,
|
}
|
||||||
)
|
|
||||||
RoomNotificationMode.MUTE ->
|
@Composable
|
||||||
|
private fun RowScope.NotificationIcons(room: RoomListRoomSummary) {
|
||||||
|
when (room.userDefinedNotificationMode) {
|
||||||
|
null,
|
||||||
|
RoomNotificationMode.ALL_MESSAGES -> {
|
||||||
|
if (room.numUnreadMentions > 0) {
|
||||||
|
Icon(
|
||||||
|
modifier = Modifier.size(16.dp),
|
||||||
|
contentDescription = null,
|
||||||
|
imageVector = CompoundIcons.Mention,
|
||||||
|
tint = ElementTheme.colors.unreadIndicator,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (room.numUnreadMessages > 0) {
|
||||||
|
UnreadIndicatorAtom()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> {
|
||||||
|
if (room.numUnreadMentions > 0) {
|
||||||
|
Icon(
|
||||||
|
modifier = Modifier.size(16.dp),
|
||||||
|
contentDescription = null,
|
||||||
|
imageVector = CompoundIcons.Mention,
|
||||||
|
tint = ElementTheme.colors.unreadIndicator,
|
||||||
|
)
|
||||||
|
if (room.numUnreadMessages > 0) {
|
||||||
|
UnreadIndicatorAtom()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (room.numUnreadMessages > 0) {
|
||||||
|
UnreadIndicatorAtom(color = ElementTheme.colors.iconQuaternary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RoomNotificationMode.MUTE -> {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.size(16.dp),
|
modifier = Modifier.size(16.dp),
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
imageVector = CompoundIcons.NotificationsSolidOff,
|
imageVector = CompoundIcons.NotificationsSolidOff,
|
||||||
tint = tint,
|
tint = ElementTheme.colors.iconQuaternary,
|
||||||
)
|
)
|
||||||
|
if (room.numUnreadMessages > 0) {
|
||||||
|
UnreadIndicatorAtom(color = ElementTheme.colors.iconQuaternary)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ class RoomListDataSource @Inject constructor(
|
||||||
val avatarData = AvatarData(
|
val avatarData = AvatarData(
|
||||||
id = roomSummary.identifier(),
|
id = roomSummary.identifier(),
|
||||||
name = roomSummary.details.name,
|
name = roomSummary.details.name,
|
||||||
url = roomSummary.details.avatarURLString,
|
url = roomSummary.details.avatarUrl,
|
||||||
size = AvatarSize.RoomListItem,
|
size = AvatarSize.RoomListItem,
|
||||||
)
|
)
|
||||||
val roomIdentifier = roomSummary.identifier()
|
val roomIdentifier = roomSummary.identifier()
|
||||||
|
|
@ -154,14 +154,15 @@ class RoomListDataSource @Inject constructor(
|
||||||
id = roomSummary.identifier(),
|
id = roomSummary.identifier(),
|
||||||
roomId = RoomId(roomIdentifier),
|
roomId = RoomId(roomIdentifier),
|
||||||
name = roomSummary.details.name,
|
name = roomSummary.details.name,
|
||||||
hasUnread = roomSummary.details.unreadNotificationCount > 0,
|
numUnreadMessages = roomSummary.details.numUnreadMessages,
|
||||||
|
numUnreadMentions = roomSummary.details.numUnreadMentions,
|
||||||
timestamp = lastMessageTimestampFormatter.format(roomSummary.details.lastMessageTimestamp),
|
timestamp = lastMessageTimestampFormatter.format(roomSummary.details.lastMessageTimestamp),
|
||||||
lastMessage = roomSummary.details.lastMessage?.let { message ->
|
lastMessage = roomSummary.details.lastMessage?.let { message ->
|
||||||
roomLastMessageFormatter.format(message.event, roomSummary.details.isDirect)
|
roomLastMessageFormatter.format(message.event, roomSummary.details.isDirect)
|
||||||
}.orEmpty(),
|
}.orEmpty(),
|
||||||
avatarData = avatarData,
|
avatarData = avatarData,
|
||||||
notificationMode = roomSummary.details.notificationMode,
|
userDefinedNotificationMode = roomSummary.details.userDefinedNotificationMode,
|
||||||
hasOngoingCall = roomSummary.details.hasOngoingCall,
|
hasRoomCall = roomSummary.details.hasRoomCall,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
null -> null
|
null -> null
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,22 @@ data class RoomListRoomSummary(
|
||||||
val id: String,
|
val id: String,
|
||||||
val roomId: RoomId,
|
val roomId: RoomId,
|
||||||
val name: String = "",
|
val name: String = "",
|
||||||
val hasUnread: Boolean = false,
|
|
||||||
val timestamp: String? = null,
|
val timestamp: String? = null,
|
||||||
val lastMessage: CharSequence? = null,
|
val lastMessage: CharSequence? = null,
|
||||||
val avatarData: AvatarData = AvatarData(id, name, size = AvatarSize.RoomListItem),
|
val avatarData: AvatarData = AvatarData(id, name, size = AvatarSize.RoomListItem),
|
||||||
val isPlaceholder: Boolean = false,
|
val isPlaceholder: Boolean = false,
|
||||||
val notificationMode: RoomNotificationMode? = null,
|
val userDefinedNotificationMode: RoomNotificationMode? = null,
|
||||||
val hasOngoingCall: Boolean = false,
|
val numUnreadMessages: Int = 0,
|
||||||
|
val numUnreadMentions: Int = 0,
|
||||||
|
val hasRoomCall: Boolean = false,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
fun RoomListRoomSummary.isTimestampHighlighted(): Boolean {
|
||||||
|
return hasRoomCall ||
|
||||||
|
when (userDefinedNotificationMode) {
|
||||||
|
null,
|
||||||
|
RoomNotificationMode.ALL_MESSAGES -> numUnreadMessages > 0 || numUnreadMentions > 0
|
||||||
|
RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY -> numUnreadMentions > 0
|
||||||
|
RoomNotificationMode.MUTE -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,32 +25,75 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||||
open class RoomListRoomSummaryProvider : PreviewParameterProvider<RoomListRoomSummary> {
|
open class RoomListRoomSummaryProvider : PreviewParameterProvider<RoomListRoomSummary> {
|
||||||
override val values: Sequence<RoomListRoomSummary>
|
override val values: Sequence<RoomListRoomSummary>
|
||||||
get() = sequenceOf(
|
get() = sequenceOf(
|
||||||
aRoomListRoomSummary(),
|
listOf(
|
||||||
aRoomListRoomSummary().copy(lastMessage = null),
|
aRoomListRoomSummary(isPlaceholder = true),
|
||||||
aRoomListRoomSummary().copy(hasUnread = true, notificationMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY),
|
aRoomListRoomSummary(timestamp = null),
|
||||||
aRoomListRoomSummary().copy(timestamp = "88:88", notificationMode = RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY),
|
aRoomListRoomSummary(lastMessage = "Last message"),
|
||||||
aRoomListRoomSummary().copy(timestamp = "88:88", notificationMode = RoomNotificationMode.MUTE),
|
aRoomListRoomSummary(
|
||||||
aRoomListRoomSummary().copy(timestamp = "88:88", hasUnread = true),
|
name = "A very long room name that should be truncated",
|
||||||
aRoomListRoomSummary().copy(isPlaceholder = true, timestamp = "88:88"),
|
lastMessage = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt" +
|
||||||
aRoomListRoomSummary().copy(
|
" ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea com" +
|
||||||
name = "A very long room name that should be truncated",
|
"modo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
|
||||||
lastMessage = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt" +
|
timestamp = "yesterday",
|
||||||
" ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea com" +
|
numUnreadMessages = 1,
|
||||||
"modo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.",
|
),
|
||||||
timestamp = "yesterday",
|
|
||||||
hasUnread = true,
|
|
||||||
),
|
),
|
||||||
aRoomListRoomSummary().copy(hasUnread = true, hasOngoingCall = true),
|
listOf(false, true).map { hasCall ->
|
||||||
)
|
listOf(
|
||||||
|
RoomNotificationMode.ALL_MESSAGES,
|
||||||
|
RoomNotificationMode.MENTIONS_AND_KEYWORDS_ONLY,
|
||||||
|
RoomNotificationMode.MUTE,
|
||||||
|
).map { roomNotificationMode ->
|
||||||
|
listOf(
|
||||||
|
aRoomListRoomSummary(
|
||||||
|
name = roomNotificationMode.name,
|
||||||
|
lastMessage = "No activity" + if (hasCall) ", call" else "",
|
||||||
|
notificationMode = roomNotificationMode,
|
||||||
|
numUnreadMessages = 0,
|
||||||
|
numUnreadMentions = 0,
|
||||||
|
hasOngoingCall = hasCall,
|
||||||
|
),
|
||||||
|
aRoomListRoomSummary(
|
||||||
|
name = roomNotificationMode.name,
|
||||||
|
lastMessage = "New messages" + if (hasCall) ", call" else "",
|
||||||
|
notificationMode = roomNotificationMode,
|
||||||
|
numUnreadMessages = 1,
|
||||||
|
numUnreadMentions = 0,
|
||||||
|
hasOngoingCall = hasCall,
|
||||||
|
),
|
||||||
|
aRoomListRoomSummary(
|
||||||
|
name = roomNotificationMode.name,
|
||||||
|
lastMessage = "New messages, mentions" + if (hasCall) ", call" else "",
|
||||||
|
notificationMode = roomNotificationMode,
|
||||||
|
numUnreadMessages = 1,
|
||||||
|
numUnreadMentions = 1,
|
||||||
|
hasOngoingCall = hasCall,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
}.flatten()
|
||||||
|
}.flatten(),
|
||||||
|
).flatten()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun aRoomListRoomSummary() = RoomListRoomSummary(
|
fun aRoomListRoomSummary(
|
||||||
|
lastMessage: String? = null,
|
||||||
|
notificationMode: RoomNotificationMode? = null,
|
||||||
|
numUnreadMessages: Int = 0,
|
||||||
|
numUnreadMentions: Int = 0,
|
||||||
|
timestamp: String? = "88:88",
|
||||||
|
hasOngoingCall: Boolean = false,
|
||||||
|
isPlaceholder: Boolean = false,
|
||||||
|
name: String = "Room name",
|
||||||
|
) = RoomListRoomSummary(
|
||||||
id = "!roomId",
|
id = "!roomId",
|
||||||
roomId = RoomId("!roomId:domain"),
|
roomId = RoomId("!roomId:domain"),
|
||||||
name = "Room name",
|
name = name,
|
||||||
hasUnread = false,
|
numUnreadMessages = numUnreadMessages,
|
||||||
timestamp = null,
|
numUnreadMentions = numUnreadMentions,
|
||||||
lastMessage = "Last message",
|
timestamp = timestamp,
|
||||||
|
lastMessage = lastMessage,
|
||||||
avatarData = AvatarData("!roomId", "Room name", size = AvatarSize.RoomListItem),
|
avatarData = AvatarData("!roomId", "Room name", size = AvatarSize.RoomListItem),
|
||||||
isPlaceholder = false,
|
isPlaceholder = isPlaceholder,
|
||||||
|
userDefinedNotificationMode = notificationMode,
|
||||||
|
hasRoomCall = hasOngoingCall,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ class RoomListPresenterTests {
|
||||||
fun `present - should start with no user and then load user with error`() = runTest {
|
fun `present - should start with no user and then load user with error`() = runTest {
|
||||||
val matrixClient = FakeMatrixClient(
|
val matrixClient = FakeMatrixClient(
|
||||||
userDisplayName = Result.failure(AN_EXCEPTION),
|
userDisplayName = Result.failure(AN_EXCEPTION),
|
||||||
userAvatarURLString = Result.failure(AN_EXCEPTION),
|
userAvatarUrl = Result.failure(AN_EXCEPTION),
|
||||||
)
|
)
|
||||||
val scope = CoroutineScope(coroutineContext + SupervisorJob())
|
val scope = CoroutineScope(coroutineContext + SupervisorJob())
|
||||||
val presenter = createRoomListPresenter(client = matrixClient, coroutineScope = scope)
|
val presenter = createRoomListPresenter(client = matrixClient, coroutineScope = scope)
|
||||||
|
|
@ -385,11 +385,11 @@ class RoomListPresenterTests {
|
||||||
notificationSettingsService.setRoomNotificationMode(A_ROOM_ID, userDefinedMode)
|
notificationSettingsService.setRoomNotificationMode(A_ROOM_ID, userDefinedMode)
|
||||||
|
|
||||||
val updatedState = consumeItemsUntilPredicate { state ->
|
val updatedState = consumeItemsUntilPredicate { state ->
|
||||||
state.roomList.any { it.id == A_ROOM_ID.value && it.notificationMode == userDefinedMode }
|
state.roomList.any { it.id == A_ROOM_ID.value && it.userDefinedNotificationMode == userDefinedMode }
|
||||||
}.last()
|
}.last()
|
||||||
|
|
||||||
val room = updatedState.roomList.find { it.id == A_ROOM_ID.value }
|
val room = updatedState.roomList.find { it.id == A_ROOM_ID.value }
|
||||||
assertThat(room?.notificationMode).isEqualTo(userDefinedMode)
|
assertThat(room?.userDefinedNotificationMode).isEqualTo(userDefinedMode)
|
||||||
cancelAndIgnoreRemainingEvents()
|
cancelAndIgnoreRemainingEvents()
|
||||||
scope.cancel()
|
scope.cancel()
|
||||||
}
|
}
|
||||||
|
|
@ -439,7 +439,7 @@ private val aRoomListRoomSummary = RoomListRoomSummary(
|
||||||
id = A_ROOM_ID.value,
|
id = A_ROOM_ID.value,
|
||||||
roomId = A_ROOM_ID,
|
roomId = A_ROOM_ID,
|
||||||
name = A_ROOM_NAME,
|
name = A_ROOM_NAME,
|
||||||
hasUnread = true,
|
numUnreadMessages = 1,
|
||||||
timestamp = A_FORMATTED_DATE,
|
timestamp = A_FORMATTED_DATE,
|
||||||
lastMessage = "",
|
lastMessage = "",
|
||||||
avatarData = AvatarData(id = A_ROOM_ID.value, name = A_ROOM_NAME, size = AvatarSize.RoomListItem),
|
avatarData = AvatarData(id = A_ROOM_ID.value, name = A_ROOM_NAME, size = AvatarSize.RoomListItem),
|
||||||
|
|
|
||||||
|
|
@ -72,7 +72,7 @@ interface MatrixClient : Closeable {
|
||||||
*/
|
*/
|
||||||
suspend fun logout(ignoreSdkError: Boolean): String?
|
suspend fun logout(ignoreSdkError: Boolean): String?
|
||||||
suspend fun loadUserDisplayName(): Result<String>
|
suspend fun loadUserDisplayName(): Result<String>
|
||||||
suspend fun loadUserAvatarURLString(): Result<String?>
|
suspend fun loadUserAvatarUrl(): Result<String?>
|
||||||
suspend fun getAccountManagementUrl(action: AccountManagementAction?): Result<String?>
|
suspend fun getAccountManagementUrl(action: AccountManagementAction?): Result<String?>
|
||||||
suspend fun uploadMedia(mimeType: String, data: ByteArray, progressCallback: ProgressCallback?): Result<String>
|
suspend fun uploadMedia(mimeType: String, data: ByteArray, progressCallback: ProgressCallback?): Result<String>
|
||||||
fun roomMembershipObserver(): RoomMembershipObserver
|
fun roomMembershipObserver(): RoomMembershipObserver
|
||||||
|
|
|
||||||
|
|
@ -36,13 +36,15 @@ sealed interface RoomSummary {
|
||||||
data class RoomSummaryDetails(
|
data class RoomSummaryDetails(
|
||||||
val roomId: RoomId,
|
val roomId: RoomId,
|
||||||
val name: String,
|
val name: String,
|
||||||
val canonicalAlias: String? = null,
|
val canonicalAlias: String?,
|
||||||
val isDirect: Boolean,
|
val isDirect: Boolean,
|
||||||
val avatarURLString: String?,
|
val avatarUrl: String?,
|
||||||
val lastMessage: RoomMessage?,
|
val lastMessage: RoomMessage?,
|
||||||
val lastMessageTimestamp: Long?,
|
val numUnreadMessages: Int,
|
||||||
val unreadNotificationCount: Int,
|
val numUnreadMentions: Int,
|
||||||
val inviter: RoomMember? = null,
|
val inviter: RoomMember?,
|
||||||
val notificationMode: RoomNotificationMode? = null,
|
val userDefinedNotificationMode: RoomNotificationMode?,
|
||||||
val hasOngoingCall: Boolean = false,
|
val hasRoomCall: Boolean,
|
||||||
)
|
) {
|
||||||
|
val lastMessageTimestamp = lastMessage?.originServerTs
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,11 +19,11 @@ package io.element.android.libraries.matrix.api.user
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current user, as [MatrixUser], using [MatrixClient.loadUserAvatarURLString]
|
* Get the current user, as [MatrixUser], using [MatrixClient.loadUserAvatarUrl]
|
||||||
* and [MatrixClient.loadUserDisplayName].
|
* and [MatrixClient.loadUserDisplayName].
|
||||||
*/
|
*/
|
||||||
suspend fun MatrixClient.getCurrentUser(): MatrixUser {
|
suspend fun MatrixClient.getCurrentUser(): MatrixUser {
|
||||||
val userAvatarUrl = loadUserAvatarURLString().getOrNull()
|
val userAvatarUrl = loadUserAvatarUrl().getOrNull()
|
||||||
val userDisplayName = loadUserDisplayName().getOrNull()
|
val userDisplayName = loadUserDisplayName().getOrNull()
|
||||||
return MatrixUser(
|
return MatrixUser(
|
||||||
userId = sessionId,
|
userId = sessionId,
|
||||||
|
|
|
||||||
|
|
@ -412,7 +412,7 @@ class RustMatrixClient(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun loadUserAvatarURLString(): Result<String?> = withContext(sessionDispatcher) {
|
override suspend fun loadUserAvatarUrl(): Result<String?> = withContext(sessionDispatcher) {
|
||||||
runCatching {
|
runCatching {
|
||||||
client.avatarUrl()
|
client.avatarUrl()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,13 +35,13 @@ class RoomSummaryDetailsFactory(private val roomMessageFactory: RoomMessageFacto
|
||||||
name = roomInfo.name ?: roomInfo.id,
|
name = roomInfo.name ?: roomInfo.id,
|
||||||
canonicalAlias = roomInfo.canonicalAlias,
|
canonicalAlias = roomInfo.canonicalAlias,
|
||||||
isDirect = roomInfo.isDirect,
|
isDirect = roomInfo.isDirect,
|
||||||
avatarURLString = roomInfo.avatarUrl,
|
avatarUrl = roomInfo.avatarUrl,
|
||||||
unreadNotificationCount = roomInfo.notificationCount.toInt(),
|
|
||||||
lastMessage = latestRoomMessage,
|
lastMessage = latestRoomMessage,
|
||||||
lastMessageTimestamp = latestRoomMessage?.originServerTs,
|
|
||||||
inviter = roomInfo.inviter?.let(RoomMemberMapper::map),
|
inviter = roomInfo.inviter?.let(RoomMemberMapper::map),
|
||||||
notificationMode = roomInfo.userDefinedNotificationMode?.let(RoomNotificationSettingsMapper::mapMode),
|
userDefinedNotificationMode = roomInfo.userDefinedNotificationMode?.let(RoomNotificationSettingsMapper::mapMode),
|
||||||
hasOngoingCall = roomInfo.hasRoomCall,
|
hasRoomCall = roomInfo.hasRoomCall,
|
||||||
|
numUnreadMentions = roomInfo.numUnreadMentions.toInt(),
|
||||||
|
numUnreadMessages = roomInfo.numUnreadMessages.toInt(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ import kotlinx.coroutines.delay
|
||||||
class FakeMatrixClient(
|
class FakeMatrixClient(
|
||||||
override val sessionId: SessionId = A_SESSION_ID,
|
override val sessionId: SessionId = A_SESSION_ID,
|
||||||
private val userDisplayName: Result<String> = Result.success(A_USER_NAME),
|
private val userDisplayName: Result<String> = Result.success(A_USER_NAME),
|
||||||
private val userAvatarURLString: Result<String> = Result.success(AN_AVATAR_URL),
|
private val userAvatarUrl: Result<String> = Result.success(AN_AVATAR_URL),
|
||||||
override val roomListService: RoomListService = FakeRoomListService(),
|
override val roomListService: RoomListService = FakeRoomListService(),
|
||||||
override val mediaLoader: MatrixMediaLoader = FakeMediaLoader(),
|
override val mediaLoader: MatrixMediaLoader = FakeMediaLoader(),
|
||||||
private val sessionVerificationService: FakeSessionVerificationService = FakeSessionVerificationService(),
|
private val sessionVerificationService: FakeSessionVerificationService = FakeSessionVerificationService(),
|
||||||
|
|
@ -136,8 +136,8 @@ class FakeMatrixClient(
|
||||||
return userDisplayName
|
return userDisplayName
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun loadUserAvatarURLString(): Result<String?> {
|
override suspend fun loadUserAvatarUrl(): Result<String?> {
|
||||||
return userAvatarURLString
|
return userAvatarUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun getAccountManagementUrl(action: AccountManagementAction?): Result<String?> {
|
override suspend fun getAccountManagementUrl(action: AccountManagementAction?): Result<String?> {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ package io.element.android.libraries.matrix.test.room
|
||||||
import io.element.android.libraries.matrix.api.core.EventId
|
import io.element.android.libraries.matrix.api.core.EventId
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
import io.element.android.libraries.matrix.api.core.RoomId
|
||||||
import io.element.android.libraries.matrix.api.core.UserId
|
import io.element.android.libraries.matrix.api.core.UserId
|
||||||
|
import io.element.android.libraries.matrix.api.room.RoomMember
|
||||||
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||||
import io.element.android.libraries.matrix.api.room.message.RoomMessage
|
import io.element.android.libraries.matrix.api.room.message.RoomMessage
|
||||||
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
|
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
|
||||||
|
|
@ -34,42 +35,46 @@ fun aRoomSummaryFilled(
|
||||||
roomId: RoomId = A_ROOM_ID,
|
roomId: RoomId = A_ROOM_ID,
|
||||||
name: String = A_ROOM_NAME,
|
name: String = A_ROOM_NAME,
|
||||||
isDirect: Boolean = false,
|
isDirect: Boolean = false,
|
||||||
avatarURLString: String? = null,
|
avatarUrl: String? = null,
|
||||||
lastMessage: RoomMessage? = aRoomMessage(),
|
lastMessage: RoomMessage? = aRoomMessage(),
|
||||||
lastMessageTimestamp: Long? = null,
|
numUnreadMessages: Int = 2,
|
||||||
unreadNotificationCount: Int = 2,
|
|
||||||
notificationMode: RoomNotificationMode? = null,
|
notificationMode: RoomNotificationMode? = null,
|
||||||
) = RoomSummary.Filled(
|
) = RoomSummary.Filled(
|
||||||
aRoomSummaryDetail(
|
aRoomSummaryDetails(
|
||||||
roomId = roomId,
|
roomId = roomId,
|
||||||
name = name,
|
name = name,
|
||||||
isDirect = isDirect,
|
isDirect = isDirect,
|
||||||
avatarURLString = avatarURLString,
|
avatarUrl = avatarUrl,
|
||||||
lastMessage = lastMessage,
|
lastMessage = lastMessage,
|
||||||
lastMessageTimestamp = lastMessageTimestamp,
|
numUnreadMessages = numUnreadMessages,
|
||||||
unreadNotificationCount = unreadNotificationCount,
|
|
||||||
notificationMode = notificationMode,
|
notificationMode = notificationMode,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
fun aRoomSummaryDetail(
|
fun aRoomSummaryDetails(
|
||||||
roomId: RoomId = A_ROOM_ID,
|
roomId: RoomId = A_ROOM_ID,
|
||||||
name: String = A_ROOM_NAME,
|
name: String = A_ROOM_NAME,
|
||||||
isDirect: Boolean = false,
|
isDirect: Boolean = false,
|
||||||
avatarURLString: String? = null,
|
avatarUrl: String? = null,
|
||||||
lastMessage: RoomMessage? = aRoomMessage(),
|
lastMessage: RoomMessage? = aRoomMessage(),
|
||||||
lastMessageTimestamp: Long? = null,
|
|
||||||
unreadNotificationCount: Int = 2,
|
|
||||||
notificationMode: RoomNotificationMode? = null,
|
notificationMode: RoomNotificationMode? = null,
|
||||||
|
inviter: RoomMember? = null,
|
||||||
|
canonicalAlias: String? = null,
|
||||||
|
hasOngoingCall: Boolean = false,
|
||||||
|
numUnreadMentions: Int = 0,
|
||||||
|
numUnreadMessages: Int = 0,
|
||||||
) = RoomSummaryDetails(
|
) = RoomSummaryDetails(
|
||||||
roomId = roomId,
|
roomId = roomId,
|
||||||
name = name,
|
name = name,
|
||||||
isDirect = isDirect,
|
isDirect = isDirect,
|
||||||
avatarURLString = avatarURLString,
|
avatarUrl = avatarUrl,
|
||||||
lastMessage = lastMessage,
|
lastMessage = lastMessage,
|
||||||
lastMessageTimestamp = lastMessageTimestamp,
|
userDefinedNotificationMode = notificationMode,
|
||||||
unreadNotificationCount = unreadNotificationCount,
|
canonicalAlias = canonicalAlias,
|
||||||
notificationMode = notificationMode
|
inviter = inviter,
|
||||||
|
hasRoomCall = hasOngoingCall,
|
||||||
|
numUnreadMentions = numUnreadMentions,
|
||||||
|
numUnreadMessages = numUnreadMessages,
|
||||||
)
|
)
|
||||||
|
|
||||||
fun aRoomMessage(
|
fun aRoomMessage(
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,9 @@ import io.element.android.libraries.designsystem.theme.components.Icon
|
||||||
import io.element.android.libraries.designsystem.theme.components.Surface
|
import io.element.android.libraries.designsystem.theme.components.Surface
|
||||||
import io.element.android.libraries.designsystem.theme.components.Text
|
import io.element.android.libraries.designsystem.theme.components.Text
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
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.RoomNotificationMode
|
||||||
|
import io.element.android.libraries.matrix.api.room.message.RoomMessage
|
||||||
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
|
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
|
|
||||||
|
|
@ -60,7 +63,7 @@ fun SelectedRoom(
|
||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
) {
|
) {
|
||||||
Avatar(AvatarData(roomSummary.roomId.value, roomSummary.name, roomSummary.avatarURLString, AvatarSize.SelectedRoom))
|
Avatar(AvatarData(roomSummary.roomId.value, roomSummary.name, roomSummary.avatarUrl, AvatarSize.SelectedRoom))
|
||||||
Text(
|
Text(
|
||||||
text = roomSummary.name,
|
text = roomSummary.name,
|
||||||
overflow = TextOverflow.Ellipsis,
|
overflow = TextOverflow.Ellipsis,
|
||||||
|
|
@ -94,17 +97,33 @@ fun SelectedRoom(
|
||||||
@Composable
|
@Composable
|
||||||
internal fun SelectedRoomPreview() = ElementPreview {
|
internal fun SelectedRoomPreview() = ElementPreview {
|
||||||
SelectedRoom(
|
SelectedRoom(
|
||||||
roomSummary = RoomSummaryDetails(
|
roomSummary = aRoomSummaryDetails(),
|
||||||
roomId = RoomId("!room:domain"),
|
|
||||||
name = "roomName",
|
|
||||||
canonicalAlias = null,
|
|
||||||
isDirect = true,
|
|
||||||
avatarURLString = null,
|
|
||||||
lastMessage = null,
|
|
||||||
lastMessageTimestamp = null,
|
|
||||||
unreadNotificationCount = 0,
|
|
||||||
inviter = null,
|
|
||||||
),
|
|
||||||
onRoomRemoved = {},
|
onRoomRemoved = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun aRoomSummaryDetails(
|
||||||
|
roomId: RoomId = RoomId("!room:domain"),
|
||||||
|
name: String = "roomName",
|
||||||
|
canonicalAlias: String? = null,
|
||||||
|
isDirect: Boolean = true,
|
||||||
|
avatarUrl: String? = null,
|
||||||
|
lastMessage: RoomMessage? = null,
|
||||||
|
inviter: RoomMember? = null,
|
||||||
|
notificationMode: RoomNotificationMode? = null,
|
||||||
|
hasOngoingCall: Boolean = false,
|
||||||
|
numUnreadMentions: Int = 0,
|
||||||
|
numUnreadMessages: Int = 0,
|
||||||
|
) = RoomSummaryDetails(
|
||||||
|
roomId = roomId,
|
||||||
|
name = name,
|
||||||
|
canonicalAlias = canonicalAlias,
|
||||||
|
isDirect = isDirect,
|
||||||
|
avatarUrl = avatarUrl,
|
||||||
|
lastMessage = lastMessage,
|
||||||
|
inviter = inviter,
|
||||||
|
userDefinedNotificationMode = notificationMode,
|
||||||
|
hasRoomCall = hasOngoingCall,
|
||||||
|
numUnreadMentions = numUnreadMentions,
|
||||||
|
numUnreadMessages = numUnreadMessages,
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -297,7 +297,7 @@ class DefaultNotificationDrawerManager @Inject constructor(
|
||||||
operation = {
|
operation = {
|
||||||
// myUserDisplayName cannot be empty else NotificationCompat.MessagingStyle() will crash
|
// myUserDisplayName cannot be empty else NotificationCompat.MessagingStyle() will crash
|
||||||
val myUserDisplayName = client.loadUserDisplayName().getOrNull() ?: sessionId.value
|
val myUserDisplayName = client.loadUserDisplayName().getOrNull() ?: sessionId.value
|
||||||
val userAvatarUrl = client.loadUserAvatarURLString().getOrNull()
|
val userAvatarUrl = client.loadUserAvatarUrl().getOrNull()
|
||||||
MatrixUser(
|
MatrixUser(
|
||||||
userId = sessionId,
|
userId = sessionId,
|
||||||
displayName = myUserDisplayName,
|
displayName = myUserDisplayName,
|
||||||
|
|
|
||||||
|
|
@ -19,9 +19,8 @@ package io.element.android.libraries.roomselect.impl
|
||||||
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
||||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||||
import io.element.android.libraries.matrix.api.core.RoomId
|
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.message.RoomMessage
|
|
||||||
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
|
import io.element.android.libraries.matrix.api.roomlist.RoomSummaryDetails
|
||||||
|
import io.element.android.libraries.matrix.ui.components.aRoomSummaryDetails
|
||||||
import io.element.android.libraries.roomselect.api.RoomSelectMode
|
import io.element.android.libraries.roomselect.api.RoomSelectMode
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
@ -41,7 +40,7 @@ open class RoomSelectStateProvider : PreviewParameterProvider<RoomSelectState> {
|
||||||
resultState = SearchBarResultState.Results(aForwardMessagesRoomList()),
|
resultState = SearchBarResultState.Results(aForwardMessagesRoomList()),
|
||||||
query = "Test",
|
query = "Test",
|
||||||
isSearchActive = true,
|
isSearchActive = true,
|
||||||
selectedRooms = persistentListOf(aRoomDetailsState(roomId = RoomId("!room2:domain")))
|
selectedRooms = persistentListOf(aRoomSummaryDetails(roomId = RoomId("!room2:domain")))
|
||||||
),
|
),
|
||||||
// Add other states here
|
// Add other states here
|
||||||
)
|
)
|
||||||
|
|
@ -62,32 +61,10 @@ private fun aRoomSelectState(
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun aForwardMessagesRoomList() = persistentListOf(
|
private fun aForwardMessagesRoomList() = persistentListOf(
|
||||||
aRoomDetailsState(),
|
aRoomSummaryDetails(),
|
||||||
aRoomDetailsState(
|
aRoomSummaryDetails(
|
||||||
roomId = RoomId("!room2:domain"),
|
roomId = RoomId("!room2:domain"),
|
||||||
name = "Room with alias",
|
name = "Room with alias",
|
||||||
canonicalAlias = "#alias:example.org",
|
canonicalAlias = "#alias:example.org",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun aRoomDetailsState(
|
|
||||||
roomId: RoomId = RoomId("!room:domain"),
|
|
||||||
name: String = "roomName",
|
|
||||||
canonicalAlias: String? = null,
|
|
||||||
isDirect: Boolean = true,
|
|
||||||
avatarURLString: String? = null,
|
|
||||||
lastMessage: RoomMessage? = null,
|
|
||||||
lastMessageTimestamp: Long? = null,
|
|
||||||
unreadNotificationCount: Int = 0,
|
|
||||||
inviter: RoomMember? = null,
|
|
||||||
) = RoomSummaryDetails(
|
|
||||||
roomId = roomId,
|
|
||||||
name = name,
|
|
||||||
canonicalAlias = canonicalAlias,
|
|
||||||
isDirect = isDirect,
|
|
||||||
avatarURLString = avatarURLString,
|
|
||||||
lastMessage = lastMessage,
|
|
||||||
lastMessageTimestamp = lastMessageTimestamp,
|
|
||||||
unreadNotificationCount = unreadNotificationCount,
|
|
||||||
inviter = inviter,
|
|
||||||
)
|
|
||||||
|
|
|
||||||
|
|
@ -222,7 +222,7 @@ private fun RoomSummaryView(
|
||||||
avatarData = AvatarData(
|
avatarData = AvatarData(
|
||||||
id = summary.roomId.value,
|
id = summary.roomId.value,
|
||||||
name = summary.name,
|
name = summary.name,
|
||||||
url = summary.avatarURLString,
|
url = summary.avatarUrl,
|
||||||
size = AvatarSize.RoomSelectRoomListItem,
|
size = AvatarSize.RoomSelectRoomListItem,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ import io.element.android.libraries.roomselect.api.RoomSelectMode
|
||||||
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
import io.element.android.libraries.designsystem.theme.components.SearchBarResultState
|
||||||
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
|
import io.element.android.libraries.matrix.api.roomlist.RoomSummary
|
||||||
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
import io.element.android.libraries.matrix.test.FakeMatrixClient
|
||||||
import io.element.android.libraries.matrix.test.room.aRoomSummaryDetail
|
import io.element.android.libraries.matrix.test.room.aRoomSummaryDetails
|
||||||
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
|
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
|
||||||
import io.element.android.tests.testutils.WarmUpRule
|
import io.element.android.tests.testutils.WarmUpRule
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
@ -73,7 +73,7 @@ class RoomSelectPresenterTests {
|
||||||
@Test
|
@Test
|
||||||
fun `present - update query`() = runTest {
|
fun `present - update query`() = runTest {
|
||||||
val roomListService = FakeRoomListService().apply {
|
val roomListService = FakeRoomListService().apply {
|
||||||
postAllRooms(listOf(RoomSummary.Filled(aRoomSummaryDetail())))
|
postAllRooms(listOf(RoomSummary.Filled(aRoomSummaryDetails())))
|
||||||
}
|
}
|
||||||
val client = FakeMatrixClient(roomListService = roomListService)
|
val client = FakeMatrixClient(roomListService = roomListService)
|
||||||
val presenter = aPresenter(client = client)
|
val presenter = aPresenter(client = client)
|
||||||
|
|
@ -81,7 +81,7 @@ class RoomSelectPresenterTests {
|
||||||
presenter.present()
|
presenter.present()
|
||||||
}.test {
|
}.test {
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
assertThat(awaitItem().resultState as? SearchBarResultState.Results).isEqualTo(SearchBarResultState.Results(listOf(aRoomSummaryDetail())))
|
assertThat(awaitItem().resultState as? SearchBarResultState.Results).isEqualTo(SearchBarResultState.Results(listOf(aRoomSummaryDetails())))
|
||||||
|
|
||||||
initialState.eventSink(RoomSelectEvents.UpdateQuery("string not contained"))
|
initialState.eventSink(RoomSelectEvents.UpdateQuery("string not contained"))
|
||||||
assertThat(awaitItem().query).isEqualTo("string not contained")
|
assertThat(awaitItem().query).isEqualTo("string not contained")
|
||||||
|
|
@ -97,7 +97,7 @@ class RoomSelectPresenterTests {
|
||||||
}.test {
|
}.test {
|
||||||
val initialState = awaitItem()
|
val initialState = awaitItem()
|
||||||
skipItems(1)
|
skipItems(1)
|
||||||
val summary = aRoomSummaryDetail()
|
val summary = aRoomSummaryDetails()
|
||||||
|
|
||||||
initialState.eventSink(RoomSelectEvents.SetSelectedRoom(summary))
|
initialState.eventSink(RoomSelectEvents.SetSelectedRoom(summary))
|
||||||
assertThat(awaitItem().selectedRooms).isEqualTo(persistentListOf(summary))
|
assertThat(awaitItem().selectedRooms).isEqualTo(persistentListOf(summary))
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue