Merge pull request #6818 from element-hq/feature/bma/markAsUnreadInRoomDetails
Add mark as read / unread in room details
This commit is contained in:
commit
dea808ce8d
66 changed files with 351 additions and 102 deletions
|
|
@ -38,6 +38,7 @@ interface RoomDetailsEntryPoint : FeatureEntryPoint {
|
|||
data class Params(val initialElement: InitialTarget) : NodeInputs
|
||||
|
||||
interface Callback : Plugin {
|
||||
fun onDone()
|
||||
fun navigateToGlobalNotificationSettings()
|
||||
fun navigateToDeveloperSettings()
|
||||
fun navigateToRoom(roomId: RoomId, serverNames: List<String>, clearBackStack: Boolean = false)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ dependencies {
|
|||
implementation(projects.libraries.featureflag.api)
|
||||
implementation(projects.libraries.permissions.api)
|
||||
implementation(projects.libraries.preferences.api)
|
||||
implementation(projects.libraries.push.api)
|
||||
implementation(projects.libraries.testtags)
|
||||
api(projects.features.roomdetails.api)
|
||||
api(projects.libraries.usersearch.api)
|
||||
|
|
@ -69,6 +70,7 @@ dependencies {
|
|||
testImplementation(projects.libraries.mediaviewer.test)
|
||||
testImplementation(projects.libraries.permissions.test)
|
||||
testImplementation(projects.libraries.preferences.test)
|
||||
testImplementation(projects.libraries.push.test)
|
||||
testImplementation(projects.libraries.usersearch.test)
|
||||
testImplementation(projects.libraries.featureflag.test)
|
||||
testImplementation(projects.features.call.test)
|
||||
|
|
|
|||
|
|
@ -14,4 +14,6 @@ sealed interface RoomDetailsEvent {
|
|||
data object UnmuteNotification : RoomDetailsEvent
|
||||
data class CopyToClipboard(val text: String) : RoomDetailsEvent
|
||||
data class SetFavorite(val isFavorite: Boolean) : RoomDetailsEvent
|
||||
data object MarkAsRead : RoomDetailsEvent
|
||||
data object MarkAsUnread : RoomDetailsEvent
|
||||
}
|
||||
|
|
|
|||
|
|
@ -176,6 +176,10 @@ class RoomDetailsFlowNode(
|
|||
return when (navTarget) {
|
||||
NavTarget.RoomDetails -> {
|
||||
val roomDetailsCallback = object : RoomDetailsNode.Callback {
|
||||
override fun navigateBack() {
|
||||
callback.onDone()
|
||||
}
|
||||
|
||||
override fun navigateToRoomMemberList() {
|
||||
backstack.push(NavTarget.RoomMemberList)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.roomdetails.impl
|
||||
|
||||
interface RoomDetailsNavigator {
|
||||
fun onDone()
|
||||
}
|
||||
|
|
@ -42,12 +42,13 @@ import io.element.android.libraries.androidutils.R as AndroidUtilsR
|
|||
class RoomDetailsNode(
|
||||
@Assisted buildContext: BuildContext,
|
||||
@Assisted plugins: List<Plugin>,
|
||||
private val presenter: RoomDetailsPresenter,
|
||||
presenterFactory: RoomDetailsPresenter.Factory,
|
||||
private val room: BaseRoom,
|
||||
private val analyticsService: AnalyticsService,
|
||||
private val leaveRoomRenderer: LeaveRoomRenderer,
|
||||
) : Node(buildContext, plugins = plugins) {
|
||||
) : Node(buildContext, plugins = plugins), RoomDetailsNavigator {
|
||||
interface Callback : Plugin {
|
||||
fun navigateBack()
|
||||
fun navigateToRoomMemberList()
|
||||
fun navigateToInviteMembers()
|
||||
fun navigateToRoomDetailsEdit()
|
||||
|
|
@ -65,6 +66,7 @@ class RoomDetailsNode(
|
|||
fun navigateToSelectNewOwnersWhenLeaving()
|
||||
}
|
||||
|
||||
private val presenter = presenterFactory.create(this)
|
||||
private val callback: Callback = callback()
|
||||
|
||||
init {
|
||||
|
|
@ -144,4 +146,8 @@ class RoomDetailsNode(
|
|||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun onDone() {
|
||||
callback.navigateBack()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,9 @@ import androidx.compose.runtime.getValue
|
|||
import androidx.compose.runtime.produceState
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import dev.zacsweers.metro.Inject
|
||||
import dev.zacsweers.metro.Assisted
|
||||
import dev.zacsweers.metro.AssistedFactory
|
||||
import dev.zacsweers.metro.AssistedInject
|
||||
import im.vector.app.features.analytics.plan.Interaction
|
||||
import io.element.android.features.knockrequests.api.KnockRequestPermissions
|
||||
import io.element.android.features.knockrequests.api.knockRequestPermissions
|
||||
|
|
@ -44,19 +46,24 @@ import io.element.android.libraries.matrix.api.room.join.JoinRule
|
|||
import io.element.android.libraries.matrix.api.room.powerlevels.canEditRolesAndPermissions
|
||||
import io.element.android.libraries.matrix.api.room.powerlevels.permissionsAsState
|
||||
import io.element.android.libraries.matrix.api.room.roomNotificationSettings
|
||||
import io.element.android.libraries.matrix.api.timeline.ReceiptType
|
||||
import io.element.android.libraries.matrix.ui.room.getDirectRoomMember
|
||||
import io.element.android.libraries.matrix.ui.room.roomMemberIdentityStateChange
|
||||
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
|
||||
import io.element.android.libraries.preferences.api.store.SessionPreferencesStore
|
||||
import io.element.android.libraries.push.api.notifications.NotificationCleaner
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import io.element.android.services.analyticsproviders.api.trackers.captureInteraction
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@Inject
|
||||
@AssistedInject
|
||||
class RoomDetailsPresenter(
|
||||
@Assisted private val navigator: RoomDetailsNavigator,
|
||||
private val client: MatrixClient,
|
||||
private val room: JoinedRoom,
|
||||
private val notificationSettingsService: NotificationSettingsService,
|
||||
|
|
@ -67,7 +74,16 @@ class RoomDetailsPresenter(
|
|||
private val analyticsService: AnalyticsService,
|
||||
private val clipboardHelper: ClipboardHelper,
|
||||
private val appPreferencesStore: AppPreferencesStore,
|
||||
private val sessionPreferencesStore: SessionPreferencesStore,
|
||||
private val notificationCleaner: NotificationCleaner,
|
||||
) : Presenter<RoomDetailsState> {
|
||||
@AssistedFactory
|
||||
interface Factory {
|
||||
fun create(
|
||||
navigator: RoomDetailsNavigator,
|
||||
): RoomDetailsPresenter
|
||||
}
|
||||
|
||||
@Composable
|
||||
override fun present(): RoomDetailsState {
|
||||
val scope = rememberCoroutineScope()
|
||||
|
|
@ -79,6 +95,14 @@ class RoomDetailsPresenter(
|
|||
val roomTopic by remember { derivedStateOf { roomInfo.topic } }
|
||||
val isFavorite by remember { derivedStateOf { roomInfo.isFavorite } }
|
||||
val joinRule by remember { derivedStateOf { roomInfo.joinRule } }
|
||||
val hasNewContent by remember {
|
||||
derivedStateOf {
|
||||
roomInfo.numUnreadMessages > 0 ||
|
||||
roomInfo.numUnreadMentions > 0 ||
|
||||
roomInfo.numUnreadNotifications > 0 ||
|
||||
roomInfo.isMarkedUnread
|
||||
}
|
||||
}
|
||||
|
||||
val pinnedMessagesCount by remember { derivedStateOf { roomInfo.pinnedEventIds.size } }
|
||||
|
||||
|
|
@ -145,6 +169,8 @@ class RoomDetailsPresenter(
|
|||
clipboardHelper.copyPlainText(event.text)
|
||||
snackbarDispatcher.post(SnackbarMessage(CommonStrings.common_copied_to_clipboard))
|
||||
}
|
||||
is RoomDetailsEvent.MarkAsRead -> scope.markAsRead()
|
||||
is RoomDetailsEvent.MarkAsUnread -> scope.markAsUnread()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -188,6 +214,7 @@ class RoomDetailsPresenter(
|
|||
showDebugInfo = isDeveloperModeEnabled,
|
||||
roomVersion = roomInfo.roomVersion,
|
||||
roomHistoryVisibility = roomInfo.historyVisibility,
|
||||
hasNewContent = hasNewContent,
|
||||
eventSink = ::handleEvent,
|
||||
)
|
||||
}
|
||||
|
|
@ -241,4 +268,26 @@ class RoomDetailsPresenter(
|
|||
analyticsService.captureInteraction(Interaction.Name.MobileRoomFavouriteToggle)
|
||||
}
|
||||
}
|
||||
|
||||
private fun CoroutineScope.markAsRead() = launch {
|
||||
notificationCleaner.clearMessagesForRoom(client.sessionId, room.roomId)
|
||||
room.setUnreadFlag(isUnread = false)
|
||||
val receiptType = if (sessionPreferencesStore.isSendPublicReadReceiptsEnabled().first()) {
|
||||
ReceiptType.READ
|
||||
} else {
|
||||
ReceiptType.READ_PRIVATE
|
||||
}
|
||||
room.markAsRead(receiptType)
|
||||
.onSuccess {
|
||||
analyticsService.captureInteraction(name = Interaction.Name.MobileRoomListRoomContextMenuUnreadToggle)
|
||||
}
|
||||
}
|
||||
|
||||
private fun CoroutineScope.markAsUnread() = launch {
|
||||
room.setUnreadFlag(isUnread = true)
|
||||
.onSuccess {
|
||||
analyticsService.captureInteraction(name = Interaction.Name.MobileRoomListRoomContextMenuUnreadToggle)
|
||||
navigator.onDone()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ data class RoomDetailsState(
|
|||
val showDebugInfo: Boolean,
|
||||
val roomVersion: String?,
|
||||
val roomHistoryVisibility: RoomHistoryVisibility,
|
||||
val hasNewContent: Boolean,
|
||||
val eventSink: (RoomDetailsEvent) -> Unit
|
||||
) {
|
||||
val roomBadges = buildList {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ open class RoomDetailsStateProvider : PreviewParameterProvider<RoomDetailsState>
|
|||
override val values: Sequence<RoomDetailsState>
|
||||
get() = sequenceOf(
|
||||
aRoomDetailsState(displayAdminSettings = true),
|
||||
aRoomDetailsState(roomTopic = RoomTopicState.Hidden, showDebugInfo = true),
|
||||
aRoomDetailsState(roomTopic = RoomTopicState.Hidden, showDebugInfo = true, hasNewContent = true),
|
||||
aRoomDetailsState(roomTopic = RoomTopicState.CanAddTopic),
|
||||
aRoomDetailsState(isEncrypted = false),
|
||||
aRoomDetailsState(roomAlias = null),
|
||||
|
|
@ -123,6 +123,7 @@ fun aRoomDetailsState(
|
|||
isTombstoned: Boolean = false,
|
||||
showDebugInfo: Boolean = false,
|
||||
roomHistoryVisibility: RoomHistoryVisibility = RoomHistoryVisibility.Shared,
|
||||
hasNewContent: Boolean = false,
|
||||
eventSink: (RoomDetailsEvent) -> Unit = {},
|
||||
) = RoomDetailsState(
|
||||
roomId = roomId,
|
||||
|
|
@ -154,6 +155,7 @@ fun aRoomDetailsState(
|
|||
showDebugInfo = showDebugInfo,
|
||||
roomVersion = "12",
|
||||
roomHistoryVisibility = roomHistoryVisibility,
|
||||
hasNewContent = hasNewContent,
|
||||
eventSink = eventSink,
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
package io.element.android.features.roomdetails.impl
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.interaction.MutableInteractionSource
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
|
|
@ -188,6 +189,46 @@ fun RoomDetailsView(
|
|||
)
|
||||
}
|
||||
|
||||
PreferenceCategory {
|
||||
if (state.hasNewContent) {
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Text(
|
||||
text = stringResource(id = R.string.screen_roomlist_mark_as_read),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
state.eventSink(RoomDetailsEvent.MarkAsRead)
|
||||
},
|
||||
leadingContent = ListItemContent.Icon(
|
||||
iconSource = IconSource.Vector(CompoundIcons.MarkAsRead())
|
||||
),
|
||||
trailingContent = ListItemContent.Custom {
|
||||
Box(
|
||||
modifier = modifier
|
||||
.size(8.dp)
|
||||
.clip(CircleShape)
|
||||
.background(ElementTheme.colors.iconAccentPrimary)
|
||||
)
|
||||
},
|
||||
)
|
||||
} else {
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Text(
|
||||
text = stringResource(id = R.string.screen_roomlist_mark_as_unread),
|
||||
)
|
||||
},
|
||||
onClick = {
|
||||
state.eventSink(RoomDetailsEvent.MarkAsUnread)
|
||||
},
|
||||
leadingContent = ListItemContent.Icon(
|
||||
iconSource = IconSource.Vector(CompoundIcons.MarkAsUnread())
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
PreferenceCategory {
|
||||
if (state.roomNotificationSettings != null) {
|
||||
NotificationItem(
|
||||
|
|
|
|||
|
|
@ -132,6 +132,8 @@
|
|||
<string name="screen_room_roles_and_permissions_roles_header">"Roles"</string>
|
||||
<string name="screen_room_roles_and_permissions_room_details">"Room details"</string>
|
||||
<string name="screen_room_roles_and_permissions_title">"Roles & permissions"</string>
|
||||
<string name="screen_roomlist_mark_as_read">"Mark as read"</string>
|
||||
<string name="screen_roomlist_mark_as_unread">"Mark as unread"</string>
|
||||
<string name="screen_security_and_privacy_add_room_address_action">"Add address"</string>
|
||||
<string name="screen_security_and_privacy_ask_to_join_multiple_spaces_members_option_description">"Anyone in authorised spaces can join, but everyone else must request access."</string>
|
||||
<string name="screen_security_and_privacy_ask_to_join_option_description">"Everyone must request access."</string>
|
||||
|
|
|
|||
|
|
@ -68,6 +68,7 @@ class DefaultRoomDetailsEntryPointTest {
|
|||
)
|
||||
}
|
||||
val callback = object : RoomDetailsEntryPoint.Callback {
|
||||
override fun onDone() = lambdaError()
|
||||
override fun navigateToGlobalNotificationSettings() = lambdaError()
|
||||
override fun navigateToDeveloperSettings() = lambdaError()
|
||||
override fun navigateToRoom(roomId: RoomId, serverNames: List<String>, clearBackStack: Boolean) = lambdaError()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.roomdetails.impl
|
||||
|
||||
import io.element.android.tests.testutils.lambda.lambdaError
|
||||
|
||||
class FakeRoomDetailsNavigator(
|
||||
private val onDoneResult: () -> Unit = { lambdaError() }
|
||||
) : RoomDetailsNavigator {
|
||||
override fun onDone() = onDoneResult()
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@ 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.join.JoinRule
|
||||
import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions
|
||||
import io.element.android.libraries.matrix.api.timeline.ReceiptType
|
||||
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ALIAS
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_ID
|
||||
|
|
@ -28,7 +29,7 @@ import io.element.android.libraries.matrix.test.room.aRoomInfo
|
|||
import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions
|
||||
import io.element.android.tests.testutils.lambda.lambdaError
|
||||
|
||||
fun aRoom(
|
||||
fun aFakeBaseRoom(
|
||||
sessionId: SessionId = A_SESSION_ID,
|
||||
roomId: RoomId = A_ROOM_ID,
|
||||
displayName: String = A_ROOM_NAME,
|
||||
|
|
@ -49,6 +50,7 @@ fun aRoom(
|
|||
getUpdatedMemberResult: (UserId) -> Result<RoomMember> = { lambdaError() },
|
||||
userRoleResult: () -> Result<RoomMember.Role> = { lambdaError() },
|
||||
setIsFavoriteResult: (Boolean) -> Result<Unit> = { lambdaError() },
|
||||
markAsReadResult: (ReceiptType) -> Result<Unit> = { lambdaError() },
|
||||
) = FakeBaseRoom(
|
||||
sessionId = sessionId,
|
||||
roomId = roomId,
|
||||
|
|
@ -57,6 +59,7 @@ fun aRoom(
|
|||
getUpdatedMemberResult = getUpdatedMemberResult,
|
||||
userRoleResult = userRoleResult,
|
||||
setIsFavoriteResult = setIsFavoriteResult,
|
||||
markAsReadResult = markAsReadResult,
|
||||
roomPermissions = roomPermissions,
|
||||
initialRoomInfo = aRoomInfo(
|
||||
name = displayName,
|
||||
|
|
@ -106,6 +109,7 @@ fun aJoinedRoom(
|
|||
publishRoomAliasInRoomDirectoryResult: (RoomAlias) -> Result<Boolean> = { lambdaError() },
|
||||
removeRoomAliasFromRoomDirectoryResult: (RoomAlias) -> Result<Boolean> = { lambdaError() },
|
||||
setIsFavoriteResult: (Boolean) -> Result<Unit> = { lambdaError() },
|
||||
markAsReadResult: (ReceiptType) -> Result<Unit> = { lambdaError() },
|
||||
) = FakeJoinedRoom(
|
||||
roomNotificationSettingsService = notificationSettingsService,
|
||||
setNameResult = setNameResult,
|
||||
|
|
@ -118,7 +122,7 @@ fun aJoinedRoom(
|
|||
updateCanonicalAliasResult = updateCanonicalAliasResult,
|
||||
publishRoomAliasInRoomDirectoryResult = publishRoomAliasInRoomDirectoryResult,
|
||||
removeRoomAliasFromRoomDirectoryResult = removeRoomAliasFromRoomDirectoryResult,
|
||||
baseRoom = aRoom(
|
||||
baseRoom = aFakeBaseRoom(
|
||||
sessionId = sessionId,
|
||||
roomId = roomId,
|
||||
roomPermissions = roomPermissions,
|
||||
|
|
@ -139,5 +143,6 @@ fun aJoinedRoom(
|
|||
joinedMemberCount = joinedMemberCount,
|
||||
activeMemberCount = activeMemberCount,
|
||||
invitedMemberCount = invitedMemberCount,
|
||||
markAsReadResult = markAsReadResult,
|
||||
)
|
||||
)
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ import io.element.android.libraries.androidutils.clipboard.ClipboardHelper
|
|||
import io.element.android.libraries.androidutils.clipboard.FakeClipboardHelper
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.core.coroutine.CoroutineDispatchers
|
||||
import io.element.android.libraries.matrix.api.core.RoomId
|
||||
import io.element.android.libraries.matrix.api.core.SessionId
|
||||
import io.element.android.libraries.matrix.api.core.UserId
|
||||
import io.element.android.libraries.matrix.api.room.JoinedRoom
|
||||
import io.element.android.libraries.matrix.api.room.RoomMembersState
|
||||
|
|
@ -28,6 +30,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.join.JoinRule
|
||||
import io.element.android.libraries.matrix.api.room.powerlevels.RoomPermissions
|
||||
import io.element.android.libraries.matrix.api.timeline.ReceiptType
|
||||
import io.element.android.libraries.matrix.test.AN_AVATAR_URL
|
||||
import io.element.android.libraries.matrix.test.AN_EVENT_ID
|
||||
import io.element.android.libraries.matrix.test.A_ROOM_NAME
|
||||
|
|
@ -41,7 +44,11 @@ import io.element.android.libraries.matrix.test.notificationsettings.FakeNotific
|
|||
import io.element.android.libraries.matrix.test.room.aRoomInfo
|
||||
import io.element.android.libraries.matrix.test.room.powerlevels.FakeRoomPermissions
|
||||
import io.element.android.libraries.preferences.api.store.AppPreferencesStore
|
||||
import io.element.android.libraries.preferences.api.store.SessionPreferencesStore
|
||||
import io.element.android.libraries.preferences.test.InMemoryAppPreferencesStore
|
||||
import io.element.android.libraries.preferences.test.InMemorySessionPreferencesStore
|
||||
import io.element.android.libraries.push.api.notifications.NotificationCleaner
|
||||
import io.element.android.libraries.push.test.notifications.FakeNotificationCleaner
|
||||
import io.element.android.services.analytics.api.AnalyticsService
|
||||
import io.element.android.services.analytics.test.FakeAnalyticsService
|
||||
import io.element.android.tests.testutils.EventsRecorder
|
||||
|
|
@ -79,7 +86,10 @@ class RoomDetailsPresenterTest {
|
|||
analyticsService: AnalyticsService = FakeAnalyticsService(),
|
||||
encryptionService: FakeEncryptionService = FakeEncryptionService(),
|
||||
clipboardHelper: ClipboardHelper = FakeClipboardHelper(),
|
||||
appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore()
|
||||
appPreferencesStore: AppPreferencesStore = InMemoryAppPreferencesStore(),
|
||||
navigator: RoomDetailsNavigator = FakeRoomDetailsNavigator(),
|
||||
notificationCleaner: NotificationCleaner = FakeNotificationCleaner(),
|
||||
sessionPreferencesStore: SessionPreferencesStore = InMemorySessionPreferencesStore(),
|
||||
): RoomDetailsPresenter {
|
||||
val matrixClient = FakeMatrixClient(notificationSettingsService = notificationSettingsService)
|
||||
val roomMemberDetailsPresenterFactory = object : RoomMemberDetailsPresenter.Factory {
|
||||
|
|
@ -96,6 +106,7 @@ class RoomDetailsPresenterTest {
|
|||
}
|
||||
}
|
||||
return RoomDetailsPresenter(
|
||||
navigator = navigator,
|
||||
client = matrixClient,
|
||||
room = room,
|
||||
notificationSettingsService = matrixClient.notificationSettingsService,
|
||||
|
|
@ -106,6 +117,8 @@ class RoomDetailsPresenterTest {
|
|||
analyticsService = analyticsService,
|
||||
clipboardHelper = clipboardHelper,
|
||||
appPreferencesStore = appPreferencesStore,
|
||||
notificationCleaner = notificationCleaner,
|
||||
sessionPreferencesStore = sessionPreferencesStore,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -598,6 +611,87 @@ class RoomDetailsPresenterTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - mark as read`() = runTest {
|
||||
val markAsReadResult = lambdaRecorder<ReceiptType, Result<Unit>> { _ -> Result.success(Unit) }
|
||||
val room = aJoinedRoom(
|
||||
markAsReadResult = markAsReadResult,
|
||||
)
|
||||
val clearMessagesForRoomResult = lambdaRecorder<SessionId, RoomId, Unit> { _, _ -> Result.success(Unit) }
|
||||
val notificationCleaner = FakeNotificationCleaner(
|
||||
clearMessagesForRoomLambda = clearMessagesForRoomResult,
|
||||
)
|
||||
val presenter = createRoomDetailsPresenter(
|
||||
room = room,
|
||||
notificationCleaner = notificationCleaner,
|
||||
)
|
||||
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
|
||||
skipItems(1)
|
||||
with(awaitItem()) {
|
||||
eventSink(RoomDetailsEvent.MarkAsRead)
|
||||
}
|
||||
assertThat(room.baseRoom.setUnreadFlagCalls).containsExactly(false)
|
||||
markAsReadResult.assertions().isCalledOnce().with(value(ReceiptType.READ))
|
||||
clearMessagesForRoomResult.assertions().isCalledOnce().with(
|
||||
value(room.sessionId),
|
||||
value(room.roomId),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - mark as read - private`() = runTest {
|
||||
val markAsReadResult = lambdaRecorder<ReceiptType, Result<Unit>> { _ -> Result.success(Unit) }
|
||||
val room = aJoinedRoom(
|
||||
markAsReadResult = markAsReadResult,
|
||||
)
|
||||
val sessionPreferencesStore = InMemorySessionPreferencesStore(
|
||||
isSendPublicReadReceiptsEnabled = false,
|
||||
)
|
||||
val clearMessagesForRoomResult = lambdaRecorder<SessionId, RoomId, Unit> { _, _ -> Result.success(Unit) }
|
||||
val notificationCleaner = FakeNotificationCleaner(
|
||||
clearMessagesForRoomLambda = clearMessagesForRoomResult,
|
||||
)
|
||||
val presenter = createRoomDetailsPresenter(
|
||||
room = room,
|
||||
notificationCleaner = notificationCleaner,
|
||||
sessionPreferencesStore = sessionPreferencesStore,
|
||||
)
|
||||
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
|
||||
skipItems(1)
|
||||
with(awaitItem()) {
|
||||
eventSink(RoomDetailsEvent.MarkAsRead)
|
||||
}
|
||||
assertThat(room.baseRoom.setUnreadFlagCalls).containsExactly(false)
|
||||
markAsReadResult.assertions().isCalledOnce().with(value(ReceiptType.READ_PRIVATE))
|
||||
clearMessagesForRoomResult.assertions().isCalledOnce().with(
|
||||
value(room.sessionId),
|
||||
value(room.roomId),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - mark as unread`() = runTest {
|
||||
val room = aJoinedRoom()
|
||||
val onDoneResult = lambdaRecorder<Unit> { }
|
||||
val navigator = FakeRoomDetailsNavigator(
|
||||
onDoneResult = onDoneResult
|
||||
)
|
||||
val presenter = createRoomDetailsPresenter(
|
||||
room = room,
|
||||
navigator = navigator,
|
||||
)
|
||||
presenter.testWithLifecycleOwner(lifecycleOwner = fakeLifecycleOwner) {
|
||||
skipItems(1)
|
||||
with(awaitItem()) {
|
||||
eventSink(RoomDetailsEvent.MarkAsUnread)
|
||||
}
|
||||
onDoneResult.assertions().isCalledOnce()
|
||||
assertThat(room.baseRoom.setUnreadFlagCalls).containsExactly(true)
|
||||
}
|
||||
}
|
||||
|
||||
private fun roomPermissions(
|
||||
canInvite: Boolean = true,
|
||||
canKick: Boolean = true,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue