@ai-matrx/meet 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -289,7 +289,17 @@ var MEET_ROUTES = {
289
289
  */
290
290
  collab: "/api/v1/meet/collab",
291
291
  /** Meet wave 5: translate finished caption lines into this viewer's language. */
292
- captionsTranslate: "/api/v1/meet/captions/translate"
292
+ captionsTranslate: "/api/v1/meet/captions/translate",
293
+ /**
294
+ * S4 — THE STATE READ (CORE-DESIGN §2.6): `GET ?meeting_id=` with `x-meet-pass`. This
295
+ * person's admission (lazy expiry applied), whether anyone who can admit is here, the run's
296
+ * phase. Read every `waiting_poll_seconds` while waiting and on every `mx.state.changed`.
297
+ */
298
+ state: "/api/v1/meet/state",
299
+ /** S4: `withdraw` (stop waiting) or `leave` (close this tab); the pass may ride in the body. */
300
+ leave: "/api/v1/meet/leave",
301
+ /** S4: a pass holder (guests included) saw the recording notice, for this run. */
302
+ consent: "/api/v1/meet/consent"
293
303
  };
294
304
 
295
305
  // src/core/recording.ts
@@ -471,7 +481,7 @@ function observedPhase(input) {
471
481
  case "left":
472
482
  return "prejoin";
473
483
  case "lobby":
474
- return "waiting:knocking";
484
+ return waitingPhase(snapshot);
475
485
  case "requesting-token":
476
486
  case "connecting":
477
487
  return "joining";
@@ -480,6 +490,24 @@ function observedPhase(input) {
480
490
  return "in_call";
481
491
  }
482
492
  }
493
+ function waitingPhase(snapshot) {
494
+ switch (snapshot.waiting?.admission) {
495
+ case "waiting_host":
496
+ return "waiting:host_not_started";
497
+ case "denied":
498
+ return "denied";
499
+ case "expired":
500
+ return "knock_expired";
501
+ case "withdrawn":
502
+ return "left";
503
+ case "ended":
504
+ return "ended";
505
+ case "removed":
506
+ return "refused:removed";
507
+ default:
508
+ return "waiting:knocking";
509
+ }
510
+ }
483
511
  var ADMITTER_ROLES = /* @__PURE__ */ new Set(["host", "cohost"]);
484
512
  function observe(input) {
485
513
  const { snapshot } = input;
@@ -494,7 +522,7 @@ function observe(input) {
494
522
  reason: phase.startsWith("refused:") ? phase.slice("refused:".length) : null,
495
523
  role,
496
524
  connection: snapshot?.phase === "reconnecting" ? "reconnecting" : "stable",
497
- hostPresent: inCall && snapshot !== null ? snapshot.participants.some((p) => ADMITTER_ROLES.has(p.role)) : null,
525
+ hostPresent: inCall && snapshot !== null ? snapshot.participants.some((p) => ADMITTER_ROLES.has(p.role)) : snapshot?.phase === "lobby" ? snapshot.waiting?.admittersPresent ?? null : null,
498
526
  lobbyCount: canAdmit && snapshot !== null ? snapshot.lobby.filter((entry) => entry.state === "knocking").length : 0,
499
527
  recording: snapshot?.recording === "recording" || snapshot?.recording === "stopping",
500
528
  audioBlocked: null,
@@ -1027,12 +1055,22 @@ function useLobby() {
1027
1055
  async () => requireSession(session, "admitAll").admitAll(),
1028
1056
  [session]
1029
1057
  ),
1030
- knock: (0, import_react4.useCallback)(
1031
- (roomName) => requireSession(session, "knock").knock(roomName),
1058
+ undeny: (0, import_react4.useCallback)(
1059
+ async (entry) => requireSession(session, "undeny").undeny(entry),
1032
1060
  [session]
1033
1061
  )
1034
1062
  };
1035
1063
  }
1064
+ function useWaiting() {
1065
+ const host = useMeetHost();
1066
+ const snapshot = useMeetSnapshot();
1067
+ const session = host?.meetings ?? null;
1068
+ return {
1069
+ waiting: snapshot?.waiting ?? null,
1070
+ withdraw: (0, import_react4.useCallback)(async () => requireSession(session, "withdraw").withdraw(), [session]),
1071
+ askAgain: (0, import_react4.useCallback)(async () => requireSession(session, "askAgain").askAgain(), [session])
1072
+ };
1073
+ }
1036
1074
  function useRecording() {
1037
1075
  const host = useMeetHost();
1038
1076
  const snapshot = useMeetSnapshot();
@@ -4519,7 +4557,7 @@ function MeetSkinRoom({
4519
4557
  ) });
4520
4558
  }
4521
4559
  if (phase === "lobby") {
4522
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mx-meet mx-meet--lobby", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(WaitingRoom, { roomName, host }) });
4560
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mx-meet mx-meet--lobby", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(WaitingRoom, { host, ...onLeave !== void 0 ? { onLeave } : {} }) });
4523
4561
  }
4524
4562
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet", children: [
4525
4563
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ConsentNotice, {}),
@@ -4544,21 +4582,58 @@ function MeetSkinRoom({
4544
4582
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ControlBar, { ...onLeave !== void 0 ? { onLeave } : {} })
4545
4583
  ] });
4546
4584
  }
4547
- function WaitingRoom({ roomName, host }) {
4548
- const knocked = (0, import_react9.useRef)(false);
4549
- (0, import_react9.useEffect)(() => {
4550
- if (knocked.current) return;
4551
- knocked.current = true;
4552
- host.meetings.knock(roomName);
4553
- }, [host, roomName]);
4585
+ function WaitingRoom({ host, onLeave }) {
4586
+ const { waiting, withdraw, askAgain } = useWaiting();
4587
+ const [busy, setBusy] = (0, import_react9.useState)(false);
4588
+ const admission = waiting?.admission ?? "knocking";
4589
+ const run = (action) => () => {
4590
+ setBusy(true);
4591
+ void action().catch(() => void 0).finally(() => setBusy(false));
4592
+ };
4593
+ const home = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system.Button, { type: "button", variant: "outline", onClick: () => onLeave !== void 0 ? onLeave() : window.location.assign("/"), children: "Back to home" });
4594
+ let title;
4595
+ let line = null;
4596
+ let actions;
4597
+ switch (admission) {
4598
+ case "waiting_host":
4599
+ title = "Waiting for the host to start";
4600
+ actions = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system.Button, { type: "button", variant: "outline", disabled: busy, onClick: run(withdraw), children: "Leave" });
4601
+ break;
4602
+ case "denied":
4603
+ title = "The host declined your request";
4604
+ actions = /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
4605
+ waiting?.reknockAllowed === true ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system.Button, { type: "button", disabled: busy, onClick: run(askAgain), children: "Ask to join again" }) : null,
4606
+ home
4607
+ ] });
4608
+ break;
4609
+ case "expired":
4610
+ title = "No one responded";
4611
+ actions = /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
4612
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system.Button, { type: "button", disabled: busy, onClick: run(askAgain), children: "Ask again" }),
4613
+ home
4614
+ ] });
4615
+ break;
4616
+ case "withdrawn":
4617
+ title = "You left the waiting room";
4618
+ actions = /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
4619
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system.Button, { type: "button", disabled: busy, onClick: run(askAgain), children: "Rejoin" }),
4620
+ home
4621
+ ] });
4622
+ break;
4623
+ case "ended":
4624
+ title = "The meeting has ended";
4625
+ actions = home;
4626
+ break;
4627
+ default:
4628
+ title = "Waiting for the host to let you in";
4629
+ line = waiting?.admittersPresent === false ? "The host isn't here yet" : null;
4630
+ actions = /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_design_system.Button, { type: "button", variant: "outline", disabled: busy, onClick: run(withdraw), children: "Cancel request" });
4631
+ }
4554
4632
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet__waiting", children: [
4555
4633
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Avatar, { name: host.identity.displayName, url: host.identity.avatarUrl, size: 72 }),
4556
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h1", { className: "mx-meet__prejoin-title", children: "Waiting for the host to let you in" }),
4557
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { className: "mx-meet__empty-body", children: [
4558
- "You are in the waiting room as ",
4559
- host.identity.displayName,
4560
- ". You will join automatically once you are admitted."
4561
- ] })
4634
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h1", { className: "mx-meet__prejoin-title", children: title }),
4635
+ line !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__empty-body", role: "status", "data-meet-notice": "host-absent", children: line }) : null,
4636
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mx-meet__waiting-actions", children: actions })
4562
4637
  ] });
4563
4638
  }
4564
4639
  function HostMenu() {