More fixes to the library update service
Restored the claim that it still shows a notifcation when cancelling the update
This commit is contained in:
parent
c88fc38238
commit
8e8cbbca3b
@ -25,19 +25,23 @@ import eu.kanade.tachiyomi.data.backup.models.Backup.TRACK
|
|||||||
import eu.kanade.tachiyomi.data.backup.models.Backup.VERSION
|
import eu.kanade.tachiyomi.data.backup.models.Backup.VERSION
|
||||||
import eu.kanade.tachiyomi.data.backup.models.DHistory
|
import eu.kanade.tachiyomi.data.backup.models.DHistory
|
||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.*
|
import eu.kanade.tachiyomi.data.database.models.ChapterImpl
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.MangaImpl
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.Track
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.TrackImpl
|
||||||
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||||
import eu.kanade.tachiyomi.data.notification.Notifications
|
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
import eu.kanade.tachiyomi.source.SourceNotFoundException
|
import eu.kanade.tachiyomi.source.SourceNotFoundException
|
||||||
import eu.kanade.tachiyomi.util.lang.chop
|
import eu.kanade.tachiyomi.util.lang.chop
|
||||||
import eu.kanade.tachiyomi.util.storage.getUriCompat
|
import eu.kanade.tachiyomi.util.storage.getUriCompat
|
||||||
|
import eu.kanade.tachiyomi.util.system.isServiceRunning
|
||||||
import eu.kanade.tachiyomi.util.system.notificationManager
|
import eu.kanade.tachiyomi.util.system.notificationManager
|
||||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import eu.kanade.tachiyomi.util.system.isServiceRunning
|
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@ -147,9 +151,7 @@ class BackupRestoreService : Service() {
|
|||||||
* @return the start value of the command.
|
* @return the start value of the command.
|
||||||
*/
|
*/
|
||||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||||
if (intent == null) return START_NOT_STICKY
|
val uri = intent?.getParcelableExtra<Uri>(BackupConst.EXTRA_URI) ?: return START_NOT_STICKY
|
||||||
|
|
||||||
val uri = intent.getParcelableExtra<Uri>(BackupConst.EXTRA_URI) ?: return START_NOT_STICKY
|
|
||||||
|
|
||||||
// Unsubscribe from any previous subscription if needed.
|
// Unsubscribe from any previous subscription if needed.
|
||||||
job?.cancel()
|
job?.cancel()
|
||||||
@ -159,7 +161,7 @@ class BackupRestoreService : Service() {
|
|||||||
stopSelf(startId)
|
stopSelf(startId)
|
||||||
}
|
}
|
||||||
job = GlobalScope.launch(handler) {
|
job = GlobalScope.launch(handler) {
|
||||||
restoreBackup(uri!!)
|
restoreBackup(uri)
|
||||||
}
|
}
|
||||||
job?.invokeOnCompletion { stopSelf(startId) }
|
job?.invokeOnCompletion { stopSelf(startId) }
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ import eu.kanade.tachiyomi.R
|
|||||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||||
import eu.kanade.tachiyomi.data.database.models.Category
|
import eu.kanade.tachiyomi.data.database.models.Category
|
||||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||||
|
import eu.kanade.tachiyomi.data.database.models.ChapterImpl
|
||||||
import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
import eu.kanade.tachiyomi.data.database.models.LibraryManga
|
||||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||||
import eu.kanade.tachiyomi.data.database.models.MangaImpl
|
import eu.kanade.tachiyomi.data.database.models.MangaImpl
|
||||||
@ -31,7 +32,6 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
|||||||
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||||
@ -104,7 +104,7 @@ class LibraryUpdateService(
|
|||||||
private val categoryIds = mutableSetOf<Int>()
|
private val categoryIds = mutableSetOf<Int>()
|
||||||
|
|
||||||
// List containing new updates
|
// List containing new updates
|
||||||
private val newUpdates = ArrayList<Pair<LibraryManga, Array<Chapter>>>()
|
private val newUpdates = mutableMapOf<LibraryManga, Array<Chapter>>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cached progress notification to avoid creating a lot.
|
* Cached progress notification to avoid creating a lot.
|
||||||
@ -187,6 +187,7 @@ class LibraryUpdateService(
|
|||||||
* @param context the application context.
|
* @param context the application context.
|
||||||
*/
|
*/
|
||||||
fun stop(context: Context) {
|
fun stop(context: Context) {
|
||||||
|
instance?.job?.cancel()
|
||||||
context.stopService(Intent(context, LibraryUpdateService::class.java))
|
context.stopService(Intent(context, LibraryUpdateService::class.java))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -329,15 +330,7 @@ class LibraryUpdateService(
|
|||||||
private fun updateChapters(mangaToAdd: List<LibraryManga>, startId: Int) {
|
private fun updateChapters(mangaToAdd: List<LibraryManga>, startId: Int) {
|
||||||
val handler = CoroutineExceptionHandler { _, exception ->
|
val handler = CoroutineExceptionHandler { _, exception ->
|
||||||
Timber.e(exception)
|
Timber.e(exception)
|
||||||
|
|
||||||
// Boolean to determine if user wants to automatically download new chapters.
|
// Boolean to determine if user wants to automatically download new chapters.
|
||||||
val downloadNew = preferences.downloadNew().getOrDefault()
|
|
||||||
if (newUpdates.isNotEmpty()) {
|
|
||||||
showResultNotification(newUpdates)
|
|
||||||
if (downloadNew && downloadManager.queue.isNotEmpty()) {
|
|
||||||
DownloadService.start(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
stopSelf(startId)
|
stopSelf(startId)
|
||||||
}
|
}
|
||||||
job = GlobalScope.launch(handler) {
|
job = GlobalScope.launch(handler) {
|
||||||
@ -347,52 +340,41 @@ class LibraryUpdateService(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun updateChaptersJob(mangaToAdd: List<LibraryManga>) {
|
private suspend fun updateChaptersJob(mangaToAdd: List<LibraryManga>) {
|
||||||
// list containing failed updates
|
|
||||||
val failedUpdates = ArrayList<Manga>()
|
|
||||||
// List containing categories that get included in downloads.
|
// List containing categories that get included in downloads.
|
||||||
val categoriesToDownload = preferences.downloadNewCategories().getOrDefault().map(String::toInt)
|
val categoriesToDownload = preferences.downloadNewCategories().getOrDefault().map(String::toInt)
|
||||||
// Boolean to determine if user wants to automatically download new chapters.
|
// Boolean to determine if user wants to automatically download new chapters.
|
||||||
val downloadNew = preferences.downloadNew().getOrDefault()
|
val downloadNew = preferences.downloadNew().getOrDefault()
|
||||||
// Boolean to determine if DownloadManager has downloads
|
// Boolean to determine if DownloadManager has downloads
|
||||||
var hasDownloads = false
|
var hasDownloads = false
|
||||||
withContext(Dispatchers.IO) {
|
val fakeM = LibraryManga()
|
||||||
// Initialize the variables holding the progress of the updates.
|
fakeM.title = "Test"
|
||||||
var count = 0
|
fakeM.favorite = true
|
||||||
|
fakeM.id = -12
|
||||||
|
fakeM.initialized = true
|
||||||
|
fakeM.url = ""
|
||||||
|
val fakeC = ChapterImpl()
|
||||||
|
fakeC.chapter_number = 1.0f
|
||||||
|
fakeC.name = "Chapter Test"
|
||||||
|
fakeC.id = -15
|
||||||
|
fakeC.url = ""
|
||||||
|
newUpdates[fakeM] = arrayOf<Chapter>(fakeC)
|
||||||
|
// Initialize the variables holding the progress of the updates.
|
||||||
|
var count = 0
|
||||||
|
|
||||||
mangaToUpdate.addAll(mangaToAdd)
|
mangaToUpdate.addAll(mangaToAdd)
|
||||||
while (count < mangaToUpdate.size) {
|
while (count < mangaToUpdate.size) {
|
||||||
if (job?.isCancelled == true) break
|
val shouldDownload = (downloadNew && (categoriesToDownload.isEmpty() ||
|
||||||
val manga = mangaToUpdate[count]
|
mangaToUpdate[count].category in categoriesToDownload))
|
||||||
showProgressNotification(manga, count++, mangaToUpdate.size)
|
if (updateMangaChapters(mangaToUpdate[count], count, shouldDownload)) {
|
||||||
val source = sourceManager.get(manga.source) as? HttpSource ?: continue
|
hasDownloads = true
|
||||||
val fetchedChapters = try {
|
|
||||||
source.fetchChapterList(manga).toBlocking().single()
|
|
||||||
} catch (e: java.lang.Exception) {
|
|
||||||
failedUpdates.add(manga)
|
|
||||||
emptyList<SChapter>()
|
|
||||||
} ?: emptyList()
|
|
||||||
if (fetchedChapters.isNotEmpty()) {
|
|
||||||
val newChapters = syncChaptersWithSource(db, fetchedChapters, manga, source)
|
|
||||||
if (newChapters.first.isNotEmpty()) {
|
|
||||||
if (downloadNew && (categoriesToDownload.isEmpty() || manga.category in categoriesToDownload)) {
|
|
||||||
downloadChapters(
|
|
||||||
manga,
|
|
||||||
newChapters.first.sortedBy { it.chapter_number })
|
|
||||||
hasDownloads = true
|
|
||||||
}
|
|
||||||
newUpdates.add(manga to newChapters.first.sortedBy { it.chapter_number }.toTypedArray())
|
|
||||||
}
|
|
||||||
if (newChapters.first.size + newChapters.second.size > 0) listener?.onUpdateManga(
|
|
||||||
manga
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
count++
|
||||||
}
|
}
|
||||||
if (newUpdates.isNotEmpty()) {
|
if (newUpdates.isNotEmpty()) {
|
||||||
showResultNotification(newUpdates)
|
showResultNotification(newUpdates)
|
||||||
|
|
||||||
if (preferences.refreshCoversToo().getOrDefault()) {
|
if (preferences.refreshCoversToo().getOrDefault() && job?.isCancelled == false) {
|
||||||
updateDetails(newUpdates.map { it.first }).observeOn(Schedulers.io())
|
updateDetails(newUpdates.map { it.key }).observeOn(Schedulers.io())
|
||||||
.doOnCompleted {
|
.doOnCompleted {
|
||||||
cancelProgressNotification()
|
cancelProgressNotification()
|
||||||
if (downloadNew && hasDownloads) {
|
if (downloadNew && hasDownloads) {
|
||||||
@ -406,13 +388,43 @@ class LibraryUpdateService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (failedUpdates.isNotEmpty()) {
|
|
||||||
Timber.e("Failed updating: ${failedUpdates.map { it.title }}")
|
|
||||||
}
|
|
||||||
|
|
||||||
cancelProgressNotification()
|
cancelProgressNotification()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun updateMangaChapters(manga: LibraryManga, progess: Int, shouldDownload: Boolean):
|
||||||
|
Boolean {
|
||||||
|
try {
|
||||||
|
var hasDownloads = false
|
||||||
|
if (job?.isCancelled == true) {
|
||||||
|
throw java.lang.Exception("Job was cancelled")
|
||||||
|
}
|
||||||
|
showProgressNotification(manga, progess, mangaToUpdate.size)
|
||||||
|
val source = sourceManager.get(manga.source) as? HttpSource ?: return false
|
||||||
|
val fetchedChapters = withContext(Dispatchers.IO) {
|
||||||
|
source.fetchChapterList(manga).toBlocking().single()
|
||||||
|
} ?: emptyList()
|
||||||
|
if (fetchedChapters.isNotEmpty()) {
|
||||||
|
val newChapters = syncChaptersWithSource(db, fetchedChapters, manga, source)
|
||||||
|
if (newChapters.first.isNotEmpty()) {
|
||||||
|
if (shouldDownload) {
|
||||||
|
downloadChapters(manga, newChapters.first.sortedBy { it.chapter_number })
|
||||||
|
hasDownloads = true
|
||||||
|
}
|
||||||
|
newUpdates[manga] =
|
||||||
|
newChapters.first.sortedBy { it.chapter_number }.toTypedArray()
|
||||||
|
}
|
||||||
|
if (newChapters.first.size + newChapters.second.size > 0) listener?.onUpdateManga(
|
||||||
|
manga
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return hasDownloads
|
||||||
|
}
|
||||||
|
catch (e: Exception) {
|
||||||
|
Timber.e("Failed updating: ${manga.title}: $e")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun downloadChapters(manga: Manga, chapters: List<Chapter>) {
|
fun downloadChapters(manga: Manga, chapters: List<Chapter>) {
|
||||||
// we need to get the chapters from the db so we have chapter ids
|
// we need to get the chapters from the db so we have chapter ids
|
||||||
val mangaChapters = db.getChapters(manga).executeAsBlocking()
|
val mangaChapters = db.getChapters(manga).executeAsBlocking()
|
||||||
@ -525,11 +537,11 @@ class LibraryUpdateService(
|
|||||||
*
|
*
|
||||||
* @param updates a list of manga with new updates.
|
* @param updates a list of manga with new updates.
|
||||||
*/
|
*/
|
||||||
private fun showResultNotification(updates: List<Pair<Manga, Array<Chapter>>>) {
|
private fun showResultNotification(updates: Map<LibraryManga, Array<Chapter>>) {
|
||||||
val notifications = ArrayList<Pair<Notification, Int>>()
|
val notifications = ArrayList<Pair<Notification, Int>>()
|
||||||
updates.forEach {
|
updates.forEach {
|
||||||
val manga = it.first
|
val manga = it.key
|
||||||
val chapters = it.second
|
val chapters = it.value
|
||||||
val chapterNames = chapters.map { chapter -> chapter.name }
|
val chapterNames = chapters.map { chapter -> chapter.name }
|
||||||
notifications.add(Pair(notification(Notifications.CHANNEL_NEW_CHAPTERS) {
|
notifications.add(Pair(notification(Notifications.CHANNEL_NEW_CHAPTERS) {
|
||||||
setSmallIcon(R.drawable.ic_tachi)
|
setSmallIcon(R.drawable.ic_tachi)
|
||||||
@ -578,12 +590,12 @@ class LibraryUpdateService(
|
|||||||
setContentText(resources.getQuantityString(R.plurals
|
setContentText(resources.getQuantityString(R.plurals
|
||||||
.notification_new_chapters_text,
|
.notification_new_chapters_text,
|
||||||
updates.size, updates.size))
|
updates.size, updates.size))
|
||||||
setStyle(NotificationCompat.BigTextStyle().bigText(updates.joinToString("\n") {
|
setStyle(NotificationCompat.BigTextStyle().bigText(updates.keys.joinToString("\n") {
|
||||||
it.first.currentTitle().chop(45)
|
it.currentTitle().chop(45)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
setContentText(updates.first().first.currentTitle().chop(45))
|
setContentText(updates.keys.first().currentTitle().chop(45))
|
||||||
}
|
}
|
||||||
priority = NotificationCompat.PRIORITY_HIGH
|
priority = NotificationCompat.PRIORITY_HIGH
|
||||||
setGroup(Notifications.GROUP_NEW_CHAPTERS)
|
setGroup(Notifications.GROUP_NEW_CHAPTERS)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user