Group notifcations for Library updates (#2582)
This commit is contained in:
@@ -4,6 +4,7 @@ import android.app.PendingIntent
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Handler
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
@@ -12,11 +13,17 @@ import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.data.download.DownloadManager
|
||||
import eu.kanade.tachiyomi.data.download.DownloadService
|
||||
import eu.kanade.tachiyomi.data.library.LibraryUpdateService
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||
import eu.kanade.tachiyomi.ui.manga.MangaController
|
||||
import eu.kanade.tachiyomi.ui.reader.ReaderActivity
|
||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||
import eu.kanade.tachiyomi.util.storage.getUriCompat
|
||||
import eu.kanade.tachiyomi.util.system.notificationManager
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.io.File
|
||||
import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID
|
||||
@@ -60,6 +67,15 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
openChapter(context, intent.getLongExtra(EXTRA_MANGA_ID, -1),
|
||||
intent.getLongExtra(EXTRA_CHAPTER_ID, -1))
|
||||
}
|
||||
ACTION_MARK_AS_READ -> {
|
||||
val notificationId = intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1)
|
||||
if (notificationId > -1) dismissNotification(
|
||||
context, notificationId, intent.getIntExtra(EXTRA_GROUP_ID, 0)
|
||||
)
|
||||
val urls = intent.getStringArrayExtra(EXTRA_CHAPTER_URL) ?: return
|
||||
val mangaId = intent.getLongExtra(EXTRA_MANGA_ID, -1)
|
||||
markAsRead(urls, mangaId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +120,6 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
val db = DatabaseHelper(context)
|
||||
val manga = db.getManga(mangaId).executeAsBlocking()
|
||||
val chapter = db.getChapter(chapterId).executeAsBlocking()
|
||||
|
||||
if (manga != null && chapter != null) {
|
||||
val intent = ReaderActivity.newIntent(context, manga, chapter).apply {
|
||||
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||
@@ -143,6 +158,28 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
Handler().post { dismissNotification(context, notificationId) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called when user wants to mark as read
|
||||
*
|
||||
* @param context context of application
|
||||
* @param notificationId id of notification
|
||||
*/
|
||||
private fun markAsRead(chapterUrls: Array<String>, mangaId: Long) {
|
||||
val db: DatabaseHelper = Injekt.get()
|
||||
chapterUrls.forEach {
|
||||
val chapter = db.getChapter(it, mangaId).executeAsBlocking() ?: return
|
||||
chapter.read = true
|
||||
db.updateChapterProgress(chapter).executeAsBlocking()
|
||||
val preferences: PreferencesHelper = Injekt.get()
|
||||
if (preferences.removeAfterMarkedAsRead()) {
|
||||
val manga = db.getManga(mangaId).executeAsBlocking() ?: return
|
||||
val sourceManager: SourceManager = Injekt.get()
|
||||
val source = sourceManager.get(manga.source) ?: return
|
||||
downloadManager.deleteChapters(listOf(chapter), manga, source)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val NAME = "NotificationReceiver"
|
||||
|
||||
@@ -155,6 +192,9 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
// Called to cancel library update.
|
||||
private const val ACTION_CANCEL_LIBRARY_UPDATE = "$ID.$NAME.CANCEL_LIBRARY_UPDATE"
|
||||
|
||||
// Called to mark as read
|
||||
private const val ACTION_MARK_AS_READ = "$ID.$NAME.MARK_AS_READ"
|
||||
|
||||
// Called to open chapter
|
||||
private const val ACTION_OPEN_CHAPTER = "$ID.$NAME.ACTION_OPEN_CHAPTER"
|
||||
|
||||
@@ -179,12 +219,18 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
// Value containing notification id.
|
||||
private const val EXTRA_NOTIFICATION_ID = "$ID.$NAME.NOTIFICATION_ID"
|
||||
|
||||
// Value containing group id.
|
||||
private const val EXTRA_GROUP_ID = "$ID.$NAME.EXTRA_GROUP_ID"
|
||||
|
||||
// Value containing manga id.
|
||||
private const val EXTRA_MANGA_ID = "$ID.$NAME.EXTRA_MANGA_ID"
|
||||
|
||||
// Value containing chapter id.
|
||||
private const val EXTRA_CHAPTER_ID = "$ID.$NAME.EXTRA_CHAPTER_ID"
|
||||
|
||||
// Value containing chapter url.
|
||||
private const val EXTRA_CHAPTER_URL = "$ID.$NAME.EXTRA_CHAPTER_URL"
|
||||
|
||||
/**
|
||||
* Returns a [PendingIntent] that resumes the download of a chapter
|
||||
*
|
||||
@@ -246,6 +292,32 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns [PendingIntent] that starts a service which dismissed the notification
|
||||
*
|
||||
* @param context context of application
|
||||
* @param notificationId id of notification
|
||||
* @return [PendingIntent]
|
||||
*/
|
||||
internal fun dismissNotification(context: Context, notificationId: Int, groupId: Int? =
|
||||
null) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
val groupKey = context.notificationManager.activeNotifications.find {
|
||||
it.id == notificationId
|
||||
}?.groupKey
|
||||
if (groupId != null && groupId != 0 && groupKey != null && groupKey.isNotEmpty()) {
|
||||
val notifications = context.notificationManager.activeNotifications.filter {
|
||||
it.groupKey == groupKey
|
||||
}
|
||||
if (notifications.size == 2) {
|
||||
context.notificationManager.cancel(groupId)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
context.notificationManager.cancel(notificationId)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns [PendingIntent] that starts a service which cancels the notification and starts a share activity
|
||||
*
|
||||
@@ -281,19 +353,55 @@ class NotificationReceiver : BroadcastReceiver() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns [PendingIntent] that start a reader activity containing chapter.
|
||||
* Returns [PendingIntent] that starts a reader activity containing chapter.
|
||||
*
|
||||
* @param context context of application
|
||||
* @param manga manga of chapter
|
||||
* @param chapter chapter that needs to be opened
|
||||
*/
|
||||
internal fun openChapterPendingBroadcast(context: Context, manga: Manga, chapter: Chapter): PendingIntent {
|
||||
val intent = Intent(context, NotificationReceiver::class.java).apply {
|
||||
action = ACTION_OPEN_CHAPTER
|
||||
internal fun openChapterPendingActivity(context: Context, manga: Manga, chapter:
|
||||
Chapter): PendingIntent {
|
||||
val newIntent = ReaderActivity.newIntent(context, manga, chapter)
|
||||
return PendingIntent.getActivity(context, manga.id.hashCode(), newIntent, PendingIntent
|
||||
.FLAG_UPDATE_CURRENT)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns [PendingIntent] that opens the manga info controller.
|
||||
*
|
||||
* @param context context of application
|
||||
* @param manga manga of chapter
|
||||
*/
|
||||
internal fun openChapterPendingActivity(context: Context, manga: Manga, groupId: Int):
|
||||
PendingIntent {
|
||||
val newIntent =
|
||||
Intent(context, MainActivity::class.java).setAction(MainActivity.SHORTCUT_MANGA)
|
||||
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
||||
.putExtra(MangaController.MANGA_EXTRA, manga.id)
|
||||
.putExtra("notificationId", manga.id.hashCode())
|
||||
.putExtra("groupId", groupId)
|
||||
return PendingIntent.getActivity(
|
||||
context, manga.id.hashCode(), newIntent, PendingIntent.FLAG_UPDATE_CURRENT
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns [PendingIntent] that marks a chapter as read and deletes it if preferred
|
||||
*
|
||||
* @param context context of application
|
||||
* @param manga manga of chapter
|
||||
*/
|
||||
internal fun markAsReadPendingBroadcast(context: Context, manga: Manga, chapters:
|
||||
Array<Chapter>, groupId: Int):
|
||||
PendingIntent {
|
||||
val newIntent = Intent(context, NotificationReceiver::class.java).apply {
|
||||
action = ACTION_MARK_AS_READ
|
||||
putExtra(EXTRA_CHAPTER_URL, chapters.map { it.url }.toTypedArray())
|
||||
putExtra(EXTRA_MANGA_ID, manga.id)
|
||||
putExtra(EXTRA_CHAPTER_ID, chapter.id)
|
||||
putExtra(EXTRA_NOTIFICATION_ID, manga.id.hashCode())
|
||||
putExtra(EXTRA_GROUP_ID, groupId)
|
||||
}
|
||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
return PendingIntent.getBroadcast(context, manga.id.hashCode(), newIntent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,15 +23,21 @@ object Notifications {
|
||||
* Notification channel and ids used by the library updater.
|
||||
*/
|
||||
const val CHANNEL_LIBRARY = "library_channel"
|
||||
const val ID_LIBRARY_PROGRESS = 101
|
||||
const val ID_LIBRARY_RESULT = 102
|
||||
const val ID_LIBRARY_PROGRESS = -101
|
||||
|
||||
/**
|
||||
* Notification channel and ids used by the downloader.
|
||||
*/
|
||||
const val CHANNEL_DOWNLOADER = "downloader_channel"
|
||||
const val ID_DOWNLOAD_CHAPTER = 201
|
||||
const val ID_DOWNLOAD_CHAPTER_ERROR = 202
|
||||
const val ID_DOWNLOAD_CHAPTER = -201
|
||||
const val ID_DOWNLOAD_CHAPTER_ERROR = -202
|
||||
|
||||
/**
|
||||
* Notification channel and ids used by the library updater.
|
||||
*/
|
||||
const val CHANNEL_NEW_CHAPTERS = "new_chapters_channel"
|
||||
const val ID_NEW_CHAPTERS = -301
|
||||
const val GROUP_NEW_CHAPTERS = "eu.kanade.tachiyomi.NEW_CHAPTERS"
|
||||
|
||||
/**
|
||||
* Creates the notification channels introduced in Android Oreo.
|
||||
@@ -45,9 +51,15 @@ object Notifications {
|
||||
NotificationChannel(CHANNEL_COMMON, context.getString(R.string.channel_common),
|
||||
NotificationManager.IMPORTANCE_LOW),
|
||||
NotificationChannel(CHANNEL_LIBRARY, context.getString(R.string.channel_library),
|
||||
NotificationManager.IMPORTANCE_LOW),
|
||||
NotificationManager.IMPORTANCE_LOW).apply {
|
||||
setShowBadge(false)
|
||||
},
|
||||
NotificationChannel(CHANNEL_DOWNLOADER, context.getString(R.string.channel_downloader),
|
||||
NotificationManager.IMPORTANCE_LOW)
|
||||
NotificationManager.IMPORTANCE_LOW).apply {
|
||||
setShowBadge(false)
|
||||
},
|
||||
NotificationChannel(CHANNEL_NEW_CHAPTERS, context.getString(R.string.channel_new_chapters),
|
||||
NotificationManager.IMPORTANCE_DEFAULT)
|
||||
)
|
||||
context.notificationManager.createNotificationChannels(channels)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user