@rapidmx/web-client 0.4.0 → 0.6.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 (320) hide show
  1. package/README.md +88 -0
  2. package/apps/admin/audit-log/index.tsx +35 -8
  3. package/apps/admin/data-requests/index.tsx +480 -485
  4. package/apps/admin/distribution-lists/[uid].tsx +19 -1
  5. package/apps/admin/escrow-scopes/[uid].tsx +348 -237
  6. package/apps/admin/escrow-scopes/new/index.tsx +8 -2
  7. package/apps/admin/index.tsx +19 -1
  8. package/apps/admin/ingest-queue/index.tsx +44 -5
  9. package/apps/admin/mailboxes/[uid].tsx +211 -184
  10. package/apps/admin/quarantine/index.tsx +46 -14
  11. package/apps/admin/transport-rules/[uid].tsx +30 -1
  12. package/apps/admin/transport-rules/_transportRuleConfig.tsx +38 -2
  13. package/apps/admin/transport-rules/index.tsx +24 -6
  14. package/apps/admin/transport-rules/new/index.tsx +30 -1
  15. package/apps/escrow/_layout.tsx +2 -3
  16. package/apps/escrow/audit-log/index.tsx +196 -168
  17. package/apps/escrow/matters/[uid].tsx +621 -521
  18. package/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.tsx +22 -1
  19. package/apps/shared/components/admin/layout/AdminShell.tsx +28 -9
  20. package/apps/shared/components/admin/mailboxes/EscrowScopeCard.tsx +152 -0
  21. package/apps/shared/components/admin/mailboxes/ResourceSettingsCard.tsx +3 -3
  22. package/apps/shared/components/admin/mailboxes/ShareAccessCard.tsx +55 -11
  23. package/apps/shared/components/admin/settings/BrandingForm.tsx +15 -4
  24. package/apps/shared/components/admin/settings/DomainDnsSetup.tsx +18 -7
  25. package/apps/shared/components/admin/settings/EncryptionPolicyForm.tsx +10 -2
  26. package/apps/shared/components/admin/settings/MailboxCreateForm.tsx +6 -0
  27. package/apps/shared/components/admin/settings/MailboxPolicyForm.tsx +45 -12
  28. package/apps/shared/components/admin/settings/PluginsManager.tsx +1235 -595
  29. package/apps/shared/components/admin/settings/RetentionPolicyForm.tsx +174 -98
  30. package/apps/shared/components/admin/setup/EscrowSetupStep.tsx +49 -13
  31. package/apps/shared/components/admin/setup/SetupWizard.tsx +150 -34
  32. package/apps/shared/components/admin/signOut.ts +79 -0
  33. package/apps/shared/components/admin/usePagedList.tsx +129 -0
  34. package/apps/shared/components/calendar/EventModal.tsx +717 -549
  35. package/apps/shared/components/calendar/MonthView.tsx +173 -139
  36. package/apps/shared/components/calendar/RecurrenceEditor.tsx +222 -180
  37. package/apps/shared/components/calendar/SplitDayView.tsx +143 -137
  38. package/apps/shared/components/calendar/TimeGridView.tsx +244 -198
  39. package/apps/shared/components/calendar/allDay.ts +124 -0
  40. package/apps/shared/components/calendar/layout/CalendarShell.tsx +194 -192
  41. package/apps/shared/components/contacts/ContactDetailPane.tsx +100 -21
  42. package/apps/shared/components/contacts/ContactForm.tsx +377 -348
  43. package/apps/shared/components/contacts/ContactsSidebar.tsx +6 -2
  44. package/apps/shared/components/contacts/KeyChangeReview.tsx +192 -0
  45. package/apps/shared/components/contacts/contactKeys.ts +78 -0
  46. package/apps/shared/components/contacts/layout/ContactsShell.tsx +199 -197
  47. package/apps/shared/components/escrow/layout/EscrowShell.tsx +148 -134
  48. package/apps/shared/components/layout/AppShell.tsx +123 -33
  49. package/apps/shared/components/layout/BrandingChrome.tsx +48 -10
  50. package/apps/shared/components/layout/KeyEnrollmentGate.tsx +389 -298
  51. package/apps/shared/components/layout/MailboxProvisioning.tsx +19 -3
  52. package/apps/shared/components/layout/RecoveryCodeUnlock.tsx +350 -0
  53. package/apps/shared/components/layout/UnlockPromptProvider.tsx +257 -128
  54. package/apps/shared/components/mail/ConversationThreadPane.tsx +216 -181
  55. package/apps/shared/components/mail/MessageDetailPane.tsx +1318 -630
  56. package/apps/shared/components/mail/compose/ComposeContext.tsx +20 -15
  57. package/apps/shared/components/mail/compose/ComposeWindow.tsx +854 -132
  58. package/apps/shared/components/mail/compose/composeFlushRegistry.ts +60 -0
  59. package/apps/shared/components/mail/layout/MailShell.tsx +420 -408
  60. package/apps/shared/components/mail/pinnedSigners.ts +124 -0
  61. package/apps/shared/components/mail/verificationSeals.ts +125 -0
  62. package/apps/shared/components/mail/writableMailboxes.ts +101 -0
  63. package/apps/shared/components/rules/RuleBuilder.tsx +311 -276
  64. package/apps/shared/components/settings/layout/SettingsShell.tsx +23 -9
  65. package/apps/shared/components/tasks/layout/TasksShell.tsx +201 -199
  66. package/apps/shared/mail/listAllPages.ts +39 -0
  67. package/apps/shared/plugins/pluginNav.ts +73 -0
  68. package/apps/shared/search/LocalIndexLifecycle.tsx +64 -55
  69. package/apps/shared/search/localIndexBuilder.ts +481 -179
  70. package/apps/shared/search/localIndexRpcClient.ts +231 -29
  71. package/apps/shared/search/localIndexSchema.ts +15 -6
  72. package/apps/shared/search/localIndexStorage.ts +98 -0
  73. package/apps/shared/search/localIndexVFS.ts +32 -1
  74. package/apps/shared/search/localIndexWorker.ts +648 -186
  75. package/apps/www/calendar/index.tsx +438 -417
  76. package/apps/www/contacts/[uid].tsx +21 -2
  77. package/apps/www/contacts/index.tsx +116 -12
  78. package/apps/www/index.tsx +1314 -1041
  79. package/apps/www/messages/[uid].tsx +18 -6
  80. package/apps/www/settings/auto-reply/index.tsx +134 -129
  81. package/apps/www/settings/encryption/index.tsx +739 -216
  82. package/apps/www/settings/filters/[uid].tsx +171 -155
  83. package/apps/www/settings/filters/new/index.tsx +8 -1
  84. package/apps/www/settings/focused-inbox/index.tsx +150 -148
  85. package/apps/www/settings/privacy/index.tsx +494 -436
  86. package/apps/www/settings/read-receipts/index.tsx +148 -125
  87. package/apps/www/settings/sharing/index.tsx +17 -14
  88. package/apps/www/tasks/index.tsx +638 -579
  89. package/dist/apps/admin/_404.d.ts +2 -0
  90. package/dist/apps/admin/_500.d.ts +2 -0
  91. package/dist/apps/admin/_layout.d.ts +8 -0
  92. package/dist/apps/admin/audit-log/index.d.ts +11 -0
  93. package/dist/apps/admin/audit-log/index.js +38 -8
  94. package/dist/apps/admin/branding/index.d.ts +3 -0
  95. package/dist/apps/admin/data-requests/index.d.ts +3 -0
  96. package/dist/apps/admin/data-requests/index.js +52 -72
  97. package/dist/apps/admin/distribution-lists/[uid].d.ts +7 -0
  98. package/dist/apps/admin/distribution-lists/[uid].js +1 -1
  99. package/dist/apps/admin/distribution-lists/index.d.ts +3 -0
  100. package/dist/apps/admin/distribution-lists/new/index.d.ts +3 -0
  101. package/dist/apps/admin/domains/[uid].d.ts +7 -0
  102. package/dist/apps/admin/domains/index.d.ts +3 -0
  103. package/dist/apps/admin/domains/new/index.d.ts +3 -0
  104. package/dist/apps/admin/encryption-policy/index.d.ts +3 -0
  105. package/dist/apps/admin/escrow-scopes/[uid].d.ts +21 -0
  106. package/dist/apps/admin/escrow-scopes/[uid].js +91 -12
  107. package/dist/apps/admin/escrow-scopes/index.d.ts +3 -0
  108. package/dist/apps/admin/escrow-scopes/new/index.d.ts +3 -0
  109. package/dist/apps/admin/escrow-scopes/new/index.js +8 -3
  110. package/dist/apps/admin/index.d.ts +3 -0
  111. package/dist/apps/admin/index.js +4 -1
  112. package/dist/apps/admin/ingest-queue/index.d.ts +4 -0
  113. package/dist/apps/admin/ingest-queue/index.js +24 -6
  114. package/dist/apps/admin/mailbox-policy/index.d.ts +3 -0
  115. package/dist/apps/admin/mailboxes/[uid].d.ts +7 -0
  116. package/dist/apps/admin/mailboxes/[uid].js +20 -4
  117. package/dist/apps/admin/mailboxes/new/index.d.ts +3 -0
  118. package/dist/apps/admin/plugins/index.d.ts +3 -0
  119. package/dist/apps/admin/quarantine/index.d.ts +6 -0
  120. package/dist/apps/admin/quarantine/index.js +20 -11
  121. package/dist/apps/admin/retention-policy/index.d.ts +3 -0
  122. package/dist/apps/admin/setup/index.d.ts +3 -0
  123. package/dist/apps/admin/transport-rules/[uid].d.ts +7 -0
  124. package/dist/apps/admin/transport-rules/[uid].js +18 -2
  125. package/dist/apps/admin/transport-rules/_transportRuleConfig.d.ts +21 -0
  126. package/dist/apps/admin/transport-rules/_transportRuleConfig.js +19 -0
  127. package/dist/apps/admin/transport-rules/index.d.ts +3 -0
  128. package/dist/apps/admin/transport-rules/index.js +22 -6
  129. package/dist/apps/admin/transport-rules/new/index.d.ts +3 -0
  130. package/dist/apps/admin/transport-rules/new/index.js +18 -2
  131. package/dist/apps/escrow/_layout.d.ts +10 -0
  132. package/dist/apps/escrow/_layout.js +3 -3
  133. package/dist/apps/escrow/audit-log/index.d.ts +9 -0
  134. package/dist/apps/escrow/audit-log/index.js +26 -1
  135. package/dist/apps/escrow/index.d.ts +3 -0
  136. package/dist/apps/escrow/matters/[uid].d.ts +7 -0
  137. package/dist/apps/escrow/matters/[uid].js +77 -42
  138. package/dist/apps/escrow/matters/new/index.d.ts +3 -0
  139. package/dist/apps/shared/components/admin/distributionLists/MemberListCard.d.ts +17 -0
  140. package/dist/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.d.ts +32 -0
  141. package/dist/apps/shared/components/admin/escrowScopes/EscrowScopeKeyAndHoldersFields.js +11 -2
  142. package/dist/apps/shared/components/admin/layout/AdminShell.d.ts +32 -0
  143. package/dist/apps/shared/components/admin/layout/AdminShell.js +15 -6
  144. package/dist/apps/shared/components/admin/mailboxes/EscrowScopeCard.d.ts +12 -0
  145. package/dist/apps/shared/components/admin/mailboxes/EscrowScopeCard.js +72 -0
  146. package/dist/apps/shared/components/admin/mailboxes/MailboxTable.d.ts +6 -0
  147. package/dist/apps/shared/components/admin/mailboxes/ResourceSettingsCard.d.ts +19 -0
  148. package/dist/apps/shared/components/admin/mailboxes/ResourceSettingsCard.js +3 -3
  149. package/dist/apps/shared/components/admin/mailboxes/ShareAccessCard.d.ts +12 -0
  150. package/dist/apps/shared/components/admin/mailboxes/ShareAccessCard.js +22 -4
  151. package/dist/apps/shared/components/admin/settings/BrandingForm.d.ts +9 -0
  152. package/dist/apps/shared/components/admin/settings/BrandingForm.js +15 -4
  153. package/dist/apps/shared/components/admin/settings/DomainDnsSetup.d.ts +12 -0
  154. package/dist/apps/shared/components/admin/settings/DomainDnsSetup.js +13 -7
  155. package/dist/apps/shared/components/admin/settings/EncryptionPolicyForm.d.ts +12 -0
  156. package/dist/apps/shared/components/admin/settings/EncryptionPolicyForm.js +7 -2
  157. package/dist/apps/shared/components/admin/settings/LoadedSettingsForm.d.ts +9 -0
  158. package/dist/apps/shared/components/admin/settings/MailboxCreateForm.d.ts +19 -0
  159. package/dist/apps/shared/components/admin/settings/MailboxCreateForm.js +6 -0
  160. package/dist/apps/shared/components/admin/settings/MailboxPolicyForm.d.ts +10 -0
  161. package/dist/apps/shared/components/admin/settings/MailboxPolicyForm.js +34 -12
  162. package/dist/apps/shared/components/admin/settings/PluginsManager.d.ts +4 -0
  163. package/dist/apps/shared/components/admin/settings/PluginsManager.js +390 -78
  164. package/dist/apps/shared/components/admin/settings/RetentionPolicyForm.d.ts +9 -0
  165. package/dist/apps/shared/components/admin/settings/RetentionPolicyForm.js +40 -11
  166. package/dist/apps/shared/components/admin/setup/EscrowSetupStep.d.ts +14 -0
  167. package/dist/apps/shared/components/admin/setup/EscrowSetupStep.js +29 -13
  168. package/dist/apps/shared/components/admin/setup/SetupWizard.d.ts +36 -0
  169. package/dist/apps/shared/components/admin/setup/SetupWizard.js +87 -21
  170. package/dist/apps/shared/components/admin/signOut.d.ts +23 -0
  171. package/dist/apps/shared/components/admin/signOut.js +75 -0
  172. package/dist/apps/shared/components/admin/usePagedList.d.ts +39 -0
  173. package/dist/apps/shared/components/admin/usePagedList.js +99 -0
  174. package/dist/apps/shared/components/calendar/CalendarListSidebar.d.ts +26 -0
  175. package/dist/apps/shared/components/calendar/EventModal.d.ts +46 -0
  176. package/dist/apps/shared/components/calendar/EventModal.js +142 -21
  177. package/dist/apps/shared/components/calendar/MonthView.d.ts +15 -0
  178. package/dist/apps/shared/components/calendar/MonthView.js +12 -5
  179. package/dist/apps/shared/components/calendar/RecurrenceEditor.d.ts +20 -0
  180. package/dist/apps/shared/components/calendar/RecurrenceEditor.js +40 -5
  181. package/dist/apps/shared/components/calendar/ResourcePicker.d.ts +19 -0
  182. package/dist/apps/shared/components/calendar/SplitDayView.d.ts +28 -0
  183. package/dist/apps/shared/components/calendar/SplitDayView.js +10 -4
  184. package/dist/apps/shared/components/calendar/TimeGridView.d.ts +17 -0
  185. package/dist/apps/shared/components/calendar/TimeGridView.js +23 -7
  186. package/dist/apps/shared/components/calendar/allDay.d.ts +51 -0
  187. package/dist/apps/shared/components/calendar/allDay.js +111 -0
  188. package/dist/apps/shared/components/calendar/layout/CalendarShell.d.ts +40 -0
  189. package/dist/apps/shared/components/calendar/layout/CalendarShell.js +3 -3
  190. package/dist/apps/shared/components/contacts/ContactDetailPane.d.ts +23 -0
  191. package/dist/apps/shared/components/contacts/ContactDetailPane.js +43 -5
  192. package/dist/apps/shared/components/contacts/ContactForm.d.ts +20 -0
  193. package/dist/apps/shared/components/contacts/ContactForm.js +32 -10
  194. package/dist/apps/shared/components/contacts/ContactsSidebar.d.ts +40 -0
  195. package/dist/apps/shared/components/contacts/ContactsSidebar.js +2 -2
  196. package/dist/apps/shared/components/contacts/ContactsToolbar.d.ts +25 -0
  197. package/dist/apps/shared/components/contacts/KeyChangeReview.d.ts +40 -0
  198. package/dist/apps/shared/components/contacts/KeyChangeReview.js +63 -0
  199. package/dist/apps/shared/components/contacts/contactKeys.d.ts +29 -0
  200. package/dist/apps/shared/components/contacts/contactKeys.js +64 -0
  201. package/dist/apps/shared/components/contacts/layout/ContactsShell.d.ts +21 -0
  202. package/dist/apps/shared/components/contacts/layout/ContactsShell.js +2 -2
  203. package/dist/apps/shared/components/escrow/layout/EscrowShell.d.ts +25 -0
  204. package/dist/apps/shared/components/escrow/layout/EscrowShell.js +24 -5
  205. package/dist/apps/shared/components/forms/StringListField.d.ts +22 -0
  206. package/dist/apps/shared/components/layout/AppShell.d.ts +49 -0
  207. package/dist/apps/shared/components/layout/AppShell.js +97 -26
  208. package/dist/apps/shared/components/layout/BrandingChrome.d.ts +18 -0
  209. package/dist/apps/shared/components/layout/BrandingChrome.js +45 -10
  210. package/dist/apps/shared/components/layout/KeyEnrollmentGate.d.ts +51 -0
  211. package/dist/apps/shared/components/layout/KeyEnrollmentGate.js +49 -12
  212. package/dist/apps/shared/components/layout/MailboxProvisioning.d.ts +13 -0
  213. package/dist/apps/shared/components/layout/MailboxProvisioning.js +10 -2
  214. package/dist/apps/shared/components/layout/RecoveryCodeUnlock.d.ts +66 -0
  215. package/dist/apps/shared/components/layout/RecoveryCodeUnlock.js +174 -0
  216. package/dist/apps/shared/components/layout/UnlockPromptProvider.d.ts +45 -0
  217. package/dist/apps/shared/components/layout/UnlockPromptProvider.js +73 -14
  218. package/dist/apps/shared/components/layout/UserMenu.d.ts +23 -0
  219. package/dist/apps/shared/components/mail/ConversationList.d.ts +11 -0
  220. package/dist/apps/shared/components/mail/ConversationThreadPane.d.ts +23 -0
  221. package/dist/apps/shared/components/mail/ConversationThreadPane.js +50 -12
  222. package/dist/apps/shared/components/mail/MessageDetailPane.d.ts +93 -0
  223. package/dist/apps/shared/components/mail/MessageDetailPane.js +441 -36
  224. package/dist/apps/shared/components/mail/compose/ComposeContext.d.ts +58 -0
  225. package/dist/apps/shared/components/mail/compose/ComposeContext.js +9 -6
  226. package/dist/apps/shared/components/mail/compose/ComposeToolbar.d.ts +15 -0
  227. package/dist/apps/shared/components/mail/compose/ComposeWindow.d.ts +37 -0
  228. package/dist/apps/shared/components/mail/compose/ComposeWindow.js +699 -128
  229. package/dist/apps/shared/components/mail/compose/EmojiPicker.d.ts +14 -0
  230. package/dist/apps/shared/components/mail/compose/GifPicker.d.ts +13 -0
  231. package/dist/apps/shared/components/mail/compose/RichTextEditor.d.ts +34 -0
  232. package/dist/apps/shared/components/mail/compose/ScheduleSendPicker.d.ts +16 -0
  233. package/dist/apps/shared/components/mail/compose/composeFlushRegistry.d.ts +27 -0
  234. package/dist/apps/shared/components/mail/compose/composeFlushRegistry.js +50 -0
  235. package/dist/apps/shared/components/mail/layout/MailShell.d.ts +57 -0
  236. package/dist/apps/shared/components/mail/layout/MailShell.js +13 -4
  237. package/dist/apps/shared/components/mail/pinnedSigners.d.ts +33 -0
  238. package/dist/apps/shared/components/mail/pinnedSigners.js +98 -0
  239. package/dist/apps/shared/components/mail/verificationSeals.d.ts +22 -0
  240. package/dist/apps/shared/components/mail/verificationSeals.js +112 -0
  241. package/dist/apps/shared/components/mail/writableMailboxes.d.ts +15 -0
  242. package/dist/apps/shared/components/mail/writableMailboxes.js +87 -0
  243. package/dist/apps/shared/components/rules/RuleBuilder.d.ts +70 -0
  244. package/dist/apps/shared/components/rules/RuleBuilder.js +34 -6
  245. package/dist/apps/shared/components/settings/layout/SettingsShell.d.ts +41 -0
  246. package/dist/apps/shared/components/settings/layout/SettingsShell.js +19 -9
  247. package/dist/apps/shared/components/tasks/TasksSidebar.d.ts +41 -0
  248. package/dist/apps/shared/components/tasks/TasksToolbar.d.ts +14 -0
  249. package/dist/apps/shared/components/tasks/layout/TasksShell.d.ts +24 -0
  250. package/dist/apps/shared/components/tasks/layout/TasksShell.js +2 -2
  251. package/dist/apps/shared/mail/findWellKnownFolderUid.d.ts +5 -0
  252. package/dist/apps/shared/mail/listAllPages.d.ts +17 -0
  253. package/dist/apps/shared/mail/listAllPages.js +25 -0
  254. package/dist/apps/shared/plugins/pluginNav.d.ts +39 -0
  255. package/dist/apps/shared/plugins/pluginNav.js +33 -0
  256. package/dist/apps/shared/search/LocalIndexLifecycle.d.ts +13 -0
  257. package/dist/apps/shared/search/LocalIndexLifecycle.js +58 -54
  258. package/dist/apps/shared/search/localIndexBlockCipher.d.ts +36 -0
  259. package/dist/apps/shared/search/localIndexBuilder.d.ts +85 -0
  260. package/dist/apps/shared/search/localIndexBuilder.js +292 -37
  261. package/dist/apps/shared/search/localIndexKey.d.ts +4 -0
  262. package/dist/apps/shared/search/localIndexRpcClient.d.ts +71 -0
  263. package/dist/apps/shared/search/localIndexRpcClient.js +191 -26
  264. package/dist/apps/shared/search/localIndexSchema.d.ts +111 -0
  265. package/dist/apps/shared/search/localIndexSchema.js +12 -6
  266. package/dist/apps/shared/search/localIndexSizePreference.d.ts +27 -0
  267. package/dist/apps/shared/search/localIndexStorage.d.ts +28 -0
  268. package/dist/apps/shared/search/localIndexStorage.js +86 -0
  269. package/dist/apps/shared/search/localIndexVFS.d.ts +101 -0
  270. package/dist/apps/shared/search/localIndexVFS.js +68 -40
  271. package/dist/apps/shared/search/localIndexWorker.d.ts +145 -0
  272. package/dist/apps/shared/search/localIndexWorker.js +519 -173
  273. package/dist/apps/shared/search/searchTier2.d.ts +30 -0
  274. package/dist/apps/www/_404.d.ts +2 -0
  275. package/dist/apps/www/_500.d.ts +2 -0
  276. package/dist/apps/www/_layout.d.ts +14 -0
  277. package/dist/apps/www/calendar/index.d.ts +3 -0
  278. package/dist/apps/www/calendar/index.js +28 -10
  279. package/dist/apps/www/contacts/[uid].d.ts +13 -0
  280. package/dist/apps/www/contacts/[uid].js +13 -2
  281. package/dist/apps/www/contacts/index.d.ts +3 -0
  282. package/dist/apps/www/contacts/index.js +80 -10
  283. package/dist/apps/www/index.d.ts +3 -0
  284. package/dist/apps/www/index.js +339 -108
  285. package/dist/apps/www/messages/[uid].d.ts +11 -0
  286. package/dist/apps/www/messages/[uid].js +18 -6
  287. package/dist/apps/www/settings/auto-reply/index.d.ts +4 -0
  288. package/dist/apps/www/settings/auto-reply/index.js +9 -4
  289. package/dist/apps/www/settings/encryption/index.d.ts +7 -0
  290. package/dist/apps/www/settings/encryption/index.js +514 -97
  291. package/dist/apps/www/settings/filters/[uid].d.ts +8 -0
  292. package/dist/apps/www/settings/filters/[uid].js +22 -7
  293. package/dist/apps/www/settings/filters/_mailFilterRuleConfig.d.ts +11 -0
  294. package/dist/apps/www/settings/filters/index.d.ts +4 -0
  295. package/dist/apps/www/settings/filters/new/index.d.ts +4 -0
  296. package/dist/apps/www/settings/filters/new/index.js +8 -2
  297. package/dist/apps/www/settings/focused-inbox/index.d.ts +4 -0
  298. package/dist/apps/www/settings/focused-inbox/index.js +3 -1
  299. package/dist/apps/www/settings/labels/index.d.ts +4 -0
  300. package/dist/apps/www/settings/privacy/index.d.ts +4 -0
  301. package/dist/apps/www/settings/privacy/index.js +57 -22
  302. package/dist/apps/www/settings/read-receipts/index.d.ts +4 -0
  303. package/dist/apps/www/settings/read-receipts/index.js +10 -3
  304. package/dist/apps/www/settings/sharing/index.d.ts +4 -0
  305. package/dist/apps/www/settings/sharing/index.js +7 -11
  306. package/dist/apps/www/settings/signatures/[uid].d.ts +8 -0
  307. package/dist/apps/www/settings/signatures/index.d.ts +4 -0
  308. package/dist/apps/www/settings/signatures/new/index.d.ts +4 -0
  309. package/dist/apps/www/settings/signatures/signatureDefaults.d.ts +10 -0
  310. package/dist/apps/www/tasks/index.d.ts +3 -0
  311. package/dist/apps/www/tasks/index.js +50 -10
  312. package/package.json +3 -3
  313. package/apps/shared/components/booking/AvailabilityEditor.tsx +0 -118
  314. package/apps/www/settings/booking-types/[uid].tsx +0 -300
  315. package/apps/www/settings/booking-types/index.tsx +0 -98
  316. package/apps/www/settings/booking-types/new/index.tsx +0 -212
  317. package/dist/apps/shared/components/booking/AvailabilityEditor.js +0 -45
  318. package/dist/apps/www/settings/booking-types/[uid].js +0 -129
  319. package/dist/apps/www/settings/booking-types/index.js +0 -29
  320. package/dist/apps/www/settings/booking-types/new/index.js +0 -86
@@ -0,0 +1,124 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ /**
6
+ * The trusted signing-key fingerprints for a received message's sender, for `evaluateMessageSecurity()`'s
7
+ * `pinnedSignerFingerprints`: the keys key discovery already pinned on the contacts in the reading mailbox's own
8
+ * contacts folder(s). Reads only stored contacts - never triggers a Discovery lookup, which must not happen on
9
+ * message receipt.
10
+ *
11
+ * `MessageDetailPane` renders once per opened message (and once per message in a thread), so each mailbox's
12
+ * contact list is fetched once and reused for `CONTACTS_CACHE_TTL_MS`; a failed load isn't cached. Any failure
13
+ * leaves the caller with no pins, which `evaluateMessageSecurity()` reports as an unverified signer - never as
14
+ * verified.
15
+ *
16
+ * The cache is dropped (`clearPinnedSignerCache()`) whenever a key session locks (subscribed on first use), on sign-out
17
+ * (`AppShell`), and after the reader adds, edits or deletes contacts (the contacts pages) - so a contact removed
18
+ * because its key was revoked doesn't keep vouching for signatures until the TTL runs out.
19
+ */
20
+ import {
21
+ Contact,
22
+ PINNED_FINGERPRINT_MAX_PAGES,
23
+ PINNED_FINGERPRINT_PAGE_SIZE,
24
+ SignerKeyState,
25
+ listContacts,
26
+ pinnedSigningFingerprintsFor,
27
+ signerKeyStateFor,
28
+ } from "@rapidmx/react-shared/contacts/contactsApi.js";
29
+ import { keyPinnedSince } from "../contacts/contactKeys.js";
30
+ import { listFolders } from "@rapidmx/react-shared/mail/mailApi.js";
31
+ import { subscribeKeySession } from "@rapidmx/react-shared/crypto/keySession.js";
32
+
33
+ /** How long one mailbox's loaded contact list is reused before it is fetched again. */
34
+ export const CONTACTS_CACHE_TTL_MS = 60_000;
35
+
36
+ const contactsCache = new Map<string, { loadedAt: number; contacts: Promise<Contact[]> }>();
37
+
38
+ /** Forgets every cached contact list - on sign-out, a key-session lock, after the reader changes their contacts, and
39
+ * in tests. */
40
+ export function clearPinnedSignerCache(): void {
41
+ contactsCache.clear();
42
+ }
43
+
44
+ let lockSubscribed = false;
45
+
46
+ /** Subscribes (once, lazily - a module-level subscription would run in every page that merely imports this) to key
47
+ * session changes, clearing the cache whenever any mailbox's keys are locked. */
48
+ function subscribeToLocksOnce(): void {
49
+ if (lockSubscribed) {
50
+ return;
51
+ }
52
+ lockSubscribed = true;
53
+ subscribeKeySession((event) => {
54
+ if (event.state === "locked") {
55
+ clearPinnedSignerCache();
56
+ }
57
+ });
58
+ }
59
+
60
+ async function loadMailboxContacts(mailboxUid: string): Promise<Contact[]> {
61
+ const folders = await listFolders(mailboxUid);
62
+ const contacts: Contact[] = [];
63
+ for (const folder of folders.filter((f) => f.type === "contacts")) {
64
+ for (let page = 0; page < PINNED_FINGERPRINT_MAX_PAGES; page++) {
65
+ const batch = await listContacts(folder.uid, { limit: PINNED_FINGERPRINT_PAGE_SIZE, page });
66
+ contacts.push(...batch);
67
+ if (batch.length < PINNED_FINGERPRINT_PAGE_SIZE) {
68
+ break;
69
+ }
70
+ }
71
+ }
72
+ return contacts;
73
+ }
74
+
75
+ /** `mailboxUid`'s contacts, from the cache when fresh. Rejects if they can't be loaded. */
76
+ function cachedMailboxContacts(mailboxUid: string): Promise<Contact[]> {
77
+ subscribeToLocksOnce();
78
+ let entry = contactsCache.get(mailboxUid);
79
+ if (!entry || Date.now() - entry.loadedAt > CONTACTS_CACHE_TTL_MS) {
80
+ const created = { loadedAt: Date.now(), contacts: loadMailboxContacts(mailboxUid) };
81
+ contactsCache.set(mailboxUid, created);
82
+ created.contacts.catch(() => {
83
+ if (contactsCache.get(mailboxUid) === created) {
84
+ contactsCache.delete(mailboxUid);
85
+ }
86
+ });
87
+ entry = created;
88
+ }
89
+ return entry.contacts;
90
+ }
91
+
92
+ /** The sender `address`'s pinned signing fingerprints from `mailboxUid`'s contacts. Rejects if they can't be loaded. */
93
+ export async function getPinnedSignerFingerprints(mailboxUid: string, address: string): Promise<string[]> {
94
+ return pinnedSigningFingerprintsFor(await cachedMailboxContacts(mailboxUid), address);
95
+ }
96
+
97
+ /** A sender's signing-key state (`signerKeyStateFor()`) plus what a key-changed notice needs to show and link. */
98
+ export interface SenderKeyState extends SignerKeyState {
99
+ /** The contact holding the first pinned signing key, else the one holding the conflict, else the first match. */
100
+ contactUid?: string;
101
+ /** When the first pinned signing key started being trusted - see `keyPinnedSince()`. */
102
+ pinnedSince?: number;
103
+ }
104
+
105
+ /** The sender `address`'s signing-key state from `mailboxUid`'s (cached) contacts, for a "signing key changed" comparison
106
+ * or to spot a recorded conflict. Reads stored contacts only. Rejects if they can't be loaded. */
107
+ export async function getSignerKeyState(mailboxUid: string, address: string): Promise<SenderKeyState> {
108
+ const contacts = await cachedMailboxContacts(mailboxUid);
109
+ const state = signerKeyStateFor(contacts, address);
110
+ const wanted = address.trim().toLowerCase();
111
+ const matching = contacts.filter((contact) => contact.emails.some((email) => email.address.trim().toLowerCase() === wanted));
112
+ // `signerKeyStateFor()` keeps the contacts' own key objects, so the holder is found by identity.
113
+ const pinned = state.pinned[0];
114
+ const holder = matching.find((candidate) => (candidate.keys ?? []).includes(pinned));
115
+ const contact =
116
+ holder ??
117
+ matching.find((candidate) => (candidate.keyConflicts ?? []).some((conflict) => conflict.useType === "sign")) ??
118
+ matching[0];
119
+ return {
120
+ ...state,
121
+ ...(contact ? { contactUid: contact.uid } : {}),
122
+ ...(holder ? { pinnedSince: keyPinnedSince(holder, pinned) } : {}),
123
+ };
124
+ }
@@ -0,0 +1,125 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ /**
6
+ * The web client's side of verification seals (`@rapidmx/react-shared`'s `crypto/verificationSeal.ts`): the vault's
7
+ * current `masterKeyGeneration` a seal is checked and written under, and best-effort seal writes.
8
+ *
9
+ * **Vault generation.** `getVaultGeneration()` reads `KeyVault.masterKeyGeneration` once per mailbox and reuses it for
10
+ * `VAULT_GENERATION_TTL_MS`; a failed read isn't cached. A vault that doesn't report a non-negative integer generation
11
+ * (a server predating it) counts as unavailable, and callers then evaluate without seals at all. The cache is dropped
12
+ * whenever a key session locks (subscribed on first use), so a rekey followed by a re-unlock is picked up.
13
+ *
14
+ * **Writes.** `sendVerificationSeal()` stores `sealToWrite` with `setMessageVerificationSeal()` and never rejects. Each
15
+ * message is written at most once per master key generation per page session - a seal carries the time it was built,
16
+ * so every evaluation of the same message produces a different one, and sending each would only draw 409s. A `409`
17
+ * (the server kept its seal), `400`, `403` or `404` is final; any other failure (a network error) lets a later
18
+ * evaluation try again, never a retry loop. A stored seal is remembered (`currentVerificationSeal()`) so a message
19
+ * reopened before its list copy is refreshed opens that seal instead of building another.
20
+ */
21
+ import { ApiRequestError } from "@rapidmx/react-shared/util/api.js";
22
+ import { getKeyVault } from "@rapidmx/react-shared/crypto/keyvaultApi.js";
23
+ import { subscribeKeySession } from "@rapidmx/react-shared/crypto/keySession.js";
24
+ import { type Message, setMessageVerificationSeal } from "@rapidmx/react-shared/mail/mailApi.js";
25
+ import type { SealToWrite } from "@rapidmx/react-shared/crypto/messageSecurity.js";
26
+
27
+ /** How long one mailbox's vault generation is reused before it is read again. */
28
+ export const VAULT_GENERATION_TTL_MS = 60_000;
29
+
30
+ /** Statuses after which a seal write is never attempted again for that message and generation. */
31
+ const FINAL_WRITE_STATUSES = new Set([400, 403, 404, 409]);
32
+
33
+ const generationCache = new Map<string, { loadedAt: number; generation: Promise<number | undefined> }>();
34
+ /** `messageUid:generation` for every write sent (or in flight) this session. */
35
+ const attemptedWrites = new Set<string>();
36
+ /** Seals this session stored, by message uid. */
37
+ const storedSeals = new Map<string, SealToWrite>();
38
+
39
+ let lockSubscribed = false;
40
+
41
+ /** Forgets the cached vault generations and this session's seal writes - in tests. */
42
+ export function clearVerificationSealCache(): void {
43
+ generationCache.clear();
44
+ attemptedWrites.clear();
45
+ storedSeals.clear();
46
+ }
47
+
48
+ function subscribeToLocksOnce(): void {
49
+ if (lockSubscribed) {
50
+ return;
51
+ }
52
+ lockSubscribed = true;
53
+ subscribeKeySession((event) => {
54
+ if (event.state === "locked") {
55
+ generationCache.clear();
56
+ }
57
+ });
58
+ }
59
+
60
+ /** Reads `mailboxUid`'s current vault `masterKeyGeneration`, uncached: `undefined` when the vault can't be read or
61
+ * reports none. Never rejects. */
62
+ export async function readVaultGeneration(mailboxUid: string): Promise<number | undefined> {
63
+ try {
64
+ const { masterKeyGeneration } = await getKeyVault(mailboxUid);
65
+ return Number.isSafeInteger(masterKeyGeneration) && masterKeyGeneration! >= 0 ? masterKeyGeneration : undefined;
66
+ } catch {
67
+ return undefined;
68
+ }
69
+ }
70
+
71
+ /** `mailboxUid`'s current vault `masterKeyGeneration`, or `undefined` when it can't be read. Never rejects. */
72
+ export function getVaultGeneration(mailboxUid: string): Promise<number | undefined> {
73
+ subscribeToLocksOnce();
74
+ const entry = generationCache.get(mailboxUid);
75
+ if (entry && Date.now() - entry.loadedAt <= VAULT_GENERATION_TTL_MS) {
76
+ return entry.generation;
77
+ }
78
+ const created = { loadedAt: Date.now(), generation: readVaultGeneration(mailboxUid) };
79
+ generationCache.set(mailboxUid, created);
80
+ void created.generation.then((generation) => {
81
+ // Only a readable generation is reused; an unavailable one is read again next time.
82
+ if (generation === undefined && generationCache.get(mailboxUid) === created) {
83
+ generationCache.delete(mailboxUid);
84
+ }
85
+ });
86
+ return created.generation;
87
+ }
88
+
89
+ /** The seal to check `message` against: the one this session stored for it when that is newer than the message's own
90
+ * copy (which may predate the write), else the message's `verificationSeal`/`verificationSealGeneration`. */
91
+ export function currentVerificationSeal(message: Pick<Message, "uid" | "verificationSeal" | "verificationSealGeneration">): {
92
+ seal?: string;
93
+ sealGeneration?: number;
94
+ } {
95
+ const stored = storedSeals.get(message.uid);
96
+ if (stored && (message.verificationSealGeneration === undefined || stored.masterKeyGeneration > message.verificationSealGeneration)) {
97
+ return { seal: stored.seal, sealGeneration: stored.masterKeyGeneration };
98
+ }
99
+ return { seal: message.verificationSeal, sealGeneration: message.verificationSealGeneration };
100
+ }
101
+
102
+ /** Whether `sendVerificationSeal()` would still send a seal for `messageUid` at `generation`. */
103
+ export function verificationSealPending(messageUid: string, generation: number): boolean {
104
+ return !attemptedWrites.has(`${messageUid}:${generation}`);
105
+ }
106
+
107
+ /** Stores `sealToWrite` on `messageUid`, best effort - see this module's doc comment. Resolves `true` when a request was
108
+ * sent, `false` when the write was skipped as already attempted. Never rejects. */
109
+ export async function sendVerificationSeal(messageUid: string, sealToWrite: SealToWrite): Promise<boolean> {
110
+ const key = `${messageUid}:${sealToWrite.masterKeyGeneration}`;
111
+ if (attemptedWrites.has(key)) {
112
+ return false;
113
+ }
114
+ attemptedWrites.add(key);
115
+ try {
116
+ await setMessageVerificationSeal(messageUid, sealToWrite.seal, sealToWrite.masterKeyGeneration);
117
+ storedSeals.set(messageUid, sealToWrite);
118
+ } catch (err) {
119
+ // `VerificationSealConflictError` is an `ApiRequestError` with status 409.
120
+ if (!(err instanceof ApiRequestError && FINAL_WRITE_STATUSES.has(err.status))) {
121
+ attemptedWrites.delete(key);
122
+ }
123
+ }
124
+ return true;
125
+ }
@@ -0,0 +1,101 @@
1
+ ///////////////////////////////////////////////////////////////////////////////
2
+ // Copyright (C) 2026 Jean-Philippe Steinmetz
3
+ // SPDX-License-Identifier: MPL-2.0
4
+ ///////////////////////////////////////////////////////////////////////////////
5
+ /**
6
+ * Which of the caller's accessible mailboxes they can actually create things in (send from, create
7
+ * events/contacts/to-dos in). `listMailboxes()` returns view-only shares too, and `Mailbox` itself carries
8
+ * no per-caller access role, so a "viewer" delegate used to be offered mailboxes every create would 403 in.
9
+ *
10
+ * The signal: an owned mailbox (or any mailbox, for a trusted caller) is always writable; for any other,
11
+ * `getMyMailboxAccess()`'s `canCreate` - the server's own ACL evaluation of the exact action a create needs.
12
+ * One request per mailbox per page load: results are cached in a module-level map, with concurrent callers
13
+ * sharing one in-flight request. A failure (network, an older server without that route) is "unknown" and
14
+ * isn't cached: the server still enforces access on the create itself, and hiding a usable mailbox over a
15
+ * transient error would be worse than offering one that later errors.
16
+ *
17
+ * Nothing waits on these checks: pickers list every mailbox straight away and drop view-only ones as each
18
+ * answer arrives.
19
+ */
20
+ import { useEffect, useMemo, useState } from "react";
21
+ import type { Mailbox } from "@rapidmx/react-shared/mail/mailApi.js";
22
+ import { getMyMailboxAccess } from "@rapidmx/react-shared/mail/mailboxAccessApi.js";
23
+
24
+ /** `true` writable, `false` known view-only, `undefined` couldn't tell (treated as writable). */
25
+ export type MailboxWritability = boolean | undefined;
26
+
27
+ const inFlight = new Map<string, Promise<MailboxWritability>>();
28
+ const settled = new Map<string, boolean>();
29
+
30
+ /** Forgets every cached answer - for tests, and anything that changes the caller's access mid-session. */
31
+ export function clearMailboxWritabilityCache(): void {
32
+ inFlight.clear();
33
+ settled.clear();
34
+ }
35
+
36
+ function isImplicitlyWritable(mailbox: Mailbox, userUid: string | undefined, trusted: boolean | undefined): boolean {
37
+ return !!trusted || (!!userUid && mailbox.ownerUserUid === userUid);
38
+ }
39
+
40
+ /** The already-known answer for `mailbox`, without making a request. */
41
+ export function peekMailboxWritability(mailbox: Mailbox, userUid: string | undefined, trusted?: boolean): MailboxWritability {
42
+ return isImplicitlyWritable(mailbox, userUid, trusted) ? true : settled.get(mailbox.uid);
43
+ }
44
+
45
+ /** Whether the caller can create items in `mailbox`. Never rejects. */
46
+ export function getMailboxWritability(mailbox: Mailbox, userUid: string | undefined, trusted?: boolean): Promise<MailboxWritability> {
47
+ const known = peekMailboxWritability(mailbox, userUid, trusted);
48
+ if (known !== undefined) {
49
+ return Promise.resolve(known);
50
+ }
51
+ let request = inFlight.get(mailbox.uid);
52
+ if (!request) {
53
+ request = getMyMailboxAccess(mailbox.uid).then(
54
+ (access) => {
55
+ settled.set(mailbox.uid, access.canCreate);
56
+ inFlight.delete(mailbox.uid);
57
+ return access.canCreate;
58
+ },
59
+ () => {
60
+ // Not cached - a later check may succeed.
61
+ inFlight.delete(mailbox.uid);
62
+ return undefined;
63
+ },
64
+ );
65
+ inFlight.set(mailbox.uid, request);
66
+ }
67
+ return request;
68
+ }
69
+
70
+ /** Per-mailbox writability answers for `mailboxes`, filled in as each one arrives (already-known answers are
71
+ * present from the first render). */
72
+ export function useMailboxWritability(mailboxes: Mailbox[], userUid: string | undefined, trusted?: boolean): Record<string, MailboxWritability> {
73
+ const [answers, setAnswers] = useState<Record<string, MailboxWritability>>({});
74
+ useEffect(() => {
75
+ let cancelled = false;
76
+ for (const mailbox of mailboxes) {
77
+ void getMailboxWritability(mailbox, userUid, trusted).then((writable) => {
78
+ if (!cancelled) {
79
+ setAnswers((prev) => ({ ...prev, [mailbox.uid]: writable }));
80
+ }
81
+ });
82
+ }
83
+ return () => {
84
+ cancelled = true;
85
+ };
86
+ }, [mailboxes, userUid, trusted]);
87
+ return useMemo(() => {
88
+ const merged: Record<string, MailboxWritability> = {};
89
+ for (const mailbox of mailboxes) {
90
+ merged[mailbox.uid] = answers[mailbox.uid] ?? peekMailboxWritability(mailbox, userUid, trusted);
91
+ }
92
+ return merged;
93
+ }, [answers, mailboxes, userUid, trusted]);
94
+ }
95
+
96
+ /** `mailboxes` minus any known to be view-only, always keeping `keepUid` (the picker's current/default value,
97
+ * so the control never shows a value missing from its own options). Lists everything until told otherwise. */
98
+ export function useWritableMailboxes(mailboxes: Mailbox[], userUid: string | undefined, keepUid?: string, trusted?: boolean): Mailbox[] {
99
+ const writability = useMailboxWritability(mailboxes, userUid, trusted);
100
+ return useMemo(() => mailboxes.filter((mb) => mb.uid === keepUid || writability[mb.uid] !== false), [mailboxes, writability, keepUid]);
101
+ }