diff --git a/app/src/test/kotlin/org/meshtastic/app/service/Fakes.kt b/app/src/test/kotlin/org/meshtastic/app/service/Fakes.kt index 37c19f477..46d5ed27c 100644 --- a/app/src/test/kotlin/org/meshtastic/app/service/Fakes.kt +++ b/app/src/test/kotlin/org/meshtastic/app/service/Fakes.kt @@ -74,6 +74,8 @@ class FakeMeshServiceNotifications : MeshServiceNotifications { override fun cancelMessageNotification(contactKey: String) {} + override suspend fun markConversationRead(contactKey: String) {} + override fun cancelLowBatteryNotification(node: Node) {} override fun clearClientNotification(notification: ClientNotification) {} diff --git a/core/repository/src/commonMain/kotlin/org/meshtastic/core/repository/MeshServiceNotifications.kt b/core/repository/src/commonMain/kotlin/org/meshtastic/core/repository/MeshServiceNotifications.kt index a68157943..1216f29a3 100644 --- a/core/repository/src/commonMain/kotlin/org/meshtastic/core/repository/MeshServiceNotifications.kt +++ b/core/repository/src/commonMain/kotlin/org/meshtastic/core/repository/MeshServiceNotifications.kt @@ -67,6 +67,13 @@ interface MeshServiceNotifications { fun cancelMessageNotification(contactKey: String) + /** + * Marks the conversation for [contactKey] as read: clears its unread count in the packet repository and cancels the + * posted message notification (and the group summary). Intended for use by notification action receivers (reply, + * mark-as-read, reaction) to keep behavior consistent. + */ + suspend fun markConversationRead(contactKey: String) + fun cancelLowBatteryNotification(node: Node) fun clearClientNotification(notification: ClientNotification) diff --git a/core/service/src/androidMain/kotlin/org/meshtastic/core/service/MarkAsReadReceiver.kt b/core/service/src/androidMain/kotlin/org/meshtastic/core/service/MarkAsReadReceiver.kt index 36c26c879..8eb3af994 100644 --- a/core/service/src/androidMain/kotlin/org/meshtastic/core/service/MarkAsReadReceiver.kt +++ b/core/service/src/androidMain/kotlin/org/meshtastic/core/service/MarkAsReadReceiver.kt @@ -24,18 +24,14 @@ import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import org.koin.core.component.KoinComponent import org.koin.core.component.inject -import org.meshtastic.core.common.util.nowMillis import org.meshtastic.core.di.CoroutineDispatchers import org.meshtastic.core.repository.MeshServiceNotifications -import org.meshtastic.core.repository.PacketRepository /** A [BroadcastReceiver] that handles "Mark as read" actions from notifications. */ class MarkAsReadReceiver : BroadcastReceiver(), KoinComponent { - private val packetRepository: PacketRepository by inject() - private val serviceNotifications: MeshServiceNotifications by inject() private val dispatchers: CoroutineDispatchers by inject() @@ -54,8 +50,7 @@ class MarkAsReadReceiver : scope.launch { try { - packetRepository.clearUnreadCount(contactKey, nowMillis) - serviceNotifications.cancelMessageNotification(contactKey) + serviceNotifications.markConversationRead(contactKey) } finally { pendingResult.finish() } diff --git a/core/service/src/androidMain/kotlin/org/meshtastic/core/service/MeshServiceNotificationsImpl.kt b/core/service/src/androidMain/kotlin/org/meshtastic/core/service/MeshServiceNotificationsImpl.kt index 3d1684cb6..97ff46766 100644 --- a/core/service/src/androidMain/kotlin/org/meshtastic/core/service/MeshServiceNotificationsImpl.kt +++ b/core/service/src/androidMain/kotlin/org/meshtastic/core/service/MeshServiceNotificationsImpl.kt @@ -515,6 +515,11 @@ class MeshServiceNotificationsImpl( notificationManager.cancel(SUMMARY_ID) } + override suspend fun markConversationRead(contactKey: String) { + packetRepository.value.clearUnreadCount(contactKey, nowMillis) + cancelMessageNotification(contactKey) + } + override fun cancelLowBatteryNotification(node: Node) = notificationManager.cancel(node.num) override fun clearClientNotification(notification: ClientNotification) = diff --git a/core/service/src/androidMain/kotlin/org/meshtastic/core/service/ReactionReceiver.kt b/core/service/src/androidMain/kotlin/org/meshtastic/core/service/ReactionReceiver.kt index f4db74403..304dff076 100644 --- a/core/service/src/androidMain/kotlin/org/meshtastic/core/service/ReactionReceiver.kt +++ b/core/service/src/androidMain/kotlin/org/meshtastic/core/service/ReactionReceiver.kt @@ -27,6 +27,7 @@ import org.koin.core.component.KoinComponent import org.koin.core.component.inject import org.meshtastic.core.di.CoroutineDispatchers import org.meshtastic.core.model.service.ServiceAction +import org.meshtastic.core.repository.MeshServiceNotifications import org.meshtastic.core.repository.ServiceRepository /** @@ -41,6 +42,8 @@ class ReactionReceiver : private val serviceRepository: ServiceRepository by inject() + private val meshServiceNotifications: MeshServiceNotifications by inject() + private val dispatchers: CoroutineDispatchers by inject() private val scope by lazy { CoroutineScope(SupervisorJob() + dispatchers.io) } @@ -57,6 +60,7 @@ class ReactionReceiver : scope.launch { try { serviceRepository.onServiceAction(ServiceAction.Reaction(reaction, replyId, contactKey)) + meshServiceNotifications.markConversationRead(contactKey) } catch (e: Exception) { Logger.e(e) { "Error sending reaction" } } finally { diff --git a/core/service/src/androidMain/kotlin/org/meshtastic/core/service/ReplyReceiver.kt b/core/service/src/androidMain/kotlin/org/meshtastic/core/service/ReplyReceiver.kt index 13fd92758..8ab6590b7 100644 --- a/core/service/src/androidMain/kotlin/org/meshtastic/core/service/ReplyReceiver.kt +++ b/core/service/src/androidMain/kotlin/org/meshtastic/core/service/ReplyReceiver.kt @@ -25,12 +25,10 @@ import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.launch import org.koin.core.component.KoinComponent import org.koin.core.component.inject -import org.meshtastic.core.common.util.nowMillis import org.meshtastic.core.di.CoroutineDispatchers import org.meshtastic.core.model.DataPacket import org.meshtastic.core.model.RadioController import org.meshtastic.core.repository.MeshServiceNotifications -import org.meshtastic.core.repository.PacketRepository /** * A [BroadcastReceiver] that handles inline replies from notifications. @@ -46,8 +44,6 @@ class ReplyReceiver : private val meshServiceNotifications: MeshServiceNotifications by inject() - private val packetRepository: PacketRepository by inject() - private val dispatchers: CoroutineDispatchers by inject() private val scope by lazy { CoroutineScope(dispatchers.io + SupervisorJob()) } @@ -69,8 +65,7 @@ class ReplyReceiver : scope.launch { try { sendMessage(message, contactKey) - packetRepository.clearUnreadCount(contactKey, nowMillis) - meshServiceNotifications.cancelMessageNotification(contactKey) + meshServiceNotifications.markConversationRead(contactKey) } finally { pendingResult.finish() } diff --git a/core/testing/src/commonMain/kotlin/org/meshtastic/core/testing/FakeMeshServiceNotifications.kt b/core/testing/src/commonMain/kotlin/org/meshtastic/core/testing/FakeMeshServiceNotifications.kt index 4f0a4b153..923d2e8aa 100644 --- a/core/testing/src/commonMain/kotlin/org/meshtastic/core/testing/FakeMeshServiceNotifications.kt +++ b/core/testing/src/commonMain/kotlin/org/meshtastic/core/testing/FakeMeshServiceNotifications.kt @@ -67,6 +67,8 @@ class FakeMeshServiceNotifications : MeshServiceNotifications { override fun cancelMessageNotification(contactKey: String) {} + override suspend fun markConversationRead(contactKey: String) {} + override fun cancelLowBatteryNotification(node: Node) {} override fun clearClientNotification(notification: ClientNotification) {} diff --git a/desktop/src/main/kotlin/org/meshtastic/desktop/notification/DesktopMeshServiceNotifications.kt b/desktop/src/main/kotlin/org/meshtastic/desktop/notification/DesktopMeshServiceNotifications.kt index 4cda00251..fd30a5be0 100644 --- a/desktop/src/main/kotlin/org/meshtastic/desktop/notification/DesktopMeshServiceNotifications.kt +++ b/desktop/src/main/kotlin/org/meshtastic/desktop/notification/DesktopMeshServiceNotifications.kt @@ -154,6 +154,10 @@ class DesktopMeshServiceNotifications(private val notificationManager: Notificat notificationManager.cancel(contactKey.hashCode()) } + override suspend fun markConversationRead(contactKey: String) { + notificationManager.cancel(contactKey.hashCode()) + } + override fun cancelLowBatteryNotification(node: Node) { notificationManager.cancel(node.num) }