@ai-matrx/meet 0.7.10 → 0.7.11
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 +31 -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 +2340 -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 +2341 -699
- package/dist/react.js.map +1 -1
- package/dist/styles.css +293 -0
- package/dist/tokens.css +2 -0
- package/package.json +3 -3
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,19 @@ 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
|
-
return /* @__PURE__ */ (0,
|
|
7657
|
-
/* @__PURE__ */ (0,
|
|
7658
|
-
/* @__PURE__ */ (0,
|
|
7659
|
-
/* @__PURE__ */ (0,
|
|
9289
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("aside", { className: "mx-meet__panel", "aria-label": title, children: [
|
|
9290
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { className: "mx-meet__panel-head", children: [
|
|
9291
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__panel-title", children: title }),
|
|
9292
|
+
/* @__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
9293
|
] }),
|
|
7661
|
-
/* @__PURE__ */ (0,
|
|
9294
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet__panel-body", children })
|
|
7662
9295
|
] });
|
|
7663
9296
|
}
|
|
7664
9297
|
function ChatPanel({
|
|
@@ -7668,17 +9301,17 @@ function ChatPanel({
|
|
|
7668
9301
|
}) {
|
|
7669
9302
|
const snapshot = useMeetSnapshot();
|
|
7670
9303
|
const room = useRoom();
|
|
7671
|
-
const [draft, setDraft] = (0,
|
|
7672
|
-
const [recipient, setRecipient] = (0,
|
|
7673
|
-
const listRef = (0,
|
|
9304
|
+
const [draft, setDraft] = (0, import_react5.useState)("");
|
|
9305
|
+
const [recipient, setRecipient] = (0, import_react5.useState)(to);
|
|
9306
|
+
const listRef = (0, import_react5.useRef)(null);
|
|
7674
9307
|
const messages = snapshot?.chat ?? [];
|
|
7675
9308
|
const local = snapshot?.localIdentity ?? null;
|
|
7676
9309
|
const people = (snapshot?.participants ?? []).filter(
|
|
7677
9310
|
(participant) => !participant.isLocal && !participant.isAgent
|
|
7678
9311
|
);
|
|
7679
9312
|
const recipientName = recipient === null ? null : people.find((p) => p.identity === recipient)?.displayName ?? null;
|
|
7680
|
-
(0,
|
|
7681
|
-
(0,
|
|
9313
|
+
(0, import_react5.useEffect)(() => setRecipient(to), [to]);
|
|
9314
|
+
(0, import_react5.useEffect)(() => {
|
|
7682
9315
|
const list = listRef.current;
|
|
7683
9316
|
if (list !== null) list.scrollTop = list.scrollHeight;
|
|
7684
9317
|
}, [messages.length]);
|
|
@@ -7686,13 +9319,13 @@ function ChatPanel({
|
|
|
7686
9319
|
setRecipient(next);
|
|
7687
9320
|
onTo?.(next);
|
|
7688
9321
|
};
|
|
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,
|
|
9322
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(PanelShell, { title: "Chat", onClose, children: [
|
|
9323
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("ul", { className: "mx-meet__chat", ref: listRef, children: [
|
|
9324
|
+
snapshot?.chatHistoryError != null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("li", { className: "mx-meet__panel-note", children: snapshot.chatHistoryError }) : null,
|
|
9325
|
+
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,
|
|
9326
|
+
messages.map((message) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChatLine, { message, local, people }, message.id))
|
|
7694
9327
|
] }),
|
|
7695
|
-
/* @__PURE__ */ (0,
|
|
9328
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7696
9329
|
"form",
|
|
7697
9330
|
{
|
|
7698
9331
|
className: "mx-meet__composer mx-meet__composer--chat",
|
|
@@ -7705,7 +9338,7 @@ function ChatPanel({
|
|
|
7705
9338
|
else void room.sendPrivateChat(recipient, text3);
|
|
7706
9339
|
},
|
|
7707
9340
|
children: [
|
|
7708
|
-
people.length > 0 ? /* @__PURE__ */ (0,
|
|
9341
|
+
people.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7709
9342
|
"select",
|
|
7710
9343
|
{
|
|
7711
9344
|
className: "mx-meet__select mx-meet__select--compact",
|
|
@@ -7713,16 +9346,16 @@ function ChatPanel({
|
|
|
7713
9346
|
value: recipient ?? "",
|
|
7714
9347
|
onChange: (event) => choose(event.target.value === "" ? null : event.target.value),
|
|
7715
9348
|
children: [
|
|
7716
|
-
/* @__PURE__ */ (0,
|
|
7717
|
-
people.map((participant) => /* @__PURE__ */ (0,
|
|
9349
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "", children: "Everyone" }),
|
|
9350
|
+
people.map((participant) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("option", { value: participant.identity, children: [
|
|
7718
9351
|
participant.displayName,
|
|
7719
9352
|
" (private)"
|
|
7720
9353
|
] }, participant.identity))
|
|
7721
9354
|
]
|
|
7722
9355
|
}
|
|
7723
9356
|
) : null,
|
|
7724
|
-
/* @__PURE__ */ (0,
|
|
7725
|
-
/* @__PURE__ */ (0,
|
|
9357
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__composer-row", children: [
|
|
9358
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7726
9359
|
"input",
|
|
7727
9360
|
{
|
|
7728
9361
|
className: "mx-meet__input",
|
|
@@ -7733,9 +9366,9 @@ function ChatPanel({
|
|
|
7733
9366
|
maxLength: 4e3
|
|
7734
9367
|
}
|
|
7735
9368
|
),
|
|
7736
|
-
/* @__PURE__ */ (0,
|
|
9369
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "submit", className: "mx-meet__send", disabled: draft.trim().length === 0, children: "Send" })
|
|
7737
9370
|
] }),
|
|
7738
|
-
recipientName !== null ? /* @__PURE__ */ (0,
|
|
9371
|
+
recipientName !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__panel-note", children: [
|
|
7739
9372
|
"Only ",
|
|
7740
9373
|
recipientName,
|
|
7741
9374
|
" sees this. Private messages are not saved."
|
|
@@ -7753,7 +9386,7 @@ function ChatLine({
|
|
|
7753
9386
|
const mine = message.identity === local;
|
|
7754
9387
|
const privateTo = message.to ?? null;
|
|
7755
9388
|
const counterpart = privateTo === null ? null : mine ? people.find((p) => p.identity === privateTo)?.displayName ?? "them" : "you";
|
|
7756
|
-
return /* @__PURE__ */ (0,
|
|
9389
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7757
9390
|
"li",
|
|
7758
9391
|
{
|
|
7759
9392
|
className: [
|
|
@@ -7762,17 +9395,17 @@ function ChatLine({
|
|
|
7762
9395
|
message.failed !== void 0 ? "mx-meet__chat-line--failed" : ""
|
|
7763
9396
|
].filter(Boolean).join(" "),
|
|
7764
9397
|
children: [
|
|
7765
|
-
/* @__PURE__ */ (0,
|
|
7766
|
-
/* @__PURE__ */ (0,
|
|
7767
|
-
counterpart !== null ? /* @__PURE__ */ (0,
|
|
9398
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__chat-meta", children: [
|
|
9399
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: mine ? "You" : message.displayName }),
|
|
9400
|
+
counterpart !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__chat-private", children: [
|
|
7768
9401
|
"to ",
|
|
7769
9402
|
counterpart,
|
|
7770
9403
|
" \xB7 private"
|
|
7771
9404
|
] }) : null,
|
|
7772
|
-
/* @__PURE__ */ (0,
|
|
9405
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("time", { dateTime: message.at, children: clockOf(message.at) })
|
|
7773
9406
|
] }),
|
|
7774
|
-
/* @__PURE__ */ (0,
|
|
7775
|
-
message.failed !== void 0 ? /* @__PURE__ */ (0,
|
|
9407
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__chat-text", children: message.text }),
|
|
9408
|
+
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
9409
|
]
|
|
7777
9410
|
}
|
|
7778
9411
|
);
|
|
@@ -7784,22 +9417,22 @@ function PeoplePanel({
|
|
|
7784
9417
|
const snapshot = useMeetSnapshot();
|
|
7785
9418
|
const controls = useHostControls();
|
|
7786
9419
|
const queue = useHandQueue();
|
|
7787
|
-
const [query, setQuery] = (0,
|
|
7788
|
-
const [menuFor, setMenuFor] = (0,
|
|
9420
|
+
const [query, setQuery] = (0, import_react5.useState)("");
|
|
9421
|
+
const [menuFor, setMenuFor] = (0, import_react5.useState)(null);
|
|
7789
9422
|
const myRole = useRole();
|
|
7790
9423
|
const local = snapshot?.localIdentity ?? null;
|
|
7791
9424
|
const everyone = snapshot?.participants ?? [];
|
|
7792
9425
|
const needle = query.trim().toLowerCase();
|
|
7793
9426
|
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,
|
|
9427
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(PanelShell, { title: `People (${everyone.length})`, onClose, children: [
|
|
9428
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LobbyPanel, {}),
|
|
9429
|
+
queue.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__section", "aria-label": "Raised hands", children: [
|
|
9430
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { className: "mx-meet__section-head", children: [
|
|
9431
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("h3", { className: "mx-meet__section-title", children: [
|
|
7799
9432
|
"Raised hands \xB7 ",
|
|
7800
9433
|
queue.length
|
|
7801
9434
|
] }),
|
|
7802
|
-
controls.isHost ? /* @__PURE__ */ (0,
|
|
9435
|
+
controls.isHost ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7803
9436
|
"button",
|
|
7804
9437
|
{
|
|
7805
9438
|
type: "button",
|
|
@@ -7809,13 +9442,13 @@ function PeoplePanel({
|
|
|
7809
9442
|
}
|
|
7810
9443
|
) : null
|
|
7811
9444
|
] }),
|
|
7812
|
-
/* @__PURE__ */ (0,
|
|
7813
|
-
/* @__PURE__ */ (0,
|
|
7814
|
-
/* @__PURE__ */ (0,
|
|
9445
|
+
/* @__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: [
|
|
9446
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Avatar, { name: participant.displayName, url: participant.avatarUrl, size: 28 }),
|
|
9447
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__person-name", children: [
|
|
7815
9448
|
participant.displayName,
|
|
7816
|
-
participant.identity === local ? /* @__PURE__ */ (0,
|
|
9449
|
+
participant.identity === local ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__you", children: " (you)" }) : null
|
|
7817
9450
|
] }),
|
|
7818
|
-
controls.isHost || participant.identity === local ? /* @__PURE__ */ (0,
|
|
9451
|
+
controls.isHost || participant.identity === local ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7819
9452
|
"button",
|
|
7820
9453
|
{
|
|
7821
9454
|
type: "button",
|
|
@@ -7826,27 +9459,27 @@ function PeoplePanel({
|
|
|
7826
9459
|
) : null
|
|
7827
9460
|
] }, participant.identity)) })
|
|
7828
9461
|
] }) : null,
|
|
7829
|
-
controls.isHost && everyone.length > 1 ? /* @__PURE__ */ (0,
|
|
7830
|
-
/* @__PURE__ */ (0,
|
|
7831
|
-
/* @__PURE__ */ (0,
|
|
9462
|
+
controls.isHost && everyone.length > 1 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__bulk", children: [
|
|
9463
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("button", { type: "button", className: "mx-meet__chip", onClick: () => void controls.run({ action: "mute_all" }), children: [
|
|
9464
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MicOffIcon, { width: 14, height: 14 }),
|
|
7832
9465
|
" Mute all"
|
|
7833
9466
|
] }),
|
|
7834
|
-
/* @__PURE__ */ (0,
|
|
9467
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7835
9468
|
"button",
|
|
7836
9469
|
{
|
|
7837
9470
|
type: "button",
|
|
7838
9471
|
className: "mx-meet__chip",
|
|
7839
9472
|
onClick: () => void controls.run({ action: "ask_all_unmute" }),
|
|
7840
9473
|
children: [
|
|
7841
|
-
/* @__PURE__ */ (0,
|
|
9474
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MicIcon, { width: 14, height: 14 }),
|
|
7842
9475
|
" Ask all to unmute"
|
|
7843
9476
|
]
|
|
7844
9477
|
}
|
|
7845
9478
|
)
|
|
7846
9479
|
] }) : null,
|
|
7847
|
-
everyone.length > 4 ? /* @__PURE__ */ (0,
|
|
7848
|
-
/* @__PURE__ */ (0,
|
|
7849
|
-
/* @__PURE__ */ (0,
|
|
9480
|
+
everyone.length > 4 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__search", children: [
|
|
9481
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SearchIcon, { width: 16, height: 16 }),
|
|
9482
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7850
9483
|
"input",
|
|
7851
9484
|
{
|
|
7852
9485
|
className: "mx-meet__input mx-meet__input--bare",
|
|
@@ -7857,31 +9490,31 @@ function PeoplePanel({
|
|
|
7857
9490
|
}
|
|
7858
9491
|
)
|
|
7859
9492
|
] }) : null,
|
|
7860
|
-
controls.notice !== null ? /* @__PURE__ */ (0,
|
|
7861
|
-
/* @__PURE__ */ (0,
|
|
7862
|
-
shown.map((participant) => /* @__PURE__ */ (0,
|
|
7863
|
-
/* @__PURE__ */ (0,
|
|
7864
|
-
/* @__PURE__ */ (0,
|
|
9493
|
+
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,
|
|
9494
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("ul", { className: "mx-meet__people", children: [
|
|
9495
|
+
shown.map((participant) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { className: "mx-meet__person", children: [
|
|
9496
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Avatar, { name: participant.displayName, url: participant.avatarUrl, size: 32 }),
|
|
9497
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__person-name", children: [
|
|
7865
9498
|
participant.displayName,
|
|
7866
|
-
participant.identity === local ? /* @__PURE__ */ (0,
|
|
7867
|
-
/* @__PURE__ */ (0,
|
|
7868
|
-
isNoteTaker(participant) ? /* @__PURE__ */ (0,
|
|
7869
|
-
snapshot?.spotlight === participant.identity ? /* @__PURE__ */ (0,
|
|
9499
|
+
participant.identity === local ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__you", children: " (you)" }) : null,
|
|
9500
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RoleBadge, { role: participant.identity === local ? myRole : participant.role }),
|
|
9501
|
+
isNoteTaker(participant) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Meeting assistant" }) : null,
|
|
9502
|
+
snapshot?.spotlight === participant.identity ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Spotlight" }) : null
|
|
7870
9503
|
] }),
|
|
7871
|
-
participant.handRaised ? /* @__PURE__ */ (0,
|
|
7872
|
-
!participant.micEnabled && !isNoteTaker(participant) ? /* @__PURE__ */ (0,
|
|
7873
|
-
/* @__PURE__ */ (0,
|
|
7874
|
-
/* @__PURE__ */ (0,
|
|
7875
|
-
/* @__PURE__ */ (0,
|
|
9504
|
+
participant.handRaised ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HandIcon, { width: 14, height: 14 }) : null,
|
|
9505
|
+
!participant.micEnabled && !isNoteTaker(participant) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MicOffIcon, { width: 14, height: 14 }) : null,
|
|
9506
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(QualityBars, { quality: participant.quality }),
|
|
9507
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__anchor", children: [
|
|
9508
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7876
9509
|
ControlButton,
|
|
7877
9510
|
{
|
|
7878
9511
|
label: `More for ${participant.displayName}`,
|
|
7879
9512
|
active: menuFor === participant.identity,
|
|
7880
9513
|
onClick: () => setMenuFor(menuFor === participant.identity ? null : participant.identity),
|
|
7881
|
-
children: /* @__PURE__ */ (0,
|
|
9514
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MoreIcon, { width: 16, height: 16 })
|
|
7882
9515
|
}
|
|
7883
9516
|
),
|
|
7884
|
-
menuFor === participant.identity ? /* @__PURE__ */ (0,
|
|
9517
|
+
menuFor === participant.identity ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7885
9518
|
PersonMenu,
|
|
7886
9519
|
{
|
|
7887
9520
|
participant,
|
|
@@ -7892,13 +9525,13 @@ function PeoplePanel({
|
|
|
7892
9525
|
) : null
|
|
7893
9526
|
] })
|
|
7894
9527
|
] }, participant.identity)),
|
|
7895
|
-
shown.length === 0 ? /* @__PURE__ */ (0,
|
|
9528
|
+
shown.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { className: "mx-meet__panel-note", children: [
|
|
7896
9529
|
"Nobody matches \u201C",
|
|
7897
9530
|
query,
|
|
7898
9531
|
"\u201D."
|
|
7899
9532
|
] }) : null
|
|
7900
9533
|
] }),
|
|
7901
|
-
snapshot?.meeting !== null && snapshot?.meeting !== void 0 ? /* @__PURE__ */ (0,
|
|
9534
|
+
snapshot?.meeting !== null && snapshot?.meeting !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(GuestRecordAccessControl, { meeting: snapshot.meeting }) : null
|
|
7902
9535
|
] });
|
|
7903
9536
|
}
|
|
7904
9537
|
function PersonMenu({
|
|
@@ -7910,14 +9543,14 @@ function PersonMenu({
|
|
|
7910
9543
|
const host = useMeetHost();
|
|
7911
9544
|
const snapshot = useMeetSnapshot();
|
|
7912
9545
|
const controls = useHostControls();
|
|
7913
|
-
const [mode, setMode] = (0,
|
|
7914
|
-
const [text3, setText] = (0,
|
|
9546
|
+
const [mode, setMode] = (0, import_react5.useState)("menu");
|
|
9547
|
+
const [text3, setText] = (0, import_react5.useState)("");
|
|
7915
9548
|
const self = participant.identity === snapshot?.localIdentity;
|
|
7916
9549
|
const moderate = controls.canModerate(participant);
|
|
7917
9550
|
const pinned = snapshot?.pinned === participant.identity;
|
|
7918
9551
|
const spotlit = snapshot?.spotlight === participant.identity;
|
|
7919
9552
|
const hasAccount = participant.userId !== null;
|
|
7920
|
-
const [refused, setRefused] = (0,
|
|
9553
|
+
const [refused, setRefused] = (0, import_react5.useState)(false);
|
|
7921
9554
|
const act = (request) => {
|
|
7922
9555
|
setRefused(false);
|
|
7923
9556
|
void controls.run(request).then((result) => {
|
|
@@ -7925,10 +9558,10 @@ function PersonMenu({
|
|
|
7925
9558
|
else setRefused(true);
|
|
7926
9559
|
});
|
|
7927
9560
|
};
|
|
7928
|
-
const refusal2 = refused && controls.notice?.failed === true ? /* @__PURE__ */ (0,
|
|
9561
|
+
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
9562
|
if (mode === "rename" || mode === "report") {
|
|
7930
9563
|
const renaming = mode === "rename";
|
|
7931
|
-
return /* @__PURE__ */ (0,
|
|
9564
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Popover, { label: renaming ? "Rename" : "Report", onClose, placement, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7932
9565
|
"form",
|
|
7933
9566
|
{
|
|
7934
9567
|
className: "mx-meet__menu-form",
|
|
@@ -7940,9 +9573,9 @@ function PersonMenu({
|
|
|
7940
9573
|
);
|
|
7941
9574
|
},
|
|
7942
9575
|
children: [
|
|
7943
|
-
/* @__PURE__ */ (0,
|
|
7944
|
-
/* @__PURE__ */ (0,
|
|
7945
|
-
renaming ? /* @__PURE__ */ (0,
|
|
9576
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__field", children: [
|
|
9577
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__field-label", children: renaming ? "Name shown in this meeting" : `What did ${participant.displayName} do?` }),
|
|
9578
|
+
renaming ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7946
9579
|
"input",
|
|
7947
9580
|
{
|
|
7948
9581
|
className: "mx-meet__input",
|
|
@@ -7951,7 +9584,7 @@ function PersonMenu({
|
|
|
7951
9584
|
value: text3,
|
|
7952
9585
|
onChange: (event) => setText(event.target.value)
|
|
7953
9586
|
}
|
|
7954
|
-
) : /* @__PURE__ */ (0,
|
|
9587
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7955
9588
|
"textarea",
|
|
7956
9589
|
{
|
|
7957
9590
|
className: "mx-meet__input",
|
|
@@ -7964,9 +9597,9 @@ function PersonMenu({
|
|
|
7964
9597
|
)
|
|
7965
9598
|
] }),
|
|
7966
9599
|
refusal2,
|
|
7967
|
-
/* @__PURE__ */ (0,
|
|
7968
|
-
/* @__PURE__ */ (0,
|
|
7969
|
-
/* @__PURE__ */ (0,
|
|
9600
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__menu-actions", children: [
|
|
9601
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mx-meet__link", onClick: () => setMode("menu"), children: "Back" }),
|
|
9602
|
+
/* @__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
9603
|
] })
|
|
7971
9604
|
]
|
|
7972
9605
|
}
|
|
@@ -7974,12 +9607,12 @@ function PersonMenu({
|
|
|
7974
9607
|
}
|
|
7975
9608
|
if (mode === "remove" || mode === "transfer") {
|
|
7976
9609
|
const removing = mode === "remove";
|
|
7977
|
-
return /* @__PURE__ */ (0,
|
|
7978
|
-
/* @__PURE__ */ (0,
|
|
9610
|
+
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: [
|
|
9611
|
+
/* @__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
9612
|
refusal2,
|
|
7980
|
-
/* @__PURE__ */ (0,
|
|
7981
|
-
/* @__PURE__ */ (0,
|
|
7982
|
-
/* @__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: "Cancel" }),
|
|
9615
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7983
9616
|
"button",
|
|
7984
9617
|
{
|
|
7985
9618
|
type: "button",
|
|
@@ -7992,8 +9625,8 @@ function PersonMenu({
|
|
|
7992
9625
|
] })
|
|
7993
9626
|
] }) });
|
|
7994
9627
|
}
|
|
7995
|
-
return /* @__PURE__ */ (0,
|
|
7996
|
-
/* @__PURE__ */ (0,
|
|
9628
|
+
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: [
|
|
9629
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7997
9630
|
MenuItem,
|
|
7998
9631
|
{
|
|
7999
9632
|
onSelect: () => {
|
|
@@ -8001,13 +9634,13 @@ function PersonMenu({
|
|
|
8001
9634
|
onClose();
|
|
8002
9635
|
},
|
|
8003
9636
|
children: [
|
|
8004
|
-
/* @__PURE__ */ (0,
|
|
9637
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PinIcon, { width: 16, height: 16 }),
|
|
8005
9638
|
" ",
|
|
8006
9639
|
pinned ? "Unpin" : "Pin for me"
|
|
8007
9640
|
]
|
|
8008
9641
|
}
|
|
8009
9642
|
),
|
|
8010
|
-
!self && !participant.isAgent && (onMessage !== void 0 || host !== null) ? /* @__PURE__ */ (0,
|
|
9643
|
+
!self && !participant.isAgent && (onMessage !== void 0 || host !== null) ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8011
9644
|
MenuItem,
|
|
8012
9645
|
{
|
|
8013
9646
|
onSelect: () => {
|
|
@@ -8019,42 +9652,42 @@ function PersonMenu({
|
|
|
8019
9652
|
onClose();
|
|
8020
9653
|
},
|
|
8021
9654
|
children: [
|
|
8022
|
-
/* @__PURE__ */ (0,
|
|
9655
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChatIcon, { width: 16, height: 16 }),
|
|
8023
9656
|
" Message privately"
|
|
8024
9657
|
]
|
|
8025
9658
|
}
|
|
8026
9659
|
) : null,
|
|
8027
|
-
controls.isHost ? /* @__PURE__ */ (0,
|
|
8028
|
-
/* @__PURE__ */ (0,
|
|
9660
|
+
controls.isHost ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { onSelect: () => act({ action: "spotlight", identity: spotlit ? null : participant.identity }), children: [
|
|
9661
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SpotlightIcon, { width: 16, height: 16 }),
|
|
8029
9662
|
" ",
|
|
8030
9663
|
spotlit ? "Remove spotlight" : "Spotlight for everyone"
|
|
8031
9664
|
] }) : null,
|
|
8032
|
-
moderate ? /* @__PURE__ */ (0,
|
|
8033
|
-
/* @__PURE__ */ (0,
|
|
8034
|
-
participant.micEnabled ? /* @__PURE__ */ (0,
|
|
8035
|
-
/* @__PURE__ */ (0,
|
|
9665
|
+
moderate ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
9666
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet__menu-sep", role: "separator" }),
|
|
9667
|
+
participant.micEnabled ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { onSelect: () => act({ action: "mute", identity: participant.identity }), children: [
|
|
9668
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MicOffIcon, { width: 16, height: 16 }),
|
|
8036
9669
|
" Mute"
|
|
8037
|
-
] }) : !participant.isAgent ? /* @__PURE__ */ (0,
|
|
8038
|
-
/* @__PURE__ */ (0,
|
|
9670
|
+
] }) : !participant.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { onSelect: () => act({ action: "ask_unmute", identity: participant.identity }), children: [
|
|
9671
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MicIcon, { width: 16, height: 16 }),
|
|
8039
9672
|
" Ask to unmute"
|
|
8040
9673
|
] }) : null,
|
|
8041
|
-
participant.cameraEnabled ? /* @__PURE__ */ (0,
|
|
8042
|
-
/* @__PURE__ */ (0,
|
|
9674
|
+
participant.cameraEnabled ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { onSelect: () => act({ action: "stop_video", identity: participant.identity }), children: [
|
|
9675
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CameraOffIcon, { width: 16, height: 16 }),
|
|
8043
9676
|
" Stop video"
|
|
8044
9677
|
] }) : null,
|
|
8045
|
-
participant.screenSharing ? /* @__PURE__ */ (0,
|
|
8046
|
-
/* @__PURE__ */ (0,
|
|
9678
|
+
participant.screenSharing ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { onSelect: () => act({ action: "stop_screen", identity: participant.identity }), children: [
|
|
9679
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ScreenShareIcon, { width: 16, height: 16 }),
|
|
8047
9680
|
" Stop screen share"
|
|
8048
9681
|
] }) : null,
|
|
8049
|
-
participant.handRaised ? /* @__PURE__ */ (0,
|
|
8050
|
-
/* @__PURE__ */ (0,
|
|
9682
|
+
participant.handRaised ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { onSelect: () => act({ action: "lower_hand", identity: participant.identity }), children: [
|
|
9683
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HandIcon, { width: 16, height: 16 }),
|
|
8051
9684
|
" Lower hand"
|
|
8052
9685
|
] }) : null,
|
|
8053
|
-
hasAccount && !participant.isAgent && participant.role !== "cohost" ? /* @__PURE__ */ (0,
|
|
8054
|
-
/* @__PURE__ */ (0,
|
|
9686
|
+
hasAccount && !participant.isAgent && participant.role !== "cohost" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { onSelect: () => act({ action: "make_cohost", identity: participant.identity }), children: [
|
|
9687
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PeopleIcon, { width: 16, height: 16 }),
|
|
8055
9688
|
" Make co-host"
|
|
8056
9689
|
] }) : null,
|
|
8057
|
-
!participant.isAgent ? /* @__PURE__ */ (0,
|
|
9690
|
+
!participant.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8058
9691
|
MenuItem,
|
|
8059
9692
|
{
|
|
8060
9693
|
onSelect: () => {
|
|
@@ -8062,21 +9695,21 @@ function PersonMenu({
|
|
|
8062
9695
|
setMode("rename");
|
|
8063
9696
|
},
|
|
8064
9697
|
children: [
|
|
8065
|
-
/* @__PURE__ */ (0,
|
|
9698
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PencilIcon, { width: 16, height: 16 }),
|
|
8066
9699
|
" Rename"
|
|
8067
9700
|
]
|
|
8068
9701
|
}
|
|
8069
9702
|
) : null
|
|
8070
9703
|
] }) : null,
|
|
8071
|
-
controls.isOwner && participant.role === "cohost" ? /* @__PURE__ */ (0,
|
|
8072
|
-
/* @__PURE__ */ (0,
|
|
9704
|
+
controls.isOwner && participant.role === "cohost" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { onSelect: () => act({ action: "revoke_cohost", identity: participant.identity }), children: [
|
|
9705
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PeopleIcon, { width: 16, height: 16 }),
|
|
8073
9706
|
" Remove co-host"
|
|
8074
9707
|
] }) : null,
|
|
8075
|
-
controls.isOwner && !self && hasAccount && !participant.isAgent ? /* @__PURE__ */ (0,
|
|
8076
|
-
/* @__PURE__ */ (0,
|
|
9708
|
+
controls.isOwner && !self && hasAccount && !participant.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { onSelect: () => setMode("transfer"), children: [
|
|
9709
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SpotlightIcon, { width: 16, height: 16 }),
|
|
8077
9710
|
" Make host"
|
|
8078
9711
|
] }) : null,
|
|
8079
|
-
self ? /* @__PURE__ */ (0,
|
|
9712
|
+
self ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8080
9713
|
MenuItem,
|
|
8081
9714
|
{
|
|
8082
9715
|
onSelect: () => {
|
|
@@ -8084,12 +9717,12 @@ function PersonMenu({
|
|
|
8084
9717
|
setMode("rename");
|
|
8085
9718
|
},
|
|
8086
9719
|
children: [
|
|
8087
|
-
/* @__PURE__ */ (0,
|
|
9720
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PencilIcon, { width: 16, height: 16 }),
|
|
8088
9721
|
" Rename yourself"
|
|
8089
9722
|
]
|
|
8090
9723
|
}
|
|
8091
9724
|
) : null,
|
|
8092
|
-
!self && !participant.isAgent ? /* @__PURE__ */ (0,
|
|
9725
|
+
!self && !participant.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8093
9726
|
MenuItem,
|
|
8094
9727
|
{
|
|
8095
9728
|
onSelect: () => {
|
|
@@ -8097,21 +9730,21 @@ function PersonMenu({
|
|
|
8097
9730
|
setMode("report");
|
|
8098
9731
|
},
|
|
8099
9732
|
children: [
|
|
8100
|
-
/* @__PURE__ */ (0,
|
|
9733
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FlagIcon, { width: 16, height: 16 }),
|
|
8101
9734
|
" Report"
|
|
8102
9735
|
]
|
|
8103
9736
|
}
|
|
8104
9737
|
) : null,
|
|
8105
|
-
moderate && !participant.isAgent ? /* @__PURE__ */ (0,
|
|
8106
|
-
/* @__PURE__ */ (0,
|
|
9738
|
+
moderate && !participant.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(MenuItem, { danger: true, onSelect: () => setMode("remove"), children: [
|
|
9739
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CloseIcon, { width: 16, height: 16 }),
|
|
8107
9740
|
" Remove from meeting"
|
|
8108
9741
|
] }) : null
|
|
8109
9742
|
] }) });
|
|
8110
9743
|
}
|
|
8111
9744
|
function SettingsPanel({ onClose }) {
|
|
8112
9745
|
const host = useRequiredMeetHost();
|
|
8113
|
-
return /* @__PURE__ */ (0,
|
|
8114
|
-
/* @__PURE__ */ (0,
|
|
9746
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(PanelShell, { title: "Settings", onClose, children: [
|
|
9747
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8115
9748
|
DeviceSettings,
|
|
8116
9749
|
{
|
|
8117
9750
|
onPick: (kind, deviceId2) => {
|
|
@@ -8120,7 +9753,8 @@ function SettingsPanel({ onClose }) {
|
|
|
8120
9753
|
}
|
|
8121
9754
|
}
|
|
8122
9755
|
),
|
|
8123
|
-
/* @__PURE__ */ (0,
|
|
9756
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(EffectsSettings, {}),
|
|
9757
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CaptionLanguageSettings, {})
|
|
8124
9758
|
] });
|
|
8125
9759
|
}
|
|
8126
9760
|
function DeviceSettings({
|
|
@@ -8132,15 +9766,15 @@ function DeviceSettings({
|
|
|
8132
9766
|
const speaker = devices?.selected.audiooutput ?? host.devices.resolve("audiooutput");
|
|
8133
9767
|
const stream = useMicrophoneStream(microphone);
|
|
8134
9768
|
const level = useAudioLevel(stream);
|
|
8135
|
-
const [testing, setTesting] = (0,
|
|
8136
|
-
(0,
|
|
9769
|
+
const [testing, setTesting] = (0, import_react5.useState)(false);
|
|
9770
|
+
(0, import_react5.useEffect)(() => {
|
|
8137
9771
|
void host.devices.refresh();
|
|
8138
9772
|
}, [host]);
|
|
8139
|
-
return /* @__PURE__ */ (0,
|
|
8140
|
-
/* @__PURE__ */ (0,
|
|
8141
|
-
/* @__PURE__ */ (0,
|
|
8142
|
-
/* @__PURE__ */ (0,
|
|
8143
|
-
/* @__PURE__ */ (0,
|
|
9773
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__section", "aria-label": "Devices", children: [
|
|
9774
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DevicePicker, { kind: "audioinput", label: "Microphone", onPick }),
|
|
9775
|
+
/* @__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))}%` } }) }),
|
|
9776
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DevicePicker, { kind: "audiooutput", label: "Speaker", onPick }),
|
|
9777
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8144
9778
|
"button",
|
|
8145
9779
|
{
|
|
8146
9780
|
type: "button",
|
|
@@ -8151,19 +9785,19 @@ function DeviceSettings({
|
|
|
8151
9785
|
void playTestSound(speaker).finally(() => setTesting(false));
|
|
8152
9786
|
},
|
|
8153
9787
|
children: [
|
|
8154
|
-
/* @__PURE__ */ (0,
|
|
9788
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SpeakerIcon, { width: 14, height: 14 }),
|
|
8155
9789
|
" ",
|
|
8156
9790
|
testing ? "Playing\u2026" : "Test speaker"
|
|
8157
9791
|
]
|
|
8158
9792
|
}
|
|
8159
9793
|
),
|
|
8160
|
-
/* @__PURE__ */ (0,
|
|
9794
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DevicePicker, { kind: "videoinput", label: "Camera", onPick })
|
|
8161
9795
|
] });
|
|
8162
9796
|
}
|
|
8163
9797
|
function EffectsSettings({ preview }) {
|
|
8164
9798
|
const effects = useMediaEffects();
|
|
8165
|
-
const [error, setError] = (0,
|
|
8166
|
-
const fileRef = (0,
|
|
9799
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
9800
|
+
const fileRef = (0, import_react5.useRef)(null);
|
|
8167
9801
|
const supported = effects.backgroundsSupported || preview != null || videoEffectsSupported();
|
|
8168
9802
|
const apply = (next) => {
|
|
8169
9803
|
setError(null);
|
|
@@ -8175,9 +9809,9 @@ function EffectsSettings({ preview }) {
|
|
|
8175
9809
|
);
|
|
8176
9810
|
}
|
|
8177
9811
|
};
|
|
8178
|
-
return /* @__PURE__ */ (0,
|
|
8179
|
-
/* @__PURE__ */ (0,
|
|
8180
|
-
/* @__PURE__ */ (0,
|
|
9812
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__section", "aria-label": "Effects", children: [
|
|
9813
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__toggle", children: [
|
|
9814
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8181
9815
|
"input",
|
|
8182
9816
|
{
|
|
8183
9817
|
type: "checkbox",
|
|
@@ -8186,11 +9820,11 @@ function EffectsSettings({ preview }) {
|
|
|
8186
9820
|
}
|
|
8187
9821
|
),
|
|
8188
9822
|
"Noise suppression",
|
|
8189
|
-
/* @__PURE__ */ (0,
|
|
9823
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__hint", children: "Filters keyboards, fans and background chatter." })
|
|
8190
9824
|
] }),
|
|
8191
|
-
supported ? /* @__PURE__ */ (0,
|
|
8192
|
-
/* @__PURE__ */ (0,
|
|
8193
|
-
/* @__PURE__ */ (0,
|
|
9825
|
+
supported ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__field", children: [
|
|
9826
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__field-label", children: "Background" }),
|
|
9827
|
+
/* @__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
9828
|
"button",
|
|
8195
9829
|
{
|
|
8196
9830
|
type: "button",
|
|
@@ -8208,7 +9842,7 @@ function EffectsSettings({ preview }) {
|
|
|
8208
9842
|
},
|
|
8209
9843
|
kind
|
|
8210
9844
|
)) }),
|
|
8211
|
-
/* @__PURE__ */ (0,
|
|
9845
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8212
9846
|
"input",
|
|
8213
9847
|
{
|
|
8214
9848
|
ref: fileRef,
|
|
@@ -8223,7 +9857,7 @@ function EffectsSettings({ preview }) {
|
|
|
8223
9857
|
}
|
|
8224
9858
|
}
|
|
8225
9859
|
),
|
|
8226
|
-
error !== null ? /* @__PURE__ */ (0,
|
|
9860
|
+
error !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__error", children: error }) : null
|
|
8227
9861
|
] }) : null
|
|
8228
9862
|
] });
|
|
8229
9863
|
}
|
|
@@ -8282,8 +9916,8 @@ async function playTestSound(sinkId) {
|
|
|
8282
9916
|
await context.close();
|
|
8283
9917
|
}
|
|
8284
9918
|
function useMicrophoneStream(deviceId2) {
|
|
8285
|
-
const [stream, setStream] = (0,
|
|
8286
|
-
(0,
|
|
9919
|
+
const [stream, setStream] = (0, import_react5.useState)(null);
|
|
9920
|
+
(0, import_react5.useEffect)(() => {
|
|
8287
9921
|
if (deviceId2 === "off") return void 0;
|
|
8288
9922
|
let live = true;
|
|
8289
9923
|
let opened = null;
|
|
@@ -8308,25 +9942,25 @@ function useMicrophoneStream(deviceId2) {
|
|
|
8308
9942
|
function LobbyPanel() {
|
|
8309
9943
|
const lobby = useLobby();
|
|
8310
9944
|
if (!lobby.canAdmit || lobby.waiting.length === 0) return null;
|
|
8311
|
-
return /* @__PURE__ */ (0,
|
|
8312
|
-
/* @__PURE__ */ (0,
|
|
8313
|
-
/* @__PURE__ */ (0,
|
|
8314
|
-
/* @__PURE__ */ (0,
|
|
9945
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__lobby", "aria-label": "Waiting room", children: [
|
|
9946
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { className: "mx-meet__lobby-head", children: [
|
|
9947
|
+
/* @__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` }),
|
|
9948
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mx-meet__link", onClick: () => void lobby.admitAll(), children: "Admit all" })
|
|
8315
9949
|
] }),
|
|
8316
|
-
/* @__PURE__ */ (0,
|
|
8317
|
-
/* @__PURE__ */ (0,
|
|
8318
|
-
/* @__PURE__ */ (0,
|
|
9950
|
+
/* @__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: [
|
|
9951
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Avatar, { name: entry.displayName, url: entry.avatarUrl, size: 32 }),
|
|
9952
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__person-name", children: [
|
|
8319
9953
|
entry.displayName,
|
|
8320
|
-
entry.userId === null ? /* @__PURE__ */ (0,
|
|
9954
|
+
entry.userId === null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Guest" }) : null
|
|
8321
9955
|
] }),
|
|
8322
|
-
/* @__PURE__ */ (0,
|
|
8323
|
-
/* @__PURE__ */ (0,
|
|
9956
|
+
/* @__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 }) }),
|
|
9957
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8324
9958
|
ControlButton,
|
|
8325
9959
|
{
|
|
8326
9960
|
label: `Deny ${entry.displayName}`,
|
|
8327
9961
|
danger: true,
|
|
8328
9962
|
onClick: () => void lobby.deny(entry),
|
|
8329
|
-
children: /* @__PURE__ */ (0,
|
|
9963
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CloseIcon, { width: 16, height: 16 })
|
|
8330
9964
|
}
|
|
8331
9965
|
)
|
|
8332
9966
|
] }, entry.identity)) })
|
|
@@ -8336,21 +9970,21 @@ function NoteTakerRow() {
|
|
|
8336
9970
|
const ai = useMeetAi();
|
|
8337
9971
|
const status = ai.noteTaker;
|
|
8338
9972
|
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,
|
|
9973
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__note-taker", "aria-label": "Note-taker", children: [
|
|
9974
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: `mx-meet__note-taker-state mx-meet__note-taker-state--${status.state}`, children: [
|
|
9975
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__note-taker-dot", "aria-hidden": "true" }),
|
|
8342
9976
|
ai.noteTakerLabel
|
|
8343
9977
|
] }),
|
|
8344
|
-
status.detail !== null ? /* @__PURE__ */ (0,
|
|
8345
|
-
status.refusal !== null ? /* @__PURE__ */ (0,
|
|
8346
|
-
/* @__PURE__ */ (0,
|
|
8347
|
-
status.refusal.remedy.length > 0 ? /* @__PURE__ */ (0,
|
|
9978
|
+
status.detail !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: status.detail }) : null,
|
|
9979
|
+
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: [
|
|
9980
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-reason", children: status.refusal.reason }),
|
|
9981
|
+
status.refusal.remedy.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-remedy", children: status.refusal.remedy }) : null
|
|
8348
9982
|
] }) : null,
|
|
8349
|
-
ai.error !== null && !duplicateError ? /* @__PURE__ */ (0,
|
|
8350
|
-
/* @__PURE__ */ (0,
|
|
8351
|
-
/* @__PURE__ */ (0,
|
|
9983
|
+
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: [
|
|
9984
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-reason", children: ai.error.message }),
|
|
9985
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-remedy", children: ai.error.remedy })
|
|
8352
9986
|
] }) : null,
|
|
8353
|
-
ai.canControlNoteTaker ? status.state === "transcribing" || status.state === "joining" || status.state === "handoff_pending" ? /* @__PURE__ */ (0,
|
|
9987
|
+
ai.canControlNoteTaker ? status.state === "transcribing" || status.state === "joining" || status.state === "handoff_pending" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8354
9988
|
"button",
|
|
8355
9989
|
{
|
|
8356
9990
|
type: "button",
|
|
@@ -8358,7 +9992,7 @@ function NoteTakerRow() {
|
|
|
8358
9992
|
onClick: () => void ai.stopNoteTaker(),
|
|
8359
9993
|
children: "Dismiss the note-taker"
|
|
8360
9994
|
}
|
|
8361
|
-
) : /* @__PURE__ */ (0,
|
|
9995
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8362
9996
|
"button",
|
|
8363
9997
|
{
|
|
8364
9998
|
type: "button",
|
|
@@ -8374,24 +10008,24 @@ function NoteList({
|
|
|
8374
10008
|
notes,
|
|
8375
10009
|
empty
|
|
8376
10010
|
}) {
|
|
8377
|
-
return /* @__PURE__ */ (0,
|
|
8378
|
-
/* @__PURE__ */ (0,
|
|
8379
|
-
notes.length === 0 ? /* @__PURE__ */ (0,
|
|
10011
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__note-group", "aria-label": title, children: [
|
|
10012
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { className: "mx-meet__note-group-title", children: title }),
|
|
10013
|
+
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
10014
|
note.text,
|
|
8381
|
-
note.assigneeDisplayName !== void 0 && note.assigneeDisplayName !== null ? /* @__PURE__ */ (0,
|
|
10015
|
+
note.assigneeDisplayName !== void 0 && note.assigneeDisplayName !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__assignee", children: note.assigneeDisplayName }) : null
|
|
8382
10016
|
] }, note.id)) })
|
|
8383
10017
|
] });
|
|
8384
10018
|
}
|
|
8385
10019
|
function AiPanel({ onClose }) {
|
|
8386
10020
|
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,
|
|
10021
|
+
const [question, setQuestion] = (0, import_react5.useState)("");
|
|
10022
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(PanelShell, { title: "Meeting assistant", onClose, children: [
|
|
10023
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NoteTakerRow, {}),
|
|
10024
|
+
ai.summary !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__note-group", "aria-label": "Summary", children: [
|
|
10025
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { className: "mx-meet__note-group-title", children: "Summary" }),
|
|
10026
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__summary", children: ai.summary.text })
|
|
8393
10027
|
] }) : null,
|
|
8394
|
-
ai.wrapUp !== null ? /* @__PURE__ */ (0,
|
|
10028
|
+
ai.wrapUp !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__wrap-up-notice", role: "status", children: [
|
|
8395
10029
|
"The wrap-up is written \u2014 ",
|
|
8396
10030
|
ai.wrapUp.noteIds.length,
|
|
8397
10031
|
" ",
|
|
@@ -8403,7 +10037,7 @@ function AiPanel({ onClose }) {
|
|
|
8403
10037
|
ai.wrapUp.segmentCount === 1 ? "transcript line" : "transcript lines",
|
|
8404
10038
|
"."
|
|
8405
10039
|
] }) : null,
|
|
8406
|
-
/* @__PURE__ */ (0,
|
|
10040
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8407
10041
|
NoteList,
|
|
8408
10042
|
{
|
|
8409
10043
|
title: "Notes",
|
|
@@ -8411,7 +10045,7 @@ function AiPanel({ onClose }) {
|
|
|
8411
10045
|
empty: "Notes appear here as the meeting goes on."
|
|
8412
10046
|
}
|
|
8413
10047
|
),
|
|
8414
|
-
/* @__PURE__ */ (0,
|
|
10048
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8415
10049
|
NoteList,
|
|
8416
10050
|
{
|
|
8417
10051
|
title: "Decisions",
|
|
@@ -8419,7 +10053,7 @@ function AiPanel({ onClose }) {
|
|
|
8419
10053
|
empty: "Nothing has been decided yet."
|
|
8420
10054
|
}
|
|
8421
10055
|
),
|
|
8422
|
-
/* @__PURE__ */ (0,
|
|
10056
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8423
10057
|
NoteList,
|
|
8424
10058
|
{
|
|
8425
10059
|
title: "Action items",
|
|
@@ -8427,21 +10061,21 @@ function AiPanel({ onClose }) {
|
|
|
8427
10061
|
empty: "No action items yet."
|
|
8428
10062
|
}
|
|
8429
10063
|
),
|
|
8430
|
-
ai.transcript.length > 0 ? /* @__PURE__ */ (0,
|
|
8431
|
-
/* @__PURE__ */ (0,
|
|
8432
|
-
/* @__PURE__ */ (0,
|
|
10064
|
+
ai.transcript.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__note-group", "aria-label": "Transcript", children: [
|
|
10065
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { className: "mx-meet__note-group-title", children: "Transcript" }),
|
|
10066
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: "mx-meet__transcript", children: ai.transcript.map((line) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8433
10067
|
"li",
|
|
8434
10068
|
{
|
|
8435
10069
|
className: line.final && line.source === "record" ? "mx-meet__line" : "mx-meet__line mx-meet__line--interim",
|
|
8436
10070
|
children: [
|
|
8437
|
-
/* @__PURE__ */ (0,
|
|
8438
|
-
/* @__PURE__ */ (0,
|
|
10071
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: line.speaker }),
|
|
10072
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: line.text })
|
|
8439
10073
|
]
|
|
8440
10074
|
},
|
|
8441
10075
|
line.id
|
|
8442
10076
|
)) })
|
|
8443
10077
|
] }) : null,
|
|
8444
|
-
/* @__PURE__ */ (0,
|
|
10078
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8445
10079
|
"form",
|
|
8446
10080
|
{
|
|
8447
10081
|
className: "mx-meet__composer",
|
|
@@ -8452,7 +10086,7 @@ function AiPanel({ onClose }) {
|
|
|
8452
10086
|
void ai.ask(asked);
|
|
8453
10087
|
},
|
|
8454
10088
|
children: [
|
|
8455
|
-
/* @__PURE__ */ (0,
|
|
10089
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8456
10090
|
"input",
|
|
8457
10091
|
{
|
|
8458
10092
|
className: "mx-meet__input",
|
|
@@ -8462,13 +10096,13 @@ function AiPanel({ onClose }) {
|
|
|
8462
10096
|
"aria-label": "Ask about this meeting"
|
|
8463
10097
|
}
|
|
8464
10098
|
),
|
|
8465
|
-
/* @__PURE__ */ (0,
|
|
10099
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "submit", className: "mx-meet__send", disabled: ai.asking, children: ai.asking ? "Asking\u2026" : "Ask" })
|
|
8466
10100
|
]
|
|
8467
10101
|
}
|
|
8468
10102
|
),
|
|
8469
|
-
ai.asking && ai.phase !== null ? /* @__PURE__ */ (0,
|
|
8470
|
-
ai.answer !== null ? /* @__PURE__ */ (0,
|
|
8471
|
-
ai.answer !== null && ai.coverage !== null ? /* @__PURE__ */ (0,
|
|
10103
|
+
ai.asking && ai.phase !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", role: "status", children: ai.phase }) : null,
|
|
10104
|
+
ai.answer !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__answer", children: ai.answer }) : null,
|
|
10105
|
+
ai.answer !== null && ai.coverage !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__coverage", children: [
|
|
8472
10106
|
"Answered from ",
|
|
8473
10107
|
ai.coverage.segmentsUsed,
|
|
8474
10108
|
" of ",
|
|
@@ -8477,48 +10111,56 @@ function AiPanel({ onClose }) {
|
|
|
8477
10111
|
ai.coverage.truncated ? " (the oldest were left out)" : "",
|
|
8478
10112
|
"."
|
|
8479
10113
|
] }) : null,
|
|
8480
|
-
ai.error !== null ? /* @__PURE__ */ (0,
|
|
8481
|
-
/* @__PURE__ */ (0,
|
|
8482
|
-
/* @__PURE__ */ (0,
|
|
10114
|
+
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: [
|
|
10115
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-reason", children: ai.error.message }),
|
|
10116
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-remedy", children: ai.error.remedy })
|
|
8483
10117
|
] }) : null
|
|
8484
10118
|
] });
|
|
8485
10119
|
}
|
|
8486
10120
|
function Captions({ lines = 3 }) {
|
|
8487
10121
|
const ai = useMeetAi();
|
|
8488
10122
|
const visible = ai.transcript.slice(-lines);
|
|
10123
|
+
const translation = useCaptionTranslation(visible);
|
|
8489
10124
|
if (visible.length === 0) return null;
|
|
8490
|
-
return /* @__PURE__ */ (0,
|
|
8491
|
-
|
|
8492
|
-
|
|
8493
|
-
|
|
8494
|
-
|
|
8495
|
-
|
|
8496
|
-
|
|
8497
|
-
|
|
8498
|
-
|
|
8499
|
-
|
|
8500
|
-
|
|
8501
|
-
|
|
10125
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__captions", "aria-live": "polite", "aria-label": "Live captions", children: [
|
|
10126
|
+
visible.map((line) => {
|
|
10127
|
+
const translated = translation.language === null ? void 0 : translation.translations[line.id];
|
|
10128
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
10129
|
+
"p",
|
|
10130
|
+
{
|
|
10131
|
+
className: line.final ? "mx-meet__caption" : "mx-meet__caption mx-meet__caption--interim",
|
|
10132
|
+
children: [
|
|
10133
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: line.speaker }),
|
|
10134
|
+
" ",
|
|
10135
|
+
translated ?? line.text,
|
|
10136
|
+
translated !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__caption-original", children: line.text }) : null
|
|
10137
|
+
]
|
|
10138
|
+
},
|
|
10139
|
+
line.id
|
|
10140
|
+
);
|
|
10141
|
+
}),
|
|
10142
|
+
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
|
|
10143
|
+
] });
|
|
8502
10144
|
}
|
|
8503
10145
|
function ConsentNotice() {
|
|
8504
10146
|
const notice = useConsentNotice();
|
|
8505
10147
|
if (notice === null) return null;
|
|
8506
|
-
return /* @__PURE__ */ (0,
|
|
10148
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__consent", role: "status", children: notice });
|
|
8507
10149
|
}
|
|
8508
10150
|
function AttendanceNotice() {
|
|
8509
10151
|
const media = useLocalMedia();
|
|
8510
10152
|
const notice = listenOnlyNotice(media);
|
|
8511
10153
|
if (notice === null) return null;
|
|
8512
10154
|
const refused = media.microphone.unavailable;
|
|
8513
|
-
return /* @__PURE__ */ (0,
|
|
10155
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__banner mx-meet__banner--attendance", role: "status", children: [
|
|
8514
10156
|
notice,
|
|
8515
|
-
refused === null ? null : /* @__PURE__ */ (0,
|
|
10157
|
+
refused === null ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__remedy", children: refused.remedy })
|
|
8516
10158
|
] });
|
|
8517
10159
|
}
|
|
8518
10160
|
function PreJoin(props) {
|
|
8519
10161
|
const host = useMeetHost();
|
|
8520
|
-
if (host === null) return /* @__PURE__ */ (0,
|
|
8521
|
-
return /* @__PURE__ */ (0,
|
|
10162
|
+
if (host === null) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InertNotice, { what: "This meeting" });
|
|
10163
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PreJoinBody, { ...props, host });
|
|
8522
10164
|
}
|
|
8523
10165
|
function PreJoinBody({
|
|
8524
10166
|
roomName,
|
|
@@ -8532,21 +10174,21 @@ function PreJoinBody({
|
|
|
8532
10174
|
const recording = useRecording();
|
|
8533
10175
|
const effects = useMediaEffects();
|
|
8534
10176
|
const { notice } = useModerationNotice();
|
|
8535
|
-
const [mode, setMode] = (0,
|
|
8536
|
-
const [microphone, setMicrophone] = (0,
|
|
8537
|
-
const [joining, setJoining] = (0,
|
|
10177
|
+
const [mode, setMode] = (0, import_react5.useState)("video");
|
|
10178
|
+
const [microphone, setMicrophone] = (0, import_react5.useState)(true);
|
|
10179
|
+
const [joining, setJoining] = (0, import_react5.useState)(false);
|
|
8538
10180
|
const camera = devices?.selected.videoinput ?? host.devices.resolve("videoinput");
|
|
8539
10181
|
const mic = devices?.selected.audioinput ?? host.devices.resolve("audioinput");
|
|
8540
10182
|
const preview = useCameraPreview(mode === "video" ? camera : void 0, effects.effects);
|
|
8541
10183
|
const micStream = useMicrophoneStream(microphone ? mic : "off");
|
|
8542
10184
|
const level = useAudioLevel(micStream);
|
|
8543
|
-
const [speakerTesting, setSpeakerTesting] = (0,
|
|
8544
|
-
(0,
|
|
10185
|
+
const [speakerTesting, setSpeakerTesting] = (0, import_react5.useState)(false);
|
|
10186
|
+
(0, import_react5.useEffect)(() => {
|
|
8545
10187
|
void host.devices.refresh();
|
|
8546
10188
|
}, [host]);
|
|
8547
|
-
return /* @__PURE__ */ (0,
|
|
8548
|
-
/* @__PURE__ */ (0,
|
|
8549
|
-
mode === "video" && preview.preview !== null ? /* @__PURE__ */ (0,
|
|
10189
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__prejoin", children: [
|
|
10190
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__preview", children: [
|
|
10191
|
+
mode === "video" && preview.preview !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8550
10192
|
"video",
|
|
8551
10193
|
{
|
|
8552
10194
|
className: "mx-meet__video mx-meet__video--mirror",
|
|
@@ -8557,16 +10199,16 @@ function PreJoinBody({
|
|
|
8557
10199
|
if (element !== null) preview.preview?.attach(element);
|
|
8558
10200
|
}
|
|
8559
10201
|
}
|
|
8560
|
-
) : /* @__PURE__ */ (0,
|
|
8561
|
-
mode === "video" && preview.error !== null ? /* @__PURE__ */ (0,
|
|
8562
|
-
microphone && micStream !== null ? /* @__PURE__ */ (0,
|
|
10202
|
+
) : /* @__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 }) }),
|
|
10203
|
+
mode === "video" && preview.error !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__preview-note", children: preview.error }) : null,
|
|
10204
|
+
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
10205
|
] }),
|
|
8564
|
-
/* @__PURE__ */ (0,
|
|
8565
|
-
/* @__PURE__ */ (0,
|
|
8566
|
-
notice?.kind === "removed" ? /* @__PURE__ */ (0,
|
|
8567
|
-
devices?.labelsHidden === true ? /* @__PURE__ */ (0,
|
|
10206
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__prejoin-panel", children: [
|
|
10207
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h1", { className: "mx-meet__prejoin-title", children: "Ready to join?" }),
|
|
10208
|
+
notice?.kind === "removed" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__warning", children: notice.text }) : null,
|
|
10209
|
+
devices?.labelsHidden === true ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__panel-note", children: [
|
|
8568
10210
|
"Your browser is hiding device names until you allow camera and microphone access.",
|
|
8569
|
-
/* @__PURE__ */ (0,
|
|
10211
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8570
10212
|
"button",
|
|
8571
10213
|
{
|
|
8572
10214
|
type: "button",
|
|
@@ -8578,11 +10220,11 @@ function PreJoinBody({
|
|
|
8578
10220
|
}
|
|
8579
10221
|
)
|
|
8580
10222
|
] }) : null,
|
|
8581
|
-
devices?.fallbackNotice != null ? /* @__PURE__ */ (0,
|
|
8582
|
-
/* @__PURE__ */ (0,
|
|
8583
|
-
/* @__PURE__ */ (0,
|
|
8584
|
-
/* @__PURE__ */ (0,
|
|
8585
|
-
/* @__PURE__ */ (0,
|
|
10223
|
+
devices?.fallbackNotice != null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__warning", children: devices.fallbackNotice }) : null,
|
|
10224
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DevicePicker, { kind: "audioinput", label: "Microphone" }),
|
|
10225
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__field-row", children: [
|
|
10226
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DevicePicker, { kind: "audiooutput", label: "Speaker" }),
|
|
10227
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8586
10228
|
"button",
|
|
8587
10229
|
{
|
|
8588
10230
|
type: "button",
|
|
@@ -8595,19 +10237,19 @@ function PreJoinBody({
|
|
|
8595
10237
|
);
|
|
8596
10238
|
},
|
|
8597
10239
|
children: [
|
|
8598
|
-
/* @__PURE__ */ (0,
|
|
10240
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SpeakerIcon, { width: 14, height: 14 }),
|
|
8599
10241
|
" ",
|
|
8600
10242
|
speakerTesting ? "Playing\u2026" : "Test"
|
|
8601
10243
|
]
|
|
8602
10244
|
}
|
|
8603
10245
|
)
|
|
8604
10246
|
] }),
|
|
8605
|
-
/* @__PURE__ */ (0,
|
|
8606
|
-
/* @__PURE__ */ (0,
|
|
8607
|
-
recording.consentNotice !== null ? /* @__PURE__ */ (0,
|
|
8608
|
-
/* @__PURE__ */ (0,
|
|
8609
|
-
/* @__PURE__ */ (0,
|
|
8610
|
-
/* @__PURE__ */ (0,
|
|
10247
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DevicePicker, { kind: "videoinput", label: "Camera" }),
|
|
10248
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(EffectsSettings, { preview: preview.preview }),
|
|
10249
|
+
recording.consentNotice !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__consent", children: recording.consentNotice }) : null,
|
|
10250
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__prejoin-actions", children: [
|
|
10251
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__toggle", children: [
|
|
10252
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8611
10253
|
"input",
|
|
8612
10254
|
{
|
|
8613
10255
|
type: "checkbox",
|
|
@@ -8617,8 +10259,8 @@ function PreJoinBody({
|
|
|
8617
10259
|
),
|
|
8618
10260
|
"Join with video"
|
|
8619
10261
|
] }),
|
|
8620
|
-
/* @__PURE__ */ (0,
|
|
8621
|
-
/* @__PURE__ */ (0,
|
|
10262
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__toggle", children: [
|
|
10263
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8622
10264
|
"input",
|
|
8623
10265
|
{
|
|
8624
10266
|
type: "checkbox",
|
|
@@ -8628,7 +10270,7 @@ function PreJoinBody({
|
|
|
8628
10270
|
),
|
|
8629
10271
|
"Join with microphone"
|
|
8630
10272
|
] }),
|
|
8631
|
-
/* @__PURE__ */ (0,
|
|
10273
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8632
10274
|
"button",
|
|
8633
10275
|
{
|
|
8634
10276
|
type: "button",
|
|
@@ -8648,20 +10290,20 @@ function PreJoinBody({
|
|
|
8648
10290
|
}
|
|
8649
10291
|
)
|
|
8650
10292
|
] }),
|
|
8651
|
-
room.failure !== null ? /* @__PURE__ */ (0,
|
|
10293
|
+
room.failure !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__error", children: [
|
|
8652
10294
|
room.failure.message,
|
|
8653
|
-
/* @__PURE__ */ (0,
|
|
10295
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__remedy", children: room.failure.remedy })
|
|
8654
10296
|
] }) : null
|
|
8655
10297
|
] })
|
|
8656
10298
|
] });
|
|
8657
10299
|
}
|
|
8658
10300
|
function useCameraPreview(deviceId2, effects) {
|
|
8659
|
-
const [preview, setPreview] = (0,
|
|
8660
|
-
const [error, setError] = (0,
|
|
8661
|
-
const current = (0,
|
|
8662
|
-
const initialEffect = (0,
|
|
10301
|
+
const [preview, setPreview] = (0, import_react5.useState)(null);
|
|
10302
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
10303
|
+
const current = (0, import_react5.useRef)(null);
|
|
10304
|
+
const initialEffect = (0, import_react5.useRef)(toVideoEffect(effects));
|
|
8663
10305
|
initialEffect.current = toVideoEffect(effects);
|
|
8664
|
-
(0,
|
|
10306
|
+
(0, import_react5.useEffect)(() => {
|
|
8665
10307
|
if (deviceId2 === void 0) return void 0;
|
|
8666
10308
|
let live = true;
|
|
8667
10309
|
setError(null);
|
|
@@ -8705,9 +10347,9 @@ function DevicePicker({
|
|
|
8705
10347
|
const devices = useDeviceSnapshot();
|
|
8706
10348
|
const list = devices?.devices[kind] ?? [];
|
|
8707
10349
|
if (list.length === 0) return null;
|
|
8708
|
-
return /* @__PURE__ */ (0,
|
|
8709
|
-
/* @__PURE__ */ (0,
|
|
8710
|
-
/* @__PURE__ */ (0,
|
|
10350
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__field", children: [
|
|
10351
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__field-label", children: label }),
|
|
10352
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8711
10353
|
"select",
|
|
8712
10354
|
{
|
|
8713
10355
|
className: "mx-meet__select",
|
|
@@ -8716,7 +10358,7 @@ function DevicePicker({
|
|
|
8716
10358
|
if (onPick !== void 0) onPick(kind, event.target.value);
|
|
8717
10359
|
else host.devices.select(kind, event.target.value);
|
|
8718
10360
|
},
|
|
8719
|
-
children: list.map((device) => /* @__PURE__ */ (0,
|
|
10361
|
+
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
10362
|
}
|
|
8721
10363
|
)
|
|
8722
10364
|
] });
|
|
@@ -8724,9 +10366,9 @@ function DevicePicker({
|
|
|
8724
10366
|
function MeetingRoom(props) {
|
|
8725
10367
|
const host = useMeetHost();
|
|
8726
10368
|
if (host === null) {
|
|
8727
|
-
return /* @__PURE__ */ (0,
|
|
10369
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InertNotice, { what: "This meeting" }) });
|
|
8728
10370
|
}
|
|
8729
|
-
return /* @__PURE__ */ (0,
|
|
10371
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MeetingRoomBody, { ...props, host });
|
|
8730
10372
|
}
|
|
8731
10373
|
function MeetingRoomBody({
|
|
8732
10374
|
roomName,
|
|
@@ -8741,25 +10383,25 @@ function MeetingRoomBody({
|
|
|
8741
10383
|
const isHost = useIsHost();
|
|
8742
10384
|
const elapsed = useElapsed(snapshot?.meeting?.startedAt ?? null);
|
|
8743
10385
|
const phase = snapshot?.phase ?? "idle";
|
|
8744
|
-
(0,
|
|
10386
|
+
(0, import_react5.useEffect)(() => {
|
|
8745
10387
|
host.meetings.watch(roomName);
|
|
8746
10388
|
}, [host, roomName]);
|
|
8747
|
-
(0,
|
|
10389
|
+
(0, import_react5.useEffect)(() => {
|
|
8748
10390
|
if (given === void 0) return;
|
|
8749
10391
|
if (host.store.snapshot().meeting !== null) return;
|
|
8750
10392
|
host.store.patch({ meeting: given, locked: given.locked });
|
|
8751
10393
|
}, [host, given]);
|
|
8752
10394
|
const watchedId = meetingId ?? snapshot?.meeting?.id ?? null;
|
|
8753
|
-
(0,
|
|
10395
|
+
(0, import_react5.useEffect)(() => {
|
|
8754
10396
|
if (watchedId === null) return;
|
|
8755
10397
|
host.meetings.watchMeeting(asMeetingId(watchedId));
|
|
8756
10398
|
}, [host, watchedId]);
|
|
8757
10399
|
const record = snapshot?.meeting ?? given ?? null;
|
|
8758
10400
|
if (hasEnded(record) && phase !== "connected" && phase !== "reconnecting") {
|
|
8759
|
-
return /* @__PURE__ */ (0,
|
|
10401
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MeetingRecordView, { meeting: record });
|
|
8760
10402
|
}
|
|
8761
10403
|
if (phase === "idle" || phase === "failed" || phase === "left") {
|
|
8762
|
-
return /* @__PURE__ */ (0,
|
|
10404
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8763
10405
|
PreJoin,
|
|
8764
10406
|
{
|
|
8765
10407
|
roomName,
|
|
@@ -8769,42 +10411,42 @@ function MeetingRoomBody({
|
|
|
8769
10411
|
) });
|
|
8770
10412
|
}
|
|
8771
10413
|
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,
|
|
10414
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet mx-meet--lobby", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(WaitingRoom, { roomName, host }) });
|
|
10415
|
+
}
|
|
10416
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet", children: [
|
|
10417
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ConsentNotice, {}),
|
|
10418
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(AttendanceNotice, {}),
|
|
10419
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("header", { className: "mx-meet__header", children: [
|
|
10420
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h1", { className: "mx-meet__title", children: snapshot?.meeting?.title ?? "Meeting" }),
|
|
10421
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__meta", children: [
|
|
8780
10422
|
participantSummary(snapshot?.participants ?? []),
|
|
8781
10423
|
elapsed > 0 ? ` \xB7 ${(0, import_format3.formatDurationMs)(elapsed)}` : ""
|
|
8782
10424
|
] }),
|
|
8783
|
-
/* @__PURE__ */ (0,
|
|
8784
|
-
snapshot?.locked === true ? /* @__PURE__ */ (0,
|
|
8785
|
-
/* @__PURE__ */ (0,
|
|
10425
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RecordingIndicator, {}),
|
|
10426
|
+
snapshot?.locked === true ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__badge", children: [
|
|
10427
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(LockIcon, { width: 12, height: 12 }),
|
|
8786
10428
|
" Locked"
|
|
8787
10429
|
] }) : null,
|
|
8788
|
-
headerControls !== void 0 && headerControls !== null ? /* @__PURE__ */ (0,
|
|
8789
|
-
isHost ? /* @__PURE__ */ (0,
|
|
10430
|
+
headerControls !== void 0 && headerControls !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__header-controls", "data-meet-header-controls": "", children: headerControls }) : null,
|
|
10431
|
+
isHost ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HostMenu, {}) : null
|
|
8790
10432
|
] }),
|
|
8791
|
-
phase === "reconnecting" ? /* @__PURE__ */ (0,
|
|
8792
|
-
/* @__PURE__ */ (0,
|
|
8793
|
-
/* @__PURE__ */ (0,
|
|
8794
|
-
/* @__PURE__ */ (0,
|
|
10433
|
+
phase === "reconnecting" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__banner", role: "status", children: "Reconnecting\u2026" }) : null,
|
|
10434
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Stage, {}),
|
|
10435
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Captions, {}),
|
|
10436
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ControlBar, { ...onLeave !== void 0 ? { onLeave } : {} })
|
|
8795
10437
|
] });
|
|
8796
10438
|
}
|
|
8797
10439
|
function WaitingRoom({ roomName, host }) {
|
|
8798
|
-
const knocked = (0,
|
|
8799
|
-
(0,
|
|
10440
|
+
const knocked = (0, import_react5.useRef)(false);
|
|
10441
|
+
(0, import_react5.useEffect)(() => {
|
|
8800
10442
|
if (knocked.current) return;
|
|
8801
10443
|
knocked.current = true;
|
|
8802
10444
|
host.meetings.knock(roomName);
|
|
8803
10445
|
}, [host, roomName]);
|
|
8804
|
-
return /* @__PURE__ */ (0,
|
|
8805
|
-
/* @__PURE__ */ (0,
|
|
8806
|
-
/* @__PURE__ */ (0,
|
|
8807
|
-
/* @__PURE__ */ (0,
|
|
10446
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__waiting", children: [
|
|
10447
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Avatar, { name: host.identity.displayName, url: host.identity.avatarUrl, size: 72 }),
|
|
10448
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h1", { className: "mx-meet__prejoin-title", children: "Waiting for the host to let you in" }),
|
|
10449
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__empty-body", children: [
|
|
8808
10450
|
"You are in the waiting room as ",
|
|
8809
10451
|
host.identity.displayName,
|
|
8810
10452
|
". You will join automatically once you are admitted."
|
|
@@ -8815,10 +10457,10 @@ function HostMenu() {
|
|
|
8815
10457
|
const host = useRequiredMeetHost();
|
|
8816
10458
|
const snapshot = useMeetSnapshot();
|
|
8817
10459
|
const end = useEndMeeting();
|
|
8818
|
-
const [confirmingEnd, setConfirmingEnd] = (0,
|
|
10460
|
+
const [confirmingEnd, setConfirmingEnd] = (0, import_react5.useState)(false);
|
|
8819
10461
|
const locked = snapshot?.locked === true;
|
|
8820
|
-
return /* @__PURE__ */ (0,
|
|
8821
|
-
/* @__PURE__ */ (0,
|
|
10462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__host-menu", children: [
|
|
10463
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8822
10464
|
"button",
|
|
8823
10465
|
{
|
|
8824
10466
|
type: "button",
|
|
@@ -8829,9 +10471,9 @@ function HostMenu() {
|
|
|
8829
10471
|
children: locked ? "Unlock meeting" : "Lock meeting"
|
|
8830
10472
|
}
|
|
8831
10473
|
),
|
|
8832
|
-
end.canEnd ? confirmingEnd ? /* @__PURE__ */ (0,
|
|
8833
|
-
/* @__PURE__ */ (0,
|
|
8834
|
-
/* @__PURE__ */ (0,
|
|
10474
|
+
end.canEnd ? confirmingEnd ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__confirm", role: "group", "aria-label": "End this meeting?", children: [
|
|
10475
|
+
/* @__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." }),
|
|
10476
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8835
10477
|
"button",
|
|
8836
10478
|
{
|
|
8837
10479
|
type: "button",
|
|
@@ -8843,7 +10485,7 @@ function HostMenu() {
|
|
|
8843
10485
|
children: "End it"
|
|
8844
10486
|
}
|
|
8845
10487
|
),
|
|
8846
|
-
/* @__PURE__ */ (0,
|
|
10488
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8847
10489
|
"button",
|
|
8848
10490
|
{
|
|
8849
10491
|
type: "button",
|
|
@@ -8852,7 +10494,7 @@ function HostMenu() {
|
|
|
8852
10494
|
children: "Keep it running"
|
|
8853
10495
|
}
|
|
8854
10496
|
)
|
|
8855
|
-
] }) : /* @__PURE__ */ (0,
|
|
10497
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8856
10498
|
"button",
|
|
8857
10499
|
{
|
|
8858
10500
|
type: "button",
|
|
@@ -8861,7 +10503,7 @@ function HostMenu() {
|
|
|
8861
10503
|
children: end.ending ? "Ending\u2026" : "End meeting for everyone"
|
|
8862
10504
|
}
|
|
8863
10505
|
) : null,
|
|
8864
|
-
end.notice !== null ? /* @__PURE__ */ (0,
|
|
10506
|
+
end.notice !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__notice", role: "status", children: end.notice }) : null
|
|
8865
10507
|
] });
|
|
8866
10508
|
}
|
|
8867
10509
|
function CallButton({
|
|
@@ -8871,7 +10513,7 @@ function CallButton({
|
|
|
8871
10513
|
}) {
|
|
8872
10514
|
const calls = useCalls();
|
|
8873
10515
|
if (!calls.canCall) return null;
|
|
8874
|
-
return /* @__PURE__ */ (0,
|
|
10516
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8875
10517
|
"button",
|
|
8876
10518
|
{
|
|
8877
10519
|
type: "button",
|
|
@@ -8880,55 +10522,55 @@ function CallButton({
|
|
|
8880
10522
|
void calls.call([person.userId], mode);
|
|
8881
10523
|
},
|
|
8882
10524
|
"aria-label": `Call ${person.displayName}`,
|
|
8883
|
-
children: children ?? /* @__PURE__ */ (0,
|
|
10525
|
+
children: children ?? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PhoneIcon, { width: 18, height: 18 })
|
|
8884
10526
|
}
|
|
8885
10527
|
);
|
|
8886
10528
|
}
|
|
8887
10529
|
function IncomingCallHost() {
|
|
8888
10530
|
const calls = useCalls();
|
|
8889
10531
|
if (calls.incoming.length === 0) return null;
|
|
8890
|
-
return /* @__PURE__ */ (0,
|
|
10532
|
+
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
10533
|
}
|
|
8892
10534
|
function IncomingCallCard({ invite }) {
|
|
8893
10535
|
const calls = useCalls();
|
|
8894
|
-
return /* @__PURE__ */ (0,
|
|
8895
|
-
/* @__PURE__ */ (0,
|
|
8896
|
-
/* @__PURE__ */ (0,
|
|
8897
|
-
/* @__PURE__ */ (0,
|
|
8898
|
-
/* @__PURE__ */ (0,
|
|
10536
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__ringing", role: "alertdialog", "aria-label": "Incoming call", children: [
|
|
10537
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Avatar, { name: invite.callerName, url: invite.callerAvatarUrl, size: 56 }),
|
|
10538
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__ringing-text", children: [
|
|
10539
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: invite.callerName }),
|
|
10540
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: invite.mode === "video" ? "Incoming video call" : "Incoming call" })
|
|
8899
10541
|
] }),
|
|
8900
|
-
/* @__PURE__ */ (0,
|
|
8901
|
-
/* @__PURE__ */ (0,
|
|
8902
|
-
invite.mode === "video" ? /* @__PURE__ */ (0,
|
|
10542
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__ringing-actions", children: [
|
|
10543
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ControlButton, { label: "Decline", danger: true, onClick: () => void calls.decline(invite), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PhoneOffIcon, {}) }),
|
|
10544
|
+
invite.mode === "video" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8903
10545
|
ControlButton,
|
|
8904
10546
|
{
|
|
8905
10547
|
label: "Accept without video",
|
|
8906
10548
|
onClick: () => void calls.accept({ ...invite, mode: "audio" }),
|
|
8907
|
-
children: /* @__PURE__ */ (0,
|
|
10549
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CameraOffIcon, {})
|
|
8908
10550
|
}
|
|
8909
10551
|
) : null,
|
|
8910
|
-
/* @__PURE__ */ (0,
|
|
10552
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ControlButton, { label: "Accept", onClick: () => void calls.accept(invite), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PhoneIcon, {}) })
|
|
8911
10553
|
] })
|
|
8912
10554
|
] });
|
|
8913
10555
|
}
|
|
8914
10556
|
function ScheduleMeeting(props) {
|
|
8915
10557
|
const host = useMeetHost();
|
|
8916
|
-
if (host === null) return /* @__PURE__ */ (0,
|
|
8917
|
-
return /* @__PURE__ */ (0,
|
|
10558
|
+
if (host === null) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InertNotice, { what: "Scheduling a meeting" });
|
|
10559
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ScheduleMeetingBody, { ...props, host });
|
|
8918
10560
|
}
|
|
8919
10561
|
function ScheduleMeetingBody({
|
|
8920
10562
|
appBaseUrl,
|
|
8921
10563
|
onScheduled,
|
|
8922
10564
|
host
|
|
8923
10565
|
}) {
|
|
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,
|
|
10566
|
+
const [title, setTitle] = (0, import_react5.useState)("");
|
|
10567
|
+
const [when2, setWhen] = (0, import_react5.useState)("");
|
|
10568
|
+
const [kind, setKind] = (0, import_react5.useState)("scheduled");
|
|
10569
|
+
const [busy, setBusy] = (0, import_react5.useState)(false);
|
|
10570
|
+
const [link, setLink] = (0, import_react5.useState)(null);
|
|
10571
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
10572
|
+
const disabled = (0, import_react5.useMemo)(() => title.trim().length === 0 || busy, [title, busy]);
|
|
10573
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8932
10574
|
"form",
|
|
8933
10575
|
{
|
|
8934
10576
|
className: "mx-meet__schedule",
|
|
@@ -8953,9 +10595,9 @@ function ScheduleMeetingBody({
|
|
|
8953
10595
|
}).finally(() => setBusy(false));
|
|
8954
10596
|
},
|
|
8955
10597
|
children: [
|
|
8956
|
-
/* @__PURE__ */ (0,
|
|
8957
|
-
/* @__PURE__ */ (0,
|
|
8958
|
-
/* @__PURE__ */ (0,
|
|
10598
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__field", children: [
|
|
10599
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__field-label", children: "Title" }),
|
|
10600
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8959
10601
|
"input",
|
|
8960
10602
|
{
|
|
8961
10603
|
className: "mx-meet__input",
|
|
@@ -8965,9 +10607,9 @@ function ScheduleMeetingBody({
|
|
|
8965
10607
|
}
|
|
8966
10608
|
)
|
|
8967
10609
|
] }),
|
|
8968
|
-
/* @__PURE__ */ (0,
|
|
8969
|
-
/* @__PURE__ */ (0,
|
|
8970
|
-
/* @__PURE__ */ (0,
|
|
10610
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__field", children: [
|
|
10611
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__field-label", children: "When" }),
|
|
10612
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8971
10613
|
"input",
|
|
8972
10614
|
{
|
|
8973
10615
|
className: "mx-meet__input",
|
|
@@ -8977,27 +10619,27 @@ function ScheduleMeetingBody({
|
|
|
8977
10619
|
}
|
|
8978
10620
|
)
|
|
8979
10621
|
] }),
|
|
8980
|
-
/* @__PURE__ */ (0,
|
|
8981
|
-
/* @__PURE__ */ (0,
|
|
8982
|
-
/* @__PURE__ */ (0,
|
|
10622
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__field", children: [
|
|
10623
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__field-label", children: "Repeats" }),
|
|
10624
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8983
10625
|
"select",
|
|
8984
10626
|
{
|
|
8985
10627
|
className: "mx-meet__select",
|
|
8986
10628
|
value: kind,
|
|
8987
10629
|
onChange: (event) => setKind(event.target.value),
|
|
8988
10630
|
children: [
|
|
8989
|
-
/* @__PURE__ */ (0,
|
|
8990
|
-
/* @__PURE__ */ (0,
|
|
10631
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "scheduled", children: "Once" }),
|
|
10632
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "recurring", children: "Recurring \u2014 one link, every time" })
|
|
8991
10633
|
]
|
|
8992
10634
|
}
|
|
8993
10635
|
)
|
|
8994
10636
|
] }),
|
|
8995
|
-
/* @__PURE__ */ (0,
|
|
8996
|
-
link !== null ? /* @__PURE__ */ (0,
|
|
8997
|
-
/* @__PURE__ */ (0,
|
|
8998
|
-
/* @__PURE__ */ (0,
|
|
10637
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "submit", className: "mx-meet__primary", disabled, children: busy ? "Creating\u2026" : "Create meeting" }),
|
|
10638
|
+
link !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__link-out", children: [
|
|
10639
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: "Anyone with this link can join \u2014 no account needed." }),
|
|
10640
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("code", { children: link })
|
|
8999
10641
|
] }) : null,
|
|
9000
|
-
error !== null ? /* @__PURE__ */ (0,
|
|
10642
|
+
error !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__error", children: error }) : null
|
|
9001
10643
|
]
|
|
9002
10644
|
}
|
|
9003
10645
|
);
|
|
@@ -9006,7 +10648,7 @@ function ReactionOverlay({
|
|
|
9006
10648
|
reactions
|
|
9007
10649
|
}) {
|
|
9008
10650
|
if (reactions.length === 0) return null;
|
|
9009
|
-
return /* @__PURE__ */ (0,
|
|
10651
|
+
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
10652
|
}
|
|
9011
10653
|
function GuestRecordAccessControl({
|
|
9012
10654
|
meeting
|
|
@@ -9018,11 +10660,11 @@ function GuestRecordAccessControl({
|
|
|
9018
10660
|
const isHost = inRoomHost || viewerId !== null && meeting.hostUserId === viewerId;
|
|
9019
10661
|
if (host === null || !isHost) return null;
|
|
9020
10662
|
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,
|
|
10663
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "What guests may read", children: [
|
|
10664
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__record-section-title", children: "What guests may read" }),
|
|
10665
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__field", children: [
|
|
10666
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__field-label", children: "People who attended by link, without an account" }),
|
|
10667
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9026
10668
|
"select",
|
|
9027
10669
|
{
|
|
9028
10670
|
className: "mx-meet__select",
|
|
@@ -9033,18 +10675,18 @@ function GuestRecordAccessControl({
|
|
|
9033
10675
|
event.target.value
|
|
9034
10676
|
);
|
|
9035
10677
|
},
|
|
9036
|
-
children: GUEST_RECORD_ACCESS_CHOICES.map((choice) => /* @__PURE__ */ (0,
|
|
10678
|
+
children: GUEST_RECORD_ACCESS_CHOICES.map((choice) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: choice, children: guestRecordAccessLabel(choice) }, choice))
|
|
9037
10679
|
}
|
|
9038
10680
|
)
|
|
9039
10681
|
] }),
|
|
9040
|
-
/* @__PURE__ */ (0,
|
|
10682
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__panel-note", children: [
|
|
9041
10683
|
guestRecordAccessExplanation(access.setting),
|
|
9042
10684
|
resolved
|
|
9043
10685
|
] }),
|
|
9044
|
-
access.saving ? /* @__PURE__ */ (0,
|
|
9045
|
-
access.error !== null ? /* @__PURE__ */ (0,
|
|
9046
|
-
/* @__PURE__ */ (0,
|
|
9047
|
-
/* @__PURE__ */ (0,
|
|
10686
|
+
access.saving ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", role: "status", children: "Saving what guests may read\u2026" }) : null,
|
|
10687
|
+
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: [
|
|
10688
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-reason", children: access.error.message }),
|
|
10689
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-remedy", children: access.error.remedy })
|
|
9048
10690
|
] }) : null
|
|
9049
10691
|
] });
|
|
9050
10692
|
}
|
|
@@ -9054,9 +10696,9 @@ function MeetingRecordView({
|
|
|
9054
10696
|
}) {
|
|
9055
10697
|
const host = useMeetHost();
|
|
9056
10698
|
if (host === null) {
|
|
9057
|
-
return /* @__PURE__ */ (0,
|
|
10699
|
+
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
10700
|
}
|
|
9059
|
-
return /* @__PURE__ */ (0,
|
|
10701
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MeetingRecordBody, { meeting, ...onRejoin !== void 0 ? { onRejoin } : {} });
|
|
9060
10702
|
}
|
|
9061
10703
|
function MeetingRecordBody({
|
|
9062
10704
|
meeting,
|
|
@@ -9064,19 +10706,19 @@ function MeetingRecordBody({
|
|
|
9064
10706
|
}) {
|
|
9065
10707
|
const host = useRequiredMeetHost();
|
|
9066
10708
|
const record = useMeetingRecord(meeting);
|
|
9067
|
-
const [question, setQuestion] = (0,
|
|
9068
|
-
const [tab, setTab] = (0,
|
|
10709
|
+
const [question, setQuestion] = (0, import_react5.useState)("");
|
|
10710
|
+
const [tab, setTab] = (0, import_react5.useState)("summary");
|
|
9069
10711
|
if (record.failure !== null) {
|
|
9070
|
-
return /* @__PURE__ */ (0,
|
|
9071
|
-
/* @__PURE__ */ (0,
|
|
9072
|
-
/* @__PURE__ */ (0,
|
|
9073
|
-
/* @__PURE__ */ (0,
|
|
10712
|
+
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: [
|
|
10713
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-title", children: "This meeting record could not be opened" }),
|
|
10714
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-body", children: record.failure.message }),
|
|
10715
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-body", children: record.failure.remedy })
|
|
9074
10716
|
] }) });
|
|
9075
10717
|
}
|
|
9076
10718
|
if (record.loading || record.record === null) {
|
|
9077
|
-
return /* @__PURE__ */ (0,
|
|
9078
|
-
/* @__PURE__ */ (0,
|
|
9079
|
-
/* @__PURE__ */ (0,
|
|
10719
|
+
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: [
|
|
10720
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-title", children: "Opening the meeting record\u2026" }),
|
|
10721
|
+
/* @__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
10722
|
] }) });
|
|
9081
10723
|
}
|
|
9082
10724
|
const bundle = record.record;
|
|
@@ -9095,44 +10737,44 @@ function MeetingRecordBody({
|
|
|
9095
10737
|
);
|
|
9096
10738
|
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
10739
|
if (entirelyRestricted) {
|
|
9098
|
-
return /* @__PURE__ */ (0,
|
|
9099
|
-
/* @__PURE__ */ (0,
|
|
9100
|
-
/* @__PURE__ */ (0,
|
|
9101
|
-
/* @__PURE__ */ (0,
|
|
9102
|
-
/* @__PURE__ */ (0,
|
|
9103
|
-
onRejoin !== void 0 ? /* @__PURE__ */ (0,
|
|
10740
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet mx-meet--record", children: [
|
|
10741
|
+
/* @__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: [
|
|
10742
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-eyebrow", children: "Meeting record" }),
|
|
10743
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h1", { className: "mx-meet__record-title", children: meeting.title }),
|
|
10744
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-when", children: meetingWhen(meeting) }),
|
|
10745
|
+
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
10746
|
] }) }),
|
|
9105
|
-
/* @__PURE__ */ (0,
|
|
9106
|
-
/* @__PURE__ */ (0,
|
|
9107
|
-
/* @__PURE__ */ (0,
|
|
9108
|
-
/* @__PURE__ */ (0,
|
|
10747
|
+
/* @__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: [
|
|
10748
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-access-title", children: "About this record" }),
|
|
10749
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-access-message", children: notice2.message }),
|
|
10750
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-access-remedy", children: notice2.remedy })
|
|
9109
10751
|
] }, notice2.parts.join("-"))) })
|
|
9110
10752
|
] });
|
|
9111
10753
|
}
|
|
9112
|
-
return /* @__PURE__ */ (0,
|
|
9113
|
-
/* @__PURE__ */ (0,
|
|
9114
|
-
/* @__PURE__ */ (0,
|
|
9115
|
-
/* @__PURE__ */ (0,
|
|
9116
|
-
/* @__PURE__ */ (0,
|
|
9117
|
-
onRejoin !== void 0 ? /* @__PURE__ */ (0,
|
|
10754
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet mx-meet--record", children: [
|
|
10755
|
+
/* @__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: [
|
|
10756
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-eyebrow", children: "Meeting record" }),
|
|
10757
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h1", { className: "mx-meet__record-title", children: meeting.title }),
|
|
10758
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-when", children: meetingWhen(meeting) }),
|
|
10759
|
+
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
10760
|
] }) }),
|
|
9119
|
-
/* @__PURE__ */ (0,
|
|
9120
|
-
restrictionNotices.map((notice2) => /* @__PURE__ */ (0,
|
|
9121
|
-
/* @__PURE__ */ (0,
|
|
9122
|
-
/* @__PURE__ */ (0,
|
|
9123
|
-
/* @__PURE__ */ (0,
|
|
10761
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__record-body", children: [
|
|
10762
|
+
restrictionNotices.map((notice2) => /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__record-access", role: "status", children: [
|
|
10763
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-access-title", children: "About this record" }),
|
|
10764
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-access-message", children: notice2.message }),
|
|
10765
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-access-remedy", children: notice2.remedy })
|
|
9124
10766
|
] }, notice2.parts.join("-"))),
|
|
9125
10767
|
attended.length === 0 ? (
|
|
9126
10768
|
/* NOT SILENCE. A refused attendance read used to remove the whole
|
|
9127
10769
|
section, so the reader could not tell "nobody" from "not shown". */
|
|
9128
|
-
/* @__PURE__ */ (0,
|
|
9129
|
-
/* @__PURE__ */ (0,
|
|
9130
|
-
/* @__PURE__ */ (0,
|
|
10770
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Who attended", children: [
|
|
10771
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__record-section-title", children: "Who attended" }),
|
|
10772
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: absenceSentence(bundle, "attendance", "Nobody is recorded as having attended.") })
|
|
9131
10773
|
] })
|
|
9132
|
-
) : /* @__PURE__ */ (0,
|
|
9133
|
-
/* @__PURE__ */ (0,
|
|
9134
|
-
/* @__PURE__ */ (0,
|
|
9135
|
-
/* @__PURE__ */ (0,
|
|
10774
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Who attended", children: [
|
|
10775
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__record-section-title", children: "Who attended" }),
|
|
10776
|
+
/* @__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: [
|
|
10777
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9136
10778
|
Avatar,
|
|
9137
10779
|
{
|
|
9138
10780
|
name: displayNameFor(bundle.names, person.identity, person.displayName),
|
|
@@ -9140,26 +10782,26 @@ function MeetingRecordBody({
|
|
|
9140
10782
|
size: 28
|
|
9141
10783
|
}
|
|
9142
10784
|
),
|
|
9143
|
-
/* @__PURE__ */ (0,
|
|
10785
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__person-name", children: [
|
|
9144
10786
|
displayNameFor(bundle.names, person.identity, person.displayName),
|
|
9145
|
-
person.role === "host" ? /* @__PURE__ */ (0,
|
|
9146
|
-
person.role === "guest" ? /* @__PURE__ */ (0,
|
|
9147
|
-
person.isAgent ? /* @__PURE__ */ (0,
|
|
10787
|
+
person.role === "host" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Host" }) : null,
|
|
10788
|
+
person.role === "guest" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Guest" }) : null,
|
|
10789
|
+
person.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Meeting assistant" }) : null
|
|
9148
10790
|
] })
|
|
9149
10791
|
] }, person.id)) })
|
|
9150
10792
|
] }),
|
|
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,
|
|
10793
|
+
bundle.recording !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__record-section mx-meet__recording-card", "aria-label": "Recording", children: [
|
|
10794
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__record-section-title", children: "Recording" }),
|
|
10795
|
+
fileId !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
10796
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RecordingPlayer, { fileId }),
|
|
10797
|
+
notice !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: notice }) : null
|
|
10798
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: notice ?? "This recording has no file." })
|
|
10799
|
+
] }) : wasRefused(bundle, "recording") ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Recording", children: [
|
|
10800
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__record-section-title", children: "Recording" }),
|
|
10801
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: REFUSED_ABSENCE })
|
|
9160
10802
|
] }) : null,
|
|
9161
|
-
/* @__PURE__ */ (0,
|
|
9162
|
-
/* @__PURE__ */ (0,
|
|
10803
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("nav", { className: "mx-meet__record-tabs", "aria-label": "Meeting record sections", children: [
|
|
10804
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9163
10805
|
"button",
|
|
9164
10806
|
{
|
|
9165
10807
|
type: "button",
|
|
@@ -9169,7 +10811,7 @@ function MeetingRecordBody({
|
|
|
9169
10811
|
children: "Summary & decisions"
|
|
9170
10812
|
}
|
|
9171
10813
|
),
|
|
9172
|
-
/* @__PURE__ */ (0,
|
|
10814
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9173
10815
|
"button",
|
|
9174
10816
|
{
|
|
9175
10817
|
type: "button",
|
|
@@ -9179,7 +10821,7 @@ function MeetingRecordBody({
|
|
|
9179
10821
|
children: "Notes as it happened"
|
|
9180
10822
|
}
|
|
9181
10823
|
),
|
|
9182
|
-
/* @__PURE__ */ (0,
|
|
10824
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9183
10825
|
"button",
|
|
9184
10826
|
{
|
|
9185
10827
|
type: "button",
|
|
@@ -9190,15 +10832,15 @@ function MeetingRecordBody({
|
|
|
9190
10832
|
}
|
|
9191
10833
|
)
|
|
9192
10834
|
] }),
|
|
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,
|
|
10835
|
+
tab === "summary" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
10836
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Summary", children: [
|
|
10837
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__record-section-title", children: "Summary" }),
|
|
10838
|
+
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: [
|
|
10839
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { children: wrapUp.message }),
|
|
10840
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "mx-meet__link", onClick: record.reload, children: "Check again" })
|
|
10841
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", role: wrapUp.state === "failed" ? "alert" : void 0, children: wrapUp.message })
|
|
9200
10842
|
] }),
|
|
9201
|
-
/* @__PURE__ */ (0,
|
|
10843
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9202
10844
|
NoteList,
|
|
9203
10845
|
{
|
|
9204
10846
|
title: "Decisions",
|
|
@@ -9210,7 +10852,7 @@ function MeetingRecordBody({
|
|
|
9210
10852
|
)
|
|
9211
10853
|
}
|
|
9212
10854
|
),
|
|
9213
|
-
/* @__PURE__ */ (0,
|
|
10855
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9214
10856
|
NoteList,
|
|
9215
10857
|
{
|
|
9216
10858
|
title: "Action items",
|
|
@@ -9223,42 +10865,42 @@ function MeetingRecordBody({
|
|
|
9223
10865
|
}
|
|
9224
10866
|
)
|
|
9225
10867
|
] }) : null,
|
|
9226
|
-
tab === "notes" ? /* @__PURE__ */ (0,
|
|
9227
|
-
/* @__PURE__ */ (0,
|
|
9228
|
-
bundle.liveNotes.length === 0 ? /* @__PURE__ */ (0,
|
|
10868
|
+
tab === "notes" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Notes as it happened", children: [
|
|
10869
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__record-section-title", children: "Notes as it happened" }),
|
|
10870
|
+
bundle.liveNotes.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: absenceSentence(
|
|
9229
10871
|
bundle,
|
|
9230
10872
|
"notes",
|
|
9231
10873
|
"No live notes are available for this meeting."
|
|
9232
|
-
) }) : /* @__PURE__ */ (0,
|
|
9233
|
-
note.window !== null ? /* @__PURE__ */ (0,
|
|
10874
|
+
) }) : /* @__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: [
|
|
10875
|
+
note.window !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__badge", children: [
|
|
9234
10876
|
"Window ",
|
|
9235
10877
|
note.window
|
|
9236
10878
|
] }) : null,
|
|
9237
10879
|
note.text
|
|
9238
10880
|
] }, note.id)) })
|
|
9239
10881
|
] }) : null,
|
|
9240
|
-
tab === "transcript" ? /* @__PURE__ */ (0,
|
|
9241
|
-
/* @__PURE__ */ (0,
|
|
10882
|
+
tab === "transcript" ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Transcript", children: [
|
|
10883
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("h2", { className: "mx-meet__record-section-title", children: [
|
|
9242
10884
|
"Transcript",
|
|
9243
|
-
/* @__PURE__ */ (0,
|
|
10885
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__record-count", children: bundle.transcript.length === 1 ? "1 line" : `${bundle.transcript.length} lines` })
|
|
9244
10886
|
] }),
|
|
9245
|
-
blocks.length === 0 ? /* @__PURE__ */ (0,
|
|
10887
|
+
blocks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: absenceSentence(
|
|
9246
10888
|
bundle,
|
|
9247
10889
|
"transcript",
|
|
9248
10890
|
"No transcript is available for this meeting."
|
|
9249
|
-
) }) : /* @__PURE__ */ (0,
|
|
9250
|
-
/* @__PURE__ */ (0,
|
|
10891
|
+
) }) : /* @__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: [
|
|
10892
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__record-speaker", children: [
|
|
9251
10893
|
block.speaker,
|
|
9252
|
-
/* @__PURE__ */ (0,
|
|
10894
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("time", { className: "mx-meet__record-time", dateTime: block.startedAt, children: clockOf(block.startedAt) })
|
|
9253
10895
|
] }),
|
|
9254
|
-
block.lines.map((line) => /* @__PURE__ */ (0,
|
|
10896
|
+
block.lines.map((line) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__record-line", children: line.text }, line.id))
|
|
9255
10897
|
] }, block.id)) })
|
|
9256
10898
|
] }) : null,
|
|
9257
|
-
/* @__PURE__ */ (0,
|
|
9258
|
-
/* @__PURE__ */ (0,
|
|
9259
|
-
/* @__PURE__ */ (0,
|
|
9260
|
-
guestFinishedMeeting ? /* @__PURE__ */ (0,
|
|
9261
|
-
/* @__PURE__ */ (0,
|
|
10899
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(GuestRecordAccessControl, { meeting }),
|
|
10900
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Ask about this meeting", children: [
|
|
10901
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h2", { className: "mx-meet__record-section-title", children: "Ask about this meeting" }),
|
|
10902
|
+
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: [
|
|
10903
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
9262
10904
|
"form",
|
|
9263
10905
|
{
|
|
9264
10906
|
className: "mx-meet__composer",
|
|
@@ -9269,7 +10911,7 @@ function MeetingRecordBody({
|
|
|
9269
10911
|
void record.ask(trimmed);
|
|
9270
10912
|
},
|
|
9271
10913
|
children: [
|
|
9272
|
-
/* @__PURE__ */ (0,
|
|
10914
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9273
10915
|
"input",
|
|
9274
10916
|
{
|
|
9275
10917
|
className: "mx-meet__input",
|
|
@@ -9279,7 +10921,7 @@ function MeetingRecordBody({
|
|
|
9279
10921
|
"aria-label": "Ask about this meeting"
|
|
9280
10922
|
}
|
|
9281
10923
|
),
|
|
9282
|
-
/* @__PURE__ */ (0,
|
|
10924
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9283
10925
|
"button",
|
|
9284
10926
|
{
|
|
9285
10927
|
type: "submit",
|
|
@@ -9291,8 +10933,8 @@ function MeetingRecordBody({
|
|
|
9291
10933
|
]
|
|
9292
10934
|
}
|
|
9293
10935
|
),
|
|
9294
|
-
record.answer !== null ? /* @__PURE__ */ (0,
|
|
9295
|
-
record.coverage !== null ? /* @__PURE__ */ (0,
|
|
10936
|
+
record.answer !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__answer", children: record.answer }) : null,
|
|
10937
|
+
record.coverage !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__coverage", children: [
|
|
9296
10938
|
"Answered from ",
|
|
9297
10939
|
record.coverage.segmentsUsed,
|
|
9298
10940
|
" of ",
|
|
@@ -9303,9 +10945,9 @@ function MeetingRecordBody({
|
|
|
9303
10945
|
record.coverage.truncated ? " (the oldest were left out)" : "",
|
|
9304
10946
|
"."
|
|
9305
10947
|
] }) : null,
|
|
9306
|
-
record.askError !== null ? /* @__PURE__ */ (0,
|
|
9307
|
-
/* @__PURE__ */ (0,
|
|
9308
|
-
/* @__PURE__ */ (0,
|
|
10948
|
+
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: [
|
|
10949
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-reason", children: record.askError.message }),
|
|
10950
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-remedy", children: record.askError.remedy })
|
|
9309
10951
|
] }) : null
|
|
9310
10952
|
] })
|
|
9311
10953
|
] })
|
|
@@ -9316,21 +10958,21 @@ var STREAM_REFUSED = "Streaming playback did not start, so this recording was do
|
|
|
9316
10958
|
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
10959
|
function RecordingPlayer(props) {
|
|
9318
10960
|
const host = useMeetHost();
|
|
9319
|
-
if (host === null) return /* @__PURE__ */ (0,
|
|
9320
|
-
return /* @__PURE__ */ (0,
|
|
10961
|
+
if (host === null) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InertNotice, { what: "This recording" });
|
|
10962
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RecordingPlayerBody, { ...props, host });
|
|
9321
10963
|
}
|
|
9322
10964
|
function RecordingPlayerBody({ fileId, host }) {
|
|
9323
|
-
const [media, setMedia] = (0,
|
|
9324
|
-
const [loading, setLoading] = (0,
|
|
9325
|
-
const [error, setError] = (0,
|
|
9326
|
-
(0,
|
|
10965
|
+
const [media, setMedia] = (0, import_react5.useState)(null);
|
|
10966
|
+
const [loading, setLoading] = (0, import_react5.useState)(false);
|
|
10967
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
10968
|
+
(0, import_react5.useEffect)(() => {
|
|
9327
10969
|
if (media === null || media.kind !== "bytes") return void 0;
|
|
9328
10970
|
const url = media.url;
|
|
9329
10971
|
return () => URL.revokeObjectURL(url);
|
|
9330
10972
|
}, [media]);
|
|
9331
10973
|
if (media !== null) {
|
|
9332
|
-
return /* @__PURE__ */ (0,
|
|
9333
|
-
/* @__PURE__ */ (0,
|
|
10974
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__record-section", children: [
|
|
10975
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9334
10976
|
"video",
|
|
9335
10977
|
{
|
|
9336
10978
|
className: "mx-meet__record-player",
|
|
@@ -9372,15 +11014,15 @@ function RecordingPlayerBody({ fileId, host }) {
|
|
|
9372
11014
|
}
|
|
9373
11015
|
}
|
|
9374
11016
|
),
|
|
9375
|
-
media.fallbackReason !== null ? /* @__PURE__ */ (0,
|
|
11017
|
+
media.fallbackReason !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: media.fallbackReason }) : null
|
|
9376
11018
|
] });
|
|
9377
11019
|
}
|
|
9378
|
-
return /* @__PURE__ */ (0,
|
|
9379
|
-
error !== null ? /* @__PURE__ */ (0,
|
|
9380
|
-
/* @__PURE__ */ (0,
|
|
9381
|
-
/* @__PURE__ */ (0,
|
|
11020
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__record-section", children: [
|
|
11021
|
+
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: [
|
|
11022
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-reason", children: error.message }),
|
|
11023
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__refusal-remedy", children: error.remedy })
|
|
9382
11024
|
] }) : null,
|
|
9383
|
-
/* @__PURE__ */ (0,
|
|
11025
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9384
11026
|
"button",
|
|
9385
11027
|
{
|
|
9386
11028
|
type: "button",
|
|
@@ -9416,35 +11058,35 @@ function clockOf(iso) {
|
|
|
9416
11058
|
function MeetingList({ baseUrl }) {
|
|
9417
11059
|
const host = useMeetHost();
|
|
9418
11060
|
const list = useMeetings();
|
|
9419
|
-
if (host === null) return /* @__PURE__ */ (0,
|
|
11061
|
+
if (host === null) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InertNotice, { what: "Your meetings" });
|
|
9420
11062
|
if (list.failure !== null) {
|
|
9421
|
-
return /* @__PURE__ */ (0,
|
|
9422
|
-
/* @__PURE__ */ (0,
|
|
9423
|
-
/* @__PURE__ */ (0,
|
|
9424
|
-
/* @__PURE__ */ (0,
|
|
11063
|
+
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: [
|
|
11064
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-title", children: "Your meetings could not be listed" }),
|
|
11065
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-body", children: list.failure.message }),
|
|
11066
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-body", children: list.failure.remedy })
|
|
9425
11067
|
] });
|
|
9426
11068
|
}
|
|
9427
11069
|
if (list.loading) {
|
|
9428
|
-
return /* @__PURE__ */ (0,
|
|
11070
|
+
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
11071
|
}
|
|
9430
11072
|
if (list.meetings.length === 0) {
|
|
9431
|
-
return /* @__PURE__ */ (0,
|
|
9432
|
-
/* @__PURE__ */ (0,
|
|
9433
|
-
/* @__PURE__ */ (0,
|
|
11073
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__empty", role: "status", children: [
|
|
11074
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-title", children: "No meetings yet" }),
|
|
11075
|
+
/* @__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
11076
|
] });
|
|
9435
11077
|
}
|
|
9436
11078
|
const origin = baseUrl ?? (typeof window === "undefined" ? "" : window.location.origin);
|
|
9437
|
-
return /* @__PURE__ */ (0,
|
|
11079
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: "mx-meet-list", children: list.meetings.map((meeting) => {
|
|
9438
11080
|
const ended = meeting.endedAt !== null;
|
|
9439
|
-
return /* @__PURE__ */ (0,
|
|
9440
|
-
/* @__PURE__ */ (0,
|
|
9441
|
-
/* @__PURE__ */ (0,
|
|
11081
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { className: "mx-meet-list__row", children: [
|
|
11082
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet-list__main", children: [
|
|
11083
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet-list__title", children: [
|
|
9442
11084
|
meeting.title,
|
|
9443
|
-
ended ? /* @__PURE__ */ (0,
|
|
11085
|
+
ended ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Ended" }) : null
|
|
9444
11086
|
] }),
|
|
9445
|
-
/* @__PURE__ */ (0,
|
|
11087
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet-list__when", children: meetingWhen(meeting) })
|
|
9446
11088
|
] }),
|
|
9447
|
-
/* @__PURE__ */ (0,
|
|
11089
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("a", { className: "mx-meet-list__action", href: meetingLink(origin, meeting.slug), children: ended ? "Open the record" : "Join" })
|
|
9448
11090
|
] }, meeting.id);
|
|
9449
11091
|
}) });
|
|
9450
11092
|
}
|