@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.
Files changed (268) hide show
  1. package/apps/escrow/matters/[uid].tsx +4 -3
  2. package/apps/shared/calendar/calendarReminders.ts +35 -0
  3. package/apps/shared/calendar/sealedEvents.ts +113 -0
  4. package/apps/shared/calendar/useCalendarReminders.ts +28 -9
  5. package/apps/shared/components/admin/settings/DomainDnsSetup.tsx +4 -0
  6. package/apps/shared/components/admin/settings/EncryptionPolicyForm.tsx +89 -3
  7. package/apps/shared/components/calendar/EventDetails.tsx +13 -2
  8. package/apps/shared/components/calendar/EventEditor.tsx +124 -17
  9. package/apps/shared/components/calendar/EventFormParts.tsx +1 -0
  10. package/apps/shared/components/calendar/EventModal.tsx +19 -2
  11. package/apps/shared/components/calendar/RequestChangeForm.tsx +4 -1
  12. package/apps/shared/components/calendar/eventForm.ts +2 -0
  13. package/apps/shared/components/contacts/ContactCard.tsx +13 -1
  14. package/apps/shared/components/contacts/ContactDetailPane.tsx +189 -9
  15. package/apps/shared/components/contacts/ContactForm.tsx +56 -7
  16. package/apps/shared/components/contacts/KeyChangeReview.tsx +5 -1
  17. package/apps/shared/components/contacts/contactCardData.ts +8 -4
  18. package/apps/shared/components/contacts/contactKeys.ts +3 -3
  19. package/apps/shared/components/layout/AppShell.tsx +34 -5
  20. package/apps/shared/components/layout/KeyEnrollmentGate.tsx +30 -1
  21. package/apps/shared/components/layout/SharedMailboxKeyManager.tsx +122 -0
  22. package/apps/shared/components/layout/UnlockPromptProvider.tsx +34 -0
  23. package/apps/shared/components/mail/ConversationList.tsx +1 -1
  24. package/apps/shared/components/mail/InviteCard.tsx +11 -1
  25. package/apps/shared/components/mail/MessageDetailPane.tsx +59 -26
  26. package/apps/shared/components/mail/compose/ComposeWindow.tsx +9 -2
  27. package/apps/shared/components/mail/compose/RecipientInput.tsx +2 -1
  28. package/apps/shared/components/mail/compose/draftResume.ts +28 -3
  29. package/apps/shared/components/mail/compose/protectedContactSuggestions.ts +121 -0
  30. package/apps/shared/components/mail/compose/quotedBody.ts +4 -3
  31. package/apps/shared/components/mail/invite/inviteStore.ts +17 -1
  32. package/apps/shared/components/mail/layout/MailShell.tsx +2 -0
  33. package/apps/shared/components/mail/pinnedSigners.ts +14 -0
  34. package/apps/shared/components/mail/reading/conversationPrint.ts +3 -3
  35. package/apps/shared/components/mail/reading/useMessageActions.ts +4 -1
  36. package/apps/shared/components/settings/KeyExportSetting.tsx +173 -0
  37. package/apps/shared/components/settings/OpenPgpKeySetting.tsx +240 -0
  38. package/apps/shared/components/settings/PolicyLockedNotice.tsx +23 -0
  39. package/apps/shared/components/settings/ZeroAccessSetting.tsx +128 -0
  40. package/apps/shared/components/settings/ZeroAccessTypes.tsx +175 -0
  41. package/apps/shared/components/settings/layout/SettingsShell.tsx +9 -2
  42. package/apps/shared/mail/decryptedMessages.ts +11 -3
  43. package/apps/shared/mail/outbox/sendJob.ts +349 -50
  44. package/apps/shared/mail/outbox/sendOutcomes.ts +91 -20
  45. package/apps/shared/mail/reportNotices.ts +3 -1
  46. package/apps/shared/mail/zeroAccessSource.ts +27 -0
  47. package/apps/shared/search/LocalIndexLifecycle.tsx +84 -24
  48. package/apps/shared/search/localIndexBuilder.ts +57 -20
  49. package/apps/shared/search/localIndexRpcClient.ts +96 -12
  50. package/apps/shared/search/localIndexSchema.ts +20 -4
  51. package/apps/shared/search/localIndexTransport.ts +6 -2
  52. package/apps/shared/search/localIndexWorker.ts +37 -18
  53. package/apps/shared/search/searchTier2.ts +5 -0
  54. package/apps/shared/search/zeroAccessIndexSync.ts +679 -0
  55. package/apps/shared/search/zeroAccessSyncState.ts +70 -0
  56. package/apps/shared/zeroAccess/ProtectedMark.tsx +19 -0
  57. package/apps/shared/zeroAccess/useKeysLocked.ts +25 -0
  58. package/apps/shared/zeroAccess/useOpenedRecord.ts +71 -0
  59. package/apps/www/_shell.tsx +2 -0
  60. package/apps/www/calendar/index.tsx +225 -61
  61. package/apps/www/contacts/index.tsx +67 -11
  62. package/apps/www/index.tsx +19 -3
  63. package/apps/www/settings/encryption/index.tsx +21 -1
  64. package/apps/www/settings/privacy/index.tsx +89 -39
  65. package/apps/www/tasks/index.tsx +24 -6
  66. package/dist/apps/escrow/matters/[uid].js +2 -2
  67. package/dist/apps/shared/calendar/calendarReminders.d.ts +14 -0
  68. package/dist/apps/shared/calendar/calendarReminders.js +26 -0
  69. package/dist/apps/shared/calendar/sealedEvents.d.ts +14 -0
  70. package/dist/apps/shared/calendar/sealedEvents.js +85 -0
  71. package/dist/apps/shared/calendar/useCalendarReminders.d.ts +2 -1
  72. package/dist/apps/shared/calendar/useCalendarReminders.js +27 -9
  73. package/dist/apps/shared/components/admin/settings/DomainDnsSetup.js +3 -0
  74. package/dist/apps/shared/components/admin/settings/EncryptionPolicyForm.js +25 -2
  75. package/dist/apps/shared/components/calendar/EventDetails.js +13 -2
  76. package/dist/apps/shared/components/calendar/EventEditor.js +115 -18
  77. package/dist/apps/shared/components/calendar/EventFormParts.js +1 -1
  78. package/dist/apps/shared/components/calendar/EventModal.d.ts +1 -1
  79. package/dist/apps/shared/components/calendar/EventModal.js +15 -2
  80. package/dist/apps/shared/components/calendar/RequestChangeForm.d.ts +3 -0
  81. package/dist/apps/shared/components/calendar/RequestChangeForm.js +1 -1
  82. package/dist/apps/shared/components/calendar/eventForm.d.ts +2 -0
  83. package/dist/apps/shared/components/contacts/ContactCard.js +12 -1
  84. package/dist/apps/shared/components/contacts/ContactDetailPane.d.ts +2 -1
  85. package/dist/apps/shared/components/contacts/ContactDetailPane.js +103 -9
  86. package/dist/apps/shared/components/contacts/ContactForm.d.ts +4 -1
  87. package/dist/apps/shared/components/contacts/ContactForm.js +37 -7
  88. package/dist/apps/shared/components/contacts/KeyChangeReview.d.ts +3 -1
  89. package/dist/apps/shared/components/contacts/KeyChangeReview.js +3 -2
  90. package/dist/apps/shared/components/contacts/contactCardData.js +8 -4
  91. package/dist/apps/shared/components/contacts/contactKeys.d.ts +1 -1
  92. package/dist/apps/shared/components/contacts/contactKeys.js +3 -3
  93. package/dist/apps/shared/components/layout/AppShell.d.ts +18 -1
  94. package/dist/apps/shared/components/layout/AppShell.js +17 -6
  95. package/dist/apps/shared/components/layout/KeyEnrollmentGate.js +27 -2
  96. package/dist/apps/shared/components/layout/SharedMailboxKeyManager.d.ts +17 -0
  97. package/dist/apps/shared/components/layout/SharedMailboxKeyManager.js +98 -0
  98. package/dist/apps/shared/components/layout/UnlockPromptProvider.d.ts +3 -0
  99. package/dist/apps/shared/components/layout/UnlockPromptProvider.js +32 -0
  100. package/dist/apps/shared/components/mail/ConversationList.js +1 -1
  101. package/dist/apps/shared/components/mail/InviteCard.js +11 -1
  102. package/dist/apps/shared/components/mail/MessageDetailPane.js +46 -21
  103. package/dist/apps/shared/components/mail/compose/ComposeWindow.js +2 -2
  104. package/dist/apps/shared/components/mail/compose/RecipientInput.js +3 -2
  105. package/dist/apps/shared/components/mail/compose/draftResume.d.ts +2 -0
  106. package/dist/apps/shared/components/mail/compose/draftResume.js +28 -3
  107. package/dist/apps/shared/components/mail/compose/protectedContactSuggestions.d.ts +14 -0
  108. package/dist/apps/shared/components/mail/compose/protectedContactSuggestions.js +96 -0
  109. package/dist/apps/shared/components/mail/compose/quotedBody.d.ts +1 -1
  110. package/dist/apps/shared/components/mail/compose/quotedBody.js +4 -3
  111. package/dist/apps/shared/components/mail/invite/inviteStore.js +16 -1
  112. package/dist/apps/shared/components/mail/layout/MailShell.js +2 -1
  113. package/dist/apps/shared/components/mail/pinnedSigners.d.ts +6 -0
  114. package/dist/apps/shared/components/mail/pinnedSigners.js +10 -1
  115. package/dist/apps/shared/components/mail/reading/conversationPrint.d.ts +2 -2
  116. package/dist/apps/shared/components/mail/reading/conversationPrint.js +3 -3
  117. package/dist/apps/shared/components/mail/reading/useMessageActions.js +4 -1
  118. package/dist/apps/shared/components/settings/KeyExportSetting.d.ts +13 -0
  119. package/dist/apps/shared/components/settings/KeyExportSetting.js +90 -0
  120. package/dist/apps/shared/components/settings/OpenPgpKeySetting.d.ts +13 -0
  121. package/dist/apps/shared/components/settings/OpenPgpKeySetting.js +143 -0
  122. package/dist/apps/shared/components/settings/PolicyLockedNotice.d.ts +11 -0
  123. package/dist/apps/shared/components/settings/PolicyLockedNotice.js +9 -0
  124. package/dist/apps/shared/components/settings/ZeroAccessSetting.d.ts +16 -0
  125. package/dist/apps/shared/components/settings/ZeroAccessSetting.js +80 -0
  126. package/dist/apps/shared/components/settings/ZeroAccessTypes.d.ts +29 -0
  127. package/dist/apps/shared/components/settings/ZeroAccessTypes.js +107 -0
  128. package/dist/apps/shared/components/settings/layout/SettingsShell.d.ts +3 -0
  129. package/dist/apps/shared/components/settings/layout/SettingsShell.js +3 -2
  130. package/dist/apps/shared/mail/decryptedMessages.d.ts +1 -1
  131. package/dist/apps/shared/mail/decryptedMessages.js +11 -3
  132. package/dist/apps/shared/mail/outbox/sendJob.d.ts +37 -4
  133. package/dist/apps/shared/mail/outbox/sendJob.js +287 -42
  134. package/dist/apps/shared/mail/outbox/sendOutcomes.d.ts +12 -0
  135. package/dist/apps/shared/mail/outbox/sendOutcomes.js +76 -20
  136. package/dist/apps/shared/mail/reportNotices.js +3 -1
  137. package/dist/apps/shared/mail/zeroAccessSource.d.ts +8 -0
  138. package/dist/apps/shared/mail/zeroAccessSource.js +26 -0
  139. package/dist/apps/shared/search/LocalIndexLifecycle.d.ts +2 -0
  140. package/dist/apps/shared/search/LocalIndexLifecycle.js +74 -24
  141. package/dist/apps/shared/search/localIndexBuilder.d.ts +9 -1
  142. package/dist/apps/shared/search/localIndexBuilder.js +50 -17
  143. package/dist/apps/shared/search/localIndexRpcClient.d.ts +5 -39
  144. package/dist/apps/shared/search/localIndexRpcClient.js +129 -11
  145. package/dist/apps/shared/search/localIndexSchema.d.ts +14 -2
  146. package/dist/apps/shared/search/localIndexSchema.js +18 -4
  147. package/dist/apps/shared/search/localIndexTransport.d.ts +6 -2
  148. package/dist/apps/shared/search/localIndexWorker.d.ts +11 -0
  149. package/dist/apps/shared/search/localIndexWorker.js +22 -15
  150. package/dist/apps/shared/search/searchTier2.js +5 -0
  151. package/dist/apps/shared/search/zeroAccessIndexSync.d.ts +102 -0
  152. package/dist/apps/shared/search/zeroAccessIndexSync.js +544 -0
  153. package/dist/apps/shared/search/zeroAccessSyncState.d.ts +20 -0
  154. package/dist/apps/shared/search/zeroAccessSyncState.js +65 -0
  155. package/dist/apps/shared/zeroAccess/ProtectedMark.d.ts +7 -0
  156. package/dist/apps/shared/zeroAccess/ProtectedMark.js +10 -0
  157. package/dist/apps/shared/zeroAccess/useKeysLocked.d.ts +6 -0
  158. package/dist/apps/shared/zeroAccess/useKeysLocked.js +20 -0
  159. package/dist/apps/shared/zeroAccess/useOpenedRecord.d.ts +18 -0
  160. package/dist/apps/shared/zeroAccess/useOpenedRecord.js +66 -0
  161. package/dist/apps/www/_shell.d.ts +1 -1
  162. package/dist/apps/www/_shell.js +2 -2
  163. package/dist/apps/www/calendar/index.js +88 -20
  164. package/dist/apps/www/contacts/index.js +64 -11
  165. package/dist/apps/www/index.js +19 -3
  166. package/dist/apps/www/settings/encryption/index.js +16 -4
  167. package/dist/apps/www/settings/privacy/index.js +47 -6
  168. package/dist/apps/www/tasks/index.js +21 -7
  169. package/dist/lib/admin/domainsApi.d.ts +1 -1
  170. package/dist/lib/admin/escrowAccessRequestsApi.d.ts +6 -0
  171. package/dist/lib/calendar/calendarApi.d.ts +52 -6
  172. package/dist/lib/calendar/calendarApi.js +110 -17
  173. package/dist/lib/calendar/calendarMutations.d.ts +20 -7
  174. package/dist/lib/calendar/calendarMutations.js +73 -14
  175. package/dist/lib/calendar/inviteApi.d.ts +17 -3
  176. package/dist/lib/calendar/inviteApi.js +86 -7
  177. package/dist/lib/calendar/protectedEvents.d.ts +31 -0
  178. package/dist/lib/calendar/protectedEvents.js +113 -0
  179. package/dist/lib/calendar/recurrence.d.ts +2 -0
  180. package/dist/lib/calendar/recurrence.js +16 -0
  181. package/dist/lib/calendar/sealedInvites.d.ts +9 -0
  182. package/dist/lib/calendar/sealedInvites.js +65 -0
  183. package/dist/lib/contacts/contactsApi.d.ts +29 -3
  184. package/dist/lib/contacts/contactsApi.js +23 -7
  185. package/dist/lib/contacts/useContactPhotoSrc.d.ts +5 -2
  186. package/dist/lib/contacts/useContactPhotoSrc.js +91 -11
  187. package/dist/lib/crypto/composeSecurity.d.ts +11 -3
  188. package/dist/lib/crypto/composeSecurity.js +13 -5
  189. package/dist/lib/crypto/keyExport.d.ts +54 -0
  190. package/dist/lib/crypto/keyExport.js +161 -0
  191. package/dist/lib/crypto/keyPairMatch.d.ts +9 -0
  192. package/dist/lib/crypto/keyPairMatch.js +65 -0
  193. package/dist/lib/crypto/keySession.d.ts +64 -3
  194. package/dist/lib/crypto/keySession.js +179 -12
  195. package/dist/lib/crypto/keyvaultApi.d.ts +129 -8
  196. package/dist/lib/crypto/keyvaultApi.js +45 -3
  197. package/dist/lib/crypto/meetingKeys.d.ts +25 -0
  198. package/dist/lib/crypto/meetingKeys.js +87 -0
  199. package/dist/lib/crypto/messageSecurity.d.ts +56 -3
  200. package/dist/lib/crypto/messageSecurity.js +201 -13
  201. package/dist/lib/crypto/mime.d.ts +5 -0
  202. package/dist/lib/crypto/mime.js +25 -0
  203. package/dist/lib/crypto/openPgpKey.d.ts +39 -0
  204. package/dist/lib/crypto/openPgpKey.js +89 -0
  205. package/dist/lib/crypto/openpgp.d.ts +47 -0
  206. package/dist/lib/crypto/openpgp.js +88 -0
  207. package/dist/lib/crypto/pgpMessage.d.ts +51 -0
  208. package/dist/lib/crypto/pgpMessage.js +271 -0
  209. package/dist/lib/crypto/sharedMailboxKeys.d.ts +62 -0
  210. package/dist/lib/crypto/sharedMailboxKeys.js +337 -0
  211. package/dist/lib/crypto/smimeMessage.d.ts +21 -0
  212. package/dist/lib/crypto/smimeMessage.js +11 -7
  213. package/dist/lib/crypto/zeroAccessKey.d.ts +32 -0
  214. package/dist/lib/crypto/zeroAccessKey.js +71 -0
  215. package/dist/lib/mail/conversationsApi.d.ts +6 -0
  216. package/dist/lib/mail/mailApi.d.ts +63 -2
  217. package/dist/lib/mail/mailApi.js +5 -1
  218. package/dist/lib/mail/mailboxImportApi.d.ts +10 -0
  219. package/dist/lib/mail/mailboxImportApi.js +15 -0
  220. package/dist/lib/search/zeroAccessIndexApi.d.ts +85 -0
  221. package/dist/lib/search/zeroAccessIndexApi.js +35 -0
  222. package/dist/lib/tasks/tasksApi.d.ts +11 -1
  223. package/dist/lib/tasks/tasksApi.js +10 -4
  224. package/dist/lib/util/clientPlatform.d.ts +14 -0
  225. package/dist/lib/util/clientPlatform.js +26 -0
  226. package/dist/lib/videoconf/protectedMeetings.d.ts +74 -0
  227. package/dist/lib/videoconf/protectedMeetings.js +181 -0
  228. package/dist/lib/videoconf/videoMeetingsApi.d.ts +25 -4
  229. package/dist/lib/videoconf/videoMeetingsApi.js +1 -1
  230. package/dist/lib/zeroAccess/sealedMoves.d.ts +41 -0
  231. package/dist/lib/zeroAccess/sealedMoves.js +63 -0
  232. package/dist/lib/zeroAccess/sealedRecords.d.ts +29 -0
  233. package/dist/lib/zeroAccess/sealedRecords.js +136 -0
  234. package/lib/admin/domainsApi.ts +1 -1
  235. package/lib/admin/escrowAccessRequestsApi.ts +6 -0
  236. package/lib/calendar/calendarApi.ts +143 -17
  237. package/lib/calendar/calendarMutations.ts +79 -12
  238. package/lib/calendar/inviteApi.ts +101 -8
  239. package/lib/calendar/protectedEvents.ts +143 -0
  240. package/lib/calendar/recurrence.ts +17 -0
  241. package/lib/calendar/sealedInvites.ts +73 -0
  242. package/lib/contacts/contactsApi.ts +43 -17
  243. package/lib/contacts/useContactPhotoSrc.ts +103 -13
  244. package/lib/crypto/composeSecurity.ts +20 -5
  245. package/lib/crypto/keyExport.ts +229 -0
  246. package/lib/crypto/keyPairMatch.ts +69 -0
  247. package/lib/crypto/keySession.ts +216 -12
  248. package/lib/crypto/keyvaultApi.ts +174 -10
  249. package/lib/crypto/meetingKeys.ts +118 -0
  250. package/lib/crypto/messageSecurity.ts +284 -16
  251. package/lib/crypto/mime.ts +26 -0
  252. package/lib/crypto/openPgpKey.ts +118 -0
  253. package/lib/crypto/openpgp.ts +115 -0
  254. package/lib/crypto/pgpMessage.ts +336 -0
  255. package/lib/crypto/sharedMailboxKeys.ts +402 -0
  256. package/lib/crypto/smimeMessage.ts +11 -7
  257. package/lib/crypto/zeroAccessKey.ts +102 -0
  258. package/lib/mail/conversationsApi.ts +3 -0
  259. package/lib/mail/mailApi.ts +60 -3
  260. package/lib/mail/mailboxImportApi.ts +24 -0
  261. package/lib/search/zeroAccessIndexApi.ts +123 -0
  262. package/lib/tasks/tasksApi.ts +19 -5
  263. package/lib/util/clientPlatform.ts +50 -0
  264. package/lib/videoconf/protectedMeetings.ts +221 -0
  265. package/lib/videoconf/videoMeetingsApi.ts +15 -4
  266. package/lib/zeroAccess/sealedMoves.ts +79 -0
  267. package/lib/zeroAccess/sealedRecords.ts +153 -0
  268. 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 { allOccurrences, initialMatchIndex, occurrencesInRange, searchOccurrences, searchTerms, stepSequenceIndex } from "../../../lib/calendar/eventSearch.js";
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, { CalendarShellProps, useCalendarShell } from "../../shared/components/calendar/layout/CalendarShell.js";
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 { CALENDAR_VIEWS, CalendarView, getStoredCalendarView, isCalendarView, storeCalendarView } from "../../shared/components/calendar/calendarView.js";
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> = { list: "List", month: "Month", week: "Week", workWeek: "Work Week", day: "Day", split: "Split" };
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({ view, current, onSelect }: { view: ViewType; current: ViewType; onSelect: (view: ViewType) => void }) {
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 } = useCalendarShell();
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.map((f) => f.uid).sort().join(",");
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).then(
321
- (fresh) => {
322
- if (checkedFolderUidsRef.current.has(fresh.folderUid)) {
323
- setEvents((previous) =>
324
- previous.some((existing) => existing.uid === fresh.uid)
325
- ? previous.map((existing) => (existing.uid === fresh.uid ? fresh : existing))
326
- : [...previous, fresh],
327
- );
328
- }
329
- },
330
- (err: unknown) => {
331
- if (err instanceof ApiRequestError && err.status === 404) {
332
- setEvents((previous) => previous.filter((existing) => existing.uid !== uid));
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(events, query) : [];
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
- }, [events, query, searching, view, dayOfList]);
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(() => (view === "list" || modal?.occurrence ? allOccurrences(events) : []), [events, view, !!modal?.occurrence]);
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 ? occurrencesInRange(matches, rangeStart, rangeEnd) : expandAllOccurrences(events, rangeStart, rangeEnd);
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(sequence, stepFrom?.occurrenceKey ?? activeKey, stepFrom ? new Date(stepFrom.startDate) : undefined, direction, searching);
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(matches[view === "list" ? initialMatchIndex(matches, from, rangeEnd, from) : initialMatchIndex(matches, rangeStart, rangeEnd, from)]);
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 => swipe.ref.current?.querySelector<HTMLElement>("[data-calendar-scroller]") ?? 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.find((el) => el.dataset.occurrenceKey === activeKey)?.scrollIntoView({ block: "nearest", inline: "nearest" });
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(start?: Date, end?: Date, targetFolderUid?: string, anchor?: EventAnchor, initialAllDay?: boolean) {
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(event, new Date(from.getTime() - 86_400_000), new Date(from.getTime() + 86_400_000));
564
- const match = candidates.find((occurrence) => new Date(occurrence.startDate).getTime() === from.getTime()) ?? candidates[0];
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
- notifyApiError(err, action.type === "move" ? "Couldn't move the event" : "Couldn't resize the event");
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
- : view === "week" || view === "workWeek"
629
- ? `${format(rangeStart, "MMM d")} – ${format(rangeEnd, "MMM d, yyyy")}`
630
- : format(viewDate, "EEEE, MMMM d, yyyy");
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((mc) => mc.calendarFolders.length > 0 && writableMailboxes.some((mb) => mb.uid === mc.mailbox.uid))
642
- .map((mc) => ({ mailbox: mc.mailbox, calendars: mc.calendarFolders.map((f) => ({ uid: f.uid, name: f.name })) })),
643
- [mailboxCalendars, writableMailboxes],
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">{sidebarContent}</div>
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 type="button" onClick={(e) => openNewEvent(undefined, undefined, undefined, anchorOf(e.currentTarget, "below"))} className="!w-auto shrink-0" {...newEventHint}>
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 type="button" onClick={() => shiftView(-1)} aria-label="Previous" {...previousHint} className="w-7 h-7 text-sm rounded-sm hover:bg-surface-alt">
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
  &lsaquo;
691
825
  </button>
692
- <button type="button" onClick={goToday} {...todayHint} className="px-2 h-7 text-sm rounded-sm hover:bg-surface-alt">
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 type="button" onClick={() => shiftView(1)} aria-label="Next" {...nextHint} className="w-7 h-7 text-sm rounded-sm hover:bg-surface-alt">
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
  &rsaquo;
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 ref={swipe.ref} className="flex-1 min-w-0 flex flex-col min-h-0 overflow-hidden" {...swipe.handlers} style={swipe.style}>
726
- <div data-swipe-phase={swipe.phase} className="flex-1 min-w-0 flex flex-col min-h-0" style={swipe.contentStyle}>
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&hellip;</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) => openNewEvent(start, end, undefined, anchor, true)}
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) => openNewEvent(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) => openNewEvent(start, end, undefined, 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.filter((f) => f.mailboxUid === modalMailbox.uid).map((f) => ({ uid: f.uid, name: f.name }))}
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 && <FloatingActionButton label="New event" icon={HiOutlinePlus} onClick={() => openNewEvent()} />}
981
+ {isMobile && mailboxUid && folderUid && !modal && (
982
+ <FloatingActionButton label="New event" icon={HiOutlinePlus} onClick={() => openNewEvent()} />
983
+ )}
820
984
  </div>
821
985
  </div>
822
986
  );