mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01: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:
		@@ -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 New Issue
	
	Block a user