docs: add comprehensive static daily reminders documentation
- Add static daily reminders to README.md core features and API reference - Create detailed usage guide in USAGE.md with examples and best practices - Add version 2.1.0 changelog entry documenting new reminder functionality - Create examples/static-daily-reminders.ts with complete usage examples - Update test-apps README to include reminder testing capabilities The static daily reminder feature provides simple daily notifications without network content dependency, supporting cross-platform scheduling with rich customization options.
This commit is contained in:
@@ -176,4 +176,305 @@ public class DailyNotificationPlugin: CAPPlugin {
|
||||
// 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)")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user