1 import { DAY_IN_SECONDS } from '@proton/shared/lib/constants';
2 import isTruthy from '@proton/utils/isTruthy';
4 import { normalize } from '../../helpers/string';
7 VcalDateOrDateTimeProperty,
10 VcalValarmRelativeComponent,
11 } from '../../interfaces/calendar';
12 import { getIsAbsoluteTrigger, normalizeDurationToUnit, normalizeTrigger } from '../alarms/trigger';
13 import { ICAL_ALARM_ACTION, MAX_NOTIFICATIONS, NOTIFICATION_UNITS, NOTIFICATION_UNITS_MAX } from '../constants';
14 import { getIsDateTimeValue, getIsPropertyAllDay } from '../vcalHelper';
16 const { DISPLAY, EMAIL, AUDIO } = ICAL_ALARM_ACTION;
18 export const getSupportedAlarmAction = (action: VcalStringProperty) => {
19 if (normalize(action.value) === 'email') {
20 return { value: EMAIL };
23 return { value: DISPLAY };
27 * Determine if a VALARM component is correct according to the RFC
29 export const getIsValidAlarm = (alarm: VcalValarmComponent) => {
30 const { action, trigger, duration, repeat } = alarm;
31 const supportedActions: string[] = [DISPLAY, EMAIL, AUDIO];
33 if (!supportedActions.includes(action?.value)) {
39 // absolute triggers should have the right format
40 if (getIsAbsoluteTrigger(trigger) && !getIsDateTimeValue(trigger.value as DateTimeValue)) {
43 // duration and repeat must be both present or absent
44 if (+!duration ^ +!repeat) {
51 * Given a VALARM component, try to transform it into something that we support.
52 * Return undefined otherwise
54 export const getSupportedAlarm = (
55 alarm: VcalValarmComponent,
56 dtstart: VcalDateOrDateTimeProperty
57 ): VcalValarmRelativeComponent | undefined => {
58 if (!getIsValidAlarm(alarm)) {
62 const supportedAction = getSupportedAlarmAction(alarm.action);
64 const { trigger } = alarm;
66 if (!getIsAbsoluteTrigger(trigger) && trigger.parameters?.related?.toLocaleLowerCase() === 'end') {
70 const normalizedTrigger = normalizeTrigger(trigger, dtstart);
71 const triggerDurationInSeconds = normalizeDurationToUnit(normalizedTrigger, 1);
73 const inFuture = getIsPropertyAllDay(dtstart)
74 ? !normalizedTrigger.isNegative && triggerDurationInSeconds >= DAY_IN_SECONDS
75 : !normalizedTrigger.isNegative && triggerDurationInSeconds !== 0;
76 const nonSupportedTrigger =
77 normalizedTrigger.seconds !== 0 ||
78 normalizedTrigger.minutes > NOTIFICATION_UNITS_MAX[NOTIFICATION_UNITS.MINUTE] ||
79 normalizedTrigger.hours > NOTIFICATION_UNITS_MAX[NOTIFICATION_UNITS.HOUR] ||
80 normalizedTrigger.days > NOTIFICATION_UNITS_MAX[NOTIFICATION_UNITS.DAY] ||
81 normalizedTrigger.weeks > NOTIFICATION_UNITS_MAX[NOTIFICATION_UNITS.WEEK];
83 if (inFuture || nonSupportedTrigger) {
89 action: supportedAction,
90 trigger: { value: normalizedTrigger },
94 export const getSupportedAlarms = (valarms: VcalValarmComponent[], dtstart: VcalDateOrDateTimeProperty) => {
96 .map((alarm) => getSupportedAlarm(alarm, dtstart))
98 .slice(0, MAX_NOTIFICATIONS);