package dev.stave.ui.nav
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.focus.onFocusChanged
/**
* Holds the [FocusRequester] of the most recently focused content row so
* the Now Playing bar's Up gesture can restore focus to it — the user
* returns to exactly where they were, not wherever Compose's spatial
* resolver happens to pick.
*
* Screens that render content above the bar (Browse's list, Queue's
* list, etc.) write their row FRs here via [Modifier.trackLastContentFocus]
* on focus gain. The bar's `onUpFromBar` reads the current value and
* calls `requestFocus()` on it; when the row has been disposed (scrolled
* out of a LazyColumn) the call fails and the caller should fall back to
* [androidx.compose.ui.focus.FocusManager.moveFocus].
*
* Default value is a no-op sink so code that reads the Local without a
* provider (unlikely, but harmless) doesn't null-pointer.
*/
val LocalLastContentFocus =
compositionLocalOf<MutableState<FocusRequester?>> { mutableStateOf(null) }
/**
* Register [requester] as the "last focused content" when the modified
* element gains focus. Pair with a real [Modifier.focusRequester] and a
* focusable modifier (e.g. staveFocusable + clickable).
*/
fun Modifier.trackLastContentFocus(
requester: FocusRequester,
sink: MutableState<FocusRequester?>,
): Modifier = this
.focusRequester(requester)
.onFocusChanged { if (it.isFocused) sink.value = requester }