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
@@ -31,7 +31,7 @@ import eu.kanade.presentation.components.WarningBanner
import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags
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.toast
import kotlinx.collections.immutable.PersistentSet
@@ -124,7 +124,7 @@ class CreateBackupScreen : Screen() {
onClick = {
if (!BackupCreateJob.isManualJobRunning(context)) {
try {
chooseBackupDir.launch(Backup.getFilename())
chooseBackupDir.launch(BackupCreator.getFilename())
} catch (e: ActivityNotFoundException) {
context.toast(MR.strings.file_picker_error)
}
@@ -154,7 +154,7 @@ class RestoreBackupScreen : Screen() {
}
val results = try {
BackupFileValidator().validate(context, it)
BackupFileValidator(context).validate(it)
} catch (e: Exception) {
model.setError(InvalidRestore(it, e.message.toString()))
return@rememberLauncherForActivityResult
@@ -17,10 +17,10 @@ import cafe.adriel.voyager.navigator.currentOrThrow
import eu.kanade.presentation.components.AppBar
import eu.kanade.presentation.components.AppBarActions
import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.data.backup.models.Backup
import eu.kanade.tachiyomi.util.system.copyToClipboard
import kotlinx.collections.immutable.persistentListOf
import kotlinx.serialization.protobuf.schema.ProtoBufSchemaGenerator
import tachiyomi.domain.backup.model.Backup
import tachiyomi.i18n.MR
import tachiyomi.presentation.core.components.material.Scaffold
import tachiyomi.presentation.core.i18n.stringResource
@@ -1,21 +1,25 @@
package eu.kanade.tachiyomi.util
package eu.kanade.tachiyomi.data.backup
import android.content.Context
import android.net.Uri
import eu.kanade.tachiyomi.data.backup.create.BackupCreator
import eu.kanade.tachiyomi.data.backup.models.Backup
import eu.kanade.tachiyomi.data.backup.models.BackupSerializer
import kotlinx.serialization.protobuf.ProtoBuf
import okio.buffer
import okio.gzip
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.
*/
fun decodeBackup(context: Context, uri: Uri): Backup {
val backupCreator = BackupCreator(context)
fun decode(uri: Uri): Backup {
val backupStringSource = context.contentResolver.openInputStream(uri)!!.source().buffer()
val peeked = backupStringSource.peek()
@@ -27,6 +31,6 @@ object BackupUtil {
backupStringSource
}.use { it.readByteArray() }
return backupCreator.parser.decodeFromByteArray(BackupSerializer, backupString)
return parser.decodeFromByteArray(BackupSerializer, backupString)
}
}
@@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.data.backup
import android.content.Context
import android.net.Uri
import eu.kanade.tachiyomi.data.track.TrackerManager
import eu.kanade.tachiyomi.util.BackupUtil
import tachiyomi.core.i18n.stringResource
import tachiyomi.domain.source.service.SourceManager
import tachiyomi.i18n.MR
@@ -11,6 +10,8 @@ import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
class BackupFileValidator(
private val context: Context,
private val sourceManager: SourceManager = Injekt.get(),
private val trackerManager: TrackerManager = Injekt.get(),
) {
@@ -21,9 +22,9 @@ class BackupFileValidator(
* @throws Exception if manga cannot be found.
* @return List of missing sources or missing trackers.
*/
fun validate(context: Context, uri: Uri): Results {
fun validate(uri: Uri): Results {
val backup = try {
BackupUtil.decodeBackup(context, uri)
BackupDecoder(context).decode(uri)
} catch (e: Exception) {
throw IllegalStateException(e)
}
@@ -29,7 +29,6 @@ import tachiyomi.domain.backup.service.BackupPreferences
import tachiyomi.domain.storage.service.StorageManager
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.time.Instant
import java.util.concurrent.TimeUnit
class BackupCreateJob(private val context: Context, workerParams: WorkerParameters) :
@@ -49,13 +48,10 @@ class BackupCreateJob(private val context: Context, workerParams: WorkerParamete
setForegroundSafely()
val flags = inputData.getInt(BACKUP_FLAGS_KEY, BackupCreateFlags.AutomaticDefaults)
val backupPreferences = Injekt.get<BackupPreferences>()
return try {
val location = BackupCreator(context).createBackup(uri, flags, isAutoBackup)
if (isAutoBackup) {
backupPreferences.lastAutoBackupTimestamp().set(Instant.now().toEpochMilli())
} else {
val location = BackupCreator(context, isAutoBackup).backup(uri, flags)
if (!isAutoBackup) {
notifier.showBackupComplete(UniFile.fromUri(context, location.toUri())!!)
}
Result.success()
@@ -3,10 +3,10 @@ package eu.kanade.tachiyomi.data.backup.create
import android.content.Context
import android.net.Uri
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.BuildConfig
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_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_SOURCE_PREFS
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.SavedSearchBackupCreator
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 logcat.LogPriority
import okio.buffer
@@ -31,40 +23,47 @@ import tachiyomi.core.i18n.stringResource
import tachiyomi.core.util.system.logcat
import tachiyomi.data.DatabaseHandler
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.GetFlatMetadataById
import tachiyomi.domain.manga.interactor.GetMergedManga
import tachiyomi.domain.manga.model.Manga
import tachiyomi.i18n.MR
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.FileOutputStream
import java.text.SimpleDateFormat
import java.time.Instant
import java.util.Date
import java.util.Locale
class BackupCreator(
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 mangaBackupCreator: MangaBackupCreator = MangaBackupCreator(),
private val preferenceBackupCreator: PreferenceBackupCreator = PreferenceBackupCreator(),
private val sourcesBackupCreator: SourcesBackupCreator = SourcesBackupCreator(),
// SY -->
private val savedSearchBackupCreator: SavedSearchBackupCreator = SavedSearchBackupCreator(),
// SY <--
private val getFavorites: GetFavorites = Injekt.get(),
// SY -->
private val getMergedManga: GetMergedManga = Injekt.get(),
private val handler: DatabaseHandler = Injekt.get()
// SY <--
) {
internal val parser = ProtoBuf
/**
* 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 {
suspend fun backup(uri: Uri, flags: Int): String {
var file: UniFile? = null
try {
file = (
@@ -73,14 +72,14 @@ class BackupCreator(
val dir = UniFile.fromUri(context, uri)
// Delete older backups
dir?.listFiles { _, filename -> Backup.filenameRegex.matches(filename) }
dir?.listFiles { _, filename -> FILENAME_REGEX.matches(filename) }
.orEmpty()
.sortedByDescending { it.name }
.drop(MAX_AUTO_BACKUPS - 1)
.forEach { it.delete() }
// Create new file to place backup
dir?.createFile(Backup.getFilename())
dir?.createFile(BackupCreator.getFilename())
} else {
UniFile.fromUri(context, uri)
}
@@ -113,14 +112,22 @@ class BackupCreator(
throw IllegalStateException(context.stringResource(MR.strings.empty_backup_error))
}
file.openOutputStream().also {
// Force overwrite old file
(it as? FileOutputStream)?.channel?.truncate(0)
}.sink().gzip().buffer().use { it.write(byteArray) }
file.openOutputStream()
.also {
// Force overwrite old file
(it as? FileOutputStream)?.channel?.truncate(0)
}
.sink().gzip().buffer().use {
it.write(byteArray)
}
val fileUri = file.uri
// 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()
} catch (e: Exception) {
@@ -161,6 +168,14 @@ class BackupCreator(
return savedSearchBackupCreator.backupSavedSearches()
}
// 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"
}
}
}
@@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.data.backup.create.creators
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
import eu.kanade.tachiyomi.data.backup.models.backupCategoryMapper
import tachiyomi.domain.backup.model.BackupCategory
import tachiyomi.domain.backup.model.backupCategoryMapper
import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.category.model.Category
import uy.kohesive.injekt.Injekt
@@ -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.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.ui.reader.setting.ReadingMode
import exh.source.MERGED_SOURCE_ID
import exh.source.getMainSource
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.history.interactor.GetHistory
import tachiyomi.domain.manga.interactor.GetCustomMangaInfo
import tachiyomi.domain.manga.interactor.GetFlatMetadataById
import tachiyomi.domain.manga.model.CustomMangaInfo
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.source.service.SourceManager
import uy.kohesive.injekt.Injekt
@@ -41,8 +43,7 @@ class MangaBackupCreator(
private suspend fun backupManga(manga: Manga, options: Int): BackupManga {
// Entry for this manga
val mangaObject = BackupManga.copyFrom(
manga,
val mangaObject = manga.toBackupManga(
// SY -->
if (options and BACKUP_CUSTOM_INFO == BACKUP_CUSTOM_INFO) {
getCustomMangaInfo.get(manga.id)
@@ -114,3 +115,35 @@ class MangaBackupCreator(
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 <--
@@ -1,18 +1,18 @@
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.preferenceKey
import eu.kanade.tachiyomi.source.sourcePreferences
import tachiyomi.core.preference.Preference
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 uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@@ -1,8 +1,8 @@
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.domain.backup.model.BackupSavedSearch
import tachiyomi.domain.backup.model.backupSavedSearchMapper
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@@ -1,6 +1,7 @@
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.source.service.SourceManager
import uy.kohesive.injekt.Injekt
@@ -16,7 +17,13 @@ class SourcesBackupCreator(
.map(Manga::source)
.distinct()
.map(sourceManager::getOrStub)
.map(BackupSource::copyFrom)
.map { it.toBackupSource() }
.toList()
}
}
private fun Source.toBackupSource() =
BackupSource(
name = this.name,
sourceId = this.id,
)
@@ -1,30 +0,0 @@
package eu.kanade.tachiyomi.data.backup.models
import eu.kanade.tachiyomi.BuildConfig
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@Serializable
data class Backup(
@ProtoNumber(1) val backupManga: List<BackupManga>,
@ProtoNumber(2) var backupCategories: List<BackupCategory> = emptyList(),
@ProtoNumber(100) var backupBrokenSources: List<BrokenBackupSource> = emptyList(),
@ProtoNumber(101) var backupSources: List<BackupSource> = emptyList(),
@ProtoNumber(104) var backupPreferences: List<BackupPreference> = emptyList(),
@ProtoNumber(105) var backupSourcePreferences: List<BackupSourcePreferences> = emptyList(),
// SY specific values
@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"
}
}
}
@@ -1,31 +0,0 @@
package eu.kanade.tachiyomi.data.backup.models
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import tachiyomi.domain.category.model.Category
@Serializable
class BackupCategory(
@ProtoNumber(1) var name: String,
@ProtoNumber(2) var order: Long = 0,
// @ProtoNumber(3) val updateInterval: Int = 0, 1.x value not used in 0.x
@ProtoNumber(100) var flags: Long = 0,
// SY specific values
/*@ProtoNumber(600) var mangaOrder: List<Long> = emptyList(),*/
) {
fun toCategory(id: Long) = Category(
id = id,
name = this@BackupCategory.name,
flags = this@BackupCategory.flags,
order = this@BackupCategory.order,
/*mangaOrder = this@BackupCategory.mangaOrder*/
)
}
val backupCategoryMapper = { category: Category ->
BackupCategory(
name = category.name,
order = category.order,
flags = category.flags,
)
}
@@ -1,70 +0,0 @@
package eu.kanade.tachiyomi.data.backup.models
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import tachiyomi.domain.chapter.model.Chapter
@Serializable
data class BackupChapter(
// in 1.x some of these values have different names
// url is called key in 1.x
@ProtoNumber(1) var url: String,
@ProtoNumber(2) var name: String,
@ProtoNumber(3) var scanlator: String? = null,
@ProtoNumber(4) var read: Boolean = false,
@ProtoNumber(5) var bookmark: Boolean = false,
// lastPageRead is called progress in 1.x
@ProtoNumber(6) var lastPageRead: Long = 0,
@ProtoNumber(7) var dateFetch: Long = 0,
@ProtoNumber(8) var dateUpload: Long = 0,
// chapterNumber is called number is 1.x
@ProtoNumber(9) var chapterNumber: Float = 0F,
@ProtoNumber(10) var sourceOrder: Long = 0,
@ProtoNumber(11) var lastModifiedAt: Long = 0,
) {
fun toChapterImpl(): Chapter {
return Chapter.create().copy(
url = this@BackupChapter.url,
name = this@BackupChapter.name,
chapterNumber = this@BackupChapter.chapterNumber.toDouble(),
scanlator = this@BackupChapter.scanlator,
read = this@BackupChapter.read,
bookmark = this@BackupChapter.bookmark,
lastPageRead = this@BackupChapter.lastPageRead,
dateFetch = this@BackupChapter.dateFetch,
dateUpload = this@BackupChapter.dateUpload,
sourceOrder = this@BackupChapter.sourceOrder,
lastModifiedAt = this@BackupChapter.lastModifiedAt,
)
}
}
val backupChapterMapper =
{ _: Long,
_: Long,
url: String,
name: String,
scanlator: String?,
read: Boolean,
bookmark: Boolean,
lastPageRead: Long,
chapterNumber: Double,
source_order: Long,
dateFetch: Long,
dateUpload: Long,
lastModifiedAt: Long,
->
BackupChapter(
url = url,
name = name,
chapterNumber = chapterNumber.toFloat(),
scanlator = scanlator,
read = read,
bookmark = bookmark,
lastPageRead = lastPageRead,
dateFetch = dateFetch,
dateUpload = dateUpload,
sourceOrder = source_order,
lastModifiedAt = lastModifiedAt,
)
}
@@ -1,33 +0,0 @@
package eu.kanade.tachiyomi.data.backup.models
import eu.kanade.tachiyomi.data.backup.models.metadata.BackupSearchMetadata
import eu.kanade.tachiyomi.data.backup.models.metadata.BackupSearchTag
import eu.kanade.tachiyomi.data.backup.models.metadata.BackupSearchTitle
import exh.metadata.metadata.base.FlatMetadata
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class BackupFlatMetadata(
@ProtoNumber(1) var searchMetadata: BackupSearchMetadata,
@ProtoNumber(2) var searchTags: List<BackupSearchTag> = emptyList(),
@ProtoNumber(3) var searchTitles: List<BackupSearchTitle> = emptyList(),
) {
fun getFlatMetadata(mangaId: Long): FlatMetadata {
return FlatMetadata(
metadata = searchMetadata.getSearchMetadata(mangaId),
tags = searchTags.map { it.getSearchTag(mangaId) },
titles = searchTitles.map { it.getSearchTitle(mangaId) },
)
}
companion object {
fun copyFrom(flatMetadata: FlatMetadata): BackupFlatMetadata {
return BackupFlatMetadata(
searchMetadata = BackupSearchMetadata.copyFrom(flatMetadata.metadata),
searchTags = flatMetadata.tags.map { BackupSearchTag.copyFrom(it) },
searchTitles = flatMetadata.titles.map { BackupSearchTitle.copyFrom(it) },
)
}
}
}
@@ -1,32 +0,0 @@
package eu.kanade.tachiyomi.data.backup.models
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import tachiyomi.domain.history.model.History
import java.util.Date
@Serializable
data class BackupHistory(
@ProtoNumber(1) var url: String,
@ProtoNumber(2) var lastRead: Long,
@ProtoNumber(3) var readDuration: Long = 0,
) {
fun getHistoryImpl(): History {
return History.create().copy(
readAt = Date(lastRead),
readDuration = readDuration,
)
}
}
@Deprecated("Replaced with BackupHistory. This is retained for legacy reasons.")
@Serializable
data class BrokenBackupHistory(
@ProtoNumber(0) var url: String,
@ProtoNumber(1) var lastRead: Long,
@ProtoNumber(2) var readDuration: Long = 0,
) {
fun toBackupHistory(): BackupHistory {
return BackupHistory(url, lastRead, readDuration)
}
}
@@ -1,141 +0,0 @@
package eu.kanade.tachiyomi.data.backup.models
import eu.kanade.tachiyomi.source.model.UpdateStrategy
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import tachiyomi.domain.manga.model.CustomMangaInfo
import tachiyomi.domain.manga.model.Manga
@Suppress("DEPRECATION")
@Serializable
data class BackupManga(
// in 1.x some of these values have different names
@ProtoNumber(1) var source: Long,
// url is called key in 1.x
@ProtoNumber(2) var url: String,
@ProtoNumber(3) var title: String = "",
@ProtoNumber(4) var artist: String? = null,
@ProtoNumber(5) var author: String? = null,
@ProtoNumber(6) var description: String? = null,
@ProtoNumber(7) var genre: List<String> = emptyList(),
@ProtoNumber(8) var status: Int = 0,
// thumbnailUrl is called cover in 1.x
@ProtoNumber(9) var thumbnailUrl: String? = null,
// @ProtoNumber(10) val customCover: String = "", 1.x value, not used in 0.x
// @ProtoNumber(11) val lastUpdate: Long = 0, 1.x value, not used in 0.x
// @ProtoNumber(12) val lastInit: Long = 0, 1.x value, not used in 0.x
@ProtoNumber(13) var dateAdded: Long = 0,
@ProtoNumber(14) var viewer: Int = 0, // Replaced by viewer_flags
// @ProtoNumber(15) val flags: Int = 0, 1.x value, not used in 0.x
@ProtoNumber(16) var chapters: List<BackupChapter> = emptyList(),
@ProtoNumber(17) var categories: List<Long> = emptyList(),
@ProtoNumber(18) var tracking: List<BackupTracking> = emptyList(),
// Bump by 100 for values that are not saved/implemented in 1.x but are used in 0.x
@ProtoNumber(100) var favorite: Boolean = true,
@ProtoNumber(101) var chapterFlags: Int = 0,
@ProtoNumber(102) var brokenHistory: List<BrokenBackupHistory> = emptyList(),
@ProtoNumber(103) var viewer_flags: Int? = null,
@ProtoNumber(104) var history: List<BackupHistory> = emptyList(),
@ProtoNumber(105) var updateStrategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE,
@ProtoNumber(106) var lastModifiedAt: Long = 0,
@ProtoNumber(107) var favoriteModifiedAt: Long? = null,
// SY specific values
@ProtoNumber(600) var mergedMangaReferences: List<BackupMergedMangaReference> = emptyList(),
@ProtoNumber(601) var flatMetadata: BackupFlatMetadata? = null,
@ProtoNumber(602) var customStatus: Int = 0,
// J2K specific values
@ProtoNumber(800) var customTitle: String? = null,
@ProtoNumber(801) var customArtist: String? = null,
@ProtoNumber(802) var customAuthor: String? = null,
// skipping 803 due to using duplicate value in previous builds
@ProtoNumber(804) var customDescription: String? = null,
@ProtoNumber(805) var customGenre: List<String>? = null,
// Neko specific values
@ProtoNumber(901) var filtered_scanlators: String? = null,
) {
fun getMangaImpl(): Manga {
return Manga.create().copy(
url = this@BackupManga.url,
// SY -->
ogTitle = this@BackupManga.title,
ogArtist = this@BackupManga.artist,
ogAuthor = this@BackupManga.author,
ogDescription = this@BackupManga.description,
ogGenre = this@BackupManga.genre,
ogStatus = this@BackupManga.status.toLong(),
// SY <--
thumbnailUrl = this@BackupManga.thumbnailUrl,
favorite = this@BackupManga.favorite,
source = this@BackupManga.source,
dateAdded = this@BackupManga.dateAdded,
viewerFlags = (this@BackupManga.viewer_flags ?: this@BackupManga.viewer).toLong(),
chapterFlags = this@BackupManga.chapterFlags.toLong(),
updateStrategy = this@BackupManga.updateStrategy,
lastModifiedAt = this@BackupManga.lastModifiedAt,
)
}
// 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 <--
}
}
}
@@ -1,61 +0,0 @@
package eu.kanade.tachiyomi.data.backup.models
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import tachiyomi.domain.manga.model.MergedMangaReference
/*
* SY merged manga backup class
*/
@Serializable
data class BackupMergedMangaReference(
@ProtoNumber(1) var isInfoManga: Boolean,
@ProtoNumber(2) var getChapterUpdates: Boolean,
@ProtoNumber(3) var chapterSortMode: Int,
@ProtoNumber(4) var chapterPriority: Int,
@ProtoNumber(5) var downloadChapters: Boolean,
@ProtoNumber(6) var mergeUrl: String,
@ProtoNumber(7) var mangaUrl: String,
@ProtoNumber(8) var mangaSourceId: Long,
) {
fun getMergedMangaReference(): MergedMangaReference {
return MergedMangaReference(
isInfoManga = isInfoManga,
getChapterUpdates = getChapterUpdates,
chapterSortMode = chapterSortMode,
chapterPriority = chapterPriority,
downloadChapters = downloadChapters,
mergeUrl = mergeUrl,
mangaUrl = mangaUrl,
mangaSourceId = mangaSourceId,
mergeId = null,
mangaId = null,
id = -1,
)
}
}
val backupMergedMangaReferenceMapper =
{ _: Long,
isInfoManga: Boolean,
getChapterUpdates: Boolean,
chapterSortMode: Long,
chapterPriority: Long,
downloadChapters: Boolean,
_: Long,
mergeUrl: String,
_: Long?,
mangaUrl: String,
mangaSourceId: Long,
->
BackupMergedMangaReference(
isInfoManga = isInfoManga,
getChapterUpdates = getChapterUpdates,
chapterSortMode = chapterSortMode.toInt(),
chapterPriority = chapterPriority.toInt(),
downloadChapters = downloadChapters,
mergeUrl = mergeUrl,
mangaUrl = mangaUrl,
mangaSourceId = mangaSourceId,
)
}
@@ -1,37 +0,0 @@
package eu.kanade.tachiyomi.data.backup.models
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class BackupPreference(
@ProtoNumber(1) val key: String,
@ProtoNumber(2) val value: PreferenceValue,
)
@Serializable
data class BackupSourcePreferences(
@ProtoNumber(1) val sourceKey: String,
@ProtoNumber(2) val prefs: List<BackupPreference>,
)
@Serializable
sealed class PreferenceValue
@Serializable
data class IntPreferenceValue(val value: Int) : PreferenceValue()
@Serializable
data class LongPreferenceValue(val value: Long) : PreferenceValue()
@Serializable
data class FloatPreferenceValue(val value: Float) : PreferenceValue()
@Serializable
data class StringPreferenceValue(val value: String) : PreferenceValue()
@Serializable
data class BooleanPreferenceValue(val value: Boolean) : PreferenceValue()
@Serializable
data class StringSetPreferenceValue(val value: Set<String>) : PreferenceValue()
@@ -1,25 +0,0 @@
package eu.kanade.tachiyomi.data.backup.models
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
/*
* SY saved searches class
*/
@Serializable
data class BackupSavedSearch(
@ProtoNumber(1) val name: String,
@ProtoNumber(2) val query: String = "",
@ProtoNumber(3) val filterList: String = "",
@ProtoNumber(4) val source: Long = 0,
)
val backupSavedSearchMapper =
{ _: Long, source: Long, name: String, query: String?, filtersJson: String? ->
BackupSavedSearch(
source = source,
name = name,
query = query.orEmpty(),
filterList = filtersJson ?: "[]",
)
}
@@ -1,6 +0,0 @@
package eu.kanade.tachiyomi.data.backup.models
import kotlinx.serialization.Serializer
@Serializer(forClass = Backup::class)
object BackupSerializer
@@ -1,28 +0,0 @@
package eu.kanade.tachiyomi.data.backup.models
import eu.kanade.tachiyomi.source.Source
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class BackupSource(
@ProtoNumber(1) var name: String = "",
@ProtoNumber(2) var sourceId: Long,
) {
companion object {
fun copyFrom(source: Source): BackupSource {
return BackupSource(
name = source.name,
sourceId = source.id,
)
}
}
}
@Serializable
data class BrokenBackupSource(
@ProtoNumber(0) var name: String = "",
@ProtoNumber(1) var sourceId: Long,
) {
fun toBackupSource() = BackupSource(name, sourceId)
}
@@ -1,72 +0,0 @@
package eu.kanade.tachiyomi.data.backup.models
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import tachiyomi.domain.track.model.Track
@Serializable
data class BackupTracking(
// in 1.x some of these values have different types or names
// syncId is called siteId in 1,x
@ProtoNumber(1) var syncId: Int,
// LibraryId is not null in 1.x
@ProtoNumber(2) var libraryId: Long,
@Deprecated("Use mediaId instead", level = DeprecationLevel.WARNING)
@ProtoNumber(3)
var mediaIdInt: Int = 0,
// trackingUrl is called mediaUrl in 1.x
@ProtoNumber(4) var trackingUrl: String = "",
@ProtoNumber(5) var title: String = "",
// lastChapterRead is called last read, and it has been changed to a float in 1.x
@ProtoNumber(6) var lastChapterRead: Float = 0F,
@ProtoNumber(7) var totalChapters: Int = 0,
@ProtoNumber(8) var score: Float = 0F,
@ProtoNumber(9) var status: Int = 0,
// startedReadingDate is called startReadTime in 1.x
@ProtoNumber(10) var startedReadingDate: Long = 0,
// finishedReadingDate is called endReadTime in 1.x
@ProtoNumber(11) var finishedReadingDate: Long = 0,
@ProtoNumber(100) var mediaId: Long = 0,
) {
@Suppress("DEPRECATION")
fun getTrackImpl(): Track {
return Track(
id = -1,
mangaId = -1,
syncId = this@BackupTracking.syncId.toLong(),
remoteId = if (this@BackupTracking.mediaIdInt != 0) {
this@BackupTracking.mediaIdInt.toLong()
} else {
this@BackupTracking.mediaId
},
libraryId = this@BackupTracking.libraryId,
title = this@BackupTracking.title,
lastChapterRead = this@BackupTracking.lastChapterRead.toDouble(),
totalChapters = this@BackupTracking.totalChapters.toLong(),
score = this@BackupTracking.score.toDouble(),
status = this@BackupTracking.status.toLong(),
startDate = this@BackupTracking.startedReadingDate,
finishDate = this@BackupTracking.finishedReadingDate,
remoteUrl = this@BackupTracking.trackingUrl,
)
}
}
val backupTrackMapper = {
_: Long, _: Long, syncId: Long, mediaId: Long, libraryId: Long?, title: String, lastChapterRead: Double, totalChapters: Long, status: Long, score: Double, remoteUrl: String, startDate: Long, finishDate: Long ->
BackupTracking(
syncId = syncId.toInt(),
mediaId = mediaId,
// forced not null so its compatible with 1.x backup system
libraryId = libraryId ?: 0,
title = title,
lastChapterRead = lastChapterRead.toFloat(),
totalChapters = totalChapters.toInt(),
score = score.toFloat(),
status = status.toInt(),
startedReadingDate = startDate,
finishedReadingDate = finishDate,
trackingUrl = remoteUrl,
)
}
@@ -1,34 +0,0 @@
package eu.kanade.tachiyomi.data.backup.models.metadata
import exh.metadata.sql.models.SearchMetadata
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class BackupSearchMetadata(
@ProtoNumber(1) var uploader: String? = null,
@ProtoNumber(2) var extra: String,
@ProtoNumber(3) var indexedExtra: String? = null,
@ProtoNumber(4) var extraVersion: Int,
) {
fun getSearchMetadata(mangaId: Long): SearchMetadata {
return SearchMetadata(
mangaId = mangaId,
uploader = uploader,
extra = extra,
indexedExtra = indexedExtra,
extraVersion = extraVersion,
)
}
companion object {
fun copyFrom(searchMetadata: SearchMetadata): BackupSearchMetadata {
return BackupSearchMetadata(
uploader = searchMetadata.uploader,
extra = searchMetadata.extra,
indexedExtra = searchMetadata.indexedExtra,
extraVersion = searchMetadata.extraVersion,
)
}
}
}
@@ -1,32 +0,0 @@
package eu.kanade.tachiyomi.data.backup.models.metadata
import exh.metadata.sql.models.SearchTag
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class BackupSearchTag(
@ProtoNumber(1) var namespace: String? = null,
@ProtoNumber(2) var name: String,
@ProtoNumber(3) var type: Int,
) {
fun getSearchTag(mangaId: Long): SearchTag {
return SearchTag(
id = null,
mangaId = mangaId,
namespace = namespace,
name = name,
type = type,
)
}
companion object {
fun copyFrom(searchTag: SearchTag): BackupSearchTag {
return BackupSearchTag(
namespace = searchTag.namespace,
name = searchTag.name,
type = searchTag.type,
)
}
}
}
@@ -1,29 +0,0 @@
package eu.kanade.tachiyomi.data.backup.models.metadata
import exh.metadata.sql.models.SearchTitle
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
@Serializable
data class BackupSearchTitle(
@ProtoNumber(1) var title: String,
@ProtoNumber(2) var type: Int,
) {
fun getSearchTitle(mangaId: Long): SearchTitle {
return SearchTitle(
id = null,
mangaId = mangaId,
title = title,
type = type,
)
}
companion object {
fun copyFrom(searchTitle: SearchTitle): BackupSearchTitle {
return BackupSearchTitle(
title = searchTitle.title,
type = searchTitle.type,
)
}
}
}
@@ -2,17 +2,12 @@ package eu.kanade.tachiyomi.data.backup.restore
import android.content.Context
import android.net.Uri
import eu.kanade.tachiyomi.data.backup.BackupDecoder
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.MangaRestorer
import eu.kanade.tachiyomi.data.backup.restore.restorers.PreferenceRestorer
import eu.kanade.tachiyomi.data.backup.restore.restorers.SavedSearchRestorer
import eu.kanade.tachiyomi.util.BackupUtil
import eu.kanade.tachiyomi.util.system.createFileInCacheDir
import exh.source.MERGED_SOURCE_ID
import kotlinx.coroutines.CoroutineScope
@@ -20,6 +15,11 @@ import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.launch
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.sy.SYMR
import java.io.File
@@ -68,7 +68,7 @@ class BackupRestorer(
}
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
val backupMaps = backup.backupSources + backup.backupBrokenSources.map { it.toBackupSource() }
@@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.data.backup.restore.restorers
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
import tachiyomi.data.DatabaseHandler
import tachiyomi.domain.backup.model.BackupCategory
import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.library.service.LibraryPreferences
import uy.kohesive.injekt.Injekt
@@ -1,18 +1,18 @@
package eu.kanade.tachiyomi.data.backup.restore.restorers
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 tachiyomi.data.DatabaseHandler
import tachiyomi.data.UpdateStrategyColumnAdapter
import tachiyomi.data.manga.MangaMapper
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.chapter.interactor.GetChaptersByMangaId
import tachiyomi.domain.chapter.model.Chapter
@@ -497,6 +497,27 @@ class MangaRestorer(
mangaJson ?: return
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 <--
private fun Track.forComparison() = this.copy(id = 0L, mangaId = 0L)
@@ -2,18 +2,18 @@ package eu.kanade.tachiyomi.data.backup.restore.restorers
import android.content.Context
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.source.sourcePreferences
import tachiyomi.core.preference.AndroidPreferenceStore
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.api.get
@@ -1,8 +1,8 @@
package eu.kanade.tachiyomi.data.backup.restore.restorers
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
import exh.util.nullIfBlank
import tachiyomi.data.DatabaseHandler
import tachiyomi.domain.backup.model.BackupSavedSearch
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@@ -26,6 +26,7 @@ import eu.kanade.tachiyomi.util.storage.CbzCrypto
import exh.eh.EHentaiUpdateHelper
import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory
import kotlinx.serialization.json.Json
import kotlinx.serialization.protobuf.ProtoBuf
import net.zetetic.database.sqlcipher.SupportOpenHelperFactory
import nl.adaptivity.xmlutil.XmlDeclMode
import nl.adaptivity.xmlutil.core.XmlVersion
@@ -134,6 +135,9 @@ class AppModule(val app: Application) : InjektModule {
xmlVersion = XmlVersion.XML10
}
}
addSingletonFactory<ProtoBuf> {
ProtoBuf
}
addSingletonFactory { ChapterCache(app) }
addSingletonFactory { CoverCache(app) }