Add scroll overlay to LibraryToolbar (#7669)
Works when category tab is not shown
This commit is contained in:
parent
3d4e56948d
commit
afceac15c8
@ -89,7 +89,7 @@ fun AppBar(
|
|||||||
// Menu
|
// Menu
|
||||||
actions: @Composable RowScope.() -> Unit = {},
|
actions: @Composable RowScope.() -> Unit = {},
|
||||||
// Action mode
|
// Action mode
|
||||||
isActionMode: Boolean,
|
isActionMode: Boolean = false,
|
||||||
onCancelActionMode: () -> Unit = {},
|
onCancelActionMode: () -> Unit = {},
|
||||||
// Banners
|
// Banners
|
||||||
downloadedOnlyMode: Boolean = false,
|
downloadedOnlyMode: Boolean = false,
|
||||||
|
@ -1,10 +1,17 @@
|
|||||||
package eu.kanade.presentation.library
|
package eu.kanade.presentation.library
|
||||||
|
|
||||||
import androidx.compose.animation.Crossfade
|
import androidx.compose.animation.Crossfade
|
||||||
import androidx.compose.foundation.layout.safeDrawingPadding
|
import androidx.compose.foundation.layout.WindowInsets
|
||||||
|
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||||
|
import androidx.compose.foundation.layout.navigationBars
|
||||||
|
import androidx.compose.foundation.layout.only
|
||||||
|
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||||
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
|
import androidx.compose.material3.rememberTopAppBarState
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||||
import eu.kanade.domain.category.model.Category
|
import eu.kanade.domain.category.model.Category
|
||||||
import eu.kanade.presentation.components.LibraryBottomActionMenu
|
import eu.kanade.presentation.components.LibraryBottomActionMenu
|
||||||
import eu.kanade.presentation.components.LoadingScreen
|
import eu.kanade.presentation.components.LoadingScreen
|
||||||
@ -30,21 +37,29 @@ fun LibraryScreen(
|
|||||||
onClickFilter: () -> Unit,
|
onClickFilter: () -> Unit,
|
||||||
onClickRefresh: (Category?) -> Unit,
|
onClickRefresh: (Category?) -> Unit,
|
||||||
) {
|
) {
|
||||||
|
val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
|
||||||
|
val insets = WindowInsets.navigationBars.only(WindowInsetsSides.Horizontal)
|
||||||
Crossfade(targetState = presenter.isLoading) { state ->
|
Crossfade(targetState = presenter.isLoading) { state ->
|
||||||
when (state) {
|
when (state) {
|
||||||
true -> LoadingScreen()
|
true -> LoadingScreen()
|
||||||
false -> Scaffold(
|
false -> Scaffold(
|
||||||
modifier = Modifier.safeDrawingPadding(),
|
modifier = Modifier
|
||||||
|
.windowInsetsPadding(insets)
|
||||||
|
.nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||||
topBar = {
|
topBar = {
|
||||||
val title by presenter.getToolbarTitle()
|
val title by presenter.getToolbarTitle()
|
||||||
|
val tabVisible = presenter.tabVisibility && presenter.categories.size > 1
|
||||||
LibraryToolbar(
|
LibraryToolbar(
|
||||||
state = presenter,
|
state = presenter,
|
||||||
title = title,
|
title = title,
|
||||||
|
incognitoMode = !tabVisible && presenter.isIncognitoMode,
|
||||||
|
downloadedOnlyMode = !tabVisible && presenter.isDownloadOnly,
|
||||||
onClickUnselectAll = onClickUnselectAll,
|
onClickUnselectAll = onClickUnselectAll,
|
||||||
onClickSelectAll = onClickSelectAll,
|
onClickSelectAll = onClickSelectAll,
|
||||||
onClickInvertSelection = onClickInvertSelection,
|
onClickInvertSelection = onClickInvertSelection,
|
||||||
onClickFilter = onClickFilter,
|
onClickFilter = onClickFilter,
|
||||||
onClickRefresh = { onClickRefresh(null) },
|
onClickRefresh = { onClickRefresh(null) },
|
||||||
|
scrollBehavior = scrollBehavior.takeIf { !tabVisible }, // For scroll overlay when no tab
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
bottomBar = {
|
bottomBar = {
|
||||||
|
@ -5,8 +5,6 @@ import androidx.compose.foundation.layout.Row
|
|||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.text.BasicTextField
|
import androidx.compose.foundation.text.BasicTextField
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.outlined.ArrowBack
|
|
||||||
import androidx.compose.material.icons.outlined.Close
|
|
||||||
import androidx.compose.material.icons.outlined.FilterList
|
import androidx.compose.material.icons.outlined.FilterList
|
||||||
import androidx.compose.material.icons.outlined.FlipToBack
|
import androidx.compose.material.icons.outlined.FlipToBack
|
||||||
import androidx.compose.material.icons.outlined.Refresh
|
import androidx.compose.material.icons.outlined.Refresh
|
||||||
@ -16,9 +14,9 @@ import androidx.compose.material3.Icon
|
|||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.LocalContentColor
|
import androidx.compose.material3.LocalContentColor
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.SmallTopAppBar
|
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.material3.TopAppBarDefaults
|
import androidx.compose.material3.TopAppBarDefaults
|
||||||
|
import androidx.compose.material3.TopAppBarScrollBehavior
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
@ -28,10 +26,10 @@ import androidx.compose.ui.Modifier
|
|||||||
import androidx.compose.ui.draw.drawBehind
|
import androidx.compose.ui.draw.drawBehind
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
import androidx.compose.ui.focus.focusRequester
|
import androidx.compose.ui.focus.focusRequester
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.graphics.SolidColor
|
import androidx.compose.ui.graphics.SolidColor
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
|
import eu.kanade.presentation.components.AppBar
|
||||||
import eu.kanade.presentation.components.Pill
|
import eu.kanade.presentation.components.Pill
|
||||||
import eu.kanade.presentation.library.LibraryState
|
import eu.kanade.presentation.library.LibraryState
|
||||||
import eu.kanade.presentation.theme.active
|
import eu.kanade.presentation.theme.active
|
||||||
@ -41,29 +39,40 @@ import kotlinx.coroutines.delay
|
|||||||
fun LibraryToolbar(
|
fun LibraryToolbar(
|
||||||
state: LibraryState,
|
state: LibraryState,
|
||||||
title: LibraryToolbarTitle,
|
title: LibraryToolbarTitle,
|
||||||
|
incognitoMode: Boolean,
|
||||||
|
downloadedOnlyMode: Boolean,
|
||||||
onClickUnselectAll: () -> Unit,
|
onClickUnselectAll: () -> Unit,
|
||||||
onClickSelectAll: () -> Unit,
|
onClickSelectAll: () -> Unit,
|
||||||
onClickInvertSelection: () -> Unit,
|
onClickInvertSelection: () -> Unit,
|
||||||
onClickFilter: () -> Unit,
|
onClickFilter: () -> Unit,
|
||||||
onClickRefresh: () -> Unit,
|
onClickRefresh: () -> Unit,
|
||||||
|
scrollBehavior: TopAppBarScrollBehavior?,
|
||||||
) = when {
|
) = when {
|
||||||
state.selectionMode -> LibrarySelectionToolbar(
|
state.selectionMode -> LibrarySelectionToolbar(
|
||||||
state = state,
|
state = state,
|
||||||
|
incognitoMode = incognitoMode,
|
||||||
|
downloadedOnlyMode = downloadedOnlyMode,
|
||||||
onClickUnselectAll = onClickUnselectAll,
|
onClickUnselectAll = onClickUnselectAll,
|
||||||
onClickSelectAll = onClickSelectAll,
|
onClickSelectAll = onClickSelectAll,
|
||||||
onClickInvertSelection = onClickInvertSelection,
|
onClickInvertSelection = onClickInvertSelection,
|
||||||
)
|
)
|
||||||
state.searchQuery != null -> LibrarySearchToolbar(
|
state.searchQuery != null -> LibrarySearchToolbar(
|
||||||
searchQuery = state.searchQuery!!,
|
searchQuery = state.searchQuery!!,
|
||||||
|
incognitoMode = incognitoMode,
|
||||||
|
downloadedOnlyMode = downloadedOnlyMode,
|
||||||
onChangeSearchQuery = { state.searchQuery = it },
|
onChangeSearchQuery = { state.searchQuery = it },
|
||||||
onClickCloseSearch = { state.searchQuery = null },
|
onClickCloseSearch = { state.searchQuery = null },
|
||||||
|
scrollBehavior = scrollBehavior,
|
||||||
)
|
)
|
||||||
else -> LibraryRegularToolbar(
|
else -> LibraryRegularToolbar(
|
||||||
title = title,
|
title = title,
|
||||||
hasFilters = state.hasActiveFilters,
|
hasFilters = state.hasActiveFilters,
|
||||||
|
incognitoMode = incognitoMode,
|
||||||
|
downloadedOnlyMode = downloadedOnlyMode,
|
||||||
onClickSearch = { state.searchQuery = "" },
|
onClickSearch = { state.searchQuery = "" },
|
||||||
onClickFilter = onClickFilter,
|
onClickFilter = onClickFilter,
|
||||||
onClickRefresh = onClickRefresh,
|
onClickRefresh = onClickRefresh,
|
||||||
|
scrollBehavior = scrollBehavior,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,14 +80,17 @@ fun LibraryToolbar(
|
|||||||
fun LibraryRegularToolbar(
|
fun LibraryRegularToolbar(
|
||||||
title: LibraryToolbarTitle,
|
title: LibraryToolbarTitle,
|
||||||
hasFilters: Boolean,
|
hasFilters: Boolean,
|
||||||
|
incognitoMode: Boolean,
|
||||||
|
downloadedOnlyMode: Boolean,
|
||||||
onClickSearch: () -> Unit,
|
onClickSearch: () -> Unit,
|
||||||
onClickFilter: () -> Unit,
|
onClickFilter: () -> Unit,
|
||||||
onClickRefresh: () -> Unit,
|
onClickRefresh: () -> Unit,
|
||||||
|
scrollBehavior: TopAppBarScrollBehavior?,
|
||||||
) {
|
) {
|
||||||
val pillAlpha = if (isSystemInDarkTheme()) 0.12f else 0.08f
|
val pillAlpha = if (isSystemInDarkTheme()) 0.12f else 0.08f
|
||||||
val filterTint = if (hasFilters) MaterialTheme.colorScheme.active else LocalContentColor.current
|
val filterTint = if (hasFilters) MaterialTheme.colorScheme.active else LocalContentColor.current
|
||||||
SmallTopAppBar(
|
AppBar(
|
||||||
title = {
|
titleContent = {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
Text(
|
Text(
|
||||||
text = title.text,
|
text = title.text,
|
||||||
@ -106,30 +118,28 @@ fun LibraryRegularToolbar(
|
|||||||
Icon(Icons.Outlined.Refresh, contentDescription = "search")
|
Icon(Icons.Outlined.Refresh, contentDescription = "search")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
incognitoMode = incognitoMode,
|
||||||
|
downloadedOnlyMode = downloadedOnlyMode,
|
||||||
|
scrollBehavior = scrollBehavior,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LibrarySelectionToolbar(
|
fun LibrarySelectionToolbar(
|
||||||
state: LibraryState,
|
state: LibraryState,
|
||||||
|
incognitoMode: Boolean,
|
||||||
|
downloadedOnlyMode: Boolean,
|
||||||
onClickUnselectAll: () -> Unit,
|
onClickUnselectAll: () -> Unit,
|
||||||
onClickSelectAll: () -> Unit,
|
onClickSelectAll: () -> Unit,
|
||||||
onClickInvertSelection: () -> Unit,
|
onClickInvertSelection: () -> Unit,
|
||||||
) {
|
) {
|
||||||
val backgroundColor by TopAppBarDefaults.smallTopAppBarColors().containerColor(1f)
|
val backgroundColor by TopAppBarDefaults.smallTopAppBarColors().containerColor(1f)
|
||||||
SmallTopAppBar(
|
AppBar(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.drawBehind {
|
.drawBehind {
|
||||||
drawRect(backgroundColor.copy(alpha = 1f))
|
drawRect(backgroundColor.copy(alpha = 1f))
|
||||||
},
|
},
|
||||||
navigationIcon = {
|
titleContent = { Text(text = "${state.selection.size}") },
|
||||||
IconButton(onClick = onClickUnselectAll) {
|
|
||||||
Icon(Icons.Outlined.Close, contentDescription = "close")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
title = {
|
|
||||||
Text(text = "${state.selection.size}")
|
|
||||||
},
|
|
||||||
actions = {
|
actions = {
|
||||||
IconButton(onClick = onClickSelectAll) {
|
IconButton(onClick = onClickSelectAll) {
|
||||||
Icon(Icons.Outlined.SelectAll, contentDescription = "search")
|
Icon(Icons.Outlined.SelectAll, contentDescription = "search")
|
||||||
@ -138,27 +148,26 @@ fun LibrarySelectionToolbar(
|
|||||||
Icon(Icons.Outlined.FlipToBack, contentDescription = "invert")
|
Icon(Icons.Outlined.FlipToBack, contentDescription = "invert")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
colors = TopAppBarDefaults.smallTopAppBarColors(
|
isActionMode = true,
|
||||||
containerColor = Color.Transparent,
|
onCancelActionMode = onClickUnselectAll,
|
||||||
scrolledContainerColor = Color.Transparent,
|
incognitoMode = incognitoMode,
|
||||||
),
|
downloadedOnlyMode = downloadedOnlyMode,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun LibrarySearchToolbar(
|
fun LibrarySearchToolbar(
|
||||||
searchQuery: String,
|
searchQuery: String,
|
||||||
|
incognitoMode: Boolean,
|
||||||
|
downloadedOnlyMode: Boolean,
|
||||||
onChangeSearchQuery: (String) -> Unit,
|
onChangeSearchQuery: (String) -> Unit,
|
||||||
onClickCloseSearch: () -> Unit,
|
onClickCloseSearch: () -> Unit,
|
||||||
|
scrollBehavior: TopAppBarScrollBehavior?,
|
||||||
) {
|
) {
|
||||||
val focusRequester = remember { FocusRequester.Default }
|
val focusRequester = remember { FocusRequester.Default }
|
||||||
SmallTopAppBar(
|
AppBar(
|
||||||
navigationIcon = {
|
navigateUp = onClickCloseSearch,
|
||||||
IconButton(onClick = onClickCloseSearch) {
|
titleContent = {
|
||||||
Icon(Icons.Outlined.ArrowBack, contentDescription = "back")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
title = {
|
|
||||||
BasicTextField(
|
BasicTextField(
|
||||||
value = searchQuery,
|
value = searchQuery,
|
||||||
onValueChange = onChangeSearchQuery,
|
onValueChange = onChangeSearchQuery,
|
||||||
@ -175,6 +184,9 @@ fun LibrarySearchToolbar(
|
|||||||
focusRequester.requestFocus()
|
focusRequester.requestFocus()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
incognitoMode = incognitoMode,
|
||||||
|
downloadedOnlyMode = downloadedOnlyMode,
|
||||||
|
scrollBehavior = scrollBehavior,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user