Reuse AppBar in manga screen (#1367)

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
This commit is contained in:
Cuong-Tran 2025-02-25 04:33:47 +07:00 committed by GitHub
parent ebfbbf0741
commit 2cd52d5a1f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 110 additions and 124 deletions

View File

@ -87,7 +87,7 @@ fun MangaScreen(
isTabletUi: Boolean, isTabletUi: Boolean,
chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction, chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction,
chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction, chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction,
onBackClicked: () -> Unit, navigateUp: () -> Unit,
onChapterClicked: (Chapter) -> Unit, onChapterClicked: (Chapter) -> Unit,
onDownloadChapter: ((List<ChapterList.Item>, ChapterDownloadAction) -> Unit)?, onDownloadChapter: ((List<ChapterList.Item>, ChapterDownloadAction) -> Unit)?,
onAddToLibraryClicked: () -> Unit, onAddToLibraryClicked: () -> Unit,
@ -141,7 +141,7 @@ fun MangaScreen(
nextUpdate = nextUpdate, nextUpdate = nextUpdate,
chapterSwipeStartAction = chapterSwipeStartAction, chapterSwipeStartAction = chapterSwipeStartAction,
chapterSwipeEndAction = chapterSwipeEndAction, chapterSwipeEndAction = chapterSwipeEndAction,
onBackClicked = onBackClicked, navigateUp = navigateUp,
onChapterClicked = onChapterClicked, onChapterClicked = onChapterClicked,
onDownloadChapter = onDownloadChapter, onDownloadChapter = onDownloadChapter,
onAddToLibraryClicked = onAddToLibraryClicked, onAddToLibraryClicked = onAddToLibraryClicked,
@ -176,7 +176,7 @@ fun MangaScreen(
chapterSwipeStartAction = chapterSwipeStartAction, chapterSwipeStartAction = chapterSwipeStartAction,
chapterSwipeEndAction = chapterSwipeEndAction, chapterSwipeEndAction = chapterSwipeEndAction,
nextUpdate = nextUpdate, nextUpdate = nextUpdate,
onBackClicked = onBackClicked, navigateUp = navigateUp,
onChapterClicked = onChapterClicked, onChapterClicked = onChapterClicked,
onDownloadChapter = onDownloadChapter, onDownloadChapter = onDownloadChapter,
onAddToLibraryClicked = onAddToLibraryClicked, onAddToLibraryClicked = onAddToLibraryClicked,
@ -214,7 +214,7 @@ private fun MangaScreenSmallImpl(
nextUpdate: Instant?, nextUpdate: Instant?,
chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction, chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction,
chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction, chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction,
onBackClicked: () -> Unit, navigateUp: () -> Unit,
onChapterClicked: (Chapter) -> Unit, onChapterClicked: (Chapter) -> Unit,
onDownloadChapter: ((List<ChapterList.Item>, ChapterDownloadAction) -> Unit)?, onDownloadChapter: ((List<ChapterList.Item>, ChapterDownloadAction) -> Unit)?,
onAddToLibraryClicked: () -> Unit, onAddToLibraryClicked: () -> Unit,
@ -265,14 +265,13 @@ private fun MangaScreenSmallImpl(
) )
} }
val internalOnBackPressed = { BackHandler(onBack = {
if (isAnySelected) { if (isAnySelected) {
onAllChapterSelected(false) onAllChapterSelected(false)
} else { } else {
onBackClicked() navigateUp()
} }
} })
BackHandler(onBack = internalOnBackPressed)
Scaffold( Scaffold(
topBar = { topBar = {
@ -285,20 +284,18 @@ private fun MangaScreenSmallImpl(
val isFirstItemScrolled by remember { val isFirstItemScrolled by remember {
derivedStateOf { chapterListState.firstVisibleItemScrollOffset > 0 } derivedStateOf { chapterListState.firstVisibleItemScrollOffset > 0 }
} }
val animatedTitleAlpha by animateFloatAsState( val titleAlpha by animateFloatAsState(
if (!isFirstItemVisible) 1f else 0f, if (!isFirstItemVisible) 1f else 0f,
label = "Top Bar Title", label = "Top Bar Title",
) )
val animatedBgAlpha by animateFloatAsState( val backgroundAlpha by animateFloatAsState(
if (!isFirstItemVisible || isFirstItemScrolled) 1f else 0f, if (!isFirstItemVisible || isFirstItemScrolled) 1f else 0f,
label = "Top Bar Background", label = "Top Bar Background",
) )
MangaToolbar( MangaToolbar(
title = state.manga.title, title = state.manga.title,
titleAlphaProvider = { animatedTitleAlpha },
backgroundAlphaProvider = { animatedBgAlpha },
hasFilters = state.filterActive, hasFilters = state.filterActive,
onBackClicked = internalOnBackPressed, navigateUp = navigateUp,
onClickFilter = onFilterClicked, onClickFilter = onFilterClicked,
onClickShare = onShareClicked, onClickShare = onShareClicked,
onClickDownload = onDownloadActionClicked, onClickDownload = onDownloadActionClicked,
@ -306,8 +303,11 @@ private fun MangaScreenSmallImpl(
onClickRefresh = onRefresh, onClickRefresh = onRefresh,
onClickMigrate = onMigrateClicked, onClickMigrate = onMigrateClicked,
actionModeCounter = selectedChapterCount, actionModeCounter = selectedChapterCount,
onCancelActionMode = { onAllChapterSelected(false) },
onSelectAll = { onAllChapterSelected(true) }, onSelectAll = { onAllChapterSelected(true) },
onInvertSelection = { onInvertSelection() }, onInvertSelection = { onInvertSelection() },
titleAlphaProvider = { titleAlpha },
backgroundAlphaProvider = { backgroundAlpha },
) )
}, },
bottomBar = { bottomBar = {
@ -458,7 +458,7 @@ fun MangaScreenLargeImpl(
nextUpdate: Instant?, nextUpdate: Instant?,
chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction, chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction,
chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction, chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction,
onBackClicked: () -> Unit, navigateUp: () -> Unit,
onChapterClicked: (Chapter) -> Unit, onChapterClicked: (Chapter) -> Unit,
onDownloadChapter: ((List<ChapterList.Item>, ChapterDownloadAction) -> Unit)?, onDownloadChapter: ((List<ChapterList.Item>, ChapterDownloadAction) -> Unit)?,
onAddToLibraryClicked: () -> Unit, onAddToLibraryClicked: () -> Unit,
@ -515,14 +515,13 @@ fun MangaScreenLargeImpl(
val chapterListState = rememberLazyListState() val chapterListState = rememberLazyListState()
val internalOnBackPressed = { BackHandler(onBack = {
if (isAnySelected) { if (isAnySelected) {
onAllChapterSelected(false) onAllChapterSelected(false)
} else { } else {
onBackClicked() navigateUp()
} }
} })
BackHandler(onBack = internalOnBackPressed)
Scaffold( Scaffold(
topBar = { topBar = {
@ -532,19 +531,20 @@ fun MangaScreenLargeImpl(
MangaToolbar( MangaToolbar(
modifier = Modifier.onSizeChanged { topBarHeight = it.height }, modifier = Modifier.onSizeChanged { topBarHeight = it.height },
title = state.manga.title, title = state.manga.title,
titleAlphaProvider = { if (isAnySelected) 1f else 0f },
backgroundAlphaProvider = { 1f },
hasFilters = state.filterActive, hasFilters = state.filterActive,
onBackClicked = internalOnBackPressed, navigateUp = navigateUp,
onClickFilter = onFilterButtonClicked, onClickFilter = onFilterButtonClicked,
onClickShare = onShareClicked, onClickShare = onShareClicked,
onClickDownload = onDownloadActionClicked, onClickDownload = onDownloadActionClicked,
onClickEditCategory = onEditCategoryClicked, onClickEditCategory = onEditCategoryClicked,
onClickRefresh = onRefresh, onClickRefresh = onRefresh,
onClickMigrate = onMigrateClicked, onClickMigrate = onMigrateClicked,
onCancelActionMode = { onAllChapterSelected(false) },
actionModeCounter = selectedChapterCount, actionModeCounter = selectedChapterCount,
onSelectAll = { onAllChapterSelected(true) }, onSelectAll = { onAllChapterSelected(true) },
onInvertSelection = { onInvertSelection() }, onInvertSelection = { onInvertSelection() },
titleAlphaProvider = { 1f },
backgroundAlphaProvider = { 1f },
) )
}, },
bottomBar = { bottomBar = {

View File

@ -1,18 +1,12 @@
package eu.kanade.presentation.manga.components package eu.kanade.presentation.manga.components
import androidx.compose.foundation.layout.Column
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Close
import androidx.compose.material.icons.outlined.Download import androidx.compose.material.icons.outlined.Download
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.SelectAll import androidx.compose.material.icons.outlined.SelectAll
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.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.surfaceColorAtElevation import androidx.compose.material3.surfaceColorAtElevation
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
@ -20,12 +14,12 @@ import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.draw.alpha
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.components.AppBarActions
import eu.kanade.presentation.components.AppBarTitle
import eu.kanade.presentation.components.DownloadDropdownMenu import eu.kanade.presentation.components.DownloadDropdownMenu
import eu.kanade.presentation.components.UpIcon
import eu.kanade.presentation.manga.DownloadAction import eu.kanade.presentation.manga.DownloadAction
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
@ -35,9 +29,8 @@ import tachiyomi.presentation.core.theme.active
@Composable @Composable
fun MangaToolbar( fun MangaToolbar(
title: String, title: String,
titleAlphaProvider: () -> Float,
hasFilters: Boolean, hasFilters: Boolean,
onBackClicked: () -> Unit, navigateUp: () -> Unit,
onClickFilter: () -> Unit, onClickFilter: () -> Unit,
onClickShare: (() -> Unit)?, onClickShare: (() -> Unit)?,
onClickDownload: ((DownloadAction) -> Unit)?, onClickDownload: ((DownloadAction) -> Unit)?,
@ -47,118 +40,111 @@ fun MangaToolbar(
// For action mode // For action mode
actionModeCounter: Int, actionModeCounter: Int,
onCancelActionMode: () -> Unit,
onSelectAll: () -> Unit, onSelectAll: () -> Unit,
onInvertSelection: () -> Unit, onInvertSelection: () -> Unit,
titleAlphaProvider: () -> Float,
backgroundAlphaProvider: () -> Float,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
backgroundAlphaProvider: () -> Float = titleAlphaProvider,
) { ) {
Column( val isActionMode = actionModeCounter > 0
AppBar(
titleContent = {
if (isActionMode) {
AppBarTitle(actionModeCounter.toString())
} else {
AppBarTitle(title, modifier = Modifier.alpha(titleAlphaProvider()))
}
},
modifier = modifier, modifier = modifier,
) { backgroundColor = MaterialTheme.colorScheme
val isActionMode = actionModeCounter > 0 .surfaceColorAtElevation(3.dp)
TopAppBar( .copy(alpha = if (isActionMode) 1f else backgroundAlphaProvider()),
title = { navigateUp = navigateUp,
Text( actions = {
text = if (isActionMode) actionModeCounter.toString() else title, var downloadExpanded by remember { mutableStateOf(false) }
maxLines = 1, if (onClickDownload != null) {
overflow = TextOverflow.Ellipsis, val onDismissRequest = { downloadExpanded = false }
color = LocalContentColor.current.copy(alpha = if (isActionMode) 1f else titleAlphaProvider()), DownloadDropdownMenu(
expanded = downloadExpanded,
onDismissRequest = onDismissRequest,
onDownloadClicked = onClickDownload,
) )
}, }
navigationIcon = {
IconButton(onClick = onBackClicked) { val filterTint = if (hasFilters) MaterialTheme.colorScheme.active else LocalContentColor.current
UpIcon(navigationIcon = Icons.Outlined.Close.takeIf { isActionMode }) AppBarActions(
} actions = persistentListOf<AppBar.AppBarAction>().builder().apply {
}, if (isActionMode) {
actions = { add(
if (isActionMode) {
AppBarActions(
persistentListOf(
AppBar.Action( AppBar.Action(
title = stringResource(MR.strings.action_select_all), title = stringResource(MR.strings.action_select_all),
icon = Icons.Outlined.SelectAll, icon = Icons.Outlined.SelectAll,
onClick = onSelectAll, onClick = onSelectAll,
), ),
)
add(
AppBar.Action( AppBar.Action(
title = stringResource(MR.strings.action_select_inverse), title = stringResource(MR.strings.action_select_inverse),
icon = Icons.Outlined.FlipToBack, icon = Icons.Outlined.FlipToBack,
onClick = onInvertSelection, onClick = onInvertSelection,
), ),
), )
) return@apply
} else { }
var downloadExpanded by remember { mutableStateOf(false) }
if (onClickDownload != null) { if (onClickDownload != null) {
val onDismissRequest = { downloadExpanded = false } add(
DownloadDropdownMenu( AppBar.Action(
expanded = downloadExpanded, title = stringResource(MR.strings.manga_download),
onDismissRequest = onDismissRequest, icon = Icons.Outlined.Download,
onDownloadClicked = onClickDownload, onClick = { downloadExpanded = !downloadExpanded },
),
) )
} }
add(
val filterTint = if (hasFilters) MaterialTheme.colorScheme.active else LocalContentColor.current AppBar.Action(
AppBarActions( title = stringResource(MR.strings.action_filter),
actions = persistentListOf<AppBar.AppBarAction>().builder() icon = Icons.Outlined.FilterList,
.apply { iconTint = filterTint,
if (onClickDownload != null) { onClick = onClickFilter,
add( ),
AppBar.Action(
title = stringResource(MR.strings.manga_download),
icon = Icons.Outlined.Download,
onClick = { downloadExpanded = !downloadExpanded },
),
)
}
add(
AppBar.Action(
title = stringResource(MR.strings.action_filter),
icon = Icons.Outlined.FilterList,
iconTint = filterTint,
onClick = onClickFilter,
),
)
add(
AppBar.OverflowAction(
title = stringResource(MR.strings.action_webview_refresh),
onClick = onClickRefresh,
),
)
if (onClickEditCategory != null) {
add(
AppBar.OverflowAction(
title = stringResource(MR.strings.action_edit_categories),
onClick = onClickEditCategory,
),
)
}
if (onClickMigrate != null) {
add(
AppBar.OverflowAction(
title = stringResource(MR.strings.action_migrate),
onClick = onClickMigrate,
),
)
}
if (onClickShare != null) {
add(
AppBar.OverflowAction(
title = stringResource(MR.strings.action_share),
onClick = onClickShare,
),
)
}
}
.build(),
) )
add(
AppBar.OverflowAction(
title = stringResource(MR.strings.action_webview_refresh),
onClick = onClickRefresh,
),
)
if (onClickEditCategory != null) {
add(
AppBar.OverflowAction(
title = stringResource(MR.strings.action_edit_categories),
onClick = onClickEditCategory,
),
)
}
if (onClickMigrate != null) {
add(
AppBar.OverflowAction(
title = stringResource(MR.strings.action_migrate),
onClick = onClickMigrate,
),
)
}
if (onClickShare != null) {
add(
AppBar.OverflowAction(
title = stringResource(MR.strings.action_share),
onClick = onClickShare,
),
)
}
} }
}, .build(),
colors = TopAppBarDefaults.topAppBarColors( )
containerColor = MaterialTheme.colorScheme },
.surfaceColorAtElevation(3.dp) isActionMode = isActionMode,
.copy(alpha = if (isActionMode) 1f else backgroundAlphaProvider()), onCancelActionMode = onCancelActionMode,
), )
)
}
} }

View File

@ -121,7 +121,7 @@ class MangaScreen(
isTabletUi = isTabletUi(), isTabletUi = isTabletUi(),
chapterSwipeStartAction = screenModel.chapterSwipeStartAction, chapterSwipeStartAction = screenModel.chapterSwipeStartAction,
chapterSwipeEndAction = screenModel.chapterSwipeEndAction, chapterSwipeEndAction = screenModel.chapterSwipeEndAction,
onBackClicked = navigator::pop, navigateUp = navigator::pop,
onChapterClicked = { openChapter(context, it) }, onChapterClicked = { openChapter(context, it) },
onDownloadChapter = screenModel::runChapterDownloadActions.takeIf { !successState.source.isLocalOrStub() }, onDownloadChapter = screenModel::runChapterDownloadActions.takeIf { !successState.source.isLocalOrStub() },
onAddToLibraryClicked = { onAddToLibraryClicked = {