Improve private message notification behavior

- Don't show PM notifications when the private chat is already open
- Store peer ID in notification userInfo for reliable chat opening
- Tap notification to open the correct private chat using peer ID
- Check both in ChatViewModel (when receiving) and NotificationDelegate (when presenting)
This commit is contained in:
jack
2025-07-24 12:00:01 +02:00
parent b0204afa75
commit c4ca38654d
3 changed files with 32 additions and 13 deletions
+21 -9
View File
@@ -147,17 +147,14 @@ class NotificationDelegate: NSObject, UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let identifier = response.notification.request.identifier let identifier = response.notification.request.identifier
let userInfo = response.notification.request.content.userInfo
// Check if this is a private message notification // Check if this is a private message notification
if identifier.hasPrefix("private-") { if identifier.hasPrefix("private-") {
// Extract sender from notification title // Get peer ID from userInfo
let title = response.notification.request.content.title if let peerID = userInfo["peerID"] as? String {
if let senderName = title.replacingOccurrences(of: "Private message from ", with: "").nilIfEmpty { DispatchQueue.main.async {
// Find peer ID and open chat self.chatViewModel?.startPrivateChat(with: peerID)
if let peerID = chatViewModel?.getPeerIDForNickname(senderName) {
DispatchQueue.main.async {
self.chatViewModel?.startPrivateChat(with: peerID)
}
} }
} }
} }
@@ -166,7 +163,22 @@ class NotificationDelegate: NSObject, UNUserNotificationCenterDelegate {
} }
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
// Show notification even when app is in foreground (for testing) let identifier = notification.request.identifier
let userInfo = notification.request.content.userInfo
// Check if this is a private message notification
if identifier.hasPrefix("private-") {
// Get peer ID from userInfo
if let peerID = userInfo["peerID"] as? String {
// Don't show notification if the private chat is already open
if chatViewModel?.selectedPrivateChatPeer == peerID {
completionHandler([])
return
}
}
}
// Show notification in all other cases
completionHandler([.banner, .sound]) completionHandler([.banner, .sound])
} }
} }
+7 -3
View File
@@ -29,7 +29,7 @@ class NotificationService {
} }
} }
func sendLocalNotification(title: String, body: String, identifier: String) { func sendLocalNotification(title: String, body: String, identifier: String, userInfo: [String: Any]? = nil) {
// For now, skip app state check entirely to avoid thread issues // For now, skip app state check entirely to avoid thread issues
// The NotificationDelegate will handle foreground presentation // The NotificationDelegate will handle foreground presentation
DispatchQueue.main.async { DispatchQueue.main.async {
@@ -37,6 +37,9 @@ class NotificationService {
content.title = title content.title = title
content.body = body content.body = body
content.sound = .default content.sound = .default
if let userInfo = userInfo {
content.userInfo = userInfo
}
let request = UNNotificationRequest( let request = UNNotificationRequest(
identifier: identifier, identifier: identifier,
@@ -58,12 +61,13 @@ class NotificationService {
sendLocalNotification(title: title, body: body, identifier: identifier) sendLocalNotification(title: title, body: body, identifier: identifier)
} }
func sendPrivateMessageNotification(from sender: String, message: String) { func sendPrivateMessageNotification(from sender: String, message: String, peerID: String) {
let title = "🔒 private message from \(sender)" let title = "🔒 private message from \(sender)"
let body = message let body = message
let identifier = "private-\(UUID().uuidString)" let identifier = "private-\(UUID().uuidString)"
let userInfo = ["peerID": peerID, "senderName": sender]
sendLocalNotification(title: title, body: body, identifier: identifier) sendLocalNotification(title: title, body: body, identifier: identifier, userInfo: userInfo)
} }
func sendFavoriteOnlineNotification(nickname: String) { func sendFavoriteOnlineNotification(nickname: String) {
+4 -1
View File
@@ -1968,7 +1968,10 @@ extension ChatViewModel: BitchatDelegate {
if isMentioned && message.sender != nickname { if isMentioned && message.sender != nickname {
NotificationService.shared.sendMentionNotification(from: message.sender, message: message.content) NotificationService.shared.sendMentionNotification(from: message.sender, message: message.content)
} else if message.isPrivate && message.sender != nickname { } else if message.isPrivate && message.sender != nickname {
NotificationService.shared.sendPrivateMessageNotification(from: message.sender, message: message.content) // Only send notification if the private chat is not currently open
if selectedPrivateChatPeer != message.senderPeerID {
NotificationService.shared.sendPrivateMessageNotification(from: message.sender, message: message.content, peerID: message.senderPeerID ?? "")
}
} }
#if os(iOS) #if os(iOS)