@ai-matrx/meet 0.11.49 → 0.11.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.
package/dist/react.js CHANGED
@@ -4451,7 +4451,10 @@ function createMeetingSession(options) {
4451
4451
  const meeting = store.snapshot().meeting;
4452
4452
  const pass = options.resolvePass?.() ?? null;
4453
4453
  if (meeting === null || pass === null) return;
4454
- if (policyReading) return policyInFlight ?? void 0;
4454
+ if (policyReading) {
4455
+ await (policyInFlight ?? void 0);
4456
+ return readLivePolicy();
4457
+ }
4455
4458
  policyReading = true;
4456
4459
  let done = () => void 0;
4457
4460
  policyInFlight = new Promise((resolve) => done = resolve);
@@ -4472,6 +4475,9 @@ function createMeetingSession(options) {
4472
4475
  if (!samePolicy(snapshot.livePolicy, next) || startedAt !== snapshot.sessionStartedAt) {
4473
4476
  store.patch({ livePolicy: next, sessionStartedAt: startedAt });
4474
4477
  }
4478
+ if (read.consent_given === true && !store.snapshot().recordingConsentGiven) {
4479
+ store.patch({ recordingConsentGiven: true });
4480
+ }
4475
4481
  } catch {
4476
4482
  } finally {
4477
4483
  policyReading = false;
@@ -4776,6 +4782,21 @@ function createMeetingSession(options) {
4776
4782
  stopWaiting,
4777
4783
  readState: readState2,
4778
4784
  readLivePolicy,
4785
+ async acknowledgeConsent() {
4786
+ const meeting = requireMeeting("meet.consent");
4787
+ const pass = options.resolvePass?.() ?? null;
4788
+ const response = await options.api.request({
4789
+ path: MEET_ROUTES.consent,
4790
+ method: "POST",
4791
+ requireAuth: false,
4792
+ operation: "meet.consent",
4793
+ body: { meeting_id: meeting.id },
4794
+ ...pass !== null ? { headers: { [MEETING_PASS_HEADER]: pass } } : {}
4795
+ });
4796
+ if (!response.ok) {
4797
+ throw new MeetError("transport", `meet.consent: the server answered ${response.status}`, "Your agreement was not saved. Try again.");
4798
+ }
4799
+ },
4779
4800
  async readExit(connection, held) {
4780
4801
  const meeting = store.snapshot().meeting;
4781
4802
  const pass = held ?? options.resolvePass?.() ?? null;
@@ -5173,7 +5194,9 @@ function createMediaSupervisor(options) {
5173
5194
  const deviceKind = INPUT_KIND[kind];
5174
5195
  const previous = inUse[deviceKind];
5175
5196
  const track = store.snapshot().media[kind];
5176
- const gone = previous !== null && !isAlias(previous) && before[deviceKind].has(previous) && !now[deviceKind].has(previous);
5197
+ const aliasLabel = previous !== null && isAlias(previous) ? before[deviceKind].get(previous) : void 0;
5198
+ const aliasGone = previous !== null && aliasLabel !== void 0 && aliasLabel !== "" && (!now[deviceKind].has(previous) || now[deviceKind].get(previous) !== aliasLabel);
5199
+ const gone = aliasGone || previous !== null && !isAlias(previous) && before[deviceKind].has(previous) && !now[deviceKind].has(previous);
5177
5200
  if (gone) {
5178
5201
  const from = before[deviceKind].get(previous) ?? "";
5179
5202
  const remaining = [...now[deviceKind].entries()].filter(([id]) => !isAlias(id));
@@ -5198,7 +5221,7 @@ function createMediaSupervisor(options) {
5198
5221
  await driver.setCameraEnabled(true);
5199
5222
  store.setLocalTrack("camera", { enabled: true, unavailable: null });
5200
5223
  }
5201
- setRegion({ notice: { id: ++noticeId, kind, outcome: "switched", from, to: nextLabel } });
5224
+ setRegion({ notice: { id: ++noticeId, kind, outcome: "switched", from, fromId: previous, to: nextLabel } });
5202
5225
  } catch (error) {
5203
5226
  const refused = await unavailable(error, "camera", "meet.camera(fallback)");
5204
5227
  store.setLocalTrack("camera", { enabled: false, unavailable: refused });
@@ -5206,8 +5229,24 @@ function createMediaSupervisor(options) {
5206
5229
  }
5207
5230
  } else {
5208
5231
  const active = driver.activeDevices().audioinput;
5209
- const to = (active !== null ? now.audioinput.get(active) : void 0) ?? now.audioinput.get("default") ?? remaining[0][1];
5210
- setRegion({ notice: { id: ++noticeId, kind, outcome: "switched", from, to } });
5232
+ let to = (active !== null && !aliasGone ? now.audioinput.get(active) : void 0) ?? now.audioinput.get("default");
5233
+ if (to === void 0 || aliasGone) {
5234
+ const [nextId, nextLabel] = remaining[0];
5235
+ try {
5236
+ await driver.switchDevice("audioinput", nextId);
5237
+ if (track.enabled || track.unavailable !== null) {
5238
+ await driver.setMicrophoneEnabled(true);
5239
+ store.setLocalTrack("microphone", { enabled: true, unavailable: null });
5240
+ }
5241
+ to = nextLabel;
5242
+ } catch (error) {
5243
+ const refused = await unavailable(error, "microphone", "meet.microphone(fallback)");
5244
+ store.setLocalTrack("microphone", { enabled: false, unavailable: refused });
5245
+ setRegion({ notice: { id: ++noticeId, kind, outcome: "lost", from, to: null } });
5246
+ continue;
5247
+ }
5248
+ }
5249
+ setRegion({ notice: { id: ++noticeId, kind, outcome: "switched", from, fromId: previous, to } });
5211
5250
  }
5212
5251
  continue;
5213
5252
  }
@@ -5312,6 +5351,21 @@ function createMediaSupervisor(options) {
5312
5351
  },
5313
5352
  dismissNotice() {
5314
5353
  setRegion({ notice: null });
5354
+ },
5355
+ async undoNotice() {
5356
+ const notice = region().notice;
5357
+ setRegion({ notice: null });
5358
+ const driver = options.driver();
5359
+ if (notice === null || notice.outcome !== "switched" || notice.fromId === void 0 || driver === null) return;
5360
+ const list = await snapshotDevices();
5361
+ if (!list[INPUT_KIND[notice.kind]].has(notice.fromId)) return;
5362
+ try {
5363
+ await driver.switchDevice(INPUT_KIND[notice.kind], notice.fromId);
5364
+ readInUse();
5365
+ } catch (error) {
5366
+ const refused = await unavailable(error, notice.kind, "meet.undoDeviceSwitch");
5367
+ store.setLocalTrack(notice.kind, { enabled: false, unavailable: refused });
5368
+ }
5315
5369
  }
5316
5370
  };
5317
5371
  return api;
@@ -5534,11 +5588,10 @@ function moderationText(kind, payload) {
5534
5588
  switch (kind) {
5535
5589
  case "muted": {
5536
5590
  const source = text2(payload["source"]) ?? "microphone";
5537
- const who = payload["by_role"] === "host" || payload["by_role"] === "cohost" ? "the host" : by;
5538
- return source === "microphone" ? `You've been muted by ${who}.` : source === "camera" ? `Your camera was turned off by ${who}.` : `Your screen share was stopped by ${who}.`;
5591
+ return source === "microphone" ? `${by} muted you.` : source === "camera" ? `${by} turned off your camera.` : `${by} stopped your screen share.`;
5539
5592
  }
5540
5593
  case "ask-unmute":
5541
- return `${by === "The host" ? "The host" : by} asked you to unmute.`;
5594
+ return `${by} is asking you to unmute.`;
5542
5595
  case "removed":
5543
5596
  return `${by} removed you from this meeting.`;
5544
5597
  default:
@@ -5564,7 +5617,7 @@ function applyModeration(store, payload, now) {
5564
5617
  grants: { ...snapshot.grants, role },
5565
5618
  moderationNotice: {
5566
5619
  kind: "role",
5567
- text: role === "host" ? "You are now the host." : role === "cohost" ? "You're now a co-host." : role === "presenter" ? "You're now a presenter." : snapshot.grants.role === "presenter" ? "You're now a participant: you can no longer present." : "You're now a participant: you are no longer a co-host.",
5620
+ text: role === "host" ? "You are now the host." : role === "cohost" ? "You are now a co-host." : role === "presenter" ? "You are now a presenter." : snapshot.grants.role === "presenter" ? "You are now a participant: you can no longer present." : "You are no longer a co-host.",
5568
5621
  at: now()
5569
5622
  }
5570
5623
  });
@@ -6066,7 +6119,14 @@ function createRoomEngine(options) {
6066
6119
  const latest = store.snapshot().meeting;
6067
6120
  if (latest === null) return;
6068
6121
  store.patch({ meeting: { ...latest, endedAt: verified.endedAt } });
6069
- store.dispatch({ type: "ended" }, { reason: "ended" });
6122
+ const connection = current?.connectionIdentity ?? current?.identity ?? store.snapshot().localIdentity ?? null;
6123
+ let why;
6124
+ try {
6125
+ why = options.readExit !== void 0 && connection !== null ? await options.readExit(connection, current?.meetingPass ?? null) : void 0;
6126
+ } catch {
6127
+ why = null;
6128
+ }
6129
+ store.dispatch({ type: "ended" }, { reason: why?.exitReason === "time_limit" ? "time_limit" : "ended" });
6070
6130
  await dropRoom();
6071
6131
  options.onLeft?.("ended");
6072
6132
  } catch (error) {
@@ -6838,6 +6898,7 @@ function createRoomEngine(options) {
6838
6898
  acceptDeviceOffer: () => media.acceptOffer(),
6839
6899
  dismissDeviceOffer: () => media.dismissOffer(),
6840
6900
  dismissDeviceNotice: () => media.dismissNotice(),
6901
+ undoDeviceNotice: () => media.undoNotice(),
6841
6902
  pin(who) {
6842
6903
  store.patch({ pinned: who, layout: who === null ? "grid" : "speaker" });
6843
6904
  },
@@ -9410,6 +9471,7 @@ function useMediaSupervisor() {
9410
9471
  acceptOffer: useCallback2(async () => engine?.acceptDeviceOffer(), [engine]),
9411
9472
  dismissOffer: useCallback2(() => engine?.dismissDeviceOffer(), [engine]),
9412
9473
  dismissNotice: useCallback2(() => engine?.dismissDeviceNotice(), [engine]),
9474
+ undoNotice: useCallback2(async () => engine?.undoDeviceNotice(), [engine]),
9413
9475
  retry: useCallback2(
9414
9476
  async (kind) => kind === "microphone" ? engine?.setMicrophoneEnabled(true) : engine?.setCameraEnabled(true),
9415
9477
  [engine]
@@ -9879,19 +9941,19 @@ function useLivePolicy() {
9879
9941
  const host = useMeetHost();
9880
9942
  const pending = consentPending(policy, role, snapshot?.recording === "recording", snapshot?.recordingConsentGiven === true);
9881
9943
  const viewOnly = pending && policy.recordingConsent === "view_only_until_agree";
9882
- const idle = snapshot !== null && snapshot.recording !== "recording" && snapshot.recording !== "starting" && snapshot.recording !== "stopping";
9883
- const given = snapshot?.recordingConsentGiven === true;
9884
9944
  const store = host?.store ?? null;
9885
- useEffect3(() => {
9886
- if (idle && given) store?.patch({ recordingConsentGiven: false });
9887
- }, [idle, given, store]);
9888
9945
  return {
9889
9946
  canChat: canChat(policy, role),
9890
9947
  chatMode: policy.chatMode,
9891
9948
  micLocked: isLockedFor(policy, role, "microphone") || viewOnly,
9892
9949
  cameraLocked: isLockedFor(policy, role, "camera") || viewOnly,
9893
9950
  consent: pending ? policy.recordingConsent === "ok_or_leave" ? "ok_or_leave" : "view_only_until_agree" : null,
9894
- agree: () => store?.patch({ recordingConsentGiven: true }),
9951
+ // The person's agreement is recorded by the SERVER (per run); the screen follows at once and
9952
+ // takes it back if the server did not save it.
9953
+ agree: () => {
9954
+ store?.patch({ recordingConsentGiven: true });
9955
+ void host?.meetings.acknowledgeConsent().catch(() => store?.patch({ recordingConsentGiven: false }));
9956
+ },
9895
9957
  minutesLeft: left,
9896
9958
  timeWarning: left !== null && left <= policy.timeLimitWarningMinutes
9897
9959
  };
@@ -12690,7 +12752,7 @@ function SpeakingWhileMutedNudge() {
12690
12752
  }
12691
12753
  function MediaNotices() {
12692
12754
  const media = useLocalMedia();
12693
- const { region, where, enableAudio, acceptOffer, dismissOffer, dismissNotice, retry } = useMediaSupervisor();
12755
+ const { region, where, enableAudio, acceptOffer, dismissOffer, dismissNotice, undoNotice, retry } = useMediaSupervisor();
12694
12756
  const [fixing, setFixing] = useState5(null);
12695
12757
  const chips = ["microphone", "camera"].flatMap((kind) => {
12696
12758
  const reason = deviceUnavailableReason(media[kind], region.permission[kind]);
@@ -12755,9 +12817,10 @@ function MediaNotices() {
12755
12817
  {
12756
12818
  className: "mx-meet__media-pill",
12757
12819
  role: "status",
12758
- ...notice.outcome === "lost" ? { "data-meet-notice": "device-lost" } : {},
12820
+ "data-meet-notice": notice.outcome === "lost" ? "device-lost" : "device-switched",
12759
12821
  children: [
12760
- /* @__PURE__ */ jsx6("span", { children: notice.outcome === "switched" ? `${notice.from || name(notice.kind)} disconnected \xB7 now using ${notice.to || "the default"}` : `${notice.from || name(notice.kind)} disconnected` }),
12822
+ /* @__PURE__ */ jsx6("span", { children: notice.outcome === "switched" ? `${notice.from || name(notice.kind)} disconnected \xB7 switched to ${notice.to || "the default"}` : `${notice.from || name(notice.kind)} disconnected` }),
12823
+ notice.outcome === "switched" ? /* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__link", onClick: () => void undoNotice(), children: "Undo" }) : null,
12761
12824
  /* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__toast-close", "aria-label": "Dismiss", onClick: dismissNotice, children: /* @__PURE__ */ jsx6(CloseIcon, { width: 14, height: 14 }) })
12762
12825
  ]
12763
12826
  }
@@ -12810,7 +12873,7 @@ function MeetingOverlays() {
12810
12873
  live.minutesLeft,
12811
12874
  " ",
12812
12875
  live.minutesLeft === 1 ? "minute" : "minutes",
12813
- " (time limit)."
12876
+ "."
12814
12877
  ] }) : null,
12815
12878
  notice !== null && notice.kind !== "removed" ? (
12816
12879
  // A host's request ("the host is asking you to unmute"), not an error: