mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-02 12:07:28 +00:00
Code cleanup, accessibility checks
This commit is contained in:
+1
-1
@@ -111,7 +111,7 @@ private fun RoomListModalBottomSheetContent(
|
|||||||
ListItem(
|
ListItem(
|
||||||
headlineContent = {
|
headlineContent = {
|
||||||
Text(
|
Text(
|
||||||
text = stringResource(id = R.string.screen_roomlist_mark_as_read),
|
text = stringResource(id = CommonStrings.action_mark_as_read),
|
||||||
style = MaterialTheme.typography.bodyLarge,
|
style = MaterialTheme.typography.bodyLarge,
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|||||||
+1
-1
@@ -36,7 +36,7 @@ class RoomListContextMenuTest {
|
|||||||
contextMenu = contextMenu,
|
contextMenu = contextMenu,
|
||||||
eventSink = eventsRecorder,
|
eventSink = eventsRecorder,
|
||||||
)
|
)
|
||||||
clickOn(R.string.screen_roomlist_mark_as_read)
|
clickOn(CommonStrings.action_mark_as_read)
|
||||||
eventsRecorder.assertList(
|
eventsRecorder.assertList(
|
||||||
listOf(
|
listOf(
|
||||||
RoomListEvent.HideContextMenu,
|
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
|
// 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
|
// without changing the list length, e.g. when [markRoomAsFullyRead] is sent while at the
|
||||||
// bottom of the room.
|
// 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) }
|
val readMarkerIndex = remember { mutableStateOf<Int?>(null) }
|
||||||
LaunchedEffect(timelineItems, displayJumpToUnread) {
|
LaunchedEffect(timelineItems, displayJumpToUnread) {
|
||||||
if (!displayJumpToUnread) {
|
if (!displayJumpToUnread) {
|
||||||
|
|||||||
+8
-3
@@ -48,7 +48,6 @@ import androidx.compose.runtime.snapshotFlow
|
|||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.draw.clip
|
import androidx.compose.ui.draw.clip
|
||||||
import androidx.compose.ui.draw.shadow
|
|
||||||
import androidx.compose.ui.graphics.vector.ImageVector
|
import androidx.compose.ui.graphics.vector.ImageVector
|
||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
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.core.EventId
|
||||||
import io.element.android.libraries.matrix.api.timeline.Timeline
|
import io.element.android.libraries.matrix.api.timeline.Timeline
|
||||||
import io.element.android.libraries.matrix.api.user.MatrixUser
|
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.TestTags
|
||||||
import io.element.android.libraries.testtags.testTag
|
import io.element.android.libraries.testtags.testTag
|
||||||
import io.element.android.libraries.ui.strings.CommonStrings
|
import io.element.android.libraries.ui.strings.CommonStrings
|
||||||
@@ -418,6 +418,7 @@ private fun BoxScope.TimelineScrollHelper(
|
|||||||
hasUnread = true,
|
hasUnread = true,
|
||||||
onClick = ::jumpToReadMarker,
|
onClick = ::jumpToReadMarker,
|
||||||
onMarkAsRead = onMarkAllAsRead,
|
onMarkAsRead = onMarkAllAsRead,
|
||||||
|
testTag = TestTags.jumpToUnreadButton,
|
||||||
)
|
)
|
||||||
JumpToPositionButton(
|
JumpToPositionButton(
|
||||||
icon = CompoundIcons.ChevronDown(),
|
icon = CompoundIcons.ChevronDown(),
|
||||||
@@ -426,6 +427,7 @@ private fun BoxScope.TimelineScrollHelper(
|
|||||||
hasUnread = displayJumpToUnread && newEventState is NewEventState.FromOther,
|
hasUnread = displayJumpToUnread && newEventState is NewEventState.FromOther,
|
||||||
onClick = ::jumpToBottom,
|
onClick = ::jumpToBottom,
|
||||||
onMarkAsRead = onMarkAllAsRead,
|
onMarkAsRead = onMarkAllAsRead,
|
||||||
|
testTag = TestTags.jumpToBottomButton,
|
||||||
dotAlignment = Alignment.BottomCenter,
|
dotAlignment = Alignment.BottomCenter,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -439,6 +441,7 @@ private fun JumpToPositionButton(
|
|||||||
hasUnread: Boolean,
|
hasUnread: Boolean,
|
||||||
onClick: () -> Unit,
|
onClick: () -> Unit,
|
||||||
onMarkAsRead: () -> Unit,
|
onMarkAsRead: () -> Unit,
|
||||||
|
testTag: TestTag,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
dotAlignment: Alignment = Alignment.TopCenter,
|
dotAlignment: Alignment = Alignment.TopCenter,
|
||||||
) {
|
) {
|
||||||
@@ -453,15 +456,15 @@ private fun JumpToPositionButton(
|
|||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.size(36.dp)
|
.size(36.dp)
|
||||||
.shadow(elevation = 0.dp, shape = CircleShape)
|
|
||||||
.background(color = ElementTheme.colors.bgCanvasDefault, shape = CircleShape)
|
.background(color = ElementTheme.colors.bgCanvasDefault, shape = CircleShape)
|
||||||
.clip(CircleShape)
|
.clip(CircleShape)
|
||||||
.border(1.dp, ElementTheme.colors.borderDisabled, CircleShape)
|
.border(1.dp, ElementTheme.colors.borderDisabled, CircleShape)
|
||||||
.combinedClickable(
|
.combinedClickable(
|
||||||
onClick = onClick,
|
onClick = onClick,
|
||||||
onLongClick = { menuExpanded = true },
|
onLongClick = { menuExpanded = true },
|
||||||
|
onLongClickLabel = stringResource(CommonStrings.action_open_context_menu),
|
||||||
)
|
)
|
||||||
.testTag(TestTags.floatingActionButton),
|
.testTag(testTag),
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
) {
|
) {
|
||||||
Icon(
|
Icon(
|
||||||
@@ -476,6 +479,8 @@ private fun JumpToPositionButton(
|
|||||||
minWidth = 0.dp,
|
minWidth = 0.dp,
|
||||||
offset = DpOffset(x = -44.dp, y = 40.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(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.clickable {
|
.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 {
|
private suspend fun <T> ReceiveTurbine<T>.awaitFirstItem(): T {
|
||||||
return awaitItem()
|
return awaitItem()
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -35,7 +35,6 @@ fun DropdownMenuItem(
|
|||||||
leadingIcon: @Composable (() -> Unit)? = null,
|
leadingIcon: @Composable (() -> Unit)? = null,
|
||||||
trailingIcon: @Composable (() -> Unit)? = null,
|
trailingIcon: @Composable (() -> Unit)? = null,
|
||||||
enabled: Boolean = true,
|
enabled: Boolean = true,
|
||||||
contentPadding: PaddingValues = DropDownMenuItemDefaults.contentPadding,
|
|
||||||
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
interactionSource: MutableInteractionSource = remember { MutableInteractionSource() },
|
||||||
) {
|
) {
|
||||||
androidx.compose.material3.DropdownMenuItem(
|
androidx.compose.material3.DropdownMenuItem(
|
||||||
@@ -50,7 +49,7 @@ fun DropdownMenuItem(
|
|||||||
trailingIcon = trailingIcon,
|
trailingIcon = trailingIcon,
|
||||||
enabled = enabled,
|
enabled = enabled,
|
||||||
colors = DropDownMenuItemDefaults.colors(),
|
colors = DropDownMenuItemDefaults.colors(),
|
||||||
contentPadding = contentPadding,
|
contentPadding = DropDownMenuItemDefaults.contentPadding,
|
||||||
interactionSource = interactionSource
|
interactionSource = interactionSource
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,6 +98,12 @@ object TestTags {
|
|||||||
*/
|
*/
|
||||||
val floatingActionButton = TestTag("floating-action-button")
|
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.
|
* Timeline.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user