Compare commits

..

No commits in common. "a5cc1a25860c5e569ffb0f43ab617f0a93c37c7b" and "8a396e6ceeb6c81254c346abc712aadf53bd3141" have entirely different histories.

6 changed files with 24 additions and 24 deletions

View File

@ -11,6 +11,9 @@ The format is a modified version of [Keep a Changelog](https://keepachangelog.co
- `Other` - for technical stuff. - `Other` - for technical stuff.
## [Unreleased] ## [Unreleased]
### Added
- Drag & Drop to reorder Category in Settings ([@cuong-tran](https://github.com/cuong-tran)) ([#1427](https://github.com/mihonapp/mihon/pull/1427))
### Changed ### Changed
- Bump default user agent - Bump default user agent

View File

@ -41,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, moveTo: (Category, Int) -> Unit,
navigateUp: () -> Unit, navigateUp: () -> Unit,
) { ) {
val lazyListState = rememberLazyListState() val lazyListState = rememberLazyListState()
@ -87,7 +87,7 @@ fun CategoryScreen(
PaddingValues(horizontal = MaterialTheme.padding.medium), PaddingValues(horizontal = MaterialTheme.padding.medium),
onClickRename = onClickRename, onClickRename = onClickRename,
onClickDelete = onClickDelete, onClickDelete = onClickDelete,
changeOrder = changeOrder, moveTo = moveTo,
) )
} }
} }
@ -99,12 +99,12 @@ private fun CategoryContent(
paddingValues: PaddingValues, paddingValues: PaddingValues,
onClickRename: (Category) -> Unit, onClickRename: (Category) -> Unit,
onClickDelete: (Category) -> Unit, onClickDelete: (Category) -> Unit,
changeOrder: (Category, Int) -> Unit, moveTo: (Category, Int) -> Unit,
) { ) {
var reorderableList by remember { mutableStateOf(categories.toList()) } var reorderableList by remember { mutableStateOf(categories.toList()) }
val reorderableLazyColumnState = rememberReorderableLazyListState(lazyListState) { from, to -> val reorderableLazyColumnState = rememberReorderableLazyListState(lazyListState) { from, to ->
reorderableList = reorderableList.toMutableList().apply { reorderableList = reorderableList.toMutableList().apply {
changeOrder(reorderableList[from.index], to.index - from.index) moveTo(reorderableList[from.index], to.index - from.index)
add(to.index, removeAt(from.index)) add(to.index, removeAt(from.index))
} }
} }
@ -122,9 +122,9 @@ private fun CategoryContent(
) { ) {
items( items(
items = reorderableList, items = reorderableList,
key = { category -> category.key }, key = { category -> category.key() },
) { category -> ) { category ->
ReorderableItem(reorderableLazyColumnState, category.key) { ReorderableItem(reorderableLazyColumnState, category.key()) {
CategoryListItem( CategoryListItem(
modifier = Modifier.animateItem(), modifier = Modifier.animateItem(),
category = category, category = category,
@ -136,4 +136,4 @@ private fun CategoryContent(
} }
} }
private val Category.key get() = "category-$id" fun Category.key() = "category-$id"

View File

@ -6,8 +6,8 @@ import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Delete import androidx.compose.material.icons.outlined.Delete
import androidx.compose.material.icons.outlined.DragHandle
import androidx.compose.material.icons.outlined.Edit import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material.icons.rounded.DragHandle
import androidx.compose.material3.ElevatedCard import androidx.compose.material3.ElevatedCard
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
@ -36,24 +36,21 @@ fun ReorderableCollectionItemScope.CategoryListItem(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.clickable { onRename() } .clickable { onRename() }
.padding(vertical = MaterialTheme.padding.small) .padding(MaterialTheme.padding.small),
.padding(
start = MaterialTheme.padding.small,
end = MaterialTheme.padding.medium,
),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
Icon( IconButton(
imageVector = Icons.Outlined.DragHandle,
contentDescription = null,
modifier = Modifier modifier = Modifier
.padding(MaterialTheme.padding.medium)
.draggableHandle(), .draggableHandle(),
) onClick = {},
) {
Icon(Icons.Rounded.DragHandle, contentDescription = "Reorder")
}
Text( Text(
text = category.name, text = category.name,
modifier = Modifier modifier = Modifier
.weight(1f), .weight(1f)
.padding(start = MaterialTheme.padding.small),
) )
IconButton(onClick = onRename) { IconButton(onClick = onRename) {
Icon( Icon(

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, moveTo = screenModel::moveTo,
navigateUp = navigator::pop, navigateUp = navigator::pop,
) )

View File

@ -74,9 +74,9 @@ class CategoryScreenModel(
} }
} }
fun changeOrder(category: Category, newOrder: Int) { fun moveTo(category: Category, offset: Int) {
screenModelScope.launch { screenModelScope.launch {
when (reorderCategory.changeOrder(category, newOrder)) { when (reorderCategory.await(category, offset)) {
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 await(category: Category, offset: Int) = withNonCancellableContext {
mutex.withLock { mutex.withLock {
val categories = categoryRepository.getAll() val categories = categoryRepository.getAll()
.filterNot(Category::isSystemCategory) .filterNot(Category::isSystemCategory)
@ -26,7 +26,7 @@ class ReorderCategory(
return@withNonCancellableContext Result.Unchanged return@withNonCancellableContext Result.Unchanged
} }
val newPosition = currentIndex + newOrder val newPosition = currentIndex + offset
try { try {
categories.add(newPosition, categories.removeAt(currentIndex)) categories.add(newPosition, categories.removeAt(currentIndex))