mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-15 15:02:49 +01:00
refactor
Signed-off-by: KaiserBh <kaiserbh@proton.me>
This commit is contained in:
parent
5dbeda6b65
commit
646ec0c947
@ -80,94 +80,91 @@ abstract class SyncService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges two lists of SyncManga objects, prioritizing the manga with the most recent lastModifiedAt value.
|
* Merges two lists of BackupManga objects, selecting the most recent manga based on the lastModifiedAt value.
|
||||||
* If lastModifiedAt is null, the function defaults to Instant.MIN for comparison purposes.
|
* If lastModifiedAt is null for a manga, it treats that manga as the oldest possible for comparison purposes.
|
||||||
|
* This function is designed to reconcile local and remote manga lists, ensuring the most up-to-date manga is retained.
|
||||||
*
|
*
|
||||||
* @param localMangaList The list of local SyncManga objects.
|
* @param localMangaList The list of local BackupManga objects or null.
|
||||||
* @param remoteMangaList The list of remote SyncManga objects.
|
* @param remoteMangaList The list of remote BackupManga objects or null.
|
||||||
* @return The merged list of SyncManga objects.
|
* @return A list of BackupManga objects, each representing the most recent version of the manga from either local or remote sources.
|
||||||
*/
|
*/
|
||||||
private fun mergeMangaLists(
|
private fun mergeMangaLists(
|
||||||
localMangaList: List<BackupManga>?,
|
localMangaList: List<BackupManga>?,
|
||||||
remoteMangaList: List<BackupManga>?,
|
remoteMangaList: List<BackupManga>?
|
||||||
): List<BackupManga> {
|
): List<BackupManga> {
|
||||||
if (localMangaList == null) return remoteMangaList ?: emptyList()
|
// Convert null lists to empty to simplify logic
|
||||||
if (remoteMangaList == null) return localMangaList
|
val localMangaListSafe = localMangaList.orEmpty()
|
||||||
|
val remoteMangaListSafe = remoteMangaList.orEmpty()
|
||||||
|
|
||||||
val localMangaMap = localMangaList.associateBy { Pair(it.source, it.url) }
|
// Associate both local and remote manga by their unique keys (source and url)
|
||||||
val remoteMangaMap = remoteMangaList.associateBy { Pair(it.source, it.url) }
|
val localMangaMap = localMangaListSafe.associateBy { Pair(it.source, it.url) }
|
||||||
|
val remoteMangaMap = remoteMangaListSafe.associateBy { Pair(it.source, it.url) }
|
||||||
|
|
||||||
val mergedMangaMap = mutableMapOf<Pair<Long, String>, BackupManga>()
|
// Prepare to merge both sets of manga
|
||||||
|
return (localMangaMap.keys + remoteMangaMap.keys).mapNotNull { key ->
|
||||||
|
val local = localMangaMap[key]
|
||||||
|
val remote = remoteMangaMap[key]
|
||||||
|
|
||||||
localMangaMap.forEach { (key, localManga) ->
|
when {
|
||||||
val remoteManga = remoteMangaMap[key]
|
local != null && remote == null -> local
|
||||||
if (remoteManga != null) {
|
local == null && remote != null -> remote
|
||||||
val localMangaLastModifiedAtInstant = Instant.ofEpochMilli(localManga.lastModifiedAt)
|
local != null && remote != null -> {
|
||||||
val remoteMangaLastModifiedAtInstant = Instant.ofEpochMilli(remoteManga.lastModifiedAt)
|
// Compare last modified times and merge chapters
|
||||||
val mergedChapters = mergeChapters(localManga.chapters, remoteManga.chapters)
|
val localTime = Instant.ofEpochMilli(local.lastModifiedAt)
|
||||||
// Keep the more recent manga
|
val remoteTime = Instant.ofEpochMilli(remote.lastModifiedAt)
|
||||||
if (localMangaLastModifiedAtInstant.isAfter(remoteMangaLastModifiedAtInstant)) {
|
val mergedChapters = mergeChapters(local.chapters, remote.chapters)
|
||||||
mergedMangaMap[key] = localManga.copy(chapters = mergedChapters)
|
|
||||||
} else {
|
if (localTime >= remoteTime) local.copy(chapters = mergedChapters)
|
||||||
mergedMangaMap[key] = remoteManga.copy(chapters = mergedChapters)
|
else remote.copy(chapters = mergedChapters)
|
||||||
|
}
|
||||||
|
else -> null // This case occurs if both are null, which shouldn't happen but is handled for completeness.
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// If there is no corresponding remote manga, keep the local one
|
|
||||||
mergedMangaMap[key] = localManga
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add any remote manga that doesn't exist locally
|
|
||||||
remoteMangaMap.forEach { (key, remoteManga) ->
|
|
||||||
if (!mergedMangaMap.containsKey(key)) {
|
|
||||||
mergedMangaMap[key] = remoteManga
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mergedMangaMap.values.toList()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Merges two lists of SyncChapter objects, prioritizing the chapter with the most recent lastModifiedAt value.
|
* Merges two lists of BackupChapter objects, selecting the most recent chapter based on the lastModifiedAt value.
|
||||||
* If lastModifiedAt is null, the function defaults to Instant.MIN for comparison purposes.
|
* If lastModifiedAt is null for a chapter, it treats that chapter as the oldest possible for comparison purposes.
|
||||||
|
* This function is designed to reconcile local and remote chapter lists, ensuring the most up-to-date chapter is retained.
|
||||||
*
|
*
|
||||||
* @param localChapters The list of local SyncChapter objects.
|
* @param localChapters The list of local BackupChapter objects.
|
||||||
* @param remoteChapters The list of remote SyncChapter objects.
|
* @param remoteChapters The list of remote BackupChapter objects.
|
||||||
* @return The merged list of SyncChapter objects.
|
* @return A list of BackupChapter objects, each representing the most recent version of the chapter from either local or remote sources.
|
||||||
|
*
|
||||||
|
* - This function is used in scenarios where local and remote chapter lists need to be synchronized.
|
||||||
|
* - It iterates over the union of the URLs from both local and remote chapters.
|
||||||
|
* - For each URL, it compares the corresponding local and remote chapters based on the lastModifiedAt value.
|
||||||
|
* - If only one source (local or remote) has the chapter for a URL, that chapter is used.
|
||||||
|
* - If both sources have the chapter, the one with the more recent lastModifiedAt value is chosen.
|
||||||
|
* - If lastModifiedAt is null or missing, the chapter is considered the oldest for safety, ensuring that any chapter with a valid timestamp is preferred.
|
||||||
|
* - The resulting list contains the most recent chapters from the combined set of local and remote chapters.
|
||||||
*/
|
*/
|
||||||
private fun mergeChapters(
|
private fun mergeChapters(
|
||||||
localChapters: List<BackupChapter>,
|
localChapters: List<BackupChapter>,
|
||||||
remoteChapters: List<BackupChapter>,
|
remoteChapters: List<BackupChapter>
|
||||||
): List<BackupChapter> {
|
): List<BackupChapter> {
|
||||||
|
// Associate chapters by URL for both local and remote
|
||||||
val localChapterMap = localChapters.associateBy { it.url }
|
val localChapterMap = localChapters.associateBy { it.url }
|
||||||
val remoteChapterMap = remoteChapters.associateBy { it.url }
|
val remoteChapterMap = remoteChapters.associateBy { it.url }
|
||||||
val mergedChapterMap = mutableMapOf<String, BackupChapter>()
|
|
||||||
|
|
||||||
localChapterMap.forEach { (url, localChapter) ->
|
// Merge both chapter maps
|
||||||
|
return (localChapterMap.keys + remoteChapterMap.keys).mapNotNull { url ->
|
||||||
|
// Determine the most recent chapter by comparing lastModifiedAt, considering null as Instant.MIN
|
||||||
|
val localChapter = localChapterMap[url]
|
||||||
val remoteChapter = remoteChapterMap[url]
|
val remoteChapter = remoteChapterMap[url]
|
||||||
if (remoteChapter != null) {
|
|
||||||
val localInstant = localChapter.lastModifiedAt.let { Instant.ofEpochMilli(it) }
|
|
||||||
val remoteInstant = remoteChapter.lastModifiedAt.let { Instant.ofEpochMilli(it) }
|
|
||||||
|
|
||||||
val mergedChapter =
|
when {
|
||||||
if (localInstant > remoteInstant) {
|
localChapter != null && remoteChapter == null -> localChapter
|
||||||
localChapter
|
localChapter == null && remoteChapter != null -> remoteChapter
|
||||||
} else {
|
localChapter != null && remoteChapter != null -> {
|
||||||
remoteChapter
|
val localInstant = localChapter.lastModifiedAt.let { Instant.ofEpochMilli(it) } ?: Instant.MIN
|
||||||
|
val remoteInstant = remoteChapter.lastModifiedAt.let { Instant.ofEpochMilli(it) } ?: Instant.MIN
|
||||||
|
if (localInstant >= remoteInstant) localChapter else remoteChapter
|
||||||
}
|
}
|
||||||
mergedChapterMap[url] = mergedChapter
|
else -> null
|
||||||
} else {
|
|
||||||
mergedChapterMap[url] = localChapter
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
remoteChapterMap.forEach { (url, remoteChapter) ->
|
|
||||||
if (!mergedChapterMap.containsKey(url)) {
|
|
||||||
mergedChapterMap[url] = remoteChapter
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return mergedChapterMap.values.toList()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user