Refresh tracks before updating progress

Closes #1652

Also removes the ability to trigger refreshes for the entire library or
as part of a library update as it should no longer be needed. Opening
the tracking sheet already refreshes the data too, so stale data is
irrelevant there.

Also closes #4775 since it would no longer be relevant.
This commit is contained in:
arkon 2023-10-21 10:04:29 -04:00
parent e1b3345b94
commit 489d22720a
8 changed files with 16 additions and 82 deletions

View File

@ -2,6 +2,7 @@ package eu.kanade.domain.track.interactor
import android.content.Context import android.content.Context
import eu.kanade.domain.track.model.toDbTrack import eu.kanade.domain.track.model.toDbTrack
import eu.kanade.domain.track.model.toDomainTrack
import eu.kanade.domain.track.service.DelayedTrackingUpdateJob import eu.kanade.domain.track.service.DelayedTrackingUpdateJob
import eu.kanade.domain.track.store.DelayedTrackingStore import eu.kanade.domain.track.store.DelayedTrackingStore
import eu.kanade.tachiyomi.data.track.TrackerManager import eu.kanade.tachiyomi.data.track.TrackerManager
@ -31,14 +32,17 @@ class TrackChapter(
return@mapNotNull null return@mapNotNull null
} }
val updatedTrack = track.copy(lastChapterRead = chapterNumber)
async { async {
runCatching { runCatching {
try { try {
val updatedTrack = service.refresh(track.toDbTrack())
.toDomainTrack(idRequired = true)!!
.copy(lastChapterRead = chapterNumber)
service.update(updatedTrack.toDbTrack(), true) service.update(updatedTrack.toDbTrack(), true)
insertTrack.await(updatedTrack) insertTrack.await(updatedTrack)
delayedTrackingStore.remove(track.id)
} catch (e: Exception) { } catch (e: Exception) {
delayedTrackingStore.addItem(updatedTrack) delayedTrackingStore.add(track.id, chapterNumber)
DelayedTrackingUpdateJob.setupTask(context) DelayedTrackingUpdateJob.setupTask(context)
throw e throw e
} }

View File

@ -8,21 +8,19 @@ import androidx.work.ExistingWorkPolicy
import androidx.work.NetworkType import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequestBuilder import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import eu.kanade.domain.track.model.toDbTrack import eu.kanade.domain.track.interactor.TrackChapter
import eu.kanade.domain.track.store.DelayedTrackingStore import eu.kanade.domain.track.store.DelayedTrackingStore
import eu.kanade.tachiyomi.data.track.TrackerManager
import eu.kanade.tachiyomi.util.system.workManager import eu.kanade.tachiyomi.util.system.workManager
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.util.lang.withIOContext import tachiyomi.core.util.lang.withIOContext
import tachiyomi.core.util.system.logcat import tachiyomi.core.util.system.logcat
import tachiyomi.domain.track.interactor.GetTracks import tachiyomi.domain.track.interactor.GetTracks
import tachiyomi.domain.track.interactor.InsertTrack
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import kotlin.time.Duration.Companion.minutes import kotlin.time.Duration.Companion.minutes
import kotlin.time.toJavaDuration import kotlin.time.toJavaDuration
class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters) : class DelayedTrackingUpdateJob(private val context: Context, workerParams: WorkerParameters) :
CoroutineWorker(context, workerParams) { CoroutineWorker(context, workerParams) {
override suspend fun doWork(): Result { override suspend fun doWork(): Result {
@ -31,9 +29,8 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters)
} }
val getTracks = Injekt.get<GetTracks>() val getTracks = Injekt.get<GetTracks>()
val insertTrack = Injekt.get<InsertTrack>() val trackChapter = Injekt.get<TrackChapter>()
val trackerManager = Injekt.get<TrackerManager>()
val delayedTrackingStore = Injekt.get<DelayedTrackingStore>() val delayedTrackingStore = Injekt.get<DelayedTrackingStore>()
withIOContext { withIOContext {
@ -46,17 +43,8 @@ class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters)
track?.copy(lastChapterRead = it.lastChapterRead.toDouble()) track?.copy(lastChapterRead = it.lastChapterRead.toDouble())
} }
.forEach { track -> .forEach { track ->
try { logcat(LogPriority.DEBUG) { "Updating delayed track item: ${track.mangaId}, last chapter read: ${track.lastChapterRead}" }
val service = trackerManager.get(track.syncId) trackChapter.await(context, track.mangaId, track.lastChapterRead)
if (service != null && service.isLoggedIn) {
logcat(LogPriority.DEBUG) { "Updating delayed track item: ${track.id}, last chapter read: ${track.lastChapterRead}" }
service.update(track.toDbTrack(), true)
insertTrack.await(track)
}
delayedTrackingStore.remove(track.id)
} catch (e: Exception) {
logcat(LogPriority.ERROR, e)
}
} }
} }

View File

@ -4,7 +4,6 @@ import android.content.Context
import androidx.core.content.edit import androidx.core.content.edit
import logcat.LogPriority import logcat.LogPriority
import tachiyomi.core.util.system.logcat import tachiyomi.core.util.system.logcat
import tachiyomi.domain.track.model.Track
class DelayedTrackingStore(context: Context) { class DelayedTrackingStore(context: Context) {
@ -13,13 +12,12 @@ class DelayedTrackingStore(context: Context) {
*/ */
private val preferences = context.getSharedPreferences("tracking_queue", Context.MODE_PRIVATE) private val preferences = context.getSharedPreferences("tracking_queue", Context.MODE_PRIVATE)
fun addItem(track: Track) { fun add(trackId: Long, lastChapterRead: Double) {
val trackId = track.id.toString() val previousLastChapterRead = preferences.getFloat(trackId.toString(), 0f)
val lastChapterRead = preferences.getFloat(trackId, 0f) if (lastChapterRead > previousLastChapterRead) {
if (track.lastChapterRead > lastChapterRead) { logcat(LogPriority.DEBUG) { "Queuing track item: $trackId, last chapter read: $lastChapterRead" }
logcat(LogPriority.DEBUG) { "Queuing track item: $trackId, last chapter read: ${track.lastChapterRead}" }
preferences.edit { preferences.edit {
putFloat(trackId, track.lastChapterRead.toFloat()) putFloat(trackId.toString(), lastChapterRead.toFloat())
} }
} }
} }

View File

@ -34,7 +34,6 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.cache.ChapterCache import eu.kanade.tachiyomi.data.cache.ChapterCache
import eu.kanade.tachiyomi.data.download.DownloadCache import eu.kanade.tachiyomi.data.download.DownloadCache
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.track.TrackerManager
import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.network.NetworkHelper
import eu.kanade.tachiyomi.network.NetworkPreferences import eu.kanade.tachiyomi.network.NetworkPreferences
import eu.kanade.tachiyomi.network.PREF_DOH_360 import eu.kanade.tachiyomi.network.PREF_DOH_360
@ -328,7 +327,6 @@ object SettingsAdvancedScreen : SearchableSettings {
private fun getLibraryGroup(): Preference.PreferenceGroup { private fun getLibraryGroup(): Preference.PreferenceGroup {
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val context = LocalContext.current val context = LocalContext.current
val trackerManager = remember { Injekt.get<TrackerManager>() }
return Preference.PreferenceGroup( return Preference.PreferenceGroup(
title = stringResource(R.string.label_library), title = stringResource(R.string.label_library),
@ -337,12 +335,6 @@ object SettingsAdvancedScreen : SearchableSettings {
title = stringResource(R.string.pref_refresh_library_covers), title = stringResource(R.string.pref_refresh_library_covers),
onClick = { LibraryUpdateJob.startNow(context, target = LibraryUpdateJob.Target.COVERS) }, onClick = { LibraryUpdateJob.startNow(context, target = LibraryUpdateJob.Target.COVERS) },
), ),
Preference.PreferenceItem.TextPreference(
title = stringResource(R.string.pref_refresh_library_tracking),
subtitle = stringResource(R.string.pref_refresh_library_tracking_summary),
enabled = trackerManager.hasLoggedIn(),
onClick = { LibraryUpdateJob.startNow(context, target = LibraryUpdateJob.Target.TRACKING) },
),
Preference.PreferenceItem.TextPreference( Preference.PreferenceItem.TextPreference(
title = stringResource(R.string.pref_reset_viewer_flags), title = stringResource(R.string.pref_reset_viewer_flags),
subtitle = stringResource(R.string.pref_reset_viewer_flags_summary), subtitle = stringResource(R.string.pref_reset_viewer_flags_summary),

View File

@ -23,7 +23,6 @@ import eu.kanade.presentation.more.settings.Preference
import eu.kanade.presentation.more.settings.widget.TriStateListDialog import eu.kanade.presentation.more.settings.widget.TriStateListDialog
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.library.LibraryUpdateJob import eu.kanade.tachiyomi.data.library.LibraryUpdateJob
import eu.kanade.tachiyomi.data.track.TrackerManager
import eu.kanade.tachiyomi.ui.category.CategoryScreen import eu.kanade.tachiyomi.ui.category.CategoryScreen
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
@ -197,12 +196,6 @@ object SettingsLibraryScreen : SearchableSettings {
title = stringResource(R.string.pref_library_update_refresh_metadata), title = stringResource(R.string.pref_library_update_refresh_metadata),
subtitle = stringResource(R.string.pref_library_update_refresh_metadata_summary), subtitle = stringResource(R.string.pref_library_update_refresh_metadata_summary),
), ),
Preference.PreferenceItem.SwitchPreference(
pref = libraryPreferences.autoUpdateTrackers(),
enabled = Injekt.get<TrackerManager>().hasLoggedIn(),
title = stringResource(R.string.pref_library_update_refresh_trackers),
subtitle = stringResource(R.string.pref_library_update_refresh_trackers_summary),
),
Preference.PreferenceItem.MultiSelectListPreference( Preference.PreferenceItem.MultiSelectListPreference(
pref = libraryPreferences.autoUpdateMangaRestrictions(), pref = libraryPreferences.autoUpdateMangaRestrictions(),
title = stringResource(R.string.pref_library_update_manga_restriction), title = stringResource(R.string.pref_library_update_manga_restriction),

View File

@ -18,7 +18,6 @@ import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.interactor.UpdateManga
import eu.kanade.domain.manga.model.copyFrom import eu.kanade.domain.manga.model.copyFrom
import eu.kanade.domain.manga.model.toSManga import eu.kanade.domain.manga.model.toSManga
import eu.kanade.domain.track.interactor.RefreshTracks
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
@ -89,7 +88,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
private val updateManga: UpdateManga = Injekt.get() private val updateManga: UpdateManga = Injekt.get()
private val getCategories: GetCategories = Injekt.get() private val getCategories: GetCategories = Injekt.get()
private val syncChaptersWithSource: SyncChaptersWithSource = Injekt.get() private val syncChaptersWithSource: SyncChaptersWithSource = Injekt.get()
private val refreshTracks: RefreshTracks = Injekt.get()
private val fetchInterval: FetchInterval = Injekt.get() private val fetchInterval: FetchInterval = Injekt.get()
private val notifier = LibraryUpdateNotifier(context) private val notifier = LibraryUpdateNotifier(context)
@ -131,7 +129,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
when (target) { when (target) {
Target.CHAPTERS -> updateChapterList() Target.CHAPTERS -> updateChapterList()
Target.COVERS -> updateCovers() Target.COVERS -> updateCovers()
Target.TRACKING -> updateTrackings()
} }
Result.success() Result.success()
} catch (e: Exception) { } catch (e: Exception) {
@ -304,10 +301,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
} }
failedUpdates.add(manga to errorMessage) failedUpdates.add(manga to errorMessage)
} }
if (libraryPreferences.autoUpdateTrackers().get()) {
refreshTracks(manga.id)
}
} }
} }
} }
@ -409,33 +402,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
notifier.cancelProgressNotification() notifier.cancelProgressNotification()
} }
/**
* Method that updates the metadata of the connected tracking services. It's called in a
* background thread, so it's safe to do heavy operations or network calls here.
*/
private suspend fun updateTrackings() {
coroutineScope {
var progressCount = 0
mangaToUpdate.forEach { libraryManga ->
ensureActive()
val manga = libraryManga.manga
notifier.showProgressNotification(listOf(manga), progressCount++, mangaToUpdate.size)
refreshTracks(manga.id)
}
notifier.cancelProgressNotification()
}
}
private suspend fun refreshTracks(mangaId: Long) {
refreshTracks.await(mangaId).forEach { (_, e) ->
// Ignore errors and continue
logcat(LogPriority.ERROR, e)
}
}
private suspend fun withUpdateNotification( private suspend fun withUpdateNotification(
updatingManga: CopyOnWriteArrayList<Manga>, updatingManga: CopyOnWriteArrayList<Manga>,
completed: AtomicInteger, completed: AtomicInteger,
@ -500,7 +466,6 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet
enum class Target { enum class Target {
CHAPTERS, // Manga chapters CHAPTERS, // Manga chapters
COVERS, // Manga covers COVERS, // Manga covers
TRACKING, // Tracking metadata
} }
companion object { companion object {

View File

@ -50,8 +50,6 @@ class LibraryPreferences(
fun autoUpdateMetadata() = preferenceStore.getBoolean("auto_update_metadata", false) fun autoUpdateMetadata() = preferenceStore.getBoolean("auto_update_metadata", false)
fun autoUpdateTrackers() = preferenceStore.getBoolean("auto_update_trackers", false)
fun showContinueReadingButton() = preferenceStore.getBoolean( fun showContinueReadingButton() = preferenceStore.getBoolean(
"display_continue_reading_button", "display_continue_reading_button",
false, false,

View File

@ -265,8 +265,6 @@
<string name="pref_library_update_refresh_metadata">Automatically refresh metadata</string> <string name="pref_library_update_refresh_metadata">Automatically refresh metadata</string>
<string name="pref_library_update_refresh_metadata_summary">Check for new cover and details when updating library</string> <string name="pref_library_update_refresh_metadata_summary">Check for new cover and details when updating library</string>
<string name="pref_library_update_refresh_trackers">Automatically refresh trackers</string>
<string name="pref_library_update_refresh_trackers_summary">Update trackers when updating library</string>
<string name="default_category">Default category</string> <string name="default_category">Default category</string>
<string name="default_category_summary">Always ask</string> <string name="default_category_summary">Always ask</string>
@ -538,8 +536,6 @@
<string name="pref_clear_webview_data">Clear WebView data</string> <string name="pref_clear_webview_data">Clear WebView data</string>
<string name="webview_data_deleted">WebView data cleared</string> <string name="webview_data_deleted">WebView data cleared</string>
<string name="pref_refresh_library_covers">Refresh library covers</string> <string name="pref_refresh_library_covers">Refresh library covers</string>
<string name="pref_refresh_library_tracking">Refresh tracking</string>
<string name="pref_refresh_library_tracking_summary">Updates status, score and last chapter read from the tracking services</string>
<string name="pref_reset_viewer_flags">Reset per-series reader settings</string> <string name="pref_reset_viewer_flags">Reset per-series reader settings</string>
<string name="pref_reset_viewer_flags_summary">Resets reading mode and orientation of all series</string> <string name="pref_reset_viewer_flags_summary">Resets reading mode and orientation of all series</string>
<string name="pref_reset_viewer_flags_success">All reader settings reset</string> <string name="pref_reset_viewer_flags_success">All reader settings reset</string>