Add ability mark as unread / mark as read a room.
This commit is contained in:
parent
6f082232d3
commit
ca91b23512
21 changed files with 229 additions and 13 deletions
|
|
@ -155,6 +155,14 @@ class MessagesPresenter @AssistedInject constructor(
|
||||||
mutableStateOf(false)
|
mutableStateOf(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
// Mark the room as read on entering but don't send read receipts
|
||||||
|
// as those will be handled by the timeline.
|
||||||
|
withContext(dispatchers.io) {
|
||||||
|
room.markAsRead(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LaunchedEffect(syncUpdateFlow.value) {
|
LaunchedEffect(syncUpdateFlow.value) {
|
||||||
withContext(dispatchers.io) {
|
withContext(dispatchers.io) {
|
||||||
canJoinCall = room.canUserJoinCall(room.sessionId).getOrDefault(false)
|
canJoinCall = room.canUserJoinCall(room.sessionId).getOrDefault(false)
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,9 @@ import io.element.android.tests.testutils.consumeItemsUntilTimeout
|
||||||
import io.element.android.tests.testutils.testCoroutineDispatchers
|
import io.element.android.tests.testutils.testCoroutineDispatchers
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import kotlinx.collections.immutable.persistentListOf
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
import kotlinx.coroutines.test.TestScope
|
import kotlinx.coroutines.test.TestScope
|
||||||
|
import kotlinx.coroutines.test.runCurrent
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
@ -129,6 +131,21 @@ class MessagesPresenterTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoroutinesApi::class)
|
||||||
|
@Test
|
||||||
|
fun `present - check that the room is marked as read`() = runTest {
|
||||||
|
val room = FakeMatrixRoom()
|
||||||
|
assertThat(room.markAsReadCalls).isEmpty()
|
||||||
|
val presenter = createMessagesPresenter(matrixRoom = room)
|
||||||
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
|
presenter.present()
|
||||||
|
}.test {
|
||||||
|
runCurrent()
|
||||||
|
assertThat(room.markAsReadCalls).isEqualTo(listOf(null))
|
||||||
|
cancelAndIgnoreRemainingEvents()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `present - call is disabled if user cannot join it even if there is an ongoing call`() = runTest {
|
fun `present - call is disabled if user cannot join it even if there is an ongoing call`() = runTest {
|
||||||
val room = FakeMatrixRoom().apply {
|
val room = FakeMatrixRoom().apply {
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ dependencies {
|
||||||
implementation(projects.libraries.eventformatter.api)
|
implementation(projects.libraries.eventformatter.api)
|
||||||
implementation(projects.libraries.indicator.api)
|
implementation(projects.libraries.indicator.api)
|
||||||
implementation(projects.libraries.deeplink)
|
implementation(projects.libraries.deeplink)
|
||||||
|
implementation(projects.libraries.preferences.api)
|
||||||
implementation(projects.features.invitelist.api)
|
implementation(projects.features.invitelist.api)
|
||||||
implementation(projects.features.networkmonitor.api)
|
implementation(projects.features.networkmonitor.api)
|
||||||
implementation(projects.features.leaveroom.api)
|
implementation(projects.features.leaveroom.api)
|
||||||
|
|
@ -71,6 +72,7 @@ dependencies {
|
||||||
testImplementation(projects.libraries.eventformatter.test)
|
testImplementation(projects.libraries.eventformatter.test)
|
||||||
testImplementation(projects.libraries.indicator.impl)
|
testImplementation(projects.libraries.indicator.impl)
|
||||||
testImplementation(projects.libraries.permissions.noop)
|
testImplementation(projects.libraries.permissions.noop)
|
||||||
|
testImplementation(projects.libraries.preferences.test)
|
||||||
testImplementation(projects.features.invitelist.test)
|
testImplementation(projects.features.invitelist.test)
|
||||||
testImplementation(projects.features.networkmonitor.test)
|
testImplementation(projects.features.networkmonitor.test)
|
||||||
testImplementation(projects.tests.testutils)
|
testImplementation(projects.tests.testutils)
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,14 @@ fun RoomListContextMenu(
|
||||||
) {
|
) {
|
||||||
RoomListModalBottomSheetContent(
|
RoomListModalBottomSheetContent(
|
||||||
contextMenu = contextMenu,
|
contextMenu = contextMenu,
|
||||||
|
onRoomMarkReadClicked = {
|
||||||
|
eventSink(RoomListEvents.HideContextMenu)
|
||||||
|
eventSink(RoomListEvents.MarkAsRead(it))
|
||||||
|
},
|
||||||
|
onRoomMarkUnreadClicked = {
|
||||||
|
eventSink(RoomListEvents.HideContextMenu)
|
||||||
|
eventSink(RoomListEvents.MarkAsUnread(it))
|
||||||
|
},
|
||||||
onRoomSettingsClicked = {
|
onRoomSettingsClicked = {
|
||||||
eventSink(RoomListEvents.HideContextMenu)
|
eventSink(RoomListEvents.HideContextMenu)
|
||||||
onRoomSettingsClicked(it)
|
onRoomSettingsClicked(it)
|
||||||
|
|
@ -64,6 +72,8 @@ fun RoomListContextMenu(
|
||||||
@Composable
|
@Composable
|
||||||
private fun RoomListModalBottomSheetContent(
|
private fun RoomListModalBottomSheetContent(
|
||||||
contextMenu: RoomListState.ContextMenu.Shown,
|
contextMenu: RoomListState.ContextMenu.Shown,
|
||||||
|
onRoomMarkReadClicked: (roomId: RoomId) -> Unit,
|
||||||
|
onRoomMarkUnreadClicked: (roomId: RoomId) -> Unit,
|
||||||
onRoomSettingsClicked: (roomId: RoomId) -> Unit,
|
onRoomSettingsClicked: (roomId: RoomId) -> Unit,
|
||||||
onLeaveRoomClicked: (roomId: RoomId) -> Unit,
|
onLeaveRoomClicked: (roomId: RoomId) -> Unit,
|
||||||
) {
|
) {
|
||||||
|
|
@ -78,6 +88,36 @@ private fun RoomListModalBottomSheetContent(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
ListItem(
|
||||||
|
headlineContent = {
|
||||||
|
Text(
|
||||||
|
text = stringResource(
|
||||||
|
id = if (contextMenu.hasNewContent) {
|
||||||
|
R.string.screen_roomlist_mark_as_read
|
||||||
|
} else {
|
||||||
|
R.string.screen_roomlist_mark_as_unread
|
||||||
|
}
|
||||||
|
),
|
||||||
|
style = MaterialTheme.typography.bodyLarge,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
modifier = Modifier.clickable {
|
||||||
|
if (contextMenu.hasNewContent) {
|
||||||
|
onRoomMarkReadClicked(contextMenu.roomId)
|
||||||
|
} else {
|
||||||
|
onRoomMarkUnreadClicked(contextMenu.roomId)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/* TODO Design
|
||||||
|
leadingContent = ListItemContent.Icon(
|
||||||
|
iconSource = IconSource.Vector(
|
||||||
|
CompoundIcons.Settings,
|
||||||
|
contentDescription = stringResource(id = CommonStrings.common_settings)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
*/
|
||||||
|
style = ListItemStyle.Primary,
|
||||||
|
)
|
||||||
ListItem(
|
ListItem(
|
||||||
headlineContent = {
|
headlineContent = {
|
||||||
Text(
|
Text(
|
||||||
|
|
@ -96,11 +136,13 @@ private fun RoomListModalBottomSheetContent(
|
||||||
)
|
)
|
||||||
ListItem(
|
ListItem(
|
||||||
headlineContent = {
|
headlineContent = {
|
||||||
val leaveText = stringResource(id = if (contextMenu.isDm) {
|
val leaveText = stringResource(
|
||||||
CommonStrings.action_leave_conversation
|
id = if (contextMenu.isDm) {
|
||||||
} else {
|
CommonStrings.action_leave_conversation
|
||||||
CommonStrings.action_leave_room
|
} else {
|
||||||
})
|
CommonStrings.action_leave_room
|
||||||
|
}
|
||||||
|
)
|
||||||
Text(text = leaveText)
|
Text(text = leaveText)
|
||||||
},
|
},
|
||||||
modifier = Modifier.clickable { onLeaveRoomClicked(contextMenu.roomId) },
|
modifier = Modifier.clickable { onLeaveRoomClicked(contextMenu.roomId) },
|
||||||
|
|
@ -126,7 +168,10 @@ internal fun RoomListModalBottomSheetContentPreview() = ElementPreview {
|
||||||
roomId = RoomId(value = "!aRoom:aDomain"),
|
roomId = RoomId(value = "!aRoom:aDomain"),
|
||||||
roomName = "aRoom",
|
roomName = "aRoom",
|
||||||
isDm = false,
|
isDm = false,
|
||||||
|
hasNewContent = true,
|
||||||
),
|
),
|
||||||
|
onRoomMarkReadClicked = {},
|
||||||
|
onRoomMarkUnreadClicked = {},
|
||||||
onRoomSettingsClicked = {},
|
onRoomSettingsClicked = {},
|
||||||
onLeaveRoomClicked = {}
|
onLeaveRoomClicked = {}
|
||||||
)
|
)
|
||||||
|
|
@ -140,7 +185,10 @@ internal fun RoomListModalBottomSheetContentForDmPreview() = ElementPreview {
|
||||||
roomId = RoomId(value = "!aRoom:aDomain"),
|
roomId = RoomId(value = "!aRoom:aDomain"),
|
||||||
roomName = "aRoom",
|
roomName = "aRoom",
|
||||||
isDm = true,
|
isDm = true,
|
||||||
|
hasNewContent = false,
|
||||||
),
|
),
|
||||||
|
onRoomMarkReadClicked = {},
|
||||||
|
onRoomMarkUnreadClicked = {},
|
||||||
onRoomSettingsClicked = {},
|
onRoomSettingsClicked = {},
|
||||||
onLeaveRoomClicked = {}
|
onLeaveRoomClicked = {}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -28,4 +28,6 @@ sealed interface RoomListEvents {
|
||||||
data class ShowContextMenu(val roomListRoomSummary: RoomListRoomSummary) : RoomListEvents
|
data class ShowContextMenu(val roomListRoomSummary: RoomListRoomSummary) : RoomListEvents
|
||||||
data object HideContextMenu : RoomListEvents
|
data object HideContextMenu : RoomListEvents
|
||||||
data class LeaveRoom(val roomId: RoomId) : RoomListEvents
|
data class LeaveRoom(val roomId: RoomId) : RoomListEvents
|
||||||
|
data class MarkAsRead(val roomId: RoomId) : RoomListEvents
|
||||||
|
data class MarkAsUnread(val roomId: RoomId) : RoomListEvents
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,14 @@ import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.produceState
|
import androidx.compose.runtime.produceState
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.saveable.rememberSaveable
|
import androidx.compose.runtime.saveable.rememberSaveable
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import io.element.android.features.leaveroom.api.LeaveRoomEvent
|
import io.element.android.features.leaveroom.api.LeaveRoomEvent
|
||||||
import io.element.android.features.leaveroom.api.LeaveRoomPresenter
|
import io.element.android.features.leaveroom.api.LeaveRoomPresenter
|
||||||
import io.element.android.features.networkmonitor.api.NetworkMonitor
|
import io.element.android.features.networkmonitor.api.NetworkMonitor
|
||||||
import io.element.android.features.networkmonitor.api.NetworkStatus
|
import io.element.android.features.networkmonitor.api.NetworkStatus
|
||||||
|
import io.element.android.features.preferences.api.store.SessionPreferencesStore
|
||||||
import io.element.android.features.roomlist.impl.datasource.InviteStateDataSource
|
import io.element.android.features.roomlist.impl.datasource.InviteStateDataSource
|
||||||
import io.element.android.features.roomlist.impl.datasource.RoomListDataSource
|
import io.element.android.features.roomlist.impl.datasource.RoomListDataSource
|
||||||
import io.element.android.features.roomlist.impl.migration.MigrationScreenPresenter
|
import io.element.android.features.roomlist.impl.migration.MigrationScreenPresenter
|
||||||
|
|
@ -44,10 +46,12 @@ import io.element.android.libraries.indicator.api.IndicatorService
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.matrix.api.encryption.EncryptionService
|
import io.element.android.libraries.matrix.api.encryption.EncryptionService
|
||||||
import io.element.android.libraries.matrix.api.encryption.RecoveryState
|
import io.element.android.libraries.matrix.api.encryption.RecoveryState
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.ReceiptType
|
||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||||
import io.element.android.libraries.matrix.api.user.getCurrentUser
|
import io.element.android.libraries.matrix.api.user.getCurrentUser
|
||||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.flow.first
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
@ -65,9 +69,11 @@ class RoomListPresenter @Inject constructor(
|
||||||
private val featureFlagService: FeatureFlagService,
|
private val featureFlagService: FeatureFlagService,
|
||||||
private val indicatorService: IndicatorService,
|
private val indicatorService: IndicatorService,
|
||||||
private val migrationScreenPresenter: MigrationScreenPresenter,
|
private val migrationScreenPresenter: MigrationScreenPresenter,
|
||||||
|
private val sessionPreferencesStore: SessionPreferencesStore,
|
||||||
) : Presenter<RoomListState> {
|
) : Presenter<RoomListState> {
|
||||||
@Composable
|
@Composable
|
||||||
override fun present(): RoomListState {
|
override fun present(): RoomListState {
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
val leaveRoomState = leaveRoomPresenter.present()
|
val leaveRoomState = leaveRoomPresenter.present()
|
||||||
val matrixUser: MutableState<MatrixUser?> = rememberSaveable {
|
val matrixUser: MutableState<MatrixUser?> = rememberSaveable {
|
||||||
mutableStateOf(null)
|
mutableStateOf(null)
|
||||||
|
|
@ -129,10 +135,22 @@ class RoomListPresenter @Inject constructor(
|
||||||
roomId = event.roomListRoomSummary.roomId,
|
roomId = event.roomListRoomSummary.roomId,
|
||||||
roomName = event.roomListRoomSummary.name,
|
roomName = event.roomListRoomSummary.name,
|
||||||
isDm = event.roomListRoomSummary.isDm,
|
isDm = event.roomListRoomSummary.isDm,
|
||||||
|
hasNewContent = event.roomListRoomSummary.hasNewContent
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
is RoomListEvents.HideContextMenu -> contextMenu = RoomListState.ContextMenu.Hidden
|
is RoomListEvents.HideContextMenu -> contextMenu = RoomListState.ContextMenu.Hidden
|
||||||
is RoomListEvents.LeaveRoom -> leaveRoomState.eventSink(LeaveRoomEvent.ShowConfirmation(event.roomId))
|
is RoomListEvents.LeaveRoom -> leaveRoomState.eventSink(LeaveRoomEvent.ShowConfirmation(event.roomId))
|
||||||
|
is RoomListEvents.MarkAsRead -> coroutineScope.launch {
|
||||||
|
val receiptType = if (sessionPreferencesStore.isSendPublicReadReceiptsEnabled().first()) {
|
||||||
|
ReceiptType.READ
|
||||||
|
} else {
|
||||||
|
ReceiptType.READ_PRIVATE
|
||||||
|
}
|
||||||
|
client.getRoom(event.roomId)?.markAsRead(receiptType)
|
||||||
|
}
|
||||||
|
is RoomListEvents.MarkAsUnread -> coroutineScope.launch {
|
||||||
|
client.getRoom(event.roomId)?.markAsUnread()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@ data class RoomListState(
|
||||||
val roomId: RoomId,
|
val roomId: RoomId,
|
||||||
val roomName: String,
|
val roomName: String,
|
||||||
val isDm: Boolean,
|
val isDm: Boolean,
|
||||||
|
val hasNewContent: Boolean,
|
||||||
) : ContextMenu
|
) : ContextMenu
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ open class RoomListStateProvider : PreviewParameterProvider<RoomListState> {
|
||||||
roomId = RoomId("!aRoom:aDomain"),
|
roomId = RoomId("!aRoom:aDomain"),
|
||||||
roomName = "A nice room name",
|
roomName = "A nice room name",
|
||||||
isDm = false,
|
isDm = false,
|
||||||
|
hasNewContent = false,
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
aRoomListState().copy(displayRecoveryKeyPrompt = true),
|
aRoomListState().copy(displayRecoveryKeyPrompt = true),
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ class RoomListRoomSummaryFactory @Inject constructor(
|
||||||
numberOfUnreadMessages = 0,
|
numberOfUnreadMessages = 0,
|
||||||
numberOfUnreadMentions = 0,
|
numberOfUnreadMentions = 0,
|
||||||
numberOfUnreadNotifications = 0,
|
numberOfUnreadNotifications = 0,
|
||||||
|
isMarkedUnread = false,
|
||||||
userDefinedNotificationMode = null,
|
userDefinedNotificationMode = null,
|
||||||
hasRoomCall = false,
|
hasRoomCall = false,
|
||||||
isDm = false,
|
isDm = false,
|
||||||
|
|
@ -73,6 +74,7 @@ class RoomListRoomSummaryFactory @Inject constructor(
|
||||||
numberOfUnreadMessages = roomSummary.details.numUnreadMessages,
|
numberOfUnreadMessages = roomSummary.details.numUnreadMessages,
|
||||||
numberOfUnreadMentions = roomSummary.details.numUnreadMentions,
|
numberOfUnreadMentions = roomSummary.details.numUnreadMentions,
|
||||||
numberOfUnreadNotifications = roomSummary.details.numUnreadNotifications,
|
numberOfUnreadNotifications = roomSummary.details.numUnreadNotifications,
|
||||||
|
isMarkedUnread = roomSummary.details.isMarkedUnread,
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,7 @@ data class RoomListRoomSummary(
|
||||||
val numberOfUnreadMessages: Int,
|
val numberOfUnreadMessages: Int,
|
||||||
val numberOfUnreadMentions: Int,
|
val numberOfUnreadMentions: Int,
|
||||||
val numberOfUnreadNotifications: Int,
|
val numberOfUnreadNotifications: Int,
|
||||||
|
val isMarkedUnread: Boolean,
|
||||||
val timestamp: String?,
|
val timestamp: String?,
|
||||||
val lastMessage: CharSequence?,
|
val lastMessage: CharSequence?,
|
||||||
val avatarData: AvatarData,
|
val avatarData: AvatarData,
|
||||||
|
|
@ -37,10 +38,12 @@ data class RoomListRoomSummary(
|
||||||
val hasRoomCall: Boolean,
|
val hasRoomCall: Boolean,
|
||||||
val isDm: Boolean,
|
val isDm: Boolean,
|
||||||
) {
|
) {
|
||||||
val isHighlighted = userDefinedNotificationMode != RoomNotificationMode.MUTE &&
|
val isHighlighted = (userDefinedNotificationMode != RoomNotificationMode.MUTE &&
|
||||||
(numberOfUnreadNotifications > 0 || numberOfUnreadMentions > 0)
|
(numberOfUnreadNotifications > 0 || numberOfUnreadMentions > 0)) ||
|
||||||
|
isMarkedUnread
|
||||||
|
|
||||||
val hasNewContent = numberOfUnreadMessages > 0 ||
|
val hasNewContent = numberOfUnreadMessages > 0 ||
|
||||||
numberOfUnreadMentions > 0 ||
|
numberOfUnreadMentions > 0 ||
|
||||||
numberOfUnreadNotifications > 0
|
numberOfUnreadNotifications > 0 ||
|
||||||
|
isMarkedUnread
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,7 @@ internal fun aRoomListRoomSummary(
|
||||||
numberOfUnreadMessages: Int = 0,
|
numberOfUnreadMessages: Int = 0,
|
||||||
numberOfUnreadMentions: Int = 0,
|
numberOfUnreadMentions: Int = 0,
|
||||||
numberOfUnreadNotifications: Int = 0,
|
numberOfUnreadNotifications: Int = 0,
|
||||||
|
isMarkedUnread: Boolean = false,
|
||||||
lastMessage: String? = "Last message",
|
lastMessage: String? = "Last message",
|
||||||
timestamp: String? = lastMessage?.let { "88:88" },
|
timestamp: String? = lastMessage?.let { "88:88" },
|
||||||
isPlaceholder: Boolean = false,
|
isPlaceholder: Boolean = false,
|
||||||
|
|
@ -103,6 +104,7 @@ internal fun aRoomListRoomSummary(
|
||||||
numberOfUnreadMessages = numberOfUnreadMessages,
|
numberOfUnreadMessages = numberOfUnreadMessages,
|
||||||
numberOfUnreadMentions = numberOfUnreadMentions,
|
numberOfUnreadMentions = numberOfUnreadMentions,
|
||||||
numberOfUnreadNotifications = numberOfUnreadNotifications,
|
numberOfUnreadNotifications = numberOfUnreadNotifications,
|
||||||
|
isMarkedUnread = isMarkedUnread,
|
||||||
timestamp = timestamp,
|
timestamp = timestamp,
|
||||||
lastMessage = lastMessage,
|
lastMessage = lastMessage,
|
||||||
avatarData = avatarData,
|
avatarData = avatarData,
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ import io.element.android.features.leaveroom.api.LeaveRoomPresenter
|
||||||
import io.element.android.features.leaveroom.fake.FakeLeaveRoomPresenter
|
import io.element.android.features.leaveroom.fake.FakeLeaveRoomPresenter
|
||||||
import io.element.android.features.networkmonitor.api.NetworkMonitor
|
import io.element.android.features.networkmonitor.api.NetworkMonitor
|
||||||
import io.element.android.features.networkmonitor.test.FakeNetworkMonitor
|
import io.element.android.features.networkmonitor.test.FakeNetworkMonitor
|
||||||
|
import io.element.android.features.preferences.api.store.SessionPreferencesStore
|
||||||
import io.element.android.features.roomlist.impl.datasource.FakeInviteDataSource
|
import io.element.android.features.roomlist.impl.datasource.FakeInviteDataSource
|
||||||
import io.element.android.features.roomlist.impl.datasource.InviteStateDataSource
|
import io.element.android.features.roomlist.impl.datasource.InviteStateDataSource
|
||||||
import io.element.android.features.roomlist.impl.datasource.RoomListDataSource
|
import io.element.android.features.roomlist.impl.datasource.RoomListDataSource
|
||||||
|
|
@ -41,12 +42,14 @@ import io.element.android.libraries.eventformatter.api.RoomLastMessageFormatter
|
||||||
import io.element.android.libraries.eventformatter.test.FakeRoomLastMessageFormatter
|
import io.element.android.libraries.eventformatter.test.FakeRoomLastMessageFormatter
|
||||||
import io.element.android.libraries.featureflag.api.FeatureFlags
|
import io.element.android.libraries.featureflag.api.FeatureFlags
|
||||||
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
import io.element.android.libraries.featureflag.test.FakeFeatureFlagService
|
||||||
|
import io.element.android.libraries.featureflag.test.InMemorySessionPreferencesStore
|
||||||
import io.element.android.libraries.indicator.impl.DefaultIndicatorService
|
import io.element.android.libraries.indicator.impl.DefaultIndicatorService
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
import io.element.android.libraries.matrix.api.encryption.BackupState
|
import io.element.android.libraries.matrix.api.encryption.BackupState
|
||||||
import io.element.android.libraries.matrix.api.encryption.EncryptionService
|
import io.element.android.libraries.matrix.api.encryption.EncryptionService
|
||||||
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.roomlist.RoomListService
|
import io.element.android.libraries.matrix.api.roomlist.RoomListService
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.ReceiptType
|
||||||
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
import io.element.android.libraries.matrix.api.verification.SessionVerificationService
|
||||||
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
|
import io.element.android.libraries.matrix.api.verification.SessionVerifiedStatus
|
||||||
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
||||||
|
|
@ -59,6 +62,7 @@ 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.encryption.FakeEncryptionService
|
import io.element.android.libraries.matrix.test.encryption.FakeEncryptionService
|
||||||
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.aRoomSummaryFilled
|
import io.element.android.libraries.matrix.test.room.aRoomSummaryFilled
|
||||||
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
|
import io.element.android.libraries.matrix.test.roomlist.FakeRoomListService
|
||||||
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
|
import io.element.android.libraries.matrix.test.verification.FakeSessionVerificationService
|
||||||
|
|
@ -326,8 +330,14 @@ class RoomListPresenterTests {
|
||||||
initialState.eventSink(RoomListEvents.ShowContextMenu(summary))
|
initialState.eventSink(RoomListEvents.ShowContextMenu(summary))
|
||||||
|
|
||||||
val shownState = awaitItem()
|
val shownState = awaitItem()
|
||||||
assertThat(shownState.contextMenu)
|
assertThat(shownState.contextMenu).isEqualTo(
|
||||||
.isEqualTo(RoomListState.ContextMenu.Shown(summary.roomId, summary.name, false))
|
RoomListState.ContextMenu.Shown(
|
||||||
|
roomId = summary.roomId,
|
||||||
|
roomName = summary.name,
|
||||||
|
isDm = false,
|
||||||
|
hasNewContent = true,
|
||||||
|
)
|
||||||
|
)
|
||||||
scope.cancel()
|
scope.cancel()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -346,8 +356,14 @@ class RoomListPresenterTests {
|
||||||
initialState.eventSink(RoomListEvents.ShowContextMenu(summary))
|
initialState.eventSink(RoomListEvents.ShowContextMenu(summary))
|
||||||
|
|
||||||
val shownState = awaitItem()
|
val shownState = awaitItem()
|
||||||
assertThat(shownState.contextMenu)
|
assertThat(shownState.contextMenu).isEqualTo(
|
||||||
.isEqualTo(RoomListState.ContextMenu.Shown(summary.roomId, summary.name, false))
|
RoomListState.ContextMenu.Shown(
|
||||||
|
roomId = summary.roomId,
|
||||||
|
roomName = summary.name,
|
||||||
|
isDm = false,
|
||||||
|
hasNewContent = true,
|
||||||
|
)
|
||||||
|
)
|
||||||
shownState.eventSink(RoomListEvents.HideContextMenu)
|
shownState.eventSink(RoomListEvents.HideContextMenu)
|
||||||
|
|
||||||
val hiddenState = awaitItem()
|
val hiddenState = awaitItem()
|
||||||
|
|
@ -430,6 +446,41 @@ class RoomListPresenterTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `present - check that the room is marked as read with correct RR and as unread`() = runTest {
|
||||||
|
val room = FakeMatrixRoom()
|
||||||
|
val sessionPreferencesStore = InMemorySessionPreferencesStore()
|
||||||
|
val matrixClient = FakeMatrixClient().apply {
|
||||||
|
givenGetRoomResult(A_ROOM_ID, room)
|
||||||
|
}
|
||||||
|
val scope = CoroutineScope(coroutineContext + SupervisorJob())
|
||||||
|
val presenter = createRoomListPresenter(
|
||||||
|
client = matrixClient,
|
||||||
|
coroutineScope = scope,
|
||||||
|
sessionPreferencesStore = sessionPreferencesStore,
|
||||||
|
)
|
||||||
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
|
presenter.present()
|
||||||
|
}.test {
|
||||||
|
val initialState = awaitItem()
|
||||||
|
assertThat(room.markAsReadCalls).isEmpty()
|
||||||
|
assertThat(room.markAsUnreadReadCallCount).isEqualTo(0)
|
||||||
|
initialState.eventSink.invoke(RoomListEvents.MarkAsRead(A_ROOM_ID))
|
||||||
|
assertThat(room.markAsReadCalls).isEqualTo(listOf(ReceiptType.READ))
|
||||||
|
assertThat(room.markAsUnreadReadCallCount).isEqualTo(0)
|
||||||
|
initialState.eventSink.invoke(RoomListEvents.MarkAsUnread(A_ROOM_ID))
|
||||||
|
assertThat(room.markAsReadCalls).isEqualTo(listOf(ReceiptType.READ))
|
||||||
|
assertThat(room.markAsUnreadReadCallCount).isEqualTo(1)
|
||||||
|
// Test again with private read receipts
|
||||||
|
sessionPreferencesStore.setSendPublicReadReceipts(false)
|
||||||
|
initialState.eventSink.invoke(RoomListEvents.MarkAsRead(A_ROOM_ID))
|
||||||
|
assertThat(room.markAsReadCalls).isEqualTo(listOf(ReceiptType.READ, ReceiptType.READ_PRIVATE))
|
||||||
|
assertThat(room.markAsUnreadReadCallCount).isEqualTo(1)
|
||||||
|
cancelAndIgnoreRemainingEvents()
|
||||||
|
scope.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun TestScope.createRoomListPresenter(
|
private fun TestScope.createRoomListPresenter(
|
||||||
client: MatrixClient = FakeMatrixClient(),
|
client: MatrixClient = FakeMatrixClient(),
|
||||||
sessionVerificationService: SessionVerificationService = FakeSessionVerificationService(),
|
sessionVerificationService: SessionVerificationService = FakeSessionVerificationService(),
|
||||||
|
|
@ -442,6 +493,7 @@ class RoomListPresenterTests {
|
||||||
},
|
},
|
||||||
roomLastMessageFormatter: RoomLastMessageFormatter = FakeRoomLastMessageFormatter(),
|
roomLastMessageFormatter: RoomLastMessageFormatter = FakeRoomLastMessageFormatter(),
|
||||||
encryptionService: EncryptionService = FakeEncryptionService(),
|
encryptionService: EncryptionService = FakeEncryptionService(),
|
||||||
|
sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(),
|
||||||
coroutineScope: CoroutineScope,
|
coroutineScope: CoroutineScope,
|
||||||
migrationScreenPresenter: MigrationScreenPresenter = MigrationScreenPresenter(
|
migrationScreenPresenter: MigrationScreenPresenter = MigrationScreenPresenter(
|
||||||
matrixClient = client,
|
matrixClient = client,
|
||||||
|
|
@ -472,6 +524,7 @@ class RoomListPresenterTests {
|
||||||
featureFlagService = FakeFeatureFlagService(mapOf(FeatureFlags.SecureStorage.key to true)),
|
featureFlagService = FakeFeatureFlagService(mapOf(FeatureFlags.SecureStorage.key to true)),
|
||||||
),
|
),
|
||||||
migrationScreenPresenter = migrationScreenPresenter,
|
migrationScreenPresenter = migrationScreenPresenter,
|
||||||
|
sessionPreferencesStore = sessionPreferencesStore,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -484,6 +537,7 @@ private val aRoomListRoomSummary = RoomListRoomSummary(
|
||||||
numberOfUnreadMentions = 1,
|
numberOfUnreadMentions = 1,
|
||||||
numberOfUnreadMessages = 2,
|
numberOfUnreadMessages = 2,
|
||||||
numberOfUnreadNotifications = 0,
|
numberOfUnreadNotifications = 0,
|
||||||
|
isMarkedUnread = false,
|
||||||
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),
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ import io.element.android.libraries.matrix.api.media.VideoInfo
|
||||||
import io.element.android.libraries.matrix.api.poll.PollKind
|
import io.element.android.libraries.matrix.api.poll.PollKind
|
||||||
import io.element.android.libraries.matrix.api.room.location.AssetType
|
import io.element.android.libraries.matrix.api.room.location.AssetType
|
||||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimeline
|
import io.element.android.libraries.matrix.api.timeline.MatrixTimeline
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.ReceiptType
|
||||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
|
import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
|
||||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
|
import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
@ -150,6 +151,17 @@ interface MatrixRoom : Closeable {
|
||||||
|
|
||||||
suspend fun reportContent(eventId: EventId, reason: String, blockUserId: UserId?): Result<Unit>
|
suspend fun reportContent(eventId: EventId, reason: String, blockUserId: UserId?): Result<Unit>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverts a previously set unread flag, and eventually send a Read Receipt.
|
||||||
|
* @param receiptType The type of receipt to send. If null, no Read Receipt will be sent.
|
||||||
|
*/
|
||||||
|
suspend fun markAsRead(receiptType: ReceiptType?): Result<Unit>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a flag on the room to indicate that the user has explicitly marked it as unread.
|
||||||
|
*/
|
||||||
|
suspend fun markAsUnread(): Result<Unit>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Share a location message in the room.
|
* Share a location message in the room.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ data class RoomSummaryDetails(
|
||||||
val numUnreadMessages: Int,
|
val numUnreadMessages: Int,
|
||||||
val numUnreadMentions: Int,
|
val numUnreadMentions: Int,
|
||||||
val numUnreadNotifications: Int,
|
val numUnreadNotifications: Int,
|
||||||
|
val isMarkedUnread: Boolean,
|
||||||
val inviter: RoomMember?,
|
val inviter: RoomMember?,
|
||||||
val userDefinedNotificationMode: RoomNotificationMode?,
|
val userDefinedNotificationMode: RoomNotificationMode?,
|
||||||
val hasRoomCall: Boolean,
|
val hasRoomCall: Boolean,
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import io.element.android.libraries.matrix.api.room.StateEventType
|
||||||
import io.element.android.libraries.matrix.api.room.location.AssetType
|
import io.element.android.libraries.matrix.api.room.location.AssetType
|
||||||
import io.element.android.libraries.matrix.api.room.roomNotificationSettings
|
import io.element.android.libraries.matrix.api.room.roomNotificationSettings
|
||||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimeline
|
import io.element.android.libraries.matrix.api.timeline.MatrixTimeline
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.ReceiptType
|
||||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
|
import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
|
||||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
|
import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
|
||||||
import io.element.android.libraries.matrix.impl.core.toProgressWatcher
|
import io.element.android.libraries.matrix.impl.core.toProgressWatcher
|
||||||
|
|
@ -51,6 +52,7 @@ import io.element.android.libraries.matrix.impl.poll.toInner
|
||||||
import io.element.android.libraries.matrix.impl.room.location.toInner
|
import io.element.android.libraries.matrix.impl.room.location.toInner
|
||||||
import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher
|
import io.element.android.libraries.matrix.impl.room.member.RoomMemberListFetcher
|
||||||
import io.element.android.libraries.matrix.impl.timeline.RustMatrixTimeline
|
import io.element.android.libraries.matrix.impl.timeline.RustMatrixTimeline
|
||||||
|
import io.element.android.libraries.matrix.impl.timeline.toRustReceiptType
|
||||||
import io.element.android.libraries.matrix.impl.util.mxCallbackFlow
|
import io.element.android.libraries.matrix.impl.util.mxCallbackFlow
|
||||||
import io.element.android.libraries.matrix.impl.widget.RustWidgetDriver
|
import io.element.android.libraries.matrix.impl.widget.RustWidgetDriver
|
||||||
import io.element.android.libraries.matrix.impl.widget.generateWidgetWebViewUrl
|
import io.element.android.libraries.matrix.impl.widget.generateWidgetWebViewUrl
|
||||||
|
|
@ -423,6 +425,22 @@ class RustMatrixRoom(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override suspend fun markAsRead(receiptType: ReceiptType?): Result<Unit> = withContext(roomDispatcher) {
|
||||||
|
runCatching {
|
||||||
|
if (receiptType != null) {
|
||||||
|
innerRoom.markAsReadAndSendReadReceipt(receiptType.toRustReceiptType())
|
||||||
|
} else {
|
||||||
|
innerRoom.markAsRead()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun markAsUnread(): Result<Unit> = withContext(roomDispatcher) {
|
||||||
|
runCatching {
|
||||||
|
innerRoom.markAsUnread()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun sendLocation(
|
override suspend fun sendLocation(
|
||||||
body: String,
|
body: String,
|
||||||
geoUri: String,
|
geoUri: String,
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ class RoomSummaryDetailsFactory(private val roomMessageFactory: RoomMessageFacto
|
||||||
numUnreadMentions = roomInfo.numUnreadMentions.toInt(),
|
numUnreadMentions = roomInfo.numUnreadMentions.toInt(),
|
||||||
numUnreadMessages = roomInfo.numUnreadMessages.toInt(),
|
numUnreadMessages = roomInfo.numUnreadMessages.toInt(),
|
||||||
numUnreadNotifications = roomInfo.numUnreadNotifications.toInt(),
|
numUnreadNotifications = roomInfo.numUnreadNotifications.toInt(),
|
||||||
|
isMarkedUnread = roomInfo.isMarkedUnread,
|
||||||
lastMessage = latestRoomMessage,
|
lastMessage = latestRoomMessage,
|
||||||
inviter = roomInfo.inviter?.let(RoomMemberMapper::map),
|
inviter = roomInfo.inviter?.let(RoomMemberMapper::map),
|
||||||
userDefinedNotificationMode = roomInfo.userDefinedNotificationMode?.let(RoomNotificationSettingsMapper::mapMode),
|
userDefinedNotificationMode = roomInfo.userDefinedNotificationMode?.let(RoomNotificationSettingsMapper::mapMode),
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ import io.element.android.libraries.matrix.api.room.RoomNotificationMode
|
||||||
import io.element.android.libraries.matrix.api.room.StateEventType
|
import io.element.android.libraries.matrix.api.room.StateEventType
|
||||||
import io.element.android.libraries.matrix.api.room.location.AssetType
|
import io.element.android.libraries.matrix.api.room.location.AssetType
|
||||||
import io.element.android.libraries.matrix.api.timeline.MatrixTimeline
|
import io.element.android.libraries.matrix.api.timeline.MatrixTimeline
|
||||||
|
import io.element.android.libraries.matrix.api.timeline.ReceiptType
|
||||||
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
|
import io.element.android.libraries.matrix.api.timeline.item.event.EventTimelineItem
|
||||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
|
import io.element.android.libraries.matrix.api.widget.MatrixWidgetDriver
|
||||||
import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
|
import io.element.android.libraries.matrix.api.widget.MatrixWidgetSettings
|
||||||
|
|
@ -374,6 +375,20 @@ class FakeMatrixRoom(
|
||||||
return reportContentResult
|
return reportContentResult
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val markAsReadCalls = mutableListOf<ReceiptType?>()
|
||||||
|
override suspend fun markAsRead(receiptType: ReceiptType?): Result<Unit> {
|
||||||
|
markAsReadCalls.add(receiptType)
|
||||||
|
return Result.success(Unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
var markAsUnreadReadCallCount = 0
|
||||||
|
private set
|
||||||
|
|
||||||
|
override suspend fun markAsUnread(): Result<Unit> {
|
||||||
|
markAsUnreadReadCallCount++
|
||||||
|
return Result.success(Unit)
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun sendLocation(
|
override suspend fun sendLocation(
|
||||||
body: String,
|
body: String,
|
||||||
geoUri: String,
|
geoUri: String,
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ fun aRoomSummaryDetails(
|
||||||
numUnreadMentions: Int = 0,
|
numUnreadMentions: Int = 0,
|
||||||
numUnreadMessages: Int = 0,
|
numUnreadMessages: Int = 0,
|
||||||
numUnreadNotifications: Int = 0,
|
numUnreadNotifications: Int = 0,
|
||||||
|
isMarkedUnread: Boolean = false,
|
||||||
notificationMode: RoomNotificationMode? = null,
|
notificationMode: RoomNotificationMode? = null,
|
||||||
inviter: RoomMember? = null,
|
inviter: RoomMember? = null,
|
||||||
canonicalAlias: String? = null,
|
canonicalAlias: String? = null,
|
||||||
|
|
@ -76,6 +77,7 @@ fun aRoomSummaryDetails(
|
||||||
numUnreadMentions = numUnreadMentions,
|
numUnreadMentions = numUnreadMentions,
|
||||||
numUnreadMessages = numUnreadMessages,
|
numUnreadMessages = numUnreadMessages,
|
||||||
numUnreadNotifications = numUnreadNotifications,
|
numUnreadNotifications = numUnreadNotifications,
|
||||||
|
isMarkedUnread = isMarkedUnread,
|
||||||
userDefinedNotificationMode = notificationMode,
|
userDefinedNotificationMode = notificationMode,
|
||||||
inviter = inviter,
|
inviter = inviter,
|
||||||
canonicalAlias = canonicalAlias,
|
canonicalAlias = canonicalAlias,
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,7 @@ fun aRoomSummaryDetails(
|
||||||
numUnreadMentions: Int = 0,
|
numUnreadMentions: Int = 0,
|
||||||
numUnreadMessages: Int = 0,
|
numUnreadMessages: Int = 0,
|
||||||
numUnreadNotifications: Int = 0,
|
numUnreadNotifications: Int = 0,
|
||||||
|
isMarkedUnread: Boolean = false,
|
||||||
) = RoomSummaryDetails(
|
) = RoomSummaryDetails(
|
||||||
roomId = roomId,
|
roomId = roomId,
|
||||||
name = name,
|
name = name,
|
||||||
|
|
@ -130,4 +131,5 @@ fun aRoomSummaryDetails(
|
||||||
numUnreadMentions = numUnreadMentions,
|
numUnreadMentions = numUnreadMentions,
|
||||||
numUnreadMessages = numUnreadMessages,
|
numUnreadMessages = numUnreadMessages,
|
||||||
numUnreadNotifications = numUnreadNotifications,
|
numUnreadNotifications = numUnreadNotifications,
|
||||||
|
isMarkedUnread = isMarkedUnread,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ dependencies {
|
||||||
implementation(projects.libraries.network)
|
implementation(projects.libraries.network)
|
||||||
implementation(projects.libraries.dateformatter.impl)
|
implementation(projects.libraries.dateformatter.impl)
|
||||||
implementation(projects.libraries.eventformatter.impl)
|
implementation(projects.libraries.eventformatter.impl)
|
||||||
|
implementation(projects.libraries.preferences.impl)
|
||||||
implementation(projects.libraries.indicator.impl)
|
implementation(projects.libraries.indicator.impl)
|
||||||
implementation(projects.features.invitelist.impl)
|
implementation(projects.features.invitelist.impl)
|
||||||
implementation(projects.features.roomlist.impl)
|
implementation(projects.features.roomlist.impl)
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ import io.element.android.libraries.indicator.impl.DefaultIndicatorService
|
||||||
import io.element.android.libraries.matrix.api.MatrixClient
|
import io.element.android.libraries.matrix.api.MatrixClient
|
||||||
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.RoomMembershipObserver
|
import io.element.android.libraries.matrix.api.room.RoomMembershipObserver
|
||||||
|
import io.element.android.libraries.preferences.impl.store.DefaultSessionPreferencesStore
|
||||||
import io.element.android.services.toolbox.impl.strings.AndroidStringProvider
|
import io.element.android.services.toolbox.impl.strings.AndroidStringProvider
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
@ -108,7 +109,12 @@ class RoomListScreen(
|
||||||
migrationScreenPresenter = MigrationScreenPresenter(
|
migrationScreenPresenter = MigrationScreenPresenter(
|
||||||
matrixClient = matrixClient,
|
matrixClient = matrixClient,
|
||||||
migrationScreenStore = SharedPrefsMigrationScreenStore(context.getSharedPreferences("migration", Context.MODE_PRIVATE))
|
migrationScreenStore = SharedPrefsMigrationScreenStore(context.getSharedPreferences("migration", Context.MODE_PRIVATE))
|
||||||
)
|
),
|
||||||
|
sessionPreferencesStore = DefaultSessionPreferencesStore(
|
||||||
|
context = context,
|
||||||
|
sessionId = matrixClient.sessionId,
|
||||||
|
sessionCoroutineScope = Singleton.appScope
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue