From 082a70f54f40a95f23b4dca7c36207fd35fdab30 Mon Sep 17 00:00:00 2001 From: Matthew Raymer Date: Tue, 11 Nov 2025 02:17:02 -0800 Subject: [PATCH] feat(ios): implement getSchedules, getSchedule, getConfig, and setConfig methods Implemented database access methods using UserDefaults: getSchedules(): - Returns schedules matching optional filters (kind, enabled) - Filters by schedule type ('fetch' | 'notify') - Filters by enabled status (true/false/undefined) - Returns schedules array matching Android API getSchedule(): - Returns single schedule by ID - Returns null if not found - Matches Android getSchedule method getConfig(): - Returns configuration value by key - Supports optional timesafariDid for scoped configs - Returns null if config not found - Uses UserDefaults with key prefix setConfig(): - Stores configuration value by key - Supports optional timesafariDid for scoped configs - Stores as JSON string in UserDefaults - Matches Android setConfig method iOS Adaptations: - Uses UserDefaults instead of SQLite database - Config keys prefixed with 'DailyNotificationConfig_' - DID-scoped configs use composite keys - JSON serialization for complex values Progress: 40/52 methods implemented (77% complete) --- ios/Plugin/DailyNotificationPlugin.swift | 136 +++++++++++++++++++++++ 1 file changed, 136 insertions(+) diff --git a/ios/Plugin/DailyNotificationPlugin.swift b/ios/Plugin/DailyNotificationPlugin.swift index 7196a18..033d852 100644 --- a/ios/Plugin/DailyNotificationPlugin.swift +++ b/ios/Plugin/DailyNotificationPlugin.swift @@ -540,6 +540,142 @@ public class DailyNotificationPlugin: CAPPlugin { return UserDefaults.standard.array(forKey: "DailyNotificationSchedules") as? [[String: Any]] ?? [] } + // MARK: - Database Access Methods + + /** + * Get schedules + * + * Returns schedules matching optional filters (kind, enabled). + * + * Equivalent to Android's getSchedules method. + */ + @objc func getSchedules(_ call: CAPPluginCall) { + let options = call.getObject("options") + let kind = options?["kind"] as? String + let enabled = options?["enabled"] as? Bool + + print("DNP-PLUGIN: Getting schedules: kind=\(kind ?? "all"), enabled=\(enabled?.description ?? "all")") + + var schedules = getSchedulesFromUserDefaults() + + // Apply filters + if let kindFilter = kind { + schedules = schedules.filter { ($0["kind"] as? String) == kindFilter } + } + + if let enabledFilter = enabled { + schedules = schedules.filter { ($0["enabled"] as? Bool) == enabledFilter } + } + + let result: [String: Any] = [ + "schedules": schedules + ] + + print("DNP-PLUGIN: Found \(schedules.count) schedule(s)") + call.resolve(result) + } + + /** + * Get schedule by ID + * + * Returns a single schedule by ID. + * + * Equivalent to Android's getSchedule method. + */ + @objc func getSchedule(_ call: CAPPluginCall) { + guard let id = call.getString("id") else { + call.reject("Schedule ID is required") + return + } + + print("DNP-PLUGIN: Getting schedule: \(id)") + + let schedules = getSchedulesFromUserDefaults() + let schedule = schedules.first { ($0["id"] as? String) == id } + + if let schedule = schedule { + call.resolve(schedule) + } else { + call.resolve(["schedule": NSNull()]) + } + } + + /** + * Get config + * + * Returns configuration value by key. + * + * Equivalent to Android's getConfig method. + */ + @objc func getConfig(_ call: CAPPluginCall) { + guard let key = call.getString("key") else { + call.reject("Config key is required") + return + } + + let options = call.getObject("options") + let timesafariDid = options?["timesafariDid"] as? String + + print("DNP-PLUGIN: Getting config: key=\(key), did=\(timesafariDid ?? "none")") + + // Build config key (include DID if provided) + let configKey = timesafariDid != nil ? "\(key)_\(timesafariDid!)" : key + let fullKey = "DailyNotificationConfig_\(configKey)" + + // Try to get config from UserDefaults + if let configString = UserDefaults.standard.string(forKey: fullKey), + let configData = configString.data(using: .utf8), + let config = try? JSONSerialization.jsonObject(with: configData) as? [String: Any] { + call.resolve(config) + } else { + // Return null if not found + call.resolve(["config": NSNull()]) + } + } + + /** + * Set config + * + * Stores configuration value by key. + * + * Equivalent to Android's setConfig method. + */ + @objc func setConfig(_ call: CAPPluginCall) { + guard let key = call.getString("key") else { + call.reject("Config key is required") + return + } + + guard let value = call.getObject("value") else { + call.reject("Config value is required") + return + } + + let options = call.getObject("options") + let timesafariDid = options?["timesafariDid"] as? String + + print("DNP-PLUGIN: Setting config: key=\(key), did=\(timesafariDid ?? "none")") + + // Build config key (include DID if provided) + let configKey = timesafariDid != nil ? "\(key)_\(timesafariDid!)" : key + let fullKey = "DailyNotificationConfig_\(configKey)" + + // Store config as JSON string + do { + let configData = try JSONSerialization.data(withJSONObject: value, options: []) + let configString = String(data: configData, encoding: .utf8) ?? "{}" + + UserDefaults.standard.set(configString, forKey: fullKey) + UserDefaults.standard.synchronize() + + print("DNP-PLUGIN: Config stored successfully") + call.resolve() + } catch { + print("DNP-PLUGIN: Failed to store config: \(error)") + call.reject("Failed to store config: \(error.localizedDescription)") + } + } + // MARK: - Permission Methods /**