mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +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