Fix migration flags usage (incorrect defaults and copy mode) (#9805)
* Fix migration flags usage (incorect defaults and copy mode) * Remove unused logcat import left from testing.
This commit is contained in:
parent
af0fdfa3b7
commit
4b7acdb022
2 changed files with 66 additions and 50 deletions
|
@ -11,6 +11,22 @@ import uy.kohesive.injekt.Injekt
|
|||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
data class MigrationFlag(
|
||||
val flag: Int,
|
||||
val isDefaultSelected: Boolean,
|
||||
val titleId: Int,
|
||||
) {
|
||||
companion object {
|
||||
fun create(flag: Int, defaultSelectionMap: Int, titleId: Int): MigrationFlag {
|
||||
return MigrationFlag(
|
||||
flag = flag,
|
||||
isDefaultSelected = defaultSelectionMap and flag != 0,
|
||||
titleId = titleId,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object MigrationFlags {
|
||||
|
||||
private const val CHAPTERS = 0b00001
|
||||
|
@ -23,9 +39,6 @@ object MigrationFlags {
|
|||
private val getTracks: GetTracks = Injekt.get()
|
||||
private val downloadCache: DownloadCache by injectLazy()
|
||||
|
||||
val flags get() = arrayOf(CHAPTERS, CATEGORIES, TRACK, CUSTOM_COVER, DELETE_DOWNLOADED)
|
||||
private var enableFlags = emptyList<Int>().toMutableList()
|
||||
|
||||
fun hasChapters(value: Int): Boolean {
|
||||
return value and CHAPTERS != 0
|
||||
}
|
||||
|
@ -46,34 +59,35 @@ object MigrationFlags {
|
|||
return value and DELETE_DOWNLOADED != 0
|
||||
}
|
||||
|
||||
fun getEnabledFlagsPositions(value: Int): List<Int> {
|
||||
return flags.mapIndexedNotNull { index, flag -> if (value and flag != 0) index else null }
|
||||
}
|
||||
/** Returns information about applicable flags with default selections. */
|
||||
fun getFlags(manga: Manga?, defaultSelectedBitMap: Int): List<MigrationFlag> {
|
||||
val flags = mutableListOf<MigrationFlag>()
|
||||
flags += MigrationFlag.create(CHAPTERS, defaultSelectedBitMap, R.string.chapters)
|
||||
flags += MigrationFlag.create(CATEGORIES, defaultSelectedBitMap, R.string.categories)
|
||||
|
||||
fun getFlagsFromPositions(positions: Array<Int>): Int {
|
||||
val fold = positions.fold(0) { accumulated, position -> accumulated or enableFlags[position] }
|
||||
enableFlags.clear()
|
||||
return fold
|
||||
}
|
||||
|
||||
fun titles(manga: Manga?): Array<Int> {
|
||||
enableFlags.add(CHAPTERS)
|
||||
enableFlags.add(CATEGORIES)
|
||||
val titles = arrayOf(R.string.chapters, R.string.categories).toMutableList()
|
||||
if (manga != null) {
|
||||
if (runBlocking { getTracks.await(manga.id) }.isNotEmpty()) {
|
||||
titles.add(R.string.track)
|
||||
enableFlags.add(TRACK)
|
||||
flags += MigrationFlag.create(TRACK, defaultSelectedBitMap, R.string.track)
|
||||
}
|
||||
if (manga.hasCustomCover(coverCache)) {
|
||||
titles.add(R.string.custom_cover)
|
||||
enableFlags.add(CUSTOM_COVER)
|
||||
flags += MigrationFlag.create(CUSTOM_COVER, defaultSelectedBitMap, R.string.custom_cover)
|
||||
}
|
||||
if (downloadCache.getDownloadCount(manga) > 0) {
|
||||
titles.add(R.string.delete_downloaded)
|
||||
enableFlags.add(DELETE_DOWNLOADED)
|
||||
flags += MigrationFlag.create(DELETE_DOWNLOADED, defaultSelectedBitMap, R.string.delete_downloaded)
|
||||
}
|
||||
}
|
||||
return titles.toTypedArray()
|
||||
return flags
|
||||
}
|
||||
|
||||
/** Returns a bit map of selected flags. */
|
||||
fun getSelectedFlagsBitMap(
|
||||
selectedFlags: List<Boolean>,
|
||||
flags: List<MigrationFlag>,
|
||||
): Int {
|
||||
return selectedFlags
|
||||
.zip(flags)
|
||||
.filter { (isSelected, _) -> isSelected }
|
||||
.map { (_, flag) -> flag.flag }
|
||||
.reduceOrNull { acc, mask -> acc or mask } ?: 0
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,15 +19,14 @@ import androidx.compose.runtime.Composable
|
|||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateListOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.toMutableStateList
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.util.fastForEachIndexed
|
||||
import cafe.adriel.voyager.core.model.StateScreenModel
|
||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||
|
@ -74,15 +73,8 @@ internal fun MigrateDialog(
|
|||
val scope = rememberCoroutineScope()
|
||||
val state by screenModel.state.collectAsState()
|
||||
|
||||
val activeFlags = remember { MigrationFlags.getEnabledFlagsPositions(screenModel.migrateFlags.get()) }
|
||||
val items = remember {
|
||||
MigrationFlags.titles(oldManga)
|
||||
.map { context.getString(it) }
|
||||
.toList()
|
||||
}
|
||||
val selected = remember {
|
||||
mutableStateListOf(*List(items.size) { i -> activeFlags.contains(i) }.toTypedArray())
|
||||
}
|
||||
val flags = remember { MigrationFlags.getFlags(oldManga, screenModel.migrateFlags.get()) }
|
||||
val selectedFlags = remember { flags.map { it.isDefaultSelected }.toMutableStateList() }
|
||||
|
||||
if (state.isMigrating) {
|
||||
LoadingScreen(
|
||||
|
@ -99,18 +91,16 @@ internal fun MigrateDialog(
|
|||
Column(
|
||||
modifier = Modifier.verticalScroll(rememberScrollState()),
|
||||
) {
|
||||
items.forEachIndexed { index, title ->
|
||||
val onChange: () -> Unit = {
|
||||
selected[index] = !selected[index]
|
||||
}
|
||||
flags.forEachIndexed { index, flag ->
|
||||
val onChange = { selectedFlags[index] = !selectedFlags[index] }
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = onChange),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
Checkbox(checked = selected[index], onCheckedChange = { onChange() })
|
||||
Text(text = title)
|
||||
Checkbox(checked = selectedFlags[index], onCheckedChange = { onChange() })
|
||||
Text(text = context.getString(flag.titleId))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -133,7 +123,12 @@ internal fun MigrateDialog(
|
|||
TextButton(
|
||||
onClick = {
|
||||
scope.launchIO {
|
||||
screenModel.migrateManga(oldManga, newManga, false)
|
||||
screenModel.migrateManga(
|
||||
oldManga,
|
||||
newManga,
|
||||
false,
|
||||
MigrationFlags.getSelectedFlagsBitMap(selectedFlags, flags),
|
||||
)
|
||||
withUIContext { onPopScreen() }
|
||||
}
|
||||
},
|
||||
|
@ -143,12 +138,13 @@ internal fun MigrateDialog(
|
|||
TextButton(
|
||||
onClick = {
|
||||
scope.launchIO {
|
||||
val selectedIndices = mutableListOf<Int>()
|
||||
selected.fastForEachIndexed { i, b -> if (b) selectedIndices.add(i) }
|
||||
val newValue =
|
||||
MigrationFlags.getFlagsFromPositions(selectedIndices.toTypedArray())
|
||||
screenModel.migrateFlags.set(newValue)
|
||||
screenModel.migrateManga(oldManga, newManga, true)
|
||||
screenModel.migrateManga(
|
||||
oldManga,
|
||||
newManga,
|
||||
true,
|
||||
MigrationFlags.getSelectedFlagsBitMap(selectedFlags, flags),
|
||||
)
|
||||
|
||||
withUIContext { onPopScreen() }
|
||||
}
|
||||
},
|
||||
|
@ -184,7 +180,13 @@ internal class MigrateDialogScreenModel(
|
|||
Injekt.get<TrackManager>().services.filterIsInstance<EnhancedTrackService>()
|
||||
}
|
||||
|
||||
suspend fun migrateManga(oldManga: Manga, newManga: Manga, replace: Boolean) {
|
||||
suspend fun migrateManga(
|
||||
oldManga: Manga,
|
||||
newManga: Manga,
|
||||
replace: Boolean,
|
||||
flags: Int,
|
||||
) {
|
||||
migrateFlags.set(flags)
|
||||
val source = sourceManager.get(newManga.source) ?: return
|
||||
val prevSource = sourceManager.get(oldManga.source)
|
||||
|
||||
|
@ -200,6 +202,7 @@ internal class MigrateDialogScreenModel(
|
|||
newManga = newManga,
|
||||
sourceChapters = chapters,
|
||||
replace = replace,
|
||||
flags = flags,
|
||||
)
|
||||
} catch (_: Throwable) {
|
||||
// Explicitly stop if an error occurred; the dialog normally gets popped at the end
|
||||
|
@ -215,9 +218,8 @@ internal class MigrateDialogScreenModel(
|
|||
newManga: Manga,
|
||||
sourceChapters: List<SChapter>,
|
||||
replace: Boolean,
|
||||
flags: Int,
|
||||
) {
|
||||
val flags = migrateFlags.get()
|
||||
|
||||
val migrateChapters = MigrationFlags.hasChapters(flags)
|
||||
val migrateCategories = MigrationFlags.hasCategories(flags)
|
||||
val migrateTracks = MigrationFlags.hasTracks(flags)
|
||||
|
|
Reference in a new issue