diff --git a/DcCore/DcCore/DC/events.swift b/DcCore/DcCore/DC/events.swift index b163f86b5..09872fe18 100644 --- a/DcCore/DcCore/DC/events.swift +++ b/DcCore/DcCore/DC/events.swift @@ -32,7 +32,8 @@ public enum Event { public static let incomingCallAccepted = Notification.Name(rawValue: "incomingCallAccepted") public static let outgoingCallAccepted = Notification.Name(rawValue: "outgoingCallAccepted") public static let callEnded = Notification.Name(rawValue: "callEnded") - + public static let callMissed = Notification.Name(rawValue: "callMissed") + public static let relayHelperDidChange = Notification.Name(rawValue: "relayHelperDidChange") } @@ -241,6 +242,14 @@ public class DcEventHandler { "message_id": Int(data1), ]) + case DC_EVENT_CALL_MISSED: + logger.info("☎️ DC_EVENT_CALL_MISSED(\(accountId),\(data1))") + NotificationCenter.default.post(name: Event.callMissed, object: nil, userInfo: [ + "account_id": Int(accountId), + "message_id": Int(data1), + "chat_id": Int(data2), + ]) + default: break } diff --git a/DcCore/DcCore/Helper/UNMutableNotificationContent+init.swift b/DcCore/DcCore/Helper/UNMutableNotificationContent+init.swift index a5c1f330f..a865d2746 100644 --- a/DcCore/DcCore/Helper/UNMutableNotificationContent+init.swift +++ b/DcCore/DcCore/Helper/UNMutableNotificationContent+init.swift @@ -72,7 +72,8 @@ public extension UNMutableNotificationContent { } convenience init?(forMissedCallMsg msg: DcMsg, chat: DcChat, context: DcContext) { - guard !context.isMuted(), !chat.isMuted, !canUseCallKit else { return nil } + guard msg.id != 0 else { return nil } // invalid message + guard !context.isMuted(), !chat.isMuted else { return nil } self.init() let sender = msg.getSenderName(context.getContact(id: msg.fromContactId)) title = chat.isMultiUser ? chat.name : sender @@ -80,7 +81,7 @@ public extension UNMutableNotificationContent { userInfo["account_id"] = context.id userInfo["chat_id"] = chat.id userInfo["message_id"] = msg.id - threadIdentifier = "calls" + threadIdentifier = "\(context.id)-\(chat.id)" sound = .default setRelevanceScore(for: msg, in: chat, context: context) } diff --git a/DcNotificationService/NotificationService.swift b/DcNotificationService/NotificationService.swift index b66051a20..b5eca03e7 100644 --- a/DcNotificationService/NotificationService.swift +++ b/DcNotificationService/NotificationService.swift @@ -83,6 +83,13 @@ class NotificationService: UNNotificationServiceExtension { if let content = UNMutableNotificationContent(forWebxdcNotification: event.data2String, msg: msg, chat: chat, context: dcContext) { notifications.append(content) } + } else if event.id == DC_EVENT_CALL_MISSED { + let dcContext = dcAccounts.get(id: event.accountId) + let chat = dcContext.getChat(chatId: event.data2Int) + let msg = dcContext.getMessage(id: event.data1Int) + if let content = UNMutableNotificationContent(forMissedCallMsg: msg, chat: chat, context: dcContext) { + notifications.append(content) + } } else if event.id == DC_EVENT_INCOMING_CALL { UserDefaults.pushToDebugArray("☎️") let payload: [String: Any] = [ diff --git a/deltachat-ios/Calls/CallManager.swift b/deltachat-ios/Calls/CallManager.swift index 8a0d32c20..6d363b111 100644 --- a/deltachat-ios/Calls/CallManager.swift +++ b/deltachat-ios/Calls/CallManager.swift @@ -169,21 +169,6 @@ class CallManager: NSObject { if let currentCall, currentCall.contextId == accountId, currentCall.messageId == msgId { logger.info("☎️ call to end (\(accountId),\(msgId)) is the current call :)") endCallController(uuid: currentCall.uuid) - - // call is missed if - // - not accepted elsewhere (currentCall would have been set to nil in handleIncomingCallAcceptedEvent) - // - and not accepted here (check currentCall.callAcceptedHere) - if !currentCall.callAcceptedHere, !canUseCallKit { - let dcContext = DcAccounts.shared.get(id: accountId) - let dcMsg = dcContext.getMessage(id: msgId) - let dcChat = dcContext.getChat(chatId: dcMsg.chatId) - let content = UNMutableNotificationContent(forMissedCallMsg: dcMsg, chat: dcChat, context: dcContext) - if let content { - let id = "missed-call-" + currentCall.uuid.uuidString - let request = UNNotificationRequest(identifier: id, content: content, trigger: nil) - UNUserNotificationCenter.current().add(request, withCompletionHandler: nil) - } - } } else { logger.info("☎️ call (\(accountId),\(msgId)) already ended") } diff --git a/deltachat-ios/Calls/CallViewController.swift b/deltachat-ios/Calls/CallViewController.swift index 0aef37105..9589ef451 100644 --- a/deltachat-ios/Calls/CallViewController.swift +++ b/deltachat-ios/Calls/CallViewController.swift @@ -4,7 +4,6 @@ import WebRTC // TODO: "Connecting..." and "Ringing..." status messages // TODO: Minimize call to PiP when app is opened from a deeplink (or from a notification) -// TODO: Fix missed call logic: if the missed call was from me dont send notification // TODO: Actually stop capturing mic when muted // FIXME: Still doesn't always work when in background diff --git a/deltachat-ios/Helper/NotificationManager.swift b/deltachat-ios/Helper/NotificationManager.swift index 9d210fd16..7a6fd6bc0 100644 --- a/deltachat-ios/Helper/NotificationManager.swift +++ b/deltachat-ios/Helper/NotificationManager.swift @@ -16,6 +16,7 @@ public class NotificationManager { NotificationCenter.default.addObserver(self, selector: #selector(NotificationManager.handleIncomingReaction(_:)), name: Event.incomingReaction, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(NotificationManager.handleIncomingWebxdcNotify(_:)), name: Event.incomingWebxdcNotify, object: nil) NotificationCenter.default.addObserver(self, selector: #selector(NotificationManager.handleMessagesNoticed(_:)), name: Event.messagesNoticed, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(handleCallMissedEvent), name: Event.callMissed, object: nil) } deinit { @@ -162,4 +163,21 @@ public class NotificationManager { UIApplication.shared.endBackgroundTask(backgroundTask) // this line must be reached to balance call to `beginBackgroundTask` above } } + + @objc private func handleCallMissedEvent(_ notification: Notification) { + DispatchQueue.global().async { [weak self] in + guard let self, + let ui = notification.userInfo, + let accountId = ui["account_id"] as? Int, + let msgId = ui["message_id"] as? Int + else { return } + let eventContext = dcAccounts.get(id: accountId) + let dcMsg = eventContext.getMessage(id: msgId) + let dcChat = eventContext.getChat(chatId: dcMsg.chatId) + if let content = UNMutableNotificationContent(forMissedCallMsg: dcMsg, chat: dcChat, context: eventContext) { + let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: nil) + UNUserNotificationCenter.current().add(request, withCompletionHandler: nil) + } + } + } }