Dismiss mark as unread button eagerly
This commit is contained in:
+14
-2
@@ -138,6 +138,12 @@ class TimelinePresenter(
|
||||
val newEventState = remember { mutableStateOf<NewEventState>(NewEventState.None) }
|
||||
val messageShieldDialogData: MutableState<MessageShieldData?> = remember { mutableStateOf(null) }
|
||||
|
||||
// Forces [JumpToUnreadState.Hidden] until the next RoomInfo push. Set after a
|
||||
// [TimelineEvent.MarkAllAsRead] await completes so the FAB hides without waiting for
|
||||
// the SDK to push a refreshed fully-read marker; the after-await ordering means any
|
||||
// RoomInfo update racing the mark-as-read call has already landed and can't undo this.
|
||||
val suppressJumpToUnread = remember { mutableStateOf(false) }
|
||||
|
||||
val resolveVerifiedUserSendFailureState = resolveVerifiedUserSendFailurePresenter.present()
|
||||
val isSendPublicReadReceiptsEnabled by remember {
|
||||
sessionPreferencesStore.isSendPublicReadReceiptsEnabled()
|
||||
@@ -234,6 +240,7 @@ class TimelinePresenter(
|
||||
null
|
||||
} ?: return@launch
|
||||
markAsFullyRead(room.roomId, latestEventId)
|
||||
suppressJumpToUnread.value = true
|
||||
}
|
||||
is TimelineEvent.ShowShieldDialog -> messageShieldDialogData.value = event.messageShieldData
|
||||
is TimelineEvent.ComputeVerifiedUserSendFailure -> {
|
||||
@@ -300,8 +307,13 @@ class TimelinePresenter(
|
||||
// - Hidden: feature flag off, no marker, caught-up (marker loaded but no virtual item),
|
||||
// or initial load (no items yet).
|
||||
val jumpToUnread = remember { mutableStateOf<JumpToUnreadState>(JumpToUnreadState.Hidden) }
|
||||
LaunchedEffect(timelineItems, displayJumpToUnread, roomInfo.fullyReadEventId) {
|
||||
if (!displayJumpToUnread) {
|
||||
// The SDK is authoritative again once it pushes a new fully-read marker, so drop the
|
||||
// post-mark-as-read suppression and let the recompute below pick up the new value.
|
||||
LaunchedEffect(roomInfo.fullyReadEventId) {
|
||||
suppressJumpToUnread.value = false
|
||||
}
|
||||
LaunchedEffect(timelineItems, displayJumpToUnread, roomInfo.fullyReadEventId, suppressJumpToUnread.value) {
|
||||
if (!displayJumpToUnread || suppressJumpToUnread.value) {
|
||||
jumpToUnread.value = JumpToUnreadState.Hidden
|
||||
return@LaunchedEffect
|
||||
}
|
||||
|
||||
+38
@@ -754,6 +754,44 @@ class TimelinePresenterTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - jumpToUnread hides eagerly after MarkAllAsRead even before a new RoomInfo arrives`() = runTest {
|
||||
val timelineItems = MutableStateFlow(emptyList<MatrixTimelineItem>())
|
||||
val timeline = FakeTimeline(
|
||||
timelineItems = timelineItems,
|
||||
getLatestEventIdResult = { Result.success(AN_EVENT_ID_2) },
|
||||
)
|
||||
val fullyReadEventId = EventId("\$older-than-loaded-window")
|
||||
val room = FakeJoinedRoom(
|
||||
liveTimeline = timeline,
|
||||
baseRoom = FakeBaseRoom(
|
||||
roomPermissions = roomPermissions(),
|
||||
initialRoomInfo = aRoomInfo(fullyReadEventId = fullyReadEventId),
|
||||
),
|
||||
)
|
||||
val presenter = createTimelinePresenter(
|
||||
timeline = timeline,
|
||||
room = room,
|
||||
featureFlagService = FakeFeatureFlagService(initialState = mapOf(FeatureFlags.JumpToUnread.key to true)),
|
||||
)
|
||||
presenter.test {
|
||||
awaitFirstItem()
|
||||
timelineItems.emit(
|
||||
listOf(
|
||||
MatrixTimelineItem.Event(UniqueId("1"), anEventTimelineItem(eventId = AN_EVENT_ID, content = aMessageContent())),
|
||||
)
|
||||
)
|
||||
val outOfWindow = consumeItemsUntilPredicate { it.jumpToUnread is JumpToUnreadState.OutOfWindow }.last()
|
||||
assertThat(outOfWindow.jumpToUnread).isEqualTo(JumpToUnreadState.OutOfWindow(eventId = fullyReadEventId))
|
||||
|
||||
outOfWindow.eventSink(TimelineEvent.MarkAllAsRead)
|
||||
// RoomInfo is intentionally NOT updated — eager hide must fire on the await alone.
|
||||
val afterMark = consumeItemsUntilPredicate { it.jumpToUnread == JumpToUnreadState.Hidden }.last()
|
||||
assertThat(afterMark.jumpToUnread).isEqualTo(JumpToUnreadState.Hidden)
|
||||
cancelAndIgnoreRemainingEvents()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - reaction ordering`() = runTest {
|
||||
val timelineItems = MutableStateFlow(emptyList<MatrixTimelineItem>())
|
||||
|
||||
Reference in New Issue
Block a user