Reading while offline will update trackers once back online

This commit is contained in:
Jays2Kings 2021-07-03 21:20:26 -04:00
parent bb3168cdb1
commit 6224dc293f
4 changed files with 103 additions and 7 deletions

View File

@ -90,6 +90,8 @@ object PreferenceKeys {
const val autoAddTrack = "pref_auto_add_track_key"
const val trackingsToAddOnline = "pref_tracking_for_online"
const val lastUsedCatalogueSource = "last_catalogue_source"
const val lastUsedCategory = "last_used_category"

View File

@ -194,6 +194,8 @@ class PreferencesHelper(val context: Context) {
fun autoAddTrack() = prefs.getBoolean(Keys.autoAddTrack, true)
fun trackingsToAddOnline() = flowPrefs.getStringSet(Keys.trackingsToAddOnline, emptySet())
fun lastUsedCatalogueSource() = flowPrefs.getLong(Keys.lastUsedCatalogueSource, -1)
fun lastUsedCategory() = rxPrefs.getInteger(Keys.lastUsedCategory, 0)

View File

@ -0,0 +1,80 @@
package eu.kanade.tachiyomi.data.track
import android.content.Context
import androidx.work.BackoffPolicy
import androidx.work.Constraints
import androidx.work.CoroutineWorker
import androidx.work.ExistingWorkPolicy
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.WorkManager
import androidx.work.WorkerParameters
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.concurrent.TimeUnit
class DelayedTrackingUpdateJob(context: Context, workerParams: WorkerParameters) :
CoroutineWorker(context, workerParams) {
override suspend fun doWork(): Result {
val preferences = Injekt.get<PreferencesHelper>()
val db = Injekt.get<DatabaseHelper>()
val trackManager = Injekt.get<TrackManager>()
val trackings = preferences.trackingsToAddOnline().get().toMutableSet().mapNotNull {
val items = it.split(":")
if (items.size != 3) {
null
} else {
val mangaId = items[0].toLongOrNull() ?: return@mapNotNull null
val trackId = items[1].toIntOrNull() ?: return@mapNotNull null
val chapterNumber = items[2].toIntOrNull() ?: return@mapNotNull null
mangaId to (trackId to chapterNumber)
}
}.groupBy { it.first }
withContext(Dispatchers.IO) {
trackings.forEach {
val mangaId = it.key
val manga = db.getManga(mangaId).executeAsBlocking() ?: return@withContext
val trackList = db.getTracks(manga).executeAsBlocking()
it.value.map { tC ->
val trackChapter = tC.second
val service = trackManager.getService(trackChapter.first)
val track = trackList.find { track -> track.sync_id == trackChapter.first }
if (service != null && track != null) {
try {
track.last_chapter_read = trackChapter.second
service.update(track, true)
db.insertTrack(track).executeAsBlocking()
} catch (e: Exception) {
Timber.e(e)
}
}
}
}
preferences.trackingsToAddOnline().set(emptySet())
}
return Result.success()
}
companion object {
private const val TAG = "DelayedTrackingUpdate"
fun setupTask(context: Context) {
val constraints =
Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build()
val request = OneTimeWorkRequestBuilder<DelayedTrackingUpdateJob>()
.setConstraints(constraints)
.setBackoffCriteria(BackoffPolicy.EXPONENTIAL, 20, TimeUnit.SECONDS)
.addTag(TAG)
.build()
WorkManager.getInstance(context)
.enqueueUniqueWork(TAG, ExistingWorkPolicy.REPLACE, request)
}
}
}

View File

@ -18,6 +18,7 @@ import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.data.track.DelayedTrackingUpdateJob
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.SourceManager
@ -34,6 +35,7 @@ import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
import eu.kanade.tachiyomi.util.storage.DiskUtil
import eu.kanade.tachiyomi.util.system.ImageUtil
import eu.kanade.tachiyomi.util.system.executeOnIO
import eu.kanade.tachiyomi.util.system.isOnline
import eu.kanade.tachiyomi.util.system.launchUI
import eu.kanade.tachiyomi.util.system.withUIContext
import kotlinx.coroutines.CoroutineScope
@ -858,13 +860,22 @@ class ReaderPresenter(
val trackManager = Injekt.get<TrackManager>()
// We wan't these to execute even if the presenter is destroyed so launch on GlobalScope
// We want these to execute even if the presenter is destroyed so launch on GlobalScope
GlobalScope.launch {
withContext(Dispatchers.IO) {
val trackList = db.getTracks(manga).executeAsBlocking()
trackList.map { track ->
val service = trackManager.getService(track.sync_id)
if (service != null && service.isLogged && chapterRead > track.last_chapter_read) {
if (!preferences.context.isOnline()) {
val mangaId = manga.id ?: return@map
val trackings = preferences.trackingsToAddOnline().get().toMutableSet()
val currentTracking = trackings.find { it.startsWith("$mangaId:${track.sync_id}:") }
trackings.remove(currentTracking)
trackings.add("$mangaId:${track.sync_id}:$chapterRead")
preferences.trackingsToAddOnline().set(trackings)
DelayedTrackingUpdateJob.setupTask(preferences.context)
} else {
try {
track.last_chapter_read = chapterRead
service.update(track, true)
@ -877,6 +888,7 @@ class ReaderPresenter(
}
}
}
}
/**
* Enqueues this [chapter] to be deleted when [deletePendingChapters] is called. The download