You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							480 lines
						
					
					
						
							17 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							480 lines
						
					
					
						
							17 KiB
						
					
					
				
								//
							 | 
						|
								//  DailyNotificationPlugin.swift
							 | 
						|
								//  DailyNotificationPlugin
							 | 
						|
								//
							 | 
						|
								//  Created by Matthew Raymer on 2025-09-22
							 | 
						|
								//  Copyright © 2025 TimeSafari. All rights reserved.
							 | 
						|
								//
							 | 
						|
								
							 | 
						|
								import Foundation
							 | 
						|
								import Capacitor
							 | 
						|
								import UserNotifications
							 | 
						|
								import BackgroundTasks
							 | 
						|
								import CoreData
							 | 
						|
								
							 | 
						|
								/**
							 | 
						|
								 * iOS implementation of Daily Notification Plugin
							 | 
						|
								 * Implements BGTaskScheduler + UNUserNotificationCenter for dual scheduling
							 | 
						|
								 * 
							 | 
						|
								 * @author Matthew Raymer
							 | 
						|
								 * @version 1.1.0
							 | 
						|
								 * @created 2025-09-22 09:22:32 UTC
							 | 
						|
								 */
							 | 
						|
								@objc(DailyNotificationPlugin)
							 | 
						|
								public class DailyNotificationPlugin: CAPPlugin {
							 | 
						|
								    
							 | 
						|
								    private let notificationCenter = UNUserNotificationCenter.current()
							 | 
						|
								    private let backgroundTaskScheduler = BGTaskScheduler.shared
							 | 
						|
								    private let persistenceController = PersistenceController.shared
							 | 
						|
								    
							 | 
						|
								    // Background task identifiers
							 | 
						|
								    private let fetchTaskIdentifier = "com.timesafari.dailynotification.fetch"
							 | 
						|
								    private let notifyTaskIdentifier = "com.timesafari.dailynotification.notify"
							 | 
						|
								    
							 | 
						|
								    override public func load() {
							 | 
						|
								        super.load()
							 | 
						|
								        setupBackgroundTasks()
							 | 
						|
								        print("DNP-PLUGIN: Daily Notification Plugin loaded on iOS")
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    // MARK: - Configuration Methods
							 | 
						|
								    
							 | 
						|
								    @objc func configure(_ call: CAPPluginCall) {
							 | 
						|
								        guard let options = call.getObject("options") else {
							 | 
						|
								            call.reject("Configuration options required")
							 | 
						|
								            return
							 | 
						|
								        }
							 | 
						|
								        
							 | 
						|
								        print("DNP-PLUGIN: Configure called with options: \(options)")
							 | 
						|
								        
							 | 
						|
								        // Store configuration in UserDefaults
							 | 
						|
								        UserDefaults.standard.set(options, forKey: "DailyNotificationConfig")
							 | 
						|
								        
							 | 
						|
								        call.resolve()
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    // MARK: - Dual Scheduling Methods
							 | 
						|
								    
							 | 
						|
								    @objc func scheduleContentFetch(_ call: CAPPluginCall) {
							 | 
						|
								        guard let config = call.getObject("config") else {
							 | 
						|
								            call.reject("Content fetch config required")
							 | 
						|
								            return
							 | 
						|
								        }
							 | 
						|
								        
							 | 
						|
								        print("DNP-PLUGIN: Scheduling content fetch")
							 | 
						|
								        
							 | 
						|
								        do {
							 | 
						|
								            try scheduleBackgroundFetch(config: config)
							 | 
						|
								            call.resolve()
							 | 
						|
								        } catch {
							 | 
						|
								            print("DNP-PLUGIN: Failed to schedule content fetch: \(error)")
							 | 
						|
								            call.reject("Content fetch scheduling failed: \(error.localizedDescription)")
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    @objc func scheduleUserNotification(_ call: CAPPluginCall) {
							 | 
						|
								        guard let config = call.getObject("config") else {
							 | 
						|
								            call.reject("User notification config required")
							 | 
						|
								            return
							 | 
						|
								        }
							 | 
						|
								        
							 | 
						|
								        print("DNP-PLUGIN: Scheduling user notification")
							 | 
						|
								        
							 | 
						|
								        do {
							 | 
						|
								            try scheduleUserNotification(config: config)
							 | 
						|
								            call.resolve()
							 | 
						|
								        } catch {
							 | 
						|
								            print("DNP-PLUGIN: Failed to schedule user notification: \(error)")
							 | 
						|
								            call.reject("User notification scheduling failed: \(error.localizedDescription)")
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    @objc func scheduleDualNotification(_ call: CAPPluginCall) {
							 | 
						|
								        guard let config = call.getObject("config"),
							 | 
						|
								              let contentFetchConfig = config["contentFetch"] as? [String: Any],
							 | 
						|
								              let userNotificationConfig = config["userNotification"] as? [String: Any] else {
							 | 
						|
								            call.reject("Dual notification config required")
							 | 
						|
								            return
							 | 
						|
								        }
							 | 
						|
								        
							 | 
						|
								        print("DNP-PLUGIN: Scheduling dual notification")
							 | 
						|
								        
							 | 
						|
								        do {
							 | 
						|
								            try scheduleBackgroundFetch(config: contentFetchConfig)
							 | 
						|
								            try scheduleUserNotification(config: userNotificationConfig)
							 | 
						|
								            call.resolve()
							 | 
						|
								        } catch {
							 | 
						|
								            print("DNP-PLUGIN: Failed to schedule dual notification: \(error)")
							 | 
						|
								            call.reject("Dual notification scheduling failed: \(error.localizedDescription)")
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    @objc func getDualScheduleStatus(_ call: CAPPluginCall) {
							 | 
						|
								        Task {
							 | 
						|
								            do {
							 | 
						|
								                let status = try await getHealthStatus()
							 | 
						|
								                call.resolve(status)
							 | 
						|
								            } catch {
							 | 
						|
								                print("DNP-PLUGIN: Failed to get dual schedule status: \(error)")
							 | 
						|
								                call.reject("Status retrieval failed: \(error.localizedDescription)")
							 | 
						|
								            }
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    // MARK: - Private Implementation Methods
							 | 
						|
								    
							 | 
						|
								    private func setupBackgroundTasks() {
							 | 
						|
								        // Register background fetch task
							 | 
						|
								        backgroundTaskScheduler.register(forTaskWithIdentifier: fetchTaskIdentifier, using: nil) { task in
							 | 
						|
								            self.handleBackgroundFetch(task: task as! BGAppRefreshTask)
							 | 
						|
								        }
							 | 
						|
								        
							 | 
						|
								        // Register background processing task
							 | 
						|
								        backgroundTaskScheduler.register(forTaskWithIdentifier: notifyTaskIdentifier, using: nil) { task in
							 | 
						|
								            self.handleBackgroundNotify(task: task as! BGProcessingTask)
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    private func scheduleBackgroundFetch(config: [String: Any]) throws {
							 | 
						|
								        let request = BGAppRefreshTaskRequest(identifier: fetchTaskIdentifier)
							 | 
						|
								        
							 | 
						|
								        // Calculate next run time (simplified - would use proper cron parsing in production)
							 | 
						|
								        let nextRunTime = calculateNextRunTime(from: config["schedule"] as? String ?? "0 9 * * *")
							 | 
						|
								        request.earliestBeginDate = Date(timeIntervalSinceNow: nextRunTime)
							 | 
						|
								        
							 | 
						|
								        try backgroundTaskScheduler.submit(request)
							 | 
						|
								        print("DNP-FETCH-SCHEDULE: Background fetch scheduled for \(request.earliestBeginDate!)")
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    private func scheduleUserNotification(config: [String: Any]) throws {
							 | 
						|
								        let content = UNMutableNotificationContent()
							 | 
						|
								        content.title = config["title"] as? String ?? "Daily Notification"
							 | 
						|
								        content.body = config["body"] as? String ?? "Your daily update is ready"
							 | 
						|
								        content.sound = (config["sound"] as? Bool ?? true) ? .default : nil
							 | 
						|
								        
							 | 
						|
								        // Create trigger (simplified - would use proper cron parsing in production)
							 | 
						|
								        let nextRunTime = calculateNextRunTime(from: config["schedule"] as? String ?? "0 9 * * *")
							 | 
						|
								        let trigger = UNTimeIntervalNotificationTrigger(timeInterval: nextRunTime, repeats: false)
							 | 
						|
								        
							 | 
						|
								        let request = UNNotificationRequest(
							 | 
						|
								            identifier: "daily-notification-\(Date().timeIntervalSince1970)",
							 | 
						|
								            content: content,
							 | 
						|
								            trigger: trigger
							 | 
						|
								        )
							 | 
						|
								        
							 | 
						|
								        notificationCenter.add(request) { error in
							 | 
						|
								            if let error = error {
							 | 
						|
								                print("DNP-NOTIFY-SCHEDULE: Failed to schedule notification: \(error)")
							 | 
						|
								            } else {
							 | 
						|
								                print("DNP-NOTIFY-SCHEDULE: Notification scheduled successfully")
							 | 
						|
								            }
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								    
							 | 
						|
								    private func calculateNextRunTime(from schedule: String) -> TimeInterval {
							 | 
						|
								        // Simplified implementation - would use proper cron parsing in production
							 | 
						|
								        // For now, return next day at 9 AM
							 | 
						|
								        return 86400 // 24 hours
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // MARK: - Static Daily Reminder Methods
							 | 
						|
								
							 | 
						|
								    @objc func scheduleDailyReminder(_ call: CAPPluginCall) {
							 | 
						|
								        guard let id = call.getString("id"),
							 | 
						|
								              let title = call.getString("title"),
							 | 
						|
								              let body = call.getString("body"),
							 | 
						|
								              let time = call.getString("time") else {
							 | 
						|
								            call.reject("Missing required parameters: id, title, body, time")
							 | 
						|
								            return
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        let sound = call.getBool("sound", true)
							 | 
						|
								        let vibration = call.getBool("vibration", true)
							 | 
						|
								        let priority = call.getString("priority", "normal")
							 | 
						|
								        let repeatDaily = call.getBool("repeatDaily", true)
							 | 
						|
								        let timezone = call.getString("timezone")
							 | 
						|
								
							 | 
						|
								        print("DNP-REMINDER: Scheduling daily reminder: \(id)")
							 | 
						|
								
							 | 
						|
								        // Parse time (HH:mm format)
							 | 
						|
								        let timeComponents = time.components(separatedBy: ":")
							 | 
						|
								        guard timeComponents.count == 2,
							 | 
						|
								              let hour = Int(timeComponents[0]),
							 | 
						|
								              let minute = Int(timeComponents[1]),
							 | 
						|
								              hour >= 0 && hour <= 23,
							 | 
						|
								              minute >= 0 && minute <= 59 else {
							 | 
						|
								            call.reject("Invalid time format. Use HH:mm (e.g., 09:00)")
							 | 
						|
								            return
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // Create notification content
							 | 
						|
								        let content = UNMutableNotificationContent()
							 | 
						|
								        content.title = title
							 | 
						|
								        content.body = body
							 | 
						|
								        content.sound = sound ? .default : nil
							 | 
						|
								        content.categoryIdentifier = "DAILY_REMINDER"
							 | 
						|
								
							 | 
						|
								        // Set priority
							 | 
						|
								        switch priority {
							 | 
						|
								        case "high":
							 | 
						|
								            content.interruptionLevel = .critical
							 | 
						|
								        case "low":
							 | 
						|
								            content.interruptionLevel = .passive
							 | 
						|
								        default:
							 | 
						|
								            content.interruptionLevel = .active
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        // Create date components for daily trigger
							 | 
						|
								        var dateComponents = DateComponents()
							 | 
						|
								        dateComponents.hour = hour
							 | 
						|
								        dateComponents.minute = minute
							 | 
						|
								
							 | 
						|
								        let trigger = UNCalendarNotificationTrigger(
							 | 
						|
								            dateMatching: dateComponents,
							 | 
						|
								            repeats: repeatDaily
							 | 
						|
								        )
							 | 
						|
								
							 | 
						|
								        let request = UNNotificationRequest(
							 | 
						|
								            identifier: "reminder_\(id)",
							 | 
						|
								            content: content,
							 | 
						|
								            trigger: trigger
							 | 
						|
								        )
							 | 
						|
								
							 | 
						|
								        // Store reminder in UserDefaults
							 | 
						|
								        storeReminderInUserDefaults(
							 | 
						|
								            id: id,
							 | 
						|
								            title: title,
							 | 
						|
								            body: body,
							 | 
						|
								            time: time,
							 | 
						|
								            sound: sound,
							 | 
						|
								            vibration: vibration,
							 | 
						|
								            priority: priority,
							 | 
						|
								            repeatDaily: repeatDaily,
							 | 
						|
								            timezone: timezone
							 | 
						|
								        )
							 | 
						|
								
							 | 
						|
								        // Schedule the notification
							 | 
						|
								        notificationCenter.add(request) { error in
							 | 
						|
								            DispatchQueue.main.async {
							 | 
						|
								                if let error = error {
							 | 
						|
								                    print("DNP-REMINDER: Failed to schedule reminder: \(error)")
							 | 
						|
								                    call.reject("Failed to schedule daily reminder: \(error.localizedDescription)")
							 | 
						|
								                } else {
							 | 
						|
								                    print("DNP-REMINDER: Daily reminder scheduled successfully: \(id)")
							 | 
						|
								                    call.resolve()
							 | 
						|
								                }
							 | 
						|
								            }
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    @objc func cancelDailyReminder(_ call: CAPPluginCall) {
							 | 
						|
								        guard let reminderId = call.getString("reminderId") else {
							 | 
						|
								            call.reject("Missing reminderId parameter")
							 | 
						|
								            return
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        print("DNP-REMINDER: Cancelling daily reminder: \(reminderId)")
							 | 
						|
								
							 | 
						|
								        // Cancel the notification
							 | 
						|
								        notificationCenter.removePendingNotificationRequests(withIdentifiers: ["reminder_\(reminderId)"])
							 | 
						|
								
							 | 
						|
								        // Remove from UserDefaults
							 | 
						|
								        removeReminderFromUserDefaults(id: reminderId)
							 | 
						|
								
							 | 
						|
								        call.resolve()
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    @objc func getScheduledReminders(_ call: CAPPluginCall) {
							 | 
						|
								        print("DNP-REMINDER: Getting scheduled reminders")
							 | 
						|
								
							 | 
						|
								        // Get pending notifications
							 | 
						|
								        notificationCenter.getPendingNotificationRequests { requests in
							 | 
						|
								            let reminderRequests = requests.filter { $0.identifier.hasPrefix("reminder_") }
							 | 
						|
								
							 | 
						|
								            // Get stored reminder data from UserDefaults
							 | 
						|
								            let reminders = self.getRemindersFromUserDefaults()
							 | 
						|
								
							 | 
						|
								            var result: [[String: Any]] = []
							 | 
						|
								            for reminder in reminders {
							 | 
						|
								                let isScheduled = reminderRequests.contains { $0.identifier == "reminder_\(reminder["id"] as! String)" }
							 | 
						|
								                var reminderInfo = reminder
							 | 
						|
								                reminderInfo["isScheduled"] = isScheduled
							 | 
						|
								                result.append(reminderInfo)
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            DispatchQueue.main.async {
							 | 
						|
								                call.resolve(["reminders": result])
							 | 
						|
								            }
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    @objc func updateDailyReminder(_ call: CAPPluginCall) {
							 | 
						|
								        guard let reminderId = call.getString("reminderId") else {
							 | 
						|
								            call.reject("Missing reminderId parameter")
							 | 
						|
								            return
							 | 
						|
								        }
							 | 
						|
								
							 | 
						|
								        print("DNP-REMINDER: Updating daily reminder: \(reminderId)")
							 | 
						|
								
							 | 
						|
								        // Cancel existing reminder
							 | 
						|
								        notificationCenter.removePendingNotificationRequests(withIdentifiers: ["reminder_\(reminderId)"])
							 | 
						|
								
							 | 
						|
								        // Update in UserDefaults
							 | 
						|
								        let title = call.getString("title")
							 | 
						|
								        let body = call.getString("body")
							 | 
						|
								        let time = call.getString("time")
							 | 
						|
								        let sound = call.getBool("sound")
							 | 
						|
								        let vibration = call.getBool("vibration")
							 | 
						|
								        let priority = call.getString("priority")
							 | 
						|
								        let repeatDaily = call.getBool("repeatDaily")
							 | 
						|
								        let timezone = call.getString("timezone")
							 | 
						|
								
							 | 
						|
								        updateReminderInUserDefaults(
							 | 
						|
								            id: reminderId,
							 | 
						|
								            title: title,
							 | 
						|
								            body: body,
							 | 
						|
								            time: time,
							 | 
						|
								            sound: sound,
							 | 
						|
								            vibration: vibration,
							 | 
						|
								            priority: priority,
							 | 
						|
								            repeatDaily: repeatDaily,
							 | 
						|
								            timezone: timezone
							 | 
						|
								        )
							 | 
						|
								
							 | 
						|
								        // Reschedule with new settings if all required fields are provided
							 | 
						|
								        if let title = title, let body = body, let time = time {
							 | 
						|
								            // Parse time
							 | 
						|
								            let timeComponents = time.components(separatedBy: ":")
							 | 
						|
								            guard timeComponents.count == 2,
							 | 
						|
								                  let hour = Int(timeComponents[0]),
							 | 
						|
								                  let minute = Int(timeComponents[1]) else {
							 | 
						|
								                call.reject("Invalid time format")
							 | 
						|
								                return
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            // Create new notification content
							 | 
						|
								            let content = UNMutableNotificationContent()
							 | 
						|
								            content.title = title
							 | 
						|
								            content.body = body
							 | 
						|
								            content.sound = (sound ?? true) ? .default : nil
							 | 
						|
								            content.categoryIdentifier = "DAILY_REMINDER"
							 | 
						|
								
							 | 
						|
								            // Set priority
							 | 
						|
								            let finalPriority = priority ?? "normal"
							 | 
						|
								            switch finalPriority {
							 | 
						|
								            case "high":
							 | 
						|
								                content.interruptionLevel = .critical
							 | 
						|
								            case "low":
							 | 
						|
								                content.interruptionLevel = .passive
							 | 
						|
								            default:
							 | 
						|
								                content.interruptionLevel = .active
							 | 
						|
								            }
							 | 
						|
								
							 | 
						|
								            // Create date components for daily trigger
							 | 
						|
								            var dateComponents = DateComponents()
							 | 
						|
								            dateComponents.hour = hour
							 | 
						|
								            dateComponents.minute = minute
							 | 
						|
								
							 | 
						|
								            let trigger = UNCalendarNotificationTrigger(
							 | 
						|
								                dateMatching: dateComponents,
							 | 
						|
								                repeats: repeatDaily ?? true
							 | 
						|
								            )
							 | 
						|
								
							 | 
						|
								            let request = UNNotificationRequest(
							 | 
						|
								                identifier: "reminder_\(reminderId)",
							 | 
						|
								                content: content,
							 | 
						|
								                trigger: trigger
							 | 
						|
								            )
							 | 
						|
								
							 | 
						|
								            // Schedule the updated notification
							 | 
						|
								            notificationCenter.add(request) { error in
							 | 
						|
								                DispatchQueue.main.async {
							 | 
						|
								                    if let error = error {
							 | 
						|
								                        call.reject("Failed to reschedule updated reminder: \(error.localizedDescription)")
							 | 
						|
								                    } else {
							 | 
						|
								                        call.resolve()
							 | 
						|
								                    }
							 | 
						|
								                }
							 | 
						|
								            }
							 | 
						|
								        } else {
							 | 
						|
								            call.resolve()
							 | 
						|
								        }
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    // MARK: - Helper Methods for Reminder Storage
							 | 
						|
								
							 | 
						|
								    private func storeReminderInUserDefaults(
							 | 
						|
								        id: String,
							 | 
						|
								        title: String,
							 | 
						|
								        body: String,
							 | 
						|
								        time: String,
							 | 
						|
								        sound: Bool,
							 | 
						|
								        vibration: Bool,
							 | 
						|
								        priority: String,
							 | 
						|
								        repeatDaily: Bool,
							 | 
						|
								        timezone: String?
							 | 
						|
								    ) {
							 | 
						|
								        let reminderData: [String: Any] = [
							 | 
						|
								            "id": id,
							 | 
						|
								            "title": title,
							 | 
						|
								            "body": body,
							 | 
						|
								            "time": time,
							 | 
						|
								            "sound": sound,
							 | 
						|
								            "vibration": vibration,
							 | 
						|
								            "priority": priority,
							 | 
						|
								            "repeatDaily": repeatDaily,
							 | 
						|
								            "timezone": timezone ?? "",
							 | 
						|
								            "createdAt": Date().timeIntervalSince1970,
							 | 
						|
								            "lastTriggered": 0
							 | 
						|
								        ]
							 | 
						|
								
							 | 
						|
								        var reminders = UserDefaults.standard.array(forKey: "daily_reminders") as? [[String: Any]] ?? []
							 | 
						|
								        reminders.append(reminderData)
							 | 
						|
								        UserDefaults.standard.set(reminders, forKey: "daily_reminders")
							 | 
						|
								
							 | 
						|
								        print("DNP-REMINDER: Reminder stored: \(id)")
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    private func removeReminderFromUserDefaults(id: String) {
							 | 
						|
								        var reminders = UserDefaults.standard.array(forKey: "daily_reminders") as? [[String: Any]] ?? []
							 | 
						|
								        reminders.removeAll { ($0["id"] as? String) == id }
							 | 
						|
								        UserDefaults.standard.set(reminders, forKey: "daily_reminders")
							 | 
						|
								
							 | 
						|
								        print("DNP-REMINDER: Reminder removed: \(id)")
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    private func getRemindersFromUserDefaults() -> [[String: Any]] {
							 | 
						|
								        return UserDefaults.standard.array(forKey: "daily_reminders") as? [[String: Any]] ?? []
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    private func updateReminderInUserDefaults(
							 | 
						|
								        id: String,
							 | 
						|
								        title: String?,
							 | 
						|
								        body: String?,
							 | 
						|
								        time: String?,
							 | 
						|
								        sound: Bool?,
							 | 
						|
								        vibration: Bool?,
							 | 
						|
								        priority: String?,
							 | 
						|
								        repeatDaily: Bool?,
							 | 
						|
								        timezone: String?
							 | 
						|
								    ) {
							 | 
						|
								        var reminders = UserDefaults.standard.array(forKey: "daily_reminders") as? [[String: Any]] ?? []
							 | 
						|
								        
							 | 
						|
								        for i in 0..<reminders.count {
							 | 
						|
								            if reminders[i]["id"] as? String == id {
							 | 
						|
								                if let title = title { reminders[i]["title"] = title }
							 | 
						|
								                if let body = body { reminders[i]["body"] = body }
							 | 
						|
								                if let time = time { reminders[i]["time"] = time }
							 | 
						|
								                if let sound = sound { reminders[i]["sound"] = sound }
							 | 
						|
								                if let vibration = vibration { reminders[i]["vibration"] = vibration }
							 | 
						|
								                if let priority = priority { reminders[i]["priority"] = priority }
							 | 
						|
								                if let repeatDaily = repeatDaily { reminders[i]["repeatDaily"] = repeatDaily }
							 | 
						|
								                if let timezone = timezone { reminders[i]["timezone"] = timezone }
							 | 
						|
								                break
							 | 
						|
								            }
							 | 
						|
								        }
							 | 
						|
								        
							 | 
						|
								        UserDefaults.standard.set(reminders, forKey: "daily_reminders")
							 | 
						|
								        print("DNP-REMINDER: Reminder updated: \(id)")
							 | 
						|
								    }
							 | 
						|
								}
							 |