fix(notifications): Revert parallelize downloads

This commit is contained in:
Quickdesh 2023-07-26 00:13:32 +05:30
parent 4ffae67048
commit 0c0bf51663
4 changed files with 36 additions and 86 deletions

View file

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.data.download.anime
import android.annotation.SuppressLint
import android.app.PendingIntent
import android.content.Context
import android.graphics.BitmapFactory
@ -12,8 +11,8 @@ import eu.kanade.tachiyomi.data.notification.NotificationHandler
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.util.lang.chop
import eu.kanade.tachiyomi.util.system.cancelNotification
import eu.kanade.tachiyomi.util.system.notificationBuilder
import eu.kanade.tachiyomi.util.system.notificationManager
import eu.kanade.tachiyomi.util.system.notify
import uy.kohesive.injekt.injectLazy
import java.util.regex.Pattern
@ -46,16 +45,6 @@ internal class AnimeDownloadNotifier(private val context: Context) {
*/
private var isDownloading = false
/**
* Updated when paused
*/
var paused = false
/**
* Map to store notification IDs for each download
*/
private val notificationIdMap: MutableMap<Long, Int> = mutableMapOf()
/**
* Shows a notification from this builder.
*
@ -69,10 +58,8 @@ internal class AnimeDownloadNotifier(private val context: Context) {
* Dismiss the downloader's notification. Downloader error notifications use a different id, so
* those can only be dismissed by the user.
*/
fun dismissProgress(download: AnimeDownload) {
val notificationId = notificationIdMap[download.episode.id] ?: return
context.cancelNotification(notificationId)
notificationIdMap.remove(download.episode.id)
fun dismissProgress() {
context.notificationManager.cancel(Notifications.ID_DOWNLOAD_EPISODE_PROGRESS)
}
/**
@ -80,12 +67,7 @@ internal class AnimeDownloadNotifier(private val context: Context) {
*
* @param download download object containing download information.
*/
@SuppressLint("RestrictedApi", "StringFormatInvalid")
fun onProgressChange(download: AnimeDownload) {
val notificationId = notificationIdMap.getOrPut(download.episode.id) {
download.episode.id.hashCode()
}
with(progressNotificationBuilder) {
if (!isDownloading) {
setSmallIcon(android.R.drawable.stat_sys_download)
@ -93,6 +75,12 @@ internal class AnimeDownloadNotifier(private val context: Context) {
// Open download manager when clicked
setContentIntent(NotificationHandler.openAnimeDownloadManagerPendingActivity(context))
isDownloading = true
// Pause action
addAction(
R.drawable.ic_pause_24dp,
context.getString(R.string.action_pause),
NotificationReceiver.pauseAnimeDownloadsPendingBroadcast(context),
)
}
val downloadingProgressText = if (download.totalProgress == 0) {
@ -118,28 +106,14 @@ internal class AnimeDownloadNotifier(private val context: Context) {
}
setOngoing(true)
show(notificationId)
}
// Add pause action if not already added
val pauseActionIntent = NotificationReceiver.pauseAnimeDownloadsPendingBroadcast(context)
val pauseActionAdded = progressNotificationBuilder.mActions.any { it.actionIntent == pauseActionIntent }
if (!paused && !pauseActionAdded) {
progressNotificationBuilder.addAction(
R.drawable.ic_pause_24dp,
context.getString(R.string.action_pause),
pauseActionIntent,
)
paused = true
show(Notifications.ID_DOWNLOAD_EPISODE_PROGRESS)
}
}
/**
* Show notification when download is paused.
*/
fun onPaused(download: AnimeDownload) {
val notificationId = notificationIdMap[download.episode.id] ?: return
fun onPaused() {
with(progressNotificationBuilder) {
setContentTitle(context.getString(R.string.download_paused))
setContentText(context.getString(R.string.download_notifier_download_paused_episodes))
@ -162,23 +136,21 @@ internal class AnimeDownloadNotifier(private val context: Context) {
NotificationReceiver.clearAnimeDownloadsPendingBroadcast(context),
)
show(notificationId)
show(Notifications.ID_DOWNLOAD_EPISODE_PROGRESS)
}
// Reset initial values
isDownloading = false
paused = false
}
/**
* Resets the state once downloads are completed.
*/
fun onComplete(download: AnimeDownload) {
dismissProgress(download)
fun onComplete() {
dismissProgress()
// Reset states to default
isDownloading = false
paused = false
}
/**
@ -198,7 +170,7 @@ internal class AnimeDownloadNotifier(private val context: Context) {
timeout?.let { setTimeoutAfter(it) }
contentIntent?.let { setContentIntent(it) }
show(Notifications.ID_DOWNLOAD_CHAPTER_ERROR)
show(Notifications.ID_DOWNLOAD_EPISODE_ERROR)
}
// Reset download information
@ -212,11 +184,7 @@ internal class AnimeDownloadNotifier(private val context: Context) {
* @param error string containing error information.
* @param episode string containing episode title.
*/
fun onError(download: AnimeDownload, error: String? = null, episode: String? = null, animeTitle: String? = null) {
val notificationId = notificationIdMap.getOrPut(download.episode.id) {
download.episode.id.hashCode()
}
fun onError(error: String? = null, episode: String? = null, animeTitle: String? = null) {
// Create notification
with(errorNotificationBuilder) {
setContentTitle(
@ -228,7 +196,7 @@ internal class AnimeDownloadNotifier(private val context: Context) {
setContentIntent(NotificationHandler.openAnimeDownloadManagerPendingActivity(context))
setProgress(0, 0, false)
show(notificationId)
show(Notifications.ID_DOWNLOAD_EPISODE_ERROR)
}
// Reset download information

View file

@ -4,7 +4,6 @@ import android.app.Notification
import android.app.Service
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.IBinder
import android.os.PowerManager
import androidx.annotation.StringRes
@ -90,14 +89,9 @@ class AnimeDownloadService : Service() {
override fun onCreate() {
scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
startForeground(Notifications.ID_DOWNLOAD_EPISODE_PROGRESS, getPlaceholderNotification())
wakeLock = acquireWakeLock(javaClass.name)
_isRunning.value = true
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForeground(1, getPlaceholderNotification())
} else {
@Suppress("DEPRECATION")
startForeground(1, Notification())
}
listenNetworkChanges()
}

View file

@ -160,20 +160,14 @@ class AnimeDownloader(
.forEach { it.status = AnimeDownload.State.ERROR }
if (reason != null) {
queueState.value.forEach {
notifier.onWarning(reason)
return
}
notifier.onWarning(reason)
return
}
if (isPaused && queueState.value.isNotEmpty()) {
queueState.value.forEach {
notifier.onPaused(it)
}
notifier.onPaused()
} else {
queueState.value.forEach {
notifier.onComplete(it)
}
notifier.onComplete()
}
isPaused = false
@ -201,10 +195,8 @@ class AnimeDownloader(
fun clearQueue() {
destroySubscription()
queueState.value.forEach {
notifier.dismissProgress(it)
}
_clearQueue()
notifier.dismissProgress()
}
/**
@ -214,8 +206,8 @@ class AnimeDownloader(
// Unsubscribe the previous subscription if it exists
destroySubscription()
subscription = downloadsRelay
.flatMapIterable { it }
subscription = downloadsRelay.flatMapIterable { it }
// Concurrently download from 3 different sources
.groupBy { it.source }
.flatMap(
{ bySource ->
@ -228,7 +220,7 @@ class AnimeDownloader(
downloadPreferences.numberOfDownloads().get(),
)
},
downloadPreferences.numberOfDownloads().get(), // Set the maximum number of concurrent downloads here
3,
)
.subscribe(
{ completedDownload ->
@ -236,9 +228,7 @@ class AnimeDownloader(
},
{ error ->
logcat(LogPriority.ERROR, error)
queueState.value.forEach {
notifier.onError(it, error.message, it.episode.name, it.anime.title)
}
notifier.onError(error.message)
stop()
},
)
@ -299,7 +289,7 @@ class AnimeDownloader(
// Start downloader if needed
if (autoStart && wasEmpty) {
val queuedDownloads = queueState.value.filter { it: AnimeDownload -> it.source !is UnmeteredSource }.count()
val queuedDownloads = queueState.value.count { it: AnimeDownload -> it.source !is UnmeteredSource }
val maxDownloadsFromSource = queueState.value
.groupBy { it.source }
.filterKeys { it !is UnmeteredSource }
@ -334,7 +324,7 @@ class AnimeDownloader(
val availSpace = DiskUtil.getAvailableStorageSpace(animeDir)
if (availSpace != -1L && availSpace < MIN_DISK_SPACE) {
download.status = AnimeDownload.State.ERROR
notifier.onError(download, context.getString(R.string.download_insufficient_space), download.episode.name, download.anime.title)
notifier.onError(context.getString(R.string.download_insufficient_space), download.episode.name, download.anime.title)
return@defer Observable.just(download)
}
@ -399,15 +389,12 @@ class AnimeDownloader(
// Do after download completes
.doOnNext {
ensureSuccessfulAnimeDownload(download, animeDir, tmpDir, episodeDirname)
queueState.value.forEach {
if (download.status == AnimeDownload.State.DOWNLOADED) notifier.dismissProgress(it)
}
if (download.status == AnimeDownload.State.DOWNLOADED) notifier.dismissProgress()
}
// If the video list threw, it will resume here
.onErrorReturn { error ->
download.status = AnimeDownload.State.ERROR
notifier.onError(download, error.message, download.episode.name, download.anime.title)
notifier.onError(error.message, download.episode.name, download.anime.title)
download
}
}
@ -465,7 +452,7 @@ class AnimeDownloader(
.onErrorReturn {
video.progress = 0
video.status = Video.State.ERROR
notifier.onError(download, it.message, download.episode.name, download.anime.title)
notifier.onError(it.message, download.episode.name, download.anime.title)
video
}
}
@ -845,8 +832,8 @@ class AnimeDownloader(
companion object {
const val TMP_DIR_SUFFIX = "_tmp"
const val WARNING_NOTIF_TIMEOUT_MS = 30_000L
const val EPISODES_PER_SOURCE_QUEUE_WARNING_THRESHOLD = 15
private const val DOWNLOADS_QUEUED_WARNING_THRESHOLD = 30
const val EPISODES_PER_SOURCE_QUEUE_WARNING_THRESHOLD = 10
private const val DOWNLOADS_QUEUED_WARNING_THRESHOLD = 20
}
}

View file

@ -38,9 +38,10 @@ object Notifications {
private const val GROUP_DOWNLOADER = "group_downloader"
const val CHANNEL_DOWNLOADER_PROGRESS = "downloader_progress_channel"
const val ID_DOWNLOAD_CHAPTER_PROGRESS = -201
const val ID_DOWNLOAD_EPISODE_PROGRESS = -205
const val ID_DOWNLOAD_EPISODE_PROGRESS = -203
const val CHANNEL_DOWNLOADER_ERROR = "downloader_error_channel"
const val ID_DOWNLOAD_CHAPTER_ERROR = -202
const val ID_DOWNLOAD_EPISODE_ERROR = -204
/**
* Notification channel and ids used by the library updater.