From b43c797e7f1d280853a51c3572636464ae6045a1 Mon Sep 17 00:00:00 2001 From: SebastianKrupinski Date: Wed, 8 Apr 2026 19:05:59 -0400 Subject: [PATCH] feat: default full / part day alarm Signed-off-by: SebastianKrupinski --- .../AppNavigation/EditCalendarModal.vue | 96 ++++++++++++++----- src/models/calendar.js | 16 ++-- src/store/calendarObjectInstance.js | 10 +- src/store/calendars.js | 27 ++++-- src/utils/alarms.js | 8 +- 5 files changed, 119 insertions(+), 38 deletions(-) diff --git a/src/components/AppNavigation/EditCalendarModal.vue b/src/components/AppNavigation/EditCalendarModal.vue index dcd2da5a90..343323025e 100644 --- a/src/components/AppNavigation/EditCalendarModal.vue +++ b/src/components/AppNavigation/EditCalendarModal.vue @@ -45,19 +45,32 @@ @@ -159,7 +172,8 @@ export default { isTransparent: false, calendarName: undefined, calendarNameChanged: false, - selectedDefaultAlarm: null, + selectedDefaultAlarmPartDay: null, + selectedDefaultAlarmFullDay: null, defaultAlarmChanged: false, } }, @@ -251,11 +265,11 @@ export default { }, /** - * Get the default alarm options for the select dropdown + * Get the default alarm options for part-day (timed) events * * @return {Array} */ - defaultAlarmOptions() { + defaultAlarmPartDayOptions() { const settingsStore = useSettingsStore() const currentUserTimezone = settingsStore.getResolvedTimezone const locale = settingsStore.momentLocale @@ -267,7 +281,6 @@ export default { }, ] - // Add standard alarm options for timed events const alarms = getDefaultAlarms(false) for (const alarm of alarms) { const alarmObject = this.getAlarmObjectFromTriggerTime(alarm) @@ -280,6 +293,35 @@ export default { return options }, + /** + * Get the default alarm options for full-day (all-day) events + * + * @return {Array} + */ + defaultAlarmFullDayOptions() { + const settingsStore = useSettingsStore() + const currentUserTimezone = settingsStore.getResolvedTimezone + const locale = settingsStore.momentLocale + + const options = [ + { + label: this.$t('calendar', 'None'), + value: null, + }, + ] + + const alarms = getDefaultAlarms(true) + for (const alarm of alarms) { + const alarmObject = this.getAlarmObjectFromTriggerTime(alarm) + options.push({ + label: alarmFormat(alarmObject, true, currentUserTimezone, locale), + value: alarm, + }) + } + + return options + }, + /** * Whether the default alarm feature is supported (Nextcloud 34+) * @@ -302,13 +344,22 @@ export default { this.calendarColorChanged = false this.isTransparent = calendar.transparency === 'transparent' - // Initialize default alarm - if (calendar.defaultAlarm === null) { - this.selectedDefaultAlarm = this.defaultAlarmOptions[0] + // Initialize default alarm for part-day events + if (calendar.defaultAlarmPartDay === null) { + this.selectedDefaultAlarmPartDay = this.defaultAlarmPartDayOptions[0] + } else { + const value = parseInt(calendar.defaultAlarmPartDay) + const option = this.defaultAlarmPartDayOptions.find((opt) => opt.value === value) + this.selectedDefaultAlarmPartDay = option || this.defaultAlarmPartDayOptions[0] + } + + // Initialize default alarm for full-day events + if (calendar.defaultAlarmFullDay === null) { + this.selectedDefaultAlarmFullDay = this.defaultAlarmFullDayOptions[0] } else { - const value = parseInt(calendar.defaultAlarm) - const option = this.defaultAlarmOptions.find((opt) => opt.value === value) - this.selectedDefaultAlarm = option || this.defaultAlarmOptions[0] + const value = parseInt(calendar.defaultAlarmFullDay) + const option = this.defaultAlarmFullDayOptions.find((opt) => opt.value === value) + this.selectedDefaultAlarmFullDay = option || this.defaultAlarmFullDayOptions[0] } this.defaultAlarmChanged = false }, @@ -377,19 +428,20 @@ export default { }, /** - * Save the calendar default alarm. + * Save the calendar default alarms. */ async saveDefaultAlarm() { try { - const defaultAlarmValue = this.selectedDefaultAlarm ? this.selectedDefaultAlarm.value : null - await this.calendarsStore.changeCalendarDefaultAlarm({ + const pdayValue = this.selectedDefaultAlarmPartDay ? this.selectedDefaultAlarmPartDay.value : null + const fdayValue = this.selectedDefaultAlarmFullDay ? this.selectedDefaultAlarmFullDay.value : null + await this.calendarsStore.changeCalendarDefaultAlarms({ calendar: this.calendar, - defaultAlarm: defaultAlarmValue, + defaultAlarmPartDay: pdayValue, + defaultAlarmFullDay: fdayValue, }) } catch (error) { - logger.error('Failed to save calendar default alarm', { + logger.error('Failed to save calendar default alarms', { calendar: this.calendar, - defaultAlarm: this.selectedDefaultAlarm, }) throw error } diff --git a/src/models/calendar.js b/src/models/calendar.js index aaa34eeffa..8b478bf474 100644 --- a/src/models/calendar.js +++ b/src/models/calendar.js @@ -63,8 +63,10 @@ function getDefaultCalendarObject(props = {}) { fetchedTimeRanges: [], // Scheduling transparency transparency: 'opaque', - // Default alarm/reminder for new events in seconds (null if disabled) - defaultAlarm: null, + // Default alarm/reminder for part-day events in seconds (null if disabled) + defaultAlarmPartDay: null, + // Default alarm/reminder for full-day events in seconds (null if disabled) + defaultAlarmFullDay: null, ...props, } } @@ -106,9 +108,10 @@ function mapDavCollectionToCalendar(calendar, currentUserPrincipal) { // then the default value CALDAV:opaque MUST be assumed. // https://datatracker.ietf.org/doc/html/rfc6638#section-9.1 const transparency = calendar.transparency || 'opaque' - // Default alarm for new events in this calendar (in seconds) - // The value can be null or a number of seconds - const defaultAlarm = isAfterVersion(34) && calendar.defaultAlarm !== undefined ? calendar.defaultAlarm : null + // Default alarm for part-day events in this calendar (in seconds) + const defaultAlarmPartDay = isAfterVersion(34) && calendar.defaultAlarmPartDay !== undefined ? calendar.defaultAlarmPartDay : null + // Default alarm for full-day events in this calendar (in seconds) + const defaultAlarmFullDay = isAfterVersion(34) && calendar.defaultAlarmFullDay !== undefined ? calendar.defaultAlarmFullDay : null let isSharedWithMe = false if (!currentUserPrincipal) { @@ -167,7 +170,8 @@ function mapDavCollectionToCalendar(calendar, currentUserPrincipal) { shares, timezone, transparency, - defaultAlarm, + defaultAlarmPartDay, + defaultAlarmFullDay, dav: calendar, }) } diff --git a/src/store/calendarObjectInstance.js b/src/store/calendarObjectInstance.js index ab366418af..69463ef7d8 100644 --- a/src/store/calendarObjectInstance.js +++ b/src/store/calendarObjectInstance.js @@ -1422,8 +1422,14 @@ export default defineStore('calendarObjectInstance', { } let defaultReminder = null - if (isAfterVersion(34) && calendar && calendar.defaultAlarm !== null) { - defaultReminder = parseInt(calendar.defaultAlarm) + if (isAfterVersion(34) && calendar) { + if (calendarObjectInstance.isAllDay && calendar.defaultAlarmFullDay !== undefined) { + defaultReminder = calendar.defaultAlarmFullDay + } else if (!calendarObjectInstance.isAllDay && calendar.defaultAlarmPartDay !== undefined) { + defaultReminder = calendar.defaultAlarmPartDay + } else { + defaultReminder = parseInt(settingsStore.defaultReminder) + } } else { defaultReminder = parseInt(settingsStore.defaultReminder) } diff --git a/src/store/calendars.js b/src/store/calendars.js index 4673a9c847..3892c9da5b 100644 --- a/src/store/calendars.js +++ b/src/store/calendars.js @@ -588,26 +588,41 @@ export default defineStore('calendars', { }, /** - * Change a calendar's default alarm + * Change a calendar's default alarms for part-day and full-day events * * @param {object} data destructuring object * @param {object} data.calendar the calendar to modify - * @param {string|null} data.defaultAlarm the new default alarm in seconds (or null to disable) + * @param {number|null} data.defaultAlarmPartDay the new default alarm for part-day events in seconds (or null to disable) + * @param {number|null} data.defaultAlarmFullDay the new default alarm for full-day events in seconds (or null to disable) * @return {Promise} */ - async changeCalendarDefaultAlarm({ calendar, defaultAlarm }) { + async changeCalendarDefaultAlarms({ calendar, defaultAlarmPartDay, defaultAlarmFullDay }) { if (!isAfterVersion(34)) { return } - if (calendar.dav.defaultAlarm === defaultAlarm) { + const partDayChanged = calendar.dav.defaultAlarmPartDay !== defaultAlarmPartDay + const fullDayChanged = calendar.dav.defaultAlarmFullDay !== defaultAlarmFullDay + + if (!partDayChanged && !fullDayChanged) { return } - calendar.dav.defaultAlarm = defaultAlarm + if (partDayChanged) { + calendar.dav.defaultAlarmPartDay = defaultAlarmPartDay + } + if (fullDayChanged) { + calendar.dav.defaultAlarmFullDay = defaultAlarmFullDay + } await calendar.dav.update() - this.calendarsById[calendar.id].defaultAlarm = defaultAlarm + + if (partDayChanged) { + this.calendarsById[calendar.id].defaultAlarmPartDay = defaultAlarmPartDay + } + if (fullDayChanged) { + this.calendarsById[calendar.id].defaultAlarmFullDay = defaultAlarmFullDay + } }, /** diff --git a/src/utils/alarms.js b/src/utils/alarms.js index 297696cdc6..3355f4b9da 100644 --- a/src/utils/alarms.js +++ b/src/utils/alarms.js @@ -209,8 +209,12 @@ export function updateDefaultAlarm() { const calendar = calendarsStore.getCalendarById(calendarObjectInstanceStore.calendarObject.calendarId) let defaultReminder = null - if (isAfterVersion(34) && calendar && calendar.defaultAlarm !== null) { - defaultReminder = calendar.defaultAlarm + if (isAfterVersion(34) && calendar) { + if (calendarObjectInstance.isAllDay && calendar.defaultAlarmFullDay !== undefined) { + defaultReminder = calendar.defaultAlarmFullDay + } else if (!calendarObjectInstance.isAllDay && calendar.defaultAlarmPartDay !== undefined) { + defaultReminder = calendar.defaultAlarmPartDay + } } // Find the existing default alarm (if any)