feat(ui): make top bars scroll aware

This commit is contained in:
2026-06-06 10:38:40 +00:00
parent 005b3249ff
commit 0bf968a42b
16 changed files with 157 additions and 58 deletions

View File

@@ -11,17 +11,22 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import hu.bbara.purefin.ui.common.image.PurefinAsyncImage
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun MediaDetailScaffold(
imageUrl: String,
@@ -29,19 +34,22 @@ fun MediaDetailScaffold(
imageHeight: Dp = 320.dp,
contentOverlap: Dp = 24.dp,
contentSpacing: Dp = 16.dp,
topBar: @Composable () -> Unit = {},
topBar: @Composable (scrollBehavior: TopAppBarScrollBehavior) -> Unit = {},
heroContent: @Composable ColumnScope.(Modifier) -> Unit,
content: @Composable ColumnScope.(Modifier) -> Unit
) {
val scheme = MaterialTheme.colorScheme
val isHomeMediaTransitionActive = isHomeMediaSharedBoundsTransitionActive()
val topBarScrollBehavior = TopAppBarDefaults.pinnedScrollBehavior()
Scaffold(
modifier = Modifier.fillMaxSize(),
modifier = Modifier
.fillMaxSize()
.nestedScroll(topBarScrollBehavior.nestedScrollConnection),
containerColor = scheme.background,
topBar = {
if (!isHomeMediaTransitionActive) {
topBar()
topBar(topBarScrollBehavior)
}
}
) { innerPadding ->
@@ -86,4 +94,3 @@ fun MediaDetailScaffold(
}
}
}

View File

@@ -1,5 +1,6 @@
package hu.bbara.purefin.ui.screen.episode
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -77,6 +78,7 @@ fun EpisodeScreen(
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun EpisodeScreenInternal(
episode: Episode,
@@ -89,10 +91,11 @@ private fun EpisodeScreenInternal(
MediaDetailScaffold(
imageUrl = ImageUrlBuilder.finishImageUrl(episode.imageUrlPrefix, ArtworkKind.PRIMARY),
modifier = modifier,
topBar = {
topBar = { scrollBehavior ->
EpisodeTopBar(
shortcut = topBarShortcut,
onBack = onBack,
scrollBehavior = scrollBehavior
)
},
heroContent = { _modifier ->

View File

@@ -12,9 +12,11 @@ import androidx.compose.material.icons.outlined.ArrowBack
import androidx.compose.material.icons.outlined.Cast
import androidx.compose.material.icons.outlined.MoreVert
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.VerticalDivider
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
@@ -47,10 +49,12 @@ internal sealed interface EpisodeTopBarShortcut {
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun EpisodeTopBar(
shortcut: EpisodeTopBarShortcut?,
onBack: () -> Unit,
scrollBehavior: TopAppBarScrollBehavior? = null,
) {
DefaultTopBar(
leftActions = {
@@ -93,7 +97,8 @@ internal fun EpisodeTopBar(
contentDescription = "More",
onClick = { })
},
withIcon = false
withIcon = false,
scrollBehavior = scrollBehavior
)
}

View File

@@ -2,19 +2,23 @@ package hu.bbara.purefin.ui.screen.home
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import hu.bbara.purefin.core.model.LibraryUiModel
import hu.bbara.purefin.core.model.MediaUiModel
import hu.bbara.purefin.ui.screen.AppBottomBar
import hu.bbara.purefin.ui.screen.home.components.HomeContent
import hu.bbara.purefin.ui.screen.home.components.HomeTopBar
import hu.bbara.purefin.ui.screen.home.components.rememberDefaultTopBarScrollBehavior
import java.util.UUID
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HomeScreen(
libraries: List<LibraryUiModel>,
@@ -39,9 +43,12 @@ fun HomeScreen(
onTabSelected: (Int) -> Unit,
modifier: Modifier = Modifier
) {
val topBarScrollBehavior = rememberDefaultTopBarScrollBehavior()
Scaffold(
modifier = modifier
.fillMaxSize(),
.fillMaxSize()
.nestedScroll(topBarScrollBehavior.nestedScrollConnection),
containerColor = MaterialTheme.colorScheme.background,
contentColor = MaterialTheme.colorScheme.onBackground,
topBar = {
@@ -51,7 +58,8 @@ fun HomeScreen(
onCheckForUpdates = onCheckForUpdates,
isCheckingForUpdates = isCheckingForUpdates,
onSettingsClick = onSettingsClick,
onLogoutClick = onLogoutClick
onLogoutClick = onLogoutClick,
scrollBehavior = topBarScrollBehavior
)
},
snackbarHost = { SnackbarHost(snackbarHostState) },

View File

@@ -7,19 +7,19 @@ import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Search
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonColors
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
@@ -32,58 +32,58 @@ import hu.bbara.purefin.navigation.LocalNavSharedAnimatedVisibilityScope
import hu.bbara.purefin.navigation.LocalSharedTransitionScope
import hu.bbara.purefin.ui.common.image.PurefinLogo
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun rememberDefaultTopBarScrollBehavior(): TopAppBarScrollBehavior =
TopAppBarDefaults.pinnedScrollBehavior()
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DefaultTopBar(
leftActions: (@Composable RowScope.() -> Unit)? = null,
rightActions: (@Composable RowScope.() -> Unit)? = null,
withIcon: Boolean = true
withIcon: Boolean = true,
scrollBehavior: TopAppBarScrollBehavior? = null
) {
val scheme = MaterialTheme.colorScheme
Surface(
color = Color.Transparent,
contentColor = scheme.onSurface,
modifier = Modifier.fillMaxWidth()
) {
Row(
modifier = Modifier
.statusBarsPadding()
.height(84.dp)
.padding(horizontal = 16.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.SpaceBetween
) {
TopAppBar(
title = {
if (withIcon) {
PurefinLogo(
modifier = Modifier.size(56.dp),
)
}
},
navigationIcon = {
if (leftActions != null) {
Row(
modifier = Modifier.padding(start = 8.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(12.dp),
content = leftActions
)
}
if (withIcon) {
Row(
modifier = Modifier,
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = when {
leftActions == null && rightActions != null -> Arrangement.Start
leftActions != null && rightActions == null -> Arrangement.Center
else -> Arrangement.Center
}
) {
PurefinLogo(
modifier = Modifier.size(56.dp),
)
}
}
},
actions = {
if (rightActions != null) {
Row(
modifier = Modifier.padding(end = 8.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(12.dp),
content = rightActions
)
}
}
}
},
colors = TopAppBarDefaults.topAppBarColors(
containerColor = Color.Transparent,
scrolledContainerColor = scheme.background,
navigationIconContentColor = scheme.onSurface,
titleContentColor = scheme.onSurface,
actionIconContentColor = scheme.onSurface
),
scrollBehavior = scrollBehavior
)
}
@Composable

View File

@@ -4,13 +4,16 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Person
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun HomeTopBar(
onSearchClick: () -> Unit,
@@ -19,10 +22,12 @@ fun HomeTopBar(
isCheckingForUpdates: Boolean,
onSettingsClick: () -> Unit,
onLogoutClick: () -> Unit,
scrollBehavior: TopAppBarScrollBehavior? = null,
) {
var isProfileMenuExpanded by remember { mutableStateOf(false) }
DefaultTopBar(
scrollBehavior = scrollBehavior,
rightActions = {
DefaultTopBarSearchButton(onClick = onSearchClick)
DefaultTopBarIconButton(

View File

@@ -29,6 +29,7 @@ import androidx.compose.material.icons.outlined.Close
import androidx.compose.material.icons.outlined.Search
import androidx.compose.material.icons.outlined.Tune
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.FilterChip
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@@ -38,6 +39,7 @@ import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -46,6 +48,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.text.font.FontWeight
@@ -64,6 +67,7 @@ import hu.bbara.purefin.navigation.LocalNavSharedAnimatedVisibilityScope
import hu.bbara.purefin.navigation.LocalSharedTransitionScope
import hu.bbara.purefin.ui.screen.home.components.DefaultTopBar
import hu.bbara.purefin.ui.screen.home.components.DefaultTopBarIconButton
import hu.bbara.purefin.ui.screen.home.components.rememberDefaultTopBarScrollBehavior
import hu.bbara.purefin.ui.theme.AppTheme
import java.util.UUID
@@ -126,7 +130,7 @@ fun SearchScreen(
)
}
@OptIn(ExperimentalLayoutApi::class)
@OptIn(ExperimentalLayoutApi::class, ExperimentalMaterial3Api::class)
@Composable
private fun SearchScreenContent(
query: String,
@@ -142,13 +146,17 @@ private fun SearchScreenContent(
modifier: Modifier = Modifier
) {
val scheme = MaterialTheme.colorScheme
val topBarScrollBehavior = rememberDefaultTopBarScrollBehavior()
Scaffold(
topBar = { SearchHeader(
onBack = onBack
onBack = onBack,
scrollBehavior = topBarScrollBehavior
) },
modifier = modifier
.fillMaxSize()
.testTag(SearchScreenTag)
.nestedScroll(topBarScrollBehavior.nestedScrollConnection)
.background(scheme.background)
) { innerPadding ->
Column(
@@ -216,10 +224,13 @@ private fun SearchResults(
}
@Composable
@OptIn(ExperimentalMaterial3Api::class)
private fun SearchHeader(
onBack: () -> Unit,
scrollBehavior: TopAppBarScrollBehavior? = null,
) {
DefaultTopBar(
scrollBehavior = scrollBehavior,
leftActions = {
DefaultTopBarIconButton(
imageVector = Icons.Outlined.ArrowBack,

View File

@@ -2,15 +2,19 @@ package hu.bbara.purefin.ui.screen.libraries
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import hu.bbara.purefin.core.model.LibraryUiModel
import hu.bbara.purefin.ui.screen.AppBottomBar
import hu.bbara.purefin.ui.screen.home.components.rememberDefaultTopBarScrollBehavior
import hu.bbara.purefin.ui.screen.libraries.components.LibrariesContent
import hu.bbara.purefin.ui.screen.libraries.components.LibrariesTopBar
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LibrariesScreen(
items: List<LibraryUiModel>,
@@ -21,13 +25,18 @@ fun LibrariesScreen(
onTabSelected: (Int) -> Unit,
modifier: Modifier = Modifier
) {
val topBarScrollBehavior = rememberDefaultTopBarScrollBehavior()
Scaffold(
modifier = modifier.fillMaxSize(),
modifier = modifier
.fillMaxSize()
.nestedScroll(topBarScrollBehavior.nestedScrollConnection),
containerColor = MaterialTheme.colorScheme.background,
contentColor = MaterialTheme.colorScheme.onBackground,
topBar = {
LibrariesTopBar(
onSearchClick = onSearchClick,
scrollBehavior = topBarScrollBehavior
)
},
bottomBar = {

View File

@@ -1,14 +1,19 @@
package hu.bbara.purefin.ui.screen.libraries.components
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import hu.bbara.purefin.ui.screen.home.components.DefaultTopBar
import hu.bbara.purefin.ui.screen.home.components.DefaultTopBarSearchButton
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LibrariesTopBar(
onSearchClick: () -> Unit,
scrollBehavior: TopAppBarScrollBehavior? = null,
) {
DefaultTopBar(
scrollBehavior = scrollBehavior,
rightActions = {
DefaultTopBarSearchButton(onClick = onSearchClick)
}

View File

@@ -10,6 +10,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.foundation.lazy.grid.LazyVerticalGrid
import androidx.compose.foundation.lazy.grid.items
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.runtime.Composable
@@ -17,6 +18,7 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.testTag
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
@@ -28,8 +30,10 @@ import hu.bbara.purefin.core.model.SeriesUiModel
import hu.bbara.purefin.core.navigation.LibraryDto
import hu.bbara.purefin.ui.common.badge.WatchStateBadge
import hu.bbara.purefin.ui.common.card.MediaImageCard
import hu.bbara.purefin.ui.screen.home.components.rememberDefaultTopBarScrollBehavior
import hu.bbara.purefin.ui.screen.library.components.LibraryTopBar
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LibraryScreen(
library: LibraryDto,
@@ -41,14 +45,18 @@ fun LibraryScreen(
}
val libraryItems = viewModel.contents.collectAsStateWithLifecycle()
val topBarScrollBehavior = rememberDefaultTopBarScrollBehavior()
Scaffold(
modifier = modifier.testTag(LibraryScreenTag),
modifier = modifier
.testTag(LibraryScreenTag)
.nestedScroll(topBarScrollBehavior.nestedScrollConnection),
containerColor = MaterialTheme.colorScheme.background,
contentColor = MaterialTheme.colorScheme.onBackground,
topBar = {
LibraryTopBar(
onBack = { viewModel.onBack() }
onBack = { viewModel.onBack() },
scrollBehavior = topBarScrollBehavior
)
}
) { innerPadding ->

View File

@@ -3,15 +3,20 @@ package hu.bbara.purefin.ui.screen.library.components
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
import androidx.compose.material.icons.outlined.FilterAlt
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import hu.bbara.purefin.ui.screen.home.components.DefaultTopBar
import hu.bbara.purefin.ui.screen.home.components.DefaultTopBarIconButton
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LibraryTopBar(
onBack: () -> Unit,
scrollBehavior: TopAppBarScrollBehavior? = null,
) {
DefaultTopBar(
scrollBehavior = scrollBehavior,
leftActions = {
DefaultTopBarIconButton(
imageVector = Icons.AutoMirrored.Outlined.ArrowBack,

View File

@@ -1,5 +1,6 @@
package hu.bbara.purefin.ui.screen.movie
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -63,6 +64,7 @@ fun MovieScreen(
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun MovieScreenInternal(
movie: Movie,
@@ -74,8 +76,11 @@ private fun MovieScreenInternal(
MediaDetailScaffold(
imageUrl = ImageUrlBuilder.finishImageUrl(movie.imageUrlPrefix, ArtworkKind.PRIMARY),
modifier = modifier,
topBar = {
MovieTopBar(onBack = onBack)
topBar = { scrollBehavior ->
MovieTopBar(
onBack = onBack,
scrollBehavior = scrollBehavior
)
},
heroContent = { _modifier ->
MovieHeroContent(

View File

@@ -11,8 +11,10 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.ArrowBack
import androidx.compose.material.icons.outlined.Cast
import androidx.compose.material.icons.outlined.MoreVert
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.VerticalDivider
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
@@ -34,9 +36,11 @@ import hu.bbara.purefin.ui.common.media.mediaPlayButtonText
import hu.bbara.purefin.ui.common.media.mediaPlaybackProgress
import hu.bbara.purefin.ui.screen.home.components.DefaultTopBar
@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun MovieTopBar(
onBack: () -> Unit,
scrollBehavior: TopAppBarScrollBehavior? = null,
) {
DefaultTopBar(
leftActions = {
@@ -53,7 +57,8 @@ internal fun MovieTopBar(
contentDescription = "More",
onClick = { })
},
withIcon = false
withIcon = false,
scrollBehavior = scrollBehavior
)
}

View File

@@ -2,6 +2,7 @@ package hu.bbara.purefin.ui.screen.series
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -112,6 +113,7 @@ fun SeriesScreen(
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun SeriesScreenInternal(
series: Series,
@@ -148,8 +150,11 @@ private fun SeriesScreenInternal(
MediaDetailScaffold(
imageUrl = ImageUrlBuilder.finishImageUrl(series.imageUrlPrefix, ArtworkKind.PRIMARY),
modifier = modifier,
topBar = {
SeriesTopBar(onBack = onBack)
topBar = { scrollBehavior ->
SeriesTopBar(
onBack = onBack,
scrollBehavior = scrollBehavior
)
},
heroContent = { _modifier ->
SeriesHeroContent(

View File

@@ -35,6 +35,7 @@ import androidx.compose.material3.ListItemDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
@@ -77,10 +78,12 @@ import hu.bbara.purefin.ui.common.media.mediaPlayButtonText
import hu.bbara.purefin.ui.common.media.mediaPlaybackProgress
import hu.bbara.purefin.ui.screen.home.components.DefaultTopBar
@OptIn(ExperimentalMaterial3Api::class)
@Composable
internal fun SeriesTopBar(
onBack: () -> Unit,
modifier: Modifier = Modifier
modifier: Modifier = Modifier,
scrollBehavior: TopAppBarScrollBehavior? = null
) {
DefaultTopBar(
leftActions = {
@@ -95,7 +98,8 @@ internal fun SeriesTopBar(
GhostIconButton(icon = Icons.Outlined.MoreVert, contentDescription = "More", onClick = { })
}
},
withIcon = false
withIcon = false,
scrollBehavior = scrollBehavior
)
}

View File

@@ -13,16 +13,19 @@ import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
@@ -36,6 +39,7 @@ import hu.bbara.purefin.core.settings.StringSetting
import hu.bbara.purefin.core.settings.VoidSetting
import hu.bbara.purefin.ui.screen.home.components.DefaultTopBar
import hu.bbara.purefin.ui.screen.home.components.DefaultTopBarIconButton
import hu.bbara.purefin.ui.screen.home.components.rememberDefaultTopBarScrollBehavior
import hu.bbara.purefin.ui.screen.settings.components.BooleanSettingItem
import hu.bbara.purefin.ui.screen.settings.components.DropdownSettingItem
import hu.bbara.purefin.ui.screen.settings.components.RangeSettingItem
@@ -43,6 +47,7 @@ import hu.bbara.purefin.ui.screen.settings.components.ReadOnlySettingItem
import hu.bbara.purefin.ui.screen.settings.components.StringSettingItem
import hu.bbara.purefin.ui.screen.settings.components.VoidSettingItem
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun SettingsScreen(
viewModel: SettingsViewModel = hiltViewModel(),
@@ -50,6 +55,7 @@ fun SettingsScreen(
) {
val settingGroups by viewModel.settingGroups.collectAsStateWithLifecycle()
val snackbarHostState = remember { SnackbarHostState() }
val topBarScrollBehavior = rememberDefaultTopBarScrollBehavior()
LaunchedEffect(viewModel) {
viewModel.snackbarMessages.collect { message ->
@@ -58,12 +64,17 @@ fun SettingsScreen(
}
Scaffold(
modifier = modifier.fillMaxSize(),
modifier = modifier
.fillMaxSize()
.nestedScroll(topBarScrollBehavior.nestedScrollConnection),
containerColor = MaterialTheme.colorScheme.background,
contentColor = MaterialTheme.colorScheme.onBackground,
snackbarHost = { SnackbarHost(snackbarHostState) },
topBar = {
SettingsTopBar(onBack = viewModel::onBack)
SettingsTopBar(
onBack = viewModel::onBack,
scrollBehavior = topBarScrollBehavior
)
}
) { innerPadding ->
LazyColumn(
@@ -224,11 +235,14 @@ private fun <T> DropdownSettingOptionItem(
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun SettingsTopBar(
onBack: () -> Unit
onBack: () -> Unit,
scrollBehavior: TopAppBarScrollBehavior? = null
) {
DefaultTopBar(
scrollBehavior = scrollBehavior,
leftActions = {
DefaultTopBarIconButton(
imageVector = Icons.AutoMirrored.Outlined.ArrowBack,