mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-31 14:27:57 +01:00 
			
		
		
		
	Add scroll overlay to LibraryToolbar (#7669)
Works when category tab is not shown
This commit is contained in:
		| @@ -89,7 +89,7 @@ fun AppBar( | ||||
|     // Menu | ||||
|     actions: @Composable RowScope.() -> Unit = {}, | ||||
|     // Action mode | ||||
|     isActionMode: Boolean, | ||||
|     isActionMode: Boolean = false, | ||||
|     onCancelActionMode: () -> Unit = {}, | ||||
|     // Banners | ||||
|     downloadedOnlyMode: Boolean = false, | ||||
|   | ||||
| @@ -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 = { | ||||
|   | ||||
| @@ -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, | ||||
|     ) | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user