Toggle and toolbar count

This commit is contained in:
Cuong M. Tran 2024-03-01 14:33:32 +07:00 committed by Cuong Tran
parent a4604809bc
commit 5c5a0f5fcf
No known key found for this signature in database
GPG key ID: 733AA7624B9315C2
4 changed files with 115 additions and 27 deletions

View file

@ -26,9 +26,7 @@ import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.unit.dp
import eu.kanade.presentation.browse.components.GlobalSearchCardRow
import eu.kanade.presentation.browse.components.GlobalSearchErrorResultItem
@ -159,7 +157,9 @@ fun FeedItem(
titles = item.results,
getManga = getMangaState,
onClick = onClickManga,
// KMK -->
/* KMK -->
onLongClick = onClickManga,
*/
onLongClick = onLongClickManga,
// KMK <--
)

View file

@ -2,19 +2,25 @@ package eu.kanade.presentation.components
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.calculateEndPadding
import androidx.compose.foundation.layout.calculateStartPadding
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Bookmark
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.PrimaryTabRow
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.Tab
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
@ -22,9 +28,11 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalLayoutDirection
import androidx.compose.ui.zIndex
import dev.icerock.moko.resources.StringResource
import eu.kanade.tachiyomi.ui.browse.feed.FeedScreenModel
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.coroutines.launch
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.components.material.TabText
import tachiyomi.presentation.core.i18n.stringResource
@ -36,6 +44,9 @@ fun TabbedScreen(
startIndex: Int? = null,
searchQuery: String? = null,
onChangeSearchQuery: (String?) -> Unit = {},
// KMK -->
feedScreenModel: FeedScreenModel,
// KMK <--
) {
val scope = rememberCoroutineScope()
val state = rememberPagerState { tabs.size }
@ -51,14 +62,23 @@ fun TabbedScreen(
topBar = {
val tab = tabs[state.currentPage]
val searchEnabled = tab.searchEnabled
SearchToolbar(
titleContent = { AppBarTitle(stringResource(titleRes)) },
searchEnabled = searchEnabled,
searchQuery = if (searchEnabled) searchQuery else null,
onChangeSearchQuery = onChangeSearchQuery,
actions = { AppBarActions(tab.actions) },
)
// KMK -->
val feedScreenState by feedScreenModel.state.collectAsState()
if (feedScreenState.selection.isNotEmpty())
FeedSelectionToolbar(
selectedCount = feedScreenState.selection.size,
onClickClearSelection = { feedScreenModel.clearSelection() },
actions = { AppBarActions(tab.actions) },
)
else
// KMK <--
SearchToolbar(
titleContent = { AppBarTitle(stringResource(titleRes)) },
searchEnabled = searchEnabled,
searchQuery = if (searchEnabled) searchQuery else null,
onChangeSearchQuery = onChangeSearchQuery,
actions = { AppBarActions(tab.actions) },
)
},
snackbarHost = { SnackbarHost(hostState = snackbarHostState) },
) { contentPadding ->
@ -104,3 +124,30 @@ data class TabContent(
val actions: ImmutableList<AppBar.AppBarAction> = persistentListOf(),
val content: @Composable (contentPadding: PaddingValues, snackbarHostState: SnackbarHostState) -> Unit,
)
// KMK -->
@Composable
private fun FeedSelectionToolbar(
selectedCount: Int,
onClickClearSelection: () -> Unit = {},
actions: @Composable RowScope.() -> Unit = {},
) {
AppBar(
titleContent = { Text(text = "$selectedCount") },
actions = {
AppBarActions(
persistentListOf(
AppBar.Action(
title = stringResource(MR.strings.action_bookmark),
icon = Icons.Outlined.Bookmark,
// TODO: method to add bookmark goes here
onClick = { },
),
),
)
},
isActionMode = true,
onCancelActionMode = onClickClearSelection,
)
}
// KMK <--

View file

@ -21,6 +21,7 @@ import eu.kanade.presentation.util.Tab
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.ui.browse.extension.ExtensionsScreenModel
import eu.kanade.tachiyomi.ui.browse.extension.extensionsTab
import eu.kanade.tachiyomi.ui.browse.feed.FeedScreenModel
import eu.kanade.tachiyomi.ui.browse.feed.feedTab
import eu.kanade.tachiyomi.ui.browse.migration.sources.migrateSourceTab
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchScreen
@ -65,6 +66,10 @@ data class BrowseTab(
val extensionsScreenModel = rememberScreenModel { ExtensionsScreenModel() }
val extensionsState by extensionsScreenModel.state.collectAsState()
// KMK -->
val feedScreenModel = rememberScreenModel { FeedScreenModel() }
// KMK <--
TabbedScreen(
titleRes = MR.strings.browse,
// SY -->
@ -76,7 +81,7 @@ data class BrowseTab(
)
} else if (feedTabInFront) {
persistentListOf(
feedTab(),
feedTab(/* KMK --> */feedScreenModel/* KMK <-- */),
sourcesTab(),
extensionsTab(extensionsScreenModel),
migrateSourceTab(),
@ -84,7 +89,7 @@ data class BrowseTab(
} else {
persistentListOf(
sourcesTab(),
feedTab(),
feedTab(/* KMK --> */feedScreenModel/* KMK <-- */),
extensionsTab(extensionsScreenModel),
migrateSourceTab(),
)
@ -93,6 +98,9 @@ data class BrowseTab(
// SY <--
searchQuery = extensionsState.searchQuery,
onChangeSearchQuery = extensionsScreenModel::search,
// KMK -->
feedScreenModel = feedScreenModel
// KMK <--
)
LaunchedEffect(Unit) {

View file

@ -1,7 +1,9 @@
package eu.kanade.tachiyomi.ui.browse.feed
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Bookmark
import androidx.compose.material.icons.outlined.Add
import androidx.compose.material.icons.outlined.Bookmark
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
@ -9,7 +11,6 @@ import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalHapticFeedback
import cafe.adriel.voyager.core.model.rememberScreenModel
import cafe.adriel.voyager.core.screen.Screen
import cafe.adriel.voyager.core.stack.StackEvent
import cafe.adriel.voyager.navigator.LocalNavigator
@ -31,9 +32,15 @@ import tachiyomi.i18n.sy.SYMR
import tachiyomi.presentation.core.i18n.stringResource
@Composable
fun Screen.feedTab(): TabContent {
fun Screen.feedTab(
// KMK -->
screenModel: FeedScreenModel
// KMK <--
): TabContent {
val navigator = LocalNavigator.currentOrThrow
/* KMK -->
val screenModel = rememberScreenModel { FeedScreenModel() }
KMK <-- */
val state by screenModel.state.collectAsState()
// KMK -->
val haptic = LocalHapticFeedback.current
@ -55,15 +62,32 @@ fun Screen.feedTab(): TabContent {
return TabContent(
titleRes = SYMR.strings.feed,
actions = persistentListOf(
AppBar.Action(
title = stringResource(MR.strings.action_add),
icon = Icons.Outlined.Add,
onClick = {
screenModel.openAddDialog()
},
actions =
// KMK -->
if (state.selection.isNotEmpty())
persistentListOf(
AppBar.Action(
title = stringResource(MR.strings.action_select_all),
icon = Icons.Outlined.Bookmark,
onClick = { },
),
AppBar.Action(
title = stringResource(MR.strings.action_select_inverse),
icon = Icons.Filled.Bookmark,
onClick = { },
),
)
else
// KMK <--
persistentListOf(
AppBar.Action(
title = stringResource(MR.strings.action_add),
icon = Icons.Outlined.Add,
onClick = {
screenModel.openAddDialog()
},
),
),
),
content = { contentPadding, snackbarHostState ->
FeedScreen(
state = state,
@ -94,12 +118,21 @@ fun Screen.feedTab(): TabContent {
},
onClickDelete = screenModel::openDeleteDialog,
onClickManga = { manga ->
navigator.push(MangaScreen(manga.id, true))
// KMK -->
if (state.selection.isNotEmpty())
screenModel.toggleSelection(manga)
else
// KMK <--
navigator.push(MangaScreen(manga.id, true))
},
// KMK -->
onLongClickManga = {
screenModel.toggleSelection(it)
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
onLongClickManga = { manga ->
if (state.selection.isNotEmpty()) {
navigator.push(MangaScreen(manga.id, true))
} else {
screenModel.toggleSelection(manga)
haptic.performHapticFeedback(HapticFeedbackType.LongPress)
}
},
// KMK <--
onRefresh = screenModel::init,