Warn before restoring backup if trackers aren't logged in

This commit is contained in:
arkon 2020-08-05 22:46:37 -04:00
parent 885ace111e
commit b1fb401f63
3 changed files with 37 additions and 17 deletions

View File

@ -7,16 +7,22 @@ import com.google.gson.JsonParser
import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonReader
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.backup.models.Backup import eu.kanade.tachiyomi.data.backup.models.Backup
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.source.SourceManager
import uy.kohesive.injekt.injectLazy
object BackupRestoreValidator { object BackupRestoreValidator {
private val sourceManager: SourceManager by injectLazy()
private val trackManager: TrackManager by injectLazy()
/** /**
* Checks for critical backup file data. * Checks for critical backup file data.
* *
* @throws Exception if version or manga cannot be found. * @throws Exception if version or manga cannot be found.
* @return List of required sources. * @return List of missing sources or missing trackers.
*/ */
fun validate(context: Context, uri: Uri): Map<Long, String> { fun validate(context: Context, uri: Uri): Results {
val reader = JsonReader(context.contentResolver.openInputStream(uri)!!.bufferedReader()) val reader = JsonReader(context.contentResolver.openInputStream(uri)!!.bufferedReader())
val json = JsonParser.parseReader(reader).asJsonObject val json = JsonParser.parseReader(reader).asJsonObject
@ -26,11 +32,29 @@ object BackupRestoreValidator {
throw Exception(context.getString(R.string.invalid_backup_file_missing_data)) throw Exception(context.getString(R.string.invalid_backup_file_missing_data))
} }
if (mangasJson.asJsonArray.size() == 0) { val mangas = mangasJson.asJsonArray
if (mangas.size() == 0) {
throw Exception(context.getString(R.string.invalid_backup_file_missing_manga)) throw Exception(context.getString(R.string.invalid_backup_file_missing_manga))
} }
return getSourceMapping(json) val sources = getSourceMapping(json)
val missingSources = sources
.filter { sourceManager.get(it.key) == null }
.values
.sorted()
val trackers = mangas
.filter { it.asJsonObject.has("track") }
.flatMap { it.asJsonObject["track"].asJsonArray }
.map { it.asJsonObject["s"].asInt }
.distinct()
val missingTrackers = trackers
.mapNotNull { trackManager.getService(it) }
.filter { !it.isLogged }
.map { it.name }
.sorted()
return Results(missingSources, missingTrackers)
} }
fun getSourceMapping(json: JsonObject): Map<Long, String> { fun getSourceMapping(json: JsonObject): Map<Long, String> {
@ -43,4 +67,6 @@ object BackupRestoreValidator {
} }
.toMap() .toMap()
} }
data class Results(val missingSources: List<String>, val missingTrackers: List<String>)
} }

View File

@ -21,7 +21,6 @@ import eu.kanade.tachiyomi.data.backup.BackupRestoreValidator
import eu.kanade.tachiyomi.data.backup.models.Backup import eu.kanade.tachiyomi.data.backup.models.Backup
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
import eu.kanade.tachiyomi.data.preference.asImmediateFlow import eu.kanade.tachiyomi.data.preference.asImmediateFlow
import eu.kanade.tachiyomi.source.SourceManager
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
import eu.kanade.tachiyomi.util.preference.defaultValue import eu.kanade.tachiyomi.util.preference.defaultValue
@ -37,8 +36,6 @@ import eu.kanade.tachiyomi.util.system.getFilePicker
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
class SettingsBackupController : SettingsController() { class SettingsBackupController : SettingsController() {
@ -258,16 +255,12 @@ class SettingsBackupController : SettingsController() {
return try { return try {
var message = activity.getString(R.string.backup_restore_content) var message = activity.getString(R.string.backup_restore_content)
val sources = BackupRestoreValidator.validate(activity, uri) val results = BackupRestoreValidator.validate(activity, uri)
if (sources.isNotEmpty()) { if (results.missingSources.isNotEmpty()) {
val sourceManager = Injekt.get<SourceManager>() message += "\n\n${activity.getString(R.string.backup_restore_missing_sources)}\n${results.missingSources.joinToString("\n") { "- $it" }}"
val missingSources = sources
.filter { sourceManager.get(it.key) == null }
.values
.sorted()
if (missingSources.isNotEmpty()) {
message += "\n\n${activity.getString(R.string.backup_restore_missing_sources)}\n${missingSources.joinToString("\n") { "- $it" }}"
} }
if (results.missingTrackers.isNotEmpty()) {
message += "\n\n${activity.getString(R.string.backup_restore_missing_trackers)}\n${results.missingTrackers.joinToString("\n") { "- $it" }}"
} }
MaterialDialog(activity) MaterialDialog(activity)

View File

@ -349,6 +349,7 @@
<string name="invalid_backup_file_missing_data">File is missing data.</string> <string name="invalid_backup_file_missing_data">File is missing data.</string>
<string name="invalid_backup_file_missing_manga">Backup does not contain any manga.</string> <string name="invalid_backup_file_missing_manga">Backup does not contain any manga.</string>
<string name="backup_restore_missing_sources">Missing sources:</string> <string name="backup_restore_missing_sources">Missing sources:</string>
<string name="backup_restore_missing_trackers">Trackers not logged into:</string>
<string name="backup_restore_content">Restore uses sources to fetch data, carrier costs may apply.\n\nMake sure you have installed all necessary extensions and are logged in to sources and tracking services before restoring.</string> <string name="backup_restore_content">Restore uses sources to fetch data, carrier costs may apply.\n\nMake sure you have installed all necessary extensions and are logged in to sources and tracking services before restoring.</string>
<string name="restore_completed">Restore completed</string> <string name="restore_completed">Restore completed</string>
<string name="restore_duration">%02d min, %02d sec</string> <string name="restore_duration">%02d min, %02d sec</string>