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.isPreviewBuildType
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.notify
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
@ -97,7 +97,10 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
.onEach { enabled ->
if (enabled) {
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))
setContentText(getString(R.string.notification_incognito_text))
setSmallIcon(R.drawable.ic_glasses_24dp)
@ -111,7 +114,6 @@ class App : Application(), DefaultLifecycleObserver, ImageLoaderFactory {
)
setContentIntent(pendingIntent)
}
notificationManager.notify(Notifications.ID_INCOGNITO_MODE, notification)
} else {
disableIncognitoReceiver.unregister()
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.isOnline
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 kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -143,8 +143,8 @@ class DownloadService : Service() {
}
private fun getPlaceholderNotification(): Notification {
return notification(Notifications.CHANNEL_DOWNLOADER_PROGRESS) {
return notificationBuilder(Notifications.CHANNEL_DOWNLOADER_PROGRESS) {
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.ui.main.MainActivity
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.notificationManager
import eu.kanade.tachiyomi.util.system.notify
import tachiyomi.core.Constants
import tachiyomi.core.util.lang.launchUI
import tachiyomi.domain.chapter.model.Chapter
@ -91,18 +91,16 @@ class LibraryUpdateNotifier(private val context: Context) {
}
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))
setStyle(NotificationCompat.BigTextStyle().bigText(context.getString(R.string.notification_size_warning)))
setSmallIcon(R.drawable.ic_warning_white_24dp)
setTimeoutAfter(Downloader.WARNING_NOTIF_TIMEOUT_MS)
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
}
context.notificationManager.notify(
context.notify(
Notifications.ID_LIBRARY_ERROR,
context.notificationBuilder(Notifications.CHANNEL_LIBRARY_ERROR) {
setContentTitle(context.resources.getString(R.string.notification_update_error, failed))
setContentText(context.getString(R.string.action_show_errors))
setSmallIcon(R.drawable.ic_tachi)
Notifications.CHANNEL_LIBRARY_ERROR,
) {
setContentTitle(context.resources.getString(R.string.notification_update_error, failed))
setContentText(context.getString(R.string.action_show_errors))
setSmallIcon(R.drawable.ic_tachi)
setContentIntent(NotificationReceiver.openErrorLogPendingActivity(context, uri))
}
.build(),
)
setContentIntent(NotificationReceiver.openErrorLogPendingActivity(context, uri))
}
}
/**
@ -139,16 +136,15 @@ class LibraryUpdateNotifier(private val context: Context) {
return
}
context.notificationManager.notify(
context.notify(
Notifications.ID_LIBRARY_SKIPPED,
context.notificationBuilder(Notifications.CHANNEL_LIBRARY_SKIPPED) {
setContentTitle(context.resources.getString(R.string.notification_update_skipped, skipped))
setContentText(context.getString(R.string.learn_more))
setSmallIcon(R.drawable.ic_tachi)
setContentIntent(NotificationHandler.openUrl(context, HELP_SKIPPED_URL))
}
.build(),
)
Notifications.CHANNEL_LIBRARY_SKIPPED,
) {
setContentTitle(context.resources.getString(R.string.notification_update_skipped, skipped))
setContentText(context.getString(R.string.learn_more))
setSmallIcon(R.drawable.ic_tachi)
setContentIntent(NotificationHandler.openUrl(context, HELP_SKIPPED_URL))
}
}
/**
@ -158,38 +154,38 @@ class LibraryUpdateNotifier(private val context: Context) {
*/
fun showUpdateNotifications(updates: List<Pair<Manga, Array<Chapter>>>) {
// Parent group notification
context.notificationManager.notify(
context.notify(
Notifications.ID_NEW_CHAPTERS,
context.notification(Notifications.CHANNEL_NEW_CHAPTERS) {
setContentTitle(context.getString(R.string.notification_new_chapters))
if (updates.size == 1 && !preferences.hideNotificationContent().get()) {
setContentText(updates.first().first.title.chop(NOTIF_TITLE_MAX_LEN))
} else {
setContentText(context.resources.getQuantityString(R.plurals.notification_new_chapters_summary, updates.size, updates.size))
Notifications.CHANNEL_NEW_CHAPTERS,
) {
setContentTitle(context.getString(R.string.notification_new_chapters))
if (updates.size == 1 && !preferences.hideNotificationContent().get()) {
setContentText(updates.first().first.title.chop(NOTIF_TITLE_MAX_LEN))
} else {
setContentText(context.resources.getQuantityString(R.plurals.notification_new_chapters_summary, updates.size, updates.size))
if (!preferences.hideNotificationContent().get()) {
setStyle(
NotificationCompat.BigTextStyle().bigText(
updates.joinToString("\n") {
it.first.title.chop(NOTIF_TITLE_MAX_LEN)
},
),
)
}
if (!preferences.hideNotificationContent().get()) {
setStyle(
NotificationCompat.BigTextStyle().bigText(
updates.joinToString("\n") {
it.first.title.chop(NOTIF_TITLE_MAX_LEN)
},
),
)
}
}
setSmallIcon(R.drawable.ic_tachi)
setLargeIcon(notificationBitmap)
setSmallIcon(R.drawable.ic_tachi)
setLargeIcon(notificationBitmap)
setGroup(Notifications.GROUP_NEW_CHAPTERS)
setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY)
setGroupSummary(true)
priority = NotificationCompat.PRIORITY_HIGH
setGroup(Notifications.GROUP_NEW_CHAPTERS)
setGroupAlertBehavior(NotificationCompat.GROUP_ALERT_SUMMARY)
setGroupSummary(true)
priority = NotificationCompat.PRIORITY_HIGH
setContentIntent(getNotificationIntent())
setAutoCancel(true)
},
)
setContentIntent(getNotificationIntent())
setAutoCancel(true)
}
// Per-manga notification
if (!preferences.hideNotificationContent().get()) {
@ -203,7 +199,7 @@ class LibraryUpdateNotifier(private val context: Context) {
private suspend fun createNewChaptersNotification(manga: Manga, chapters: Array<Chapter>): Notification {
val icon = getMangaIcon(manga)
return context.notification(Notifications.CHANNEL_NEW_CHAPTERS) {
return context.notificationBuilder(Notifications.CHANNEL_NEW_CHAPTERS) {
setContentTitle(manga.title)
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.data.notification.NotificationReceiver
import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.util.system.notification
import eu.kanade.tachiyomi.util.system.notificationManager
import eu.kanade.tachiyomi.util.system.notify
class ExtensionUpdateNotifier(private val context: Context) {
fun promptUpdates(names: List<String>) {
context.notificationManager.notify(
context.notify(
Notifications.ID_UPDATES_TO_EXTS,
context.notification(Notifications.CHANNEL_EXTENSIONS_UPDATE) {
setContentTitle(
context.resources.getQuantityString(
R.plurals.update_check_notification_ext_updates,
names.size,
names.size,
),
)
val extNames = names.joinToString(", ")
setContentText(extNames)
setStyle(NotificationCompat.BigTextStyle().bigText(extNames))
setSmallIcon(R.drawable.ic_extension_24dp)
setContentIntent(NotificationReceiver.openExtensionsPendingActivity(context))
setAutoCancel(true)
},
)
Notifications.CHANNEL_EXTENSIONS_UPDATE,
) {
setContentTitle(
context.resources.getQuantityString(
R.plurals.update_check_notification_ext_updates,
names.size,
names.size,
),
)
val extNames = names.joinToString(", ")
setContentText(extNames)
setStyle(NotificationCompat.BigTextStyle().bigText(extNames))
setSmallIcon(R.drawable.ic_extension_24dp)
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.util.storage.getUriCompat
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.notify
import eu.kanade.tachiyomi.util.system.toast
import tachiyomi.core.util.lang.withNonCancellableContext
import tachiyomi.core.util.lang.withUIContext
class CrashLogUtil(private val context: Context) {
private val notificationBuilder = context.notificationBuilder(Notifications.CHANNEL_CRASH_LOGS) {
setSmallIcon(R.drawable.ic_tachi)
}
suspend fun dumpLogs() = withNonCancellableContext {
try {
val file = context.createFileInCacheDir("tachiyomi_crash_logs.txt")
@ -49,8 +45,12 @@ class CrashLogUtil(private val context: Context) {
private fun showNotification(uri: Uri) {
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))
setSmallIcon(R.drawable.ic_tachi)
clearActions()
addAction(
@ -63,8 +63,6 @@ class CrashLogUtil(private val context: Context) {
context.getString(R.string.action_share),
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.ColorInt
import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.content.ContextCompat
import androidx.core.content.PermissionChecker
import androidx.core.content.getSystemService
import androidx.core.graphics.alpha
import androidx.core.graphics.blue
@ -78,7 +78,7 @@ fun Context.copyToClipboard(label: String, content: String) {
* @param permission the permission to check.
* @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.

View file

@ -1,12 +1,39 @@
package eu.kanade.tachiyomi.util.system
import android.app.Notification
import android.Manifest
import android.content.Context
import androidx.core.app.NotificationChannelCompat
import androidx.core.app.NotificationChannelGroupCompat
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.PermissionChecker
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.
*
@ -40,31 +67,3 @@ fun buildNotificationChannel(
builder.block()
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()
}