diff --git a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt index 90a17ce2..b1894c39 100644 --- a/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt +++ b/app/src/main/java/com/bitchat/android/ui/ChatViewModel.kt @@ -35,6 +35,7 @@ class ChatViewModel(application: Application) : AndroidViewModel(application), B private val channelManager = ChannelManager(state, messageManager, dataManager, viewModelScope) val privateChatManager = PrivateChatManager(state, messageManager, dataManager) private val commandProcessor = CommandProcessor(state, messageManager, channelManager, privateChatManager) + private val notificationManager = NotificationManager(application.applicationContext) // Delegate handler for mesh callbacks private val meshDelegateHandler = MeshDelegateHandler( @@ -42,6 +43,7 @@ class ChatViewModel(application: Application) : AndroidViewModel(application), B messageManager = messageManager, channelManager = channelManager, privateChatManager = privateChatManager, + notificationManager = notificationManager, coroutineScope = viewModelScope, onHapticFeedback = { ChatViewModelUtils.triggerHapticFeedback(context) }, getMyPeerID = { meshService.myPeerID } diff --git a/app/src/main/java/com/bitchat/android/ui/MeshDelegateHandler.kt b/app/src/main/java/com/bitchat/android/ui/MeshDelegateHandler.kt index ee656059..4a98ae57 100644 --- a/app/src/main/java/com/bitchat/android/ui/MeshDelegateHandler.kt +++ b/app/src/main/java/com/bitchat/android/ui/MeshDelegateHandler.kt @@ -18,11 +18,12 @@ class MeshDelegateHandler( private val messageManager: MessageManager, private val channelManager: ChannelManager, private val privateChatManager: PrivateChatManager, + private val notificationManager: NotificationManager, private val coroutineScope: CoroutineScope, private val onHapticFeedback: () -> Unit, private val getMyPeerID: () -> String ) : BluetoothMeshDelegate { - + override fun didReceiveMessage(message: BitchatMessage) { coroutineScope.launch { // FIXED: Deduplicate messages from dual connection paths @@ -45,6 +46,9 @@ class MeshDelegateHandler( if (message.isPrivate) { // Private message privateChatManager.handleIncomingPrivateMessage(message) + if (state.getSelectedPrivateChatPeerValue() != message.senderPeerID) { + notificationManager.showPrivateMessageNotification(message.sender, message.content) + } } else if (message.channel != null) { // Channel message if (state.getJoinedChannelsValue().contains(message.channel)) { diff --git a/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt b/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt new file mode 100644 index 00000000..160eccf2 --- /dev/null +++ b/app/src/main/java/com/bitchat/android/ui/NotificationManager.kt @@ -0,0 +1,41 @@ +package com.bitchat.android.ui + +import android.app.NotificationChannel +import android.app.NotificationManager +import android.content.Context +import android.os.Build +import androidx.core.app.NotificationCompat +import com.bitchat.android.R + +class NotificationManager(private val context: Context) { + + private val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager + private val channelId = "bitchat_notifications" + + init { + createNotificationChannel() + } + + private fun createNotificationChannel() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val name = "Bitchat Notifications" + val descriptionText = "Notifications for new messages and other events" + val importance = NotificationManager.IMPORTANCE_DEFAULT + val channel = NotificationChannel(channelId, name, importance).apply { + description = descriptionText + } + notificationManager.createNotificationChannel(channel) + } + } + + fun showPrivateMessageNotification(sender: String, message: String) { + val builder = NotificationCompat.Builder(context, channelId) + .setSmallIcon(R.drawable.ic_notification) + .setContentTitle("New message from $sender") + .setContentText(message) + .setPriority(NotificationCompat.PRIORITY_DEFAULT) + .setAutoCancel(true) + + notificationManager.notify(System.currentTimeMillis().toInt(), builder.build()) + } +}