mirror of
https://github.com/null2264/yokai.git
synced 2025-06-21 10:44:42 +00:00
refactor: Rewrite migrator
Should also fixed auto-backup, auto-update, and update checker being stuck when it failed Co-authored-by: Andreas <andreas.everos@gmail.com>
This commit is contained in:
parent
c17be3831c
commit
573015a4b9
39 changed files with 977 additions and 347 deletions
22
app/src/main/java/dev/yokai/core/migration/Migration.kt
Normal file
22
app/src/main/java/dev/yokai/core/migration/Migration.kt
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
package dev.yokai.core.migration
|
||||||
|
|
||||||
|
interface Migration {
|
||||||
|
val version: Float
|
||||||
|
|
||||||
|
suspend operator fun invoke(migrationContext: MigrationContext): Boolean
|
||||||
|
|
||||||
|
val isAlways: Boolean
|
||||||
|
get() = version == ALWAYS
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val ALWAYS = -1f
|
||||||
|
|
||||||
|
fun of(version: Float, action: suspend (MigrationContext) -> Boolean): Migration = object : Migration {
|
||||||
|
override val version: Float = version
|
||||||
|
|
||||||
|
override suspend operator fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
return action(migrationContext)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
package dev.yokai.core.migration
|
||||||
|
|
||||||
|
typealias MigrationCompletedListener = () -> Unit
|
|
@ -0,0 +1,10 @@
|
||||||
|
package dev.yokai.core.migration
|
||||||
|
|
||||||
|
import uy.kohesive.injekt.Injekt
|
||||||
|
|
||||||
|
class MigrationContext(val dryRun: Boolean) {
|
||||||
|
|
||||||
|
inline fun <reified T> get(): T? {
|
||||||
|
return Injekt.getInstanceOrNull(T::class.java)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package dev.yokai.core.migration
|
||||||
|
|
||||||
|
import co.touchlab.kermit.Logger
|
||||||
|
import kotlinx.coroutines.CompletableDeferred
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Deferred
|
||||||
|
import kotlinx.coroutines.async
|
||||||
|
|
||||||
|
class MigrationJobFactory(
|
||||||
|
private val migrationContext: MigrationContext,
|
||||||
|
private val scope: CoroutineScope
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun create(migrations: List<Migration>): Deferred<Boolean> = with(scope) {
|
||||||
|
return migrations.sortedBy { it.version }
|
||||||
|
.fold(CompletableDeferred(true)) { acc: Deferred<Boolean>, migration: Migration ->
|
||||||
|
if (!migrationContext.dryRun) {
|
||||||
|
Logger.i { "Running migration: { name = ${migration::class.simpleName}, version = ${migration.version} }" }
|
||||||
|
async {
|
||||||
|
val prev = acc.await()
|
||||||
|
migration(migrationContext) || prev
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Logger.i { "(Dry-run) Running migration: { name = ${migration::class.simpleName}, version = ${migration.version} }" }
|
||||||
|
CompletableDeferred(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package dev.yokai.core.migration
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CompletableDeferred
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Deferred
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
|
interface MigrationStrategy {
|
||||||
|
operator fun invoke(migrations: List<Migration>): Deferred<Boolean>
|
||||||
|
}
|
||||||
|
|
||||||
|
class DefaultMigrationStrategy(
|
||||||
|
private val migrationJobFactory: MigrationJobFactory,
|
||||||
|
private val migrationCompletedListener: MigrationCompletedListener,
|
||||||
|
private val scope: CoroutineScope
|
||||||
|
) : MigrationStrategy {
|
||||||
|
|
||||||
|
override operator fun invoke(migrations: List<Migration>): Deferred<Boolean> = with(scope) {
|
||||||
|
if (migrations.isEmpty()) {
|
||||||
|
return@with CompletableDeferred(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
val chain = migrationJobFactory.create(migrations)
|
||||||
|
|
||||||
|
launch {
|
||||||
|
if (chain.await()) migrationCompletedListener()
|
||||||
|
}.start()
|
||||||
|
|
||||||
|
chain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class InitialMigrationStrategy(private val strategy: DefaultMigrationStrategy) : MigrationStrategy {
|
||||||
|
|
||||||
|
override operator fun invoke(migrations: List<Migration>): Deferred<Boolean> {
|
||||||
|
return strategy(migrations.filter { it.isAlways })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class NoopMigrationStrategy(val state: Boolean) : MigrationStrategy {
|
||||||
|
|
||||||
|
override fun invoke(migrations: List<Migration>): Deferred<Boolean> {
|
||||||
|
return CompletableDeferred(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class VersionRangeMigrationStrategy(
|
||||||
|
private val versions: IntRange,
|
||||||
|
private val strategy: DefaultMigrationStrategy
|
||||||
|
) : MigrationStrategy {
|
||||||
|
|
||||||
|
override operator fun invoke(migrations: List<Migration>): Deferred<Boolean> {
|
||||||
|
return strategy(migrations.filter { it.isAlways || it.version.toInt() in versions })
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package dev.yokai.core.migration
|
||||||
|
|
||||||
|
class MigrationStrategyFactory(
|
||||||
|
private val factory: MigrationJobFactory,
|
||||||
|
private val migrationCompletedListener: MigrationCompletedListener,
|
||||||
|
) {
|
||||||
|
|
||||||
|
fun create(old: Int, new: Int): MigrationStrategy {
|
||||||
|
val versions = (old + 1)..new
|
||||||
|
val strategy = when {
|
||||||
|
old == 0 -> InitialMigrationStrategy(
|
||||||
|
strategy = DefaultMigrationStrategy(factory, migrationCompletedListener, Migrator.scope),
|
||||||
|
)
|
||||||
|
|
||||||
|
old >= new -> NoopMigrationStrategy(false)
|
||||||
|
else -> VersionRangeMigrationStrategy(
|
||||||
|
versions = versions,
|
||||||
|
strategy = DefaultMigrationStrategy(factory, migrationCompletedListener, Migrator.scope),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return strategy
|
||||||
|
}
|
||||||
|
}
|
40
app/src/main/java/dev/yokai/core/migration/Migrator.kt
Normal file
40
app/src/main/java/dev/yokai/core/migration/Migrator.kt
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
package dev.yokai.core.migration
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CompletableDeferred
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Deferred
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.runBlocking
|
||||||
|
|
||||||
|
object Migrator {
|
||||||
|
private var result: Deferred<Boolean>? = null
|
||||||
|
val scope = CoroutineScope(Dispatchers.Main + Job())
|
||||||
|
|
||||||
|
fun initialize(
|
||||||
|
old: Int,
|
||||||
|
new: Int,
|
||||||
|
migrations: List<Migration>,
|
||||||
|
dryRun: Boolean = false,
|
||||||
|
onMigrationComplete: () -> Unit
|
||||||
|
) {
|
||||||
|
val migrationContext = MigrationContext(dryRun)
|
||||||
|
val migrationJobFactory = MigrationJobFactory(migrationContext, scope)
|
||||||
|
val migrationStrategyFactory = MigrationStrategyFactory(migrationJobFactory, onMigrationComplete)
|
||||||
|
val strategy = migrationStrategyFactory.create(old, new)
|
||||||
|
result = strategy(migrations)
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun await(): Boolean {
|
||||||
|
val result = result ?: CompletableDeferred(false)
|
||||||
|
return result.await()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun release() {
|
||||||
|
result = null
|
||||||
|
}
|
||||||
|
|
||||||
|
fun awaitAndRelease(): Boolean = runBlocking {
|
||||||
|
await().also { release() }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete external chapter cache dir.
|
||||||
|
*/
|
||||||
|
class ChapterCacheMigration : Migration {
|
||||||
|
override val version: Float = 26f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
val extCache = context.externalCacheDir
|
||||||
|
if (extCache != null) {
|
||||||
|
val chapterCache = File(extCache, "chapter_disk_cache")
|
||||||
|
if (chapterCache.exists()) {
|
||||||
|
chapterCache.deleteRecursively()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move covers to external files dir.
|
||||||
|
*/
|
||||||
|
class CoverCacheMigration : Migration {
|
||||||
|
override val version: Float = 19f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
val oldDir = File(context.externalCacheDir, "cover_disk_cache")
|
||||||
|
if (oldDir.exists()) {
|
||||||
|
val destDir = context.getExternalFilesDir("covers")
|
||||||
|
if (destDir != null) {
|
||||||
|
oldDir.listFiles()?.forEach {
|
||||||
|
it.renameTo(File(destDir, it.name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.ui.library.LibraryPresenter
|
||||||
|
|
||||||
|
class CustomInfoMigration : Migration {
|
||||||
|
override val version: Float = 66f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
try {
|
||||||
|
LibraryPresenter.updateCustoms()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,47 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import dev.yokai.domain.ui.settings.ReaderPreferences
|
||||||
|
import dev.yokai.domain.ui.settings.ReaderPreferences.CutoutBehaviour
|
||||||
|
import dev.yokai.domain.ui.settings.ReaderPreferences.LandscapeCutoutBehaviour
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferenceKeys
|
||||||
|
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerConfig
|
||||||
|
|
||||||
|
class CutoutMigration : Migration {
|
||||||
|
override val version: Float = 121f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val readerPreferences: ReaderPreferences = migrationContext.get() ?: return false
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
|
try {
|
||||||
|
val oldCutoutBehaviour = prefs.getInt(PreferenceKeys.pagerCutoutBehavior, 0)
|
||||||
|
readerPreferences.pagerCutoutBehavior().set(
|
||||||
|
when (oldCutoutBehaviour) {
|
||||||
|
PagerConfig.CUTOUT_PAD -> CutoutBehaviour.HIDE
|
||||||
|
PagerConfig.CUTOUT_IGNORE -> CutoutBehaviour.IGNORE
|
||||||
|
else -> CutoutBehaviour.SHOW
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} catch (_: Exception) {
|
||||||
|
readerPreferences.pagerCutoutBehavior().set(CutoutBehaviour.SHOW)
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
val oldCutoutBehaviour = prefs.getInt("landscape_cutout_behavior", 0)
|
||||||
|
readerPreferences.landscapeCutoutBehavior().set(
|
||||||
|
when (oldCutoutBehaviour) {
|
||||||
|
0 -> LandscapeCutoutBehaviour.HIDE
|
||||||
|
else -> LandscapeCutoutBehaviour.DEFAULT
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} catch (_: Exception) {
|
||||||
|
readerPreferences.landscapeCutoutBehavior().set(LandscapeCutoutBehaviour.DEFAULT)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import androidx.core.content.edit
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferenceKeys
|
||||||
|
import eu.kanade.tachiyomi.network.PREF_DOH_CLOUDFLARE
|
||||||
|
|
||||||
|
class DoHMigration : Migration {
|
||||||
|
override val version: Float = 71f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
// Migrate DNS over HTTPS setting
|
||||||
|
val wasDohEnabled = prefs.getBoolean("enable_doh", false)
|
||||||
|
if (wasDohEnabled) {
|
||||||
|
prefs.edit {
|
||||||
|
putInt(PreferenceKeys.dohProvider, PREF_DOH_CLOUDFLARE)
|
||||||
|
remove("enable_doh")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import eu.kanade.tachiyomi.data.download.DownloadProvider
|
||||||
|
|
||||||
|
class DownloadedChaptersMigration : Migration {
|
||||||
|
override val version: Float = 54f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
DownloadProvider(context).renameChapters()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.data.preference.plusAssign
|
||||||
|
|
||||||
|
class EnabledLanguageMigration : Migration {
|
||||||
|
override val version: Float = 83f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
val preferences: PreferencesHelper = migrationContext.get() ?: return false
|
||||||
|
|
||||||
|
if (preferences.enabledLanguages().isSet()) {
|
||||||
|
preferences.enabledLanguages() += "all"
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import eu.kanade.tachiyomi.BuildConfig
|
||||||
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||||
|
import eu.kanade.tachiyomi.data.updater.AppUpdateJob
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore jobs after upgrading to evernote's job scheduler.
|
||||||
|
*/
|
||||||
|
class EvernoteJobUpgradeMigration : Migration {
|
||||||
|
override val version: Float = 14f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
if (BuildConfig.INCLUDE_UPDATER) {
|
||||||
|
AppUpdateJob.setupTask(context)
|
||||||
|
}
|
||||||
|
LibraryUpdateJob.setupTask(context)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import dev.yokai.domain.base.BasePreferences
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Upstream no longer use Int for extension installer prefs, this solves incompatibility with upstreams backup
|
||||||
|
*/
|
||||||
|
class ExtensionInstallerEnumMigration : Migration {
|
||||||
|
override val version: Float = 119f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val basePreferences: BasePreferences = migrationContext.get() ?: return false
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
|
try {
|
||||||
|
val oldExtensionInstall = prefs.getInt("extension_installer", 0)
|
||||||
|
basePreferences.extensionInstaller().set(
|
||||||
|
when (oldExtensionInstall) {
|
||||||
|
1 -> BasePreferences.ExtensionInstaller.SHIZUKU
|
||||||
|
2 -> BasePreferences.ExtensionInstaller.PRIVATE
|
||||||
|
else -> BasePreferences.ExtensionInstaller.PACKAGEINSTALLER
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} catch (_: Exception) {
|
||||||
|
basePreferences.extensionInstaller().set(BasePreferences.ExtensionInstaller.PACKAGEINSTALLER)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete internal chapter cache dir.
|
||||||
|
*/
|
||||||
|
class InternalChapterCacheUpdateMigration : Migration {
|
||||||
|
override val version: Float = 15f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
File(context.cacheDir, "chapter_disk_cache").deleteRecursively()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import androidx.core.content.edit
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import eu.kanade.tachiyomi.ui.library.LibrarySort
|
||||||
|
|
||||||
|
class LibrarySortMigration : Migration {
|
||||||
|
override val version: Float = 110f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
|
try {
|
||||||
|
val librarySortString = prefs.getString("library_sorting_mode", "")
|
||||||
|
if (!librarySortString.isNullOrEmpty()) {
|
||||||
|
prefs.edit {
|
||||||
|
remove("library_sorting_mode")
|
||||||
|
putInt(
|
||||||
|
"library_sorting_mode",
|
||||||
|
LibrarySort.deserialize(librarySortString).mainValue,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (_: Exception) {
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||||
|
|
||||||
|
class LibraryUpdateResetMigration : Migration {
|
||||||
|
override val version: Float = 105f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
LibraryUpdateJob.cancelAllWorks(context)
|
||||||
|
LibraryUpdateJob.setupTask(context)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
|
||||||
|
val migrations: ImmutableList<Migration> = persistentListOf(
|
||||||
|
SetupAppUpdateMigration(),
|
||||||
|
SetupBackupCreateMigration(),
|
||||||
|
SetupExtensionUpdateMigration(),
|
||||||
|
SetupLibraryUpdateMigration(),
|
||||||
|
|
||||||
|
// For archive purposes
|
||||||
|
EvernoteJobUpgradeMigration(),
|
||||||
|
InternalChapterCacheUpdateMigration(),
|
||||||
|
CoverCacheMigration(),
|
||||||
|
ChapterCacheMigration(),
|
||||||
|
DownloadedChaptersMigration(),
|
||||||
|
WorkManagerMigration(),
|
||||||
|
CustomInfoMigration(),
|
||||||
|
MyAnimeListMigration(),
|
||||||
|
DoHMigration(),
|
||||||
|
RotationTypeMigration(),
|
||||||
|
ShortcutsMigration(),
|
||||||
|
RotationTypeEnumMigration(),
|
||||||
|
EnabledLanguageMigration(),
|
||||||
|
UpdateIntervalMigration(),
|
||||||
|
ReaderUpdateMigration(),
|
||||||
|
PrefsMigration(),
|
||||||
|
LibraryUpdateResetMigration(),
|
||||||
|
TrackerPrivateSettingsMigration(),
|
||||||
|
LibrarySortMigration(),
|
||||||
|
|
||||||
|
// Yokai fork
|
||||||
|
ThePurgeMigration(),
|
||||||
|
ExtensionInstallerEnumMigration(),
|
||||||
|
CutoutMigration(),
|
||||||
|
RepoJsonMigration(),
|
||||||
|
)
|
|
@ -0,0 +1,28 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Force MAL log out due to login flow change
|
||||||
|
* v67: switched from scraping to WebView
|
||||||
|
* v68: switched from WebView to OAuth
|
||||||
|
*/
|
||||||
|
class MyAnimeListMigration : Migration {
|
||||||
|
override val version: Float = 68f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val trackManager: TrackManager = migrationContext.get() ?: return false
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
|
||||||
|
if (trackManager.myAnimeList.isLogged) {
|
||||||
|
trackManager.myAnimeList.logout()
|
||||||
|
context.toast(R.string.myanimelist_relogin)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferenceValues
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.ui.recents.RecentsPresenter
|
||||||
|
import kotlin.math.max
|
||||||
|
|
||||||
|
class PrefsMigration : Migration {
|
||||||
|
override val version: Float = 102f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
val preferences: PreferencesHelper = migrationContext.get() ?: return false
|
||||||
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
|
val oldSecureScreen = prefs.getBoolean("secure_screen", false)
|
||||||
|
if (oldSecureScreen) {
|
||||||
|
preferences.secureScreen().set(PreferenceValues.SecureScreenMode.ALWAYS)
|
||||||
|
}
|
||||||
|
|
||||||
|
val oldDLAfterReading = prefs.getInt("auto_download_after_reading", 0)
|
||||||
|
if (oldDLAfterReading > 0) {
|
||||||
|
preferences.autoDownloadWhileReading().set(max(2, oldDLAfterReading))
|
||||||
|
}
|
||||||
|
|
||||||
|
val oldGroupHistory = prefs.getBoolean("group_chapters_history", true)
|
||||||
|
if (!oldGroupHistory) {
|
||||||
|
preferences.groupChaptersHistory().set(RecentsPresenter.GroupType.Never)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
import eu.kanade.tachiyomi.ui.library.LibraryPresenter
|
||||||
|
import eu.kanade.tachiyomi.util.system.withIOContext
|
||||||
|
|
||||||
|
class ReaderUpdateMigration : Migration {
|
||||||
|
override val version: Float = 88f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
val preferences: PreferencesHelper = migrationContext.get() ?: return false
|
||||||
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
|
withIOContext {
|
||||||
|
LibraryPresenter.updateRatiosAndColors()
|
||||||
|
}
|
||||||
|
val oldReaderTap = prefs.getBoolean("reader_tap", true)
|
||||||
|
if (!oldReaderTap) {
|
||||||
|
preferences.navigationModePager().set(5)
|
||||||
|
preferences.navigationModeWebtoon().set(5)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import co.touchlab.kermit.Logger
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import dev.yokai.domain.extension.repo.ExtensionRepoRepository
|
||||||
|
import dev.yokai.domain.extension.repo.exception.SaveExtensionRepoException
|
||||||
|
import eu.kanade.tachiyomi.core.preference.Preference
|
||||||
|
import eu.kanade.tachiyomi.core.preference.PreferenceStore
|
||||||
|
import eu.kanade.tachiyomi.util.system.withIOContext
|
||||||
|
|
||||||
|
class RepoJsonMigration : Migration {
|
||||||
|
override val version: Float = 130f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean = withIOContext {
|
||||||
|
val extensionRepoRepository: ExtensionRepoRepository = migrationContext.get() ?: return@withIOContext false
|
||||||
|
val preferenceStore: PreferenceStore = migrationContext.get() ?: return@withIOContext false
|
||||||
|
val extensionRepos: Preference<Set<String>> = preferenceStore.getStringSet("extension_repos", emptySet())
|
||||||
|
|
||||||
|
for ((index, source) in extensionRepos.get().withIndex()) {
|
||||||
|
try {
|
||||||
|
extensionRepoRepository.upsertRepository(
|
||||||
|
source,
|
||||||
|
"Repo #${index + 1}",
|
||||||
|
null,
|
||||||
|
source,
|
||||||
|
"NOFINGERPRINT-${index + 1}",
|
||||||
|
)
|
||||||
|
} catch (e: SaveExtensionRepoException) {
|
||||||
|
Logger.e(e) { "Error Migrating Extension Repo with baseUrl: $source" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extensionRepos.delete()
|
||||||
|
|
||||||
|
return@withIOContext true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import androidx.core.content.edit
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import eu.kanade.tachiyomi.ui.reader.settings.OrientationType
|
||||||
|
|
||||||
|
class RotationTypeEnumMigration : Migration {
|
||||||
|
override val version: Float = 77f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
|
// Migrate Rotation and Viewer values to default values for viewer_flags
|
||||||
|
val newOrientation = when (prefs.getInt("pref_rotation_type_key", 1)) {
|
||||||
|
1 -> OrientationType.FREE.flagValue
|
||||||
|
2 -> OrientationType.PORTRAIT.flagValue
|
||||||
|
3 -> OrientationType.LANDSCAPE.flagValue
|
||||||
|
4 -> OrientationType.LOCKED_PORTRAIT.flagValue
|
||||||
|
5 -> OrientationType.LOCKED_LANDSCAPE.flagValue
|
||||||
|
else -> OrientationType.FREE.flagValue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reading mode flag and prefValue is the same value
|
||||||
|
val newReadingMode = prefs.getInt("pref_default_viewer_key", 1)
|
||||||
|
|
||||||
|
prefs.edit {
|
||||||
|
putInt("pref_default_orientation_type_key", newOrientation)
|
||||||
|
remove("pref_rotation_type_key")
|
||||||
|
putInt("pref_default_reading_mode_key", newReadingMode)
|
||||||
|
remove("pref_default_viewer_key")
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import androidx.core.content.edit
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
|
||||||
|
class RotationTypeMigration : Migration {
|
||||||
|
override val version: Float = 73f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
if (prefs.contains("pref_rotation_type_key")) {
|
||||||
|
prefs.edit {
|
||||||
|
putInt("pref_rotation_type_key", 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import eu.kanade.tachiyomi.BuildConfig
|
||||||
|
import eu.kanade.tachiyomi.data.updater.AppUpdateJob
|
||||||
|
|
||||||
|
class SetupAppUpdateMigration : Migration {
|
||||||
|
override val version: Float = Migration.ALWAYS
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
if (!BuildConfig.INCLUDE_UPDATER) return false
|
||||||
|
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
AppUpdateJob.setupTask(context)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import eu.kanade.tachiyomi.data.backup.create.BackupCreatorJob
|
||||||
|
|
||||||
|
class SetupBackupCreateMigration : Migration {
|
||||||
|
override val version: Float = Migration.ALWAYS
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
BackupCreatorJob.setupTask(context)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
|
||||||
|
|
||||||
|
class SetupExtensionUpdateMigration : Migration {
|
||||||
|
override val version: Float = Migration.ALWAYS
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
ExtensionUpdateJob.setupTask(context)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||||
|
|
||||||
|
class SetupLibraryUpdateMigration : Migration {
|
||||||
|
override val version: Float = Migration.ALWAYS
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
LibraryUpdateJob.setupTask(context)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import androidx.core.content.edit
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferenceKeys
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
|
||||||
|
class ShortcutsMigration : Migration {
|
||||||
|
override val version: Float = 75f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
val preferences: PreferencesHelper = migrationContext.get() ?: return false
|
||||||
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
|
val wasShortcutsDisabled = !prefs.getBoolean("show_manga_app_shortcuts", true)
|
||||||
|
if (wasShortcutsDisabled) {
|
||||||
|
prefs.edit {
|
||||||
|
putBoolean(PreferenceKeys.showSourcesInShortcuts, false)
|
||||||
|
putBoolean(PreferenceKeys.showSeriesInShortcuts, false)
|
||||||
|
remove("show_manga_app_shortcuts")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Handle removed every 1 or 2 hour library updates
|
||||||
|
val updateInterval = preferences.libraryUpdateInterval().get()
|
||||||
|
if (updateInterval == 1 || updateInterval == 2) {
|
||||||
|
preferences.libraryUpdateInterval().set(3)
|
||||||
|
LibraryUpdateJob.setupTask(context, 3)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import androidx.core.content.edit
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
|
||||||
|
class ThePurgeMigration : Migration {
|
||||||
|
override val version: Float = 112f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
|
prefs.edit {
|
||||||
|
remove("trusted_signatures")
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.core.preference.Preference
|
||||||
|
import eu.kanade.tachiyomi.core.preference.PreferenceStore
|
||||||
|
|
||||||
|
class TrackerPrivateSettingsMigration : Migration {
|
||||||
|
override val version: Float = 108f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val preferenceStore: PreferenceStore = migrationContext.get() ?: return false
|
||||||
|
preferenceStore.getAll()
|
||||||
|
.filter { it.key.startsWith("pref_mangasync_") || it.key.startsWith("track_token_") }
|
||||||
|
.forEach { (key, value) ->
|
||||||
|
if (value is String) {
|
||||||
|
preferenceStore
|
||||||
|
.getString(Preference.privateKey(key))
|
||||||
|
.set(value)
|
||||||
|
|
||||||
|
preferenceStore.getString(key).delete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||||
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
|
|
||||||
|
class UpdateIntervalMigration : Migration {
|
||||||
|
override val version: Float = 86f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
val preferences: PreferencesHelper = migrationContext.get() ?: return false
|
||||||
|
|
||||||
|
// Handle removed every 3, 4, 6, and 8 hour library updates
|
||||||
|
val updateInterval = preferences.libraryUpdateInterval().get()
|
||||||
|
if (updateInterval in listOf(3, 4, 6, 8)) {
|
||||||
|
preferences.libraryUpdateInterval().set(12)
|
||||||
|
LibraryUpdateJob.setupTask(context, 12)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package dev.yokai.core.migration.migrations
|
||||||
|
|
||||||
|
import dev.yokai.core.migration.Migration
|
||||||
|
import dev.yokai.core.migration.MigrationContext
|
||||||
|
import eu.kanade.tachiyomi.App
|
||||||
|
import eu.kanade.tachiyomi.BuildConfig
|
||||||
|
import eu.kanade.tachiyomi.data.backup.create.BackupCreatorJob
|
||||||
|
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
||||||
|
import eu.kanade.tachiyomi.data.updater.AppUpdateJob
|
||||||
|
import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
|
||||||
|
import eu.kanade.tachiyomi.ui.library.LibraryPresenter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Restore jobs after migrating from Evernote's job scheduler to WorkManager.
|
||||||
|
*/
|
||||||
|
class WorkManagerMigration : Migration {
|
||||||
|
override val version: Float = 62f
|
||||||
|
|
||||||
|
override suspend fun invoke(migrationContext: MigrationContext): Boolean {
|
||||||
|
val context: App = migrationContext.get() ?: return false
|
||||||
|
LibraryPresenter.updateDB()
|
||||||
|
if (BuildConfig.INCLUDE_UPDATER) {
|
||||||
|
AppUpdateJob.setupTask(context)
|
||||||
|
}
|
||||||
|
LibraryUpdateJob.setupTask(context)
|
||||||
|
BackupCreatorJob.setupTask(context)
|
||||||
|
ExtensionUpdateJob.setupTask(context)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,8 +38,12 @@ import dev.yokai.core.CrashlyticsLogWriter
|
||||||
import dev.yokai.core.di.AppModule
|
import dev.yokai.core.di.AppModule
|
||||||
import dev.yokai.core.di.DomainModule
|
import dev.yokai.core.di.DomainModule
|
||||||
import dev.yokai.core.di.PreferenceModule
|
import dev.yokai.core.di.PreferenceModule
|
||||||
|
import dev.yokai.core.migration.Migrator
|
||||||
|
import dev.yokai.core.migration.migrations.migrations
|
||||||
import dev.yokai.domain.base.BasePreferences
|
import dev.yokai.domain.base.BasePreferences
|
||||||
import eu.kanade.tachiyomi.appwidget.TachiyomiWidgetManager
|
import eu.kanade.tachiyomi.appwidget.TachiyomiWidgetManager
|
||||||
|
import eu.kanade.tachiyomi.core.preference.Preference
|
||||||
|
import eu.kanade.tachiyomi.core.preference.PreferenceStore
|
||||||
import eu.kanade.tachiyomi.data.coil.BufferedSourceFetcher
|
import eu.kanade.tachiyomi.data.coil.BufferedSourceFetcher
|
||||||
import eu.kanade.tachiyomi.data.coil.CoilDiskCache
|
import eu.kanade.tachiyomi.data.coil.CoilDiskCache
|
||||||
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
|
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
|
||||||
|
@ -154,6 +158,34 @@ open class App : Application(), DefaultLifecycleObserver, SingletonImageLoader.F
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.launchIn(ProcessLifecycleOwner.get().lifecycleScope)
|
.launchIn(ProcessLifecycleOwner.get().lifecycleScope)
|
||||||
|
|
||||||
|
initializeMigrator()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun initializeMigrator() {
|
||||||
|
val preferenceStore = Injekt.get<PreferenceStore>()
|
||||||
|
|
||||||
|
val preference = preferenceStore.getInt(
|
||||||
|
Preference.appStateKey("last_version_code"),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
// TODO: Remove later
|
||||||
|
val old = preferenceStore.getInt("last_version_code", -1)
|
||||||
|
if (old.get() >= preference.get()) {
|
||||||
|
preference.set(old.get())
|
||||||
|
old.delete()
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger.i { "Migration from ${preference.get()} to ${BuildConfig.VERSION_CODE}" }
|
||||||
|
Migrator.initialize(
|
||||||
|
old = preference.get(),
|
||||||
|
new = BuildConfig.VERSION_CODE,
|
||||||
|
migrations = migrations,
|
||||||
|
onMigrationComplete = {
|
||||||
|
Logger.i { "Updating last version to ${BuildConfig.VERSION_CODE}" }
|
||||||
|
preference.set(BuildConfig.VERSION_CODE)
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause(owner: LifecycleOwner) {
|
override fun onPause(owner: LifecycleOwner) {
|
||||||
|
|
|
@ -1,342 +0,0 @@
|
||||||
package eu.kanade.tachiyomi
|
|
||||||
|
|
||||||
import androidx.core.content.edit
|
|
||||||
import androidx.preference.PreferenceManager
|
|
||||||
import co.touchlab.kermit.Logger
|
|
||||||
import dev.yokai.domain.base.BasePreferences
|
|
||||||
import dev.yokai.domain.extension.repo.ExtensionRepoRepository
|
|
||||||
import dev.yokai.domain.extension.repo.exception.SaveExtensionRepoException
|
|
||||||
import dev.yokai.domain.ui.settings.ReaderPreferences
|
|
||||||
import dev.yokai.domain.ui.settings.ReaderPreferences.CutoutBehaviour
|
|
||||||
import dev.yokai.domain.ui.settings.ReaderPreferences.LandscapeCutoutBehaviour
|
|
||||||
import eu.kanade.tachiyomi.core.preference.Preference
|
|
||||||
import eu.kanade.tachiyomi.core.preference.PreferenceStore
|
|
||||||
import eu.kanade.tachiyomi.core.preference.plusAssign
|
|
||||||
import eu.kanade.tachiyomi.data.backup.create.BackupCreatorJob
|
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadProvider
|
|
||||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
|
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferenceKeys
|
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues
|
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
|
||||||
import eu.kanade.tachiyomi.data.updater.AppDownloadInstallJob
|
|
||||||
import eu.kanade.tachiyomi.data.updater.AppUpdateJob
|
|
||||||
import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
|
|
||||||
import eu.kanade.tachiyomi.network.PREF_DOH_CLOUDFLARE
|
|
||||||
import eu.kanade.tachiyomi.ui.library.LibraryPresenter
|
|
||||||
import eu.kanade.tachiyomi.ui.library.LibrarySort
|
|
||||||
import eu.kanade.tachiyomi.ui.reader.settings.OrientationType
|
|
||||||
import eu.kanade.tachiyomi.ui.reader.viewer.pager.PagerConfig
|
|
||||||
import eu.kanade.tachiyomi.ui.recents.RecentsPresenter
|
|
||||||
import eu.kanade.tachiyomi.util.system.launchIO
|
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import uy.kohesive.injekt.Injekt
|
|
||||||
import uy.kohesive.injekt.api.get
|
|
||||||
import uy.kohesive.injekt.injectLazy
|
|
||||||
import java.io.File
|
|
||||||
import kotlin.math.max
|
|
||||||
|
|
||||||
object Migrations {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Performs a migration when the application is updated.
|
|
||||||
*
|
|
||||||
* @param preferences Preferences of the application.
|
|
||||||
* @return true if a migration is performed, false otherwise.
|
|
||||||
*/
|
|
||||||
fun upgrade(
|
|
||||||
preferences: PreferencesHelper,
|
|
||||||
preferenceStore: PreferenceStore,
|
|
||||||
scope: CoroutineScope,
|
|
||||||
): Boolean {
|
|
||||||
val context = preferences.context
|
|
||||||
val prefs = PreferenceManager.getDefaultSharedPreferences(context)
|
|
||||||
prefs.edit {
|
|
||||||
remove(AppDownloadInstallJob.NOTIFY_ON_INSTALL_KEY)
|
|
||||||
}
|
|
||||||
val oldVersion = preferences.lastVersionCode().get()
|
|
||||||
if (oldVersion < BuildConfig.VERSION_CODE) {
|
|
||||||
preferences.lastVersionCode().set(BuildConfig.VERSION_CODE)
|
|
||||||
|
|
||||||
// Always set up background tasks to ensure they're running
|
|
||||||
if (BuildConfig.INCLUDE_UPDATER) {
|
|
||||||
AppUpdateJob.setupTask(context)
|
|
||||||
}
|
|
||||||
ExtensionUpdateJob.setupTask(context)
|
|
||||||
LibraryUpdateJob.setupTask(context)
|
|
||||||
BackupCreatorJob.setupTask(context)
|
|
||||||
|
|
||||||
if (oldVersion == 0) {
|
|
||||||
return BuildConfig.DEBUG
|
|
||||||
}
|
|
||||||
|
|
||||||
if (oldVersion < 14) {
|
|
||||||
// Restore jobs after upgrading to evernote's job scheduler.
|
|
||||||
if (BuildConfig.INCLUDE_UPDATER) {
|
|
||||||
AppUpdateJob.setupTask(context)
|
|
||||||
}
|
|
||||||
LibraryUpdateJob.setupTask(context)
|
|
||||||
}
|
|
||||||
if (oldVersion < 15) {
|
|
||||||
// Delete internal chapter cache dir.
|
|
||||||
File(context.cacheDir, "chapter_disk_cache").deleteRecursively()
|
|
||||||
}
|
|
||||||
if (oldVersion < 19) {
|
|
||||||
// Move covers to external files dir.
|
|
||||||
val oldDir = File(context.externalCacheDir, "cover_disk_cache")
|
|
||||||
if (oldDir.exists()) {
|
|
||||||
val destDir = context.getExternalFilesDir("covers")
|
|
||||||
if (destDir != null) {
|
|
||||||
oldDir.listFiles()?.forEach {
|
|
||||||
it.renameTo(File(destDir, it.name))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 26) {
|
|
||||||
// Delete external chapter cache dir.
|
|
||||||
val extCache = context.externalCacheDir
|
|
||||||
if (extCache != null) {
|
|
||||||
val chapterCache = File(extCache, "chapter_disk_cache")
|
|
||||||
if (chapterCache.exists()) {
|
|
||||||
chapterCache.deleteRecursively()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 54) {
|
|
||||||
DownloadProvider(context).renameChapters()
|
|
||||||
}
|
|
||||||
if (oldVersion < 62) {
|
|
||||||
LibraryPresenter.updateDB()
|
|
||||||
// Restore jobs after migrating from Evernote's job scheduler to WorkManager.
|
|
||||||
if (BuildConfig.INCLUDE_UPDATER) {
|
|
||||||
AppUpdateJob.setupTask(context)
|
|
||||||
}
|
|
||||||
LibraryUpdateJob.setupTask(context)
|
|
||||||
BackupCreatorJob.setupTask(context)
|
|
||||||
ExtensionUpdateJob.setupTask(context)
|
|
||||||
}
|
|
||||||
if (oldVersion < 66) {
|
|
||||||
LibraryPresenter.updateCustoms()
|
|
||||||
}
|
|
||||||
if (oldVersion < 68) {
|
|
||||||
// Force MAL log out due to login flow change
|
|
||||||
// v67: switched from scraping to WebView
|
|
||||||
// v68: switched from WebView to OAuth
|
|
||||||
val trackManager = Injekt.get<TrackManager>()
|
|
||||||
if (trackManager.myAnimeList.isLogged) {
|
|
||||||
trackManager.myAnimeList.logout()
|
|
||||||
context.toast(R.string.myanimelist_relogin)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 71) {
|
|
||||||
// Migrate DNS over HTTPS setting
|
|
||||||
val wasDohEnabled = prefs.getBoolean("enable_doh", false)
|
|
||||||
if (wasDohEnabled) {
|
|
||||||
prefs.edit {
|
|
||||||
putInt(PreferenceKeys.dohProvider, PREF_DOH_CLOUDFLARE)
|
|
||||||
remove("enable_doh")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 73) {
|
|
||||||
// Reset rotation to Free after replacing Lock
|
|
||||||
if (prefs.contains("pref_rotation_type_key")) {
|
|
||||||
prefs.edit {
|
|
||||||
putInt("pref_rotation_type_key", 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 74) {
|
|
||||||
// Turn on auto updates for all users
|
|
||||||
if (BuildConfig.INCLUDE_UPDATER) {
|
|
||||||
AppUpdateJob.setupTask(context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 75) {
|
|
||||||
val wasShortcutsDisabled = !prefs.getBoolean("show_manga_app_shortcuts", true)
|
|
||||||
if (wasShortcutsDisabled) {
|
|
||||||
prefs.edit {
|
|
||||||
putBoolean(PreferenceKeys.showSourcesInShortcuts, false)
|
|
||||||
putBoolean(PreferenceKeys.showSeriesInShortcuts, false)
|
|
||||||
remove("show_manga_app_shortcuts")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Handle removed every 1 or 2 hour library updates
|
|
||||||
val updateInterval = preferences.libraryUpdateInterval().get()
|
|
||||||
if (updateInterval == 1 || updateInterval == 2) {
|
|
||||||
preferences.libraryUpdateInterval().set(3)
|
|
||||||
LibraryUpdateJob.setupTask(context, 3)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 77) {
|
|
||||||
// Migrate Rotation and Viewer values to default values for viewer_flags
|
|
||||||
val newOrientation = when (prefs.getInt("pref_rotation_type_key", 1)) {
|
|
||||||
1 -> OrientationType.FREE.flagValue
|
|
||||||
2 -> OrientationType.PORTRAIT.flagValue
|
|
||||||
3 -> OrientationType.LANDSCAPE.flagValue
|
|
||||||
4 -> OrientationType.LOCKED_PORTRAIT.flagValue
|
|
||||||
5 -> OrientationType.LOCKED_LANDSCAPE.flagValue
|
|
||||||
else -> OrientationType.FREE.flagValue
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reading mode flag and prefValue is the same value
|
|
||||||
val newReadingMode = prefs.getInt("pref_default_viewer_key", 1)
|
|
||||||
|
|
||||||
prefs.edit {
|
|
||||||
putInt("pref_default_orientation_type_key", newOrientation)
|
|
||||||
remove("pref_rotation_type_key")
|
|
||||||
putInt("pref_default_reading_mode_key", newReadingMode)
|
|
||||||
remove("pref_default_viewer_key")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 83) {
|
|
||||||
if (preferences.enabledLanguages().isSet()) {
|
|
||||||
preferences.enabledLanguages() += "all"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 86) {
|
|
||||||
// Handle removed every 3, 4, 6, and 8 hour library updates
|
|
||||||
val updateInterval = preferences.libraryUpdateInterval().get()
|
|
||||||
if (updateInterval in listOf(3, 4, 6, 8)) {
|
|
||||||
preferences.libraryUpdateInterval().set(12)
|
|
||||||
LibraryUpdateJob.setupTask(context, 12)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 88) {
|
|
||||||
scope.launchIO {
|
|
||||||
LibraryPresenter.updateRatiosAndColors()
|
|
||||||
}
|
|
||||||
val oldReaderTap = prefs.getBoolean("reader_tap", true)
|
|
||||||
if (!oldReaderTap) {
|
|
||||||
preferences.navigationModePager().set(5)
|
|
||||||
preferences.navigationModeWebtoon().set(5)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 90) {
|
|
||||||
val oldSecureScreen = prefs.getBoolean("secure_screen", false)
|
|
||||||
if (oldSecureScreen) {
|
|
||||||
preferences.secureScreen().set(PreferenceValues.SecureScreenMode.ALWAYS)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 97) {
|
|
||||||
val oldDLAfterReading = prefs.getInt("auto_download_after_reading", 0)
|
|
||||||
if (oldDLAfterReading > 0) {
|
|
||||||
preferences.autoDownloadWhileReading().set(max(2, oldDLAfterReading))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 102) {
|
|
||||||
val oldGroupHistory = prefs.getBoolean("group_chapters_history", true)
|
|
||||||
if (!oldGroupHistory) {
|
|
||||||
preferences.groupChaptersHistory().set(RecentsPresenter.GroupType.Never)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 105) {
|
|
||||||
LibraryUpdateJob.cancelAllWorks(context)
|
|
||||||
LibraryUpdateJob.setupTask(context)
|
|
||||||
}
|
|
||||||
if (oldVersion < 108) {
|
|
||||||
preferenceStore.getAll()
|
|
||||||
.filter { it.key.startsWith("pref_mangasync_") || it.key.startsWith("track_token_") }
|
|
||||||
.forEach { (key, value) ->
|
|
||||||
if (value is String) {
|
|
||||||
preferenceStore
|
|
||||||
.getString(Preference.privateKey(key))
|
|
||||||
.set(value)
|
|
||||||
|
|
||||||
preferenceStore.getString(key).delete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 110) {
|
|
||||||
try {
|
|
||||||
val librarySortString = prefs.getString("library_sorting_mode", "")
|
|
||||||
if (!librarySortString.isNullOrEmpty()) {
|
|
||||||
prefs.edit {
|
|
||||||
remove("library_sorting_mode")
|
|
||||||
putInt(
|
|
||||||
"library_sorting_mode",
|
|
||||||
LibrarySort.deserialize(librarySortString).mainValue,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (_: Exception) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 112) {
|
|
||||||
prefs.edit {
|
|
||||||
remove("trusted_signatures")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 119) {
|
|
||||||
val basePreferences: BasePreferences = Injekt.get()
|
|
||||||
try {
|
|
||||||
val oldExtensionInstall = prefs.getInt("extension_installer", 0)
|
|
||||||
basePreferences.extensionInstaller().set(
|
|
||||||
when (oldExtensionInstall) {
|
|
||||||
1 -> BasePreferences.ExtensionInstaller.SHIZUKU
|
|
||||||
2 -> BasePreferences.ExtensionInstaller.PRIVATE
|
|
||||||
else -> BasePreferences.ExtensionInstaller.PACKAGEINSTALLER
|
|
||||||
}
|
|
||||||
)
|
|
||||||
} catch (_: Exception) {
|
|
||||||
basePreferences.extensionInstaller().set(BasePreferences.ExtensionInstaller.PACKAGEINSTALLER)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 121) {
|
|
||||||
val readerPreferences: ReaderPreferences = Injekt.get()
|
|
||||||
try {
|
|
||||||
val oldCutoutBehaviour = prefs.getInt(PreferenceKeys.pagerCutoutBehavior, 0)
|
|
||||||
readerPreferences.pagerCutoutBehavior().set(
|
|
||||||
when (oldCutoutBehaviour) {
|
|
||||||
PagerConfig.CUTOUT_PAD -> CutoutBehaviour.HIDE
|
|
||||||
PagerConfig.CUTOUT_IGNORE -> CutoutBehaviour.IGNORE
|
|
||||||
else -> CutoutBehaviour.SHOW
|
|
||||||
}
|
|
||||||
)
|
|
||||||
} catch (_: Exception) {
|
|
||||||
readerPreferences.pagerCutoutBehavior().set(CutoutBehaviour.SHOW)
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
val oldCutoutBehaviour = prefs.getInt("landscape_cutout_behavior", 0)
|
|
||||||
readerPreferences.landscapeCutoutBehavior().set(
|
|
||||||
when (oldCutoutBehaviour) {
|
|
||||||
0 -> LandscapeCutoutBehaviour.HIDE
|
|
||||||
else -> LandscapeCutoutBehaviour.DEFAULT
|
|
||||||
}
|
|
||||||
)
|
|
||||||
} catch (_: Exception) {
|
|
||||||
readerPreferences.landscapeCutoutBehavior().set(LandscapeCutoutBehaviour.DEFAULT)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (oldVersion < 130) {
|
|
||||||
val coroutineScope = CoroutineScope(Dispatchers.IO)
|
|
||||||
val extensionRepoRepository: ExtensionRepoRepository by injectLazy()
|
|
||||||
val extensionRepos: Preference<Set<String>> = preferenceStore.getStringSet("extension_repos", emptySet())
|
|
||||||
|
|
||||||
coroutineScope.launchIO {
|
|
||||||
for ((index, source) in extensionRepos.get().withIndex()) {
|
|
||||||
try {
|
|
||||||
extensionRepoRepository.upsertRepository(
|
|
||||||
source,
|
|
||||||
"Repo #${index + 1}",
|
|
||||||
null,
|
|
||||||
source,
|
|
||||||
"NOFINGERPRINT-${index + 1}",
|
|
||||||
)
|
|
||||||
} catch (e: SaveExtensionRepoException) {
|
|
||||||
Logger.e(e) { "Error Migrating Extension Repo with baseUrl: $source" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
extensionRepos.delete()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -30,6 +30,7 @@ import eu.kanade.tachiyomi.extension.api.ExtensionApi
|
||||||
import eu.kanade.tachiyomi.extension.model.Extension
|
import eu.kanade.tachiyomi.extension.model.Extension
|
||||||
import eu.kanade.tachiyomi.extension.util.ExtensionLoader
|
import eu.kanade.tachiyomi.extension.util.ExtensionLoader
|
||||||
import eu.kanade.tachiyomi.util.system.connectivityManager
|
import eu.kanade.tachiyomi.util.system.connectivityManager
|
||||||
|
import eu.kanade.tachiyomi.util.system.jobIsRunning
|
||||||
import eu.kanade.tachiyomi.util.system.localeContext
|
import eu.kanade.tachiyomi.util.system.localeContext
|
||||||
import eu.kanade.tachiyomi.util.system.notification
|
import eu.kanade.tachiyomi.util.system.notification
|
||||||
import eu.kanade.tachiyomi.util.system.toInt
|
import eu.kanade.tachiyomi.util.system.toInt
|
||||||
|
@ -38,7 +39,7 @@ import rikka.shizuku.Shizuku
|
||||||
import uy.kohesive.injekt.Injekt
|
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
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.*
|
||||||
|
|
||||||
class ExtensionUpdateJob(private val context: Context, workerParams: WorkerParameters) :
|
class ExtensionUpdateJob(private val context: Context, workerParams: WorkerParameters) :
|
||||||
CoroutineWorker(context, workerParams) {
|
CoroutineWorker(context, workerParams) {
|
||||||
|
@ -179,6 +180,7 @@ class ExtensionUpdateJob(private val context: Context, workerParams: WorkerParam
|
||||||
fun setupTask(context: Context, forceAutoUpdateJob: Boolean? = null) {
|
fun setupTask(context: Context, forceAutoUpdateJob: Boolean? = null) {
|
||||||
val preferences = Injekt.get<PreferencesHelper>()
|
val preferences = Injekt.get<PreferencesHelper>()
|
||||||
val autoUpdateJob = forceAutoUpdateJob ?: preferences.automaticExtUpdates().get()
|
val autoUpdateJob = forceAutoUpdateJob ?: preferences.automaticExtUpdates().get()
|
||||||
|
WorkManager.getInstance(context).jobIsRunning(TAG)
|
||||||
if (autoUpdateJob) {
|
if (autoUpdateJob) {
|
||||||
val constraints = Constraints.Builder()
|
val constraints = Constraints.Builder()
|
||||||
.setRequiredNetworkType(NetworkType.CONNECTED)
|
.setRequiredNetworkType(NetworkType.CONNECTED)
|
||||||
|
|
|
@ -67,11 +67,11 @@ import com.google.android.material.snackbar.Snackbar
|
||||||
import com.google.android.material.transition.platform.MaterialContainerTransformSharedElementCallback
|
import com.google.android.material.transition.platform.MaterialContainerTransformSharedElementCallback
|
||||||
import com.google.common.primitives.Floats.max
|
import com.google.common.primitives.Floats.max
|
||||||
import com.google.common.primitives.Ints.max
|
import com.google.common.primitives.Ints.max
|
||||||
|
import dev.yokai.core.migration.Migrator
|
||||||
import dev.yokai.domain.base.BasePreferences
|
import dev.yokai.domain.base.BasePreferences
|
||||||
import dev.yokai.presentation.extension.repo.ExtensionRepoController
|
import dev.yokai.presentation.extension.repo.ExtensionRepoController
|
||||||
import dev.yokai.presentation.onboarding.OnboardingController
|
import dev.yokai.presentation.onboarding.OnboardingController
|
||||||
import eu.kanade.tachiyomi.BuildConfig
|
import eu.kanade.tachiyomi.BuildConfig
|
||||||
import eu.kanade.tachiyomi.Migrations
|
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.download.DownloadJob
|
import eu.kanade.tachiyomi.data.download.DownloadJob
|
||||||
|
@ -142,9 +142,22 @@ import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import uy.kohesive.injekt.Injekt
|
|
||||||
import uy.kohesive.injekt.api.get
|
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
import kotlin.collections.List
|
||||||
|
import kotlin.collections.MutableList
|
||||||
|
import kotlin.collections.MutableMap
|
||||||
|
import kotlin.collections.distinct
|
||||||
|
import kotlin.collections.filterNotNull
|
||||||
|
import kotlin.collections.firstOrNull
|
||||||
|
import kotlin.collections.forEach
|
||||||
|
import kotlin.collections.forEachIndexed
|
||||||
|
import kotlin.collections.lastOrNull
|
||||||
|
import kotlin.collections.listOf
|
||||||
|
import kotlin.collections.map
|
||||||
|
import kotlin.collections.maxByOrNull
|
||||||
|
import kotlin.collections.orEmpty
|
||||||
|
import kotlin.collections.plus
|
||||||
|
import kotlin.collections.set
|
||||||
import kotlin.math.abs
|
import kotlin.math.abs
|
||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
import kotlin.math.roundToLong
|
import kotlin.math.roundToLong
|
||||||
|
@ -442,8 +455,10 @@ open class MainActivity : BaseActivity<MainActivityBinding>() {
|
||||||
// Reset Incognito Mode on relaunch
|
// Reset Incognito Mode on relaunch
|
||||||
preferences.incognitoMode().set(false)
|
preferences.incognitoMode().set(false)
|
||||||
|
|
||||||
|
val didMigration = Migrator.awaitAndRelease()
|
||||||
|
|
||||||
// Show changelog if needed
|
// Show changelog if needed
|
||||||
if (Migrations.upgrade(preferences, Injekt.get(), lifecycleScope)) {
|
if (didMigration) {
|
||||||
if (!BuildConfig.DEBUG) {
|
if (!BuildConfig.DEBUG) {
|
||||||
content.post {
|
content.post {
|
||||||
whatsNewSheet().show()
|
whatsNewSheet().show()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue