mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-15 15:02:49 +01:00
refactor: composite keys.
Use composite keys for better matching, there was mismatch before and better manga categories handling. Added more logs as well. Signed-off-by: KaiserBh <kaiserbh@proton.me>
This commit is contained in:
parent
3c95d3aefc
commit
f3c2c13f49
@ -17,7 +17,7 @@ import eu.kanade.tachiyomi.data.sync.service.SyncYomiSyncService
|
|||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.protobuf.ProtoBuf
|
import kotlinx.serialization.protobuf.ProtoBuf
|
||||||
import logcat.LogPriority
|
import logcat.LogPriority
|
||||||
import tachiyomi.core.util.system.logcat
|
import logcat.logcat
|
||||||
import tachiyomi.data.Chapters
|
import tachiyomi.data.Chapters
|
||||||
import tachiyomi.data.DatabaseHandler
|
import tachiyomi.data.DatabaseHandler
|
||||||
import tachiyomi.data.manga.MangaMapper.mapManga
|
import tachiyomi.data.manga.MangaMapper.mapManga
|
||||||
@ -119,6 +119,13 @@ class SyncManager(
|
|||||||
|
|
||||||
val remoteBackup = syncService?.doSync(syncData)
|
val remoteBackup = syncService?.doSync(syncData)
|
||||||
|
|
||||||
|
// Check if it's first sync based on lastSyncTimestamp
|
||||||
|
if (syncPreferences.lastSyncTimestamp().get() == 0L && databaseManga.isNotEmpty()) {
|
||||||
|
// It's first sync no need to restore data. (just update remote data)
|
||||||
|
syncPreferences.lastSyncTimestamp().set(Date().time)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if (remoteBackup != null) {
|
if (remoteBackup != null) {
|
||||||
val (filteredFavorites, nonFavorites) = filterFavoritesAndNonFavorites(remoteBackup)
|
val (filteredFavorites, nonFavorites) = filterFavoritesAndNonFavorites(remoteBackup)
|
||||||
updateNonFavorites(nonFavorites)
|
updateNonFavorites(nonFavorites)
|
||||||
@ -187,24 +194,66 @@ class SyncManager(
|
|||||||
private suspend fun isMangaDifferent(localManga: Manga, remoteManga: BackupManga): Boolean {
|
private suspend fun isMangaDifferent(localManga: Manga, remoteManga: BackupManga): Boolean {
|
||||||
val localChapters = handler.await { chaptersQueries.getChaptersByMangaId(localManga.id, 0).executeAsList() }
|
val localChapters = handler.await { chaptersQueries.getChaptersByMangaId(localManga.id, 0).executeAsList() }
|
||||||
val localCategories = getCategories.await(localManga.id).map { it.order }
|
val localCategories = getCategories.await(localManga.id).map { it.order }
|
||||||
|
val logTag = "isMangaDifferent"
|
||||||
|
|
||||||
return localManga.source != remoteManga.source ||
|
// Logging the start of comparison
|
||||||
localManga.url != remoteManga.url ||
|
logcat(LogPriority.DEBUG, logTag) {
|
||||||
localManga.title != remoteManga.title ||
|
"Comparing local manga (Title: ${localManga.title}) with remote manga (Title: ${remoteManga.title})"
|
||||||
localManga.status.toInt() != remoteManga.status ||
|
}
|
||||||
localManga.thumbnailUrl != remoteManga.thumbnailUrl ||
|
|
||||||
localManga.dateAdded != remoteManga.dateAdded ||
|
var isDifferent = false
|
||||||
localManga.chapterFlags.toInt() != remoteManga.chapterFlags ||
|
|
||||||
localManga.favorite != remoteManga.favorite ||
|
// Compare each field and log if they are different
|
||||||
localManga.viewerFlags.toInt() != remoteManga.viewer_flags ||
|
if (localManga.source != remoteManga.source) {
|
||||||
localManga.updateStrategy != remoteManga.updateStrategy ||
|
logDifference(logTag, "Source", localManga.source.toString(), remoteManga.source.toString())
|
||||||
areChaptersDifferent(localChapters, remoteManga.chapters) ||
|
isDifferent = true
|
||||||
localCategories != remoteManga.categories
|
}
|
||||||
|
if (localManga.url != remoteManga.url) {
|
||||||
|
logDifference(logTag, "URL", localManga.url, remoteManga.url)
|
||||||
|
isDifferent = true
|
||||||
|
}
|
||||||
|
if (localManga.favorite != remoteManga.favorite) {
|
||||||
|
logDifference(logTag, "Favorite", localManga.favorite.toString(), remoteManga.favorite.toString())
|
||||||
|
isDifferent = true
|
||||||
|
}
|
||||||
|
if (areChaptersDifferent(localChapters, remoteManga.chapters)) {
|
||||||
|
logcat(LogPriority.DEBUG, logTag) {
|
||||||
|
"Chapters are different for manga: ${localManga.title}"
|
||||||
|
}
|
||||||
|
isDifferent = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localCategories.toSet() != remoteManga.categories.toSet()) {
|
||||||
|
logcat(LogPriority.DEBUG, logTag) {
|
||||||
|
"Categories differ for manga: ${localManga.title}. " +
|
||||||
|
"Local categories: ${localCategories.joinToString()}, " +
|
||||||
|
"Remote categories: ${remoteManga.categories.joinToString()}"
|
||||||
|
}
|
||||||
|
isDifferent = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Log final result
|
||||||
|
logcat(LogPriority.DEBUG, logTag) {
|
||||||
|
"Manga difference check result for local manga (Title: ${localManga.title}): $isDifferent"
|
||||||
|
}
|
||||||
|
|
||||||
|
return isDifferent
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun logDifference(tag: String, field: String, localValue: String, remoteValue: String) {
|
||||||
|
logcat(LogPriority.DEBUG, tag) {
|
||||||
|
"Difference found in $field. Local: $localValue, Remote: $remoteValue"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun areChaptersDifferent(localChapters: List<Chapters>, remoteChapters: List<BackupChapter>): Boolean {
|
private fun areChaptersDifferent(localChapters: List<Chapters>, remoteChapters: List<BackupChapter>): Boolean {
|
||||||
|
val logTag = "areChaptersDifferent"
|
||||||
|
|
||||||
// Early return if the sizes are different
|
// Early return if the sizes are different
|
||||||
if (localChapters.size != remoteChapters.size) {
|
if (localChapters.size != remoteChapters.size) {
|
||||||
|
logcat(LogPriority.DEBUG, logTag) {
|
||||||
|
"Chapter lists differ in size. Local: ${localChapters.size}, Remote: ${remoteChapters.size}"
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,16 +263,60 @@ class SyncManager(
|
|||||||
// Create a map for the local chapters for efficient comparison
|
// Create a map for the local chapters for efficient comparison
|
||||||
val localChapterMap = localChapters.associateBy { it.url }
|
val localChapterMap = localChapters.associateBy { it.url }
|
||||||
|
|
||||||
|
var isDifferent = false
|
||||||
|
|
||||||
// Check for any differences
|
// Check for any differences
|
||||||
return convertedRemoteChapters.any { remoteChapter ->
|
for (remoteChapter in convertedRemoteChapters) {
|
||||||
val localChapter = localChapterMap[remoteChapter.url]
|
val localChapter = localChapterMap[remoteChapter.url]
|
||||||
localChapter == null || // No corresponding local chapter
|
|
||||||
localChapter.url != remoteChapter.url ||
|
if (localChapter == null) {
|
||||||
localChapter.read != remoteChapter.read ||
|
logcat(LogPriority.DEBUG, logTag) {
|
||||||
localChapter.bookmark != remoteChapter.bookmark ||
|
"Local chapter not found for URL: ${remoteChapter.url}"
|
||||||
localChapter.last_page_read != remoteChapter.lastPageRead ||
|
|
||||||
localChapter.chapter_number != remoteChapter.chapterNumber
|
|
||||||
}
|
}
|
||||||
|
isDifferent = true
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localChapter.url != remoteChapter.url) {
|
||||||
|
logDifference(logTag, "URL", localChapter.url, remoteChapter.url)
|
||||||
|
isDifferent = true
|
||||||
|
}
|
||||||
|
if (localChapter.read != remoteChapter.read) {
|
||||||
|
logDifference(logTag, "Read Status", localChapter.read.toString(), remoteChapter.read.toString())
|
||||||
|
isDifferent = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localChapter.bookmark != remoteChapter.bookmark) {
|
||||||
|
logDifference(
|
||||||
|
logTag,
|
||||||
|
"Bookmark Status",
|
||||||
|
localChapter.bookmark.toString(),
|
||||||
|
remoteChapter.bookmark.toString(),
|
||||||
|
)
|
||||||
|
isDifferent = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (localChapter.last_page_read != remoteChapter.lastPageRead) {
|
||||||
|
logDifference(
|
||||||
|
logTag,
|
||||||
|
"Last Page Read",
|
||||||
|
localChapter.last_page_read.toString(),
|
||||||
|
remoteChapter.lastPageRead.toString(),
|
||||||
|
)
|
||||||
|
isDifferent = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Break the loop if a difference is found
|
||||||
|
if (isDifferent) break
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isDifferent) {
|
||||||
|
logcat(LogPriority.DEBUG, logTag) {
|
||||||
|
"No differences found in chapters."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return isDifferent
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -234,27 +327,31 @@ class SyncManager(
|
|||||||
private suspend fun filterFavoritesAndNonFavorites(backup: Backup): Pair<List<BackupManga>, List<BackupManga>> {
|
private suspend fun filterFavoritesAndNonFavorites(backup: Backup): Pair<List<BackupManga>, List<BackupManga>> {
|
||||||
val favorites = mutableListOf<BackupManga>()
|
val favorites = mutableListOf<BackupManga>()
|
||||||
val nonFavorites = mutableListOf<BackupManga>()
|
val nonFavorites = mutableListOf<BackupManga>()
|
||||||
|
val logTag = "filterFavoritesAndNonFavorites"
|
||||||
val elapsedTimeMillis = measureTimeMillis {
|
val elapsedTimeMillis = measureTimeMillis {
|
||||||
val databaseMangaFavorites = getFavorites.await()
|
val databaseMangaFavorites = getFavorites.await()
|
||||||
val localMangaMap = databaseMangaFavorites.associateBy { it.url }
|
val localMangaMap = databaseMangaFavorites.associateBy {
|
||||||
|
Triple(it.source, it.url, it.title)
|
||||||
|
}
|
||||||
|
|
||||||
logcat(LogPriority.DEBUG) { "Starting to filter favorites and non-favorites from backup data." }
|
logcat(LogPriority.DEBUG, logTag) { "Starting to filter favorites and non-favorites from backup data." }
|
||||||
|
|
||||||
backup.backupManga.forEach { remoteManga ->
|
backup.backupManga.forEach { remoteManga ->
|
||||||
val localManga = localMangaMap[remoteManga.url]
|
val compositeKey = Triple(remoteManga.source, remoteManga.url, remoteManga.title)
|
||||||
|
val localManga = localMangaMap[compositeKey]
|
||||||
when {
|
when {
|
||||||
// Checks if the manga is in favorites and needs updating or adding
|
// Checks if the manga is in favorites and needs updating or adding
|
||||||
remoteManga.favorite -> {
|
remoteManga.favorite -> {
|
||||||
if (localManga == null || isMangaDifferent(localManga, remoteManga)) {
|
if (localManga == null || isMangaDifferent(localManga, remoteManga)) {
|
||||||
logcat(LogPriority.DEBUG) { "Adding to favorites: ${remoteManga.title}" }
|
logcat(LogPriority.DEBUG, logTag) { "Adding to favorites: ${remoteManga.title}" }
|
||||||
favorites.add(remoteManga)
|
favorites.add(remoteManga)
|
||||||
} else {
|
} else {
|
||||||
logcat(LogPriority.DEBUG) { "Already up-to-date favorite: ${remoteManga.title}" }
|
logcat(LogPriority.DEBUG, logTag) { "Already up-to-date favorite: ${remoteManga.title}" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Handle non-favorites
|
// Handle non-favorites
|
||||||
!remoteManga.favorite -> {
|
!remoteManga.favorite -> {
|
||||||
logcat(LogPriority.DEBUG) { "Adding to non-favorites: ${remoteManga.title}" }
|
logcat(LogPriority.DEBUG, logTag) { "Adding to non-favorites: ${remoteManga.title}" }
|
||||||
nonFavorites.add(remoteManga)
|
nonFavorites.add(remoteManga)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,7 +360,7 @@ class SyncManager(
|
|||||||
|
|
||||||
val minutes = elapsedTimeMillis / 60000
|
val minutes = elapsedTimeMillis / 60000
|
||||||
val seconds = (elapsedTimeMillis % 60000) / 1000
|
val seconds = (elapsedTimeMillis % 60000) / 1000
|
||||||
logcat(LogPriority.DEBUG) {
|
logcat(LogPriority.DEBUG, logTag) {
|
||||||
"Filtering completed in ${minutes}m ${seconds}s. Favorites found: ${favorites.size}, " +
|
"Filtering completed in ${minutes}m ${seconds}s. Favorites found: ${favorites.size}, " +
|
||||||
"Non-favorites found: ${nonFavorites.size}"
|
"Non-favorites found: ${nonFavorites.size}"
|
||||||
}
|
}
|
||||||
@ -309,7 +406,7 @@ class SyncManager(
|
|||||||
if (updated) {
|
if (updated) {
|
||||||
logcat(LogPriority.DEBUG) {
|
logcat(LogPriority.DEBUG) {
|
||||||
"Chapter ${chapter.name} of ${manga.title} updated after last sync " +
|
"Chapter ${chapter.name} of ${manga.title} updated after last sync " +
|
||||||
"(Chapter Last Modified: ${chapter.lastModifiedAt}, Last Sync: $lastSyncTimeStamp)."
|
"(Chapter Last Modified: ${chapter.lastModifiedAt * 1000L}, Last Sync: $lastSyncTimeStamp)."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
updated
|
updated
|
||||||
|
@ -100,7 +100,7 @@ abstract class SyncService(
|
|||||||
val localMangaListSafe = localMangaList.orEmpty()
|
val localMangaListSafe = localMangaList.orEmpty()
|
||||||
val remoteMangaListSafe = remoteMangaList.orEmpty()
|
val remoteMangaListSafe = remoteMangaList.orEmpty()
|
||||||
|
|
||||||
logcat(logTag, LogPriority.DEBUG) {
|
logcat(LogPriority.DEBUG, logTag) {
|
||||||
"Starting merge. Local list size: ${localMangaListSafe.size}, Remote list size: ${remoteMangaListSafe.size}"
|
"Starting merge. Local list size: ${localMangaListSafe.size}, Remote list size: ${remoteMangaListSafe.size}"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,8 +144,9 @@ abstract class SyncService(
|
|||||||
}
|
}
|
||||||
local != null && remote != null -> {
|
local != null && remote != null -> {
|
||||||
logcat(LogPriority.DEBUG, logTag) {
|
logcat(LogPriority.DEBUG, logTag) {
|
||||||
"Inspecting timestamps for ${local.title}. Local lastModifiedAt: ${local.lastModifiedAt}, " +
|
"Inspecting timestamps for ${local.title}. " +
|
||||||
"Remote lastModifiedAt: ${remote.lastModifiedAt}"
|
"Local lastModifiedAt: ${local.lastModifiedAt * 1000L}, " +
|
||||||
|
"Remote lastModifiedAt: ${remote.lastModifiedAt * 1000L}"
|
||||||
}
|
}
|
||||||
// Convert seconds to milliseconds for accurate time comparison
|
// Convert seconds to milliseconds for accurate time comparison
|
||||||
val localTime = Instant.ofEpochMilli(local.lastModifiedAt * 1000L)
|
val localTime = Instant.ofEpochMilli(local.lastModifiedAt * 1000L)
|
||||||
|
Loading…
Reference in New Issue
Block a user