@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.
package/dist/react.d.cts CHANGED
@@ -341,6 +341,8 @@ interface UseCaptionsResult {
341
341
  readonly reason: string | null;
342
342
  readonly remedy: string | null;
343
343
  readonly toggle: () => void;
344
+ /** Try again after `unavailable`: asks for captions afresh and restarts the start ceiling. */
345
+ readonly retry: () => void;
344
346
  }
345
347
  declare function useCaptions(): UseCaptionsResult;
346
348
  /**
package/dist/react.d.ts CHANGED
@@ -341,6 +341,8 @@ interface UseCaptionsResult {
341
341
  readonly reason: string | null;
342
342
  readonly remedy: string | null;
343
343
  readonly toggle: () => void;
344
+ /** Try again after `unavailable`: asks for captions afresh and restarts the start ceiling. */
345
+ readonly retry: () => void;
344
346
  }
345
347
  declare function useCaptions(): UseCaptionsResult;
346
348
  /**
package/dist/react.js CHANGED
@@ -151,7 +151,8 @@ var DEFAULT_CONNECTION_POLICY = {
151
151
  autoRejoin: true,
152
152
  autoRejoinMaxAttempts: 5,
153
153
  reconnectGraceSeconds: 30,
154
- videoAutoOffAfterPoorSeconds: 20
154
+ videoAutoOffAfterPoorSeconds: 20,
155
+ captionsStartTimeoutSeconds: 20
155
156
  };
156
157
  function clampInt(value, min, max, fallback) {
157
158
  if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
@@ -166,7 +167,8 @@ function connectionPolicyFrom(raw) {
166
167
  autoRejoin: typeof row["auto_rejoin"] === "boolean" ? row["auto_rejoin"] : d.autoRejoin,
167
168
  autoRejoinMaxAttempts: clampInt(row["auto_rejoin_max_attempts"], 0, 20, d.autoRejoinMaxAttempts),
168
169
  reconnectGraceSeconds: clampInt(row["reconnect_grace_seconds"], 0, 600, d.reconnectGraceSeconds),
169
- videoAutoOffAfterPoorSeconds: clampInt(row["video_auto_off_after_poor_seconds"], 0, 600, d.videoAutoOffAfterPoorSeconds)
170
+ videoAutoOffAfterPoorSeconds: clampInt(row["video_auto_off_after_poor_seconds"], 0, 600, d.videoAutoOffAfterPoorSeconds),
171
+ captionsStartTimeoutSeconds: clampInt(row["captions_start_timeout_seconds"], 1, 600, d.captionsStartTimeoutSeconds)
170
172
  };
171
173
  }
172
174
  var LIVEKIT_BASE_DELAYS_MS = [0, 300, 1200, 2700, 4800, 7e3];
@@ -4030,6 +4032,7 @@ var EMPTY = {
4030
4032
  noteTakerRefusal: null,
4031
4033
  captionsOn: false,
4032
4034
  captionsRefusal: null,
4035
+ captionsStartTimeoutSeconds: 20,
4033
4036
  media: IDLE_MEDIA,
4034
4037
  mediaRegion: IDLE_MEDIA_REGION,
4035
4038
  failure: null,
@@ -6454,6 +6457,7 @@ function createRoomEngine(options) {
6454
6457
  current = token;
6455
6458
  lastServerUrl = token.serverUrl;
6456
6459
  connectionPolicy = token.connectionPolicy ?? DEFAULT_CONNECTION_POLICY;
6460
+ store.patch({ captionsStartTimeoutSeconds: connectionPolicy.captionsStartTimeoutSeconds });
6457
6461
  if (token.leavePolicy !== void 0) store.patch({ leavePolicy: token.leavePolicy });
6458
6462
  store.patch({ canReclaim: token.canReclaim === true });
6459
6463
  store.patch({
@@ -8901,6 +8905,22 @@ function createMeetingRecordCache(options = {}) {
8901
8905
  };
8902
8906
  }
8903
8907
 
8908
+ // src/core/captions-state.ts
8909
+ var CAPTIONS_TIMEOUT_REASON = "Captions are unavailable right now.";
8910
+ function resolveCaptionsState(i) {
8911
+ if (!i.on) return { state: "off", reason: null, remedy: null };
8912
+ if (i.takerState === "transcribing" && i.takerPresent) return { state: "live", reason: null, remedy: null };
8913
+ if (i.takerState === "joining" && !i.timedOut) return { state: "starting", reason: null, remedy: null };
8914
+ if (i.refusal !== null && i.refusal.reason.length > 0) {
8915
+ return { state: "unavailable", reason: i.refusal.reason, remedy: i.refusal.remedy.length > 0 ? i.refusal.remedy : null };
8916
+ }
8917
+ if (i.takerState === "ended" || i.takerState === "handoff_pending") {
8918
+ return { state: "unavailable", reason: i.takerLabel, remedy: null };
8919
+ }
8920
+ if (i.timedOut) return { state: "unavailable", reason: CAPTIONS_TIMEOUT_REASON, remedy: null };
8921
+ return { state: "starting", reason: null, remedy: null };
8922
+ }
8923
+
8904
8924
  // src/core/layout.ts
8905
8925
  var DEFAULT_PAGE_SIZE = 12;
8906
8926
  function orderParticipants(participants, activeSpeakers) {
@@ -8991,7 +9011,8 @@ function useRoom() {
8991
9011
  local,
8992
9012
  // An observer (role `viewer`) publishes nothing: no Share screen to press and be refused (MD-16).
8993
9013
  sharingAllowed: snapshot === null || canShareUnder(snapshot.livePolicy, effectiveRole(snapshot), effectiveStanding(snapshot)),
8994
- canShareScreen: (engine?.supportsScreenShare() ?? true) && !isObserverRole(snapshot?.grants.role ?? null) && (snapshot === null || canShareUnder(snapshot.livePolicy, effectiveRole(snapshot), effectiveStanding(snapshot))),
9014
+ 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.
9015
+ !(snapshot?.share.state === "ended" && snapshot.share.reason === "not_allowed") && (snapshot === null || canShareUnder(snapshot.livePolicy, effectiveRole(snapshot), effectiveStanding(snapshot))),
8995
9016
  otherPresenter: otherPresenterOf(snapshot),
8996
9017
  join: useCallback2(
8997
9018
  async (request) => requireEngine(engine, "join").join(request),
@@ -9388,32 +9409,37 @@ function useCaptions() {
9388
9409
  if (host === null || meeting === null) return;
9389
9410
  void host.ai.requestCaptions({ meetingId: meeting.id });
9390
9411
  }, [host, meeting]);
9412
+ const [timedOut, setTimedOut] = useState3(false);
9413
+ const timeoutSeconds = snapshot?.captionsStartTimeoutSeconds ?? 20;
9414
+ const live = taker.state === "transcribing" && taker.present;
9415
+ const [attempt, setAttempt] = useState3(0);
9416
+ useEffect3(() => {
9417
+ setTimedOut(false);
9418
+ if (!on || live) return void 0;
9419
+ const id = setTimeout(() => setTimedOut(true), timeoutSeconds * 1e3);
9420
+ return () => clearTimeout(id);
9421
+ }, [on, live, timeoutSeconds, attempt]);
9391
9422
  const toggle = useCallback2(() => {
9392
9423
  if (host === null) return;
9393
9424
  const next = !on;
9394
9425
  host.store.patch({ captionsOn: next, captionsRefusal: null });
9395
9426
  if (next && taker.state !== "joining" && taker.state !== "transcribing") request();
9396
9427
  }, [host, on, taker.state, request]);
9397
- let state = "off";
9398
- let reason = null;
9399
- let remedy = null;
9400
- if (on) {
9401
- if (taker.state === "transcribing" && taker.present) {
9402
- state = "live";
9403
- } else if (taker.state === "joining") {
9404
- state = "starting";
9405
- } else if (refusal2 !== null && refusal2.reason.length > 0) {
9406
- state = "unavailable";
9407
- reason = refusal2.reason;
9408
- remedy = refusal2.remedy.length > 0 ? refusal2.remedy : null;
9409
- } else if (taker.state === "ended" || taker.state === "handoff_pending") {
9410
- state = "unavailable";
9411
- reason = noteTakerLabel(taker);
9412
- } else {
9413
- state = "starting";
9414
- }
9415
- }
9416
- return { on, state, reason, remedy, toggle };
9428
+ const retry = useCallback2(() => {
9429
+ if (host === null) return;
9430
+ host.store.patch({ captionsOn: true, captionsRefusal: null });
9431
+ setAttempt((n) => n + 1);
9432
+ request();
9433
+ }, [host, request]);
9434
+ const view = resolveCaptionsState({
9435
+ on,
9436
+ takerState: taker.state,
9437
+ takerPresent: taker.present,
9438
+ refusal: refusal2,
9439
+ takerLabel: on ? noteTakerLabel(taker) : "",
9440
+ timedOut
9441
+ });
9442
+ return { on, state: view.state, reason: view.reason, remedy: view.remedy, toggle, retry };
9417
9443
  }
9418
9444
  function useEndMeeting() {
9419
9445
  const host = useMeetHost();
@@ -13932,11 +13958,14 @@ function Captions({ lines = 3 }) {
13932
13958
  const captions = useCaptions();
13933
13959
  if (!captions.on) return null;
13934
13960
  if (captions.state === "unavailable") {
13935
- return /* @__PURE__ */ jsx6("div", { className: "mx-meet__captions", role: "status", "data-meet-notice": "captions-unavailable", children: /* @__PURE__ */ jsxs4("p", { className: "mx-meet__caption", children: [
13936
- "Captions are unavailable. ",
13937
- captions.reason,
13938
- captions.remedy !== null ? ` ${captions.remedy}` : ""
13939
- ] }) });
13961
+ return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__captions", role: "status", "data-meet-notice": "captions-unavailable", children: [
13962
+ /* @__PURE__ */ jsxs4("p", { className: "mx-meet__caption", children: [
13963
+ (captions.reason ?? "").startsWith("Captions are unavailable") ? "" : "Captions are unavailable. ",
13964
+ captions.reason,
13965
+ captions.remedy !== null ? ` ${captions.remedy}` : ""
13966
+ ] }),
13967
+ /* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__caption-retry", onClick: captions.retry, children: "Try again" })
13968
+ ] });
13940
13969
  }
13941
13970
  if (visible.length === 0) {
13942
13971
  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." }) });