Drag to reorder feeds (#660)
This commit is contained in:
parent
5b775366b8
commit
af77a962c1
14 changed files with 108 additions and 193 deletions
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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<SourceFeedUI.SourceSavedSearch>()
|
||||
|
||||
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) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<SourceFeedUI.SourceSavedSearch>().size,
|
||||
index != items.lastIndex,
|
||||
)
|
||||
onLongClickFeed(item)
|
||||
// KMK <--
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -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 = {},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 = { },
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 -> {
|
||||
|
|
|
|||
|
|
@ -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 -> {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class HideCategory(
|
|||
}
|
||||
|
||||
sealed class Result {
|
||||
object Success : Result()
|
||||
data object Success : Result()
|
||||
data class InternalError(val error: Throwable) : Result()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
)
|
||||
|
|
|
|||
Loading…
Reference in a new issue