diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/sync/SyncManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/sync/SyncManager.kt index 6deee8429..414218cc7 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/sync/SyncManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/sync/SyncManager.kt @@ -22,6 +22,7 @@ import tachiyomi.data.Chapters import tachiyomi.data.DatabaseHandler import tachiyomi.data.manga.MangaMapper.mapManga import tachiyomi.domain.category.interactor.GetCategories +import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.manga.interactor.GetFavorites import tachiyomi.domain.manga.model.Manga import tachiyomi.domain.sync.SyncPreferences @@ -169,58 +170,73 @@ class SyncManager( } /** - * Compares two Manga objects (one from the local database and one from the backup) to check if they are different. - * @param localManga the Manga object from the local database. - * @param remoteManga the BackupManga object from the backup. - * @return true if the Manga objects are different, otherwise false. + * Determines if there are differences between the local manga details and categories and their corresponding + * remote backup versions. This is used to identify changes or updates that might have occurred. + * + * @param localManga The manga object from the local database of type [Manga]. + * @param backupManga The manga object from the remote backup of type [BackupManga]. + * + * @return Boolean indicating whether there are differences. Returns true if any of the following is true: + * - The local manga details differ from the remote backup manga details. + * - The chapters of the local manga differ from the chapters of the remote backup manga. + * - The categories of the local manga differ from the categories of the remote backup manga. + * + * This function uses a combination of direct property comparisons and delegated comparison functions + * to assess differences across manga details, chapters, and categories. It relies on proper conversion + * of remote manga and chapters to the local format for accurate comparison. */ - private suspend fun isMangaDifferent(localManga: Manga, remoteManga: BackupManga): Boolean { + private suspend fun isMangaDifferent(localManga: Manga, backupManga: BackupManga): Boolean { + val remoteManga = backupManga.getMangaImpl() val localChapters = handler.await { chaptersQueries.getChaptersByMangaId(localManga.id, 0).executeAsList() } val localCategories = getCategories.await(localManga.id).map { it.order } - return localManga.source != remoteManga.source || - localManga.url != remoteManga.url || - localManga.title != remoteManga.title || - localManga.artist != remoteManga.artist || - localManga.author != remoteManga.author || - localManga.description != remoteManga.description || - localManga.genre != remoteManga.genre || - localManga.status.toInt() != remoteManga.status || - localManga.thumbnailUrl != remoteManga.thumbnailUrl || - localManga.dateAdded != remoteManga.dateAdded || - localManga.chapterFlags.toInt() != remoteManga.chapterFlags || - localManga.favorite != remoteManga.favorite || - localManga.viewerFlags.toInt() != remoteManga.viewer_flags || - localManga.updateStrategy != remoteManga.updateStrategy || - areChaptersDifferent(localChapters, remoteManga.chapters) || - localCategories != remoteManga.categories + return localManga != remoteManga || areChaptersDifferent(localChapters, backupManga.chapters) || localCategories != backupManga.categories } /** - * Compares two lists of chapters (one from the local database and one from the backup) to check if they are different. - * @param localChapters the list of chapters from the local database. - * @param remoteChapters the list of BackupChapter objects from the backup. - * @return true if the lists of chapters are different, otherwise false. + * Checks if there are any differences between a list of local chapters and a list of backup chapters. + * This function is used to determine if updates or changes have occurred between the two sets of chapters. + * + * @param localChapters The list of chapters from the local source, of type [Chapters]. + * @param remoteChapters The list of chapters from the remote backup source, of type [BackupChapter]. + * + * @return Boolean indicating whether there are differences. Returns true if any of the following is true: + * - The count of local and remote chapters differs. + * - Any corresponding chapters (matched by URL) have differing attributes including name, scanlator, + * read status, bookmark status, last page read, chapter number, source order, fetch date, upload date, + * or last modified date. + * + * Each chapter is compared based on a set of fields that define its content and state. If any of these fields + * differ between the local chapter and its corresponding remote chapter, it is considered a difference. + * */ private fun areChaptersDifferent(localChapters: List, remoteChapters: List): Boolean { + // Early return if the sizes are different if (localChapters.size != remoteChapters.size) { return true } + // Convert all remote chapters to Chapter instances + val convertedRemoteChapters = remoteChapters.map { it.toChapterImpl() } + + // Create a map for the local chapters for efficient comparison val localChapterMap = localChapters.associateBy { it.url } - return remoteChapters.any { remoteChapter -> - localChapterMap[remoteChapter.url]?.let { localChapter -> + // Check for any differences + return convertedRemoteChapters.any { remoteChapter -> + val localChapter = localChapterMap[remoteChapter.url] + localChapter == null || // No corresponding local chapter + localChapter.url != remoteChapter.url || localChapter.name != remoteChapter.name || - localChapter.scanlator != remoteChapter.scanlator || - localChapter.read != remoteChapter.read || - localChapter.bookmark != remoteChapter.bookmark || - localChapter.last_page_read != remoteChapter.lastPageRead || - localChapter.date_fetch != remoteChapter.dateFetch || - localChapter.date_upload != remoteChapter.dateUpload || - localChapter.chapter_number.toFloat() != remoteChapter.chapterNumber || - localChapter.source_order != remoteChapter.sourceOrder - } ?: true + localChapter.scanlator != remoteChapter.scanlator || + localChapter.read != remoteChapter.read || + localChapter.bookmark != remoteChapter.bookmark || + localChapter.last_page_read != remoteChapter.lastPageRead || + localChapter.chapter_number != remoteChapter.chapterNumber || + localChapter.source_order != remoteChapter.sourceOrder || + localChapter.date_fetch != remoteChapter.dateFetch || + localChapter.date_upload != remoteChapter.dateUpload || + localChapter.last_modified_at != remoteChapter.lastModifiedAt } }