mirror of
https://github.com/mihonapp/mihon.git
synced 2024-12-25 18:38:23 +01:00
Merge a5cc1a2586
into 4a7fe44e0e
This commit is contained in:
commit
45756db557
@ -260,6 +260,7 @@ dependencies {
|
||||
implementation(libs.swipe)
|
||||
implementation(libs.compose.webview)
|
||||
implementation(libs.compose.grid)
|
||||
implementation(libs.reorderable)
|
||||
|
||||
// Logging
|
||||
implementation(libs.logcat)
|
||||
|
@ -5,12 +5,17 @@ import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.LazyListState
|
||||
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.category.components.CategoryFloatingActionButton
|
||||
import eu.kanade.presentation.category.components.CategoryListItem
|
||||
@ -18,6 +23,8 @@ import eu.kanade.presentation.components.AppBar
|
||||
import eu.kanade.presentation.components.AppBarActions
|
||||
import eu.kanade.tachiyomi.ui.category.CategoryScreenState
|
||||
import kotlinx.collections.immutable.persistentListOf
|
||||
import sh.calvin.reorderable.ReorderableItem
|
||||
import sh.calvin.reorderable.rememberReorderableLazyListState
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.Scaffold
|
||||
@ -34,8 +41,7 @@ fun CategoryScreen(
|
||||
onClickSortAlphabetically: () -> Unit,
|
||||
onClickRename: (Category) -> Unit,
|
||||
onClickDelete: (Category) -> Unit,
|
||||
onClickMoveUp: (Category) -> Unit,
|
||||
onClickMoveDown: (Category) -> Unit,
|
||||
changeOrder: (Category, Int) -> Unit,
|
||||
navigateUp: () -> Unit,
|
||||
) {
|
||||
val lazyListState = rememberLazyListState()
|
||||
@ -81,8 +87,7 @@ fun CategoryScreen(
|
||||
PaddingValues(horizontal = MaterialTheme.padding.medium),
|
||||
onClickRename = onClickRename,
|
||||
onClickDelete = onClickDelete,
|
||||
onMoveUp = onClickMoveUp,
|
||||
onMoveDown = onClickMoveDown,
|
||||
changeOrder = changeOrder,
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -94,28 +99,41 @@ private fun CategoryContent(
|
||||
paddingValues: PaddingValues,
|
||||
onClickRename: (Category) -> Unit,
|
||||
onClickDelete: (Category) -> Unit,
|
||||
onMoveUp: (Category) -> Unit,
|
||||
onMoveDown: (Category) -> Unit,
|
||||
changeOrder: (Category, Int) -> Unit,
|
||||
) {
|
||||
var reorderableList by remember { mutableStateOf(categories.toList()) }
|
||||
val reorderableLazyColumnState = rememberReorderableLazyListState(lazyListState) { from, to ->
|
||||
reorderableList = reorderableList.toMutableList().apply {
|
||||
changeOrder(reorderableList[from.index], to.index - from.index)
|
||||
add(to.index, removeAt(from.index))
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(categories) {
|
||||
if (!reorderableLazyColumnState.isAnyItemDragging) {
|
||||
reorderableList = categories.toList()
|
||||
}
|
||||
}
|
||||
|
||||
LazyColumn(
|
||||
state = lazyListState,
|
||||
contentPadding = paddingValues,
|
||||
verticalArrangement = Arrangement.spacedBy(MaterialTheme.padding.small),
|
||||
) {
|
||||
itemsIndexed(
|
||||
items = categories,
|
||||
key = { _, category -> "category-${category.id}" },
|
||||
) { index, category ->
|
||||
items(
|
||||
items = reorderableList,
|
||||
key = { category -> category.key },
|
||||
) { category ->
|
||||
ReorderableItem(reorderableLazyColumnState, category.key) {
|
||||
CategoryListItem(
|
||||
modifier = Modifier.animateItem(),
|
||||
category = category,
|
||||
canMoveUp = index != 0,
|
||||
canMoveDown = index != categories.lastIndex,
|
||||
onMoveUp = onMoveUp,
|
||||
onMoveDown = onMoveDown,
|
||||
onRename = { onClickRename(category) },
|
||||
onDelete = { onClickDelete(category) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val Category.key get() = "category-$id"
|
||||
|
@ -2,14 +2,11 @@ package eu.kanade.presentation.category.components
|
||||
|
||||
import androidx.compose.foundation.clickable
|
||||
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.automirrored.outlined.Label
|
||||
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.DragHandle
|
||||
import androidx.compose.material.icons.outlined.Edit
|
||||
import androidx.compose.material3.ElevatedCard
|
||||
import androidx.compose.material3.Icon
|
||||
@ -19,18 +16,15 @@ import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import sh.calvin.reorderable.ReorderableCollectionItemScope
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.i18n.MR
|
||||
import tachiyomi.presentation.core.components.material.padding
|
||||
import tachiyomi.presentation.core.i18n.stringResource
|
||||
|
||||
@Composable
|
||||
fun CategoryListItem(
|
||||
fun ReorderableCollectionItemScope.CategoryListItem(
|
||||
category: Category,
|
||||
canMoveUp: Boolean,
|
||||
canMoveDown: Boolean,
|
||||
onMoveUp: (Category) -> Unit,
|
||||
onMoveDown: (Category) -> Unit,
|
||||
onRename: () -> Unit,
|
||||
onDelete: () -> Unit,
|
||||
modifier: Modifier = Modifier,
|
||||
@ -42,34 +36,25 @@ fun CategoryListItem(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable { onRename() }
|
||||
.padding(vertical = MaterialTheme.padding.small)
|
||||
.padding(
|
||||
start = MaterialTheme.padding.medium,
|
||||
top = MaterialTheme.padding.medium,
|
||||
start = MaterialTheme.padding.small,
|
||||
end = MaterialTheme.padding.medium,
|
||||
),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Icon(imageVector = Icons.AutoMirrored.Outlined.Label, contentDescription = null)
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.DragHandle,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(MaterialTheme.padding.medium)
|
||||
.draggableHandle(),
|
||||
)
|
||||
Text(
|
||||
text = category.name,
|
||||
modifier = Modifier
|
||||
.padding(start = MaterialTheme.padding.medium),
|
||||
.weight(1f),
|
||||
)
|
||||
}
|
||||
Row {
|
||||
IconButton(
|
||||
onClick = { onMoveUp(category) },
|
||||
enabled = canMoveUp,
|
||||
) {
|
||||
Icon(imageVector = Icons.Outlined.ArrowDropUp, contentDescription = null)
|
||||
}
|
||||
IconButton(
|
||||
onClick = { onMoveDown(category) },
|
||||
enabled = canMoveDown,
|
||||
) {
|
||||
Icon(imageVector = Icons.Outlined.ArrowDropDown, contentDescription = null)
|
||||
}
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
IconButton(onClick = onRename) {
|
||||
Icon(
|
||||
imageVector = Icons.Outlined.Edit,
|
||||
|
@ -43,8 +43,7 @@ class CategoryScreen : Screen() {
|
||||
onClickSortAlphabetically = { screenModel.showDialog(CategoryDialog.SortAlphabetically) },
|
||||
onClickRename = { screenModel.showDialog(CategoryDialog.Rename(it)) },
|
||||
onClickDelete = { screenModel.showDialog(CategoryDialog.Delete(it)) },
|
||||
onClickMoveUp = screenModel::moveUp,
|
||||
onClickMoveDown = screenModel::moveDown,
|
||||
changeOrder = screenModel::changeOrder,
|
||||
navigateUp = navigator::pop,
|
||||
)
|
||||
|
||||
|
@ -74,18 +74,9 @@ class CategoryScreenModel(
|
||||
}
|
||||
}
|
||||
|
||||
fun moveUp(category: Category) {
|
||||
fun changeOrder(category: Category, newOrder: Int) {
|
||||
screenModelScope.launch {
|
||||
when (reorderCategory.moveUp(category)) {
|
||||
is ReorderCategory.Result.InternalError -> _events.send(CategoryEvent.InternalError)
|
||||
else -> {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun moveDown(category: Category) {
|
||||
screenModelScope.launch {
|
||||
when (reorderCategory.moveDown(category)) {
|
||||
when (reorderCategory.changeOrder(category, newOrder)) {
|
||||
is ReorderCategory.Result.InternalError -> _events.send(CategoryEvent.InternalError)
|
||||
else -> {}
|
||||
}
|
||||
|
@ -8,7 +8,6 @@ import tachiyomi.core.common.util.system.logcat
|
||||
import tachiyomi.domain.category.model.Category
|
||||
import tachiyomi.domain.category.model.CategoryUpdate
|
||||
import tachiyomi.domain.category.repository.CategoryRepository
|
||||
import java.util.Collections
|
||||
|
||||
class ReorderCategory(
|
||||
private val categoryRepository: CategoryRepository,
|
||||
@ -16,11 +15,7 @@ class ReorderCategory(
|
||||
|
||||
private val mutex = Mutex()
|
||||
|
||||
suspend fun moveUp(category: Category): Result = await(category, MoveTo.UP)
|
||||
|
||||
suspend fun moveDown(category: Category): Result = await(category, MoveTo.DOWN)
|
||||
|
||||
private suspend fun await(category: Category, moveTo: MoveTo) = withNonCancellableContext {
|
||||
suspend fun changeOrder(category: Category, newOrder: Int) = withNonCancellableContext {
|
||||
mutex.withLock {
|
||||
val categories = categoryRepository.getAll()
|
||||
.filterNot(Category::isSystemCategory)
|
||||
@ -31,13 +26,10 @@ class ReorderCategory(
|
||||
return@withNonCancellableContext Result.Unchanged
|
||||
}
|
||||
|
||||
val newPosition = when (moveTo) {
|
||||
MoveTo.UP -> currentIndex - 1
|
||||
MoveTo.DOWN -> currentIndex + 1
|
||||
}.toInt()
|
||||
val newPosition = currentIndex + newOrder
|
||||
|
||||
try {
|
||||
Collections.swap(categories, currentIndex, newPosition)
|
||||
categories.add(newPosition, categories.removeAt(currentIndex))
|
||||
|
||||
val updates = categories.mapIndexed { index, category ->
|
||||
CategoryUpdate(
|
||||
@ -81,9 +73,4 @@ class ReorderCategory(
|
||||
data object Unchanged : Result
|
||||
data class InternalError(val error: Throwable) : Result
|
||||
}
|
||||
|
||||
private enum class MoveTo {
|
||||
UP,
|
||||
DOWN,
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ compose-materialmotion = "io.github.fornewid:material-motion-compose-core:2.0.1"
|
||||
compose-webview = "io.github.kevinnzou:compose-webview:0.33.6"
|
||||
compose-grid = "io.woong.compose.grid:grid:1.2.2"
|
||||
compose-stablemarker = "com.github.skydoves:compose-stable-marker:1.0.5"
|
||||
reorderable = { module = "sh.calvin.reorderable:reorderable", version = "2.4.0" }
|
||||
|
||||
swipe = "me.saket.swipe:swipe:1.3.0"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user