mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-05-06 10:09:39 +00:00
feat(home): Refactor HomeCatalogRowSection and HomeContinueWatchingSection for dynamic padding and layout adjustments
This commit is contained in:
parent
fc5a078f73
commit
ae95c9d004
4 changed files with 134 additions and 70 deletions
|
|
@ -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) } },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue