Migrate things to use newer data models (#9239)

* Remove old database models from Coil

* Remove old database models from TrackInfoDialogHome

* Remove old database models from Backup Manager

(cherry picked from commit dfdb688b437c38954b1072b7a1df15921a437868)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestorer.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/backup/models/BackupManga.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/database/models/Manga.kt
#	app/src/main/java/eu/kanade/tachiyomi/data/database/models/MangaImpl.kt
#	app/src/main/java/eu/kanade/tachiyomi/source/model/SMangaExtensions.kt
#	app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaScreenModel.kt
This commit is contained in:
Andreas 2023-03-19 18:11:58 +01:00 committed by Jobobby04
parent 95f770b39e
commit 0f3bb9f7d7
20 changed files with 276 additions and 482 deletions

View File

@ -2,6 +2,7 @@ package eu.kanade.domain.chapter.model
import eu.kanade.tachiyomi.data.database.models.ChapterImpl
import eu.kanade.tachiyomi.source.model.SChapter
import tachiyomi.data.Chapters
import tachiyomi.domain.chapter.model.Chapter
import eu.kanade.tachiyomi.data.database.models.Chapter as DbChapter
@ -26,6 +27,16 @@ fun Chapter.copyFromSChapter(sChapter: SChapter): Chapter {
)
}
fun Chapter.copyFrom(other: Chapters): Chapter {
return copy(
name = other.name,
url = other.url,
dateUpload = other.date_upload,
chapterNumber = other.chapter_number,
scanlator = other.scanlator?.ifBlank { null },
)
}
fun Chapter.toDbChapter(): DbChapter = ChapterImpl().also {
it.id = id
it.manga_id = mangaId

View File

@ -43,6 +43,7 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import eu.kanade.domain.track.model.toDbTrack
import eu.kanade.presentation.components.DropdownMenu
import eu.kanade.presentation.track.components.TrackLogoIcon
import eu.kanade.tachiyomi.R
@ -84,10 +85,10 @@ fun TrackInfoDialogHome(
TrackInfoItem(
title = item.track.title,
service = item.service,
status = item.service.getStatus(item.track.status),
status = item.service.getStatus(item.track.status.toInt()),
onStatusClick = { onStatusClick(item) },
chapters = "${item.track.last_chapter_read.toInt()}".let {
val totalChapters = item.track.total_chapters
chapters = "${item.track.lastChapterRead.toInt()}".let {
val totalChapters = item.track.totalChapters
if (totalChapters > 0) {
// Add known total chapter count
"$it / $totalChapters"
@ -96,16 +97,16 @@ fun TrackInfoDialogHome(
}
},
onChaptersClick = { onChapterClick(item) },
score = item.service.displayScore(item.track)
score = item.service.displayScore(item.track.toDbTrack())
.takeIf { supportsScoring && item.track.score != 0F },
onScoreClick = { onScoreClick(item) }
.takeIf { supportsScoring },
startDate = remember(item.track.started_reading_date) { dateFormat.format(item.track.started_reading_date) }
.takeIf { supportsReadingDates && item.track.started_reading_date != 0L },
startDate = remember(item.track.startDate) { dateFormat.format(item.track.startDate) }
.takeIf { supportsReadingDates && item.track.startDate != 0L },
onStartDateClick = { onStartDateEdit(item) } // TODO
.takeIf { supportsReadingDates },
endDate = dateFormat.format(item.track.finished_reading_date)
.takeIf { supportsReadingDates && item.track.finished_reading_date != 0L },
endDate = dateFormat.format(item.track.finishDate)
.takeIf { supportsReadingDates && item.track.finishDate != 0L },
onEndDateClick = { onEndDateEdit(item) }
.takeIf { supportsReadingDates },
onNewSearch = { onNewSearch(item) },

View File

@ -40,7 +40,6 @@ import eu.kanade.domain.ui.UiPreferences
import eu.kanade.domain.ui.model.setAppCompatDelegateThemeMode
import eu.kanade.tachiyomi.crash.CrashActivity
import eu.kanade.tachiyomi.crash.GlobalExceptionHandler
import eu.kanade.tachiyomi.data.coil.DomainMangaKeyer
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
import eu.kanade.tachiyomi.data.coil.MangaCoverKeyer
import eu.kanade.tachiyomi.data.coil.MangaKeyer
@ -169,11 +168,9 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
add(GifDecoder.Factory())
}
add(TachiyomiImageDecoder.Factory())
add(MangaCoverFetcher.Factory(lazy(callFactoryInit), lazy(diskCacheInit)))
add(MangaCoverFetcher.DomainMangaFactory(lazy(callFactoryInit), lazy(diskCacheInit)))
add(MangaCoverFetcher.MangaFactory(lazy(callFactoryInit), lazy(diskCacheInit)))
add(MangaCoverFetcher.MangaCoverFactory(lazy(callFactoryInit), lazy(diskCacheInit)))
add(MangaKeyer())
add(DomainMangaKeyer())
add(MangaCoverKeyer())
// SY -->
add(PagePreviewKeyer())

View File

@ -4,6 +4,7 @@ import android.Manifest
import android.content.Context
import android.net.Uri
import com.hippo.unifile.UniFile
import eu.kanade.domain.chapter.model.copyFrom
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CATEGORY
import eu.kanade.tachiyomi.data.backup.BackupConst.BACKUP_CATEGORY_MASK
@ -31,15 +32,13 @@ import eu.kanade.tachiyomi.data.backup.models.backupChapterMapper
import eu.kanade.tachiyomi.data.backup.models.backupMergedMangaReferenceMapper
import eu.kanade.tachiyomi.data.backup.models.backupSavedSearchMapper
import eu.kanade.tachiyomi.data.backup.models.backupTrackMapper
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.source.model.copyFrom
import eu.kanade.tachiyomi.source.online.MetadataSource
import eu.kanade.tachiyomi.util.system.hasPermission
import exh.source.MERGED_SOURCE_ID
import exh.source.getMainSource
import exh.util.nullIfBlank
import exh.util.nullIfEmpty
import kotlinx.serialization.protobuf.ProtoBuf
import logcat.LogPriority
import okio.buffer
@ -66,13 +65,13 @@ import tachiyomi.domain.manga.interactor.GetMergedManga
import tachiyomi.domain.manga.interactor.InsertFlatMetadata
import tachiyomi.domain.manga.interactor.SetCustomMangaInfo
import tachiyomi.domain.manga.model.CustomMangaInfo
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.source.service.SourceManager
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.FileOutputStream
import java.util.Date
import kotlin.math.max
import tachiyomi.domain.manga.model.Manga as DomainManga
class BackupManager(
private val context: Context,
@ -176,12 +175,12 @@ class BackupManager(
}
}
private fun backupExtensionInfo(mangas: List<DomainManga>): List<BackupSource> {
private fun backupExtensionInfo(mangas: List<Manga>): List<BackupSource> {
return mangas
.asSequence()
.map { it.source }
.map(Manga::source)
.distinct()
.map { sourceManager.getOrStub(it) }
.map(sourceManager::getOrStub)
.map { BackupSource.copyFrom(it) }
.toList()
}
@ -202,7 +201,7 @@ class BackupManager(
}
}
private suspend fun backupMangas(mangas: List<DomainManga>, flags: Int): List<BackupManga> {
private suspend fun backupMangas(mangas: List<Manga>, flags: Int): List<BackupManga> {
return mangas.map {
backupManga(it, flags)
}
@ -226,7 +225,7 @@ class BackupManager(
* @param options options for the backup
* @return [BackupManga] containing manga in a serializable form
*/
private suspend fun backupManga(manga: DomainManga, options: Int): BackupManga {
private suspend fun backupManga(manga: Manga, options: Int): BackupManga {
// Entry for this manga
val mangaObject = BackupManga.copyFrom(
manga,
@ -290,10 +289,11 @@ class BackupManager(
return mangaObject
}
internal suspend fun restoreExistingManga(manga: Manga, dbManga: Mangas) {
manga.id = dbManga._id
manga.copyFrom(dbManga)
internal suspend fun restoreExistingManga(manga: Manga, dbManga: Mangas): Manga {
var manga = manga.copy(id = dbManga._id)
manga = manga.copyFrom(dbManga)
updateManga(manga)
return manga
}
/**
@ -303,10 +303,10 @@ class BackupManager(
* @return Updated manga info.
*/
internal suspend fun restoreNewManga(manga: Manga): Manga {
return manga.also {
it.initialized = it.description != null
it.id = insertManga(it)
}
return manga.copy(
initialized = manga.description != null,
id = insertManga(manga),
)
}
/**
@ -437,28 +437,28 @@ class BackupManager(
* @param manga the manga whose sync have to be restored.
* @param tracks the track list to restore.
*/
internal suspend fun restoreTracking(manga: Manga, tracks: List<Track>) {
internal suspend fun restoreTracking(manga: Manga, tracks: List<tachiyomi.domain.track.model.Track>) {
// Fix foreign keys with the current manga id
tracks.map { it.manga_id = manga.id!! }
val tracks = tracks.map { it.copy(mangaId = manga.id!!) }
// Get tracks from database
val dbTracks = handler.awaitList { manga_syncQueries.getTracksByMangaId(manga.id!!) }
val toUpdate = mutableListOf<Manga_sync>()
val toInsert = mutableListOf<Track>()
val toInsert = mutableListOf<tachiyomi.domain.track.model.Track>()
tracks.forEach { track ->
var isInDatabase = false
for (dbTrack in dbTracks) {
if (track.sync_id == dbTrack.sync_id.toInt()) {
if (track.syncId == dbTrack.sync_id) {
// The sync is already in the db, only update its fields
var temp = dbTrack
if (track.media_id != dbTrack.remote_id) {
temp = temp.copy(remote_id = track.media_id)
if (track.remoteId != dbTrack.remote_id) {
temp = temp.copy(remote_id = track.remoteId)
}
if (track.library_id != dbTrack.library_id) {
temp = temp.copy(library_id = track.library_id)
if (track.libraryId != dbTrack.library_id) {
temp = temp.copy(library_id = track.libraryId)
}
temp = temp.copy(last_chapter_read = max(dbTrack.last_chapter_read, track.last_chapter_read.toDouble()))
temp = temp.copy(last_chapter_read = max(dbTrack.last_chapter_read, track.lastChapterRead))
isInDatabase = true
toUpdate.add(temp)
break
@ -466,8 +466,7 @@ class BackupManager(
}
if (!isInDatabase) {
// Insert new sync. Let the db assign the id
track.id = null
toInsert.add(track)
toInsert.add(track.copy(id = 0))
}
}
// Update database
@ -496,47 +495,47 @@ class BackupManager(
handler.await(true) {
toInsert.forEach { track ->
manga_syncQueries.insert(
track.manga_id,
track.sync_id.toLong(),
track.media_id,
track.library_id,
track.mangaId,
track.syncId,
track.remoteId,
track.libraryId,
track.title,
track.last_chapter_read.toDouble(),
track.total_chapters.toLong(),
track.status.toLong(),
track.lastChapterRead,
track.totalChapters,
track.status,
track.score,
track.tracking_url,
track.started_reading_date,
track.finished_reading_date,
track.remoteUrl,
track.startDate,
track.finishDate,
)
}
}
}
}
internal suspend fun restoreChapters(manga: Manga, chapters: List<Chapter>) {
internal suspend fun restoreChapters(manga: Manga, chapters: List<tachiyomi.domain.chapter.model.Chapter>) {
val dbChapters = handler.awaitList { chaptersQueries.getChaptersByMangaId(manga.id!!) }
chapters.forEach { chapter ->
val processed = chapters.map { chapter ->
var chapter = chapter
val dbChapter = dbChapters.find { it.url == chapter.url }
if (dbChapter != null) {
chapter.id = dbChapter._id
chapter.copyFrom(dbChapter)
chapter = chapter.copy(id = dbChapter._id)
chapter = chapter.copyFrom(dbChapter)
if (dbChapter.read && !chapter.read) {
chapter.read = dbChapter.read
chapter.last_page_read = dbChapter.last_page_read.toInt()
} else if (chapter.last_page_read == 0 && dbChapter.last_page_read != 0L) {
chapter.last_page_read = dbChapter.last_page_read.toInt()
chapter = chapter.copy(read = dbChapter.read, lastPageRead = dbChapter.last_page_read)
} else if (chapter.lastPageRead == 0L && dbChapter.last_page_read != 0L) {
chapter = chapter.copy(lastPageRead = dbChapter.last_page_read)
}
if (!chapter.bookmark && dbChapter.bookmark) {
chapter.bookmark = dbChapter.bookmark
chapter = chapter.copy(bookmark = dbChapter.bookmark)
}
}
chapter.manga_id = manga.id
chapter.copy(mangaId = manga.id ?: -1)
}
val newChapters = chapters.groupBy { it.id != null }
val newChapters = processed.groupBy { it.id > 0 }
newChapters[true]?.let { updateKnownChapters(it) }
newChapters[false]?.let { insertChapters(it) }
}
@ -563,22 +562,22 @@ class BackupManager(
artist = manga.artist,
author = manga.author,
description = manga.description,
genre = manga.getGenres(),
genre = manga.genre,
title = manga.title,
status = manga.status.toLong(),
thumbnailUrl = manga.thumbnail_url,
status = manga.status,
thumbnailUrl = manga.thumbnailUrl,
favorite = manga.favorite,
lastUpdate = manga.last_update,
lastUpdate = manga.lastUpdate,
nextUpdate = 0L,
initialized = manga.initialized,
viewerFlags = manga.viewer_flags.toLong(),
chapterFlags = manga.chapter_flags.toLong(),
coverLastModified = manga.cover_last_modified,
dateAdded = manga.date_added,
viewerFlags = manga.viewerFlags,
chapterFlags = manga.chapterFlags,
coverLastModified = manga.coverLastModified,
dateAdded = manga.dateAdded,
// SY -->
filteredScanlators = manga.filtered_scanlators?.nullIfBlank()?.let(listOfStringsAndAdapter::decode),
filteredScanlators = manga.filteredScanlators?.nullIfEmpty(),
// SY <--
updateStrategy = manga.update_strategy,
updateStrategy = manga.updateStrategy,
)
mangasQueries.selectLastInsertedRowId()
}
@ -592,45 +591,45 @@ class BackupManager(
artist = manga.artist,
author = manga.author,
description = manga.description,
genre = manga.genre,
genre = manga.genre?.joinToString(separator = ", "),
title = manga.title,
status = manga.status.toLong(),
thumbnailUrl = manga.thumbnail_url,
status = manga.status,
thumbnailUrl = manga.thumbnailUrl,
favorite = manga.favorite.toLong(),
lastUpdate = manga.last_update,
lastUpdate = manga.lastUpdate,
initialized = manga.initialized.toLong(),
viewer = manga.viewer_flags.toLong(),
chapterFlags = manga.chapter_flags.toLong(),
coverLastModified = manga.cover_last_modified,
dateAdded = manga.date_added,
viewer = manga.viewerFlags,
chapterFlags = manga.chapterFlags,
coverLastModified = manga.coverLastModified,
dateAdded = manga.dateAdded,
// SY -->
filteredScanlators = manga.filtered_scanlators,
filteredScanlators = manga.filteredScanlators?.let(listOfStringsAndAdapter::encode),
// SY <--
mangaId = manga.id!!,
updateStrategy = manga.update_strategy.let(updateStrategyAdapter::encode),
mangaId = manga.id,
updateStrategy = manga.updateStrategy.let(updateStrategyAdapter::encode),
)
}
return manga.id!!
return manga.id
}
/**
* Inserts list of chapters
*/
private suspend fun insertChapters(chapters: List<Chapter>) {
private suspend fun insertChapters(chapters: List<tachiyomi.domain.chapter.model.Chapter>) {
handler.await(true) {
chapters.forEach { chapter ->
chaptersQueries.insert(
chapter.manga_id!!,
chapter.mangaId,
chapter.url,
chapter.name,
chapter.scanlator,
chapter.read,
chapter.bookmark,
chapter.last_page_read.toLong(),
chapter.chapter_number,
chapter.source_order.toLong(),
chapter.date_fetch,
chapter.date_upload,
chapter.lastPageRead,
chapter.chapterNumber,
chapter.sourceOrder,
chapter.dateFetch,
chapter.dateUpload,
)
}
}
@ -639,22 +638,22 @@ class BackupManager(
/**
* Updates a list of chapters
*/
private suspend fun updateChapters(chapters: List<Chapter>) {
private suspend fun updateChapters(chapters: List<tachiyomi.domain.chapter.model.Chapter>) {
handler.await(true) {
chapters.forEach { chapter ->
chaptersQueries.update(
chapter.manga_id!!,
chapter.mangaId,
chapter.url,
chapter.name,
chapter.scanlator,
chapter.read.toLong(),
chapter.bookmark.toLong(),
chapter.last_page_read.toLong(),
chapter.chapter_number.toDouble(),
chapter.source_order.toLong(),
chapter.date_fetch,
chapter.date_upload,
chapter.id!!,
chapter.lastPageRead,
chapter.chapterNumber.toDouble(),
chapter.sourceOrder,
chapter.dateFetch,
chapter.dateUpload,
chapter.id,
)
}
}
@ -663,7 +662,7 @@ class BackupManager(
/**
* Updates a list of chapters with known database ids
*/
private suspend fun updateKnownChapters(chapters: List<Chapter>) {
private suspend fun updateKnownChapters(chapters: List<tachiyomi.domain.chapter.model.Chapter>) {
handler.await(true) {
chapters.forEach { chapter ->
chaptersQueries.update(
@ -673,12 +672,12 @@ class BackupManager(
scanlator = null,
read = chapter.read.toLong(),
bookmark = chapter.bookmark.toLong(),
lastPageRead = chapter.last_page_read.toLong(),
lastPageRead = chapter.lastPageRead,
chapterNumber = null,
sourceOrder = null,
dateFetch = null,
dateUpload = null,
chapterId = chapter.id!!,
chapterId = chapter.id,
)
}
}

View File

@ -10,16 +10,15 @@ import eu.kanade.tachiyomi.data.backup.models.BackupManga
import eu.kanade.tachiyomi.data.backup.models.BackupMergedMangaReference
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
import eu.kanade.tachiyomi.data.backup.models.BackupSource
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.util.BackupUtil
import eu.kanade.tachiyomi.util.system.createFileInCacheDir
import exh.EXHMigrations
import exh.source.MERGED_SOURCE_ID
import kotlinx.coroutines.Job
import okio.source
import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.manga.model.CustomMangaInfo
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.track.model.Track
import java.io.File
import java.text.SimpleDateFormat
import java.util.Date
@ -133,7 +132,7 @@ class BackupRestorer(
// SY <--
private suspend fun restoreManga(backupManga: BackupManga, backupCategories: List<BackupCategory>) {
val manga = backupManga.getMangaImpl()
var manga = backupManga.getMangaImpl()
val chapters = backupManga.getChaptersImpl()
val categories = backupManga.categories.map { it.toInt() }
val history =
@ -146,7 +145,7 @@ class BackupRestorer(
// SY <--
// SY -->
EXHMigrations.migrateBackupEntry(manga)
manga = EXHMigrations.migrateBackupEntry(manga)
// SY <--
try {
@ -157,7 +156,7 @@ class BackupRestorer(
} else {
// Manga in database
// Copy information from manga already in database
backupManager.restoreExistingManga(manga, dbManga)
val manga = backupManager.restoreExistingManga(manga, dbManga)
// Fetch rest of manga information
restoreNewManga(manga, chapters, categories, history, tracks, backupCategories/* SY --> */, mergedMangaReferences, flatMetadata, customManga/* SY <-- */)
}
@ -191,8 +190,6 @@ class BackupRestorer(
// SY <--
) {
val fetchedManga = backupManager.restoreNewManga(manga)
fetchedManga.id ?: return
backupManager.restoreChapters(fetchedManga, chapters)
restoreExtras(fetchedManga, categories, history, tracks, backupCategories/* SY --> */, mergedMangaReferences, flatMetadata, customManga/* SY <-- */)
}

View File

@ -1,8 +1,8 @@
package eu.kanade.tachiyomi.data.backup.models
import eu.kanade.tachiyomi.data.database.models.ChapterImpl
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import tachiyomi.domain.chapter.model.Chapter
@Serializable
data class BackupChapter(
@ -21,19 +21,19 @@ data class BackupChapter(
@ProtoNumber(9) var chapterNumber: Float = 0F,
@ProtoNumber(10) var sourceOrder: Long = 0,
) {
fun toChapterImpl(): ChapterImpl {
return ChapterImpl().apply {
url = this@BackupChapter.url
name = this@BackupChapter.name
chapter_number = this@BackupChapter.chapterNumber
scanlator = this@BackupChapter.scanlator
read = this@BackupChapter.read
bookmark = this@BackupChapter.bookmark
last_page_read = this@BackupChapter.lastPageRead.toInt()
date_fetch = this@BackupChapter.dateFetch
date_upload = this@BackupChapter.dateUpload
source_order = this@BackupChapter.sourceOrder.toInt()
}
fun toChapterImpl(): Chapter {
return Chapter.create().copy(
url = this@BackupChapter.url,
name = this@BackupChapter.name,
chapterNumber = this@BackupChapter.chapterNumber,
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,
)
}
}

View File

@ -1,15 +1,14 @@
package eu.kanade.tachiyomi.data.backup.models
import eu.kanade.tachiyomi.data.database.models.ChapterImpl
import eu.kanade.tachiyomi.data.database.models.MangaImpl
import eu.kanade.tachiyomi.data.database.models.TrackImpl
import eu.kanade.tachiyomi.source.model.UpdateStrategy
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import tachiyomi.data.listOfStringsAndAdapter
import tachiyomi.domain.chapter.model.Chapter
import tachiyomi.domain.manga.model.CustomMangaInfo
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.track.model.Track
@Suppress("DEPRECATION")
@Serializable
@ -59,27 +58,29 @@ data class BackupManga(
// Neko specific values
@ProtoNumber(901) var filtered_scanlators: String? = null,
) {
fun getMangaImpl(): MangaImpl {
return MangaImpl().apply {
url = this@BackupManga.url
title = this@BackupManga.title
artist = this@BackupManga.artist
author = this@BackupManga.author
description = this@BackupManga.description
genre = this@BackupManga.genre.joinToString()
status = this@BackupManga.status
thumbnail_url = this@BackupManga.thumbnailUrl
favorite = this@BackupManga.favorite
source = this@BackupManga.source
date_added = this@BackupManga.dateAdded
viewer_flags = this@BackupManga.viewer_flags ?: this@BackupManga.viewer
chapter_flags = this@BackupManga.chapterFlags
update_strategy = this@BackupManga.updateStrategy
filtered_scanlators = this@BackupManga.filtered_scanlators
}
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,
filteredScanlators = this@BackupManga.filtered_scanlators?.let(listOfStringsAndAdapter::decode),
)
}
fun getChaptersImpl(): List<ChapterImpl> {
fun getChaptersImpl(): List<Chapter> {
return chapters.map {
it.toChapterImpl()
}
@ -108,7 +109,7 @@ data class BackupManga(
}
// SY <--
fun getTrackingImpl(): List<TrackImpl> {
fun getTrackingImpl(): List<Track> {
return tracking.map {
it.getTrackingImpl()
}

View File

@ -1,8 +1,8 @@
package eu.kanade.tachiyomi.data.backup.models
import eu.kanade.tachiyomi.data.database.models.TrackImpl
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import tachiyomi.domain.track.model.Track
@Serializable
data class BackupTracking(
@ -29,25 +29,26 @@ data class BackupTracking(
@ProtoNumber(100) var mediaId: Long = 0,
) {
fun getTrackingImpl(): TrackImpl {
return TrackImpl().apply {
sync_id = this@BackupTracking.syncId
@Suppress("DEPRECATION")
media_id = if (this@BackupTracking.mediaIdInt != 0) {
fun getTrackingImpl(): 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
}
library_id = this@BackupTracking.libraryId
title = this@BackupTracking.title
last_chapter_read = this@BackupTracking.lastChapterRead
total_chapters = this@BackupTracking.totalChapters
score = this@BackupTracking.score
status = this@BackupTracking.status
started_reading_date = this@BackupTracking.startedReadingDate
finished_reading_date = this@BackupTracking.finishedReadingDate
tracking_url = this@BackupTracking.trackingUrl
}
},
libraryId = this@BackupTracking.libraryId,
title = this@BackupTracking.title,
lastChapterRead = this@BackupTracking.lastChapterRead.toDouble(),
totalChapters = this@BackupTracking.totalChapters.toLong(),
score = this@BackupTracking.score,
status = this@BackupTracking.status.toLong(),
startDate = this@BackupTracking.startedReadingDate,
finishDate = this@BackupTracking.finishedReadingDate,
remoteUrl = this@BackupTracking.trackingUrl,
)
}
}

View File

@ -12,7 +12,6 @@ import coil.request.Options
import coil.request.Parameters
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher.Companion.USE_CUSTOM_COVER
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.online.HttpSource
import logcat.LogPriority
@ -26,11 +25,11 @@ import okio.Source
import okio.buffer
import okio.sink
import tachiyomi.core.util.system.logcat
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.manga.model.MangaCover
import tachiyomi.domain.source.service.SourceManager
import uy.kohesive.injekt.injectLazy
import java.io.File
import tachiyomi.domain.manga.model.Manga as DomainManga
/**
* A [Fetcher] that fetches cover image for [Manga] object.
@ -261,7 +260,7 @@ class MangaCoverFetcher(
File, URL
}
class Factory(
class MangaFactory(
private val callFactoryLazy: Lazy<Call.Factory>,
private val diskCacheLazy: Lazy<DiskCache>,
) : Fetcher.Factory<Manga> {
@ -270,36 +269,13 @@ class MangaCoverFetcher(
private val sourceManager: SourceManager by injectLazy()
override fun create(data: Manga, options: Options, imageLoader: ImageLoader): Fetcher {
return MangaCoverFetcher(
url = data.thumbnail_url,
isLibraryManga = data.favorite,
options = options,
coverFileLazy = lazy { coverCache.getCoverFile(data.thumbnail_url) },
customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.id) },
diskCacheKeyLazy = lazy { MangaKeyer().key(data, options) },
sourceLazy = lazy { sourceManager.get(data.source) as? HttpSource },
callFactoryLazy = callFactoryLazy,
diskCacheLazy = diskCacheLazy,
)
}
}
class DomainMangaFactory(
private val callFactoryLazy: Lazy<Call.Factory>,
private val diskCacheLazy: Lazy<DiskCache>,
) : Fetcher.Factory<DomainManga> {
private val coverCache: CoverCache by injectLazy()
private val sourceManager: SourceManager by injectLazy()
override fun create(data: DomainManga, options: Options, imageLoader: ImageLoader): Fetcher {
return MangaCoverFetcher(
url = data.thumbnailUrl,
isLibraryManga = data.favorite,
options = options,
coverFileLazy = lazy { coverCache.getCoverFile(data.thumbnailUrl) },
customCoverFileLazy = lazy { coverCache.getCustomCoverFile(data.id) },
diskCacheKeyLazy = lazy { DomainMangaKeyer().key(data, options) },
diskCacheKeyLazy = lazy { MangaKeyer().key(data, options) },
sourceLazy = lazy { sourceManager.get(data.source) as? HttpSource },
callFactoryLazy = callFactoryLazy,
diskCacheLazy = diskCacheLazy,

View File

@ -4,24 +4,12 @@ import coil.key.Keyer
import coil.request.Options
import eu.kanade.domain.manga.model.hasCustomCover
import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.toDomainManga
import tachiyomi.domain.manga.model.MangaCover
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import tachiyomi.domain.manga.model.Manga as DomainManga
class MangaKeyer : Keyer<Manga> {
override fun key(data: Manga, options: Options): String {
return if (data.toDomainManga()!!.hasCustomCover()) {
"${data.id};${data.cover_last_modified}"
} else {
"${data.thumbnail_url};${data.cover_last_modified}"
}
}
}
class DomainMangaKeyer : Keyer<DomainManga> {
class MangaKeyer : Keyer<DomainManga> {
override fun key(data: DomainManga, options: Options): String {
return if (data.hasCustomCover()) {
"${data.id};${data.coverLastModified}"
@ -31,9 +19,11 @@ class DomainMangaKeyer : Keyer<DomainManga> {
}
}
class MangaCoverKeyer : Keyer<MangaCover> {
class MangaCoverKeyer(
private val coverCache: CoverCache = Injekt.get(),
) : Keyer<MangaCover> {
override fun key(data: MangaCover, options: Options): String {
return if (Injekt.get<CoverCache>().getCustomCoverFile(data.mangaId).exists()) {
return if (coverCache.getCustomCoverFile(data.mangaId).exists()) {
"${data.mangaId};${data.lastModified}"
} else {
"${data.url};${data.lastModified}"

View File

@ -1,77 +0,0 @@
package eu.kanade.tachiyomi.data.database.models
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.ui.reader.setting.OrientationType
import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
import exh.util.nullIfEmpty
import tachiyomi.data.listOfStringsAndAdapter
import tachiyomi.domain.manga.model.Manga as DomainManga
interface Manga : SManga {
var id: Long?
var source: Long
var favorite: Boolean
// last time the chapter list changed in any way
var last_update: Long
var date_added: Long
var viewer_flags: Int
var chapter_flags: Int
var cover_last_modified: Long
// SY -->
var filtered_scanlators: String?
fun getOriginalGenres(): List<String>? {
return originalGenre?.split(", ")?.map { it.trim() }
}
// SY <--
private fun setViewerFlags(flag: Int, mask: Int) {
viewer_flags = viewer_flags and mask.inv() or (flag and mask)
}
var readingModeType: Int
get() = viewer_flags and ReadingModeType.MASK
set(readingMode) = setViewerFlags(readingMode, ReadingModeType.MASK)
var orientationType: Int
get() = viewer_flags and OrientationType.MASK
set(rotationType) = setViewerFlags(rotationType, OrientationType.MASK)
}
fun Manga.toDomainManga(): DomainManga? {
val mangaId = id ?: return null
return DomainManga(
id = mangaId,
source = source,
favorite = favorite,
lastUpdate = last_update,
dateAdded = date_added,
viewerFlags = viewer_flags.toLong(),
chapterFlags = chapter_flags.toLong(),
coverLastModified = cover_last_modified,
url = url,
// SY -->
ogTitle = originalTitle,
ogArtist = originalArtist,
ogAuthor = originalAuthor,
ogDescription = originalDescription,
ogGenre = getOriginalGenres(),
ogStatus = originalStatus.toLong(),
// SY <--
thumbnailUrl = thumbnail_url,
updateStrategy = update_strategy,
initialized = initialized,
// SY -->
filteredScanlators = filtered_scanlators?.let(listOfStringsAndAdapter::decode)?.nullIfEmpty(),
// SY <--
)
}

View File

@ -1,133 +0,0 @@
package eu.kanade.tachiyomi.data.database.models
import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.UpdateStrategy
import tachiyomi.domain.manga.interactor.GetCustomMangaInfo
import tachiyomi.domain.manga.model.CustomMangaInfo
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
open class MangaImpl : Manga {
override var id: Long? = null
override var source: Long = -1
override lateinit var url: String
// SY -->
private val customManga: CustomMangaInfo?
get() = getCustomMangaInfo.get(id!!)
override var title: String
get() = if (favorite) {
customManga?.title ?: ogTitle
} else {
ogTitle
}
set(value) {
ogTitle = value
}
override var author: String?
get() = if (favorite) customManga?.author ?: ogAuthor else ogAuthor
set(value) { ogAuthor = value }
override var artist: String?
get() = if (favorite) customManga?.artist ?: ogArtist else ogArtist
set(value) { ogArtist = value }
override var description: String?
get() = if (favorite) customManga?.description ?: ogDesc else ogDesc
set(value) { ogDesc = value }
override var genre: String?
get() = if (favorite) customManga?.genre?.joinToString() ?: ogGenre else ogGenre
set(value) { ogGenre = value }
override var status: Int
get() = if (favorite) customManga?.status?.toInt() ?: ogStatus else ogStatus
set(value) { ogStatus = value }
// SY <--
override var thumbnail_url: String? = null
override var favorite: Boolean = false
override var last_update: Long = 0
override var date_added: Long = 0
override var update_strategy: UpdateStrategy = UpdateStrategy.ALWAYS_UPDATE
override var initialized: Boolean = false
override var viewer_flags: Int = 0
override var chapter_flags: Int = 0
override var cover_last_modified: Long = 0
override var filtered_scanlators: String? = null
// SY -->
lateinit var ogTitle: String
private set
var ogAuthor: String? = null
private set
var ogArtist: String? = null
private set
var ogDesc: String? = null
private set
var ogGenre: String? = null
private set
var ogStatus: Int = 0
private set
override val originalTitle: String
get() = ogTitle
override val originalAuthor: String?
get() = ogAuthor ?: author
override val originalArtist: String?
get() = ogArtist ?: artist
override val originalDescription: String?
get() = ogDesc ?: description
override val originalGenre: String?
get() = ogGenre ?: genre
override val originalStatus: Int
get() = ogStatus
// SY <--
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (other == null || javaClass != other.javaClass) return false
val manga = other as Manga
if (url != manga.url) return false
return id == manga.id
}
override fun hashCode(): Int {
return url.hashCode() + id.hashCode()
}
// SY -->
override fun copyFrom(other: SManga) {
// EXH -->
if (other.title.isNotBlank() && originalTitle != other.title) {
val source = (this as? Manga)?.source
if (source != null) {
Injekt.get<DownloadManager>().renameMangaDir(originalTitle, other.originalTitle, source)
}
}
// EXH <--
super.copyFrom(other)
}
companion object {
private val getCustomMangaInfo: GetCustomMangaInfo by injectLazy()
}
// SY <--
}

View File

@ -34,7 +34,6 @@ import eu.kanade.tachiyomi.source.UnmeteredSource
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.UpdateStrategy
import eu.kanade.tachiyomi.source.online.all.MergedSource
import eu.kanade.tachiyomi.ui.manga.track.TrackItem
import eu.kanade.tachiyomi.util.prepUpdateCover
import eu.kanade.tachiyomi.util.shouldDownloadNewChapters
import eu.kanade.tachiyomi.util.storage.getUriCompat
@ -631,11 +630,14 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
val dbTracks = getTracks.await(manga.id)
// find the mdlist entry if its unfollowed the follow it
val tracker = TrackItem(dbTracks.firstOrNull { it.syncId == TrackManager.MDLIST }?.toDbTrack() ?: trackManager.mdList.createInitialTracker(manga), trackManager.mdList)
var tracker = dbTracks.firstOrNull { it.syncId == TrackManager.MDLIST }
?: trackManager.mdList.createInitialTracker(manga).toDomainTrack(idRequired = false)
if (tracker.track?.status == FollowStatus.UNFOLLOWED.int) {
tracker.track.status = FollowStatus.READING.int
val updatedTrack = tracker.service.update(tracker.track)
if (tracker?.status == FollowStatus.UNFOLLOWED.int.toLong()) {
tracker = tracker.copy(
status = FollowStatus.READING.int.toLong(),
)
val updatedTrack = trackManager.mdList.update(tracker.toDbTrack())
insertTrack.await(updatedTrack.toDomainTrack(false)!!)
}
}

View File

@ -1,20 +1,12 @@
package eu.kanade.tachiyomi.source.model
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.download.DownloadManager
import tachiyomi.data.Mangas
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import tachiyomi.domain.manga.model.Manga
fun SManga.copyFrom(other: Mangas) {
// EXH -->
if (other.title.isNotBlank() && originalTitle != other.title) {
val oldTitle = originalTitle
title = other.title
val source = (this as? Manga)?.source
if (source != null) {
Injekt.get<DownloadManager>().renameMangaDir(oldTitle, other.title, source)
}
}
// EXH <--
@ -44,3 +36,33 @@ fun SManga.copyFrom(other: Mangas) {
initialized = other.initialized
}
}
fun Manga.copyFrom(other: Mangas): Manga {
var manga = this
if (other.author != null) {
manga = manga.copy(ogAuthor = other.author)
}
if (other.artist != null) {
manga = manga.copy(ogArtist = other.artist)
}
if (other.description != null) {
manga = manga.copy(ogDescription = other.description)
}
if (other.genre != null) {
manga = manga.copy(ogGenre = other.genre)
}
if (other.thumbnail_url != null) {
manga = manga.copy(thumbnailUrl = other.thumbnail_url)
}
manga = manga.copy(ogStatus = other.status)
if (!initialized) {
manga = manga.copy(initialized = other.initialized)
}
return manga
}

View File

@ -20,7 +20,6 @@ import eu.kanade.domain.manga.model.downloadedFilter
import eu.kanade.domain.manga.model.isLocal
import eu.kanade.domain.manga.model.toSManga
import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.domain.track.model.toDbTrack
import eu.kanade.domain.track.model.toDomainTrack
import eu.kanade.domain.ui.UiPreferences
import eu.kanade.presentation.manga.DownloadAction
@ -1381,10 +1380,9 @@ class MangaInfoScreenModel(
getTracks.subscribe(manga.id)
.catch { logcat(LogPriority.ERROR, it) }
.map { tracks ->
val dbTracks = tracks.map { it.toDbTrack() }
loggedServices
// Map to TrackItem
.map { service -> TrackItem(dbTracks.find { it.sync_id.toLong() == service.id }, service) }
.map { service -> TrackItem(tracks.find { it.syncId == service.id }, service) }
// Show only if the service supports this manga's source
.filter { (it.service as? EnhancedTrackService)?.accept(source!!) ?: true }
}
@ -1422,7 +1420,7 @@ class MangaInfoScreenModel(
val track = trackManager.mdList.createInitialTracker(state.manga, mdManga)
.toDomainTrack(false)!!
insertTrack.await(track)
return TrackItem(getTracks.await(mangaId).first { it.syncId == TrackManager.MDLIST }.toDbTrack(), trackManager.mdList)
return TrackItem(getTracks.await(mangaId).first { it.syncId == TrackManager.MDLIST }, trackManager.mdList)
}
// SY <--
@ -1557,7 +1555,7 @@ sealed class MangaScreenState {
get() = trackItems.isNotEmpty()
val trackingCount: Int
get() = trackItems.count { it.track != null && ((it.service.id == TrackManager.MDLIST && it.track.status != FollowStatus.UNFOLLOWED.int) || it.service.id != TrackManager.MDLIST) }
get() = trackItems.count { it.track != null && ((it.service.id == TrackManager.MDLIST && it.track.status != FollowStatus.UNFOLLOWED.int.toLong()) || it.service.id != TrackManager.MDLIST) }
/**
* Applies the view filters to the list of chapters obtained from the database.

View File

@ -47,7 +47,6 @@ import eu.kanade.presentation.track.TrackServiceSearch
import eu.kanade.presentation.track.TrackStatusSelector
import eu.kanade.presentation.util.Screen
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.track.TrackService
@ -71,6 +70,7 @@ import tachiyomi.domain.source.service.SourceManager
import tachiyomi.domain.track.interactor.DeleteTrack
import tachiyomi.domain.track.interactor.GetTracks
import tachiyomi.domain.track.interactor.InsertTrack
import tachiyomi.domain.track.model.Track
import tachiyomi.presentation.core.components.material.AlertDialogContent
import tachiyomi.presentation.core.components.material.padding
import uy.kohesive.injekt.Injekt
@ -149,7 +149,7 @@ data class TrackInfoDialogHomeScreen(
TrackServiceSearchScreen(
mangaId = mangaId,
initialQuery = it.track?.title ?: mangaTitle,
currentUrl = it.track?.tracking_url,
currentUrl = it.track?.remoteUrl,
serviceId = it.service.id,
),
)
@ -163,7 +163,7 @@ data class TrackInfoDialogHomeScreen(
* Opens registered tracker url in browser
*/
private fun openTrackerInBrowser(context: Context, trackItem: TrackItem) {
val url = trackItem.track?.tracking_url ?: return
val url = trackItem.track?.remoteUrl ?: return
if (url.isNotBlank()) {
context.openInBrowser(url)
}
@ -218,7 +218,7 @@ data class TrackInfoDialogHomeScreen(
for (trackItem in trackItems) {
try {
val track = trackItem.track ?: continue
val domainTrack = trackItem.service.refresh(track).toDomainTrack() ?: continue
val domainTrack = trackItem.service.refresh(track.toDbTrack()).toDomainTrack() ?: continue
insertTrack.await(domainTrack)
if (trackItem.service is EnhancedTrackService) {
@ -247,13 +247,12 @@ data class TrackInfoDialogHomeScreen(
}
}
private fun List<tachiyomi.domain.track.model.Track>.mapToTrackItem(): List<TrackItem> {
val dbTracks = map { it.toDbTrack() }
private fun List<Track>.mapToTrackItem(): List<TrackItem> {
val loggedServices = Injekt.get<TrackManager>().services.filter { it.isLogged }
val source = Injekt.get<SourceManager>().getOrStub(sourceId)
return loggedServices
// Map to TrackItem
.map { service -> TrackItem(dbTracks.find { it.sync_id.toLong() == service.id }, service) }
.map { service -> TrackItem(find { it.syncId == service.id }, service) }
// Show only if the service supports this manga's source
.filter { (it.service as? EnhancedTrackService)?.accept(source) ?: true }
}
@ -291,7 +290,7 @@ private data class TrackStatusSelectorScreen(
private class Model(
private val track: Track,
private val service: TrackService,
) : StateScreenModel<Model.State>(State(track.status)) {
) : StateScreenModel<Model.State>(State(track.status.toInt())) {
fun getSelections(): Map<Int, Int?> {
return service.getStatusList().associateWith { service.getStatus(it) }
@ -303,7 +302,7 @@ private data class TrackStatusSelectorScreen(
fun setStatus() {
coroutineScope.launchNonCancellable {
service.setRemoteStatus(track, state.value.selection)
service.setRemoteStatus(track.toDbTrack(), state.value.selection)
}
}
@ -341,15 +340,15 @@ private data class TrackChapterSelectorScreen(
private class Model(
private val track: Track,
private val service: TrackService,
) : StateScreenModel<Model.State>(State(track.last_chapter_read.toInt())) {
) : StateScreenModel<Model.State>(State(track.lastChapterRead.toInt())) {
fun getRange(): Iterable<Int> {
val endRange = if (track.total_chapters > 0) {
track.total_chapters
val endRange = if (track.totalChapters > 0) {
track.totalChapters
} else {
10000
}
return 0..endRange
return 0..endRange.toInt()
}
fun setSelection(selection: Int) {
@ -358,7 +357,7 @@ private data class TrackChapterSelectorScreen(
fun setChapter() {
coroutineScope.launchNonCancellable {
service.setRemoteLastChapterRead(track, state.value.selection)
service.setRemoteLastChapterRead(track.toDbTrack(), state.value.selection)
}
}
@ -396,7 +395,7 @@ private data class TrackScoreSelectorScreen(
private class Model(
private val track: Track,
private val service: TrackService,
) : StateScreenModel<Model.State>(State(service.displayScore(track))) {
) : StateScreenModel<Model.State>(State(service.displayScore(track.toDbTrack()))) {
fun getSelections(): List<String> {
return service.getScoreList()
@ -408,7 +407,7 @@ private data class TrackScoreSelectorScreen(
fun setScore() {
coroutineScope.launchNonCancellable {
service.setRemoteScore(track, state.value.selection)
service.setRemoteScore(track.toDbTrack(), state.value.selection)
}
}
@ -436,9 +435,9 @@ private data class TrackDateSelectorScreen(
}
val canRemove = if (start) {
track.started_reading_date > 0
track.startDate > 0
} else {
track.finished_reading_date > 0
track.finishDate > 0
}
TrackDateSelector(
title = if (start) {
@ -457,15 +456,15 @@ private data class TrackDateSelectorScreen(
return@TrackDateSelector false
}
if (start && track.finished_reading_date > 0) {
if (start && track.finishDate > 0) {
// Disallow start date to be set later than finish date
val dateFinished = Instant.ofEpochMilli(track.finished_reading_date)
val dateFinished = Instant.ofEpochMilli(track.finishDate)
.atZone(ZoneId.systemDefault())
.toLocalDate()
dateToCheck <= dateFinished
} else if (!start && track.started_reading_date > 0) {
} else if (!start && track.startDate > 0) {
// Disallow end date to be set earlier than start date
val dateStarted = Instant.ofEpochMilli(track.started_reading_date)
val dateStarted = Instant.ofEpochMilli(track.startDate)
.atZone(ZoneId.systemDefault())
.toLocalDate()
dateToCheck >= dateStarted
@ -489,7 +488,7 @@ private data class TrackDateSelectorScreen(
// In UTC
val initialSelection: Long
get() {
val millis = (if (start) track.started_reading_date else track.finished_reading_date)
val millis = (if (start) track.startDate else track.finishDate)
.takeIf { it != 0L }
?: Instant.now().toEpochMilli()
return convertEpochMillisZone(millis, ZoneOffset.systemDefault(), ZoneOffset.UTC)
@ -501,9 +500,9 @@ private data class TrackDateSelectorScreen(
val localMillis = convertEpochMillisZone(millis, ZoneOffset.UTC, ZoneOffset.systemDefault())
coroutineScope.launchNonCancellable {
if (start) {
service.setRemoteStartDate(track, localMillis)
service.setRemoteStartDate(track.toDbTrack(), localMillis)
} else {
service.setRemoteFinishDate(track, localMillis)
service.setRemoteFinishDate(track.toDbTrack(), localMillis)
}
}
}
@ -600,9 +599,9 @@ private data class TrackDateRemoverScreen(
fun removeDate() {
coroutineScope.launchNonCancellable {
if (start) {
service.setRemoteStartDate(track, 0)
service.setRemoteStartDate(track.toDbTrack(), 0)
} else {
service.setRemoteFinishDate(track, 0)
service.setRemoteFinishDate(track.toDbTrack(), 0)
}
}
}
@ -679,7 +678,7 @@ data class TrackServiceSearchScreen(
}
}
fun registerTracking(item: Track) {
fun registerTracking(item: TrackSearch) {
coroutineScope.launchNonCancellable { service.registerTracking(item, mangaId) }
}

View File

@ -1,6 +1,6 @@
package eu.kanade.tachiyomi.ui.manga.track
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.TrackService
import tachiyomi.domain.track.model.Track
data class TrackItem(val track: Track?, val service: TrackService)

View File

@ -13,7 +13,6 @@ import eu.kanade.domain.ui.UiPreferences
import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.core.security.SecurityPreferences
import eu.kanade.tachiyomi.data.backup.BackupCreatorJob
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.preference.PreferenceValues
import eu.kanade.tachiyomi.data.track.TrackManager
@ -59,6 +58,7 @@ import tachiyomi.domain.library.service.LibraryPreferences.Companion.MANGA_NON_C
import tachiyomi.domain.manga.interactor.GetManga
import tachiyomi.domain.manga.interactor.GetMangaBySource
import tachiyomi.domain.manga.interactor.InsertMergedReference
import tachiyomi.domain.manga.model.Manga
import tachiyomi.domain.manga.model.MangaUpdate
import tachiyomi.domain.manga.model.MergedMangaReference
import tachiyomi.domain.manga.model.TriStateFilter
@ -73,7 +73,6 @@ import uy.kohesive.injekt.injectLazy
import java.io.File
import java.net.URI
import java.net.URISyntaxException
import tachiyomi.domain.manga.model.Manga as DomainManga
object EXHMigrations {
private val handler: DatabaseHandler by injectLazy()
@ -558,28 +557,39 @@ object EXHMigrations {
return false
}
fun migrateBackupEntry(manga: Manga) {
if (manga.source == 6907L) {
// Migrate the old source to the delegated one
manga.source = NHentai.otherId
// Migrate nhentai URLs
manga.url = getUrlWithoutDomain(manga.url)
fun migrateBackupEntry(manga: Manga): Manga {
var newManga = manga
if (newManga.source == 6907L) {
newManga = newManga.copy(
// Migrate the old source to the delegated one
source = NHentai.otherId,
// Migrate nhentai URLs
url = getUrlWithoutDomain(newManga.url),
)
}
// Migrate Tsumino source IDs
if (manga.source == 6909L) {
manga.source = TSUMINO_SOURCE_ID
if (newManga.source == 6909L) {
newManga = newManga.copy(
source = TSUMINO_SOURCE_ID,
)
}
if (manga.source == 6912L) {
manga.source = HBROWSE_SOURCE_ID
manga.url = manga.url + "/c00001/"
if (newManga.source == 6912L) {
newManga = newManga.copy(
source = HBROWSE_SOURCE_ID,
url = newManga.url + "/c00001/",
)
}
// Allow importing of EHentai extension backups
if (manga.source in BlacklistedSources.EHENTAI_EXT_SOURCES) {
manga.source = EH_SOURCE_ID
if (newManga.source in BlacklistedSources.EHENTAI_EXT_SOURCES) {
newManga = newManga.copy(
source = EH_SOURCE_ID,
)
}
return newManga
}
private fun getUrlWithoutDomain(orig: String): String {
@ -624,7 +634,7 @@ object EXHMigrations {
}
}
private fun readMangaConfig(manga: DomainManga): MangaConfig? {
private fun readMangaConfig(manga: Manga): MangaConfig? {
return MangaConfig.readFromUrl(manga.url)
}
@ -650,7 +660,7 @@ object EXHMigrations {
}
}
private data class LoadedMangaSource(val source: Source, val manga: DomainManga)
private data class LoadedMangaSource(val source: Source, val manga: Manga)
private fun updateSourceId(newId: Long, oldId: Long) {
runBlocking {

View File

@ -17,7 +17,7 @@ class MangaDexFollowsScreenModel(sourceId: Long) : BrowseSourceScreenModel(sourc
return MangaDexFollowsPagingSource(source.getMainSource() as MangaDex)
}
override fun Flow<Manga>.combineMetadata(dbManga: Manga, metadata: RaisedSearchMetadata?): Flow<Pair<Manga, RaisedSearchMetadata?>> {
override fun Flow<Manga>.combineMetadata(metadata: RaisedSearchMetadata?): Flow<Pair<Manga, RaisedSearchMetadata?>> {
return map { it to metadata }
}

View File

@ -27,7 +27,7 @@ class MangaDexSimilarScreenModel(
return MangaDexSimilarPagingSource(manga, source.getMainSource() as MangaDex)
}
override fun Flow<Manga>.combineMetadata(dbManga: Manga, metadata: RaisedSearchMetadata?): Flow<Pair<Manga, RaisedSearchMetadata?>> {
override fun Flow<Manga>.combineMetadata(metadata: RaisedSearchMetadata?): Flow<Pair<Manga, RaisedSearchMetadata?>> {
return map { it to metadata }
}