Files
Qlyra/ios/Runner/KometNotifications.swift
T

106 lines
3.1 KiB
Swift

import Flutter
import UIKit
import UserNotifications
final class KometNotifications: NSObject {
static let shared = KometNotifications()
private static let chatKeys = ["komet_chat", "chatId", "chat_id"]
private var sink: FlutterEventSink?
private var pendingChatId: Int64 = 0
private var activeChatId: Int64 = 0
func start() {
UNUserNotificationCenter.current().delegate = self
}
func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
switch call.method {
case "consumeInitialChat":
let chatId = pendingChatId
pendingChatId = 0
result(chatId > 0 ? NSNumber(value: chatId) : nil)
case "setActiveChat":
activeChatId = Self.chatId(from: call.arguments)
dismissDelivered(chatId: activeChatId)
result(nil)
case "clearActiveChat":
activeChatId = 0
result(nil)
default:
result(FlutterMethodNotImplemented)
}
}
func attach(_ sink: FlutterEventSink?) {
self.sink = sink
}
func deliver(chatId: Int64) {
guard chatId > 0 else { return }
if let sink = sink {
sink(NSNumber(value: chatId))
} else {
pendingChatId = chatId
}
}
private func dismissDelivered(chatId: Int64) {
guard chatId > 0 else { return }
let center = UNUserNotificationCenter.current()
center.getDeliveredNotifications { delivered in
let identifiers = delivered
.filter { Self.chatId(from: $0.request.content.userInfo) == chatId }
.map { $0.request.identifier }
guard !identifiers.isEmpty else { return }
center.removeDeliveredNotifications(withIdentifiers: identifiers)
}
}
private static func chatId(from raw: Any?) -> Int64 {
if let number = raw as? NSNumber { return number.int64Value }
if let text = raw as? String { return Int64(text) ?? 0 }
if let map = raw as? [AnyHashable: Any] {
for key in chatKeys {
if let value = map[key], let parsed = optionalChatId(value) { return parsed }
}
}
return 0
}
private static func optionalChatId(_ raw: Any) -> Int64? {
if let number = raw as? NSNumber { return number.int64Value }
if let text = raw as? String { return Int64(text) }
return nil
}
}
extension KometNotifications: UNUserNotificationCenterDelegate {
func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void
) {
let chatId = Self.chatId(from: notification.request.content.userInfo)
if chatId > 0, chatId == activeChatId {
completionHandler([])
return
}
if #available(iOS 14.0, *) {
completionHandler([.banner, .list, .sound, .badge])
} else {
completionHandler([.alert, .sound, .badge])
}
}
func userNotificationCenter(
_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void
) {
deliver(chatId: Self.chatId(from: response.notification.request.content.userInfo))
completionHandler()
}
}