@ai-matrx/meet 0.10.7 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/{collab-ytIzjceh.d.cts → collab-CIyXdQ5l.d.cts} +1 -2
- package/dist/{collab-ytIzjceh.d.ts → collab-CIyXdQ5l.d.ts} +1 -2
- package/dist/{components-CnnefQn-.d.cts → components-DUvy3BQf.d.cts} +1 -1
- package/dist/{components-DjzH3u_c.d.ts → components-DiGxfKXI.d.ts} +1 -1
- package/dist/core.cjs +403 -98
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +254 -24
- package/dist/core.d.ts +254 -24
- package/dist/core.js +403 -98
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +403 -98
- 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 +403 -98
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +696 -116
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +68 -7
- package/dist/react.d.ts +68 -7
- package/dist/react.js +697 -117
- package/dist/react.js.map +1 -1
- package/dist/skins/meet.cjs +265 -50
- 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 +265 -50
- package/dist/skins/meet.js.map +1 -1
- package/dist/styles.css +20 -0
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -1014,6 +1014,166 @@ var MEET_EVENTS = {
|
|
|
1014
1014
|
stateChanged: "mx.state.changed"
|
|
1015
1015
|
};
|
|
1016
1016
|
|
|
1017
|
+
// src/core/reasons.ts
|
|
1018
|
+
var JOIN_REFUSAL_REASONS = [
|
|
1019
|
+
"not_found",
|
|
1020
|
+
"cancelled",
|
|
1021
|
+
"ended",
|
|
1022
|
+
"expired",
|
|
1023
|
+
"too_early",
|
|
1024
|
+
"sign_in_required",
|
|
1025
|
+
"wrong_account",
|
|
1026
|
+
"not_invited",
|
|
1027
|
+
"locked",
|
|
1028
|
+
"removed",
|
|
1029
|
+
"lobby_rejects",
|
|
1030
|
+
"meeting_full",
|
|
1031
|
+
"platform_capacity",
|
|
1032
|
+
"verification_required",
|
|
1033
|
+
"registration_required"
|
|
1034
|
+
];
|
|
1035
|
+
function isJoinRefusalReason(value) {
|
|
1036
|
+
return typeof value === "string" && JOIN_REFUSAL_REASONS.includes(value);
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
// src/core/phase.ts
|
|
1040
|
+
var LIVE_PHASES = /* @__PURE__ */ new Set(["joining", "in_call"]);
|
|
1041
|
+
var WAITING_PHASES = /* @__PURE__ */ new Set([
|
|
1042
|
+
"waiting:host_not_started",
|
|
1043
|
+
"waiting:knocking",
|
|
1044
|
+
"denied",
|
|
1045
|
+
"knock_expired"
|
|
1046
|
+
]);
|
|
1047
|
+
var JOINABLE_FROM = /* @__PURE__ */ new Set([
|
|
1048
|
+
"prejoin",
|
|
1049
|
+
"left",
|
|
1050
|
+
"disconnected",
|
|
1051
|
+
"superseded",
|
|
1052
|
+
"inactive",
|
|
1053
|
+
"denied",
|
|
1054
|
+
"knock_expired"
|
|
1055
|
+
]);
|
|
1056
|
+
var NOT_ENDABLE = /* @__PURE__ */ new Set([
|
|
1057
|
+
"ended",
|
|
1058
|
+
"record",
|
|
1059
|
+
"unsupported",
|
|
1060
|
+
"ringing_out",
|
|
1061
|
+
"ringing_in",
|
|
1062
|
+
"call_declined",
|
|
1063
|
+
"call_missed",
|
|
1064
|
+
"call_busy",
|
|
1065
|
+
"answered_elsewhere"
|
|
1066
|
+
]);
|
|
1067
|
+
var RINGING = /* @__PURE__ */ new Set(["ringing_out", "ringing_in"]);
|
|
1068
|
+
var IDLE_PHASES = /* @__PURE__ */ new Set([
|
|
1069
|
+
"resolving",
|
|
1070
|
+
"left",
|
|
1071
|
+
"call_declined",
|
|
1072
|
+
"call_missed",
|
|
1073
|
+
"call_busy",
|
|
1074
|
+
"answered_elsewhere"
|
|
1075
|
+
]);
|
|
1076
|
+
function isLivePhase(phase) {
|
|
1077
|
+
return LIVE_PHASES.has(phase);
|
|
1078
|
+
}
|
|
1079
|
+
function isWaitingPhase(phase) {
|
|
1080
|
+
return WAITING_PHASES.has(phase);
|
|
1081
|
+
}
|
|
1082
|
+
function isRefusedPhase(phase) {
|
|
1083
|
+
return phase.startsWith("refused:");
|
|
1084
|
+
}
|
|
1085
|
+
function reasonOf(phase) {
|
|
1086
|
+
return isRefusedPhase(phase) ? phase.slice("refused:".length) : null;
|
|
1087
|
+
}
|
|
1088
|
+
function refusalPhase(reason) {
|
|
1089
|
+
if (reason === null || !isJoinRefusalReason(reason)) return "disconnected";
|
|
1090
|
+
return reason === "ended" ? "ended" : `refused:${reason}`;
|
|
1091
|
+
}
|
|
1092
|
+
function admissionPhase(admission) {
|
|
1093
|
+
switch (admission) {
|
|
1094
|
+
case "waiting_host":
|
|
1095
|
+
return "waiting:host_not_started";
|
|
1096
|
+
case "knocking":
|
|
1097
|
+
return "waiting:knocking";
|
|
1098
|
+
case "denied":
|
|
1099
|
+
return "denied";
|
|
1100
|
+
case "expired":
|
|
1101
|
+
return "knock_expired";
|
|
1102
|
+
case "withdrawn":
|
|
1103
|
+
return "left";
|
|
1104
|
+
case "ended":
|
|
1105
|
+
return "ended";
|
|
1106
|
+
case "removed":
|
|
1107
|
+
return "refused:removed";
|
|
1108
|
+
default:
|
|
1109
|
+
return null;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
function nextPhase(from, event) {
|
|
1113
|
+
switch (event.type) {
|
|
1114
|
+
case "resolved":
|
|
1115
|
+
return from === "resolving" ? "prejoin" : null;
|
|
1116
|
+
case "unsupported":
|
|
1117
|
+
return from === "resolving" ? "unsupported" : null;
|
|
1118
|
+
case "join":
|
|
1119
|
+
return JOINABLE_FROM.has(from) ? "joining" : null;
|
|
1120
|
+
case "back_to_prejoin":
|
|
1121
|
+
return from === "left" || from === "disconnected" ? "prejoin" : null;
|
|
1122
|
+
case "retry":
|
|
1123
|
+
return isRefusedPhase(from) || from === "unsupported" ? "resolving" : null;
|
|
1124
|
+
case "admission": {
|
|
1125
|
+
if (from !== "joining" && !WAITING_PHASES.has(from)) return null;
|
|
1126
|
+
return admissionPhase(event.admission);
|
|
1127
|
+
}
|
|
1128
|
+
case "admitted":
|
|
1129
|
+
return WAITING_PHASES.has(from) ? "joining" : null;
|
|
1130
|
+
case "connected":
|
|
1131
|
+
return from === "joining" ? "in_call" : null;
|
|
1132
|
+
case "join_failed":
|
|
1133
|
+
return from === "joining" ? refusalPhase(event.reason) : null;
|
|
1134
|
+
case "exit":
|
|
1135
|
+
return from === "in_call" || from === "joining" ? event.to : null;
|
|
1136
|
+
case "leave":
|
|
1137
|
+
return from === "in_call" || from === "joining" || WAITING_PHASES.has(from) ? "left" : null;
|
|
1138
|
+
case "ended":
|
|
1139
|
+
return NOT_ENDABLE.has(from) ? null : "ended";
|
|
1140
|
+
case "ring_out":
|
|
1141
|
+
return IDLE_PHASES.has(from) || from === "prejoin" ? "ringing_out" : null;
|
|
1142
|
+
case "ring_in":
|
|
1143
|
+
return IDLE_PHASES.has(from) ? "ringing_in" : null;
|
|
1144
|
+
case "call_answered":
|
|
1145
|
+
return RINGING.has(from) ? "joining" : null;
|
|
1146
|
+
case "call_outcome":
|
|
1147
|
+
return RINGING.has(from) ? event.outcome : null;
|
|
1148
|
+
case "reset":
|
|
1149
|
+
return LIVE_PHASES.has(from) ? null : "resolving";
|
|
1150
|
+
}
|
|
1151
|
+
}
|
|
1152
|
+
function resolveExit(input) {
|
|
1153
|
+
const { server, hint } = input;
|
|
1154
|
+
if (server === null) {
|
|
1155
|
+
return { to: "disconnected", reason: null, connection: "server_unreachable", notice: null };
|
|
1156
|
+
}
|
|
1157
|
+
const word = server?.exitReason ?? null;
|
|
1158
|
+
if (server !== void 0 && (server.sessionPhase === "ended" || server.meetingPhase === "ended" || word === "ended" || word === "time_limit")) {
|
|
1159
|
+
return { to: "ended", reason: word === "time_limit" ? "time_limit" : "ended", connection: "stable", notice: null };
|
|
1160
|
+
}
|
|
1161
|
+
if (word === "removed") return { to: "removed", reason: "removed", connection: "stable", notice: null };
|
|
1162
|
+
if (word === "displaced") return { to: "superseded", reason: "displaced", connection: "stable", notice: null };
|
|
1163
|
+
if (word === "sent_to_waiting") {
|
|
1164
|
+
return { to: "waiting:knocking", reason: "sent_to_waiting", connection: "stable", notice: "sent-to-waiting" };
|
|
1165
|
+
}
|
|
1166
|
+
if (hint === "DUPLICATE_IDENTITY") return { to: "superseded", reason: "displaced", connection: "stable", notice: null };
|
|
1167
|
+
if (hint === "PARTICIPANT_REMOVED" && word === null && server === void 0) {
|
|
1168
|
+
return { to: "removed", reason: "removed", connection: "stable", notice: null };
|
|
1169
|
+
}
|
|
1170
|
+
if (hint === "ROOM_DELETED" && server === void 0) {
|
|
1171
|
+
return { to: "ended", reason: "ended", connection: "stable", notice: null };
|
|
1172
|
+
}
|
|
1173
|
+
if (input.frozen === true) return { to: "inactive", reason: "inactive", connection: "stable", notice: null };
|
|
1174
|
+
return { to: "disconnected", reason: null, connection: "stable", notice: null };
|
|
1175
|
+
}
|
|
1176
|
+
|
|
1017
1177
|
// src/core/types.ts
|
|
1018
1178
|
var asMeetingId = (value) => value;
|
|
1019
1179
|
var asCallId = (value) => value;
|
|
@@ -1105,6 +1265,39 @@ function createCallCenter(options) {
|
|
|
1105
1265
|
clearRing(invite.id);
|
|
1106
1266
|
incoming.delete(invite.id);
|
|
1107
1267
|
if (outgoing !== null && outgoing.id === invite.id) outgoing = invite;
|
|
1268
|
+
const held = options.store.snapshot().call;
|
|
1269
|
+
if (held !== null && held.invite.id === invite.id && held.direction === "incoming") {
|
|
1270
|
+
const outcome = invite.state === "connecting" || invite.state === "active" ? "answered_elsewhere" : invite.state === "declined" ? "reset" : "call_missed";
|
|
1271
|
+
const moved = outcome === "reset" ? options.store.dispatch({ type: "reset" }) : options.store.dispatch({ type: "call_outcome", outcome });
|
|
1272
|
+
if (moved) options.store.patch({ call: outcome === "reset" ? null : { ...held, invite } });
|
|
1273
|
+
}
|
|
1274
|
+
options.onSettled?.(invite);
|
|
1275
|
+
}
|
|
1276
|
+
function settleOutgoing(invite) {
|
|
1277
|
+
if (outgoing === null || outgoing.id !== invite.id) return;
|
|
1278
|
+
clearRing(invite.id);
|
|
1279
|
+
outgoing = invite;
|
|
1280
|
+
const store = options.store;
|
|
1281
|
+
const held = store.snapshot().call;
|
|
1282
|
+
if (held !== null && held.invite.id === invite.id) store.patch({ call: { ...held, invite } });
|
|
1283
|
+
switch (invite.state) {
|
|
1284
|
+
case "connecting":
|
|
1285
|
+
case "active":
|
|
1286
|
+
if (store.dispatch({ type: "call_answered" })) options.onAnswered?.(invite);
|
|
1287
|
+
break;
|
|
1288
|
+
case "declined":
|
|
1289
|
+
store.dispatch({ type: "call_outcome", outcome: "call_declined" });
|
|
1290
|
+
break;
|
|
1291
|
+
case "busy":
|
|
1292
|
+
store.dispatch({ type: "call_outcome", outcome: "call_busy" });
|
|
1293
|
+
break;
|
|
1294
|
+
case "missed":
|
|
1295
|
+
case "failed":
|
|
1296
|
+
store.dispatch({ type: "call_outcome", outcome: "call_missed" });
|
|
1297
|
+
break;
|
|
1298
|
+
default:
|
|
1299
|
+
break;
|
|
1300
|
+
}
|
|
1108
1301
|
options.onSettled?.(invite);
|
|
1109
1302
|
}
|
|
1110
1303
|
function ingest(invite) {
|
|
@@ -1113,7 +1306,7 @@ function createCallCenter(options) {
|
|
|
1113
1306
|
if (identity.userId === null) return;
|
|
1114
1307
|
if (invite.callerUserId === identity.userId) return;
|
|
1115
1308
|
const phase = options.store.snapshot().phase;
|
|
1116
|
-
if (phase
|
|
1309
|
+
if (isLivePhase(phase) || phase === "ringing_out") {
|
|
1117
1310
|
void repository.settleCallInvite(invite.id, "busy", null).then((settled) => {
|
|
1118
1311
|
to(settled.callerUserId).send(MEET_EVENTS.settled, settled);
|
|
1119
1312
|
}).catch((error) => {
|
|
@@ -1126,6 +1319,9 @@ function createCallCenter(options) {
|
|
|
1126
1319
|
return;
|
|
1127
1320
|
}
|
|
1128
1321
|
incoming.set(invite.id, { ...invite, state: "ringing" });
|
|
1322
|
+
if (options.store.snapshot().call === null && options.store.dispatch({ type: "ring_in" })) {
|
|
1323
|
+
options.store.patch({ call: { invite: { ...invite, state: "ringing" }, direction: "incoming" } });
|
|
1324
|
+
}
|
|
1129
1325
|
options.onIncoming?.(invite);
|
|
1130
1326
|
timeouts.set(
|
|
1131
1327
|
invite.id,
|
|
@@ -1163,6 +1359,7 @@ function createCallCenter(options) {
|
|
|
1163
1359
|
const invite = message.data;
|
|
1164
1360
|
const held = incoming.get(invite.id);
|
|
1165
1361
|
if (held !== void 0) settleLocal(invite);
|
|
1362
|
+
else if (outgoing?.id === invite.id) settleOutgoing(invite);
|
|
1166
1363
|
}
|
|
1167
1364
|
}
|
|
1168
1365
|
],
|
|
@@ -1229,6 +1426,9 @@ function createCallCenter(options) {
|
|
|
1229
1426
|
expiresAt: new Date(timers.now() + ringTimeoutMs).toISOString()
|
|
1230
1427
|
});
|
|
1231
1428
|
outgoing = invite;
|
|
1429
|
+
if (options.store.dispatch({ type: "ring_out" })) {
|
|
1430
|
+
options.store.patch({ call: { invite, direction: "outgoing" } });
|
|
1431
|
+
}
|
|
1232
1432
|
for (const callee of people) {
|
|
1233
1433
|
to(callee).send(MEET_EVENTS.ring, invite);
|
|
1234
1434
|
}
|
|
@@ -1237,8 +1437,7 @@ function createCallCenter(options) {
|
|
|
1237
1437
|
timers.setTimeout(() => {
|
|
1238
1438
|
if (outgoing?.id !== invite.id) return;
|
|
1239
1439
|
void repository.settleCallInvite(invite.id, "missed", null).then((settled) => {
|
|
1240
|
-
|
|
1241
|
-
options.onSettled?.(settled);
|
|
1440
|
+
settleOutgoing(settled);
|
|
1242
1441
|
}).catch(() => void 0);
|
|
1243
1442
|
}, ringTimeoutMs)
|
|
1244
1443
|
);
|
|
@@ -1253,7 +1452,9 @@ function createCallCenter(options) {
|
|
|
1253
1452
|
"A late accept must not resurrect a settled call. Close the ringing UI; the caller has already moved on."
|
|
1254
1453
|
);
|
|
1255
1454
|
}
|
|
1455
|
+
if (options.store.snapshot().phase === "ringing_in") options.store.dispatch({ type: "call_answered" });
|
|
1256
1456
|
const settled = await repository.settleCallInvite(id, "connecting", null);
|
|
1457
|
+
options.store.patch({ call: { invite: settled, direction: "incoming" } });
|
|
1257
1458
|
settleLocal(settled);
|
|
1258
1459
|
channel?.send(MEET_EVENTS.settled, settled);
|
|
1259
1460
|
to(settled.callerUserId).send(MEET_EVENTS.settled, { ...settled, mode });
|
|
@@ -1261,6 +1462,9 @@ function createCallCenter(options) {
|
|
|
1261
1462
|
},
|
|
1262
1463
|
async decline(id, message) {
|
|
1263
1464
|
const settled = await repository.settleCallInvite(id, "declined", message ?? null);
|
|
1465
|
+
if (options.store.snapshot().call?.invite.id === id && options.store.dispatch({ type: "reset" })) {
|
|
1466
|
+
options.store.patch({ call: null });
|
|
1467
|
+
}
|
|
1264
1468
|
settleLocal(settled);
|
|
1265
1469
|
channel?.send(MEET_EVENTS.settled, settled);
|
|
1266
1470
|
to(settled.callerUserId).send(MEET_EVENTS.settled, settled);
|
|
@@ -1270,6 +1474,9 @@ function createCallCenter(options) {
|
|
|
1270
1474
|
const settled = await repository.settleCallInvite(id, "cancelled", null);
|
|
1271
1475
|
clearRing(id);
|
|
1272
1476
|
if (outgoing?.id === id) outgoing = settled;
|
|
1477
|
+
if (options.store.snapshot().call?.invite.id === id && options.store.dispatch({ type: "reset" })) {
|
|
1478
|
+
options.store.patch({ call: null });
|
|
1479
|
+
}
|
|
1273
1480
|
for (const callee of settled.calleeUserIds) {
|
|
1274
1481
|
to(callee).send(MEET_EVENTS.cancel, settled);
|
|
1275
1482
|
}
|
|
@@ -1301,7 +1508,9 @@ var TABLES = {
|
|
|
1301
1508
|
/** Wave 1 (0.8): who a meeting was sent to, and what they answered. */
|
|
1302
1509
|
invitees: "meet_invitees",
|
|
1303
1510
|
/** Wave 1 (0.8): one occurrence of a series cancelled or moved. */
|
|
1304
|
-
occurrenceOverrides: "meet_occurrence_overrides"
|
|
1511
|
+
occurrenceOverrides: "meet_occurrence_overrides",
|
|
1512
|
+
/** S5: one row per RUN of a meeting; carries that run's note-taker state. */
|
|
1513
|
+
sessions: "meet_sessions"
|
|
1305
1514
|
};
|
|
1306
1515
|
var RPCS = {
|
|
1307
1516
|
/** Atomic: create the invite row and stamp its expiry in one statement. */
|
|
@@ -2782,8 +2991,15 @@ var NO_GRANTS = {
|
|
|
2782
2991
|
canPublish: false,
|
|
2783
2992
|
canSubscribe: false
|
|
2784
2993
|
};
|
|
2994
|
+
var NO_SHARE = { state: "none", reason: null, remedy: null, at: 0 };
|
|
2785
2995
|
var EMPTY = {
|
|
2786
|
-
phase: "
|
|
2996
|
+
phase: "resolving",
|
|
2997
|
+
reason: null,
|
|
2998
|
+
phaseNotice: null,
|
|
2999
|
+
roomName: null,
|
|
3000
|
+
connection: "stable",
|
|
3001
|
+
share: NO_SHARE,
|
|
3002
|
+
call: null,
|
|
2787
3003
|
waiting: null,
|
|
2788
3004
|
meeting: null,
|
|
2789
3005
|
localIdentity: null,
|
|
@@ -2847,8 +3063,20 @@ function createMeetStore(initial = {}) {
|
|
|
2847
3063
|
return () => listeners.delete(listener);
|
|
2848
3064
|
},
|
|
2849
3065
|
patch(next) {
|
|
3066
|
+
if ("phase" in next || "reason" in next || "phaseNotice" in next) {
|
|
3067
|
+
throw new TypeError("meet store: the phase moves only through store.dispatch(event)");
|
|
3068
|
+
}
|
|
2850
3069
|
commit({ ...state, ...next });
|
|
2851
3070
|
},
|
|
3071
|
+
dispatch(event, detail) {
|
|
3072
|
+
const to = nextPhase(state.phase, event);
|
|
3073
|
+
if (to === null) return false;
|
|
3074
|
+
const reason = detail?.reason !== void 0 ? detail.reason : reasonOf(to);
|
|
3075
|
+
const phaseNotice = detail?.notice ?? null;
|
|
3076
|
+
if (to === state.phase && reason === state.reason && phaseNotice === state.phaseNotice) return true;
|
|
3077
|
+
commit({ ...state, phase: to, reason, phaseNotice });
|
|
3078
|
+
return true;
|
|
3079
|
+
},
|
|
2852
3080
|
setParticipants(participants) {
|
|
2853
3081
|
const names = learnNames(state.names, participants);
|
|
2854
3082
|
const hands = new Map(state.participants.map((p) => [p.identity, p.handRaised]));
|
|
@@ -3842,7 +4070,8 @@ function createLiveKitDriver(handlers, options = {}) {
|
|
|
3842
4070
|
}).on(RoomEvent.Disconnected, (reason) => {
|
|
3843
4071
|
audioContainer?.remove();
|
|
3844
4072
|
audioContainer = null;
|
|
3845
|
-
|
|
4073
|
+
const named = reason === void 0 ? null : module?.DisconnectReason?.[reason] ?? String(reason);
|
|
4074
|
+
handlers.disconnected(named);
|
|
3846
4075
|
});
|
|
3847
4076
|
try {
|
|
3848
4077
|
created.registerTextStreamHandler(TRANSCRIPTION_TOPIC, (reader, participantInfo) => {
|
|
@@ -4190,7 +4419,7 @@ function createMeetingSession(options) {
|
|
|
4190
4419
|
}
|
|
4191
4420
|
function apply(read) {
|
|
4192
4421
|
const snapshot = store.snapshot();
|
|
4193
|
-
if (snapshot.phase
|
|
4422
|
+
if (!isWaitingPhase(snapshot.phase)) return;
|
|
4194
4423
|
const admission = read.admission_state ?? null;
|
|
4195
4424
|
const ended = admission === "ended" || read.session_phase === "ended" || read.meeting_phase === "ended";
|
|
4196
4425
|
if (admission === "admitted" && !ended) {
|
|
@@ -4207,6 +4436,7 @@ function createMeetingSession(options) {
|
|
|
4207
4436
|
if (read.meeting_phase === "ended" && meeting !== null && meeting.endedAt === null) {
|
|
4208
4437
|
store.patch({ meeting: { ...meeting, endedAt: (/* @__PURE__ */ new Date()).toISOString() } });
|
|
4209
4438
|
}
|
|
4439
|
+
store.dispatch({ type: "admission", admission: "ended" }, { reason: "ended" });
|
|
4210
4440
|
return;
|
|
4211
4441
|
}
|
|
4212
4442
|
if (admission === null) return;
|
|
@@ -4218,6 +4448,7 @@ function createMeetingSession(options) {
|
|
|
4218
4448
|
pollSeconds: read.poll_seconds ?? snapshot.waiting?.pollSeconds ?? 3,
|
|
4219
4449
|
liveVersion: read.live_version ?? 0
|
|
4220
4450
|
});
|
|
4451
|
+
store.dispatch({ type: "admission", admission });
|
|
4221
4452
|
if (admission === "denied" || admission === "expired" || admission === "withdrawn" || admission === "removed") {
|
|
4222
4453
|
stopWaiting();
|
|
4223
4454
|
}
|
|
@@ -4313,7 +4544,7 @@ function createMeetingSession(options) {
|
|
|
4313
4544
|
// 🚨 PAYLOAD-FREE. Every receiver reads again; a spoofed hint only causes a read.
|
|
4314
4545
|
event: MEET_EVENTS.stateChanged,
|
|
4315
4546
|
onMessage: () => {
|
|
4316
|
-
if (store.snapshot().phase
|
|
4547
|
+
if (isWaitingPhase(store.snapshot().phase)) void readState2();
|
|
4317
4548
|
void refreshQueue();
|
|
4318
4549
|
}
|
|
4319
4550
|
}
|
|
@@ -4325,7 +4556,7 @@ function createMeetingSession(options) {
|
|
|
4325
4556
|
if (meeting === null) return;
|
|
4326
4557
|
const fresh = isGuest(identity) ? await repository.meetingBySlug(meeting.slug) : await readMeeting(meeting.id);
|
|
4327
4558
|
store.patch({ meeting: fresh, locked: fresh.locked });
|
|
4328
|
-
if (store.snapshot().phase
|
|
4559
|
+
if (isWaitingPhase(store.snapshot().phase)) void readState2();
|
|
4329
4560
|
}
|
|
4330
4561
|
});
|
|
4331
4562
|
},
|
|
@@ -4492,10 +4723,34 @@ function createMeetingSession(options) {
|
|
|
4492
4723
|
},
|
|
4493
4724
|
stopWaiting,
|
|
4494
4725
|
readState: readState2,
|
|
4726
|
+
async readExit(connection) {
|
|
4727
|
+
const meeting = store.snapshot().meeting;
|
|
4728
|
+
const pass = options.resolvePass?.() ?? null;
|
|
4729
|
+
if (meeting === null || pass === null) return void 0;
|
|
4730
|
+
try {
|
|
4731
|
+
const response = await options.api.request({
|
|
4732
|
+
path: `${MEET_ROUTES.state}?meeting_id=${encodeURIComponent(meeting.id)}&connection=${encodeURIComponent(connection)}`,
|
|
4733
|
+
method: "GET",
|
|
4734
|
+
requireAuth: false,
|
|
4735
|
+
operation: "meet.state(exit)",
|
|
4736
|
+
headers: { [MEETING_PASS_HEADER]: pass }
|
|
4737
|
+
});
|
|
4738
|
+
if (!response.ok) return null;
|
|
4739
|
+
const read = await response.json();
|
|
4740
|
+
return {
|
|
4741
|
+
exitReason: read.exit_reason ?? null,
|
|
4742
|
+
sessionPhase: read.session_phase ?? null,
|
|
4743
|
+
meetingPhase: read.meeting_phase ?? null
|
|
4744
|
+
};
|
|
4745
|
+
} catch {
|
|
4746
|
+
return null;
|
|
4747
|
+
}
|
|
4748
|
+
},
|
|
4495
4749
|
async withdraw() {
|
|
4496
4750
|
stopWaiting();
|
|
4497
4751
|
await postLeave("withdraw");
|
|
4498
4752
|
patchWaiting({ admission: "withdrawn" });
|
|
4753
|
+
store.dispatch({ type: "admission", admission: "withdrawn" });
|
|
4499
4754
|
hint();
|
|
4500
4755
|
},
|
|
4501
4756
|
async askAgain() {
|
|
@@ -5119,6 +5374,9 @@ async function pushMeetingToGoogleCalendar(api, meetingId, target) {
|
|
|
5119
5374
|
}
|
|
5120
5375
|
|
|
5121
5376
|
// src/core/room.ts
|
|
5377
|
+
function SCREEN_SHARE_BLOCKED_REMEDY_FOR(remedy) {
|
|
5378
|
+
return /administrator|policy/i.test(remedy) ? remedy : SCREEN_SHARE_BLOCKED_REMEDY;
|
|
5379
|
+
}
|
|
5122
5380
|
var PARTICIPANT_ROLE_ATTRIBUTE = "matrx.participant.role";
|
|
5123
5381
|
var PARTICIPANT_CAN_RECORD_ATTRIBUTE = "matrx.participant.can_record";
|
|
5124
5382
|
var PARTICIPANT_STANDING_ATTRIBUTE = "matrx.participant.standing";
|
|
@@ -5186,7 +5444,7 @@ function createRoomEngine(options) {
|
|
|
5186
5444
|
let disposed = false;
|
|
5187
5445
|
let moving = false;
|
|
5188
5446
|
const confirmingEnds = /* @__PURE__ */ new WeakSet();
|
|
5189
|
-
async function
|
|
5447
|
+
async function dropRoom() {
|
|
5190
5448
|
const target = driver;
|
|
5191
5449
|
driver = null;
|
|
5192
5450
|
if (current !== null) {
|
|
@@ -5195,9 +5453,14 @@ function createRoomEngine(options) {
|
|
|
5195
5453
|
}
|
|
5196
5454
|
store.setLocalTrack("microphone", IDLE_TRACK);
|
|
5197
5455
|
store.setLocalTrack("camera", IDLE_TRACK);
|
|
5198
|
-
store.patch({
|
|
5456
|
+
store.patch({ share: NO_SHARE, connection: "stable" });
|
|
5199
5457
|
await target?.disconnect();
|
|
5200
5458
|
}
|
|
5459
|
+
async function leaveRoom() {
|
|
5460
|
+
store.dispatch({ type: "leave" });
|
|
5461
|
+
await dropRoom();
|
|
5462
|
+
options.onLeft?.(null);
|
|
5463
|
+
}
|
|
5201
5464
|
async function confirmMeetingEnd() {
|
|
5202
5465
|
const meeting = store.snapshot().meeting;
|
|
5203
5466
|
const target = driver;
|
|
@@ -5219,7 +5482,9 @@ function createRoomEngine(options) {
|
|
|
5219
5482
|
const latest = store.snapshot().meeting;
|
|
5220
5483
|
if (latest === null) return;
|
|
5221
5484
|
store.patch({ meeting: { ...latest, endedAt: verified.endedAt } });
|
|
5222
|
-
|
|
5485
|
+
store.dispatch({ type: "ended" }, { reason: "ended" });
|
|
5486
|
+
await dropRoom();
|
|
5487
|
+
options.onLeft?.("ended");
|
|
5223
5488
|
} catch (error) {
|
|
5224
5489
|
report("error", `Meet could not confirm or finish meeting teardown: ${String(error)}`, "Check the meeting link again; if media remains active, close this meeting tab.");
|
|
5225
5490
|
} finally {
|
|
@@ -5231,12 +5496,12 @@ function createRoomEngine(options) {
|
|
|
5231
5496
|
options.onDiagnostic?.(remedy === void 0 ? { level, message } : { level, message, remedy });
|
|
5232
5497
|
}
|
|
5233
5498
|
let ambiguousShareDenials = 0;
|
|
5234
|
-
function
|
|
5499
|
+
function failJoin(error, operation) {
|
|
5235
5500
|
const normalized = normalizeMeetError(error, operation);
|
|
5236
5501
|
store.patch({
|
|
5237
|
-
phase: "failed",
|
|
5238
5502
|
failure: { message: normalized.message, remedy: normalized.remedy, reason: normalized.reason }
|
|
5239
5503
|
});
|
|
5504
|
+
store.dispatch({ type: "join_failed", reason: normalized.reason ?? null });
|
|
5240
5505
|
report(
|
|
5241
5506
|
normalized.code === "session-unavailable" ? "warn" : "error",
|
|
5242
5507
|
normalized.message,
|
|
@@ -5244,6 +5509,14 @@ function createRoomEngine(options) {
|
|
|
5244
5509
|
);
|
|
5245
5510
|
return normalized;
|
|
5246
5511
|
}
|
|
5512
|
+
async function lostRoom(error, operation) {
|
|
5513
|
+
const normalized = normalizeMeetError(error, operation);
|
|
5514
|
+
store.patch({ failure: { message: normalized.message, remedy: normalized.remedy, reason: normalized.reason } });
|
|
5515
|
+
await dropRoom();
|
|
5516
|
+
store.dispatch({ type: "exit", to: "disconnected" });
|
|
5517
|
+
report("error", normalized.message, normalized.remedy);
|
|
5518
|
+
return normalized;
|
|
5519
|
+
}
|
|
5247
5520
|
const handlers = {
|
|
5248
5521
|
participants(list) {
|
|
5249
5522
|
const joinedAt = new Date(now()).toISOString();
|
|
@@ -5286,9 +5559,12 @@ function createRoomEngine(options) {
|
|
|
5286
5559
|
store.setQuality(asParticipantIdentity(who), value);
|
|
5287
5560
|
},
|
|
5288
5561
|
connectionState(state) {
|
|
5289
|
-
if (state === "connected")
|
|
5290
|
-
|
|
5291
|
-
|
|
5562
|
+
if (state === "connected") {
|
|
5563
|
+
if (store.snapshot().connection !== "stable") store.patch({ connection: "stable" });
|
|
5564
|
+
store.dispatch({ type: "connected" });
|
|
5565
|
+
} else if (state === "reconnecting") {
|
|
5566
|
+
store.patch({ connection: "reconnecting" });
|
|
5567
|
+
}
|
|
5292
5568
|
},
|
|
5293
5569
|
transcription(event) {
|
|
5294
5570
|
const snapshot = store.snapshot();
|
|
@@ -5415,17 +5691,48 @@ function createRoomEngine(options) {
|
|
|
5415
5691
|
}
|
|
5416
5692
|
},
|
|
5417
5693
|
disconnected(reason) {
|
|
5418
|
-
if (moving) return;
|
|
5419
|
-
|
|
5420
|
-
tokens.invalidate(current.roomName);
|
|
5421
|
-
current = null;
|
|
5422
|
-
}
|
|
5423
|
-
store.patch({ phase: "left" });
|
|
5424
|
-
options.onLeft?.(reason);
|
|
5694
|
+
if (moving || driver === null) return;
|
|
5695
|
+
void resolveExitAndApply(reason);
|
|
5425
5696
|
}
|
|
5426
5697
|
};
|
|
5698
|
+
async function resolveExitAndApply(hint) {
|
|
5699
|
+
const connection = current?.identity ?? store.snapshot().localIdentity ?? null;
|
|
5700
|
+
await dropRoom();
|
|
5701
|
+
let server;
|
|
5702
|
+
if (options.readExit === void 0 || connection === null || store.snapshot().meeting === null) {
|
|
5703
|
+
server = void 0;
|
|
5704
|
+
} else {
|
|
5705
|
+
try {
|
|
5706
|
+
server = await options.readExit(connection);
|
|
5707
|
+
} catch {
|
|
5708
|
+
server = null;
|
|
5709
|
+
}
|
|
5710
|
+
}
|
|
5711
|
+
if (disposed) return;
|
|
5712
|
+
const resolved = resolveExit({ server, hint, frozen: options.wasFrozen?.() ?? false });
|
|
5713
|
+
store.patch({ connection: resolved.connection });
|
|
5714
|
+
if (resolved.to === "waiting:knocking") {
|
|
5715
|
+
store.patch({
|
|
5716
|
+
waiting: {
|
|
5717
|
+
admission: "knocking",
|
|
5718
|
+
admittersPresent: null,
|
|
5719
|
+
reknockAllowed: true,
|
|
5720
|
+
knockExpiresAt: null,
|
|
5721
|
+
pollSeconds: store.snapshot().waiting?.pollSeconds ?? 3,
|
|
5722
|
+
liveVersion: 0
|
|
5723
|
+
}
|
|
5724
|
+
});
|
|
5725
|
+
}
|
|
5726
|
+
store.dispatch({ type: "exit", to: resolved.to }, { reason: resolved.reason, notice: resolved.notice });
|
|
5727
|
+
report(
|
|
5728
|
+
resolved.to === "disconnected" ? "warn" : "info",
|
|
5729
|
+
`meet: the room connection ended (${hint ?? "no LiveKit reason"}) \u2192 ${resolved.to}`,
|
|
5730
|
+
resolved.to === "disconnected" ? "Press Rejoin; the meeting is still going." : "The screen says what happened."
|
|
5731
|
+
);
|
|
5732
|
+
options.onLeft?.(hint);
|
|
5733
|
+
}
|
|
5427
5734
|
async function connect(request) {
|
|
5428
|
-
store.patch({
|
|
5735
|
+
store.patch({ failure: null, waiting: null, roomName: request.roomName, share: NO_SHARE, connection: "stable" });
|
|
5429
5736
|
const token = await tokens.get({
|
|
5430
5737
|
roomName: request.roomName,
|
|
5431
5738
|
identity,
|
|
@@ -5448,10 +5755,10 @@ function createRoomEngine(options) {
|
|
|
5448
5755
|
}
|
|
5449
5756
|
});
|
|
5450
5757
|
if (token.lobby || !token.canSubscribe) {
|
|
5758
|
+
const admission = token.admissionState !== void 0 && token.admissionState !== "admitted" ? token.admissionState : "knocking";
|
|
5451
5759
|
store.patch({
|
|
5452
|
-
phase: "lobby",
|
|
5453
5760
|
waiting: {
|
|
5454
|
-
admission
|
|
5761
|
+
admission,
|
|
5455
5762
|
admittersPresent: null,
|
|
5456
5763
|
reknockAllowed: true,
|
|
5457
5764
|
knockExpiresAt: null,
|
|
@@ -5459,9 +5766,10 @@ function createRoomEngine(options) {
|
|
|
5459
5766
|
liveVersion: 0
|
|
5460
5767
|
}
|
|
5461
5768
|
});
|
|
5769
|
+
store.dispatch({ type: "admission", admission });
|
|
5462
5770
|
return;
|
|
5463
5771
|
}
|
|
5464
|
-
store.patch({
|
|
5772
|
+
store.patch({ waiting: null });
|
|
5465
5773
|
const created = await options.driverFactory(handlers);
|
|
5466
5774
|
if (disposed) {
|
|
5467
5775
|
await created.disconnect();
|
|
@@ -5469,7 +5777,8 @@ function createRoomEngine(options) {
|
|
|
5469
5777
|
}
|
|
5470
5778
|
driver = created;
|
|
5471
5779
|
await created.connect(token.serverUrl, token.token);
|
|
5472
|
-
store.patch({
|
|
5780
|
+
store.patch({ failure: null, connection: "stable" });
|
|
5781
|
+
store.dispatch({ type: "connected" });
|
|
5473
5782
|
store.setLocalTrack("microphone", IDLE_TRACK);
|
|
5474
5783
|
store.setLocalTrack("camera", IDLE_TRACK);
|
|
5475
5784
|
const effects = options.effectsStorage?.load() ?? store.snapshot().effects;
|
|
@@ -5540,9 +5849,17 @@ function createRoomEngine(options) {
|
|
|
5540
5849
|
return {
|
|
5541
5850
|
join(request) {
|
|
5542
5851
|
if (joining !== null) return joining;
|
|
5852
|
+
if (store.snapshot().phase !== "joining" && !store.dispatch({ type: "join", click: true })) {
|
|
5853
|
+
report(
|
|
5854
|
+
"warn",
|
|
5855
|
+
`meet.join: cannot join from "${store.snapshot().phase}"`,
|
|
5856
|
+
"Join is offered from the pre-join, left, disconnected and replaced screens only."
|
|
5857
|
+
);
|
|
5858
|
+
return Promise.resolve();
|
|
5859
|
+
}
|
|
5543
5860
|
lastRequest = request;
|
|
5544
5861
|
joining = connect(request).catch((error) => {
|
|
5545
|
-
throw
|
|
5862
|
+
throw failJoin(error, "meet.join");
|
|
5546
5863
|
}).finally(() => {
|
|
5547
5864
|
joining = null;
|
|
5548
5865
|
});
|
|
@@ -5559,10 +5876,16 @@ function createRoomEngine(options) {
|
|
|
5559
5876
|
return;
|
|
5560
5877
|
}
|
|
5561
5878
|
if (joining !== null) return joining;
|
|
5879
|
+
const phase = store.snapshot().phase;
|
|
5880
|
+
const moved = phase === "joining" || store.dispatch({ type: "join", click: true }) || store.dispatch({ type: "admitted" });
|
|
5881
|
+
if (!moved) {
|
|
5882
|
+
report("warn", `meet.rejoin: cannot rejoin from "${phase}"`, "Rejoin is offered after leaving, a lost connection, or admission.");
|
|
5883
|
+
return;
|
|
5884
|
+
}
|
|
5562
5885
|
tokens.invalidate(request.roomName);
|
|
5563
5886
|
current = null;
|
|
5564
5887
|
joining = connect(request).catch((error) => {
|
|
5565
|
-
throw
|
|
5888
|
+
throw failJoin(error, "meet.rejoin");
|
|
5566
5889
|
}).finally(() => {
|
|
5567
5890
|
joining = null;
|
|
5568
5891
|
});
|
|
@@ -5607,11 +5930,11 @@ function createRoomEngine(options) {
|
|
|
5607
5930
|
joining = connect(lastRequest).finally(() => {
|
|
5608
5931
|
joining = null;
|
|
5609
5932
|
});
|
|
5610
|
-
await joining.catch((again) => {
|
|
5611
|
-
throw
|
|
5933
|
+
await joining.catch(async (again) => {
|
|
5934
|
+
throw await lostRoom(again, "meet.moveToBreakout");
|
|
5612
5935
|
});
|
|
5613
5936
|
} else {
|
|
5614
|
-
throw
|
|
5937
|
+
throw await lostRoom(error, "meet.moveToBreakout");
|
|
5615
5938
|
}
|
|
5616
5939
|
throw normalized;
|
|
5617
5940
|
} finally {
|
|
@@ -5619,6 +5942,9 @@ function createRoomEngine(options) {
|
|
|
5619
5942
|
}
|
|
5620
5943
|
},
|
|
5621
5944
|
leave: leaveRoom,
|
|
5945
|
+
backToPrejoin() {
|
|
5946
|
+
store.dispatch({ type: "back_to_prejoin", click: true });
|
|
5947
|
+
},
|
|
5622
5948
|
// Turning a device on mid-meeting is the SAME operation as turning it on
|
|
5623
5949
|
// during the join, so it runs the same function. A failure here used to
|
|
5624
5950
|
// stamp the room `failed` — a busy microphone would blank a live meeting.
|
|
@@ -5632,21 +5958,41 @@ function createRoomEngine(options) {
|
|
|
5632
5958
|
},
|
|
5633
5959
|
async setScreenShareEnabled(enabled) {
|
|
5634
5960
|
if (driver === null) return;
|
|
5961
|
+
if (enabled && driver.supportsScreenShare?.() === false) {
|
|
5962
|
+
store.patch({ share: { state: "refused", reason: "unsupported", remedy: null, at: now() } });
|
|
5963
|
+
report("warn", "meet: this browser cannot share a screen", "Share from a desktop browser (Chrome, Edge, Firefox or Safari).");
|
|
5964
|
+
return;
|
|
5965
|
+
}
|
|
5966
|
+
if (enabled) store.patch({ share: { state: "picking", reason: null, remedy: null, at: now() } });
|
|
5635
5967
|
try {
|
|
5636
5968
|
await driver.setScreenShareEnabled(enabled);
|
|
5637
5969
|
ambiguousShareDenials = 0;
|
|
5970
|
+
store.patch({ share: { state: enabled ? "presenting" : "none", reason: null, remedy: null, at: now() } });
|
|
5638
5971
|
} catch (error) {
|
|
5639
5972
|
const kind = classifyScreenShareError(error);
|
|
5640
5973
|
if (kind === "ambiguous") {
|
|
5641
5974
|
ambiguousShareDenials += 1;
|
|
5642
|
-
if (ambiguousShareDenials < 2)
|
|
5975
|
+
if (ambiguousShareDenials < 2) {
|
|
5976
|
+
store.patch({ share: NO_SHARE });
|
|
5977
|
+
return;
|
|
5978
|
+
}
|
|
5643
5979
|
}
|
|
5980
|
+
ambiguousShareDenials = 0;
|
|
5644
5981
|
const normalized = normalizeScreenShareError(error, "meet.setScreenShareEnabled");
|
|
5645
5982
|
report("warn", normalized.message, normalized.remedy);
|
|
5646
|
-
|
|
5647
|
-
|
|
5983
|
+
store.patch({
|
|
5984
|
+
share: {
|
|
5985
|
+
state: "refused",
|
|
5986
|
+
reason: kind === "other" ? "failed" : "blocked",
|
|
5987
|
+
remedy: kind === "other" ? normalized.remedy : SCREEN_SHARE_BLOCKED_REMEDY_FOR(normalized.remedy),
|
|
5988
|
+
at: now()
|
|
5989
|
+
}
|
|
5990
|
+
});
|
|
5648
5991
|
}
|
|
5649
5992
|
},
|
|
5993
|
+
dismissShareNotice() {
|
|
5994
|
+
if (store.snapshot().share.state === "refused") store.patch({ share: NO_SHARE });
|
|
5995
|
+
},
|
|
5650
5996
|
async raiseHand(raised) {
|
|
5651
5997
|
const local = store.snapshot().localIdentity;
|
|
5652
5998
|
if (local !== null) store.setHand(local, raised);
|
|
@@ -6613,28 +6959,6 @@ function createMeetingRecordCache(options = {}) {
|
|
|
6613
6959
|
};
|
|
6614
6960
|
}
|
|
6615
6961
|
|
|
6616
|
-
// src/core/reasons.ts
|
|
6617
|
-
var JOIN_REFUSAL_REASONS = [
|
|
6618
|
-
"not_found",
|
|
6619
|
-
"cancelled",
|
|
6620
|
-
"ended",
|
|
6621
|
-
"expired",
|
|
6622
|
-
"too_early",
|
|
6623
|
-
"sign_in_required",
|
|
6624
|
-
"wrong_account",
|
|
6625
|
-
"not_invited",
|
|
6626
|
-
"locked",
|
|
6627
|
-
"removed",
|
|
6628
|
-
"lobby_rejects",
|
|
6629
|
-
"meeting_full",
|
|
6630
|
-
"platform_capacity",
|
|
6631
|
-
"verification_required",
|
|
6632
|
-
"registration_required"
|
|
6633
|
-
];
|
|
6634
|
-
function isJoinRefusalReason(value) {
|
|
6635
|
-
return typeof value === "string" && JOIN_REFUSAL_REASONS.includes(value);
|
|
6636
|
-
}
|
|
6637
|
-
|
|
6638
6962
|
// src/core/reactions.ts
|
|
6639
6963
|
var MEET_REACTIONS = ["\u{1F496}", "\u{1F44D}", "\u{1F389}", "\u{1F44F}", "\u{1F602}", "\u{1F62E}", "\u{1F622}", "\u{1F914}", "\u{1F44E}"];
|
|
6640
6964
|
|
|
@@ -6733,43 +7057,12 @@ function endedRecord(snapshot, given) {
|
|
|
6733
7057
|
function observedPhase(input) {
|
|
6734
7058
|
const { snapshot } = input;
|
|
6735
7059
|
if (snapshot === null) return "resolving";
|
|
6736
|
-
const
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
const reason = raw === "failed" ? snapshot.failure?.reason ?? null : null;
|
|
6740
|
-
if (reason !== null) return reason === "ended" ? "ended" : `refused:${reason}`;
|
|
6741
|
-
switch (raw) {
|
|
6742
|
-
case "idle":
|
|
6743
|
-
case "failed":
|
|
6744
|
-
case "left":
|
|
6745
|
-
return "prejoin";
|
|
6746
|
-
case "lobby":
|
|
6747
|
-
return waitingPhase(snapshot);
|
|
6748
|
-
case "requesting-token":
|
|
6749
|
-
case "connecting":
|
|
6750
|
-
return "joining";
|
|
6751
|
-
case "connected":
|
|
6752
|
-
case "reconnecting":
|
|
6753
|
-
return "in_call";
|
|
6754
|
-
}
|
|
7060
|
+
const phase = snapshot.phase;
|
|
7061
|
+
if (endedRecord(snapshot, input.meeting ?? null) && !isLivePhase(phase) && !isCallPhase(phase)) return "ended";
|
|
7062
|
+
return phase;
|
|
6755
7063
|
}
|
|
6756
|
-
function
|
|
6757
|
-
|
|
6758
|
-
case "waiting_host":
|
|
6759
|
-
return "waiting:host_not_started";
|
|
6760
|
-
case "denied":
|
|
6761
|
-
return "denied";
|
|
6762
|
-
case "expired":
|
|
6763
|
-
return "knock_expired";
|
|
6764
|
-
case "withdrawn":
|
|
6765
|
-
return "left";
|
|
6766
|
-
case "ended":
|
|
6767
|
-
return "ended";
|
|
6768
|
-
case "removed":
|
|
6769
|
-
return "refused:removed";
|
|
6770
|
-
default:
|
|
6771
|
-
return "waiting:knocking";
|
|
6772
|
-
}
|
|
7064
|
+
function isCallPhase(phase) {
|
|
7065
|
+
return phase.startsWith("ringing_") || phase.startsWith("call_") || phase === "answered_elsewhere";
|
|
6773
7066
|
}
|
|
6774
7067
|
var ADMITTER_ROLES = /* @__PURE__ */ new Set(["host", "cohost"]);
|
|
6775
7068
|
function observe(input) {
|
|
@@ -6782,10 +7075,10 @@ function observe(input) {
|
|
|
6782
7075
|
const deviceInPlay = phase === "joining" || inCall;
|
|
6783
7076
|
return {
|
|
6784
7077
|
phase,
|
|
6785
|
-
reason: phase
|
|
7078
|
+
reason: phase === "ended" ? snapshot?.reason ?? null : snapshot?.reason ?? reasonOf(phase),
|
|
6786
7079
|
role,
|
|
6787
|
-
connection: snapshot?.
|
|
6788
|
-
hostPresent: inCall && snapshot !== null ? snapshot.participants.some((p) => ADMITTER_ROLES.has(p.role)) : snapshot
|
|
7080
|
+
connection: snapshot?.connection ?? "stable",
|
|
7081
|
+
hostPresent: inCall && snapshot !== null ? snapshot.participants.some((p) => ADMITTER_ROLES.has(p.role)) : snapshot !== null && isWaitingPhase(snapshot.phase) ? snapshot.waiting?.admittersPresent ?? null : null,
|
|
6789
7082
|
lobbyCount: canAdmit && snapshot !== null ? snapshot.lobby.filter((entry) => entry.state === "knocking").length : 0,
|
|
6790
7083
|
recording: snapshot?.recording === "recording" || snapshot?.recording === "stopping",
|
|
6791
7084
|
audioBlocked: null,
|
|
@@ -6877,9 +7170,11 @@ export {
|
|
|
6877
7170
|
GUEST_RECORD_ACCESS_METADATA_KEY,
|
|
6878
7171
|
GUEST_RECORD_NOT_SHARED,
|
|
6879
7172
|
IDLE_MEDIA,
|
|
7173
|
+
IDLE_PHASES,
|
|
6880
7174
|
IDLE_TRACK,
|
|
6881
7175
|
JOIN_REFUSAL_REASONS,
|
|
6882
7176
|
LISTEN_ONLY_NOTICE,
|
|
7177
|
+
LIVE_PHASES,
|
|
6883
7178
|
MEETING_INVITE_KIND,
|
|
6884
7179
|
MEETING_INVITE_VERSION,
|
|
6885
7180
|
MEETING_PASS_HEADER,
|
|
@@ -6895,6 +7190,7 @@ export {
|
|
|
6895
7190
|
NOTE_TAKER_IDENTITY_PREFIX,
|
|
6896
7191
|
NOTE_TAKER_METADATA_KEY,
|
|
6897
7192
|
NO_GRANTS,
|
|
7193
|
+
NO_SHARE,
|
|
6898
7194
|
ORGANIZATION_HEADER,
|
|
6899
7195
|
PARTICIPANT_CAN_RECORD_ATTRIBUTE,
|
|
6900
7196
|
PARTICIPANT_ROLE_ATTRIBUTE,
|
|
@@ -6908,9 +7204,11 @@ export {
|
|
|
6908
7204
|
TABLES,
|
|
6909
7205
|
TRANSCRIPTION_ATTRIBUTES,
|
|
6910
7206
|
TRANSCRIPTION_TOPIC,
|
|
7207
|
+
WAITING_PHASES,
|
|
6911
7208
|
absenceSentence,
|
|
6912
7209
|
activeWrapUpSummary,
|
|
6913
7210
|
activityAttention,
|
|
7211
|
+
admissionPhase,
|
|
6914
7212
|
announceMeeting,
|
|
6915
7213
|
appPanelOf,
|
|
6916
7214
|
applyCollabPacket,
|
|
@@ -6980,10 +7278,13 @@ export {
|
|
|
6980
7278
|
isJoinRefusalReason,
|
|
6981
7279
|
isLinkFollower,
|
|
6982
7280
|
isListenOnly,
|
|
7281
|
+
isLivePhase,
|
|
6983
7282
|
isNoteTaker,
|
|
6984
7283
|
isObserverRole,
|
|
6985
7284
|
isRealName,
|
|
7285
|
+
isRefusedPhase,
|
|
6986
7286
|
isRoomEventTopic,
|
|
7287
|
+
isWaitingPhase,
|
|
6987
7288
|
learnName,
|
|
6988
7289
|
learnNames,
|
|
6989
7290
|
listenOnlyNotice,
|
|
@@ -7007,6 +7308,7 @@ export {
|
|
|
7007
7308
|
mergeRecord,
|
|
7008
7309
|
microphoneNoticeCode,
|
|
7009
7310
|
moveToRoom,
|
|
7311
|
+
nextPhase,
|
|
7010
7312
|
nextTranslationBatch,
|
|
7011
7313
|
normalizeDeviceError,
|
|
7012
7314
|
normalizeMeetError,
|
|
@@ -7039,10 +7341,13 @@ export {
|
|
|
7039
7341
|
pushMeetingToGoogleCalendar,
|
|
7040
7342
|
readServerRefusal,
|
|
7041
7343
|
readableTranscript,
|
|
7344
|
+
reasonOf,
|
|
7042
7345
|
recordingLabel,
|
|
7043
7346
|
recordingNotice,
|
|
7044
7347
|
recordingOffsetMs,
|
|
7348
|
+
refusalPhase,
|
|
7045
7349
|
rememberedMeetingPass,
|
|
7350
|
+
resolveExit,
|
|
7046
7351
|
roleOf,
|
|
7047
7352
|
roomTopic,
|
|
7048
7353
|
rootAttributes,
|