Code cleanup, accessibility checks
This commit is contained in:
+1
-1
@@ -111,7 +111,7 @@ private fun RoomListModalBottomSheetContent(
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Text(
|
||||
text = stringResource(id = R.string.screen_roomlist_mark_as_read),
|
||||
text = stringResource(id = CommonStrings.action_mark_as_read),
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
)
|
||||
},
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ class RoomListContextMenuTest {
|
||||
contextMenu = contextMenu,
|
||||
eventSink = eventsRecorder,
|
||||
)
|
||||
clickOn(R.string.screen_roomlist_mark_as_read)
|
||||
clickOn(CommonStrings.action_mark_as_read)
|
||||
eventsRecorder.assertList(
|
||||
listOf(
|
||||
RoomListEvent.HideContextMenu,
|
||||
|
||||
+5
@@ -287,6 +287,11 @@ class TimelinePresenter(
|
||||
// read marker advances in place — the SDK swaps the marker virtual item to a new position
|
||||
// without changing the list length, e.g. when [markRoomAsFullyRead] is sent while at the
|
||||
// bottom of the room.
|
||||
//
|
||||
// Limitation: when the read marker is outside the loaded window (gaps, pagination), this
|
||||
// returns null and the jump-to-unread button stays hidden. Proper fix needs an SDK
|
||||
// accessor for the m.fully_read marker plus FocusedOnEvent navigation on click; gated
|
||||
// behind FeatureFlags.JumpToUnread until that lands.
|
||||
val readMarkerIndex = remember { mutableStateOf<Int?>(null) }
|
||||
LaunchedEffect(timelineItems, displayJumpToUnread) {
|
||||
if (!displayJumpToUnread) {
|
||||
|
||||
+8
-3
@@ -48,7 +48,6 @@ import androidx.compose.runtime.snapshotFlow
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.graphics.vector.ImageVector
|
||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
@@ -88,6 +87,7 @@ import io.element.android.libraries.designsystem.utils.animateScrollToItemCenter
|
||||
import io.element.android.libraries.matrix.api.core.EventId
|
||||
import io.element.android.libraries.matrix.api.timeline.Timeline
|
||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
||||
import io.element.android.libraries.testtags.TestTag
|
||||
import io.element.android.libraries.testtags.TestTags
|
||||
import io.element.android.libraries.testtags.testTag
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
@@ -418,6 +418,7 @@ private fun BoxScope.TimelineScrollHelper(
|
||||
hasUnread = true,
|
||||
onClick = ::jumpToReadMarker,
|
||||
onMarkAsRead = onMarkAllAsRead,
|
||||
testTag = TestTags.jumpToUnreadButton,
|
||||
)
|
||||
JumpToPositionButton(
|
||||
icon = CompoundIcons.ChevronDown(),
|
||||
@@ -426,6 +427,7 @@ private fun BoxScope.TimelineScrollHelper(
|
||||
hasUnread = displayJumpToUnread && newEventState is NewEventState.FromOther,
|
||||
onClick = ::jumpToBottom,
|
||||
onMarkAsRead = onMarkAllAsRead,
|
||||
testTag = TestTags.jumpToBottomButton,
|
||||
dotAlignment = Alignment.BottomCenter,
|
||||
)
|
||||
}
|
||||
@@ -439,6 +441,7 @@ private fun JumpToPositionButton(
|
||||
hasUnread: Boolean,
|
||||
onClick: () -> Unit,
|
||||
onMarkAsRead: () -> Unit,
|
||||
testTag: TestTag,
|
||||
modifier: Modifier = Modifier,
|
||||
dotAlignment: Alignment = Alignment.TopCenter,
|
||||
) {
|
||||
@@ -453,15 +456,15 @@ private fun JumpToPositionButton(
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(36.dp)
|
||||
.shadow(elevation = 0.dp, shape = CircleShape)
|
||||
.background(color = ElementTheme.colors.bgCanvasDefault, shape = CircleShape)
|
||||
.clip(CircleShape)
|
||||
.border(1.dp, ElementTheme.colors.borderDisabled, CircleShape)
|
||||
.combinedClickable(
|
||||
onClick = onClick,
|
||||
onLongClick = { menuExpanded = true },
|
||||
onLongClickLabel = stringResource(CommonStrings.action_open_context_menu),
|
||||
)
|
||||
.testTag(TestTags.floatingActionButton),
|
||||
.testTag(testTag),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
Icon(
|
||||
@@ -476,6 +479,8 @@ private fun JumpToPositionButton(
|
||||
minWidth = 0.dp,
|
||||
offset = DpOffset(x = -44.dp, y = 40.dp)
|
||||
) {
|
||||
// Hand-rolled instead of DropdownMenuItem: padding here is tighter
|
||||
// than DropdownMenuItem's 12.dp default to match the Figma spec.
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.clickable {
|
||||
|
||||
+16
@@ -1238,6 +1238,22 @@ class TimelinePresenterTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `present - MarkAllAsRead does not invoke markAsFullyRead when there is no latest event`() = runTest {
|
||||
val markAsFullyReadRecorder = lambdaRecorder<RoomId, EventId, Unit> { _, _ -> }
|
||||
val presenter = createTimelinePresenter(
|
||||
timeline = FakeTimeline(getLatestEventIdResult = { Result.success(null) }),
|
||||
markAsFullyRead = FakeMarkAsFullyRead(markAsFullyReadRecorder),
|
||||
)
|
||||
presenter.test {
|
||||
val initialState = awaitFirstItem()
|
||||
initialState.eventSink(TimelineEvent.MarkAllAsRead)
|
||||
advanceUntilIdle()
|
||||
markAsFullyReadRecorder.assertions().isNeverCalled()
|
||||
cancelAndIgnoreRemainingEvents()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun <T> ReceiveTurbine<T>.awaitFirstItem(): T {
|
||||
return awaitItem()
|
||||
}
|
||||
|
||||
+1
-2
@@ -35,7 +35,6 @@ fun DropdownMenuItem(
|
||||
leadingIcon: @Composable (() -> Unit)? = null,
|
||||
trailingIcon: @Composable (() -> Unit)? = null,
|
||||
enabled: Boolean = true,
|
||||
contentPadding: PaddingValues = DropDownMenuItemDefaults.contentPadding,
|
||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||
) {
|
||||
androidx.compose.material3.DropdownMenuItem(
|
||||
@@ -50,7 +49,7 @@ fun DropdownMenuItem(
|
||||
trailingIcon = trailingIcon,
|
||||
enabled = enabled,
|
||||
colors = DropDownMenuItemDefaults.colors(),
|
||||
contentPadding = contentPadding,
|
||||
contentPadding = DropDownMenuItemDefaults.contentPadding,
|
||||
interactionSource = interactionSource
|
||||
)
|
||||
}
|
||||
|
||||
@@ -98,6 +98,12 @@ object TestTags {
|
||||
*/
|
||||
val floatingActionButton = TestTag("floating-action-button")
|
||||
|
||||
/**
|
||||
* Timeline jump-to-position buttons (long-press exposes "Mark as read").
|
||||
*/
|
||||
val jumpToUnreadButton = TestTag("jump-to-unread-button")
|
||||
val jumpToBottomButton = TestTag("jump-to-bottom-button")
|
||||
|
||||
/**
|
||||
* Timeline.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user