diff --git a/components/calendar/calendar-app.tsx b/components/calendar/calendar-app.tsx index 11f2436db..ecd136b64 100644 --- a/components/calendar/calendar-app.tsx +++ b/components/calendar/calendar-app.tsx @@ -137,9 +137,18 @@ export function CalendarApp({ linkSegments }: CalendarAppProps = {}) { void fetchPrincipal(); }, [accountEmails, fetchPrincipal]); + // The default ParticipantIdentity (draft-ietf-jmap-calendars §6) is the + // address new invitations are organised from, so it goes first: the event + // modal takes currentUserEmails[0] as organizer. + const participantIdentities = useCalendarStore((s) => s.participantIdentities); const currentUserEmails = useMemo( - () => collectUserCalendarAddresses(identities.map(id => id.email), accountEmails), - [identities, accountEmails] + () => collectUserCalendarAddresses( + participantIdentities.filter(i => i.isDefault).map(i => i.calendarAddress.replace(/^mailto:/i, '')), + participantIdentities.map(i => i.calendarAddress.replace(/^mailto:/i, '')), + identities.map(id => id.email), + accountEmails, + ), + [participantIdentities, identities, accountEmails] ); const [showEventModal, setShowEventModal] = useState(false); diff --git a/components/settings/calendar-settings.tsx b/components/settings/calendar-settings.tsx index 4154f17b5..c841d26fb 100644 --- a/components/settings/calendar-settings.tsx +++ b/components/settings/calendar-settings.tsx @@ -1,16 +1,30 @@ "use client"; +import { useEffect } from 'react'; import { useTranslations } from 'next-intl'; import { useCalendarStore, CalendarViewMode } from '@/stores/calendar-store'; import { useSettingsStore } from '@/stores/settings-store'; import { usePolicyStore } from '@/stores/policy-store'; +import { useAuthStore } from '@/stores/auth-store'; +import { toast } from '@/stores/toast-store'; import { SettingsSection, SettingItem, Select, ToggleSwitch } from './settings-section'; export function CalendarSettings() { const t = useTranslations('calendar.settings'); const tViews = useTranslations('calendar.views'); - const { viewMode, setViewMode } = useCalendarStore(); + const { viewMode, setViewMode, participantIdentities, fetchParticipantIdentities, setDefaultParticipantIdentity } = useCalendarStore(); + const client = useAuthStore((s) => s.client); + + // ParticipantIdentity list (draft-ietf-jmap-calendars §6): which of the + // user's addresses organises new invitations. Loaded here because the + // settings page can open before the calendar app ever did. + useEffect(() => { + if (client && participantIdentities.length === 0) { + void fetchParticipantIdentities(client); + } + }, [client, participantIdentities.length, fetchParticipantIdentities]); + const defaultIdentityId = participantIdentities.find((i) => i.isDefault)?.id ?? participantIdentities[0]?.id ?? ''; const { showTimeInMonthView, showWeekNumbers, @@ -37,6 +51,26 @@ export function CalendarSettings() { /> + {client && participantIdentities.length > 1 && ( + +