Fix sources reordering

This commit is contained in:
Koitharu
2023-08-23 17:07:14 +03:00
parent ba0ea5a9fc
commit b3b022807a
3 changed files with 49 additions and 38 deletions

View File

@@ -91,6 +91,14 @@ class MangaSourcesRepository @Inject constructor(
}
}
suspend fun setPositions(sources: List<MangaSource>) {
db.withTransaction {
for ((index, item) in sources.withIndex()) {
dao.setSortKey(item.name, index)
}
}
}
suspend fun setPosition(source: MangaSource, index: Int) {
db.withTransaction {
val all = dao.findAll().toMutableList()

View File

@@ -172,10 +172,20 @@ class SourcesManageFragment :
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder,
): Boolean = viewHolder.itemViewType == target.itemViewType && viewModel.reorderSources(
viewHolder.bindingAdapterPosition,
target.bindingAdapterPosition,
)
): Boolean = viewHolder.itemViewType == target.itemViewType
override fun onMoved(
recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder,
fromPos: Int,
target: RecyclerView.ViewHolder,
toPos: Int,
x: Int,
y: Int
) {
super.onMoved(recyclerView, viewHolder, fromPos, target, toPos, x, y)
viewModel.reorderSources(fromPos, toPos)
}
override fun canDropOver(
recyclerView: RecyclerView,

View File

@@ -4,17 +4,15 @@ import androidx.annotation.CheckResult
import androidx.core.os.LocaleListCompat
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.CoroutineStart
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.plus
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.core.model.getLocaleTitle
import org.koitharu.kotatsu.core.prefs.AppSettings
@@ -29,13 +27,12 @@ import org.koitharu.kotatsu.core.util.ext.toEnumSet
import org.koitharu.kotatsu.explore.data.MangaSourcesRepository
import org.koitharu.kotatsu.parsers.model.ContentType
import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.util.move
import org.koitharu.kotatsu.parsers.util.toTitleCase
import org.koitharu.kotatsu.settings.sources.model.SourceConfigItem
import java.util.Locale
import java.util.TreeMap
import javax.inject.Inject
import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext
private const val KEY_ENABLED = "!"
private const val TIP_REORDER = "src_reorder"
@@ -48,7 +45,7 @@ class SourcesManageViewModel @Inject constructor(
private val expandedGroups = MutableStateFlow(emptySet<String?>())
private var searchQuery = MutableStateFlow<String?>(null)
private val mutex = Mutex()
private var reorderJob: Job? = null
val content = combine(
repository.observeEnabledSources(),
@@ -62,23 +59,28 @@ class SourcesManageViewModel @Inject constructor(
val onActionDone = MutableEventFlow<ReversibleAction>()
fun reorderSources(oldPos: Int, newPos: Int): Boolean {
val snapshot = content.value
val item = (snapshot[oldPos] as? SourceConfigItem.SourceItem) ?: return false
if ((snapshot[newPos] as? SourceConfigItem.SourceItem)?.isDraggable != true) return false
launchAtomicJob(Dispatchers.Default) {
var targetPosition = 0
for ((i, x) in snapshot.withIndex()) {
if (i == newPos) {
break
}
if (x is SourceConfigItem.SourceItem) {
targetPosition++
fun reorderSources(oldPos: Int, newPos: Int) {
val snapshot = content.value.toMutableList()
val prevJob = reorderJob
reorderJob = launchJob(Dispatchers.Default) {
prevJob?.cancelAndJoin()
if ((snapshot[oldPos] as? SourceConfigItem.SourceItem)?.isDraggable != true) {
return@launchJob
}
if ((snapshot[newPos] as? SourceConfigItem.SourceItem)?.isDraggable != true) {
return@launchJob
}
delay(100)
snapshot.move(oldPos, newPos)
val newSourcesList = snapshot.mapNotNull { x ->
if (x is SourceConfigItem.SourceItem && x.isDraggable) {
x.source
} else {
null
}
}
repository.setPosition(item.source, targetPosition)
repository.setPositions(newSourcesList)
}
return true
}
fun canReorder(oldPos: Int, newPos: Int): Boolean {
@@ -88,7 +90,7 @@ class SourcesManageViewModel @Inject constructor(
}
fun setEnabled(source: MangaSource, isEnabled: Boolean) {
launchAtomicJob(Dispatchers.Default) {
launchJob(Dispatchers.Default) {
val rollback = repository.setSourceEnabled(source, isEnabled)
if (!isEnabled) {
onActionDone.call(ReversibleAction(R.string.source_disabled, rollback))
@@ -97,7 +99,7 @@ class SourcesManageViewModel @Inject constructor(
}
fun disableAll() {
launchAtomicJob(Dispatchers.Default) {
launchJob(Dispatchers.Default) {
repository.disableAllSources()
}
}
@@ -116,7 +118,7 @@ class SourcesManageViewModel @Inject constructor(
}
fun onTipClosed(item: SourceConfigItem.Tip) {
launchAtomicJob(Dispatchers.Default) {
launchJob(Dispatchers.Default) {
settings.closeTip(item.key)
}
}
@@ -203,15 +205,6 @@ class SourcesManageViewModel @Inject constructor(
return locale.getDisplayLanguage(locale).toTitleCase(locale)
}
private fun launchAtomicJob(
context: CoroutineContext = EmptyCoroutineContext,
block: suspend CoroutineScope.() -> Unit
) = launchJob(start = CoroutineStart.ATOMIC) {
mutex.withLock {
withContext(context, block)
}
}
private fun observeTip() = settings.observeAsFlow(AppSettings.KEY_TIPS_CLOSED) {
isTipEnabled(TIP_REORDER)
}