diff --git a/bitchat/BitchatApp.swift b/bitchat/BitchatApp.swift index c2694842..8322ff45 100644 --- a/bitchat/BitchatApp.swift +++ b/bitchat/BitchatApp.swift @@ -147,17 +147,14 @@ class NotificationDelegate: NSObject, UNUserNotificationCenterDelegate { func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { let identifier = response.notification.request.identifier + let userInfo = response.notification.request.content.userInfo // Check if this is a private message notification if identifier.hasPrefix("private-") { - // Extract sender from notification title - let title = response.notification.request.content.title - if let senderName = title.replacingOccurrences(of: "Private message from ", with: "").nilIfEmpty { - // Find peer ID and open chat - if let peerID = chatViewModel?.getPeerIDForNickname(senderName) { - DispatchQueue.main.async { - self.chatViewModel?.startPrivateChat(with: peerID) - } + // Get peer ID from userInfo + if let peerID = userInfo["peerID"] as? String { + 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) { - // 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]) } } diff --git a/bitchat/Services/NotificationService.swift b/bitchat/Services/NotificationService.swift index 4d2cbbfc..dfde4d48 100644 --- a/bitchat/Services/NotificationService.swift +++ b/bitchat/Services/NotificationService.swift @@ -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 // The NotificationDelegate will handle foreground presentation DispatchQueue.main.async { @@ -37,6 +37,9 @@ class NotificationService { content.title = title content.body = body content.sound = .default + if let userInfo = userInfo { + content.userInfo = userInfo + } let request = UNNotificationRequest( identifier: identifier, @@ -58,12 +61,13 @@ class NotificationService { 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 body = message 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) { diff --git a/bitchat/ViewModels/ChatViewModel.swift b/bitchat/ViewModels/ChatViewModel.swift index 0afbc21c..d9f539cf 100644 --- a/bitchat/ViewModels/ChatViewModel.swift +++ b/bitchat/ViewModels/ChatViewModel.swift @@ -1968,7 +1968,10 @@ extension ChatViewModel: BitchatDelegate { if isMentioned && message.sender != nickname { NotificationService.shared.sendMentionNotification(from: message.sender, message: message.content) } 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)