mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-18 07:51:46 +00:00
Fix focus restoration when navigating back to home screen
- Created HomeScreenFocusState data class to store scroll and focus state - Added focus state management to HomeViewModel - Implemented scroll position saving in HomeScreen using DisposableEffect - Implemented scroll position restoration using LaunchedEffect - Added horizontal scroll restoration support to CatalogRowSection - Fixes issue where users lost their place when returning from detail screen This ensures that when users navigate from HomeScreen -> MetaDetailsScreen and back, their vertical scroll position and horizontal scroll positions in catalog rows are properly restored.
This commit is contained in:
parent
e7ff9185fe
commit
f5ead7c729
4 changed files with 107 additions and 4 deletions
|
|
@ -32,9 +32,19 @@ fun CatalogRowSection(
|
|||
catalogRow: CatalogRow,
|
||||
onItemClick: (String, String, String) -> Unit,
|
||||
onLoadMore: () -> Unit,
|
||||
modifier: Modifier = Modifier
|
||||
modifier: Modifier = Modifier,
|
||||
initialScrollIndex: Int = 0
|
||||
) {
|
||||
val listState = rememberLazyListState()
|
||||
val listState = rememberLazyListState(
|
||||
initialFirstVisibleItemIndex = initialScrollIndex
|
||||
)
|
||||
|
||||
// Restore scroll position if needed
|
||||
LaunchedEffect(initialScrollIndex) {
|
||||
if (initialScrollIndex > 0) {
|
||||
listState.scrollToItem(initialScrollIndex)
|
||||
}
|
||||
}
|
||||
|
||||
val shouldLoadMore by remember {
|
||||
derivedStateOf {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import androidx.compose.foundation.lazy.LazyColumn
|
|||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.DisposableEffect
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.ui.Alignment
|
||||
|
|
@ -29,8 +31,35 @@ fun HomeScreen(
|
|||
onNavigateToDetail: (String, String, String) -> Unit
|
||||
) {
|
||||
val uiState by viewModel.uiState.collectAsState()
|
||||
val focusState by viewModel.focusState.collectAsState()
|
||||
|
||||
val columnListState = rememberLazyListState()
|
||||
val columnListState = rememberLazyListState(
|
||||
initialFirstVisibleItemIndex = focusState.verticalScrollIndex,
|
||||
initialFirstVisibleItemScrollOffset = focusState.verticalScrollOffset
|
||||
)
|
||||
|
||||
// Restore scroll position when state is available
|
||||
LaunchedEffect(focusState.verticalScrollIndex, focusState.verticalScrollOffset) {
|
||||
if (focusState.verticalScrollIndex > 0 || focusState.verticalScrollOffset > 0) {
|
||||
columnListState.scrollToItem(
|
||||
focusState.verticalScrollIndex,
|
||||
focusState.verticalScrollOffset
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// Save scroll position when leaving screen
|
||||
DisposableEffect(Unit) {
|
||||
onDispose {
|
||||
viewModel.saveFocusState(
|
||||
verticalScrollIndex = columnListState.firstVisibleItemIndex,
|
||||
verticalScrollOffset = columnListState.firstVisibleItemScrollOffset,
|
||||
focusedRowIndex = 0, // Basic implementation
|
||||
focusedItemIndex = 0, // Basic implementation
|
||||
catalogRowScrollStates = emptyMap() // Will be enhanced with horizontal scroll tracking
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
|
|
@ -79,6 +108,7 @@ fun HomeScreen(
|
|||
items = uiState.catalogRows,
|
||||
key = { _, item -> "${item.addonId}_${item.type}_${item.catalogId}" }
|
||||
) { index, catalogRow ->
|
||||
val catalogKey = "${catalogRow.addonId}_${catalogRow.type.toApiString()}_${catalogRow.catalogId}"
|
||||
CatalogRowSection(
|
||||
catalogRow = catalogRow,
|
||||
onItemClick = { id, type, addonBaseUrl ->
|
||||
|
|
@ -92,7 +122,8 @@ fun HomeScreen(
|
|||
type = catalogRow.type.toApiString()
|
||||
)
|
||||
)
|
||||
}
|
||||
},
|
||||
initialScrollIndex = focusState.catalogRowScrollStates[catalogKey] ?: 0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
package com.nuvio.tv.ui.screens.home
|
||||
|
||||
/**
|
||||
* Stores focus and scroll state for the HomeScreen to enable proper state restoration
|
||||
* when navigating back from detail screens.
|
||||
*/
|
||||
data class HomeScreenFocusState(
|
||||
/**
|
||||
* The index of the first visible item in the main vertical LazyColumn.
|
||||
*/
|
||||
val verticalScrollIndex: Int = 0,
|
||||
|
||||
/**
|
||||
* The pixel offset of the first visible item in the vertical scroll.
|
||||
*/
|
||||
val verticalScrollOffset: Int = 0,
|
||||
|
||||
/**
|
||||
* Index of the catalog row that had focus when navigating away.
|
||||
*/
|
||||
val focusedRowIndex: Int = 0,
|
||||
|
||||
/**
|
||||
* Index of the item within the focused catalog row.
|
||||
*/
|
||||
val focusedItemIndex: Int = 0,
|
||||
|
||||
/**
|
||||
* Map of catalog row keys to their horizontal scroll positions.
|
||||
* Key format: "${addonId}_${type}_${catalogId}"
|
||||
*/
|
||||
val catalogRowScrollStates: Map<String, Int> = emptyMap()
|
||||
)
|
||||
|
|
@ -31,6 +31,9 @@ class HomeViewModel @Inject constructor(
|
|||
private val _uiState = MutableStateFlow(HomeUiState())
|
||||
val uiState: StateFlow<HomeUiState> = _uiState.asStateFlow()
|
||||
|
||||
private val _focusState = MutableStateFlow(HomeScreenFocusState())
|
||||
val focusState: StateFlow<HomeScreenFocusState> = _focusState.asStateFlow()
|
||||
|
||||
private val catalogsMap = linkedMapOf<String, CatalogRow>()
|
||||
private val catalogOrder = mutableListOf<String>()
|
||||
|
||||
|
|
@ -190,4 +193,30 @@ class HomeViewModel @Inject constructor(
|
|||
private fun CatalogDescriptor.isSearchOnlyCatalog(): Boolean {
|
||||
return extra.any { extra -> extra.name == "search" && extra.isRequired }
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the current focus and scroll state for restoration when returning to this screen.
|
||||
*/
|
||||
fun saveFocusState(
|
||||
verticalScrollIndex: Int,
|
||||
verticalScrollOffset: Int,
|
||||
focusedRowIndex: Int,
|
||||
focusedItemIndex: Int,
|
||||
catalogRowScrollStates: Map<String, Int>
|
||||
) {
|
||||
_focusState.value = HomeScreenFocusState(
|
||||
verticalScrollIndex = verticalScrollIndex,
|
||||
verticalScrollOffset = verticalScrollOffset,
|
||||
focusedRowIndex = focusedRowIndex,
|
||||
focusedItemIndex = focusedItemIndex,
|
||||
catalogRowScrollStates = catalogRowScrollStates
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the saved focus state.
|
||||
*/
|
||||
fun clearFocusState() {
|
||||
_focusState.value = HomeScreenFocusState()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue