Toggle and toolbar count
This commit is contained in:
parent
a4604809bc
commit
5c5a0f5fcf
4 changed files with 115 additions and 27 deletions
|
|
@ -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 <--
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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 <--
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in a new issue