From f6511244667386f99b688eb589f65a3ec9023705 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Tue, 11 Nov 2025 01:55:28 -0800 Subject: [PATCH] feat(ios): implement permission checking and requesting methods Implemented permission management methods matching Android functionality: checkPermissionStatus(): - Checks notification authorization status - Checks Background App Refresh (iOS equivalent of exact alarm) - Returns boolean flags matching Android API - Includes allPermissionsGranted flag requestNotificationPermissions(): - Requests notification authorization from user - Returns PermissionStatus matching Android format - Includes detailed permission settings (alert, badge, sound, lockScreen, carPlay) - Handles already-granted case checkPermissions() / requestPermissions(): - Standard Capacitor permission format methods - Maps iOS authorization status to PermissionState - Compatible with Capacitor permission system iOS Adaptations: - Uses UNUserNotificationCenter for permission checks - Background App Refresh inferred from notification status - Wake lock always enabled on iOS (not applicable) Progress: 15/52 methods implemented (29% complete) --- ios/Plugin/DailyNotificationPlugin.swift | 162 +++++++++++++++++++++++ 1 file changed, 162 insertions(+) diff --git a/ios/Plugin/DailyNotificationPlugin.swift b/ios/Plugin/DailyNotificationPlugin.swift index ded74f0..cd39922 100644 --- a/ios/Plugin/DailyNotificationPlugin.swift +++ b/ios/Plugin/DailyNotificationPlugin.swift @@ -446,6 +446,168 @@ public class DailyNotificationPlugin: CAPPlugin { return UserDefaults.standard.array(forKey: "DailyNotificationSchedules") as? [[String: Any]] ?? [] } + // MARK: - Permission Methods + + /** + * Check permission status + * + * Returns boolean flags for each permission type: + * - notificationsEnabled: Notification authorization status + * - exactAlarmEnabled: Background App Refresh status (iOS equivalent) + * - wakeLockEnabled: Always true on iOS (not applicable) + * - allPermissionsGranted: All permissions granted + * + * Equivalent to Android's checkPermissionStatus method. + */ + @objc func checkPermissionStatus(_ call: CAPPluginCall) { + print("DNP-PLUGIN: Checking permission status") + + // Check notification authorization + notificationCenter.getNotificationSettings { settings in + let notificationsEnabled = settings.authorizationStatus == .authorized + + // Check Background App Refresh (iOS equivalent of exact alarm permission) + // Note: We can't directly check this, but we can infer it's enabled + // if the app is allowed to run background tasks + // For now, we'll assume it's enabled if notifications are authorized + // (Background App Refresh is a system setting, not a runtime permission) + let exactAlarmEnabled = notificationsEnabled // Simplified - actual check would require checking system settings + + // Wake lock is not applicable on iOS (always available if app is running) + let wakeLockEnabled = true + + let allPermissionsGranted = notificationsEnabled && exactAlarmEnabled && wakeLockEnabled + + let result: [String: Any] = [ + "notificationsEnabled": notificationsEnabled, + "exactAlarmEnabled": exactAlarmEnabled, + "wakeLockEnabled": wakeLockEnabled, + "allPermissionsGranted": allPermissionsGranted + ] + + print("DNP-PLUGIN: Permission status: notifications=\(notificationsEnabled), exactAlarm=\(exactAlarmEnabled), wakeLock=\(wakeLockEnabled), all=\(allPermissionsGranted)") + + DispatchQueue.main.async { + call.resolve(result) + } + } + } + + /** + * Request notification permissions + * + * Requests notification authorization from the user. + * Returns PermissionStatus matching Android API format. + * + * Equivalent to Android's requestNotificationPermissions method. + */ + @objc func requestNotificationPermissions(_ call: CAPPluginCall) { + print("DNP-PLUGIN: Requesting notification permissions") + + // Check current authorization status + notificationCenter.getNotificationSettings { settings in + if settings.authorizationStatus == .authorized { + // Already granted + let result: [String: Any] = [ + "status": "granted", + "granted": true, + "notifications": "granted", + "alert": settings.alertSetting == .enabled, + "badge": settings.badgeSetting == .enabled, + "sound": settings.soundSetting == .enabled, + "lockScreen": settings.lockScreenSetting == .enabled, + "carPlay": settings.carPlaySetting == .enabled + ] + + DispatchQueue.main.async { + call.resolve(result) + } + return + } + + // Request authorization + self.notificationCenter.requestAuthorization(options: [.alert, .sound, .badge]) { granted, error in + DispatchQueue.main.async { + if let error = error { + print("DNP-PLUGIN: Permission request failed: \(error)") + call.reject("Permission request failed: \(error.localizedDescription)") + return + } + + // Get updated settings after request + self.notificationCenter.getNotificationSettings { updatedSettings in + let result: [String: Any] = [ + "status": granted ? "granted" : "denied", + "granted": granted, + "notifications": granted ? "granted" : "denied", + "alert": updatedSettings.alertSetting == .enabled, + "badge": updatedSettings.badgeSetting == .enabled, + "sound": updatedSettings.soundSetting == .enabled, + "lockScreen": updatedSettings.lockScreenSetting == .enabled, + "carPlay": updatedSettings.carPlaySetting == .enabled + ] + + DispatchQueue.main.async { + print("DNP-PLUGIN: Permission request completed: granted=\(granted)") + call.resolve(result) + } + } + } + } + } + } + + /** + * Check permissions (Capacitor standard format) + * + * Returns PermissionStatus with notifications field as PermissionState. + * This is the standard Capacitor permission check format. + */ + @objc func checkPermissions(_ call: CAPPluginCall) { + print("DNP-PLUGIN: Checking permissions (Capacitor format)") + + notificationCenter.getNotificationSettings { settings in + let permissionState: String + switch settings.authorizationStatus { + case .authorized: + permissionState = "granted" + case .denied: + permissionState = "denied" + case .notDetermined: + permissionState = "prompt" + case .provisional: + permissionState = "provisional" + @unknown default: + permissionState = "unknown" + } + + let result: [String: Any] = [ + "status": permissionState, + "granted": settings.authorizationStatus == .authorized, + "notifications": permissionState, + "alert": settings.alertSetting == .enabled, + "badge": settings.badgeSetting == .enabled, + "sound": settings.soundSetting == .enabled, + "lockScreen": settings.lockScreenSetting == .enabled, + "carPlay": settings.carPlaySetting == .enabled + ] + + DispatchQueue.main.async { + call.resolve(result) + } + } + } + + /** + * Request permissions (alias for requestNotificationPermissions) + * + * Standard Capacitor permission request method. + */ + @objc func requestPermissions(_ call: CAPPluginCall) { + // Delegate to requestNotificationPermissions + requestNotificationPermissions(call) + } + // MARK: - Private Implementation Methods private func setupBackgroundTasks() {