From be6cdc98d6d056b151b4fe30f56a53ff6c5eaa32 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Tue, 11 Nov 2025 02:17:59 -0800 Subject: [PATCH] feat(ios): implement createSchedule, updateSchedule, deleteSchedule, and enableSchedule methods Implemented schedule CRUD methods using UserDefaults: createSchedule(): - Creates new schedule with required kind field - Auto-generates ID if not provided (kind_timestamp) - Stores optional fields (cron, clockTime, jitterMs, backoffPolicy, stateJson) - Adds to schedules array in UserDefaults - Returns created schedule updateSchedule(): - Updates existing schedule by ID - Updates provided fields (enabled, cron, clockTime, jitterMs, backoffPolicy, stateJson, lastRunAt, nextRunAt) - Returns updated schedule - Rejects if schedule not found deleteSchedule(): - Deletes schedule by ID from UserDefaults - Removes from schedules array - Rejects if schedule not found enableSchedule(): - Enables or disables schedule by ID - Updates enabled field in schedule - Rejects if schedule not found iOS Adaptations: - Uses UserDefaults array instead of SQLite database - In-memory array manipulation then persistence - Maintains schedule structure matching Android Progress: 44/52 methods implemented (85% complete) --- ios/Plugin/DailyNotificationPlugin.swift | 182 +++++++++++++++++++++++ 1 file changed, 182 insertions(+) diff --git a/ios/Plugin/DailyNotificationPlugin.swift b/ios/Plugin/DailyNotificationPlugin.swift index 033d852..24d5063 100644 --- a/ios/Plugin/DailyNotificationPlugin.swift +++ b/ios/Plugin/DailyNotificationPlugin.swift @@ -676,6 +676,188 @@ public class DailyNotificationPlugin: CAPPlugin { } } + /** + * Create schedule + * + * Creates a new schedule and stores it in UserDefaults. + * + * Equivalent to Android's createSchedule method. + */ + @objc func createSchedule(_ call: CAPPluginCall) { + guard let scheduleJson = call.getObject("schedule") else { + call.reject("Schedule data is required") + return + } + + guard let kind = scheduleJson["kind"] as? String else { + call.reject("Schedule kind is required") + return + } + + // Generate ID if not provided + let id = scheduleJson["id"] as? String ?? "\(kind)_\(Int64(Date().timeIntervalSince1970 * 1000))" + + print("DNP-PLUGIN: Creating schedule: id=\(id), kind=\(kind)") + + // Build schedule dictionary + var schedule: [String: Any] = [ + "id": id, + "kind": kind, + "enabled": scheduleJson["enabled"] as? Bool ?? true, + "createdAt": Int64(Date().timeIntervalSince1970 * 1000) + ] + + // Add optional fields + if let cron = scheduleJson["cron"] as? String { + schedule["cron"] = cron + } + if let clockTime = scheduleJson["clockTime"] as? String { + schedule["clockTime"] = clockTime + } + if let jitterMs = scheduleJson["jitterMs"] as? Int { + schedule["jitterMs"] = jitterMs + } + if let backoffPolicy = scheduleJson["backoffPolicy"] as? String { + schedule["backoffPolicy"] = backoffPolicy + } + if let stateJson = scheduleJson["stateJson"] as? String { + schedule["stateJson"] = stateJson + } + + // Add to schedules array + var schedules = getSchedulesFromUserDefaults() + schedules.append(schedule) + UserDefaults.standard.set(schedules, forKey: "DailyNotificationSchedules") + UserDefaults.standard.synchronize() + + print("DNP-PLUGIN: Schedule created successfully") + call.resolve(schedule) + } + + /** + * Update schedule + * + * Updates an existing schedule in UserDefaults. + * + * Equivalent to Android's updateSchedule method. + */ + @objc func updateSchedule(_ call: CAPPluginCall) { + guard let id = call.getString("id") else { + call.reject("Schedule ID is required") + return + } + + guard let updates = call.getObject("updates") else { + call.reject("Updates are required") + return + } + + print("DNP-PLUGIN: Updating schedule: id=\(id)") + + var schedules = getSchedulesFromUserDefaults() + guard let index = schedules.firstIndex(where: { ($0["id"] as? String) == id }) else { + call.reject("Schedule not found: \(id)") + return + } + + // Update schedule fields + var schedule = schedules[index] + + if let enabled = updates["enabled"] as? Bool { + schedule["enabled"] = enabled + } + if let cron = updates["cron"] as? String { + schedule["cron"] = cron + } + if let clockTime = updates["clockTime"] as? String { + schedule["clockTime"] = clockTime + } + if let jitterMs = updates["jitterMs"] as? Int { + schedule["jitterMs"] = jitterMs + } + if let backoffPolicy = updates["backoffPolicy"] as? String { + schedule["backoffPolicy"] = backoffPolicy + } + if let stateJson = updates["stateJson"] as? String { + schedule["stateJson"] = stateJson + } + if let lastRunAt = updates["lastRunAt"] as? Int64 { + schedule["lastRunAt"] = lastRunAt + } + if let nextRunAt = updates["nextRunAt"] as? Int64 { + schedule["nextRunAt"] = nextRunAt + } + + schedules[index] = schedule + UserDefaults.standard.set(schedules, forKey: "DailyNotificationSchedules") + UserDefaults.standard.synchronize() + + print("DNP-PLUGIN: Schedule updated successfully") + call.resolve(schedule) + } + + /** + * Delete schedule + * + * Deletes a schedule from UserDefaults. + * + * Equivalent to Android's deleteSchedule method. + */ + @objc func deleteSchedule(_ call: CAPPluginCall) { + guard let id = call.getString("id") else { + call.reject("Schedule ID is required") + return + } + + print("DNP-PLUGIN: Deleting schedule: id=\(id)") + + var schedules = getSchedulesFromUserDefaults() + let initialCount = schedules.count + schedules.removeAll { ($0["id"] as? String) == id } + + if schedules.count == initialCount { + call.reject("Schedule not found: \(id)") + return + } + + UserDefaults.standard.set(schedules, forKey: "DailyNotificationSchedules") + UserDefaults.standard.synchronize() + + print("DNP-PLUGIN: Schedule deleted successfully") + call.resolve() + } + + /** + * Enable/disable schedule + * + * Enables or disables a schedule. + * + * Equivalent to Android's enableSchedule method. + */ + @objc func enableSchedule(_ call: CAPPluginCall) { + guard let id = call.getString("id") else { + call.reject("Schedule ID is required") + return + } + + let enabled = call.getBool("enabled") ?? true + + print("DNP-PLUGIN: Setting schedule enabled: id=\(id), enabled=\(enabled)") + + var schedules = getSchedulesFromUserDefaults() + guard let index = schedules.firstIndex(where: { ($0["id"] as? String) == id }) else { + call.reject("Schedule not found: \(id)") + return + } + + schedules[index]["enabled"] = enabled + UserDefaults.standard.set(schedules, forKey: "DailyNotificationSchedules") + UserDefaults.standard.synchronize() + + print("DNP-PLUGIN: Schedule enabled status updated") + call.resolve() + } + // MARK: - Permission Methods /**