mirror of
https://git.mihon.tech/mihonapp/mihon
synced 2024-11-23 13:45:43 +03:00
Remove legacy backup creation
This commit is contained in:
parent
6843dbf7e1
commit
5e37f72d74
10 changed files with 24 additions and 262 deletions
|
@ -8,7 +8,6 @@ object BackupConst {
|
||||||
const val EXTRA_URI = "$ID.$NAME.EXTRA_URI"
|
const val EXTRA_URI = "$ID.$NAME.EXTRA_URI"
|
||||||
const val EXTRA_FLAGS = "$ID.$NAME.EXTRA_FLAGS"
|
const val EXTRA_FLAGS = "$ID.$NAME.EXTRA_FLAGS"
|
||||||
const val EXTRA_MODE = "$ID.$NAME.EXTRA_MODE"
|
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_LEGACY = 0
|
||||||
const val BACKUP_TYPE_FULL = 1
|
const val BACKUP_TYPE_FULL = 1
|
||||||
|
|
|
@ -10,7 +10,6 @@ import androidx.core.content.ContextCompat
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import com.hippo.unifile.UniFile
|
import com.hippo.unifile.UniFile
|
||||||
import eu.kanade.tachiyomi.data.backup.full.FullBackupManager
|
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.data.notification.Notifications
|
||||||
import eu.kanade.tachiyomi.util.system.acquireWakeLock
|
import eu.kanade.tachiyomi.util.system.acquireWakeLock
|
||||||
import eu.kanade.tachiyomi.util.system.isServiceRunning
|
import eu.kanade.tachiyomi.util.system.isServiceRunning
|
||||||
|
@ -48,12 +47,11 @@ class BackupCreateService : Service() {
|
||||||
* @param uri path of Uri
|
* @param uri path of Uri
|
||||||
* @param flags determines what to backup
|
* @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)) {
|
if (!isRunning(context)) {
|
||||||
val intent = Intent(context, BackupCreateService::class.java).apply {
|
val intent = Intent(context, BackupCreateService::class.java).apply {
|
||||||
putExtra(BackupConst.EXTRA_URI, uri)
|
putExtra(BackupConst.EXTRA_URI, uri)
|
||||||
putExtra(BackupConst.EXTRA_FLAGS, flags)
|
putExtra(BackupConst.EXTRA_FLAGS, flags)
|
||||||
putExtra(BackupConst.EXTRA_TYPE, type)
|
|
||||||
}
|
}
|
||||||
ContextCompat.startForegroundService(context, intent)
|
ContextCompat.startForegroundService(context, intent)
|
||||||
}
|
}
|
||||||
|
@ -103,15 +101,9 @@ class BackupCreateService : Service() {
|
||||||
try {
|
try {
|
||||||
val uri = intent.getParcelableExtra<Uri>(BackupConst.EXTRA_URI)
|
val uri = intent.getParcelableExtra<Uri>(BackupConst.EXTRA_URI)
|
||||||
val backupFlags = intent.getIntExtra(BackupConst.EXTRA_FLAGS, 0)
|
val backupFlags = intent.getIntExtra(BackupConst.EXTRA_FLAGS, 0)
|
||||||
val backupType = intent.getIntExtra(BackupConst.EXTRA_TYPE, BackupConst.BACKUP_TYPE_LEGACY)
|
val backupFileUri = FullBackupManager(this).createBackup(uri, backupFlags, false)?.toUri()
|
||||||
val backupManager = when (backupType) {
|
|
||||||
BackupConst.BACKUP_TYPE_FULL -> FullBackupManager(this)
|
|
||||||
else -> LegacyBackupManager(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
val backupFileUri = backupManager.createBackup(uri, backupFlags, false)?.toUri()
|
|
||||||
val unifile = UniFile.fromUri(this, backupFileUri)
|
val unifile = UniFile.fromUri(this, backupFileUri)
|
||||||
notifier.showBackupComplete(unifile, backupType == BackupConst.BACKUP_TYPE_LEGACY)
|
notifier.showBackupComplete(unifile)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
notifier.showBackupError(e.message)
|
notifier.showBackupError(e.message)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,6 @@ import androidx.work.WorkManager
|
||||||
import androidx.work.Worker
|
import androidx.work.Worker
|
||||||
import androidx.work.WorkerParameters
|
import androidx.work.WorkerParameters
|
||||||
import eu.kanade.tachiyomi.data.backup.full.FullBackupManager
|
import eu.kanade.tachiyomi.data.backup.full.FullBackupManager
|
||||||
import eu.kanade.tachiyomi.data.backup.legacy.LegacyBackupManager
|
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
@ -23,9 +22,6 @@ class BackupCreatorJob(private val context: Context, workerParams: WorkerParamet
|
||||||
val flags = BackupCreateService.BACKUP_ALL
|
val flags = BackupCreateService.BACKUP_ALL
|
||||||
return try {
|
return try {
|
||||||
FullBackupManager(context).createBackup(uri, flags, true)
|
FullBackupManager(context).createBackup(uri, flags, true)
|
||||||
if (preferences.createLegacyBackup().get()) {
|
|
||||||
LegacyBackupManager(context).createBackup(uri, flags, true)
|
|
||||||
}
|
|
||||||
Result.success()
|
Result.success()
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Result.failure()
|
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)
|
context.notificationManager.cancel(Notifications.ID_BACKUP_PROGRESS)
|
||||||
|
|
||||||
with(completeNotificationBuilder) {
|
with(completeNotificationBuilder) {
|
||||||
|
@ -73,7 +73,7 @@ class BackupNotifier(private val context: Context) {
|
||||||
addAction(
|
addAction(
|
||||||
R.drawable.ic_share_24dp,
|
R.drawable.ic_share_24dp,
|
||||||
context.getString(R.string.action_share),
|
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)
|
show(Notifications.ID_BACKUP_COMPLETE)
|
||||||
|
|
|
@ -5,30 +5,11 @@ import android.net.Uri
|
||||||
import com.github.salomonbrys.kotson.fromJson
|
import com.github.salomonbrys.kotson.fromJson
|
||||||
import com.github.salomonbrys.kotson.registerTypeAdapter
|
import com.github.salomonbrys.kotson.registerTypeAdapter
|
||||||
import com.github.salomonbrys.kotson.registerTypeHierarchyAdapter
|
import com.github.salomonbrys.kotson.registerTypeHierarchyAdapter
|
||||||
import com.github.salomonbrys.kotson.set
|
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import com.google.gson.GsonBuilder
|
import com.google.gson.GsonBuilder
|
||||||
import com.google.gson.JsonArray
|
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.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.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.models.DHistory
|
||||||
import eu.kanade.tachiyomi.data.backup.legacy.serializer.CategoryTypeAdapter
|
import eu.kanade.tachiyomi.data.backup.legacy.serializer.CategoryTypeAdapter
|
||||||
import eu.kanade.tachiyomi.data.backup.legacy.serializer.ChapterTypeAdapter
|
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.Track
|
||||||
import eu.kanade.tachiyomi.data.database.models.TrackImpl
|
import eu.kanade.tachiyomi.data.database.models.TrackImpl
|
||||||
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
|
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.Source
|
||||||
import eu.kanade.tachiyomi.source.model.toSManga
|
import eu.kanade.tachiyomi.source.model.toSManga
|
||||||
import timber.log.Timber
|
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
||||||
class LegacyBackupManager(context: Context, version: Int = CURRENT_VERSION) : AbstractBackupManager(context) {
|
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 uri path of Uri
|
||||||
* @param isJob backup called from job
|
* @param isJob backup called from job
|
||||||
*/
|
*/
|
||||||
override fun createBackup(uri: Uri, flags: Int, isJob: Boolean): String? {
|
override fun createBackup(uri: Uri, flags: Int, isJob: Boolean) =
|
||||||
// Create root object
|
throw IllegalStateException("Legacy backup creation is not supported")
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
fun restoreMangaNoFetch(manga: Manga, dbManga: Manga) {
|
fun restoreMangaNoFetch(manga: Manga, dbManga: Manga) {
|
||||||
manga.id = dbManga.id
|
manga.id = dbManga.id
|
||||||
|
|
|
@ -73,7 +73,7 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||||
shareFile(
|
shareFile(
|
||||||
context,
|
context,
|
||||||
intent.getParcelableExtra(EXTRA_URI),
|
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)
|
intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1)
|
||||||
)
|
)
|
||||||
ACTION_CANCEL_RESTORE -> cancelRestore(
|
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_MANGA_ID = "$ID.$NAME.EXTRA_MANGA_ID"
|
||||||
private const val EXTRA_CHAPTER_ID = "$ID.$NAME.EXTRA_CHAPTER_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_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
|
* Returns a [PendingIntent] that resumes the download of a chapter
|
||||||
|
@ -494,11 +493,10 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||||
* @param notificationId id of notification
|
* @param notificationId id of notification
|
||||||
* @return [PendingIntent]
|
* @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 {
|
val intent = Intent(context, NotificationReceiver::class.java).apply {
|
||||||
action = ACTION_SHARE_BACKUP
|
action = ACTION_SHARE_BACKUP
|
||||||
putExtra(EXTRA_URI, uri)
|
putExtra(EXTRA_URI, uri)
|
||||||
putExtra(EXTRA_IS_LEGACY_BACKUP, isLegacyFormat)
|
|
||||||
putExtra(EXTRA_NOTIFICATION_ID, notificationId)
|
putExtra(EXTRA_NOTIFICATION_ID, notificationId)
|
||||||
}
|
}
|
||||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
|
|
|
@ -214,8 +214,6 @@ object PreferenceKeys {
|
||||||
|
|
||||||
const val incognitoMode = "incognito_mode"
|
const val incognitoMode = "incognito_mode"
|
||||||
|
|
||||||
const val createLegacyBackup = "create_legacy_backup"
|
|
||||||
|
|
||||||
fun trackUsername(syncId: Int) = "pref_mangasync_username_$syncId"
|
fun trackUsername(syncId: Int) = "pref_mangasync_username_$syncId"
|
||||||
|
|
||||||
fun trackPassword(syncId: Int) = "pref_mangasync_password_$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 incognitoMode() = flowPrefs.getBoolean(Keys.incognitoMode, false)
|
||||||
|
|
||||||
fun createLegacyBackup() = flowPrefs.getBoolean(Keys.createLegacyBackup, true)
|
|
||||||
|
|
||||||
fun setChapterSettingsDefault(manga: Manga) {
|
fun setChapterSettingsDefault(manga: Manga) {
|
||||||
prefs.edit {
|
prefs.edit {
|
||||||
putInt(Keys.defaultChapterFilterByRead, manga.readFilter)
|
putInt(Keys.defaultChapterFilterByRead, manga.readFilter)
|
||||||
|
|
|
@ -4,7 +4,6 @@ import android.Manifest.permission.WRITE_EXTERNAL_STORAGE
|
||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.app.Dialog
|
import android.app.Dialog
|
||||||
import android.content.ActivityNotFoundException
|
import android.content.ActivityNotFoundException
|
||||||
import android.content.Context
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
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.FullBackupRestoreValidator
|
||||||
import eu.kanade.tachiyomi.data.backup.full.models.BackupFull
|
import eu.kanade.tachiyomi.data.backup.full.models.BackupFull
|
||||||
import eu.kanade.tachiyomi.data.backup.legacy.LegacyBackupRestoreValidator
|
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.data.preference.asImmediateFlow
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe
|
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.preference
|
||||||
import eu.kanade.tachiyomi.util.preference.preferenceCategory
|
import eu.kanade.tachiyomi.util.preference.preferenceCategory
|
||||||
import eu.kanade.tachiyomi.util.preference.summaryRes
|
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.preference.titleRes
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import kotlinx.coroutines.flow.launchIn
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
@ -66,14 +63,15 @@ class SettingsBackupController : SettingsController() {
|
||||||
titleRes = R.string.pref_create_backup
|
titleRes = R.string.pref_create_backup
|
||||||
summaryRes = R.string.pref_create_backup_summ
|
summaryRes = R.string.pref_create_backup_summ
|
||||||
|
|
||||||
onClick { backup(context, BackupConst.BACKUP_TYPE_FULL) }
|
onClick {
|
||||||
}
|
if (!BackupCreateService.isRunning(context)) {
|
||||||
preference {
|
val ctrl = CreateBackupDialog()
|
||||||
key = "pref_create_legacy_backup"
|
ctrl.targetController = this@SettingsBackupController
|
||||||
titleRes = R.string.pref_create_legacy_backup
|
ctrl.showDialog(router)
|
||||||
summaryRes = R.string.pref_create_legacy_backup_summary
|
} else {
|
||||||
|
context.toast(R.string.backup_in_progress)
|
||||||
onClick { backup(context, BackupConst.BACKUP_TYPE_LEGACY) }
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
preference {
|
preference {
|
||||||
key = "pref_restore_backup"
|
key = "pref_restore_backup"
|
||||||
|
@ -150,14 +148,6 @@ class SettingsBackupController : SettingsController() {
|
||||||
defaultValue = "1"
|
defaultValue = "1"
|
||||||
summary = "%s"
|
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 }
|
preferences.backupInterval().asImmediateFlow { isVisible = it > 0 }
|
||||||
.launchIn(viewScope)
|
.launchIn(viewScope)
|
||||||
}
|
}
|
||||||
|
@ -182,7 +172,7 @@ class SettingsBackupController : SettingsController() {
|
||||||
// Set backup Uri
|
// Set backup Uri
|
||||||
preferences.backupsDirectory().set(uri.toString())
|
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
|
val flags = Intent.FLAG_GRANT_READ_URI_PERMISSION or
|
||||||
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||||
|
|
||||||
|
@ -198,7 +188,6 @@ class SettingsBackupController : SettingsController() {
|
||||||
activity,
|
activity,
|
||||||
file.uri,
|
file.uri,
|
||||||
backupFlags,
|
backupFlags,
|
||||||
if (requestCode == CODE_FULL_BACKUP_CREATE) BackupConst.BACKUP_TYPE_FULL else BackupConst.BACKUP_TYPE_LEGACY
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
CODE_BACKUP_RESTORE -> {
|
CODE_BACKUP_RESTORE -> {
|
||||||
|
@ -227,49 +216,23 @@ class SettingsBackupController : SettingsController() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun backup(context: Context, type: Int) {
|
fun createBackup(flags: 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) {
|
|
||||||
backupFlags = flags
|
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 {
|
try {
|
||||||
// Use Android's built-in file creator
|
// Use Android's built-in file creator
|
||||||
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
|
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT)
|
||||||
.addCategory(Intent.CATEGORY_OPENABLE)
|
.addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
.setType("application/*")
|
.setType("application/*")
|
||||||
.putExtra(Intent.EXTRA_TITLE, fileName)
|
.putExtra(Intent.EXTRA_TITLE, BackupFull.getDefaultFilename())
|
||||||
|
|
||||||
startActivityForResult(intent, code)
|
startActivityForResult(intent, CODE_BACKUP_CREATE)
|
||||||
} catch (e: ActivityNotFoundException) {
|
} catch (e: ActivityNotFoundException) {
|
||||||
activity?.toast(R.string.file_picker_error)
|
activity?.toast(R.string.file_picker_error)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CreateBackupDialog(bundle: Bundle? = null) : DialogController(bundle) {
|
class CreateBackupDialog(bundle: Bundle? = null) : DialogController(bundle) {
|
||||||
constructor(type: Int) : this(
|
|
||||||
bundleOf(
|
|
||||||
KEY_TYPE to type
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||||
val type = args.getInt(KEY_TYPE)
|
|
||||||
val activity = activity!!
|
val activity = activity!!
|
||||||
val options = arrayOf(
|
val options = arrayOf(
|
||||||
R.string.manga,
|
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)
|
.positiveButton(R.string.action_create)
|
||||||
.negativeButton(android.R.string.cancel)
|
.negativeButton(android.R.string.cancel)
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
|
||||||
const val KEY_TYPE = "CreateBackupDialog.type"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class RestoreBackupDialog(bundle: Bundle? = null) : DialogController(bundle) {
|
class RestoreBackupDialog(bundle: Bundle? = null) : DialogController(bundle) {
|
||||||
|
@ -364,9 +323,8 @@ class SettingsBackupController : SettingsController() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private companion object {
|
private companion object {
|
||||||
const val CODE_LEGACY_BACKUP_CREATE = 501
|
|
||||||
const val CODE_BACKUP_DIR = 503
|
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
|
const val CODE_BACKUP_RESTORE = 505
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -392,9 +392,6 @@
|
||||||
<string name="pref_create_backup_summ">Can be used to restore current library</string>
|
<string name="pref_create_backup_summ">Can be used to restore current library</string>
|
||||||
<string name="pref_restore_backup">Restore backup</string>
|
<string name="pref_restore_backup">Restore backup</string>
|
||||||
<string name="pref_restore_backup_summ">Restore library from backup file</string>
|
<string name="pref_restore_backup_summ">Restore library from backup file</string>
|
||||||
<string name="pref_create_legacy_backup">Create legacy backup</string>
|
|
||||||
<string name="pref_create_legacy_backup_summary">Can be used in older versions of Tachiyomi</string>
|
|
||||||
<string name="pref_backup_auto_create_legacy">Also create legacy backup</string>
|
|
||||||
<string name="pref_backup_directory">Backup location</string>
|
<string name="pref_backup_directory">Backup location</string>
|
||||||
<string name="pref_backup_service_category">Automatic backups</string>
|
<string name="pref_backup_service_category">Automatic backups</string>
|
||||||
<string name="pref_backup_interval">Backup frequency</string>
|
<string name="pref_backup_interval">Backup frequency</string>
|
||||||
|
|
Loading…
Reference in a new issue