@ai-matrx/meet 0.11.36 → 0.11.38
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 +12 -0
- package/dist/core.cjs +129 -87
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +66 -22
- package/dist/core.d.ts +66 -22
- package/dist/core.js +129 -87
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +129 -87
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +129 -87
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +231 -107
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +17 -3
- package/dist/react.d.ts +17 -3
- package/dist/react.js +231 -107
- package/dist/react.js.map +1 -1
- package/dist/skins/meet.cjs +120 -20
- package/dist/skins/meet.cjs.map +1 -1
- package/dist/skins/meet.js +120 -20
- package/dist/skins/meet.js.map +1 -1
- package/dist/styles.css +7 -0
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog — `@ai-matrx/meet`
|
|
2
2
|
|
|
3
|
+
## 0.11.38
|
|
4
|
+
|
|
5
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
6
|
+
`git diff npm/meet/v0.11.37..npm/meet/v0.11.38 -- apps/shared/meet`).
|
|
7
|
+
No source changes intended and no consumer action required.
|
|
8
|
+
|
|
9
|
+
## 0.11.37
|
|
10
|
+
|
|
11
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
12
|
+
`git diff npm/meet/v0.11.36..npm/meet/v0.11.37 -- apps/shared/meet`).
|
|
13
|
+
No source changes intended and no consumer action required.
|
|
14
|
+
|
|
3
15
|
## 0.11.36
|
|
4
16
|
|
|
5
17
|
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
package/dist/core.cjs
CHANGED
|
@@ -38,6 +38,7 @@ __export(core_exports, {
|
|
|
38
38
|
DATA_TOPICS: () => DATA_TOPICS,
|
|
39
39
|
DEFAULT_CONNECTION_POLICY: () => DEFAULT_CONNECTION_POLICY,
|
|
40
40
|
DEFAULT_EFFECTS: () => DEFAULT_EFFECTS,
|
|
41
|
+
DEFAULT_LEAVE_POLICY: () => DEFAULT_LEAVE_POLICY,
|
|
41
42
|
DEFAULT_PAGE_SIZE: () => DEFAULT_PAGE_SIZE,
|
|
42
43
|
EMPTY_COLLAB: () => EMPTY_COLLAB,
|
|
43
44
|
END_MEETING_NOT_SERVED: () => END_MEETING_NOT_SERVED,
|
|
@@ -72,6 +73,7 @@ __export(core_exports, {
|
|
|
72
73
|
NO_SHARE: () => NO_SHARE,
|
|
73
74
|
ORGANIZATION_HEADER: () => ORGANIZATION_HEADER,
|
|
74
75
|
PARTICIPANT_CAN_RECORD_ATTRIBUTE: () => PARTICIPANT_CAN_RECORD_ATTRIBUTE,
|
|
76
|
+
PARTICIPANT_HAND_ATTRIBUTE: () => PARTICIPANT_HAND_ATTRIBUTE,
|
|
75
77
|
PARTICIPANT_ROLE_ATTRIBUTE: () => PARTICIPANT_ROLE_ATTRIBUTE,
|
|
76
78
|
PARTICIPANT_STANDING_ATTRIBUTE: () => PARTICIPANT_STANDING_ATTRIBUTE,
|
|
77
79
|
REACTION_TTL_MS: () => REACTION_TTL_MS,
|
|
@@ -184,6 +186,8 @@ __export(core_exports, {
|
|
|
184
186
|
isWaitingPhase: () => isWaitingPhase,
|
|
185
187
|
learnName: () => learnName,
|
|
186
188
|
learnNames: () => learnNames,
|
|
189
|
+
leaveChoices: () => leaveChoices,
|
|
190
|
+
leavePolicyFrom: () => leavePolicyFrom,
|
|
187
191
|
listenOnlyNotice: () => listenOnlyNotice,
|
|
188
192
|
loadFollowUpDraft: () => loadFollowUpDraft,
|
|
189
193
|
loadGuestMeetingRecord: () => loadGuestMeetingRecord,
|
|
@@ -831,6 +835,30 @@ function mergeGhosts(live, ghosts, at) {
|
|
|
831
835
|
return { roster: [...live, ...extra], kept };
|
|
832
836
|
}
|
|
833
837
|
|
|
838
|
+
// src/core/leave.ts
|
|
839
|
+
var DEFAULT_LEAVE_POLICY = { hostLeavePrompt: "leave_or_end", endConfirm: false };
|
|
840
|
+
var PROMPTS = ["leave_or_end", "must_assign_or_end", "leave_only"];
|
|
841
|
+
function leavePolicyFrom(raw) {
|
|
842
|
+
if (typeof raw !== "object" || raw === null) return DEFAULT_LEAVE_POLICY;
|
|
843
|
+
const value = raw;
|
|
844
|
+
const prompt = value["host_leave_prompt"];
|
|
845
|
+
const confirm = value["end_confirm"];
|
|
846
|
+
return {
|
|
847
|
+
hostLeavePrompt: PROMPTS.includes(prompt) ? prompt : DEFAULT_LEAVE_POLICY.hostLeavePrompt,
|
|
848
|
+
endConfirm: typeof confirm === "boolean" ? confirm : DEFAULT_LEAVE_POLICY.endConfirm
|
|
849
|
+
};
|
|
850
|
+
}
|
|
851
|
+
function leaveChoices(args) {
|
|
852
|
+
if (args.role !== "host") return ["leave"];
|
|
853
|
+
switch (args.policy.hostLeavePrompt) {
|
|
854
|
+
case "must_assign_or_end":
|
|
855
|
+
return args.othersPresent ? ["assign_and_leave", "end_for_all"] : ["leave", "end_for_all"];
|
|
856
|
+
case "leave_only":
|
|
857
|
+
case "leave_or_end":
|
|
858
|
+
return ["leave", "end_for_all"];
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
|
|
834
862
|
// src/core/tokens.ts
|
|
835
863
|
function createWebRoomTokenStorage(onDiagnostic) {
|
|
836
864
|
const store = globalThis.localStorage;
|
|
@@ -938,6 +966,12 @@ var MEET_ROUTES = {
|
|
|
938
966
|
state: "/api/v1/meet/state",
|
|
939
967
|
/** S4: `withdraw` (stop waiting) or `leave` (close this tab); the pass may ride in the body. */
|
|
940
968
|
leave: "/api/v1/meet/leave",
|
|
969
|
+
/**
|
|
970
|
+
* S8: a host's browser just called an admission DOOR (`meet_admit` · `meet_deny` ·
|
|
971
|
+
* `meet_undeny` · `meet_admit_all`). Payload-free: the server republishes the room's
|
|
972
|
+
* replicated state (the People badge's waiting count) from the database truth.
|
|
973
|
+
*/
|
|
974
|
+
admissionChanged: "/api/v1/meet/admission/changed",
|
|
941
975
|
/** S4: a pass holder (guests included) saw the recording notice, for this run. */
|
|
942
976
|
consent: "/api/v1/meet/consent"
|
|
943
977
|
};
|
|
@@ -1022,7 +1056,8 @@ function parseRoomToken(body, roomName) {
|
|
|
1022
1056
|
pollSeconds: typeof payload["poll_seconds"] === "number" ? payload["poll_seconds"] : void 0,
|
|
1023
1057
|
breakoutRoomId: readString(payload, "breakout_room_id") ?? null,
|
|
1024
1058
|
observersVisibleTo: readString(payload, "observers_visible_to") === "hosts" ? "hosts" : "everyone",
|
|
1025
|
-
connectionPolicy: connectionPolicyFrom(payload["connection_policy"])
|
|
1059
|
+
connectionPolicy: connectionPolicyFrom(payload["connection_policy"]),
|
|
1060
|
+
leavePolicy: leavePolicyFrom(payload["leave_policy"])
|
|
1026
1061
|
};
|
|
1027
1062
|
}
|
|
1028
1063
|
function createTokenClient(options) {
|
|
@@ -3721,6 +3756,10 @@ var EMPTY = {
|
|
|
3721
3756
|
chatHistoryError: null,
|
|
3722
3757
|
reactions: [],
|
|
3723
3758
|
spotlight: null,
|
|
3759
|
+
actingHost: null,
|
|
3760
|
+
presenter: null,
|
|
3761
|
+
waitingCount: 0,
|
|
3762
|
+
leavePolicy: DEFAULT_LEAVE_POLICY,
|
|
3724
3763
|
moderationNotice: null,
|
|
3725
3764
|
actionNotice: null,
|
|
3726
3765
|
privateChatRequest: null,
|
|
@@ -3782,8 +3821,6 @@ function createMeetStore(initial = {}) {
|
|
|
3782
3821
|
},
|
|
3783
3822
|
setParticipants(participants) {
|
|
3784
3823
|
const names = learnNames(state.names, participants);
|
|
3785
|
-
const hands = new Map(state.participants.map((p) => [p.identity, p.handRaised]));
|
|
3786
|
-
const handTimes = new Map(state.participants.map((p) => [p.identity, p.handRaisedAt ?? null]));
|
|
3787
3824
|
const quality = new Map(state.participants.map((p) => [p.identity, p.quality]));
|
|
3788
3825
|
commit({
|
|
3789
3826
|
...state,
|
|
@@ -3796,8 +3833,6 @@ function createMeetStore(initial = {}) {
|
|
|
3796
3833
|
// identity could reach a screen, and it is the place that asks the
|
|
3797
3834
|
// name book. `roster-names.test.ts` fails if a token ever gets past it.
|
|
3798
3835
|
displayName: displayNameFor(names, participant.identity, participant.displayName),
|
|
3799
|
-
handRaised: hands.get(participant.identity) ?? participant.handRaised,
|
|
3800
|
-
handRaisedAt: handTimes.get(participant.identity) ?? participant.handRaisedAt ?? null,
|
|
3801
3836
|
quality: participant.quality === "unknown" ? quality.get(participant.identity) ?? "unknown" : participant.quality
|
|
3802
3837
|
}))
|
|
3803
3838
|
});
|
|
@@ -3820,20 +3855,6 @@ function createMeetStore(initial = {}) {
|
|
|
3820
3855
|
)
|
|
3821
3856
|
});
|
|
3822
3857
|
},
|
|
3823
|
-
setHand(identity, raised, at) {
|
|
3824
|
-
commit({
|
|
3825
|
-
...state,
|
|
3826
|
-
participants: state.participants.map(
|
|
3827
|
-
(participant) => participant.identity === identity ? {
|
|
3828
|
-
...participant,
|
|
3829
|
-
handRaised: raised,
|
|
3830
|
-
// A hand that is ALREADY up keeps its place in the queue when
|
|
3831
|
-
// it is re-announced (to a late joiner): the first time wins.
|
|
3832
|
-
handRaisedAt: raised ? participant.handRaised && participant.handRaisedAt != null ? participant.handRaisedAt : at ?? Date.now() : null
|
|
3833
|
-
} : participant
|
|
3834
|
-
)
|
|
3835
|
-
});
|
|
3836
|
-
},
|
|
3837
3858
|
addChat(message) {
|
|
3838
3859
|
if (state.chat.some((existing) => existing.id === message.id)) return;
|
|
3839
3860
|
const chat = [...state.chat, message];
|
|
@@ -3982,18 +4003,6 @@ var ROOM_EVENTS = {
|
|
|
3982
4003
|
wrapUp: "matrx.meet.wrap_up",
|
|
3983
4004
|
/** The meeting ended for everyone. Payload `{ meeting_id, ended_at, trigger }`. */
|
|
3984
4005
|
ended: "matrx.meet.ended",
|
|
3985
|
-
/**
|
|
3986
|
-
* A `meet_recordings` row changed state. Payload
|
|
3987
|
-
* `{ meeting_id, recording: { id, state, started_by } }`.
|
|
3988
|
-
*
|
|
3989
|
-
* 🚨 THIS IS THE ONLY WAY A GUEST LEARNS A RECORDING IS RUNNING. PreJoin
|
|
3990
|
-
* promises every joiner an indicator, and `anon` holds no SELECT grant on
|
|
3991
|
-
* `meet_recordings` (MRI-A10 settled that widening it is forbidden), so
|
|
3992
|
-
* without this packet the promise was a sentence with nothing behind it: on
|
|
3993
|
-
* production 2026-09-09 the guest lane showed no indicator at all while the
|
|
3994
|
-
* host recorded (MRI-C8).
|
|
3995
|
-
*/
|
|
3996
|
-
recording: "matrx.meet.recording",
|
|
3997
4006
|
/**
|
|
3998
4007
|
* A chat message to everyone was SAVED (Meet wave 2). Payload
|
|
3999
4008
|
* `{ message: { id, meeting_id, sender_identity, sender_name, body, created_at } }`.
|
|
@@ -4046,8 +4055,6 @@ function applyRoomEvent(args) {
|
|
|
4046
4055
|
return applyWrapUp(store, payload, now);
|
|
4047
4056
|
case ROOM_EVENTS.ended:
|
|
4048
4057
|
return applyEnded(store, payload);
|
|
4049
|
-
case ROOM_EVENTS.recording:
|
|
4050
|
-
return applyRecording(store, payload);
|
|
4051
4058
|
case ROOM_EVENTS.chat:
|
|
4052
4059
|
return applyChat(store, payload);
|
|
4053
4060
|
case ROOM_EVENTS.moderation:
|
|
@@ -4127,9 +4134,9 @@ function applyWrapUp(store, payload, now) {
|
|
|
4127
4134
|
store.announceWrapUp(announcement);
|
|
4128
4135
|
return HANDLED;
|
|
4129
4136
|
}
|
|
4130
|
-
function
|
|
4137
|
+
function applyRecordingState(store, payload) {
|
|
4131
4138
|
const row = object(payload["recording"]);
|
|
4132
|
-
if (row === null) return ignored("
|
|
4139
|
+
if (row === null) return ignored("room state carries no recording");
|
|
4133
4140
|
const meetingId = text2(payload["meeting_id"]);
|
|
4134
4141
|
const meeting = store.snapshot().meeting;
|
|
4135
4142
|
if (meeting !== null && meetingId !== null && meetingId !== meeting.id) {
|
|
@@ -4211,19 +4218,6 @@ function applyModeration(store, payload, now) {
|
|
|
4211
4218
|
}
|
|
4212
4219
|
const kind = text2(payload["kind"]);
|
|
4213
4220
|
switch (kind) {
|
|
4214
|
-
case "lower-hands": {
|
|
4215
|
-
const raw = payload["identities"];
|
|
4216
|
-
const everyone = raw === "*";
|
|
4217
|
-
const named = new Set(
|
|
4218
|
-
Array.isArray(raw) ? raw.filter((value) => typeof value === "string") : []
|
|
4219
|
-
);
|
|
4220
|
-
for (const participant of snapshot.participants) {
|
|
4221
|
-
if (participant.handRaised && (everyone || named.has(participant.identity))) {
|
|
4222
|
-
store.setHand(participant.identity, false);
|
|
4223
|
-
}
|
|
4224
|
-
}
|
|
4225
|
-
return HANDLED;
|
|
4226
|
-
}
|
|
4227
4221
|
case "role": {
|
|
4228
4222
|
const identity = text2(payload["identity"]);
|
|
4229
4223
|
const role = text2(payload["role"]);
|
|
@@ -4615,7 +4609,6 @@ function gridColumns(count2) {
|
|
|
4615
4609
|
|
|
4616
4610
|
// src/core/room-driver.ts
|
|
4617
4611
|
var DATA_TOPICS = {
|
|
4618
|
-
hand: "mx.hand",
|
|
4619
4612
|
reaction: "mx.reaction",
|
|
4620
4613
|
chat: "mx.chat"
|
|
4621
4614
|
};
|
|
@@ -5249,7 +5242,7 @@ function createMeetingSession(options) {
|
|
|
5249
5242
|
})();
|
|
5250
5243
|
return reading;
|
|
5251
5244
|
}
|
|
5252
|
-
async function postLeave(intent) {
|
|
5245
|
+
async function postLeave(intent, extra = {}) {
|
|
5253
5246
|
const meeting = requireMeeting(`meet.${intent}`);
|
|
5254
5247
|
const pass = options.resolvePass?.() ?? null;
|
|
5255
5248
|
const response = await options.api.request({
|
|
@@ -5257,7 +5250,7 @@ function createMeetingSession(options) {
|
|
|
5257
5250
|
method: "POST",
|
|
5258
5251
|
requireAuth: false,
|
|
5259
5252
|
operation: `meet.${intent}`,
|
|
5260
|
-
body: { meeting_id: meeting.id, intent },
|
|
5253
|
+
body: { meeting_id: meeting.id, intent, ...extra },
|
|
5261
5254
|
...pass !== null ? { headers: { [MEETING_PASS_HEADER]: pass } } : {}
|
|
5262
5255
|
});
|
|
5263
5256
|
if (!response.ok) {
|
|
@@ -5271,13 +5264,41 @@ function createMeetingSession(options) {
|
|
|
5271
5264
|
throw new MeetError(
|
|
5272
5265
|
"transport",
|
|
5273
5266
|
refusal2?.reason ?? `meet.${intent}: the server answered ${response.status}`,
|
|
5274
|
-
refusal2?.remedy ?? "You are still in the waiting room. Try again."
|
|
5267
|
+
refusal2?.remedy ?? (intent === "withdraw" ? "You are still in the waiting room. Try again." : "Nothing was changed. Try again.")
|
|
5275
5268
|
);
|
|
5276
5269
|
}
|
|
5277
5270
|
}
|
|
5278
5271
|
function hint() {
|
|
5279
5272
|
channel?.send(MEET_EVENTS.stateChanged, { v: null });
|
|
5280
5273
|
}
|
|
5274
|
+
async function tellServerAdmissionChanged(operation) {
|
|
5275
|
+
const meeting = store.snapshot().meeting;
|
|
5276
|
+
if (meeting === null) return;
|
|
5277
|
+
const pass = options.resolvePass?.() ?? null;
|
|
5278
|
+
try {
|
|
5279
|
+
const response = await options.api.request({
|
|
5280
|
+
path: MEET_ROUTES.admissionChanged,
|
|
5281
|
+
method: "POST",
|
|
5282
|
+
requireAuth: false,
|
|
5283
|
+
operation,
|
|
5284
|
+
body: { meeting_id: meeting.id },
|
|
5285
|
+
...pass !== null ? { headers: { [MEETING_PASS_HEADER]: pass } } : {}
|
|
5286
|
+
});
|
|
5287
|
+
if (!response.ok) {
|
|
5288
|
+
report(
|
|
5289
|
+
"warn",
|
|
5290
|
+
`${operation}: the server answered ${response.status} when told about the admission change`,
|
|
5291
|
+
"The decision was saved. The waiting count in the room may lag until the next change."
|
|
5292
|
+
);
|
|
5293
|
+
}
|
|
5294
|
+
} catch (error) {
|
|
5295
|
+
report(
|
|
5296
|
+
"warn",
|
|
5297
|
+
`${operation}: ${String(error)}`,
|
|
5298
|
+
"The decision was saved. The waiting count in the room may lag until the next change."
|
|
5299
|
+
);
|
|
5300
|
+
}
|
|
5301
|
+
}
|
|
5281
5302
|
async function refreshQueue() {
|
|
5282
5303
|
const meeting = store.snapshot().meeting;
|
|
5283
5304
|
if (meeting === null || isGuest(identity) || !isHostRole(effectiveRole(store.snapshot()))) return;
|
|
@@ -5433,6 +5454,7 @@ function createMeetingSession(options) {
|
|
|
5433
5454
|
decidedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
5434
5455
|
decidedBy: by
|
|
5435
5456
|
});
|
|
5457
|
+
await tellServerAdmissionChanged("meet.admit");
|
|
5436
5458
|
hint();
|
|
5437
5459
|
},
|
|
5438
5460
|
async undeny(entry) {
|
|
@@ -5445,6 +5467,7 @@ function createMeetingSession(options) {
|
|
|
5445
5467
|
byUserId: by
|
|
5446
5468
|
});
|
|
5447
5469
|
store.upsertLobby({ ...entry, state: decidedState(row.admissionState), decidedAt: (/* @__PURE__ */ new Date()).toISOString(), decidedBy: by });
|
|
5470
|
+
await tellServerAdmissionChanged("meet.undeny");
|
|
5448
5471
|
hint();
|
|
5449
5472
|
},
|
|
5450
5473
|
async admitAll() {
|
|
@@ -5454,6 +5477,7 @@ function createMeetingSession(options) {
|
|
|
5454
5477
|
for (const row of rows) {
|
|
5455
5478
|
store.setAdmission(row.identity, row.admissionState, by);
|
|
5456
5479
|
}
|
|
5480
|
+
await tellServerAdmissionChanged("meet.admitAll");
|
|
5457
5481
|
hint();
|
|
5458
5482
|
},
|
|
5459
5483
|
startWaiting() {
|
|
@@ -5495,6 +5519,10 @@ function createMeetingSession(options) {
|
|
|
5495
5519
|
store.dispatch({ type: "admission", admission: "withdrawn" });
|
|
5496
5520
|
hint();
|
|
5497
5521
|
},
|
|
5522
|
+
async hostLeave(intent) {
|
|
5523
|
+
if (intent === "end_for_all") await postLeave("end_for_all");
|
|
5524
|
+
else await postLeave("assign_and_leave", { assign_to: intent.assignTo });
|
|
5525
|
+
},
|
|
5498
5526
|
async askAgain() {
|
|
5499
5527
|
await options.rejoin?.();
|
|
5500
5528
|
},
|
|
@@ -6456,6 +6484,11 @@ function SCREEN_SHARE_BLOCKED_REMEDY_FOR(remedy) {
|
|
|
6456
6484
|
return /administrator|policy/i.test(remedy) ? remedy : SCREEN_SHARE_BLOCKED_REMEDY;
|
|
6457
6485
|
}
|
|
6458
6486
|
var PARTICIPANT_ROLE_ATTRIBUTE = "matrx.participant.role";
|
|
6487
|
+
var PARTICIPANT_HAND_ATTRIBUTE = "matrx.hand";
|
|
6488
|
+
function handFrom(value) {
|
|
6489
|
+
const at = value === void 0 || value.length === 0 ? Number.NaN : Number(value);
|
|
6490
|
+
return Number.isFinite(at) ? { handRaised: true, handRaisedAt: at } : { handRaised: false, handRaisedAt: null };
|
|
6491
|
+
}
|
|
6459
6492
|
var PARTICIPANT_CAN_RECORD_ATTRIBUTE = "matrx.participant.can_record";
|
|
6460
6493
|
var CONNECTION_KIND_ATTRIBUTE = "matrx.participant.connection_kind";
|
|
6461
6494
|
var PARTICIPANT_STANDING_ATTRIBUTE = "matrx.participant.standing";
|
|
@@ -6509,7 +6542,10 @@ function projectParticipant(driver, joinedAt) {
|
|
|
6509
6542
|
cameraEnabled: driver.cameraEnabled,
|
|
6510
6543
|
screenSharing: driver.screenSharing,
|
|
6511
6544
|
speaking: false,
|
|
6512
|
-
|
|
6545
|
+
// S8: a hand is the SERVER's (`hand_raised_at` on the person row, `/moderate raise_hand`),
|
|
6546
|
+
// replicated as the `matrx.hand` attribute: epoch ms of the raise, "" when down. It is
|
|
6547
|
+
// therefore delivered to late joiners and survives refresh and reconnect.
|
|
6548
|
+
...handFrom(driver.attributes[PARTICIPANT_HAND_ATTRIBUTE]),
|
|
6513
6549
|
quality: "unknown",
|
|
6514
6550
|
joinedAt
|
|
6515
6551
|
};
|
|
@@ -6639,40 +6675,38 @@ function createRoomEngine(options) {
|
|
|
6639
6675
|
},
|
|
6640
6676
|
participants(list) {
|
|
6641
6677
|
const joinedAt = new Date(now()).toISOString();
|
|
6642
|
-
const before = new Set(store.snapshot().participants.map((p) => p.identity));
|
|
6643
6678
|
projectRoster(list, joinedAt);
|
|
6644
|
-
const snapshot = store.snapshot();
|
|
6645
|
-
const newcomer = snapshot.participants.some(
|
|
6646
|
-
(participant) => !participant.isLocal && !before.has(participant.identity)
|
|
6647
|
-
);
|
|
6648
|
-
const me = snapshot.participants.find((p) => p.identity === snapshot.localIdentity);
|
|
6649
|
-
if (newcomer && before.size > 0 && me?.handRaised === true) {
|
|
6650
|
-
void publish(DATA_TOPICS.hand, { raised: true, raisedAt: me.handRaisedAt ?? now() }).catch(
|
|
6651
|
-
() => void 0
|
|
6652
|
-
);
|
|
6653
|
-
}
|
|
6654
6679
|
},
|
|
6655
6680
|
participantLeft(who, reason) {
|
|
6656
6681
|
departures.set(who, reason);
|
|
6657
6682
|
},
|
|
6658
6683
|
roomMetadata(metadata) {
|
|
6659
|
-
let
|
|
6684
|
+
let parsed = {};
|
|
6660
6685
|
if (metadata.length > 0) {
|
|
6661
6686
|
try {
|
|
6662
|
-
const
|
|
6663
|
-
if (typeof
|
|
6664
|
-
const value = parsed.spotlight;
|
|
6665
|
-
if (typeof value === "string" && value.length > 0) spotlight = asParticipantIdentity(value);
|
|
6666
|
-
}
|
|
6687
|
+
const value = JSON.parse(metadata);
|
|
6688
|
+
if (typeof value === "object" && value !== null) parsed = value;
|
|
6667
6689
|
} catch {
|
|
6668
6690
|
report(
|
|
6669
6691
|
"warn",
|
|
6670
|
-
"meet: the room's metadata is not JSON, so
|
|
6671
|
-
"Only aidream writes room metadata; check services/meet/
|
|
6692
|
+
"meet: the room's metadata is not JSON, so the room state was not read from it",
|
|
6693
|
+
"Only aidream writes room metadata; check services/meet/room_state.py."
|
|
6672
6694
|
);
|
|
6673
6695
|
}
|
|
6674
6696
|
}
|
|
6675
|
-
|
|
6697
|
+
const key = (name) => {
|
|
6698
|
+
const value = parsed[name];
|
|
6699
|
+
return typeof value === "string" && value.length > 0 ? asParticipantIdentity(personOf(value)) : null;
|
|
6700
|
+
};
|
|
6701
|
+
const waiting = typeof parsed["waiting_count"] === "number" ? parsed["waiting_count"] : 0;
|
|
6702
|
+
const before = store.snapshot();
|
|
6703
|
+
const next = { spotlight: key("spotlight"), actingHost: key("acting_host"), presenter: key("presenter"), waitingCount: waiting };
|
|
6704
|
+
if (before.spotlight !== next.spotlight || before.actingHost !== next.actingHost || before.presenter !== next.presenter || before.waitingCount !== next.waitingCount) {
|
|
6705
|
+
store.patch(next);
|
|
6706
|
+
}
|
|
6707
|
+
if (parsed["recording"] !== void 0 && parsed["recording"] !== null) {
|
|
6708
|
+
applyRecordingState(store, { meeting_id: parsed["meeting_id"], recording: parsed["recording"] });
|
|
6709
|
+
}
|
|
6676
6710
|
},
|
|
6677
6711
|
activeSpeakers(identities) {
|
|
6678
6712
|
store.setSpeaking([...new Set(identities.map((who) => personOf(who)))]);
|
|
@@ -6774,13 +6808,6 @@ function createRoomEngine(options) {
|
|
|
6774
6808
|
}
|
|
6775
6809
|
const sender = personOf(from ?? "");
|
|
6776
6810
|
switch (topic) {
|
|
6777
|
-
case DATA_TOPICS.hand:
|
|
6778
|
-
store.setHand(
|
|
6779
|
-
sender,
|
|
6780
|
-
envelope.raised === true,
|
|
6781
|
-
typeof envelope.raisedAt === "number" ? envelope.raisedAt : now()
|
|
6782
|
-
);
|
|
6783
|
-
return;
|
|
6784
6811
|
case DATA_TOPICS.reaction:
|
|
6785
6812
|
if (typeof envelope.emoji === "string") {
|
|
6786
6813
|
store.addReaction({
|
|
@@ -6879,6 +6906,7 @@ function createRoomEngine(options) {
|
|
|
6879
6906
|
current = token;
|
|
6880
6907
|
lastServerUrl = token.serverUrl;
|
|
6881
6908
|
connectionPolicy = token.connectionPolicy ?? DEFAULT_CONNECTION_POLICY;
|
|
6909
|
+
if (token.leavePolicy !== void 0) store.patch({ leavePolicy: token.leavePolicy });
|
|
6882
6910
|
store.patch({
|
|
6883
6911
|
localIdentity: token.identity,
|
|
6884
6912
|
breakoutRoomId: token.breakoutRoomId ?? null,
|
|
@@ -7245,11 +7273,6 @@ function createRoomEngine(options) {
|
|
|
7245
7273
|
dismissShareNotice() {
|
|
7246
7274
|
if (store.snapshot().share.state === "refused") store.patch({ share: NO_SHARE });
|
|
7247
7275
|
},
|
|
7248
|
-
async raiseHand(raised) {
|
|
7249
|
-
const local = store.snapshot().localIdentity;
|
|
7250
|
-
if (local !== null) store.setHand(local, raised);
|
|
7251
|
-
await publish(DATA_TOPICS.hand, { raised, raisedAt: now() });
|
|
7252
|
-
},
|
|
7253
7276
|
async react(emoji) {
|
|
7254
7277
|
const local = store.snapshot().localIdentity;
|
|
7255
7278
|
const id = `${local ?? "local"}-${now()}`;
|
|
@@ -7378,6 +7401,8 @@ var MODERATION_ACTIONS = [
|
|
|
7378
7401
|
"ask_unmute",
|
|
7379
7402
|
"ask_all_unmute",
|
|
7380
7403
|
"spotlight",
|
|
7404
|
+
"present",
|
|
7405
|
+
"raise_hand",
|
|
7381
7406
|
"lower_hand",
|
|
7382
7407
|
"lower_all_hands",
|
|
7383
7408
|
"make_cohost",
|
|
@@ -7408,7 +7433,22 @@ function createInRoomClient(options) {
|
|
|
7408
7433
|
function refusal2(response, operation, remedy) {
|
|
7409
7434
|
return refusalFromResponse(response, operation, remedy);
|
|
7410
7435
|
}
|
|
7411
|
-
|
|
7436
|
+
let toldPresenting = false;
|
|
7437
|
+
let tellChain = Promise.resolve();
|
|
7438
|
+
store.subscribe(() => {
|
|
7439
|
+
const local = store.snapshot().participants.find((p) => p.isLocal);
|
|
7440
|
+
const sharing = local?.screenSharing === true;
|
|
7441
|
+
if (sharing === toldPresenting || local === void 0) return;
|
|
7442
|
+
toldPresenting = sharing;
|
|
7443
|
+
const on = sharing;
|
|
7444
|
+
tellChain = tellChain.then(() => client.moderate({ action: "present", on })).then(
|
|
7445
|
+
() => void 0,
|
|
7446
|
+
(error) => {
|
|
7447
|
+
console.warn(`[meet] the server did not take presenter=${String(on)}: ${String(error)}`);
|
|
7448
|
+
}
|
|
7449
|
+
);
|
|
7450
|
+
});
|
|
7451
|
+
const client = {
|
|
7412
7452
|
async moderate(request) {
|
|
7413
7453
|
const operation = `meet.moderate(${request.action})`;
|
|
7414
7454
|
const hdrs = headers();
|
|
@@ -7421,7 +7461,8 @@ function createInRoomClient(options) {
|
|
|
7421
7461
|
action: request.action,
|
|
7422
7462
|
...request.identity != null ? { identity: request.identity } : {},
|
|
7423
7463
|
...request.name !== void 0 ? { name: request.name } : {},
|
|
7424
|
-
...request.reason !== void 0 ? { reason: request.reason } : {}
|
|
7464
|
+
...request.reason !== void 0 ? { reason: request.reason } : {},
|
|
7465
|
+
...request.on !== void 0 ? { on: request.on } : {}
|
|
7425
7466
|
},
|
|
7426
7467
|
...hdrs !== void 0 ? { headers: hdrs } : {}
|
|
7427
7468
|
});
|
|
@@ -7612,6 +7653,7 @@ function createInRoomClient(options) {
|
|
|
7612
7653
|
});
|
|
7613
7654
|
}
|
|
7614
7655
|
};
|
|
7656
|
+
return client;
|
|
7615
7657
|
}
|
|
7616
7658
|
|
|
7617
7659
|
// src/core/record.ts
|