diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeCatalogSection.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeCatalogSection.kt index 937a33fd..5d25e1c4 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeCatalogSection.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeCatalogSection.kt @@ -1,8 +1,10 @@ package com.nuvio.app.features.home.components +import androidx.compose.foundation.layout.BoxWithConstraints +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp import com.nuvio.app.core.ui.NuvioShelfSection import com.nuvio.app.core.ui.NuvioViewAllPillSize import com.nuvio.app.features.home.HomeCatalogSection @@ -20,24 +22,27 @@ fun HomeCatalogRowSection( onPosterClick: ((MetaPreview) -> Unit)? = null, onPosterLongClick: ((MetaPreview) -> Unit)? = null, ) { - NuvioShelfSection( - title = section.title, - entries = entries, - modifier = modifier, - headerHorizontalPadding = 16.dp, - rowContentPadding = androidx.compose.foundation.layout.PaddingValues(horizontal = 16.dp), - onViewAllClick = onViewAllClick, - viewAllPillSize = NuvioViewAllPillSize.Compact, - key = { item -> item.stableKey() }, - ) { item -> - HomePosterCard( - item = item, - isWatched = WatchingState.isPosterWatched( - watchedKeys = watchedKeys, + BoxWithConstraints(modifier = modifier.fillMaxWidth()) { + val sectionPadding = homeSectionHorizontalPaddingForWidth(maxWidth.value) + NuvioShelfSection( + title = section.title, + entries = entries, + modifier = Modifier.fillMaxWidth(), + headerHorizontalPadding = sectionPadding, + rowContentPadding = PaddingValues(horizontal = sectionPadding), + onViewAllClick = onViewAllClick, + viewAllPillSize = NuvioViewAllPillSize.Compact, + key = { item -> item.stableKey() }, + ) { item -> + HomePosterCard( item = item, - ), - onClick = onPosterClick?.let { { it(item) } }, - onLongClick = onPosterLongClick?.let { { it(item) } }, - ) + isWatched = WatchingState.isPosterWatched( + watchedKeys = watchedKeys, + item = item, + ), + onClick = onPosterClick?.let { { it(item) } }, + onLongClick = onPosterLongClick?.let { { it(item) } }, + ) + } } } 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 209f7d64..e22d0922 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 @@ -56,12 +56,13 @@ fun HomeContinueWatchingSection( BoxWithConstraints(modifier = modifier.fillMaxWidth()) { val layout = rememberContinueWatchingLayout(maxWidth.value) + val sectionPadding = homeSectionHorizontalPaddingForWidth(maxWidth.value) NuvioShelfSection( title = "Continue Watching", entries = items, modifier = Modifier.fillMaxWidth(), - headerHorizontalPadding = layout.sectionPadding, - rowContentPadding = PaddingValues(horizontal = layout.sectionPadding), + headerHorizontalPadding = sectionPadding, + rowContentPadding = PaddingValues(horizontal = sectionPadding), itemSpacing = layout.itemGap, key = { item -> item.videoId }, ) { item -> @@ -460,7 +461,6 @@ private fun UpNextBadge( } private data class ContinueWatchingLayout( - val sectionPadding: Dp, val itemGap: Dp, val wideCardWidth: Dp, val wideCardHeight: Dp, @@ -482,7 +482,6 @@ private data class ContinueWatchingLayout( private fun rememberContinueWatchingLayout(maxWidthDp: Float): ContinueWatchingLayout = when { maxWidthDp >= 1440f -> ContinueWatchingLayout( - sectionPadding = 32.dp, itemGap = 20.dp, wideCardWidth = 400.dp, wideCardHeight = 160.dp, @@ -501,7 +500,6 @@ private fun rememberContinueWatchingLayout(maxWidthDp: Float): ContinueWatchingL posterBadgeTextSize = 12.sp, ) maxWidthDp >= 1024f -> ContinueWatchingLayout( - sectionPadding = 28.dp, itemGap = 18.dp, wideCardWidth = 350.dp, wideCardHeight = 140.dp, @@ -520,7 +518,6 @@ private fun rememberContinueWatchingLayout(maxWidthDp: Float): ContinueWatchingL posterBadgeTextSize = 10.sp, ) maxWidthDp >= 768f -> ContinueWatchingLayout( - sectionPadding = 24.dp, itemGap = 16.dp, wideCardWidth = 320.dp, wideCardHeight = 130.dp, @@ -539,7 +536,6 @@ private fun rememberContinueWatchingLayout(maxWidthDp: Float): ContinueWatchingL posterBadgeTextSize = 10.sp, ) else -> ContinueWatchingLayout( - sectionPadding = 16.dp, itemGap = 16.dp, wideCardWidth = 280.dp, wideCardHeight = 120.dp, diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeSectionLayout.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeSectionLayout.kt new file mode 100644 index 00000000..5e79868d --- /dev/null +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/home/components/HomeSectionLayout.kt @@ -0,0 +1,12 @@ +package com.nuvio.app.features.home.components + +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp + +internal fun homeSectionHorizontalPaddingForWidth(maxWidthDp: Float): Dp = + when { + maxWidthDp >= 1440f -> 32.dp + maxWidthDp >= 1024f -> 28.dp + maxWidthDp >= 768f -> 24.dp + else -> 16.dp + } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/profiles/ProfileSelectionScreen.kt b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/profiles/ProfileSelectionScreen.kt index 6b81411a..fcd7536a 100644 --- a/composeApp/src/commonMain/kotlin/com/nuvio/app/features/profiles/ProfileSelectionScreen.kt +++ b/composeApp/src/commonMain/kotlin/com/nuvio/app/features/profiles/ProfileSelectionScreen.kt @@ -10,6 +10,7 @@ import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.collectIsPressedAsState import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -22,6 +23,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.statusBars import androidx.compose.foundation.layout.width +import androidx.compose.foundation.horizontalScroll import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape @@ -89,7 +91,7 @@ fun ProfileSelectionScreen( val statusBarTop = WindowInsets.statusBars.asPaddingValues().calculateTopPadding() - Box( + BoxWithConstraints( modifier = modifier .fillMaxSize() .background( @@ -103,14 +105,23 @@ fun ProfileSelectionScreen( ) .padding(top = statusBarTop), ) { + val isTabletLayout = maxWidth >= 768.dp + Column( modifier = Modifier .fillMaxSize() - .verticalScroll(rememberScrollState()) + .then( + if (isTabletLayout) { + Modifier + } else { + Modifier.verticalScroll(rememberScrollState()) + }, + ) .padding(horizontal = 24.dp), + verticalArrangement = if (isTabletLayout) Arrangement.Center else Arrangement.Top, horizontalAlignment = Alignment.CenterHorizontally, ) { - Spacer(modifier = Modifier.height(60.dp)) + Spacer(modifier = Modifier.height(if (isTabletLayout) 0.dp else 60.dp)) Text( text = "Who's watching?", @@ -126,52 +137,92 @@ fun ProfileSelectionScreen( }, ) - Spacer(modifier = Modifier.height(48.dp)) + Spacer(modifier = Modifier.height(if (isTabletLayout) 28.dp else 48.dp)) val profiles = profileState.profiles val items = profiles.size + if (profiles.size < 4) 1 else 0 - Column( - verticalArrangement = Arrangement.spacedBy(20.dp), - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier.fillMaxWidth(), - ) { - var index = 0 - while (index < items) { + if (isTabletLayout) { + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center, + ) { Row( - horizontalArrangement = Arrangement.spacedBy(20.dp, Alignment.CenterHorizontally), - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .horizontalScroll(rememberScrollState()) + .padding(horizontal = 4.dp), + horizontalArrangement = Arrangement.spacedBy(20.dp), ) { - for (col in 0..1) { - if (index < items) { - val currentIndex = index - if (currentIndex < profiles.size) { - val profile = profiles[currentIndex] - ProfileAvatarCard( - profile = profile, - isEditMode = isEditMode, - animDelay = currentIndex * 80, - onClick = { - if (isEditMode) { - onEditProfile(profile) - } else if (profile.pinEnabled) { - pinDialogProfile = profile - } else { - ProfileRepository.selectProfile(profile.profileIndex) - onProfileSelected(profile) - } - }, - ) - } else { - AddProfileCard( - animDelay = currentIndex * 80, - onClick = onAddProfile, - ) - } - index++ + for (currentIndex in 0 until items) { + if (currentIndex < profiles.size) { + val profile = profiles[currentIndex] + ProfileAvatarCard( + profile = profile, + isEditMode = isEditMode, + animDelay = currentIndex * 80, + onClick = { + if (isEditMode) { + onEditProfile(profile) + } else if (profile.pinEnabled) { + pinDialogProfile = profile + } else { + ProfileRepository.selectProfile(profile.profileIndex) + onProfileSelected(profile) + } + }, + ) } else { - if (profiles.isNotEmpty()) { - Spacer(modifier = Modifier.width(150.dp)) + AddProfileCard( + animDelay = currentIndex * 80, + onClick = onAddProfile, + ) + } + } + } + } + } else { + Column( + verticalArrangement = Arrangement.spacedBy(20.dp), + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier.fillMaxWidth(), + ) { + var index = 0 + while (index < items) { + Row( + horizontalArrangement = Arrangement.spacedBy(20.dp, Alignment.CenterHorizontally), + modifier = Modifier.fillMaxWidth(), + ) { + for (col in 0..1) { + if (index < items) { + val currentIndex = index + if (currentIndex < profiles.size) { + val profile = profiles[currentIndex] + ProfileAvatarCard( + profile = profile, + isEditMode = isEditMode, + animDelay = currentIndex * 80, + onClick = { + if (isEditMode) { + onEditProfile(profile) + } else if (profile.pinEnabled) { + pinDialogProfile = profile + } else { + ProfileRepository.selectProfile(profile.profileIndex) + onProfileSelected(profile) + } + }, + ) + } else { + AddProfileCard( + animDelay = currentIndex * 80, + onClick = onAddProfile, + ) + } + index++ + } else { + if (profiles.isNotEmpty()) { + Spacer(modifier = Modifier.width(150.dp)) + } } } } @@ -179,7 +230,7 @@ fun ProfileSelectionScreen( } } - Spacer(modifier = Modifier.height(48.dp)) + Spacer(modifier = Modifier.height(if (isTabletLayout) 28.dp else 48.dp)) Box( modifier = Modifier @@ -207,7 +258,7 @@ fun ProfileSelectionScreen( ) } - Spacer(modifier = Modifier.height(32.dp)) + Spacer(modifier = Modifier.height(if (isTabletLayout) 0.dp else 32.dp)) } }