DownloadNotifier.kt 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. package eu.kanade.tachiyomi.data.download
  2. import android.content.Context
  3. import android.graphics.BitmapFactory
  4. import androidx.core.app.NotificationCompat
  5. import eu.kanade.tachiyomi.R
  6. import eu.kanade.tachiyomi.data.download.model.Download
  7. import eu.kanade.tachiyomi.data.notification.NotificationHandler
  8. import eu.kanade.tachiyomi.data.notification.NotificationReceiver
  9. import eu.kanade.tachiyomi.data.notification.Notifications
  10. import eu.kanade.tachiyomi.data.preference.PreferencesHelper
  11. import eu.kanade.tachiyomi.util.lang.chop
  12. import eu.kanade.tachiyomi.util.system.notificationBuilder
  13. import eu.kanade.tachiyomi.util.system.notificationManager
  14. import java.util.regex.Pattern
  15. import uy.kohesive.injekt.Injekt
  16. import uy.kohesive.injekt.api.get
  17. /**
  18. * DownloadNotifier is used to show notifications when downloading one or multiple chapters.
  19. *
  20. * @param context context of application
  21. */
  22. internal class DownloadNotifier(private val context: Context) {
  23. private val notificationBuilder = context.notificationBuilder(Notifications.CHANNEL_DOWNLOADER) {
  24. setLargeIcon(BitmapFactory.decodeResource(context.resources, R.mipmap.ic_launcher))
  25. }
  26. private val preferences by lazy { Injekt.get<PreferencesHelper>() }
  27. /**
  28. * Status of download. Used for correct notification icon.
  29. */
  30. private var isDownloading = false
  31. /**
  32. * Updated when error is thrown
  33. */
  34. var errorThrown = false
  35. /**
  36. * Updated when paused
  37. */
  38. var paused = false
  39. /**
  40. * Shows a notification from this builder.
  41. *
  42. * @param id the id of the notification.
  43. */
  44. private fun NotificationCompat.Builder.show(id: Int = Notifications.ID_DOWNLOAD_CHAPTER) {
  45. context.notificationManager.notify(id, build())
  46. }
  47. /**
  48. * Clear old actions if they exist.
  49. */
  50. private fun clearActions() = with(notificationBuilder) {
  51. if (mActions.isNotEmpty()) {
  52. mActions.clear()
  53. }
  54. }
  55. /**
  56. * Dismiss the downloader's notification. Downloader error notifications use a different id, so
  57. * those can only be dismissed by the user.
  58. */
  59. fun dismiss() {
  60. context.notificationManager.cancel(Notifications.ID_DOWNLOAD_CHAPTER)
  61. }
  62. /**
  63. * Called when download progress changes.
  64. *
  65. * @param download download object containing download information.
  66. */
  67. fun onProgressChange(download: Download) {
  68. // Create notification
  69. with(notificationBuilder) {
  70. // Check if first call.
  71. if (!isDownloading) {
  72. setSmallIcon(android.R.drawable.stat_sys_download)
  73. setAutoCancel(false)
  74. clearActions()
  75. // Open download manager when clicked
  76. setContentIntent(NotificationHandler.openDownloadManagerPendingActivity(context))
  77. isDownloading = true
  78. // Pause action
  79. addAction(R.drawable.ic_pause_24dp,
  80. context.getString(R.string.action_pause),
  81. NotificationReceiver.pauseDownloadsPendingBroadcast(context))
  82. }
  83. val downloadingProgressText = context.getString(R.string.chapter_downloading_progress)
  84. .format(download.downloadedImages, download.pages!!.size)
  85. if (preferences.hideNotificationContent()) {
  86. setContentTitle(downloadingProgressText)
  87. } else {
  88. val title = download.manga.title.chop(15)
  89. val quotedTitle = Pattern.quote(title)
  90. val chapter = download.chapter.name.replaceFirst("$quotedTitle[\\s]*[-]*[\\s]*".toRegex(RegexOption.IGNORE_CASE), "")
  91. setContentTitle("$title - $chapter".chop(30))
  92. setContentText(downloadingProgressText)
  93. }
  94. setProgress(download.pages!!.size, download.downloadedImages, false)
  95. }
  96. // Displays the progress bar on notification
  97. notificationBuilder.show()
  98. }
  99. /**
  100. * Show notification when download is paused.
  101. */
  102. fun onDownloadPaused() {
  103. with(notificationBuilder) {
  104. setContentTitle(context.getString(R.string.chapter_paused))
  105. setContentText(context.getString(R.string.download_notifier_download_paused))
  106. setSmallIcon(R.drawable.ic_pause_24dp)
  107. setAutoCancel(false)
  108. setProgress(0, 0, false)
  109. clearActions()
  110. // Open download manager when clicked
  111. setContentIntent(NotificationHandler.openDownloadManagerPendingActivity(context))
  112. // Resume action
  113. addAction(R.drawable.ic_play_arrow_24dp,
  114. context.getString(R.string.action_resume),
  115. NotificationReceiver.resumeDownloadsPendingBroadcast(context))
  116. // Clear action
  117. addAction(R.drawable.ic_close_24dp,
  118. context.getString(R.string.action_cancel_all),
  119. NotificationReceiver.clearDownloadsPendingBroadcast(context))
  120. }
  121. // Show notification.
  122. notificationBuilder.show()
  123. // Reset initial values
  124. isDownloading = false
  125. }
  126. /**
  127. * Called when the downloader receives a warning.
  128. *
  129. * @param reason the text to show.
  130. */
  131. fun onWarning(reason: String) {
  132. with(notificationBuilder) {
  133. setContentTitle(context.getString(R.string.download_notifier_downloader_title))
  134. setContentText(reason)
  135. setSmallIcon(android.R.drawable.stat_sys_warning)
  136. setAutoCancel(true)
  137. clearActions()
  138. setContentIntent(NotificationHandler.openDownloadManagerPendingActivity(context))
  139. setProgress(0, 0, false)
  140. }
  141. notificationBuilder.show()
  142. // Reset download information
  143. isDownloading = false
  144. }
  145. /**
  146. * Called when the downloader receives an error. It's shown as a separate notification to avoid
  147. * being overwritten.
  148. *
  149. * @param error string containing error information.
  150. * @param chapter string containing chapter title.
  151. */
  152. fun onError(error: String? = null, chapter: String? = null) {
  153. // Create notification
  154. with(notificationBuilder) {
  155. setContentTitle(chapter
  156. ?: context.getString(R.string.download_notifier_downloader_title))
  157. setContentText(error ?: context.getString(R.string.download_notifier_unkown_error))
  158. setSmallIcon(android.R.drawable.stat_sys_warning)
  159. clearActions()
  160. setAutoCancel(false)
  161. setContentIntent(NotificationHandler.openDownloadManagerPendingActivity(context))
  162. setProgress(0, 0, false)
  163. }
  164. notificationBuilder.show(Notifications.ID_DOWNLOAD_CHAPTER_ERROR)
  165. // Reset download information
  166. errorThrown = true
  167. isDownloading = false
  168. }
  169. }