@arbidocs/react 0.5.110 → 0.5.112

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 (1011) hide show
  1. package/dist/PdfViewerImpl-QUSDLNNM.cjs +380 -0
  2. package/dist/PdfViewerImpl-QUSDLNNM.cjs.map +1 -0
  3. package/dist/{PdfViewer.d-bQH9yxFg.d.cts → PdfViewerImpl.d-B28hLEuj.d.ts} +8 -1
  4. package/dist/account/client.js +96 -0
  5. package/dist/account/client.js.map +7 -0
  6. package/dist/account/delete.js +70 -0
  7. package/dist/account/delete.js.map +7 -0
  8. package/dist/account/didit.js +34 -0
  9. package/dist/account/didit.js.map +7 -0
  10. package/dist/account/dismissed-tips.js +33 -0
  11. package/dist/account/dismissed-tips.js.map +7 -0
  12. package/dist/account/email.js +84 -0
  13. package/dist/account/email.js.map +7 -0
  14. package/dist/account/entitlements.js +47 -0
  15. package/dist/account/entitlements.js.map +7 -0
  16. package/dist/account/identity.js +270 -0
  17. package/dist/account/identity.js.map +7 -0
  18. package/dist/account/index.js +93 -0
  19. package/dist/account/index.js.map +7 -0
  20. package/dist/account/notifications.js +59 -0
  21. package/dist/account/notifications.js.map +7 -0
  22. package/dist/account/password.js +103 -0
  23. package/dist/account/password.js.map +7 -0
  24. package/dist/account/profile.js +116 -0
  25. package/dist/account/profile.js.map +7 -0
  26. package/dist/account/recovery.js +13 -0
  27. package/dist/account/recovery.js.map +7 -0
  28. package/dist/account/relevance.js +82 -0
  29. package/dist/account/relevance.js.map +7 -0
  30. package/dist/account/sessions.js +37 -0
  31. package/dist/account/sessions.js.map +7 -0
  32. package/dist/account/settings.js +39 -0
  33. package/dist/account/settings.js.map +7 -0
  34. package/dist/account/table-views.js +16 -0
  35. package/dist/account/table-views.js.map +7 -0
  36. package/dist/ai/AiAnswer.js +83 -0
  37. package/dist/ai/AiAnswer.js.map +7 -0
  38. package/dist/ai/AiMarkdown.js +40 -0
  39. package/dist/ai/AiMarkdown.js.map +7 -0
  40. package/dist/ai/ArtifactCanvas.js +193 -0
  41. package/dist/ai/ArtifactCanvas.js.map +7 -0
  42. package/dist/ai/CitationRenderer.js +413 -0
  43. package/dist/ai/CitationRenderer.js.map +7 -0
  44. package/dist/{chunk-WL2Y2T47.js → ai/MarkdownRenderer.js} +35 -101
  45. package/dist/ai/MarkdownRenderer.js.map +7 -0
  46. package/dist/ai/MessageArtifactCard.js +75 -0
  47. package/dist/ai/MessageArtifactCard.js.map +7 -0
  48. package/dist/ai/PassageCard.js +79 -0
  49. package/dist/ai/PassageCard.js.map +7 -0
  50. package/dist/ai/engine.js +110 -0
  51. package/dist/ai/engine.js.map +7 -0
  52. package/dist/ai/index.js +63 -0
  53. package/dist/ai/index.js.map +7 -0
  54. package/dist/ai/markdown-base-components.js +37 -0
  55. package/dist/ai/markdown-base-components.js.map +7 -0
  56. package/dist/ai/markdown-streaming-context.js +6 -0
  57. package/dist/ai/markdown-streaming-context.js.map +7 -0
  58. package/dist/{chunk-VSCU7K4V.js → ai/normalize-citations.js} +12 -19
  59. package/dist/ai/normalize-citations.js.map +7 -0
  60. package/dist/ai/redline.js +41 -0
  61. package/dist/ai/redline.js.map +7 -0
  62. package/dist/ai/split-markdown-blocks.js +40 -0
  63. package/dist/ai/split-markdown-blocks.js.map +7 -0
  64. package/dist/{chunk-UW2SGTI5.js → ai/stored-markdown.js} +41 -93
  65. package/dist/ai/stored-markdown.js.map +7 -0
  66. package/dist/annotations/AnnotationPageOverlay.js +807 -0
  67. package/dist/annotations/AnnotationPageOverlay.js.map +7 -0
  68. package/dist/annotations/AnnotationToolbar.js +398 -0
  69. package/dist/annotations/AnnotationToolbar.js.map +7 -0
  70. package/dist/annotations/FreezeDialog.js +170 -0
  71. package/dist/annotations/FreezeDialog.js.map +7 -0
  72. package/dist/annotations/ProductionDialog.js +354 -0
  73. package/dist/annotations/ProductionDialog.js.map +7 -0
  74. package/dist/annotations/controller.js +49 -0
  75. package/dist/annotations/controller.js.map +7 -0
  76. package/dist/annotations/freeze/browser.js +21 -0
  77. package/dist/annotations/freeze/browser.js.map +7 -0
  78. package/dist/annotations/freeze/bundle.js +201 -0
  79. package/dist/annotations/freeze/bundle.js.map +7 -0
  80. package/dist/annotations/freeze/coords.js +37 -0
  81. package/dist/annotations/freeze/coords.js.map +7 -0
  82. package/dist/annotations/freeze/freeze.js +261 -0
  83. package/dist/annotations/freeze/freeze.js.map +7 -0
  84. package/dist/annotations/freeze/hash.js +28 -0
  85. package/dist/annotations/freeze/hash.js.map +7 -0
  86. package/dist/annotations/freeze/index-page.js +78 -0
  87. package/dist/annotations/freeze/index-page.js.map +7 -0
  88. package/dist/annotations/freeze/index.d.ts +1 -1
  89. package/dist/annotations/freeze/index.js +28 -22
  90. package/dist/annotations/freeze/index.js.map +7 -1
  91. package/dist/annotations/freeze/raster.js +208 -0
  92. package/dist/annotations/freeze/raster.js.map +7 -0
  93. package/dist/annotations/freeze/stamp.js +117 -0
  94. package/dist/annotations/freeze/stamp.js.map +7 -0
  95. package/dist/annotations/freeze/types.js +14 -0
  96. package/dist/annotations/freeze/types.js.map +7 -0
  97. package/dist/annotations/freeze/vector.js +283 -0
  98. package/dist/annotations/freeze/vector.js.map +7 -0
  99. package/dist/annotations/geometry.js +81 -0
  100. package/dist/annotations/geometry.js.map +7 -0
  101. package/dist/annotations/index.js +125 -6
  102. package/dist/annotations/index.js.map +7 -1
  103. package/dist/annotations/merge.js +53 -0
  104. package/dist/annotations/merge.js.map +7 -0
  105. package/dist/{chunk-T3USOSVN.js → annotations/model.js} +23 -16
  106. package/dist/annotations/model.js.map +7 -0
  107. package/dist/annotations/overlay-geometry.js +41 -0
  108. package/dist/annotations/overlay-geometry.js.map +7 -0
  109. package/dist/annotations/redaction-log.js +33 -0
  110. package/dist/annotations/redaction-log.js.map +7 -0
  111. package/dist/annotations/selection-marks.js +122 -0
  112. package/dist/annotations/selection-marks.js.map +7 -0
  113. package/dist/annotations/state.js +140 -0
  114. package/dist/annotations/state.js.map +7 -0
  115. package/dist/annotations/store.js +49 -0
  116. package/dist/annotations/store.js.map +7 -0
  117. package/dist/annotations/useAnnotationLayer.js +306 -0
  118. package/dist/annotations/useAnnotationLayer.js.map +7 -0
  119. package/dist/annotations/useAnnotationShortcuts.js +31 -0
  120. package/dist/annotations/useAnnotationShortcuts.js.map +7 -0
  121. package/dist/annotations/useTextSelectionMarks.js +100 -0
  122. package/dist/annotations/useTextSelectionMarks.js.map +7 -0
  123. package/dist/artifacts/artifact-kind.js +19 -0
  124. package/dist/artifacts/artifact-kind.js.map +7 -0
  125. package/dist/artifacts/index.cjs +13 -13
  126. package/dist/artifacts/index.js +89 -571
  127. package/dist/artifacts/index.js.map +7 -1
  128. package/dist/{chunk-WUTL62MC.js → artifacts/normalize-markdown.js} +12 -14
  129. package/dist/artifacts/normalize-markdown.js.map +7 -0
  130. package/dist/artifacts/redline-core.js +12 -3
  131. package/dist/artifacts/redline-core.js.map +7 -1
  132. package/dist/{chunk-74N436VK.js → artifacts/redline-diff.js} +10 -9
  133. package/dist/artifacts/redline-diff.js.map +7 -0
  134. package/dist/artifacts/redline-engine.js +14 -0
  135. package/dist/artifacts/redline-engine.js.map +7 -0
  136. package/dist/artifacts/renderArtifactMarkdown.js +9 -0
  137. package/dist/artifacts/renderArtifactMarkdown.js.map +7 -0
  138. package/dist/artifacts/useArtifactEditSession.js +183 -0
  139. package/dist/artifacts/useArtifactEditSession.js.map +7 -0
  140. package/dist/artifacts/useArtifactSession.js +173 -0
  141. package/dist/artifacts/useArtifactSession.js.map +7 -0
  142. package/dist/artifacts/useArtifactSource.js +16 -0
  143. package/dist/artifacts/useArtifactSource.js.map +7 -0
  144. package/dist/artifacts/useArtifactText.js +78 -0
  145. package/dist/artifacts/useArtifactText.js.map +7 -0
  146. package/dist/artifacts/useRedline.js +65 -0
  147. package/dist/artifacts/useRedline.js.map +7 -0
  148. package/dist/artifacts/useStreamedArtifact.js +74 -0
  149. package/dist/artifacts/useStreamedArtifact.js.map +7 -0
  150. package/dist/artifacts/versions.js +68 -0
  151. package/dist/artifacts/versions.js.map +7 -0
  152. package/dist/billing.js +200 -0
  153. package/dist/billing.js.map +7 -0
  154. package/dist/boot-timeout.js +19 -0
  155. package/dist/boot-timeout.js.map +7 -0
  156. package/dist/calendar/accounts.js +213 -0
  157. package/dist/calendar/accounts.js.map +7 -0
  158. package/dist/calendar/hooks.js +409 -0
  159. package/dist/calendar/hooks.js.map +7 -0
  160. package/dist/calendar/index.js +31 -0
  161. package/dist/calendar/index.js.map +7 -0
  162. package/dist/calendar/keys.js +5 -0
  163. package/dist/calendar/keys.js.map +7 -0
  164. package/dist/calendar/offline/outbox.js +231 -0
  165. package/dist/calendar/offline/outbox.js.map +7 -0
  166. package/dist/calendar/offline/runtime.js +109 -0
  167. package/dist/calendar/offline/runtime.js.map +7 -0
  168. package/dist/calendar/offline/support.js +41 -0
  169. package/dist/calendar/offline/support.js.map +7 -0
  170. package/dist/calendar/support.js +34 -0
  171. package/dist/calendar/support.js.map +7 -0
  172. package/dist/calls/actions.js +226 -0
  173. package/dist/calls/actions.js.map +7 -0
  174. package/dist/calls/events.js +138 -0
  175. package/dist/calls/events.js.map +7 -0
  176. package/dist/calls/gate.js +19 -0
  177. package/dist/calls/gate.js.map +7 -0
  178. package/dist/calls/hooks.js +115 -0
  179. package/dist/calls/hooks.js.map +7 -0
  180. package/dist/calls/in-call-chat.js +132 -0
  181. package/dist/calls/in-call-chat.js.map +7 -0
  182. package/dist/calls/index.js +24 -0
  183. package/dist/calls/index.js.map +7 -0
  184. package/dist/calls/keys.js +17 -0
  185. package/dist/calls/keys.js.map +7 -0
  186. package/dist/calls/livekit/index.cjs +48 -48
  187. package/dist/calls/livekit/index.js +6 -958
  188. package/dist/calls/livekit/index.js.map +7 -1
  189. package/dist/calls/livekit/room.js +98 -0
  190. package/dist/calls/livekit/room.js.map +7 -0
  191. package/dist/calls/livekit/useCallRecorder.js +219 -0
  192. package/dist/calls/livekit/useCallRecorder.js.map +7 -0
  193. package/dist/calls/livekit/useCallTranscriber.js +309 -0
  194. package/dist/calls/livekit/useCallTranscriber.js.map +7 -0
  195. package/dist/calls/livekit/useHostMuteNotice.js +29 -0
  196. package/dist/calls/livekit/useHostMuteNotice.js.map +7 -0
  197. package/dist/calls/livekit/useInCallChat.js +161 -0
  198. package/dist/calls/livekit/useInCallChat.js.map +7 -0
  199. package/dist/calls/livekit/useWebinar.js +239 -0
  200. package/dist/calls/livekit/useWebinar.js.map +7 -0
  201. package/dist/calls/meeting-chat.js +149 -0
  202. package/dist/calls/meeting-chat.js.map +7 -0
  203. package/dist/calls/moderation.js +50 -0
  204. package/dist/calls/moderation.js.map +7 -0
  205. package/dist/calls/open-meeting-chat.js +29 -0
  206. package/dist/calls/open-meeting-chat.js.map +7 -0
  207. package/dist/calls/read-only.js +24 -0
  208. package/dist/calls/read-only.js.map +7 -0
  209. package/dist/calls/recording-media.js +218 -0
  210. package/dist/calls/recording-media.js.map +7 -0
  211. package/dist/calls/recording-playback.js +260 -0
  212. package/dist/calls/recording-playback.js.map +7 -0
  213. package/dist/calls/recording.js +268 -0
  214. package/dist/calls/recording.js.map +7 -0
  215. package/dist/calls/save-to-thread.js +80 -0
  216. package/dist/calls/save-to-thread.js.map +7 -0
  217. package/dist/calls/session.js +134 -0
  218. package/dist/calls/session.js.map +7 -0
  219. package/dist/calls/transcript-format.js +147 -0
  220. package/dist/calls/transcript-format.js.map +7 -0
  221. package/dist/calls/transcription.js +101 -0
  222. package/dist/calls/transcription.js.map +7 -0
  223. package/dist/calls/webinar.js +71 -0
  224. package/dist/calls/webinar.js.map +7 -0
  225. package/dist/charge-watch.js +71 -0
  226. package/dist/charge-watch.js.map +7 -0
  227. package/dist/chat/ChatBubble.js +146 -0
  228. package/dist/chat/ChatBubble.js.map +7 -0
  229. package/dist/chat/ConversationScope.js +30 -0
  230. package/dist/chat/ConversationScope.js.map +7 -0
  231. package/dist/chat/active-config.js +20 -0
  232. package/dist/chat/active-config.js.map +7 -0
  233. package/dist/chat/agent-chat-owner.js +25 -0
  234. package/dist/chat/agent-chat-owner.js.map +7 -0
  235. package/dist/chat/chat-artifacts.js +64 -0
  236. package/dist/chat/chat-artifacts.js.map +7 -0
  237. package/dist/chat/citations.js +32 -0
  238. package/dist/chat/citations.js.map +7 -0
  239. package/dist/chat/config-model.js +10 -0
  240. package/dist/chat/config-model.js.map +7 -0
  241. package/dist/chat/conversation-cache.js +676 -0
  242. package/dist/chat/conversation-cache.js.map +7 -0
  243. package/dist/chat/conversation-events.js +57 -0
  244. package/dist/chat/conversation-events.js.map +7 -0
  245. package/dist/chat/conversation-mentions.js +58 -0
  246. package/dist/chat/conversation-mentions.js.map +7 -0
  247. package/dist/chat/conversation-workspace.js +58 -0
  248. package/dist/chat/conversation-workspace.js.map +7 -0
  249. package/dist/chat/mentions.js +116 -0
  250. package/dist/chat/mentions.js.map +7 -0
  251. package/dist/chat/open-document.js +106 -0
  252. package/dist/chat/open-document.js.map +7 -0
  253. package/dist/chat/orphaned.js +44 -0
  254. package/dist/chat/orphaned.js.map +7 -0
  255. package/dist/chat/pendingFirstTurn.js +30 -0
  256. package/dist/chat/pendingFirstTurn.js.map +7 -0
  257. package/dist/chat/reply-target.js +12 -0
  258. package/dist/chat/reply-target.js.map +7 -0
  259. package/dist/chat/run-finished.js +28 -0
  260. package/dist/chat/run-finished.js.map +7 -0
  261. package/dist/chat/run-state.js +91 -0
  262. package/dist/chat/run-state.js.map +7 -0
  263. package/dist/chat/stream-handlers.js +419 -0
  264. package/dist/chat/stream-handlers.js.map +7 -0
  265. package/dist/chat/thread-binding.js +76 -0
  266. package/dist/chat/thread-binding.js.map +7 -0
  267. package/dist/chat/thread-document.js +53 -0
  268. package/dist/chat/thread-document.js.map +7 -0
  269. package/dist/chat/turn-control.js +79 -0
  270. package/dist/chat/turn-control.js.map +7 -0
  271. package/dist/chat/useAgentRunControl.js +36 -0
  272. package/dist/chat/useAgentRunControl.js.map +7 -0
  273. package/dist/chat/useAnswerAgentQuestion.js +19 -0
  274. package/dist/chat/useAnswerAgentQuestion.js.map +7 -0
  275. package/dist/chat/useAskAgain.js +32 -0
  276. package/dist/chat/useAskAgain.js.map +7 -0
  277. package/dist/chat/useAutoSendDraft.js +17 -0
  278. package/dist/chat/useAutoSendDraft.js.map +7 -0
  279. package/dist/chat/useBranchNavigation.js +97 -0
  280. package/dist/chat/useBranchNavigation.js.map +7 -0
  281. package/dist/chat/useConnectRunStream.js +169 -0
  282. package/dist/chat/useConnectRunStream.js.map +7 -0
  283. package/dist/chat/useConversation.js +431 -0
  284. package/dist/chat/useConversation.js.map +7 -0
  285. package/dist/chat/useConversationActions.js +662 -0
  286. package/dist/chat/useConversationActions.js.map +7 -0
  287. package/dist/chat/useConversationData.js +143 -0
  288. package/dist/chat/useConversationData.js.map +7 -0
  289. package/dist/chat/useConversationDocuments.js +41 -0
  290. package/dist/chat/useConversationDocuments.js.map +7 -0
  291. package/dist/chat/useConversationSettings.js +78 -0
  292. package/dist/chat/useConversationSettings.js.map +7 -0
  293. package/dist/chat/useConversationTurn.js +31 -0
  294. package/dist/chat/useConversationTurn.js.map +7 -0
  295. package/dist/chat/useConversationWorkspace.js +12 -0
  296. package/dist/chat/useConversationWorkspace.js.map +7 -0
  297. package/dist/chat/useDeleteMessage.js +15 -0
  298. package/dist/chat/useDeleteMessage.js.map +7 -0
  299. package/dist/chat/useDocumentAutoAdd.js +73 -0
  300. package/dist/chat/useDocumentAutoAdd.js.map +7 -0
  301. package/dist/chat/useMessageTimer.js +39 -0
  302. package/dist/chat/useMessageTimer.js.map +7 -0
  303. package/dist/chat/useThinkingContent.js +67 -0
  304. package/dist/chat/useThinkingContent.js.map +7 -0
  305. package/dist/chat/useThreadDocument.js +61 -0
  306. package/dist/chat/useThreadDocument.js.map +7 -0
  307. package/dist/chat/workflow-run-titles.js +50 -0
  308. package/dist/chat/workflow-run-titles.js.map +7 -0
  309. package/dist/{chunk-W2FATOTX.cjs → chunk-3JAEX57E.cjs} +4 -4
  310. package/dist/{chunk-W2FATOTX.cjs.map → chunk-3JAEX57E.cjs.map} +1 -1
  311. package/dist/{chunk-HD5H2PPP.cjs → chunk-5TRUFWKT.cjs} +66 -66
  312. package/dist/{chunk-HD5H2PPP.cjs.map → chunk-5TRUFWKT.cjs.map} +1 -1
  313. package/dist/{chunk-Z3W4XFWB.cjs → chunk-C72FSQUE.cjs} +3 -3
  314. package/dist/{chunk-Z3W4XFWB.cjs.map → chunk-C72FSQUE.cjs.map} +1 -1
  315. package/dist/{chunk-LBAG7KL7.cjs → chunk-FQVNZCTD.cjs} +3 -3
  316. package/dist/{chunk-LBAG7KL7.cjs.map → chunk-FQVNZCTD.cjs.map} +1 -1
  317. package/dist/{chunk-RVUGSM65.cjs → chunk-GKGAPU6T.cjs} +44 -44
  318. package/dist/{chunk-RVUGSM65.cjs.map → chunk-GKGAPU6T.cjs.map} +1 -1
  319. package/dist/{chunk-7LIMHY56.cjs → chunk-O32T7XRD.cjs} +3 -3
  320. package/dist/{chunk-7LIMHY56.cjs.map → chunk-O32T7XRD.cjs.map} +1 -1
  321. package/dist/chunk-PWGSIM3F.cjs +291 -0
  322. package/dist/chunk-PWGSIM3F.cjs.map +1 -0
  323. package/dist/chunk-QP3WQSAA.cjs +23 -0
  324. package/dist/chunk-QP3WQSAA.cjs.map +1 -0
  325. package/dist/chunk-T5FZICXN.cjs +50 -0
  326. package/dist/chunk-T5FZICXN.cjs.map +1 -0
  327. package/dist/{chunk-QF2BW6HZ.cjs → chunk-UDDJIUHJ.cjs} +38 -38
  328. package/dist/{chunk-QF2BW6HZ.cjs.map → chunk-UDDJIUHJ.cjs.map} +1 -1
  329. package/dist/{chunk-5HDKL6XB.cjs → chunk-YMB6XUR2.cjs} +57 -57
  330. package/dist/{chunk-5HDKL6XB.cjs.map → chunk-YMB6XUR2.cjs.map} +1 -1
  331. package/dist/config/config-hooks.js +209 -0
  332. package/dist/config/config-hooks.js.map +7 -0
  333. package/dist/connectivity.js +72 -0
  334. package/dist/connectivity.js.map +7 -0
  335. package/dist/connectors/hooks.js +263 -0
  336. package/dist/connectors/hooks.js.map +7 -0
  337. package/dist/connectors/index.js +28 -0
  338. package/dist/connectors/index.js.map +7 -0
  339. package/dist/contacts.js +100 -0
  340. package/dist/contacts.js.map +7 -0
  341. package/dist/conversation-list.js +65 -0
  342. package/dist/conversation-list.js.map +7 -0
  343. package/dist/databases.js +195 -0
  344. package/dist/databases.js.map +7 -0
  345. package/dist/datasets/aggregate.js +281 -0
  346. package/dist/datasets/aggregate.js.map +7 -0
  347. package/dist/datasets/index.js +122 -0
  348. package/dist/datasets/index.js.map +7 -0
  349. package/dist/datasets/members.js +27 -0
  350. package/dist/datasets/members.js.map +7 -0
  351. package/dist/datasets/panel.js +44 -0
  352. package/dist/datasets/panel.js.map +7 -0
  353. package/dist/datasets/registry.js +47 -0
  354. package/dist/datasets/registry.js.map +7 -0
  355. package/dist/datasets/rows-source.js +44 -0
  356. package/dist/datasets/rows-source.js.map +7 -0
  357. package/dist/datasets/sources/activity.js +83 -0
  358. package/dist/datasets/sources/activity.js.map +7 -0
  359. package/dist/datasets/sources/conversations.js +74 -0
  360. package/dist/datasets/sources/conversations.js.map +7 -0
  361. package/dist/datasets/sources/database.js +209 -0
  362. package/dist/datasets/sources/database.js.map +7 -0
  363. package/dist/datasets/sources/documents.js +93 -0
  364. package/dist/datasets/sources/documents.js.map +7 -0
  365. package/dist/datasets/sources/facts.js +56 -0
  366. package/dist/datasets/sources/facts.js.map +7 -0
  367. package/dist/datasets/sources/projects.js +117 -0
  368. package/dist/datasets/sources/projects.js.map +7 -0
  369. package/dist/datasets/sources/tags.js +67 -0
  370. package/dist/datasets/sources/tags.js.map +7 -0
  371. package/dist/datasets/sources/usage.js +268 -0
  372. package/dist/datasets/sources/usage.js.map +7 -0
  373. package/dist/datasets/sources/workflows.js +91 -0
  374. package/dist/datasets/sources/workflows.js.map +7 -0
  375. package/dist/datasets/sources/workspaces.js +67 -0
  376. package/dist/datasets/sources/workspaces.js.map +7 -0
  377. package/dist/datasets/store.js +194 -0
  378. package/dist/datasets/store.js.map +7 -0
  379. package/dist/datasets/types.js +14 -0
  380. package/dist/datasets/types.js.map +7 -0
  381. package/dist/directmessages/ConversationList.js +148 -0
  382. package/dist/directmessages/ConversationList.js.map +7 -0
  383. package/dist/directmessages/DateSeparator.js +8 -0
  384. package/dist/directmessages/DateSeparator.js.map +7 -0
  385. package/dist/directmessages/DmAvatar.js +29 -0
  386. package/dist/directmessages/DmAvatar.js.map +7 -0
  387. package/dist/directmessages/DmComposer.js +201 -0
  388. package/dist/directmessages/DmComposer.js.map +7 -0
  389. package/dist/directmessages/arrivals.js +29 -0
  390. package/dist/directmessages/arrivals.js.map +7 -0
  391. package/dist/directmessages/chat-cache.js +192 -0
  392. package/dist/directmessages/chat-cache.js.map +7 -0
  393. package/dist/directmessages/grouping.js +26 -0
  394. package/dist/directmessages/grouping.js.map +7 -0
  395. package/dist/directmessages/index.js +81 -0
  396. package/dist/directmessages/index.js.map +7 -0
  397. package/dist/directmessages/useChats.js +266 -0
  398. package/dist/directmessages/useChats.js.map +7 -0
  399. package/dist/directmessages/utils.js +23 -0
  400. package/dist/directmessages/utils.js.map +7 -0
  401. package/dist/document-tools/can-annotate.js +7 -0
  402. package/dist/document-tools/can-annotate.js.map +7 -0
  403. package/dist/document-tools/core.cjs +99 -99
  404. package/dist/document-tools/core.d.ts +2 -2
  405. package/dist/document-tools/core.js +218 -12
  406. package/dist/document-tools/core.js.map +7 -1
  407. package/dist/document-tools/document-pdf.js +76 -0
  408. package/dist/document-tools/document-pdf.js.map +7 -0
  409. package/dist/document-tools/environment.js +136 -0
  410. package/dist/document-tools/environment.js.map +7 -0
  411. package/dist/document-tools/file-shares.js +112 -0
  412. package/dist/document-tools/file-shares.js.map +7 -0
  413. package/dist/document-tools/frozen-copy.js +27 -0
  414. package/dist/document-tools/frozen-copy.js.map +7 -0
  415. package/dist/document-tools/index.cjs +101 -101
  416. package/dist/document-tools/index.d.ts +1 -1
  417. package/dist/document-tools/index.js +26 -148
  418. package/dist/document-tools/index.js.map +7 -1
  419. package/dist/document-tools/markup-download.js +51 -0
  420. package/dist/document-tools/markup-download.js.map +7 -0
  421. package/dist/document-tools/markup-store.js +138 -0
  422. package/dist/document-tools/markup-store.js.map +7 -0
  423. package/dist/document-tools/markup-transfer.js +88 -0
  424. package/dist/document-tools/markup-transfer.js.map +7 -0
  425. package/dist/document-tools/production.js +147 -0
  426. package/dist/document-tools/production.js.map +7 -0
  427. package/dist/document-tools/saved-signature.js +90 -0
  428. package/dist/document-tools/saved-signature.js.map +7 -0
  429. package/dist/document-tools/signature-requests.js +310 -0
  430. package/dist/document-tools/signature-requests.js.map +7 -0
  431. package/dist/document-tools/signing.js +127 -0
  432. package/dist/document-tools/signing.js.map +7 -0
  433. package/dist/document-tools/useDocumentBytes.js +38 -0
  434. package/dist/document-tools/useDocumentBytes.js.map +7 -0
  435. package/dist/document-tools/useDocumentMarkup.js +154 -0
  436. package/dist/document-tools/useDocumentMarkup.js.map +7 -0
  437. package/dist/document-tools/useIsOnline.js +13 -0
  438. package/dist/document-tools/useIsOnline.js.map +7 -0
  439. package/dist/document-tools/verification.js +60 -0
  440. package/dist/document-tools/verification.js.map +7 -0
  441. package/dist/documents/DocumentReview.js +220 -0
  442. package/dist/documents/DocumentReview.js.map +7 -0
  443. package/dist/documents/DraftTitleControls.js +41 -0
  444. package/dist/documents/DraftTitleControls.js.map +7 -0
  445. package/dist/documents/InlineMicButton.js +90 -0
  446. package/dist/documents/InlineMicButton.js.map +7 -0
  447. package/dist/documents/MicRecordingOverlay.js +29 -0
  448. package/dist/documents/MicRecordingOverlay.js.map +7 -0
  449. package/dist/documents/MicWaveformIndicator.js +68 -0
  450. package/dist/documents/MicWaveformIndicator.js.map +7 -0
  451. package/dist/documents/PhotoCapture.js +120 -0
  452. package/dist/documents/PhotoCapture.js.map +7 -0
  453. package/dist/documents/VideoCapture.js +129 -0
  454. package/dist/documents/VideoCapture.js.map +7 -0
  455. package/dist/documents/VoiceNoteRecorder.js +166 -0
  456. package/dist/documents/VoiceNoteRecorder.js.map +7 -0
  457. package/dist/documents/audio-segmenter.js +63 -0
  458. package/dist/documents/audio-segmenter.js.map +7 -0
  459. package/dist/documents/capture-frame.js +21 -0
  460. package/dist/documents/capture-frame.js.map +7 -0
  461. package/dist/documents/chunked-recorder.js +190 -0
  462. package/dist/documents/chunked-recorder.js.map +7 -0
  463. package/dist/documents/document-download.js +53 -0
  464. package/dist/documents/document-download.js.map +7 -0
  465. package/dist/documents/document-fields.js +109 -0
  466. package/dist/documents/document-fields.js.map +7 -0
  467. package/dist/documents/documents-cache.js +110 -0
  468. package/dist/documents/documents-cache.js.map +7 -0
  469. package/dist/documents/documents-data.js +128 -0
  470. package/dist/documents/documents-data.js.map +7 -0
  471. package/dist/documents/documents-loader.js +113 -0
  472. package/dist/documents/documents-loader.js.map +7 -0
  473. package/dist/documents/documents-writes.js +448 -0
  474. package/dist/documents/documents-writes.js.map +7 -0
  475. package/dist/documents/format-elapsed.js +10 -0
  476. package/dist/documents/format-elapsed.js.map +7 -0
  477. package/dist/documents/has-video-track.js +26 -0
  478. package/dist/documents/has-video-track.js.map +7 -0
  479. package/dist/documents/index.js +266 -0
  480. package/dist/documents/index.js.map +7 -0
  481. package/dist/documents/media-error.js +18 -0
  482. package/dist/documents/media-error.js.map +7 -0
  483. package/dist/documents/offline-documents.js +160 -0
  484. package/dist/documents/offline-documents.js.map +7 -0
  485. package/dist/documents/pending-sync.js +210 -0
  486. package/dist/documents/pending-sync.js.map +7 -0
  487. package/dist/documents/processing-live.js +122 -0
  488. package/dist/documents/processing-live.js.map +7 -0
  489. package/dist/documents/processing-order.js +59 -0
  490. package/dist/documents/processing-order.js.map +7 -0
  491. package/dist/documents/processing-settle.js +21 -0
  492. package/dist/documents/processing-settle.js.map +7 -0
  493. package/dist/documents/related-documents.js +133 -0
  494. package/dist/documents/related-documents.js.map +7 -0
  495. package/dist/documents/support.js +29 -0
  496. package/dist/documents/support.js.map +7 -0
  497. package/dist/documents/upload-files.js +169 -0
  498. package/dist/documents/upload-files.js.map +7 -0
  499. package/dist/documents/useAudioRecorder.js +315 -0
  500. package/dist/documents/useAudioRecorder.js.map +7 -0
  501. package/dist/documents/useCameraStream.js +35 -0
  502. package/dist/documents/useCameraStream.js.map +7 -0
  503. package/dist/documents/useDocumentThumbnails.js +71 -0
  504. package/dist/documents/useDocumentThumbnails.js.map +7 -0
  505. package/dist/documents/useDownloadDocuments.js +90 -0
  506. package/dist/documents/useDownloadDocuments.js.map +7 -0
  507. package/dist/documents/usePassageQuotes.js +37 -0
  508. package/dist/documents/usePassageQuotes.js.map +7 -0
  509. package/dist/documents/useUploadFiles.js +165 -0
  510. package/dist/documents/useUploadFiles.js.map +7 -0
  511. package/dist/documents/useUploadFromUrls.js +63 -0
  512. package/dist/documents/useUploadFromUrls.js.map +7 -0
  513. package/dist/documents/useVideoRecorder.js +62 -0
  514. package/dist/documents/useVideoRecorder.js.map +7 -0
  515. package/dist/entities/AgentMarkers.js +61 -0
  516. package/dist/entities/AgentMarkers.js.map +7 -0
  517. package/dist/entities/DocumentEntity.js +125 -0
  518. package/dist/entities/DocumentEntity.js.map +7 -0
  519. package/dist/entities/EntityPill.js +250 -0
  520. package/dist/entities/EntityPill.js.map +7 -0
  521. package/dist/entities/ProjectEntity.js +61 -0
  522. package/dist/entities/ProjectEntity.js.map +7 -0
  523. package/dist/entities/ShieldIcon.js +49 -0
  524. package/dist/entities/ShieldIcon.js.map +7 -0
  525. package/dist/entities/TagEntity.js +79 -0
  526. package/dist/entities/TagEntity.js.map +7 -0
  527. package/dist/entities/ThreadVisibilityIcon.js +15 -0
  528. package/dist/entities/ThreadVisibilityIcon.js.map +7 -0
  529. package/dist/entities/UserEntity.js +211 -0
  530. package/dist/entities/UserEntity.js.map +7 -0
  531. package/dist/entities/VerifiedBadge.js +19 -0
  532. package/dist/entities/VerifiedBadge.js.map +7 -0
  533. package/dist/entities/agent-avatar-colors.js +26 -0
  534. package/dist/entities/agent-avatar-colors.js.map +7 -0
  535. package/dist/entities/colors.js +64 -0
  536. package/dist/entities/colors.js.map +7 -0
  537. package/dist/entities/file-type.js +151 -0
  538. package/dist/entities/file-type.js.map +7 -0
  539. package/dist/entities/index.js +100 -0
  540. package/dist/entities/index.js.map +7 -0
  541. package/dist/entities/media-type.js +61 -0
  542. package/dist/entities/media-type.js.map +7 -0
  543. package/dist/entities/registry.js +385 -0
  544. package/dist/entities/registry.js.map +7 -0
  545. package/dist/entities/status.js +43 -0
  546. package/dist/entities/status.js.map +7 -0
  547. package/dist/entities/tag-kinds.js +23 -0
  548. package/dist/entities/tag-kinds.js.map +7 -0
  549. package/dist/entities/tag-types.js +44 -0
  550. package/dist/entities/tag-types.js.map +7 -0
  551. package/dist/entities/vocabulary.js +12 -0
  552. package/dist/entities/vocabulary.js.map +7 -0
  553. package/dist/entity-extraction.js +25 -0
  554. package/dist/entity-extraction.js.map +7 -0
  555. package/dist/facts-search.js +57 -0
  556. package/dist/facts-search.js.map +7 -0
  557. package/dist/facts.js +69 -0
  558. package/dist/facts.js.map +7 -0
  559. package/dist/hooks.js +320 -0
  560. package/dist/hooks.js.map +7 -0
  561. package/dist/host/ArbiHost.js +24 -0
  562. package/dist/host/ArbiHost.js.map +7 -0
  563. package/dist/host/assistant-copy.js +54 -0
  564. package/dist/host/assistant-copy.js.map +7 -0
  565. package/dist/host/config.js +9 -0
  566. package/dist/host/config.js.map +7 -0
  567. package/dist/host/context.js +10 -0
  568. package/dist/host/context.js.map +7 -0
  569. package/dist/host/features.js +144 -0
  570. package/dist/host/features.js.map +7 -0
  571. package/dist/host/index.js +12 -0
  572. package/dist/host/index.js.map +7 -0
  573. package/dist/{chunk-DPYBZDJB.js → host/merge.js} +7 -7
  574. package/dist/host/merge.js.map +7 -0
  575. package/dist/house-template.js +40 -0
  576. package/dist/house-template.js.map +7 -0
  577. package/dist/icons/AppleIcon.js +25 -0
  578. package/dist/icons/AppleIcon.js.map +7 -0
  579. package/dist/icons/ArbiBotHeadIcon.js +46 -0
  580. package/dist/icons/ArbiBotHeadIcon.js.map +7 -0
  581. package/dist/icons/ArbiIcon.js +24 -0
  582. package/dist/icons/ArbiIcon.js.map +7 -0
  583. package/dist/icons/AudIcon.js +56 -0
  584. package/dist/icons/AudIcon.js.map +7 -0
  585. package/dist/icons/ClaudeIcon.js +28 -0
  586. package/dist/icons/ClaudeIcon.js.map +7 -0
  587. package/dist/icons/DocIcon.js +56 -0
  588. package/dist/icons/DocIcon.js.map +7 -0
  589. package/dist/icons/EmlIcon.js +57 -0
  590. package/dist/icons/EmlIcon.js.map +7 -0
  591. package/dist/icons/FireworksIcon.js +47 -0
  592. package/dist/icons/FireworksIcon.js.map +7 -0
  593. package/dist/icons/GeminiIcon.js +37 -0
  594. package/dist/icons/GeminiIcon.js.map +7 -0
  595. package/dist/icons/GitHubIcon.js +32 -0
  596. package/dist/icons/GitHubIcon.js.map +7 -0
  597. package/dist/icons/GoogleIcon.js +53 -0
  598. package/dist/icons/GoogleIcon.js.map +7 -0
  599. package/dist/icons/HtmlIcon.js +56 -0
  600. package/dist/icons/HtmlIcon.js.map +7 -0
  601. package/dist/icons/ImgIcon.js +56 -0
  602. package/dist/icons/ImgIcon.js.map +7 -0
  603. package/dist/icons/LinkedInIcon.js +25 -0
  604. package/dist/icons/LinkedInIcon.js.map +7 -0
  605. package/dist/icons/OpenAIIcon.js +28 -0
  606. package/dist/icons/OpenAIIcon.js.map +7 -0
  607. package/dist/icons/PdfIcon.js +56 -0
  608. package/dist/icons/PdfIcon.js.map +7 -0
  609. package/dist/icons/ProviderIcon.js +42 -0
  610. package/dist/icons/ProviderIcon.js.map +7 -0
  611. package/dist/icons/TxtIcon.js +56 -0
  612. package/dist/icons/TxtIcon.js.map +7 -0
  613. package/dist/icons/VidIcon.js +56 -0
  614. package/dist/icons/VidIcon.js.map +7 -0
  615. package/dist/icons/XlsIcon.js +56 -0
  616. package/dist/icons/XlsIcon.js.map +7 -0
  617. package/dist/icons/arbi-mark.js +5 -0
  618. package/dist/icons/arbi-mark.js.map +7 -0
  619. package/dist/icons/colors.js +31 -0
  620. package/dist/icons/colors.js.map +7 -0
  621. package/dist/icons/file-type.js +105 -0
  622. package/dist/icons/file-type.js.map +7 -0
  623. package/dist/icons/index.js +55 -0
  624. package/dist/icons/index.js.map +7 -0
  625. package/dist/imagecrop/ImageCropModal.js +56 -0
  626. package/dist/imagecrop/ImageCropModal.js.map +7 -0
  627. package/dist/imagecrop/ImageCropper.js +100 -0
  628. package/dist/imagecrop/ImageCropper.js.map +7 -0
  629. package/dist/imagecrop/cropImage.js +43 -0
  630. package/dist/imagecrop/cropImage.js.map +7 -0
  631. package/dist/imagecrop/index.js +13 -0
  632. package/dist/imagecrop/index.js.map +7 -0
  633. package/dist/index.cjs +1689 -1619
  634. package/dist/index.cjs.map +1 -1
  635. package/dist/{index.d-BMhTH98a.d.ts → index.d-CYXcTKYt.d.ts} +1 -0
  636. package/dist/index.d.ts +38 -8
  637. package/dist/index.js +702 -17060
  638. package/dist/index.js.map +7 -1
  639. package/dist/lazy-chunk.d-B6YDLMKI.d.ts +31 -0
  640. package/dist/lazy-chunk.js +46 -0
  641. package/dist/lazy-chunk.js.map +7 -0
  642. package/dist/lib/collision-padding.js +13 -0
  643. package/dist/lib/collision-padding.js.map +7 -0
  644. package/dist/lib/format-friendly-date.js +55 -0
  645. package/dist/lib/format-friendly-date.js.map +7 -0
  646. package/dist/lib/format-relative-time.js +52 -0
  647. package/dist/lib/format-relative-time.js.map +7 -0
  648. package/dist/lib/markdown-to-text.js +35 -0
  649. package/dist/lib/markdown-to-text.js.map +7 -0
  650. package/dist/lib/toast-interaction.js +9 -0
  651. package/dist/lib/toast-interaction.js.map +7 -0
  652. package/dist/lib/utils.js +9 -0
  653. package/dist/lib/utils.js.map +7 -0
  654. package/dist/mail/client.js +103 -0
  655. package/dist/mail/client.js.map +7 -0
  656. package/dist/mail/document-attachment.js +38 -0
  657. package/dist/mail/document-attachment.js.map +7 -0
  658. package/dist/mail/filing.js +132 -0
  659. package/dist/mail/filing.js.map +7 -0
  660. package/dist/mail/hooks.js +393 -0
  661. package/dist/mail/hooks.js.map +7 -0
  662. package/dist/mail/index.js +120 -0
  663. package/dist/mail/index.js.map +7 -0
  664. package/dist/mail/offline/changes.js +258 -0
  665. package/dist/mail/offline/changes.js.map +7 -0
  666. package/dist/mail/offline/confirm-sign-out.js +37 -0
  667. package/dist/mail/offline/confirm-sign-out.js.map +7 -0
  668. package/dist/mail/offline/crypto.js +26 -0
  669. package/dist/mail/offline/crypto.js.map +7 -0
  670. package/dist/mail/offline/drafts.js +69 -0
  671. package/dist/mail/offline/drafts.js.map +7 -0
  672. package/dist/mail/offline/hooks.js +104 -0
  673. package/dist/mail/offline/hooks.js.map +7 -0
  674. package/dist/mail/offline/index.js +48 -0
  675. package/dist/mail/offline/index.js.map +7 -0
  676. package/dist/mail/offline/live.js +233 -0
  677. package/dist/mail/offline/live.js.map +7 -0
  678. package/dist/mail/offline/mailbox.js +191 -0
  679. package/dist/mail/offline/mailbox.js.map +7 -0
  680. package/dist/mail/offline/outbox.js +167 -0
  681. package/dist/mail/offline/outbox.js.map +7 -0
  682. package/dist/mail/offline/reads.js +159 -0
  683. package/dist/mail/offline/reads.js.map +7 -0
  684. package/dist/mail/offline/runtime.js +100 -0
  685. package/dist/mail/offline/runtime.js.map +7 -0
  686. package/dist/mail/offline/settings.js +84 -0
  687. package/dist/mail/offline/settings.js.map +7 -0
  688. package/dist/mail/offline/store.js +29 -0
  689. package/dist/mail/offline/store.js.map +7 -0
  690. package/dist/mail/offline/sync.js +251 -0
  691. package/dist/mail/offline/sync.js.map +7 -0
  692. package/dist/mail/offline/wipe.js +19 -0
  693. package/dist/mail/offline/wipe.js.map +7 -0
  694. package/dist/mail/thread-keys.js +53 -0
  695. package/dist/mail/thread-keys.js.map +7 -0
  696. package/dist/mail/threads.js +71 -0
  697. package/dist/mail/threads.js.map +7 -0
  698. package/dist/mail/useMailClient.js +42 -0
  699. package/dist/mail/useMailClient.js.map +7 -0
  700. package/dist/model-connections.js +58 -0
  701. package/dist/model-connections.js.map +7 -0
  702. package/dist/notifications/ActivityFeed.js +70 -0
  703. package/dist/notifications/ActivityFeed.js.map +7 -0
  704. package/dist/notifications/NotificationBell.js +200 -0
  705. package/dist/notifications/NotificationBell.js.map +7 -0
  706. package/dist/notifications/Toaster.js +24 -0
  707. package/dist/notifications/Toaster.js.map +7 -0
  708. package/dist/notifications/activity-types.js +65 -0
  709. package/dist/notifications/activity-types.js.map +7 -0
  710. package/dist/notifications/bell.js +24 -0
  711. package/dist/notifications/bell.js.map +7 -0
  712. package/dist/notifications/calendar-notifications.js +79 -0
  713. package/dist/notifications/calendar-notifications.js.map +7 -0
  714. package/dist/notifications/index.js +108 -0
  715. package/dist/notifications/index.js.map +7 -0
  716. package/dist/notifications/live.js +28 -0
  717. package/dist/notifications/live.js.map +7 -0
  718. package/dist/notifications/notification-types.js +127 -0
  719. package/dist/notifications/notification-types.js.map +7 -0
  720. package/dist/{chunk-BF5KW5ZI.js → notifications/notify-store.js} +24 -74
  721. package/dist/notifications/notify-store.js.map +7 -0
  722. package/dist/notifications/server-notifications.js +452 -0
  723. package/dist/notifications/server-notifications.js.map +7 -0
  724. package/dist/notifications/useNotifications.js +34 -0
  725. package/dist/notifications/useNotifications.js.map +7 -0
  726. package/dist/offline-store/network.js +11 -0
  727. package/dist/offline-store/network.js.map +7 -0
  728. package/dist/offline-store/store.js +136 -0
  729. package/dist/offline-store/store.js.map +7 -0
  730. package/dist/offline-store/wipe.js +8 -0
  731. package/dist/offline-store/wipe.js.map +7 -0
  732. package/dist/offline.js +58 -0
  733. package/dist/offline.js.map +7 -0
  734. package/dist/people.js +122 -0
  735. package/dist/people.js.map +7 -0
  736. package/dist/projects.js +30 -0
  737. package/dist/projects.js.map +7 -0
  738. package/dist/query-client.js +63 -0
  739. package/dist/query-client.js.map +7 -0
  740. package/dist/{query-keys.d-ChgpJLPF.d.ts → query-keys.d-B1Am9tIF.d.ts} +1 -1
  741. package/dist/{chunk-6H3O63TQ.js → query-keys.js} +19 -32
  742. package/dist/query-keys.js.map +7 -0
  743. package/dist/query-persist.js +66 -0
  744. package/dist/query-persist.js.map +7 -0
  745. package/dist/queued-writes.js +59 -0
  746. package/dist/queued-writes.js.map +7 -0
  747. package/dist/remote-control.js +67 -0
  748. package/dist/remote-control.js.map +7 -0
  749. package/dist/search/index.js +23 -0
  750. package/dist/search/index.js.map +7 -0
  751. package/dist/search/session.js +58 -0
  752. package/dist/search/session.js.map +7 -0
  753. package/dist/search/useSemanticSearch.js +82 -0
  754. package/dist/search/useSemanticSearch.js.map +7 -0
  755. package/dist/session/chat.js +512 -0
  756. package/dist/session/chat.js.map +7 -0
  757. package/dist/session/documents.js +196 -0
  758. package/dist/session/documents.js.map +7 -0
  759. package/dist/session/drafts.js +103 -0
  760. package/dist/session/drafts.js.map +7 -0
  761. package/dist/session/index.js +123 -0
  762. package/dist/session/index.js.map +7 -0
  763. package/dist/session/layout.js +339 -0
  764. package/dist/session/layout.js.map +7 -0
  765. package/dist/session/persist.js +106 -0
  766. package/dist/session/persist.js.map +7 -0
  767. package/dist/session/session-hooks.js +53 -0
  768. package/dist/session/session-hooks.js.map +7 -0
  769. package/dist/session/signed-in.js +36 -0
  770. package/dist/session/signed-in.js.map +7 -0
  771. package/dist/session/store.js +166 -0
  772. package/dist/session/store.js.map +7 -0
  773. package/dist/session/thread-tabs.js +121 -0
  774. package/dist/session/thread-tabs.js.map +7 -0
  775. package/dist/session/ui-state-storage.js +76 -0
  776. package/dist/session/ui-state-storage.js.map +7 -0
  777. package/dist/session/workspace.js +77 -0
  778. package/dist/session/workspace.js.map +7 -0
  779. package/dist/shell/index.cjs +37 -37
  780. package/dist/shell/index.js +43 -10
  781. package/dist/shell/index.js.map +7 -1
  782. package/dist/skill-pack.js +111 -0
  783. package/dist/skill-pack.js.map +7 -0
  784. package/dist/storage.js +186 -0
  785. package/dist/storage.js.map +7 -0
  786. package/dist/support/index.js +35 -0
  787. package/dist/support/index.js.map +7 -0
  788. package/dist/tags.js +204 -0
  789. package/dist/tags.js.map +7 -0
  790. package/dist/ui/DebouncedInput.js +109 -0
  791. package/dist/ui/DebouncedInput.js.map +7 -0
  792. package/dist/ui/DictateContext.js +8 -0
  793. package/dist/ui/DictateContext.js.map +7 -0
  794. package/dist/ui/IconToggle.js +79 -0
  795. package/dist/ui/IconToggle.js.map +7 -0
  796. package/dist/ui/VerifiedToggle.js +38 -0
  797. package/dist/ui/VerifiedToggle.js.map +7 -0
  798. package/dist/ui/VisibilityToggle.js +103 -0
  799. package/dist/ui/VisibilityToggle.js.map +7 -0
  800. package/dist/ui/avatar.js +40 -0
  801. package/dist/ui/avatar.js.map +7 -0
  802. package/dist/ui/badge.js +28 -0
  803. package/dist/ui/badge.js.map +7 -0
  804. package/dist/ui/button.js +48 -0
  805. package/dist/ui/button.js.map +7 -0
  806. package/dist/ui/card.js +90 -0
  807. package/dist/ui/card.js.map +7 -0
  808. package/dist/ui/checkbox.js +22 -0
  809. package/dist/ui/checkbox.js.map +7 -0
  810. package/dist/ui/collapsible.js +10 -0
  811. package/dist/ui/collapsible.js.map +7 -0
  812. package/dist/ui/command.js +103 -0
  813. package/dist/ui/command.js.map +7 -0
  814. package/dist/{chunk-YNNAJJ5Z.js → ui/dialog.js} +30 -68
  815. package/dist/ui/dialog.js.map +7 -0
  816. package/dist/{chunk-47CCGUWR.js → ui/dropdown-menu.js} +40 -45
  817. package/dist/ui/dropdown-menu.js.map +7 -0
  818. package/dist/ui/hover-card.js +36 -0
  819. package/dist/ui/hover-card.js.map +7 -0
  820. package/dist/ui/index.cjs +167 -154
  821. package/dist/ui/index.d.ts +2 -1
  822. package/dist/ui/index.js +290 -9
  823. package/dist/ui/index.js.map +7 -1
  824. package/dist/ui/input.js +65 -0
  825. package/dist/ui/input.js.map +7 -0
  826. package/dist/ui/label.js +16 -0
  827. package/dist/ui/label.js.map +7 -0
  828. package/dist/ui/mark-menu.js +300 -0
  829. package/dist/ui/mark-menu.js.map +7 -0
  830. package/dist/ui/popover.js +40 -0
  831. package/dist/ui/popover.js.map +7 -0
  832. package/dist/ui/portal-container.js +17 -0
  833. package/dist/ui/portal-container.js.map +7 -0
  834. package/dist/ui/progress.js +24 -0
  835. package/dist/ui/progress.js.map +7 -0
  836. package/dist/ui/radio-group.js +29 -0
  837. package/dist/ui/radio-group.js.map +7 -0
  838. package/dist/ui/scroll-area.js +39 -0
  839. package/dist/ui/scroll-area.js.map +7 -0
  840. package/dist/ui/select.js +130 -0
  841. package/dist/ui/select.js.map +7 -0
  842. package/dist/ui/separator.js +23 -0
  843. package/dist/ui/separator.js.map +7 -0
  844. package/dist/ui/slider.js +23 -0
  845. package/dist/ui/slider.js.map +7 -0
  846. package/dist/ui/switch.js +28 -0
  847. package/dist/ui/switch.js.map +7 -0
  848. package/dist/ui/table.js +75 -0
  849. package/dist/ui/table.js.map +7 -0
  850. package/dist/ui/tabs.js +48 -0
  851. package/dist/ui/tabs.js.map +7 -0
  852. package/dist/ui/textarea.js +63 -0
  853. package/dist/ui/textarea.js.map +7 -0
  854. package/dist/ui/toggle-group.js +43 -0
  855. package/dist/ui/toggle-group.js.map +7 -0
  856. package/dist/ui/toggle.js +40 -0
  857. package/dist/ui/toggle.js.map +7 -0
  858. package/dist/ui/tooltip.js +215 -0
  859. package/dist/ui/tooltip.js.map +7 -0
  860. package/dist/usage-metered.js +8 -0
  861. package/dist/usage-metered.js.map +7 -0
  862. package/dist/useArbi.js +16 -0
  863. package/dist/useArbi.js.map +7 -0
  864. package/dist/useInstallSkillPack.js +81 -0
  865. package/dist/useInstallSkillPack.js.map +7 -0
  866. package/dist/usermenu/UserMenu.js +188 -0
  867. package/dist/usermenu/UserMenu.js.map +7 -0
  868. package/dist/usermenu/index.js +5 -0
  869. package/dist/usermenu/index.js.map +7 -0
  870. package/dist/users/index.js +15 -0
  871. package/dist/users/index.js.map +7 -0
  872. package/dist/users/user-display.js +60 -0
  873. package/dist/users/user-display.js.map +7 -0
  874. package/dist/viewers/AudioViewer.js +23 -0
  875. package/dist/viewers/AudioViewer.js.map +7 -0
  876. package/dist/viewers/DocxViewer.js +81 -0
  877. package/dist/viewers/DocxViewer.js.map +7 -0
  878. package/dist/viewers/ImageViewer.js +31 -0
  879. package/dist/viewers/ImageViewer.js.map +7 -0
  880. package/dist/viewers/PdfViewer.cjs +17 -0
  881. package/dist/viewers/PdfViewer.cjs.map +1 -0
  882. package/dist/viewers/PdfViewer.d.ts +9 -0
  883. package/dist/viewers/PdfViewer.js +20 -0
  884. package/dist/viewers/PdfViewer.js.map +7 -0
  885. package/dist/viewers/PdfViewerImpl.js +384 -0
  886. package/dist/viewers/PdfViewerImpl.js.map +7 -0
  887. package/dist/viewers/VideoViewer.js +31 -0
  888. package/dist/viewers/VideoViewer.js.map +7 -0
  889. package/dist/viewers/XlsxViewer.js +102 -0
  890. package/dist/viewers/XlsxViewer.js.map +7 -0
  891. package/dist/viewers/index.cjs +79 -653
  892. package/dist/viewers/index.cjs.map +1 -1
  893. package/dist/viewers/index.d.ts +3 -1
  894. package/dist/viewers/index.js +60 -903
  895. package/dist/viewers/index.js.map +7 -1
  896. package/dist/viewers/page-scroll.js +59 -0
  897. package/dist/viewers/page-scroll.js.map +7 -0
  898. package/dist/viewers/pdf-viewer-constants.js +9 -0
  899. package/dist/viewers/pdf-viewer-constants.js.map +7 -0
  900. package/dist/{chunk-PTOP7OHG.js → viewers/pdfjs-polyfills.js} +5 -6
  901. package/dist/viewers/pdfjs-polyfills.js.map +7 -0
  902. package/dist/viewers/selection-runs.js +38 -0
  903. package/dist/viewers/selection-runs.js.map +7 -0
  904. package/dist/viewers/usePageIntersectionObserver.js +68 -0
  905. package/dist/viewers/usePageIntersectionObserver.js.map +7 -0
  906. package/dist/viewers/useProcessedChunks.js +58 -0
  907. package/dist/viewers/useProcessedChunks.js.map +7 -0
  908. package/dist/viewers/viewer-zoom.js +163 -0
  909. package/dist/viewers/viewer-zoom.js.map +7 -0
  910. package/dist/websocket/ArbiWebSocketProvider.js +207 -0
  911. package/dist/websocket/ArbiWebSocketProvider.js.map +7 -0
  912. package/dist/websocket/context.js +14 -0
  913. package/dist/websocket/context.js.map +7 -0
  914. package/dist/websocket/hooks.js +30 -0
  915. package/dist/websocket/hooks.js.map +7 -0
  916. package/dist/websocket/index.js +22 -0
  917. package/dist/websocket/index.js.map +7 -0
  918. package/dist/websocket/live-updates.js +38 -0
  919. package/dist/websocket/live-updates.js.map +7 -0
  920. package/dist/websocket/reconnect.js +13 -0
  921. package/dist/websocket/reconnect.js.map +7 -0
  922. package/dist/websocket/store.js +58 -0
  923. package/dist/websocket/store.js.map +7 -0
  924. package/dist/workforce.js +607 -0
  925. package/dist/workforce.js.map +7 -0
  926. package/dist/workspaces/access-request.js +35 -0
  927. package/dist/workspaces/access-request.js.map +7 -0
  928. package/dist/workspaces/archive.js +59 -0
  929. package/dist/workspaces/archive.js.map +7 -0
  930. package/dist/workspaces/current.js +20 -0
  931. package/dist/workspaces/current.js.map +7 -0
  932. package/dist/workspaces/delete-workspaces.js +15 -0
  933. package/dist/workspaces/delete-workspaces.js.map +7 -0
  934. package/dist/workspaces/export-archive.js +40 -0
  935. package/dist/workspaces/export-archive.js.map +7 -0
  936. package/dist/workspaces/index.js +99 -0
  937. package/dist/workspaces/index.js.map +7 -0
  938. package/dist/workspaces/settings.js +45 -0
  939. package/dist/workspaces/settings.js.map +7 -0
  940. package/dist/workspaces/shell-workspaces.js +49 -0
  941. package/dist/workspaces/shell-workspaces.js.map +7 -0
  942. package/dist/workspaces/switch.js +234 -0
  943. package/dist/workspaces/switch.js.map +7 -0
  944. package/dist/workspaces/transfer.js +170 -0
  945. package/dist/workspaces/transfer.js.map +7 -0
  946. package/dist/workspaces/useShellWorkspaces.js +86 -0
  947. package/dist/workspaces/useShellWorkspaces.js.map +7 -0
  948. package/dist/workspaces/workspace-users.js +65 -0
  949. package/dist/workspaces/workspace-users.js.map +7 -0
  950. package/package.json +12 -4
  951. package/dist/PdfViewer.d-bQH9yxFg.d.ts +0 -55
  952. package/dist/ProductionDialog.d-CpzslFn0.d.cts +0 -51
  953. package/dist/annotations/freeze/index.d.cts +0 -205
  954. package/dist/annotations/index.d.cts +0 -360
  955. package/dist/artifacts/index.d.cts +0 -476
  956. package/dist/artifacts/redline-core.d.cts +0 -39
  957. package/dist/bundle-YNOX7VIL.js +0 -5
  958. package/dist/bundle-YNOX7VIL.js.map +0 -1
  959. package/dist/bundle.d-BnCSbHy2.d.cts +0 -85
  960. package/dist/calls/livekit/index.d.cts +0 -280
  961. package/dist/chunk-47CCGUWR.js.map +0 -1
  962. package/dist/chunk-6H3O63TQ.js.map +0 -1
  963. package/dist/chunk-74N436VK.js.map +0 -1
  964. package/dist/chunk-APZZQZ6P.js +0 -147
  965. package/dist/chunk-APZZQZ6P.js.map +0 -1
  966. package/dist/chunk-BF5KW5ZI.js.map +0 -1
  967. package/dist/chunk-CPQ3CU4B.js +0 -246
  968. package/dist/chunk-CPQ3CU4B.js.map +0 -1
  969. package/dist/chunk-DPYBZDJB.js.map +0 -1
  970. package/dist/chunk-DQALOQPI.js +0 -2766
  971. package/dist/chunk-DQALOQPI.js.map +0 -1
  972. package/dist/chunk-FZJMA32S.js +0 -1011
  973. package/dist/chunk-FZJMA32S.js.map +0 -1
  974. package/dist/chunk-H5M7FXLB.js +0 -2057
  975. package/dist/chunk-H5M7FXLB.js.map +0 -1
  976. package/dist/chunk-HDCRPPBW.js +0 -75
  977. package/dist/chunk-HDCRPPBW.js.map +0 -1
  978. package/dist/chunk-NIKPG4PW.js +0 -1128
  979. package/dist/chunk-NIKPG4PW.js.map +0 -1
  980. package/dist/chunk-NNAJLY6B.js +0 -4974
  981. package/dist/chunk-NNAJLY6B.js.map +0 -1
  982. package/dist/chunk-OYPKKHXY.js +0 -559
  983. package/dist/chunk-OYPKKHXY.js.map +0 -1
  984. package/dist/chunk-P6WLV5UY.js +0 -644
  985. package/dist/chunk-P6WLV5UY.js.map +0 -1
  986. package/dist/chunk-PTOP7OHG.js.map +0 -1
  987. package/dist/chunk-SN5YV6FF.js +0 -11
  988. package/dist/chunk-SN5YV6FF.js.map +0 -1
  989. package/dist/chunk-T3USOSVN.js.map +0 -1
  990. package/dist/chunk-T4CLW3DN.js +0 -2560
  991. package/dist/chunk-T4CLW3DN.js.map +0 -1
  992. package/dist/chunk-UW2SGTI5.js.map +0 -1
  993. package/dist/chunk-VSCU7K4V.js.map +0 -1
  994. package/dist/chunk-WL2Y2T47.js.map +0 -1
  995. package/dist/chunk-WUTL62MC.js.map +0 -1
  996. package/dist/chunk-Y3MTRA7D.js +0 -97
  997. package/dist/chunk-Y3MTRA7D.js.map +0 -1
  998. package/dist/chunk-YNNAJJ5Z.js.map +0 -1
  999. package/dist/document-tools/core.d.cts +0 -883
  1000. package/dist/document-tools/index.d.cts +0 -90
  1001. package/dist/index.d-BMhTH98a.d.cts +0 -2035
  1002. package/dist/index.d-oR5FKZpJ.d.cts +0 -579
  1003. package/dist/index.d.cts +0 -15893
  1004. package/dist/model.d-CNtRWKVK.d.cts +0 -110
  1005. package/dist/query-keys.d-ChgpJLPF.d.cts +0 -337
  1006. package/dist/shell/index.d.cts +0 -6
  1007. package/dist/store.d-GADDvC7w.d.cts +0 -35
  1008. package/dist/stored-markdown.d-Bp18vrbr.d.cts +0 -125
  1009. package/dist/ui/index.d.cts +0 -25
  1010. package/dist/useAudioRecorder.d-B9rlMI_E.d.cts +0 -778
  1011. package/dist/viewers/index.d.cts +0 -260
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mail/offline/settings.ts"],
4
+ "sourcesContent": ["/**\n * Per-device offline mail settings and the shared change/status signal.\n *\n * Settings are a device preference, not mail content, so they live in localStorage keyed by the\n * user (two people sharing a browser keep separate choices). The mail itself is wiped on sign-out;\n * the preference survives so the mailbox re-syncs after the user signs back in on this device\n * (decided in #2187: they hold no mail, and keeping them favours the person coming back).\n *\n * By default the last 7 days of mail are kept; the person can choose a shorter or longer window,\n * or none (\"Off\": only drafts and the Outbox stay on the device).\n *\n * `onOfflineMailChange` notifies this tab and, through a BroadcastChannel, other open tabs whenever\n * the offline store changes (sync progress, Outbox, drafts), so every Mail view stays current.\n */\n\n/** How far back mail is kept on this device. */\nexport type OfflineMailScope = '1d' | '7d' | '30d' | '90d'\n\nexport interface OfflineMailSettings {\n /** Keep recent mail on this device (the window is `scope`). Off: only drafts and the Outbox. */\n enabled: boolean\n /** How far back mail is kept. */\n scope: OfflineMailScope\n /** Attachments of one message larger than this (MB, in total) are not saved. */\n attachmentCapMb: number\n /** Total space the offline mailbox may use (MB); the least recently opened attachments go first. */\n quotaMb: number\n}\n\n/** On, for the last week: recent mail can be read and answered offline unless the person opts out. */\nexport const DEFAULT_OFFLINE_MAIL_SETTINGS: OfflineMailSettings = {\n enabled: true,\n scope: '7d',\n attachmentCapMb: 25,\n quotaMb: 1024,\n}\n\nexport const SCOPE_DAYS: Record<OfflineMailScope, number> = {\n '1d': 1,\n '7d': 7,\n '30d': 30,\n '90d': 90,\n}\n\nconst DAY_MS = 24 * 60 * 60 * 1000\n\n/** The oldest receive time (ms) kept on the device under `settings`. */\nexport function offlineWindowStart(settings: OfflineMailSettings, now = Date.now()): number {\n return now - SCOPE_DAYS[settings.scope] * DAY_MS\n}\n\n/** Whether a message received at `receivedAt` belongs on the device (an undated one always does). */\nexport function inOfflineWindow(\n settings: OfflineMailSettings,\n receivedAt: string | undefined,\n now = Date.now()\n): boolean {\n const at = receivedAt ? Date.parse(receivedAt) || 0 : 0\n return settings.enabled && (!at || at >= offlineWindowStart(settings, now))\n}\n\n/**\n * Saved choices from earlier versions: a longer window (\"Last year\", \"All mail\") becomes the\n * longest one offered now, anything unknown the default.\n */\nfunction normalize(saved: Partial<OfflineMailSettings>): OfflineMailSettings {\n const merged = { ...DEFAULT_OFFLINE_MAIL_SETTINGS, ...saved }\n const scope: string = merged.scope\n if (scope in SCOPE_DAYS) return merged\n const longer = scope === '365d' || scope === 'all'\n return { ...merged, scope: longer ? '90d' : DEFAULT_OFFLINE_MAIL_SETTINGS.scope }\n}\n\nconst STORAGE_PREFIX = 'arbi-offline-mail-settings:'\n\n/** The signed-in user whose settings apply (`null`: signed out, nothing is kept). */\nexport type OfflineMailUser = string | null | undefined\n\n/** Nobody signed in (or a restored tab whose profile isn't loaded yet): keep no mail. */\nconst SIGNED_OUT: OfflineMailSettings = { ...DEFAULT_OFFLINE_MAIL_SETTINGS, enabled: false }\n\nexport function getOfflineMailSettings(userExtId: OfflineMailUser): OfflineMailSettings {\n if (!userExtId) return SIGNED_OUT\n const key = STORAGE_PREFIX + userExtId\n try {\n const raw = localStorage.getItem(key)\n return raw\n ? normalize(JSON.parse(raw) as Partial<OfflineMailSettings>)\n : DEFAULT_OFFLINE_MAIL_SETTINGS\n } catch {\n return DEFAULT_OFFLINE_MAIL_SETTINGS\n }\n}\n\nexport function setOfflineMailSettings(\n userExtId: OfflineMailUser,\n patch: Partial<OfflineMailSettings>\n): OfflineMailSettings {\n const next = { ...getOfflineMailSettings(userExtId), ...patch }\n if (userExtId) {\n try {\n localStorage.setItem(STORAGE_PREFIX + userExtId, JSON.stringify(next))\n } catch {\n // Storage full/blocked: the choice applies for this session only.\n }\n }\n notifyOfflineMailChange('settings')\n return next\n}\n\nexport type OfflineMailChange =\n 'settings' | 'mailbox' | 'outbox' | 'drafts' | 'changes' | 'status' | 'wiped'\n\nconst listeners = new Set<(change: OfflineMailChange) => void>()\nconst CHANNEL = 'arbi-offline-mail'\nlet channel: BroadcastChannel | null = null\n\nfunction getChannel(): BroadcastChannel | null {\n if (channel || typeof BroadcastChannel === 'undefined') return channel\n channel = new BroadcastChannel(CHANNEL)\n channel.onmessage = (event: MessageEvent<OfflineMailChange>) => {\n for (const listener of listeners) listener(event.data)\n }\n return channel\n}\n\nexport function notifyOfflineMailChange(change: OfflineMailChange): void {\n for (const listener of listeners) listener(change)\n try {\n getChannel()?.postMessage(change)\n } catch {\n // Channel closed (tab unloading): other tabs pick the change up on their next read.\n }\n}\n\nexport function onOfflineMailChange(listener: (change: OfflineMailChange) => void): () => void {\n getChannel()\n listeners.add(listener)\n return () => listeners.delete(listener)\n}\n"],
5
+ "mappings": "AA8BO,MAAM,gCAAqD;AAAA,EAChE,SAAS;AAAA,EACT,OAAO;AAAA,EACP,iBAAiB;AAAA,EACjB,SAAS;AACX;AAEO,MAAM,aAA+C;AAAA,EAC1D,MAAM;AAAA,EACN,MAAM;AAAA,EACN,OAAO;AAAA,EACP,OAAO;AACT;AAEA,MAAM,SAAS,KAAK,KAAK,KAAK;AAGvB,SAAS,mBAAmB,UAA+B,MAAM,KAAK,IAAI,GAAW;AAC1F,SAAO,MAAM,WAAW,SAAS,KAAK,IAAI;AAC5C;AAGO,SAAS,gBACd,UACA,YACA,MAAM,KAAK,IAAI,GACN;AACT,QAAM,KAAK,aAAa,KAAK,MAAM,UAAU,KAAK,IAAI;AACtD,SAAO,SAAS,YAAY,CAAC,MAAM,MAAM,mBAAmB,UAAU,GAAG;AAC3E;AAMA,SAAS,UAAU,OAA0D;AAC3E,QAAM,SAAS,EAAE,GAAG,+BAA+B,GAAG,MAAM;AAC5D,QAAM,QAAgB,OAAO;AAC7B,MAAI,SAAS,WAAY,QAAO;AAChC,QAAM,SAAS,UAAU,UAAU,UAAU;AAC7C,SAAO,EAAE,GAAG,QAAQ,OAAO,SAAS,QAAQ,8BAA8B,MAAM;AAClF;AAEA,MAAM,iBAAiB;AAMvB,MAAM,aAAkC,EAAE,GAAG,+BAA+B,SAAS,MAAM;AAEpF,SAAS,uBAAuB,WAAiD;AACtF,MAAI,CAAC,UAAW,QAAO;AACvB,QAAM,MAAM,iBAAiB;AAC7B,MAAI;AACF,UAAM,MAAM,aAAa,QAAQ,GAAG;AACpC,WAAO,MACH,UAAU,KAAK,MAAM,GAAG,CAAiC,IACzD;AAAA,EACN,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,uBACd,WACA,OACqB;AACrB,QAAM,OAAO,EAAE,GAAG,uBAAuB,SAAS,GAAG,GAAG,MAAM;AAC9D,MAAI,WAAW;AACb,QAAI;AACF,mBAAa,QAAQ,iBAAiB,WAAW,KAAK,UAAU,IAAI,CAAC;AAAA,IACvE,QAAQ;AAAA,IAER;AAAA,EACF;AACA,0BAAwB,UAAU;AAClC,SAAO;AACT;AAKA,MAAM,YAAY,oBAAI,IAAyC;AAC/D,MAAM,UAAU;AAChB,IAAI,UAAmC;AAEvC,SAAS,aAAsC;AAC7C,MAAI,WAAW,OAAO,qBAAqB,YAAa,QAAO;AAC/D,YAAU,IAAI,iBAAiB,OAAO;AACtC,UAAQ,YAAY,CAAC,UAA2C;AAC9D,eAAW,YAAY,UAAW,UAAS,MAAM,IAAI;AAAA,EACvD;AACA,SAAO;AACT;AAEO,SAAS,wBAAwB,QAAiC;AACvE,aAAW,YAAY,UAAW,UAAS,MAAM;AACjD,MAAI;AACF,eAAW,GAAG,YAAY,MAAM;AAAA,EAClC,QAAQ;AAAA,EAER;AACF;AAEO,SAAS,oBAAoB,UAA2D;AAC7F,aAAW;AACX,YAAU,IAAI,QAAQ;AACtB,SAAO,MAAM,UAAU,OAAO,QAAQ;AACxC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,29 @@
1
+ import { createRecordStore } from "../../offline-store/store.js";
2
+ const OFFLINE_MAIL_DB = "arbi-offline-mail";
3
+ const store = createRecordStore(OFFLINE_MAIL_DB);
4
+ const putRecord = store.putRecord;
5
+ const getRecord = store.getRecord;
6
+ const hasRecord = store.hasRecord;
7
+ const deleteRecords = store.deleteRecords;
8
+ const recordsInBucket = store.recordsInBucket;
9
+ const recordsOfKind = store.recordsOfKind;
10
+ const allRecordSizes = store.allRecordSizes;
11
+ const touchRecord = store.touchRecord;
12
+ const getMeta = store.getMeta;
13
+ const setMeta = store.setMeta;
14
+ const deleteOfflineMailDatabase = store.deleteDatabase;
15
+ export {
16
+ OFFLINE_MAIL_DB,
17
+ allRecordSizes,
18
+ deleteOfflineMailDatabase,
19
+ deleteRecords,
20
+ getMeta,
21
+ getRecord,
22
+ hasRecord,
23
+ putRecord,
24
+ recordsInBucket,
25
+ recordsOfKind,
26
+ setMeta,
27
+ touchRecord
28
+ };
29
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mail/offline/store.ts"],
4
+ "sourcesContent": ["/**\n * The offline mailbox's IndexedDB store (the generic encrypted record store, see\n * ../../offline-store/store, under the `arbi-offline-mail` database).\n *\n * Record plaintext fields are only what IndexedDB needs to find and evict a record: a blind key, its\n * kind, a blind bucket (which folder/account it belongs to), a sort time, its size and last read.\n * Everything else \u2014 subjects, addresses, bodies, attachments, drafts, queued mail and changes \u2014 is sealed in\n * `data` with the key from ./crypto. `meta` holds non-content facts: owner, sync times and counts.\n */\n\nimport { createRecordStore, type StoredRecord as GenericRecord } from '../../offline-store/store'\n\nexport const OFFLINE_MAIL_DB = 'arbi-offline-mail'\n\nexport type RecordKind =\n | 'accounts'\n | 'policy'\n | 'folders'\n | 'header'\n | 'body'\n | 'attachment'\n | 'draft'\n | 'outbox'\n | 'change'\n\nexport type StoredRecord = GenericRecord<RecordKind>\n\nconst store = createRecordStore<RecordKind>(OFFLINE_MAIL_DB)\n\nexport const putRecord = store.putRecord\nexport const getRecord = store.getRecord\nexport const hasRecord = store.hasRecord\nexport const deleteRecords = store.deleteRecords\nexport const recordsInBucket = store.recordsInBucket\nexport const recordsOfKind = store.recordsOfKind\n/** Keys + sizes only (no data), for quota accounting without loading ciphertext. */\nexport const allRecordSizes = store.allRecordSizes\nexport const touchRecord = store.touchRecord\nexport const getMeta = store.getMeta\nexport const setMeta = store.setMeta\n/** Delete the whole database (sign-out / \"Remove offline data\"). */\nexport const deleteOfflineMailDatabase = store.deleteDatabase\n"],
5
+ "mappings": "AAUA,SAAS,yBAA6D;AAE/D,MAAM,kBAAkB;AAe/B,MAAM,QAAQ,kBAA8B,eAAe;AAEpD,MAAM,YAAY,MAAM;AACxB,MAAM,YAAY,MAAM;AACxB,MAAM,YAAY,MAAM;AACxB,MAAM,gBAAgB,MAAM;AAC5B,MAAM,kBAAkB,MAAM;AAC9B,MAAM,gBAAgB,MAAM;AAE5B,MAAM,iBAAiB,MAAM;AAC7B,MAAM,cAAc,MAAM;AAC1B,MAAM,UAAU,MAAM;AACtB,MAAM,UAAU,MAAM;AAEtB,MAAM,4BAA4B,MAAM;",
6
+ "names": []
7
+ }
@@ -0,0 +1,251 @@
1
+ import { logger } from "@arbidocs/client";
2
+ import {
3
+ bucketOf,
4
+ hasAttachment,
5
+ hasBody,
6
+ isVirtualFolder,
7
+ keyOf,
8
+ loadAccounts,
9
+ loadFolders,
10
+ loadHeaders,
11
+ removeKeys,
12
+ saveAccounts,
13
+ saveAttachment,
14
+ saveBody,
15
+ saveFolders,
16
+ saveHeader,
17
+ savePolicy,
18
+ toHeader
19
+ } from "./mailbox.js";
20
+ import { allRecordSizes, getMeta, recordsInBucket, recordsOfKind, setMeta } from "./store.js";
21
+ import { overlayPendingMailChanges } from "./changes.js";
22
+ import {
23
+ notifyOfflineMailChange,
24
+ offlineWindowStart,
25
+ SCOPE_DAYS
26
+ } from "./settings.js";
27
+ const STATUS_KEY = "status";
28
+ const FULL_SYNC_EVERY_MS = 60 * 60 * 1e3;
29
+ const MAX_PAGES = 200;
30
+ async function getOfflineMailStatus() {
31
+ return await getMeta(STATUS_KEY) ?? { messages: 0, bytes: 0, skipped: [] };
32
+ }
33
+ const MB = 1024 * 1024;
34
+ const time = (m) => m.received_at ? Date.parse(m.received_at) || 0 : 0;
35
+ const sameHeader = (a, b) => JSON.stringify(toHeader(a)) === JSON.stringify(toHeader(b));
36
+ class Budget {
37
+ constructor(used, quota) {
38
+ this.used = used;
39
+ this.quota = quota;
40
+ }
41
+ used;
42
+ quota;
43
+ get full() {
44
+ return this.used >= this.quota;
45
+ }
46
+ take(bytes) {
47
+ this.used += bytes;
48
+ }
49
+ }
50
+ async function saveMessageContent(transport, account, header, settings, budget) {
51
+ const message = await transport.message(account, header.id);
52
+ await saveBody(account.id, message);
53
+ budget.take((message.text?.length ?? 0) + (message.html?.length ?? 0));
54
+ let attachmentBytes = 0;
55
+ for (const attachment of message.attachments) {
56
+ if (budget.full) return;
57
+ if (attachmentBytes + attachment.size > settings.attachmentCapMb * MB) continue;
58
+ if (await hasAttachment(account.id, message.id, attachment.id)) continue;
59
+ const bytes = attachment.content_base64 ? Uint8Array.from(atob(attachment.content_base64), (c) => c.charCodeAt(0)) : await transport.attachment(account, message.id, attachment.id);
60
+ await saveAttachment(account.id, message.id, attachment.id, bytes, time(message));
61
+ attachmentBytes += bytes.byteLength;
62
+ budget.take(bytes.byteLength);
63
+ }
64
+ }
65
+ async function syncFolder(transport, account, folder, settings, windowStart, full, budget) {
66
+ const saved = new Map(
67
+ (await loadHeaders(account.id, folder.id)).map((h) => [h.message.id, h])
68
+ );
69
+ const seen = /* @__PURE__ */ new Set();
70
+ let oldestSeen = Infinity;
71
+ let cursor = null;
72
+ let reachedEnd = false;
73
+ for (let page = 0; page < MAX_PAGES; page++) {
74
+ const result = await transport.messages(account, folder.id, cursor);
75
+ let anythingNew = false;
76
+ let outOfScope = false;
77
+ for (const message of result.messages) {
78
+ const at = time(message);
79
+ if (at && at < windowStart) {
80
+ outOfScope = true;
81
+ break;
82
+ }
83
+ seen.add(message.id);
84
+ if (at) oldestSeen = Math.min(oldestSeen, at);
85
+ const previous = saved.get(message.id)?.message;
86
+ if (!previous || !sameHeader(previous, message)) {
87
+ await saveHeader(account.id, folder.id, message);
88
+ anythingNew = true;
89
+ }
90
+ if (!budget.full && !await hasBody(account.id, message.id)) {
91
+ try {
92
+ await saveMessageContent(transport, account, message, settings, budget);
93
+ anythingNew = true;
94
+ } catch (error) {
95
+ logger.warn("[offline-mail] could not save a message body", error);
96
+ }
97
+ }
98
+ }
99
+ cursor = result.next_cursor ?? null;
100
+ if (outOfScope || !cursor) {
101
+ reachedEnd = true;
102
+ break;
103
+ }
104
+ if (!full && !anythingNew) break;
105
+ }
106
+ const stale = [...saved.values()].filter(
107
+ (h) => !seen.has(h.message.id) && (reachedEnd || h.sortAt >= oldestSeen)
108
+ );
109
+ await removeKeys(stale.map((h) => h.key));
110
+ }
111
+ async function collectGarbage(accounts) {
112
+ for (const account of accounts) {
113
+ const folders = await loadFolders(account.id) ?? [];
114
+ const expected = /* @__PURE__ */ new Set([await keyOf.folders(account.id)]);
115
+ for (const folder of folders) {
116
+ for (const { message } of await loadHeaders(account.id, folder.id)) {
117
+ expected.add(await keyOf.body(account.id, message.id));
118
+ for (const attachment of message.attachments)
119
+ expected.add(await keyOf.attachment(account.id, message.id, attachment.id));
120
+ }
121
+ }
122
+ const orphans = (await recordsInBucket(await bucketOf.account(account.id))).filter((r) => (r.kind === "body" || r.kind === "attachment") && !expected.has(r.key)).map((r) => r.key);
123
+ await removeKeys(orphans);
124
+ }
125
+ }
126
+ async function forgetAccount(accountId) {
127
+ for (const folder of await loadFolders(accountId) ?? []) {
128
+ const records2 = await recordsInBucket(await bucketOf.folder(accountId, folder.id));
129
+ await removeKeys(records2.map((r) => r.key));
130
+ }
131
+ const records = await recordsInBucket(await bucketOf.account(accountId));
132
+ await removeKeys(records.filter((r) => r.kind !== "draft").map((r) => r.key));
133
+ }
134
+ async function enforceQuota(quotaBytes) {
135
+ let used = (await allRecordSizes()).reduce((n, r) => n + r.size, 0);
136
+ if (used <= quotaBytes) return used;
137
+ for (const kind of ["attachment", "body"]) {
138
+ const records = (await recordsOfKind(kind)).sort(
139
+ (a, b) => kind === "attachment" ? a.lastAccess - b.lastAccess : a.sortAt - b.sortAt
140
+ );
141
+ const evict = [];
142
+ for (const record of records) {
143
+ if (used <= quotaBytes) break;
144
+ evict.push(record.key);
145
+ used -= record.size;
146
+ }
147
+ await removeKeys(evict);
148
+ if (used <= quotaBytes) break;
149
+ }
150
+ return used;
151
+ }
152
+ const CONTENT_KINDS = ["header", "body", "attachment"];
153
+ async function trimOfflineMailbox(settings, now = Date.now()) {
154
+ const windowStart = offlineWindowStart(settings, now);
155
+ const kinds = settings.enabled ? CONTENT_KINDS : [...CONTENT_KINDS, "folders"];
156
+ for (const kind of kinds) {
157
+ const records = await recordsOfKind(kind);
158
+ const old = settings.enabled ? records.filter((r) => r.sortAt > 0 && r.sortAt < windowStart) : records;
159
+ await removeKeys(old.map((r) => r.key));
160
+ }
161
+ const previous = await getOfflineMailStatus();
162
+ const status = {
163
+ ...previous,
164
+ messages: (await recordsOfKind("header")).length,
165
+ bytes: (await allRecordSizes()).reduce((n, r) => n + r.size, 0),
166
+ // A shorter window no longer covers what the last full pass fetched: growing it again (even
167
+ // before the next hourly full pass) makes the next pass a full one.
168
+ windowDays: settings.enabled && previous.windowDays !== void 0 ? Math.min(previous.windowDays, SCOPE_DAYS[settings.scope]) : void 0,
169
+ // Off: nothing is saved, so turning it back on starts with a full pass.
170
+ ...!settings.enabled && { lastSyncedAt: void 0, lastFullSyncAt: void 0 }
171
+ };
172
+ await setMeta(STATUS_KEY, status);
173
+ notifyOfflineMailChange("status");
174
+ return status;
175
+ }
176
+ async function syncMailbox(transport, settings, options = {}) {
177
+ const now = options.now ?? Date.now();
178
+ const previous = await getOfflineMailStatus();
179
+ const days = SCOPE_DAYS[settings.scope];
180
+ const full = options.full || !previous.lastFullSyncAt || now - previous.lastFullSyncAt > FULL_SYNC_EVERY_MS || (previous.windowDays ?? 0) < days;
181
+ const windowStart = offlineWindowStart(settings, now);
182
+ const quota = settings.quotaMb * MB;
183
+ const skipped = [];
184
+ let error;
185
+ try {
186
+ await savePolicy(await transport.policy());
187
+ const accounts = await transport.accounts();
188
+ const before = await loadAccounts() ?? [];
189
+ await saveAccounts(accounts);
190
+ for (const gone of before.filter((b) => !accounts.some((a) => a.id === b.id)))
191
+ await forgetAccount(gone.id);
192
+ const budget = new Budget(
193
+ (await allRecordSizes()).reduce((n, r) => n + r.size, 0),
194
+ quota
195
+ );
196
+ for (const account of accounts) {
197
+ if (account.needs_reconsent) {
198
+ skipped.push(account.email);
199
+ continue;
200
+ }
201
+ try {
202
+ await transport.unlock(account);
203
+ const folders = await transport.folders(account);
204
+ const oldFolders = await loadFolders(account.id) ?? [];
205
+ await saveFolders(account.id, folders);
206
+ for (const gone of oldFolders.filter((o) => !folders.some((f) => f.id === o.id))) {
207
+ const records = await recordsInBucket(await bucketOf.folder(account.id, gone.id));
208
+ await removeKeys(records.map((r) => r.key));
209
+ }
210
+ for (const folder of folders.filter((f) => !isVirtualFolder(f)))
211
+ await syncFolder(transport, account, folder, settings, windowStart, full, budget);
212
+ notifyOfflineMailChange("mailbox");
213
+ } catch (accountError) {
214
+ if (accountError.status === void 0) throw accountError;
215
+ logger.warn("[offline-mail] account sync failed", accountError);
216
+ skipped.push(account.email);
217
+ }
218
+ }
219
+ if (full) await collectGarbage(accounts);
220
+ } catch (syncError) {
221
+ error = syncError.status === void 0 ? "The connection dropped during sync. It will continue when you are back online." : syncError instanceof Error ? syncError.message : "Sync failed";
222
+ }
223
+ await overlayPendingMailChanges().catch(
224
+ (overlayError) => logger.warn("[offline-mail] could not lay pending changes over the device copy", overlayError)
225
+ );
226
+ const current = options.latest?.() ?? settings;
227
+ const trimmed = await trimOfflineMailbox(current, now);
228
+ if (!current.enabled) return trimmed;
229
+ const bytes = await enforceQuota(current.quotaMb * MB);
230
+ const messages = (await recordsOfKind("header")).length;
231
+ const fullDone = !error && full;
232
+ const status = {
233
+ lastSyncedAt: error ? previous.lastSyncedAt : now,
234
+ lastFullSyncAt: fullDone ? now : previous.lastFullSyncAt,
235
+ windowDays: fullDone ? Math.min(days, SCOPE_DAYS[current.scope]) : trimmed.windowDays,
236
+ messages,
237
+ bytes,
238
+ error,
239
+ skipped
240
+ };
241
+ await setMeta(STATUS_KEY, status);
242
+ notifyOfflineMailChange("status");
243
+ return status;
244
+ }
245
+ export {
246
+ enforceQuota,
247
+ getOfflineMailStatus,
248
+ syncMailbox,
249
+ trimOfflineMailbox
250
+ };
251
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mail/offline/sync.ts"],
4
+ "sourcesContent": ["/**\n * Mailbox sync: copies the user's mail (native inbox and connected accounts, through the same list/\n * get endpoints the Mail page uses) into the encrypted offline store, incrementally.\n *\n * For each account \u2192 folder, list pages newest first within the chosen scope. Headers are always\n * refreshed (cheap: read/unread and moves show up); a body and its attachments are fetched only for\n * a message not saved yet. A quick pass stops at the first page that holds nothing new; a full pass\n * (hourly, or \"Sync now\") walks the whole scope and drops what was deleted or moved on the server.\n *\n * Space: attachments of one message are saved up to the per-message cap; the whole store is held\n * under the quota, evicting the least recently opened attachments first, then the oldest bodies.\n * A message whose body isn't saved still lists offline and says so when opened.\n *\n * Window: only mail received within the chosen window is kept (`trimOfflineMailbox`, after every\n * pass and as soon as the setting changes, offline too). A longer window than the last full pass\n * covered makes the next pass a full one, which fetches the older mail.\n */\n\nimport type { MailAccount, MailFolder, MailMessage, MailPolicy } from '../types'\nimport { logger } from '@arbidocs/client'\nimport {\n bucketOf,\n hasAttachment,\n hasBody,\n isVirtualFolder,\n keyOf,\n loadAccounts,\n loadFolders,\n loadHeaders,\n removeKeys,\n saveAccounts,\n saveAttachment,\n saveBody,\n saveFolders,\n saveHeader,\n savePolicy,\n toHeader,\n} from './mailbox'\nimport { allRecordSizes, getMeta, recordsInBucket, recordsOfKind, setMeta } from './store'\nimport { overlayPendingMailChanges } from './changes'\nimport {\n notifyOfflineMailChange,\n offlineWindowStart,\n SCOPE_DAYS,\n type OfflineMailSettings,\n} from './settings'\n\nexport interface MailTransport {\n policy: () => Promise<MailPolicy>\n accounts: () => Promise<MailAccount[]>\n unlock: (account: MailAccount) => Promise<void>\n folders: (account: MailAccount) => Promise<MailFolder[]>\n messages: (\n account: MailAccount,\n folderId: string,\n cursor: string | null\n ) => Promise<{ messages: MailMessage[]; next_cursor?: string | null }>\n message: (account: MailAccount, messageId: string) => Promise<MailMessage>\n attachment: (account: MailAccount, messageId: string, attachmentId: string) => Promise<Uint8Array>\n}\n\nexport interface OfflineMailStatus {\n lastSyncedAt?: number\n lastFullSyncAt?: number\n messages: number\n bytes: number\n /** Why the last sync didn't finish, in plain words. */\n error?: string\n /** Accounts that could not be synced (e.g. need reconnecting), by email. */\n skipped: string[]\n /** The window (days) the last full pass covered; a longer one needs another full pass. */\n windowDays?: number\n}\n\nconst STATUS_KEY = 'status'\nconst FULL_SYNC_EVERY_MS = 60 * 60 * 1000\n/** Safety stop per folder per pass. */\nconst MAX_PAGES = 200\n\nexport async function getOfflineMailStatus(): Promise<OfflineMailStatus> {\n return (await getMeta<OfflineMailStatus>(STATUS_KEY)) ?? { messages: 0, bytes: 0, skipped: [] }\n}\n\nconst MB = 1024 * 1024\nconst time = (m: MailMessage) => (m.received_at ? Date.parse(m.received_at) || 0 : 0)\nconst sameHeader = (a: MailMessage, b: MailMessage) =>\n JSON.stringify(toHeader(a)) === JSON.stringify(toHeader(b))\n\nclass Budget {\n constructor(\n public used: number,\n private readonly quota: number\n ) {}\n get full() {\n return this.used >= this.quota\n }\n take(bytes: number) {\n this.used += bytes\n }\n}\n\nasync function saveMessageContent(\n transport: MailTransport,\n account: MailAccount,\n header: MailMessage,\n settings: OfflineMailSettings,\n budget: Budget\n): Promise<void> {\n const message = await transport.message(account, header.id)\n await saveBody(account.id, message)\n budget.take((message.text?.length ?? 0) + (message.html?.length ?? 0))\n let attachmentBytes = 0\n for (const attachment of message.attachments) {\n if (budget.full) return\n if (attachmentBytes + attachment.size > settings.attachmentCapMb * MB) continue\n if (await hasAttachment(account.id, message.id, attachment.id)) continue\n const bytes = attachment.content_base64\n ? Uint8Array.from(atob(attachment.content_base64), (c) => c.charCodeAt(0))\n : await transport.attachment(account, message.id, attachment.id)\n await saveAttachment(account.id, message.id, attachment.id, bytes, time(message))\n attachmentBytes += bytes.byteLength\n budget.take(bytes.byteLength)\n }\n}\n\nasync function syncFolder(\n transport: MailTransport,\n account: MailAccount,\n folder: MailFolder,\n settings: OfflineMailSettings,\n windowStart: number,\n full: boolean,\n budget: Budget\n): Promise<void> {\n const saved = new Map(\n (await loadHeaders(account.id, folder.id)).map((h) => [h.message.id, h] as const)\n )\n const seen = new Set<string>()\n let oldestSeen = Infinity\n let cursor: string | null = null\n let reachedEnd = false\n for (let page = 0; page < MAX_PAGES; page++) {\n const result = await transport.messages(account, folder.id, cursor)\n let anythingNew = false\n let outOfScope = false\n for (const message of result.messages) {\n const at = time(message)\n if (at && at < windowStart) {\n outOfScope = true\n break\n }\n seen.add(message.id)\n if (at) oldestSeen = Math.min(oldestSeen, at)\n const previous = saved.get(message.id)?.message\n if (!previous || !sameHeader(previous, message)) {\n await saveHeader(account.id, folder.id, message)\n anythingNew = true\n }\n if (!budget.full && !(await hasBody(account.id, message.id))) {\n try {\n await saveMessageContent(transport, account, message, settings, budget)\n anythingNew = true\n } catch (error) {\n // One unreadable message must not stop the folder; it lists, and says it isn't saved.\n logger.warn('[offline-mail] could not save a message body', error)\n }\n }\n }\n cursor = result.next_cursor ?? null\n if (outOfScope || !cursor) {\n reachedEnd = true\n break\n }\n if (!full && !anythingNew) break\n }\n // Drop what the server no longer has here: everything unseen in the range this pass covered\n // (the whole folder when it reached the end of the scope).\n const stale = [...saved.values()].filter(\n (h) => !seen.has(h.message.id) && (reachedEnd || h.sortAt >= oldestSeen)\n )\n await removeKeys(stale.map((h) => h.key))\n}\n\n/** Remove bodies/attachments no header points to any more, and folders/accounts that went away. */\nasync function collectGarbage(accounts: MailAccount[]): Promise<void> {\n for (const account of accounts) {\n const folders = (await loadFolders(account.id)) ?? []\n const expected = new Set<string>([await keyOf.folders(account.id)])\n for (const folder of folders) {\n for (const { message } of await loadHeaders(account.id, folder.id)) {\n expected.add(await keyOf.body(account.id, message.id))\n for (const attachment of message.attachments)\n expected.add(await keyOf.attachment(account.id, message.id, attachment.id))\n }\n }\n const orphans = (await recordsInBucket(await bucketOf.account(account.id)))\n .filter((r) => (r.kind === 'body' || r.kind === 'attachment') && !expected.has(r.key))\n .map((r) => r.key)\n await removeKeys(orphans)\n }\n}\n\nasync function forgetAccount(accountId: string): Promise<void> {\n for (const folder of (await loadFolders(accountId)) ?? []) {\n const records = await recordsInBucket(await bucketOf.folder(accountId, folder.id))\n await removeKeys(records.map((r) => r.key))\n }\n const records = await recordsInBucket(await bucketOf.account(accountId))\n await removeKeys(records.filter((r) => r.kind !== 'draft').map((r) => r.key))\n}\n\n/** Hold the store under the quota: least recently opened attachments first, then oldest bodies. */\nexport async function enforceQuota(quotaBytes: number): Promise<number> {\n let used = (await allRecordSizes()).reduce((n, r) => n + r.size, 0)\n if (used <= quotaBytes) return used\n for (const kind of ['attachment', 'body'] as const) {\n const records = (await recordsOfKind(kind)).sort((a, b) =>\n kind === 'attachment' ? a.lastAccess - b.lastAccess : a.sortAt - b.sortAt\n )\n const evict: string[] = []\n for (const record of records) {\n if (used <= quotaBytes) break\n evict.push(record.key)\n used -= record.size\n }\n await removeKeys(evict)\n if (used <= quotaBytes) break\n }\n return used\n}\n\nconst CONTENT_KINDS = ['header', 'body', 'attachment'] as const\n\n/**\n * Hold the device copy to the chosen window, with no network: mail received before it goes (its\n * list row, body and attachments; an undated message stays). Off: every folder and message goes,\n * and only the accounts, drafts and the Outbox stay. Returns the status with the new totals.\n */\nexport async function trimOfflineMailbox(\n settings: OfflineMailSettings,\n now = Date.now()\n): Promise<OfflineMailStatus> {\n const windowStart = offlineWindowStart(settings, now)\n const kinds = settings.enabled ? CONTENT_KINDS : ([...CONTENT_KINDS, 'folders'] as const)\n for (const kind of kinds) {\n const records = await recordsOfKind(kind)\n const old = settings.enabled\n ? records.filter((r) => r.sortAt > 0 && r.sortAt < windowStart)\n : records\n await removeKeys(old.map((r) => r.key))\n }\n const previous = await getOfflineMailStatus()\n const status: OfflineMailStatus = {\n ...previous,\n messages: (await recordsOfKind('header')).length,\n bytes: (await allRecordSizes()).reduce((n, r) => n + r.size, 0),\n // A shorter window no longer covers what the last full pass fetched: growing it again (even\n // before the next hourly full pass) makes the next pass a full one.\n windowDays:\n settings.enabled && previous.windowDays !== undefined\n ? Math.min(previous.windowDays, SCOPE_DAYS[settings.scope])\n : undefined,\n // Off: nothing is saved, so turning it back on starts with a full pass.\n ...(!settings.enabled && { lastSyncedAt: undefined, lastFullSyncAt: undefined }),\n }\n await setMeta(STATUS_KEY, status)\n notifyOfflineMailChange('status')\n return status\n}\n\n/**\n * One sync pass. Never throws: the outcome is recorded in the status (and announced), because it\n * runs in the background and a failure must show up as \"couldn't sync\", not vanish.\n *\n * `latest` reads the settings again at the end: a window shortened (or Off chosen) while the pass\n * ran is what the device copy is trimmed to, not the settings the pass started with.\n */\nexport async function syncMailbox(\n transport: MailTransport,\n settings: OfflineMailSettings,\n options: { full?: boolean; now?: number; latest?: () => OfflineMailSettings } = {}\n): Promise<OfflineMailStatus> {\n const now = options.now ?? Date.now()\n const previous = await getOfflineMailStatus()\n const days = SCOPE_DAYS[settings.scope]\n const full =\n options.full ||\n !previous.lastFullSyncAt ||\n now - previous.lastFullSyncAt > FULL_SYNC_EVERY_MS ||\n (previous.windowDays ?? 0) < days\n const windowStart = offlineWindowStart(settings, now)\n const quota = settings.quotaMb * MB\n const skipped: string[] = []\n let error: string | undefined\n try {\n await savePolicy(await transport.policy())\n const accounts = await transport.accounts()\n const before = (await loadAccounts()) ?? []\n await saveAccounts(accounts)\n for (const gone of before.filter((b) => !accounts.some((a) => a.id === b.id)))\n await forgetAccount(gone.id)\n const budget = new Budget(\n (await allRecordSizes()).reduce((n, r) => n + r.size, 0),\n quota\n )\n for (const account of accounts) {\n if (account.needs_reconsent) {\n skipped.push(account.email)\n continue\n }\n try {\n await transport.unlock(account)\n const folders = await transport.folders(account)\n const oldFolders = (await loadFolders(account.id)) ?? []\n await saveFolders(account.id, folders)\n for (const gone of oldFolders.filter((o) => !folders.some((f) => f.id === o.id))) {\n const records = await recordsInBucket(await bucketOf.folder(account.id, gone.id))\n await removeKeys(records.map((r) => r.key))\n }\n // Flagged is a view over the other folders: its messages are saved where they are.\n for (const folder of folders.filter((f) => !isVirtualFolder(f)))\n await syncFolder(transport, account, folder, settings, windowStart, full, budget)\n notifyOfflineMailChange('mailbox')\n } catch (accountError) {\n // Network loss mid-sync: stop; everything saved so far stays and the next pass continues.\n if ((accountError as { status?: number }).status === undefined) throw accountError\n logger.warn('[offline-mail] account sync failed', accountError)\n skipped.push(account.email)\n }\n }\n if (full) await collectGarbage(accounts)\n } catch (syncError) {\n error =\n (syncError as { status?: number }).status === undefined\n ? 'The connection dropped during sync. It will continue when you are back online.'\n : syncError instanceof Error\n ? syncError.message\n : 'Sync failed'\n }\n // Changes made offline that the server hasn't applied yet: the pass wrote the server's state.\n await overlayPendingMailChanges().catch((overlayError) =>\n logger.warn('[offline-mail] could not lay pending changes over the device copy', overlayError)\n )\n // Mail that aged out of the window since the last pass, under the settings as they are now.\n const current = options.latest?.() ?? settings\n const trimmed = await trimOfflineMailbox(current, now)\n // Off was chosen while this pass ran: nothing stays, and nothing counts as synced.\n if (!current.enabled) return trimmed\n const bytes = await enforceQuota(current.quotaMb * MB)\n const messages = (await recordsOfKind('header')).length\n const fullDone = !error && full\n const status: OfflineMailStatus = {\n lastSyncedAt: error ? previous.lastSyncedAt : now,\n lastFullSyncAt: fullDone ? now : previous.lastFullSyncAt,\n windowDays: fullDone ? Math.min(days, SCOPE_DAYS[current.scope]) : trimmed.windowDays,\n messages,\n bytes,\n error,\n skipped,\n }\n await setMeta(STATUS_KEY, status)\n notifyOfflineMailChange('status')\n return status\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["records"]
7
+ }
@@ -0,0 +1,19 @@
1
+ import { forgetOfflineMailKeys } from "./crypto.js";
2
+ import { deleteOfflineMailDatabase, getMeta, setMeta } from "./store.js";
3
+ import { notifyOfflineMailChange } from "./settings.js";
4
+ const OWNER_KEY = "owner";
5
+ async function wipeOfflineMail() {
6
+ forgetOfflineMailKeys();
7
+ await deleteOfflineMailDatabase();
8
+ notifyOfflineMailChange("wiped");
9
+ }
10
+ async function claimOfflineMail(userExtId) {
11
+ const owner = await getMeta(OWNER_KEY);
12
+ if (owner && owner !== userExtId) await wipeOfflineMail();
13
+ await setMeta(OWNER_KEY, userExtId);
14
+ }
15
+ export {
16
+ claimOfflineMail,
17
+ wipeOfflineMail
18
+ };
19
+ //# sourceMappingURL=wipe.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mail/offline/wipe.ts"],
4
+ "sourcesContent": ["/**\n * Removing the offline mailbox: on sign-out, on \"Remove offline data\", and when a different account\n * signs in on this device.\n */\n\nimport { forgetOfflineMailKeys } from './crypto'\nimport { deleteOfflineMailDatabase, getMeta, setMeta } from './store'\nimport { notifyOfflineMailChange } from './settings'\n\nconst OWNER_KEY = 'owner'\n\n/** Delete everything the offline mailbox stored on this device (mail, drafts, Outbox, status). */\nexport async function wipeOfflineMail(): Promise<void> {\n forgetOfflineMailKeys()\n await deleteOfflineMailDatabase()\n notifyOfflineMailChange('wiped')\n}\n\n/**\n * Bind the store to the account signing in. A store written by someone else on this device is\n * removed (it is sealed to their key, so it is unreadable anyway, but it must not take space or\n * leave their queued mail behind).\n */\nexport async function claimOfflineMail(userExtId: string): Promise<void> {\n const owner = await getMeta<string>(OWNER_KEY)\n if (owner && owner !== userExtId) await wipeOfflineMail()\n await setMeta(OWNER_KEY, userExtId)\n}\n"],
5
+ "mappings": "AAKA,SAAS,6BAA6B;AACtC,SAAS,2BAA2B,SAAS,eAAe;AAC5D,SAAS,+BAA+B;AAExC,MAAM,YAAY;AAGlB,eAAsB,kBAAiC;AACrD,wBAAsB;AACtB,QAAM,0BAA0B;AAChC,0BAAwB,OAAO;AACjC;AAOA,eAAsB,iBAAiB,WAAkC;AACvE,QAAM,QAAQ,MAAM,QAAgB,SAAS;AAC7C,MAAI,SAAS,UAAU,UAAW,OAAM,gBAAgB;AACxD,QAAM,QAAQ,WAAW,SAAS;AACpC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,53 @@
1
+ import { useEffect } from "react";
2
+ import { useQueryClient } from "@tanstack/react-query";
3
+ import { logger } from "@arbidocs/client";
4
+ import { mail as mailOps } from "@arbidocs/sdk/browser";
5
+ import { useMailOnline, useReadMailMessage } from "./hooks.js";
6
+ import { useMailClient } from "./useMailClient.js";
7
+ import { nativeThreadKeys } from "./threads.js";
8
+ import { mailQueryKeys } from "../query-keys.js";
9
+ const BATCH = 50;
10
+ const SECRET_FRESH_MS = 6e4;
11
+ const tried = /* @__PURE__ */ new Set();
12
+ function useNativeThreadKeys(account, messages) {
13
+ const { client, enabled } = useMailClient();
14
+ const isOnline = useMailOnline();
15
+ const queryClient = useQueryClient();
16
+ const readMessage = useReadMailMessage();
17
+ useEffect(() => {
18
+ if (!enabled || !isOnline || account?.provider !== "native" || !messages) return;
19
+ const unkeyed = messages.filter((m) => !m.thread_id && m.id.startsWith("eml-") && !tried.has(m.id)).slice(0, BATCH);
20
+ if (!unkeyed.length) return;
21
+ for (const m of unkeyed) tried.add(m.id);
22
+ const keyable = unkeyed.filter((m) => m.message_id);
23
+ if (!keyable.length) return;
24
+ void (async () => {
25
+ try {
26
+ const secret = await queryClient.fetchQuery({
27
+ queryKey: mailQueryKeys.threadSecret(),
28
+ queryFn: () => mailOps.getNativeThreadSecret(client.fetch),
29
+ staleTime: SECRET_FRESH_MS
30
+ });
31
+ const keys = {};
32
+ for (const listed of keyable) {
33
+ const source = listed.references.length ? listed : await readMessage(account, listed.id).catch(() => void 0);
34
+ const key = source && await nativeThreadKeys(secret, source);
35
+ if (key) keys[listed.id] = key;
36
+ }
37
+ if (!Object.keys(keys).length) return;
38
+ if (await mailOps.submitNativeThreadKeys(client.fetch, keys) > 0) {
39
+ await queryClient.invalidateQueries({ queryKey: mailQueryKeys.allConversations() });
40
+ await queryClient.invalidateQueries({ queryKey: mailQueryKeys.allMessages() });
41
+ }
42
+ } catch (error) {
43
+ queryClient.removeQueries({ queryKey: mailQueryKeys.threadSecret() });
44
+ for (const m of keyable) tried.delete(m.id);
45
+ logger.warn("[mail] could not key older mail into conversations", error);
46
+ }
47
+ })();
48
+ }, [account, messages, enabled, isOnline, client, queryClient, readMessage]);
49
+ }
50
+ export {
51
+ useNativeThreadKeys
52
+ };
53
+ //# sourceMappingURL=thread-keys.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/mail/thread-keys.ts"],
4
+ "sourcesContent": ["/**\n * Keying older native mail into conversations, lazily, in the background.\n *\n * The server keys every message it stores from now on, but it cannot key mail stored before: its\n * Message-IDs are encrypted to the owner. The owner's client can read them, so it computes the keys\n * (with the owner's thread secret) for the unkeyed messages it lists and submits them. Until then\n * such a message is a conversation of its own, online and offline alike.\n *\n * A list row carries the Message-ID and References; only a row with no References is read in full\n * (for its In-Reply-To), through the query cache, so a message already opened is not read again.\n */\n\nimport { useEffect } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { logger } from '@arbidocs/client'\nimport { mail as mailOps } from '@arbidocs/sdk/browser'\nimport { useMailOnline, useReadMailMessage } from './hooks'\nimport { useMailClient } from './useMailClient'\nimport { nativeThreadKeys } from './threads'\nimport { mailQueryKeys } from '../query-keys'\nimport type { MailAccount, MailMessage } from './types'\n\n/** Messages keyed per round: the next list read brings the next ones. */\nconst BATCH = 50\n\n/** How long a fetched thread secret is used before it is fetched again. */\nconst SECRET_FRESH_MS = 60_000\n\n/**\n * Messages tried in this page's life, across mounts: a keyed one needs no second try, and one with\n * no Message-ID never gets a key (it stays on its own). A failed round is tried again later.\n */\nconst tried = new Set<string>()\n\n/** Key the native `messages` listed that have no thread yet. Failures stay quiet. */\nexport function useNativeThreadKeys(\n account: MailAccount | undefined,\n messages: MailMessage[] | undefined\n): void {\n const { client, enabled } = useMailClient()\n const isOnline = useMailOnline()\n const queryClient = useQueryClient()\n const readMessage = useReadMailMessage()\n useEffect(() => {\n if (!enabled || !isOnline || account?.provider !== 'native' || !messages) return\n const unkeyed = messages\n .filter((m) => !m.thread_id && m.id.startsWith('eml-') && !tried.has(m.id))\n .slice(0, BATCH)\n if (!unkeyed.length) return\n for (const m of unkeyed) tried.add(m.id)\n const keyable = unkeyed.filter((m) => m.message_id)\n if (!keyable.length) return\n void (async () => {\n try {\n // Fetched again for a batch after a minute, and after any failure: a secret kept across a\n // change on the server (a tab open through a deploy) would key mail into conversations\n // nobody else's keys match, for good.\n const secret = await queryClient.fetchQuery({\n queryKey: mailQueryKeys.threadSecret(),\n queryFn: () => mailOps.getNativeThreadSecret(client.fetch),\n staleTime: SECRET_FRESH_MS,\n })\n const keys: Record<string, { thread_hmac: string; message_id_hmac?: string }> = {}\n for (const listed of keyable) {\n // Older list rows carry no In-Reply-To: one without References is read in full for it.\n const source = listed.references.length\n ? listed\n : await readMessage(account, listed.id).catch(() => undefined)\n const key = source && (await nativeThreadKeys(secret, source))\n if (key) keys[listed.id] = key\n }\n if (!Object.keys(keys).length) return\n if ((await mailOps.submitNativeThreadKeys(client.fetch, keys)) > 0) {\n await queryClient.invalidateQueries({ queryKey: mailQueryKeys.allConversations() })\n await queryClient.invalidateQueries({ queryKey: mailQueryKeys.allMessages() })\n }\n } catch (error) {\n queryClient.removeQueries({ queryKey: mailQueryKeys.threadSecret() })\n for (const m of keyable) tried.delete(m.id)\n logger.warn('[mail] could not key older mail into conversations', error)\n }\n })()\n }, [account, messages, enabled, isOnline, client, queryClient, readMessage])\n}\n"],
5
+ "mappings": "AAYA,SAAS,iBAAiB;AAC1B,SAAS,sBAAsB;AAC/B,SAAS,cAAc;AACvB,SAAS,QAAQ,eAAe;AAChC,SAAS,eAAe,0BAA0B;AAClD,SAAS,qBAAqB;AAC9B,SAAS,wBAAwB;AACjC,SAAS,qBAAqB;AAI9B,MAAM,QAAQ;AAGd,MAAM,kBAAkB;AAMxB,MAAM,QAAQ,oBAAI,IAAY;AAGvB,SAAS,oBACd,SACA,UACM;AACN,QAAM,EAAE,QAAQ,QAAQ,IAAI,cAAc;AAC1C,QAAM,WAAW,cAAc;AAC/B,QAAM,cAAc,eAAe;AACnC,QAAM,cAAc,mBAAmB;AACvC,YAAU,MAAM;AACd,QAAI,CAAC,WAAW,CAAC,YAAY,SAAS,aAAa,YAAY,CAAC,SAAU;AAC1E,UAAM,UAAU,SACb,OAAO,CAAC,MAAM,CAAC,EAAE,aAAa,EAAE,GAAG,WAAW,MAAM,KAAK,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC,EACzE,MAAM,GAAG,KAAK;AACjB,QAAI,CAAC,QAAQ,OAAQ;AACrB,eAAW,KAAK,QAAS,OAAM,IAAI,EAAE,EAAE;AACvC,UAAM,UAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,UAAU;AAClD,QAAI,CAAC,QAAQ,OAAQ;AACrB,UAAM,YAAY;AAChB,UAAI;AAIF,cAAM,SAAS,MAAM,YAAY,WAAW;AAAA,UAC1C,UAAU,cAAc,aAAa;AAAA,UACrC,SAAS,MAAM,QAAQ,sBAAsB,OAAO,KAAK;AAAA,UACzD,WAAW;AAAA,QACb,CAAC;AACD,cAAM,OAA0E,CAAC;AACjF,mBAAW,UAAU,SAAS;AAE5B,gBAAM,SAAS,OAAO,WAAW,SAC7B,SACA,MAAM,YAAY,SAAS,OAAO,EAAE,EAAE,MAAM,MAAM,MAAS;AAC/D,gBAAM,MAAM,UAAW,MAAM,iBAAiB,QAAQ,MAAM;AAC5D,cAAI,IAAK,MAAK,OAAO,EAAE,IAAI;AAAA,QAC7B;AACA,YAAI,CAAC,OAAO,KAAK,IAAI,EAAE,OAAQ;AAC/B,YAAK,MAAM,QAAQ,uBAAuB,OAAO,OAAO,IAAI,IAAK,GAAG;AAClE,gBAAM,YAAY,kBAAkB,EAAE,UAAU,cAAc,iBAAiB,EAAE,CAAC;AAClF,gBAAM,YAAY,kBAAkB,EAAE,UAAU,cAAc,YAAY,EAAE,CAAC;AAAA,QAC/E;AAAA,MACF,SAAS,OAAO;AACd,oBAAY,cAAc,EAAE,UAAU,cAAc,aAAa,EAAE,CAAC;AACpE,mBAAW,KAAK,QAAS,OAAM,OAAO,EAAE,EAAE;AAC1C,eAAO,KAAK,sDAAsD,KAAK;AAAA,MACzE;AAAA,IACF,GAAG;AAAA,EACL,GAAG,CAAC,SAAS,UAAU,SAAS,UAAU,QAAQ,aAAa,WAAW,CAAC;AAC7E;",
6
+ "names": []
7
+ }
@@ -0,0 +1,71 @@
1
+ function mailConversationKey(message) {
2
+ return message.thread_id || message.id;
3
+ }
4
+ function toMailConversation(threadId, members) {
5
+ const newest = members[0];
6
+ const senders = /* @__PURE__ */ new Map();
7
+ for (const message of [...members].reverse())
8
+ for (const address of message.sender)
9
+ if (!senders.has(address.email.toLowerCase()))
10
+ senders.set(address.email.toLowerCase(), address);
11
+ return {
12
+ thread_id: threadId,
13
+ subject: [...members].reverse().find((m) => m.subject)?.subject ?? "",
14
+ preview: newest.preview,
15
+ senders: [...senders.values()],
16
+ received_at: newest.received_at ?? null,
17
+ message_count: members.length,
18
+ unread_count: members.filter((m) => m.unread).length,
19
+ flagged: members.some((m) => m.flagged),
20
+ messages: members
21
+ };
22
+ }
23
+ function groupMailConversations(messages) {
24
+ const groups = /* @__PURE__ */ new Map();
25
+ for (const message of messages) {
26
+ const key = mailConversationKey(message);
27
+ const members = groups.get(key);
28
+ if (members) members.push(message);
29
+ else groups.set(key, [message]);
30
+ }
31
+ return [...groups].map(([key, members]) => toMailConversation(key, members));
32
+ }
33
+ const MESSAGE_ID = /<[^<>\s]+>/g;
34
+ function ids(header) {
35
+ if (!header || header.length === 0) return [];
36
+ const text = Array.isArray(header) ? header.join(" ") : header;
37
+ return text.match(MESSAGE_ID) ?? text.split(/\s+/).filter(Boolean);
38
+ }
39
+ function mailThreadRoot(message) {
40
+ return ids(message.references)[0] ?? ids(message.in_reply_to)[0] ?? ids(message.message_id)[0];
41
+ }
42
+ async function hmacKey(secret, value) {
43
+ const key = await crypto.subtle.importKey(
44
+ "raw",
45
+ secret,
46
+ { name: "HMAC", hash: "SHA-256" },
47
+ false,
48
+ ["sign"]
49
+ );
50
+ const mac = new Uint8Array(
51
+ await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(`message:${value.trim()}`))
52
+ );
53
+ return Array.from(mac.slice(0, 16), (b) => b.toString(16).padStart(2, "0")).join("");
54
+ }
55
+ async function nativeThreadKeys(secret, message) {
56
+ const root = mailThreadRoot(message);
57
+ if (!root) return void 0;
58
+ const own = ids(message.message_id)[0];
59
+ return {
60
+ thread_hmac: await hmacKey(secret, root),
61
+ ...own && { message_id_hmac: await hmacKey(secret, own) }
62
+ };
63
+ }
64
+ export {
65
+ groupMailConversations,
66
+ mailConversationKey,
67
+ mailThreadRoot,
68
+ nativeThreadKeys,
69
+ toMailConversation
70
+ };
71
+ //# sourceMappingURL=threads.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/mail/threads.ts"],
4
+ "sourcesContent": ["/**\n * Conversations: how messages group into threads, the same rule as the server's, so a list read\n * from this device groups exactly as one read online (`group_conversations` in the backend).\n *\n * A message's conversation is its `thread_id`, else (it stands alone) its own id. Native mail's\n * thread id is a per-user key: an HMAC of the thread's root Message-ID (the first References entry,\n * else In-Reply-To, else its own Message-ID), as the backend's `email_threading.thread_keys`. The\n * server keys mail it stores; older mail is keyed by the owner's client ({@link nativeThreadKeys}),\n * because only the client can read its Message-IDs.\n */\n\nimport type { MailAddress, MailConversation, MailMessage } from './types'\n\n/** What groups a message into a conversation. */\nexport function mailConversationKey(message: Pick<MailMessage, 'id' | 'thread_id'>): string {\n return message.thread_id || message.id\n}\n\n/** A conversation row from its messages (newest first). */\nexport function toMailConversation(threadId: string, members: MailMessage[]): MailConversation {\n const newest = members[0]\n const senders = new Map<string, MailAddress>()\n for (const message of [...members].reverse())\n for (const address of message.sender)\n if (!senders.has(address.email.toLowerCase()))\n senders.set(address.email.toLowerCase(), address)\n return {\n thread_id: threadId,\n subject: [...members].reverse().find((m) => m.subject)?.subject ?? '',\n preview: newest.preview,\n senders: [...senders.values()],\n received_at: newest.received_at ?? null,\n message_count: members.length,\n unread_count: members.filter((m) => m.unread).length,\n flagged: members.some((m) => m.flagged),\n messages: members,\n }\n}\n\n/** Conversations of `messages` (newest first), in the order of each one's newest message. */\nexport function groupMailConversations(messages: MailMessage[]): MailConversation[] {\n const groups = new Map<string, MailMessage[]>()\n for (const message of messages) {\n const key = mailConversationKey(message)\n const members = groups.get(key)\n if (members) members.push(message)\n else groups.set(key, [message])\n }\n return [...groups].map(([key, members]) => toMailConversation(key, members))\n}\n\nconst MESSAGE_ID = /<[^<>\\s]+>/g\n\n/** Message-IDs in a header, as the backend reads them (`<\u2026>` tokens, else whitespace-split). */\nfunction ids(header: string | string[] | null | undefined): string[] {\n if (!header || header.length === 0) return []\n const text = Array.isArray(header) ? header.join(' ') : header\n return text.match(MESSAGE_ID) ?? text.split(/\\s+/).filter(Boolean)\n}\n\n/** The thread's root Message-ID: the first References entry, else In-Reply-To, else its own. */\nexport function mailThreadRoot(\n message: Pick<MailMessage, 'message_id' | 'in_reply_to' | 'references'>\n): string | undefined {\n return ids(message.references)[0] ?? ids(message.in_reply_to)[0] ?? ids(message.message_id)[0]\n}\n\nasync function hmacKey(secret: Uint8Array, value: string): Promise<string> {\n const key = await crypto.subtle.importKey(\n 'raw',\n secret as BufferSource,\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign']\n )\n const mac = new Uint8Array(\n await crypto.subtle.sign('HMAC', key, new TextEncoder().encode(`message:${value.trim()}`))\n )\n return Array.from(mac.slice(0, 16), (b) => b.toString(16).padStart(2, '0')).join('')\n}\n\n/**\n * A native message's keys, computed with the owner's thread secret: its thread key and its own\n * Message-ID's. `undefined` when it has no Message-ID to key (it stays a conversation of its own).\n */\nexport async function nativeThreadKeys(\n secret: Uint8Array,\n message: Pick<MailMessage, 'message_id' | 'in_reply_to' | 'references'>\n): Promise<{ thread_hmac: string; message_id_hmac?: string } | undefined> {\n const root = mailThreadRoot(message)\n if (!root) return undefined\n const own = ids(message.message_id)[0]\n return {\n thread_hmac: await hmacKey(secret, root),\n ...(own && { message_id_hmac: await hmacKey(secret, own) }),\n }\n}\n"],
5
+ "mappings": "AAcO,SAAS,oBAAoB,SAAwD;AAC1F,SAAO,QAAQ,aAAa,QAAQ;AACtC;AAGO,SAAS,mBAAmB,UAAkB,SAA0C;AAC7F,QAAM,SAAS,QAAQ,CAAC;AACxB,QAAM,UAAU,oBAAI,IAAyB;AAC7C,aAAW,WAAW,CAAC,GAAG,OAAO,EAAE,QAAQ;AACzC,eAAW,WAAW,QAAQ;AAC5B,UAAI,CAAC,QAAQ,IAAI,QAAQ,MAAM,YAAY,CAAC;AAC1C,gBAAQ,IAAI,QAAQ,MAAM,YAAY,GAAG,OAAO;AACtD,SAAO;AAAA,IACL,WAAW;AAAA,IACX,SAAS,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO,GAAG,WAAW;AAAA,IACnE,SAAS,OAAO;AAAA,IAChB,SAAS,CAAC,GAAG,QAAQ,OAAO,CAAC;AAAA,IAC7B,aAAa,OAAO,eAAe;AAAA,IACnC,eAAe,QAAQ;AAAA,IACvB,cAAc,QAAQ,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE;AAAA,IAC9C,SAAS,QAAQ,KAAK,CAAC,MAAM,EAAE,OAAO;AAAA,IACtC,UAAU;AAAA,EACZ;AACF;AAGO,SAAS,uBAAuB,UAA6C;AAClF,QAAM,SAAS,oBAAI,IAA2B;AAC9C,aAAW,WAAW,UAAU;AAC9B,UAAM,MAAM,oBAAoB,OAAO;AACvC,UAAM,UAAU,OAAO,IAAI,GAAG;AAC9B,QAAI,QAAS,SAAQ,KAAK,OAAO;AAAA,QAC5B,QAAO,IAAI,KAAK,CAAC,OAAO,CAAC;AAAA,EAChC;AACA,SAAO,CAAC,GAAG,MAAM,EAAE,IAAI,CAAC,CAAC,KAAK,OAAO,MAAM,mBAAmB,KAAK,OAAO,CAAC;AAC7E;AAEA,MAAM,aAAa;AAGnB,SAAS,IAAI,QAAwD;AACnE,MAAI,CAAC,UAAU,OAAO,WAAW,EAAG,QAAO,CAAC;AAC5C,QAAM,OAAO,MAAM,QAAQ,MAAM,IAAI,OAAO,KAAK,GAAG,IAAI;AACxD,SAAO,KAAK,MAAM,UAAU,KAAK,KAAK,MAAM,KAAK,EAAE,OAAO,OAAO;AACnE;AAGO,SAAS,eACd,SACoB;AACpB,SAAO,IAAI,QAAQ,UAAU,EAAE,CAAC,KAAK,IAAI,QAAQ,WAAW,EAAE,CAAC,KAAK,IAAI,QAAQ,UAAU,EAAE,CAAC;AAC/F;AAEA,eAAe,QAAQ,QAAoB,OAAgC;AACzE,QAAM,MAAM,MAAM,OAAO,OAAO;AAAA,IAC9B;AAAA,IACA;AAAA,IACA,EAAE,MAAM,QAAQ,MAAM,UAAU;AAAA,IAChC;AAAA,IACA,CAAC,MAAM;AAAA,EACT;AACA,QAAM,MAAM,IAAI;AAAA,IACd,MAAM,OAAO,OAAO,KAAK,QAAQ,KAAK,IAAI,YAAY,EAAE,OAAO,WAAW,MAAM,KAAK,CAAC,EAAE,CAAC;AAAA,EAC3F;AACA,SAAO,MAAM,KAAK,IAAI,MAAM,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,EAAE,SAAS,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE;AACrF;AAMA,eAAsB,iBACpB,QACA,SACwE;AACxE,QAAM,OAAO,eAAe,OAAO;AACnC,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,MAAM,IAAI,QAAQ,UAAU,EAAE,CAAC;AACrC,SAAO;AAAA,IACL,aAAa,MAAM,QAAQ,QAAQ,IAAI;AAAA,IACvC,GAAI,OAAO,EAAE,iBAAiB,MAAM,QAAQ,QAAQ,GAAG,EAAE;AAAA,EAC3D;AACF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,42 @@
1
+ import { useMemo } from "react";
2
+ import { useArbiHost } from "../host/config.js";
3
+ import { arbiMailClient, createMailClient } from "./client.js";
4
+ import { offlineMailReads } from "./offline/reads.js";
5
+ const NO_MAIL = {
6
+ client: createMailClient(
7
+ () => Promise.reject(new Error("Mail needs an <ArbiHost> with `mail` or an `arbi`"))
8
+ ),
9
+ enabled: false,
10
+ sessionKey: null
11
+ };
12
+ const ALWAYS = () => ({ enabled: true, sessionKey: "session" });
13
+ function useMailClient() {
14
+ const { mail, arbi } = useArbiHost();
15
+ const fallback = useMemo(
16
+ () => arbi ? arbiMailClient(
17
+ arbi,
18
+ offlineMailReads(() => arbi)
19
+ ) : null,
20
+ [arbi]
21
+ );
22
+ const useStatus = mail ? mail.useStatus ?? ALWAYS : ALWAYS;
23
+ const { enabled, sessionKey } = useStatus();
24
+ const client = mail?.client;
25
+ const provided = useMemo(
26
+ () => client ? { client, enabled, sessionKey } : null,
27
+ [client, enabled, sessionKey]
28
+ );
29
+ if (provided) return provided;
30
+ if (!arbi || !fallback) return NO_MAIL;
31
+ let identity = null;
32
+ try {
33
+ identity = arbi.isLoggedIn ? arbi.user.identity()?.externalId ?? "session" : null;
34
+ } catch {
35
+ identity = null;
36
+ }
37
+ return { client: fallback, enabled: identity !== null, sessionKey: identity };
38
+ }
39
+ export {
40
+ useMailClient
41
+ };
42
+ //# sourceMappingURL=useMailClient.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/mail/useMailClient.ts"],
4
+ "sourcesContent": ["import { useMemo } from 'react'\nimport { useArbiHost } from '../host/config'\nimport { arbiMailClient, createMailClient, type MailClient } from './client'\nimport { offlineMailReads } from './offline/reads'\n\nexport interface MailClientContextValue {\n client: MailClient\n /** Mail reads run only while this is true (signed in). */\n enabled: boolean\n /**\n * Identifies the server session the mailbox is unlocked for: unlocking runs again when it\n * changes. `null`: no session yet, so nothing is unlocked.\n */\n sessionKey: string | null\n}\n\nconst NO_MAIL: MailClientContextValue = {\n client: createMailClient(() =>\n Promise.reject(new Error('Mail needs an <ArbiHost> with `mail` or an `arbi`'))\n ),\n enabled: false,\n sessionKey: null,\n}\n\nconst ALWAYS = () => ({ enabled: true, sessionKey: 'session' })\n\n/**\n * The mail client in scope: the host configuration's `mail`, else one on its `arbi` session\n * (`arbiMailClient`) whose reads keep working offline from the mail kept on this device\n * (`offlineMailReads`).\n */\nexport function useMailClient(): MailClientContextValue {\n const { mail, arbi } = useArbiHost()\n const fallback = useMemo(\n () =>\n arbi\n ? arbiMailClient(\n arbi,\n offlineMailReads(() => arbi)\n )\n : null,\n [arbi]\n )\n // The host's status hook is fixed for its configuration's life.\n const useStatus = mail ? (mail.useStatus ?? ALWAYS) : ALWAYS\n const { enabled, sessionKey } = useStatus()\n const client = mail?.client\n const provided = useMemo(\n () => (client ? { client, enabled, sessionKey } : null),\n [client, enabled, sessionKey]\n )\n if (provided) return provided\n // Neither: mail stays off (reads disabled, writes refused) rather than breaking the screen.\n if (!arbi || !fallback) return NO_MAIL\n let identity: string | null = null\n try {\n identity = arbi.isLoggedIn ? (arbi.user.identity()?.externalId ?? 'session') : null\n } catch {\n identity = null\n }\n return { client: fallback, enabled: identity !== null, sessionKey: identity }\n}\n"],
5
+ "mappings": "AAAA,SAAS,eAAe;AACxB,SAAS,mBAAmB;AAC5B,SAAS,gBAAgB,wBAAyC;AAClE,SAAS,wBAAwB;AAajC,MAAM,UAAkC;AAAA,EACtC,QAAQ;AAAA,IAAiB,MACvB,QAAQ,OAAO,IAAI,MAAM,mDAAmD,CAAC;AAAA,EAC/E;AAAA,EACA,SAAS;AAAA,EACT,YAAY;AACd;AAEA,MAAM,SAAS,OAAO,EAAE,SAAS,MAAM,YAAY,UAAU;AAOtD,SAAS,gBAAwC;AACtD,QAAM,EAAE,MAAM,KAAK,IAAI,YAAY;AACnC,QAAM,WAAW;AAAA,IACf,MACE,OACI;AAAA,MACE;AAAA,MACA,iBAAiB,MAAM,IAAI;AAAA,IAC7B,IACA;AAAA,IACN,CAAC,IAAI;AAAA,EACP;AAEA,QAAM,YAAY,OAAQ,KAAK,aAAa,SAAU;AACtD,QAAM,EAAE,SAAS,WAAW,IAAI,UAAU;AAC1C,QAAM,SAAS,MAAM;AACrB,QAAM,WAAW;AAAA,IACf,MAAO,SAAS,EAAE,QAAQ,SAAS,WAAW,IAAI;AAAA,IAClD,CAAC,QAAQ,SAAS,UAAU;AAAA,EAC9B;AACA,MAAI,SAAU,QAAO;AAErB,MAAI,CAAC,QAAQ,CAAC,SAAU,QAAO;AAC/B,MAAI,WAA0B;AAC9B,MAAI;AACF,eAAW,KAAK,aAAc,KAAK,KAAK,SAAS,GAAG,cAAc,YAAa;AAAA,EACjF,QAAQ;AACN,eAAW;AAAA,EACb;AACA,SAAO,EAAE,QAAQ,UAAU,SAAS,aAAa,MAAM,YAAY,SAAS;AAC9E;",
6
+ "names": []
7
+ }