Merge branch 'master' into sync-part-final

This commit is contained in:
KaiserBh 2024-01-03 00:45:44 +11:00 committed by GitHub
commit 7bd9c2f7c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 41 additions and 38 deletions

View File

@ -246,7 +246,7 @@ dependencies {
implementation(libs.logcat)
// Crash reports/analytics
implementation(libs.acra.http)
implementation(libs.bundles.acra)
"standardImplementation"(libs.firebase.analytics)
// Shizuku

View File

@ -22,7 +22,6 @@ import tachiyomi.domain.chapter.service.ChapterRecognition
import tachiyomi.domain.manga.model.Manga
import tachiyomi.source.local.isLocal
import java.lang.Long.max
import java.time.Instant
import java.time.ZonedDateTime
import java.util.TreeSet
@ -57,6 +56,7 @@ class SyncChaptersWithSource(
}
val now = ZonedDateTime.now()
val nowMillis = now.toInstant().toEpochMilli()
val sourceChapters = rawSourceChapters
.distinctBy { it.url }
@ -67,36 +67,27 @@ class SyncChaptersWithSource(
.copy(mangaId = manga.id, sourceOrder = i.toLong())
}
// Chapters from db.
val dbChapters = getChaptersByMangaId.await(manga.id)
// Chapters from the source not in db.
val toAdd = mutableListOf<Chapter>()
// Chapters whose metadata have changed.
val toChange = mutableListOf<Chapter>()
// Chapters from the db not in source.
val toDelete = dbChapters.filterNot { dbChapter ->
val newChapters = mutableListOf<Chapter>()
val updatedChapters = mutableListOf<Chapter>()
val removedChapters = dbChapters.filterNot { dbChapter ->
sourceChapters.any { sourceChapter ->
dbChapter.url == sourceChapter.url
}
}
val rightNow = Instant.now().toEpochMilli()
// Used to not set upload date of older chapters
// to a higher value than newer chapters
var maxSeenUploadDate = 0L
val sManga = manga.toSManga()
for (sourceChapter in sourceChapters) {
var chapter = sourceChapter
// Update metadata from source if necessary.
if (source is HttpSource) {
val sChapter = chapter.toSChapter()
source.prepareNewChapter(sChapter, sManga)
source.prepareNewChapter(sChapter, manga.toSManga())
chapter = chapter.copyFromSChapter(sChapter)
}
@ -108,13 +99,13 @@ class SyncChaptersWithSource(
if (dbChapter == null) {
val toAddChapter = if (chapter.dateUpload == 0L) {
val altDateUpload = if (maxSeenUploadDate == 0L) rightNow else maxSeenUploadDate
val altDateUpload = if (maxSeenUploadDate == 0L) nowMillis else maxSeenUploadDate
chapter.copy(dateUpload = altDateUpload)
} else {
maxSeenUploadDate = max(maxSeenUploadDate, sourceChapter.dateUpload)
chapter
}
toAdd.add(toAddChapter)
newChapters.add(toAddChapter)
} else {
if (shouldUpdateDbChapter.await(dbChapter, chapter)) {
val shouldRenameChapter = downloadProvider.isChapterDirNameChanged(dbChapter, chapter) &&
@ -134,13 +125,13 @@ class SyncChaptersWithSource(
if (chapter.dateUpload != 0L) {
toChangeChapter = toChangeChapter.copy(dateUpload = chapter.dateUpload)
}
toChange.add(toChangeChapter)
updatedChapters.add(toChangeChapter)
}
}
}
// Return if there's nothing to add, delete or change, avoiding unnecessary db transactions.
if (toAdd.isEmpty() && toDelete.isEmpty() && toChange.isEmpty()) {
// Return if there's nothing to add, delete, or update to avoid unnecessary db transactions.
if (newChapters.isEmpty() && removedChapters.isEmpty() && updatedChapters.isEmpty()) {
if (manualFetch || manga.fetchInterval == 0 || manga.nextUpdate < fetchWindow.first) {
updateManga.awaitUpdateFetchInterval(
manga,
@ -157,20 +148,20 @@ class SyncChaptersWithSource(
val deletedReadChapterNumbers = TreeSet<Double>()
val deletedBookmarkedChapterNumbers = TreeSet<Double>()
toDelete.forEach { chapter ->
removedChapters.forEach { chapter ->
if (chapter.read) deletedReadChapterNumbers.add(chapter.chapterNumber)
if (chapter.bookmark) deletedBookmarkedChapterNumbers.add(chapter.chapterNumber)
deletedChapterNumbers.add(chapter.chapterNumber)
}
val deletedChapterNumberDateFetchMap = toDelete.sortedByDescending { it.dateFetch }
val deletedChapterNumberDateFetchMap = removedChapters.sortedByDescending { it.dateFetch }
.associate { it.chapterNumber to it.dateFetch }
// Date fetch is set in such a way that the upper ones will have bigger value than the lower ones
// Sources MUST return the chapters from most to less recent, which is common.
var itemCount = toAdd.size
var updatedToAdd = toAdd.map { toAddItem ->
var chapter = toAddItem.copy(dateFetch = rightNow + itemCount--)
var itemCount = newChapters.size
var updatedToAdd = newChapters.map { toAddItem ->
var chapter = toAddItem.copy(dateFetch = nowMillis + itemCount--)
if (chapter.isRecognizedNumber.not() || chapter.chapterNumber !in deletedChapterNumbers) return@map chapter
@ -189,8 +180,8 @@ class SyncChaptersWithSource(
chapter
}
if (toDelete.isNotEmpty()) {
val toDeleteIds = toDelete.map { it.id }
if (removedChapters.isNotEmpty()) {
val toDeleteIds = removedChapters.map { it.id }
chapterRepository.removeChaptersWithIds(toDeleteIds)
}
@ -198,8 +189,8 @@ class SyncChaptersWithSource(
updatedToAdd = chapterRepository.addAll(updatedToAdd)
}
if (toChange.isNotEmpty()) {
val chapterUpdates = toChange.map { it.toChapterUpdate() }
if (updatedChapters.isNotEmpty()) {
val chapterUpdates = updatedChapters.map { it.toChapterUpdate() }
updateChapter.awaitAll(chapterUpdates)
}
updateManga.awaitUpdateFetchInterval(manga, now, fetchWindow)

View File

@ -77,7 +77,6 @@ fun SetIntervalDialog(
title = { Text(stringResource(MR.strings.manga_modify_calculated_interval_title)) },
text = {
Column {
// TODO: figure out why nextUpdate is a weird number sometimes
if (nextUpdateDays >= 0) {
Text(
stringResource(

View File

@ -3,6 +3,7 @@ package eu.kanade.tachiyomi
import android.annotation.SuppressLint
import android.app.Application
import android.app.PendingIntent
import android.app.job.JobInfo
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
@ -51,10 +52,12 @@ import logcat.AndroidLogcatLogger
import logcat.LogPriority
import logcat.LogcatLogger
import org.acra.config.httpSender
import org.acra.config.scheduler
import org.acra.ktx.initAcra
import org.acra.sender.HttpSender
import org.conscrypt.Conscrypt
import tachiyomi.core.i18n.stringResource
import tachiyomi.core.preference.Preference
import tachiyomi.core.util.system.logcat
import tachiyomi.i18n.MR
import tachiyomi.presentation.widget.WidgetManager
@ -199,12 +202,20 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
if (isPreviewBuildType || isReleaseBuildType) {
initAcra {
buildConfigClass = BuildConfig::class.java
excludeMatchingSharedPreferencesKeys = listOf(".*username.*", ".*password.*", ".*token.*")
excludeMatchingSharedPreferencesKeys = listOf(
Preference.privateKey(".*"), ".*username.*", ".*password.*", ".*token.*",
)
httpSender {
uri = BuildConfig.ACRA_URI
httpMethod = HttpSender.Method.PUT
}
scheduler {
requiresBatteryNotLow = true
requiresDeviceIdle = true
requiresNetworkType = JobInfo.NETWORK_TYPE_UNMETERED
}
}
}
}

View File

@ -19,16 +19,15 @@ class FetchInterval(
dateTime: ZonedDateTime,
window: Pair<Long, Long>,
): MangaUpdate? {
val interval = manga.fetchInterval.takeIf { it < 0 } ?: calculateInterval(
chapters = getChaptersByMangaId.await(manga.id, applyScanlatorFilter = true),
zone = dateTime.zone,
)
val currentWindow = if (window.first == 0L && window.second == 0L) {
getWindow(ZonedDateTime.now())
} else {
window
}
val chapters = getChaptersByMangaId.await(manga.id, applyScanlatorFilter = true)
val interval = manga.fetchInterval.takeIf { it < 0 } ?: calculateInterval(
chapters,
dateTime.zone,
)
val nextUpdate = calculateNextUpdate(manga, interval, dateTime, currentWindow)
return if (manga.nextUpdate == nextUpdate && manga.fetchInterval == interval) {
@ -102,7 +101,7 @@ class FetchInterval(
manga.fetchInterval == 0
) {
val latestDate = ZonedDateTime.ofInstant(
Instant.ofEpochMilli(manga.lastUpdate),
if (manga.lastUpdate > 0) Instant.ofEpochMilli(manga.lastUpdate) else Instant.now(),
dateTime.zone,
)
.toLocalDate()

View File

@ -1,5 +1,6 @@
[versions]
aboutlib_version = "10.10.0"
acra = "5.11.3"
leakcanary = "2.12"
moko = "0.23.0"
okhttp_version = "5.0.0-alpha.12"
@ -67,7 +68,8 @@ moko-gradle = { module = "dev.icerock.moko:resources-generator", version.ref = "
logcat = "com.squareup.logcat:logcat:0.1"
acra-http = "ch.acra:acra-http:5.11.3"
acra-http = { module = "ch.acra:acra-http", version.ref = "acra" }
acra-scheduler = { module = "ch.acra:acra-advanced-scheduler", version.ref = "acra" }
firebase-analytics = "com.google.firebase:firebase-analytics-ktx:21.5.0"
aboutLibraries-gradle = { module = "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin", version.ref = "aboutlib_version" }
@ -99,6 +101,7 @@ google-api-services-drive = "com.google.apis:google-api-services-drive:v3-rev197
google-api-client-oauth = "com.google.oauth-client:google-oauth-client:1.34.1"
[bundles]
acra = ["acra-http", "acra-scheduler"]
okhttp = ["okhttp-core", "okhttp-logging", "okhttp-brotli", "okhttp-dnsoverhttps"]
js-engine = ["quickjs-android"]
sqlite = ["sqlite-framework", "sqlite-ktx", "sqlite-android"]