@ai-matrx/meet 0.11.42 → 0.11.44
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/CHANGELOG.md +12 -0
- package/dist/{collab-Bf5evcLO.d.cts → collab-BNJNgXFB.d.cts} +10 -1
- package/dist/{collab-Bf5evcLO.d.ts → collab-BNJNgXFB.d.ts} +10 -1
- package/dist/{components-Frpvls4N.d.ts → components-BDtGzHf4.d.ts} +4 -2
- package/dist/{components-roCEgyFH.d.cts → components-BxK993iW.d.cts} +4 -2
- package/dist/core.cjs +328 -25
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +152 -7
- package/dist/core.d.ts +152 -7
- package/dist/core.js +328 -25
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +328 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +328 -25
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +839 -77
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +22 -5
- package/dist/react.d.ts +22 -5
- package/dist/react.js +1225 -463
- package/dist/react.js.map +1 -1
- package/dist/skins/meet.cjs +581 -60
- package/dist/skins/meet.cjs.map +1 -1
- package/dist/skins/meet.d.cts +6 -3
- package/dist/skins/meet.d.ts +6 -3
- package/dist/skins/meet.js +908 -387
- package/dist/skins/meet.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +4 -4
package/dist/skins/meet.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"use client";
|
|
3
3
|
|
|
4
4
|
// src/skins/meet/components.tsx
|
|
5
|
-
import { useEffect as useEffect6, useLayoutEffect, useRef as useRef6, useState as
|
|
5
|
+
import { useEffect as useEffect6, useLayoutEffect, useRef as useRef6, useState as useState5 } from "react";
|
|
6
6
|
|
|
7
7
|
// src/react/facade.ts
|
|
8
8
|
import { useMemo as useMemo5 } from "react";
|
|
@@ -160,6 +160,8 @@ var MEET_ROUTES = {
|
|
|
160
160
|
noteTakerStop: "/api/v1/meet/agent/stop",
|
|
161
161
|
/** In-meeting Q&A. Streams NDJSON; body is `{meeting_id, question}` only. */
|
|
162
162
|
intelligenceAsk: "/api/v1/meet/intelligence/ask",
|
|
163
|
+
/** Anyone in the meeting (guests with the room pass included) asks for captions for themselves. */
|
|
164
|
+
noteTakerCaptions: "/api/v1/meet/agent/captions",
|
|
163
165
|
/** A host ends the meeting for everyone. Served by MRI-A6. */
|
|
164
166
|
meetingEnd: "/api/v1/meet/end",
|
|
165
167
|
/**
|
|
@@ -255,12 +257,39 @@ function recordingLabel(state) {
|
|
|
255
257
|
}
|
|
256
258
|
}
|
|
257
259
|
|
|
260
|
+
// src/core/live-policy.ts
|
|
261
|
+
var DEFAULT_LIVE_POLICY = {
|
|
262
|
+
chatMode: "everyone",
|
|
263
|
+
avLock: "off",
|
|
264
|
+
timeLimitMinutes: 0,
|
|
265
|
+
timeLimitWarningMinutes: 5,
|
|
266
|
+
recordingConsent: "notice"
|
|
267
|
+
};
|
|
268
|
+
var MODERATORS = /* @__PURE__ */ new Set(["host", "cohost"]);
|
|
269
|
+
function isLockedFor(policy, role, kind) {
|
|
270
|
+
if (MODERATORS.has(role)) return false;
|
|
271
|
+
return policy.avLock === "both" || (kind === "microphone" ? policy.avLock === "mic" : policy.avLock === "camera");
|
|
272
|
+
}
|
|
273
|
+
function consentPending(policy, role, recordingOn, given) {
|
|
274
|
+
return recordingOn && !given && policy.recordingConsent !== "notice" && !MODERATORS.has(role);
|
|
275
|
+
}
|
|
276
|
+
function canChat(policy, role) {
|
|
277
|
+
if (policy.chatMode === "everyone") return true;
|
|
278
|
+
return policy.chatMode === "hosts_only" && MODERATORS.has(role);
|
|
279
|
+
}
|
|
280
|
+
function minutesLeft(policy, startedAtMs, nowMs) {
|
|
281
|
+
if (policy.timeLimitMinutes <= 0 || startedAtMs === null) return null;
|
|
282
|
+
return Math.ceil((startedAtMs + policy.timeLimitMinutes * 6e4 - nowMs) / 6e4);
|
|
283
|
+
}
|
|
284
|
+
|
|
258
285
|
// src/core/attendance.ts
|
|
286
|
+
var IDLE_PREVIEW = { state: "idle", unavailable: null };
|
|
259
287
|
var IDLE_MEDIA_REGION = {
|
|
260
288
|
permission: { microphone: "unknown", camera: "unknown" },
|
|
261
289
|
audioOutput: "ok",
|
|
262
290
|
notice: null,
|
|
263
|
-
offer: null
|
|
291
|
+
offer: null,
|
|
292
|
+
preview: { microphone: IDLE_PREVIEW, camera: IDLE_PREVIEW }
|
|
264
293
|
};
|
|
265
294
|
var IDLE_TRACK = { enabled: false, unavailable: null };
|
|
266
295
|
var IDLE_MEDIA = {
|
|
@@ -347,9 +376,17 @@ function autoAssign(identities, rooms, exclude = []) {
|
|
|
347
376
|
return out;
|
|
348
377
|
}
|
|
349
378
|
function breakoutRemainingMs(plan, now) {
|
|
350
|
-
if (plan === null || plan.state !== "open"
|
|
351
|
-
const
|
|
352
|
-
|
|
379
|
+
if (plan === null || plan.state !== "open") return null;
|
|
380
|
+
const ends = [plan.endsAt, plan.closingAt].map((stamp) => stamp === null ? Number.NaN : Date.parse(stamp)).filter((time) => !Number.isNaN(time));
|
|
381
|
+
if (ends.length === 0) return null;
|
|
382
|
+
return Math.max(0, Math.min(...ends) - now);
|
|
383
|
+
}
|
|
384
|
+
var BREAKOUT_COUNTDOWN_MS = 3e4;
|
|
385
|
+
function breakoutClosingMs(plan, now) {
|
|
386
|
+
if (plan === null || plan.state !== "open") return null;
|
|
387
|
+
const remaining = breakoutRemainingMs(plan, now);
|
|
388
|
+
if (remaining === null) return null;
|
|
389
|
+
return plan.closingAt !== null || remaining <= BREAKOUT_COUNTDOWN_MS ? remaining : null;
|
|
353
390
|
}
|
|
354
391
|
function defaultCaptionLanguage(settings, viewerLanguage) {
|
|
355
392
|
const configured = settings?.captionTranslationLanguage.trim() ?? "";
|
|
@@ -411,7 +448,7 @@ function effectiveStanding(snapshot) {
|
|
|
411
448
|
var REACTION_TTL_MS = 5e3;
|
|
412
449
|
|
|
413
450
|
// src/react/root.tsx
|
|
414
|
-
import { useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2 } from "react";
|
|
451
|
+
import { useEffect as useEffect2, useMemo as useMemo2, useRef as useRef2, useState as useState2 } from "react";
|
|
415
452
|
|
|
416
453
|
// src/core/media-supervisor.ts
|
|
417
454
|
function classifyDeviceFailure(error, permission) {
|
|
@@ -473,7 +510,7 @@ function deviceFixSteps(kind, reason, where) {
|
|
|
473
510
|
case "safari":
|
|
474
511
|
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"];
|
|
475
512
|
default:
|
|
476
|
-
return ["Click the icon
|
|
513
|
+
return ["Click the site settings icon in the address bar", `Set ${device} to Allow`, "Press Try again"];
|
|
477
514
|
}
|
|
478
515
|
case "blocked_os": {
|
|
479
516
|
const app = where.browser === "chrome" ? "Google Chrome" : where.browser === "edge" ? "Microsoft Edge" : where.browser === "firefox" ? "Firefox" : "your browser";
|
|
@@ -557,14 +594,31 @@ function webMediaPlatform() {
|
|
|
557
594
|
|
|
558
595
|
// src/core/observation.ts
|
|
559
596
|
function observedRole(role, standing) {
|
|
560
|
-
if (role === "host" || role === "cohost") return role;
|
|
597
|
+
if (role === "host" || role === "cohost" || role === "presenter") return role;
|
|
561
598
|
return isLinkFollower(standing) ? "guest" : "participant";
|
|
562
599
|
}
|
|
563
|
-
function observedDevice(track, permission = "unknown") {
|
|
600
|
+
function observedDevice(track, permission = "unknown", held = null) {
|
|
601
|
+
if (held === "locked") return "locked";
|
|
564
602
|
if (track.enabled) return "on";
|
|
603
|
+
if (held === "muted_by_host") return "muted_by_host";
|
|
565
604
|
const reason = deviceUnavailableReason(track, permission);
|
|
566
605
|
return reason === null ? "muted_by_me" : `unavailable:${reason}`;
|
|
567
606
|
}
|
|
607
|
+
function observedPreview(preview, permission = "unknown") {
|
|
608
|
+
if (permission === "denied") return "unavailable:denied";
|
|
609
|
+
switch (preview.state) {
|
|
610
|
+
case "on":
|
|
611
|
+
return "on";
|
|
612
|
+
case "off":
|
|
613
|
+
return "muted_by_me";
|
|
614
|
+
case "prompting":
|
|
615
|
+
return "prompting";
|
|
616
|
+
case "unavailable":
|
|
617
|
+
return `unavailable:${preview.unavailable?.reason ?? "failed"}`;
|
|
618
|
+
default:
|
|
619
|
+
return null;
|
|
620
|
+
}
|
|
621
|
+
}
|
|
568
622
|
function endedRecord(snapshot, given) {
|
|
569
623
|
const record = snapshot?.meeting ?? given;
|
|
570
624
|
return record !== null && record.endedAt !== null;
|
|
@@ -588,20 +642,34 @@ function observe(input) {
|
|
|
588
642
|
const canAdmit = actual !== "none" && ADMITTER_ROLES.has(actual);
|
|
589
643
|
const role = actual === "none" || snapshot === null ? "none" : observedRole(actual, effectiveStanding(snapshot));
|
|
590
644
|
const deviceInPlay = phase === "joining" || inCall;
|
|
645
|
+
const region = snapshot?.mediaRegion;
|
|
646
|
+
const atPrejoin = phase === "prejoin" && region !== void 0;
|
|
591
647
|
return {
|
|
592
648
|
phase,
|
|
593
649
|
reason: phase === "ended" ? snapshot?.reason ?? null : snapshot?.reason ?? reasonOf(phase),
|
|
594
650
|
role,
|
|
595
|
-
|
|
651
|
+
// `net-blip`: in the call, a drop shorter than `reconnect_banner_delay_ms` is not something the
|
|
652
|
+
// person sees — the contract says what is on screen, so it reads `stable` until the banner shows.
|
|
653
|
+
connection: snapshot === null ? "stable" : inCall && snapshot.connection !== "stable" && !snapshot.connectionBanner ? "stable" : snapshot.connection,
|
|
596
654
|
hostPresent: inCall && snapshot !== null ? snapshot.participants.some((p) => ADMITTER_ROLES.has(p.role)) : snapshot !== null && isWaitingPhase(snapshot.phase) ? snapshot.waiting?.admittersPresent ?? null : null,
|
|
597
655
|
lobbyCount: canAdmit && snapshot !== null ? snapshot.lobby.filter((entry) => entry.state === "knocking").length : 0,
|
|
598
656
|
recording: snapshot?.recording === "recording" || snapshot?.recording === "stopping",
|
|
599
657
|
// S6c: the autoplay region is known only inside the room (no remote audio exists elsewhere).
|
|
600
658
|
audioBlocked: inCall && snapshot !== null ? snapshot.mediaRegion.audioOutput === "blocked" : null,
|
|
601
|
-
camera: deviceInPlay && snapshot !== null ? observedDevice(snapshot.media.camera, snapshot.mediaRegion.permission.camera) : null,
|
|
602
|
-
microphone: deviceInPlay && snapshot !== null ? observedDevice(snapshot.media.microphone, snapshot.mediaRegion.permission.microphone) : null
|
|
659
|
+
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,
|
|
660
|
+
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
|
|
603
661
|
};
|
|
604
662
|
}
|
|
663
|
+
function lockedFor(snapshot, kind, inCall) {
|
|
664
|
+
if (!inCall) return null;
|
|
665
|
+
const role = effectiveRole(snapshot);
|
|
666
|
+
if (isLockedFor(snapshot.livePolicy, role, kind)) return "locked";
|
|
667
|
+
if (snapshot.livePolicy.recordingConsent === "view_only_until_agree" && consentPending(snapshot.livePolicy, role, snapshot.recording === "recording", snapshot.recordingConsentGiven)) {
|
|
668
|
+
return "locked";
|
|
669
|
+
}
|
|
670
|
+
if (kind === "microphone" && snapshot.mutedByHost) return "muted_by_host";
|
|
671
|
+
return null;
|
|
672
|
+
}
|
|
605
673
|
function staticObservation(phase, reason = null) {
|
|
606
674
|
return {
|
|
607
675
|
phase,
|
|
@@ -704,7 +772,7 @@ function exactNoteTakerParticipant(meeting, participants) {
|
|
|
704
772
|
}
|
|
705
773
|
function noteTakerStatus(args) {
|
|
706
774
|
const present = exactNoteTakerParticipant(args.meeting, args.participants) !== null;
|
|
707
|
-
const raw = args.meeting?.metadata[NOTE_TAKER_METADATA_KEY];
|
|
775
|
+
const raw = args.meeting?.metadata?.[NOTE_TAKER_METADATA_KEY];
|
|
708
776
|
const row = typeof raw === "object" && raw !== null && !Array.isArray(raw) ? raw : {};
|
|
709
777
|
const recorded = readState(row["state"]);
|
|
710
778
|
const detail = typeof row["reason"] === "string" && row["reason"].length > 0 ? row["reason"] : null;
|
|
@@ -843,7 +911,7 @@ function useCanRecord() {
|
|
|
843
911
|
}
|
|
844
912
|
|
|
845
913
|
// src/react/root.tsx
|
|
846
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
914
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
847
915
|
function useCoreObservation(options = {}) {
|
|
848
916
|
const snapshot = useMeetSnapshot();
|
|
849
917
|
const { meeting, phase, reason } = options;
|
|
@@ -1000,7 +1068,7 @@ function useMeetAppPanel(meeting) {
|
|
|
1000
1068
|
}
|
|
1001
1069
|
|
|
1002
1070
|
// src/react/hooks.ts
|
|
1003
|
-
import { useCallback as useCallback2, useEffect as useEffect3, useMemo as useMemo4, useRef as useRef3, useState as
|
|
1071
|
+
import { useCallback as useCallback2, useEffect as useEffect3, useMemo as useMemo4, useRef as useRef3, useState as useState3, useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
1004
1072
|
import { useRealtimeManager as useRealtimeManager2 } from "@ai-matrx/realtime/react";
|
|
1005
1073
|
|
|
1006
1074
|
// src/core/record.ts
|
|
@@ -1126,7 +1194,8 @@ function useRoom() {
|
|
|
1126
1194
|
failure: snapshot?.failure ?? null,
|
|
1127
1195
|
secondDevice: snapshot?.secondDevice ?? null,
|
|
1128
1196
|
local,
|
|
1129
|
-
|
|
1197
|
+
// An observer (role `viewer`) publishes nothing: no Share screen to press and be refused (MD-16).
|
|
1198
|
+
canShareScreen: (engine?.supportsScreenShare() ?? true) && !isObserverRole(snapshot?.grants.role ?? null),
|
|
1130
1199
|
join: useCallback2(
|
|
1131
1200
|
async (request) => requireEngine(engine, "join").join(request),
|
|
1132
1201
|
[engine]
|
|
@@ -1183,7 +1252,7 @@ function useRoom() {
|
|
|
1183
1252
|
}
|
|
1184
1253
|
function useStage(pageSize = DEFAULT_PAGE_SIZE) {
|
|
1185
1254
|
const snapshot = useMeetSnapshot();
|
|
1186
|
-
const [page, setPage] =
|
|
1255
|
+
const [page, setPage] = useState3(0);
|
|
1187
1256
|
const stage = useMemo4(
|
|
1188
1257
|
() => computeStage({
|
|
1189
1258
|
participants: snapshot?.participants ?? [],
|
|
@@ -1244,7 +1313,7 @@ function useLobby() {
|
|
|
1244
1313
|
};
|
|
1245
1314
|
}
|
|
1246
1315
|
function useCountdown(untilMs) {
|
|
1247
|
-
const [now, setNow] =
|
|
1316
|
+
const [now, setNow] = useState3(() => Date.now());
|
|
1248
1317
|
const active = typeof untilMs === "number" && untilMs > now;
|
|
1249
1318
|
useEffect3(() => {
|
|
1250
1319
|
if (!active) return void 0;
|
|
@@ -1257,7 +1326,7 @@ function useCountdown(untilMs) {
|
|
|
1257
1326
|
}
|
|
1258
1327
|
function useKnockNotice() {
|
|
1259
1328
|
const lobby = useLobby();
|
|
1260
|
-
const [dismissed, setDismissed] =
|
|
1329
|
+
const [dismissed, setDismissed] = useState3([]);
|
|
1261
1330
|
const keyOf = (entry) => `${entry.identity}@${entry.knockedAt}`;
|
|
1262
1331
|
const open = lobby.canAdmit ? lobby.waiting.filter((entry) => !dismissed.includes(keyOf(entry))) : [];
|
|
1263
1332
|
const knocker = open[0] ?? null;
|
|
@@ -1343,11 +1412,11 @@ function useMeetAi() {
|
|
|
1343
1412
|
const host = useMeetHost();
|
|
1344
1413
|
const snapshot = useMeetSnapshot();
|
|
1345
1414
|
const isHost = useIsHost();
|
|
1346
|
-
const [asking, setAsking] =
|
|
1347
|
-
const [answer, setAnswer] =
|
|
1348
|
-
const [coverage, setCoverage] =
|
|
1349
|
-
const [phase, setPhase] =
|
|
1350
|
-
const [error, setError] =
|
|
1415
|
+
const [asking, setAsking] = useState3(false);
|
|
1416
|
+
const [answer, setAnswer] = useState3(null);
|
|
1417
|
+
const [coverage, setCoverage] = useState3(null);
|
|
1418
|
+
const [phase, setPhase] = useState3(null);
|
|
1419
|
+
const [error, setError] = useState3(null);
|
|
1351
1420
|
const ai = host?.ai ?? null;
|
|
1352
1421
|
const meeting = snapshot?.meeting ?? null;
|
|
1353
1422
|
const participants = snapshot?.participants ?? [];
|
|
@@ -1457,12 +1526,51 @@ function useMeetAi() {
|
|
|
1457
1526
|
}, [ai, meeting, dispatchNoteTaker])
|
|
1458
1527
|
};
|
|
1459
1528
|
}
|
|
1529
|
+
function useCaptions() {
|
|
1530
|
+
const host = useMeetHost();
|
|
1531
|
+
const snapshot = useMeetSnapshot();
|
|
1532
|
+
const ai = useMeetAi();
|
|
1533
|
+
const on = snapshot?.captionsOn === true;
|
|
1534
|
+
const refusal = snapshot?.captionsRefusal ?? null;
|
|
1535
|
+
const taker = ai.noteTaker;
|
|
1536
|
+
const meeting = snapshot?.meeting ?? null;
|
|
1537
|
+
const request = useCallback2(() => {
|
|
1538
|
+
if (host === null || meeting === null) return;
|
|
1539
|
+
void host.ai.requestCaptions({ meetingId: meeting.id });
|
|
1540
|
+
}, [host, meeting]);
|
|
1541
|
+
const toggle = useCallback2(() => {
|
|
1542
|
+
if (host === null) return;
|
|
1543
|
+
const next = !on;
|
|
1544
|
+
host.store.patch({ captionsOn: next, captionsRefusal: null });
|
|
1545
|
+
if (next && taker.state !== "joining" && taker.state !== "transcribing") request();
|
|
1546
|
+
}, [host, on, taker.state, request]);
|
|
1547
|
+
let state = "off";
|
|
1548
|
+
let reason = null;
|
|
1549
|
+
let remedy = null;
|
|
1550
|
+
if (on) {
|
|
1551
|
+
if (taker.state === "transcribing" && taker.present) {
|
|
1552
|
+
state = "live";
|
|
1553
|
+
} else if (taker.state === "joining") {
|
|
1554
|
+
state = "starting";
|
|
1555
|
+
} else if (refusal !== null && refusal.reason.length > 0) {
|
|
1556
|
+
state = "unavailable";
|
|
1557
|
+
reason = refusal.reason;
|
|
1558
|
+
remedy = refusal.remedy.length > 0 ? refusal.remedy : null;
|
|
1559
|
+
} else if (taker.state === "ended" || taker.state === "handoff_pending") {
|
|
1560
|
+
state = "unavailable";
|
|
1561
|
+
reason = noteTakerLabel(taker);
|
|
1562
|
+
} else {
|
|
1563
|
+
state = "starting";
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
return { on, state, reason, remedy, toggle };
|
|
1567
|
+
}
|
|
1460
1568
|
function useEndMeeting() {
|
|
1461
1569
|
const host = useMeetHost();
|
|
1462
1570
|
const snapshot = useMeetSnapshot();
|
|
1463
1571
|
const isHost = useIsHost();
|
|
1464
|
-
const [ending, setEnding] =
|
|
1465
|
-
const [notice, setNotice] =
|
|
1572
|
+
const [ending, setEnding] = useState3(false);
|
|
1573
|
+
const [notice, setNotice] = useState3(null);
|
|
1466
1574
|
const meeting = snapshot?.meeting ?? null;
|
|
1467
1575
|
const session = host?.meetings ?? null;
|
|
1468
1576
|
return {
|
|
@@ -1494,7 +1602,7 @@ function useConsentNotice() {
|
|
|
1494
1602
|
const snapshot = useMeetSnapshot();
|
|
1495
1603
|
const agent = noteTakerParticipant(snapshot?.participants ?? []);
|
|
1496
1604
|
if (agent === null) return null;
|
|
1497
|
-
return
|
|
1605
|
+
return `AI notes are on. ${agent.displayName} is in this meeting, transcribing what is said and writing notes everyone here can read.`;
|
|
1498
1606
|
}
|
|
1499
1607
|
function useMediaSupervisor() {
|
|
1500
1608
|
const host = useMeetHost();
|
|
@@ -1513,6 +1621,12 @@ function useMediaSupervisor() {
|
|
|
1513
1621
|
retry: useCallback2(
|
|
1514
1622
|
async (kind) => kind === "microphone" ? engine?.setMicrophoneEnabled(true) : engine?.setCameraEnabled(true),
|
|
1515
1623
|
[engine]
|
|
1624
|
+
),
|
|
1625
|
+
reportPreview: useCallback2(
|
|
1626
|
+
(kind, outcome) => {
|
|
1627
|
+
void engine?.previewDevice(kind, outcome);
|
|
1628
|
+
},
|
|
1629
|
+
[engine]
|
|
1516
1630
|
)
|
|
1517
1631
|
};
|
|
1518
1632
|
}
|
|
@@ -1532,7 +1646,7 @@ function useReactions() {
|
|
|
1532
1646
|
return snapshot?.reactions ?? [];
|
|
1533
1647
|
}
|
|
1534
1648
|
function useElapsed(startedAt) {
|
|
1535
|
-
const [now, setNow] =
|
|
1649
|
+
const [now, setNow] = useState3(() => Date.now());
|
|
1536
1650
|
useEffect3(() => {
|
|
1537
1651
|
if (startedAt === null) return void 0;
|
|
1538
1652
|
const timer = setInterval(() => setNow(Date.now()), 1e3);
|
|
@@ -1549,7 +1663,7 @@ function useHostControls() {
|
|
|
1549
1663
|
(participant) => participant.identity === snapshot.localIdentity
|
|
1550
1664
|
);
|
|
1551
1665
|
const actor = me === void 0 ? void 0 : { ...me, role };
|
|
1552
|
-
const [busy, setBusy] =
|
|
1666
|
+
const [busy, setBusy] = useState3(false);
|
|
1553
1667
|
const inRoom = host?.inRoom ?? null;
|
|
1554
1668
|
const store = host?.store ?? null;
|
|
1555
1669
|
const notice = snapshot?.actionNotice ?? null;
|
|
@@ -1632,7 +1746,7 @@ function useModerationNotice() {
|
|
|
1632
1746
|
};
|
|
1633
1747
|
}
|
|
1634
1748
|
function useAudioLevel(stream) {
|
|
1635
|
-
const [level, setLevel] =
|
|
1749
|
+
const [level, setLevel] = useState3(0);
|
|
1636
1750
|
useEffect3(() => {
|
|
1637
1751
|
if (stream === null || stream.getAudioTracks().length === 0) {
|
|
1638
1752
|
setLevel(0);
|
|
@@ -1703,10 +1817,10 @@ function useGuestRecordAccess(meeting) {
|
|
|
1703
1817
|
const host = useMeetHost();
|
|
1704
1818
|
const api = host?.api ?? null;
|
|
1705
1819
|
const stored = guestRecordAccessSetting(meeting);
|
|
1706
|
-
const [chosen, setChosen] =
|
|
1707
|
-
const [effective, setEffective] =
|
|
1708
|
-
const [saving, setSaving] =
|
|
1709
|
-
const [error, setError] =
|
|
1820
|
+
const [chosen, setChosen] = useState3(null);
|
|
1821
|
+
const [effective, setEffective] = useState3(null);
|
|
1822
|
+
const [saving, setSaving] = useState3(false);
|
|
1823
|
+
const [error, setError] = useState3(null);
|
|
1710
1824
|
useEffect3(() => {
|
|
1711
1825
|
setChosen(null);
|
|
1712
1826
|
}, [stored, meeting?.id]);
|
|
@@ -1742,6 +1856,38 @@ function useGuestRecordAccess(meeting) {
|
|
|
1742
1856
|
)
|
|
1743
1857
|
};
|
|
1744
1858
|
}
|
|
1859
|
+
function useLivePolicy() {
|
|
1860
|
+
const snapshot = useMeetSnapshot();
|
|
1861
|
+
const role = useRole();
|
|
1862
|
+
const [now, setNow] = useState3(() => Date.now());
|
|
1863
|
+
const limited = (snapshot?.livePolicy.timeLimitMinutes ?? 0) > 0;
|
|
1864
|
+
useEffect3(() => {
|
|
1865
|
+
if (!limited) return void 0;
|
|
1866
|
+
const timer = setInterval(() => setNow(Date.now()), 1e3);
|
|
1867
|
+
return () => clearInterval(timer);
|
|
1868
|
+
}, [limited]);
|
|
1869
|
+
const policy = snapshot?.livePolicy ?? DEFAULT_LIVE_POLICY;
|
|
1870
|
+
const left = minutesLeft(policy, snapshot?.sessionStartedAt ?? null, now);
|
|
1871
|
+
const host = useMeetHost();
|
|
1872
|
+
const pending = consentPending(policy, role, snapshot?.recording === "recording", snapshot?.recordingConsentGiven === true);
|
|
1873
|
+
const viewOnly = pending && policy.recordingConsent === "view_only_until_agree";
|
|
1874
|
+
const idle = snapshot !== null && snapshot.recording !== "recording" && snapshot.recording !== "starting" && snapshot.recording !== "stopping";
|
|
1875
|
+
const given = snapshot?.recordingConsentGiven === true;
|
|
1876
|
+
const store = host?.store ?? null;
|
|
1877
|
+
useEffect3(() => {
|
|
1878
|
+
if (idle && given) store?.patch({ recordingConsentGiven: false });
|
|
1879
|
+
}, [idle, given, store]);
|
|
1880
|
+
return {
|
|
1881
|
+
canChat: canChat(policy, role),
|
|
1882
|
+
chatMode: policy.chatMode,
|
|
1883
|
+
micLocked: isLockedFor(policy, role, "microphone") || viewOnly,
|
|
1884
|
+
cameraLocked: isLockedFor(policy, role, "camera") || viewOnly,
|
|
1885
|
+
consent: pending ? policy.recordingConsent === "ok_or_leave" ? "ok_or_leave" : "view_only_until_agree" : null,
|
|
1886
|
+
agree: () => store?.patch({ recordingConsentGiven: true }),
|
|
1887
|
+
minutesLeft: left,
|
|
1888
|
+
timeWarning: left !== null && left <= policy.timeLimitWarningMinutes
|
|
1889
|
+
};
|
|
1890
|
+
}
|
|
1745
1891
|
|
|
1746
1892
|
// src/react/collab-hooks.ts
|
|
1747
1893
|
import { useEffect as useEffect4, useRef as useRef4 } from "react";
|
|
@@ -1801,6 +1947,39 @@ function useCollabPanelRequest(onRequest) {
|
|
|
1801
1947
|
// src/core/reactions.ts
|
|
1802
1948
|
var MEET_REACTIONS = ["\u{1F496}", "\u{1F44D}", "\u{1F389}", "\u{1F44F}", "\u{1F602}", "\u{1F62E}", "\u{1F622}", "\u{1F914}", "\u{1F44E}"];
|
|
1803
1949
|
|
|
1950
|
+
// src/core/speaking-detector.ts
|
|
1951
|
+
function createSpeakingWhileMutedDetector(options = {}) {
|
|
1952
|
+
const threshold = options.threshold ?? 0.06;
|
|
1953
|
+
const holdMs = options.holdMs ?? 600;
|
|
1954
|
+
const gapMs = options.gapMs ?? 400;
|
|
1955
|
+
const cooldownMs = options.cooldownMs ?? 2e4;
|
|
1956
|
+
let speechStart = null;
|
|
1957
|
+
let lastLoud = null;
|
|
1958
|
+
let firedAt = null;
|
|
1959
|
+
return {
|
|
1960
|
+
feed(level, at) {
|
|
1961
|
+
if (level >= threshold) {
|
|
1962
|
+
if (speechStart === null || lastLoud === null || at - lastLoud > gapMs) speechStart = at;
|
|
1963
|
+
lastLoud = at;
|
|
1964
|
+
} else if (lastLoud !== null && at - lastLoud > gapMs) {
|
|
1965
|
+
speechStart = null;
|
|
1966
|
+
lastLoud = null;
|
|
1967
|
+
}
|
|
1968
|
+
if (speechStart === null || at - speechStart < holdMs) return false;
|
|
1969
|
+
if (firedAt !== null && at - firedAt < cooldownMs) return false;
|
|
1970
|
+
firedAt = at;
|
|
1971
|
+
speechStart = null;
|
|
1972
|
+
lastLoud = null;
|
|
1973
|
+
return true;
|
|
1974
|
+
},
|
|
1975
|
+
reset() {
|
|
1976
|
+
speechStart = null;
|
|
1977
|
+
lastLoud = null;
|
|
1978
|
+
firedAt = null;
|
|
1979
|
+
}
|
|
1980
|
+
};
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1804
1983
|
// src/react/facade.ts
|
|
1805
1984
|
var NO_ACTIONS = {
|
|
1806
1985
|
join: async () => void 0,
|
|
@@ -1865,10 +2044,10 @@ function useMeetCore() {
|
|
|
1865
2044
|
import { Alert, AlertDescription, Button, Checkbox, ErrorBox, Label, SegmentedControl, Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@ai-matrx/design-system";
|
|
1866
2045
|
|
|
1867
2046
|
// src/skins/meet/collab.tsx
|
|
1868
|
-
import { useEffect as useEffect5, useRef as useRef5, useState as
|
|
2047
|
+
import { useEffect as useEffect5, useRef as useRef5, useState as useState4 } from "react";
|
|
1869
2048
|
|
|
1870
2049
|
// src/skins/meet/icons.tsx
|
|
1871
|
-
import { jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
2050
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
1872
2051
|
function Icon({ children, ...props }) {
|
|
1873
2052
|
return /* @__PURE__ */ jsx4(
|
|
1874
2053
|
"svg",
|
|
@@ -1889,14 +2068,14 @@ function Icon({ children, ...props }) {
|
|
|
1889
2068
|
);
|
|
1890
2069
|
}
|
|
1891
2070
|
function MicIcon(props) {
|
|
1892
|
-
return /* @__PURE__ */
|
|
2071
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
1893
2072
|
/* @__PURE__ */ jsx4("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" }),
|
|
1894
2073
|
/* @__PURE__ */ jsx4("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
|
|
1895
2074
|
/* @__PURE__ */ jsx4("path", { d: "M12 19v3" })
|
|
1896
2075
|
] });
|
|
1897
2076
|
}
|
|
1898
2077
|
function MicOffIcon(props) {
|
|
1899
|
-
return /* @__PURE__ */
|
|
2078
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
1900
2079
|
/* @__PURE__ */ jsx4("path", { d: "M2 2l20 20" }),
|
|
1901
2080
|
/* @__PURE__ */ jsx4("path", { d: "M9 9v3a3 3 0 0 0 5.12 2.12" }),
|
|
1902
2081
|
/* @__PURE__ */ jsx4("path", { d: "M15 9.34V5a3 3 0 0 0-5.94-.6" }),
|
|
@@ -1905,20 +2084,20 @@ function MicOffIcon(props) {
|
|
|
1905
2084
|
] });
|
|
1906
2085
|
}
|
|
1907
2086
|
function CameraIcon(props) {
|
|
1908
|
-
return /* @__PURE__ */
|
|
2087
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
1909
2088
|
/* @__PURE__ */ jsx4("path", { d: "m23 7-7 5 7 5V7Z" }),
|
|
1910
2089
|
/* @__PURE__ */ jsx4("rect", { x: "1", y: "5", width: "15", height: "14", rx: "2" })
|
|
1911
2090
|
] });
|
|
1912
2091
|
}
|
|
1913
2092
|
function CameraOffIcon(props) {
|
|
1914
|
-
return /* @__PURE__ */
|
|
2093
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
1915
2094
|
/* @__PURE__ */ jsx4("path", { d: "M2 2l20 20" }),
|
|
1916
2095
|
/* @__PURE__ */ jsx4("path", { d: "M10.66 5H14a2 2 0 0 1 2 2v3.34l1 1L23 7v10" }),
|
|
1917
2096
|
/* @__PURE__ */ jsx4("path", { d: "M16 16a2 2 0 0 1-2 2H3a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h2" })
|
|
1918
2097
|
] });
|
|
1919
2098
|
}
|
|
1920
2099
|
function ScreenShareIcon(props) {
|
|
1921
|
-
return /* @__PURE__ */
|
|
2100
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
1922
2101
|
/* @__PURE__ */ jsx4("rect", { x: "2", y: "3", width: "20", height: "14", rx: "2" }),
|
|
1923
2102
|
/* @__PURE__ */ jsx4("path", { d: "M8 21h8M12 17v4" }),
|
|
1924
2103
|
/* @__PURE__ */ jsx4("path", { d: "M12 13V8m0 0-2.5 2.5M12 8l2.5 2.5" })
|
|
@@ -1931,7 +2110,7 @@ function PhoneOffIcon(props) {
|
|
|
1931
2110
|
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" }) });
|
|
1932
2111
|
}
|
|
1933
2112
|
function HandIcon(props) {
|
|
1934
|
-
return /* @__PURE__ */
|
|
2113
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
1935
2114
|
/* @__PURE__ */ jsx4("path", { d: "M18 11V6a2 2 0 0 0-4 0v5" }),
|
|
1936
2115
|
/* @__PURE__ */ jsx4("path", { d: "M14 10V4a2 2 0 0 0-4 0v7" }),
|
|
1937
2116
|
/* @__PURE__ */ jsx4("path", { d: "M10 10.5V6a2 2 0 0 0-4 0v8" }),
|
|
@@ -1942,7 +2121,7 @@ function ChatIcon(props) {
|
|
|
1942
2121
|
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" }) });
|
|
1943
2122
|
}
|
|
1944
2123
|
function PeopleIcon(props) {
|
|
1945
|
-
return /* @__PURE__ */
|
|
2124
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
1946
2125
|
/* @__PURE__ */ jsx4("path", { d: "M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2" }),
|
|
1947
2126
|
/* @__PURE__ */ jsx4("circle", { cx: "9", cy: "7", r: "4" }),
|
|
1948
2127
|
/* @__PURE__ */ jsx4("path", { d: "M22 21v-2a4 4 0 0 0-3-3.87M16 3.13a4 4 0 0 1 0 7.75" })
|
|
@@ -1952,25 +2131,37 @@ function RecordIcon(props) {
|
|
|
1952
2131
|
return /* @__PURE__ */ jsx4(Icon, { ...props, children: /* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "8", fill: "currentColor", stroke: "none" }) });
|
|
1953
2132
|
}
|
|
1954
2133
|
function SparklesIcon(props) {
|
|
1955
|
-
return /* @__PURE__ */
|
|
2134
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
1956
2135
|
/* @__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" }),
|
|
1957
2136
|
/* @__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" })
|
|
1958
2137
|
] });
|
|
1959
2138
|
}
|
|
2139
|
+
function CaptionsIcon(props) {
|
|
2140
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
2141
|
+
/* @__PURE__ */ jsx4("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
|
|
2142
|
+
/* @__PURE__ */ jsx4("path", { d: "M10 10.5a2 2 0 1 0 0 3M16 10.5a2 2 0 1 0 0 3" })
|
|
2143
|
+
] });
|
|
2144
|
+
}
|
|
2145
|
+
function NotesIcon(props) {
|
|
2146
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
2147
|
+
/* @__PURE__ */ jsx4("path", { d: "M4 20l1-4L16.5 4.5a2.1 2.1 0 0 1 3 3L8 19l-4 1Z" }),
|
|
2148
|
+
/* @__PURE__ */ jsx4("path", { d: "M14 7l3 3" })
|
|
2149
|
+
] });
|
|
2150
|
+
}
|
|
1960
2151
|
function LockIcon(props) {
|
|
1961
|
-
return /* @__PURE__ */
|
|
2152
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
1962
2153
|
/* @__PURE__ */ jsx4("rect", { x: "4", y: "10", width: "16", height: "11", rx: "2" }),
|
|
1963
2154
|
/* @__PURE__ */ jsx4("path", { d: "M8 10V7a4 4 0 0 1 8 0v3" })
|
|
1964
2155
|
] });
|
|
1965
2156
|
}
|
|
1966
2157
|
function LayoutIcon(props) {
|
|
1967
|
-
return /* @__PURE__ */
|
|
2158
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
1968
2159
|
/* @__PURE__ */ jsx4("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
|
|
1969
2160
|
/* @__PURE__ */ jsx4("path", { d: "M3 9h18M9 21V9" })
|
|
1970
2161
|
] });
|
|
1971
2162
|
}
|
|
1972
2163
|
function SettingsIcon(props) {
|
|
1973
|
-
return /* @__PURE__ */
|
|
2164
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
1974
2165
|
/* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "3" }),
|
|
1975
2166
|
/* @__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" })
|
|
1976
2167
|
] });
|
|
@@ -1982,19 +2173,19 @@ function CloseIcon(props) {
|
|
|
1982
2173
|
return /* @__PURE__ */ jsx4(Icon, { ...props, children: /* @__PURE__ */ jsx4("path", { d: "M18 6 6 18M6 6l12 12" }) });
|
|
1983
2174
|
}
|
|
1984
2175
|
function PinIcon(props) {
|
|
1985
|
-
return /* @__PURE__ */
|
|
2176
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
1986
2177
|
/* @__PURE__ */ jsx4("path", { d: "M12 17v5" }),
|
|
1987
2178
|
/* @__PURE__ */ jsx4("path", { d: "M9 2h6l-1 6 3.5 3.5V14H6.5v-2.5L10 8 9 2Z" })
|
|
1988
2179
|
] });
|
|
1989
2180
|
}
|
|
1990
2181
|
function WifiLowIcon(props) {
|
|
1991
|
-
return /* @__PURE__ */
|
|
2182
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
1992
2183
|
/* @__PURE__ */ jsx4("path", { d: "M12 20h.01" }),
|
|
1993
2184
|
/* @__PURE__ */ jsx4("path", { d: "M8.5 16.5a5 5 0 0 1 7 0" })
|
|
1994
2185
|
] });
|
|
1995
2186
|
}
|
|
1996
2187
|
function SmileIcon(props) {
|
|
1997
|
-
return /* @__PURE__ */
|
|
2188
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
1998
2189
|
/* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "10" }),
|
|
1999
2190
|
/* @__PURE__ */ jsx4("path", { d: "M8 14s1.5 2 4 2 4-2 4-2" }),
|
|
2000
2191
|
/* @__PURE__ */ jsx4("line", { x1: "9", x2: "9.01", y1: "9", y2: "9" }),
|
|
@@ -2002,20 +2193,20 @@ function SmileIcon(props) {
|
|
|
2002
2193
|
] });
|
|
2003
2194
|
}
|
|
2004
2195
|
function MoreIcon(props) {
|
|
2005
|
-
return /* @__PURE__ */
|
|
2196
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
2006
2197
|
/* @__PURE__ */ jsx4("circle", { cx: "12", cy: "12", r: "1" }),
|
|
2007
2198
|
/* @__PURE__ */ jsx4("circle", { cx: "19", cy: "12", r: "1" }),
|
|
2008
2199
|
/* @__PURE__ */ jsx4("circle", { cx: "5", cy: "12", r: "1" })
|
|
2009
2200
|
] });
|
|
2010
2201
|
}
|
|
2011
2202
|
function SearchIcon(props) {
|
|
2012
|
-
return /* @__PURE__ */
|
|
2203
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
2013
2204
|
/* @__PURE__ */ jsx4("circle", { cx: "11", cy: "11", r: "8" }),
|
|
2014
2205
|
/* @__PURE__ */ jsx4("path", { d: "m21 21-4.3-4.3" })
|
|
2015
2206
|
] });
|
|
2016
2207
|
}
|
|
2017
2208
|
function KeyboardIcon(props) {
|
|
2018
|
-
return /* @__PURE__ */
|
|
2209
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
2019
2210
|
/* @__PURE__ */ jsx4("path", { d: "M10 8h.01M12 12h.01M14 8h.01M16 12h.01M18 8h.01M6 8h.01M7 16h10M8 12h.01" }),
|
|
2020
2211
|
/* @__PURE__ */ jsx4("rect", { width: "20", height: "16", x: "2", y: "4", rx: "2" })
|
|
2021
2212
|
] });
|
|
@@ -2024,7 +2215,7 @@ function SpotlightIcon(props) {
|
|
|
2024
2215
|
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" }) });
|
|
2025
2216
|
}
|
|
2026
2217
|
function SignalIcon({ bars, ...props }) {
|
|
2027
|
-
return /* @__PURE__ */
|
|
2218
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
2028
2219
|
/* @__PURE__ */ jsx4("path", { d: "M4 20v-2", opacity: bars >= 1 ? 1 : 0.3 }),
|
|
2029
2220
|
/* @__PURE__ */ jsx4("path", { d: "M10 20v-6", opacity: bars >= 2 ? 1 : 0.3 }),
|
|
2030
2221
|
/* @__PURE__ */ jsx4("path", { d: "M16 20V9", opacity: bars >= 3 ? 1 : 0.3 }),
|
|
@@ -2032,14 +2223,14 @@ function SignalIcon({ bars, ...props }) {
|
|
|
2032
2223
|
] });
|
|
2033
2224
|
}
|
|
2034
2225
|
function SpeakerIcon(props) {
|
|
2035
|
-
return /* @__PURE__ */
|
|
2226
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
2036
2227
|
/* @__PURE__ */ jsx4("path", { d: "M11 5 6 9H2v6h4l5 4V5Z" }),
|
|
2037
2228
|
/* @__PURE__ */ jsx4("path", { d: "M15.54 8.46a5 5 0 0 1 0 7.07" }),
|
|
2038
2229
|
/* @__PURE__ */ jsx4("path", { d: "M19.07 4.93a10 10 0 0 1 0 14.14" })
|
|
2039
2230
|
] });
|
|
2040
2231
|
}
|
|
2041
2232
|
function FlagIcon(props) {
|
|
2042
|
-
return /* @__PURE__ */
|
|
2233
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
2043
2234
|
/* @__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" }),
|
|
2044
2235
|
/* @__PURE__ */ jsx4("line", { x1: "4", x2: "4", y1: "22", y2: "15" })
|
|
2045
2236
|
] });
|
|
@@ -2048,35 +2239,35 @@ function PencilIcon(props) {
|
|
|
2048
2239
|
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" }) });
|
|
2049
2240
|
}
|
|
2050
2241
|
function ActivitiesIcon(props) {
|
|
2051
|
-
return /* @__PURE__ */
|
|
2242
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
2052
2243
|
/* @__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" }),
|
|
2053
2244
|
/* @__PURE__ */ jsx4("rect", { x: "3", y: "14", width: "7", height: "7", rx: "1" }),
|
|
2054
2245
|
/* @__PURE__ */ jsx4("circle", { cx: "17.5", cy: "17.5", r: "3.5" })
|
|
2055
2246
|
] });
|
|
2056
2247
|
}
|
|
2057
2248
|
function PollIcon(props) {
|
|
2058
|
-
return /* @__PURE__ */
|
|
2249
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
2059
2250
|
/* @__PURE__ */ jsx4("line", { x1: "18", x2: "18", y1: "20", y2: "10" }),
|
|
2060
2251
|
/* @__PURE__ */ jsx4("line", { x1: "12", x2: "12", y1: "20", y2: "4" }),
|
|
2061
2252
|
/* @__PURE__ */ jsx4("line", { x1: "6", x2: "6", y1: "20", y2: "14" })
|
|
2062
2253
|
] });
|
|
2063
2254
|
}
|
|
2064
2255
|
function QuestionIcon(props) {
|
|
2065
|
-
return /* @__PURE__ */
|
|
2256
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
2066
2257
|
/* @__PURE__ */ jsx4("path", { d: "M7.9 20A9 9 0 1 0 4 16.1L2 22Z" }),
|
|
2067
2258
|
/* @__PURE__ */ jsx4("path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" }),
|
|
2068
2259
|
/* @__PURE__ */ jsx4("path", { d: "M12 17h.01" })
|
|
2069
2260
|
] });
|
|
2070
2261
|
}
|
|
2071
2262
|
function WhiteboardIcon(props) {
|
|
2072
|
-
return /* @__PURE__ */
|
|
2263
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
2073
2264
|
/* @__PURE__ */ jsx4("path", { d: "M2 3h20" }),
|
|
2074
2265
|
/* @__PURE__ */ jsx4("path", { d: "M21 3v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V3" }),
|
|
2075
2266
|
/* @__PURE__ */ jsx4("path", { d: "m7 21 5-5 5 5" })
|
|
2076
2267
|
] });
|
|
2077
2268
|
}
|
|
2078
2269
|
function BreakoutIcon(props) {
|
|
2079
|
-
return /* @__PURE__ */
|
|
2270
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
2080
2271
|
/* @__PURE__ */ jsx4("rect", { width: "7", height: "18", x: "3", y: "3", rx: "1" }),
|
|
2081
2272
|
/* @__PURE__ */ jsx4("rect", { width: "7", height: "7", x: "14", y: "3", rx: "1" }),
|
|
2082
2273
|
/* @__PURE__ */ jsx4("rect", { width: "7", height: "7", x: "14", y: "14", rx: "1" })
|
|
@@ -2086,29 +2277,32 @@ function UpvoteIcon(props) {
|
|
|
2086
2277
|
return /* @__PURE__ */ jsx4(Icon, { ...props, children: /* @__PURE__ */ jsx4("path", { d: "M9 18v-6H5l7-7 7 7h-4v6H9z" }) });
|
|
2087
2278
|
}
|
|
2088
2279
|
function EraserIcon(props) {
|
|
2089
|
-
return /* @__PURE__ */
|
|
2280
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
2090
2281
|
/* @__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" }),
|
|
2091
2282
|
/* @__PURE__ */ jsx4("path", { d: "M22 21H7" }),
|
|
2092
2283
|
/* @__PURE__ */ jsx4("path", { d: "m5 11 9 9" })
|
|
2093
2284
|
] });
|
|
2094
2285
|
}
|
|
2095
2286
|
function HighlighterIcon(props) {
|
|
2096
|
-
return /* @__PURE__ */
|
|
2287
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
2097
2288
|
/* @__PURE__ */ jsx4("path", { d: "m9 11-6 6v3h9l3-3" }),
|
|
2098
2289
|
/* @__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" })
|
|
2099
2290
|
] });
|
|
2100
2291
|
}
|
|
2101
2292
|
function UndoIcon(props) {
|
|
2102
|
-
return /* @__PURE__ */
|
|
2293
|
+
return /* @__PURE__ */ jsxs2(Icon, { ...props, children: [
|
|
2103
2294
|
/* @__PURE__ */ jsx4("path", { d: "M9 14 4 9l5-5" }),
|
|
2104
2295
|
/* @__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" })
|
|
2105
2296
|
] });
|
|
2106
2297
|
}
|
|
2298
|
+
function ChevronUpIcon(props) {
|
|
2299
|
+
return /* @__PURE__ */ jsx4(Icon, { ...props, children: /* @__PURE__ */ jsx4("path", { d: "m6 15 6-6 6 6" }) });
|
|
2300
|
+
}
|
|
2107
2301
|
|
|
2108
2302
|
// src/skins/meet/collab.tsx
|
|
2109
|
-
import { jsx as jsx5, jsxs as
|
|
2303
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
2110
2304
|
function useNotice() {
|
|
2111
|
-
const [notice, setNotice] =
|
|
2305
|
+
const [notice, setNotice] = useState4(null);
|
|
2112
2306
|
useEffect5(() => {
|
|
2113
2307
|
if (notice === null) return void 0;
|
|
2114
2308
|
const timer = setTimeout(() => setNotice(null), notice.failed ? 7e3 : 3e3);
|
|
@@ -2137,16 +2331,16 @@ function ActivitiesControl({
|
|
|
2137
2331
|
active,
|
|
2138
2332
|
onOpen
|
|
2139
2333
|
}) {
|
|
2140
|
-
const [open, setOpen] =
|
|
2334
|
+
const [open, setOpen] = useState4(false);
|
|
2141
2335
|
const available = useAvailableActivities();
|
|
2142
2336
|
const attention = useActivityAttention();
|
|
2143
2337
|
if (available.length === 0) return null;
|
|
2144
|
-
return /* @__PURE__ */
|
|
2145
|
-
/* @__PURE__ */
|
|
2338
|
+
return /* @__PURE__ */ jsxs3("span", { className: "mx-meet__anchor", children: [
|
|
2339
|
+
/* @__PURE__ */ jsxs3(ControlButton, { label: "Activities", active: open || active !== null, onClick: () => setOpen(!open), children: [
|
|
2146
2340
|
/* @__PURE__ */ jsx5(ActivitiesIcon, {}),
|
|
2147
2341
|
attention ? /* @__PURE__ */ jsx5("span", { className: "mx-meet__dot", "aria-hidden": "true" }) : null
|
|
2148
2342
|
] }),
|
|
2149
|
-
open ? /* @__PURE__ */ jsx5(Popover, { label: "Activities", onClose: () => setOpen(false), children: /* @__PURE__ */ jsx5("div", { className: "mx-meet__menu", role: "menu", children: available.map((panel) => /* @__PURE__ */
|
|
2343
|
+
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(
|
|
2150
2344
|
MenuItem,
|
|
2151
2345
|
{
|
|
2152
2346
|
onSelect: () => {
|
|
@@ -2165,11 +2359,11 @@ function ActivitiesControl({
|
|
|
2165
2359
|
}
|
|
2166
2360
|
function PollComposer({ maxOptions, onDone }) {
|
|
2167
2361
|
const { act } = useCollab();
|
|
2168
|
-
const [question, setQuestion] =
|
|
2169
|
-
const [options, setOptions] =
|
|
2170
|
-
const [multiple, setMultiple] =
|
|
2171
|
-
const [anonymous, setAnonymous] =
|
|
2172
|
-
const [busy, setBusy] =
|
|
2362
|
+
const [question, setQuestion] = useState4("");
|
|
2363
|
+
const [options, setOptions] = useState4(["", ""]);
|
|
2364
|
+
const [multiple, setMultiple] = useState4(false);
|
|
2365
|
+
const [anonymous, setAnonymous] = useState4(false);
|
|
2366
|
+
const [busy, setBusy] = useState4(false);
|
|
2173
2367
|
const [notice, show] = useNotice();
|
|
2174
2368
|
const filled = options.map((o) => o.trim()).filter(Boolean);
|
|
2175
2369
|
const ready = question.trim().length > 0 && filled.length >= 2;
|
|
@@ -2192,7 +2386,7 @@ function PollComposer({ maxOptions, onDone }) {
|
|
|
2192
2386
|
setBusy(false);
|
|
2193
2387
|
onDone();
|
|
2194
2388
|
};
|
|
2195
|
-
return /* @__PURE__ */
|
|
2389
|
+
return /* @__PURE__ */ jsxs3(
|
|
2196
2390
|
"form",
|
|
2197
2391
|
{
|
|
2198
2392
|
className: "mx-meet__collab-card",
|
|
@@ -2201,7 +2395,7 @@ function PollComposer({ maxOptions, onDone }) {
|
|
|
2201
2395
|
if (ready) void save(true);
|
|
2202
2396
|
},
|
|
2203
2397
|
children: [
|
|
2204
|
-
/* @__PURE__ */
|
|
2398
|
+
/* @__PURE__ */ jsxs3("label", { className: "mx-meet__field", children: [
|
|
2205
2399
|
/* @__PURE__ */ jsx5("span", { className: "mx-meet__field-label", children: "Question" }),
|
|
2206
2400
|
/* @__PURE__ */ jsx5(
|
|
2207
2401
|
"input",
|
|
@@ -2215,7 +2409,7 @@ function PollComposer({ maxOptions, onDone }) {
|
|
|
2215
2409
|
}
|
|
2216
2410
|
)
|
|
2217
2411
|
] }),
|
|
2218
|
-
options.map((option, index) => /* @__PURE__ */
|
|
2412
|
+
options.map((option, index) => /* @__PURE__ */ jsxs3("div", { className: "mx-meet__composer-row", children: [
|
|
2219
2413
|
/* @__PURE__ */ jsx5(
|
|
2220
2414
|
"input",
|
|
2221
2415
|
{
|
|
@@ -2230,16 +2424,16 @@ function PollComposer({ maxOptions, onDone }) {
|
|
|
2230
2424
|
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
|
|
2231
2425
|
] }, index)),
|
|
2232
2426
|
options.length < maxOptions ? /* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__link", onClick: () => setOptions([...options, ""]), children: "Add an answer" }) : null,
|
|
2233
|
-
/* @__PURE__ */
|
|
2427
|
+
/* @__PURE__ */ jsxs3("label", { className: "mx-meet__toggle", children: [
|
|
2234
2428
|
/* @__PURE__ */ jsx5("input", { type: "checkbox", checked: multiple, onChange: (event) => setMultiple(event.target.checked) }),
|
|
2235
2429
|
"People can pick more than one"
|
|
2236
2430
|
] }),
|
|
2237
|
-
/* @__PURE__ */
|
|
2431
|
+
/* @__PURE__ */ jsxs3("label", { className: "mx-meet__toggle", children: [
|
|
2238
2432
|
/* @__PURE__ */ jsx5("input", { type: "checkbox", checked: anonymous, onChange: (event) => setAnonymous(event.target.checked) }),
|
|
2239
2433
|
"Anonymous \u2014 nobody sees who picked what"
|
|
2240
2434
|
] }),
|
|
2241
2435
|
/* @__PURE__ */ jsx5(Notice, { notice }),
|
|
2242
|
-
/* @__PURE__ */
|
|
2436
|
+
/* @__PURE__ */ jsxs3("div", { className: "mx-meet__collab-actions", children: [
|
|
2243
2437
|
/* @__PURE__ */ jsx5("button", { type: "submit", className: "mx-meet__primary mx-meet__primary--small", disabled: !ready || busy, children: "Launch" }),
|
|
2244
2438
|
/* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__chip", disabled: !ready || busy, onClick: () => void save(false), children: "Save draft" }),
|
|
2245
2439
|
/* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__link", onClick: onDone, children: "Cancel" })
|
|
@@ -2250,7 +2444,7 @@ function PollComposer({ maxOptions, onDone }) {
|
|
|
2250
2444
|
}
|
|
2251
2445
|
function PollCard({ poll }) {
|
|
2252
2446
|
const { act, isHost } = useCollab();
|
|
2253
|
-
const [picked, setPicked] =
|
|
2447
|
+
const [picked, setPicked] = useState4(poll.myVote.slice());
|
|
2254
2448
|
const [notice, show] = useNotice();
|
|
2255
2449
|
useEffect5(() => setPicked(poll.myVote.slice()), [poll.myVote]);
|
|
2256
2450
|
const counts = poll.options.some((o) => o.votes !== void 0);
|
|
@@ -2262,12 +2456,12 @@ function PollCard({ poll }) {
|
|
|
2262
2456
|
if (!canVote) return;
|
|
2263
2457
|
setPicked(poll.multiple ? picked.includes(id) ? picked.filter((p) => p !== id) : [...picked, id] : [id]);
|
|
2264
2458
|
};
|
|
2265
|
-
return /* @__PURE__ */
|
|
2266
|
-
/* @__PURE__ */
|
|
2459
|
+
return /* @__PURE__ */ jsxs3("article", { className: "mx-meet__collab-card", "aria-label": poll.question, children: [
|
|
2460
|
+
/* @__PURE__ */ jsxs3("header", { className: "mx-meet__collab-head", children: [
|
|
2267
2461
|
/* @__PURE__ */ jsx5("strong", { className: "mx-meet__collab-title", children: poll.question }),
|
|
2268
2462
|
/* @__PURE__ */ jsx5("span", { className: "mx-meet__collab-state", children: stateWord })
|
|
2269
2463
|
] }),
|
|
2270
|
-
/* @__PURE__ */
|
|
2464
|
+
/* @__PURE__ */ jsxs3("p", { className: "mx-meet__panel-note", children: [
|
|
2271
2465
|
poll.multiple ? "Pick any." : "Pick one.",
|
|
2272
2466
|
poll.anonymous ? " Anonymous." : "",
|
|
2273
2467
|
counts && poll.voterCount !== null ? ` ${poll.voterCount} voted.` : "",
|
|
@@ -2276,8 +2470,8 @@ function PollCard({ poll }) {
|
|
|
2276
2470
|
/* @__PURE__ */ jsx5("ul", { className: "mx-meet__poll-options", children: poll.options.map((option) => {
|
|
2277
2471
|
const share = counts && total > 0 ? Math.round((option.votes ?? 0) / total * 100) : 0;
|
|
2278
2472
|
const chosen = picked.includes(option.id);
|
|
2279
|
-
return /* @__PURE__ */
|
|
2280
|
-
/* @__PURE__ */
|
|
2473
|
+
return /* @__PURE__ */ jsxs3("li", { children: [
|
|
2474
|
+
/* @__PURE__ */ jsxs3(
|
|
2281
2475
|
"button",
|
|
2282
2476
|
{
|
|
2283
2477
|
type: "button",
|
|
@@ -2288,7 +2482,7 @@ function PollCard({ poll }) {
|
|
|
2288
2482
|
children: [
|
|
2289
2483
|
counts ? /* @__PURE__ */ jsx5("span", { className: "mx-meet__poll-bar", style: { width: `${share}%` }, "aria-hidden": "true" }) : null,
|
|
2290
2484
|
/* @__PURE__ */ jsx5("span", { className: "mx-meet__poll-text", children: option.text }),
|
|
2291
|
-
counts ? /* @__PURE__ */
|
|
2485
|
+
counts ? /* @__PURE__ */ jsxs3("span", { className: "mx-meet__poll-count", children: [
|
|
2292
2486
|
option.votes ?? 0,
|
|
2293
2487
|
" \xB7 ",
|
|
2294
2488
|
share,
|
|
@@ -2301,7 +2495,7 @@ function PollCard({ poll }) {
|
|
|
2301
2495
|
] }, option.id);
|
|
2302
2496
|
}) }),
|
|
2303
2497
|
/* @__PURE__ */ jsx5(Notice, { notice }),
|
|
2304
|
-
/* @__PURE__ */
|
|
2498
|
+
/* @__PURE__ */ jsxs3("div", { className: "mx-meet__collab-actions", children: [
|
|
2305
2499
|
canVote ? /* @__PURE__ */ jsx5(
|
|
2306
2500
|
"button",
|
|
2307
2501
|
{
|
|
@@ -2321,11 +2515,11 @@ function PollCard({ poll }) {
|
|
|
2321
2515
|
}
|
|
2322
2516
|
function PollsPanel({ onClose }) {
|
|
2323
2517
|
const { collab, isHost } = useCollab();
|
|
2324
|
-
const [composing, setComposing] =
|
|
2518
|
+
const [composing, setComposing] = useState4(false);
|
|
2325
2519
|
const polls = collab?.polls ?? [];
|
|
2326
2520
|
const maxOptions = collab?.settings?.pollMaxOptions ?? 10;
|
|
2327
2521
|
const ordered = [...polls].reverse();
|
|
2328
|
-
return /* @__PURE__ */
|
|
2522
|
+
return /* @__PURE__ */ jsxs3(PanelShell, { title: "Polls", onClose, children: [
|
|
2329
2523
|
collab?.error != null ? /* @__PURE__ */ jsx5("p", { className: "mx-meet__panel-note mx-meet__collab-error", children: collab.error }) : null,
|
|
2330
2524
|
isHost && !composing ? /* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__primary mx-meet__primary--small", onClick: () => setComposing(true), children: "New poll" }) : null,
|
|
2331
2525
|
isHost && composing ? /* @__PURE__ */ jsx5(PollComposer, { maxOptions, onDone: () => setComposing(false) }) : null,
|
|
@@ -2335,12 +2529,12 @@ function PollsPanel({ onClose }) {
|
|
|
2335
2529
|
}
|
|
2336
2530
|
function QuestionCard({ question }) {
|
|
2337
2531
|
const { act, isHost } = useCollab();
|
|
2338
|
-
const [answering, setAnswering] =
|
|
2339
|
-
const [reply, setReply] =
|
|
2532
|
+
const [answering, setAnswering] = useState4(false);
|
|
2533
|
+
const [reply, setReply] = useState4("");
|
|
2340
2534
|
const [notice, show] = useNotice();
|
|
2341
|
-
return /* @__PURE__ */
|
|
2342
|
-
/* @__PURE__ */
|
|
2343
|
-
/* @__PURE__ */
|
|
2535
|
+
return /* @__PURE__ */ jsxs3("li", { className: `mx-meet__collab-card mx-meet__question mx-meet__question--${question.state}`, children: [
|
|
2536
|
+
/* @__PURE__ */ jsxs3("div", { className: "mx-meet__question-row", children: [
|
|
2537
|
+
/* @__PURE__ */ jsxs3(
|
|
2344
2538
|
"button",
|
|
2345
2539
|
{
|
|
2346
2540
|
type: "button",
|
|
@@ -2355,15 +2549,15 @@ function QuestionCard({ question }) {
|
|
|
2355
2549
|
]
|
|
2356
2550
|
}
|
|
2357
2551
|
),
|
|
2358
|
-
/* @__PURE__ */
|
|
2359
|
-
/* @__PURE__ */
|
|
2552
|
+
/* @__PURE__ */ jsxs3("div", { className: "mx-meet__question-body", children: [
|
|
2553
|
+
/* @__PURE__ */ jsxs3("span", { className: "mx-meet__chat-meta", children: [
|
|
2360
2554
|
/* @__PURE__ */ jsx5("strong", { children: question.mine ? "You" : question.askerName }),
|
|
2361
2555
|
question.mine && question.anonymous ? /* @__PURE__ */ jsx5("span", { className: "mx-meet__chat-private", children: "anonymous" }) : null,
|
|
2362
2556
|
question.state !== "open" ? /* @__PURE__ */ jsx5("span", { className: "mx-meet__collab-state", children: question.state === "answered" ? "Answered" : "Dismissed" }) : null
|
|
2363
2557
|
] }),
|
|
2364
2558
|
/* @__PURE__ */ jsx5("span", { className: "mx-meet__chat-text", children: question.text }),
|
|
2365
|
-
question.answer !== null ? /* @__PURE__ */
|
|
2366
|
-
/* @__PURE__ */
|
|
2559
|
+
question.answer !== null ? /* @__PURE__ */ jsxs3("span", { className: "mx-meet__question-answer", children: [
|
|
2560
|
+
/* @__PURE__ */ jsxs3("strong", { children: [
|
|
2367
2561
|
question.answeredByName ?? "Host",
|
|
2368
2562
|
":"
|
|
2369
2563
|
] }),
|
|
@@ -2372,7 +2566,7 @@ function QuestionCard({ question }) {
|
|
|
2372
2566
|
] }) : null
|
|
2373
2567
|
] })
|
|
2374
2568
|
] }),
|
|
2375
|
-
answering ? /* @__PURE__ */
|
|
2569
|
+
answering ? /* @__PURE__ */ jsxs3(
|
|
2376
2570
|
"form",
|
|
2377
2571
|
{
|
|
2378
2572
|
className: "mx-meet__composer-row",
|
|
@@ -2404,7 +2598,7 @@ function QuestionCard({ question }) {
|
|
|
2404
2598
|
}
|
|
2405
2599
|
) : null,
|
|
2406
2600
|
/* @__PURE__ */ jsx5(Notice, { notice }),
|
|
2407
|
-
isHost || question.mine ? /* @__PURE__ */
|
|
2601
|
+
isHost || question.mine ? /* @__PURE__ */ jsxs3("div", { className: "mx-meet__collab-actions", children: [
|
|
2408
2602
|
isHost && question.state === "open" && !answering ? /* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__chip", onClick: () => setAnswering(true), children: "Answer" }) : null,
|
|
2409
2603
|
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,
|
|
2410
2604
|
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,
|
|
@@ -2414,9 +2608,9 @@ function QuestionCard({ question }) {
|
|
|
2414
2608
|
}
|
|
2415
2609
|
function QaPanel({ onClose }) {
|
|
2416
2610
|
const { collab, act } = useCollab();
|
|
2417
|
-
const [draft, setDraft] =
|
|
2418
|
-
const [anonymous, setAnonymous] =
|
|
2419
|
-
const [order, setOrder] =
|
|
2611
|
+
const [draft, setDraft] = useState4("");
|
|
2612
|
+
const [anonymous, setAnonymous] = useState4(false);
|
|
2613
|
+
const [order, setOrder] = useState4("popular");
|
|
2420
2614
|
const [notice, show] = useNotice();
|
|
2421
2615
|
const allowAnonymous = collab?.settings?.qaAnonymousAllowed === true;
|
|
2422
2616
|
const questions = [...collab?.questions ?? []];
|
|
@@ -2424,9 +2618,9 @@ function QaPanel({ onClose }) {
|
|
|
2424
2618
|
questions.sort(
|
|
2425
2619
|
(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 ?? "")
|
|
2426
2620
|
);
|
|
2427
|
-
return /* @__PURE__ */
|
|
2621
|
+
return /* @__PURE__ */ jsxs3(PanelShell, { title: "Q&A", onClose, children: [
|
|
2428
2622
|
collab?.error != null ? /* @__PURE__ */ jsx5("p", { className: "mx-meet__panel-note mx-meet__collab-error", children: collab.error }) : null,
|
|
2429
|
-
/* @__PURE__ */
|
|
2623
|
+
/* @__PURE__ */ jsxs3(
|
|
2430
2624
|
"form",
|
|
2431
2625
|
{
|
|
2432
2626
|
className: "mx-meet__composer mx-meet__composer--chat",
|
|
@@ -2440,7 +2634,7 @@ function QaPanel({ onClose }) {
|
|
|
2440
2634
|
});
|
|
2441
2635
|
},
|
|
2442
2636
|
children: [
|
|
2443
|
-
/* @__PURE__ */
|
|
2637
|
+
/* @__PURE__ */ jsxs3("div", { className: "mx-meet__composer-row", children: [
|
|
2444
2638
|
/* @__PURE__ */ jsx5(
|
|
2445
2639
|
"input",
|
|
2446
2640
|
{
|
|
@@ -2454,7 +2648,7 @@ function QaPanel({ onClose }) {
|
|
|
2454
2648
|
),
|
|
2455
2649
|
/* @__PURE__ */ jsx5("button", { type: "submit", className: "mx-meet__send", disabled: draft.trim().length === 0, children: "Ask" })
|
|
2456
2650
|
] }),
|
|
2457
|
-
allowAnonymous ? /* @__PURE__ */
|
|
2651
|
+
allowAnonymous ? /* @__PURE__ */ jsxs3("label", { className: "mx-meet__toggle", children: [
|
|
2458
2652
|
/* @__PURE__ */ jsx5("input", { type: "checkbox", checked: anonymous, onChange: (event) => setAnonymous(event.target.checked) }),
|
|
2459
2653
|
"Ask anonymously"
|
|
2460
2654
|
] }) : null
|
|
@@ -2505,10 +2699,10 @@ function StrokeView({ stroke, onPick }) {
|
|
|
2505
2699
|
}
|
|
2506
2700
|
function WhiteboardPanel({ onClose }) {
|
|
2507
2701
|
const { collab, act, isHost, localIdentity } = useCollab();
|
|
2508
|
-
const [tool, setTool] =
|
|
2509
|
-
const [color, setColor] =
|
|
2510
|
-
const [drawing, setDrawing] =
|
|
2511
|
-
const [pending, setPending] =
|
|
2702
|
+
const [tool, setTool] = useState4("pen");
|
|
2703
|
+
const [color, setColor] = useState4(INK[0]);
|
|
2704
|
+
const [drawing, setDrawing] = useState4(null);
|
|
2705
|
+
const [pending, setPending] = useState4([]);
|
|
2512
2706
|
const [notice, show] = useNotice();
|
|
2513
2707
|
const svgRef = useRef5(null);
|
|
2514
2708
|
const strokes = collab?.strokes ?? [];
|
|
@@ -2542,8 +2736,8 @@ function WhiteboardPanel({ onClose }) {
|
|
|
2542
2736
|
if (!result.ok) show(result);
|
|
2543
2737
|
});
|
|
2544
2738
|
};
|
|
2545
|
-
return /* @__PURE__ */
|
|
2546
|
-
/* @__PURE__ */
|
|
2739
|
+
return /* @__PURE__ */ jsxs3("section", { className: "mx-meet__whiteboard", "aria-label": "Whiteboard", children: [
|
|
2740
|
+
/* @__PURE__ */ jsxs3("header", { className: "mx-meet__whiteboard-bar", children: [
|
|
2547
2741
|
/* @__PURE__ */ jsx5("strong", { className: "mx-meet__panel-title", children: "Whiteboard" }),
|
|
2548
2742
|
/* @__PURE__ */ jsx5("div", { className: "mx-meet__pills", role: "group", "aria-label": "Tool", children: [
|
|
2549
2743
|
["pen", "Pen", /* @__PURE__ */ jsx5(PencilIcon, { width: 16, height: 16 }, "p")],
|
|
@@ -2593,7 +2787,7 @@ function WhiteboardPanel({ onClose }) {
|
|
|
2593
2787
|
/* @__PURE__ */ jsx5(ControlButton, { label: "Close whiteboard", onClick: onClose, children: /* @__PURE__ */ jsx5(CloseIcon, { width: 16, height: 16 }) })
|
|
2594
2788
|
] }),
|
|
2595
2789
|
/* @__PURE__ */ jsx5(Notice, { notice }),
|
|
2596
|
-
/* @__PURE__ */
|
|
2790
|
+
/* @__PURE__ */ jsxs3(
|
|
2597
2791
|
"svg",
|
|
2598
2792
|
{
|
|
2599
2793
|
ref: svgRef,
|
|
@@ -2651,7 +2845,7 @@ function clock(ms) {
|
|
|
2651
2845
|
}
|
|
2652
2846
|
var BREAKOUT_EXPIRE_RETRY_MS = 5e3;
|
|
2653
2847
|
function useNow(active) {
|
|
2654
|
-
const [now, setNow] =
|
|
2848
|
+
const [now, setNow] = useState4(() => Date.now());
|
|
2655
2849
|
useEffect5(() => {
|
|
2656
2850
|
if (!active) return void 0;
|
|
2657
2851
|
const timer = setInterval(() => setNow(Date.now()), 1e3);
|
|
@@ -2666,11 +2860,11 @@ function BreakoutSetup() {
|
|
|
2666
2860
|
const people = (snapshot?.participants ?? []).filter(
|
|
2667
2861
|
(p) => !p.isAgent && p.role !== "host" && p.role !== "cohost"
|
|
2668
2862
|
);
|
|
2669
|
-
const [count, setCount] =
|
|
2670
|
-
const [mode, setMode] =
|
|
2671
|
-
const [minutes, setMinutes] =
|
|
2672
|
-
const [manual, setManual] =
|
|
2673
|
-
const [busy, setBusy] =
|
|
2863
|
+
const [count, setCount] = useState4(Math.min(Math.max(2, Math.ceil(people.length / 4)), settings?.breakoutMaxRooms ?? 20));
|
|
2864
|
+
const [mode, setMode] = useState4("auto");
|
|
2865
|
+
const [minutes, setMinutes] = useState4(settings?.breakoutDefaultMinutes ?? 15);
|
|
2866
|
+
const [manual, setManual] = useState4({});
|
|
2867
|
+
const [busy, setBusy] = useState4(false);
|
|
2674
2868
|
const [notice, show] = useNotice();
|
|
2675
2869
|
const max = settings?.breakoutMaxRooms ?? 20;
|
|
2676
2870
|
const rooms = Math.min(Math.max(1, count), max);
|
|
@@ -2682,8 +2876,8 @@ function BreakoutSetup() {
|
|
|
2682
2876
|
(_, index) => people.filter((p) => (manual[p.identity] ?? -1) === index).map((p) => p.identity)
|
|
2683
2877
|
) : Array.from({ length: rooms }, () => []);
|
|
2684
2878
|
const nameOf = (identity) => people.find((p) => p.identity === identity)?.displayName ?? identity;
|
|
2685
|
-
return /* @__PURE__ */
|
|
2686
|
-
/* @__PURE__ */
|
|
2879
|
+
return /* @__PURE__ */ jsxs3("div", { className: "mx-meet__collab-card", children: [
|
|
2880
|
+
/* @__PURE__ */ jsxs3("label", { className: "mx-meet__field", children: [
|
|
2687
2881
|
/* @__PURE__ */ jsx5("span", { className: "mx-meet__field-label", children: "Rooms" }),
|
|
2688
2882
|
/* @__PURE__ */ jsx5(
|
|
2689
2883
|
"input",
|
|
@@ -2712,7 +2906,7 @@ function BreakoutSetup() {
|
|
|
2712
2906
|
},
|
|
2713
2907
|
value
|
|
2714
2908
|
)) }),
|
|
2715
|
-
/* @__PURE__ */
|
|
2909
|
+
/* @__PURE__ */ jsxs3("label", { className: "mx-meet__field", children: [
|
|
2716
2910
|
/* @__PURE__ */ jsx5("span", { className: "mx-meet__field-label", children: "Timer (minutes, 0 for none)" }),
|
|
2717
2911
|
/* @__PURE__ */ jsx5(
|
|
2718
2912
|
"input",
|
|
@@ -2726,9 +2920,9 @@ function BreakoutSetup() {
|
|
|
2726
2920
|
}
|
|
2727
2921
|
)
|
|
2728
2922
|
] }),
|
|
2729
|
-
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__ */
|
|
2923
|
+
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: [
|
|
2730
2924
|
/* @__PURE__ */ jsx5("span", { className: "mx-meet__person-name", children: person.displayName }),
|
|
2731
|
-
/* @__PURE__ */
|
|
2925
|
+
/* @__PURE__ */ jsxs3(
|
|
2732
2926
|
"select",
|
|
2733
2927
|
{
|
|
2734
2928
|
className: "mx-meet__select mx-meet__select--compact",
|
|
@@ -2737,15 +2931,15 @@ function BreakoutSetup() {
|
|
|
2737
2931
|
onChange: (event) => setManual({ ...manual, [person.identity]: Number(event.target.value) }),
|
|
2738
2932
|
children: [
|
|
2739
2933
|
/* @__PURE__ */ jsx5("option", { value: -1, children: "Main room" }),
|
|
2740
|
-
Array.from({ length: rooms }, (_, index) => /* @__PURE__ */
|
|
2934
|
+
Array.from({ length: rooms }, (_, index) => /* @__PURE__ */ jsxs3("option", { value: index, children: [
|
|
2741
2935
|
"Room ",
|
|
2742
2936
|
index + 1
|
|
2743
2937
|
] }, index))
|
|
2744
2938
|
]
|
|
2745
2939
|
}
|
|
2746
2940
|
)
|
|
2747
|
-
] }, person.identity)) }) : mode === "auto" ? /* @__PURE__ */ jsx5("ul", { className: "mx-meet__breakout-rooms", children: assignment.map((members, index) => /* @__PURE__ */
|
|
2748
|
-
/* @__PURE__ */
|
|
2941
|
+
] }, person.identity)) }) : mode === "auto" ? /* @__PURE__ */ jsx5("ul", { className: "mx-meet__breakout-rooms", children: assignment.map((members, index) => /* @__PURE__ */ jsxs3("li", { children: [
|
|
2942
|
+
/* @__PURE__ */ jsxs3("strong", { children: [
|
|
2749
2943
|
"Room ",
|
|
2750
2944
|
index + 1
|
|
2751
2945
|
] }),
|
|
@@ -2753,7 +2947,7 @@ function BreakoutSetup() {
|
|
|
2753
2947
|
/* @__PURE__ */ jsx5("span", { className: "mx-meet__panel-note", children: members.length === 0 ? "empty" : members.map(nameOf).join(", ") })
|
|
2754
2948
|
] }, index)) }) : /* @__PURE__ */ jsx5("p", { className: "mx-meet__panel-note", children: "Everyone picks a room from their own screen." }),
|
|
2755
2949
|
/* @__PURE__ */ jsx5(Notice, { notice }),
|
|
2756
|
-
/* @__PURE__ */
|
|
2950
|
+
/* @__PURE__ */ jsxs3(
|
|
2757
2951
|
"button",
|
|
2758
2952
|
{
|
|
2759
2953
|
type: "button",
|
|
@@ -2786,7 +2980,7 @@ function BreakoutRun({ plan }) {
|
|
|
2786
2980
|
const snapshot = useMeetSnapshot();
|
|
2787
2981
|
const now = useNow(plan.endsAt !== null);
|
|
2788
2982
|
const remaining = breakoutRemainingMs(plan, now);
|
|
2789
|
-
const [broadcast, setBroadcast] =
|
|
2983
|
+
const [broadcast, setBroadcast] = useState4("");
|
|
2790
2984
|
const [notice, show] = useNotice();
|
|
2791
2985
|
const nameOf = (identity) => displayNameFor(snapshot?.names ?? {}, identity, snapshot?.participants.find((p) => p.identity === identity)?.displayName);
|
|
2792
2986
|
const mine = assignedRoom(plan, localIdentity);
|
|
@@ -2798,8 +2992,8 @@ function BreakoutRun({ plan }) {
|
|
|
2798
2992
|
}
|
|
2799
2993
|
show(await moveTo(roomId));
|
|
2800
2994
|
};
|
|
2801
|
-
return /* @__PURE__ */
|
|
2802
|
-
/* @__PURE__ */
|
|
2995
|
+
return /* @__PURE__ */ jsxs3("div", { className: "mx-meet__collab-card", children: [
|
|
2996
|
+
/* @__PURE__ */ jsxs3("p", { className: "mx-meet__panel-note", children: [
|
|
2803
2997
|
plan.rooms.length,
|
|
2804
2998
|
" room",
|
|
2805
2999
|
plan.rooms.length === 1 ? "" : "s",
|
|
@@ -2810,15 +3004,15 @@ function BreakoutRun({ plan }) {
|
|
|
2810
3004
|
/* @__PURE__ */ jsx5("ul", { className: "mx-meet__breakout-rooms", children: plan.rooms.map((room) => {
|
|
2811
3005
|
const here = breakoutRoomId === room.id;
|
|
2812
3006
|
const mayJoin = isHost || plan.allowChoose || mine?.id === room.id;
|
|
2813
|
-
return /* @__PURE__ */
|
|
2814
|
-
/* @__PURE__ */
|
|
3007
|
+
return /* @__PURE__ */ jsxs3("li", { className: here ? "mx-meet__breakout-room mx-meet__breakout-room--here" : "mx-meet__breakout-room", children: [
|
|
3008
|
+
/* @__PURE__ */ jsxs3("div", { className: "mx-meet__collab-head", children: [
|
|
2815
3009
|
/* @__PURE__ */ jsx5("strong", { children: room.name }),
|
|
2816
3010
|
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
|
|
2817
3011
|
] }),
|
|
2818
3012
|
/* @__PURE__ */ jsx5("span", { className: "mx-meet__panel-note", children: room.identities.length === 0 ? "Nobody assigned" : room.identities.map(nameOf).join(", ") }),
|
|
2819
|
-
isHost && room.identities.length > 0 ? /* @__PURE__ */ jsx5("ul", { className: "mx-meet__people", children: room.identities.map((identity) => /* @__PURE__ */
|
|
3013
|
+
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: [
|
|
2820
3014
|
/* @__PURE__ */ jsx5("span", { className: "mx-meet__person-name", children: nameOf(identity) }),
|
|
2821
|
-
/* @__PURE__ */
|
|
3015
|
+
/* @__PURE__ */ jsxs3(
|
|
2822
3016
|
"select",
|
|
2823
3017
|
{
|
|
2824
3018
|
className: "mx-meet__select mx-meet__select--compact",
|
|
@@ -2839,7 +3033,7 @@ function BreakoutRun({ plan }) {
|
|
|
2839
3033
|
] }, room.id);
|
|
2840
3034
|
}) }),
|
|
2841
3035
|
breakoutRoomId !== null ? /* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__chip", onClick: () => void join(null), children: "Return to the main room" }) : null,
|
|
2842
|
-
isHost ? /* @__PURE__ */
|
|
3036
|
+
isHost ? /* @__PURE__ */ jsxs3(
|
|
2843
3037
|
"form",
|
|
2844
3038
|
{
|
|
2845
3039
|
className: "mx-meet__composer-row",
|
|
@@ -2875,7 +3069,7 @@ function BreakoutRun({ plan }) {
|
|
|
2875
3069
|
type: "button",
|
|
2876
3070
|
className: "mx-meet__primary mx-meet__primary--small",
|
|
2877
3071
|
onClick: () => void act({ action: "breakout_close" }).then(show),
|
|
2878
|
-
children: "
|
|
3072
|
+
children: "Close rooms"
|
|
2879
3073
|
}
|
|
2880
3074
|
) : null
|
|
2881
3075
|
] });
|
|
@@ -2883,7 +3077,7 @@ function BreakoutRun({ plan }) {
|
|
|
2883
3077
|
function BreakoutsPanel({ onClose }) {
|
|
2884
3078
|
const { collab, isHost } = useCollab();
|
|
2885
3079
|
const plan = collab?.breakout?.state === "open" ? collab.breakout : null;
|
|
2886
|
-
return /* @__PURE__ */
|
|
3080
|
+
return /* @__PURE__ */ jsxs3(PanelShell, { title: "Breakout rooms", onClose, children: [
|
|
2887
3081
|
collab?.error != null ? /* @__PURE__ */ jsx5("p", { className: "mx-meet__panel-note mx-meet__collab-error", children: collab.error }) : null,
|
|
2888
3082
|
plan !== null ? /* @__PURE__ */ jsx5(BreakoutRun, { plan }) : isHost ? /* @__PURE__ */ jsx5(BreakoutSetup, {}) : /* @__PURE__ */ jsx5("p", { className: "mx-meet__panel-note", children: "Breakout rooms are closed." })
|
|
2889
3083
|
] });
|
|
@@ -2893,11 +3087,16 @@ function BreakoutBanner() {
|
|
|
2893
3087
|
const { collab, act, moveTo, localIdentity, breakoutRoomId } = useCollab();
|
|
2894
3088
|
const plan = collab?.breakout ?? null;
|
|
2895
3089
|
const open = plan?.state === "open" ? plan : null;
|
|
2896
|
-
const now = useNow(open?.endsAt != null);
|
|
3090
|
+
const now = useNow(open?.endsAt != null || open?.closingAt != null);
|
|
2897
3091
|
const remaining = breakoutRemainingMs(open, now);
|
|
3092
|
+
const closing = breakoutClosingMs(open, now);
|
|
2898
3093
|
const assigned = assignedRoom(open, localIdentity);
|
|
2899
|
-
const [
|
|
2900
|
-
const [
|
|
3094
|
+
const [later, setLater] = useState4(null);
|
|
3095
|
+
const [autoSince, setAutoSince] = useState4(null);
|
|
3096
|
+
const AUTO_MOVE_MS = 1e4;
|
|
3097
|
+
const autoLeft = open?.moveMode === "auto" && assigned !== null && autoSince?.id === open.id && later !== open.id ? Math.max(0, AUTO_MOVE_MS - (now - autoSince.at)) : null;
|
|
3098
|
+
const [dismissedBroadcast, setDismissedBroadcast] = useState4(null);
|
|
3099
|
+
const [failure, setFailure] = useState4(null);
|
|
2901
3100
|
const expireAsked = useRef5(null);
|
|
2902
3101
|
const moveAt = collab?.moveRequest?.at ?? null;
|
|
2903
3102
|
useEffect5(() => {
|
|
@@ -2908,6 +3107,19 @@ function BreakoutBanner() {
|
|
|
2908
3107
|
if ((here ?? null) === request.roomId) return;
|
|
2909
3108
|
void moveTo(request.roomId).then((result) => setFailure(result.ok ? null : result.message));
|
|
2910
3109
|
}, [moveAt, host, moveTo]);
|
|
3110
|
+
const joinAssigned = async () => {
|
|
3111
|
+
if (assigned === null) return;
|
|
3112
|
+
const said = await act({ action: "breakout_join", roomId: assigned.id });
|
|
3113
|
+
const result = said.ok ? await moveTo(assigned.id) : said;
|
|
3114
|
+
setFailure(result.ok ? null : result.message);
|
|
3115
|
+
};
|
|
3116
|
+
useEffect5(() => {
|
|
3117
|
+
if (open === null || open.moveMode !== "auto" || assigned === null || breakoutRoomId !== null) return;
|
|
3118
|
+
if (autoSince?.id !== open.id) setAutoSince({ id: open.id, at: Date.now() });
|
|
3119
|
+
}, [open, assigned, breakoutRoomId, autoSince]);
|
|
3120
|
+
useEffect5(() => {
|
|
3121
|
+
if (autoLeft === 0) void joinAssigned();
|
|
3122
|
+
}, [autoLeft]);
|
|
2911
3123
|
useEffect5(() => {
|
|
2912
3124
|
if (open === null || remaining === null || remaining > 0) return;
|
|
2913
3125
|
const asked = expireAsked.current;
|
|
@@ -2919,31 +3131,29 @@ function BreakoutBanner() {
|
|
|
2919
3131
|
const showBroadcast = broadcast !== null && broadcast.at !== dismissedBroadcast && open !== null;
|
|
2920
3132
|
const room = open?.rooms.find((r) => r.id === breakoutRoomId) ?? null;
|
|
2921
3133
|
if (open === null && failure === null) return null;
|
|
2922
|
-
return /* @__PURE__ */
|
|
3134
|
+
return /* @__PURE__ */ jsxs3("div", { className: "mx-meet__breakout-banner", role: "status", children: [
|
|
2923
3135
|
failure !== null ? /* @__PURE__ */ jsx5("span", { className: "mx-meet__collab-error", children: failure }) : null,
|
|
2924
|
-
|
|
3136
|
+
closing !== null ? /* @__PURE__ */ jsxs3("span", { role: "status", "data-meet-notice": "breakout-closing", children: [
|
|
3137
|
+
"Rooms closing in ",
|
|
3138
|
+
Math.ceil(closing / 1e3),
|
|
3139
|
+
room !== null ? " \u2014 you return to the main meeting" : ""
|
|
3140
|
+
] }) : null,
|
|
3141
|
+
room !== null ? /* @__PURE__ */ jsxs3("span", { children: [
|
|
2925
3142
|
/* @__PURE__ */ jsx5("strong", { children: room.name }),
|
|
2926
|
-
remaining !== null ? ` \xB7 ${clock(remaining)} left` : "",
|
|
3143
|
+
remaining !== null && closing === null ? ` \xB7 ${clock(remaining)} left` : "",
|
|
2927
3144
|
/* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__chip", onClick: () => void moveTo(null), children: "Return to main room" })
|
|
2928
|
-
] }) : assigned !== null ? /* @__PURE__ */
|
|
2929
|
-
|
|
2930
|
-
|
|
2931
|
-
|
|
2932
|
-
/* @__PURE__ */ jsx5(
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
}),
|
|
2941
|
-
children: "Join"
|
|
2942
|
-
}
|
|
2943
|
-
)
|
|
2944
|
-
] }) : open?.allowChoose ? /* @__PURE__ */ jsx5("span", { children: "Breakout rooms are open \u2014 pick one under Activities." }) : null,
|
|
2945
|
-
showBroadcast ? /* @__PURE__ */ jsxs2("span", { className: "mx-meet__breakout-broadcast", children: [
|
|
2946
|
-
/* @__PURE__ */ jsxs2("strong", { children: [
|
|
3145
|
+
] }) : assigned !== null && later !== open?.id ? /* @__PURE__ */ jsxs3("span", { children: [
|
|
3146
|
+
autoLeft !== null ? `You're being moved to ${assigned.name} in ${Math.ceil(autoLeft / 1e3)} s` : `You're invited to ${assigned.name}`,
|
|
3147
|
+
remaining !== null && closing === null ? ` \xB7 ${clock(remaining)} left` : "",
|
|
3148
|
+
/* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__primary mx-meet__primary--small", onClick: () => void joinAssigned(), children: "Join room" }),
|
|
3149
|
+
/* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__chip", onClick: () => setLater(open?.id ?? null), children: "Later" })
|
|
3150
|
+
] }) : assigned !== null ? /* @__PURE__ */ jsxs3("span", { children: [
|
|
3151
|
+
assigned.name,
|
|
3152
|
+
" is open",
|
|
3153
|
+
/* @__PURE__ */ jsx5("button", { type: "button", className: "mx-meet__chip", onClick: () => void joinAssigned(), children: "Join room" })
|
|
3154
|
+
] }) : open?.allowChoose ? /* @__PURE__ */ jsx5("span", { children: "Rooms are open \u2014 pick one under Activities." }) : null,
|
|
3155
|
+
showBroadcast ? /* @__PURE__ */ jsxs3("span", { className: "mx-meet__breakout-broadcast", children: [
|
|
3156
|
+
/* @__PURE__ */ jsxs3("strong", { children: [
|
|
2947
3157
|
broadcast.by,
|
|
2948
3158
|
":"
|
|
2949
3159
|
] }),
|
|
@@ -2963,10 +3173,10 @@ function CaptionLanguageSettings() {
|
|
|
2963
3173
|
const preferred = defaultCaptionLanguage(settings, viewer);
|
|
2964
3174
|
const current = collab?.captionLanguage ?? "";
|
|
2965
3175
|
const choices = CAPTION_LANGUAGES.some((l) => l.tag === preferred) ? CAPTION_LANGUAGES : [{ tag: preferred, name: preferred }, ...CAPTION_LANGUAGES];
|
|
2966
|
-
return /* @__PURE__ */
|
|
2967
|
-
/* @__PURE__ */
|
|
3176
|
+
return /* @__PURE__ */ jsxs3("section", { className: "mx-meet__section", "aria-label": "Captions", children: [
|
|
3177
|
+
/* @__PURE__ */ jsxs3("label", { className: "mx-meet__field", children: [
|
|
2968
3178
|
/* @__PURE__ */ jsx5("span", { className: "mx-meet__field-label", children: "Translate captions to" }),
|
|
2969
|
-
/* @__PURE__ */
|
|
3179
|
+
/* @__PURE__ */ jsxs3(
|
|
2970
3180
|
"select",
|
|
2971
3181
|
{
|
|
2972
3182
|
className: "mx-meet__select",
|
|
@@ -2977,7 +3187,7 @@ function CaptionLanguageSettings() {
|
|
|
2977
3187
|
},
|
|
2978
3188
|
children: [
|
|
2979
3189
|
/* @__PURE__ */ jsx5("option", { value: "", children: "Off \u2014 as spoken" }),
|
|
2980
|
-
current === "" ? /* @__PURE__ */
|
|
3190
|
+
current === "" ? /* @__PURE__ */ jsxs3("option", { value: preferred, children: [
|
|
2981
3191
|
choices.find((c) => c.tag === preferred)?.name ?? preferred,
|
|
2982
3192
|
" (yours)"
|
|
2983
3193
|
] }) : null,
|
|
@@ -2989,12 +3199,39 @@ function CaptionLanguageSettings() {
|
|
|
2989
3199
|
collab?.captionTranslationError != null ? /* @__PURE__ */ jsx5("p", { className: "mx-meet__panel-note mx-meet__collab-error", children: collab.captionTranslationError }) : null
|
|
2990
3200
|
] });
|
|
2991
3201
|
}
|
|
3202
|
+
function CaptionsControl() {
|
|
3203
|
+
const captions = useCaptions();
|
|
3204
|
+
return /* @__PURE__ */ jsx5(
|
|
3205
|
+
ControlButton,
|
|
3206
|
+
{
|
|
3207
|
+
label: captions.on ? "Turn off captions" : "Turn on captions",
|
|
3208
|
+
active: captions.on,
|
|
3209
|
+
pressed: captions.on,
|
|
3210
|
+
onClick: captions.toggle,
|
|
3211
|
+
children: /* @__PURE__ */ jsx5(CaptionsIcon, {})
|
|
3212
|
+
}
|
|
3213
|
+
);
|
|
3214
|
+
}
|
|
3215
|
+
function TakeNotesControl() {
|
|
3216
|
+
const ai = useMeetAi();
|
|
3217
|
+
if (!ai.canControlNoteTaker) return null;
|
|
3218
|
+
const running = ai.noteTaker.state === "joining" || ai.noteTaker.state === "transcribing";
|
|
3219
|
+
return /* @__PURE__ */ jsx5(
|
|
3220
|
+
ControlButton,
|
|
3221
|
+
{
|
|
3222
|
+
label: running ? "Stop taking notes" : "Take notes for me",
|
|
3223
|
+
active: running,
|
|
3224
|
+
onClick: () => void (running ? ai.stopNoteTaker() : ai.startNoteTaker()),
|
|
3225
|
+
children: /* @__PURE__ */ jsx5(NotesIcon, {})
|
|
3226
|
+
}
|
|
3227
|
+
);
|
|
3228
|
+
}
|
|
2992
3229
|
|
|
2993
3230
|
// src/skins/meet/components.tsx
|
|
2994
|
-
import { Fragment, jsx as jsx6, jsxs as
|
|
3231
|
+
import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2995
3232
|
function InertNotice({ what }) {
|
|
2996
|
-
return /* @__PURE__ */
|
|
2997
|
-
/* @__PURE__ */
|
|
3233
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__empty", role: "status", children: [
|
|
3234
|
+
/* @__PURE__ */ jsxs4("p", { className: "mx-meet__empty-title", children: [
|
|
2998
3235
|
what,
|
|
2999
3236
|
" is not ready yet"
|
|
3000
3237
|
] }),
|
|
@@ -3039,6 +3276,7 @@ function ControlButton({
|
|
|
3039
3276
|
label,
|
|
3040
3277
|
active = false,
|
|
3041
3278
|
danger = false,
|
|
3279
|
+
pressed,
|
|
3042
3280
|
onClick,
|
|
3043
3281
|
children
|
|
3044
3282
|
}) {
|
|
@@ -3053,26 +3291,49 @@ function ControlButton({
|
|
|
3053
3291
|
].filter(Boolean).join(" "),
|
|
3054
3292
|
"aria-label": label,
|
|
3055
3293
|
title: label,
|
|
3294
|
+
...pressed !== void 0 ? { "aria-pressed": pressed } : {},
|
|
3056
3295
|
onClick,
|
|
3057
3296
|
children
|
|
3058
3297
|
}
|
|
3059
3298
|
);
|
|
3060
3299
|
}
|
|
3061
3300
|
function RecordingIndicator() {
|
|
3062
|
-
const { state, label } = useRecording();
|
|
3063
|
-
|
|
3064
|
-
|
|
3065
|
-
|
|
3066
|
-
|
|
3067
|
-
|
|
3068
|
-
|
|
3069
|
-
|
|
3070
|
-
|
|
3071
|
-
|
|
3072
|
-
|
|
3073
|
-
]
|
|
3301
|
+
const { state, label, canStart } = useRecording();
|
|
3302
|
+
const snapshot = useMeetSnapshot();
|
|
3303
|
+
const previous = useRef6(state);
|
|
3304
|
+
const [stoppedAt, setStoppedAt] = useState5(null);
|
|
3305
|
+
useEffect6(() => {
|
|
3306
|
+
const was = previous.current;
|
|
3307
|
+
previous.current = state;
|
|
3308
|
+
if ((was === "recording" || was === "starting") && state !== "recording" && state !== "starting") {
|
|
3309
|
+
setStoppedAt(Date.now());
|
|
3310
|
+
const timer = setTimeout(() => setStoppedAt(null), 1e4);
|
|
3311
|
+
return () => clearTimeout(timer);
|
|
3074
3312
|
}
|
|
3075
|
-
|
|
3313
|
+
return void 0;
|
|
3314
|
+
}, [state]);
|
|
3315
|
+
const meetingId = snapshot?.meeting?.id ?? null;
|
|
3316
|
+
if (label === null && stoppedAt === null) return null;
|
|
3317
|
+
return /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
3318
|
+
label !== null ? /* @__PURE__ */ jsxs4(
|
|
3319
|
+
"span",
|
|
3320
|
+
{
|
|
3321
|
+
className: `mx-meet__recording mx-meet__recording--${state}`,
|
|
3322
|
+
role: "status",
|
|
3323
|
+
"aria-live": "polite",
|
|
3324
|
+
children: [
|
|
3325
|
+
/* @__PURE__ */ jsx6(RecordIcon, { width: 10, height: 10 }),
|
|
3326
|
+
label
|
|
3327
|
+
]
|
|
3328
|
+
}
|
|
3329
|
+
) : null,
|
|
3330
|
+
stoppedAt !== null ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__recording", role: "status", "data-meet-notice": "recording-stopped", children: "Recording stopped" }) : null,
|
|
3331
|
+
state === "processing" ? (
|
|
3332
|
+
// rec-processing: the host is told it is being made ready (the indicator says Processing…).
|
|
3333
|
+
/* @__PURE__ */ jsx6("span", { className: "mx-meet__recording", role: "status", "data-meet-notice": "recording-processing", children: "Your recording is being processed. A link appears here when it is ready." })
|
|
3334
|
+
) : null,
|
|
3335
|
+
state === "available" && canStart && meetingId !== null ? /* @__PURE__ */ jsx6("a", { className: "mx-meet__link", href: `/meetings/${meetingId}`, target: "_blank", rel: "noreferrer", children: "View recording" }) : null
|
|
3336
|
+
] });
|
|
3076
3337
|
}
|
|
3077
3338
|
function ConnectionDot({ quality }) {
|
|
3078
3339
|
if (quality === "excellent" || quality === "good" || quality === "unknown") return null;
|
|
@@ -3095,7 +3356,7 @@ function ParticipantTile({
|
|
|
3095
3356
|
const host = useMeetHost();
|
|
3096
3357
|
const snapshot = useMeetSnapshot();
|
|
3097
3358
|
const queue = useHandQueue();
|
|
3098
|
-
const [menu, setMenu] =
|
|
3359
|
+
const [menu, setMenu] = useState5(false);
|
|
3099
3360
|
const videoRef = useTrack(
|
|
3100
3361
|
participant.identity,
|
|
3101
3362
|
participant.screenSharing ? "screen" : "camera"
|
|
@@ -3105,7 +3366,7 @@ function ParticipantTile({
|
|
|
3105
3366
|
const spotlit = snapshot?.spotlight === participant.identity;
|
|
3106
3367
|
const presenting = snapshot?.presenter === participant.identity;
|
|
3107
3368
|
const handPosition = participant.handRaised ? queue.findIndex((entry) => entry.identity === participant.identity) + 1 : 0;
|
|
3108
|
-
return /* @__PURE__ */
|
|
3369
|
+
return /* @__PURE__ */ jsxs4(
|
|
3109
3370
|
"div",
|
|
3110
3371
|
{
|
|
3111
3372
|
className: [
|
|
@@ -3128,12 +3389,12 @@ function ParticipantTile({
|
|
|
3128
3389
|
}
|
|
3129
3390
|
) : /* @__PURE__ */ jsx6("div", { className: "mx-meet__tile-placeholder", children: /* @__PURE__ */ jsx6(Avatar, { name: participant.displayName, url: participant.avatarUrl, size: featured ? 96 : 56 }) }),
|
|
3130
3391
|
presenting ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__tile-presenting", role: "status", children: participant.isLocal ? "You are presenting" : `${participant.displayName} is presenting` }) : null,
|
|
3131
|
-
participant.handRaised ? /* @__PURE__ */
|
|
3392
|
+
participant.handRaised ? /* @__PURE__ */ jsxs4("span", { className: "mx-meet__tile-hand", title: `Hand raised \xB7 ${ordinal(handPosition)} in line`, children: [
|
|
3132
3393
|
/* @__PURE__ */ jsx6(HandIcon, { width: 14, height: 14 }),
|
|
3133
3394
|
handPosition > 0 ? handPosition : null
|
|
3134
3395
|
] }) : null,
|
|
3135
|
-
/* @__PURE__ */
|
|
3136
|
-
/* @__PURE__ */
|
|
3396
|
+
/* @__PURE__ */ jsxs4("div", { className: "mx-meet__tile-bar", children: [
|
|
3397
|
+
/* @__PURE__ */ jsxs4("span", { className: "mx-meet__tile-name", children: [
|
|
3137
3398
|
spotlit ? /* @__PURE__ */ jsx6("span", { title: "Spotlighted for everyone", className: "mx-meet__tile-flag", children: /* @__PURE__ */ jsx6(SpotlightIcon, { width: 12, height: 12 }) }) : null,
|
|
3138
3399
|
participant.displayName,
|
|
3139
3400
|
participant.isLocal ? " (you)" : "",
|
|
@@ -3144,7 +3405,7 @@ function ParticipantTile({
|
|
|
3144
3405
|
!participant.micEnabled ? /* @__PURE__ */ jsx6(MicOffIcon, { width: 14, height: 14 }) : null,
|
|
3145
3406
|
/* @__PURE__ */ jsx6(QualityBars, { quality: participant.quality })
|
|
3146
3407
|
] }),
|
|
3147
|
-
/* @__PURE__ */
|
|
3408
|
+
/* @__PURE__ */ jsxs4("div", { className: menu ? "mx-meet__tile-actions mx-meet__tile-actions--open" : "mx-meet__tile-actions", children: [
|
|
3148
3409
|
/* @__PURE__ */ jsx6(
|
|
3149
3410
|
ControlButton,
|
|
3150
3411
|
{
|
|
@@ -3154,7 +3415,7 @@ function ParticipantTile({
|
|
|
3154
3415
|
children: /* @__PURE__ */ jsx6(PinIcon, { width: 16, height: 16 })
|
|
3155
3416
|
}
|
|
3156
3417
|
),
|
|
3157
|
-
/* @__PURE__ */
|
|
3418
|
+
/* @__PURE__ */ jsxs4("span", { className: "mx-meet__anchor", children: [
|
|
3158
3419
|
/* @__PURE__ */ jsx6(
|
|
3159
3420
|
ControlButton,
|
|
3160
3421
|
{
|
|
@@ -3192,12 +3453,12 @@ function Stage({ pageSize }) {
|
|
|
3192
3453
|
const stage = useStage(pageSize);
|
|
3193
3454
|
const columns = gridColumns(stage.tiles.length);
|
|
3194
3455
|
if (stage.feature === null && stage.tiles.length === 0) {
|
|
3195
|
-
return /* @__PURE__ */
|
|
3456
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__stage mx-meet__stage--empty", children: [
|
|
3196
3457
|
/* @__PURE__ */ jsx6("p", { className: "mx-meet__empty-title", children: "Waiting for others to join" }),
|
|
3197
3458
|
/* @__PURE__ */ jsx6("p", { className: "mx-meet__empty-body", children: "Share the meeting link and people can join from anywhere \u2014 no account needed." })
|
|
3198
3459
|
] });
|
|
3199
3460
|
}
|
|
3200
|
-
return /* @__PURE__ */
|
|
3461
|
+
return /* @__PURE__ */ jsxs4("div", { className: `mx-meet__stage${stage.feature !== null ? " mx-meet__stage--speaker" : ""}`, children: [
|
|
3201
3462
|
stage.feature !== null ? /* @__PURE__ */ jsx6(ParticipantTile, { participant: stage.feature, featured: true }) : null,
|
|
3202
3463
|
/* @__PURE__ */ jsx6(
|
|
3203
3464
|
"div",
|
|
@@ -3207,7 +3468,7 @@ function Stage({ pageSize }) {
|
|
|
3207
3468
|
children: stage.tiles.map((participant) => /* @__PURE__ */ jsx6(ParticipantTile, { participant }, participant.identity))
|
|
3208
3469
|
}
|
|
3209
3470
|
),
|
|
3210
|
-
stage.overflow > 0 ? /* @__PURE__ */
|
|
3471
|
+
stage.overflow > 0 ? /* @__PURE__ */ jsxs4("p", { className: "mx-meet__overflow", children: [
|
|
3211
3472
|
"+",
|
|
3212
3473
|
stage.overflow,
|
|
3213
3474
|
" more ",
|
|
@@ -3219,17 +3480,18 @@ function Stage({ pageSize }) {
|
|
|
3219
3480
|
function ControlBar({ onLeave }) {
|
|
3220
3481
|
const room = useRoom();
|
|
3221
3482
|
const recording = useRecording();
|
|
3222
|
-
const [panel, setPanel] =
|
|
3223
|
-
const [chatTo, setChatTo] =
|
|
3224
|
-
const [popover, setPopover] =
|
|
3225
|
-
const [shortcuts, setShortcuts] =
|
|
3483
|
+
const [panel, setPanel] = useState5("none");
|
|
3484
|
+
const [chatTo, setChatTo] = useState5(null);
|
|
3485
|
+
const [popover, setPopover] = useState5("none");
|
|
3486
|
+
const [shortcuts, setShortcuts] = useState5(false);
|
|
3226
3487
|
const snapshot = useMeetSnapshot();
|
|
3227
3488
|
const lobby = useLobby();
|
|
3228
3489
|
const controls = useHostControls();
|
|
3229
3490
|
const queue = useHandQueue();
|
|
3230
3491
|
const micUnavailable = useLocalMedia().microphone.unavailable;
|
|
3492
|
+
const live = useLivePolicy();
|
|
3231
3493
|
const unread = useUnreadChat(panel === "chat");
|
|
3232
|
-
const [whiteboard, setWhiteboard] =
|
|
3494
|
+
const [whiteboard, setWhiteboard] = useState5(false);
|
|
3233
3495
|
const app = useMeetAppPanel();
|
|
3234
3496
|
const appOpened = useRef6(false);
|
|
3235
3497
|
useEffect6(() => {
|
|
@@ -3263,7 +3525,7 @@ function ControlBar({ onLeave }) {
|
|
|
3263
3525
|
help: () => setShortcuts(true)
|
|
3264
3526
|
});
|
|
3265
3527
|
const hasSpotlight = snapshot?.spotlight !== null && snapshot?.spotlight !== void 0;
|
|
3266
|
-
return /* @__PURE__ */
|
|
3528
|
+
return /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
3267
3529
|
/* @__PURE__ */ jsx6(MeetingOverlays, {}),
|
|
3268
3530
|
shortcuts ? /* @__PURE__ */ jsx6(ShortcutsSheet, { onClose: () => setShortcuts(false) }) : null,
|
|
3269
3531
|
panel === "chat" ? /* @__PURE__ */ jsx6(ChatPanel, { onClose: () => setPanel("none"), to: chatTo, onTo: setChatTo }) : null,
|
|
@@ -3293,9 +3555,10 @@ function ControlBar({ onLeave }) {
|
|
|
3293
3555
|
) }) }) : null,
|
|
3294
3556
|
/* @__PURE__ */ jsx6(BreakoutBanner, {}),
|
|
3295
3557
|
panel !== "people" ? /* @__PURE__ */ jsx6(KnockNotice, { onView: () => setPanel("people") }) : null,
|
|
3558
|
+
/* @__PURE__ */ jsx6(SpeakingWhileMutedNudge, {}),
|
|
3296
3559
|
controls.notice !== null && panel !== "people" ? /* @__PURE__ */ jsx6(Toast, { text: controls.notice.text, failed: controls.notice.failed, onDone: controls.clearNotice }) : null,
|
|
3297
|
-
/* @__PURE__ */
|
|
3298
|
-
/* @__PURE__ */ jsx6(
|
|
3560
|
+
/* @__PURE__ */ jsxs4("div", { className: "mx-meet__controls", children: [
|
|
3561
|
+
live.micLocked ? null : /* @__PURE__ */ jsx6(
|
|
3299
3562
|
ControlButton,
|
|
3300
3563
|
{
|
|
3301
3564
|
label: micUnavailable !== null ? `Unmute \u2014 ${micUnavailable.remedy}` : room.local?.micEnabled === true ? "Mute (\u2318D)" : "Unmute (\u2318D)",
|
|
@@ -3304,7 +3567,8 @@ function ControlBar({ onLeave }) {
|
|
|
3304
3567
|
children: room.local?.micEnabled === true ? /* @__PURE__ */ jsx6(MicIcon, {}) : /* @__PURE__ */ jsx6(MicOffIcon, {})
|
|
3305
3568
|
}
|
|
3306
3569
|
),
|
|
3307
|
-
/* @__PURE__ */ jsx6(
|
|
3570
|
+
/* @__PURE__ */ jsx6(AudioSettingsControl, {}),
|
|
3571
|
+
live.cameraLocked ? null : /* @__PURE__ */ jsx6(
|
|
3308
3572
|
ControlButton,
|
|
3309
3573
|
{
|
|
3310
3574
|
label: room.local?.cameraEnabled === true ? "Stop video (\u2318E)" : "Start video (\u2318E)",
|
|
@@ -3313,6 +3577,7 @@ function ControlBar({ onLeave }) {
|
|
|
3313
3577
|
children: room.local?.cameraEnabled === true ? /* @__PURE__ */ jsx6(CameraIcon, {}) : /* @__PURE__ */ jsx6(CameraOffIcon, {})
|
|
3314
3578
|
}
|
|
3315
3579
|
),
|
|
3580
|
+
/* @__PURE__ */ jsx6(CaptionsControl, {}),
|
|
3316
3581
|
room.canShareScreen || room.local?.screenSharing === true ? /* @__PURE__ */ jsx6(
|
|
3317
3582
|
ControlButton,
|
|
3318
3583
|
{
|
|
@@ -3322,7 +3587,7 @@ function ControlBar({ onLeave }) {
|
|
|
3322
3587
|
children: /* @__PURE__ */ jsx6(ScreenShareIcon, {})
|
|
3323
3588
|
}
|
|
3324
3589
|
) : null,
|
|
3325
|
-
/* @__PURE__ */
|
|
3590
|
+
/* @__PURE__ */ jsxs4("span", { className: "mx-meet__anchor", children: [
|
|
3326
3591
|
/* @__PURE__ */ jsx6(
|
|
3327
3592
|
ControlButton,
|
|
3328
3593
|
{
|
|
@@ -3354,11 +3619,11 @@ function ControlBar({ onLeave }) {
|
|
|
3354
3619
|
}
|
|
3355
3620
|
),
|
|
3356
3621
|
app !== null ? /* @__PURE__ */ jsx6(ControlButton, { label: app.title, active: panel === "app", onClick: () => toggle("app"), children: /* @__PURE__ */ jsx6(FlagIcon, {}) }) : null,
|
|
3357
|
-
/* @__PURE__ */
|
|
3622
|
+
/* @__PURE__ */ jsxs4(ControlButton, { label: "Chat (\u2318\u2325C)", active: panel === "chat", onClick: () => toggle("chat"), children: [
|
|
3358
3623
|
/* @__PURE__ */ jsx6(ChatIcon, {}),
|
|
3359
3624
|
unread > 0 ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__dot", "aria-hidden": "true" }) : null
|
|
3360
3625
|
] }),
|
|
3361
|
-
/* @__PURE__ */
|
|
3626
|
+
/* @__PURE__ */ jsxs4(
|
|
3362
3627
|
ControlButton,
|
|
3363
3628
|
{
|
|
3364
3629
|
label: lobby.waiting.length > 0 ? `People \u2014 ${lobby.waiting.length} waiting` : `People \u2014 ${(snapshot?.participants ?? []).length} in the meeting`,
|
|
@@ -3377,10 +3642,11 @@ function ControlBar({ onLeave }) {
|
|
|
3377
3642
|
onOpen: openActivity
|
|
3378
3643
|
}
|
|
3379
3644
|
),
|
|
3645
|
+
/* @__PURE__ */ jsx6(TakeNotesControl, {}),
|
|
3380
3646
|
/* @__PURE__ */ jsx6(AiControl, { active: panel === "ai", onToggle: () => toggle("ai") }),
|
|
3381
3647
|
recording.canStart ? /* @__PURE__ */ jsx6(ControlButton, { label: "Start recording", onClick: () => void recording.start(), children: /* @__PURE__ */ jsx6(RecordIcon, {}) }) : null,
|
|
3382
3648
|
recording.canStop ? /* @__PURE__ */ jsx6(ControlButton, { label: "Stop recording", active: true, onClick: () => void recording.stop(), children: /* @__PURE__ */ jsx6(RecordIcon, {}) }) : null,
|
|
3383
|
-
/* @__PURE__ */
|
|
3649
|
+
/* @__PURE__ */ jsxs4("span", { className: "mx-meet__anchor", children: [
|
|
3384
3650
|
/* @__PURE__ */ jsx6(
|
|
3385
3651
|
ControlButton,
|
|
3386
3652
|
{
|
|
@@ -3390,8 +3656,8 @@ function ControlBar({ onLeave }) {
|
|
|
3390
3656
|
children: /* @__PURE__ */ jsx6(MoreIcon, {})
|
|
3391
3657
|
}
|
|
3392
3658
|
),
|
|
3393
|
-
popover === "more" ? /* @__PURE__ */ jsx6(Popover, { label: "More options", onClose: () => setPopover("none"), children: /* @__PURE__ */
|
|
3394
|
-
/* @__PURE__ */
|
|
3659
|
+
popover === "more" ? /* @__PURE__ */ jsx6(Popover, { label: "More options", onClose: () => setPopover("none"), children: /* @__PURE__ */ jsxs4("div", { className: "mx-meet__menu", role: "menu", children: [
|
|
3660
|
+
/* @__PURE__ */ jsxs4(
|
|
3395
3661
|
MenuItem,
|
|
3396
3662
|
{
|
|
3397
3663
|
onSelect: () => {
|
|
@@ -3404,7 +3670,7 @@ function ControlBar({ onLeave }) {
|
|
|
3404
3670
|
]
|
|
3405
3671
|
}
|
|
3406
3672
|
),
|
|
3407
|
-
/* @__PURE__ */
|
|
3673
|
+
/* @__PURE__ */ jsxs4(
|
|
3408
3674
|
MenuItem,
|
|
3409
3675
|
{
|
|
3410
3676
|
onSelect: () => {
|
|
@@ -3417,9 +3683,16 @@ function ControlBar({ onLeave }) {
|
|
|
3417
3683
|
]
|
|
3418
3684
|
}
|
|
3419
3685
|
),
|
|
3420
|
-
|
|
3686
|
+
!room.canShareScreen && room.local?.screenSharing !== true ? (
|
|
3687
|
+
// `share-unsupported-mobile`: the control is absent; the menu says where it lives.
|
|
3688
|
+
/* @__PURE__ */ jsxs4("p", { className: "mx-meet__menu-note", role: "note", "data-meet-notice": "share-unsupported", children: [
|
|
3689
|
+
/* @__PURE__ */ jsx6(ScreenShareIcon, { width: 16, height: 16 }),
|
|
3690
|
+
" Present from a computer"
|
|
3691
|
+
] })
|
|
3692
|
+
) : null,
|
|
3693
|
+
controls.isHost ? /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
3421
3694
|
/* @__PURE__ */ jsx6("div", { className: "mx-meet__menu-sep", role: "separator" }),
|
|
3422
|
-
/* @__PURE__ */
|
|
3695
|
+
/* @__PURE__ */ jsxs4(
|
|
3423
3696
|
MenuItem,
|
|
3424
3697
|
{
|
|
3425
3698
|
onSelect: () => {
|
|
@@ -3432,7 +3705,24 @@ function ControlBar({ onLeave }) {
|
|
|
3432
3705
|
]
|
|
3433
3706
|
}
|
|
3434
3707
|
),
|
|
3435
|
-
/* @__PURE__ */
|
|
3708
|
+
/* @__PURE__ */ jsxs4(
|
|
3709
|
+
MenuItem,
|
|
3710
|
+
{
|
|
3711
|
+
onSelect: () => {
|
|
3712
|
+
setPopover("none");
|
|
3713
|
+
void controls.run({
|
|
3714
|
+
action: "set_av_lock",
|
|
3715
|
+
value: snapshot?.livePolicy.avLock === "both" ? "off" : "both"
|
|
3716
|
+
});
|
|
3717
|
+
},
|
|
3718
|
+
children: [
|
|
3719
|
+
/* @__PURE__ */ jsx6(MicOffIcon, { width: 16, height: 16 }),
|
|
3720
|
+
" ",
|
|
3721
|
+
snapshot?.livePolicy.avLock === "both" ? "Turn on attendees' microphone and camera" : "Turn off attendees' microphone and camera"
|
|
3722
|
+
]
|
|
3723
|
+
}
|
|
3724
|
+
),
|
|
3725
|
+
/* @__PURE__ */ jsxs4(
|
|
3436
3726
|
MenuItem,
|
|
3437
3727
|
{
|
|
3438
3728
|
onSelect: () => {
|
|
@@ -3445,7 +3735,7 @@ function ControlBar({ onLeave }) {
|
|
|
3445
3735
|
]
|
|
3446
3736
|
}
|
|
3447
3737
|
),
|
|
3448
|
-
queue.length > 0 ? /* @__PURE__ */
|
|
3738
|
+
queue.length > 0 ? /* @__PURE__ */ jsxs4(
|
|
3449
3739
|
MenuItem,
|
|
3450
3740
|
{
|
|
3451
3741
|
onSelect: () => {
|
|
@@ -3460,7 +3750,7 @@ function ControlBar({ onLeave }) {
|
|
|
3460
3750
|
]
|
|
3461
3751
|
}
|
|
3462
3752
|
) : null,
|
|
3463
|
-
hasSpotlight ? /* @__PURE__ */
|
|
3753
|
+
hasSpotlight ? /* @__PURE__ */ jsxs4(
|
|
3464
3754
|
MenuItem,
|
|
3465
3755
|
{
|
|
3466
3756
|
onSelect: () => {
|
|
@@ -3487,8 +3777,8 @@ var LEAVE_WORDS = {
|
|
|
3487
3777
|
};
|
|
3488
3778
|
function LeaveControl({ onLeave }) {
|
|
3489
3779
|
const leave = useLeave();
|
|
3490
|
-
const [open, setOpen] =
|
|
3491
|
-
const [failure, setFailure] =
|
|
3780
|
+
const [open, setOpen] = useState5("none");
|
|
3781
|
+
const [failure, setFailure] = useState5(null);
|
|
3492
3782
|
const words = LEAVE_WORDS[leave.policy.hostLeavePrompt];
|
|
3493
3783
|
const run = (work, leaving) => {
|
|
3494
3784
|
setFailure(null);
|
|
@@ -3499,7 +3789,7 @@ function LeaveControl({ onLeave }) {
|
|
|
3499
3789
|
};
|
|
3500
3790
|
const leaveNow = () => run(leave.leave, true);
|
|
3501
3791
|
const endNow = () => run(leave.endForAll, false);
|
|
3502
|
-
return /* @__PURE__ */
|
|
3792
|
+
return /* @__PURE__ */ jsxs4("span", { className: "mx-meet__anchor", children: [
|
|
3503
3793
|
/* @__PURE__ */ jsx6(
|
|
3504
3794
|
ControlButton,
|
|
3505
3795
|
{
|
|
@@ -3513,7 +3803,7 @@ function LeaveControl({ onLeave }) {
|
|
|
3513
3803
|
children: /* @__PURE__ */ jsx6(PhoneOffIcon, {})
|
|
3514
3804
|
}
|
|
3515
3805
|
),
|
|
3516
|
-
open !== "none" ? /* @__PURE__ */ jsx6(Popover, { label: open === "assign" ? words.assign_and_leave : "Leave", onClose: () => setOpen("none"), children: /* @__PURE__ */
|
|
3806
|
+
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: [
|
|
3517
3807
|
open === "menu" ? leave.choices.map((choice) => /* @__PURE__ */ jsx6(
|
|
3518
3808
|
"button",
|
|
3519
3809
|
{
|
|
@@ -3539,7 +3829,7 @@ function LeaveControl({ onLeave }) {
|
|
|
3539
3829
|
},
|
|
3540
3830
|
String(person.identity)
|
|
3541
3831
|
)) : null,
|
|
3542
|
-
open === "confirm" ? /* @__PURE__ */
|
|
3832
|
+
open === "confirm" ? /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
3543
3833
|
/* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__menu-item mx-meet__menu-item--danger", onClick: endNow, children: words.end_for_all }),
|
|
3544
3834
|
/* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__menu-item", onClick: () => setOpen("menu"), children: "Cancel" })
|
|
3545
3835
|
] }) : null,
|
|
@@ -3560,12 +3850,12 @@ function useUnreadChat(open) {
|
|
|
3560
3850
|
const snapshot = useMeetSnapshot();
|
|
3561
3851
|
const chat = snapshot?.chat ?? [];
|
|
3562
3852
|
const local = snapshot?.localIdentity ?? null;
|
|
3563
|
-
const [seen, setSeen] =
|
|
3853
|
+
const [seen, setSeen] = useState5(0);
|
|
3564
3854
|
useEffect6(() => {
|
|
3565
3855
|
if (open) setSeen(chat.length);
|
|
3566
3856
|
}, [open, chat.length]);
|
|
3567
3857
|
const loaded = snapshot?.chatLoaded === true;
|
|
3568
|
-
const [baseline, setBaseline] =
|
|
3858
|
+
const [baseline, setBaseline] = useState5(null);
|
|
3569
3859
|
useEffect6(() => {
|
|
3570
3860
|
if (loaded && baseline === null) setBaseline(chat.length);
|
|
3571
3861
|
}, [loaded, baseline, chat.length]);
|
|
@@ -3580,7 +3870,7 @@ function Popover({
|
|
|
3580
3870
|
placement = "up"
|
|
3581
3871
|
}) {
|
|
3582
3872
|
const ref = useRef6(null);
|
|
3583
|
-
const [style, setStyle] =
|
|
3873
|
+
const [style, setStyle] = useState5({
|
|
3584
3874
|
position: "fixed",
|
|
3585
3875
|
top: 0,
|
|
3586
3876
|
left: 0,
|
|
@@ -3669,15 +3959,103 @@ function Toast({ text, failed, onDone }) {
|
|
|
3669
3959
|
const timer = setTimeout(onDone, failed ? 7e3 : 4e3);
|
|
3670
3960
|
return () => clearTimeout(timer);
|
|
3671
3961
|
}, [text, failed, onDone]);
|
|
3672
|
-
return /* @__PURE__ */
|
|
3962
|
+
return /* @__PURE__ */ jsxs4("div", { className: failed ? "mx-meet__toast mx-meet__toast--failed" : "mx-meet__toast", role: "status", children: [
|
|
3673
3963
|
/* @__PURE__ */ jsx6("span", { children: text }),
|
|
3674
3964
|
/* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__toast-close", "aria-label": "Dismiss", onClick: onDone, children: /* @__PURE__ */ jsx6(CloseIcon, { width: 14, height: 14 }) })
|
|
3675
3965
|
] });
|
|
3676
3966
|
}
|
|
3967
|
+
function AudioSettingsControl() {
|
|
3968
|
+
const host = useMeetHost();
|
|
3969
|
+
const devices = useDeviceSnapshot();
|
|
3970
|
+
const [open, setOpen] = useState5(false);
|
|
3971
|
+
const list = (devices?.devices.audioinput ?? []).filter((device) => device.deviceId.length > 0);
|
|
3972
|
+
if (host === null || list.length < 2) return null;
|
|
3973
|
+
const current = devices?.selected.audioinput ?? host.devices.resolve("audioinput");
|
|
3974
|
+
return /* @__PURE__ */ jsxs4("span", { className: "mx-meet__anchor", children: [
|
|
3975
|
+
/* @__PURE__ */ jsx6(
|
|
3976
|
+
ControlButton,
|
|
3977
|
+
{
|
|
3978
|
+
label: "Audio settings",
|
|
3979
|
+
active: open,
|
|
3980
|
+
onClick: () => {
|
|
3981
|
+
if (!open) void host.devices.refresh();
|
|
3982
|
+
setOpen(!open);
|
|
3983
|
+
},
|
|
3984
|
+
children: /* @__PURE__ */ jsx6(ChevronUpIcon, {})
|
|
3985
|
+
}
|
|
3986
|
+
),
|
|
3987
|
+
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(
|
|
3988
|
+
"button",
|
|
3989
|
+
{
|
|
3990
|
+
type: "button",
|
|
3991
|
+
role: "menuitemradio",
|
|
3992
|
+
"aria-checked": device.deviceId === current,
|
|
3993
|
+
className: "mx-meet__menu-item",
|
|
3994
|
+
onClick: () => {
|
|
3995
|
+
setOpen(false);
|
|
3996
|
+
host.devices.select("audioinput", device.deviceId);
|
|
3997
|
+
void host.engine.switchDevice("audioinput", device.deviceId).catch(() => void 0);
|
|
3998
|
+
},
|
|
3999
|
+
children: [
|
|
4000
|
+
device.deviceId === current ? /* @__PURE__ */ jsx6(CheckIcon, { width: 16, height: 16 }) : /* @__PURE__ */ jsx6("span", { className: "mx-meet__menu-gap" }),
|
|
4001
|
+
device.label.length > 0 ? device.label : "Microphone"
|
|
4002
|
+
]
|
|
4003
|
+
},
|
|
4004
|
+
device.deviceId
|
|
4005
|
+
)) }) }) : null
|
|
4006
|
+
] });
|
|
4007
|
+
}
|
|
4008
|
+
function SpeakingWhileMutedNudge() {
|
|
4009
|
+
const room = useRoom();
|
|
4010
|
+
const host = useMeetHost();
|
|
4011
|
+
const devices = useDeviceSnapshot();
|
|
4012
|
+
const microphone = useLocalMedia().microphone;
|
|
4013
|
+
const mutedByMe = host !== null && room.local != null && room.local.micEnabled !== true && microphone.unavailable === null;
|
|
4014
|
+
const mic = devices?.selected.audioinput ?? host?.devices.resolve("audioinput") ?? null;
|
|
4015
|
+
const stream = useMicrophoneStream(mutedByMe ? mic : "off");
|
|
4016
|
+
const level = useAudioLevel(stream);
|
|
4017
|
+
const latest = useRef6(0);
|
|
4018
|
+
latest.current = level;
|
|
4019
|
+
const [shown, setShown] = useState5(false);
|
|
4020
|
+
const [detector] = useState5(() => createSpeakingWhileMutedDetector());
|
|
4021
|
+
useEffect6(() => {
|
|
4022
|
+
if (!mutedByMe) {
|
|
4023
|
+
detector.reset();
|
|
4024
|
+
setShown(false);
|
|
4025
|
+
return void 0;
|
|
4026
|
+
}
|
|
4027
|
+
const timer = setInterval(() => {
|
|
4028
|
+
if (detector.feed(latest.current, Date.now())) setShown(true);
|
|
4029
|
+
}, 150);
|
|
4030
|
+
return () => clearInterval(timer);
|
|
4031
|
+
}, [mutedByMe, detector]);
|
|
4032
|
+
useEffect6(() => {
|
|
4033
|
+
if (!shown) return void 0;
|
|
4034
|
+
const timer = setTimeout(() => setShown(false), 8e3);
|
|
4035
|
+
return () => clearTimeout(timer);
|
|
4036
|
+
}, [shown]);
|
|
4037
|
+
if (!shown || !mutedByMe) return null;
|
|
4038
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__notice-bar", role: "status", "data-meet-notice": "speaking-while-muted", children: [
|
|
4039
|
+
/* @__PURE__ */ jsx6(MicOffIcon, { width: 16, height: 16 }),
|
|
4040
|
+
/* @__PURE__ */ jsx6("span", { children: "You're muted" }),
|
|
4041
|
+
/* @__PURE__ */ jsx6(
|
|
4042
|
+
"button",
|
|
4043
|
+
{
|
|
4044
|
+
type: "button",
|
|
4045
|
+
className: "mx-meet__primary mx-meet__primary--small",
|
|
4046
|
+
onClick: () => {
|
|
4047
|
+
setShown(false);
|
|
4048
|
+
void room.toggleMicrophone();
|
|
4049
|
+
},
|
|
4050
|
+
children: "Unmute"
|
|
4051
|
+
}
|
|
4052
|
+
)
|
|
4053
|
+
] });
|
|
4054
|
+
}
|
|
3677
4055
|
function MediaNotices() {
|
|
3678
4056
|
const media = useLocalMedia();
|
|
3679
4057
|
const { region, where, enableAudio, acceptOffer, dismissOffer, dismissNotice, retry } = useMediaSupervisor();
|
|
3680
|
-
const [fixing, setFixing] =
|
|
4058
|
+
const [fixing, setFixing] = useState5(null);
|
|
3681
4059
|
const chips = ["microphone", "camera"].flatMap((kind) => {
|
|
3682
4060
|
const reason = deviceUnavailableReason(media[kind], region.permission[kind]);
|
|
3683
4061
|
return reason === null ? [] : [{ kind, reason }];
|
|
@@ -3687,8 +4065,8 @@ function MediaNotices() {
|
|
|
3687
4065
|
const offer = region.offer;
|
|
3688
4066
|
const name = (kind) => kind === "microphone" ? "Microphone" : "Camera";
|
|
3689
4067
|
if (chips.length === 0 && region.audioOutput !== "blocked" && notice === null && offer === null) return null;
|
|
3690
|
-
return /* @__PURE__ */
|
|
3691
|
-
region.audioOutput === "blocked" ? /* @__PURE__ */
|
|
4068
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__media-notices", children: [
|
|
4069
|
+
region.audioOutput === "blocked" ? /* @__PURE__ */ jsxs4(
|
|
3692
4070
|
ErrorBox,
|
|
3693
4071
|
{
|
|
3694
4072
|
as: "div",
|
|
@@ -3703,7 +4081,7 @@ function MediaNotices() {
|
|
|
3703
4081
|
]
|
|
3704
4082
|
}
|
|
3705
4083
|
) : null,
|
|
3706
|
-
chips.map(({ kind, reason }) => /* @__PURE__ */
|
|
4084
|
+
chips.map(({ kind, reason }) => /* @__PURE__ */ jsxs4("div", { className: "mx-meet__media-pill", role: "status", "data-meet-notice": deviceNoticeCode(kind, reason), children: [
|
|
3707
4085
|
/* @__PURE__ */ jsx6("span", { children: deviceChipLabel(kind, reason) }),
|
|
3708
4086
|
/* @__PURE__ */ jsx6(
|
|
3709
4087
|
"button",
|
|
@@ -3717,9 +4095,9 @@ function MediaNotices() {
|
|
|
3717
4095
|
}
|
|
3718
4096
|
)
|
|
3719
4097
|
] }, kind)),
|
|
3720
|
-
fixing !== null && fixReason !== null ? /* @__PURE__ */
|
|
4098
|
+
fixing !== null && fixReason !== null ? /* @__PURE__ */ jsxs4("div", { className: "mx-meet__popover mx-meet__fix-sheet", role: "dialog", "aria-label": `Fix ${name(fixing).toLowerCase()}`, children: [
|
|
3721
4099
|
/* @__PURE__ */ jsx6("ol", { className: "mx-meet__fix-steps", children: deviceFixSteps(fixing, fixReason, where).map((step) => /* @__PURE__ */ jsx6("li", { children: step }, step)) }),
|
|
3722
|
-
/* @__PURE__ */
|
|
4100
|
+
/* @__PURE__ */ jsxs4("div", { className: "mx-meet__fix-actions", children: [
|
|
3723
4101
|
/* @__PURE__ */ jsx6(
|
|
3724
4102
|
"button",
|
|
3725
4103
|
{
|
|
@@ -3736,7 +4114,7 @@ function MediaNotices() {
|
|
|
3736
4114
|
/* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__toast-close", "aria-label": "Close", onClick: () => setFixing(null), children: /* @__PURE__ */ jsx6(CloseIcon, { width: 14, height: 14 }) })
|
|
3737
4115
|
] })
|
|
3738
4116
|
] }) : null,
|
|
3739
|
-
notice !== null ? /* @__PURE__ */
|
|
4117
|
+
notice !== null ? /* @__PURE__ */ jsxs4(
|
|
3740
4118
|
"div",
|
|
3741
4119
|
{
|
|
3742
4120
|
className: "mx-meet__media-pill",
|
|
@@ -3748,7 +4126,7 @@ function MediaNotices() {
|
|
|
3748
4126
|
]
|
|
3749
4127
|
}
|
|
3750
4128
|
) : null,
|
|
3751
|
-
offer !== null ? /* @__PURE__ */
|
|
4129
|
+
offer !== null ? /* @__PURE__ */ jsxs4("div", { className: "mx-meet__media-pill", role: "status", children: [
|
|
3752
4130
|
/* @__PURE__ */ jsx6("span", { children: `New ${offer.kind}: ${offer.label || name(offer.kind)}` }),
|
|
3753
4131
|
/* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__primary mx-meet__primary--small", onClick: () => void acceptOffer(), children: "Use it" }),
|
|
3754
4132
|
/* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__toast-close", "aria-label": "Dismiss", onClick: dismissOffer, children: /* @__PURE__ */ jsx6(CloseIcon, { width: 14, height: 14 }) })
|
|
@@ -3759,14 +4137,50 @@ function MeetingOverlays() {
|
|
|
3759
4137
|
const reactions = useReactions();
|
|
3760
4138
|
const { notice, dismiss } = useModerationNotice();
|
|
3761
4139
|
const room = useRoom();
|
|
3762
|
-
|
|
4140
|
+
const live = useLivePolicy();
|
|
4141
|
+
const snapshot = useMeetSnapshot();
|
|
4142
|
+
const controls = useHostControls();
|
|
4143
|
+
const isHostNow = useRole() === "host";
|
|
4144
|
+
return /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
3763
4145
|
/* @__PURE__ */ jsx6(ReactionOverlay, { reactions }),
|
|
3764
4146
|
/* @__PURE__ */ jsx6(MediaNotices, {}),
|
|
4147
|
+
snapshot !== null && snapshot.phase === "in_call" && snapshot.participants.length >= 2 && !snapshot.participants.some((p) => p.role === "host" || p.role === "cohost") ? (
|
|
4148
|
+
// meeting-without-host: the call goes on; host-only controls are simply not on screen.
|
|
4149
|
+
/* @__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." })
|
|
4150
|
+
) : null,
|
|
4151
|
+
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: [
|
|
4152
|
+
/* @__PURE__ */ jsx6("h2", { className: "mx-meet__panel-title", children: "This meeting is being recorded" }),
|
|
4153
|
+
/* @__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." }),
|
|
4154
|
+
/* @__PURE__ */ jsxs4("div", { className: "mx-meet__menu-actions", children: [
|
|
4155
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__send", onClick: live.agree, children: live.consent === "ok_or_leave" ? "OK" : "I agree" }),
|
|
4156
|
+
live.consent === "ok_or_leave" ? /* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__link", onClick: () => void room.leave(), children: "Leave meeting" }) : null
|
|
4157
|
+
] })
|
|
4158
|
+
] }) }) : null,
|
|
4159
|
+
snapshot?.canReclaim === true && !isHostNow ? /* @__PURE__ */ jsxs4("div", { className: "mx-meet__notice-bar", role: "status", "data-meet-notice": "host-reclaim", children: [
|
|
4160
|
+
/* @__PURE__ */ jsx6("span", { children: "You started this meeting. Take back the host?" }),
|
|
4161
|
+
/* @__PURE__ */ jsx6(
|
|
4162
|
+
"button",
|
|
4163
|
+
{
|
|
4164
|
+
type: "button",
|
|
4165
|
+
className: "mx-meet__primary mx-meet__primary--small",
|
|
4166
|
+
onClick: () => void controls.run({ action: "reclaim_host" }),
|
|
4167
|
+
children: "Reclaim host"
|
|
4168
|
+
}
|
|
4169
|
+
)
|
|
4170
|
+
] }) : null,
|
|
4171
|
+
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,
|
|
4172
|
+
live.timeWarning && live.minutesLeft !== null && live.minutesLeft > 0 ? /* @__PURE__ */ jsxs4("p", { className: "mx-meet__banner", role: "status", "data-meet-notice": "time-warning", children: [
|
|
4173
|
+
"This meeting will end in ",
|
|
4174
|
+
live.minutesLeft,
|
|
4175
|
+
" ",
|
|
4176
|
+
live.minutesLeft === 1 ? "minute" : "minutes",
|
|
4177
|
+
" (time limit)."
|
|
4178
|
+
] }) : null,
|
|
3765
4179
|
notice !== null && notice.kind !== "removed" ? (
|
|
3766
4180
|
// A host's request ("the host is asking you to unmute"), not an error:
|
|
3767
4181
|
// an assertive status, so it is announced at once without being filed
|
|
3768
4182
|
// as a failure (design-system error-box census).
|
|
3769
|
-
/* @__PURE__ */
|
|
4183
|
+
/* @__PURE__ */ jsxs4("div", { className: "mx-meet__notice-bar", role: "status", "aria-live": "assertive", children: [
|
|
3770
4184
|
/* @__PURE__ */ jsx6("span", { children: notice.text }),
|
|
3771
4185
|
notice.kind === "ask-unmute" && room.local?.micEnabled !== true ? /* @__PURE__ */ jsx6(
|
|
3772
4186
|
"button",
|
|
@@ -3793,7 +4207,7 @@ function ShortcutsSheet({ onClose }) {
|
|
|
3793
4207
|
window.addEventListener("keydown", onKey);
|
|
3794
4208
|
return () => window.removeEventListener("keydown", onKey);
|
|
3795
4209
|
}, [onClose]);
|
|
3796
|
-
return /* @__PURE__ */ jsx6("div", { className: "mx-meet__sheet-backdrop", onClick: onClose, children: /* @__PURE__ */
|
|
4210
|
+
return /* @__PURE__ */ jsx6("div", { className: "mx-meet__sheet-backdrop", onClick: onClose, children: /* @__PURE__ */ jsxs4(
|
|
3797
4211
|
"div",
|
|
3798
4212
|
{
|
|
3799
4213
|
className: "mx-meet__sheet",
|
|
@@ -3801,11 +4215,11 @@ function ShortcutsSheet({ onClose }) {
|
|
|
3801
4215
|
"aria-label": "Keyboard shortcuts",
|
|
3802
4216
|
onClick: (event) => event.stopPropagation(),
|
|
3803
4217
|
children: [
|
|
3804
|
-
/* @__PURE__ */
|
|
4218
|
+
/* @__PURE__ */ jsxs4("header", { className: "mx-meet__panel-head", children: [
|
|
3805
4219
|
/* @__PURE__ */ jsx6("h2", { className: "mx-meet__panel-title", children: "Keyboard shortcuts" }),
|
|
3806
4220
|
/* @__PURE__ */ jsx6(ControlButton, { label: "Close", onClick: onClose, children: /* @__PURE__ */ jsx6(CloseIcon, { width: 16, height: 16 }) })
|
|
3807
4221
|
] }),
|
|
3808
|
-
/* @__PURE__ */ jsx6("dl", { className: "mx-meet__shortcuts", children: MEET_SHORTCUTS.map((shortcut) => /* @__PURE__ */
|
|
4222
|
+
/* @__PURE__ */ jsx6("dl", { className: "mx-meet__shortcuts", children: MEET_SHORTCUTS.map((shortcut) => /* @__PURE__ */ jsxs4("div", { className: "mx-meet__shortcut", children: [
|
|
3809
4223
|
/* @__PURE__ */ jsx6("dt", { children: shortcut.label }),
|
|
3810
4224
|
/* @__PURE__ */ jsx6("dd", { children: /* @__PURE__ */ jsx6("kbd", { className: "mx-meet__kbd", children: shortcut.keys }) })
|
|
3811
4225
|
] }, shortcut.id)) })
|
|
@@ -3837,8 +4251,8 @@ function PanelShell({
|
|
|
3837
4251
|
observer.observe(header);
|
|
3838
4252
|
return () => observer.disconnect();
|
|
3839
4253
|
}, []);
|
|
3840
|
-
return /* @__PURE__ */
|
|
3841
|
-
/* @__PURE__ */
|
|
4254
|
+
return /* @__PURE__ */ jsxs4("aside", { ref, className: "mx-meet__panel", "aria-label": title, children: [
|
|
4255
|
+
/* @__PURE__ */ jsxs4("header", { className: "mx-meet__panel-head", children: [
|
|
3842
4256
|
/* @__PURE__ */ jsx6("h2", { className: "mx-meet__panel-title", children: title }),
|
|
3843
4257
|
/* @__PURE__ */ jsx6(ControlButton, { label: "Close panel", onClick: onClose, children: /* @__PURE__ */ jsx6(CloseIcon, { width: 16, height: 16 }) })
|
|
3844
4258
|
] }),
|
|
@@ -3852,8 +4266,9 @@ function ChatPanel({
|
|
|
3852
4266
|
}) {
|
|
3853
4267
|
const snapshot = useMeetSnapshot();
|
|
3854
4268
|
const room = useRoom();
|
|
3855
|
-
const
|
|
3856
|
-
const [
|
|
4269
|
+
const live = useLivePolicy();
|
|
4270
|
+
const [draft, setDraft] = useState5("");
|
|
4271
|
+
const [recipient, setRecipient] = useState5(to);
|
|
3857
4272
|
const listRef = useRef6(null);
|
|
3858
4273
|
const messages = snapshot?.chat ?? [];
|
|
3859
4274
|
const local = snapshot?.localIdentity ?? null;
|
|
@@ -3870,13 +4285,13 @@ function ChatPanel({
|
|
|
3870
4285
|
setRecipient(next);
|
|
3871
4286
|
onTo?.(next);
|
|
3872
4287
|
};
|
|
3873
|
-
return /* @__PURE__ */
|
|
3874
|
-
/* @__PURE__ */
|
|
4288
|
+
return /* @__PURE__ */ jsxs4(PanelShell, { title: "Chat", onClose, children: [
|
|
4289
|
+
/* @__PURE__ */ jsxs4("ul", { className: "mx-meet__chat", ref: listRef, children: [
|
|
3875
4290
|
snapshot?.chatHistoryError != null ? /* @__PURE__ */ jsx6("li", { className: "mx-meet__panel-note", children: snapshot.chatHistoryError }) : null,
|
|
3876
4291
|
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,
|
|
3877
4292
|
messages.map((message) => /* @__PURE__ */ jsx6(ChatLine, { message, local, people }, message.id))
|
|
3878
4293
|
] }),
|
|
3879
|
-
/* @__PURE__ */
|
|
4294
|
+
!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(
|
|
3880
4295
|
"form",
|
|
3881
4296
|
{
|
|
3882
4297
|
className: "mx-meet__composer mx-meet__composer--chat",
|
|
@@ -3889,7 +4304,7 @@ function ChatPanel({
|
|
|
3889
4304
|
else void room.sendPrivateChat(recipient, text);
|
|
3890
4305
|
},
|
|
3891
4306
|
children: [
|
|
3892
|
-
people.length > 0 ? /* @__PURE__ */
|
|
4307
|
+
people.length > 0 ? /* @__PURE__ */ jsxs4(
|
|
3893
4308
|
"select",
|
|
3894
4309
|
{
|
|
3895
4310
|
className: "mx-meet__select mx-meet__select--compact",
|
|
@@ -3898,14 +4313,14 @@ function ChatPanel({
|
|
|
3898
4313
|
onChange: (event) => choose(event.target.value === "" ? null : event.target.value),
|
|
3899
4314
|
children: [
|
|
3900
4315
|
/* @__PURE__ */ jsx6("option", { value: "", children: "Everyone" }),
|
|
3901
|
-
people.map((participant) => /* @__PURE__ */
|
|
4316
|
+
people.map((participant) => /* @__PURE__ */ jsxs4("option", { value: participant.identity, children: [
|
|
3902
4317
|
participant.displayName,
|
|
3903
4318
|
" (private)"
|
|
3904
4319
|
] }, participant.identity))
|
|
3905
4320
|
]
|
|
3906
4321
|
}
|
|
3907
4322
|
) : null,
|
|
3908
|
-
/* @__PURE__ */
|
|
4323
|
+
/* @__PURE__ */ jsxs4("div", { className: "mx-meet__composer-row", children: [
|
|
3909
4324
|
/* @__PURE__ */ jsx6(
|
|
3910
4325
|
"input",
|
|
3911
4326
|
{
|
|
@@ -3919,7 +4334,7 @@ function ChatPanel({
|
|
|
3919
4334
|
),
|
|
3920
4335
|
/* @__PURE__ */ jsx6("button", { type: "submit", className: "mx-meet__send", disabled: draft.trim().length === 0, children: "Send" })
|
|
3921
4336
|
] }),
|
|
3922
|
-
recipientName !== null ? /* @__PURE__ */
|
|
4337
|
+
recipientName !== null ? /* @__PURE__ */ jsxs4("p", { className: "mx-meet__panel-note", children: [
|
|
3923
4338
|
"Only ",
|
|
3924
4339
|
recipientName,
|
|
3925
4340
|
" sees this. Private messages are not saved."
|
|
@@ -3937,7 +4352,7 @@ function ChatLine({
|
|
|
3937
4352
|
const mine = message.identity === local;
|
|
3938
4353
|
const privateTo = message.to ?? null;
|
|
3939
4354
|
const counterpart = privateTo === null ? null : mine ? people.find((p) => p.identity === privateTo)?.displayName ?? "them" : "you";
|
|
3940
|
-
return /* @__PURE__ */
|
|
4355
|
+
return /* @__PURE__ */ jsxs4(
|
|
3941
4356
|
"li",
|
|
3942
4357
|
{
|
|
3943
4358
|
className: [
|
|
@@ -3946,9 +4361,9 @@ function ChatLine({
|
|
|
3946
4361
|
message.failed !== void 0 ? "mx-meet__chat-line--failed" : ""
|
|
3947
4362
|
].filter(Boolean).join(" "),
|
|
3948
4363
|
children: [
|
|
3949
|
-
/* @__PURE__ */
|
|
4364
|
+
/* @__PURE__ */ jsxs4("span", { className: "mx-meet__chat-meta", children: [
|
|
3950
4365
|
/* @__PURE__ */ jsx6("strong", { children: mine ? "You" : message.displayName }),
|
|
3951
|
-
counterpart !== null ? /* @__PURE__ */
|
|
4366
|
+
counterpart !== null ? /* @__PURE__ */ jsxs4("span", { className: "mx-meet__chat-private", children: [
|
|
3952
4367
|
"to ",
|
|
3953
4368
|
counterpart,
|
|
3954
4369
|
" \xB7 private"
|
|
@@ -3968,8 +4383,8 @@ function PeoplePanel({
|
|
|
3968
4383
|
const snapshot = useMeetSnapshot();
|
|
3969
4384
|
const controls = useHostControls();
|
|
3970
4385
|
const queue = useHandQueue();
|
|
3971
|
-
const [query, setQuery] =
|
|
3972
|
-
const [menuFor, setMenuFor] =
|
|
4386
|
+
const [query, setQuery] = useState5("");
|
|
4387
|
+
const [menuFor, setMenuFor] = useState5(null);
|
|
3973
4388
|
const myRole = useRole();
|
|
3974
4389
|
const local = snapshot?.localIdentity ?? null;
|
|
3975
4390
|
const observersHidden = snapshot?.grants.observersVisibleTo === "hosts" && !controls.isHost;
|
|
@@ -3978,11 +4393,11 @@ function PeoplePanel({
|
|
|
3978
4393
|
);
|
|
3979
4394
|
const needle = query.trim().toLowerCase();
|
|
3980
4395
|
const shown = needle.length === 0 ? everyone : everyone.filter((participant) => participant.displayName.toLowerCase().includes(needle));
|
|
3981
|
-
return /* @__PURE__ */
|
|
4396
|
+
return /* @__PURE__ */ jsxs4(PanelShell, { title: `People (${everyone.length})`, onClose, children: [
|
|
3982
4397
|
/* @__PURE__ */ jsx6(LobbyPanel, {}),
|
|
3983
|
-
queue.length > 0 ? /* @__PURE__ */
|
|
3984
|
-
/* @__PURE__ */
|
|
3985
|
-
/* @__PURE__ */
|
|
4398
|
+
queue.length > 0 ? /* @__PURE__ */ jsxs4("section", { className: "mx-meet__section", "aria-label": "Raised hands", children: [
|
|
4399
|
+
/* @__PURE__ */ jsxs4("header", { className: "mx-meet__section-head", children: [
|
|
4400
|
+
/* @__PURE__ */ jsxs4("h3", { className: "mx-meet__section-title", children: [
|
|
3986
4401
|
"Raised hands \xB7 ",
|
|
3987
4402
|
queue.length
|
|
3988
4403
|
] }),
|
|
@@ -3996,9 +4411,9 @@ function PeoplePanel({
|
|
|
3996
4411
|
}
|
|
3997
4412
|
) : null
|
|
3998
4413
|
] }),
|
|
3999
|
-
/* @__PURE__ */ jsx6("ol", { className: "mx-meet__queue", children: queue.map((participant) => /* @__PURE__ */
|
|
4414
|
+
/* @__PURE__ */ jsx6("ol", { className: "mx-meet__queue", children: queue.map((participant) => /* @__PURE__ */ jsxs4("li", { className: "mx-meet__person", children: [
|
|
4000
4415
|
/* @__PURE__ */ jsx6(Avatar, { name: participant.displayName, url: participant.avatarUrl, size: 28 }),
|
|
4001
|
-
/* @__PURE__ */
|
|
4416
|
+
/* @__PURE__ */ jsxs4("span", { className: "mx-meet__person-name", children: [
|
|
4002
4417
|
participant.displayName,
|
|
4003
4418
|
participant.identity === local ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__you", children: " (you)" }) : null
|
|
4004
4419
|
] }),
|
|
@@ -4013,12 +4428,12 @@ function PeoplePanel({
|
|
|
4013
4428
|
) : null
|
|
4014
4429
|
] }, participant.identity)) })
|
|
4015
4430
|
] }) : null,
|
|
4016
|
-
controls.isHost && everyone.length > 1 ? /* @__PURE__ */
|
|
4017
|
-
/* @__PURE__ */
|
|
4431
|
+
controls.isHost && everyone.length > 1 ? /* @__PURE__ */ jsxs4("div", { className: "mx-meet__bulk", children: [
|
|
4432
|
+
/* @__PURE__ */ jsxs4("button", { type: "button", className: "mx-meet__chip", onClick: () => void controls.run({ action: "mute_all" }), children: [
|
|
4018
4433
|
/* @__PURE__ */ jsx6(MicOffIcon, { width: 14, height: 14 }),
|
|
4019
4434
|
" Mute all"
|
|
4020
4435
|
] }),
|
|
4021
|
-
/* @__PURE__ */
|
|
4436
|
+
/* @__PURE__ */ jsxs4(
|
|
4022
4437
|
"button",
|
|
4023
4438
|
{
|
|
4024
4439
|
type: "button",
|
|
@@ -4031,7 +4446,7 @@ function PeoplePanel({
|
|
|
4031
4446
|
}
|
|
4032
4447
|
)
|
|
4033
4448
|
] }) : null,
|
|
4034
|
-
everyone.length > 4 ? /* @__PURE__ */
|
|
4449
|
+
everyone.length > 4 ? /* @__PURE__ */ jsxs4("label", { className: "mx-meet__search", children: [
|
|
4035
4450
|
/* @__PURE__ */ jsx6(SearchIcon, { width: 16, height: 16 }),
|
|
4036
4451
|
/* @__PURE__ */ jsx6(
|
|
4037
4452
|
"input",
|
|
@@ -4045,10 +4460,10 @@ function PeoplePanel({
|
|
|
4045
4460
|
)
|
|
4046
4461
|
] }) : null,
|
|
4047
4462
|
controls.notice !== null ? /* @__PURE__ */ jsx6("p", { className: controls.notice.failed ? "mx-meet__error" : "mx-meet__notice", role: "status", children: controls.notice.text }) : null,
|
|
4048
|
-
/* @__PURE__ */
|
|
4049
|
-
shown.map((participant) => /* @__PURE__ */
|
|
4463
|
+
/* @__PURE__ */ jsxs4("ul", { className: "mx-meet__people", children: [
|
|
4464
|
+
shown.map((participant) => /* @__PURE__ */ jsxs4("li", { className: "mx-meet__person", children: [
|
|
4050
4465
|
/* @__PURE__ */ jsx6(Avatar, { name: participant.displayName, url: participant.avatarUrl, size: 32 }),
|
|
4051
|
-
/* @__PURE__ */
|
|
4466
|
+
/* @__PURE__ */ jsxs4("span", { className: "mx-meet__person-name", children: [
|
|
4052
4467
|
participant.displayName,
|
|
4053
4468
|
participant.identity === local ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__you", children: " (you)" }) : null,
|
|
4054
4469
|
/* @__PURE__ */ jsx6(
|
|
@@ -4065,7 +4480,7 @@ function PeoplePanel({
|
|
|
4065
4480
|
participant.handRaised ? /* @__PURE__ */ jsx6(HandIcon, { width: 14, height: 14 }) : null,
|
|
4066
4481
|
!participant.micEnabled && !isNoteTaker(participant) ? /* @__PURE__ */ jsx6(MicOffIcon, { width: 14, height: 14 }) : null,
|
|
4067
4482
|
/* @__PURE__ */ jsx6(QualityBars, { quality: participant.quality }),
|
|
4068
|
-
/* @__PURE__ */
|
|
4483
|
+
/* @__PURE__ */ jsxs4("span", { className: "mx-meet__anchor", children: [
|
|
4069
4484
|
/* @__PURE__ */ jsx6(
|
|
4070
4485
|
ControlButton,
|
|
4071
4486
|
{
|
|
@@ -4086,7 +4501,7 @@ function PeoplePanel({
|
|
|
4086
4501
|
) : null
|
|
4087
4502
|
] })
|
|
4088
4503
|
] }, participant.identity)),
|
|
4089
|
-
shown.length === 0 ? /* @__PURE__ */
|
|
4504
|
+
shown.length === 0 ? /* @__PURE__ */ jsxs4("li", { className: "mx-meet__panel-note", children: [
|
|
4090
4505
|
"Nobody matches \u201C",
|
|
4091
4506
|
query,
|
|
4092
4507
|
"\u201D."
|
|
@@ -4104,14 +4519,14 @@ function PersonMenu({
|
|
|
4104
4519
|
const host = useMeetHost();
|
|
4105
4520
|
const snapshot = useMeetSnapshot();
|
|
4106
4521
|
const controls = useHostControls();
|
|
4107
|
-
const [mode, setMode] =
|
|
4108
|
-
const [text, setText] =
|
|
4522
|
+
const [mode, setMode] = useState5("menu");
|
|
4523
|
+
const [text, setText] = useState5("");
|
|
4109
4524
|
const self = participant.identity === snapshot?.localIdentity;
|
|
4110
4525
|
const moderate = controls.canModerate(participant);
|
|
4111
4526
|
const pinned = snapshot?.pinned === participant.identity;
|
|
4112
4527
|
const spotlit = snapshot?.spotlight === participant.identity;
|
|
4113
4528
|
const hasAccount = participant.userId !== null;
|
|
4114
|
-
const [refused, setRefused] =
|
|
4529
|
+
const [refused, setRefused] = useState5(false);
|
|
4115
4530
|
const act = (request) => {
|
|
4116
4531
|
setRefused(false);
|
|
4117
4532
|
void controls.run(request).then((result) => {
|
|
@@ -4122,7 +4537,7 @@ function PersonMenu({
|
|
|
4122
4537
|
const refusal = 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;
|
|
4123
4538
|
if (mode === "rename" || mode === "report") {
|
|
4124
4539
|
const renaming = mode === "rename";
|
|
4125
|
-
return /* @__PURE__ */ jsx6(Popover, { label: renaming ? "Rename" : "Report", onClose, placement, children: /* @__PURE__ */
|
|
4540
|
+
return /* @__PURE__ */ jsx6(Popover, { label: renaming ? "Rename" : "Report", onClose, placement, children: /* @__PURE__ */ jsxs4(
|
|
4126
4541
|
"form",
|
|
4127
4542
|
{
|
|
4128
4543
|
className: "mx-meet__menu-form",
|
|
@@ -4134,7 +4549,7 @@ function PersonMenu({
|
|
|
4134
4549
|
);
|
|
4135
4550
|
},
|
|
4136
4551
|
children: [
|
|
4137
|
-
/* @__PURE__ */
|
|
4552
|
+
/* @__PURE__ */ jsxs4("label", { className: "mx-meet__field", children: [
|
|
4138
4553
|
/* @__PURE__ */ jsx6("span", { className: "mx-meet__field-label", children: renaming ? "Name shown in this meeting" : `What did ${participant.displayName} do?` }),
|
|
4139
4554
|
renaming ? /* @__PURE__ */ jsx6(
|
|
4140
4555
|
"input",
|
|
@@ -4158,7 +4573,7 @@ function PersonMenu({
|
|
|
4158
4573
|
)
|
|
4159
4574
|
] }),
|
|
4160
4575
|
refusal,
|
|
4161
|
-
/* @__PURE__ */
|
|
4576
|
+
/* @__PURE__ */ jsxs4("div", { className: "mx-meet__menu-actions", children: [
|
|
4162
4577
|
/* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__link", onClick: () => setMode("menu"), children: "Back" }),
|
|
4163
4578
|
/* @__PURE__ */ jsx6("button", { type: "submit", className: "mx-meet__send", disabled: text.trim().length === 0 || controls.busy, children: renaming ? "Rename" : "Report" })
|
|
4164
4579
|
] })
|
|
@@ -4168,10 +4583,10 @@ function PersonMenu({
|
|
|
4168
4583
|
}
|
|
4169
4584
|
if (mode === "remove" || mode === "transfer") {
|
|
4170
4585
|
const removing = mode === "remove";
|
|
4171
|
-
return /* @__PURE__ */ jsx6(Popover, { label: removing ? "Remove" : "Make host", onClose, placement, children: /* @__PURE__ */
|
|
4586
|
+
return /* @__PURE__ */ jsx6(Popover, { label: removing ? "Remove" : "Make host", onClose, placement, children: /* @__PURE__ */ jsxs4("div", { className: "mx-meet__menu-form", children: [
|
|
4172
4587
|
/* @__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.` }),
|
|
4173
4588
|
refusal,
|
|
4174
|
-
/* @__PURE__ */
|
|
4589
|
+
/* @__PURE__ */ jsxs4("div", { className: "mx-meet__menu-actions", children: [
|
|
4175
4590
|
/* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__link", onClick: () => setMode("menu"), children: "Cancel" }),
|
|
4176
4591
|
/* @__PURE__ */ jsx6(
|
|
4177
4592
|
"button",
|
|
@@ -4186,8 +4601,8 @@ function PersonMenu({
|
|
|
4186
4601
|
] })
|
|
4187
4602
|
] }) });
|
|
4188
4603
|
}
|
|
4189
|
-
return /* @__PURE__ */ jsx6(Popover, { label: `Options for ${participant.displayName}`, onClose, placement, children: /* @__PURE__ */
|
|
4190
|
-
/* @__PURE__ */
|
|
4604
|
+
return /* @__PURE__ */ jsx6(Popover, { label: `Options for ${participant.displayName}`, onClose, placement, children: /* @__PURE__ */ jsxs4("div", { className: "mx-meet__menu", role: "menu", children: [
|
|
4605
|
+
/* @__PURE__ */ jsxs4(
|
|
4191
4606
|
MenuItem,
|
|
4192
4607
|
{
|
|
4193
4608
|
onSelect: () => {
|
|
@@ -4201,7 +4616,7 @@ function PersonMenu({
|
|
|
4201
4616
|
]
|
|
4202
4617
|
}
|
|
4203
4618
|
),
|
|
4204
|
-
!self && !participant.isAgent && (onMessage !== void 0 || host !== null) ? /* @__PURE__ */
|
|
4619
|
+
!self && !participant.isAgent && (onMessage !== void 0 || host !== null) ? /* @__PURE__ */ jsxs4(
|
|
4205
4620
|
MenuItem,
|
|
4206
4621
|
{
|
|
4207
4622
|
onSelect: () => {
|
|
@@ -4218,37 +4633,44 @@ function PersonMenu({
|
|
|
4218
4633
|
]
|
|
4219
4634
|
}
|
|
4220
4635
|
) : null,
|
|
4221
|
-
controls.isHost ? /* @__PURE__ */
|
|
4636
|
+
controls.isHost ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "spotlight", identity: spotlit ? null : participant.identity }), children: [
|
|
4222
4637
|
/* @__PURE__ */ jsx6(SpotlightIcon, { width: 16, height: 16 }),
|
|
4223
4638
|
" ",
|
|
4224
4639
|
spotlit ? "Remove spotlight" : "Spotlight for everyone"
|
|
4225
4640
|
] }) : null,
|
|
4226
|
-
moderate ? /* @__PURE__ */
|
|
4641
|
+
moderate ? /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
4227
4642
|
/* @__PURE__ */ jsx6("div", { className: "mx-meet__menu-sep", role: "separator" }),
|
|
4228
|
-
participant.micEnabled ? /* @__PURE__ */
|
|
4643
|
+
participant.micEnabled ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "mute", identity: participant.identity }), children: [
|
|
4229
4644
|
/* @__PURE__ */ jsx6(MicOffIcon, { width: 16, height: 16 }),
|
|
4230
4645
|
" Mute"
|
|
4231
|
-
] }) : !participant.isAgent ? /* @__PURE__ */
|
|
4646
|
+
] }) : !participant.isAgent ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "ask_unmute", identity: participant.identity }), children: [
|
|
4232
4647
|
/* @__PURE__ */ jsx6(MicIcon, { width: 16, height: 16 }),
|
|
4233
4648
|
" Ask to unmute"
|
|
4234
4649
|
] }) : null,
|
|
4235
|
-
participant.cameraEnabled ? /* @__PURE__ */
|
|
4650
|
+
participant.cameraEnabled ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "stop_video", identity: participant.identity }), children: [
|
|
4236
4651
|
/* @__PURE__ */ jsx6(CameraOffIcon, { width: 16, height: 16 }),
|
|
4237
4652
|
" Stop video"
|
|
4238
4653
|
] }) : null,
|
|
4239
|
-
participant.screenSharing ? /* @__PURE__ */
|
|
4654
|
+
participant.screenSharing ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "stop_screen", identity: participant.identity }), children: [
|
|
4240
4655
|
/* @__PURE__ */ jsx6(ScreenShareIcon, { width: 16, height: 16 }),
|
|
4241
4656
|
" Stop screen share"
|
|
4242
4657
|
] }) : null,
|
|
4243
|
-
participant.handRaised ? /* @__PURE__ */
|
|
4658
|
+
participant.handRaised ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "lower_hand", identity: participant.identity }), children: [
|
|
4244
4659
|
/* @__PURE__ */ jsx6(HandIcon, { width: 16, height: 16 }),
|
|
4245
4660
|
" Lower hand"
|
|
4246
4661
|
] }) : null,
|
|
4247
|
-
hasAccount && !participant.isAgent && participant.role !== "cohost" ? /* @__PURE__ */
|
|
4662
|
+
hasAccount && !participant.isAgent && participant.role !== "cohost" ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "make_cohost", identity: participant.identity }), children: [
|
|
4248
4663
|
/* @__PURE__ */ jsx6(PeopleIcon, { width: 16, height: 16 }),
|
|
4249
4664
|
" Make co-host"
|
|
4250
4665
|
] }) : null,
|
|
4251
|
-
!participant.isAgent ? /* @__PURE__ */
|
|
4666
|
+
!participant.isAgent && participant.role !== "cohost" && participant.role !== "host" ? participant.role === "presenter" ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "revoke_presenter", identity: participant.identity }), children: [
|
|
4667
|
+
/* @__PURE__ */ jsx6(ScreenShareIcon, { width: 16, height: 16 }),
|
|
4668
|
+
" Remove presenter"
|
|
4669
|
+
] }) : /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "make_presenter", identity: participant.identity }), children: [
|
|
4670
|
+
/* @__PURE__ */ jsx6(ScreenShareIcon, { width: 16, height: 16 }),
|
|
4671
|
+
" Make presenter"
|
|
4672
|
+
] }) : null,
|
|
4673
|
+
!participant.isAgent ? /* @__PURE__ */ jsxs4(
|
|
4252
4674
|
MenuItem,
|
|
4253
4675
|
{
|
|
4254
4676
|
onSelect: () => {
|
|
@@ -4262,15 +4684,15 @@ function PersonMenu({
|
|
|
4262
4684
|
}
|
|
4263
4685
|
) : null
|
|
4264
4686
|
] }) : null,
|
|
4265
|
-
controls.isOwner && participant.role === "cohost" ? /* @__PURE__ */
|
|
4687
|
+
controls.isOwner && participant.role === "cohost" ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => act({ action: "revoke_cohost", identity: participant.identity }), children: [
|
|
4266
4688
|
/* @__PURE__ */ jsx6(PeopleIcon, { width: 16, height: 16 }),
|
|
4267
4689
|
" Remove co-host"
|
|
4268
4690
|
] }) : null,
|
|
4269
|
-
controls.isOwner && !self && hasAccount && !participant.isAgent ? /* @__PURE__ */
|
|
4691
|
+
controls.isOwner && !self && hasAccount && !participant.isAgent ? /* @__PURE__ */ jsxs4(MenuItem, { onSelect: () => setMode("transfer"), children: [
|
|
4270
4692
|
/* @__PURE__ */ jsx6(SpotlightIcon, { width: 16, height: 16 }),
|
|
4271
4693
|
" Make host"
|
|
4272
4694
|
] }) : null,
|
|
4273
|
-
self ? /* @__PURE__ */
|
|
4695
|
+
self ? /* @__PURE__ */ jsxs4(
|
|
4274
4696
|
MenuItem,
|
|
4275
4697
|
{
|
|
4276
4698
|
onSelect: () => {
|
|
@@ -4283,7 +4705,7 @@ function PersonMenu({
|
|
|
4283
4705
|
]
|
|
4284
4706
|
}
|
|
4285
4707
|
) : null,
|
|
4286
|
-
!self && !participant.isAgent ? /* @__PURE__ */
|
|
4708
|
+
!self && !participant.isAgent ? /* @__PURE__ */ jsxs4(
|
|
4287
4709
|
MenuItem,
|
|
4288
4710
|
{
|
|
4289
4711
|
onSelect: () => {
|
|
@@ -4296,7 +4718,7 @@ function PersonMenu({
|
|
|
4296
4718
|
]
|
|
4297
4719
|
}
|
|
4298
4720
|
) : null,
|
|
4299
|
-
moderate && !participant.isAgent ? /* @__PURE__ */
|
|
4721
|
+
moderate && !participant.isAgent ? /* @__PURE__ */ jsxs4(MenuItem, { danger: true, onSelect: () => setMode("remove"), children: [
|
|
4300
4722
|
/* @__PURE__ */ jsx6(CloseIcon, { width: 16, height: 16 }),
|
|
4301
4723
|
" Remove from meeting"
|
|
4302
4724
|
] }) : null
|
|
@@ -4304,7 +4726,7 @@ function PersonMenu({
|
|
|
4304
4726
|
}
|
|
4305
4727
|
function SettingsPanel({ onClose }) {
|
|
4306
4728
|
const host = useRequiredMeetHost();
|
|
4307
|
-
return /* @__PURE__ */
|
|
4729
|
+
return /* @__PURE__ */ jsxs4(PanelShell, { title: "Settings", onClose, children: [
|
|
4308
4730
|
/* @__PURE__ */ jsx6(
|
|
4309
4731
|
DeviceSettings,
|
|
4310
4732
|
{
|
|
@@ -4327,15 +4749,15 @@ function DeviceSettings({
|
|
|
4327
4749
|
const speaker = devices?.selected.audiooutput ?? host.devices.resolve("audiooutput");
|
|
4328
4750
|
const stream = useMicrophoneStream(microphone);
|
|
4329
4751
|
const level = useAudioLevel(stream);
|
|
4330
|
-
const [testing, setTesting] =
|
|
4752
|
+
const [testing, setTesting] = useState5(false);
|
|
4331
4753
|
useEffect6(() => {
|
|
4332
4754
|
void host.devices.refresh();
|
|
4333
4755
|
}, [host]);
|
|
4334
|
-
return /* @__PURE__ */
|
|
4756
|
+
return /* @__PURE__ */ jsxs4("section", { className: "mx-meet__section", "aria-label": "Devices", children: [
|
|
4335
4757
|
/* @__PURE__ */ jsx6(DevicePicker, { kind: "audioinput", label: "Microphone", onPick }),
|
|
4336
4758
|
/* @__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))}%` } }) }),
|
|
4337
4759
|
/* @__PURE__ */ jsx6(DevicePicker, { kind: "audiooutput", label: "Speaker", onPick }),
|
|
4338
|
-
/* @__PURE__ */
|
|
4760
|
+
/* @__PURE__ */ jsxs4(
|
|
4339
4761
|
"button",
|
|
4340
4762
|
{
|
|
4341
4763
|
type: "button",
|
|
@@ -4357,7 +4779,7 @@ function DeviceSettings({
|
|
|
4357
4779
|
}
|
|
4358
4780
|
function EffectsSettings({ preview }) {
|
|
4359
4781
|
const effects = useMediaEffects();
|
|
4360
|
-
const [error, setError] =
|
|
4782
|
+
const [error, setError] = useState5(null);
|
|
4361
4783
|
const fileRef = useRef6(null);
|
|
4362
4784
|
const supported = effects.backgroundsSupported || preview != null || videoEffectsSupported();
|
|
4363
4785
|
const apply = (next) => {
|
|
@@ -4370,8 +4792,8 @@ function EffectsSettings({ preview }) {
|
|
|
4370
4792
|
);
|
|
4371
4793
|
}
|
|
4372
4794
|
};
|
|
4373
|
-
return /* @__PURE__ */
|
|
4374
|
-
/* @__PURE__ */
|
|
4795
|
+
return /* @__PURE__ */ jsxs4("section", { className: "mx-meet__section", "aria-label": "Effects", children: [
|
|
4796
|
+
/* @__PURE__ */ jsxs4("div", { className: "mx-meet__check", children: [
|
|
4375
4797
|
/* @__PURE__ */ jsx6(
|
|
4376
4798
|
Checkbox,
|
|
4377
4799
|
{
|
|
@@ -4380,12 +4802,12 @@ function EffectsSettings({ preview }) {
|
|
|
4380
4802
|
onCheckedChange: (checked) => apply({ noiseSuppression: checked === true })
|
|
4381
4803
|
}
|
|
4382
4804
|
),
|
|
4383
|
-
/* @__PURE__ */
|
|
4805
|
+
/* @__PURE__ */ jsxs4("div", { className: "mx-meet__check-text", children: [
|
|
4384
4806
|
/* @__PURE__ */ jsx6(Label, { htmlFor: "mx-meet-noise", children: "Noise suppression" }),
|
|
4385
4807
|
/* @__PURE__ */ jsx6("span", { className: "mx-meet__hint", children: "Filters keyboards, fans and background chatter." })
|
|
4386
4808
|
] })
|
|
4387
4809
|
] }),
|
|
4388
|
-
supported ? /* @__PURE__ */
|
|
4810
|
+
supported ? /* @__PURE__ */ jsxs4("div", { className: "mx-meet__field", children: [
|
|
4389
4811
|
/* @__PURE__ */ jsx6(Label, { children: "Background" }),
|
|
4390
4812
|
/* @__PURE__ */ jsx6(
|
|
4391
4813
|
SegmentedControl,
|
|
@@ -4479,14 +4901,20 @@ async function playTestSound(sinkId) {
|
|
|
4479
4901
|
audio.pause();
|
|
4480
4902
|
await context.close();
|
|
4481
4903
|
}
|
|
4482
|
-
function useMicrophoneStream(deviceId) {
|
|
4483
|
-
const [stream, setStream] =
|
|
4904
|
+
function useMicrophoneStream(deviceId, report, attempt = 0) {
|
|
4905
|
+
const [stream, setStream] = useState5(null);
|
|
4906
|
+
const reportRef = useRef6(report);
|
|
4907
|
+
reportRef.current = report;
|
|
4484
4908
|
useEffect6(() => {
|
|
4485
|
-
if (deviceId === "off")
|
|
4909
|
+
if (deviceId === "off") {
|
|
4910
|
+
reportRef.current?.("off");
|
|
4911
|
+
return void 0;
|
|
4912
|
+
}
|
|
4486
4913
|
let live = true;
|
|
4487
4914
|
let opened = null;
|
|
4488
4915
|
const media = globalThis.navigator?.mediaDevices;
|
|
4489
4916
|
if (media === void 0) return void 0;
|
|
4917
|
+
reportRef.current?.("prompting");
|
|
4490
4918
|
void media.getUserMedia({ audio: deviceId === null ? true : { deviceId: { exact: deviceId } } }).then((next) => {
|
|
4491
4919
|
if (!live) {
|
|
4492
4920
|
next.getTracks().forEach((track) => track.stop());
|
|
@@ -4494,20 +4922,54 @@ function useMicrophoneStream(deviceId) {
|
|
|
4494
4922
|
}
|
|
4495
4923
|
opened = next;
|
|
4496
4924
|
setStream(next);
|
|
4497
|
-
|
|
4925
|
+
reportRef.current?.("on");
|
|
4926
|
+
}).catch((thrown) => {
|
|
4927
|
+
setStream(null);
|
|
4928
|
+
if (live) reportRef.current?.({ error: thrown });
|
|
4929
|
+
});
|
|
4498
4930
|
return () => {
|
|
4499
4931
|
live = false;
|
|
4500
4932
|
opened?.getTracks().forEach((track) => track.stop());
|
|
4501
4933
|
setStream(null);
|
|
4502
4934
|
};
|
|
4503
|
-
}, [deviceId]);
|
|
4935
|
+
}, [deviceId, attempt]);
|
|
4504
4936
|
return stream;
|
|
4505
4937
|
}
|
|
4938
|
+
function PreviewStatus({ onRetry }) {
|
|
4939
|
+
const { region, where } = useMediaSupervisor();
|
|
4940
|
+
const [waited, setWaited] = useState5(false);
|
|
4941
|
+
const prompting = region.preview.microphone.state === "prompting" || region.preview.camera.state === "prompting";
|
|
4942
|
+
useEffect6(() => {
|
|
4943
|
+
if (!prompting) {
|
|
4944
|
+
setWaited(false);
|
|
4945
|
+
return void 0;
|
|
4946
|
+
}
|
|
4947
|
+
const timer = setTimeout(() => setWaited(true), 800);
|
|
4948
|
+
return () => clearTimeout(timer);
|
|
4949
|
+
}, [prompting]);
|
|
4950
|
+
const refused = ["microphone", "camera"].flatMap((kind) => {
|
|
4951
|
+
const preview = region.preview[kind];
|
|
4952
|
+
const reason = region.permission[kind] === "denied" ? "denied" : preview.state === "unavailable" ? preview.unavailable?.reason ?? "failed" : null;
|
|
4953
|
+
return reason === null ? [] : [{ kind, reason }];
|
|
4954
|
+
});
|
|
4955
|
+
if (refused.length === 0) {
|
|
4956
|
+
if (!prompting || !waited) return null;
|
|
4957
|
+
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" });
|
|
4958
|
+
}
|
|
4959
|
+
const first = refused[0];
|
|
4960
|
+
const both = refused.length === 2 && refused[0].reason === refused[1].reason;
|
|
4961
|
+
const label = both ? deviceChipLabel("camera", first.reason).replace(/^Camera/, "Camera and mic") : refused.map((r) => deviceChipLabel(r.kind, r.reason)).join(" \xB7 ");
|
|
4962
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__warning", role: "status", "data-meet-notice": deviceNoticeCode(first.kind, first.reason), children: [
|
|
4963
|
+
/* @__PURE__ */ jsx6("strong", { children: label }),
|
|
4964
|
+
/* @__PURE__ */ jsx6("ol", { className: "mx-meet__fix-steps", children: deviceFixSteps(first.kind, first.reason, where).map((step) => /* @__PURE__ */ jsx6("li", { children: step }, step)) }),
|
|
4965
|
+
/* @__PURE__ */ jsx6(Button, { type: "button", variant: "outline", size: "sm", onClick: onRetry, children: "Try again" })
|
|
4966
|
+
] });
|
|
4967
|
+
}
|
|
4506
4968
|
function KnockNotice({ onView }) {
|
|
4507
4969
|
const { knocker, others, admit, dismiss } = useKnockNotice();
|
|
4508
4970
|
if (knocker === null) return null;
|
|
4509
|
-
return /* @__PURE__ */
|
|
4510
|
-
/* @__PURE__ */
|
|
4971
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__notice-bar", role: "status", "data-meet-notice": "knock-received", "data-meet-participant-name": knocker.displayName, children: [
|
|
4972
|
+
/* @__PURE__ */ jsxs4("span", { children: [
|
|
4511
4973
|
knocker.displayName,
|
|
4512
4974
|
" wants to join",
|
|
4513
4975
|
others > 0 ? ` (+${others} more)` : ""
|
|
@@ -4531,15 +4993,15 @@ function KnockNotice({ onView }) {
|
|
|
4531
4993
|
function LobbyPanel() {
|
|
4532
4994
|
const lobby = useLobby();
|
|
4533
4995
|
if (!lobby.canAdmit || lobby.waiting.length === 0 && lobby.declined.length === 0) return null;
|
|
4534
|
-
return /* @__PURE__ */
|
|
4996
|
+
return /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
4535
4997
|
lobby.waiting.length > 0 ? /* @__PURE__ */ jsx6(WaitingList, { lobby }) : null,
|
|
4536
4998
|
lobby.declined.length > 0 ? /* @__PURE__ */ jsx6(DeclinedList, { lobby }) : null
|
|
4537
4999
|
] });
|
|
4538
5000
|
}
|
|
4539
5001
|
function DeclinedList({ lobby }) {
|
|
4540
|
-
return /* @__PURE__ */
|
|
5002
|
+
return /* @__PURE__ */ jsxs4("section", { className: "mx-meet__lobby", "aria-label": "Declined requests", "data-meet-declined": "", children: [
|
|
4541
5003
|
/* @__PURE__ */ jsx6("header", { className: "mx-meet__lobby-head", children: /* @__PURE__ */ jsx6("h3", { className: "mx-meet__lobby-title", children: "Declined" }) }),
|
|
4542
|
-
/* @__PURE__ */ jsx6("ul", { className: "mx-meet__lobby-list", children: lobby.declined.map((entry) => /* @__PURE__ */
|
|
5004
|
+
/* @__PURE__ */ jsx6("ul", { className: "mx-meet__lobby-list", children: lobby.declined.map((entry) => /* @__PURE__ */ jsxs4(
|
|
4543
5005
|
"li",
|
|
4544
5006
|
{
|
|
4545
5007
|
className: "mx-meet__lobby-row",
|
|
@@ -4565,12 +5027,12 @@ function DeclinedList({ lobby }) {
|
|
|
4565
5027
|
] });
|
|
4566
5028
|
}
|
|
4567
5029
|
function WaitingList({ lobby }) {
|
|
4568
|
-
return /* @__PURE__ */
|
|
4569
|
-
/* @__PURE__ */
|
|
5030
|
+
return /* @__PURE__ */ jsxs4("section", { className: "mx-meet__lobby", "aria-label": "Waiting room", children: [
|
|
5031
|
+
/* @__PURE__ */ jsxs4("header", { className: "mx-meet__lobby-head", children: [
|
|
4570
5032
|
/* @__PURE__ */ jsx6("h3", { className: "mx-meet__lobby-title", children: lobby.waiting.length === 1 ? "1 person is waiting" : `${lobby.waiting.length} people are waiting` }),
|
|
4571
5033
|
/* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__link", onClick: () => void lobby.admitAll(), children: "Admit all" })
|
|
4572
5034
|
] }),
|
|
4573
|
-
/* @__PURE__ */ jsx6("ul", { className: "mx-meet__lobby-list", children: lobby.waiting.map((entry) => /* @__PURE__ */
|
|
5035
|
+
/* @__PURE__ */ jsx6("ul", { className: "mx-meet__lobby-list", children: lobby.waiting.map((entry) => /* @__PURE__ */ jsxs4(
|
|
4574
5036
|
"li",
|
|
4575
5037
|
{
|
|
4576
5038
|
className: "mx-meet__lobby-row",
|
|
@@ -4578,7 +5040,7 @@ function WaitingList({ lobby }) {
|
|
|
4578
5040
|
"data-meet-participant-name": entry.displayName,
|
|
4579
5041
|
children: [
|
|
4580
5042
|
/* @__PURE__ */ jsx6(Avatar, { name: entry.displayName, url: entry.avatarUrl, size: 32 }),
|
|
4581
|
-
/* @__PURE__ */
|
|
5043
|
+
/* @__PURE__ */ jsxs4("span", { className: "mx-meet__person-name", children: [
|
|
4582
5044
|
entry.displayName,
|
|
4583
5045
|
entry.userId === null ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__badge", children: "Guest" }) : null
|
|
4584
5046
|
] }),
|
|
@@ -4602,17 +5064,17 @@ function NoteTakerRow() {
|
|
|
4602
5064
|
const ai = useMeetAi();
|
|
4603
5065
|
const status = ai.noteTaker;
|
|
4604
5066
|
const duplicateError = status.refusal !== null && ai.error !== null && status.refusal.reason === ai.error.message && status.refusal.remedy === ai.error.remedy;
|
|
4605
|
-
return /* @__PURE__ */
|
|
4606
|
-
/* @__PURE__ */
|
|
5067
|
+
return /* @__PURE__ */ jsxs4("section", { className: "mx-meet__note-taker", "aria-label": "Note-taker", children: [
|
|
5068
|
+
/* @__PURE__ */ jsxs4("p", { className: `mx-meet__note-taker-state mx-meet__note-taker-state--${status.state}`, children: [
|
|
4607
5069
|
/* @__PURE__ */ jsx6("span", { className: "mx-meet__note-taker-dot", "aria-hidden": "true" }),
|
|
4608
5070
|
ai.noteTakerLabel
|
|
4609
5071
|
] }),
|
|
4610
5072
|
status.detail !== null ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__panel-note", children: status.detail }) : null,
|
|
4611
|
-
status.refusal !== null ? /* @__PURE__ */
|
|
5073
|
+
status.refusal !== null ? /* @__PURE__ */ jsxs4(ErrorBox, { as: "div", className: "mx-meet__refusal", error: status.refusal, operation: "Join this meeting", origin: "meet/components", children: [
|
|
4612
5074
|
/* @__PURE__ */ jsx6("p", { className: "mx-meet__refusal-reason", children: status.refusal.reason }),
|
|
4613
5075
|
status.refusal.remedy.length > 0 ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__refusal-remedy", children: status.refusal.remedy }) : null
|
|
4614
5076
|
] }) : null,
|
|
4615
|
-
ai.error !== null && !duplicateError ? /* @__PURE__ */
|
|
5077
|
+
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: [
|
|
4616
5078
|
/* @__PURE__ */ jsx6("p", { className: "mx-meet__refusal-reason", children: ai.error.message }),
|
|
4617
5079
|
/* @__PURE__ */ jsx6("p", { className: "mx-meet__refusal-remedy", children: ai.error.remedy })
|
|
4618
5080
|
] }) : null,
|
|
@@ -4640,9 +5102,9 @@ function NoteList({
|
|
|
4640
5102
|
notes,
|
|
4641
5103
|
empty
|
|
4642
5104
|
}) {
|
|
4643
|
-
return /* @__PURE__ */
|
|
5105
|
+
return /* @__PURE__ */ jsxs4("section", { className: "mx-meet__note-group", "aria-label": title, children: [
|
|
4644
5106
|
/* @__PURE__ */ jsx6("h3", { className: "mx-meet__note-group-title", children: title }),
|
|
4645
|
-
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__ */
|
|
5107
|
+
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: [
|
|
4646
5108
|
note.text,
|
|
4647
5109
|
note.assigneeDisplayName !== void 0 && note.assigneeDisplayName !== null ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__assignee", children: note.assigneeDisplayName }) : null
|
|
4648
5110
|
] }, note.id)) })
|
|
@@ -4650,14 +5112,14 @@ function NoteList({
|
|
|
4650
5112
|
}
|
|
4651
5113
|
function AiPanel({ onClose }) {
|
|
4652
5114
|
const ai = useMeetAi();
|
|
4653
|
-
const [question, setQuestion] =
|
|
4654
|
-
return /* @__PURE__ */
|
|
5115
|
+
const [question, setQuestion] = useState5("");
|
|
5116
|
+
return /* @__PURE__ */ jsxs4(PanelShell, { title: "Meeting assistant", onClose, children: [
|
|
4655
5117
|
/* @__PURE__ */ jsx6(NoteTakerRow, {}),
|
|
4656
|
-
ai.summary !== null ? /* @__PURE__ */
|
|
5118
|
+
ai.summary !== null ? /* @__PURE__ */ jsxs4("section", { className: "mx-meet__note-group", "aria-label": "Summary", children: [
|
|
4657
5119
|
/* @__PURE__ */ jsx6("h3", { className: "mx-meet__note-group-title", children: "Summary" }),
|
|
4658
5120
|
/* @__PURE__ */ jsx6("p", { className: "mx-meet__summary", children: ai.summary.text })
|
|
4659
5121
|
] }) : null,
|
|
4660
|
-
ai.wrapUp !== null ? /* @__PURE__ */
|
|
5122
|
+
ai.wrapUp !== null ? /* @__PURE__ */ jsxs4("p", { className: "mx-meet__wrap-up-notice", role: "status", children: [
|
|
4661
5123
|
"The wrap-up is written \u2014 ",
|
|
4662
5124
|
ai.wrapUp.noteIds.length,
|
|
4663
5125
|
" ",
|
|
@@ -4693,9 +5155,9 @@ function AiPanel({ onClose }) {
|
|
|
4693
5155
|
empty: "No action items yet."
|
|
4694
5156
|
}
|
|
4695
5157
|
),
|
|
4696
|
-
ai.transcript.length > 0 ? /* @__PURE__ */
|
|
5158
|
+
ai.transcript.length > 0 ? /* @__PURE__ */ jsxs4("section", { className: "mx-meet__note-group", "aria-label": "Transcript", children: [
|
|
4697
5159
|
/* @__PURE__ */ jsx6("h3", { className: "mx-meet__note-group-title", children: "Transcript" }),
|
|
4698
|
-
/* @__PURE__ */ jsx6("ul", { className: "mx-meet__transcript", children: ai.transcript.map((line) => /* @__PURE__ */
|
|
5160
|
+
/* @__PURE__ */ jsx6("ul", { className: "mx-meet__transcript", children: ai.transcript.map((line) => /* @__PURE__ */ jsxs4(
|
|
4699
5161
|
"li",
|
|
4700
5162
|
{
|
|
4701
5163
|
className: line.final && line.source === "record" ? "mx-meet__line" : "mx-meet__line mx-meet__line--interim",
|
|
@@ -4707,7 +5169,7 @@ function AiPanel({ onClose }) {
|
|
|
4707
5169
|
line.id
|
|
4708
5170
|
)) })
|
|
4709
5171
|
] }) : null,
|
|
4710
|
-
/* @__PURE__ */
|
|
5172
|
+
/* @__PURE__ */ jsxs4(
|
|
4711
5173
|
"form",
|
|
4712
5174
|
{
|
|
4713
5175
|
className: "mx-meet__composer",
|
|
@@ -4734,7 +5196,7 @@ function AiPanel({ onClose }) {
|
|
|
4734
5196
|
),
|
|
4735
5197
|
ai.asking && ai.phase !== null ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__panel-note", role: "status", children: ai.phase }) : null,
|
|
4736
5198
|
ai.answer !== null ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__answer", children: ai.answer }) : null,
|
|
4737
|
-
ai.answer !== null && ai.coverage !== null ? /* @__PURE__ */
|
|
5199
|
+
ai.answer !== null && ai.coverage !== null ? /* @__PURE__ */ jsxs4("p", { className: "mx-meet__coverage", children: [
|
|
4738
5200
|
"Answered from ",
|
|
4739
5201
|
ai.coverage.segmentsUsed,
|
|
4740
5202
|
" of ",
|
|
@@ -4743,7 +5205,7 @@ function AiPanel({ onClose }) {
|
|
|
4743
5205
|
ai.coverage.truncated ? " (the oldest were left out)" : "",
|
|
4744
5206
|
"."
|
|
4745
5207
|
] }) : null,
|
|
4746
|
-
ai.error !== null ? /* @__PURE__ */
|
|
5208
|
+
ai.error !== null ? /* @__PURE__ */ jsxs4(ErrorBox, { as: "div", className: "mx-meet__refusal", error: ai.error, operation: "Run the meeting assistant", origin: "meet/components", children: [
|
|
4747
5209
|
/* @__PURE__ */ jsx6("p", { className: "mx-meet__refusal-reason", children: ai.error.message }),
|
|
4748
5210
|
/* @__PURE__ */ jsx6("p", { className: "mx-meet__refusal-remedy", children: ai.error.remedy })
|
|
4749
5211
|
] }) : null
|
|
@@ -4753,11 +5215,22 @@ function Captions({ lines = 3 }) {
|
|
|
4753
5215
|
const ai = useMeetAi();
|
|
4754
5216
|
const visible = ai.transcript.slice(-lines);
|
|
4755
5217
|
const translation = useCaptionTranslation(visible);
|
|
4756
|
-
|
|
4757
|
-
|
|
5218
|
+
const captions = useCaptions();
|
|
5219
|
+
if (!captions.on) return null;
|
|
5220
|
+
if (captions.state === "unavailable") {
|
|
5221
|
+
return /* @__PURE__ */ jsx6("div", { className: "mx-meet__captions", role: "status", "data-meet-notice": "captions-unavailable", children: /* @__PURE__ */ jsxs4("p", { className: "mx-meet__caption", children: [
|
|
5222
|
+
"Captions are unavailable. ",
|
|
5223
|
+
captions.reason,
|
|
5224
|
+
captions.remedy !== null ? ` ${captions.remedy}` : ""
|
|
5225
|
+
] }) });
|
|
5226
|
+
}
|
|
5227
|
+
if (visible.length === 0) {
|
|
5228
|
+
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." }) });
|
|
5229
|
+
}
|
|
5230
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__captions", "aria-live": "polite", "aria-label": "Live captions", "data-meet-caption": "live", children: [
|
|
4758
5231
|
visible.map((line) => {
|
|
4759
5232
|
const translated = translation.language === null ? void 0 : translation.translations[line.id];
|
|
4760
|
-
return /* @__PURE__ */
|
|
5233
|
+
return /* @__PURE__ */ jsxs4(
|
|
4761
5234
|
"p",
|
|
4762
5235
|
{
|
|
4763
5236
|
className: line.final ? "mx-meet__caption" : "mx-meet__caption mx-meet__caption--interim",
|
|
@@ -4777,7 +5250,7 @@ function Captions({ lines = 3 }) {
|
|
|
4777
5250
|
function ConsentNotice() {
|
|
4778
5251
|
const notice = useConsentNotice();
|
|
4779
5252
|
if (notice === null) return null;
|
|
4780
|
-
return /* @__PURE__ */ jsx6("p", { className: "mx-meet__consent", role: "status", children: notice });
|
|
5253
|
+
return /* @__PURE__ */ jsx6("p", { className: "mx-meet__consent", role: "status", "data-meet-notice": "notes-started", children: notice });
|
|
4781
5254
|
}
|
|
4782
5255
|
function AttendanceNotice() {
|
|
4783
5256
|
const media = useLocalMedia();
|
|
@@ -4785,7 +5258,7 @@ function AttendanceNotice() {
|
|
|
4785
5258
|
if (notice === null) return null;
|
|
4786
5259
|
const refused = media.microphone.unavailable;
|
|
4787
5260
|
const code = microphoneNoticeCode(media.microphone);
|
|
4788
|
-
return /* @__PURE__ */
|
|
5261
|
+
return /* @__PURE__ */ jsxs4(
|
|
4789
5262
|
"p",
|
|
4790
5263
|
{
|
|
4791
5264
|
className: "mx-meet__banner mx-meet__banner--attendance",
|
|
@@ -4816,15 +5289,22 @@ function PreJoinBody({
|
|
|
4816
5289
|
const recording = useRecording();
|
|
4817
5290
|
const effects = useMediaEffects();
|
|
4818
5291
|
const { notice } = useModerationNotice();
|
|
4819
|
-
const [mode, setMode] =
|
|
4820
|
-
const [microphone, setMicrophone] =
|
|
4821
|
-
const [joining, setJoining] =
|
|
5292
|
+
const [mode, setMode] = useState5("video");
|
|
5293
|
+
const [microphone, setMicrophone] = useState5(true);
|
|
5294
|
+
const [joining, setJoining] = useState5(false);
|
|
4822
5295
|
const camera = devices?.selected.videoinput ?? host.devices.resolve("videoinput");
|
|
4823
5296
|
const mic = devices?.selected.audioinput ?? host.devices.resolve("audioinput");
|
|
4824
|
-
const
|
|
4825
|
-
const
|
|
5297
|
+
const { reportPreview } = useMediaSupervisor();
|
|
5298
|
+
const [attempt, setAttempt] = useState5(0);
|
|
5299
|
+
const preview = useCameraPreview(
|
|
5300
|
+
mode === "video" ? camera : void 0,
|
|
5301
|
+
effects.effects,
|
|
5302
|
+
(outcome) => reportPreview("camera", outcome),
|
|
5303
|
+
attempt
|
|
5304
|
+
);
|
|
5305
|
+
const micStream = useMicrophoneStream(microphone ? mic : "off", (outcome) => reportPreview("microphone", outcome), attempt);
|
|
4826
5306
|
const level = useAudioLevel(micStream);
|
|
4827
|
-
const [speakerTesting, setSpeakerTesting] =
|
|
5307
|
+
const [speakerTesting, setSpeakerTesting] = useState5(false);
|
|
4828
5308
|
useEffect6(() => {
|
|
4829
5309
|
void host.devices.refresh();
|
|
4830
5310
|
}, [host]);
|
|
@@ -4847,8 +5327,8 @@ function PreJoinBody({
|
|
|
4847
5327
|
...secondDevice !== void 0 ? { secondDevice } : {}
|
|
4848
5328
|
}).then(() => onJoined?.()).catch(() => void 0).finally(() => setJoining(false));
|
|
4849
5329
|
};
|
|
4850
|
-
return /* @__PURE__ */
|
|
4851
|
-
/* @__PURE__ */
|
|
5330
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__prejoin", children: [
|
|
5331
|
+
/* @__PURE__ */ jsxs4("div", { className: "mx-meet__preview", children: [
|
|
4852
5332
|
mode === "video" && preview.preview !== null ? /* @__PURE__ */ jsx6(
|
|
4853
5333
|
"video",
|
|
4854
5334
|
{
|
|
@@ -4864,10 +5344,11 @@ function PreJoinBody({
|
|
|
4864
5344
|
mode === "video" && preview.error !== null ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__preview-note", children: preview.error }) : null,
|
|
4865
5345
|
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
|
|
4866
5346
|
] }),
|
|
4867
|
-
/* @__PURE__ */
|
|
5347
|
+
/* @__PURE__ */ jsxs4("div", { className: "mx-meet__prejoin-panel", children: [
|
|
4868
5348
|
/* @__PURE__ */ jsx6("h1", { className: "mx-meet__prejoin-title", children: "Ready to join?" }),
|
|
5349
|
+
/* @__PURE__ */ jsx6(PreviewStatus, { onRetry: () => setAttempt((n) => n + 1) }),
|
|
4869
5350
|
notice?.kind === "removed" ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__warning", children: notice.text }) : null,
|
|
4870
|
-
devices?.labelsHidden === true ? /* @__PURE__ */
|
|
5351
|
+
devices?.labelsHidden === true ? /* @__PURE__ */ jsxs4("p", { className: "mx-meet__panel-note", children: [
|
|
4871
5352
|
"Your browser is hiding device names until you allow camera and microphone access.",
|
|
4872
5353
|
/* @__PURE__ */ jsx6(
|
|
4873
5354
|
"button",
|
|
@@ -4883,9 +5364,9 @@ function PreJoinBody({
|
|
|
4883
5364
|
] }) : null,
|
|
4884
5365
|
devices?.fallbackNotice != null ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__warning", children: devices.fallbackNotice }) : null,
|
|
4885
5366
|
/* @__PURE__ */ jsx6(DevicePicker, { kind: "audioinput", label: "Microphone" }),
|
|
4886
|
-
/* @__PURE__ */
|
|
5367
|
+
/* @__PURE__ */ jsxs4("div", { className: "mx-meet__field-row", children: [
|
|
4887
5368
|
/* @__PURE__ */ jsx6(DevicePicker, { kind: "audiooutput", label: "Speaker" }),
|
|
4888
|
-
/* @__PURE__ */
|
|
5369
|
+
/* @__PURE__ */ jsxs4(
|
|
4889
5370
|
Button,
|
|
4890
5371
|
{
|
|
4891
5372
|
type: "button",
|
|
@@ -4908,8 +5389,8 @@ function PreJoinBody({
|
|
|
4908
5389
|
/* @__PURE__ */ jsx6(DevicePicker, { kind: "videoinput", label: "Camera" }),
|
|
4909
5390
|
/* @__PURE__ */ jsx6(EffectsSettings, { preview: preview.preview }),
|
|
4910
5391
|
recording.consentNotice !== null ? /* @__PURE__ */ jsx6(Alert, { variant: "info", children: /* @__PURE__ */ jsx6(AlertDescription, { children: recording.consentNotice }) }) : null,
|
|
4911
|
-
/* @__PURE__ */
|
|
4912
|
-
/* @__PURE__ */
|
|
5392
|
+
/* @__PURE__ */ jsxs4("div", { className: "mx-meet__prejoin-actions", children: [
|
|
5393
|
+
/* @__PURE__ */ jsxs4("div", { className: "mx-meet__check", children: [
|
|
4913
5394
|
/* @__PURE__ */ jsx6(
|
|
4914
5395
|
Checkbox,
|
|
4915
5396
|
{
|
|
@@ -4920,7 +5401,7 @@ function PreJoinBody({
|
|
|
4920
5401
|
),
|
|
4921
5402
|
/* @__PURE__ */ jsx6(Label, { htmlFor: "mx-meet-join-video", children: "Join with video" })
|
|
4922
5403
|
] }),
|
|
4923
|
-
/* @__PURE__ */
|
|
5404
|
+
/* @__PURE__ */ jsxs4("div", { className: "mx-meet__check", children: [
|
|
4924
5405
|
/* @__PURE__ */ jsx6(
|
|
4925
5406
|
Checkbox,
|
|
4926
5407
|
{
|
|
@@ -4934,7 +5415,7 @@ function PreJoinBody({
|
|
|
4934
5415
|
room.secondDevice === null ? /* @__PURE__ */ jsx6(Button, { type: "button", className: "mx-meet__join", disabled: joining, onClick: () => joinWith(), children: joining ? "Joining\u2026" : observe2 ? "Observe" : "Join now" }) : (
|
|
4935
5416
|
// S7: ALREADY IN THIS MEETING on another tab or device — the meeting's choice
|
|
4936
5417
|
// (Meet: Switch here / Join here too; Teams: Transfer here / Add this device).
|
|
4937
|
-
/* @__PURE__ */
|
|
5418
|
+
/* @__PURE__ */ jsxs4("div", { className: "mx-meet__second-device", "data-meet-region": "second-device", children: [
|
|
4938
5419
|
/* @__PURE__ */ jsx6("p", { className: "mx-meet__hint", children: "You're in this meeting on another device" }),
|
|
4939
5420
|
/* @__PURE__ */ jsx6(
|
|
4940
5421
|
Button,
|
|
@@ -4961,23 +5442,29 @@ function PreJoinBody({
|
|
|
4961
5442
|
] })
|
|
4962
5443
|
)
|
|
4963
5444
|
] }),
|
|
4964
|
-
room.failure !== null ? /* @__PURE__ */
|
|
5445
|
+
room.failure !== null ? /* @__PURE__ */ jsxs4("p", { className: "mx-meet__error", children: [
|
|
4965
5446
|
room.failure.message,
|
|
4966
5447
|
/* @__PURE__ */ jsx6("span", { className: "mx-meet__remedy", children: room.failure.remedy })
|
|
4967
5448
|
] }) : null
|
|
4968
5449
|
] })
|
|
4969
5450
|
] });
|
|
4970
5451
|
}
|
|
4971
|
-
function useCameraPreview(deviceId, effects) {
|
|
4972
|
-
const
|
|
4973
|
-
|
|
5452
|
+
function useCameraPreview(deviceId, effects, report, attempt = 0) {
|
|
5453
|
+
const reportRef = useRef6(report);
|
|
5454
|
+
reportRef.current = report;
|
|
5455
|
+
const [preview, setPreview] = useState5(null);
|
|
5456
|
+
const [error, setError] = useState5(null);
|
|
4974
5457
|
const current = useRef6(null);
|
|
4975
5458
|
const initialEffect = useRef6(toVideoEffect(effects));
|
|
4976
5459
|
initialEffect.current = toVideoEffect(effects);
|
|
4977
5460
|
useEffect6(() => {
|
|
4978
|
-
if (deviceId === void 0)
|
|
5461
|
+
if (deviceId === void 0) {
|
|
5462
|
+
reportRef.current?.("off");
|
|
5463
|
+
return void 0;
|
|
5464
|
+
}
|
|
4979
5465
|
let live = true;
|
|
4980
5466
|
setError(null);
|
|
5467
|
+
reportRef.current?.("prompting");
|
|
4981
5468
|
void createCameraPreview(deviceId, initialEffect.current).then((created) => {
|
|
4982
5469
|
if (!live) {
|
|
4983
5470
|
created.stop();
|
|
@@ -4985,8 +5472,10 @@ function useCameraPreview(deviceId, effects) {
|
|
|
4985
5472
|
}
|
|
4986
5473
|
current.current = created;
|
|
4987
5474
|
setPreview(created);
|
|
5475
|
+
reportRef.current?.("on");
|
|
4988
5476
|
}).catch((thrown) => {
|
|
4989
5477
|
if (!live) return;
|
|
5478
|
+
reportRef.current?.({ error: thrown });
|
|
4990
5479
|
const failure = thrown;
|
|
4991
5480
|
const message = (failure.message ?? "").replace(/^meet\.[A-Za-z.()]+:\s*/, "");
|
|
4992
5481
|
const sentence = message.length > 0 ? message.charAt(0).toUpperCase() + message.slice(1) : "";
|
|
@@ -4998,7 +5487,7 @@ function useCameraPreview(deviceId, effects) {
|
|
|
4998
5487
|
current.current = null;
|
|
4999
5488
|
setPreview(null);
|
|
5000
5489
|
};
|
|
5001
|
-
}, [deviceId]);
|
|
5490
|
+
}, [deviceId, attempt]);
|
|
5002
5491
|
return {
|
|
5003
5492
|
preview,
|
|
5004
5493
|
error,
|
|
@@ -5021,9 +5510,9 @@ function DevicePicker({
|
|
|
5021
5510
|
const triggerId = `mx-meet-device-${kind}`;
|
|
5022
5511
|
const valueOf = (deviceId) => deviceId.length > 0 ? deviceId : "default";
|
|
5023
5512
|
const current = devices?.selected[kind] ?? host.devices.resolve(kind) ?? "";
|
|
5024
|
-
return /* @__PURE__ */
|
|
5513
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__field", children: [
|
|
5025
5514
|
/* @__PURE__ */ jsx6(Label, { htmlFor: triggerId, children: label }),
|
|
5026
|
-
/* @__PURE__ */
|
|
5515
|
+
/* @__PURE__ */ jsxs4(
|
|
5027
5516
|
Select,
|
|
5028
5517
|
{
|
|
5029
5518
|
...current.length > 0 ? { value: valueOf(current) } : {},
|
|
@@ -5110,19 +5599,19 @@ function MeetSkinRoom({
|
|
|
5110
5599
|
if (screen === "refused" || screen === "exit") {
|
|
5111
5600
|
return /* @__PURE__ */ jsx6("div", { className: "mx-meet mx-meet--lobby", children: /* @__PURE__ */ jsx6(ExitScreen, { ...onLeave !== void 0 ? { onLeave } : {} }) });
|
|
5112
5601
|
}
|
|
5113
|
-
return /* @__PURE__ */
|
|
5602
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mx-meet", children: [
|
|
5114
5603
|
/* @__PURE__ */ jsx6(ConsentNotice, {}),
|
|
5115
5604
|
/* @__PURE__ */ jsx6(AttendanceNotice, {}),
|
|
5116
|
-
/* @__PURE__ */
|
|
5605
|
+
/* @__PURE__ */ jsxs4("header", { className: "mx-meet__header", children: [
|
|
5117
5606
|
/* @__PURE__ */ jsx6("h1", { className: "mx-meet__title", children: snapshot?.meeting?.title ?? "Meeting" }),
|
|
5118
|
-
/* @__PURE__ */
|
|
5607
|
+
/* @__PURE__ */ jsxs4("span", { className: "mx-meet__meta", children: [
|
|
5119
5608
|
participantSummary(snapshot?.participants ?? []),
|
|
5120
5609
|
elapsed > 0 ? ` \xB7 ${formatDurationMs2(elapsed)}` : ""
|
|
5121
5610
|
] }),
|
|
5122
5611
|
/* @__PURE__ */ jsx6(RecordingIndicator, {}),
|
|
5123
5612
|
captureHeldOf(snapshot?.meeting) ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__badge", "data-meet-capture-held": "", children: "Confidential \xB7 not recorded" }) : null,
|
|
5124
5613
|
isObserverRole(snapshot?.grants.role) ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__badge", "data-meet-observing": "self", children: "Observing" }) : null,
|
|
5125
|
-
snapshot?.locked === true ? /* @__PURE__ */
|
|
5614
|
+
snapshot?.locked === true ? /* @__PURE__ */ jsxs4("span", { className: "mx-meet__badge", children: [
|
|
5126
5615
|
/* @__PURE__ */ jsx6(LockIcon, { width: 12, height: 12 }),
|
|
5127
5616
|
" Locked"
|
|
5128
5617
|
] }) : null,
|
|
@@ -5138,9 +5627,17 @@ function MeetSkinRoom({
|
|
|
5138
5627
|
}
|
|
5139
5628
|
function ShareNotice() {
|
|
5140
5629
|
const { share, actions } = useMeetCore();
|
|
5630
|
+
const [soundHintClosed, setSoundHintClosed] = useState5(null);
|
|
5631
|
+
if (share.state === "presenting" && share.audio === false && soundHintClosed !== share.at) {
|
|
5632
|
+
return /* @__PURE__ */ jsxs4("p", { className: "mx-meet__banner", role: "status", "data-meet-notice": "share-audio-missing", children: [
|
|
5633
|
+
"Sound not shared",
|
|
5634
|
+
/* @__PURE__ */ jsx6("span", { className: "mx-meet__remedy", children: "To include sound, share a tab and turn on Also share tab audio" }),
|
|
5635
|
+
/* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__link", onClick: () => setSoundHintClosed(share.at), children: "Dismiss" })
|
|
5636
|
+
] });
|
|
5637
|
+
}
|
|
5141
5638
|
if (share.state !== "refused") return null;
|
|
5142
5639
|
const text = 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";
|
|
5143
|
-
return /* @__PURE__ */
|
|
5640
|
+
return /* @__PURE__ */ jsxs4("p", { className: "mx-meet__banner", role: "status", "data-meet-notice": "share-unavailable", children: [
|
|
5144
5641
|
text,
|
|
5145
5642
|
share.remedy !== null ? /* @__PURE__ */ jsx6("span", { className: "mx-meet__remedy", children: share.remedy }) : null,
|
|
5146
5643
|
/* @__PURE__ */ jsx6("button", { type: "button", className: "mx-meet__link", onClick: actions.dismissShareNotice, children: "Dismiss" })
|
|
@@ -5168,7 +5665,7 @@ function clockText(ms) {
|
|
|
5168
5665
|
}
|
|
5169
5666
|
function ExitScreen({ onLeave }) {
|
|
5170
5667
|
const { phase, reason, host, snapshot, actions, call, connection } = useMeetCore();
|
|
5171
|
-
const [busy, setBusy] =
|
|
5668
|
+
const [busy, setBusy] = useState5(false);
|
|
5172
5669
|
const failure = snapshot?.failure ?? null;
|
|
5173
5670
|
const retryLeft = useCountdown(phase === "refused:lobby_rejects" ? failure?.retryAt ?? null : null);
|
|
5174
5671
|
const rejoin = /* @__PURE__ */ jsx6(
|
|
@@ -5209,7 +5706,7 @@ function ExitScreen({ onLeave }) {
|
|
|
5209
5706
|
const code = phase.slice("refused:".length);
|
|
5210
5707
|
title = REFUSED_TITLES[code] ?? "You can't join this meeting";
|
|
5211
5708
|
line = code === "too_early" || code === "registration_required" || code === "cancelled" ? failure?.remedy ?? null : null;
|
|
5212
|
-
actionsNode = /* @__PURE__ */
|
|
5709
|
+
actionsNode = /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
5213
5710
|
/* @__PURE__ */ jsx6(Button, { type: "button", variant: "outline", onClick: actions.retry, children: "Try again" }),
|
|
5214
5711
|
home
|
|
5215
5712
|
] });
|
|
@@ -5220,7 +5717,7 @@ function ExitScreen({ onLeave }) {
|
|
|
5220
5717
|
actionsNode = home;
|
|
5221
5718
|
} else if (retryLeft === 0) {
|
|
5222
5719
|
line = "You can ask to join again";
|
|
5223
|
-
actionsNode = /* @__PURE__ */
|
|
5720
|
+
actionsNode = /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
5224
5721
|
/* @__PURE__ */ jsx6(
|
|
5225
5722
|
Button,
|
|
5226
5723
|
{
|
|
@@ -5244,16 +5741,37 @@ function ExitScreen({ onLeave }) {
|
|
|
5244
5741
|
switch (phase) {
|
|
5245
5742
|
case "left":
|
|
5246
5743
|
title = "You left the meeting";
|
|
5247
|
-
actionsNode = /* @__PURE__ */
|
|
5744
|
+
actionsNode = /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
5248
5745
|
rejoin,
|
|
5249
5746
|
home
|
|
5250
5747
|
] });
|
|
5251
5748
|
break;
|
|
5252
5749
|
case "disconnected":
|
|
5750
|
+
if (failure?.stage === "join" && (failure.reason ?? null) === null) {
|
|
5751
|
+
title = "Can't connect to the meeting";
|
|
5752
|
+
line = connection === "offline" ? "You're offline. Check your internet connection." : "Check your network. A VPN, firewall or proxy may be blocking the call.";
|
|
5753
|
+
notice = "cannot-connect";
|
|
5754
|
+
actionsNode = /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
5755
|
+
/* @__PURE__ */ jsx6(
|
|
5756
|
+
Button,
|
|
5757
|
+
{
|
|
5758
|
+
type: "button",
|
|
5759
|
+
disabled: busy,
|
|
5760
|
+
onClick: () => {
|
|
5761
|
+
setBusy(true);
|
|
5762
|
+
void actions.rejoin().catch(() => void 0).finally(() => setBusy(false));
|
|
5763
|
+
},
|
|
5764
|
+
children: "Try again"
|
|
5765
|
+
}
|
|
5766
|
+
),
|
|
5767
|
+
home
|
|
5768
|
+
] });
|
|
5769
|
+
break;
|
|
5770
|
+
}
|
|
5253
5771
|
title = "You lost your connection to the meeting";
|
|
5254
5772
|
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.";
|
|
5255
5773
|
notice = "disconnected";
|
|
5256
|
-
actionsNode = /* @__PURE__ */
|
|
5774
|
+
actionsNode = /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
5257
5775
|
rejoin,
|
|
5258
5776
|
home
|
|
5259
5777
|
] });
|
|
@@ -5266,14 +5784,14 @@ function ExitScreen({ onLeave }) {
|
|
|
5266
5784
|
title = "You joined from another tab or device";
|
|
5267
5785
|
line = "This screen left the meeting so you aren't in it twice.";
|
|
5268
5786
|
notice = "displaced";
|
|
5269
|
-
actionsNode = /* @__PURE__ */
|
|
5787
|
+
actionsNode = /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
5270
5788
|
rejoin,
|
|
5271
5789
|
home
|
|
5272
5790
|
] });
|
|
5273
5791
|
break;
|
|
5274
5792
|
case "inactive":
|
|
5275
5793
|
title = "You left the meeting because this tab was inactive";
|
|
5276
|
-
actionsNode = /* @__PURE__ */
|
|
5794
|
+
actionsNode = /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
5277
5795
|
rejoin,
|
|
5278
5796
|
home
|
|
5279
5797
|
] });
|
|
@@ -5296,7 +5814,7 @@ function ExitScreen({ onLeave }) {
|
|
|
5296
5814
|
break;
|
|
5297
5815
|
}
|
|
5298
5816
|
}
|
|
5299
|
-
return /* @__PURE__ */
|
|
5817
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__waiting", "data-meet-exit": phase, children: [
|
|
5300
5818
|
/* @__PURE__ */ jsx6(Avatar, { name: host?.identity.displayName ?? "", url: host?.identity.avatarUrl ?? null, size: 72 }),
|
|
5301
5819
|
/* @__PURE__ */ jsx6("h1", { className: "mx-meet__prejoin-title", children: title }),
|
|
5302
5820
|
line !== null ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__empty-body", children: line }) : null,
|
|
@@ -5307,7 +5825,7 @@ function ExitScreen({ onLeave }) {
|
|
|
5307
5825
|
function WaitingRoom({ host, onLeave }) {
|
|
5308
5826
|
const { waiting, withdraw, askAgain } = useWaiting();
|
|
5309
5827
|
const { phaseNotice } = useMeetCore();
|
|
5310
|
-
const [busy, setBusy] =
|
|
5828
|
+
const [busy, setBusy] = useState5(false);
|
|
5311
5829
|
const admission = waiting?.admission ?? "knocking";
|
|
5312
5830
|
const reknockLeft = useCountdown(admission === "denied" ? waiting?.reknockAt ?? null : null);
|
|
5313
5831
|
const run = (action) => () => {
|
|
@@ -5330,21 +5848,21 @@ function WaitingRoom({ host, onLeave }) {
|
|
|
5330
5848
|
line = `You can ask again in ${clockText(reknockLeft)}`;
|
|
5331
5849
|
cooldownNotice = true;
|
|
5332
5850
|
}
|
|
5333
|
-
actions = /* @__PURE__ */
|
|
5851
|
+
actions = /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
5334
5852
|
waiting?.reknockAllowed === true || waiting?.reknockAt != null && reknockLeft === 0 ? /* @__PURE__ */ jsx6(Button, { type: "button", disabled: busy, onClick: run(askAgain), children: "Ask to join again" }) : null,
|
|
5335
5853
|
home
|
|
5336
5854
|
] });
|
|
5337
5855
|
break;
|
|
5338
5856
|
case "expired":
|
|
5339
5857
|
title = "No one responded";
|
|
5340
|
-
actions = /* @__PURE__ */
|
|
5858
|
+
actions = /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
5341
5859
|
/* @__PURE__ */ jsx6(Button, { type: "button", disabled: busy, onClick: run(askAgain), children: "Ask again" }),
|
|
5342
5860
|
home
|
|
5343
5861
|
] });
|
|
5344
5862
|
break;
|
|
5345
5863
|
case "withdrawn":
|
|
5346
5864
|
title = "You left the waiting room";
|
|
5347
|
-
actions = /* @__PURE__ */
|
|
5865
|
+
actions = /* @__PURE__ */ jsxs4(Fragment, { children: [
|
|
5348
5866
|
/* @__PURE__ */ jsx6(Button, { type: "button", disabled: busy, onClick: run(askAgain), children: "Rejoin" }),
|
|
5349
5867
|
home
|
|
5350
5868
|
] });
|
|
@@ -5358,7 +5876,7 @@ function WaitingRoom({ host, onLeave }) {
|
|
|
5358
5876
|
line = waiting?.admittersPresent === false ? "The host isn't here yet" : null;
|
|
5359
5877
|
actions = /* @__PURE__ */ jsx6(Button, { type: "button", variant: "outline", disabled: busy, onClick: run(withdraw), children: "Cancel request" });
|
|
5360
5878
|
}
|
|
5361
|
-
return /* @__PURE__ */
|
|
5879
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__waiting", children: [
|
|
5362
5880
|
/* @__PURE__ */ jsx6(Avatar, { name: host.identity.displayName, url: host.identity.avatarUrl, size: 72 }),
|
|
5363
5881
|
/* @__PURE__ */ jsx6("h1", { className: "mx-meet__prejoin-title", children: title }),
|
|
5364
5882
|
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,
|
|
@@ -5378,9 +5896,9 @@ function HostMenu() {
|
|
|
5378
5896
|
const host = useRequiredMeetHost();
|
|
5379
5897
|
const snapshot = useMeetSnapshot();
|
|
5380
5898
|
const end = useEndMeeting();
|
|
5381
|
-
const [confirmingEnd, setConfirmingEnd] =
|
|
5899
|
+
const [confirmingEnd, setConfirmingEnd] = useState5(false);
|
|
5382
5900
|
const locked = snapshot?.locked === true;
|
|
5383
|
-
return /* @__PURE__ */
|
|
5901
|
+
return /* @__PURE__ */ jsxs4("div", { className: "mx-meet__host-menu", children: [
|
|
5384
5902
|
/* @__PURE__ */ jsx6(
|
|
5385
5903
|
"button",
|
|
5386
5904
|
{
|
|
@@ -5392,7 +5910,7 @@ function HostMenu() {
|
|
|
5392
5910
|
children: locked ? "Unlock meeting" : "Lock meeting"
|
|
5393
5911
|
}
|
|
5394
5912
|
),
|
|
5395
|
-
end.canEnd ? confirmingEnd ? /* @__PURE__ */
|
|
5913
|
+
end.canEnd ? confirmingEnd ? /* @__PURE__ */ jsxs4("span", { className: "mx-meet__confirm", role: "group", "aria-label": "End this meeting?", children: [
|
|
5396
5914
|
/* @__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." }),
|
|
5397
5915
|
/* @__PURE__ */ jsx6(
|
|
5398
5916
|
"button",
|
|
@@ -5448,9 +5966,9 @@ function GuestRecordAccessControl({
|
|
|
5448
5966
|
const isHost = inRoomHost || viewerId !== null && meeting.hostUserId === viewerId;
|
|
5449
5967
|
if (host === null || !isHost) return null;
|
|
5450
5968
|
const resolved = access.setting === "default" && access.effective !== null ? ` Right now that means: ${guestRecordAccessLabel(access.effective.level).toLowerCase()}.` : "";
|
|
5451
|
-
return /* @__PURE__ */
|
|
5969
|
+
return /* @__PURE__ */ jsxs4("section", { className: "mx-meet__record-section", "aria-label": "What guests may read", children: [
|
|
5452
5970
|
/* @__PURE__ */ jsx6("h2", { className: "mx-meet__record-section-title", children: "What guests may read" }),
|
|
5453
|
-
/* @__PURE__ */
|
|
5971
|
+
/* @__PURE__ */ jsxs4("label", { className: "mx-meet__field", children: [
|
|
5454
5972
|
/* @__PURE__ */ jsx6("span", { className: "mx-meet__field-label", children: "People who attended by link, without an account" }),
|
|
5455
5973
|
/* @__PURE__ */ jsx6(
|
|
5456
5974
|
"select",
|
|
@@ -5467,12 +5985,12 @@ function GuestRecordAccessControl({
|
|
|
5467
5985
|
}
|
|
5468
5986
|
)
|
|
5469
5987
|
] }),
|
|
5470
|
-
/* @__PURE__ */
|
|
5988
|
+
/* @__PURE__ */ jsxs4("p", { className: "mx-meet__panel-note", children: [
|
|
5471
5989
|
guestRecordAccessExplanation(access.setting),
|
|
5472
5990
|
resolved
|
|
5473
5991
|
] }),
|
|
5474
5992
|
access.saving ? /* @__PURE__ */ jsx6("p", { className: "mx-meet__panel-note", role: "status", children: "Saving what guests may read\u2026" }) : null,
|
|
5475
|
-
access.error !== null ? /* @__PURE__ */
|
|
5993
|
+
access.error !== null ? /* @__PURE__ */ jsxs4(ErrorBox, { as: "div", className: "mx-meet__refusal", error: access.error, operation: "Change who can join", origin: "meet/components", children: [
|
|
5476
5994
|
/* @__PURE__ */ jsx6("p", { className: "mx-meet__refusal-reason", children: access.error.message }),
|
|
5477
5995
|
/* @__PURE__ */ jsx6("p", { className: "mx-meet__refusal-remedy", children: access.error.remedy })
|
|
5478
5996
|
] }) : null
|
|
@@ -5491,9 +6009,11 @@ export {
|
|
|
5491
6009
|
CameraOffIcon,
|
|
5492
6010
|
CaptionLanguageSettings,
|
|
5493
6011
|
Captions,
|
|
6012
|
+
CaptionsIcon,
|
|
5494
6013
|
ChatIcon,
|
|
5495
6014
|
ChatPanel,
|
|
5496
6015
|
CheckIcon,
|
|
6016
|
+
ChevronUpIcon,
|
|
5497
6017
|
CloseIcon,
|
|
5498
6018
|
ConnectionDot,
|
|
5499
6019
|
ConsentNotice,
|
|
@@ -5514,6 +6034,7 @@ export {
|
|
|
5514
6034
|
MicIcon,
|
|
5515
6035
|
MicOffIcon,
|
|
5516
6036
|
MoreIcon,
|
|
6037
|
+
NotesIcon,
|
|
5517
6038
|
PanelShell,
|
|
5518
6039
|
ParticipantTile,
|
|
5519
6040
|
PencilIcon,
|