Improve support for drag-and-drop category/feed reordering (mihonapp/mihon#1427)

This commit is contained in:
Cuong-Tran 2025-02-26 12:37:10 +07:00
parent 0a6caab64b
commit 69adc4605e
No known key found for this signature in database
GPG key ID: 733AA7624B9315C2
15 changed files with 80 additions and 82 deletions

View file

@ -19,6 +19,7 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co
- Support for private tracking with AniList and Bangumi ([@NarwhalHorns](https://github.com/NarwhalHorns)) ([#1736](https://github.com/mihonapp/mihon/pull/1736)) - Support for private tracking with AniList and Bangumi ([@NarwhalHorns](https://github.com/NarwhalHorns)) ([#1736](https://github.com/mihonapp/mihon/pull/1736))
- Add private tracking support for Kitsu ([@MajorTanya](https://github.com/MajorTanya)) ([#1774](https://github.com/mihonapp/mihon/pull/1774)) - Add private tracking support for Kitsu ([@MajorTanya](https://github.com/MajorTanya)) ([#1774](https://github.com/mihonapp/mihon/pull/1774))
- Add option to export minimal library information to a CSV file ([@Animeboynz](https://github.com/Animeboynz), [@AntsyLich](https://github.com/AntsyLich)) ([#1161](https://github.com/mihonapp/mihon/pull/1161)) - Add option to export minimal library information to a CSV file ([@Animeboynz](https://github.com/Animeboynz), [@AntsyLich](https://github.com/AntsyLich)) ([#1161](https://github.com/mihonapp/mihon/pull/1161))
- Add back support for drag-and-drop category reordering ([@cuong-tran](https://github.com/cuong-tran)) ([#1427](https://github.com/mihonapp/mihon/pull/1427))
### Changed ### Changed
- Apply "Downloaded only" filter to all entries regardless of favourite status ([@NGB-Was-Taken](https://github.com/NGB-Was-Taken)) ([#1603](https://github.com/mihonapp/mihon/pull/1603)) - Apply "Downloaded only" filter to all entries regardless of favourite status ([@NGB-Was-Taken](https://github.com/NGB-Was-Taken)) ([#1603](https://github.com/mihonapp/mihon/pull/1603))

View file

@ -2,16 +2,14 @@ package eu.kanade.presentation.browse
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import eu.kanade.presentation.browse.components.FeedOrderListItem import eu.kanade.presentation.browse.components.FeedOrderListItem
import eu.kanade.tachiyomi.ui.browse.feed.FeedScreenState import eu.kanade.tachiyomi.ui.browse.feed.FeedScreenState
@ -29,7 +27,7 @@ import tachiyomi.presentation.core.util.plus
fun FeedOrderScreen( fun FeedOrderScreen(
state: FeedScreenState, state: FeedScreenState,
onClickDelete: (FeedSavedSearch) -> Unit, onClickDelete: (FeedSavedSearch) -> Unit,
changeOrder: (FeedSavedSearch, Int) -> Unit, onChangeOrder: (FeedSavedSearch, Int) -> Unit,
) { ) {
when { when {
state.isLoading -> LoadingScreen() state.isLoading -> LoadingScreen()
@ -41,31 +39,32 @@ fun FeedOrderScreen(
val lazyListState = rememberLazyListState() val lazyListState = rememberLazyListState()
val feeds = state.items val feeds = state.items
var reorderableList by remember { mutableStateOf(feeds) } val feedsState = remember { feeds.toMutableList() }
val reorderableLazyColumnState = rememberReorderableLazyListState(lazyListState) { from, to -> val reorderableState = rememberReorderableLazyListState(lazyListState) { from, to ->
reorderableList = reorderableList.toMutableList().apply { val item = feedsState.removeAt(from.index)
changeOrder(reorderableList[from.index].feed, to.index - from.index) feedsState.add(to.index, item)
add(to.index, removeAt(from.index)) onChangeOrder(item.feed, to.index)
}
} }
LaunchedEffect(feeds) { LaunchedEffect(feeds) {
if (!reorderableLazyColumnState.isAnyItemDragging) { if (!reorderableState.isAnyItemDragging) {
reorderableList = feeds feedsState.clear()
feedsState.addAll(feeds)
} }
} }
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxSize(),
state = lazyListState, state = lazyListState,
contentPadding = topSmallPaddingValues + contentPadding = topSmallPaddingValues +
PaddingValues(horizontal = MaterialTheme.padding.medium), PaddingValues(horizontal = MaterialTheme.padding.medium),
verticalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small), verticalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
) { ) {
items( items(
items = reorderableList, items = feedsState,
key = { it.feed.key }, key = { it.feed.key },
) { feed -> ) { feed ->
ReorderableItem(reorderableLazyColumnState, feed.feed.key) { ReorderableItem(reorderableState, feed.feed.key) {
FeedOrderListItem( FeedOrderListItem(
modifier = Modifier.animateItem(), modifier = Modifier.animateItem(),
title = feed.title, title = feed.title,
@ -78,4 +77,4 @@ fun FeedOrderScreen(
} }
} }
internal val FeedSavedSearch.key get() = "feed-$id" internal val FeedSavedSearch.key inline get() = "feed-$id"

View file

@ -2,6 +2,7 @@ package eu.kanade.presentation.browse
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState import androidx.compose.foundation.lazy.rememberLazyListState
@ -10,10 +11,7 @@ import androidx.compose.material.icons.outlined.SortByAlpha
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import eu.kanade.presentation.browse.components.FeedOrderListItem import eu.kanade.presentation.browse.components.FeedOrderListItem
import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBar
@ -37,7 +35,7 @@ import tachiyomi.presentation.core.util.plus
fun SourceFeedOrderScreen( fun SourceFeedOrderScreen(
state: SourceFeedState, state: SourceFeedState,
onClickDelete: (FeedSavedSearch) -> Unit, onClickDelete: (FeedSavedSearch) -> Unit,
changeOrder: (FeedSavedSearch, Int) -> Unit, onChangeOrder: (FeedSavedSearch, Int) -> Unit,
onClickSortAlphabetically: () -> Unit, onClickSortAlphabetically: () -> Unit,
navigateUp: (() -> Unit)? = null, navigateUp: (() -> Unit)? = null,
) { ) {
@ -75,31 +73,33 @@ fun SourceFeedOrderScreen(
val feeds = state.items val feeds = state.items
.filterIsInstance<SourceFeedUI.SourceSavedSearch>() .filterIsInstance<SourceFeedUI.SourceSavedSearch>()
var reorderableList by remember { mutableStateOf(feeds) } val feedsState = remember { feeds.toMutableList() }
val reorderableLazyColumnState = rememberReorderableLazyListState(lazyListState) { from, to -> val reorderableState = rememberReorderableLazyListState(lazyListState, paddingValues) { from, to ->
reorderableList = reorderableList.toMutableList().apply { val item = feedsState.removeAt(from.index)
changeOrder(reorderableList[from.index].feed, to.index - from.index) feedsState.add(to.index, item)
add(to.index, removeAt(from.index)) onChangeOrder(item.feed, to.index)
}
} }
LaunchedEffect(feeds) { LaunchedEffect(feeds) {
if (!reorderableLazyColumnState.isAnyItemDragging) { if (!reorderableState.isAnyItemDragging) {
reorderableList = feeds feedsState.clear()
feedsState.addAll(feeds)
} }
} }
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxSize(),
state = lazyListState, state = lazyListState,
contentPadding = paddingValues + topSmallPaddingValues + contentPadding = paddingValues +
topSmallPaddingValues +
PaddingValues(horizontal = MaterialTheme.padding.medium), PaddingValues(horizontal = MaterialTheme.padding.medium),
verticalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small), verticalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
) { ) {
items( items(
items = reorderableList, items = feedsState,
key = { it.feed.key }, key = { it.feed.key },
) { feed -> ) { feed ->
ReorderableItem(reorderableLazyColumnState, feed.feed.key) { ReorderableItem(reorderableState, feed.feed.key) {
FeedOrderListItem( FeedOrderListItem(
modifier = Modifier.animateItem(), modifier = Modifier.animateItem(),
title = feed.title, title = feed.title,

View file

@ -25,12 +25,11 @@ fun ReorderableCollectionItemScope.FeedOrderListItem(
onDelete: () -> Unit, onDelete: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
ElevatedCard( ElevatedCard(modifier = modifier) {
modifier = modifier,
) {
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(vertical = MaterialTheme.padding.small)
.padding( .padding(
start = MaterialTheme.padding.small, start = MaterialTheme.padding.small,
end = MaterialTheme.padding.medium, end = MaterialTheme.padding.medium,
@ -46,11 +45,13 @@ fun ReorderableCollectionItemScope.FeedOrderListItem(
) )
Text( Text(
text = title, text = title,
modifier = Modifier modifier = Modifier.weight(1f),
.weight(1f),
) )
IconButton(onClick = onDelete) { IconButton(onClick = onDelete) {
Icon(imageVector = Icons.Outlined.Delete, contentDescription = stringResource(MR.strings.action_delete)) Icon(
imageVector = Icons.Outlined.Delete,
contentDescription = stringResource(MR.strings.action_delete),
)
} }
} }
} }

View file

@ -2,6 +2,7 @@ package eu.kanade.presentation.category
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.LazyListState
@ -12,10 +13,8 @@ import androidx.compose.material.icons.outlined.SortByAlpha
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue import androidx.compose.runtime.toMutableStateList
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import eu.kanade.presentation.category.components.CategoryFloatingActionButton import eu.kanade.presentation.category.components.CategoryFloatingActionButton
import eu.kanade.presentation.category.components.CategoryListItem import eu.kanade.presentation.category.components.CategoryListItem
@ -42,7 +41,7 @@ fun CategoryScreen(
onClickSortAlphabetically: () -> Unit, onClickSortAlphabetically: () -> Unit,
onClickRename: (Category) -> Unit, onClickRename: (Category) -> Unit,
onClickDelete: (Category) -> Unit, onClickDelete: (Category) -> Unit,
changeOrder: (Category, Int) -> Unit, onChangeOrder: (Category, Int) -> Unit,
// KMK --> // KMK -->
onClickHide: (Category) -> Unit, onClickHide: (Category) -> Unit,
// KMK <-- // KMK <--
@ -86,11 +85,10 @@ fun CategoryScreen(
CategoryContent( CategoryContent(
categories = state.categories, categories = state.categories,
lazyListState = lazyListState, lazyListState = lazyListState,
paddingValues = paddingValues + topSmallPaddingValues + paddingValues = paddingValues,
PaddingValues(horizontal = MaterialTheme.padding.medium),
onClickRename = onClickRename, onClickRename = onClickRename,
onClickDelete = onClickDelete, onClickDelete = onClickDelete,
changeOrder = changeOrder, onChangeOrder = onChangeOrder,
// KMK --> // KMK -->
onClickHide = onClickHide, onClickHide = onClickHide,
// KMK <-- // KMK <--
@ -105,35 +103,38 @@ private fun CategoryContent(
paddingValues: PaddingValues, paddingValues: PaddingValues,
onClickRename: (Category) -> Unit, onClickRename: (Category) -> Unit,
onClickDelete: (Category) -> Unit, onClickDelete: (Category) -> Unit,
changeOrder: (Category, Int) -> Unit, onChangeOrder: (Category, Int) -> Unit,
// KMK --> // KMK -->
onClickHide: (Category) -> Unit, onClickHide: (Category) -> Unit,
// KMK <-- // KMK <--
) { ) {
var reorderableList by remember { mutableStateOf(categories.toList()) } val categoriesState = remember { categories.toMutableStateList() }
val reorderableLazyColumnState = rememberReorderableLazyListState(lazyListState) { from, to -> val reorderableState = rememberReorderableLazyListState(lazyListState, paddingValues) { from, to ->
reorderableList = reorderableList.toMutableList().apply { val item = categoriesState.removeAt(from.index)
changeOrder(reorderableList[from.index], to.index - from.index) categoriesState.add(to.index, item)
add(to.index, removeAt(from.index)) onChangeOrder(item, to.index)
}
} }
LaunchedEffect(categories) { LaunchedEffect(categories) {
if (!reorderableLazyColumnState.isAnyItemDragging) { if (!reorderableState.isAnyItemDragging) {
reorderableList = categories.toList() categoriesState.clear()
categoriesState.addAll(categories)
} }
} }
LazyColumn( LazyColumn(
modifier = Modifier.fillMaxSize(),
state = lazyListState, state = lazyListState,
contentPadding = paddingValues, contentPadding = paddingValues +
topSmallPaddingValues +
PaddingValues(horizontal = MaterialTheme.padding.medium),
verticalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small), verticalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
) { ) {
items( items(
items = reorderableList, items = categoriesState,
key = { category -> category.key }, key = { category -> category.key },
) { category -> ) { category ->
ReorderableItem(reorderableLazyColumnState, category.key) { ReorderableItem(reorderableState, category.key) {
CategoryListItem( CategoryListItem(
modifier = Modifier.animateItem(), modifier = Modifier.animateItem(),
category = category, category = category,
@ -148,4 +149,4 @@ private fun CategoryContent(
} }
} }
private val Category.key get() = "category-$id" private val Category.key inline get() = "category-$id"

View file

@ -37,13 +37,12 @@ fun ReorderableCollectionItemScope.CategoryListItem(
// KMK <-- // KMK <--
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
ElevatedCard( ElevatedCard(modifier = modifier) {
modifier = modifier,
) {
Row( Row(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.clickable { onRename() } .clickable(onClick = onRename)
.padding(vertical = MaterialTheme.padding.small)
.padding( .padding(
start = MaterialTheme.padding.small, start = MaterialTheme.padding.small,
end = MaterialTheme.padding.medium, end = MaterialTheme.padding.medium,
@ -63,8 +62,7 @@ fun ReorderableCollectionItemScope.CategoryListItem(
color = LocalContentColor.current.let { if (category.hidden) it.copy(alpha = 0.6f) else it }, color = LocalContentColor.current.let { if (category.hidden) it.copy(alpha = 0.6f) else it },
textDecoration = TextDecoration.LineThrough.takeIf { category.hidden }, textDecoration = TextDecoration.LineThrough.takeIf { category.hidden },
// KMK <-- // KMK <--
modifier = Modifier modifier = Modifier.weight(1f),
.weight(1f),
) )
IconButton(onClick = onRename) { IconButton(onClick = onRename) {
Icon( Icon(
@ -88,7 +86,10 @@ fun ReorderableCollectionItemScope.CategoryListItem(
) )
// KMK <-- // KMK <--
IconButton(onClick = onDelete) { IconButton(onClick = onDelete) {
Icon(imageVector = Icons.Outlined.Delete, contentDescription = stringResource(MR.strings.action_delete)) Icon(
imageVector = Icons.Outlined.Delete,
contentDescription = stringResource(MR.strings.action_delete),
)
} }
} }
} }

View file

@ -218,9 +218,9 @@ open class FeedScreenModel(
} }
// KMK --> // KMK -->
fun changeOrder(feed: FeedSavedSearch, newOrder: Int) { fun changeOrder(feed: FeedSavedSearch, newIndex: Int) {
screenModelScope.launch { screenModelScope.launch {
reorderFeed.changeOrder(feed, newOrder) reorderFeed.changeOrder(feed, newIndex)
} }
} }

View file

@ -142,7 +142,7 @@ fun feedTab(
FeedOrderScreen( FeedOrderScreen(
state = state, state = state,
onClickDelete = screenModel::openDeleteDialog, onClickDelete = screenModel::openDeleteDialog,
changeOrder = screenModel::changeOrder, onChangeOrder = screenModel::changeOrder,
) )
} else { } else {
// KMK <-- // KMK <--

View file

@ -105,7 +105,7 @@ class SourceFeedScreen(val sourceId: Long) : Screen() {
SourceFeedOrderScreen( SourceFeedOrderScreen(
state = state, state = state,
onClickDelete = screenModel::openDeleteFeed, onClickDelete = screenModel::openDeleteFeed,
changeOrder = screenModel::changeOrder, onChangeOrder = screenModel::changeOrder,
onClickSortAlphabetically = { onClickSortAlphabetically = {
screenModel.showDialog(SourceFeedScreenModel.Dialog.SortAlphabetically) screenModel.showDialog(SourceFeedScreenModel.Dialog.SortAlphabetically)
}, },

View file

@ -33,7 +33,6 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import tachiyomi.core.common.util.lang.launchIO import tachiyomi.core.common.util.lang.launchIO
import tachiyomi.core.common.util.lang.launchNonCancellable import tachiyomi.core.common.util.lang.launchNonCancellable
@ -156,9 +155,9 @@ open class SourceFeedScreenModel(
} }
// KMK --> // KMK -->
fun changeOrder(feed: FeedSavedSearch, newOrder: Int) { fun changeOrder(feed: FeedSavedSearch, newIndex: Int) {
screenModelScope.launch { screenModelScope.launch {
reorderFeed.changeOrder(feed, newOrder, false) reorderFeed.changeOrder(feed, newIndex, false)
} }
} }

View file

@ -43,7 +43,7 @@ class CategoryScreen : Screen() {
onClickSortAlphabetically = { screenModel.showDialog(CategoryDialog.SortAlphabetically) }, onClickSortAlphabetically = { screenModel.showDialog(CategoryDialog.SortAlphabetically) },
onClickRename = { screenModel.showDialog(CategoryDialog.Rename(it)) }, onClickRename = { screenModel.showDialog(CategoryDialog.Rename(it)) },
onClickDelete = { screenModel.showDialog(CategoryDialog.Delete(it)) }, onClickDelete = { screenModel.showDialog(CategoryDialog.Delete(it)) },
changeOrder = screenModel::changeOrder, onChangeOrder = screenModel::changeOrder,
// KMK --> // KMK -->
onClickHide = screenModel::hideCategory, onClickHide = screenModel::hideCategory,
// KMK <-- // KMK <--

View file

@ -89,9 +89,9 @@ class CategoryScreenModel(
} }
} }
fun changeOrder(category: Category, newOrder: Int) { fun changeOrder(category: Category, newIndex: Int) {
screenModelScope.launch { screenModelScope.launch {
when (reorderCategory.changeOrder(category, newOrder)) { when (reorderCategory.changeOrder(category, newIndex)) {
is ReorderCategory.Result.InternalError -> _events.send(CategoryEvent.InternalError) is ReorderCategory.Result.InternalError -> _events.send(CategoryEvent.InternalError)
else -> {} else -> {}
} }

View file

@ -15,7 +15,7 @@ class ReorderCategory(
private val mutex = Mutex() private val mutex = Mutex()
suspend fun changeOrder(category: Category, newOrder: Int) = withNonCancellableContext { suspend fun changeOrder(category: Category, newIndex: Int) = withNonCancellableContext {
mutex.withLock { mutex.withLock {
val categories = categoryRepository.getAll() val categories = categoryRepository.getAll()
.filterNot(Category::isSystemCategory) .filterNot(Category::isSystemCategory)
@ -26,10 +26,8 @@ class ReorderCategory(
return@withNonCancellableContext Result.Unchanged return@withNonCancellableContext Result.Unchanged
} }
val newPosition = currentIndex + newOrder
try { try {
categories.add(newPosition, categories.removeAt(currentIndex)) categories.add(newIndex, categories.removeAt(currentIndex))
val updates = categories.mapIndexed { index, category -> val updates = categories.mapIndexed { index, category ->
CategoryUpdate( CategoryUpdate(

View file

@ -15,7 +15,7 @@ class ReorderFeed(
private val mutex = Mutex() private val mutex = Mutex()
suspend fun changeOrder(feed: FeedSavedSearch, newOrder: Int, global: Boolean = true) = withNonCancellableContext { suspend fun changeOrder(feed: FeedSavedSearch, newIndex: Int, global: Boolean = true) = withNonCancellableContext {
mutex.withLock { mutex.withLock {
val feeds = if (global) { val feeds = if (global) {
feedSavedSearchRepository.getGlobal() feedSavedSearchRepository.getGlobal()
@ -30,10 +30,8 @@ class ReorderFeed(
return@withNonCancellableContext Result.Unchanged return@withNonCancellableContext Result.Unchanged
} }
val newPosition = currentIndex + newOrder
try { try {
feeds.add(newPosition, feeds.removeAt(currentIndex)) feeds.add(newIndex, feeds.removeAt(currentIndex))
val updates = feeds.mapIndexed { index, feed -> val updates = feeds.mapIndexed { index, feed ->
FeedSavedSearchUpdate( FeedSavedSearchUpdate(

View file

@ -64,10 +64,10 @@ compose-materialmotion = "io.github.fornewid:material-motion-compose-core:2.0.1"
compose-webview = "io.github.kevinnzou:compose-webview:0.33.6" compose-webview = "io.github.kevinnzou:compose-webview:0.33.6"
compose-grid = "io.woong.compose.grid:grid:1.2.2" compose-grid = "io.woong.compose.grid:grid:1.2.2"
compose-stablemarker = "com.github.skydoves:compose-stable-marker:1.0.5" compose-stablemarker = "com.github.skydoves:compose-stable-marker:1.0.5"
reorderable = { module = "sh.calvin.reorderable:reorderable", version = "2.4.3" }
palette-ktx = "androidx.palette:palette-ktx:1.0.0" palette-ktx = "androidx.palette:palette-ktx:1.0.0"
materialKolor = "com.materialkolor:material-kolor:2.0.2" materialKolor = "com.materialkolor:material-kolor:2.0.2"
haze = "dev.chrisbanes.haze:haze:1.3.1" haze = "dev.chrisbanes.haze:haze:1.3.1"
reorderable = { module = "sh.calvin.reorderable:reorderable", version = "2.4.3" }
swipe = "me.saket.swipe:swipe:1.3.0" swipe = "me.saket.swipe:swipe:1.3.0"