From a4604809bc6ae48491e30051e9600aef8790e756 Mon Sep 17 00:00:00 2001 From: "Cuong M. Tran" Date: Thu, 29 Feb 2024 18:36:57 +0700 Subject: [PATCH] selection list & toggleSelection/clearSelection --- .../kanade/presentation/browse/FeedScreen.kt | 15 +++++++++++- .../ui/browse/feed/FeedScreenModel.kt | 24 +++++++++++++++++++ .../tachiyomi/ui/browse/feed/FeedTab.kt | 11 +++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) 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 9d77b94e0..8c978e71b 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/FeedScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/FeedScreen.kt @@ -26,7 +26,9 @@ 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 @@ -69,6 +71,9 @@ fun FeedScreen( onClickSource: (CatalogueSource) -> Unit, onClickDelete: (FeedSavedSearch) -> Unit, onClickManga: (Manga) -> Unit, + // KMK --> + onLongClickManga: (Manga) -> Unit, + // KMK <-- onRefresh: () -> Unit, getMangaState: @Composable (Manga, CatalogueSource?) -> State, ) { @@ -121,6 +126,9 @@ fun FeedScreen( item = item, getMangaState = { getMangaState(it, item.source) }, onClickManga = onClickManga, + // KMK --> + onLongClickManga = onLongClickManga, + // KMK <-- ) } } @@ -135,6 +143,9 @@ fun FeedItem( item: FeedItemUI, getMangaState: @Composable ((Manga) -> State), onClickManga: (Manga) -> Unit, + // KMK --> + onLongClickManga: (Manga) -> Unit, + // KMK <-- ) { when { item.results == null -> { @@ -148,7 +159,9 @@ fun FeedItem( titles = item.results, getManga = getMangaState, onClick = onClickManga, - onLongClick = onClickManga, + // KMK --> + onLongClick = onLongClickManga, + // KMK <-- ) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/feed/FeedScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/feed/FeedScreenModel.kt index 8197def21..7e86fc8cc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/feed/FeedScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/feed/FeedScreenModel.kt @@ -14,6 +14,8 @@ import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.util.system.LocaleHelper import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.mutate import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.asCoroutineDispatcher @@ -305,6 +307,25 @@ open class FeedScreenModel( mutableState.update { it.copy(dialog = null) } } + // KMK --> + fun clearSelection() { + mutableState.update { it.copy(selection = persistentListOf()) } + } + + fun toggleSelection(manga: DomainManga) { + mutableState.update { state -> + val newSelection = state.selection.mutate { list -> + if (list.fastAny { it.id == manga.id }) { + list.removeAll { it.id == manga.id } + } else { + list.add(manga) + } + } + state.copy(selection = newSelection) + } + } + // KMK <-- + sealed class Dialog { data class AddFeed(val options: ImmutableList) : Dialog() data class AddFeedSearch(val source: CatalogueSource, val options: ImmutableList) : Dialog() @@ -320,6 +341,9 @@ open class FeedScreenModel( data class FeedScreenState( val dialog: FeedScreenModel.Dialog? = null, val items: List? = null, + // KMK --> + val selection: PersistentList = persistentListOf(), + // KMK <-- ) { val isLoading get() = items == null 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 ba9300c86..3649cacab 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 @@ -7,6 +7,8 @@ import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect 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 @@ -33,6 +35,9 @@ fun Screen.feedTab(): TabContent { val navigator = LocalNavigator.currentOrThrow val screenModel = rememberScreenModel { FeedScreenModel() } val state by screenModel.state.collectAsState() + // KMK --> + val haptic = LocalHapticFeedback.current + // KMK <-- DisposableEffect(navigator.lastEvent) { if (navigator.lastEvent == StackEvent.Push) { @@ -91,6 +96,12 @@ fun Screen.feedTab(): TabContent { onClickManga = { manga -> navigator.push(MangaScreen(manga.id, true)) }, + // KMK --> + onLongClickManga = { + screenModel.toggleSelection(it) + haptic.performHapticFeedback(HapticFeedbackType.LongPress) + }, + // KMK <-- onRefresh = screenModel::init, getMangaState = { manga, source -> screenModel.getManga(initialManga = manga, source = source) }, )