kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
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.pull/1384/head
rodzic
eea62e6533
commit
80e915a36c
|
@ -270,6 +270,14 @@ class MainActivity : AppCompatActivity(), Logging {
|
|||
// We now wait for the device to connect, once connected, we ask the user if they want to switch to the new channel
|
||||
}
|
||||
|
||||
MeshServiceNotifications.OPEN_MESSAGE_ACTION -> {
|
||||
val contactKey =
|
||||
intent.getStringExtra(MeshServiceNotifications.OPEN_MESSAGE_EXTRA_CONTACT_KEY)
|
||||
val contactName =
|
||||
intent.getStringExtra(MeshServiceNotifications.OPEN_MESSAGE_EXTRA_CONTACT_NAME)
|
||||
showMessages(contactKey, contactName)
|
||||
}
|
||||
|
||||
UsbManager.ACTION_USB_DEVICE_ATTACHED -> {
|
||||
showSettingsPage()
|
||||
}
|
||||
|
@ -599,6 +607,13 @@ class MainActivity : AppCompatActivity(), Logging {
|
|||
binding.pager.currentItem = 5
|
||||
}
|
||||
|
||||
private fun showMessages(contactKey: String?, contactName: String?) {
|
||||
model.setCurrentTab(0)
|
||||
if (contactKey != null && contactName != null) {
|
||||
supportFragmentManager.navigateToMessages(contactKey, contactName)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
// Inflate the menu; this adds items to the action bar if it is present.
|
||||
menuInflater.inflate(R.menu.menu_main, menu)
|
||||
|
|
|
@ -247,7 +247,7 @@ class MeshService : Service(), Logging {
|
|||
startPacketQueue()
|
||||
}
|
||||
|
||||
private fun updateMessageNotification(dataPacket: DataPacket) {
|
||||
private fun updateMessageNotification(contactKey: String, dataPacket: DataPacket) {
|
||||
val message: String = when (dataPacket.dataType) {
|
||||
Portnums.PortNum.TEXT_MESSAGE_APP_VALUE -> dataPacket.text!!
|
||||
Portnums.PortNum.WAYPOINT_APP_VALUE -> {
|
||||
|
@ -256,7 +256,7 @@ class MeshService : Service(), Logging {
|
|||
|
||||
else -> return
|
||||
}
|
||||
serviceNotifications.updateMessageNotification(getSenderName(dataPacket), message)
|
||||
serviceNotifications.updateMessageNotification(contactKey, getSenderName(dataPacket), message)
|
||||
}
|
||||
|
||||
override fun onCreate() {
|
||||
|
@ -627,7 +627,7 @@ class MeshService : Service(), Logging {
|
|||
packetRepository.get().apply {
|
||||
insert(packetToSave)
|
||||
val isMuted = getContactSettings(contactKey).isMuted
|
||||
if (updateNotification && !isMuted) updateMessageNotification(dataPacket)
|
||||
if (updateNotification && !isMuted) updateMessageNotification(contactKey, dataPacket)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue