@ai-matrx/meet 0.11.41 → 0.11.43
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 +18 -0
- package/dist/{collab-XY6Xj1dG.d.cts → collab-BNJNgXFB.d.cts} +11 -2
- package/dist/{collab-XY6Xj1dG.d.ts → collab-BNJNgXFB.d.ts} +11 -2
- package/dist/{components-4f9Mf8fz.d.cts → components-BDtGzHf4.d.ts} +4 -2
- package/dist/{components-Cwep2NYU.d.ts → components-BxK993iW.d.cts} +4 -2
- package/dist/core.cjs +190 -25
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +58 -11
- package/dist/core.d.ts +58 -11
- package/dist/core.js +190 -25
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +190 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +190 -25
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +469 -66
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +21 -4
- package/dist/react.d.ts +21 -4
- package/dist/react.js +469 -66
- package/dist/react.js.map +1 -1
- package/dist/skins/meet.cjs +326 -48
- package/dist/skins/meet.cjs.map +1 -1
- package/dist/skins/meet.d.cts +5 -3
- package/dist/skins/meet.d.ts +5 -3
- package/dist/skins/meet.js +326 -48
- package/dist/skins/meet.js.map +1 -1
- package/dist/styles.css +12 -0
- package/package.json +3 -3
package/dist/react.cjs
CHANGED
|
@@ -122,6 +122,7 @@ __export(react_exports, {
|
|
|
122
122
|
autoAssign: () => autoAssign,
|
|
123
123
|
autoRejoinDelayMs: () => autoRejoinDelayMs,
|
|
124
124
|
availableActivities: () => availableActivities,
|
|
125
|
+
breakoutClosingMs: () => breakoutClosingMs,
|
|
125
126
|
breakoutRemainingMs: () => breakoutRemainingMs,
|
|
126
127
|
callInviteAction: () => callInviteAction,
|
|
127
128
|
callInviteText: () => callInviteText,
|
|
@@ -289,6 +290,7 @@ __export(react_exports, {
|
|
|
289
290
|
useCanModerate: () => useCanModerate,
|
|
290
291
|
useCanRecord: () => useCanRecord,
|
|
291
292
|
useCaptionTranslation: () => useCaptionTranslation,
|
|
293
|
+
useCaptions: () => useCaptions,
|
|
292
294
|
useCollab: () => useCollab,
|
|
293
295
|
useCollabPanelRequest: () => useCollabPanelRequest,
|
|
294
296
|
useConsentNotice: () => useConsentNotice,
|
|
@@ -1107,6 +1109,8 @@ var MEET_ROUTES = {
|
|
|
1107
1109
|
noteTakerStop: "/api/v1/meet/agent/stop",
|
|
1108
1110
|
/** In-meeting Q&A. Streams NDJSON; body is `{meeting_id, question}` only. */
|
|
1109
1111
|
intelligenceAsk: "/api/v1/meet/intelligence/ask",
|
|
1112
|
+
/** Anyone in the meeting (guests with the room pass included) asks for captions for themselves. */
|
|
1113
|
+
noteTakerCaptions: "/api/v1/meet/agent/captions",
|
|
1110
1114
|
/** A host ends the meeting for everyone. Served by MRI-A6. */
|
|
1111
1115
|
meetingEnd: "/api/v1/meet/end",
|
|
1112
1116
|
/**
|
|
@@ -1253,7 +1257,8 @@ function parseRoomToken(body, roomName) {
|
|
|
1253
1257
|
breakoutRoomId: readString(payload, "breakout_room_id") ?? null,
|
|
1254
1258
|
observersVisibleTo: readString(payload, "observers_visible_to") === "hosts" ? "hosts" : "everyone",
|
|
1255
1259
|
connectionPolicy: connectionPolicyFrom(payload["connection_policy"]),
|
|
1256
|
-
leavePolicy: leavePolicyFrom(payload["leave_policy"])
|
|
1260
|
+
leavePolicy: leavePolicyFrom(payload["leave_policy"]),
|
|
1261
|
+
canReclaim: payload["can_reclaim"] === true
|
|
1257
1262
|
};
|
|
1258
1263
|
}
|
|
1259
1264
|
function createTokenClient(options) {
|
|
@@ -1715,6 +1720,42 @@ function createMeetAi(options) {
|
|
|
1715
1720
|
},
|
|
1716
1721
|
"meet.ai.startNoteTaker"
|
|
1717
1722
|
),
|
|
1723
|
+
requestCaptions: async ({ meetingId }) => {
|
|
1724
|
+
const roomToken = options.resolveRoomToken?.() ?? null;
|
|
1725
|
+
const operation = "meet.ai.requestCaptions";
|
|
1726
|
+
try {
|
|
1727
|
+
const response = await send({
|
|
1728
|
+
path: MEET_ROUTES.noteTakerCaptions,
|
|
1729
|
+
body: { meeting_id: meetingId },
|
|
1730
|
+
operation,
|
|
1731
|
+
requireAuth: roomToken === null,
|
|
1732
|
+
...roomToken !== null ? { headers: { [MEETING_PASS_HEADER]: roomToken } } : {}
|
|
1733
|
+
});
|
|
1734
|
+
if (!response.ok) {
|
|
1735
|
+
options.store.patch({ captionsRefusal: await refusalFor(response, operation) });
|
|
1736
|
+
return;
|
|
1737
|
+
}
|
|
1738
|
+
let payload = null;
|
|
1739
|
+
try {
|
|
1740
|
+
payload = await response.json();
|
|
1741
|
+
} catch {
|
|
1742
|
+
payload = null;
|
|
1743
|
+
}
|
|
1744
|
+
const row = typeof payload === "object" && payload !== null ? payload : {};
|
|
1745
|
+
const detail = typeof row["detail"] === "string" ? row["detail"] : "";
|
|
1746
|
+
options.store.patch({
|
|
1747
|
+
captionsRefusal: row["dispatched"] === true ? null : { status: 200, reason: detail, remedy: "" }
|
|
1748
|
+
});
|
|
1749
|
+
} catch (error) {
|
|
1750
|
+
options.store.patch({
|
|
1751
|
+
captionsRefusal: {
|
|
1752
|
+
status: 0,
|
|
1753
|
+
reason: error.message,
|
|
1754
|
+
remedy: error.remedy ?? ""
|
|
1755
|
+
}
|
|
1756
|
+
});
|
|
1757
|
+
}
|
|
1758
|
+
},
|
|
1718
1759
|
stopNoteTaker: ({ meetingId }) => dispatch(
|
|
1719
1760
|
MEET_ROUTES.noteTakerStop,
|
|
1720
1761
|
{ meeting_id: meetingId },
|
|
@@ -2701,6 +2742,55 @@ function recordingLabel(state) {
|
|
|
2701
2742
|
}
|
|
2702
2743
|
}
|
|
2703
2744
|
|
|
2745
|
+
// src/core/live-policy.ts
|
|
2746
|
+
var DEFAULT_LIVE_POLICY = {
|
|
2747
|
+
chatMode: "everyone",
|
|
2748
|
+
avLock: "off",
|
|
2749
|
+
timeLimitMinutes: 0,
|
|
2750
|
+
timeLimitWarningMinutes: 5,
|
|
2751
|
+
recordingConsent: "notice"
|
|
2752
|
+
};
|
|
2753
|
+
function oneOf(value, allowed, fallback) {
|
|
2754
|
+
return typeof value === "string" && allowed.includes(value) ? value : fallback;
|
|
2755
|
+
}
|
|
2756
|
+
function whole(value, fallback) {
|
|
2757
|
+
const n = typeof value === "number" ? value : typeof value === "string" ? Number(value) : NaN;
|
|
2758
|
+
return Number.isFinite(n) && n >= 0 ? Math.floor(n) : fallback;
|
|
2759
|
+
}
|
|
2760
|
+
function livePolicyFrom(raw) {
|
|
2761
|
+
const o = typeof raw === "object" && raw !== null ? raw : {};
|
|
2762
|
+
return {
|
|
2763
|
+
chatMode: oneOf(o["chat_mode"], ["everyone", "hosts_only", "off"], DEFAULT_LIVE_POLICY.chatMode),
|
|
2764
|
+
avLock: oneOf(o["attendee_av_lock"], ["off", "mic", "camera", "both"], DEFAULT_LIVE_POLICY.avLock),
|
|
2765
|
+
timeLimitMinutes: whole(o["time_limit_minutes"], 0),
|
|
2766
|
+
timeLimitWarningMinutes: whole(o["time_limit_warning_minutes"], DEFAULT_LIVE_POLICY.timeLimitWarningMinutes),
|
|
2767
|
+
recordingConsent: oneOf(
|
|
2768
|
+
o["recording_consent"],
|
|
2769
|
+
["notice", "ok_or_leave", "view_only_until_agree"],
|
|
2770
|
+
DEFAULT_LIVE_POLICY.recordingConsent
|
|
2771
|
+
)
|
|
2772
|
+
};
|
|
2773
|
+
}
|
|
2774
|
+
function samePolicy(a, b) {
|
|
2775
|
+
return a.chatMode === b.chatMode && a.avLock === b.avLock && a.timeLimitMinutes === b.timeLimitMinutes && a.timeLimitWarningMinutes === b.timeLimitWarningMinutes && a.recordingConsent === b.recordingConsent;
|
|
2776
|
+
}
|
|
2777
|
+
var MODERATORS = /* @__PURE__ */ new Set(["host", "cohost"]);
|
|
2778
|
+
function isLockedFor(policy, role, kind) {
|
|
2779
|
+
if (MODERATORS.has(role)) return false;
|
|
2780
|
+
return policy.avLock === "both" || (kind === "microphone" ? policy.avLock === "mic" : policy.avLock === "camera");
|
|
2781
|
+
}
|
|
2782
|
+
function consentPending(policy, role, recordingOn, given) {
|
|
2783
|
+
return recordingOn && !given && policy.recordingConsent !== "notice" && !MODERATORS.has(role);
|
|
2784
|
+
}
|
|
2785
|
+
function canChat(policy, role) {
|
|
2786
|
+
if (policy.chatMode === "everyone") return true;
|
|
2787
|
+
return policy.chatMode === "hosts_only" && MODERATORS.has(role);
|
|
2788
|
+
}
|
|
2789
|
+
function minutesLeft(policy, startedAtMs, nowMs) {
|
|
2790
|
+
if (policy.timeLimitMinutes <= 0 || startedAtMs === null) return null;
|
|
2791
|
+
return Math.ceil((startedAtMs + policy.timeLimitMinutes * 6e4 - nowMs) / 6e4);
|
|
2792
|
+
}
|
|
2793
|
+
|
|
2704
2794
|
// src/core/attendance.ts
|
|
2705
2795
|
var IDLE_MEDIA_REGION = {
|
|
2706
2796
|
permission: { microphone: "unknown", camera: "unknown" },
|
|
@@ -3827,6 +3917,8 @@ function planFromRow(row) {
|
|
|
3827
3917
|
minutes: num2(row["minutes"]) ?? 0,
|
|
3828
3918
|
openedAt: str(row["opened_at"]),
|
|
3829
3919
|
endsAt: str(row["ends_at"]),
|
|
3920
|
+
closingAt: str(row["closing_at"]),
|
|
3921
|
+
moveMode: row["move_mode"] === "auto" ? "auto" : "invite",
|
|
3830
3922
|
closedAt: str(row["closed_at"]),
|
|
3831
3923
|
broadcasts: (Array.isArray(row["broadcasts"]) ? row["broadcasts"] : []).map(broadcastFrom).filter((b) => b !== null)
|
|
3832
3924
|
};
|
|
@@ -3978,9 +4070,17 @@ function autoAssign(identities, rooms, exclude = []) {
|
|
|
3978
4070
|
return out;
|
|
3979
4071
|
}
|
|
3980
4072
|
function breakoutRemainingMs(plan, now) {
|
|
3981
|
-
if (plan === null || plan.state !== "open"
|
|
3982
|
-
const
|
|
3983
|
-
|
|
4073
|
+
if (plan === null || plan.state !== "open") return null;
|
|
4074
|
+
const ends = [plan.endsAt, plan.closingAt].map((stamp) => stamp === null ? Number.NaN : Date.parse(stamp)).filter((time) => !Number.isNaN(time));
|
|
4075
|
+
if (ends.length === 0) return null;
|
|
4076
|
+
return Math.max(0, Math.min(...ends) - now);
|
|
4077
|
+
}
|
|
4078
|
+
var BREAKOUT_COUNTDOWN_MS = 3e4;
|
|
4079
|
+
function breakoutClosingMs(plan, now) {
|
|
4080
|
+
if (plan === null || plan.state !== "open") return null;
|
|
4081
|
+
const remaining = breakoutRemainingMs(plan, now);
|
|
4082
|
+
if (remaining === null) return null;
|
|
4083
|
+
return plan.closingAt !== null || remaining <= BREAKOUT_COUNTDOWN_MS ? remaining : null;
|
|
3984
4084
|
}
|
|
3985
4085
|
function defaultCaptionLanguage(settings, viewerLanguage) {
|
|
3986
4086
|
const configured = settings?.captionTranslationLanguage.trim() ?? "";
|
|
@@ -4157,6 +4257,11 @@ var EMPTY = {
|
|
|
4157
4257
|
presenter: null,
|
|
4158
4258
|
waitingCount: 0,
|
|
4159
4259
|
leavePolicy: DEFAULT_LEAVE_POLICY,
|
|
4260
|
+
livePolicy: DEFAULT_LIVE_POLICY,
|
|
4261
|
+
canReclaim: false,
|
|
4262
|
+
recordingConsentGiven: false,
|
|
4263
|
+
sessionStartedAt: null,
|
|
4264
|
+
mutedByHost: false,
|
|
4160
4265
|
moderationNotice: null,
|
|
4161
4266
|
actionNotice: null,
|
|
4162
4267
|
privateChatRequest: null,
|
|
@@ -4166,6 +4271,8 @@ var EMPTY = {
|
|
|
4166
4271
|
names: {},
|
|
4167
4272
|
wrapUp: null,
|
|
4168
4273
|
noteTakerRefusal: null,
|
|
4274
|
+
captionsOn: false,
|
|
4275
|
+
captionsRefusal: null,
|
|
4169
4276
|
media: IDLE_MEDIA,
|
|
4170
4277
|
mediaRegion: IDLE_MEDIA_REGION,
|
|
4171
4278
|
failure: null,
|
|
@@ -4370,7 +4477,12 @@ function createMeetStore(initial = {}) {
|
|
|
4370
4477
|
if (current.enabled === next.enabled && current.unavailable?.code === next.unavailable?.code && current.unavailable?.reason === next.unavailable?.reason && current.unavailable?.message === next.unavailable?.message) {
|
|
4371
4478
|
return;
|
|
4372
4479
|
}
|
|
4373
|
-
commit({
|
|
4480
|
+
commit({
|
|
4481
|
+
...state,
|
|
4482
|
+
media: { ...state.media, [kind]: next },
|
|
4483
|
+
// The person turned their own microphone on again: the host's mute is over.
|
|
4484
|
+
...kind === "microphone" && next.enabled && state.mutedByHost ? { mutedByHost: false } : {}
|
|
4485
|
+
});
|
|
4374
4486
|
},
|
|
4375
4487
|
reset() {
|
|
4376
4488
|
const phase = nextPhase(state.phase, { type: "reset", teardown: true }) ?? EMPTY.phase;
|
|
@@ -4432,6 +4544,7 @@ function applyDoorRow(store, attendee) {
|
|
|
4432
4544
|
function decidedState(state) {
|
|
4433
4545
|
return WAITING_ADMISSION_STATES.includes(state) ? "expired" : state;
|
|
4434
4546
|
}
|
|
4547
|
+
var LIVE_POLICY_POLL_MS = 3e3;
|
|
4435
4548
|
function createMeetingSession(options) {
|
|
4436
4549
|
const { manager, repository, store, identity } = options;
|
|
4437
4550
|
let channel = null;
|
|
@@ -4573,6 +4686,46 @@ function createMeetingSession(options) {
|
|
|
4573
4686
|
stopWaiting();
|
|
4574
4687
|
}
|
|
4575
4688
|
}
|
|
4689
|
+
let policyTimer = null;
|
|
4690
|
+
let policyReading = false;
|
|
4691
|
+
async function readLivePolicy() {
|
|
4692
|
+
const meeting = store.snapshot().meeting;
|
|
4693
|
+
const pass = options.resolvePass?.() ?? null;
|
|
4694
|
+
if (meeting === null || pass === null || policyReading) return;
|
|
4695
|
+
policyReading = true;
|
|
4696
|
+
try {
|
|
4697
|
+
const response = await options.api.request({
|
|
4698
|
+
path: `${MEET_ROUTES.state}?meeting_id=${encodeURIComponent(meeting.id)}`,
|
|
4699
|
+
method: "GET",
|
|
4700
|
+
requireAuth: false,
|
|
4701
|
+
operation: "meet.state(policy)",
|
|
4702
|
+
headers: { [MEETING_PASS_HEADER]: pass }
|
|
4703
|
+
});
|
|
4704
|
+
if (!response.ok) return;
|
|
4705
|
+
const read = await response.json();
|
|
4706
|
+
const next = livePolicyFrom(read.live_policy);
|
|
4707
|
+
const started = read.session_started_at ? Date.parse(read.session_started_at) : NaN;
|
|
4708
|
+
const snapshot = store.snapshot();
|
|
4709
|
+
const startedAt = Number.isFinite(started) ? started : snapshot.sessionStartedAt;
|
|
4710
|
+
if (!samePolicy(snapshot.livePolicy, next) || startedAt !== snapshot.sessionStartedAt) {
|
|
4711
|
+
store.patch({ livePolicy: next, sessionStartedAt: startedAt });
|
|
4712
|
+
}
|
|
4713
|
+
} catch {
|
|
4714
|
+
} finally {
|
|
4715
|
+
policyReading = false;
|
|
4716
|
+
}
|
|
4717
|
+
}
|
|
4718
|
+
function syncLivePolicyTimer() {
|
|
4719
|
+
const inCall = store.snapshot().phase === "in_call";
|
|
4720
|
+
if (inCall && policyTimer === null) {
|
|
4721
|
+
void readLivePolicy();
|
|
4722
|
+
policyTimer = setInterval(() => void readLivePolicy(), LIVE_POLICY_POLL_MS);
|
|
4723
|
+
} else if (!inCall && policyTimer !== null) {
|
|
4724
|
+
clearInterval(policyTimer);
|
|
4725
|
+
policyTimer = null;
|
|
4726
|
+
}
|
|
4727
|
+
}
|
|
4728
|
+
const unsubscribePolicy = store.subscribe(syncLivePolicyTimer);
|
|
4576
4729
|
async function readState2() {
|
|
4577
4730
|
if (reading !== null) return reading;
|
|
4578
4731
|
const meeting = store.snapshot().meeting;
|
|
@@ -4959,6 +5112,9 @@ function createMeetingSession(options) {
|
|
|
4959
5112
|
},
|
|
4960
5113
|
dispose() {
|
|
4961
5114
|
stopWaiting();
|
|
5115
|
+
unsubscribePolicy();
|
|
5116
|
+
if (policyTimer !== null) clearInterval(policyTimer);
|
|
5117
|
+
policyTimer = null;
|
|
4962
5118
|
channel?.close();
|
|
4963
5119
|
channel = null;
|
|
4964
5120
|
meetingChannel?.close();
|
|
@@ -5360,8 +5516,7 @@ var ROOM_EVENTS = {
|
|
|
5360
5516
|
/**
|
|
5361
5517
|
* A host or co-host acted (Meet wave 2). Payload `{ meeting_id, kind, … }`:
|
|
5362
5518
|
* `muted {source, by}` · `ask-unmute {by}` · `removed {by}` — addressed to the
|
|
5363
|
-
* person concerned; `
|
|
5364
|
-
* role}` — to everyone.
|
|
5519
|
+
* person concerned; `role {identity, role}` — to everyone.
|
|
5365
5520
|
*/
|
|
5366
5521
|
moderation: "matrx.meet.moderation",
|
|
5367
5522
|
/**
|
|
@@ -5549,10 +5704,11 @@ function moderationText(kind, payload) {
|
|
|
5549
5704
|
switch (kind) {
|
|
5550
5705
|
case "muted": {
|
|
5551
5706
|
const source = text2(payload["source"]) ?? "microphone";
|
|
5552
|
-
|
|
5707
|
+
const who = payload["by_role"] === "host" || payload["by_role"] === "cohost" ? "the host" : by;
|
|
5708
|
+
return source === "microphone" ? `You've been muted by ${who}.` : source === "camera" ? `Your camera was turned off by ${who}.` : `Your screen share was stopped by ${who}.`;
|
|
5553
5709
|
}
|
|
5554
5710
|
case "ask-unmute":
|
|
5555
|
-
return `${by}
|
|
5711
|
+
return `${by === "The host" ? "The host" : by} asked you to unmute.`;
|
|
5556
5712
|
case "removed":
|
|
5557
5713
|
return `${by} removed you from this meeting.`;
|
|
5558
5714
|
default:
|
|
@@ -5578,7 +5734,7 @@ function applyModeration(store, payload, now) {
|
|
|
5578
5734
|
grants: { ...snapshot.grants, role },
|
|
5579
5735
|
moderationNotice: {
|
|
5580
5736
|
kind: "role",
|
|
5581
|
-
text: role === "host" ? "You are now the host." : role === "cohost" ? "You
|
|
5737
|
+
text: role === "host" ? "You are now the host." : role === "cohost" ? "You're now a co-host." : role === "presenter" ? "You're now a presenter." : snapshot.grants.role === "presenter" ? "You're now a participant: you can no longer present." : "You're now a participant: you are no longer a co-host.",
|
|
5582
5738
|
at: now()
|
|
5583
5739
|
}
|
|
5584
5740
|
});
|
|
@@ -5590,7 +5746,10 @@ function applyModeration(store, payload, now) {
|
|
|
5590
5746
|
case "removed": {
|
|
5591
5747
|
const sentence = moderationText(kind, payload);
|
|
5592
5748
|
if (sentence === null) return ignored("a moderation event with no sentence");
|
|
5593
|
-
store.patch({
|
|
5749
|
+
store.patch({
|
|
5750
|
+
moderationNotice: { kind, text: sentence, at: now() },
|
|
5751
|
+
...kind === "muted" && (text2(payload["source"]) ?? "microphone") === "microphone" ? { mutedByHost: true } : {}
|
|
5752
|
+
});
|
|
5594
5753
|
return HANDLED;
|
|
5595
5754
|
}
|
|
5596
5755
|
default:
|
|
@@ -5629,7 +5788,7 @@ function exactNoteTakerParticipant(meeting, participants) {
|
|
|
5629
5788
|
}
|
|
5630
5789
|
function noteTakerStatus(args) {
|
|
5631
5790
|
const present = exactNoteTakerParticipant(args.meeting, args.participants) !== null;
|
|
5632
|
-
const raw = args.meeting?.metadata[NOTE_TAKER_METADATA_KEY];
|
|
5791
|
+
const raw = args.meeting?.metadata?.[NOTE_TAKER_METADATA_KEY];
|
|
5633
5792
|
const row = typeof raw === "object" && raw !== null && !Array.isArray(raw) ? raw : {};
|
|
5634
5793
|
const recorded = readState(row["state"]);
|
|
5635
5794
|
const detail = typeof row["reason"] === "string" && row["reason"].length > 0 ? row["reason"] : null;
|
|
@@ -6106,6 +6265,7 @@ function createRoomEngine(options) {
|
|
|
6106
6265
|
lastServerUrl = token.serverUrl;
|
|
6107
6266
|
connectionPolicy = token.connectionPolicy ?? DEFAULT_CONNECTION_POLICY;
|
|
6108
6267
|
if (token.leavePolicy !== void 0) store.patch({ leavePolicy: token.leavePolicy });
|
|
6268
|
+
store.patch({ canReclaim: token.canReclaim === true });
|
|
6109
6269
|
store.patch({
|
|
6110
6270
|
localIdentity: token.identity,
|
|
6111
6271
|
breakoutRoomId: token.breakoutRoomId ?? null,
|
|
@@ -6600,13 +6760,17 @@ var MODERATION_ACTIONS = [
|
|
|
6600
6760
|
"ask_unmute",
|
|
6601
6761
|
"ask_all_unmute",
|
|
6602
6762
|
"spotlight",
|
|
6603
|
-
"
|
|
6763
|
+
"sync_presenter",
|
|
6604
6764
|
"raise_hand",
|
|
6605
6765
|
"lower_hand",
|
|
6606
6766
|
"lower_all_hands",
|
|
6607
6767
|
"make_cohost",
|
|
6768
|
+
"make_presenter",
|
|
6769
|
+
"revoke_presenter",
|
|
6770
|
+
"set_av_lock",
|
|
6608
6771
|
"revoke_cohost",
|
|
6609
6772
|
"transfer_host",
|
|
6773
|
+
"reclaim_host",
|
|
6610
6774
|
"rename",
|
|
6611
6775
|
"remove",
|
|
6612
6776
|
"report"
|
|
@@ -6632,18 +6796,17 @@ function createInRoomClient(options) {
|
|
|
6632
6796
|
function refusal2(response, operation, remedy) {
|
|
6633
6797
|
return refusalFromResponse(response, operation, remedy);
|
|
6634
6798
|
}
|
|
6635
|
-
let
|
|
6799
|
+
let toldSharing = false;
|
|
6636
6800
|
let tellChain = Promise.resolve();
|
|
6637
6801
|
store.subscribe(() => {
|
|
6638
6802
|
const local = store.snapshot().participants.find((p) => p.isLocal);
|
|
6639
6803
|
const sharing = local?.screenSharing === true;
|
|
6640
|
-
if (sharing ===
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
tellChain = tellChain.then(() => client.moderate({ action: "present", on })).then(
|
|
6804
|
+
if (sharing === toldSharing || local === void 0) return;
|
|
6805
|
+
toldSharing = sharing;
|
|
6806
|
+
tellChain = tellChain.then(() => client.moderate({ action: "sync_presenter" })).then(
|
|
6644
6807
|
() => void 0,
|
|
6645
6808
|
(error) => {
|
|
6646
|
-
console.warn(`[meet] the server did not take
|
|
6809
|
+
console.warn(`[meet] the server did not take the screen-share change: ${String(error)}`);
|
|
6647
6810
|
}
|
|
6648
6811
|
);
|
|
6649
6812
|
});
|
|
@@ -6660,8 +6823,7 @@ function createInRoomClient(options) {
|
|
|
6660
6823
|
action: request.action,
|
|
6661
6824
|
...request.identity != null ? { identity: request.identity } : {},
|
|
6662
6825
|
...request.name !== void 0 ? { name: request.name } : {},
|
|
6663
|
-
...request.reason !== void 0 ? { reason: request.reason } : {}
|
|
6664
|
-
...request.on !== void 0 ? { on: request.on } : {}
|
|
6826
|
+
...request.reason !== void 0 ? { reason: request.reason } : {}
|
|
6665
6827
|
},
|
|
6666
6828
|
...hdrs !== void 0 ? { headers: hdrs } : {}
|
|
6667
6829
|
});
|
|
@@ -7646,11 +7808,13 @@ var import_react3 = require("react");
|
|
|
7646
7808
|
|
|
7647
7809
|
// src/core/observation.ts
|
|
7648
7810
|
function observedRole(role, standing) {
|
|
7649
|
-
if (role === "host" || role === "cohost") return role;
|
|
7811
|
+
if (role === "host" || role === "cohost" || role === "presenter") return role;
|
|
7650
7812
|
return isLinkFollower(standing) ? "guest" : "participant";
|
|
7651
7813
|
}
|
|
7652
|
-
function observedDevice(track, permission = "unknown") {
|
|
7814
|
+
function observedDevice(track, permission = "unknown", held = null) {
|
|
7815
|
+
if (held === "locked") return "locked";
|
|
7653
7816
|
if (track.enabled) return "on";
|
|
7817
|
+
if (held === "muted_by_host") return "muted_by_host";
|
|
7654
7818
|
const reason = deviceUnavailableReason(track, permission);
|
|
7655
7819
|
return reason === null ? "muted_by_me" : `unavailable:${reason}`;
|
|
7656
7820
|
}
|
|
@@ -7687,10 +7851,20 @@ function observe(input) {
|
|
|
7687
7851
|
recording: snapshot?.recording === "recording" || snapshot?.recording === "stopping",
|
|
7688
7852
|
// S6c: the autoplay region is known only inside the room (no remote audio exists elsewhere).
|
|
7689
7853
|
audioBlocked: inCall && snapshot !== null ? snapshot.mediaRegion.audioOutput === "blocked" : null,
|
|
7690
|
-
camera: deviceInPlay && snapshot !== null ? observedDevice(snapshot.media.camera, snapshot.mediaRegion.permission.camera) : null,
|
|
7691
|
-
microphone: deviceInPlay && snapshot !== null ? observedDevice(snapshot.media.microphone, snapshot.mediaRegion.permission.microphone) : null
|
|
7854
|
+
camera: deviceInPlay && snapshot !== null ? observedDevice(snapshot.media.camera, snapshot.mediaRegion.permission.camera, lockedFor(snapshot, "camera", inCall)) : null,
|
|
7855
|
+
microphone: deviceInPlay && snapshot !== null ? observedDevice(snapshot.media.microphone, snapshot.mediaRegion.permission.microphone, lockedFor(snapshot, "microphone", inCall)) : null
|
|
7692
7856
|
};
|
|
7693
7857
|
}
|
|
7858
|
+
function lockedFor(snapshot, kind, inCall) {
|
|
7859
|
+
if (!inCall) return null;
|
|
7860
|
+
const role = effectiveRole(snapshot);
|
|
7861
|
+
if (isLockedFor(snapshot.livePolicy, role, kind)) return "locked";
|
|
7862
|
+
if (snapshot.livePolicy.recordingConsent === "view_only_until_agree" && consentPending(snapshot.livePolicy, role, snapshot.recording === "recording", snapshot.recordingConsentGiven)) {
|
|
7863
|
+
return "locked";
|
|
7864
|
+
}
|
|
7865
|
+
if (kind === "microphone" && snapshot.mutedByHost) return "muted_by_host";
|
|
7866
|
+
return null;
|
|
7867
|
+
}
|
|
7694
7868
|
function staticObservation(phase, reason = null) {
|
|
7695
7869
|
return {
|
|
7696
7870
|
phase,
|
|
@@ -8880,6 +9054,45 @@ function useMeetAi() {
|
|
|
8880
9054
|
}, [ai, meeting, dispatchNoteTaker])
|
|
8881
9055
|
};
|
|
8882
9056
|
}
|
|
9057
|
+
function useCaptions() {
|
|
9058
|
+
const host = useMeetHost();
|
|
9059
|
+
const snapshot = useMeetSnapshot();
|
|
9060
|
+
const ai = useMeetAi();
|
|
9061
|
+
const on = snapshot?.captionsOn === true;
|
|
9062
|
+
const refusal2 = snapshot?.captionsRefusal ?? null;
|
|
9063
|
+
const taker = ai.noteTaker;
|
|
9064
|
+
const meeting = snapshot?.meeting ?? null;
|
|
9065
|
+
const request = (0, import_react4.useCallback)(() => {
|
|
9066
|
+
if (host === null || meeting === null) return;
|
|
9067
|
+
void host.ai.requestCaptions({ meetingId: meeting.id });
|
|
9068
|
+
}, [host, meeting]);
|
|
9069
|
+
const toggle = (0, import_react4.useCallback)(() => {
|
|
9070
|
+
if (host === null) return;
|
|
9071
|
+
const next = !on;
|
|
9072
|
+
host.store.patch({ captionsOn: next, captionsRefusal: null });
|
|
9073
|
+
if (next && taker.state !== "joining" && taker.state !== "transcribing") request();
|
|
9074
|
+
}, [host, on, taker.state, request]);
|
|
9075
|
+
let state = "off";
|
|
9076
|
+
let reason = null;
|
|
9077
|
+
let remedy = null;
|
|
9078
|
+
if (on) {
|
|
9079
|
+
if (taker.state === "transcribing" && taker.present) {
|
|
9080
|
+
state = "live";
|
|
9081
|
+
} else if (taker.state === "joining") {
|
|
9082
|
+
state = "starting";
|
|
9083
|
+
} else if (refusal2 !== null && refusal2.reason.length > 0) {
|
|
9084
|
+
state = "unavailable";
|
|
9085
|
+
reason = refusal2.reason;
|
|
9086
|
+
remedy = refusal2.remedy.length > 0 ? refusal2.remedy : null;
|
|
9087
|
+
} else if (taker.state === "ended" || taker.state === "handoff_pending") {
|
|
9088
|
+
state = "unavailable";
|
|
9089
|
+
reason = noteTakerLabel(taker);
|
|
9090
|
+
} else {
|
|
9091
|
+
state = "starting";
|
|
9092
|
+
}
|
|
9093
|
+
}
|
|
9094
|
+
return { on, state, reason, remedy, toggle };
|
|
9095
|
+
}
|
|
8883
9096
|
function useEndMeeting() {
|
|
8884
9097
|
const host = useMeetHost();
|
|
8885
9098
|
const snapshot = useMeetSnapshot();
|
|
@@ -8917,7 +9130,7 @@ function useConsentNotice() {
|
|
|
8917
9130
|
const snapshot = useMeetSnapshot();
|
|
8918
9131
|
const agent = noteTakerParticipant(snapshot?.participants ?? []);
|
|
8919
9132
|
if (agent === null) return null;
|
|
8920
|
-
return
|
|
9133
|
+
return `AI notes are on. ${agent.displayName} is in this meeting, transcribing what is said and writing notes everyone here can read.`;
|
|
8921
9134
|
}
|
|
8922
9135
|
function useMediaSupervisor() {
|
|
8923
9136
|
const host = useMeetHost();
|
|
@@ -9381,6 +9594,38 @@ function useGuestRecordAccess(meeting) {
|
|
|
9381
9594
|
)
|
|
9382
9595
|
};
|
|
9383
9596
|
}
|
|
9597
|
+
function useLivePolicy() {
|
|
9598
|
+
const snapshot = useMeetSnapshot();
|
|
9599
|
+
const role = useRole();
|
|
9600
|
+
const [now, setNow] = (0, import_react4.useState)(() => Date.now());
|
|
9601
|
+
const limited = (snapshot?.livePolicy.timeLimitMinutes ?? 0) > 0;
|
|
9602
|
+
(0, import_react4.useEffect)(() => {
|
|
9603
|
+
if (!limited) return void 0;
|
|
9604
|
+
const timer = setInterval(() => setNow(Date.now()), 1e3);
|
|
9605
|
+
return () => clearInterval(timer);
|
|
9606
|
+
}, [limited]);
|
|
9607
|
+
const policy = snapshot?.livePolicy ?? DEFAULT_LIVE_POLICY;
|
|
9608
|
+
const left = minutesLeft(policy, snapshot?.sessionStartedAt ?? null, now);
|
|
9609
|
+
const host = useMeetHost();
|
|
9610
|
+
const pending = consentPending(policy, role, snapshot?.recording === "recording", snapshot?.recordingConsentGiven === true);
|
|
9611
|
+
const viewOnly = pending && policy.recordingConsent === "view_only_until_agree";
|
|
9612
|
+
const idle = snapshot !== null && snapshot.recording !== "recording" && snapshot.recording !== "starting" && snapshot.recording !== "stopping";
|
|
9613
|
+
const given = snapshot?.recordingConsentGiven === true;
|
|
9614
|
+
const store = host?.store ?? null;
|
|
9615
|
+
(0, import_react4.useEffect)(() => {
|
|
9616
|
+
if (idle && given) store?.patch({ recordingConsentGiven: false });
|
|
9617
|
+
}, [idle, given, store]);
|
|
9618
|
+
return {
|
|
9619
|
+
canChat: canChat(policy, role),
|
|
9620
|
+
chatMode: policy.chatMode,
|
|
9621
|
+
micLocked: isLockedFor(policy, role, "microphone") || viewOnly,
|
|
9622
|
+
cameraLocked: isLockedFor(policy, role, "camera") || viewOnly,
|
|
9623
|
+
consent: pending ? policy.recordingConsent === "ok_or_leave" ? "ok_or_leave" : "view_only_until_agree" : null,
|
|
9624
|
+
agree: () => store?.patch({ recordingConsentGiven: true }),
|
|
9625
|
+
minutesLeft: left,
|
|
9626
|
+
timeWarning: left !== null && left <= policy.timeLimitWarningMinutes
|
|
9627
|
+
};
|
|
9628
|
+
}
|
|
9384
9629
|
|
|
9385
9630
|
// src/react/skin-root.tsx
|
|
9386
9631
|
var import_react12 = require("react");
|
|
@@ -10155,6 +10400,18 @@ function SparklesIcon(props) {
|
|
|
10155
10400
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("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" })
|
|
10156
10401
|
] });
|
|
10157
10402
|
}
|
|
10403
|
+
function CaptionsIcon(props) {
|
|
10404
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Icon, { ...props, children: [
|
|
10405
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
|
|
10406
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M10 10.5a2 2 0 1 0 0 3M16 10.5a2 2 0 1 0 0 3" })
|
|
10407
|
+
] });
|
|
10408
|
+
}
|
|
10409
|
+
function NotesIcon(props) {
|
|
10410
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Icon, { ...props, children: [
|
|
10411
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M4 20l1-4L16.5 4.5a2.1 2.1 0 0 1 3 3L8 19l-4 1Z" }),
|
|
10412
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M14 7l3 3" })
|
|
10413
|
+
] });
|
|
10414
|
+
}
|
|
10158
10415
|
function LockIcon(props) {
|
|
10159
10416
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Icon, { ...props, children: [
|
|
10160
10417
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("rect", { x: "4", y: "10", width: "16", height: "11", rx: "2" }),
|
|
@@ -11061,7 +11318,7 @@ function BreakoutRun({ plan }) {
|
|
|
11061
11318
|
type: "button",
|
|
11062
11319
|
className: "mx-meet__primary mx-meet__primary--small",
|
|
11063
11320
|
onClick: () => void act({ action: "breakout_close" }).then(show),
|
|
11064
|
-
children: "
|
|
11321
|
+
children: "Close rooms"
|
|
11065
11322
|
}
|
|
11066
11323
|
) : null
|
|
11067
11324
|
] });
|
|
@@ -11079,9 +11336,14 @@ function BreakoutBanner() {
|
|
|
11079
11336
|
const { collab, act, moveTo, localIdentity, breakoutRoomId } = useCollab();
|
|
11080
11337
|
const plan = collab?.breakout ?? null;
|
|
11081
11338
|
const open = plan?.state === "open" ? plan : null;
|
|
11082
|
-
const now = useNow(open?.endsAt != null);
|
|
11339
|
+
const now = useNow(open?.endsAt != null || open?.closingAt != null);
|
|
11083
11340
|
const remaining = breakoutRemainingMs(open, now);
|
|
11341
|
+
const closing = breakoutClosingMs(open, now);
|
|
11084
11342
|
const assigned = assignedRoom(open, localIdentity);
|
|
11343
|
+
const [later, setLater] = (0, import_react9.useState)(null);
|
|
11344
|
+
const [autoSince, setAutoSince] = (0, import_react9.useState)(null);
|
|
11345
|
+
const AUTO_MOVE_MS = 1e4;
|
|
11346
|
+
const autoLeft = open?.moveMode === "auto" && assigned !== null && autoSince?.id === open.id && later !== open.id ? Math.max(0, AUTO_MOVE_MS - (now - autoSince.at)) : null;
|
|
11085
11347
|
const [dismissedBroadcast, setDismissedBroadcast] = (0, import_react9.useState)(null);
|
|
11086
11348
|
const [failure, setFailure] = (0, import_react9.useState)(null);
|
|
11087
11349
|
const expireAsked = (0, import_react9.useRef)(null);
|
|
@@ -11094,6 +11356,19 @@ function BreakoutBanner() {
|
|
|
11094
11356
|
if ((here ?? null) === request.roomId) return;
|
|
11095
11357
|
void moveTo(request.roomId).then((result) => setFailure(result.ok ? null : result.message));
|
|
11096
11358
|
}, [moveAt, host, moveTo]);
|
|
11359
|
+
const joinAssigned = async () => {
|
|
11360
|
+
if (assigned === null) return;
|
|
11361
|
+
const said = await act({ action: "breakout_join", roomId: assigned.id });
|
|
11362
|
+
const result = said.ok ? await moveTo(assigned.id) : said;
|
|
11363
|
+
setFailure(result.ok ? null : result.message);
|
|
11364
|
+
};
|
|
11365
|
+
(0, import_react9.useEffect)(() => {
|
|
11366
|
+
if (open === null || open.moveMode !== "auto" || assigned === null || breakoutRoomId !== null) return;
|
|
11367
|
+
if (autoSince?.id !== open.id) setAutoSince({ id: open.id, at: Date.now() });
|
|
11368
|
+
}, [open, assigned, breakoutRoomId, autoSince]);
|
|
11369
|
+
(0, import_react9.useEffect)(() => {
|
|
11370
|
+
if (autoLeft === 0) void joinAssigned();
|
|
11371
|
+
}, [autoLeft]);
|
|
11097
11372
|
(0, import_react9.useEffect)(() => {
|
|
11098
11373
|
if (open === null || remaining === null || remaining > 0) return;
|
|
11099
11374
|
const asked = expireAsked.current;
|
|
@@ -11107,27 +11382,25 @@ function BreakoutBanner() {
|
|
|
11107
11382
|
if (open === null && failure === null) return null;
|
|
11108
11383
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet__breakout-banner", role: "status", children: [
|
|
11109
11384
|
failure !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__collab-error", children: failure }) : null,
|
|
11385
|
+
closing !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { role: "status", "data-meet-notice": "breakout-closing", children: [
|
|
11386
|
+
"Rooms closing in ",
|
|
11387
|
+
Math.ceil(closing / 1e3),
|
|
11388
|
+
room !== null ? " \u2014 you return to the main meeting" : ""
|
|
11389
|
+
] }) : null,
|
|
11110
11390
|
room !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { children: [
|
|
11111
11391
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { children: room.name }),
|
|
11112
|
-
remaining !== null ? ` \xB7 ${clock(remaining)} left` : "",
|
|
11392
|
+
remaining !== null && closing === null ? ` \xB7 ${clock(remaining)} left` : "",
|
|
11113
11393
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mx-meet__chip", onClick: () => void moveTo(null), children: "Return to main room" })
|
|
11394
|
+
] }) : assigned !== null && later !== open?.id ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { children: [
|
|
11395
|
+
autoLeft !== null ? `You're being moved to ${assigned.name} in ${Math.ceil(autoLeft / 1e3)} s` : `You're invited to ${assigned.name}`,
|
|
11396
|
+
remaining !== null && closing === null ? ` \xB7 ${clock(remaining)} left` : "",
|
|
11397
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mx-meet__primary mx-meet__primary--small", onClick: () => void joinAssigned(), children: "Join room" }),
|
|
11398
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mx-meet__chip", onClick: () => setLater(open?.id ?? null), children: "Later" })
|
|
11114
11399
|
] }) : assigned !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { children: [
|
|
11115
|
-
|
|
11116
|
-
|
|
11117
|
-
|
|
11118
|
-
|
|
11119
|
-
"button",
|
|
11120
|
-
{
|
|
11121
|
-
type: "button",
|
|
11122
|
-
className: "mx-meet__primary mx-meet__primary--small",
|
|
11123
|
-
onClick: () => void act({ action: "breakout_join", roomId: assigned.id }).then(async (said) => {
|
|
11124
|
-
const result = said.ok ? await moveTo(assigned.id) : said;
|
|
11125
|
-
setFailure(result.ok ? null : result.message);
|
|
11126
|
-
}),
|
|
11127
|
-
children: "Join"
|
|
11128
|
-
}
|
|
11129
|
-
)
|
|
11130
|
-
] }) : open?.allowChoose ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Breakout rooms are open \u2014 pick one under Activities." }) : null,
|
|
11400
|
+
assigned.name,
|
|
11401
|
+
" is open",
|
|
11402
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mx-meet__chip", onClick: () => void joinAssigned(), children: "Join room" })
|
|
11403
|
+
] }) : open?.allowChoose ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Rooms are open \u2014 pick one under Activities." }) : null,
|
|
11131
11404
|
showBroadcast ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "mx-meet__breakout-broadcast", children: [
|
|
11132
11405
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("strong", { children: [
|
|
11133
11406
|
broadcast.by,
|
|
@@ -11175,6 +11448,33 @@ function CaptionLanguageSettings() {
|
|
|
11175
11448
|
collab?.captionTranslationError != null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__panel-note mx-meet__collab-error", children: collab.captionTranslationError }) : null
|
|
11176
11449
|
] });
|
|
11177
11450
|
}
|
|
11451
|
+
function CaptionsControl() {
|
|
11452
|
+
const captions = useCaptions();
|
|
11453
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
11454
|
+
ControlButton,
|
|
11455
|
+
{
|
|
11456
|
+
label: captions.on ? "Turn off captions" : "Turn on captions",
|
|
11457
|
+
active: captions.on,
|
|
11458
|
+
pressed: captions.on,
|
|
11459
|
+
onClick: captions.toggle,
|
|
11460
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CaptionsIcon, {})
|
|
11461
|
+
}
|
|
11462
|
+
);
|
|
11463
|
+
}
|
|
11464
|
+
function TakeNotesControl() {
|
|
11465
|
+
const ai = useMeetAi();
|
|
11466
|
+
if (!ai.canControlNoteTaker) return null;
|
|
11467
|
+
const running = ai.noteTaker.state === "joining" || ai.noteTaker.state === "transcribing";
|
|
11468
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
11469
|
+
ControlButton,
|
|
11470
|
+
{
|
|
11471
|
+
label: running ? "Stop taking notes" : "Take notes for me",
|
|
11472
|
+
active: running,
|
|
11473
|
+
onClick: () => void (running ? ai.stopNoteTaker() : ai.startNoteTaker()),
|
|
11474
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(NotesIcon, {})
|
|
11475
|
+
}
|
|
11476
|
+
);
|
|
11477
|
+
}
|
|
11178
11478
|
|
|
11179
11479
|
// src/skins/meet/components.tsx
|
|
11180
11480
|
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
@@ -11225,6 +11525,7 @@ function ControlButton({
|
|
|
11225
11525
|
label,
|
|
11226
11526
|
active = false,
|
|
11227
11527
|
danger = false,
|
|
11528
|
+
pressed,
|
|
11228
11529
|
onClick,
|
|
11229
11530
|
children
|
|
11230
11531
|
}) {
|
|
@@ -11239,26 +11540,49 @@ function ControlButton({
|
|
|
11239
11540
|
].filter(Boolean).join(" "),
|
|
11240
11541
|
"aria-label": label,
|
|
11241
11542
|
title: label,
|
|
11543
|
+
...pressed !== void 0 ? { "aria-pressed": pressed } : {},
|
|
11242
11544
|
onClick,
|
|
11243
11545
|
children
|
|
11244
11546
|
}
|
|
11245
11547
|
);
|
|
11246
11548
|
}
|
|
11247
11549
|
function RecordingIndicator() {
|
|
11248
|
-
const { state, label } = useRecording();
|
|
11249
|
-
|
|
11250
|
-
|
|
11251
|
-
|
|
11252
|
-
|
|
11253
|
-
|
|
11254
|
-
|
|
11255
|
-
|
|
11256
|
-
|
|
11257
|
-
|
|
11258
|
-
|
|
11259
|
-
|
|
11260
|
-
|
|
11261
|
-
);
|
|
11550
|
+
const { state, label, canStart } = useRecording();
|
|
11551
|
+
const snapshot = useMeetSnapshot();
|
|
11552
|
+
const previous = (0, import_react10.useRef)(state);
|
|
11553
|
+
const [stoppedAt, setStoppedAt] = (0, import_react10.useState)(null);
|
|
11554
|
+
(0, import_react10.useEffect)(() => {
|
|
11555
|
+
const was = previous.current;
|
|
11556
|
+
previous.current = state;
|
|
11557
|
+
if ((was === "recording" || was === "starting") && state !== "recording" && state !== "starting") {
|
|
11558
|
+
setStoppedAt(Date.now());
|
|
11559
|
+
const timer = setTimeout(() => setStoppedAt(null), 1e4);
|
|
11560
|
+
return () => clearTimeout(timer);
|
|
11561
|
+
}
|
|
11562
|
+
return void 0;
|
|
11563
|
+
}, [state]);
|
|
11564
|
+
const meetingId = snapshot?.meeting?.id ?? null;
|
|
11565
|
+
if (label === null && stoppedAt === null) return null;
|
|
11566
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
11567
|
+
label !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
11568
|
+
"span",
|
|
11569
|
+
{
|
|
11570
|
+
className: `mx-meet__recording mx-meet__recording--${state}`,
|
|
11571
|
+
role: "status",
|
|
11572
|
+
"aria-live": "polite",
|
|
11573
|
+
children: [
|
|
11574
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RecordIcon, { width: 10, height: 10 }),
|
|
11575
|
+
label
|
|
11576
|
+
]
|
|
11577
|
+
}
|
|
11578
|
+
) : null,
|
|
11579
|
+
stoppedAt !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mx-meet__recording", role: "status", "data-meet-notice": "recording-stopped", children: "Recording stopped" }) : null,
|
|
11580
|
+
state === "processing" ? (
|
|
11581
|
+
// rec-processing: the host is told it is being made ready (the indicator says Processing…).
|
|
11582
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("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." })
|
|
11583
|
+
) : null,
|
|
11584
|
+
state === "available" && canStart && meetingId !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("a", { className: "mx-meet__link", href: `/meetings/${meetingId}`, target: "_blank", rel: "noreferrer", children: "View recording" }) : null
|
|
11585
|
+
] });
|
|
11262
11586
|
}
|
|
11263
11587
|
function RoleBadge({
|
|
11264
11588
|
role,
|
|
@@ -11285,6 +11609,7 @@ function ParticipantTile({
|
|
|
11285
11609
|
const showVideo = participant.cameraEnabled || participant.screenSharing;
|
|
11286
11610
|
const pinnedHere = snapshot?.pinned === participant.identity;
|
|
11287
11611
|
const spotlit = snapshot?.spotlight === participant.identity;
|
|
11612
|
+
const presenting = snapshot?.presenter === participant.identity;
|
|
11288
11613
|
const handPosition = participant.handRaised ? queue.findIndex((entry) => entry.identity === participant.identity) + 1 : 0;
|
|
11289
11614
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
11290
11615
|
"div",
|
|
@@ -11296,6 +11621,7 @@ function ParticipantTile({
|
|
|
11296
11621
|
].filter(Boolean).join(" "),
|
|
11297
11622
|
"data-identity": participant.identity,
|
|
11298
11623
|
...participantAttributes(participant),
|
|
11624
|
+
...presenting ? { "data-meet-participant-presenting": "true" } : {},
|
|
11299
11625
|
children: [
|
|
11300
11626
|
showVideo ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
11301
11627
|
"video",
|
|
@@ -11307,6 +11633,7 @@ function ParticipantTile({
|
|
|
11307
11633
|
muted: participant.isLocal
|
|
11308
11634
|
}
|
|
11309
11635
|
) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mx-meet__tile-placeholder", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Avatar, { name: participant.displayName, url: participant.avatarUrl, size: featured ? 96 : 56 }) }),
|
|
11636
|
+
presenting ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mx-meet__tile-presenting", role: "status", children: participant.isLocal ? "You are presenting" : `${participant.displayName} is presenting` }) : null,
|
|
11310
11637
|
participant.handRaised ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "mx-meet__tile-hand", title: `Hand raised \xB7 ${ordinal(handPosition)} in line`, children: [
|
|
11311
11638
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(HandIcon, { width: 14, height: 14 }),
|
|
11312
11639
|
handPosition > 0 ? handPosition : null
|
|
@@ -11407,6 +11734,7 @@ function ControlBar({ onLeave }) {
|
|
|
11407
11734
|
const controls = useHostControls();
|
|
11408
11735
|
const queue = useHandQueue();
|
|
11409
11736
|
const micUnavailable = useLocalMedia().microphone.unavailable;
|
|
11737
|
+
const live = useLivePolicy();
|
|
11410
11738
|
const unread = useUnreadChat(panel === "chat");
|
|
11411
11739
|
const [whiteboard, setWhiteboard] = (0, import_react10.useState)(false);
|
|
11412
11740
|
const app = useMeetAppPanel();
|
|
@@ -11474,7 +11802,7 @@ function ControlBar({ onLeave }) {
|
|
|
11474
11802
|
panel !== "people" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(KnockNotice, { onView: () => setPanel("people") }) : null,
|
|
11475
11803
|
controls.notice !== null && panel !== "people" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(Toast, { text: controls.notice.text, failed: controls.notice.failed, onDone: controls.clearNotice }) : null,
|
|
11476
11804
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-meet__controls", children: [
|
|
11477
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
11805
|
+
live.micLocked ? null : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
11478
11806
|
ControlButton,
|
|
11479
11807
|
{
|
|
11480
11808
|
label: micUnavailable !== null ? `Unmute \u2014 ${micUnavailable.remedy}` : room.local?.micEnabled === true ? "Mute (\u2318D)" : "Unmute (\u2318D)",
|
|
@@ -11483,7 +11811,7 @@ function ControlBar({ onLeave }) {
|
|
|
11483
11811
|
children: room.local?.micEnabled === true ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MicIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MicOffIcon, {})
|
|
11484
11812
|
}
|
|
11485
11813
|
),
|
|
11486
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
11814
|
+
live.cameraLocked ? null : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
11487
11815
|
ControlButton,
|
|
11488
11816
|
{
|
|
11489
11817
|
label: room.local?.cameraEnabled === true ? "Stop video (\u2318E)" : "Start video (\u2318E)",
|
|
@@ -11492,6 +11820,7 @@ function ControlBar({ onLeave }) {
|
|
|
11492
11820
|
children: room.local?.cameraEnabled === true ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CameraIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CameraOffIcon, {})
|
|
11493
11821
|
}
|
|
11494
11822
|
),
|
|
11823
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CaptionsControl, {}),
|
|
11495
11824
|
room.canShareScreen || room.local?.screenSharing === true ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
11496
11825
|
ControlButton,
|
|
11497
11826
|
{
|
|
@@ -11556,6 +11885,7 @@ function ControlBar({ onLeave }) {
|
|
|
11556
11885
|
onOpen: openActivity
|
|
11557
11886
|
}
|
|
11558
11887
|
),
|
|
11888
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(TakeNotesControl, {}),
|
|
11559
11889
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(AiControl, { active: panel === "ai", onToggle: () => toggle("ai") }),
|
|
11560
11890
|
recording.canStart ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ControlButton, { label: "Start recording", onClick: () => void recording.start(), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RecordIcon, {}) }) : null,
|
|
11561
11891
|
recording.canStop ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ControlButton, { label: "Stop recording", active: true, onClick: () => void recording.stop(), children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RecordIcon, {}) }) : null,
|
|
@@ -11611,6 +11941,23 @@ function ControlBar({ onLeave }) {
|
|
|
11611
11941
|
]
|
|
11612
11942
|
}
|
|
11613
11943
|
),
|
|
11944
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
11945
|
+
MenuItem,
|
|
11946
|
+
{
|
|
11947
|
+
onSelect: () => {
|
|
11948
|
+
setPopover("none");
|
|
11949
|
+
void controls.run({
|
|
11950
|
+
action: "set_av_lock",
|
|
11951
|
+
value: snapshot?.livePolicy.avLock === "both" ? "off" : "both"
|
|
11952
|
+
});
|
|
11953
|
+
},
|
|
11954
|
+
children: [
|
|
11955
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MicOffIcon, { width: 16, height: 16 }),
|
|
11956
|
+
" ",
|
|
11957
|
+
snapshot?.livePolicy.avLock === "both" ? "Turn on attendees' microphone and camera" : "Turn off attendees' microphone and camera"
|
|
11958
|
+
]
|
|
11959
|
+
}
|
|
11960
|
+
),
|
|
11614
11961
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
11615
11962
|
MenuItem,
|
|
11616
11963
|
{
|
|
@@ -11938,9 +12285,45 @@ function MeetingOverlays() {
|
|
|
11938
12285
|
const reactions = useReactions();
|
|
11939
12286
|
const { notice, dismiss } = useModerationNotice();
|
|
11940
12287
|
const room = useRoom();
|
|
12288
|
+
const live = useLivePolicy();
|
|
12289
|
+
const snapshot = useMeetSnapshot();
|
|
12290
|
+
const controls = useHostControls();
|
|
12291
|
+
const isHostNow = useRole() === "host";
|
|
11941
12292
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
|
|
11942
12293
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ReactionOverlay, { reactions }),
|
|
11943
12294
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MediaNotices, {}),
|
|
12295
|
+
snapshot !== null && snapshot.phase === "in_call" && snapshot.participants.length >= 2 && !snapshot.participants.some((p) => p.role === "host" || p.role === "cohost") ? (
|
|
12296
|
+
// meeting-without-host: the call goes on; host-only controls are simply not on screen.
|
|
12297
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("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." })
|
|
12298
|
+
) : null,
|
|
12299
|
+
live.consent !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mx-meet__sheet-backdrop", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-meet__sheet", role: "alertdialog", "aria-label": "This meeting is being recorded", "data-meet-notice": "recording-consent", children: [
|
|
12300
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { className: "mx-meet__panel-title", children: "This meeting is being recorded" }),
|
|
12301
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("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." }),
|
|
12302
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-meet__menu-actions", children: [
|
|
12303
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "mx-meet__send", onClick: live.agree, children: live.consent === "ok_or_leave" ? "OK" : "I agree" }),
|
|
12304
|
+
live.consent === "ok_or_leave" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "mx-meet__link", onClick: () => void room.leave(), children: "Leave meeting" }) : null
|
|
12305
|
+
] })
|
|
12306
|
+
] }) }) : null,
|
|
12307
|
+
snapshot?.canReclaim === true && !isHostNow ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-meet__notice-bar", role: "status", "data-meet-notice": "host-reclaim", children: [
|
|
12308
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: "You started this meeting. Take back the host?" }),
|
|
12309
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
12310
|
+
"button",
|
|
12311
|
+
{
|
|
12312
|
+
type: "button",
|
|
12313
|
+
className: "mx-meet__primary mx-meet__primary--small",
|
|
12314
|
+
onClick: () => void controls.run({ action: "reclaim_host" }),
|
|
12315
|
+
children: "Reclaim host"
|
|
12316
|
+
}
|
|
12317
|
+
)
|
|
12318
|
+
] }) : null,
|
|
12319
|
+
live.micLocked || live.cameraLocked ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("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,
|
|
12320
|
+
live.timeWarning && live.minutesLeft !== null && live.minutesLeft > 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: "mx-meet__banner", role: "status", "data-meet-notice": "time-warning", children: [
|
|
12321
|
+
"This meeting will end in ",
|
|
12322
|
+
live.minutesLeft,
|
|
12323
|
+
" ",
|
|
12324
|
+
live.minutesLeft === 1 ? "minute" : "minutes",
|
|
12325
|
+
" (time limit)."
|
|
12326
|
+
] }) : null,
|
|
11944
12327
|
notice !== null && notice.kind !== "removed" ? (
|
|
11945
12328
|
// A host's request ("the host is asking you to unmute"), not an error:
|
|
11946
12329
|
// an assertive status, so it is announced at once without being filed
|
|
@@ -12031,6 +12414,7 @@ function ChatPanel({
|
|
|
12031
12414
|
}) {
|
|
12032
12415
|
const snapshot = useMeetSnapshot();
|
|
12033
12416
|
const room = useRoom();
|
|
12417
|
+
const live = useLivePolicy();
|
|
12034
12418
|
const [draft, setDraft] = (0, import_react10.useState)("");
|
|
12035
12419
|
const [recipient, setRecipient] = (0, import_react10.useState)(to);
|
|
12036
12420
|
const listRef = (0, import_react10.useRef)(null);
|
|
@@ -12055,7 +12439,7 @@ function ChatPanel({
|
|
|
12055
12439
|
snapshot?.chatLoaded !== true && messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("li", { className: "mx-meet__panel-note", children: "Reading earlier messages\u2026" }) : messages.length === 0 && snapshot?.chatHistoryError == null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("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,
|
|
12056
12440
|
messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ChatLine, { message, local, people }, message.id))
|
|
12057
12441
|
] }),
|
|
12058
|
-
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
12442
|
+
!live.canChat ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("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__ */ (0, import_jsx_runtime6.jsxs)(
|
|
12059
12443
|
"form",
|
|
12060
12444
|
{
|
|
12061
12445
|
className: "mx-meet__composer mx-meet__composer--chat",
|
|
@@ -12238,7 +12622,8 @@ function PeoplePanel({
|
|
|
12238
12622
|
}
|
|
12239
12623
|
),
|
|
12240
12624
|
isNoteTaker(participant) ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mx-meet__badge", children: "Meeting assistant" }) : null,
|
|
12241
|
-
snapshot?.spotlight === participant.identity ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mx-meet__badge", children: "Spotlight" }) : null
|
|
12625
|
+
snapshot?.spotlight === participant.identity ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mx-meet__badge", children: "Spotlight" }) : null,
|
|
12626
|
+
snapshot?.presenter === participant.identity ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mx-meet__badge", "data-meet-presenting": "true", children: "Presenting" }) : null
|
|
12242
12627
|
] }),
|
|
12243
12628
|
participant.handRaised ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(HandIcon, { width: 14, height: 14 }) : null,
|
|
12244
12629
|
!participant.micEnabled && !isNoteTaker(participant) ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MicOffIcon, { width: 14, height: 14 }) : null,
|
|
@@ -12426,6 +12811,13 @@ function PersonMenu({
|
|
|
12426
12811
|
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(PeopleIcon, { width: 16, height: 16 }),
|
|
12427
12812
|
" Make co-host"
|
|
12428
12813
|
] }) : null,
|
|
12814
|
+
!participant.isAgent && participant.role !== "cohost" && participant.role !== "host" ? participant.role === "presenter" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(MenuItem, { onSelect: () => act({ action: "revoke_presenter", identity: participant.identity }), children: [
|
|
12815
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ScreenShareIcon, { width: 16, height: 16 }),
|
|
12816
|
+
" Remove presenter"
|
|
12817
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(MenuItem, { onSelect: () => act({ action: "make_presenter", identity: participant.identity }), children: [
|
|
12818
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(ScreenShareIcon, { width: 16, height: 16 }),
|
|
12819
|
+
" Make presenter"
|
|
12820
|
+
] }) : null,
|
|
12429
12821
|
!participant.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
12430
12822
|
MenuItem,
|
|
12431
12823
|
{
|
|
@@ -12931,8 +13323,19 @@ function Captions({ lines = 3 }) {
|
|
|
12931
13323
|
const ai = useMeetAi();
|
|
12932
13324
|
const visible = ai.transcript.slice(-lines);
|
|
12933
13325
|
const translation = useCaptionTranslation(visible);
|
|
12934
|
-
|
|
12935
|
-
|
|
13326
|
+
const captions = useCaptions();
|
|
13327
|
+
if (!captions.on) return null;
|
|
13328
|
+
if (captions.state === "unavailable") {
|
|
13329
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mx-meet__captions", role: "status", "data-meet-notice": "captions-unavailable", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: "mx-meet__caption", children: [
|
|
13330
|
+
"Captions are unavailable. ",
|
|
13331
|
+
captions.reason,
|
|
13332
|
+
captions.remedy !== null ? ` ${captions.remedy}` : ""
|
|
13333
|
+
] }) });
|
|
13334
|
+
}
|
|
13335
|
+
if (visible.length === 0) {
|
|
13336
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mx-meet__captions", "aria-live": "polite", "aria-label": "Live captions", "data-meet-caption": captions.state, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__caption mx-meet__caption--interim", children: captions.state === "starting" ? "Starting captions. They appear as people speak." : "Captions are on. They appear as people speak." }) });
|
|
13337
|
+
}
|
|
13338
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-meet__captions", "aria-live": "polite", "aria-label": "Live captions", "data-meet-caption": "live", children: [
|
|
12936
13339
|
visible.map((line) => {
|
|
12937
13340
|
const translated = translation.language === null ? void 0 : translation.translations[line.id];
|
|
12938
13341
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
@@ -12955,7 +13358,7 @@ function Captions({ lines = 3 }) {
|
|
|
12955
13358
|
function ConsentNotice() {
|
|
12956
13359
|
const notice = useConsentNotice();
|
|
12957
13360
|
if (notice === null) return null;
|
|
12958
|
-
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__consent", role: "status", children: notice });
|
|
13361
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__consent", role: "status", "data-meet-notice": "notes-started", children: notice });
|
|
12959
13362
|
}
|
|
12960
13363
|
function AttendanceNotice() {
|
|
12961
13364
|
const media = useLocalMedia();
|