@rapidmx/web-client 0.35.0 → 0.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/apps/escrow/matters/[uid].tsx +4 -3
- package/apps/shared/calendar/calendarReminders.ts +35 -0
- package/apps/shared/calendar/sealedEvents.ts +113 -0
- package/apps/shared/calendar/useCalendarReminders.ts +28 -9
- package/apps/shared/components/admin/settings/DomainDnsSetup.tsx +4 -0
- package/apps/shared/components/admin/settings/EncryptionPolicyForm.tsx +89 -3
- package/apps/shared/components/calendar/EventDetails.tsx +13 -2
- package/apps/shared/components/calendar/EventEditor.tsx +124 -17
- package/apps/shared/components/calendar/EventFormParts.tsx +1 -0
- package/apps/shared/components/calendar/EventModal.tsx +19 -2
- package/apps/shared/components/calendar/RequestChangeForm.tsx +4 -1
- package/apps/shared/components/calendar/eventForm.ts +2 -0
- package/apps/shared/components/contacts/ContactCard.tsx +13 -1
- package/apps/shared/components/contacts/ContactDetailPane.tsx +189 -9
- package/apps/shared/components/contacts/ContactForm.tsx +56 -7
- package/apps/shared/components/contacts/KeyChangeReview.tsx +5 -1
- package/apps/shared/components/contacts/contactCardData.ts +8 -4
- package/apps/shared/components/contacts/contactKeys.ts +3 -3
- package/apps/shared/components/layout/AppShell.tsx +34 -5
- package/apps/shared/components/layout/KeyEnrollmentGate.tsx +30 -1
- package/apps/shared/components/layout/SharedMailboxKeyManager.tsx +122 -0
- package/apps/shared/components/layout/UnlockPromptProvider.tsx +34 -0
- package/apps/shared/components/mail/ConversationList.tsx +1 -1
- package/apps/shared/components/mail/InviteCard.tsx +11 -1
- package/apps/shared/components/mail/MessageDetailPane.tsx +59 -26
- package/apps/shared/components/mail/compose/ComposeWindow.tsx +9 -2
- package/apps/shared/components/mail/compose/RecipientInput.tsx +2 -1
- package/apps/shared/components/mail/compose/draftResume.ts +28 -3
- package/apps/shared/components/mail/compose/protectedContactSuggestions.ts +121 -0
- package/apps/shared/components/mail/compose/quotedBody.ts +4 -3
- package/apps/shared/components/mail/invite/inviteStore.ts +17 -1
- package/apps/shared/components/mail/layout/MailShell.tsx +2 -0
- package/apps/shared/components/mail/pinnedSigners.ts +14 -0
- package/apps/shared/components/mail/reading/conversationPrint.ts +3 -3
- package/apps/shared/components/mail/reading/useMessageActions.ts +4 -1
- package/apps/shared/components/settings/KeyExportSetting.tsx +173 -0
- package/apps/shared/components/settings/OpenPgpKeySetting.tsx +240 -0
- package/apps/shared/components/settings/PolicyLockedNotice.tsx +23 -0
- package/apps/shared/components/settings/ZeroAccessSetting.tsx +128 -0
- package/apps/shared/components/settings/ZeroAccessTypes.tsx +175 -0
- package/apps/shared/components/settings/layout/SettingsShell.tsx +9 -2
- package/apps/shared/mail/decryptedMessages.ts +11 -3
- package/apps/shared/mail/outbox/sendJob.ts +349 -50
- package/apps/shared/mail/outbox/sendOutcomes.ts +91 -20
- package/apps/shared/mail/reportNotices.ts +3 -1
- package/apps/shared/mail/zeroAccessSource.ts +27 -0
- package/apps/shared/search/LocalIndexLifecycle.tsx +84 -24
- package/apps/shared/search/localIndexBuilder.ts +57 -20
- package/apps/shared/search/localIndexRpcClient.ts +96 -12
- package/apps/shared/search/localIndexSchema.ts +20 -4
- package/apps/shared/search/localIndexTransport.ts +6 -2
- package/apps/shared/search/localIndexWorker.ts +37 -18
- package/apps/shared/search/searchTier2.ts +5 -0
- package/apps/shared/search/zeroAccessIndexSync.ts +679 -0
- package/apps/shared/search/zeroAccessSyncState.ts +70 -0
- package/apps/shared/zeroAccess/ProtectedMark.tsx +19 -0
- package/apps/shared/zeroAccess/useKeysLocked.ts +25 -0
- package/apps/shared/zeroAccess/useOpenedRecord.ts +71 -0
- package/apps/www/_shell.tsx +2 -0
- package/apps/www/calendar/index.tsx +225 -61
- package/apps/www/contacts/index.tsx +67 -11
- package/apps/www/index.tsx +19 -3
- package/apps/www/settings/encryption/index.tsx +21 -1
- package/apps/www/settings/privacy/index.tsx +89 -39
- package/apps/www/tasks/index.tsx +24 -6
- package/dist/apps/escrow/matters/[uid].js +2 -2
- package/dist/apps/shared/calendar/calendarReminders.d.ts +14 -0
- package/dist/apps/shared/calendar/calendarReminders.js +26 -0
- package/dist/apps/shared/calendar/sealedEvents.d.ts +14 -0
- package/dist/apps/shared/calendar/sealedEvents.js +85 -0
- package/dist/apps/shared/calendar/useCalendarReminders.d.ts +2 -1
- package/dist/apps/shared/calendar/useCalendarReminders.js +27 -9
- package/dist/apps/shared/components/admin/settings/DomainDnsSetup.js +3 -0
- package/dist/apps/shared/components/admin/settings/EncryptionPolicyForm.js +25 -2
- package/dist/apps/shared/components/calendar/EventDetails.js +13 -2
- package/dist/apps/shared/components/calendar/EventEditor.js +115 -18
- package/dist/apps/shared/components/calendar/EventFormParts.js +1 -1
- package/dist/apps/shared/components/calendar/EventModal.d.ts +1 -1
- package/dist/apps/shared/components/calendar/EventModal.js +15 -2
- package/dist/apps/shared/components/calendar/RequestChangeForm.d.ts +3 -0
- package/dist/apps/shared/components/calendar/RequestChangeForm.js +1 -1
- package/dist/apps/shared/components/calendar/eventForm.d.ts +2 -0
- package/dist/apps/shared/components/contacts/ContactCard.js +12 -1
- package/dist/apps/shared/components/contacts/ContactDetailPane.d.ts +2 -1
- package/dist/apps/shared/components/contacts/ContactDetailPane.js +103 -9
- package/dist/apps/shared/components/contacts/ContactForm.d.ts +4 -1
- package/dist/apps/shared/components/contacts/ContactForm.js +37 -7
- package/dist/apps/shared/components/contacts/KeyChangeReview.d.ts +3 -1
- package/dist/apps/shared/components/contacts/KeyChangeReview.js +3 -2
- package/dist/apps/shared/components/contacts/contactCardData.js +8 -4
- package/dist/apps/shared/components/contacts/contactKeys.d.ts +1 -1
- package/dist/apps/shared/components/contacts/contactKeys.js +3 -3
- package/dist/apps/shared/components/layout/AppShell.d.ts +18 -1
- package/dist/apps/shared/components/layout/AppShell.js +17 -6
- package/dist/apps/shared/components/layout/KeyEnrollmentGate.js +27 -2
- package/dist/apps/shared/components/layout/SharedMailboxKeyManager.d.ts +17 -0
- package/dist/apps/shared/components/layout/SharedMailboxKeyManager.js +98 -0
- package/dist/apps/shared/components/layout/UnlockPromptProvider.d.ts +3 -0
- package/dist/apps/shared/components/layout/UnlockPromptProvider.js +32 -0
- package/dist/apps/shared/components/mail/ConversationList.js +1 -1
- package/dist/apps/shared/components/mail/InviteCard.js +11 -1
- package/dist/apps/shared/components/mail/MessageDetailPane.js +46 -21
- package/dist/apps/shared/components/mail/compose/ComposeWindow.js +2 -2
- package/dist/apps/shared/components/mail/compose/RecipientInput.js +3 -2
- package/dist/apps/shared/components/mail/compose/draftResume.d.ts +2 -0
- package/dist/apps/shared/components/mail/compose/draftResume.js +28 -3
- package/dist/apps/shared/components/mail/compose/protectedContactSuggestions.d.ts +14 -0
- package/dist/apps/shared/components/mail/compose/protectedContactSuggestions.js +96 -0
- package/dist/apps/shared/components/mail/compose/quotedBody.d.ts +1 -1
- package/dist/apps/shared/components/mail/compose/quotedBody.js +4 -3
- package/dist/apps/shared/components/mail/invite/inviteStore.js +16 -1
- package/dist/apps/shared/components/mail/layout/MailShell.js +2 -1
- package/dist/apps/shared/components/mail/pinnedSigners.d.ts +6 -0
- package/dist/apps/shared/components/mail/pinnedSigners.js +10 -1
- package/dist/apps/shared/components/mail/reading/conversationPrint.d.ts +2 -2
- package/dist/apps/shared/components/mail/reading/conversationPrint.js +3 -3
- package/dist/apps/shared/components/mail/reading/useMessageActions.js +4 -1
- package/dist/apps/shared/components/settings/KeyExportSetting.d.ts +13 -0
- package/dist/apps/shared/components/settings/KeyExportSetting.js +90 -0
- package/dist/apps/shared/components/settings/OpenPgpKeySetting.d.ts +13 -0
- package/dist/apps/shared/components/settings/OpenPgpKeySetting.js +143 -0
- package/dist/apps/shared/components/settings/PolicyLockedNotice.d.ts +11 -0
- package/dist/apps/shared/components/settings/PolicyLockedNotice.js +9 -0
- package/dist/apps/shared/components/settings/ZeroAccessSetting.d.ts +16 -0
- package/dist/apps/shared/components/settings/ZeroAccessSetting.js +80 -0
- package/dist/apps/shared/components/settings/ZeroAccessTypes.d.ts +29 -0
- package/dist/apps/shared/components/settings/ZeroAccessTypes.js +107 -0
- package/dist/apps/shared/components/settings/layout/SettingsShell.d.ts +3 -0
- package/dist/apps/shared/components/settings/layout/SettingsShell.js +3 -2
- package/dist/apps/shared/mail/decryptedMessages.d.ts +1 -1
- package/dist/apps/shared/mail/decryptedMessages.js +11 -3
- package/dist/apps/shared/mail/outbox/sendJob.d.ts +37 -4
- package/dist/apps/shared/mail/outbox/sendJob.js +287 -42
- package/dist/apps/shared/mail/outbox/sendOutcomes.d.ts +12 -0
- package/dist/apps/shared/mail/outbox/sendOutcomes.js +76 -20
- package/dist/apps/shared/mail/reportNotices.js +3 -1
- package/dist/apps/shared/mail/zeroAccessSource.d.ts +8 -0
- package/dist/apps/shared/mail/zeroAccessSource.js +26 -0
- package/dist/apps/shared/search/LocalIndexLifecycle.d.ts +2 -0
- package/dist/apps/shared/search/LocalIndexLifecycle.js +74 -24
- package/dist/apps/shared/search/localIndexBuilder.d.ts +9 -1
- package/dist/apps/shared/search/localIndexBuilder.js +50 -17
- package/dist/apps/shared/search/localIndexRpcClient.d.ts +5 -39
- package/dist/apps/shared/search/localIndexRpcClient.js +129 -11
- package/dist/apps/shared/search/localIndexSchema.d.ts +14 -2
- package/dist/apps/shared/search/localIndexSchema.js +18 -4
- package/dist/apps/shared/search/localIndexTransport.d.ts +6 -2
- package/dist/apps/shared/search/localIndexWorker.d.ts +11 -0
- package/dist/apps/shared/search/localIndexWorker.js +22 -15
- package/dist/apps/shared/search/searchTier2.js +5 -0
- package/dist/apps/shared/search/zeroAccessIndexSync.d.ts +102 -0
- package/dist/apps/shared/search/zeroAccessIndexSync.js +544 -0
- package/dist/apps/shared/search/zeroAccessSyncState.d.ts +20 -0
- package/dist/apps/shared/search/zeroAccessSyncState.js +65 -0
- package/dist/apps/shared/zeroAccess/ProtectedMark.d.ts +7 -0
- package/dist/apps/shared/zeroAccess/ProtectedMark.js +10 -0
- package/dist/apps/shared/zeroAccess/useKeysLocked.d.ts +6 -0
- package/dist/apps/shared/zeroAccess/useKeysLocked.js +20 -0
- package/dist/apps/shared/zeroAccess/useOpenedRecord.d.ts +18 -0
- package/dist/apps/shared/zeroAccess/useOpenedRecord.js +66 -0
- package/dist/apps/www/_shell.d.ts +1 -1
- package/dist/apps/www/_shell.js +2 -2
- package/dist/apps/www/calendar/index.js +88 -20
- package/dist/apps/www/contacts/index.js +64 -11
- package/dist/apps/www/index.js +19 -3
- package/dist/apps/www/settings/encryption/index.js +16 -4
- package/dist/apps/www/settings/privacy/index.js +47 -6
- package/dist/apps/www/tasks/index.js +21 -7
- package/dist/lib/admin/domainsApi.d.ts +1 -1
- package/dist/lib/admin/escrowAccessRequestsApi.d.ts +6 -0
- package/dist/lib/calendar/calendarApi.d.ts +52 -6
- package/dist/lib/calendar/calendarApi.js +110 -17
- package/dist/lib/calendar/calendarMutations.d.ts +20 -7
- package/dist/lib/calendar/calendarMutations.js +73 -14
- package/dist/lib/calendar/inviteApi.d.ts +17 -3
- package/dist/lib/calendar/inviteApi.js +86 -7
- package/dist/lib/calendar/protectedEvents.d.ts +31 -0
- package/dist/lib/calendar/protectedEvents.js +113 -0
- package/dist/lib/calendar/recurrence.d.ts +2 -0
- package/dist/lib/calendar/recurrence.js +16 -0
- package/dist/lib/calendar/sealedInvites.d.ts +9 -0
- package/dist/lib/calendar/sealedInvites.js +65 -0
- package/dist/lib/contacts/contactsApi.d.ts +29 -3
- package/dist/lib/contacts/contactsApi.js +23 -7
- package/dist/lib/contacts/useContactPhotoSrc.d.ts +5 -2
- package/dist/lib/contacts/useContactPhotoSrc.js +91 -11
- package/dist/lib/crypto/composeSecurity.d.ts +11 -3
- package/dist/lib/crypto/composeSecurity.js +13 -5
- package/dist/lib/crypto/keyExport.d.ts +54 -0
- package/dist/lib/crypto/keyExport.js +161 -0
- package/dist/lib/crypto/keyPairMatch.d.ts +9 -0
- package/dist/lib/crypto/keyPairMatch.js +65 -0
- package/dist/lib/crypto/keySession.d.ts +64 -3
- package/dist/lib/crypto/keySession.js +179 -12
- package/dist/lib/crypto/keyvaultApi.d.ts +129 -8
- package/dist/lib/crypto/keyvaultApi.js +45 -3
- package/dist/lib/crypto/meetingKeys.d.ts +25 -0
- package/dist/lib/crypto/meetingKeys.js +87 -0
- package/dist/lib/crypto/messageSecurity.d.ts +56 -3
- package/dist/lib/crypto/messageSecurity.js +201 -13
- package/dist/lib/crypto/mime.d.ts +5 -0
- package/dist/lib/crypto/mime.js +25 -0
- package/dist/lib/crypto/openPgpKey.d.ts +39 -0
- package/dist/lib/crypto/openPgpKey.js +89 -0
- package/dist/lib/crypto/openpgp.d.ts +47 -0
- package/dist/lib/crypto/openpgp.js +88 -0
- package/dist/lib/crypto/pgpMessage.d.ts +51 -0
- package/dist/lib/crypto/pgpMessage.js +271 -0
- package/dist/lib/crypto/sharedMailboxKeys.d.ts +62 -0
- package/dist/lib/crypto/sharedMailboxKeys.js +337 -0
- package/dist/lib/crypto/smimeMessage.d.ts +21 -0
- package/dist/lib/crypto/smimeMessage.js +11 -7
- package/dist/lib/crypto/zeroAccessKey.d.ts +32 -0
- package/dist/lib/crypto/zeroAccessKey.js +71 -0
- package/dist/lib/mail/conversationsApi.d.ts +6 -0
- package/dist/lib/mail/mailApi.d.ts +63 -2
- package/dist/lib/mail/mailApi.js +5 -1
- package/dist/lib/mail/mailboxImportApi.d.ts +10 -0
- package/dist/lib/mail/mailboxImportApi.js +15 -0
- package/dist/lib/search/zeroAccessIndexApi.d.ts +85 -0
- package/dist/lib/search/zeroAccessIndexApi.js +35 -0
- package/dist/lib/tasks/tasksApi.d.ts +11 -1
- package/dist/lib/tasks/tasksApi.js +10 -4
- package/dist/lib/util/clientPlatform.d.ts +14 -0
- package/dist/lib/util/clientPlatform.js +26 -0
- package/dist/lib/videoconf/protectedMeetings.d.ts +74 -0
- package/dist/lib/videoconf/protectedMeetings.js +181 -0
- package/dist/lib/videoconf/videoMeetingsApi.d.ts +25 -4
- package/dist/lib/videoconf/videoMeetingsApi.js +1 -1
- package/dist/lib/zeroAccess/sealedMoves.d.ts +41 -0
- package/dist/lib/zeroAccess/sealedMoves.js +63 -0
- package/dist/lib/zeroAccess/sealedRecords.d.ts +29 -0
- package/dist/lib/zeroAccess/sealedRecords.js +136 -0
- package/lib/admin/domainsApi.ts +1 -1
- package/lib/admin/escrowAccessRequestsApi.ts +6 -0
- package/lib/calendar/calendarApi.ts +143 -17
- package/lib/calendar/calendarMutations.ts +79 -12
- package/lib/calendar/inviteApi.ts +101 -8
- package/lib/calendar/protectedEvents.ts +143 -0
- package/lib/calendar/recurrence.ts +17 -0
- package/lib/calendar/sealedInvites.ts +73 -0
- package/lib/contacts/contactsApi.ts +43 -17
- package/lib/contacts/useContactPhotoSrc.ts +103 -13
- package/lib/crypto/composeSecurity.ts +20 -5
- package/lib/crypto/keyExport.ts +229 -0
- package/lib/crypto/keyPairMatch.ts +69 -0
- package/lib/crypto/keySession.ts +216 -12
- package/lib/crypto/keyvaultApi.ts +174 -10
- package/lib/crypto/meetingKeys.ts +118 -0
- package/lib/crypto/messageSecurity.ts +284 -16
- package/lib/crypto/mime.ts +26 -0
- package/lib/crypto/openPgpKey.ts +118 -0
- package/lib/crypto/openpgp.ts +115 -0
- package/lib/crypto/pgpMessage.ts +336 -0
- package/lib/crypto/sharedMailboxKeys.ts +402 -0
- package/lib/crypto/smimeMessage.ts +11 -7
- package/lib/crypto/zeroAccessKey.ts +102 -0
- package/lib/mail/conversationsApi.ts +3 -0
- package/lib/mail/mailApi.ts +60 -3
- package/lib/mail/mailboxImportApi.ts +24 -0
- package/lib/search/zeroAccessIndexApi.ts +123 -0
- package/lib/tasks/tasksApi.ts +19 -5
- package/lib/util/clientPlatform.ts +50 -0
- package/lib/videoconf/protectedMeetings.ts +221 -0
- package/lib/videoconf/videoMeetingsApi.ts +15 -4
- package/lib/zeroAccess/sealedMoves.ts +79 -0
- package/lib/zeroAccess/sealedRecords.ts +153 -0
- package/package.json +14 -5
|
@@ -24,16 +24,30 @@ import {
|
|
|
24
24
|
import { ApiRequestError } from "../../../lib/util/api.js";
|
|
25
25
|
import { useApiClient } from "../../../lib/util/apiClientContext.js";
|
|
26
26
|
import useIsMobile from "../../../lib/util/useIsMobile.js";
|
|
27
|
-
import { CalendarEvent, getCalendarEvent, listCalendarEvents } from "../../../lib/calendar/calendarApi.js";
|
|
27
|
+
import { CalendarEvent, fullyOpenedEvent, getCalendarEvent, listCalendarEvents } from "../../../lib/calendar/calendarApi.js";
|
|
28
|
+
import { isOpenedRecord, isProtectedRecord } from "../../../lib/zeroAccess/sealedRecords.js";
|
|
29
|
+
import { isSealedRecord } from "../../../lib/zeroAccess/sealedMoves.js";
|
|
30
|
+
import { useKeysLocked } from "../../shared/zeroAccess/useKeysLocked.js";
|
|
31
|
+
import { openSealedEvent, openSealedEvents } from "../../shared/calendar/sealedEvents.js";
|
|
28
32
|
import { useFolderLiveUpdates } from "../../shared/live/useFolderLiveUpdates.js";
|
|
29
|
-
import { moveOccurrence, resizeOccurrenceEnd } from "../../../lib/calendar/calendarMutations.js";
|
|
33
|
+
import { SealedOccurrenceError, moveOccurrence, resizeOccurrenceEnd } from "../../../lib/calendar/calendarMutations.js";
|
|
30
34
|
import { resolveDragAction } from "../../../lib/calendar/calendarDragIds.js";
|
|
31
35
|
import { createFolder } from "../../../lib/mail/mailApi.js";
|
|
32
36
|
import { CalendarOccurrence, expandAllOccurrences, expandOccurrences } from "../../../lib/calendar/recurrence.js";
|
|
33
37
|
import { useDayKey } from "../../../lib/calendar/useDayKey.js";
|
|
34
|
-
import {
|
|
38
|
+
import {
|
|
39
|
+
allOccurrences,
|
|
40
|
+
initialMatchIndex,
|
|
41
|
+
occurrencesInRange,
|
|
42
|
+
searchOccurrences,
|
|
43
|
+
searchTerms,
|
|
44
|
+
stepSequenceIndex,
|
|
45
|
+
} from "../../../lib/calendar/eventSearch.js";
|
|
35
46
|
import Drawer from "../../../lib/components/overlays/Drawer.js";
|
|
36
|
-
import CalendarShell, {
|
|
47
|
+
import CalendarShell, {
|
|
48
|
+
CalendarShellProps,
|
|
49
|
+
useCalendarShell,
|
|
50
|
+
} from "../../shared/components/calendar/layout/CalendarShell.js";
|
|
37
51
|
import CalendarListSidebar from "../../shared/components/calendar/CalendarListSidebar.js";
|
|
38
52
|
import CalendarSearchBox from "../../shared/components/calendar/CalendarSearchBox.js";
|
|
39
53
|
import { ActiveOccurrenceContext } from "../../shared/components/calendar/activeOccurrence.js";
|
|
@@ -49,7 +63,13 @@ import SplitDayView from "../../shared/components/calendar/SplitDayView.js";
|
|
|
49
63
|
import TimeGridView from "../../shared/components/calendar/TimeGridView.js";
|
|
50
64
|
import Alert from "../../../lib/components/feedback/Alert.js";
|
|
51
65
|
import Button from "../../../lib/components/buttons/Button.js";
|
|
52
|
-
import {
|
|
66
|
+
import {
|
|
67
|
+
CALENDAR_VIEWS,
|
|
68
|
+
CalendarView,
|
|
69
|
+
getStoredCalendarView,
|
|
70
|
+
isCalendarView,
|
|
71
|
+
storeCalendarView,
|
|
72
|
+
} from "../../shared/components/calendar/calendarView.js";
|
|
53
73
|
import { SlideFrom } from "../../shared/components/calendar/SlideIn.js";
|
|
54
74
|
import { SWIPE_PERIOD_SHIFT } from "../../shared/components/calendar/swipeNavigation.js";
|
|
55
75
|
import { nextHalfHour } from "../../shared/components/calendar/timePicker.js";
|
|
@@ -60,6 +80,8 @@ import { SHORTCUTS, ShortcutDef } from "../../shared/keyboard/keymap.js";
|
|
|
60
80
|
import { useShortcut } from "../../shared/keyboard/useShortcut.js";
|
|
61
81
|
import { useShortcutProps } from "../../shared/keyboard/useShortcutProps.js";
|
|
62
82
|
import { notifyApiError } from "../../shared/notifications/apiErrors.js";
|
|
83
|
+
import { notify } from "../../shared/notifications/store.js";
|
|
84
|
+
import { KeysLockedError } from "../../../lib/crypto/masterKey.js";
|
|
63
85
|
import { bookingSettingsHref } from "../../shared/calendar/bookingPlugin.js";
|
|
64
86
|
import { changedEventOf } from "../../shared/calendar/calendarLiveUpdates.js";
|
|
65
87
|
|
|
@@ -78,7 +100,14 @@ function CalendarPage(props: CalendarShellProps) {
|
|
|
78
100
|
}
|
|
79
101
|
|
|
80
102
|
type ViewType = CalendarView;
|
|
81
|
-
const VIEW_LABELS: Record<ViewType, string> = {
|
|
103
|
+
const VIEW_LABELS: Record<ViewType, string> = {
|
|
104
|
+
list: "List",
|
|
105
|
+
month: "Month",
|
|
106
|
+
week: "Week",
|
|
107
|
+
workWeek: "Work Week",
|
|
108
|
+
day: "Day",
|
|
109
|
+
split: "Split",
|
|
110
|
+
};
|
|
82
111
|
/** The shortcut that switches to a view (Outlook's Ctrl+Alt+1-4, the List one more); the split view has none. */
|
|
83
112
|
const VIEW_SHORTCUTS: Partial<Record<ViewType, ShortcutDef>> = {
|
|
84
113
|
list: SHORTCUTS.calendar.list,
|
|
@@ -89,7 +118,15 @@ const VIEW_SHORTCUTS: Partial<Record<ViewType, ShortcutDef>> = {
|
|
|
89
118
|
};
|
|
90
119
|
|
|
91
120
|
/** One of the view switcher's buttons, with its shortcut in the tooltip. */
|
|
92
|
-
function ViewButton({
|
|
121
|
+
function ViewButton({
|
|
122
|
+
view,
|
|
123
|
+
current,
|
|
124
|
+
onSelect,
|
|
125
|
+
}: {
|
|
126
|
+
view: ViewType;
|
|
127
|
+
current: ViewType;
|
|
128
|
+
onSelect: (view: ViewType) => void;
|
|
129
|
+
}) {
|
|
93
130
|
const shortcut = VIEW_SHORTCUTS[view];
|
|
94
131
|
const hint = useShortcutProps(VIEW_LABELS[view], shortcut ?? SHORTCUTS.calendar.day, !!shortcut);
|
|
95
132
|
return (
|
|
@@ -124,7 +161,8 @@ interface ModalState {
|
|
|
124
161
|
}
|
|
125
162
|
|
|
126
163
|
function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHref?: string }) {
|
|
127
|
-
const { mailboxUid, folderUid, calendarFolders, mailboxCalendars, mailboxes, reloadFolders, colorFor } =
|
|
164
|
+
const { mailboxUid, folderUid, calendarFolders, mailboxCalendars, mailboxes, reloadFolders, colorFor } =
|
|
165
|
+
useCalendarShell();
|
|
128
166
|
const client = useApiClient();
|
|
129
167
|
// `PointerSensor` alone activates a drag on the very first touch-move, indistinguishable from a
|
|
130
168
|
// scroll gesture on a touch device. `MouseSensor` (a small `distance` — desktop drags still start
|
|
@@ -133,7 +171,7 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
133
171
|
// dnd-kit's own documented pattern for this exact conflict.
|
|
134
172
|
const sensors = useSensors(
|
|
135
173
|
useSensor(MouseSensor, { activationConstraint: { distance: 8 } }),
|
|
136
|
-
useSensor(TouchSensor, { activationConstraint: { delay: 250, tolerance: 8 } })
|
|
174
|
+
useSensor(TouchSensor, { activationConstraint: { delay: 250, tolerance: 8 } })
|
|
137
175
|
);
|
|
138
176
|
|
|
139
177
|
const [drawerOpen, setDrawerOpen] = useState(false);
|
|
@@ -194,7 +232,7 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
194
232
|
const checkedFolderUids = checkedFolderUidsState ?? new Set(calendarFolders.map((f) => f.uid));
|
|
195
233
|
const folderColors = useMemo(
|
|
196
234
|
() => Object.fromEntries(calendarFolders.map((f) => [f.uid, colorFor(f)])),
|
|
197
|
-
[calendarFolders, colorFor]
|
|
235
|
+
[calendarFolders, colorFor]
|
|
198
236
|
);
|
|
199
237
|
|
|
200
238
|
function toggleCalendar(toggledUid: string) {
|
|
@@ -257,7 +295,7 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
257
295
|
}
|
|
258
296
|
setLoading(true);
|
|
259
297
|
setError(null);
|
|
260
|
-
void Promise.allSettled(targets.map((f) => listCalendarEvents(f.uid, client)))
|
|
298
|
+
void Promise.allSettled(targets.map((f) => listCalendarEvents(f.uid, client).then(openSealedEvents)))
|
|
261
299
|
.then((results) => {
|
|
262
300
|
if (seq !== reloadSeqRef.current) {
|
|
263
301
|
return;
|
|
@@ -295,7 +333,10 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
295
333
|
|
|
296
334
|
// Keyed on stable string summaries (not the array/set objects themselves, which are new references
|
|
297
335
|
// every render) so this only re-fires when the actual set of folders to fetch changes.
|
|
298
|
-
const calendarFolderUidsKey = calendarFolders
|
|
336
|
+
const calendarFolderUidsKey = calendarFolders
|
|
337
|
+
.map((f) => f.uid)
|
|
338
|
+
.sort()
|
|
339
|
+
.join(",");
|
|
299
340
|
const checkedFolderUidsKey = Array.from(checkedFolderUids).sort().join(",");
|
|
300
341
|
useEffect(reload, [calendarFolderUidsKey, checkedFolderUidsKey]);
|
|
301
342
|
|
|
@@ -317,23 +358,25 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
317
358
|
setEvents((previous) => previous.filter((existing) => existing.uid !== uid));
|
|
318
359
|
return;
|
|
319
360
|
}
|
|
320
|
-
void getCalendarEvent(uid, client)
|
|
321
|
-
(
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
361
|
+
void getCalendarEvent(uid, client)
|
|
362
|
+
.then(openSealedEvent)
|
|
363
|
+
.then(
|
|
364
|
+
(fresh) => {
|
|
365
|
+
if (checkedFolderUidsRef.current.has(fresh.folderUid)) {
|
|
366
|
+
setEvents((previous) =>
|
|
367
|
+
previous.some((existing) => existing.uid === fresh.uid)
|
|
368
|
+
? previous.map((existing) => (existing.uid === fresh.uid ? fresh : existing))
|
|
369
|
+
: [...previous, fresh]
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
},
|
|
373
|
+
(err: unknown) => {
|
|
374
|
+
if (err instanceof ApiRequestError && err.status === 404) {
|
|
375
|
+
setEvents((previous) => previous.filter((existing) => existing.uid !== uid));
|
|
376
|
+
}
|
|
333
377
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
},
|
|
378
|
+
);
|
|
379
|
+
}
|
|
337
380
|
);
|
|
338
381
|
|
|
339
382
|
// Search: `searchText` is the box, `query` what it held once typing paused (or Enter was pressed) and is what is searched for. A search covers every
|
|
@@ -352,16 +395,52 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
352
395
|
// Today moves on at midnight: the List's "from today on" is worked out again then (`listDay` is only a dependency).
|
|
353
396
|
const listDay = useDayKey();
|
|
354
397
|
const dayOfList = view === "list" ? listDay : "";
|
|
398
|
+
// A search matches descriptions too, which a list leaves sealed (`EVENT_LIST_FIELDS`): the protected events are opened in full once one
|
|
399
|
+
// runs, and searched as they are until then.
|
|
400
|
+
const [searchable, setSearchable] = useState<{ from: CalendarEvent[]; events: CalendarEvent[] } | null>(null);
|
|
401
|
+
useEffect(() => {
|
|
402
|
+
if (!searching || !events.some((event) => isProtectedRecord(event) && !isOpenedRecord(event))) {
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
let cancelled = false;
|
|
406
|
+
void Promise.all(events.map((event) => fullyOpenedEvent(event))).then((opened) => {
|
|
407
|
+
if (!cancelled) {
|
|
408
|
+
setSearchable({ from: events, events: opened });
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
return () => {
|
|
412
|
+
cancelled = true;
|
|
413
|
+
};
|
|
414
|
+
}, [events, searching]);
|
|
415
|
+
const searchedEvents = searchable?.from === events ? searchable.events : events;
|
|
416
|
+
|
|
417
|
+
// The calendar holds protected events opened with their mailboxes' keys: a lock of one takes them off screen - read again with their
|
|
418
|
+
// placeholders, the search's fully opened copies dropped, and an open card or form of a protected event closed - its own mailbox's
|
|
419
|
+
// lock closes it too when it isn't one of the listed events (opened from a reminder, its calendar unchecked).
|
|
420
|
+
useKeysLocked((locked) => {
|
|
421
|
+
const listed: boolean = events.some((event) => event.mailboxUid === locked);
|
|
422
|
+
setModal((current) =>
|
|
423
|
+
current?.occurrence && isSealedRecord(current.occurrence) && (listed || current.occurrence.mailboxUid === locked) ? null : current,
|
|
424
|
+
);
|
|
425
|
+
if (!listed) {
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
reload();
|
|
429
|
+
setSearchable(null);
|
|
430
|
+
});
|
|
355
431
|
const matches = useMemo(() => {
|
|
356
|
-
const found = searching ? searchOccurrences(
|
|
432
|
+
const found = searching ? searchOccurrences(searchedEvents, query) : [];
|
|
357
433
|
const today = new Date();
|
|
358
434
|
return view === "list" ? found.filter((occurrence) => isUpcoming(occurrence, today)) : found;
|
|
359
|
-
}, [
|
|
435
|
+
}, [searchedEvents, query, searching, view, dayOfList]);
|
|
360
436
|
const activeIndex = matches.findIndex((m) => m.occurrenceKey === activeKey);
|
|
361
437
|
|
|
362
438
|
// What an open event card steps through, in order: the matches while a search runs, else every event of the checked calendars (bounded as a
|
|
363
439
|
// search is). The List holds only what is from today on, so that is all its card steps through. Worked out only when something needs it.
|
|
364
|
-
const everything = useMemo(
|
|
440
|
+
const everything = useMemo(
|
|
441
|
+
() => (view === "list" || modal?.occurrence ? allOccurrences(events) : []),
|
|
442
|
+
[events, view, !!modal?.occurrence]
|
|
443
|
+
);
|
|
365
444
|
const sequence = useMemo(() => {
|
|
366
445
|
if (searching) {
|
|
367
446
|
return matches;
|
|
@@ -377,7 +456,9 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
377
456
|
if (view === "list") {
|
|
378
457
|
return sequence;
|
|
379
458
|
}
|
|
380
|
-
return searching
|
|
459
|
+
return searching
|
|
460
|
+
? occurrencesInRange(matches, rangeStart, rangeEnd)
|
|
461
|
+
: expandAllOccurrences(events, rangeStart, rangeEnd);
|
|
381
462
|
}, [events, matches, searching, view, sequence, rangeStart, rangeEnd]);
|
|
382
463
|
|
|
383
464
|
/** Points at `match`, moving the view to the day it is on unless the view already shows it. */
|
|
@@ -397,7 +478,13 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
397
478
|
// calendar do not.
|
|
398
479
|
const stepFrom = modal?.occurrence;
|
|
399
480
|
const stepIndex = (direction: 1 | -1) =>
|
|
400
|
-
stepSequenceIndex(
|
|
481
|
+
stepSequenceIndex(
|
|
482
|
+
sequence,
|
|
483
|
+
stepFrom?.occurrenceKey ?? activeKey,
|
|
484
|
+
stepFrom ? new Date(stepFrom.startDate) : undefined,
|
|
485
|
+
direction,
|
|
486
|
+
searching
|
|
487
|
+
);
|
|
401
488
|
|
|
402
489
|
function stepMatch(direction: 1 | -1) {
|
|
403
490
|
const next = sequence[stepIndex(direction)];
|
|
@@ -433,17 +520,22 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
433
520
|
searchedQueryRef.current = query;
|
|
434
521
|
// The List holds every match: it starts at the first from the day being viewed on rather than the first of all.
|
|
435
522
|
const from = startOfDay(viewDate);
|
|
436
|
-
showMatch(
|
|
523
|
+
showMatch(
|
|
524
|
+
matches[
|
|
525
|
+
view === "list"
|
|
526
|
+
? initialMatchIndex(matches, from, rangeEnd, from)
|
|
527
|
+
: initialMatchIndex(matches, rangeStart, rangeEnd, from)
|
|
528
|
+
]
|
|
529
|
+
);
|
|
437
530
|
}
|
|
438
531
|
}, [matches, query, searching]);
|
|
439
532
|
|
|
440
|
-
|
|
441
533
|
const splitColumns = useMemo(
|
|
442
534
|
() =>
|
|
443
535
|
calendarFolders
|
|
444
536
|
.filter((f) => checkedFolderUids.has(f.uid))
|
|
445
537
|
.map((f) => ({ folderUid: f.uid, name: f.name, color: colorFor(f) })),
|
|
446
|
-
[calendarFolders, checkedFolderUidsKey, colorFor]
|
|
538
|
+
[calendarFolders, checkedFolderUidsKey, colorFor]
|
|
447
539
|
);
|
|
448
540
|
|
|
449
541
|
function shiftView(direction: 1 | -1) {
|
|
@@ -457,7 +549,7 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
457
549
|
? addMonths(d, direction)
|
|
458
550
|
: view === "week" || view === "workWeek"
|
|
459
551
|
? addWeeks(d, direction)
|
|
460
|
-
: addDays(d, direction)
|
|
552
|
+
: addDays(d, direction)
|
|
461
553
|
);
|
|
462
554
|
}
|
|
463
555
|
|
|
@@ -476,7 +568,8 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
476
568
|
const wheelSlide = useEnterSlide();
|
|
477
569
|
/** Where the scroller of the page a wheel step arrived at starts: its top after going on, its bottom after going back. */
|
|
478
570
|
const arrivalEdge = useRef<WheelEdge | null>(null);
|
|
479
|
-
const scrollerOf = (): HTMLElement | null =>
|
|
571
|
+
const scrollerOf = (): HTMLElement | null =>
|
|
572
|
+
swipe.ref.current?.querySelector<HTMLElement>("[data-calendar-scroller]") ?? null;
|
|
480
573
|
useWheelPaging(swipe.ref, {
|
|
481
574
|
enabled: !isMobile && !dragging && !modal && view !== "list",
|
|
482
575
|
getScroller: () => (view === "month" ? null : scrollerOf()),
|
|
@@ -498,7 +591,9 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
498
591
|
// Brings the match being pointed at into sight (the views scroll their own hours; the page may too).
|
|
499
592
|
useEffect(() => {
|
|
500
593
|
const marked = Array.from(swipe.ref.current!.querySelectorAll<HTMLElement>("[data-occurrence-key]"));
|
|
501
|
-
marked
|
|
594
|
+
marked
|
|
595
|
+
.find((el) => el.dataset.occurrenceKey === activeKey)
|
|
596
|
+
?.scrollIntoView({ block: "nearest", inline: "nearest" });
|
|
502
597
|
}, [activeKey, view === "list" ? null : viewDate, view, loading]);
|
|
503
598
|
|
|
504
599
|
// The List scrolls to `viewDate` when this changes (Today, a day picked in the mini calendar), even when it is the date it already has.
|
|
@@ -514,7 +609,13 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
514
609
|
setViewDate(startOfDay(date));
|
|
515
610
|
}
|
|
516
611
|
|
|
517
|
-
function openNewEvent(
|
|
612
|
+
function openNewEvent(
|
|
613
|
+
start?: Date,
|
|
614
|
+
end?: Date,
|
|
615
|
+
targetFolderUid?: string,
|
|
616
|
+
anchor?: EventAnchor,
|
|
617
|
+
initialAllDay?: boolean
|
|
618
|
+
) {
|
|
518
619
|
if (!mailboxUid || !folderUid) {
|
|
519
620
|
return;
|
|
520
621
|
}
|
|
@@ -558,10 +659,17 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
558
659
|
const requestedStart = new Date(params.get("start") ?? "");
|
|
559
660
|
navigateTo("/calendar", { replace: true });
|
|
560
661
|
getCalendarEvent(eventUid, client)
|
|
662
|
+
.then(openSealedEvent)
|
|
561
663
|
.then((event) => {
|
|
562
664
|
const from = isNaN(requestedStart.getTime()) ? new Date(event.startDate) : requestedStart;
|
|
563
|
-
const candidates = expandOccurrences(
|
|
564
|
-
|
|
665
|
+
const candidates = expandOccurrences(
|
|
666
|
+
event,
|
|
667
|
+
new Date(from.getTime() - 86_400_000),
|
|
668
|
+
new Date(from.getTime() + 86_400_000)
|
|
669
|
+
);
|
|
670
|
+
const match =
|
|
671
|
+
candidates.find((occurrence) => new Date(occurrence.startDate).getTime() === from.getTime()) ??
|
|
672
|
+
candidates[0];
|
|
565
673
|
if (match) {
|
|
566
674
|
setViewDate(occurrenceDay(match));
|
|
567
675
|
openEvent(match);
|
|
@@ -614,7 +722,13 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
614
722
|
}
|
|
615
723
|
reload();
|
|
616
724
|
} catch (err) {
|
|
617
|
-
|
|
725
|
+
const context = action.type === "move" ? "Couldn't move the event" : "Couldn't resize the event";
|
|
726
|
+
if (err instanceof KeysLockedError || err instanceof SealedOccurrenceError) {
|
|
727
|
+
// A protected occurrence while the mailbox is locked, or one of a zero-access invitation: nothing was written.
|
|
728
|
+
notify({ kind: "warning", title: context, message: err.message });
|
|
729
|
+
} else {
|
|
730
|
+
notifyApiError(err, context);
|
|
731
|
+
}
|
|
618
732
|
// A refused change (a 409 most of all) means the page holds a stale version: load again, or every later drag of this event fails the same way.
|
|
619
733
|
reload();
|
|
620
734
|
}
|
|
@@ -625,9 +739,9 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
625
739
|
? "Upcoming events"
|
|
626
740
|
: view === "month"
|
|
627
741
|
? format(viewDate, "MMMM yyyy")
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
742
|
+
: view === "week" || view === "workWeek"
|
|
743
|
+
? `${format(rangeStart, "MMM d")} – ${format(rangeEnd, "MMM d, yyyy")}`
|
|
744
|
+
: format(viewDate, "EEEE, MMMM d, yyyy");
|
|
631
745
|
|
|
632
746
|
const modalFolderUid = modal ? (modal.targetFolderUid ?? modal.occurrence?.folderUid ?? folderUid) : undefined;
|
|
633
747
|
const modalMailboxUid = calendarFolders.find((f) => f.uid === modalFolderUid)?.mailboxUid ?? mailboxUid;
|
|
@@ -638,9 +752,14 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
638
752
|
const mailboxOptions = useMemo(
|
|
639
753
|
() =>
|
|
640
754
|
mailboxCalendars
|
|
641
|
-
.filter(
|
|
642
|
-
|
|
643
|
-
|
|
755
|
+
.filter(
|
|
756
|
+
(mc) => mc.calendarFolders.length > 0 && writableMailboxes.some((mb) => mb.uid === mc.mailbox.uid)
|
|
757
|
+
)
|
|
758
|
+
.map((mc) => ({
|
|
759
|
+
mailbox: mc.mailbox,
|
|
760
|
+
calendars: mc.calendarFolders.map((f) => ({ uid: f.uid, name: f.name })),
|
|
761
|
+
})),
|
|
762
|
+
[mailboxCalendars, writableMailboxes]
|
|
644
763
|
);
|
|
645
764
|
|
|
646
765
|
const sidebarContent = (
|
|
@@ -664,7 +783,9 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
664
783
|
|
|
665
784
|
return (
|
|
666
785
|
<div className="flex-1 min-w-0 flex min-h-0">
|
|
667
|
-
<div className="hidden lg:flex w-56 shrink-0 border-r border-border flex-col overflow-y-auto">
|
|
786
|
+
<div className="hidden lg:flex w-56 shrink-0 border-r border-border flex-col overflow-y-auto">
|
|
787
|
+
{sidebarContent}
|
|
788
|
+
</div>
|
|
668
789
|
<Drawer open={drawerOpen} onClose={() => setDrawerOpen(false)} title="Calendars" fullScreen>
|
|
669
790
|
<div className="flex flex-col">{sidebarContent}</div>
|
|
670
791
|
</Drawer>
|
|
@@ -681,18 +802,42 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
681
802
|
</button>
|
|
682
803
|
{/* On a phone New event is the floating button at the bottom of the page instead, as in Mail. */}
|
|
683
804
|
{!isMobile && (
|
|
684
|
-
<Button
|
|
805
|
+
<Button
|
|
806
|
+
type="button"
|
|
807
|
+
onClick={(e) =>
|
|
808
|
+
openNewEvent(undefined, undefined, undefined, anchorOf(e.currentTarget, "below"))
|
|
809
|
+
}
|
|
810
|
+
className="!w-auto shrink-0"
|
|
811
|
+
{...newEventHint}
|
|
812
|
+
>
|
|
685
813
|
+ New event
|
|
686
814
|
</Button>
|
|
687
815
|
)}
|
|
688
816
|
<div className="flex items-center gap-1">
|
|
689
|
-
<button
|
|
817
|
+
<button
|
|
818
|
+
type="button"
|
|
819
|
+
onClick={() => shiftView(-1)}
|
|
820
|
+
aria-label="Previous"
|
|
821
|
+
{...previousHint}
|
|
822
|
+
className="w-7 h-7 text-sm rounded-sm hover:bg-surface-alt"
|
|
823
|
+
>
|
|
690
824
|
‹
|
|
691
825
|
</button>
|
|
692
|
-
<button
|
|
826
|
+
<button
|
|
827
|
+
type="button"
|
|
828
|
+
onClick={goToday}
|
|
829
|
+
{...todayHint}
|
|
830
|
+
className="px-2 h-7 text-sm rounded-sm hover:bg-surface-alt"
|
|
831
|
+
>
|
|
693
832
|
Today
|
|
694
833
|
</button>
|
|
695
|
-
<button
|
|
834
|
+
<button
|
|
835
|
+
type="button"
|
|
836
|
+
onClick={() => shiftView(1)}
|
|
837
|
+
aria-label="Next"
|
|
838
|
+
{...nextHint}
|
|
839
|
+
className="w-7 h-7 text-sm rounded-sm hover:bg-surface-alt"
|
|
840
|
+
>
|
|
696
841
|
›
|
|
697
842
|
</button>
|
|
698
843
|
</div>
|
|
@@ -722,8 +867,17 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
722
867
|
</div>
|
|
723
868
|
)}
|
|
724
869
|
|
|
725
|
-
<div
|
|
726
|
-
|
|
870
|
+
<div
|
|
871
|
+
ref={swipe.ref}
|
|
872
|
+
className="flex-1 min-w-0 flex flex-col min-h-0 overflow-hidden"
|
|
873
|
+
{...swipe.handlers}
|
|
874
|
+
style={swipe.style}
|
|
875
|
+
>
|
|
876
|
+
<div
|
|
877
|
+
data-swipe-phase={swipe.phase}
|
|
878
|
+
className="flex-1 min-w-0 flex flex-col min-h-0"
|
|
879
|
+
style={swipe.contentStyle}
|
|
880
|
+
>
|
|
727
881
|
<div className="flex-1 min-w-0 flex flex-col min-h-0" style={wheelSlide.style}>
|
|
728
882
|
{loading ? (
|
|
729
883
|
<p className="p-4 text-sm text-text-muted">Loading…</p>
|
|
@@ -751,7 +905,9 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
751
905
|
folderColors={folderColors}
|
|
752
906
|
onSelectDay={handleSelectDay}
|
|
753
907
|
onSelectEvent={openEvent}
|
|
754
|
-
onSelectSlot={(start, end, anchor) =>
|
|
908
|
+
onSelectSlot={(start, end, anchor) =>
|
|
909
|
+
openNewEvent(start, end, undefined, anchor, true)
|
|
910
|
+
}
|
|
755
911
|
/>
|
|
756
912
|
) : view === "split" ? (
|
|
757
913
|
<SplitDayView
|
|
@@ -759,7 +915,9 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
759
915
|
columns={splitColumns}
|
|
760
916
|
occurrences={occurrences}
|
|
761
917
|
onSelectEvent={openEvent}
|
|
762
|
-
onSelectSlot={(start, end, targetFolderUid, anchor) =>
|
|
918
|
+
onSelectSlot={(start, end, targetFolderUid, anchor) =>
|
|
919
|
+
openNewEvent(start, end, targetFolderUid, anchor)
|
|
920
|
+
}
|
|
763
921
|
/>
|
|
764
922
|
) : (
|
|
765
923
|
<TimeGridView
|
|
@@ -767,7 +925,9 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
767
925
|
occurrences={occurrences}
|
|
768
926
|
folderColors={folderColors}
|
|
769
927
|
onSelectEvent={openEvent}
|
|
770
|
-
onSelectSlot={(start, end, anchor) =>
|
|
928
|
+
onSelectSlot={(start, end, anchor) =>
|
|
929
|
+
openNewEvent(start, end, undefined, anchor)
|
|
930
|
+
}
|
|
771
931
|
/>
|
|
772
932
|
)}
|
|
773
933
|
</DndContext>
|
|
@@ -787,7 +947,9 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
787
947
|
onClose={closeModal}
|
|
788
948
|
mailboxUid={modalMailbox.uid}
|
|
789
949
|
folderUid={modalFolderUid!}
|
|
790
|
-
calendars={calendarFolders
|
|
950
|
+
calendars={calendarFolders
|
|
951
|
+
.filter((f) => f.mailboxUid === modalMailbox.uid)
|
|
952
|
+
.map((f) => ({ uid: f.uid, name: f.name }))}
|
|
791
953
|
mailboxOptions={mailboxOptions}
|
|
792
954
|
folderColors={folderColors}
|
|
793
955
|
organizerAddress={modalMailbox.primarySmtpAddress}
|
|
@@ -816,7 +978,9 @@ function CalendarContent({ userUid, bookingHref }: { userUid?: string; bookingHr
|
|
|
816
978
|
)}
|
|
817
979
|
{/* The phone layout's New event: the old toolbar button's action (its quick form is a bottom sheet there, so no anchor), offered
|
|
818
980
|
only where that button could act - a calendar to put the event in - and not while the editor or its sheet is open. */}
|
|
819
|
-
{isMobile && mailboxUid && folderUid && !modal &&
|
|
981
|
+
{isMobile && mailboxUid && folderUid && !modal && (
|
|
982
|
+
<FloatingActionButton label="New event" icon={HiOutlinePlus} onClick={() => openNewEvent()} />
|
|
983
|
+
)}
|
|
820
984
|
</div>
|
|
821
985
|
</div>
|
|
822
986
|
);
|