From af77a962c1ed902eb328bfb49818c88cdc597d08 Mon Sep 17 00:00:00 2001 From: Cuong-Tran Date: Sun, 26 Jan 2025 01:56:11 +0700 Subject: [PATCH] Drag to reorder feeds (#660) --- .../presentation/browse/FeedOrderScreen.kt | 57 +++++++++++++------ .../kanade/presentation/browse/FeedScreen.kt | 16 ++---- .../browse/SourceFeedOrderScreen.kt | 51 +++++++++++------ .../presentation/browse/SourceFeedScreen.kt | 18 +++--- .../browse/components/FeedOrderListItem.kt | 51 +++-------------- .../browse/components/SourceFeedDialogs.kt | 37 ------------ .../category/components/CategoryListItem.kt | 1 - .../ui/browse/feed/FeedScreenModel.kt | 17 +----- .../tachiyomi/ui/browse/feed/FeedTab.kt | 7 +-- .../ui/browse/source/feed/SourceFeedScreen.kt | 7 +-- .../source/feed/SourceFeedScreenModel.kt | 16 +----- .../category/interactor/HideCategory.kt | 2 +- .../domain/source/interactor/ReorderFeed.kt | 19 +------ .../source/model/FeedSavedSearchUpdate.kt | 2 + 14 files changed, 108 insertions(+), 193 deletions(-) diff --git a/app/src/main/java/eu/kanade/presentation/browse/FeedOrderScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/FeedOrderScreen.kt index 723083d45..eeadabcf4 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/FeedOrderScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/FeedOrderScreen.kt @@ -3,13 +3,20 @@ package eu.kanade.presentation.browse import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import eu.kanade.presentation.browse.components.FeedOrderListItem import eu.kanade.tachiyomi.ui.browse.feed.FeedScreenState +import sh.calvin.reorderable.ReorderableItem +import sh.calvin.reorderable.rememberReorderableLazyListState import tachiyomi.domain.source.model.FeedSavedSearch import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.padding @@ -22,39 +29,53 @@ import tachiyomi.presentation.core.util.plus fun FeedOrderScreen( state: FeedScreenState, onClickDelete: (FeedSavedSearch) -> Unit, - onClickMoveUp: (FeedSavedSearch) -> Unit, - onClickMoveDown: (FeedSavedSearch) -> Unit, + changeOrder: (FeedSavedSearch, Int) -> Unit, ) { when { state.isLoading -> LoadingScreen() - state.isEmpty -> EmptyScreen( + state.isEmpty || state.items.isNullOrEmpty() -> EmptyScreen( stringRes = MR.strings.empty_screen, ) else -> { val lazyListState = rememberLazyListState() - val feeds = state.items ?: emptyList() + val feeds = state.items + + var reorderableList by remember { mutableStateOf(feeds) } + val reorderableLazyColumnState = rememberReorderableLazyListState(lazyListState) { from, to -> + reorderableList = reorderableList.toMutableList().apply { + changeOrder(reorderableList[from.index].feed, to.index - from.index) + add(to.index, removeAt(from.index)) + } + } + + LaunchedEffect(feeds) { + if (!reorderableLazyColumnState.isAnyItemDragging) { + reorderableList = feeds + } + } + LazyColumn( state = lazyListState, contentPadding = topSmallPaddingValues + PaddingValues(horizontal = MaterialTheme.padding.medium), verticalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small), ) { - itemsIndexed( - items = feeds, - key = { _, feed -> "feed-${feed.feed.id}" }, - ) { index, feed -> - FeedOrderListItem( - modifier = Modifier.animateItem(), - title = feed.title, - canMoveUp = index != 0, - canMoveDown = index != feeds.lastIndex, - onMoveUp = { onClickMoveUp(feed.feed) }, - onMoveDown = { onClickMoveDown(feed.feed) }, - onDelete = { onClickDelete(feed.feed) }, - ) + items( + items = reorderableList, + key = { it.feed.key }, + ) { feed -> + ReorderableItem(reorderableLazyColumnState, feed.feed.key) { + FeedOrderListItem( + modifier = Modifier.animateItem(), + title = feed.title, + onDelete = { onClickDelete(feed.feed) }, + ) + } } } } } } + +internal val FeedSavedSearch.key get() = "feed-$id" 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 a55773205..494a64925 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/FeedScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/FeedScreen.kt @@ -11,7 +11,7 @@ import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width -import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll import androidx.compose.material3.AlertDialog @@ -75,7 +75,7 @@ fun FeedScreen( onClickSavedSearch: (SavedSearch, CatalogueSource) -> Unit, onClickSource: (CatalogueSource) -> Unit, // KMK --> - onLongClickFeed: (FeedItemUI, Boolean, Boolean) -> Unit, + onLongClickFeed: (FeedItemUI) -> Unit, // KMK <-- onClickManga: (Manga) -> Unit, // KMK --> @@ -113,21 +113,17 @@ fun FeedScreen( ) { // KMK --> val feeds = state.items.orEmpty() - itemsIndexed( + items( items = feeds, - key = { _, it -> "feed-${it.feed.id}" }, - ) { index, item -> + key = { it.feed.key }, + ) { item -> // KMK <-- GlobalSearchResultItem( title = item.title, subtitle = item.subtitle, onLongClick = { // KMK --> - onLongClickFeed( - item, - index != 0, - index != feeds.lastIndex, - ) + onLongClickFeed(item) // KMK <-- }, onClick = { diff --git a/app/src/main/java/eu/kanade/presentation/browse/SourceFeedOrderScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/SourceFeedOrderScreen.kt index 637c61450..58a33e21d 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/SourceFeedOrderScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/SourceFeedOrderScreen.kt @@ -3,18 +3,25 @@ package eu.kanade.presentation.browse import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.SortByAlpha import androidx.compose.material3.MaterialTheme import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import eu.kanade.presentation.browse.components.FeedOrderListItem import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBarTitle import eu.kanade.tachiyomi.ui.browse.source.feed.SourceFeedState import kotlinx.collections.immutable.persistentListOf +import sh.calvin.reorderable.ReorderableItem +import sh.calvin.reorderable.rememberReorderableLazyListState import tachiyomi.domain.source.model.FeedSavedSearch import tachiyomi.i18n.MR import tachiyomi.i18n.kmk.KMR @@ -30,8 +37,7 @@ import tachiyomi.presentation.core.util.plus fun SourceFeedOrderScreen( state: SourceFeedState, onClickDelete: (FeedSavedSearch) -> Unit, - onClickMoveUp: (FeedSavedSearch) -> Unit, - onClickMoveDown: (FeedSavedSearch) -> Unit, + changeOrder: (FeedSavedSearch, Int) -> Unit, onClickSortAlphabetically: () -> Unit, navigateUp: (() -> Unit)? = null, ) { @@ -68,25 +74,38 @@ fun SourceFeedOrderScreen( val lazyListState = rememberLazyListState() val feeds = state.items .filterIsInstance() + + var reorderableList by remember { mutableStateOf(feeds) } + val reorderableLazyColumnState = rememberReorderableLazyListState(lazyListState) { from, to -> + reorderableList = reorderableList.toMutableList().apply { + changeOrder(reorderableList[from.index].feed, to.index - from.index) + add(to.index, removeAt(from.index)) + } + } + + LaunchedEffect(feeds) { + if (!reorderableLazyColumnState.isAnyItemDragging) { + reorderableList = feeds + } + } + LazyColumn( state = lazyListState, contentPadding = paddingValues + topSmallPaddingValues + PaddingValues(horizontal = MaterialTheme.padding.medium), verticalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small), ) { - itemsIndexed( - items = feeds, - key = { _, feed -> "feed-${feed.feed.id}" }, - ) { index, feed -> - FeedOrderListItem( - modifier = Modifier.animateItem(), - title = feed.title, - canMoveUp = index != 0, - canMoveDown = index != feeds.lastIndex, - onMoveUp = { onClickMoveUp(feed.feed) }, - onMoveDown = { onClickMoveDown(feed.feed) }, - onDelete = { onClickDelete(feed.feed) }, - ) + items( + items = reorderableList, + key = { it.feed.key }, + ) { feed -> + ReorderableItem(reorderableLazyColumnState, feed.feed.key) { + FeedOrderListItem( + modifier = Modifier.animateItem(), + title = feed.title, + onDelete = { onClickDelete(feed.feed) }, + ) + } } } } diff --git a/app/src/main/java/eu/kanade/presentation/browse/SourceFeedScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/SourceFeedScreen.kt index e1ea7441b..f9f69722c 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/SourceFeedScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/SourceFeedScreen.kt @@ -2,7 +2,7 @@ package eu.kanade.presentation.browse import androidx.compose.animation.Crossfade import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.foundation.lazy.items import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Public import androidx.compose.material3.TopAppBarScrollBehavior @@ -94,7 +94,7 @@ fun SourceFeedScreen( onClickSavedSearch: (SavedSearch) -> Unit, // KMK --> // onClickDelete: (FeedSavedSearch) -> Unit, - onLongClickFeed: (SourceFeedUI.SourceSavedSearch, Boolean, Boolean) -> Unit, + onLongClickFeed: (SourceFeedUI.SourceSavedSearch) -> Unit, // KMK <-- onClickManga: (Manga) -> Unit, onClickSearch: (String) -> Unit, @@ -200,7 +200,7 @@ fun SourceFeedList( onClickSavedSearch: (SavedSearch) -> Unit, // KMK --> // onClickDelete: (FeedSavedSearch) -> Unit, - onLongClickFeed: (SourceFeedUI.SourceSavedSearch, Boolean, Boolean) -> Unit, + onLongClickFeed: (SourceFeedUI.SourceSavedSearch) -> Unit, // KMK <-- onClickManga: (Manga) -> Unit, // KMK --> @@ -212,10 +212,10 @@ fun SourceFeedList( contentPadding = paddingValues + topSmallPaddingValues, ) { // KMK --> - itemsIndexed( + items( items, - key = { _, it -> "source-feed-${it.id}" }, - ) { index, item -> + key = { "source-feed-${it.id}" }, + ) { item -> // KMK <-- GlobalSearchResultItem( modifier = Modifier.animateItem(), @@ -231,11 +231,7 @@ fun SourceFeedList( onLongClick = if (item is SourceFeedUI.SourceSavedSearch) { { // KMK --> - onLongClickFeed( - item, - index != items.size - items.filterIsInstance().size, - index != items.lastIndex, - ) + onLongClickFeed(item) // KMK <-- } } else { diff --git a/app/src/main/java/eu/kanade/presentation/browse/components/FeedOrderListItem.kt b/app/src/main/java/eu/kanade/presentation/browse/components/FeedOrderListItem.kt index ebba5a22c..d4e46b0a8 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/components/FeedOrderListItem.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/components/FeedOrderListItem.kt @@ -1,14 +1,11 @@ package eu.kanade.presentation.browse.components import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.ArrowDropDown -import androidx.compose.material.icons.outlined.ArrowDropUp import androidx.compose.material.icons.outlined.Delete -import androidx.compose.material.icons.outlined.Splitscreen +import androidx.compose.material.icons.outlined.DragHandle import androidx.compose.material3.ElevatedCard import androidx.compose.material3.Icon import androidx.compose.material3.IconButton @@ -17,18 +14,14 @@ import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.tooling.preview.Preview +import sh.calvin.reorderable.ReorderableCollectionItemScope import tachiyomi.i18n.MR import tachiyomi.presentation.core.components.material.padding import tachiyomi.presentation.core.i18n.stringResource @Composable -fun FeedOrderListItem( +fun ReorderableCollectionItemScope.FeedOrderListItem( title: String, - canMoveUp: Boolean, - canMoveDown: Boolean, - onMoveUp: () -> Unit, - onMoveDown: () -> Unit, onDelete: () -> Unit, modifier: Modifier = Modifier, ) { @@ -39,52 +32,26 @@ fun FeedOrderListItem( modifier = Modifier .fillMaxWidth() .padding( - start = MaterialTheme.padding.medium, - top = MaterialTheme.padding.medium, + start = MaterialTheme.padding.small, end = MaterialTheme.padding.medium, ), verticalAlignment = Alignment.CenterVertically, ) { Icon( - imageVector = Icons.Outlined.Splitscreen, + imageVector = Icons.Outlined.DragHandle, contentDescription = null, + modifier = Modifier + .padding(MaterialTheme.padding.medium) + .draggableHandle(), ) Text( text = title, modifier = Modifier - .padding(start = MaterialTheme.padding.medium), + .weight(1f), ) - } - Row { - IconButton( - onClick = onMoveUp, - enabled = canMoveUp, - ) { - Icon(imageVector = Icons.Outlined.ArrowDropUp, contentDescription = null) - } - IconButton( - onClick = onMoveDown, - enabled = canMoveDown, - ) { - Icon(imageVector = Icons.Outlined.ArrowDropDown, contentDescription = null) - } - Spacer(modifier = Modifier.weight(1f)) IconButton(onClick = onDelete) { Icon(imageVector = Icons.Outlined.Delete, contentDescription = stringResource(MR.strings.action_delete)) } } } } - -@Preview -@Composable -private fun FeedOrderListItemPreview() { - FeedOrderListItem( - title = "Feed 1", - canMoveUp = true, - canMoveDown = true, - onMoveUp = {}, - onMoveDown = {}, - onDelete = {}, - ) -} diff --git a/app/src/main/java/eu/kanade/presentation/browse/components/SourceFeedDialogs.kt b/app/src/main/java/eu/kanade/presentation/browse/components/SourceFeedDialogs.kt index f16b850dc..8e227b141 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/components/SourceFeedDialogs.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/components/SourceFeedDialogs.kt @@ -11,11 +11,8 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.sizeIn import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.ArrowDownward -import androidx.compose.material.icons.outlined.ArrowUpward import androidx.compose.material.icons.outlined.Delete import androidx.compose.material3.AlertDialog -import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedButton import androidx.compose.material3.Text @@ -99,12 +96,8 @@ private val TitlePadding = PaddingValues(bottom = 16.dp, top = 8.dp) fun FeedActionsDialog( feed: FeedSavedSearch, title: String, - canMoveUp: Boolean, - canMoveDown: Boolean, onDismissRequest: () -> Unit, onClickDelete: (FeedSavedSearch) -> Unit, - onMoveUp: (FeedSavedSearch) -> Unit, - onMoveDown: (FeedSavedSearch) -> Unit, modifier: Modifier = Modifier, ) { val minHeight = LocalPreferenceMinHeight.current @@ -129,32 +122,6 @@ fun FeedActionsDialog( Spacer(Modifier.height(PaddingSize)) - if (canMoveUp) { - TextPreferenceWidget( - title = stringResource(KMR.strings.action_move_up), - icon = Icons.Outlined.ArrowUpward, - onPreferenceClick = { - onDismissRequest() - onMoveUp(feed) - }, - ) - - HorizontalDivider() - } - - if (canMoveDown) { - TextPreferenceWidget( - title = stringResource(KMR.strings.action_move_down), - icon = Icons.Outlined.ArrowDownward, - onPreferenceClick = { - onDismissRequest() - onMoveDown(feed) - }, - ) - - HorizontalDivider() - } - TextPreferenceWidget( title = stringResource(MR.strings.action_delete), icon = Icons.Outlined.Delete, @@ -200,12 +167,8 @@ private fun FeedActionsDialogPreview() { feedOrder = 0, ), title = "Feed 1", - canMoveUp = true, - canMoveDown = true, onDismissRequest = { }, onClickDelete = { }, - onMoveUp = { }, - onMoveDown = { }, ) } diff --git a/app/src/main/java/eu/kanade/presentation/category/components/CategoryListItem.kt b/app/src/main/java/eu/kanade/presentation/category/components/CategoryListItem.kt index c3e9b0853..b4e08785a 100644 --- a/app/src/main/java/eu/kanade/presentation/category/components/CategoryListItem.kt +++ b/app/src/main/java/eu/kanade/presentation/category/components/CategoryListItem.kt @@ -44,7 +44,6 @@ fun ReorderableCollectionItemScope.CategoryListItem( modifier = Modifier .fillMaxWidth() .clickable { onRename() } - .padding(vertical = MaterialTheme.padding.small) .padding( start = MaterialTheme.padding.small, end = MaterialTheme.padding.medium, 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 6385c6394..635c4bec0 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 @@ -24,7 +24,6 @@ import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.receiveAsFlow import kotlinx.coroutines.flow.update @@ -161,16 +160,12 @@ open class FeedScreenModel( // KMK --> fun openActionsDialog( feed: FeedItemUI, - canMoveUp: Boolean, - canMoveDown: Boolean, ) { screenModelScope.launchIO { mutableState.update { state -> state.copy( dialog = Dialog.FeedActions( feedItem = feed, - canMoveUp = canMoveUp, - canMoveDown = canMoveDown, ), ) } @@ -221,15 +216,9 @@ open class FeedScreenModel( } // KMK --> - fun moveUp(feed: FeedSavedSearch) { + fun changeOrder(feed: FeedSavedSearch, newOrder: Int) { screenModelScope.launch { - reorderFeed.moveUp(feed) - } - } - - fun moveDown(feed: FeedSavedSearch) { - screenModelScope.launch { - reorderFeed.moveDown(feed) + reorderFeed.changeOrder(feed, newOrder) } } @@ -392,8 +381,6 @@ open class FeedScreenModel( // KMK --> data class FeedActions( val feedItem: FeedItemUI, - val canMoveUp: Boolean, - val canMoveDown: Boolean, ) : Dialog() data object SortAlphabetically : Dialog() 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 864427918..f3611311a 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 @@ -142,8 +142,7 @@ fun feedTab( FeedOrderScreen( state = state, onClickDelete = screenModel::openDeleteDialog, - onClickMoveUp = screenModel::moveUp, - onClickMoveDown = screenModel::moveDown, + changeOrder = screenModel::changeOrder, ) } else { // KMK <-- @@ -249,12 +248,8 @@ fun feedTab( FeedActionsDialog( feed = dialog.feedItem.feed, title = dialog.feedItem.title, - canMoveUp = dialog.canMoveUp, - canMoveDown = dialog.canMoveDown, onDismissRequest = onDismissRequest, onClickDelete = { screenModel.openDeleteDialog(it) }, - onMoveUp = { screenModel.moveUp(it) }, - onMoveDown = { screenModel.moveDown(it) }, ) } is FeedScreenModel.Dialog.SortAlphabetically -> { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedScreen.kt index 8bb9f5523..600280645 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedScreen.kt @@ -105,8 +105,7 @@ class SourceFeedScreen(val sourceId: Long) : Screen() { SourceFeedOrderScreen( state = state, onClickDelete = screenModel::openDeleteFeed, - onClickMoveUp = screenModel::moveUp, - onClickMoveDown = screenModel::moveDown, + changeOrder = screenModel::changeOrder, onClickSortAlphabetically = { screenModel.showDialog(SourceFeedScreenModel.Dialog.SortAlphabetically) }, @@ -221,12 +220,8 @@ class SourceFeedScreen(val sourceId: Long) : Screen() { FeedActionsDialog( feed = dialog.feedItem.feed, title = dialog.feedItem.title, - canMoveUp = dialog.canMoveUp, - canMoveDown = dialog.canMoveDown, onDismissRequest = screenModel::dismissDialog, onClickDelete = { screenModel.openDeleteFeed(it) }, - onMoveUp = { screenModel.moveUp(it) }, - onMoveDown = { screenModel.moveDown(it) }, ) } is SourceFeedScreenModel.Dialog.SortAlphabetically -> { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedScreenModel.kt index 23d3cda84..5b6447848 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/feed/SourceFeedScreenModel.kt @@ -156,15 +156,9 @@ open class SourceFeedScreenModel( } // KMK --> - fun moveUp(feed: FeedSavedSearch) { + fun changeOrder(feed: FeedSavedSearch, newOrder: Int) { screenModelScope.launch { - reorderFeed.moveUp(feed, false) - } - } - - fun moveDown(feed: FeedSavedSearch) { - screenModelScope.launch { - reorderFeed.moveDown(feed, false) + reorderFeed.changeOrder(feed, newOrder, false) } } @@ -391,16 +385,12 @@ open class SourceFeedScreenModel( // KMK --> fun openActionsDialog( feed: SourceFeedUI.SourceSavedSearch, - canMoveUp: Boolean, - canMoveDown: Boolean, ) { screenModelScope.launchIO { mutableState.update { state -> state.copy( dialog = Dialog.FeedActions( feedItem = feed, - canMoveUp = canMoveUp, - canMoveDown = canMoveDown, ), ) } @@ -432,8 +422,6 @@ open class SourceFeedScreenModel( // KMK --> data class FeedActions( val feedItem: SourceFeedUI.SourceSavedSearch, - val canMoveUp: Boolean, - val canMoveDown: Boolean, ) : Dialog() data object SortAlphabetically : Dialog() diff --git a/domain/src/main/java/tachiyomi/domain/category/interactor/HideCategory.kt b/domain/src/main/java/tachiyomi/domain/category/interactor/HideCategory.kt index d47335a6a..5ab46a7c8 100644 --- a/domain/src/main/java/tachiyomi/domain/category/interactor/HideCategory.kt +++ b/domain/src/main/java/tachiyomi/domain/category/interactor/HideCategory.kt @@ -27,7 +27,7 @@ class HideCategory( } sealed class Result { - object Success : Result() + data object Success : Result() data class InternalError(val error: Throwable) : Result() } } diff --git a/domain/src/main/java/tachiyomi/domain/source/interactor/ReorderFeed.kt b/domain/src/main/java/tachiyomi/domain/source/interactor/ReorderFeed.kt index a7d533bbe..bd1ae9b32 100644 --- a/domain/src/main/java/tachiyomi/domain/source/interactor/ReorderFeed.kt +++ b/domain/src/main/java/tachiyomi/domain/source/interactor/ReorderFeed.kt @@ -8,7 +8,6 @@ import tachiyomi.core.common.util.system.logcat import tachiyomi.domain.source.model.FeedSavedSearch import tachiyomi.domain.source.model.FeedSavedSearchUpdate import tachiyomi.domain.source.repository.FeedSavedSearchRepository -import java.util.Collections class ReorderFeed( private val feedSavedSearchRepository: FeedSavedSearchRepository, @@ -16,11 +15,7 @@ class ReorderFeed( private val mutex = Mutex() - suspend fun moveUp(feed: FeedSavedSearch, global: Boolean = true): Result = awaitGlobal(feed, MoveTo.UP, global) - - suspend fun moveDown(feed: FeedSavedSearch, global: Boolean = true): Result = awaitGlobal(feed, MoveTo.DOWN, global) - - private suspend fun awaitGlobal(feed: FeedSavedSearch, moveTo: MoveTo, global: Boolean = true) = withNonCancellableContext { + suspend fun changeOrder(feed: FeedSavedSearch, newOrder: Int, global: Boolean = true) = withNonCancellableContext { mutex.withLock { val feeds = if (global) { feedSavedSearchRepository.getGlobal() @@ -35,13 +30,10 @@ class ReorderFeed( return@withNonCancellableContext Result.Unchanged } - val newPosition = when (moveTo) { - MoveTo.UP -> currentIndex - 1 - MoveTo.DOWN -> currentIndex + 1 - }.toInt() + val newPosition = currentIndex + newOrder try { - Collections.swap(feeds, currentIndex, newPosition) + feeds.add(newPosition, feeds.removeAt(currentIndex)) val updates = feeds.mapIndexed { index, feed -> FeedSavedSearchUpdate( @@ -77,9 +69,4 @@ class ReorderFeed( data object Unchanged : Result data class InternalError(val error: Throwable) : Result } - - private enum class MoveTo { - UP, - DOWN, - } } diff --git a/domain/src/main/java/tachiyomi/domain/source/model/FeedSavedSearchUpdate.kt b/domain/src/main/java/tachiyomi/domain/source/model/FeedSavedSearchUpdate.kt index 95bafd4f3..a16b7ea5a 100644 --- a/domain/src/main/java/tachiyomi/domain/source/model/FeedSavedSearchUpdate.kt +++ b/domain/src/main/java/tachiyomi/domain/source/model/FeedSavedSearchUpdate.kt @@ -12,5 +12,7 @@ data class FeedSavedSearchUpdate( // If the feed is a global (FeedScreen) or source specific feed (SourceFeedScreen) val global: Boolean? = null, + + // Local index in global feed if it's a global one or in source feed if it's a source one val feedOrder: Long? = null, )