From 46c2fd6bf93fcd233ac3d4d4c5ae25a6c4bf1c71 Mon Sep 17 00:00:00 2001 From: James Magahern Date: Fri, 29 Mar 2024 01:04:09 -0700 Subject: [PATCH] Notifications: deep linking --- app/src/main/AndroidManifest.xml | 6 ++- .../kordophonedroid/UpdateMonitorService.kt | 39 +++++++++++++++---- .../kordophonedroid/ui/KordophoneApp.kt | 8 +++- 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 92213c5..f59fa92 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -27,10 +27,14 @@ android:theme="@style/Theme.KordophoneDroid"> - + + + + + diff --git a/app/src/main/java/net/buzzert/kordophonedroid/UpdateMonitorService.kt b/app/src/main/java/net/buzzert/kordophonedroid/UpdateMonitorService.kt index 4d790db..32d32ab 100644 --- a/app/src/main/java/net/buzzert/kordophonedroid/UpdateMonitorService.kt +++ b/app/src/main/java/net/buzzert/kordophonedroid/UpdateMonitorService.kt @@ -17,14 +17,19 @@ import android.util.Log import androidx.core.app.ActivityCompat import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat +import androidx.core.net.toUri +import androidx.navigation.NavDeepLinkBuilder +import androidx.navigation.NavDeepLinkRequest import dagger.hilt.android.AndroidEntryPoint import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import net.buzzert.kordophone.backend.model.Message import net.buzzert.kordophone.backend.server.ChatRepository +import net.buzzert.kordophonedroid.ui.Destination import javax.inject.Inject const val PUSH_CHANNEL_ID = "net.buzzert.kordophone.persistentNotification" @@ -38,6 +43,7 @@ class UpdateMonitorService: Service() @Inject lateinit var chatRepository: ChatRepository private var newMessageID: Int = 0 + private var watchJob: Job? = null private val job = SupervisorJob() private val scope = CoroutineScope(Dispatchers.IO + job) @@ -53,7 +59,18 @@ class UpdateMonitorService: Service() override fun onCreate() { super.onCreate() + Log.v(UPDATER_LOG, "UpdateMonitor onCreate: Begin watching for updates.") + createNotificationChannel(NEW_MESSAGE_CHANNEL_ID, "New Messages") + + // Connect to monitor + chatRepository.beginWatchingForUpdates(scope) + + // Connect to new message flow for notifications + watchJob?.cancel() + watchJob = scope.launch { + chatRepository.newMessages.collectLatest(::onReceiveNewMessage) + } } override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { @@ -77,14 +94,6 @@ class UpdateMonitorService: Service() startForeground(5738, notification) - // Connect to monitor - chatRepository.beginWatchingForUpdates(scope) - - // Connect to new message flow for notifications - scope.launch { - chatRepository.newMessages.collectLatest(::onReceiveNewMessage) - } - // Restart if we get killed return START_STICKY } @@ -98,25 +107,39 @@ class UpdateMonitorService: Service() if (message.conversation.unreadCount == 0) { // Not unread. + Log.v(UPDATER_LOG, "Ignoring read message.") return } if (message.sender == null) { // From me. + Log.v(UPDATER_LOG, "Ignoring message from me.") return } if (message.conversation.isGroupChat) { // For now, since these can be noisy and there's no UI for changing it, ignore group chats. + Log.v(UPDATER_LOG, "Ignoring group chat message.") return } + val guid = message.conversation.guid + val deepLinkIntent = Intent( + Intent.ACTION_VIEW, + "kordophone://messages/$guid".toUri(), + this, + MainActivity::class.java + ) + + val pendingIntent = PendingIntent.getActivity(this, 0, deepLinkIntent, PendingIntent.FLAG_IMMUTABLE) + val groupId = message.conversation.guid val notification = NotificationCompat.Builder(this, NEW_MESSAGE_CHANNEL_ID) .setContentTitle(message.sender) .setContentText(message.text) .setSmallIcon(R.drawable.stat_notify_chat) .setPriority(NotificationCompat.PRIORITY_DEFAULT) + .setContentIntent(pendingIntent) .setGroup(groupId) .build() diff --git a/app/src/main/java/net/buzzert/kordophonedroid/ui/KordophoneApp.kt b/app/src/main/java/net/buzzert/kordophonedroid/ui/KordophoneApp.kt index 35fc62d..48ff26b 100644 --- a/app/src/main/java/net/buzzert/kordophonedroid/ui/KordophoneApp.kt +++ b/app/src/main/java/net/buzzert/kordophonedroid/ui/KordophoneApp.kt @@ -17,6 +17,7 @@ import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController +import androidx.navigation.navDeepLink import kotlinx.coroutines.flow.collectLatest import net.buzzert.kordophone.backend.server.ChatRepository @@ -77,11 +78,14 @@ fun KordophoneApp( navController = navController, startDestination = Destination.ConversationList.route, ) { - composable(route = Destination.ConversationList.route) { + composable(Destination.ConversationList.route) { ConversationListScreen() } - composable(Destination.MessageList.route) { + composable( + route = Destination.MessageList.route, + deepLinks = listOf(navDeepLink { uriPattern = "kordophone://messages/{id}" }) + ) { val conversationID = it.arguments?.getString("id")!! MessageListScreen(conversationGUID = conversationID) }