Skip to content

Commit

Permalink
Move backup models to domain module
Browse files Browse the repository at this point in the history
  • Loading branch information
arkon committed Dec 24, 2023
1 parent 1a55912 commit 5908bd1
Show file tree
Hide file tree
Showing 26 changed files with 155 additions and 151 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -123,7 +123,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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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()
Expand All @@ -27,6 +31,6 @@ object BackupUtil {
backupStringSource
}.use { it.readByteArray() }

return backupCreator.parser.decodeFromByteArray(BackupSerializer, backupString)
return parser.decodeFromByteArray(BackupSerializer, backupString)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ 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
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(),
) {
Expand All @@ -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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) :
Expand All @@ -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()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ 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
Expand All @@ -11,45 +12,47 @@ import eu.kanade.tachiyomi.data.backup.create.creators.CategoriesBackupCreator
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.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.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
import okio.gzip
import okio.sink
import tachiyomi.core.i18n.stringResource
import tachiyomi.core.util.system.logcat
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.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.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(),
private val getFavorites: GetFavorites = Injekt.get(),
) {

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 = (
Expand All @@ -58,14 +61,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)
}
Expand All @@ -90,14 +93,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) {
Expand Down Expand Up @@ -132,6 +143,14 @@ class BackupCreator(

return preferenceBackupCreator.backupSourcePreferences()
}
}

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"
}
}
}
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package eu.kanade.tachiyomi.data.backup.create.creators

import eu.kanade.tachiyomi.data.backup.create.BackupCreateFlags
import eu.kanade.tachiyomi.data.backup.models.BackupChapter
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.backupTrackMapper
import eu.kanade.tachiyomi.ui.reader.setting.ReadingMode
import tachiyomi.data.DatabaseHandler
import tachiyomi.domain.backup.model.BackupChapter
import tachiyomi.domain.backup.model.BackupHistory
import tachiyomi.domain.backup.model.BackupManga
import tachiyomi.domain.backup.model.backupChapterMapper
import tachiyomi.domain.backup.model.backupTrackMapper
import tachiyomi.domain.category.interactor.GetCategories
import tachiyomi.domain.history.interactor.GetHistory
import tachiyomi.domain.manga.model.Manga
Expand All @@ -27,7 +28,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()

// Check if user wants chapter information in backup
if (options and BackupCreateFlags.BACKUP_CHAPTER == BackupCreateFlags.BACKUP_CHAPTER) {
Expand Down Expand Up @@ -77,3 +78,24 @@ class MangaBackupCreator(
return mangaObject
}
}

private fun Manga.toBackupManga() =
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,
)
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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,
)

This file was deleted.

Loading

0 comments on commit 5908bd1

Please sign in to comment.