@ai-matrx/meet 0.7.84 → 0.8.0

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/dist/react.cjs CHANGED
@@ -33,54 +33,26 @@ 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,
38
- AiPanel: () => AiPanel,
39
- AttendanceNotice: () => AttendanceNotice,
40
- Avatar: () => Avatar,
41
- BreakoutBanner: () => BreakoutBanner,
42
- BreakoutIcon: () => BreakoutIcon,
43
- BreakoutsPanel: () => BreakoutsPanel,
44
36
  CALL_INVITE_KIND: () => CALL_INVITE_KIND,
45
37
  CALL_INVITE_VERSION: () => CALL_INVITE_VERSION,
46
38
  CAPTION_LANGUAGES: () => CAPTION_LANGUAGES,
47
39
  CONSENT_NOTICE_ATTRIBUTE: () => CONSENT_NOTICE_ATTRIBUTE,
48
- CallButton: () => CallButton,
49
- CameraIcon: () => CameraIcon,
50
- CameraOffIcon: () => CameraOffIcon,
51
- CaptionLanguageSettings: () => CaptionLanguageSettings,
52
- Captions: () => Captions,
53
- ChatIcon: () => ChatIcon,
54
- ChatPanel: () => ChatPanel,
55
- CheckIcon: () => CheckIcon,
56
- CloseIcon: () => CloseIcon,
57
- ConnectionDot: () => ConnectionDot,
58
- ConsentNotice: () => ConsentNotice,
59
- ControlBar: () => ControlBar,
60
- ControlButton: () => ControlButton,
61
40
  DATA_TOPICS: () => DATA_TOPICS,
62
41
  DEFAULT_EFFECTS: () => DEFAULT_EFFECTS,
63
42
  DEFAULT_PAGE_SIZE: () => DEFAULT_PAGE_SIZE,
64
43
  EMPTY_COLLAB: () => EMPTY_COLLAB,
65
44
  END_MEETING_NOT_SERVED: () => END_MEETING_NOT_SERVED,
66
45
  FILE_SESSION_PATH: () => FILE_SESSION_PATH,
67
- FlagIcon: () => FlagIcon,
68
46
  GUEST_RECORD_ACCESS_CHOICES: () => GUEST_RECORD_ACCESS_CHOICES,
69
47
  GUEST_RECORD_ACCESS_LEVELS: () => GUEST_RECORD_ACCESS_LEVELS,
70
48
  GUEST_RECORD_ACCESS_METADATA_KEY: () => GUEST_RECORD_ACCESS_METADATA_KEY,
71
49
  GUEST_RECORD_NOT_SHARED: () => GUEST_RECORD_NOT_SHARED,
72
50
  GuestRecordAccessControl: () => GuestRecordAccessControl,
73
- HandIcon: () => HandIcon,
74
- HostMenu: () => HostMenu,
75
51
  IDLE_MEDIA: () => IDLE_MEDIA,
76
52
  IDLE_TRACK: () => IDLE_TRACK,
77
53
  IncomingCallCard: () => IncomingCallCard,
78
54
  IncomingCallHost: () => IncomingCallHost,
79
- KeyboardIcon: () => KeyboardIcon,
80
55
  LISTEN_ONLY_NOTICE: () => LISTEN_ONLY_NOTICE,
81
- LayoutIcon: () => LayoutIcon,
82
- LobbyPanel: () => LobbyPanel,
83
- LockIcon: () => LockIcon,
84
56
  MEETING_INVITE_KIND: () => MEETING_INVITE_KIND,
85
57
  MEETING_INVITE_VERSION: () => MEETING_INVITE_VERSION,
86
58
  MEETING_RECORD_GRACE_MS: () => MEETING_RECORD_GRACE_MS,
@@ -95,33 +67,14 @@ __export(react_exports, {
95
67
  MeetError: () => MeetError,
96
68
  MeetProvider: () => MeetProvider,
97
69
  MeetRoot: () => MeetRoot,
98
- MeetingList: () => MeetingList,
99
- MeetingOverlays: () => MeetingOverlays,
100
70
  MeetingRecordView: () => MeetingRecordView,
101
- MeetingRoom: () => MeetingRoom,
102
- MicIcon: () => MicIcon,
103
- MicOffIcon: () => MicOffIcon,
104
- MoreIcon: () => MoreIcon,
71
+ MeetingSkinRoot: () => MeetingSkinRoot,
105
72
  NOTE_TAKER_IDENTITY_PREFIX: () => NOTE_TAKER_IDENTITY_PREFIX,
106
73
  NOTE_TAKER_METADATA_KEY: () => NOTE_TAKER_METADATA_KEY,
107
74
  NO_GRANTS: () => NO_GRANTS,
108
75
  ORGANIZATION_HEADER: () => ORGANIZATION_HEADER,
109
76
  PARTICIPANT_CAN_RECORD_ATTRIBUTE: () => PARTICIPANT_CAN_RECORD_ATTRIBUTE,
110
77
  PARTICIPANT_ROLE_ATTRIBUTE: () => PARTICIPANT_ROLE_ATTRIBUTE,
111
- ParticipantTile: () => ParticipantTile,
112
- PencilIcon: () => PencilIcon,
113
- PeopleIcon: () => PeopleIcon,
114
- PeoplePanel: () => PeoplePanel,
115
- PersonMenu: () => PersonMenu,
116
- PhoneIcon: () => PhoneIcon,
117
- PhoneOffIcon: () => PhoneOffIcon,
118
- PinIcon: () => PinIcon,
119
- PollIcon: () => PollIcon,
120
- PollsPanel: () => PollsPanel,
121
- PreJoin: () => PreJoin,
122
- QaPanel: () => QaPanel,
123
- QualityBars: () => QualityBars,
124
- QuestionIcon: () => QuestionIcon,
125
78
  REACTION_TTL_MS: () => REACTION_TTL_MS,
126
79
  REFUSED_ABSENCE: () => REFUSED_ABSENCE,
127
80
  ROLE_RANK: () => ROLE_RANK,
@@ -129,30 +82,13 @@ __export(react_exports, {
129
82
  ROOM_EVENT_PREFIX: () => ROOM_EVENT_PREFIX,
130
83
  ROOM_TOKEN_HEADER: () => ROOM_TOKEN_HEADER,
131
84
  RPCS: () => RPCS,
132
- ReactionOverlay: () => ReactionOverlay,
133
- RecordIcon: () => RecordIcon,
134
- RecordingIndicator: () => RecordingIndicator,
135
85
  RecordingPlayer: () => RecordingPlayer,
136
- ScheduleMeeting: () => ScheduleMeeting,
137
- ScreenShareIcon: () => ScreenShareIcon,
138
- SearchIcon: () => SearchIcon,
139
- SettingsIcon: () => SettingsIcon,
140
- SettingsPanel: () => SettingsPanel,
141
- ShortcutsSheet: () => ShortcutsSheet,
142
- SignalIcon: () => SignalIcon,
143
- SmileIcon: () => SmileIcon,
144
- SparklesIcon: () => SparklesIcon,
145
- SpeakerIcon: () => SpeakerIcon,
146
- SpotlightIcon: () => SpotlightIcon,
147
- Stage: () => Stage,
148
86
  TABLES: () => TABLES,
149
87
  TRANSCRIPTION_ATTRIBUTES: () => TRANSCRIPTION_ATTRIBUTES,
150
88
  TRANSCRIPTION_TOPIC: () => TRANSCRIPTION_TOPIC,
151
- WhiteboardIcon: () => WhiteboardIcon,
152
- WhiteboardPanel: () => WhiteboardPanel,
153
- WifiLowIcon: () => WifiLowIcon,
154
89
  absenceSentence: () => absenceSentence,
155
90
  activeWrapUpSummary: () => activeWrapUpSummary,
91
+ activityAttention: () => activityAttention,
156
92
  announceMeeting: () => announceMeeting,
157
93
  applyCollabPacket: () => applyCollabPacket,
158
94
  applyRoomEvent: () => applyRoomEvent,
@@ -169,6 +105,7 @@ __export(react_exports, {
169
105
  attendanceTotals: () => attendanceTotals,
170
106
  attendeeKey: () => attendeeKey,
171
107
  autoAssign: () => autoAssign,
108
+ availableActivities: () => availableActivities,
172
109
  breakoutRemainingMs: () => breakoutRemainingMs,
173
110
  callInviteAction: () => callInviteAction,
174
111
  callInviteText: () => callInviteText,
@@ -241,6 +178,8 @@ __export(react_exports, {
241
178
  mergeCaption: () => mergeCaption,
242
179
  mergeRecord: () => mergeRecord,
243
180
  microphoneNoticeCode: () => microphoneNoticeCode,
181
+ moveToRoom: () => moveToRoom,
182
+ nextTranslationBatch: () => nextTranslationBatch,
244
183
  normalizeDeviceError: () => normalizeDeviceError,
245
184
  normalizeMeetError: () => normalizeMeetError,
246
185
  normalizeSpoken: () => normalizeSpoken,
@@ -257,6 +196,7 @@ __export(react_exports, {
257
196
  parseRoomToken: () => parseRoomToken,
258
197
  participantAttributes: () => participantAttributes,
259
198
  participantSummary: () => participantSummary,
199
+ performCollab: () => performCollab,
260
200
  playableRecordingFileId: () => playableRecordingFileId,
261
201
  projectInvitee: () => projectInvitee,
262
202
  projectLibraryRecording: () => projectLibraryRecording,
@@ -279,15 +219,20 @@ __export(react_exports, {
279
219
  rootAttributes: () => rootAttributes,
280
220
  searchTranscript: () => searchTranscript,
281
221
  sendFollowUp: () => sendFollowUp,
222
+ setCaptionLanguage: () => setCaptionLanguage,
282
223
  setGuestRecordAccess: () => setGuestRecordAccess,
283
224
  settingsPatch: () => settingsPatch,
284
225
  snapshotParticipant: () => snapshotParticipant,
285
226
  snippetRuns: () => snippetRuns,
286
227
  staticObservation: () => staticObservation,
287
228
  summarizeMeetingRecordRestrictions: () => summarizeMeetingRecordRestrictions,
229
+ takeMoveRequest: () => takeMoveRequest,
230
+ takePanelRequest: () => takePanelRequest,
288
231
  transcriptDocument: () => transcriptDocument,
289
232
  unavailableFrom: () => unavailableFrom,
290
233
  uniqueAttendees: () => uniqueAttendees,
234
+ untranslatedLines: () => untranslatedLines,
235
+ useActivityAttention: () => useActivityAttention,
291
236
  useAudioLevel: () => useAudioLevel,
292
237
  useAvailableActivities: () => useAvailableActivities,
293
238
  useCalls: () => useCalls,
@@ -312,6 +257,7 @@ __export(react_exports, {
312
257
  useLocalUserId: () => useLocalUserId,
313
258
  useMediaEffects: () => useMediaEffects,
314
259
  useMeetAi: () => useMeetAi,
260
+ useMeetCore: () => useMeetCore,
315
261
  useMeetHost: () => useMeetHost,
316
262
  useMeetShortcuts: () => useMeetShortcuts,
317
263
  useMeetSnapshot: () => useMeetSnapshot,
@@ -335,6 +281,7 @@ __export(react_exports, {
335
281
  module.exports = __toCommonJS(react_exports);
336
282
 
337
283
  // src/react/provider.tsx
284
+ var import_global_slot2 = require("@ai-matrx/kit/global-slot");
338
285
  var import_react = require("react");
339
286
  var import_react2 = require("@ai-matrx/realtime/react");
340
287
 
@@ -1221,22 +1168,9 @@ function fileDownloadPath(fileId) {
1221
1168
 
1222
1169
  // src/core/channels.ts
1223
1170
  var import_realtime = require("@ai-matrx/realtime");
1224
-
1225
- // src/core/slot.ts
1226
- var NAMESPACE = "ai-matrx.meet";
1227
- function globalSlot(name, create) {
1228
- const key = /* @__PURE__ */ Symbol.for(`${NAMESPACE}.${name}`);
1229
- const host = globalThis;
1230
- const existing = host[key];
1231
- if (existing !== void 0) return existing;
1232
- const created = create();
1233
- host[key] = created;
1234
- return created;
1235
- }
1236
-
1237
- // src/core/channels.ts
1171
+ var import_global_slot = require("@ai-matrx/kit/global-slot");
1238
1172
  function namespaces() {
1239
- return globalSlot("channel-namespaces", () => ({
1173
+ return (0, import_global_slot.globalSlot)("ai-matrx.meet.channel-namespaces", () => ({
1240
1174
  user: (0, import_realtime.defineChannelNamespace)({
1241
1175
  namespace: "meet-user",
1242
1176
  parts: ["userId"],
@@ -3819,87 +3753,20 @@ function snippetRuns(snippet) {
3819
3753
  }
3820
3754
 
3821
3755
  // src/core/session-identity.ts
3822
- var RESOLVING = Object.freeze({
3823
- state: "resolving",
3824
- userId: null
3825
- });
3826
- var SERVER_SESSION_IDENTITY = RESOLVING;
3827
- function authOf(client) {
3828
- const candidate = client.auth;
3829
- if (candidate === null || typeof candidate !== "object") return null;
3830
- const auth = candidate;
3831
- if (typeof auth.getSession !== "function") return null;
3832
- if (typeof auth.onAuthStateChange !== "function") return null;
3833
- return auth;
3834
- }
3835
- function userIdOf(session) {
3836
- const id = session?.user?.id;
3837
- return typeof id === "string" && id.length > 0 ? asUserId(id) : null;
3838
- }
3839
- function createSessionIdentity(options) {
3840
- const { client, onDiagnostic } = options;
3841
- const listeners = /* @__PURE__ */ new Set();
3842
- let current = RESOLVING;
3843
- let disposed = false;
3844
- const publish = (state, userId) => {
3845
- if (disposed) return;
3846
- if (current.state === state && current.userId === userId) return;
3847
- current = Object.freeze({ state, userId });
3848
- for (const listener of [...listeners]) listener();
3849
- };
3850
- const auth = authOf(client);
3851
- if (auth === null) {
3852
- onDiagnostic?.({
3853
- level: "error",
3854
- message: "Meet cannot tell who is signed in: the Supabase client it was given has no auth session source.",
3855
- remedy: "Pass your app's browser Supabase client to <MeetProvider client={...}> \u2014 the same client it signs in with. Meet reads the acting user from that client's session; there is no prop for a user id, on purpose."
3856
- });
3857
- current = Object.freeze({ state: "resolved", userId: null });
3858
- return {
3859
- snapshot: () => current,
3860
- subscribe: (listener) => {
3861
- listeners.add(listener);
3862
- return () => listeners.delete(listener);
3863
- },
3864
- dispose: () => {
3865
- disposed = true;
3866
- listeners.clear();
3867
- }
3868
- };
3869
- }
3870
- void (async () => {
3871
- try {
3872
- const result = await auth.getSession();
3873
- publish("resolved", userIdOf(result?.data?.session));
3874
- } catch (error) {
3875
- onDiagnostic?.({
3876
- level: "warn",
3877
- message: `Meet could not read the signed-in session: ${String(
3878
- error?.message ?? error
3879
- )}`,
3880
- remedy: "Calls and meetings stay unavailable on this device until the session can be read. Reload the page; if it persists, sign in again."
3881
- });
3882
- publish("resolved", null);
3883
- }
3884
- })();
3885
- const subscription = auth.onAuthStateChange((_event, session) => {
3886
- publish("resolved", userIdOf(session));
3756
+ var import_session_identity = require("@ai-matrx/data/session-identity");
3757
+ var import_session_identity2 = require("@ai-matrx/data/session-identity");
3758
+ var MEET_SESSION_WORDS = {
3759
+ product: "Meet",
3760
+ noAuthSourceRemedy: "Pass your app's browser Supabase client to <MeetProvider client={...}> \u2014 the same client it signs in with. Meet reads the acting user from that client's session; there is no prop for a user id, on purpose.",
3761
+ unreadableRemedy: "Calls and meetings stay unavailable on this device until the session can be read. Reload the page; if it persists, sign in again."
3762
+ };
3763
+ function createMeetSessionIdentity(options) {
3764
+ return (0, import_session_identity.createSessionIdentity)({
3765
+ client: options.client,
3766
+ words: MEET_SESSION_WORDS,
3767
+ toUserId: asUserId,
3768
+ onDiagnostic: options.onDiagnostic
3887
3769
  });
3888
- return {
3889
- snapshot: () => current,
3890
- subscribe: (listener) => {
3891
- listeners.add(listener);
3892
- return () => listeners.delete(listener);
3893
- },
3894
- dispose: () => {
3895
- disposed = true;
3896
- listeners.clear();
3897
- try {
3898
- subscription.data.subscription.unsubscribe();
3899
- } catch {
3900
- }
3901
- }
3902
- };
3903
3770
  }
3904
3771
 
3905
3772
  // src/core/room-events.ts
@@ -5543,7 +5410,7 @@ async function createCameraPreview(deviceId2, effect) {
5543
5410
 
5544
5411
  // src/react/provider.tsx
5545
5412
  var import_jsx_runtime = require("react/jsx-runtime");
5546
- var MeetContext = (0, import_react.createContext)(null);
5413
+ var MeetContext = (0, import_global_slot2.globalSlot)("ai-matrx.meet.react.context", () => (0, import_react.createContext)(null));
5547
5414
  function defaultDiagnostics(event) {
5548
5415
  const line = `[@ai-matrx/meet] ${event.message}${event.remedy !== void 0 ? `
5549
5416
  \u2192 ${event.remedy}` : ""}`;
@@ -5565,13 +5432,13 @@ function deviceId() {
5565
5432
  }
5566
5433
  }
5567
5434
  function useSessionIdentity(client, report) {
5568
- const [snapshot, setSnapshot] = (0, import_react.useState)(SERVER_SESSION_IDENTITY);
5435
+ const [snapshot, setSnapshot] = (0, import_react.useState)(import_session_identity2.SERVER_SESSION_IDENTITY);
5569
5436
  (0, import_react.useEffect)(() => {
5570
5437
  if (client == null) {
5571
- setSnapshot(SERVER_SESSION_IDENTITY);
5438
+ setSnapshot(import_session_identity2.SERVER_SESSION_IDENTITY);
5572
5439
  return void 0;
5573
5440
  }
5574
- const identity = createSessionIdentity({ client, onDiagnostic: report });
5441
+ const identity = createMeetSessionIdentity({ client, onDiagnostic: report });
5575
5442
  setSnapshot(identity.snapshot());
5576
5443
  const unsubscribe = identity.subscribe(() => setSnapshot(identity.snapshot()));
5577
5444
  return () => {
@@ -7521,10 +7388,15 @@ function useGuestRecordAccess(meeting) {
7521
7388
  };
7522
7389
  }
7523
7390
 
7524
- // src/react/components.tsx
7391
+ // src/react/skin-root.tsx
7392
+ var import_react11 = require("react");
7393
+
7394
+ // src/skins/meet/components.tsx
7395
+ var import_react9 = require("react");
7396
+
7397
+ // src/react/facade.ts
7525
7398
  var import_react7 = require("react");
7526
- var import_design_system = require("@ai-matrx/design-system");
7527
- var import_format4 = require("@ai-matrx/kit/format");
7399
+ var import_format3 = require("@ai-matrx/kit/format");
7528
7400
 
7529
7401
  // src/core/after.ts
7530
7402
  var import_delimited = require("@ai-matrx/kit/delimited");
@@ -7961,11 +7833,151 @@ function countLabel(count2, singular, plural = `${singular}s`) {
7961
7833
  return `${count2} ${count2 === 1 ? singular : plural}`;
7962
7834
  }
7963
7835
 
7964
- // src/react/collab.tsx
7836
+ // src/core/collab-state.ts
7837
+ function availableActivities(collab, isHost) {
7838
+ const settings = collab?.settings ?? null;
7839
+ if (settings === null) return [];
7840
+ const out = [];
7841
+ if (settings.whiteboardEnabled) out.push("whiteboard");
7842
+ if (settings.pollsEnabled && (isHost || (collab?.polls.length ?? 0) > 0)) out.push("polls");
7843
+ if (settings.qaEnabled) out.push("qa");
7844
+ if (settings.breakoutsEnabled && (isHost || collab?.breakout?.state === "open")) out.push("breakouts");
7845
+ return out;
7846
+ }
7847
+ function activityAttention(collab, isHost) {
7848
+ if (collab === null) return false;
7849
+ if (collab.polls.some((poll) => poll.state === "live" && poll.myVote.length === 0 && !isHost)) return true;
7850
+ if (isHost && collab.questions.some((q) => q.state === "open")) return true;
7851
+ return false;
7852
+ }
7853
+ async function performCollab(runtime, request) {
7854
+ if (runtime === null) return { ok: false, message: "This meeting is not connected." };
7855
+ try {
7856
+ const result = await runtime.inRoom.collab(request);
7857
+ return { ok: true, message: result.message, itemId: result.itemId };
7858
+ } catch (error) {
7859
+ return { ok: false, message: error.message ?? "That did not work." };
7860
+ }
7861
+ }
7862
+ async function moveToRoom(runtime, roomId) {
7863
+ if (runtime === null) return { ok: false, message: "This meeting is not connected." };
7864
+ try {
7865
+ await runtime.engine.moveToBreakout(roomId);
7866
+ return { ok: true, message: roomId === null ? "Back in the main room." : "Joined the breakout room." };
7867
+ } catch (error) {
7868
+ return { ok: false, message: error.message ?? "That room could not be joined." };
7869
+ }
7870
+ }
7871
+ function untranslatedLines(lines, translations) {
7872
+ return lines.filter((line) => line.final && translations[line.id] === void 0).map(({ id, text: text3 }) => ({ id, text: text3 }));
7873
+ }
7874
+ function nextTranslationBatch(pending, language, asked) {
7875
+ const batch = pending.filter((line) => !asked.has(`${language}:${line.id}`)).slice(-20);
7876
+ for (const line of batch) asked.add(`${language}:${line.id}`);
7877
+ return batch;
7878
+ }
7879
+ function setCaptionLanguage(store, next) {
7880
+ store.patch({
7881
+ collab: {
7882
+ ...store.snapshot().collab,
7883
+ captionLanguage: next,
7884
+ captionTranslations: {},
7885
+ captionTranslationError: null
7886
+ }
7887
+ });
7888
+ }
7889
+ function takePanelRequest(store) {
7890
+ const request = store.snapshot().collab.panelRequest;
7891
+ if (request === null) return null;
7892
+ store.patch({ collab: { ...store.snapshot().collab, panelRequest: null } });
7893
+ return request.panel;
7894
+ }
7895
+ function takeMoveRequest(store) {
7896
+ const request = store.snapshot().collab.moveRequest;
7897
+ if (request === null) return null;
7898
+ store.patch({ collab: { ...store.snapshot().collab, moveRequest: null } });
7899
+ return { roomId: request.roomId };
7900
+ }
7901
+
7902
+ // src/react/collab-hooks.ts
7965
7903
  var import_react6 = require("react");
7966
- var import_format3 = require("@ai-matrx/kit/format");
7904
+ function useCollab() {
7905
+ const host = useMeetHost();
7906
+ const snapshot = useMeetSnapshot();
7907
+ const isHost = useIsHost();
7908
+ return {
7909
+ collab: snapshot?.collab ?? null,
7910
+ isHost,
7911
+ localIdentity: snapshot?.localIdentity ?? null,
7912
+ breakoutRoomId: snapshot?.breakoutRoomId ?? null,
7913
+ act: (request) => performCollab(host, request),
7914
+ moveTo: (roomId) => moveToRoom(host, roomId)
7915
+ };
7916
+ }
7917
+ function useAvailableActivities() {
7918
+ const { collab, isHost } = useCollab();
7919
+ return availableActivities(collab, isHost);
7920
+ }
7921
+ function useActivityAttention() {
7922
+ const { collab, isHost } = useCollab();
7923
+ return activityAttention(collab, isHost);
7924
+ }
7925
+ function useCaptionTranslation(lines) {
7926
+ const host = useMeetHost();
7927
+ const snapshot = useMeetSnapshot();
7928
+ const collab = snapshot?.collab ?? null;
7929
+ const language = collab?.captionLanguage ?? null;
7930
+ const asked = (0, import_react6.useRef)(/* @__PURE__ */ new Set());
7931
+ const translations = collab?.captionTranslations ?? {};
7932
+ const missing = untranslatedLines(lines, translations);
7933
+ const key = `${language ?? ""}|${missing.map((l) => l.id).join(",")}`;
7934
+ const pending = (0, import_react6.useRef)(missing);
7935
+ pending.current = missing;
7936
+ (0, import_react6.useEffect)(() => {
7937
+ if (host === null || language === null) return;
7938
+ const batch = nextTranslationBatch(pending.current, language, asked.current);
7939
+ if (batch.length === 0) return;
7940
+ void host.inRoom.translateCaptions(language, batch).catch(() => void 0);
7941
+ }, [host, language, key]);
7942
+ return { language, translations, error: collab?.captionTranslationError ?? null };
7943
+ }
7944
+ function useCollabPanelRequest(onRequest) {
7945
+ const host = useMeetHost();
7946
+ const at = useMeetSnapshot()?.collab.panelRequest?.at ?? null;
7947
+ const callback = (0, import_react6.useRef)(onRequest);
7948
+ callback.current = onRequest;
7949
+ (0, import_react6.useEffect)(() => {
7950
+ if (host === null) return;
7951
+ const panel = takePanelRequest(host.store);
7952
+ if (panel === null) return;
7953
+ callback.current(panel);
7954
+ }, [at, host]);
7955
+ }
7956
+
7957
+ // src/core/reactions.ts
7958
+ var MEET_REACTIONS = ["\u{1F496}", "\u{1F44D}", "\u{1F389}", "\u{1F44F}", "\u{1F602}", "\u{1F62E}", "\u{1F622}", "\u{1F914}", "\u{1F44E}"];
7967
7959
 
7968
- // src/react/icons.tsx
7960
+ // src/react/facade.ts
7961
+ function useMeetCore() {
7962
+ const host = useMeetHost();
7963
+ const snapshot = useMeetSnapshot();
7964
+ const devices = useDeviceSnapshot();
7965
+ const role = useRole();
7966
+ const isHost = useIsHost();
7967
+ const observation = useCoreObservation();
7968
+ return (0, import_react7.useMemo)(
7969
+ () => ({ host, snapshot, devices, role, isHost, observation }),
7970
+ [host, snapshot, devices, role, isHost, observation]
7971
+ );
7972
+ }
7973
+
7974
+ // src/skins/meet/components.tsx
7975
+ var import_design_system = require("@ai-matrx/design-system");
7976
+
7977
+ // src/skins/meet/collab.tsx
7978
+ var import_react8 = require("react");
7979
+
7980
+ // src/skins/meet/icons.tsx
7969
7981
  var import_jsx_runtime3 = require("react/jsx-runtime");
7970
7982
  function Icon({ children, ...props }) {
7971
7983
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
@@ -8061,12 +8073,6 @@ function LockIcon(props) {
8061
8073
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M8 10V7a4 4 0 0 1 8 0v3" })
8062
8074
  ] });
8063
8075
  }
8064
- function LayoutIcon(props) {
8065
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Icon, { ...props, children: [
8066
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2" }),
8067
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M3 9h18M9 21V9" })
8068
- ] });
8069
- }
8070
8076
  function SettingsIcon(props) {
8071
8077
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Icon, { ...props, children: [
8072
8078
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "12", cy: "12", r: "3" }),
@@ -8085,12 +8091,6 @@ function PinIcon(props) {
8085
8091
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M9 2h6l-1 6 3.5 3.5V14H6.5v-2.5L10 8 9 2Z" })
8086
8092
  ] });
8087
8093
  }
8088
- function WifiLowIcon(props) {
8089
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Icon, { ...props, children: [
8090
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M12 20h.01" }),
8091
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M8.5 16.5a5 5 0 0 1 7 0" })
8092
- ] });
8093
- }
8094
8094
  function SmileIcon(props) {
8095
8095
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Icon, { ...props, children: [
8096
8096
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
@@ -8203,40 +8203,11 @@ function UndoIcon(props) {
8203
8203
  ] });
8204
8204
  }
8205
8205
 
8206
- // src/react/collab.tsx
8206
+ // src/skins/meet/collab.tsx
8207
8207
  var import_jsx_runtime4 = require("react/jsx-runtime");
8208
- function useCollab() {
8209
- const host = useMeetHost();
8210
- const snapshot = useMeetSnapshot();
8211
- const isHost = useIsHost();
8212
- return {
8213
- collab: snapshot?.collab ?? null,
8214
- isHost,
8215
- localIdentity: snapshot?.localIdentity ?? null,
8216
- breakoutRoomId: snapshot?.breakoutRoomId ?? null,
8217
- async act(request) {
8218
- if (host === null) return { ok: false, message: "This meeting is not connected." };
8219
- try {
8220
- const result = await host.inRoom.collab(request);
8221
- return { ok: true, message: result.message, itemId: result.itemId };
8222
- } catch (error) {
8223
- return { ok: false, message: error.message ?? "That did not work." };
8224
- }
8225
- },
8226
- async moveTo(roomId) {
8227
- if (host === null) return { ok: false, message: "This meeting is not connected." };
8228
- try {
8229
- await host.engine.moveToBreakout(roomId);
8230
- return { ok: true, message: roomId === null ? "Back in the main room." : "Joined the breakout room." };
8231
- } catch (error) {
8232
- return { ok: false, message: error.message ?? "That room could not be joined." };
8233
- }
8234
- }
8235
- };
8236
- }
8237
8208
  function useNotice() {
8238
- const [notice, setNotice] = (0, import_react6.useState)(null);
8239
- (0, import_react6.useEffect)(() => {
8209
+ const [notice, setNotice] = (0, import_react8.useState)(null);
8210
+ (0, import_react8.useEffect)(() => {
8240
8211
  if (notice === null) return void 0;
8241
8212
  const timer = setTimeout(() => setNotice(null), notice.failed ? 7e3 : 3e3);
8242
8213
  return () => clearTimeout(timer);
@@ -8260,29 +8231,11 @@ function ActivityIcon({ panel }) {
8260
8231
  if (panel === "whiteboard") return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(WhiteboardIcon, { ...props });
8261
8232
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(BreakoutIcon, { ...props });
8262
8233
  }
8263
- function useAvailableActivities() {
8264
- const { collab, isHost } = useCollab();
8265
- const settings = collab?.settings ?? null;
8266
- if (settings === null) return [];
8267
- const out = [];
8268
- if (settings.whiteboardEnabled) out.push("whiteboard");
8269
- if (settings.pollsEnabled && (isHost || (collab?.polls.length ?? 0) > 0)) out.push("polls");
8270
- if (settings.qaEnabled) out.push("qa");
8271
- if (settings.breakoutsEnabled && (isHost || collab?.breakout?.state === "open")) out.push("breakouts");
8272
- return out;
8273
- }
8274
- function useActivityAttention() {
8275
- const { collab, isHost } = useCollab();
8276
- if (collab === null) return false;
8277
- if (collab.polls.some((poll) => poll.state === "live" && poll.myVote.length === 0 && !isHost)) return true;
8278
- if (isHost && collab.questions.some((q) => q.state === "open")) return true;
8279
- return false;
8280
- }
8281
8234
  function ActivitiesControl({
8282
8235
  active,
8283
8236
  onOpen
8284
8237
  }) {
8285
- const [open, setOpen] = (0, import_react6.useState)(false);
8238
+ const [open, setOpen] = (0, import_react8.useState)(false);
8286
8239
  const available = useAvailableActivities();
8287
8240
  const attention = useActivityAttention();
8288
8241
  if (available.length === 0) return null;
@@ -8310,11 +8263,11 @@ function ActivitiesControl({
8310
8263
  }
8311
8264
  function PollComposer({ maxOptions, onDone }) {
8312
8265
  const { act } = useCollab();
8313
- const [question, setQuestion] = (0, import_react6.useState)("");
8314
- const [options, setOptions] = (0, import_react6.useState)(["", ""]);
8315
- const [multiple, setMultiple] = (0, import_react6.useState)(false);
8316
- const [anonymous, setAnonymous] = (0, import_react6.useState)(false);
8317
- const [busy, setBusy] = (0, import_react6.useState)(false);
8266
+ const [question, setQuestion] = (0, import_react8.useState)("");
8267
+ const [options, setOptions] = (0, import_react8.useState)(["", ""]);
8268
+ const [multiple, setMultiple] = (0, import_react8.useState)(false);
8269
+ const [anonymous, setAnonymous] = (0, import_react8.useState)(false);
8270
+ const [busy, setBusy] = (0, import_react8.useState)(false);
8318
8271
  const [notice, show] = useNotice();
8319
8272
  const filled = options.map((o) => o.trim()).filter(Boolean);
8320
8273
  const ready = question.trim().length > 0 && filled.length >= 2;
@@ -8395,9 +8348,9 @@ function PollComposer({ maxOptions, onDone }) {
8395
8348
  }
8396
8349
  function PollCard({ poll }) {
8397
8350
  const { act, isHost } = useCollab();
8398
- const [picked, setPicked] = (0, import_react6.useState)(poll.myVote.slice());
8351
+ const [picked, setPicked] = (0, import_react8.useState)(poll.myVote.slice());
8399
8352
  const [notice, show] = useNotice();
8400
- (0, import_react6.useEffect)(() => setPicked(poll.myVote.slice()), [poll.myVote]);
8353
+ (0, import_react8.useEffect)(() => setPicked(poll.myVote.slice()), [poll.myVote]);
8401
8354
  const counts = poll.options.some((o) => o.votes !== void 0);
8402
8355
  const total = poll.options.reduce((sum, o) => sum + (o.votes ?? 0), 0);
8403
8356
  const canVote = poll.state === "live";
@@ -8466,7 +8419,7 @@ function PollCard({ poll }) {
8466
8419
  }
8467
8420
  function PollsPanel({ onClose }) {
8468
8421
  const { collab, isHost } = useCollab();
8469
- const [composing, setComposing] = (0, import_react6.useState)(false);
8422
+ const [composing, setComposing] = (0, import_react8.useState)(false);
8470
8423
  const polls = collab?.polls ?? [];
8471
8424
  const maxOptions = collab?.settings?.pollMaxOptions ?? 10;
8472
8425
  const ordered = [...polls].reverse();
@@ -8480,8 +8433,8 @@ function PollsPanel({ onClose }) {
8480
8433
  }
8481
8434
  function QuestionCard({ question }) {
8482
8435
  const { act, isHost } = useCollab();
8483
- const [answering, setAnswering] = (0, import_react6.useState)(false);
8484
- const [reply, setReply] = (0, import_react6.useState)("");
8436
+ const [answering, setAnswering] = (0, import_react8.useState)(false);
8437
+ const [reply, setReply] = (0, import_react8.useState)("");
8485
8438
  const [notice, show] = useNotice();
8486
8439
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("li", { className: `mx-meet__collab-card mx-meet__question mx-meet__question--${question.state}`, children: [
8487
8440
  /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__question-row", children: [
@@ -8559,9 +8512,9 @@ function QuestionCard({ question }) {
8559
8512
  }
8560
8513
  function QaPanel({ onClose }) {
8561
8514
  const { collab, act } = useCollab();
8562
- const [draft, setDraft] = (0, import_react6.useState)("");
8563
- const [anonymous, setAnonymous] = (0, import_react6.useState)(false);
8564
- const [order, setOrder] = (0, import_react6.useState)("popular");
8515
+ const [draft, setDraft] = (0, import_react8.useState)("");
8516
+ const [anonymous, setAnonymous] = (0, import_react8.useState)(false);
8517
+ const [order, setOrder] = (0, import_react8.useState)("popular");
8565
8518
  const [notice, show] = useNotice();
8566
8519
  const allowAnonymous = collab?.settings?.qaAnonymousAllowed === true;
8567
8520
  const questions = [...collab?.questions ?? []];
@@ -8650,12 +8603,12 @@ function StrokeView({ stroke, onPick }) {
8650
8603
  }
8651
8604
  function WhiteboardPanel({ onClose }) {
8652
8605
  const { collab, act, isHost, localIdentity } = useCollab();
8653
- const [tool, setTool] = (0, import_react6.useState)("pen");
8654
- const [color, setColor] = (0, import_react6.useState)(INK[0]);
8655
- const [drawing, setDrawing] = (0, import_react6.useState)(null);
8656
- const [pending, setPending] = (0, import_react6.useState)([]);
8606
+ const [tool, setTool] = (0, import_react8.useState)("pen");
8607
+ const [color, setColor] = (0, import_react8.useState)(INK[0]);
8608
+ const [drawing, setDrawing] = (0, import_react8.useState)(null);
8609
+ const [pending, setPending] = (0, import_react8.useState)([]);
8657
8610
  const [notice, show] = useNotice();
8658
- const svgRef = (0, import_react6.useRef)(null);
8611
+ const svgRef = (0, import_react8.useRef)(null);
8659
8612
  const strokes = collab?.strokes ?? [];
8660
8613
  const mine = strokes.filter((s) => s.by === localIdentity);
8661
8614
  const point = (event) => {
@@ -8796,8 +8749,8 @@ function clock(ms2) {
8796
8749
  }
8797
8750
  var BREAKOUT_EXPIRE_RETRY_MS = 5e3;
8798
8751
  function useNow(active) {
8799
- const [now, setNow] = (0, import_react6.useState)(() => Date.now());
8800
- (0, import_react6.useEffect)(() => {
8752
+ const [now, setNow] = (0, import_react8.useState)(() => Date.now());
8753
+ (0, import_react8.useEffect)(() => {
8801
8754
  if (!active) return void 0;
8802
8755
  const timer = setInterval(() => setNow(Date.now()), 1e3);
8803
8756
  return () => clearInterval(timer);
@@ -8811,11 +8764,11 @@ function BreakoutSetup() {
8811
8764
  const people = (snapshot?.participants ?? []).filter(
8812
8765
  (p) => !p.isAgent && p.role !== "host" && p.role !== "cohost"
8813
8766
  );
8814
- const [count2, setCount] = (0, import_react6.useState)(Math.min(Math.max(2, Math.ceil(people.length / 4)), settings?.breakoutMaxRooms ?? 20));
8815
- const [mode, setMode] = (0, import_react6.useState)("auto");
8816
- const [minutes, setMinutes] = (0, import_react6.useState)(settings?.breakoutDefaultMinutes ?? 15);
8817
- const [manual, setManual] = (0, import_react6.useState)({});
8818
- const [busy, setBusy] = (0, import_react6.useState)(false);
8767
+ const [count2, setCount] = (0, import_react8.useState)(Math.min(Math.max(2, Math.ceil(people.length / 4)), settings?.breakoutMaxRooms ?? 20));
8768
+ const [mode, setMode] = (0, import_react8.useState)("auto");
8769
+ const [minutes, setMinutes] = (0, import_react8.useState)(settings?.breakoutDefaultMinutes ?? 15);
8770
+ const [manual, setManual] = (0, import_react8.useState)({});
8771
+ const [busy, setBusy] = (0, import_react8.useState)(false);
8819
8772
  const [notice, show] = useNotice();
8820
8773
  const max = settings?.breakoutMaxRooms ?? 20;
8821
8774
  const rooms = Math.min(Math.max(1, count2), max);
@@ -8931,7 +8884,7 @@ function BreakoutRun({ plan }) {
8931
8884
  const snapshot = useMeetSnapshot();
8932
8885
  const now = useNow(plan.endsAt !== null);
8933
8886
  const remaining = breakoutRemainingMs(plan, now);
8934
- const [broadcast, setBroadcast] = (0, import_react6.useState)("");
8887
+ const [broadcast, setBroadcast] = (0, import_react8.useState)("");
8935
8888
  const [notice, show] = useNotice();
8936
8889
  const nameOf = (identity) => displayNameFor(snapshot?.names ?? {}, identity, snapshot?.participants.find((p) => p.identity === identity)?.displayName);
8937
8890
  const mine = assignedRoom(plan, localIdentity);
@@ -9041,19 +8994,19 @@ function BreakoutBanner() {
9041
8994
  const now = useNow(open?.endsAt != null);
9042
8995
  const remaining = breakoutRemainingMs(open, now);
9043
8996
  const assigned = assignedRoom(open, localIdentity);
9044
- const [dismissedBroadcast, setDismissedBroadcast] = (0, import_react6.useState)(null);
9045
- const [failure, setFailure] = (0, import_react6.useState)(null);
9046
- const expireAsked = (0, import_react6.useRef)(null);
8997
+ const [dismissedBroadcast, setDismissedBroadcast] = (0, import_react8.useState)(null);
8998
+ const [failure, setFailure] = (0, import_react8.useState)(null);
8999
+ const expireAsked = (0, import_react8.useRef)(null);
9047
9000
  const moveAt = collab?.moveRequest?.at ?? null;
9048
- (0, import_react6.useEffect)(() => {
9049
- const request = host?.store.snapshot().collab.moveRequest ?? null;
9050
- if (request === null || host === null) return;
9051
- host.store.patch({ collab: { ...host.store.snapshot().collab, moveRequest: null } });
9001
+ (0, import_react8.useEffect)(() => {
9002
+ if (host === null) return;
9003
+ const request = takeMoveRequest(host.store);
9004
+ if (request === null) return;
9052
9005
  const here = host.store.snapshot().breakoutRoomId;
9053
9006
  if ((here ?? null) === request.roomId) return;
9054
9007
  void moveTo(request.roomId).then((result) => setFailure(result.ok ? null : result.message));
9055
9008
  }, [moveAt, host, moveTo]);
9056
- (0, import_react6.useEffect)(() => {
9009
+ (0, import_react8.useEffect)(() => {
9057
9010
  if (open === null || remaining === null || remaining > 0) return;
9058
9011
  const asked = expireAsked.current;
9059
9012
  if (asked !== null && asked.id === open.id && now - asked.at < BREAKOUT_EXPIRE_RETRY_MS) return;
@@ -9098,26 +9051,6 @@ function BreakoutBanner() {
9098
9051
  ] }) : null
9099
9052
  ] });
9100
9053
  }
9101
- function useCaptionTranslation(lines) {
9102
- const host = useMeetHost();
9103
- const snapshot = useMeetSnapshot();
9104
- const collab = snapshot?.collab ?? null;
9105
- const language = collab?.captionLanguage ?? null;
9106
- const asked = (0, import_react6.useRef)(/* @__PURE__ */ new Set());
9107
- const translations = collab?.captionTranslations ?? {};
9108
- const missing = lines.filter((line) => line.final && translations[line.id] === void 0).map(({ id, text: text3 }) => ({ id, text: text3 }));
9109
- const key = `${language ?? ""}|${missing.map((l) => l.id).join(",")}`;
9110
- const pending = (0, import_react6.useRef)(missing);
9111
- pending.current = missing;
9112
- (0, import_react6.useEffect)(() => {
9113
- if (host === null || language === null) return;
9114
- const batch = pending.current.filter((line) => !asked.current.has(`${language}:${line.id}`)).slice(-20);
9115
- if (batch.length === 0) return;
9116
- for (const line of batch) asked.current.add(`${language}:${line.id}`);
9117
- void host.inRoom.translateCaptions(language, batch).catch(() => void 0);
9118
- }, [host, language, key]);
9119
- return { language, translations, error: collab?.captionTranslationError ?? null };
9120
- }
9121
9054
  function CaptionLanguageSettings() {
9122
9055
  const host = useMeetHost();
9123
9056
  const snapshot = useMeetSnapshot();
@@ -9138,14 +9071,7 @@ function CaptionLanguageSettings() {
9138
9071
  value: current,
9139
9072
  onChange: (event) => {
9140
9073
  const next = event.target.value === "" ? null : event.target.value;
9141
- host.store.patch({
9142
- collab: {
9143
- ...host.store.snapshot().collab,
9144
- captionLanguage: next,
9145
- captionTranslations: {},
9146
- captionTranslationError: null
9147
- }
9148
- });
9074
+ setCaptionLanguage(host.store, next);
9149
9075
  },
9150
9076
  children: [
9151
9077
  /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("option", { value: "", children: "Off \u2014 as spoken" }),
@@ -9161,20 +9087,8 @@ function CaptionLanguageSettings() {
9161
9087
  collab?.captionTranslationError != null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__panel-note mx-meet__collab-error", children: collab.captionTranslationError }) : null
9162
9088
  ] });
9163
9089
  }
9164
- function useCollabPanelRequest(onRequest) {
9165
- const host = useMeetHost();
9166
- const at = useMeetSnapshot()?.collab.panelRequest?.at ?? null;
9167
- const callback = (0, import_react6.useRef)(onRequest);
9168
- callback.current = onRequest;
9169
- (0, import_react6.useEffect)(() => {
9170
- const request = host?.store.snapshot().collab.panelRequest ?? null;
9171
- if (request === null || host === null) return;
9172
- host.store.patch({ collab: { ...host.store.snapshot().collab, panelRequest: null } });
9173
- callback.current(request.panel);
9174
- }, [at, host]);
9175
- }
9176
9090
 
9177
- // src/react/components.tsx
9091
+ // src/skins/meet/components.tsx
9178
9092
  var import_jsx_runtime5 = require("react/jsx-runtime");
9179
9093
  function InertNotice({ what }) {
9180
9094
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet__empty", role: "status", children: [
@@ -9190,7 +9104,7 @@ function Avatar({
9190
9104
  url,
9191
9105
  size = 40
9192
9106
  }) {
9193
- const tint = (0, import_format4.avatarPaletteIndex)(name);
9107
+ const tint = (0, import_format3.avatarPaletteIndex)(name);
9194
9108
  if (url != null && url.length > 0) {
9195
9109
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
9196
9110
  "img",
@@ -9215,7 +9129,7 @@ function Avatar({
9215
9129
  background: `var(--mx-meet-avatar-${tint})`
9216
9130
  },
9217
9131
  "aria-hidden": "true",
9218
- children: (0, import_format4.getInitials)(name)
9132
+ children: (0, import_format3.getInitials)(name)
9219
9133
  }
9220
9134
  );
9221
9135
  }
@@ -9258,10 +9172,6 @@ function RecordingIndicator() {
9258
9172
  }
9259
9173
  );
9260
9174
  }
9261
- function ConnectionDot({ quality }) {
9262
- if (quality === "excellent" || quality === "good" || quality === "unknown") return null;
9263
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: `mx-meet__quality mx-meet__quality--${quality}`, title: `Connection ${quality}`, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(WifiLowIcon, { width: 14, height: 14 }) });
9264
- }
9265
9175
  function RoleBadge({ role }) {
9266
9176
  if (role === "host") return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__badge", children: "Host" });
9267
9177
  if (role === "cohost") return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__badge", children: "Co-host" });
@@ -9275,7 +9185,7 @@ function ParticipantTile({
9275
9185
  const host = useMeetHost();
9276
9186
  const snapshot = useMeetSnapshot();
9277
9187
  const queue = useHandQueue();
9278
- const [menu, setMenu] = (0, import_react7.useState)(false);
9188
+ const [menu, setMenu] = (0, import_react9.useState)(false);
9279
9189
  const videoRef = useTrack(
9280
9190
  participant.identity,
9281
9191
  participant.screenSharing ? "screen" : "camera"
@@ -9386,21 +9296,20 @@ function Stage({ pageSize }) {
9386
9296
  ] }) : null
9387
9297
  ] });
9388
9298
  }
9389
- var MEET_REACTIONS = ["\u{1F496}", "\u{1F44D}", "\u{1F389}", "\u{1F44F}", "\u{1F602}", "\u{1F62E}", "\u{1F622}", "\u{1F914}", "\u{1F44E}"];
9390
9299
  function ControlBar({ onLeave }) {
9391
9300
  const room = useRoom();
9392
9301
  const recording = useRecording();
9393
- const [panel, setPanel] = (0, import_react7.useState)("none");
9394
- const [chatTo, setChatTo] = (0, import_react7.useState)(null);
9395
- const [popover, setPopover] = (0, import_react7.useState)("none");
9396
- const [shortcuts, setShortcuts] = (0, import_react7.useState)(false);
9302
+ const [panel, setPanel] = (0, import_react9.useState)("none");
9303
+ const [chatTo, setChatTo] = (0, import_react9.useState)(null);
9304
+ const [popover, setPopover] = (0, import_react9.useState)("none");
9305
+ const [shortcuts, setShortcuts] = (0, import_react9.useState)(false);
9397
9306
  const snapshot = useMeetSnapshot();
9398
9307
  const lobby = useLobby();
9399
9308
  const controls = useHostControls();
9400
9309
  const queue = useHandQueue();
9401
9310
  const micUnavailable = useLocalMedia().microphone.unavailable;
9402
9311
  const unread = useUnreadChat(panel === "chat");
9403
- const [whiteboard, setWhiteboard] = (0, import_react7.useState)(false);
9312
+ const [whiteboard, setWhiteboard] = (0, import_react9.useState)(false);
9404
9313
  const toggle = (next) => setPanel(panel === next ? "none" : next);
9405
9314
  const openActivity = (activity) => {
9406
9315
  if (activity === "whiteboard") setWhiteboard(true);
@@ -9411,7 +9320,7 @@ function ControlBar({ onLeave }) {
9411
9320
  });
9412
9321
  const privateChatAt = snapshot?.privateChatRequest?.at ?? null;
9413
9322
  const meetStore = useMeetHost()?.store ?? null;
9414
- (0, import_react7.useEffect)(() => {
9323
+ (0, import_react9.useEffect)(() => {
9415
9324
  const request = meetStore?.snapshot().privateChatRequest ?? null;
9416
9325
  if (request === null) return;
9417
9326
  setChatTo(request.to);
@@ -9649,13 +9558,13 @@ function useUnreadChat(open) {
9649
9558
  const snapshot = useMeetSnapshot();
9650
9559
  const chat = snapshot?.chat ?? [];
9651
9560
  const local = snapshot?.localIdentity ?? null;
9652
- const [seen, setSeen] = (0, import_react7.useState)(0);
9653
- (0, import_react7.useEffect)(() => {
9561
+ const [seen, setSeen] = (0, import_react9.useState)(0);
9562
+ (0, import_react9.useEffect)(() => {
9654
9563
  if (open) setSeen(chat.length);
9655
9564
  }, [open, chat.length]);
9656
9565
  const loaded = snapshot?.chatLoaded === true;
9657
- const [baseline, setBaseline] = (0, import_react7.useState)(null);
9658
- (0, import_react7.useEffect)(() => {
9566
+ const [baseline, setBaseline] = (0, import_react9.useState)(null);
9567
+ (0, import_react9.useEffect)(() => {
9659
9568
  if (loaded && baseline === null) setBaseline(chat.length);
9660
9569
  }, [loaded, baseline, chat.length]);
9661
9570
  if (open) return 0;
@@ -9668,14 +9577,14 @@ function Popover({
9668
9577
  children,
9669
9578
  placement = "up"
9670
9579
  }) {
9671
- const ref = (0, import_react7.useRef)(null);
9672
- const [style, setStyle] = (0, import_react7.useState)({
9580
+ const ref = (0, import_react9.useRef)(null);
9581
+ const [style, setStyle] = (0, import_react9.useState)({
9673
9582
  position: "fixed",
9674
9583
  top: 0,
9675
9584
  left: 0,
9676
9585
  visibility: "hidden"
9677
9586
  });
9678
- (0, import_react7.useLayoutEffect)(() => {
9587
+ (0, import_react9.useLayoutEffect)(() => {
9679
9588
  const element = ref.current;
9680
9589
  const anchor = element?.parentElement ?? null;
9681
9590
  if (element === null || anchor === null) return;
@@ -9720,7 +9629,7 @@ function Popover({
9720
9629
  window.removeEventListener("scroll", place, true);
9721
9630
  };
9722
9631
  }, [placement]);
9723
- (0, import_react7.useEffect)(() => {
9632
+ (0, import_react9.useEffect)(() => {
9724
9633
  const onKey = (event) => {
9725
9634
  if (event.key === "Escape") onClose();
9726
9635
  };
@@ -9754,7 +9663,7 @@ function MenuItem({
9754
9663
  );
9755
9664
  }
9756
9665
  function Toast({ text: text3, failed, onDone }) {
9757
- (0, import_react7.useEffect)(() => {
9666
+ (0, import_react9.useEffect)(() => {
9758
9667
  const timer = setTimeout(onDone, failed ? 7e3 : 4e3);
9759
9668
  return () => clearTimeout(timer);
9760
9669
  }, [text3, failed, onDone]);
@@ -9793,7 +9702,7 @@ function MeetingOverlays() {
9793
9702
  ] });
9794
9703
  }
9795
9704
  function ShortcutsSheet({ onClose }) {
9796
- (0, import_react7.useEffect)(() => {
9705
+ (0, import_react9.useEffect)(() => {
9797
9706
  const onKey = (event) => {
9798
9707
  if (event.key === "Escape") onClose();
9799
9708
  };
@@ -9831,8 +9740,8 @@ function PanelShell({
9831
9740
  onClose,
9832
9741
  children
9833
9742
  }) {
9834
- const ref = (0, import_react7.useRef)(null);
9835
- (0, import_react7.useLayoutEffect)(() => {
9743
+ const ref = (0, import_react9.useRef)(null);
9744
+ (0, import_react9.useLayoutEffect)(() => {
9836
9745
  const panel = ref.current;
9837
9746
  const root = panel?.closest(".mx-meet");
9838
9747
  const header = root?.querySelector(":scope > .mx-meet__header") ?? null;
@@ -9859,17 +9768,17 @@ function ChatPanel({
9859
9768
  }) {
9860
9769
  const snapshot = useMeetSnapshot();
9861
9770
  const room = useRoom();
9862
- const [draft, setDraft] = (0, import_react7.useState)("");
9863
- const [recipient, setRecipient] = (0, import_react7.useState)(to);
9864
- const listRef = (0, import_react7.useRef)(null);
9771
+ const [draft, setDraft] = (0, import_react9.useState)("");
9772
+ const [recipient, setRecipient] = (0, import_react9.useState)(to);
9773
+ const listRef = (0, import_react9.useRef)(null);
9865
9774
  const messages = snapshot?.chat ?? [];
9866
9775
  const local = snapshot?.localIdentity ?? null;
9867
9776
  const people = (snapshot?.participants ?? []).filter(
9868
9777
  (participant) => !participant.isLocal && !participant.isAgent
9869
9778
  );
9870
9779
  const recipientName = recipient === null ? null : people.find((p) => p.identity === recipient)?.displayName ?? null;
9871
- (0, import_react7.useEffect)(() => setRecipient(to), [to]);
9872
- (0, import_react7.useEffect)(() => {
9780
+ (0, import_react9.useEffect)(() => setRecipient(to), [to]);
9781
+ (0, import_react9.useEffect)(() => {
9873
9782
  const list = listRef.current;
9874
9783
  if (list !== null) list.scrollTop = list.scrollHeight;
9875
9784
  }, [messages.length]);
@@ -9975,8 +9884,8 @@ function PeoplePanel({
9975
9884
  const snapshot = useMeetSnapshot();
9976
9885
  const controls = useHostControls();
9977
9886
  const queue = useHandQueue();
9978
- const [query, setQuery] = (0, import_react7.useState)("");
9979
- const [menuFor, setMenuFor] = (0, import_react7.useState)(null);
9887
+ const [query, setQuery] = (0, import_react9.useState)("");
9888
+ const [menuFor, setMenuFor] = (0, import_react9.useState)(null);
9980
9889
  const myRole = useRole();
9981
9890
  const local = snapshot?.localIdentity ?? null;
9982
9891
  const everyone = snapshot?.participants ?? [];
@@ -10101,14 +10010,14 @@ function PersonMenu({
10101
10010
  const host = useMeetHost();
10102
10011
  const snapshot = useMeetSnapshot();
10103
10012
  const controls = useHostControls();
10104
- const [mode, setMode] = (0, import_react7.useState)("menu");
10105
- const [text3, setText] = (0, import_react7.useState)("");
10013
+ const [mode, setMode] = (0, import_react9.useState)("menu");
10014
+ const [text3, setText] = (0, import_react9.useState)("");
10106
10015
  const self = participant.identity === snapshot?.localIdentity;
10107
10016
  const moderate = controls.canModerate(participant);
10108
10017
  const pinned = snapshot?.pinned === participant.identity;
10109
10018
  const spotlit = snapshot?.spotlight === participant.identity;
10110
10019
  const hasAccount = participant.userId !== null;
10111
- const [refused, setRefused] = (0, import_react7.useState)(false);
10020
+ const [refused, setRefused] = (0, import_react9.useState)(false);
10112
10021
  const act = (request) => {
10113
10022
  setRefused(false);
10114
10023
  void controls.run(request).then((result) => {
@@ -10324,8 +10233,8 @@ function DeviceSettings({
10324
10233
  const speaker = devices?.selected.audiooutput ?? host.devices.resolve("audiooutput");
10325
10234
  const stream = useMicrophoneStream(microphone);
10326
10235
  const level = useAudioLevel(stream);
10327
- const [testing, setTesting] = (0, import_react7.useState)(false);
10328
- (0, import_react7.useEffect)(() => {
10236
+ const [testing, setTesting] = (0, import_react9.useState)(false);
10237
+ (0, import_react9.useEffect)(() => {
10329
10238
  void host.devices.refresh();
10330
10239
  }, [host]);
10331
10240
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "mx-meet__section", "aria-label": "Devices", children: [
@@ -10354,8 +10263,8 @@ function DeviceSettings({
10354
10263
  }
10355
10264
  function EffectsSettings({ preview }) {
10356
10265
  const effects = useMediaEffects();
10357
- const [error, setError] = (0, import_react7.useState)(null);
10358
- const fileRef = (0, import_react7.useRef)(null);
10266
+ const [error, setError] = (0, import_react9.useState)(null);
10267
+ const fileRef = (0, import_react9.useRef)(null);
10359
10268
  const supported = effects.backgroundsSupported || preview != null || videoEffectsSupported();
10360
10269
  const apply = (next) => {
10361
10270
  setError(null);
@@ -10477,8 +10386,8 @@ async function playTestSound(sinkId) {
10477
10386
  await context.close();
10478
10387
  }
10479
10388
  function useMicrophoneStream(deviceId2) {
10480
- const [stream, setStream] = (0, import_react7.useState)(null);
10481
- (0, import_react7.useEffect)(() => {
10389
+ const [stream, setStream] = (0, import_react9.useState)(null);
10390
+ (0, import_react9.useEffect)(() => {
10482
10391
  if (deviceId2 === "off") return void 0;
10483
10392
  let live = true;
10484
10393
  let opened = null;
@@ -10588,7 +10497,7 @@ function NoteList({
10588
10497
  }
10589
10498
  function AiPanel({ onClose }) {
10590
10499
  const ai = useMeetAi();
10591
- const [question, setQuestion] = (0, import_react7.useState)("");
10500
+ const [question, setQuestion] = (0, import_react9.useState)("");
10592
10501
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(PanelShell, { title: "Meeting assistant", onClose, children: [
10593
10502
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(NoteTakerRow, {}),
10594
10503
  ai.summary !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "mx-meet__note-group", "aria-label": "Summary", children: [
@@ -10753,16 +10662,16 @@ function PreJoinBody({
10753
10662
  const recording = useRecording();
10754
10663
  const effects = useMediaEffects();
10755
10664
  const { notice } = useModerationNotice();
10756
- const [mode, setMode] = (0, import_react7.useState)("video");
10757
- const [microphone, setMicrophone] = (0, import_react7.useState)(true);
10758
- const [joining, setJoining] = (0, import_react7.useState)(false);
10665
+ const [mode, setMode] = (0, import_react9.useState)("video");
10666
+ const [microphone, setMicrophone] = (0, import_react9.useState)(true);
10667
+ const [joining, setJoining] = (0, import_react9.useState)(false);
10759
10668
  const camera = devices?.selected.videoinput ?? host.devices.resolve("videoinput");
10760
10669
  const mic = devices?.selected.audioinput ?? host.devices.resolve("audioinput");
10761
10670
  const preview = useCameraPreview(mode === "video" ? camera : void 0, effects.effects);
10762
10671
  const micStream = useMicrophoneStream(microphone ? mic : "off");
10763
10672
  const level = useAudioLevel(micStream);
10764
- const [speakerTesting, setSpeakerTesting] = (0, import_react7.useState)(false);
10765
- (0, import_react7.useEffect)(() => {
10673
+ const [speakerTesting, setSpeakerTesting] = (0, import_react9.useState)(false);
10674
+ (0, import_react9.useEffect)(() => {
10766
10675
  void host.devices.refresh();
10767
10676
  }, [host]);
10768
10677
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet__prejoin", children: [
@@ -10878,12 +10787,12 @@ function PreJoinBody({
10878
10787
  ] });
10879
10788
  }
10880
10789
  function useCameraPreview(deviceId2, effects) {
10881
- const [preview, setPreview] = (0, import_react7.useState)(null);
10882
- const [error, setError] = (0, import_react7.useState)(null);
10883
- const current = (0, import_react7.useRef)(null);
10884
- const initialEffect = (0, import_react7.useRef)(toVideoEffect(effects));
10790
+ const [preview, setPreview] = (0, import_react9.useState)(null);
10791
+ const [error, setError] = (0, import_react9.useState)(null);
10792
+ const current = (0, import_react9.useRef)(null);
10793
+ const initialEffect = (0, import_react9.useRef)(toVideoEffect(effects));
10885
10794
  initialEffect.current = toVideoEffect(effects);
10886
- (0, import_react7.useEffect)(() => {
10795
+ (0, import_react9.useEffect)(() => {
10887
10796
  if (deviceId2 === void 0) return void 0;
10888
10797
  let live = true;
10889
10798
  setError(null);
@@ -10949,43 +10858,17 @@ function DevicePicker({
10949
10858
  )
10950
10859
  ] });
10951
10860
  }
10952
- function MeetingRoom(props) {
10953
- const host = useMeetHost();
10954
- if (host === null) {
10955
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MeetRoot, { meeting: props.meeting, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mx-meet", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(InertNotice, { what: "This meeting" }) }) });
10956
- }
10957
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MeetRoot, { meeting: props.meeting, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MeetingRoomBody, { ...props, host }) });
10958
- }
10959
- function MeetingRoomBody({
10861
+ function MeetSkinRoom({
10960
10862
  roomName,
10961
10863
  meetingId,
10962
10864
  slug,
10963
- meeting: given,
10964
10865
  onLeave,
10965
- headerControls,
10966
- host
10866
+ headerControls
10967
10867
  }) {
10968
- const snapshot = useMeetSnapshot();
10969
- const isHost = useIsHost();
10868
+ const { host, snapshot, isHost } = useMeetCore();
10970
10869
  const elapsed = useElapsed(snapshot?.meeting?.startedAt ?? null);
10971
10870
  const phase = snapshot?.phase ?? "idle";
10972
- (0, import_react7.useEffect)(() => {
10973
- host.meetings.watch(roomName);
10974
- }, [host, roomName]);
10975
- (0, import_react7.useEffect)(() => {
10976
- if (given === void 0) return;
10977
- if (host.store.snapshot().meeting !== null) return;
10978
- host.store.patch({ meeting: given, locked: given.locked });
10979
- }, [host, given]);
10980
- const watchedId = meetingId ?? snapshot?.meeting?.id ?? null;
10981
- (0, import_react7.useEffect)(() => {
10982
- if (watchedId === null) return;
10983
- host.meetings.watchMeeting(asMeetingId(watchedId));
10984
- }, [host, watchedId]);
10985
- const record = snapshot?.meeting ?? given ?? null;
10986
- if (hasEnded(record) && phase !== "connected" && phase !== "reconnecting") {
10987
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MeetingRecordView, { meeting: record });
10988
- }
10871
+ if (host === null) return null;
10989
10872
  if (phase === "idle" || phase === "failed" || phase === "left") {
10990
10873
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mx-meet", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
10991
10874
  PreJoin,
@@ -11006,7 +10889,7 @@ function MeetingRoomBody({
11006
10889
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h1", { className: "mx-meet__title", children: snapshot?.meeting?.title ?? "Meeting" }),
11007
10890
  /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "mx-meet__meta", children: [
11008
10891
  participantSummary(snapshot?.participants ?? []),
11009
- elapsed > 0 ? ` \xB7 ${(0, import_format4.formatDurationMs)(elapsed)}` : ""
10892
+ elapsed > 0 ? ` \xB7 ${(0, import_format3.formatDurationMs)(elapsed)}` : ""
11010
10893
  ] }),
11011
10894
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RecordingIndicator, {}),
11012
10895
  snapshot?.locked === true ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "mx-meet__badge", children: [
@@ -11023,8 +10906,8 @@ function MeetingRoomBody({
11023
10906
  ] });
11024
10907
  }
11025
10908
  function WaitingRoom({ roomName, host }) {
11026
- const knocked = (0, import_react7.useRef)(false);
11027
- (0, import_react7.useEffect)(() => {
10909
+ const knocked = (0, import_react9.useRef)(false);
10910
+ (0, import_react9.useEffect)(() => {
11028
10911
  if (knocked.current) return;
11029
10912
  knocked.current = true;
11030
10913
  host.meetings.knock(roomName);
@@ -11043,7 +10926,7 @@ function HostMenu() {
11043
10926
  const host = useRequiredMeetHost();
11044
10927
  const snapshot = useMeetSnapshot();
11045
10928
  const end = useEndMeeting();
11046
- const [confirmingEnd, setConfirmingEnd] = (0, import_react7.useState)(false);
10929
+ const [confirmingEnd, setConfirmingEnd] = (0, import_react9.useState)(false);
11047
10930
  const locked = snapshot?.locked === true;
11048
10931
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet__host-menu", children: [
11049
10932
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
@@ -11092,150 +10975,17 @@ function HostMenu() {
11092
10975
  end.notice !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__notice", role: "status", children: end.notice }) : null
11093
10976
  ] });
11094
10977
  }
11095
- function CallButton({
11096
- person,
11097
- mode = "video",
11098
- children
11099
- }) {
11100
- const calls = useCalls();
11101
- if (!calls.canCall) return null;
11102
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
11103
- "button",
11104
- {
11105
- type: "button",
11106
- className: "mx-meet__call-button",
11107
- onClick: () => {
11108
- void calls.call([person.userId], mode);
11109
- },
11110
- "aria-label": `Call ${person.displayName}`,
11111
- children: children ?? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PhoneIcon, { width: 18, height: 18 })
11112
- }
11113
- );
11114
- }
11115
- function IncomingCallHost() {
11116
- const calls = useCalls();
11117
- if (calls.incoming.length === 0) return null;
11118
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mx-meet__ringing-stack", children: calls.incoming.map((invite) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IncomingCallCard, { invite }, invite.id)) });
11119
- }
11120
- function IncomingCallCard({ invite }) {
11121
- const calls = useCalls();
11122
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "mx-meet__ringing", role: "alertdialog", "aria-label": "Incoming call", children: [
11123
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Avatar, { name: invite.callerName, url: invite.callerAvatarUrl, size: 56 }),
11124
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet__ringing-text", children: [
11125
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("strong", { children: invite.callerName }),
11126
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: invite.mode === "video" ? "Incoming video call" : "Incoming call" })
11127
- ] }),
11128
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet__ringing-actions", children: [
11129
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ControlButton, { label: "Decline", danger: true, onClick: () => void calls.decline(invite), children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PhoneOffIcon, {}) }),
11130
- invite.mode === "video" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
11131
- ControlButton,
11132
- {
11133
- label: "Accept without video",
11134
- onClick: () => void calls.accept({ ...invite, mode: "audio" }),
11135
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(CameraOffIcon, {})
11136
- }
11137
- ) : null,
11138
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ControlButton, { label: "Accept", onClick: () => void calls.accept(invite), children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(PhoneIcon, {}) })
11139
- ] })
11140
- ] });
11141
- }
11142
- function ScheduleMeeting(props) {
11143
- const host = useMeetHost();
11144
- if (host === null) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(InertNotice, { what: "Scheduling a meeting" });
11145
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ScheduleMeetingBody, { ...props, host });
11146
- }
11147
- function ScheduleMeetingBody({
11148
- appBaseUrl,
11149
- onScheduled,
11150
- host
11151
- }) {
11152
- const [title, setTitle] = (0, import_react7.useState)("");
11153
- const [when2, setWhen] = (0, import_react7.useState)("");
11154
- const [kind, setKind] = (0, import_react7.useState)("scheduled");
11155
- const [busy, setBusy] = (0, import_react7.useState)(false);
11156
- const [link, setLink] = (0, import_react7.useState)(null);
11157
- const [error, setError] = (0, import_react7.useState)(null);
11158
- const disabled = (0, import_react7.useMemo)(() => title.trim().length === 0 || busy, [title, busy]);
11159
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
11160
- "form",
11161
- {
11162
- className: "mx-meet__schedule",
11163
- onSubmit: (event) => {
11164
- event.preventDefault();
11165
- if (host.identity.userId === null) return;
11166
- setBusy(true);
11167
- setError(null);
11168
- void host.repository.getOrCreateMeeting({
11169
- organizationId: host.identity.organizationId,
11170
- hostUserId: host.identity.userId,
11171
- title: title.trim(),
11172
- kind,
11173
- scheduledFor: when2.length > 0 ? new Date(when2).toISOString() : null
11174
- }).then((meeting) => {
11175
- setLink(meetingLink(appBaseUrl, meeting.slug));
11176
- onScheduled?.(meeting.slug);
11177
- }).catch((thrown) => {
11178
- setError(
11179
- thrown.remedy ?? thrown.message ?? "The meeting could not be created."
11180
- );
11181
- }).finally(() => setBusy(false));
11182
- },
11183
- children: [
11184
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mx-meet__field", children: [
11185
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__field-label", children: "Title" }),
11186
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
11187
- "input",
11188
- {
11189
- className: "mx-meet__input",
11190
- value: title,
11191
- onChange: (event) => setTitle(event.target.value),
11192
- placeholder: "Weekly sync"
11193
- }
11194
- )
11195
- ] }),
11196
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mx-meet__field", children: [
11197
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__field-label", children: "When" }),
11198
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
11199
- "input",
11200
- {
11201
- className: "mx-meet__input",
11202
- type: "datetime-local",
11203
- value: when2,
11204
- onChange: (event) => setWhen(event.target.value)
11205
- }
11206
- )
11207
- ] }),
11208
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("label", { className: "mx-meet__field", children: [
11209
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__field-label", children: "Repeats" }),
11210
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
11211
- "select",
11212
- {
11213
- className: "mx-meet__select",
11214
- value: kind,
11215
- onChange: (event) => setKind(event.target.value),
11216
- children: [
11217
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "scheduled", children: "Once" }),
11218
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("option", { value: "recurring", children: "Recurring \u2014 one link, every time" })
11219
- ]
11220
- }
11221
- )
11222
- ] }),
11223
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "submit", className: "mx-meet__primary", disabled, children: busy ? "Creating\u2026" : "Create meeting" }),
11224
- link !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { className: "mx-meet__link-out", children: [
11225
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: "Anyone with this link can join \u2014 no account needed." }),
11226
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("code", { children: link })
11227
- ] }) : null,
11228
- error !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__error", children: error }) : null
11229
- ]
11230
- }
11231
- );
11232
- }
11233
10978
  function ReactionOverlay({
11234
10979
  reactions
11235
10980
  }) {
11236
10981
  if (reactions.length === 0) return null;
11237
10982
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mx-meet__reactions", "aria-hidden": "true", children: reactions.map((reaction) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__reaction", children: reaction.emoji }, reaction.id)) });
11238
10983
  }
10984
+ function clockOf(iso) {
10985
+ const at = new Date(iso);
10986
+ if (Number.isNaN(at.getTime())) return "";
10987
+ return at.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" });
10988
+ }
11239
10989
  function GuestRecordAccessControl({
11240
10990
  meeting
11241
10991
  }) {
@@ -11276,15 +11026,20 @@ function GuestRecordAccessControl({
11276
11026
  ] }) : null
11277
11027
  ] });
11278
11028
  }
11029
+
11030
+ // src/react/record.tsx
11031
+ var import_react10 = require("react");
11032
+ var import_design_system2 = require("@ai-matrx/design-system");
11033
+ var import_jsx_runtime6 = require("react/jsx-runtime");
11279
11034
  function MeetingRecordView({
11280
11035
  meeting,
11281
11036
  onRejoin
11282
11037
  }) {
11283
11038
  const host = useMeetHost();
11284
11039
  if (host === null) {
11285
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mx-meet mx-meet--record", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(InertNotice, { what: "This meeting record" }) });
11040
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mx-meet mx-meet--record", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(InertNotice, { what: "This meeting record" }) });
11286
11041
  }
11287
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(MeetingRecordBody, { meeting, ...onRejoin !== void 0 ? { onRejoin } : {} });
11042
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(MeetingRecordBody, { meeting, ...onRejoin !== void 0 ? { onRejoin } : {} });
11288
11043
  }
11289
11044
  function MeetingRecordBody({
11290
11045
  meeting,
@@ -11292,19 +11047,19 @@ function MeetingRecordBody({
11292
11047
  }) {
11293
11048
  const host = useRequiredMeetHost();
11294
11049
  const record = useMeetingRecord(meeting);
11295
- const [question, setQuestion] = (0, import_react7.useState)("");
11296
- const [tab, setTab] = (0, import_react7.useState)("summary");
11050
+ const [question, setQuestion] = (0, import_react10.useState)("");
11051
+ const [tab, setTab] = (0, import_react10.useState)("summary");
11297
11052
  if (record.failure !== null) {
11298
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mx-meet mx-meet--record", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system.ErrorBox, { as: "div", className: "mx-meet__empty", error: record.failure, operation: "Open this meeting record", origin: "meet/components", children: [
11299
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__empty-title", children: "This meeting record could not be opened" }),
11300
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__empty-body", children: record.failure.message }),
11301
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__empty-body", children: record.failure.remedy })
11053
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mx-meet mx-meet--record", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system2.ErrorBox, { as: "div", className: "mx-meet__empty", error: record.failure, operation: "Open this meeting record", origin: "meet/components", children: [
11054
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__empty-title", children: "This meeting record could not be opened" }),
11055
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__empty-body", children: record.failure.message }),
11056
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__empty-body", children: record.failure.remedy })
11302
11057
  ] }) });
11303
11058
  }
11304
11059
  if (record.loading || record.record === null) {
11305
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mx-meet mx-meet--record", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet__empty", role: "status", children: [
11306
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__empty-title", children: "Opening the meeting record\u2026" }),
11307
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__empty-body", children: "Reading the summary, the notes and the transcript this meeting left behind." })
11060
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mx-meet mx-meet--record", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-meet__empty", role: "status", children: [
11061
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__empty-title", children: "Opening the meeting record\u2026" }),
11062
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__empty-body", children: "Reading the summary, the notes and the transcript this meeting left behind." })
11308
11063
  ] }) });
11309
11064
  }
11310
11065
  const bundle = record.record;
@@ -11323,44 +11078,44 @@ function MeetingRecordBody({
11323
11078
  );
11324
11079
  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;
11325
11080
  if (entirelyRestricted) {
11326
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet mx-meet--record", children: [
11327
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("header", { className: "mx-meet__record-head", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet__record-head-inner", children: [
11328
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__record-eyebrow", children: "Meeting record" }),
11329
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h1", { className: "mx-meet__record-title", children: meeting.title }),
11330
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__record-when", children: meetingWhen(meeting) }),
11331
- onRejoin !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mx-meet__link", onClick: onRejoin, children: "Open this link again" }) : null
11081
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-meet mx-meet--record", children: [
11082
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("header", { className: "mx-meet__record-head", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-meet__record-head-inner", children: [
11083
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__record-eyebrow", children: "Meeting record" }),
11084
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h1", { className: "mx-meet__record-title", children: meeting.title }),
11085
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__record-when", children: meetingWhen(meeting) }),
11086
+ onRejoin !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "mx-meet__link", onClick: onRejoin, children: "Open this link again" }) : null
11332
11087
  ] }) }),
11333
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mx-meet__record-body", children: restrictionNotices.map((notice2) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet__record-access", role: "status", children: [
11334
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__record-access-title", children: "About this record" }),
11335
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__record-access-message", children: notice2.message }),
11336
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__record-access-remedy", children: notice2.remedy })
11088
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mx-meet__record-body", children: restrictionNotices.map((notice2) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-meet__record-access", role: "status", children: [
11089
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__record-access-title", children: "About this record" }),
11090
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__record-access-message", children: notice2.message }),
11091
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__record-access-remedy", children: notice2.remedy })
11337
11092
  ] }, notice2.parts.join("-"))) })
11338
11093
  ] });
11339
11094
  }
11340
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet mx-meet--record", children: [
11341
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("header", { className: "mx-meet__record-head", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet__record-head-inner", children: [
11342
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__record-eyebrow", children: "Meeting record" }),
11343
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h1", { className: "mx-meet__record-title", children: meeting.title }),
11344
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__record-when", children: meetingWhen(meeting) }),
11345
- onRejoin !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mx-meet__link", onClick: onRejoin, children: "Open this link again" }) : null
11095
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-meet mx-meet--record", children: [
11096
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("header", { className: "mx-meet__record-head", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-meet__record-head-inner", children: [
11097
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__record-eyebrow", children: "Meeting record" }),
11098
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h1", { className: "mx-meet__record-title", children: meeting.title }),
11099
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__record-when", children: meetingWhen(meeting) }),
11100
+ onRejoin !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "mx-meet__link", onClick: onRejoin, children: "Open this link again" }) : null
11346
11101
  ] }) }),
11347
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet__record-body", children: [
11348
- restrictionNotices.map((notice2) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet__record-access", role: "status", children: [
11349
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__record-access-title", children: "About this record" }),
11350
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__record-access-message", children: notice2.message }),
11351
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__record-access-remedy", children: notice2.remedy })
11102
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-meet__record-body", children: [
11103
+ restrictionNotices.map((notice2) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-meet__record-access", role: "status", children: [
11104
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__record-access-title", children: "About this record" }),
11105
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__record-access-message", children: notice2.message }),
11106
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__record-access-remedy", children: notice2.remedy })
11352
11107
  ] }, notice2.parts.join("-"))),
11353
11108
  attended.length === 0 ? (
11354
11109
  /* NOT SILENCE. A refused attendance read used to remove the whole
11355
11110
  section, so the reader could not tell "nobody" from "not shown". */
11356
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Who attended", children: [
11357
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: "mx-meet__record-section-title", children: "Who attended" }),
11358
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__panel-note", children: absenceSentence(bundle, "attendance", "Nobody is recorded as having attended.") })
11111
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Who attended", children: [
11112
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { className: "mx-meet__record-section-title", children: "Who attended" }),
11113
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__panel-note", children: absenceSentence(bundle, "attendance", "Nobody is recorded as having attended.") })
11359
11114
  ] })
11360
- ) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Who attended", children: [
11361
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: "mx-meet__record-section-title", children: "Who attended" }),
11362
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ul", { className: "mx-meet__record-attendees", children: attended.map((person) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("li", { className: "mx-meet__record-attendee", children: [
11363
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
11115
+ ) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Who attended", children: [
11116
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { className: "mx-meet__record-section-title", children: "Who attended" }),
11117
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { className: "mx-meet__record-attendees", children: attended.map((person) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("li", { className: "mx-meet__record-attendee", children: [
11118
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
11364
11119
  Avatar,
11365
11120
  {
11366
11121
  name: displayNameFor(bundle.names, person.identity, person.displayName),
@@ -11368,26 +11123,26 @@ function MeetingRecordBody({
11368
11123
  size: 28
11369
11124
  }
11370
11125
  ),
11371
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "mx-meet__person-name", children: [
11126
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "mx-meet__person-name", children: [
11372
11127
  displayNameFor(bundle.names, person.identity, person.displayName),
11373
- person.role === "host" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__badge", children: "Host" }) : null,
11374
- person.role === "guest" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__badge", children: "Guest" }) : null,
11375
- person.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__badge", children: "Meeting assistant" }) : null
11128
+ person.role === "host" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mx-meet__badge", children: "Host" }) : null,
11129
+ person.role === "guest" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mx-meet__badge", children: "Guest" }) : null,
11130
+ person.isAgent ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mx-meet__badge", children: "Meeting assistant" }) : null
11376
11131
  ] })
11377
11132
  ] }, person.id)) })
11378
11133
  ] }),
11379
- bundle.recording !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "mx-meet__record-section mx-meet__recording-card", "aria-label": "Recording", children: [
11380
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: "mx-meet__record-section-title", children: "Recording" }),
11381
- fileId !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
11382
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RecordingPlayer, { fileId }),
11383
- notice !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__panel-note", children: notice }) : null
11384
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__panel-note", children: notice ?? "This recording has no file." })
11385
- ] }) : wasRefused(bundle, "recording") ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Recording", children: [
11386
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: "mx-meet__record-section-title", children: "Recording" }),
11387
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__panel-note", children: REFUSED_ABSENCE })
11134
+ bundle.recording !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: "mx-meet__record-section mx-meet__recording-card", "aria-label": "Recording", children: [
11135
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { className: "mx-meet__record-section-title", children: "Recording" }),
11136
+ fileId !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
11137
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RecordingPlayer, { fileId }),
11138
+ notice !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__panel-note", children: notice }) : null
11139
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__panel-note", children: notice ?? "This recording has no file." })
11140
+ ] }) : wasRefused(bundle, "recording") ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Recording", children: [
11141
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { className: "mx-meet__record-section-title", children: "Recording" }),
11142
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__panel-note", children: REFUSED_ABSENCE })
11388
11143
  ] }) : null,
11389
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("nav", { className: "mx-meet__record-tabs", "aria-label": "Meeting record sections", children: [
11390
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
11144
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("nav", { className: "mx-meet__record-tabs", "aria-label": "Meeting record sections", children: [
11145
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
11391
11146
  "button",
11392
11147
  {
11393
11148
  type: "button",
@@ -11397,7 +11152,7 @@ function MeetingRecordBody({
11397
11152
  children: "Summary & decisions"
11398
11153
  }
11399
11154
  ),
11400
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
11155
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
11401
11156
  "button",
11402
11157
  {
11403
11158
  type: "button",
@@ -11407,7 +11162,7 @@ function MeetingRecordBody({
11407
11162
  children: "Notes as it happened"
11408
11163
  }
11409
11164
  ),
11410
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
11165
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
11411
11166
  "button",
11412
11167
  {
11413
11168
  type: "button",
@@ -11418,15 +11173,15 @@ function MeetingRecordBody({
11418
11173
  }
11419
11174
  )
11420
11175
  ] }),
11421
- tab === "summary" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
11422
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Summary", children: [
11423
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: "mx-meet__record-section-title", children: "Summary" }),
11424
- wrapUp.state === "written" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__record-summary", children: bundle.summary?.text }) : wrapUp.state === "in-progress" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet__panel-note", role: "status", children: [
11425
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { children: wrapUp.message }),
11426
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { type: "button", className: "mx-meet__link", onClick: record.reload, children: "Check again" })
11427
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__panel-note", role: wrapUp.state === "failed" ? "alert" : void 0, children: wrapUp.message })
11176
+ tab === "summary" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
11177
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Summary", children: [
11178
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { className: "mx-meet__record-section-title", children: "Summary" }),
11179
+ wrapUp.state === "written" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__record-summary", children: bundle.summary?.text }) : wrapUp.state === "in-progress" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-meet__panel-note", role: "status", children: [
11180
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { children: wrapUp.message }),
11181
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("button", { type: "button", className: "mx-meet__link", onClick: record.reload, children: "Check again" })
11182
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__panel-note", role: wrapUp.state === "failed" ? "alert" : void 0, children: wrapUp.message })
11428
11183
  ] }),
11429
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
11184
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
11430
11185
  NoteList,
11431
11186
  {
11432
11187
  title: "Decisions",
@@ -11438,7 +11193,7 @@ function MeetingRecordBody({
11438
11193
  )
11439
11194
  }
11440
11195
  ),
11441
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
11196
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
11442
11197
  NoteList,
11443
11198
  {
11444
11199
  title: "Action items",
@@ -11451,42 +11206,42 @@ function MeetingRecordBody({
11451
11206
  }
11452
11207
  )
11453
11208
  ] }) : null,
11454
- tab === "notes" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Notes as it happened", children: [
11455
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: "mx-meet__record-section-title", children: "Notes as it happened" }),
11456
- bundle.liveNotes.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__panel-note", children: absenceSentence(
11209
+ tab === "notes" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Notes as it happened", children: [
11210
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { className: "mx-meet__record-section-title", children: "Notes as it happened" }),
11211
+ bundle.liveNotes.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__panel-note", children: absenceSentence(
11457
11212
  bundle,
11458
11213
  "notes",
11459
11214
  "No live notes are available for this meeting."
11460
- ) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ul", { className: "mx-meet__notes", children: bundle.liveNotes.map((note) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("li", { className: "mx-meet__note", children: [
11461
- note.window !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "mx-meet__badge", children: [
11215
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { className: "mx-meet__notes", children: bundle.liveNotes.map((note) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("li", { className: "mx-meet__note", children: [
11216
+ note.window !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("span", { className: "mx-meet__badge", children: [
11462
11217
  "Window ",
11463
11218
  note.window
11464
11219
  ] }) : null,
11465
11220
  note.text
11466
11221
  ] }, note.id)) })
11467
11222
  ] }) : null,
11468
- tab === "transcript" ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Transcript", children: [
11469
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("h2", { className: "mx-meet__record-section-title", children: [
11223
+ tab === "transcript" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Transcript", children: [
11224
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("h2", { className: "mx-meet__record-section-title", children: [
11470
11225
  "Transcript",
11471
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__record-count", children: bundle.transcript.length === 1 ? "1 line" : `${bundle.transcript.length} lines` })
11226
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "mx-meet__record-count", children: bundle.transcript.length === 1 ? "1 line" : `${bundle.transcript.length} lines` })
11472
11227
  ] }),
11473
- blocks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__panel-note", children: absenceSentence(
11228
+ blocks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__panel-note", children: absenceSentence(
11474
11229
  bundle,
11475
11230
  "transcript",
11476
11231
  "No transcript is available for this meeting."
11477
- ) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ol", { className: "mx-meet__record-transcript", children: blocks.map((block) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("li", { className: "mx-meet__record-block", children: [
11478
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { className: "mx-meet__record-speaker", children: [
11232
+ ) }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ol", { className: "mx-meet__record-transcript", children: blocks.map((block) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("li", { className: "mx-meet__record-block", children: [
11233
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: "mx-meet__record-speaker", children: [
11479
11234
  block.speaker,
11480
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("time", { className: "mx-meet__record-time", dateTime: block.startedAt, children: clockOf(block.startedAt) })
11235
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("time", { className: "mx-meet__record-time", dateTime: block.startedAt, children: clockOf(block.startedAt) })
11481
11236
  ] }),
11482
- block.lines.map((line) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__record-line", children: line.text }, line.id))
11237
+ block.lines.map((line) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__record-line", children: line.text }, line.id))
11483
11238
  ] }, block.id)) })
11484
11239
  ] }) : null,
11485
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(GuestRecordAccessControl, { meeting }),
11486
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Ask about this meeting", children: [
11487
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: "mx-meet__record-section-title", children: "Ask about this meeting" }),
11488
- guestFinishedMeeting ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__panel-note", children: "Sign in to ask the assistant about a meeting after it ends." }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
11489
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
11240
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(GuestRecordAccessControl, { meeting }),
11241
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("section", { className: "mx-meet__record-section", "aria-label": "Ask about this meeting", children: [
11242
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("h2", { className: "mx-meet__record-section-title", children: "Ask about this meeting" }),
11243
+ guestFinishedMeeting ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__panel-note", children: "Sign in to ask the assistant about a meeting after it ends." }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
11244
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
11490
11245
  "form",
11491
11246
  {
11492
11247
  className: "mx-meet__composer",
@@ -11497,7 +11252,7 @@ function MeetingRecordBody({
11497
11252
  void record.ask(trimmed);
11498
11253
  },
11499
11254
  children: [
11500
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
11255
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
11501
11256
  "input",
11502
11257
  {
11503
11258
  className: "mx-meet__input",
@@ -11507,7 +11262,7 @@ function MeetingRecordBody({
11507
11262
  "aria-label": "Ask about this meeting"
11508
11263
  }
11509
11264
  ),
11510
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
11265
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
11511
11266
  "button",
11512
11267
  {
11513
11268
  type: "submit",
@@ -11519,8 +11274,8 @@ function MeetingRecordBody({
11519
11274
  ]
11520
11275
  }
11521
11276
  ),
11522
- record.answer !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__answer", children: record.answer }) : null,
11523
- record.coverage !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("p", { className: "mx-meet__coverage", children: [
11277
+ record.answer !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__answer", children: record.answer }) : null,
11278
+ record.coverage !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("p", { className: "mx-meet__coverage", children: [
11524
11279
  "Answered from ",
11525
11280
  record.coverage.segmentsUsed,
11526
11281
  " of ",
@@ -11531,9 +11286,9 @@ function MeetingRecordBody({
11531
11286
  record.coverage.truncated ? " (the oldest were left out)" : "",
11532
11287
  "."
11533
11288
  ] }) : null,
11534
- record.askError !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system.ErrorBox, { as: "div", className: "mx-meet__refusal", error: record.askError, operation: "Ask about this meeting", origin: "meet/components", children: [
11535
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__refusal-reason", children: record.askError.message }),
11536
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__refusal-remedy", children: record.askError.remedy })
11289
+ record.askError !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system2.ErrorBox, { as: "div", className: "mx-meet__refusal", error: record.askError, operation: "Ask about this meeting", origin: "meet/components", children: [
11290
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__refusal-reason", children: record.askError.message }),
11291
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__refusal-remedy", children: record.askError.remedy })
11537
11292
  ] }) : null
11538
11293
  ] })
11539
11294
  ] })
@@ -11544,21 +11299,21 @@ var STREAM_REFUSED = "Streaming playback did not start, so this recording was do
11544
11299
  var PLAYBACK_RETRY_REMEDY = "Reload the page and try again. If it still will not play, ask a meeting host to check the recording.";
11545
11300
  function RecordingPlayer(props) {
11546
11301
  const host = useMeetHost();
11547
- if (host === null) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(InertNotice, { what: "This recording" });
11548
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(RecordingPlayerBody, { ...props, host });
11302
+ if (host === null) return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(InertNotice, { what: "This recording" });
11303
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(RecordingPlayerBody, { ...props, host });
11549
11304
  }
11550
11305
  function RecordingPlayerBody({ fileId, host }) {
11551
- const [media, setMedia] = (0, import_react7.useState)(null);
11552
- const [loading, setLoading] = (0, import_react7.useState)(false);
11553
- const [error, setError] = (0, import_react7.useState)(null);
11554
- (0, import_react7.useEffect)(() => {
11306
+ const [media, setMedia] = (0, import_react10.useState)(null);
11307
+ const [loading, setLoading] = (0, import_react10.useState)(false);
11308
+ const [error, setError] = (0, import_react10.useState)(null);
11309
+ (0, import_react10.useEffect)(() => {
11555
11310
  if (media === null || media.kind !== "bytes") return void 0;
11556
11311
  const url = media.url;
11557
11312
  return () => URL.revokeObjectURL(url);
11558
11313
  }, [media]);
11559
11314
  if (media !== null) {
11560
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet__record-section", children: [
11561
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
11315
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-meet__record-section", children: [
11316
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
11562
11317
  "video",
11563
11318
  {
11564
11319
  className: "mx-meet__record-player",
@@ -11600,15 +11355,15 @@ function RecordingPlayerBody({ fileId, host }) {
11600
11355
  }
11601
11356
  }
11602
11357
  ),
11603
- media.fallbackReason !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__panel-note", children: media.fallbackReason }) : null
11358
+ media.fallbackReason !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__panel-note", children: media.fallbackReason }) : null
11604
11359
  ] });
11605
11360
  }
11606
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet__record-section", children: [
11607
- error !== null ? /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system.ErrorBox, { as: "div", className: "mx-meet__refusal", error, operation: "Complete this meeting action", origin: "meet/components", children: [
11608
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__refusal-reason", children: error.message }),
11609
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__refusal-remedy", children: error.remedy })
11361
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "mx-meet__record-section", children: [
11362
+ error !== null ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_design_system2.ErrorBox, { as: "div", className: "mx-meet__refusal", error, operation: "Complete this meeting action", origin: "meet/components", children: [
11363
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__refusal-reason", children: error.message }),
11364
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mx-meet__refusal-remedy", children: error.remedy })
11610
11365
  ] }) : null,
11611
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
11366
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
11612
11367
  "button",
11613
11368
  {
11614
11369
  type: "button",
@@ -11636,45 +11391,84 @@ function RecordingPlayerBody({ fileId, host }) {
11636
11391
  )
11637
11392
  ] });
11638
11393
  }
11639
- function clockOf(iso) {
11640
- const at = new Date(iso);
11641
- if (Number.isNaN(at.getTime())) return "";
11642
- return at.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" });
11643
- }
11644
- function MeetingList({ baseUrl }) {
11394
+
11395
+ // src/react/skin-root.tsx
11396
+ var import_jsx_runtime7 = require("react/jsx-runtime");
11397
+ function MeetingSkinRoot(props) {
11645
11398
  const host = useMeetHost();
11646
- const list = useMeetings();
11647
- if (host === null) return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(InertNotice, { what: "Your meetings" });
11648
- if (list.failure !== null) {
11649
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_design_system.ErrorBox, { as: "div", className: "mx-meet__empty", error: list.failure, operation: "List your meetings", origin: "meet/components", children: [
11650
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__empty-title", children: "Your meetings could not be listed" }),
11651
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__empty-body", children: list.failure.message }),
11652
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__empty-body", children: list.failure.remedy })
11653
- ] });
11654
- }
11655
- if (list.loading) {
11656
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "mx-meet__empty", role: "status", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__empty-title", children: "Loading your meetings\u2026" }) });
11399
+ if (host === null) {
11400
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MeetRoot, { meeting: props.meeting, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mx-meet", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(InertNotice, { what: "This meeting" }) }) });
11657
11401
  }
11658
- if (list.meetings.length === 0) {
11659
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet__empty", role: "status", children: [
11660
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "mx-meet__empty-title", children: "No meetings yet" }),
11661
- /* @__PURE__ */ (0, import_jsx_runtime5.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." })
11662
- ] });
11402
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MeetRoot, { meeting: props.meeting, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MeetingSkinRootBody, { ...props, host }) });
11403
+ }
11404
+ function MeetingSkinRootBody({
11405
+ roomName,
11406
+ meetingId,
11407
+ slug,
11408
+ meeting: given,
11409
+ onLeave,
11410
+ headerControls,
11411
+ host
11412
+ }) {
11413
+ const snapshot = useMeetSnapshot();
11414
+ const phase = snapshot?.phase ?? "idle";
11415
+ (0, import_react11.useEffect)(() => {
11416
+ host.meetings.watch(roomName);
11417
+ }, [host, roomName]);
11418
+ (0, import_react11.useEffect)(() => {
11419
+ if (given === void 0) return;
11420
+ if (host.store.snapshot().meeting !== null) return;
11421
+ host.store.patch({ meeting: given, locked: given.locked });
11422
+ }, [host, given]);
11423
+ const watchedId = meetingId ?? snapshot?.meeting?.id ?? null;
11424
+ (0, import_react11.useEffect)(() => {
11425
+ if (watchedId === null) return;
11426
+ host.meetings.watchMeeting(asMeetingId(watchedId));
11427
+ }, [host, watchedId]);
11428
+ const record = snapshot?.meeting ?? given ?? null;
11429
+ if (hasEnded(record) && phase !== "connected" && phase !== "reconnecting") {
11430
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MeetingRecordView, { meeting: record });
11663
11431
  }
11664
- const origin = baseUrl ?? (typeof window === "undefined" ? "" : window.location.origin);
11665
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("ul", { className: "mx-meet-list", children: list.meetings.map((meeting) => {
11666
- const ended = meeting.endedAt !== null;
11667
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("li", { className: "mx-meet-list__row", children: [
11668
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "mx-meet-list__main", children: [
11669
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "mx-meet-list__title", children: [
11670
- meeting.title,
11671
- ended ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet__badge", children: "Ended" }) : null
11672
- ] }),
11673
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "mx-meet-list__when", children: meetingWhen(meeting) })
11674
- ] }),
11675
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("a", { className: "mx-meet-list__action", href: meetingLink(origin, meeting.slug), children: ended ? "Open the record" : "Join" })
11676
- ] }, meeting.id);
11677
- }) });
11432
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
11433
+ MeetSkinRoom,
11434
+ {
11435
+ roomName,
11436
+ ...meetingId !== void 0 ? { meetingId } : {},
11437
+ ...slug !== void 0 ? { slug } : {},
11438
+ ...onLeave !== void 0 ? { onLeave } : {},
11439
+ ...headerControls !== void 0 ? { headerControls } : {}
11440
+ }
11441
+ );
11442
+ }
11443
+
11444
+ // src/react/calls-ui.tsx
11445
+ var import_jsx_runtime8 = require("react/jsx-runtime");
11446
+ function IncomingCallHost() {
11447
+ const calls = useCalls();
11448
+ if (calls.incoming.length === 0) return null;
11449
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "mx-meet__ringing-stack", children: calls.incoming.map((invite) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IncomingCallCard, { invite }, invite.id)) });
11450
+ }
11451
+ function IncomingCallCard({ invite }) {
11452
+ const calls = useCalls();
11453
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("section", { className: "mx-meet__ringing", role: "alertdialog", "aria-label": "Incoming call", children: [
11454
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Avatar, { name: invite.callerName, url: invite.callerAvatarUrl, size: 56 }),
11455
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "mx-meet__ringing-text", children: [
11456
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("strong", { children: invite.callerName }),
11457
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: invite.mode === "video" ? "Incoming video call" : "Incoming call" })
11458
+ ] }),
11459
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "mx-meet__ringing-actions", children: [
11460
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ControlButton, { label: "Decline", danger: true, onClick: () => void calls.decline(invite), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PhoneOffIcon, {}) }),
11461
+ invite.mode === "video" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
11462
+ ControlButton,
11463
+ {
11464
+ label: "Accept without video",
11465
+ onClick: () => void calls.accept({ ...invite, mode: "audio" }),
11466
+ children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(CameraOffIcon, {})
11467
+ }
11468
+ ) : null,
11469
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ControlButton, { label: "Accept", onClick: () => void calls.accept(invite), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PhoneIcon, {}) })
11470
+ ] })
11471
+ ] });
11678
11472
  }
11679
11473
 
11680
11474
  // src/core/invitations.ts