Rail click target fix + reorder mode via context menu
Sonar / Sonar Quality Checks (push) Has been cancelled
Code Quality Checks / Search for invalid screenshot files (push) Has been cancelled
Code Quality Checks / Search for invalid dependencies (push) Has been cancelled
Code Quality Checks / Konsist tests (push) Has been cancelled
Code Quality Checks / Compose tests (push) Has been cancelled
Code Quality Checks / Android lint check (push) Has been cancelled
Code Quality Checks / Detekt checks (push) Has been cancelled
Code Quality Checks / Run zizmor (push) Has been cancelled
Code Quality Checks / Search for forbidden patterns (push) Has been cancelled
Code Quality Checks / Ktlint checks (push) Has been cancelled
Code Quality Checks / Doc checks (push) Has been cancelled
Code Quality Checks / Check shell scripts (push) Has been cancelled
Code Quality Checks / Project Check Suite (push) Has been cancelled
Create release App Bundle and APKs / Create App Bundle (Gplay) (push) Has been cancelled
Create release App Bundle and APKs / Create App Bundle Enterprise (push) Has been cancelled
Create release App Bundle and APKs / Create APKs (FDroid) (push) Has been cancelled
Test / Runs unit tests (push) Has been cancelled
Post-release / post-release (push) Has been cancelled
Sonar / Sonar Quality Checks (push) Has been cancelled
Code Quality Checks / Search for invalid screenshot files (push) Has been cancelled
Code Quality Checks / Search for invalid dependencies (push) Has been cancelled
Code Quality Checks / Konsist tests (push) Has been cancelled
Code Quality Checks / Compose tests (push) Has been cancelled
Code Quality Checks / Android lint check (push) Has been cancelled
Code Quality Checks / Detekt checks (push) Has been cancelled
Code Quality Checks / Run zizmor (push) Has been cancelled
Code Quality Checks / Search for forbidden patterns (push) Has been cancelled
Code Quality Checks / Ktlint checks (push) Has been cancelled
Code Quality Checks / Doc checks (push) Has been cancelled
Code Quality Checks / Check shell scripts (push) Has been cancelled
Code Quality Checks / Project Check Suite (push) Has been cancelled
Create release App Bundle and APKs / Create App Bundle (Gplay) (push) Has been cancelled
Create release App Bundle and APKs / Create App Bundle Enterprise (push) Has been cancelled
Create release App Bundle and APKs / Create APKs (FDroid) (push) Has been cancelled
Test / Runs unit tests (push) Has been cancelled
Post-release / post-release (push) Has been cancelled
- The rail's new name labels were dead zones (click lived only on the avatar),
which shifted and broke taps across the whole rail — the entire item
(avatar + label) is one click target now
- Drag-to-arrange is an explicit mode entered from the room long-press menu
("Reorder rooms"): whole rows drag, a banner with Done exits. The previous
avatar long-press handle fired the context menu at the same time
This commit is contained in:
+5
-4
@@ -105,13 +105,16 @@ private fun RailItem(
|
||||
onClick: () -> Unit,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
// The whole item (avatar + label) is one click target — a click only on the
|
||||
// avatar left the label a dead zone and made the rail feel broken.
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = onClick)
|
||||
.padding(vertical = 4.dp),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
RailItemAvatar(isSelected = isSelected, onClick = onClick, content = content)
|
||||
RailItemAvatar(isSelected = isSelected, content = content)
|
||||
Text(
|
||||
text = label,
|
||||
style = ElementTheme.typography.fontBodyXsRegular,
|
||||
@@ -129,7 +132,6 @@ private fun RailItem(
|
||||
@Composable
|
||||
private fun RailItemAvatar(
|
||||
isSelected: Boolean,
|
||||
onClick: () -> Unit,
|
||||
content: @Composable () -> Unit,
|
||||
) {
|
||||
Box(
|
||||
@@ -166,8 +168,7 @@ private fun RailItemAvatar(
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
)
|
||||
.clickable(onClick = onClick),
|
||||
),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
content()
|
||||
|
||||
+31
-6
@@ -15,8 +15,10 @@ import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.ColumnScope
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
@@ -57,6 +59,7 @@ import io.element.android.libraries.designsystem.theme.components.Button
|
||||
import io.element.android.libraries.designsystem.theme.components.HorizontalDivider
|
||||
import io.element.android.libraries.designsystem.theme.components.IconSource
|
||||
import io.element.android.libraries.designsystem.theme.components.Text
|
||||
import io.element.android.libraries.designsystem.theme.components.TextButton
|
||||
import io.element.android.libraries.designsystem.utils.OnVisibleRangeChangeEffect
|
||||
import io.element.android.libraries.ui.strings.CommonStrings
|
||||
import kotlinx.collections.immutable.ImmutableList
|
||||
@@ -297,6 +300,29 @@ private fun RoomsViewList(
|
||||
}
|
||||
}
|
||||
|
||||
// Blap: drag-to-arrange banner while reorder mode is active.
|
||||
if (state.blapReorderMode) {
|
||||
item(key = "blap_reorder_banner", contentType = "blap_reorder_banner") {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(ElementTheme.colors.bgSubtleSecondary)
|
||||
.padding(start = 16.dp, end = 8.dp),
|
||||
) {
|
||||
Text(
|
||||
text = "Drag rooms to arrange",
|
||||
style = ElementTheme.typography.fontBodyMdMedium,
|
||||
color = ElementTheme.colors.textPrimary,
|
||||
modifier = Modifier.weight(1f),
|
||||
)
|
||||
TextButton(
|
||||
text = stringResource(CommonStrings.action_done),
|
||||
onClick = { eventSink(RoomListEvent.BlapSetReorderMode(false)) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Note: do not use a key for the LazyColumn, or the scroll will not behave as expected if a room
|
||||
// is moved to the top of the list.
|
||||
itemsIndexed(
|
||||
@@ -331,11 +357,11 @@ private fun RoomsViewList(
|
||||
) { index, room ->
|
||||
ReorderableItem(blapReorderableState, key = room.roomId.value) { isDragging ->
|
||||
Column(
|
||||
modifier = if (isDragging) {
|
||||
Modifier.background(ElementTheme.colors.bgSubtleSecondary)
|
||||
} else {
|
||||
Modifier
|
||||
},
|
||||
// In reorder mode the whole row is the drag handle (long-press
|
||||
// drag conflicted with the row's context menu).
|
||||
modifier = Modifier
|
||||
.then(if (state.blapReorderMode) Modifier.draggableHandle() else Modifier)
|
||||
.then(if (isDragging) Modifier.background(ElementTheme.colors.bgSubtleSecondary) else Modifier),
|
||||
) {
|
||||
RoomSummaryRow(
|
||||
room = room,
|
||||
@@ -343,7 +369,6 @@ private fun RoomsViewList(
|
||||
isInviteSeen = false,
|
||||
showUnreadCount = state.showUnreadCount,
|
||||
onClick = onRoomClick,
|
||||
blapAvatarModifier = Modifier.longPressDraggableHandle(),
|
||||
eventSink = eventSink,
|
||||
)
|
||||
// Any room with an active call shows who's in it — not just classified
|
||||
|
||||
+19
@@ -62,6 +62,10 @@ fun RoomListContextMenu(
|
||||
eventSink(RoomListEvent.HideContextMenu)
|
||||
onRoomSettingsClick(contextMenu.roomId)
|
||||
},
|
||||
onBlapReorderClick = {
|
||||
eventSink(RoomListEvent.HideContextMenu)
|
||||
eventSink(RoomListEvent.BlapSetReorderMode(true))
|
||||
},
|
||||
onLeaveRoomClick = {
|
||||
eventSink(RoomListEvent.HideContextMenu)
|
||||
eventSink(RoomListEvent.LeaveRoom(contextMenu.roomId, needsConfirmation = true))
|
||||
@@ -82,6 +86,7 @@ private fun RoomListModalBottomSheetContent(
|
||||
contextMenu: RoomListState.ContextMenu.Shown,
|
||||
canReportRoom: Boolean,
|
||||
onRoomSettingsClick: () -> Unit,
|
||||
onBlapReorderClick: () -> Unit,
|
||||
onLeaveRoomClick: () -> Unit,
|
||||
onFavoriteChange: (isFavorite: Boolean) -> Unit,
|
||||
onRoomMarkReadClick: () -> Unit,
|
||||
@@ -129,6 +134,20 @@ private fun RoomListModalBottomSheetContent(
|
||||
),
|
||||
)
|
||||
}
|
||||
// Blap: drag-to-arrange mode — long-press drag conflicted with this very menu,
|
||||
// so reordering is an explicit mode instead.
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Text(
|
||||
text = "Reorder rooms",
|
||||
style = MaterialTheme.typography.bodyLarge,
|
||||
)
|
||||
},
|
||||
onClick = onBlapReorderClick,
|
||||
leadingContent = ListItemContent.Icon(
|
||||
iconSource = IconSource.Vector(CompoundIcons.DragList())
|
||||
),
|
||||
)
|
||||
val (textResId, icon) = if (contextMenu.isFavorite) {
|
||||
CommonStrings.common_favourited to CompoundIcons.FavouriteSolid()
|
||||
} else {
|
||||
|
||||
+3
@@ -31,6 +31,9 @@ sealed interface RoomListEvent {
|
||||
data class BlapSetRoomOrder(val order: List<RoomId>) : RoomListEvent
|
||||
|
||||
sealed interface ContextMenuEvent : RoomListEvent
|
||||
|
||||
// Blap: enter/exit drag-to-arrange mode (entered from the room context menu)
|
||||
data class BlapSetReorderMode(val enabled: Boolean) : ContextMenuEvent
|
||||
data object HideContextMenu : ContextMenuEvent
|
||||
data class LeaveRoom(val roomId: RoomId, val needsConfirmation: Boolean) : ContextMenuEvent
|
||||
data class MarkAsRead(val roomId: RoomId) : ContextMenuEvent
|
||||
|
||||
+8
@@ -159,6 +159,8 @@ class RoomListPresenter(
|
||||
?.split(",")?.filter { it.isNotBlank() }?.map { RoomId(it) }.orEmpty()
|
||||
)
|
||||
}
|
||||
// Blap: drag-to-arrange mode, entered from the room context menu.
|
||||
var blapReorderMode by remember { mutableStateOf(false) }
|
||||
// Blap: resolve profiles (display name + avatar) for users in active calls.
|
||||
var blapCallUsers by remember { mutableStateOf(emptyMap<UserId, MatrixUser>()) }
|
||||
val blapProfileAttempts = remember { mutableSetOf<UserId>() }
|
||||
@@ -237,6 +239,9 @@ class RoomListPresenter(
|
||||
putString(blapOrderKey(selectedSpaceId), event.order.joinToString(",") { it.value })
|
||||
}
|
||||
}
|
||||
is RoomListEvent.BlapSetReorderMode -> {
|
||||
blapReorderMode = event.enabled
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,6 +269,7 @@ class RoomListPresenter(
|
||||
blapCollapsedSections,
|
||||
blapManualOrder,
|
||||
blapCallUsers,
|
||||
blapReorderMode,
|
||||
)
|
||||
|
||||
return RoomListState(
|
||||
@@ -333,6 +339,7 @@ class RoomListPresenter(
|
||||
blapCollapsedSections: Set<String>,
|
||||
blapManualOrder: List<RoomId>,
|
||||
blapCallUsers: Map<UserId, MatrixUser>,
|
||||
blapReorderMode: Boolean,
|
||||
): RoomListContentState {
|
||||
val roomSummaries by produceState(initialValue = AsyncData.Loading()) {
|
||||
roomListDataSource.roomSummariesFlow.collect { value = AsyncData.Success(it) }
|
||||
@@ -370,6 +377,7 @@ class RoomListPresenter(
|
||||
blapCollapsedSections = blapCollapsedSections.toImmutableSet(),
|
||||
blapManualOrder = blapManualOrder.toImmutableList(),
|
||||
blapCallUsers = blapCallUsers.toImmutableMap(),
|
||||
blapReorderMode = blapReorderMode,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -86,5 +86,7 @@ sealed interface RoomListContentState {
|
||||
// profiles for users in active calls
|
||||
val blapManualOrder: ImmutableList<RoomId> = persistentListOf(),
|
||||
val blapCallUsers: ImmutableMap<UserId, MatrixUser> = persistentMapOf(),
|
||||
// Blap: drag-to-arrange mode (whole rows become drag handles, Done exits)
|
||||
val blapReorderMode: Boolean = false,
|
||||
) : RoomListContentState
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user