diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/ShelfComponents.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/ShelfComponents.kt index df5f05de6..d9554540a 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/ShelfComponents.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/core/ui/ShelfComponents.kt @@ -17,7 +17,9 @@ import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.lazy.LazyRow +import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.items +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.rounded.KeyboardArrowRight @@ -70,6 +72,7 @@ fun NuvioShelfSection( viewAllPillSize: NuvioViewAllPillSize = NuvioViewAllPillSize.Default, key: ((T) -> Any)? = null, animatePlacement: Boolean = false, + state: LazyListState = rememberLazyListState(), itemContent: @Composable (T) -> Unit, ) { val tokens = MaterialTheme.nuvio @@ -87,6 +90,7 @@ fun NuvioShelfSection( ) } LazyRow( + state = state, contentPadding = rowContentPadding, horizontalArrangement = Arrangement.spacedBy(itemSpacing), ) { diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeScreen.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeScreen.kt index 1d2d048f1..bd0ee9f0c 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/HomeScreen.kt @@ -9,6 +9,7 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.snapshotFlow import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp @@ -127,6 +128,7 @@ fun HomeScreen( HomeCatalogSettingsRepository.uiState }.collectAsStateWithLifecycle() val homeListState = rememberLazyListState() + val continueWatchingListState = rememberLazyListState() val collections by CollectionRepository.collections.collectAsStateWithLifecycle() val continueWatchingPreferences by ContinueWatchingPreferencesRepository.uiState.collectAsStateWithLifecycle() val watchedUiState by WatchedRepository.uiState.collectAsStateWithLifecycle() @@ -280,6 +282,13 @@ fun HomeScreen( val profileState by ProfileRepository.state.collectAsStateWithLifecycle() val activeProfileId = profileState.activeProfile?.profileIndex ?: 1 val cwCacheGeneration by ContinueWatchingEnrichmentCache.generation.collectAsStateWithLifecycle() + var hasUserScrolledContinueWatching by remember(activeProfileId) { mutableStateOf(false) } + + LaunchedEffect(activeProfileId, continueWatchingListState) { + snapshotFlow { continueWatchingListState.isScrollInProgress }.collect { isScrolling -> + if (isScrolling) hasUserScrolledContinueWatching = true + } + } var nextUpItemsBySeries by remember(activeProfileId, effectiveWatchProgressSource) { mutableStateOf>>(emptyMap()) @@ -427,6 +436,22 @@ fun HomeScreen( cloudLibraryUiState = cloudLibraryUiState, ) } + LaunchedEffect(activeProfileId, continueWatchingItems.isNotEmpty(), hasUserScrolledContinueWatching) { + if (!hasUserScrolledContinueWatching && continueWatchingItems.isNotEmpty()) { + snapshotFlow { + continueWatchingListState.firstVisibleItemIndex to + continueWatchingListState.firstVisibleItemScrollOffset + }.collect { (index, offset) -> + if ( + !hasUserScrolledContinueWatching && + !continueWatchingListState.isScrollInProgress && + (index != 0 || offset != 0) + ) { + continueWatchingListState.scrollToItem(0) + } + } + } + } val enabledAddons = remember(addonsUiState.addons) { addonsUiState.addons.enabledAddons() } @@ -853,6 +878,7 @@ fun HomeScreen( modifier = Modifier.padding(bottom = HomeContinueWatchingSectionBottomPadding), sectionPadding = homeSectionPadding, layout = continueWatchingLayout, + listState = continueWatchingListState, onItemClick = onContinueWatchingClick, onItemLongPress = onContinueWatchingLongPress, ) @@ -878,6 +904,7 @@ fun HomeScreen( modifier = Modifier.padding(bottom = HomeContinueWatchingSectionBottomPadding), sectionPadding = homeSectionPadding, layout = continueWatchingLayout, + listState = continueWatchingListState, onItemClick = onContinueWatchingClick, onItemLongPress = onContinueWatchingLongPress, ) @@ -926,6 +953,7 @@ fun HomeScreen( modifier = Modifier.padding(bottom = HomeContinueWatchingSectionBottomPadding), sectionPadding = homeSectionPadding, layout = continueWatchingLayout, + listState = continueWatchingListState, onItemClick = onContinueWatchingClick, onItemLongPress = onContinueWatchingLongPress, ) diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeContinueWatchingSection.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeContinueWatchingSection.kt index a906d0033..2ad956799 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeContinueWatchingSection.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeContinueWatchingSection.kt @@ -19,6 +19,8 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme @@ -235,6 +237,7 @@ internal fun HomeContinueWatchingSection( modifier: Modifier = Modifier, sectionPadding: Dp? = null, layout: ContinueWatchingLayout? = null, + listState: LazyListState = rememberLazyListState(), onItemClick: ((ContinueWatchingItem) -> Unit)? = null, onItemLongPress: ((ContinueWatchingItem) -> Unit)? = null, ) { @@ -249,6 +252,7 @@ internal fun HomeContinueWatchingSection( modifier = modifier.fillMaxWidth(), sectionPadding = sectionPadding, layout = layout, + listState = listState, onItemClick = onItemClick, onItemLongPress = onItemLongPress, ) @@ -262,6 +266,7 @@ internal fun HomeContinueWatchingSection( modifier = Modifier.fillMaxWidth(), sectionPadding = homeSectionHorizontalPaddingForWidth(maxWidth.value), layout = rememberContinueWatchingLayout(maxWidth.value), + listState = listState, onItemClick = onItemClick, onItemLongPress = onItemLongPress, ) @@ -278,6 +283,7 @@ private fun HomeContinueWatchingSectionContent( modifier: Modifier, sectionPadding: Dp, layout: ContinueWatchingLayout, + listState: LazyListState, onItemClick: ((ContinueWatchingItem) -> Unit)?, onItemLongPress: ((ContinueWatchingItem) -> Unit)?, ) { @@ -299,6 +305,7 @@ private fun HomeContinueWatchingSectionContent( showHeaderAccent = !homeCatalogSettings.hideCatalogUnderline, key = { entry -> entry.videoId }, animatePlacement = true, + state = listState, ) { entry -> val item = entry.item val onClick = if (entry.exiting) null else onItemClick?.let { { it(item) } }