@ai-matrx/meet 0.11.50 → 0.11.51

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.
@@ -1190,6 +1190,22 @@ async function setGuestRecordAccess(args) {
1190
1190
  };
1191
1191
  }
1192
1192
 
1193
+ // src/core/captions-state.ts
1194
+ var CAPTIONS_TIMEOUT_REASON = "Captions are unavailable right now.";
1195
+ function resolveCaptionsState(i) {
1196
+ if (!i.on) return { state: "off", reason: null, remedy: null };
1197
+ if (i.takerState === "transcribing" && i.takerPresent) return { state: "live", reason: null, remedy: null };
1198
+ if (i.takerState === "joining" && !i.timedOut) return { state: "starting", reason: null, remedy: null };
1199
+ if (i.refusal !== null && i.refusal.reason.length > 0) {
1200
+ return { state: "unavailable", reason: i.refusal.reason, remedy: i.refusal.remedy.length > 0 ? i.refusal.remedy : null };
1201
+ }
1202
+ if (i.takerState === "ended" || i.takerState === "handoff_pending") {
1203
+ return { state: "unavailable", reason: i.takerLabel, remedy: null };
1204
+ }
1205
+ if (i.timedOut) return { state: "unavailable", reason: CAPTIONS_TIMEOUT_REASON, remedy: null };
1206
+ return { state: "starting", reason: null, remedy: null };
1207
+ }
1208
+
1193
1209
  // src/react/hooks.ts
1194
1210
  var EMPTY_NAMES = {};
1195
1211
  var NO_RUNTIME_REMEDY = "Render this inside a <MeetProvider> that has a Supabase client, an organization id and an identity (userId or guestName). The provider stays inert until all three are real, and while it is inert this package's components render nothing rather than a dead control.";
@@ -1234,7 +1250,8 @@ function useRoom() {
1234
1250
  local,
1235
1251
  // An observer (role `viewer`) publishes nothing: no Share screen to press and be refused (MD-16).
1236
1252
  sharingAllowed: snapshot === null || canShareUnder(snapshot.livePolicy, effectiveRole(snapshot), effectiveStanding(snapshot)),
1237
- canShareScreen: (engine?.supportsScreenShare() ?? true) && !isObserverRole(snapshot?.grants.role ?? null) && (snapshot === null || canShareUnder(snapshot.livePolicy, effectiveRole(snapshot), effectiveStanding(snapshot))),
1253
+ canShareScreen: (engine?.supportsScreenShare() ?? true) && !isObserverRole(snapshot?.grants.role ?? null) && // The server's word that sharing was taken away arrives before the rules refresh does: the control goes at once.
1254
+ !(snapshot?.share.state === "ended" && snapshot.share.reason === "not_allowed") && (snapshot === null || canShareUnder(snapshot.livePolicy, effectiveRole(snapshot), effectiveStanding(snapshot))),
1238
1255
  otherPresenter: otherPresenterOf(snapshot),
1239
1256
  join: useCallback2(
1240
1257
  async (request) => requireEngine(engine, "join").join(request),
@@ -1578,32 +1595,37 @@ function useCaptions() {
1578
1595
  if (host === null || meeting === null) return;
1579
1596
  void host.ai.requestCaptions({ meetingId: meeting.id });
1580
1597
  }, [host, meeting]);
1598
+ const [timedOut, setTimedOut] = useState3(false);
1599
+ const timeoutSeconds = snapshot?.captionsStartTimeoutSeconds ?? 20;
1600
+ const live = taker.state === "transcribing" && taker.present;
1601
+ const [attempt, setAttempt] = useState3(0);
1602
+ useEffect3(() => {
1603
+ setTimedOut(false);
1604
+ if (!on || live) return void 0;
1605
+ const id = setTimeout(() => setTimedOut(true), timeoutSeconds * 1e3);
1606
+ return () => clearTimeout(id);
1607
+ }, [on, live, timeoutSeconds, attempt]);
1581
1608
  const toggle = useCallback2(() => {
1582
1609
  if (host === null) return;
1583
1610
  const next = !on;
1584
1611
  host.store.patch({ captionsOn: next, captionsRefusal: null });
1585
1612
  if (next && taker.state !== "joining" && taker.state !== "transcribing") request();
1586
1613
  }, [host, on, taker.state, request]);
1587
- let state = "off";
1588
- let reason = null;
1589
- let remedy = null;
1590
- if (on) {
1591
- if (taker.state === "transcribing" && taker.present) {
1592
- state = "live";
1593
- } else if (taker.state === "joining") {
1594
- state = "starting";
1595
- } else if (refusal !== null && refusal.reason.length > 0) {
1596
- state = "unavailable";
1597
- reason = refusal.reason;
1598
- remedy = refusal.remedy.length > 0 ? refusal.remedy : null;
1599
- } else if (taker.state === "ended" || taker.state === "handoff_pending") {
1600
- state = "unavailable";
1601
- reason = noteTakerLabel(taker);
1602
- } else {
1603
- state = "starting";
1604
- }
1605
- }
1606
- return { on, state, reason, remedy, toggle };
1614
+ const retry = useCallback2(() => {
1615
+ if (host === null) return;
1616
+ host.store.patch({ captionsOn: true, captionsRefusal: null });
1617
+ setAttempt((n) => n + 1);
1618
+ request();
1619
+ }, [host, request]);
1620
+ const view = resolveCaptionsState({
1621
+ on,
1622
+ takerState: taker.state,
1623
+ takerPresent: taker.present,
1624
+ refusal,
1625
+ takerLabel: on ? noteTakerLabel(taker) : "",
1626
+ timedOut
1627
+ });
1628
+ return { on, state: view.state, reason: view.reason, remedy: view.remedy, toggle, retry };
1607
1629
  }
1608
1630
  function useEndMeeting() {
1609
1631
  const host = useMeetHost();
@@ -5362,11 +5384,14 @@ function Captions({ lines = 3 }) {
5362
5384
  const captions = useCaptions();
5363
5385
  if (!captions.on) return null;
5364
5386
  if (captions.state === "unavailable") {
5365
- return /* @__PURE__ */ jsx6("div", { className: "mx-meet__captions", role: "status", "data-meet-notice": "captions-unavailable", children: /* @__PURE__ */ jsxs4("p", { className: "mx-meet__caption", children: [
5366
- "Captions are unavailable. ",
5367
- captions.reason,
5368
- captions.remedy !== null ? ` ${captions.remedy}` : ""
5369
- ] }) });
5387
+ return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__captions", role: "status", "data-meet-notice": "captions-unavailable", children: [
5388
+ /* @__PURE__ */ jsxs4("p", { className: "mx-meet__caption", children: [
5389
+ (captions.reason ?? "").startsWith("Captions are unavailable") ? "" : "Captions are unavailable. ",
5390
+ captions.reason,
5391
+ captions.remedy !== null ? ` ${captions.remedy}` : ""
5392
+ ] }),
5393
+ /* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__caption-retry", onClick: captions.retry, children: "Try again" })
5394
+ ] });
5370
5395
  }
5371
5396
  if (visible.length === 0) {
5372
5397
  return /* @__PURE__ */ jsx6("div", { className: "mx-meet__captions", "aria-live": "polite", "aria-label": "Live captions", "data-meet-caption": captions.state, children: /* @__PURE__ */ jsx6("p", { className: "mx-meet__caption mx-meet__caption--interim", children: captions.state === "starting" ? "Starting captions. They appear as people speak." : "Captions are on. They appear as people speak." }) });