@ai-matrx/meet 0.7.78 → 0.7.80
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/dist/index.cjs +230 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +120 -1
- package/dist/index.d.ts +120 -1
- package/dist/index.js +230 -20
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +489 -219
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +4 -3
- package/dist/react.d.ts +4 -3
- package/dist/react.js +384 -114
- package/dist/react.js.map +1 -1
- package/package.json +2 -2
package/dist/react.cjs
CHANGED
|
@@ -83,6 +83,7 @@ __export(react_exports, {
|
|
|
83
83
|
LockIcon: () => LockIcon,
|
|
84
84
|
MEETING_INVITE_KIND: () => MEETING_INVITE_KIND,
|
|
85
85
|
MEETING_INVITE_VERSION: () => MEETING_INVITE_VERSION,
|
|
86
|
+
MEETING_RECORD_GRACE_MS: () => MEETING_RECORD_GRACE_MS,
|
|
86
87
|
MEET_ANSWER_CONTEXT_EVENT: () => MEET_ANSWER_CONTEXT_EVENT,
|
|
87
88
|
MEET_ANSWER_EVENTS: () => MEET_ANSWER_EVENTS,
|
|
88
89
|
MEET_EVENTS: () => MEET_EVENTS,
|
|
@@ -160,6 +161,7 @@ __export(react_exports, {
|
|
|
160
161
|
asParticipantIdentity: () => asParticipantIdentity,
|
|
161
162
|
asRoomName: () => asRoomName,
|
|
162
163
|
asUserId: () => asUserId,
|
|
164
|
+
assembleMeetingRecord: () => assembleMeetingRecord,
|
|
163
165
|
assignedRoom: () => assignedRoom,
|
|
164
166
|
attendanceCsv: () => attendanceCsv,
|
|
165
167
|
attendanceReport: () => attendanceReport,
|
|
@@ -189,6 +191,7 @@ __export(react_exports, {
|
|
|
189
191
|
createMeetRepository: () => createMeetRepository,
|
|
190
192
|
createMeetStore: () => createMeetStore,
|
|
191
193
|
createMeetingInviteHandler: () => createMeetingInviteHandler,
|
|
194
|
+
createMeetingRecordCache: () => createMeetingRecordCache,
|
|
192
195
|
createMeetingSession: () => createMeetingSession,
|
|
193
196
|
createMemoryDeviceStorage: () => createMemoryDeviceStorage,
|
|
194
197
|
createRecordingController: () => createRecordingController,
|
|
@@ -223,12 +226,14 @@ __export(react_exports, {
|
|
|
223
226
|
loadMeetingActivities: () => loadMeetingActivities,
|
|
224
227
|
loadMeetingChat: () => loadMeetingChat,
|
|
225
228
|
loadMeetingRecord: () => loadMeetingRecord,
|
|
229
|
+
loadMeetingRecordParts: () => loadMeetingRecordParts,
|
|
226
230
|
mapConnectionState: () => mapConnectionState,
|
|
227
231
|
mapQuality: () => mapQuality,
|
|
228
232
|
meetingInviteAction: () => meetingInviteAction,
|
|
229
233
|
meetingLength: () => meetingLength,
|
|
230
234
|
meetingLink: () => meetingLink,
|
|
231
235
|
meetingPath: () => meetingPath,
|
|
236
|
+
meetingRecordCache: () => meetingRecordCache,
|
|
232
237
|
meetingSlug: () => meetingSlug,
|
|
233
238
|
meetingTopic: () => meetingTopic,
|
|
234
239
|
meetingWhen: () => meetingWhen,
|
|
@@ -2205,13 +2210,13 @@ function mergeCaption(list, caption) {
|
|
|
2205
2210
|
return list.map((entry, position) => position === index ? caption : entry);
|
|
2206
2211
|
}
|
|
2207
2212
|
function mergeRecord(list, record) {
|
|
2208
|
-
const
|
|
2209
|
-
if (
|
|
2210
|
-
const existing = list[
|
|
2213
|
+
const byId2 = list.findIndex((entry) => entry.source === "record" && entry.id === record.id);
|
|
2214
|
+
if (byId2 !== -1) {
|
|
2215
|
+
const existing = list[byId2];
|
|
2211
2216
|
if (existing !== void 0 && existing.text === record.text && existing.final === record.final) {
|
|
2212
2217
|
return list;
|
|
2213
2218
|
}
|
|
2214
|
-
return list.map((entry, position) => position ===
|
|
2219
|
+
return list.map((entry, position) => position === byId2 ? record : entry);
|
|
2215
2220
|
}
|
|
2216
2221
|
const captionIndex = list.findIndex((entry) => supersedes(record, entry));
|
|
2217
2222
|
if (captionIndex === -1) return [...list, record];
|
|
@@ -5786,49 +5791,7 @@ function useLocalUserId() {
|
|
|
5786
5791
|
|
|
5787
5792
|
// src/react/hooks.ts
|
|
5788
5793
|
var import_react3 = require("react");
|
|
5789
|
-
|
|
5790
|
-
// src/core/layout.ts
|
|
5791
|
-
var DEFAULT_PAGE_SIZE = 12;
|
|
5792
|
-
function orderParticipants(participants, activeSpeakers) {
|
|
5793
|
-
const speakerRank = /* @__PURE__ */ new Map();
|
|
5794
|
-
activeSpeakers.forEach((identity, index) => speakerRank.set(identity, index));
|
|
5795
|
-
return [...participants].sort((a, b) => {
|
|
5796
|
-
const speakerA = speakerRank.get(a.identity) ?? Number.MAX_SAFE_INTEGER;
|
|
5797
|
-
const speakerB = speakerRank.get(b.identity) ?? Number.MAX_SAFE_INTEGER;
|
|
5798
|
-
if (speakerA !== speakerB) return speakerA - speakerB;
|
|
5799
|
-
if (a.handRaised !== b.handRaised) return a.handRaised ? -1 : 1;
|
|
5800
|
-
if (a.cameraEnabled !== b.cameraEnabled) return a.cameraEnabled ? -1 : 1;
|
|
5801
|
-
if (a.joinedAt !== b.joinedAt) return a.joinedAt < b.joinedAt ? -1 : 1;
|
|
5802
|
-
return a.identity < b.identity ? -1 : 1;
|
|
5803
|
-
});
|
|
5804
|
-
}
|
|
5805
|
-
function computeStage(args) {
|
|
5806
|
-
const pageSize = Math.max(1, args.pageSize ?? DEFAULT_PAGE_SIZE);
|
|
5807
|
-
const ordered = orderParticipants(args.participants, args.activeSpeakers);
|
|
5808
|
-
const sharer = ordered.find((participant) => participant.screenSharing) ?? null;
|
|
5809
|
-
const pinnedParticipant = args.pinned === null ? null : ordered.find((participant) => participant.identity === args.pinned) ?? null;
|
|
5810
|
-
const spotlit = args.spotlight == null ? null : ordered.find((participant) => participant.identity === args.spotlight) ?? null;
|
|
5811
|
-
const feature = sharer !== null ? sharer : pinnedParticipant !== null && args.layout !== "grid" ? pinnedParticipant : spotlit !== null ? spotlit : args.layout === "grid" ? null : ordered[0] ?? null;
|
|
5812
|
-
const rest = feature === null ? ordered : ordered.filter((participant) => participant.identity !== feature.identity);
|
|
5813
|
-
const pageCount = Math.max(1, Math.ceil(rest.length / pageSize));
|
|
5814
|
-
const page = Math.min(Math.max(0, args.page ?? 0), pageCount - 1);
|
|
5815
|
-
const tiles = rest.slice(page * pageSize, page * pageSize + pageSize);
|
|
5816
|
-
return {
|
|
5817
|
-
feature,
|
|
5818
|
-
tiles,
|
|
5819
|
-
overflow: rest.length - tiles.length,
|
|
5820
|
-
page,
|
|
5821
|
-
pageCount,
|
|
5822
|
-
presenting: sharer !== null
|
|
5823
|
-
};
|
|
5824
|
-
}
|
|
5825
|
-
function gridColumns(count2) {
|
|
5826
|
-
if (count2 <= 1) return 1;
|
|
5827
|
-
if (count2 <= 4) return 2;
|
|
5828
|
-
if (count2 <= 9) return 3;
|
|
5829
|
-
if (count2 <= 16) return 4;
|
|
5830
|
-
return 5;
|
|
5831
|
-
}
|
|
5794
|
+
var import_react4 = require("@ai-matrx/realtime/react");
|
|
5832
5795
|
|
|
5833
5796
|
// src/core/record.ts
|
|
5834
5797
|
var import_format = require("@ai-matrx/kit/format");
|
|
@@ -5852,6 +5815,9 @@ function restrictionFor(part, error) {
|
|
|
5852
5815
|
};
|
|
5853
5816
|
}
|
|
5854
5817
|
async function loadMeetingRecord(repository, meetingId, meeting, reader = { userId: null }) {
|
|
5818
|
+
return assembleMeetingRecord(meeting, await loadMeetingRecordParts(repository, meetingId, reader));
|
|
5819
|
+
}
|
|
5820
|
+
async function loadMeetingRecordParts(repository, meetingId, reader = { userId: null }) {
|
|
5855
5821
|
const restrictions = [];
|
|
5856
5822
|
async function attempt(part, run, empty) {
|
|
5857
5823
|
if (reader.userId === null) {
|
|
@@ -5879,6 +5845,10 @@ async function loadMeetingRecord(repository, meetingId, meeting, reader = { user
|
|
|
5879
5845
|
[]
|
|
5880
5846
|
)
|
|
5881
5847
|
]);
|
|
5848
|
+
return { attendees, notes, transcript, recordings, restrictions };
|
|
5849
|
+
}
|
|
5850
|
+
function assembleMeetingRecord(meeting, parts) {
|
|
5851
|
+
const { attendees, notes, transcript, recordings, restrictions } = parts;
|
|
5882
5852
|
return {
|
|
5883
5853
|
meeting,
|
|
5884
5854
|
attendees,
|
|
@@ -6224,6 +6194,253 @@ async function setGuestRecordAccess(args) {
|
|
|
6224
6194
|
}
|
|
6225
6195
|
var GUEST_RECORD_NOT_SHARED = NOT_SHARED;
|
|
6226
6196
|
|
|
6197
|
+
// src/core/record-cache.ts
|
|
6198
|
+
var MEETING_RECORD_GRACE_MS = 6e4;
|
|
6199
|
+
var INITIAL = { loading: true, record: null, failure: null };
|
|
6200
|
+
function upsert2(rows, row, removedId, order) {
|
|
6201
|
+
const id = row?.id ?? removedId;
|
|
6202
|
+
if (id === void 0) return rows;
|
|
6203
|
+
const rest = rows.filter((existing) => existing.id !== id);
|
|
6204
|
+
return row === null ? rest : [...rest, row].sort(order);
|
|
6205
|
+
}
|
|
6206
|
+
var byId = (a, b) => a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
|
|
6207
|
+
var ascending = (a, b) => a === b ? 0 : a === null ? 1 : b === null ? -1 : a < b ? -1 : 1;
|
|
6208
|
+
function createMeetingRecordCache(options = {}) {
|
|
6209
|
+
const graceMs = options.graceMs ?? MEETING_RECORD_GRACE_MS;
|
|
6210
|
+
const entries = /* @__PURE__ */ new Map();
|
|
6211
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
6212
|
+
const notify = () => {
|
|
6213
|
+
for (const listener of listeners) listener();
|
|
6214
|
+
};
|
|
6215
|
+
const entryOf = (key) => {
|
|
6216
|
+
let entry = entries.get(key);
|
|
6217
|
+
if (!entry) {
|
|
6218
|
+
entry = {
|
|
6219
|
+
state: INITIAL,
|
|
6220
|
+
meeting: null,
|
|
6221
|
+
parts: null,
|
|
6222
|
+
fresh: false,
|
|
6223
|
+
seq: 0,
|
|
6224
|
+
inflight: null,
|
|
6225
|
+
holders: 0,
|
|
6226
|
+
close: null,
|
|
6227
|
+
owner: null,
|
|
6228
|
+
grace: null
|
|
6229
|
+
};
|
|
6230
|
+
entries.set(key, entry);
|
|
6231
|
+
}
|
|
6232
|
+
return entry;
|
|
6233
|
+
};
|
|
6234
|
+
const assemble = (entry) => {
|
|
6235
|
+
if (entry.meeting === null || entry.parts === null) return;
|
|
6236
|
+
entry.state = { loading: false, failure: null, record: assembleMeetingRecord(entry.meeting, entry.parts) };
|
|
6237
|
+
notify();
|
|
6238
|
+
};
|
|
6239
|
+
return {
|
|
6240
|
+
state: (key) => key === null ? INITIAL : entries.get(key)?.state ?? INITIAL,
|
|
6241
|
+
subscribe(listener) {
|
|
6242
|
+
listeners.add(listener);
|
|
6243
|
+
return () => {
|
|
6244
|
+
listeners.delete(listener);
|
|
6245
|
+
};
|
|
6246
|
+
},
|
|
6247
|
+
ensure(key, read, { force = false } = {}) {
|
|
6248
|
+
const entry = entryOf(key);
|
|
6249
|
+
if (!force) {
|
|
6250
|
+
if (entry.inflight !== null) return entry.inflight;
|
|
6251
|
+
if (entry.fresh) return Promise.resolve();
|
|
6252
|
+
}
|
|
6253
|
+
const seq = ++entry.seq;
|
|
6254
|
+
if (entry.state.failure !== null) {
|
|
6255
|
+
entry.state = { ...entry.state, loading: true, failure: null };
|
|
6256
|
+
notify();
|
|
6257
|
+
}
|
|
6258
|
+
const request = read().then(
|
|
6259
|
+
(answer) => {
|
|
6260
|
+
if (seq !== entry.seq) return;
|
|
6261
|
+
entry.fresh = true;
|
|
6262
|
+
if (answer.kind === "parts") {
|
|
6263
|
+
entry.meeting = answer.meeting;
|
|
6264
|
+
entry.parts = answer.parts;
|
|
6265
|
+
assemble(entry);
|
|
6266
|
+
} else {
|
|
6267
|
+
entry.meeting = answer.bundle.meeting;
|
|
6268
|
+
entry.parts = null;
|
|
6269
|
+
entry.state = { loading: false, failure: null, record: answer.bundle };
|
|
6270
|
+
notify();
|
|
6271
|
+
}
|
|
6272
|
+
},
|
|
6273
|
+
(thrown) => {
|
|
6274
|
+
if (seq !== entry.seq) return;
|
|
6275
|
+
entry.fresh = false;
|
|
6276
|
+
entry.state = {
|
|
6277
|
+
loading: false,
|
|
6278
|
+
record: entry.state.record,
|
|
6279
|
+
failure: {
|
|
6280
|
+
message: thrown?.message ?? String(thrown),
|
|
6281
|
+
remedy: thrown?.remedy ?? "The meeting record could not be read. Reload the page; nothing was changed."
|
|
6282
|
+
}
|
|
6283
|
+
};
|
|
6284
|
+
notify();
|
|
6285
|
+
}
|
|
6286
|
+
);
|
|
6287
|
+
const tracked = request.finally(() => {
|
|
6288
|
+
if (entry.inflight === tracked) entry.inflight = null;
|
|
6289
|
+
});
|
|
6290
|
+
entry.inflight = tracked;
|
|
6291
|
+
return tracked;
|
|
6292
|
+
},
|
|
6293
|
+
setMeeting(key, meeting) {
|
|
6294
|
+
const entry = entries.get(key);
|
|
6295
|
+
if (!entry || entry.meeting === meeting) return;
|
|
6296
|
+
if (entry.parts !== null) {
|
|
6297
|
+
entry.meeting = meeting;
|
|
6298
|
+
assemble(entry);
|
|
6299
|
+
} else if (entry.state.record !== null) {
|
|
6300
|
+
entry.meeting = meeting;
|
|
6301
|
+
entry.state = { ...entry.state, record: { ...entry.state.record, meeting } };
|
|
6302
|
+
notify();
|
|
6303
|
+
}
|
|
6304
|
+
},
|
|
6305
|
+
apply(key, change) {
|
|
6306
|
+
const entry = entries.get(key);
|
|
6307
|
+
const parts = entry?.parts;
|
|
6308
|
+
if (!entry || !parts) return;
|
|
6309
|
+
const refused = parts.restrictions.some((r) => r.part === change.part);
|
|
6310
|
+
if (refused) return;
|
|
6311
|
+
switch (change.part) {
|
|
6312
|
+
case "transcript":
|
|
6313
|
+
entry.parts = {
|
|
6314
|
+
...parts,
|
|
6315
|
+
transcript: upsert2(
|
|
6316
|
+
parts.transcript,
|
|
6317
|
+
change.row,
|
|
6318
|
+
change.removedId,
|
|
6319
|
+
(a, b) => ascending(a.startedAt, b.startedAt) || byId(a, b)
|
|
6320
|
+
)
|
|
6321
|
+
};
|
|
6322
|
+
break;
|
|
6323
|
+
case "notes":
|
|
6324
|
+
entry.parts = {
|
|
6325
|
+
...parts,
|
|
6326
|
+
notes: upsert2(
|
|
6327
|
+
parts.notes,
|
|
6328
|
+
change.row,
|
|
6329
|
+
change.removedId,
|
|
6330
|
+
(a, b) => ascending(a.createdAt, b.createdAt) || byId(a, b)
|
|
6331
|
+
)
|
|
6332
|
+
};
|
|
6333
|
+
break;
|
|
6334
|
+
case "attendance":
|
|
6335
|
+
entry.parts = {
|
|
6336
|
+
...parts,
|
|
6337
|
+
attendees: upsert2(
|
|
6338
|
+
parts.attendees,
|
|
6339
|
+
change.row,
|
|
6340
|
+
change.removedId,
|
|
6341
|
+
(a, b) => ascending(a.joinedAt, b.joinedAt) || byId(a, b)
|
|
6342
|
+
)
|
|
6343
|
+
};
|
|
6344
|
+
break;
|
|
6345
|
+
case "recording":
|
|
6346
|
+
entry.parts = {
|
|
6347
|
+
...parts,
|
|
6348
|
+
// Newest first, as the read orders them.
|
|
6349
|
+
recordings: upsert2(
|
|
6350
|
+
parts.recordings,
|
|
6351
|
+
change.row,
|
|
6352
|
+
change.removedId,
|
|
6353
|
+
(a, b) => ascending(b.startedAt, a.startedAt) || byId(a, b)
|
|
6354
|
+
)
|
|
6355
|
+
};
|
|
6356
|
+
break;
|
|
6357
|
+
}
|
|
6358
|
+
assemble(entry);
|
|
6359
|
+
},
|
|
6360
|
+
hold(key, open, owner = null) {
|
|
6361
|
+
const entry = entryOf(key);
|
|
6362
|
+
if (entry.grace !== null) {
|
|
6363
|
+
clearTimeout(entry.grace);
|
|
6364
|
+
entry.grace = null;
|
|
6365
|
+
}
|
|
6366
|
+
if (entry.close !== null && entry.owner !== owner) {
|
|
6367
|
+
entry.close();
|
|
6368
|
+
entry.close = null;
|
|
6369
|
+
}
|
|
6370
|
+
if (entry.close === null) {
|
|
6371
|
+
entry.close = open();
|
|
6372
|
+
entry.owner = owner;
|
|
6373
|
+
}
|
|
6374
|
+
entry.holders += 1;
|
|
6375
|
+
let released = false;
|
|
6376
|
+
return () => {
|
|
6377
|
+
if (released) return;
|
|
6378
|
+
released = true;
|
|
6379
|
+
entry.holders -= 1;
|
|
6380
|
+
if (entry.holders > 0) return;
|
|
6381
|
+
entry.grace = setTimeout(() => {
|
|
6382
|
+
entry.grace = null;
|
|
6383
|
+
if (entry.holders > 0) return;
|
|
6384
|
+
entry.close?.();
|
|
6385
|
+
entry.close = null;
|
|
6386
|
+
entry.fresh = false;
|
|
6387
|
+
}, graceMs);
|
|
6388
|
+
};
|
|
6389
|
+
},
|
|
6390
|
+
reset() {
|
|
6391
|
+
for (const entry of entries.values()) {
|
|
6392
|
+
if (entry.grace !== null) clearTimeout(entry.grace);
|
|
6393
|
+
entry.close?.();
|
|
6394
|
+
}
|
|
6395
|
+
entries.clear();
|
|
6396
|
+
notify();
|
|
6397
|
+
}
|
|
6398
|
+
};
|
|
6399
|
+
}
|
|
6400
|
+
|
|
6401
|
+
// src/core/layout.ts
|
|
6402
|
+
var DEFAULT_PAGE_SIZE = 12;
|
|
6403
|
+
function orderParticipants(participants, activeSpeakers) {
|
|
6404
|
+
const speakerRank = /* @__PURE__ */ new Map();
|
|
6405
|
+
activeSpeakers.forEach((identity, index) => speakerRank.set(identity, index));
|
|
6406
|
+
return [...participants].sort((a, b) => {
|
|
6407
|
+
const speakerA = speakerRank.get(a.identity) ?? Number.MAX_SAFE_INTEGER;
|
|
6408
|
+
const speakerB = speakerRank.get(b.identity) ?? Number.MAX_SAFE_INTEGER;
|
|
6409
|
+
if (speakerA !== speakerB) return speakerA - speakerB;
|
|
6410
|
+
if (a.handRaised !== b.handRaised) return a.handRaised ? -1 : 1;
|
|
6411
|
+
if (a.cameraEnabled !== b.cameraEnabled) return a.cameraEnabled ? -1 : 1;
|
|
6412
|
+
if (a.joinedAt !== b.joinedAt) return a.joinedAt < b.joinedAt ? -1 : 1;
|
|
6413
|
+
return a.identity < b.identity ? -1 : 1;
|
|
6414
|
+
});
|
|
6415
|
+
}
|
|
6416
|
+
function computeStage(args) {
|
|
6417
|
+
const pageSize = Math.max(1, args.pageSize ?? DEFAULT_PAGE_SIZE);
|
|
6418
|
+
const ordered = orderParticipants(args.participants, args.activeSpeakers);
|
|
6419
|
+
const sharer = ordered.find((participant) => participant.screenSharing) ?? null;
|
|
6420
|
+
const pinnedParticipant = args.pinned === null ? null : ordered.find((participant) => participant.identity === args.pinned) ?? null;
|
|
6421
|
+
const spotlit = args.spotlight == null ? null : ordered.find((participant) => participant.identity === args.spotlight) ?? null;
|
|
6422
|
+
const feature = sharer !== null ? sharer : pinnedParticipant !== null && args.layout !== "grid" ? pinnedParticipant : spotlit !== null ? spotlit : args.layout === "grid" ? null : ordered[0] ?? null;
|
|
6423
|
+
const rest = feature === null ? ordered : ordered.filter((participant) => participant.identity !== feature.identity);
|
|
6424
|
+
const pageCount = Math.max(1, Math.ceil(rest.length / pageSize));
|
|
6425
|
+
const page = Math.min(Math.max(0, args.page ?? 0), pageCount - 1);
|
|
6426
|
+
const tiles = rest.slice(page * pageSize, page * pageSize + pageSize);
|
|
6427
|
+
return {
|
|
6428
|
+
feature,
|
|
6429
|
+
tiles,
|
|
6430
|
+
overflow: rest.length - tiles.length,
|
|
6431
|
+
page,
|
|
6432
|
+
pageCount,
|
|
6433
|
+
presenting: sharer !== null
|
|
6434
|
+
};
|
|
6435
|
+
}
|
|
6436
|
+
function gridColumns(count2) {
|
|
6437
|
+
if (count2 <= 1) return 1;
|
|
6438
|
+
if (count2 <= 4) return 2;
|
|
6439
|
+
if (count2 <= 9) return 3;
|
|
6440
|
+
if (count2 <= 16) return 4;
|
|
6441
|
+
return 5;
|
|
6442
|
+
}
|
|
6443
|
+
|
|
6227
6444
|
// src/react/hooks.ts
|
|
6228
6445
|
var EMPTY_NAMES = {};
|
|
6229
6446
|
var NO_RUNTIME_REMEDY = "Render this inside a <MeetProvider> that has a Supabase client, an organization id and an identity (userId or guestName). The provider stays inert until all three are real, and while it is inert this package's components render nothing rather than a dead control.";
|
|
@@ -6809,16 +7026,22 @@ function useMeeting() {
|
|
|
6809
7026
|
function useMeetingId() {
|
|
6810
7027
|
return useMeetSnapshot()?.meeting?.id ?? null;
|
|
6811
7028
|
}
|
|
7029
|
+
var RECORD_CACHE_KEY = /* @__PURE__ */ Symbol.for("@ai-matrx/meet/meeting-record-cache");
|
|
7030
|
+
function meetingRecordCache() {
|
|
7031
|
+
const holder = globalThis;
|
|
7032
|
+
let cache = holder[RECORD_CACHE_KEY];
|
|
7033
|
+
if (cache === void 0) {
|
|
7034
|
+
cache = createMeetingRecordCache();
|
|
7035
|
+
holder[RECORD_CACHE_KEY] = cache;
|
|
7036
|
+
}
|
|
7037
|
+
return cache;
|
|
7038
|
+
}
|
|
7039
|
+
var rowIdOf = (row) => typeof row["id"] === "string" ? row["id"] : void 0;
|
|
6812
7040
|
function useMeetingRecord(meeting) {
|
|
6813
7041
|
const host = useMeetHost();
|
|
6814
7042
|
const repository = host?.repository ?? null;
|
|
6815
7043
|
const ai = host?.ai ?? null;
|
|
6816
7044
|
const readerId = host?.identity.userId ?? null;
|
|
6817
|
-
const [recordReaderId, setRecordReaderId] = (0, import_react3.useState)(readerId);
|
|
6818
|
-
const [record, setRecord] = (0, import_react3.useState)(null);
|
|
6819
|
-
const [loading, setLoading] = (0, import_react3.useState)(true);
|
|
6820
|
-
const [failure, setFailure] = (0, import_react3.useState)(null);
|
|
6821
|
-
const [nonce, setNonce] = (0, import_react3.useState)(0);
|
|
6822
7045
|
const [asking, setAsking] = (0, import_react3.useState)(false);
|
|
6823
7046
|
const [answer, setAnswer] = (0, import_react3.useState)(null);
|
|
6824
7047
|
const [coverage, setCoverage] = (0, import_react3.useState)(null);
|
|
@@ -6827,57 +7050,107 @@ function useMeetingRecord(meeting) {
|
|
|
6827
7050
|
const api = host?.api ?? null;
|
|
6828
7051
|
const tokens = host?.tokens ?? null;
|
|
6829
7052
|
const roomName = meeting?.roomName ?? null;
|
|
6830
|
-
(0,
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
|
|
6843
|
-
|
|
6844
|
-
|
|
6845
|
-
// answers members and invitees; a person from another organization
|
|
6846
|
-
// the host admitted — or a guest who later made an account — reads
|
|
6847
|
-
// the guest share through the server, with their session as the pass.
|
|
6848
|
-
api !== null && direct.restrictions.some((part) => part.part === "notes") ? loadGuestMeetingRecord({
|
|
7053
|
+
const manager = (0, import_react4.useRealtimeManager)();
|
|
7054
|
+
const cache = meetingRecordCache();
|
|
7055
|
+
const key = repository !== null && meetingId !== null ? `${readerId ?? `guest:${roomName ?? "-"}`}|${meetingId}` : null;
|
|
7056
|
+
const state = (0, import_react3.useSyncExternalStore)(
|
|
7057
|
+
cache.subscribe,
|
|
7058
|
+
() => cache.state(key),
|
|
7059
|
+
() => cache.state(null)
|
|
7060
|
+
);
|
|
7061
|
+
const readRef = (0, import_react3.useRef)(() => Promise.reject(new Error("not ready")));
|
|
7062
|
+
readRef.current = async () => {
|
|
7063
|
+
if (repository === null || meeting === null || meetingId === null) throw new Error("No meeting to read.");
|
|
7064
|
+
if (readerId === null && api !== null && tokens !== null && roomName !== null) {
|
|
7065
|
+
return {
|
|
7066
|
+
kind: "bundle",
|
|
7067
|
+
bundle: await loadGuestMeetingRecord({
|
|
6849
7068
|
api,
|
|
6850
7069
|
repository,
|
|
6851
7070
|
meetingId,
|
|
6852
7071
|
meeting,
|
|
6853
|
-
roomToken:
|
|
6854
|
-
|
|
6855
|
-
|
|
6856
|
-
|
|
6857
|
-
|
|
6858
|
-
|
|
6859
|
-
|
|
6860
|
-
|
|
6861
|
-
|
|
6862
|
-
|
|
6863
|
-
|
|
6864
|
-
|
|
6865
|
-
|
|
6866
|
-
if (!live) return;
|
|
6867
|
-
setFailure({
|
|
6868
|
-
message: thrown.message,
|
|
6869
|
-
remedy: thrown.remedy ?? "The meeting record could not be read. Reload the page; nothing was changed."
|
|
7072
|
+
roomToken: tokens.remembered(roomName)
|
|
7073
|
+
})
|
|
7074
|
+
};
|
|
7075
|
+
}
|
|
7076
|
+
const parts = await loadMeetingRecordParts(repository, meetingId, { userId: readerId });
|
|
7077
|
+
if (api !== null && parts.restrictions.some((part) => part.part === "notes")) {
|
|
7078
|
+
const viaServer = await loadGuestMeetingRecord({
|
|
7079
|
+
api,
|
|
7080
|
+
repository,
|
|
7081
|
+
meetingId,
|
|
7082
|
+
meeting,
|
|
7083
|
+
roomToken: null,
|
|
7084
|
+
session: true
|
|
6870
7085
|
});
|
|
6871
|
-
|
|
7086
|
+
if (viaServer.restrictions.length < parts.restrictions.length) return { kind: "bundle", bundle: viaServer };
|
|
7087
|
+
}
|
|
7088
|
+
return { kind: "parts", meeting, parts };
|
|
7089
|
+
};
|
|
7090
|
+
(0, import_react3.useEffect)(() => {
|
|
7091
|
+
if (key === null) return;
|
|
7092
|
+
void cache.ensure(key, () => readRef.current());
|
|
7093
|
+
}, [cache, key]);
|
|
7094
|
+
(0, import_react3.useEffect)(() => {
|
|
7095
|
+
if (key !== null && meeting !== null) cache.setMeeting(key, meeting);
|
|
7096
|
+
}, [cache, key, meeting]);
|
|
7097
|
+
(0, import_react3.useEffect)(() => {
|
|
7098
|
+
if (key === null || manager === null || repository === null || meetingId === null || readerId === null) {
|
|
7099
|
+
return void 0;
|
|
7100
|
+
}
|
|
7101
|
+
const repo = repository;
|
|
7102
|
+
const binding = (table, apply) => ({
|
|
7103
|
+
event: "*",
|
|
7104
|
+
schema: repo.schema,
|
|
7105
|
+
table,
|
|
7106
|
+
filter: `meeting_id=eq.${meetingId}`,
|
|
7107
|
+
rowId: rowIdOf,
|
|
7108
|
+
onChange: ({ row, payload }) => {
|
|
7109
|
+
if (row === null) return;
|
|
7110
|
+
const gone = payload.eventType === "DELETE";
|
|
7111
|
+
apply(gone ? null : row, gone ? rowIdOf(row) : void 0);
|
|
7112
|
+
}
|
|
6872
7113
|
});
|
|
6873
|
-
return (
|
|
6874
|
-
|
|
6875
|
-
|
|
6876
|
-
|
|
7114
|
+
return cache.hold(
|
|
7115
|
+
key,
|
|
7116
|
+
() => {
|
|
7117
|
+
const handle = manager.open({
|
|
7118
|
+
topic: meetingTopic(meetingId),
|
|
7119
|
+
postgresChanges: [
|
|
7120
|
+
binding(
|
|
7121
|
+
repo.tables.notes,
|
|
7122
|
+
(row, removedId) => cache.apply(key, { part: "notes", row: row && repo.projectNote(row), removedId })
|
|
7123
|
+
),
|
|
7124
|
+
binding(
|
|
7125
|
+
repo.tables.transcripts,
|
|
7126
|
+
(row, removedId) => cache.apply(key, { part: "transcript", row: row && repo.projectSegment(row), removedId })
|
|
7127
|
+
),
|
|
7128
|
+
binding(
|
|
7129
|
+
repo.tables.participants,
|
|
7130
|
+
(row, removedId) => cache.apply(key, { part: "attendance", row: row && repo.projectAttendee(row), removedId })
|
|
7131
|
+
),
|
|
7132
|
+
binding(
|
|
7133
|
+
repo.tables.recordings,
|
|
7134
|
+
(row, removedId) => (
|
|
7135
|
+
// An archived recording is off the record (the read filters it the same way).
|
|
7136
|
+
row !== null && row["deleted_at"] != null ? cache.apply(key, { part: "recording", row: null, removedId: rowIdOf(row) }) : cache.apply(key, { part: "recording", row: row && repo.projectRecording(row), removedId })
|
|
7137
|
+
)
|
|
7138
|
+
)
|
|
7139
|
+
],
|
|
7140
|
+
// Realtime has no replay: a socket that blipped reads the record again.
|
|
7141
|
+
onBackfill: async () => {
|
|
7142
|
+
await cache.ensure(key, () => readRef.current(), { force: true });
|
|
7143
|
+
}
|
|
7144
|
+
});
|
|
7145
|
+
return () => handle.close();
|
|
7146
|
+
},
|
|
7147
|
+
manager
|
|
7148
|
+
);
|
|
7149
|
+
}, [cache, key, manager, repository, meetingId, readerId]);
|
|
6877
7150
|
return {
|
|
6878
|
-
loading: loading && failure === null,
|
|
6879
|
-
record:
|
|
6880
|
-
failure,
|
|
7151
|
+
loading: state.loading && state.failure === null,
|
|
7152
|
+
record: state.record,
|
|
7153
|
+
failure: state.failure,
|
|
6881
7154
|
asking,
|
|
6882
7155
|
answer,
|
|
6883
7156
|
coverage,
|
|
@@ -6908,7 +7181,9 @@ function useMeetingRecord(meeting) {
|
|
|
6908
7181
|
},
|
|
6909
7182
|
[ai, meetingId]
|
|
6910
7183
|
),
|
|
6911
|
-
reload: (0, import_react3.useCallback)(() =>
|
|
7184
|
+
reload: (0, import_react3.useCallback)(() => {
|
|
7185
|
+
if (key !== null) void cache.ensure(key, () => readRef.current(), { force: true });
|
|
7186
|
+
}, [cache, key])
|
|
6912
7187
|
};
|
|
6913
7188
|
}
|
|
6914
7189
|
function useMeetings(limit = 25, organizationFilter = null) {
|
|
@@ -6995,11 +7270,12 @@ function useGuestRecordAccess(meeting) {
|
|
|
6995
7270
|
}
|
|
6996
7271
|
|
|
6997
7272
|
// src/react/components.tsx
|
|
6998
|
-
var
|
|
7273
|
+
var import_react6 = require("react");
|
|
6999
7274
|
var import_design_system = require("@ai-matrx/design-system");
|
|
7000
7275
|
var import_format4 = require("@ai-matrx/kit/format");
|
|
7001
7276
|
|
|
7002
7277
|
// src/core/after.ts
|
|
7278
|
+
var import_delimited = require("@ai-matrx/kit/delimited");
|
|
7003
7279
|
var import_format2 = require("@ai-matrx/kit/format");
|
|
7004
7280
|
function kindOf(person) {
|
|
7005
7281
|
if (person.isAgent) return "assistant";
|
|
@@ -7138,11 +7414,6 @@ function attendanceTotals(rows) {
|
|
|
7138
7414
|
averageMs: timed.length === 0 ? null : Math.round(timed.reduce((sum, row) => sum + (row.durationMs ?? 0), 0) / timed.length)
|
|
7139
7415
|
};
|
|
7140
7416
|
}
|
|
7141
|
-
function csvCell(value) {
|
|
7142
|
-
if (value === null) return "";
|
|
7143
|
-
const text3 = String(value);
|
|
7144
|
-
return /[",\n\r]/.test(text3) ? `"${text3.replace(/"/g, '""')}"` : text3;
|
|
7145
|
-
}
|
|
7146
7417
|
var ATTENDANCE_CSV_HEADER = [
|
|
7147
7418
|
"Meeting",
|
|
7148
7419
|
"Meeting started",
|
|
@@ -7154,11 +7425,11 @@ var ATTENDANCE_CSV_HEADER = [
|
|
|
7154
7425
|
"Admission"
|
|
7155
7426
|
];
|
|
7156
7427
|
function attendanceCsv(reports) {
|
|
7157
|
-
|
|
7158
|
-
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
[
|
|
7428
|
+
return (0, import_delimited.toDelimited)(
|
|
7429
|
+
[
|
|
7430
|
+
ATTENDANCE_CSV_HEADER,
|
|
7431
|
+
...reports.flatMap(
|
|
7432
|
+
({ meeting, rows }) => rows.map((row) => [
|
|
7162
7433
|
meeting.title,
|
|
7163
7434
|
meeting.startedAt ?? meeting.scheduledFor,
|
|
7164
7435
|
row.name,
|
|
@@ -7167,12 +7438,11 @@ function attendanceCsv(reports) {
|
|
|
7167
7438
|
row.leftAt,
|
|
7168
7439
|
row.durationMs === null ? null : Math.round(row.durationMs / 6e3) / 10,
|
|
7169
7440
|
row.admission
|
|
7170
|
-
]
|
|
7171
|
-
)
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
`;
|
|
7441
|
+
])
|
|
7442
|
+
)
|
|
7443
|
+
],
|
|
7444
|
+
{ lineEnding: "\r\n", trailingNewline: true }
|
|
7445
|
+
);
|
|
7176
7446
|
}
|
|
7177
7447
|
function recordingOffsetMs(at, recording) {
|
|
7178
7448
|
if (recording === null || recording.state !== "available") return null;
|
|
@@ -7440,7 +7710,7 @@ function countLabel(count2, singular, plural = `${singular}s`) {
|
|
|
7440
7710
|
}
|
|
7441
7711
|
|
|
7442
7712
|
// src/react/collab.tsx
|
|
7443
|
-
var
|
|
7713
|
+
var import_react5 = require("react");
|
|
7444
7714
|
var import_format3 = require("@ai-matrx/kit/format");
|
|
7445
7715
|
|
|
7446
7716
|
// src/react/icons.tsx
|
|
@@ -7717,8 +7987,8 @@ function useCollab() {
|
|
|
7717
7987
|
};
|
|
7718
7988
|
}
|
|
7719
7989
|
function useNotice() {
|
|
7720
|
-
const [notice, setNotice] = (0,
|
|
7721
|
-
(0,
|
|
7990
|
+
const [notice, setNotice] = (0, import_react5.useState)(null);
|
|
7991
|
+
(0, import_react5.useEffect)(() => {
|
|
7722
7992
|
if (notice === null) return void 0;
|
|
7723
7993
|
const timer = setTimeout(() => setNotice(null), notice.failed ? 7e3 : 3e3);
|
|
7724
7994
|
return () => clearTimeout(timer);
|
|
@@ -7764,7 +8034,7 @@ function ActivitiesControl({
|
|
|
7764
8034
|
active,
|
|
7765
8035
|
onOpen
|
|
7766
8036
|
}) {
|
|
7767
|
-
const [open, setOpen] = (0,
|
|
8037
|
+
const [open, setOpen] = (0, import_react5.useState)(false);
|
|
7768
8038
|
const available = useAvailableActivities();
|
|
7769
8039
|
const attention = useActivityAttention();
|
|
7770
8040
|
if (available.length === 0) return null;
|
|
@@ -7792,11 +8062,11 @@ function ActivitiesControl({
|
|
|
7792
8062
|
}
|
|
7793
8063
|
function PollComposer({ maxOptions, onDone }) {
|
|
7794
8064
|
const { act } = useCollab();
|
|
7795
|
-
const [question, setQuestion] = (0,
|
|
7796
|
-
const [options, setOptions] = (0,
|
|
7797
|
-
const [multiple, setMultiple] = (0,
|
|
7798
|
-
const [anonymous, setAnonymous] = (0,
|
|
7799
|
-
const [busy, setBusy] = (0,
|
|
8065
|
+
const [question, setQuestion] = (0, import_react5.useState)("");
|
|
8066
|
+
const [options, setOptions] = (0, import_react5.useState)(["", ""]);
|
|
8067
|
+
const [multiple, setMultiple] = (0, import_react5.useState)(false);
|
|
8068
|
+
const [anonymous, setAnonymous] = (0, import_react5.useState)(false);
|
|
8069
|
+
const [busy, setBusy] = (0, import_react5.useState)(false);
|
|
7800
8070
|
const [notice, show] = useNotice();
|
|
7801
8071
|
const filled = options.map((o) => o.trim()).filter(Boolean);
|
|
7802
8072
|
const ready = question.trim().length > 0 && filled.length >= 2;
|
|
@@ -7877,9 +8147,9 @@ function PollComposer({ maxOptions, onDone }) {
|
|
|
7877
8147
|
}
|
|
7878
8148
|
function PollCard({ poll }) {
|
|
7879
8149
|
const { act, isHost } = useCollab();
|
|
7880
|
-
const [picked, setPicked] = (0,
|
|
8150
|
+
const [picked, setPicked] = (0, import_react5.useState)(poll.myVote.slice());
|
|
7881
8151
|
const [notice, show] = useNotice();
|
|
7882
|
-
(0,
|
|
8152
|
+
(0, import_react5.useEffect)(() => setPicked(poll.myVote.slice()), [poll.myVote]);
|
|
7883
8153
|
const counts = poll.options.some((o) => o.votes !== void 0);
|
|
7884
8154
|
const total = poll.options.reduce((sum, o) => sum + (o.votes ?? 0), 0);
|
|
7885
8155
|
const canVote = poll.state === "live";
|
|
@@ -7948,7 +8218,7 @@ function PollCard({ poll }) {
|
|
|
7948
8218
|
}
|
|
7949
8219
|
function PollsPanel({ onClose }) {
|
|
7950
8220
|
const { collab, isHost } = useCollab();
|
|
7951
|
-
const [composing, setComposing] = (0,
|
|
8221
|
+
const [composing, setComposing] = (0, import_react5.useState)(false);
|
|
7952
8222
|
const polls = collab?.polls ?? [];
|
|
7953
8223
|
const maxOptions = collab?.settings?.pollMaxOptions ?? 10;
|
|
7954
8224
|
const ordered = [...polls].reverse();
|
|
@@ -7962,8 +8232,8 @@ function PollsPanel({ onClose }) {
|
|
|
7962
8232
|
}
|
|
7963
8233
|
function QuestionCard({ question }) {
|
|
7964
8234
|
const { act, isHost } = useCollab();
|
|
7965
|
-
const [answering, setAnswering] = (0,
|
|
7966
|
-
const [reply, setReply] = (0,
|
|
8235
|
+
const [answering, setAnswering] = (0, import_react5.useState)(false);
|
|
8236
|
+
const [reply, setReply] = (0, import_react5.useState)("");
|
|
7967
8237
|
const [notice, show] = useNotice();
|
|
7968
8238
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { className: `mx-meet__collab-card mx-meet__question mx-meet__question--${question.state}`, children: [
|
|
7969
8239
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "mx-meet__question-row", children: [
|
|
@@ -8041,9 +8311,9 @@ function QuestionCard({ question }) {
|
|
|
8041
8311
|
}
|
|
8042
8312
|
function QaPanel({ onClose }) {
|
|
8043
8313
|
const { collab, act } = useCollab();
|
|
8044
|
-
const [draft, setDraft] = (0,
|
|
8045
|
-
const [anonymous, setAnonymous] = (0,
|
|
8046
|
-
const [order, setOrder] = (0,
|
|
8314
|
+
const [draft, setDraft] = (0, import_react5.useState)("");
|
|
8315
|
+
const [anonymous, setAnonymous] = (0, import_react5.useState)(false);
|
|
8316
|
+
const [order, setOrder] = (0, import_react5.useState)("popular");
|
|
8047
8317
|
const [notice, show] = useNotice();
|
|
8048
8318
|
const allowAnonymous = collab?.settings?.qaAnonymousAllowed === true;
|
|
8049
8319
|
const questions = [...collab?.questions ?? []];
|
|
@@ -8132,12 +8402,12 @@ function StrokeView({ stroke, onPick }) {
|
|
|
8132
8402
|
}
|
|
8133
8403
|
function WhiteboardPanel({ onClose }) {
|
|
8134
8404
|
const { collab, act, isHost, localIdentity } = useCollab();
|
|
8135
|
-
const [tool, setTool] = (0,
|
|
8136
|
-
const [color, setColor] = (0,
|
|
8137
|
-
const [drawing, setDrawing] = (0,
|
|
8138
|
-
const [pending, setPending] = (0,
|
|
8405
|
+
const [tool, setTool] = (0, import_react5.useState)("pen");
|
|
8406
|
+
const [color, setColor] = (0, import_react5.useState)(INK[0]);
|
|
8407
|
+
const [drawing, setDrawing] = (0, import_react5.useState)(null);
|
|
8408
|
+
const [pending, setPending] = (0, import_react5.useState)([]);
|
|
8139
8409
|
const [notice, show] = useNotice();
|
|
8140
|
-
const svgRef = (0,
|
|
8410
|
+
const svgRef = (0, import_react5.useRef)(null);
|
|
8141
8411
|
const strokes = collab?.strokes ?? [];
|
|
8142
8412
|
const mine = strokes.filter((s) => s.by === localIdentity);
|
|
8143
8413
|
const point = (event) => {
|
|
@@ -8278,8 +8548,8 @@ function clock(ms2) {
|
|
|
8278
8548
|
}
|
|
8279
8549
|
var BREAKOUT_EXPIRE_RETRY_MS = 5e3;
|
|
8280
8550
|
function useNow(active) {
|
|
8281
|
-
const [now, setNow] = (0,
|
|
8282
|
-
(0,
|
|
8551
|
+
const [now, setNow] = (0, import_react5.useState)(() => Date.now());
|
|
8552
|
+
(0, import_react5.useEffect)(() => {
|
|
8283
8553
|
if (!active) return void 0;
|
|
8284
8554
|
const timer = setInterval(() => setNow(Date.now()), 1e3);
|
|
8285
8555
|
return () => clearInterval(timer);
|
|
@@ -8293,11 +8563,11 @@ function BreakoutSetup() {
|
|
|
8293
8563
|
const people = (snapshot?.participants ?? []).filter(
|
|
8294
8564
|
(p) => !p.isAgent && p.role !== "host" && p.role !== "cohost"
|
|
8295
8565
|
);
|
|
8296
|
-
const [count2, setCount] = (0,
|
|
8297
|
-
const [mode, setMode] = (0,
|
|
8298
|
-
const [minutes, setMinutes] = (0,
|
|
8299
|
-
const [manual, setManual] = (0,
|
|
8300
|
-
const [busy, setBusy] = (0,
|
|
8566
|
+
const [count2, setCount] = (0, import_react5.useState)(Math.min(Math.max(2, Math.ceil(people.length / 4)), settings?.breakoutMaxRooms ?? 20));
|
|
8567
|
+
const [mode, setMode] = (0, import_react5.useState)("auto");
|
|
8568
|
+
const [minutes, setMinutes] = (0, import_react5.useState)(settings?.breakoutDefaultMinutes ?? 15);
|
|
8569
|
+
const [manual, setManual] = (0, import_react5.useState)({});
|
|
8570
|
+
const [busy, setBusy] = (0, import_react5.useState)(false);
|
|
8301
8571
|
const [notice, show] = useNotice();
|
|
8302
8572
|
const max = settings?.breakoutMaxRooms ?? 20;
|
|
8303
8573
|
const rooms = Math.min(Math.max(1, count2), max);
|
|
@@ -8413,7 +8683,7 @@ function BreakoutRun({ plan }) {
|
|
|
8413
8683
|
const snapshot = useMeetSnapshot();
|
|
8414
8684
|
const now = useNow(plan.endsAt !== null);
|
|
8415
8685
|
const remaining = breakoutRemainingMs(plan, now);
|
|
8416
|
-
const [broadcast, setBroadcast] = (0,
|
|
8686
|
+
const [broadcast, setBroadcast] = (0, import_react5.useState)("");
|
|
8417
8687
|
const [notice, show] = useNotice();
|
|
8418
8688
|
const nameOf = (identity) => displayNameFor(snapshot?.names ?? {}, identity, snapshot?.participants.find((p) => p.identity === identity)?.displayName);
|
|
8419
8689
|
const mine = assignedRoom(plan, localIdentity);
|
|
@@ -8523,11 +8793,11 @@ function BreakoutBanner() {
|
|
|
8523
8793
|
const now = useNow(open?.endsAt != null);
|
|
8524
8794
|
const remaining = breakoutRemainingMs(open, now);
|
|
8525
8795
|
const assigned = assignedRoom(open, localIdentity);
|
|
8526
|
-
const [dismissedBroadcast, setDismissedBroadcast] = (0,
|
|
8527
|
-
const [failure, setFailure] = (0,
|
|
8528
|
-
const expireAsked = (0,
|
|
8796
|
+
const [dismissedBroadcast, setDismissedBroadcast] = (0, import_react5.useState)(null);
|
|
8797
|
+
const [failure, setFailure] = (0, import_react5.useState)(null);
|
|
8798
|
+
const expireAsked = (0, import_react5.useRef)(null);
|
|
8529
8799
|
const moveAt = collab?.moveRequest?.at ?? null;
|
|
8530
|
-
(0,
|
|
8800
|
+
(0, import_react5.useEffect)(() => {
|
|
8531
8801
|
const request = host?.store.snapshot().collab.moveRequest ?? null;
|
|
8532
8802
|
if (request === null || host === null) return;
|
|
8533
8803
|
host.store.patch({ collab: { ...host.store.snapshot().collab, moveRequest: null } });
|
|
@@ -8535,7 +8805,7 @@ function BreakoutBanner() {
|
|
|
8535
8805
|
if ((here ?? null) === request.roomId) return;
|
|
8536
8806
|
void moveTo(request.roomId).then((result) => setFailure(result.ok ? null : result.message));
|
|
8537
8807
|
}, [moveAt, host, moveTo]);
|
|
8538
|
-
(0,
|
|
8808
|
+
(0, import_react5.useEffect)(() => {
|
|
8539
8809
|
if (open === null || remaining === null || remaining > 0) return;
|
|
8540
8810
|
const asked = expireAsked.current;
|
|
8541
8811
|
if (asked !== null && asked.id === open.id && now - asked.at < BREAKOUT_EXPIRE_RETRY_MS) return;
|
|
@@ -8585,13 +8855,13 @@ function useCaptionTranslation(lines) {
|
|
|
8585
8855
|
const snapshot = useMeetSnapshot();
|
|
8586
8856
|
const collab = snapshot?.collab ?? null;
|
|
8587
8857
|
const language = collab?.captionLanguage ?? null;
|
|
8588
|
-
const asked = (0,
|
|
8858
|
+
const asked = (0, import_react5.useRef)(/* @__PURE__ */ new Set());
|
|
8589
8859
|
const translations = collab?.captionTranslations ?? {};
|
|
8590
8860
|
const missing = lines.filter((line) => line.final && translations[line.id] === void 0).map(({ id, text: text3 }) => ({ id, text: text3 }));
|
|
8591
8861
|
const key = `${language ?? ""}|${missing.map((l) => l.id).join(",")}`;
|
|
8592
|
-
const pending = (0,
|
|
8862
|
+
const pending = (0, import_react5.useRef)(missing);
|
|
8593
8863
|
pending.current = missing;
|
|
8594
|
-
(0,
|
|
8864
|
+
(0, import_react5.useEffect)(() => {
|
|
8595
8865
|
if (host === null || language === null) return;
|
|
8596
8866
|
const batch = pending.current.filter((line) => !asked.current.has(`${language}:${line.id}`)).slice(-20);
|
|
8597
8867
|
if (batch.length === 0) return;
|
|
@@ -8646,9 +8916,9 @@ function CaptionLanguageSettings() {
|
|
|
8646
8916
|
function useCollabPanelRequest(onRequest) {
|
|
8647
8917
|
const host = useMeetHost();
|
|
8648
8918
|
const at = useMeetSnapshot()?.collab.panelRequest?.at ?? null;
|
|
8649
|
-
const callback = (0,
|
|
8919
|
+
const callback = (0, import_react5.useRef)(onRequest);
|
|
8650
8920
|
callback.current = onRequest;
|
|
8651
|
-
(0,
|
|
8921
|
+
(0, import_react5.useEffect)(() => {
|
|
8652
8922
|
const request = host?.store.snapshot().collab.panelRequest ?? null;
|
|
8653
8923
|
if (request === null || host === null) return;
|
|
8654
8924
|
host.store.patch({ collab: { ...host.store.snapshot().collab, panelRequest: null } });
|
|
@@ -8757,7 +9027,7 @@ function ParticipantTile({
|
|
|
8757
9027
|
const host = useMeetHost();
|
|
8758
9028
|
const snapshot = useMeetSnapshot();
|
|
8759
9029
|
const queue = useHandQueue();
|
|
8760
|
-
const [menu, setMenu] = (0,
|
|
9030
|
+
const [menu, setMenu] = (0, import_react6.useState)(false);
|
|
8761
9031
|
const videoRef = useTrack(
|
|
8762
9032
|
participant.identity,
|
|
8763
9033
|
participant.screenSharing ? "screen" : "camera"
|
|
@@ -8871,17 +9141,17 @@ var MEET_REACTIONS = ["\u{1F496}", "\u{1F44D}", "\u{1F389}", "\u{1F44F}", "\u{1F
|
|
|
8871
9141
|
function ControlBar({ onLeave }) {
|
|
8872
9142
|
const room = useRoom();
|
|
8873
9143
|
const recording = useRecording();
|
|
8874
|
-
const [panel, setPanel] = (0,
|
|
8875
|
-
const [chatTo, setChatTo] = (0,
|
|
8876
|
-
const [popover, setPopover] = (0,
|
|
8877
|
-
const [shortcuts, setShortcuts] = (0,
|
|
9144
|
+
const [panel, setPanel] = (0, import_react6.useState)("none");
|
|
9145
|
+
const [chatTo, setChatTo] = (0, import_react6.useState)(null);
|
|
9146
|
+
const [popover, setPopover] = (0, import_react6.useState)("none");
|
|
9147
|
+
const [shortcuts, setShortcuts] = (0, import_react6.useState)(false);
|
|
8878
9148
|
const snapshot = useMeetSnapshot();
|
|
8879
9149
|
const lobby = useLobby();
|
|
8880
9150
|
const controls = useHostControls();
|
|
8881
9151
|
const queue = useHandQueue();
|
|
8882
9152
|
const micUnavailable = useLocalMedia().microphone.unavailable;
|
|
8883
9153
|
const unread = useUnreadChat(panel === "chat");
|
|
8884
|
-
const [whiteboard, setWhiteboard] = (0,
|
|
9154
|
+
const [whiteboard, setWhiteboard] = (0, import_react6.useState)(false);
|
|
8885
9155
|
const toggle = (next) => setPanel(panel === next ? "none" : next);
|
|
8886
9156
|
const openActivity = (activity) => {
|
|
8887
9157
|
if (activity === "whiteboard") setWhiteboard(true);
|
|
@@ -8892,7 +9162,7 @@ function ControlBar({ onLeave }) {
|
|
|
8892
9162
|
});
|
|
8893
9163
|
const privateChatAt = snapshot?.privateChatRequest?.at ?? null;
|
|
8894
9164
|
const meetStore = useMeetHost()?.store ?? null;
|
|
8895
|
-
(0,
|
|
9165
|
+
(0, import_react6.useEffect)(() => {
|
|
8896
9166
|
const request = meetStore?.snapshot().privateChatRequest ?? null;
|
|
8897
9167
|
if (request === null) return;
|
|
8898
9168
|
setChatTo(request.to);
|
|
@@ -9130,13 +9400,13 @@ function useUnreadChat(open) {
|
|
|
9130
9400
|
const snapshot = useMeetSnapshot();
|
|
9131
9401
|
const chat = snapshot?.chat ?? [];
|
|
9132
9402
|
const local = snapshot?.localIdentity ?? null;
|
|
9133
|
-
const [seen, setSeen] = (0,
|
|
9134
|
-
(0,
|
|
9403
|
+
const [seen, setSeen] = (0, import_react6.useState)(0);
|
|
9404
|
+
(0, import_react6.useEffect)(() => {
|
|
9135
9405
|
if (open) setSeen(chat.length);
|
|
9136
9406
|
}, [open, chat.length]);
|
|
9137
9407
|
const loaded = snapshot?.chatLoaded === true;
|
|
9138
|
-
const [baseline, setBaseline] = (0,
|
|
9139
|
-
(0,
|
|
9408
|
+
const [baseline, setBaseline] = (0, import_react6.useState)(null);
|
|
9409
|
+
(0, import_react6.useEffect)(() => {
|
|
9140
9410
|
if (loaded && baseline === null) setBaseline(chat.length);
|
|
9141
9411
|
}, [loaded, baseline, chat.length]);
|
|
9142
9412
|
if (open) return 0;
|
|
@@ -9149,14 +9419,14 @@ function Popover({
|
|
|
9149
9419
|
children,
|
|
9150
9420
|
placement = "up"
|
|
9151
9421
|
}) {
|
|
9152
|
-
const ref = (0,
|
|
9153
|
-
const [style, setStyle] = (0,
|
|
9422
|
+
const ref = (0, import_react6.useRef)(null);
|
|
9423
|
+
const [style, setStyle] = (0, import_react6.useState)({
|
|
9154
9424
|
position: "fixed",
|
|
9155
9425
|
top: 0,
|
|
9156
9426
|
left: 0,
|
|
9157
9427
|
visibility: "hidden"
|
|
9158
9428
|
});
|
|
9159
|
-
(0,
|
|
9429
|
+
(0, import_react6.useLayoutEffect)(() => {
|
|
9160
9430
|
const element = ref.current;
|
|
9161
9431
|
const anchor = element?.parentElement ?? null;
|
|
9162
9432
|
if (element === null || anchor === null) return;
|
|
@@ -9201,7 +9471,7 @@ function Popover({
|
|
|
9201
9471
|
window.removeEventListener("scroll", place, true);
|
|
9202
9472
|
};
|
|
9203
9473
|
}, [placement]);
|
|
9204
|
-
(0,
|
|
9474
|
+
(0, import_react6.useEffect)(() => {
|
|
9205
9475
|
const onKey = (event) => {
|
|
9206
9476
|
if (event.key === "Escape") onClose();
|
|
9207
9477
|
};
|
|
@@ -9235,7 +9505,7 @@ function MenuItem({
|
|
|
9235
9505
|
);
|
|
9236
9506
|
}
|
|
9237
9507
|
function Toast({ text: text3, failed, onDone }) {
|
|
9238
|
-
(0,
|
|
9508
|
+
(0, import_react6.useEffect)(() => {
|
|
9239
9509
|
const timer = setTimeout(onDone, failed ? 7e3 : 4e3);
|
|
9240
9510
|
return () => clearTimeout(timer);
|
|
9241
9511
|
}, [text3, failed, onDone]);
|
|
@@ -9274,7 +9544,7 @@ function MeetingOverlays() {
|
|
|
9274
9544
|
] });
|
|
9275
9545
|
}
|
|
9276
9546
|
function ShortcutsSheet({ onClose }) {
|
|
9277
|
-
(0,
|
|
9547
|
+
(0, import_react6.useEffect)(() => {
|
|
9278
9548
|
const onKey = (event) => {
|
|
9279
9549
|
if (event.key === "Escape") onClose();
|
|
9280
9550
|
};
|
|
@@ -9312,8 +9582,8 @@ function PanelShell({
|
|
|
9312
9582
|
onClose,
|
|
9313
9583
|
children
|
|
9314
9584
|
}) {
|
|
9315
|
-
const ref = (0,
|
|
9316
|
-
(0,
|
|
9585
|
+
const ref = (0, import_react6.useRef)(null);
|
|
9586
|
+
(0, import_react6.useLayoutEffect)(() => {
|
|
9317
9587
|
const panel = ref.current;
|
|
9318
9588
|
const root = panel?.closest(".mx-meet");
|
|
9319
9589
|
const header = root?.querySelector(":scope > .mx-meet__header") ?? null;
|
|
@@ -9340,17 +9610,17 @@ function ChatPanel({
|
|
|
9340
9610
|
}) {
|
|
9341
9611
|
const snapshot = useMeetSnapshot();
|
|
9342
9612
|
const room = useRoom();
|
|
9343
|
-
const [draft, setDraft] = (0,
|
|
9344
|
-
const [recipient, setRecipient] = (0,
|
|
9345
|
-
const listRef = (0,
|
|
9613
|
+
const [draft, setDraft] = (0, import_react6.useState)("");
|
|
9614
|
+
const [recipient, setRecipient] = (0, import_react6.useState)(to);
|
|
9615
|
+
const listRef = (0, import_react6.useRef)(null);
|
|
9346
9616
|
const messages = snapshot?.chat ?? [];
|
|
9347
9617
|
const local = snapshot?.localIdentity ?? null;
|
|
9348
9618
|
const people = (snapshot?.participants ?? []).filter(
|
|
9349
9619
|
(participant) => !participant.isLocal && !participant.isAgent
|
|
9350
9620
|
);
|
|
9351
9621
|
const recipientName = recipient === null ? null : people.find((p) => p.identity === recipient)?.displayName ?? null;
|
|
9352
|
-
(0,
|
|
9353
|
-
(0,
|
|
9622
|
+
(0, import_react6.useEffect)(() => setRecipient(to), [to]);
|
|
9623
|
+
(0, import_react6.useEffect)(() => {
|
|
9354
9624
|
const list = listRef.current;
|
|
9355
9625
|
if (list !== null) list.scrollTop = list.scrollHeight;
|
|
9356
9626
|
}, [messages.length]);
|
|
@@ -9456,8 +9726,8 @@ function PeoplePanel({
|
|
|
9456
9726
|
const snapshot = useMeetSnapshot();
|
|
9457
9727
|
const controls = useHostControls();
|
|
9458
9728
|
const queue = useHandQueue();
|
|
9459
|
-
const [query, setQuery] = (0,
|
|
9460
|
-
const [menuFor, setMenuFor] = (0,
|
|
9729
|
+
const [query, setQuery] = (0, import_react6.useState)("");
|
|
9730
|
+
const [menuFor, setMenuFor] = (0, import_react6.useState)(null);
|
|
9461
9731
|
const myRole = useRole();
|
|
9462
9732
|
const local = snapshot?.localIdentity ?? null;
|
|
9463
9733
|
const everyone = snapshot?.participants ?? [];
|
|
@@ -9582,14 +9852,14 @@ function PersonMenu({
|
|
|
9582
9852
|
const host = useMeetHost();
|
|
9583
9853
|
const snapshot = useMeetSnapshot();
|
|
9584
9854
|
const controls = useHostControls();
|
|
9585
|
-
const [mode, setMode] = (0,
|
|
9586
|
-
const [text3, setText] = (0,
|
|
9855
|
+
const [mode, setMode] = (0, import_react6.useState)("menu");
|
|
9856
|
+
const [text3, setText] = (0, import_react6.useState)("");
|
|
9587
9857
|
const self = participant.identity === snapshot?.localIdentity;
|
|
9588
9858
|
const moderate = controls.canModerate(participant);
|
|
9589
9859
|
const pinned = snapshot?.pinned === participant.identity;
|
|
9590
9860
|
const spotlit = snapshot?.spotlight === participant.identity;
|
|
9591
9861
|
const hasAccount = participant.userId !== null;
|
|
9592
|
-
const [refused, setRefused] = (0,
|
|
9862
|
+
const [refused, setRefused] = (0, import_react6.useState)(false);
|
|
9593
9863
|
const act = (request) => {
|
|
9594
9864
|
setRefused(false);
|
|
9595
9865
|
void controls.run(request).then((result) => {
|
|
@@ -9805,8 +10075,8 @@ function DeviceSettings({
|
|
|
9805
10075
|
const speaker = devices?.selected.audiooutput ?? host.devices.resolve("audiooutput");
|
|
9806
10076
|
const stream = useMicrophoneStream(microphone);
|
|
9807
10077
|
const level = useAudioLevel(stream);
|
|
9808
|
-
const [testing, setTesting] = (0,
|
|
9809
|
-
(0,
|
|
10078
|
+
const [testing, setTesting] = (0, import_react6.useState)(false);
|
|
10079
|
+
(0, import_react6.useEffect)(() => {
|
|
9810
10080
|
void host.devices.refresh();
|
|
9811
10081
|
}, [host]);
|
|
9812
10082
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__section", "aria-label": "Devices", children: [
|
|
@@ -9835,8 +10105,8 @@ function DeviceSettings({
|
|
|
9835
10105
|
}
|
|
9836
10106
|
function EffectsSettings({ preview }) {
|
|
9837
10107
|
const effects = useMediaEffects();
|
|
9838
|
-
const [error, setError] = (0,
|
|
9839
|
-
const fileRef = (0,
|
|
10108
|
+
const [error, setError] = (0, import_react6.useState)(null);
|
|
10109
|
+
const fileRef = (0, import_react6.useRef)(null);
|
|
9840
10110
|
const supported = effects.backgroundsSupported || preview != null || videoEffectsSupported();
|
|
9841
10111
|
const apply = (next) => {
|
|
9842
10112
|
setError(null);
|
|
@@ -9958,8 +10228,8 @@ async function playTestSound(sinkId) {
|
|
|
9958
10228
|
await context.close();
|
|
9959
10229
|
}
|
|
9960
10230
|
function useMicrophoneStream(deviceId2) {
|
|
9961
|
-
const [stream, setStream] = (0,
|
|
9962
|
-
(0,
|
|
10231
|
+
const [stream, setStream] = (0, import_react6.useState)(null);
|
|
10232
|
+
(0, import_react6.useEffect)(() => {
|
|
9963
10233
|
if (deviceId2 === "off") return void 0;
|
|
9964
10234
|
let live = true;
|
|
9965
10235
|
let opened = null;
|
|
@@ -10060,7 +10330,7 @@ function NoteList({
|
|
|
10060
10330
|
}
|
|
10061
10331
|
function AiPanel({ onClose }) {
|
|
10062
10332
|
const ai = useMeetAi();
|
|
10063
|
-
const [question, setQuestion] = (0,
|
|
10333
|
+
const [question, setQuestion] = (0, import_react6.useState)("");
|
|
10064
10334
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(PanelShell, { title: "Meeting assistant", onClose, children: [
|
|
10065
10335
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(NoteTakerRow, {}),
|
|
10066
10336
|
ai.summary !== null ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("section", { className: "mx-meet__note-group", "aria-label": "Summary", children: [
|
|
@@ -10216,16 +10486,16 @@ function PreJoinBody({
|
|
|
10216
10486
|
const recording = useRecording();
|
|
10217
10487
|
const effects = useMediaEffects();
|
|
10218
10488
|
const { notice } = useModerationNotice();
|
|
10219
|
-
const [mode, setMode] = (0,
|
|
10220
|
-
const [microphone, setMicrophone] = (0,
|
|
10221
|
-
const [joining, setJoining] = (0,
|
|
10489
|
+
const [mode, setMode] = (0, import_react6.useState)("video");
|
|
10490
|
+
const [microphone, setMicrophone] = (0, import_react6.useState)(true);
|
|
10491
|
+
const [joining, setJoining] = (0, import_react6.useState)(false);
|
|
10222
10492
|
const camera = devices?.selected.videoinput ?? host.devices.resolve("videoinput");
|
|
10223
10493
|
const mic = devices?.selected.audioinput ?? host.devices.resolve("audioinput");
|
|
10224
10494
|
const preview = useCameraPreview(mode === "video" ? camera : void 0, effects.effects);
|
|
10225
10495
|
const micStream = useMicrophoneStream(microphone ? mic : "off");
|
|
10226
10496
|
const level = useAudioLevel(micStream);
|
|
10227
|
-
const [speakerTesting, setSpeakerTesting] = (0,
|
|
10228
|
-
(0,
|
|
10497
|
+
const [speakerTesting, setSpeakerTesting] = (0, import_react6.useState)(false);
|
|
10498
|
+
(0, import_react6.useEffect)(() => {
|
|
10229
10499
|
void host.devices.refresh();
|
|
10230
10500
|
}, [host]);
|
|
10231
10501
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__prejoin", children: [
|
|
@@ -10341,12 +10611,12 @@ function PreJoinBody({
|
|
|
10341
10611
|
] });
|
|
10342
10612
|
}
|
|
10343
10613
|
function useCameraPreview(deviceId2, effects) {
|
|
10344
|
-
const [preview, setPreview] = (0,
|
|
10345
|
-
const [error, setError] = (0,
|
|
10346
|
-
const current = (0,
|
|
10347
|
-
const initialEffect = (0,
|
|
10614
|
+
const [preview, setPreview] = (0, import_react6.useState)(null);
|
|
10615
|
+
const [error, setError] = (0, import_react6.useState)(null);
|
|
10616
|
+
const current = (0, import_react6.useRef)(null);
|
|
10617
|
+
const initialEffect = (0, import_react6.useRef)(toVideoEffect(effects));
|
|
10348
10618
|
initialEffect.current = toVideoEffect(effects);
|
|
10349
|
-
(0,
|
|
10619
|
+
(0, import_react6.useEffect)(() => {
|
|
10350
10620
|
if (deviceId2 === void 0) return void 0;
|
|
10351
10621
|
let live = true;
|
|
10352
10622
|
setError(null);
|
|
@@ -10432,16 +10702,16 @@ function MeetingRoomBody({
|
|
|
10432
10702
|
const isHost = useIsHost();
|
|
10433
10703
|
const elapsed = useElapsed(snapshot?.meeting?.startedAt ?? null);
|
|
10434
10704
|
const phase = snapshot?.phase ?? "idle";
|
|
10435
|
-
(0,
|
|
10705
|
+
(0, import_react6.useEffect)(() => {
|
|
10436
10706
|
host.meetings.watch(roomName);
|
|
10437
10707
|
}, [host, roomName]);
|
|
10438
|
-
(0,
|
|
10708
|
+
(0, import_react6.useEffect)(() => {
|
|
10439
10709
|
if (given === void 0) return;
|
|
10440
10710
|
if (host.store.snapshot().meeting !== null) return;
|
|
10441
10711
|
host.store.patch({ meeting: given, locked: given.locked });
|
|
10442
10712
|
}, [host, given]);
|
|
10443
10713
|
const watchedId = meetingId ?? snapshot?.meeting?.id ?? null;
|
|
10444
|
-
(0,
|
|
10714
|
+
(0, import_react6.useEffect)(() => {
|
|
10445
10715
|
if (watchedId === null) return;
|
|
10446
10716
|
host.meetings.watchMeeting(asMeetingId(watchedId));
|
|
10447
10717
|
}, [host, watchedId]);
|
|
@@ -10486,8 +10756,8 @@ function MeetingRoomBody({
|
|
|
10486
10756
|
] });
|
|
10487
10757
|
}
|
|
10488
10758
|
function WaitingRoom({ roomName, host }) {
|
|
10489
|
-
const knocked = (0,
|
|
10490
|
-
(0,
|
|
10759
|
+
const knocked = (0, import_react6.useRef)(false);
|
|
10760
|
+
(0, import_react6.useEffect)(() => {
|
|
10491
10761
|
if (knocked.current) return;
|
|
10492
10762
|
knocked.current = true;
|
|
10493
10763
|
host.meetings.knock(roomName);
|
|
@@ -10506,7 +10776,7 @@ function HostMenu() {
|
|
|
10506
10776
|
const host = useRequiredMeetHost();
|
|
10507
10777
|
const snapshot = useMeetSnapshot();
|
|
10508
10778
|
const end = useEndMeeting();
|
|
10509
|
-
const [confirmingEnd, setConfirmingEnd] = (0,
|
|
10779
|
+
const [confirmingEnd, setConfirmingEnd] = (0, import_react6.useState)(false);
|
|
10510
10780
|
const locked = snapshot?.locked === true;
|
|
10511
10781
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mx-meet__host-menu", children: [
|
|
10512
10782
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
@@ -10612,13 +10882,13 @@ function ScheduleMeetingBody({
|
|
|
10612
10882
|
onScheduled,
|
|
10613
10883
|
host
|
|
10614
10884
|
}) {
|
|
10615
|
-
const [title, setTitle] = (0,
|
|
10616
|
-
const [when2, setWhen] = (0,
|
|
10617
|
-
const [kind, setKind] = (0,
|
|
10618
|
-
const [busy, setBusy] = (0,
|
|
10619
|
-
const [link, setLink] = (0,
|
|
10620
|
-
const [error, setError] = (0,
|
|
10621
|
-
const disabled = (0,
|
|
10885
|
+
const [title, setTitle] = (0, import_react6.useState)("");
|
|
10886
|
+
const [when2, setWhen] = (0, import_react6.useState)("");
|
|
10887
|
+
const [kind, setKind] = (0, import_react6.useState)("scheduled");
|
|
10888
|
+
const [busy, setBusy] = (0, import_react6.useState)(false);
|
|
10889
|
+
const [link, setLink] = (0, import_react6.useState)(null);
|
|
10890
|
+
const [error, setError] = (0, import_react6.useState)(null);
|
|
10891
|
+
const disabled = (0, import_react6.useMemo)(() => title.trim().length === 0 || busy, [title, busy]);
|
|
10622
10892
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
10623
10893
|
"form",
|
|
10624
10894
|
{
|
|
@@ -10755,8 +11025,8 @@ function MeetingRecordBody({
|
|
|
10755
11025
|
}) {
|
|
10756
11026
|
const host = useRequiredMeetHost();
|
|
10757
11027
|
const record = useMeetingRecord(meeting);
|
|
10758
|
-
const [question, setQuestion] = (0,
|
|
10759
|
-
const [tab, setTab] = (0,
|
|
11028
|
+
const [question, setQuestion] = (0, import_react6.useState)("");
|
|
11029
|
+
const [tab, setTab] = (0, import_react6.useState)("summary");
|
|
10760
11030
|
if (record.failure !== null) {
|
|
10761
11031
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "mx-meet mx-meet--record", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_design_system.ErrorBox, { as: "div", className: "mx-meet__empty", error: record.failure, operation: "Open this meeting record", origin: "meet/components", children: [
|
|
10762
11032
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "mx-meet__empty-title", children: "This meeting record could not be opened" }),
|
|
@@ -11011,10 +11281,10 @@ function RecordingPlayer(props) {
|
|
|
11011
11281
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(RecordingPlayerBody, { ...props, host });
|
|
11012
11282
|
}
|
|
11013
11283
|
function RecordingPlayerBody({ fileId, host }) {
|
|
11014
|
-
const [media, setMedia] = (0,
|
|
11015
|
-
const [loading, setLoading] = (0,
|
|
11016
|
-
const [error, setError] = (0,
|
|
11017
|
-
(0,
|
|
11284
|
+
const [media, setMedia] = (0, import_react6.useState)(null);
|
|
11285
|
+
const [loading, setLoading] = (0, import_react6.useState)(false);
|
|
11286
|
+
const [error, setError] = (0, import_react6.useState)(null);
|
|
11287
|
+
(0, import_react6.useEffect)(() => {
|
|
11018
11288
|
if (media === null || media.kind !== "bytes") return void 0;
|
|
11019
11289
|
const url = media.url;
|
|
11020
11290
|
return () => URL.revokeObjectURL(url);
|