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:
@@ -1583,4 +1583,353 @@ public class DailyNotificationPlugin extends Plugin {
|
||||
call.reject("Coordination status retrieval failed: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Static Daily Reminder Methods
|
||||
@PluginMethod
|
||||
public void scheduleDailyReminder(PluginCall call) {
|
||||
try {
|
||||
Log.d(TAG, "Scheduling daily reminder");
|
||||
|
||||
// Extract reminder options
|
||||
String id = call.getString("id");
|
||||
String title = call.getString("title");
|
||||
String body = call.getString("body");
|
||||
String time = call.getString("time");
|
||||
boolean sound = call.getBoolean("sound", true);
|
||||
boolean vibration = call.getBoolean("vibration", true);
|
||||
String priority = call.getString("priority", "normal");
|
||||
boolean repeatDaily = call.getBoolean("repeatDaily", true);
|
||||
String timezone = call.getString("timezone");
|
||||
|
||||
// Validate required parameters
|
||||
if (id == null || title == null || body == null || time == null) {
|
||||
call.reject("Missing required parameters: id, title, body, time");
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse time (HH:mm format)
|
||||
String[] timeParts = time.split(":");
|
||||
if (timeParts.length != 2) {
|
||||
call.reject("Invalid time format. Use HH:mm (e.g., 09:00)");
|
||||
return;
|
||||
}
|
||||
|
||||
int hour = Integer.parseInt(timeParts[0]);
|
||||
int minute = Integer.parseInt(timeParts[1]);
|
||||
|
||||
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
|
||||
call.reject("Invalid time values. Hour must be 0-23, minute must be 0-59");
|
||||
return;
|
||||
}
|
||||
|
||||
// Create reminder content
|
||||
NotificationContent reminderContent = new NotificationContent();
|
||||
reminderContent.setId("reminder_" + id); // Prefix to identify as reminder
|
||||
reminderContent.setTitle(title);
|
||||
reminderContent.setBody(body);
|
||||
reminderContent.setSound(sound);
|
||||
reminderContent.setPriority(priority);
|
||||
reminderContent.setFetchTime(System.currentTimeMillis());
|
||||
|
||||
// Calculate next trigger time
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.set(Calendar.HOUR_OF_DAY, hour);
|
||||
calendar.set(Calendar.MINUTE, minute);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
// If time has passed today, schedule for tomorrow
|
||||
if (calendar.getTimeInMillis() <= System.currentTimeMillis()) {
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
|
||||
reminderContent.setScheduledTime(calendar.getTimeInMillis());
|
||||
|
||||
// Store reminder in database
|
||||
storeReminderInDatabase(id, title, body, time, sound, vibration, priority, repeatDaily, timezone);
|
||||
|
||||
// Schedule the notification
|
||||
boolean scheduled = scheduler.scheduleNotification(reminderContent);
|
||||
|
||||
if (scheduled) {
|
||||
Log.i(TAG, "Daily reminder scheduled successfully: " + id);
|
||||
call.resolve();
|
||||
} else {
|
||||
call.reject("Failed to schedule daily reminder");
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error scheduling daily reminder", e);
|
||||
call.reject("Daily reminder scheduling failed: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
public void cancelDailyReminder(PluginCall call) {
|
||||
try {
|
||||
Log.d(TAG, "Cancelling daily reminder");
|
||||
|
||||
String reminderId = call.getString("reminderId");
|
||||
if (reminderId == null) {
|
||||
call.reject("Missing reminderId parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
// Cancel the scheduled notification (use prefixed ID)
|
||||
scheduler.cancelNotification("reminder_" + reminderId);
|
||||
|
||||
// Remove from database
|
||||
removeReminderFromDatabase(reminderId);
|
||||
|
||||
Log.i(TAG, "Daily reminder cancelled: " + reminderId);
|
||||
call.resolve();
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error cancelling daily reminder", e);
|
||||
call.reject("Daily reminder cancellation failed: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
public void getScheduledReminders(PluginCall call) {
|
||||
try {
|
||||
Log.d(TAG, "Getting scheduled reminders");
|
||||
|
||||
// Get reminders from database
|
||||
java.util.List<DailyReminderInfo> reminders = getRemindersFromDatabase();
|
||||
|
||||
// Convert to JSObject array
|
||||
JSObject result = new JSObject();
|
||||
result.put("reminders", reminders);
|
||||
|
||||
call.resolve(result);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error getting scheduled reminders", e);
|
||||
call.reject("Failed to get scheduled reminders: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
public void updateDailyReminder(PluginCall call) {
|
||||
try {
|
||||
Log.d(TAG, "Updating daily reminder");
|
||||
|
||||
String reminderId = call.getString("reminderId");
|
||||
if (reminderId == null) {
|
||||
call.reject("Missing reminderId parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
// Extract updated options
|
||||
String title = call.getString("title");
|
||||
String body = call.getString("body");
|
||||
String time = call.getString("time");
|
||||
Boolean sound = call.getBoolean("sound");
|
||||
Boolean vibration = call.getBoolean("vibration");
|
||||
String priority = call.getString("priority");
|
||||
Boolean repeatDaily = call.getBoolean("repeatDaily");
|
||||
String timezone = call.getString("timezone");
|
||||
|
||||
// Cancel existing reminder (use prefixed ID)
|
||||
scheduler.cancelNotification("reminder_" + reminderId);
|
||||
|
||||
// Update in database
|
||||
updateReminderInDatabase(reminderId, title, body, time, sound, vibration, priority, repeatDaily, timezone);
|
||||
|
||||
// Reschedule with new settings
|
||||
if (title != null && body != null && time != null) {
|
||||
// Create new reminder content
|
||||
NotificationContent reminderContent = new NotificationContent();
|
||||
reminderContent.setId("reminder_" + reminderId); // Prefix to identify as reminder
|
||||
reminderContent.setTitle(title);
|
||||
reminderContent.setBody(body);
|
||||
reminderContent.setSound(sound != null ? sound : true);
|
||||
reminderContent.setPriority(priority != null ? priority : "normal");
|
||||
reminderContent.setFetchTime(System.currentTimeMillis());
|
||||
|
||||
// Calculate next trigger time
|
||||
String[] timeParts = time.split(":");
|
||||
int hour = Integer.parseInt(timeParts[0]);
|
||||
int minute = Integer.parseInt(timeParts[1]);
|
||||
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.set(Calendar.HOUR_OF_DAY, hour);
|
||||
calendar.set(Calendar.MINUTE, minute);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
if (calendar.getTimeInMillis() <= System.currentTimeMillis()) {
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
|
||||
reminderContent.setScheduledTime(calendar.getTimeInMillis());
|
||||
|
||||
// Schedule the updated notification
|
||||
boolean scheduled = scheduler.scheduleNotification(reminderContent);
|
||||
|
||||
if (!scheduled) {
|
||||
call.reject("Failed to reschedule updated reminder");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Log.i(TAG, "Daily reminder updated: " + reminderId);
|
||||
call.resolve();
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error updating daily reminder", e);
|
||||
call.reject("Daily reminder update failed: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// Helper methods for reminder database operations
|
||||
private void storeReminderInDatabase(String id, String title, String body, String time,
|
||||
boolean sound, boolean vibration, String priority,
|
||||
boolean repeatDaily, String timezone) {
|
||||
try {
|
||||
SharedPreferences prefs = getContext().getSharedPreferences("daily_reminders", Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
|
||||
editor.putString(id + "_title", title);
|
||||
editor.putString(id + "_body", body);
|
||||
editor.putString(id + "_time", time);
|
||||
editor.putBoolean(id + "_sound", sound);
|
||||
editor.putBoolean(id + "_vibration", vibration);
|
||||
editor.putString(id + "_priority", priority);
|
||||
editor.putBoolean(id + "_repeatDaily", repeatDaily);
|
||||
editor.putString(id + "_timezone", timezone);
|
||||
editor.putLong(id + "_createdAt", System.currentTimeMillis());
|
||||
editor.putBoolean(id + "_isScheduled", true);
|
||||
|
||||
editor.apply();
|
||||
Log.d(TAG, "Reminder stored in database: " + id);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error storing reminder in database", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeReminderFromDatabase(String id) {
|
||||
try {
|
||||
SharedPreferences prefs = getContext().getSharedPreferences("daily_reminders", Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
|
||||
editor.remove(id + "_title");
|
||||
editor.remove(id + "_body");
|
||||
editor.remove(id + "_time");
|
||||
editor.remove(id + "_sound");
|
||||
editor.remove(id + "_vibration");
|
||||
editor.remove(id + "_priority");
|
||||
editor.remove(id + "_repeatDaily");
|
||||
editor.remove(id + "_timezone");
|
||||
editor.remove(id + "_createdAt");
|
||||
editor.remove(id + "_isScheduled");
|
||||
editor.remove(id + "_lastTriggered");
|
||||
|
||||
editor.apply();
|
||||
Log.d(TAG, "Reminder removed from database: " + id);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error removing reminder from database", e);
|
||||
}
|
||||
}
|
||||
|
||||
private java.util.List<DailyReminderInfo> getRemindersFromDatabase() {
|
||||
java.util.List<DailyReminderInfo> reminders = new java.util.ArrayList<>();
|
||||
|
||||
try {
|
||||
SharedPreferences prefs = getContext().getSharedPreferences("daily_reminders", Context.MODE_PRIVATE);
|
||||
java.util.Map<String, ?> allEntries = prefs.getAll();
|
||||
|
||||
java.util.Set<String> reminderIds = new java.util.HashSet<>();
|
||||
for (String key : allEntries.keySet()) {
|
||||
if (key.endsWith("_title")) {
|
||||
String id = key.substring(0, key.length() - 6); // Remove "_title"
|
||||
reminderIds.add(id);
|
||||
}
|
||||
}
|
||||
|
||||
for (String id : reminderIds) {
|
||||
DailyReminderInfo reminder = new DailyReminderInfo();
|
||||
reminder.id = id;
|
||||
reminder.title = prefs.getString(id + "_title", "");
|
||||
reminder.body = prefs.getString(id + "_body", "");
|
||||
reminder.time = prefs.getString(id + "_time", "");
|
||||
reminder.sound = prefs.getBoolean(id + "_sound", true);
|
||||
reminder.vibration = prefs.getBoolean(id + "_vibration", true);
|
||||
reminder.priority = prefs.getString(id + "_priority", "normal");
|
||||
reminder.repeatDaily = prefs.getBoolean(id + "_repeatDaily", true);
|
||||
reminder.timezone = prefs.getString(id + "_timezone", null);
|
||||
reminder.isScheduled = prefs.getBoolean(id + "_isScheduled", false);
|
||||
reminder.createdAt = prefs.getLong(id + "_createdAt", 0);
|
||||
reminder.lastTriggered = prefs.getLong(id + "_lastTriggered", 0);
|
||||
|
||||
// Calculate next trigger time
|
||||
String[] timeParts = reminder.time.split(":");
|
||||
int hour = Integer.parseInt(timeParts[0]);
|
||||
int minute = Integer.parseInt(timeParts[1]);
|
||||
|
||||
Calendar calendar = Calendar.getInstance();
|
||||
calendar.set(Calendar.HOUR_OF_DAY, hour);
|
||||
calendar.set(Calendar.MINUTE, minute);
|
||||
calendar.set(Calendar.SECOND, 0);
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
if (calendar.getTimeInMillis() <= System.currentTimeMillis()) {
|
||||
calendar.add(Calendar.DAY_OF_MONTH, 1);
|
||||
}
|
||||
|
||||
reminder.nextTriggerTime = calendar.getTimeInMillis();
|
||||
|
||||
reminders.add(reminder);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error getting reminders from database", e);
|
||||
}
|
||||
|
||||
return reminders;
|
||||
}
|
||||
|
||||
private void updateReminderInDatabase(String id, String title, String body, String time,
|
||||
Boolean sound, Boolean vibration, String priority,
|
||||
Boolean repeatDaily, String timezone) {
|
||||
try {
|
||||
SharedPreferences prefs = getContext().getSharedPreferences("daily_reminders", Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = prefs.edit();
|
||||
|
||||
if (title != null) editor.putString(id + "_title", title);
|
||||
if (body != null) editor.putString(id + "_body", body);
|
||||
if (time != null) editor.putString(id + "_time", time);
|
||||
if (sound != null) editor.putBoolean(id + "_sound", sound);
|
||||
if (vibration != null) editor.putBoolean(id + "_vibration", vibration);
|
||||
if (priority != null) editor.putString(id + "_priority", priority);
|
||||
if (repeatDaily != null) editor.putBoolean(id + "_repeatDaily", repeatDaily);
|
||||
if (timezone != null) editor.putString(id + "_timezone", timezone);
|
||||
|
||||
editor.apply();
|
||||
Log.d(TAG, "Reminder updated in database: " + id);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error updating reminder in database", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Data class for reminder info
|
||||
public static class DailyReminderInfo {
|
||||
public String id;
|
||||
public String title;
|
||||
public String body;
|
||||
public String time;
|
||||
public boolean sound;
|
||||
public boolean vibration;
|
||||
public String priority;
|
||||
public boolean repeatDaily;
|
||||
public String timezone;
|
||||
public boolean isScheduled;
|
||||
public long nextTriggerTime;
|
||||
public long createdAt;
|
||||
public long lastTriggered;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,6 +108,17 @@ public class DailyNotificationScheduler {
|
||||
intent.setAction(ACTION_NOTIFICATION);
|
||||
intent.putExtra(EXTRA_NOTIFICATION_ID, content.getId());
|
||||
|
||||
// Check if this is a static reminder
|
||||
if (content.getId().startsWith("reminder_") || content.getId().contains("_reminder")) {
|
||||
intent.putExtra("is_static_reminder", true);
|
||||
intent.putExtra("reminder_id", content.getId());
|
||||
intent.putExtra("title", content.getTitle());
|
||||
intent.putExtra("body", content.getBody());
|
||||
intent.putExtra("sound", content.isSound());
|
||||
intent.putExtra("vibration", true); // Default to true for reminders
|
||||
intent.putExtra("priority", content.getPriority());
|
||||
}
|
||||
|
||||
// Create pending intent with unique request code
|
||||
int requestCode = content.getId().hashCode();
|
||||
PendingIntent pendingIntent = PendingIntent.getBroadcast(
|
||||
|
||||
@@ -103,6 +103,35 @@ export interface PermissionStatus {
|
||||
carPlay?: boolean;
|
||||
}
|
||||
|
||||
// Static Daily Reminder Interfaces
|
||||
export interface DailyReminderOptions {
|
||||
id: string;
|
||||
title: string;
|
||||
body: string;
|
||||
time: string; // HH:mm format (e.g., "09:00")
|
||||
sound?: boolean;
|
||||
vibration?: boolean;
|
||||
priority?: 'low' | 'normal' | 'high';
|
||||
repeatDaily?: boolean;
|
||||
timezone?: string;
|
||||
}
|
||||
|
||||
export interface DailyReminderInfo {
|
||||
id: string;
|
||||
title: string;
|
||||
body: string;
|
||||
time: string;
|
||||
sound: boolean;
|
||||
vibration: boolean;
|
||||
priority: 'low' | 'normal' | 'high';
|
||||
repeatDaily: boolean;
|
||||
timezone?: string;
|
||||
isScheduled: boolean;
|
||||
nextTriggerTime?: number;
|
||||
createdAt: number;
|
||||
lastTriggered?: number;
|
||||
}
|
||||
|
||||
export type PermissionState = 'prompt' | 'prompt-with-rationale' | 'granted' | 'denied' | 'provisional' | 'ephemeral' | 'unknown';
|
||||
|
||||
// Additional interfaces for enhanced functionality
|
||||
@@ -364,6 +393,28 @@ export interface DailyNotificationPlugin {
|
||||
refreshAuthenticationForNewIdentity(activeDid: string): Promise<void>;
|
||||
clearCacheForNewIdentity(): Promise<void>;
|
||||
updateBackgroundTaskIdentity(activeDid: string): Promise<void>;
|
||||
|
||||
// Static Daily Reminder Methods
|
||||
/**
|
||||
* Schedule a simple daily reminder notification
|
||||
* No network content required - just static text
|
||||
*/
|
||||
scheduleDailyReminder(options: DailyReminderOptions): Promise<void>;
|
||||
|
||||
/**
|
||||
* Cancel a daily reminder notification
|
||||
*/
|
||||
cancelDailyReminder(reminderId: string): Promise<void>;
|
||||
|
||||
/**
|
||||
* Get all scheduled daily reminders
|
||||
*/
|
||||
getScheduledReminders(): Promise<DailyReminderInfo[]>;
|
||||
|
||||
/**
|
||||
* Update an existing daily reminder
|
||||
*/
|
||||
updateDailyReminder(reminderId: string, options: DailyReminderOptions): Promise<void>;
|
||||
}
|
||||
|
||||
// Phase 1: TimeSafari Endorser.ch API Interfaces
|
||||
|
||||
314
src/web.ts
314
src/web.ts
@@ -811,4 +811,318 @@ export class DailyNotificationWeb extends WebPlugin implements DailyNotification
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Static Daily Reminder Methods
|
||||
async scheduleDailyReminder(options: any): Promise<void> {
|
||||
try {
|
||||
console.log('DNP-WEB-REMINDER: Scheduling daily reminder:', options.id);
|
||||
|
||||
const { id, title, body, time, sound = true, vibration = true, priority = 'normal', repeatDaily = true, timezone } = options;
|
||||
|
||||
// Validate required parameters
|
||||
if (!id || !title || !body || !time) {
|
||||
throw new Error('Missing required parameters: id, title, body, time');
|
||||
}
|
||||
|
||||
// Parse time (HH:mm format)
|
||||
const timeParts = time.split(':');
|
||||
if (timeParts.length !== 2) {
|
||||
throw new Error('Invalid time format. Use HH:mm (e.g., 09:00)');
|
||||
}
|
||||
|
||||
const hour = parseInt(timeParts[0]);
|
||||
const minute = parseInt(timeParts[1]);
|
||||
|
||||
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) {
|
||||
throw new Error('Invalid time values. Hour must be 0-23, minute must be 0-59');
|
||||
}
|
||||
|
||||
// Check if notifications are supported
|
||||
if (!('Notification' in window)) {
|
||||
throw new Error('This browser does not support notifications');
|
||||
}
|
||||
|
||||
// Request permission if not granted
|
||||
if (Notification.permission === 'default') {
|
||||
const permission = await Notification.requestPermission();
|
||||
if (permission !== 'granted') {
|
||||
throw new Error('Notification permission denied');
|
||||
}
|
||||
}
|
||||
|
||||
if (Notification.permission !== 'granted') {
|
||||
throw new Error('Notification permission not granted');
|
||||
}
|
||||
|
||||
// Calculate next trigger time
|
||||
const now = new Date();
|
||||
const triggerTime = new Date();
|
||||
triggerTime.setHours(hour, minute, 0, 0);
|
||||
|
||||
// If time has passed today, schedule for tomorrow
|
||||
if (triggerTime <= now) {
|
||||
triggerTime.setDate(triggerTime.getDate() + 1);
|
||||
}
|
||||
|
||||
const timeUntilTrigger = triggerTime.getTime() - now.getTime();
|
||||
|
||||
// Store reminder in localStorage
|
||||
this.storeReminderInLocalStorage(id, title, body, time, sound, vibration, priority, repeatDaily, timezone);
|
||||
|
||||
// Schedule the notification using setTimeout (simplified web implementation)
|
||||
const timeoutId = setTimeout(() => {
|
||||
this.showReminderNotification(title, body, sound, vibration, priority, id);
|
||||
|
||||
// If repeatDaily is true, schedule the next occurrence
|
||||
if (repeatDaily) {
|
||||
this.scheduleDailyReminder(options);
|
||||
}
|
||||
}, timeUntilTrigger);
|
||||
|
||||
// Store timeout ID for cancellation
|
||||
this.storeReminderTimeout(id, timeoutId);
|
||||
|
||||
console.log('DNP-WEB-REMINDER: Daily reminder scheduled successfully:', id);
|
||||
} catch (error) {
|
||||
console.error('DNP-WEB-REMINDER: Error scheduling daily reminder:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async cancelDailyReminder(reminderId: string): Promise<void> {
|
||||
try {
|
||||
console.log('DNP-WEB-REMINDER: Cancelling daily reminder:', reminderId);
|
||||
|
||||
// Cancel the timeout
|
||||
this.cancelReminderTimeout(reminderId);
|
||||
|
||||
// Remove from localStorage
|
||||
this.removeReminderFromLocalStorage(reminderId);
|
||||
|
||||
console.log('DNP-WEB-REMINDER: Daily reminder cancelled:', reminderId);
|
||||
} catch (error) {
|
||||
console.error('DNP-WEB-REMINDER: Error cancelling daily reminder:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async getScheduledReminders(): Promise<any> {
|
||||
try {
|
||||
console.log('DNP-WEB-REMINDER: Getting scheduled reminders');
|
||||
|
||||
const reminders = this.getRemindersFromLocalStorage();
|
||||
|
||||
return { reminders };
|
||||
} catch (error) {
|
||||
console.error('DNP-WEB-REMINDER: Error getting scheduled reminders:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async updateDailyReminder(reminderId: string, options: any): Promise<void> {
|
||||
try {
|
||||
console.log('DNP-WEB-REMINDER: Updating daily reminder:', reminderId);
|
||||
|
||||
// Cancel existing reminder
|
||||
await this.cancelDailyReminder(reminderId);
|
||||
|
||||
// Update in localStorage
|
||||
this.updateReminderInLocalStorage(reminderId, options);
|
||||
|
||||
// Reschedule with new settings if all required fields are provided
|
||||
if (options.title && options.body && options.time) {
|
||||
await this.scheduleDailyReminder({ ...options, id: reminderId });
|
||||
}
|
||||
|
||||
console.log('DNP-WEB-REMINDER: Daily reminder updated:', reminderId);
|
||||
} catch (error) {
|
||||
console.error('DNP-WEB-REMINDER: Error updating daily reminder:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Helper methods for web reminder functionality
|
||||
private showReminderNotification(
|
||||
title: string,
|
||||
body: string,
|
||||
sound: boolean,
|
||||
vibration: boolean,
|
||||
priority: string,
|
||||
reminderId: string
|
||||
): void {
|
||||
try {
|
||||
const notification = new Notification(title, {
|
||||
body: body,
|
||||
icon: '/favicon.ico', // You can customize this
|
||||
badge: '/favicon.ico',
|
||||
tag: `reminder_${reminderId}`,
|
||||
requireInteraction: priority === 'high',
|
||||
silent: !sound
|
||||
});
|
||||
|
||||
// Handle notification click
|
||||
notification.onclick = () => {
|
||||
console.log('DNP-WEB-REMINDER: Reminder notification clicked:', reminderId);
|
||||
notification.close();
|
||||
};
|
||||
|
||||
// Handle notification close
|
||||
notification.onclose = () => {
|
||||
console.log('DNP-WEB-REMINDER: Reminder notification closed:', reminderId);
|
||||
};
|
||||
|
||||
// Handle notification error
|
||||
notification.onerror = (error) => {
|
||||
console.error('DNP-WEB-REMINDER: Reminder notification error:', error);
|
||||
};
|
||||
|
||||
// Auto-close after 10 seconds for non-high priority
|
||||
if (priority !== 'high') {
|
||||
setTimeout(() => {
|
||||
notification.close();
|
||||
}, 10000);
|
||||
}
|
||||
|
||||
// Trigger vibration if supported and enabled
|
||||
if (vibration && 'vibrate' in navigator) {
|
||||
navigator.vibrate([200, 100, 200]);
|
||||
}
|
||||
|
||||
// Record reminder trigger
|
||||
this.recordReminderTrigger(reminderId);
|
||||
|
||||
console.log('DNP-WEB-REMINDER: Reminder notification displayed:', title);
|
||||
} catch (error) {
|
||||
console.error('DNP-WEB-REMINDER: Error showing reminder notification:', error);
|
||||
}
|
||||
}
|
||||
|
||||
private storeReminderInLocalStorage(
|
||||
id: string,
|
||||
title: string,
|
||||
body: string,
|
||||
time: string,
|
||||
sound: boolean,
|
||||
vibration: boolean,
|
||||
priority: string,
|
||||
repeatDaily: boolean,
|
||||
timezone?: string
|
||||
): void {
|
||||
try {
|
||||
const reminderData = {
|
||||
id,
|
||||
title,
|
||||
body,
|
||||
time,
|
||||
sound,
|
||||
vibration,
|
||||
priority,
|
||||
repeatDaily,
|
||||
timezone: timezone || '',
|
||||
createdAt: Date.now(),
|
||||
lastTriggered: 0
|
||||
};
|
||||
|
||||
const reminders = this.getRemindersFromLocalStorage();
|
||||
reminders.push(reminderData);
|
||||
localStorage.setItem('daily_reminders', JSON.stringify(reminders));
|
||||
|
||||
console.log('DNP-WEB-REMINDER: Reminder stored:', id);
|
||||
} catch (error) {
|
||||
console.error('DNP-WEB-REMINDER: Error storing reminder:', error);
|
||||
}
|
||||
}
|
||||
|
||||
private removeReminderFromLocalStorage(id: string): void {
|
||||
try {
|
||||
const reminders = this.getRemindersFromLocalStorage();
|
||||
const filteredReminders = reminders.filter((reminder: any) => reminder.id !== id);
|
||||
localStorage.setItem('daily_reminders', JSON.stringify(filteredReminders));
|
||||
|
||||
console.log('DNP-WEB-REMINDER: Reminder removed:', id);
|
||||
} catch (error) {
|
||||
console.error('DNP-WEB-REMINDER: Error removing reminder:', error);
|
||||
}
|
||||
}
|
||||
|
||||
private getRemindersFromLocalStorage(): any[] {
|
||||
try {
|
||||
const reminders = localStorage.getItem('daily_reminders');
|
||||
return reminders ? JSON.parse(reminders) : [];
|
||||
} catch (error) {
|
||||
console.error('DNP-WEB-REMINDER: Error getting reminders from localStorage:', error);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
private updateReminderInLocalStorage(id: string, options: any): void {
|
||||
try {
|
||||
const reminders = this.getRemindersFromLocalStorage();
|
||||
const reminderIndex = reminders.findIndex((reminder: any) => reminder.id === id);
|
||||
|
||||
if (reminderIndex !== -1) {
|
||||
if (options.title) reminders[reminderIndex].title = options.title;
|
||||
if (options.body) reminders[reminderIndex].body = options.body;
|
||||
if (options.time) reminders[reminderIndex].time = options.time;
|
||||
if (options.sound !== undefined) reminders[reminderIndex].sound = options.sound;
|
||||
if (options.vibration !== undefined) reminders[reminderIndex].vibration = options.vibration;
|
||||
if (options.priority) reminders[reminderIndex].priority = options.priority;
|
||||
if (options.repeatDaily !== undefined) reminders[reminderIndex].repeatDaily = options.repeatDaily;
|
||||
if (options.timezone) reminders[reminderIndex].timezone = options.timezone;
|
||||
|
||||
localStorage.setItem('daily_reminders', JSON.stringify(reminders));
|
||||
console.log('DNP-WEB-REMINDER: Reminder updated:', id);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('DNP-WEB-REMINDER: Error updating reminder:', error);
|
||||
}
|
||||
}
|
||||
|
||||
private storeReminderTimeout(id: string, timeoutId: number): void {
|
||||
try {
|
||||
const timeouts = this.getReminderTimeouts();
|
||||
timeouts[id] = timeoutId;
|
||||
localStorage.setItem('daily_reminder_timeouts', JSON.stringify(timeouts));
|
||||
} catch (error) {
|
||||
console.error('DNP-WEB-REMINDER: Error storing reminder timeout:', error);
|
||||
}
|
||||
}
|
||||
|
||||
private cancelReminderTimeout(id: string): void {
|
||||
try {
|
||||
const timeouts = this.getReminderTimeouts();
|
||||
if (timeouts[id]) {
|
||||
clearTimeout(timeouts[id]);
|
||||
delete timeouts[id];
|
||||
localStorage.setItem('daily_reminder_timeouts', JSON.stringify(timeouts));
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('DNP-WEB-REMINDER: Error cancelling reminder timeout:', error);
|
||||
}
|
||||
}
|
||||
|
||||
private getReminderTimeouts(): Record<string, number> {
|
||||
try {
|
||||
const timeouts = localStorage.getItem('daily_reminder_timeouts');
|
||||
return timeouts ? JSON.parse(timeouts) : {};
|
||||
} catch (error) {
|
||||
console.error('DNP-WEB-REMINDER: Error getting reminder timeouts:', error);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
private recordReminderTrigger(id: string): void {
|
||||
try {
|
||||
const reminders = this.getRemindersFromLocalStorage();
|
||||
const reminderIndex = reminders.findIndex((reminder: any) => reminder.id === id);
|
||||
|
||||
if (reminderIndex !== -1) {
|
||||
reminders[reminderIndex].lastTriggered = Date.now();
|
||||
localStorage.setItem('daily_reminders', JSON.stringify(reminders));
|
||||
console.log('DNP-WEB-REMINDER: Reminder trigger recorded:', id);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('DNP-WEB-REMINDER: Error recording reminder trigger:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user