mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-21 20:47:03 -05:00
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.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
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 {
|
object MigrationFlags {
|
||||||
|
|
||||||
private const val CHAPTERS = 0b00001
|
private const val CHAPTERS = 0b00001
|
||||||
|
@ -23,9 +39,6 @@ object MigrationFlags {
|
||||||
private val getTracks: GetTracks = Injekt.get()
|
private val getTracks: GetTracks = Injekt.get()
|
||||||
private val downloadCache: DownloadCache by injectLazy()
|
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 {
|
fun hasChapters(value: Int): Boolean {
|
||||||
return value and CHAPTERS != 0
|
return value and CHAPTERS != 0
|
||||||
}
|
}
|
||||||
|
@ -46,34 +59,35 @@ object MigrationFlags {
|
||||||
return value and DELETE_DOWNLOADED != 0
|
return value and DELETE_DOWNLOADED != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getEnabledFlagsPositions(value: Int): List<Int> {
|
/** Returns information about applicable flags with default selections. */
|
||||||
return flags.mapIndexedNotNull { index, flag -> if (value and flag != 0) index else null }
|
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 (manga != null) {
|
||||||
if (runBlocking { getTracks.await(manga.id) }.isNotEmpty()) {
|
if (runBlocking { getTracks.await(manga.id) }.isNotEmpty()) {
|
||||||
titles.add(R.string.track)
|
flags += MigrationFlag.create(TRACK, defaultSelectedBitMap, R.string.track)
|
||||||
enableFlags.add(TRACK)
|
|
||||||
}
|
}
|
||||||
if (manga.hasCustomCover(coverCache)) {
|
if (manga.hasCustomCover(coverCache)) {
|
||||||
titles.add(R.string.custom_cover)
|
flags += MigrationFlag.create(CUSTOM_COVER, defaultSelectedBitMap, R.string.custom_cover)
|
||||||
enableFlags.add(CUSTOM_COVER)
|
|
||||||
}
|
}
|
||||||
if (downloadCache.getDownloadCount(manga) > 0) {
|
if (downloadCache.getDownloadCount(manga) > 0) {
|
||||||
titles.add(R.string.delete_downloaded)
|
flags += MigrationFlag.create(DELETE_DOWNLOADED, defaultSelectedBitMap, R.string.delete_downloaded)
|
||||||
enableFlags.add(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.Immutable
|
||||||
import androidx.compose.runtime.collectAsState
|
import androidx.compose.runtime.collectAsState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateListOf
|
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.toMutableStateList
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.util.fastForEachIndexed
|
|
||||||
import cafe.adriel.voyager.core.model.StateScreenModel
|
import cafe.adriel.voyager.core.model.StateScreenModel
|
||||||
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
|
||||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||||
|
@ -74,15 +73,8 @@ internal fun MigrateDialog(
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val state by screenModel.state.collectAsState()
|
val state by screenModel.state.collectAsState()
|
||||||
|
|
||||||
val activeFlags = remember { MigrationFlags.getEnabledFlagsPositions(screenModel.migrateFlags.get()) }
|
val flags = remember { MigrationFlags.getFlags(oldManga, screenModel.migrateFlags.get()) }
|
||||||
val items = remember {
|
val selectedFlags = remember { flags.map { it.isDefaultSelected }.toMutableStateList() }
|
||||||
MigrationFlags.titles(oldManga)
|
|
||||||
.map { context.getString(it) }
|
|
||||||
.toList()
|
|
||||||
}
|
|
||||||
val selected = remember {
|
|
||||||
mutableStateListOf(*List(items.size) { i -> activeFlags.contains(i) }.toTypedArray())
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state.isMigrating) {
|
if (state.isMigrating) {
|
||||||
LoadingScreen(
|
LoadingScreen(
|
||||||
|
@ -99,18 +91,16 @@ internal fun MigrateDialog(
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.verticalScroll(rememberScrollState()),
|
modifier = Modifier.verticalScroll(rememberScrollState()),
|
||||||
) {
|
) {
|
||||||
items.forEachIndexed { index, title ->
|
flags.forEachIndexed { index, flag ->
|
||||||
val onChange: () -> Unit = {
|
val onChange = { selectedFlags[index] = !selectedFlags[index] }
|
||||||
selected[index] = !selected[index]
|
|
||||||
}
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.clickable(onClick = onChange),
|
.clickable(onClick = onChange),
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
Checkbox(checked = selected[index], onCheckedChange = { onChange() })
|
Checkbox(checked = selectedFlags[index], onCheckedChange = { onChange() })
|
||||||
Text(text = title)
|
Text(text = context.getString(flag.titleId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -133,7 +123,12 @@ internal fun MigrateDialog(
|
||||||
TextButton(
|
TextButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
scope.launchIO {
|
scope.launchIO {
|
||||||
screenModel.migrateManga(oldManga, newManga, false)
|
screenModel.migrateManga(
|
||||||
|
oldManga,
|
||||||
|
newManga,
|
||||||
|
false,
|
||||||
|
MigrationFlags.getSelectedFlagsBitMap(selectedFlags, flags),
|
||||||
|
)
|
||||||
withUIContext { onPopScreen() }
|
withUIContext { onPopScreen() }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -143,12 +138,13 @@ internal fun MigrateDialog(
|
||||||
TextButton(
|
TextButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
scope.launchIO {
|
scope.launchIO {
|
||||||
val selectedIndices = mutableListOf<Int>()
|
screenModel.migrateManga(
|
||||||
selected.fastForEachIndexed { i, b -> if (b) selectedIndices.add(i) }
|
oldManga,
|
||||||
val newValue =
|
newManga,
|
||||||
MigrationFlags.getFlagsFromPositions(selectedIndices.toTypedArray())
|
true,
|
||||||
screenModel.migrateFlags.set(newValue)
|
MigrationFlags.getSelectedFlagsBitMap(selectedFlags, flags),
|
||||||
screenModel.migrateManga(oldManga, newManga, true)
|
)
|
||||||
|
|
||||||
withUIContext { onPopScreen() }
|
withUIContext { onPopScreen() }
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -184,7 +180,13 @@ internal class MigrateDialogScreenModel(
|
||||||
Injekt.get<TrackManager>().services.filterIsInstance<EnhancedTrackService>()
|
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 source = sourceManager.get(newManga.source) ?: return
|
||||||
val prevSource = sourceManager.get(oldManga.source)
|
val prevSource = sourceManager.get(oldManga.source)
|
||||||
|
|
||||||
|
@ -200,6 +202,7 @@ internal class MigrateDialogScreenModel(
|
||||||
newManga = newManga,
|
newManga = newManga,
|
||||||
sourceChapters = chapters,
|
sourceChapters = chapters,
|
||||||
replace = replace,
|
replace = replace,
|
||||||
|
flags = flags,
|
||||||
)
|
)
|
||||||
} catch (_: Throwable) {
|
} catch (_: Throwable) {
|
||||||
// Explicitly stop if an error occurred; the dialog normally gets popped at the end
|
// Explicitly stop if an error occurred; the dialog normally gets popped at the end
|
||||||
|
@ -215,9 +218,8 @@ internal class MigrateDialogScreenModel(
|
||||||
newManga: Manga,
|
newManga: Manga,
|
||||||
sourceChapters: List<SChapter>,
|
sourceChapters: List<SChapter>,
|
||||||
replace: Boolean,
|
replace: Boolean,
|
||||||
|
flags: Int,
|
||||||
) {
|
) {
|
||||||
val flags = migrateFlags.get()
|
|
||||||
|
|
||||||
val migrateChapters = MigrationFlags.hasChapters(flags)
|
val migrateChapters = MigrationFlags.hasChapters(flags)
|
||||||
val migrateCategories = MigrationFlags.hasCategories(flags)
|
val migrateCategories = MigrationFlags.hasCategories(flags)
|
||||||
val migrateTracks = MigrationFlags.hasTracks(flags)
|
val migrateTracks = MigrationFlags.hasTracks(flags)
|
||||||
|
|
Loading…
Reference in a new issue