From ccebe08d0029abd9e0e2a305fedc895351cd8d25 Mon Sep 17 00:00:00 2001 From: Cuong-Tran Date: Tue, 25 Feb 2025 04:33:47 +0700 Subject: [PATCH] Reuse `AppBar` in manga screen (mihonapp/mihon#1367) Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com> (cherry picked from commit 2cd52d5a1ff48b0f9cf17245c1bfa66f99b8c187) --- .../kanade/presentation/components/AppBar.kt | 23 +- .../kanade/presentation/manga/MangaScreen.kt | 42 +-- .../manga/components/MangaToolbar.kt | 328 +++++++++--------- .../kanade/tachiyomi/ui/manga/MangaScreen.kt | 2 +- 4 files changed, 197 insertions(+), 198 deletions(-) diff --git a/app/src/main/java/eu/kanade/presentation/components/AppBar.kt b/app/src/main/java/eu/kanade/presentation/components/AppBar.kt index f7d16d7c9..84fd7bdf9 100644 --- a/app/src/main/java/eu/kanade/presentation/components/AppBar.kt +++ b/app/src/main/java/eu/kanade/presentation/components/AppBar.kt @@ -4,6 +4,7 @@ import androidx.compose.foundation.basicMarquee import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.size @@ -12,6 +13,7 @@ import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.outlined.ArrowBack +import androidx.compose.material.icons.filled.Home import androidx.compose.material.icons.outlined.Close import androidx.compose.material.icons.outlined.MoreVert import androidx.compose.material.icons.outlined.Search @@ -128,6 +130,10 @@ fun AppBar( isActionMode: Boolean = false, onCancelActionMode: () -> Unit = {}, + // KMK --> + goHome: (() -> Boolean?)? = null, + // KMK <-- + scrollBehavior: TopAppBarScrollBehavior? = null, ) { Column( @@ -143,10 +149,21 @@ fun AppBar( ) } } else { - navigateUp?.let { - IconButton(onClick = it) { - UpIcon(navigationIcon = navigationIcon) + // KMK --> + Row { + // KMK <-- + navigateUp?.let { + IconButton(onClick = it) { + UpIcon(navigationIcon = navigationIcon) + } } + // KMK --> + goHome?.let { + IconButton(onClick = { it.invoke() }) { + UpIcon(navigationIcon = Icons.Filled.Home) + } + } + // KMK <-- } } }, diff --git a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt index 7789c938d..03f062594 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/MangaScreen.kt @@ -145,7 +145,7 @@ fun MangaScreen( isTabletUi: Boolean, chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction, chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction, - onBackClicked: () -> Unit, + navigateUp: () -> Unit, onChapterClicked: (Chapter) -> Unit, onDownloadChapter: ((List, ChapterDownloadAction) -> Unit)?, onAddToLibraryClicked: () -> Unit, @@ -223,7 +223,7 @@ fun MangaScreen( nextUpdate = nextUpdate, chapterSwipeStartAction = chapterSwipeStartAction, chapterSwipeEndAction = chapterSwipeEndAction, - onBackClicked = onBackClicked, + navigateUp = navigateUp, onChapterClicked = onChapterClicked, onDownloadChapter = onDownloadChapter, onAddToLibraryClicked = onAddToLibraryClicked, @@ -281,7 +281,7 @@ fun MangaScreen( chapterSwipeStartAction = chapterSwipeStartAction, chapterSwipeEndAction = chapterSwipeEndAction, nextUpdate = nextUpdate, - onBackClicked = onBackClicked, + navigateUp = navigateUp, onChapterClicked = onChapterClicked, onDownloadChapter = onDownloadChapter, onAddToLibraryClicked = onAddToLibraryClicked, @@ -342,7 +342,7 @@ private fun MangaScreenSmallImpl( nextUpdate: Instant?, chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction, chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction, - onBackClicked: () -> Unit, + navigateUp: () -> Unit, onChapterClicked: (Chapter) -> Unit, onDownloadChapter: ((List, ChapterDownloadAction) -> Unit)?, onAddToLibraryClicked: () -> Unit, @@ -436,14 +436,13 @@ private fun MangaScreenSmallImpl( val readButtonPosition = uiPreferences.readButtonPosition() // KMK <-- - val internalOnBackPressed = { + BackHandler(onBack = { if (isAnySelected) { onAllChapterSelected(false) } else { - onBackClicked() + navigateUp() } - } - BackHandler(onBack = internalOnBackPressed) + }) Scaffold( topBar = { @@ -456,20 +455,18 @@ private fun MangaScreenSmallImpl( val isFirstItemScrolled by remember { derivedStateOf { chapterListState.firstVisibleItemScrollOffset > 0 } } - val animatedTitleAlpha by animateFloatAsState( + val titleAlpha by animateFloatAsState( if (!isFirstItemVisible) 1f else 0f, label = "Top Bar Title", ) - val animatedBgAlpha by animateFloatAsState( + val backgroundAlpha by animateFloatAsState( if (!isFirstItemVisible || isFirstItemScrolled) 1f else 0f, label = "Top Bar Background", ) MangaToolbar( title = state.manga.title, - titleAlphaProvider = { animatedTitleAlpha }, - backgroundAlphaProvider = { animatedBgAlpha }, hasFilters = state.filterActive, - onBackClicked = internalOnBackPressed, + navigateUp = navigateUp, onClickFilter = onFilterClicked, onClickShare = onShareClicked, onClickDownload = onDownloadActionClicked, @@ -490,8 +487,11 @@ private fun MangaScreenSmallImpl( onClickMerge = onMergeClicked.takeIf { state.showMergeInOverflow }, // SY <-- actionModeCounter = selectedChapterCount, + onCancelActionMode = { onAllChapterSelected(false) }, onSelectAll = { onAllChapterSelected(true) }, onInvertSelection = { onInvertSelection() }, + titleAlphaProvider = { titleAlpha }, + backgroundAlphaProvider = { backgroundAlpha }, // KMK --> onPaletteScreenClick = onPaletteScreenClick, // KMK <-- @@ -797,7 +797,7 @@ private fun MangaScreenLargeImpl( nextUpdate: Instant?, chapterSwipeStartAction: LibraryPreferences.ChapterSwipeAction, chapterSwipeEndAction: LibraryPreferences.ChapterSwipeAction, - onBackClicked: () -> Unit, + navigateUp: () -> Unit, onChapterClicked: (Chapter) -> Unit, onDownloadChapter: ((List, ChapterDownloadAction) -> Unit)?, onAddToLibraryClicked: () -> Unit, @@ -895,14 +895,13 @@ private fun MangaScreenLargeImpl( val chapterListState = rememberLazyListState() - val internalOnBackPressed = { + BackHandler(onBack = { if (isAnySelected) { onAllChapterSelected(false) } else { - onBackClicked() + navigateUp() } - } - BackHandler(onBack = internalOnBackPressed) + }) Scaffold( topBar = { @@ -912,16 +911,15 @@ private fun MangaScreenLargeImpl( MangaToolbar( modifier = Modifier.onSizeChanged { topBarHeight = it.height }, title = state.manga.title, - titleAlphaProvider = { if (isAnySelected) 1f else 0f }, - backgroundAlphaProvider = { 1f }, hasFilters = state.filterActive, - onBackClicked = internalOnBackPressed, + navigateUp = navigateUp, onClickFilter = onFilterButtonClicked, onClickShare = onShareClicked, onClickDownload = onDownloadActionClicked, onClickEditCategory = onEditCategoryClicked, onClickRefresh = onRefresh, onClickMigrate = onMigrateClicked, + onCancelActionMode = { onAllChapterSelected(false) }, // SY --> onClickEditInfo = onEditInfoClicked.takeIf { state.manga.favorite }, // KMK --> @@ -938,6 +936,8 @@ private fun MangaScreenLargeImpl( actionModeCounter = selectedChapterCount, onSelectAll = { onAllChapterSelected(true) }, onInvertSelection = { onInvertSelection() }, + titleAlphaProvider = { 1f }, + backgroundAlphaProvider = { 1f }, // KMK --> onPaletteScreenClick = onPaletteScreenClick, // KMK <-- diff --git a/app/src/main/java/eu/kanade/presentation/manga/components/MangaToolbar.kt b/app/src/main/java/eu/kanade/presentation/manga/components/MangaToolbar.kt index 2ec5cab66..ef7f49805 100644 --- a/app/src/main/java/eu/kanade/presentation/manga/components/MangaToolbar.kt +++ b/app/src/main/java/eu/kanade/presentation/manga/components/MangaToolbar.kt @@ -1,20 +1,12 @@ package eu.kanade.presentation.manga.components -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.Home -import androidx.compose.material.icons.outlined.Close import androidx.compose.material.icons.outlined.Download import androidx.compose.material.icons.outlined.FilterList import androidx.compose.material.icons.outlined.FlipToBack import androidx.compose.material.icons.outlined.SelectAll -import androidx.compose.material3.IconButton import androidx.compose.material3.LocalContentColor 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.runtime.Composable import androidx.compose.runtime.getValue @@ -22,14 +14,14 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.setValue 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 cafe.adriel.voyager.navigator.LocalNavigator import eu.kanade.domain.ui.UiPreferences import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBarActions +import eu.kanade.presentation.components.AppBarTitle import eu.kanade.presentation.components.DownloadDropdownMenu -import eu.kanade.presentation.components.UpIcon import eu.kanade.presentation.manga.DownloadAction import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourceScreen import eu.kanade.tachiyomi.ui.browse.source.feed.SourceFeedScreen @@ -47,9 +39,8 @@ import uy.kohesive.injekt.api.get @Composable fun MangaToolbar( title: String, - titleAlphaProvider: () -> Float, hasFilters: Boolean, - onBackClicked: () -> Unit, + navigateUp: () -> Unit, onClickFilter: () -> Unit, onClickShare: (() -> Unit)?, onClickDownload: ((DownloadAction) -> Unit)?, @@ -68,14 +59,16 @@ fun MangaToolbar( // For action mode actionModeCounter: Int, + onCancelActionMode: () -> Unit, onSelectAll: () -> Unit, onInvertSelection: () -> Unit, - modifier: Modifier = Modifier, - backgroundAlphaProvider: () -> Float = titleAlphaProvider, + titleAlphaProvider: () -> Float, + backgroundAlphaProvider: () -> Float, // KMK --> onPaletteScreenClick: () -> Unit, // KMK <-- + modifier: Modifier = Modifier, ) { // KMK --> val navigator = LocalNavigator.current @@ -84,180 +77,169 @@ fun MangaToolbar( } val isHomeEnabled = Injekt.get().showHomeOnRelatedMangas().get() // KMK <-- - Column( + + val isActionMode = actionModeCounter > 0 + AppBar( + titleContent = { + if (isActionMode) { + AppBarTitle(actionModeCounter.toString()) + } else { + AppBarTitle(title, modifier = Modifier.alpha(titleAlphaProvider())) + } + }, modifier = modifier, - ) { - val isActionMode = actionModeCounter > 0 - TopAppBar( - title = { - Text( - text = if (isActionMode) actionModeCounter.toString() else title, - maxLines = 1, - overflow = TextOverflow.Ellipsis, - color = LocalContentColor.current.copy(alpha = if (isActionMode) 1f else titleAlphaProvider()), + backgroundColor = MaterialTheme.colorScheme + .surfaceColorAtElevation(3.dp) + .copy(alpha = if (isActionMode) 1f else backgroundAlphaProvider()), + // KMK --> + goHome = { onHomeClicked() }.takeIf { + isHomeEnabled && + navigator != null && + ( + navigator.size >= 2 && + navigator.items[navigator.size - 2] is MangaScreen || + navigator.size >= 5 + ) + }, + // KMK <-- + navigateUp = navigateUp, + actions = { + var downloadExpanded by remember { mutableStateOf(false) } + if (onClickDownload != null) { + val onDismissRequest = { downloadExpanded = false } + DownloadDropdownMenu( + expanded = downloadExpanded, + onDismissRequest = onDismissRequest, + onDownloadClicked = onClickDownload, ) - }, - navigationIcon = { - Row { - IconButton(onClick = onBackClicked) { - UpIcon(navigationIcon = Icons.Outlined.Close.takeIf { isActionMode }) - } - // KMK --> - if (isHomeEnabled && navigator != null) { - if (navigator.size >= 2 && - navigator.items[navigator.size - 2] is MangaScreen || - navigator.size >= 5 - ) { - IconButton(onClick = { onHomeClicked() }) { - UpIcon(navigationIcon = Icons.Filled.Home) - } - } - } - // KMK <-- - } - }, - actions = { - if (isActionMode) { - AppBarActions( - persistentListOf( + } + + val filterTint = if (hasFilters) MaterialTheme.colorScheme.active else LocalContentColor.current + AppBarActions( + actions = persistentListOf().builder().apply { + if (isActionMode) { + add( AppBar.Action( title = stringResource(MR.strings.action_select_all), icon = Icons.Outlined.SelectAll, onClick = onSelectAll, ), + ) + add( AppBar.Action( title = stringResource(MR.strings.action_select_inverse), icon = Icons.Outlined.FlipToBack, onClick = onInvertSelection, ), - ), - ) - } else { - var downloadExpanded by remember { mutableStateOf(false) } + ) + return@apply + } if (onClickDownload != null) { - val onDismissRequest = { downloadExpanded = false } - DownloadDropdownMenu( - expanded = downloadExpanded, - onDismissRequest = onDismissRequest, - onDownloadClicked = onClickDownload, + add( + AppBar.Action( + title = stringResource(MR.strings.manga_download), + icon = Icons.Outlined.Download, + onClick = { downloadExpanded = !downloadExpanded }, + ), ) } - - val filterTint = if (hasFilters) MaterialTheme.colorScheme.active else LocalContentColor.current - AppBarActions( - actions = persistentListOf().builder() - .apply { - if (onClickDownload != null) { - 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, - ), - ) - } - // SY --> - if (onClickMerge != null) { - add( - AppBar.OverflowAction( - title = stringResource(SYMR.strings.merge), - onClick = onClickMerge, - ), - ) - } - if (onClickEditInfo != null) { - add( - AppBar.OverflowAction( - title = stringResource(SYMR.strings.action_edit_info), - onClick = onClickEditInfo, - ), - ) - } - // KMK --> - if (onClickRelatedMangas != null) { - add( - AppBar.OverflowAction( - title = stringResource(KMR.strings.pref_source_related_mangas), - onClick = onClickRelatedMangas, - ), - ) - } - // KMK <-- - if (onClickRecommend != null) { - add( - AppBar.OverflowAction( - title = stringResource(SYMR.strings.az_recommends), - onClick = onClickRecommend, - ), - ) - } - if (onClickMergedSettings != null) { - add( - AppBar.OverflowAction( - title = stringResource(SYMR.strings.merge_settings), - onClick = onClickMergedSettings, - ), - ) - } - // SY <-- - // KMK --> - if (isDevFlavor) { - add( - AppBar.OverflowAction( - title = "Colors Palette", - onClick = onPaletteScreenClick, - ), - ) - } - // KMK <-- - } - .build(), + 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, + ), + ) + } + // SY --> + if (onClickMerge != null) { + add( + AppBar.OverflowAction( + title = stringResource(SYMR.strings.merge), + onClick = onClickMerge, + ), + ) + } + if (onClickEditInfo != null) { + add( + AppBar.OverflowAction( + title = stringResource(SYMR.strings.action_edit_info), + onClick = onClickEditInfo, + ), + ) + } + // KMK --> + if (onClickRelatedMangas != null) { + add( + AppBar.OverflowAction( + title = stringResource(KMR.strings.pref_source_related_mangas), + onClick = onClickRelatedMangas, + ), + ) + } + // KMK <-- + if (onClickRecommend != null) { + add( + AppBar.OverflowAction( + title = stringResource(SYMR.strings.az_recommends), + onClick = onClickRecommend, + ), + ) + } + if (onClickMergedSettings != null) { + add( + AppBar.OverflowAction( + title = stringResource(SYMR.strings.merge_settings), + onClick = onClickMergedSettings, + ), + ) + } + // SY <-- + // KMK --> + if (isDevFlavor) { + add( + AppBar.OverflowAction( + title = "Colors Palette", + onClick = onPaletteScreenClick, + ), + ) + } + // KMK <-- } - }, - colors = TopAppBarDefaults.topAppBarColors( - containerColor = MaterialTheme.colorScheme - .surfaceColorAtElevation(3.dp) - .copy(alpha = if (isActionMode) 1f else backgroundAlphaProvider()), - ), - ) - } + .build(), + ) + }, + isActionMode = isActionMode, + onCancelActionMode = onCancelActionMode, + ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt index b665dcb61..1b7d88ab7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreen.kt @@ -279,7 +279,7 @@ class MangaScreen( isTabletUi = isTabletUi(), chapterSwipeStartAction = screenModel.chapterSwipeStartAction, chapterSwipeEndAction = screenModel.chapterSwipeEndAction, - onBackClicked = navigator::pop, + navigateUp = navigator::pop, onChapterClicked = { openChapter(context, it) }, onDownloadChapter = screenModel::runChapterDownloadActions.takeIf { !successState.source.isLocalOrStub() }, onAddToLibraryClicked = {