LibreTube/app/src/main/java/com/github/libretube/util/NotificationHelper.kt

210 lines
7.3 KiB
Kotlin
Raw Normal View History

2022-07-28 16:09:56 +05:30
package com.github.libretube.util
2022-08-26 12:12:13 +05:30
import android.app.NotificationManager
2022-07-28 16:09:56 +05:30
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
2022-09-09 00:35:51 +05:30
import android.os.Build
2022-07-28 16:09:56 +05:30
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
2022-09-20 23:23:34 +05:30
import com.github.libretube.ui.activities.MainActivity
2022-08-14 13:25:28 +05:30
import com.github.libretube.api.RetrofitInstance
import com.github.libretube.api.SubscriptionHelper
2022-09-08 22:12:52 +05:30
import com.github.libretube.constants.NOTIFICATION_WORK_NAME
import com.github.libretube.constants.PUSH_CHANNEL_ID
2022-09-08 21:59:00 +05:30
import com.github.libretube.constants.PreferenceKeys
2022-09-08 22:01:22 +05:30
import com.github.libretube.extensions.toID
2022-07-28 16:09:56 +05:30
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import java.util.concurrent.TimeUnit
2022-08-26 02:06:07 +05:30
class NotificationHelper(
private val context: Context
) {
2022-08-26 22:39:09 +05:30
val NotificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
2022-08-26 12:12:13 +05:30
// the id where notification channels start
2022-09-09 00:35:51 +05:30
private var notificationId = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
NotificationManager.activeNotifications.size + 5
} else {
5
}
2022-08-26 02:06:07 +05:30
2022-08-20 13:12:24 +05:30
/**
* Enqueue the work manager task
*/
2022-07-28 16:09:56 +05:30
fun enqueueWork(
2022-07-30 14:38:28 +05:30
existingPeriodicWorkPolicy: ExistingPeriodicWorkPolicy
2022-07-28 16:09:56 +05:30
) {
2022-07-28 19:28:22 +05:30
// get the notification preferences
2022-08-26 12:12:13 +05:30
PreferenceHelper.initialize(context)
2022-07-28 18:01:35 +05:30
val notificationsEnabled = PreferenceHelper.getBoolean(
PreferenceKeys.NOTIFICATION_ENABLED,
true
2022-07-28 16:09:56 +05:30
)
2022-07-28 18:01:35 +05:30
val checkingFrequency = PreferenceHelper.getString(
PreferenceKeys.CHECKING_FREQUENCY,
"60"
).toLong()
2022-07-29 17:18:59 +05:30
// schedule the work manager request if logged in and notifications enabled
if (notificationsEnabled && PreferenceHelper.getToken() != "") {
2022-07-31 18:06:39 +05:30
// required network type for the work
val networkType = when (
PreferenceHelper.getString(PreferenceKeys.REQUIRED_NETWORK, "all")
) {
"all" -> NetworkType.CONNECTED
"wifi" -> NetworkType.UNMETERED
"metered" -> NetworkType.METERED
else -> NetworkType.CONNECTED
}
2022-07-28 19:28:22 +05:30
// requirements for the work
// here: network needed to run the task
2022-07-28 18:01:35 +05:30
val constraints = Constraints.Builder()
2022-07-31 18:06:39 +05:30
.setRequiredNetworkType(networkType)
2022-07-28 18:01:35 +05:30
.build()
2022-07-28 19:28:22 +05:30
// create the worker
val notificationWorker = PeriodicWorkRequest.Builder(
2022-07-28 18:01:35 +05:30
NotificationWorker::class.java,
2022-07-28 18:19:02 +05:30
checkingFrequency,
TimeUnit.MINUTES
2022-07-28 16:09:56 +05:30
)
2022-07-28 18:01:35 +05:30
.setConstraints(constraints)
2022-07-28 19:28:22 +05:30
.build()
2022-07-28 18:01:35 +05:30
2022-07-28 19:28:22 +05:30
// enqueue the task
2022-07-28 18:01:35 +05:30
WorkManager.getInstance(context)
.enqueueUniquePeriodicWork(
2022-08-20 13:12:24 +05:30
NOTIFICATION_WORK_NAME,
2022-07-30 14:38:28 +05:30
existingPeriodicWorkPolicy,
2022-07-28 19:28:22 +05:30
notificationWorker
2022-07-28 18:01:35 +05:30
)
} else {
2022-07-29 17:18:59 +05:30
// cancel the work if notifications are disabled or the user is not logged in
2022-07-28 18:01:35 +05:30
WorkManager.getInstance(context)
2022-08-20 13:12:24 +05:30
.cancelUniqueWork(NOTIFICATION_WORK_NAME)
2022-07-28 18:01:35 +05:30
}
2022-07-28 16:09:56 +05:30
}
2022-07-28 18:01:35 +05:30
/**
* check whether new streams are available in subscriptions
*/
2022-08-26 02:06:07 +05:30
fun checkForNewStreams(): Boolean {
2022-08-26 12:12:13 +05:30
var success = true
2022-07-29 17:18:59 +05:30
2022-07-28 16:09:56 +05:30
val token = PreferenceHelper.getToken()
runBlocking {
val task = async {
2022-08-24 21:26:57 +05:30
if (token != "") {
RetrofitInstance.authApi.getFeed(token)
} else {
RetrofitInstance.authApi.getUnauthenticatedFeed(
SubscriptionHelper.getFormattedLocalSubscriptions()
)
}
2022-07-28 16:09:56 +05:30
}
2022-07-28 18:19:02 +05:30
// fetch the users feed
2022-07-28 18:15:29 +05:30
val videoFeed = try {
task.await()
} catch (e: Exception) {
2022-08-26 12:12:13 +05:30
success = false
2022-07-28 18:15:29 +05:30
return@runBlocking
}
2022-07-28 19:28:22 +05:30
2022-09-12 17:52:55 +05:30
val lastSeenStreamId = PreferenceHelper.getLastSeenVideoId()
2022-09-09 00:35:51 +05:30
val latestFeedStreamId = videoFeed[0].url!!.toID()
2022-07-28 19:28:22 +05:30
2022-08-26 02:06:07 +05:30
// first time notifications enabled or no new video available
if (lastSeenStreamId == "" || lastSeenStreamId == latestFeedStreamId) {
2022-08-24 21:26:57 +05:30
PreferenceHelper.setLatestVideoId(lastSeenStreamId)
2022-08-26 02:06:07 +05:30
return@runBlocking
}
// filter the new videos out
2022-09-09 00:35:51 +05:30
val lastSeenStreamItem = videoFeed.filter { it.url!!.toID() == lastSeenStreamId }
2022-08-26 02:06:07 +05:30
// 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) ->
2022-08-26 12:12:13 +05:30
createNotification(
2022-09-09 00:35:51 +05:30
group = streams[0].uploaderUrl!!.toID(),
2022-08-26 12:12:13 +05:30
title = streams[0].uploaderName.toString(),
isSummary = true
2022-08-26 02:06:07 +05:30
)
streams.forEach { streamItem ->
notificationId += 1
createNotification(
title = streamItem.title.toString(),
description = streamItem.uploaderName.toString(),
2022-09-09 00:35:51 +05:30
group = streamItem.uploaderUrl!!.toID()
2022-08-26 02:06:07 +05:30
)
2022-07-28 18:01:35 +05:30
}
}
2022-08-26 12:12:13 +05:30
// save the latest streams that got notified about
2022-09-09 00:35:51 +05:30
PreferenceHelper.setLatestVideoId(videoFeed[0].url!!.toID())
2022-07-28 18:01:35 +05:30
}
2022-07-29 17:18:59 +05:30
// return whether the work succeeded
2022-08-26 12:12:13 +05:30
return success
2022-07-28 16:09:56 +05:30
}
2022-07-28 18:15:29 +05:30
/**
* Notification that is created when new streams are found
*/
2022-08-26 02:06:07 +05:30
private fun createNotification(
title: String,
2022-08-26 12:12:13 +05:30
group: String,
description: String? = null,
isSummary: Boolean = false
2022-08-26 02:06:07 +05:30
) {
2022-07-28 16:09:56 +05:30
val intent = Intent(context, MainActivity::class.java).apply {
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
}
2022-07-30 14:51:18 +05:30
val pendingIntent: PendingIntent = PendingIntent.getActivity(
context,
0,
intent,
PendingIntent.FLAG_IMMUTABLE
)
2022-07-28 16:09:56 +05:30
2022-07-30 14:51:18 +05:30
val builder = NotificationCompat.Builder(context, PUSH_CHANNEL_ID)
2022-07-28 16:09:56 +05:30
.setContentTitle(title)
2022-08-26 02:06:07 +05:30
.setGroup(group)
.setSmallIcon(R.drawable.ic_notification)
2022-07-28 16:09:56 +05:30
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
// Set the intent that will fire when the user taps the notification
.setContentIntent(pendingIntent)
.setAutoCancel(true)
2022-08-26 02:06:07 +05:30
2022-08-26 12:34:35 +05:30
if (isSummary) {
builder.setGroupSummary(true)
} else {
builder.setContentText(description)
}
2022-08-26 02:06:07 +05:30
with(NotificationManagerCompat.from(context)) {
// notificationId is a unique int for each notification that you must define
2022-08-26 12:12:13 +05:30
notify(notificationId, builder.build())
2022-07-28 16:09:56 +05:30
}
}
}