LastContentFocus.kt
40 lines · 1.7 KB
Changed in: 0.5.0
| 1 | package dev.stave.ui.nav |
| 2 | |
| 3 | import androidx.compose.runtime.MutableState |
| 4 | import androidx.compose.runtime.compositionLocalOf |
| 5 | import androidx.compose.runtime.mutableStateOf |
| 6 | import androidx.compose.ui.Modifier |
| 7 | import androidx.compose.ui.focus.FocusRequester |
| 8 | import androidx.compose.ui.focus.focusRequester |
| 9 | import 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 | */ |
| 27 | val 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 | */ |
| 35 | fun Modifier.trackLastContentFocus( |
| 36 | requester: FocusRequester, |
| 37 | sink: MutableState<FocusRequester?>, |
| 38 | ): Modifier = this |
| 39 | .focusRequester(requester) |
| 40 | .onFocusChanged { if (it.isFocused) sink.value = requester } |


