Move backup models to domain module

(cherry picked from commit 5908bd19305b3461165fcfe2da5d2217115562b9)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/data/backup/create/BackupCreator.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/backup/create/creators/MangaBackupCreator.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/backup/restore/BackupRestorer.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/backup/restore/restorers/MangaRestorer.kt
#	app/src/main/java/eu/kanade/tachiyomi/di/AppModule.kt
#	domain/src/main/java/tachiyomi/domain/backup/model/Backup.kt
#	domain/src/main/java/tachiyomi/domain/backup/model/BackupFlatMetadata.kt
#	domain/src/main/java/tachiyomi/domain/backup/model/BackupManga.kt
#	domain/src/main/java/tachiyomi/domain/backup/model/BackupMergedMangaReference.kt
#	domain/src/main/java/tachiyomi/domain/backup/model/BackupSavedSearch.kt
#	domain/src/main/java/tachiyomi/domain/backup/model/metadata/BackupSearchMetadata.kt
#	domain/src/main/java/tachiyomi/domain/backup/model/metadata/BackupSearchTag.kt
#	domain/src/main/java/tachiyomi/domain/backup/model/metadata/BackupSearchTitle.kt
This commit is contained in:
arkon 2023-12-24 17:38:01 -05:00 committed by Jobobby04
parent 2238b123f9
commit a96cff950a
35 changed files with 209 additions and 212 deletions

View File

@ -31,7 +31,7 @@ import eu.kanade.presentation.components.WarningBanner
import eu.kanade.presentation.util.Screen import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags
import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob
import eu.kanade.tachiyomi.data.backup.models.Backup import eu.kanade.tachiyomi.data.backup.create.BackupCreator
import eu.kanade.tachiyomi.util.system.DeviceUtil import eu.kanade.tachiyomi.util.system.DeviceUtil
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.collections.immutable.PersistentSet import kotlinx.collections.immutable.PersistentSet
@ -124,7 +124,7 @@ class CreateBackupScreen : Screen() {
onClick = { onClick = {
if (!BackupCreateJob.isManualJobRunning(context)) { if (!BackupCreateJob.isManualJobRunning(context)) {
try { try {
chooseBackupDir.launch(Backup.getFilename()) chooseBackupDir.launch(BackupCreator.getFilename())
} catch (e: ActivityNotFoundException) { } catch (e: ActivityNotFoundException) {
context.toast(MR.strings.file_picker_error) context.toast(MR.strings.file_picker_error)
} }

View File

@ -154,7 +154,7 @@ class RestoreBackupScreen : Screen() {
} }
val results = try { val results = try {
BackupFileValidator().validate(context, it) BackupFileValidator(context).validate(it)
} catch (e: Exception) { } catch (e: Exception) {
model.setError(InvalidRestore(it, e.message.toString())) model.setError(InvalidRestore(it, e.message.toString()))
return@rememberLauncherForActivityResult return@rememberLauncherForActivityResult

View File

@ -17,10 +17,10 @@ import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.presentation.components.AppBar import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.components.AppBarActions import eu.kanade.presentation.components.AppBarActions
import eu.kanade.presentation.util.Screen import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.data.backup.models.Backup
import eu.kanade.tachiyomi.util.system.copyToClipboard import eu.kanade.tachiyomi.util.system.copyToClipboard
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import kotlinx.serialization.protobuf.schema.ProtoBufSchemaGenerator import kotlinx.serialization.protobuf.schema.ProtoBufSchemaGenerator
import tachiyomi.domain.backup.model.Backup
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.Scaffold import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.i18n.stringResource import tachiyomi.presentation.core.i18n.stringResource

View File

@ -1,21 +1,25 @@
package eu.kanade.tachiyomi.util package eu.kanade.tachiyomi.data.backup
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import eu.kanade.tachiyomi.data.backup.create.BackupCreator import kotlinx.serialization.protobuf.ProtoBuf
import eu.kanade.tachiyomi.data.backup.models.Backup
import eu.kanade.tachiyomi.data.backup.models.BackupSerializer
import okio.buffer import okio.buffer
import okio.gzip import okio.gzip
import okio.source import okio.source
import tachiyomi.domain.backup.model.Backup
import tachiyomi.domain.backup.model.BackupSerializer
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
class BackupDecoder(
private val context: Context,
private val parser: ProtoBuf = Injekt.get(),
) {
object BackupUtil {
/** /**
* Decode a potentially-gzipped backup. * Decode a potentially-gzipped backup.
*/ */
fun decodeBackup(context: Context, uri: Uri): Backup { fun decode(uri: Uri): Backup {
val backupCreator = BackupCreator(context)
val backupStringSource = context.contentResolver.openInputStream(uri)!!.source().buffer() val backupStringSource = context.contentResolver.openInputStream(uri)!!.source().buffer()
val peeked = backupStringSource.peek() val peeked = backupStringSource.peek()
@ -27,6 +31,6 @@ object BackupUtil {
backupStringSource backupStringSource
}.use { it.readByteArray() } }.use { it.readByteArray() }
return backupCreator.parser.decodeFromByteArray(BackupSerializer, backupString) return parser.decodeFromByteArray(BackupSerializer, backupString)
} }
} }

View File

@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.data.backup
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import eu.kanade.tachiyomi.data.track.TrackerManager import eu.kanade.tachiyomi.data.track.TrackerManager
import eu.kanade.tachiyomi.util.BackupUtil
import tachiyomi.core.i18n.stringResource import tachiyomi.core.i18n.stringResource
import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.source.service.SourceManager
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
@ -11,6 +10,8 @@ import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
class BackupFileValidator( class BackupFileValidator(
private val context: Context,
private val sourceManager: SourceManager = Injekt.get(), private val sourceManager: SourceManager = Injekt.get(),
private val trackerManager: TrackerManager = Injekt.get(), private val trackerManager: TrackerManager = Injekt.get(),
) { ) {
@ -21,9 +22,9 @@ class BackupFileValidator(
* @throws Exception if manga cannot be found. * @throws Exception if manga cannot be found.
* @return List of missing sources or missing trackers. * @return List of missing sources or missing trackers.
*/ */
fun validate(context: Context, uri: Uri): Results { fun validate(uri: Uri): Results {
val backup = try { val backup = try {
BackupUtil.decodeBackup(context, uri) BackupDecoder(context).decode(uri)
} catch (e: Exception) { } catch (e: Exception) {
throw IllegalStateException(e) throw IllegalStateException(e)
} }

View File

@ -29,7 +29,6 @@ import tachiyomi.domain.backup.service.BackupPreferences
import tachiyomi.domain.storage.service.StorageManager import tachiyomi.domain.storage.service.StorageManager
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.time.Instant
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
class BackupCreateJob(private val context: Context, workerParams: WorkerParameters) : class BackupCreateJob(private val context: Context, workerParams: WorkerParameters) :
@ -49,13 +48,10 @@ class BackupCreateJob(private val context: Context, workerParams: WorkerParamete
setForegroundSafely() setForegroundSafely()
val flags = inputData.getInt(BACKUP_FLAGS_KEY, BackupCreateFlags.AutomaticDefaults) val flags = inputData.getInt(BACKUP_FLAGS_KEY, BackupCreateFlags.AutomaticDefaults)
val backupPreferences = Injekt.get<BackupPreferences>()
return try { return try {
val location = BackupCreator(context).createBackup(uri, flags, isAutoBackup) val location = BackupCreator(context, isAutoBackup).backup(uri, flags)
if (isAutoBackup) { if (!isAutoBackup) {
backupPreferences.lastAutoBackupTimestamp().set(Instant.now().toEpochMilli())
} else {
notifier.showBackupComplete(UniFile.fromUri(context, location.toUri())!!) notifier.showBackupComplete(UniFile.fromUri(context, location.toUri())!!)
} }
Result.success() Result.success()

View File

@ -3,10 +3,10 @@ package eu.kanade.tachiyomi.data.backup.create
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import com.hippo.unifile.UniFile import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.data.backup.BackupFileValidator import eu.kanade.tachiyomi.data.backup.BackupFileValidator
import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags.BACKUP_APP_PREFS import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags.BACKUP_APP_PREFS
import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags.BACKUP_CATEGORY import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags.BACKUP_CATEGORY
import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags.BACKUP_CUSTOM_INFO
import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags.BACKUP_READ_MANGA import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags.BACKUP_READ_MANGA
import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags.BACKUP_SOURCE_PREFS import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags.BACKUP_SOURCE_PREFS
import eu.kanade.tachiyomi.data.backup.create.creators.CategoriesBackupCreator import eu.kanade.tachiyomi.data.backup.create.creators.CategoriesBackupCreator
@ -14,14 +14,6 @@ import eu.kanade.tachiyomi.data.backup.create.creators.MangaBackupCreator
import eu.kanade.tachiyomi.data.backup.create.creators.PreferenceBackupCreator import eu.kanade.tachiyomi.data.backup.create.creators.PreferenceBackupCreator
import eu.kanade.tachiyomi.data.backup.create.creators.SavedSearchBackupCreator import eu.kanade.tachiyomi.data.backup.create.creators.SavedSearchBackupCreator
import eu.kanade.tachiyomi.data.backup.create.creators.SourcesBackupCreator import eu.kanade.tachiyomi.data.backup.create.creators.SourcesBackupCreator
import eu.kanade.tachiyomi.data.backup.models.Backup
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
import eu.kanade.tachiyomi.data.backup.models.BackupManga
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
import eu.kanade.tachiyomi.data.backup.models.BackupSerializer
import eu.kanade.tachiyomi.data.backup.models.BackupSource
import eu.kanade.tachiyomi.data.backup.models.BackupSourcePreferences
import kotlinx.serialization.protobuf.ProtoBuf import kotlinx.serialization.protobuf.ProtoBuf
import logcat.LogPriority import logcat.LogPriority
import okio.buffer import okio.buffer
@ -31,40 +23,47 @@ import tachiyomi.core.i18n.stringResource
import tachiyomi.core.util.system.logcat import tachiyomi.core.util.system.logcat
import tachiyomi.data.DatabaseHandler import tachiyomi.data.DatabaseHandler
import tachiyomi.data.manga.MangaMapper import tachiyomi.data.manga.MangaMapper
import tachiyomi.domain.backup.model.Backup
import tachiyomi.domain.backup.model.BackupCategory
import tachiyomi.domain.backup.model.BackupManga
import tachiyomi.domain.backup.model.BackupPreference
import tachiyomi.domain.backup.model.BackupSavedSearch
import tachiyomi.domain.backup.model.BackupSerializer
import tachiyomi.domain.backup.model.BackupSource
import tachiyomi.domain.backup.model.BackupSourcePreferences
import tachiyomi.domain.backup.service.BackupPreferences
import tachiyomi.domain.manga.interactor.GetFavorites import tachiyomi.domain.manga.interactor.GetFavorites
import tachiyomi.domain.manga.interactor.GetFlatMetadataById
import tachiyomi.domain.manga.interactor.GetMergedManga import tachiyomi.domain.manga.interactor.GetMergedManga
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.io.FileOutputStream import java.io.FileOutputStream
import java.text.SimpleDateFormat
import java.time.Instant
import java.util.Date
import java.util.Locale
class BackupCreator( class BackupCreator(
private val context: Context, private val context: Context,
private val isAutoBackup: Boolean,
private val parser: ProtoBuf = Injekt.get(),
private val getFavorites: GetFavorites = Injekt.get(),
private val backupPreferences: BackupPreferences = Injekt.get(),
private val categoriesBackupCreator: CategoriesBackupCreator = CategoriesBackupCreator(), private val categoriesBackupCreator: CategoriesBackupCreator = CategoriesBackupCreator(),
private val mangaBackupCreator: MangaBackupCreator = MangaBackupCreator(), private val mangaBackupCreator: MangaBackupCreator = MangaBackupCreator(),
private val preferenceBackupCreator: PreferenceBackupCreator = PreferenceBackupCreator(), private val preferenceBackupCreator: PreferenceBackupCreator = PreferenceBackupCreator(),
private val sourcesBackupCreator: SourcesBackupCreator = SourcesBackupCreator(), private val sourcesBackupCreator: SourcesBackupCreator = SourcesBackupCreator(),
// SY --> // SY -->
private val savedSearchBackupCreator: SavedSearchBackupCreator = SavedSearchBackupCreator(), private val savedSearchBackupCreator: SavedSearchBackupCreator = SavedSearchBackupCreator(),
// SY <--
private val getFavorites: GetFavorites = Injekt.get(),
// SY -->
private val getMergedManga: GetMergedManga = Injekt.get(), private val getMergedManga: GetMergedManga = Injekt.get(),
private val handler: DatabaseHandler = Injekt.get() private val handler: DatabaseHandler = Injekt.get()
// SY <-- // SY <--
) { ) {
internal val parser = ProtoBuf suspend fun backup(uri: Uri, flags: Int): String {
/**
* Create backup file.
*
* @param uri path of Uri
* @param isAutoBackup backup called from scheduled backup job
*/
suspend fun createBackup(uri: Uri, flags: Int, isAutoBackup: Boolean): String {
var file: UniFile? = null var file: UniFile? = null
try { try {
file = ( file = (
@ -73,14 +72,14 @@ class BackupCreator(
val dir = UniFile.fromUri(context, uri) val dir = UniFile.fromUri(context, uri)
// Delete older backups // Delete older backups
dir?.listFiles { _, filename -> Backup.filenameRegex.matches(filename) } dir?.listFiles { _, filename -> FILENAME_REGEX.matches(filename) }
.orEmpty() .orEmpty()
.sortedByDescending { it.name } .sortedByDescending { it.name }
.drop(MAX_AUTO_BACKUPS - 1) .drop(MAX_AUTO_BACKUPS - 1)
.forEach { it.delete() } .forEach { it.delete() }
// Create new file to place backup // Create new file to place backup
dir?.createFile(Backup.getFilename()) dir?.createFile(BackupCreator.getFilename())
} else { } else {
UniFile.fromUri(context, uri) UniFile.fromUri(context, uri)
} }
@ -113,14 +112,22 @@ class BackupCreator(
throw IllegalStateException(context.stringResource(MR.strings.empty_backup_error)) throw IllegalStateException(context.stringResource(MR.strings.empty_backup_error))
} }
file.openOutputStream().also { file.openOutputStream()
// Force overwrite old file .also {
(it as? FileOutputStream)?.channel?.truncate(0) // Force overwrite old file
}.sink().gzip().buffer().use { it.write(byteArray) } (it as? FileOutputStream)?.channel?.truncate(0)
}
.sink().gzip().buffer().use {
it.write(byteArray)
}
val fileUri = file.uri val fileUri = file.uri
// Make sure it's a valid backup file // Make sure it's a valid backup file
BackupFileValidator().validate(context, fileUri) BackupFileValidator(context).validate(fileUri)
if (isAutoBackup) {
backupPreferences.lastAutoBackupTimestamp().set(Instant.now().toEpochMilli())
}
return fileUri.toString() return fileUri.toString()
} catch (e: Exception) { } catch (e: Exception) {
@ -161,6 +168,14 @@ class BackupCreator(
return savedSearchBackupCreator.backupSavedSearches() return savedSearchBackupCreator.backupSavedSearches()
} }
// SY <-- // SY <--
}
private val MAX_AUTO_BACKUPS: Int = 4 companion object {
private const val MAX_AUTO_BACKUPS: Int = 4
private val FILENAME_REGEX = """${BuildConfig.APPLICATION_ID}_\d{4}-\d{2}-\d{2}_\d{2}-\d{2}.tachibk""".toRegex()
fun getFilename(): String {
val date = SimpleDateFormat("yyyy-MM-dd_HH-mm", Locale.ENGLISH).format(Date())
return "${BuildConfig.APPLICATION_ID}_$date.tachibk"
}
}
}

View File

@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.data.backup.create.creators package eu.kanade.tachiyomi.data.backup.create.creators
import eu.kanade.tachiyomi.data.backup.models.BackupCategory import tachiyomi.domain.backup.model.BackupCategory
import eu.kanade.tachiyomi.data.backup.models.backupCategoryMapper import tachiyomi.domain.backup.model.backupCategoryMapper
import tachiyomi.domain.category.interactor.GetCategories import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.category.model.Category import tachiyomi.domain.category.model.Category
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt

View File

@ -2,21 +2,23 @@ package eu.kanade.tachiyomi.data.backup.create.creators
import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags
import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags.BACKUP_CUSTOM_INFO import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags.BACKUP_CUSTOM_INFO
import eu.kanade.tachiyomi.data.backup.models.BackupChapter
import eu.kanade.tachiyomi.data.backup.models.BackupFlatMetadata
import eu.kanade.tachiyomi.data.backup.models.BackupHistory
import eu.kanade.tachiyomi.data.backup.models.BackupManga
import eu.kanade.tachiyomi.data.backup.models.backupChapterMapper
import eu.kanade.tachiyomi.data.backup.models.backupMergedMangaReferenceMapper
import eu.kanade.tachiyomi.data.backup.models.backupTrackMapper
import eu.kanade.tachiyomi.source.online.MetadataSource import eu.kanade.tachiyomi.source.online.MetadataSource
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
import exh.source.MERGED_SOURCE_ID import exh.source.MERGED_SOURCE_ID
import exh.source.getMainSource import exh.source.getMainSource
import tachiyomi.data.DatabaseHandler import tachiyomi.data.DatabaseHandler
import tachiyomi.domain.backup.model.BackupChapter
import tachiyomi.domain.backup.model.BackupFlatMetadata
import tachiyomi.domain.backup.model.BackupHistory
import tachiyomi.domain.backup.model.BackupManga
import tachiyomi.domain.backup.model.backupChapterMapper
import tachiyomi.domain.backup.model.backupMergedMangaReferenceMapper
import tachiyomi.domain.backup.model.backupTrackMapper
import tachiyomi.domain.category.interactor.GetCategories import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.history.interactor.GetHistory import tachiyomi.domain.history.interactor.GetHistory
import tachiyomi.domain.manga.interactor.GetCustomMangaInfo import tachiyomi.domain.manga.interactor.GetCustomMangaInfo
import tachiyomi.domain.manga.interactor.GetFlatMetadataById import tachiyomi.domain.manga.interactor.GetFlatMetadataById
import tachiyomi.domain.manga.model.CustomMangaInfo
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.source.service.SourceManager
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
@ -41,8 +43,7 @@ class MangaBackupCreator(
private suspend fun backupManga(manga: Manga, options: Int): BackupManga { private suspend fun backupManga(manga: Manga, options: Int): BackupManga {
// Entry for this manga // Entry for this manga
val mangaObject = BackupManga.copyFrom( val mangaObject = manga.toBackupManga(
manga,
// SY --> // SY -->
if (options and BACKUP_CUSTOM_INFO == BACKUP_CUSTOM_INFO) { if (options and BACKUP_CUSTOM_INFO == BACKUP_CUSTOM_INFO) {
getCustomMangaInfo.get(manga.id) getCustomMangaInfo.get(manga.id)
@ -114,3 +115,35 @@ class MangaBackupCreator(
return mangaObject return mangaObject
} }
} }
private fun Manga.toBackupManga(/* SY --> */customMangaInfo: CustomMangaInfo?/* SY <-- */) =
BackupManga(
url = this.url,
title = this.title,
artist = this.artist,
author = this.author,
description = this.description,
genre = this.genre.orEmpty(),
status = this.status.toInt(),
thumbnailUrl = this.thumbnailUrl,
favorite = this.favorite,
source = this.source,
dateAdded = this.dateAdded,
viewer = (this.viewerFlags.toInt() and ReadingMode.MASK),
viewer_flags = this.viewerFlags.toInt(),
chapterFlags = this.chapterFlags.toInt(),
updateStrategy = this.updateStrategy,
lastModifiedAt = this.lastModifiedAt,
favoriteModifiedAt = this.favoriteModifiedAt,
// SY -->
).also { backupManga ->
customMangaInfo?.let {
backupManga.customTitle = it.title
backupManga.customArtist = it.artist
backupManga.customAuthor = it.author
backupManga.customDescription = it.description
backupManga.customGenre = it.genre
backupManga.customStatus = it.status?.toInt() ?: 0
}
}
// SY <--

View File

@ -1,18 +1,18 @@
package eu.kanade.tachiyomi.data.backup.create.creators package eu.kanade.tachiyomi.data.backup.create.creators
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
import eu.kanade.tachiyomi.data.backup.models.BackupSourcePreferences
import eu.kanade.tachiyomi.data.backup.models.BooleanPreferenceValue
import eu.kanade.tachiyomi.data.backup.models.FloatPreferenceValue
import eu.kanade.tachiyomi.data.backup.models.IntPreferenceValue
import eu.kanade.tachiyomi.data.backup.models.LongPreferenceValue
import eu.kanade.tachiyomi.data.backup.models.StringPreferenceValue
import eu.kanade.tachiyomi.data.backup.models.StringSetPreferenceValue
import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.preferenceKey import eu.kanade.tachiyomi.source.preferenceKey
import eu.kanade.tachiyomi.source.sourcePreferences import eu.kanade.tachiyomi.source.sourcePreferences
import tachiyomi.core.preference.Preference import tachiyomi.core.preference.Preference
import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.preference.PreferenceStore
import tachiyomi.domain.backup.model.BackupPreference
import tachiyomi.domain.backup.model.BackupSourcePreferences
import tachiyomi.domain.backup.model.BooleanPreferenceValue
import tachiyomi.domain.backup.model.FloatPreferenceValue
import tachiyomi.domain.backup.model.IntPreferenceValue
import tachiyomi.domain.backup.model.LongPreferenceValue
import tachiyomi.domain.backup.model.StringPreferenceValue
import tachiyomi.domain.backup.model.StringSetPreferenceValue
import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.source.service.SourceManager
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get

View File

@ -1,8 +1,8 @@
package eu.kanade.tachiyomi.data.backup.create.creators package eu.kanade.tachiyomi.data.backup.create.creators
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
import eu.kanade.tachiyomi.data.backup.models.backupSavedSearchMapper
import tachiyomi.data.DatabaseHandler import tachiyomi.data.DatabaseHandler
import tachiyomi.domain.backup.model.BackupSavedSearch
import tachiyomi.domain.backup.model.backupSavedSearchMapper
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get

View File

@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.data.backup.create.creators package eu.kanade.tachiyomi.data.backup.create.creators
import eu.kanade.tachiyomi.data.backup.models.BackupSource import eu.kanade.tachiyomi.source.Source
import tachiyomi.domain.backup.model.BackupSource
import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.source.service.SourceManager import tachiyomi.domain.source.service.SourceManager
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
@ -16,7 +17,13 @@ class SourcesBackupCreator(
.map(Manga::source) .map(Manga::source)
.distinct() .distinct()
.map(sourceManager::getOrStub) .map(sourceManager::getOrStub)
.map(BackupSource::copyFrom) .map { it.toBackupSource() }
.toList() .toList()
} }
} }
private fun Source.toBackupSource() =
BackupSource(
name = this.name,
sourceId = this.id,
)

View File

@ -1,6 +0,0 @@
package eu.kanade.tachiyomi.data.backup.models
import kotlinx.serialization.Serializer
@Serializer(forClass = Backup::class)
object BackupSerializer

View File

@ -2,17 +2,12 @@ package eu.kanade.tachiyomi.data.backup.restore
import android.content.Context import android.content.Context
import android.net.Uri import android.net.Uri
import eu.kanade.tachiyomi.data.backup.BackupDecoder
import eu.kanade.tachiyomi.data.backup.BackupNotifier import eu.kanade.tachiyomi.data.backup.BackupNotifier
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
import eu.kanade.tachiyomi.data.backup.models.BackupManga
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
import eu.kanade.tachiyomi.data.backup.models.BackupSourcePreferences
import eu.kanade.tachiyomi.data.backup.restore.restorers.CategoriesRestorer import eu.kanade.tachiyomi.data.backup.restore.restorers.CategoriesRestorer
import eu.kanade.tachiyomi.data.backup.restore.restorers.MangaRestorer import eu.kanade.tachiyomi.data.backup.restore.restorers.MangaRestorer
import eu.kanade.tachiyomi.data.backup.restore.restorers.PreferenceRestorer import eu.kanade.tachiyomi.data.backup.restore.restorers.PreferenceRestorer
import eu.kanade.tachiyomi.data.backup.restore.restorers.SavedSearchRestorer import eu.kanade.tachiyomi.data.backup.restore.restorers.SavedSearchRestorer
import eu.kanade.tachiyomi.util.BackupUtil
import eu.kanade.tachiyomi.util.system.createFileInCacheDir import eu.kanade.tachiyomi.util.system.createFileInCacheDir
import exh.source.MERGED_SOURCE_ID import exh.source.MERGED_SOURCE_ID
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -20,6 +15,11 @@ import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.ensureActive import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import tachiyomi.core.i18n.stringResource import tachiyomi.core.i18n.stringResource
import tachiyomi.domain.backup.model.BackupCategory
import tachiyomi.domain.backup.model.BackupManga
import tachiyomi.domain.backup.model.BackupPreference
import tachiyomi.domain.backup.model.BackupSavedSearch
import tachiyomi.domain.backup.model.BackupSourcePreferences
import tachiyomi.i18n.MR import tachiyomi.i18n.MR
import tachiyomi.i18n.sy.SYMR import tachiyomi.i18n.sy.SYMR
import java.io.File import java.io.File
@ -68,7 +68,7 @@ class BackupRestorer(
} }
private suspend fun restoreFromFile(uri: Uri, options: RestoreOptions) { private suspend fun restoreFromFile(uri: Uri, options: RestoreOptions) {
val backup = BackupUtil.decodeBackup(context, uri) val backup = BackupDecoder(context).decode(uri)
// Store source mapping for error messages // Store source mapping for error messages
val backupMaps = backup.backupSources + backup.backupBrokenSources.map { it.toBackupSource() } val backupMaps = backup.backupSources + backup.backupBrokenSources.map { it.toBackupSource() }

View File

@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.data.backup.restore.restorers package eu.kanade.tachiyomi.data.backup.restore.restorers
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
import tachiyomi.data.DatabaseHandler import tachiyomi.data.DatabaseHandler
import tachiyomi.domain.backup.model.BackupCategory
import tachiyomi.domain.category.interactor.GetCategories import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.library.service.LibraryPreferences
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt

View File

@ -1,18 +1,18 @@
package eu.kanade.tachiyomi.data.backup.restore.restorers package eu.kanade.tachiyomi.data.backup.restore.restorers
import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.interactor.UpdateManga
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
import eu.kanade.tachiyomi.data.backup.models.BackupChapter
import eu.kanade.tachiyomi.data.backup.models.BackupFlatMetadata
import eu.kanade.tachiyomi.data.backup.models.BackupHistory
import eu.kanade.tachiyomi.data.backup.models.BackupManga
import eu.kanade.tachiyomi.data.backup.models.BackupMergedMangaReference
import eu.kanade.tachiyomi.data.backup.models.BackupTracking
import exh.EXHMigrations import exh.EXHMigrations
import tachiyomi.data.DatabaseHandler import tachiyomi.data.DatabaseHandler
import tachiyomi.data.UpdateStrategyColumnAdapter import tachiyomi.data.UpdateStrategyColumnAdapter
import tachiyomi.data.manga.MangaMapper import tachiyomi.data.manga.MangaMapper
import tachiyomi.data.manga.MergedMangaMapper import tachiyomi.data.manga.MergedMangaMapper
import tachiyomi.domain.backup.model.BackupCategory
import tachiyomi.domain.backup.model.BackupChapter
import tachiyomi.domain.backup.model.BackupFlatMetadata
import tachiyomi.domain.backup.model.BackupHistory
import tachiyomi.domain.backup.model.BackupManga
import tachiyomi.domain.backup.model.BackupMergedMangaReference
import tachiyomi.domain.backup.model.BackupTracking
import tachiyomi.domain.category.interactor.GetCategories import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId import tachiyomi.domain.chapter.interactor.GetChaptersByMangaId
import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.Chapter
@ -497,6 +497,27 @@ class MangaRestorer(
mangaJson ?: return mangaJson ?: return
setCustomMangaInfo.set(mangaJson) setCustomMangaInfo.set(mangaJson)
} }
fun BackupManga.getCustomMangaInfo(): CustomMangaInfo? {
if (customTitle != null ||
customArtist != null ||
customAuthor != null ||
customDescription != null ||
customGenre != null ||
customStatus != 0
) {
return CustomMangaInfo(
id = 0L,
title = customTitle,
author = customAuthor,
artist = customArtist,
description = customDescription,
genre = customGenre,
status = customStatus.takeUnless { it == 0 }?.toLong(),
)
}
return null
}
// SY <-- // SY <--
private fun Track.forComparison() = this.copy(id = 0L, mangaId = 0L) private fun Track.forComparison() = this.copy(id = 0L, mangaId = 0L)

View File

@ -2,18 +2,18 @@ package eu.kanade.tachiyomi.data.backup.restore.restorers
import android.content.Context import android.content.Context
import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob import eu.kanade.tachiyomi.data.backup.create.BackupCreateJob
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
import eu.kanade.tachiyomi.data.backup.models.BackupSourcePreferences
import eu.kanade.tachiyomi.data.backup.models.BooleanPreferenceValue
import eu.kanade.tachiyomi.data.backup.models.FloatPreferenceValue
import eu.kanade.tachiyomi.data.backup.models.IntPreferenceValue
import eu.kanade.tachiyomi.data.backup.models.LongPreferenceValue
import eu.kanade.tachiyomi.data.backup.models.StringPreferenceValue
import eu.kanade.tachiyomi.data.backup.models.StringSetPreferenceValue
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.source.sourcePreferences import eu.kanade.tachiyomi.source.sourcePreferences
import tachiyomi.core.preference.AndroidPreferenceStore import tachiyomi.core.preference.AndroidPreferenceStore
import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.preference.PreferenceStore
import tachiyomi.domain.backup.model.BackupPreference
import tachiyomi.domain.backup.model.BackupSourcePreferences
import tachiyomi.domain.backup.model.BooleanPreferenceValue
import tachiyomi.domain.backup.model.FloatPreferenceValue
import tachiyomi.domain.backup.model.IntPreferenceValue
import tachiyomi.domain.backup.model.LongPreferenceValue
import tachiyomi.domain.backup.model.StringPreferenceValue
import tachiyomi.domain.backup.model.StringSetPreferenceValue
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get

View File

@ -1,8 +1,8 @@
package eu.kanade.tachiyomi.data.backup.restore.restorers package eu.kanade.tachiyomi.data.backup.restore.restorers
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
import exh.util.nullIfBlank import exh.util.nullIfBlank
import tachiyomi.data.DatabaseHandler import tachiyomi.data.DatabaseHandler
import tachiyomi.domain.backup.model.BackupSavedSearch
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get

View File

@ -26,6 +26,7 @@ import eu.kanade.tachiyomi.util.storage.CbzCrypto
import exh.eh.EHentaiUpdateHelper import exh.eh.EHentaiUpdateHelper
import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.protobuf.ProtoBuf
import net.zetetic.database.sqlcipher.SupportOpenHelperFactory import net.zetetic.database.sqlcipher.SupportOpenHelperFactory
import nl.adaptivity.xmlutil.XmlDeclMode import nl.adaptivity.xmlutil.XmlDeclMode
import nl.adaptivity.xmlutil.core.XmlVersion import nl.adaptivity.xmlutil.core.XmlVersion
@ -134,6 +135,9 @@ class AppModule(val app: Application) : InjektModule {
xmlVersion = XmlVersion.XML10 xmlVersion = XmlVersion.XML10
} }
} }
addSingletonFactory<ProtoBuf> {
ProtoBuf
}
addSingletonFactory { ChapterCache(app) } addSingletonFactory { ChapterCache(app) }
addSingletonFactory { CoverCache(app) } addSingletonFactory { CoverCache(app) }

View File

@ -7,7 +7,6 @@ import eu.kanade.domain.manga.model.toSManga
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.domain.ui.UiPreferences import eu.kanade.domain.ui.UiPreferences
import eu.kanade.tachiyomi.core.security.SecurityPreferences import eu.kanade.tachiyomi.core.security.SecurityPreferences
import eu.kanade.tachiyomi.data.backup.models.Backup
import eu.kanade.tachiyomi.data.cache.PagePreviewCache import eu.kanade.tachiyomi.data.cache.PagePreviewCache
import eu.kanade.tachiyomi.data.track.TrackerManager import eu.kanade.tachiyomi.data.track.TrackerManager
import eu.kanade.tachiyomi.network.NetworkPreferences import eu.kanade.tachiyomi.network.NetworkPreferences
@ -27,6 +26,7 @@ import kotlinx.coroutines.runBlocking
import kotlinx.serialization.protobuf.schema.ProtoBufSchemaGenerator import kotlinx.serialization.protobuf.schema.ProtoBufSchemaGenerator
import tachiyomi.core.preference.PreferenceStore import tachiyomi.core.preference.PreferenceStore
import tachiyomi.data.DatabaseHandler import tachiyomi.data.DatabaseHandler
import tachiyomi.domain.backup.model.BackupSerializer
import tachiyomi.domain.backup.service.BackupPreferences import tachiyomi.domain.backup.service.BackupPreferences
import tachiyomi.domain.library.service.LibraryPreferences import tachiyomi.domain.library.service.LibraryPreferences
import tachiyomi.domain.manga.interactor.GetAllManga import tachiyomi.domain.manga.interactor.GetAllManga
@ -339,5 +339,5 @@ object DebugFunctions {
runBlocking { handler.await { ehQueries.migrateAllNhentaiToOtherLang(NHentai.otherId, sources) } } runBlocking { handler.await { ehQueries.migrateAllNhentaiToOtherLang(NHentai.otherId, sources) } }
} }
fun exportProtobufScheme() = ProtoBufSchemaGenerator.generateSchemaText(Backup.serializer().descriptor) fun exportProtobufScheme() = ProtoBufSchemaGenerator.generateSchemaText(BackupSerializer.descriptor)
} }

View File

@ -1,6 +1,7 @@
plugins { plugins {
id("com.android.library") id("com.android.library")
kotlin("android") kotlin("android")
kotlin("plugin.serialization")
} }
android { android {
@ -18,6 +19,7 @@ dependencies {
implementation(platform(kotlinx.coroutines.bom)) implementation(platform(kotlinx.coroutines.bom))
implementation(kotlinx.bundles.coroutines) implementation(kotlinx.bundles.coroutines)
implementation(kotlinx.bundles.serialization)
implementation(libs.unifile) implementation(libs.unifile)

View File

@ -1,11 +1,11 @@
package eu.kanade.tachiyomi.data.backup.models package tachiyomi.domain.backup.model
import eu.kanade.tachiyomi.BuildConfig
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.Serializer
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
import java.text.SimpleDateFormat
import java.util.Date @Serializer(forClass = Backup::class)
import java.util.Locale object BackupSerializer
@Serializable @Serializable
data class Backup( data class Backup(
@ -17,14 +17,4 @@ data class Backup(
@ProtoNumber(105) var backupSourcePreferences: List<BackupSourcePreferences> = emptyList(), @ProtoNumber(105) var backupSourcePreferences: List<BackupSourcePreferences> = emptyList(),
// SY specific values // SY specific values
@ProtoNumber(600) var backupSavedSearches: List<BackupSavedSearch> = emptyList(), @ProtoNumber(600) var backupSavedSearches: List<BackupSavedSearch> = emptyList(),
) { )
companion object {
val filenameRegex = """${BuildConfig.APPLICATION_ID}_\d+-\d+-\d+_\d+-\d+.tachibk""".toRegex()
fun getFilename(): String {
val date = SimpleDateFormat("yyyy-MM-dd_HH-mm", Locale.getDefault()).format(Date())
return "${BuildConfig.APPLICATION_ID}_$date.tachibk"
}
}
}

View File

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.data.backup.models package tachiyomi.domain.backup.model
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber

View File

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.data.backup.models package tachiyomi.domain.backup.model
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber

View File

@ -1,8 +1,8 @@
package eu.kanade.tachiyomi.data.backup.models package tachiyomi.domain.backup.model
import eu.kanade.tachiyomi.data.backup.models.metadata.BackupSearchMetadata import tachiyomi.domain.backup.model.metadata.BackupSearchMetadata
import eu.kanade.tachiyomi.data.backup.models.metadata.BackupSearchTag import tachiyomi.domain.backup.model.metadata.BackupSearchTag
import eu.kanade.tachiyomi.data.backup.models.metadata.BackupSearchTitle import tachiyomi.domain.backup.model.metadata.BackupSearchTitle
import exh.metadata.metadata.base.FlatMetadata import exh.metadata.metadata.base.FlatMetadata
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber

View File

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.data.backup.models package tachiyomi.domain.backup.model
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber

View File

@ -1,7 +1,6 @@
package eu.kanade.tachiyomi.data.backup.models package tachiyomi.domain.backup.model
import eu.kanade.tachiyomi.source.model.UpdateStrategy import eu.kanade.tachiyomi.source.model.UpdateStrategy
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
import tachiyomi.domain.manga.model.CustomMangaInfo import tachiyomi.domain.manga.model.CustomMangaInfo
@ -76,66 +75,7 @@ data class BackupManga(
chapterFlags = this@BackupManga.chapterFlags.toLong(), chapterFlags = this@BackupManga.chapterFlags.toLong(),
updateStrategy = this@BackupManga.updateStrategy, updateStrategy = this@BackupManga.updateStrategy,
lastModifiedAt = this@BackupManga.lastModifiedAt, lastModifiedAt = this@BackupManga.lastModifiedAt,
favoriteModifiedAt = this@BackupManga.favoriteModifiedAt,
) )
} }
// SY -->
fun getCustomMangaInfo(): CustomMangaInfo? {
if (customTitle != null ||
customArtist != null ||
customAuthor != null ||
customDescription != null ||
customGenre != null ||
customStatus != 0
) {
return CustomMangaInfo(
id = 0L,
title = customTitle,
author = customAuthor,
artist = customArtist,
description = customDescription,
genre = customGenre,
status = customStatus.takeUnless { it == 0 }?.toLong(),
)
}
return null
}
// SY <--
companion object {
fun copyFrom(manga: Manga /* SY --> */, customMangaInfo: CustomMangaInfo?/* SY <-- */): BackupManga {
return BackupManga(
url = manga.url,
// SY -->
title = manga.ogTitle,
artist = manga.ogArtist,
author = manga.ogAuthor,
description = manga.ogDescription,
genre = manga.ogGenre.orEmpty(),
status = manga.ogStatus.toInt(),
// SY <--
thumbnailUrl = manga.thumbnailUrl,
favorite = manga.favorite,
source = manga.source,
dateAdded = manga.dateAdded,
viewer = (manga.viewerFlags.toInt() and ReadingMode.MASK),
viewer_flags = manga.viewerFlags.toInt(),
chapterFlags = manga.chapterFlags.toInt(),
updateStrategy = manga.updateStrategy,
lastModifiedAt = manga.lastModifiedAt,
favoriteModifiedAt = manga.favoriteModifiedAt,
// SY -->
).also { backupManga ->
customMangaInfo?.let {
backupManga.customTitle = it.title
backupManga.customArtist = it.artist
backupManga.customAuthor = it.author
backupManga.customDescription = it.description
backupManga.customGenre = it.genre
backupManga.customStatus = it.status?.toInt() ?: 0
}
}
// SY <--
}
}
} }

View File

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.data.backup.models package tachiyomi.domain.backup.model
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber

View File

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.data.backup.models package tachiyomi.domain.backup.model
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber

View File

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.data.backup.models package tachiyomi.domain.backup.model
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber

View File

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.data.backup.models package tachiyomi.domain.backup.model
import eu.kanade.tachiyomi.source.Source
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber
@ -8,16 +7,7 @@ import kotlinx.serialization.protobuf.ProtoNumber
data class BackupSource( data class BackupSource(
@ProtoNumber(1) var name: String = "", @ProtoNumber(1) var name: String = "",
@ProtoNumber(2) var sourceId: Long, @ProtoNumber(2) var sourceId: Long,
) { )
companion object {
fun copyFrom(source: Source): BackupSource {
return BackupSource(
name = source.name,
sourceId = source.id,
)
}
}
}
@Serializable @Serializable
data class BrokenBackupSource( data class BrokenBackupSource(

View File

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.data.backup.models package tachiyomi.domain.backup.model
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber import kotlinx.serialization.protobuf.ProtoNumber

View File

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.data.backup.models.metadata package tachiyomi.domain.backup.model.metadata
import exh.metadata.sql.models.SearchMetadata import exh.metadata.sql.models.SearchMetadata
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable

View File

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.data.backup.models.metadata package tachiyomi.domain.backup.model.metadata
import exh.metadata.sql.models.SearchTag import exh.metadata.sql.models.SearchTag
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable

View File

@ -1,4 +1,4 @@
package eu.kanade.tachiyomi.data.backup.models.metadata package tachiyomi.domain.backup.model.metadata
import exh.metadata.sql.models.SearchTitle import exh.metadata.sql.models.SearchTitle
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable