@ai-matrx/meet 0.7.10 → 0.7.12
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 +37 -0
- package/dist/index.cjs +1673 -1116
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +292 -1
- package/dist/index.d.ts +292 -1
- package/dist/index.js +1673 -1116
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +2353 -698
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +94 -3
- package/dist/react.d.ts +94 -3
- package/dist/react.js +2354 -699
- package/dist/react.js.map +1 -1
- package/dist/styles.css +295 -1
- package/dist/tokens.css +2 -0
- package/package.json +5 -5
package/dist/react.cjs
CHANGED
|
@@ -33,15 +33,22 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
33
33
|
var react_exports = {};
|
|
34
34
|
__export(react_exports, {
|
|
35
35
|
ATTENDANCE_CSV_HEADER: () => ATTENDANCE_CSV_HEADER,
|
|
36
|
+
ActivitiesControl: () => ActivitiesControl,
|
|
37
|
+
ActivitiesIcon: () => ActivitiesIcon,
|
|
36
38
|
AiPanel: () => AiPanel,
|
|
37
39
|
AttendanceNotice: () => AttendanceNotice,
|
|
38
40
|
Avatar: () => Avatar,
|
|
41
|
+
BreakoutBanner: () => BreakoutBanner,
|
|
42
|
+
BreakoutIcon: () => BreakoutIcon,
|
|
43
|
+
BreakoutsPanel: () => BreakoutsPanel,
|
|
39
44
|
CALL_INVITE_KIND: () => CALL_INVITE_KIND,
|
|
40
45
|
CALL_INVITE_VERSION: () => CALL_INVITE_VERSION,
|
|
46
|
+
CAPTION_LANGUAGES: () => CAPTION_LANGUAGES,
|
|
41
47
|
CONSENT_NOTICE_ATTRIBUTE: () => CONSENT_NOTICE_ATTRIBUTE,
|
|
42
48
|
CallButton: () => CallButton,
|
|
43
49
|
CameraIcon: () => CameraIcon,
|
|
44
50
|
CameraOffIcon: () => CameraOffIcon,
|
|
51
|
+
CaptionLanguageSettings: () => CaptionLanguageSettings,
|
|
45
52
|
Captions: () => Captions,
|
|
46
53
|
ChatIcon: () => ChatIcon,
|
|
47
54
|
ChatPanel: () => ChatPanel,
|
|
@@ -54,6 +61,7 @@ __export(react_exports, {
|
|
|
54
61
|
DATA_TOPICS: () => DATA_TOPICS,
|
|
55
62
|
DEFAULT_EFFECTS: () => DEFAULT_EFFECTS,
|
|
56
63
|
DEFAULT_PAGE_SIZE: () => DEFAULT_PAGE_SIZE,
|
|
64
|
+
EMPTY_COLLAB: () => EMPTY_COLLAB,
|
|
57
65
|
END_MEETING_NOT_SERVED: () => END_MEETING_NOT_SERVED,
|
|
58
66
|
FILE_SESSION_PATH: () => FILE_SESSION_PATH,
|
|
59
67
|
FlagIcon: () => FlagIcon,
|
|
@@ -106,8 +114,12 @@ __export(react_exports, {
|
|
|
106
114
|
PhoneIcon: () => PhoneIcon,
|
|
107
115
|
PhoneOffIcon: () => PhoneOffIcon,
|
|
108
116
|
PinIcon: () => PinIcon,
|
|
117
|
+
PollIcon: () => PollIcon,
|
|
118
|
+
PollsPanel: () => PollsPanel,
|
|
109
119
|
PreJoin: () => PreJoin,
|
|
120
|
+
QaPanel: () => QaPanel,
|
|
110
121
|
QualityBars: () => QualityBars,
|
|
122
|
+
QuestionIcon: () => QuestionIcon,
|
|
111
123
|
REACTION_TTL_MS: () => REACTION_TTL_MS,
|
|
112
124
|
REFUSED_ABSENCE: () => REFUSED_ABSENCE,
|
|
113
125
|
ROLE_RANK: () => ROLE_RANK,
|
|
@@ -134,10 +146,13 @@ __export(react_exports, {
|
|
|
134
146
|
TABLES: () => TABLES,
|
|
135
147
|
TRANSCRIPTION_ATTRIBUTES: () => TRANSCRIPTION_ATTRIBUTES,
|
|
136
148
|
TRANSCRIPTION_TOPIC: () => TRANSCRIPTION_TOPIC,
|
|
149
|
+
WhiteboardIcon: () => WhiteboardIcon,
|
|
150
|
+
WhiteboardPanel: () => WhiteboardPanel,
|
|
137
151
|
WifiLowIcon: () => WifiLowIcon,
|
|
138
152
|
absenceSentence: () => absenceSentence,
|
|
139
153
|
activeWrapUpSummary: () => activeWrapUpSummary,
|
|
140
154
|
announceMeeting: () => announceMeeting,
|
|
155
|
+
applyCollabPacket: () => applyCollabPacket,
|
|
141
156
|
applyRoomEvent: () => applyRoomEvent,
|
|
142
157
|
asCallId: () => asCallId,
|
|
143
158
|
asMeetingId: () => asMeetingId,
|
|
@@ -145,10 +160,13 @@ __export(react_exports, {
|
|
|
145
160
|
asParticipantIdentity: () => asParticipantIdentity,
|
|
146
161
|
asRoomName: () => asRoomName,
|
|
147
162
|
asUserId: () => asUserId,
|
|
163
|
+
assignedRoom: () => assignedRoom,
|
|
148
164
|
attendanceCsv: () => attendanceCsv,
|
|
149
165
|
attendanceReport: () => attendanceReport,
|
|
150
166
|
attendanceTotals: () => attendanceTotals,
|
|
151
167
|
attendeeKey: () => attendeeKey,
|
|
168
|
+
autoAssign: () => autoAssign,
|
|
169
|
+
breakoutRemainingMs: () => breakoutRemainingMs,
|
|
152
170
|
callInviteAction: () => callInviteAction,
|
|
153
171
|
callInviteText: () => callInviteText,
|
|
154
172
|
callStateLabel: () => callStateLabel,
|
|
@@ -158,6 +176,7 @@ __export(react_exports, {
|
|
|
158
176
|
captionSegment: () => captionSegment,
|
|
159
177
|
changesPatch: () => changesPatch,
|
|
160
178
|
clockPosition: () => clockPosition,
|
|
179
|
+
collabFromState: () => collabFromState,
|
|
161
180
|
computeStage: () => computeStage,
|
|
162
181
|
countLabel: () => countLabel,
|
|
163
182
|
createCallCenter: () => createCallCenter,
|
|
@@ -178,6 +197,7 @@ __export(react_exports, {
|
|
|
178
197
|
createWebDeviceStorage: () => createWebDeviceStorage,
|
|
179
198
|
createWebEffectsStorage: () => createWebEffectsStorage,
|
|
180
199
|
createWebRoomTokenStorage: () => createWebRoomTokenStorage,
|
|
200
|
+
defaultCaptionLanguage: () => defaultCaptionLanguage,
|
|
181
201
|
displayNameFor: () => displayNameFor,
|
|
182
202
|
fileDownloadPath: () => fileDownloadPath,
|
|
183
203
|
gridColumns: () => gridColumns,
|
|
@@ -200,6 +220,7 @@ __export(react_exports, {
|
|
|
200
220
|
listenOnlyNotice: () => listenOnlyNotice,
|
|
201
221
|
loadFollowUpDraft: () => loadFollowUpDraft,
|
|
202
222
|
loadGuestMeetingRecord: () => loadGuestMeetingRecord,
|
|
223
|
+
loadMeetingActivities: () => loadMeetingActivities,
|
|
203
224
|
loadMeetingChat: () => loadMeetingChat,
|
|
204
225
|
loadMeetingRecord: () => loadMeetingRecord,
|
|
205
226
|
mapConnectionState: () => mapConnectionState,
|
|
@@ -254,9 +275,13 @@ __export(react_exports, {
|
|
|
254
275
|
unavailableFrom: () => unavailableFrom,
|
|
255
276
|
uniqueAttendees: () => uniqueAttendees,
|
|
256
277
|
useAudioLevel: () => useAudioLevel,
|
|
278
|
+
useAvailableActivities: () => useAvailableActivities,
|
|
257
279
|
useCalls: () => useCalls,
|
|
258
280
|
useCanModerate: () => useCanModerate,
|
|
259
281
|
useCanRecord: () => useCanRecord,
|
|
282
|
+
useCaptionTranslation: () => useCaptionTranslation,
|
|
283
|
+
useCollab: () => useCollab,
|
|
284
|
+
useCollabPanelRequest: () => useCollabPanelRequest,
|
|
260
285
|
useConsentNotice: () => useConsentNotice,
|
|
261
286
|
useDeviceSnapshot: () => useDeviceSnapshot,
|
|
262
287
|
useElapsed: () => useElapsed,
|
|
@@ -288,6 +313,7 @@ __export(react_exports, {
|
|
|
288
313
|
useTrack: () => useTrack,
|
|
289
314
|
userTopic: () => userTopic,
|
|
290
315
|
wasRefused: () => wasRefused,
|
|
316
|
+
withItem: () => withItem,
|
|
291
317
|
wrapUpStatus: () => wrapUpStatus
|
|
292
318
|
});
|
|
293
319
|
module.exports = __toCommonJS(react_exports);
|
|
@@ -519,7 +545,14 @@ var MEET_ROUTES = {
|
|
|
519
545
|
*/
|
|
520
546
|
moderate: "/api/v1/meet/moderate",
|
|
521
547
|
/** Meet wave 2: the SAVED chat — `POST` sends to everyone, `GET ?meeting_id=` reads history. */
|
|
522
|
-
chat: "/api/v1/meet/chat"
|
|
548
|
+
chat: "/api/v1/meet/chat",
|
|
549
|
+
/**
|
|
550
|
+
* Meet wave 5: polls, Q&A, the shared whiteboard and breakout rooms. `POST` acts
|
|
551
|
+
* (`{meeting_id, action, …}`), `GET ?meeting_id=` reads what this viewer may see.
|
|
552
|
+
*/
|
|
553
|
+
collab: "/api/v1/meet/collab",
|
|
554
|
+
/** Meet wave 5: translate finished caption lines into this viewer's language. */
|
|
555
|
+
captionsTranslate: "/api/v1/meet/captions/translate"
|
|
523
556
|
};
|
|
524
557
|
function meetingPath(template, meetingId) {
|
|
525
558
|
return template.replace("{meeting_id}", encodeURIComponent(meetingId));
|
|
@@ -578,7 +611,8 @@ function parseRoomToken(body, roomName) {
|
|
|
578
611
|
// server that has not landed MRI-A11 — and never invents a host from
|
|
579
612
|
// silence, because both fallbacks below grant nothing.
|
|
580
613
|
role: readRole(payload, "role") ?? (isHost ? "host" : identity.startsWith("guest:") ? "guest" : "participant"),
|
|
581
|
-
lobby: readBoolean(payload, "lobby", false)
|
|
614
|
+
lobby: readBoolean(payload, "lobby", false),
|
|
615
|
+
breakoutRoomId: readString(payload, "breakout_room_id") ?? null
|
|
582
616
|
};
|
|
583
617
|
}
|
|
584
618
|
function createTokenClient(options) {
|
|
@@ -626,6 +660,7 @@ function createTokenClient(options) {
|
|
|
626
660
|
room_name: input.roomName,
|
|
627
661
|
...input.meetingId !== void 0 ? { meeting_id: input.meetingId } : {},
|
|
628
662
|
...input.slug !== void 0 ? { slug: input.slug } : {},
|
|
663
|
+
...input.breakoutRoomId != null ? { breakout_room_id: input.breakoutRoomId } : {},
|
|
629
664
|
organization_id: input.identity.organizationId,
|
|
630
665
|
display_name: input.identity.displayName,
|
|
631
666
|
device_id: input.identity.deviceId,
|
|
@@ -689,7 +724,8 @@ function createTokenClient(options) {
|
|
|
689
724
|
return {
|
|
690
725
|
get(input) {
|
|
691
726
|
const entry = cache.get(input.roomName);
|
|
692
|
-
|
|
727
|
+
const sameRoom = entry !== void 0 && (entry.token.breakoutRoomId ?? null) === (input.breakoutRoomId ?? null);
|
|
728
|
+
if (entry !== void 0 && sameRoom) {
|
|
693
729
|
if (entry.inFlight !== null) return entry.inFlight;
|
|
694
730
|
if (!expired(entry)) return Promise.resolve(entry.token);
|
|
695
731
|
}
|
|
@@ -735,7 +771,8 @@ function placeholder(roomName) {
|
|
|
735
771
|
canRecord: false,
|
|
736
772
|
isHost: false,
|
|
737
773
|
role: "participant",
|
|
738
|
-
lobby: false
|
|
774
|
+
lobby: false,
|
|
775
|
+
breakoutRoomId: null
|
|
739
776
|
};
|
|
740
777
|
}
|
|
741
778
|
async function serverSentence(response) {
|
|
@@ -1793,6 +1830,339 @@ function listenOnlyNotice(media) {
|
|
|
1793
1830
|
return isListenOnly(media) ? LISTEN_ONLY_NOTICE : null;
|
|
1794
1831
|
}
|
|
1795
1832
|
|
|
1833
|
+
// src/core/collab.ts
|
|
1834
|
+
var EMPTY_COLLAB = {
|
|
1835
|
+
loaded: false,
|
|
1836
|
+
error: null,
|
|
1837
|
+
settings: null,
|
|
1838
|
+
polls: [],
|
|
1839
|
+
questions: [],
|
|
1840
|
+
strokes: [],
|
|
1841
|
+
breakout: null,
|
|
1842
|
+
broadcast: null,
|
|
1843
|
+
moveRequest: null,
|
|
1844
|
+
panelRequest: null,
|
|
1845
|
+
captionLanguage: null,
|
|
1846
|
+
captionTranslations: {},
|
|
1847
|
+
captionTranslationError: null
|
|
1848
|
+
};
|
|
1849
|
+
function obj(value) {
|
|
1850
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
1851
|
+
}
|
|
1852
|
+
function str(value) {
|
|
1853
|
+
return typeof value === "string" ? value : null;
|
|
1854
|
+
}
|
|
1855
|
+
function num(value) {
|
|
1856
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
1857
|
+
}
|
|
1858
|
+
function strings(value) {
|
|
1859
|
+
return Array.isArray(value) ? value.filter((v) => typeof v === "string") : [];
|
|
1860
|
+
}
|
|
1861
|
+
function pollFromRow(row) {
|
|
1862
|
+
const id = str(row["id"]);
|
|
1863
|
+
if (id === null) return null;
|
|
1864
|
+
const options = [];
|
|
1865
|
+
for (const raw of Array.isArray(row["options"]) ? row["options"] : []) {
|
|
1866
|
+
const option = obj(raw);
|
|
1867
|
+
const optionId = option === null ? null : str(option["id"]);
|
|
1868
|
+
if (option === null || optionId === null) continue;
|
|
1869
|
+
const votes = num(option["votes"]);
|
|
1870
|
+
options.push({
|
|
1871
|
+
id: optionId,
|
|
1872
|
+
text: str(option["text"]) ?? "",
|
|
1873
|
+
...votes !== null ? { votes } : {},
|
|
1874
|
+
...Array.isArray(option["voters"]) ? { voters: strings(option["voters"]) } : {}
|
|
1875
|
+
});
|
|
1876
|
+
}
|
|
1877
|
+
const state = str(row["state"]);
|
|
1878
|
+
return {
|
|
1879
|
+
id,
|
|
1880
|
+
question: str(row["question"]) ?? "",
|
|
1881
|
+
options,
|
|
1882
|
+
multiple: row["multiple"] === true,
|
|
1883
|
+
anonymous: row["anonymous"] === true,
|
|
1884
|
+
state: state === "live" || state === "closed" ? state : "draft",
|
|
1885
|
+
resultsShared: row["results_shared"] === true,
|
|
1886
|
+
voterCount: num(row["voter_count"]),
|
|
1887
|
+
myVote: strings(row["my_vote"]),
|
|
1888
|
+
createdByName: str(row["created_by_name"]) ?? "",
|
|
1889
|
+
createdAt: str(row["created_at"])
|
|
1890
|
+
};
|
|
1891
|
+
}
|
|
1892
|
+
function questionFromRow(row) {
|
|
1893
|
+
const id = str(row["id"]);
|
|
1894
|
+
if (id === null) return null;
|
|
1895
|
+
const state = str(row["state"]);
|
|
1896
|
+
return {
|
|
1897
|
+
id,
|
|
1898
|
+
text: str(row["text"]) ?? "",
|
|
1899
|
+
askerName: str(row["asker_name"]) ?? "",
|
|
1900
|
+
anonymous: row["anonymous"] === true,
|
|
1901
|
+
state: state === "answered" || state === "dismissed" ? state : "open",
|
|
1902
|
+
answer: str(row["answer"]),
|
|
1903
|
+
answeredByName: str(row["answered_by_name"]),
|
|
1904
|
+
upvotes: num(row["upvotes"]) ?? 0,
|
|
1905
|
+
upvotedByMe: row["upvoted_by_me"] === true,
|
|
1906
|
+
mine: row["mine"] === true,
|
|
1907
|
+
createdAt: str(row["created_at"])
|
|
1908
|
+
};
|
|
1909
|
+
}
|
|
1910
|
+
function strokeFromRow(row) {
|
|
1911
|
+
const id = str(row["id"]);
|
|
1912
|
+
if (id === null || !Array.isArray(row["points"])) return null;
|
|
1913
|
+
const points = [];
|
|
1914
|
+
for (const raw of row["points"]) {
|
|
1915
|
+
if (Array.isArray(raw) && typeof raw[0] === "number" && typeof raw[1] === "number") {
|
|
1916
|
+
points.push([raw[0], raw[1]]);
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
return {
|
|
1920
|
+
id,
|
|
1921
|
+
points,
|
|
1922
|
+
color: str(row["color"]) ?? "#111827",
|
|
1923
|
+
width: num(row["width"]) ?? 3,
|
|
1924
|
+
tool: row["tool"] === "highlighter" ? "highlighter" : "pen",
|
|
1925
|
+
by: str(row["by"]) ?? "",
|
|
1926
|
+
byName: str(row["by_name"]) ?? ""
|
|
1927
|
+
};
|
|
1928
|
+
}
|
|
1929
|
+
function broadcastFrom(value) {
|
|
1930
|
+
const row = obj(value);
|
|
1931
|
+
const text3 = row === null ? null : str(row["text"]);
|
|
1932
|
+
if (row === null || text3 === null) return null;
|
|
1933
|
+
return { text: text3, by: str(row["by"]) ?? "", at: str(row["at"]) ?? "" };
|
|
1934
|
+
}
|
|
1935
|
+
function planFromRow(row) {
|
|
1936
|
+
const id = str(row["id"]);
|
|
1937
|
+
if (id === null) return null;
|
|
1938
|
+
const rooms = [];
|
|
1939
|
+
for (const raw of Array.isArray(row["rooms"]) ? row["rooms"] : []) {
|
|
1940
|
+
const room = obj(raw);
|
|
1941
|
+
const roomId = room === null ? null : str(room["id"]);
|
|
1942
|
+
if (room === null || roomId === null) continue;
|
|
1943
|
+
rooms.push({ id: roomId, name: str(room["name"]) ?? roomId, identities: strings(room["identities"]) });
|
|
1944
|
+
}
|
|
1945
|
+
return {
|
|
1946
|
+
id,
|
|
1947
|
+
state: row["state"] === "open" ? "open" : "closed",
|
|
1948
|
+
rooms,
|
|
1949
|
+
allowChoose: row["allow_choose"] === true,
|
|
1950
|
+
minutes: num(row["minutes"]) ?? 0,
|
|
1951
|
+
openedAt: str(row["opened_at"]),
|
|
1952
|
+
endsAt: str(row["ends_at"]),
|
|
1953
|
+
closedAt: str(row["closed_at"]),
|
|
1954
|
+
broadcasts: (Array.isArray(row["broadcasts"]) ? row["broadcasts"] : []).map(broadcastFrom).filter((b) => b !== null)
|
|
1955
|
+
};
|
|
1956
|
+
}
|
|
1957
|
+
function settingsFromRow(row) {
|
|
1958
|
+
if (row === null) return null;
|
|
1959
|
+
return {
|
|
1960
|
+
pollsEnabled: row["polls_enabled"] === true,
|
|
1961
|
+
pollMaxOptions: num(row["poll_max_options"]) ?? 10,
|
|
1962
|
+
qaEnabled: row["qa_enabled"] === true,
|
|
1963
|
+
qaAnonymousAllowed: row["qa_anonymous_allowed"] === true,
|
|
1964
|
+
whiteboardEnabled: row["whiteboard_enabled"] === true,
|
|
1965
|
+
breakoutsEnabled: row["breakouts_enabled"] === true,
|
|
1966
|
+
breakoutMaxRooms: num(row["breakout_max_rooms"]) ?? 20,
|
|
1967
|
+
breakoutDefaultMinutes: num(row["breakout_default_minutes"]) ?? 15,
|
|
1968
|
+
captionTranslationEnabled: row["caption_translation_enabled"] === true,
|
|
1969
|
+
captionTranslationLanguage: str(row["caption_translation_language"]) ?? ""
|
|
1970
|
+
};
|
|
1971
|
+
}
|
|
1972
|
+
function collabFromState(body, previous) {
|
|
1973
|
+
const list = (key, parse) => (Array.isArray(body[key]) ? body[key] : []).map((raw) => {
|
|
1974
|
+
const row = obj(raw);
|
|
1975
|
+
return row === null ? null : parse(row);
|
|
1976
|
+
}).filter((item) => item !== null);
|
|
1977
|
+
const breakoutRow = obj(body["breakout"]);
|
|
1978
|
+
return {
|
|
1979
|
+
...previous,
|
|
1980
|
+
loaded: true,
|
|
1981
|
+
error: null,
|
|
1982
|
+
settings: settingsFromRow(obj(body["settings"])),
|
|
1983
|
+
polls: list("polls", pollFromRow),
|
|
1984
|
+
questions: list("questions", questionFromRow),
|
|
1985
|
+
strokes: list("strokes", strokeFromRow),
|
|
1986
|
+
breakout: breakoutRow === null ? null : planFromRow(breakoutRow)
|
|
1987
|
+
};
|
|
1988
|
+
}
|
|
1989
|
+
function upsert(items, next) {
|
|
1990
|
+
const index = items.findIndex((item) => item.id === next.id);
|
|
1991
|
+
if (index === -1) return [...items, next];
|
|
1992
|
+
const copy = items.slice();
|
|
1993
|
+
copy[index] = next;
|
|
1994
|
+
return copy;
|
|
1995
|
+
}
|
|
1996
|
+
function withItem(collab, row, fromRoom = false) {
|
|
1997
|
+
const kind = str(row["kind"]);
|
|
1998
|
+
if (kind === "poll") {
|
|
1999
|
+
const poll = pollFromRow(row);
|
|
2000
|
+
if (poll === null) return collab;
|
|
2001
|
+
const known = collab.polls.find((p) => p.id === poll.id);
|
|
2002
|
+
const merged = fromRoom && known !== void 0 ? { ...poll, myVote: known.myVote } : poll;
|
|
2003
|
+
return { ...collab, polls: upsert(collab.polls, merged) };
|
|
2004
|
+
}
|
|
2005
|
+
if (kind === "question") {
|
|
2006
|
+
const question = questionFromRow(row);
|
|
2007
|
+
if (question === null) return collab;
|
|
2008
|
+
const known = collab.questions.find((q) => q.id === question.id);
|
|
2009
|
+
const merged = fromRoom && known !== void 0 ? { ...question, mine: known.mine, upvotedByMe: known.upvotedByMe } : question;
|
|
2010
|
+
return { ...collab, questions: upsert(collab.questions, merged) };
|
|
2011
|
+
}
|
|
2012
|
+
if (kind === "stroke") {
|
|
2013
|
+
const stroke = strokeFromRow(row);
|
|
2014
|
+
if (stroke === null) return collab;
|
|
2015
|
+
return { ...collab, strokes: upsert(collab.strokes, stroke) };
|
|
2016
|
+
}
|
|
2017
|
+
if (kind === "breakout") {
|
|
2018
|
+
const plan = planFromRow(row);
|
|
2019
|
+
if (plan === null) return collab;
|
|
2020
|
+
return { ...collab, breakout: plan };
|
|
2021
|
+
}
|
|
2022
|
+
return collab;
|
|
2023
|
+
}
|
|
2024
|
+
function without(collab, ids) {
|
|
2025
|
+
const gone = new Set(ids);
|
|
2026
|
+
return {
|
|
2027
|
+
...collab,
|
|
2028
|
+
polls: collab.polls.filter((p) => !gone.has(p.id)),
|
|
2029
|
+
questions: collab.questions.filter((q) => !gone.has(q.id)),
|
|
2030
|
+
strokes: collab.strokes.filter((s) => !gone.has(s.id))
|
|
2031
|
+
};
|
|
2032
|
+
}
|
|
2033
|
+
function applyCollabPacket(collab, payload, context) {
|
|
2034
|
+
const item = obj(payload["item"]);
|
|
2035
|
+
const audience = str(payload["audience"]);
|
|
2036
|
+
if (item !== null) {
|
|
2037
|
+
const kind = str(item["kind"]);
|
|
2038
|
+
const hostOnlyView = kind === "poll" || kind === "question";
|
|
2039
|
+
if (hostOnlyView && context.isHost && audience !== "hosts") {
|
|
2040
|
+
return { next: null, dropped: "the room copy of an item a host receives in full" };
|
|
2041
|
+
}
|
|
2042
|
+
let next = withItem(collab, item, true);
|
|
2043
|
+
if (kind === "poll" && str(item["state"]) === "live") {
|
|
2044
|
+
const before = collab.polls.find((p) => p.id === str(item["id"]));
|
|
2045
|
+
if (before === void 0 || before.state !== "live") {
|
|
2046
|
+
next = { ...next, panelRequest: { panel: "polls", at: context.now } };
|
|
2047
|
+
}
|
|
2048
|
+
}
|
|
2049
|
+
if (kind === "breakout") {
|
|
2050
|
+
const plan = planFromRow(item);
|
|
2051
|
+
if (plan !== null && plan.state === "closed") {
|
|
2052
|
+
next = { ...next, moveRequest: { roomId: null, at: context.now } };
|
|
2053
|
+
}
|
|
2054
|
+
}
|
|
2055
|
+
const move = obj(payload["move"]);
|
|
2056
|
+
if (move !== null && str(move["identity"]) === context.localIdentity) {
|
|
2057
|
+
next = { ...next, moveRequest: { roomId: str(move["room_id"]), at: context.now } };
|
|
2058
|
+
}
|
|
2059
|
+
return { next };
|
|
2060
|
+
}
|
|
2061
|
+
if (Array.isArray(payload["removed"])) {
|
|
2062
|
+
return { next: without(collab, strings(payload["removed"])) };
|
|
2063
|
+
}
|
|
2064
|
+
if (Array.isArray(payload["hidden"])) {
|
|
2065
|
+
return context.isHost ? { next: null, dropped: "hosts keep dismissed questions" } : { next: without(collab, strings(payload["hidden"])) };
|
|
2066
|
+
}
|
|
2067
|
+
if (payload["cleared"] === "whiteboard") {
|
|
2068
|
+
return { next: { ...collab, strokes: [] } };
|
|
2069
|
+
}
|
|
2070
|
+
const broadcast = broadcastFrom(payload["broadcast"]);
|
|
2071
|
+
if (broadcast !== null) {
|
|
2072
|
+
return { next: { ...collab, broadcast } };
|
|
2073
|
+
}
|
|
2074
|
+
return { next: null, dropped: "a collab packet with nothing this version understands" };
|
|
2075
|
+
}
|
|
2076
|
+
function assignedRoom(plan, identity) {
|
|
2077
|
+
if (plan === null || plan.state !== "open" || identity === null) return null;
|
|
2078
|
+
return plan.rooms.find((room) => room.identities.includes(identity)) ?? null;
|
|
2079
|
+
}
|
|
2080
|
+
function autoAssign(identities, rooms, exclude = []) {
|
|
2081
|
+
const count2 = Math.max(1, Math.floor(rooms));
|
|
2082
|
+
const out = Array.from({ length: count2 }, () => []);
|
|
2083
|
+
const skip = new Set(exclude);
|
|
2084
|
+
let index = 0;
|
|
2085
|
+
for (const identity of identities) {
|
|
2086
|
+
if (skip.has(identity)) continue;
|
|
2087
|
+
out[index % count2].push(identity);
|
|
2088
|
+
index += 1;
|
|
2089
|
+
}
|
|
2090
|
+
return out;
|
|
2091
|
+
}
|
|
2092
|
+
function breakoutRemainingMs(plan, now) {
|
|
2093
|
+
if (plan === null || plan.state !== "open" || plan.endsAt === null) return null;
|
|
2094
|
+
const end = Date.parse(plan.endsAt);
|
|
2095
|
+
return Number.isNaN(end) ? null : Math.max(0, end - now);
|
|
2096
|
+
}
|
|
2097
|
+
function defaultCaptionLanguage(settings, viewerLanguage) {
|
|
2098
|
+
const configured = settings?.captionTranslationLanguage.trim() ?? "";
|
|
2099
|
+
if (configured.length > 0) return configured;
|
|
2100
|
+
const own = (viewerLanguage ?? "").trim();
|
|
2101
|
+
return own.length > 0 ? own : "en";
|
|
2102
|
+
}
|
|
2103
|
+
var CAPTION_LANGUAGES = [
|
|
2104
|
+
{ tag: "en", name: "English" },
|
|
2105
|
+
{ tag: "es", name: "Spanish" },
|
|
2106
|
+
{ tag: "fr", name: "French" },
|
|
2107
|
+
{ tag: "de", name: "German" },
|
|
2108
|
+
{ tag: "it", name: "Italian" },
|
|
2109
|
+
{ tag: "pt", name: "Portuguese" },
|
|
2110
|
+
{ tag: "nl", name: "Dutch" },
|
|
2111
|
+
{ tag: "pl", name: "Polish" },
|
|
2112
|
+
{ tag: "ru", name: "Russian" },
|
|
2113
|
+
{ tag: "uk", name: "Ukrainian" },
|
|
2114
|
+
{ tag: "tr", name: "Turkish" },
|
|
2115
|
+
{ tag: "ar", name: "Arabic" },
|
|
2116
|
+
{ tag: "he", name: "Hebrew" },
|
|
2117
|
+
{ tag: "fa", name: "Persian" },
|
|
2118
|
+
{ tag: "hi", name: "Hindi" },
|
|
2119
|
+
{ tag: "bn", name: "Bengali" },
|
|
2120
|
+
{ tag: "zh", name: "Chinese" },
|
|
2121
|
+
{ tag: "ja", name: "Japanese" },
|
|
2122
|
+
{ tag: "ko", name: "Korean" },
|
|
2123
|
+
{ tag: "vi", name: "Vietnamese" },
|
|
2124
|
+
{ tag: "th", name: "Thai" },
|
|
2125
|
+
{ tag: "id", name: "Indonesian" },
|
|
2126
|
+
{ tag: "sv", name: "Swedish" }
|
|
2127
|
+
];
|
|
2128
|
+
async function loadMeetingActivities(api, meetingId, roomToken = null) {
|
|
2129
|
+
let response;
|
|
2130
|
+
try {
|
|
2131
|
+
response = await api.request({
|
|
2132
|
+
path: `${MEET_ROUTES.collab}?meeting_id=${encodeURIComponent(meetingId)}`,
|
|
2133
|
+
method: "GET",
|
|
2134
|
+
operation: "meet.loadMeetingActivities",
|
|
2135
|
+
requireAuth: roomToken === null,
|
|
2136
|
+
...roomToken !== null ? { headers: { [ROOM_TOKEN_HEADER]: roomToken } } : {}
|
|
2137
|
+
});
|
|
2138
|
+
} catch (error) {
|
|
2139
|
+
return {
|
|
2140
|
+
collab: null,
|
|
2141
|
+
refusal: {
|
|
2142
|
+
message: `Polls, questions and the whiteboard could not be read (${error.message}).`,
|
|
2143
|
+
remedy: error.remedy ?? "Reload the page."
|
|
2144
|
+
}
|
|
2145
|
+
};
|
|
2146
|
+
}
|
|
2147
|
+
if (!response.ok) {
|
|
2148
|
+
let body = null;
|
|
2149
|
+
try {
|
|
2150
|
+
body = await response.json();
|
|
2151
|
+
} catch {
|
|
2152
|
+
body = null;
|
|
2153
|
+
}
|
|
2154
|
+
const said = readServerRefusal(body);
|
|
2155
|
+
return {
|
|
2156
|
+
collab: null,
|
|
2157
|
+
refusal: {
|
|
2158
|
+
message: said?.reason ?? `Polls and questions could not be read (the server answered ${response.status}).`,
|
|
2159
|
+
remedy: said?.remedy || "Reload the page."
|
|
2160
|
+
}
|
|
2161
|
+
};
|
|
2162
|
+
}
|
|
2163
|
+
return { collab: collabFromState(await response.json(), EMPTY_COLLAB), refusal: null };
|
|
2164
|
+
}
|
|
2165
|
+
|
|
1796
2166
|
// src/core/transcript.ts
|
|
1797
2167
|
function normalizeSpoken(text3) {
|
|
1798
2168
|
return text3.toLowerCase().replace(/[^\p{L}\p{N}]+/gu, " ").trim();
|
|
@@ -1894,7 +2264,9 @@ var EMPTY = {
|
|
|
1894
2264
|
wrapUp: null,
|
|
1895
2265
|
noteTakerRefusal: null,
|
|
1896
2266
|
media: IDLE_MEDIA,
|
|
1897
|
-
failure: null
|
|
2267
|
+
failure: null,
|
|
2268
|
+
collab: EMPTY_COLLAB,
|
|
2269
|
+
breakoutRoomId: null
|
|
1898
2270
|
};
|
|
1899
2271
|
function effectiveRole(snapshot) {
|
|
1900
2272
|
const me = snapshot.participants.find(
|
|
@@ -2545,7 +2917,19 @@ var INVITEE_COLUMNS = "id,meeting_id,invitee_user_id,email,display_name,role,rsv
|
|
|
2545
2917
|
var RECORDING_COLUMNS = "id,meeting_id,state,started_at,ended_at,started_by,file_id,failure_reason";
|
|
2546
2918
|
var SEGMENT_COLUMNS = "id,meeting_id,identity,speaker,text,started_at,is_final,metadata";
|
|
2547
2919
|
var NOTE_COLUMNS = "id,meeting_id,text,kind,assignee_user_id,created_at,metadata";
|
|
2548
|
-
var ATTENDEE_COLUMNS = "id,meeting_id,identity,participant_user_id,display_name,avatar_url,role,admission_state,is_agent,joined_at,left_at";
|
|
2920
|
+
var ATTENDEE_COLUMNS = "id,meeting_id,identity,participant_user_id,display_name,avatar_url,role,admission_state,is_agent,joined_at,left_at,sessions:metadata->sessions";
|
|
2921
|
+
function projectStays(value) {
|
|
2922
|
+
if (!Array.isArray(value)) return [];
|
|
2923
|
+
const stays = [];
|
|
2924
|
+
for (const item of value) {
|
|
2925
|
+
if (item === null || typeof item !== "object") continue;
|
|
2926
|
+
const joined = item["joined_at"];
|
|
2927
|
+
const left = item["left_at"];
|
|
2928
|
+
if (typeof joined !== "string" || joined.length === 0) continue;
|
|
2929
|
+
stays.push({ joinedAt: joined, leftAt: typeof left === "string" && left.length > 0 ? left : null });
|
|
2930
|
+
}
|
|
2931
|
+
return stays;
|
|
2932
|
+
}
|
|
2549
2933
|
function text(row, key) {
|
|
2550
2934
|
const value = row[key];
|
|
2551
2935
|
return typeof value === "string" && value.length > 0 ? value : null;
|
|
@@ -2644,7 +3028,7 @@ var OCCURRENCE_STATES = ["scheduled", "moved", "cancelled"];
|
|
|
2644
3028
|
function rsvpState(value) {
|
|
2645
3029
|
return RSVP_STATES.includes(value) ? value : "needs_action";
|
|
2646
3030
|
}
|
|
2647
|
-
function
|
|
3031
|
+
function num2(row, key) {
|
|
2648
3032
|
const value = row[key];
|
|
2649
3033
|
return typeof value === "number" ? value : null;
|
|
2650
3034
|
}
|
|
@@ -2666,7 +3050,7 @@ function projectInvitee(row) {
|
|
|
2666
3050
|
rsvpState: rsvpState(text(row, "rsvp_state")),
|
|
2667
3051
|
respondedAt: when(row, "responded_at"),
|
|
2668
3052
|
rsvpNote: text(row, "rsvp_note"),
|
|
2669
|
-
lastSentSequence:
|
|
3053
|
+
lastSentSequence: num2(row, "last_sent_sequence"),
|
|
2670
3054
|
lastSentAt: when(row, "last_sent_at")
|
|
2671
3055
|
};
|
|
2672
3056
|
}
|
|
@@ -2677,10 +3061,10 @@ function projectOccurrence(row) {
|
|
|
2677
3061
|
meetingId: asMeetingId(requireText(row, "meeting_id", operation)),
|
|
2678
3062
|
originalStart: when(row, "original_start") ?? requireText(row, "original_start", operation),
|
|
2679
3063
|
occurrenceStart: when(row, "occurrence_start") ?? requireText(row, "occurrence_start", operation),
|
|
2680
|
-
durationMinutes:
|
|
3064
|
+
durationMinutes: num2(row, "duration_minutes"),
|
|
2681
3065
|
// An unknown state is shown as scheduled, never dropped: the row is real.
|
|
2682
3066
|
state: OCCURRENCE_STATES.includes(state) ? state : "scheduled",
|
|
2683
|
-
sequence:
|
|
3067
|
+
sequence: num2(row, "sequence") ?? 0
|
|
2684
3068
|
};
|
|
2685
3069
|
}
|
|
2686
3070
|
function projectUpcoming(row) {
|
|
@@ -2709,9 +3093,9 @@ function projectOverride(row) {
|
|
|
2709
3093
|
originalStart: when(row, "original_start") ?? requireText(row, "original_start", operation),
|
|
2710
3094
|
state: text(row, "state") === "moved" ? "moved" : "cancelled",
|
|
2711
3095
|
newStart: when(row, "new_start"),
|
|
2712
|
-
newDurationMinutes:
|
|
3096
|
+
newDurationMinutes: num2(row, "new_duration_minutes"),
|
|
2713
3097
|
reason: text(row, "reason"),
|
|
2714
|
-
calendarSequence:
|
|
3098
|
+
calendarSequence: num2(row, "calendar_sequence") ?? 0,
|
|
2715
3099
|
deletedAt: when(row, "deleted_at")
|
|
2716
3100
|
};
|
|
2717
3101
|
}
|
|
@@ -2735,7 +3119,7 @@ function projectRsvpInvitation(body) {
|
|
|
2735
3119
|
title: text(meeting, "title") ?? "Meeting",
|
|
2736
3120
|
slug: requireText(meeting, "slug", operation),
|
|
2737
3121
|
scheduledFor: when(meeting, "scheduled_for"),
|
|
2738
|
-
durationMinutes:
|
|
3122
|
+
durationMinutes: num2(meeting, "duration_minutes"),
|
|
2739
3123
|
timeZone: text(meeting, "time_zone") ?? "UTC",
|
|
2740
3124
|
agenda: text(meeting, "agenda"),
|
|
2741
3125
|
recurrenceRule: text(meeting, "recurrence_rule"),
|
|
@@ -2769,6 +3153,7 @@ function changesPatch(changes) {
|
|
|
2769
3153
|
patch["scheduled_duration_minutes"] = changes.scheduledDurationMinutes;
|
|
2770
3154
|
}
|
|
2771
3155
|
if (changes.recurrenceRule !== void 0) patch["recurrence_rule"] = changes.recurrenceRule;
|
|
3156
|
+
if (changes.keepExceptions !== void 0) patch["keep_exceptions"] = changes.keepExceptions;
|
|
2772
3157
|
return patch;
|
|
2773
3158
|
}
|
|
2774
3159
|
function createMeetRepository(options) {
|
|
@@ -2915,7 +3300,8 @@ function createMeetRepository(options) {
|
|
|
2915
3300
|
admissionState: states.includes(admission) ? admission : "admitted",
|
|
2916
3301
|
isAgent: bool(row, "is_agent", false),
|
|
2917
3302
|
joinedAt: text(row, "joined_at"),
|
|
2918
|
-
leftAt: text(row, "left_at")
|
|
3303
|
+
leftAt: text(row, "left_at"),
|
|
3304
|
+
sessions: projectStays(row["sessions"])
|
|
2919
3305
|
};
|
|
2920
3306
|
}
|
|
2921
3307
|
function requireOrg(organizationId, operation) {
|
|
@@ -3309,8 +3695,8 @@ function projectLibraryRecording(row) {
|
|
|
3309
3695
|
fileId: text(row, "file_id"),
|
|
3310
3696
|
startedAt: text(row, "started_at"),
|
|
3311
3697
|
endedAt: text(row, "ended_at"),
|
|
3312
|
-
durationMs:
|
|
3313
|
-
sizeBytes:
|
|
3698
|
+
durationMs: num2(row, "duration_ms"),
|
|
3699
|
+
sizeBytes: num2(row, "size_bytes"),
|
|
3314
3700
|
failureReason: text(row, "failure_reason"),
|
|
3315
3701
|
archivedAt: text(row, "deleted_at"),
|
|
3316
3702
|
organizationId: asOrganizationId(requireText(row, "organization_id", operation))
|
|
@@ -3337,7 +3723,7 @@ function projectSearchHit(row) {
|
|
|
3337
3723
|
speaker: text(row, "speaker"),
|
|
3338
3724
|
snippet: text(row, "snippet") ?? "",
|
|
3339
3725
|
at: text(row, "said_at"),
|
|
3340
|
-
rank:
|
|
3726
|
+
rank: num2(row, "rank") ?? 0
|
|
3341
3727
|
};
|
|
3342
3728
|
}
|
|
3343
3729
|
function snippetRuns(snippet) {
|
|
@@ -3482,7 +3868,14 @@ var ROOM_EVENTS = {
|
|
|
3482
3868
|
* person concerned; `lower-hands {identities: [...] | "*"}` · `role {identity,
|
|
3483
3869
|
* role}` — to everyone.
|
|
3484
3870
|
*/
|
|
3485
|
-
moderation: "matrx.meet.moderation"
|
|
3871
|
+
moderation: "matrx.meet.moderation",
|
|
3872
|
+
/**
|
|
3873
|
+
* A meeting ROOM ITEM changed (Meet wave 5): a poll, a Q&A question, a whiteboard
|
|
3874
|
+
* stroke or the breakout plan. Payload `{ meeting_id, item }` · `{ removed: [ids] }` ·
|
|
3875
|
+
* `{ hidden: [ids] }` · `{ cleared: "whiteboard" }` · `{ broadcast }` · `{ item, move }`.
|
|
3876
|
+
* A host's fuller copy of a poll or question carries `audience: "hosts"`.
|
|
3877
|
+
*/
|
|
3878
|
+
collab: "matrx.meet.collab"
|
|
3486
3879
|
};
|
|
3487
3880
|
function isRoomEventTopic(topic) {
|
|
3488
3881
|
return topic.startsWith(ROOM_EVENT_PREFIX);
|
|
@@ -3522,10 +3915,27 @@ function applyRoomEvent(args) {
|
|
|
3522
3915
|
return applyChat(store, payload);
|
|
3523
3916
|
case ROOM_EVENTS.moderation:
|
|
3524
3917
|
return applyModeration(store, payload, now);
|
|
3918
|
+
case ROOM_EVENTS.collab:
|
|
3919
|
+
return applyCollab(store, payload, now);
|
|
3525
3920
|
default:
|
|
3526
3921
|
return ignored(`${topic} is not known to this version of @ai-matrx/meet`);
|
|
3527
3922
|
}
|
|
3528
3923
|
}
|
|
3924
|
+
function applyCollab(store, payload, now) {
|
|
3925
|
+
const snapshot = store.snapshot();
|
|
3926
|
+
const meeting = snapshot.meeting;
|
|
3927
|
+
if (meeting !== null && text2(payload["meeting_id"]) !== null && payload["meeting_id"] !== meeting.id) {
|
|
3928
|
+
return ignored("a collab event for a different meeting than this room is showing");
|
|
3929
|
+
}
|
|
3930
|
+
const result = applyCollabPacket(snapshot.collab, payload, {
|
|
3931
|
+
localIdentity: snapshot.localIdentity,
|
|
3932
|
+
isHost: ROLE_RANK[effectiveRole(snapshot)] >= ROLE_RANK.cohost,
|
|
3933
|
+
now: now()
|
|
3934
|
+
});
|
|
3935
|
+
if (result.next === null) return ignored(result.dropped ?? "a collab packet that changed nothing");
|
|
3936
|
+
store.patch({ collab: result.next });
|
|
3937
|
+
return HANDLED;
|
|
3938
|
+
}
|
|
3529
3939
|
function applyNote(store, payload) {
|
|
3530
3940
|
const row = object(payload["note"]);
|
|
3531
3941
|
if (row === null) return ignored("a note event with no `note` row");
|
|
@@ -3847,6 +4257,7 @@ function createRoomEngine(options) {
|
|
|
3847
4257
|
let joining = null;
|
|
3848
4258
|
let lastRequest = null;
|
|
3849
4259
|
let disposed = false;
|
|
4260
|
+
let moving = false;
|
|
3850
4261
|
const confirmingEnds = /* @__PURE__ */ new WeakSet();
|
|
3851
4262
|
async function leaveRoom() {
|
|
3852
4263
|
const target = driver;
|
|
@@ -4076,6 +4487,7 @@ function createRoomEngine(options) {
|
|
|
4076
4487
|
}
|
|
4077
4488
|
},
|
|
4078
4489
|
disconnected(reason) {
|
|
4490
|
+
if (moving) return;
|
|
4079
4491
|
if (current !== null) {
|
|
4080
4492
|
tokens.invalidate(current.roomName);
|
|
4081
4493
|
current = null;
|
|
@@ -4090,11 +4502,13 @@ function createRoomEngine(options) {
|
|
|
4090
4502
|
roomName: request.roomName,
|
|
4091
4503
|
identity,
|
|
4092
4504
|
...request.meetingId !== void 0 ? { meetingId: request.meetingId } : {},
|
|
4093
|
-
...request.slug !== void 0 ? { slug: request.slug } : {}
|
|
4505
|
+
...request.slug !== void 0 ? { slug: request.slug } : {},
|
|
4506
|
+
...request.breakoutRoomId != null ? { breakoutRoomId: request.breakoutRoomId } : {}
|
|
4094
4507
|
});
|
|
4095
4508
|
current = token;
|
|
4096
4509
|
store.patch({
|
|
4097
4510
|
localIdentity: token.identity,
|
|
4511
|
+
breakoutRoomId: token.breakoutRoomId ?? null,
|
|
4098
4512
|
grants: {
|
|
4099
4513
|
role: token.role,
|
|
4100
4514
|
canRecord: token.canRecord,
|
|
@@ -4213,6 +4627,56 @@ function createRoomEngine(options) {
|
|
|
4213
4627
|
});
|
|
4214
4628
|
return joining;
|
|
4215
4629
|
},
|
|
4630
|
+
async moveToBreakout(roomId) {
|
|
4631
|
+
const request = lastRequest;
|
|
4632
|
+
if (request === null || driver === null) {
|
|
4633
|
+
report(
|
|
4634
|
+
"warn",
|
|
4635
|
+
"meet.moveToBreakout: this engine is not in a meeting room",
|
|
4636
|
+
"Join the meeting first; a breakout is a room OF a meeting."
|
|
4637
|
+
);
|
|
4638
|
+
return;
|
|
4639
|
+
}
|
|
4640
|
+
if ((store.snapshot().breakoutRoomId ?? null) === roomId) return;
|
|
4641
|
+
if (joining !== null) await joining.catch(() => void 0);
|
|
4642
|
+
const previous = driver;
|
|
4643
|
+
const next = {
|
|
4644
|
+
...request,
|
|
4645
|
+
breakoutRoomId: roomId,
|
|
4646
|
+
// Arrive as you were: camera and microphone as they are now.
|
|
4647
|
+
mode: store.snapshot().media.camera.enabled ? "video" : "audio",
|
|
4648
|
+
microphone: store.snapshot().media.microphone.enabled
|
|
4649
|
+
};
|
|
4650
|
+
moving = true;
|
|
4651
|
+
try {
|
|
4652
|
+
driver = null;
|
|
4653
|
+
tokens.invalidate(request.roomName);
|
|
4654
|
+
current = null;
|
|
4655
|
+
await previous.disconnect();
|
|
4656
|
+
lastRequest = next;
|
|
4657
|
+
joining = connect(next).finally(() => {
|
|
4658
|
+
joining = null;
|
|
4659
|
+
});
|
|
4660
|
+
await joining;
|
|
4661
|
+
} catch (error) {
|
|
4662
|
+
const normalized = normalizeMeetError(error, "meet.moveToBreakout");
|
|
4663
|
+
report("warn", normalized.message, normalized.remedy);
|
|
4664
|
+
if (roomId !== null) {
|
|
4665
|
+
lastRequest = { ...next, breakoutRoomId: null };
|
|
4666
|
+
joining = connect(lastRequest).finally(() => {
|
|
4667
|
+
joining = null;
|
|
4668
|
+
});
|
|
4669
|
+
await joining.catch((again) => {
|
|
4670
|
+
throw fail(again, "meet.moveToBreakout");
|
|
4671
|
+
});
|
|
4672
|
+
} else {
|
|
4673
|
+
throw fail(error, "meet.moveToBreakout");
|
|
4674
|
+
}
|
|
4675
|
+
throw normalized;
|
|
4676
|
+
} finally {
|
|
4677
|
+
moving = false;
|
|
4678
|
+
}
|
|
4679
|
+
},
|
|
4216
4680
|
leave: leaveRoom,
|
|
4217
4681
|
// Turning a device on mid-meeting is the SAME operation as turning it on
|
|
4218
4682
|
// during the join, so it runs the same function. A failure here used to
|
|
@@ -4482,6 +4946,109 @@ function createInRoomClient(options) {
|
|
|
4482
4946
|
(row) => typeof row === "object" && row !== null ? chatFromRow(row) : null
|
|
4483
4947
|
).filter((message) => message !== null);
|
|
4484
4948
|
store.loadChat(messages);
|
|
4949
|
+
},
|
|
4950
|
+
async loadCollab() {
|
|
4951
|
+
const operation = "meet.loadCollab";
|
|
4952
|
+
const id = meetingId(operation);
|
|
4953
|
+
const hdrs = headers();
|
|
4954
|
+
const response = await api.request({
|
|
4955
|
+
path: `${MEET_ROUTES.collab}?meeting_id=${encodeURIComponent(id)}`,
|
|
4956
|
+
method: "GET",
|
|
4957
|
+
operation,
|
|
4958
|
+
...hdrs !== void 0 ? { headers: hdrs } : {}
|
|
4959
|
+
});
|
|
4960
|
+
if (!response.ok) {
|
|
4961
|
+
const error = await refusal2(
|
|
4962
|
+
response,
|
|
4963
|
+
operation,
|
|
4964
|
+
"Polls, questions and the whiteboard could not be read. New ones still arrive."
|
|
4965
|
+
);
|
|
4966
|
+
store.patch({ collab: { ...store.snapshot().collab, loaded: true, error: error.message } });
|
|
4967
|
+
throw error;
|
|
4968
|
+
}
|
|
4969
|
+
const body = await response.json();
|
|
4970
|
+
store.patch({ collab: collabFromState(body, store.snapshot().collab) });
|
|
4971
|
+
},
|
|
4972
|
+
async collab(request) {
|
|
4973
|
+
const operation = `meet.collab(${request.action})`;
|
|
4974
|
+
const hdrs = headers();
|
|
4975
|
+
const response = await api.request({
|
|
4976
|
+
path: MEET_ROUTES.collab,
|
|
4977
|
+
method: "POST",
|
|
4978
|
+
operation,
|
|
4979
|
+
body: {
|
|
4980
|
+
meeting_id: meetingId(operation),
|
|
4981
|
+
action: request.action,
|
|
4982
|
+
...request.itemId !== void 0 ? { item_id: request.itemId } : {},
|
|
4983
|
+
...request.question !== void 0 ? { question: request.question } : {},
|
|
4984
|
+
...request.options !== void 0 ? { options: request.options } : {},
|
|
4985
|
+
...request.multiple !== void 0 ? { multiple: request.multiple } : {},
|
|
4986
|
+
...request.anonymous !== void 0 ? { anonymous: request.anonymous } : {},
|
|
4987
|
+
...request.optionIds !== void 0 ? { option_ids: request.optionIds } : {},
|
|
4988
|
+
...request.text !== void 0 ? { text: request.text } : {},
|
|
4989
|
+
...request.stroke !== void 0 ? { stroke: request.stroke } : {},
|
|
4990
|
+
...request.rooms !== void 0 ? { rooms: request.rooms } : {},
|
|
4991
|
+
...request.allowChoose !== void 0 ? { allow_choose: request.allowChoose } : {},
|
|
4992
|
+
...request.minutes !== void 0 ? { minutes: request.minutes } : {},
|
|
4993
|
+
...request.identity !== void 0 ? { identity: request.identity } : {},
|
|
4994
|
+
...request.roomId !== void 0 ? { room_id: request.roomId } : {}
|
|
4995
|
+
},
|
|
4996
|
+
...hdrs !== void 0 ? { headers: hdrs } : {}
|
|
4997
|
+
});
|
|
4998
|
+
if (!response.ok) {
|
|
4999
|
+
throw await refusal2(response, operation, "Nothing was changed.");
|
|
5000
|
+
}
|
|
5001
|
+
const payload = await response.json();
|
|
5002
|
+
const removed = Array.isArray(payload["removed"]) ? payload["removed"].filter((v) => typeof v === "string") : [];
|
|
5003
|
+
let next = store.snapshot().collab;
|
|
5004
|
+
const item = payload["item"];
|
|
5005
|
+
if (typeof item === "object" && item !== null) next = withItem(next, item);
|
|
5006
|
+
if (removed.length > 0) {
|
|
5007
|
+
const gone = new Set(removed);
|
|
5008
|
+
next = {
|
|
5009
|
+
...next,
|
|
5010
|
+
polls: next.polls.filter((p) => !gone.has(p.id)),
|
|
5011
|
+
questions: next.questions.filter((q) => !gone.has(q.id)),
|
|
5012
|
+
strokes: next.strokes.filter((st) => !gone.has(st.id))
|
|
5013
|
+
};
|
|
5014
|
+
}
|
|
5015
|
+
store.patch({ collab: next });
|
|
5016
|
+
const itemId = typeof item === "object" && item !== null && typeof item["id"] === "string" ? item["id"] : null;
|
|
5017
|
+
return {
|
|
5018
|
+
action: request.action,
|
|
5019
|
+
message: typeof payload["message"] === "string" ? payload["message"] : "Done.",
|
|
5020
|
+
removed,
|
|
5021
|
+
itemId
|
|
5022
|
+
};
|
|
5023
|
+
},
|
|
5024
|
+
async translateCaptions(language, lines) {
|
|
5025
|
+
if (lines.length === 0) return;
|
|
5026
|
+
const operation = "meet.translateCaptions";
|
|
5027
|
+
const hdrs = headers();
|
|
5028
|
+
const response = await api.request({
|
|
5029
|
+
path: MEET_ROUTES.captionsTranslate,
|
|
5030
|
+
method: "POST",
|
|
5031
|
+
operation,
|
|
5032
|
+
body: { meeting_id: meetingId(operation), target_language: language, lines },
|
|
5033
|
+
...hdrs !== void 0 ? { headers: hdrs } : {}
|
|
5034
|
+
});
|
|
5035
|
+
if (!response.ok) {
|
|
5036
|
+
const error = await refusal2(response, operation, "Captions stay in the language they were spoken.");
|
|
5037
|
+
store.patch({
|
|
5038
|
+
collab: { ...store.snapshot().collab, captionTranslationError: error.message }
|
|
5039
|
+
});
|
|
5040
|
+
throw error;
|
|
5041
|
+
}
|
|
5042
|
+
const payload = await response.json();
|
|
5043
|
+
const current = store.snapshot().collab;
|
|
5044
|
+
if (current.captionLanguage !== language) return;
|
|
5045
|
+
const merged = { ...current.captionTranslations };
|
|
5046
|
+
for (const [id, value] of Object.entries(payload.translations ?? {})) {
|
|
5047
|
+
if (typeof value === "string") merged[id] = value;
|
|
5048
|
+
}
|
|
5049
|
+
store.patch({
|
|
5050
|
+
collab: { ...current, captionTranslations: merged, captionTranslationError: null }
|
|
5051
|
+
});
|
|
4485
5052
|
}
|
|
4486
5053
|
};
|
|
4487
5054
|
}
|
|
@@ -5049,6 +5616,14 @@ function MeetRuntime(props) {
|
|
|
5049
5616
|
}
|
|
5050
5617
|
if (chatReadFor === snapshot.meeting.id) return;
|
|
5051
5618
|
chatReadFor = snapshot.meeting.id;
|
|
5619
|
+
void inRoom.loadCollab().catch((error) => {
|
|
5620
|
+
const normalized = error;
|
|
5621
|
+
report({
|
|
5622
|
+
level: "warn",
|
|
5623
|
+
message: normalized.message ?? "meet: polls, questions and the whiteboard could not be read",
|
|
5624
|
+
...normalized.remedy !== void 0 ? { remedy: normalized.remedy } : {}
|
|
5625
|
+
});
|
|
5626
|
+
});
|
|
5052
5627
|
void inRoom.loadChat().catch((error) => {
|
|
5053
5628
|
const normalized = error;
|
|
5054
5629
|
store.patch({
|
|
@@ -6389,7 +6964,7 @@ function useGuestRecordAccess(meeting) {
|
|
|
6389
6964
|
}
|
|
6390
6965
|
|
|
6391
6966
|
// src/react/components.tsx
|
|
6392
|
-
var
|
|
6967
|
+
var import_react5 = require("react");
|
|
6393
6968
|
var import_design_system = require("@ai-matrx/design-system");
|
|
6394
6969
|
var import_format3 = require("@ai-matrx/kit/format");
|
|
6395
6970
|
|
|
@@ -6456,12 +7031,19 @@ function coveredMs(intervals) {
|
|
|
6456
7031
|
}
|
|
6457
7032
|
function attendanceReport(meeting, attendees, names = {}) {
|
|
6458
7033
|
const end = ms(meeting.endedAt);
|
|
7034
|
+
const measuredOf = /* @__PURE__ */ new Map();
|
|
6459
7035
|
const perJoin = attendees.map((person) => {
|
|
6460
|
-
const
|
|
6461
|
-
|
|
6462
|
-
const
|
|
6463
|
-
const
|
|
6464
|
-
|
|
7036
|
+
const stays = person.sessions !== void 0 && person.sessions.length > 0 ? person.sessions.map((stay) => [ms(stay.joinedAt), ms(stay.leftAt)]) : [[ms(person.joinedAt), ms(person.leftAt)]];
|
|
7037
|
+
let toEnd = false;
|
|
7038
|
+
const measured = [];
|
|
7039
|
+
for (const [joined, left] of stays) {
|
|
7040
|
+
const until = left ?? end;
|
|
7041
|
+
if (joined === null || until === null || until < joined) continue;
|
|
7042
|
+
if (left === null) toEnd = true;
|
|
7043
|
+
measured.push([joined, until]);
|
|
7044
|
+
}
|
|
7045
|
+
const duration = measured.length === 0 ? null : coveredMs(measured);
|
|
7046
|
+
const row = {
|
|
6465
7047
|
id: person.id,
|
|
6466
7048
|
identity: person.identity,
|
|
6467
7049
|
name: displayNameFor(names, person.identity, person.displayName),
|
|
@@ -6470,10 +7052,12 @@ function attendanceReport(meeting, attendees, names = {}) {
|
|
|
6470
7052
|
joinedAt: person.joinedAt,
|
|
6471
7053
|
leftAt: person.leftAt,
|
|
6472
7054
|
durationMs: duration,
|
|
6473
|
-
durationToEnd: duration !== null &&
|
|
7055
|
+
durationToEnd: duration !== null && toEnd,
|
|
6474
7056
|
admission: person.admissionState,
|
|
6475
|
-
joins: 1
|
|
7057
|
+
joins: Math.max(1, person.sessions?.length ?? 0)
|
|
6476
7058
|
};
|
|
7059
|
+
measuredOf.set(row, measured);
|
|
7060
|
+
return row;
|
|
6477
7061
|
});
|
|
6478
7062
|
const groups = /* @__PURE__ */ new Map();
|
|
6479
7063
|
attendees.forEach((person, index) => {
|
|
@@ -6496,17 +7080,14 @@ function attendanceReport(meeting, attendees, names = {}) {
|
|
|
6496
7080
|
const left = ms(row.leftAt);
|
|
6497
7081
|
return left !== null && (latest === null || left > latest) ? left : latest;
|
|
6498
7082
|
}, null);
|
|
6499
|
-
const intervals = came.flatMap((row) =>
|
|
6500
|
-
const joined = ms(row.joinedAt);
|
|
6501
|
-
return joined !== null && row.durationMs !== null ? [[joined, joined + row.durationMs]] : [];
|
|
6502
|
-
});
|
|
7083
|
+
const intervals = came.flatMap((row) => measuredOf.get(row) ?? []);
|
|
6503
7084
|
return {
|
|
6504
7085
|
...first,
|
|
6505
7086
|
kind,
|
|
6506
7087
|
leftAt: open ? null : lastLeave === null ? null : new Date(lastLeave).toISOString(),
|
|
6507
7088
|
durationMs: intervals.length === 0 ? null : coveredMs(intervals),
|
|
6508
7089
|
durationToEnd: came.some((row) => row.durationToEnd),
|
|
6509
|
-
joins: came.length === 0 ? joins.length : came.
|
|
7090
|
+
joins: came.length === 0 ? joins.length : came.reduce((total, row) => total + row.joins, 0)
|
|
6510
7091
|
};
|
|
6511
7092
|
});
|
|
6512
7093
|
const rank = KIND_RANK;
|
|
@@ -6650,8 +7231,8 @@ function transcriptDocument(bundle, format, options = {}) {
|
|
|
6650
7231
|
if (line.identity !== last) {
|
|
6651
7232
|
if (last !== null) out.push("");
|
|
6652
7233
|
const who = speaker(line);
|
|
6653
|
-
const
|
|
6654
|
-
out.push(format === "md" ? `**${who}** \xB7 ${
|
|
7234
|
+
const clock2 = clockOfDay(line.startedAt, options);
|
|
7235
|
+
out.push(format === "md" ? `**${who}** \xB7 ${clock2}` : `${who} (${clock2})`);
|
|
6655
7236
|
last = line.identity;
|
|
6656
7237
|
}
|
|
6657
7238
|
out.push(line.text.trim());
|
|
@@ -6832,6 +7413,9 @@ function countLabel(count2, singular, plural = `${singular}s`) {
|
|
|
6832
7413
|
return `${count2} ${count2 === 1 ? singular : plural}`;
|
|
6833
7414
|
}
|
|
6834
7415
|
|
|
7416
|
+
// src/react/collab.tsx
|
|
7417
|
+
var import_react4 = require("react");
|
|
7418
|
+
|
|
6835
7419
|
// src/react/icons.tsx
|
|
6836
7420
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
6837
7421
|
function Icon({ children, ...props }) {
|
|
@@ -7016,99 +7600,1128 @@ function FlagIcon(props) {
|
|
|
7016
7600
|
function PencilIcon(props) {
|
|
7017
7601
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Icon, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M17 3a2.85 2.83 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5Z" }) });
|
|
7018
7602
|
}
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
|
|
7023
|
-
|
|
7024
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "mx-meet__empty-title", children: [
|
|
7025
|
-
what,
|
|
7026
|
-
" is not ready yet"
|
|
7027
|
-
] }),
|
|
7028
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mx-meet__empty-body", children: "Calls and meetings need a signed-in identity and an active organization. This will appear as soon as they resolve." })
|
|
7603
|
+
function ActivitiesIcon(props) {
|
|
7604
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Icon, { ...props, children: [
|
|
7605
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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" }),
|
|
7606
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { x: "3", y: "14", width: "7", height: "7", rx: "1" }),
|
|
7607
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "17.5", cy: "17.5", r: "3.5" })
|
|
7029
7608
|
] });
|
|
7030
7609
|
}
|
|
7031
|
-
function
|
|
7032
|
-
|
|
7033
|
-
|
|
7034
|
-
|
|
7035
|
-
|
|
7036
|
-
|
|
7037
|
-
if (url != null && url.length > 0) {
|
|
7038
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
7039
|
-
"img",
|
|
7040
|
-
{
|
|
7041
|
-
className: "mx-meet__avatar",
|
|
7042
|
-
src: url,
|
|
7043
|
-
alt: "",
|
|
7044
|
-
width: size,
|
|
7045
|
-
height: size,
|
|
7046
|
-
style: { width: size, height: size }
|
|
7047
|
-
}
|
|
7048
|
-
);
|
|
7049
|
-
}
|
|
7050
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
7051
|
-
"span",
|
|
7052
|
-
{
|
|
7053
|
-
className: "mx-meet__avatar mx-meet__avatar--initials",
|
|
7054
|
-
style: {
|
|
7055
|
-
width: size,
|
|
7056
|
-
height: size,
|
|
7057
|
-
fontSize: Math.round(size * 0.38),
|
|
7058
|
-
background: `var(--mx-meet-avatar-${tint})`
|
|
7059
|
-
},
|
|
7060
|
-
"aria-hidden": "true",
|
|
7061
|
-
children: (0, import_format3.getInitials)(name)
|
|
7062
|
-
}
|
|
7063
|
-
);
|
|
7610
|
+
function PollIcon(props) {
|
|
7611
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Icon, { ...props, children: [
|
|
7612
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "18", x2: "18", y1: "20", y2: "10" }),
|
|
7613
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "12", x2: "12", y1: "20", y2: "4" }),
|
|
7614
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "6", x2: "6", y1: "20", y2: "14" })
|
|
7615
|
+
] });
|
|
7064
7616
|
}
|
|
7065
|
-
function
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7071
|
-
}) {
|
|
7072
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
7073
|
-
"button",
|
|
7074
|
-
{
|
|
7075
|
-
type: "button",
|
|
7076
|
-
className: [
|
|
7077
|
-
"mx-meet__control",
|
|
7078
|
-
active ? "mx-meet__control--active" : "",
|
|
7079
|
-
danger ? "mx-meet__control--danger" : ""
|
|
7080
|
-
].filter(Boolean).join(" "),
|
|
7081
|
-
"aria-label": label,
|
|
7082
|
-
title: label,
|
|
7083
|
-
onClick,
|
|
7084
|
-
children
|
|
7085
|
-
}
|
|
7086
|
-
);
|
|
7617
|
+
function QuestionIcon(props) {
|
|
7618
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Icon, { ...props, children: [
|
|
7619
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M7.9 20A9 9 0 1 0 4 16.1L2 22Z" }),
|
|
7620
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" }),
|
|
7621
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 17h.01" })
|
|
7622
|
+
] });
|
|
7087
7623
|
}
|
|
7088
|
-
function
|
|
7089
|
-
|
|
7090
|
-
|
|
7091
|
-
|
|
7092
|
-
"
|
|
7093
|
-
|
|
7094
|
-
className: `mx-meet__recording mx-meet__recording--${state}`,
|
|
7095
|
-
role: "status",
|
|
7096
|
-
"aria-live": "polite",
|
|
7097
|
-
children: [
|
|
7098
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RecordIcon, { width: 10, height: 10 }),
|
|
7099
|
-
label
|
|
7100
|
-
]
|
|
7101
|
-
}
|
|
7102
|
-
);
|
|
7624
|
+
function WhiteboardIcon(props) {
|
|
7625
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Icon, { ...props, children: [
|
|
7626
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M2 3h20" }),
|
|
7627
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M21 3v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V3" }),
|
|
7628
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m7 21 5-5 5 5" })
|
|
7629
|
+
] });
|
|
7103
7630
|
}
|
|
7104
|
-
function
|
|
7105
|
-
|
|
7106
|
-
|
|
7631
|
+
function BreakoutIcon(props) {
|
|
7632
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Icon, { ...props, children: [
|
|
7633
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { width: "7", height: "18", x: "3", y: "3", rx: "1" }),
|
|
7634
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { width: "7", height: "7", x: "14", y: "3", rx: "1" }),
|
|
7635
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("rect", { width: "7", height: "7", x: "14", y: "14", rx: "1" })
|
|
7636
|
+
] });
|
|
7637
|
+
}
|
|
7638
|
+
function UpvoteIcon(props) {
|
|
7639
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Icon, { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M9 18v-6H5l7-7 7 7h-4v6H9z" }) });
|
|
7640
|
+
}
|
|
7641
|
+
function EraserIcon(props) {
|
|
7642
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Icon, { ...props, children: [
|
|
7643
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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" }),
|
|
7644
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M22 21H7" }),
|
|
7645
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m5 11 9 9" })
|
|
7646
|
+
] });
|
|
7647
|
+
}
|
|
7648
|
+
function HighlighterIcon(props) {
|
|
7649
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Icon, { ...props, children: [
|
|
7650
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "m9 11-6 6v3h9l3-3" }),
|
|
7651
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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" })
|
|
7652
|
+
] });
|
|
7653
|
+
}
|
|
7654
|
+
function UndoIcon(props) {
|
|
7655
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Icon, { ...props, children: [
|
|
7656
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M9 14 4 9l5-5" }),
|
|
7657
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("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" })
|
|
7658
|
+
] });
|
|
7659
|
+
}
|
|
7660
|
+
|
|
7661
|
+
// src/react/collab.tsx
|
|
7662
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
7663
|
+
function useCollab() {
|
|
7664
|
+
const host = useMeetHost();
|
|
7665
|
+
const snapshot = useMeetSnapshot();
|
|
7666
|
+
const isHost = useIsHost();
|
|
7667
|
+
return {
|
|
7668
|
+
collab: snapshot?.collab ?? null,
|
|
7669
|
+
isHost,
|
|
7670
|
+
localIdentity: snapshot?.localIdentity ?? null,
|
|
7671
|
+
breakoutRoomId: snapshot?.breakoutRoomId ?? null,
|
|
7672
|
+
async act(request) {
|
|
7673
|
+
if (host === null) return { ok: false, message: "This meeting is not connected." };
|
|
7674
|
+
try {
|
|
7675
|
+
const result = await host.inRoom.collab(request);
|
|
7676
|
+
return { ok: true, message: result.message, itemId: result.itemId };
|
|
7677
|
+
} catch (error) {
|
|
7678
|
+
return { ok: false, message: error.message ?? "That did not work." };
|
|
7679
|
+
}
|
|
7680
|
+
},
|
|
7681
|
+
async moveTo(roomId) {
|
|
7682
|
+
if (host === null) return { ok: false, message: "This meeting is not connected." };
|
|
7683
|
+
try {
|
|
7684
|
+
await host.engine.moveToBreakout(roomId);
|
|
7685
|
+
return { ok: true, message: roomId === null ? "Back in the main room." : "Joined the breakout room." };
|
|
7686
|
+
} catch (error) {
|
|
7687
|
+
return { ok: false, message: error.message ?? "That room could not be joined." };
|
|
7688
|
+
}
|
|
7689
|
+
}
|
|
7690
|
+
};
|
|
7691
|
+
}
|
|
7692
|
+
function useNotice() {
|
|
7693
|
+
const [notice, setNotice] = (0, import_react4.useState)(null);
|
|
7694
|
+
(0, import_react4.useEffect)(() => {
|
|
7695
|
+
if (notice === null) return void 0;
|
|
7696
|
+
const timer = setTimeout(() => setNotice(null), notice.failed ? 7e3 : 3e3);
|
|
7697
|
+
return () => clearTimeout(timer);
|
|
7698
|
+
}, [notice]);
|
|
7699
|
+
return [notice, (result) => setNotice({ text: result.message, failed: !result.ok })];
|
|
7700
|
+
}
|
|
7701
|
+
function Notice({ notice }) {
|
|
7702
|
+
if (notice === null) return null;
|
|
7703
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: notice.failed ? "mx-meet__panel-note mx-meet__collab-error" : "mx-meet__panel-note", role: "status", children: notice.text });
|
|
7704
|
+
}
|
|
7705
|
+
var ACTIVITY_LABELS = {
|
|
7706
|
+
polls: "Polls",
|
|
7707
|
+
qa: "Q&A",
|
|
7708
|
+
whiteboard: "Whiteboard",
|
|
7709
|
+
breakouts: "Breakout rooms"
|
|
7710
|
+
};
|
|
7711
|
+
function ActivityIcon({ panel }) {
|
|
7712
|
+
const props = { width: 16, height: 16 };
|
|
7713
|
+
if (panel === "polls") return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PollIcon, { ...props });
|
|
7714
|
+
if (panel === "qa") return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(QuestionIcon, { ...props });
|
|
7715
|
+
if (panel === "whiteboard") return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(WhiteboardIcon, { ...props });
|
|
7716
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(BreakoutIcon, { ...props });
|
|
7717
|
+
}
|
|
7718
|
+
function useAvailableActivities() {
|
|
7719
|
+
const { collab, isHost } = useCollab();
|
|
7720
|
+
const settings = collab?.settings ?? null;
|
|
7721
|
+
if (settings === null) return [];
|
|
7722
|
+
const out = [];
|
|
7723
|
+
if (settings.whiteboardEnabled) out.push("whiteboard");
|
|
7724
|
+
if (settings.pollsEnabled && (isHost || (collab?.polls.length ?? 0) > 0)) out.push("polls");
|
|
7725
|
+
if (settings.qaEnabled) out.push("qa");
|
|
7726
|
+
if (settings.breakoutsEnabled && (isHost || collab?.breakout?.state === "open")) out.push("breakouts");
|
|
7727
|
+
return out;
|
|
7728
|
+
}
|
|
7729
|
+
function useActivityAttention() {
|
|
7730
|
+
const { collab, isHost } = useCollab();
|
|
7731
|
+
if (collab === null) return false;
|
|
7732
|
+
if (collab.polls.some((poll) => poll.state === "live" && poll.myVote.length === 0 && !isHost)) return true;
|
|
7733
|
+
if (isHost && collab.questions.some((q) => q.state === "open")) return true;
|
|
7734
|
+
return false;
|
|
7735
|
+
}
|
|
7736
|
+
function ActivitiesControl({
|
|
7737
|
+
active,
|
|
7738
|
+
onOpen
|
|
7739
|
+
}) {
|
|
7740
|
+
const [open, setOpen] = (0, import_react4.useState)(false);
|
|
7741
|
+
const available = useAvailableActivities();
|
|
7742
|
+
const attention = useActivityAttention();
|
|
7743
|
+
if (available.length === 0) return null;
|
|
7744
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "mx-meet__anchor", children: [
|
|
7745
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(ControlButton, { label: "Activities", active: open || active !== null, onClick: () => setOpen(!open), children: [
|
|
7746
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ActivitiesIcon, {}),
|
|
7747
|
+
attention ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__dot", "aria-hidden": "true" }) : null
|
|
7748
|
+
] }),
|
|
7749
|
+
open ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Popover, { label: "Activities", onClose: () => setOpen(false), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mx-meet__menu", role: "menu", children: available.map((panel) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
7750
|
+
MenuItem,
|
|
7751
|
+
{
|
|
7752
|
+
onSelect: () => {
|
|
7753
|
+
setOpen(false);
|
|
7754
|
+
onOpen(panel);
|
|
7755
|
+
},
|
|
7756
|
+
children: [
|
|
7757
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ActivityIcon, { panel }),
|
|
7758
|
+
" ",
|
|
7759
|
+
ACTIVITY_LABELS[panel]
|
|
7760
|
+
]
|
|
7761
|
+
},
|
|
7762
|
+
panel
|
|
7763
|
+
)) }) }) : null
|
|
7764
|
+
] });
|
|
7765
|
+
}
|
|
7766
|
+
function PollComposer({ maxOptions, onDone }) {
|
|
7767
|
+
const { act } = useCollab();
|
|
7768
|
+
const [question, setQuestion] = (0, import_react4.useState)("");
|
|
7769
|
+
const [options, setOptions] = (0, import_react4.useState)(["", ""]);
|
|
7770
|
+
const [multiple, setMultiple] = (0, import_react4.useState)(false);
|
|
7771
|
+
const [anonymous, setAnonymous] = (0, import_react4.useState)(false);
|
|
7772
|
+
const [busy, setBusy] = (0, import_react4.useState)(false);
|
|
7773
|
+
const [notice, show] = useNotice();
|
|
7774
|
+
const filled = options.map((o) => o.trim()).filter(Boolean);
|
|
7775
|
+
const ready = question.trim().length > 0 && filled.length >= 2;
|
|
7776
|
+
const save = async (launch) => {
|
|
7777
|
+
setBusy(true);
|
|
7778
|
+
const created = await act({ action: "poll_create", question, options: filled, multiple, anonymous });
|
|
7779
|
+
if (!created.ok) {
|
|
7780
|
+
show(created);
|
|
7781
|
+
setBusy(false);
|
|
7782
|
+
return;
|
|
7783
|
+
}
|
|
7784
|
+
if (launch && created.itemId != null) {
|
|
7785
|
+
const launched = await act({ action: "poll_launch", itemId: created.itemId });
|
|
7786
|
+
if (!launched.ok) {
|
|
7787
|
+
show(launched);
|
|
7788
|
+
setBusy(false);
|
|
7789
|
+
return;
|
|
7790
|
+
}
|
|
7791
|
+
}
|
|
7792
|
+
setBusy(false);
|
|
7793
|
+
onDone();
|
|
7794
|
+
};
|
|
7795
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
7796
|
+
"form",
|
|
7797
|
+
{
|
|
7798
|
+
className: "mx-meet__collab-card",
|
|
7799
|
+
onSubmit: (event) => {
|
|
7800
|
+
event.preventDefault();
|
|
7801
|
+
if (ready) void save(true);
|
|
7802
|
+
},
|
|
7803
|
+
children: [
|
|
7804
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mx-meet__field", children: [
|
|
7805
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__field-label", children: "Question" }),
|
|
7806
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
7807
|
+
"input",
|
|
7808
|
+
{
|
|
7809
|
+
className: "mx-meet__input",
|
|
7810
|
+
value: question,
|
|
7811
|
+
maxLength: 1e3,
|
|
7812
|
+
onChange: (event) => setQuestion(event.target.value),
|
|
7813
|
+
placeholder: "Ask the room something",
|
|
7814
|
+
autoFocus: true
|
|
7815
|
+
}
|
|
7816
|
+
)
|
|
7817
|
+
] }),
|
|
7818
|
+
options.map((option, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mx-meet__composer-row", children: [
|
|
7819
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
7820
|
+
"input",
|
|
7821
|
+
{
|
|
7822
|
+
className: "mx-meet__input",
|
|
7823
|
+
value: option,
|
|
7824
|
+
maxLength: 200,
|
|
7825
|
+
"aria-label": `Answer ${index + 1}`,
|
|
7826
|
+
placeholder: `Answer ${index + 1}`,
|
|
7827
|
+
onChange: (event) => setOptions(options.map((o, i) => i === index ? event.target.value : o))
|
|
7828
|
+
}
|
|
7829
|
+
),
|
|
7830
|
+
options.length > 2 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ControlButton, { label: `Remove answer ${index + 1}`, onClick: () => setOptions(options.filter((_, i) => i !== index)), children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CloseIcon, { width: 14, height: 14 }) }) : null
|
|
7831
|
+
] }, index)),
|
|
7832
|
+
options.length < maxOptions ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mx-meet__link", onClick: () => setOptions([...options, ""]), children: "Add an answer" }) : null,
|
|
7833
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mx-meet__toggle", children: [
|
|
7834
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "checkbox", checked: multiple, onChange: (event) => setMultiple(event.target.checked) }),
|
|
7835
|
+
"People can pick more than one"
|
|
7836
|
+
] }),
|
|
7837
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mx-meet__toggle", children: [
|
|
7838
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "checkbox", checked: anonymous, onChange: (event) => setAnonymous(event.target.checked) }),
|
|
7839
|
+
"Anonymous \u2014 nobody sees who picked what"
|
|
7840
|
+
] }),
|
|
7841
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Notice, { notice }),
|
|
7842
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mx-meet__collab-actions", children: [
|
|
7843
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "submit", className: "mx-meet__primary mx-meet__primary--small", disabled: !ready || busy, children: "Launch" }),
|
|
7844
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mx-meet__chip", disabled: !ready || busy, onClick: () => void save(false), children: "Save draft" }),
|
|
7845
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mx-meet__link", onClick: onDone, children: "Cancel" })
|
|
7846
|
+
] })
|
|
7847
|
+
]
|
|
7848
|
+
}
|
|
7849
|
+
);
|
|
7850
|
+
}
|
|
7851
|
+
function PollCard({ poll }) {
|
|
7852
|
+
const { act, isHost } = useCollab();
|
|
7853
|
+
const [picked, setPicked] = (0, import_react4.useState)(poll.myVote.slice());
|
|
7854
|
+
const [notice, show] = useNotice();
|
|
7855
|
+
(0, import_react4.useEffect)(() => setPicked(poll.myVote.slice()), [poll.myVote]);
|
|
7856
|
+
const counts = poll.options.some((o) => o.votes !== void 0);
|
|
7857
|
+
const total = poll.options.reduce((sum, o) => sum + (o.votes ?? 0), 0);
|
|
7858
|
+
const canVote = poll.state === "live";
|
|
7859
|
+
const voted = poll.myVote.length > 0;
|
|
7860
|
+
const stateWord = poll.state === "draft" ? "Draft" : poll.state === "live" ? "Open" : "Closed";
|
|
7861
|
+
const toggle = (id) => {
|
|
7862
|
+
if (!canVote) return;
|
|
7863
|
+
setPicked(poll.multiple ? picked.includes(id) ? picked.filter((p) => p !== id) : [...picked, id] : [id]);
|
|
7864
|
+
};
|
|
7865
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { className: "mx-meet__collab-card", "aria-label": poll.question, children: [
|
|
7866
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("header", { className: "mx-meet__collab-head", children: [
|
|
7867
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { className: "mx-meet__collab-title", children: poll.question }),
|
|
7868
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__collab-state", children: stateWord })
|
|
7869
|
+
] }),
|
|
7870
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "mx-meet__panel-note", children: [
|
|
7871
|
+
poll.multiple ? "Pick any." : "Pick one.",
|
|
7872
|
+
poll.anonymous ? " Anonymous." : "",
|
|
7873
|
+
counts && poll.voterCount !== null ? ` ${poll.voterCount} voted.` : "",
|
|
7874
|
+
isHost && poll.state !== "draft" && !poll.resultsShared ? " Results are visible only to hosts." : ""
|
|
7875
|
+
] }),
|
|
7876
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ul", { className: "mx-meet__poll-options", children: poll.options.map((option) => {
|
|
7877
|
+
const share = counts && total > 0 ? Math.round((option.votes ?? 0) / total * 100) : 0;
|
|
7878
|
+
const chosen = picked.includes(option.id);
|
|
7879
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { children: [
|
|
7880
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
7881
|
+
"button",
|
|
7882
|
+
{
|
|
7883
|
+
type: "button",
|
|
7884
|
+
className: chosen ? "mx-meet__poll-option mx-meet__poll-option--chosen" : "mx-meet__poll-option",
|
|
7885
|
+
"aria-pressed": chosen,
|
|
7886
|
+
disabled: !canVote,
|
|
7887
|
+
onClick: () => toggle(option.id),
|
|
7888
|
+
children: [
|
|
7889
|
+
counts ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__poll-bar", style: { width: `${share}%` }, "aria-hidden": "true" }) : null,
|
|
7890
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__poll-text", children: option.text }),
|
|
7891
|
+
counts ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "mx-meet__poll-count", children: [
|
|
7892
|
+
option.votes ?? 0,
|
|
7893
|
+
" \xB7 ",
|
|
7894
|
+
share,
|
|
7895
|
+
"%"
|
|
7896
|
+
] }) : null
|
|
7897
|
+
]
|
|
7898
|
+
}
|
|
7899
|
+
),
|
|
7900
|
+
option.voters !== void 0 && option.voters.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__poll-voters", children: option.voters.join(", ") }) : null
|
|
7901
|
+
] }, option.id);
|
|
7902
|
+
}) }),
|
|
7903
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Notice, { notice }),
|
|
7904
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mx-meet__collab-actions", children: [
|
|
7905
|
+
canVote ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
7906
|
+
"button",
|
|
7907
|
+
{
|
|
7908
|
+
type: "button",
|
|
7909
|
+
className: "mx-meet__primary mx-meet__primary--small",
|
|
7910
|
+
disabled: picked.length === 0 || voted && picked.join() === poll.myVote.join(),
|
|
7911
|
+
onClick: () => void act({ action: "poll_vote", itemId: poll.id, optionIds: picked }).then(show),
|
|
7912
|
+
children: voted ? "Change vote" : "Vote"
|
|
7913
|
+
}
|
|
7914
|
+
) : null,
|
|
7915
|
+
isHost && poll.state === "draft" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mx-meet__primary mx-meet__primary--small", onClick: () => void act({ action: "poll_launch", itemId: poll.id }).then(show), children: "Launch" }) : null,
|
|
7916
|
+
isHost && poll.state === "live" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mx-meet__chip", onClick: () => void act({ action: "poll_close", itemId: poll.id }).then(show), children: "End poll" }) : null,
|
|
7917
|
+
isHost && poll.state !== "draft" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mx-meet__chip", onClick: () => void act({ action: "poll_share", itemId: poll.id }).then(show), children: poll.resultsShared ? "Hide results" : "Share results" }) : null,
|
|
7918
|
+
isHost && poll.state === "live" ? null : isHost ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mx-meet__link", onClick: () => void act({ action: "poll_delete", itemId: poll.id }).then(show), children: "Delete" }) : null
|
|
7919
|
+
] })
|
|
7920
|
+
] });
|
|
7921
|
+
}
|
|
7922
|
+
function PollsPanel({ onClose }) {
|
|
7923
|
+
const { collab, isHost } = useCollab();
|
|
7924
|
+
const [composing, setComposing] = (0, import_react4.useState)(false);
|
|
7925
|
+
const polls = collab?.polls ?? [];
|
|
7926
|
+
const maxOptions = collab?.settings?.pollMaxOptions ?? 10;
|
|
7927
|
+
const ordered = [...polls].reverse();
|
|
7928
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(PanelShell, { title: "Polls", onClose, children: [
|
|
7929
|
+
collab?.error != null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mx-meet__panel-note mx-meet__collab-error", children: collab.error }) : null,
|
|
7930
|
+
isHost && !composing ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mx-meet__primary mx-meet__primary--small", onClick: () => setComposing(true), children: "New poll" }) : null,
|
|
7931
|
+
isHost && composing ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PollComposer, { maxOptions, onDone: () => setComposing(false) }) : null,
|
|
7932
|
+
ordered.length === 0 && !composing ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mx-meet__panel-note", children: isHost ? "No polls yet. Polls and their results are kept with the meeting." : "No polls yet." }) : null,
|
|
7933
|
+
ordered.map((poll) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PollCard, { poll }, poll.id))
|
|
7934
|
+
] });
|
|
7935
|
+
}
|
|
7936
|
+
function QuestionCard({ question }) {
|
|
7937
|
+
const { act, isHost } = useCollab();
|
|
7938
|
+
const [answering, setAnswering] = (0, import_react4.useState)(false);
|
|
7939
|
+
const [reply, setReply] = (0, import_react4.useState)("");
|
|
7940
|
+
const [notice, show] = useNotice();
|
|
7941
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { className: `mx-meet__collab-card mx-meet__question mx-meet__question--${question.state}`, children: [
|
|
7942
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mx-meet__question-row", children: [
|
|
7943
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
7944
|
+
"button",
|
|
7945
|
+
{
|
|
7946
|
+
type: "button",
|
|
7947
|
+
className: question.upvotedByMe ? "mx-meet__upvote mx-meet__upvote--on" : "mx-meet__upvote",
|
|
7948
|
+
"aria-pressed": question.upvotedByMe,
|
|
7949
|
+
"aria-label": question.upvotedByMe ? "Remove your upvote" : "Upvote",
|
|
7950
|
+
disabled: question.state === "dismissed",
|
|
7951
|
+
onClick: () => void act({ action: "question_upvote", itemId: question.id }).then((r) => r.ok ? void 0 : show(r)),
|
|
7952
|
+
children: [
|
|
7953
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(UpvoteIcon, { width: 16, height: 16 }),
|
|
7954
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: question.upvotes })
|
|
7955
|
+
]
|
|
7956
|
+
}
|
|
7957
|
+
),
|
|
7958
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mx-meet__question-body", children: [
|
|
7959
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "mx-meet__chat-meta", children: [
|
|
7960
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: question.mine ? "You" : question.askerName }),
|
|
7961
|
+
question.mine && question.anonymous ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__chat-private", children: "anonymous" }) : null,
|
|
7962
|
+
question.state !== "open" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__collab-state", children: question.state === "answered" ? "Answered" : "Dismissed" }) : null
|
|
7963
|
+
] }),
|
|
7964
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__chat-text", children: question.text }),
|
|
7965
|
+
question.answer !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "mx-meet__question-answer", children: [
|
|
7966
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("strong", { children: [
|
|
7967
|
+
question.answeredByName ?? "Host",
|
|
7968
|
+
":"
|
|
7969
|
+
] }),
|
|
7970
|
+
" ",
|
|
7971
|
+
question.answer
|
|
7972
|
+
] }) : null
|
|
7973
|
+
] })
|
|
7974
|
+
] }),
|
|
7975
|
+
answering ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
7976
|
+
"form",
|
|
7977
|
+
{
|
|
7978
|
+
className: "mx-meet__composer-row",
|
|
7979
|
+
onSubmit: (event) => {
|
|
7980
|
+
event.preventDefault();
|
|
7981
|
+
void act({ action: "question_answer", itemId: question.id, text: reply }).then((r) => {
|
|
7982
|
+
show(r);
|
|
7983
|
+
if (r.ok) {
|
|
7984
|
+
setAnswering(false);
|
|
7985
|
+
setReply("");
|
|
7986
|
+
}
|
|
7987
|
+
});
|
|
7988
|
+
},
|
|
7989
|
+
children: [
|
|
7990
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
7991
|
+
"input",
|
|
7992
|
+
{
|
|
7993
|
+
className: "mx-meet__input",
|
|
7994
|
+
value: reply,
|
|
7995
|
+
maxLength: 2e3,
|
|
7996
|
+
onChange: (event) => setReply(event.target.value),
|
|
7997
|
+
placeholder: "Type an answer, or leave empty if you answered out loud",
|
|
7998
|
+
"aria-label": "Answer",
|
|
7999
|
+
autoFocus: true
|
|
8000
|
+
}
|
|
8001
|
+
),
|
|
8002
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "submit", className: "mx-meet__send", children: "Done" })
|
|
8003
|
+
]
|
|
8004
|
+
}
|
|
8005
|
+
) : null,
|
|
8006
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Notice, { notice }),
|
|
8007
|
+
isHost || question.mine ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mx-meet__collab-actions", children: [
|
|
8008
|
+
isHost && question.state === "open" && !answering ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mx-meet__chip", onClick: () => setAnswering(true), children: "Answer" }) : null,
|
|
8009
|
+
isHost && question.state === "open" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mx-meet__chip", onClick: () => void act({ action: "question_dismiss", itemId: question.id }).then(show), children: "Dismiss" }) : null,
|
|
8010
|
+
isHost && question.state !== "open" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mx-meet__chip", onClick: () => void act({ action: "question_reopen", itemId: question.id }).then(show), children: "Reopen" }) : null,
|
|
8011
|
+
question.mine || isHost ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mx-meet__link", onClick: () => void act({ action: "question_delete", itemId: question.id }).then(show), children: "Delete" }) : null
|
|
8012
|
+
] }) : null
|
|
8013
|
+
] });
|
|
8014
|
+
}
|
|
8015
|
+
function QaPanel({ onClose }) {
|
|
8016
|
+
const { collab, act } = useCollab();
|
|
8017
|
+
const [draft, setDraft] = (0, import_react4.useState)("");
|
|
8018
|
+
const [anonymous, setAnonymous] = (0, import_react4.useState)(false);
|
|
8019
|
+
const [order, setOrder] = (0, import_react4.useState)("popular");
|
|
8020
|
+
const [notice, show] = useNotice();
|
|
8021
|
+
const allowAnonymous = collab?.settings?.qaAnonymousAllowed === true;
|
|
8022
|
+
const questions = [...collab?.questions ?? []];
|
|
8023
|
+
const rank = (q) => q.state === "open" ? 0 : q.state === "answered" ? 1 : 2;
|
|
8024
|
+
questions.sort(
|
|
8025
|
+
(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 ?? "")
|
|
8026
|
+
);
|
|
8027
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(PanelShell, { title: "Q&A", onClose, children: [
|
|
8028
|
+
collab?.error != null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mx-meet__panel-note mx-meet__collab-error", children: collab.error }) : null,
|
|
8029
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
8030
|
+
"form",
|
|
8031
|
+
{
|
|
8032
|
+
className: "mx-meet__composer mx-meet__composer--chat",
|
|
8033
|
+
onSubmit: (event) => {
|
|
8034
|
+
event.preventDefault();
|
|
8035
|
+
const text3 = draft.trim();
|
|
8036
|
+
if (text3.length === 0) return;
|
|
8037
|
+
void act({ action: "question_ask", text: text3, anonymous: allowAnonymous && anonymous }).then((r) => {
|
|
8038
|
+
if (r.ok) setDraft("");
|
|
8039
|
+
else show(r);
|
|
8040
|
+
});
|
|
8041
|
+
},
|
|
8042
|
+
children: [
|
|
8043
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mx-meet__composer-row", children: [
|
|
8044
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
8045
|
+
"input",
|
|
8046
|
+
{
|
|
8047
|
+
className: "mx-meet__input",
|
|
8048
|
+
value: draft,
|
|
8049
|
+
maxLength: 1e3,
|
|
8050
|
+
onChange: (event) => setDraft(event.target.value),
|
|
8051
|
+
placeholder: "Ask the host a question",
|
|
8052
|
+
"aria-label": "Ask the host a question"
|
|
8053
|
+
}
|
|
8054
|
+
),
|
|
8055
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "submit", className: "mx-meet__send", disabled: draft.trim().length === 0, children: "Ask" })
|
|
8056
|
+
] }),
|
|
8057
|
+
allowAnonymous ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mx-meet__toggle", children: [
|
|
8058
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { type: "checkbox", checked: anonymous, onChange: (event) => setAnonymous(event.target.checked) }),
|
|
8059
|
+
"Ask anonymously"
|
|
8060
|
+
] }) : null
|
|
8061
|
+
]
|
|
8062
|
+
}
|
|
8063
|
+
),
|
|
8064
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Notice, { notice }),
|
|
8065
|
+
questions.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mx-meet__pills", role: "group", "aria-label": "Order questions", children: ["popular", "recent"].map((value) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
8066
|
+
"button",
|
|
8067
|
+
{
|
|
8068
|
+
type: "button",
|
|
8069
|
+
className: order === value ? "mx-meet__pill mx-meet__pill--on" : "mx-meet__pill",
|
|
8070
|
+
"aria-pressed": order === value,
|
|
8071
|
+
onClick: () => setOrder(value),
|
|
8072
|
+
children: value === "popular" ? "Popular" : "Recent"
|
|
8073
|
+
},
|
|
8074
|
+
value
|
|
8075
|
+
)) }) : null,
|
|
8076
|
+
questions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mx-meet__panel-note", children: "No questions yet. Questions are kept with the meeting." }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ul", { className: "mx-meet__chat", children: questions.map((question) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(QuestionCard, { question }, question.id)) })
|
|
8077
|
+
] });
|
|
8078
|
+
}
|
|
8079
|
+
var BOARD_W = 1600;
|
|
8080
|
+
var BOARD_H = 1e3;
|
|
8081
|
+
var INK = ["#111827", "#dc2626", "#2563eb", "#16a34a", "#f59e0b", "#7c3aed"];
|
|
8082
|
+
function strokePath(points) {
|
|
8083
|
+
if (points.length === 0) return "";
|
|
8084
|
+
const [first, ...rest] = points;
|
|
8085
|
+
const move = `M${(first[0] * BOARD_W).toFixed(1)} ${(first[1] * BOARD_H).toFixed(1)}`;
|
|
8086
|
+
if (rest.length === 0) return `${move} l0.1 0`;
|
|
8087
|
+
return `${move} ${rest.map(([x, y]) => `L${(x * BOARD_W).toFixed(1)} ${(y * BOARD_H).toFixed(1)}`).join(" ")}`;
|
|
8088
|
+
}
|
|
8089
|
+
function StrokeView({ stroke, onPick }) {
|
|
8090
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
8091
|
+
"path",
|
|
8092
|
+
{
|
|
8093
|
+
d: strokePath(stroke.points),
|
|
8094
|
+
fill: "none",
|
|
8095
|
+
stroke: stroke.color,
|
|
8096
|
+
strokeWidth: stroke.tool === "highlighter" ? stroke.width * 4 : stroke.width,
|
|
8097
|
+
strokeOpacity: stroke.tool === "highlighter" ? 0.35 : stroke.pending === true ? 0.6 : 1,
|
|
8098
|
+
strokeLinecap: "round",
|
|
8099
|
+
strokeLinejoin: "round",
|
|
8100
|
+
onPointerDown: onPick,
|
|
8101
|
+
style: onPick !== void 0 ? { cursor: "pointer" } : void 0,
|
|
8102
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("title", { children: stroke.byName })
|
|
8103
|
+
}
|
|
8104
|
+
);
|
|
8105
|
+
}
|
|
8106
|
+
function WhiteboardPanel({ onClose }) {
|
|
8107
|
+
const { collab, act, isHost, localIdentity } = useCollab();
|
|
8108
|
+
const [tool, setTool] = (0, import_react4.useState)("pen");
|
|
8109
|
+
const [color, setColor] = (0, import_react4.useState)(INK[0]);
|
|
8110
|
+
const [drawing, setDrawing] = (0, import_react4.useState)(null);
|
|
8111
|
+
const [pending, setPending] = (0, import_react4.useState)([]);
|
|
8112
|
+
const [notice, show] = useNotice();
|
|
8113
|
+
const svgRef = (0, import_react4.useRef)(null);
|
|
8114
|
+
const strokes = collab?.strokes ?? [];
|
|
8115
|
+
const mine = strokes.filter((s) => s.by === localIdentity);
|
|
8116
|
+
const point = (event) => {
|
|
8117
|
+
const svg = svgRef.current;
|
|
8118
|
+
if (svg === null) return null;
|
|
8119
|
+
const rect = svg.getBoundingClientRect();
|
|
8120
|
+
const scale = Math.min(rect.width / BOARD_W, rect.height / BOARD_H);
|
|
8121
|
+
const offsetX = (rect.width - BOARD_W * scale) / 2;
|
|
8122
|
+
const offsetY = (rect.height - BOARD_H * scale) / 2;
|
|
8123
|
+
const x = (event.clientX - rect.left - offsetX) / (BOARD_W * scale);
|
|
8124
|
+
const y = (event.clientY - rect.top - offsetY) / (BOARD_H * scale);
|
|
8125
|
+
return [Math.min(1, Math.max(0, x)), Math.min(1, Math.max(0, y))];
|
|
8126
|
+
};
|
|
8127
|
+
const finish = () => {
|
|
8128
|
+
const points = drawing;
|
|
8129
|
+
setDrawing(null);
|
|
8130
|
+
if (points === null || points.length === 0 || tool === "eraser") return;
|
|
8131
|
+
const thinned = points.filter((p, i) => i === 0 || i === points.length - 1 || i % 2 === 0).slice(0, 2e3);
|
|
8132
|
+
const stroke = {
|
|
8133
|
+
points: thinned.map(([x, y]) => [Number(x.toFixed(4)), Number(y.toFixed(4))]),
|
|
8134
|
+
color,
|
|
8135
|
+
width: tool === "highlighter" ? 4 : 3,
|
|
8136
|
+
tool: tool === "highlighter" ? "highlighter" : "pen"
|
|
8137
|
+
};
|
|
8138
|
+
const localId = `pending-${Date.now()}`;
|
|
8139
|
+
setPending((list) => [...list, { id: localId, ...stroke, by: localIdentity ?? "", byName: "You", pending: true }]);
|
|
8140
|
+
void act({ action: "stroke_add", stroke }).then((result) => {
|
|
8141
|
+
setPending((list) => list.filter((s) => s.id !== localId));
|
|
8142
|
+
if (!result.ok) show(result);
|
|
8143
|
+
});
|
|
8144
|
+
};
|
|
8145
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "mx-meet__whiteboard", "aria-label": "Whiteboard", children: [
|
|
8146
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("header", { className: "mx-meet__whiteboard-bar", children: [
|
|
8147
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { className: "mx-meet__panel-title", children: "Whiteboard" }),
|
|
8148
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mx-meet__pills", role: "group", "aria-label": "Tool", children: [
|
|
8149
|
+
["pen", "Pen", /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(PencilIcon, { width: 16, height: 16 }, "p")],
|
|
8150
|
+
["highlighter", "Highlighter", /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(HighlighterIcon, { width: 16, height: 16 }, "h")],
|
|
8151
|
+
["eraser", "Eraser \u2014 click a stroke", /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(EraserIcon, { width: 16, height: 16 }, "e")]
|
|
8152
|
+
].map(([value, label, icon]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
8153
|
+
"button",
|
|
8154
|
+
{
|
|
8155
|
+
type: "button",
|
|
8156
|
+
className: tool === value ? "mx-meet__pill mx-meet__pill--on" : "mx-meet__pill",
|
|
8157
|
+
"aria-pressed": tool === value,
|
|
8158
|
+
"aria-label": label,
|
|
8159
|
+
title: label,
|
|
8160
|
+
onClick: () => setTool(value),
|
|
8161
|
+
children: icon
|
|
8162
|
+
},
|
|
8163
|
+
value
|
|
8164
|
+
)) }),
|
|
8165
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mx-meet__swatches", role: "group", "aria-label": "Color", children: INK.map((ink) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
8166
|
+
"button",
|
|
8167
|
+
{
|
|
8168
|
+
type: "button",
|
|
8169
|
+
className: ink === color ? "mx-meet__swatch mx-meet__swatch--on" : "mx-meet__swatch",
|
|
8170
|
+
style: { background: ink },
|
|
8171
|
+
"aria-label": `Color ${ink}`,
|
|
8172
|
+
"aria-pressed": ink === color,
|
|
8173
|
+
onClick: () => {
|
|
8174
|
+
setColor(ink);
|
|
8175
|
+
if (tool === "eraser") setTool("pen");
|
|
8176
|
+
}
|
|
8177
|
+
},
|
|
8178
|
+
ink
|
|
8179
|
+
)) }),
|
|
8180
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
8181
|
+
ControlButton,
|
|
8182
|
+
{
|
|
8183
|
+
label: "Undo my last stroke",
|
|
8184
|
+
onClick: () => {
|
|
8185
|
+
const last = mine[mine.length - 1];
|
|
8186
|
+
if (last !== void 0) void act({ action: "stroke_erase", itemId: last.id }).then((r) => r.ok ? void 0 : show(r));
|
|
8187
|
+
},
|
|
8188
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(UndoIcon, { width: 16, height: 16 })
|
|
8189
|
+
}
|
|
8190
|
+
),
|
|
8191
|
+
isHost && strokes.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mx-meet__chip", onClick: () => void act({ action: "whiteboard_clear" }).then(show), children: "Clear board" }) : null,
|
|
8192
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__whiteboard-note", children: "Saved with the meeting" }),
|
|
8193
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ControlButton, { label: "Close whiteboard", onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(CloseIcon, { width: 16, height: 16 }) })
|
|
8194
|
+
] }),
|
|
8195
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Notice, { notice }),
|
|
8196
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
8197
|
+
"svg",
|
|
8198
|
+
{
|
|
8199
|
+
ref: svgRef,
|
|
8200
|
+
className: tool === "eraser" ? "mx-meet__board mx-meet__board--erase" : "mx-meet__board",
|
|
8201
|
+
viewBox: `0 0 ${BOARD_W} ${BOARD_H}`,
|
|
8202
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
8203
|
+
role: "img",
|
|
8204
|
+
"aria-label": `Shared whiteboard, ${strokes.length} strokes`,
|
|
8205
|
+
onPointerDown: (event) => {
|
|
8206
|
+
if (tool === "eraser") return;
|
|
8207
|
+
const p = point(event);
|
|
8208
|
+
if (p === null) return;
|
|
8209
|
+
event.target.setPointerCapture?.(event.pointerId);
|
|
8210
|
+
setDrawing([p]);
|
|
8211
|
+
},
|
|
8212
|
+
onPointerMove: (event) => {
|
|
8213
|
+
if (drawing === null) return;
|
|
8214
|
+
const p = point(event);
|
|
8215
|
+
if (p !== null) setDrawing([...drawing, p]);
|
|
8216
|
+
},
|
|
8217
|
+
onPointerUp: finish,
|
|
8218
|
+
onPointerCancel: finish,
|
|
8219
|
+
children: [
|
|
8220
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: 0, y: 0, width: BOARD_W, height: BOARD_H, className: "mx-meet__board-paper" }),
|
|
8221
|
+
strokes.map((stroke) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
8222
|
+
StrokeView,
|
|
8223
|
+
{
|
|
8224
|
+
stroke,
|
|
8225
|
+
onPick: tool === "eraser" && (isHost || stroke.by === localIdentity) ? () => void act({ action: "stroke_erase", itemId: stroke.id }).then((r) => r.ok ? void 0 : show(r)) : void 0
|
|
8226
|
+
},
|
|
8227
|
+
stroke.id
|
|
8228
|
+
)),
|
|
8229
|
+
pending.map((stroke) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(StrokeView, { stroke }, stroke.id)),
|
|
8230
|
+
drawing !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
8231
|
+
StrokeView,
|
|
8232
|
+
{
|
|
8233
|
+
stroke: {
|
|
8234
|
+
id: "drawing",
|
|
8235
|
+
points: drawing,
|
|
8236
|
+
color,
|
|
8237
|
+
width: tool === "highlighter" ? 4 : 3,
|
|
8238
|
+
tool: tool === "highlighter" ? "highlighter" : "pen",
|
|
8239
|
+
by: "",
|
|
8240
|
+
byName: "You"
|
|
8241
|
+
}
|
|
8242
|
+
}
|
|
8243
|
+
) : null
|
|
8244
|
+
]
|
|
8245
|
+
}
|
|
8246
|
+
)
|
|
8247
|
+
] });
|
|
8248
|
+
}
|
|
8249
|
+
function clock(ms2) {
|
|
8250
|
+
const total = Math.ceil(ms2 / 1e3);
|
|
8251
|
+
const minutes = Math.floor(total / 60);
|
|
8252
|
+
const seconds = total % 60;
|
|
8253
|
+
return `${minutes}:${seconds.toString().padStart(2, "0")}`;
|
|
8254
|
+
}
|
|
8255
|
+
function useNow(active) {
|
|
8256
|
+
const [now, setNow] = (0, import_react4.useState)(() => Date.now());
|
|
8257
|
+
(0, import_react4.useEffect)(() => {
|
|
8258
|
+
if (!active) return void 0;
|
|
8259
|
+
const timer = setInterval(() => setNow(Date.now()), 1e3);
|
|
8260
|
+
return () => clearInterval(timer);
|
|
8261
|
+
}, [active]);
|
|
8262
|
+
return now;
|
|
8263
|
+
}
|
|
8264
|
+
function BreakoutSetup() {
|
|
8265
|
+
const { collab, act } = useCollab();
|
|
8266
|
+
const snapshot = useMeetSnapshot();
|
|
8267
|
+
const settings = collab?.settings ?? null;
|
|
8268
|
+
const people = (snapshot?.participants ?? []).filter(
|
|
8269
|
+
(p) => !p.isAgent && p.role !== "host" && p.role !== "cohost"
|
|
8270
|
+
);
|
|
8271
|
+
const [count2, setCount] = (0, import_react4.useState)(Math.min(Math.max(2, Math.ceil(people.length / 4)), settings?.breakoutMaxRooms ?? 20));
|
|
8272
|
+
const [mode, setMode] = (0, import_react4.useState)("auto");
|
|
8273
|
+
const [minutes, setMinutes] = (0, import_react4.useState)(settings?.breakoutDefaultMinutes ?? 15);
|
|
8274
|
+
const [manual, setManual] = (0, import_react4.useState)({});
|
|
8275
|
+
const [busy, setBusy] = (0, import_react4.useState)(false);
|
|
8276
|
+
const [notice, show] = useNotice();
|
|
8277
|
+
const max = settings?.breakoutMaxRooms ?? 20;
|
|
8278
|
+
const rooms = Math.min(Math.max(1, count2), max);
|
|
8279
|
+
const assignment = mode === "auto" ? autoAssign(
|
|
8280
|
+
people.map((p) => p.identity),
|
|
8281
|
+
rooms
|
|
8282
|
+
) : mode === "manual" ? Array.from(
|
|
8283
|
+
{ length: rooms },
|
|
8284
|
+
(_, index) => people.filter((p) => (manual[p.identity] ?? -1) === index).map((p) => p.identity)
|
|
8285
|
+
) : Array.from({ length: rooms }, () => []);
|
|
8286
|
+
const nameOf = (identity) => people.find((p) => p.identity === identity)?.displayName ?? identity;
|
|
8287
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mx-meet__collab-card", children: [
|
|
8288
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mx-meet__field", children: [
|
|
8289
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__field-label", children: "Rooms" }),
|
|
8290
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
8291
|
+
"input",
|
|
8292
|
+
{
|
|
8293
|
+
className: "mx-meet__input",
|
|
8294
|
+
type: "number",
|
|
8295
|
+
min: 1,
|
|
8296
|
+
max,
|
|
8297
|
+
value: count2,
|
|
8298
|
+
onChange: (event) => setCount(Number(event.target.value) || 1)
|
|
8299
|
+
}
|
|
8300
|
+
)
|
|
8301
|
+
] }),
|
|
8302
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "mx-meet__pills", role: "group", "aria-label": "How people are placed", children: [
|
|
8303
|
+
["auto", "Automatically"],
|
|
8304
|
+
["manual", "Manually"],
|
|
8305
|
+
["choose", "Let people choose"]
|
|
8306
|
+
].map(([value, label]) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
8307
|
+
"button",
|
|
8308
|
+
{
|
|
8309
|
+
type: "button",
|
|
8310
|
+
className: mode === value ? "mx-meet__pill mx-meet__pill--on" : "mx-meet__pill",
|
|
8311
|
+
"aria-pressed": mode === value,
|
|
8312
|
+
onClick: () => setMode(value),
|
|
8313
|
+
children: label
|
|
8314
|
+
},
|
|
8315
|
+
value
|
|
8316
|
+
)) }),
|
|
8317
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mx-meet__field", children: [
|
|
8318
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__field-label", children: "Timer (minutes, 0 for none)" }),
|
|
8319
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
8320
|
+
"input",
|
|
8321
|
+
{
|
|
8322
|
+
className: "mx-meet__input",
|
|
8323
|
+
type: "number",
|
|
8324
|
+
min: 0,
|
|
8325
|
+
max: 720,
|
|
8326
|
+
value: minutes,
|
|
8327
|
+
onChange: (event) => setMinutes(Math.max(0, Number(event.target.value) || 0))
|
|
8328
|
+
}
|
|
8329
|
+
)
|
|
8330
|
+
] }),
|
|
8331
|
+
mode === "manual" ? people.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mx-meet__panel-note", children: "Nobody else is in the meeting yet." }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ul", { className: "mx-meet__people", children: people.map((person) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { className: "mx-meet__person", children: [
|
|
8332
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__person-name", children: person.displayName }),
|
|
8333
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
8334
|
+
"select",
|
|
8335
|
+
{
|
|
8336
|
+
className: "mx-meet__select mx-meet__select--compact",
|
|
8337
|
+
"aria-label": `Room for ${person.displayName}`,
|
|
8338
|
+
value: manual[person.identity] ?? -1,
|
|
8339
|
+
onChange: (event) => setManual({ ...manual, [person.identity]: Number(event.target.value) }),
|
|
8340
|
+
children: [
|
|
8341
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: -1, children: "Main room" }),
|
|
8342
|
+
Array.from({ length: rooms }, (_, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("option", { value: index, children: [
|
|
8343
|
+
"Room ",
|
|
8344
|
+
index + 1
|
|
8345
|
+
] }, index))
|
|
8346
|
+
]
|
|
8347
|
+
}
|
|
8348
|
+
)
|
|
8349
|
+
] }, person.identity)) }) : mode === "auto" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ul", { className: "mx-meet__breakout-rooms", children: assignment.map((members, index) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { children: [
|
|
8350
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("strong", { children: [
|
|
8351
|
+
"Room ",
|
|
8352
|
+
index + 1
|
|
8353
|
+
] }),
|
|
8354
|
+
" ",
|
|
8355
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__panel-note", children: members.length === 0 ? "empty" : members.map(nameOf).join(", ") })
|
|
8356
|
+
] }, index)) }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mx-meet__panel-note", children: "Everyone picks a room from their own screen." }),
|
|
8357
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Notice, { notice }),
|
|
8358
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
8359
|
+
"button",
|
|
8360
|
+
{
|
|
8361
|
+
type: "button",
|
|
8362
|
+
className: "mx-meet__primary mx-meet__primary--small",
|
|
8363
|
+
disabled: busy,
|
|
8364
|
+
onClick: () => {
|
|
8365
|
+
setBusy(true);
|
|
8366
|
+
void act({
|
|
8367
|
+
action: "breakout_open",
|
|
8368
|
+
rooms: assignment.map((identities, index) => ({ name: `Room ${index + 1}`, identities })),
|
|
8369
|
+
allowChoose: mode === "choose",
|
|
8370
|
+
minutes
|
|
8371
|
+
}).then((result) => {
|
|
8372
|
+
setBusy(false);
|
|
8373
|
+
show(result);
|
|
8374
|
+
});
|
|
8375
|
+
},
|
|
8376
|
+
children: [
|
|
8377
|
+
"Open ",
|
|
8378
|
+
rooms,
|
|
8379
|
+
" room",
|
|
8380
|
+
rooms === 1 ? "" : "s"
|
|
8381
|
+
]
|
|
8382
|
+
}
|
|
8383
|
+
)
|
|
8384
|
+
] });
|
|
8385
|
+
}
|
|
8386
|
+
function BreakoutRun({ plan }) {
|
|
8387
|
+
const { act, moveTo, isHost, breakoutRoomId, localIdentity } = useCollab();
|
|
8388
|
+
const snapshot = useMeetSnapshot();
|
|
8389
|
+
const now = useNow(plan.endsAt !== null);
|
|
8390
|
+
const remaining = breakoutRemainingMs(plan, now);
|
|
8391
|
+
const [broadcast, setBroadcast] = (0, import_react4.useState)("");
|
|
8392
|
+
const [notice, show] = useNotice();
|
|
8393
|
+
const nameOf = (identity) => displayNameFor(snapshot?.names ?? {}, identity, snapshot?.participants.find((p) => p.identity === identity)?.displayName);
|
|
8394
|
+
const mine = assignedRoom(plan, localIdentity);
|
|
8395
|
+
const join = async (roomId) => {
|
|
8396
|
+
const said = await act({ action: "breakout_join", roomId });
|
|
8397
|
+
if (!said.ok) {
|
|
8398
|
+
show(said);
|
|
8399
|
+
return;
|
|
8400
|
+
}
|
|
8401
|
+
show(await moveTo(roomId));
|
|
8402
|
+
};
|
|
8403
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mx-meet__collab-card", children: [
|
|
8404
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "mx-meet__panel-note", children: [
|
|
8405
|
+
plan.rooms.length,
|
|
8406
|
+
" room",
|
|
8407
|
+
plan.rooms.length === 1 ? "" : "s",
|
|
8408
|
+
" open",
|
|
8409
|
+
remaining !== null ? ` \xB7 ${clock(remaining)} left` : "",
|
|
8410
|
+
plan.allowChoose ? " \xB7 people choose their room" : ""
|
|
8411
|
+
] }),
|
|
8412
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ul", { className: "mx-meet__breakout-rooms", children: plan.rooms.map((room) => {
|
|
8413
|
+
const here = breakoutRoomId === room.id;
|
|
8414
|
+
const mayJoin = isHost || plan.allowChoose || mine?.id === room.id;
|
|
8415
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { className: here ? "mx-meet__breakout-room mx-meet__breakout-room--here" : "mx-meet__breakout-room", children: [
|
|
8416
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mx-meet__collab-head", children: [
|
|
8417
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: room.name }),
|
|
8418
|
+
here ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__collab-state", children: "You are here" }) : mayJoin ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mx-meet__chip", onClick: () => void join(room.id), children: "Join" }) : null
|
|
8419
|
+
] }),
|
|
8420
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__panel-note", children: room.identities.length === 0 ? "Nobody assigned" : room.identities.map(nameOf).join(", ") }),
|
|
8421
|
+
isHost && room.identities.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ul", { className: "mx-meet__people", children: room.identities.map((identity) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { className: "mx-meet__person", children: [
|
|
8422
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__person-name", children: nameOf(identity) }),
|
|
8423
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
8424
|
+
"select",
|
|
8425
|
+
{
|
|
8426
|
+
className: "mx-meet__select mx-meet__select--compact",
|
|
8427
|
+
"aria-label": `Move ${nameOf(identity)}`,
|
|
8428
|
+
value: room.id,
|
|
8429
|
+
onChange: (event) => void act({
|
|
8430
|
+
action: "breakout_move",
|
|
8431
|
+
identity,
|
|
8432
|
+
roomId: event.target.value === "" ? null : event.target.value
|
|
8433
|
+
}).then(show),
|
|
8434
|
+
children: [
|
|
8435
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "", children: "Main room" }),
|
|
8436
|
+
plan.rooms.map((option) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: option.id, children: option.name }, option.id))
|
|
8437
|
+
]
|
|
8438
|
+
}
|
|
8439
|
+
)
|
|
8440
|
+
] }, identity)) }) : null
|
|
8441
|
+
] }, room.id);
|
|
8442
|
+
}) }),
|
|
8443
|
+
breakoutRoomId !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mx-meet__chip", onClick: () => void join(null), children: "Return to the main room" }) : null,
|
|
8444
|
+
isHost ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
8445
|
+
"form",
|
|
8446
|
+
{
|
|
8447
|
+
className: "mx-meet__composer-row",
|
|
8448
|
+
onSubmit: (event) => {
|
|
8449
|
+
event.preventDefault();
|
|
8450
|
+
const text3 = broadcast.trim();
|
|
8451
|
+
if (text3.length === 0) return;
|
|
8452
|
+
void act({ action: "breakout_broadcast", text: text3 }).then((result) => {
|
|
8453
|
+
show(result);
|
|
8454
|
+
if (result.ok) setBroadcast("");
|
|
8455
|
+
});
|
|
8456
|
+
},
|
|
8457
|
+
children: [
|
|
8458
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
8459
|
+
"input",
|
|
8460
|
+
{
|
|
8461
|
+
className: "mx-meet__input",
|
|
8462
|
+
value: broadcast,
|
|
8463
|
+
maxLength: 500,
|
|
8464
|
+
onChange: (event) => setBroadcast(event.target.value),
|
|
8465
|
+
placeholder: "Message every room",
|
|
8466
|
+
"aria-label": "Message every room"
|
|
8467
|
+
}
|
|
8468
|
+
),
|
|
8469
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "submit", className: "mx-meet__send", disabled: broadcast.trim().length === 0, children: "Send" })
|
|
8470
|
+
]
|
|
8471
|
+
}
|
|
8472
|
+
) : null,
|
|
8473
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Notice, { notice }),
|
|
8474
|
+
isHost ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
8475
|
+
"button",
|
|
8476
|
+
{
|
|
8477
|
+
type: "button",
|
|
8478
|
+
className: "mx-meet__primary mx-meet__primary--small",
|
|
8479
|
+
onClick: () => void act({ action: "breakout_close" }).then(show),
|
|
8480
|
+
children: "Bring everyone back"
|
|
8481
|
+
}
|
|
8482
|
+
) : null
|
|
8483
|
+
] });
|
|
8484
|
+
}
|
|
8485
|
+
function BreakoutsPanel({ onClose }) {
|
|
8486
|
+
const { collab, isHost } = useCollab();
|
|
8487
|
+
const plan = collab?.breakout?.state === "open" ? collab.breakout : null;
|
|
8488
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(PanelShell, { title: "Breakout rooms", onClose, children: [
|
|
8489
|
+
collab?.error != null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mx-meet__panel-note mx-meet__collab-error", children: collab.error }) : null,
|
|
8490
|
+
plan !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(BreakoutRun, { plan }) : isHost ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(BreakoutSetup, {}) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mx-meet__panel-note", children: "Breakout rooms are closed." })
|
|
8491
|
+
] });
|
|
8492
|
+
}
|
|
8493
|
+
function BreakoutBanner() {
|
|
8494
|
+
const host = useMeetHost();
|
|
8495
|
+
const { collab, act, moveTo, localIdentity, breakoutRoomId } = useCollab();
|
|
8496
|
+
const plan = collab?.breakout ?? null;
|
|
8497
|
+
const open = plan?.state === "open" ? plan : null;
|
|
8498
|
+
const now = useNow(open?.endsAt != null);
|
|
8499
|
+
const remaining = breakoutRemainingMs(open, now);
|
|
8500
|
+
const assigned = assignedRoom(open, localIdentity);
|
|
8501
|
+
const [dismissedBroadcast, setDismissedBroadcast] = (0, import_react4.useState)(null);
|
|
8502
|
+
const [failure, setFailure] = (0, import_react4.useState)(null);
|
|
8503
|
+
const expireAsked = (0, import_react4.useRef)(null);
|
|
8504
|
+
const moveAt = collab?.moveRequest?.at ?? null;
|
|
8505
|
+
(0, import_react4.useEffect)(() => {
|
|
8506
|
+
const request = host?.store.snapshot().collab.moveRequest ?? null;
|
|
8507
|
+
if (request === null || host === null) return;
|
|
8508
|
+
host.store.patch({ collab: { ...host.store.snapshot().collab, moveRequest: null } });
|
|
8509
|
+
const here = host.store.snapshot().breakoutRoomId;
|
|
8510
|
+
if ((here ?? null) === request.roomId) return;
|
|
8511
|
+
void moveTo(request.roomId).then((result) => setFailure(result.ok ? null : result.message));
|
|
8512
|
+
}, [moveAt, host, moveTo]);
|
|
8513
|
+
(0, import_react4.useEffect)(() => {
|
|
8514
|
+
if (open === null || remaining === null || remaining > 0) return;
|
|
8515
|
+
if (expireAsked.current === open.id) return;
|
|
8516
|
+
expireAsked.current = open.id;
|
|
8517
|
+
void act({ action: "breakout_expire" });
|
|
8518
|
+
}, [open, remaining, act]);
|
|
8519
|
+
const broadcast = collab?.broadcast ?? null;
|
|
8520
|
+
const showBroadcast = broadcast !== null && broadcast.at !== dismissedBroadcast && open !== null;
|
|
8521
|
+
const room = open?.rooms.find((r) => r.id === breakoutRoomId) ?? null;
|
|
8522
|
+
if (open === null && failure === null) return null;
|
|
8523
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mx-meet__breakout-banner", role: "status", children: [
|
|
8524
|
+
failure !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__collab-error", children: failure }) : null,
|
|
8525
|
+
room !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
|
|
8526
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: room.name }),
|
|
8527
|
+
remaining !== null ? ` \xB7 ${clock(remaining)} left` : "",
|
|
8528
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mx-meet__chip", onClick: () => void moveTo(null), children: "Return to main room" })
|
|
8529
|
+
] }) : assigned !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { children: [
|
|
8530
|
+
"You are assigned to ",
|
|
8531
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: assigned.name }),
|
|
8532
|
+
remaining !== null ? ` \xB7 ${clock(remaining)} left` : "",
|
|
8533
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
8534
|
+
"button",
|
|
8535
|
+
{
|
|
8536
|
+
type: "button",
|
|
8537
|
+
className: "mx-meet__primary mx-meet__primary--small",
|
|
8538
|
+
onClick: () => void act({ action: "breakout_join", roomId: assigned.id }).then(async (said) => {
|
|
8539
|
+
const result = said.ok ? await moveTo(assigned.id) : said;
|
|
8540
|
+
setFailure(result.ok ? null : result.message);
|
|
8541
|
+
}),
|
|
8542
|
+
children: "Join"
|
|
8543
|
+
}
|
|
8544
|
+
)
|
|
8545
|
+
] }) : open?.allowChoose ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "Breakout rooms are open \u2014 pick one under Activities." }) : null,
|
|
8546
|
+
showBroadcast ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "mx-meet__breakout-broadcast", children: [
|
|
8547
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("strong", { children: [
|
|
8548
|
+
broadcast.by,
|
|
8549
|
+
":"
|
|
8550
|
+
] }),
|
|
8551
|
+
" ",
|
|
8552
|
+
broadcast.text,
|
|
8553
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "mx-meet__link", onClick: () => setDismissedBroadcast(broadcast.at), children: "Dismiss" })
|
|
8554
|
+
] }) : null
|
|
8555
|
+
] });
|
|
8556
|
+
}
|
|
8557
|
+
function useCaptionTranslation(lines) {
|
|
8558
|
+
const host = useMeetHost();
|
|
8559
|
+
const snapshot = useMeetSnapshot();
|
|
8560
|
+
const collab = snapshot?.collab ?? null;
|
|
8561
|
+
const language = collab?.captionLanguage ?? null;
|
|
8562
|
+
const asked = (0, import_react4.useRef)(/* @__PURE__ */ new Set());
|
|
8563
|
+
const translations = collab?.captionTranslations ?? {};
|
|
8564
|
+
const missing = lines.filter((line) => line.final && translations[line.id] === void 0).map(({ id, text: text3 }) => ({ id, text: text3 }));
|
|
8565
|
+
const key = `${language ?? ""}|${missing.map((l) => l.id).join(",")}`;
|
|
8566
|
+
const pending = (0, import_react4.useRef)(missing);
|
|
8567
|
+
pending.current = missing;
|
|
8568
|
+
(0, import_react4.useEffect)(() => {
|
|
8569
|
+
if (host === null || language === null) return;
|
|
8570
|
+
const batch = pending.current.filter((line) => !asked.current.has(`${language}:${line.id}`)).slice(-20);
|
|
8571
|
+
if (batch.length === 0) return;
|
|
8572
|
+
for (const line of batch) asked.current.add(`${language}:${line.id}`);
|
|
8573
|
+
void host.inRoom.translateCaptions(language, batch).catch(() => void 0);
|
|
8574
|
+
}, [host, language, key]);
|
|
8575
|
+
return { language, translations, error: collab?.captionTranslationError ?? null };
|
|
8576
|
+
}
|
|
8577
|
+
function CaptionLanguageSettings() {
|
|
8578
|
+
const host = useMeetHost();
|
|
8579
|
+
const snapshot = useMeetSnapshot();
|
|
8580
|
+
const collab = snapshot?.collab ?? null;
|
|
8581
|
+
const settings = collab?.settings ?? null;
|
|
8582
|
+
if (host === null || settings === null || !settings.captionTranslationEnabled) return null;
|
|
8583
|
+
const viewer = typeof navigator !== "undefined" && typeof navigator.language === "string" ? navigator.language.slice(0, 2) : null;
|
|
8584
|
+
const preferred = defaultCaptionLanguage(settings, viewer);
|
|
8585
|
+
const current = collab?.captionLanguage ?? "";
|
|
8586
|
+
const choices = CAPTION_LANGUAGES.some((l) => l.tag === preferred) ? CAPTION_LANGUAGES : [{ tag: preferred, name: preferred }, ...CAPTION_LANGUAGES];
|
|
8587
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "mx-meet__section", "aria-label": "Captions", children: [
|
|
8588
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "mx-meet__field", children: [
|
|
8589
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "mx-meet__field-label", children: "Translate captions to" }),
|
|
8590
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
8591
|
+
"select",
|
|
8592
|
+
{
|
|
8593
|
+
className: "mx-meet__select",
|
|
8594
|
+
value: current,
|
|
8595
|
+
onChange: (event) => {
|
|
8596
|
+
const next = event.target.value === "" ? null : event.target.value;
|
|
8597
|
+
host.store.patch({
|
|
8598
|
+
collab: {
|
|
8599
|
+
...host.store.snapshot().collab,
|
|
8600
|
+
captionLanguage: next,
|
|
8601
|
+
captionTranslations: {},
|
|
8602
|
+
captionTranslationError: null
|
|
8603
|
+
}
|
|
8604
|
+
});
|
|
8605
|
+
},
|
|
8606
|
+
children: [
|
|
8607
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "", children: "Off \u2014 as spoken" }),
|
|
8608
|
+
current === "" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("option", { value: preferred, children: [
|
|
8609
|
+
choices.find((c) => c.tag === preferred)?.name ?? preferred,
|
|
8610
|
+
" (yours)"
|
|
8611
|
+
] }) : null,
|
|
8612
|
+
choices.filter((choice) => current !== "" || choice.tag !== preferred).map((choice) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: choice.tag, children: choice.name }, choice.tag))
|
|
8613
|
+
]
|
|
8614
|
+
}
|
|
8615
|
+
)
|
|
8616
|
+
] }),
|
|
8617
|
+
collab?.captionTranslationError != null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mx-meet__panel-note mx-meet__collab-error", children: collab.captionTranslationError }) : null
|
|
8618
|
+
] });
|
|
8619
|
+
}
|
|
8620
|
+
function useCollabPanelRequest(onRequest) {
|
|
8621
|
+
const host = useMeetHost();
|
|
8622
|
+
const at = useMeetSnapshot()?.collab.panelRequest?.at ?? null;
|
|
8623
|
+
const callback = (0, import_react4.useRef)(onRequest);
|
|
8624
|
+
callback.current = onRequest;
|
|
8625
|
+
(0, import_react4.useEffect)(() => {
|
|
8626
|
+
const request = host?.store.snapshot().collab.panelRequest ?? null;
|
|
8627
|
+
if (request === null || host === null) return;
|
|
8628
|
+
host.store.patch({ collab: { ...host.store.snapshot().collab, panelRequest: null } });
|
|
8629
|
+
callback.current(request.panel);
|
|
8630
|
+
}, [at, host]);
|
|
8631
|
+
}
|
|
8632
|
+
|
|
8633
|
+
// src/react/components.tsx
|
|
8634
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
8635
|
+
function InertNotice({ what }) {
|
|
8636
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__empty", role: "status", children: [
|
|
8637
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__empty-title", children: [
|
|
8638
|
+
what,
|
|
8639
|
+
" is not ready yet"
|
|
8640
|
+
] }),
|
|
8641
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-body", children: "Calls and meetings need a signed-in identity and an active organization. This will appear as soon as they resolve." })
|
|
8642
|
+
] });
|
|
8643
|
+
}
|
|
8644
|
+
function Avatar({
|
|
8645
|
+
name,
|
|
8646
|
+
url,
|
|
8647
|
+
size = 40
|
|
8648
|
+
}) {
|
|
8649
|
+
const tint = (0, import_format3.avatarPaletteIndex)(name);
|
|
8650
|
+
if (url != null && url.length > 0) {
|
|
8651
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8652
|
+
"img",
|
|
8653
|
+
{
|
|
8654
|
+
className: "mx-meet__avatar",
|
|
8655
|
+
src: url,
|
|
8656
|
+
alt: "",
|
|
8657
|
+
width: size,
|
|
8658
|
+
height: size,
|
|
8659
|
+
style: { width: size, height: size }
|
|
8660
|
+
}
|
|
8661
|
+
);
|
|
8662
|
+
}
|
|
8663
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8664
|
+
"span",
|
|
8665
|
+
{
|
|
8666
|
+
className: "mx-meet__avatar mx-meet__avatar--initials",
|
|
8667
|
+
style: {
|
|
8668
|
+
width: size,
|
|
8669
|
+
height: size,
|
|
8670
|
+
fontSize: Math.round(size * 0.38),
|
|
8671
|
+
background: `var(--mx-meet-avatar-${tint})`
|
|
8672
|
+
},
|
|
8673
|
+
"aria-hidden": "true",
|
|
8674
|
+
children: (0, import_format3.getInitials)(name)
|
|
8675
|
+
}
|
|
8676
|
+
);
|
|
8677
|
+
}
|
|
8678
|
+
function ControlButton({
|
|
8679
|
+
label,
|
|
8680
|
+
active = false,
|
|
8681
|
+
danger = false,
|
|
8682
|
+
onClick,
|
|
8683
|
+
children
|
|
8684
|
+
}) {
|
|
8685
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8686
|
+
"button",
|
|
8687
|
+
{
|
|
8688
|
+
type: "button",
|
|
8689
|
+
className: [
|
|
8690
|
+
"mx-meet__control",
|
|
8691
|
+
active ? "mx-meet__control--active" : "",
|
|
8692
|
+
danger ? "mx-meet__control--danger" : ""
|
|
8693
|
+
].filter(Boolean).join(" "),
|
|
8694
|
+
"aria-label": label,
|
|
8695
|
+
title: label,
|
|
8696
|
+
onClick,
|
|
8697
|
+
children
|
|
8698
|
+
}
|
|
8699
|
+
);
|
|
8700
|
+
}
|
|
8701
|
+
function RecordingIndicator() {
|
|
8702
|
+
const { state, label } = useRecording();
|
|
8703
|
+
if (label === null) return null;
|
|
8704
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8705
|
+
"span",
|
|
8706
|
+
{
|
|
8707
|
+
className: `mx-meet__recording mx-meet__recording--${state}`,
|
|
8708
|
+
role: "status",
|
|
8709
|
+
"aria-live": "polite",
|
|
8710
|
+
children: [
|
|
8711
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RecordIcon, { width: 10, height: 10 }),
|
|
8712
|
+
label
|
|
8713
|
+
]
|
|
8714
|
+
}
|
|
8715
|
+
);
|
|
8716
|
+
}
|
|
8717
|
+
function ConnectionDot({ quality }) {
|
|
8718
|
+
if (quality === "excellent" || quality === "good" || quality === "unknown") return null;
|
|
8719
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: `mx-meet__quality mx-meet__quality--${quality}`, title: `Connection ${quality}`, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(WifiLowIcon, { width: 14, height: 14 }) });
|
|
7107
8720
|
}
|
|
7108
8721
|
function RoleBadge({ role }) {
|
|
7109
|
-
if (role === "host") return /* @__PURE__ */ (0,
|
|
7110
|
-
if (role === "cohost") return /* @__PURE__ */ (0,
|
|
7111
|
-
if (role === "guest") return /* @__PURE__ */ (0,
|
|
8722
|
+
if (role === "host") return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Host" });
|
|
8723
|
+
if (role === "cohost") return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Co-host" });
|
|
8724
|
+
if (role === "guest") return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Guest" });
|
|
7112
8725
|
return null;
|
|
7113
8726
|
}
|
|
7114
8727
|
function ParticipantTile({
|
|
@@ -7118,7 +8731,7 @@ function ParticipantTile({
|
|
|
7118
8731
|
const host = useMeetHost();
|
|
7119
8732
|
const snapshot = useMeetSnapshot();
|
|
7120
8733
|
const queue = useHandQueue();
|
|
7121
|
-
const [menu, setMenu] = (0,
|
|
8734
|
+
const [menu, setMenu] = (0, import_react5.useState)(false);
|
|
7122
8735
|
const videoRef = useTrack(
|
|
7123
8736
|
participant.identity,
|
|
7124
8737
|
participant.screenSharing ? "screen" : "camera"
|
|
@@ -7127,7 +8740,7 @@ function ParticipantTile({
|
|
|
7127
8740
|
const pinnedHere = snapshot?.pinned === participant.identity;
|
|
7128
8741
|
const spotlit = snapshot?.spotlight === participant.identity;
|
|
7129
8742
|
const handPosition = participant.handRaised ? queue.findIndex((entry) => entry.identity === participant.identity) + 1 : 0;
|
|
7130
|
-
return /* @__PURE__ */ (0,
|
|
8743
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7131
8744
|
"div",
|
|
7132
8745
|
{
|
|
7133
8746
|
className: [
|
|
@@ -7137,7 +8750,7 @@ function ParticipantTile({
|
|
|
7137
8750
|
].filter(Boolean).join(" "),
|
|
7138
8751
|
"data-identity": participant.identity,
|
|
7139
8752
|
children: [
|
|
7140
|
-
showVideo ? /* @__PURE__ */ (0,
|
|
8753
|
+
showVideo ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7141
8754
|
"video",
|
|
7142
8755
|
{
|
|
7143
8756
|
ref: videoRef,
|
|
@@ -7146,43 +8759,43 @@ function ParticipantTile({
|
|
|
7146
8759
|
playsInline: true,
|
|
7147
8760
|
muted: participant.isLocal
|
|
7148
8761
|
}
|
|
7149
|
-
) : /* @__PURE__ */ (0,
|
|
7150
|
-
participant.handRaised ? /* @__PURE__ */ (0,
|
|
7151
|
-
/* @__PURE__ */ (0,
|
|
8762
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet__tile-placeholder", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Avatar, { name: participant.displayName, url: participant.avatarUrl, size: featured ? 96 : 56 }) }),
|
|
8763
|
+
participant.handRaised ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__tile-hand", title: `Hand raised \xB7 ${ordinal(handPosition)} in line`, children: [
|
|
8764
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HandIcon, { width: 14, height: 14 }),
|
|
7152
8765
|
handPosition > 0 ? handPosition : null
|
|
7153
8766
|
] }) : null,
|
|
7154
|
-
/* @__PURE__ */ (0,
|
|
7155
|
-
/* @__PURE__ */ (0,
|
|
7156
|
-
spotlit ? /* @__PURE__ */ (0,
|
|
8767
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__tile-bar", children: [
|
|
8768
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__tile-name", children: [
|
|
8769
|
+
spotlit ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { title: "Spotlighted for everyone", className: "mx-meet__tile-flag", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SpotlightIcon, { width: 12, height: 12 }) }) : null,
|
|
7157
8770
|
participant.displayName,
|
|
7158
8771
|
participant.isLocal ? " (you)" : "",
|
|
7159
|
-
participant.isAgent ? /* @__PURE__ */ (0,
|
|
7160
|
-
/* @__PURE__ */ (0,
|
|
8772
|
+
participant.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "AI" }) : null,
|
|
8773
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RoleBadge, { role: participant.role })
|
|
7161
8774
|
] }),
|
|
7162
|
-
!participant.micEnabled ? /* @__PURE__ */ (0,
|
|
7163
|
-
/* @__PURE__ */ (0,
|
|
8775
|
+
!participant.micEnabled ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MicOffIcon, { width: 14, height: 14 }) : null,
|
|
8776
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(QualityBars, { quality: participant.quality })
|
|
7164
8777
|
] }),
|
|
7165
|
-
/* @__PURE__ */ (0,
|
|
7166
|
-
/* @__PURE__ */ (0,
|
|
8778
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: menu ? "mx-meet__tile-actions mx-meet__tile-actions--open" : "mx-meet__tile-actions", children: [
|
|
8779
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7167
8780
|
ControlButton,
|
|
7168
8781
|
{
|
|
7169
8782
|
label: pinnedHere ? "Unpin" : `Pin ${participant.displayName} for me`,
|
|
7170
8783
|
active: pinnedHere,
|
|
7171
8784
|
onClick: () => host?.engine.pin(pinnedHere ? null : participant.identity),
|
|
7172
|
-
children: /* @__PURE__ */ (0,
|
|
8785
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PinIcon, { width: 16, height: 16 })
|
|
7173
8786
|
}
|
|
7174
8787
|
),
|
|
7175
|
-
/* @__PURE__ */ (0,
|
|
7176
|
-
/* @__PURE__ */ (0,
|
|
8788
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__anchor", children: [
|
|
8789
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7177
8790
|
ControlButton,
|
|
7178
8791
|
{
|
|
7179
8792
|
label: `More for ${participant.displayName}`,
|
|
7180
8793
|
active: menu,
|
|
7181
8794
|
onClick: () => setMenu(!menu),
|
|
7182
|
-
children: /* @__PURE__ */ (0,
|
|
8795
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MoreIcon, { width: 16, height: 16 })
|
|
7183
8796
|
}
|
|
7184
8797
|
),
|
|
7185
|
-
menu ? /* @__PURE__ */ (0,
|
|
8798
|
+
menu ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PersonMenu, { participant, onClose: () => setMenu(false), placement: "down" }) : null
|
|
7186
8799
|
] })
|
|
7187
8800
|
] })
|
|
7188
8801
|
]
|
|
@@ -7198,28 +8811,28 @@ function QualityBars({ quality }) {
|
|
|
7198
8811
|
if (quality === "unknown") return null;
|
|
7199
8812
|
const bars = quality === "excellent" ? 3 : quality === "good" ? 2 : quality === "poor" ? 1 : 0;
|
|
7200
8813
|
const label = quality === "lost" ? "Connection lost" : quality === "poor" ? "Poor connection" : `Connection ${quality}`;
|
|
7201
|
-
return /* @__PURE__ */ (0,
|
|
8814
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: `mx-meet__signal mx-meet__signal--${quality}`, title: label, "aria-label": label, role: "img", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SignalIcon, { bars, width: 14, height: 14 }) });
|
|
7202
8815
|
}
|
|
7203
8816
|
function Stage({ pageSize }) {
|
|
7204
8817
|
const stage = useStage(pageSize);
|
|
7205
8818
|
const columns = gridColumns(stage.tiles.length);
|
|
7206
8819
|
if (stage.feature === null && stage.tiles.length === 0) {
|
|
7207
|
-
return /* @__PURE__ */ (0,
|
|
7208
|
-
/* @__PURE__ */ (0,
|
|
7209
|
-
/* @__PURE__ */ (0,
|
|
8820
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__stage mx-meet__stage--empty", children: [
|
|
8821
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-title", children: "Waiting for others to join" }),
|
|
8822
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-body", children: "Share the meeting link and people can join from anywhere \u2014 no account needed." })
|
|
7210
8823
|
] });
|
|
7211
8824
|
}
|
|
7212
|
-
return /* @__PURE__ */ (0,
|
|
7213
|
-
stage.feature !== null ? /* @__PURE__ */ (0,
|
|
7214
|
-
/* @__PURE__ */ (0,
|
|
8825
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: `mx-meet__stage${stage.feature !== null ? " mx-meet__stage--speaker" : ""}`, children: [
|
|
8826
|
+
stage.feature !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ParticipantTile, { participant: stage.feature, featured: true }) : null,
|
|
8827
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7215
8828
|
"div",
|
|
7216
8829
|
{
|
|
7217
8830
|
className: "mx-meet__grid",
|
|
7218
8831
|
style: { "--mx-meet-columns": columns },
|
|
7219
|
-
children: stage.tiles.map((participant) => /* @__PURE__ */ (0,
|
|
8832
|
+
children: stage.tiles.map((participant) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ParticipantTile, { participant }, participant.identity))
|
|
7220
8833
|
}
|
|
7221
8834
|
),
|
|
7222
|
-
stage.overflow > 0 ? /* @__PURE__ */ (0,
|
|
8835
|
+
stage.overflow > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__overflow", children: [
|
|
7223
8836
|
"+",
|
|
7224
8837
|
stage.overflow,
|
|
7225
8838
|
" more ",
|
|
@@ -7232,20 +8845,28 @@ var MEET_REACTIONS = ["\u{1F496}", "\u{1F44D}", "\u{1F389}", "\u{1F44F}", "\u{1F
|
|
|
7232
8845
|
function ControlBar({ onLeave }) {
|
|
7233
8846
|
const room = useRoom();
|
|
7234
8847
|
const recording = useRecording();
|
|
7235
|
-
const [panel, setPanel] = (0,
|
|
7236
|
-
const [chatTo, setChatTo] = (0,
|
|
7237
|
-
const [popover, setPopover] = (0,
|
|
7238
|
-
const [shortcuts, setShortcuts] = (0,
|
|
8848
|
+
const [panel, setPanel] = (0, import_react5.useState)("none");
|
|
8849
|
+
const [chatTo, setChatTo] = (0, import_react5.useState)(null);
|
|
8850
|
+
const [popover, setPopover] = (0, import_react5.useState)("none");
|
|
8851
|
+
const [shortcuts, setShortcuts] = (0, import_react5.useState)(false);
|
|
7239
8852
|
const snapshot = useMeetSnapshot();
|
|
7240
8853
|
const lobby = useLobby();
|
|
7241
8854
|
const controls = useHostControls();
|
|
7242
8855
|
const queue = useHandQueue();
|
|
7243
8856
|
const micUnavailable = useLocalMedia().microphone.unavailable;
|
|
7244
8857
|
const unread = useUnreadChat(panel === "chat");
|
|
8858
|
+
const [whiteboard, setWhiteboard] = (0, import_react5.useState)(false);
|
|
7245
8859
|
const toggle = (next) => setPanel(panel === next ? "none" : next);
|
|
8860
|
+
const openActivity = (activity) => {
|
|
8861
|
+
if (activity === "whiteboard") setWhiteboard(true);
|
|
8862
|
+
else setPanel(activity);
|
|
8863
|
+
};
|
|
8864
|
+
useCollabPanelRequest((activity) => {
|
|
8865
|
+
if (!controls.isHost) openActivity(activity);
|
|
8866
|
+
});
|
|
7246
8867
|
const privateChatAt = snapshot?.privateChatRequest?.at ?? null;
|
|
7247
8868
|
const meetStore = useMeetHost()?.store ?? null;
|
|
7248
|
-
(0,
|
|
8869
|
+
(0, import_react5.useEffect)(() => {
|
|
7249
8870
|
const request = meetStore?.snapshot().privateChatRequest ?? null;
|
|
7250
8871
|
if (request === null) return;
|
|
7251
8872
|
setChatTo(request.to);
|
|
@@ -7261,11 +8882,11 @@ function ControlBar({ onLeave }) {
|
|
|
7261
8882
|
help: () => setShortcuts(true)
|
|
7262
8883
|
});
|
|
7263
8884
|
const hasSpotlight = snapshot?.spotlight !== null && snapshot?.spotlight !== void 0;
|
|
7264
|
-
return /* @__PURE__ */ (0,
|
|
7265
|
-
/* @__PURE__ */ (0,
|
|
7266
|
-
shortcuts ? /* @__PURE__ */ (0,
|
|
7267
|
-
panel === "chat" ? /* @__PURE__ */ (0,
|
|
7268
|
-
panel === "people" ? /* @__PURE__ */ (0,
|
|
8885
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
8886
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MeetingOverlays, {}),
|
|
8887
|
+
shortcuts ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ShortcutsSheet, { onClose: () => setShortcuts(false) }) : null,
|
|
8888
|
+
panel === "chat" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChatPanel, { onClose: () => setPanel("none"), to: chatTo, onTo: setChatTo }) : null,
|
|
8889
|
+
panel === "people" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7269
8890
|
PeoplePanel,
|
|
7270
8891
|
{
|
|
7271
8892
|
onClose: () => setPanel("none"),
|
|
@@ -7275,48 +8896,53 @@ function ControlBar({ onLeave }) {
|
|
|
7275
8896
|
}
|
|
7276
8897
|
}
|
|
7277
8898
|
) : null,
|
|
7278
|
-
panel === "ai" ? /* @__PURE__ */ (0,
|
|
7279
|
-
panel === "settings" ? /* @__PURE__ */ (0,
|
|
7280
|
-
|
|
7281
|
-
/* @__PURE__ */ (0,
|
|
7282
|
-
|
|
8899
|
+
panel === "ai" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AiPanel, { onClose: () => setPanel("none") }) : null,
|
|
8900
|
+
panel === "settings" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SettingsPanel, { onClose: () => setPanel("none") }) : null,
|
|
8901
|
+
panel === "polls" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PollsPanel, { onClose: () => setPanel("none") }) : null,
|
|
8902
|
+
panel === "qa" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(QaPanel, { onClose: () => setPanel("none") }) : null,
|
|
8903
|
+
panel === "breakouts" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(BreakoutsPanel, { onClose: () => setPanel("none") }) : null,
|
|
8904
|
+
whiteboard ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(WhiteboardPanel, { onClose: () => setWhiteboard(false) }) : null,
|
|
8905
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(BreakoutBanner, {}),
|
|
8906
|
+
controls.notice !== null && panel !== "people" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Toast, { text: controls.notice.text, failed: controls.notice.failed, onDone: controls.clearNotice }) : null,
|
|
8907
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__controls", children: [
|
|
8908
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7283
8909
|
ControlButton,
|
|
7284
8910
|
{
|
|
7285
8911
|
label: micUnavailable !== null ? `Unmute \u2014 ${micUnavailable.remedy}` : room.local?.micEnabled === true ? "Mute (\u2318D)" : "Unmute (\u2318D)",
|
|
7286
8912
|
active: room.local?.micEnabled === true,
|
|
7287
8913
|
onClick: () => void room.toggleMicrophone(),
|
|
7288
|
-
children: room.local?.micEnabled === true ? /* @__PURE__ */ (0,
|
|
8914
|
+
children: room.local?.micEnabled === true ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MicIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MicOffIcon, {})
|
|
7289
8915
|
}
|
|
7290
8916
|
),
|
|
7291
|
-
/* @__PURE__ */ (0,
|
|
8917
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7292
8918
|
ControlButton,
|
|
7293
8919
|
{
|
|
7294
8920
|
label: room.local?.cameraEnabled === true ? "Stop video (\u2318E)" : "Start video (\u2318E)",
|
|
7295
8921
|
active: room.local?.cameraEnabled === true,
|
|
7296
8922
|
onClick: () => void room.toggleCamera(),
|
|
7297
|
-
children: room.local?.cameraEnabled === true ? /* @__PURE__ */ (0,
|
|
8923
|
+
children: room.local?.cameraEnabled === true ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CameraIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CameraOffIcon, {})
|
|
7298
8924
|
}
|
|
7299
8925
|
),
|
|
7300
|
-
/* @__PURE__ */ (0,
|
|
8926
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7301
8927
|
ControlButton,
|
|
7302
8928
|
{
|
|
7303
8929
|
label: room.local?.screenSharing === true ? "Stop sharing" : "Share screen",
|
|
7304
8930
|
active: room.local?.screenSharing === true,
|
|
7305
8931
|
onClick: () => void room.toggleScreenShare(),
|
|
7306
|
-
children: /* @__PURE__ */ (0,
|
|
8932
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ScreenShareIcon, {})
|
|
7307
8933
|
}
|
|
7308
8934
|
),
|
|
7309
|
-
/* @__PURE__ */ (0,
|
|
7310
|
-
/* @__PURE__ */ (0,
|
|
8935
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__anchor", children: [
|
|
8936
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7311
8937
|
ControlButton,
|
|
7312
8938
|
{
|
|
7313
8939
|
label: "Send a reaction",
|
|
7314
8940
|
active: popover === "reactions",
|
|
7315
8941
|
onClick: () => setPopover(popover === "reactions" ? "none" : "reactions"),
|
|
7316
|
-
children: /* @__PURE__ */ (0,
|
|
8942
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SmileIcon, {})
|
|
7317
8943
|
}
|
|
7318
8944
|
),
|
|
7319
|
-
popover === "reactions" ? /* @__PURE__ */ (0,
|
|
8945
|
+
popover === "reactions" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Popover, { label: "Reactions", onClose: () => setPopover("none"), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet__emoji-bar", children: MEET_REACTIONS.map((emoji) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7320
8946
|
"button",
|
|
7321
8947
|
{
|
|
7322
8948
|
type: "button",
|
|
@@ -7328,46 +8954,53 @@ function ControlBar({ onLeave }) {
|
|
|
7328
8954
|
emoji
|
|
7329
8955
|
)) }) }) : null
|
|
7330
8956
|
] }),
|
|
7331
|
-
/* @__PURE__ */ (0,
|
|
8957
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7332
8958
|
ControlButton,
|
|
7333
8959
|
{
|
|
7334
8960
|
label: room.local?.handRaised === true ? "Lower hand (\u2318\u2325H)" : "Raise hand (\u2318\u2325H)",
|
|
7335
8961
|
active: room.local?.handRaised === true,
|
|
7336
8962
|
onClick: () => void room.toggleHand(),
|
|
7337
|
-
children: /* @__PURE__ */ (0,
|
|
8963
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HandIcon, {})
|
|
7338
8964
|
}
|
|
7339
8965
|
),
|
|
7340
|
-
/* @__PURE__ */ (0,
|
|
7341
|
-
/* @__PURE__ */ (0,
|
|
7342
|
-
unread > 0 ? /* @__PURE__ */ (0,
|
|
8966
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(ControlButton, { label: "Chat (\u2318\u2325C)", active: panel === "chat", onClick: () => toggle("chat"), children: [
|
|
8967
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChatIcon, {}),
|
|
8968
|
+
unread > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__dot", "aria-hidden": "true" }) : null
|
|
7343
8969
|
] }),
|
|
7344
|
-
/* @__PURE__ */ (0,
|
|
8970
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7345
8971
|
ControlButton,
|
|
7346
8972
|
{
|
|
7347
8973
|
label: lobby.waiting.length > 0 ? `People \u2014 ${lobby.waiting.length} waiting` : `People \u2014 ${(snapshot?.participants ?? []).length} in the meeting`,
|
|
7348
8974
|
active: panel === "people",
|
|
7349
8975
|
onClick: () => toggle("people"),
|
|
7350
8976
|
children: [
|
|
7351
|
-
/* @__PURE__ */ (0,
|
|
7352
|
-
lobby.waiting.length > 0 || controls.isHost && queue.length > 0 ? /* @__PURE__ */ (0,
|
|
8977
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PeopleIcon, {}),
|
|
8978
|
+
lobby.waiting.length > 0 || controls.isHost && queue.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__dot", "aria-hidden": "true" }) : null
|
|
7353
8979
|
]
|
|
7354
8980
|
}
|
|
7355
8981
|
),
|
|
7356
|
-
/* @__PURE__ */ (0,
|
|
7357
|
-
|
|
7358
|
-
|
|
7359
|
-
|
|
7360
|
-
|
|
8982
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8983
|
+
ActivitiesControl,
|
|
8984
|
+
{
|
|
8985
|
+
active: whiteboard ? "whiteboard" : panel === "polls" || panel === "qa" || panel === "breakouts" ? panel : null,
|
|
8986
|
+
onOpen: openActivity
|
|
8987
|
+
}
|
|
8988
|
+
),
|
|
8989
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AiControl, { active: panel === "ai", onToggle: () => toggle("ai") }),
|
|
8990
|
+
recording.canStart ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ControlButton, { label: "Start recording", onClick: () => void recording.start(), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RecordIcon, {}) }) : null,
|
|
8991
|
+
recording.canStop ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ControlButton, { label: "Stop recording", active: true, onClick: () => void recording.stop(), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RecordIcon, {}) }) : null,
|
|
8992
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__anchor", children: [
|
|
8993
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7361
8994
|
ControlButton,
|
|
7362
8995
|
{
|
|
7363
8996
|
label: "More options",
|
|
7364
8997
|
active: popover === "more" || panel === "settings",
|
|
7365
8998
|
onClick: () => setPopover(popover === "more" ? "none" : "more"),
|
|
7366
|
-
children: /* @__PURE__ */ (0,
|
|
8999
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MoreIcon, {})
|
|
7367
9000
|
}
|
|
7368
9001
|
),
|
|
7369
|
-
popover === "more" ? /* @__PURE__ */ (0,
|
|
7370
|
-
/* @__PURE__ */ (0,
|
|
9002
|
+
popover === "more" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Popover, { label: "More options", onClose: () => setPopover("none"), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__menu", role: "menu", children: [
|
|
9003
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7371
9004
|
MenuItem,
|
|
7372
9005
|
{
|
|
7373
9006
|
onSelect: () => {
|
|
@@ -7375,12 +9008,12 @@ function ControlBar({ onLeave }) {
|
|
|
7375
9008
|
setPanel("settings");
|
|
7376
9009
|
},
|
|
7377
9010
|
children: [
|
|
7378
|
-
/* @__PURE__ */ (0,
|
|
7379
|
-
"
|
|
9011
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SettingsIcon, { width: 16, height: 16 }),
|
|
9012
|
+
" Settings"
|
|
7380
9013
|
]
|
|
7381
9014
|
}
|
|
7382
9015
|
),
|
|
7383
|
-
/* @__PURE__ */ (0,
|
|
9016
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7384
9017
|
MenuItem,
|
|
7385
9018
|
{
|
|
7386
9019
|
onSelect: () => {
|
|
@@ -7388,14 +9021,14 @@ function ControlBar({ onLeave }) {
|
|
|
7388
9021
|
setShortcuts(true);
|
|
7389
9022
|
},
|
|
7390
9023
|
children: [
|
|
7391
|
-
/* @__PURE__ */ (0,
|
|
9024
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(KeyboardIcon, { width: 16, height: 16 }),
|
|
7392
9025
|
" Keyboard shortcuts"
|
|
7393
9026
|
]
|
|
7394
9027
|
}
|
|
7395
9028
|
),
|
|
7396
|
-
controls.isHost ? /* @__PURE__ */ (0,
|
|
7397
|
-
/* @__PURE__ */ (0,
|
|
7398
|
-
/* @__PURE__ */ (0,
|
|
9029
|
+
controls.isHost ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
9030
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet__menu-sep", role: "separator" }),
|
|
9031
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7399
9032
|
MenuItem,
|
|
7400
9033
|
{
|
|
7401
9034
|
onSelect: () => {
|
|
@@ -7403,12 +9036,12 @@ function ControlBar({ onLeave }) {
|
|
|
7403
9036
|
void controls.run({ action: "mute_all" });
|
|
7404
9037
|
},
|
|
7405
9038
|
children: [
|
|
7406
|
-
/* @__PURE__ */ (0,
|
|
9039
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MicOffIcon, { width: 16, height: 16 }),
|
|
7407
9040
|
" Mute everyone"
|
|
7408
9041
|
]
|
|
7409
9042
|
}
|
|
7410
9043
|
),
|
|
7411
|
-
/* @__PURE__ */ (0,
|
|
9044
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7412
9045
|
MenuItem,
|
|
7413
9046
|
{
|
|
7414
9047
|
onSelect: () => {
|
|
@@ -7416,12 +9049,12 @@ function ControlBar({ onLeave }) {
|
|
|
7416
9049
|
void controls.run({ action: "ask_all_unmute" });
|
|
7417
9050
|
},
|
|
7418
9051
|
children: [
|
|
7419
|
-
/* @__PURE__ */ (0,
|
|
9052
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MicIcon, { width: 16, height: 16 }),
|
|
7420
9053
|
" Ask everyone to unmute"
|
|
7421
9054
|
]
|
|
7422
9055
|
}
|
|
7423
9056
|
),
|
|
7424
|
-
queue.length > 0 ? /* @__PURE__ */ (0,
|
|
9057
|
+
queue.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7425
9058
|
MenuItem,
|
|
7426
9059
|
{
|
|
7427
9060
|
onSelect: () => {
|
|
@@ -7429,14 +9062,14 @@ function ControlBar({ onLeave }) {
|
|
|
7429
9062
|
void controls.run({ action: "lower_all_hands" });
|
|
7430
9063
|
},
|
|
7431
9064
|
children: [
|
|
7432
|
-
/* @__PURE__ */ (0,
|
|
9065
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HandIcon, { width: 16, height: 16 }),
|
|
7433
9066
|
" Lower all hands (",
|
|
7434
9067
|
queue.length,
|
|
7435
9068
|
")"
|
|
7436
9069
|
]
|
|
7437
9070
|
}
|
|
7438
9071
|
) : null,
|
|
7439
|
-
hasSpotlight ? /* @__PURE__ */ (0,
|
|
9072
|
+
hasSpotlight ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7440
9073
|
MenuItem,
|
|
7441
9074
|
{
|
|
7442
9075
|
onSelect: () => {
|
|
@@ -7444,7 +9077,7 @@ function ControlBar({ onLeave }) {
|
|
|
7444
9077
|
void controls.run({ action: "spotlight", identity: null });
|
|
7445
9078
|
},
|
|
7446
9079
|
children: [
|
|
7447
|
-
/* @__PURE__ */ (0,
|
|
9080
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SpotlightIcon, { width: 16, height: 16 }),
|
|
7448
9081
|
" Remove spotlight"
|
|
7449
9082
|
]
|
|
7450
9083
|
}
|
|
@@ -7452,7 +9085,7 @@ function ControlBar({ onLeave }) {
|
|
|
7452
9085
|
] }) : null
|
|
7453
9086
|
] }) }) : null
|
|
7454
9087
|
] }),
|
|
7455
|
-
/* @__PURE__ */ (0,
|
|
9088
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7456
9089
|
ControlButton,
|
|
7457
9090
|
{
|
|
7458
9091
|
label: "Leave",
|
|
@@ -7461,7 +9094,7 @@ function ControlBar({ onLeave }) {
|
|
|
7461
9094
|
void room.leave();
|
|
7462
9095
|
onLeave?.();
|
|
7463
9096
|
},
|
|
7464
|
-
children: /* @__PURE__ */ (0,
|
|
9097
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PhoneOffIcon, {})
|
|
7465
9098
|
}
|
|
7466
9099
|
)
|
|
7467
9100
|
] })
|
|
@@ -7471,13 +9104,13 @@ function useUnreadChat(open) {
|
|
|
7471
9104
|
const snapshot = useMeetSnapshot();
|
|
7472
9105
|
const chat = snapshot?.chat ?? [];
|
|
7473
9106
|
const local = snapshot?.localIdentity ?? null;
|
|
7474
|
-
const [seen, setSeen] = (0,
|
|
7475
|
-
(0,
|
|
9107
|
+
const [seen, setSeen] = (0, import_react5.useState)(0);
|
|
9108
|
+
(0, import_react5.useEffect)(() => {
|
|
7476
9109
|
if (open) setSeen(chat.length);
|
|
7477
9110
|
}, [open, chat.length]);
|
|
7478
9111
|
const loaded = snapshot?.chatLoaded === true;
|
|
7479
|
-
const [baseline, setBaseline] = (0,
|
|
7480
|
-
(0,
|
|
9112
|
+
const [baseline, setBaseline] = (0, import_react5.useState)(null);
|
|
9113
|
+
(0, import_react5.useEffect)(() => {
|
|
7481
9114
|
if (loaded && baseline === null) setBaseline(chat.length);
|
|
7482
9115
|
}, [loaded, baseline, chat.length]);
|
|
7483
9116
|
if (open) return 0;
|
|
@@ -7490,14 +9123,14 @@ function Popover({
|
|
|
7490
9123
|
children,
|
|
7491
9124
|
placement = "up"
|
|
7492
9125
|
}) {
|
|
7493
|
-
const ref = (0,
|
|
7494
|
-
const [style, setStyle] = (0,
|
|
9126
|
+
const ref = (0, import_react5.useRef)(null);
|
|
9127
|
+
const [style, setStyle] = (0, import_react5.useState)({
|
|
7495
9128
|
position: "fixed",
|
|
7496
9129
|
top: 0,
|
|
7497
9130
|
left: 0,
|
|
7498
9131
|
visibility: "hidden"
|
|
7499
9132
|
});
|
|
7500
|
-
(0,
|
|
9133
|
+
(0, import_react5.useLayoutEffect)(() => {
|
|
7501
9134
|
const element = ref.current;
|
|
7502
9135
|
const anchor = element?.parentElement ?? null;
|
|
7503
9136
|
if (element === null || anchor === null) return;
|
|
@@ -7542,7 +9175,7 @@ function Popover({
|
|
|
7542
9175
|
window.removeEventListener("scroll", place, true);
|
|
7543
9176
|
};
|
|
7544
9177
|
}, [placement]);
|
|
7545
|
-
(0,
|
|
9178
|
+
(0, import_react5.useEffect)(() => {
|
|
7546
9179
|
const onKey = (event) => {
|
|
7547
9180
|
if (event.key === "Escape") onClose();
|
|
7548
9181
|
};
|
|
@@ -7557,14 +9190,14 @@ function Popover({
|
|
|
7557
9190
|
window.removeEventListener("pointerdown", onPointer);
|
|
7558
9191
|
};
|
|
7559
9192
|
}, [onClose]);
|
|
7560
|
-
return /* @__PURE__ */ (0,
|
|
9193
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ref, className: "mx-meet__popover", style, role: "dialog", "aria-label": label, children });
|
|
7561
9194
|
}
|
|
7562
9195
|
function MenuItem({
|
|
7563
9196
|
onSelect,
|
|
7564
9197
|
danger = false,
|
|
7565
9198
|
children
|
|
7566
9199
|
}) {
|
|
7567
|
-
return /* @__PURE__ */ (0,
|
|
9200
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7568
9201
|
"button",
|
|
7569
9202
|
{
|
|
7570
9203
|
type: "button",
|
|
@@ -7576,28 +9209,28 @@ function MenuItem({
|
|
|
7576
9209
|
);
|
|
7577
9210
|
}
|
|
7578
9211
|
function Toast({ text: text3, failed, onDone }) {
|
|
7579
|
-
(0,
|
|
9212
|
+
(0, import_react5.useEffect)(() => {
|
|
7580
9213
|
const timer = setTimeout(onDone, failed ? 7e3 : 4e3);
|
|
7581
9214
|
return () => clearTimeout(timer);
|
|
7582
9215
|
}, [text3, failed, onDone]);
|
|
7583
|
-
return /* @__PURE__ */ (0,
|
|
7584
|
-
/* @__PURE__ */ (0,
|
|
7585
|
-
/* @__PURE__ */ (0,
|
|
9216
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: failed ? "mx-meet__toast mx-meet__toast--failed" : "mx-meet__toast", role: "status", children: [
|
|
9217
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: text3 }),
|
|
9218
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mx-meet__toast-close", "aria-label": "Dismiss", onClick: onDone, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CloseIcon, { width: 14, height: 14 }) })
|
|
7586
9219
|
] });
|
|
7587
9220
|
}
|
|
7588
9221
|
function MeetingOverlays() {
|
|
7589
9222
|
const reactions = useReactions();
|
|
7590
9223
|
const { notice, dismiss } = useModerationNotice();
|
|
7591
9224
|
const room = useRoom();
|
|
7592
|
-
return /* @__PURE__ */ (0,
|
|
7593
|
-
/* @__PURE__ */ (0,
|
|
9225
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
9226
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ReactionOverlay, { reactions }),
|
|
7594
9227
|
notice !== null && notice.kind !== "removed" ? (
|
|
7595
9228
|
// A host's request ("the host is asking you to unmute"), not an error:
|
|
7596
9229
|
// an assertive status, so it is announced at once without being filed
|
|
7597
9230
|
// as a failure (design-system error-box census).
|
|
7598
|
-
/* @__PURE__ */ (0,
|
|
7599
|
-
/* @__PURE__ */ (0,
|
|
7600
|
-
notice.kind === "ask-unmute" && room.local?.micEnabled !== true ? /* @__PURE__ */ (0,
|
|
9231
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__notice-bar", role: "status", "aria-live": "assertive", children: [
|
|
9232
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: notice.text }),
|
|
9233
|
+
notice.kind === "ask-unmute" && room.local?.micEnabled !== true ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7601
9234
|
"button",
|
|
7602
9235
|
{
|
|
7603
9236
|
type: "button",
|
|
@@ -7609,20 +9242,20 @@ function MeetingOverlays() {
|
|
|
7609
9242
|
children: "Unmute"
|
|
7610
9243
|
}
|
|
7611
9244
|
) : null,
|
|
7612
|
-
/* @__PURE__ */ (0,
|
|
9245
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mx-meet__toast-close", "aria-label": "Dismiss", onClick: dismiss, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CloseIcon, { width: 14, height: 14 }) })
|
|
7613
9246
|
] })
|
|
7614
9247
|
) : null
|
|
7615
9248
|
] });
|
|
7616
9249
|
}
|
|
7617
9250
|
function ShortcutsSheet({ onClose }) {
|
|
7618
|
-
(0,
|
|
9251
|
+
(0, import_react5.useEffect)(() => {
|
|
7619
9252
|
const onKey = (event) => {
|
|
7620
9253
|
if (event.key === "Escape") onClose();
|
|
7621
9254
|
};
|
|
7622
9255
|
window.addEventListener("keydown", onKey);
|
|
7623
9256
|
return () => window.removeEventListener("keydown", onKey);
|
|
7624
9257
|
}, [onClose]);
|
|
7625
|
-
return /* @__PURE__ */ (0,
|
|
9258
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet__sheet-backdrop", onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7626
9259
|
"div",
|
|
7627
9260
|
{
|
|
7628
9261
|
className: "mx-meet__sheet",
|
|
@@ -7630,13 +9263,13 @@ function ShortcutsSheet({ onClose }) {
|
|
|
7630
9263
|
"aria-label": "Keyboard shortcuts",
|
|
7631
9264
|
onClick: (event) => event.stopPropagation(),
|
|
7632
9265
|
children: [
|
|
7633
|
-
/* @__PURE__ */ (0,
|
|
7634
|
-
/* @__PURE__ */ (0,
|
|
7635
|
-
/* @__PURE__ */ (0,
|
|
9266
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { className: "mx-meet__panel-head", children: [
|
|
9267
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__panel-title", children: "Keyboard shortcuts" }),
|
|
9268
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ControlButton, { label: "Close", onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CloseIcon, { width: 16, height: 16 }) })
|
|
7636
9269
|
] }),
|
|
7637
|
-
/* @__PURE__ */ (0,
|
|
7638
|
-
/* @__PURE__ */ (0,
|
|
7639
|
-
/* @__PURE__ */ (0,
|
|
9270
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("dl", { className: "mx-meet__shortcuts", children: MEET_SHORTCUTS.map((shortcut) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__shortcut", children: [
|
|
9271
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("dt", { children: shortcut.label }),
|
|
9272
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("dd", { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("kbd", { className: "mx-meet__kbd", children: shortcut.keys }) })
|
|
7640
9273
|
] }, shortcut.id)) })
|
|
7641
9274
|
]
|
|
7642
9275
|
}
|
|
@@ -7646,19 +9279,32 @@ function AiControl({ active, onToggle }) {
|
|
|
7646
9279
|
const snapshot = useMeetSnapshot();
|
|
7647
9280
|
const meeting = snapshot?.meeting ?? null;
|
|
7648
9281
|
if (meeting === null || !meeting.aiEnabled) return null;
|
|
7649
|
-
return /* @__PURE__ */ (0,
|
|
9282
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ControlButton, { label: "Meeting assistant", active, onClick: onToggle, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SparklesIcon, {}) });
|
|
7650
9283
|
}
|
|
7651
9284
|
function PanelShell({
|
|
7652
9285
|
title,
|
|
7653
9286
|
onClose,
|
|
7654
9287
|
children
|
|
7655
9288
|
}) {
|
|
7656
|
-
|
|
7657
|
-
|
|
7658
|
-
|
|
7659
|
-
|
|
9289
|
+
const ref = (0, import_react5.useRef)(null);
|
|
9290
|
+
(0, import_react5.useLayoutEffect)(() => {
|
|
9291
|
+
const panel = ref.current;
|
|
9292
|
+
const root = panel?.closest(".mx-meet");
|
|
9293
|
+
const header = root?.querySelector(":scope > .mx-meet__header") ?? null;
|
|
9294
|
+
if (!panel || !header) return void 0;
|
|
9295
|
+
const place = () => panel.style.setProperty("--mx-meet-panel-top", `${header.offsetHeight}px`);
|
|
9296
|
+
place();
|
|
9297
|
+
if (typeof ResizeObserver === "undefined") return void 0;
|
|
9298
|
+
const observer = new ResizeObserver(place);
|
|
9299
|
+
observer.observe(header);
|
|
9300
|
+
return () => observer.disconnect();
|
|
9301
|
+
}, []);
|
|
9302
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("aside", { ref, className: "mx-meet__panel", "aria-label": title, children: [
|
|
9303
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { className: "mx-meet__panel-head", children: [
|
|
9304
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__panel-title", children: title }),
|
|
9305
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ControlButton, { label: "Close panel", onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CloseIcon, { width: 16, height: 16 }) })
|
|
7660
9306
|
] }),
|
|
7661
|
-
/* @__PURE__ */ (0,
|
|
9307
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet__panel-body", children })
|
|
7662
9308
|
] });
|
|
7663
9309
|
}
|
|
7664
9310
|
function ChatPanel({
|
|
@@ -7668,17 +9314,17 @@ function ChatPanel({
|
|
|
7668
9314
|
}) {
|
|
7669
9315
|
const snapshot = useMeetSnapshot();
|
|
7670
9316
|
const room = useRoom();
|
|
7671
|
-
const [draft, setDraft] = (0,
|
|
7672
|
-
const [recipient, setRecipient] = (0,
|
|
7673
|
-
const listRef = (0,
|
|
9317
|
+
const [draft, setDraft] = (0, import_react5.useState)("");
|
|
9318
|
+
const [recipient, setRecipient] = (0, import_react5.useState)(to);
|
|
9319
|
+
const listRef = (0, import_react5.useRef)(null);
|
|
7674
9320
|
const messages = snapshot?.chat ?? [];
|
|
7675
9321
|
const local = snapshot?.localIdentity ?? null;
|
|
7676
9322
|
const people = (snapshot?.participants ?? []).filter(
|
|
7677
9323
|
(participant) => !participant.isLocal && !participant.isAgent
|
|
7678
9324
|
);
|
|
7679
9325
|
const recipientName = recipient === null ? null : people.find((p) => p.identity === recipient)?.displayName ?? null;
|
|
7680
|
-
(0,
|
|
7681
|
-
(0,
|
|
9326
|
+
(0, import_react5.useEffect)(() => setRecipient(to), [to]);
|
|
9327
|
+
(0, import_react5.useEffect)(() => {
|
|
7682
9328
|
const list = listRef.current;
|
|
7683
9329
|
if (list !== null) list.scrollTop = list.scrollHeight;
|
|
7684
9330
|
}, [messages.length]);
|
|
@@ -7686,13 +9332,13 @@ function ChatPanel({
|
|
|
7686
9332
|
setRecipient(next);
|
|
7687
9333
|
onTo?.(next);
|
|
7688
9334
|
};
|
|
7689
|
-
return /* @__PURE__ */ (0,
|
|
7690
|
-
/* @__PURE__ */ (0,
|
|
7691
|
-
snapshot?.chatHistoryError != null ? /* @__PURE__ */ (0,
|
|
7692
|
-
snapshot?.chatLoaded !== true && messages.length === 0 ? /* @__PURE__ */ (0,
|
|
7693
|
-
messages.map((message) => /* @__PURE__ */ (0,
|
|
9335
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(PanelShell, { title: "Chat", onClose, children: [
|
|
9336
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("ul", { className: "mx-meet__chat", ref: listRef, children: [
|
|
9337
|
+
snapshot?.chatHistoryError != null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("li", { className: "mx-meet__panel-note", children: snapshot.chatHistoryError }) : null,
|
|
9338
|
+
snapshot?.chatLoaded !== true && messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("li", { className: "mx-meet__panel-note", children: "Reading earlier messages\u2026" }) : messages.length === 0 && snapshot?.chatHistoryError == null ? /* @__PURE__ */ (0, import_jsx_runtime4.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,
|
|
9339
|
+
messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChatLine, { message, local, people }, message.id))
|
|
7694
9340
|
] }),
|
|
7695
|
-
/* @__PURE__ */ (0,
|
|
9341
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7696
9342
|
"form",
|
|
7697
9343
|
{
|
|
7698
9344
|
className: "mx-meet__composer mx-meet__composer--chat",
|
|
@@ -7705,7 +9351,7 @@ function ChatPanel({
|
|
|
7705
9351
|
else void room.sendPrivateChat(recipient, text3);
|
|
7706
9352
|
},
|
|
7707
9353
|
children: [
|
|
7708
|
-
people.length > 0 ? /* @__PURE__ */ (0,
|
|
9354
|
+
people.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7709
9355
|
"select",
|
|
7710
9356
|
{
|
|
7711
9357
|
className: "mx-meet__select mx-meet__select--compact",
|
|
@@ -7713,16 +9359,16 @@ function ChatPanel({
|
|
|
7713
9359
|
value: recipient ?? "",
|
|
7714
9360
|
onChange: (event) => choose(event.target.value === "" ? null : event.target.value),
|
|
7715
9361
|
children: [
|
|
7716
|
-
/* @__PURE__ */ (0,
|
|
7717
|
-
people.map((participant) => /* @__PURE__ */ (0,
|
|
9362
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "", children: "Everyone" }),
|
|
9363
|
+
people.map((participant) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("option", { value: participant.identity, children: [
|
|
7718
9364
|
participant.displayName,
|
|
7719
9365
|
" (private)"
|
|
7720
9366
|
] }, participant.identity))
|
|
7721
9367
|
]
|
|
7722
9368
|
}
|
|
7723
9369
|
) : null,
|
|
7724
|
-
/* @__PURE__ */ (0,
|
|
7725
|
-
/* @__PURE__ */ (0,
|
|
9370
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__composer-row", children: [
|
|
9371
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7726
9372
|
"input",
|
|
7727
9373
|
{
|
|
7728
9374
|
className: "mx-meet__input",
|
|
@@ -7733,9 +9379,9 @@ function ChatPanel({
|
|
|
7733
9379
|
maxLength: 4e3
|
|
7734
9380
|
}
|
|
7735
9381
|
),
|
|
7736
|
-
/* @__PURE__ */ (0,
|
|
9382
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "submit", className: "mx-meet__send", disabled: draft.trim().length === 0, children: "Send" })
|
|
7737
9383
|
] }),
|
|
7738
|
-
recipientName !== null ? /* @__PURE__ */ (0,
|
|
9384
|
+
recipientName !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__panel-note", children: [
|
|
7739
9385
|
"Only ",
|
|
7740
9386
|
recipientName,
|
|
7741
9387
|
" sees this. Private messages are not saved."
|
|
@@ -7753,7 +9399,7 @@ function ChatLine({
|
|
|
7753
9399
|
const mine = message.identity === local;
|
|
7754
9400
|
const privateTo = message.to ?? null;
|
|
7755
9401
|
const counterpart = privateTo === null ? null : mine ? people.find((p) => p.identity === privateTo)?.displayName ?? "them" : "you";
|
|
7756
|
-
return /* @__PURE__ */ (0,
|
|
9402
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7757
9403
|
"li",
|
|
7758
9404
|
{
|
|
7759
9405
|
className: [
|
|
@@ -7762,17 +9408,17 @@ function ChatLine({
|
|
|
7762
9408
|
message.failed !== void 0 ? "mx-meet__chat-line--failed" : ""
|
|
7763
9409
|
].filter(Boolean).join(" "),
|
|
7764
9410
|
children: [
|
|
7765
|
-
/* @__PURE__ */ (0,
|
|
7766
|
-
/* @__PURE__ */ (0,
|
|
7767
|
-
counterpart !== null ? /* @__PURE__ */ (0,
|
|
9411
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__chat-meta", children: [
|
|
9412
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: mine ? "You" : message.displayName }),
|
|
9413
|
+
counterpart !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__chat-private", children: [
|
|
7768
9414
|
"to ",
|
|
7769
9415
|
counterpart,
|
|
7770
9416
|
" \xB7 private"
|
|
7771
9417
|
] }) : null,
|
|
7772
|
-
/* @__PURE__ */ (0,
|
|
9418
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("time", { dateTime: message.at, children: clockOf(message.at) })
|
|
7773
9419
|
] }),
|
|
7774
|
-
/* @__PURE__ */ (0,
|
|
7775
|
-
message.failed !== void 0 ? /* @__PURE__ */ (0,
|
|
9420
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__chat-text", children: message.text }),
|
|
9421
|
+
message.failed !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__chat-failed", children: message.failed }) : privateTo === null && message.saved === false ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__chat-pending", children: message.id.startsWith("pending-") ? "Sending\u2026" : "Not saved \u2014 people who join later will not see this" }) : null
|
|
7776
9422
|
]
|
|
7777
9423
|
}
|
|
7778
9424
|
);
|
|
@@ -7784,22 +9430,22 @@ function PeoplePanel({
|
|
|
7784
9430
|
const snapshot = useMeetSnapshot();
|
|
7785
9431
|
const controls = useHostControls();
|
|
7786
9432
|
const queue = useHandQueue();
|
|
7787
|
-
const [query, setQuery] = (0,
|
|
7788
|
-
const [menuFor, setMenuFor] = (0,
|
|
9433
|
+
const [query, setQuery] = (0, import_react5.useState)("");
|
|
9434
|
+
const [menuFor, setMenuFor] = (0, import_react5.useState)(null);
|
|
7789
9435
|
const myRole = useRole();
|
|
7790
9436
|
const local = snapshot?.localIdentity ?? null;
|
|
7791
9437
|
const everyone = snapshot?.participants ?? [];
|
|
7792
9438
|
const needle = query.trim().toLowerCase();
|
|
7793
9439
|
const shown = needle.length === 0 ? everyone : everyone.filter((participant) => participant.displayName.toLowerCase().includes(needle));
|
|
7794
|
-
return /* @__PURE__ */ (0,
|
|
7795
|
-
/* @__PURE__ */ (0,
|
|
7796
|
-
queue.length > 0 ? /* @__PURE__ */ (0,
|
|
7797
|
-
/* @__PURE__ */ (0,
|
|
7798
|
-
/* @__PURE__ */ (0,
|
|
9440
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(PanelShell, { title: `People (${everyone.length})`, onClose, children: [
|
|
9441
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LobbyPanel, {}),
|
|
9442
|
+
queue.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__section", "aria-label": "Raised hands", children: [
|
|
9443
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { className: "mx-meet__section-head", children: [
|
|
9444
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("h3", { className: "mx-meet__section-title", children: [
|
|
7799
9445
|
"Raised hands \xB7 ",
|
|
7800
9446
|
queue.length
|
|
7801
9447
|
] }),
|
|
7802
|
-
controls.isHost ? /* @__PURE__ */ (0,
|
|
9448
|
+
controls.isHost ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7803
9449
|
"button",
|
|
7804
9450
|
{
|
|
7805
9451
|
type: "button",
|
|
@@ -7809,13 +9455,13 @@ function PeoplePanel({
|
|
|
7809
9455
|
}
|
|
7810
9456
|
) : null
|
|
7811
9457
|
] }),
|
|
7812
|
-
/* @__PURE__ */ (0,
|
|
7813
|
-
/* @__PURE__ */ (0,
|
|
7814
|
-
/* @__PURE__ */ (0,
|
|
9458
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ol", { className: "mx-meet__queue", children: queue.map((participant) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { className: "mx-meet__person", children: [
|
|
9459
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Avatar, { name: participant.displayName, url: participant.avatarUrl, size: 28 }),
|
|
9460
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__person-name", children: [
|
|
7815
9461
|
participant.displayName,
|
|
7816
|
-
participant.identity === local ? /* @__PURE__ */ (0,
|
|
9462
|
+
participant.identity === local ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__you", children: " (you)" }) : null
|
|
7817
9463
|
] }),
|
|
7818
|
-
controls.isHost || participant.identity === local ? /* @__PURE__ */ (0,
|
|
9464
|
+
controls.isHost || participant.identity === local ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7819
9465
|
"button",
|
|
7820
9466
|
{
|
|
7821
9467
|
type: "button",
|
|
@@ -7826,27 +9472,27 @@ function PeoplePanel({
|
|
|
7826
9472
|
) : null
|
|
7827
9473
|
] }, participant.identity)) })
|
|
7828
9474
|
] }) : null,
|
|
7829
|
-
controls.isHost && everyone.length > 1 ? /* @__PURE__ */ (0,
|
|
7830
|
-
/* @__PURE__ */ (0,
|
|
7831
|
-
/* @__PURE__ */ (0,
|
|
9475
|
+
controls.isHost && everyone.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__bulk", children: [
|
|
9476
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { type: "button", className: "mx-meet__chip", onClick: () => void controls.run({ action: "mute_all" }), children: [
|
|
9477
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MicOffIcon, { width: 14, height: 14 }),
|
|
7832
9478
|
" Mute all"
|
|
7833
9479
|
] }),
|
|
7834
|
-
/* @__PURE__ */ (0,
|
|
9480
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7835
9481
|
"button",
|
|
7836
9482
|
{
|
|
7837
9483
|
type: "button",
|
|
7838
9484
|
className: "mx-meet__chip",
|
|
7839
9485
|
onClick: () => void controls.run({ action: "ask_all_unmute" }),
|
|
7840
9486
|
children: [
|
|
7841
|
-
/* @__PURE__ */ (0,
|
|
9487
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MicIcon, { width: 14, height: 14 }),
|
|
7842
9488
|
" Ask all to unmute"
|
|
7843
9489
|
]
|
|
7844
9490
|
}
|
|
7845
9491
|
)
|
|
7846
9492
|
] }) : null,
|
|
7847
|
-
everyone.length > 4 ? /* @__PURE__ */ (0,
|
|
7848
|
-
/* @__PURE__ */ (0,
|
|
7849
|
-
/* @__PURE__ */ (0,
|
|
9493
|
+
everyone.length > 4 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__search", children: [
|
|
9494
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SearchIcon, { width: 16, height: 16 }),
|
|
9495
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7850
9496
|
"input",
|
|
7851
9497
|
{
|
|
7852
9498
|
className: "mx-meet__input mx-meet__input--bare",
|
|
@@ -7857,31 +9503,31 @@ function PeoplePanel({
|
|
|
7857
9503
|
}
|
|
7858
9504
|
)
|
|
7859
9505
|
] }) : null,
|
|
7860
|
-
controls.notice !== null ? /* @__PURE__ */ (0,
|
|
7861
|
-
/* @__PURE__ */ (0,
|
|
7862
|
-
shown.map((participant) => /* @__PURE__ */ (0,
|
|
7863
|
-
/* @__PURE__ */ (0,
|
|
7864
|
-
/* @__PURE__ */ (0,
|
|
9506
|
+
controls.notice !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: controls.notice.failed ? "mx-meet__error" : "mx-meet__notice", role: "status", children: controls.notice.text }) : null,
|
|
9507
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("ul", { className: "mx-meet__people", children: [
|
|
9508
|
+
shown.map((participant) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { className: "mx-meet__person", children: [
|
|
9509
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Avatar, { name: participant.displayName, url: participant.avatarUrl, size: 32 }),
|
|
9510
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__person-name", children: [
|
|
7865
9511
|
participant.displayName,
|
|
7866
|
-
participant.identity === local ? /* @__PURE__ */ (0,
|
|
7867
|
-
/* @__PURE__ */ (0,
|
|
7868
|
-
isNoteTaker(participant) ? /* @__PURE__ */ (0,
|
|
7869
|
-
snapshot?.spotlight === participant.identity ? /* @__PURE__ */ (0,
|
|
9512
|
+
participant.identity === local ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__you", children: " (you)" }) : null,
|
|
9513
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RoleBadge, { role: participant.identity === local ? myRole : participant.role }),
|
|
9514
|
+
isNoteTaker(participant) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Meeting assistant" }) : null,
|
|
9515
|
+
snapshot?.spotlight === participant.identity ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Spotlight" }) : null
|
|
7870
9516
|
] }),
|
|
7871
|
-
participant.handRaised ? /* @__PURE__ */ (0,
|
|
7872
|
-
!participant.micEnabled && !isNoteTaker(participant) ? /* @__PURE__ */ (0,
|
|
7873
|
-
/* @__PURE__ */ (0,
|
|
7874
|
-
/* @__PURE__ */ (0,
|
|
7875
|
-
/* @__PURE__ */ (0,
|
|
9517
|
+
participant.handRaised ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HandIcon, { width: 14, height: 14 }) : null,
|
|
9518
|
+
!participant.micEnabled && !isNoteTaker(participant) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MicOffIcon, { width: 14, height: 14 }) : null,
|
|
9519
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(QualityBars, { quality: participant.quality }),
|
|
9520
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__anchor", children: [
|
|
9521
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7876
9522
|
ControlButton,
|
|
7877
9523
|
{
|
|
7878
9524
|
label: `More for ${participant.displayName}`,
|
|
7879
9525
|
active: menuFor === participant.identity,
|
|
7880
9526
|
onClick: () => setMenuFor(menuFor === participant.identity ? null : participant.identity),
|
|
7881
|
-
children: /* @__PURE__ */ (0,
|
|
9527
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MoreIcon, { width: 16, height: 16 })
|
|
7882
9528
|
}
|
|
7883
9529
|
),
|
|
7884
|
-
menuFor === participant.identity ? /* @__PURE__ */ (0,
|
|
9530
|
+
menuFor === participant.identity ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7885
9531
|
PersonMenu,
|
|
7886
9532
|
{
|
|
7887
9533
|
participant,
|
|
@@ -7892,13 +9538,13 @@ function PeoplePanel({
|
|
|
7892
9538
|
) : null
|
|
7893
9539
|
] })
|
|
7894
9540
|
] }, participant.identity)),
|
|
7895
|
-
shown.length === 0 ? /* @__PURE__ */ (0,
|
|
9541
|
+
shown.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { className: "mx-meet__panel-note", children: [
|
|
7896
9542
|
"Nobody matches \u201C",
|
|
7897
9543
|
query,
|
|
7898
9544
|
"\u201D."
|
|
7899
9545
|
] }) : null
|
|
7900
9546
|
] }),
|
|
7901
|
-
snapshot?.meeting !== null && snapshot?.meeting !== void 0 ? /* @__PURE__ */ (0,
|
|
9547
|
+
snapshot?.meeting !== null && snapshot?.meeting !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(GuestRecordAccessControl, { meeting: snapshot.meeting }) : null
|
|
7902
9548
|
] });
|
|
7903
9549
|
}
|
|
7904
9550
|
function PersonMenu({
|
|
@@ -7910,14 +9556,14 @@ function PersonMenu({
|
|
|
7910
9556
|
const host = useMeetHost();
|
|
7911
9557
|
const snapshot = useMeetSnapshot();
|
|
7912
9558
|
const controls = useHostControls();
|
|
7913
|
-
const [mode, setMode] = (0,
|
|
7914
|
-
const [text3, setText] = (0,
|
|
9559
|
+
const [mode, setMode] = (0, import_react5.useState)("menu");
|
|
9560
|
+
const [text3, setText] = (0, import_react5.useState)("");
|
|
7915
9561
|
const self = participant.identity === snapshot?.localIdentity;
|
|
7916
9562
|
const moderate = controls.canModerate(participant);
|
|
7917
9563
|
const pinned = snapshot?.pinned === participant.identity;
|
|
7918
9564
|
const spotlit = snapshot?.spotlight === participant.identity;
|
|
7919
9565
|
const hasAccount = participant.userId !== null;
|
|
7920
|
-
const [refused, setRefused] = (0,
|
|
9566
|
+
const [refused, setRefused] = (0, import_react5.useState)(false);
|
|
7921
9567
|
const act = (request) => {
|
|
7922
9568
|
setRefused(false);
|
|
7923
9569
|
void controls.run(request).then((result) => {
|
|
@@ -7925,10 +9571,10 @@ function PersonMenu({
|
|
|
7925
9571
|
else setRefused(true);
|
|
7926
9572
|
});
|
|
7927
9573
|
};
|
|
7928
|
-
const refusal2 = refused && controls.notice?.failed === true ? /* @__PURE__ */ (0,
|
|
9574
|
+
const refusal2 = refused && controls.notice?.failed === true ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_design_system.ErrorBox, { as: "p", className: "mx-meet__error", message: controls.notice.text, operation: "Change this participant", origin: "meet/components", children: controls.notice.text }) : null;
|
|
7929
9575
|
if (mode === "rename" || mode === "report") {
|
|
7930
9576
|
const renaming = mode === "rename";
|
|
7931
|
-
return /* @__PURE__ */ (0,
|
|
9577
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Popover, { label: renaming ? "Rename" : "Report", onClose, placement, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7932
9578
|
"form",
|
|
7933
9579
|
{
|
|
7934
9580
|
className: "mx-meet__menu-form",
|
|
@@ -7940,9 +9586,9 @@ function PersonMenu({
|
|
|
7940
9586
|
);
|
|
7941
9587
|
},
|
|
7942
9588
|
children: [
|
|
7943
|
-
/* @__PURE__ */ (0,
|
|
7944
|
-
/* @__PURE__ */ (0,
|
|
7945
|
-
renaming ? /* @__PURE__ */ (0,
|
|
9589
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__field", children: [
|
|
9590
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__field-label", children: renaming ? "Name shown in this meeting" : `What did ${participant.displayName} do?` }),
|
|
9591
|
+
renaming ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7946
9592
|
"input",
|
|
7947
9593
|
{
|
|
7948
9594
|
className: "mx-meet__input",
|
|
@@ -7951,7 +9597,7 @@ function PersonMenu({
|
|
|
7951
9597
|
value: text3,
|
|
7952
9598
|
onChange: (event) => setText(event.target.value)
|
|
7953
9599
|
}
|
|
7954
|
-
) : /* @__PURE__ */ (0,
|
|
9600
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7955
9601
|
"textarea",
|
|
7956
9602
|
{
|
|
7957
9603
|
className: "mx-meet__input",
|
|
@@ -7964,9 +9610,9 @@ function PersonMenu({
|
|
|
7964
9610
|
)
|
|
7965
9611
|
] }),
|
|
7966
9612
|
refusal2,
|
|
7967
|
-
/* @__PURE__ */ (0,
|
|
7968
|
-
/* @__PURE__ */ (0,
|
|
7969
|
-
/* @__PURE__ */ (0,
|
|
9613
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__menu-actions", children: [
|
|
9614
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mx-meet__link", onClick: () => setMode("menu"), children: "Back" }),
|
|
9615
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "submit", className: "mx-meet__send", disabled: text3.trim().length === 0 || controls.busy, children: renaming ? "Rename" : "Report" })
|
|
7970
9616
|
] })
|
|
7971
9617
|
]
|
|
7972
9618
|
}
|
|
@@ -7974,12 +9620,12 @@ function PersonMenu({
|
|
|
7974
9620
|
}
|
|
7975
9621
|
if (mode === "remove" || mode === "transfer") {
|
|
7976
9622
|
const removing = mode === "remove";
|
|
7977
|
-
return /* @__PURE__ */ (0,
|
|
7978
|
-
/* @__PURE__ */ (0,
|
|
9623
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Popover, { label: removing ? "Remove" : "Make host", onClose, placement, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__menu-form", children: [
|
|
9624
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("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.` }),
|
|
7979
9625
|
refusal2,
|
|
7980
|
-
/* @__PURE__ */ (0,
|
|
7981
|
-
/* @__PURE__ */ (0,
|
|
7982
|
-
/* @__PURE__ */ (0,
|
|
9626
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__menu-actions", children: [
|
|
9627
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mx-meet__link", onClick: () => setMode("menu"), children: "Cancel" }),
|
|
9628
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7983
9629
|
"button",
|
|
7984
9630
|
{
|
|
7985
9631
|
type: "button",
|
|
@@ -7992,8 +9638,8 @@ function PersonMenu({
|
|
|
7992
9638
|
] })
|
|
7993
9639
|
] }) });
|
|
7994
9640
|
}
|
|
7995
|
-
return /* @__PURE__ */ (0,
|
|
7996
|
-
/* @__PURE__ */ (0,
|
|
9641
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Popover, { label: `Options for ${participant.displayName}`, onClose, placement, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__menu", role: "menu", children: [
|
|
9642
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7997
9643
|
MenuItem,
|
|
7998
9644
|
{
|
|
7999
9645
|
onSelect: () => {
|
|
@@ -8001,13 +9647,13 @@ function PersonMenu({
|
|
|
8001
9647
|
onClose();
|
|
8002
9648
|
},
|
|
8003
9649
|
children: [
|
|
8004
|
-
/* @__PURE__ */ (0,
|
|
9650
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PinIcon, { width: 16, height: 16 }),
|
|
8005
9651
|
" ",
|
|
8006
9652
|
pinned ? "Unpin" : "Pin for me"
|
|
8007
9653
|
]
|
|
8008
9654
|
}
|
|
8009
9655
|
),
|
|
8010
|
-
!self && !participant.isAgent && (onMessage !== void 0 || host !== null) ? /* @__PURE__ */ (0,
|
|
9656
|
+
!self && !participant.isAgent && (onMessage !== void 0 || host !== null) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8011
9657
|
MenuItem,
|
|
8012
9658
|
{
|
|
8013
9659
|
onSelect: () => {
|
|
@@ -8019,42 +9665,42 @@ function PersonMenu({
|
|
|
8019
9665
|
onClose();
|
|
8020
9666
|
},
|
|
8021
9667
|
children: [
|
|
8022
|
-
/* @__PURE__ */ (0,
|
|
9668
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChatIcon, { width: 16, height: 16 }),
|
|
8023
9669
|
" Message privately"
|
|
8024
9670
|
]
|
|
8025
9671
|
}
|
|
8026
9672
|
) : null,
|
|
8027
|
-
controls.isHost ? /* @__PURE__ */ (0,
|
|
8028
|
-
/* @__PURE__ */ (0,
|
|
9673
|
+
controls.isHost ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { onSelect: () => act({ action: "spotlight", identity: spotlit ? null : participant.identity }), children: [
|
|
9674
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SpotlightIcon, { width: 16, height: 16 }),
|
|
8029
9675
|
" ",
|
|
8030
9676
|
spotlit ? "Remove spotlight" : "Spotlight for everyone"
|
|
8031
9677
|
] }) : null,
|
|
8032
|
-
moderate ? /* @__PURE__ */ (0,
|
|
8033
|
-
/* @__PURE__ */ (0,
|
|
8034
|
-
participant.micEnabled ? /* @__PURE__ */ (0,
|
|
8035
|
-
/* @__PURE__ */ (0,
|
|
9678
|
+
moderate ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
9679
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet__menu-sep", role: "separator" }),
|
|
9680
|
+
participant.micEnabled ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { onSelect: () => act({ action: "mute", identity: participant.identity }), children: [
|
|
9681
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MicOffIcon, { width: 16, height: 16 }),
|
|
8036
9682
|
" Mute"
|
|
8037
|
-
] }) : !participant.isAgent ? /* @__PURE__ */ (0,
|
|
8038
|
-
/* @__PURE__ */ (0,
|
|
9683
|
+
] }) : !participant.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { onSelect: () => act({ action: "ask_unmute", identity: participant.identity }), children: [
|
|
9684
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MicIcon, { width: 16, height: 16 }),
|
|
8039
9685
|
" Ask to unmute"
|
|
8040
9686
|
] }) : null,
|
|
8041
|
-
participant.cameraEnabled ? /* @__PURE__ */ (0,
|
|
8042
|
-
/* @__PURE__ */ (0,
|
|
9687
|
+
participant.cameraEnabled ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { onSelect: () => act({ action: "stop_video", identity: participant.identity }), children: [
|
|
9688
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CameraOffIcon, { width: 16, height: 16 }),
|
|
8043
9689
|
" Stop video"
|
|
8044
9690
|
] }) : null,
|
|
8045
|
-
participant.screenSharing ? /* @__PURE__ */ (0,
|
|
8046
|
-
/* @__PURE__ */ (0,
|
|
9691
|
+
participant.screenSharing ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { onSelect: () => act({ action: "stop_screen", identity: participant.identity }), children: [
|
|
9692
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ScreenShareIcon, { width: 16, height: 16 }),
|
|
8047
9693
|
" Stop screen share"
|
|
8048
9694
|
] }) : null,
|
|
8049
|
-
participant.handRaised ? /* @__PURE__ */ (0,
|
|
8050
|
-
/* @__PURE__ */ (0,
|
|
9695
|
+
participant.handRaised ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { onSelect: () => act({ action: "lower_hand", identity: participant.identity }), children: [
|
|
9696
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HandIcon, { width: 16, height: 16 }),
|
|
8051
9697
|
" Lower hand"
|
|
8052
9698
|
] }) : null,
|
|
8053
|
-
hasAccount && !participant.isAgent && participant.role !== "cohost" ? /* @__PURE__ */ (0,
|
|
8054
|
-
/* @__PURE__ */ (0,
|
|
9699
|
+
hasAccount && !participant.isAgent && participant.role !== "cohost" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { onSelect: () => act({ action: "make_cohost", identity: participant.identity }), children: [
|
|
9700
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PeopleIcon, { width: 16, height: 16 }),
|
|
8055
9701
|
" Make co-host"
|
|
8056
9702
|
] }) : null,
|
|
8057
|
-
!participant.isAgent ? /* @__PURE__ */ (0,
|
|
9703
|
+
!participant.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8058
9704
|
MenuItem,
|
|
8059
9705
|
{
|
|
8060
9706
|
onSelect: () => {
|
|
@@ -8062,21 +9708,21 @@ function PersonMenu({
|
|
|
8062
9708
|
setMode("rename");
|
|
8063
9709
|
},
|
|
8064
9710
|
children: [
|
|
8065
|
-
/* @__PURE__ */ (0,
|
|
9711
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PencilIcon, { width: 16, height: 16 }),
|
|
8066
9712
|
" Rename"
|
|
8067
9713
|
]
|
|
8068
9714
|
}
|
|
8069
9715
|
) : null
|
|
8070
9716
|
] }) : null,
|
|
8071
|
-
controls.isOwner && participant.role === "cohost" ? /* @__PURE__ */ (0,
|
|
8072
|
-
/* @__PURE__ */ (0,
|
|
9717
|
+
controls.isOwner && participant.role === "cohost" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { onSelect: () => act({ action: "revoke_cohost", identity: participant.identity }), children: [
|
|
9718
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PeopleIcon, { width: 16, height: 16 }),
|
|
8073
9719
|
" Remove co-host"
|
|
8074
9720
|
] }) : null,
|
|
8075
|
-
controls.isOwner && !self && hasAccount && !participant.isAgent ? /* @__PURE__ */ (0,
|
|
8076
|
-
/* @__PURE__ */ (0,
|
|
9721
|
+
controls.isOwner && !self && hasAccount && !participant.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { onSelect: () => setMode("transfer"), children: [
|
|
9722
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SpotlightIcon, { width: 16, height: 16 }),
|
|
8077
9723
|
" Make host"
|
|
8078
9724
|
] }) : null,
|
|
8079
|
-
self ? /* @__PURE__ */ (0,
|
|
9725
|
+
self ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8080
9726
|
MenuItem,
|
|
8081
9727
|
{
|
|
8082
9728
|
onSelect: () => {
|
|
@@ -8084,12 +9730,12 @@ function PersonMenu({
|
|
|
8084
9730
|
setMode("rename");
|
|
8085
9731
|
},
|
|
8086
9732
|
children: [
|
|
8087
|
-
/* @__PURE__ */ (0,
|
|
9733
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PencilIcon, { width: 16, height: 16 }),
|
|
8088
9734
|
" Rename yourself"
|
|
8089
9735
|
]
|
|
8090
9736
|
}
|
|
8091
9737
|
) : null,
|
|
8092
|
-
!self && !participant.isAgent ? /* @__PURE__ */ (0,
|
|
9738
|
+
!self && !participant.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8093
9739
|
MenuItem,
|
|
8094
9740
|
{
|
|
8095
9741
|
onSelect: () => {
|
|
@@ -8097,21 +9743,21 @@ function PersonMenu({
|
|
|
8097
9743
|
setMode("report");
|
|
8098
9744
|
},
|
|
8099
9745
|
children: [
|
|
8100
|
-
/* @__PURE__ */ (0,
|
|
9746
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FlagIcon, { width: 16, height: 16 }),
|
|
8101
9747
|
" Report"
|
|
8102
9748
|
]
|
|
8103
9749
|
}
|
|
8104
9750
|
) : null,
|
|
8105
|
-
moderate && !participant.isAgent ? /* @__PURE__ */ (0,
|
|
8106
|
-
/* @__PURE__ */ (0,
|
|
9751
|
+
moderate && !participant.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { danger: true, onSelect: () => setMode("remove"), children: [
|
|
9752
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CloseIcon, { width: 16, height: 16 }),
|
|
8107
9753
|
" Remove from meeting"
|
|
8108
9754
|
] }) : null
|
|
8109
9755
|
] }) });
|
|
8110
9756
|
}
|
|
8111
9757
|
function SettingsPanel({ onClose }) {
|
|
8112
9758
|
const host = useRequiredMeetHost();
|
|
8113
|
-
return /* @__PURE__ */ (0,
|
|
8114
|
-
/* @__PURE__ */ (0,
|
|
9759
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(PanelShell, { title: "Settings", onClose, children: [
|
|
9760
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8115
9761
|
DeviceSettings,
|
|
8116
9762
|
{
|
|
8117
9763
|
onPick: (kind, deviceId2) => {
|
|
@@ -8120,7 +9766,8 @@ function SettingsPanel({ onClose }) {
|
|
|
8120
9766
|
}
|
|
8121
9767
|
}
|
|
8122
9768
|
),
|
|
8123
|
-
/* @__PURE__ */ (0,
|
|
9769
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(EffectsSettings, {}),
|
|
9770
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CaptionLanguageSettings, {})
|
|
8124
9771
|
] });
|
|
8125
9772
|
}
|
|
8126
9773
|
function DeviceSettings({
|
|
@@ -8132,15 +9779,15 @@ function DeviceSettings({
|
|
|
8132
9779
|
const speaker = devices?.selected.audiooutput ?? host.devices.resolve("audiooutput");
|
|
8133
9780
|
const stream = useMicrophoneStream(microphone);
|
|
8134
9781
|
const level = useAudioLevel(stream);
|
|
8135
|
-
const [testing, setTesting] = (0,
|
|
8136
|
-
(0,
|
|
9782
|
+
const [testing, setTesting] = (0, import_react5.useState)(false);
|
|
9783
|
+
(0, import_react5.useEffect)(() => {
|
|
8137
9784
|
void host.devices.refresh();
|
|
8138
9785
|
}, [host]);
|
|
8139
|
-
return /* @__PURE__ */ (0,
|
|
8140
|
-
/* @__PURE__ */ (0,
|
|
8141
|
-
/* @__PURE__ */ (0,
|
|
8142
|
-
/* @__PURE__ */ (0,
|
|
8143
|
-
/* @__PURE__ */ (0,
|
|
9786
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__section", "aria-label": "Devices", children: [
|
|
9787
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DevicePicker, { kind: "audioinput", label: "Microphone", onPick }),
|
|
9788
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("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__ */ (0, import_jsx_runtime4.jsx)("span", { style: { width: `${Math.min(100, Math.round(level * 160))}%` } }) }),
|
|
9789
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DevicePicker, { kind: "audiooutput", label: "Speaker", onPick }),
|
|
9790
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8144
9791
|
"button",
|
|
8145
9792
|
{
|
|
8146
9793
|
type: "button",
|
|
@@ -8151,19 +9798,19 @@ function DeviceSettings({
|
|
|
8151
9798
|
void playTestSound(speaker).finally(() => setTesting(false));
|
|
8152
9799
|
},
|
|
8153
9800
|
children: [
|
|
8154
|
-
/* @__PURE__ */ (0,
|
|
9801
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SpeakerIcon, { width: 14, height: 14 }),
|
|
8155
9802
|
" ",
|
|
8156
9803
|
testing ? "Playing\u2026" : "Test speaker"
|
|
8157
9804
|
]
|
|
8158
9805
|
}
|
|
8159
9806
|
),
|
|
8160
|
-
/* @__PURE__ */ (0,
|
|
9807
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DevicePicker, { kind: "videoinput", label: "Camera", onPick })
|
|
8161
9808
|
] });
|
|
8162
9809
|
}
|
|
8163
9810
|
function EffectsSettings({ preview }) {
|
|
8164
9811
|
const effects = useMediaEffects();
|
|
8165
|
-
const [error, setError] = (0,
|
|
8166
|
-
const fileRef = (0,
|
|
9812
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
9813
|
+
const fileRef = (0, import_react5.useRef)(null);
|
|
8167
9814
|
const supported = effects.backgroundsSupported || preview != null || videoEffectsSupported();
|
|
8168
9815
|
const apply = (next) => {
|
|
8169
9816
|
setError(null);
|
|
@@ -8175,9 +9822,9 @@ function EffectsSettings({ preview }) {
|
|
|
8175
9822
|
);
|
|
8176
9823
|
}
|
|
8177
9824
|
};
|
|
8178
|
-
return /* @__PURE__ */ (0,
|
|
8179
|
-
/* @__PURE__ */ (0,
|
|
8180
|
-
/* @__PURE__ */ (0,
|
|
9825
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__section", "aria-label": "Effects", children: [
|
|
9826
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__toggle", children: [
|
|
9827
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8181
9828
|
"input",
|
|
8182
9829
|
{
|
|
8183
9830
|
type: "checkbox",
|
|
@@ -8186,11 +9833,11 @@ function EffectsSettings({ preview }) {
|
|
|
8186
9833
|
}
|
|
8187
9834
|
),
|
|
8188
9835
|
"Noise suppression",
|
|
8189
|
-
/* @__PURE__ */ (0,
|
|
9836
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__hint", children: "Filters keyboards, fans and background chatter." })
|
|
8190
9837
|
] }),
|
|
8191
|
-
supported ? /* @__PURE__ */ (0,
|
|
8192
|
-
/* @__PURE__ */ (0,
|
|
8193
|
-
/* @__PURE__ */ (0,
|
|
9838
|
+
supported ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__field", children: [
|
|
9839
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__field-label", children: "Background" }),
|
|
9840
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet__pills", role: "radiogroup", "aria-label": "Background", children: ["none", "blur", "image"].map((kind) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8194
9841
|
"button",
|
|
8195
9842
|
{
|
|
8196
9843
|
type: "button",
|
|
@@ -8208,7 +9855,7 @@ function EffectsSettings({ preview }) {
|
|
|
8208
9855
|
},
|
|
8209
9856
|
kind
|
|
8210
9857
|
)) }),
|
|
8211
|
-
/* @__PURE__ */ (0,
|
|
9858
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8212
9859
|
"input",
|
|
8213
9860
|
{
|
|
8214
9861
|
ref: fileRef,
|
|
@@ -8223,7 +9870,7 @@ function EffectsSettings({ preview }) {
|
|
|
8223
9870
|
}
|
|
8224
9871
|
}
|
|
8225
9872
|
),
|
|
8226
|
-
error !== null ? /* @__PURE__ */ (0,
|
|
9873
|
+
error !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__error", children: error }) : null
|
|
8227
9874
|
] }) : null
|
|
8228
9875
|
] });
|
|
8229
9876
|
}
|
|
@@ -8282,8 +9929,8 @@ async function playTestSound(sinkId) {
|
|
|
8282
9929
|
await context.close();
|
|
8283
9930
|
}
|
|
8284
9931
|
function useMicrophoneStream(deviceId2) {
|
|
8285
|
-
const [stream, setStream] = (0,
|
|
8286
|
-
(0,
|
|
9932
|
+
const [stream, setStream] = (0, import_react5.useState)(null);
|
|
9933
|
+
(0, import_react5.useEffect)(() => {
|
|
8287
9934
|
if (deviceId2 === "off") return void 0;
|
|
8288
9935
|
let live = true;
|
|
8289
9936
|
let opened = null;
|
|
@@ -8308,25 +9955,25 @@ function useMicrophoneStream(deviceId2) {
|
|
|
8308
9955
|
function LobbyPanel() {
|
|
8309
9956
|
const lobby = useLobby();
|
|
8310
9957
|
if (!lobby.canAdmit || lobby.waiting.length === 0) return null;
|
|
8311
|
-
return /* @__PURE__ */ (0,
|
|
8312
|
-
/* @__PURE__ */ (0,
|
|
8313
|
-
/* @__PURE__ */ (0,
|
|
8314
|
-
/* @__PURE__ */ (0,
|
|
9958
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__lobby", "aria-label": "Waiting room", children: [
|
|
9959
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { className: "mx-meet__lobby-head", children: [
|
|
9960
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { className: "mx-meet__lobby-title", children: lobby.waiting.length === 1 ? "1 person is waiting" : `${lobby.waiting.length} people are waiting` }),
|
|
9961
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mx-meet__link", onClick: () => void lobby.admitAll(), children: "Admit all" })
|
|
8315
9962
|
] }),
|
|
8316
|
-
/* @__PURE__ */ (0,
|
|
8317
|
-
/* @__PURE__ */ (0,
|
|
8318
|
-
/* @__PURE__ */ (0,
|
|
9963
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: "mx-meet__lobby-list", children: lobby.waiting.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { className: "mx-meet__lobby-row", children: [
|
|
9964
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Avatar, { name: entry.displayName, url: entry.avatarUrl, size: 32 }),
|
|
9965
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__person-name", children: [
|
|
8319
9966
|
entry.displayName,
|
|
8320
|
-
entry.userId === null ? /* @__PURE__ */ (0,
|
|
9967
|
+
entry.userId === null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Guest" }) : null
|
|
8321
9968
|
] }),
|
|
8322
|
-
/* @__PURE__ */ (0,
|
|
8323
|
-
/* @__PURE__ */ (0,
|
|
9969
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ControlButton, { label: `Admit ${entry.displayName}`, onClick: () => void lobby.admit(entry), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CheckIcon, { width: 16, height: 16 }) }),
|
|
9970
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8324
9971
|
ControlButton,
|
|
8325
9972
|
{
|
|
8326
9973
|
label: `Deny ${entry.displayName}`,
|
|
8327
9974
|
danger: true,
|
|
8328
9975
|
onClick: () => void lobby.deny(entry),
|
|
8329
|
-
children: /* @__PURE__ */ (0,
|
|
9976
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CloseIcon, { width: 16, height: 16 })
|
|
8330
9977
|
}
|
|
8331
9978
|
)
|
|
8332
9979
|
] }, entry.identity)) })
|
|
@@ -8336,21 +9983,21 @@ function NoteTakerRow() {
|
|
|
8336
9983
|
const ai = useMeetAi();
|
|
8337
9984
|
const status = ai.noteTaker;
|
|
8338
9985
|
const duplicateError = status.refusal !== null && ai.error !== null && status.refusal.reason === ai.error.message && status.refusal.remedy === ai.error.remedy;
|
|
8339
|
-
return /* @__PURE__ */ (0,
|
|
8340
|
-
/* @__PURE__ */ (0,
|
|
8341
|
-
/* @__PURE__ */ (0,
|
|
9986
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__note-taker", "aria-label": "Note-taker", children: [
|
|
9987
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: `mx-meet__note-taker-state mx-meet__note-taker-state--${status.state}`, children: [
|
|
9988
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__note-taker-dot", "aria-hidden": "true" }),
|
|
8342
9989
|
ai.noteTakerLabel
|
|
8343
9990
|
] }),
|
|
8344
|
-
status.detail !== null ? /* @__PURE__ */ (0,
|
|
8345
|
-
status.refusal !== null ? /* @__PURE__ */ (0,
|
|
8346
|
-
/* @__PURE__ */ (0,
|
|
8347
|
-
status.refusal.remedy.length > 0 ? /* @__PURE__ */ (0,
|
|
9991
|
+
status.detail !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: status.detail }) : null,
|
|
9992
|
+
status.refusal !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system.ErrorBox, { as: "div", className: "mx-meet__refusal", error: status.refusal, operation: "Join this meeting", origin: "meet/components", children: [
|
|
9993
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-reason", children: status.refusal.reason }),
|
|
9994
|
+
status.refusal.remedy.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-remedy", children: status.refusal.remedy }) : null
|
|
8348
9995
|
] }) : null,
|
|
8349
|
-
ai.error !== null && !duplicateError ? /* @__PURE__ */ (0,
|
|
8350
|
-
/* @__PURE__ */ (0,
|
|
8351
|
-
/* @__PURE__ */ (0,
|
|
9996
|
+
ai.error !== null && !duplicateError ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system.ErrorBox, { as: "div", className: "mx-meet__refusal", error: ai.error, operation: "Run the meeting assistant", origin: "meet/components", children: [
|
|
9997
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-reason", children: ai.error.message }),
|
|
9998
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-remedy", children: ai.error.remedy })
|
|
8352
9999
|
] }) : null,
|
|
8353
|
-
ai.canControlNoteTaker ? status.state === "transcribing" || status.state === "joining" || status.state === "handoff_pending" ? /* @__PURE__ */ (0,
|
|
10000
|
+
ai.canControlNoteTaker ? status.state === "transcribing" || status.state === "joining" || status.state === "handoff_pending" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8354
10001
|
"button",
|
|
8355
10002
|
{
|
|
8356
10003
|
type: "button",
|
|
@@ -8358,7 +10005,7 @@ function NoteTakerRow() {
|
|
|
8358
10005
|
onClick: () => void ai.stopNoteTaker(),
|
|
8359
10006
|
children: "Dismiss the note-taker"
|
|
8360
10007
|
}
|
|
8361
|
-
) : /* @__PURE__ */ (0,
|
|
10008
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8362
10009
|
"button",
|
|
8363
10010
|
{
|
|
8364
10011
|
type: "button",
|
|
@@ -8374,24 +10021,24 @@ function NoteList({
|
|
|
8374
10021
|
notes,
|
|
8375
10022
|
empty
|
|
8376
10023
|
}) {
|
|
8377
|
-
return /* @__PURE__ */ (0,
|
|
8378
|
-
/* @__PURE__ */ (0,
|
|
8379
|
-
notes.length === 0 ? /* @__PURE__ */ (0,
|
|
10024
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__note-group", "aria-label": title, children: [
|
|
10025
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { className: "mx-meet__note-group-title", children: title }),
|
|
10026
|
+
notes.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: empty }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: "mx-meet__notes", children: notes.map((note) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { className: "mx-meet__note", children: [
|
|
8380
10027
|
note.text,
|
|
8381
|
-
note.assigneeDisplayName !== void 0 && note.assigneeDisplayName !== null ? /* @__PURE__ */ (0,
|
|
10028
|
+
note.assigneeDisplayName !== void 0 && note.assigneeDisplayName !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__assignee", children: note.assigneeDisplayName }) : null
|
|
8382
10029
|
] }, note.id)) })
|
|
8383
10030
|
] });
|
|
8384
10031
|
}
|
|
8385
10032
|
function AiPanel({ onClose }) {
|
|
8386
10033
|
const ai = useMeetAi();
|
|
8387
|
-
const [question, setQuestion] = (0,
|
|
8388
|
-
return /* @__PURE__ */ (0,
|
|
8389
|
-
/* @__PURE__ */ (0,
|
|
8390
|
-
ai.summary !== null ? /* @__PURE__ */ (0,
|
|
8391
|
-
/* @__PURE__ */ (0,
|
|
8392
|
-
/* @__PURE__ */ (0,
|
|
10034
|
+
const [question, setQuestion] = (0, import_react5.useState)("");
|
|
10035
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(PanelShell, { title: "Meeting assistant", onClose, children: [
|
|
10036
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NoteTakerRow, {}),
|
|
10037
|
+
ai.summary !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__note-group", "aria-label": "Summary", children: [
|
|
10038
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { className: "mx-meet__note-group-title", children: "Summary" }),
|
|
10039
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__summary", children: ai.summary.text })
|
|
8393
10040
|
] }) : null,
|
|
8394
|
-
ai.wrapUp !== null ? /* @__PURE__ */ (0,
|
|
10041
|
+
ai.wrapUp !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__wrap-up-notice", role: "status", children: [
|
|
8395
10042
|
"The wrap-up is written \u2014 ",
|
|
8396
10043
|
ai.wrapUp.noteIds.length,
|
|
8397
10044
|
" ",
|
|
@@ -8403,7 +10050,7 @@ function AiPanel({ onClose }) {
|
|
|
8403
10050
|
ai.wrapUp.segmentCount === 1 ? "transcript line" : "transcript lines",
|
|
8404
10051
|
"."
|
|
8405
10052
|
] }) : null,
|
|
8406
|
-
/* @__PURE__ */ (0,
|
|
10053
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8407
10054
|
NoteList,
|
|
8408
10055
|
{
|
|
8409
10056
|
title: "Notes",
|
|
@@ -8411,7 +10058,7 @@ function AiPanel({ onClose }) {
|
|
|
8411
10058
|
empty: "Notes appear here as the meeting goes on."
|
|
8412
10059
|
}
|
|
8413
10060
|
),
|
|
8414
|
-
/* @__PURE__ */ (0,
|
|
10061
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8415
10062
|
NoteList,
|
|
8416
10063
|
{
|
|
8417
10064
|
title: "Decisions",
|
|
@@ -8419,7 +10066,7 @@ function AiPanel({ onClose }) {
|
|
|
8419
10066
|
empty: "Nothing has been decided yet."
|
|
8420
10067
|
}
|
|
8421
10068
|
),
|
|
8422
|
-
/* @__PURE__ */ (0,
|
|
10069
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8423
10070
|
NoteList,
|
|
8424
10071
|
{
|
|
8425
10072
|
title: "Action items",
|
|
@@ -8427,21 +10074,21 @@ function AiPanel({ onClose }) {
|
|
|
8427
10074
|
empty: "No action items yet."
|
|
8428
10075
|
}
|
|
8429
10076
|
),
|
|
8430
|
-
ai.transcript.length > 0 ? /* @__PURE__ */ (0,
|
|
8431
|
-
/* @__PURE__ */ (0,
|
|
8432
|
-
/* @__PURE__ */ (0,
|
|
10077
|
+
ai.transcript.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__note-group", "aria-label": "Transcript", children: [
|
|
10078
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { className: "mx-meet__note-group-title", children: "Transcript" }),
|
|
10079
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: "mx-meet__transcript", children: ai.transcript.map((line) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8433
10080
|
"li",
|
|
8434
10081
|
{
|
|
8435
10082
|
className: line.final && line.source === "record" ? "mx-meet__line" : "mx-meet__line mx-meet__line--interim",
|
|
8436
10083
|
children: [
|
|
8437
|
-
/* @__PURE__ */ (0,
|
|
8438
|
-
/* @__PURE__ */ (0,
|
|
10084
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: line.speaker }),
|
|
10085
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: line.text })
|
|
8439
10086
|
]
|
|
8440
10087
|
},
|
|
8441
10088
|
line.id
|
|
8442
10089
|
)) })
|
|
8443
10090
|
] }) : null,
|
|
8444
|
-
/* @__PURE__ */ (0,
|
|
10091
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8445
10092
|
"form",
|
|
8446
10093
|
{
|
|
8447
10094
|
className: "mx-meet__composer",
|
|
@@ -8452,7 +10099,7 @@ function AiPanel({ onClose }) {
|
|
|
8452
10099
|
void ai.ask(asked);
|
|
8453
10100
|
},
|
|
8454
10101
|
children: [
|
|
8455
|
-
/* @__PURE__ */ (0,
|
|
10102
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8456
10103
|
"input",
|
|
8457
10104
|
{
|
|
8458
10105
|
className: "mx-meet__input",
|
|
@@ -8462,13 +10109,13 @@ function AiPanel({ onClose }) {
|
|
|
8462
10109
|
"aria-label": "Ask about this meeting"
|
|
8463
10110
|
}
|
|
8464
10111
|
),
|
|
8465
|
-
/* @__PURE__ */ (0,
|
|
10112
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "submit", className: "mx-meet__send", disabled: ai.asking, children: ai.asking ? "Asking\u2026" : "Ask" })
|
|
8466
10113
|
]
|
|
8467
10114
|
}
|
|
8468
10115
|
),
|
|
8469
|
-
ai.asking && ai.phase !== null ? /* @__PURE__ */ (0,
|
|
8470
|
-
ai.answer !== null ? /* @__PURE__ */ (0,
|
|
8471
|
-
ai.answer !== null && ai.coverage !== null ? /* @__PURE__ */ (0,
|
|
10116
|
+
ai.asking && ai.phase !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", role: "status", children: ai.phase }) : null,
|
|
10117
|
+
ai.answer !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__answer", children: ai.answer }) : null,
|
|
10118
|
+
ai.answer !== null && ai.coverage !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__coverage", children: [
|
|
8472
10119
|
"Answered from ",
|
|
8473
10120
|
ai.coverage.segmentsUsed,
|
|
8474
10121
|
" of ",
|
|
@@ -8477,48 +10124,56 @@ function AiPanel({ onClose }) {
|
|
|
8477
10124
|
ai.coverage.truncated ? " (the oldest were left out)" : "",
|
|
8478
10125
|
"."
|
|
8479
10126
|
] }) : null,
|
|
8480
|
-
ai.error !== null ? /* @__PURE__ */ (0,
|
|
8481
|
-
/* @__PURE__ */ (0,
|
|
8482
|
-
/* @__PURE__ */ (0,
|
|
10127
|
+
ai.error !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system.ErrorBox, { as: "div", className: "mx-meet__refusal", error: ai.error, operation: "Run the meeting assistant", origin: "meet/components", children: [
|
|
10128
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-reason", children: ai.error.message }),
|
|
10129
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-remedy", children: ai.error.remedy })
|
|
8483
10130
|
] }) : null
|
|
8484
10131
|
] });
|
|
8485
10132
|
}
|
|
8486
10133
|
function Captions({ lines = 3 }) {
|
|
8487
10134
|
const ai = useMeetAi();
|
|
8488
10135
|
const visible = ai.transcript.slice(-lines);
|
|
10136
|
+
const translation = useCaptionTranslation(visible);
|
|
8489
10137
|
if (visible.length === 0) return null;
|
|
8490
|
-
return /* @__PURE__ */ (0,
|
|
8491
|
-
|
|
8492
|
-
|
|
8493
|
-
|
|
8494
|
-
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
|
|
8498
|
-
|
|
8499
|
-
|
|
8500
|
-
|
|
8501
|
-
|
|
10138
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__captions", "aria-live": "polite", "aria-label": "Live captions", children: [
|
|
10139
|
+
visible.map((line) => {
|
|
10140
|
+
const translated = translation.language === null ? void 0 : translation.translations[line.id];
|
|
10141
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
10142
|
+
"p",
|
|
10143
|
+
{
|
|
10144
|
+
className: line.final ? "mx-meet__caption" : "mx-meet__caption mx-meet__caption--interim",
|
|
10145
|
+
children: [
|
|
10146
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: line.speaker }),
|
|
10147
|
+
" ",
|
|
10148
|
+
translated ?? line.text,
|
|
10149
|
+
translated !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__caption-original", children: line.text }) : null
|
|
10150
|
+
]
|
|
10151
|
+
},
|
|
10152
|
+
line.id
|
|
10153
|
+
);
|
|
10154
|
+
}),
|
|
10155
|
+
translation.language !== null && translation.error !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__caption mx-meet__caption--interim", children: translation.error }) : null
|
|
10156
|
+
] });
|
|
8502
10157
|
}
|
|
8503
10158
|
function ConsentNotice() {
|
|
8504
10159
|
const notice = useConsentNotice();
|
|
8505
10160
|
if (notice === null) return null;
|
|
8506
|
-
return /* @__PURE__ */ (0,
|
|
10161
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__consent", role: "status", children: notice });
|
|
8507
10162
|
}
|
|
8508
10163
|
function AttendanceNotice() {
|
|
8509
10164
|
const media = useLocalMedia();
|
|
8510
10165
|
const notice = listenOnlyNotice(media);
|
|
8511
10166
|
if (notice === null) return null;
|
|
8512
10167
|
const refused = media.microphone.unavailable;
|
|
8513
|
-
return /* @__PURE__ */ (0,
|
|
10168
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__banner mx-meet__banner--attendance", role: "status", children: [
|
|
8514
10169
|
notice,
|
|
8515
|
-
refused === null ? null : /* @__PURE__ */ (0,
|
|
10170
|
+
refused === null ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__remedy", children: refused.remedy })
|
|
8516
10171
|
] });
|
|
8517
10172
|
}
|
|
8518
10173
|
function PreJoin(props) {
|
|
8519
10174
|
const host = useMeetHost();
|
|
8520
|
-
if (host === null) return /* @__PURE__ */ (0,
|
|
8521
|
-
return /* @__PURE__ */ (0,
|
|
10175
|
+
if (host === null) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InertNotice, { what: "This meeting" });
|
|
10176
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PreJoinBody, { ...props, host });
|
|
8522
10177
|
}
|
|
8523
10178
|
function PreJoinBody({
|
|
8524
10179
|
roomName,
|
|
@@ -8532,21 +10187,21 @@ function PreJoinBody({
|
|
|
8532
10187
|
const recording = useRecording();
|
|
8533
10188
|
const effects = useMediaEffects();
|
|
8534
10189
|
const { notice } = useModerationNotice();
|
|
8535
|
-
const [mode, setMode] = (0,
|
|
8536
|
-
const [microphone, setMicrophone] = (0,
|
|
8537
|
-
const [joining, setJoining] = (0,
|
|
10190
|
+
const [mode, setMode] = (0, import_react5.useState)("video");
|
|
10191
|
+
const [microphone, setMicrophone] = (0, import_react5.useState)(true);
|
|
10192
|
+
const [joining, setJoining] = (0, import_react5.useState)(false);
|
|
8538
10193
|
const camera = devices?.selected.videoinput ?? host.devices.resolve("videoinput");
|
|
8539
10194
|
const mic = devices?.selected.audioinput ?? host.devices.resolve("audioinput");
|
|
8540
10195
|
const preview = useCameraPreview(mode === "video" ? camera : void 0, effects.effects);
|
|
8541
10196
|
const micStream = useMicrophoneStream(microphone ? mic : "off");
|
|
8542
10197
|
const level = useAudioLevel(micStream);
|
|
8543
|
-
const [speakerTesting, setSpeakerTesting] = (0,
|
|
8544
|
-
(0,
|
|
10198
|
+
const [speakerTesting, setSpeakerTesting] = (0, import_react5.useState)(false);
|
|
10199
|
+
(0, import_react5.useEffect)(() => {
|
|
8545
10200
|
void host.devices.refresh();
|
|
8546
10201
|
}, [host]);
|
|
8547
|
-
return /* @__PURE__ */ (0,
|
|
8548
|
-
/* @__PURE__ */ (0,
|
|
8549
|
-
mode === "video" && preview.preview !== null ? /* @__PURE__ */ (0,
|
|
10202
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__prejoin", children: [
|
|
10203
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__preview", children: [
|
|
10204
|
+
mode === "video" && preview.preview !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8550
10205
|
"video",
|
|
8551
10206
|
{
|
|
8552
10207
|
className: "mx-meet__video mx-meet__video--mirror",
|
|
@@ -8557,16 +10212,16 @@ function PreJoinBody({
|
|
|
8557
10212
|
if (element !== null) preview.preview?.attach(element);
|
|
8558
10213
|
}
|
|
8559
10214
|
}
|
|
8560
|
-
) : /* @__PURE__ */ (0,
|
|
8561
|
-
mode === "video" && preview.error !== null ? /* @__PURE__ */ (0,
|
|
8562
|
-
microphone && micStream !== null ? /* @__PURE__ */ (0,
|
|
10215
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet__tile-placeholder", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Avatar, { name: host.identity.displayName, url: host.identity.avatarUrl, size: 96 }) }),
|
|
10216
|
+
mode === "video" && preview.error !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__preview-note", children: preview.error }) : null,
|
|
10217
|
+
microphone && micStream !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("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__ */ (0, import_jsx_runtime4.jsx)("span", { style: { width: `${Math.min(100, Math.round(level * 160))}%` } }) }) : null
|
|
8563
10218
|
] }),
|
|
8564
|
-
/* @__PURE__ */ (0,
|
|
8565
|
-
/* @__PURE__ */ (0,
|
|
8566
|
-
notice?.kind === "removed" ? /* @__PURE__ */ (0,
|
|
8567
|
-
devices?.labelsHidden === true ? /* @__PURE__ */ (0,
|
|
10219
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__prejoin-panel", children: [
|
|
10220
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h1", { className: "mx-meet__prejoin-title", children: "Ready to join?" }),
|
|
10221
|
+
notice?.kind === "removed" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__warning", children: notice.text }) : null,
|
|
10222
|
+
devices?.labelsHidden === true ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__panel-note", children: [
|
|
8568
10223
|
"Your browser is hiding device names until you allow camera and microphone access.",
|
|
8569
|
-
/* @__PURE__ */ (0,
|
|
10224
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8570
10225
|
"button",
|
|
8571
10226
|
{
|
|
8572
10227
|
type: "button",
|
|
@@ -8578,11 +10233,11 @@ function PreJoinBody({
|
|
|
8578
10233
|
}
|
|
8579
10234
|
)
|
|
8580
10235
|
] }) : null,
|
|
8581
|
-
devices?.fallbackNotice != null ? /* @__PURE__ */ (0,
|
|
8582
|
-
/* @__PURE__ */ (0,
|
|
8583
|
-
/* @__PURE__ */ (0,
|
|
8584
|
-
/* @__PURE__ */ (0,
|
|
8585
|
-
/* @__PURE__ */ (0,
|
|
10236
|
+
devices?.fallbackNotice != null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__warning", children: devices.fallbackNotice }) : null,
|
|
10237
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DevicePicker, { kind: "audioinput", label: "Microphone" }),
|
|
10238
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__field-row", children: [
|
|
10239
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DevicePicker, { kind: "audiooutput", label: "Speaker" }),
|
|
10240
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8586
10241
|
"button",
|
|
8587
10242
|
{
|
|
8588
10243
|
type: "button",
|
|
@@ -8595,19 +10250,19 @@ function PreJoinBody({
|
|
|
8595
10250
|
);
|
|
8596
10251
|
},
|
|
8597
10252
|
children: [
|
|
8598
|
-
/* @__PURE__ */ (0,
|
|
10253
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SpeakerIcon, { width: 14, height: 14 }),
|
|
8599
10254
|
" ",
|
|
8600
10255
|
speakerTesting ? "Playing\u2026" : "Test"
|
|
8601
10256
|
]
|
|
8602
10257
|
}
|
|
8603
10258
|
)
|
|
8604
10259
|
] }),
|
|
8605
|
-
/* @__PURE__ */ (0,
|
|
8606
|
-
/* @__PURE__ */ (0,
|
|
8607
|
-
recording.consentNotice !== null ? /* @__PURE__ */ (0,
|
|
8608
|
-
/* @__PURE__ */ (0,
|
|
8609
|
-
/* @__PURE__ */ (0,
|
|
8610
|
-
/* @__PURE__ */ (0,
|
|
10260
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DevicePicker, { kind: "videoinput", label: "Camera" }),
|
|
10261
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(EffectsSettings, { preview: preview.preview }),
|
|
10262
|
+
recording.consentNotice !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__consent", children: recording.consentNotice }) : null,
|
|
10263
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__prejoin-actions", children: [
|
|
10264
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__toggle", children: [
|
|
10265
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8611
10266
|
"input",
|
|
8612
10267
|
{
|
|
8613
10268
|
type: "checkbox",
|
|
@@ -8617,8 +10272,8 @@ function PreJoinBody({
|
|
|
8617
10272
|
),
|
|
8618
10273
|
"Join with video"
|
|
8619
10274
|
] }),
|
|
8620
|
-
/* @__PURE__ */ (0,
|
|
8621
|
-
/* @__PURE__ */ (0,
|
|
10275
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__toggle", children: [
|
|
10276
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8622
10277
|
"input",
|
|
8623
10278
|
{
|
|
8624
10279
|
type: "checkbox",
|
|
@@ -8628,7 +10283,7 @@ function PreJoinBody({
|
|
|
8628
10283
|
),
|
|
8629
10284
|
"Join with microphone"
|
|
8630
10285
|
] }),
|
|
8631
|
-
/* @__PURE__ */ (0,
|
|
10286
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8632
10287
|
"button",
|
|
8633
10288
|
{
|
|
8634
10289
|
type: "button",
|
|
@@ -8648,20 +10303,20 @@ function PreJoinBody({
|
|
|
8648
10303
|
}
|
|
8649
10304
|
)
|
|
8650
10305
|
] }),
|
|
8651
|
-
room.failure !== null ? /* @__PURE__ */ (0,
|
|
10306
|
+
room.failure !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__error", children: [
|
|
8652
10307
|
room.failure.message,
|
|
8653
|
-
/* @__PURE__ */ (0,
|
|
10308
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__remedy", children: room.failure.remedy })
|
|
8654
10309
|
] }) : null
|
|
8655
10310
|
] })
|
|
8656
10311
|
] });
|
|
8657
10312
|
}
|
|
8658
10313
|
function useCameraPreview(deviceId2, effects) {
|
|
8659
|
-
const [preview, setPreview] = (0,
|
|
8660
|
-
const [error, setError] = (0,
|
|
8661
|
-
const current = (0,
|
|
8662
|
-
const initialEffect = (0,
|
|
10314
|
+
const [preview, setPreview] = (0, import_react5.useState)(null);
|
|
10315
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
10316
|
+
const current = (0, import_react5.useRef)(null);
|
|
10317
|
+
const initialEffect = (0, import_react5.useRef)(toVideoEffect(effects));
|
|
8663
10318
|
initialEffect.current = toVideoEffect(effects);
|
|
8664
|
-
(0,
|
|
10319
|
+
(0, import_react5.useEffect)(() => {
|
|
8665
10320
|
if (deviceId2 === void 0) return void 0;
|
|
8666
10321
|
let live = true;
|
|
8667
10322
|
setError(null);
|
|
@@ -8705,9 +10360,9 @@ function DevicePicker({
|
|
|
8705
10360
|
const devices = useDeviceSnapshot();
|
|
8706
10361
|
const list = devices?.devices[kind] ?? [];
|
|
8707
10362
|
if (list.length === 0) return null;
|
|
8708
|
-
return /* @__PURE__ */ (0,
|
|
8709
|
-
/* @__PURE__ */ (0,
|
|
8710
|
-
/* @__PURE__ */ (0,
|
|
10363
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__field", children: [
|
|
10364
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__field-label", children: label }),
|
|
10365
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8711
10366
|
"select",
|
|
8712
10367
|
{
|
|
8713
10368
|
className: "mx-meet__select",
|
|
@@ -8716,7 +10371,7 @@ function DevicePicker({
|
|
|
8716
10371
|
if (onPick !== void 0) onPick(kind, event.target.value);
|
|
8717
10372
|
else host.devices.select(kind, event.target.value);
|
|
8718
10373
|
},
|
|
8719
|
-
children: list.map((device) => /* @__PURE__ */ (0,
|
|
10374
|
+
children: list.map((device) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: device.deviceId, children: device.label.length > 0 ? device.label : `${label} (name hidden)` }, device.deviceId))
|
|
8720
10375
|
}
|
|
8721
10376
|
)
|
|
8722
10377
|
] });
|
|
@@ -8724,9 +10379,9 @@ function DevicePicker({
|
|
|
8724
10379
|
function MeetingRoom(props) {
|
|
8725
10380
|
const host = useMeetHost();
|
|
8726
10381
|
if (host === null) {
|
|
8727
|
-
return /* @__PURE__ */ (0,
|
|
10382
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InertNotice, { what: "This meeting" }) });
|
|
8728
10383
|
}
|
|
8729
|
-
return /* @__PURE__ */ (0,
|
|
10384
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MeetingRoomBody, { ...props, host });
|
|
8730
10385
|
}
|
|
8731
10386
|
function MeetingRoomBody({
|
|
8732
10387
|
roomName,
|
|
@@ -8741,25 +10396,25 @@ function MeetingRoomBody({
|
|
|
8741
10396
|
const isHost = useIsHost();
|
|
8742
10397
|
const elapsed = useElapsed(snapshot?.meeting?.startedAt ?? null);
|
|
8743
10398
|
const phase = snapshot?.phase ?? "idle";
|
|
8744
|
-
(0,
|
|
10399
|
+
(0, import_react5.useEffect)(() => {
|
|
8745
10400
|
host.meetings.watch(roomName);
|
|
8746
10401
|
}, [host, roomName]);
|
|
8747
|
-
(0,
|
|
10402
|
+
(0, import_react5.useEffect)(() => {
|
|
8748
10403
|
if (given === void 0) return;
|
|
8749
10404
|
if (host.store.snapshot().meeting !== null) return;
|
|
8750
10405
|
host.store.patch({ meeting: given, locked: given.locked });
|
|
8751
10406
|
}, [host, given]);
|
|
8752
10407
|
const watchedId = meetingId ?? snapshot?.meeting?.id ?? null;
|
|
8753
|
-
(0,
|
|
10408
|
+
(0, import_react5.useEffect)(() => {
|
|
8754
10409
|
if (watchedId === null) return;
|
|
8755
10410
|
host.meetings.watchMeeting(asMeetingId(watchedId));
|
|
8756
10411
|
}, [host, watchedId]);
|
|
8757
10412
|
const record = snapshot?.meeting ?? given ?? null;
|
|
8758
10413
|
if (hasEnded(record) && phase !== "connected" && phase !== "reconnecting") {
|
|
8759
|
-
return /* @__PURE__ */ (0,
|
|
10414
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MeetingRecordView, { meeting: record });
|
|
8760
10415
|
}
|
|
8761
10416
|
if (phase === "idle" || phase === "failed" || phase === "left") {
|
|
8762
|
-
return /* @__PURE__ */ (0,
|
|
10417
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8763
10418
|
PreJoin,
|
|
8764
10419
|
{
|
|
8765
10420
|
roomName,
|
|
@@ -8769,42 +10424,42 @@ function MeetingRoomBody({
|
|
|
8769
10424
|
) });
|
|
8770
10425
|
}
|
|
8771
10426
|
if (phase === "lobby") {
|
|
8772
|
-
return /* @__PURE__ */ (0,
|
|
8773
|
-
}
|
|
8774
|
-
return /* @__PURE__ */ (0,
|
|
8775
|
-
/* @__PURE__ */ (0,
|
|
8776
|
-
/* @__PURE__ */ (0,
|
|
8777
|
-
/* @__PURE__ */ (0,
|
|
8778
|
-
/* @__PURE__ */ (0,
|
|
8779
|
-
/* @__PURE__ */ (0,
|
|
10427
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet mx-meet--lobby", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(WaitingRoom, { roomName, host }) });
|
|
10428
|
+
}
|
|
10429
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet", children: [
|
|
10430
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ConsentNotice, {}),
|
|
10431
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AttendanceNotice, {}),
|
|
10432
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { className: "mx-meet__header", children: [
|
|
10433
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h1", { className: "mx-meet__title", children: snapshot?.meeting?.title ?? "Meeting" }),
|
|
10434
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__meta", children: [
|
|
8780
10435
|
participantSummary(snapshot?.participants ?? []),
|
|
8781
10436
|
elapsed > 0 ? ` \xB7 ${(0, import_format3.formatDurationMs)(elapsed)}` : ""
|
|
8782
10437
|
] }),
|
|
8783
|
-
/* @__PURE__ */ (0,
|
|
8784
|
-
snapshot?.locked === true ? /* @__PURE__ */ (0,
|
|
8785
|
-
/* @__PURE__ */ (0,
|
|
10438
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RecordingIndicator, {}),
|
|
10439
|
+
snapshot?.locked === true ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__badge", children: [
|
|
10440
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LockIcon, { width: 12, height: 12 }),
|
|
8786
10441
|
" Locked"
|
|
8787
10442
|
] }) : null,
|
|
8788
|
-
headerControls !== void 0 && headerControls !== null ? /* @__PURE__ */ (0,
|
|
8789
|
-
isHost ? /* @__PURE__ */ (0,
|
|
10443
|
+
headerControls !== void 0 && headerControls !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__header-controls", "data-meet-header-controls": "", children: headerControls }) : null,
|
|
10444
|
+
isHost ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HostMenu, {}) : null
|
|
8790
10445
|
] }),
|
|
8791
|
-
phase === "reconnecting" ? /* @__PURE__ */ (0,
|
|
8792
|
-
/* @__PURE__ */ (0,
|
|
8793
|
-
/* @__PURE__ */ (0,
|
|
8794
|
-
/* @__PURE__ */ (0,
|
|
10446
|
+
phase === "reconnecting" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__banner", role: "status", children: "Reconnecting\u2026" }) : null,
|
|
10447
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stage, {}),
|
|
10448
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Captions, {}),
|
|
10449
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ControlBar, { ...onLeave !== void 0 ? { onLeave } : {} })
|
|
8795
10450
|
] });
|
|
8796
10451
|
}
|
|
8797
10452
|
function WaitingRoom({ roomName, host }) {
|
|
8798
|
-
const knocked = (0,
|
|
8799
|
-
(0,
|
|
10453
|
+
const knocked = (0, import_react5.useRef)(false);
|
|
10454
|
+
(0, import_react5.useEffect)(() => {
|
|
8800
10455
|
if (knocked.current) return;
|
|
8801
10456
|
knocked.current = true;
|
|
8802
10457
|
host.meetings.knock(roomName);
|
|
8803
10458
|
}, [host, roomName]);
|
|
8804
|
-
return /* @__PURE__ */ (0,
|
|
8805
|
-
/* @__PURE__ */ (0,
|
|
8806
|
-
/* @__PURE__ */ (0,
|
|
8807
|
-
/* @__PURE__ */ (0,
|
|
10459
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__waiting", children: [
|
|
10460
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Avatar, { name: host.identity.displayName, url: host.identity.avatarUrl, size: 72 }),
|
|
10461
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h1", { className: "mx-meet__prejoin-title", children: "Waiting for the host to let you in" }),
|
|
10462
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__empty-body", children: [
|
|
8808
10463
|
"You are in the waiting room as ",
|
|
8809
10464
|
host.identity.displayName,
|
|
8810
10465
|
". You will join automatically once you are admitted."
|
|
@@ -8815,10 +10470,10 @@ function HostMenu() {
|
|
|
8815
10470
|
const host = useRequiredMeetHost();
|
|
8816
10471
|
const snapshot = useMeetSnapshot();
|
|
8817
10472
|
const end = useEndMeeting();
|
|
8818
|
-
const [confirmingEnd, setConfirmingEnd] = (0,
|
|
10473
|
+
const [confirmingEnd, setConfirmingEnd] = (0, import_react5.useState)(false);
|
|
8819
10474
|
const locked = snapshot?.locked === true;
|
|
8820
|
-
return /* @__PURE__ */ (0,
|
|
8821
|
-
/* @__PURE__ */ (0,
|
|
10475
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__host-menu", children: [
|
|
10476
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8822
10477
|
"button",
|
|
8823
10478
|
{
|
|
8824
10479
|
type: "button",
|
|
@@ -8829,9 +10484,9 @@ function HostMenu() {
|
|
|
8829
10484
|
children: locked ? "Unlock meeting" : "Lock meeting"
|
|
8830
10485
|
}
|
|
8831
10486
|
),
|
|
8832
|
-
end.canEnd ? confirmingEnd ? /* @__PURE__ */ (0,
|
|
8833
|
-
/* @__PURE__ */ (0,
|
|
8834
|
-
/* @__PURE__ */ (0,
|
|
10487
|
+
end.canEnd ? confirmingEnd ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__confirm", role: "group", "aria-label": "End this meeting?", children: [
|
|
10488
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("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." }),
|
|
10489
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8835
10490
|
"button",
|
|
8836
10491
|
{
|
|
8837
10492
|
type: "button",
|
|
@@ -8843,7 +10498,7 @@ function HostMenu() {
|
|
|
8843
10498
|
children: "End it"
|
|
8844
10499
|
}
|
|
8845
10500
|
),
|
|
8846
|
-
/* @__PURE__ */ (0,
|
|
10501
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8847
10502
|
"button",
|
|
8848
10503
|
{
|
|
8849
10504
|
type: "button",
|
|
@@ -8852,7 +10507,7 @@ function HostMenu() {
|
|
|
8852
10507
|
children: "Keep it running"
|
|
8853
10508
|
}
|
|
8854
10509
|
)
|
|
8855
|
-
] }) : /* @__PURE__ */ (0,
|
|
10510
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8856
10511
|
"button",
|
|
8857
10512
|
{
|
|
8858
10513
|
type: "button",
|
|
@@ -8861,7 +10516,7 @@ function HostMenu() {
|
|
|
8861
10516
|
children: end.ending ? "Ending\u2026" : "End meeting for everyone"
|
|
8862
10517
|
}
|
|
8863
10518
|
) : null,
|
|
8864
|
-
end.notice !== null ? /* @__PURE__ */ (0,
|
|
10519
|
+
end.notice !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__notice", role: "status", children: end.notice }) : null
|
|
8865
10520
|
] });
|
|
8866
10521
|
}
|
|
8867
10522
|
function CallButton({
|
|
@@ -8871,7 +10526,7 @@ function CallButton({
|
|
|
8871
10526
|
}) {
|
|
8872
10527
|
const calls = useCalls();
|
|
8873
10528
|
if (!calls.canCall) return null;
|
|
8874
|
-
return /* @__PURE__ */ (0,
|
|
10529
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8875
10530
|
"button",
|
|
8876
10531
|
{
|
|
8877
10532
|
type: "button",
|
|
@@ -8880,55 +10535,55 @@ function CallButton({
|
|
|
8880
10535
|
void calls.call([person.userId], mode);
|
|
8881
10536
|
},
|
|
8882
10537
|
"aria-label": `Call ${person.displayName}`,
|
|
8883
|
-
children: children ?? /* @__PURE__ */ (0,
|
|
10538
|
+
children: children ?? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PhoneIcon, { width: 18, height: 18 })
|
|
8884
10539
|
}
|
|
8885
10540
|
);
|
|
8886
10541
|
}
|
|
8887
10542
|
function IncomingCallHost() {
|
|
8888
10543
|
const calls = useCalls();
|
|
8889
10544
|
if (calls.incoming.length === 0) return null;
|
|
8890
|
-
return /* @__PURE__ */ (0,
|
|
10545
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet__ringing-stack", children: calls.incoming.map((invite) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(IncomingCallCard, { invite }, invite.id)) });
|
|
8891
10546
|
}
|
|
8892
10547
|
function IncomingCallCard({ invite }) {
|
|
8893
10548
|
const calls = useCalls();
|
|
8894
|
-
return /* @__PURE__ */ (0,
|
|
8895
|
-
/* @__PURE__ */ (0,
|
|
8896
|
-
/* @__PURE__ */ (0,
|
|
8897
|
-
/* @__PURE__ */ (0,
|
|
8898
|
-
/* @__PURE__ */ (0,
|
|
10549
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__ringing", role: "alertdialog", "aria-label": "Incoming call", children: [
|
|
10550
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Avatar, { name: invite.callerName, url: invite.callerAvatarUrl, size: 56 }),
|
|
10551
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__ringing-text", children: [
|
|
10552
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: invite.callerName }),
|
|
10553
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: invite.mode === "video" ? "Incoming video call" : "Incoming call" })
|
|
8899
10554
|
] }),
|
|
8900
|
-
/* @__PURE__ */ (0,
|
|
8901
|
-
/* @__PURE__ */ (0,
|
|
8902
|
-
invite.mode === "video" ? /* @__PURE__ */ (0,
|
|
10555
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__ringing-actions", children: [
|
|
10556
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ControlButton, { label: "Decline", danger: true, onClick: () => void calls.decline(invite), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PhoneOffIcon, {}) }),
|
|
10557
|
+
invite.mode === "video" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8903
10558
|
ControlButton,
|
|
8904
10559
|
{
|
|
8905
10560
|
label: "Accept without video",
|
|
8906
10561
|
onClick: () => void calls.accept({ ...invite, mode: "audio" }),
|
|
8907
|
-
children: /* @__PURE__ */ (0,
|
|
10562
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CameraOffIcon, {})
|
|
8908
10563
|
}
|
|
8909
10564
|
) : null,
|
|
8910
|
-
/* @__PURE__ */ (0,
|
|
10565
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ControlButton, { label: "Accept", onClick: () => void calls.accept(invite), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PhoneIcon, {}) })
|
|
8911
10566
|
] })
|
|
8912
10567
|
] });
|
|
8913
10568
|
}
|
|
8914
10569
|
function ScheduleMeeting(props) {
|
|
8915
10570
|
const host = useMeetHost();
|
|
8916
|
-
if (host === null) return /* @__PURE__ */ (0,
|
|
8917
|
-
return /* @__PURE__ */ (0,
|
|
10571
|
+
if (host === null) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InertNotice, { what: "Scheduling a meeting" });
|
|
10572
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ScheduleMeetingBody, { ...props, host });
|
|
8918
10573
|
}
|
|
8919
10574
|
function ScheduleMeetingBody({
|
|
8920
10575
|
appBaseUrl,
|
|
8921
10576
|
onScheduled,
|
|
8922
10577
|
host
|
|
8923
10578
|
}) {
|
|
8924
|
-
const [title, setTitle] = (0,
|
|
8925
|
-
const [when2, setWhen] = (0,
|
|
8926
|
-
const [kind, setKind] = (0,
|
|
8927
|
-
const [busy, setBusy] = (0,
|
|
8928
|
-
const [link, setLink] = (0,
|
|
8929
|
-
const [error, setError] = (0,
|
|
8930
|
-
const disabled = (0,
|
|
8931
|
-
return /* @__PURE__ */ (0,
|
|
10579
|
+
const [title, setTitle] = (0, import_react5.useState)("");
|
|
10580
|
+
const [when2, setWhen] = (0, import_react5.useState)("");
|
|
10581
|
+
const [kind, setKind] = (0, import_react5.useState)("scheduled");
|
|
10582
|
+
const [busy, setBusy] = (0, import_react5.useState)(false);
|
|
10583
|
+
const [link, setLink] = (0, import_react5.useState)(null);
|
|
10584
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
10585
|
+
const disabled = (0, import_react5.useMemo)(() => title.trim().length === 0 || busy, [title, busy]);
|
|
10586
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8932
10587
|
"form",
|
|
8933
10588
|
{
|
|
8934
10589
|
className: "mx-meet__schedule",
|
|
@@ -8953,9 +10608,9 @@ function ScheduleMeetingBody({
|
|
|
8953
10608
|
}).finally(() => setBusy(false));
|
|
8954
10609
|
},
|
|
8955
10610
|
children: [
|
|
8956
|
-
/* @__PURE__ */ (0,
|
|
8957
|
-
/* @__PURE__ */ (0,
|
|
8958
|
-
/* @__PURE__ */ (0,
|
|
10611
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__field", children: [
|
|
10612
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__field-label", children: "Title" }),
|
|
10613
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8959
10614
|
"input",
|
|
8960
10615
|
{
|
|
8961
10616
|
className: "mx-meet__input",
|
|
@@ -8965,9 +10620,9 @@ function ScheduleMeetingBody({
|
|
|
8965
10620
|
}
|
|
8966
10621
|
)
|
|
8967
10622
|
] }),
|
|
8968
|
-
/* @__PURE__ */ (0,
|
|
8969
|
-
/* @__PURE__ */ (0,
|
|
8970
|
-
/* @__PURE__ */ (0,
|
|
10623
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__field", children: [
|
|
10624
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__field-label", children: "When" }),
|
|
10625
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8971
10626
|
"input",
|
|
8972
10627
|
{
|
|
8973
10628
|
className: "mx-meet__input",
|
|
@@ -8977,27 +10632,27 @@ function ScheduleMeetingBody({
|
|
|
8977
10632
|
}
|
|
8978
10633
|
)
|
|
8979
10634
|
] }),
|
|
8980
|
-
/* @__PURE__ */ (0,
|
|
8981
|
-
/* @__PURE__ */ (0,
|
|
8982
|
-
/* @__PURE__ */ (0,
|
|
10635
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__field", children: [
|
|
10636
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__field-label", children: "Repeats" }),
|
|
10637
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8983
10638
|
"select",
|
|
8984
10639
|
{
|
|
8985
10640
|
className: "mx-meet__select",
|
|
8986
10641
|
value: kind,
|
|
8987
10642
|
onChange: (event) => setKind(event.target.value),
|
|
8988
10643
|
children: [
|
|
8989
|
-
/* @__PURE__ */ (0,
|
|
8990
|
-
/* @__PURE__ */ (0,
|
|
10644
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "scheduled", children: "Once" }),
|
|
10645
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "recurring", children: "Recurring \u2014 one link, every time" })
|
|
8991
10646
|
]
|
|
8992
10647
|
}
|
|
8993
10648
|
)
|
|
8994
10649
|
] }),
|
|
8995
|
-
/* @__PURE__ */ (0,
|
|
8996
|
-
link !== null ? /* @__PURE__ */ (0,
|
|
8997
|
-
/* @__PURE__ */ (0,
|
|
8998
|
-
/* @__PURE__ */ (0,
|
|
10650
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "submit", className: "mx-meet__primary", disabled, children: busy ? "Creating\u2026" : "Create meeting" }),
|
|
10651
|
+
link !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__link-out", children: [
|
|
10652
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Anyone with this link can join \u2014 no account needed." }),
|
|
10653
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("code", { children: link })
|
|
8999
10654
|
] }) : null,
|
|
9000
|
-
error !== null ? /* @__PURE__ */ (0,
|
|
10655
|
+
error !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__error", children: error }) : null
|
|
9001
10656
|
]
|
|
9002
10657
|
}
|
|
9003
10658
|
);
|
|
@@ -9006,7 +10661,7 @@ function ReactionOverlay({
|
|
|
9006
10661
|
reactions
|
|
9007
10662
|
}) {
|
|
9008
10663
|
if (reactions.length === 0) return null;
|
|
9009
|
-
return /* @__PURE__ */ (0,
|
|
10664
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet__reactions", "aria-hidden": "true", children: reactions.map((reaction) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__reaction", children: reaction.emoji }, reaction.id)) });
|
|
9010
10665
|
}
|
|
9011
10666
|
function GuestRecordAccessControl({
|
|
9012
10667
|
meeting
|
|
@@ -9018,11 +10673,11 @@ function GuestRecordAccessControl({
|
|
|
9018
10673
|
const isHost = inRoomHost || viewerId !== null && meeting.hostUserId === viewerId;
|
|
9019
10674
|
if (host === null || !isHost) return null;
|
|
9020
10675
|
const resolved = access.setting === "default" && access.effective !== null ? ` Right now that means: ${guestRecordAccessLabel(access.effective.level).toLowerCase()}.` : "";
|
|
9021
|
-
return /* @__PURE__ */ (0,
|
|
9022
|
-
/* @__PURE__ */ (0,
|
|
9023
|
-
/* @__PURE__ */ (0,
|
|
9024
|
-
/* @__PURE__ */ (0,
|
|
9025
|
-
/* @__PURE__ */ (0,
|
|
10676
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "What guests may read", children: [
|
|
10677
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__record-section-title", children: "What guests may read" }),
|
|
10678
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__field", children: [
|
|
10679
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__field-label", children: "People who attended by link, without an account" }),
|
|
10680
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9026
10681
|
"select",
|
|
9027
10682
|
{
|
|
9028
10683
|
className: "mx-meet__select",
|
|
@@ -9033,18 +10688,18 @@ function GuestRecordAccessControl({
|
|
|
9033
10688
|
event.target.value
|
|
9034
10689
|
);
|
|
9035
10690
|
},
|
|
9036
|
-
children: GUEST_RECORD_ACCESS_CHOICES.map((choice) => /* @__PURE__ */ (0,
|
|
10691
|
+
children: GUEST_RECORD_ACCESS_CHOICES.map((choice) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: choice, children: guestRecordAccessLabel(choice) }, choice))
|
|
9037
10692
|
}
|
|
9038
10693
|
)
|
|
9039
10694
|
] }),
|
|
9040
|
-
/* @__PURE__ */ (0,
|
|
10695
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__panel-note", children: [
|
|
9041
10696
|
guestRecordAccessExplanation(access.setting),
|
|
9042
10697
|
resolved
|
|
9043
10698
|
] }),
|
|
9044
|
-
access.saving ? /* @__PURE__ */ (0,
|
|
9045
|
-
access.error !== null ? /* @__PURE__ */ (0,
|
|
9046
|
-
/* @__PURE__ */ (0,
|
|
9047
|
-
/* @__PURE__ */ (0,
|
|
10699
|
+
access.saving ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", role: "status", children: "Saving what guests may read\u2026" }) : null,
|
|
10700
|
+
access.error !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system.ErrorBox, { as: "div", className: "mx-meet__refusal", error: access.error, operation: "Change who can join", origin: "meet/components", children: [
|
|
10701
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-reason", children: access.error.message }),
|
|
10702
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-remedy", children: access.error.remedy })
|
|
9048
10703
|
] }) : null
|
|
9049
10704
|
] });
|
|
9050
10705
|
}
|
|
@@ -9054,9 +10709,9 @@ function MeetingRecordView({
|
|
|
9054
10709
|
}) {
|
|
9055
10710
|
const host = useMeetHost();
|
|
9056
10711
|
if (host === null) {
|
|
9057
|
-
return /* @__PURE__ */ (0,
|
|
10712
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet mx-meet--record", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InertNotice, { what: "This meeting record" }) });
|
|
9058
10713
|
}
|
|
9059
|
-
return /* @__PURE__ */ (0,
|
|
10714
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MeetingRecordBody, { meeting, ...onRejoin !== void 0 ? { onRejoin } : {} });
|
|
9060
10715
|
}
|
|
9061
10716
|
function MeetingRecordBody({
|
|
9062
10717
|
meeting,
|
|
@@ -9064,19 +10719,19 @@ function MeetingRecordBody({
|
|
|
9064
10719
|
}) {
|
|
9065
10720
|
const host = useRequiredMeetHost();
|
|
9066
10721
|
const record = useMeetingRecord(meeting);
|
|
9067
|
-
const [question, setQuestion] = (0,
|
|
9068
|
-
const [tab, setTab] = (0,
|
|
10722
|
+
const [question, setQuestion] = (0, import_react5.useState)("");
|
|
10723
|
+
const [tab, setTab] = (0, import_react5.useState)("summary");
|
|
9069
10724
|
if (record.failure !== null) {
|
|
9070
|
-
return /* @__PURE__ */ (0,
|
|
9071
|
-
/* @__PURE__ */ (0,
|
|
9072
|
-
/* @__PURE__ */ (0,
|
|
9073
|
-
/* @__PURE__ */ (0,
|
|
10725
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet mx-meet--record", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system.ErrorBox, { as: "div", className: "mx-meet__empty", error: record.failure, operation: "Open this meeting record", origin: "meet/components", children: [
|
|
10726
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-title", children: "This meeting record could not be opened" }),
|
|
10727
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-body", children: record.failure.message }),
|
|
10728
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-body", children: record.failure.remedy })
|
|
9074
10729
|
] }) });
|
|
9075
10730
|
}
|
|
9076
10731
|
if (record.loading || record.record === null) {
|
|
9077
|
-
return /* @__PURE__ */ (0,
|
|
9078
|
-
/* @__PURE__ */ (0,
|
|
9079
|
-
/* @__PURE__ */ (0,
|
|
10732
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet mx-meet--record", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__empty", role: "status", children: [
|
|
10733
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-title", children: "Opening the meeting record\u2026" }),
|
|
10734
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-body", children: "Reading the summary, the notes and the transcript this meeting left behind." })
|
|
9080
10735
|
] }) });
|
|
9081
10736
|
}
|
|
9082
10737
|
const bundle = record.record;
|
|
@@ -9095,44 +10750,44 @@ function MeetingRecordBody({
|
|
|
9095
10750
|
);
|
|
9096
10751
|
const entirelyRestricted = everyRecordPartRefused && bundle.attendees.length === 0 && bundle.liveNotes.length === 0 && bundle.transcript.length === 0 && bundle.recording === null && bundle.summary === null && bundle.decisions.length === 0 && bundle.actionItems.length === 0;
|
|
9097
10752
|
if (entirelyRestricted) {
|
|
9098
|
-
return /* @__PURE__ */ (0,
|
|
9099
|
-
/* @__PURE__ */ (0,
|
|
9100
|
-
/* @__PURE__ */ (0,
|
|
9101
|
-
/* @__PURE__ */ (0,
|
|
9102
|
-
/* @__PURE__ */ (0,
|
|
9103
|
-
onRejoin !== void 0 ? /* @__PURE__ */ (0,
|
|
10753
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet mx-meet--record", children: [
|
|
10754
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("header", { className: "mx-meet__record-head", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__record-head-inner", children: [
|
|
10755
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-eyebrow", children: "Meeting record" }),
|
|
10756
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h1", { className: "mx-meet__record-title", children: meeting.title }),
|
|
10757
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-when", children: meetingWhen(meeting) }),
|
|
10758
|
+
onRejoin !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mx-meet__link", onClick: onRejoin, children: "Open this link again" }) : null
|
|
9104
10759
|
] }) }),
|
|
9105
|
-
/* @__PURE__ */ (0,
|
|
9106
|
-
/* @__PURE__ */ (0,
|
|
9107
|
-
/* @__PURE__ */ (0,
|
|
9108
|
-
/* @__PURE__ */ (0,
|
|
10760
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet__record-body", children: restrictionNotices.map((notice2) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__record-access", role: "status", children: [
|
|
10761
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-access-title", children: "About this record" }),
|
|
10762
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-access-message", children: notice2.message }),
|
|
10763
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-access-remedy", children: notice2.remedy })
|
|
9109
10764
|
] }, notice2.parts.join("-"))) })
|
|
9110
10765
|
] });
|
|
9111
10766
|
}
|
|
9112
|
-
return /* @__PURE__ */ (0,
|
|
9113
|
-
/* @__PURE__ */ (0,
|
|
9114
|
-
/* @__PURE__ */ (0,
|
|
9115
|
-
/* @__PURE__ */ (0,
|
|
9116
|
-
/* @__PURE__ */ (0,
|
|
9117
|
-
onRejoin !== void 0 ? /* @__PURE__ */ (0,
|
|
10767
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet mx-meet--record", children: [
|
|
10768
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("header", { className: "mx-meet__record-head", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__record-head-inner", children: [
|
|
10769
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-eyebrow", children: "Meeting record" }),
|
|
10770
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h1", { className: "mx-meet__record-title", children: meeting.title }),
|
|
10771
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-when", children: meetingWhen(meeting) }),
|
|
10772
|
+
onRejoin !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mx-meet__link", onClick: onRejoin, children: "Open this link again" }) : null
|
|
9118
10773
|
] }) }),
|
|
9119
|
-
/* @__PURE__ */ (0,
|
|
9120
|
-
restrictionNotices.map((notice2) => /* @__PURE__ */ (0,
|
|
9121
|
-
/* @__PURE__ */ (0,
|
|
9122
|
-
/* @__PURE__ */ (0,
|
|
9123
|
-
/* @__PURE__ */ (0,
|
|
10774
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__record-body", children: [
|
|
10775
|
+
restrictionNotices.map((notice2) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__record-access", role: "status", children: [
|
|
10776
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-access-title", children: "About this record" }),
|
|
10777
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-access-message", children: notice2.message }),
|
|
10778
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-access-remedy", children: notice2.remedy })
|
|
9124
10779
|
] }, notice2.parts.join("-"))),
|
|
9125
10780
|
attended.length === 0 ? (
|
|
9126
10781
|
/* NOT SILENCE. A refused attendance read used to remove the whole
|
|
9127
10782
|
section, so the reader could not tell "nobody" from "not shown". */
|
|
9128
|
-
/* @__PURE__ */ (0,
|
|
9129
|
-
/* @__PURE__ */ (0,
|
|
9130
|
-
/* @__PURE__ */ (0,
|
|
10783
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Who attended", children: [
|
|
10784
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__record-section-title", children: "Who attended" }),
|
|
10785
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: absenceSentence(bundle, "attendance", "Nobody is recorded as having attended.") })
|
|
9131
10786
|
] })
|
|
9132
|
-
) : /* @__PURE__ */ (0,
|
|
9133
|
-
/* @__PURE__ */ (0,
|
|
9134
|
-
/* @__PURE__ */ (0,
|
|
9135
|
-
/* @__PURE__ */ (0,
|
|
10787
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Who attended", children: [
|
|
10788
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__record-section-title", children: "Who attended" }),
|
|
10789
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: "mx-meet__record-attendees", children: attended.map((person) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { className: "mx-meet__record-attendee", children: [
|
|
10790
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9136
10791
|
Avatar,
|
|
9137
10792
|
{
|
|
9138
10793
|
name: displayNameFor(bundle.names, person.identity, person.displayName),
|
|
@@ -9140,26 +10795,26 @@ function MeetingRecordBody({
|
|
|
9140
10795
|
size: 28
|
|
9141
10796
|
}
|
|
9142
10797
|
),
|
|
9143
|
-
/* @__PURE__ */ (0,
|
|
10798
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__person-name", children: [
|
|
9144
10799
|
displayNameFor(bundle.names, person.identity, person.displayName),
|
|
9145
|
-
person.role === "host" ? /* @__PURE__ */ (0,
|
|
9146
|
-
person.role === "guest" ? /* @__PURE__ */ (0,
|
|
9147
|
-
person.isAgent ? /* @__PURE__ */ (0,
|
|
10800
|
+
person.role === "host" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Host" }) : null,
|
|
10801
|
+
person.role === "guest" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Guest" }) : null,
|
|
10802
|
+
person.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Meeting assistant" }) : null
|
|
9148
10803
|
] })
|
|
9149
10804
|
] }, person.id)) })
|
|
9150
10805
|
] }),
|
|
9151
|
-
bundle.recording !== null ? /* @__PURE__ */ (0,
|
|
9152
|
-
/* @__PURE__ */ (0,
|
|
9153
|
-
fileId !== null ? /* @__PURE__ */ (0,
|
|
9154
|
-
/* @__PURE__ */ (0,
|
|
9155
|
-
notice !== null ? /* @__PURE__ */ (0,
|
|
9156
|
-
] }) : /* @__PURE__ */ (0,
|
|
9157
|
-
] }) : wasRefused(bundle, "recording") ? /* @__PURE__ */ (0,
|
|
9158
|
-
/* @__PURE__ */ (0,
|
|
9159
|
-
/* @__PURE__ */ (0,
|
|
10806
|
+
bundle.recording !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__record-section mx-meet__recording-card", "aria-label": "Recording", children: [
|
|
10807
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__record-section-title", children: "Recording" }),
|
|
10808
|
+
fileId !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
10809
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RecordingPlayer, { fileId }),
|
|
10810
|
+
notice !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: notice }) : null
|
|
10811
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: notice ?? "This recording has no file." })
|
|
10812
|
+
] }) : wasRefused(bundle, "recording") ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Recording", children: [
|
|
10813
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__record-section-title", children: "Recording" }),
|
|
10814
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: REFUSED_ABSENCE })
|
|
9160
10815
|
] }) : null,
|
|
9161
|
-
/* @__PURE__ */ (0,
|
|
9162
|
-
/* @__PURE__ */ (0,
|
|
10816
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("nav", { className: "mx-meet__record-tabs", "aria-label": "Meeting record sections", children: [
|
|
10817
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9163
10818
|
"button",
|
|
9164
10819
|
{
|
|
9165
10820
|
type: "button",
|
|
@@ -9169,7 +10824,7 @@ function MeetingRecordBody({
|
|
|
9169
10824
|
children: "Summary & decisions"
|
|
9170
10825
|
}
|
|
9171
10826
|
),
|
|
9172
|
-
/* @__PURE__ */ (0,
|
|
10827
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9173
10828
|
"button",
|
|
9174
10829
|
{
|
|
9175
10830
|
type: "button",
|
|
@@ -9179,7 +10834,7 @@ function MeetingRecordBody({
|
|
|
9179
10834
|
children: "Notes as it happened"
|
|
9180
10835
|
}
|
|
9181
10836
|
),
|
|
9182
|
-
/* @__PURE__ */ (0,
|
|
10837
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9183
10838
|
"button",
|
|
9184
10839
|
{
|
|
9185
10840
|
type: "button",
|
|
@@ -9190,15 +10845,15 @@ function MeetingRecordBody({
|
|
|
9190
10845
|
}
|
|
9191
10846
|
)
|
|
9192
10847
|
] }),
|
|
9193
|
-
tab === "summary" ? /* @__PURE__ */ (0,
|
|
9194
|
-
/* @__PURE__ */ (0,
|
|
9195
|
-
/* @__PURE__ */ (0,
|
|
9196
|
-
wrapUp.state === "written" ? /* @__PURE__ */ (0,
|
|
9197
|
-
/* @__PURE__ */ (0,
|
|
9198
|
-
/* @__PURE__ */ (0,
|
|
9199
|
-
] }) : /* @__PURE__ */ (0,
|
|
10848
|
+
tab === "summary" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
10849
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Summary", children: [
|
|
10850
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__record-section-title", children: "Summary" }),
|
|
10851
|
+
wrapUp.state === "written" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-summary", children: bundle.summary?.text }) : wrapUp.state === "in-progress" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__panel-note", role: "status", children: [
|
|
10852
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { children: wrapUp.message }),
|
|
10853
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mx-meet__link", onClick: record.reload, children: "Check again" })
|
|
10854
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", role: wrapUp.state === "failed" ? "alert" : void 0, children: wrapUp.message })
|
|
9200
10855
|
] }),
|
|
9201
|
-
/* @__PURE__ */ (0,
|
|
10856
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9202
10857
|
NoteList,
|
|
9203
10858
|
{
|
|
9204
10859
|
title: "Decisions",
|
|
@@ -9210,7 +10865,7 @@ function MeetingRecordBody({
|
|
|
9210
10865
|
)
|
|
9211
10866
|
}
|
|
9212
10867
|
),
|
|
9213
|
-
/* @__PURE__ */ (0,
|
|
10868
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9214
10869
|
NoteList,
|
|
9215
10870
|
{
|
|
9216
10871
|
title: "Action items",
|
|
@@ -9223,42 +10878,42 @@ function MeetingRecordBody({
|
|
|
9223
10878
|
}
|
|
9224
10879
|
)
|
|
9225
10880
|
] }) : null,
|
|
9226
|
-
tab === "notes" ? /* @__PURE__ */ (0,
|
|
9227
|
-
/* @__PURE__ */ (0,
|
|
9228
|
-
bundle.liveNotes.length === 0 ? /* @__PURE__ */ (0,
|
|
10881
|
+
tab === "notes" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Notes as it happened", children: [
|
|
10882
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__record-section-title", children: "Notes as it happened" }),
|
|
10883
|
+
bundle.liveNotes.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: absenceSentence(
|
|
9229
10884
|
bundle,
|
|
9230
10885
|
"notes",
|
|
9231
10886
|
"No live notes are available for this meeting."
|
|
9232
|
-
) }) : /* @__PURE__ */ (0,
|
|
9233
|
-
note.window !== null ? /* @__PURE__ */ (0,
|
|
10887
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: "mx-meet__notes", children: bundle.liveNotes.map((note) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { className: "mx-meet__note", children: [
|
|
10888
|
+
note.window !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__badge", children: [
|
|
9234
10889
|
"Window ",
|
|
9235
10890
|
note.window
|
|
9236
10891
|
] }) : null,
|
|
9237
10892
|
note.text
|
|
9238
10893
|
] }, note.id)) })
|
|
9239
10894
|
] }) : null,
|
|
9240
|
-
tab === "transcript" ? /* @__PURE__ */ (0,
|
|
9241
|
-
/* @__PURE__ */ (0,
|
|
10895
|
+
tab === "transcript" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Transcript", children: [
|
|
10896
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("h2", { className: "mx-meet__record-section-title", children: [
|
|
9242
10897
|
"Transcript",
|
|
9243
|
-
/* @__PURE__ */ (0,
|
|
10898
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__record-count", children: bundle.transcript.length === 1 ? "1 line" : `${bundle.transcript.length} lines` })
|
|
9244
10899
|
] }),
|
|
9245
|
-
blocks.length === 0 ? /* @__PURE__ */ (0,
|
|
10900
|
+
blocks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: absenceSentence(
|
|
9246
10901
|
bundle,
|
|
9247
10902
|
"transcript",
|
|
9248
10903
|
"No transcript is available for this meeting."
|
|
9249
|
-
) }) : /* @__PURE__ */ (0,
|
|
9250
|
-
/* @__PURE__ */ (0,
|
|
10904
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ol", { className: "mx-meet__record-transcript", children: blocks.map((block) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { className: "mx-meet__record-block", children: [
|
|
10905
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__record-speaker", children: [
|
|
9251
10906
|
block.speaker,
|
|
9252
|
-
/* @__PURE__ */ (0,
|
|
10907
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("time", { className: "mx-meet__record-time", dateTime: block.startedAt, children: clockOf(block.startedAt) })
|
|
9253
10908
|
] }),
|
|
9254
|
-
block.lines.map((line) => /* @__PURE__ */ (0,
|
|
10909
|
+
block.lines.map((line) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-line", children: line.text }, line.id))
|
|
9255
10910
|
] }, block.id)) })
|
|
9256
10911
|
] }) : null,
|
|
9257
|
-
/* @__PURE__ */ (0,
|
|
9258
|
-
/* @__PURE__ */ (0,
|
|
9259
|
-
/* @__PURE__ */ (0,
|
|
9260
|
-
guestFinishedMeeting ? /* @__PURE__ */ (0,
|
|
9261
|
-
/* @__PURE__ */ (0,
|
|
10912
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(GuestRecordAccessControl, { meeting }),
|
|
10913
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Ask about this meeting", children: [
|
|
10914
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__record-section-title", children: "Ask about this meeting" }),
|
|
10915
|
+
guestFinishedMeeting ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: "Sign in to ask the assistant about a meeting after it ends." }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
10916
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
9262
10917
|
"form",
|
|
9263
10918
|
{
|
|
9264
10919
|
className: "mx-meet__composer",
|
|
@@ -9269,7 +10924,7 @@ function MeetingRecordBody({
|
|
|
9269
10924
|
void record.ask(trimmed);
|
|
9270
10925
|
},
|
|
9271
10926
|
children: [
|
|
9272
|
-
/* @__PURE__ */ (0,
|
|
10927
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9273
10928
|
"input",
|
|
9274
10929
|
{
|
|
9275
10930
|
className: "mx-meet__input",
|
|
@@ -9279,7 +10934,7 @@ function MeetingRecordBody({
|
|
|
9279
10934
|
"aria-label": "Ask about this meeting"
|
|
9280
10935
|
}
|
|
9281
10936
|
),
|
|
9282
|
-
/* @__PURE__ */ (0,
|
|
10937
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9283
10938
|
"button",
|
|
9284
10939
|
{
|
|
9285
10940
|
type: "submit",
|
|
@@ -9291,8 +10946,8 @@ function MeetingRecordBody({
|
|
|
9291
10946
|
]
|
|
9292
10947
|
}
|
|
9293
10948
|
),
|
|
9294
|
-
record.answer !== null ? /* @__PURE__ */ (0,
|
|
9295
|
-
record.coverage !== null ? /* @__PURE__ */ (0,
|
|
10949
|
+
record.answer !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__answer", children: record.answer }) : null,
|
|
10950
|
+
record.coverage !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__coverage", children: [
|
|
9296
10951
|
"Answered from ",
|
|
9297
10952
|
record.coverage.segmentsUsed,
|
|
9298
10953
|
" of ",
|
|
@@ -9303,9 +10958,9 @@ function MeetingRecordBody({
|
|
|
9303
10958
|
record.coverage.truncated ? " (the oldest were left out)" : "",
|
|
9304
10959
|
"."
|
|
9305
10960
|
] }) : null,
|
|
9306
|
-
record.askError !== null ? /* @__PURE__ */ (0,
|
|
9307
|
-
/* @__PURE__ */ (0,
|
|
9308
|
-
/* @__PURE__ */ (0,
|
|
10961
|
+
record.askError !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system.ErrorBox, { as: "div", className: "mx-meet__refusal", error: record.askError, operation: "Ask about this meeting", origin: "meet/components", children: [
|
|
10962
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-reason", children: record.askError.message }),
|
|
10963
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-remedy", children: record.askError.remedy })
|
|
9309
10964
|
] }) : null
|
|
9310
10965
|
] })
|
|
9311
10966
|
] })
|
|
@@ -9316,21 +10971,21 @@ var STREAM_REFUSED = "Streaming playback did not start, so this recording was do
|
|
|
9316
10971
|
var PLAYBACK_RETRY_REMEDY = "Reload the page and try again. If it still will not play, ask a meeting host to check the recording.";
|
|
9317
10972
|
function RecordingPlayer(props) {
|
|
9318
10973
|
const host = useMeetHost();
|
|
9319
|
-
if (host === null) return /* @__PURE__ */ (0,
|
|
9320
|
-
return /* @__PURE__ */ (0,
|
|
10974
|
+
if (host === null) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InertNotice, { what: "This recording" });
|
|
10975
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RecordingPlayerBody, { ...props, host });
|
|
9321
10976
|
}
|
|
9322
10977
|
function RecordingPlayerBody({ fileId, host }) {
|
|
9323
|
-
const [media, setMedia] = (0,
|
|
9324
|
-
const [loading, setLoading] = (0,
|
|
9325
|
-
const [error, setError] = (0,
|
|
9326
|
-
(0,
|
|
10978
|
+
const [media, setMedia] = (0, import_react5.useState)(null);
|
|
10979
|
+
const [loading, setLoading] = (0, import_react5.useState)(false);
|
|
10980
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
10981
|
+
(0, import_react5.useEffect)(() => {
|
|
9327
10982
|
if (media === null || media.kind !== "bytes") return void 0;
|
|
9328
10983
|
const url = media.url;
|
|
9329
10984
|
return () => URL.revokeObjectURL(url);
|
|
9330
10985
|
}, [media]);
|
|
9331
10986
|
if (media !== null) {
|
|
9332
|
-
return /* @__PURE__ */ (0,
|
|
9333
|
-
/* @__PURE__ */ (0,
|
|
10987
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__record-section", children: [
|
|
10988
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9334
10989
|
"video",
|
|
9335
10990
|
{
|
|
9336
10991
|
className: "mx-meet__record-player",
|
|
@@ -9372,15 +11027,15 @@ function RecordingPlayerBody({ fileId, host }) {
|
|
|
9372
11027
|
}
|
|
9373
11028
|
}
|
|
9374
11029
|
),
|
|
9375
|
-
media.fallbackReason !== null ? /* @__PURE__ */ (0,
|
|
11030
|
+
media.fallbackReason !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: media.fallbackReason }) : null
|
|
9376
11031
|
] });
|
|
9377
11032
|
}
|
|
9378
|
-
return /* @__PURE__ */ (0,
|
|
9379
|
-
error !== null ? /* @__PURE__ */ (0,
|
|
9380
|
-
/* @__PURE__ */ (0,
|
|
9381
|
-
/* @__PURE__ */ (0,
|
|
11033
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__record-section", children: [
|
|
11034
|
+
error !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system.ErrorBox, { as: "div", className: "mx-meet__refusal", error, operation: "Complete this meeting action", origin: "meet/components", children: [
|
|
11035
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-reason", children: error.message }),
|
|
11036
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-remedy", children: error.remedy })
|
|
9382
11037
|
] }) : null,
|
|
9383
|
-
/* @__PURE__ */ (0,
|
|
11038
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9384
11039
|
"button",
|
|
9385
11040
|
{
|
|
9386
11041
|
type: "button",
|
|
@@ -9416,35 +11071,35 @@ function clockOf(iso) {
|
|
|
9416
11071
|
function MeetingList({ baseUrl }) {
|
|
9417
11072
|
const host = useMeetHost();
|
|
9418
11073
|
const list = useMeetings();
|
|
9419
|
-
if (host === null) return /* @__PURE__ */ (0,
|
|
11074
|
+
if (host === null) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InertNotice, { what: "Your meetings" });
|
|
9420
11075
|
if (list.failure !== null) {
|
|
9421
|
-
return /* @__PURE__ */ (0,
|
|
9422
|
-
/* @__PURE__ */ (0,
|
|
9423
|
-
/* @__PURE__ */ (0,
|
|
9424
|
-
/* @__PURE__ */ (0,
|
|
11076
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system.ErrorBox, { as: "div", className: "mx-meet__empty", error: list.failure, operation: "List your meetings", origin: "meet/components", children: [
|
|
11077
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-title", children: "Your meetings could not be listed" }),
|
|
11078
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-body", children: list.failure.message }),
|
|
11079
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-body", children: list.failure.remedy })
|
|
9425
11080
|
] });
|
|
9426
11081
|
}
|
|
9427
11082
|
if (list.loading) {
|
|
9428
|
-
return /* @__PURE__ */ (0,
|
|
11083
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet__empty", role: "status", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-title", children: "Loading your meetings\u2026" }) });
|
|
9429
11084
|
}
|
|
9430
11085
|
if (list.meetings.length === 0) {
|
|
9431
|
-
return /* @__PURE__ */ (0,
|
|
9432
|
-
/* @__PURE__ */ (0,
|
|
9433
|
-
/* @__PURE__ */ (0,
|
|
11086
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__empty", role: "status", children: [
|
|
11087
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-title", children: "No meetings yet" }),
|
|
11088
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-body", children: "Create one above. Its link works before, during and after the meeting \u2014 afterwards it opens the record." })
|
|
9434
11089
|
] });
|
|
9435
11090
|
}
|
|
9436
11091
|
const origin = baseUrl ?? (typeof window === "undefined" ? "" : window.location.origin);
|
|
9437
|
-
return /* @__PURE__ */ (0,
|
|
11092
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: "mx-meet-list", children: list.meetings.map((meeting) => {
|
|
9438
11093
|
const ended = meeting.endedAt !== null;
|
|
9439
|
-
return /* @__PURE__ */ (0,
|
|
9440
|
-
/* @__PURE__ */ (0,
|
|
9441
|
-
/* @__PURE__ */ (0,
|
|
11094
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { className: "mx-meet-list__row", children: [
|
|
11095
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet-list__main", children: [
|
|
11096
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet-list__title", children: [
|
|
9442
11097
|
meeting.title,
|
|
9443
|
-
ended ? /* @__PURE__ */ (0,
|
|
11098
|
+
ended ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Ended" }) : null
|
|
9444
11099
|
] }),
|
|
9445
|
-
/* @__PURE__ */ (0,
|
|
11100
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet-list__when", children: meetingWhen(meeting) })
|
|
9446
11101
|
] }),
|
|
9447
|
-
/* @__PURE__ */ (0,
|
|
11102
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("a", { className: "mx-meet-list__action", href: meetingLink(origin, meeting.slug), children: ended ? "Open the record" : "Join" })
|
|
9448
11103
|
] }, meeting.id);
|
|
9449
11104
|
}) });
|
|
9450
11105
|
}
|