From 8707059d6ed8f1ecad0442c88e74163cbe81f2e3 Mon Sep 17 00:00:00 2001 From: Bnyro Date: Sun, 6 Nov 2022 10:21:37 +0100 Subject: [PATCH] notifications cleanup --- .../java/com/github/libretube/LibreTubeApp.kt | 3 +- .../ui/preferences/NotificationSettings.kt | 3 +- .../libretube/util/NotificationHelper.kt | 140 +----------------- .../libretube/util/NotificationWorker.kt | 138 ++++++++++++++++- 4 files changed, 142 insertions(+), 142 deletions(-) diff --git a/app/src/main/java/com/github/libretube/LibreTubeApp.kt b/app/src/main/java/com/github/libretube/LibreTubeApp.kt index 77212a998..9c75cae9b 100644 --- a/app/src/main/java/com/github/libretube/LibreTubeApp.kt +++ b/app/src/main/java/com/github/libretube/LibreTubeApp.kt @@ -52,7 +52,8 @@ class LibreTubeApp : Application() { /** * Initialize the notification listener in the background */ - NotificationHelper(this).enqueueWork( + NotificationHelper.enqueueWork( + context = this, existingPeriodicWorkPolicy = ExistingPeriodicWorkPolicy.KEEP ) diff --git a/app/src/main/java/com/github/libretube/ui/preferences/NotificationSettings.kt b/app/src/main/java/com/github/libretube/ui/preferences/NotificationSettings.kt index 80b87bb87..3a1f20cd0 100644 --- a/app/src/main/java/com/github/libretube/ui/preferences/NotificationSettings.kt +++ b/app/src/main/java/com/github/libretube/ui/preferences/NotificationSettings.kt @@ -45,8 +45,9 @@ class NotificationSettings : BasePreferenceFragment() { private fun updateNotificationPrefs() { // replace the previous queued work request - NotificationHelper(requireContext()) + NotificationHelper .enqueueWork( + context = requireContext(), existingPeriodicWorkPolicy = ExistingPeriodicWorkPolicy.REPLACE ) } diff --git a/app/src/main/java/com/github/libretube/util/NotificationHelper.kt b/app/src/main/java/com/github/libretube/util/NotificationHelper.kt index 7780cfbb0..ec467e9fb 100644 --- a/app/src/main/java/com/github/libretube/util/NotificationHelper.kt +++ b/app/src/main/java/com/github/libretube/util/NotificationHelper.kt @@ -1,46 +1,21 @@ package com.github.libretube.util -import android.app.NotificationManager -import android.app.PendingIntent import android.content.Context -import android.content.Intent -import android.os.Build -import androidx.core.app.NotificationCompat -import androidx.core.app.NotificationManagerCompat import androidx.work.Constraints import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.NetworkType import androidx.work.PeriodicWorkRequest import androidx.work.WorkManager -import com.github.libretube.R -import com.github.libretube.api.RetrofitInstance -import com.github.libretube.api.SubscriptionHelper import com.github.libretube.constants.NOTIFICATION_WORK_NAME -import com.github.libretube.constants.PUSH_CHANNEL_ID import com.github.libretube.constants.PreferenceKeys -import com.github.libretube.extensions.toID -import com.github.libretube.ui.activities.MainActivity -import kotlinx.coroutines.async -import kotlinx.coroutines.runBlocking import java.util.concurrent.TimeUnit -class NotificationHelper( - private val context: Context -) { - val NotificationManager = - context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager - - // the id where notification channels start - private var notificationId = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - NotificationManager.activeNotifications.size + 5 - } else { - 5 - } - +object NotificationHelper { /** * Enqueue the work manager task */ fun enqueueWork( + context: Context, existingPeriodicWorkPolicy: ExistingPeriodicWorkPolicy ) { // get the notification preferences @@ -95,115 +70,4 @@ class NotificationHelper( .cancelUniqueWork(NOTIFICATION_WORK_NAME) } } - - /** - * check whether new streams are available in subscriptions - */ - fun checkForNewStreams(): Boolean { - var success = true - - val token = PreferenceHelper.getToken() - runBlocking { - val task = async { - if (token != "") { - RetrofitInstance.authApi.getFeed(token) - } else { - RetrofitInstance.authApi.getUnauthenticatedFeed( - SubscriptionHelper.getFormattedLocalSubscriptions() - ) - } - } - // fetch the users feed - val videoFeed = try { - task.await() - } catch (e: Exception) { - success = false - return@runBlocking - } - - val lastSeenStreamId = PreferenceHelper.getLastSeenVideoId() - val latestFeedStreamId = videoFeed[0].url!!.toID() - - // first time notifications enabled or no new video available - if (lastSeenStreamId == "" || lastSeenStreamId == latestFeedStreamId) { - PreferenceHelper.setLatestVideoId(lastSeenStreamId) - return@runBlocking - } - - // filter the new videos out - val lastSeenStreamItem = videoFeed.filter { it.url!!.toID() == lastSeenStreamId } - - // previous video not found - if (lastSeenStreamItem.isEmpty()) return@runBlocking - - val lastStreamIndex = videoFeed.indexOf(lastSeenStreamItem[0]) - val newVideos = videoFeed.filterIndexed { index, _ -> - index < lastStreamIndex - } - - // group the new streams by the uploader - val channelGroups = newVideos.groupBy { it.uploaderUrl } - // create a notification for each new stream - channelGroups.forEach { (_, streams) -> - createNotification( - group = streams[0].uploaderUrl!!.toID(), - title = streams[0].uploaderName.toString(), - isSummary = true - ) - - streams.forEach { streamItem -> - notificationId += 1 - createNotification( - title = streamItem.title.toString(), - description = streamItem.uploaderName.toString(), - group = streamItem.uploaderUrl!!.toID() - ) - } - } - // save the latest streams that got notified about - PreferenceHelper.setLatestVideoId(videoFeed[0].url!!.toID()) - } - // return whether the work succeeded - return success - } - - /** - * Notification that is created when new streams are found - */ - private fun createNotification( - title: String, - group: String, - description: String? = null, - isSummary: Boolean = false - ) { - val intent = Intent(context, MainActivity::class.java).apply { - flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK - } - val pendingIntent: PendingIntent = PendingIntent.getActivity( - context, - 0, - intent, - PendingIntent.FLAG_IMMUTABLE - ) - - val builder = NotificationCompat.Builder(context, PUSH_CHANNEL_ID) - .setContentTitle(title) - .setGroup(group) - .setSmallIcon(R.drawable.ic_notification) - .setPriority(NotificationCompat.PRIORITY_DEFAULT) - // Set the intent that will fire when the user taps the notification - .setContentIntent(pendingIntent) - .setAutoCancel(true) - - if (isSummary) { - builder.setGroupSummary(true) - } else { - builder.setContentText(description) - } - - with(NotificationManagerCompat.from(context)) { - // notificationId is a unique int for each notification that you must define - notify(notificationId, builder.build()) - } - } } diff --git a/app/src/main/java/com/github/libretube/util/NotificationWorker.kt b/app/src/main/java/com/github/libretube/util/NotificationWorker.kt index ea7e06da2..b3cfc46e6 100644 --- a/app/src/main/java/com/github/libretube/util/NotificationWorker.kt +++ b/app/src/main/java/com/github/libretube/util/NotificationWorker.kt @@ -1,8 +1,22 @@ package com.github.libretube.util +import android.app.NotificationManager +import android.app.PendingIntent import android.content.Context +import android.content.Intent +import android.os.Build +import androidx.core.app.NotificationCompat +import androidx.core.app.NotificationManagerCompat import androidx.work.Worker import androidx.work.WorkerParameters +import com.github.libretube.R +import com.github.libretube.api.RetrofitInstance +import com.github.libretube.api.SubscriptionHelper +import com.github.libretube.constants.PUSH_CHANNEL_ID +import com.github.libretube.extensions.toID +import com.github.libretube.ui.activities.MainActivity +import kotlinx.coroutines.async +import kotlinx.coroutines.runBlocking /** * The notification worker which checks for new streams in a certain frequency @@ -10,11 +24,131 @@ import androidx.work.WorkerParameters class NotificationWorker(appContext: Context, parameters: WorkerParameters) : Worker(appContext, parameters) { + val NotificationManager = + appContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + + // the id where notification channels start + private var notificationId = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + NotificationManager.activeNotifications.size + 5 + } else { + 5 + } + override fun doWork(): Result { // check whether there are new streams and notify if there are some - val result = NotificationHelper(applicationContext) - .checkForNewStreams() + val result = checkForNewStreams() // return success if the API request succeeded return if (result) Result.success() else Result.retry() } + + /** + * check whether new streams are available in subscriptions + */ + fun checkForNewStreams(): Boolean { + var success = true + + val token = PreferenceHelper.getToken() + runBlocking { + val task = async { + if (token != "") { + RetrofitInstance.authApi.getFeed(token) + } else { + RetrofitInstance.authApi.getUnauthenticatedFeed( + SubscriptionHelper.getFormattedLocalSubscriptions() + ) + } + } + // fetch the users feed + val videoFeed = try { + task.await() + } catch (e: Exception) { + success = false + return@runBlocking + } + + val lastSeenStreamId = PreferenceHelper.getLastSeenVideoId() + val latestFeedStreamId = videoFeed[0].url!!.toID() + + // first time notifications enabled or no new video available + if (lastSeenStreamId == "" || lastSeenStreamId == latestFeedStreamId) { + PreferenceHelper.setLatestVideoId(lastSeenStreamId) + return@runBlocking + } + + // filter the new videos out + val lastSeenStreamItem = videoFeed.filter { it.url!!.toID() == lastSeenStreamId } + + // previous video not found + if (lastSeenStreamItem.isEmpty()) return@runBlocking + + val lastStreamIndex = videoFeed.indexOf(lastSeenStreamItem[0]) + val newVideos = videoFeed.filterIndexed { index, _ -> + index < lastStreamIndex + } + + // group the new streams by the uploader + val channelGroups = newVideos.groupBy { it.uploaderUrl } + // create a notification for each new stream + channelGroups.forEach { (_, streams) -> + createNotification( + group = streams[0].uploaderUrl!!.toID(), + title = streams[0].uploaderName.toString(), + isSummary = true + ) + + streams.forEach { streamItem -> + notificationId += 1 + createNotification( + title = streamItem.title.toString(), + description = streamItem.uploaderName.toString(), + group = streamItem.uploaderUrl!!.toID() + ) + } + } + // save the latest streams that got notified about + PreferenceHelper.setLatestVideoId(videoFeed[0].url!!.toID()) + } + // return whether the work succeeded + return success + } + + /** + * Notification that is created when new streams are found + */ + private fun createNotification( + title: String, + group: String, + description: String? = null, + isSummary: Boolean = false + ) { + val intent = Intent(applicationContext, MainActivity::class.java).apply { + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK + } + val pendingIntent: PendingIntent = PendingIntent.getActivity( + applicationContext, + 0, + intent, + PendingIntent.FLAG_IMMUTABLE + ) + + val builder = NotificationCompat.Builder(applicationContext, PUSH_CHANNEL_ID) + .setContentTitle(title) + .setGroup(group) + .setSmallIcon(R.drawable.ic_notification) + .setPriority(NotificationCompat.PRIORITY_DEFAULT) + // Set the intent that will fire when the user taps the notification + .setContentIntent(pendingIntent) + .setAutoCancel(true) + + if (isSummary) { + builder.setGroupSummary(true) + } else { + builder.setContentText(description) + } + + with(NotificationManagerCompat.from(applicationContext)) { + // notificationId is a unique int for each notification that you must define + notify(notificationId, builder.build()) + } + } }