mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-11-04 08:08:55 +01:00 
			
		
		
		
	Remove legacy backup creation
This commit is contained in:
		@@ -8,7 +8,6 @@ object BackupConst {
 | 
			
		||||
    const val EXTRA_URI = "$ID.$NAME.EXTRA_URI"
 | 
			
		||||
    const val EXTRA_FLAGS = "$ID.$NAME.EXTRA_FLAGS"
 | 
			
		||||
    const val EXTRA_MODE = "$ID.$NAME.EXTRA_MODE"
 | 
			
		||||
    const val EXTRA_TYPE = "$ID.$NAME.EXTRA_TYPE"
 | 
			
		||||
 | 
			
		||||
    const val BACKUP_TYPE_LEGACY = 0
 | 
			
		||||
    const val BACKUP_TYPE_FULL = 1
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,6 @@ import androidx.core.content.ContextCompat
 | 
			
		||||
import androidx.core.net.toUri
 | 
			
		||||
import com.hippo.unifile.UniFile
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.full.FullBackupManager
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.legacy.LegacyBackupManager
 | 
			
		||||
import eu.kanade.tachiyomi.data.notification.Notifications
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.acquireWakeLock
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.isServiceRunning
 | 
			
		||||
@@ -48,12 +47,11 @@ class BackupCreateService : Service() {
 | 
			
		||||
         * @param uri path of Uri
 | 
			
		||||
         * @param flags determines what to backup
 | 
			
		||||
         */
 | 
			
		||||
        fun start(context: Context, uri: Uri, flags: Int, type: Int) {
 | 
			
		||||
        fun start(context: Context, uri: Uri, flags: Int) {
 | 
			
		||||
            if (!isRunning(context)) {
 | 
			
		||||
                val intent = Intent(context, BackupCreateService::class.java).apply {
 | 
			
		||||
                    putExtra(BackupConst.EXTRA_URI, uri)
 | 
			
		||||
                    putExtra(BackupConst.EXTRA_FLAGS, flags)
 | 
			
		||||
                    putExtra(BackupConst.EXTRA_TYPE, type)
 | 
			
		||||
                }
 | 
			
		||||
                ContextCompat.startForegroundService(context, intent)
 | 
			
		||||
            }
 | 
			
		||||
@@ -103,15 +101,9 @@ class BackupCreateService : Service() {
 | 
			
		||||
        try {
 | 
			
		||||
            val uri = intent.getParcelableExtra<Uri>(BackupConst.EXTRA_URI)
 | 
			
		||||
            val backupFlags = intent.getIntExtra(BackupConst.EXTRA_FLAGS, 0)
 | 
			
		||||
            val backupType = intent.getIntExtra(BackupConst.EXTRA_TYPE, BackupConst.BACKUP_TYPE_LEGACY)
 | 
			
		||||
            val backupManager = when (backupType) {
 | 
			
		||||
                BackupConst.BACKUP_TYPE_FULL -> FullBackupManager(this)
 | 
			
		||||
                else -> LegacyBackupManager(this)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            val backupFileUri = backupManager.createBackup(uri, backupFlags, false)?.toUri()
 | 
			
		||||
            val backupFileUri = FullBackupManager(this).createBackup(uri, backupFlags, false)?.toUri()
 | 
			
		||||
            val unifile = UniFile.fromUri(this, backupFileUri)
 | 
			
		||||
            notifier.showBackupComplete(unifile, backupType == BackupConst.BACKUP_TYPE_LEGACY)
 | 
			
		||||
            notifier.showBackupComplete(unifile)
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            notifier.showBackupError(e.message)
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,6 @@ import androidx.work.WorkManager
 | 
			
		||||
import androidx.work.Worker
 | 
			
		||||
import androidx.work.WorkerParameters
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.full.FullBackupManager
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.legacy.LegacyBackupManager
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 | 
			
		||||
import uy.kohesive.injekt.Injekt
 | 
			
		||||
import uy.kohesive.injekt.api.get
 | 
			
		||||
@@ -23,9 +22,6 @@ class BackupCreatorJob(private val context: Context, workerParams: WorkerParamet
 | 
			
		||||
        val flags = BackupCreateService.BACKUP_ALL
 | 
			
		||||
        return try {
 | 
			
		||||
            FullBackupManager(context).createBackup(uri, flags, true)
 | 
			
		||||
            if (preferences.createLegacyBackup().get()) {
 | 
			
		||||
                LegacyBackupManager(context).createBackup(uri, flags, true)
 | 
			
		||||
            }
 | 
			
		||||
            Result.success()
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            Result.failure()
 | 
			
		||||
 
 | 
			
		||||
@@ -60,7 +60,7 @@ class BackupNotifier(private val context: Context) {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun showBackupComplete(unifile: UniFile, isLegacyFormat: Boolean) {
 | 
			
		||||
    fun showBackupComplete(unifile: UniFile) {
 | 
			
		||||
        context.notificationManager.cancel(Notifications.ID_BACKUP_PROGRESS)
 | 
			
		||||
 | 
			
		||||
        with(completeNotificationBuilder) {
 | 
			
		||||
@@ -73,7 +73,7 @@ class BackupNotifier(private val context: Context) {
 | 
			
		||||
            addAction(
 | 
			
		||||
                R.drawable.ic_share_24dp,
 | 
			
		||||
                context.getString(R.string.action_share),
 | 
			
		||||
                NotificationReceiver.shareBackupPendingBroadcast(context, unifile.uri, isLegacyFormat, Notifications.ID_BACKUP_COMPLETE)
 | 
			
		||||
                NotificationReceiver.shareBackupPendingBroadcast(context, unifile.uri, Notifications.ID_BACKUP_COMPLETE)
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
            show(Notifications.ID_BACKUP_COMPLETE)
 | 
			
		||||
 
 | 
			
		||||
@@ -5,30 +5,11 @@ import android.net.Uri
 | 
			
		||||
import com.github.salomonbrys.kotson.fromJson
 | 
			
		||||
import com.github.salomonbrys.kotson.registerTypeAdapter
 | 
			
		||||
import com.github.salomonbrys.kotson.registerTypeHierarchyAdapter
 | 
			
		||||
import com.github.salomonbrys.kotson.set
 | 
			
		||||
import com.google.gson.Gson
 | 
			
		||||
import com.google.gson.GsonBuilder
 | 
			
		||||
import com.google.gson.JsonArray
 | 
			
		||||
import com.google.gson.JsonElement
 | 
			
		||||
import com.google.gson.JsonObject
 | 
			
		||||
import com.hippo.unifile.UniFile
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.AbstractBackupManager
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CATEGORY
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CATEGORY_MASK
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CHAPTER
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CHAPTER_MASK
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_HISTORY
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_HISTORY_MASK
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_TRACK
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_TRACK_MASK
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.legacy.models.Backup
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.legacy.models.Backup.CATEGORIES
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.legacy.models.Backup.CHAPTERS
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.legacy.models.Backup.CURRENT_VERSION
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.legacy.models.Backup.EXTENSIONS
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.legacy.models.Backup.HISTORY
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.legacy.models.Backup.MANGA
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.legacy.models.Backup.TRACK
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.legacy.models.DHistory
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.legacy.serializer.CategoryTypeAdapter
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.legacy.serializer.ChapterTypeAdapter
 | 
			
		||||
@@ -45,10 +26,8 @@ import eu.kanade.tachiyomi.data.database.models.MangaImpl
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.Track
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.TrackImpl
 | 
			
		||||
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
 | 
			
		||||
import eu.kanade.tachiyomi.source.LocalSource
 | 
			
		||||
import eu.kanade.tachiyomi.source.Source
 | 
			
		||||
import eu.kanade.tachiyomi.source.model.toSManga
 | 
			
		||||
import timber.log.Timber
 | 
			
		||||
import kotlin.math.max
 | 
			
		||||
 | 
			
		||||
class LegacyBackupManager(context: Context, version: Int = CURRENT_VERSION) : AbstractBackupManager(context) {
 | 
			
		||||
@@ -70,161 +49,8 @@ class LegacyBackupManager(context: Context, version: Int = CURRENT_VERSION) : Ab
 | 
			
		||||
     * @param uri path of Uri
 | 
			
		||||
     * @param isJob backup called from job
 | 
			
		||||
     */
 | 
			
		||||
    override fun createBackup(uri: Uri, flags: Int, isJob: Boolean): String? {
 | 
			
		||||
        // Create root object
 | 
			
		||||
        val root = JsonObject()
 | 
			
		||||
 | 
			
		||||
        // Create manga array
 | 
			
		||||
        val mangaEntries = JsonArray()
 | 
			
		||||
 | 
			
		||||
        // Create category array
 | 
			
		||||
        val categoryEntries = JsonArray()
 | 
			
		||||
 | 
			
		||||
        // Create extension ID/name mapping
 | 
			
		||||
        val extensionEntries = JsonArray()
 | 
			
		||||
 | 
			
		||||
        // Add value's to root
 | 
			
		||||
        root[Backup.VERSION] = CURRENT_VERSION
 | 
			
		||||
        root[Backup.MANGAS] = mangaEntries
 | 
			
		||||
        root[CATEGORIES] = categoryEntries
 | 
			
		||||
        root[EXTENSIONS] = extensionEntries
 | 
			
		||||
 | 
			
		||||
        databaseHelper.inTransaction {
 | 
			
		||||
            val mangas = getFavoriteManga()
 | 
			
		||||
 | 
			
		||||
            val extensions: MutableSet<String> = mutableSetOf()
 | 
			
		||||
 | 
			
		||||
            // Backup library manga and its dependencies
 | 
			
		||||
            mangas.forEach { manga ->
 | 
			
		||||
                mangaEntries.add(backupMangaObject(manga, flags))
 | 
			
		||||
 | 
			
		||||
                // Maintain set of extensions/sources used (excludes local source)
 | 
			
		||||
                if (manga.source != LocalSource.ID) {
 | 
			
		||||
                    sourceManager.get(manga.source)?.let {
 | 
			
		||||
                        extensions.add("${manga.source}:${it.name}")
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Backup categories
 | 
			
		||||
            if ((flags and BACKUP_CATEGORY_MASK) == BACKUP_CATEGORY) {
 | 
			
		||||
                backupCategories(categoryEntries)
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Backup extension ID/name mapping
 | 
			
		||||
            backupExtensionInfo(extensionEntries, extensions)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            val file: UniFile = (
 | 
			
		||||
                if (isJob) {
 | 
			
		||||
                    // Get dir of file and create
 | 
			
		||||
                    var dir = UniFile.fromUri(context, uri)
 | 
			
		||||
                    dir = dir.createDirectory("automatic")
 | 
			
		||||
 | 
			
		||||
                    // Delete older backups
 | 
			
		||||
                    val numberOfBackups = numberOfBackups()
 | 
			
		||||
                    val backupRegex = Regex("""tachiyomi_\d+-\d+-\d+_\d+-\d+.json""")
 | 
			
		||||
                    dir.listFiles { _, filename -> backupRegex.matches(filename) }
 | 
			
		||||
                        .orEmpty()
 | 
			
		||||
                        .sortedByDescending { it.name }
 | 
			
		||||
                        .drop(numberOfBackups - 1)
 | 
			
		||||
                        .forEach { it.delete() }
 | 
			
		||||
 | 
			
		||||
                    // Create new file to place backup
 | 
			
		||||
                    dir.createFile(Backup.getDefaultFilename())
 | 
			
		||||
                } else {
 | 
			
		||||
                    UniFile.fromUri(context, uri)
 | 
			
		||||
                }
 | 
			
		||||
                )
 | 
			
		||||
                ?: throw Exception("Couldn't create backup file")
 | 
			
		||||
 | 
			
		||||
            file.openOutputStream().bufferedWriter().use {
 | 
			
		||||
                parser.toJson(root, it)
 | 
			
		||||
            }
 | 
			
		||||
            return file.uri.toString()
 | 
			
		||||
        } catch (e: Exception) {
 | 
			
		||||
            Timber.e(e)
 | 
			
		||||
            throw e
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun backupExtensionInfo(root: JsonArray, extensions: Set<String>) {
 | 
			
		||||
        extensions.sorted().forEach {
 | 
			
		||||
            root.add(it)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Backup the categories of library
 | 
			
		||||
     *
 | 
			
		||||
     * @param root root of categories json
 | 
			
		||||
     */
 | 
			
		||||
    internal fun backupCategories(root: JsonArray) {
 | 
			
		||||
        val categories = databaseHelper.getCategories().executeAsBlocking()
 | 
			
		||||
        categories.forEach { root.add(parser.toJsonTree(it)) }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Convert a manga to Json
 | 
			
		||||
     *
 | 
			
		||||
     * @param manga manga that gets converted
 | 
			
		||||
     * @return [JsonElement] containing manga information
 | 
			
		||||
     */
 | 
			
		||||
    internal fun backupMangaObject(manga: Manga, options: Int): JsonElement {
 | 
			
		||||
        // Entry for this manga
 | 
			
		||||
        val entry = JsonObject()
 | 
			
		||||
 | 
			
		||||
        // Backup manga fields
 | 
			
		||||
        entry[MANGA] = parser.toJsonTree(manga)
 | 
			
		||||
 | 
			
		||||
        // Check if user wants chapter information in backup
 | 
			
		||||
        if (options and BACKUP_CHAPTER_MASK == BACKUP_CHAPTER) {
 | 
			
		||||
            // Backup all the chapters
 | 
			
		||||
            val chapters = databaseHelper.getChapters(manga).executeAsBlocking()
 | 
			
		||||
            if (chapters.isNotEmpty()) {
 | 
			
		||||
                val chaptersJson = parser.toJsonTree(chapters)
 | 
			
		||||
                if (chaptersJson.asJsonArray.size() > 0) {
 | 
			
		||||
                    entry[CHAPTERS] = chaptersJson
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Check if user wants category information in backup
 | 
			
		||||
        if (options and BACKUP_CATEGORY_MASK == BACKUP_CATEGORY) {
 | 
			
		||||
            // Backup categories for this manga
 | 
			
		||||
            val categoriesForManga = databaseHelper.getCategoriesForManga(manga).executeAsBlocking()
 | 
			
		||||
            if (categoriesForManga.isNotEmpty()) {
 | 
			
		||||
                val categoriesNames = categoriesForManga.map { it.name }
 | 
			
		||||
                entry[CATEGORIES] = parser.toJsonTree(categoriesNames)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Check if user wants track information in backup
 | 
			
		||||
        if (options and BACKUP_TRACK_MASK == BACKUP_TRACK) {
 | 
			
		||||
            val tracks = databaseHelper.getTracks(manga).executeAsBlocking()
 | 
			
		||||
            if (tracks.isNotEmpty()) {
 | 
			
		||||
                entry[TRACK] = parser.toJsonTree(tracks)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Check if user wants history information in backup
 | 
			
		||||
        if (options and BACKUP_HISTORY_MASK == BACKUP_HISTORY) {
 | 
			
		||||
            val historyForManga = databaseHelper.getHistoryByMangaId(manga.id!!).executeAsBlocking()
 | 
			
		||||
            if (historyForManga.isNotEmpty()) {
 | 
			
		||||
                val historyData = historyForManga.mapNotNull { history ->
 | 
			
		||||
                    val url = databaseHelper.getChapter(history.chapter_id).executeAsBlocking()?.url
 | 
			
		||||
                    url?.let { DHistory(url, history.last_read) }
 | 
			
		||||
                }
 | 
			
		||||
                val historyJson = parser.toJsonTree(historyData)
 | 
			
		||||
                if (historyJson.asJsonArray.size() > 0) {
 | 
			
		||||
                    entry[HISTORY] = historyJson
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return entry
 | 
			
		||||
    }
 | 
			
		||||
    override fun createBackup(uri: Uri, flags: Int, isJob: Boolean) =
 | 
			
		||||
        throw IllegalStateException("Legacy backup creation is not supported")
 | 
			
		||||
 | 
			
		||||
    fun restoreMangaNoFetch(manga: Manga, dbManga: Manga) {
 | 
			
		||||
        manga.id = dbManga.id
 | 
			
		||||
 
 | 
			
		||||
@@ -73,7 +73,7 @@ class NotificationReceiver : BroadcastReceiver() {
 | 
			
		||||
                shareFile(
 | 
			
		||||
                    context,
 | 
			
		||||
                    intent.getParcelableExtra(EXTRA_URI),
 | 
			
		||||
                    if (intent.getBooleanExtra(EXTRA_IS_LEGACY_BACKUP, false)) "application/json" else "application/x-protobuf+gzip",
 | 
			
		||||
                    "application/x-protobuf+gzip",
 | 
			
		||||
                    intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1)
 | 
			
		||||
                )
 | 
			
		||||
            ACTION_CANCEL_RESTORE -> cancelRestore(
 | 
			
		||||
@@ -281,7 +281,6 @@ class NotificationReceiver : BroadcastReceiver() {
 | 
			
		||||
        private const val EXTRA_MANGA_ID = "$ID.$NAME.EXTRA_MANGA_ID"
 | 
			
		||||
        private const val EXTRA_CHAPTER_ID = "$ID.$NAME.EXTRA_CHAPTER_ID"
 | 
			
		||||
        private const val EXTRA_CHAPTER_URL = "$ID.$NAME.EXTRA_CHAPTER_URL"
 | 
			
		||||
        private const val EXTRA_IS_LEGACY_BACKUP = "$ID.$NAME.EXTRA_IS_LEGACY_BACKUP"
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Returns a [PendingIntent] that resumes the download of a chapter
 | 
			
		||||
@@ -494,11 +493,10 @@ class NotificationReceiver : BroadcastReceiver() {
 | 
			
		||||
         * @param notificationId id of notification
 | 
			
		||||
         * @return [PendingIntent]
 | 
			
		||||
         */
 | 
			
		||||
        internal fun shareBackupPendingBroadcast(context: Context, uri: Uri, isLegacyFormat: Boolean, notificationId: Int): PendingIntent {
 | 
			
		||||
        internal fun shareBackupPendingBroadcast(context: Context, uri: Uri, notificationId: Int): PendingIntent {
 | 
			
		||||
            val intent = Intent(context, NotificationReceiver::class.java).apply {
 | 
			
		||||
                action = ACTION_SHARE_BACKUP
 | 
			
		||||
                putExtra(EXTRA_URI, uri)
 | 
			
		||||
                putExtra(EXTRA_IS_LEGACY_BACKUP, isLegacyFormat)
 | 
			
		||||
                putExtra(EXTRA_NOTIFICATION_ID, notificationId)
 | 
			
		||||
            }
 | 
			
		||||
            return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
 | 
			
		||||
 
 | 
			
		||||
@@ -214,8 +214,6 @@ object PreferenceKeys {
 | 
			
		||||
 | 
			
		||||
    const val incognitoMode = "incognito_mode"
 | 
			
		||||
 | 
			
		||||
    const val createLegacyBackup = "create_legacy_backup"
 | 
			
		||||
 | 
			
		||||
    fun trackUsername(syncId: Int) = "pref_mangasync_username_$syncId"
 | 
			
		||||
 | 
			
		||||
    fun trackPassword(syncId: Int) = "pref_mangasync_password_$syncId"
 | 
			
		||||
 
 | 
			
		||||
@@ -306,8 +306,6 @@ class PreferencesHelper(val context: Context) {
 | 
			
		||||
 | 
			
		||||
    fun incognitoMode() = flowPrefs.getBoolean(Keys.incognitoMode, false)
 | 
			
		||||
 | 
			
		||||
    fun createLegacyBackup() = flowPrefs.getBoolean(Keys.createLegacyBackup, true)
 | 
			
		||||
 | 
			
		||||
    fun setChapterSettingsDefault(manga: Manga) {
 | 
			
		||||
        prefs.edit {
 | 
			
		||||
            putInt(Keys.defaultChapterFilterByRead, manga.readFilter)
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,6 @@ import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
 | 
			
		||||
import android.app.Activity
 | 
			
		||||
import android.app.Dialog
 | 
			
		||||
import android.content.ActivityNotFoundException
 | 
			
		||||
import android.content.Context
 | 
			
		||||
import android.content.Intent
 | 
			
		||||
import android.net.Uri
 | 
			
		||||
import android.os.Bundle
 | 
			
		||||
@@ -24,7 +23,6 @@ import eu.kanade.tachiyomi.data.backup.BackupRestoreService
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.full.FullBackupRestoreValidator
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupFull
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.legacy.LegacyBackupRestoreValidator
 | 
			
		||||
import eu.kanade.tachiyomi.data.backup.legacy.models.Backup
 | 
			
		||||
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
 | 
			
		||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
 | 
			
		||||
import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe
 | 
			
		||||
@@ -36,7 +34,6 @@ import eu.kanade.tachiyomi.util.preference.onClick
 | 
			
		||||
import eu.kanade.tachiyomi.util.preference.preference
 | 
			
		||||
import eu.kanade.tachiyomi.util.preference.preferenceCategory
 | 
			
		||||
import eu.kanade.tachiyomi.util.preference.summaryRes
 | 
			
		||||
import eu.kanade.tachiyomi.util.preference.switchPreference
 | 
			
		||||
import eu.kanade.tachiyomi.util.preference.titleRes
 | 
			
		||||
import eu.kanade.tachiyomi.util.system.toast
 | 
			
		||||
import kotlinx.coroutines.flow.launchIn
 | 
			
		||||
@@ -66,14 +63,15 @@ class SettingsBackupController : SettingsController() {
 | 
			
		||||
                titleRes = R.string.pref_create_backup
 | 
			
		||||
                summaryRes = R.string.pref_create_backup_summ
 | 
			
		||||
 | 
			
		||||
                onClick { backup(context, BackupConst.BACKUP_TYPE_FULL) }
 | 
			
		||||
            }
 | 
			
		||||
            preference {
 | 
			
		||||
                key = "pref_create_legacy_backup"
 | 
			
		||||
                titleRes = R.string.pref_create_legacy_backup
 | 
			
		||||
                summaryRes = R.string.pref_create_legacy_backup_summary
 | 
			
		||||
 | 
			
		||||
                onClick { backup(context, BackupConst.BACKUP_TYPE_LEGACY) }
 | 
			
		||||
                onClick {
 | 
			
		||||
                    if (!BackupCreateService.isRunning(context)) {
 | 
			
		||||
                        val ctrl = CreateBackupDialog()
 | 
			
		||||
                        ctrl.targetController = this@SettingsBackupController
 | 
			
		||||
                        ctrl.showDialog(router)
 | 
			
		||||
                    } else {
 | 
			
		||||
                        context.toast(R.string.backup_in_progress)
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            preference {
 | 
			
		||||
                key = "pref_restore_backup"
 | 
			
		||||
@@ -150,14 +148,6 @@ class SettingsBackupController : SettingsController() {
 | 
			
		||||
                defaultValue = "1"
 | 
			
		||||
                summary = "%s"
 | 
			
		||||
 | 
			
		||||
                preferences.backupInterval().asImmediateFlow { isVisible = it > 0 }
 | 
			
		||||
                    .launchIn(viewScope)
 | 
			
		||||
            }
 | 
			
		||||
            switchPreference {
 | 
			
		||||
                key = Keys.createLegacyBackup
 | 
			
		||||
                titleRes = R.string.pref_backup_auto_create_legacy
 | 
			
		||||
                defaultValue = true
 | 
			
		||||
 | 
			
		||||
                preferences.backupInterval().asImmediateFlow { isVisible = it > 0 }
 | 
			
		||||
                    .launchIn(viewScope)
 | 
			
		||||
            }
 | 
			
		||||
@@ -182,7 +172,7 @@ class SettingsBackupController : SettingsController() {
 | 
			
		||||
                    // Set backup Uri
 | 
			
		||||
                    preferences.backupsDirectory().set(uri.toString())
 | 
			
		||||
                }
 | 
			
		||||
                CODE_FULL_BACKUP_CREATE, CODE_LEGACY_BACKUP_CREATE -> {
 | 
			
		||||
                CODE_BACKUP_CREATE -> {
 | 
			
		||||
                    val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
 | 
			
		||||
                        Intent.FLAG_GRANT_WRITE_URI_PERMISSION
 | 
			
		||||
 | 
			
		||||
@@ -198,7 +188,6 @@ class SettingsBackupController : SettingsController() {
 | 
			
		||||
                        activity,
 | 
			
		||||
                        file.uri,
 | 
			
		||||
                        backupFlags,
 | 
			
		||||
                        if (requestCode == CODE_FULL_BACKUP_CREATE) BackupConst.BACKUP_TYPE_FULL else BackupConst.BACKUP_TYPE_LEGACY
 | 
			
		||||
                    )
 | 
			
		||||
                }
 | 
			
		||||
                CODE_BACKUP_RESTORE -> {
 | 
			
		||||
@@ -227,49 +216,23 @@ class SettingsBackupController : SettingsController() {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun backup(context: Context, type: Int) {
 | 
			
		||||
        if (!BackupCreateService.isRunning(context)) {
 | 
			
		||||
            val ctrl = CreateBackupDialog(type)
 | 
			
		||||
            ctrl.targetController = this@SettingsBackupController
 | 
			
		||||
            ctrl.showDialog(router)
 | 
			
		||||
        } else {
 | 
			
		||||
            context.toast(R.string.backup_in_progress)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun createBackup(flags: Int, type: Int) {
 | 
			
		||||
    fun createBackup(flags: Int) {
 | 
			
		||||
        backupFlags = flags
 | 
			
		||||
        val code = when (type) {
 | 
			
		||||
            BackupConst.BACKUP_TYPE_FULL -> CODE_FULL_BACKUP_CREATE
 | 
			
		||||
            else -> CODE_LEGACY_BACKUP_CREATE
 | 
			
		||||
        }
 | 
			
		||||
        val fileName = when (type) {
 | 
			
		||||
            BackupConst.BACKUP_TYPE_FULL -> BackupFull.getDefaultFilename()
 | 
			
		||||
            else -> Backup.getDefaultFilename()
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            // Use Android's built-in file creator
 | 
			
		||||
            val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
 | 
			
		||||
                .addCategory(Intent.CATEGORY_OPENABLE)
 | 
			
		||||
                .setType("application/*")
 | 
			
		||||
                .putExtra(Intent.EXTRA_TITLE, fileName)
 | 
			
		||||
                .putExtra(Intent.EXTRA_TITLE, BackupFull.getDefaultFilename())
 | 
			
		||||
 | 
			
		||||
            startActivityForResult(intent, code)
 | 
			
		||||
            startActivityForResult(intent, CODE_BACKUP_CREATE)
 | 
			
		||||
        } catch (e: ActivityNotFoundException) {
 | 
			
		||||
            activity?.toast(R.string.file_picker_error)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class CreateBackupDialog(bundle: Bundle? = null) : DialogController(bundle) {
 | 
			
		||||
        constructor(type: Int) : this(
 | 
			
		||||
            bundleOf(
 | 
			
		||||
                KEY_TYPE to type
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        override fun onCreateDialog(savedViewState: Bundle?): Dialog {
 | 
			
		||||
            val type = args.getInt(KEY_TYPE)
 | 
			
		||||
            val activity = activity!!
 | 
			
		||||
            val options = arrayOf(
 | 
			
		||||
                R.string.manga,
 | 
			
		||||
@@ -298,15 +261,11 @@ class SettingsBackupController : SettingsController() {
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    (targetController as? SettingsBackupController)?.createBackup(flags, type)
 | 
			
		||||
                    (targetController as? SettingsBackupController)?.createBackup(flags)
 | 
			
		||||
                }
 | 
			
		||||
                .positiveButton(R.string.action_create)
 | 
			
		||||
                .negativeButton(android.R.string.cancel)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private companion object {
 | 
			
		||||
            const val KEY_TYPE = "CreateBackupDialog.type"
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class RestoreBackupDialog(bundle: Bundle? = null) : DialogController(bundle) {
 | 
			
		||||
@@ -364,9 +323,8 @@ class SettingsBackupController : SettingsController() {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private companion object {
 | 
			
		||||
        const val CODE_LEGACY_BACKUP_CREATE = 501
 | 
			
		||||
        const val CODE_BACKUP_DIR = 503
 | 
			
		||||
        const val CODE_FULL_BACKUP_CREATE = 504
 | 
			
		||||
        const val CODE_BACKUP_CREATE = 504
 | 
			
		||||
        const val CODE_BACKUP_RESTORE = 505
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user