From 002ce25d7e1186b6ddd6cc04df6637b5e61de35e Mon Sep 17 00:00:00 2001 From: Koitharu Date: Wed, 8 May 2024 08:40:32 +0300 Subject: [PATCH] Notification settings actions in notifications --- .../browser/cloudflare/CaptchaNotifier.kt | 21 +++++++++++-- .../suggestions/ui/SuggestionsWorker.kt | 23 +++++++++++--- .../kotatsu/tracker/work/TrackWorker.kt | 31 ++++++++++++------- 3 files changed, 57 insertions(+), 18 deletions(-) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CaptchaNotifier.kt b/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CaptchaNotifier.kt index 087387314..cc20b8ecb 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CaptchaNotifier.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/browser/cloudflare/CaptchaNotifier.kt @@ -1,6 +1,9 @@ package org.koitharu.kotatsu.browser.cloudflare import android.content.Context +import android.content.Intent +import android.os.Build +import android.provider.Settings import androidx.core.app.NotificationChannelCompat import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat @@ -56,8 +59,21 @@ class CaptchaNotifier( ), ) .setContentIntent(PendingIntentCompat.getActivity(context, 0, intent, 0, false)) - .build() - manager.notify(TAG, exception.source.hashCode(), notification) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val actionIntent = PendingIntentCompat.getActivity( + context, SETTINGS_ACTION_CODE, + Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) + .putExtra(Settings.EXTRA_APP_PACKAGE, context.packageName) + .putExtra(Settings.EXTRA_CHANNEL_ID, CHANNEL_ID), + 0, false, + ) + notification.addAction( + R.drawable.ic_settings, + context.getString(R.string.notifications_settings), + actionIntent, + ) + } + manager.notify(TAG, exception.source.hashCode(), notification.build()) } fun dismiss(source: MangaSource) { @@ -84,5 +100,6 @@ class CaptchaNotifier( private const val CHANNEL_ID = "captcha" private const val TAG = CHANNEL_ID private const val GROUP_CAPTCHA = "org.koitharu.kotatsu.CAPTCHA" + private const val SETTINGS_ACTION_CODE = 3 } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt index cedee30e0..7737e2c98 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt @@ -3,8 +3,10 @@ package org.koitharu.kotatsu.suggestions.ui import android.Manifest import android.app.PendingIntent import android.content.Context +import android.content.Intent import android.content.pm.ServiceInfo import android.os.Build +import android.provider.Settings import androidx.annotation.FloatRange import androidx.annotation.RequiresPermission import androidx.core.app.NotificationChannelCompat @@ -149,12 +151,24 @@ class SuggestionsWorker @AssistedInject constructor( NotificationCompat.FOREGROUND_SERVICE_DEFERRED }, ) - .build() - + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val actionIntent = PendingIntentCompat.getActivity( + applicationContext, SETTINGS_ACTION_CODE, + Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) + .putExtra(Settings.EXTRA_APP_PACKAGE, applicationContext.packageName) + .putExtra(Settings.EXTRA_CHANNEL_ID, WORKER_CHANNEL_ID), + 0, false, + ) + notification.addAction( + R.drawable.ic_settings, + applicationContext.getString(R.string.notifications_settings), + actionIntent, + ) + } return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - ForegroundInfo(WORKER_NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC) + ForegroundInfo(WORKER_NOTIFICATION_ID, notification.build(), ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC) } else { - ForegroundInfo(WORKER_NOTIFICATION_ID, notification) + ForegroundInfo(WORKER_NOTIFICATION_ID, notification.build()) } } @@ -435,6 +449,7 @@ class SuggestionsWorker @AssistedInject constructor( const val MAX_RAW_RESULTS = 200 const val TAG_EQ_THRESHOLD = 0.4f const val RATING_MIN = 0.5f + const val SETTINGS_ACTION_CODE = 4 val preferredSortOrders = listOf( SortOrder.UPDATED, diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/work/TrackWorker.kt b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/work/TrackWorker.kt index 6da0ef433..97ca8e931 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/tracker/work/TrackWorker.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/tracker/work/TrackWorker.kt @@ -1,8 +1,10 @@ package org.koitharu.kotatsu.tracker.work import android.content.Context +import android.content.Intent import android.content.pm.ServiceInfo import android.os.Build +import android.provider.Settings import androidx.annotation.CheckResult import androidx.core.app.NotificationChannelCompat import androidx.core.app.NotificationCompat @@ -12,7 +14,6 @@ import androidx.hilt.work.HiltWorker import androidx.work.BackoffPolicy import androidx.work.Constraints import androidx.work.CoroutineWorker -import androidx.work.Data import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.ForegroundInfo import androidx.work.NetworkType @@ -98,12 +99,12 @@ class TrackWorker @AssistedInject constructor( private suspend fun doWorkImpl(isFullRun: Boolean): Result { if (!settings.isTrackerEnabled) { - return Result.success(workDataOf(0, 0)) + return Result.success() } val tracks = tracker.getTracks(if (isFullRun) Int.MAX_VALUE else BATCH_SIZE) logger.log("Total ${tracks.size} tracks") if (tracks.isEmpty()) { - return Result.success(workDataOf(0, 0)) + return Result.success() } val notifications = checkUpdatesAsync(tracks) @@ -218,15 +219,22 @@ class TrackWorker @AssistedInject constructor( NotificationCompat.FOREGROUND_SERVICE_DEFERRED }, ) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val actionIntent = PendingIntentCompat.getActivity( + applicationContext, SETTINGS_ACTION_CODE, + Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) + .putExtra(Settings.EXTRA_APP_PACKAGE, applicationContext.packageName) + .putExtra(Settings.EXTRA_CHANNEL_ID, WORKER_CHANNEL_ID), + 0, false, + ) + addAction( + R.drawable.ic_settings, + applicationContext.getString(R.string.notifications_settings), + actionIntent, + ) + } }.build() - private fun workDataOf(success: Int, failed: Int): Data { - return Data.Builder() - .putInt(DATA_KEY_SUCCESS, success) - .putInt(DATA_KEY_FAILED, failed) - .build() - } - @Reusable class Scheduler @Inject constructor( private val workManager: WorkManager, @@ -294,8 +302,7 @@ class TrackWorker @AssistedInject constructor( const val TAG = "tracking" const val TAG_ONESHOT = "tracking_oneshot" const val MAX_PARALLELISM = 6 - const val DATA_KEY_SUCCESS = "success" - const val DATA_KEY_FAILED = "failed" val BATCH_SIZE = if (BuildConfig.DEBUG) 20 else 46 + const val SETTINGS_ACTION_CODE = 5 } }