Răsfoiți Sursa

Add scroll overlay to LibraryToolbar (#7669)

Works when category tab is not shown
Ivan Iskandar 2 ani în urmă
părinte
comite
afceac15c8

+ 1 - 1
app/src/main/java/eu/kanade/presentation/components/AppBar.kt

@@ -89,7 +89,7 @@ fun AppBar(
     // Menu
     actions: @Composable RowScope.() -> Unit = {},
     // Action mode
-    isActionMode: Boolean,
+    isActionMode: Boolean = false,
     onCancelActionMode: () -> Unit = {},
     // Banners
     downloadedOnlyMode: Boolean = false,

+ 17 - 2
app/src/main/java/eu/kanade/presentation/library/LibraryScreen.kt

@@ -1,10 +1,17 @@
 package eu.kanade.presentation.library
 
 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.getValue
 import androidx.compose.ui.Modifier
+import androidx.compose.ui.input.nestedscroll.nestedScroll
 import eu.kanade.domain.category.model.Category
 import eu.kanade.presentation.components.LibraryBottomActionMenu
 import eu.kanade.presentation.components.LoadingScreen
@@ -30,21 +37,29 @@ fun LibraryScreen(
     onClickFilter: () -> Unit,
     onClickRefresh: (Category?) -> Unit,
 ) {
+    val scrollBehavior = TopAppBarDefaults.pinnedScrollBehavior(rememberTopAppBarState())
+    val insets = WindowInsets.navigationBars.only(WindowInsetsSides.Horizontal)
     Crossfade(targetState = presenter.isLoading) { state ->
         when (state) {
             true -> LoadingScreen()
             false -> Scaffold(
-                modifier = Modifier.safeDrawingPadding(),
+                modifier = Modifier
+                    .windowInsetsPadding(insets)
+                    .nestedScroll(scrollBehavior.nestedScrollConnection),
                 topBar = {
                     val title by presenter.getToolbarTitle()
+                    val tabVisible = presenter.tabVisibility && presenter.categories.size > 1
                     LibraryToolbar(
                         state = presenter,
                         title = title,
+                        incognitoMode = !tabVisible && presenter.isIncognitoMode,
+                        downloadedOnlyMode = !tabVisible && presenter.isDownloadOnly,
                         onClickUnselectAll = onClickUnselectAll,
                         onClickSelectAll = onClickSelectAll,
                         onClickInvertSelection = onClickInvertSelection,
                         onClickFilter = onClickFilter,
                         onClickRefresh = { onClickRefresh(null) },
+                        scrollBehavior = scrollBehavior.takeIf { !tabVisible }, // For scroll overlay when no tab
                     )
                 },
                 bottomBar = {

+ 38 - 26
app/src/main/java/eu/kanade/presentation/library/components/LibraryToolbar.kt

@@ -5,8 +5,6 @@ import androidx.compose.foundation.layout.Row
 import androidx.compose.foundation.layout.fillMaxWidth
 import androidx.compose.foundation.text.BasicTextField
 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.FlipToBack
 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.LocalContentColor
 import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.SmallTopAppBar
 import androidx.compose.material3.Text
 import androidx.compose.material3.TopAppBarDefaults
+import androidx.compose.material3.TopAppBarScrollBehavior
 import androidx.compose.runtime.Composable
 import androidx.compose.runtime.LaunchedEffect
 import androidx.compose.runtime.getValue
@@ -28,10 +26,10 @@ import androidx.compose.ui.Modifier
 import androidx.compose.ui.draw.drawBehind
 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.text.style.TextOverflow
 import androidx.compose.ui.unit.sp
+import eu.kanade.presentation.components.AppBar
 import eu.kanade.presentation.components.Pill
 import eu.kanade.presentation.library.LibraryState
 import eu.kanade.presentation.theme.active
@@ -41,29 +39,40 @@ import kotlinx.coroutines.delay
 fun LibraryToolbar(
     state: LibraryState,
     title: LibraryToolbarTitle,
+    incognitoMode: Boolean,
+    downloadedOnlyMode: Boolean,
     onClickUnselectAll: () -> Unit,
     onClickSelectAll: () -> Unit,
     onClickInvertSelection: () -> Unit,
     onClickFilter: () -> Unit,
     onClickRefresh: () -> Unit,
+    scrollBehavior: TopAppBarScrollBehavior?,
 ) = when {
     state.selectionMode -> LibrarySelectionToolbar(
         state = state,
+        incognitoMode = incognitoMode,
+        downloadedOnlyMode = downloadedOnlyMode,
         onClickUnselectAll = onClickUnselectAll,
         onClickSelectAll = onClickSelectAll,
         onClickInvertSelection = onClickInvertSelection,
     )
     state.searchQuery != null -> LibrarySearchToolbar(
         searchQuery = state.searchQuery!!,
+        incognitoMode = incognitoMode,
+        downloadedOnlyMode = downloadedOnlyMode,
         onChangeSearchQuery = { state.searchQuery = it },
         onClickCloseSearch = { state.searchQuery = null },
+        scrollBehavior = scrollBehavior,
     )
     else -> LibraryRegularToolbar(
         title = title,
         hasFilters = state.hasActiveFilters,
+        incognitoMode = incognitoMode,
+        downloadedOnlyMode = downloadedOnlyMode,
         onClickSearch = { state.searchQuery = "" },
         onClickFilter = onClickFilter,
         onClickRefresh = onClickRefresh,
+        scrollBehavior = scrollBehavior,
     )
 }
 
@@ -71,14 +80,17 @@ fun LibraryToolbar(
 fun LibraryRegularToolbar(
     title: LibraryToolbarTitle,
     hasFilters: Boolean,
+    incognitoMode: Boolean,
+    downloadedOnlyMode: Boolean,
     onClickSearch: () -> Unit,
     onClickFilter: () -> Unit,
     onClickRefresh: () -> Unit,
+    scrollBehavior: TopAppBarScrollBehavior?,
 ) {
     val pillAlpha = if (isSystemInDarkTheme()) 0.12f else 0.08f
     val filterTint = if (hasFilters) MaterialTheme.colorScheme.active else LocalContentColor.current
-    SmallTopAppBar(
-        title = {
+    AppBar(
+        titleContent = {
             Row(verticalAlignment = Alignment.CenterVertically) {
                 Text(
                     text = title.text,
@@ -106,30 +118,28 @@ fun LibraryRegularToolbar(
                 Icon(Icons.Outlined.Refresh, contentDescription = "search")
             }
         },
+        incognitoMode = incognitoMode,
+        downloadedOnlyMode = downloadedOnlyMode,
+        scrollBehavior = scrollBehavior,
     )
 }
 
 @Composable
 fun LibrarySelectionToolbar(
     state: LibraryState,
+    incognitoMode: Boolean,
+    downloadedOnlyMode: Boolean,
     onClickUnselectAll: () -> Unit,
     onClickSelectAll: () -> Unit,
     onClickInvertSelection: () -> Unit,
 ) {
     val backgroundColor by TopAppBarDefaults.smallTopAppBarColors().containerColor(1f)
-    SmallTopAppBar(
+    AppBar(
         modifier = Modifier
             .drawBehind {
                 drawRect(backgroundColor.copy(alpha = 1f))
             },
-        navigationIcon = {
-            IconButton(onClick = onClickUnselectAll) {
-                Icon(Icons.Outlined.Close, contentDescription = "close")
-            }
-        },
-        title = {
-            Text(text = "${state.selection.size}")
-        },
+        titleContent = { Text(text = "${state.selection.size}") },
         actions = {
             IconButton(onClick = onClickSelectAll) {
                 Icon(Icons.Outlined.SelectAll, contentDescription = "search")
@@ -138,27 +148,26 @@ fun LibrarySelectionToolbar(
                 Icon(Icons.Outlined.FlipToBack, contentDescription = "invert")
             }
         },
-        colors = TopAppBarDefaults.smallTopAppBarColors(
-            containerColor = Color.Transparent,
-            scrolledContainerColor = Color.Transparent,
-        ),
+        isActionMode = true,
+        onCancelActionMode = onClickUnselectAll,
+        incognitoMode = incognitoMode,
+        downloadedOnlyMode = downloadedOnlyMode,
     )
 }
 
 @Composable
 fun LibrarySearchToolbar(
     searchQuery: String,
+    incognitoMode: Boolean,
+    downloadedOnlyMode: Boolean,
     onChangeSearchQuery: (String) -> Unit,
     onClickCloseSearch: () -> Unit,
+    scrollBehavior: TopAppBarScrollBehavior?,
 ) {
     val focusRequester = remember { FocusRequester.Default }
-    SmallTopAppBar(
-        navigationIcon = {
-            IconButton(onClick = onClickCloseSearch) {
-                Icon(Icons.Outlined.ArrowBack, contentDescription = "back")
-            }
-        },
-        title = {
+    AppBar(
+        navigateUp = onClickCloseSearch,
+        titleContent = {
             BasicTextField(
                 value = searchQuery,
                 onValueChange = onChangeSearchQuery,
@@ -175,6 +184,9 @@ fun LibrarySearchToolbar(
                 focusRequester.requestFocus()
             }
         },
+        incognitoMode = incognitoMode,
+        downloadedOnlyMode = downloadedOnlyMode,
+        scrollBehavior = scrollBehavior,
     )
 }