mirror of
https://github.com/urosran/cally.git
synced 2025-07-10 07:07:16 +00:00
Functions update
This commit is contained in:
@ -17,8 +17,21 @@ export const useCalendarControls = (events: any[]) => {
|
||||
|
||||
const handlePressEvent = useCallback((event: any) => {
|
||||
const foundEvent = events?.find(x => x.id === event.id);
|
||||
setEditVisible(true);
|
||||
setEventForEdit(foundEvent!);
|
||||
|
||||
if (foundEvent) {
|
||||
const processedEvent = {
|
||||
...foundEvent,
|
||||
startDate: foundEvent.startDate?.seconds ?
|
||||
new Date(foundEvent.startDate.seconds * 1000) :
|
||||
new Date(foundEvent.start),
|
||||
endDate: foundEvent.endDate?.seconds ?
|
||||
new Date(foundEvent.endDate.seconds * 1000) :
|
||||
new Date(foundEvent.end)
|
||||
};
|
||||
|
||||
setEditVisible(true);
|
||||
setEventForEdit(processedEvent);
|
||||
}
|
||||
}, [events, setEditVisible, setEventForEdit]);
|
||||
|
||||
const handlePressCell = useCallback((date: DateOrDateTime) => {
|
||||
|
@ -313,18 +313,22 @@ exports.checkUpcomingEvents = functions.pubsub
|
||||
.schedule("every 5 minutes")
|
||||
.onRun(async (context) => {
|
||||
const now = Timestamp.now();
|
||||
const tenMinutesFromNow = new Date(now.toDate().getTime() + 10 * 60 * 1000);
|
||||
|
||||
const eventsSnapshot = await db.collection("Events")
|
||||
.where("startDate", ">=", now)
|
||||
.where("startDate", "<=", Timestamp.fromDate(tenMinutesFromNow))
|
||||
.get();
|
||||
|
||||
await Promise.all(eventsSnapshot.docs.map(async (doc) => {
|
||||
const event = doc.data();
|
||||
if (!event?.startDate) return;
|
||||
const { familyId, title, allDay } = event;
|
||||
try {
|
||||
const familyDoc = await db.collection("Families").doc(familyId).get();
|
||||
const familyDoc = await db.collection("Households").doc(familyId).get();
|
||||
if (!familyDoc.exists) return;
|
||||
const familySettings = familyDoc.data()?.settings || {};
|
||||
const reminderTime = familySettings.defaultReminderTime || 15;
|
||||
const reminderTime = familySettings.defaultReminderTime || 5;
|
||||
const eventTime = event.startDate.toDate();
|
||||
const reminderThreshold = new Date(now.toDate().getTime() + reminderTime * 60 * 1000);
|
||||
if (allDay) {
|
||||
@ -460,6 +464,13 @@ exports.syncNewEventToGoogle = functions.firestore
|
||||
.onCreate(async (snapshot, context) => {
|
||||
const newEvent = snapshot.data();
|
||||
const eventId = context.params.eventId;
|
||||
|
||||
await snapshot.ref.update({
|
||||
reminderSent: false,
|
||||
eveningReminderSent: false,
|
||||
notifiedAt: null
|
||||
});
|
||||
|
||||
if (newEvent.externalOrigin === "google") {
|
||||
logger.info("[GOOGLE_SYNC] Skipping sync for Google-originated event", eventId);
|
||||
return;
|
||||
@ -1132,19 +1143,19 @@ exports.notifyOnEventUpdate = functions.firestore
|
||||
───────────────────────────────── */
|
||||
// We keep the reminder scheduler mostly as-is but ensure that once a notification is sent, the event is updated
|
||||
exports.checkUpcomingEvents = functions.pubsub
|
||||
.schedule("every 5 minutes") // Run more frequently to catch reminders
|
||||
.schedule("every 5 minutes")
|
||||
.onRun(async (context) => {
|
||||
const now = Timestamp.now();
|
||||
const thirtyMinutesFromNow = new Date(now.toDate().getTime() + 30 * 60 * 1000);
|
||||
|
||||
// Query only events starting in the next 30 minutes that haven't been reminded
|
||||
logger.info(`Running check at ${now.toDate().toISOString()}`);
|
||||
|
||||
const eventsSnapshot = await db.collection("Events")
|
||||
.where("startDate", ">=", now)
|
||||
.where("startDate", "<=", thirtyMinutesFromNow)
|
||||
.where("reminderSent", "==", false) // Only get events that haven't been reminded
|
||||
.where("startDate", "<=", Timestamp.fromDate(thirtyMinutesFromNow))
|
||||
.get();
|
||||
|
||||
const batch = db.batch(); // Batch our updates
|
||||
const batch = db.batch();
|
||||
const notificationPromises = [];
|
||||
|
||||
for (const doc of eventsSnapshot.docs) {
|
||||
@ -1152,64 +1163,65 @@ exports.checkUpcomingEvents = functions.pubsub
|
||||
if (!event?.startDate) continue;
|
||||
|
||||
const { familyId, title, allDay } = event;
|
||||
|
||||
// Skip if reminder already sent
|
||||
if (event.reminderSent) {
|
||||
logger.info(`Reminder already sent for event: ${title}`);
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
const familyDoc = await db.collection("Families").doc(familyId).get();
|
||||
if (!familyDoc.exists) continue;
|
||||
|
||||
const familySettings = familyDoc.data()?.settings || {};
|
||||
const reminderTime = familySettings.defaultReminderTime || 10; // Default to 10 minutes
|
||||
const eventTime = event.startDate.toDate();
|
||||
const reminderThreshold = new Date(now.toDate().getTime() + reminderTime * 60 * 1000);
|
||||
const reminderTime = familySettings.defaultReminderTime || 10;
|
||||
|
||||
// Check if we're within the reminder window
|
||||
const eventTime = event.startDate.toDate();
|
||||
const timeUntilEvent = eventTime.getTime() - now.toDate().getTime();
|
||||
const minutesUntilEvent = Math.floor(timeUntilEvent / (60 * 1000));
|
||||
|
||||
logger.info(`Checking event: "${title}"`, {
|
||||
minutesUntilEvent,
|
||||
reminderTime,
|
||||
eventTime: eventTime.toISOString()
|
||||
});
|
||||
|
||||
// Modified timing logic: Send reminder when we're close to the reminder time
|
||||
// This ensures we don't miss the window between function executions
|
||||
if (minutesUntilEvent <= reminderTime && minutesUntilEvent > 0) {
|
||||
notificationPromises.push(async () => {
|
||||
const pushTokens = await getPushTokensForFamily(familyId);
|
||||
if (pushTokens.length) {
|
||||
await sendNotifications(pushTokens, {
|
||||
title: "Upcoming Event",
|
||||
body: `In ${minutesUntilEvent} minutes: ${title}`,
|
||||
data: { type: 'event_reminder', eventId: doc.id }
|
||||
});
|
||||
batch.update(doc.ref, { reminderSent: true });
|
||||
}
|
||||
});
|
||||
}
|
||||
logger.info(`Preparing to send reminder for: ${title}`);
|
||||
const pushTokens = await getPushTokensForFamily(familyId);
|
||||
|
||||
// Handle all-day events separately
|
||||
if (allDay && !event.eveningReminderSent) {
|
||||
const eveningBefore = new Date(eventTime);
|
||||
eveningBefore.setDate(eveningBefore.getDate() - 1);
|
||||
eveningBefore.setHours(20, 0, 0, 0);
|
||||
|
||||
if (now.toDate() >= eveningBefore) {
|
||||
notificationPromises.push(async () => {
|
||||
const pushTokens = await getPushTokensForFamily(familyId);
|
||||
if (pushTokens.length) {
|
||||
await sendNotifications(pushTokens, {
|
||||
title: "Tomorrow's All-Day Event",
|
||||
body: `Tomorrow: ${title}`,
|
||||
data: { type: 'event_reminder', eventId: doc.id }
|
||||
});
|
||||
batch.update(doc.ref, { eveningReminderSent: true });
|
||||
}
|
||||
if (pushTokens.length) {
|
||||
await sendNotifications(pushTokens, {
|
||||
title: "Upcoming Event",
|
||||
body: `In ${minutesUntilEvent} minutes: ${title}`,
|
||||
data: { type: 'event_reminder', eventId: doc.id }
|
||||
});
|
||||
|
||||
batch.update(doc.ref, {
|
||||
reminderSent: true,
|
||||
lastReminderSent: Timestamp.now()
|
||||
});
|
||||
|
||||
logger.info(`Reminder sent for: ${title}`);
|
||||
}
|
||||
} else {
|
||||
logger.info(`Not yet time for reminder: ${title}`, {
|
||||
minutesUntilEvent,
|
||||
reminderTime
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(`Error processing reminder for event ${doc.id}:`, error);
|
||||
}
|
||||
}
|
||||
|
||||
// Execute all notifications
|
||||
await Promise.all(notificationPromises.map(fn => fn()));
|
||||
|
||||
// Commit all updates in one batch
|
||||
// Commit batch if there are any operations
|
||||
if (batch._ops.length > 0) {
|
||||
await batch.commit();
|
||||
logger.info(`Committed ${batch._ops.length} updates`);
|
||||
}
|
||||
});
|
||||
|
||||
|
Reference in New Issue
Block a user