From 68f4752c66b24c76d89344f9332e71fc1bae03c9 Mon Sep 17 00:00:00 2001 From: KotlinGeekDev Date: Wed, 18 Oct 2023 03:20:22 +0100 Subject: [PATCH] Introduce PushDistributorHandler and wire up PushMessageReceiver and PushNotificationUtils. --- .../notifications/PushDistributorHandler.kt | 43 +++++++++++++ .../notifications/PushMessageReceiver.kt | 62 +++++++++++++++++-- .../notifications/PushNotificationUtils.kt | 15 ++++- 3 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushDistributorHandler.kt diff --git a/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushDistributorHandler.kt b/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushDistributorHandler.kt new file mode 100644 index 000000000..60c272285 --- /dev/null +++ b/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushDistributorHandler.kt @@ -0,0 +1,43 @@ +package com.vitorpamplona.amethyst.service.notifications + +import com.vitorpamplona.amethyst.Amethyst +import org.unifiedpush.android.connector.UnifiedPush + +interface PushDistributorActions { + fun getSavedDistributor(): String + fun getInstalledDistributors(): List + fun saveDistributor(distributor: String) + fun removeSavedDistributor() +} +class PushDistributorHandler() : PushDistributorActions { + private val appContext = Amethyst.instance.applicationContext + private val unifiedPush: UnifiedPush = UnifiedPush() + + private var endpointInternal = "" + val endpoint = endpointInternal + + fun getEndpoint() = endpoint + fun setEndpoint(newEndpoint: String) { + endpointInternal = newEndpoint + } + + override fun getSavedDistributor(): String { + return unifiedPush.getDistributor(appContext) + } + + fun savedDistributorExists(): Boolean = getSavedDistributor().isNotEmpty() + + override fun getInstalledDistributors(): List { + return unifiedPush.getDistributors(appContext) + } + + override fun saveDistributor(distributor: String) { + unifiedPush.saveDistributor(appContext, distributor) + } + + override fun removeSavedDistributor() { + unifiedPush.safeRemoveDistributor(appContext) + } +} + +fun UnifiedPush() = UnifiedPush diff --git a/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushMessageReceiver.kt b/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushMessageReceiver.kt index 14d05a96b..a232c3ea6 100644 --- a/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushMessageReceiver.kt +++ b/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushMessageReceiver.kt @@ -1,27 +1,81 @@ package com.vitorpamplona.amethyst.service.notifications +import android.app.NotificationManager import android.content.Context import android.content.Intent +import android.util.Log +import android.util.LruCache +import androidx.core.content.ContextCompat +import com.vitorpamplona.amethyst.Amethyst +import com.vitorpamplona.amethyst.LocalPreferences +import com.vitorpamplona.amethyst.service.notifications.NotificationUtils.getOrCreateDMChannel +import com.vitorpamplona.amethyst.service.notifications.NotificationUtils.getOrCreateZapChannel +import com.vitorpamplona.quartz.events.Event +import com.vitorpamplona.quartz.events.GiftWrapEvent +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.cancel +import kotlinx.coroutines.launch import org.unifiedpush.android.connector.MessagingReceiver -class PushMessageReceiver: MessagingReceiver() { +class PushMessageReceiver : MessagingReceiver() { + private val appContext = Amethyst.instance.applicationContext + private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob()) + private val eventCache = LruCache(100) + private val pushHandler = PushDistributorHandler() + override fun onMessage(context: Context, message: ByteArray, instance: String) { - super.onMessage(context, message, instance) + val messageStr = String(message) + Log.d("Amethyst-OSSPush", "New message ${message.decodeToString()} for Instance: $instance") + scope.launch { + parseMessage(messageStr)?.let { + receiveIfNew(it) + } + } + } + + private suspend fun parseMessage(message: String): GiftWrapEvent? { + (Event.fromJson(message) as? GiftWrapEvent)?.let { + return it + } + return null + } + + private suspend fun receiveIfNew(event: GiftWrapEvent) { + if (eventCache.get(event.id) == null) { + eventCache.put(event.id, event.id) + EventNotificationConsumer(appContext).consume(event) + } } override fun onNewEndpoint(context: Context, endpoint: String, instance: String) { - super.onNewEndpoint(context, endpoint, instance) + Log.d("Amethyst-OSSPush", "New endpoint provided:- $endpoint for Instance: $instance") + pushHandler.setEndpoint(endpoint) + scope.launch(Dispatchers.IO) { + RegisterAccounts(LocalPreferences.allSavedAccounts()).go(endpoint) + notificationManager().getOrCreateZapChannel(appContext) + notificationManager().getOrCreateDMChannel(appContext) + } } override fun onReceive(context: Context, intent: Intent) { + val intentData = intent.dataString + val intentAction = intent.action.toString() + Log.d("Amethyst-OSSPush", "Intent Data:- $intentData Intent Action: $intentAction") super.onReceive(context, intent) } override fun onRegistrationFailed(context: Context, instance: String) { + scope.cancel() super.onRegistrationFailed(context, instance) } override fun onUnregistered(context: Context, instance: String) { super.onUnregistered(context, instance) } -} \ No newline at end of file + + fun notificationManager(): NotificationManager { + return ContextCompat.getSystemService(appContext, NotificationManager::class.java) as NotificationManager + } +} diff --git a/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushNotificationUtils.kt b/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushNotificationUtils.kt index 2855d5e5a..733735ee3 100644 --- a/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushNotificationUtils.kt +++ b/app/src/fdroid/java/com/vitorpamplona/amethyst/service/notifications/PushNotificationUtils.kt @@ -1,9 +1,20 @@ package com.vitorpamplona.amethyst.service.notifications +import android.util.Log import com.vitorpamplona.amethyst.AccountInfo +import kotlinx.coroutines.Dispatchers object PushNotificationUtils { - var hasInit: Boolean = true - suspend fun init(accounts: List) { + var hasInit: Boolean = false + private val pushHandler = PushDistributorHandler() + suspend fun init(accounts: List) = with(Dispatchers.IO) { + if (hasInit || pushHandler.savedDistributorExists()) { + return@with + } + try { + RegisterAccounts(accounts).go(pushHandler.getEndpoint()) + } catch (e: Exception) { + Log.d("Amethyst-OSSPushUtils", "Failed to get endpoint.") + } } }