Add chapter lastReadAt to backups as BackupHistory (#1477)
* Add chapter lastReadAt to backups as BackupHistory * MaxOrNull
This commit is contained in:
+37
-21
@@ -34,6 +34,7 @@ import suwayomi.tachidesk.manga.impl.backup.BackupFlags
|
|||||||
import suwayomi.tachidesk.manga.impl.backup.proto.models.Backup
|
import suwayomi.tachidesk.manga.impl.backup.proto.models.Backup
|
||||||
import suwayomi.tachidesk.manga.impl.backup.proto.models.BackupCategory
|
import suwayomi.tachidesk.manga.impl.backup.proto.models.BackupCategory
|
||||||
import suwayomi.tachidesk.manga.impl.backup.proto.models.BackupChapter
|
import suwayomi.tachidesk.manga.impl.backup.proto.models.BackupChapter
|
||||||
|
import suwayomi.tachidesk.manga.impl.backup.proto.models.BackupHistory
|
||||||
import suwayomi.tachidesk.manga.impl.backup.proto.models.BackupManga
|
import suwayomi.tachidesk.manga.impl.backup.proto.models.BackupManga
|
||||||
import suwayomi.tachidesk.manga.impl.backup.proto.models.BackupServerSettings
|
import suwayomi.tachidesk.manga.impl.backup.proto.models.BackupServerSettings
|
||||||
import suwayomi.tachidesk.manga.impl.backup.proto.models.BackupSource
|
import suwayomi.tachidesk.manga.impl.backup.proto.models.BackupSource
|
||||||
@@ -53,8 +54,8 @@ import uy.kohesive.injekt.api.get
|
|||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import kotlin.time.Duration.Companion.days
|
import kotlin.time.Duration.Companion.days
|
||||||
|
import kotlin.time.Duration.Companion.seconds
|
||||||
|
|
||||||
object ProtoBackupExport : ProtoBackupBase() {
|
object ProtoBackupExport : ProtoBackupBase() {
|
||||||
private val logger = KotlinLogging.logger { }
|
private val logger = KotlinLogging.logger { }
|
||||||
@@ -222,7 +223,7 @@ object ProtoBackupExport : ProtoBackupBase() {
|
|||||||
genre = mangaRow[MangaTable.genre]?.split(", ") ?: emptyList(),
|
genre = mangaRow[MangaTable.genre]?.split(", ") ?: emptyList(),
|
||||||
status = MangaStatus.valueOf(mangaRow[MangaTable.status]).value,
|
status = MangaStatus.valueOf(mangaRow[MangaTable.status]).value,
|
||||||
thumbnailUrl = mangaRow[MangaTable.thumbnail_url],
|
thumbnailUrl = mangaRow[MangaTable.thumbnail_url],
|
||||||
dateAdded = TimeUnit.SECONDS.toMillis(mangaRow[MangaTable.inLibraryAt]),
|
dateAdded = mangaRow[MangaTable.inLibraryAt].seconds.inWholeMilliseconds,
|
||||||
viewer = 0, // not supported in Tachidesk
|
viewer = 0, // not supported in Tachidesk
|
||||||
updateStrategy = UpdateStrategy.valueOf(mangaRow[MangaTable.updateStrategy]),
|
updateStrategy = UpdateStrategy.valueOf(mangaRow[MangaTable.updateStrategy]),
|
||||||
)
|
)
|
||||||
@@ -233,7 +234,7 @@ object ProtoBackupExport : ProtoBackupBase() {
|
|||||||
backupManga.meta = Manga.getMangaMetaMap(mangaId)
|
backupManga.meta = Manga.getMangaMetaMap(mangaId)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.includeChapters) {
|
if (flags.includeChapters || flags.includeHistory) {
|
||||||
val chapters =
|
val chapters =
|
||||||
transaction {
|
transaction {
|
||||||
ChapterTable
|
ChapterTable
|
||||||
@@ -244,27 +245,42 @@ object ProtoBackupExport : ProtoBackupBase() {
|
|||||||
ChapterTable.toDataClass(it)
|
ChapterTable.toDataClass(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val chapterToMeta = Chapter.getChaptersMetaMaps(chapters.map { it.id })
|
if (flags.includeChapters) {
|
||||||
|
val chapterToMeta = Chapter.getChaptersMetaMaps(chapters.map { it.id })
|
||||||
|
|
||||||
backupManga.chapters =
|
backupManga.chapters =
|
||||||
chapters.map {
|
chapters.map {
|
||||||
BackupChapter(
|
BackupChapter(
|
||||||
it.url,
|
it.url,
|
||||||
it.name,
|
it.name,
|
||||||
it.scanlator,
|
it.scanlator,
|
||||||
it.read,
|
it.read,
|
||||||
it.bookmarked,
|
it.bookmarked,
|
||||||
it.lastPageRead,
|
it.lastPageRead,
|
||||||
TimeUnit.SECONDS.toMillis(it.fetchedAt),
|
it.fetchedAt.seconds.inWholeMilliseconds,
|
||||||
it.uploadDate,
|
it.uploadDate,
|
||||||
it.chapterNumber,
|
it.chapterNumber,
|
||||||
chapters.size - it.index,
|
chapters.size - it.index,
|
||||||
).apply {
|
).apply {
|
||||||
if (flags.includeClientData) {
|
if (flags.includeClientData) {
|
||||||
this.meta = chapterToMeta[it.id] ?: emptyMap()
|
this.meta = chapterToMeta[it.id] ?: emptyMap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (flags.includeHistory) {
|
||||||
|
backupManga.history =
|
||||||
|
chapters.mapNotNull {
|
||||||
|
if (it.lastReadAt > 0) {
|
||||||
|
BackupHistory(
|
||||||
|
url = it.url,
|
||||||
|
lastRead = it.lastReadAt.seconds.inWholeMilliseconds,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.includeCategories) {
|
if (flags.includeCategories) {
|
||||||
|
|||||||
+10
-3
@@ -61,6 +61,7 @@ import java.io.InputStream
|
|||||||
import java.util.Date
|
import java.util.Date
|
||||||
import java.util.Timer
|
import java.util.Timer
|
||||||
import java.util.TimerTask
|
import java.util.TimerTask
|
||||||
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
import kotlin.time.Duration.Companion.milliseconds
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
import suwayomi.tachidesk.manga.impl.track.Track as Tracker
|
import suwayomi.tachidesk.manga.impl.track.Track as Tracker
|
||||||
@@ -106,7 +107,7 @@ object ProtoBackupImport : ProtoBackupBase() {
|
|||||||
) : BackupRestoreState()
|
) : BackupRestoreState()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val backupRestoreIdToState = mutableMapOf<String, BackupRestoreState>()
|
private val backupRestoreIdToState = ConcurrentHashMap<String, BackupRestoreState>()
|
||||||
|
|
||||||
val notifyFlow = MutableSharedFlow<Unit>(extraBufferCapacity = 1, onBufferOverflow = DROP_OLDEST)
|
val notifyFlow = MutableSharedFlow<Unit>(extraBufferCapacity = 1, onBufferOverflow = DROP_OLDEST)
|
||||||
|
|
||||||
@@ -294,7 +295,6 @@ object ProtoBackupImport : ProtoBackupBase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNUSED_PARAMETER") // TODO: remove
|
|
||||||
private fun restoreMangaData(
|
private fun restoreMangaData(
|
||||||
manga: BackupManga,
|
manga: BackupManga,
|
||||||
chapters: List<BackupChapter>,
|
chapters: List<BackupChapter>,
|
||||||
@@ -368,7 +368,7 @@ object ProtoBackupImport : ProtoBackupBase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// merge chapter data
|
// merge chapter data
|
||||||
restoreMangaChapterData(mangaId, restoreMode, chapters)
|
restoreMangaChapterData(mangaId, restoreMode, chapters, history)
|
||||||
|
|
||||||
// merge categories
|
// merge categories
|
||||||
restoreMangaCategoryData(mangaId, categoryIds)
|
restoreMangaCategoryData(mangaId, categoryIds)
|
||||||
@@ -404,8 +404,10 @@ object ProtoBackupImport : ProtoBackupBase() {
|
|||||||
mangaId: Int,
|
mangaId: Int,
|
||||||
restoreMode: RestoreMode,
|
restoreMode: RestoreMode,
|
||||||
chapters: List<BackupChapter>,
|
chapters: List<BackupChapter>,
|
||||||
|
history: List<BackupHistory>,
|
||||||
) = dbTransaction {
|
) = dbTransaction {
|
||||||
val (chaptersToInsert, chaptersToUpdateToDbChapter) = getMangaChapterToRestoreInfo(mangaId, restoreMode, chapters)
|
val (chaptersToInsert, chaptersToUpdateToDbChapter) = getMangaChapterToRestoreInfo(mangaId, restoreMode, chapters)
|
||||||
|
val historyByChapter = history.groupBy({ it.url }, { it.lastRead })
|
||||||
|
|
||||||
val insertedChapterIds =
|
val insertedChapterIds =
|
||||||
ChapterTable
|
ChapterTable
|
||||||
@@ -428,6 +430,8 @@ object ProtoBackupImport : ProtoBackupBase() {
|
|||||||
this[ChapterTable.isBookmarked] = chapter.bookmark
|
this[ChapterTable.isBookmarked] = chapter.bookmark
|
||||||
|
|
||||||
this[ChapterTable.fetchedAt] = chapter.dateFetch.milliseconds.inWholeSeconds
|
this[ChapterTable.fetchedAt] = chapter.dateFetch.milliseconds.inWholeSeconds
|
||||||
|
|
||||||
|
this[ChapterTable.lastReadAt] = historyByChapter[chapter.url]?.maxOrNull()?.milliseconds?.inWholeSeconds ?: 0
|
||||||
}.map { it[ChapterTable.id].value }
|
}.map { it[ChapterTable.id].value }
|
||||||
|
|
||||||
if (chaptersToUpdateToDbChapter.isNotEmpty()) {
|
if (chaptersToUpdateToDbChapter.isNotEmpty()) {
|
||||||
@@ -438,6 +442,9 @@ object ProtoBackupImport : ProtoBackupBase() {
|
|||||||
this[ChapterTable.lastPageRead] =
|
this[ChapterTable.lastPageRead] =
|
||||||
max(backupChapter.lastPageRead, dbChapter[ChapterTable.lastPageRead]).coerceAtLeast(0)
|
max(backupChapter.lastPageRead, dbChapter[ChapterTable.lastPageRead]).coerceAtLeast(0)
|
||||||
this[ChapterTable.isBookmarked] = backupChapter.bookmark || dbChapter[ChapterTable.isBookmarked]
|
this[ChapterTable.isBookmarked] = backupChapter.bookmark || dbChapter[ChapterTable.isBookmarked]
|
||||||
|
this[ChapterTable.lastReadAt] =
|
||||||
|
(historyByChapter[backupChapter.url]?.maxOrNull()?.milliseconds?.inWholeSeconds ?: 0)
|
||||||
|
.coerceAtLeast(dbChapter[ChapterTable.lastReadAt])
|
||||||
}
|
}
|
||||||
execute(this@dbTransaction)
|
execute(this@dbTransaction)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user