Simplify some of the notification builders

This commit is contained in:
arkon 2023-03-19 16:24:37 -04:00
parent dfdb688b43
commit 7d8a865cac
7 changed files with 111 additions and 117 deletions

View File

@ -40,8 +40,8 @@ import eu.kanade.tachiyomi.util.system.WebViewUtil
import eu.kanade.tachiyomi.util.system.animatorDurationScale import eu.kanade.tachiyomi.util.system.animatorDurationScale
import eu.kanade.tachiyomi.util.system.isPreviewBuildType import eu.kanade.tachiyomi.util.system.isPreviewBuildType
import eu.kanade.tachiyomi.util.system.isReleaseBuildType import eu.kanade.tachiyomi.util.system.isReleaseBuildType
import eu.kanade.tachiyomi.util.system.notification
import eu.kanade.tachiyomi.util.system.notificationManager import eu.kanade.tachiyomi.util.system.notificationManager
import eu.kanade.tachiyomi.util.system.notify
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -97,7 +97,10 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
.onEach { enabled -> .onEach { enabled ->
if (enabled) { if (enabled) {
disableIncognitoReceiver.register() disableIncognitoReceiver.register()
val notification = notification(Notifications.CHANNEL_INCOGNITO_MODE) { notify(
Notifications.ID_INCOGNITO_MODE,
Notifications.CHANNEL_INCOGNITO_MODE,
) {
setContentTitle(getString(R.string.pref_incognito_mode)) setContentTitle(getString(R.string.pref_incognito_mode))
setContentText(getString(R.string.notification_incognito_text)) setContentText(getString(R.string.notification_incognito_text))
setSmallIcon(R.drawable.ic_glasses_24dp) setSmallIcon(R.drawable.ic_glasses_24dp)
@ -111,7 +114,6 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
) )
setContentIntent(pendingIntent) setContentIntent(pendingIntent)
} }
notificationManager.notify(Notifications.ID_INCOGNITO_MODE, notification)
} else { } else {
disableIncognitoReceiver.unregister() disableIncognitoReceiver.unregister()
notificationManager.cancel(Notifications.ID_INCOGNITO_MODE) notificationManager.cancel(Notifications.ID_INCOGNITO_MODE)

View File

@ -14,7 +14,7 @@ import eu.kanade.tachiyomi.util.system.acquireWakeLock
import eu.kanade.tachiyomi.util.system.isConnectedToWifi import eu.kanade.tachiyomi.util.system.isConnectedToWifi
import eu.kanade.tachiyomi.util.system.isOnline import eu.kanade.tachiyomi.util.system.isOnline
import eu.kanade.tachiyomi.util.system.isServiceRunning import eu.kanade.tachiyomi.util.system.isServiceRunning
import eu.kanade.tachiyomi.util.system.notification import eu.kanade.tachiyomi.util.system.notificationBuilder
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@ -143,8 +143,8 @@ class DownloadService : Service() {
} }
private fun getPlaceholderNotification(): Notification { private fun getPlaceholderNotification(): Notification {
return notification(Notifications.CHANNEL_DOWNLOADER_PROGRESS) { return notificationBuilder(Notifications.CHANNEL_DOWNLOADER_PROGRESS) {
setContentTitle(getString(R.string.download_notifier_downloader_title)) setContentTitle(getString(R.string.download_notifier_downloader_title))
} }.build()
} }
} }

View File

@ -20,9 +20,9 @@ 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.ui.main.MainActivity import eu.kanade.tachiyomi.ui.main.MainActivity
import eu.kanade.tachiyomi.util.lang.chop import eu.kanade.tachiyomi.util.lang.chop
import eu.kanade.tachiyomi.util.system.notification
import eu.kanade.tachiyomi.util.system.notificationBuilder import eu.kanade.tachiyomi.util.system.notificationBuilder
import eu.kanade.tachiyomi.util.system.notificationManager import eu.kanade.tachiyomi.util.system.notificationManager
import eu.kanade.tachiyomi.util.system.notify
import tachiyomi.core.Constants import tachiyomi.core.Constants
import tachiyomi.core.util.lang.launchUI import tachiyomi.core.util.lang.launchUI
import tachiyomi.domain.chapter.model.Chapter import tachiyomi.domain.chapter.model.Chapter
@ -91,18 +91,16 @@ class LibraryUpdateNotifier(private val context: Context) {
} }
fun showQueueSizeWarningNotification() { fun showQueueSizeWarningNotification() {
val notificationBuilder = context.notificationBuilder(Notifications.CHANNEL_LIBRARY_PROGRESS) { context.notify(
Notifications.ID_LIBRARY_SIZE_WARNING,
Notifications.CHANNEL_LIBRARY_PROGRESS,
) {
setContentTitle(context.getString(R.string.label_warning)) setContentTitle(context.getString(R.string.label_warning))
setStyle(NotificationCompat.BigTextStyle().bigText(context.getString(R.string.notification_size_warning))) setStyle(NotificationCompat.BigTextStyle().bigText(context.getString(R.string.notification_size_warning)))
setSmallIcon(R.drawable.ic_warning_white_24dp) setSmallIcon(R.drawable.ic_warning_white_24dp)
setTimeoutAfter(Downloader.WARNING_NOTIF_TIMEOUT_MS) setTimeoutAfter(Downloader.WARNING_NOTIF_TIMEOUT_MS)
setContentIntent(NotificationHandler.openUrl(context, HELP_WARNING_URL)) setContentIntent(NotificationHandler.openUrl(context, HELP_WARNING_URL))
} }
context.notificationManager.notify(
Notifications.ID_LIBRARY_SIZE_WARNING,
notificationBuilder.build(),
)
} }
/** /**
@ -116,17 +114,16 @@ class LibraryUpdateNotifier(private val context: Context) {
return return
} }
context.notificationManager.notify( context.notify(
Notifications.ID_LIBRARY_ERROR, Notifications.ID_LIBRARY_ERROR,
context.notificationBuilder(Notifications.CHANNEL_LIBRARY_ERROR) { Notifications.CHANNEL_LIBRARY_ERROR,
setContentTitle(context.resources.getString(R.string.notification_update_error, failed)) ) {
setContentText(context.getString(R.string.action_show_errors)) setContentTitle(context.resources.getString(R.string.notification_update_error, failed))
setSmallIcon(R.drawable.ic_tachi) setContentText(context.getString(R.string.action_show_errors))
setSmallIcon(R.drawable.ic_tachi)
setContentIntent(NotificationReceiver.openErrorLogPendingActivity(context, uri)) setContentIntent(NotificationReceiver.openErrorLogPendingActivity(context, uri))
} }
.build(),
)
} }
/** /**
@ -139,16 +136,15 @@ class LibraryUpdateNotifier(private val context: Context) {
return return
} }
context.notificationManager.notify( context.notify(
Notifications.ID_LIBRARY_SKIPPED, Notifications.ID_LIBRARY_SKIPPED,
context.notificationBuilder(Notifications.CHANNEL_LIBRARY_SKIPPED) { Notifications.CHANNEL_LIBRARY_SKIPPED,
setContentTitle(context.resources.getString(R.string.notification_update_skipped, skipped)) ) {
setContentText(context.getString(R.string.learn_more)) setContentTitle(context.resources.getString(R.string.notification_update_skipped, skipped))
setSmallIcon(R.drawable.ic_tachi) setContentText(context.getString(R.string.learn_more))
setContentIntent(NotificationHandler.openUrl(context, HELP_SKIPPED_URL)) setSmallIcon(R.drawable.ic_tachi)
} setContentIntent(NotificationHandler.openUrl(context, HELP_SKIPPED_URL))
.build(), }
)
} }
/** /**
@ -158,38 +154,38 @@ class LibraryUpdateNotifier(private val context: Context) {
*/ */
fun showUpdateNotifications(updates: List<Pair<Manga, Array<Chapter>>>) { fun showUpdateNotifications(updates: List<Pair<Manga, Array<Chapter>>>) {
// Parent group notification // Parent group notification
context.notificationManager.notify( context.notify(
Notifications.ID_NEW_CHAPTERS, Notifications.ID_NEW_CHAPTERS,
context.notification(Notifications.CHANNEL_NEW_CHAPTERS) { Notifications.CHANNEL_NEW_CHAPTERS,
setContentTitle(context.getString(R.string.notification_new_chapters)) ) {
if (updates.size == 1 && !preferences.hideNotificationContent().get()) { setContentTitle(context.getString(R.string.notification_new_chapters))
setContentText(updates.first().first.title.chop(NOTIF_TITLE_MAX_LEN)) if (updates.size == 1 && !preferences.hideNotificationContent().get()) {
} else { setContentText(updates.first().first.title.chop(NOTIF_TITLE_MAX_LEN))
setContentText(context.resources.getQuantityString(R.plurals.notification_new_chapters_summary, updates.size, updates.size)) } else {
setContentText(context.resources.getQuantityString(R.plurals.notification_new_chapters_summary, updates.size, updates.size))
if (!preferences.hideNotificationContent().get()) { if (!preferences.hideNotificationContent().get()) {
setStyle( setStyle(
NotificationCompat.BigTextStyle().bigText( NotificationCompat.BigTextStyle().bigText(
updates.joinToString("\n") { updates.joinToString("\n") {
it.first.title.chop(NOTIF_TITLE_MAX_LEN) it.first.title.chop(NOTIF_TITLE_MAX_LEN)
}, },
), ),
) )
}
} }
}
setSmallIcon(R.drawable.ic_tachi) setSmallIcon(R.drawable.ic_tachi)
setLargeIcon(notificationBitmap) setLargeIcon(notificationBitmap)
setGroup(Notifications.GROUP_NEW_CHAPTERS) setGroup(Notifications.GROUP_NEW_CHAPTERS)
setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY) setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY)
setGroupSummary(true) setGroupSummary(true)
priority = NotificationCompat.PRIORITY_HIGH priority = NotificationCompat.PRIORITY_HIGH
setContentIntent(getNotificationIntent()) setContentIntent(getNotificationIntent())
setAutoCancel(true) setAutoCancel(true)
}, }
)
// Per-manga notification // Per-manga notification
if (!preferences.hideNotificationContent().get()) { if (!preferences.hideNotificationContent().get()) {
@ -203,7 +199,7 @@ class LibraryUpdateNotifier(private val context: Context) {
private suspend fun createNewChaptersNotification(manga: Manga, chapters: Array<Chapter>): Notification { private suspend fun createNewChaptersNotification(manga: Manga, chapters: Array<Chapter>): Notification {
val icon = getMangaIcon(manga) val icon = getMangaIcon(manga)
return context.notification(Notifications.CHANNEL_NEW_CHAPTERS) { return context.notificationBuilder(Notifications.CHANNEL_NEW_CHAPTERS) {
setContentTitle(manga.title) setContentTitle(manga.title)
val description = getNewChaptersDescription(chapters) val description = getNewChaptersDescription(chapters)
@ -259,7 +255,7 @@ class LibraryUpdateNotifier(private val context: Context) {
), ),
) )
} }
} }.build()
} }
/** /**

View File

@ -5,29 +5,28 @@ import androidx.core.app.NotificationCompat
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
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.util.system.notification import eu.kanade.tachiyomi.util.system.notify
import eu.kanade.tachiyomi.util.system.notificationManager
class ExtensionUpdateNotifier(private val context: Context) { class ExtensionUpdateNotifier(private val context: Context) {
fun promptUpdates(names: List<String>) { fun promptUpdates(names: List<String>) {
context.notificationManager.notify( context.notify(
Notifications.ID_UPDATES_TO_EXTS, Notifications.ID_UPDATES_TO_EXTS,
context.notification(Notifications.CHANNEL_EXTENSIONS_UPDATE) { Notifications.CHANNEL_EXTENSIONS_UPDATE,
setContentTitle( ) {
context.resources.getQuantityString( setContentTitle(
R.plurals.update_check_notification_ext_updates, context.resources.getQuantityString(
names.size, R.plurals.update_check_notification_ext_updates,
names.size, names.size,
), names.size,
) ),
val extNames = names.joinToString(", ") )
setContentText(extNames) val extNames = names.joinToString(", ")
setStyle(NotificationCompat.BigTextStyle().bigText(extNames)) setContentText(extNames)
setSmallIcon(R.drawable.ic_extension_24dp) setStyle(NotificationCompat.BigTextStyle().bigText(extNames))
setContentIntent(NotificationReceiver.openExtensionsPendingActivity(context)) setSmallIcon(R.drawable.ic_extension_24dp)
setAutoCancel(true) setContentIntent(NotificationReceiver.openExtensionsPendingActivity(context))
}, setAutoCancel(true)
) }
} }
} }

View File

@ -9,18 +9,14 @@ 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.util.storage.getUriCompat import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.createFileInCacheDir import eu.kanade.tachiyomi.util.system.createFileInCacheDir
import eu.kanade.tachiyomi.util.system.notificationBuilder
import eu.kanade.tachiyomi.util.system.notificationManager import eu.kanade.tachiyomi.util.system.notificationManager
import eu.kanade.tachiyomi.util.system.notify
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import tachiyomi.core.util.lang.withNonCancellableContext import tachiyomi.core.util.lang.withNonCancellableContext
import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.util.lang.withUIContext
class CrashLogUtil(private val context: Context) { class CrashLogUtil(private val context: Context) {
private val notificationBuilder = context.notificationBuilder(Notifications.CHANNEL_CRASH_LOGS) {
setSmallIcon(R.drawable.ic_tachi)
}
suspend fun dumpLogs() = withNonCancellableContext { suspend fun dumpLogs() = withNonCancellableContext {
try { try {
val file = context.createFileInCacheDir("tachiyomi_crash_logs.txt") val file = context.createFileInCacheDir("tachiyomi_crash_logs.txt")
@ -49,8 +45,12 @@ class CrashLogUtil(private val context: Context) {
private fun showNotification(uri: Uri) { private fun showNotification(uri: Uri) {
context.notificationManager.cancel(Notifications.ID_CRASH_LOGS) context.notificationManager.cancel(Notifications.ID_CRASH_LOGS)
with(notificationBuilder) { context.notify(
Notifications.ID_CRASH_LOGS,
Notifications.CHANNEL_CRASH_LOGS,
) {
setContentTitle(context.getString(R.string.crash_log_saved)) setContentTitle(context.getString(R.string.crash_log_saved))
setSmallIcon(R.drawable.ic_tachi)
clearActions() clearActions()
addAction( addAction(
@ -63,8 +63,6 @@ class CrashLogUtil(private val context: Context) {
context.getString(R.string.action_share), context.getString(R.string.action_share),
NotificationReceiver.shareCrashLogPendingBroadcast(context, uri, Notifications.ID_CRASH_LOGS), NotificationReceiver.shareCrashLogPendingBroadcast(context, uri, Notifications.ID_CRASH_LOGS),
) )
context.notificationManager.notify(Notifications.ID_CRASH_LOGS, build())
} }
} }
} }

View File

@ -25,7 +25,7 @@ import android.view.WindowManager
import androidx.annotation.AttrRes import androidx.annotation.AttrRes
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import androidx.appcompat.view.ContextThemeWrapper import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.content.ContextCompat import androidx.core.content.PermissionChecker
import androidx.core.content.getSystemService import androidx.core.content.getSystemService
import androidx.core.graphics.alpha import androidx.core.graphics.alpha
import androidx.core.graphics.blue import androidx.core.graphics.blue
@ -78,7 +78,7 @@ fun Context.copyToClipboard(label: String, content: String) {
* @param permission the permission to check. * @param permission the permission to check.
* @return true if it has permissions. * @return true if it has permissions.
*/ */
fun Context.hasPermission(permission: String) = ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED fun Context.hasPermission(permission: String) = PermissionChecker.checkSelfPermission(this, permission) == PermissionChecker.PERMISSION_GRANTED
/** /**
* Returns the color for the given attribute. * Returns the color for the given attribute.

View File

@ -1,12 +1,39 @@
package eu.kanade.tachiyomi.util.system package eu.kanade.tachiyomi.util.system
import android.app.Notification import android.Manifest
import android.content.Context import android.content.Context
import androidx.core.app.NotificationChannelCompat import androidx.core.app.NotificationChannelCompat
import androidx.core.app.NotificationChannelGroupCompat import androidx.core.app.NotificationChannelGroupCompat
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.PermissionChecker
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
fun Context.notify(id: Int, channelId: String, block: (NotificationCompat.Builder.() -> Unit)? = null) {
if (PermissionChecker.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) != PermissionChecker.PERMISSION_GRANTED) {
return
}
val notification = notificationBuilder(channelId, block).build()
NotificationManagerCompat.from(this).notify(id, notification)
}
/**
* Helper method to create a notification builder.
*
* @param id the channel id.
* @param block the function that will execute inside the builder.
* @return a notification to be displayed or updated.
*/
fun Context.notificationBuilder(channelId: String, block: (NotificationCompat.Builder.() -> Unit)? = null): NotificationCompat.Builder {
val builder = NotificationCompat.Builder(this, channelId)
.setColor(getColor(R.color.accent_blue))
if (block != null) {
builder.block()
}
return builder
}
/** /**
* Helper method to build a notification channel group. * Helper method to build a notification channel group.
* *
@ -40,31 +67,3 @@ fun buildNotificationChannel(
builder.block() builder.block()
return builder.build() return builder.build()
} }
/**
* Helper method to create a notification builder.
*
* @param id the channel id.
* @param block the function that will execute inside the builder.
* @return a notification to be displayed or updated.
*/
fun Context.notificationBuilder(channelId: String, block: (NotificationCompat.Builder.() -> Unit)? = null): NotificationCompat.Builder {
val builder = NotificationCompat.Builder(this, channelId)
.setColor(getColor(R.color.accent_blue))
if (block != null) {
builder.block()
}
return builder
}
/**
* Helper method to create a notification.
*
* @param id the channel id.
* @param block the function that will execute inside the builder.
* @return a notification to be displayed or updated.
*/
fun Context.notification(channelId: String, block: (NotificationCompat.Builder.() -> Unit)?): Notification {
val builder = notificationBuilder(channelId, block)
return builder.build()
}