@arbidocs/blocks 0.5.48 → 0.5.50

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 (81) hide show
  1. package/dist/DocumentReviewCard-DLR4XOIZ.cjs +516 -0
  2. package/dist/DocumentReviewCard-DLR4XOIZ.cjs.map +1 -0
  3. package/dist/DocumentReviewCard-Y67FFRPC.js +514 -0
  4. package/dist/DocumentReviewCard-Y67FFRPC.js.map +1 -0
  5. package/dist/calls/connected/ConnectedCallPage.d.ts +23 -0
  6. package/dist/calls/connected/index.d.ts +1 -0
  7. package/dist/calls/index.cjs +172 -0
  8. package/dist/calls/index.cjs.map +1 -1
  9. package/dist/calls/index.js +175 -4
  10. package/dist/calls/index.js.map +1 -1
  11. package/dist/chunk-3Y4UTPCD.js +1521 -0
  12. package/dist/chunk-3Y4UTPCD.js.map +1 -0
  13. package/dist/chunk-5TDGVOR5.js +142 -0
  14. package/dist/chunk-5TDGVOR5.js.map +1 -0
  15. package/dist/{chunk-QKOFQMAY.cjs → chunk-5YX3R6CK.cjs} +5 -4
  16. package/dist/chunk-5YX3R6CK.cjs.map +1 -0
  17. package/dist/chunk-63IH7V5F.js +13 -0
  18. package/dist/chunk-63IH7V5F.js.map +1 -0
  19. package/dist/chunk-C3VTWM74.js +123 -0
  20. package/dist/chunk-C3VTWM74.js.map +1 -0
  21. package/dist/chunk-DVE6NNZ2.cjs +15 -0
  22. package/dist/chunk-DVE6NNZ2.cjs.map +1 -0
  23. package/dist/{chunk-XBITXJZU.js → chunk-EQ433QPZ.js} +4 -3
  24. package/dist/chunk-EQ433QPZ.js.map +1 -0
  25. package/dist/{chunk-UAEYU2NN.cjs → chunk-H32DV7XS.cjs} +2 -136
  26. package/dist/chunk-H32DV7XS.cjs.map +1 -0
  27. package/dist/{chunk-EARQ2CUX.js → chunk-IQ3VDTR7.js} +6 -119
  28. package/dist/chunk-IQ3VDTR7.js.map +1 -0
  29. package/dist/chunk-NUQ3RY7M.cjs +130 -0
  30. package/dist/chunk-NUQ3RY7M.cjs.map +1 -0
  31. package/dist/{chunk-V2UQR7P6.cjs → chunk-QLY22ZZW.cjs} +9 -8
  32. package/dist/chunk-QLY22ZZW.cjs.map +1 -0
  33. package/dist/chunk-REH7PX3N.cjs +145 -0
  34. package/dist/chunk-REH7PX3N.cjs.map +1 -0
  35. package/dist/{chunk-VQHXVY26.cjs → chunk-RTS3B2W7.cjs} +2 -121
  36. package/dist/chunk-RTS3B2W7.cjs.map +1 -0
  37. package/dist/chunk-S7B5E3RU.cjs +1553 -0
  38. package/dist/chunk-S7B5E3RU.cjs.map +1 -0
  39. package/dist/{chunk-WZ63HE2C.js → chunk-XRL4R2TT.js} +4 -136
  40. package/dist/chunk-XRL4R2TT.js.map +1 -0
  41. package/dist/{chunk-E6EYRQC2.js → chunk-YYZH6VRP.js} +6 -5
  42. package/dist/chunk-YYZH6VRP.js.map +1 -0
  43. package/dist/connect/index.cjs +464 -1861
  44. package/dist/connect/index.cjs.map +1 -1
  45. package/dist/connect/index.js +55 -1538
  46. package/dist/connect/index.js.map +1 -1
  47. package/dist/connect/viewer.cjs +39 -39
  48. package/dist/connect/viewer.js +1 -1
  49. package/dist/connection/config/useDeveloperConfig.d.ts +1 -1
  50. package/dist/connection/files/fields/DocumentFieldParts.d.ts +2 -1
  51. package/dist/connection/files/fields/documentField.d.ts +1 -0
  52. package/dist/connection/files/grid/cells.d.ts +1 -0
  53. package/dist/connection/files/page/ConnectedFilesPage.d.ts +5 -2
  54. package/dist/connection/files/review/DocumentReviewCard.d.ts +32 -0
  55. package/dist/connection/files/review/useDocumentValueWrites.d.ts +15 -0
  56. package/dist/connection/files/review/useReviewColumns.d.ts +33 -0
  57. package/dist/files/cells/RelatedDocsCell.d.ts +3 -1
  58. package/dist/files/index.cjs +221 -221
  59. package/dist/files/index.js +1 -1
  60. package/dist/home/index.cjs +7 -6
  61. package/dist/home/index.cjs.map +1 -1
  62. package/dist/home/index.js +2 -1
  63. package/dist/home/index.js.map +1 -1
  64. package/dist/index.cjs +82 -82
  65. package/dist/index.cjs.map +1 -1
  66. package/dist/index.js +5 -8
  67. package/dist/index.js.map +1 -1
  68. package/dist/workspaces/index.cjs +29 -28
  69. package/dist/workspaces/index.cjs.map +1 -1
  70. package/dist/workspaces/index.js +4 -3
  71. package/dist/workspaces/index.js.map +1 -1
  72. package/node_modules/@arbidocs/coedit/package.json +1 -1
  73. package/package.json +5 -5
  74. package/dist/chunk-E6EYRQC2.js.map +0 -1
  75. package/dist/chunk-EARQ2CUX.js.map +0 -1
  76. package/dist/chunk-QKOFQMAY.cjs.map +0 -1
  77. package/dist/chunk-UAEYU2NN.cjs.map +0 -1
  78. package/dist/chunk-V2UQR7P6.cjs.map +0 -1
  79. package/dist/chunk-VQHXVY26.cjs.map +0 -1
  80. package/dist/chunk-WZ63HE2C.js.map +0 -1
  81. package/dist/chunk-XBITXJZU.js.map +0 -1
@@ -23,6 +23,7 @@ var jsxRuntime = require('react/jsx-runtime');
23
23
  var ui = require('@arbidocs/react/ui');
24
24
  var lucideReact = require('lucide-react');
25
25
  var browser = require('@arbidocs/sdk/browser');
26
+ var client = require('@arbidocs/client');
26
27
 
27
28
  var RING_TIMEOUT_MS = 3e4;
28
29
  function useRingTimeout(ring) {
@@ -411,6 +412,176 @@ function ConnectedCallChatHistory({
411
412
  view === "all" && /* @__PURE__ */ jsxRuntime.jsx(chunkPFJSYJ34_cjs.ProvisionalSpeakers, { ids: provisionalSpeakers })
412
413
  ] });
413
414
  }
415
+ var INVITE_TOKEN_RE = /^[A-Za-z0-9_-]{8,256}$/;
416
+ function Shell({ children }) {
417
+ return /* @__PURE__ */ jsxRuntime.jsx("main", { className: "flex min-h-screen items-center justify-center bg-background p-4 text-foreground", children: /* @__PURE__ */ jsxRuntime.jsx(
418
+ "section",
419
+ {
420
+ className: "w-full max-w-md rounded-lg border border-border bg-card p-6 shadow-sm",
421
+ "data-testid": "call-page",
422
+ children
423
+ }
424
+ ) });
425
+ }
426
+ function ErrorCard({ message, action }) {
427
+ return /* @__PURE__ */ jsxRuntime.jsxs(Shell, { children: [
428
+ /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: "mb-4 text-sm text-destructive", "data-testid": "call-page-error", children: message }),
429
+ action
430
+ ] });
431
+ }
432
+ function MemberJoin({
433
+ callId,
434
+ callKey,
435
+ linkVersion,
436
+ inviteToken,
437
+ onReturnToApp,
438
+ loading,
439
+ appName
440
+ }) {
441
+ const arbi = react$1.useArbi();
442
+ const [failed, setFailed] = react.useState(false);
443
+ const [attempt, setAttempt] = react.useState(0);
444
+ const started = react.useRef(null);
445
+ react.useEffect(() => {
446
+ const id = `${callId}#${attempt}`;
447
+ if (started.current === id) return;
448
+ started.current = id;
449
+ void react$1.openCall(arbi, { callExtId: callId, key: callKey, linkVersion, inviteToken }).then(
450
+ (ok) => {
451
+ if (ok) onReturnToApp();
452
+ else setFailed(true);
453
+ }
454
+ );
455
+ }, [arbi, callId, callKey, linkVersion, inviteToken, attempt, onReturnToApp]);
456
+ if (!failed) return loading;
457
+ return /* @__PURE__ */ jsxRuntime.jsx(
458
+ ErrorCard,
459
+ {
460
+ message: "Could not open this call. The link may be incomplete or no longer valid.",
461
+ action: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
462
+ /* @__PURE__ */ jsxRuntime.jsx(
463
+ ui.Button,
464
+ {
465
+ onClick: () => {
466
+ setFailed(false);
467
+ setAttempt((n) => n + 1);
468
+ },
469
+ "data-testid": "call-page-retry",
470
+ children: "Try again"
471
+ }
472
+ ),
473
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { variant: "outline", onClick: onReturnToApp, children: `Go to ${appName}` })
474
+ ] })
475
+ }
476
+ );
477
+ }
478
+ function SignedOut({
479
+ hasKey,
480
+ returnUrl,
481
+ onAuthenticate,
482
+ appName
483
+ }) {
484
+ const go = (register) => onAuthenticate({ register, returnUrl });
485
+ if (!hasKey) return /* @__PURE__ */ jsxRuntime.jsx(ErrorCard, { message: "This call link is incomplete: it is missing its key." });
486
+ return /* @__PURE__ */ jsxRuntime.jsxs(Shell, { children: [
487
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mb-5 flex items-center gap-2", children: [
488
+ /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-lg font-semibold", "data-testid": "call-page-title", children: "Join the call" }),
489
+ /* @__PURE__ */ jsxRuntime.jsx(chunkQPZDJVNY_cjs.CallsExperimentalBadge, {})
490
+ ] }),
491
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-4 text-sm text-muted-foreground", children: `Sign in to your ${appName} account to join, or create one \u2014 it takes a minute.` }),
492
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
493
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { type: "button", onClick: () => go(false), "data-testid": "call-sign-in", children: [
494
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.LogIn, { className: "mr-1.5 size-4" }),
495
+ "Sign in"
496
+ ] }),
497
+ /* @__PURE__ */ jsxRuntime.jsxs(
498
+ ui.Button,
499
+ {
500
+ type: "button",
501
+ variant: "outline",
502
+ onClick: () => go(true),
503
+ "data-testid": "call-create-account",
504
+ children: [
505
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.UserPlus, { className: "mr-1.5 size-4" }),
506
+ "Create account"
507
+ ]
508
+ }
509
+ ),
510
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "mt-1 flex items-center gap-1.5 text-xs text-muted-foreground", children: [
511
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Lock, { className: "size-3", "aria-hidden": true }),
512
+ "Audio and video are end-to-end encrypted."
513
+ ] })
514
+ ] })
515
+ ] });
516
+ }
517
+ function RegisterFirst({
518
+ pathname,
519
+ hash,
520
+ search,
521
+ onAuthenticate,
522
+ loading
523
+ }) {
524
+ react.useEffect(() => {
525
+ const params = new URLSearchParams(search);
526
+ params.delete("register");
527
+ const query = params.toString();
528
+ onAuthenticate({
529
+ register: true,
530
+ replace: true,
531
+ returnUrl: `${pathname}${query ? `?${query}` : ""}${hash}`
532
+ });
533
+ }, [pathname, hash, search, onAuthenticate]);
534
+ return loading;
535
+ }
536
+ function ConnectedCallPage({
537
+ callId,
538
+ location: { pathname, hash, search },
539
+ authenticated,
540
+ onAuthenticate,
541
+ onReturnToApp,
542
+ appName = "app",
543
+ loading = /* @__PURE__ */ jsxRuntime.jsx("div", { role: "status", children: "Loading\u2026" })
544
+ }) {
545
+ const fragment = react.useMemo(() => client.parseCallFragment(hash), [hash]);
546
+ const params = react.useMemo(() => new URLSearchParams(search), [search]);
547
+ const rawInvite = params.get("i");
548
+ const inviteToken = rawInvite && INVITE_TOKEN_RE.test(rawInvite) ? rawInvite : null;
549
+ if (authenticated) {
550
+ return /* @__PURE__ */ jsxRuntime.jsx(
551
+ MemberJoin,
552
+ {
553
+ callId,
554
+ callKey: fragment?.key ?? null,
555
+ linkVersion: fragment?.linkVersion ?? null,
556
+ inviteToken,
557
+ onReturnToApp,
558
+ loading,
559
+ appName
560
+ }
561
+ );
562
+ }
563
+ if (params.get("register") === "1") {
564
+ return /* @__PURE__ */ jsxRuntime.jsx(
565
+ RegisterFirst,
566
+ {
567
+ pathname,
568
+ hash,
569
+ search,
570
+ onAuthenticate,
571
+ loading
572
+ }
573
+ );
574
+ }
575
+ return /* @__PURE__ */ jsxRuntime.jsx(
576
+ SignedOut,
577
+ {
578
+ hasKey: !!fragment,
579
+ returnUrl: `${pathname}${search}${hash}`,
580
+ onAuthenticate,
581
+ appName
582
+ }
583
+ );
584
+ }
414
585
 
415
586
  Object.defineProperty(exports, "CallConversationEmpty", {
416
587
  enumerable: true,
@@ -956,6 +1127,7 @@ exports.ChatCallCard = ChatCallCard;
956
1127
  exports.ConnectedCallChatHistory = ConnectedCallChatHistory;
957
1128
  exports.ConnectedCallDock = ConnectedCallDock;
958
1129
  exports.ConnectedCallLayer = ConnectedCallLayer;
1130
+ exports.ConnectedCallPage = ConnectedCallPage;
959
1131
  exports.ConnectedCallRoom = ConnectedCallRoom;
960
1132
  exports.ConnectedIncomingCall = ConnectedIncomingCall;
961
1133
  exports.DmCallButton = DmCallButton;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/calls/connected/ConnectedIncomingCall.tsx","../../src/calls/connected/ConnectedCallLayer.tsx","../../src/calls/connected/GroupCallButton.tsx","../../src/calls/connected/DmCallButton.tsx","../../src/calls/connected/NewCallChip.tsx","../../src/calls/connected/ChatCallCard.tsx","../../src/calls/connected/ConnectedCallChatHistory.tsx"],"names":["useEffect","callSession","useArbi","useCallSession","useState","useRingtoneMuted","useRingtone","acceptRing","jsx","IncomingCallCard","CallUserPill","declineRing","lazy","useCallsEnabled","jsxs","Fragment","Suspense","useConnectedWorkspace","chatLiveCallId","useCanHostCalls","isAgent","StartCallButton","openCall","startChatCall","CallPeoplePicker","userDisplayName","startDmCall","DmInviteChip","startContactsCall","contactsCallTitle","getUserDisplayName","useCall","isCallLive","formatCallDuration","Phone","PhoneOff","Button","chats","usePendingRecording","useMemo","hasRecordingTranscript","chatTranscriptRef","useRecordingWindows","supersededTranscriptLines","sortTranscriptMessages","transcriptRuns","TranscriptEntry","useProvisionalSpeakers","CallConversationEmpty","ConversationFilter","RecordingsList","SaveTranscriptToThread","ProvisionalSpeakers","DateSeparator","RecordingCard"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAwBO,IAAM,eAAA,GAAkB;AAE/B,SAAS,eAAe,IAAA,EAAgC;AACtD,EAAAA,eAAA,CAAU,MAAM;AACd,IAAA,IAAI,CAAC,IAAA,EAAM;AACX,IAAA,MAAM,SAAA,GAAY,KAAK,GAAA,CAAI,CAAA,EAAG,KAAK,UAAA,GAAa,eAAA,GAAkB,IAAA,CAAK,GAAA,EAAK,CAAA;AAC5E,IAAA,MAAM,KAAA,GAAQ,WAAW,MAAMC,mBAAA,CAAY,mBAAmB,IAAA,CAAK,WAAW,GAAG,SAAS,CAAA;AAC1F,IAAA,OAAO,MAAM,aAAa,KAAK,CAAA;AAAA,EACjC,CAAA,EAAG,CAAC,IAAI,CAAC,CAAA;AACX;AAEO,SAAS,qBAAA,GAA6C;AAC3D,EAAA,MAAM,OAAOC,eAAA,EAAQ;AACrB,EAAA,MAAM,OAAOC,sBAAA,CAAe,CAAC,MAAM,CAAA,CAAE,QAAA,CAAS,CAAC,CAAC,CAAA;AAChD,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIC,eAAS,KAAK,CAAA;AACtC,EAAA,MAAM,CAAC,KAAA,EAAO,QAAQ,CAAA,GAAIC,kCAAA,EAAiB;AAC3C,EAAA,cAAA,CAAe,IAAI,CAAA;AAEnB,EAAAC,6BAAA,CAAY,CAAC,CAAC,IAAA,IAAQ,CAAC,MAAM,KAAK,CAAA;AAElC,EAAA,IAAI,CAAC,MAAM,OAAO,IAAA;AAElB,EAAA,MAAM,SAAS,YAAY;AACzB,IAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,IAAA,MAAMC,kBAAA,CAAW,MAAM,IAAI,CAAA;AAC3B,IAAA,OAAA,CAAQ,KAAK,CAAA;AAAA,EACf,CAAA;AAIA,EAAA,MAAM,OAAA,GACJ,IAAA,CAAK,OAAA,KAAY,IAAA,GACb,gBAAA,GACA,IAAA,CAAK,OAAA,KAAY,QAAA,GACf,mCAAA,GACA,IAAA,CAAK,OAAA,KAAY,SAAA,GACf,6BAAA,GACA,uBAAA;AAEV,EAAA,uBACEC,cAAA;AAAA,IAACC,kCAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,4BAAA;AAAA,MACV,YAAY,IAAA,CAAK,WAAA;AAAA,MACjB,MAAA,kBAAQD,cAAA,CAACE,8BAAA,EAAA,EAAa,QAAA,EAAU,IAAA,CAAK,eAAe,IAAA,EAAM,IAAA,CAAK,WAAA,EAAa,IAAA,EAAK,IAAA,EAAK,CAAA;AAAA,MACtF,OAAA;AAAA,MACA,IAAA;AAAA,MACA,KAAA;AAAA,MACA,aAAA,EAAe,QAAA;AAAA,MACf,QAAA,EAAU,MAAM,KAAK,MAAA,EAAO;AAAA,MAC5B,SAAA,EAAW,MAAMC,mBAAA,CAAY,IAAA,EAAM,IAAI;AAAA;AAAA,GACzC;AAEJ;AChEO,IAAM,iBAAA,GAAoBC,UAAA;AAAA,EAAK,MACpC,OAAO,mCAAqB,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,iBAAA,EAAkB,CAAE;AAC9E;AAGO,IAAM,iBAAA,GAAoBA,UAAA;AAAA,EAAK,MACpC,OAAO,mCAAqB,CAAA,CAAE,IAAA,CAAK,CAAC,CAAA,MAAO,EAAE,OAAA,EAAS,CAAA,CAAE,iBAAA,EAAkB,CAAE;AAC9E;AAEO,SAAS,kBAAA,GAAmC;AACjD,EAAA,MAAM,gBAAgBT,sBAAAA,CAAe,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,IAAI,CAAA;AAC7D,EAAA,MAAM,kBAAkBA,sBAAAA,CAAe,CAAC,MAAM,CAAA,CAAE,QAAA,CAAS,SAAS,CAAC,CAAA;AACnE,EAAA,MAAM,eAAeU,uBAAA,EAAgB;AACrC,EAAA,uBACEC,eAAA,CAAAC,mBAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,aAAA,oBACCP,eAACQ,cAAA,EAAA,EAAS,QAAA,EAAU,MAClB,QAAA,kBAAAR,cAAAA,CAAC,qBAAkB,CAAA,EACrB,CAAA;AAAA,IAED,eAAA,IAAmB,YAAA,oBAAgBA,cAAAA,CAAC,qBAAA,EAAA,EAAsB;AAAA,GAAA,EAC7D,CAAA;AAEJ;ACfO,SAAS,eAAA,CAAgB;AAAA,EAC9B,SAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAAA,EAIiB;AACf,EAAA,MAAM,OAAON,eAAAA,EAAQ;AACrB,EAAA,MAAM,EAAE,MAAA,EAAQ,EAAA,EAAG,GAAIe,uCAAA,EAAsB;AAC7C,EAAA,MAAM,aAAad,sBAAAA,CAAe,CAAC,MAAMe,sBAAA,CAAe,CAAA,EAAG,SAAS,CAAC,CAAA;AACrE,EAAA,MAAM,SAAS,UAAA,KAAe,IAAA;AAC9B,EAAA,MAAM,UAAUC,uBAAA,EAAgB;AAChC,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAIf,eAAS,KAAK,CAAA;AAC5C,EAAA,MAAM,MAAA,GAAS,OAAA,CAAQ,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,WAAA,KAAgB,EAAA,IAAM,CAACgB,UAAA,CAAQ,CAAC,CAAC,CAAA;AAExE,EAAA,uBACEN,eAAAA,CAAAC,mBAAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAAP,cAAAA;AAAA,MAACa,iCAAA;AAAA,MAAA;AAAA,QACC,SAAS,YAAY;AAEnB,UAAA,IAAI,UAAA,IAAc,CAAC,OAAA,EAAS,OAAOC,iBAAS,IAAA,EAAM,EAAE,SAAA,EAAW,UAAA,EAAY,CAAA;AAC3E,UAAA,IAAI,MAAA,EAAQ,OAAOC,qBAAA,CAAc,IAAA,EAAM,EAAE,WAAW,KAAA,EAAO,IAAA,EAAM,EAAC,EAAG,CAAA;AACrE,UAAA,UAAA,CAAW,IAAI,CAAA;AACf,UAAA,OAAO,IAAA;AAAA,QACT,CAAA;AAAA,QACA,MAAA;AAAA,QACA,KAAA,EAAM,gBAAA;AAAA,QACN,MAAA,EAAO;AAAA;AAAA,KACT;AAAA,IACC,2BACCf,cAAAA;AAAA,MAACgB,kCAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAI,IAAA;AAAA,QACJ,YAAA,EAAc,UAAA;AAAA,QACd,KAAA,EAAM,MAAA;AAAA,QACN,OAAA,EAAS,MAAA;AAAA,QACT,aAAa,MAAA,CAAO,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,WAAW,CAAA;AAAA,QAC5C,QAAA,EAAU,OAAO,EAAE,IAAA,EAAK,KAAM;AAC5B,UAAA,MAAMD,sBAAc,IAAA,EAAM,EAAE,SAAA,EAAW,KAAA,EAAO,MAAM,CAAA;AAAA,QACtD;AAAA;AAAA;AACF,GAAA,EAEJ,CAAA;AAEJ;AC3DO,SAAS,YAAA,CAAa,EAAE,IAAA,EAAK,EAAyC;AAC3E,EAAA,MAAM,OAAOrB,eAAAA,EAAQ;AACrB,EAAA,MAAM,IAAA,GAAOuB,wBAAgB,IAAI,CAAA;AACjC,EAAA,uBACEjB,cAAAA;AAAA,IAACa,iCAAA;AAAA,IAAA;AAAA,MACC,OAAA,EAAS,MACPK,mBAAA,CAAY,IAAA,EAAM;AAAA,QAChB,aAAa,IAAA,CAAK,WAAA;AAAA,QAClB,qBAAA,EAAuB,KAAK,qBAAA,IAAyB,IAAA;AAAA,QACrD;AAAA,OACD,CAAA;AAAA,MAEH,KAAA,EAAO,QAAQ,IAAI,CAAA,CAAA;AAAA,MACnB,MAAA,EAAO;AAAA;AAAA,GACT;AAEJ;ACTO,SAAS,WAAA,GAAmC;AAEjD,EAAA,OAAOP,uBAAAA,EAAgB,mBAAIX,cAAAA,CAAC,sBAAmB,CAAA,GAAK,IAAA;AACtD;AAEA,SAAS,kBAAA,GAAmC;AAC1C,EAAA,MAAM,OAAON,eAAAA,EAAQ;AACrB,EAAA,MAAM,SAASC,sBAAAA,CAAe,CAAC,CAAA,KAAM,CAAA,CAAE,WAAW,IAAI,CAAA;AACtD,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIC,eAAS,KAAK,CAAA;AACtC,EAAA,uBACEU,eAAAA,CAAAC,mBAAAA,EAAA,EACE,QAAA,EAAA;AAAA,oBAAAP,cAAAA;AAAA,MAACmB,8BAAA;AAAA,MAAA;AAAA,QACC,MAAA,EAAO,kBAAA;AAAA,QACP,KAAA,EAAM,UAAA;AAAA,QACN,WAAA,EAAa,SAAS,2BAAA,GAA8B,gCAAA;AAAA,QACpD,OAAA,EAAS,MAAM,CAAC,MAAA,IAAU,QAAQ,IAAI;AAAA;AAAA,KACxC;AAAA,IACC,wBACCnB,cAAAA;AAAA,MAACgB,kCAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAI,IAAA;AAAA,QACJ,YAAA,EAAc,OAAA;AAAA,QACd,KAAA,EAAM,UAAA;AAAA,QACN,QAAA,EAAU,OAAO,EAAE,IAAA,EAAM,SAAQ,KAAM;AACrC,UAAA,MAAMI,0BAAkB,IAAA,EAAM;AAAA,YAC5B,OAAOC,mCAAA,CAAkB;AAAA,cACvB,GAAG,IAAA,CAAK,GAAA,CAAI,CAAC,CAAA,KAAMC,qBAAA,CAAmB,CAAC,CAAC,CAAA;AAAA,cACxC,GAAG,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,EAAE,IAAI;AAAA,aAC7B,CAAA;AAAA,YACD,IAAA;AAAA,YACA;AAAA,WACD,CAAA;AAAA,QACH;AAAA;AAAA;AACF,GAAA,EAEJ,CAAA;AAEJ;AChCO,SAAS,YAAA,CAAa;AAAA,EAC3B,SAAA;AAAA,EACA,UAAA;AAAA,EACA,MAAA;AAAA,EACA,IAAA;AAAA,EACA;AACF,CAAA,EASiB;AACf,EAAA,MAAM,OAAO5B,eAAAA,EAAQ;AACrB,EAAA,MAAM,EAAE,IAAA,EAAM,IAAA,KAAS6B,eAAA,CAAQ,MAAA,GAAS,YAAY,IAAI,CAAA;AACxD,EAAA,MAAM,UAAU5B,sBAAAA,CAAe,CAAC,CAAA,KAAM,SAAA,IAAa,EAAE,SAAS,CAAA;AAC9D,EAAA,MAAM,aAAaA,sBAAAA,CAAe,CAAC,MAAM,CAAA,CAAE,MAAA,EAAQ,cAAc,SAAS,CAAA;AAC1E,EAAA,MAAM,aAAA,GAAgBA,sBAAAA,CAAe,CAAC,CAAA,KAAM,CAAC,CAAC,CAAA,CAAE,MAAA,IAAU,CAAA,CAAE,MAAA,CAAO,SAAA,KAAc,SAAS,CAAA;AAC1F,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIC,eAAS,KAAK,CAAA;AACtC,EAAA,MAAM,IAAA,GAAO,MAAA,IAAU4B,4BAAA,CAAW,IAAA,EAAM,OAAO,CAAA;AAE/C,EAAA,IAAI,OAAA;AACJ,EAAA,IAAI,IAAA,EAAM,OAAA,GAAU,UAAA,GAAa,CAAA,EAAG,UAAU,CAAA,eAAA,CAAA,GAAoB,kBAAA;AAAA,OAAA,IACzD,MAAA,IAAU,IAAA,EAAM,UAAA,IAAc,IAAA,CAAK,QAAA,EAAU;AACpD,IAAA,MAAM,OAAA,GAAA,CAAW,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,QAAQ,IAAI,IAAA,CAAK,KAAA,CAAM,IAAA,CAAK,UAAU,CAAA,IAAK,GAAA;AAC5E,IAAA,MAAM,UAAU,IAAA,CAAK,iBAAA,IAAqB,EAAC,EAAG,IAAI,IAAI,CAAA;AACtD,IAAA,OAAA,GAAU;AAAA,MACR,MAAA;AAAA,MACAC,qCAAmB,OAAO,CAAA;AAAA,MAC1B,OAAO,MAAA,GAAS,CAAA,OAAA,EAAU,OAAO,IAAA,CAAK,IAAI,CAAC,CAAA,CAAA,GAAK;AAAA,KAClD,CACG,MAAA,CAAO,OAAO,CAAA,CACd,KAAK,QAAK,CAAA;AAAA,EACf,CAAA,MAAO,OAAA,GAAU,UAAA,GAAa,CAAA,gBAAA,EAAmB,UAAU,CAAA,CAAA,GAAK,MAAA;AAEhE,EAAA,uBACEnB,eAAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAU,0IAAA;AAAA,MACV,aAAA,EAAY,gBAAA;AAAA,MACZ,aAAW,IAAA,IAAQ,MAAA;AAAA,MAElB,QAAA,EAAA;AAAA,QAAA,IAAA,mBACCN,cAAAA,CAAC0B,iBAAA,EAAA,EAAM,SAAA,EAAU,wCAAuC,aAAA,EAAW,IAAA,EAAC,CAAA,mBAEpE1B,cAAAA,CAAC2B,oBAAA,EAAA,EAAS,SAAA,EAAU,8BAAA,EAA+B,eAAW,IAAA,EAAC,CAAA;AAAA,wBAEjE3B,cAAAA,CAAC,MAAA,EAAA,EAAK,aAAA,EAAY,0BAA0B,QAAA,EAAA,OAAA,EAAQ,CAAA;AAAA,QACnD,wBAAQA,cAAAA,CAAC,MAAA,EAAA,EAAK,SAAA,EAAU,yBAAyB,QAAA,EAAA,IAAA,EAAK,CAAA;AAAA,QACtD,wBACCA,cAAAA;AAAA,UAAC4B,SAAA;AAAA,UAAA;AAAA,YACC,IAAA,EAAK,QAAA;AAAA,YACL,IAAA,EAAK,IAAA;AAAA,YACL,SAAA,EAAU,gDAAA;AAAA,YACV,QAAA,EAAU,QAAQ,UAAA,IAAc,aAAA;AAAA,YAChC,KAAA,EAAO,gBAAgB,2BAAA,GAA8B,MAAA;AAAA,YACrD,SAAS,MAAM;AACb,cAAA,OAAA,CAAQ,IAAI,CAAA;AACZ,cAAA,KAAKd,gBAAAA,CAAS,IAAA,EAAM,EAAE,SAAA,EAAW,EAAE,OAAA,CAAQ,MAAM,OAAA,CAAQ,KAAK,CAAC,CAAA;AAAA,YACjE,CAAA;AAAA,YACA,aAAA,EAAY,qBAAA;AAAA,YAEX,uBAAa,SAAA,GAAY;AAAA;AAAA;AAC5B;AAAA;AAAA,GAEJ;AAEJ;ACrDA,IAAM,EAAE,mBAAA,EAAqB,sBAAA,EAAuB,GAAIe,aAAA;AAEjD,SAAS,wBAAA,CAAyB;AAAA,EACvC,IAAA;AAAA,EACA,QAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAA;AAAA,EACA,SAAA;AAAA,EACA,UAAA;AAAA,EACA,UAAA;AAAA,EACA,OAAA;AAAA,EACA,UAAA;AAAA,EACA;AACF,CAAA,EAAqB;AACnB,EAAA,MAAM,OAAOnC,eAAAA,EAAQ;AAErB,EAAA,MAAM,CAAC,IAAA,EAAM,OAAO,CAAA,GAAIE,eAAuD,KAAK,CAAA;AACpF,EAAAJ,eAAAA,CAAU,MAAM,OAAA,CAAQ,KAAK,GAAG,CAAC,IAAA,EAAM,WAAW,CAAC,CAAA;AAEnD,EAAA,MAAM,mBAAA,GAAsB,MAAM,WAAA,IAAe,IAAA;AAEjD,EAAA,MAAM,mBAAmBsC,qCAAA,EAAoB;AAC7C,EAAAtC,gBAAU,MAAM;AACd,IAAA,IAAI,gBAAA,IAAoB,mBAAA,EAAqB,OAAA,CAAQ,YAAY,CAAA;AAAA,EACnE,CAAA,EAAG,CAAC,gBAAA,EAAkB,mBAAmB,CAAC,CAAA;AAG1C,EAAA,MAAM,eAAA,GAAkBuC,cAAQ,MAAM;AACpC,IAAA,MAAM,MAAA,uBAAa,GAAA,EAAoB;AACvC,IAAA,KAAA,MAAW,CAAA,IAAK,QAAA;AACd,MAAA,IAAI,CAAA,CAAE,IAAA,KAAS,MAAA,IAAU,CAAA,CAAE,WAAA,IAAe,CAAC,CAAA,CAAE,OAAA,EAAS,MAAA,CAAO,GAAA,CAAI,CAAA,CAAE,WAAA,EAAa,EAAE,WAAW,CAAA;AAC/F,IAAA,OAAO,IAAI,GAAA,CAAI,MAAA,CAAO,MAAA,EAAQ,CAAA;AAAA,EAChC,CAAA,EAAG,CAAC,QAAQ,CAAC,CAAA;AAGb,EAAA,MAAM,gBAAA,GAAmBA,aAAA;AAAA,IACvB,MAAMC,8BAAA,CAAuB,QAAA,EAAUC,yBAAiB,CAAA;AAAA,IACxD,CAAC,QAAQ;AAAA,GACX;AACA,EAAA,MAAM,gBAAA,GAAmBC,2BAAA,CAAoB,mBAAA,EAAqB,gBAAgB,CAAA;AAClF,EAAA,MAAM,oBAAA,GAAuBH,aAAA;AAAA,IAC3B,MAAMI,iCAAA,CAA0B,QAAA,EAAUF,yBAAA,EAAmB,gBAAgB,CAAA;AAAA,IAC7E,CAAC,UAAU,gBAAgB;AAAA,GAC7B;AACA,EAAA,MAAM,kBAAA,GAAqBF,aAAA;AAAA,IACzB,MACEK,8BAAA;AAAA,MACE,QAAA,CAAS,MAAA,CAAO,CAAC,CAAA,KAAM,oBAAoB,CAAC,CAAA,IAAK,CAAC,CAAA,CAAE,OAAA,IAAW,CAAC,oBAAA,CAAqB,GAAA,CAAI,CAAC,CAAC;AAAA,KAC7F;AAAA,IACF,CAAC,UAAU,oBAAoB;AAAA,GACjC;AACA,EAAA,MAAM,aAAA,GAAgB,mBAAmB,MAAA,GAAS,CAAA;AAGlD,EAAA,MAAM,EAAE,MAAM,WAAA,EAAY,GAAIb,gBAAQ,aAAA,GAAgB,IAAA,EAAM,cAAc,IAAI,CAAA;AAC9E,EAAA,MAAM,MAAA,GAAS,CAAC,CAAC,WAAA,EAAa,UAAA;AAC9B,EAAA,MAAM,CAAC,YAAA,EAAc,eAAe,CAAA,GAAI3B,eAAwB,IAAI,CAAA;AACpE,EAAAJ,gBAAU,MAAM;AACd,IAAA,IAAI,CAAC,IAAA,IAAS,CAAC,MAAA,IAAU,CAAC,mBAAA,EAAsB;AAChD,IAAA,IAAI,SAAA,GAAY,KAAA;AAChB,IAAA,IAAA,CAAK,KAAA,CACF,KAAA,CAAM,IAAI,CAAA,CACV,KAAK,CAAC,CAAA,KAAM,CAAC,SAAA,IAAa,gBAAgB,CAAC,CAAC,CAAA,CAC5C,KAAA,CAAM,MAAM,MAAS,CAAA;AACxB,IAAA,OAAO,MAAM;AACX,MAAA,SAAA,GAAY,IAAA;AAAA,IACd,CAAA;AAAA,EACF,GAAG,CAAC,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,mBAAmB,CAAC,CAAA;AAE5C,EAAA,MAAM,iBAAA,GAAoB,CAAC,GAAA,KAA2B;AACpD,IAAA,MAAM,SAAS,GAAA,CAAI,aAAA,GAAgB,IAAA,GAAO,sBAAA,CAAuB,IAAI,OAAO,CAAA;AAC5E,IAAA,OAAO,EAAE,MAAA,EAAQ,SAAA,EAAW,QAAQ,gBAAA,IAAoB,GAAA,CAAI,iBAAiB,EAAA,EAAG;AAAA,EAClF,CAAA;AACA,EAAA,MAAM,gBAAA,GAAmBuC,aAAA;AAAA,IACvB,MACE,kBAAA,CACG,MAAA,CAAO,CAAC,CAAA,KAAM,CAAC,CAAA,CAAE,aAAa,CAAA,CAC9B,GAAA,CAAI,CAAC,CAAA,KAAM;AACV,MAAA,MAAM,MAAA,GAAS,sBAAA,CAAuB,CAAA,CAAE,OAAO,CAAA;AAC/C,MAAA,MAAM,SAAA,GAAY,MAAA,EAAQ,gBAAA,IAAoB,CAAA,CAAE,aAAA,IAAiB,EAAA;AACjE,MAAA,OAAO;AAAA,QACL,OAAA,EACE,QAAQ,YAAA,KACP,UAAA,CAAW,SAAS,CAAA,GAAI,UAAA,CAAW,SAAS,CAAA,GAAI,EAAA,CAAA,IACjD,eAAA;AAAA,QACF,EAAA,EAAI,MAAA,EAAQ,UAAA,IAAc,CAAA,CAAE,UAAA;AAAA,QAC5B,IAAA,EAAM,MAAA,EAAQ,IAAA,IAAQ,CAAA,CAAE,OAAA,IAAW;AAAA,OACrC;AAAA,IACF,CAAC,CAAA;AAAA,IACL,CAAC,kBAAA,EAAoB,UAAA,EAAY,UAAU;AAAA,GAC7C;AAGA,EAAA,MAAM,gBAAA,GAAmBA,cAAQ,MAAM;AACrC,IAAA,MAAM,KAAA,GAAQ,IAAA,KAAS,YAAA,GAAe,kBAAA,GAAqB,QAAA;AAC3D,IAAA,MAAM,SAAA,GAAYM,gCAAA;AAAA,MAChB,KAAA;AAAA,MACA,CAAC,CAAA,KACC,mBAAA,CAAoB,CAAC,CAAA,IAAK,CAAC,oBAAA,CAAqB,GAAA,CAAI,CAAC,CAAA,GACjD,iBAAA,CAAkB,CAAC,EAAE,SAAA,GACrB,IAAA;AAAA,MACN,CAAC,CAAA,KAAM,IAAA,CAAK,KAAA,CAAM,iBAAA,CAAkB,CAAC,CAAA,CAAE,MAAA,EAAQ,UAAA,IAAc,CAAA,CAAE,UAAA,IAAc,EAAE,CAAA,IAAK;AAAA,KACtF;AACA,IAAA,OAAO,EAAE,SAAA,EAAU;AAAA,EACrB,GAAG,CAAC,IAAA,EAAM,QAAA,EAAU,kBAAA,EAAoB,oBAAoB,CAAC,CAAA;AAC7D,EAAA,MAAM,eAAA,GAAkB,CAAC,GAAA,KAA2B;AAClD,IAAA,MAAM,EAAE,MAAA,EAAQ,SAAA,EAAU,GAAI,kBAAkB,GAAG,CAAA;AACnD,IAAA,uBACErC,cAAAA;AAAA,MAACsC,iCAAA;AAAA,MAAA;AAAA,QAEC,SAAA;AAAA,QACA,WAAA,EACE,SAAA,KAAc,OAAA,GACV,IAAA,GACA,QAAQ,YAAA,KACP,UAAA,CAAW,SAAS,CAAA,GAAI,UAAA,CAAW,SAAS,CAAA,GAAI,UAAA,CAAW,IAAI,aAAa,CAAA,CAAA;AAAA,QAEnF,IAAA,EAAM,MAAA,EAAQ,IAAA,IAAQ,GAAA,CAAI,OAAA,IAAW,EAAA;AAAA,QACrC,EAAA,EAAI,MAAA,EAAQ,UAAA,IAAc,GAAA,CAAI,UAAA;AAAA,QAC9B,SAAA,EAAW,gBAAA,CAAiB,SAAA,CAAU,GAAA,CAAI,GAAG;AAAA,OAAA;AAAA,MAVxC,GAAA,CAAI;AAAA,KAWX;AAAA,EAEJ,CAAA;AAEA,EAAA,MAAM,SAAA,GAAYP,aAAA;AAAA,IAChB,MACE,kBAAA,CAAmB,GAAA,CAAI,CAAC,CAAA,KAAM;AAC5B,MAAA,MAAM,EAAE,MAAA,EAAQ,SAAA,EAAU,GAAI,kBAAkB,CAAC,CAAA;AACjD,MAAA,OAAO,EAAE,SAAA,EAAW,EAAA,EAAI,IAAA,CAAK,KAAA,CAAM,MAAA,EAAQ,UAAA,IAAc,CAAA,CAAE,UAAA,IAAc,EAAE,CAAA,IAAK,CAAA,EAAE;AAAA,IACpF,CAAC,CAAA;AAAA,IAEH,CAAC,kBAAkB;AAAA,GACrB;AACA,EAAA,MAAM,mBAAA,GAAsBQ,wCAAA,CAAuB,mBAAA,EAAqB,SAAS,CAAA;AAEjF,EAAA,MAAM,aAAA,GAAgB;AAAA,IACpB,EAAE,KAAA,EAAO,KAAA,EAAgB,KAAA,EAAO,KAAA,EAAM;AAAA,IACtC,EAAE,KAAA,EAAO,MAAA,EAAiB,KAAA,EAAO,MAAA,EAAQ,QAAQ,aAAA,EAAc;AAAA,IAC/D;AAAA,MACE,KAAA,EAAO,YAAA;AAAA,MACP,KAAA,EAAO,YAAA;AAAA,MACP,OAAO,kBAAA,CAAmB,MAAA;AAAA,MAC1B,MAAA,EAAQ;AAAA,KACV;AAAA,IACA,GAAI,mBAAA,GACA,CAAC,EAAE,KAAA,EAAO,YAAA,EAAuB,KAAA,EAAO,YAAA,EAAc,MAAA,EAAQ,mBAAA,EAAqB,CAAA,GACnF;AAAC,GACP;AAEA,EAAA,uBACEjC,eAAAA,CAAAC,mBAAAA,EAAA,EACG,QAAA,EAAA;AAAA,IAAA,QAAA,CAAS,WAAW,CAAA,IAAK,mBAAA,oBACxBP,cAAAA,CAACwC,uCAAA,EAAA,EAAsB,WAAW,mBAAA,EAAqB,CAAA;AAAA,IAAA,CAEvD,iBAAiB,mBAAA,qBACjBxC,eAAC,KAAA,EAAA,EAAI,SAAA,EAAU,8CACb,QAAA,kBAAAA,cAAAA;AAAA,MAACyC,oCAAA;AAAA,MAAA;AAAA,QACC,KAAA,EAAO,IAAA;AAAA,QACP,OAAA,EAAS,aAAA;AAAA,QACT,QAAA,EAAU;AAAA;AAAA,KACZ,EACF,CAAA;AAAA,IAED,IAAA,KAAS,YAAA,IAAgB,mBAAA,oBACxBzC,cAAAA,CAAC0C,gCAAA,EAAA,EAAe,SAAA,EAAW,mBAAA,EAAqB,KAAA,EAAO,YAAA,EAAc,SAAA,EAAU,MAAA,EAAO,CAAA;AAAA,IAEvF,SAAA;AAAA,IACA,IAAA,KAAS,gCACRpC,eAAAA,CAAC,SAAI,SAAA,EAAU,oBAAA,EAAqB,eAAY,iBAAA,EAC7C,QAAA,EAAA;AAAA,MAAA,MAAA,oBACCN,cAAAA;AAAA,QAAC2C,wCAAA;AAAA,QAAA;AAAA,UACC,KAAA,EAAO,YAAA;AAAA,UACP,KAAA,EAAO,gBAAA;AAAA,UACP,SAAA,EAAU;AAAA;AAAA,OACZ;AAAA,MAED,mBAAmB,GAAA,CAAI,CAAC,GAAA,KAAQ,eAAA,CAAgB,GAAG,CAAC,CAAA;AAAA,sBACrD3C,cAAAA,CAAC4C,qCAAA,EAAA,EAAoB,GAAA,EAAK,mBAAA,EAAqB;AAAA,KAAA,EACjD,CAAA;AAAA,IAAA,CAEA,IAAA,KAAS,SAAS,IAAA,KAAS,MAAA,KAC3B,MAAM,GAAA,CAAI,CAAC,MAAM,CAAA,KAAM;AACrB,MAAA,MAAM,EAAE,OAAA,EAAS,GAAA,EAAK,YAAA,EAAa,GAAI,IAAA;AACvC,MAAA,MAAM,OAAA,GAAU,CAAC,CAAC,GAAA,CAAI,OAAA;AAEtB,MAAA,IAAI,OAAA,IAAW,mBAAA,CAAoB,GAAG,CAAA,EAAG,OAAO,IAAA;AAChD,MAAA,MAAM,SAAA,GAAY,gCAChB5C,cAAAA,CAAC6C,yBAAe,QAAA,EAAA,SAAA,CAAU,GAAA,CAAI,UAAU,CAAA,EAAE,CAAA;AAE5C,MAAA,IAAI,mBAAA,CAAoB,GAAG,CAAA,EAAG;AAC5B,QAAA,IAAI,IAAA,KAAS,QAAQ,OAAO,IAAA;AAE5B,QAAA,MAAM,UAAA,GAAa,oBAAA,CAAqB,GAAA,CAAI,GAAG,CAAA;AAC/C,QAAA,IAAI,UAAA,IAAc,CAAC,YAAA,EAAc,OAAO,IAAA;AACxC,QAAA,uBACEvC,eAAAA,CAACC,cAAAA,EAAA,EACE,QAAA,EAAA;AAAA,UAAA,SAAA;AAAA,UACA,CAAC,UAAA,IAAc,eAAA,CAAgB,GAAG;AAAA,SAAA,EAAA,EAFtB,IAAI,WAGnB,CAAA;AAAA,MAEJ;AACA,MAAA,IAAI,IAAI,IAAA,KAAS,WAAA,IAAe,GAAA,CAAI,WAAA,IAAe,CAAC,OAAA,EAAS;AAE3D,QAAA,uBACED,eAAAA,CAACC,cAAAA,EAAA,EACE,QAAA,EAAA;AAAA,UAAA,SAAA;AAAA,0BACDP,cAAAA;AAAA,YAAC8C,+BAAA;AAAA,YAAA;AAAA,cACC,WAAW,GAAA,CAAI,WAAA;AAAA,cACf,cAAA,EAAgB,IAAI,gBAAA,IAAoB,IAAA;AAAA,cACxC,KAAA,EAAO,YAAA;AAAA,cACP,IAAA,EAAM,UAAA,CAAW,GAAA,CAAI,UAAU;AAAA;AAAA;AACjC,SAAA,EAAA,EAPa,IAAI,WAQnB,CAAA;AAAA,MAEJ;AACA,MAAA,IAAI,IAAI,IAAA,KAAS,MAAA,IAAU,GAAA,CAAI,WAAA,IAAe,CAAC,OAAA,EAAS;AACtD,QAAA,uBACExC,eAAAA,CAACC,cAAAA,EAAA,EACE,QAAA,EAAA;AAAA,UAAA,SAAA;AAAA,0BACDP,cAAAA;AAAA,YAAC,YAAA;AAAA,YAAA;AAAA,cACC,WAAW,GAAA,CAAI,WAAA;AAAA,cACf,YAAY,GAAA,CAAI,aAAA,GAAgB,UAAA,CAAW,GAAA,CAAI,aAAa,CAAA,GAAI,IAAA;AAAA,cAChE,MAAA,EAAQ,eAAA,CAAgB,GAAA,CAAI,GAAA,CAAI,WAAW,CAAA;AAAA,cAC3C,IAAA,EAAM,UAAA;AAAA,cACN,IAAA,EAAM,UAAA,CAAW,GAAA,CAAI,UAAU;AAAA;AAAA;AACjC,SAAA,EAAA,EARa,IAAI,WASnB,CAAA;AAAA,MAEJ;AACA,MAAA,OAAO,UAAA,CAAW,MAAM,CAAC,CAAA;AAAA,IAC3B,CAAC,CAAA;AAAA,IACF,SAAS,KAAA,oBAASA,cAAAA,CAAC4C,qCAAA,EAAA,EAAoB,KAAK,mBAAA,EAAqB;AAAA,GAAA,EACpE,CAAA;AAEJ","file":"index.cjs","sourcesContent":["/**\n * ConnectedIncomingCall — persistent ringer for the oldest queued `call.ringing` (the card itself is\n * `IncomingCallCard`).\n *\n * A non-modal card (role=\"alertdialog\") rather than a blocking modal: a ring\n * should not trap the user mid-sentence. It rings (WebAudio, mutable) and\n * stays until accepted, declined, cancelled by the caller (`call.ended`), or\n * 30 s pass (then it is dropped silently — the backend records a missed call).\n * Accepting joins at once (microphone on, camera off), without the pre-join.\n */\n\nimport {\n useArbi,\n callSession,\n useCallSession,\n type IncomingCall,\n acceptRing,\n declineRing,\n} from '@arbidocs/react'\nimport { useEffect, useState, type ReactElement } from 'react'\nimport { IncomingCallCard } from '../cards'\nimport { useRingtone, useRingtoneMuted } from '../ringtone'\nimport { CallUserPill } from './CallUserPill'\n\nexport const RING_TIMEOUT_MS = 30_000\n\nfunction useRingTimeout(ring: IncomingCall | undefined) {\n useEffect(() => {\n if (!ring) return\n const remaining = Math.max(0, ring.receivedAt + RING_TIMEOUT_MS - Date.now())\n const timer = setTimeout(() => callSession.removeIncomingCall(ring.call_ext_id), remaining)\n return () => clearTimeout(timer)\n }, [ring])\n}\n\nexport function ConnectedIncomingCall(): ReactElement | null {\n const arbi = useArbi()\n const ring = useCallSession((s) => s.incoming[0])\n const [busy, setBusy] = useState(false)\n const [muted, setMuted] = useRingtoneMuted()\n useRingTimeout(ring)\n // Stops on accept (busy), decline / timeout / caller hang-up (ring removed), or mute.\n useRingtone(!!ring && !busy, muted)\n\n if (!ring) return null\n\n const accept = async () => {\n setBusy(true)\n await acceptRing(arbi, ring)\n setBusy(false)\n }\n\n // thread: a workspace-locked thread call; dm: our direct chat; meeting: a group / meeting chat;\n // none: a contacts or calendar-event call.\n const context =\n ring.context === 'dm'\n ? 'is calling you'\n : ring.context === 'thread'\n ? 'started a call in a shared thread'\n : ring.context === 'meeting'\n ? 'invites you to a group call'\n : 'invites you to a call'\n\n return (\n <IncomingCallCard\n className=\"fixed right-4 top-4 z-[60]\"\n callerName={ring.caller_name}\n caller={<CallUserPill identity={ring.caller_ext_id} name={ring.caller_name} size=\"sm\" />}\n context={context}\n busy={busy}\n muted={muted}\n onMutedChange={setMuted}\n onAccept={() => void accept()}\n onDecline={() => declineRing(arbi, ring)}\n />\n )\n}\n","/**\n * The global call surface, mounted once by the host: the incoming-call ringer (when the call UI is\n * on, `useCallsEnabled`) and, only while a call is active, the dock. The dock is loaded on demand: it\n * pulls in LiveKit, so a page without a call never downloads it. The dock is not gated: an active\n * call comes from the gated call buttons or from a call link, which must open for everyone.\n */\n\nimport { lazy, Suspense, type ReactElement } from 'react'\nimport { useCallSession, useCallsEnabled } from '@arbidocs/react'\nimport { ConnectedIncomingCall } from './ConnectedIncomingCall'\n\n/** The dock (and with it LiveKit), loaded when a call starts. */\nexport const ConnectedCallDock = lazy(() =>\n import('./ConnectedCallDock').then((m) => ({ default: m.ConnectedCallDock }))\n)\n\n/** One call room, loaded on demand (LiveKit); render it inside `<Suspense>`. */\nexport const ConnectedCallRoom = lazy(() =>\n import('./ConnectedCallRoom').then((m) => ({ default: m.ConnectedCallRoom }))\n)\n\nexport function ConnectedCallLayer(): ReactElement {\n const hasActiveCall = useCallSession((s) => s.active !== null)\n const hasIncomingCall = useCallSession((s) => s.incoming.length > 0)\n const callsEnabled = useCallsEnabled()\n return (\n <>\n {hasActiveCall && (\n <Suspense fallback={null}>\n <ConnectedCallDock />\n </Suspense>\n )}\n {hasIncomingCall && callsEnabled && <ConnectedIncomingCall />}\n </>\n )\n}\n","/**\n * Call button for an open group chat: the group's call (the group is its meeting chat). The\n * members picker opens with everyone ticked; only the people left ticked are rung.\n */\n\nimport {\n useArbi,\n chatLiveCallId,\n useCallSession,\n openCall,\n startChatCall,\n useCanHostCalls,\n type UserResponse,\n} from '@arbidocs/react'\nimport { isAgent } from '@arbidocs/react/ui'\nimport { useState, type ReactElement } from 'react'\nimport { useConnectedWorkspace } from '../../connection/ConnectionProvider'\nimport { StartCallButton } from './StartCallButton'\nimport { CallPeoplePicker } from './CallPeoplePicker'\n\nexport function GroupCallButton({\n chatExtId,\n title,\n members,\n}: {\n chatExtId: string\n title: string | null\n members: UserResponse[]\n}): ReactElement {\n const arbi = useArbi()\n const { userId: me } = useConnectedWorkspace()\n const liveCallId = useCallSession((s) => chatLiveCallId(s, chatExtId))\n const isLive = liveCallId !== null\n const canHost = useCanHostCalls()\n const [picking, setPicking] = useState(false)\n const others = members.filter((u) => u.external_id !== me && !isAgent(u))\n\n return (\n <>\n <StartCallButton\n onStart={async () => {\n // Someone who may not host opens the running call itself (a new create would make them its host).\n if (liveCallId && !canHost) return openCall(arbi, { callExtId: liveCallId })\n if (isLive) return startChatCall(arbi, { chatExtId, title, ring: [] })\n setPicking(true)\n return true\n }}\n isLive={isLive}\n label=\"Call the group\"\n testId=\"group-call-button\"\n />\n {picking && (\n <CallPeoplePicker\n open\n onOpenChange={setPicking}\n scope=\"chat\"\n members={others}\n preselected={others.map((u) => u.external_id)}\n onSubmit={async ({ ring }) => {\n await startChatCall(arbi, { chatExtId, title, ring })\n }}\n />\n )}\n </>\n )\n}\n","/** Call button for an open DM thread: a new call with the peer as context, ringing the peer. */\n\nimport { useArbi, userDisplayName, startDmCall, type UserResponse } from '@arbidocs/react'\nimport type { ReactElement } from 'react'\nimport { StartCallButton } from './StartCallButton'\n\nexport function DmCallButton({ peer }: { peer: UserResponse }): ReactElement {\n const arbi = useArbi()\n const name = userDisplayName(peer)\n return (\n <StartCallButton\n onStart={() =>\n startDmCall(arbi, {\n external_id: peer.external_id,\n encryption_public_key: peer.encryption_public_key ?? null,\n name,\n })\n }\n label={`Call ${name}`}\n testId=\"dm-call-button\"\n />\n )\n}\n","/**\n * \"New call\" — a call with people from my contacts (no thread or chat). Registered contacts are\n * rung; unregistered ones get a personal invite link by e-mail (register, then join). Its meeting chat is made on first\n * use. Renders nothing unless the person may host calls (server + Settings → Experimental + entitlement).\n */\n\nimport { useArbi, useCallSession, useCanHostCalls, startContactsCall } from '@arbidocs/react'\nimport { getUserDisplayName } from '@arbidocs/react/ui'\nimport { useState, type ReactElement } from 'react'\nimport { DmInviteChip } from '../../collaboration/direct-messages/DirectMessages'\nimport { CallPeoplePicker } from './CallPeoplePicker'\nimport { contactsCallTitle } from '../call-cards'\n\nexport function NewCallChip(): ReactElement | null {\n // Gate first so a deployment without calls pays for none of the hooks below.\n return useCanHostCalls() ? <EnabledNewCallChip /> : null\n}\n\nfunction EnabledNewCallChip(): ReactElement {\n const arbi = useArbi()\n const inCall = useCallSession((s) => s.active !== null)\n const [open, setOpen] = useState(false)\n return (\n <>\n <DmInviteChip\n testId=\"dm-new-call-chip\"\n title=\"New call\"\n description={inCall ? 'You are already in a call' : 'Call people from your contacts'}\n onClick={() => !inCall && setOpen(true)}\n />\n {open && (\n <CallPeoplePicker\n open\n onOpenChange={setOpen}\n scope=\"contacts\"\n onSubmit={async ({ ring, invites }) => {\n await startContactsCall(arbi, {\n title: contactsCallTitle([\n ...ring.map((u) => getUserDisplayName(u)),\n ...invites.map((g) => g.name),\n ]),\n ring,\n invites,\n })\n }}\n />\n )}\n </>\n )\n}\n","/**\n * A `kind=call` chat message (the server posts one into the call's chat — a DM, a group or a\n * meeting chat — when a session starts). The newest card of a call shows its state:\n *\n * live: \"Ada started a call\" · Join\n * ended: \"Call · 12 min · joined Ada, Bob\"\n *\n * Older cards of the same call (earlier sessions) stay a plain \"Call\" line. The call is re-read on\n * `call.started` / `call.ended` (see `refreshCallCards`).\n */\n\nimport { useArbi, useCallSession, useCall, openCall } from '@arbidocs/react'\nimport { useState, type ReactElement } from 'react'\nimport { Phone, PhoneOff } from 'lucide-react'\nimport { Button } from '@arbidocs/react/ui'\nimport { formatCallDuration, isCallLive } from '../call-cards'\n\nexport function ChatCallCard({\n callExtId,\n senderName,\n latest,\n name,\n time,\n}: {\n callExtId: string\n /** Who started the session (the card's sender). */\n senderName: string | null\n /** The newest card of this call in the chat. */\n latest: boolean\n /** A member's display name by user ext id. */\n name: (userExtId: string) => string\n time?: string\n}): ReactElement {\n const arbi = useArbi()\n const { data: call } = useCall(latest ? callExtId : null)\n const liveNow = useCallSession((s) => callExtId in s.liveCalls)\n const inThisCall = useCallSession((s) => s.active?.callExtId === callExtId)\n const inAnotherCall = useCallSession((s) => !!s.active && s.active.callExtId !== callExtId)\n const [busy, setBusy] = useState(false)\n const live = latest && isCallLive(call, liveNow)\n\n let summary: string\n if (live) summary = senderName ? `${senderName} started a call` : 'Call in progress'\n else if (latest && call?.started_at && call.ended_at) {\n const seconds = (Date.parse(call.ended_at) - Date.parse(call.started_at)) / 1000\n const joined = (call.last_participants ?? []).map(name)\n summary = [\n 'Call',\n formatCallDuration(seconds),\n joined.length ? `joined ${joined.join(', ')}` : null,\n ]\n .filter(Boolean)\n .join(' · ')\n } else summary = senderName ? `Call started by ${senderName}` : 'Call'\n\n return (\n <div\n className=\"mx-auto my-2 flex w-fit max-w-full flex-wrap items-center justify-center gap-2 rounded-md border border-border bg-card px-3 py-2 text-xs\"\n data-testid=\"chat-call-card\"\n data-live={live || undefined}\n >\n {live ? (\n <Phone className=\"size-4 animate-pulse text-green-text\" aria-hidden />\n ) : (\n <PhoneOff className=\"size-4 text-muted-foreground\" aria-hidden />\n )}\n <span data-testid=\"chat-call-card-summary\">{summary}</span>\n {time && <time className=\"text-muted-foreground\">{time}</time>}\n {live && (\n <Button\n type=\"button\"\n size=\"sm\"\n className=\"h-7 bg-green-600 text-white hover:bg-green-700\"\n disabled={busy || inThisCall || inAnotherCall}\n title={inAnotherCall ? 'You are already in a call' : undefined}\n onClick={() => {\n setBusy(true)\n void openCall(arbi, { callExtId }).finally(() => setBusy(false))\n }}\n data-testid=\"chat-call-card-join\"\n >\n {inThisCall ? 'In call' : 'Join'}\n </Button>\n )}\n </div>\n )\n}\n","/**\n * A chat thread's history with its call: the messenger kit's `ThreadHistory` (blocks\n * `ConnectedChatThread`). A chat with a call (a meeting chat, or a direct or group chat a call was\n * started from) shows its call cards, live transcript, recordings and the speakers talking right\n * now, and filters between everything, the typed chat, the transcript and the recordings. Typed\n * messages are drawn by the kit (`renderItem`).\n */\n\nimport { Fragment, useEffect, useMemo, useState } from 'react'\nimport {\n DateSeparator,\n useArbi,\n type ChatThreadMessage,\n useCall,\n chatTranscriptRef,\n hasRecordingTranscript,\n sortTranscriptMessages,\n supersededTranscriptLines,\n type TranscriptExportLine,\n useRecordingWindows,\n} from '@arbidocs/react'\nimport { chats } from '@arbidocs/sdk/browser'\nimport { ConversationFilter } from '../../chat/TranscriptLine'\nimport { transcriptRuns } from '../../chat/transcript-runs'\nimport type { ChatHistoryProps } from '../../connection/messenger/types'\nimport { usePendingRecording } from '../recording-link'\nimport { ChatCallCard } from './ChatCallCard'\nimport { TranscriptEntry } from './TranscriptEntry'\nimport { CallConversationEmpty, ProvisionalSpeakers } from './CallConversationParts'\nimport { useProvisionalSpeakers } from './provisional-speakers'\nimport { SaveTranscriptToThread } from './SaveTranscriptToThread'\nimport { RecordingCard, RecordingsList } from './RecordingCard'\n\nconst { isTranscriptMessage, parseTranscriptContent } = chats\n\nexport function ConnectedCallChatHistory({\n chat,\n messages,\n items,\n renderItem,\n loadOlder,\n memberById,\n senderName,\n myExtId,\n formatTime,\n formatDay,\n}: ChatHistoryProps) {\n const arbi = useArbi()\n // A call's chat: everything, typed chat only, the transcript only, or the recordings.\n const [view, setView] = useState<'all' | 'chat' | 'transcript' | 'recordings'>('all')\n useEffect(() => setView('all'), [chat?.external_id])\n // A call's chat (meeting, DM or group with a call) lists the call's recordings.\n const recordingsCallExtId = chat?.call_ext_id ?? null\n // A recording link opened this chat: show its recordings.\n const pendingRecording = usePendingRecording()\n useEffect(() => {\n if (pendingRecording && recordingsCallExtId) setView('recordings')\n }, [pendingRecording, recordingsCallExtId])\n\n // The newest call card of each call shows its live / ended state; older ones are a plain line.\n const latestCallCards = useMemo(() => {\n const latest = new Map<string, string>()\n for (const m of messages)\n if (m.kind === 'call' && m.call_ext_id && !m.deleted) latest.set(m.call_ext_id, m.external_id)\n return new Set(latest.values())\n }, [messages])\n\n // A recording's transcript supersedes the live lines spoken while it recorded (else both show).\n const hasRecTranscript = useMemo(\n () => hasRecordingTranscript(messages, chatTranscriptRef),\n [messages]\n )\n const recordingWindows = useRecordingWindows(recordingsCallExtId, hasRecTranscript)\n const supersededTranscript = useMemo(\n () => supersededTranscriptLines(messages, chatTranscriptRef, recordingWindows),\n [messages, recordingWindows]\n )\n const transcriptMessages = useMemo(\n () =>\n sortTranscriptMessages(\n messages.filter((m) => isTranscriptMessage(m) && !m.deleted && !supersededTranscript.has(m))\n ),\n [messages, supersededTranscript]\n )\n const hasTranscript = transcriptMessages.length > 0\n\n // The host can save the decrypted transcript as one comment into a workspace thread.\n const { data: meetingCall } = useCall(hasTranscript ? chat?.call_ext_id : null)\n const isHost = !!meetingCall?.is_creator\n const [meetingTitle, setMeetingTitle] = useState<string | null>(null)\n useEffect(() => {\n if (!chat || (!isHost && !recordingsCallExtId)) return\n let cancelled = false\n arbi.chats\n .title(chat)\n .then((t) => !cancelled && setMeetingTitle(t))\n .catch(() => undefined)\n return () => {\n cancelled = true\n }\n }, [arbi, isHost, chat, recordingsCallExtId])\n\n const transcriptSpeaker = (msg: ChatThreadMessage) => {\n const parsed = msg.decryptFailed ? null : parseTranscriptContent(msg.content)\n return { parsed, speakerId: parsed?.speaker_identity || msg.sender_ext_id || '' }\n }\n const transcriptExport = useMemo<TranscriptExportLine[]>(\n () =>\n transcriptMessages\n .filter((m) => !m.decryptFailed)\n .map((m) => {\n const parsed = parseTranscriptContent(m.content)\n const speakerId = parsed?.speaker_identity || m.sender_ext_id || ''\n return {\n speaker:\n parsed?.speaker_name ||\n (memberById(speakerId) ? senderName(speakerId) : '') ||\n 'Former member',\n at: parsed?.started_at ?? m.created_at,\n text: parsed?.text ?? m.content ?? '',\n }\n }),\n [transcriptMessages, memberById, senderName]\n )\n // Consecutive lines of one speaker are one run (the name once); each speaker's newest line is\n // highlighted while they talk in the call.\n const transcriptLayout = useMemo(() => {\n const shown = view === 'transcript' ? transcriptMessages : messages\n const continued = transcriptRuns(\n shown,\n (m) =>\n isTranscriptMessage(m) && !supersededTranscript.has(m)\n ? transcriptSpeaker(m).speakerId\n : null,\n (m) => Date.parse(transcriptSpeaker(m).parsed?.started_at ?? m.created_at ?? '') || 0\n )\n return { continued }\n }, [view, messages, transcriptMessages, supersededTranscript])\n const transcriptEntry = (msg: ChatThreadMessage) => {\n const { parsed, speakerId } = transcriptSpeaker(msg)\n return (\n <TranscriptEntry\n key={msg.external_id}\n speakerId={speakerId}\n speakerName={\n speakerId === myExtId\n ? 'Me'\n : parsed?.speaker_name ||\n (memberById(speakerId) ? senderName(speakerId) : senderName(msg.sender_ext_id))\n }\n text={parsed?.text ?? msg.content ?? ''}\n at={parsed?.started_at ?? msg.created_at}\n continued={transcriptLayout.continued.has(msg)}\n />\n )\n }\n // While I am in this chat's call: \"<speaker> is speaking…\" until their line arrives.\n const chatLines = useMemo(\n () =>\n transcriptMessages.map((m) => {\n const { parsed, speakerId } = transcriptSpeaker(m)\n return { speakerId, at: Date.parse(parsed?.started_at ?? m.created_at ?? '') || 0 }\n }),\n\n [transcriptMessages]\n )\n const provisionalSpeakers = useProvisionalSpeakers(recordingsCallExtId, chatLines)\n\n const filterOptions = [\n { value: 'all' as const, label: 'All' },\n { value: 'chat' as const, label: 'Chat', testId: 'chat-filter' },\n {\n value: 'transcript' as const,\n label: 'Transcript',\n count: transcriptMessages.length,\n testId: 'transcript-filter',\n },\n ...(recordingsCallExtId\n ? [{ value: 'recordings' as const, label: 'Recordings', testId: 'recordings-filter' }]\n : []),\n ]\n\n return (\n <>\n {messages.length === 0 && recordingsCallExtId && (\n <CallConversationEmpty callExtId={recordingsCallExtId} />\n )}\n {(hasTranscript || recordingsCallExtId) && (\n <div className=\"sticky top-0 z-10 flex justify-center py-1\">\n <ConversationFilter<typeof view>\n value={view}\n options={filterOptions}\n onChange={setView}\n />\n </div>\n )}\n {view === 'recordings' && recordingsCallExtId && (\n <RecordingsList callExtId={recordingsCallExtId} title={meetingTitle} className=\"py-1\" />\n )}\n {loadOlder}\n {view === 'transcript' && (\n <div className=\"flex flex-col py-1\" data-testid=\"transcript-view\">\n {isHost && (\n <SaveTranscriptToThread\n title={meetingTitle}\n lines={transcriptExport}\n className=\"mx-3 mb-2 self-start\"\n />\n )}\n {transcriptMessages.map((msg) => transcriptEntry(msg))}\n <ProvisionalSpeakers ids={provisionalSpeakers} />\n </div>\n )}\n {(view === 'all' || view === 'chat') &&\n items.map((item, i) => {\n const { message: msg, isFirstOfDay } = item\n const deleted = !!msg.deleted\n // A deleted transcript line is not part of the record (it may be stored again).\n if (deleted && isTranscriptMessage(msg)) return null\n const separator = isFirstOfDay && (\n <DateSeparator>{formatDay(msg.created_at)}</DateSeparator>\n )\n if (isTranscriptMessage(msg)) {\n if (view === 'chat') return null\n // A live line superseded by the recording's transcript is not shown.\n const superseded = supersededTranscript.has(msg)\n if (superseded && !isFirstOfDay) return null\n return (\n <Fragment key={msg.external_id}>\n {separator}\n {!superseded && transcriptEntry(msg)}\n </Fragment>\n )\n }\n if (msg.kind === 'recording' && msg.call_ext_id && !deleted) {\n // The server's Recording card (posted when a recording stops).\n return (\n <Fragment key={msg.external_id}>\n {separator}\n <RecordingCard\n callExtId={msg.call_ext_id}\n recordingExtId={msg.recording_ext_id ?? null}\n title={meetingTitle}\n time={formatTime(msg.created_at)}\n />\n </Fragment>\n )\n }\n if (msg.kind === 'call' && msg.call_ext_id && !deleted) {\n return (\n <Fragment key={msg.external_id}>\n {separator}\n <ChatCallCard\n callExtId={msg.call_ext_id}\n senderName={msg.sender_ext_id ? senderName(msg.sender_ext_id) : null}\n latest={latestCallCards.has(msg.external_id)}\n name={senderName}\n time={formatTime(msg.created_at)}\n />\n </Fragment>\n )\n }\n return renderItem(item, i)\n })}\n {view === 'all' && <ProvisionalSpeakers ids={provisionalSpeakers} />}\n </>\n )\n}\n"]}
1
+ {"version":3,"sources":["../../src/calls/connected/ConnectedIncomingCall.tsx","../../src/calls/connected/ConnectedCallLayer.tsx","../../src/calls/connected/GroupCallButton.tsx","../../src/calls/connected/DmCallButton.tsx","../../src/calls/connected/NewCallChip.tsx","../../src/calls/connected/ChatCallCard.tsx","../../src/calls/connected/ConnectedCallChatHistory.tsx","../../src/calls/connected/ConnectedCallPage.tsx"],"names":["useEffect","callSession","useArbi","useCallSession","useState","useRingtoneMuted","useRingtone","acceptRing","jsx","IncomingCallCard","CallUserPill","declineRing","lazy","useCallsEnabled","jsxs","Fragment","Suspense","useConnectedWorkspace","chatLiveCallId","useCanHostCalls","isAgent","StartCallButton","openCall","startChatCall","CallPeoplePicker","userDisplayName","startDmCall","DmInviteChip","startContactsCall","contactsCallTitle","getUserDisplayName","useCall","isCallLive","formatCallDuration","Phone","PhoneOff","Button","chats","usePendingRecording","useMemo","hasRecordingTranscript","chatTranscriptRef","useRecordingWindows","supersededTranscriptLines","sortTranscriptMessages","transcriptRuns","TranscriptEntry","useProvisionalSpeakers","CallConversationEmpty","ConversationFilter","RecordingsList","SaveTranscriptToThread","ProvisionalSpeakers","DateSeparator","RecordingCard","useRef","CallsExperimentalBadge","LogIn","UserPlus","Lock","parseCallFragment"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * ConnectedIncomingCall — persistent ringer for the oldest queued `call.ringing` (the card itself is\n * `IncomingCallCard`).\n *\n * A non-modal card (role=\"alertdialog\") rather than a blocking modal: a ring\n * should not trap the user mid-sentence. It rings (WebAudio, mutable) and\n * stays until accepted, declined, cancelled by the caller (`call.ended`), or\n * 30 s pass (then it is dropped silently — the backend records a missed call).\n * Accepting joins at once (microphone on, camera off), without the pre-join.\n */\n\nimport {\n useArbi,\n callSession,\n useCallSession,\n type IncomingCall,\n acceptRing,\n declineRing,\n} from '@arbidocs/react'\nimport { useEffect, useState, type ReactElement } from 'react'\nimport { IncomingCallCard } from '../cards'\nimport { useRingtone, useRingtoneMuted } from '../ringtone'\nimport { CallUserPill } from './CallUserPill'\n\nexport const RING_TIMEOUT_MS = 30_000\n\nfunction useRingTimeout(ring: IncomingCall | undefined) {\n useEffect(() => {\n if (!ring) return\n const remaining = Math.max(0, ring.receivedAt + RING_TIMEOUT_MS - Date.now())\n const timer = setTimeout(() => callSession.removeIncomingCall(ring.call_ext_id), remaining)\n return () => clearTimeout(timer)\n }, [ring])\n}\n\nexport function ConnectedIncomingCall(): ReactElement | null {\n const arbi = useArbi()\n const ring = useCallSession((s) => s.incoming[0])\n const [busy, setBusy] = useState(false)\n const [muted, setMuted] = useRingtoneMuted()\n useRingTimeout(ring)\n // Stops on accept (busy), decline / timeout / caller hang-up (ring removed), or mute.\n useRingtone(!!ring && !busy, muted)\n\n if (!ring) return null\n\n const accept = async () => {\n setBusy(true)\n await acceptRing(arbi, ring)\n setBusy(false)\n }\n\n // thread: a workspace-locked thread call; dm: our direct chat; meeting: a group / meeting chat;\n // none: a contacts or calendar-event call.\n const context =\n ring.context === 'dm'\n ? 'is calling you'\n : ring.context === 'thread'\n ? 'started a call in a shared thread'\n : ring.context === 'meeting'\n ? 'invites you to a group call'\n : 'invites you to a call'\n\n return (\n <IncomingCallCard\n className=\"fixed right-4 top-4 z-[60]\"\n callerName={ring.caller_name}\n caller={<CallUserPill identity={ring.caller_ext_id} name={ring.caller_name} size=\"sm\" />}\n context={context}\n busy={busy}\n muted={muted}\n onMutedChange={setMuted}\n onAccept={() => void accept()}\n onDecline={() => declineRing(arbi, ring)}\n />\n )\n}\n","/**\n * The global call surface, mounted once by the host: the incoming-call ringer (when the call UI is\n * on, `useCallsEnabled`) and, only while a call is active, the dock. The dock is loaded on demand: it\n * pulls in LiveKit, so a page without a call never downloads it. The dock is not gated: an active\n * call comes from the gated call buttons or from a call link, which must open for everyone.\n */\n\nimport { lazy, Suspense, type ReactElement } from 'react'\nimport { useCallSession, useCallsEnabled } from '@arbidocs/react'\nimport { ConnectedIncomingCall } from './ConnectedIncomingCall'\n\n/** The dock (and with it LiveKit), loaded when a call starts. */\nexport const ConnectedCallDock = lazy(() =>\n import('./ConnectedCallDock').then((m) => ({ default: m.ConnectedCallDock }))\n)\n\n/** One call room, loaded on demand (LiveKit); render it inside `<Suspense>`. */\nexport const ConnectedCallRoom = lazy(() =>\n import('./ConnectedCallRoom').then((m) => ({ default: m.ConnectedCallRoom }))\n)\n\nexport function ConnectedCallLayer(): ReactElement {\n const hasActiveCall = useCallSession((s) => s.active !== null)\n const hasIncomingCall = useCallSession((s) => s.incoming.length > 0)\n const callsEnabled = useCallsEnabled()\n return (\n <>\n {hasActiveCall && (\n <Suspense fallback={null}>\n <ConnectedCallDock />\n </Suspense>\n )}\n {hasIncomingCall && callsEnabled && <ConnectedIncomingCall />}\n </>\n )\n}\n","/**\n * Call button for an open group chat: the group's call (the group is its meeting chat). The\n * members picker opens with everyone ticked; only the people left ticked are rung.\n */\n\nimport {\n useArbi,\n chatLiveCallId,\n useCallSession,\n openCall,\n startChatCall,\n useCanHostCalls,\n type UserResponse,\n} from '@arbidocs/react'\nimport { isAgent } from '@arbidocs/react/ui'\nimport { useState, type ReactElement } from 'react'\nimport { useConnectedWorkspace } from '../../connection/ConnectionProvider'\nimport { StartCallButton } from './StartCallButton'\nimport { CallPeoplePicker } from './CallPeoplePicker'\n\nexport function GroupCallButton({\n chatExtId,\n title,\n members,\n}: {\n chatExtId: string\n title: string | null\n members: UserResponse[]\n}): ReactElement {\n const arbi = useArbi()\n const { userId: me } = useConnectedWorkspace()\n const liveCallId = useCallSession((s) => chatLiveCallId(s, chatExtId))\n const isLive = liveCallId !== null\n const canHost = useCanHostCalls()\n const [picking, setPicking] = useState(false)\n const others = members.filter((u) => u.external_id !== me && !isAgent(u))\n\n return (\n <>\n <StartCallButton\n onStart={async () => {\n // Someone who may not host opens the running call itself (a new create would make them its host).\n if (liveCallId && !canHost) return openCall(arbi, { callExtId: liveCallId })\n if (isLive) return startChatCall(arbi, { chatExtId, title, ring: [] })\n setPicking(true)\n return true\n }}\n isLive={isLive}\n label=\"Call the group\"\n testId=\"group-call-button\"\n />\n {picking && (\n <CallPeoplePicker\n open\n onOpenChange={setPicking}\n scope=\"chat\"\n members={others}\n preselected={others.map((u) => u.external_id)}\n onSubmit={async ({ ring }) => {\n await startChatCall(arbi, { chatExtId, title, ring })\n }}\n />\n )}\n </>\n )\n}\n","/** Call button for an open DM thread: a new call with the peer as context, ringing the peer. */\n\nimport { useArbi, userDisplayName, startDmCall, type UserResponse } from '@arbidocs/react'\nimport type { ReactElement } from 'react'\nimport { StartCallButton } from './StartCallButton'\n\nexport function DmCallButton({ peer }: { peer: UserResponse }): ReactElement {\n const arbi = useArbi()\n const name = userDisplayName(peer)\n return (\n <StartCallButton\n onStart={() =>\n startDmCall(arbi, {\n external_id: peer.external_id,\n encryption_public_key: peer.encryption_public_key ?? null,\n name,\n })\n }\n label={`Call ${name}`}\n testId=\"dm-call-button\"\n />\n )\n}\n","/**\n * \"New call\" — a call with people from my contacts (no thread or chat). Registered contacts are\n * rung; unregistered ones get a personal invite link by e-mail (register, then join). Its meeting chat is made on first\n * use. Renders nothing unless the person may host calls (server + Settings → Experimental + entitlement).\n */\n\nimport { useArbi, useCallSession, useCanHostCalls, startContactsCall } from '@arbidocs/react'\nimport { getUserDisplayName } from '@arbidocs/react/ui'\nimport { useState, type ReactElement } from 'react'\nimport { DmInviteChip } from '../../collaboration/direct-messages/DirectMessages'\nimport { CallPeoplePicker } from './CallPeoplePicker'\nimport { contactsCallTitle } from '../call-cards'\n\nexport function NewCallChip(): ReactElement | null {\n // Gate first so a deployment without calls pays for none of the hooks below.\n return useCanHostCalls() ? <EnabledNewCallChip /> : null\n}\n\nfunction EnabledNewCallChip(): ReactElement {\n const arbi = useArbi()\n const inCall = useCallSession((s) => s.active !== null)\n const [open, setOpen] = useState(false)\n return (\n <>\n <DmInviteChip\n testId=\"dm-new-call-chip\"\n title=\"New call\"\n description={inCall ? 'You are already in a call' : 'Call people from your contacts'}\n onClick={() => !inCall && setOpen(true)}\n />\n {open && (\n <CallPeoplePicker\n open\n onOpenChange={setOpen}\n scope=\"contacts\"\n onSubmit={async ({ ring, invites }) => {\n await startContactsCall(arbi, {\n title: contactsCallTitle([\n ...ring.map((u) => getUserDisplayName(u)),\n ...invites.map((g) => g.name),\n ]),\n ring,\n invites,\n })\n }}\n />\n )}\n </>\n )\n}\n","/**\n * A `kind=call` chat message (the server posts one into the call's chat — a DM, a group or a\n * meeting chat — when a session starts). The newest card of a call shows its state:\n *\n * live: \"Ada started a call\" · Join\n * ended: \"Call · 12 min · joined Ada, Bob\"\n *\n * Older cards of the same call (earlier sessions) stay a plain \"Call\" line. The call is re-read on\n * `call.started` / `call.ended` (see `refreshCallCards`).\n */\n\nimport { useArbi, useCallSession, useCall, openCall } from '@arbidocs/react'\nimport { useState, type ReactElement } from 'react'\nimport { Phone, PhoneOff } from 'lucide-react'\nimport { Button } from '@arbidocs/react/ui'\nimport { formatCallDuration, isCallLive } from '../call-cards'\n\nexport function ChatCallCard({\n callExtId,\n senderName,\n latest,\n name,\n time,\n}: {\n callExtId: string\n /** Who started the session (the card's sender). */\n senderName: string | null\n /** The newest card of this call in the chat. */\n latest: boolean\n /** A member's display name by user ext id. */\n name: (userExtId: string) => string\n time?: string\n}): ReactElement {\n const arbi = useArbi()\n const { data: call } = useCall(latest ? callExtId : null)\n const liveNow = useCallSession((s) => callExtId in s.liveCalls)\n const inThisCall = useCallSession((s) => s.active?.callExtId === callExtId)\n const inAnotherCall = useCallSession((s) => !!s.active && s.active.callExtId !== callExtId)\n const [busy, setBusy] = useState(false)\n const live = latest && isCallLive(call, liveNow)\n\n let summary: string\n if (live) summary = senderName ? `${senderName} started a call` : 'Call in progress'\n else if (latest && call?.started_at && call.ended_at) {\n const seconds = (Date.parse(call.ended_at) - Date.parse(call.started_at)) / 1000\n const joined = (call.last_participants ?? []).map(name)\n summary = [\n 'Call',\n formatCallDuration(seconds),\n joined.length ? `joined ${joined.join(', ')}` : null,\n ]\n .filter(Boolean)\n .join(' · ')\n } else summary = senderName ? `Call started by ${senderName}` : 'Call'\n\n return (\n <div\n className=\"mx-auto my-2 flex w-fit max-w-full flex-wrap items-center justify-center gap-2 rounded-md border border-border bg-card px-3 py-2 text-xs\"\n data-testid=\"chat-call-card\"\n data-live={live || undefined}\n >\n {live ? (\n <Phone className=\"size-4 animate-pulse text-green-text\" aria-hidden />\n ) : (\n <PhoneOff className=\"size-4 text-muted-foreground\" aria-hidden />\n )}\n <span data-testid=\"chat-call-card-summary\">{summary}</span>\n {time && <time className=\"text-muted-foreground\">{time}</time>}\n {live && (\n <Button\n type=\"button\"\n size=\"sm\"\n className=\"h-7 bg-green-600 text-white hover:bg-green-700\"\n disabled={busy || inThisCall || inAnotherCall}\n title={inAnotherCall ? 'You are already in a call' : undefined}\n onClick={() => {\n setBusy(true)\n void openCall(arbi, { callExtId }).finally(() => setBusy(false))\n }}\n data-testid=\"chat-call-card-join\"\n >\n {inThisCall ? 'In call' : 'Join'}\n </Button>\n )}\n </div>\n )\n}\n","/**\n * A chat thread's history with its call: the messenger kit's `ThreadHistory` (blocks\n * `ConnectedChatThread`). A chat with a call (a meeting chat, or a direct or group chat a call was\n * started from) shows its call cards, live transcript, recordings and the speakers talking right\n * now, and filters between everything, the typed chat, the transcript and the recordings. Typed\n * messages are drawn by the kit (`renderItem`).\n */\n\nimport { Fragment, useEffect, useMemo, useState } from 'react'\nimport {\n DateSeparator,\n useArbi,\n type ChatThreadMessage,\n useCall,\n chatTranscriptRef,\n hasRecordingTranscript,\n sortTranscriptMessages,\n supersededTranscriptLines,\n type TranscriptExportLine,\n useRecordingWindows,\n} from '@arbidocs/react'\nimport { chats } from '@arbidocs/sdk/browser'\nimport { ConversationFilter } from '../../chat/TranscriptLine'\nimport { transcriptRuns } from '../../chat/transcript-runs'\nimport type { ChatHistoryProps } from '../../connection/messenger/types'\nimport { usePendingRecording } from '../recording-link'\nimport { ChatCallCard } from './ChatCallCard'\nimport { TranscriptEntry } from './TranscriptEntry'\nimport { CallConversationEmpty, ProvisionalSpeakers } from './CallConversationParts'\nimport { useProvisionalSpeakers } from './provisional-speakers'\nimport { SaveTranscriptToThread } from './SaveTranscriptToThread'\nimport { RecordingCard, RecordingsList } from './RecordingCard'\n\nconst { isTranscriptMessage, parseTranscriptContent } = chats\n\nexport function ConnectedCallChatHistory({\n chat,\n messages,\n items,\n renderItem,\n loadOlder,\n memberById,\n senderName,\n myExtId,\n formatTime,\n formatDay,\n}: ChatHistoryProps) {\n const arbi = useArbi()\n // A call's chat: everything, typed chat only, the transcript only, or the recordings.\n const [view, setView] = useState<'all' | 'chat' | 'transcript' | 'recordings'>('all')\n useEffect(() => setView('all'), [chat?.external_id])\n // A call's chat (meeting, DM or group with a call) lists the call's recordings.\n const recordingsCallExtId = chat?.call_ext_id ?? null\n // A recording link opened this chat: show its recordings.\n const pendingRecording = usePendingRecording()\n useEffect(() => {\n if (pendingRecording && recordingsCallExtId) setView('recordings')\n }, [pendingRecording, recordingsCallExtId])\n\n // The newest call card of each call shows its live / ended state; older ones are a plain line.\n const latestCallCards = useMemo(() => {\n const latest = new Map<string, string>()\n for (const m of messages)\n if (m.kind === 'call' && m.call_ext_id && !m.deleted) latest.set(m.call_ext_id, m.external_id)\n return new Set(latest.values())\n }, [messages])\n\n // A recording's transcript supersedes the live lines spoken while it recorded (else both show).\n const hasRecTranscript = useMemo(\n () => hasRecordingTranscript(messages, chatTranscriptRef),\n [messages]\n )\n const recordingWindows = useRecordingWindows(recordingsCallExtId, hasRecTranscript)\n const supersededTranscript = useMemo(\n () => supersededTranscriptLines(messages, chatTranscriptRef, recordingWindows),\n [messages, recordingWindows]\n )\n const transcriptMessages = useMemo(\n () =>\n sortTranscriptMessages(\n messages.filter((m) => isTranscriptMessage(m) && !m.deleted && !supersededTranscript.has(m))\n ),\n [messages, supersededTranscript]\n )\n const hasTranscript = transcriptMessages.length > 0\n\n // The host can save the decrypted transcript as one comment into a workspace thread.\n const { data: meetingCall } = useCall(hasTranscript ? chat?.call_ext_id : null)\n const isHost = !!meetingCall?.is_creator\n const [meetingTitle, setMeetingTitle] = useState<string | null>(null)\n useEffect(() => {\n if (!chat || (!isHost && !recordingsCallExtId)) return\n let cancelled = false\n arbi.chats\n .title(chat)\n .then((t) => !cancelled && setMeetingTitle(t))\n .catch(() => undefined)\n return () => {\n cancelled = true\n }\n }, [arbi, isHost, chat, recordingsCallExtId])\n\n const transcriptSpeaker = (msg: ChatThreadMessage) => {\n const parsed = msg.decryptFailed ? null : parseTranscriptContent(msg.content)\n return { parsed, speakerId: parsed?.speaker_identity || msg.sender_ext_id || '' }\n }\n const transcriptExport = useMemo<TranscriptExportLine[]>(\n () =>\n transcriptMessages\n .filter((m) => !m.decryptFailed)\n .map((m) => {\n const parsed = parseTranscriptContent(m.content)\n const speakerId = parsed?.speaker_identity || m.sender_ext_id || ''\n return {\n speaker:\n parsed?.speaker_name ||\n (memberById(speakerId) ? senderName(speakerId) : '') ||\n 'Former member',\n at: parsed?.started_at ?? m.created_at,\n text: parsed?.text ?? m.content ?? '',\n }\n }),\n [transcriptMessages, memberById, senderName]\n )\n // Consecutive lines of one speaker are one run (the name once); each speaker's newest line is\n // highlighted while they talk in the call.\n const transcriptLayout = useMemo(() => {\n const shown = view === 'transcript' ? transcriptMessages : messages\n const continued = transcriptRuns(\n shown,\n (m) =>\n isTranscriptMessage(m) && !supersededTranscript.has(m)\n ? transcriptSpeaker(m).speakerId\n : null,\n (m) => Date.parse(transcriptSpeaker(m).parsed?.started_at ?? m.created_at ?? '') || 0\n )\n return { continued }\n }, [view, messages, transcriptMessages, supersededTranscript])\n const transcriptEntry = (msg: ChatThreadMessage) => {\n const { parsed, speakerId } = transcriptSpeaker(msg)\n return (\n <TranscriptEntry\n key={msg.external_id}\n speakerId={speakerId}\n speakerName={\n speakerId === myExtId\n ? 'Me'\n : parsed?.speaker_name ||\n (memberById(speakerId) ? senderName(speakerId) : senderName(msg.sender_ext_id))\n }\n text={parsed?.text ?? msg.content ?? ''}\n at={parsed?.started_at ?? msg.created_at}\n continued={transcriptLayout.continued.has(msg)}\n />\n )\n }\n // While I am in this chat's call: \"<speaker> is speaking…\" until their line arrives.\n const chatLines = useMemo(\n () =>\n transcriptMessages.map((m) => {\n const { parsed, speakerId } = transcriptSpeaker(m)\n return { speakerId, at: Date.parse(parsed?.started_at ?? m.created_at ?? '') || 0 }\n }),\n\n [transcriptMessages]\n )\n const provisionalSpeakers = useProvisionalSpeakers(recordingsCallExtId, chatLines)\n\n const filterOptions = [\n { value: 'all' as const, label: 'All' },\n { value: 'chat' as const, label: 'Chat', testId: 'chat-filter' },\n {\n value: 'transcript' as const,\n label: 'Transcript',\n count: transcriptMessages.length,\n testId: 'transcript-filter',\n },\n ...(recordingsCallExtId\n ? [{ value: 'recordings' as const, label: 'Recordings', testId: 'recordings-filter' }]\n : []),\n ]\n\n return (\n <>\n {messages.length === 0 && recordingsCallExtId && (\n <CallConversationEmpty callExtId={recordingsCallExtId} />\n )}\n {(hasTranscript || recordingsCallExtId) && (\n <div className=\"sticky top-0 z-10 flex justify-center py-1\">\n <ConversationFilter<typeof view>\n value={view}\n options={filterOptions}\n onChange={setView}\n />\n </div>\n )}\n {view === 'recordings' && recordingsCallExtId && (\n <RecordingsList callExtId={recordingsCallExtId} title={meetingTitle} className=\"py-1\" />\n )}\n {loadOlder}\n {view === 'transcript' && (\n <div className=\"flex flex-col py-1\" data-testid=\"transcript-view\">\n {isHost && (\n <SaveTranscriptToThread\n title={meetingTitle}\n lines={transcriptExport}\n className=\"mx-3 mb-2 self-start\"\n />\n )}\n {transcriptMessages.map((msg) => transcriptEntry(msg))}\n <ProvisionalSpeakers ids={provisionalSpeakers} />\n </div>\n )}\n {(view === 'all' || view === 'chat') &&\n items.map((item, i) => {\n const { message: msg, isFirstOfDay } = item\n const deleted = !!msg.deleted\n // A deleted transcript line is not part of the record (it may be stored again).\n if (deleted && isTranscriptMessage(msg)) return null\n const separator = isFirstOfDay && (\n <DateSeparator>{formatDay(msg.created_at)}</DateSeparator>\n )\n if (isTranscriptMessage(msg)) {\n if (view === 'chat') return null\n // A live line superseded by the recording's transcript is not shown.\n const superseded = supersededTranscript.has(msg)\n if (superseded && !isFirstOfDay) return null\n return (\n <Fragment key={msg.external_id}>\n {separator}\n {!superseded && transcriptEntry(msg)}\n </Fragment>\n )\n }\n if (msg.kind === 'recording' && msg.call_ext_id && !deleted) {\n // The server's Recording card (posted when a recording stops).\n return (\n <Fragment key={msg.external_id}>\n {separator}\n <RecordingCard\n callExtId={msg.call_ext_id}\n recordingExtId={msg.recording_ext_id ?? null}\n title={meetingTitle}\n time={formatTime(msg.created_at)}\n />\n </Fragment>\n )\n }\n if (msg.kind === 'call' && msg.call_ext_id && !deleted) {\n return (\n <Fragment key={msg.external_id}>\n {separator}\n <ChatCallCard\n callExtId={msg.call_ext_id}\n senderName={msg.sender_ext_id ? senderName(msg.sender_ext_id) : null}\n latest={latestCallCards.has(msg.external_id)}\n name={senderName}\n time={formatTime(msg.created_at)}\n />\n </Fragment>\n )\n }\n return renderItem(item, i)\n })}\n {view === 'all' && <ProvisionalSpeakers ids={provisionalSpeakers} />}\n </>\n )\n}\n","import { useEffect, useMemo, useRef, useState, type ReactNode } from 'react'\nimport { Lock, LogIn, UserPlus } from 'lucide-react'\nimport { parseCallFragment } from '@arbidocs/client'\nimport { Button } from '@arbidocs/react/ui'\nimport { openCall, useArbi } from '@arbidocs/react'\nimport { CallsExperimentalBadge } from '../CallsExperimentalBadge'\n\n/** A personal invite token (`?i=`). */\nconst INVITE_TOKEN_RE = /^[A-Za-z0-9_-]{8,256}$/\n\nfunction Shell({ children }: { children: ReactNode }) {\n return (\n <main className=\"flex min-h-screen items-center justify-center bg-background p-4 text-foreground\">\n <section\n className=\"w-full max-w-md rounded-lg border border-border bg-card p-6 shadow-sm\"\n data-testid=\"call-page\"\n >\n {children}\n </section>\n </main>\n )\n}\n\nfunction ErrorCard({ message, action }: { message: string; action?: ReactNode }) {\n return (\n <Shell>\n <p role=\"alert\" className=\"mb-4 text-sm text-destructive\" data-testid=\"call-page-error\">\n {message}\n </p>\n {action}\n </Shell>\n )\n}\n\nfunction MemberJoin({\n callId,\n callKey,\n linkVersion,\n inviteToken,\n onReturnToApp,\n loading,\n appName,\n}: {\n callId: string\n callKey: Uint8Array | null\n linkVersion: number | null\n inviteToken: string | null\n onReturnToApp: () => void\n loading: ReactNode\n appName: string\n}) {\n const arbi = useArbi()\n const [failed, setFailed] = useState(false)\n const [attempt, setAttempt] = useState(0)\n const started = useRef<string | null>(null)\n\n useEffect(() => {\n // StrictMode / re-renders must not open the call twice for one attempt.\n const id = `${callId}#${attempt}`\n if (started.current === id) return\n started.current = id\n void openCall(arbi, { callExtId: callId, key: callKey, linkVersion, inviteToken }).then(\n (ok) => {\n // The pre-join and the call live in the app's call dock: hand over to the app\n // (replace, so the key in the fragment does not linger in history).\n if (ok) onReturnToApp()\n else setFailed(true)\n }\n )\n }, [arbi, callId, callKey, linkVersion, inviteToken, attempt, onReturnToApp])\n\n if (!failed) return loading\n return (\n <ErrorCard\n message=\"Could not open this call. The link may be incomplete or no longer valid.\"\n action={\n <div className=\"flex gap-2\">\n <Button\n onClick={() => {\n setFailed(false)\n setAttempt((n) => n + 1)\n }}\n data-testid=\"call-page-retry\"\n >\n Try again\n </Button>\n <Button variant=\"outline\" onClick={onReturnToApp}>\n {`Go to ${appName}`}\n </Button>\n </div>\n }\n />\n )\n}\n\n/** Signed out: only \"Sign in / Create account\", coming back to this exact link after. */\nfunction SignedOut({\n hasKey,\n returnUrl,\n onAuthenticate,\n appName,\n}: {\n hasKey: boolean\n returnUrl: string\n onAuthenticate: ConnectedCallPageProps['onAuthenticate']\n appName: string\n}) {\n const go = (register: boolean) => onAuthenticate({ register, returnUrl })\n if (!hasKey) return <ErrorCard message=\"This call link is incomplete: it is missing its key.\" />\n return (\n <Shell>\n <div className=\"mb-5 flex items-center gap-2\">\n <h1 className=\"text-lg font-semibold\" data-testid=\"call-page-title\">\n Join the call\n </h1>\n <CallsExperimentalBadge />\n </div>\n <p className=\"mb-4 text-sm text-muted-foreground\">\n {`Sign in to your ${appName} account to join, or create one — it takes a minute.`}\n </p>\n <div className=\"flex flex-col gap-2\">\n <Button type=\"button\" onClick={() => go(false)} data-testid=\"call-sign-in\">\n <LogIn className=\"mr-1.5 size-4\" />\n Sign in\n </Button>\n <Button\n type=\"button\"\n variant=\"outline\"\n onClick={() => go(true)}\n data-testid=\"call-create-account\"\n >\n <UserPlus className=\"mr-1.5 size-4\" />\n Create account\n </Button>\n <p className=\"mt-1 flex items-center gap-1.5 text-xs text-muted-foreground\">\n <Lock className=\"size-3\" aria-hidden />\n Audio and video are end-to-end encrypted.\n </p>\n </div>\n </Shell>\n )\n}\n\n/** `?register=1`: straight to registration, coming back to the call (with its key) after. */\nfunction RegisterFirst({\n pathname,\n hash,\n search,\n onAuthenticate,\n loading,\n}: {\n pathname: string\n hash: string\n search: string\n onAuthenticate: ConnectedCallPageProps['onAuthenticate']\n loading: ReactNode\n}) {\n useEffect(() => {\n const params = new URLSearchParams(search)\n params.delete('register')\n const query = params.toString()\n onAuthenticate({\n register: true,\n replace: true,\n returnUrl: `${pathname}${query ? `?${query}` : ''}${hash}`,\n })\n }, [pathname, hash, search, onAuthenticate])\n return loading\n}\n\nexport interface ConnectedCallPageProps {\n callId: string\n /** The current host URL, including the private call key in its fragment. */\n location: { pathname: string; search: string; hash: string }\n authenticated: boolean\n /** Save the supplied return URL locally, then open the host sign-in/registration route. */\n onAuthenticate: (request: { register: boolean; returnUrl: string; replace?: boolean }) => void\n /** Replace the call link with the host app once its call dock has accepted it. */\n onReturnToApp: () => void\n appName?: string\n loading?: ReactNode\n}\n\n/** The shared call-link entry. Routing, session ownership and return-URL storage stay with the host. */\nexport function ConnectedCallPage({\n callId,\n location: { pathname, hash, search },\n authenticated,\n onAuthenticate,\n onReturnToApp,\n appName = 'app',\n loading = <div role=\"status\">Loading…</div>,\n}: ConnectedCallPageProps) {\n const fragment = useMemo(() => parseCallFragment(hash), [hash])\n const params = useMemo(() => new URLSearchParams(search), [search])\n const rawInvite = params.get('i')\n const inviteToken = rawInvite && INVITE_TOKEN_RE.test(rawInvite) ? rawInvite : null\n if (authenticated) {\n return (\n <MemberJoin\n callId={callId}\n callKey={fragment?.key ?? null}\n linkVersion={fragment?.linkVersion ?? null}\n inviteToken={inviteToken}\n onReturnToApp={onReturnToApp}\n loading={loading}\n appName={appName}\n />\n )\n }\n if (params.get('register') === '1') {\n return (\n <RegisterFirst\n pathname={pathname}\n hash={hash}\n search={search}\n onAuthenticate={onAuthenticate}\n loading={loading}\n />\n )\n }\n return (\n <SignedOut\n hasKey={!!fragment}\n returnUrl={`${pathname}${search}${hash}`}\n onAuthenticate={onAuthenticate}\n appName={appName}\n />\n )\n}\n"]}
@@ -1,7 +1,7 @@
1
1
  "use client";
2
2
  import { StartCallButton, CallPeoplePicker, useProvisionalSpeakers, CallConversationEmpty, RecordingsList, SaveTranscriptToThread, ProvisionalSpeakers, RecordingCard, TranscriptEntry } from '../chunk-IDFAMK2G.js';
3
3
  export { CallConversationEmpty, CallPeoplePicker, ConnectedConversationCallActions, MeetingThreadRecordingsAction, MeetingThreadTranscriptAction, PickThreadDialog, ProvisionalSpeakers, RecordingCard, RecordingsList, SaveTranscriptToThread, ScheduleCallButton, StartCallButton, ThreadCallButton, ThreadCallLogCard, TranscriptEntry, TranscriptRunsContext, buildCallCandidates, callContactOf, isPickable, matchesQuery, threadTranscriptRuns, useCallPersonName, useProvisionalSpeakers, useTranscriptRuns } from '../chunk-IDFAMK2G.js';
4
- import { useRingtoneMuted, useRingtone, IncomingCallCard, CallUserPill, contactsCallTitle, isCallLive, formatCallDuration, usePendingRecording } from '../chunk-6GI3S7TN.js';
4
+ import { useRingtoneMuted, useRingtone, IncomingCallCard, CallUserPill, contactsCallTitle, isCallLive, formatCallDuration, usePendingRecording, CallsExperimentalBadge } from '../chunk-6GI3S7TN.js';
5
5
  export { BackstageBanner, CHAT_ID_PATTERN, COMPOSITE_FPS, COMPOSITE_MAX_HEIGHT, COMPOSITE_MAX_WIDTH, CallControlBar, CallControlButton, CallFocus, CallGrid, CallHeader, CallNotice, CallParticipants, CallPersonLabel, CallSidePanel, CallStageFrame, CallStateMessage, CallStatusChip, CallTile, CallUserPill, CallsExperimentalBadge, CaptionsStrip, ChatPermissionSetting, ConnectionOverlay, ControlBadge, ControlDivider, ControlGroup, EXPIRY_DAYS, ElapsedTime, EncryptionStatusChip, HeaderAction, IncomingCallCard, LEVEL_TICK_MS, LeaveButton, LobbyRequests, MIRROR_SELF_VIEW_KEY, MODE_LABEL, MediaControl, MinimisedCall, MoreMenu, OnStageCheck, PanelComposer, PreJoin, QAPanel, RECORDING_ID_PATTERN, RINGTONE_MUTED_KEY, RaiseHandButton, RecordControl, RecordingStatusChip, SpeakingNow, TranscriptionStatusChip, VoiceMeter, WebinarAudiencePanel, WebinarEndConfirm, WebinarLiveChip, WebinarLiveControl, WebinarViewer, WebinarWaiting, chatPermissionSection, contactsCallTitle, describeMediaError, drawStageFrame, expiryChoiceOf, expiryFor, fitMedia, fitStage, formatCallDuration, getPendingRecording, isCallLive, parseCallLogDetail, parseRecordingLinkParams, publishCallStatus, recordingLink, setMirrorSelfView, setPendingRecording, sortQuestions, startCompositeCapture, startRingtone, startVoiceLevels, useBriefNotice, useElementSize, useIsSpeaking, useMirrorSelfView, useMyCallStatus, usePendingRecording, useRingtone, useRingtoneMuted, useShortcutKeys, useSpeakingIds, useSpotlightId, useVoiceLevel, useVoiceLevels } from '../chunk-6GI3S7TN.js';
6
6
  import '../chunk-5RYZUX5L.js';
7
7
  import { useConnectedWorkspace } from '../chunk-A7MWHMHP.js';
@@ -18,12 +18,13 @@ import '../chunk-3VCTVCAX.js';
18
18
  import '../chunk-TX2ZICS7.js';
19
19
  import '../chunk-7F6CBP3Z.js';
20
20
  import '../chunk-VUNV25KB.js';
21
- import { lazy, useState, Suspense, useEffect, useMemo, Fragment as Fragment$1 } from 'react';
21
+ import { lazy, useState, Suspense, useEffect, useMemo, Fragment as Fragment$1, useRef } from 'react';
22
22
  import { useArbi, useCallSession, declineRing, useCallsEnabled, chatLiveCallId, useCanHostCalls, openCall, startChatCall, userDisplayName, startDmCall, startContactsCall, useCall, hasRecordingTranscript, chatTranscriptRef, useRecordingWindows, supersededTranscriptLines, sortTranscriptMessages, DateSeparator, acceptRing, callSession } from '@arbidocs/react';
23
23
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
24
24
  import { isAgent, getUserDisplayName, Button } from '@arbidocs/react/ui';
25
- import { Phone, PhoneOff } from 'lucide-react';
25
+ import { Phone, PhoneOff, LogIn, UserPlus, Lock } from 'lucide-react';
26
26
  import { chats } from '@arbidocs/sdk/browser';
27
+ import { parseCallFragment } from '@arbidocs/client';
27
28
 
28
29
  var RING_TIMEOUT_MS = 3e4;
29
30
  function useRingTimeout(ring) {
@@ -412,7 +413,177 @@ function ConnectedCallChatHistory({
412
413
  view === "all" && /* @__PURE__ */ jsx(ProvisionalSpeakers, { ids: provisionalSpeakers })
413
414
  ] });
414
415
  }
416
+ var INVITE_TOKEN_RE = /^[A-Za-z0-9_-]{8,256}$/;
417
+ function Shell({ children }) {
418
+ return /* @__PURE__ */ jsx("main", { className: "flex min-h-screen items-center justify-center bg-background p-4 text-foreground", children: /* @__PURE__ */ jsx(
419
+ "section",
420
+ {
421
+ className: "w-full max-w-md rounded-lg border border-border bg-card p-6 shadow-sm",
422
+ "data-testid": "call-page",
423
+ children
424
+ }
425
+ ) });
426
+ }
427
+ function ErrorCard({ message, action }) {
428
+ return /* @__PURE__ */ jsxs(Shell, { children: [
429
+ /* @__PURE__ */ jsx("p", { role: "alert", className: "mb-4 text-sm text-destructive", "data-testid": "call-page-error", children: message }),
430
+ action
431
+ ] });
432
+ }
433
+ function MemberJoin({
434
+ callId,
435
+ callKey,
436
+ linkVersion,
437
+ inviteToken,
438
+ onReturnToApp,
439
+ loading,
440
+ appName
441
+ }) {
442
+ const arbi = useArbi();
443
+ const [failed, setFailed] = useState(false);
444
+ const [attempt, setAttempt] = useState(0);
445
+ const started = useRef(null);
446
+ useEffect(() => {
447
+ const id = `${callId}#${attempt}`;
448
+ if (started.current === id) return;
449
+ started.current = id;
450
+ void openCall(arbi, { callExtId: callId, key: callKey, linkVersion, inviteToken }).then(
451
+ (ok) => {
452
+ if (ok) onReturnToApp();
453
+ else setFailed(true);
454
+ }
455
+ );
456
+ }, [arbi, callId, callKey, linkVersion, inviteToken, attempt, onReturnToApp]);
457
+ if (!failed) return loading;
458
+ return /* @__PURE__ */ jsx(
459
+ ErrorCard,
460
+ {
461
+ message: "Could not open this call. The link may be incomplete or no longer valid.",
462
+ action: /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
463
+ /* @__PURE__ */ jsx(
464
+ Button,
465
+ {
466
+ onClick: () => {
467
+ setFailed(false);
468
+ setAttempt((n) => n + 1);
469
+ },
470
+ "data-testid": "call-page-retry",
471
+ children: "Try again"
472
+ }
473
+ ),
474
+ /* @__PURE__ */ jsx(Button, { variant: "outline", onClick: onReturnToApp, children: `Go to ${appName}` })
475
+ ] })
476
+ }
477
+ );
478
+ }
479
+ function SignedOut({
480
+ hasKey,
481
+ returnUrl,
482
+ onAuthenticate,
483
+ appName
484
+ }) {
485
+ const go = (register) => onAuthenticate({ register, returnUrl });
486
+ if (!hasKey) return /* @__PURE__ */ jsx(ErrorCard, { message: "This call link is incomplete: it is missing its key." });
487
+ return /* @__PURE__ */ jsxs(Shell, { children: [
488
+ /* @__PURE__ */ jsxs("div", { className: "mb-5 flex items-center gap-2", children: [
489
+ /* @__PURE__ */ jsx("h1", { className: "text-lg font-semibold", "data-testid": "call-page-title", children: "Join the call" }),
490
+ /* @__PURE__ */ jsx(CallsExperimentalBadge, {})
491
+ ] }),
492
+ /* @__PURE__ */ jsx("p", { className: "mb-4 text-sm text-muted-foreground", children: `Sign in to your ${appName} account to join, or create one \u2014 it takes a minute.` }),
493
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
494
+ /* @__PURE__ */ jsxs(Button, { type: "button", onClick: () => go(false), "data-testid": "call-sign-in", children: [
495
+ /* @__PURE__ */ jsx(LogIn, { className: "mr-1.5 size-4" }),
496
+ "Sign in"
497
+ ] }),
498
+ /* @__PURE__ */ jsxs(
499
+ Button,
500
+ {
501
+ type: "button",
502
+ variant: "outline",
503
+ onClick: () => go(true),
504
+ "data-testid": "call-create-account",
505
+ children: [
506
+ /* @__PURE__ */ jsx(UserPlus, { className: "mr-1.5 size-4" }),
507
+ "Create account"
508
+ ]
509
+ }
510
+ ),
511
+ /* @__PURE__ */ jsxs("p", { className: "mt-1 flex items-center gap-1.5 text-xs text-muted-foreground", children: [
512
+ /* @__PURE__ */ jsx(Lock, { className: "size-3", "aria-hidden": true }),
513
+ "Audio and video are end-to-end encrypted."
514
+ ] })
515
+ ] })
516
+ ] });
517
+ }
518
+ function RegisterFirst({
519
+ pathname,
520
+ hash,
521
+ search,
522
+ onAuthenticate,
523
+ loading
524
+ }) {
525
+ useEffect(() => {
526
+ const params = new URLSearchParams(search);
527
+ params.delete("register");
528
+ const query = params.toString();
529
+ onAuthenticate({
530
+ register: true,
531
+ replace: true,
532
+ returnUrl: `${pathname}${query ? `?${query}` : ""}${hash}`
533
+ });
534
+ }, [pathname, hash, search, onAuthenticate]);
535
+ return loading;
536
+ }
537
+ function ConnectedCallPage({
538
+ callId,
539
+ location: { pathname, hash, search },
540
+ authenticated,
541
+ onAuthenticate,
542
+ onReturnToApp,
543
+ appName = "app",
544
+ loading = /* @__PURE__ */ jsx("div", { role: "status", children: "Loading\u2026" })
545
+ }) {
546
+ const fragment = useMemo(() => parseCallFragment(hash), [hash]);
547
+ const params = useMemo(() => new URLSearchParams(search), [search]);
548
+ const rawInvite = params.get("i");
549
+ const inviteToken = rawInvite && INVITE_TOKEN_RE.test(rawInvite) ? rawInvite : null;
550
+ if (authenticated) {
551
+ return /* @__PURE__ */ jsx(
552
+ MemberJoin,
553
+ {
554
+ callId,
555
+ callKey: fragment?.key ?? null,
556
+ linkVersion: fragment?.linkVersion ?? null,
557
+ inviteToken,
558
+ onReturnToApp,
559
+ loading,
560
+ appName
561
+ }
562
+ );
563
+ }
564
+ if (params.get("register") === "1") {
565
+ return /* @__PURE__ */ jsx(
566
+ RegisterFirst,
567
+ {
568
+ pathname,
569
+ hash,
570
+ search,
571
+ onAuthenticate,
572
+ loading
573
+ }
574
+ );
575
+ }
576
+ return /* @__PURE__ */ jsx(
577
+ SignedOut,
578
+ {
579
+ hasKey: !!fragment,
580
+ returnUrl: `${pathname}${search}${hash}`,
581
+ onAuthenticate,
582
+ appName
583
+ }
584
+ );
585
+ }
415
586
 
416
- export { ChatCallCard, ConnectedCallChatHistory, ConnectedCallDock, ConnectedCallLayer, ConnectedCallRoom, ConnectedIncomingCall, DmCallButton, GroupCallButton, NewCallChip, RING_TIMEOUT_MS };
587
+ export { ChatCallCard, ConnectedCallChatHistory, ConnectedCallDock, ConnectedCallLayer, ConnectedCallPage, ConnectedCallRoom, ConnectedIncomingCall, DmCallButton, GroupCallButton, NewCallChip, RING_TIMEOUT_MS };
417
588
  //# sourceMappingURL=index.js.map
418
589
  //# sourceMappingURL=index.js.map