@ai-matrx/meet 0.11.35 → 0.11.37
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 +99 -86
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +73 -22
- package/dist/core.d.ts +73 -22
- package/dist/core.js +99 -86
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +99 -86
- 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 +99 -86
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +213 -106
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +20 -4
- package/dist/react.d.ts +20 -4
- package/dist/react.js +213 -106
- package/dist/react.js.map +1 -1
- package/dist/skins/meet.cjs +126 -20
- package/dist/skins/meet.cjs.map +1 -1
- package/dist/skins/meet.js +126 -20
- package/dist/skins/meet.js.map +1 -1
- package/dist/styles.css +7 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog — `@ai-matrx/meet`
|
|
2
2
|
|
|
3
|
+
## 0.11.37
|
|
4
|
+
|
|
5
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
6
|
+
`git diff npm/meet/v0.11.36..npm/meet/v0.11.37 -- apps/shared/meet`).
|
|
7
|
+
No source changes intended and no consumer action required.
|
|
8
|
+
|
|
9
|
+
## 0.11.36
|
|
10
|
+
|
|
11
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
12
|
+
`git diff npm/meet/v0.11.35..npm/meet/v0.11.36 -- apps/shared/meet`).
|
|
13
|
+
No source changes intended and no consumer action required.
|
|
14
|
+
|
|
3
15
|
## 0.11.35
|
|
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;
|
|
@@ -1022,7 +1050,8 @@ function parseRoomToken(body, roomName) {
|
|
|
1022
1050
|
pollSeconds: typeof payload["poll_seconds"] === "number" ? payload["poll_seconds"] : void 0,
|
|
1023
1051
|
breakoutRoomId: readString(payload, "breakout_room_id") ?? null,
|
|
1024
1052
|
observersVisibleTo: readString(payload, "observers_visible_to") === "hosts" ? "hosts" : "everyone",
|
|
1025
|
-
connectionPolicy: connectionPolicyFrom(payload["connection_policy"])
|
|
1053
|
+
connectionPolicy: connectionPolicyFrom(payload["connection_policy"]),
|
|
1054
|
+
leavePolicy: leavePolicyFrom(payload["leave_policy"])
|
|
1026
1055
|
};
|
|
1027
1056
|
}
|
|
1028
1057
|
function createTokenClient(options) {
|
|
@@ -3721,6 +3750,10 @@ var EMPTY = {
|
|
|
3721
3750
|
chatHistoryError: null,
|
|
3722
3751
|
reactions: [],
|
|
3723
3752
|
spotlight: null,
|
|
3753
|
+
actingHost: null,
|
|
3754
|
+
presenter: null,
|
|
3755
|
+
waitingCount: 0,
|
|
3756
|
+
leavePolicy: DEFAULT_LEAVE_POLICY,
|
|
3724
3757
|
moderationNotice: null,
|
|
3725
3758
|
actionNotice: null,
|
|
3726
3759
|
privateChatRequest: null,
|
|
@@ -3782,8 +3815,6 @@ function createMeetStore(initial = {}) {
|
|
|
3782
3815
|
},
|
|
3783
3816
|
setParticipants(participants) {
|
|
3784
3817
|
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
3818
|
const quality = new Map(state.participants.map((p) => [p.identity, p.quality]));
|
|
3788
3819
|
commit({
|
|
3789
3820
|
...state,
|
|
@@ -3796,8 +3827,6 @@ function createMeetStore(initial = {}) {
|
|
|
3796
3827
|
// identity could reach a screen, and it is the place that asks the
|
|
3797
3828
|
// name book. `roster-names.test.ts` fails if a token ever gets past it.
|
|
3798
3829
|
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
3830
|
quality: participant.quality === "unknown" ? quality.get(participant.identity) ?? "unknown" : participant.quality
|
|
3802
3831
|
}))
|
|
3803
3832
|
});
|
|
@@ -3820,20 +3849,6 @@ function createMeetStore(initial = {}) {
|
|
|
3820
3849
|
)
|
|
3821
3850
|
});
|
|
3822
3851
|
},
|
|
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
3852
|
addChat(message) {
|
|
3838
3853
|
if (state.chat.some((existing) => existing.id === message.id)) return;
|
|
3839
3854
|
const chat = [...state.chat, message];
|
|
@@ -3982,18 +3997,6 @@ var ROOM_EVENTS = {
|
|
|
3982
3997
|
wrapUp: "matrx.meet.wrap_up",
|
|
3983
3998
|
/** The meeting ended for everyone. Payload `{ meeting_id, ended_at, trigger }`. */
|
|
3984
3999
|
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
4000
|
/**
|
|
3998
4001
|
* A chat message to everyone was SAVED (Meet wave 2). Payload
|
|
3999
4002
|
* `{ message: { id, meeting_id, sender_identity, sender_name, body, created_at } }`.
|
|
@@ -4046,8 +4049,6 @@ function applyRoomEvent(args) {
|
|
|
4046
4049
|
return applyWrapUp(store, payload, now);
|
|
4047
4050
|
case ROOM_EVENTS.ended:
|
|
4048
4051
|
return applyEnded(store, payload);
|
|
4049
|
-
case ROOM_EVENTS.recording:
|
|
4050
|
-
return applyRecording(store, payload);
|
|
4051
4052
|
case ROOM_EVENTS.chat:
|
|
4052
4053
|
return applyChat(store, payload);
|
|
4053
4054
|
case ROOM_EVENTS.moderation:
|
|
@@ -4127,9 +4128,9 @@ function applyWrapUp(store, payload, now) {
|
|
|
4127
4128
|
store.announceWrapUp(announcement);
|
|
4128
4129
|
return HANDLED;
|
|
4129
4130
|
}
|
|
4130
|
-
function
|
|
4131
|
+
function applyRecordingState(store, payload) {
|
|
4131
4132
|
const row = object(payload["recording"]);
|
|
4132
|
-
if (row === null) return ignored("
|
|
4133
|
+
if (row === null) return ignored("room state carries no recording");
|
|
4133
4134
|
const meetingId = text2(payload["meeting_id"]);
|
|
4134
4135
|
const meeting = store.snapshot().meeting;
|
|
4135
4136
|
if (meeting !== null && meetingId !== null && meetingId !== meeting.id) {
|
|
@@ -4211,19 +4212,6 @@ function applyModeration(store, payload, now) {
|
|
|
4211
4212
|
}
|
|
4212
4213
|
const kind = text2(payload["kind"]);
|
|
4213
4214
|
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
4215
|
case "role": {
|
|
4228
4216
|
const identity = text2(payload["identity"]);
|
|
4229
4217
|
const role = text2(payload["role"]);
|
|
@@ -4615,7 +4603,6 @@ function gridColumns(count2) {
|
|
|
4615
4603
|
|
|
4616
4604
|
// src/core/room-driver.ts
|
|
4617
4605
|
var DATA_TOPICS = {
|
|
4618
|
-
hand: "mx.hand",
|
|
4619
4606
|
reaction: "mx.reaction",
|
|
4620
4607
|
chat: "mx.chat"
|
|
4621
4608
|
};
|
|
@@ -4757,6 +4744,7 @@ function createLiveKitDriver(handlers, options = {}) {
|
|
|
4757
4744
|
projectRoster = roster;
|
|
4758
4745
|
created.on(RoomEvent.TrackSubscribed, (track) => {
|
|
4759
4746
|
if (track.kind !== Track.Kind.Audio || typeof document === "undefined") return;
|
|
4747
|
+
if (!remoteAudioPlayback) return;
|
|
4760
4748
|
const element = track.attach();
|
|
4761
4749
|
element.setAttribute("data-mx-meet-audio", "");
|
|
4762
4750
|
audioSink().appendChild(element);
|
|
@@ -4841,6 +4829,7 @@ function createLiveKitDriver(handlers, options = {}) {
|
|
|
4841
4829
|
let sources = null;
|
|
4842
4830
|
let trackEvents = null;
|
|
4843
4831
|
let audioContainer = null;
|
|
4832
|
+
let remoteAudioPlayback = true;
|
|
4844
4833
|
function audioSink() {
|
|
4845
4834
|
if (audioContainer !== null && audioContainer.isConnected) return audioContainer;
|
|
4846
4835
|
const container = document.createElement("div");
|
|
@@ -4999,6 +4988,14 @@ function createLiveKitDriver(handlers, options = {}) {
|
|
|
4999
4988
|
throw normalizeDeviceError(error, "meet.switchDevice");
|
|
5000
4989
|
}
|
|
5001
4990
|
},
|
|
4991
|
+
setRemoteAudioPlayback(enabled) {
|
|
4992
|
+
remoteAudioPlayback = enabled;
|
|
4993
|
+
if (enabled || audioContainer === null) return;
|
|
4994
|
+
for (const element of Array.from(audioContainer.querySelectorAll("[data-mx-meet-audio]"))) {
|
|
4995
|
+
if (element instanceof HTMLMediaElement) element.srcObject = null;
|
|
4996
|
+
element.remove();
|
|
4997
|
+
}
|
|
4998
|
+
},
|
|
5002
4999
|
async startAudio() {
|
|
5003
5000
|
const target = room;
|
|
5004
5001
|
if (target === null) return;
|
|
@@ -5239,7 +5236,7 @@ function createMeetingSession(options) {
|
|
|
5239
5236
|
})();
|
|
5240
5237
|
return reading;
|
|
5241
5238
|
}
|
|
5242
|
-
async function postLeave(intent) {
|
|
5239
|
+
async function postLeave(intent, extra = {}) {
|
|
5243
5240
|
const meeting = requireMeeting(`meet.${intent}`);
|
|
5244
5241
|
const pass = options.resolvePass?.() ?? null;
|
|
5245
5242
|
const response = await options.api.request({
|
|
@@ -5247,7 +5244,7 @@ function createMeetingSession(options) {
|
|
|
5247
5244
|
method: "POST",
|
|
5248
5245
|
requireAuth: false,
|
|
5249
5246
|
operation: `meet.${intent}`,
|
|
5250
|
-
body: { meeting_id: meeting.id, intent },
|
|
5247
|
+
body: { meeting_id: meeting.id, intent, ...extra },
|
|
5251
5248
|
...pass !== null ? { headers: { [MEETING_PASS_HEADER]: pass } } : {}
|
|
5252
5249
|
});
|
|
5253
5250
|
if (!response.ok) {
|
|
@@ -5261,7 +5258,7 @@ function createMeetingSession(options) {
|
|
|
5261
5258
|
throw new MeetError(
|
|
5262
5259
|
"transport",
|
|
5263
5260
|
refusal2?.reason ?? `meet.${intent}: the server answered ${response.status}`,
|
|
5264
|
-
refusal2?.remedy ?? "You are still in the waiting room. Try again."
|
|
5261
|
+
refusal2?.remedy ?? (intent === "withdraw" ? "You are still in the waiting room. Try again." : "Nothing was changed. Try again.")
|
|
5265
5262
|
);
|
|
5266
5263
|
}
|
|
5267
5264
|
}
|
|
@@ -5485,6 +5482,10 @@ function createMeetingSession(options) {
|
|
|
5485
5482
|
store.dispatch({ type: "admission", admission: "withdrawn" });
|
|
5486
5483
|
hint();
|
|
5487
5484
|
},
|
|
5485
|
+
async hostLeave(intent) {
|
|
5486
|
+
if (intent === "end_for_all") await postLeave("end_for_all");
|
|
5487
|
+
else await postLeave("assign_and_leave", { assign_to: intent.assignTo });
|
|
5488
|
+
},
|
|
5488
5489
|
async askAgain() {
|
|
5489
5490
|
await options.rejoin?.();
|
|
5490
5491
|
},
|
|
@@ -6446,6 +6447,11 @@ function SCREEN_SHARE_BLOCKED_REMEDY_FOR(remedy) {
|
|
|
6446
6447
|
return /administrator|policy/i.test(remedy) ? remedy : SCREEN_SHARE_BLOCKED_REMEDY;
|
|
6447
6448
|
}
|
|
6448
6449
|
var PARTICIPANT_ROLE_ATTRIBUTE = "matrx.participant.role";
|
|
6450
|
+
var PARTICIPANT_HAND_ATTRIBUTE = "matrx.hand";
|
|
6451
|
+
function handFrom(value) {
|
|
6452
|
+
const at = value === void 0 || value.length === 0 ? Number.NaN : Number(value);
|
|
6453
|
+
return Number.isFinite(at) ? { handRaised: true, handRaisedAt: at } : { handRaised: false, handRaisedAt: null };
|
|
6454
|
+
}
|
|
6449
6455
|
var PARTICIPANT_CAN_RECORD_ATTRIBUTE = "matrx.participant.can_record";
|
|
6450
6456
|
var CONNECTION_KIND_ATTRIBUTE = "matrx.participant.connection_kind";
|
|
6451
6457
|
var PARTICIPANT_STANDING_ATTRIBUTE = "matrx.participant.standing";
|
|
@@ -6499,7 +6505,10 @@ function projectParticipant(driver, joinedAt) {
|
|
|
6499
6505
|
cameraEnabled: driver.cameraEnabled,
|
|
6500
6506
|
screenSharing: driver.screenSharing,
|
|
6501
6507
|
speaking: false,
|
|
6502
|
-
|
|
6508
|
+
// S8: a hand is the SERVER's (`hand_raised_at` on the person row, `/moderate raise_hand`),
|
|
6509
|
+
// replicated as the `matrx.hand` attribute: epoch ms of the raise, "" when down. It is
|
|
6510
|
+
// therefore delivered to late joiners and survives refresh and reconnect.
|
|
6511
|
+
...handFrom(driver.attributes[PARTICIPANT_HAND_ATTRIBUTE]),
|
|
6503
6512
|
quality: "unknown",
|
|
6504
6513
|
joinedAt
|
|
6505
6514
|
};
|
|
@@ -6629,40 +6638,38 @@ function createRoomEngine(options) {
|
|
|
6629
6638
|
},
|
|
6630
6639
|
participants(list) {
|
|
6631
6640
|
const joinedAt = new Date(now()).toISOString();
|
|
6632
|
-
const before = new Set(store.snapshot().participants.map((p) => p.identity));
|
|
6633
6641
|
projectRoster(list, joinedAt);
|
|
6634
|
-
const snapshot = store.snapshot();
|
|
6635
|
-
const newcomer = snapshot.participants.some(
|
|
6636
|
-
(participant) => !participant.isLocal && !before.has(participant.identity)
|
|
6637
|
-
);
|
|
6638
|
-
const me = snapshot.participants.find((p) => p.identity === snapshot.localIdentity);
|
|
6639
|
-
if (newcomer && before.size > 0 && me?.handRaised === true) {
|
|
6640
|
-
void publish(DATA_TOPICS.hand, { raised: true, raisedAt: me.handRaisedAt ?? now() }).catch(
|
|
6641
|
-
() => void 0
|
|
6642
|
-
);
|
|
6643
|
-
}
|
|
6644
6642
|
},
|
|
6645
6643
|
participantLeft(who, reason) {
|
|
6646
6644
|
departures.set(who, reason);
|
|
6647
6645
|
},
|
|
6648
6646
|
roomMetadata(metadata) {
|
|
6649
|
-
let
|
|
6647
|
+
let parsed = {};
|
|
6650
6648
|
if (metadata.length > 0) {
|
|
6651
6649
|
try {
|
|
6652
|
-
const
|
|
6653
|
-
if (typeof
|
|
6654
|
-
const value = parsed.spotlight;
|
|
6655
|
-
if (typeof value === "string" && value.length > 0) spotlight = asParticipantIdentity(value);
|
|
6656
|
-
}
|
|
6650
|
+
const value = JSON.parse(metadata);
|
|
6651
|
+
if (typeof value === "object" && value !== null) parsed = value;
|
|
6657
6652
|
} catch {
|
|
6658
6653
|
report(
|
|
6659
6654
|
"warn",
|
|
6660
|
-
"meet: the room's metadata is not JSON, so
|
|
6661
|
-
"Only aidream writes room metadata; check services/meet/
|
|
6655
|
+
"meet: the room's metadata is not JSON, so the room state was not read from it",
|
|
6656
|
+
"Only aidream writes room metadata; check services/meet/room_state.py."
|
|
6662
6657
|
);
|
|
6663
6658
|
}
|
|
6664
6659
|
}
|
|
6665
|
-
|
|
6660
|
+
const key = (name) => {
|
|
6661
|
+
const value = parsed[name];
|
|
6662
|
+
return typeof value === "string" && value.length > 0 ? asParticipantIdentity(personOf(value)) : null;
|
|
6663
|
+
};
|
|
6664
|
+
const waiting = typeof parsed["waiting_count"] === "number" ? parsed["waiting_count"] : 0;
|
|
6665
|
+
const before = store.snapshot();
|
|
6666
|
+
const next = { spotlight: key("spotlight"), actingHost: key("acting_host"), presenter: key("presenter"), waitingCount: waiting };
|
|
6667
|
+
if (before.spotlight !== next.spotlight || before.actingHost !== next.actingHost || before.presenter !== next.presenter || before.waitingCount !== next.waitingCount) {
|
|
6668
|
+
store.patch(next);
|
|
6669
|
+
}
|
|
6670
|
+
if (parsed["recording"] !== void 0 && parsed["recording"] !== null) {
|
|
6671
|
+
applyRecordingState(store, { meeting_id: parsed["meeting_id"], recording: parsed["recording"] });
|
|
6672
|
+
}
|
|
6666
6673
|
},
|
|
6667
6674
|
activeSpeakers(identities) {
|
|
6668
6675
|
store.setSpeaking([...new Set(identities.map((who) => personOf(who)))]);
|
|
@@ -6764,13 +6771,6 @@ function createRoomEngine(options) {
|
|
|
6764
6771
|
}
|
|
6765
6772
|
const sender = personOf(from ?? "");
|
|
6766
6773
|
switch (topic) {
|
|
6767
|
-
case DATA_TOPICS.hand:
|
|
6768
|
-
store.setHand(
|
|
6769
|
-
sender,
|
|
6770
|
-
envelope.raised === true,
|
|
6771
|
-
typeof envelope.raisedAt === "number" ? envelope.raisedAt : now()
|
|
6772
|
-
);
|
|
6773
|
-
return;
|
|
6774
6774
|
case DATA_TOPICS.reaction:
|
|
6775
6775
|
if (typeof envelope.emoji === "string") {
|
|
6776
6776
|
store.addReaction({
|
|
@@ -6869,6 +6869,7 @@ function createRoomEngine(options) {
|
|
|
6869
6869
|
current = token;
|
|
6870
6870
|
lastServerUrl = token.serverUrl;
|
|
6871
6871
|
connectionPolicy = token.connectionPolicy ?? DEFAULT_CONNECTION_POLICY;
|
|
6872
|
+
if (token.leavePolicy !== void 0) store.patch({ leavePolicy: token.leavePolicy });
|
|
6872
6873
|
store.patch({
|
|
6873
6874
|
localIdentity: token.identity,
|
|
6874
6875
|
breakoutRoomId: token.breakoutRoomId ?? null,
|
|
@@ -6903,6 +6904,7 @@ function createRoomEngine(options) {
|
|
|
6903
6904
|
return;
|
|
6904
6905
|
}
|
|
6905
6906
|
driver = created;
|
|
6907
|
+
if (token.connectionKind === "companion") created.setRemoteAudioPlayback?.(false);
|
|
6906
6908
|
await created.connect(token.serverUrl, token.token);
|
|
6907
6909
|
store.patch({ failure: null, connection: "stable" });
|
|
6908
6910
|
store.dispatch({ type: "connected" });
|
|
@@ -7164,6 +7166,19 @@ function createRoomEngine(options) {
|
|
|
7164
7166
|
}
|
|
7165
7167
|
},
|
|
7166
7168
|
leave: leaveRoom,
|
|
7169
|
+
async checkElsewhere(roomName) {
|
|
7170
|
+
const claim = options.tabClaim;
|
|
7171
|
+
const userId = identity.userId;
|
|
7172
|
+
if (claim === void 0 || userId === null) return false;
|
|
7173
|
+
const before = store.snapshot();
|
|
7174
|
+
if (before.phase !== "prejoin" || before.secondDevice !== null) return false;
|
|
7175
|
+
if (!await claim.presentElsewhere(String(roomName), `user:${String(userId)}`)) return false;
|
|
7176
|
+
const now2 = store.snapshot();
|
|
7177
|
+
if (now2.phase !== "prejoin" || now2.secondDevice !== null) return false;
|
|
7178
|
+
store.patch({ secondDevice: { rule: "ask_switch_or_join" } });
|
|
7179
|
+
report("info", "meet: this browser already has you in this meeting \u2014 offering the choice before Join");
|
|
7180
|
+
return true;
|
|
7181
|
+
},
|
|
7167
7182
|
backToPrejoin() {
|
|
7168
7183
|
store.dispatch({ type: "back_to_prejoin", click: true });
|
|
7169
7184
|
},
|
|
@@ -7221,11 +7236,6 @@ function createRoomEngine(options) {
|
|
|
7221
7236
|
dismissShareNotice() {
|
|
7222
7237
|
if (store.snapshot().share.state === "refused") store.patch({ share: NO_SHARE });
|
|
7223
7238
|
},
|
|
7224
|
-
async raiseHand(raised) {
|
|
7225
|
-
const local = store.snapshot().localIdentity;
|
|
7226
|
-
if (local !== null) store.setHand(local, raised);
|
|
7227
|
-
await publish(DATA_TOPICS.hand, { raised, raisedAt: now() });
|
|
7228
|
-
},
|
|
7229
7239
|
async react(emoji) {
|
|
7230
7240
|
const local = store.snapshot().localIdentity;
|
|
7231
7241
|
const id = `${local ?? "local"}-${now()}`;
|
|
@@ -7354,6 +7364,8 @@ var MODERATION_ACTIONS = [
|
|
|
7354
7364
|
"ask_unmute",
|
|
7355
7365
|
"ask_all_unmute",
|
|
7356
7366
|
"spotlight",
|
|
7367
|
+
"present",
|
|
7368
|
+
"raise_hand",
|
|
7357
7369
|
"lower_hand",
|
|
7358
7370
|
"lower_all_hands",
|
|
7359
7371
|
"make_cohost",
|
|
@@ -7397,7 +7409,8 @@ function createInRoomClient(options) {
|
|
|
7397
7409
|
action: request.action,
|
|
7398
7410
|
...request.identity != null ? { identity: request.identity } : {},
|
|
7399
7411
|
...request.name !== void 0 ? { name: request.name } : {},
|
|
7400
|
-
...request.reason !== void 0 ? { reason: request.reason } : {}
|
|
7412
|
+
...request.reason !== void 0 ? { reason: request.reason } : {},
|
|
7413
|
+
...request.on !== void 0 ? { on: request.on } : {}
|
|
7401
7414
|
},
|
|
7402
7415
|
...hdrs !== void 0 ? { headers: hdrs } : {}
|
|
7403
7416
|
});
|