@ai-matrx/meet 0.7.9 → 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 +51 -0
- package/dist/index.cjs +1917 -1311
- 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 +1917 -1311
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +2360 -669
- 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 +2361 -670
- package/dist/react.js.map +1 -1
- package/dist/styles.css +293 -0
- package/dist/tokens.css +2 -0
- package/package.json +1 -1
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
|
}
|
|
@@ -4600,6 +5167,15 @@ function createLiveKitDriver(handlers, options = {}) {
|
|
|
4600
5167
|
handlers.participants([local, ...remotes]);
|
|
4601
5168
|
};
|
|
4602
5169
|
projectRoster = roster;
|
|
5170
|
+
created.on(RoomEvent.TrackSubscribed, (track) => {
|
|
5171
|
+
if (track.kind !== Track.Kind.Audio || typeof document === "undefined") return;
|
|
5172
|
+
const element = track.attach();
|
|
5173
|
+
element.setAttribute("data-mx-meet-audio", "");
|
|
5174
|
+
audioSink().appendChild(element);
|
|
5175
|
+
}).on(RoomEvent.TrackUnsubscribed, (track) => {
|
|
5176
|
+
if (track.kind !== Track.Kind.Audio) return;
|
|
5177
|
+
for (const element of track.detach()) element.remove();
|
|
5178
|
+
});
|
|
4603
5179
|
created.on(RoomEvent.ParticipantConnected, roster).on(RoomEvent.ParticipantDisconnected, roster).on(RoomEvent.TrackSubscribed, roster).on(RoomEvent.TrackUnsubscribed, roster).on(RoomEvent.TrackMuted, roster).on(RoomEvent.TrackUnmuted, roster).on(RoomEvent.LocalTrackPublished, roster).on(RoomEvent.LocalTrackUnpublished, roster).on(RoomEvent.ParticipantNameChanged, roster).on(RoomEvent.ParticipantAttributesChanged, roster).on(RoomEvent.ParticipantMetadataChanged, roster).on(RoomEvent.RoomMetadataChanged, (metadata) => {
|
|
4604
5180
|
handlers.roomMetadata?.(metadata ?? "");
|
|
4605
5181
|
}).on(RoomEvent.ActiveSpeakersChanged, (speakers) => {
|
|
@@ -4615,6 +5191,8 @@ function createLiveKitDriver(handlers, options = {}) {
|
|
|
4615
5191
|
participant?.identity ?? null
|
|
4616
5192
|
);
|
|
4617
5193
|
}).on(RoomEvent.Disconnected, (reason) => {
|
|
5194
|
+
audioContainer?.remove();
|
|
5195
|
+
audioContainer = null;
|
|
4618
5196
|
handlers.disconnected(reason === void 0 ? null : String(reason));
|
|
4619
5197
|
});
|
|
4620
5198
|
try {
|
|
@@ -4656,10 +5234,26 @@ function createLiveKitDriver(handlers, options = {}) {
|
|
|
4656
5234
|
microphone: Track.Source.Microphone,
|
|
4657
5235
|
screen: Track.Source.ScreenShare
|
|
4658
5236
|
};
|
|
5237
|
+
trackEvents = {
|
|
5238
|
+
subscribed: RoomEvent.TrackSubscribed,
|
|
5239
|
+
localPublished: RoomEvent.LocalTrackPublished
|
|
5240
|
+
};
|
|
4659
5241
|
room = created;
|
|
4660
5242
|
return created;
|
|
4661
5243
|
}
|
|
4662
5244
|
let sources = null;
|
|
5245
|
+
let trackEvents = null;
|
|
5246
|
+
let audioContainer = null;
|
|
5247
|
+
function audioSink() {
|
|
5248
|
+
if (audioContainer !== null && audioContainer.isConnected) return audioContainer;
|
|
5249
|
+
const container = document.createElement("div");
|
|
5250
|
+
container.setAttribute("data-mx-meet-audio-sink", "");
|
|
5251
|
+
container.setAttribute("aria-hidden", "true");
|
|
5252
|
+
container.style.display = "none";
|
|
5253
|
+
document.body.appendChild(container);
|
|
5254
|
+
audioContainer = container;
|
|
5255
|
+
return container;
|
|
5256
|
+
}
|
|
4663
5257
|
function requireRoom(operation) {
|
|
4664
5258
|
if (room === null) {
|
|
4665
5259
|
throw new MeetError(
|
|
@@ -4690,6 +5284,8 @@ function createLiveKitDriver(handlers, options = {}) {
|
|
|
4690
5284
|
} catch {
|
|
4691
5285
|
}
|
|
4692
5286
|
projectRoster = null;
|
|
5287
|
+
audioContainer?.remove();
|
|
5288
|
+
audioContainer = null;
|
|
4693
5289
|
await target.disconnect();
|
|
4694
5290
|
},
|
|
4695
5291
|
async setMicrophoneEnabled(enabled) {
|
|
@@ -4755,14 +5351,33 @@ function createLiveKitDriver(handlers, options = {}) {
|
|
|
4755
5351
|
attach(identity, kind, element) {
|
|
4756
5352
|
const target = requireRoom("attach");
|
|
4757
5353
|
const source = sources?.[kind];
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
const
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
5354
|
+
if (source === void 0) return () => void 0;
|
|
5355
|
+
let current = null;
|
|
5356
|
+
const sync = () => {
|
|
5357
|
+
const participant = target.localParticipant.identity === identity ? target.localParticipant : target.remoteParticipants.get(identity);
|
|
5358
|
+
const track = participant?.getTrackPublication(source)?.track;
|
|
5359
|
+
if (track === void 0 || track === current) return;
|
|
5360
|
+
current?.detach(element);
|
|
5361
|
+
track.attach(element);
|
|
5362
|
+
current = track;
|
|
5363
|
+
};
|
|
5364
|
+
const onTrack = (...args) => {
|
|
5365
|
+
const who = args[args.length - 1];
|
|
5366
|
+
if (who?.identity === identity) sync();
|
|
5367
|
+
};
|
|
5368
|
+
sync();
|
|
5369
|
+
const events = trackEvents;
|
|
5370
|
+
if (events !== null) {
|
|
5371
|
+
target.on(events.subscribed, onTrack);
|
|
5372
|
+
target.on(events.localPublished, onTrack);
|
|
5373
|
+
}
|
|
4764
5374
|
return () => {
|
|
4765
|
-
|
|
5375
|
+
if (events !== null) {
|
|
5376
|
+
target.off(events.subscribed, onTrack);
|
|
5377
|
+
target.off(events.localPublished, onTrack);
|
|
5378
|
+
}
|
|
5379
|
+
current?.detach(element);
|
|
5380
|
+
current = null;
|
|
4766
5381
|
};
|
|
4767
5382
|
},
|
|
4768
5383
|
activeDevices() {
|
|
@@ -5001,6 +5616,14 @@ function MeetRuntime(props) {
|
|
|
5001
5616
|
}
|
|
5002
5617
|
if (chatReadFor === snapshot.meeting.id) return;
|
|
5003
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
|
+
});
|
|
5004
5627
|
void inRoom.loadChat().catch((error) => {
|
|
5005
5628
|
const normalized = error;
|
|
5006
5629
|
store.patch({
|
|
@@ -6341,7 +6964,7 @@ function useGuestRecordAccess(meeting) {
|
|
|
6341
6964
|
}
|
|
6342
6965
|
|
|
6343
6966
|
// src/react/components.tsx
|
|
6344
|
-
var
|
|
6967
|
+
var import_react5 = require("react");
|
|
6345
6968
|
var import_design_system = require("@ai-matrx/design-system");
|
|
6346
6969
|
var import_format3 = require("@ai-matrx/kit/format");
|
|
6347
6970
|
|
|
@@ -6352,6 +6975,7 @@ function kindOf(person) {
|
|
|
6352
6975
|
if (person.role === "host") return "host";
|
|
6353
6976
|
if (person.role === "cohost") return "cohost";
|
|
6354
6977
|
if (person.role === "guest") return person.userId !== null ? "signed-in guest" : "guest";
|
|
6978
|
+
if (person.userId === null) return "guest";
|
|
6355
6979
|
return "member";
|
|
6356
6980
|
}
|
|
6357
6981
|
function ms(iso) {
|
|
@@ -6407,12 +7031,19 @@ function coveredMs(intervals) {
|
|
|
6407
7031
|
}
|
|
6408
7032
|
function attendanceReport(meeting, attendees, names = {}) {
|
|
6409
7033
|
const end = ms(meeting.endedAt);
|
|
7034
|
+
const measuredOf = /* @__PURE__ */ new Map();
|
|
6410
7035
|
const perJoin = attendees.map((person) => {
|
|
6411
|
-
const
|
|
6412
|
-
|
|
6413
|
-
const
|
|
6414
|
-
const
|
|
6415
|
-
|
|
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 = {
|
|
6416
7047
|
id: person.id,
|
|
6417
7048
|
identity: person.identity,
|
|
6418
7049
|
name: displayNameFor(names, person.identity, person.displayName),
|
|
@@ -6421,10 +7052,12 @@ function attendanceReport(meeting, attendees, names = {}) {
|
|
|
6421
7052
|
joinedAt: person.joinedAt,
|
|
6422
7053
|
leftAt: person.leftAt,
|
|
6423
7054
|
durationMs: duration,
|
|
6424
|
-
durationToEnd: duration !== null &&
|
|
7055
|
+
durationToEnd: duration !== null && toEnd,
|
|
6425
7056
|
admission: person.admissionState,
|
|
6426
|
-
joins: 1
|
|
7057
|
+
joins: Math.max(1, person.sessions?.length ?? 0)
|
|
6427
7058
|
};
|
|
7059
|
+
measuredOf.set(row, measured);
|
|
7060
|
+
return row;
|
|
6428
7061
|
});
|
|
6429
7062
|
const groups = /* @__PURE__ */ new Map();
|
|
6430
7063
|
attendees.forEach((person, index) => {
|
|
@@ -6447,17 +7080,14 @@ function attendanceReport(meeting, attendees, names = {}) {
|
|
|
6447
7080
|
const left = ms(row.leftAt);
|
|
6448
7081
|
return left !== null && (latest === null || left > latest) ? left : latest;
|
|
6449
7082
|
}, null);
|
|
6450
|
-
const intervals = came.flatMap((row) =>
|
|
6451
|
-
const joined = ms(row.joinedAt);
|
|
6452
|
-
return joined !== null && row.durationMs !== null ? [[joined, joined + row.durationMs]] : [];
|
|
6453
|
-
});
|
|
7083
|
+
const intervals = came.flatMap((row) => measuredOf.get(row) ?? []);
|
|
6454
7084
|
return {
|
|
6455
7085
|
...first,
|
|
6456
7086
|
kind,
|
|
6457
7087
|
leftAt: open ? null : lastLeave === null ? null : new Date(lastLeave).toISOString(),
|
|
6458
7088
|
durationMs: intervals.length === 0 ? null : coveredMs(intervals),
|
|
6459
7089
|
durationToEnd: came.some((row) => row.durationToEnd),
|
|
6460
|
-
joins: came.length === 0 ? joins.length : came.
|
|
7090
|
+
joins: came.length === 0 ? joins.length : came.reduce((total, row) => total + row.joins, 0)
|
|
6461
7091
|
};
|
|
6462
7092
|
});
|
|
6463
7093
|
const rank = KIND_RANK;
|
|
@@ -6601,8 +7231,8 @@ function transcriptDocument(bundle, format, options = {}) {
|
|
|
6601
7231
|
if (line.identity !== last) {
|
|
6602
7232
|
if (last !== null) out.push("");
|
|
6603
7233
|
const who = speaker(line);
|
|
6604
|
-
const
|
|
6605
|
-
out.push(format === "md" ? `**${who}** \xB7 ${
|
|
7234
|
+
const clock2 = clockOfDay(line.startedAt, options);
|
|
7235
|
+
out.push(format === "md" ? `**${who}** \xB7 ${clock2}` : `${who} (${clock2})`);
|
|
6606
7236
|
last = line.identity;
|
|
6607
7237
|
}
|
|
6608
7238
|
out.push(line.text.trim());
|
|
@@ -6783,6 +7413,9 @@ function countLabel(count2, singular, plural = `${singular}s`) {
|
|
|
6783
7413
|
return `${count2} ${count2 === 1 ? singular : plural}`;
|
|
6784
7414
|
}
|
|
6785
7415
|
|
|
7416
|
+
// src/react/collab.tsx
|
|
7417
|
+
var import_react4 = require("react");
|
|
7418
|
+
|
|
6786
7419
|
// src/react/icons.tsx
|
|
6787
7420
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
6788
7421
|
function Icon({ children, ...props }) {
|
|
@@ -6967,60 +7600,1089 @@ function FlagIcon(props) {
|
|
|
6967
7600
|
function PencilIcon(props) {
|
|
6968
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" }) });
|
|
6969
7602
|
}
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "mx-meet__empty-title", children: [
|
|
6976
|
-
what,
|
|
6977
|
-
" is not ready yet"
|
|
6978
|
-
] }),
|
|
6979
|
-
/* @__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" })
|
|
6980
7608
|
] });
|
|
6981
7609
|
}
|
|
6982
|
-
function
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
6987
|
-
|
|
6988
|
-
|
|
6989
|
-
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
|
|
6997
|
-
|
|
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
|
+
] });
|
|
7616
|
+
}
|
|
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
|
+
] });
|
|
7623
|
+
}
|
|
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
|
+
] });
|
|
7630
|
+
}
|
|
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." };
|
|
6998
7688
|
}
|
|
6999
|
-
);
|
|
7000
|
-
}
|
|
7001
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
7002
|
-
"span",
|
|
7003
|
-
{
|
|
7004
|
-
className: "mx-meet__avatar mx-meet__avatar--initials",
|
|
7005
|
-
style: {
|
|
7006
|
-
width: size,
|
|
7007
|
-
height: size,
|
|
7008
|
-
fontSize: Math.round(size * 0.38),
|
|
7009
|
-
background: `var(--mx-meet-avatar-${tint})`
|
|
7010
|
-
},
|
|
7011
|
-
"aria-hidden": "true",
|
|
7012
|
-
children: (0, import_format3.getInitials)(name)
|
|
7013
7689
|
}
|
|
7014
|
-
|
|
7690
|
+
};
|
|
7015
7691
|
}
|
|
7016
|
-
function
|
|
7017
|
-
|
|
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,
|
|
7018
8680
|
active = false,
|
|
7019
8681
|
danger = false,
|
|
7020
8682
|
onClick,
|
|
7021
8683
|
children
|
|
7022
8684
|
}) {
|
|
7023
|
-
return /* @__PURE__ */ (0,
|
|
8685
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7024
8686
|
"button",
|
|
7025
8687
|
{
|
|
7026
8688
|
type: "button",
|
|
@@ -7039,14 +8701,14 @@ function ControlButton({
|
|
|
7039
8701
|
function RecordingIndicator() {
|
|
7040
8702
|
const { state, label } = useRecording();
|
|
7041
8703
|
if (label === null) return null;
|
|
7042
|
-
return /* @__PURE__ */ (0,
|
|
8704
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7043
8705
|
"span",
|
|
7044
8706
|
{
|
|
7045
8707
|
className: `mx-meet__recording mx-meet__recording--${state}`,
|
|
7046
8708
|
role: "status",
|
|
7047
8709
|
"aria-live": "polite",
|
|
7048
8710
|
children: [
|
|
7049
|
-
/* @__PURE__ */ (0,
|
|
8711
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RecordIcon, { width: 10, height: 10 }),
|
|
7050
8712
|
label
|
|
7051
8713
|
]
|
|
7052
8714
|
}
|
|
@@ -7054,12 +8716,12 @@ function RecordingIndicator() {
|
|
|
7054
8716
|
}
|
|
7055
8717
|
function ConnectionDot({ quality }) {
|
|
7056
8718
|
if (quality === "excellent" || quality === "good" || quality === "unknown") return null;
|
|
7057
|
-
return /* @__PURE__ */ (0,
|
|
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 }) });
|
|
7058
8720
|
}
|
|
7059
8721
|
function RoleBadge({ role }) {
|
|
7060
|
-
if (role === "host") return /* @__PURE__ */ (0,
|
|
7061
|
-
if (role === "cohost") return /* @__PURE__ */ (0,
|
|
7062
|
-
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" });
|
|
7063
8725
|
return null;
|
|
7064
8726
|
}
|
|
7065
8727
|
function ParticipantTile({
|
|
@@ -7069,7 +8731,7 @@ function ParticipantTile({
|
|
|
7069
8731
|
const host = useMeetHost();
|
|
7070
8732
|
const snapshot = useMeetSnapshot();
|
|
7071
8733
|
const queue = useHandQueue();
|
|
7072
|
-
const [menu, setMenu] = (0,
|
|
8734
|
+
const [menu, setMenu] = (0, import_react5.useState)(false);
|
|
7073
8735
|
const videoRef = useTrack(
|
|
7074
8736
|
participant.identity,
|
|
7075
8737
|
participant.screenSharing ? "screen" : "camera"
|
|
@@ -7078,7 +8740,7 @@ function ParticipantTile({
|
|
|
7078
8740
|
const pinnedHere = snapshot?.pinned === participant.identity;
|
|
7079
8741
|
const spotlit = snapshot?.spotlight === participant.identity;
|
|
7080
8742
|
const handPosition = participant.handRaised ? queue.findIndex((entry) => entry.identity === participant.identity) + 1 : 0;
|
|
7081
|
-
return /* @__PURE__ */ (0,
|
|
8743
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7082
8744
|
"div",
|
|
7083
8745
|
{
|
|
7084
8746
|
className: [
|
|
@@ -7088,7 +8750,7 @@ function ParticipantTile({
|
|
|
7088
8750
|
].filter(Boolean).join(" "),
|
|
7089
8751
|
"data-identity": participant.identity,
|
|
7090
8752
|
children: [
|
|
7091
|
-
showVideo ? /* @__PURE__ */ (0,
|
|
8753
|
+
showVideo ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7092
8754
|
"video",
|
|
7093
8755
|
{
|
|
7094
8756
|
ref: videoRef,
|
|
@@ -7097,43 +8759,43 @@ function ParticipantTile({
|
|
|
7097
8759
|
playsInline: true,
|
|
7098
8760
|
muted: participant.isLocal
|
|
7099
8761
|
}
|
|
7100
|
-
) : /* @__PURE__ */ (0,
|
|
7101
|
-
participant.handRaised ? /* @__PURE__ */ (0,
|
|
7102
|
-
/* @__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 }),
|
|
7103
8765
|
handPosition > 0 ? handPosition : null
|
|
7104
8766
|
] }) : null,
|
|
7105
|
-
/* @__PURE__ */ (0,
|
|
7106
|
-
/* @__PURE__ */ (0,
|
|
7107
|
-
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,
|
|
7108
8770
|
participant.displayName,
|
|
7109
8771
|
participant.isLocal ? " (you)" : "",
|
|
7110
|
-
participant.isAgent ? /* @__PURE__ */ (0,
|
|
7111
|
-
/* @__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 })
|
|
7112
8774
|
] }),
|
|
7113
|
-
!participant.micEnabled ? /* @__PURE__ */ (0,
|
|
7114
|
-
/* @__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 })
|
|
7115
8777
|
] }),
|
|
7116
|
-
/* @__PURE__ */ (0,
|
|
7117
|
-
/* @__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)(
|
|
7118
8780
|
ControlButton,
|
|
7119
8781
|
{
|
|
7120
8782
|
label: pinnedHere ? "Unpin" : `Pin ${participant.displayName} for me`,
|
|
7121
8783
|
active: pinnedHere,
|
|
7122
8784
|
onClick: () => host?.engine.pin(pinnedHere ? null : participant.identity),
|
|
7123
|
-
children: /* @__PURE__ */ (0,
|
|
8785
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PinIcon, { width: 16, height: 16 })
|
|
7124
8786
|
}
|
|
7125
8787
|
),
|
|
7126
|
-
/* @__PURE__ */ (0,
|
|
7127
|
-
/* @__PURE__ */ (0,
|
|
8788
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__anchor", children: [
|
|
8789
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7128
8790
|
ControlButton,
|
|
7129
8791
|
{
|
|
7130
8792
|
label: `More for ${participant.displayName}`,
|
|
7131
8793
|
active: menu,
|
|
7132
8794
|
onClick: () => setMenu(!menu),
|
|
7133
|
-
children: /* @__PURE__ */ (0,
|
|
8795
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MoreIcon, { width: 16, height: 16 })
|
|
7134
8796
|
}
|
|
7135
8797
|
),
|
|
7136
|
-
menu ? /* @__PURE__ */ (0,
|
|
8798
|
+
menu ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PersonMenu, { participant, onClose: () => setMenu(false), placement: "down" }) : null
|
|
7137
8799
|
] })
|
|
7138
8800
|
] })
|
|
7139
8801
|
]
|
|
@@ -7149,28 +8811,28 @@ function QualityBars({ quality }) {
|
|
|
7149
8811
|
if (quality === "unknown") return null;
|
|
7150
8812
|
const bars = quality === "excellent" ? 3 : quality === "good" ? 2 : quality === "poor" ? 1 : 0;
|
|
7151
8813
|
const label = quality === "lost" ? "Connection lost" : quality === "poor" ? "Poor connection" : `Connection ${quality}`;
|
|
7152
|
-
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 }) });
|
|
7153
8815
|
}
|
|
7154
8816
|
function Stage({ pageSize }) {
|
|
7155
8817
|
const stage = useStage(pageSize);
|
|
7156
8818
|
const columns = gridColumns(stage.tiles.length);
|
|
7157
8819
|
if (stage.feature === null && stage.tiles.length === 0) {
|
|
7158
|
-
return /* @__PURE__ */ (0,
|
|
7159
|
-
/* @__PURE__ */ (0,
|
|
7160
|
-
/* @__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." })
|
|
7161
8823
|
] });
|
|
7162
8824
|
}
|
|
7163
|
-
return /* @__PURE__ */ (0,
|
|
7164
|
-
stage.feature !== null ? /* @__PURE__ */ (0,
|
|
7165
|
-
/* @__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)(
|
|
7166
8828
|
"div",
|
|
7167
8829
|
{
|
|
7168
8830
|
className: "mx-meet__grid",
|
|
7169
8831
|
style: { "--mx-meet-columns": columns },
|
|
7170
|
-
children: stage.tiles.map((participant) => /* @__PURE__ */ (0,
|
|
8832
|
+
children: stage.tiles.map((participant) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ParticipantTile, { participant }, participant.identity))
|
|
7171
8833
|
}
|
|
7172
8834
|
),
|
|
7173
|
-
stage.overflow > 0 ? /* @__PURE__ */ (0,
|
|
8835
|
+
stage.overflow > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__overflow", children: [
|
|
7174
8836
|
"+",
|
|
7175
8837
|
stage.overflow,
|
|
7176
8838
|
" more ",
|
|
@@ -7183,20 +8845,28 @@ var MEET_REACTIONS = ["\u{1F496}", "\u{1F44D}", "\u{1F389}", "\u{1F44F}", "\u{1F
|
|
|
7183
8845
|
function ControlBar({ onLeave }) {
|
|
7184
8846
|
const room = useRoom();
|
|
7185
8847
|
const recording = useRecording();
|
|
7186
|
-
const [panel, setPanel] = (0,
|
|
7187
|
-
const [chatTo, setChatTo] = (0,
|
|
7188
|
-
const [popover, setPopover] = (0,
|
|
7189
|
-
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);
|
|
7190
8852
|
const snapshot = useMeetSnapshot();
|
|
7191
8853
|
const lobby = useLobby();
|
|
7192
8854
|
const controls = useHostControls();
|
|
7193
8855
|
const queue = useHandQueue();
|
|
7194
8856
|
const micUnavailable = useLocalMedia().microphone.unavailable;
|
|
7195
8857
|
const unread = useUnreadChat(panel === "chat");
|
|
8858
|
+
const [whiteboard, setWhiteboard] = (0, import_react5.useState)(false);
|
|
7196
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
|
+
});
|
|
7197
8867
|
const privateChatAt = snapshot?.privateChatRequest?.at ?? null;
|
|
7198
8868
|
const meetStore = useMeetHost()?.store ?? null;
|
|
7199
|
-
(0,
|
|
8869
|
+
(0, import_react5.useEffect)(() => {
|
|
7200
8870
|
const request = meetStore?.snapshot().privateChatRequest ?? null;
|
|
7201
8871
|
if (request === null) return;
|
|
7202
8872
|
setChatTo(request.to);
|
|
@@ -7212,11 +8882,11 @@ function ControlBar({ onLeave }) {
|
|
|
7212
8882
|
help: () => setShortcuts(true)
|
|
7213
8883
|
});
|
|
7214
8884
|
const hasSpotlight = snapshot?.spotlight !== null && snapshot?.spotlight !== void 0;
|
|
7215
|
-
return /* @__PURE__ */ (0,
|
|
7216
|
-
/* @__PURE__ */ (0,
|
|
7217
|
-
shortcuts ? /* @__PURE__ */ (0,
|
|
7218
|
-
panel === "chat" ? /* @__PURE__ */ (0,
|
|
7219
|
-
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)(
|
|
7220
8890
|
PeoplePanel,
|
|
7221
8891
|
{
|
|
7222
8892
|
onClose: () => setPanel("none"),
|
|
@@ -7226,48 +8896,53 @@ function ControlBar({ onLeave }) {
|
|
|
7226
8896
|
}
|
|
7227
8897
|
}
|
|
7228
8898
|
) : null,
|
|
7229
|
-
panel === "ai" ? /* @__PURE__ */ (0,
|
|
7230
|
-
panel === "settings" ? /* @__PURE__ */ (0,
|
|
7231
|
-
|
|
7232
|
-
/* @__PURE__ */ (0,
|
|
7233
|
-
|
|
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)(
|
|
7234
8909
|
ControlButton,
|
|
7235
8910
|
{
|
|
7236
8911
|
label: micUnavailable !== null ? `Unmute \u2014 ${micUnavailable.remedy}` : room.local?.micEnabled === true ? "Mute (\u2318D)" : "Unmute (\u2318D)",
|
|
7237
8912
|
active: room.local?.micEnabled === true,
|
|
7238
8913
|
onClick: () => void room.toggleMicrophone(),
|
|
7239
|
-
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, {})
|
|
7240
8915
|
}
|
|
7241
8916
|
),
|
|
7242
|
-
/* @__PURE__ */ (0,
|
|
8917
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7243
8918
|
ControlButton,
|
|
7244
8919
|
{
|
|
7245
8920
|
label: room.local?.cameraEnabled === true ? "Stop video (\u2318E)" : "Start video (\u2318E)",
|
|
7246
8921
|
active: room.local?.cameraEnabled === true,
|
|
7247
8922
|
onClick: () => void room.toggleCamera(),
|
|
7248
|
-
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, {})
|
|
7249
8924
|
}
|
|
7250
8925
|
),
|
|
7251
|
-
/* @__PURE__ */ (0,
|
|
8926
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7252
8927
|
ControlButton,
|
|
7253
8928
|
{
|
|
7254
8929
|
label: room.local?.screenSharing === true ? "Stop sharing" : "Share screen",
|
|
7255
8930
|
active: room.local?.screenSharing === true,
|
|
7256
8931
|
onClick: () => void room.toggleScreenShare(),
|
|
7257
|
-
children: /* @__PURE__ */ (0,
|
|
8932
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ScreenShareIcon, {})
|
|
7258
8933
|
}
|
|
7259
8934
|
),
|
|
7260
|
-
/* @__PURE__ */ (0,
|
|
7261
|
-
/* @__PURE__ */ (0,
|
|
8935
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__anchor", children: [
|
|
8936
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7262
8937
|
ControlButton,
|
|
7263
8938
|
{
|
|
7264
8939
|
label: "Send a reaction",
|
|
7265
8940
|
active: popover === "reactions",
|
|
7266
8941
|
onClick: () => setPopover(popover === "reactions" ? "none" : "reactions"),
|
|
7267
|
-
children: /* @__PURE__ */ (0,
|
|
8942
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SmileIcon, {})
|
|
7268
8943
|
}
|
|
7269
8944
|
),
|
|
7270
|
-
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)(
|
|
7271
8946
|
"button",
|
|
7272
8947
|
{
|
|
7273
8948
|
type: "button",
|
|
@@ -7279,46 +8954,53 @@ function ControlBar({ onLeave }) {
|
|
|
7279
8954
|
emoji
|
|
7280
8955
|
)) }) }) : null
|
|
7281
8956
|
] }),
|
|
7282
|
-
/* @__PURE__ */ (0,
|
|
8957
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7283
8958
|
ControlButton,
|
|
7284
8959
|
{
|
|
7285
8960
|
label: room.local?.handRaised === true ? "Lower hand (\u2318\u2325H)" : "Raise hand (\u2318\u2325H)",
|
|
7286
8961
|
active: room.local?.handRaised === true,
|
|
7287
8962
|
onClick: () => void room.toggleHand(),
|
|
7288
|
-
children: /* @__PURE__ */ (0,
|
|
8963
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HandIcon, {})
|
|
7289
8964
|
}
|
|
7290
8965
|
),
|
|
7291
|
-
/* @__PURE__ */ (0,
|
|
7292
|
-
/* @__PURE__ */ (0,
|
|
7293
|
-
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
|
|
7294
8969
|
] }),
|
|
7295
|
-
/* @__PURE__ */ (0,
|
|
8970
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7296
8971
|
ControlButton,
|
|
7297
8972
|
{
|
|
7298
8973
|
label: lobby.waiting.length > 0 ? `People \u2014 ${lobby.waiting.length} waiting` : `People \u2014 ${(snapshot?.participants ?? []).length} in the meeting`,
|
|
7299
8974
|
active: panel === "people",
|
|
7300
8975
|
onClick: () => toggle("people"),
|
|
7301
8976
|
children: [
|
|
7302
|
-
/* @__PURE__ */ (0,
|
|
7303
|
-
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
|
|
7304
8979
|
]
|
|
7305
8980
|
}
|
|
7306
8981
|
),
|
|
7307
|
-
/* @__PURE__ */ (0,
|
|
7308
|
-
|
|
7309
|
-
|
|
7310
|
-
|
|
7311
|
-
|
|
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)(
|
|
7312
8994
|
ControlButton,
|
|
7313
8995
|
{
|
|
7314
8996
|
label: "More options",
|
|
7315
8997
|
active: popover === "more" || panel === "settings",
|
|
7316
8998
|
onClick: () => setPopover(popover === "more" ? "none" : "more"),
|
|
7317
|
-
children: /* @__PURE__ */ (0,
|
|
8999
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MoreIcon, {})
|
|
7318
9000
|
}
|
|
7319
9001
|
),
|
|
7320
|
-
popover === "more" ? /* @__PURE__ */ (0,
|
|
7321
|
-
/* @__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)(
|
|
7322
9004
|
MenuItem,
|
|
7323
9005
|
{
|
|
7324
9006
|
onSelect: () => {
|
|
@@ -7326,12 +9008,12 @@ function ControlBar({ onLeave }) {
|
|
|
7326
9008
|
setPanel("settings");
|
|
7327
9009
|
},
|
|
7328
9010
|
children: [
|
|
7329
|
-
/* @__PURE__ */ (0,
|
|
7330
|
-
"
|
|
9011
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SettingsIcon, { width: 16, height: 16 }),
|
|
9012
|
+
" Settings"
|
|
7331
9013
|
]
|
|
7332
9014
|
}
|
|
7333
9015
|
),
|
|
7334
|
-
/* @__PURE__ */ (0,
|
|
9016
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7335
9017
|
MenuItem,
|
|
7336
9018
|
{
|
|
7337
9019
|
onSelect: () => {
|
|
@@ -7339,14 +9021,14 @@ function ControlBar({ onLeave }) {
|
|
|
7339
9021
|
setShortcuts(true);
|
|
7340
9022
|
},
|
|
7341
9023
|
children: [
|
|
7342
|
-
/* @__PURE__ */ (0,
|
|
9024
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(KeyboardIcon, { width: 16, height: 16 }),
|
|
7343
9025
|
" Keyboard shortcuts"
|
|
7344
9026
|
]
|
|
7345
9027
|
}
|
|
7346
9028
|
),
|
|
7347
|
-
controls.isHost ? /* @__PURE__ */ (0,
|
|
7348
|
-
/* @__PURE__ */ (0,
|
|
7349
|
-
/* @__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)(
|
|
7350
9032
|
MenuItem,
|
|
7351
9033
|
{
|
|
7352
9034
|
onSelect: () => {
|
|
@@ -7354,12 +9036,12 @@ function ControlBar({ onLeave }) {
|
|
|
7354
9036
|
void controls.run({ action: "mute_all" });
|
|
7355
9037
|
},
|
|
7356
9038
|
children: [
|
|
7357
|
-
/* @__PURE__ */ (0,
|
|
9039
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MicOffIcon, { width: 16, height: 16 }),
|
|
7358
9040
|
" Mute everyone"
|
|
7359
9041
|
]
|
|
7360
9042
|
}
|
|
7361
9043
|
),
|
|
7362
|
-
/* @__PURE__ */ (0,
|
|
9044
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7363
9045
|
MenuItem,
|
|
7364
9046
|
{
|
|
7365
9047
|
onSelect: () => {
|
|
@@ -7367,12 +9049,12 @@ function ControlBar({ onLeave }) {
|
|
|
7367
9049
|
void controls.run({ action: "ask_all_unmute" });
|
|
7368
9050
|
},
|
|
7369
9051
|
children: [
|
|
7370
|
-
/* @__PURE__ */ (0,
|
|
9052
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MicIcon, { width: 16, height: 16 }),
|
|
7371
9053
|
" Ask everyone to unmute"
|
|
7372
9054
|
]
|
|
7373
9055
|
}
|
|
7374
9056
|
),
|
|
7375
|
-
queue.length > 0 ? /* @__PURE__ */ (0,
|
|
9057
|
+
queue.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7376
9058
|
MenuItem,
|
|
7377
9059
|
{
|
|
7378
9060
|
onSelect: () => {
|
|
@@ -7380,14 +9062,14 @@ function ControlBar({ onLeave }) {
|
|
|
7380
9062
|
void controls.run({ action: "lower_all_hands" });
|
|
7381
9063
|
},
|
|
7382
9064
|
children: [
|
|
7383
|
-
/* @__PURE__ */ (0,
|
|
9065
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(HandIcon, { width: 16, height: 16 }),
|
|
7384
9066
|
" Lower all hands (",
|
|
7385
9067
|
queue.length,
|
|
7386
9068
|
")"
|
|
7387
9069
|
]
|
|
7388
9070
|
}
|
|
7389
9071
|
) : null,
|
|
7390
|
-
hasSpotlight ? /* @__PURE__ */ (0,
|
|
9072
|
+
hasSpotlight ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7391
9073
|
MenuItem,
|
|
7392
9074
|
{
|
|
7393
9075
|
onSelect: () => {
|
|
@@ -7395,7 +9077,7 @@ function ControlBar({ onLeave }) {
|
|
|
7395
9077
|
void controls.run({ action: "spotlight", identity: null });
|
|
7396
9078
|
},
|
|
7397
9079
|
children: [
|
|
7398
|
-
/* @__PURE__ */ (0,
|
|
9080
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SpotlightIcon, { width: 16, height: 16 }),
|
|
7399
9081
|
" Remove spotlight"
|
|
7400
9082
|
]
|
|
7401
9083
|
}
|
|
@@ -7403,7 +9085,7 @@ function ControlBar({ onLeave }) {
|
|
|
7403
9085
|
] }) : null
|
|
7404
9086
|
] }) }) : null
|
|
7405
9087
|
] }),
|
|
7406
|
-
/* @__PURE__ */ (0,
|
|
9088
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7407
9089
|
ControlButton,
|
|
7408
9090
|
{
|
|
7409
9091
|
label: "Leave",
|
|
@@ -7412,7 +9094,7 @@ function ControlBar({ onLeave }) {
|
|
|
7412
9094
|
void room.leave();
|
|
7413
9095
|
onLeave?.();
|
|
7414
9096
|
},
|
|
7415
|
-
children: /* @__PURE__ */ (0,
|
|
9097
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PhoneOffIcon, {})
|
|
7416
9098
|
}
|
|
7417
9099
|
)
|
|
7418
9100
|
] })
|
|
@@ -7422,13 +9104,13 @@ function useUnreadChat(open) {
|
|
|
7422
9104
|
const snapshot = useMeetSnapshot();
|
|
7423
9105
|
const chat = snapshot?.chat ?? [];
|
|
7424
9106
|
const local = snapshot?.localIdentity ?? null;
|
|
7425
|
-
const [seen, setSeen] = (0,
|
|
7426
|
-
(0,
|
|
9107
|
+
const [seen, setSeen] = (0, import_react5.useState)(0);
|
|
9108
|
+
(0, import_react5.useEffect)(() => {
|
|
7427
9109
|
if (open) setSeen(chat.length);
|
|
7428
9110
|
}, [open, chat.length]);
|
|
7429
9111
|
const loaded = snapshot?.chatLoaded === true;
|
|
7430
|
-
const [baseline, setBaseline] = (0,
|
|
7431
|
-
(0,
|
|
9112
|
+
const [baseline, setBaseline] = (0, import_react5.useState)(null);
|
|
9113
|
+
(0, import_react5.useEffect)(() => {
|
|
7432
9114
|
if (loaded && baseline === null) setBaseline(chat.length);
|
|
7433
9115
|
}, [loaded, baseline, chat.length]);
|
|
7434
9116
|
if (open) return 0;
|
|
@@ -7441,14 +9123,14 @@ function Popover({
|
|
|
7441
9123
|
children,
|
|
7442
9124
|
placement = "up"
|
|
7443
9125
|
}) {
|
|
7444
|
-
const ref = (0,
|
|
7445
|
-
const [style, setStyle] = (0,
|
|
9126
|
+
const ref = (0, import_react5.useRef)(null);
|
|
9127
|
+
const [style, setStyle] = (0, import_react5.useState)({
|
|
7446
9128
|
position: "fixed",
|
|
7447
9129
|
top: 0,
|
|
7448
9130
|
left: 0,
|
|
7449
9131
|
visibility: "hidden"
|
|
7450
9132
|
});
|
|
7451
|
-
(0,
|
|
9133
|
+
(0, import_react5.useLayoutEffect)(() => {
|
|
7452
9134
|
const element = ref.current;
|
|
7453
9135
|
const anchor = element?.parentElement ?? null;
|
|
7454
9136
|
if (element === null || anchor === null) return;
|
|
@@ -7493,7 +9175,7 @@ function Popover({
|
|
|
7493
9175
|
window.removeEventListener("scroll", place, true);
|
|
7494
9176
|
};
|
|
7495
9177
|
}, [placement]);
|
|
7496
|
-
(0,
|
|
9178
|
+
(0, import_react5.useEffect)(() => {
|
|
7497
9179
|
const onKey = (event) => {
|
|
7498
9180
|
if (event.key === "Escape") onClose();
|
|
7499
9181
|
};
|
|
@@ -7508,14 +9190,14 @@ function Popover({
|
|
|
7508
9190
|
window.removeEventListener("pointerdown", onPointer);
|
|
7509
9191
|
};
|
|
7510
9192
|
}, [onClose]);
|
|
7511
|
-
return /* @__PURE__ */ (0,
|
|
9193
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ref, className: "mx-meet__popover", style, role: "dialog", "aria-label": label, children });
|
|
7512
9194
|
}
|
|
7513
9195
|
function MenuItem({
|
|
7514
9196
|
onSelect,
|
|
7515
9197
|
danger = false,
|
|
7516
9198
|
children
|
|
7517
9199
|
}) {
|
|
7518
|
-
return /* @__PURE__ */ (0,
|
|
9200
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7519
9201
|
"button",
|
|
7520
9202
|
{
|
|
7521
9203
|
type: "button",
|
|
@@ -7527,28 +9209,28 @@ function MenuItem({
|
|
|
7527
9209
|
);
|
|
7528
9210
|
}
|
|
7529
9211
|
function Toast({ text: text3, failed, onDone }) {
|
|
7530
|
-
(0,
|
|
9212
|
+
(0, import_react5.useEffect)(() => {
|
|
7531
9213
|
const timer = setTimeout(onDone, failed ? 7e3 : 4e3);
|
|
7532
9214
|
return () => clearTimeout(timer);
|
|
7533
9215
|
}, [text3, failed, onDone]);
|
|
7534
|
-
return /* @__PURE__ */ (0,
|
|
7535
|
-
/* @__PURE__ */ (0,
|
|
7536
|
-
/* @__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 }) })
|
|
7537
9219
|
] });
|
|
7538
9220
|
}
|
|
7539
9221
|
function MeetingOverlays() {
|
|
7540
9222
|
const reactions = useReactions();
|
|
7541
9223
|
const { notice, dismiss } = useModerationNotice();
|
|
7542
9224
|
const room = useRoom();
|
|
7543
|
-
return /* @__PURE__ */ (0,
|
|
7544
|
-
/* @__PURE__ */ (0,
|
|
9225
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
9226
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ReactionOverlay, { reactions }),
|
|
7545
9227
|
notice !== null && notice.kind !== "removed" ? (
|
|
7546
9228
|
// A host's request ("the host is asking you to unmute"), not an error:
|
|
7547
9229
|
// an assertive status, so it is announced at once without being filed
|
|
7548
9230
|
// as a failure (design-system error-box census).
|
|
7549
|
-
/* @__PURE__ */ (0,
|
|
7550
|
-
/* @__PURE__ */ (0,
|
|
7551
|
-
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)(
|
|
7552
9234
|
"button",
|
|
7553
9235
|
{
|
|
7554
9236
|
type: "button",
|
|
@@ -7560,20 +9242,20 @@ function MeetingOverlays() {
|
|
|
7560
9242
|
children: "Unmute"
|
|
7561
9243
|
}
|
|
7562
9244
|
) : null,
|
|
7563
|
-
/* @__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 }) })
|
|
7564
9246
|
] })
|
|
7565
9247
|
) : null
|
|
7566
9248
|
] });
|
|
7567
9249
|
}
|
|
7568
9250
|
function ShortcutsSheet({ onClose }) {
|
|
7569
|
-
(0,
|
|
9251
|
+
(0, import_react5.useEffect)(() => {
|
|
7570
9252
|
const onKey = (event) => {
|
|
7571
9253
|
if (event.key === "Escape") onClose();
|
|
7572
9254
|
};
|
|
7573
9255
|
window.addEventListener("keydown", onKey);
|
|
7574
9256
|
return () => window.removeEventListener("keydown", onKey);
|
|
7575
9257
|
}, [onClose]);
|
|
7576
|
-
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)(
|
|
7577
9259
|
"div",
|
|
7578
9260
|
{
|
|
7579
9261
|
className: "mx-meet__sheet",
|
|
@@ -7581,13 +9263,13 @@ function ShortcutsSheet({ onClose }) {
|
|
|
7581
9263
|
"aria-label": "Keyboard shortcuts",
|
|
7582
9264
|
onClick: (event) => event.stopPropagation(),
|
|
7583
9265
|
children: [
|
|
7584
|
-
/* @__PURE__ */ (0,
|
|
7585
|
-
/* @__PURE__ */ (0,
|
|
7586
|
-
/* @__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 }) })
|
|
7587
9269
|
] }),
|
|
7588
|
-
/* @__PURE__ */ (0,
|
|
7589
|
-
/* @__PURE__ */ (0,
|
|
7590
|
-
/* @__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 }) })
|
|
7591
9273
|
] }, shortcut.id)) })
|
|
7592
9274
|
]
|
|
7593
9275
|
}
|
|
@@ -7597,19 +9279,19 @@ function AiControl({ active, onToggle }) {
|
|
|
7597
9279
|
const snapshot = useMeetSnapshot();
|
|
7598
9280
|
const meeting = snapshot?.meeting ?? null;
|
|
7599
9281
|
if (meeting === null || !meeting.aiEnabled) return null;
|
|
7600
|
-
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, {}) });
|
|
7601
9283
|
}
|
|
7602
9284
|
function PanelShell({
|
|
7603
9285
|
title,
|
|
7604
9286
|
onClose,
|
|
7605
9287
|
children
|
|
7606
9288
|
}) {
|
|
7607
|
-
return /* @__PURE__ */ (0,
|
|
7608
|
-
/* @__PURE__ */ (0,
|
|
7609
|
-
/* @__PURE__ */ (0,
|
|
7610
|
-
/* @__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 }) })
|
|
7611
9293
|
] }),
|
|
7612
|
-
/* @__PURE__ */ (0,
|
|
9294
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet__panel-body", children })
|
|
7613
9295
|
] });
|
|
7614
9296
|
}
|
|
7615
9297
|
function ChatPanel({
|
|
@@ -7619,17 +9301,17 @@ function ChatPanel({
|
|
|
7619
9301
|
}) {
|
|
7620
9302
|
const snapshot = useMeetSnapshot();
|
|
7621
9303
|
const room = useRoom();
|
|
7622
|
-
const [draft, setDraft] = (0,
|
|
7623
|
-
const [recipient, setRecipient] = (0,
|
|
7624
|
-
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);
|
|
7625
9307
|
const messages = snapshot?.chat ?? [];
|
|
7626
9308
|
const local = snapshot?.localIdentity ?? null;
|
|
7627
9309
|
const people = (snapshot?.participants ?? []).filter(
|
|
7628
9310
|
(participant) => !participant.isLocal && !participant.isAgent
|
|
7629
9311
|
);
|
|
7630
9312
|
const recipientName = recipient === null ? null : people.find((p) => p.identity === recipient)?.displayName ?? null;
|
|
7631
|
-
(0,
|
|
7632
|
-
(0,
|
|
9313
|
+
(0, import_react5.useEffect)(() => setRecipient(to), [to]);
|
|
9314
|
+
(0, import_react5.useEffect)(() => {
|
|
7633
9315
|
const list = listRef.current;
|
|
7634
9316
|
if (list !== null) list.scrollTop = list.scrollHeight;
|
|
7635
9317
|
}, [messages.length]);
|
|
@@ -7637,13 +9319,13 @@ function ChatPanel({
|
|
|
7637
9319
|
setRecipient(next);
|
|
7638
9320
|
onTo?.(next);
|
|
7639
9321
|
};
|
|
7640
|
-
return /* @__PURE__ */ (0,
|
|
7641
|
-
/* @__PURE__ */ (0,
|
|
7642
|
-
snapshot?.chatHistoryError != null ? /* @__PURE__ */ (0,
|
|
7643
|
-
snapshot?.chatLoaded !== true && messages.length === 0 ? /* @__PURE__ */ (0,
|
|
7644
|
-
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))
|
|
7645
9327
|
] }),
|
|
7646
|
-
/* @__PURE__ */ (0,
|
|
9328
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7647
9329
|
"form",
|
|
7648
9330
|
{
|
|
7649
9331
|
className: "mx-meet__composer mx-meet__composer--chat",
|
|
@@ -7656,7 +9338,7 @@ function ChatPanel({
|
|
|
7656
9338
|
else void room.sendPrivateChat(recipient, text3);
|
|
7657
9339
|
},
|
|
7658
9340
|
children: [
|
|
7659
|
-
people.length > 0 ? /* @__PURE__ */ (0,
|
|
9341
|
+
people.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7660
9342
|
"select",
|
|
7661
9343
|
{
|
|
7662
9344
|
className: "mx-meet__select mx-meet__select--compact",
|
|
@@ -7664,16 +9346,16 @@ function ChatPanel({
|
|
|
7664
9346
|
value: recipient ?? "",
|
|
7665
9347
|
onChange: (event) => choose(event.target.value === "" ? null : event.target.value),
|
|
7666
9348
|
children: [
|
|
7667
|
-
/* @__PURE__ */ (0,
|
|
7668
|
-
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: [
|
|
7669
9351
|
participant.displayName,
|
|
7670
9352
|
" (private)"
|
|
7671
9353
|
] }, participant.identity))
|
|
7672
9354
|
]
|
|
7673
9355
|
}
|
|
7674
9356
|
) : null,
|
|
7675
|
-
/* @__PURE__ */ (0,
|
|
7676
|
-
/* @__PURE__ */ (0,
|
|
9357
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__composer-row", children: [
|
|
9358
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7677
9359
|
"input",
|
|
7678
9360
|
{
|
|
7679
9361
|
className: "mx-meet__input",
|
|
@@ -7684,9 +9366,9 @@ function ChatPanel({
|
|
|
7684
9366
|
maxLength: 4e3
|
|
7685
9367
|
}
|
|
7686
9368
|
),
|
|
7687
|
-
/* @__PURE__ */ (0,
|
|
9369
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "submit", className: "mx-meet__send", disabled: draft.trim().length === 0, children: "Send" })
|
|
7688
9370
|
] }),
|
|
7689
|
-
recipientName !== null ? /* @__PURE__ */ (0,
|
|
9371
|
+
recipientName !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__panel-note", children: [
|
|
7690
9372
|
"Only ",
|
|
7691
9373
|
recipientName,
|
|
7692
9374
|
" sees this. Private messages are not saved."
|
|
@@ -7704,7 +9386,7 @@ function ChatLine({
|
|
|
7704
9386
|
const mine = message.identity === local;
|
|
7705
9387
|
const privateTo = message.to ?? null;
|
|
7706
9388
|
const counterpart = privateTo === null ? null : mine ? people.find((p) => p.identity === privateTo)?.displayName ?? "them" : "you";
|
|
7707
|
-
return /* @__PURE__ */ (0,
|
|
9389
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7708
9390
|
"li",
|
|
7709
9391
|
{
|
|
7710
9392
|
className: [
|
|
@@ -7713,17 +9395,17 @@ function ChatLine({
|
|
|
7713
9395
|
message.failed !== void 0 ? "mx-meet__chat-line--failed" : ""
|
|
7714
9396
|
].filter(Boolean).join(" "),
|
|
7715
9397
|
children: [
|
|
7716
|
-
/* @__PURE__ */ (0,
|
|
7717
|
-
/* @__PURE__ */ (0,
|
|
7718
|
-
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: [
|
|
7719
9401
|
"to ",
|
|
7720
9402
|
counterpart,
|
|
7721
9403
|
" \xB7 private"
|
|
7722
9404
|
] }) : null,
|
|
7723
|
-
/* @__PURE__ */ (0,
|
|
9405
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("time", { dateTime: message.at, children: clockOf(message.at) })
|
|
7724
9406
|
] }),
|
|
7725
|
-
/* @__PURE__ */ (0,
|
|
7726
|
-
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
|
|
7727
9409
|
]
|
|
7728
9410
|
}
|
|
7729
9411
|
);
|
|
@@ -7735,22 +9417,22 @@ function PeoplePanel({
|
|
|
7735
9417
|
const snapshot = useMeetSnapshot();
|
|
7736
9418
|
const controls = useHostControls();
|
|
7737
9419
|
const queue = useHandQueue();
|
|
7738
|
-
const [query, setQuery] = (0,
|
|
7739
|
-
const [menuFor, setMenuFor] = (0,
|
|
9420
|
+
const [query, setQuery] = (0, import_react5.useState)("");
|
|
9421
|
+
const [menuFor, setMenuFor] = (0, import_react5.useState)(null);
|
|
7740
9422
|
const myRole = useRole();
|
|
7741
9423
|
const local = snapshot?.localIdentity ?? null;
|
|
7742
9424
|
const everyone = snapshot?.participants ?? [];
|
|
7743
9425
|
const needle = query.trim().toLowerCase();
|
|
7744
9426
|
const shown = needle.length === 0 ? everyone : everyone.filter((participant) => participant.displayName.toLowerCase().includes(needle));
|
|
7745
|
-
return /* @__PURE__ */ (0,
|
|
7746
|
-
/* @__PURE__ */ (0,
|
|
7747
|
-
queue.length > 0 ? /* @__PURE__ */ (0,
|
|
7748
|
-
/* @__PURE__ */ (0,
|
|
7749
|
-
/* @__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: [
|
|
7750
9432
|
"Raised hands \xB7 ",
|
|
7751
9433
|
queue.length
|
|
7752
9434
|
] }),
|
|
7753
|
-
controls.isHost ? /* @__PURE__ */ (0,
|
|
9435
|
+
controls.isHost ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7754
9436
|
"button",
|
|
7755
9437
|
{
|
|
7756
9438
|
type: "button",
|
|
@@ -7760,13 +9442,13 @@ function PeoplePanel({
|
|
|
7760
9442
|
}
|
|
7761
9443
|
) : null
|
|
7762
9444
|
] }),
|
|
7763
|
-
/* @__PURE__ */ (0,
|
|
7764
|
-
/* @__PURE__ */ (0,
|
|
7765
|
-
/* @__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: [
|
|
7766
9448
|
participant.displayName,
|
|
7767
|
-
participant.identity === local ? /* @__PURE__ */ (0,
|
|
9449
|
+
participant.identity === local ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__you", children: " (you)" }) : null
|
|
7768
9450
|
] }),
|
|
7769
|
-
controls.isHost || participant.identity === local ? /* @__PURE__ */ (0,
|
|
9451
|
+
controls.isHost || participant.identity === local ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7770
9452
|
"button",
|
|
7771
9453
|
{
|
|
7772
9454
|
type: "button",
|
|
@@ -7777,27 +9459,27 @@ function PeoplePanel({
|
|
|
7777
9459
|
) : null
|
|
7778
9460
|
] }, participant.identity)) })
|
|
7779
9461
|
] }) : null,
|
|
7780
|
-
controls.isHost && everyone.length > 1 ? /* @__PURE__ */ (0,
|
|
7781
|
-
/* @__PURE__ */ (0,
|
|
7782
|
-
/* @__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 }),
|
|
7783
9465
|
" Mute all"
|
|
7784
9466
|
] }),
|
|
7785
|
-
/* @__PURE__ */ (0,
|
|
9467
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
7786
9468
|
"button",
|
|
7787
9469
|
{
|
|
7788
9470
|
type: "button",
|
|
7789
9471
|
className: "mx-meet__chip",
|
|
7790
9472
|
onClick: () => void controls.run({ action: "ask_all_unmute" }),
|
|
7791
9473
|
children: [
|
|
7792
|
-
/* @__PURE__ */ (0,
|
|
9474
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MicIcon, { width: 14, height: 14 }),
|
|
7793
9475
|
" Ask all to unmute"
|
|
7794
9476
|
]
|
|
7795
9477
|
}
|
|
7796
9478
|
)
|
|
7797
9479
|
] }) : null,
|
|
7798
|
-
everyone.length > 4 ? /* @__PURE__ */ (0,
|
|
7799
|
-
/* @__PURE__ */ (0,
|
|
7800
|
-
/* @__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)(
|
|
7801
9483
|
"input",
|
|
7802
9484
|
{
|
|
7803
9485
|
className: "mx-meet__input mx-meet__input--bare",
|
|
@@ -7808,31 +9490,31 @@ function PeoplePanel({
|
|
|
7808
9490
|
}
|
|
7809
9491
|
)
|
|
7810
9492
|
] }) : null,
|
|
7811
|
-
controls.notice !== null ? /* @__PURE__ */ (0,
|
|
7812
|
-
/* @__PURE__ */ (0,
|
|
7813
|
-
shown.map((participant) => /* @__PURE__ */ (0,
|
|
7814
|
-
/* @__PURE__ */ (0,
|
|
7815
|
-
/* @__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: [
|
|
7816
9498
|
participant.displayName,
|
|
7817
|
-
participant.identity === local ? /* @__PURE__ */ (0,
|
|
7818
|
-
/* @__PURE__ */ (0,
|
|
7819
|
-
isNoteTaker(participant) ? /* @__PURE__ */ (0,
|
|
7820
|
-
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
|
|
7821
9503
|
] }),
|
|
7822
|
-
participant.handRaised ? /* @__PURE__ */ (0,
|
|
7823
|
-
!participant.micEnabled && !isNoteTaker(participant) ? /* @__PURE__ */ (0,
|
|
7824
|
-
/* @__PURE__ */ (0,
|
|
7825
|
-
/* @__PURE__ */ (0,
|
|
7826
|
-
/* @__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)(
|
|
7827
9509
|
ControlButton,
|
|
7828
9510
|
{
|
|
7829
9511
|
label: `More for ${participant.displayName}`,
|
|
7830
9512
|
active: menuFor === participant.identity,
|
|
7831
9513
|
onClick: () => setMenuFor(menuFor === participant.identity ? null : participant.identity),
|
|
7832
|
-
children: /* @__PURE__ */ (0,
|
|
9514
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MoreIcon, { width: 16, height: 16 })
|
|
7833
9515
|
}
|
|
7834
9516
|
),
|
|
7835
|
-
menuFor === participant.identity ? /* @__PURE__ */ (0,
|
|
9517
|
+
menuFor === participant.identity ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7836
9518
|
PersonMenu,
|
|
7837
9519
|
{
|
|
7838
9520
|
participant,
|
|
@@ -7843,13 +9525,13 @@ function PeoplePanel({
|
|
|
7843
9525
|
) : null
|
|
7844
9526
|
] })
|
|
7845
9527
|
] }, participant.identity)),
|
|
7846
|
-
shown.length === 0 ? /* @__PURE__ */ (0,
|
|
9528
|
+
shown.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { className: "mx-meet__panel-note", children: [
|
|
7847
9529
|
"Nobody matches \u201C",
|
|
7848
9530
|
query,
|
|
7849
9531
|
"\u201D."
|
|
7850
9532
|
] }) : null
|
|
7851
9533
|
] }),
|
|
7852
|
-
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
|
|
7853
9535
|
] });
|
|
7854
9536
|
}
|
|
7855
9537
|
function PersonMenu({
|
|
@@ -7861,14 +9543,14 @@ function PersonMenu({
|
|
|
7861
9543
|
const host = useMeetHost();
|
|
7862
9544
|
const snapshot = useMeetSnapshot();
|
|
7863
9545
|
const controls = useHostControls();
|
|
7864
|
-
const [mode, setMode] = (0,
|
|
7865
|
-
const [text3, setText] = (0,
|
|
9546
|
+
const [mode, setMode] = (0, import_react5.useState)("menu");
|
|
9547
|
+
const [text3, setText] = (0, import_react5.useState)("");
|
|
7866
9548
|
const self = participant.identity === snapshot?.localIdentity;
|
|
7867
9549
|
const moderate = controls.canModerate(participant);
|
|
7868
9550
|
const pinned = snapshot?.pinned === participant.identity;
|
|
7869
9551
|
const spotlit = snapshot?.spotlight === participant.identity;
|
|
7870
9552
|
const hasAccount = participant.userId !== null;
|
|
7871
|
-
const [refused, setRefused] = (0,
|
|
9553
|
+
const [refused, setRefused] = (0, import_react5.useState)(false);
|
|
7872
9554
|
const act = (request) => {
|
|
7873
9555
|
setRefused(false);
|
|
7874
9556
|
void controls.run(request).then((result) => {
|
|
@@ -7876,10 +9558,10 @@ function PersonMenu({
|
|
|
7876
9558
|
else setRefused(true);
|
|
7877
9559
|
});
|
|
7878
9560
|
};
|
|
7879
|
-
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;
|
|
7880
9562
|
if (mode === "rename" || mode === "report") {
|
|
7881
9563
|
const renaming = mode === "rename";
|
|
7882
|
-
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)(
|
|
7883
9565
|
"form",
|
|
7884
9566
|
{
|
|
7885
9567
|
className: "mx-meet__menu-form",
|
|
@@ -7891,9 +9573,9 @@ function PersonMenu({
|
|
|
7891
9573
|
);
|
|
7892
9574
|
},
|
|
7893
9575
|
children: [
|
|
7894
|
-
/* @__PURE__ */ (0,
|
|
7895
|
-
/* @__PURE__ */ (0,
|
|
7896
|
-
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)(
|
|
7897
9579
|
"input",
|
|
7898
9580
|
{
|
|
7899
9581
|
className: "mx-meet__input",
|
|
@@ -7902,7 +9584,7 @@ function PersonMenu({
|
|
|
7902
9584
|
value: text3,
|
|
7903
9585
|
onChange: (event) => setText(event.target.value)
|
|
7904
9586
|
}
|
|
7905
|
-
) : /* @__PURE__ */ (0,
|
|
9587
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
7906
9588
|
"textarea",
|
|
7907
9589
|
{
|
|
7908
9590
|
className: "mx-meet__input",
|
|
@@ -7915,9 +9597,9 @@ function PersonMenu({
|
|
|
7915
9597
|
)
|
|
7916
9598
|
] }),
|
|
7917
9599
|
refusal2,
|
|
7918
|
-
/* @__PURE__ */ (0,
|
|
7919
|
-
/* @__PURE__ */ (0,
|
|
7920
|
-
/* @__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" })
|
|
7921
9603
|
] })
|
|
7922
9604
|
]
|
|
7923
9605
|
}
|
|
@@ -7925,12 +9607,12 @@ function PersonMenu({
|
|
|
7925
9607
|
}
|
|
7926
9608
|
if (mode === "remove" || mode === "transfer") {
|
|
7927
9609
|
const removing = mode === "remove";
|
|
7928
|
-
return /* @__PURE__ */ (0,
|
|
7929
|
-
/* @__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.` }),
|
|
7930
9612
|
refusal2,
|
|
7931
|
-
/* @__PURE__ */ (0,
|
|
7932
|
-
/* @__PURE__ */ (0,
|
|
7933
|
-
/* @__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)(
|
|
7934
9616
|
"button",
|
|
7935
9617
|
{
|
|
7936
9618
|
type: "button",
|
|
@@ -7943,8 +9625,8 @@ function PersonMenu({
|
|
|
7943
9625
|
] })
|
|
7944
9626
|
] }) });
|
|
7945
9627
|
}
|
|
7946
|
-
return /* @__PURE__ */ (0,
|
|
7947
|
-
/* @__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)(
|
|
7948
9630
|
MenuItem,
|
|
7949
9631
|
{
|
|
7950
9632
|
onSelect: () => {
|
|
@@ -7952,13 +9634,13 @@ function PersonMenu({
|
|
|
7952
9634
|
onClose();
|
|
7953
9635
|
},
|
|
7954
9636
|
children: [
|
|
7955
|
-
/* @__PURE__ */ (0,
|
|
9637
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PinIcon, { width: 16, height: 16 }),
|
|
7956
9638
|
" ",
|
|
7957
9639
|
pinned ? "Unpin" : "Pin for me"
|
|
7958
9640
|
]
|
|
7959
9641
|
}
|
|
7960
9642
|
),
|
|
7961
|
-
!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)(
|
|
7962
9644
|
MenuItem,
|
|
7963
9645
|
{
|
|
7964
9646
|
onSelect: () => {
|
|
@@ -7970,42 +9652,42 @@ function PersonMenu({
|
|
|
7970
9652
|
onClose();
|
|
7971
9653
|
},
|
|
7972
9654
|
children: [
|
|
7973
|
-
/* @__PURE__ */ (0,
|
|
9655
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChatIcon, { width: 16, height: 16 }),
|
|
7974
9656
|
" Message privately"
|
|
7975
9657
|
]
|
|
7976
9658
|
}
|
|
7977
9659
|
) : null,
|
|
7978
|
-
controls.isHost ? /* @__PURE__ */ (0,
|
|
7979
|
-
/* @__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 }),
|
|
7980
9662
|
" ",
|
|
7981
9663
|
spotlit ? "Remove spotlight" : "Spotlight for everyone"
|
|
7982
9664
|
] }) : null,
|
|
7983
|
-
moderate ? /* @__PURE__ */ (0,
|
|
7984
|
-
/* @__PURE__ */ (0,
|
|
7985
|
-
participant.micEnabled ? /* @__PURE__ */ (0,
|
|
7986
|
-
/* @__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 }),
|
|
7987
9669
|
" Mute"
|
|
7988
|
-
] }) : !participant.isAgent ? /* @__PURE__ */ (0,
|
|
7989
|
-
/* @__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 }),
|
|
7990
9672
|
" Ask to unmute"
|
|
7991
9673
|
] }) : null,
|
|
7992
|
-
participant.cameraEnabled ? /* @__PURE__ */ (0,
|
|
7993
|
-
/* @__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 }),
|
|
7994
9676
|
" Stop video"
|
|
7995
9677
|
] }) : null,
|
|
7996
|
-
participant.screenSharing ? /* @__PURE__ */ (0,
|
|
7997
|
-
/* @__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 }),
|
|
7998
9680
|
" Stop screen share"
|
|
7999
9681
|
] }) : null,
|
|
8000
|
-
participant.handRaised ? /* @__PURE__ */ (0,
|
|
8001
|
-
/* @__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 }),
|
|
8002
9684
|
" Lower hand"
|
|
8003
9685
|
] }) : null,
|
|
8004
|
-
hasAccount && !participant.isAgent && participant.role !== "cohost" ? /* @__PURE__ */ (0,
|
|
8005
|
-
/* @__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 }),
|
|
8006
9688
|
" Make co-host"
|
|
8007
9689
|
] }) : null,
|
|
8008
|
-
!participant.isAgent ? /* @__PURE__ */ (0,
|
|
9690
|
+
!participant.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8009
9691
|
MenuItem,
|
|
8010
9692
|
{
|
|
8011
9693
|
onSelect: () => {
|
|
@@ -8013,21 +9695,21 @@ function PersonMenu({
|
|
|
8013
9695
|
setMode("rename");
|
|
8014
9696
|
},
|
|
8015
9697
|
children: [
|
|
8016
|
-
/* @__PURE__ */ (0,
|
|
9698
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PencilIcon, { width: 16, height: 16 }),
|
|
8017
9699
|
" Rename"
|
|
8018
9700
|
]
|
|
8019
9701
|
}
|
|
8020
9702
|
) : null
|
|
8021
9703
|
] }) : null,
|
|
8022
|
-
controls.isOwner && participant.role === "cohost" ? /* @__PURE__ */ (0,
|
|
8023
|
-
/* @__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 }),
|
|
8024
9706
|
" Remove co-host"
|
|
8025
9707
|
] }) : null,
|
|
8026
|
-
controls.isOwner && !self && hasAccount && !participant.isAgent ? /* @__PURE__ */ (0,
|
|
8027
|
-
/* @__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 }),
|
|
8028
9710
|
" Make host"
|
|
8029
9711
|
] }) : null,
|
|
8030
|
-
self ? /* @__PURE__ */ (0,
|
|
9712
|
+
self ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8031
9713
|
MenuItem,
|
|
8032
9714
|
{
|
|
8033
9715
|
onSelect: () => {
|
|
@@ -8035,12 +9717,12 @@ function PersonMenu({
|
|
|
8035
9717
|
setMode("rename");
|
|
8036
9718
|
},
|
|
8037
9719
|
children: [
|
|
8038
|
-
/* @__PURE__ */ (0,
|
|
9720
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PencilIcon, { width: 16, height: 16 }),
|
|
8039
9721
|
" Rename yourself"
|
|
8040
9722
|
]
|
|
8041
9723
|
}
|
|
8042
9724
|
) : null,
|
|
8043
|
-
!self && !participant.isAgent ? /* @__PURE__ */ (0,
|
|
9725
|
+
!self && !participant.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8044
9726
|
MenuItem,
|
|
8045
9727
|
{
|
|
8046
9728
|
onSelect: () => {
|
|
@@ -8048,21 +9730,21 @@ function PersonMenu({
|
|
|
8048
9730
|
setMode("report");
|
|
8049
9731
|
},
|
|
8050
9732
|
children: [
|
|
8051
|
-
/* @__PURE__ */ (0,
|
|
9733
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(FlagIcon, { width: 16, height: 16 }),
|
|
8052
9734
|
" Report"
|
|
8053
9735
|
]
|
|
8054
9736
|
}
|
|
8055
9737
|
) : null,
|
|
8056
|
-
moderate && !participant.isAgent ? /* @__PURE__ */ (0,
|
|
8057
|
-
/* @__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 }),
|
|
8058
9740
|
" Remove from meeting"
|
|
8059
9741
|
] }) : null
|
|
8060
9742
|
] }) });
|
|
8061
9743
|
}
|
|
8062
9744
|
function SettingsPanel({ onClose }) {
|
|
8063
9745
|
const host = useRequiredMeetHost();
|
|
8064
|
-
return /* @__PURE__ */ (0,
|
|
8065
|
-
/* @__PURE__ */ (0,
|
|
9746
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(PanelShell, { title: "Settings", onClose, children: [
|
|
9747
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8066
9748
|
DeviceSettings,
|
|
8067
9749
|
{
|
|
8068
9750
|
onPick: (kind, deviceId2) => {
|
|
@@ -8071,7 +9753,8 @@ function SettingsPanel({ onClose }) {
|
|
|
8071
9753
|
}
|
|
8072
9754
|
}
|
|
8073
9755
|
),
|
|
8074
|
-
/* @__PURE__ */ (0,
|
|
9756
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(EffectsSettings, {}),
|
|
9757
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CaptionLanguageSettings, {})
|
|
8075
9758
|
] });
|
|
8076
9759
|
}
|
|
8077
9760
|
function DeviceSettings({
|
|
@@ -8083,15 +9766,15 @@ function DeviceSettings({
|
|
|
8083
9766
|
const speaker = devices?.selected.audiooutput ?? host.devices.resolve("audiooutput");
|
|
8084
9767
|
const stream = useMicrophoneStream(microphone);
|
|
8085
9768
|
const level = useAudioLevel(stream);
|
|
8086
|
-
const [testing, setTesting] = (0,
|
|
8087
|
-
(0,
|
|
9769
|
+
const [testing, setTesting] = (0, import_react5.useState)(false);
|
|
9770
|
+
(0, import_react5.useEffect)(() => {
|
|
8088
9771
|
void host.devices.refresh();
|
|
8089
9772
|
}, [host]);
|
|
8090
|
-
return /* @__PURE__ */ (0,
|
|
8091
|
-
/* @__PURE__ */ (0,
|
|
8092
|
-
/* @__PURE__ */ (0,
|
|
8093
|
-
/* @__PURE__ */ (0,
|
|
8094
|
-
/* @__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)(
|
|
8095
9778
|
"button",
|
|
8096
9779
|
{
|
|
8097
9780
|
type: "button",
|
|
@@ -8102,19 +9785,19 @@ function DeviceSettings({
|
|
|
8102
9785
|
void playTestSound(speaker).finally(() => setTesting(false));
|
|
8103
9786
|
},
|
|
8104
9787
|
children: [
|
|
8105
|
-
/* @__PURE__ */ (0,
|
|
9788
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SpeakerIcon, { width: 14, height: 14 }),
|
|
8106
9789
|
" ",
|
|
8107
9790
|
testing ? "Playing\u2026" : "Test speaker"
|
|
8108
9791
|
]
|
|
8109
9792
|
}
|
|
8110
9793
|
),
|
|
8111
|
-
/* @__PURE__ */ (0,
|
|
9794
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DevicePicker, { kind: "videoinput", label: "Camera", onPick })
|
|
8112
9795
|
] });
|
|
8113
9796
|
}
|
|
8114
9797
|
function EffectsSettings({ preview }) {
|
|
8115
9798
|
const effects = useMediaEffects();
|
|
8116
|
-
const [error, setError] = (0,
|
|
8117
|
-
const fileRef = (0,
|
|
9799
|
+
const [error, setError] = (0, import_react5.useState)(null);
|
|
9800
|
+
const fileRef = (0, import_react5.useRef)(null);
|
|
8118
9801
|
const supported = effects.backgroundsSupported || preview != null || videoEffectsSupported();
|
|
8119
9802
|
const apply = (next) => {
|
|
8120
9803
|
setError(null);
|
|
@@ -8126,9 +9809,9 @@ function EffectsSettings({ preview }) {
|
|
|
8126
9809
|
);
|
|
8127
9810
|
}
|
|
8128
9811
|
};
|
|
8129
|
-
return /* @__PURE__ */ (0,
|
|
8130
|
-
/* @__PURE__ */ (0,
|
|
8131
|
-
/* @__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)(
|
|
8132
9815
|
"input",
|
|
8133
9816
|
{
|
|
8134
9817
|
type: "checkbox",
|
|
@@ -8137,11 +9820,11 @@ function EffectsSettings({ preview }) {
|
|
|
8137
9820
|
}
|
|
8138
9821
|
),
|
|
8139
9822
|
"Noise suppression",
|
|
8140
|
-
/* @__PURE__ */ (0,
|
|
9823
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__hint", children: "Filters keyboards, fans and background chatter." })
|
|
8141
9824
|
] }),
|
|
8142
|
-
supported ? /* @__PURE__ */ (0,
|
|
8143
|
-
/* @__PURE__ */ (0,
|
|
8144
|
-
/* @__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)(
|
|
8145
9828
|
"button",
|
|
8146
9829
|
{
|
|
8147
9830
|
type: "button",
|
|
@@ -8159,7 +9842,7 @@ function EffectsSettings({ preview }) {
|
|
|
8159
9842
|
},
|
|
8160
9843
|
kind
|
|
8161
9844
|
)) }),
|
|
8162
|
-
/* @__PURE__ */ (0,
|
|
9845
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8163
9846
|
"input",
|
|
8164
9847
|
{
|
|
8165
9848
|
ref: fileRef,
|
|
@@ -8174,7 +9857,7 @@ function EffectsSettings({ preview }) {
|
|
|
8174
9857
|
}
|
|
8175
9858
|
}
|
|
8176
9859
|
),
|
|
8177
|
-
error !== null ? /* @__PURE__ */ (0,
|
|
9860
|
+
error !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__error", children: error }) : null
|
|
8178
9861
|
] }) : null
|
|
8179
9862
|
] });
|
|
8180
9863
|
}
|
|
@@ -8233,8 +9916,8 @@ async function playTestSound(sinkId) {
|
|
|
8233
9916
|
await context.close();
|
|
8234
9917
|
}
|
|
8235
9918
|
function useMicrophoneStream(deviceId2) {
|
|
8236
|
-
const [stream, setStream] = (0,
|
|
8237
|
-
(0,
|
|
9919
|
+
const [stream, setStream] = (0, import_react5.useState)(null);
|
|
9920
|
+
(0, import_react5.useEffect)(() => {
|
|
8238
9921
|
if (deviceId2 === "off") return void 0;
|
|
8239
9922
|
let live = true;
|
|
8240
9923
|
let opened = null;
|
|
@@ -8259,25 +9942,25 @@ function useMicrophoneStream(deviceId2) {
|
|
|
8259
9942
|
function LobbyPanel() {
|
|
8260
9943
|
const lobby = useLobby();
|
|
8261
9944
|
if (!lobby.canAdmit || lobby.waiting.length === 0) return null;
|
|
8262
|
-
return /* @__PURE__ */ (0,
|
|
8263
|
-
/* @__PURE__ */ (0,
|
|
8264
|
-
/* @__PURE__ */ (0,
|
|
8265
|
-
/* @__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" })
|
|
8266
9949
|
] }),
|
|
8267
|
-
/* @__PURE__ */ (0,
|
|
8268
|
-
/* @__PURE__ */ (0,
|
|
8269
|
-
/* @__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: [
|
|
8270
9953
|
entry.displayName,
|
|
8271
|
-
entry.userId === null ? /* @__PURE__ */ (0,
|
|
9954
|
+
entry.userId === null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Guest" }) : null
|
|
8272
9955
|
] }),
|
|
8273
|
-
/* @__PURE__ */ (0,
|
|
8274
|
-
/* @__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)(
|
|
8275
9958
|
ControlButton,
|
|
8276
9959
|
{
|
|
8277
9960
|
label: `Deny ${entry.displayName}`,
|
|
8278
9961
|
danger: true,
|
|
8279
9962
|
onClick: () => void lobby.deny(entry),
|
|
8280
|
-
children: /* @__PURE__ */ (0,
|
|
9963
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CloseIcon, { width: 16, height: 16 })
|
|
8281
9964
|
}
|
|
8282
9965
|
)
|
|
8283
9966
|
] }, entry.identity)) })
|
|
@@ -8287,21 +9970,21 @@ function NoteTakerRow() {
|
|
|
8287
9970
|
const ai = useMeetAi();
|
|
8288
9971
|
const status = ai.noteTaker;
|
|
8289
9972
|
const duplicateError = status.refusal !== null && ai.error !== null && status.refusal.reason === ai.error.message && status.refusal.remedy === ai.error.remedy;
|
|
8290
|
-
return /* @__PURE__ */ (0,
|
|
8291
|
-
/* @__PURE__ */ (0,
|
|
8292
|
-
/* @__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" }),
|
|
8293
9976
|
ai.noteTakerLabel
|
|
8294
9977
|
] }),
|
|
8295
|
-
status.detail !== null ? /* @__PURE__ */ (0,
|
|
8296
|
-
status.refusal !== null ? /* @__PURE__ */ (0,
|
|
8297
|
-
/* @__PURE__ */ (0,
|
|
8298
|
-
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
|
|
8299
9982
|
] }) : null,
|
|
8300
|
-
ai.error !== null && !duplicateError ? /* @__PURE__ */ (0,
|
|
8301
|
-
/* @__PURE__ */ (0,
|
|
8302
|
-
/* @__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 })
|
|
8303
9986
|
] }) : null,
|
|
8304
|
-
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)(
|
|
8305
9988
|
"button",
|
|
8306
9989
|
{
|
|
8307
9990
|
type: "button",
|
|
@@ -8309,7 +9992,7 @@ function NoteTakerRow() {
|
|
|
8309
9992
|
onClick: () => void ai.stopNoteTaker(),
|
|
8310
9993
|
children: "Dismiss the note-taker"
|
|
8311
9994
|
}
|
|
8312
|
-
) : /* @__PURE__ */ (0,
|
|
9995
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8313
9996
|
"button",
|
|
8314
9997
|
{
|
|
8315
9998
|
type: "button",
|
|
@@ -8325,24 +10008,24 @@ function NoteList({
|
|
|
8325
10008
|
notes,
|
|
8326
10009
|
empty
|
|
8327
10010
|
}) {
|
|
8328
|
-
return /* @__PURE__ */ (0,
|
|
8329
|
-
/* @__PURE__ */ (0,
|
|
8330
|
-
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: [
|
|
8331
10014
|
note.text,
|
|
8332
|
-
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
|
|
8333
10016
|
] }, note.id)) })
|
|
8334
10017
|
] });
|
|
8335
10018
|
}
|
|
8336
10019
|
function AiPanel({ onClose }) {
|
|
8337
10020
|
const ai = useMeetAi();
|
|
8338
|
-
const [question, setQuestion] = (0,
|
|
8339
|
-
return /* @__PURE__ */ (0,
|
|
8340
|
-
/* @__PURE__ */ (0,
|
|
8341
|
-
ai.summary !== null ? /* @__PURE__ */ (0,
|
|
8342
|
-
/* @__PURE__ */ (0,
|
|
8343
|
-
/* @__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 })
|
|
8344
10027
|
] }) : null,
|
|
8345
|
-
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: [
|
|
8346
10029
|
"The wrap-up is written \u2014 ",
|
|
8347
10030
|
ai.wrapUp.noteIds.length,
|
|
8348
10031
|
" ",
|
|
@@ -8354,7 +10037,7 @@ function AiPanel({ onClose }) {
|
|
|
8354
10037
|
ai.wrapUp.segmentCount === 1 ? "transcript line" : "transcript lines",
|
|
8355
10038
|
"."
|
|
8356
10039
|
] }) : null,
|
|
8357
|
-
/* @__PURE__ */ (0,
|
|
10040
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8358
10041
|
NoteList,
|
|
8359
10042
|
{
|
|
8360
10043
|
title: "Notes",
|
|
@@ -8362,7 +10045,7 @@ function AiPanel({ onClose }) {
|
|
|
8362
10045
|
empty: "Notes appear here as the meeting goes on."
|
|
8363
10046
|
}
|
|
8364
10047
|
),
|
|
8365
|
-
/* @__PURE__ */ (0,
|
|
10048
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8366
10049
|
NoteList,
|
|
8367
10050
|
{
|
|
8368
10051
|
title: "Decisions",
|
|
@@ -8370,7 +10053,7 @@ function AiPanel({ onClose }) {
|
|
|
8370
10053
|
empty: "Nothing has been decided yet."
|
|
8371
10054
|
}
|
|
8372
10055
|
),
|
|
8373
|
-
/* @__PURE__ */ (0,
|
|
10056
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8374
10057
|
NoteList,
|
|
8375
10058
|
{
|
|
8376
10059
|
title: "Action items",
|
|
@@ -8378,21 +10061,21 @@ function AiPanel({ onClose }) {
|
|
|
8378
10061
|
empty: "No action items yet."
|
|
8379
10062
|
}
|
|
8380
10063
|
),
|
|
8381
|
-
ai.transcript.length > 0 ? /* @__PURE__ */ (0,
|
|
8382
|
-
/* @__PURE__ */ (0,
|
|
8383
|
-
/* @__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)(
|
|
8384
10067
|
"li",
|
|
8385
10068
|
{
|
|
8386
10069
|
className: line.final && line.source === "record" ? "mx-meet__line" : "mx-meet__line mx-meet__line--interim",
|
|
8387
10070
|
children: [
|
|
8388
|
-
/* @__PURE__ */ (0,
|
|
8389
|
-
/* @__PURE__ */ (0,
|
|
10071
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("strong", { children: line.speaker }),
|
|
10072
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: line.text })
|
|
8390
10073
|
]
|
|
8391
10074
|
},
|
|
8392
10075
|
line.id
|
|
8393
10076
|
)) })
|
|
8394
10077
|
] }) : null,
|
|
8395
|
-
/* @__PURE__ */ (0,
|
|
10078
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
8396
10079
|
"form",
|
|
8397
10080
|
{
|
|
8398
10081
|
className: "mx-meet__composer",
|
|
@@ -8403,7 +10086,7 @@ function AiPanel({ onClose }) {
|
|
|
8403
10086
|
void ai.ask(asked);
|
|
8404
10087
|
},
|
|
8405
10088
|
children: [
|
|
8406
|
-
/* @__PURE__ */ (0,
|
|
10089
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8407
10090
|
"input",
|
|
8408
10091
|
{
|
|
8409
10092
|
className: "mx-meet__input",
|
|
@@ -8413,13 +10096,13 @@ function AiPanel({ onClose }) {
|
|
|
8413
10096
|
"aria-label": "Ask about this meeting"
|
|
8414
10097
|
}
|
|
8415
10098
|
),
|
|
8416
|
-
/* @__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" })
|
|
8417
10100
|
]
|
|
8418
10101
|
}
|
|
8419
10102
|
),
|
|
8420
|
-
ai.asking && ai.phase !== null ? /* @__PURE__ */ (0,
|
|
8421
|
-
ai.answer !== null ? /* @__PURE__ */ (0,
|
|
8422
|
-
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: [
|
|
8423
10106
|
"Answered from ",
|
|
8424
10107
|
ai.coverage.segmentsUsed,
|
|
8425
10108
|
" of ",
|
|
@@ -8428,48 +10111,56 @@ function AiPanel({ onClose }) {
|
|
|
8428
10111
|
ai.coverage.truncated ? " (the oldest were left out)" : "",
|
|
8429
10112
|
"."
|
|
8430
10113
|
] }) : null,
|
|
8431
|
-
ai.error !== null ? /* @__PURE__ */ (0,
|
|
8432
|
-
/* @__PURE__ */ (0,
|
|
8433
|
-
/* @__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 })
|
|
8434
10117
|
] }) : null
|
|
8435
10118
|
] });
|
|
8436
10119
|
}
|
|
8437
10120
|
function Captions({ lines = 3 }) {
|
|
8438
10121
|
const ai = useMeetAi();
|
|
8439
10122
|
const visible = ai.transcript.slice(-lines);
|
|
10123
|
+
const translation = useCaptionTranslation(visible);
|
|
8440
10124
|
if (visible.length === 0) return null;
|
|
8441
|
-
return /* @__PURE__ */ (0,
|
|
8442
|
-
|
|
8443
|
-
|
|
8444
|
-
|
|
8445
|
-
|
|
8446
|
-
|
|
8447
|
-
|
|
8448
|
-
|
|
8449
|
-
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
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
|
+
] });
|
|
8453
10144
|
}
|
|
8454
10145
|
function ConsentNotice() {
|
|
8455
10146
|
const notice = useConsentNotice();
|
|
8456
10147
|
if (notice === null) return null;
|
|
8457
|
-
return /* @__PURE__ */ (0,
|
|
10148
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__consent", role: "status", children: notice });
|
|
8458
10149
|
}
|
|
8459
10150
|
function AttendanceNotice() {
|
|
8460
10151
|
const media = useLocalMedia();
|
|
8461
10152
|
const notice = listenOnlyNotice(media);
|
|
8462
10153
|
if (notice === null) return null;
|
|
8463
10154
|
const refused = media.microphone.unavailable;
|
|
8464
|
-
return /* @__PURE__ */ (0,
|
|
10155
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__banner mx-meet__banner--attendance", role: "status", children: [
|
|
8465
10156
|
notice,
|
|
8466
|
-
refused === null ? null : /* @__PURE__ */ (0,
|
|
10157
|
+
refused === null ? null : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__remedy", children: refused.remedy })
|
|
8467
10158
|
] });
|
|
8468
10159
|
}
|
|
8469
10160
|
function PreJoin(props) {
|
|
8470
10161
|
const host = useMeetHost();
|
|
8471
|
-
if (host === null) return /* @__PURE__ */ (0,
|
|
8472
|
-
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 });
|
|
8473
10164
|
}
|
|
8474
10165
|
function PreJoinBody({
|
|
8475
10166
|
roomName,
|
|
@@ -8483,21 +10174,21 @@ function PreJoinBody({
|
|
|
8483
10174
|
const recording = useRecording();
|
|
8484
10175
|
const effects = useMediaEffects();
|
|
8485
10176
|
const { notice } = useModerationNotice();
|
|
8486
|
-
const [mode, setMode] = (0,
|
|
8487
|
-
const [microphone, setMicrophone] = (0,
|
|
8488
|
-
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);
|
|
8489
10180
|
const camera = devices?.selected.videoinput ?? host.devices.resolve("videoinput");
|
|
8490
10181
|
const mic = devices?.selected.audioinput ?? host.devices.resolve("audioinput");
|
|
8491
10182
|
const preview = useCameraPreview(mode === "video" ? camera : void 0, effects.effects);
|
|
8492
10183
|
const micStream = useMicrophoneStream(microphone ? mic : "off");
|
|
8493
10184
|
const level = useAudioLevel(micStream);
|
|
8494
|
-
const [speakerTesting, setSpeakerTesting] = (0,
|
|
8495
|
-
(0,
|
|
10185
|
+
const [speakerTesting, setSpeakerTesting] = (0, import_react5.useState)(false);
|
|
10186
|
+
(0, import_react5.useEffect)(() => {
|
|
8496
10187
|
void host.devices.refresh();
|
|
8497
10188
|
}, [host]);
|
|
8498
|
-
return /* @__PURE__ */ (0,
|
|
8499
|
-
/* @__PURE__ */ (0,
|
|
8500
|
-
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)(
|
|
8501
10192
|
"video",
|
|
8502
10193
|
{
|
|
8503
10194
|
className: "mx-meet__video mx-meet__video--mirror",
|
|
@@ -8508,16 +10199,16 @@ function PreJoinBody({
|
|
|
8508
10199
|
if (element !== null) preview.preview?.attach(element);
|
|
8509
10200
|
}
|
|
8510
10201
|
}
|
|
8511
|
-
) : /* @__PURE__ */ (0,
|
|
8512
|
-
mode === "video" && preview.error !== null ? /* @__PURE__ */ (0,
|
|
8513
|
-
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
|
|
8514
10205
|
] }),
|
|
8515
|
-
/* @__PURE__ */ (0,
|
|
8516
|
-
/* @__PURE__ */ (0,
|
|
8517
|
-
notice?.kind === "removed" ? /* @__PURE__ */ (0,
|
|
8518
|
-
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: [
|
|
8519
10210
|
"Your browser is hiding device names until you allow camera and microphone access.",
|
|
8520
|
-
/* @__PURE__ */ (0,
|
|
10211
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8521
10212
|
"button",
|
|
8522
10213
|
{
|
|
8523
10214
|
type: "button",
|
|
@@ -8529,11 +10220,11 @@ function PreJoinBody({
|
|
|
8529
10220
|
}
|
|
8530
10221
|
)
|
|
8531
10222
|
] }) : null,
|
|
8532
|
-
devices?.fallbackNotice != null ? /* @__PURE__ */ (0,
|
|
8533
|
-
/* @__PURE__ */ (0,
|
|
8534
|
-
/* @__PURE__ */ (0,
|
|
8535
|
-
/* @__PURE__ */ (0,
|
|
8536
|
-
/* @__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)(
|
|
8537
10228
|
"button",
|
|
8538
10229
|
{
|
|
8539
10230
|
type: "button",
|
|
@@ -8546,19 +10237,19 @@ function PreJoinBody({
|
|
|
8546
10237
|
);
|
|
8547
10238
|
},
|
|
8548
10239
|
children: [
|
|
8549
|
-
/* @__PURE__ */ (0,
|
|
10240
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(SpeakerIcon, { width: 14, height: 14 }),
|
|
8550
10241
|
" ",
|
|
8551
10242
|
speakerTesting ? "Playing\u2026" : "Test"
|
|
8552
10243
|
]
|
|
8553
10244
|
}
|
|
8554
10245
|
)
|
|
8555
10246
|
] }),
|
|
8556
|
-
/* @__PURE__ */ (0,
|
|
8557
|
-
/* @__PURE__ */ (0,
|
|
8558
|
-
recording.consentNotice !== null ? /* @__PURE__ */ (0,
|
|
8559
|
-
/* @__PURE__ */ (0,
|
|
8560
|
-
/* @__PURE__ */ (0,
|
|
8561
|
-
/* @__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)(
|
|
8562
10253
|
"input",
|
|
8563
10254
|
{
|
|
8564
10255
|
type: "checkbox",
|
|
@@ -8568,8 +10259,8 @@ function PreJoinBody({
|
|
|
8568
10259
|
),
|
|
8569
10260
|
"Join with video"
|
|
8570
10261
|
] }),
|
|
8571
|
-
/* @__PURE__ */ (0,
|
|
8572
|
-
/* @__PURE__ */ (0,
|
|
10262
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("label", { className: "mx-meet__toggle", children: [
|
|
10263
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8573
10264
|
"input",
|
|
8574
10265
|
{
|
|
8575
10266
|
type: "checkbox",
|
|
@@ -8579,7 +10270,7 @@ function PreJoinBody({
|
|
|
8579
10270
|
),
|
|
8580
10271
|
"Join with microphone"
|
|
8581
10272
|
] }),
|
|
8582
|
-
/* @__PURE__ */ (0,
|
|
10273
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8583
10274
|
"button",
|
|
8584
10275
|
{
|
|
8585
10276
|
type: "button",
|
|
@@ -8599,20 +10290,20 @@ function PreJoinBody({
|
|
|
8599
10290
|
}
|
|
8600
10291
|
)
|
|
8601
10292
|
] }),
|
|
8602
|
-
room.failure !== null ? /* @__PURE__ */ (0,
|
|
10293
|
+
room.failure !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__error", children: [
|
|
8603
10294
|
room.failure.message,
|
|
8604
|
-
/* @__PURE__ */ (0,
|
|
10295
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__remedy", children: room.failure.remedy })
|
|
8605
10296
|
] }) : null
|
|
8606
10297
|
] })
|
|
8607
10298
|
] });
|
|
8608
10299
|
}
|
|
8609
10300
|
function useCameraPreview(deviceId2, effects) {
|
|
8610
|
-
const [preview, setPreview] = (0,
|
|
8611
|
-
const [error, setError] = (0,
|
|
8612
|
-
const current = (0,
|
|
8613
|
-
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));
|
|
8614
10305
|
initialEffect.current = toVideoEffect(effects);
|
|
8615
|
-
(0,
|
|
10306
|
+
(0, import_react5.useEffect)(() => {
|
|
8616
10307
|
if (deviceId2 === void 0) return void 0;
|
|
8617
10308
|
let live = true;
|
|
8618
10309
|
setError(null);
|
|
@@ -8656,9 +10347,9 @@ function DevicePicker({
|
|
|
8656
10347
|
const devices = useDeviceSnapshot();
|
|
8657
10348
|
const list = devices?.devices[kind] ?? [];
|
|
8658
10349
|
if (list.length === 0) return null;
|
|
8659
|
-
return /* @__PURE__ */ (0,
|
|
8660
|
-
/* @__PURE__ */ (0,
|
|
8661
|
-
/* @__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)(
|
|
8662
10353
|
"select",
|
|
8663
10354
|
{
|
|
8664
10355
|
className: "mx-meet__select",
|
|
@@ -8667,7 +10358,7 @@ function DevicePicker({
|
|
|
8667
10358
|
if (onPick !== void 0) onPick(kind, event.target.value);
|
|
8668
10359
|
else host.devices.select(kind, event.target.value);
|
|
8669
10360
|
},
|
|
8670
|
-
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))
|
|
8671
10362
|
}
|
|
8672
10363
|
)
|
|
8673
10364
|
] });
|
|
@@ -8675,9 +10366,9 @@ function DevicePicker({
|
|
|
8675
10366
|
function MeetingRoom(props) {
|
|
8676
10367
|
const host = useMeetHost();
|
|
8677
10368
|
if (host === null) {
|
|
8678
|
-
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" }) });
|
|
8679
10370
|
}
|
|
8680
|
-
return /* @__PURE__ */ (0,
|
|
10371
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MeetingRoomBody, { ...props, host });
|
|
8681
10372
|
}
|
|
8682
10373
|
function MeetingRoomBody({
|
|
8683
10374
|
roomName,
|
|
@@ -8692,25 +10383,25 @@ function MeetingRoomBody({
|
|
|
8692
10383
|
const isHost = useIsHost();
|
|
8693
10384
|
const elapsed = useElapsed(snapshot?.meeting?.startedAt ?? null);
|
|
8694
10385
|
const phase = snapshot?.phase ?? "idle";
|
|
8695
|
-
(0,
|
|
10386
|
+
(0, import_react5.useEffect)(() => {
|
|
8696
10387
|
host.meetings.watch(roomName);
|
|
8697
10388
|
}, [host, roomName]);
|
|
8698
|
-
(0,
|
|
10389
|
+
(0, import_react5.useEffect)(() => {
|
|
8699
10390
|
if (given === void 0) return;
|
|
8700
10391
|
if (host.store.snapshot().meeting !== null) return;
|
|
8701
10392
|
host.store.patch({ meeting: given, locked: given.locked });
|
|
8702
10393
|
}, [host, given]);
|
|
8703
10394
|
const watchedId = meetingId ?? snapshot?.meeting?.id ?? null;
|
|
8704
|
-
(0,
|
|
10395
|
+
(0, import_react5.useEffect)(() => {
|
|
8705
10396
|
if (watchedId === null) return;
|
|
8706
10397
|
host.meetings.watchMeeting(asMeetingId(watchedId));
|
|
8707
10398
|
}, [host, watchedId]);
|
|
8708
10399
|
const record = snapshot?.meeting ?? given ?? null;
|
|
8709
10400
|
if (hasEnded(record) && phase !== "connected" && phase !== "reconnecting") {
|
|
8710
|
-
return /* @__PURE__ */ (0,
|
|
10401
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MeetingRecordView, { meeting: record });
|
|
8711
10402
|
}
|
|
8712
10403
|
if (phase === "idle" || phase === "failed" || phase === "left") {
|
|
8713
|
-
return /* @__PURE__ */ (0,
|
|
10404
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8714
10405
|
PreJoin,
|
|
8715
10406
|
{
|
|
8716
10407
|
roomName,
|
|
@@ -8720,42 +10411,42 @@ function MeetingRoomBody({
|
|
|
8720
10411
|
) });
|
|
8721
10412
|
}
|
|
8722
10413
|
if (phase === "lobby") {
|
|
8723
|
-
return /* @__PURE__ */ (0,
|
|
8724
|
-
}
|
|
8725
|
-
return /* @__PURE__ */ (0,
|
|
8726
|
-
/* @__PURE__ */ (0,
|
|
8727
|
-
/* @__PURE__ */ (0,
|
|
8728
|
-
/* @__PURE__ */ (0,
|
|
8729
|
-
/* @__PURE__ */ (0,
|
|
8730
|
-
/* @__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: [
|
|
8731
10422
|
participantSummary(snapshot?.participants ?? []),
|
|
8732
10423
|
elapsed > 0 ? ` \xB7 ${(0, import_format3.formatDurationMs)(elapsed)}` : ""
|
|
8733
10424
|
] }),
|
|
8734
|
-
/* @__PURE__ */ (0,
|
|
8735
|
-
snapshot?.locked === true ? /* @__PURE__ */ (0,
|
|
8736
|
-
/* @__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 }),
|
|
8737
10428
|
" Locked"
|
|
8738
10429
|
] }) : null,
|
|
8739
|
-
headerControls !== void 0 && headerControls !== null ? /* @__PURE__ */ (0,
|
|
8740
|
-
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
|
|
8741
10432
|
] }),
|
|
8742
|
-
phase === "reconnecting" ? /* @__PURE__ */ (0,
|
|
8743
|
-
/* @__PURE__ */ (0,
|
|
8744
|
-
/* @__PURE__ */ (0,
|
|
8745
|
-
/* @__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 } : {} })
|
|
8746
10437
|
] });
|
|
8747
10438
|
}
|
|
8748
10439
|
function WaitingRoom({ roomName, host }) {
|
|
8749
|
-
const knocked = (0,
|
|
8750
|
-
(0,
|
|
10440
|
+
const knocked = (0, import_react5.useRef)(false);
|
|
10441
|
+
(0, import_react5.useEffect)(() => {
|
|
8751
10442
|
if (knocked.current) return;
|
|
8752
10443
|
knocked.current = true;
|
|
8753
10444
|
host.meetings.knock(roomName);
|
|
8754
10445
|
}, [host, roomName]);
|
|
8755
|
-
return /* @__PURE__ */ (0,
|
|
8756
|
-
/* @__PURE__ */ (0,
|
|
8757
|
-
/* @__PURE__ */ (0,
|
|
8758
|
-
/* @__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: [
|
|
8759
10450
|
"You are in the waiting room as ",
|
|
8760
10451
|
host.identity.displayName,
|
|
8761
10452
|
". You will join automatically once you are admitted."
|
|
@@ -8766,10 +10457,10 @@ function HostMenu() {
|
|
|
8766
10457
|
const host = useRequiredMeetHost();
|
|
8767
10458
|
const snapshot = useMeetSnapshot();
|
|
8768
10459
|
const end = useEndMeeting();
|
|
8769
|
-
const [confirmingEnd, setConfirmingEnd] = (0,
|
|
10460
|
+
const [confirmingEnd, setConfirmingEnd] = (0, import_react5.useState)(false);
|
|
8770
10461
|
const locked = snapshot?.locked === true;
|
|
8771
|
-
return /* @__PURE__ */ (0,
|
|
8772
|
-
/* @__PURE__ */ (0,
|
|
10462
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__host-menu", children: [
|
|
10463
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8773
10464
|
"button",
|
|
8774
10465
|
{
|
|
8775
10466
|
type: "button",
|
|
@@ -8780,9 +10471,9 @@ function HostMenu() {
|
|
|
8780
10471
|
children: locked ? "Unlock meeting" : "Lock meeting"
|
|
8781
10472
|
}
|
|
8782
10473
|
),
|
|
8783
|
-
end.canEnd ? confirmingEnd ? /* @__PURE__ */ (0,
|
|
8784
|
-
/* @__PURE__ */ (0,
|
|
8785
|
-
/* @__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)(
|
|
8786
10477
|
"button",
|
|
8787
10478
|
{
|
|
8788
10479
|
type: "button",
|
|
@@ -8794,7 +10485,7 @@ function HostMenu() {
|
|
|
8794
10485
|
children: "End it"
|
|
8795
10486
|
}
|
|
8796
10487
|
),
|
|
8797
|
-
/* @__PURE__ */ (0,
|
|
10488
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8798
10489
|
"button",
|
|
8799
10490
|
{
|
|
8800
10491
|
type: "button",
|
|
@@ -8803,7 +10494,7 @@ function HostMenu() {
|
|
|
8803
10494
|
children: "Keep it running"
|
|
8804
10495
|
}
|
|
8805
10496
|
)
|
|
8806
|
-
] }) : /* @__PURE__ */ (0,
|
|
10497
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8807
10498
|
"button",
|
|
8808
10499
|
{
|
|
8809
10500
|
type: "button",
|
|
@@ -8812,7 +10503,7 @@ function HostMenu() {
|
|
|
8812
10503
|
children: end.ending ? "Ending\u2026" : "End meeting for everyone"
|
|
8813
10504
|
}
|
|
8814
10505
|
) : null,
|
|
8815
|
-
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
|
|
8816
10507
|
] });
|
|
8817
10508
|
}
|
|
8818
10509
|
function CallButton({
|
|
@@ -8822,7 +10513,7 @@ function CallButton({
|
|
|
8822
10513
|
}) {
|
|
8823
10514
|
const calls = useCalls();
|
|
8824
10515
|
if (!calls.canCall) return null;
|
|
8825
|
-
return /* @__PURE__ */ (0,
|
|
10516
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
8826
10517
|
"button",
|
|
8827
10518
|
{
|
|
8828
10519
|
type: "button",
|
|
@@ -8831,55 +10522,55 @@ function CallButton({
|
|
|
8831
10522
|
void calls.call([person.userId], mode);
|
|
8832
10523
|
},
|
|
8833
10524
|
"aria-label": `Call ${person.displayName}`,
|
|
8834
|
-
children: children ?? /* @__PURE__ */ (0,
|
|
10525
|
+
children: children ?? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(PhoneIcon, { width: 18, height: 18 })
|
|
8835
10526
|
}
|
|
8836
10527
|
);
|
|
8837
10528
|
}
|
|
8838
10529
|
function IncomingCallHost() {
|
|
8839
10530
|
const calls = useCalls();
|
|
8840
10531
|
if (calls.incoming.length === 0) return null;
|
|
8841
|
-
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)) });
|
|
8842
10533
|
}
|
|
8843
10534
|
function IncomingCallCard({ invite }) {
|
|
8844
10535
|
const calls = useCalls();
|
|
8845
|
-
return /* @__PURE__ */ (0,
|
|
8846
|
-
/* @__PURE__ */ (0,
|
|
8847
|
-
/* @__PURE__ */ (0,
|
|
8848
|
-
/* @__PURE__ */ (0,
|
|
8849
|
-
/* @__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" })
|
|
8850
10541
|
] }),
|
|
8851
|
-
/* @__PURE__ */ (0,
|
|
8852
|
-
/* @__PURE__ */ (0,
|
|
8853
|
-
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)(
|
|
8854
10545
|
ControlButton,
|
|
8855
10546
|
{
|
|
8856
10547
|
label: "Accept without video",
|
|
8857
10548
|
onClick: () => void calls.accept({ ...invite, mode: "audio" }),
|
|
8858
|
-
children: /* @__PURE__ */ (0,
|
|
10549
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(CameraOffIcon, {})
|
|
8859
10550
|
}
|
|
8860
10551
|
) : null,
|
|
8861
|
-
/* @__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, {}) })
|
|
8862
10553
|
] })
|
|
8863
10554
|
] });
|
|
8864
10555
|
}
|
|
8865
10556
|
function ScheduleMeeting(props) {
|
|
8866
10557
|
const host = useMeetHost();
|
|
8867
|
-
if (host === null) return /* @__PURE__ */ (0,
|
|
8868
|
-
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 });
|
|
8869
10560
|
}
|
|
8870
10561
|
function ScheduleMeetingBody({
|
|
8871
10562
|
appBaseUrl,
|
|
8872
10563
|
onScheduled,
|
|
8873
10564
|
host
|
|
8874
10565
|
}) {
|
|
8875
|
-
const [title, setTitle] = (0,
|
|
8876
|
-
const [when2, setWhen] = (0,
|
|
8877
|
-
const [kind, setKind] = (0,
|
|
8878
|
-
const [busy, setBusy] = (0,
|
|
8879
|
-
const [link, setLink] = (0,
|
|
8880
|
-
const [error, setError] = (0,
|
|
8881
|
-
const disabled = (0,
|
|
8882
|
-
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)(
|
|
8883
10574
|
"form",
|
|
8884
10575
|
{
|
|
8885
10576
|
className: "mx-meet__schedule",
|
|
@@ -8904,9 +10595,9 @@ function ScheduleMeetingBody({
|
|
|
8904
10595
|
}).finally(() => setBusy(false));
|
|
8905
10596
|
},
|
|
8906
10597
|
children: [
|
|
8907
|
-
/* @__PURE__ */ (0,
|
|
8908
|
-
/* @__PURE__ */ (0,
|
|
8909
|
-
/* @__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)(
|
|
8910
10601
|
"input",
|
|
8911
10602
|
{
|
|
8912
10603
|
className: "mx-meet__input",
|
|
@@ -8916,9 +10607,9 @@ function ScheduleMeetingBody({
|
|
|
8916
10607
|
}
|
|
8917
10608
|
)
|
|
8918
10609
|
] }),
|
|
8919
|
-
/* @__PURE__ */ (0,
|
|
8920
|
-
/* @__PURE__ */ (0,
|
|
8921
|
-
/* @__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)(
|
|
8922
10613
|
"input",
|
|
8923
10614
|
{
|
|
8924
10615
|
className: "mx-meet__input",
|
|
@@ -8928,27 +10619,27 @@ function ScheduleMeetingBody({
|
|
|
8928
10619
|
}
|
|
8929
10620
|
)
|
|
8930
10621
|
] }),
|
|
8931
|
-
/* @__PURE__ */ (0,
|
|
8932
|
-
/* @__PURE__ */ (0,
|
|
8933
|
-
/* @__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)(
|
|
8934
10625
|
"select",
|
|
8935
10626
|
{
|
|
8936
10627
|
className: "mx-meet__select",
|
|
8937
10628
|
value: kind,
|
|
8938
10629
|
onChange: (event) => setKind(event.target.value),
|
|
8939
10630
|
children: [
|
|
8940
|
-
/* @__PURE__ */ (0,
|
|
8941
|
-
/* @__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" })
|
|
8942
10633
|
]
|
|
8943
10634
|
}
|
|
8944
10635
|
)
|
|
8945
10636
|
] }),
|
|
8946
|
-
/* @__PURE__ */ (0,
|
|
8947
|
-
link !== null ? /* @__PURE__ */ (0,
|
|
8948
|
-
/* @__PURE__ */ (0,
|
|
8949
|
-
/* @__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 })
|
|
8950
10641
|
] }) : null,
|
|
8951
|
-
error !== null ? /* @__PURE__ */ (0,
|
|
10642
|
+
error !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__error", children: error }) : null
|
|
8952
10643
|
]
|
|
8953
10644
|
}
|
|
8954
10645
|
);
|
|
@@ -8957,7 +10648,7 @@ function ReactionOverlay({
|
|
|
8957
10648
|
reactions
|
|
8958
10649
|
}) {
|
|
8959
10650
|
if (reactions.length === 0) return null;
|
|
8960
|
-
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)) });
|
|
8961
10652
|
}
|
|
8962
10653
|
function GuestRecordAccessControl({
|
|
8963
10654
|
meeting
|
|
@@ -8969,11 +10660,11 @@ function GuestRecordAccessControl({
|
|
|
8969
10660
|
const isHost = inRoomHost || viewerId !== null && meeting.hostUserId === viewerId;
|
|
8970
10661
|
if (host === null || !isHost) return null;
|
|
8971
10662
|
const resolved = access.setting === "default" && access.effective !== null ? ` Right now that means: ${guestRecordAccessLabel(access.effective.level).toLowerCase()}.` : "";
|
|
8972
|
-
return /* @__PURE__ */ (0,
|
|
8973
|
-
/* @__PURE__ */ (0,
|
|
8974
|
-
/* @__PURE__ */ (0,
|
|
8975
|
-
/* @__PURE__ */ (0,
|
|
8976
|
-
/* @__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)(
|
|
8977
10668
|
"select",
|
|
8978
10669
|
{
|
|
8979
10670
|
className: "mx-meet__select",
|
|
@@ -8984,18 +10675,18 @@ function GuestRecordAccessControl({
|
|
|
8984
10675
|
event.target.value
|
|
8985
10676
|
);
|
|
8986
10677
|
},
|
|
8987
|
-
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))
|
|
8988
10679
|
}
|
|
8989
10680
|
)
|
|
8990
10681
|
] }),
|
|
8991
|
-
/* @__PURE__ */ (0,
|
|
10682
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("p", { className: "mx-meet__panel-note", children: [
|
|
8992
10683
|
guestRecordAccessExplanation(access.setting),
|
|
8993
10684
|
resolved
|
|
8994
10685
|
] }),
|
|
8995
|
-
access.saving ? /* @__PURE__ */ (0,
|
|
8996
|
-
access.error !== null ? /* @__PURE__ */ (0,
|
|
8997
|
-
/* @__PURE__ */ (0,
|
|
8998
|
-
/* @__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 })
|
|
8999
10690
|
] }) : null
|
|
9000
10691
|
] });
|
|
9001
10692
|
}
|
|
@@ -9005,9 +10696,9 @@ function MeetingRecordView({
|
|
|
9005
10696
|
}) {
|
|
9006
10697
|
const host = useMeetHost();
|
|
9007
10698
|
if (host === null) {
|
|
9008
|
-
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" }) });
|
|
9009
10700
|
}
|
|
9010
|
-
return /* @__PURE__ */ (0,
|
|
10701
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MeetingRecordBody, { meeting, ...onRejoin !== void 0 ? { onRejoin } : {} });
|
|
9011
10702
|
}
|
|
9012
10703
|
function MeetingRecordBody({
|
|
9013
10704
|
meeting,
|
|
@@ -9015,19 +10706,19 @@ function MeetingRecordBody({
|
|
|
9015
10706
|
}) {
|
|
9016
10707
|
const host = useRequiredMeetHost();
|
|
9017
10708
|
const record = useMeetingRecord(meeting);
|
|
9018
|
-
const [question, setQuestion] = (0,
|
|
9019
|
-
const [tab, setTab] = (0,
|
|
10709
|
+
const [question, setQuestion] = (0, import_react5.useState)("");
|
|
10710
|
+
const [tab, setTab] = (0, import_react5.useState)("summary");
|
|
9020
10711
|
if (record.failure !== null) {
|
|
9021
|
-
return /* @__PURE__ */ (0,
|
|
9022
|
-
/* @__PURE__ */ (0,
|
|
9023
|
-
/* @__PURE__ */ (0,
|
|
9024
|
-
/* @__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 })
|
|
9025
10716
|
] }) });
|
|
9026
10717
|
}
|
|
9027
10718
|
if (record.loading || record.record === null) {
|
|
9028
|
-
return /* @__PURE__ */ (0,
|
|
9029
|
-
/* @__PURE__ */ (0,
|
|
9030
|
-
/* @__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." })
|
|
9031
10722
|
] }) });
|
|
9032
10723
|
}
|
|
9033
10724
|
const bundle = record.record;
|
|
@@ -9046,44 +10737,44 @@ function MeetingRecordBody({
|
|
|
9046
10737
|
);
|
|
9047
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;
|
|
9048
10739
|
if (entirelyRestricted) {
|
|
9049
|
-
return /* @__PURE__ */ (0,
|
|
9050
|
-
/* @__PURE__ */ (0,
|
|
9051
|
-
/* @__PURE__ */ (0,
|
|
9052
|
-
/* @__PURE__ */ (0,
|
|
9053
|
-
/* @__PURE__ */ (0,
|
|
9054
|
-
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
|
|
9055
10746
|
] }) }),
|
|
9056
|
-
/* @__PURE__ */ (0,
|
|
9057
|
-
/* @__PURE__ */ (0,
|
|
9058
|
-
/* @__PURE__ */ (0,
|
|
9059
|
-
/* @__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 })
|
|
9060
10751
|
] }, notice2.parts.join("-"))) })
|
|
9061
10752
|
] });
|
|
9062
10753
|
}
|
|
9063
|
-
return /* @__PURE__ */ (0,
|
|
9064
|
-
/* @__PURE__ */ (0,
|
|
9065
|
-
/* @__PURE__ */ (0,
|
|
9066
|
-
/* @__PURE__ */ (0,
|
|
9067
|
-
/* @__PURE__ */ (0,
|
|
9068
|
-
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
|
|
9069
10760
|
] }) }),
|
|
9070
|
-
/* @__PURE__ */ (0,
|
|
9071
|
-
restrictionNotices.map((notice2) => /* @__PURE__ */ (0,
|
|
9072
|
-
/* @__PURE__ */ (0,
|
|
9073
|
-
/* @__PURE__ */ (0,
|
|
9074
|
-
/* @__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 })
|
|
9075
10766
|
] }, notice2.parts.join("-"))),
|
|
9076
10767
|
attended.length === 0 ? (
|
|
9077
10768
|
/* NOT SILENCE. A refused attendance read used to remove the whole
|
|
9078
10769
|
section, so the reader could not tell "nobody" from "not shown". */
|
|
9079
|
-
/* @__PURE__ */ (0,
|
|
9080
|
-
/* @__PURE__ */ (0,
|
|
9081
|
-
/* @__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.") })
|
|
9082
10773
|
] })
|
|
9083
|
-
) : /* @__PURE__ */ (0,
|
|
9084
|
-
/* @__PURE__ */ (0,
|
|
9085
|
-
/* @__PURE__ */ (0,
|
|
9086
|
-
/* @__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)(
|
|
9087
10778
|
Avatar,
|
|
9088
10779
|
{
|
|
9089
10780
|
name: displayNameFor(bundle.names, person.identity, person.displayName),
|
|
@@ -9091,26 +10782,26 @@ function MeetingRecordBody({
|
|
|
9091
10782
|
size: 28
|
|
9092
10783
|
}
|
|
9093
10784
|
),
|
|
9094
|
-
/* @__PURE__ */ (0,
|
|
10785
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("span", { className: "mx-meet__person-name", children: [
|
|
9095
10786
|
displayNameFor(bundle.names, person.identity, person.displayName),
|
|
9096
|
-
person.role === "host" ? /* @__PURE__ */ (0,
|
|
9097
|
-
person.role === "guest" ? /* @__PURE__ */ (0,
|
|
9098
|
-
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
|
|
9099
10790
|
] })
|
|
9100
10791
|
] }, person.id)) })
|
|
9101
10792
|
] }),
|
|
9102
|
-
bundle.recording !== null ? /* @__PURE__ */ (0,
|
|
9103
|
-
/* @__PURE__ */ (0,
|
|
9104
|
-
fileId !== null ? /* @__PURE__ */ (0,
|
|
9105
|
-
/* @__PURE__ */ (0,
|
|
9106
|
-
notice !== null ? /* @__PURE__ */ (0,
|
|
9107
|
-
] }) : /* @__PURE__ */ (0,
|
|
9108
|
-
] }) : wasRefused(bundle, "recording") ? /* @__PURE__ */ (0,
|
|
9109
|
-
/* @__PURE__ */ (0,
|
|
9110
|
-
/* @__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 })
|
|
9111
10802
|
] }) : null,
|
|
9112
|
-
/* @__PURE__ */ (0,
|
|
9113
|
-
/* @__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)(
|
|
9114
10805
|
"button",
|
|
9115
10806
|
{
|
|
9116
10807
|
type: "button",
|
|
@@ -9120,7 +10811,7 @@ function MeetingRecordBody({
|
|
|
9120
10811
|
children: "Summary & decisions"
|
|
9121
10812
|
}
|
|
9122
10813
|
),
|
|
9123
|
-
/* @__PURE__ */ (0,
|
|
10814
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9124
10815
|
"button",
|
|
9125
10816
|
{
|
|
9126
10817
|
type: "button",
|
|
@@ -9130,7 +10821,7 @@ function MeetingRecordBody({
|
|
|
9130
10821
|
children: "Notes as it happened"
|
|
9131
10822
|
}
|
|
9132
10823
|
),
|
|
9133
|
-
/* @__PURE__ */ (0,
|
|
10824
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9134
10825
|
"button",
|
|
9135
10826
|
{
|
|
9136
10827
|
type: "button",
|
|
@@ -9141,15 +10832,15 @@ function MeetingRecordBody({
|
|
|
9141
10832
|
}
|
|
9142
10833
|
)
|
|
9143
10834
|
] }),
|
|
9144
|
-
tab === "summary" ? /* @__PURE__ */ (0,
|
|
9145
|
-
/* @__PURE__ */ (0,
|
|
9146
|
-
/* @__PURE__ */ (0,
|
|
9147
|
-
wrapUp.state === "written" ? /* @__PURE__ */ (0,
|
|
9148
|
-
/* @__PURE__ */ (0,
|
|
9149
|
-
/* @__PURE__ */ (0,
|
|
9150
|
-
] }) : /* @__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 })
|
|
9151
10842
|
] }),
|
|
9152
|
-
/* @__PURE__ */ (0,
|
|
10843
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9153
10844
|
NoteList,
|
|
9154
10845
|
{
|
|
9155
10846
|
title: "Decisions",
|
|
@@ -9161,7 +10852,7 @@ function MeetingRecordBody({
|
|
|
9161
10852
|
)
|
|
9162
10853
|
}
|
|
9163
10854
|
),
|
|
9164
|
-
/* @__PURE__ */ (0,
|
|
10855
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9165
10856
|
NoteList,
|
|
9166
10857
|
{
|
|
9167
10858
|
title: "Action items",
|
|
@@ -9174,42 +10865,42 @@ function MeetingRecordBody({
|
|
|
9174
10865
|
}
|
|
9175
10866
|
)
|
|
9176
10867
|
] }) : null,
|
|
9177
|
-
tab === "notes" ? /* @__PURE__ */ (0,
|
|
9178
|
-
/* @__PURE__ */ (0,
|
|
9179
|
-
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(
|
|
9180
10871
|
bundle,
|
|
9181
10872
|
"notes",
|
|
9182
10873
|
"No live notes are available for this meeting."
|
|
9183
|
-
) }) : /* @__PURE__ */ (0,
|
|
9184
|
-
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: [
|
|
9185
10876
|
"Window ",
|
|
9186
10877
|
note.window
|
|
9187
10878
|
] }) : null,
|
|
9188
10879
|
note.text
|
|
9189
10880
|
] }, note.id)) })
|
|
9190
10881
|
] }) : null,
|
|
9191
|
-
tab === "transcript" ? /* @__PURE__ */ (0,
|
|
9192
|
-
/* @__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: [
|
|
9193
10884
|
"Transcript",
|
|
9194
|
-
/* @__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` })
|
|
9195
10886
|
] }),
|
|
9196
|
-
blocks.length === 0 ? /* @__PURE__ */ (0,
|
|
10887
|
+
blocks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note", children: absenceSentence(
|
|
9197
10888
|
bundle,
|
|
9198
10889
|
"transcript",
|
|
9199
10890
|
"No transcript is available for this meeting."
|
|
9200
|
-
) }) : /* @__PURE__ */ (0,
|
|
9201
|
-
/* @__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: [
|
|
9202
10893
|
block.speaker,
|
|
9203
|
-
/* @__PURE__ */ (0,
|
|
10894
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("time", { className: "mx-meet__record-time", dateTime: block.startedAt, children: clockOf(block.startedAt) })
|
|
9204
10895
|
] }),
|
|
9205
|
-
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))
|
|
9206
10897
|
] }, block.id)) })
|
|
9207
10898
|
] }) : null,
|
|
9208
|
-
/* @__PURE__ */ (0,
|
|
9209
|
-
/* @__PURE__ */ (0,
|
|
9210
|
-
/* @__PURE__ */ (0,
|
|
9211
|
-
guestFinishedMeeting ? /* @__PURE__ */ (0,
|
|
9212
|
-
/* @__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)(
|
|
9213
10904
|
"form",
|
|
9214
10905
|
{
|
|
9215
10906
|
className: "mx-meet__composer",
|
|
@@ -9220,7 +10911,7 @@ function MeetingRecordBody({
|
|
|
9220
10911
|
void record.ask(trimmed);
|
|
9221
10912
|
},
|
|
9222
10913
|
children: [
|
|
9223
|
-
/* @__PURE__ */ (0,
|
|
10914
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9224
10915
|
"input",
|
|
9225
10916
|
{
|
|
9226
10917
|
className: "mx-meet__input",
|
|
@@ -9230,7 +10921,7 @@ function MeetingRecordBody({
|
|
|
9230
10921
|
"aria-label": "Ask about this meeting"
|
|
9231
10922
|
}
|
|
9232
10923
|
),
|
|
9233
|
-
/* @__PURE__ */ (0,
|
|
10924
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9234
10925
|
"button",
|
|
9235
10926
|
{
|
|
9236
10927
|
type: "submit",
|
|
@@ -9242,8 +10933,8 @@ function MeetingRecordBody({
|
|
|
9242
10933
|
]
|
|
9243
10934
|
}
|
|
9244
10935
|
),
|
|
9245
|
-
record.answer !== null ? /* @__PURE__ */ (0,
|
|
9246
|
-
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: [
|
|
9247
10938
|
"Answered from ",
|
|
9248
10939
|
record.coverage.segmentsUsed,
|
|
9249
10940
|
" of ",
|
|
@@ -9254,9 +10945,9 @@ function MeetingRecordBody({
|
|
|
9254
10945
|
record.coverage.truncated ? " (the oldest were left out)" : "",
|
|
9255
10946
|
"."
|
|
9256
10947
|
] }) : null,
|
|
9257
|
-
record.askError !== null ? /* @__PURE__ */ (0,
|
|
9258
|
-
/* @__PURE__ */ (0,
|
|
9259
|
-
/* @__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 })
|
|
9260
10951
|
] }) : null
|
|
9261
10952
|
] })
|
|
9262
10953
|
] })
|
|
@@ -9267,21 +10958,21 @@ var STREAM_REFUSED = "Streaming playback did not start, so this recording was do
|
|
|
9267
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.";
|
|
9268
10959
|
function RecordingPlayer(props) {
|
|
9269
10960
|
const host = useMeetHost();
|
|
9270
|
-
if (host === null) return /* @__PURE__ */ (0,
|
|
9271
|
-
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 });
|
|
9272
10963
|
}
|
|
9273
10964
|
function RecordingPlayerBody({ fileId, host }) {
|
|
9274
|
-
const [media, setMedia] = (0,
|
|
9275
|
-
const [loading, setLoading] = (0,
|
|
9276
|
-
const [error, setError] = (0,
|
|
9277
|
-
(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)(() => {
|
|
9278
10969
|
if (media === null || media.kind !== "bytes") return void 0;
|
|
9279
10970
|
const url = media.url;
|
|
9280
10971
|
return () => URL.revokeObjectURL(url);
|
|
9281
10972
|
}, [media]);
|
|
9282
10973
|
if (media !== null) {
|
|
9283
|
-
return /* @__PURE__ */ (0,
|
|
9284
|
-
/* @__PURE__ */ (0,
|
|
10974
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__record-section", children: [
|
|
10975
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9285
10976
|
"video",
|
|
9286
10977
|
{
|
|
9287
10978
|
className: "mx-meet__record-player",
|
|
@@ -9323,15 +11014,15 @@ function RecordingPlayerBody({ fileId, host }) {
|
|
|
9323
11014
|
}
|
|
9324
11015
|
}
|
|
9325
11016
|
),
|
|
9326
|
-
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
|
|
9327
11018
|
] });
|
|
9328
11019
|
}
|
|
9329
|
-
return /* @__PURE__ */ (0,
|
|
9330
|
-
error !== null ? /* @__PURE__ */ (0,
|
|
9331
|
-
/* @__PURE__ */ (0,
|
|
9332
|
-
/* @__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 })
|
|
9333
11024
|
] }) : null,
|
|
9334
|
-
/* @__PURE__ */ (0,
|
|
11025
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
9335
11026
|
"button",
|
|
9336
11027
|
{
|
|
9337
11028
|
type: "button",
|
|
@@ -9367,35 +11058,35 @@ function clockOf(iso) {
|
|
|
9367
11058
|
function MeetingList({ baseUrl }) {
|
|
9368
11059
|
const host = useMeetHost();
|
|
9369
11060
|
const list = useMeetings();
|
|
9370
|
-
if (host === null) return /* @__PURE__ */ (0,
|
|
11061
|
+
if (host === null) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(InertNotice, { what: "Your meetings" });
|
|
9371
11062
|
if (list.failure !== null) {
|
|
9372
|
-
return /* @__PURE__ */ (0,
|
|
9373
|
-
/* @__PURE__ */ (0,
|
|
9374
|
-
/* @__PURE__ */ (0,
|
|
9375
|
-
/* @__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 })
|
|
9376
11067
|
] });
|
|
9377
11068
|
}
|
|
9378
11069
|
if (list.loading) {
|
|
9379
|
-
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" }) });
|
|
9380
11071
|
}
|
|
9381
11072
|
if (list.meetings.length === 0) {
|
|
9382
|
-
return /* @__PURE__ */ (0,
|
|
9383
|
-
/* @__PURE__ */ (0,
|
|
9384
|
-
/* @__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." })
|
|
9385
11076
|
] });
|
|
9386
11077
|
}
|
|
9387
11078
|
const origin = baseUrl ?? (typeof window === "undefined" ? "" : window.location.origin);
|
|
9388
|
-
return /* @__PURE__ */ (0,
|
|
11079
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("ul", { className: "mx-meet-list", children: list.meetings.map((meeting) => {
|
|
9389
11080
|
const ended = meeting.endedAt !== null;
|
|
9390
|
-
return /* @__PURE__ */ (0,
|
|
9391
|
-
/* @__PURE__ */ (0,
|
|
9392
|
-
/* @__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: [
|
|
9393
11084
|
meeting.title,
|
|
9394
|
-
ended ? /* @__PURE__ */ (0,
|
|
11085
|
+
ended ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet__badge", children: "Ended" }) : null
|
|
9395
11086
|
] }),
|
|
9396
|
-
/* @__PURE__ */ (0,
|
|
11087
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "mx-meet-list__when", children: meetingWhen(meeting) })
|
|
9397
11088
|
] }),
|
|
9398
|
-
/* @__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" })
|
|
9399
11090
|
] }, meeting.id);
|
|
9400
11091
|
}) });
|
|
9401
11092
|
}
|