feat: show unique messaging notifications per contact (#1381)

* Show unique notifications per contact

Instead of a single notification for all messages, each contact now has its own, unique notification. This uses the `NotificationCompat.MessagingStyle` and the contact's name to create distinct notifications, enhancing message organization.

* feat: Add notification tap action to open contacts tab

This is done by:
- Adding an intent extra to the notification with the contact key for future use to navigate to the message thread.
- Adding a new action to the MainActivity to handle the intent.
- Updating the message notification to include the intent.

* Open message notification to the correct conversation

Adds an extra to the message notification intent to open the correct conversation. This ensures that when a user taps on a message notification, they are taken to the conversation with the sender of that message.
This commit is contained in:
James Rich 2024-11-04 16:05:39 -06:00 committed by GitHub
parent eea62e6533
commit 80e915a36c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 45 additions and 14 deletions

View file

@ -12,6 +12,7 @@ import android.media.RingtoneManager
import android.os.Build
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import androidx.core.app.Person
import com.geeksville.mesh.MainActivity
import com.geeksville.mesh.R
import com.geeksville.mesh.TelemetryProtos.LocalStats
@ -29,13 +30,16 @@ class MeshServiceNotifications(
companion object {
private const val FIFTEEN_MINUTES_IN_MILLIS = 15L * 60 * 1000
const val OPEN_MESSAGE_ACTION = "com.geeksville.mesh.OPEN_MESSAGE_ACTION"
const val OPEN_MESSAGE_EXTRA_CONTACT_KEY = "com.geeksville.mesh.OPEN_MESSAGE_EXTRA_CONTACT_KEY"
const val OPEN_MESSAGE_EXTRA_CONTACT_NAME =
"com.geeksville.mesh.OPEN_MESSAGE_EXTRA_CONTACT_NAME"
}
private val notificationManager: NotificationManager get() = context.notificationManager
// We have two notification channels: one for general service status and another one for messages
val notifyId = 101
private val messageNotifyId = 102
@RequiresApi(Build.VERSION_CODES.O)
private fun createNotificationChannel(): String {
@ -165,10 +169,10 @@ class MeshServiceNotifications(
)
}
fun updateMessageNotification(name: String, message: String) =
fun updateMessageNotification(contactKey: String, name: String, message: String) =
notificationManager.notify(
messageNotifyId,
createMessageNotification(name, message)
contactKey.hashCode(), // show unique notifications,
createMessageNotification(contactKey, name, message)
)
fun showNewNodeSeenNotification(node: NodeEntity) {
@ -187,6 +191,21 @@ class MeshServiceNotifications(
)
}
private fun openMessageIntent(contactKey: String, contactName: String): PendingIntent {
val intent = Intent(context, MainActivity::class.java)
intent.action = OPEN_MESSAGE_ACTION
intent.putExtra(OPEN_MESSAGE_EXTRA_CONTACT_KEY, contactKey)
intent.putExtra(OPEN_MESSAGE_EXTRA_CONTACT_NAME, contactName)
val pendingIntent = PendingIntent.getActivity(
context,
0,
intent,
PendingIntentCompat.FLAG_IMMUTABLE
)
return pendingIntent
}
private fun commonBuilder(channel: String): NotificationCompat.Builder {
val builder = NotificationCompat.Builder(context, channel)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
@ -246,22 +265,19 @@ class MeshServiceNotifications(
}
lateinit var messageNotificationBuilder: NotificationCompat.Builder
private fun createMessageNotification(name: String, message: String): Notification {
private fun createMessageNotification(contactKey: String, name: String, message: String): Notification {
if (!::messageNotificationBuilder.isInitialized) {
messageNotificationBuilder = commonBuilder(messageChannelId)
}
val person = Person.Builder().setName(name).build()
with(messageNotificationBuilder) {
setContentIntent(openMessageIntent(contactKey, name))
priority = NotificationCompat.PRIORITY_DEFAULT
setCategory(Notification.CATEGORY_MESSAGE)
setAutoCancel(true)
setContentTitle(name)
setContentText(message)
setStyle(
NotificationCompat.BigTextStyle()
.bigText(message),
NotificationCompat.MessagingStyle(person).addMessage(message, System.currentTimeMillis(), person)
)
setWhen(System.currentTimeMillis())
setShowWhen(true)
}
return messageNotificationBuilder.build()
}