@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.cjs CHANGED
@@ -491,7 +491,8 @@ var DEFAULT_CONNECTION_POLICY = {
491
491
  autoRejoin: true,
492
492
  autoRejoinMaxAttempts: 5,
493
493
  reconnectGraceSeconds: 30,
494
- videoAutoOffAfterPoorSeconds: 20
494
+ videoAutoOffAfterPoorSeconds: 20,
495
+ captionsStartTimeoutSeconds: 20
495
496
  };
496
497
  function clampInt(value, min, max, fallback) {
497
498
  if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
@@ -506,7 +507,8 @@ function connectionPolicyFrom(raw) {
506
507
  autoRejoin: typeof row["auto_rejoin"] === "boolean" ? row["auto_rejoin"] : d.autoRejoin,
507
508
  autoRejoinMaxAttempts: clampInt(row["auto_rejoin_max_attempts"], 0, 20, d.autoRejoinMaxAttempts),
508
509
  reconnectGraceSeconds: clampInt(row["reconnect_grace_seconds"], 0, 600, d.reconnectGraceSeconds),
509
- videoAutoOffAfterPoorSeconds: clampInt(row["video_auto_off_after_poor_seconds"], 0, 600, d.videoAutoOffAfterPoorSeconds)
510
+ videoAutoOffAfterPoorSeconds: clampInt(row["video_auto_off_after_poor_seconds"], 0, 600, d.videoAutoOffAfterPoorSeconds),
511
+ captionsStartTimeoutSeconds: clampInt(row["captions_start_timeout_seconds"], 1, 600, d.captionsStartTimeoutSeconds)
510
512
  };
511
513
  }
512
514
  var LIVEKIT_BASE_DELAYS_MS = [0, 300, 1200, 2700, 4800, 7e3];
@@ -4357,6 +4359,7 @@ var EMPTY = {
4357
4359
  noteTakerRefusal: null,
4358
4360
  captionsOn: false,
4359
4361
  captionsRefusal: null,
4362
+ captionsStartTimeoutSeconds: 20,
4360
4363
  media: IDLE_MEDIA,
4361
4364
  mediaRegion: IDLE_MEDIA_REGION,
4362
4365
  failure: null,
@@ -6779,6 +6782,7 @@ function createRoomEngine(options) {
6779
6782
  current = token;
6780
6783
  lastServerUrl = token.serverUrl;
6781
6784
  connectionPolicy = token.connectionPolicy ?? DEFAULT_CONNECTION_POLICY;
6785
+ store.patch({ captionsStartTimeoutSeconds: connectionPolicy.captionsStartTimeoutSeconds });
6782
6786
  if (token.leavePolicy !== void 0) store.patch({ leavePolicy: token.leavePolicy });
6783
6787
  store.patch({ canReclaim: token.canReclaim === true });
6784
6788
  store.patch({
@@ -9226,6 +9230,22 @@ function createMeetingRecordCache(options = {}) {
9226
9230
  };
9227
9231
  }
9228
9232
 
9233
+ // src/core/captions-state.ts
9234
+ var CAPTIONS_TIMEOUT_REASON = "Captions are unavailable right now.";
9235
+ function resolveCaptionsState(i) {
9236
+ if (!i.on) return { state: "off", reason: null, remedy: null };
9237
+ if (i.takerState === "transcribing" && i.takerPresent) return { state: "live", reason: null, remedy: null };
9238
+ if (i.takerState === "joining" && !i.timedOut) return { state: "starting", reason: null, remedy: null };
9239
+ if (i.refusal !== null && i.refusal.reason.length > 0) {
9240
+ return { state: "unavailable", reason: i.refusal.reason, remedy: i.refusal.remedy.length > 0 ? i.refusal.remedy : null };
9241
+ }
9242
+ if (i.takerState === "ended" || i.takerState === "handoff_pending") {
9243
+ return { state: "unavailable", reason: i.takerLabel, remedy: null };
9244
+ }
9245
+ if (i.timedOut) return { state: "unavailable", reason: CAPTIONS_TIMEOUT_REASON, remedy: null };
9246
+ return { state: "starting", reason: null, remedy: null };
9247
+ }
9248
+
9229
9249
  // src/core/layout.ts
9230
9250
  var DEFAULT_PAGE_SIZE = 12;
9231
9251
  function orderParticipants(participants, activeSpeakers) {
@@ -9316,7 +9336,8 @@ function useRoom() {
9316
9336
  local,
9317
9337
  // An observer (role `viewer`) publishes nothing: no Share screen to press and be refused (MD-16).
9318
9338
  sharingAllowed: snapshot === null || canShareUnder(snapshot.livePolicy, effectiveRole(snapshot), effectiveStanding(snapshot)),
9319
- canShareScreen: (engine?.supportsScreenShare() ?? true) && !isObserverRole(snapshot?.grants.role ?? null) && (snapshot === null || canShareUnder(snapshot.livePolicy, effectiveRole(snapshot), effectiveStanding(snapshot))),
9339
+ 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.
9340
+ !(snapshot?.share.state === "ended" && snapshot.share.reason === "not_allowed") && (snapshot === null || canShareUnder(snapshot.livePolicy, effectiveRole(snapshot), effectiveStanding(snapshot))),
9320
9341
  otherPresenter: otherPresenterOf(snapshot),
9321
9342
  join: (0, import_react4.useCallback)(
9322
9343
  async (request) => requireEngine(engine, "join").join(request),
@@ -9713,32 +9734,37 @@ function useCaptions() {
9713
9734
  if (host === null || meeting === null) return;
9714
9735
  void host.ai.requestCaptions({ meetingId: meeting.id });
9715
9736
  }, [host, meeting]);
9737
+ const [timedOut, setTimedOut] = (0, import_react4.useState)(false);
9738
+ const timeoutSeconds = snapshot?.captionsStartTimeoutSeconds ?? 20;
9739
+ const live = taker.state === "transcribing" && taker.present;
9740
+ const [attempt, setAttempt] = (0, import_react4.useState)(0);
9741
+ (0, import_react4.useEffect)(() => {
9742
+ setTimedOut(false);
9743
+ if (!on || live) return void 0;
9744
+ const id = setTimeout(() => setTimedOut(true), timeoutSeconds * 1e3);
9745
+ return () => clearTimeout(id);
9746
+ }, [on, live, timeoutSeconds, attempt]);
9716
9747
  const toggle = (0, import_react4.useCallback)(() => {
9717
9748
  if (host === null) return;
9718
9749
  const next = !on;
9719
9750
  host.store.patch({ captionsOn: next, captionsRefusal: null });
9720
9751
  if (next && taker.state !== "joining" && taker.state !== "transcribing") request();
9721
9752
  }, [host, on, taker.state, request]);
9722
- let state = "off";
9723
- let reason = null;
9724
- let remedy = null;
9725
- if (on) {
9726
- if (taker.state === "transcribing" && taker.present) {
9727
- state = "live";
9728
- } else if (taker.state === "joining") {
9729
- state = "starting";
9730
- } else if (refusal2 !== null && refusal2.reason.length > 0) {
9731
- state = "unavailable";
9732
- reason = refusal2.reason;
9733
- remedy = refusal2.remedy.length > 0 ? refusal2.remedy : null;
9734
- } else if (taker.state === "ended" || taker.state === "handoff_pending") {
9735
- state = "unavailable";
9736
- reason = noteTakerLabel(taker);
9737
- } else {
9738
- state = "starting";
9739
- }
9740
- }
9741
- return { on, state, reason, remedy, toggle };
9753
+ const retry = (0, import_react4.useCallback)(() => {
9754
+ if (host === null) return;
9755
+ host.store.patch({ captionsOn: true, captionsRefusal: null });
9756
+ setAttempt((n) => n + 1);
9757
+ request();
9758
+ }, [host, request]);
9759
+ const view = resolveCaptionsState({
9760
+ on,
9761
+ takerState: taker.state,
9762
+ takerPresent: taker.present,
9763
+ refusal: refusal2,
9764
+ takerLabel: on ? noteTakerLabel(taker) : "",
9765
+ timedOut
9766
+ });
9767
+ return { on, state: view.state, reason: view.reason, remedy: view.remedy, toggle, retry };
9742
9768
  }
9743
9769
  function useEndMeeting() {
9744
9770
  const host = useMeetHost();
@@ -14257,11 +14283,14 @@ function Captions({ lines = 3 }) {
14257
14283
  const captions = useCaptions();
14258
14284
  if (!captions.on) return null;
14259
14285
  if (captions.state === "unavailable") {
14260
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mx-meet__captions", role: "status", "data-meet-notice": "captions-unavailable", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: "mx-meet__caption", children: [
14261
- "Captions are unavailable. ",
14262
- captions.reason,
14263
- captions.remedy !== null ? ` ${captions.remedy}` : ""
14264
- ] }) });
14286
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-meet__captions", role: "status", "data-meet-notice": "captions-unavailable", children: [
14287
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: "mx-meet__caption", children: [
14288
+ (captions.reason ?? "").startsWith("Captions are unavailable") ? "" : "Captions are unavailable. ",
14289
+ captions.reason,
14290
+ captions.remedy !== null ? ` ${captions.remedy}` : ""
14291
+ ] }),
14292
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "mx-meet__caption-retry", onClick: captions.retry, children: "Try again" })
14293
+ ] });
14265
14294
  }
14266
14295
  if (visible.length === 0) {
14267
14296
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mx-meet__captions", "aria-live": "polite", "aria-label": "Live captions", "data-meet-caption": captions.state, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("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." }) });