Browse Source
Extracted daily reminder functionality from DailyNotificationPlugin into a dedicated DailyReminderManager class to reduce the plugin's size and effortsify responsibilities. Changes: - Created DailyReminderManager class (405 lines) for reminder CRUD - Created DailyReminderInfo data class (moved from inner class) - Delegated reminder methods to the manager - Removed duplicate helper methods from plugin - Added ensureReminderManagerInitialized() helper Impact: - Reduced DailyNotificationPlugin from 2639 to 2430 lines (209 lines) - Clear separation of concerns - Easier to test and maintain reminder functionality - Follows existing manager pattern (PermissionManager, ChannelManager, etc.) All public API methods remain unchanged - this is purely an internal refactoring.master
3 changed files with 486 additions and 260 deletions
@ -0,0 +1,31 @@ |
|||||
|
/** |
||||
|
* DailyReminderInfo.java |
||||
|
* |
||||
|
* Data class representing a daily reminder configuration |
||||
|
* and its current state. |
||||
|
* |
||||
|
* @author Matthew Raymer |
||||
|
* @version 1.0.0 |
||||
|
*/ |
||||
|
|
||||
|
package com.timesafari.dailynotification; |
||||
|
|
||||
|
/** |
||||
|
* Information about a scheduled daily reminder |
||||
|
*/ |
||||
|
public 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; |
||||
|
} |
||||
|
|
||||
@ -0,0 +1,403 @@ |
|||||
|
/** |
||||
|
* DailyReminderManager.java |
||||
|
* |
||||
|
* Manages daily reminder functionality including creation, updates, |
||||
|
* cancellation, and retrieval. Handles persistent storage and |
||||
|
* notification scheduling. |
||||
|
* |
||||
|
* @author Matthew Raymer |
||||
|
* @version 1.0.0 |
||||
|
*/ |
||||
|
|
||||
|
package com.timesafari.dailynotification; |
||||
|
|
||||
|
import android.content.Context; |
||||
|
import android.content.SharedPreferences; |
||||
|
import android.util.Log; |
||||
|
|
||||
|
import com.getcapacitor.JSObject; |
||||
|
import com.getcapacitor.PluginCall; |
||||
|
|
||||
|
import java.util.ArrayList; |
||||
|
import java.util.Calendar; |
||||
|
import java.util.HashSet; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
import java.util.Set; |
||||
|
|
||||
|
/** |
||||
|
* Manager class for daily reminder operations |
||||
|
* |
||||
|
* Responsibilities: |
||||
|
* - Schedule daily reminders |
||||
|
* - Cancel scheduled reminders |
||||
|
* - Update existing reminders |
||||
|
* - Retrieve reminder list |
||||
|
* - Manage persistent storage |
||||
|
*/ |
||||
|
public class DailyReminderManager { |
||||
|
private static final String TAG = "DailyReminderManager"; |
||||
|
private static final String PREF_NAME = "daily_reminders"; |
||||
|
private static final String REMINDER_ID_PREFIX = "reminder_"; |
||||
|
|
||||
|
private final Context context; |
||||
|
private final DailyNotificationScheduler scheduler; |
||||
|
|
||||
|
/** |
||||
|
* Initialize the DailyReminderManager |
||||
|
* |
||||
|
* @param context Android context |
||||
|
* @param scheduler Notification scheduler instance |
||||
|
*/ |
||||
|
public DailyReminderManager(Context context, |
||||
|
DailyNotificationScheduler scheduler) { |
||||
|
this.context = context; |
||||
|
this.scheduler = scheduler; |
||||
|
Log.d(TAG, "DailyReminderManager initialized"); |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Schedule a new daily reminder |
||||
|
* |
||||
|
* @param id Unique identifier for the reminder |
||||
|
* @param title Reminder title |
||||
|
* @param body Reminder body text |
||||
|
* @param time Time in HH:mm format |
||||
|
* @param sound Whether to play sound |
||||
|
* @param vibration Whether to vibrate |
||||
|
* @param priority Notification priority |
||||
|
* @param repeatDaily Whether to repeat daily |
||||
|
* @param timezone Optional timezone string |
||||
|
* @return true if scheduled successfully |
||||
|
*/ |
||||
|
public boolean scheduleReminder(String id, String title, String body, |
||||
|
String time, boolean sound, |
||||
|
boolean vibration, String priority, |
||||
|
boolean repeatDaily, String timezone) { |
||||
|
try { |
||||
|
Log.d(TAG, "Scheduling daily reminder: " + id); |
||||
|
|
||||
|
// Validate time format
|
||||
|
String[] timeParts = time.split(":"); |
||||
|
if (timeParts.length != 2) { |
||||
|
Log.e(TAG, "Invalid time format: " + time); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
int hour = Integer.parseInt(timeParts[0]); |
||||
|
int minute = Integer.parseInt(timeParts[1]); |
||||
|
|
||||
|
if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { |
||||
|
Log.e(TAG, "Invalid time values"); |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
// Create reminder content
|
||||
|
NotificationContent reminderContent = new NotificationContent(); |
||||
|
reminderContent.setId(REMINDER_ID_PREFIX + id); |
||||
|
reminderContent.setTitle(title); |
||||
|
reminderContent.setBody(body); |
||||
|
reminderContent.setSound(sound); |
||||
|
reminderContent.setPriority(priority); |
||||
|
|
||||
|
// 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); |
||||
|
} else { |
||||
|
Log.e(TAG, "Failed to schedule daily reminder: " + id); |
||||
|
} |
||||
|
|
||||
|
return scheduled; |
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
Log.e(TAG, "Error scheduling daily reminder", e); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Cancel a scheduled reminder |
||||
|
* |
||||
|
* @param reminderId Reminder ID to cancel |
||||
|
* @return true if cancelled successfully |
||||
|
*/ |
||||
|
public boolean cancelReminder(String reminderId) { |
||||
|
try { |
||||
|
Log.d(TAG, "Cancelling daily reminder: " + reminderId); |
||||
|
|
||||
|
// Cancel the scheduled notification
|
||||
|
scheduler.cancelNotification(REMINDER_ID_PREFIX + reminderId); |
||||
|
|
||||
|
// Remove from database
|
||||
|
removeReminderFromDatabase(reminderId); |
||||
|
|
||||
|
Log.i(TAG, "Daily reminder cancelled: " + reminderId); |
||||
|
return true; |
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
Log.e(TAG, "Error cancelling daily reminder", e); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Update an existing reminder |
||||
|
* |
||||
|
* @param reminderId Reminder ID to update |
||||
|
* @param title Optional new title |
||||
|
* @param body Optional new body |
||||
|
* @param time Optional new time in HH:mm format |
||||
|
* @param sound Optional new sound setting |
||||
|
* @param vibration Optional new vibration setting |
||||
|
* @param priority Optional new priority |
||||
|
* @param repeatDaily Optional new repeat setting |
||||
|
* @param timezone Optional new timezone |
||||
|
* @return true if updated successfully |
||||
|
*/ |
||||
|
public boolean updateReminder(String reminderId, String title, |
||||
|
String body, String time, Boolean sound, |
||||
|
Boolean vibration, String priority, |
||||
|
Boolean repeatDaily, String timezone) { |
||||
|
try { |
||||
|
Log.d(TAG, "Updating daily reminder: " + reminderId); |
||||
|
|
||||
|
// Cancel existing reminder
|
||||
|
scheduler.cancelNotification(REMINDER_ID_PREFIX + 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) { |
||||
|
// Parse time
|
||||
|
String[] timeParts = time.split(":"); |
||||
|
int hour = Integer.parseInt(timeParts[0]); |
||||
|
int minute = Integer.parseInt(timeParts[1]); |
||||
|
|
||||
|
// Create new reminder content
|
||||
|
NotificationContent reminderContent = new NotificationContent(); |
||||
|
reminderContent.setId(REMINDER_ID_PREFIX + reminderId); |
||||
|
reminderContent.setTitle(title); |
||||
|
reminderContent.setBody(body); |
||||
|
reminderContent.setSound(sound != null ? sound : true); |
||||
|
reminderContent.setPriority(priority != null ? priority : "normal"); |
||||
|
|
||||
|
// 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 (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) { |
||||
|
Log.e(TAG, "Failed to reschedule updated reminder"); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
Log.i(TAG, "Daily reminder updated: " + reminderId); |
||||
|
return true; |
||||
|
|
||||
|
} catch (Exception e) { |
||||
|
Log.e(TAG, "Error updating daily reminder", e); |
||||
|
return false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get all scheduled reminders |
||||
|
* |
||||
|
* @return List of DailyReminderInfo objects |
||||
|
*/ |
||||
|
public List<DailyReminderInfo> getReminders() { |
||||
|
try { |
||||
|
Log.d(TAG, "Getting scheduled reminders"); |
||||
|
return getRemindersFromDatabase(); |
||||
|
} catch (Exception e) { |
||||
|
Log.e(TAG, "Error getting reminders from database", e); |
||||
|
return new ArrayList<>(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Store reminder in SharedPreferences database |
||||
|
*/ |
||||
|
private void storeReminderInDatabase(String id, String title, String body, |
||||
|
String time, boolean sound, |
||||
|
boolean vibration, String priority, |
||||
|
boolean repeatDaily, String timezone) { |
||||
|
try { |
||||
|
SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, |
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Remove reminder from SharedPreferences database |
||||
|
*/ |
||||
|
private void removeReminderFromDatabase(String id) { |
||||
|
try { |
||||
|
SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, |
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Get reminders from SharedPreferences database |
||||
|
*/ |
||||
|
private List<DailyReminderInfo> getRemindersFromDatabase() { |
||||
|
List<DailyReminderInfo> reminders = new ArrayList<>(); |
||||
|
|
||||
|
try { |
||||
|
SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, |
||||
|
Context.MODE_PRIVATE); |
||||
|
Map<String, ?> allEntries = prefs.getAll(); |
||||
|
|
||||
|
Set<String> reminderIds = new 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; |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* Update reminder in SharedPreferences database |
||||
|
*/ |
||||
|
private void updateReminderInDatabase(String id, String title, String body, |
||||
|
String time, Boolean sound, |
||||
|
Boolean vibration, String priority, |
||||
|
Boolean repeatDaily, String timezone) { |
||||
|
try { |
||||
|
SharedPreferences prefs = context.getSharedPreferences(PREF_NAME, |
||||
|
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); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
Loading…
Reference in new issue