EARHORNMUSIC UPnP · Android TV · Phones · Android Auto · GNU/Linux
Release 0.5.0

LastContentFocus.kt

Each line, with the release that last changed it.

0.5.01package dev.stave.ui.nav
2
3import androidx.compose.runtime.MutableState
4import androidx.compose.runtime.compositionLocalOf
5import androidx.compose.runtime.mutableStateOf
6import androidx.compose.ui.Modifier
7import androidx.compose.ui.focus.FocusRequester
8import androidx.compose.ui.focus.focusRequester
9import androidx.compose.ui.focus.onFocusChanged
10
11/**
12 * Holds the [FocusRequester] of the most recently focused content row so
13 * the Now Playing bar's Up gesture can restore focus to it — the user
14 * returns to exactly where they were, not wherever Compose's spatial
15 * resolver happens to pick.
16 *
17 * Screens that render content above the bar (Browse's list, Queue's
18 * list, etc.) write their row FRs here via [Modifier.trackLastContentFocus]
19 * on focus gain. The bar's `onUpFromBar` reads the current value and
20 * calls `requestFocus()` on it; when the row has been disposed (scrolled
21 * out of a LazyColumn) the call fails and the caller should fall back to
22 * [androidx.compose.ui.focus.FocusManager.moveFocus].
23 *
24 * Default value is a no-op sink so code that reads the Local without a
25 * provider (unlikely, but harmless) doesn't null-pointer.
26 */
27val LocalLastContentFocus =
28 compositionLocalOf<MutableState<FocusRequester?>> { mutableStateOf(null) }
29
30/**
31 * Register [requester] as the "last focused content" when the modified
32 * element gains focus. Pair with a real [Modifier.focusRequester] and a
33 * focusable modifier (e.g. staveFocusable + clickable).
34 */
35fun Modifier.trackLastContentFocus(
36 requester: FocusRequester,
37 sink: MutableState<FocusRequester?>,
38): Modifier = this
39 .focusRequester(requester)
40 .onFocusChanged { if (it.isFocused) sink.value = requester }