ui: Explicit UP from first content row to the top bar
Focus search silently failed to move from the first content card up to the top bar (why the menu felt unreachable); the first row's cards now have a wired UP target (the search button) in rows and grids.
This commit is contained in:
parent
828bfdafa9
commit
d469101eb0
5 changed files with 26 additions and 6 deletions
|
|
@ -153,6 +153,7 @@ fun HomeRowsScreen(
|
||||||
restoreToken: Int = 0,
|
restoreToken: Int = 0,
|
||||||
epoch: Int = 0,
|
epoch: Int = 0,
|
||||||
onOpenDrawer: () -> Unit = {},
|
onOpenDrawer: () -> Unit = {},
|
||||||
|
upToTopBar: (() -> Unit)? = null,
|
||||||
viewModel: HomeRowsViewModel = viewModel(key = "home$epoch", factory = HomeRowsViewModel.factory),
|
viewModel: HomeRowsViewModel = viewModel(key = "home$epoch", factory = HomeRowsViewModel.factory),
|
||||||
) {
|
) {
|
||||||
val continueRestore = androidx.compose.runtime.remember { androidx.compose.runtime.mutableIntStateOf(-1) }
|
val continueRestore = androidx.compose.runtime.remember { androidx.compose.runtime.mutableIntStateOf(-1) }
|
||||||
|
|
@ -188,6 +189,7 @@ fun HomeRowsScreen(
|
||||||
onLeftAtStart = onOpenDrawer,
|
onLeftAtStart = onOpenDrawer,
|
||||||
clickedIndex = continueRestore,
|
clickedIndex = continueRestore,
|
||||||
restoreToken = restoreToken,
|
restoreToken = restoreToken,
|
||||||
|
upToTopBar = upToTopBar,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -257,6 +259,7 @@ fun FocusScrollRow(
|
||||||
onLeftAtStart: () -> Unit,
|
onLeftAtStart: () -> Unit,
|
||||||
clickedIndex: androidx.compose.runtime.MutableIntState? = null, // set on card click
|
clickedIndex: androidx.compose.runtime.MutableIntState? = null, // set on card click
|
||||||
restoreToken: Int = 0, // bumped when playback ends
|
restoreToken: Int = 0, // bumped when playback ends
|
||||||
|
upToTopBar: (() -> Unit)? = null, // first content row only
|
||||||
afterItem: @Composable (index: Int, video: VideoDto) -> Unit = { _, _ -> },
|
afterItem: @Composable (index: Int, video: VideoDto) -> Unit = { _, _ -> },
|
||||||
) {
|
) {
|
||||||
val rowState = rememberLazyListState()
|
val rowState = rememberLazyListState()
|
||||||
|
|
@ -315,6 +318,7 @@ fun FocusScrollRow(
|
||||||
compact = true,
|
compact = true,
|
||||||
progress = progressOf(video.shortUUID),
|
progress = progressOf(video.shortUUID),
|
||||||
onLeftAtStart = if (index == 0) onLeftAtStart else null,
|
onLeftAtStart = if (index == 0) onLeftAtStart else null,
|
||||||
|
onUpToTopBar = upToTopBar,
|
||||||
onFocused = { focusedIndex = index },
|
onFocused = { focusedIndex = index },
|
||||||
)
|
)
|
||||||
afterItem(index, video)
|
afterItem(index, video)
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,7 @@ fun HomeScreen(viewModel: AppViewModel = androidx.lifecycle.viewmodel.compose.vi
|
||||||
restoreToken = restoreToken,
|
restoreToken = restoreToken,
|
||||||
epoch = epoch,
|
epoch = epoch,
|
||||||
onOpenDrawer = { drawerOpen = true },
|
onOpenDrawer = { drawerOpen = true },
|
||||||
|
upToTopBar = { runCatching { searchFocus.requestFocus() } },
|
||||||
)
|
)
|
||||||
Destination.MyVideos ->
|
Destination.MyVideos ->
|
||||||
VideoListScreen(
|
VideoListScreen(
|
||||||
|
|
@ -162,6 +163,7 @@ fun HomeScreen(viewModel: AppViewModel = androidx.lifecycle.viewmodel.compose.vi
|
||||||
restoreToken = restoreToken,
|
restoreToken = restoreToken,
|
||||||
epoch = epoch,
|
epoch = epoch,
|
||||||
onOpenDrawer = { drawerOpen = true },
|
onOpenDrawer = { drawerOpen = true },
|
||||||
|
upToTopBar = { runCatching { searchFocus.requestFocus() } },
|
||||||
)
|
)
|
||||||
Destination.Channels -> ChannelsScreen(
|
Destination.Channels -> ChannelsScreen(
|
||||||
onOpenChannel = { handle -> channelDetails = handle },
|
onOpenChannel = { handle -> channelDetails = handle },
|
||||||
|
|
@ -175,6 +177,7 @@ fun HomeScreen(viewModel: AppViewModel = androidx.lifecycle.viewmodel.compose.vi
|
||||||
restoreToken = restoreToken,
|
restoreToken = restoreToken,
|
||||||
epoch = epoch,
|
epoch = epoch,
|
||||||
onOpenDrawer = { drawerOpen = true },
|
onOpenDrawer = { drawerOpen = true },
|
||||||
|
upToTopBar = { runCatching { searchFocus.requestFocus() } },
|
||||||
)
|
)
|
||||||
Destination.Subscriptions ->
|
Destination.Subscriptions ->
|
||||||
SubscriptionRowsScreen(
|
SubscriptionRowsScreen(
|
||||||
|
|
@ -182,6 +185,7 @@ fun HomeScreen(viewModel: AppViewModel = androidx.lifecycle.viewmodel.compose.vi
|
||||||
restoreToken = restoreToken,
|
restoreToken = restoreToken,
|
||||||
epoch = epoch,
|
epoch = epoch,
|
||||||
onOpenDrawer = { drawerOpen = true },
|
onOpenDrawer = { drawerOpen = true },
|
||||||
|
upToTopBar = { runCatching { searchFocus.requestFocus() } },
|
||||||
)
|
)
|
||||||
Destination.History ->
|
Destination.History ->
|
||||||
VideoListScreen(
|
VideoListScreen(
|
||||||
|
|
@ -190,6 +194,7 @@ fun HomeScreen(viewModel: AppViewModel = androidx.lifecycle.viewmodel.compose.vi
|
||||||
restoreToken = restoreToken,
|
restoreToken = restoreToken,
|
||||||
epoch = epoch,
|
epoch = epoch,
|
||||||
onOpenDrawer = { drawerOpen = true },
|
onOpenDrawer = { drawerOpen = true },
|
||||||
|
upToTopBar = { runCatching { searchFocus.requestFocus() } },
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,7 @@ fun SubscriptionRowsScreen(
|
||||||
restoreToken: Int = 0,
|
restoreToken: Int = 0,
|
||||||
epoch: Int = 0,
|
epoch: Int = 0,
|
||||||
onOpenDrawer: () -> Unit = {},
|
onOpenDrawer: () -> Unit = {},
|
||||||
|
upToTopBar: (() -> Unit)? = null,
|
||||||
viewModel: SubscriptionRowsViewModel = viewModel(
|
viewModel: SubscriptionRowsViewModel = viewModel(
|
||||||
key = "subsrows$epoch",
|
key = "subsrows$epoch",
|
||||||
factory = object : ViewModelProvider.Factory {
|
factory = object : ViewModelProvider.Factory {
|
||||||
|
|
@ -157,6 +158,7 @@ fun SubscriptionRowsScreen(
|
||||||
progressOf = { null },
|
progressOf = { null },
|
||||||
onOpenVideo = onOpenVideo,
|
onOpenVideo = onOpenVideo,
|
||||||
onLeftAtStart = onOpenDrawer,
|
onLeftAtStart = onOpenDrawer,
|
||||||
|
upToTopBar = upToTopBar.takeIf { group == groups.firstOrNull() },
|
||||||
) { rowIndex, _ ->
|
) { rowIndex, _ ->
|
||||||
if (group.startIndex + rowIndex >= items.size - PagedListViewModel.LOOKAHEAD) {
|
if (group.startIndex + rowIndex >= items.size - PagedListViewModel.LOOKAHEAD) {
|
||||||
viewModel.loadMore()
|
viewModel.loadMore()
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,8 @@ fun VideoCard(
|
||||||
compact: Boolean = false,
|
compact: Boolean = false,
|
||||||
/** LEFT (only on the row's first card) can open the menu drawer. */
|
/** LEFT (only on the row's first card) can open the menu drawer. */
|
||||||
onLeftAtStart: (() -> Unit)? = null,
|
onLeftAtStart: (() -> Unit)? = null,
|
||||||
|
/** Explicit UP-target for the first content row (focus search misses the top bar). */
|
||||||
|
onUpToTopBar: (() -> Unit)? = null,
|
||||||
/** Notifies the row wrapper when this card gains focus (for eased scrolling). */
|
/** Notifies the row wrapper when this card gains focus (for eased scrolling). */
|
||||||
onFocused: (() -> Unit)? = null,
|
onFocused: (() -> Unit)? = null,
|
||||||
) {
|
) {
|
||||||
|
|
@ -72,12 +74,17 @@ fun VideoCard(
|
||||||
if (it.isFocused) onFocused?.invoke()
|
if (it.isFocused) onFocused?.invoke()
|
||||||
}
|
}
|
||||||
.onPreviewKeyEvent { ke ->
|
.onPreviewKeyEvent { ke ->
|
||||||
if (ke.type == androidx.compose.ui.input.key.KeyEventType.KeyDown &&
|
val direction = ke.key
|
||||||
ke.key == androidx.compose.ui.input.key.Key.DirectionLeft &&
|
if (ke.type == androidx.compose.ui.input.key.KeyEventType.KeyDown) {
|
||||||
onLeftAtStart != null
|
when {
|
||||||
) {
|
direction == androidx.compose.ui.input.key.Key.DirectionLeft && onLeftAtStart != null -> {
|
||||||
onLeftAtStart()
|
onLeftAtStart(); true
|
||||||
true
|
}
|
||||||
|
direction == androidx.compose.ui.input.key.Key.DirectionUp && onUpToTopBar != null -> {
|
||||||
|
onUpToTopBar(); true
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
} else false
|
} else false
|
||||||
},
|
},
|
||||||
colors = CardDefaults.colors(
|
colors = CardDefaults.colors(
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ fun VideoListScreen(
|
||||||
restoreToken: Int = 0,
|
restoreToken: Int = 0,
|
||||||
epoch: Int = 0,
|
epoch: Int = 0,
|
||||||
onOpenDrawer: () -> Unit = {},
|
onOpenDrawer: () -> Unit = {},
|
||||||
|
upToTopBar: (() -> Unit)? = null,
|
||||||
viewModel: VideoListViewModel = viewModel(
|
viewModel: VideoListViewModel = viewModel(
|
||||||
key = "v$epoch:" + sourceKey(source),
|
key = "v$epoch:" + sourceKey(source),
|
||||||
factory = VideoListViewModel.factory(source),
|
factory = VideoListViewModel.factory(source),
|
||||||
|
|
@ -140,6 +141,7 @@ fun VideoListScreen(
|
||||||
showPrivacy = source is ListSource.MyVideos,
|
showPrivacy = source is ListSource.MyVideos,
|
||||||
compact = true,
|
compact = true,
|
||||||
onLeftAtStart = if (index == 0) onOpenDrawer else null,
|
onLeftAtStart = if (index == 0) onOpenDrawer else null,
|
||||||
|
onUpToTopBar = upToTopBar?.takeIf { index < 4 },
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.focusRequester(fr),
|
.focusRequester(fr),
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue