Fix list items reorder

This commit is contained in:
Koitharu
2023-12-05 09:59:07 +02:00
parent 21639ddcbc
commit 357669d8b2
9 changed files with 184 additions and 127 deletions

View File

@@ -2,14 +2,14 @@ package org.koitharu.kotatsu.settings.sources.adapter
import androidx.lifecycle.LifecycleOwner
import coil.ImageLoader
import org.koitharu.kotatsu.core.ui.BaseListAdapter
import org.koitharu.kotatsu.core.ui.ReorderableListAdapter
import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem
class SourceConfigAdapter(
listener: SourceConfigListener,
coil: ImageLoader,
lifecycleOwner: LifecycleOwner,
) : BaseListAdapter<SourceConfigItem>() {
) : ReorderableListAdapter<SourceConfigItem>() {
init {
with(delegatesManager) {

View File

@@ -54,6 +54,7 @@ class SourcesManageFragment :
lateinit var shortcutManager: AppShortcutManager
private var reorderHelper: ItemTouchHelper? = null
private var sourcesAdapter: SourceConfigAdapter? = null
private val viewModel by viewModels<SourcesManageViewModel>()
override val recyclerView: RecyclerView
@@ -69,7 +70,7 @@ class SourcesManageFragment :
savedInstanceState: Bundle?,
) {
super.onViewBindingCreated(binding, savedInstanceState)
val sourcesAdapter = SourceConfigAdapter(this, coil, viewLifecycleOwner)
sourcesAdapter = SourceConfigAdapter(this, coil, viewLifecycleOwner)
with(binding.recyclerView) {
setHasFixedSize(true)
adapter = sourcesAdapter
@@ -77,7 +78,7 @@ class SourcesManageFragment :
it.attachToRecyclerView(this)
}
}
viewModel.content.observe(viewLifecycleOwner, sourcesAdapter)
viewModel.content.observe(viewLifecycleOwner, checkNotNull(sourcesAdapter))
viewModel.onActionDone.observeEvent(
viewLifecycleOwner,
ReversibleActionObserver(binding.recyclerView),
@@ -91,6 +92,7 @@ class SourcesManageFragment :
}
override fun onDestroyView() {
sourcesAdapter = null
reorderHelper = null
super.onDestroyView()
}
@@ -204,7 +206,7 @@ class SourcesManageFragment :
y: Int,
) {
super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y)
viewModel.reorderSources(fromPos, toPos)
sourcesAdapter?.reorderItems(fromPos, toPos)
}
override fun canDropOver(
@@ -248,5 +250,10 @@ class SourcesManageFragment :
}
override fun isLongPressDragEnabled() = true
override fun clearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
super.clearView(recyclerView, viewHolder)
viewModel.saveSourcesOrder(sourcesAdapter?.items ?: return)
}
}
}

View File

@@ -4,8 +4,6 @@ import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.delay
import kotlinx.coroutines.yield
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.db.MangaDatabase
import org.koitharu.kotatsu.core.db.removeObserverAsync
@@ -43,17 +41,19 @@ class SourcesManageViewModel @Inject constructor(
database.invalidationTracker.removeObserverAsync(listProducer)
}
fun reorderSources(oldPos: Int, newPos: Int) {
val snapshot = content.value.toMutableList()
if ((snapshot[oldPos] as? SourceConfigItem.SourceItem)?.isDraggable != true) {
return
fun saveSourcesOrder(snapshot: List<SourceConfigItem>) {
val prevJob = commitJob
commitJob = launchJob(Dispatchers.Default) {
prevJob?.cancelAndJoin()
val newSourcesList = snapshot.mapNotNull { x ->
if (x is SourceConfigItem.SourceItem && x.isDraggable) {
x.source
} else {
null
}
}
repository.setPositions(newSourcesList)
}
if ((snapshot[newPos] as? SourceConfigItem.SourceItem)?.isDraggable != true) {
return
}
snapshot.move(oldPos, newPos)
content.value = snapshot
commit(snapshot)
}
fun canReorder(oldPos: Int, newPos: Int): Boolean {
@@ -72,28 +72,31 @@ class SourcesManageViewModel @Inject constructor(
}
fun bringToTop(source: MangaSource) {
var oldPos = -1
var newPos = -1
val snapshot = content.value
for ((i, x) in snapshot.withIndex()) {
if (x !is SourceConfigItem.SourceItem) {
continue
launchJob(Dispatchers.Default) {
var oldPos = -1
var newPos = -1
for ((i, x) in snapshot.withIndex()) {
if (x !is SourceConfigItem.SourceItem) {
continue
}
if (newPos == -1) {
newPos = i
}
if (x.source == source) {
oldPos = i
break
}
}
if (newPos == -1) {
newPos = i
@Suppress("KotlinConstantConditions")
if (oldPos != -1 && newPos != -1) {
reorderSources(oldPos, newPos)
val revert = ReversibleAction(R.string.moved_to_top) {
reorderSources(newPos, oldPos)
}
commitJob?.join()
onActionDone.call(revert)
}
if (x.source == source) {
oldPos = i
break
}
}
@Suppress("KotlinConstantConditions")
if (oldPos != -1 && newPos != -1) {
reorderSources(oldPos, newPos)
val revert = ReversibleAction(R.string.moved_to_top) {
reorderSources(newPos, oldPos)
}
onActionDone.call(revert)
}
}
@@ -113,20 +116,15 @@ class SourcesManageViewModel @Inject constructor(
}
}
private fun commit(snapshot: List<SourceConfigItem>) {
val prevJob = commitJob
commitJob = launchJob {
prevJob?.cancelAndJoin()
delay(500)
val newSourcesList = snapshot.mapNotNull { x ->
if (x is SourceConfigItem.SourceItem && x.isDraggable) {
x.source
} else {
null
}
}
repository.setPositions(newSourcesList)
yield()
private fun reorderSources(oldPos: Int, newPos: Int) {
val snapshot = content.value.toMutableList()
if ((snapshot[oldPos] as? SourceConfigItem.SourceItem)?.isDraggable != true) {
return
}
if ((snapshot[newPos] as? SourceConfigItem.SourceItem)?.isDraggable != true) {
return
}
snapshot.move(oldPos, newPos)
saveSourcesOrder(snapshot)
}
}