fix(live): returning from playback keeps the group you were in
Some checks failed
Build TV app / build (push) Failing after 3s
Some checks failed
Build TV app / build (push) Failing after 3s
The rail opens whatever gets focused, so when the player closed and focus landed on "Alle Sender", the view silently switched away from the group the viewer had been browsing. A restore flag now suppresses that auto-select until focus has been placed on the channel that was watched. Completes #13. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -12,8 +12,8 @@ android {
|
|||||||
applicationId = "dev.castarr.tv"
|
applicationId = "dev.castarr.tv"
|
||||||
minSdk = 26
|
minSdk = 26
|
||||||
targetSdk = 35
|
targetSdk = 35
|
||||||
versionCode = 23
|
versionCode = 24
|
||||||
versionName = "0.9.0"
|
versionName = "0.9.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Release signing from environment (see ~/.keys/castarr-release.env on the
|
// Release signing from environment (see ~/.keys/castarr-release.env on the
|
||||||
|
|||||||
@@ -51,6 +51,13 @@ class AppState(
|
|||||||
/** Channel to restore focus to when the list comes back (#13). */
|
/** Channel to restore focus to when the list comes back (#13). */
|
||||||
var lastWatched by mutableStateOf<Channel?>(null)
|
var lastWatched by mutableStateOf<Channel?>(null)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True while the list is being restored after playback. The group rail
|
||||||
|
* opens whatever gets focused, so without this the focus landing there
|
||||||
|
* would silently switch the view back to "Alle Sender".
|
||||||
|
*/
|
||||||
|
var restorePending by mutableStateOf(false)
|
||||||
|
|
||||||
private val reentryHandler = android.os.Handler(android.os.Looper.getMainLooper())
|
private val reentryHandler = android.os.Handler(android.os.Looper.getMainLooper())
|
||||||
private var lastStoppedUrl: String = ""
|
private var lastStoppedUrl: String = ""
|
||||||
private var lastStoppedAt: Long = 0L
|
private var lastStoppedAt: Long = 0L
|
||||||
@@ -190,6 +197,7 @@ class AppState(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun stopPlayback() {
|
fun stopPlayback() {
|
||||||
|
restorePending = lastWatched != null
|
||||||
reentryHandler.removeCallbacksAndMessages(null)
|
reentryHandler.removeCallbacksAndMessages(null)
|
||||||
lastStoppedUrl = currentChannel?.url.orEmpty()
|
lastStoppedUrl = currentChannel?.url.orEmpty()
|
||||||
lastStoppedAt = System.currentTimeMillis()
|
lastStoppedAt = System.currentTimeMillis()
|
||||||
|
|||||||
@@ -106,11 +106,12 @@ fun LiveScreen(state: AppState) {
|
|||||||
// A fresh group starts at the top; a return from playback does not.
|
// A fresh group starts at the top; a return from playback does not.
|
||||||
if (restoreIndex == null) listState.scrollToItem(0)
|
if (restoreIndex == null) listState.scrollToItem(0)
|
||||||
}
|
}
|
||||||
LaunchedEffect(restoreIndex, channels.size) {
|
LaunchedEffect(restoreIndex, channels.size, state.restorePending) {
|
||||||
if (restoreIndex != null && !restored) {
|
if (restoreIndex != null && (state.restorePending || !restored)) {
|
||||||
listState.scrollToItem(restoreIndex)
|
listState.scrollToItem(restoreIndex)
|
||||||
runCatching { restoreFocus.requestFocus() }
|
runCatching { restoreFocus.requestFocus() }
|
||||||
restored = true
|
restored = true
|
||||||
|
state.restorePending = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val intoList = if (channels.isEmpty()) Modifier
|
val intoList = if (channels.isEmpty()) Modifier
|
||||||
@@ -135,6 +136,7 @@ fun LiveScreen(state: AppState) {
|
|||||||
modifier = intoList.then(
|
modifier = intoList.then(
|
||||||
if (selected) Modifier.focusRequester(railFocus) else Modifier
|
if (selected) Modifier.focusRequester(railFocus) else Modifier
|
||||||
),
|
),
|
||||||
|
suppressAutoSelect = { state.restorePending },
|
||||||
) {
|
) {
|
||||||
state.favoritesOnly = false
|
state.favoritesOnly = false
|
||||||
state.groupFilter = null
|
state.groupFilter = null
|
||||||
@@ -149,6 +151,7 @@ fun LiveScreen(state: AppState) {
|
|||||||
modifier = intoList.then(
|
modifier = intoList.then(
|
||||||
if (state.favoritesOnly) Modifier.focusRequester(railFocus) else Modifier
|
if (state.favoritesOnly) Modifier.focusRequester(railFocus) else Modifier
|
||||||
),
|
),
|
||||||
|
suppressAutoSelect = { state.restorePending },
|
||||||
) {
|
) {
|
||||||
state.favoritesOnly = true
|
state.favoritesOnly = true
|
||||||
state.groupFilter = null
|
state.groupFilter = null
|
||||||
@@ -172,6 +175,7 @@ fun LiveScreen(state: AppState) {
|
|||||||
modifier = intoList.then(
|
modifier = intoList.then(
|
||||||
if (state.groupFilter == group) Modifier.focusRequester(railFocus) else Modifier
|
if (state.groupFilter == group) Modifier.focusRequester(railFocus) else Modifier
|
||||||
),
|
),
|
||||||
|
suppressAutoSelect = { state.restorePending },
|
||||||
) {
|
) {
|
||||||
state.favoritesOnly = false
|
state.favoritesOnly = false
|
||||||
state.groupFilter = group
|
state.groupFilter = group
|
||||||
@@ -237,6 +241,7 @@ private fun GroupItem(
|
|||||||
count: Int,
|
count: Int,
|
||||||
selected: Boolean,
|
selected: Boolean,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
suppressAutoSelect: () -> Boolean = { false },
|
||||||
onSelect: () -> Unit,
|
onSelect: () -> Unit,
|
||||||
) {
|
) {
|
||||||
Surface(
|
Surface(
|
||||||
@@ -245,7 +250,7 @@ private fun GroupItem(
|
|||||||
onClick = onSelect,
|
onClick = onSelect,
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onFocusChanged { if (it.isFocused) onSelect() },
|
.onFocusChanged { if (it.isFocused && !suppressAutoSelect()) onSelect() },
|
||||||
shape = ClickableSurfaceDefaults.shape(RoundedCornerShape(10.dp)),
|
shape = ClickableSurfaceDefaults.shape(RoundedCornerShape(10.dp)),
|
||||||
scale = ClickableSurfaceDefaults.scale(focusedScale = 1f),
|
scale = ClickableSurfaceDefaults.scale(focusedScale = 1f),
|
||||||
colors = ClickableSurfaceDefaults.colors(
|
colors = ClickableSurfaceDefaults.colors(
|
||||||
|
|||||||
Reference in New Issue
Block a user