@ai-matrx/meet 0.11.28 → 0.11.30
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 +6 -0
- package/dist/{collab-CUxjUtrb.d.cts → collab-XY6Xj1dG.d.cts} +5 -0
- package/dist/{collab-CUxjUtrb.d.ts → collab-XY6Xj1dG.d.ts} +5 -0
- package/dist/{components-DPdU3POT.d.cts → components-4f9Mf8fz.d.cts} +1 -1
- package/dist/{components-CUPzD0y3.d.ts → components-Cwep2NYU.d.ts} +1 -1
- package/dist/core.cjs +893 -43
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +549 -169
- package/dist/core.d.ts +549 -169
- package/dist/core.js +893 -43
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +893 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +893 -43
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +1005 -48
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +6 -12
- package/dist/react.d.ts +6 -12
- package/dist/react.js +1005 -48
- package/dist/react.js.map +1 -1
- package/dist/skins/meet.cjs +263 -27
- package/dist/skins/meet.cjs.map +1 -1
- package/dist/skins/meet.d.cts +2 -2
- package/dist/skins/meet.d.ts +2 -2
- package/dist/skins/meet.js +263 -27
- package/dist/skins/meet.js.map +1 -1
- package/dist/styles.css +46 -0
- package/package.json +4 -4
package/dist/core.js
CHANGED
|
@@ -204,6 +204,352 @@ function invalidResponse(operation, detail) {
|
|
|
204
204
|
);
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
+
// src/core/connection-supervisor.ts
|
|
208
|
+
var DEFAULT_CONNECTION_POLICY = {
|
|
209
|
+
bannerDelayMs: 2e3,
|
|
210
|
+
autoRejoin: true,
|
|
211
|
+
autoRejoinMaxAttempts: 5,
|
|
212
|
+
reconnectGraceSeconds: 30
|
|
213
|
+
};
|
|
214
|
+
function clampInt(value, min, max, fallback) {
|
|
215
|
+
if (typeof value !== "number" || !Number.isFinite(value)) return fallback;
|
|
216
|
+
return Math.min(max, Math.max(min, Math.round(value)));
|
|
217
|
+
}
|
|
218
|
+
function connectionPolicyFrom(raw) {
|
|
219
|
+
if (typeof raw !== "object" || raw === null) return DEFAULT_CONNECTION_POLICY;
|
|
220
|
+
const row = raw;
|
|
221
|
+
const d = DEFAULT_CONNECTION_POLICY;
|
|
222
|
+
return {
|
|
223
|
+
bannerDelayMs: clampInt(row["reconnect_banner_delay_ms"], 0, 1e4, d.bannerDelayMs),
|
|
224
|
+
autoRejoin: typeof row["auto_rejoin"] === "boolean" ? row["auto_rejoin"] : d.autoRejoin,
|
|
225
|
+
autoRejoinMaxAttempts: clampInt(row["auto_rejoin_max_attempts"], 0, 20, d.autoRejoinMaxAttempts),
|
|
226
|
+
reconnectGraceSeconds: clampInt(row["reconnect_grace_seconds"], 0, 600, d.reconnectGraceSeconds)
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
var LIVEKIT_BASE_DELAYS_MS = [0, 300, 1200, 2700, 4800, 7e3];
|
|
230
|
+
function createReconnectPolicy(options = {}) {
|
|
231
|
+
const delays = options.delaysMs !== void 0 && options.delaysMs.length > 0 ? options.delaysMs : LIVEKIT_BASE_DELAYS_MS;
|
|
232
|
+
const giveUpMs = options.giveUpMs ?? 45e3;
|
|
233
|
+
const maxAttempts = options.maxAttempts ?? 12;
|
|
234
|
+
const random = options.random ?? Math.random;
|
|
235
|
+
return {
|
|
236
|
+
nextRetryDelayInMs({ retryCount, elapsedMs }) {
|
|
237
|
+
if (retryCount >= maxAttempts || elapsedMs >= giveUpMs) return null;
|
|
238
|
+
const base = delays[Math.min(retryCount, delays.length - 1)] ?? 0;
|
|
239
|
+
const spread = Math.min(2e3, Math.max(500, base / 2));
|
|
240
|
+
return Math.round(base + random() * spread);
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
function createWebNetworkPort() {
|
|
245
|
+
const scope = globalThis;
|
|
246
|
+
return {
|
|
247
|
+
online: () => scope.navigator?.onLine !== false,
|
|
248
|
+
subscribe(listener) {
|
|
249
|
+
if (typeof scope.addEventListener !== "function") return () => void 0;
|
|
250
|
+
const on = () => listener(true);
|
|
251
|
+
const off = () => listener(false);
|
|
252
|
+
scope.addEventListener("online", on);
|
|
253
|
+
scope.addEventListener("offline", off);
|
|
254
|
+
return () => {
|
|
255
|
+
scope.removeEventListener?.("online", on);
|
|
256
|
+
scope.removeEventListener?.("offline", off);
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
function createReachabilityProbe(urls, timeoutMs = 4e3) {
|
|
262
|
+
return async () => {
|
|
263
|
+
const targets = urls().filter((url) => url.length > 0);
|
|
264
|
+
if (targets.length === 0 || typeof fetch !== "function") return true;
|
|
265
|
+
const one = async (url) => {
|
|
266
|
+
const controller = typeof AbortController === "function" ? new AbortController() : null;
|
|
267
|
+
const timer = setTimeout(() => controller?.abort(), timeoutMs);
|
|
268
|
+
try {
|
|
269
|
+
await fetch(url, {
|
|
270
|
+
method: "GET",
|
|
271
|
+
mode: "no-cors",
|
|
272
|
+
cache: "no-store",
|
|
273
|
+
credentials: "omit",
|
|
274
|
+
...controller !== null ? { signal: controller.signal } : {}
|
|
275
|
+
});
|
|
276
|
+
return true;
|
|
277
|
+
} catch {
|
|
278
|
+
return false;
|
|
279
|
+
} finally {
|
|
280
|
+
clearTimeout(timer);
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
const answers = await Promise.all(targets.map(one));
|
|
284
|
+
return answers.every(Boolean);
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
function httpUrlOf(serverUrl) {
|
|
288
|
+
return serverUrl.replace(/^ws(s?):\/\//i, "http$1://");
|
|
289
|
+
}
|
|
290
|
+
var RESUME_WINDOW_MS = 15 * 6e4;
|
|
291
|
+
var RESUME_KEY = "mx-meet:resume:";
|
|
292
|
+
function createWebResumeStorage() {
|
|
293
|
+
const storage = globalThis.sessionStorage;
|
|
294
|
+
if (storage === void 0) return void 0;
|
|
295
|
+
return {
|
|
296
|
+
load(roomName) {
|
|
297
|
+
try {
|
|
298
|
+
const raw = storage.getItem(RESUME_KEY + roomName);
|
|
299
|
+
if (raw === null) return null;
|
|
300
|
+
const parsed = JSON.parse(raw);
|
|
301
|
+
return typeof parsed?.at === "number" && typeof parsed.request?.roomName === "string" ? parsed : null;
|
|
302
|
+
} catch {
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
},
|
|
306
|
+
save(roomName, marker) {
|
|
307
|
+
try {
|
|
308
|
+
storage.setItem(RESUME_KEY + roomName, JSON.stringify(marker));
|
|
309
|
+
} catch {
|
|
310
|
+
}
|
|
311
|
+
},
|
|
312
|
+
clear(roomName) {
|
|
313
|
+
try {
|
|
314
|
+
storage.removeItem(RESUME_KEY + roomName);
|
|
315
|
+
} catch {
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
}
|
|
320
|
+
var CLEARS_RESUME = (phase) => phase === "left" || phase === "removed" || phase === "superseded" || phase === "inactive" || phase === "ended" || phase === "record" || phase === "prejoin" || phase.startsWith("refused:") || phase.startsWith("waiting:");
|
|
321
|
+
function autoRejoinDelayMs(attempt, random = Math.random) {
|
|
322
|
+
const base = Math.min(15e3, 1e3 * 2 ** Math.max(0, attempt));
|
|
323
|
+
return Math.round(base * (0.5 + random()));
|
|
324
|
+
}
|
|
325
|
+
function createConnectionSupervisor(options) {
|
|
326
|
+
const { store, network } = options;
|
|
327
|
+
const now = options.now ?? (() => Date.now());
|
|
328
|
+
const random = options.random ?? Math.random;
|
|
329
|
+
const probeEveryMs = options.probeEveryMs ?? 3e3;
|
|
330
|
+
let driverRegion = null;
|
|
331
|
+
let probeTimer = null;
|
|
332
|
+
let probing = false;
|
|
333
|
+
let bannerTimer = null;
|
|
334
|
+
let rejoinTimer = null;
|
|
335
|
+
let rejoinAttempts = 0;
|
|
336
|
+
let lastPhase = store.snapshot().phase;
|
|
337
|
+
let lastSavedAt = 0;
|
|
338
|
+
let disposed = false;
|
|
339
|
+
const inCall = () => store.snapshot().phase === "in_call";
|
|
340
|
+
const dropped = () => store.snapshot().phase === "disconnected";
|
|
341
|
+
function setRegion(next) {
|
|
342
|
+
if (store.snapshot().connection !== next) store.patch({ connection: next });
|
|
343
|
+
}
|
|
344
|
+
function regionFor(reachable) {
|
|
345
|
+
if (!network.online()) return "offline";
|
|
346
|
+
if (reachable === false) return "server_unreachable";
|
|
347
|
+
if (dropped()) return reachable === true ? "stable" : store.snapshot().connection;
|
|
348
|
+
return driverRegion ?? "stable";
|
|
349
|
+
}
|
|
350
|
+
function needsWatch() {
|
|
351
|
+
const snap = store.snapshot();
|
|
352
|
+
if (dropped()) return true;
|
|
353
|
+
return inCall() && (driverRegion !== null || snap.connection !== "stable");
|
|
354
|
+
}
|
|
355
|
+
function stopProbe() {
|
|
356
|
+
if (probeTimer !== null) clearTimeout(probeTimer);
|
|
357
|
+
probeTimer = null;
|
|
358
|
+
}
|
|
359
|
+
function scheduleProbe(delayMs) {
|
|
360
|
+
if (disposed || probeTimer !== null) return;
|
|
361
|
+
probeTimer = setTimeout(() => {
|
|
362
|
+
probeTimer = null;
|
|
363
|
+
void runProbe();
|
|
364
|
+
}, delayMs);
|
|
365
|
+
}
|
|
366
|
+
async function runProbe() {
|
|
367
|
+
if (disposed || probing) return;
|
|
368
|
+
if (!needsWatch()) return;
|
|
369
|
+
if (!network.online()) {
|
|
370
|
+
setRegion("offline");
|
|
371
|
+
scheduleProbe(probeEveryMs);
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
probing = true;
|
|
375
|
+
let reachable = false;
|
|
376
|
+
try {
|
|
377
|
+
reachable = await options.probe();
|
|
378
|
+
} catch {
|
|
379
|
+
reachable = false;
|
|
380
|
+
} finally {
|
|
381
|
+
probing = false;
|
|
382
|
+
}
|
|
383
|
+
if (disposed) return;
|
|
384
|
+
if (inCall() || dropped()) setRegion(regionFor(reachable));
|
|
385
|
+
if (dropped() && reachable) maybeRejoin();
|
|
386
|
+
if (needsWatch()) scheduleProbe(Math.round(probeEveryMs * (0.75 + random() * 0.5)));
|
|
387
|
+
}
|
|
388
|
+
function syncBanner() {
|
|
389
|
+
const snap = store.snapshot();
|
|
390
|
+
const unstable = snap.phase === "in_call" && snap.connection !== "stable";
|
|
391
|
+
if (!unstable) {
|
|
392
|
+
if (bannerTimer !== null) clearTimeout(bannerTimer);
|
|
393
|
+
bannerTimer = null;
|
|
394
|
+
if (snap.connectionBanner) store.patch({ connectionBanner: false });
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
if (snap.connectionBanner || bannerTimer !== null) return;
|
|
398
|
+
const delay = options.policy().bannerDelayMs;
|
|
399
|
+
if (delay <= 0) {
|
|
400
|
+
store.patch({ connectionBanner: true });
|
|
401
|
+
return;
|
|
402
|
+
}
|
|
403
|
+
bannerTimer = setTimeout(() => {
|
|
404
|
+
bannerTimer = null;
|
|
405
|
+
const latest = store.snapshot();
|
|
406
|
+
if (latest.phase === "in_call" && latest.connection !== "stable" && !latest.connectionBanner) {
|
|
407
|
+
store.patch({ connectionBanner: true });
|
|
408
|
+
}
|
|
409
|
+
}, delay);
|
|
410
|
+
}
|
|
411
|
+
function stopRejoin() {
|
|
412
|
+
if (rejoinTimer !== null) clearTimeout(rejoinTimer);
|
|
413
|
+
rejoinTimer = null;
|
|
414
|
+
}
|
|
415
|
+
function maybeRejoin() {
|
|
416
|
+
if (disposed || rejoinTimer !== null || !dropped()) return;
|
|
417
|
+
const policy = options.policy();
|
|
418
|
+
if (!policy.autoRejoin) return;
|
|
419
|
+
if (rejoinAttempts >= policy.autoRejoinMaxAttempts) return;
|
|
420
|
+
if (!network.online()) return;
|
|
421
|
+
const attempt = rejoinAttempts;
|
|
422
|
+
rejoinTimer = setTimeout(() => {
|
|
423
|
+
rejoinTimer = null;
|
|
424
|
+
if (disposed || !dropped() || !network.online()) return;
|
|
425
|
+
rejoinAttempts = attempt + 1;
|
|
426
|
+
options.report?.("info", `meet: rejoining by itself (attempt ${rejoinAttempts} of ${policy.autoRejoinMaxAttempts})`);
|
|
427
|
+
void options.autoRejoin().catch(() => void 0);
|
|
428
|
+
}, autoRejoinDelayMs(attempt, random));
|
|
429
|
+
}
|
|
430
|
+
function saveMarker(force) {
|
|
431
|
+
const resume = options.resume;
|
|
432
|
+
const snap = store.snapshot();
|
|
433
|
+
if (resume === void 0 || snap.roomName === null) return;
|
|
434
|
+
const at = now();
|
|
435
|
+
if (!force && at - lastSavedAt < 1e4) return;
|
|
436
|
+
const request = options.currentRequest();
|
|
437
|
+
if (request === null) return;
|
|
438
|
+
lastSavedAt = at;
|
|
439
|
+
resume.save(snap.roomName, { request, at });
|
|
440
|
+
}
|
|
441
|
+
const unsubscribeStore = store.subscribe(() => {
|
|
442
|
+
if (disposed) return;
|
|
443
|
+
const snap = store.snapshot();
|
|
444
|
+
const phase = snap.phase;
|
|
445
|
+
const changed = phase !== lastPhase;
|
|
446
|
+
lastPhase = phase;
|
|
447
|
+
if (changed) {
|
|
448
|
+
if (phase === "in_call") {
|
|
449
|
+
rejoinAttempts = 0;
|
|
450
|
+
stopRejoin();
|
|
451
|
+
saveMarker(true);
|
|
452
|
+
} else if (phase === "disconnected") {
|
|
453
|
+
driverRegion = null;
|
|
454
|
+
saveMarker(true);
|
|
455
|
+
stopProbe();
|
|
456
|
+
scheduleProbe(0);
|
|
457
|
+
} else {
|
|
458
|
+
stopRejoin();
|
|
459
|
+
if (phase !== "joining") driverRegion = null;
|
|
460
|
+
if (CLEARS_RESUME(phase) && snap.roomName !== null) options.resume?.clear(snap.roomName);
|
|
461
|
+
}
|
|
462
|
+
} else if (phase === "in_call" || phase === "disconnected") {
|
|
463
|
+
saveMarker(false);
|
|
464
|
+
}
|
|
465
|
+
syncBanner();
|
|
466
|
+
});
|
|
467
|
+
const unsubscribeNetwork = network.subscribe((online) => {
|
|
468
|
+
if (disposed) return;
|
|
469
|
+
if (!online) {
|
|
470
|
+
if (inCall() || dropped()) setRegion("offline");
|
|
471
|
+
stopRejoin();
|
|
472
|
+
stopProbe();
|
|
473
|
+
if (needsWatch()) scheduleProbe(probeEveryMs);
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
stopProbe();
|
|
477
|
+
if (needsWatch()) scheduleProbe(0);
|
|
478
|
+
});
|
|
479
|
+
return {
|
|
480
|
+
driverState(state) {
|
|
481
|
+
if (disposed) return;
|
|
482
|
+
if (state === "connected") {
|
|
483
|
+
driverRegion = null;
|
|
484
|
+
if (inCall() || store.snapshot().phase === "joining") setRegion(network.online() ? "stable" : "offline");
|
|
485
|
+
if (!needsWatch()) stopProbe();
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
if (state === "reconnecting" || state === "signal_reconnecting") {
|
|
489
|
+
driverRegion = state;
|
|
490
|
+
if (inCall()) {
|
|
491
|
+
setRegion(network.online() ? state : "offline");
|
|
492
|
+
stopProbe();
|
|
493
|
+
scheduleProbe(0);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
},
|
|
497
|
+
exitConnection() {
|
|
498
|
+
return network.online() ? "server_unreachable" : "offline";
|
|
499
|
+
},
|
|
500
|
+
resumable(roomName) {
|
|
501
|
+
const resume = options.resume;
|
|
502
|
+
if (resume === void 0) return null;
|
|
503
|
+
const marker = resume.load(roomName);
|
|
504
|
+
if (marker === null) return null;
|
|
505
|
+
if (now() - marker.at > RESUME_WINDOW_MS) {
|
|
506
|
+
resume.clear(roomName);
|
|
507
|
+
return null;
|
|
508
|
+
}
|
|
509
|
+
return marker;
|
|
510
|
+
},
|
|
511
|
+
dispose() {
|
|
512
|
+
disposed = true;
|
|
513
|
+
stopProbe();
|
|
514
|
+
stopRejoin();
|
|
515
|
+
if (bannerTimer !== null) clearTimeout(bannerTimer);
|
|
516
|
+
bannerTimer = null;
|
|
517
|
+
unsubscribeStore();
|
|
518
|
+
unsubscribeNetwork();
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
var DELIBERATE_DEPARTURES = /* @__PURE__ */ new Set([
|
|
523
|
+
"CLIENT_INITIATED",
|
|
524
|
+
"PARTICIPANT_REMOVED",
|
|
525
|
+
"ROOM_DELETED",
|
|
526
|
+
"ROOM_CLOSED",
|
|
527
|
+
"DUPLICATE_IDENTITY",
|
|
528
|
+
"USER_REJECTED",
|
|
529
|
+
"USER_UNAVAILABLE",
|
|
530
|
+
"SIP_TRUNK_FAILURE"
|
|
531
|
+
]);
|
|
532
|
+
function isUnannouncedDeparture(reason) {
|
|
533
|
+
return reason === null || !DELIBERATE_DEPARTURES.has(reason);
|
|
534
|
+
}
|
|
535
|
+
function mergeGhosts(live, ghosts, at) {
|
|
536
|
+
const present = new Set(live.map((p) => p.identity));
|
|
537
|
+
const kept = /* @__PURE__ */ new Map();
|
|
538
|
+
const extra = [];
|
|
539
|
+
for (const [identity, ghost] of ghosts) {
|
|
540
|
+
if (present.has(identity) || ghost.until <= at) continue;
|
|
541
|
+
kept.set(identity, ghost);
|
|
542
|
+
extra.push({
|
|
543
|
+
...ghost.participant,
|
|
544
|
+
micEnabled: false,
|
|
545
|
+
cameraEnabled: false,
|
|
546
|
+
screenSharing: false,
|
|
547
|
+
reconnecting: true
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
return { roster: [...live, ...extra], kept };
|
|
551
|
+
}
|
|
552
|
+
|
|
207
553
|
// src/core/tokens.ts
|
|
208
554
|
function createWebRoomTokenStorage(onDiagnostic) {
|
|
209
555
|
const store = globalThis.localStorage;
|
|
@@ -389,7 +735,8 @@ function parseRoomToken(body, roomName) {
|
|
|
389
735
|
admissionState: readString(payload, "admission_state") ?? void 0,
|
|
390
736
|
pollSeconds: typeof payload["poll_seconds"] === "number" ? payload["poll_seconds"] : void 0,
|
|
391
737
|
breakoutRoomId: readString(payload, "breakout_room_id") ?? null,
|
|
392
|
-
observersVisibleTo: readString(payload, "observers_visible_to") === "hosts" ? "hosts" : "everyone"
|
|
738
|
+
observersVisibleTo: readString(payload, "observers_visible_to") === "hosts" ? "hosts" : "everyone",
|
|
739
|
+
connectionPolicy: connectionPolicyFrom(payload["connection_policy"])
|
|
393
740
|
};
|
|
394
741
|
}
|
|
395
742
|
function createTokenClient(options) {
|
|
@@ -1119,6 +1466,10 @@ function nextPhase(from, event) {
|
|
|
1119
1466
|
return from === "resolving" && event.reason !== null && isJoinRefusalReason(event.reason) ? refusalPhase(event.reason) : null;
|
|
1120
1467
|
case "join":
|
|
1121
1468
|
return JOINABLE_FROM.has(from) ? "joining" : null;
|
|
1469
|
+
case "auto_rejoin":
|
|
1470
|
+
return from === "disconnected" ? "joining" : null;
|
|
1471
|
+
case "resumed":
|
|
1472
|
+
return from === "resolving" ? "joining" : null;
|
|
1122
1473
|
case "back_to_prejoin":
|
|
1123
1474
|
return from === "left" || from === "disconnected" ? "prejoin" : null;
|
|
1124
1475
|
case "retry":
|
|
@@ -2996,13 +3347,19 @@ function recordingLabel(state) {
|
|
|
2996
3347
|
}
|
|
2997
3348
|
|
|
2998
3349
|
// src/core/attendance.ts
|
|
3350
|
+
var IDLE_MEDIA_REGION = {
|
|
3351
|
+
permission: { microphone: "unknown", camera: "unknown" },
|
|
3352
|
+
audioOutput: "ok",
|
|
3353
|
+
notice: null,
|
|
3354
|
+
offer: null
|
|
3355
|
+
};
|
|
2999
3356
|
var IDLE_TRACK = { enabled: false, unavailable: null };
|
|
3000
3357
|
var IDLE_MEDIA = {
|
|
3001
3358
|
microphone: IDLE_TRACK,
|
|
3002
3359
|
camera: IDLE_TRACK
|
|
3003
3360
|
};
|
|
3004
|
-
function unavailableFrom(error) {
|
|
3005
|
-
return { code: error.code, message: error.message, remedy: error.remedy };
|
|
3361
|
+
function unavailableFrom(error, reason) {
|
|
3362
|
+
return reason === void 0 ? { code: error.code, message: error.message, remedy: error.remedy } : { code: error.code, message: error.message, remedy: error.remedy, reason };
|
|
3006
3363
|
}
|
|
3007
3364
|
var LISTEN_ONLY_NOTICE = "You're attending without a microphone \u2014 others can't hear you";
|
|
3008
3365
|
function isListenOnly(media) {
|
|
@@ -3032,6 +3389,7 @@ var EMPTY = {
|
|
|
3032
3389
|
phaseNotice: null,
|
|
3033
3390
|
roomName: null,
|
|
3034
3391
|
connection: "stable",
|
|
3392
|
+
connectionBanner: false,
|
|
3035
3393
|
share: NO_SHARE,
|
|
3036
3394
|
call: null,
|
|
3037
3395
|
waiting: null,
|
|
@@ -3063,6 +3421,7 @@ var EMPTY = {
|
|
|
3063
3421
|
wrapUp: null,
|
|
3064
3422
|
noteTakerRefusal: null,
|
|
3065
3423
|
media: IDLE_MEDIA,
|
|
3424
|
+
mediaRegion: IDLE_MEDIA_REGION,
|
|
3066
3425
|
failure: null,
|
|
3067
3426
|
collab: EMPTY_COLLAB,
|
|
3068
3427
|
breakoutRoomId: null
|
|
@@ -3280,7 +3639,7 @@ function createMeetStore(initial = {}) {
|
|
|
3280
3639
|
},
|
|
3281
3640
|
setLocalTrack(kind, next) {
|
|
3282
3641
|
const current = state.media[kind];
|
|
3283
|
-
if (current.enabled === next.enabled && current.unavailable?.code === next.unavailable?.code && current.unavailable?.message === next.unavailable?.message) {
|
|
3642
|
+
if (current.enabled === next.enabled && current.unavailable?.code === next.unavailable?.code && current.unavailable?.reason === next.unavailable?.reason && current.unavailable?.message === next.unavailable?.message) {
|
|
3284
3643
|
return;
|
|
3285
3644
|
}
|
|
3286
3645
|
commit({ ...state, media: { ...state.media, [kind]: next } });
|
|
@@ -3986,8 +4345,11 @@ function mapConnectionState(state) {
|
|
|
3986
4345
|
case "connecting":
|
|
3987
4346
|
return "connecting";
|
|
3988
4347
|
case "reconnecting":
|
|
3989
|
-
case "signalReconnecting":
|
|
3990
4348
|
return "reconnecting";
|
|
4349
|
+
// Only the signal socket is down (S6b): its own region value, so the supervisor can tell a
|
|
4350
|
+
// signal blip from a full media reconnect.
|
|
4351
|
+
case "signalReconnecting":
|
|
4352
|
+
return "signal_reconnecting";
|
|
3991
4353
|
default:
|
|
3992
4354
|
return "disconnected";
|
|
3993
4355
|
}
|
|
@@ -4068,8 +4430,12 @@ function createLiveKitDriver(handlers, options = {}) {
|
|
|
4068
4430
|
// R5: large meetings degrade gracefully instead of melting a laptop.
|
|
4069
4431
|
adaptiveStream: true,
|
|
4070
4432
|
dynacast: true,
|
|
4433
|
+
// S6b: OUR retry schedule — jittered from attempt 0 (the SDK's default has no jitter on its
|
|
4434
|
+
// first two attempts), give-up limits in one place (`connection-supervisor.ts`).
|
|
4435
|
+
reconnectPolicy: createReconnectPolicy(),
|
|
4071
4436
|
...options.roomOptions
|
|
4072
4437
|
});
|
|
4438
|
+
const reasonName = (reason) => reason === void 0 || reason === null ? null : module.DisconnectReason?.[reason] ?? String(reason);
|
|
4073
4439
|
const roster = () => {
|
|
4074
4440
|
const local = snapshotParticipant(created.localParticipant, true);
|
|
4075
4441
|
const remotes = [...created.remoteParticipants.values()].map(
|
|
@@ -4087,8 +4453,17 @@ function createLiveKitDriver(handlers, options = {}) {
|
|
|
4087
4453
|
if (track.kind !== Track.Kind.Audio) return;
|
|
4088
4454
|
for (const element of track.detach()) element.remove();
|
|
4089
4455
|
});
|
|
4090
|
-
created.on(RoomEvent.ParticipantConnected, roster).on(RoomEvent.ParticipantDisconnected,
|
|
4456
|
+
created.on(RoomEvent.ParticipantConnected, roster).on(RoomEvent.ParticipantDisconnected, (participant, reason) => {
|
|
4457
|
+
handlers.participantLeft?.(participant.identity, reasonName(reason));
|
|
4458
|
+
roster();
|
|
4459
|
+
}).on(RoomEvent.TrackSubscribed, roster).on(RoomEvent.TrackUnsubscribed, roster).on(RoomEvent.TrackMuted, roster).on(RoomEvent.TrackUnmuted, roster).on(RoomEvent.LocalTrackPublished, roster).on(RoomEvent.LocalTrackUnpublished, roster).on(RoomEvent.ParticipantNameChanged, roster).on(RoomEvent.ParticipantAttributesChanged, roster).on(RoomEvent.ParticipantMetadataChanged, roster).on(RoomEvent.RoomMetadataChanged, (metadata) => {
|
|
4091
4460
|
handlers.roomMetadata?.(metadata ?? "");
|
|
4461
|
+
}).on(RoomEvent.AudioPlaybackStatusChanged, (canPlay) => {
|
|
4462
|
+
handlers.audioPlayback?.(canPlay);
|
|
4463
|
+
}).on(RoomEvent.MediaDevicesChanged, () => {
|
|
4464
|
+
handlers.devicesChanged?.();
|
|
4465
|
+
}).on(RoomEvent.MediaDevicesError, (error, kind) => {
|
|
4466
|
+
handlers.mediaDeviceError?.(error, kind === "audioinput" || kind === "videoinput" ? kind : null);
|
|
4092
4467
|
}).on(RoomEvent.ActiveSpeakersChanged, (speakers) => {
|
|
4093
4468
|
handlers.activeSpeakers(speakers.map((speaker) => speaker.identity));
|
|
4094
4469
|
}).on(RoomEvent.ConnectionQualityChanged, (quality, participant) => {
|
|
@@ -4104,8 +4479,7 @@ function createLiveKitDriver(handlers, options = {}) {
|
|
|
4104
4479
|
}).on(RoomEvent.Disconnected, (reason) => {
|
|
4105
4480
|
audioContainer?.remove();
|
|
4106
4481
|
audioContainer = null;
|
|
4107
|
-
|
|
4108
|
-
handlers.disconnected(named);
|
|
4482
|
+
handlers.disconnected(reasonName(reason));
|
|
4109
4483
|
});
|
|
4110
4484
|
try {
|
|
4111
4485
|
created.registerTextStreamHandler(TRANSCRIPTION_TOPIC, (reader, participantInfo) => {
|
|
@@ -4186,6 +4560,7 @@ function createLiveKitDriver(handlers, options = {}) {
|
|
|
4186
4560
|
}
|
|
4187
4561
|
projectRoster?.();
|
|
4188
4562
|
handlers.roomMetadata?.(target.metadata ?? "");
|
|
4563
|
+
handlers.audioPlayback?.(target.canPlaybackAudio);
|
|
4189
4564
|
},
|
|
4190
4565
|
async disconnect() {
|
|
4191
4566
|
if (room === null) return;
|
|
@@ -4312,6 +4687,11 @@ function createLiveKitDriver(handlers, options = {}) {
|
|
|
4312
4687
|
} catch (error) {
|
|
4313
4688
|
throw normalizeDeviceError(error, "meet.switchDevice");
|
|
4314
4689
|
}
|
|
4690
|
+
},
|
|
4691
|
+
async startAudio() {
|
|
4692
|
+
const target = room;
|
|
4693
|
+
if (target === null) return;
|
|
4694
|
+
await target.startAudio();
|
|
4315
4695
|
}
|
|
4316
4696
|
};
|
|
4317
4697
|
}
|
|
@@ -5407,6 +5787,342 @@ async function pushMeetingToGoogleCalendar(api, meetingId, target) {
|
|
|
5407
5787
|
return await response.json();
|
|
5408
5788
|
}
|
|
5409
5789
|
|
|
5790
|
+
// src/core/media-supervisor.ts
|
|
5791
|
+
function classifyDeviceFailure(error, permission) {
|
|
5792
|
+
if (permission === "denied") return "denied";
|
|
5793
|
+
switch (error.code) {
|
|
5794
|
+
case "permission-denied":
|
|
5795
|
+
if (/by system/i.test(error.message) || permission === "granted") return "blocked_os";
|
|
5796
|
+
return "denied";
|
|
5797
|
+
case "device-not-found":
|
|
5798
|
+
return "none";
|
|
5799
|
+
case "device-in-use":
|
|
5800
|
+
return "busy";
|
|
5801
|
+
case "insecure-context":
|
|
5802
|
+
return "blocked_site";
|
|
5803
|
+
default:
|
|
5804
|
+
return "failed";
|
|
5805
|
+
}
|
|
5806
|
+
}
|
|
5807
|
+
function deviceNoticeCode(kind, reason) {
|
|
5808
|
+
if (reason === "denied" || reason === "blocked_site" || reason === "blocked_os") {
|
|
5809
|
+
return kind === "microphone" ? "mic-blocked" : "camera-blocked";
|
|
5810
|
+
}
|
|
5811
|
+
return "device-lost";
|
|
5812
|
+
}
|
|
5813
|
+
function deviceUnavailableReason(track, permission) {
|
|
5814
|
+
if (track.enabled) return null;
|
|
5815
|
+
if (permission === "denied") return "denied";
|
|
5816
|
+
const refused = track.unavailable;
|
|
5817
|
+
if (refused === null) return null;
|
|
5818
|
+
return refused.reason ?? classifyDeviceFailure({ code: refused.code, message: refused.message }, permission);
|
|
5819
|
+
}
|
|
5820
|
+
function deviceChipLabel(kind, reason) {
|
|
5821
|
+
const what = kind === "microphone" ? "Mic" : "Camera";
|
|
5822
|
+
switch (reason) {
|
|
5823
|
+
case "denied":
|
|
5824
|
+
case "blocked_site":
|
|
5825
|
+
case "blocked_os":
|
|
5826
|
+
return `${what} blocked`;
|
|
5827
|
+
case "none":
|
|
5828
|
+
return kind === "microphone" ? "No microphone found" : "No camera found";
|
|
5829
|
+
case "busy":
|
|
5830
|
+
return `${what} in use by another app`;
|
|
5831
|
+
case "revoked":
|
|
5832
|
+
return `${what} access was turned off`;
|
|
5833
|
+
default:
|
|
5834
|
+
return `${what} didn't start`;
|
|
5835
|
+
}
|
|
5836
|
+
}
|
|
5837
|
+
function deviceFixSteps(kind, reason, where) {
|
|
5838
|
+
const device = kind === "microphone" ? "Microphone" : "Camera";
|
|
5839
|
+
const lower = device.toLowerCase();
|
|
5840
|
+
switch (reason) {
|
|
5841
|
+
case "denied":
|
|
5842
|
+
case "revoked":
|
|
5843
|
+
case "blocked_site":
|
|
5844
|
+
switch (where.browser) {
|
|
5845
|
+
case "firefox":
|
|
5846
|
+
return [`Click the crossed-out ${lower} icon in the address bar`, "Clear the Blocked setting", "Press Try again and choose Allow"];
|
|
5847
|
+
case "safari":
|
|
5848
|
+
return where.os === "ios" ? [`Settings \u203A Apps \u203A Safari \u203A ${device}`, "Choose Allow", "Return here and press Try again"] : ["Safari \u203A Settings for This Website", `Set ${device} to Allow`, "Press Try again"];
|
|
5849
|
+
default:
|
|
5850
|
+
return ["Click the icon left of the web address", `Set ${device} to Allow`, "Press Try again"];
|
|
5851
|
+
}
|
|
5852
|
+
case "blocked_os": {
|
|
5853
|
+
const app = where.browser === "chrome" ? "Google Chrome" : where.browser === "edge" ? "Microsoft Edge" : where.browser === "firefox" ? "Firefox" : "your browser";
|
|
5854
|
+
if (where.os === "mac") return [`System Settings \u203A Privacy & Security \u203A ${device}`, `Turn on ${app}`, "Reopen the browser if asked, then Try again"];
|
|
5855
|
+
if (where.os === "windows") return [`Settings \u203A Privacy & security \u203A ${device}`, `Turn on ${device} access for apps`, "Press Try again"];
|
|
5856
|
+
return [`Allow ${lower} access for ${app} in your system settings`, "Press Try again"];
|
|
5857
|
+
}
|
|
5858
|
+
case "busy":
|
|
5859
|
+
return [`Close other apps using the ${lower} (Zoom, Teams, another tab)`, "Press Try again"];
|
|
5860
|
+
case "none":
|
|
5861
|
+
return [`Connect a ${lower}`, "Press Try again"];
|
|
5862
|
+
default:
|
|
5863
|
+
return [`Pick another ${lower} in Settings`, "Press Try again"];
|
|
5864
|
+
}
|
|
5865
|
+
}
|
|
5866
|
+
function detectBrowser(userAgent) {
|
|
5867
|
+
if (/Edg\//.test(userAgent)) return "edge";
|
|
5868
|
+
if (/Firefox\//.test(userAgent)) return "firefox";
|
|
5869
|
+
if (/Chrome\/|Chromium\/|CriOS\//.test(userAgent)) return "chrome";
|
|
5870
|
+
if (/Safari\//.test(userAgent)) return "safari";
|
|
5871
|
+
return "other";
|
|
5872
|
+
}
|
|
5873
|
+
function detectOs(userAgent, maxTouchPoints = 0) {
|
|
5874
|
+
if (/iPhone|iPad|iPod/.test(userAgent)) return "ios";
|
|
5875
|
+
if (/Macintosh/.test(userAgent)) return maxTouchPoints > 1 ? "ios" : "mac";
|
|
5876
|
+
if (/Android/.test(userAgent)) return "android";
|
|
5877
|
+
if (/Windows/.test(userAgent)) return "windows";
|
|
5878
|
+
if (/Linux|CrOS/.test(userAgent)) return "linux";
|
|
5879
|
+
return "other";
|
|
5880
|
+
}
|
|
5881
|
+
function webMediaPlatform() {
|
|
5882
|
+
const scope = globalThis;
|
|
5883
|
+
const nav = scope.navigator;
|
|
5884
|
+
if (nav === void 0) return null;
|
|
5885
|
+
const ua = nav.userAgent ?? "";
|
|
5886
|
+
const reading = (state) => state === "granted" || state === "denied" || state === "prompt" ? state : "unknown";
|
|
5887
|
+
const query = async (kind) => {
|
|
5888
|
+
try {
|
|
5889
|
+
return await nav.permissions?.query({ name: kind }) ?? null;
|
|
5890
|
+
} catch {
|
|
5891
|
+
return null;
|
|
5892
|
+
}
|
|
5893
|
+
};
|
|
5894
|
+
return {
|
|
5895
|
+
browser: detectBrowser(ua),
|
|
5896
|
+
os: detectOs(ua, nav.maxTouchPoints ?? 0),
|
|
5897
|
+
async queryPermission(kind) {
|
|
5898
|
+
return reading((await query(kind))?.state);
|
|
5899
|
+
},
|
|
5900
|
+
watchPermission(kind, onChange) {
|
|
5901
|
+
let status = null;
|
|
5902
|
+
let stopped = false;
|
|
5903
|
+
void query(kind).then((found) => {
|
|
5904
|
+
if (stopped || found === null) return;
|
|
5905
|
+
status = found;
|
|
5906
|
+
found.onchange = () => onChange(reading(found.state));
|
|
5907
|
+
});
|
|
5908
|
+
return () => {
|
|
5909
|
+
stopped = true;
|
|
5910
|
+
if (status !== null) status.onchange = null;
|
|
5911
|
+
};
|
|
5912
|
+
},
|
|
5913
|
+
async listDevices() {
|
|
5914
|
+
try {
|
|
5915
|
+
return await nav.mediaDevices?.enumerateDevices() ?? [];
|
|
5916
|
+
} catch {
|
|
5917
|
+
return [];
|
|
5918
|
+
}
|
|
5919
|
+
},
|
|
5920
|
+
onVisible(callback) {
|
|
5921
|
+
const doc = scope.document;
|
|
5922
|
+
if (doc === void 0) return () => void 0;
|
|
5923
|
+
const handler = () => {
|
|
5924
|
+
if (doc.visibilityState === "visible") callback();
|
|
5925
|
+
};
|
|
5926
|
+
doc.addEventListener("visibilitychange", handler);
|
|
5927
|
+
return () => doc.removeEventListener("visibilitychange", handler);
|
|
5928
|
+
}
|
|
5929
|
+
};
|
|
5930
|
+
}
|
|
5931
|
+
var INPUT_KIND = { microphone: "audioinput", camera: "videoinput" };
|
|
5932
|
+
function isAlias(deviceId) {
|
|
5933
|
+
return deviceId === "default" || deviceId === "communications" || deviceId === "";
|
|
5934
|
+
}
|
|
5935
|
+
function createMediaSupervisor(options) {
|
|
5936
|
+
const { store, platform } = options;
|
|
5937
|
+
let unsubscribers = [];
|
|
5938
|
+
let started = false;
|
|
5939
|
+
let noticeId = 0;
|
|
5940
|
+
let known = null;
|
|
5941
|
+
let inUse = { audioinput: null, videoinput: null };
|
|
5942
|
+
function region() {
|
|
5943
|
+
return store.snapshot().mediaRegion;
|
|
5944
|
+
}
|
|
5945
|
+
function setRegion(next) {
|
|
5946
|
+
const current = region();
|
|
5947
|
+
const merged = { ...current, ...next };
|
|
5948
|
+
if (merged.audioOutput === current.audioOutput && merged.notice === current.notice && merged.offer === current.offer && merged.permission.microphone === current.permission.microphone && merged.permission.camera === current.permission.camera) {
|
|
5949
|
+
return;
|
|
5950
|
+
}
|
|
5951
|
+
store.patch({ mediaRegion: merged });
|
|
5952
|
+
}
|
|
5953
|
+
function setPermission(kind, reading) {
|
|
5954
|
+
const current = region().permission;
|
|
5955
|
+
if (current[kind] === reading) return;
|
|
5956
|
+
setRegion({ permission: { ...current, [kind]: reading } });
|
|
5957
|
+
const track = store.snapshot().media[kind];
|
|
5958
|
+
if (reading === "granted" && !track.enabled && track.unavailable?.reason === "denied") {
|
|
5959
|
+
store.setLocalTrack(kind, {
|
|
5960
|
+
enabled: false,
|
|
5961
|
+
unavailable: { ...track.unavailable, reason: "failed", remedy: "Access is allowed now. Press Try again." }
|
|
5962
|
+
});
|
|
5963
|
+
}
|
|
5964
|
+
}
|
|
5965
|
+
async function snapshotDevices() {
|
|
5966
|
+
const list = platform === null ? [] : await platform.listDevices();
|
|
5967
|
+
const out = { audioinput: /* @__PURE__ */ new Map(), videoinput: /* @__PURE__ */ new Map() };
|
|
5968
|
+
for (const device of list) {
|
|
5969
|
+
if (device.kind === "audioinput" || device.kind === "videoinput") out[device.kind].set(device.deviceId, device.label);
|
|
5970
|
+
}
|
|
5971
|
+
return out;
|
|
5972
|
+
}
|
|
5973
|
+
function readInUse() {
|
|
5974
|
+
const driver = options.driver();
|
|
5975
|
+
if (driver === null) return;
|
|
5976
|
+
const active = driver.activeDevices();
|
|
5977
|
+
inUse = { audioinput: active.audioinput, videoinput: active.videoinput };
|
|
5978
|
+
}
|
|
5979
|
+
async function handleDevicesChanged() {
|
|
5980
|
+
if (platform === null) return;
|
|
5981
|
+
const before = known;
|
|
5982
|
+
const now = await snapshotDevices();
|
|
5983
|
+
known = now;
|
|
5984
|
+
const driver = options.driver();
|
|
5985
|
+
if (driver === null || before === null) {
|
|
5986
|
+
readInUse();
|
|
5987
|
+
return;
|
|
5988
|
+
}
|
|
5989
|
+
for (const kind of ["microphone", "camera"]) {
|
|
5990
|
+
const deviceKind = INPUT_KIND[kind];
|
|
5991
|
+
const previous = inUse[deviceKind];
|
|
5992
|
+
const track = store.snapshot().media[kind];
|
|
5993
|
+
const gone = previous !== null && !isAlias(previous) && before[deviceKind].has(previous) && !now[deviceKind].has(previous);
|
|
5994
|
+
if (gone) {
|
|
5995
|
+
const from = before[deviceKind].get(previous) ?? "";
|
|
5996
|
+
const remaining = [...now[deviceKind].entries()].filter(([id]) => !isAlias(id));
|
|
5997
|
+
if (remaining.length === 0) {
|
|
5998
|
+
store.setLocalTrack(kind, {
|
|
5999
|
+
enabled: false,
|
|
6000
|
+
unavailable: {
|
|
6001
|
+
code: "device-not-found",
|
|
6002
|
+
message: `meet.${kind}: the ${kind} was disconnected and no other is connected`,
|
|
6003
|
+
remedy: `Connect a ${kind === "microphone" ? "microphone" : "camera"}, then press Try again.`,
|
|
6004
|
+
reason: "none"
|
|
6005
|
+
}
|
|
6006
|
+
});
|
|
6007
|
+
setRegion({ notice: { id: ++noticeId, kind, outcome: "lost", from, to: null } });
|
|
6008
|
+
continue;
|
|
6009
|
+
}
|
|
6010
|
+
if (kind === "camera") {
|
|
6011
|
+
const [nextId, nextLabel] = remaining[0];
|
|
6012
|
+
try {
|
|
6013
|
+
await driver.switchDevice("videoinput", nextId);
|
|
6014
|
+
if (track.enabled || track.unavailable !== null) {
|
|
6015
|
+
await driver.setCameraEnabled(true);
|
|
6016
|
+
store.setLocalTrack("camera", { enabled: true, unavailable: null });
|
|
6017
|
+
}
|
|
6018
|
+
setRegion({ notice: { id: ++noticeId, kind, outcome: "switched", from, to: nextLabel } });
|
|
6019
|
+
} catch (error) {
|
|
6020
|
+
const refused = await unavailable(error, "camera", "meet.camera(fallback)");
|
|
6021
|
+
store.setLocalTrack("camera", { enabled: false, unavailable: refused });
|
|
6022
|
+
setRegion({ notice: { id: ++noticeId, kind, outcome: "lost", from, to: null } });
|
|
6023
|
+
}
|
|
6024
|
+
} else {
|
|
6025
|
+
const active = driver.activeDevices().audioinput;
|
|
6026
|
+
const to = (active !== null ? now.audioinput.get(active) : void 0) ?? now.audioinput.get("default") ?? remaining[0][1];
|
|
6027
|
+
setRegion({ notice: { id: ++noticeId, kind, outcome: "switched", from, to } });
|
|
6028
|
+
}
|
|
6029
|
+
continue;
|
|
6030
|
+
}
|
|
6031
|
+
const added = [...now[deviceKind].entries()].find(([id]) => !isAlias(id) && !before[deviceKind].has(id));
|
|
6032
|
+
if (added !== void 0 && added[0] !== driver.activeDevices()[deviceKind]) {
|
|
6033
|
+
setRegion({ offer: { kind, deviceId: added[0], label: added[1] } });
|
|
6034
|
+
}
|
|
6035
|
+
}
|
|
6036
|
+
readInUse();
|
|
6037
|
+
}
|
|
6038
|
+
async function unavailable(error, kind, operation) {
|
|
6039
|
+
const normalized = normalizeDeviceError(error, operation);
|
|
6040
|
+
const permission = platform === null ? "unknown" : await platform.queryPermission(kind);
|
|
6041
|
+
if (permission !== "unknown") setPermission(kind, permission);
|
|
6042
|
+
return unavailableFrom(normalized, classifyDeviceFailure(normalized, permission));
|
|
6043
|
+
}
|
|
6044
|
+
return {
|
|
6045
|
+
start() {
|
|
6046
|
+
if (started || platform === null) return;
|
|
6047
|
+
started = true;
|
|
6048
|
+
for (const kind of ["microphone", "camera"]) {
|
|
6049
|
+
void platform.queryPermission(kind).then((reading) => setPermission(kind, reading));
|
|
6050
|
+
unsubscribers.push(platform.watchPermission(kind, (reading) => setPermission(kind, reading)));
|
|
6051
|
+
}
|
|
6052
|
+
unsubscribers.push(
|
|
6053
|
+
platform.onVisible(() => {
|
|
6054
|
+
const driver = options.driver();
|
|
6055
|
+
if (driver?.startAudio === void 0 || region().audioOutput !== "blocked") return;
|
|
6056
|
+
driver.startAudio().catch(() => void 0);
|
|
6057
|
+
})
|
|
6058
|
+
);
|
|
6059
|
+
},
|
|
6060
|
+
stop() {
|
|
6061
|
+
for (const off of unsubscribers) off();
|
|
6062
|
+
unsubscribers = [];
|
|
6063
|
+
started = false;
|
|
6064
|
+
},
|
|
6065
|
+
unavailable,
|
|
6066
|
+
onAudioPlayback(canPlay) {
|
|
6067
|
+
setRegion({ audioOutput: canPlay ? "ok" : "blocked" });
|
|
6068
|
+
},
|
|
6069
|
+
onDevicesChanged() {
|
|
6070
|
+
void handleDevicesChanged().catch((error) => {
|
|
6071
|
+
options.report("warn", `meet: device change could not be handled: ${String(error)}`, "Pick the device in Settings.");
|
|
6072
|
+
});
|
|
6073
|
+
},
|
|
6074
|
+
onDeviceError(error, deviceKind) {
|
|
6075
|
+
if (deviceKind === null) return;
|
|
6076
|
+
const kind = deviceKind === "audioinput" ? "microphone" : "camera";
|
|
6077
|
+
void unavailable(error, kind, `meet.${kind}`).then((refused) => {
|
|
6078
|
+
const track = store.snapshot().media[kind];
|
|
6079
|
+
if (track.enabled) return;
|
|
6080
|
+
store.setLocalTrack(kind, { enabled: false, unavailable: refused });
|
|
6081
|
+
});
|
|
6082
|
+
},
|
|
6083
|
+
onConnected() {
|
|
6084
|
+
void snapshotDevices().then((now) => {
|
|
6085
|
+
known = now;
|
|
6086
|
+
readInUse();
|
|
6087
|
+
});
|
|
6088
|
+
},
|
|
6089
|
+
onDisconnected() {
|
|
6090
|
+
known = null;
|
|
6091
|
+
inUse = { audioinput: null, videoinput: null };
|
|
6092
|
+
setRegion({ audioOutput: "ok", notice: null, offer: null });
|
|
6093
|
+
},
|
|
6094
|
+
async enableAudio() {
|
|
6095
|
+
const driver = options.driver();
|
|
6096
|
+
if (driver?.startAudio === void 0) return;
|
|
6097
|
+
try {
|
|
6098
|
+
await driver.startAudio();
|
|
6099
|
+
setRegion({ audioOutput: "ok" });
|
|
6100
|
+
} catch (error) {
|
|
6101
|
+
options.report("warn", `meet: sound could not be enabled: ${String(error)}`, "Click Enable sound again, or check the tab is not muted.");
|
|
6102
|
+
}
|
|
6103
|
+
},
|
|
6104
|
+
async acceptOffer() {
|
|
6105
|
+
const offer = region().offer;
|
|
6106
|
+
const driver = options.driver();
|
|
6107
|
+
setRegion({ offer: null });
|
|
6108
|
+
if (offer === null || driver === null) return;
|
|
6109
|
+
try {
|
|
6110
|
+
await driver.switchDevice(INPUT_KIND[offer.kind], offer.deviceId);
|
|
6111
|
+
readInUse();
|
|
6112
|
+
} catch (error) {
|
|
6113
|
+
const refused = await unavailable(error, offer.kind, "meet.switchDevice");
|
|
6114
|
+
options.report("warn", refused.message, refused.remedy);
|
|
6115
|
+
}
|
|
6116
|
+
},
|
|
6117
|
+
dismissOffer() {
|
|
6118
|
+
setRegion({ offer: null });
|
|
6119
|
+
},
|
|
6120
|
+
dismissNotice() {
|
|
6121
|
+
setRegion({ notice: null });
|
|
6122
|
+
}
|
|
6123
|
+
};
|
|
6124
|
+
}
|
|
6125
|
+
|
|
5410
6126
|
// src/core/room.ts
|
|
5411
6127
|
function SCREEN_SHARE_BLOCKED_REMEDY_FOR(remedy) {
|
|
5412
6128
|
return /administrator|policy/i.test(remedy) ? remedy : SCREEN_SHARE_BLOCKED_REMEDY;
|
|
@@ -5478,6 +6194,18 @@ function createRoomEngine(options) {
|
|
|
5478
6194
|
let disposed = false;
|
|
5479
6195
|
let moving = false;
|
|
5480
6196
|
const confirmingEnds = /* @__PURE__ */ new WeakSet();
|
|
6197
|
+
let lastServerUrl = null;
|
|
6198
|
+
let connectionPolicy = DEFAULT_CONNECTION_POLICY;
|
|
6199
|
+
let ghosts = /* @__PURE__ */ new Map();
|
|
6200
|
+
let ghostTimer = null;
|
|
6201
|
+
let liveRoster = [];
|
|
6202
|
+
const departures = /* @__PURE__ */ new Map();
|
|
6203
|
+
function requestAsNow() {
|
|
6204
|
+
if (lastRequest === null) return null;
|
|
6205
|
+
const media2 = store.snapshot().media;
|
|
6206
|
+
if (store.snapshot().phase !== "in_call") return lastRequest;
|
|
6207
|
+
return { ...lastRequest, mode: media2.camera.enabled ? "video" : "audio", microphone: media2.microphone.enabled };
|
|
6208
|
+
}
|
|
5481
6209
|
async function dropRoom() {
|
|
5482
6210
|
const target = driver;
|
|
5483
6211
|
driver = null;
|
|
@@ -5487,7 +6215,9 @@ function createRoomEngine(options) {
|
|
|
5487
6215
|
}
|
|
5488
6216
|
store.setLocalTrack("microphone", IDLE_TRACK);
|
|
5489
6217
|
store.setLocalTrack("camera", IDLE_TRACK);
|
|
6218
|
+
media.onDisconnected();
|
|
5490
6219
|
store.patch({ share: NO_SHARE, connection: "stable" });
|
|
6220
|
+
clearGhosts();
|
|
5491
6221
|
await target?.disconnect();
|
|
5492
6222
|
}
|
|
5493
6223
|
async function leaveRoom() {
|
|
@@ -5551,11 +6281,26 @@ function createRoomEngine(options) {
|
|
|
5551
6281
|
report("error", normalized.message, normalized.remedy);
|
|
5552
6282
|
return normalized;
|
|
5553
6283
|
}
|
|
6284
|
+
const media = createMediaSupervisor({
|
|
6285
|
+
store,
|
|
6286
|
+
platform: options.mediaPlatform === void 0 ? webMediaPlatform() : options.mediaPlatform,
|
|
6287
|
+
driver: () => driver,
|
|
6288
|
+
report
|
|
6289
|
+
});
|
|
5554
6290
|
const handlers = {
|
|
6291
|
+
audioPlayback(canPlay) {
|
|
6292
|
+
media.onAudioPlayback(canPlay);
|
|
6293
|
+
},
|
|
6294
|
+
devicesChanged() {
|
|
6295
|
+
media.onDevicesChanged();
|
|
6296
|
+
},
|
|
6297
|
+
mediaDeviceError(error, kind) {
|
|
6298
|
+
media.onDeviceError(error, kind);
|
|
6299
|
+
},
|
|
5555
6300
|
participants(list) {
|
|
5556
6301
|
const joinedAt = new Date(now()).toISOString();
|
|
5557
6302
|
const before = new Set(store.snapshot().participants.map((p) => p.identity));
|
|
5558
|
-
|
|
6303
|
+
projectRoster(list, joinedAt);
|
|
5559
6304
|
const snapshot = store.snapshot();
|
|
5560
6305
|
const newcomer = snapshot.participants.some(
|
|
5561
6306
|
(participant) => !participant.isLocal && !before.has(participant.identity)
|
|
@@ -5567,6 +6312,9 @@ function createRoomEngine(options) {
|
|
|
5567
6312
|
);
|
|
5568
6313
|
}
|
|
5569
6314
|
},
|
|
6315
|
+
participantLeft(who, reason) {
|
|
6316
|
+
departures.set(who, reason);
|
|
6317
|
+
},
|
|
5570
6318
|
roomMetadata(metadata) {
|
|
5571
6319
|
let spotlight = null;
|
|
5572
6320
|
if (metadata.length > 0) {
|
|
@@ -5593,12 +6341,8 @@ function createRoomEngine(options) {
|
|
|
5593
6341
|
store.setQuality(asParticipantIdentity(who), value);
|
|
5594
6342
|
},
|
|
5595
6343
|
connectionState(state) {
|
|
5596
|
-
|
|
5597
|
-
|
|
5598
|
-
store.dispatch({ type: "connected" });
|
|
5599
|
-
} else if (state === "reconnecting") {
|
|
5600
|
-
store.patch({ connection: "reconnecting" });
|
|
5601
|
-
}
|
|
6344
|
+
supervisor.driverState(state);
|
|
6345
|
+
if (state === "connected" && store.snapshot().phase === "joining") store.dispatch({ type: "connected" });
|
|
5602
6346
|
},
|
|
5603
6347
|
transcription(event) {
|
|
5604
6348
|
const snapshot = store.snapshot();
|
|
@@ -5731,6 +6475,7 @@ function createRoomEngine(options) {
|
|
|
5731
6475
|
};
|
|
5732
6476
|
async function resolveExitAndApply(hint) {
|
|
5733
6477
|
const connection = current?.identity ?? store.snapshot().localIdentity ?? null;
|
|
6478
|
+
lastRequest = requestAsNow();
|
|
5734
6479
|
await dropRoom();
|
|
5735
6480
|
let server;
|
|
5736
6481
|
if (options.readExit === void 0 || connection === null || store.snapshot().meeting === null) {
|
|
@@ -5744,7 +6489,7 @@ function createRoomEngine(options) {
|
|
|
5744
6489
|
}
|
|
5745
6490
|
if (disposed) return;
|
|
5746
6491
|
const resolved = resolveExit({ server, hint, frozen: options.wasFrozen?.() ?? false });
|
|
5747
|
-
store.patch({ connection: resolved.connection });
|
|
6492
|
+
store.patch({ connection: server === null ? supervisor.exitConnection() : resolved.connection });
|
|
5748
6493
|
if (resolved.to === "waiting:knocking") {
|
|
5749
6494
|
store.patch({
|
|
5750
6495
|
waiting: {
|
|
@@ -5776,6 +6521,8 @@ function createRoomEngine(options) {
|
|
|
5776
6521
|
...request.observe === true ? { observe: true } : {}
|
|
5777
6522
|
});
|
|
5778
6523
|
current = token;
|
|
6524
|
+
lastServerUrl = token.serverUrl;
|
|
6525
|
+
connectionPolicy = token.connectionPolicy ?? DEFAULT_CONNECTION_POLICY;
|
|
5779
6526
|
store.patch({
|
|
5780
6527
|
localIdentity: token.identity,
|
|
5781
6528
|
breakoutRoomId: token.breakoutRoomId ?? null,
|
|
@@ -5815,6 +6562,7 @@ function createRoomEngine(options) {
|
|
|
5815
6562
|
store.dispatch({ type: "connected" });
|
|
5816
6563
|
store.setLocalTrack("microphone", IDLE_TRACK);
|
|
5817
6564
|
store.setLocalTrack("camera", IDLE_TRACK);
|
|
6565
|
+
media.start();
|
|
5818
6566
|
const effects = options.effectsStorage?.load() ?? store.snapshot().effects;
|
|
5819
6567
|
store.patch({ effects });
|
|
5820
6568
|
if (!effects.noiseSuppression || effects.background !== "none") {
|
|
@@ -5839,6 +6587,7 @@ function createRoomEngine(options) {
|
|
|
5839
6587
|
if (request.microphone !== false) {
|
|
5840
6588
|
await enableTrack(created, "microphone", true);
|
|
5841
6589
|
}
|
|
6590
|
+
media.onConnected();
|
|
5842
6591
|
}
|
|
5843
6592
|
async function enableTrack(target, kind, enabled) {
|
|
5844
6593
|
try {
|
|
@@ -5848,10 +6597,10 @@ function createRoomEngine(options) {
|
|
|
5848
6597
|
store.setLocalTrack(kind, state);
|
|
5849
6598
|
return state;
|
|
5850
6599
|
} catch (error) {
|
|
5851
|
-
const
|
|
5852
|
-
const state = { enabled: false, unavailable:
|
|
6600
|
+
const refused = await media.unavailable(error, kind, `meet.${kind}`);
|
|
6601
|
+
const state = { enabled: false, unavailable: refused };
|
|
5853
6602
|
store.setLocalTrack(kind, state);
|
|
5854
|
-
report("warn",
|
|
6603
|
+
report("warn", refused.message, refused.remedy);
|
|
5855
6604
|
return state;
|
|
5856
6605
|
}
|
|
5857
6606
|
}
|
|
@@ -5880,7 +6629,59 @@ function createRoomEngine(options) {
|
|
|
5880
6629
|
throw normalized;
|
|
5881
6630
|
}
|
|
5882
6631
|
}
|
|
5883
|
-
|
|
6632
|
+
function projectRoster(list, joinedAt) {
|
|
6633
|
+
const at = now();
|
|
6634
|
+
const previous = new Map(liveRoster.map((p) => [p.identity, p]));
|
|
6635
|
+
const present = new Set(list.map((p) => p.identity));
|
|
6636
|
+
const graceMs = connectionPolicy.reconnectGraceSeconds * 1e3;
|
|
6637
|
+
for (const [who, reason] of departures) {
|
|
6638
|
+
const last = previous.get(who);
|
|
6639
|
+
if (last !== void 0 && !last.isLocal && !present.has(who) && graceMs > 0 && isUnannouncedDeparture(reason)) {
|
|
6640
|
+
ghosts.set(who, { participant: last, until: at + graceMs });
|
|
6641
|
+
}
|
|
6642
|
+
}
|
|
6643
|
+
departures.clear();
|
|
6644
|
+
liveRoster = list;
|
|
6645
|
+
const merged = mergeGhosts(list, ghosts, at);
|
|
6646
|
+
ghosts = merged.kept;
|
|
6647
|
+
store.setParticipants(
|
|
6648
|
+
merged.roster.map((entry) => {
|
|
6649
|
+
const projected = projectParticipant(entry, joinedAt);
|
|
6650
|
+
return entry.reconnecting === true ? { ...projected, reconnecting: true, quality: "lost" } : projected;
|
|
6651
|
+
})
|
|
6652
|
+
);
|
|
6653
|
+
scheduleGhostExpiry();
|
|
6654
|
+
}
|
|
6655
|
+
function scheduleGhostExpiry() {
|
|
6656
|
+
if (ghostTimer !== null) clearTimeout(ghostTimer);
|
|
6657
|
+
ghostTimer = null;
|
|
6658
|
+
if (ghosts.size === 0 || disposed) return;
|
|
6659
|
+
const next = Math.min(...[...ghosts.values()].map((g) => g.until));
|
|
6660
|
+
ghostTimer = setTimeout(() => {
|
|
6661
|
+
ghostTimer = null;
|
|
6662
|
+
if (disposed || driver === null) return;
|
|
6663
|
+
projectRoster(liveRoster, new Date(now()).toISOString());
|
|
6664
|
+
}, Math.max(0, next - now()) + 50);
|
|
6665
|
+
}
|
|
6666
|
+
function clearGhosts() {
|
|
6667
|
+
ghosts = /* @__PURE__ */ new Map();
|
|
6668
|
+
departures.clear();
|
|
6669
|
+
liveRoster = [];
|
|
6670
|
+
if (ghostTimer !== null) clearTimeout(ghostTimer);
|
|
6671
|
+
ghostTimer = null;
|
|
6672
|
+
}
|
|
6673
|
+
const supervisor = createConnectionSupervisor({
|
|
6674
|
+
store,
|
|
6675
|
+
network: options.connection?.network ?? createWebNetworkPort(),
|
|
6676
|
+
probe: () => options.connection?.probe?.(current?.serverUrl ?? lastServerUrl) ?? Promise.resolve(true),
|
|
6677
|
+
policy: () => connectionPolicy,
|
|
6678
|
+
autoRejoin: () => engine.autoRejoin(),
|
|
6679
|
+
currentRequest: requestAsNow,
|
|
6680
|
+
resume: options.connection?.resume,
|
|
6681
|
+
now,
|
|
6682
|
+
report: (level, message) => report(level, message)
|
|
6683
|
+
});
|
|
6684
|
+
const engine = {
|
|
5884
6685
|
join(request) {
|
|
5885
6686
|
if (joining !== null) return joining;
|
|
5886
6687
|
if (store.snapshot().phase !== "joining" && !store.dispatch({ type: "join", click: true })) {
|
|
@@ -5925,6 +6726,35 @@ function createRoomEngine(options) {
|
|
|
5925
6726
|
});
|
|
5926
6727
|
return joining;
|
|
5927
6728
|
},
|
|
6729
|
+
async autoRejoin() {
|
|
6730
|
+
const request = lastRequest;
|
|
6731
|
+
if (request === null || joining !== null) return joining ?? void 0;
|
|
6732
|
+
if (!store.dispatch({ type: "auto_rejoin" })) return;
|
|
6733
|
+
tokens.invalidate(request.roomName);
|
|
6734
|
+
current = null;
|
|
6735
|
+
joining = connect(request).catch((error) => {
|
|
6736
|
+
throw failJoin(error, "meet.autoRejoin");
|
|
6737
|
+
}).finally(() => {
|
|
6738
|
+
joining = null;
|
|
6739
|
+
});
|
|
6740
|
+
return joining;
|
|
6741
|
+
},
|
|
6742
|
+
resume(roomName) {
|
|
6743
|
+
const marker = supervisor.resumable(roomName);
|
|
6744
|
+
if (marker === null || joining !== null) return false;
|
|
6745
|
+
if (!store.dispatch({ type: "resumed" })) return false;
|
|
6746
|
+
lastRequest = { ...marker.request, roomName };
|
|
6747
|
+
report("info", "meet: this tab was in the call before the page reloaded \u2014 rejoining");
|
|
6748
|
+
tokens.invalidate(roomName);
|
|
6749
|
+
current = null;
|
|
6750
|
+
joining = connect(lastRequest).catch((error) => {
|
|
6751
|
+
throw failJoin(error, "meet.resume");
|
|
6752
|
+
}).finally(() => {
|
|
6753
|
+
joining = null;
|
|
6754
|
+
});
|
|
6755
|
+
joining.catch(() => void 0);
|
|
6756
|
+
return true;
|
|
6757
|
+
},
|
|
5928
6758
|
async moveToBreakout(roomId) {
|
|
5929
6759
|
const request = lastRequest;
|
|
5930
6760
|
if (request === null || driver === null) {
|
|
@@ -6079,6 +6909,10 @@ function createRoomEngine(options) {
|
|
|
6079
6909
|
if (driver === null) return;
|
|
6080
6910
|
await driver.switchDevice(kind, deviceId);
|
|
6081
6911
|
},
|
|
6912
|
+
enableAudio: () => media.enableAudio(),
|
|
6913
|
+
acceptDeviceOffer: () => media.acceptOffer(),
|
|
6914
|
+
dismissDeviceOffer: () => media.dismissOffer(),
|
|
6915
|
+
dismissDeviceNotice: () => media.dismissNotice(),
|
|
6082
6916
|
pin(who) {
|
|
6083
6917
|
store.patch({ pinned: who, layout: who === null ? "grid" : "speaker" });
|
|
6084
6918
|
},
|
|
@@ -6092,6 +6926,9 @@ function createRoomEngine(options) {
|
|
|
6092
6926
|
token: () => current,
|
|
6093
6927
|
async dispose() {
|
|
6094
6928
|
disposed = true;
|
|
6929
|
+
supervisor.dispose();
|
|
6930
|
+
media.stop();
|
|
6931
|
+
clearGhosts();
|
|
6095
6932
|
if (driver !== null) {
|
|
6096
6933
|
const target = driver;
|
|
6097
6934
|
driver = null;
|
|
@@ -6100,6 +6937,7 @@ function createRoomEngine(options) {
|
|
|
6100
6937
|
store.reset();
|
|
6101
6938
|
}
|
|
6102
6939
|
};
|
|
6940
|
+
return engine;
|
|
6103
6941
|
}
|
|
6104
6942
|
function canModerate(participant) {
|
|
6105
6943
|
return participant !== void 0 && isHostRole(participant.role);
|
|
@@ -7074,22 +7912,10 @@ function observedRole(role, standing) {
|
|
|
7074
7912
|
if (role === "host" || role === "cohost") return role;
|
|
7075
7913
|
return isLinkFollower(standing) ? "guest" : "participant";
|
|
7076
7914
|
}
|
|
7077
|
-
function observedDevice(track) {
|
|
7915
|
+
function observedDevice(track, permission = "unknown") {
|
|
7078
7916
|
if (track.enabled) return "on";
|
|
7079
|
-
const
|
|
7080
|
-
|
|
7081
|
-
switch (refused.code) {
|
|
7082
|
-
case "permission-denied":
|
|
7083
|
-
return "unavailable:denied";
|
|
7084
|
-
case "device-not-found":
|
|
7085
|
-
return "unavailable:none";
|
|
7086
|
-
case "device-in-use":
|
|
7087
|
-
return "unavailable:busy";
|
|
7088
|
-
case "insecure-context":
|
|
7089
|
-
return "unavailable:blocked_site";
|
|
7090
|
-
default:
|
|
7091
|
-
return "unavailable:failed";
|
|
7092
|
-
}
|
|
7917
|
+
const reason = deviceUnavailableReason(track, permission);
|
|
7918
|
+
return reason === null ? "muted_by_me" : `unavailable:${reason}`;
|
|
7093
7919
|
}
|
|
7094
7920
|
function endedRecord(snapshot, given) {
|
|
7095
7921
|
const record = snapshot?.meeting ?? given;
|
|
@@ -7122,9 +7948,10 @@ function observe(input) {
|
|
|
7122
7948
|
hostPresent: inCall && snapshot !== null ? snapshot.participants.some((p) => ADMITTER_ROLES.has(p.role)) : snapshot !== null && isWaitingPhase(snapshot.phase) ? snapshot.waiting?.admittersPresent ?? null : null,
|
|
7123
7949
|
lobbyCount: canAdmit && snapshot !== null ? snapshot.lobby.filter((entry) => entry.state === "knocking").length : 0,
|
|
7124
7950
|
recording: snapshot?.recording === "recording" || snapshot?.recording === "stopping",
|
|
7125
|
-
|
|
7126
|
-
|
|
7127
|
-
|
|
7951
|
+
// S6c: the autoplay region is known only inside the room (no remote audio exists elsewhere).
|
|
7952
|
+
audioBlocked: inCall && snapshot !== null ? snapshot.mediaRegion.audioOutput === "blocked" : null,
|
|
7953
|
+
camera: deviceInPlay && snapshot !== null ? observedDevice(snapshot.media.camera, snapshot.mediaRegion.permission.camera) : null,
|
|
7954
|
+
microphone: deviceInPlay && snapshot !== null ? observedDevice(snapshot.media.microphone, snapshot.mediaRegion.permission.microphone) : null
|
|
7128
7955
|
};
|
|
7129
7956
|
}
|
|
7130
7957
|
function staticObservation(phase, reason = null) {
|
|
@@ -7185,14 +8012,14 @@ function participantAttributes(p) {
|
|
|
7185
8012
|
"data-meet-participant-role": observedRole(p.role, p.standing),
|
|
7186
8013
|
"data-meet-participant-self": String(p.isLocal)
|
|
7187
8014
|
};
|
|
7188
|
-
const quality = observedQuality(p.quality);
|
|
8015
|
+
const quality = p.reconnecting === true ? "reconnecting" : observedQuality(p.quality);
|
|
7189
8016
|
if (quality !== null) attrs["data-meet-participant-connection"] = quality;
|
|
7190
8017
|
return attrs;
|
|
7191
8018
|
}
|
|
7192
|
-
function microphoneNoticeCode(track) {
|
|
7193
|
-
const
|
|
7194
|
-
if (
|
|
7195
|
-
return
|
|
8019
|
+
function microphoneNoticeCode(track, permission = "unknown") {
|
|
8020
|
+
const reason = deviceUnavailableReason(track, permission);
|
|
8021
|
+
if (reason === null) return null;
|
|
8022
|
+
return deviceNoticeCode("microphone", reason) === "mic-blocked" ? "mic-blocked" : "device-lost";
|
|
7196
8023
|
}
|
|
7197
8024
|
export {
|
|
7198
8025
|
ATTENDANCE_CSV_HEADER,
|
|
@@ -7201,6 +8028,7 @@ export {
|
|
|
7201
8028
|
CAPTION_LANGUAGES,
|
|
7202
8029
|
CONSENT_NOTICE_ATTRIBUTE,
|
|
7203
8030
|
DATA_TOPICS,
|
|
8031
|
+
DEFAULT_CONNECTION_POLICY,
|
|
7204
8032
|
DEFAULT_EFFECTS,
|
|
7205
8033
|
DEFAULT_PAGE_SIZE,
|
|
7206
8034
|
EMPTY_COLLAB,
|
|
@@ -7211,10 +8039,12 @@ export {
|
|
|
7211
8039
|
GUEST_RECORD_ACCESS_METADATA_KEY,
|
|
7212
8040
|
GUEST_RECORD_NOT_SHARED,
|
|
7213
8041
|
IDLE_MEDIA,
|
|
8042
|
+
IDLE_MEDIA_REGION,
|
|
7214
8043
|
IDLE_PHASES,
|
|
7215
8044
|
IDLE_TRACK,
|
|
7216
8045
|
JOIN_REFUSAL_REASONS,
|
|
7217
8046
|
LISTEN_ONLY_NOTICE,
|
|
8047
|
+
LIVEKIT_BASE_DELAYS_MS,
|
|
7218
8048
|
LIVE_PHASES,
|
|
7219
8049
|
MEETING_INVITE_KIND,
|
|
7220
8050
|
MEETING_INVITE_VERSION,
|
|
@@ -7238,6 +8068,7 @@ export {
|
|
|
7238
8068
|
PARTICIPANT_STANDING_ATTRIBUTE,
|
|
7239
8069
|
REACTION_TTL_MS,
|
|
7240
8070
|
REFUSED_ABSENCE,
|
|
8071
|
+
RESUME_WINDOW_MS,
|
|
7241
8072
|
ROLE_RANK,
|
|
7242
8073
|
ROOM_EVENTS,
|
|
7243
8074
|
ROOM_EVENT_PREFIX,
|
|
@@ -7267,6 +8098,7 @@ export {
|
|
|
7267
8098
|
attendanceTotals,
|
|
7268
8099
|
attendeeKey,
|
|
7269
8100
|
autoAssign,
|
|
8101
|
+
autoRejoinDelayMs,
|
|
7270
8102
|
availableActivities,
|
|
7271
8103
|
breakoutRemainingMs,
|
|
7272
8104
|
callInviteAction,
|
|
@@ -7278,15 +8110,19 @@ export {
|
|
|
7278
8110
|
captionSegment,
|
|
7279
8111
|
captureHeldOf,
|
|
7280
8112
|
changesPatch,
|
|
8113
|
+
classifyDeviceFailure,
|
|
7281
8114
|
clockPosition,
|
|
7282
8115
|
collabFromState,
|
|
7283
8116
|
computeStage,
|
|
8117
|
+
connectionPolicyFrom,
|
|
7284
8118
|
countLabel,
|
|
7285
8119
|
createCallCenter,
|
|
7286
8120
|
createCallInviteHandler,
|
|
8121
|
+
createConnectionSupervisor,
|
|
7287
8122
|
createDeviceManager,
|
|
7288
8123
|
createInRoomClient,
|
|
7289
8124
|
createLiveKitDriver,
|
|
8125
|
+
createMediaSupervisor,
|
|
7290
8126
|
createMeetAi,
|
|
7291
8127
|
createMeetApi,
|
|
7292
8128
|
createMeetRepository,
|
|
@@ -7295,13 +8131,23 @@ export {
|
|
|
7295
8131
|
createMeetingRecordCache,
|
|
7296
8132
|
createMeetingSession,
|
|
7297
8133
|
createMemoryDeviceStorage,
|
|
8134
|
+
createReachabilityProbe,
|
|
8135
|
+
createReconnectPolicy,
|
|
7298
8136
|
createRecordingController,
|
|
7299
8137
|
createRoomEngine,
|
|
7300
8138
|
createTokenClient,
|
|
7301
8139
|
createWebDeviceStorage,
|
|
7302
8140
|
createWebEffectsStorage,
|
|
8141
|
+
createWebNetworkPort,
|
|
8142
|
+
createWebResumeStorage,
|
|
7303
8143
|
createWebRoomTokenStorage,
|
|
7304
8144
|
defaultCaptionLanguage,
|
|
8145
|
+
detectBrowser,
|
|
8146
|
+
detectOs,
|
|
8147
|
+
deviceChipLabel,
|
|
8148
|
+
deviceFixSteps,
|
|
8149
|
+
deviceNoticeCode,
|
|
8150
|
+
deviceUnavailableReason,
|
|
7305
8151
|
displayNameFor,
|
|
7306
8152
|
fileDownloadPath,
|
|
7307
8153
|
focusFromRow,
|
|
@@ -7312,6 +8158,7 @@ export {
|
|
|
7312
8158
|
guestRecordAccessSetting,
|
|
7313
8159
|
hasEnded,
|
|
7314
8160
|
hostUserIds,
|
|
8161
|
+
httpUrlOf,
|
|
7315
8162
|
invalidResponse,
|
|
7316
8163
|
isGuest,
|
|
7317
8164
|
isGuestIdentity,
|
|
@@ -7325,6 +8172,7 @@ export {
|
|
|
7325
8172
|
isRealName,
|
|
7326
8173
|
isRefusedPhase,
|
|
7327
8174
|
isRoomEventTopic,
|
|
8175
|
+
isUnannouncedDeparture,
|
|
7328
8176
|
isWaitingPhase,
|
|
7329
8177
|
learnName,
|
|
7330
8178
|
learnNames,
|
|
@@ -7346,6 +8194,7 @@ export {
|
|
|
7346
8194
|
meetingTopic,
|
|
7347
8195
|
meetingWhen,
|
|
7348
8196
|
mergeCaption,
|
|
8197
|
+
mergeGhosts,
|
|
7349
8198
|
mergeRecord,
|
|
7350
8199
|
microphoneNoticeCode,
|
|
7351
8200
|
moveToRoom,
|
|
@@ -7410,6 +8259,7 @@ export {
|
|
|
7410
8259
|
untranslatedLines,
|
|
7411
8260
|
userTopic,
|
|
7412
8261
|
wasRefused,
|
|
8262
|
+
webMediaPlatform,
|
|
7413
8263
|
withItem,
|
|
7414
8264
|
wrapUpStatus
|
|
7415
8265
|
};
|