Fix sources reordering

pull/462/head
Koitharu 3 years ago
parent ba0ea5a9fc
commit b3b022807a
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -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) { suspend fun setPosition(source: MangaSource, index: Int) {
db.withTransaction { db.withTransaction {
val all = dao.findAll().toMutableList() val all = dao.findAll().toMutableList()

@ -172,10 +172,20 @@ class SourcesManageFragment :
recyclerView: RecyclerView, recyclerView: RecyclerView,
viewHolder: RecyclerView.ViewHolder, viewHolder: RecyclerView.ViewHolder,
target: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder,
): Boolean = viewHolder.itemViewType == target.itemViewType && viewModel.reorderSources( ): Boolean = viewHolder.itemViewType == target.itemViewType
viewHolder.bindingAdapterPosition,
target.bindingAdapterPosition, 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( override fun canDropOver(
recyclerView: RecyclerView, recyclerView: RecyclerView,

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

Loading…
Cancel
Save