@arbidocs/react 0.5.111 → 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 (983) hide show
  1. package/dist/account/client.js +96 -0
  2. package/dist/account/client.js.map +7 -0
  3. package/dist/account/delete.js +70 -0
  4. package/dist/account/delete.js.map +7 -0
  5. package/dist/account/didit.js +34 -0
  6. package/dist/account/didit.js.map +7 -0
  7. package/dist/account/dismissed-tips.js +33 -0
  8. package/dist/account/dismissed-tips.js.map +7 -0
  9. package/dist/account/email.js +84 -0
  10. package/dist/account/email.js.map +7 -0
  11. package/dist/account/entitlements.js +47 -0
  12. package/dist/account/entitlements.js.map +7 -0
  13. package/dist/account/identity.js +270 -0
  14. package/dist/account/identity.js.map +7 -0
  15. package/dist/account/index.js +93 -0
  16. package/dist/account/index.js.map +7 -0
  17. package/dist/account/notifications.js +59 -0
  18. package/dist/account/notifications.js.map +7 -0
  19. package/dist/account/password.js +103 -0
  20. package/dist/account/password.js.map +7 -0
  21. package/dist/account/profile.js +116 -0
  22. package/dist/account/profile.js.map +7 -0
  23. package/dist/account/recovery.js +13 -0
  24. package/dist/account/recovery.js.map +7 -0
  25. package/dist/account/relevance.js +82 -0
  26. package/dist/account/relevance.js.map +7 -0
  27. package/dist/account/sessions.js +37 -0
  28. package/dist/account/sessions.js.map +7 -0
  29. package/dist/account/settings.js +39 -0
  30. package/dist/account/settings.js.map +7 -0
  31. package/dist/account/table-views.js +16 -0
  32. package/dist/account/table-views.js.map +7 -0
  33. package/dist/ai/AiAnswer.js +83 -0
  34. package/dist/ai/AiAnswer.js.map +7 -0
  35. package/dist/ai/AiMarkdown.js +40 -0
  36. package/dist/ai/AiMarkdown.js.map +7 -0
  37. package/dist/ai/ArtifactCanvas.js +193 -0
  38. package/dist/ai/ArtifactCanvas.js.map +7 -0
  39. package/dist/ai/CitationRenderer.js +413 -0
  40. package/dist/ai/CitationRenderer.js.map +7 -0
  41. package/dist/{chunk-WL2Y2T47.js → ai/MarkdownRenderer.js} +35 -101
  42. package/dist/ai/MarkdownRenderer.js.map +7 -0
  43. package/dist/ai/MessageArtifactCard.js +75 -0
  44. package/dist/ai/MessageArtifactCard.js.map +7 -0
  45. package/dist/ai/PassageCard.js +79 -0
  46. package/dist/ai/PassageCard.js.map +7 -0
  47. package/dist/ai/engine.js +110 -0
  48. package/dist/ai/engine.js.map +7 -0
  49. package/dist/ai/index.js +63 -0
  50. package/dist/ai/index.js.map +7 -0
  51. package/dist/ai/markdown-base-components.js +37 -0
  52. package/dist/ai/markdown-base-components.js.map +7 -0
  53. package/dist/ai/markdown-streaming-context.js +6 -0
  54. package/dist/ai/markdown-streaming-context.js.map +7 -0
  55. package/dist/{chunk-VSCU7K4V.js → ai/normalize-citations.js} +12 -19
  56. package/dist/ai/normalize-citations.js.map +7 -0
  57. package/dist/ai/redline.js +41 -0
  58. package/dist/ai/redline.js.map +7 -0
  59. package/dist/ai/split-markdown-blocks.js +40 -0
  60. package/dist/ai/split-markdown-blocks.js.map +7 -0
  61. package/dist/{chunk-UW2SGTI5.js → ai/stored-markdown.js} +41 -93
  62. package/dist/ai/stored-markdown.js.map +7 -0
  63. package/dist/annotations/AnnotationPageOverlay.js +807 -0
  64. package/dist/annotations/AnnotationPageOverlay.js.map +7 -0
  65. package/dist/annotations/AnnotationToolbar.js +398 -0
  66. package/dist/annotations/AnnotationToolbar.js.map +7 -0
  67. package/dist/annotations/FreezeDialog.js +170 -0
  68. package/dist/annotations/FreezeDialog.js.map +7 -0
  69. package/dist/annotations/ProductionDialog.js +354 -0
  70. package/dist/annotations/ProductionDialog.js.map +7 -0
  71. package/dist/annotations/controller.js +49 -0
  72. package/dist/annotations/controller.js.map +7 -0
  73. package/dist/annotations/freeze/browser.js +21 -0
  74. package/dist/annotations/freeze/browser.js.map +7 -0
  75. package/dist/annotations/freeze/bundle.js +201 -0
  76. package/dist/annotations/freeze/bundle.js.map +7 -0
  77. package/dist/annotations/freeze/coords.js +37 -0
  78. package/dist/annotations/freeze/coords.js.map +7 -0
  79. package/dist/annotations/freeze/freeze.js +261 -0
  80. package/dist/annotations/freeze/freeze.js.map +7 -0
  81. package/dist/annotations/freeze/hash.js +28 -0
  82. package/dist/annotations/freeze/hash.js.map +7 -0
  83. package/dist/annotations/freeze/index-page.js +78 -0
  84. package/dist/annotations/freeze/index-page.js.map +7 -0
  85. package/dist/annotations/freeze/index.js +28 -22
  86. package/dist/annotations/freeze/index.js.map +7 -1
  87. package/dist/annotations/freeze/raster.js +208 -0
  88. package/dist/annotations/freeze/raster.js.map +7 -0
  89. package/dist/annotations/freeze/stamp.js +117 -0
  90. package/dist/annotations/freeze/stamp.js.map +7 -0
  91. package/dist/annotations/freeze/types.js +14 -0
  92. package/dist/annotations/freeze/types.js.map +7 -0
  93. package/dist/annotations/freeze/vector.js +283 -0
  94. package/dist/annotations/freeze/vector.js.map +7 -0
  95. package/dist/annotations/geometry.js +81 -0
  96. package/dist/annotations/geometry.js.map +7 -0
  97. package/dist/annotations/index.js +125 -6
  98. package/dist/annotations/index.js.map +7 -1
  99. package/dist/annotations/merge.js +53 -0
  100. package/dist/annotations/merge.js.map +7 -0
  101. package/dist/{chunk-T3USOSVN.js → annotations/model.js} +23 -16
  102. package/dist/annotations/model.js.map +7 -0
  103. package/dist/annotations/overlay-geometry.js +41 -0
  104. package/dist/annotations/overlay-geometry.js.map +7 -0
  105. package/dist/annotations/redaction-log.js +33 -0
  106. package/dist/annotations/redaction-log.js.map +7 -0
  107. package/dist/annotations/selection-marks.js +122 -0
  108. package/dist/annotations/selection-marks.js.map +7 -0
  109. package/dist/annotations/state.js +140 -0
  110. package/dist/annotations/state.js.map +7 -0
  111. package/dist/annotations/store.js +49 -0
  112. package/dist/annotations/store.js.map +7 -0
  113. package/dist/annotations/useAnnotationLayer.js +306 -0
  114. package/dist/annotations/useAnnotationLayer.js.map +7 -0
  115. package/dist/annotations/useAnnotationShortcuts.js +31 -0
  116. package/dist/annotations/useAnnotationShortcuts.js.map +7 -0
  117. package/dist/annotations/useTextSelectionMarks.js +100 -0
  118. package/dist/annotations/useTextSelectionMarks.js.map +7 -0
  119. package/dist/artifacts/artifact-kind.js +19 -0
  120. package/dist/artifacts/artifact-kind.js.map +7 -0
  121. package/dist/artifacts/index.js +89 -571
  122. package/dist/artifacts/index.js.map +7 -1
  123. package/dist/{chunk-WUTL62MC.js → artifacts/normalize-markdown.js} +12 -14
  124. package/dist/artifacts/normalize-markdown.js.map +7 -0
  125. package/dist/artifacts/redline-core.js +12 -3
  126. package/dist/artifacts/redline-core.js.map +7 -1
  127. package/dist/{chunk-74N436VK.js → artifacts/redline-diff.js} +10 -9
  128. package/dist/artifacts/redline-diff.js.map +7 -0
  129. package/dist/artifacts/redline-engine.js +14 -0
  130. package/dist/artifacts/redline-engine.js.map +7 -0
  131. package/dist/artifacts/renderArtifactMarkdown.js +9 -0
  132. package/dist/artifacts/renderArtifactMarkdown.js.map +7 -0
  133. package/dist/artifacts/useArtifactEditSession.js +183 -0
  134. package/dist/artifacts/useArtifactEditSession.js.map +7 -0
  135. package/dist/artifacts/useArtifactSession.js +173 -0
  136. package/dist/artifacts/useArtifactSession.js.map +7 -0
  137. package/dist/artifacts/useArtifactSource.js +16 -0
  138. package/dist/artifacts/useArtifactSource.js.map +7 -0
  139. package/dist/artifacts/useArtifactText.js +78 -0
  140. package/dist/artifacts/useArtifactText.js.map +7 -0
  141. package/dist/artifacts/useRedline.js +65 -0
  142. package/dist/artifacts/useRedline.js.map +7 -0
  143. package/dist/artifacts/useStreamedArtifact.js +74 -0
  144. package/dist/artifacts/useStreamedArtifact.js.map +7 -0
  145. package/dist/artifacts/versions.js +68 -0
  146. package/dist/artifacts/versions.js.map +7 -0
  147. package/dist/billing.js +200 -0
  148. package/dist/billing.js.map +7 -0
  149. package/dist/boot-timeout.js +19 -0
  150. package/dist/boot-timeout.js.map +7 -0
  151. package/dist/calendar/accounts.js +213 -0
  152. package/dist/calendar/accounts.js.map +7 -0
  153. package/dist/calendar/hooks.js +409 -0
  154. package/dist/calendar/hooks.js.map +7 -0
  155. package/dist/calendar/index.js +31 -0
  156. package/dist/calendar/index.js.map +7 -0
  157. package/dist/calendar/keys.js +5 -0
  158. package/dist/calendar/keys.js.map +7 -0
  159. package/dist/calendar/offline/outbox.js +231 -0
  160. package/dist/calendar/offline/outbox.js.map +7 -0
  161. package/dist/calendar/offline/runtime.js +109 -0
  162. package/dist/calendar/offline/runtime.js.map +7 -0
  163. package/dist/calendar/offline/support.js +41 -0
  164. package/dist/calendar/offline/support.js.map +7 -0
  165. package/dist/calendar/support.js +34 -0
  166. package/dist/calendar/support.js.map +7 -0
  167. package/dist/calls/actions.js +226 -0
  168. package/dist/calls/actions.js.map +7 -0
  169. package/dist/calls/events.js +138 -0
  170. package/dist/calls/events.js.map +7 -0
  171. package/dist/calls/gate.js +19 -0
  172. package/dist/calls/gate.js.map +7 -0
  173. package/dist/calls/hooks.js +115 -0
  174. package/dist/calls/hooks.js.map +7 -0
  175. package/dist/calls/in-call-chat.js +132 -0
  176. package/dist/calls/in-call-chat.js.map +7 -0
  177. package/dist/calls/index.js +24 -0
  178. package/dist/calls/index.js.map +7 -0
  179. package/dist/calls/keys.js +17 -0
  180. package/dist/calls/keys.js.map +7 -0
  181. package/dist/calls/livekit/index.js +6 -958
  182. package/dist/calls/livekit/index.js.map +7 -1
  183. package/dist/calls/livekit/room.js +98 -0
  184. package/dist/calls/livekit/room.js.map +7 -0
  185. package/dist/calls/livekit/useCallRecorder.js +219 -0
  186. package/dist/calls/livekit/useCallRecorder.js.map +7 -0
  187. package/dist/calls/livekit/useCallTranscriber.js +309 -0
  188. package/dist/calls/livekit/useCallTranscriber.js.map +7 -0
  189. package/dist/calls/livekit/useHostMuteNotice.js +29 -0
  190. package/dist/calls/livekit/useHostMuteNotice.js.map +7 -0
  191. package/dist/calls/livekit/useInCallChat.js +161 -0
  192. package/dist/calls/livekit/useInCallChat.js.map +7 -0
  193. package/dist/calls/livekit/useWebinar.js +239 -0
  194. package/dist/calls/livekit/useWebinar.js.map +7 -0
  195. package/dist/calls/meeting-chat.js +149 -0
  196. package/dist/calls/meeting-chat.js.map +7 -0
  197. package/dist/calls/moderation.js +50 -0
  198. package/dist/calls/moderation.js.map +7 -0
  199. package/dist/calls/open-meeting-chat.js +29 -0
  200. package/dist/calls/open-meeting-chat.js.map +7 -0
  201. package/dist/calls/read-only.js +24 -0
  202. package/dist/calls/read-only.js.map +7 -0
  203. package/dist/calls/recording-media.js +218 -0
  204. package/dist/calls/recording-media.js.map +7 -0
  205. package/dist/calls/recording-playback.js +260 -0
  206. package/dist/calls/recording-playback.js.map +7 -0
  207. package/dist/calls/recording.js +268 -0
  208. package/dist/calls/recording.js.map +7 -0
  209. package/dist/calls/save-to-thread.js +80 -0
  210. package/dist/calls/save-to-thread.js.map +7 -0
  211. package/dist/calls/session.js +134 -0
  212. package/dist/calls/session.js.map +7 -0
  213. package/dist/calls/transcript-format.js +147 -0
  214. package/dist/calls/transcript-format.js.map +7 -0
  215. package/dist/calls/transcription.js +101 -0
  216. package/dist/calls/transcription.js.map +7 -0
  217. package/dist/calls/webinar.js +71 -0
  218. package/dist/calls/webinar.js.map +7 -0
  219. package/dist/charge-watch.js +71 -0
  220. package/dist/charge-watch.js.map +7 -0
  221. package/dist/chat/ChatBubble.js +146 -0
  222. package/dist/chat/ChatBubble.js.map +7 -0
  223. package/dist/chat/ConversationScope.js +30 -0
  224. package/dist/chat/ConversationScope.js.map +7 -0
  225. package/dist/chat/active-config.js +20 -0
  226. package/dist/chat/active-config.js.map +7 -0
  227. package/dist/chat/agent-chat-owner.js +25 -0
  228. package/dist/chat/agent-chat-owner.js.map +7 -0
  229. package/dist/chat/chat-artifacts.js +64 -0
  230. package/dist/chat/chat-artifacts.js.map +7 -0
  231. package/dist/chat/citations.js +32 -0
  232. package/dist/chat/citations.js.map +7 -0
  233. package/dist/chat/config-model.js +10 -0
  234. package/dist/chat/config-model.js.map +7 -0
  235. package/dist/chat/conversation-cache.js +676 -0
  236. package/dist/chat/conversation-cache.js.map +7 -0
  237. package/dist/chat/conversation-events.js +57 -0
  238. package/dist/chat/conversation-events.js.map +7 -0
  239. package/dist/chat/conversation-mentions.js +58 -0
  240. package/dist/chat/conversation-mentions.js.map +7 -0
  241. package/dist/chat/conversation-workspace.js +58 -0
  242. package/dist/chat/conversation-workspace.js.map +7 -0
  243. package/dist/chat/mentions.js +116 -0
  244. package/dist/chat/mentions.js.map +7 -0
  245. package/dist/chat/open-document.js +106 -0
  246. package/dist/chat/open-document.js.map +7 -0
  247. package/dist/chat/orphaned.js +44 -0
  248. package/dist/chat/orphaned.js.map +7 -0
  249. package/dist/chat/pendingFirstTurn.js +30 -0
  250. package/dist/chat/pendingFirstTurn.js.map +7 -0
  251. package/dist/chat/reply-target.js +12 -0
  252. package/dist/chat/reply-target.js.map +7 -0
  253. package/dist/chat/run-finished.js +28 -0
  254. package/dist/chat/run-finished.js.map +7 -0
  255. package/dist/chat/run-state.js +91 -0
  256. package/dist/chat/run-state.js.map +7 -0
  257. package/dist/chat/stream-handlers.js +419 -0
  258. package/dist/chat/stream-handlers.js.map +7 -0
  259. package/dist/chat/thread-binding.js +76 -0
  260. package/dist/chat/thread-binding.js.map +7 -0
  261. package/dist/chat/thread-document.js +53 -0
  262. package/dist/chat/thread-document.js.map +7 -0
  263. package/dist/chat/turn-control.js +79 -0
  264. package/dist/chat/turn-control.js.map +7 -0
  265. package/dist/chat/useAgentRunControl.js +36 -0
  266. package/dist/chat/useAgentRunControl.js.map +7 -0
  267. package/dist/chat/useAnswerAgentQuestion.js +19 -0
  268. package/dist/chat/useAnswerAgentQuestion.js.map +7 -0
  269. package/dist/chat/useAskAgain.js +32 -0
  270. package/dist/chat/useAskAgain.js.map +7 -0
  271. package/dist/chat/useAutoSendDraft.js +17 -0
  272. package/dist/chat/useAutoSendDraft.js.map +7 -0
  273. package/dist/chat/useBranchNavigation.js +97 -0
  274. package/dist/chat/useBranchNavigation.js.map +7 -0
  275. package/dist/chat/useConnectRunStream.js +169 -0
  276. package/dist/chat/useConnectRunStream.js.map +7 -0
  277. package/dist/chat/useConversation.js +431 -0
  278. package/dist/chat/useConversation.js.map +7 -0
  279. package/dist/chat/useConversationActions.js +662 -0
  280. package/dist/chat/useConversationActions.js.map +7 -0
  281. package/dist/chat/useConversationData.js +143 -0
  282. package/dist/chat/useConversationData.js.map +7 -0
  283. package/dist/chat/useConversationDocuments.js +41 -0
  284. package/dist/chat/useConversationDocuments.js.map +7 -0
  285. package/dist/chat/useConversationSettings.js +78 -0
  286. package/dist/chat/useConversationSettings.js.map +7 -0
  287. package/dist/chat/useConversationTurn.js +31 -0
  288. package/dist/chat/useConversationTurn.js.map +7 -0
  289. package/dist/chat/useConversationWorkspace.js +12 -0
  290. package/dist/chat/useConversationWorkspace.js.map +7 -0
  291. package/dist/chat/useDeleteMessage.js +15 -0
  292. package/dist/chat/useDeleteMessage.js.map +7 -0
  293. package/dist/chat/useDocumentAutoAdd.js +73 -0
  294. package/dist/chat/useDocumentAutoAdd.js.map +7 -0
  295. package/dist/chat/useMessageTimer.js +39 -0
  296. package/dist/chat/useMessageTimer.js.map +7 -0
  297. package/dist/chat/useThinkingContent.js +67 -0
  298. package/dist/chat/useThinkingContent.js.map +7 -0
  299. package/dist/chat/useThreadDocument.js +61 -0
  300. package/dist/chat/useThreadDocument.js.map +7 -0
  301. package/dist/chat/workflow-run-titles.js +50 -0
  302. package/dist/chat/workflow-run-titles.js.map +7 -0
  303. package/dist/{chunk-Z3W4XFWB.cjs → chunk-C72FSQUE.cjs} +3 -3
  304. package/dist/{chunk-Z3W4XFWB.cjs.map → chunk-C72FSQUE.cjs.map} +1 -1
  305. package/dist/{chunk-LBAG7KL7.cjs → chunk-FQVNZCTD.cjs} +3 -3
  306. package/dist/{chunk-LBAG7KL7.cjs.map → chunk-FQVNZCTD.cjs.map} +1 -1
  307. package/dist/{chunk-DI5KSVKY.cjs → chunk-UDDJIUHJ.cjs} +3 -3
  308. package/dist/{chunk-DI5KSVKY.cjs.map → chunk-UDDJIUHJ.cjs.map} +1 -1
  309. package/dist/config/config-hooks.js +209 -0
  310. package/dist/config/config-hooks.js.map +7 -0
  311. package/dist/connectivity.js +72 -0
  312. package/dist/connectivity.js.map +7 -0
  313. package/dist/connectors/hooks.js +263 -0
  314. package/dist/connectors/hooks.js.map +7 -0
  315. package/dist/connectors/index.js +28 -0
  316. package/dist/connectors/index.js.map +7 -0
  317. package/dist/contacts.js +100 -0
  318. package/dist/contacts.js.map +7 -0
  319. package/dist/conversation-list.js +65 -0
  320. package/dist/conversation-list.js.map +7 -0
  321. package/dist/databases.js +195 -0
  322. package/dist/databases.js.map +7 -0
  323. package/dist/datasets/aggregate.js +281 -0
  324. package/dist/datasets/aggregate.js.map +7 -0
  325. package/dist/datasets/index.js +122 -0
  326. package/dist/datasets/index.js.map +7 -0
  327. package/dist/datasets/members.js +27 -0
  328. package/dist/datasets/members.js.map +7 -0
  329. package/dist/datasets/panel.js +44 -0
  330. package/dist/datasets/panel.js.map +7 -0
  331. package/dist/datasets/registry.js +47 -0
  332. package/dist/datasets/registry.js.map +7 -0
  333. package/dist/datasets/rows-source.js +44 -0
  334. package/dist/datasets/rows-source.js.map +7 -0
  335. package/dist/datasets/sources/activity.js +83 -0
  336. package/dist/datasets/sources/activity.js.map +7 -0
  337. package/dist/datasets/sources/conversations.js +74 -0
  338. package/dist/datasets/sources/conversations.js.map +7 -0
  339. package/dist/datasets/sources/database.js +209 -0
  340. package/dist/datasets/sources/database.js.map +7 -0
  341. package/dist/datasets/sources/documents.js +93 -0
  342. package/dist/datasets/sources/documents.js.map +7 -0
  343. package/dist/datasets/sources/facts.js +56 -0
  344. package/dist/datasets/sources/facts.js.map +7 -0
  345. package/dist/datasets/sources/projects.js +117 -0
  346. package/dist/datasets/sources/projects.js.map +7 -0
  347. package/dist/datasets/sources/tags.js +67 -0
  348. package/dist/datasets/sources/tags.js.map +7 -0
  349. package/dist/datasets/sources/usage.js +268 -0
  350. package/dist/datasets/sources/usage.js.map +7 -0
  351. package/dist/datasets/sources/workflows.js +91 -0
  352. package/dist/datasets/sources/workflows.js.map +7 -0
  353. package/dist/datasets/sources/workspaces.js +67 -0
  354. package/dist/datasets/sources/workspaces.js.map +7 -0
  355. package/dist/datasets/store.js +194 -0
  356. package/dist/datasets/store.js.map +7 -0
  357. package/dist/datasets/types.js +14 -0
  358. package/dist/datasets/types.js.map +7 -0
  359. package/dist/directmessages/ConversationList.js +148 -0
  360. package/dist/directmessages/ConversationList.js.map +7 -0
  361. package/dist/directmessages/DateSeparator.js +8 -0
  362. package/dist/directmessages/DateSeparator.js.map +7 -0
  363. package/dist/directmessages/DmAvatar.js +29 -0
  364. package/dist/directmessages/DmAvatar.js.map +7 -0
  365. package/dist/directmessages/DmComposer.js +201 -0
  366. package/dist/directmessages/DmComposer.js.map +7 -0
  367. package/dist/directmessages/arrivals.js +29 -0
  368. package/dist/directmessages/arrivals.js.map +7 -0
  369. package/dist/directmessages/chat-cache.js +192 -0
  370. package/dist/directmessages/chat-cache.js.map +7 -0
  371. package/dist/directmessages/grouping.js +26 -0
  372. package/dist/directmessages/grouping.js.map +7 -0
  373. package/dist/directmessages/index.js +81 -0
  374. package/dist/directmessages/index.js.map +7 -0
  375. package/dist/directmessages/useChats.js +266 -0
  376. package/dist/directmessages/useChats.js.map +7 -0
  377. package/dist/directmessages/utils.js +23 -0
  378. package/dist/directmessages/utils.js.map +7 -0
  379. package/dist/document-tools/can-annotate.js +7 -0
  380. package/dist/document-tools/can-annotate.js.map +7 -0
  381. package/dist/document-tools/core.cjs +80 -80
  382. package/dist/document-tools/core.js +218 -12
  383. package/dist/document-tools/core.js.map +7 -1
  384. package/dist/document-tools/document-pdf.js +76 -0
  385. package/dist/document-tools/document-pdf.js.map +7 -0
  386. package/dist/document-tools/environment.js +136 -0
  387. package/dist/document-tools/environment.js.map +7 -0
  388. package/dist/document-tools/file-shares.js +112 -0
  389. package/dist/document-tools/file-shares.js.map +7 -0
  390. package/dist/document-tools/frozen-copy.js +27 -0
  391. package/dist/document-tools/frozen-copy.js.map +7 -0
  392. package/dist/document-tools/index.cjs +80 -80
  393. package/dist/document-tools/index.js +26 -148
  394. package/dist/document-tools/index.js.map +7 -1
  395. package/dist/document-tools/markup-download.js +51 -0
  396. package/dist/document-tools/markup-download.js.map +7 -0
  397. package/dist/document-tools/markup-store.js +138 -0
  398. package/dist/document-tools/markup-store.js.map +7 -0
  399. package/dist/document-tools/markup-transfer.js +88 -0
  400. package/dist/document-tools/markup-transfer.js.map +7 -0
  401. package/dist/document-tools/production.js +147 -0
  402. package/dist/document-tools/production.js.map +7 -0
  403. package/dist/document-tools/saved-signature.js +90 -0
  404. package/dist/document-tools/saved-signature.js.map +7 -0
  405. package/dist/document-tools/signature-requests.js +310 -0
  406. package/dist/document-tools/signature-requests.js.map +7 -0
  407. package/dist/document-tools/signing.js +127 -0
  408. package/dist/document-tools/signing.js.map +7 -0
  409. package/dist/document-tools/useDocumentBytes.js +38 -0
  410. package/dist/document-tools/useDocumentBytes.js.map +7 -0
  411. package/dist/document-tools/useDocumentMarkup.js +154 -0
  412. package/dist/document-tools/useDocumentMarkup.js.map +7 -0
  413. package/dist/document-tools/useIsOnline.js +13 -0
  414. package/dist/document-tools/useIsOnline.js.map +7 -0
  415. package/dist/document-tools/verification.js +60 -0
  416. package/dist/document-tools/verification.js.map +7 -0
  417. package/dist/documents/DocumentReview.js +220 -0
  418. package/dist/documents/DocumentReview.js.map +7 -0
  419. package/dist/documents/DraftTitleControls.js +41 -0
  420. package/dist/documents/DraftTitleControls.js.map +7 -0
  421. package/dist/documents/InlineMicButton.js +90 -0
  422. package/dist/documents/InlineMicButton.js.map +7 -0
  423. package/dist/documents/MicRecordingOverlay.js +29 -0
  424. package/dist/documents/MicRecordingOverlay.js.map +7 -0
  425. package/dist/documents/MicWaveformIndicator.js +68 -0
  426. package/dist/documents/MicWaveformIndicator.js.map +7 -0
  427. package/dist/documents/PhotoCapture.js +120 -0
  428. package/dist/documents/PhotoCapture.js.map +7 -0
  429. package/dist/documents/VideoCapture.js +129 -0
  430. package/dist/documents/VideoCapture.js.map +7 -0
  431. package/dist/documents/VoiceNoteRecorder.js +166 -0
  432. package/dist/documents/VoiceNoteRecorder.js.map +7 -0
  433. package/dist/documents/audio-segmenter.js +63 -0
  434. package/dist/documents/audio-segmenter.js.map +7 -0
  435. package/dist/documents/capture-frame.js +21 -0
  436. package/dist/documents/capture-frame.js.map +7 -0
  437. package/dist/documents/chunked-recorder.js +190 -0
  438. package/dist/documents/chunked-recorder.js.map +7 -0
  439. package/dist/documents/document-download.js +53 -0
  440. package/dist/documents/document-download.js.map +7 -0
  441. package/dist/documents/document-fields.js +109 -0
  442. package/dist/documents/document-fields.js.map +7 -0
  443. package/dist/documents/documents-cache.js +110 -0
  444. package/dist/documents/documents-cache.js.map +7 -0
  445. package/dist/documents/documents-data.js +128 -0
  446. package/dist/documents/documents-data.js.map +7 -0
  447. package/dist/documents/documents-loader.js +113 -0
  448. package/dist/documents/documents-loader.js.map +7 -0
  449. package/dist/documents/documents-writes.js +448 -0
  450. package/dist/documents/documents-writes.js.map +7 -0
  451. package/dist/documents/format-elapsed.js +10 -0
  452. package/dist/documents/format-elapsed.js.map +7 -0
  453. package/dist/documents/has-video-track.js +26 -0
  454. package/dist/documents/has-video-track.js.map +7 -0
  455. package/dist/documents/index.js +266 -0
  456. package/dist/documents/index.js.map +7 -0
  457. package/dist/documents/media-error.js +18 -0
  458. package/dist/documents/media-error.js.map +7 -0
  459. package/dist/documents/offline-documents.js +160 -0
  460. package/dist/documents/offline-documents.js.map +7 -0
  461. package/dist/documents/pending-sync.js +210 -0
  462. package/dist/documents/pending-sync.js.map +7 -0
  463. package/dist/documents/processing-live.js +122 -0
  464. package/dist/documents/processing-live.js.map +7 -0
  465. package/dist/documents/processing-order.js +59 -0
  466. package/dist/documents/processing-order.js.map +7 -0
  467. package/dist/documents/processing-settle.js +21 -0
  468. package/dist/documents/processing-settle.js.map +7 -0
  469. package/dist/documents/related-documents.js +133 -0
  470. package/dist/documents/related-documents.js.map +7 -0
  471. package/dist/documents/support.js +29 -0
  472. package/dist/documents/support.js.map +7 -0
  473. package/dist/documents/upload-files.js +169 -0
  474. package/dist/documents/upload-files.js.map +7 -0
  475. package/dist/documents/useAudioRecorder.js +315 -0
  476. package/dist/documents/useAudioRecorder.js.map +7 -0
  477. package/dist/documents/useCameraStream.js +35 -0
  478. package/dist/documents/useCameraStream.js.map +7 -0
  479. package/dist/documents/useDocumentThumbnails.js +71 -0
  480. package/dist/documents/useDocumentThumbnails.js.map +7 -0
  481. package/dist/documents/useDownloadDocuments.js +90 -0
  482. package/dist/documents/useDownloadDocuments.js.map +7 -0
  483. package/dist/documents/usePassageQuotes.js +37 -0
  484. package/dist/documents/usePassageQuotes.js.map +7 -0
  485. package/dist/documents/useUploadFiles.js +165 -0
  486. package/dist/documents/useUploadFiles.js.map +7 -0
  487. package/dist/documents/useUploadFromUrls.js +63 -0
  488. package/dist/documents/useUploadFromUrls.js.map +7 -0
  489. package/dist/documents/useVideoRecorder.js +62 -0
  490. package/dist/documents/useVideoRecorder.js.map +7 -0
  491. package/dist/entities/AgentMarkers.js +61 -0
  492. package/dist/entities/AgentMarkers.js.map +7 -0
  493. package/dist/entities/DocumentEntity.js +125 -0
  494. package/dist/entities/DocumentEntity.js.map +7 -0
  495. package/dist/entities/EntityPill.js +250 -0
  496. package/dist/entities/EntityPill.js.map +7 -0
  497. package/dist/entities/ProjectEntity.js +61 -0
  498. package/dist/entities/ProjectEntity.js.map +7 -0
  499. package/dist/entities/ShieldIcon.js +49 -0
  500. package/dist/entities/ShieldIcon.js.map +7 -0
  501. package/dist/entities/TagEntity.js +79 -0
  502. package/dist/entities/TagEntity.js.map +7 -0
  503. package/dist/entities/ThreadVisibilityIcon.js +15 -0
  504. package/dist/entities/ThreadVisibilityIcon.js.map +7 -0
  505. package/dist/entities/UserEntity.js +211 -0
  506. package/dist/entities/UserEntity.js.map +7 -0
  507. package/dist/entities/VerifiedBadge.js +19 -0
  508. package/dist/entities/VerifiedBadge.js.map +7 -0
  509. package/dist/entities/agent-avatar-colors.js +26 -0
  510. package/dist/entities/agent-avatar-colors.js.map +7 -0
  511. package/dist/entities/colors.js +64 -0
  512. package/dist/entities/colors.js.map +7 -0
  513. package/dist/entities/file-type.js +151 -0
  514. package/dist/entities/file-type.js.map +7 -0
  515. package/dist/entities/index.js +100 -0
  516. package/dist/entities/index.js.map +7 -0
  517. package/dist/entities/media-type.js +61 -0
  518. package/dist/entities/media-type.js.map +7 -0
  519. package/dist/entities/registry.js +385 -0
  520. package/dist/entities/registry.js.map +7 -0
  521. package/dist/entities/status.js +43 -0
  522. package/dist/entities/status.js.map +7 -0
  523. package/dist/entities/tag-kinds.js +23 -0
  524. package/dist/entities/tag-kinds.js.map +7 -0
  525. package/dist/entities/tag-types.js +44 -0
  526. package/dist/entities/tag-types.js.map +7 -0
  527. package/dist/entities/vocabulary.js +12 -0
  528. package/dist/entities/vocabulary.js.map +7 -0
  529. package/dist/entity-extraction.js +25 -0
  530. package/dist/entity-extraction.js.map +7 -0
  531. package/dist/facts-search.js +57 -0
  532. package/dist/facts-search.js.map +7 -0
  533. package/dist/facts.js +69 -0
  534. package/dist/facts.js.map +7 -0
  535. package/dist/hooks.js +320 -0
  536. package/dist/hooks.js.map +7 -0
  537. package/dist/host/ArbiHost.js +24 -0
  538. package/dist/host/ArbiHost.js.map +7 -0
  539. package/dist/host/assistant-copy.js +54 -0
  540. package/dist/host/assistant-copy.js.map +7 -0
  541. package/dist/host/config.js +9 -0
  542. package/dist/host/config.js.map +7 -0
  543. package/dist/host/context.js +10 -0
  544. package/dist/host/context.js.map +7 -0
  545. package/dist/host/features.js +144 -0
  546. package/dist/host/features.js.map +7 -0
  547. package/dist/host/index.js +12 -0
  548. package/dist/host/index.js.map +7 -0
  549. package/dist/{chunk-DPYBZDJB.js → host/merge.js} +7 -7
  550. package/dist/host/merge.js.map +7 -0
  551. package/dist/house-template.js +40 -0
  552. package/dist/house-template.js.map +7 -0
  553. package/dist/icons/AppleIcon.js +25 -0
  554. package/dist/icons/AppleIcon.js.map +7 -0
  555. package/dist/icons/ArbiBotHeadIcon.js +46 -0
  556. package/dist/icons/ArbiBotHeadIcon.js.map +7 -0
  557. package/dist/icons/ArbiIcon.js +24 -0
  558. package/dist/icons/ArbiIcon.js.map +7 -0
  559. package/dist/icons/AudIcon.js +56 -0
  560. package/dist/icons/AudIcon.js.map +7 -0
  561. package/dist/icons/ClaudeIcon.js +28 -0
  562. package/dist/icons/ClaudeIcon.js.map +7 -0
  563. package/dist/icons/DocIcon.js +56 -0
  564. package/dist/icons/DocIcon.js.map +7 -0
  565. package/dist/icons/EmlIcon.js +57 -0
  566. package/dist/icons/EmlIcon.js.map +7 -0
  567. package/dist/icons/FireworksIcon.js +47 -0
  568. package/dist/icons/FireworksIcon.js.map +7 -0
  569. package/dist/icons/GeminiIcon.js +37 -0
  570. package/dist/icons/GeminiIcon.js.map +7 -0
  571. package/dist/icons/GitHubIcon.js +32 -0
  572. package/dist/icons/GitHubIcon.js.map +7 -0
  573. package/dist/icons/GoogleIcon.js +53 -0
  574. package/dist/icons/GoogleIcon.js.map +7 -0
  575. package/dist/icons/HtmlIcon.js +56 -0
  576. package/dist/icons/HtmlIcon.js.map +7 -0
  577. package/dist/icons/ImgIcon.js +56 -0
  578. package/dist/icons/ImgIcon.js.map +7 -0
  579. package/dist/icons/LinkedInIcon.js +25 -0
  580. package/dist/icons/LinkedInIcon.js.map +7 -0
  581. package/dist/icons/OpenAIIcon.js +28 -0
  582. package/dist/icons/OpenAIIcon.js.map +7 -0
  583. package/dist/icons/PdfIcon.js +56 -0
  584. package/dist/icons/PdfIcon.js.map +7 -0
  585. package/dist/icons/ProviderIcon.js +42 -0
  586. package/dist/icons/ProviderIcon.js.map +7 -0
  587. package/dist/icons/TxtIcon.js +56 -0
  588. package/dist/icons/TxtIcon.js.map +7 -0
  589. package/dist/icons/VidIcon.js +56 -0
  590. package/dist/icons/VidIcon.js.map +7 -0
  591. package/dist/icons/XlsIcon.js +56 -0
  592. package/dist/icons/XlsIcon.js.map +7 -0
  593. package/dist/icons/arbi-mark.js +5 -0
  594. package/dist/icons/arbi-mark.js.map +7 -0
  595. package/dist/icons/colors.js +31 -0
  596. package/dist/icons/colors.js.map +7 -0
  597. package/dist/icons/file-type.js +105 -0
  598. package/dist/icons/file-type.js.map +7 -0
  599. package/dist/icons/index.js +55 -0
  600. package/dist/icons/index.js.map +7 -0
  601. package/dist/imagecrop/ImageCropModal.js +56 -0
  602. package/dist/imagecrop/ImageCropModal.js.map +7 -0
  603. package/dist/imagecrop/ImageCropper.js +100 -0
  604. package/dist/imagecrop/ImageCropper.js.map +7 -0
  605. package/dist/imagecrop/cropImage.js +43 -0
  606. package/dist/imagecrop/cropImage.js.map +7 -0
  607. package/dist/imagecrop/index.js +13 -0
  608. package/dist/imagecrop/index.js.map +7 -0
  609. package/dist/index.cjs +282 -282
  610. package/dist/index.js +702 -17116
  611. package/dist/index.js.map +7 -1
  612. package/dist/{chunk-SSXFVWCT.js → lazy-chunk.js} +8 -8
  613. package/dist/lazy-chunk.js.map +7 -0
  614. package/dist/lib/collision-padding.js +13 -0
  615. package/dist/lib/collision-padding.js.map +7 -0
  616. package/dist/lib/format-friendly-date.js +55 -0
  617. package/dist/lib/format-friendly-date.js.map +7 -0
  618. package/dist/lib/format-relative-time.js +52 -0
  619. package/dist/lib/format-relative-time.js.map +7 -0
  620. package/dist/lib/markdown-to-text.js +35 -0
  621. package/dist/lib/markdown-to-text.js.map +7 -0
  622. package/dist/lib/toast-interaction.js +9 -0
  623. package/dist/lib/toast-interaction.js.map +7 -0
  624. package/dist/lib/utils.js +9 -0
  625. package/dist/lib/utils.js.map +7 -0
  626. package/dist/mail/client.js +103 -0
  627. package/dist/mail/client.js.map +7 -0
  628. package/dist/mail/document-attachment.js +38 -0
  629. package/dist/mail/document-attachment.js.map +7 -0
  630. package/dist/mail/filing.js +132 -0
  631. package/dist/mail/filing.js.map +7 -0
  632. package/dist/mail/hooks.js +393 -0
  633. package/dist/mail/hooks.js.map +7 -0
  634. package/dist/mail/index.js +120 -0
  635. package/dist/mail/index.js.map +7 -0
  636. package/dist/mail/offline/changes.js +258 -0
  637. package/dist/mail/offline/changes.js.map +7 -0
  638. package/dist/mail/offline/confirm-sign-out.js +37 -0
  639. package/dist/mail/offline/confirm-sign-out.js.map +7 -0
  640. package/dist/mail/offline/crypto.js +26 -0
  641. package/dist/mail/offline/crypto.js.map +7 -0
  642. package/dist/mail/offline/drafts.js +69 -0
  643. package/dist/mail/offline/drafts.js.map +7 -0
  644. package/dist/mail/offline/hooks.js +104 -0
  645. package/dist/mail/offline/hooks.js.map +7 -0
  646. package/dist/mail/offline/index.js +48 -0
  647. package/dist/mail/offline/index.js.map +7 -0
  648. package/dist/mail/offline/live.js +233 -0
  649. package/dist/mail/offline/live.js.map +7 -0
  650. package/dist/mail/offline/mailbox.js +191 -0
  651. package/dist/mail/offline/mailbox.js.map +7 -0
  652. package/dist/mail/offline/outbox.js +167 -0
  653. package/dist/mail/offline/outbox.js.map +7 -0
  654. package/dist/mail/offline/reads.js +159 -0
  655. package/dist/mail/offline/reads.js.map +7 -0
  656. package/dist/mail/offline/runtime.js +100 -0
  657. package/dist/mail/offline/runtime.js.map +7 -0
  658. package/dist/mail/offline/settings.js +84 -0
  659. package/dist/mail/offline/settings.js.map +7 -0
  660. package/dist/mail/offline/store.js +29 -0
  661. package/dist/mail/offline/store.js.map +7 -0
  662. package/dist/mail/offline/sync.js +251 -0
  663. package/dist/mail/offline/sync.js.map +7 -0
  664. package/dist/mail/offline/wipe.js +19 -0
  665. package/dist/mail/offline/wipe.js.map +7 -0
  666. package/dist/mail/thread-keys.js +53 -0
  667. package/dist/mail/thread-keys.js.map +7 -0
  668. package/dist/mail/threads.js +71 -0
  669. package/dist/mail/threads.js.map +7 -0
  670. package/dist/mail/useMailClient.js +42 -0
  671. package/dist/mail/useMailClient.js.map +7 -0
  672. package/dist/model-connections.js +58 -0
  673. package/dist/model-connections.js.map +7 -0
  674. package/dist/notifications/ActivityFeed.js +70 -0
  675. package/dist/notifications/ActivityFeed.js.map +7 -0
  676. package/dist/notifications/NotificationBell.js +200 -0
  677. package/dist/notifications/NotificationBell.js.map +7 -0
  678. package/dist/notifications/Toaster.js +24 -0
  679. package/dist/notifications/Toaster.js.map +7 -0
  680. package/dist/notifications/activity-types.js +65 -0
  681. package/dist/notifications/activity-types.js.map +7 -0
  682. package/dist/notifications/bell.js +24 -0
  683. package/dist/notifications/bell.js.map +7 -0
  684. package/dist/notifications/calendar-notifications.js +79 -0
  685. package/dist/notifications/calendar-notifications.js.map +7 -0
  686. package/dist/notifications/index.js +108 -0
  687. package/dist/notifications/index.js.map +7 -0
  688. package/dist/notifications/live.js +28 -0
  689. package/dist/notifications/live.js.map +7 -0
  690. package/dist/notifications/notification-types.js +127 -0
  691. package/dist/notifications/notification-types.js.map +7 -0
  692. package/dist/{chunk-BF5KW5ZI.js → notifications/notify-store.js} +24 -74
  693. package/dist/notifications/notify-store.js.map +7 -0
  694. package/dist/notifications/server-notifications.js +452 -0
  695. package/dist/notifications/server-notifications.js.map +7 -0
  696. package/dist/notifications/useNotifications.js +34 -0
  697. package/dist/notifications/useNotifications.js.map +7 -0
  698. package/dist/offline-store/network.js +11 -0
  699. package/dist/offline-store/network.js.map +7 -0
  700. package/dist/offline-store/store.js +136 -0
  701. package/dist/offline-store/store.js.map +7 -0
  702. package/dist/offline-store/wipe.js +8 -0
  703. package/dist/offline-store/wipe.js.map +7 -0
  704. package/dist/offline.js +58 -0
  705. package/dist/offline.js.map +7 -0
  706. package/dist/people.js +122 -0
  707. package/dist/people.js.map +7 -0
  708. package/dist/projects.js +30 -0
  709. package/dist/projects.js.map +7 -0
  710. package/dist/query-client.js +63 -0
  711. package/dist/query-client.js.map +7 -0
  712. package/dist/{chunk-ZM6N7YZH.js → query-keys.js} +18 -31
  713. package/dist/query-keys.js.map +7 -0
  714. package/dist/query-persist.js +66 -0
  715. package/dist/query-persist.js.map +7 -0
  716. package/dist/queued-writes.js +59 -0
  717. package/dist/queued-writes.js.map +7 -0
  718. package/dist/remote-control.js +67 -0
  719. package/dist/remote-control.js.map +7 -0
  720. package/dist/search/index.js +23 -0
  721. package/dist/search/index.js.map +7 -0
  722. package/dist/search/session.js +58 -0
  723. package/dist/search/session.js.map +7 -0
  724. package/dist/search/useSemanticSearch.js +82 -0
  725. package/dist/search/useSemanticSearch.js.map +7 -0
  726. package/dist/session/chat.js +512 -0
  727. package/dist/session/chat.js.map +7 -0
  728. package/dist/session/documents.js +196 -0
  729. package/dist/session/documents.js.map +7 -0
  730. package/dist/session/drafts.js +103 -0
  731. package/dist/session/drafts.js.map +7 -0
  732. package/dist/session/index.js +123 -0
  733. package/dist/session/index.js.map +7 -0
  734. package/dist/session/layout.js +339 -0
  735. package/dist/session/layout.js.map +7 -0
  736. package/dist/session/persist.js +106 -0
  737. package/dist/session/persist.js.map +7 -0
  738. package/dist/session/session-hooks.js +53 -0
  739. package/dist/session/session-hooks.js.map +7 -0
  740. package/dist/session/signed-in.js +36 -0
  741. package/dist/session/signed-in.js.map +7 -0
  742. package/dist/session/store.js +166 -0
  743. package/dist/session/store.js.map +7 -0
  744. package/dist/session/thread-tabs.js +121 -0
  745. package/dist/session/thread-tabs.js.map +7 -0
  746. package/dist/session/ui-state-storage.js +76 -0
  747. package/dist/session/ui-state-storage.js.map +7 -0
  748. package/dist/session/workspace.js +77 -0
  749. package/dist/session/workspace.js.map +7 -0
  750. package/dist/shell/index.cjs +37 -37
  751. package/dist/shell/index.js +43 -10
  752. package/dist/shell/index.js.map +7 -1
  753. package/dist/skill-pack.js +111 -0
  754. package/dist/skill-pack.js.map +7 -0
  755. package/dist/storage.js +186 -0
  756. package/dist/storage.js.map +7 -0
  757. package/dist/support/index.js +35 -0
  758. package/dist/support/index.js.map +7 -0
  759. package/dist/tags.js +204 -0
  760. package/dist/tags.js.map +7 -0
  761. package/dist/ui/DebouncedInput.js +109 -0
  762. package/dist/ui/DebouncedInput.js.map +7 -0
  763. package/dist/ui/DictateContext.js +8 -0
  764. package/dist/ui/DictateContext.js.map +7 -0
  765. package/dist/ui/IconToggle.js +79 -0
  766. package/dist/ui/IconToggle.js.map +7 -0
  767. package/dist/ui/VerifiedToggle.js +38 -0
  768. package/dist/ui/VerifiedToggle.js.map +7 -0
  769. package/dist/ui/VisibilityToggle.js +103 -0
  770. package/dist/ui/VisibilityToggle.js.map +7 -0
  771. package/dist/ui/avatar.js +40 -0
  772. package/dist/ui/avatar.js.map +7 -0
  773. package/dist/ui/badge.js +28 -0
  774. package/dist/ui/badge.js.map +7 -0
  775. package/dist/ui/button.js +48 -0
  776. package/dist/ui/button.js.map +7 -0
  777. package/dist/ui/card.js +90 -0
  778. package/dist/ui/card.js.map +7 -0
  779. package/dist/ui/checkbox.js +22 -0
  780. package/dist/ui/checkbox.js.map +7 -0
  781. package/dist/ui/collapsible.js +10 -0
  782. package/dist/ui/collapsible.js.map +7 -0
  783. package/dist/ui/command.js +103 -0
  784. package/dist/ui/command.js.map +7 -0
  785. package/dist/{chunk-YNNAJJ5Z.js → ui/dialog.js} +30 -68
  786. package/dist/ui/dialog.js.map +7 -0
  787. package/dist/{chunk-47CCGUWR.js → ui/dropdown-menu.js} +40 -45
  788. package/dist/ui/dropdown-menu.js.map +7 -0
  789. package/dist/ui/hover-card.js +36 -0
  790. package/dist/ui/hover-card.js.map +7 -0
  791. package/dist/ui/index.cjs +154 -154
  792. package/dist/ui/index.js +290 -10
  793. package/dist/ui/index.js.map +7 -1
  794. package/dist/ui/input.js +65 -0
  795. package/dist/ui/input.js.map +7 -0
  796. package/dist/ui/label.js +16 -0
  797. package/dist/ui/label.js.map +7 -0
  798. package/dist/ui/mark-menu.js +300 -0
  799. package/dist/ui/mark-menu.js.map +7 -0
  800. package/dist/ui/popover.js +40 -0
  801. package/dist/ui/popover.js.map +7 -0
  802. package/dist/ui/portal-container.js +17 -0
  803. package/dist/ui/portal-container.js.map +7 -0
  804. package/dist/ui/progress.js +24 -0
  805. package/dist/ui/progress.js.map +7 -0
  806. package/dist/ui/radio-group.js +29 -0
  807. package/dist/ui/radio-group.js.map +7 -0
  808. package/dist/ui/scroll-area.js +39 -0
  809. package/dist/ui/scroll-area.js.map +7 -0
  810. package/dist/ui/select.js +130 -0
  811. package/dist/ui/select.js.map +7 -0
  812. package/dist/ui/separator.js +23 -0
  813. package/dist/ui/separator.js.map +7 -0
  814. package/dist/ui/slider.js +23 -0
  815. package/dist/ui/slider.js.map +7 -0
  816. package/dist/ui/switch.js +28 -0
  817. package/dist/ui/switch.js.map +7 -0
  818. package/dist/ui/table.js +75 -0
  819. package/dist/ui/table.js.map +7 -0
  820. package/dist/ui/tabs.js +48 -0
  821. package/dist/ui/tabs.js.map +7 -0
  822. package/dist/ui/textarea.js +63 -0
  823. package/dist/ui/textarea.js.map +7 -0
  824. package/dist/ui/toggle-group.js +43 -0
  825. package/dist/ui/toggle-group.js.map +7 -0
  826. package/dist/ui/toggle.js +40 -0
  827. package/dist/ui/toggle.js.map +7 -0
  828. package/dist/ui/tooltip.js +215 -0
  829. package/dist/ui/tooltip.js.map +7 -0
  830. package/dist/usage-metered.js +8 -0
  831. package/dist/usage-metered.js.map +7 -0
  832. package/dist/useArbi.js +16 -0
  833. package/dist/useArbi.js.map +7 -0
  834. package/dist/useInstallSkillPack.js +81 -0
  835. package/dist/useInstallSkillPack.js.map +7 -0
  836. package/dist/usermenu/UserMenu.js +188 -0
  837. package/dist/usermenu/UserMenu.js.map +7 -0
  838. package/dist/usermenu/index.js +5 -0
  839. package/dist/usermenu/index.js.map +7 -0
  840. package/dist/users/index.js +15 -0
  841. package/dist/users/index.js.map +7 -0
  842. package/dist/users/user-display.js +60 -0
  843. package/dist/users/user-display.js.map +7 -0
  844. package/dist/viewers/AudioViewer.js +23 -0
  845. package/dist/viewers/AudioViewer.js.map +7 -0
  846. package/dist/viewers/DocxViewer.js +81 -0
  847. package/dist/viewers/DocxViewer.js.map +7 -0
  848. package/dist/viewers/ImageViewer.js +31 -0
  849. package/dist/viewers/ImageViewer.js.map +7 -0
  850. package/dist/viewers/PdfViewer.js +19 -3
  851. package/dist/viewers/PdfViewer.js.map +7 -1
  852. package/dist/{PdfViewerImpl-TEBYF2QI.js → viewers/PdfViewerImpl.js} +25 -19
  853. package/dist/viewers/PdfViewerImpl.js.map +7 -0
  854. package/dist/viewers/VideoViewer.js +31 -0
  855. package/dist/viewers/VideoViewer.js.map +7 -0
  856. package/dist/viewers/XlsxViewer.js +102 -0
  857. package/dist/viewers/XlsxViewer.js.map +7 -0
  858. package/dist/viewers/index.js +61 -271
  859. package/dist/viewers/index.js.map +7 -1
  860. package/dist/viewers/page-scroll.js +59 -0
  861. package/dist/viewers/page-scroll.js.map +7 -0
  862. package/dist/viewers/pdf-viewer-constants.js +9 -0
  863. package/dist/viewers/pdf-viewer-constants.js.map +7 -0
  864. package/dist/{chunk-PTOP7OHG.js → viewers/pdfjs-polyfills.js} +5 -6
  865. package/dist/viewers/pdfjs-polyfills.js.map +7 -0
  866. package/dist/viewers/selection-runs.js +38 -0
  867. package/dist/viewers/selection-runs.js.map +7 -0
  868. package/dist/viewers/usePageIntersectionObserver.js +68 -0
  869. package/dist/viewers/usePageIntersectionObserver.js.map +7 -0
  870. package/dist/viewers/useProcessedChunks.js +58 -0
  871. package/dist/viewers/useProcessedChunks.js.map +7 -0
  872. package/dist/viewers/viewer-zoom.js +163 -0
  873. package/dist/viewers/viewer-zoom.js.map +7 -0
  874. package/dist/websocket/ArbiWebSocketProvider.js +207 -0
  875. package/dist/websocket/ArbiWebSocketProvider.js.map +7 -0
  876. package/dist/websocket/context.js +14 -0
  877. package/dist/websocket/context.js.map +7 -0
  878. package/dist/websocket/hooks.js +30 -0
  879. package/dist/websocket/hooks.js.map +7 -0
  880. package/dist/websocket/index.js +22 -0
  881. package/dist/websocket/index.js.map +7 -0
  882. package/dist/websocket/live-updates.js +38 -0
  883. package/dist/websocket/live-updates.js.map +7 -0
  884. package/dist/websocket/reconnect.js +13 -0
  885. package/dist/websocket/reconnect.js.map +7 -0
  886. package/dist/websocket/store.js +58 -0
  887. package/dist/websocket/store.js.map +7 -0
  888. package/dist/workforce.js +607 -0
  889. package/dist/workforce.js.map +7 -0
  890. package/dist/workspaces/access-request.js +35 -0
  891. package/dist/workspaces/access-request.js.map +7 -0
  892. package/dist/workspaces/archive.js +59 -0
  893. package/dist/workspaces/archive.js.map +7 -0
  894. package/dist/workspaces/current.js +20 -0
  895. package/dist/workspaces/current.js.map +7 -0
  896. package/dist/workspaces/delete-workspaces.js +15 -0
  897. package/dist/workspaces/delete-workspaces.js.map +7 -0
  898. package/dist/workspaces/export-archive.js +40 -0
  899. package/dist/workspaces/export-archive.js.map +7 -0
  900. package/dist/workspaces/index.js +99 -0
  901. package/dist/workspaces/index.js.map +7 -0
  902. package/dist/workspaces/settings.js +45 -0
  903. package/dist/workspaces/settings.js.map +7 -0
  904. package/dist/workspaces/shell-workspaces.js +49 -0
  905. package/dist/workspaces/shell-workspaces.js.map +7 -0
  906. package/dist/workspaces/switch.js +234 -0
  907. package/dist/workspaces/switch.js.map +7 -0
  908. package/dist/workspaces/transfer.js +170 -0
  909. package/dist/workspaces/transfer.js.map +7 -0
  910. package/dist/workspaces/useShellWorkspaces.js +86 -0
  911. package/dist/workspaces/useShellWorkspaces.js.map +7 -0
  912. package/dist/workspaces/workspace-users.js +65 -0
  913. package/dist/workspaces/workspace-users.js.map +7 -0
  914. package/package.json +4 -4
  915. package/dist/PdfViewerImpl-TEBYF2QI.js.map +0 -1
  916. package/dist/PdfViewerImpl.d-B28hLEuj.d.cts +0 -62
  917. package/dist/ProductionDialog.d-CpzslFn0.d.cts +0 -51
  918. package/dist/annotations/freeze/index.d.cts +0 -205
  919. package/dist/annotations/index.d.cts +0 -360
  920. package/dist/artifacts/index.d.cts +0 -476
  921. package/dist/artifacts/redline-core.d.cts +0 -39
  922. package/dist/bundle-YNOX7VIL.js +0 -5
  923. package/dist/bundle-YNOX7VIL.js.map +0 -1
  924. package/dist/bundle.d-BnCSbHy2.d.cts +0 -85
  925. package/dist/calls/livekit/index.d.cts +0 -280
  926. package/dist/chunk-47CCGUWR.js.map +0 -1
  927. package/dist/chunk-4FL3X3LA.js +0 -2057
  928. package/dist/chunk-4FL3X3LA.js.map +0 -1
  929. package/dist/chunk-6QNBSXCE.js +0 -271
  930. package/dist/chunk-6QNBSXCE.js.map +0 -1
  931. package/dist/chunk-74N436VK.js.map +0 -1
  932. package/dist/chunk-APZZQZ6P.js +0 -147
  933. package/dist/chunk-APZZQZ6P.js.map +0 -1
  934. package/dist/chunk-BF5KW5ZI.js.map +0 -1
  935. package/dist/chunk-DPYBZDJB.js.map +0 -1
  936. package/dist/chunk-DZKRL5H3.js +0 -2766
  937. package/dist/chunk-DZKRL5H3.js.map +0 -1
  938. package/dist/chunk-HDCRPPBW.js +0 -75
  939. package/dist/chunk-HDCRPPBW.js.map +0 -1
  940. package/dist/chunk-L2IPPTVC.js +0 -20
  941. package/dist/chunk-L2IPPTVC.js.map +0 -1
  942. package/dist/chunk-LSU4UPS5.js +0 -1011
  943. package/dist/chunk-LSU4UPS5.js.map +0 -1
  944. package/dist/chunk-NIKPG4PW.js +0 -1128
  945. package/dist/chunk-NIKPG4PW.js.map +0 -1
  946. package/dist/chunk-NNAJLY6B.js +0 -4974
  947. package/dist/chunk-NNAJLY6B.js.map +0 -1
  948. package/dist/chunk-OYPKKHXY.js +0 -559
  949. package/dist/chunk-OYPKKHXY.js.map +0 -1
  950. package/dist/chunk-PTOP7OHG.js.map +0 -1
  951. package/dist/chunk-QMY2JKBI.js +0 -246
  952. package/dist/chunk-QMY2JKBI.js.map +0 -1
  953. package/dist/chunk-SN5YV6FF.js +0 -11
  954. package/dist/chunk-SN5YV6FF.js.map +0 -1
  955. package/dist/chunk-SSXFVWCT.js.map +0 -1
  956. package/dist/chunk-T3USOSVN.js.map +0 -1
  957. package/dist/chunk-T4CLW3DN.js +0 -2560
  958. package/dist/chunk-T4CLW3DN.js.map +0 -1
  959. package/dist/chunk-UW2SGTI5.js.map +0 -1
  960. package/dist/chunk-VSCU7K4V.js.map +0 -1
  961. package/dist/chunk-WL2Y2T47.js.map +0 -1
  962. package/dist/chunk-WUTL62MC.js.map +0 -1
  963. package/dist/chunk-XWPLOFDN.js +0 -644
  964. package/dist/chunk-XWPLOFDN.js.map +0 -1
  965. package/dist/chunk-Y3MTRA7D.js +0 -97
  966. package/dist/chunk-Y3MTRA7D.js.map +0 -1
  967. package/dist/chunk-YNNAJJ5Z.js.map +0 -1
  968. package/dist/chunk-ZM6N7YZH.js.map +0 -1
  969. package/dist/document-tools/core.d.cts +0 -883
  970. package/dist/document-tools/index.d.cts +0 -90
  971. package/dist/index.d-LArLnpI8.d.cts +0 -2036
  972. package/dist/index.d-oR5FKZpJ.d.cts +0 -579
  973. package/dist/index.d.cts +0 -15923
  974. package/dist/lazy-chunk.d-B6YDLMKI.d.cts +0 -31
  975. package/dist/model.d-CNtRWKVK.d.cts +0 -110
  976. package/dist/query-keys.d-B1Am9tIF.d.cts +0 -337
  977. package/dist/shell/index.d.cts +0 -6
  978. package/dist/store.d-GADDvC7w.d.cts +0 -35
  979. package/dist/stored-markdown.d-Bp18vrbr.d.cts +0 -125
  980. package/dist/ui/index.d.cts +0 -26
  981. package/dist/useAudioRecorder.d-B9rlMI_E.d.cts +0 -778
  982. package/dist/viewers/PdfViewer.d.cts +0 -9
  983. package/dist/viewers/index.d.cts +0 -262
@@ -0,0 +1,258 @@
1
+ import { blind, openJson, sealJson } from "./crypto.js";
2
+ import { isNetworkFailure } from "../../offline-store/network.js";
3
+ import { deleteRecords, getRecord, putRecord, recordsInBucket } from "./store.js";
4
+ import { keyOf, loadBody, loadFolders, removeKeys, saveBody, saveHeader } from "./mailbox.js";
5
+ import { notifyOfflineMailChange } from "./settings.js";
6
+ const isFiling = (change) => change.kind === "file";
7
+ const MAX_ATTEMPTS = 5;
8
+ const bucket = () => blind("bucket", "changes");
9
+ const keyFor = (id) => blind("change", id);
10
+ async function write(item) {
11
+ await putRecord({
12
+ key: await keyFor(item.id),
13
+ kind: "change",
14
+ bucket: await bucket(),
15
+ sortAt: item.seq,
16
+ size: 0,
17
+ lastAccess: Date.now(),
18
+ data: await sealJson(item)
19
+ });
20
+ }
21
+ async function drop(item) {
22
+ await deleteRecords([await keyFor(item.id)]);
23
+ }
24
+ async function readHeader(accountId, folderId, messageId) {
25
+ const record = await getRecord(await keyOf.header(accountId, folderId, messageId));
26
+ if (!record) return void 0;
27
+ try {
28
+ return await openJson(record.data);
29
+ } catch {
30
+ return void 0;
31
+ }
32
+ }
33
+ async function deviceCopies(accountId, messageId) {
34
+ const copies = [];
35
+ for (const folder of await loadFolders(accountId) ?? []) {
36
+ const header = await readHeader(accountId, folder.id, messageId);
37
+ if (header) copies.push({ folderId: folder.id, header });
38
+ }
39
+ return copies;
40
+ }
41
+ async function applyToDevice({ account, messageId, folderId, change }) {
42
+ if (change.kind === "file") return;
43
+ let header = await readHeader(account.id, folderId, messageId);
44
+ let headerKey = await keyOf.header(account.id, folderId, messageId);
45
+ if (!header) {
46
+ const [copy] = await deviceCopies(account.id, messageId);
47
+ if (copy) {
48
+ header = copy.header;
49
+ headerKey = await keyOf.header(account.id, copy.folderId, messageId);
50
+ }
51
+ }
52
+ if (change.kind === "delete") {
53
+ const attachments = header?.attachments ?? [];
54
+ await removeKeys([
55
+ headerKey,
56
+ await keyOf.body(account.id, messageId),
57
+ ...await Promise.all(attachments.map((a) => keyOf.attachment(account.id, messageId, a.id)))
58
+ ]);
59
+ return;
60
+ }
61
+ const { unread, flagged, folder_id: moveTo, action } = change.update;
62
+ if (unread !== void 0 || flagged !== void 0) {
63
+ const state = {
64
+ ...unread !== void 0 && { unread },
65
+ ...flagged !== void 0 && { flagged }
66
+ };
67
+ if (header) header = { ...header, ...state };
68
+ for (const copy of await deviceCopies(account.id, messageId))
69
+ await saveHeader(account.id, copy.folderId, { ...copy.header, ...state });
70
+ const body = await loadBody(account.id, messageId);
71
+ if (body) await saveBody(account.id, { ...body, ...state });
72
+ }
73
+ if (!moveTo && !action) return;
74
+ if (header) await removeKeys([headerKey]);
75
+ const folders = await loadFolders(account.id) ?? [];
76
+ const destination = action === "trash" ? folders.find((f) => f.role === "trash")?.id : action ? void 0 : moveTo;
77
+ if (header && destination && folders.some((f) => f.id === destination))
78
+ await saveHeader(account.id, destination, header);
79
+ }
80
+ function combine(pending, next) {
81
+ if (isFiling(next) || isFiling(pending.change)) return { change: next };
82
+ if (pending.change.kind === "delete" || next.kind === "delete")
83
+ return { change: { kind: "delete" } };
84
+ const update = { ...pending.change.update };
85
+ let restoreTo = pending.restoreTo;
86
+ if (next.update.unread !== void 0) update.unread = next.update.unread;
87
+ if (next.update.flagged !== void 0) update.flagged = next.update.flagged;
88
+ if (next.update.folder_id !== void 0 || next.update.action !== void 0) {
89
+ const before = { folder_id: update.folder_id, action: update.action };
90
+ delete update.folder_id;
91
+ delete update.action;
92
+ restoreTo = void 0;
93
+ if (next.update.action === "trash") {
94
+ if (before.action !== "restore") {
95
+ update.action = "trash";
96
+ if (before.folder_id) restoreTo = before.folder_id;
97
+ }
98
+ } else if (next.update.action === "restore" && before.action === "trash") {
99
+ if (pending.restoreTo) update.folder_id = pending.restoreTo;
100
+ } else if (next.update.folder_id !== void 0) {
101
+ if (next.update.folder_id !== pending.folderId) update.folder_id = next.update.folder_id;
102
+ } else if (next.update.action !== void 0) {
103
+ update.action = next.update.action;
104
+ }
105
+ }
106
+ return Object.keys(update).length > 0 ? { change: { kind: "update", update }, restoreTo } : null;
107
+ }
108
+ async function listMailChanges() {
109
+ const items = [];
110
+ for (const record of await recordsInBucket(await bucket())) {
111
+ try {
112
+ items.push(await openJson(record.data));
113
+ } catch {
114
+ }
115
+ }
116
+ return items.sort((a, b) => a.seq - b.seq);
117
+ }
118
+ async function hasPendingMailChange(accountId, messageId) {
119
+ return (await listMailChanges()).some(
120
+ (c) => c.account.id === accountId && c.messageId === messageId
121
+ );
122
+ }
123
+ async function queue(input) {
124
+ const pending = await listMailChanges();
125
+ const existing = pending.find(
126
+ (c) => c.account.id === input.account.id && c.messageId === input.messageId && isFiling(c.change) === isFiling(input.change)
127
+ );
128
+ const restoredHome = existing?.change.kind === "update" && existing.change.update.action === "trash" && input.change.kind === "update" && input.change.update.action === "restore";
129
+ const onDevice = restoredHome && input.change.kind === "update" ? {
130
+ ...input,
131
+ change: {
132
+ kind: "update",
133
+ update: {
134
+ unread: input.change.update.unread,
135
+ flagged: input.change.update.flagged,
136
+ folder_id: existing.restoreTo ?? existing.folderId
137
+ }
138
+ }
139
+ } : input;
140
+ await applyToDevice(onDevice);
141
+ if (existing) {
142
+ const combined = combine(existing, input.change);
143
+ if (combined) await write({ ...existing, ...combined, attempts: 0, error: void 0 });
144
+ else await drop(existing);
145
+ } else {
146
+ await write({
147
+ id: crypto.randomUUID(),
148
+ ...input,
149
+ createdAt: Date.now(),
150
+ seq: Math.max(0, ...pending.map((c) => c.seq)) + 1,
151
+ attempts: 0
152
+ });
153
+ }
154
+ }
155
+ const STORE_LOCK = "arbi-mail-changes-store";
156
+ let chain = Promise.resolve();
157
+ function serially(fn) {
158
+ if (typeof navigator !== "undefined" && navigator.locks?.request)
159
+ return navigator.locks.request(STORE_LOCK, fn);
160
+ const run = chain.then(fn);
161
+ chain = run.catch(() => {
162
+ });
163
+ return run;
164
+ }
165
+ async function queueMailChange(input) {
166
+ await serially(() => queue(input));
167
+ notifyOfflineMailChange("changes");
168
+ notifyOfflineMailChange("mailbox");
169
+ }
170
+ async function readChange(id) {
171
+ const record = await getRecord(await keyFor(id));
172
+ if (!record) return void 0;
173
+ try {
174
+ return await openJson(record.data);
175
+ } catch {
176
+ return void 0;
177
+ }
178
+ }
179
+ async function overlayPendingMailChanges() {
180
+ for (const change of await listMailChanges()) await applyToDevice(change);
181
+ }
182
+ const reason = (error, fallback) => error instanceof Error && error.message ? error.message : fallback;
183
+ function classify(error) {
184
+ if (isNetworkFailure(error)) return "offline";
185
+ const status = error?.status;
186
+ if (status === 404 || status === 410) return "gone";
187
+ if (status === 401)
188
+ return { wait: reason(error, "Reconnect this mailbox to apply the change"), counts: true };
189
+ if (status === void 0 || status === 408 || status === 429 || status >= 500)
190
+ return { wait: reason(error, "The mail server could not apply the change"), counts: false };
191
+ return { refused: reason(error, "The server refused this change") };
192
+ }
193
+ async function attempt(item, sender) {
194
+ try {
195
+ await sender.apply(item);
196
+ return "applied";
197
+ } catch (error) {
198
+ if (error.status !== 401) return classify(error);
199
+ try {
200
+ await sender.unlock(item.account);
201
+ await sender.apply(item);
202
+ return "applied";
203
+ } catch (retryError) {
204
+ return classify(retryError);
205
+ }
206
+ }
207
+ }
208
+ async function applyMailChangesOnce(sender, isOnline) {
209
+ const result = { applied: 0, gone: 0, refused: [], interrupted: false };
210
+ const waiting = /* @__PURE__ */ new Set();
211
+ for (const listed of await listMailChanges()) {
212
+ if (!isOnline()) {
213
+ result.interrupted = true;
214
+ break;
215
+ }
216
+ if (waiting.has(listed.account.id)) continue;
217
+ const outcome = await serially(async () => {
218
+ const item = await readChange(listed.id);
219
+ if (!item) return null;
220
+ const sent = await attempt(item, sender);
221
+ if (sent === "offline") return sent;
222
+ if (typeof sent === "object" && "wait" in sent) {
223
+ const attempts = item.attempts + (sent.counts ? 1 : 0);
224
+ if (attempts < MAX_ATTEMPTS) {
225
+ await write({ ...item, attempts, error: sent.wait });
226
+ return sent;
227
+ }
228
+ await drop(item);
229
+ result.refused.push({ change: item, error: sent.wait });
230
+ return { refused: sent.wait };
231
+ }
232
+ await drop(item);
233
+ if (sent === "applied") result.applied++;
234
+ else if (sent === "gone") result.gone++;
235
+ else result.refused.push({ change: item, error: sent.refused });
236
+ return sent;
237
+ });
238
+ if (outcome === "offline") {
239
+ result.interrupted = true;
240
+ break;
241
+ }
242
+ if (outcome && typeof outcome === "object" && "wait" in outcome) {
243
+ waiting.add(listed.account.id);
244
+ result.interrupted = true;
245
+ }
246
+ }
247
+ if (result.applied + result.gone + result.refused.length > 0) notifyOfflineMailChange("changes");
248
+ return result;
249
+ }
250
+ export {
251
+ MAX_ATTEMPTS,
252
+ applyMailChangesOnce,
253
+ hasPendingMailChange,
254
+ listMailChanges,
255
+ overlayPendingMailChanges,
256
+ queueMailChange
257
+ };
258
+ //# sourceMappingURL=changes.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mail/offline/changes.ts"],
4
+ "sourcesContent": ["/**\n * Changes to messages made offline (or whose request got no answer): mark read or unread, flag or\n * unflag, move or archive, send to Trash, restore and delete forever. Each is applied to the device copy at once (so\n * the lists read from this device show it), kept sealed on the device, and sent to the server once\n * the connection is back.\n *\n * One pending change per message: a second change to the same message is combined with the first\n * into the message's final state (Archive then mark unread is one PATCH; Flag then Unflag is one PATCH; Trash then Delete forever is\n * one DELETE; Trash then Restore is nothing). Some providers (IMAP, Outlook) give a message a new id\n * when it moves, so replaying the steps one by one would aim the later ones at an id that no longer\n * exists. The combined change is sent once, to the id the message had when it was first changed.\n *\n * Replay keeps the order in which messages were first changed, per account: one account that cannot\n * be reached does not hold back the others. The server's message writes are idempotent (a PATCH sets\n * a state; a repeated DELETE finds nothing), so a replay after a lost answer does no harm. Outcomes:\n * - the message is gone on the server (404, 410): dropped; nothing is left to change, and the next\n * sync removes it from the device too;\n * - refused (another 4xx): dropped, and reported with the server's reason;\n * - no answer at all: the replay stops (no connection), everything stays for the next reconnect;\n * - a server error, rate limit, timeout or an answer that isn't the mail API's (5xx, 429, 408, no\n * status: a deploy, a captive portal): that account waits, with no limit;\n * - a session the server keeps refusing after an unlock (401: an account that needs reconnecting):\n * after {@link MAX_ATTEMPTS} tries it is reported as refused, so it can't wait for ever.\n *\n * Queuing a change and replaying one run one at a time, through the same Web Lock (so across tabs\n * too; a plain in-tab chain where Web Locks don't exist). A replay reads the message's record\n * fresh, sends it and drops it in one step, so a change made meanwhile is never folded into a record\n * that is about to be dropped (or overwritten): it waits for the step, then is kept on its own.\n */\n\nimport type { MailAccount, MailMessage, MailMessageUpdate } from '../types'\nimport type { MailFileRequest } from '../filing'\nimport { blind, openJson, sealJson } from './crypto'\nimport { isNetworkFailure } from '../../offline-store/network'\nimport { deleteRecords, getRecord, putRecord, recordsInBucket } from './store'\nimport { keyOf, loadBody, loadFolders, removeKeys, saveBody, saveHeader } from './mailbox'\nimport { notifyOfflineMailChange } from './settings'\n\n/**\n * What happens to the message: a PATCH (`update`), deleting it for good (`delete`), or adding it (or\n * its whole conversation) to a workspace (`file`). A filing waits beside the message's other change,\n * never combined with it.\n */\nexport type MailChange =\n | { kind: 'update'; update: MailMessageUpdate }\n | { kind: 'delete' }\n | ({ kind: 'file' } & MailFileRequest)\n\nconst isFiling = (change: MailChange) => change.kind === 'file'\n\nexport interface PendingMailChange {\n id: string\n account: MailAccount\n /** The message's id when it was first changed (the id the server still knows it by). */\n messageId: string\n /** The folder the message was in when it was first changed. */\n folderId: string\n /** The message's final state: every change made to it since, combined. */\n change: MailChange\n createdAt: number\n /** Order first changed (a counter, not the clock). */\n seq: number\n /** Tries refused with a 401 after an unlock (an account that needs reconnecting). */\n attempts: number\n /** Trashed on the device after a move the server hasn't seen: Restore brings it back there. */\n restoreTo?: string\n /** Why the last try didn't go through. */\n error?: string\n}\n\nexport interface MailChangeSender {\n /** Make the account usable in this session (connector tokens, IMAP credentials). */\n unlock: (account: MailAccount) => Promise<void>\n /** Send the change to the server. */\n apply: (change: PendingMailChange) => Promise<void>\n}\n\n/** Tries refused with a lasting 401 before a change is given up and reported. */\nexport const MAX_ATTEMPTS = 5\n\nconst bucket = () => blind('bucket', 'changes')\nconst keyFor = (id: string) => blind('change', id)\n\nasync function write(item: PendingMailChange): Promise<void> {\n await putRecord({\n key: await keyFor(item.id),\n kind: 'change',\n bucket: await bucket(),\n sortAt: item.seq,\n size: 0,\n lastAccess: Date.now(),\n data: await sealJson(item),\n })\n}\n\nasync function drop(item: PendingMailChange): Promise<void> {\n await deleteRecords([await keyFor(item.id)])\n}\n\nasync function readHeader(\n accountId: string,\n folderId: string,\n messageId: string\n): Promise<MailMessage | undefined> {\n const record = await getRecord(await keyOf.header(accountId, folderId, messageId))\n if (!record) return undefined\n try {\n return await openJson<MailMessage>(record.data)\n } catch {\n return undefined\n }\n}\n\n/** Where `messageId` is listed on the device: each folder's copy of its header. */\nasync function deviceCopies(accountId: string, messageId: string) {\n const copies: { folderId: string; header: MailMessage }[] = []\n for (const folder of (await loadFolders(accountId)) ?? []) {\n const header = await readHeader(accountId, folder.id, messageId)\n if (header) copies.push({ folderId: folder.id, header })\n }\n return copies\n}\n\ntype DeviceChange = Pick<PendingMailChange, 'account' | 'messageId' | 'folderId' | 'change'>\n\n/**\n * Show a change in the device copy (the lists and the opened message read from it offline). Safe to\n * run again: a message already moved is not found where it was, and is left where it is.\n */\nasync function applyToDevice({ account, messageId, folderId, change }: DeviceChange) {\n // Adding to a workspace changes nothing in the mailbox.\n if (change.kind === 'file') return\n let header = await readHeader(account.id, folderId, messageId)\n let headerKey = await keyOf.header(account.id, folderId, messageId)\n if (!header) {\n // Changed from a view over the folders (Flagged): its copy is in the folder it is in.\n const [copy] = await deviceCopies(account.id, messageId)\n if (copy) {\n header = copy.header\n headerKey = await keyOf.header(account.id, copy.folderId, messageId)\n }\n }\n if (change.kind === 'delete') {\n const attachments = header?.attachments ?? []\n await removeKeys([\n headerKey,\n await keyOf.body(account.id, messageId),\n ...(await Promise.all(attachments.map((a) => keyOf.attachment(account.id, messageId, a.id)))),\n ])\n return\n }\n const { unread, flagged, folder_id: moveTo, action } = change.update\n if (unread !== undefined || flagged !== undefined) {\n const state = {\n ...(unread !== undefined && { unread }),\n ...(flagged !== undefined && { flagged }),\n }\n if (header) header = { ...header, ...state }\n // Every copy on the device shows it: a change made from the Flagged view names no folder of its\n // own, and a Gmail message is listed under each of its labels.\n for (const copy of await deviceCopies(account.id, messageId))\n await saveHeader(account.id, copy.folderId, { ...copy.header, ...state })\n const body = await loadBody(account.id, messageId)\n if (body) await saveBody(account.id, { ...body, ...state })\n }\n if (!moveTo && !action) return\n // It leaves this folder. It appears in the destination when the device knows that folder;\n // a restored message's folder is known only to the server, so it shows there after the next sync.\n if (header) await removeKeys([headerKey])\n const folders = (await loadFolders(account.id)) ?? []\n const destination =\n action === 'trash' ? folders.find((f) => f.role === 'trash')?.id : action ? undefined : moveTo\n if (header && destination && folders.some((f) => f.id === destination))\n await saveHeader(account.id, destination, header)\n}\n\ninterface Combined {\n change: MailChange\n restoreTo?: string\n}\n\n/**\n * `next` made after `pending`, as one final state; `null` when they cancel out (moved back where it\n * was, trashed and restored, or restored and trashed, with no change to read state). A message\n * moved, then trashed, then restored ends where it was moved to, as the server's restore would.\n */\nfunction combine(pending: PendingMailChange, next: MailChange): Combined | null {\n // A second filing of the message replaces the first (the last workspace chosen wins).\n if (isFiling(next) || isFiling(pending.change)) return { change: next }\n if (pending.change.kind === 'delete' || next.kind === 'delete')\n return { change: { kind: 'delete' } }\n const update: MailMessageUpdate = { ...pending.change.update }\n let restoreTo = pending.restoreTo\n if (next.update.unread !== undefined) update.unread = next.update.unread\n if (next.update.flagged !== undefined) update.flagged = next.update.flagged\n if (next.update.folder_id !== undefined || next.update.action !== undefined) {\n const before = { folder_id: update.folder_id, action: update.action }\n delete update.folder_id\n delete update.action\n restoreTo = undefined\n if (next.update.action === 'trash') {\n // Restored, then trashed again: back in the Trash, where the server has it.\n if (before.action !== 'restore') {\n update.action = 'trash'\n if (before.folder_id) restoreTo = before.folder_id\n }\n } else if (next.update.action === 'restore' && before.action === 'trash') {\n // Trashed, then restored: where it was before (a move the server hasn't seen), else nowhere.\n if (pending.restoreTo) update.folder_id = pending.restoreTo\n } else if (next.update.folder_id !== undefined) {\n if (next.update.folder_id !== pending.folderId) update.folder_id = next.update.folder_id\n } else if (next.update.action !== undefined) {\n update.action = next.update.action\n }\n }\n return Object.keys(update).length > 0 ? { change: { kind: 'update', update }, restoreTo } : null\n}\n\n/** The changes waiting for a connection, in the order their messages were first changed. */\nexport async function listMailChanges(): Promise<PendingMailChange[]> {\n const items: PendingMailChange[] = []\n for (const record of await recordsInBucket(await bucket())) {\n try {\n items.push(await openJson<PendingMailChange>(record.data))\n } catch {\n // Sealed under another identity: not this user's.\n }\n }\n return items.sort((a, b) => a.seq - b.seq)\n}\n\n/** Whether a change to this message waits on the device (a new change must combine with it). */\nexport async function hasPendingMailChange(accountId: string, messageId: string): Promise<boolean> {\n return (await listMailChanges()).some(\n (c) => c.account.id === accountId && c.messageId === messageId\n )\n}\n\nasync function queue(input: DeviceChange): Promise<void> {\n const pending = await listMailChanges()\n const existing = pending.find(\n (c) =>\n c.account.id === input.account.id &&\n c.messageId === input.messageId &&\n isFiling(c.change) === isFiling(input.change)\n )\n // Trashed, then restored before the server heard of it: it goes back where it was.\n const restoredHome =\n existing?.change.kind === 'update' &&\n existing.change.update.action === 'trash' &&\n input.change.kind === 'update' &&\n input.change.update.action === 'restore'\n const onDevice: DeviceChange =\n restoredHome && input.change.kind === 'update'\n ? {\n ...input,\n change: {\n kind: 'update',\n update: {\n unread: input.change.update.unread,\n flagged: input.change.update.flagged,\n folder_id: existing.restoreTo ?? existing.folderId,\n },\n },\n }\n : input\n // The device copy first: a change is kept only once it shows.\n await applyToDevice(onDevice)\n if (existing) {\n const combined = combine(existing, input.change)\n if (combined) await write({ ...existing, ...combined, attempts: 0, error: undefined })\n else await drop(existing)\n } else {\n await write({\n id: crypto.randomUUID(),\n ...input,\n createdAt: Date.now(),\n seq: Math.max(0, ...pending.map((c) => c.seq)) + 1,\n attempts: 0,\n })\n }\n}\n\nconst STORE_LOCK = 'arbi-mail-changes-store'\nlet chain: Promise<unknown> = Promise.resolve()\n\n/**\n * Run `fn` alone: no other queuing or replay step runs on the changes meanwhile, in this tab or\n * another (Web Locks wait their turn). Without Web Locks, one at a time in this tab.\n */\nfunction serially<T>(fn: () => Promise<T>): Promise<T> {\n if (typeof navigator !== 'undefined' && navigator.locks?.request)\n return navigator.locks.request(STORE_LOCK, fn) as Promise<T>\n const run = chain.then(fn)\n chain = run.catch(() => {})\n return run\n}\n\n/** Keep a change made offline, combined with any change to the same message still waiting. */\nexport async function queueMailChange(input: DeviceChange): Promise<void> {\n await serially(() => queue(input))\n notifyOfflineMailChange('changes')\n notifyOfflineMailChange('mailbox')\n}\n\nasync function readChange(id: string): Promise<PendingMailChange | undefined> {\n const record = await getRecord(await keyFor(id))\n if (!record) return undefined\n try {\n return await openJson<PendingMailChange>(record.data)\n } catch {\n return undefined\n }\n}\n\n/**\n * Lay the waiting changes over the device copy again, after a sync or an online read wrote the\n * server's state (where the change hasn't reached yet): a moved message must not reappear.\n */\nexport async function overlayPendingMailChanges(): Promise<void> {\n for (const change of await listMailChanges()) await applyToDevice(change)\n}\n\nexport interface ApplyChangesResult {\n applied: number\n /** Dropped because the message is no longer on the server. */\n gone: number\n /** Refused by the server, or given up after {@link MAX_ATTEMPTS} lasting 401s, with the reason. */\n refused: { change: PendingMailChange; error: string }[]\n /** Something still waits: no connection, or an account to try again later. */\n interrupted: boolean\n}\n\ntype Outcome =\n 'applied' | 'gone' | 'offline' | { wait: string; counts?: boolean } | { refused: string }\n\nconst reason = (error: unknown, fallback: string) =>\n error instanceof Error && error.message ? error.message : fallback\n\ntype Wait = { wait: string; counts: boolean }\n\nfunction classify(error: unknown): Exclude<Outcome, { wait: string }> | Wait {\n if (isNetworkFailure(error)) return 'offline'\n const status = (error as { status?: number } | null)?.status\n if (status === 404 || status === 410) return 'gone'\n // Only a session refused even after an unlock counts towards giving up.\n if (status === 401)\n return { wait: reason(error, 'Reconnect this mailbox to apply the change'), counts: true }\n if (status === undefined || status === 408 || status === 429 || status >= 500)\n return { wait: reason(error, 'The mail server could not apply the change'), counts: false }\n return { refused: reason(error, 'The server refused this change') }\n}\n\nasync function attempt(item: PendingMailChange, sender: MailChangeSender): Promise<Outcome> {\n try {\n await sender.apply(item)\n return 'applied'\n } catch (error) {\n if ((error as { status?: number }).status !== 401) return classify(error)\n // The account isn't unlocked for this session yet: unlock once and send again.\n try {\n await sender.unlock(item.account)\n await sender.apply(item)\n return 'applied'\n } catch (retryError) {\n return classify(retryError)\n }\n }\n}\n\n/** Send the waiting changes to the server, in order per account. */\nexport async function applyMailChangesOnce(\n sender: MailChangeSender,\n isOnline: () => boolean\n): Promise<ApplyChangesResult> {\n const result: ApplyChangesResult = { applied: 0, gone: 0, refused: [], interrupted: false }\n // Accounts with a change that has to wait: their later changes wait behind it.\n const waiting = new Set<string>()\n for (const listed of await listMailChanges()) {\n if (!isOnline()) {\n result.interrupted = true\n break\n }\n if (waiting.has(listed.account.id)) continue\n // Read, send and settle in one step: a change made meanwhile waits, and is then kept.\n const outcome = await serially(async (): Promise<Outcome | null> => {\n const item = await readChange(listed.id)\n if (!item) return null\n const sent = await attempt(item, sender)\n if (sent === 'offline') return sent\n if (typeof sent === 'object' && 'wait' in sent) {\n const attempts = item.attempts + (sent.counts ? 1 : 0)\n if (attempts < MAX_ATTEMPTS) {\n // Not announced: it is the same change, still waiting.\n await write({ ...item, attempts, error: sent.wait })\n return sent\n }\n await drop(item)\n result.refused.push({ change: item, error: sent.wait })\n return { refused: sent.wait }\n }\n await drop(item)\n if (sent === 'applied') result.applied++\n else if (sent === 'gone') result.gone++\n else result.refused.push({ change: item, error: sent.refused })\n return sent\n })\n if (outcome === 'offline') {\n result.interrupted = true\n break\n }\n if (outcome && typeof outcome === 'object' && 'wait' in outcome) {\n waiting.add(listed.account.id)\n result.interrupted = true\n }\n }\n if (result.applied + result.gone + result.refused.length > 0) notifyOfflineMailChange('changes')\n return result\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,37 @@
1
+ import { listLocalDrafts } from "./drafts.js";
2
+ import { listOutbox } from "./outbox.js";
3
+ import { listMailChanges } from "./changes.js";
4
+ import { OFFLINE_MAIL_DB } from "./store.js";
5
+ async function storeExists() {
6
+ try {
7
+ const databases = await indexedDB.databases?.();
8
+ return databases ? databases.some((d) => d.name === OFFLINE_MAIL_DB) : true;
9
+ } catch {
10
+ return true;
11
+ }
12
+ }
13
+ async function confirmLosingOfflineMail(confirm) {
14
+ if (!await storeExists()) return true;
15
+ const [outbox, drafts, changes] = await Promise.all([
16
+ listOutbox().catch(() => []),
17
+ listLocalDrafts().catch(() => []),
18
+ listMailChanges().catch(() => [])
19
+ ]);
20
+ const unsent = outbox.filter((item) => item.status !== "sent").length;
21
+ if (unsent === 0 && drafts.length === 0 && changes.length === 0) return true;
22
+ const parts = [
23
+ unsent > 0 ? `${unsent} unsent ${unsent === 1 ? "message" : "messages"} in your Outbox` : "",
24
+ drafts.length > 0 ? `${drafts.length} ${drafts.length === 1 ? "draft" : "drafts"} saved only on this device` : "",
25
+ changes.length > 0 ? `${changes.length} ${changes.length === 1 ? "change" : "changes"} to your mail not applied yet` : ""
26
+ ].filter(Boolean);
27
+ const list = parts.length > 1 ? `${parts.slice(0, -1).join(", ")} and ${parts[parts.length - 1]}` : parts[0];
28
+ const count = unsent + drafts.length + changes.length;
29
+ return confirm({
30
+ message: `You have ${list}. Signing out deletes ${count === 1 ? "it" : "them"} from this device. Reconnect first to send and save them.`,
31
+ title: "Sign out and delete unsent mail?"
32
+ });
33
+ }
34
+ export {
35
+ confirmLosingOfflineMail
36
+ };
37
+ //# sourceMappingURL=confirm-sign-out.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mail/offline/confirm-sign-out.ts"],
4
+ "sourcesContent": ["import { listLocalDrafts } from './drafts'\nimport { listOutbox } from './outbox'\nimport { listMailChanges } from './changes'\nimport { OFFLINE_MAIL_DB } from './store'\n\n/** Whether this device has an offline mailbox at all (asked without creating one). */\nasync function storeExists(): Promise<boolean> {\n try {\n const databases = await indexedDB.databases?.()\n return databases ? databases.some((d) => d.name === OFFLINE_MAIL_DB) : true\n } catch {\n // Can't tell: look (an empty store just asks nothing).\n return true\n }\n}\n\n/** Asks the user (the blocks environment's `confirm`); resolves with their answer. */\ntype Confirm = (options: { message: string; title: string }) => Promise<boolean>\n\n/**\n * Signing out removes mail kept on this device. When that includes unsent Outbox messages or drafts\n * that never reached the server, say so and let the user stay signed in to send them first.\n */\nexport async function confirmLosingOfflineMail(confirm: Confirm): Promise<boolean> {\n // Checked whatever the mail settings say: they may not have loaded (a cold start offline), and\n // unsent mail must never go without a word. Nothing on the device: nothing to ask.\n if (!(await storeExists())) return true\n const [outbox, drafts, changes] = await Promise.all([\n listOutbox().catch(() => []),\n listLocalDrafts().catch(() => []),\n listMailChanges().catch(() => []),\n ])\n const unsent = outbox.filter((item) => item.status !== 'sent').length\n if (unsent === 0 && drafts.length === 0 && changes.length === 0) return true\n const parts = [\n unsent > 0 ? `${unsent} unsent ${unsent === 1 ? 'message' : 'messages'} in your Outbox` : '',\n drafts.length > 0\n ? `${drafts.length} ${drafts.length === 1 ? 'draft' : 'drafts'} saved only on this device`\n : '',\n changes.length > 0\n ? `${changes.length} ${changes.length === 1 ? 'change' : 'changes'} to your mail not applied yet`\n : '',\n ].filter(Boolean)\n const list =\n parts.length > 1 ? `${parts.slice(0, -1).join(', ')} and ${parts[parts.length - 1]}` : parts[0]\n const count = unsent + drafts.length + changes.length\n return confirm({\n message: `You have ${list}. Signing out deletes ${count === 1 ? 'it' : 'them'} from this device. Reconnect first to send and save them.`,\n title: 'Sign out and delete unsent mail?',\n })\n}\n"],
5
+ "mappings": "AAAA,SAAS,uBAAuB;AAChC,SAAS,kBAAkB;AAC3B,SAAS,uBAAuB;AAChC,SAAS,uBAAuB;AAGhC,eAAe,cAAgC;AAC7C,MAAI;AACF,UAAM,YAAY,MAAM,UAAU,YAAY;AAC9C,WAAO,YAAY,UAAU,KAAK,CAAC,MAAM,EAAE,SAAS,eAAe,IAAI;AAAA,EACzE,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;AASA,eAAsB,yBAAyB,SAAoC;AAGjF,MAAI,CAAE,MAAM,YAAY,EAAI,QAAO;AACnC,QAAM,CAAC,QAAQ,QAAQ,OAAO,IAAI,MAAM,QAAQ,IAAI;AAAA,IAClD,WAAW,EAAE,MAAM,MAAM,CAAC,CAAC;AAAA,IAC3B,gBAAgB,EAAE,MAAM,MAAM,CAAC,CAAC;AAAA,IAChC,gBAAgB,EAAE,MAAM,MAAM,CAAC,CAAC;AAAA,EAClC,CAAC;AACD,QAAM,SAAS,OAAO,OAAO,CAAC,SAAS,KAAK,WAAW,MAAM,EAAE;AAC/D,MAAI,WAAW,KAAK,OAAO,WAAW,KAAK,QAAQ,WAAW,EAAG,QAAO;AACxE,QAAM,QAAQ;AAAA,IACZ,SAAS,IAAI,GAAG,MAAM,WAAW,WAAW,IAAI,YAAY,UAAU,oBAAoB;AAAA,IAC1F,OAAO,SAAS,IACZ,GAAG,OAAO,MAAM,IAAI,OAAO,WAAW,IAAI,UAAU,QAAQ,+BAC5D;AAAA,IACJ,QAAQ,SAAS,IACb,GAAG,QAAQ,MAAM,IAAI,QAAQ,WAAW,IAAI,WAAW,SAAS,kCAChE;AAAA,EACN,EAAE,OAAO,OAAO;AAChB,QAAM,OACJ,MAAM,SAAS,IAAI,GAAG,MAAM,MAAM,GAAG,EAAE,EAAE,KAAK,IAAI,CAAC,QAAQ,MAAM,MAAM,SAAS,CAAC,CAAC,KAAK,MAAM,CAAC;AAChG,QAAM,QAAQ,SAAS,OAAO,SAAS,QAAQ;AAC/C,SAAO,QAAQ;AAAA,IACb,SAAS,YAAY,IAAI,yBAAyB,UAAU,IAAI,OAAO,MAAM;AAAA,IAC7E,OAAO;AAAA,EACT,CAAC;AACH;",
6
+ "names": []
7
+ }
@@ -0,0 +1,26 @@
1
+ import { createOfflineSealer } from "@arbidocs/client";
2
+ class OfflineMailLockedError extends Error {
3
+ constructor() {
4
+ super("Sign in to open the mail saved on this device");
5
+ this.name = "OfflineMailLockedError";
6
+ }
7
+ }
8
+ const sealer = createOfflineSealer("arbi-offline-mail-v1", {
9
+ locked: () => new OfflineMailLockedError()
10
+ });
11
+ const forgetOfflineMailKeys = sealer.forget;
12
+ const sealBytes = sealer.sealBytes;
13
+ const openBytes = sealer.openBytes;
14
+ const sealJson = sealer.sealJson;
15
+ const openJson = sealer.openJson;
16
+ const blind = sealer.blind;
17
+ export {
18
+ OfflineMailLockedError,
19
+ blind,
20
+ forgetOfflineMailKeys,
21
+ openBytes,
22
+ openJson,
23
+ sealBytes,
24
+ sealJson
25
+ };
26
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mail/offline/crypto.ts"],
4
+ "sourcesContent": ["/**\n * Encryption at rest for the offline mailbox: the offline sealer of @arbidocs/client under\n * the `arbi-offline-mail-v1` namespace. Record keys and folder buckets are blind keyed hashes, so\n * folder names (an IMAP \"Clients/Acme\") or message ids never appear in plaintext either.\n */\n\nimport { createOfflineSealer } from '@arbidocs/client'\n\n/** The device has no unlocked identity key (signed out, or session storage cleared). */\nexport class OfflineMailLockedError extends Error {\n constructor() {\n super('Sign in to open the mail saved on this device')\n this.name = 'OfflineMailLockedError'\n }\n}\n\nconst sealer = createOfflineSealer('arbi-offline-mail-v1', {\n locked: () => new OfflineMailLockedError(),\n})\n\n/** Forget the derived keys (sign-out, or the offline data was removed). */\nexport const forgetOfflineMailKeys = sealer.forget\nexport const sealBytes = sealer.sealBytes\nexport const openBytes = sealer.openBytes\nexport const sealJson = sealer.sealJson\nexport const openJson = sealer.openJson\n/** A keyed hash of `parts`, used as an IndexedDB key so ids never appear in plaintext. */\nexport const blind = sealer.blind\n"],
5
+ "mappings": "AAMA,SAAS,2BAA2B;AAG7B,MAAM,+BAA+B,MAAM;AAAA,EAChD,cAAc;AACZ,UAAM,+CAA+C;AACrD,SAAK,OAAO;AAAA,EACd;AACF;AAEA,MAAM,SAAS,oBAAoB,wBAAwB;AAAA,EACzD,QAAQ,MAAM,IAAI,uBAAuB;AAC3C,CAAC;AAGM,MAAM,wBAAwB,OAAO;AACrC,MAAM,YAAY,OAAO;AACzB,MAAM,YAAY,OAAO;AACzB,MAAM,WAAW,OAAO;AACxB,MAAM,WAAW,OAAO;AAExB,MAAM,QAAQ,OAAO;",
6
+ "names": []
7
+ }
@@ -0,0 +1,69 @@
1
+ import { blind, openJson, sealJson } from "./crypto.js";
2
+ import { isNetworkFailure } from "../../offline-store/network.js";
3
+ import { deleteRecords, putRecord, recordsOfKind } from "./store.js";
4
+ import { notifyOfflineMailChange } from "./settings.js";
5
+ const keyFor = (id) => blind("draft", id);
6
+ async function saveLocalDraft(accountId, compose, id = crypto.randomUUID()) {
7
+ const draft = { id, accountId, compose, updatedAt: Date.now() };
8
+ await putRecord({
9
+ key: await keyFor(id),
10
+ kind: "draft",
11
+ bucket: await blind("bucket", "drafts", accountId),
12
+ sortAt: draft.updatedAt,
13
+ size: 0,
14
+ lastAccess: draft.updatedAt,
15
+ data: await sealJson(draft)
16
+ });
17
+ notifyOfflineMailChange("drafts");
18
+ return draft;
19
+ }
20
+ async function listLocalDrafts(accountId) {
21
+ const drafts = [];
22
+ for (const record of await recordsOfKind("draft")) {
23
+ try {
24
+ const draft = await openJson(record.data);
25
+ if (!accountId || draft.accountId === accountId) drafts.push(draft);
26
+ } catch {
27
+ }
28
+ }
29
+ return drafts.sort((a, b) => b.updatedAt - a.updatedAt);
30
+ }
31
+ async function deleteLocalDraft(id) {
32
+ await deleteRecords([await keyFor(id)]);
33
+ notifyOfflineMailChange("drafts");
34
+ }
35
+ async function syncLocalDrafts(save) {
36
+ let uploaded = 0;
37
+ for (const draft of await listLocalDrafts()) {
38
+ if (draft.error) continue;
39
+ try {
40
+ await save(draft);
41
+ await deleteLocalDraft(draft.id);
42
+ uploaded++;
43
+ } catch (error) {
44
+ const status = error.status;
45
+ if (isNetworkFailure(error) || status === void 0 || status === 401 || status >= 500) break;
46
+ await putRecord({
47
+ key: await keyFor(draft.id),
48
+ kind: "draft",
49
+ bucket: await blind("bucket", "drafts", draft.accountId),
50
+ sortAt: draft.updatedAt,
51
+ size: 0,
52
+ lastAccess: Date.now(),
53
+ data: await sealJson({
54
+ ...draft,
55
+ error: error instanceof Error ? error.message : "The server refused this draft"
56
+ })
57
+ });
58
+ notifyOfflineMailChange("drafts");
59
+ }
60
+ }
61
+ return uploaded;
62
+ }
63
+ export {
64
+ deleteLocalDraft,
65
+ listLocalDrafts,
66
+ saveLocalDraft,
67
+ syncLocalDrafts
68
+ };
69
+ //# sourceMappingURL=drafts.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mail/offline/drafts.ts"],
4
+ "sourcesContent": ["/**\n * Drafts saved while offline. They are kept (encrypted) on this device and uploaded to the account's\n * server Drafts as soon as the connection is back; once the server has a draft, the local copy is\n * removed and the server draft is the one shown. Editing a server draft offline keeps its\n * `draft_id`, so the upload replaces it instead of adding a second draft.\n */\n\nimport type { MailCompose } from '../types'\nimport { blind, openJson, sealJson } from './crypto'\nimport { isNetworkFailure } from '../../offline-store/network'\nimport { deleteRecords, putRecord, recordsOfKind } from './store'\nimport { notifyOfflineMailChange } from './settings'\n\nexport interface LocalDraft {\n id: string\n accountId: string\n compose: MailCompose\n updatedAt: number\n /** Set when the server refused the upload (e.g. too large); otherwise it waits for a connection. */\n error?: string\n}\n\nconst keyFor = (id: string) => blind('draft', id)\n\nexport async function saveLocalDraft(\n accountId: string,\n compose: MailCompose,\n id: string = crypto.randomUUID()\n): Promise<LocalDraft> {\n const draft: LocalDraft = { id, accountId, compose, updatedAt: Date.now() }\n await putRecord({\n key: await keyFor(id),\n kind: 'draft',\n bucket: await blind('bucket', 'drafts', accountId),\n sortAt: draft.updatedAt,\n size: 0,\n lastAccess: draft.updatedAt,\n data: await sealJson(draft),\n })\n notifyOfflineMailChange('drafts')\n return draft\n}\n\nexport async function listLocalDrafts(accountId?: string): Promise<LocalDraft[]> {\n const drafts: LocalDraft[] = []\n for (const record of await recordsOfKind('draft')) {\n try {\n const draft = await openJson<LocalDraft>(record.data)\n if (!accountId || draft.accountId === accountId) drafts.push(draft)\n } catch {\n // Another identity's record: ignore.\n }\n }\n return drafts.sort((a, b) => b.updatedAt - a.updatedAt)\n}\n\nexport async function deleteLocalDraft(id: string): Promise<void> {\n await deleteRecords([await keyFor(id)])\n notifyOfflineMailChange('drafts')\n}\n\n/**\n * Upload every local draft. `save` posts one draft to the server and resolves with its id. Stops at\n * the first network failure (the rest wait for the next reconnect); a refusal is recorded on the\n * draft so the user sees why it is still only on this device.\n */\nexport async function syncLocalDrafts(\n save: (draft: LocalDraft) => Promise<{ id: string }>\n): Promise<number> {\n let uploaded = 0\n for (const draft of await listLocalDrafts()) {\n if (draft.error) continue\n try {\n await save(draft)\n await deleteLocalDraft(draft.id)\n uploaded++\n } catch (error) {\n const status = (error as { status?: number }).status\n // No answer, a session to unlock, or a server hiccup: keep it and try on the next reconnect.\n if (isNetworkFailure(error) || status === undefined || status === 401 || status >= 500) break\n await putRecord({\n key: await keyFor(draft.id),\n kind: 'draft',\n bucket: await blind('bucket', 'drafts', draft.accountId),\n sortAt: draft.updatedAt,\n size: 0,\n lastAccess: Date.now(),\n data: await sealJson({\n ...draft,\n error: error instanceof Error ? error.message : 'The server refused this draft',\n }),\n })\n notifyOfflineMailChange('drafts')\n }\n }\n return uploaded\n}\n"],
5
+ "mappings": "AAQA,SAAS,OAAO,UAAU,gBAAgB;AAC1C,SAAS,wBAAwB;AACjC,SAAS,eAAe,WAAW,qBAAqB;AACxD,SAAS,+BAA+B;AAWxC,MAAM,SAAS,CAAC,OAAe,MAAM,SAAS,EAAE;AAEhD,eAAsB,eACpB,WACA,SACA,KAAa,OAAO,WAAW,GACV;AACrB,QAAM,QAAoB,EAAE,IAAI,WAAW,SAAS,WAAW,KAAK,IAAI,EAAE;AAC1E,QAAM,UAAU;AAAA,IACd,KAAK,MAAM,OAAO,EAAE;AAAA,IACpB,MAAM;AAAA,IACN,QAAQ,MAAM,MAAM,UAAU,UAAU,SAAS;AAAA,IACjD,QAAQ,MAAM;AAAA,IACd,MAAM;AAAA,IACN,YAAY,MAAM;AAAA,IAClB,MAAM,MAAM,SAAS,KAAK;AAAA,EAC5B,CAAC;AACD,0BAAwB,QAAQ;AAChC,SAAO;AACT;AAEA,eAAsB,gBAAgB,WAA2C;AAC/E,QAAM,SAAuB,CAAC;AAC9B,aAAW,UAAU,MAAM,cAAc,OAAO,GAAG;AACjD,QAAI;AACF,YAAM,QAAQ,MAAM,SAAqB,OAAO,IAAI;AACpD,UAAI,CAAC,aAAa,MAAM,cAAc,UAAW,QAAO,KAAK,KAAK;AAAA,IACpE,QAAQ;AAAA,IAER;AAAA,EACF;AACA,SAAO,OAAO,KAAK,CAAC,GAAG,MAAM,EAAE,YAAY,EAAE,SAAS;AACxD;AAEA,eAAsB,iBAAiB,IAA2B;AAChE,QAAM,cAAc,CAAC,MAAM,OAAO,EAAE,CAAC,CAAC;AACtC,0BAAwB,QAAQ;AAClC;AAOA,eAAsB,gBACpB,MACiB;AACjB,MAAI,WAAW;AACf,aAAW,SAAS,MAAM,gBAAgB,GAAG;AAC3C,QAAI,MAAM,MAAO;AACjB,QAAI;AACF,YAAM,KAAK,KAAK;AAChB,YAAM,iBAAiB,MAAM,EAAE;AAC/B;AAAA,IACF,SAAS,OAAO;AACd,YAAM,SAAU,MAA8B;AAE9C,UAAI,iBAAiB,KAAK,KAAK,WAAW,UAAa,WAAW,OAAO,UAAU,IAAK;AACxF,YAAM,UAAU;AAAA,QACd,KAAK,MAAM,OAAO,MAAM,EAAE;AAAA,QAC1B,MAAM;AAAA,QACN,QAAQ,MAAM,MAAM,UAAU,UAAU,MAAM,SAAS;AAAA,QACvD,QAAQ,MAAM;AAAA,QACd,MAAM;AAAA,QACN,YAAY,KAAK,IAAI;AAAA,QACrB,MAAM,MAAM,SAAS;AAAA,UACnB,GAAG;AAAA,UACH,OAAO,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QAClD,CAAC;AAAA,MACH,CAAC;AACD,8BAAwB,QAAQ;AAAA,IAClC;AAAA,EACF;AACA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1,104 @@
1
+ import { useCallback, useEffect, useMemo, useState, useSyncExternalStore } from "react";
2
+ import { useQueryClient } from "@tanstack/react-query";
3
+ import { logger } from "@arbidocs/client";
4
+ import { useArbi } from "../../useArbi.js";
5
+ import { useArbiSession } from "../../session/signed-in.js";
6
+ import { listLocalDrafts } from "./drafts.js";
7
+ import { flushOutbox, isMailSyncRunning, syncOfflineMailbox } from "./live.js";
8
+ import { listOutbox } from "./outbox.js";
9
+ import { listMailChanges } from "./changes.js";
10
+ import {
11
+ getOfflineMailSettings,
12
+ onOfflineMailChange,
13
+ setOfflineMailSettings
14
+ } from "./settings.js";
15
+ import { getOfflineMailStatus } from "./sync.js";
16
+ function useStoreValue(load, initial, changes) {
17
+ const [value, setValue] = useState(initial);
18
+ const key = changes.join(",");
19
+ useEffect(() => {
20
+ let alive = true;
21
+ const read = () => load().then((next) => alive && setValue(next)).catch((error) => logger.warn("[offline-mail] read failed", error));
22
+ void read();
23
+ const off = onOfflineMailChange((change) => {
24
+ if (change === "wiped") setValue(initial);
25
+ if (change === "wiped" || key.split(",").includes(change)) void read();
26
+ });
27
+ return () => {
28
+ alive = false;
29
+ off();
30
+ };
31
+ }, [key, load, initial]);
32
+ return value;
33
+ }
34
+ function useOfflineMailSettings() {
35
+ const userExtId = useArbiSession().user?.external_id;
36
+ const subscribe = useCallback(
37
+ (onChange) => onOfflineMailChange((change) => {
38
+ if (change === "settings") onChange();
39
+ }),
40
+ []
41
+ );
42
+ const raw = useSyncExternalStore(
43
+ subscribe,
44
+ () => JSON.stringify([userExtId, getOfflineMailSettings(userExtId)])
45
+ );
46
+ const settings = useMemo(() => JSON.parse(raw)[1], [raw]);
47
+ const update = useCallback(
48
+ (patch) => void setOfflineMailSettings(userExtId, patch),
49
+ [userExtId]
50
+ );
51
+ return [settings, update];
52
+ }
53
+ const EMPTY_STATUS = { messages: 0, bytes: 0, skipped: [] };
54
+ function useOfflineMailStatus() {
55
+ const status = useStoreValue(getOfflineMailStatus, EMPTY_STATUS, ["status", "mailbox"]);
56
+ const [syncing, setSyncing] = useState(isMailSyncRunning);
57
+ useEffect(
58
+ () => onOfflineMailChange((change) => {
59
+ if (change === "status") setSyncing(isMailSyncRunning());
60
+ }),
61
+ []
62
+ );
63
+ return { ...status, syncing };
64
+ }
65
+ const NO_ITEMS = [];
66
+ function useOutbox(enabled = true) {
67
+ const load = useCallback(() => enabled ? listOutbox() : Promise.resolve(NO_ITEMS), [enabled]);
68
+ return useStoreValue(load, NO_ITEMS, ["outbox"]);
69
+ }
70
+ const NO_CHANGES = [];
71
+ function usePendingMailChanges(enabled = true) {
72
+ const load = useCallback(
73
+ () => enabled ? listMailChanges() : Promise.resolve(NO_CHANGES),
74
+ [enabled]
75
+ );
76
+ return useStoreValue(load, NO_CHANGES, ["changes"]);
77
+ }
78
+ const NO_DRAFTS = [];
79
+ function useLocalDrafts(accountId) {
80
+ const load = useCallback(
81
+ () => accountId ? listLocalDrafts(accountId) : Promise.resolve(NO_DRAFTS),
82
+ [accountId]
83
+ );
84
+ return useStoreValue(load, NO_DRAFTS, ["drafts"]);
85
+ }
86
+ function useFlushOutbox() {
87
+ const arbi = useArbi();
88
+ const queryClient = useQueryClient();
89
+ return useCallback(() => flushOutbox({ arbi, queryClient }), [arbi, queryClient]);
90
+ }
91
+ function useSyncOfflineMailbox() {
92
+ const arbi = useArbi();
93
+ return useCallback((options) => syncOfflineMailbox({ arbi }, options), [arbi]);
94
+ }
95
+ export {
96
+ useFlushOutbox,
97
+ useLocalDrafts,
98
+ useOfflineMailSettings,
99
+ useOfflineMailStatus,
100
+ useOutbox,
101
+ usePendingMailChanges,
102
+ useSyncOfflineMailbox
103
+ };
104
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/mail/offline/hooks.ts"],
4
+ "sourcesContent": ["/**\n * React bindings for the offline mailbox: the per-device settings, sync status, the Outbox, the\n * changes made offline and the drafts kept on this device. Every hook re-reads when the store changes in this tab or another.\n */\n\nimport { useCallback, useEffect, useMemo, useState, useSyncExternalStore } from 'react'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { logger } from '@arbidocs/client'\nimport { useArbi } from '../../useArbi'\nimport { useArbiSession } from '../../session/signed-in'\nimport { listLocalDrafts, type LocalDraft } from './drafts'\nimport { flushOutbox, isMailSyncRunning, syncOfflineMailbox } from './live'\nimport { listOutbox, type OutboxItem } from './outbox'\nimport { listMailChanges, type PendingMailChange } from './changes'\nimport {\n getOfflineMailSettings,\n onOfflineMailChange,\n setOfflineMailSettings,\n type OfflineMailChange,\n type OfflineMailSettings,\n} from './settings'\nimport { getOfflineMailStatus, type OfflineMailStatus } from './sync'\n\n/** Re-run `load` on mount and whenever one of `changes` happens; errors leave the last value. */\nfunction useStoreValue<T>(load: () => Promise<T>, initial: T, changes: OfflineMailChange[]): T {\n const [value, setValue] = useState<T>(initial)\n const key = changes.join(',')\n useEffect(() => {\n let alive = true\n const read = () =>\n load()\n .then((next) => alive && setValue(next))\n .catch((error) => logger.warn('[offline-mail] read failed', error))\n void read()\n const off = onOfflineMailChange((change) => {\n if (change === 'wiped') setValue(initial)\n if (change === 'wiped' || key.split(',').includes(change)) void read()\n })\n return () => {\n alive = false\n off()\n }\n }, [key, load, initial])\n return value\n}\n\nexport function useOfflineMailSettings(): [\n OfflineMailSettings,\n (patch: Partial<OfflineMailSettings>) => void,\n] {\n const userExtId = useArbiSession().user?.external_id\n const subscribe = useCallback(\n (onChange: () => void) =>\n onOfflineMailChange((change) => {\n if (change === 'settings') onChange()\n }),\n []\n )\n // Snapshot as a string so useSyncExternalStore sees a stable value between changes; the user is\n // part of it because the settings are per user.\n const raw = useSyncExternalStore(subscribe, () =>\n JSON.stringify([userExtId, getOfflineMailSettings(userExtId)])\n )\n const settings = useMemo(() => (JSON.parse(raw) as [unknown, OfflineMailSettings])[1], [raw])\n const update = useCallback(\n (patch: Partial<OfflineMailSettings>) => void setOfflineMailSettings(userExtId, patch),\n [userExtId]\n )\n return [settings, update]\n}\n\nconst EMPTY_STATUS: OfflineMailStatus = { messages: 0, bytes: 0, skipped: [] }\n\nexport function useOfflineMailStatus(): OfflineMailStatus & { syncing: boolean } {\n const status = useStoreValue(getOfflineMailStatus, EMPTY_STATUS, ['status', 'mailbox'])\n const [syncing, setSyncing] = useState(isMailSyncRunning)\n useEffect(\n () =>\n onOfflineMailChange((change) => {\n if (change === 'status') setSyncing(isMailSyncRunning())\n }),\n []\n )\n return { ...status, syncing }\n}\n\nconst NO_ITEMS: OutboxItem[] = []\n/** The Outbox, oldest first. `enabled: false` skips reading the store (Mail switched off). */\nexport function useOutbox(enabled = true): OutboxItem[] {\n const load = useCallback(() => (enabled ? listOutbox() : Promise.resolve(NO_ITEMS)), [enabled])\n return useStoreValue(load, NO_ITEMS, ['outbox'])\n}\n\nconst NO_CHANGES: PendingMailChange[] = []\n/**\n * The changes made offline that wait for a connection, oldest first. `enabled: false` skips\n * reading the store (Mail switched off).\n */\nexport function usePendingMailChanges(enabled = true): PendingMailChange[] {\n const load = useCallback(\n () => (enabled ? listMailChanges() : Promise.resolve(NO_CHANGES)),\n [enabled]\n )\n return useStoreValue(load, NO_CHANGES, ['changes'])\n}\n\nconst NO_DRAFTS: LocalDraft[] = []\nexport function useLocalDrafts(accountId: string | undefined): LocalDraft[] {\n const load = useCallback(\n () => (accountId ? listLocalDrafts(accountId) : Promise.resolve(NO_DRAFTS)),\n [accountId]\n )\n return useStoreValue(load, NO_DRAFTS, ['drafts'])\n}\n\n/** Send what waits in the Outbox now (\"Send now\"), on the session in scope. */\nexport function useFlushOutbox(): () => Promise<void> {\n const arbi = useArbi()\n const queryClient = useQueryClient()\n return useCallback(() => flushOutbox({ arbi, queryClient }), [arbi, queryClient])\n}\n\n/** One sync pass of the offline mailbox now (\"Sync now\": `{ full: true }`). */\nexport function useSyncOfflineMailbox(): (options?: { full?: boolean }) => Promise<void> {\n const arbi = useArbi()\n return useCallback((options) => syncOfflineMailbox({ arbi }, options), [arbi])\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }