Skip to content

Instantly share code, notes, and snippets.

@bbsmithy
Created January 19, 2023 14:59
Show Gist options
  • Save bbsmithy/62140e84dad1eaa5db31e220d1f28b37 to your computer and use it in GitHub Desktop.
Save bbsmithy/62140e84dad1eaa5db31e220d1f28b37 to your computer and use it in GitHub Desktop.
Redux middleware for adding notification reminders
import { PayloadAction } from "@reduxjs/toolkit";
import * as Notifications from "expo-notifications";
export type ReminderType = "daily" | "weekly" | "every_other_day";
export type Reminder = {
type: ReminderType;
title: string;
subTitle: string;
optionKey: string;
trigger: {
hours: number;
minutes: number;
repeats?: boolean;
weekday?: number;
daysInterval?: number;
},
// notification identifier
id?: string;
// used for launch functionality when opening notification
data?: any;
}
Notifications.setNotificationHandler({
handleNotification: async () => ({
shouldShowAlert: true,
shouldPlaySound: false,
shouldSetBadge: false,
}),
});
export const DEFAULT_THOUGHT_EXCERCISE_REMINDER: Reminder = {
type: "every_other_day",
title: "Every Second Day Reminder",
subTitle: "This is a default reminder",
data: {},
optionKey: "every_other_day_2",
trigger: {
daysInterval: 2,
hours: 11,
minutes: 13,
}
}
const schduleEveryOtherDayReminder = (reminder: Reminder) => {
// TODO: Calculate seconds from daysInterval
const secondsInDays = 86400;
// @ts-ignore
let seconds = secondsInDays * reminder.trigger.daysInterval;
// Get the diff in seconds between 24hr current time
// and the 24hr time of the reminder
const selectedHourMinuteInSeconds = (reminder.trigger.hours * 3600) + (reminder.trigger.minutes * 60);
const currentHourMinuteInSeconds = (new Date().getHours() * 3600) + (new Date().getMinutes() * 60);
const diff = selectedHourMinuteInSeconds - currentHourMinuteInSeconds;
seconds = seconds + diff;
return Notifications.scheduleNotificationAsync({
content: {
title: reminder.title,
body: reminder.subTitle,
data: reminder.data,
},
trigger: {
seconds,
repeats: true
},
});
}
const schduleWeeklyReminder = (reminder: Reminder) => {
return Notifications.scheduleNotificationAsync({
content: {
title: reminder.title,
body: reminder.subTitle,
data: reminder.data,
},
trigger: {
hour: reminder.trigger.hours,
minute: reminder.trigger.minutes,
weekday: reminder.trigger.weekday,
repeats: true
},
});
}
const schduleDailyReminder = (reminder: Reminder) => {
return Notifications.scheduleNotificationAsync({
content: {
title: reminder.title,
body: reminder.subTitle,
data: reminder.data
},
trigger: {
hour: reminder.trigger.hours,
minute: reminder.trigger.minutes,
repeats: true,
},
})
}
const cancelReminder = (identifier: string) => {
return Notifications.cancelScheduledNotificationAsync(identifier)
}
export const notifications =
(store: any) => (next: any) => async (action: PayloadAction<Reminder>) => {
try {
switch (action.type) {
case "Reminders/setThoughtExcerciseReminder": {
const previousReminderId = store.getState().Reminders.thought_excercise?.id;
if (previousReminderId) {
await cancelReminder(previousReminderId);
}
if (action.payload.type === "daily") {
const notificationId = await schduleDailyReminder(action.payload);
if (notificationId) {
action.payload.id = notificationId;
next(action)
break;
} else {
throw new Error("Notification ID is null")
}
} else {
const notificationId = await schduleEveryOtherDayReminder(action.payload);
if (notificationId) {
action.payload.id = notificationId;
next(action)
break;
} else {
throw new Error("Notification ID is null")
}
}
}
case "Reminders/setSessionRatingReportReminder": {
const previousReminderId = store.getState().Reminders.session_rating_report?.id;
if (previousReminderId) {
await cancelReminder(previousReminderId);
}
const notificationId = await schduleWeeklyReminder(action.payload);
if (notificationId) {
action.payload.id = notificationId;
next(action)
} else {
throw new Error("Notification ID is null")
}
break;
}
case "Reminders/setOverallProgressReportReminder": {
const previousReminderId = store.getState().Reminders.overall_progress_report?.id;
if (previousReminderId) {
await cancelReminder(previousReminderId);
}
const notificationId = await schduleWeeklyReminder(action.payload);
if (notificationId) {
action.payload.id = notificationId;
next(action)
} else {
throw new Error("Notification ID is null")
}
break;
}
case "Reminders/updateReminder": {
// Cancel old reminder using identifier
// Schedule new reminder
next(action)
break;
}
case "Reminders/resetReminders": {
try {
// Cancel reminder using identifier
const notifs = await Notifications.getAllScheduledNotificationsAsync();
const cancelReqs = notifs.map((notif) => {
return cancelReminder(notif.identifier)
})
await Promise.all(cancelReqs)
next(action)
break;
} catch (err) {
console.log("deleteReminder Error: ", err)
break;
}
}
default: {
next(action);
}
}
} catch (err) {
console.log(err)
alert(JSON.stringify(err))
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment