@ai-matrx/meet 0.11.43 → 0.11.45

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
@@ -18,7 +18,14 @@ function createTabClaim(platform = webTabPlatform()) {
18
18
  if (message.kind === "tab-alive?" && mine !== null && message.tabId === mine && message.from !== self) {
19
19
  platform.bus?.post({ kind: "tab-alive", tabId: mine });
20
20
  } else if (message.kind === "who-is-in?" && current !== null && mine !== null && message.from !== self && message.room === current.room && message.person === current.person) {
21
- platform.bus?.post({ kind: "in-room", room: current.room, person: current.person, tabId: mine, to: message.from });
21
+ platform.bus?.post({
22
+ kind: "in-room",
23
+ room: current.room,
24
+ person: current.person,
25
+ tabId: mine,
26
+ to: message.from,
27
+ rule: current.rule
28
+ });
22
29
  }
23
30
  }) ?? (() => {
24
31
  });
@@ -48,28 +55,32 @@ function createTabClaim(platform = webTabPlatform()) {
48
55
  return candidate;
49
56
  }
50
57
  const tabId = claim();
58
+ async function presence(room, person) {
59
+ const bus = platform.bus;
60
+ if (bus === null) return null;
61
+ let seen = null;
62
+ const stop = bus.subscribe((message) => {
63
+ if (message.kind === "in-room" && message.to === self && message.room === room && message.person === person) {
64
+ seen = { rule: seen?.rule ?? message.rule ?? null };
65
+ }
66
+ });
67
+ bus.post({ kind: "who-is-in?", room, person, from: self });
68
+ await wait(TAB_ANSWER_MS);
69
+ stop();
70
+ return seen;
71
+ }
51
72
  return {
52
73
  tabId,
53
- inRoom(room, person) {
54
- current = { room, person };
74
+ inRoom(room, person, rule) {
75
+ current = { room, person, rule: rule ?? null };
55
76
  },
56
77
  left() {
57
78
  current = null;
58
79
  },
59
80
  async presentElsewhere(room, person) {
60
- const bus = platform.bus;
61
- if (bus === null) return false;
62
- let seen = false;
63
- const stop = bus.subscribe((message) => {
64
- if (message.kind === "in-room" && message.to === self && message.room === room && message.person === person) {
65
- seen = true;
66
- }
67
- });
68
- bus.post({ kind: "who-is-in?", room, person, from: self });
69
- await wait(TAB_ANSWER_MS);
70
- stop();
71
- return seen;
81
+ return await presence(room, person) !== null;
72
82
  },
83
+ presenceElsewhere: (room, person) => presence(room, person),
73
84
  dispose() {
74
85
  unsubscribe();
75
86
  }
@@ -247,7 +258,8 @@ function createWebResumeStorage() {
247
258
  }
248
259
  };
249
260
  }
250
- var CLEARS_RESUME = (phase) => phase === "left" || phase === "removed" || phase === "superseded" || phase === "inactive" || phase === "ended" || phase === "record" || phase === "prejoin" || phase.startsWith("refused:") || phase.startsWith("waiting:");
261
+ var CLEARS_RESUME = (phase) => phase === "left" || phase === "removed" || phase === "superseded" || phase === "inactive" || phase === "ended" || phase === "record" || phase === "prejoin" || phase === "denied" || phase === "knock_expired" || phase.startsWith("refused:");
262
+ var WAITING_RESUMES = (phase) => phase.startsWith("waiting:");
251
263
  function autoRejoinDelayMs(attempt, random = Math.random) {
252
264
  const base = Math.min(15e3, 1e3 * 2 ** Math.max(0, attempt));
253
265
  return Math.round(base * (0.5 + random()));
@@ -379,6 +391,10 @@ function createConnectionSupervisor(options) {
379
391
  rejoinAttempts = 0;
380
392
  stopRejoin();
381
393
  saveMarker(true);
394
+ } else if (WAITING_RESUMES(phase)) {
395
+ stopRejoin();
396
+ driverRegion = null;
397
+ saveMarker(true);
382
398
  } else if (phase === "disconnected") {
383
399
  driverRegion = null;
384
400
  saveMarker(true);
@@ -912,6 +928,7 @@ function parseRoomToken(body, roomName) {
912
928
  connectionIdentity: readString(payload, "connection_identity") ?? personKey,
913
929
  connectionKind: readString(payload, "connection_kind") === "companion" ? "companion" : "main",
914
930
  secondDeviceChoice,
931
+ secondDeviceRule: readString(payload, "second_device_rule"),
915
932
  displayName: readString(payload, "display_name") ?? readString(payload, "displayName") ?? identity,
916
933
  expiresAt,
917
934
  canPublish: readBoolean(payload, "can_publish", true),
@@ -1625,6 +1642,12 @@ var JOINABLE_FROM = /* @__PURE__ */ new Set([
1625
1642
  // allows the press; the server's gate decides whether it knocks or is refused again.
1626
1643
  "refused:lobby_rejects"
1627
1644
  ]);
1645
+ var RETRYABLE_REFUSALS = /* @__PURE__ */ new Set([
1646
+ "refused:locked",
1647
+ "refused:too_early",
1648
+ "refused:meeting_full",
1649
+ "refused:platform_capacity"
1650
+ ]);
1628
1651
  var NOT_ENDABLE = /* @__PURE__ */ new Set([
1629
1652
  "ended",
1630
1653
  "record",
@@ -1690,7 +1713,7 @@ function nextPhase(from, event) {
1690
1713
  case "link_state":
1691
1714
  return from === "resolving" && event.reason !== null && isJoinRefusalReason(event.reason) ? refusalPhase(event.reason) : null;
1692
1715
  case "join":
1693
- return JOINABLE_FROM.has(from) ? "joining" : null;
1716
+ return JOINABLE_FROM.has(from) || RETRYABLE_REFUSALS.has(from) ? "joining" : null;
1694
1717
  case "auto_rejoin":
1695
1718
  return from === "disconnected" ? "joining" : null;
1696
1719
  case "resumed":
@@ -2469,11 +2492,13 @@ function minutesLeft(policy, startedAtMs, nowMs) {
2469
2492
  }
2470
2493
 
2471
2494
  // src/core/attendance.ts
2495
+ var IDLE_PREVIEW = { state: "idle", unavailable: null };
2472
2496
  var IDLE_MEDIA_REGION = {
2473
2497
  permission: { microphone: "unknown", camera: "unknown" },
2474
2498
  audioOutput: "ok",
2475
2499
  notice: null,
2476
- offer: null
2500
+ offer: null,
2501
+ preview: { microphone: IDLE_PREVIEW, camera: IDLE_PREVIEW }
2477
2502
  };
2478
2503
  var IDLE_TRACK = { enabled: false, unavailable: null };
2479
2504
  var IDLE_MEDIA = {
@@ -2530,6 +2555,10 @@ var RPCS = {
2530
2555
  admitAll: "meet_admit_all",
2531
2556
  setLock: "meet_set_lock",
2532
2557
  recordConsent: "meet_record_consent",
2558
+ /** One meeting rule as the gate obeys it (the knob ladder, this meeting's rung included). */
2559
+ meetingRule: "meet_policy",
2560
+ /** A host sets one rule for THIS meeting (the `meet_meeting` rung); refusals come back as `{ok:false}`. */
2561
+ setMeetingRule: "meet_policy_set",
2533
2562
  /*
2534
2563
  * ── MEET WAVE 1 — management (0.8). Every write is a SECURITY DEFINER door
2535
2564
  * authorized by the meeting's host or a real iam grant (editor to change,
@@ -2576,7 +2605,7 @@ var INVITEE_COLUMNS = "id,meeting_id,invitee_user_id,email,display_name,role,rsv
2576
2605
  var RECORDING_COLUMNS = "id,meeting_id,state,started_at,ended_at,started_by,file_id,failure_reason";
2577
2606
  var SEGMENT_COLUMNS = "id,meeting_id,identity,speaker,text,started_at,is_final,metadata";
2578
2607
  var NOTE_COLUMNS = "id,meeting_id,text,kind,assignee_user_id,created_at,metadata";
2579
- var ATTENDEE_COLUMNS = "id,meeting_id,identity,participant_user_id,display_name,avatar_url,role,admission_state,knocked_at,knock_expires_at,is_agent,joined_at,left_at,sessions:metadata->sessions";
2608
+ var ATTENDEE_COLUMNS = "id,meeting_id,identity,participant_user_id,display_name,avatar_url,role,admission_state,knocked_at,knock_expires_at,is_agent,joined_at,left_at,sessions:metadata->sessions,knock_flag:metadata->>knock_flag";
2580
2609
  function projectStays(value) {
2581
2610
  if (!Array.isArray(value)) return [];
2582
2611
  const stays = [];
@@ -2976,6 +3005,8 @@ function createMeetRepository(options) {
2976
3005
  admissionState: states.includes(admission) ? admission : "admitted",
2977
3006
  knockedAt: text(row, "knocked_at"),
2978
3007
  knockExpiresAt: text(row, "knock_expires_at"),
3008
+ // The list read selects `metadata->>knock_flag`; a Postgres Changes row carries `metadata`.
3009
+ knockFlag: text(row, "knock_flag") ?? (typeof row["metadata"] === "object" && row["metadata"] !== null ? text(row["metadata"], "knock_flag") : null),
2979
3010
  isAgent: bool(row, "is_agent", false),
2980
3011
  joinedAt: text(row, "joined_at"),
2981
3012
  leftAt: text(row, "left_at"),
@@ -3299,6 +3330,25 @@ function createMeetRepository(options) {
3299
3330
  );
3300
3331
  return projectMeeting(row);
3301
3332
  },
3333
+ async meetingRule(meetingId, key) {
3334
+ const response = await db.rpc(RPCS.meetingRule, { p_meeting_id: meetingId, p_key: key });
3335
+ if (response.error !== null) throw normalizeMeetError(response.error, "meet.meetingRule");
3336
+ return response.data;
3337
+ },
3338
+ async setMeetingRule(meetingId, key, value) {
3339
+ const response = await db.rpc(RPCS.setMeetingRule, { p_meeting_id: meetingId, p_key: key, p_value: value });
3340
+ if (response.error !== null) throw normalizeMeetError(response.error, "meet.setMeetingRule");
3341
+ const answer = response.data ?? {};
3342
+ if (answer["ok"] !== true) {
3343
+ throw new MeetError(
3344
+ "forbidden",
3345
+ typeof answer["detail"] === "string" ? answer["detail"] : "This meeting's rule was not changed.",
3346
+ "Only the meeting's host or a co-host sets its rules; an organization can lock a rule for everyone.",
3347
+ answer
3348
+ );
3349
+ }
3350
+ return answer["effective_value"];
3351
+ },
3302
3352
  async transcript(meetingId, limit = 1e3) {
3303
3353
  const response = await db.from(TABLES.transcripts).select(SEGMENT_COLUMNS).eq("meeting_id", meetingId).order("started_at", { ascending: true }).order("id", { ascending: true }).limit(limit);
3304
3354
  if (response.error !== null) throw normalizeMeetError(response.error, "meet.transcript");
@@ -4193,7 +4243,8 @@ function lobbyEntryFrom(attendee, now = Date.now()) {
4193
4243
  knockedAt: attendee.knockedAt ?? attendee.joinedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
4194
4244
  knockExpiresAt: attendee.knockExpiresAt ?? null,
4195
4245
  decidedAt: null,
4196
- decidedBy: null
4246
+ decidedBy: null,
4247
+ flag: attendee.knockFlag ?? null
4197
4248
  };
4198
4249
  }
4199
4250
  function deniedEntryFrom(attendee) {
@@ -4725,6 +4776,17 @@ function createMeetingSession(options) {
4725
4776
  async askAgain() {
4726
4777
  await options.rejoin?.();
4727
4778
  },
4779
+ async meetingRule(key) {
4780
+ const meeting = requireMeeting("meet.meetingRule");
4781
+ return repository.meetingRule(meeting.id, key);
4782
+ },
4783
+ async setMeetingRule(key, value) {
4784
+ requireHostUser("meet.setMeetingRule");
4785
+ const meeting = requireMeeting("meet.setMeetingRule");
4786
+ const effective = await repository.setMeetingRule(meeting.id, key, value);
4787
+ hint();
4788
+ return effective;
4789
+ },
4728
4790
  async setLock(locked) {
4729
4791
  const by = requireHostUser("meet.setLock");
4730
4792
  const meeting = requireMeeting("meet.setLock");
@@ -4830,6 +4892,47 @@ function createMeetSessionIdentity(options) {
4830
4892
  });
4831
4893
  }
4832
4894
 
4895
+ // src/core/capabilities.ts
4896
+ var IN_APP = [
4897
+ [/Instagram/i, "Instagram"],
4898
+ [/FBAN|FBAV|FB_IAB/i, "Facebook"],
4899
+ [/LinkedInApp/i, "LinkedIn"],
4900
+ [/MicroMessenger/i, "WeChat"],
4901
+ [/Snapchat/i, "Snapchat"],
4902
+ [/\bLine\//i, "LINE"],
4903
+ [/Twitter|TwitterAndroid/i, "X"],
4904
+ [/TikTok|musical_ly|BytedanceWebview/i, "TikTok"]
4905
+ ];
4906
+ function isMobileUserAgent(userAgent, maxTouchPoints = 0) {
4907
+ if (/iPhone|iPod|Android|Mobile|iPad/i.test(userAgent)) return true;
4908
+ return /Macintosh/.test(userAgent) && maxTouchPoints > 1;
4909
+ }
4910
+ function detectCapabilities(scope = typeof globalThis === "undefined" ? null : globalThis) {
4911
+ if (scope === null || scope.navigator === void 0) {
4912
+ return { canJoin: true, reason: null, inAppBrowser: null, mobile: false, canShareScreen: false };
4913
+ }
4914
+ const ua = scope.navigator.userAgent ?? "";
4915
+ const webrtc = typeof scope.RTCPeerConnection === "function" || typeof scope.webkitRTCPeerConnection === "function";
4916
+ const mobile = isMobileUserAgent(ua, scope.navigator.maxTouchPoints ?? 0);
4917
+ const inAppBrowser = IN_APP.find(([pattern]) => pattern.test(ua))?.[1] ?? null;
4918
+ return {
4919
+ canJoin: webrtc,
4920
+ reason: webrtc ? null : "no_webrtc",
4921
+ inAppBrowser,
4922
+ mobile,
4923
+ canShareScreen: !mobile && typeof scope.navigator.mediaDevices?.getDisplayMedia === "function"
4924
+ };
4925
+ }
4926
+ function unsupportedWords(capabilities) {
4927
+ if (capabilities.inAppBrowser !== null) {
4928
+ return {
4929
+ title: `${capabilities.inAppBrowser}'s browser can't join calls`,
4930
+ body: "Open this link in Chrome, Safari, Edge or Firefox"
4931
+ };
4932
+ }
4933
+ return { title: "This browser can't join calls", body: "Open this link in Chrome, Safari, Edge or Firefox" };
4934
+ }
4935
+
4833
4936
  // src/core/media-supervisor.ts
4834
4937
  function classifyDeviceFailure(error, permission) {
4835
4938
  if (permission === "denied") return "denied";
@@ -4890,7 +4993,7 @@ function deviceFixSteps(kind, reason, where) {
4890
4993
  case "safari":
4891
4994
  return where.os === "ios" ? [`Settings \u203A Apps \u203A Safari \u203A ${device}`, "Choose Allow", "Return here and press Try again"] : ["Safari \u203A Settings for This Website", `Set ${device} to Allow`, "Press Try again"];
4892
4995
  default:
4893
- return ["Click the icon left of the web address", `Set ${device} to Allow`, "Press Try again"];
4996
+ return ["Click the site settings icon in the address bar", `Set ${device} to Allow`, "Press Try again"];
4894
4997
  }
4895
4998
  case "blocked_os": {
4896
4999
  const app = where.browser === "chrome" ? "Google Chrome" : where.browser === "edge" ? "Microsoft Edge" : where.browser === "firefox" ? "Firefox" : "your browser";
@@ -4988,7 +5091,7 @@ function createMediaSupervisor(options) {
4988
5091
  function setRegion(next) {
4989
5092
  const current = region();
4990
5093
  const merged = { ...current, ...next };
4991
- if (merged.audioOutput === current.audioOutput && merged.notice === current.notice && merged.offer === current.offer && merged.permission.microphone === current.permission.microphone && merged.permission.camera === current.permission.camera) {
5094
+ if (merged.audioOutput === current.audioOutput && merged.notice === current.notice && merged.offer === current.offer && merged.preview === current.preview && merged.permission.microphone === current.permission.microphone && merged.permission.camera === current.permission.camera) {
4992
5095
  return;
4993
5096
  }
4994
5097
  store.patch({ mediaRegion: merged });
@@ -5084,7 +5187,7 @@ function createMediaSupervisor(options) {
5084
5187
  if (permission !== "unknown") setPermission(kind, permission);
5085
5188
  return unavailableFrom(normalized, classifyDeviceFailure(normalized, permission));
5086
5189
  }
5087
- return {
5190
+ const api = {
5088
5191
  start() {
5089
5192
  if (started || platform === null) return;
5090
5193
  started = true;
@@ -5106,6 +5209,16 @@ function createMediaSupervisor(options) {
5106
5209
  started = false;
5107
5210
  },
5108
5211
  unavailable,
5212
+ async preview(kind, outcome) {
5213
+ api.start();
5214
+ let next;
5215
+ if (typeof outcome === "string") next = { state: outcome, unavailable: null };
5216
+ else next = { state: "unavailable", unavailable: await unavailable(outcome.error, kind, `meet.${kind}Preview`) };
5217
+ const current = region().preview;
5218
+ const was = current[kind];
5219
+ if (was.state === next.state && was.unavailable?.reason === next.unavailable?.reason && was.unavailable?.message === next.unavailable?.message) return;
5220
+ setRegion({ preview: { ...region().preview, [kind]: next } });
5221
+ },
5109
5222
  onAudioPlayback(canPlay) {
5110
5223
  setRegion({ audioOutput: canPlay ? "ok" : "blocked" });
5111
5224
  },
@@ -5164,6 +5277,7 @@ function createMediaSupervisor(options) {
5164
5277
  setRegion({ notice: null });
5165
5278
  }
5166
5279
  };
5280
+ return api;
5167
5281
  }
5168
5282
 
5169
5283
  // src/core/room-events.ts
@@ -5675,7 +5789,8 @@ function createRoomEngine(options) {
5675
5789
  message: normalized.message,
5676
5790
  remedy: normalized.remedy,
5677
5791
  reason: normalized.reason,
5678
- retryAt: normalized.retryAfterSeconds === null ? null : now() + normalized.retryAfterSeconds * 1e3
5792
+ retryAt: normalized.retryAfterSeconds === null ? null : now() + normalized.retryAfterSeconds * 1e3,
5793
+ stage: "join"
5679
5794
  }
5680
5795
  });
5681
5796
  store.dispatch({ type: "join_failed", reason: normalized.reason ?? null });
@@ -5939,7 +6054,7 @@ function createRoomEngine(options) {
5939
6054
  const { secondDevice: _answered, ...rest } = lastRequest;
5940
6055
  lastRequest = rest;
5941
6056
  }
5942
- options.tabClaim?.inRoom(String(request.roomName), String(token.identity));
6057
+ options.tabClaim?.inRoom(String(request.roomName), String(token.identity), token.secondDeviceRule ?? null);
5943
6058
  current = token;
5944
6059
  lastServerUrl = token.serverUrl;
5945
6060
  connectionPolicy = token.connectionPolicy ?? DEFAULT_CONNECTION_POLICY;
@@ -6066,6 +6181,10 @@ function createRoomEngine(options) {
6066
6181
  }
6067
6182
  departures.clear();
6068
6183
  liveRoster = list;
6184
+ const localNow = list.find((p) => p.isLocal);
6185
+ if (localNow !== void 0 && !localNow.screenSharing && store.snapshot().share.state === "presenting") {
6186
+ store.patch({ share: NO_SHARE });
6187
+ }
6069
6188
  const merged = mergeGhosts(list, ghosts, at);
6070
6189
  ghosts = merged.kept;
6071
6190
  const people = /* @__PURE__ */ new Map();
@@ -6247,10 +6366,12 @@ function createRoomEngine(options) {
6247
6366
  if (claim === void 0 || userId === null) return false;
6248
6367
  const before = store.snapshot();
6249
6368
  if (before.phase !== "prejoin" || before.secondDevice !== null) return false;
6250
- if (!await claim.presentElsewhere(String(roomName), `user:${String(userId)}`)) return false;
6369
+ const person = `user:${String(userId)}`;
6370
+ const found = claim.presenceElsewhere !== void 0 ? await claim.presenceElsewhere(String(roomName), person) : await claim.presentElsewhere(String(roomName), person) ? { rule: null } : null;
6371
+ if (found === null || found.rule === "allow_both") return false;
6251
6372
  const now2 = store.snapshot();
6252
6373
  if (now2.phase !== "prejoin" || now2.secondDevice !== null) return false;
6253
- store.patch({ secondDevice: { rule: "ask_switch_or_join" } });
6374
+ store.patch({ secondDevice: { rule: found.rule ?? "ask_switch_or_join" } });
6254
6375
  report("info", "meet: this browser already has you in this meeting \u2014 offering the choice before Join");
6255
6376
  return true;
6256
6377
  },
@@ -6285,7 +6406,10 @@ function createRoomEngine(options) {
6285
6406
  try {
6286
6407
  await driver.setScreenShareEnabled(enabled);
6287
6408
  ambiguousShareDenials = 0;
6288
- store.patch({ share: { state: enabled ? "presenting" : "none", reason: null, remedy: null, at: now() } });
6409
+ const audio = enabled ? driver?.screenShareHasAudio?.() : void 0;
6410
+ store.patch({
6411
+ share: { state: enabled ? "presenting" : "none", reason: null, remedy: null, at: now(), ...audio !== void 0 ? { audio } : {} }
6412
+ });
6289
6413
  } catch (error) {
6290
6414
  const kind = classifyScreenShareError(error);
6291
6415
  if (kind === "ambiguous") {
@@ -6352,13 +6476,14 @@ function createRoomEngine(options) {
6352
6476
  return driver?.supportsVideoEffects?.() ?? false;
6353
6477
  },
6354
6478
  supportsScreenShare() {
6355
- return driver?.supportsScreenShare?.() ?? true;
6479
+ return driver?.supportsScreenShare?.() ?? detectCapabilities().canShareScreen;
6356
6480
  },
6357
6481
  async switchDevice(kind, deviceId2) {
6358
6482
  if (driver === null) return;
6359
6483
  await driver.switchDevice(kind, deviceId2);
6360
6484
  },
6361
6485
  enableAudio: () => media.enableAudio(),
6486
+ previewDevice: (kind, outcome) => media.preview(kind, outcome),
6362
6487
  acceptDeviceOffer: () => media.acceptOffer(),
6363
6488
  dismissDeviceOffer: () => media.dismissOffer(),
6364
6489
  dismissDeviceNotice: () => media.dismissNotice(),
@@ -6830,7 +6955,15 @@ function createLiveKitDriver(handlers, options = {}) {
6830
6955
  created.on(RoomEvent.ParticipantConnected, roster).on(RoomEvent.ParticipantDisconnected, (participant, reason) => {
6831
6956
  handlers.participantLeft?.(participant.identity, reasonName(reason));
6832
6957
  roster();
6833
- }).on(RoomEvent.TrackSubscribed, roster).on(RoomEvent.TrackUnsubscribed, roster).on(RoomEvent.TrackMuted, roster).on(RoomEvent.TrackUnmuted, roster).on(RoomEvent.LocalTrackPublished, roster).on(RoomEvent.LocalTrackUnpublished, roster).on(RoomEvent.ParticipantNameChanged, roster).on(RoomEvent.ParticipantAttributesChanged, roster).on(RoomEvent.ParticipantMetadataChanged, roster).on(RoomEvent.RoomMetadataChanged, (metadata) => {
6958
+ }).on(RoomEvent.TrackSubscribed, roster).on(RoomEvent.TrackUnsubscribed, roster).on(RoomEvent.TrackMuted, roster).on(RoomEvent.TrackUnmuted, roster).on(RoomEvent.LocalTrackPublished, (publication) => {
6959
+ if (publication.source === Track.Source.ScreenShare) {
6960
+ const ended = () => {
6961
+ void created.localParticipant.setScreenShareEnabled(false).catch(() => void 0);
6962
+ };
6963
+ publication.track?.mediaStreamTrack.addEventListener("ended", ended, { once: true });
6964
+ }
6965
+ roster();
6966
+ }).on(RoomEvent.LocalTrackUnpublished, roster).on(RoomEvent.ParticipantNameChanged, roster).on(RoomEvent.ParticipantAttributesChanged, roster).on(RoomEvent.ParticipantMetadataChanged, roster).on(RoomEvent.RoomMetadataChanged, (metadata) => {
6834
6967
  handlers.roomMetadata?.(metadata ?? "");
6835
6968
  }).on(RoomEvent.AudioPlaybackStatusChanged, (canPlay) => {
6836
6969
  handlers.audioPlayback?.(canPlay);
@@ -6971,7 +7104,10 @@ function createLiveKitDriver(handlers, options = {}) {
6971
7104
  },
6972
7105
  async setScreenShareEnabled(enabled) {
6973
7106
  try {
6974
- await requireRoom("setScreenShareEnabled").localParticipant.setScreenShareEnabled(enabled);
7107
+ await requireRoom("setScreenShareEnabled").localParticipant.setScreenShareEnabled(
7108
+ enabled,
7109
+ enabled ? { audio: true, systemAudio: "include" } : void 0
7110
+ );
6975
7111
  } catch (error) {
6976
7112
  throw normalizeScreenShareError(error, "meet.setScreenShareEnabled");
6977
7113
  }
@@ -7010,8 +7146,13 @@ function createLiveKitDriver(handlers, options = {}) {
7010
7146
  supportsVideoEffects() {
7011
7147
  return videoEffectsSupported();
7012
7148
  },
7149
+ screenShareHasAudio() {
7150
+ const target = room;
7151
+ if (target === null) return false;
7152
+ return target.localParticipant.getTrackPublications().some((p) => String(p.source) === "screen_share_audio" && p.track !== void 0);
7153
+ },
7013
7154
  supportsScreenShare() {
7014
- return typeof navigator !== "undefined" && typeof navigator.mediaDevices?.getDisplayMedia === "function";
7155
+ return detectCapabilities().canShareScreen;
7015
7156
  },
7016
7157
  attach(identity, kind, element) {
7017
7158
  const target = requireRoom("attach");
@@ -7483,7 +7624,7 @@ function useLocalUserId() {
7483
7624
  }
7484
7625
 
7485
7626
  // src/react/root.tsx
7486
- import { useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2 } from "react";
7627
+ import { useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
7487
7628
 
7488
7629
  // src/core/observation.ts
7489
7630
  function observedRole(role, standing) {
@@ -7497,6 +7638,21 @@ function observedDevice(track, permission = "unknown", held = null) {
7497
7638
  const reason = deviceUnavailableReason(track, permission);
7498
7639
  return reason === null ? "muted_by_me" : `unavailable:${reason}`;
7499
7640
  }
7641
+ function observedPreview(preview, permission = "unknown") {
7642
+ if (permission === "denied") return "unavailable:denied";
7643
+ switch (preview.state) {
7644
+ case "on":
7645
+ return "on";
7646
+ case "off":
7647
+ return "muted_by_me";
7648
+ case "prompting":
7649
+ return "prompting";
7650
+ case "unavailable":
7651
+ return `unavailable:${preview.unavailable?.reason ?? "failed"}`;
7652
+ default:
7653
+ return null;
7654
+ }
7655
+ }
7500
7656
  function endedRecord(snapshot, given) {
7501
7657
  const record = snapshot?.meeting ?? given;
7502
7658
  return record !== null && record.endedAt !== null;
@@ -7520,18 +7676,22 @@ function observe(input) {
7520
7676
  const canAdmit = actual !== "none" && ADMITTER_ROLES.has(actual);
7521
7677
  const role = actual === "none" || snapshot === null ? "none" : observedRole(actual, effectiveStanding(snapshot));
7522
7678
  const deviceInPlay = phase === "joining" || inCall;
7679
+ const region = snapshot?.mediaRegion;
7680
+ const atPrejoin = phase === "prejoin" && region !== void 0;
7523
7681
  return {
7524
7682
  phase,
7525
7683
  reason: phase === "ended" ? snapshot?.reason ?? null : snapshot?.reason ?? reasonOf(phase),
7526
7684
  role,
7527
- connection: snapshot?.connection ?? "stable",
7685
+ // `net-blip`: in the call, a drop shorter than `reconnect_banner_delay_ms` is not something the
7686
+ // person sees — the contract says what is on screen, so it reads `stable` until the banner shows.
7687
+ connection: snapshot === null ? "stable" : inCall && snapshot.connection !== "stable" && !snapshot.connectionBanner ? "stable" : snapshot.connection,
7528
7688
  hostPresent: inCall && snapshot !== null ? snapshot.participants.some((p) => ADMITTER_ROLES.has(p.role)) : snapshot !== null && isWaitingPhase(snapshot.phase) ? snapshot.waiting?.admittersPresent ?? null : null,
7529
7689
  lobbyCount: canAdmit && snapshot !== null ? snapshot.lobby.filter((entry) => entry.state === "knocking").length : 0,
7530
7690
  recording: snapshot?.recording === "recording" || snapshot?.recording === "stopping",
7531
7691
  // S6c: the autoplay region is known only inside the room (no remote audio exists elsewhere).
7532
7692
  audioBlocked: inCall && snapshot !== null ? snapshot.mediaRegion.audioOutput === "blocked" : null,
7533
- camera: deviceInPlay && snapshot !== null ? observedDevice(snapshot.media.camera, snapshot.mediaRegion.permission.camera, lockedFor(snapshot, "camera", inCall)) : null,
7534
- microphone: deviceInPlay && snapshot !== null ? observedDevice(snapshot.media.microphone, snapshot.mediaRegion.permission.microphone, lockedFor(snapshot, "microphone", inCall)) : null
7693
+ camera: deviceInPlay && snapshot !== null ? observedDevice(snapshot.media.camera, snapshot.mediaRegion.permission.camera, lockedFor(snapshot, "camera", inCall)) : atPrejoin ? observedPreview(region.preview.camera, region.permission.camera) : null,
7694
+ microphone: deviceInPlay && snapshot !== null ? observedDevice(snapshot.media.microphone, snapshot.mediaRegion.permission.microphone, lockedFor(snapshot, "microphone", inCall)) : atPrejoin ? observedPreview(region.preview.microphone, region.permission.microphone) : null
7535
7695
  };
7536
7696
  }
7537
7697
  function lockedFor(snapshot, kind, inCall) {
@@ -7613,7 +7773,7 @@ function microphoneNoticeCode(track, permission = "unknown") {
7613
7773
  }
7614
7774
 
7615
7775
  // src/react/root.tsx
7616
- import { jsx as jsx2 } from "react/jsx-runtime";
7776
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
7617
7777
  function useCoreObservation(options = {}) {
7618
7778
  const snapshot = useMeetSnapshot();
7619
7779
  const { meeting, phase, reason } = options;
@@ -7631,7 +7791,13 @@ function MeetRoot({
7631
7791
  ...options
7632
7792
  }) {
7633
7793
  const snapshot = useMeetSnapshot();
7634
- const observation = useCoreObservation(options);
7794
+ const probed = useCapabilities();
7795
+ const base = useCoreObservation(options);
7796
+ const unsupported = probed !== null && !probed.canJoin;
7797
+ const observation = useMemo2(
7798
+ () => unsupported ? { ...staticObservation("unsupported", probed?.reason ?? null) } : base,
7799
+ [unsupported, probed, base]
7800
+ );
7635
7801
  const attrs = useMemo2(() => rootAttributes(observation), [observation]);
7636
7802
  const latest = useRef2({ observation, storePhase: snapshot?.phase ?? null });
7637
7803
  latest.current = { observation, storePhase: snapshot?.phase ?? null };
@@ -7649,11 +7815,38 @@ function MeetRoot({
7649
7815
  if (target.__matrxMeet === diagnostics) delete target.__matrxMeet;
7650
7816
  };
7651
7817
  }, []);
7652
- return /* @__PURE__ */ jsx2("div", { ...attrs, style: { display: "contents" }, children });
7818
+ return /* @__PURE__ */ jsx2("div", { ...attrs, style: { display: "contents" }, children: unsupported && probed !== null ? /* @__PURE__ */ jsx2(UnsupportedBrowser, { capabilities: probed }) : children });
7819
+ }
7820
+ function useCapabilities() {
7821
+ const [found, setFound] = useState2(null);
7822
+ useEffect2(() => {
7823
+ setFound(detectCapabilities());
7824
+ }, []);
7825
+ return found;
7826
+ }
7827
+ function UnsupportedBrowser({ capabilities }) {
7828
+ const words = unsupportedWords(capabilities);
7829
+ const [copied, setCopied] = useState2(false);
7830
+ const href = typeof window === "undefined" ? "" : window.location.href;
7831
+ return /* @__PURE__ */ jsx2("div", { className: "mx-meet", children: /* @__PURE__ */ jsxs("div", { className: "mx-meet__waiting", "data-meet-exit": "unsupported", children: [
7832
+ /* @__PURE__ */ jsx2("h1", { className: "mx-meet__prejoin-title", children: words.title }),
7833
+ /* @__PURE__ */ jsx2("p", { className: "mx-meet__hint", role: "status", "data-meet-notice": "browser-unsupported", children: words.body }),
7834
+ href.length > 0 ? /* @__PURE__ */ jsx2(
7835
+ "button",
7836
+ {
7837
+ type: "button",
7838
+ className: "mx-meet__primary",
7839
+ onClick: () => {
7840
+ void navigator.clipboard?.writeText(href).then(() => setCopied(true), () => void 0);
7841
+ },
7842
+ children: copied ? "Link copied" : "Copy link"
7843
+ }
7844
+ ) : null
7845
+ ] }) });
7653
7846
  }
7654
7847
 
7655
7848
  // src/react/hooks.ts
7656
- import { useCallback as useCallback2, useEffect as useEffect3, useMemo as useMemo3, useRef as useRef3, useState as useState2, useSyncExternalStore as useSyncExternalStore2 } from "react";
7849
+ import { useCallback as useCallback2, useEffect as useEffect3, useMemo as useMemo3, useRef as useRef3, useState as useState3, useSyncExternalStore as useSyncExternalStore2 } from "react";
7657
7850
  import { useRealtimeManager as useRealtimeManager2 } from "@ai-matrx/realtime/react";
7658
7851
 
7659
7852
  // src/core/record.ts
@@ -8349,7 +8542,8 @@ function useRoom() {
8349
8542
  failure: snapshot?.failure ?? null,
8350
8543
  secondDevice: snapshot?.secondDevice ?? null,
8351
8544
  local,
8352
- canShareScreen: engine?.supportsScreenShare() ?? true,
8545
+ // An observer (role `viewer`) publishes nothing: no Share screen to press and be refused (MD-16).
8546
+ canShareScreen: (engine?.supportsScreenShare() ?? true) && !isObserverRole(snapshot?.grants.role ?? null),
8353
8547
  join: useCallback2(
8354
8548
  async (request) => requireEngine(engine, "join").join(request),
8355
8549
  [engine]
@@ -8406,7 +8600,7 @@ function useRoom() {
8406
8600
  }
8407
8601
  function useStage(pageSize = DEFAULT_PAGE_SIZE) {
8408
8602
  const snapshot = useMeetSnapshot();
8409
- const [page, setPage] = useState2(0);
8603
+ const [page, setPage] = useState3(0);
8410
8604
  const stage = useMemo3(
8411
8605
  () => computeStage({
8412
8606
  participants: snapshot?.participants ?? [],
@@ -8440,7 +8634,7 @@ function useTrack(identity, kind) {
8440
8634
  function useCalls() {
8441
8635
  const host = useMeetHost();
8442
8636
  const center = host?.calls ?? null;
8443
- const [, force] = useState2(0);
8637
+ const [, force] = useState3(0);
8444
8638
  useEffect3(() => {
8445
8639
  if (center === null) return void 0;
8446
8640
  const timer = setInterval(() => force((value) => value + 1), 1e3);
@@ -8520,7 +8714,7 @@ function useLobby() {
8520
8714
  };
8521
8715
  }
8522
8716
  function useCountdown(untilMs) {
8523
- const [now, setNow] = useState2(() => Date.now());
8717
+ const [now, setNow] = useState3(() => Date.now());
8524
8718
  const active = typeof untilMs === "number" && untilMs > now;
8525
8719
  useEffect3(() => {
8526
8720
  if (!active) return void 0;
@@ -8533,7 +8727,7 @@ function useCountdown(untilMs) {
8533
8727
  }
8534
8728
  function useKnockNotice() {
8535
8729
  const lobby = useLobby();
8536
- const [dismissed, setDismissed] = useState2([]);
8730
+ const [dismissed, setDismissed] = useState3([]);
8537
8731
  const keyOf = (entry) => `${entry.identity}@${entry.knockedAt}`;
8538
8732
  const open = lobby.canAdmit ? lobby.waiting.filter((entry) => !dismissed.includes(keyOf(entry))) : [];
8539
8733
  const knocker = open[0] ?? null;
@@ -8619,11 +8813,11 @@ function useMeetAi() {
8619
8813
  const host = useMeetHost();
8620
8814
  const snapshot = useMeetSnapshot();
8621
8815
  const isHost = useIsHost();
8622
- const [asking, setAsking] = useState2(false);
8623
- const [answer, setAnswer] = useState2(null);
8624
- const [coverage, setCoverage] = useState2(null);
8625
- const [phase, setPhase] = useState2(null);
8626
- const [error, setError] = useState2(null);
8816
+ const [asking, setAsking] = useState3(false);
8817
+ const [answer, setAnswer] = useState3(null);
8818
+ const [coverage, setCoverage] = useState3(null);
8819
+ const [phase, setPhase] = useState3(null);
8820
+ const [error, setError] = useState3(null);
8627
8821
  const ai = host?.ai ?? null;
8628
8822
  const meeting = snapshot?.meeting ?? null;
8629
8823
  const participants = snapshot?.participants ?? [];
@@ -8776,8 +8970,8 @@ function useEndMeeting() {
8776
8970
  const host = useMeetHost();
8777
8971
  const snapshot = useMeetSnapshot();
8778
8972
  const isHost = useIsHost();
8779
- const [ending, setEnding] = useState2(false);
8780
- const [notice, setNotice] = useState2(null);
8973
+ const [ending, setEnding] = useState3(false);
8974
+ const [notice, setNotice] = useState3(null);
8781
8975
  const meeting = snapshot?.meeting ?? null;
8782
8976
  const session = host?.meetings ?? null;
8783
8977
  return {
@@ -8828,6 +9022,12 @@ function useMediaSupervisor() {
8828
9022
  retry: useCallback2(
8829
9023
  async (kind) => kind === "microphone" ? engine?.setMicrophoneEnabled(true) : engine?.setCameraEnabled(true),
8830
9024
  [engine]
9025
+ ),
9026
+ reportPreview: useCallback2(
9027
+ (kind, outcome) => {
9028
+ void engine?.previewDevice(kind, outcome);
9029
+ },
9030
+ [engine]
8831
9031
  )
8832
9032
  };
8833
9033
  }
@@ -8850,7 +9050,7 @@ function useReactions() {
8850
9050
  return snapshot?.reactions ?? [];
8851
9051
  }
8852
9052
  function useElapsed(startedAt) {
8853
- const [now, setNow] = useState2(() => Date.now());
9053
+ const [now, setNow] = useState3(() => Date.now());
8854
9054
  useEffect3(() => {
8855
9055
  if (startedAt === null) return void 0;
8856
9056
  const timer = setInterval(() => setNow(Date.now()), 1e3);
@@ -8875,7 +9075,7 @@ function useHostControls() {
8875
9075
  (participant) => participant.identity === snapshot.localIdentity
8876
9076
  );
8877
9077
  const actor = me === void 0 ? void 0 : { ...me, role };
8878
- const [busy, setBusy] = useState2(false);
9078
+ const [busy, setBusy] = useState3(false);
8879
9079
  const inRoom = host?.inRoom ?? null;
8880
9080
  const store = host?.store ?? null;
8881
9081
  const notice = snapshot?.actionNotice ?? null;
@@ -8958,7 +9158,7 @@ function useModerationNotice() {
8958
9158
  };
8959
9159
  }
8960
9160
  function useAudioLevel(stream) {
8961
- const [level, setLevel] = useState2(0);
9161
+ const [level, setLevel] = useState3(0);
8962
9162
  useEffect3(() => {
8963
9163
  if (stream === null || stream.getAudioTracks().length === 0) {
8964
9164
  setLevel(0);
@@ -9047,10 +9247,10 @@ function useMeetingRecord(meeting) {
9047
9247
  const repository = host?.repository ?? null;
9048
9248
  const ai = host?.ai ?? null;
9049
9249
  const readerId = host?.identity.userId ?? null;
9050
- const [asking, setAsking] = useState2(false);
9051
- const [answer, setAnswer] = useState2(null);
9052
- const [coverage, setCoverage] = useState2(null);
9053
- const [askError, setAskError] = useState2(null);
9250
+ const [asking, setAsking] = useState3(false);
9251
+ const [answer, setAnswer] = useState3(null);
9252
+ const [coverage, setCoverage] = useState3(null);
9253
+ const [askError, setAskError] = useState3(null);
9054
9254
  const meetingId = meeting?.id ?? null;
9055
9255
  const api = host?.api ?? null;
9056
9256
  const tokens = host?.tokens ?? null;
@@ -9195,11 +9395,11 @@ function useMeetings(limit = 25, organizationFilter = null) {
9195
9395
  const host = useMeetHost();
9196
9396
  const repository = host?.repository ?? null;
9197
9397
  const organizationId = organizationFilter;
9198
- const [meetings, setMeetings] = useState2([]);
9199
- const [hasMore, setHasMore] = useState2(false);
9200
- const [loading, setLoading] = useState2(true);
9201
- const [failure, setFailure] = useState2(null);
9202
- const [nonce, setNonce] = useState2(0);
9398
+ const [meetings, setMeetings] = useState3([]);
9399
+ const [hasMore, setHasMore] = useState3(false);
9400
+ const [loading, setLoading] = useState3(true);
9401
+ const [failure, setFailure] = useState3(null);
9402
+ const [nonce, setNonce] = useState3(0);
9203
9403
  useEffect3(() => {
9204
9404
  if (repository === null) return void 0;
9205
9405
  let live = true;
@@ -9234,10 +9434,10 @@ function useGuestRecordAccess(meeting) {
9234
9434
  const host = useMeetHost();
9235
9435
  const api = host?.api ?? null;
9236
9436
  const stored = guestRecordAccessSetting(meeting);
9237
- const [chosen, setChosen] = useState2(null);
9238
- const [effective, setEffective] = useState2(null);
9239
- const [saving, setSaving] = useState2(false);
9240
- const [error, setError] = useState2(null);
9437
+ const [chosen, setChosen] = useState3(null);
9438
+ const [effective, setEffective] = useState3(null);
9439
+ const [saving, setSaving] = useState3(false);
9440
+ const [error, setError] = useState3(null);
9241
9441
  useEffect3(() => {
9242
9442
  setChosen(null);
9243
9443
  }, [stored, meeting?.id]);
@@ -9276,7 +9476,7 @@ function useGuestRecordAccess(meeting) {
9276
9476
  function useLivePolicy() {
9277
9477
  const snapshot = useMeetSnapshot();
9278
9478
  const role = useRole();
9279
- const [now, setNow] = useState2(() => Date.now());
9479
+ const [now, setNow] = useState3(() => Date.now());
9280
9480
  const limited = (snapshot?.livePolicy.timeLimitMinutes ?? 0) > 0;
9281
9481
  useEffect3(() => {
9282
9482
  if (!limited) return void 0;
@@ -9310,7 +9510,7 @@ function useLivePolicy() {
9310
9510
  import { useEffect as useEffect8 } from "react";
9311
9511
 
9312
9512
  // src/skins/meet/components.tsx
9313
- import { useEffect as useEffect6, useLayoutEffect, useRef as useRef6, useState as useState4 } from "react";
9513
+ import { useEffect as useEffect6, useLayoutEffect, useRef as useRef6, useState as useState5 } from "react";
9314
9514
 
9315
9515
  // src/react/facade.ts
9316
9516
  import { useMemo as useMemo5 } from "react";
@@ -9923,6 +10123,39 @@ function useCollabPanelRequest(onRequest) {
9923
10123
  // src/core/reactions.ts
9924
10124
  var MEET_REACTIONS = ["\u{1F496}", "\u{1F44D}", "\u{1F389}", "\u{1F44F}", "\u{1F602}", "\u{1F62E}", "\u{1F622}", "\u{1F914}", "\u{1F44E}"];
9925
10125
 
10126
+ // src/core/speaking-detector.ts
10127
+ function createSpeakingWhileMutedDetector(options = {}) {
10128
+ const threshold = options.threshold ?? 0.06;
10129
+ const holdMs = options.holdMs ?? 600;
10130
+ const gapMs = options.gapMs ?? 400;
10131
+ const cooldownMs = options.cooldownMs ?? 2e4;
10132
+ let speechStart = null;
10133
+ let lastLoud = null;
10134
+ let firedAt = null;
10135
+ return {
10136
+ feed(level, at) {
10137
+ if (level >= threshold) {
10138
+ if (speechStart === null || lastLoud === null || at - lastLoud > gapMs) speechStart = at;
10139
+ lastLoud = at;
10140
+ } else if (lastLoud !== null && at - lastLoud > gapMs) {
10141
+ speechStart = null;
10142
+ lastLoud = null;
10143
+ }
10144
+ if (speechStart === null || at - speechStart < holdMs) return false;
10145
+ if (firedAt !== null && at - firedAt < cooldownMs) return false;
10146
+ firedAt = at;
10147
+ speechStart = null;
10148
+ lastLoud = null;
10149
+ return true;
10150
+ },
10151
+ reset() {
10152
+ speechStart = null;
10153
+ lastLoud = null;
10154
+ firedAt = null;
10155
+ }
10156
+ };
10157
+ }
10158
+
9926
10159
  // src/react/facade.ts
9927
10160
  var NO_ACTIONS = {
9928
10161
  join: async () => void 0,
@@ -9943,6 +10176,10 @@ function actionsFor(host) {
9943
10176
  leave: () => engine.leave(),
9944
10177
  backToPrejoin: () => engine.backToPrejoin(),
9945
10178
  retry: () => {
10179
+ if (RETRYABLE_REFUSALS.has(store.snapshot().phase)) {
10180
+ void engine.rejoin().catch(() => void 0);
10181
+ return;
10182
+ }
9946
10183
  store.dispatch({ type: "retry", click: true });
9947
10184
  },
9948
10185
  resolved: () => {
@@ -9987,10 +10224,10 @@ function useMeetCore() {
9987
10224
  import { Alert, AlertDescription, Button, Checkbox, ErrorBox, Label, SegmentedControl, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@ai-matrx/design-system";
9988
10225
 
9989
10226
  // src/skins/meet/collab.tsx
9990
- import { useEffect as useEffect5, useRef as useRef5, useState as useState3 } from "react";
10227
+ import { useEffect as useEffect5, useRef as useRef5, useState as useState4 } from "react";
9991
10228
 
9992
10229
  // src/skins/meet/icons.tsx
9993
- import { jsx as jsx4, jsxs } from "react/jsx-runtime";
10230
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
9994
10231
  function Icon({ children, ...props }) {
9995
10232
  return /* @__PURE__ */ jsx4(
9996
10233
  "svg",
@@ -10011,14 +10248,14 @@ function Icon({ children, ...props }) {
10011
10248
  );
10012
10249
  }
10013
10250
  function MicIcon(props) {
10014
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10251
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10015
10252
  /* @__PURE__ */ jsx4("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" }),
10016
10253
  /* @__PURE__ */ jsx4("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
10017
10254
  /* @__PURE__ */ jsx4("path", { d: "M12 19v3" })
10018
10255
  ] });
10019
10256
  }
10020
10257
  function MicOffIcon(props) {
10021
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10258
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10022
10259
  /* @__PURE__ */ jsx4("path", { d: "M2 2l20 20" }),
10023
10260
  /* @__PURE__ */ jsx4("path", { d: "M9 9v3a3 3 0 0 0 5.12 2.12" }),
10024
10261
  /* @__PURE__ */ jsx4("path", { d: "M15 9.34V5a3 3 0 0 0-5.94-.6" }),
@@ -10027,20 +10264,20 @@ function MicOffIcon(props) {
10027
10264
  ] });
10028
10265
  }
10029
10266
  function CameraIcon(props) {
10030
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10267
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10031
10268
  /* @__PURE__ */ jsx4("path", { d: "m23 7-7 5 7 5V7Z" }),
10032
10269
  /* @__PURE__ */ jsx4("rect", { x: "1", y: "5", width: "15", height: "14", rx: "2" })
10033
10270
  ] });
10034
10271
  }
10035
10272
  function CameraOffIcon(props) {
10036
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10273
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10037
10274
  /* @__PURE__ */ jsx4("path", { d: "M2 2l20 20" }),
10038
10275
  /* @__PURE__ */ jsx4("path", { d: "M10.66 5H14a2 2 0 0 1 2 2v3.34l1 1L23 7v10" }),
10039
10276
  /* @__PURE__ */ jsx4("path", { d: "M16 16a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h2" })
10040
10277
  ] });
10041
10278
  }
10042
10279
  function ScreenShareIcon(props) {
10043
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10280
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10044
10281
  /* @__PURE__ */ jsx4("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2" }),
10045
10282
  /* @__PURE__ */ jsx4("path", { d: "M8 21h8M12 17v4" }),
10046
10283
  /* @__PURE__ */ jsx4("path", { d: "M12 13V8m0 0-2.5 2.5M12 8l2.5 2.5" })
@@ -10053,7 +10290,7 @@ function PhoneOffIcon(props) {
10053
10290
  return /* @__PURE__ */ jsx4(Icon, { fill: "currentColor", stroke: "none", ...props, children: /* @__PURE__ */ jsx4("path", { d: "M12 9c-1.6 0-3.15.25-4.6.72v3.1c0 .39-.23.74-.56.9-.98.49-1.87 1.12-2.66 1.85-.18.18-.43.28-.7.28-.28 0-.53-.11-.71-.29L.29 13.08a.99.99 0 0 1-.29-.7c0-.28.11-.53.29-.71C3.34 8.78 7.46 7 12 7s8.66 1.78 11.71 4.67c.18.18.29.43.29.71 0 .28-.11.53-.29.71l-2.48 2.48c-.18.18-.43.29-.71.29-.27 0-.52-.11-.7-.28a11.27 11.27 0 0 0-2.67-1.85.996.996 0 0 1-.56-.9v-3.1C15.15 9.25 13.6 9 12 9Z" }) });
10054
10291
  }
10055
10292
  function HandIcon(props) {
10056
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10293
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10057
10294
  /* @__PURE__ */ jsx4("path", { d: "M18 11V6a2 2 0 0 0-4 0v5" }),
10058
10295
  /* @__PURE__ */ jsx4("path", { d: "M14 10V4a2 2 0 0 0-4 0v7" }),
10059
10296
  /* @__PURE__ */ jsx4("path", { d: "M10 10.5V6a2 2 0 0 0-4 0v8" }),
@@ -10064,7 +10301,7 @@ function ChatIcon(props) {
10064
10301
  return /* @__PURE__ */ jsx4(Icon, { ...props, children: /* @__PURE__ */ jsx4("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2Z" }) });
10065
10302
  }
10066
10303
  function PeopleIcon(props) {
10067
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10304
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10068
10305
  /* @__PURE__ */ jsx4("path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" }),
10069
10306
  /* @__PURE__ */ jsx4("circle", { cx: "9", cy: "7", r: "4" }),
10070
10307
  /* @__PURE__ */ jsx4("path", { d: "M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75" })
@@ -10074,31 +10311,31 @@ function RecordIcon(props) {
10074
10311
  return /* @__PURE__ */ jsx4(Icon, { ...props, children: /* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "8", fill: "currentColor", stroke: "none" }) });
10075
10312
  }
10076
10313
  function SparklesIcon(props) {
10077
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10314
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10078
10315
  /* @__PURE__ */ jsx4("path", { d: "M12 3l1.9 4.6L18.5 9.5l-4.6 1.9L12 16l-1.9-4.6L5.5 9.5l4.6-1.9L12 3Z" }),
10079
10316
  /* @__PURE__ */ jsx4("path", { d: "M19 15l.9 2.1 2.1.9-2.1.9-.9 2.1-.9-2.1-2.1-.9 2.1-.9L19 15Z" })
10080
10317
  ] });
10081
10318
  }
10082
10319
  function CaptionsIcon(props) {
10083
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10320
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10084
10321
  /* @__PURE__ */ jsx4("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
10085
10322
  /* @__PURE__ */ jsx4("path", { d: "M10 10.5a2 2 0 1 0 0 3M16 10.5a2 2 0 1 0 0 3" })
10086
10323
  ] });
10087
10324
  }
10088
10325
  function NotesIcon(props) {
10089
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10326
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10090
10327
  /* @__PURE__ */ jsx4("path", { d: "M4 20l1-4L16.5 4.5a2.1 2.1 0 0 1 3 3L8 19l-4 1Z" }),
10091
10328
  /* @__PURE__ */ jsx4("path", { d: "M14 7l3 3" })
10092
10329
  ] });
10093
10330
  }
10094
10331
  function LockIcon(props) {
10095
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10332
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10096
10333
  /* @__PURE__ */ jsx4("rect", { x: "4", y: "10", width: "16", height: "11", rx: "2" }),
10097
10334
  /* @__PURE__ */ jsx4("path", { d: "M8 10V7a4 4 0 0 1 8 0v3" })
10098
10335
  ] });
10099
10336
  }
10100
10337
  function SettingsIcon(props) {
10101
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10338
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10102
10339
  /* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "3" }),
10103
10340
  /* @__PURE__ */ jsx4("path", { d: "M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06A1.65 1.65 0 0 0 9 4.6a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1Z" })
10104
10341
  ] });
@@ -10110,13 +10347,13 @@ function CloseIcon(props) {
10110
10347
  return /* @__PURE__ */ jsx4(Icon, { ...props, children: /* @__PURE__ */ jsx4("path", { d: "M18 6 6 18M6 6l12 12" }) });
10111
10348
  }
10112
10349
  function PinIcon(props) {
10113
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10350
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10114
10351
  /* @__PURE__ */ jsx4("path", { d: "M12 17v5" }),
10115
10352
  /* @__PURE__ */ jsx4("path", { d: "M9 2h6l-1 6 3.5 3.5V14H6.5v-2.5L10 8 9 2Z" })
10116
10353
  ] });
10117
10354
  }
10118
10355
  function SmileIcon(props) {
10119
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10356
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10120
10357
  /* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "10" }),
10121
10358
  /* @__PURE__ */ jsx4("path", { d: "M8 14s1.5 2 4 2 4-2 4-2" }),
10122
10359
  /* @__PURE__ */ jsx4("line", { x1: "9", x2: "9.01", y1: "9", y2: "9" }),
@@ -10124,20 +10361,20 @@ function SmileIcon(props) {
10124
10361
  ] });
10125
10362
  }
10126
10363
  function MoreIcon(props) {
10127
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10364
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10128
10365
  /* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "1" }),
10129
10366
  /* @__PURE__ */ jsx4("circle", { cx: "19", cy: "12", r: "1" }),
10130
10367
  /* @__PURE__ */ jsx4("circle", { cx: "5", cy: "12", r: "1" })
10131
10368
  ] });
10132
10369
  }
10133
10370
  function SearchIcon(props) {
10134
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10371
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10135
10372
  /* @__PURE__ */ jsx4("circle", { cx: "11", cy: "11", r: "8" }),
10136
10373
  /* @__PURE__ */ jsx4("path", { d: "m21 21-4.3-4.3" })
10137
10374
  ] });
10138
10375
  }
10139
10376
  function KeyboardIcon(props) {
10140
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10377
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10141
10378
  /* @__PURE__ */ jsx4("path", { d: "M10 8h.01M12 12h.01M14 8h.01M16 12h.01M18 8h.01M6 8h.01M7 16h10M8 12h.01" }),
10142
10379
  /* @__PURE__ */ jsx4("rect", { width: "20", height: "16", x: "2", y: "4", rx: "2" })
10143
10380
  ] });
@@ -10146,7 +10383,7 @@ function SpotlightIcon(props) {
10146
10383
  return /* @__PURE__ */ jsx4(Icon, { ...props, children: /* @__PURE__ */ jsx4("path", { d: "M12 2 15 8.5 22 9.3 17 14 18.2 21 12 17.6 5.8 21 7 14 2 9.3 9 8.5Z" }) });
10147
10384
  }
10148
10385
  function SignalIcon({ bars, ...props }) {
10149
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10386
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10150
10387
  /* @__PURE__ */ jsx4("path", { d: "M4 20v-2", opacity: bars >= 1 ? 1 : 0.3 }),
10151
10388
  /* @__PURE__ */ jsx4("path", { d: "M10 20v-6", opacity: bars >= 2 ? 1 : 0.3 }),
10152
10389
  /* @__PURE__ */ jsx4("path", { d: "M16 20V9", opacity: bars >= 3 ? 1 : 0.3 }),
@@ -10154,14 +10391,14 @@ function SignalIcon({ bars, ...props }) {
10154
10391
  ] });
10155
10392
  }
10156
10393
  function SpeakerIcon(props) {
10157
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10394
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10158
10395
  /* @__PURE__ */ jsx4("path", { d: "M11 5 6 9H2v6h4l5 4V5Z" }),
10159
10396
  /* @__PURE__ */ jsx4("path", { d: "M15.54 8.46a5 5 0 0 1 0 7.07" }),
10160
10397
  /* @__PURE__ */ jsx4("path", { d: "M19.07 4.93a10 10 0 0 1 0 14.14" })
10161
10398
  ] });
10162
10399
  }
10163
10400
  function FlagIcon(props) {
10164
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10401
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10165
10402
  /* @__PURE__ */ jsx4("path", { d: "M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z" }),
10166
10403
  /* @__PURE__ */ jsx4("line", { x1: "4", x2: "4", y1: "22", y2: "15" })
10167
10404
  ] });
@@ -10170,35 +10407,35 @@ function PencilIcon(props) {
10170
10407
  return /* @__PURE__ */ jsx4(Icon, { ...props, children: /* @__PURE__ */ jsx4("path", { d: "M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z" }) });
10171
10408
  }
10172
10409
  function ActivitiesIcon(props) {
10173
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10410
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10174
10411
  /* @__PURE__ */ jsx4("path", { d: "M8.3 10a.7.7 0 0 1-.626-1.079L11.4 3a.7.7 0 0 1 1.198-.043L16.3 8.9a.7.7 0 0 1-.572 1.1Z" }),
10175
10412
  /* @__PURE__ */ jsx4("rect", { x: "3", y: "14", width: "7", height: "7", rx: "1" }),
10176
10413
  /* @__PURE__ */ jsx4("circle", { cx: "17.5", cy: "17.5", r: "3.5" })
10177
10414
  ] });
10178
10415
  }
10179
10416
  function PollIcon(props) {
10180
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10417
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10181
10418
  /* @__PURE__ */ jsx4("line", { x1: "18", x2: "18", y1: "20", y2: "10" }),
10182
10419
  /* @__PURE__ */ jsx4("line", { x1: "12", x2: "12", y1: "20", y2: "4" }),
10183
10420
  /* @__PURE__ */ jsx4("line", { x1: "6", x2: "6", y1: "20", y2: "14" })
10184
10421
  ] });
10185
10422
  }
10186
10423
  function QuestionIcon(props) {
10187
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10424
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10188
10425
  /* @__PURE__ */ jsx4("path", { d: "M7.9 20A9 9 0 1 0 4 16.1L2 22Z" }),
10189
10426
  /* @__PURE__ */ jsx4("path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" }),
10190
10427
  /* @__PURE__ */ jsx4("path", { d: "M12 17h.01" })
10191
10428
  ] });
10192
10429
  }
10193
10430
  function WhiteboardIcon(props) {
10194
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10431
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10195
10432
  /* @__PURE__ */ jsx4("path", { d: "M2 3h20" }),
10196
10433
  /* @__PURE__ */ jsx4("path", { d: "M21 3v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V3" }),
10197
10434
  /* @__PURE__ */ jsx4("path", { d: "m7 21 5-5 5 5" })
10198
10435
  ] });
10199
10436
  }
10200
10437
  function BreakoutIcon(props) {
10201
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10438
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10202
10439
  /* @__PURE__ */ jsx4("rect", { width: "7", height: "18", x: "3", y: "3", rx: "1" }),
10203
10440
  /* @__PURE__ */ jsx4("rect", { width: "7", height: "7", x: "14", y: "3", rx: "1" }),
10204
10441
  /* @__PURE__ */ jsx4("rect", { width: "7", height: "7", x: "14", y: "14", rx: "1" })
@@ -10208,29 +10445,32 @@ function UpvoteIcon(props) {
10208
10445
  return /* @__PURE__ */ jsx4(Icon, { ...props, children: /* @__PURE__ */ jsx4("path", { d: "M9 18v-6H5l7-7 7 7h-4v6H9z" }) });
10209
10446
  }
10210
10447
  function EraserIcon(props) {
10211
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10448
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10212
10449
  /* @__PURE__ */ jsx4("path", { d: "m7 21-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21" }),
10213
10450
  /* @__PURE__ */ jsx4("path", { d: "M22 21H7" }),
10214
10451
  /* @__PURE__ */ jsx4("path", { d: "m5 11 9 9" })
10215
10452
  ] });
10216
10453
  }
10217
10454
  function HighlighterIcon(props) {
10218
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10455
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10219
10456
  /* @__PURE__ */ jsx4("path", { d: "m9 11-6 6v3h9l3-3" }),
10220
10457
  /* @__PURE__ */ jsx4("path", { d: "m22 12-4.6 4.6a2 2 0 0 1-2.8 0l-5.2-5.2a2 2 0 0 1 0-2.8L14 4" })
10221
10458
  ] });
10222
10459
  }
10223
10460
  function UndoIcon(props) {
10224
- return /* @__PURE__ */ jsxs(Icon, { ...props, children: [
10461
+ return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
10225
10462
  /* @__PURE__ */ jsx4("path", { d: "M9 14 4 9l5-5" }),
10226
10463
  /* @__PURE__ */ jsx4("path", { d: "M4 9h10.5a5.5 5.5 0 0 1 5.5 5.5a5.5 5.5 0 0 1-5.5 5.5H11" })
10227
10464
  ] });
10228
10465
  }
10466
+ function ChevronUpIcon(props) {
10467
+ return /* @__PURE__ */ jsx4(Icon, { ...props, children: /* @__PURE__ */ jsx4("path", { d: "m6 15 6-6 6 6" }) });
10468
+ }
10229
10469
 
10230
10470
  // src/skins/meet/collab.tsx
10231
- import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
10471
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
10232
10472
  function useNotice() {
10233
- const [notice, setNotice] = useState3(null);
10473
+ const [notice, setNotice] = useState4(null);
10234
10474
  useEffect5(() => {
10235
10475
  if (notice === null) return void 0;
10236
10476
  const timer = setTimeout(() => setNotice(null), notice.failed ? 7e3 : 3e3);
@@ -10259,16 +10499,16 @@ function ActivitiesControl({
10259
10499
  active,
10260
10500
  onOpen
10261
10501
  }) {
10262
- const [open, setOpen] = useState3(false);
10502
+ const [open, setOpen] = useState4(false);
10263
10503
  const available = useAvailableActivities();
10264
10504
  const attention = useActivityAttention();
10265
10505
  if (available.length === 0) return null;
10266
- return /* @__PURE__ */ jsxs2("span", { className: "mx-meet__anchor", children: [
10267
- /* @__PURE__ */ jsxs2(ControlButton, { label: "Activities", active: open || active !== null, onClick: () => setOpen(!open), children: [
10506
+ return /* @__PURE__ */ jsxs3("span", { className: "mx-meet__anchor", children: [
10507
+ /* @__PURE__ */ jsxs3(ControlButton, { label: "Activities", active: open || active !== null, onClick: () => setOpen(!open), children: [
10268
10508
  /* @__PURE__ */ jsx5(ActivitiesIcon, {}),
10269
10509
  attention ? /* @__PURE__ */ jsx5("span", { className: "mx-meet__dot", "aria-hidden": "true" }) : null
10270
10510
  ] }),
10271
- open ? /* @__PURE__ */ jsx5(Popover, { label: "Activities", onClose: () => setOpen(false), children: /* @__PURE__ */ jsx5("div", { className: "mx-meet__menu", role: "menu", children: available.map((panel) => /* @__PURE__ */ jsxs2(
10511
+ open ? /* @__PURE__ */ jsx5(Popover, { label: "Activities", onClose: () => setOpen(false), children: /* @__PURE__ */ jsx5("div", { className: "mx-meet__menu", role: "menu", children: available.map((panel) => /* @__PURE__ */ jsxs3(
10272
10512
  MenuItem,
10273
10513
  {
10274
10514
  onSelect: () => {
@@ -10287,11 +10527,11 @@ function ActivitiesControl({
10287
10527
  }
10288
10528
  function PollComposer({ maxOptions, onDone }) {
10289
10529
  const { act } = useCollab();
10290
- const [question, setQuestion] = useState3("");
10291
- const [options, setOptions] = useState3(["", ""]);
10292
- const [multiple, setMultiple] = useState3(false);
10293
- const [anonymous, setAnonymous] = useState3(false);
10294
- const [busy, setBusy] = useState3(false);
10530
+ const [question, setQuestion] = useState4("");
10531
+ const [options, setOptions] = useState4(["", ""]);
10532
+ const [multiple, setMultiple] = useState4(false);
10533
+ const [anonymous, setAnonymous] = useState4(false);
10534
+ const [busy, setBusy] = useState4(false);
10295
10535
  const [notice, show] = useNotice();
10296
10536
  const filled = options.map((o) => o.trim()).filter(Boolean);
10297
10537
  const ready = question.trim().length > 0 && filled.length >= 2;
@@ -10314,7 +10554,7 @@ function PollComposer({ maxOptions, onDone }) {
10314
10554
  setBusy(false);
10315
10555
  onDone();
10316
10556
  };
10317
- return /* @__PURE__ */ jsxs2(
10557
+ return /* @__PURE__ */ jsxs3(
10318
10558
  "form",
10319
10559
  {
10320
10560
  className: "mx-meet__collab-card",
@@ -10323,7 +10563,7 @@ function PollComposer({ maxOptions, onDone }) {
10323
10563
  if (ready) void save(true);
10324
10564
  },
10325
10565
  children: [
10326
- /* @__PURE__ */ jsxs2("label", { className: "mx-meet__field", children: [
10566
+ /* @__PURE__ */ jsxs3("label", { className: "mx-meet__field", children: [
10327
10567
  /* @__PURE__ */ jsx5("span", { className: "mx-meet__field-label", children: "Question" }),
10328
10568
  /* @__PURE__ */ jsx5(
10329
10569
  "input",
@@ -10337,7 +10577,7 @@ function PollComposer({ maxOptions, onDone }) {
10337
10577
  }
10338
10578
  )
10339
10579
  ] }),
10340
- options.map((option, index) => /* @__PURE__ */ jsxs2("div", { className: "mx-meet__composer-row", children: [
10580
+ options.map((option, index) => /* @__PURE__ */ jsxs3("div", { className: "mx-meet__composer-row", children: [
10341
10581
  /* @__PURE__ */ jsx5(
10342
10582
  "input",
10343
10583
  {
@@ -10352,16 +10592,16 @@ function PollComposer({ maxOptions, onDone }) {
10352
10592
  options.length > 2 ? /* @__PURE__ */ jsx5(ControlButton, { label: `Remove answer ${index + 1}`, onClick: () => setOptions(options.filter((_, i) => i !== index)), children: /* @__PURE__ */ jsx5(CloseIcon, { width: 14, height: 14 }) }) : null
10353
10593
  ] }, index)),
10354
10594
  options.length < maxOptions ? /* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__link", onClick: () => setOptions([...options, ""]), children: "Add an answer" }) : null,
10355
- /* @__PURE__ */ jsxs2("label", { className: "mx-meet__toggle", children: [
10595
+ /* @__PURE__ */ jsxs3("label", { className: "mx-meet__toggle", children: [
10356
10596
  /* @__PURE__ */ jsx5("input", { type: "checkbox", checked: multiple, onChange: (event) => setMultiple(event.target.checked) }),
10357
10597
  "People can pick more than one"
10358
10598
  ] }),
10359
- /* @__PURE__ */ jsxs2("label", { className: "mx-meet__toggle", children: [
10599
+ /* @__PURE__ */ jsxs3("label", { className: "mx-meet__toggle", children: [
10360
10600
  /* @__PURE__ */ jsx5("input", { type: "checkbox", checked: anonymous, onChange: (event) => setAnonymous(event.target.checked) }),
10361
10601
  "Anonymous \u2014 nobody sees who picked what"
10362
10602
  ] }),
10363
10603
  /* @__PURE__ */ jsx5(Notice, { notice }),
10364
- /* @__PURE__ */ jsxs2("div", { className: "mx-meet__collab-actions", children: [
10604
+ /* @__PURE__ */ jsxs3("div", { className: "mx-meet__collab-actions", children: [
10365
10605
  /* @__PURE__ */ jsx5("button", { type: "submit", className: "mx-meet__primary mx-meet__primary--small", disabled: !ready || busy, children: "Launch" }),
10366
10606
  /* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__chip", disabled: !ready || busy, onClick: () => void save(false), children: "Save draft" }),
10367
10607
  /* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__link", onClick: onDone, children: "Cancel" })
@@ -10372,7 +10612,7 @@ function PollComposer({ maxOptions, onDone }) {
10372
10612
  }
10373
10613
  function PollCard({ poll }) {
10374
10614
  const { act, isHost } = useCollab();
10375
- const [picked, setPicked] = useState3(poll.myVote.slice());
10615
+ const [picked, setPicked] = useState4(poll.myVote.slice());
10376
10616
  const [notice, show] = useNotice();
10377
10617
  useEffect5(() => setPicked(poll.myVote.slice()), [poll.myVote]);
10378
10618
  const counts = poll.options.some((o) => o.votes !== void 0);
@@ -10384,12 +10624,12 @@ function PollCard({ poll }) {
10384
10624
  if (!canVote) return;
10385
10625
  setPicked(poll.multiple ? picked.includes(id) ? picked.filter((p) => p !== id) : [...picked, id] : [id]);
10386
10626
  };
10387
- return /* @__PURE__ */ jsxs2("article", { className: "mx-meet__collab-card", "aria-label": poll.question, children: [
10388
- /* @__PURE__ */ jsxs2("header", { className: "mx-meet__collab-head", children: [
10627
+ return /* @__PURE__ */ jsxs3("article", { className: "mx-meet__collab-card", "aria-label": poll.question, children: [
10628
+ /* @__PURE__ */ jsxs3("header", { className: "mx-meet__collab-head", children: [
10389
10629
  /* @__PURE__ */ jsx5("strong", { className: "mx-meet__collab-title", children: poll.question }),
10390
10630
  /* @__PURE__ */ jsx5("span", { className: "mx-meet__collab-state", children: stateWord })
10391
10631
  ] }),
10392
- /* @__PURE__ */ jsxs2("p", { className: "mx-meet__panel-note", children: [
10632
+ /* @__PURE__ */ jsxs3("p", { className: "mx-meet__panel-note", children: [
10393
10633
  poll.multiple ? "Pick any." : "Pick one.",
10394
10634
  poll.anonymous ? " Anonymous." : "",
10395
10635
  counts && poll.voterCount !== null ? ` ${poll.voterCount} voted.` : "",
@@ -10398,8 +10638,8 @@ function PollCard({ poll }) {
10398
10638
  /* @__PURE__ */ jsx5("ul", { className: "mx-meet__poll-options", children: poll.options.map((option) => {
10399
10639
  const share = counts && total > 0 ? Math.round((option.votes ?? 0) / total * 100) : 0;
10400
10640
  const chosen = picked.includes(option.id);
10401
- return /* @__PURE__ */ jsxs2("li", { children: [
10402
- /* @__PURE__ */ jsxs2(
10641
+ return /* @__PURE__ */ jsxs3("li", { children: [
10642
+ /* @__PURE__ */ jsxs3(
10403
10643
  "button",
10404
10644
  {
10405
10645
  type: "button",
@@ -10410,7 +10650,7 @@ function PollCard({ poll }) {
10410
10650
  children: [
10411
10651
  counts ? /* @__PURE__ */ jsx5("span", { className: "mx-meet__poll-bar", style: { width: `${share}%` }, "aria-hidden": "true" }) : null,
10412
10652
  /* @__PURE__ */ jsx5("span", { className: "mx-meet__poll-text", children: option.text }),
10413
- counts ? /* @__PURE__ */ jsxs2("span", { className: "mx-meet__poll-count", children: [
10653
+ counts ? /* @__PURE__ */ jsxs3("span", { className: "mx-meet__poll-count", children: [
10414
10654
  option.votes ?? 0,
10415
10655
  " \xB7 ",
10416
10656
  share,
@@ -10423,7 +10663,7 @@ function PollCard({ poll }) {
10423
10663
  ] }, option.id);
10424
10664
  }) }),
10425
10665
  /* @__PURE__ */ jsx5(Notice, { notice }),
10426
- /* @__PURE__ */ jsxs2("div", { className: "mx-meet__collab-actions", children: [
10666
+ /* @__PURE__ */ jsxs3("div", { className: "mx-meet__collab-actions", children: [
10427
10667
  canVote ? /* @__PURE__ */ jsx5(
10428
10668
  "button",
10429
10669
  {
@@ -10443,11 +10683,11 @@ function PollCard({ poll }) {
10443
10683
  }
10444
10684
  function PollsPanel({ onClose }) {
10445
10685
  const { collab, isHost } = useCollab();
10446
- const [composing, setComposing] = useState3(false);
10686
+ const [composing, setComposing] = useState4(false);
10447
10687
  const polls = collab?.polls ?? [];
10448
10688
  const maxOptions = collab?.settings?.pollMaxOptions ?? 10;
10449
10689
  const ordered = [...polls].reverse();
10450
- return /* @__PURE__ */ jsxs2(PanelShell, { title: "Polls", onClose, children: [
10690
+ return /* @__PURE__ */ jsxs3(PanelShell, { title: "Polls", onClose, children: [
10451
10691
  collab?.error != null ? /* @__PURE__ */ jsx5("p", { className: "mx-meet__panel-note mx-meet__collab-error", children: collab.error }) : null,
10452
10692
  isHost && !composing ? /* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__primary mx-meet__primary--small", onClick: () => setComposing(true), children: "New poll" }) : null,
10453
10693
  isHost && composing ? /* @__PURE__ */ jsx5(PollComposer, { maxOptions, onDone: () => setComposing(false) }) : null,
@@ -10457,12 +10697,12 @@ function PollsPanel({ onClose }) {
10457
10697
  }
10458
10698
  function QuestionCard({ question }) {
10459
10699
  const { act, isHost } = useCollab();
10460
- const [answering, setAnswering] = useState3(false);
10461
- const [reply, setReply] = useState3("");
10700
+ const [answering, setAnswering] = useState4(false);
10701
+ const [reply, setReply] = useState4("");
10462
10702
  const [notice, show] = useNotice();
10463
- return /* @__PURE__ */ jsxs2("li", { className: `mx-meet__collab-card mx-meet__question mx-meet__question--${question.state}`, children: [
10464
- /* @__PURE__ */ jsxs2("div", { className: "mx-meet__question-row", children: [
10465
- /* @__PURE__ */ jsxs2(
10703
+ return /* @__PURE__ */ jsxs3("li", { className: `mx-meet__collab-card mx-meet__question mx-meet__question--${question.state}`, children: [
10704
+ /* @__PURE__ */ jsxs3("div", { className: "mx-meet__question-row", children: [
10705
+ /* @__PURE__ */ jsxs3(
10466
10706
  "button",
10467
10707
  {
10468
10708
  type: "button",
@@ -10477,15 +10717,15 @@ function QuestionCard({ question }) {
10477
10717
  ]
10478
10718
  }
10479
10719
  ),
10480
- /* @__PURE__ */ jsxs2("div", { className: "mx-meet__question-body", children: [
10481
- /* @__PURE__ */ jsxs2("span", { className: "mx-meet__chat-meta", children: [
10720
+ /* @__PURE__ */ jsxs3("div", { className: "mx-meet__question-body", children: [
10721
+ /* @__PURE__ */ jsxs3("span", { className: "mx-meet__chat-meta", children: [
10482
10722
  /* @__PURE__ */ jsx5("strong", { children: question.mine ? "You" : question.askerName }),
10483
10723
  question.mine && question.anonymous ? /* @__PURE__ */ jsx5("span", { className: "mx-meet__chat-private", children: "anonymous" }) : null,
10484
10724
  question.state !== "open" ? /* @__PURE__ */ jsx5("span", { className: "mx-meet__collab-state", children: question.state === "answered" ? "Answered" : "Dismissed" }) : null
10485
10725
  ] }),
10486
10726
  /* @__PURE__ */ jsx5("span", { className: "mx-meet__chat-text", children: question.text }),
10487
- question.answer !== null ? /* @__PURE__ */ jsxs2("span", { className: "mx-meet__question-answer", children: [
10488
- /* @__PURE__ */ jsxs2("strong", { children: [
10727
+ question.answer !== null ? /* @__PURE__ */ jsxs3("span", { className: "mx-meet__question-answer", children: [
10728
+ /* @__PURE__ */ jsxs3("strong", { children: [
10489
10729
  question.answeredByName ?? "Host",
10490
10730
  ":"
10491
10731
  ] }),
@@ -10494,7 +10734,7 @@ function QuestionCard({ question }) {
10494
10734
  ] }) : null
10495
10735
  ] })
10496
10736
  ] }),
10497
- answering ? /* @__PURE__ */ jsxs2(
10737
+ answering ? /* @__PURE__ */ jsxs3(
10498
10738
  "form",
10499
10739
  {
10500
10740
  className: "mx-meet__composer-row",
@@ -10526,7 +10766,7 @@ function QuestionCard({ question }) {
10526
10766
  }
10527
10767
  ) : null,
10528
10768
  /* @__PURE__ */ jsx5(Notice, { notice }),
10529
- isHost || question.mine ? /* @__PURE__ */ jsxs2("div", { className: "mx-meet__collab-actions", children: [
10769
+ isHost || question.mine ? /* @__PURE__ */ jsxs3("div", { className: "mx-meet__collab-actions", children: [
10530
10770
  isHost && question.state === "open" && !answering ? /* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__chip", onClick: () => setAnswering(true), children: "Answer" }) : null,
10531
10771
  isHost && question.state === "open" ? /* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__chip", onClick: () => void act({ action: "question_dismiss", itemId: question.id }).then(show), children: "Dismiss" }) : null,
10532
10772
  isHost && question.state !== "open" ? /* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__chip", onClick: () => void act({ action: "question_reopen", itemId: question.id }).then(show), children: "Reopen" }) : null,
@@ -10536,9 +10776,9 @@ function QuestionCard({ question }) {
10536
10776
  }
10537
10777
  function QaPanel({ onClose }) {
10538
10778
  const { collab, act } = useCollab();
10539
- const [draft, setDraft] = useState3("");
10540
- const [anonymous, setAnonymous] = useState3(false);
10541
- const [order, setOrder] = useState3("popular");
10779
+ const [draft, setDraft] = useState4("");
10780
+ const [anonymous, setAnonymous] = useState4(false);
10781
+ const [order, setOrder] = useState4("popular");
10542
10782
  const [notice, show] = useNotice();
10543
10783
  const allowAnonymous = collab?.settings?.qaAnonymousAllowed === true;
10544
10784
  const questions = [...collab?.questions ?? []];
@@ -10546,9 +10786,9 @@ function QaPanel({ onClose }) {
10546
10786
  questions.sort(
10547
10787
  (a, b) => rank(a) !== rank(b) ? rank(a) - rank(b) : order === "popular" ? b.upvotes - a.upvotes || (b.createdAt ?? "").localeCompare(a.createdAt ?? "") : (b.createdAt ?? "").localeCompare(a.createdAt ?? "")
10548
10788
  );
10549
- return /* @__PURE__ */ jsxs2(PanelShell, { title: "Q&A", onClose, children: [
10789
+ return /* @__PURE__ */ jsxs3(PanelShell, { title: "Q&A", onClose, children: [
10550
10790
  collab?.error != null ? /* @__PURE__ */ jsx5("p", { className: "mx-meet__panel-note mx-meet__collab-error", children: collab.error }) : null,
10551
- /* @__PURE__ */ jsxs2(
10791
+ /* @__PURE__ */ jsxs3(
10552
10792
  "form",
10553
10793
  {
10554
10794
  className: "mx-meet__composer mx-meet__composer--chat",
@@ -10562,7 +10802,7 @@ function QaPanel({ onClose }) {
10562
10802
  });
10563
10803
  },
10564
10804
  children: [
10565
- /* @__PURE__ */ jsxs2("div", { className: "mx-meet__composer-row", children: [
10805
+ /* @__PURE__ */ jsxs3("div", { className: "mx-meet__composer-row", children: [
10566
10806
  /* @__PURE__ */ jsx5(
10567
10807
  "input",
10568
10808
  {
@@ -10576,7 +10816,7 @@ function QaPanel({ onClose }) {
10576
10816
  ),
10577
10817
  /* @__PURE__ */ jsx5("button", { type: "submit", className: "mx-meet__send", disabled: draft.trim().length === 0, children: "Ask" })
10578
10818
  ] }),
10579
- allowAnonymous ? /* @__PURE__ */ jsxs2("label", { className: "mx-meet__toggle", children: [
10819
+ allowAnonymous ? /* @__PURE__ */ jsxs3("label", { className: "mx-meet__toggle", children: [
10580
10820
  /* @__PURE__ */ jsx5("input", { type: "checkbox", checked: anonymous, onChange: (event) => setAnonymous(event.target.checked) }),
10581
10821
  "Ask anonymously"
10582
10822
  ] }) : null
@@ -10627,10 +10867,10 @@ function StrokeView({ stroke, onPick }) {
10627
10867
  }
10628
10868
  function WhiteboardPanel({ onClose }) {
10629
10869
  const { collab, act, isHost, localIdentity } = useCollab();
10630
- const [tool, setTool] = useState3("pen");
10631
- const [color, setColor] = useState3(INK[0]);
10632
- const [drawing, setDrawing] = useState3(null);
10633
- const [pending, setPending] = useState3([]);
10870
+ const [tool, setTool] = useState4("pen");
10871
+ const [color, setColor] = useState4(INK[0]);
10872
+ const [drawing, setDrawing] = useState4(null);
10873
+ const [pending, setPending] = useState4([]);
10634
10874
  const [notice, show] = useNotice();
10635
10875
  const svgRef = useRef5(null);
10636
10876
  const strokes = collab?.strokes ?? [];
@@ -10664,8 +10904,8 @@ function WhiteboardPanel({ onClose }) {
10664
10904
  if (!result.ok) show(result);
10665
10905
  });
10666
10906
  };
10667
- return /* @__PURE__ */ jsxs2("section", { className: "mx-meet__whiteboard", "aria-label": "Whiteboard", children: [
10668
- /* @__PURE__ */ jsxs2("header", { className: "mx-meet__whiteboard-bar", children: [
10907
+ return /* @__PURE__ */ jsxs3("section", { className: "mx-meet__whiteboard", "aria-label": "Whiteboard", children: [
10908
+ /* @__PURE__ */ jsxs3("header", { className: "mx-meet__whiteboard-bar", children: [
10669
10909
  /* @__PURE__ */ jsx5("strong", { className: "mx-meet__panel-title", children: "Whiteboard" }),
10670
10910
  /* @__PURE__ */ jsx5("div", { className: "mx-meet__pills", role: "group", "aria-label": "Tool", children: [
10671
10911
  ["pen", "Pen", /* @__PURE__ */ jsx5(PencilIcon, { width: 16, height: 16 }, "p")],
@@ -10715,7 +10955,7 @@ function WhiteboardPanel({ onClose }) {
10715
10955
  /* @__PURE__ */ jsx5(ControlButton, { label: "Close whiteboard", onClick: onClose, children: /* @__PURE__ */ jsx5(CloseIcon, { width: 16, height: 16 }) })
10716
10956
  ] }),
10717
10957
  /* @__PURE__ */ jsx5(Notice, { notice }),
10718
- /* @__PURE__ */ jsxs2(
10958
+ /* @__PURE__ */ jsxs3(
10719
10959
  "svg",
10720
10960
  {
10721
10961
  ref: svgRef,
@@ -10773,7 +11013,7 @@ function clock(ms2) {
10773
11013
  }
10774
11014
  var BREAKOUT_EXPIRE_RETRY_MS = 5e3;
10775
11015
  function useNow(active) {
10776
- const [now, setNow] = useState3(() => Date.now());
11016
+ const [now, setNow] = useState4(() => Date.now());
10777
11017
  useEffect5(() => {
10778
11018
  if (!active) return void 0;
10779
11019
  const timer = setInterval(() => setNow(Date.now()), 1e3);
@@ -10788,11 +11028,11 @@ function BreakoutSetup() {
10788
11028
  const people = (snapshot?.participants ?? []).filter(
10789
11029
  (p) => !p.isAgent && p.role !== "host" && p.role !== "cohost"
10790
11030
  );
10791
- const [count2, setCount] = useState3(Math.min(Math.max(2, Math.ceil(people.length / 4)), settings?.breakoutMaxRooms ?? 20));
10792
- const [mode, setMode] = useState3("auto");
10793
- const [minutes, setMinutes] = useState3(settings?.breakoutDefaultMinutes ?? 15);
10794
- const [manual, setManual] = useState3({});
10795
- const [busy, setBusy] = useState3(false);
11031
+ const [count2, setCount] = useState4(Math.min(Math.max(2, Math.ceil(people.length / 4)), settings?.breakoutMaxRooms ?? 20));
11032
+ const [mode, setMode] = useState4("auto");
11033
+ const [minutes, setMinutes] = useState4(settings?.breakoutDefaultMinutes ?? 15);
11034
+ const [manual, setManual] = useState4({});
11035
+ const [busy, setBusy] = useState4(false);
10796
11036
  const [notice, show] = useNotice();
10797
11037
  const max = settings?.breakoutMaxRooms ?? 20;
10798
11038
  const rooms = Math.min(Math.max(1, count2), max);
@@ -10804,8 +11044,8 @@ function BreakoutSetup() {
10804
11044
  (_, index) => people.filter((p) => (manual[p.identity] ?? -1) === index).map((p) => p.identity)
10805
11045
  ) : Array.from({ length: rooms }, () => []);
10806
11046
  const nameOf = (identity) => people.find((p) => p.identity === identity)?.displayName ?? identity;
10807
- return /* @__PURE__ */ jsxs2("div", { className: "mx-meet__collab-card", children: [
10808
- /* @__PURE__ */ jsxs2("label", { className: "mx-meet__field", children: [
11047
+ return /* @__PURE__ */ jsxs3("div", { className: "mx-meet__collab-card", children: [
11048
+ /* @__PURE__ */ jsxs3("label", { className: "mx-meet__field", children: [
10809
11049
  /* @__PURE__ */ jsx5("span", { className: "mx-meet__field-label", children: "Rooms" }),
10810
11050
  /* @__PURE__ */ jsx5(
10811
11051
  "input",
@@ -10834,7 +11074,7 @@ function BreakoutSetup() {
10834
11074
  },
10835
11075
  value
10836
11076
  )) }),
10837
- /* @__PURE__ */ jsxs2("label", { className: "mx-meet__field", children: [
11077
+ /* @__PURE__ */ jsxs3("label", { className: "mx-meet__field", children: [
10838
11078
  /* @__PURE__ */ jsx5("span", { className: "mx-meet__field-label", children: "Timer (minutes, 0 for none)" }),
10839
11079
  /* @__PURE__ */ jsx5(
10840
11080
  "input",
@@ -10848,9 +11088,9 @@ function BreakoutSetup() {
10848
11088
  }
10849
11089
  )
10850
11090
  ] }),
10851
- mode === "manual" ? people.length === 0 ? /* @__PURE__ */ jsx5("p", { className: "mx-meet__panel-note", children: "Nobody else is in the meeting yet." }) : /* @__PURE__ */ jsx5("ul", { className: "mx-meet__people", children: people.map((person) => /* @__PURE__ */ jsxs2("li", { className: "mx-meet__person", children: [
11091
+ mode === "manual" ? people.length === 0 ? /* @__PURE__ */ jsx5("p", { className: "mx-meet__panel-note", children: "Nobody else is in the meeting yet." }) : /* @__PURE__ */ jsx5("ul", { className: "mx-meet__people", children: people.map((person) => /* @__PURE__ */ jsxs3("li", { className: "mx-meet__person", children: [
10852
11092
  /* @__PURE__ */ jsx5("span", { className: "mx-meet__person-name", children: person.displayName }),
10853
- /* @__PURE__ */ jsxs2(
11093
+ /* @__PURE__ */ jsxs3(
10854
11094
  "select",
10855
11095
  {
10856
11096
  className: "mx-meet__select mx-meet__select--compact",
@@ -10859,15 +11099,15 @@ function BreakoutSetup() {
10859
11099
  onChange: (event) => setManual({ ...manual, [person.identity]: Number(event.target.value) }),
10860
11100
  children: [
10861
11101
  /* @__PURE__ */ jsx5("option", { value: -1, children: "Main room" }),
10862
- Array.from({ length: rooms }, (_, index) => /* @__PURE__ */ jsxs2("option", { value: index, children: [
11102
+ Array.from({ length: rooms }, (_, index) => /* @__PURE__ */ jsxs3("option", { value: index, children: [
10863
11103
  "Room ",
10864
11104
  index + 1
10865
11105
  ] }, index))
10866
11106
  ]
10867
11107
  }
10868
11108
  )
10869
- ] }, person.identity)) }) : mode === "auto" ? /* @__PURE__ */ jsx5("ul", { className: "mx-meet__breakout-rooms", children: assignment.map((members, index) => /* @__PURE__ */ jsxs2("li", { children: [
10870
- /* @__PURE__ */ jsxs2("strong", { children: [
11109
+ ] }, person.identity)) }) : mode === "auto" ? /* @__PURE__ */ jsx5("ul", { className: "mx-meet__breakout-rooms", children: assignment.map((members, index) => /* @__PURE__ */ jsxs3("li", { children: [
11110
+ /* @__PURE__ */ jsxs3("strong", { children: [
10871
11111
  "Room ",
10872
11112
  index + 1
10873
11113
  ] }),
@@ -10875,7 +11115,7 @@ function BreakoutSetup() {
10875
11115
  /* @__PURE__ */ jsx5("span", { className: "mx-meet__panel-note", children: members.length === 0 ? "empty" : members.map(nameOf).join(", ") })
10876
11116
  ] }, index)) }) : /* @__PURE__ */ jsx5("p", { className: "mx-meet__panel-note", children: "Everyone picks a room from their own screen." }),
10877
11117
  /* @__PURE__ */ jsx5(Notice, { notice }),
10878
- /* @__PURE__ */ jsxs2(
11118
+ /* @__PURE__ */ jsxs3(
10879
11119
  "button",
10880
11120
  {
10881
11121
  type: "button",
@@ -10908,7 +11148,7 @@ function BreakoutRun({ plan }) {
10908
11148
  const snapshot = useMeetSnapshot();
10909
11149
  const now = useNow(plan.endsAt !== null);
10910
11150
  const remaining = breakoutRemainingMs(plan, now);
10911
- const [broadcast, setBroadcast] = useState3("");
11151
+ const [broadcast, setBroadcast] = useState4("");
10912
11152
  const [notice, show] = useNotice();
10913
11153
  const nameOf = (identity) => displayNameFor(snapshot?.names ?? {}, identity, snapshot?.participants.find((p) => p.identity === identity)?.displayName);
10914
11154
  const mine = assignedRoom(plan, localIdentity);
@@ -10920,8 +11160,8 @@ function BreakoutRun({ plan }) {
10920
11160
  }
10921
11161
  show(await moveTo(roomId));
10922
11162
  };
10923
- return /* @__PURE__ */ jsxs2("div", { className: "mx-meet__collab-card", children: [
10924
- /* @__PURE__ */ jsxs2("p", { className: "mx-meet__panel-note", children: [
11163
+ return /* @__PURE__ */ jsxs3("div", { className: "mx-meet__collab-card", children: [
11164
+ /* @__PURE__ */ jsxs3("p", { className: "mx-meet__panel-note", children: [
10925
11165
  plan.rooms.length,
10926
11166
  " room",
10927
11167
  plan.rooms.length === 1 ? "" : "s",
@@ -10932,15 +11172,15 @@ function BreakoutRun({ plan }) {
10932
11172
  /* @__PURE__ */ jsx5("ul", { className: "mx-meet__breakout-rooms", children: plan.rooms.map((room) => {
10933
11173
  const here = breakoutRoomId === room.id;
10934
11174
  const mayJoin = isHost || plan.allowChoose || mine?.id === room.id;
10935
- return /* @__PURE__ */ jsxs2("li", { className: here ? "mx-meet__breakout-room mx-meet__breakout-room--here" : "mx-meet__breakout-room", children: [
10936
- /* @__PURE__ */ jsxs2("div", { className: "mx-meet__collab-head", children: [
11175
+ return /* @__PURE__ */ jsxs3("li", { className: here ? "mx-meet__breakout-room mx-meet__breakout-room--here" : "mx-meet__breakout-room", children: [
11176
+ /* @__PURE__ */ jsxs3("div", { className: "mx-meet__collab-head", children: [
10937
11177
  /* @__PURE__ */ jsx5("strong", { children: room.name }),
10938
11178
  here ? /* @__PURE__ */ jsx5("span", { className: "mx-meet__collab-state", children: "You are here" }) : mayJoin ? /* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__chip", onClick: () => void join(room.id), children: "Join" }) : null
10939
11179
  ] }),
10940
11180
  /* @__PURE__ */ jsx5("span", { className: "mx-meet__panel-note", children: room.identities.length === 0 ? "Nobody assigned" : room.identities.map(nameOf).join(", ") }),
10941
- isHost && room.identities.length > 0 ? /* @__PURE__ */ jsx5("ul", { className: "mx-meet__people", children: room.identities.map((identity) => /* @__PURE__ */ jsxs2("li", { className: "mx-meet__person", children: [
11181
+ isHost && room.identities.length > 0 ? /* @__PURE__ */ jsx5("ul", { className: "mx-meet__people", children: room.identities.map((identity) => /* @__PURE__ */ jsxs3("li", { className: "mx-meet__person", children: [
10942
11182
  /* @__PURE__ */ jsx5("span", { className: "mx-meet__person-name", children: nameOf(identity) }),
10943
- /* @__PURE__ */ jsxs2(
11183
+ /* @__PURE__ */ jsxs3(
10944
11184
  "select",
10945
11185
  {
10946
11186
  className: "mx-meet__select mx-meet__select--compact",
@@ -10961,7 +11201,7 @@ function BreakoutRun({ plan }) {
10961
11201
  ] }, room.id);
10962
11202
  }) }),
10963
11203
  breakoutRoomId !== null ? /* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__chip", onClick: () => void join(null), children: "Return to the main room" }) : null,
10964
- isHost ? /* @__PURE__ */ jsxs2(
11204
+ isHost ? /* @__PURE__ */ jsxs3(
10965
11205
  "form",
10966
11206
  {
10967
11207
  className: "mx-meet__composer-row",
@@ -11005,7 +11245,7 @@ function BreakoutRun({ plan }) {
11005
11245
  function BreakoutsPanel({ onClose }) {
11006
11246
  const { collab, isHost } = useCollab();
11007
11247
  const plan = collab?.breakout?.state === "open" ? collab.breakout : null;
11008
- return /* @__PURE__ */ jsxs2(PanelShell, { title: "Breakout rooms", onClose, children: [
11248
+ return /* @__PURE__ */ jsxs3(PanelShell, { title: "Breakout rooms", onClose, children: [
11009
11249
  collab?.error != null ? /* @__PURE__ */ jsx5("p", { className: "mx-meet__panel-note mx-meet__collab-error", children: collab.error }) : null,
11010
11250
  plan !== null ? /* @__PURE__ */ jsx5(BreakoutRun, { plan }) : isHost ? /* @__PURE__ */ jsx5(BreakoutSetup, {}) : /* @__PURE__ */ jsx5("p", { className: "mx-meet__panel-note", children: "Breakout rooms are closed." })
11011
11251
  ] });
@@ -11019,12 +11259,12 @@ function BreakoutBanner() {
11019
11259
  const remaining = breakoutRemainingMs(open, now);
11020
11260
  const closing = breakoutClosingMs(open, now);
11021
11261
  const assigned = assignedRoom(open, localIdentity);
11022
- const [later, setLater] = useState3(null);
11023
- const [autoSince, setAutoSince] = useState3(null);
11262
+ const [later, setLater] = useState4(null);
11263
+ const [autoSince, setAutoSince] = useState4(null);
11024
11264
  const AUTO_MOVE_MS = 1e4;
11025
11265
  const autoLeft = open?.moveMode === "auto" && assigned !== null && autoSince?.id === open.id && later !== open.id ? Math.max(0, AUTO_MOVE_MS - (now - autoSince.at)) : null;
11026
- const [dismissedBroadcast, setDismissedBroadcast] = useState3(null);
11027
- const [failure, setFailure] = useState3(null);
11266
+ const [dismissedBroadcast, setDismissedBroadcast] = useState4(null);
11267
+ const [failure, setFailure] = useState4(null);
11028
11268
  const expireAsked = useRef5(null);
11029
11269
  const moveAt = collab?.moveRequest?.at ?? null;
11030
11270
  useEffect5(() => {
@@ -11059,29 +11299,29 @@ function BreakoutBanner() {
11059
11299
  const showBroadcast = broadcast !== null && broadcast.at !== dismissedBroadcast && open !== null;
11060
11300
  const room = open?.rooms.find((r) => r.id === breakoutRoomId) ?? null;
11061
11301
  if (open === null && failure === null) return null;
11062
- return /* @__PURE__ */ jsxs2("div", { className: "mx-meet__breakout-banner", role: "status", children: [
11302
+ return /* @__PURE__ */ jsxs3("div", { className: "mx-meet__breakout-banner", role: "status", children: [
11063
11303
  failure !== null ? /* @__PURE__ */ jsx5("span", { className: "mx-meet__collab-error", children: failure }) : null,
11064
- closing !== null ? /* @__PURE__ */ jsxs2("span", { role: "status", "data-meet-notice": "breakout-closing", children: [
11304
+ closing !== null ? /* @__PURE__ */ jsxs3("span", { role: "status", "data-meet-notice": "breakout-closing", children: [
11065
11305
  "Rooms closing in ",
11066
11306
  Math.ceil(closing / 1e3),
11067
11307
  room !== null ? " \u2014 you return to the main meeting" : ""
11068
11308
  ] }) : null,
11069
- room !== null ? /* @__PURE__ */ jsxs2("span", { children: [
11309
+ room !== null ? /* @__PURE__ */ jsxs3("span", { children: [
11070
11310
  /* @__PURE__ */ jsx5("strong", { children: room.name }),
11071
11311
  remaining !== null && closing === null ? ` \xB7 ${clock(remaining)} left` : "",
11072
11312
  /* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__chip", onClick: () => void moveTo(null), children: "Return to main room" })
11073
- ] }) : assigned !== null && later !== open?.id ? /* @__PURE__ */ jsxs2("span", { children: [
11313
+ ] }) : assigned !== null && later !== open?.id ? /* @__PURE__ */ jsxs3("span", { children: [
11074
11314
  autoLeft !== null ? `You're being moved to ${assigned.name} in ${Math.ceil(autoLeft / 1e3)} s` : `You're invited to ${assigned.name}`,
11075
11315
  remaining !== null && closing === null ? ` \xB7 ${clock(remaining)} left` : "",
11076
11316
  /* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__primary mx-meet__primary--small", onClick: () => void joinAssigned(), children: "Join room" }),
11077
11317
  /* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__chip", onClick: () => setLater(open?.id ?? null), children: "Later" })
11078
- ] }) : assigned !== null ? /* @__PURE__ */ jsxs2("span", { children: [
11318
+ ] }) : assigned !== null ? /* @__PURE__ */ jsxs3("span", { children: [
11079
11319
  assigned.name,
11080
11320
  " is open",
11081
11321
  /* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__chip", onClick: () => void joinAssigned(), children: "Join room" })
11082
11322
  ] }) : open?.allowChoose ? /* @__PURE__ */ jsx5("span", { children: "Rooms are open \u2014 pick one under Activities." }) : null,
11083
- showBroadcast ? /* @__PURE__ */ jsxs2("span", { className: "mx-meet__breakout-broadcast", children: [
11084
- /* @__PURE__ */ jsxs2("strong", { children: [
11323
+ showBroadcast ? /* @__PURE__ */ jsxs3("span", { className: "mx-meet__breakout-broadcast", children: [
11324
+ /* @__PURE__ */ jsxs3("strong", { children: [
11085
11325
  broadcast.by,
11086
11326
  ":"
11087
11327
  ] }),
@@ -11101,10 +11341,10 @@ function CaptionLanguageSettings() {
11101
11341
  const preferred = defaultCaptionLanguage(settings, viewer);
11102
11342
  const current = collab?.captionLanguage ?? "";
11103
11343
  const choices = CAPTION_LANGUAGES.some((l) => l.tag === preferred) ? CAPTION_LANGUAGES : [{ tag: preferred, name: preferred }, ...CAPTION_LANGUAGES];
11104
- return /* @__PURE__ */ jsxs2("section", { className: "mx-meet__section", "aria-label": "Captions", children: [
11105
- /* @__PURE__ */ jsxs2("label", { className: "mx-meet__field", children: [
11344
+ return /* @__PURE__ */ jsxs3("section", { className: "mx-meet__section", "aria-label": "Captions", children: [
11345
+ /* @__PURE__ */ jsxs3("label", { className: "mx-meet__field", children: [
11106
11346
  /* @__PURE__ */ jsx5("span", { className: "mx-meet__field-label", children: "Translate captions to" }),
11107
- /* @__PURE__ */ jsxs2(
11347
+ /* @__PURE__ */ jsxs3(
11108
11348
  "select",
11109
11349
  {
11110
11350
  className: "mx-meet__select",
@@ -11115,7 +11355,7 @@ function CaptionLanguageSettings() {
11115
11355
  },
11116
11356
  children: [
11117
11357
  /* @__PURE__ */ jsx5("option", { value: "", children: "Off \u2014 as spoken" }),
11118
- current === "" ? /* @__PURE__ */ jsxs2("option", { value: preferred, children: [
11358
+ current === "" ? /* @__PURE__ */ jsxs3("option", { value: preferred, children: [
11119
11359
  choices.find((c) => c.tag === preferred)?.name ?? preferred,
11120
11360
  " (yours)"
11121
11361
  ] }) : null,
@@ -11156,10 +11396,10 @@ function TakeNotesControl() {
11156
11396
  }
11157
11397
 
11158
11398
  // src/skins/meet/components.tsx
11159
- import { Fragment, jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
11399
+ import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
11160
11400
  function InertNotice({ what }) {
11161
- return /* @__PURE__ */ jsxs3("div", { className: "mx-meet__empty", role: "status", children: [
11162
- /* @__PURE__ */ jsxs3("p", { className: "mx-meet__empty-title", children: [
11401
+ return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__empty", role: "status", children: [
11402
+ /* @__PURE__ */ jsxs4("p", { className: "mx-meet__empty-title", children: [
11163
11403
  what,
11164
11404
  " is not ready yet"
11165
11405
  ] }),
@@ -11229,7 +11469,7 @@ function RecordingIndicator() {
11229
11469
  const { state, label, canStart } = useRecording();
11230
11470
  const snapshot = useMeetSnapshot();
11231
11471
  const previous = useRef6(state);
11232
- const [stoppedAt, setStoppedAt] = useState4(null);
11472
+ const [stoppedAt, setStoppedAt] = useState5(null);
11233
11473
  useEffect6(() => {
11234
11474
  const was = previous.current;
11235
11475
  previous.current = state;
@@ -11242,8 +11482,8 @@ function RecordingIndicator() {
11242
11482
  }, [state]);
11243
11483
  const meetingId = snapshot?.meeting?.id ?? null;
11244
11484
  if (label === null && stoppedAt === null) return null;
11245
- return /* @__PURE__ */ jsxs3(Fragment, { children: [
11246
- label !== null ? /* @__PURE__ */ jsxs3(
11485
+ return /* @__PURE__ */ jsxs4(Fragment, { children: [
11486
+ label !== null ? /* @__PURE__ */ jsxs4(
11247
11487
  "span",
11248
11488
  {
11249
11489
  className: `mx-meet__recording mx-meet__recording--${state}`,
@@ -11280,7 +11520,7 @@ function ParticipantTile({
11280
11520
  const host = useMeetHost();
11281
11521
  const snapshot = useMeetSnapshot();
11282
11522
  const queue = useHandQueue();
11283
- const [menu, setMenu] = useState4(false);
11523
+ const [menu, setMenu] = useState5(false);
11284
11524
  const videoRef = useTrack(
11285
11525
  participant.identity,
11286
11526
  participant.screenSharing ? "screen" : "camera"
@@ -11290,7 +11530,7 @@ function ParticipantTile({
11290
11530
  const spotlit = snapshot?.spotlight === participant.identity;
11291
11531
  const presenting = snapshot?.presenter === participant.identity;
11292
11532
  const handPosition = participant.handRaised ? queue.findIndex((entry) => entry.identity === participant.identity) + 1 : 0;
11293
- return /* @__PURE__ */ jsxs3(
11533
+ return /* @__PURE__ */ jsxs4(
11294
11534
  "div",
11295
11535
  {
11296
11536
  className: [
@@ -11313,12 +11553,12 @@ function ParticipantTile({
11313
11553
  }
11314
11554
  ) : /* @__PURE__ */ jsx6("div", { className: "mx-meet__tile-placeholder", children: /* @__PURE__ */ jsx6(Avatar, { name: participant.displayName, url: participant.avatarUrl, size: featured ? 96 : 56 }) }),
11315
11555
  presenting ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__tile-presenting", role: "status", children: participant.isLocal ? "You are presenting" : `${participant.displayName} is presenting` }) : null,
11316
- participant.handRaised ? /* @__PURE__ */ jsxs3("span", { className: "mx-meet__tile-hand", title: `Hand raised \xB7 ${ordinal(handPosition)} in line`, children: [
11556
+ participant.handRaised ? /* @__PURE__ */ jsxs4("span", { className: "mx-meet__tile-hand", title: `Hand raised \xB7 ${ordinal(handPosition)} in line`, children: [
11317
11557
  /* @__PURE__ */ jsx6(HandIcon, { width: 14, height: 14 }),
11318
11558
  handPosition > 0 ? handPosition : null
11319
11559
  ] }) : null,
11320
- /* @__PURE__ */ jsxs3("div", { className: "mx-meet__tile-bar", children: [
11321
- /* @__PURE__ */ jsxs3("span", { className: "mx-meet__tile-name", children: [
11560
+ /* @__PURE__ */ jsxs4("div", { className: "mx-meet__tile-bar", children: [
11561
+ /* @__PURE__ */ jsxs4("span", { className: "mx-meet__tile-name", children: [
11322
11562
  spotlit ? /* @__PURE__ */ jsx6("span", { title: "Spotlighted for everyone", className: "mx-meet__tile-flag", children: /* @__PURE__ */ jsx6(SpotlightIcon, { width: 12, height: 12 }) }) : null,
11323
11563
  participant.displayName,
11324
11564
  participant.isLocal ? " (you)" : "",
@@ -11329,7 +11569,7 @@ function ParticipantTile({
11329
11569
  !participant.micEnabled ? /* @__PURE__ */ jsx6(MicOffIcon, { width: 14, height: 14 }) : null,
11330
11570
  /* @__PURE__ */ jsx6(QualityBars, { quality: participant.quality })
11331
11571
  ] }),
11332
- /* @__PURE__ */ jsxs3("div", { className: menu ? "mx-meet__tile-actions mx-meet__tile-actions--open" : "mx-meet__tile-actions", children: [
11572
+ /* @__PURE__ */ jsxs4("div", { className: menu ? "mx-meet__tile-actions mx-meet__tile-actions--open" : "mx-meet__tile-actions", children: [
11333
11573
  /* @__PURE__ */ jsx6(
11334
11574
  ControlButton,
11335
11575
  {
@@ -11339,7 +11579,7 @@ function ParticipantTile({
11339
11579
  children: /* @__PURE__ */ jsx6(PinIcon, { width: 16, height: 16 })
11340
11580
  }
11341
11581
  ),
11342
- /* @__PURE__ */ jsxs3("span", { className: "mx-meet__anchor", children: [
11582
+ /* @__PURE__ */ jsxs4("span", { className: "mx-meet__anchor", children: [
11343
11583
  /* @__PURE__ */ jsx6(
11344
11584
  ControlButton,
11345
11585
  {
@@ -11377,12 +11617,12 @@ function Stage({ pageSize }) {
11377
11617
  const stage = useStage(pageSize);
11378
11618
  const columns = gridColumns(stage.tiles.length);
11379
11619
  if (stage.feature === null && stage.tiles.length === 0) {
11380
- return /* @__PURE__ */ jsxs3("div", { className: "mx-meet__stage mx-meet__stage--empty", children: [
11620
+ return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__stage mx-meet__stage--empty", children: [
11381
11621
  /* @__PURE__ */ jsx6("p", { className: "mx-meet__empty-title", children: "Waiting for others to join" }),
11382
11622
  /* @__PURE__ */ jsx6("p", { className: "mx-meet__empty-body", children: "Share the meeting link and people can join from anywhere \u2014 no account needed." })
11383
11623
  ] });
11384
11624
  }
11385
- return /* @__PURE__ */ jsxs3("div", { className: `mx-meet__stage${stage.feature !== null ? " mx-meet__stage--speaker" : ""}`, children: [
11625
+ return /* @__PURE__ */ jsxs4("div", { className: `mx-meet__stage${stage.feature !== null ? " mx-meet__stage--speaker" : ""}`, children: [
11386
11626
  stage.feature !== null ? /* @__PURE__ */ jsx6(ParticipantTile, { participant: stage.feature, featured: true }) : null,
11387
11627
  /* @__PURE__ */ jsx6(
11388
11628
  "div",
@@ -11392,7 +11632,7 @@ function Stage({ pageSize }) {
11392
11632
  children: stage.tiles.map((participant) => /* @__PURE__ */ jsx6(ParticipantTile, { participant }, participant.identity))
11393
11633
  }
11394
11634
  ),
11395
- stage.overflow > 0 ? /* @__PURE__ */ jsxs3("p", { className: "mx-meet__overflow", children: [
11635
+ stage.overflow > 0 ? /* @__PURE__ */ jsxs4("p", { className: "mx-meet__overflow", children: [
11396
11636
  "+",
11397
11637
  stage.overflow,
11398
11638
  " more ",
@@ -11404,10 +11644,10 @@ function Stage({ pageSize }) {
11404
11644
  function ControlBar({ onLeave }) {
11405
11645
  const room = useRoom();
11406
11646
  const recording = useRecording();
11407
- const [panel, setPanel] = useState4("none");
11408
- const [chatTo, setChatTo] = useState4(null);
11409
- const [popover, setPopover] = useState4("none");
11410
- const [shortcuts, setShortcuts] = useState4(false);
11647
+ const [panel, setPanel] = useState5("none");
11648
+ const [chatTo, setChatTo] = useState5(null);
11649
+ const [popover, setPopover] = useState5("none");
11650
+ const [shortcuts, setShortcuts] = useState5(false);
11411
11651
  const snapshot = useMeetSnapshot();
11412
11652
  const lobby = useLobby();
11413
11653
  const controls = useHostControls();
@@ -11415,7 +11655,7 @@ function ControlBar({ onLeave }) {
11415
11655
  const micUnavailable = useLocalMedia().microphone.unavailable;
11416
11656
  const live = useLivePolicy();
11417
11657
  const unread = useUnreadChat(panel === "chat");
11418
- const [whiteboard, setWhiteboard] = useState4(false);
11658
+ const [whiteboard, setWhiteboard] = useState5(false);
11419
11659
  const app = useMeetAppPanel();
11420
11660
  const appOpened = useRef6(false);
11421
11661
  useEffect6(() => {
@@ -11449,7 +11689,7 @@ function ControlBar({ onLeave }) {
11449
11689
  help: () => setShortcuts(true)
11450
11690
  });
11451
11691
  const hasSpotlight = snapshot?.spotlight !== null && snapshot?.spotlight !== void 0;
11452
- return /* @__PURE__ */ jsxs3(Fragment, { children: [
11692
+ return /* @__PURE__ */ jsxs4(Fragment, { children: [
11453
11693
  /* @__PURE__ */ jsx6(MeetingOverlays, {}),
11454
11694
  shortcuts ? /* @__PURE__ */ jsx6(ShortcutsSheet, { onClose: () => setShortcuts(false) }) : null,
11455
11695
  panel === "chat" ? /* @__PURE__ */ jsx6(ChatPanel, { onClose: () => setPanel("none"), to: chatTo, onTo: setChatTo }) : null,
@@ -11479,8 +11719,9 @@ function ControlBar({ onLeave }) {
11479
11719
  ) }) }) : null,
11480
11720
  /* @__PURE__ */ jsx6(BreakoutBanner, {}),
11481
11721
  panel !== "people" ? /* @__PURE__ */ jsx6(KnockNotice, { onView: () => setPanel("people") }) : null,
11722
+ /* @__PURE__ */ jsx6(SpeakingWhileMutedNudge, {}),
11482
11723
  controls.notice !== null && panel !== "people" ? /* @__PURE__ */ jsx6(Toast, { text: controls.notice.text, failed: controls.notice.failed, onDone: controls.clearNotice }) : null,
11483
- /* @__PURE__ */ jsxs3("div", { className: "mx-meet__controls", children: [
11724
+ /* @__PURE__ */ jsxs4("div", { className: "mx-meet__controls", children: [
11484
11725
  live.micLocked ? null : /* @__PURE__ */ jsx6(
11485
11726
  ControlButton,
11486
11727
  {
@@ -11490,6 +11731,7 @@ function ControlBar({ onLeave }) {
11490
11731
  children: room.local?.micEnabled === true ? /* @__PURE__ */ jsx6(MicIcon, {}) : /* @__PURE__ */ jsx6(MicOffIcon, {})
11491
11732
  }
11492
11733
  ),
11734
+ /* @__PURE__ */ jsx6(AudioSettingsControl, {}),
11493
11735
  live.cameraLocked ? null : /* @__PURE__ */ jsx6(
11494
11736
  ControlButton,
11495
11737
  {
@@ -11509,7 +11751,7 @@ function ControlBar({ onLeave }) {
11509
11751
  children: /* @__PURE__ */ jsx6(ScreenShareIcon, {})
11510
11752
  }
11511
11753
  ) : null,
11512
- /* @__PURE__ */ jsxs3("span", { className: "mx-meet__anchor", children: [
11754
+ /* @__PURE__ */ jsxs4("span", { className: "mx-meet__anchor", children: [
11513
11755
  /* @__PURE__ */ jsx6(
11514
11756
  ControlButton,
11515
11757
  {
@@ -11541,11 +11783,11 @@ function ControlBar({ onLeave }) {
11541
11783
  }
11542
11784
  ),
11543
11785
  app !== null ? /* @__PURE__ */ jsx6(ControlButton, { label: app.title, active: panel === "app", onClick: () => toggle("app"), children: /* @__PURE__ */ jsx6(FlagIcon, {}) }) : null,
11544
- /* @__PURE__ */ jsxs3(ControlButton, { label: "Chat (\u2318\u2325C)", active: panel === "chat", onClick: () => toggle("chat"), children: [
11786
+ /* @__PURE__ */ jsxs4(ControlButton, { label: "Chat (\u2318\u2325C)", active: panel === "chat", onClick: () => toggle("chat"), children: [
11545
11787
  /* @__PURE__ */ jsx6(ChatIcon, {}),
11546
11788
  unread > 0 ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__dot", "aria-hidden": "true" }) : null
11547
11789
  ] }),
11548
- /* @__PURE__ */ jsxs3(
11790
+ /* @__PURE__ */ jsxs4(
11549
11791
  ControlButton,
11550
11792
  {
11551
11793
  label: lobby.waiting.length > 0 ? `People \u2014 ${lobby.waiting.length} waiting` : `People \u2014 ${(snapshot?.participants ?? []).length} in the meeting`,
@@ -11568,7 +11810,7 @@ function ControlBar({ onLeave }) {
11568
11810
  /* @__PURE__ */ jsx6(AiControl, { active: panel === "ai", onToggle: () => toggle("ai") }),
11569
11811
  recording.canStart ? /* @__PURE__ */ jsx6(ControlButton, { label: "Start recording", onClick: () => void recording.start(), children: /* @__PURE__ */ jsx6(RecordIcon, {}) }) : null,
11570
11812
  recording.canStop ? /* @__PURE__ */ jsx6(ControlButton, { label: "Stop recording", active: true, onClick: () => void recording.stop(), children: /* @__PURE__ */ jsx6(RecordIcon, {}) }) : null,
11571
- /* @__PURE__ */ jsxs3("span", { className: "mx-meet__anchor", children: [
11813
+ /* @__PURE__ */ jsxs4("span", { className: "mx-meet__anchor", children: [
11572
11814
  /* @__PURE__ */ jsx6(
11573
11815
  ControlButton,
11574
11816
  {
@@ -11578,8 +11820,8 @@ function ControlBar({ onLeave }) {
11578
11820
  children: /* @__PURE__ */ jsx6(MoreIcon, {})
11579
11821
  }
11580
11822
  ),
11581
- popover === "more" ? /* @__PURE__ */ jsx6(Popover, { label: "More options", onClose: () => setPopover("none"), children: /* @__PURE__ */ jsxs3("div", { className: "mx-meet__menu", role: "menu", children: [
11582
- /* @__PURE__ */ jsxs3(
11823
+ popover === "more" ? /* @__PURE__ */ jsx6(Popover, { label: "More options", onClose: () => setPopover("none"), children: /* @__PURE__ */ jsxs4("div", { className: "mx-meet__menu", role: "menu", children: [
11824
+ /* @__PURE__ */ jsxs4(
11583
11825
  MenuItem,
11584
11826
  {
11585
11827
  onSelect: () => {
@@ -11592,7 +11834,7 @@ function ControlBar({ onLeave }) {
11592
11834
  ]
11593
11835
  }
11594
11836
  ),
11595
- /* @__PURE__ */ jsxs3(
11837
+ /* @__PURE__ */ jsxs4(
11596
11838
  MenuItem,
11597
11839
  {
11598
11840
  onSelect: () => {
@@ -11605,9 +11847,16 @@ function ControlBar({ onLeave }) {
11605
11847
  ]
11606
11848
  }
11607
11849
  ),
11608
- controls.isHost ? /* @__PURE__ */ jsxs3(Fragment, { children: [
11850
+ !room.canShareScreen && room.local?.screenSharing !== true ? (
11851
+ // `share-unsupported-mobile`: the control is absent; the menu says where it lives.
11852
+ /* @__PURE__ */ jsxs4("p", { className: "mx-meet__menu-note", role: "note", "data-meet-notice": "share-unsupported", children: [
11853
+ /* @__PURE__ */ jsx6(ScreenShareIcon, { width: 16, height: 16 }),
11854
+ " Present from a computer"
11855
+ ] })
11856
+ ) : null,
11857
+ controls.isHost ? /* @__PURE__ */ jsxs4(Fragment, { children: [
11609
11858
  /* @__PURE__ */ jsx6("div", { className: "mx-meet__menu-sep", role: "separator" }),
11610
- /* @__PURE__ */ jsxs3(
11859
+ /* @__PURE__ */ jsxs4(
11611
11860
  MenuItem,
11612
11861
  {
11613
11862
  onSelect: () => {
@@ -11620,7 +11869,7 @@ function ControlBar({ onLeave }) {
11620
11869
  ]
11621
11870
  }
11622
11871
  ),
11623
- /* @__PURE__ */ jsxs3(
11872
+ /* @__PURE__ */ jsxs4(
11624
11873
  MenuItem,
11625
11874
  {
11626
11875
  onSelect: () => {
@@ -11637,7 +11886,7 @@ function ControlBar({ onLeave }) {
11637
11886
  ]
11638
11887
  }
11639
11888
  ),
11640
- /* @__PURE__ */ jsxs3(
11889
+ /* @__PURE__ */ jsxs4(
11641
11890
  MenuItem,
11642
11891
  {
11643
11892
  onSelect: () => {
@@ -11650,7 +11899,8 @@ function ControlBar({ onLeave }) {
11650
11899
  ]
11651
11900
  }
11652
11901
  ),
11653
- queue.length > 0 ? /* @__PURE__ */ jsxs3(
11902
+ /* @__PURE__ */ jsx6(WaitingRoomRule, {}),
11903
+ queue.length > 0 ? /* @__PURE__ */ jsxs4(
11654
11904
  MenuItem,
11655
11905
  {
11656
11906
  onSelect: () => {
@@ -11665,7 +11915,7 @@ function ControlBar({ onLeave }) {
11665
11915
  ]
11666
11916
  }
11667
11917
  ) : null,
11668
- hasSpotlight ? /* @__PURE__ */ jsxs3(
11918
+ hasSpotlight ? /* @__PURE__ */ jsxs4(
11669
11919
  MenuItem,
11670
11920
  {
11671
11921
  onSelect: () => {
@@ -11692,8 +11942,8 @@ var LEAVE_WORDS = {
11692
11942
  };
11693
11943
  function LeaveControl({ onLeave }) {
11694
11944
  const leave = useLeave();
11695
- const [open, setOpen] = useState4("none");
11696
- const [failure, setFailure] = useState4(null);
11945
+ const [open, setOpen] = useState5("none");
11946
+ const [failure, setFailure] = useState5(null);
11697
11947
  const words = LEAVE_WORDS[leave.policy.hostLeavePrompt];
11698
11948
  const run = (work, leaving) => {
11699
11949
  setFailure(null);
@@ -11704,7 +11954,7 @@ function LeaveControl({ onLeave }) {
11704
11954
  };
11705
11955
  const leaveNow = () => run(leave.leave, true);
11706
11956
  const endNow = () => run(leave.endForAll, false);
11707
- return /* @__PURE__ */ jsxs3("span", { className: "mx-meet__anchor", children: [
11957
+ return /* @__PURE__ */ jsxs4("span", { className: "mx-meet__anchor", children: [
11708
11958
  /* @__PURE__ */ jsx6(
11709
11959
  ControlButton,
11710
11960
  {
@@ -11718,7 +11968,7 @@ function LeaveControl({ onLeave }) {
11718
11968
  children: /* @__PURE__ */ jsx6(PhoneOffIcon, {})
11719
11969
  }
11720
11970
  ),
11721
- open !== "none" ? /* @__PURE__ */ jsx6(Popover, { label: open === "assign" ? words.assign_and_leave : "Leave", onClose: () => setOpen("none"), children: /* @__PURE__ */ jsxs3("div", { className: "mx-meet__menu", "data-meet-leave-menu": leave.policy.hostLeavePrompt, children: [
11971
+ open !== "none" ? /* @__PURE__ */ jsx6(Popover, { label: open === "assign" ? words.assign_and_leave : "Leave", onClose: () => setOpen("none"), children: /* @__PURE__ */ jsxs4("div", { className: "mx-meet__menu", "data-meet-leave-menu": leave.policy.hostLeavePrompt, children: [
11722
11972
  open === "menu" ? leave.choices.map((choice) => /* @__PURE__ */ jsx6(
11723
11973
  "button",
11724
11974
  {
@@ -11744,7 +11994,7 @@ function LeaveControl({ onLeave }) {
11744
11994
  },
11745
11995
  String(person.identity)
11746
11996
  )) : null,
11747
- open === "confirm" ? /* @__PURE__ */ jsxs3(Fragment, { children: [
11997
+ open === "confirm" ? /* @__PURE__ */ jsxs4(Fragment, { children: [
11748
11998
  /* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__menu-item mx-meet__menu-item--danger", onClick: endNow, children: words.end_for_all }),
11749
11999
  /* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__menu-item", onClick: () => setOpen("menu"), children: "Cancel" })
11750
12000
  ] }) : null,
@@ -11765,12 +12015,12 @@ function useUnreadChat(open) {
11765
12015
  const snapshot = useMeetSnapshot();
11766
12016
  const chat = snapshot?.chat ?? [];
11767
12017
  const local = snapshot?.localIdentity ?? null;
11768
- const [seen, setSeen] = useState4(0);
12018
+ const [seen, setSeen] = useState5(0);
11769
12019
  useEffect6(() => {
11770
12020
  if (open) setSeen(chat.length);
11771
12021
  }, [open, chat.length]);
11772
12022
  const loaded = snapshot?.chatLoaded === true;
11773
- const [baseline, setBaseline] = useState4(null);
12023
+ const [baseline, setBaseline] = useState5(null);
11774
12024
  useEffect6(() => {
11775
12025
  if (loaded && baseline === null) setBaseline(chat.length);
11776
12026
  }, [loaded, baseline, chat.length]);
@@ -11785,7 +12035,7 @@ function Popover({
11785
12035
  placement = "up"
11786
12036
  }) {
11787
12037
  const ref = useRef6(null);
11788
- const [style, setStyle] = useState4({
12038
+ const [style, setStyle] = useState5({
11789
12039
  position: "fixed",
11790
12040
  top: 0,
11791
12041
  left: 0,
@@ -11869,20 +12119,160 @@ function MenuItem({
11869
12119
  }
11870
12120
  );
11871
12121
  }
12122
+ var LOBBY_BYPASS_CHOICES = [
12123
+ { value: "everyone", label: "Everyone" },
12124
+ { value: "org_and_invited", label: "Your organization and invited people" },
12125
+ { value: "org", label: "Your organization" },
12126
+ { value: "invited", label: "Invited people" },
12127
+ { value: "host_only", label: "Only hosts" }
12128
+ ];
12129
+ function WaitingRoomRule() {
12130
+ const host = useRequiredMeetHost();
12131
+ const [open, setOpen] = useState5(false);
12132
+ const [value, setValue] = useState5(null);
12133
+ const [notice, setNotice] = useState5(null);
12134
+ useEffect6(() => {
12135
+ let live = true;
12136
+ void host.meetings.meetingRule("lobby_bypass").then((rule) => {
12137
+ if (live) setValue(typeof rule === "string" ? rule : null);
12138
+ }).catch(() => void 0);
12139
+ return () => {
12140
+ live = false;
12141
+ };
12142
+ }, [host]);
12143
+ const current = LOBBY_BYPASS_CHOICES.find((choice) => choice.value === value)?.label ?? null;
12144
+ return /* @__PURE__ */ jsxs4(Fragment, { children: [
12145
+ /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => setOpen(!open), children: [
12146
+ /* @__PURE__ */ jsx6(LockIcon, { width: 16, height: 16 }),
12147
+ " Who can skip the waiting room",
12148
+ current !== null ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__menu-value", children: current }) : null
12149
+ ] }),
12150
+ open ? /* @__PURE__ */ jsxs4("div", { role: "group", "aria-label": "Who can skip the waiting room", "data-meet-rule": "lobby_bypass", children: [
12151
+ LOBBY_BYPASS_CHOICES.map((choice) => /* @__PURE__ */ jsxs4(
12152
+ "button",
12153
+ {
12154
+ type: "button",
12155
+ role: "menuitemradio",
12156
+ "aria-checked": choice.value === value,
12157
+ className: "mx-meet__menu-item mx-meet__menu-item--sub",
12158
+ onClick: () => {
12159
+ setNotice(null);
12160
+ void host.meetings.setMeetingRule("lobby_bypass", choice.value).then(() => setValue(choice.value)).catch((error) => setNotice(error instanceof Error ? error.message : String(error)));
12161
+ },
12162
+ children: [
12163
+ choice.value === value ? /* @__PURE__ */ jsx6(CheckIcon, { width: 14, height: 14 }) : null,
12164
+ " ",
12165
+ choice.label
12166
+ ]
12167
+ },
12168
+ choice.value
12169
+ )),
12170
+ notice !== null ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__menu-note", role: "status", children: notice }) : null
12171
+ ] }) : null
12172
+ ] });
12173
+ }
11872
12174
  function Toast({ text: text3, failed, onDone }) {
11873
12175
  useEffect6(() => {
11874
12176
  const timer = setTimeout(onDone, failed ? 7e3 : 4e3);
11875
12177
  return () => clearTimeout(timer);
11876
12178
  }, [text3, failed, onDone]);
11877
- return /* @__PURE__ */ jsxs3("div", { className: failed ? "mx-meet__toast mx-meet__toast--failed" : "mx-meet__toast", role: "status", children: [
12179
+ return /* @__PURE__ */ jsxs4("div", { className: failed ? "mx-meet__toast mx-meet__toast--failed" : "mx-meet__toast", role: "status", children: [
11878
12180
  /* @__PURE__ */ jsx6("span", { children: text3 }),
11879
12181
  /* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__toast-close", "aria-label": "Dismiss", onClick: onDone, children: /* @__PURE__ */ jsx6(CloseIcon, { width: 14, height: 14 }) })
11880
12182
  ] });
11881
12183
  }
12184
+ function AudioSettingsControl() {
12185
+ const host = useMeetHost();
12186
+ const devices = useDeviceSnapshot();
12187
+ const [open, setOpen] = useState5(false);
12188
+ const list = (devices?.devices.audioinput ?? []).filter((device) => device.deviceId.length > 0);
12189
+ if (host === null || list.length < 2) return null;
12190
+ const current = devices?.selected.audioinput ?? host.devices.resolve("audioinput");
12191
+ return /* @__PURE__ */ jsxs4("span", { className: "mx-meet__anchor", children: [
12192
+ /* @__PURE__ */ jsx6(
12193
+ ControlButton,
12194
+ {
12195
+ label: "Audio settings",
12196
+ active: open,
12197
+ onClick: () => {
12198
+ if (!open) void host.devices.refresh();
12199
+ setOpen(!open);
12200
+ },
12201
+ children: /* @__PURE__ */ jsx6(ChevronUpIcon, {})
12202
+ }
12203
+ ),
12204
+ open ? /* @__PURE__ */ jsx6(Popover, { label: "Microphone", onClose: () => setOpen(false), children: /* @__PURE__ */ jsx6("div", { className: "mx-meet__menu", role: "menu", "aria-label": "Microphone", children: list.map((device) => /* @__PURE__ */ jsxs4(
12205
+ "button",
12206
+ {
12207
+ type: "button",
12208
+ role: "menuitemradio",
12209
+ "aria-checked": device.deviceId === current,
12210
+ className: "mx-meet__menu-item",
12211
+ onClick: () => {
12212
+ setOpen(false);
12213
+ host.devices.select("audioinput", device.deviceId);
12214
+ void host.engine.switchDevice("audioinput", device.deviceId).catch(() => void 0);
12215
+ },
12216
+ children: [
12217
+ device.deviceId === current ? /* @__PURE__ */ jsx6(CheckIcon, { width: 16, height: 16 }) : /* @__PURE__ */ jsx6("span", { className: "mx-meet__menu-gap" }),
12218
+ device.label.length > 0 ? device.label : "Microphone"
12219
+ ]
12220
+ },
12221
+ device.deviceId
12222
+ )) }) }) : null
12223
+ ] });
12224
+ }
12225
+ function SpeakingWhileMutedNudge() {
12226
+ const room = useRoom();
12227
+ const host = useMeetHost();
12228
+ const devices = useDeviceSnapshot();
12229
+ const microphone = useLocalMedia().microphone;
12230
+ const mutedByMe = host !== null && room.local != null && room.local.micEnabled !== true && microphone.unavailable === null;
12231
+ const mic = devices?.selected.audioinput ?? host?.devices.resolve("audioinput") ?? null;
12232
+ const stream = useMicrophoneStream(mutedByMe ? mic : "off");
12233
+ const level = useAudioLevel(stream);
12234
+ const latest = useRef6(0);
12235
+ latest.current = level;
12236
+ const [shown, setShown] = useState5(false);
12237
+ const [detector] = useState5(() => createSpeakingWhileMutedDetector());
12238
+ useEffect6(() => {
12239
+ if (!mutedByMe) {
12240
+ detector.reset();
12241
+ setShown(false);
12242
+ return void 0;
12243
+ }
12244
+ const timer = setInterval(() => {
12245
+ if (detector.feed(latest.current, Date.now())) setShown(true);
12246
+ }, 150);
12247
+ return () => clearInterval(timer);
12248
+ }, [mutedByMe, detector]);
12249
+ useEffect6(() => {
12250
+ if (!shown) return void 0;
12251
+ const timer = setTimeout(() => setShown(false), 8e3);
12252
+ return () => clearTimeout(timer);
12253
+ }, [shown]);
12254
+ if (!shown || !mutedByMe) return null;
12255
+ return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__notice-bar", role: "status", "data-meet-notice": "speaking-while-muted", children: [
12256
+ /* @__PURE__ */ jsx6(MicOffIcon, { width: 16, height: 16 }),
12257
+ /* @__PURE__ */ jsx6("span", { children: "You're muted" }),
12258
+ /* @__PURE__ */ jsx6(
12259
+ "button",
12260
+ {
12261
+ type: "button",
12262
+ className: "mx-meet__primary mx-meet__primary--small",
12263
+ onClick: () => {
12264
+ setShown(false);
12265
+ void room.toggleMicrophone();
12266
+ },
12267
+ children: "Unmute"
12268
+ }
12269
+ )
12270
+ ] });
12271
+ }
11882
12272
  function MediaNotices() {
11883
12273
  const media = useLocalMedia();
11884
12274
  const { region, where, enableAudio, acceptOffer, dismissOffer, dismissNotice, retry } = useMediaSupervisor();
11885
- const [fixing, setFixing] = useState4(null);
12275
+ const [fixing, setFixing] = useState5(null);
11886
12276
  const chips = ["microphone", "camera"].flatMap((kind) => {
11887
12277
  const reason = deviceUnavailableReason(media[kind], region.permission[kind]);
11888
12278
  return reason === null ? [] : [{ kind, reason }];
@@ -11892,8 +12282,8 @@ function MediaNotices() {
11892
12282
  const offer = region.offer;
11893
12283
  const name = (kind) => kind === "microphone" ? "Microphone" : "Camera";
11894
12284
  if (chips.length === 0 && region.audioOutput !== "blocked" && notice === null && offer === null) return null;
11895
- return /* @__PURE__ */ jsxs3("div", { className: "mx-meet__media-notices", children: [
11896
- region.audioOutput === "blocked" ? /* @__PURE__ */ jsxs3(
12285
+ return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__media-notices", children: [
12286
+ region.audioOutput === "blocked" ? /* @__PURE__ */ jsxs4(
11897
12287
  ErrorBox,
11898
12288
  {
11899
12289
  as: "div",
@@ -11908,7 +12298,7 @@ function MediaNotices() {
11908
12298
  ]
11909
12299
  }
11910
12300
  ) : null,
11911
- chips.map(({ kind, reason }) => /* @__PURE__ */ jsxs3("div", { className: "mx-meet__media-pill", role: "status", "data-meet-notice": deviceNoticeCode(kind, reason), children: [
12301
+ chips.map(({ kind, reason }) => /* @__PURE__ */ jsxs4("div", { className: "mx-meet__media-pill", role: "status", "data-meet-notice": deviceNoticeCode(kind, reason), children: [
11912
12302
  /* @__PURE__ */ jsx6("span", { children: deviceChipLabel(kind, reason) }),
11913
12303
  /* @__PURE__ */ jsx6(
11914
12304
  "button",
@@ -11922,9 +12312,9 @@ function MediaNotices() {
11922
12312
  }
11923
12313
  )
11924
12314
  ] }, kind)),
11925
- fixing !== null && fixReason !== null ? /* @__PURE__ */ jsxs3("div", { className: "mx-meet__popover mx-meet__fix-sheet", role: "dialog", "aria-label": `Fix ${name(fixing).toLowerCase()}`, children: [
12315
+ fixing !== null && fixReason !== null ? /* @__PURE__ */ jsxs4("div", { className: "mx-meet__popover mx-meet__fix-sheet", role: "dialog", "aria-label": `Fix ${name(fixing).toLowerCase()}`, children: [
11926
12316
  /* @__PURE__ */ jsx6("ol", { className: "mx-meet__fix-steps", children: deviceFixSteps(fixing, fixReason, where).map((step) => /* @__PURE__ */ jsx6("li", { children: step }, step)) }),
11927
- /* @__PURE__ */ jsxs3("div", { className: "mx-meet__fix-actions", children: [
12317
+ /* @__PURE__ */ jsxs4("div", { className: "mx-meet__fix-actions", children: [
11928
12318
  /* @__PURE__ */ jsx6(
11929
12319
  "button",
11930
12320
  {
@@ -11941,7 +12331,7 @@ function MediaNotices() {
11941
12331
  /* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__toast-close", "aria-label": "Close", onClick: () => setFixing(null), children: /* @__PURE__ */ jsx6(CloseIcon, { width: 14, height: 14 }) })
11942
12332
  ] })
11943
12333
  ] }) : null,
11944
- notice !== null ? /* @__PURE__ */ jsxs3(
12334
+ notice !== null ? /* @__PURE__ */ jsxs4(
11945
12335
  "div",
11946
12336
  {
11947
12337
  className: "mx-meet__media-pill",
@@ -11953,7 +12343,7 @@ function MediaNotices() {
11953
12343
  ]
11954
12344
  }
11955
12345
  ) : null,
11956
- offer !== null ? /* @__PURE__ */ jsxs3("div", { className: "mx-meet__media-pill", role: "status", children: [
12346
+ offer !== null ? /* @__PURE__ */ jsxs4("div", { className: "mx-meet__media-pill", role: "status", children: [
11957
12347
  /* @__PURE__ */ jsx6("span", { children: `New ${offer.kind}: ${offer.label || name(offer.kind)}` }),
11958
12348
  /* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__primary mx-meet__primary--small", onClick: () => void acceptOffer(), children: "Use it" }),
11959
12349
  /* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__toast-close", "aria-label": "Dismiss", onClick: dismissOffer, children: /* @__PURE__ */ jsx6(CloseIcon, { width: 14, height: 14 }) })
@@ -11968,22 +12358,22 @@ function MeetingOverlays() {
11968
12358
  const snapshot = useMeetSnapshot();
11969
12359
  const controls = useHostControls();
11970
12360
  const isHostNow = useRole() === "host";
11971
- return /* @__PURE__ */ jsxs3(Fragment, { children: [
12361
+ return /* @__PURE__ */ jsxs4(Fragment, { children: [
11972
12362
  /* @__PURE__ */ jsx6(ReactionOverlay, { reactions }),
11973
12363
  /* @__PURE__ */ jsx6(MediaNotices, {}),
11974
12364
  snapshot !== null && snapshot.phase === "in_call" && snapshot.participants.length >= 2 && !snapshot.participants.some((p) => p.role === "host" || p.role === "cohost") ? (
11975
12365
  // meeting-without-host: the call goes on; host-only controls are simply not on screen.
11976
12366
  /* @__PURE__ */ jsx6("p", { className: "mx-meet__banner", role: "status", "data-meet-notice": "host-absent", children: "The host has left the meeting. Host controls are not available until a host is back." })
11977
12367
  ) : null,
11978
- live.consent !== null ? /* @__PURE__ */ jsx6("div", { className: "mx-meet__sheet-backdrop", children: /* @__PURE__ */ jsxs3("div", { className: "mx-meet__sheet", role: "alertdialog", "aria-label": "This meeting is being recorded", "data-meet-notice": "recording-consent", children: [
12368
+ live.consent !== null ? /* @__PURE__ */ jsx6("div", { className: "mx-meet__sheet-backdrop", children: /* @__PURE__ */ jsxs4("div", { className: "mx-meet__sheet", role: "alertdialog", "aria-label": "This meeting is being recorded", "data-meet-notice": "recording-consent", children: [
11979
12369
  /* @__PURE__ */ jsx6("h2", { className: "mx-meet__panel-title", children: "This meeting is being recorded" }),
11980
12370
  /* @__PURE__ */ jsx6("p", { className: "mx-meet__confirm-text", children: live.consent === "ok_or_leave" ? "By staying you agree to be recorded. You can leave now if you do not agree." : "Until you agree to the recording you can watch and listen, but not use your microphone or camera." }),
11981
- /* @__PURE__ */ jsxs3("div", { className: "mx-meet__menu-actions", children: [
12371
+ /* @__PURE__ */ jsxs4("div", { className: "mx-meet__menu-actions", children: [
11982
12372
  /* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__send", onClick: live.agree, children: live.consent === "ok_or_leave" ? "OK" : "I agree" }),
11983
12373
  live.consent === "ok_or_leave" ? /* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__link", onClick: () => void room.leave(), children: "Leave meeting" }) : null
11984
12374
  ] })
11985
12375
  ] }) }) : null,
11986
- snapshot?.canReclaim === true && !isHostNow ? /* @__PURE__ */ jsxs3("div", { className: "mx-meet__notice-bar", role: "status", "data-meet-notice": "host-reclaim", children: [
12376
+ snapshot?.canReclaim === true && !isHostNow ? /* @__PURE__ */ jsxs4("div", { className: "mx-meet__notice-bar", role: "status", "data-meet-notice": "host-reclaim", children: [
11987
12377
  /* @__PURE__ */ jsx6("span", { children: "You started this meeting. Take back the host?" }),
11988
12378
  /* @__PURE__ */ jsx6(
11989
12379
  "button",
@@ -11996,7 +12386,7 @@ function MeetingOverlays() {
11996
12386
  )
11997
12387
  ] }) : null,
11998
12388
  live.micLocked || live.cameraLocked ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__banner", role: "status", "data-meet-notice": "mic-locked", children: live.micLocked && live.cameraLocked ? "Your microphone and camera are turned off by the organizer." : live.micLocked ? "Your microphone is turned off by the organizer." : "Your camera is turned off by the organizer." }) : null,
11999
- live.timeWarning && live.minutesLeft !== null && live.minutesLeft > 0 ? /* @__PURE__ */ jsxs3("p", { className: "mx-meet__banner", role: "status", "data-meet-notice": "time-warning", children: [
12389
+ live.timeWarning && live.minutesLeft !== null && live.minutesLeft > 0 ? /* @__PURE__ */ jsxs4("p", { className: "mx-meet__banner", role: "status", "data-meet-notice": "time-warning", children: [
12000
12390
  "This meeting will end in ",
12001
12391
  live.minutesLeft,
12002
12392
  " ",
@@ -12007,7 +12397,7 @@ function MeetingOverlays() {
12007
12397
  // A host's request ("the host is asking you to unmute"), not an error:
12008
12398
  // an assertive status, so it is announced at once without being filed
12009
12399
  // as a failure (design-system error-box census).
12010
- /* @__PURE__ */ jsxs3("div", { className: "mx-meet__notice-bar", role: "status", "aria-live": "assertive", children: [
12400
+ /* @__PURE__ */ jsxs4("div", { className: "mx-meet__notice-bar", role: "status", "aria-live": "assertive", children: [
12011
12401
  /* @__PURE__ */ jsx6("span", { children: notice.text }),
12012
12402
  notice.kind === "ask-unmute" && room.local?.micEnabled !== true ? /* @__PURE__ */ jsx6(
12013
12403
  "button",
@@ -12034,7 +12424,7 @@ function ShortcutsSheet({ onClose }) {
12034
12424
  window.addEventListener("keydown", onKey);
12035
12425
  return () => window.removeEventListener("keydown", onKey);
12036
12426
  }, [onClose]);
12037
- return /* @__PURE__ */ jsx6("div", { className: "mx-meet__sheet-backdrop", onClick: onClose, children: /* @__PURE__ */ jsxs3(
12427
+ return /* @__PURE__ */ jsx6("div", { className: "mx-meet__sheet-backdrop", onClick: onClose, children: /* @__PURE__ */ jsxs4(
12038
12428
  "div",
12039
12429
  {
12040
12430
  className: "mx-meet__sheet",
@@ -12042,11 +12432,11 @@ function ShortcutsSheet({ onClose }) {
12042
12432
  "aria-label": "Keyboard shortcuts",
12043
12433
  onClick: (event) => event.stopPropagation(),
12044
12434
  children: [
12045
- /* @__PURE__ */ jsxs3("header", { className: "mx-meet__panel-head", children: [
12435
+ /* @__PURE__ */ jsxs4("header", { className: "mx-meet__panel-head", children: [
12046
12436
  /* @__PURE__ */ jsx6("h2", { className: "mx-meet__panel-title", children: "Keyboard shortcuts" }),
12047
12437
  /* @__PURE__ */ jsx6(ControlButton, { label: "Close", onClick: onClose, children: /* @__PURE__ */ jsx6(CloseIcon, { width: 16, height: 16 }) })
12048
12438
  ] }),
12049
- /* @__PURE__ */ jsx6("dl", { className: "mx-meet__shortcuts", children: MEET_SHORTCUTS.map((shortcut) => /* @__PURE__ */ jsxs3("div", { className: "mx-meet__shortcut", children: [
12439
+ /* @__PURE__ */ jsx6("dl", { className: "mx-meet__shortcuts", children: MEET_SHORTCUTS.map((shortcut) => /* @__PURE__ */ jsxs4("div", { className: "mx-meet__shortcut", children: [
12050
12440
  /* @__PURE__ */ jsx6("dt", { children: shortcut.label }),
12051
12441
  /* @__PURE__ */ jsx6("dd", { children: /* @__PURE__ */ jsx6("kbd", { className: "mx-meet__kbd", children: shortcut.keys }) })
12052
12442
  ] }, shortcut.id)) })
@@ -12078,8 +12468,8 @@ function PanelShell({
12078
12468
  observer.observe(header);
12079
12469
  return () => observer.disconnect();
12080
12470
  }, []);
12081
- return /* @__PURE__ */ jsxs3("aside", { ref, className: "mx-meet__panel", "aria-label": title, children: [
12082
- /* @__PURE__ */ jsxs3("header", { className: "mx-meet__panel-head", children: [
12471
+ return /* @__PURE__ */ jsxs4("aside", { ref, className: "mx-meet__panel", "aria-label": title, children: [
12472
+ /* @__PURE__ */ jsxs4("header", { className: "mx-meet__panel-head", children: [
12083
12473
  /* @__PURE__ */ jsx6("h2", { className: "mx-meet__panel-title", children: title }),
12084
12474
  /* @__PURE__ */ jsx6(ControlButton, { label: "Close panel", onClick: onClose, children: /* @__PURE__ */ jsx6(CloseIcon, { width: 16, height: 16 }) })
12085
12475
  ] }),
@@ -12094,8 +12484,8 @@ function ChatPanel({
12094
12484
  const snapshot = useMeetSnapshot();
12095
12485
  const room = useRoom();
12096
12486
  const live = useLivePolicy();
12097
- const [draft, setDraft] = useState4("");
12098
- const [recipient, setRecipient] = useState4(to);
12487
+ const [draft, setDraft] = useState5("");
12488
+ const [recipient, setRecipient] = useState5(to);
12099
12489
  const listRef = useRef6(null);
12100
12490
  const messages = snapshot?.chat ?? [];
12101
12491
  const local = snapshot?.localIdentity ?? null;
@@ -12112,13 +12502,13 @@ function ChatPanel({
12112
12502
  setRecipient(next);
12113
12503
  onTo?.(next);
12114
12504
  };
12115
- return /* @__PURE__ */ jsxs3(PanelShell, { title: "Chat", onClose, children: [
12116
- /* @__PURE__ */ jsxs3("ul", { className: "mx-meet__chat", ref: listRef, children: [
12505
+ return /* @__PURE__ */ jsxs4(PanelShell, { title: "Chat", onClose, children: [
12506
+ /* @__PURE__ */ jsxs4("ul", { className: "mx-meet__chat", ref: listRef, children: [
12117
12507
  snapshot?.chatHistoryError != null ? /* @__PURE__ */ jsx6("li", { className: "mx-meet__panel-note", children: snapshot.chatHistoryError }) : null,
12118
12508
  snapshot?.chatLoaded !== true && messages.length === 0 ? /* @__PURE__ */ jsx6("li", { className: "mx-meet__panel-note", children: "Reading earlier messages\u2026" }) : messages.length === 0 && snapshot?.chatHistoryError == null ? /* @__PURE__ */ jsx6("li", { className: "mx-meet__panel-note", children: "No messages yet. Messages to everyone stay with the meeting, so people who join later see them." }) : null,
12119
12509
  messages.map((message) => /* @__PURE__ */ jsx6(ChatLine, { message, local, people }, message.id))
12120
12510
  ] }),
12121
- !live.canChat ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__panel-note", role: "status", "data-meet-notice": "chat-restricted", children: live.chatMode === "off" ? "Chat is turned off for this meeting." : "Chat is limited to the host and co-hosts in this meeting." }) : /* @__PURE__ */ jsxs3(
12511
+ !live.canChat ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__panel-note", role: "status", "data-meet-notice": "chat-restricted", children: live.chatMode === "off" ? "Chat is turned off for this meeting." : "Chat is limited to the host and co-hosts in this meeting." }) : /* @__PURE__ */ jsxs4(
12122
12512
  "form",
12123
12513
  {
12124
12514
  className: "mx-meet__composer mx-meet__composer--chat",
@@ -12131,7 +12521,7 @@ function ChatPanel({
12131
12521
  else void room.sendPrivateChat(recipient, text3);
12132
12522
  },
12133
12523
  children: [
12134
- people.length > 0 ? /* @__PURE__ */ jsxs3(
12524
+ people.length > 0 ? /* @__PURE__ */ jsxs4(
12135
12525
  "select",
12136
12526
  {
12137
12527
  className: "mx-meet__select mx-meet__select--compact",
@@ -12140,14 +12530,14 @@ function ChatPanel({
12140
12530
  onChange: (event) => choose(event.target.value === "" ? null : event.target.value),
12141
12531
  children: [
12142
12532
  /* @__PURE__ */ jsx6("option", { value: "", children: "Everyone" }),
12143
- people.map((participant) => /* @__PURE__ */ jsxs3("option", { value: participant.identity, children: [
12533
+ people.map((participant) => /* @__PURE__ */ jsxs4("option", { value: participant.identity, children: [
12144
12534
  participant.displayName,
12145
12535
  " (private)"
12146
12536
  ] }, participant.identity))
12147
12537
  ]
12148
12538
  }
12149
12539
  ) : null,
12150
- /* @__PURE__ */ jsxs3("div", { className: "mx-meet__composer-row", children: [
12540
+ /* @__PURE__ */ jsxs4("div", { className: "mx-meet__composer-row", children: [
12151
12541
  /* @__PURE__ */ jsx6(
12152
12542
  "input",
12153
12543
  {
@@ -12161,7 +12551,7 @@ function ChatPanel({
12161
12551
  ),
12162
12552
  /* @__PURE__ */ jsx6("button", { type: "submit", className: "mx-meet__send", disabled: draft.trim().length === 0, children: "Send" })
12163
12553
  ] }),
12164
- recipientName !== null ? /* @__PURE__ */ jsxs3("p", { className: "mx-meet__panel-note", children: [
12554
+ recipientName !== null ? /* @__PURE__ */ jsxs4("p", { className: "mx-meet__panel-note", children: [
12165
12555
  "Only ",
12166
12556
  recipientName,
12167
12557
  " sees this. Private messages are not saved."
@@ -12179,7 +12569,7 @@ function ChatLine({
12179
12569
  const mine = message.identity === local;
12180
12570
  const privateTo = message.to ?? null;
12181
12571
  const counterpart = privateTo === null ? null : mine ? people.find((p) => p.identity === privateTo)?.displayName ?? "them" : "you";
12182
- return /* @__PURE__ */ jsxs3(
12572
+ return /* @__PURE__ */ jsxs4(
12183
12573
  "li",
12184
12574
  {
12185
12575
  className: [
@@ -12188,9 +12578,9 @@ function ChatLine({
12188
12578
  message.failed !== void 0 ? "mx-meet__chat-line--failed" : ""
12189
12579
  ].filter(Boolean).join(" "),
12190
12580
  children: [
12191
- /* @__PURE__ */ jsxs3("span", { className: "mx-meet__chat-meta", children: [
12581
+ /* @__PURE__ */ jsxs4("span", { className: "mx-meet__chat-meta", children: [
12192
12582
  /* @__PURE__ */ jsx6("strong", { children: mine ? "You" : message.displayName }),
12193
- counterpart !== null ? /* @__PURE__ */ jsxs3("span", { className: "mx-meet__chat-private", children: [
12583
+ counterpart !== null ? /* @__PURE__ */ jsxs4("span", { className: "mx-meet__chat-private", children: [
12194
12584
  "to ",
12195
12585
  counterpart,
12196
12586
  " \xB7 private"
@@ -12210,8 +12600,8 @@ function PeoplePanel({
12210
12600
  const snapshot = useMeetSnapshot();
12211
12601
  const controls = useHostControls();
12212
12602
  const queue = useHandQueue();
12213
- const [query, setQuery] = useState4("");
12214
- const [menuFor, setMenuFor] = useState4(null);
12603
+ const [query, setQuery] = useState5("");
12604
+ const [menuFor, setMenuFor] = useState5(null);
12215
12605
  const myRole = useRole();
12216
12606
  const local = snapshot?.localIdentity ?? null;
12217
12607
  const observersHidden = snapshot?.grants.observersVisibleTo === "hosts" && !controls.isHost;
@@ -12220,11 +12610,11 @@ function PeoplePanel({
12220
12610
  );
12221
12611
  const needle = query.trim().toLowerCase();
12222
12612
  const shown = needle.length === 0 ? everyone : everyone.filter((participant) => participant.displayName.toLowerCase().includes(needle));
12223
- return /* @__PURE__ */ jsxs3(PanelShell, { title: `People (${everyone.length})`, onClose, children: [
12613
+ return /* @__PURE__ */ jsxs4(PanelShell, { title: `People (${everyone.length})`, onClose, children: [
12224
12614
  /* @__PURE__ */ jsx6(LobbyPanel, {}),
12225
- queue.length > 0 ? /* @__PURE__ */ jsxs3("section", { className: "mx-meet__section", "aria-label": "Raised hands", children: [
12226
- /* @__PURE__ */ jsxs3("header", { className: "mx-meet__section-head", children: [
12227
- /* @__PURE__ */ jsxs3("h3", { className: "mx-meet__section-title", children: [
12615
+ queue.length > 0 ? /* @__PURE__ */ jsxs4("section", { className: "mx-meet__section", "aria-label": "Raised hands", children: [
12616
+ /* @__PURE__ */ jsxs4("header", { className: "mx-meet__section-head", children: [
12617
+ /* @__PURE__ */ jsxs4("h3", { className: "mx-meet__section-title", children: [
12228
12618
  "Raised hands \xB7 ",
12229
12619
  queue.length
12230
12620
  ] }),
@@ -12238,9 +12628,9 @@ function PeoplePanel({
12238
12628
  }
12239
12629
  ) : null
12240
12630
  ] }),
12241
- /* @__PURE__ */ jsx6("ol", { className: "mx-meet__queue", children: queue.map((participant) => /* @__PURE__ */ jsxs3("li", { className: "mx-meet__person", children: [
12631
+ /* @__PURE__ */ jsx6("ol", { className: "mx-meet__queue", children: queue.map((participant) => /* @__PURE__ */ jsxs4("li", { className: "mx-meet__person", children: [
12242
12632
  /* @__PURE__ */ jsx6(Avatar, { name: participant.displayName, url: participant.avatarUrl, size: 28 }),
12243
- /* @__PURE__ */ jsxs3("span", { className: "mx-meet__person-name", children: [
12633
+ /* @__PURE__ */ jsxs4("span", { className: "mx-meet__person-name", children: [
12244
12634
  participant.displayName,
12245
12635
  participant.identity === local ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__you", children: " (you)" }) : null
12246
12636
  ] }),
@@ -12255,12 +12645,12 @@ function PeoplePanel({
12255
12645
  ) : null
12256
12646
  ] }, participant.identity)) })
12257
12647
  ] }) : null,
12258
- controls.isHost && everyone.length > 1 ? /* @__PURE__ */ jsxs3("div", { className: "mx-meet__bulk", children: [
12259
- /* @__PURE__ */ jsxs3("button", { type: "button", className: "mx-meet__chip", onClick: () => void controls.run({ action: "mute_all" }), children: [
12648
+ controls.isHost && everyone.length > 1 ? /* @__PURE__ */ jsxs4("div", { className: "mx-meet__bulk", children: [
12649
+ /* @__PURE__ */ jsxs4("button", { type: "button", className: "mx-meet__chip", onClick: () => void controls.run({ action: "mute_all" }), children: [
12260
12650
  /* @__PURE__ */ jsx6(MicOffIcon, { width: 14, height: 14 }),
12261
12651
  " Mute all"
12262
12652
  ] }),
12263
- /* @__PURE__ */ jsxs3(
12653
+ /* @__PURE__ */ jsxs4(
12264
12654
  "button",
12265
12655
  {
12266
12656
  type: "button",
@@ -12273,7 +12663,7 @@ function PeoplePanel({
12273
12663
  }
12274
12664
  )
12275
12665
  ] }) : null,
12276
- everyone.length > 4 ? /* @__PURE__ */ jsxs3("label", { className: "mx-meet__search", children: [
12666
+ everyone.length > 4 ? /* @__PURE__ */ jsxs4("label", { className: "mx-meet__search", children: [
12277
12667
  /* @__PURE__ */ jsx6(SearchIcon, { width: 16, height: 16 }),
12278
12668
  /* @__PURE__ */ jsx6(
12279
12669
  "input",
@@ -12287,10 +12677,10 @@ function PeoplePanel({
12287
12677
  )
12288
12678
  ] }) : null,
12289
12679
  controls.notice !== null ? /* @__PURE__ */ jsx6("p", { className: controls.notice.failed ? "mx-meet__error" : "mx-meet__notice", role: "status", children: controls.notice.text }) : null,
12290
- /* @__PURE__ */ jsxs3("ul", { className: "mx-meet__people", children: [
12291
- shown.map((participant) => /* @__PURE__ */ jsxs3("li", { className: "mx-meet__person", children: [
12680
+ /* @__PURE__ */ jsxs4("ul", { className: "mx-meet__people", children: [
12681
+ shown.map((participant) => /* @__PURE__ */ jsxs4("li", { className: "mx-meet__person", children: [
12292
12682
  /* @__PURE__ */ jsx6(Avatar, { name: participant.displayName, url: participant.avatarUrl, size: 32 }),
12293
- /* @__PURE__ */ jsxs3("span", { className: "mx-meet__person-name", children: [
12683
+ /* @__PURE__ */ jsxs4("span", { className: "mx-meet__person-name", children: [
12294
12684
  participant.displayName,
12295
12685
  participant.identity === local ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__you", children: " (you)" }) : null,
12296
12686
  /* @__PURE__ */ jsx6(
@@ -12307,7 +12697,7 @@ function PeoplePanel({
12307
12697
  participant.handRaised ? /* @__PURE__ */ jsx6(HandIcon, { width: 14, height: 14 }) : null,
12308
12698
  !participant.micEnabled && !isNoteTaker(participant) ? /* @__PURE__ */ jsx6(MicOffIcon, { width: 14, height: 14 }) : null,
12309
12699
  /* @__PURE__ */ jsx6(QualityBars, { quality: participant.quality }),
12310
- /* @__PURE__ */ jsxs3("span", { className: "mx-meet__anchor", children: [
12700
+ /* @__PURE__ */ jsxs4("span", { className: "mx-meet__anchor", children: [
12311
12701
  /* @__PURE__ */ jsx6(
12312
12702
  ControlButton,
12313
12703
  {
@@ -12328,7 +12718,7 @@ function PeoplePanel({
12328
12718
  ) : null
12329
12719
  ] })
12330
12720
  ] }, participant.identity)),
12331
- shown.length === 0 ? /* @__PURE__ */ jsxs3("li", { className: "mx-meet__panel-note", children: [
12721
+ shown.length === 0 ? /* @__PURE__ */ jsxs4("li", { className: "mx-meet__panel-note", children: [
12332
12722
  "Nobody matches \u201C",
12333
12723
  query,
12334
12724
  "\u201D."
@@ -12346,14 +12736,14 @@ function PersonMenu({
12346
12736
  const host = useMeetHost();
12347
12737
  const snapshot = useMeetSnapshot();
12348
12738
  const controls = useHostControls();
12349
- const [mode, setMode] = useState4("menu");
12350
- const [text3, setText] = useState4("");
12739
+ const [mode, setMode] = useState5("menu");
12740
+ const [text3, setText] = useState5("");
12351
12741
  const self = participant.identity === snapshot?.localIdentity;
12352
12742
  const moderate = controls.canModerate(participant);
12353
12743
  const pinned = snapshot?.pinned === participant.identity;
12354
12744
  const spotlit = snapshot?.spotlight === participant.identity;
12355
12745
  const hasAccount = participant.userId !== null;
12356
- const [refused, setRefused] = useState4(false);
12746
+ const [refused, setRefused] = useState5(false);
12357
12747
  const act = (request) => {
12358
12748
  setRefused(false);
12359
12749
  void controls.run(request).then((result) => {
@@ -12364,7 +12754,7 @@ function PersonMenu({
12364
12754
  const refusal2 = refused && controls.notice?.failed === true ? /* @__PURE__ */ jsx6(ErrorBox, { as: "p", className: "mx-meet__error", message: controls.notice.text, operation: "Change this participant", origin: "meet/components", children: controls.notice.text }) : null;
12365
12755
  if (mode === "rename" || mode === "report") {
12366
12756
  const renaming = mode === "rename";
12367
- return /* @__PURE__ */ jsx6(Popover, { label: renaming ? "Rename" : "Report", onClose, placement, children: /* @__PURE__ */ jsxs3(
12757
+ return /* @__PURE__ */ jsx6(Popover, { label: renaming ? "Rename" : "Report", onClose, placement, children: /* @__PURE__ */ jsxs4(
12368
12758
  "form",
12369
12759
  {
12370
12760
  className: "mx-meet__menu-form",
@@ -12376,7 +12766,7 @@ function PersonMenu({
12376
12766
  );
12377
12767
  },
12378
12768
  children: [
12379
- /* @__PURE__ */ jsxs3("label", { className: "mx-meet__field", children: [
12769
+ /* @__PURE__ */ jsxs4("label", { className: "mx-meet__field", children: [
12380
12770
  /* @__PURE__ */ jsx6("span", { className: "mx-meet__field-label", children: renaming ? "Name shown in this meeting" : `What did ${participant.displayName} do?` }),
12381
12771
  renaming ? /* @__PURE__ */ jsx6(
12382
12772
  "input",
@@ -12400,7 +12790,7 @@ function PersonMenu({
12400
12790
  )
12401
12791
  ] }),
12402
12792
  refusal2,
12403
- /* @__PURE__ */ jsxs3("div", { className: "mx-meet__menu-actions", children: [
12793
+ /* @__PURE__ */ jsxs4("div", { className: "mx-meet__menu-actions", children: [
12404
12794
  /* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__link", onClick: () => setMode("menu"), children: "Back" }),
12405
12795
  /* @__PURE__ */ jsx6("button", { type: "submit", className: "mx-meet__send", disabled: text3.trim().length === 0 || controls.busy, children: renaming ? "Rename" : "Report" })
12406
12796
  ] })
@@ -12410,10 +12800,10 @@ function PersonMenu({
12410
12800
  }
12411
12801
  if (mode === "remove" || mode === "transfer") {
12412
12802
  const removing = mode === "remove";
12413
- return /* @__PURE__ */ jsx6(Popover, { label: removing ? "Remove" : "Make host", onClose, placement, children: /* @__PURE__ */ jsxs3("div", { className: "mx-meet__menu-form", children: [
12803
+ return /* @__PURE__ */ jsx6(Popover, { label: removing ? "Remove" : "Make host", onClose, placement, children: /* @__PURE__ */ jsxs4("div", { className: "mx-meet__menu-form", children: [
12414
12804
  /* @__PURE__ */ jsx6("p", { className: "mx-meet__confirm-text", children: removing ? `Remove ${participant.displayName}? They leave immediately and cannot rejoin this meeting.` : `Make ${participant.displayName} the host? They get every host control and own this meeting. You stay on as a co-host.` }),
12415
12805
  refusal2,
12416
- /* @__PURE__ */ jsxs3("div", { className: "mx-meet__menu-actions", children: [
12806
+ /* @__PURE__ */ jsxs4("div", { className: "mx-meet__menu-actions", children: [
12417
12807
  /* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__link", onClick: () => setMode("menu"), children: "Cancel" }),
12418
12808
  /* @__PURE__ */ jsx6(
12419
12809
  "button",
@@ -12428,8 +12818,8 @@ function PersonMenu({
12428
12818
  ] })
12429
12819
  ] }) });
12430
12820
  }
12431
- return /* @__PURE__ */ jsx6(Popover, { label: `Options for ${participant.displayName}`, onClose, placement, children: /* @__PURE__ */ jsxs3("div", { className: "mx-meet__menu", role: "menu", children: [
12432
- /* @__PURE__ */ jsxs3(
12821
+ return /* @__PURE__ */ jsx6(Popover, { label: `Options for ${participant.displayName}`, onClose, placement, children: /* @__PURE__ */ jsxs4("div", { className: "mx-meet__menu", role: "menu", children: [
12822
+ /* @__PURE__ */ jsxs4(
12433
12823
  MenuItem,
12434
12824
  {
12435
12825
  onSelect: () => {
@@ -12443,7 +12833,7 @@ function PersonMenu({
12443
12833
  ]
12444
12834
  }
12445
12835
  ),
12446
- !self && !participant.isAgent && (onMessage !== void 0 || host !== null) ? /* @__PURE__ */ jsxs3(
12836
+ !self && !participant.isAgent && (onMessage !== void 0 || host !== null) ? /* @__PURE__ */ jsxs4(
12447
12837
  MenuItem,
12448
12838
  {
12449
12839
  onSelect: () => {
@@ -12460,44 +12850,44 @@ function PersonMenu({
12460
12850
  ]
12461
12851
  }
12462
12852
  ) : null,
12463
- controls.isHost ? /* @__PURE__ */ jsxs3(MenuItem, { onSelect: () => act({ action: "spotlight", identity: spotlit ? null : participant.identity }), children: [
12853
+ controls.isHost ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "spotlight", identity: spotlit ? null : participant.identity }), children: [
12464
12854
  /* @__PURE__ */ jsx6(SpotlightIcon, { width: 16, height: 16 }),
12465
12855
  " ",
12466
12856
  spotlit ? "Remove spotlight" : "Spotlight for everyone"
12467
12857
  ] }) : null,
12468
- moderate ? /* @__PURE__ */ jsxs3(Fragment, { children: [
12858
+ moderate ? /* @__PURE__ */ jsxs4(Fragment, { children: [
12469
12859
  /* @__PURE__ */ jsx6("div", { className: "mx-meet__menu-sep", role: "separator" }),
12470
- participant.micEnabled ? /* @__PURE__ */ jsxs3(MenuItem, { onSelect: () => act({ action: "mute", identity: participant.identity }), children: [
12860
+ participant.micEnabled ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "mute", identity: participant.identity }), children: [
12471
12861
  /* @__PURE__ */ jsx6(MicOffIcon, { width: 16, height: 16 }),
12472
12862
  " Mute"
12473
- ] }) : !participant.isAgent ? /* @__PURE__ */ jsxs3(MenuItem, { onSelect: () => act({ action: "ask_unmute", identity: participant.identity }), children: [
12863
+ ] }) : !participant.isAgent ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "ask_unmute", identity: participant.identity }), children: [
12474
12864
  /* @__PURE__ */ jsx6(MicIcon, { width: 16, height: 16 }),
12475
12865
  " Ask to unmute"
12476
12866
  ] }) : null,
12477
- participant.cameraEnabled ? /* @__PURE__ */ jsxs3(MenuItem, { onSelect: () => act({ action: "stop_video", identity: participant.identity }), children: [
12867
+ participant.cameraEnabled ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "stop_video", identity: participant.identity }), children: [
12478
12868
  /* @__PURE__ */ jsx6(CameraOffIcon, { width: 16, height: 16 }),
12479
12869
  " Stop video"
12480
12870
  ] }) : null,
12481
- participant.screenSharing ? /* @__PURE__ */ jsxs3(MenuItem, { onSelect: () => act({ action: "stop_screen", identity: participant.identity }), children: [
12871
+ participant.screenSharing ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "stop_screen", identity: participant.identity }), children: [
12482
12872
  /* @__PURE__ */ jsx6(ScreenShareIcon, { width: 16, height: 16 }),
12483
12873
  " Stop screen share"
12484
12874
  ] }) : null,
12485
- participant.handRaised ? /* @__PURE__ */ jsxs3(MenuItem, { onSelect: () => act({ action: "lower_hand", identity: participant.identity }), children: [
12875
+ participant.handRaised ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "lower_hand", identity: participant.identity }), children: [
12486
12876
  /* @__PURE__ */ jsx6(HandIcon, { width: 16, height: 16 }),
12487
12877
  " Lower hand"
12488
12878
  ] }) : null,
12489
- hasAccount && !participant.isAgent && participant.role !== "cohost" ? /* @__PURE__ */ jsxs3(MenuItem, { onSelect: () => act({ action: "make_cohost", identity: participant.identity }), children: [
12879
+ hasAccount && !participant.isAgent && participant.role !== "cohost" ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "make_cohost", identity: participant.identity }), children: [
12490
12880
  /* @__PURE__ */ jsx6(PeopleIcon, { width: 16, height: 16 }),
12491
12881
  " Make co-host"
12492
12882
  ] }) : null,
12493
- !participant.isAgent && participant.role !== "cohost" && participant.role !== "host" ? participant.role === "presenter" ? /* @__PURE__ */ jsxs3(MenuItem, { onSelect: () => act({ action: "revoke_presenter", identity: participant.identity }), children: [
12883
+ !participant.isAgent && participant.role !== "cohost" && participant.role !== "host" ? participant.role === "presenter" ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "revoke_presenter", identity: participant.identity }), children: [
12494
12884
  /* @__PURE__ */ jsx6(ScreenShareIcon, { width: 16, height: 16 }),
12495
12885
  " Remove presenter"
12496
- ] }) : /* @__PURE__ */ jsxs3(MenuItem, { onSelect: () => act({ action: "make_presenter", identity: participant.identity }), children: [
12886
+ ] }) : /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "make_presenter", identity: participant.identity }), children: [
12497
12887
  /* @__PURE__ */ jsx6(ScreenShareIcon, { width: 16, height: 16 }),
12498
12888
  " Make presenter"
12499
12889
  ] }) : null,
12500
- !participant.isAgent ? /* @__PURE__ */ jsxs3(
12890
+ !participant.isAgent ? /* @__PURE__ */ jsxs4(
12501
12891
  MenuItem,
12502
12892
  {
12503
12893
  onSelect: () => {
@@ -12511,15 +12901,15 @@ function PersonMenu({
12511
12901
  }
12512
12902
  ) : null
12513
12903
  ] }) : null,
12514
- controls.isOwner && participant.role === "cohost" ? /* @__PURE__ */ jsxs3(MenuItem, { onSelect: () => act({ action: "revoke_cohost", identity: participant.identity }), children: [
12904
+ controls.isOwner && participant.role === "cohost" ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "revoke_cohost", identity: participant.identity }), children: [
12515
12905
  /* @__PURE__ */ jsx6(PeopleIcon, { width: 16, height: 16 }),
12516
12906
  " Remove co-host"
12517
12907
  ] }) : null,
12518
- controls.isOwner && !self && hasAccount && !participant.isAgent ? /* @__PURE__ */ jsxs3(MenuItem, { onSelect: () => setMode("transfer"), children: [
12908
+ controls.isOwner && !self && hasAccount && !participant.isAgent ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => setMode("transfer"), children: [
12519
12909
  /* @__PURE__ */ jsx6(SpotlightIcon, { width: 16, height: 16 }),
12520
12910
  " Make host"
12521
12911
  ] }) : null,
12522
- self ? /* @__PURE__ */ jsxs3(
12912
+ self ? /* @__PURE__ */ jsxs4(
12523
12913
  MenuItem,
12524
12914
  {
12525
12915
  onSelect: () => {
@@ -12532,7 +12922,7 @@ function PersonMenu({
12532
12922
  ]
12533
12923
  }
12534
12924
  ) : null,
12535
- !self && !participant.isAgent ? /* @__PURE__ */ jsxs3(
12925
+ !self && !participant.isAgent ? /* @__PURE__ */ jsxs4(
12536
12926
  MenuItem,
12537
12927
  {
12538
12928
  onSelect: () => {
@@ -12545,7 +12935,7 @@ function PersonMenu({
12545
12935
  ]
12546
12936
  }
12547
12937
  ) : null,
12548
- moderate && !participant.isAgent ? /* @__PURE__ */ jsxs3(MenuItem, { danger: true, onSelect: () => setMode("remove"), children: [
12938
+ moderate && !participant.isAgent ? /* @__PURE__ */ jsxs4(MenuItem, { danger: true, onSelect: () => setMode("remove"), children: [
12549
12939
  /* @__PURE__ */ jsx6(CloseIcon, { width: 16, height: 16 }),
12550
12940
  " Remove from meeting"
12551
12941
  ] }) : null
@@ -12553,7 +12943,7 @@ function PersonMenu({
12553
12943
  }
12554
12944
  function SettingsPanel({ onClose }) {
12555
12945
  const host = useRequiredMeetHost();
12556
- return /* @__PURE__ */ jsxs3(PanelShell, { title: "Settings", onClose, children: [
12946
+ return /* @__PURE__ */ jsxs4(PanelShell, { title: "Settings", onClose, children: [
12557
12947
  /* @__PURE__ */ jsx6(
12558
12948
  DeviceSettings,
12559
12949
  {
@@ -12576,15 +12966,15 @@ function DeviceSettings({
12576
12966
  const speaker = devices?.selected.audiooutput ?? host.devices.resolve("audiooutput");
12577
12967
  const stream = useMicrophoneStream(microphone);
12578
12968
  const level = useAudioLevel(stream);
12579
- const [testing, setTesting] = useState4(false);
12969
+ const [testing, setTesting] = useState5(false);
12580
12970
  useEffect6(() => {
12581
12971
  void host.devices.refresh();
12582
12972
  }, [host]);
12583
- return /* @__PURE__ */ jsxs3("section", { className: "mx-meet__section", "aria-label": "Devices", children: [
12973
+ return /* @__PURE__ */ jsxs4("section", { className: "mx-meet__section", "aria-label": "Devices", children: [
12584
12974
  /* @__PURE__ */ jsx6(DevicePicker, { kind: "audioinput", label: "Microphone", onPick }),
12585
12975
  /* @__PURE__ */ jsx6("div", { className: "mx-meet__meter", role: "meter", "aria-label": "Microphone level", "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": Math.round(level * 100), children: /* @__PURE__ */ jsx6("span", { style: { width: `${Math.min(100, Math.round(level * 160))}%` } }) }),
12586
12976
  /* @__PURE__ */ jsx6(DevicePicker, { kind: "audiooutput", label: "Speaker", onPick }),
12587
- /* @__PURE__ */ jsxs3(
12977
+ /* @__PURE__ */ jsxs4(
12588
12978
  "button",
12589
12979
  {
12590
12980
  type: "button",
@@ -12606,7 +12996,7 @@ function DeviceSettings({
12606
12996
  }
12607
12997
  function EffectsSettings({ preview }) {
12608
12998
  const effects = useMediaEffects();
12609
- const [error, setError] = useState4(null);
12999
+ const [error, setError] = useState5(null);
12610
13000
  const fileRef = useRef6(null);
12611
13001
  const supported = effects.backgroundsSupported || preview != null || videoEffectsSupported();
12612
13002
  const apply = (next) => {
@@ -12619,8 +13009,8 @@ function EffectsSettings({ preview }) {
12619
13009
  );
12620
13010
  }
12621
13011
  };
12622
- return /* @__PURE__ */ jsxs3("section", { className: "mx-meet__section", "aria-label": "Effects", children: [
12623
- /* @__PURE__ */ jsxs3("div", { className: "mx-meet__check", children: [
13012
+ return /* @__PURE__ */ jsxs4("section", { className: "mx-meet__section", "aria-label": "Effects", children: [
13013
+ /* @__PURE__ */ jsxs4("div", { className: "mx-meet__check", children: [
12624
13014
  /* @__PURE__ */ jsx6(
12625
13015
  Checkbox,
12626
13016
  {
@@ -12629,12 +13019,12 @@ function EffectsSettings({ preview }) {
12629
13019
  onCheckedChange: (checked) => apply({ noiseSuppression: checked === true })
12630
13020
  }
12631
13021
  ),
12632
- /* @__PURE__ */ jsxs3("div", { className: "mx-meet__check-text", children: [
13022
+ /* @__PURE__ */ jsxs4("div", { className: "mx-meet__check-text", children: [
12633
13023
  /* @__PURE__ */ jsx6(Label, { htmlFor: "mx-meet-noise", children: "Noise suppression" }),
12634
13024
  /* @__PURE__ */ jsx6("span", { className: "mx-meet__hint", children: "Filters keyboards, fans and background chatter." })
12635
13025
  ] })
12636
13026
  ] }),
12637
- supported ? /* @__PURE__ */ jsxs3("div", { className: "mx-meet__field", children: [
13027
+ supported ? /* @__PURE__ */ jsxs4("div", { className: "mx-meet__field", children: [
12638
13028
  /* @__PURE__ */ jsx6(Label, { children: "Background" }),
12639
13029
  /* @__PURE__ */ jsx6(
12640
13030
  SegmentedControl,
@@ -12728,14 +13118,20 @@ async function playTestSound(sinkId) {
12728
13118
  audio.pause();
12729
13119
  await context.close();
12730
13120
  }
12731
- function useMicrophoneStream(deviceId2) {
12732
- const [stream, setStream] = useState4(null);
13121
+ function useMicrophoneStream(deviceId2, report, attempt = 0) {
13122
+ const [stream, setStream] = useState5(null);
13123
+ const reportRef = useRef6(report);
13124
+ reportRef.current = report;
12733
13125
  useEffect6(() => {
12734
- if (deviceId2 === "off") return void 0;
13126
+ if (deviceId2 === "off") {
13127
+ reportRef.current?.("off");
13128
+ return void 0;
13129
+ }
12735
13130
  let live = true;
12736
13131
  let opened = null;
12737
13132
  const media = globalThis.navigator?.mediaDevices;
12738
13133
  if (media === void 0) return void 0;
13134
+ reportRef.current?.("prompting");
12739
13135
  void media.getUserMedia({ audio: deviceId2 === null ? true : { deviceId: { exact: deviceId2 } } }).then((next) => {
12740
13136
  if (!live) {
12741
13137
  next.getTracks().forEach((track) => track.stop());
@@ -12743,20 +13139,54 @@ function useMicrophoneStream(deviceId2) {
12743
13139
  }
12744
13140
  opened = next;
12745
13141
  setStream(next);
12746
- }).catch(() => setStream(null));
13142
+ reportRef.current?.("on");
13143
+ }).catch((thrown) => {
13144
+ setStream(null);
13145
+ if (live) reportRef.current?.({ error: thrown });
13146
+ });
12747
13147
  return () => {
12748
13148
  live = false;
12749
13149
  opened?.getTracks().forEach((track) => track.stop());
12750
13150
  setStream(null);
12751
13151
  };
12752
- }, [deviceId2]);
13152
+ }, [deviceId2, attempt]);
12753
13153
  return stream;
12754
13154
  }
13155
+ function PreviewStatus({ onRetry }) {
13156
+ const { region, where } = useMediaSupervisor();
13157
+ const [waited, setWaited] = useState5(false);
13158
+ const prompting = region.preview.microphone.state === "prompting" || region.preview.camera.state === "prompting";
13159
+ useEffect6(() => {
13160
+ if (!prompting) {
13161
+ setWaited(false);
13162
+ return void 0;
13163
+ }
13164
+ const timer = setTimeout(() => setWaited(true), 800);
13165
+ return () => clearTimeout(timer);
13166
+ }, [prompting]);
13167
+ const refused = ["microphone", "camera"].flatMap((kind) => {
13168
+ const preview = region.preview[kind];
13169
+ const reason = region.permission[kind] === "denied" ? "denied" : preview.state === "unavailable" ? preview.unavailable?.reason ?? "failed" : null;
13170
+ return reason === null ? [] : [{ kind, reason }];
13171
+ });
13172
+ if (refused.length === 0) {
13173
+ if (!prompting || !waited) return null;
13174
+ return /* @__PURE__ */ jsx6("p", { className: "mx-meet__panel-note", role: "status", "data-meet-notice": "permission-prompt", children: "Allow camera and microphone when your browser asks" });
13175
+ }
13176
+ const first = refused[0];
13177
+ const both = refused.length === 2 && refused[0].reason === refused[1].reason;
13178
+ const label = both ? deviceChipLabel("camera", first.reason).replace(/^Camera/, "Camera and mic") : refused.map((r) => deviceChipLabel(r.kind, r.reason)).join(" \xB7 ");
13179
+ return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__warning", role: "status", "data-meet-notice": deviceNoticeCode(first.kind, first.reason), children: [
13180
+ /* @__PURE__ */ jsx6("strong", { children: label }),
13181
+ /* @__PURE__ */ jsx6("ol", { className: "mx-meet__fix-steps", children: deviceFixSteps(first.kind, first.reason, where).map((step) => /* @__PURE__ */ jsx6("li", { children: step }, step)) }),
13182
+ /* @__PURE__ */ jsx6(Button, { type: "button", variant: "outline", size: "sm", onClick: onRetry, children: "Try again" })
13183
+ ] });
13184
+ }
12755
13185
  function KnockNotice({ onView }) {
12756
13186
  const { knocker, others, admit, dismiss } = useKnockNotice();
12757
13187
  if (knocker === null) return null;
12758
- return /* @__PURE__ */ jsxs3("div", { className: "mx-meet__notice-bar", role: "status", "data-meet-notice": "knock-received", "data-meet-participant-name": knocker.displayName, children: [
12759
- /* @__PURE__ */ jsxs3("span", { children: [
13188
+ return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__notice-bar", role: "status", "data-meet-notice": "knock-received", "data-meet-participant-name": knocker.displayName, children: [
13189
+ /* @__PURE__ */ jsxs4("span", { children: [
12760
13190
  knocker.displayName,
12761
13191
  " wants to join",
12762
13192
  others > 0 ? ` (+${others} more)` : ""
@@ -12780,15 +13210,15 @@ function KnockNotice({ onView }) {
12780
13210
  function LobbyPanel() {
12781
13211
  const lobby = useLobby();
12782
13212
  if (!lobby.canAdmit || lobby.waiting.length === 0 && lobby.declined.length === 0) return null;
12783
- return /* @__PURE__ */ jsxs3(Fragment, { children: [
13213
+ return /* @__PURE__ */ jsxs4(Fragment, { children: [
12784
13214
  lobby.waiting.length > 0 ? /* @__PURE__ */ jsx6(WaitingList, { lobby }) : null,
12785
13215
  lobby.declined.length > 0 ? /* @__PURE__ */ jsx6(DeclinedList, { lobby }) : null
12786
13216
  ] });
12787
13217
  }
12788
13218
  function DeclinedList({ lobby }) {
12789
- return /* @__PURE__ */ jsxs3("section", { className: "mx-meet__lobby", "aria-label": "Declined requests", "data-meet-declined": "", children: [
13219
+ return /* @__PURE__ */ jsxs4("section", { className: "mx-meet__lobby", "aria-label": "Declined requests", "data-meet-declined": "", children: [
12790
13220
  /* @__PURE__ */ jsx6("header", { className: "mx-meet__lobby-head", children: /* @__PURE__ */ jsx6("h3", { className: "mx-meet__lobby-title", children: "Declined" }) }),
12791
- /* @__PURE__ */ jsx6("ul", { className: "mx-meet__lobby-list", children: lobby.declined.map((entry) => /* @__PURE__ */ jsxs3(
13221
+ /* @__PURE__ */ jsx6("ul", { className: "mx-meet__lobby-list", children: lobby.declined.map((entry) => /* @__PURE__ */ jsxs4(
12792
13222
  "li",
12793
13223
  {
12794
13224
  className: "mx-meet__lobby-row",
@@ -12814,12 +13244,12 @@ function DeclinedList({ lobby }) {
12814
13244
  ] });
12815
13245
  }
12816
13246
  function WaitingList({ lobby }) {
12817
- return /* @__PURE__ */ jsxs3("section", { className: "mx-meet__lobby", "aria-label": "Waiting room", children: [
12818
- /* @__PURE__ */ jsxs3("header", { className: "mx-meet__lobby-head", children: [
13247
+ return /* @__PURE__ */ jsxs4("section", { className: "mx-meet__lobby", "aria-label": "Waiting room", children: [
13248
+ /* @__PURE__ */ jsxs4("header", { className: "mx-meet__lobby-head", children: [
12819
13249
  /* @__PURE__ */ jsx6("h3", { className: "mx-meet__lobby-title", children: lobby.waiting.length === 1 ? "1 person is waiting" : `${lobby.waiting.length} people are waiting` }),
12820
13250
  /* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__link", onClick: () => void lobby.admitAll(), children: "Admit all" })
12821
13251
  ] }),
12822
- /* @__PURE__ */ jsx6("ul", { className: "mx-meet__lobby-list", children: lobby.waiting.map((entry) => /* @__PURE__ */ jsxs3(
13252
+ /* @__PURE__ */ jsx6("ul", { className: "mx-meet__lobby-list", children: lobby.waiting.map((entry) => /* @__PURE__ */ jsxs4(
12823
13253
  "li",
12824
13254
  {
12825
13255
  className: "mx-meet__lobby-row",
@@ -12827,9 +13257,13 @@ function WaitingList({ lobby }) {
12827
13257
  "data-meet-participant-name": entry.displayName,
12828
13258
  children: [
12829
13259
  /* @__PURE__ */ jsx6(Avatar, { name: entry.displayName, url: entry.avatarUrl, size: 32 }),
12830
- /* @__PURE__ */ jsxs3("span", { className: "mx-meet__person-name", children: [
13260
+ /* @__PURE__ */ jsxs4("span", { className: "mx-meet__person-name", children: [
12831
13261
  entry.displayName,
12832
- entry.userId === null ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__badge", children: "Guest" }) : null
13262
+ entry.userId === null ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__badge", children: "Guest" }) : null,
13263
+ entry.flag === "previously_removed" ? (
13264
+ // `mod-removed-bypass`: advice for the host, never a block — Admit stays.
13265
+ /* @__PURE__ */ jsx6("span", { className: "mx-meet__badge mx-meet__badge--warn", "data-meet-notice": "knock-flagged", children: "Previously removed" })
13266
+ ) : null
12833
13267
  ] }),
12834
13268
  /* @__PURE__ */ jsx6(ControlButton, { label: `Admit ${entry.displayName}`, onClick: () => void lobby.admit(entry), children: /* @__PURE__ */ jsx6(CheckIcon, { width: 16, height: 16 }) }),
12835
13269
  /* @__PURE__ */ jsx6(
@@ -12851,17 +13285,17 @@ function NoteTakerRow() {
12851
13285
  const ai = useMeetAi();
12852
13286
  const status = ai.noteTaker;
12853
13287
  const duplicateError = status.refusal !== null && ai.error !== null && status.refusal.reason === ai.error.message && status.refusal.remedy === ai.error.remedy;
12854
- return /* @__PURE__ */ jsxs3("section", { className: "mx-meet__note-taker", "aria-label": "Note-taker", children: [
12855
- /* @__PURE__ */ jsxs3("p", { className: `mx-meet__note-taker-state mx-meet__note-taker-state--${status.state}`, children: [
13288
+ return /* @__PURE__ */ jsxs4("section", { className: "mx-meet__note-taker", "aria-label": "Note-taker", children: [
13289
+ /* @__PURE__ */ jsxs4("p", { className: `mx-meet__note-taker-state mx-meet__note-taker-state--${status.state}`, children: [
12856
13290
  /* @__PURE__ */ jsx6("span", { className: "mx-meet__note-taker-dot", "aria-hidden": "true" }),
12857
13291
  ai.noteTakerLabel
12858
13292
  ] }),
12859
13293
  status.detail !== null ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__panel-note", children: status.detail }) : null,
12860
- status.refusal !== null ? /* @__PURE__ */ jsxs3(ErrorBox, { as: "div", className: "mx-meet__refusal", error: status.refusal, operation: "Join this meeting", origin: "meet/components", children: [
13294
+ status.refusal !== null ? /* @__PURE__ */ jsxs4(ErrorBox, { as: "div", className: "mx-meet__refusal", error: status.refusal, operation: "Join this meeting", origin: "meet/components", children: [
12861
13295
  /* @__PURE__ */ jsx6("p", { className: "mx-meet__refusal-reason", children: status.refusal.reason }),
12862
13296
  status.refusal.remedy.length > 0 ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__refusal-remedy", children: status.refusal.remedy }) : null
12863
13297
  ] }) : null,
12864
- ai.error !== null && !duplicateError ? /* @__PURE__ */ jsxs3(ErrorBox, { as: "div", className: "mx-meet__refusal", error: ai.error, operation: "Run the meeting assistant", origin: "meet/components", children: [
13298
+ ai.error !== null && !duplicateError ? /* @__PURE__ */ jsxs4(ErrorBox, { as: "div", className: "mx-meet__refusal", error: ai.error, operation: "Run the meeting assistant", origin: "meet/components", children: [
12865
13299
  /* @__PURE__ */ jsx6("p", { className: "mx-meet__refusal-reason", children: ai.error.message }),
12866
13300
  /* @__PURE__ */ jsx6("p", { className: "mx-meet__refusal-remedy", children: ai.error.remedy })
12867
13301
  ] }) : null,
@@ -12889,9 +13323,9 @@ function NoteList({
12889
13323
  notes,
12890
13324
  empty
12891
13325
  }) {
12892
- return /* @__PURE__ */ jsxs3("section", { className: "mx-meet__note-group", "aria-label": title, children: [
13326
+ return /* @__PURE__ */ jsxs4("section", { className: "mx-meet__note-group", "aria-label": title, children: [
12893
13327
  /* @__PURE__ */ jsx6("h3", { className: "mx-meet__note-group-title", children: title }),
12894
- notes.length === 0 ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__panel-note", children: empty }) : /* @__PURE__ */ jsx6("ul", { className: "mx-meet__notes", children: notes.map((note) => /* @__PURE__ */ jsxs3("li", { className: "mx-meet__note", children: [
13328
+ notes.length === 0 ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__panel-note", children: empty }) : /* @__PURE__ */ jsx6("ul", { className: "mx-meet__notes", children: notes.map((note) => /* @__PURE__ */ jsxs4("li", { className: "mx-meet__note", children: [
12895
13329
  note.text,
12896
13330
  note.assigneeDisplayName !== void 0 && note.assigneeDisplayName !== null ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__assignee", children: note.assigneeDisplayName }) : null
12897
13331
  ] }, note.id)) })
@@ -12899,14 +13333,14 @@ function NoteList({
12899
13333
  }
12900
13334
  function AiPanel({ onClose }) {
12901
13335
  const ai = useMeetAi();
12902
- const [question, setQuestion] = useState4("");
12903
- return /* @__PURE__ */ jsxs3(PanelShell, { title: "Meeting assistant", onClose, children: [
13336
+ const [question, setQuestion] = useState5("");
13337
+ return /* @__PURE__ */ jsxs4(PanelShell, { title: "Meeting assistant", onClose, children: [
12904
13338
  /* @__PURE__ */ jsx6(NoteTakerRow, {}),
12905
- ai.summary !== null ? /* @__PURE__ */ jsxs3("section", { className: "mx-meet__note-group", "aria-label": "Summary", children: [
13339
+ ai.summary !== null ? /* @__PURE__ */ jsxs4("section", { className: "mx-meet__note-group", "aria-label": "Summary", children: [
12906
13340
  /* @__PURE__ */ jsx6("h3", { className: "mx-meet__note-group-title", children: "Summary" }),
12907
13341
  /* @__PURE__ */ jsx6("p", { className: "mx-meet__summary", children: ai.summary.text })
12908
13342
  ] }) : null,
12909
- ai.wrapUp !== null ? /* @__PURE__ */ jsxs3("p", { className: "mx-meet__wrap-up-notice", role: "status", children: [
13343
+ ai.wrapUp !== null ? /* @__PURE__ */ jsxs4("p", { className: "mx-meet__wrap-up-notice", role: "status", children: [
12910
13344
  "The wrap-up is written \u2014 ",
12911
13345
  ai.wrapUp.noteIds.length,
12912
13346
  " ",
@@ -12942,9 +13376,9 @@ function AiPanel({ onClose }) {
12942
13376
  empty: "No action items yet."
12943
13377
  }
12944
13378
  ),
12945
- ai.transcript.length > 0 ? /* @__PURE__ */ jsxs3("section", { className: "mx-meet__note-group", "aria-label": "Transcript", children: [
13379
+ ai.transcript.length > 0 ? /* @__PURE__ */ jsxs4("section", { className: "mx-meet__note-group", "aria-label": "Transcript", children: [
12946
13380
  /* @__PURE__ */ jsx6("h3", { className: "mx-meet__note-group-title", children: "Transcript" }),
12947
- /* @__PURE__ */ jsx6("ul", { className: "mx-meet__transcript", children: ai.transcript.map((line) => /* @__PURE__ */ jsxs3(
13381
+ /* @__PURE__ */ jsx6("ul", { className: "mx-meet__transcript", children: ai.transcript.map((line) => /* @__PURE__ */ jsxs4(
12948
13382
  "li",
12949
13383
  {
12950
13384
  className: line.final && line.source === "record" ? "mx-meet__line" : "mx-meet__line mx-meet__line--interim",
@@ -12956,7 +13390,7 @@ function AiPanel({ onClose }) {
12956
13390
  line.id
12957
13391
  )) })
12958
13392
  ] }) : null,
12959
- /* @__PURE__ */ jsxs3(
13393
+ /* @__PURE__ */ jsxs4(
12960
13394
  "form",
12961
13395
  {
12962
13396
  className: "mx-meet__composer",
@@ -12983,7 +13417,7 @@ function AiPanel({ onClose }) {
12983
13417
  ),
12984
13418
  ai.asking && ai.phase !== null ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__panel-note", role: "status", children: ai.phase }) : null,
12985
13419
  ai.answer !== null ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__answer", children: ai.answer }) : null,
12986
- ai.answer !== null && ai.coverage !== null ? /* @__PURE__ */ jsxs3("p", { className: "mx-meet__coverage", children: [
13420
+ ai.answer !== null && ai.coverage !== null ? /* @__PURE__ */ jsxs4("p", { className: "mx-meet__coverage", children: [
12987
13421
  "Answered from ",
12988
13422
  ai.coverage.segmentsUsed,
12989
13423
  " of ",
@@ -12992,7 +13426,7 @@ function AiPanel({ onClose }) {
12992
13426
  ai.coverage.truncated ? " (the oldest were left out)" : "",
12993
13427
  "."
12994
13428
  ] }) : null,
12995
- ai.error !== null ? /* @__PURE__ */ jsxs3(ErrorBox, { as: "div", className: "mx-meet__refusal", error: ai.error, operation: "Run the meeting assistant", origin: "meet/components", children: [
13429
+ ai.error !== null ? /* @__PURE__ */ jsxs4(ErrorBox, { as: "div", className: "mx-meet__refusal", error: ai.error, operation: "Run the meeting assistant", origin: "meet/components", children: [
12996
13430
  /* @__PURE__ */ jsx6("p", { className: "mx-meet__refusal-reason", children: ai.error.message }),
12997
13431
  /* @__PURE__ */ jsx6("p", { className: "mx-meet__refusal-remedy", children: ai.error.remedy })
12998
13432
  ] }) : null
@@ -13005,7 +13439,7 @@ function Captions({ lines = 3 }) {
13005
13439
  const captions = useCaptions();
13006
13440
  if (!captions.on) return null;
13007
13441
  if (captions.state === "unavailable") {
13008
- return /* @__PURE__ */ jsx6("div", { className: "mx-meet__captions", role: "status", "data-meet-notice": "captions-unavailable", children: /* @__PURE__ */ jsxs3("p", { className: "mx-meet__caption", children: [
13442
+ return /* @__PURE__ */ jsx6("div", { className: "mx-meet__captions", role: "status", "data-meet-notice": "captions-unavailable", children: /* @__PURE__ */ jsxs4("p", { className: "mx-meet__caption", children: [
13009
13443
  "Captions are unavailable. ",
13010
13444
  captions.reason,
13011
13445
  captions.remedy !== null ? ` ${captions.remedy}` : ""
@@ -13014,10 +13448,10 @@ function Captions({ lines = 3 }) {
13014
13448
  if (visible.length === 0) {
13015
13449
  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." }) });
13016
13450
  }
13017
- return /* @__PURE__ */ jsxs3("div", { className: "mx-meet__captions", "aria-live": "polite", "aria-label": "Live captions", "data-meet-caption": "live", children: [
13451
+ return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__captions", "aria-live": "polite", "aria-label": "Live captions", "data-meet-caption": "live", children: [
13018
13452
  visible.map((line) => {
13019
13453
  const translated = translation.language === null ? void 0 : translation.translations[line.id];
13020
- return /* @__PURE__ */ jsxs3(
13454
+ return /* @__PURE__ */ jsxs4(
13021
13455
  "p",
13022
13456
  {
13023
13457
  className: line.final ? "mx-meet__caption" : "mx-meet__caption mx-meet__caption--interim",
@@ -13045,7 +13479,7 @@ function AttendanceNotice() {
13045
13479
  if (notice === null) return null;
13046
13480
  const refused = media.microphone.unavailable;
13047
13481
  const code = microphoneNoticeCode(media.microphone);
13048
- return /* @__PURE__ */ jsxs3(
13482
+ return /* @__PURE__ */ jsxs4(
13049
13483
  "p",
13050
13484
  {
13051
13485
  className: "mx-meet__banner mx-meet__banner--attendance",
@@ -13076,15 +13510,22 @@ function PreJoinBody({
13076
13510
  const recording = useRecording();
13077
13511
  const effects = useMediaEffects();
13078
13512
  const { notice } = useModerationNotice();
13079
- const [mode, setMode] = useState4("video");
13080
- const [microphone, setMicrophone] = useState4(true);
13081
- const [joining, setJoining] = useState4(false);
13513
+ const [mode, setMode] = useState5("video");
13514
+ const [microphone, setMicrophone] = useState5(true);
13515
+ const [joining, setJoining] = useState5(false);
13082
13516
  const camera = devices?.selected.videoinput ?? host.devices.resolve("videoinput");
13083
13517
  const mic = devices?.selected.audioinput ?? host.devices.resolve("audioinput");
13084
- const preview = useCameraPreview(mode === "video" ? camera : void 0, effects.effects);
13085
- const micStream = useMicrophoneStream(microphone ? mic : "off");
13518
+ const { reportPreview } = useMediaSupervisor();
13519
+ const [attempt, setAttempt] = useState5(0);
13520
+ const preview = useCameraPreview(
13521
+ mode === "video" ? camera : void 0,
13522
+ effects.effects,
13523
+ (outcome) => reportPreview("camera", outcome),
13524
+ attempt
13525
+ );
13526
+ const micStream = useMicrophoneStream(microphone ? mic : "off", (outcome) => reportPreview("microphone", outcome), attempt);
13086
13527
  const level = useAudioLevel(micStream);
13087
- const [speakerTesting, setSpeakerTesting] = useState4(false);
13528
+ const [speakerTesting, setSpeakerTesting] = useState5(false);
13088
13529
  useEffect6(() => {
13089
13530
  void host.devices.refresh();
13090
13531
  }, [host]);
@@ -13107,8 +13548,8 @@ function PreJoinBody({
13107
13548
  ...secondDevice !== void 0 ? { secondDevice } : {}
13108
13549
  }).then(() => onJoined?.()).catch(() => void 0).finally(() => setJoining(false));
13109
13550
  };
13110
- return /* @__PURE__ */ jsxs3("div", { className: "mx-meet__prejoin", children: [
13111
- /* @__PURE__ */ jsxs3("div", { className: "mx-meet__preview", children: [
13551
+ return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__prejoin", children: [
13552
+ /* @__PURE__ */ jsxs4("div", { className: "mx-meet__preview", children: [
13112
13553
  mode === "video" && preview.preview !== null ? /* @__PURE__ */ jsx6(
13113
13554
  "video",
13114
13555
  {
@@ -13124,10 +13565,11 @@ function PreJoinBody({
13124
13565
  mode === "video" && preview.error !== null ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__preview-note", children: preview.error }) : null,
13125
13566
  microphone && micStream !== null ? /* @__PURE__ */ jsx6("div", { className: "mx-meet__meter mx-meet__meter--preview", role: "meter", "aria-label": "Microphone level", "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuenow": Math.round(level * 100), children: /* @__PURE__ */ jsx6("span", { style: { width: `${Math.min(100, Math.round(level * 160))}%` } }) }) : null
13126
13567
  ] }),
13127
- /* @__PURE__ */ jsxs3("div", { className: "mx-meet__prejoin-panel", children: [
13568
+ /* @__PURE__ */ jsxs4("div", { className: "mx-meet__prejoin-panel", children: [
13128
13569
  /* @__PURE__ */ jsx6("h1", { className: "mx-meet__prejoin-title", children: "Ready to join?" }),
13570
+ /* @__PURE__ */ jsx6(PreviewStatus, { onRetry: () => setAttempt((n) => n + 1) }),
13129
13571
  notice?.kind === "removed" ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__warning", children: notice.text }) : null,
13130
- devices?.labelsHidden === true ? /* @__PURE__ */ jsxs3("p", { className: "mx-meet__panel-note", children: [
13572
+ devices?.labelsHidden === true ? /* @__PURE__ */ jsxs4("p", { className: "mx-meet__panel-note", children: [
13131
13573
  "Your browser is hiding device names until you allow camera and microphone access.",
13132
13574
  /* @__PURE__ */ jsx6(
13133
13575
  "button",
@@ -13143,9 +13585,9 @@ function PreJoinBody({
13143
13585
  ] }) : null,
13144
13586
  devices?.fallbackNotice != null ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__warning", children: devices.fallbackNotice }) : null,
13145
13587
  /* @__PURE__ */ jsx6(DevicePicker, { kind: "audioinput", label: "Microphone" }),
13146
- /* @__PURE__ */ jsxs3("div", { className: "mx-meet__field-row", children: [
13588
+ /* @__PURE__ */ jsxs4("div", { className: "mx-meet__field-row", children: [
13147
13589
  /* @__PURE__ */ jsx6(DevicePicker, { kind: "audiooutput", label: "Speaker" }),
13148
- /* @__PURE__ */ jsxs3(
13590
+ /* @__PURE__ */ jsxs4(
13149
13591
  Button,
13150
13592
  {
13151
13593
  type: "button",
@@ -13168,8 +13610,8 @@ function PreJoinBody({
13168
13610
  /* @__PURE__ */ jsx6(DevicePicker, { kind: "videoinput", label: "Camera" }),
13169
13611
  /* @__PURE__ */ jsx6(EffectsSettings, { preview: preview.preview }),
13170
13612
  recording.consentNotice !== null ? /* @__PURE__ */ jsx6(Alert, { variant: "info", children: /* @__PURE__ */ jsx6(AlertDescription, { children: recording.consentNotice }) }) : null,
13171
- /* @__PURE__ */ jsxs3("div", { className: "mx-meet__prejoin-actions", children: [
13172
- /* @__PURE__ */ jsxs3("div", { className: "mx-meet__check", children: [
13613
+ /* @__PURE__ */ jsxs4("div", { className: "mx-meet__prejoin-actions", children: [
13614
+ /* @__PURE__ */ jsxs4("div", { className: "mx-meet__check", children: [
13173
13615
  /* @__PURE__ */ jsx6(
13174
13616
  Checkbox,
13175
13617
  {
@@ -13180,7 +13622,7 @@ function PreJoinBody({
13180
13622
  ),
13181
13623
  /* @__PURE__ */ jsx6(Label, { htmlFor: "mx-meet-join-video", children: "Join with video" })
13182
13624
  ] }),
13183
- /* @__PURE__ */ jsxs3("div", { className: "mx-meet__check", children: [
13625
+ /* @__PURE__ */ jsxs4("div", { className: "mx-meet__check", children: [
13184
13626
  /* @__PURE__ */ jsx6(
13185
13627
  Checkbox,
13186
13628
  {
@@ -13194,7 +13636,7 @@ function PreJoinBody({
13194
13636
  room.secondDevice === null ? /* @__PURE__ */ jsx6(Button, { type: "button", className: "mx-meet__join", disabled: joining, onClick: () => joinWith(), children: joining ? "Joining\u2026" : observe2 ? "Observe" : "Join now" }) : (
13195
13637
  // S7: ALREADY IN THIS MEETING on another tab or device — the meeting's choice
13196
13638
  // (Meet: Switch here / Join here too; Teams: Transfer here / Add this device).
13197
- /* @__PURE__ */ jsxs3("div", { className: "mx-meet__second-device", "data-meet-region": "second-device", children: [
13639
+ /* @__PURE__ */ jsxs4("div", { className: "mx-meet__second-device", "data-meet-region": "second-device", children: [
13198
13640
  /* @__PURE__ */ jsx6("p", { className: "mx-meet__hint", children: "You're in this meeting on another device" }),
13199
13641
  /* @__PURE__ */ jsx6(
13200
13642
  Button,
@@ -13221,23 +13663,29 @@ function PreJoinBody({
13221
13663
  ] })
13222
13664
  )
13223
13665
  ] }),
13224
- room.failure !== null ? /* @__PURE__ */ jsxs3("p", { className: "mx-meet__error", children: [
13666
+ room.failure !== null ? /* @__PURE__ */ jsxs4("p", { className: "mx-meet__error", children: [
13225
13667
  room.failure.message,
13226
13668
  /* @__PURE__ */ jsx6("span", { className: "mx-meet__remedy", children: room.failure.remedy })
13227
13669
  ] }) : null
13228
13670
  ] })
13229
13671
  ] });
13230
13672
  }
13231
- function useCameraPreview(deviceId2, effects) {
13232
- const [preview, setPreview] = useState4(null);
13233
- const [error, setError] = useState4(null);
13673
+ function useCameraPreview(deviceId2, effects, report, attempt = 0) {
13674
+ const reportRef = useRef6(report);
13675
+ reportRef.current = report;
13676
+ const [preview, setPreview] = useState5(null);
13677
+ const [error, setError] = useState5(null);
13234
13678
  const current = useRef6(null);
13235
13679
  const initialEffect = useRef6(toVideoEffect(effects));
13236
13680
  initialEffect.current = toVideoEffect(effects);
13237
13681
  useEffect6(() => {
13238
- if (deviceId2 === void 0) return void 0;
13682
+ if (deviceId2 === void 0) {
13683
+ reportRef.current?.("off");
13684
+ return void 0;
13685
+ }
13239
13686
  let live = true;
13240
13687
  setError(null);
13688
+ reportRef.current?.("prompting");
13241
13689
  void createCameraPreview(deviceId2, initialEffect.current).then((created) => {
13242
13690
  if (!live) {
13243
13691
  created.stop();
@@ -13245,8 +13693,10 @@ function useCameraPreview(deviceId2, effects) {
13245
13693
  }
13246
13694
  current.current = created;
13247
13695
  setPreview(created);
13696
+ reportRef.current?.("on");
13248
13697
  }).catch((thrown) => {
13249
13698
  if (!live) return;
13699
+ reportRef.current?.({ error: thrown });
13250
13700
  const failure = thrown;
13251
13701
  const message = (failure.message ?? "").replace(/^meet\.[A-Za-z.()]+:\s*/, "");
13252
13702
  const sentence = message.length > 0 ? message.charAt(0).toUpperCase() + message.slice(1) : "";
@@ -13258,7 +13708,7 @@ function useCameraPreview(deviceId2, effects) {
13258
13708
  current.current = null;
13259
13709
  setPreview(null);
13260
13710
  };
13261
- }, [deviceId2]);
13711
+ }, [deviceId2, attempt]);
13262
13712
  return {
13263
13713
  preview,
13264
13714
  error,
@@ -13281,9 +13731,9 @@ function DevicePicker({
13281
13731
  const triggerId = `mx-meet-device-${kind}`;
13282
13732
  const valueOf = (deviceId2) => deviceId2.length > 0 ? deviceId2 : "default";
13283
13733
  const current = devices?.selected[kind] ?? host.devices.resolve(kind) ?? "";
13284
- return /* @__PURE__ */ jsxs3("div", { className: "mx-meet__field", children: [
13734
+ return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__field", children: [
13285
13735
  /* @__PURE__ */ jsx6(Label, { htmlFor: triggerId, children: label }),
13286
- /* @__PURE__ */ jsxs3(
13736
+ /* @__PURE__ */ jsxs4(
13287
13737
  Select,
13288
13738
  {
13289
13739
  ...current.length > 0 ? { value: valueOf(current) } : {},
@@ -13370,19 +13820,19 @@ function MeetSkinRoom({
13370
13820
  if (screen === "refused" || screen === "exit") {
13371
13821
  return /* @__PURE__ */ jsx6("div", { className: "mx-meet mx-meet--lobby", children: /* @__PURE__ */ jsx6(ExitScreen, { ...onLeave !== void 0 ? { onLeave } : {} }) });
13372
13822
  }
13373
- return /* @__PURE__ */ jsxs3("div", { className: "mx-meet", children: [
13823
+ return /* @__PURE__ */ jsxs4("div", { className: "mx-meet", children: [
13374
13824
  /* @__PURE__ */ jsx6(ConsentNotice, {}),
13375
13825
  /* @__PURE__ */ jsx6(AttendanceNotice, {}),
13376
- /* @__PURE__ */ jsxs3("header", { className: "mx-meet__header", children: [
13826
+ /* @__PURE__ */ jsxs4("header", { className: "mx-meet__header", children: [
13377
13827
  /* @__PURE__ */ jsx6("h1", { className: "mx-meet__title", children: snapshot?.meeting?.title ?? "Meeting" }),
13378
- /* @__PURE__ */ jsxs3("span", { className: "mx-meet__meta", children: [
13828
+ /* @__PURE__ */ jsxs4("span", { className: "mx-meet__meta", children: [
13379
13829
  participantSummary(snapshot?.participants ?? []),
13380
13830
  elapsed > 0 ? ` \xB7 ${formatDurationMs3(elapsed)}` : ""
13381
13831
  ] }),
13382
13832
  /* @__PURE__ */ jsx6(RecordingIndicator, {}),
13383
13833
  captureHeldOf(snapshot?.meeting) ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__badge", "data-meet-capture-held": "", children: "Confidential \xB7 not recorded" }) : null,
13384
13834
  isObserverRole(snapshot?.grants.role) ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__badge", "data-meet-observing": "self", children: "Observing" }) : null,
13385
- snapshot?.locked === true ? /* @__PURE__ */ jsxs3("span", { className: "mx-meet__badge", children: [
13835
+ snapshot?.locked === true ? /* @__PURE__ */ jsxs4("span", { className: "mx-meet__badge", children: [
13386
13836
  /* @__PURE__ */ jsx6(LockIcon, { width: 12, height: 12 }),
13387
13837
  " Locked"
13388
13838
  ] }) : null,
@@ -13398,9 +13848,17 @@ function MeetSkinRoom({
13398
13848
  }
13399
13849
  function ShareNotice() {
13400
13850
  const { share, actions } = useMeetCore();
13851
+ const [soundHintClosed, setSoundHintClosed] = useState5(null);
13852
+ if (share.state === "presenting" && share.audio === false && soundHintClosed !== share.at) {
13853
+ return /* @__PURE__ */ jsxs4("p", { className: "mx-meet__banner", role: "status", "data-meet-notice": "share-audio-missing", children: [
13854
+ "Sound not shared",
13855
+ /* @__PURE__ */ jsx6("span", { className: "mx-meet__remedy", children: "To include sound, share a tab and turn on Also share tab audio" }),
13856
+ /* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__link", onClick: () => setSoundHintClosed(share.at), children: "Dismiss" })
13857
+ ] });
13858
+ }
13401
13859
  if (share.state !== "refused") return null;
13402
13860
  const text3 = share.reason === "unsupported" ? "You can't share your screen from this browser" : share.reason === "blocked" ? "Screen sharing is blocked" : "Couldn't start sharing your screen";
13403
- return /* @__PURE__ */ jsxs3("p", { className: "mx-meet__banner", role: "status", "data-meet-notice": "share-unavailable", children: [
13861
+ return /* @__PURE__ */ jsxs4("p", { className: "mx-meet__banner", role: "status", "data-meet-notice": "share-unavailable", children: [
13404
13862
  text3,
13405
13863
  share.remedy !== null ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__remedy", children: share.remedy }) : null,
13406
13864
  /* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__link", onClick: actions.dismissShareNotice, children: "Dismiss" })
@@ -13428,9 +13886,22 @@ function clockText(ms2) {
13428
13886
  }
13429
13887
  function ExitScreen({ onLeave }) {
13430
13888
  const { phase, reason, host, snapshot, actions, call, connection } = useMeetCore();
13431
- const [busy, setBusy] = useState4(false);
13889
+ const [busy, setBusy] = useState5(false);
13432
13890
  const failure = snapshot?.failure ?? null;
13433
- const retryLeft = useCountdown(phase === "refused:lobby_rejects" ? failure?.retryAt ?? null : null);
13891
+ const retryLeft = useCountdown(
13892
+ phase === "refused:lobby_rejects" || phase === "refused:too_early" ? failure?.retryAt ?? null : null
13893
+ );
13894
+ const reaskedAtZero = useRef6(false);
13895
+ useEffect6(() => {
13896
+ if (phase !== "refused:too_early") {
13897
+ reaskedAtZero.current = false;
13898
+ return;
13899
+ }
13900
+ if (retryLeft === 0 && !reaskedAtZero.current) {
13901
+ reaskedAtZero.current = true;
13902
+ actions.retry();
13903
+ }
13904
+ }, [phase, retryLeft, actions]);
13434
13905
  const rejoin = /* @__PURE__ */ jsx6(
13435
13906
  Button,
13436
13907
  {
@@ -13468,11 +13939,19 @@ function ExitScreen({ onLeave }) {
13468
13939
  if (phase.startsWith("refused:")) {
13469
13940
  const code = phase.slice("refused:".length);
13470
13941
  title = REFUSED_TITLES[code] ?? "You can't join this meeting";
13471
- line = code === "too_early" || code === "registration_required" || code === "cancelled" ? failure?.remedy ?? null : null;
13472
- actionsNode = /* @__PURE__ */ jsxs3(Fragment, { children: [
13942
+ line = code === "too_early" || code === "registration_required" || code === "cancelled" || code === "wrong_account" ? failure?.remedy ?? null : null;
13943
+ if (code === "too_early" && retryLeft !== null && retryLeft > 0) line = `Opens in ${clockText(retryLeft)}`;
13944
+ actionsNode = /* @__PURE__ */ jsxs4(Fragment, { children: [
13473
13945
  /* @__PURE__ */ jsx6(Button, { type: "button", variant: "outline", onClick: actions.retry, children: "Try again" }),
13474
13946
  home
13475
13947
  ] });
13948
+ if (code === "sign_in_required" || code === "wrong_account") {
13949
+ const back = typeof window === "undefined" ? "/" : `${window.location.pathname}${window.location.search}`;
13950
+ actionsNode = /* @__PURE__ */ jsxs4(Fragment, { children: [
13951
+ /* @__PURE__ */ jsx6(Button, { asChild: true, children: /* @__PURE__ */ jsx6("a", { href: `/login?redirectTo=${encodeURIComponent(back)}`, children: code === "sign_in_required" ? "Sign in" : "Switch account" }) }),
13952
+ home
13953
+ ] });
13954
+ }
13476
13955
  if (code === "lobby_rejects") {
13477
13956
  if (retryLeft !== null && retryLeft > 0) {
13478
13957
  line = `You can ask again in ${clockText(retryLeft)}`;
@@ -13480,7 +13959,7 @@ function ExitScreen({ onLeave }) {
13480
13959
  actionsNode = home;
13481
13960
  } else if (retryLeft === 0) {
13482
13961
  line = "You can ask to join again";
13483
- actionsNode = /* @__PURE__ */ jsxs3(Fragment, { children: [
13962
+ actionsNode = /* @__PURE__ */ jsxs4(Fragment, { children: [
13484
13963
  /* @__PURE__ */ jsx6(
13485
13964
  Button,
13486
13965
  {
@@ -13504,16 +13983,37 @@ function ExitScreen({ onLeave }) {
13504
13983
  switch (phase) {
13505
13984
  case "left":
13506
13985
  title = "You left the meeting";
13507
- actionsNode = /* @__PURE__ */ jsxs3(Fragment, { children: [
13986
+ actionsNode = /* @__PURE__ */ jsxs4(Fragment, { children: [
13508
13987
  rejoin,
13509
13988
  home
13510
13989
  ] });
13511
13990
  break;
13512
13991
  case "disconnected":
13992
+ if (failure?.stage === "join" && (failure.reason ?? null) === null) {
13993
+ title = "Can't connect to the meeting";
13994
+ line = connection === "offline" ? "You're offline. Check your internet connection." : "Check your network. A VPN, firewall or proxy may be blocking the call.";
13995
+ notice = "cannot-connect";
13996
+ actionsNode = /* @__PURE__ */ jsxs4(Fragment, { children: [
13997
+ /* @__PURE__ */ jsx6(
13998
+ Button,
13999
+ {
14000
+ type: "button",
14001
+ disabled: busy,
14002
+ onClick: () => {
14003
+ setBusy(true);
14004
+ void actions.rejoin().catch(() => void 0).finally(() => setBusy(false));
14005
+ },
14006
+ children: "Try again"
14007
+ }
14008
+ ),
14009
+ home
14010
+ ] });
14011
+ break;
14012
+ }
13513
14013
  title = "You lost your connection to the meeting";
13514
14014
  line = connection === "offline" ? "You're offline. You'll rejoin automatically when your internet is back." : connection === "server_unreachable" ? "Can't reach the meeting server. You'll rejoin automatically when it answers." : failure?.remedy ?? "Check your internet connection, then rejoin.";
13515
14015
  notice = "disconnected";
13516
- actionsNode = /* @__PURE__ */ jsxs3(Fragment, { children: [
14016
+ actionsNode = /* @__PURE__ */ jsxs4(Fragment, { children: [
13517
14017
  rejoin,
13518
14018
  home
13519
14019
  ] });
@@ -13526,14 +14026,14 @@ function ExitScreen({ onLeave }) {
13526
14026
  title = "You joined from another tab or device";
13527
14027
  line = "This screen left the meeting so you aren't in it twice.";
13528
14028
  notice = "displaced";
13529
- actionsNode = /* @__PURE__ */ jsxs3(Fragment, { children: [
14029
+ actionsNode = /* @__PURE__ */ jsxs4(Fragment, { children: [
13530
14030
  rejoin,
13531
14031
  home
13532
14032
  ] });
13533
14033
  break;
13534
14034
  case "inactive":
13535
14035
  title = "You left the meeting because this tab was inactive";
13536
- actionsNode = /* @__PURE__ */ jsxs3(Fragment, { children: [
14036
+ actionsNode = /* @__PURE__ */ jsxs4(Fragment, { children: [
13537
14037
  rejoin,
13538
14038
  home
13539
14039
  ] });
@@ -13556,7 +14056,7 @@ function ExitScreen({ onLeave }) {
13556
14056
  break;
13557
14057
  }
13558
14058
  }
13559
- return /* @__PURE__ */ jsxs3("div", { className: "mx-meet__waiting", "data-meet-exit": phase, children: [
14059
+ return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__waiting", "data-meet-exit": phase, children: [
13560
14060
  /* @__PURE__ */ jsx6(Avatar, { name: host?.identity.displayName ?? "", url: host?.identity.avatarUrl ?? null, size: 72 }),
13561
14061
  /* @__PURE__ */ jsx6("h1", { className: "mx-meet__prejoin-title", children: title }),
13562
14062
  line !== null ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__empty-body", children: line }) : null,
@@ -13567,7 +14067,7 @@ function ExitScreen({ onLeave }) {
13567
14067
  function WaitingRoom({ host, onLeave }) {
13568
14068
  const { waiting, withdraw, askAgain } = useWaiting();
13569
14069
  const { phaseNotice } = useMeetCore();
13570
- const [busy, setBusy] = useState4(false);
14070
+ const [busy, setBusy] = useState5(false);
13571
14071
  const admission = waiting?.admission ?? "knocking";
13572
14072
  const reknockLeft = useCountdown(admission === "denied" ? waiting?.reknockAt ?? null : null);
13573
14073
  const run = (action) => () => {
@@ -13590,21 +14090,21 @@ function WaitingRoom({ host, onLeave }) {
13590
14090
  line = `You can ask again in ${clockText(reknockLeft)}`;
13591
14091
  cooldownNotice = true;
13592
14092
  }
13593
- actions = /* @__PURE__ */ jsxs3(Fragment, { children: [
14093
+ actions = /* @__PURE__ */ jsxs4(Fragment, { children: [
13594
14094
  waiting?.reknockAllowed === true || waiting?.reknockAt != null && reknockLeft === 0 ? /* @__PURE__ */ jsx6(Button, { type: "button", disabled: busy, onClick: run(askAgain), children: "Ask to join again" }) : null,
13595
14095
  home
13596
14096
  ] });
13597
14097
  break;
13598
14098
  case "expired":
13599
14099
  title = "No one responded";
13600
- actions = /* @__PURE__ */ jsxs3(Fragment, { children: [
14100
+ actions = /* @__PURE__ */ jsxs4(Fragment, { children: [
13601
14101
  /* @__PURE__ */ jsx6(Button, { type: "button", disabled: busy, onClick: run(askAgain), children: "Ask again" }),
13602
14102
  home
13603
14103
  ] });
13604
14104
  break;
13605
14105
  case "withdrawn":
13606
14106
  title = "You left the waiting room";
13607
- actions = /* @__PURE__ */ jsxs3(Fragment, { children: [
14107
+ actions = /* @__PURE__ */ jsxs4(Fragment, { children: [
13608
14108
  /* @__PURE__ */ jsx6(Button, { type: "button", disabled: busy, onClick: run(askAgain), children: "Rejoin" }),
13609
14109
  home
13610
14110
  ] });
@@ -13618,7 +14118,7 @@ function WaitingRoom({ host, onLeave }) {
13618
14118
  line = waiting?.admittersPresent === false ? "The host isn't here yet" : null;
13619
14119
  actions = /* @__PURE__ */ jsx6(Button, { type: "button", variant: "outline", disabled: busy, onClick: run(withdraw), children: "Cancel request" });
13620
14120
  }
13621
- return /* @__PURE__ */ jsxs3("div", { className: "mx-meet__waiting", children: [
14121
+ return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__waiting", children: [
13622
14122
  /* @__PURE__ */ jsx6(Avatar, { name: host.identity.displayName, url: host.identity.avatarUrl, size: 72 }),
13623
14123
  /* @__PURE__ */ jsx6("h1", { className: "mx-meet__prejoin-title", children: title }),
13624
14124
  phaseNotice === "sent-to-waiting" ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__empty-body", role: "status", "data-meet-notice": "sent-to-waiting", children: "The host moved you back to the waiting room" }) : null,
@@ -13638,9 +14138,9 @@ function HostMenu() {
13638
14138
  const host = useRequiredMeetHost();
13639
14139
  const snapshot = useMeetSnapshot();
13640
14140
  const end = useEndMeeting();
13641
- const [confirmingEnd, setConfirmingEnd] = useState4(false);
14141
+ const [confirmingEnd, setConfirmingEnd] = useState5(false);
13642
14142
  const locked = snapshot?.locked === true;
13643
- return /* @__PURE__ */ jsxs3("div", { className: "mx-meet__host-menu", children: [
14143
+ return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__host-menu", children: [
13644
14144
  /* @__PURE__ */ jsx6(
13645
14145
  "button",
13646
14146
  {
@@ -13652,7 +14152,7 @@ function HostMenu() {
13652
14152
  children: locked ? "Unlock meeting" : "Lock meeting"
13653
14153
  }
13654
14154
  ),
13655
- end.canEnd ? confirmingEnd ? /* @__PURE__ */ jsxs3("span", { className: "mx-meet__confirm", role: "group", "aria-label": "End this meeting?", children: [
14155
+ end.canEnd ? confirmingEnd ? /* @__PURE__ */ jsxs4("span", { className: "mx-meet__confirm", role: "group", "aria-label": "End this meeting?", children: [
13656
14156
  /* @__PURE__ */ jsx6("span", { className: "mx-meet__confirm-text", children: "End it for everyone? Every participant is disconnected, the note-taker stops, and the wrap-up is written. Nobody can rejoin this meeting afterwards." }),
13657
14157
  /* @__PURE__ */ jsx6(
13658
14158
  "button",
@@ -13708,9 +14208,9 @@ function GuestRecordAccessControl({
13708
14208
  const isHost = inRoomHost || viewerId !== null && meeting.hostUserId === viewerId;
13709
14209
  if (host === null || !isHost) return null;
13710
14210
  const resolved = access.setting === "default" && access.effective !== null ? ` Right now that means: ${guestRecordAccessLabel(access.effective.level).toLowerCase()}.` : "";
13711
- return /* @__PURE__ */ jsxs3("section", { className: "mx-meet__record-section", "aria-label": "What guests may read", children: [
14211
+ return /* @__PURE__ */ jsxs4("section", { className: "mx-meet__record-section", "aria-label": "What guests may read", children: [
13712
14212
  /* @__PURE__ */ jsx6("h2", { className: "mx-meet__record-section-title", children: "What guests may read" }),
13713
- /* @__PURE__ */ jsxs3("label", { className: "mx-meet__field", children: [
14213
+ /* @__PURE__ */ jsxs4("label", { className: "mx-meet__field", children: [
13714
14214
  /* @__PURE__ */ jsx6("span", { className: "mx-meet__field-label", children: "People who attended by link, without an account" }),
13715
14215
  /* @__PURE__ */ jsx6(
13716
14216
  "select",
@@ -13727,12 +14227,12 @@ function GuestRecordAccessControl({
13727
14227
  }
13728
14228
  )
13729
14229
  ] }),
13730
- /* @__PURE__ */ jsxs3("p", { className: "mx-meet__panel-note", children: [
14230
+ /* @__PURE__ */ jsxs4("p", { className: "mx-meet__panel-note", children: [
13731
14231
  guestRecordAccessExplanation(access.setting),
13732
14232
  resolved
13733
14233
  ] }),
13734
14234
  access.saving ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__panel-note", role: "status", children: "Saving what guests may read\u2026" }) : null,
13735
- access.error !== null ? /* @__PURE__ */ jsxs3(ErrorBox, { as: "div", className: "mx-meet__refusal", error: access.error, operation: "Change who can join", origin: "meet/components", children: [
14235
+ access.error !== null ? /* @__PURE__ */ jsxs4(ErrorBox, { as: "div", className: "mx-meet__refusal", error: access.error, operation: "Change who can join", origin: "meet/components", children: [
13736
14236
  /* @__PURE__ */ jsx6("p", { className: "mx-meet__refusal-reason", children: access.error.message }),
13737
14237
  /* @__PURE__ */ jsx6("p", { className: "mx-meet__refusal-remedy", children: access.error.remedy })
13738
14238
  ] }) : null
@@ -13740,9 +14240,9 @@ function GuestRecordAccessControl({
13740
14240
  }
13741
14241
 
13742
14242
  // src/react/record.tsx
13743
- import { useEffect as useEffect7, useState as useState5 } from "react";
14243
+ import { useEffect as useEffect7, useState as useState6 } from "react";
13744
14244
  import { ErrorBox as ErrorBox2 } from "@ai-matrx/design-system";
13745
- import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
14245
+ import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
13746
14246
  function MeetingRecordView({
13747
14247
  meeting,
13748
14248
  onRejoin
@@ -13759,17 +14259,17 @@ function MeetingRecordBody({
13759
14259
  }) {
13760
14260
  const host = useRequiredMeetHost();
13761
14261
  const record = useMeetingRecord(meeting);
13762
- const [question, setQuestion] = useState5("");
13763
- const [tab, setTab] = useState5("summary");
14262
+ const [question, setQuestion] = useState6("");
14263
+ const [tab, setTab] = useState6("summary");
13764
14264
  if (record.failure !== null) {
13765
- return /* @__PURE__ */ jsx7("div", { className: "mx-meet mx-meet--record", children: /* @__PURE__ */ jsxs4(ErrorBox2, { as: "div", className: "mx-meet__empty", error: record.failure, operation: "Open this meeting record", origin: "meet/components", children: [
14265
+ return /* @__PURE__ */ jsx7("div", { className: "mx-meet mx-meet--record", children: /* @__PURE__ */ jsxs5(ErrorBox2, { as: "div", className: "mx-meet__empty", error: record.failure, operation: "Open this meeting record", origin: "meet/components", children: [
13766
14266
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__empty-title", children: "This meeting record could not be opened" }),
13767
14267
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__empty-body", children: record.failure.message }),
13768
14268
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__empty-body", children: record.failure.remedy })
13769
14269
  ] }) });
13770
14270
  }
13771
14271
  if (record.loading || record.record === null) {
13772
- return /* @__PURE__ */ jsx7("div", { className: "mx-meet mx-meet--record", children: /* @__PURE__ */ jsxs4("div", { className: "mx-meet__empty", role: "status", children: [
14272
+ return /* @__PURE__ */ jsx7("div", { className: "mx-meet mx-meet--record", children: /* @__PURE__ */ jsxs5("div", { className: "mx-meet__empty", role: "status", children: [
13773
14273
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__empty-title", children: "Opening the meeting record\u2026" }),
13774
14274
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__empty-body", children: "Reading the summary, the notes and the transcript this meeting left behind." })
13775
14275
  ] }) });
@@ -13790,29 +14290,29 @@ function MeetingRecordBody({
13790
14290
  );
13791
14291
  const entirelyRestricted = everyRecordPartRefused && bundle.attendees.length === 0 && bundle.liveNotes.length === 0 && bundle.transcript.length === 0 && bundle.recording === null && bundle.summary === null && bundle.decisions.length === 0 && bundle.actionItems.length === 0;
13792
14292
  if (entirelyRestricted) {
13793
- return /* @__PURE__ */ jsxs4("div", { className: "mx-meet mx-meet--record", children: [
13794
- /* @__PURE__ */ jsx7("header", { className: "mx-meet__record-head", children: /* @__PURE__ */ jsxs4("div", { className: "mx-meet__record-head-inner", children: [
14293
+ return /* @__PURE__ */ jsxs5("div", { className: "mx-meet mx-meet--record", children: [
14294
+ /* @__PURE__ */ jsx7("header", { className: "mx-meet__record-head", children: /* @__PURE__ */ jsxs5("div", { className: "mx-meet__record-head-inner", children: [
13795
14295
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__record-eyebrow", children: "Meeting record" }),
13796
14296
  /* @__PURE__ */ jsx7("h1", { className: "mx-meet__record-title", children: meeting.title }),
13797
14297
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__record-when", children: meetingWhen(meeting) }),
13798
14298
  onRejoin !== void 0 ? /* @__PURE__ */ jsx7("button", { type: "button", className: "mx-meet__link", onClick: onRejoin, children: "Open this link again" }) : null
13799
14299
  ] }) }),
13800
- /* @__PURE__ */ jsx7("div", { className: "mx-meet__record-body", children: restrictionNotices.map((notice2) => /* @__PURE__ */ jsxs4("div", { className: "mx-meet__record-access", role: "status", children: [
14300
+ /* @__PURE__ */ jsx7("div", { className: "mx-meet__record-body", children: restrictionNotices.map((notice2) => /* @__PURE__ */ jsxs5("div", { className: "mx-meet__record-access", role: "status", children: [
13801
14301
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__record-access-title", children: "About this record" }),
13802
14302
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__record-access-message", children: notice2.message }),
13803
14303
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__record-access-remedy", children: notice2.remedy })
13804
14304
  ] }, notice2.parts.join("-"))) })
13805
14305
  ] });
13806
14306
  }
13807
- return /* @__PURE__ */ jsxs4("div", { className: "mx-meet mx-meet--record", children: [
13808
- /* @__PURE__ */ jsx7("header", { className: "mx-meet__record-head", children: /* @__PURE__ */ jsxs4("div", { className: "mx-meet__record-head-inner", children: [
14307
+ return /* @__PURE__ */ jsxs5("div", { className: "mx-meet mx-meet--record", children: [
14308
+ /* @__PURE__ */ jsx7("header", { className: "mx-meet__record-head", children: /* @__PURE__ */ jsxs5("div", { className: "mx-meet__record-head-inner", children: [
13809
14309
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__record-eyebrow", children: "Meeting record" }),
13810
14310
  /* @__PURE__ */ jsx7("h1", { className: "mx-meet__record-title", children: meeting.title }),
13811
14311
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__record-when", children: meetingWhen(meeting) }),
13812
14312
  onRejoin !== void 0 ? /* @__PURE__ */ jsx7("button", { type: "button", className: "mx-meet__link", onClick: onRejoin, children: "Open this link again" }) : null
13813
14313
  ] }) }),
13814
- /* @__PURE__ */ jsxs4("div", { className: "mx-meet__record-body", children: [
13815
- restrictionNotices.map((notice2) => /* @__PURE__ */ jsxs4("div", { className: "mx-meet__record-access", role: "status", children: [
14314
+ /* @__PURE__ */ jsxs5("div", { className: "mx-meet__record-body", children: [
14315
+ restrictionNotices.map((notice2) => /* @__PURE__ */ jsxs5("div", { className: "mx-meet__record-access", role: "status", children: [
13816
14316
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__record-access-title", children: "About this record" }),
13817
14317
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__record-access-message", children: notice2.message }),
13818
14318
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__record-access-remedy", children: notice2.remedy })
@@ -13820,13 +14320,13 @@ function MeetingRecordBody({
13820
14320
  attended.length === 0 ? (
13821
14321
  /* NOT SILENCE. A refused attendance read used to remove the whole
13822
14322
  section, so the reader could not tell "nobody" from "not shown". */
13823
- /* @__PURE__ */ jsxs4("section", { className: "mx-meet__record-section", "aria-label": "Who attended", children: [
14323
+ /* @__PURE__ */ jsxs5("section", { className: "mx-meet__record-section", "aria-label": "Who attended", children: [
13824
14324
  /* @__PURE__ */ jsx7("h2", { className: "mx-meet__record-section-title", children: "Who attended" }),
13825
14325
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__panel-note", children: absenceSentence(bundle, "attendance", "Nobody is recorded as having attended.") })
13826
14326
  ] })
13827
- ) : /* @__PURE__ */ jsxs4("section", { className: "mx-meet__record-section", "aria-label": "Who attended", children: [
14327
+ ) : /* @__PURE__ */ jsxs5("section", { className: "mx-meet__record-section", "aria-label": "Who attended", children: [
13828
14328
  /* @__PURE__ */ jsx7("h2", { className: "mx-meet__record-section-title", children: "Who attended" }),
13829
- /* @__PURE__ */ jsx7("ul", { className: "mx-meet__record-attendees", children: attended.map((person) => /* @__PURE__ */ jsxs4("li", { className: "mx-meet__record-attendee", children: [
14329
+ /* @__PURE__ */ jsx7("ul", { className: "mx-meet__record-attendees", children: attended.map((person) => /* @__PURE__ */ jsxs5("li", { className: "mx-meet__record-attendee", children: [
13830
14330
  /* @__PURE__ */ jsx7(
13831
14331
  Avatar,
13832
14332
  {
@@ -13835,7 +14335,7 @@ function MeetingRecordBody({
13835
14335
  size: 28
13836
14336
  }
13837
14337
  ),
13838
- /* @__PURE__ */ jsxs4("span", { className: "mx-meet__person-name", children: [
14338
+ /* @__PURE__ */ jsxs5("span", { className: "mx-meet__person-name", children: [
13839
14339
  displayNameFor(bundle.names, person.identity, person.displayName),
13840
14340
  person.role === "host" ? /* @__PURE__ */ jsx7("span", { className: "mx-meet__badge", children: "Host" }) : null,
13841
14341
  person.userId === null && !person.isAgent ? /* @__PURE__ */ jsx7("span", { className: "mx-meet__badge", children: "Guest" }) : null,
@@ -13843,17 +14343,17 @@ function MeetingRecordBody({
13843
14343
  ] })
13844
14344
  ] }, person.id)) })
13845
14345
  ] }),
13846
- bundle.recording !== null ? /* @__PURE__ */ jsxs4("section", { className: "mx-meet__record-section mx-meet__recording-card", "aria-label": "Recording", children: [
14346
+ bundle.recording !== null ? /* @__PURE__ */ jsxs5("section", { className: "mx-meet__record-section mx-meet__recording-card", "aria-label": "Recording", children: [
13847
14347
  /* @__PURE__ */ jsx7("h2", { className: "mx-meet__record-section-title", children: "Recording" }),
13848
- fileId !== null ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
14348
+ fileId !== null ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
13849
14349
  /* @__PURE__ */ jsx7(RecordingPlayer, { fileId }),
13850
14350
  notice !== null ? /* @__PURE__ */ jsx7("p", { className: "mx-meet__panel-note", children: notice }) : null
13851
14351
  ] }) : /* @__PURE__ */ jsx7("p", { className: "mx-meet__panel-note", children: notice ?? "This recording has no file." })
13852
- ] }) : wasRefused(bundle, "recording") ? /* @__PURE__ */ jsxs4("section", { className: "mx-meet__record-section", "aria-label": "Recording", children: [
14352
+ ] }) : wasRefused(bundle, "recording") ? /* @__PURE__ */ jsxs5("section", { className: "mx-meet__record-section", "aria-label": "Recording", children: [
13853
14353
  /* @__PURE__ */ jsx7("h2", { className: "mx-meet__record-section-title", children: "Recording" }),
13854
14354
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__panel-note", children: REFUSED_ABSENCE })
13855
14355
  ] }) : null,
13856
- /* @__PURE__ */ jsxs4("nav", { className: "mx-meet__record-tabs", "aria-label": "Meeting record sections", children: [
14356
+ /* @__PURE__ */ jsxs5("nav", { className: "mx-meet__record-tabs", "aria-label": "Meeting record sections", children: [
13857
14357
  /* @__PURE__ */ jsx7(
13858
14358
  "button",
13859
14359
  {
@@ -13885,10 +14385,10 @@ function MeetingRecordBody({
13885
14385
  }
13886
14386
  )
13887
14387
  ] }),
13888
- tab === "summary" ? /* @__PURE__ */ jsxs4(Fragment2, { children: [
13889
- /* @__PURE__ */ jsxs4("section", { className: "mx-meet__record-section", "aria-label": "Summary", children: [
14388
+ tab === "summary" ? /* @__PURE__ */ jsxs5(Fragment2, { children: [
14389
+ /* @__PURE__ */ jsxs5("section", { className: "mx-meet__record-section", "aria-label": "Summary", children: [
13890
14390
  /* @__PURE__ */ jsx7("h2", { className: "mx-meet__record-section-title", children: "Summary" }),
13891
- wrapUp.state === "written" ? /* @__PURE__ */ jsx7("p", { className: "mx-meet__record-summary", children: bundle.summary?.text }) : wrapUp.state === "in-progress" ? /* @__PURE__ */ jsxs4("div", { className: "mx-meet__panel-note", role: "status", children: [
14391
+ wrapUp.state === "written" ? /* @__PURE__ */ jsx7("p", { className: "mx-meet__record-summary", children: bundle.summary?.text }) : wrapUp.state === "in-progress" ? /* @__PURE__ */ jsxs5("div", { className: "mx-meet__panel-note", role: "status", children: [
13892
14392
  /* @__PURE__ */ jsx7("p", { children: wrapUp.message }),
13893
14393
  /* @__PURE__ */ jsx7("button", { type: "button", className: "mx-meet__link", onClick: record.reload, children: "Check again" })
13894
14394
  ] }) : /* @__PURE__ */ jsx7("p", { className: "mx-meet__panel-note", role: wrapUp.state === "failed" ? "alert" : void 0, children: wrapUp.message })
@@ -13918,22 +14418,22 @@ function MeetingRecordBody({
13918
14418
  }
13919
14419
  )
13920
14420
  ] }) : null,
13921
- tab === "notes" ? /* @__PURE__ */ jsxs4("section", { className: "mx-meet__record-section", "aria-label": "Notes as it happened", children: [
14421
+ tab === "notes" ? /* @__PURE__ */ jsxs5("section", { className: "mx-meet__record-section", "aria-label": "Notes as it happened", children: [
13922
14422
  /* @__PURE__ */ jsx7("h2", { className: "mx-meet__record-section-title", children: "Notes as it happened" }),
13923
14423
  bundle.liveNotes.length === 0 ? /* @__PURE__ */ jsx7("p", { className: "mx-meet__panel-note", children: absenceSentence(
13924
14424
  bundle,
13925
14425
  "notes",
13926
14426
  "No live notes are available for this meeting."
13927
- ) }) : /* @__PURE__ */ jsx7("ul", { className: "mx-meet__notes", children: bundle.liveNotes.map((note) => /* @__PURE__ */ jsxs4("li", { className: "mx-meet__note", children: [
13928
- note.window !== null ? /* @__PURE__ */ jsxs4("span", { className: "mx-meet__badge", children: [
14427
+ ) }) : /* @__PURE__ */ jsx7("ul", { className: "mx-meet__notes", children: bundle.liveNotes.map((note) => /* @__PURE__ */ jsxs5("li", { className: "mx-meet__note", children: [
14428
+ note.window !== null ? /* @__PURE__ */ jsxs5("span", { className: "mx-meet__badge", children: [
13929
14429
  "Window ",
13930
14430
  note.window
13931
14431
  ] }) : null,
13932
14432
  note.text
13933
14433
  ] }, note.id)) })
13934
14434
  ] }) : null,
13935
- tab === "transcript" ? /* @__PURE__ */ jsxs4("section", { className: "mx-meet__record-section", "aria-label": "Transcript", children: [
13936
- /* @__PURE__ */ jsxs4("h2", { className: "mx-meet__record-section-title", children: [
14435
+ tab === "transcript" ? /* @__PURE__ */ jsxs5("section", { className: "mx-meet__record-section", "aria-label": "Transcript", children: [
14436
+ /* @__PURE__ */ jsxs5("h2", { className: "mx-meet__record-section-title", children: [
13937
14437
  "Transcript",
13938
14438
  /* @__PURE__ */ jsx7("span", { className: "mx-meet__record-count", children: bundle.transcript.length === 1 ? "1 line" : `${bundle.transcript.length} lines` })
13939
14439
  ] }),
@@ -13941,8 +14441,8 @@ function MeetingRecordBody({
13941
14441
  bundle,
13942
14442
  "transcript",
13943
14443
  "No transcript is available for this meeting."
13944
- ) }) : /* @__PURE__ */ jsx7("ol", { className: "mx-meet__record-transcript", children: blocks.map((block) => /* @__PURE__ */ jsxs4("li", { className: "mx-meet__record-block", children: [
13945
- /* @__PURE__ */ jsxs4("p", { className: "mx-meet__record-speaker", children: [
14444
+ ) }) : /* @__PURE__ */ jsx7("ol", { className: "mx-meet__record-transcript", children: blocks.map((block) => /* @__PURE__ */ jsxs5("li", { className: "mx-meet__record-block", children: [
14445
+ /* @__PURE__ */ jsxs5("p", { className: "mx-meet__record-speaker", children: [
13946
14446
  block.speaker,
13947
14447
  /* @__PURE__ */ jsx7("time", { className: "mx-meet__record-time", dateTime: block.startedAt, children: clockOf(block.startedAt) })
13948
14448
  ] }),
@@ -13950,10 +14450,10 @@ function MeetingRecordBody({
13950
14450
  ] }, block.id)) })
13951
14451
  ] }) : null,
13952
14452
  /* @__PURE__ */ jsx7(GuestRecordAccessControl, { meeting }),
13953
- /* @__PURE__ */ jsxs4("section", { className: "mx-meet__record-section", "aria-label": "Ask about this meeting", children: [
14453
+ /* @__PURE__ */ jsxs5("section", { className: "mx-meet__record-section", "aria-label": "Ask about this meeting", children: [
13954
14454
  /* @__PURE__ */ jsx7("h2", { className: "mx-meet__record-section-title", children: "Ask about this meeting" }),
13955
- guestFinishedMeeting ? /* @__PURE__ */ jsx7("p", { className: "mx-meet__panel-note", children: "Sign in to ask the assistant about a meeting after it ends." }) : /* @__PURE__ */ jsxs4(Fragment2, { children: [
13956
- /* @__PURE__ */ jsxs4(
14455
+ guestFinishedMeeting ? /* @__PURE__ */ jsx7("p", { className: "mx-meet__panel-note", children: "Sign in to ask the assistant about a meeting after it ends." }) : /* @__PURE__ */ jsxs5(Fragment2, { children: [
14456
+ /* @__PURE__ */ jsxs5(
13957
14457
  "form",
13958
14458
  {
13959
14459
  className: "mx-meet__composer",
@@ -13987,7 +14487,7 @@ function MeetingRecordBody({
13987
14487
  }
13988
14488
  ),
13989
14489
  record.answer !== null ? /* @__PURE__ */ jsx7("p", { className: "mx-meet__answer", children: record.answer }) : null,
13990
- record.coverage !== null ? /* @__PURE__ */ jsxs4("p", { className: "mx-meet__coverage", children: [
14490
+ record.coverage !== null ? /* @__PURE__ */ jsxs5("p", { className: "mx-meet__coverage", children: [
13991
14491
  "Answered from ",
13992
14492
  record.coverage.segmentsUsed,
13993
14493
  " of ",
@@ -13998,7 +14498,7 @@ function MeetingRecordBody({
13998
14498
  record.coverage.truncated ? " (the oldest were left out)" : "",
13999
14499
  "."
14000
14500
  ] }) : null,
14001
- record.askError !== null ? /* @__PURE__ */ jsxs4(ErrorBox2, { as: "div", className: "mx-meet__refusal", error: record.askError, operation: "Ask about this meeting", origin: "meet/components", children: [
14501
+ record.askError !== null ? /* @__PURE__ */ jsxs5(ErrorBox2, { as: "div", className: "mx-meet__refusal", error: record.askError, operation: "Ask about this meeting", origin: "meet/components", children: [
14002
14502
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__refusal-reason", children: record.askError.message }),
14003
14503
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__refusal-remedy", children: record.askError.remedy })
14004
14504
  ] }) : null
@@ -14015,16 +14515,16 @@ function RecordingPlayer(props) {
14015
14515
  return /* @__PURE__ */ jsx7(RecordingPlayerBody, { ...props, host });
14016
14516
  }
14017
14517
  function RecordingPlayerBody({ fileId, host }) {
14018
- const [media, setMedia] = useState5(null);
14019
- const [loading, setLoading] = useState5(false);
14020
- const [error, setError] = useState5(null);
14518
+ const [media, setMedia] = useState6(null);
14519
+ const [loading, setLoading] = useState6(false);
14520
+ const [error, setError] = useState6(null);
14021
14521
  useEffect7(() => {
14022
14522
  if (media === null || media.kind !== "bytes") return void 0;
14023
14523
  const url = media.url;
14024
14524
  return () => URL.revokeObjectURL(url);
14025
14525
  }, [media]);
14026
14526
  if (media !== null) {
14027
- return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__record-section", children: [
14527
+ return /* @__PURE__ */ jsxs5("div", { className: "mx-meet__record-section", children: [
14028
14528
  /* @__PURE__ */ jsx7(
14029
14529
  "video",
14030
14530
  {
@@ -14070,8 +14570,8 @@ function RecordingPlayerBody({ fileId, host }) {
14070
14570
  media.fallbackReason !== null ? /* @__PURE__ */ jsx7("p", { className: "mx-meet__panel-note", children: media.fallbackReason }) : null
14071
14571
  ] });
14072
14572
  }
14073
- return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__record-section", children: [
14074
- error !== null ? /* @__PURE__ */ jsxs4(ErrorBox2, { as: "div", className: "mx-meet__refusal", error, operation: "Complete this meeting action", origin: "meet/components", children: [
14573
+ return /* @__PURE__ */ jsxs5("div", { className: "mx-meet__record-section", children: [
14574
+ error !== null ? /* @__PURE__ */ jsxs5(ErrorBox2, { as: "div", className: "mx-meet__refusal", error, operation: "Complete this meeting action", origin: "meet/components", children: [
14075
14575
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__refusal-reason", children: error.message }),
14076
14576
  /* @__PURE__ */ jsx7("p", { className: "mx-meet__refusal-remedy", children: error.remedy })
14077
14577
  ] }) : null,
@@ -14197,7 +14697,7 @@ function linkRunWords(run) {
14197
14697
 
14198
14698
  // src/react/calls-ui.tsx
14199
14699
  import { useEffect as useEffect9 } from "react";
14200
- import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
14700
+ import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
14201
14701
  function IncomingCallHost() {
14202
14702
  const calls = useCalls();
14203
14703
  const { call, phase, actions } = useMeetCore();
@@ -14211,9 +14711,9 @@ function IncomingCallHost() {
14211
14711
  return () => clearTimeout(timer);
14212
14712
  }, [outcome, actions]);
14213
14713
  const inCall = call !== null && (phase === "joining" || phase === "in_call" || phase === "disconnected" || phase === "removed" || phase === "superseded");
14214
- return /* @__PURE__ */ jsxs5(Fragment3, { children: [
14714
+ return /* @__PURE__ */ jsxs6(Fragment3, { children: [
14215
14715
  inCall && call !== null ? /* @__PURE__ */ jsx9("div", { className: "mx-meet__call-overlay", "data-meet-call": call.invite.id, children: /* @__PURE__ */ jsx9(MeetRoot, { children: /* @__PURE__ */ jsx9(MeetSkinRoom, { roomName: call.invite.roomName, onLeave: actions.dismissCall }) }) }) : null,
14216
- calls.incoming.length > 0 || call !== null && (phase === "ringing_out" || outcome) ? /* @__PURE__ */ jsxs5("div", { className: "mx-meet__ringing-stack", children: [
14716
+ calls.incoming.length > 0 || call !== null && (phase === "ringing_out" || outcome) ? /* @__PURE__ */ jsxs6("div", { className: "mx-meet__ringing-stack", children: [
14217
14717
  call !== null && phase === "ringing_out" ? /* @__PURE__ */ jsx9(OutgoingCallCard, { invite: call.invite }) : null,
14218
14718
  outcome && call !== null ? /* @__PURE__ */ jsx9(CallOutcomeCard, { invite: call.invite }) : null,
14219
14719
  calls.incoming.map((invite) => /* @__PURE__ */ jsx9(IncomingCallCard, { invite }, invite.id))
@@ -14222,9 +14722,9 @@ function IncomingCallHost() {
14222
14722
  }
14223
14723
  function OutgoingCallCard({ invite }) {
14224
14724
  const calls = useCalls();
14225
- return /* @__PURE__ */ jsxs5("section", { className: "mx-meet__ringing", role: "status", "aria-label": "Calling", "data-meet-notice": "ringing-out", children: [
14725
+ return /* @__PURE__ */ jsxs6("section", { className: "mx-meet__ringing", role: "status", "aria-label": "Calling", "data-meet-notice": "ringing-out", children: [
14226
14726
  /* @__PURE__ */ jsx9(Avatar, { name: invite.callerName, url: invite.callerAvatarUrl, size: 56 }),
14227
- /* @__PURE__ */ jsxs5("div", { className: "mx-meet__ringing-text", children: [
14727
+ /* @__PURE__ */ jsxs6("div", { className: "mx-meet__ringing-text", children: [
14228
14728
  /* @__PURE__ */ jsx9("strong", { children: "Calling\u2026" }),
14229
14729
  /* @__PURE__ */ jsx9("span", { children: invite.mode === "video" ? "Video call" : "Voice call" })
14230
14730
  ] }),
@@ -14235,20 +14735,20 @@ function CallOutcomeCard({ invite }) {
14235
14735
  const { phase, actions, call } = useMeetCore();
14236
14736
  const outgoing = call?.direction === "outgoing";
14237
14737
  const text3 = phase === "call_declined" ? "Call declined" : phase === "call_busy" ? "They're on another call" : phase === "answered_elsewhere" ? "Answered on another device" : outgoing ? "No answer" : `Missed call from ${invite.callerName}`;
14238
- return /* @__PURE__ */ jsxs5("section", { className: "mx-meet__ringing", role: "status", "aria-label": text3, "data-meet-call-outcome": phase, children: [
14738
+ return /* @__PURE__ */ jsxs6("section", { className: "mx-meet__ringing", role: "status", "aria-label": text3, "data-meet-call-outcome": phase, children: [
14239
14739
  /* @__PURE__ */ jsx9("div", { className: "mx-meet__ringing-text", children: /* @__PURE__ */ jsx9("strong", { children: text3 }) }),
14240
14740
  /* @__PURE__ */ jsx9("div", { className: "mx-meet__ringing-actions", children: /* @__PURE__ */ jsx9(ControlButton, { label: "Close", onClick: actions.dismissCall, children: /* @__PURE__ */ jsx9(PhoneOffIcon, {}) }) })
14241
14741
  ] });
14242
14742
  }
14243
14743
  function IncomingCallCard({ invite }) {
14244
14744
  const calls = useCalls();
14245
- return /* @__PURE__ */ jsxs5("section", { className: "mx-meet__ringing", role: "alertdialog", "aria-label": "Incoming call", children: [
14745
+ return /* @__PURE__ */ jsxs6("section", { className: "mx-meet__ringing", role: "alertdialog", "aria-label": "Incoming call", children: [
14246
14746
  /* @__PURE__ */ jsx9(Avatar, { name: invite.callerName, url: invite.callerAvatarUrl, size: 56 }),
14247
- /* @__PURE__ */ jsxs5("div", { className: "mx-meet__ringing-text", children: [
14747
+ /* @__PURE__ */ jsxs6("div", { className: "mx-meet__ringing-text", children: [
14248
14748
  /* @__PURE__ */ jsx9("strong", { children: invite.callerName }),
14249
14749
  /* @__PURE__ */ jsx9("span", { children: invite.mode === "video" ? "Incoming video call" : "Incoming call" })
14250
14750
  ] }),
14251
- /* @__PURE__ */ jsxs5("div", { className: "mx-meet__ringing-actions", children: [
14751
+ /* @__PURE__ */ jsxs6("div", { className: "mx-meet__ringing-actions", children: [
14252
14752
  /* @__PURE__ */ jsx9(ControlButton, { label: "Decline", danger: true, onClick: () => void calls.decline(invite), children: /* @__PURE__ */ jsx9(PhoneOffIcon, {}) }),
14253
14753
  invite.mode === "video" ? /* @__PURE__ */ jsx9(
14254
14754
  ControlButton,
@@ -14540,6 +15040,7 @@ export {
14540
15040
  createReconnectPolicy,
14541
15041
  createRecordingController,
14542
15042
  createRoomEngine,
15043
+ createSpeakingWhileMutedDetector,
14543
15044
  createTokenClient,
14544
15045
  createWebDeviceStorage,
14545
15046
  createWebEffectsStorage,
@@ -14548,6 +15049,7 @@ export {
14548
15049
  createWebRoomTokenStorage,
14549
15050
  defaultCaptionLanguage,
14550
15051
  detectBrowser,
15052
+ detectCapabilities,
14551
15053
  detectOs,
14552
15054
  deviceChipLabel,
14553
15055
  deviceFixSteps,
@@ -14572,6 +15074,7 @@ export {
14572
15074
  isLinkFollower,
14573
15075
  isListenOnly,
14574
15076
  isLivePhase,
15077
+ isMobileUserAgent,
14575
15078
  isNoteTaker,
14576
15079
  isObserverRole,
14577
15080
  isRealName,
@@ -14664,6 +15167,7 @@ export {
14664
15167
  transcriptDocument,
14665
15168
  unavailableFrom,
14666
15169
  uniqueAttendees,
15170
+ unsupportedWords,
14667
15171
  untranslatedLines,
14668
15172
  useActivityAttention,
14669
15173
  useAudioLevel,