@rapidmx/web-client 0.14.1 → 0.16.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 (314) hide show
  1. package/README.md +373 -373
  2. package/apps/admin/branding/index.tsx +39 -39
  3. package/apps/admin/data-requests/index.tsx +482 -480
  4. package/apps/admin/domains/[uid].tsx +164 -163
  5. package/apps/admin/escrow-scopes/[uid].tsx +348 -348
  6. package/apps/admin/index.tsx +127 -124
  7. package/apps/admin/mailboxes/[uid].tsx +269 -224
  8. package/apps/admin/mailboxes/new/index.tsx +28 -28
  9. package/apps/admin/plugins/index.tsx +15 -15
  10. package/apps/admin/retention-policy/index.tsx +39 -39
  11. package/apps/admin/signing-certificates/index.tsx +343 -343
  12. package/apps/escrow/audit-log/index.tsx +196 -196
  13. package/apps/escrow/matters/[uid].tsx +621 -621
  14. package/apps/shared/appearance/AppearanceForm.tsx +9 -1
  15. package/apps/shared/auth/adminAccess.ts +99 -99
  16. package/apps/shared/calendar/bookingPlugin.ts +100 -0
  17. package/apps/shared/calendar/calendarLiveUpdates.ts +27 -0
  18. package/apps/shared/components/admin/layout/AdminShell.tsx +378 -346
  19. package/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.tsx +238 -0
  20. package/apps/shared/components/admin/mailboxes/EscrowScopeCard.tsx +152 -152
  21. package/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.tsx +194 -0
  22. package/apps/shared/components/admin/settings/BrandingForm.tsx +423 -423
  23. package/apps/shared/components/admin/settings/EncryptionPolicyForm.tsx +119 -119
  24. package/apps/shared/components/admin/settings/MailboxCreateForm.tsx +53 -4
  25. package/apps/shared/components/admin/settings/MailboxPolicyForm.tsx +198 -198
  26. package/apps/shared/components/admin/settings/PluginsManager.tsx +64 -10
  27. package/apps/shared/components/admin/settings/RetentionPolicyForm.tsx +182 -182
  28. package/apps/shared/components/admin/setup/EscrowSetupStep.tsx +288 -288
  29. package/apps/shared/components/admin/setup/SetupWizard.tsx +444 -444
  30. package/apps/shared/components/admin/usePagedList.tsx +129 -129
  31. package/apps/shared/components/calendar/AppointmentQuickForm.tsx +327 -0
  32. package/apps/shared/components/calendar/DescriptionEditor.tsx +274 -0
  33. package/apps/shared/components/calendar/EventDescriptionView.tsx +70 -0
  34. package/apps/shared/components/calendar/EventDetails.tsx +401 -0
  35. package/apps/shared/components/calendar/EventEditor.tsx +635 -0
  36. package/apps/shared/components/calendar/EventExpandedForm.tsx +210 -0
  37. package/apps/shared/components/calendar/EventFormParts.tsx +591 -0
  38. package/apps/shared/components/calendar/EventModal.tsx +206 -946
  39. package/apps/shared/components/calendar/EventQuickForm.tsx +116 -0
  40. package/apps/shared/components/calendar/EventShell.tsx +202 -0
  41. package/apps/shared/components/calendar/FindATime.tsx +379 -0
  42. package/apps/shared/components/calendar/GuestInput.tsx +100 -0
  43. package/apps/shared/components/calendar/LazyDescriptionEditor.tsx +70 -0
  44. package/apps/shared/components/calendar/MonthView.tsx +185 -173
  45. package/apps/shared/components/calendar/QuickCreateFaces.tsx +87 -0
  46. package/apps/shared/components/calendar/QuickCreateTabs.tsx +81 -0
  47. package/apps/shared/components/calendar/QuickFaceFrame.tsx +81 -0
  48. package/apps/shared/components/calendar/RecurrenceEditor.tsx +227 -222
  49. package/apps/shared/components/calendar/RequestChangeForm.tsx +240 -0
  50. package/apps/shared/components/calendar/SplitDayView.tsx +144 -143
  51. package/apps/shared/components/calendar/TaskQuickForm.tsx +289 -0
  52. package/apps/shared/components/calendar/TimeGridView.tsx +246 -244
  53. package/apps/shared/components/calendar/allDay.ts +124 -124
  54. package/apps/shared/components/calendar/eventDialogFields.ts +86 -0
  55. package/apps/shared/components/calendar/eventForm.ts +108 -0
  56. package/apps/shared/components/calendar/eventFormat.ts +210 -0
  57. package/apps/shared/components/calendar/findTimeGrid.ts +90 -0
  58. package/apps/shared/components/calendar/layout/CalendarShell.tsx +201 -200
  59. package/apps/shared/components/calendar/swipeNavigation.ts +14 -0
  60. package/apps/shared/components/contacts/ContactForm.tsx +383 -383
  61. package/apps/shared/components/contacts/ContactsSidebar.tsx +1 -1
  62. package/apps/shared/components/contacts/ContactsToolbar.tsx +103 -98
  63. package/apps/shared/components/contacts/layout/ContactsShell.tsx +217 -216
  64. package/apps/shared/components/escrow/layout/EscrowShell.tsx +155 -155
  65. package/apps/shared/components/layout/AppShell.tsx +480 -480
  66. package/apps/shared/components/layout/FloatingActionButton.tsx +31 -0
  67. package/apps/shared/components/layout/KeyEnrollmentGate.tsx +398 -398
  68. package/apps/shared/components/layout/MailboxProvisioning.tsx +168 -168
  69. package/apps/shared/components/layout/ResponsiveToolbar.tsx +315 -315
  70. package/apps/shared/components/layout/ThemeSwitch.tsx +84 -84
  71. package/apps/shared/components/layout/UserMenu.tsx +439 -372
  72. package/apps/shared/components/mail/ConversationList.tsx +323 -271
  73. package/apps/shared/components/mail/ConversationThreadPane.tsx +130 -5
  74. package/apps/shared/components/mail/InviteCard.tsx +387 -0
  75. package/apps/shared/components/mail/MailSelectionBar.tsx +236 -227
  76. package/apps/shared/components/mail/MessageDetailPane.tsx +1559 -1537
  77. package/apps/shared/components/mail/SwipeRow.tsx +120 -0
  78. package/apps/shared/components/mail/compose/ComposeContext.tsx +312 -312
  79. package/apps/shared/components/mail/compose/ComposeToolbar.tsx +422 -422
  80. package/apps/shared/components/mail/compose/ComposeWindow.tsx +1681 -1673
  81. package/apps/shared/components/mail/compose/RecipientInput.tsx +54 -11
  82. package/apps/shared/components/mail/compose/RichTextEditor.tsx +147 -147
  83. package/apps/shared/components/mail/compose/composeFlushRegistry.ts +60 -60
  84. package/apps/shared/components/mail/compose/quotedBody.ts +161 -161
  85. package/apps/shared/components/mail/invite/InviteRowChip.tsx +104 -0
  86. package/apps/shared/components/mail/invite/InviteRsvpPopover.tsx +271 -0
  87. package/apps/shared/components/mail/invite/InviteTimeline.tsx +200 -0
  88. package/apps/shared/components/mail/invite/ProposeTimeForm.tsx +109 -0
  89. package/apps/shared/components/mail/invite/inviteFormat.ts +110 -0
  90. package/apps/shared/components/mail/invite/inviteStore.ts +114 -0
  91. package/apps/shared/components/mail/layout/FolderBadgeChip.tsx +21 -0
  92. package/apps/shared/components/mail/layout/MailShell.tsx +546 -490
  93. package/apps/shared/components/mail/layout/SidebarSection.tsx +66 -0
  94. package/apps/shared/components/mail/reading/PendingMessageCard.tsx +68 -0
  95. package/apps/shared/components/mail/verificationSeals.ts +125 -125
  96. package/apps/shared/components/rules/RuleBuilder.tsx +311 -311
  97. package/apps/shared/components/settings/SigningCertificateCard.tsx +344 -344
  98. package/apps/shared/components/settings/layout/SettingsShell.tsx +255 -253
  99. package/apps/shared/components/tasks/TasksSidebar.tsx +1 -1
  100. package/apps/shared/components/tasks/layout/TasksShell.tsx +218 -217
  101. package/apps/shared/gestures/useEnterSlide.ts +54 -0
  102. package/apps/shared/gestures/useSwipe.ts +114 -0
  103. package/apps/shared/gestures/useSwipeSlide.ts +113 -0
  104. package/apps/shared/gestures/useWheelPaging.ts +107 -0
  105. package/apps/shared/keyboard/GlobalShortcuts.tsx +51 -51
  106. package/apps/shared/keyboard/ShortcutProvider.tsx +62 -62
  107. package/apps/shared/keyboard/ShortcutsDialog.tsx +84 -84
  108. package/apps/shared/keyboard/dispatch.ts +124 -124
  109. package/apps/shared/keyboard/format.ts +89 -89
  110. package/apps/shared/keyboard/keymap.ts +114 -114
  111. package/apps/shared/keyboard/registry.ts +65 -65
  112. package/apps/shared/keyboard/targets.ts +79 -79
  113. package/apps/shared/mail/folderCounts.ts +17 -0
  114. package/apps/shared/mail/folderTree.ts +143 -143
  115. package/apps/shared/mail/listAllPages.ts +39 -39
  116. package/apps/shared/mail/newMailNotifications.ts +3 -15
  117. package/apps/shared/mail/outbox/outgoingReplies.ts +192 -0
  118. package/apps/shared/mail/outbox/sendJob.ts +19 -1
  119. package/apps/shared/mail/outbox/sendOutcomes.ts +13 -4
  120. package/apps/shared/mail/primaryMailbox.ts +71 -0
  121. package/apps/shared/mail/useCollapsedSections.ts +146 -0
  122. package/apps/shared/mail/useMailConnection.ts +205 -203
  123. package/apps/shared/mail/useMailLiveUpdates.ts +277 -277
  124. package/apps/shared/mail/useMarkMessageRead.ts +47 -47
  125. package/apps/shared/mail/useNewMailNotifications.ts +2 -2
  126. package/apps/shared/navigation/AppRouter.tsx +300 -300
  127. package/apps/shared/navigation/routerContext.tsx +83 -83
  128. package/apps/shared/notifications/preferences.ts +36 -0
  129. package/apps/shared/notifications/store.ts +9 -0
  130. package/apps/shared/search/LocalIndexLifecycle.tsx +114 -114
  131. package/apps/shared/search/crossMailboxSearch.ts +169 -0
  132. package/apps/shared/search/localIndexBuilder.ts +481 -481
  133. package/apps/shared/signing/enrollmentStorage.ts +33 -33
  134. package/apps/shared/signing/enrollmentTracker.ts +385 -385
  135. package/apps/shared/signing/enrollmentView.ts +251 -251
  136. package/apps/shared/signing/useNow.ts +19 -19
  137. package/apps/shared/signing/useSigningEnrollmentWatcher.ts +90 -90
  138. package/apps/shared/styles/app.css +396 -386
  139. package/apps/www/_routes.ts +1 -0
  140. package/apps/www/calendar/index.tsx +578 -469
  141. package/apps/www/contacts/[uid].tsx +109 -109
  142. package/apps/www/contacts/index.tsx +6 -0
  143. package/apps/www/index.tsx +2847 -2332
  144. package/apps/www/messages/[uid].tsx +135 -108
  145. package/apps/www/settings/auto-reply/index.tsx +133 -133
  146. package/apps/www/settings/encryption/index.tsx +1287 -1287
  147. package/apps/www/settings/filters/[uid].tsx +176 -176
  148. package/apps/www/settings/filters/index.tsx +102 -102
  149. package/apps/www/settings/filters/new/index.tsx +140 -140
  150. package/apps/www/settings/labels/index.tsx +204 -204
  151. package/apps/www/settings/privacy/index.tsx +492 -492
  152. package/apps/www/settings/profile/index.tsx +248 -0
  153. package/apps/www/settings/read-receipts/index.tsx +147 -147
  154. package/apps/www/settings/sharing/index.tsx +256 -256
  155. package/apps/www/settings/signatures/[uid].tsx +172 -172
  156. package/apps/www/settings/signatures/index.tsx +88 -88
  157. package/apps/www/settings/signatures/new/index.tsx +135 -135
  158. package/apps/www/tasks/index.tsx +649 -649
  159. package/dist/apps/admin/data-requests/index.js +1 -1
  160. package/dist/apps/admin/domains/[uid].js +4 -2
  161. package/dist/apps/admin/index.js +2 -1
  162. package/dist/apps/admin/mailboxes/[uid].js +12 -2
  163. package/dist/apps/shared/appearance/AppearanceForm.js +9 -1
  164. package/dist/apps/shared/calendar/bookingPlugin.d.ts +50 -0
  165. package/dist/apps/shared/calendar/bookingPlugin.js +57 -0
  166. package/dist/apps/shared/calendar/calendarLiveUpdates.d.ts +11 -0
  167. package/dist/apps/shared/calendar/calendarLiveUpdates.js +23 -0
  168. package/dist/apps/shared/components/admin/layout/AdminShell.d.ts +1 -1
  169. package/dist/apps/shared/components/admin/layout/AdminShell.js +7 -3
  170. package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.d.ts +35 -0
  171. package/dist/apps/shared/components/admin/mailboxes/EraseLeftoverDataDialog.js +115 -0
  172. package/dist/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.d.ts +16 -0
  173. package/dist/apps/shared/components/admin/mailboxes/LeftoverMailboxesSection.js +92 -0
  174. package/dist/apps/shared/components/admin/settings/BrandingForm.js +3 -3
  175. package/dist/apps/shared/components/admin/settings/MailboxCreateForm.js +28 -4
  176. package/dist/apps/shared/components/admin/settings/PluginsManager.js +40 -6
  177. package/dist/apps/shared/components/calendar/AppointmentQuickForm.d.ts +47 -0
  178. package/dist/apps/shared/components/calendar/AppointmentQuickForm.js +135 -0
  179. package/dist/apps/shared/components/calendar/DescriptionEditor.d.ts +26 -0
  180. package/dist/apps/shared/components/calendar/DescriptionEditor.js +192 -0
  181. package/dist/apps/shared/components/calendar/EventDescriptionView.d.ts +14 -0
  182. package/dist/apps/shared/components/calendar/EventDescriptionView.js +39 -0
  183. package/dist/apps/shared/components/calendar/EventDetails.d.ts +33 -0
  184. package/dist/apps/shared/components/calendar/EventDetails.js +137 -0
  185. package/dist/apps/shared/components/calendar/EventEditor.d.ts +59 -0
  186. package/dist/apps/shared/components/calendar/EventEditor.js +544 -0
  187. package/dist/apps/shared/components/calendar/EventExpandedForm.d.ts +14 -0
  188. package/dist/apps/shared/components/calendar/EventExpandedForm.js +44 -0
  189. package/dist/apps/shared/components/calendar/EventFormParts.d.ts +70 -0
  190. package/dist/apps/shared/components/calendar/EventFormParts.js +191 -0
  191. package/dist/apps/shared/components/calendar/EventModal.d.ts +26 -13
  192. package/dist/apps/shared/components/calendar/EventModal.js +57 -459
  193. package/dist/apps/shared/components/calendar/EventQuickForm.d.ts +18 -0
  194. package/dist/apps/shared/components/calendar/EventQuickForm.js +25 -0
  195. package/dist/apps/shared/components/calendar/EventShell.d.ts +64 -0
  196. package/dist/apps/shared/components/calendar/EventShell.js +134 -0
  197. package/dist/apps/shared/components/calendar/FindATime.d.ts +18 -0
  198. package/dist/apps/shared/components/calendar/FindATime.js +190 -0
  199. package/dist/apps/shared/components/calendar/GuestInput.d.ts +45 -0
  200. package/dist/apps/shared/components/calendar/GuestInput.js +30 -0
  201. package/dist/apps/shared/components/calendar/LazyDescriptionEditor.d.ts +8 -0
  202. package/dist/apps/shared/components/calendar/LazyDescriptionEditor.js +44 -0
  203. package/dist/apps/shared/components/calendar/MonthView.d.ts +5 -1
  204. package/dist/apps/shared/components/calendar/MonthView.js +11 -5
  205. package/dist/apps/shared/components/calendar/QuickCreateFaces.d.ts +30 -0
  206. package/dist/apps/shared/components/calendar/QuickCreateFaces.js +44 -0
  207. package/dist/apps/shared/components/calendar/QuickCreateTabs.d.ts +24 -0
  208. package/dist/apps/shared/components/calendar/QuickCreateTabs.js +46 -0
  209. package/dist/apps/shared/components/calendar/QuickFaceFrame.d.ts +25 -0
  210. package/dist/apps/shared/components/calendar/QuickFaceFrame.js +19 -0
  211. package/dist/apps/shared/components/calendar/RecurrenceEditor.d.ts +4 -1
  212. package/dist/apps/shared/components/calendar/RecurrenceEditor.js +2 -2
  213. package/dist/apps/shared/components/calendar/RequestChangeForm.d.ts +36 -0
  214. package/dist/apps/shared/components/calendar/RequestChangeForm.js +127 -0
  215. package/dist/apps/shared/components/calendar/SplitDayView.d.ts +3 -2
  216. package/dist/apps/shared/components/calendar/SplitDayView.js +3 -2
  217. package/dist/apps/shared/components/calendar/TaskQuickForm.d.ts +40 -0
  218. package/dist/apps/shared/components/calendar/TaskQuickForm.js +101 -0
  219. package/dist/apps/shared/components/calendar/TimeGridView.d.ts +4 -2
  220. package/dist/apps/shared/components/calendar/TimeGridView.js +3 -2
  221. package/dist/apps/shared/components/calendar/eventDialogFields.d.ts +28 -0
  222. package/dist/apps/shared/components/calendar/eventDialogFields.js +59 -0
  223. package/dist/apps/shared/components/calendar/eventForm.d.ts +98 -0
  224. package/dist/apps/shared/components/calendar/eventForm.js +1 -0
  225. package/dist/apps/shared/components/calendar/eventFormat.d.ts +80 -0
  226. package/dist/apps/shared/components/calendar/eventFormat.js +190 -0
  227. package/dist/apps/shared/components/calendar/findTimeGrid.d.ts +30 -0
  228. package/dist/apps/shared/components/calendar/findTimeGrid.js +83 -0
  229. package/dist/apps/shared/components/calendar/layout/CalendarShell.js +3 -2
  230. package/dist/apps/shared/components/calendar/swipeNavigation.d.ts +9 -0
  231. package/dist/apps/shared/components/calendar/swipeNavigation.js +8 -0
  232. package/dist/apps/shared/components/contacts/ContactsSidebar.js +1 -1
  233. package/dist/apps/shared/components/contacts/ContactsToolbar.d.ts +3 -1
  234. package/dist/apps/shared/components/contacts/ContactsToolbar.js +4 -2
  235. package/dist/apps/shared/components/contacts/layout/ContactsShell.js +4 -3
  236. package/dist/apps/shared/components/layout/FloatingActionButton.d.ts +13 -0
  237. package/dist/apps/shared/components/layout/FloatingActionButton.js +9 -0
  238. package/dist/apps/shared/components/layout/UserMenu.d.ts +14 -9
  239. package/dist/apps/shared/components/layout/UserMenu.js +74 -26
  240. package/dist/apps/shared/components/mail/ConversationList.d.ts +12 -1
  241. package/dist/apps/shared/components/mail/ConversationList.js +21 -4
  242. package/dist/apps/shared/components/mail/ConversationThreadPane.d.ts +4 -1
  243. package/dist/apps/shared/components/mail/ConversationThreadPane.js +127 -22
  244. package/dist/apps/shared/components/mail/InviteCard.d.ts +20 -0
  245. package/dist/apps/shared/components/mail/InviteCard.js +150 -0
  246. package/dist/apps/shared/components/mail/MailSelectionBar.d.ts +6 -1
  247. package/dist/apps/shared/components/mail/MailSelectionBar.js +3 -3
  248. package/dist/apps/shared/components/mail/MessageDetailPane.js +13 -2
  249. package/dist/apps/shared/components/mail/SwipeRow.d.ts +22 -0
  250. package/dist/apps/shared/components/mail/SwipeRow.js +71 -0
  251. package/dist/apps/shared/components/mail/compose/ComposeWindow.js +16 -7
  252. package/dist/apps/shared/components/mail/compose/RecipientInput.d.ts +21 -1
  253. package/dist/apps/shared/components/mail/compose/RecipientInput.js +18 -10
  254. package/dist/apps/shared/components/mail/invite/InviteRowChip.d.ts +23 -0
  255. package/dist/apps/shared/components/mail/invite/InviteRowChip.js +46 -0
  256. package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.d.ts +20 -0
  257. package/dist/apps/shared/components/mail/invite/InviteRsvpPopover.js +141 -0
  258. package/dist/apps/shared/components/mail/invite/InviteTimeline.d.ts +27 -0
  259. package/dist/apps/shared/components/mail/invite/InviteTimeline.js +120 -0
  260. package/dist/apps/shared/components/mail/invite/ProposeTimeForm.d.ts +17 -0
  261. package/dist/apps/shared/components/mail/invite/ProposeTimeForm.js +45 -0
  262. package/dist/apps/shared/components/mail/invite/inviteFormat.d.ts +28 -0
  263. package/dist/apps/shared/components/mail/invite/inviteFormat.js +94 -0
  264. package/dist/apps/shared/components/mail/invite/inviteStore.d.ts +28 -0
  265. package/dist/apps/shared/components/mail/invite/inviteStore.js +95 -0
  266. package/dist/apps/shared/components/mail/layout/FolderBadgeChip.d.ts +6 -0
  267. package/dist/apps/shared/components/mail/layout/FolderBadgeChip.js +9 -0
  268. package/dist/apps/shared/components/mail/layout/MailShell.d.ts +10 -0
  269. package/dist/apps/shared/components/mail/layout/MailShell.js +76 -46
  270. package/dist/apps/shared/components/mail/layout/SidebarSection.d.ts +23 -0
  271. package/dist/apps/shared/components/mail/layout/SidebarSection.js +16 -0
  272. package/dist/apps/shared/components/mail/reading/PendingMessageCard.d.ts +14 -0
  273. package/dist/apps/shared/components/mail/reading/PendingMessageCard.js +16 -0
  274. package/dist/apps/shared/components/settings/layout/SettingsShell.js +7 -5
  275. package/dist/apps/shared/components/tasks/TasksSidebar.js +1 -1
  276. package/dist/apps/shared/components/tasks/layout/TasksShell.js +4 -3
  277. package/dist/apps/shared/gestures/useEnterSlide.d.ts +14 -0
  278. package/dist/apps/shared/gestures/useEnterSlide.js +47 -0
  279. package/dist/apps/shared/gestures/useSwipe.d.ts +45 -0
  280. package/dist/apps/shared/gestures/useSwipe.js +90 -0
  281. package/dist/apps/shared/gestures/useSwipeSlide.d.ts +40 -0
  282. package/dist/apps/shared/gestures/useSwipeSlide.js +95 -0
  283. package/dist/apps/shared/gestures/useWheelPaging.d.ts +32 -0
  284. package/dist/apps/shared/gestures/useWheelPaging.js +85 -0
  285. package/dist/apps/shared/mail/folderCounts.d.ts +10 -0
  286. package/dist/apps/shared/mail/folderCounts.js +12 -0
  287. package/dist/apps/shared/mail/newMailNotifications.d.ts +3 -8
  288. package/dist/apps/shared/mail/newMailNotifications.js +3 -12
  289. package/dist/apps/shared/mail/outbox/outgoingReplies.d.ts +80 -0
  290. package/dist/apps/shared/mail/outbox/outgoingReplies.js +131 -0
  291. package/dist/apps/shared/mail/outbox/sendJob.d.ts +5 -1
  292. package/dist/apps/shared/mail/outbox/sendJob.js +14 -1
  293. package/dist/apps/shared/mail/outbox/sendOutcomes.js +13 -4
  294. package/dist/apps/shared/mail/primaryMailbox.d.ts +29 -0
  295. package/dist/apps/shared/mail/primaryMailbox.js +61 -0
  296. package/dist/apps/shared/mail/useCollapsedSections.d.ts +32 -0
  297. package/dist/apps/shared/mail/useCollapsedSections.js +110 -0
  298. package/dist/apps/shared/mail/useMailConnection.js +3 -1
  299. package/dist/apps/shared/mail/useNewMailNotifications.js +3 -2
  300. package/dist/apps/shared/notifications/preferences.d.ts +13 -0
  301. package/dist/apps/shared/notifications/preferences.js +36 -0
  302. package/dist/apps/shared/notifications/store.d.ts +1 -0
  303. package/dist/apps/shared/notifications/store.js +7 -23
  304. package/dist/apps/shared/search/crossMailboxSearch.d.ts +72 -0
  305. package/dist/apps/shared/search/crossMailboxSearch.js +136 -0
  306. package/dist/apps/shared/styles/app.css +396 -386
  307. package/dist/apps/www/_routes.js +1 -0
  308. package/dist/apps/www/calendar/index.js +78 -7
  309. package/dist/apps/www/contacts/index.js +3 -1
  310. package/dist/apps/www/index.js +548 -210
  311. package/dist/apps/www/messages/[uid].js +13 -5
  312. package/dist/apps/www/settings/profile/index.d.ts +4 -0
  313. package/dist/apps/www/settings/profile/index.js +124 -0
  314. package/package.json +2 -2
@@ -0,0 +1,110 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ import type { Attachment } from "@rapidmx/react-shared/mail/mailApi.js";
6
+ import type { InviteResponse, MessageInvite } from "@rapidmx/react-shared/calendar/inviteApi.js";
7
+ import { APP_HREFS } from "../../../navigation/appHrefs.js";
8
+
9
+ /** Whether an attachment is a calendar file - what tells the pane a message may carry an invitation worth asking the server about. By type
10
+ * or by name, since mail clients disagree about which one they set (`text/calendar`, `application/ics`, or a bare `.ics` as octet-stream). */
11
+ export function isCalendarAttachment(attachment: Pick<Attachment, "filename" | "mimeType">): boolean {
12
+ const type = (attachment.mimeType ?? "").split(";")[0].trim().toLowerCase();
13
+ return type === "text/calendar" || type === "application/ics" || (attachment.filename ?? "").trim().toLowerCase().endsWith(".ics");
14
+ }
15
+
16
+ const DAY_FORMAT: Intl.DateTimeFormatOptions = { weekday: "short", year: "numeric", month: "short", day: "numeric" };
17
+ const CLOCK_FORMAT: Intl.DateTimeFormatOptions = { hour: "numeric", minute: "2-digit" };
18
+
19
+ /** `zone` if the browser knows it, else UTC - an all-day date is a calendar day, and needs a fixed zone to stay the same day for every reader. */
20
+ export function allDayZone(zone: string | undefined): string {
21
+ try {
22
+ new Intl.DateTimeFormat(undefined, { timeZone: zone });
23
+ return zone ?? "UTC";
24
+ } catch {
25
+ return "UTC";
26
+ }
27
+ }
28
+
29
+ /** The instant an ISO string names, or `undefined` when it is missing or unparseable. */
30
+ export function validDate(iso: string | undefined): Date | undefined {
31
+ const date = iso ? new Date(iso) : undefined;
32
+ return date && !isNaN(date.getTime()) ? date : undefined;
33
+ }
34
+
35
+ /**
36
+ * When the meeting is, in the reader's own locale and time zone: one date and a time range for a same-day event, both ends in full for
37
+ * one that spans days, and dates only for an all-day event (drawn in the organizer's zone, since a calendar day is not an instant). `undefined`
38
+ * when the invitation names no usable start. A missing or unusable end shows the start alone.
39
+ */
40
+ export function formatInviteWhen(invite: Pick<MessageInvite, "startDate" | "endDate" | "allDay" | "timezone">): string | undefined {
41
+ const start = validDate(invite.startDate);
42
+ if (!start) {
43
+ return undefined;
44
+ }
45
+ const parsedEnd = validDate(invite.endDate);
46
+ const end = parsedEnd && parsedEnd > start ? parsedEnd : undefined;
47
+ if (invite.allDay) {
48
+ const day = new Intl.DateTimeFormat(undefined, { ...DAY_FORMAT, timeZone: allDayZone(invite.timezone) });
49
+ const first = day.format(start);
50
+ // An all-day event's end is the midnight after its last day (iCalendar's DTEND is exclusive), so the last day is a moment before it.
51
+ const last = end ? day.format(new Date(end.getTime() - 1)) : first;
52
+ return last === first ? first : `${first} - ${last}`;
53
+ }
54
+ const date = new Intl.DateTimeFormat(undefined, DAY_FORMAT);
55
+ const time = new Intl.DateTimeFormat(undefined, CLOCK_FORMAT);
56
+ // The zone is named once, after the last time shown: the times are the reader's own, not the organizer's.
57
+ const timeAndZone = new Intl.DateTimeFormat(undefined, { ...CLOCK_FORMAT, timeZoneName: "short" });
58
+ const startDay = date.format(start);
59
+ if (!end) {
60
+ return `${startDay}, ${timeAndZone.format(start)}`;
61
+ }
62
+ return startDay === date.format(end)
63
+ ? `${startDay}, ${time.format(start)} - ${timeAndZone.format(end)}`
64
+ : `${startDay}, ${time.format(start)} - ${date.format(end)}, ${timeAndZone.format(end)}`;
65
+ }
66
+
67
+ /** The meeting's start the way a list row writes it - `Thu 9/24/2026 1:00 PM` (dates only for an all-day event), in the reader's zone. */
68
+ export function formatRowStart(invite: Pick<MessageInvite, "startDate" | "allDay" | "timezone">): string | undefined {
69
+ const start = validDate(invite.startDate);
70
+ if (!start) {
71
+ return undefined;
72
+ }
73
+ const zone = invite.allDay ? allDayZone(invite.timezone) : undefined;
74
+ const weekday = new Intl.DateTimeFormat(undefined, { weekday: "short", timeZone: zone }).format(start);
75
+ const date = new Intl.DateTimeFormat(undefined, { year: "numeric", month: "numeric", day: "numeric", timeZone: zone }).format(start);
76
+ return invite.allDay ? `${weekday} ${date}` : `${weekday} ${date} ${new Intl.DateTimeFormat(undefined, CLOCK_FORMAT).format(start)}`;
77
+ }
78
+
79
+ /** `YYYY-MM-DD` of an instant in the reader's zone, or in `timeZone` when given (`en-CA` writes a date that way). */
80
+ export function isoDay(date: Date, timeZone?: string): string {
81
+ return new Intl.DateTimeFormat("en-CA", { year: "numeric", month: "2-digit", day: "2-digit", timeZone }).format(date);
82
+ }
83
+
84
+ /** Where "Open in Calendar" goes: the day view of the day the meeting starts (the `date`/`view` the calendar page reads), or the calendar itself
85
+ * when the invitation names no usable start. An all-day event's day is the organizer's; any other is the reader's. */
86
+ export function calendarHref(invite: Pick<MessageInvite, "startDate" | "allDay" | "timezone">): string {
87
+ const start = validDate(invite.startDate);
88
+ if (!start) {
89
+ return APP_HREFS.calendar;
90
+ }
91
+ return `${APP_HREFS.calendar}?date=${isoDay(start, invite.allDay ? allDayZone(invite.timezone) : undefined)}&view=day`;
92
+ }
93
+
94
+ /** The reader's answer as a list row says it. */
95
+ export const ANSWER_LABEL: Record<InviteResponse, string> = {
96
+ accepted: "Accepted",
97
+ tentative: "Tentative",
98
+ declined: "Declined",
99
+ };
100
+
101
+ /** The most conflicting events that are named; more are counted. */
102
+ const MAX_NAMED_CONFLICTS = 3;
103
+
104
+ /** The titles of the events an invitation conflicts with, as "A, B and 2 more". */
105
+ export function conflictSummary(conflicts: { title: string }[]): string {
106
+ const titles = conflicts.map((c) => c.title.trim() || "(no title)");
107
+ return titles.length <= MAX_NAMED_CONFLICTS
108
+ ? titles.join(", ")
109
+ : `${titles.slice(0, MAX_NAMED_CONFLICTS).join(", ")} and ${titles.length - MAX_NAMED_CONFLICTS} more`;
110
+ }
@@ -0,0 +1,114 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ import { useCallback, useEffect, useReducer } from "react";
6
+ import { MessageInvite, getMessageInvite } from "@rapidmx/react-shared/calendar/inviteApi.js";
7
+
8
+ /**
9
+ * A per-message cache of the calendar invitation the server reads out of a message, shared by everything that draws one: the reading pane's
10
+ * card, the list row's RSVP chip and its popover. They ask for the same message a moment apart (the row's chip, then the pane once it is
11
+ * opened), and an answer given in one has to show in the others, so a lookup is made once and every answer goes through `storeInvite()`.
12
+ *
13
+ * A message with no invitation (`null`, the server's 404) is remembered too. A lookup that fails is not - nothing is cached and the next
14
+ * thing to ask (a remount, another row) tries again - but nothing retries on its own. An entry goes stale after `INVITE_TTL_MS`, because the
15
+ * calendar it describes can change elsewhere (the meeting deleted, another device answering); it is refetched when next asked for.
16
+ */
17
+
18
+ /** How long a looked-up invitation is trusted before the next ask reads it again. */
19
+ export const INVITE_TTL_MS = 30_000;
20
+
21
+ interface Entry {
22
+ promise: Promise<MessageInvite | null>;
23
+ /** `undefined` until the lookup answers; `null` for a message with no readable invitation. */
24
+ value?: MessageInvite | null;
25
+ at: number;
26
+ }
27
+
28
+ const entries = new Map<string, Entry>();
29
+ const listeners = new Map<string, Set<() => void>>();
30
+
31
+ function notify(uid: string): void {
32
+ listeners.get(uid)?.forEach((listener) => listener());
33
+ }
34
+
35
+ /** Older servers, or a partial answer, may leave a list out: a card must never fail to draw over one. */
36
+ function normalize(invite: MessageInvite | null): MessageInvite | null {
37
+ if (!invite) {
38
+ return null;
39
+ }
40
+ const partial: Partial<MessageInvite> = invite;
41
+ return { ...invite, attendees: partial.attendees ?? [], conflicts: partial.conflicts ?? [], schedule: partial.schedule ?? [] };
42
+ }
43
+
44
+ /** Reads a message's invitation, from the cache when it is fresh. Rejects when the lookup fails. */
45
+ export function loadInvite(uid: string): Promise<MessageInvite | null> {
46
+ const existing = entries.get(uid);
47
+ if (existing && (existing.value === undefined || Date.now() - existing.at < INVITE_TTL_MS)) {
48
+ return existing.promise;
49
+ }
50
+ const entry: Entry = {
51
+ at: Date.now(),
52
+ promise: getMessageInvite(uid).then(
53
+ (invite) => {
54
+ entry.value = normalize(invite);
55
+ entry.at = Date.now();
56
+ notify(uid);
57
+ return entry.value;
58
+ },
59
+ (err: unknown) => {
60
+ if (entries.get(uid) === entry) {
61
+ entries.delete(uid);
62
+ }
63
+ throw err;
64
+ },
65
+ ),
66
+ };
67
+ entries.set(uid, entry);
68
+ return entry.promise;
69
+ }
70
+
71
+ /** Records the invitation as it now stands after an answer, so the pane, the chip and the popover all show it. */
72
+ export function storeInvite(uid: string, invite: MessageInvite): void {
73
+ const value = normalize(invite);
74
+ entries.set(uid, { promise: Promise.resolve(value), value, at: Date.now() });
75
+ notify(uid);
76
+ }
77
+
78
+ /** Forgets everything - for tests, and for a sign-out. */
79
+ export function clearInviteCache(): void {
80
+ entries.clear();
81
+ }
82
+
83
+ /**
84
+ * A message's invitation, looked up once (shared with every other user of the same message) when `enabled`. `invite` is `null` until it is
85
+ * known, and stays `null` for a message with none or a lookup that failed - nothing to draw either way. `settled` says the lookup is over.
86
+ * Nothing is asked while disabled, and a failure is never retried from here.
87
+ */
88
+ export function useMessageInvite(uid: string, enabled = true): { invite: MessageInvite | null; settled: boolean; setInvite: (invite: MessageInvite) => void } {
89
+ const [, rerender] = useReducer((n: number) => n + 1, 0);
90
+ useEffect(() => {
91
+ if (!enabled) {
92
+ return;
93
+ }
94
+ let cancelled = false;
95
+ const update = () => {
96
+ if (!cancelled) {
97
+ rerender();
98
+ }
99
+ };
100
+ const set = listeners.get(uid) ?? new Set();
101
+ set.add(update);
102
+ listeners.set(uid, set);
103
+ loadInvite(uid).then(update, () => {
104
+ // Nothing to show, and nothing worth interrupting the reader with: the message reads the same without it.
105
+ });
106
+ return () => {
107
+ cancelled = true;
108
+ set.delete(update);
109
+ };
110
+ }, [uid, enabled]);
111
+ const setInvite = useCallback((invite: MessageInvite) => storeInvite(uid, invite), [uid]);
112
+ const value = enabled ? entries.get(uid)?.value : undefined;
113
+ return { invite: value ?? null, settled: value !== undefined, setInvite };
114
+ }
@@ -0,0 +1,21 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ import React from "react";
6
+ import { FolderBadge, badgeLabel } from "../../../mail/folderCounts.js";
7
+
8
+ /** A folder's badge: an accent pill with the unread count, or - for the folders that show how many they hold - plain muted text. */
9
+ export default function FolderBadgeChip({ badge }: { badge: FolderBadge }) {
10
+ return (
11
+ <span
12
+ className={[
13
+ "text-xs rounded-pill py-0.5 px-1.5",
14
+ badge.kind === "unread" ? "font-bold bg-primary/15 text-primary-dark" : "font-medium text-text-muted",
15
+ ].join(" ")}
16
+ >
17
+ <span aria-hidden="true">{badge.value}</span>
18
+ <span className="sr-only"> {badgeLabel(badge)}</span>
19
+ </span>
20
+ );
21
+ }