import UIKit import Flutter import receive_sharing_intent import flutter_local_notifications @main @objc class AppDelegate: FlutterAppDelegate { var notificationInteractionChannel: FlutterMethodChannel? var fcmMethodChannel: FlutterMethodChannel? var currentEmailId: String? override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) createNotificationInteractionChannel() createFcmMethodChannel() if let payload = launchOptions?[.remoteNotification] as? [AnyHashable : Any], let emailId = payload[JmapConstants.EMAIL_ID] as? String, !emailId.isEmpty { currentEmailId = emailId } if #available(iOS 10.0, *) { UNUserNotificationCenter.current().delegate = self as UNUserNotificationCenterDelegate } FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { registry in GeneratedPluginRegistrant.register(with: registry) } let sharingIntent = SwiftReceiveSharingIntentPlugin.instance if let url = launchOptions?[UIApplication.LaunchOptionsKey.url] as? URL { if url.scheme == "mailto" { if let url = handleEmailAndress(open: url) { let corrected = launchOptions!.map { (key, value) in key != .url ? (key, value) : (key, url) } return sharingIntent.application(application, didFinishLaunchingWithOptions: Dictionary(uniqueKeysWithValues: corrected)) } } } return super.application(application, didFinishLaunchingWithOptions: launchOptions) } override func applicationDidEnterBackground(_ application: UIApplication) { updateApplicationStateInUserDefaults(false) } override func applicationWillTerminate(_ application: UIApplication) { updateApplicationStateInUserDefaults(false) } override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { let sharingIntent = SwiftReceiveSharingIntentPlugin.instance if sharingIntent.hasMatchingSchemePrefix(url: url) { return sharingIntent.application(app, open: url, options: options) } if url.scheme == "mailto" { if let url = handleEmailAndress(open: url) { return sharingIntent.application(app, open: url, options: options) } } return super.application(app, open: url, options:options) } override func applicationDidBecomeActive(_ application: UIApplication) { removeAppBadger() updateApplicationStateInUserDefaults(true) } private func handleEmailAndress(open url: URL) -> URL? { let appDomain = Bundle.main.bundleIdentifier! let appGroupId = (Bundle.main.object(forInfoDictionaryKey: "AppGroupId") as? String) ?? "group.\(Bundle.main.bundleIdentifier!)" let sharedKey = "ShareKey" var sharedText: [String] = [] if let email = url.absoluteString.components(separatedBy: ":").last { sharedText.append(email) } let userDefaults = UserDefaults(suiteName: appGroupId) userDefaults?.set(sharedText, forKey: sharedKey) userDefaults?.synchronize() return URL(string: "ShareMedia-\(appDomain)://dataUrl=\(sharedKey)#text") } // Receive displayed notifications for iOS 10 or later devices. override func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { TwakeLogger.shared.log(message: "AppDelegate::userNotificationCenter::willPresent::notification: \(notification)") TwakeLogger.shared.log(message: "AppDelegate::userNotificationCenter::willPresent::notificationContent: \(notification.request.content.userInfo)") if let notificationBadgeCount = notification.request.content.badge?.intValue, notificationBadgeCount > 0 { let newBadgeCount = UIApplication.shared.applicationIconBadgeNumber + notificationBadgeCount TwakeLogger.shared.log(message: "AppDelegate::userNotificationCenter::willPresent:newBadgeCount: \(newBadgeCount)") updateAppBadger(newBadgeCount: newBadgeCount) } if UIApplication.shared.applicationState == .active { fcmMethodChannel?.invokeMethod( CoreUtils.FCM_ON_MESSAGE_METHOD_NAME, arguments: notification.request.content.userInfo) completionHandler([]) } else if validateDisplayPushNotification(userInfo: notification.request.content.userInfo) { completionHandler([.alert, .badge, .sound]) } else { completionHandler([]) } } override func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { TwakeLogger.shared.log(message: "AppDelegate::userNotificationCenter::didReceive::response: \(response)") let currentBadgeCount = UIApplication.shared.applicationIconBadgeNumber let newBadgeCount = currentBadgeCount > 0 ? currentBadgeCount - 1 : 0 updateAppBadger(newBadgeCount: newBadgeCount) let userInfo = response.notification.request.content.userInfo if let emailId = userInfo[JmapConstants.EMAIL_ID] as? String, !emailId.isEmpty { self.notificationInteractionChannel?.invokeMethod( CoreUtils.CURRENT_EMAIL_ID_IN_NOTIFICATION_CLICK_WHEN_APP_FOREGROUND_OR_BACKGROUND, arguments: emailId) } completionHandler() } private func validateDisplayPushNotification(userInfo: [AnyHashable : Any]) -> Bool { if let emailId = userInfo[JmapConstants.EMAIL_ID] as? String, !emailId.isEmpty, UIApplication.shared.applicationState != .active { return true } return false } } extension AppDelegate { private func updateAppBadger(newBadgeCount: Int) { TwakeLogger.shared.log(message: "AppDelegate::updateAppBadger::newBadgeCount: \(newBadgeCount)") if #available(iOS 16.0, *) { UNUserNotificationCenter.current().setBadgeCount(newBadgeCount) } else { UIApplication.shared.applicationIconBadgeNumber = newBadgeCount } } private func removeAppBadger() { TwakeLogger.shared.log(message: "AppDelegate::removeAppBadger") if #available(iOS 16.0, *) { UNUserNotificationCenter.current().setBadgeCount(0) } else { UIApplication.shared.applicationIconBadgeNumber = 0 } } private func createNotificationInteractionChannel() { let controller : FlutterViewController = window?.rootViewController as! FlutterViewController self.notificationInteractionChannel = FlutterMethodChannel( name: CoreUtils.NOTIFICATION_INTERACTION_CHANNEL_NAME, binaryMessenger: controller.binaryMessenger ) self.notificationInteractionChannel?.setMethodCallHandler { (call, result) in switch call.method { case CoreUtils.CURRENT_EMAIL_ID_IN_NOTIFICATION_CLICK_WHEN_APP_TERMINATED: result(self.currentEmailId) self.currentEmailId = nil default: break } } } private func createFcmMethodChannel() { let controller : FlutterViewController = window?.rootViewController as! FlutterViewController self.fcmMethodChannel = FlutterMethodChannel( name: CoreUtils.FCM_METHOD_CHANNEL_NAME, binaryMessenger: controller.binaryMessenger ) } private func updateApplicationStateInUserDefaults(_ appIsActive: Bool) { let appGroupId = (Bundle.main.object(forInfoDictionaryKey: "AppGroupId") as? String) ?? "group.\(Bundle.main.bundleIdentifier!)" let userDefaults = UserDefaults(suiteName: appGroupId) userDefaults?.set(appIsActive, forKey: CoreUtils.APPLICATION_STATE) } }