diff --git a/app/src/main/java/eu/kanade/presentation/browse/FeedScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/FeedScreen.kt index 8c978e71b..47275d45d 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/FeedScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/FeedScreen.kt @@ -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 <-- ) diff --git a/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt b/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt index efb1e2e04..0bd32c924 100644 --- a/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/components/TabbedScreen.kt @@ -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 = 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 <-- diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseTab.kt index 20c9e79d6..1a7644fb2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/BrowseTab.kt @@ -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) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/feed/FeedTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/feed/FeedTab.kt index 3649cacab..b4488631d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/feed/FeedTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/feed/FeedTab.kt @@ -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,