@ai-matrx/meet 0.11.41 → 0.11.43
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 +18 -0
- package/dist/{collab-XY6Xj1dG.d.cts → collab-BNJNgXFB.d.cts} +11 -2
- package/dist/{collab-XY6Xj1dG.d.ts → collab-BNJNgXFB.d.ts} +11 -2
- package/dist/{components-4f9Mf8fz.d.cts → components-BDtGzHf4.d.ts} +4 -2
- package/dist/{components-Cwep2NYU.d.ts → components-BxK993iW.d.cts} +4 -2
- package/dist/core.cjs +190 -25
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +58 -11
- package/dist/core.d.ts +58 -11
- package/dist/core.js +190 -25
- package/dist/core.js.map +1 -1
- package/dist/index.cjs +190 -25
- 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 +190 -25
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +469 -66
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +21 -4
- package/dist/react.d.ts +21 -4
- package/dist/react.js +469 -66
- package/dist/react.js.map +1 -1
- package/dist/skins/meet.cjs +326 -48
- package/dist/skins/meet.cjs.map +1 -1
- package/dist/skins/meet.d.cts +5 -3
- package/dist/skins/meet.d.ts +5 -3
- package/dist/skins/meet.js +326 -48
- package/dist/skins/meet.js.map +1 -1
- package/dist/styles.css +12 -0
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,29 @@
|
|
|
1
1
|
# Changelog — `@ai-matrx/meet`
|
|
2
2
|
|
|
3
|
+
## 0.11.43
|
|
4
|
+
|
|
5
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
6
|
+
`git diff npm/meet/v0.11.42..npm/meet/v0.11.43 -- apps/shared/meet`).
|
|
7
|
+
No source changes intended and no consumer action required.
|
|
8
|
+
|
|
9
|
+
## 0.11.42
|
|
10
|
+
|
|
11
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
12
|
+
`git diff npm/meet/v0.11.41..npm/meet/v0.11.42 -- apps/shared/meet`).
|
|
13
|
+
No source changes intended and no consumer action required.
|
|
14
|
+
|
|
3
15
|
## 0.11.41
|
|
4
16
|
|
|
5
17
|
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
6
18
|
`git diff npm/meet/v0.11.40..npm/meet/v0.11.41 -- apps/shared/meet`).
|
|
7
19
|
No source changes intended and no consumer action required.
|
|
8
20
|
|
|
21
|
+
## 0.11.40
|
|
22
|
+
|
|
23
|
+
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
24
|
+
`git diff npm/meet/v0.11.39..npm/meet/v0.11.40 -- apps/shared/meet`).
|
|
25
|
+
No source changes intended and no consumer action required.
|
|
26
|
+
|
|
9
27
|
## 0.11.39
|
|
10
28
|
|
|
11
29
|
Automatic changed-only republish (docs/metadata drift since the last tag — see
|
|
@@ -332,7 +332,7 @@ type RecordingState = "idle" | "starting" | "recording" | "stopping" | "processi
|
|
|
332
332
|
*
|
|
333
333
|
* `local` — this browser's own optimistic `starting`/`stopping`, which is all
|
|
334
334
|
* the indicator ever had through 0.4.7, and the reason it never went solid.
|
|
335
|
-
* `room` —
|
|
335
|
+
* `room` — the room's replicated state (metadata), the ONLY feed a guest has.
|
|
336
336
|
* `record` — the durable `meet_recordings` row. It outranks both (D16).
|
|
337
337
|
*/
|
|
338
338
|
type RecordingSource = "local" | "room" | "record";
|
|
@@ -779,6 +779,10 @@ interface MeetBreakoutPlan {
|
|
|
779
779
|
readonly minutes: number;
|
|
780
780
|
readonly openedAt: string | null;
|
|
781
781
|
readonly endsAt: string | null;
|
|
782
|
+
/** Set while the host's closing countdown runs: everyone returns to the main meeting at this time. */
|
|
783
|
+
readonly closingAt: string | null;
|
|
784
|
+
/** `invite` (Join / Later) or `auto` (a countdown, then moved) — the org's `meet.breakout_move`. */
|
|
785
|
+
readonly moveMode: "invite" | "auto";
|
|
782
786
|
readonly closedAt: string | null;
|
|
783
787
|
readonly broadcasts: readonly MeetBreakoutBroadcast[];
|
|
784
788
|
}
|
|
@@ -861,6 +865,11 @@ declare function assignedRoom(plan: MeetBreakoutPlan | null, identity: string |
|
|
|
861
865
|
declare function autoAssign(identities: readonly string[], rooms: number, exclude?: readonly string[]): string[][];
|
|
862
866
|
/** Milliseconds until the plan's timer ends, or null when it has none. */
|
|
863
867
|
declare function breakoutRemainingMs(plan: MeetBreakoutPlan | null, now: number): number | null;
|
|
868
|
+
/**
|
|
869
|
+
* The closing countdown to show, in ms — or null when the rooms are not closing. Closing
|
|
870
|
+
* means the host asked (`closingAt`) or the timer is within its last 30 seconds.
|
|
871
|
+
*/
|
|
872
|
+
declare function breakoutClosingMs(plan: MeetBreakoutPlan | null, now: number): number | null;
|
|
864
873
|
/** The language translated captions start in: the knob, else the viewer's own. */
|
|
865
874
|
declare function defaultCaptionLanguage(settings: MeetCollabSettings | null, viewerLanguage: string | null | undefined): string;
|
|
866
875
|
/** Languages offered in the captions menu (tags the translator understands). */
|
|
@@ -883,4 +892,4 @@ interface MeetingActivities {
|
|
|
883
892
|
*/
|
|
884
893
|
declare function loadMeetingActivities(api: MeetApi, meetingId: string, meetingPass?: string | null): Promise<MeetingActivities>;
|
|
885
894
|
|
|
886
|
-
export { type MeetingOccurrence as $, type AccessTokenSource as A, type MeetPoll as B, type CollabPanel as C, type MeetPollOption as D, EMPTY_COLLAB as E, FILE_SESSION_PATH as F, type MeetPollState as G, type MeetQuestion as H, type InviteeInput as I, type JsonObject as J, type MeetQuestionState as K, type LobbyEntry as L, type MeetingRecord as M, type MeetStroke as N, type OrganizationId as O, type ParticipantIdentity as P, type MeetingActivities as Q, type RoomName as R, type StageLayout as S, type TranscriptSource as T, type UserId as U, type MeetingAttendee as V, type WrapUpAnnouncement as W, type MeetingChanges as X, type MeetingInvitee as Y, type MeetingKind as Z, type MeetingNoteKind as _, type MeetParticipant as a, type MeetingSettings as a0, type NoteTakerState as a1, ORGANIZATION_HEADER as a2, type ObserversVisibleTo as a3, type OccurrenceOverride as a4, type OccurrenceState as a5, type ParticipantStanding as a6, ROLE_RANK as a7, type RecordingPolicy as a8, type RecordingRecord as a9,
|
|
895
|
+
export { type MeetingOccurrence as $, type AccessTokenSource as A, type MeetPoll as B, type CollabPanel as C, type MeetPollOption as D, EMPTY_COLLAB as E, FILE_SESSION_PATH as F, type MeetPollState as G, type MeetQuestion as H, type InviteeInput as I, type JsonObject as J, type MeetQuestionState as K, type LobbyEntry as L, type MeetingRecord as M, type MeetStroke as N, type OrganizationId as O, type ParticipantIdentity as P, type MeetingActivities as Q, type RoomName as R, type StageLayout as S, type TranscriptSource as T, type UserId as U, type MeetingAttendee as V, type WrapUpAnnouncement as W, type MeetingChanges as X, type MeetingInvitee as Y, type MeetingKind as Z, type MeetingNoteKind as _, type MeetParticipant as a, type MeetingSettings as a0, type NoteTakerState as a1, ORGANIZATION_HEADER as a2, type ObserversVisibleTo as a3, type OccurrenceOverride as a4, type OccurrenceState as a5, type ParticipantStanding as a6, ROLE_RANK as a7, type RecordingPolicy as a8, type RecordingRecord as a9, isLinkFollower as aA, isObserverRole as aB, loadMeetingActivities as aC, scheduleSettingsPatch as aD, withItem as aE, type RecordingSource as aF, type RecordingState as aa, type RsvpAnswer as ab, type RsvpInvitation as ac, type RsvpState as ad, type TranscriptSegment as ae, type UpcomingOccurrence as af, appPanelOf as ag, applyCollabPacket as ah, asCallId as ai, asMeetingId as aj, asOrganizationId as ak, asParticipantIdentity as al, asRoomName as am, asUserId as an, assignedRoom as ao, autoAssign as ap, breakoutClosingMs as aq, breakoutRemainingMs as ar, captureHeldOf as as, collabFromState as at, createMeetApi as au, defaultCaptionLanguage as av, fileDownloadPath as aw, focusFromRow as ax, isGuest as ay, isHostRole as az, type MeetApi as b, type MeetIdentity as c, type CallInvite as d, type ParticipantRole as e, type CallMode as f, type MeetingNote as g, type MeetingId as h, type MeetingAppPanel as i, type CollabSnapshot as j, type AdmissionState as k, CAPTION_LANGUAGES as l, type CallId as m, type CallState as n, type CallablePerson as o, type ConnectionQuality as p, type InviteeRole as q, type JsonValue as r, type MeetApiOptions as s, type MeetApiRequest as t, type MeetAppFocus as u, type MeetBreakoutBroadcast as v, type MeetBreakoutPlan as w, type MeetBreakoutRoom as x, type MeetCollabSettings as y, type MeetFileMedia as z };
|
|
@@ -332,7 +332,7 @@ type RecordingState = "idle" | "starting" | "recording" | "stopping" | "processi
|
|
|
332
332
|
*
|
|
333
333
|
* `local` — this browser's own optimistic `starting`/`stopping`, which is all
|
|
334
334
|
* the indicator ever had through 0.4.7, and the reason it never went solid.
|
|
335
|
-
* `room` —
|
|
335
|
+
* `room` — the room's replicated state (metadata), the ONLY feed a guest has.
|
|
336
336
|
* `record` — the durable `meet_recordings` row. It outranks both (D16).
|
|
337
337
|
*/
|
|
338
338
|
type RecordingSource = "local" | "room" | "record";
|
|
@@ -779,6 +779,10 @@ interface MeetBreakoutPlan {
|
|
|
779
779
|
readonly minutes: number;
|
|
780
780
|
readonly openedAt: string | null;
|
|
781
781
|
readonly endsAt: string | null;
|
|
782
|
+
/** Set while the host's closing countdown runs: everyone returns to the main meeting at this time. */
|
|
783
|
+
readonly closingAt: string | null;
|
|
784
|
+
/** `invite` (Join / Later) or `auto` (a countdown, then moved) — the org's `meet.breakout_move`. */
|
|
785
|
+
readonly moveMode: "invite" | "auto";
|
|
782
786
|
readonly closedAt: string | null;
|
|
783
787
|
readonly broadcasts: readonly MeetBreakoutBroadcast[];
|
|
784
788
|
}
|
|
@@ -861,6 +865,11 @@ declare function assignedRoom(plan: MeetBreakoutPlan | null, identity: string |
|
|
|
861
865
|
declare function autoAssign(identities: readonly string[], rooms: number, exclude?: readonly string[]): string[][];
|
|
862
866
|
/** Milliseconds until the plan's timer ends, or null when it has none. */
|
|
863
867
|
declare function breakoutRemainingMs(plan: MeetBreakoutPlan | null, now: number): number | null;
|
|
868
|
+
/**
|
|
869
|
+
* The closing countdown to show, in ms — or null when the rooms are not closing. Closing
|
|
870
|
+
* means the host asked (`closingAt`) or the timer is within its last 30 seconds.
|
|
871
|
+
*/
|
|
872
|
+
declare function breakoutClosingMs(plan: MeetBreakoutPlan | null, now: number): number | null;
|
|
864
873
|
/** The language translated captions start in: the knob, else the viewer's own. */
|
|
865
874
|
declare function defaultCaptionLanguage(settings: MeetCollabSettings | null, viewerLanguage: string | null | undefined): string;
|
|
866
875
|
/** Languages offered in the captions menu (tags the translator understands). */
|
|
@@ -883,4 +892,4 @@ interface MeetingActivities {
|
|
|
883
892
|
*/
|
|
884
893
|
declare function loadMeetingActivities(api: MeetApi, meetingId: string, meetingPass?: string | null): Promise<MeetingActivities>;
|
|
885
894
|
|
|
886
|
-
export { type MeetingOccurrence as $, type AccessTokenSource as A, type MeetPoll as B, type CollabPanel as C, type MeetPollOption as D, EMPTY_COLLAB as E, FILE_SESSION_PATH as F, type MeetPollState as G, type MeetQuestion as H, type InviteeInput as I, type JsonObject as J, type MeetQuestionState as K, type LobbyEntry as L, type MeetingRecord as M, type MeetStroke as N, type OrganizationId as O, type ParticipantIdentity as P, type MeetingActivities as Q, type RoomName as R, type StageLayout as S, type TranscriptSource as T, type UserId as U, type MeetingAttendee as V, type WrapUpAnnouncement as W, type MeetingChanges as X, type MeetingInvitee as Y, type MeetingKind as Z, type MeetingNoteKind as _, type MeetParticipant as a, type MeetingSettings as a0, type NoteTakerState as a1, ORGANIZATION_HEADER as a2, type ObserversVisibleTo as a3, type OccurrenceOverride as a4, type OccurrenceState as a5, type ParticipantStanding as a6, ROLE_RANK as a7, type RecordingPolicy as a8, type RecordingRecord as a9,
|
|
895
|
+
export { type MeetingOccurrence as $, type AccessTokenSource as A, type MeetPoll as B, type CollabPanel as C, type MeetPollOption as D, EMPTY_COLLAB as E, FILE_SESSION_PATH as F, type MeetPollState as G, type MeetQuestion as H, type InviteeInput as I, type JsonObject as J, type MeetQuestionState as K, type LobbyEntry as L, type MeetingRecord as M, type MeetStroke as N, type OrganizationId as O, type ParticipantIdentity as P, type MeetingActivities as Q, type RoomName as R, type StageLayout as S, type TranscriptSource as T, type UserId as U, type MeetingAttendee as V, type WrapUpAnnouncement as W, type MeetingChanges as X, type MeetingInvitee as Y, type MeetingKind as Z, type MeetingNoteKind as _, type MeetParticipant as a, type MeetingSettings as a0, type NoteTakerState as a1, ORGANIZATION_HEADER as a2, type ObserversVisibleTo as a3, type OccurrenceOverride as a4, type OccurrenceState as a5, type ParticipantStanding as a6, ROLE_RANK as a7, type RecordingPolicy as a8, type RecordingRecord as a9, isLinkFollower as aA, isObserverRole as aB, loadMeetingActivities as aC, scheduleSettingsPatch as aD, withItem as aE, type RecordingSource as aF, type RecordingState as aa, type RsvpAnswer as ab, type RsvpInvitation as ac, type RsvpState as ad, type TranscriptSegment as ae, type UpcomingOccurrence as af, appPanelOf as ag, applyCollabPacket as ah, asCallId as ai, asMeetingId as aj, asOrganizationId as ak, asParticipantIdentity as al, asRoomName as am, asUserId as an, assignedRoom as ao, autoAssign as ap, breakoutClosingMs as aq, breakoutRemainingMs as ar, captureHeldOf as as, collabFromState as at, createMeetApi as au, defaultCaptionLanguage as av, fileDownloadPath as aw, focusFromRow as ax, isGuest as ay, isHostRole as az, type MeetApi as b, type MeetIdentity as c, type CallInvite as d, type ParticipantRole as e, type CallMode as f, type MeetingNote as g, type MeetingId as h, type MeetingAppPanel as i, type CollabSnapshot as j, type AdmissionState as k, CAPTION_LANGUAGES as l, type CallId as m, type CallState as n, type CallablePerson as o, type ConnectionQuality as p, type InviteeRole as q, type JsonValue as r, type MeetApiOptions as s, type MeetApiRequest as t, type MeetAppFocus as u, type MeetBreakoutBroadcast as v, type MeetBreakoutPlan as w, type MeetBreakoutRoom as x, type MeetCollabSettings as y, type MeetFileMedia as z };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import { M as MeetingRecord, P as ParticipantIdentity, R as RoomName, a as MeetParticipant } from './collab-
|
|
2
|
+
import { M as MeetingRecord, P as ParticipantIdentity, R as RoomName, a as MeetParticipant } from './collab-BNJNgXFB.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* THE PRODUCT UI (R6/R7). Not a headless kernel with a note telling the host to
|
|
@@ -26,10 +26,12 @@ declare function Avatar({ name, url, size, }: {
|
|
|
26
26
|
url?: string | null;
|
|
27
27
|
size?: number;
|
|
28
28
|
}): ReactNode;
|
|
29
|
-
declare function ControlButton({ label, active, danger, onClick, children, }: {
|
|
29
|
+
declare function ControlButton({ label, active, danger, pressed, onClick, children, }: {
|
|
30
30
|
label: string;
|
|
31
31
|
active?: boolean;
|
|
32
32
|
danger?: boolean;
|
|
33
|
+
/** A toggle's state, for assistive tech and the harness (`aria-pressed`). */
|
|
34
|
+
pressed?: boolean | undefined;
|
|
33
35
|
onClick: () => void;
|
|
34
36
|
children: ReactNode;
|
|
35
37
|
}): ReactNode;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ReactNode } from 'react';
|
|
2
|
-
import { M as MeetingRecord, P as ParticipantIdentity, R as RoomName, a as MeetParticipant } from './collab-
|
|
2
|
+
import { M as MeetingRecord, P as ParticipantIdentity, R as RoomName, a as MeetParticipant } from './collab-BNJNgXFB.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* THE PRODUCT UI (R6/R7). Not a headless kernel with a note telling the host to
|
|
@@ -26,10 +26,12 @@ declare function Avatar({ name, url, size, }: {
|
|
|
26
26
|
url?: string | null;
|
|
27
27
|
size?: number;
|
|
28
28
|
}): ReactNode;
|
|
29
|
-
declare function ControlButton({ label, active, danger, onClick, children, }: {
|
|
29
|
+
declare function ControlButton({ label, active, danger, pressed, onClick, children, }: {
|
|
30
30
|
label: string;
|
|
31
31
|
active?: boolean;
|
|
32
32
|
danger?: boolean;
|
|
33
|
+
/** A toggle's state, for assistive tech and the harness (`aria-pressed`). */
|
|
34
|
+
pressed?: boolean | undefined;
|
|
33
35
|
onClick: () => void;
|
|
34
36
|
children: ReactNode;
|
|
35
37
|
}): ReactNode;
|
package/dist/core.cjs
CHANGED
|
@@ -110,6 +110,7 @@ __export(core_exports, {
|
|
|
110
110
|
autoAssign: () => autoAssign,
|
|
111
111
|
autoRejoinDelayMs: () => autoRejoinDelayMs,
|
|
112
112
|
availableActivities: () => availableActivities,
|
|
113
|
+
breakoutClosingMs: () => breakoutClosingMs,
|
|
113
114
|
breakoutRemainingMs: () => breakoutRemainingMs,
|
|
114
115
|
callInviteAction: () => callInviteAction,
|
|
115
116
|
callInviteText: () => callInviteText,
|
|
@@ -911,6 +912,8 @@ var MEET_ROUTES = {
|
|
|
911
912
|
noteTakerStop: "/api/v1/meet/agent/stop",
|
|
912
913
|
/** In-meeting Q&A. Streams NDJSON; body is `{meeting_id, question}` only. */
|
|
913
914
|
intelligenceAsk: "/api/v1/meet/intelligence/ask",
|
|
915
|
+
/** Anyone in the meeting (guests with the room pass included) asks for captions for themselves. */
|
|
916
|
+
noteTakerCaptions: "/api/v1/meet/agent/captions",
|
|
914
917
|
/** A host ends the meeting for everyone. Served by MRI-A6. */
|
|
915
918
|
meetingEnd: "/api/v1/meet/end",
|
|
916
919
|
/**
|
|
@@ -1057,7 +1060,8 @@ function parseRoomToken(body, roomName) {
|
|
|
1057
1060
|
breakoutRoomId: readString(payload, "breakout_room_id") ?? null,
|
|
1058
1061
|
observersVisibleTo: readString(payload, "observers_visible_to") === "hosts" ? "hosts" : "everyone",
|
|
1059
1062
|
connectionPolicy: connectionPolicyFrom(payload["connection_policy"]),
|
|
1060
|
-
leavePolicy: leavePolicyFrom(payload["leave_policy"])
|
|
1063
|
+
leavePolicy: leavePolicyFrom(payload["leave_policy"]),
|
|
1064
|
+
canReclaim: payload["can_reclaim"] === true
|
|
1061
1065
|
};
|
|
1062
1066
|
}
|
|
1063
1067
|
function createTokenClient(options) {
|
|
@@ -1519,6 +1523,42 @@ function createMeetAi(options) {
|
|
|
1519
1523
|
},
|
|
1520
1524
|
"meet.ai.startNoteTaker"
|
|
1521
1525
|
),
|
|
1526
|
+
requestCaptions: async ({ meetingId }) => {
|
|
1527
|
+
const roomToken = options.resolveRoomToken?.() ?? null;
|
|
1528
|
+
const operation = "meet.ai.requestCaptions";
|
|
1529
|
+
try {
|
|
1530
|
+
const response = await send({
|
|
1531
|
+
path: MEET_ROUTES.noteTakerCaptions,
|
|
1532
|
+
body: { meeting_id: meetingId },
|
|
1533
|
+
operation,
|
|
1534
|
+
requireAuth: roomToken === null,
|
|
1535
|
+
...roomToken !== null ? { headers: { [MEETING_PASS_HEADER]: roomToken } } : {}
|
|
1536
|
+
});
|
|
1537
|
+
if (!response.ok) {
|
|
1538
|
+
options.store.patch({ captionsRefusal: await refusalFor(response, operation) });
|
|
1539
|
+
return;
|
|
1540
|
+
}
|
|
1541
|
+
let payload = null;
|
|
1542
|
+
try {
|
|
1543
|
+
payload = await response.json();
|
|
1544
|
+
} catch {
|
|
1545
|
+
payload = null;
|
|
1546
|
+
}
|
|
1547
|
+
const row = typeof payload === "object" && payload !== null ? payload : {};
|
|
1548
|
+
const detail = typeof row["detail"] === "string" ? row["detail"] : "";
|
|
1549
|
+
options.store.patch({
|
|
1550
|
+
captionsRefusal: row["dispatched"] === true ? null : { status: 200, reason: detail, remedy: "" }
|
|
1551
|
+
});
|
|
1552
|
+
} catch (error) {
|
|
1553
|
+
options.store.patch({
|
|
1554
|
+
captionsRefusal: {
|
|
1555
|
+
status: 0,
|
|
1556
|
+
reason: error.message,
|
|
1557
|
+
remedy: error.remedy ?? ""
|
|
1558
|
+
}
|
|
1559
|
+
});
|
|
1560
|
+
}
|
|
1561
|
+
},
|
|
1522
1562
|
stopNoteTaker: ({ meetingId }) => dispatch(
|
|
1523
1563
|
MEET_ROUTES.noteTakerStop,
|
|
1524
1564
|
{ meeting_id: meetingId },
|
|
@@ -1557,7 +1597,7 @@ function exactNoteTakerParticipant(meeting, participants) {
|
|
|
1557
1597
|
}
|
|
1558
1598
|
function noteTakerStatus(args) {
|
|
1559
1599
|
const present = exactNoteTakerParticipant(args.meeting, args.participants) !== null;
|
|
1560
|
-
const raw = args.meeting?.metadata[NOTE_TAKER_METADATA_KEY];
|
|
1600
|
+
const raw = args.meeting?.metadata?.[NOTE_TAKER_METADATA_KEY];
|
|
1561
1601
|
const row = typeof raw === "object" && raw !== null && !Array.isArray(raw) ? raw : {};
|
|
1562
1602
|
const recorded = readState(row["state"]);
|
|
1563
1603
|
const detail = typeof row["reason"] === "string" && row["reason"].length > 0 ? row["reason"] : null;
|
|
@@ -3290,6 +3330,8 @@ function planFromRow(row) {
|
|
|
3290
3330
|
minutes: num2(row["minutes"]) ?? 0,
|
|
3291
3331
|
openedAt: str(row["opened_at"]),
|
|
3292
3332
|
endsAt: str(row["ends_at"]),
|
|
3333
|
+
closingAt: str(row["closing_at"]),
|
|
3334
|
+
moveMode: row["move_mode"] === "auto" ? "auto" : "invite",
|
|
3293
3335
|
closedAt: str(row["closed_at"]),
|
|
3294
3336
|
broadcasts: (Array.isArray(row["broadcasts"]) ? row["broadcasts"] : []).map(broadcastFrom).filter((b) => b !== null)
|
|
3295
3337
|
};
|
|
@@ -3441,9 +3483,17 @@ function autoAssign(identities, rooms, exclude = []) {
|
|
|
3441
3483
|
return out;
|
|
3442
3484
|
}
|
|
3443
3485
|
function breakoutRemainingMs(plan, now) {
|
|
3444
|
-
if (plan === null || plan.state !== "open"
|
|
3445
|
-
const
|
|
3446
|
-
|
|
3486
|
+
if (plan === null || plan.state !== "open") return null;
|
|
3487
|
+
const ends = [plan.endsAt, plan.closingAt].map((stamp) => stamp === null ? Number.NaN : Date.parse(stamp)).filter((time) => !Number.isNaN(time));
|
|
3488
|
+
if (ends.length === 0) return null;
|
|
3489
|
+
return Math.max(0, Math.min(...ends) - now);
|
|
3490
|
+
}
|
|
3491
|
+
var BREAKOUT_COUNTDOWN_MS = 3e4;
|
|
3492
|
+
function breakoutClosingMs(plan, now) {
|
|
3493
|
+
if (plan === null || plan.state !== "open") return null;
|
|
3494
|
+
const remaining = breakoutRemainingMs(plan, now);
|
|
3495
|
+
if (remaining === null) return null;
|
|
3496
|
+
return plan.closingAt !== null || remaining <= BREAKOUT_COUNTDOWN_MS ? remaining : null;
|
|
3447
3497
|
}
|
|
3448
3498
|
function defaultCaptionLanguage(settings, viewerLanguage) {
|
|
3449
3499
|
const configured = settings?.captionTranslationLanguage.trim() ?? "";
|
|
@@ -3690,6 +3740,47 @@ function recordingLabel(state) {
|
|
|
3690
3740
|
}
|
|
3691
3741
|
}
|
|
3692
3742
|
|
|
3743
|
+
// src/core/live-policy.ts
|
|
3744
|
+
var DEFAULT_LIVE_POLICY = {
|
|
3745
|
+
chatMode: "everyone",
|
|
3746
|
+
avLock: "off",
|
|
3747
|
+
timeLimitMinutes: 0,
|
|
3748
|
+
timeLimitWarningMinutes: 5,
|
|
3749
|
+
recordingConsent: "notice"
|
|
3750
|
+
};
|
|
3751
|
+
function oneOf(value, allowed, fallback) {
|
|
3752
|
+
return typeof value === "string" && allowed.includes(value) ? value : fallback;
|
|
3753
|
+
}
|
|
3754
|
+
function whole(value, fallback) {
|
|
3755
|
+
const n = typeof value === "number" ? value : typeof value === "string" ? Number(value) : NaN;
|
|
3756
|
+
return Number.isFinite(n) && n >= 0 ? Math.floor(n) : fallback;
|
|
3757
|
+
}
|
|
3758
|
+
function livePolicyFrom(raw) {
|
|
3759
|
+
const o = typeof raw === "object" && raw !== null ? raw : {};
|
|
3760
|
+
return {
|
|
3761
|
+
chatMode: oneOf(o["chat_mode"], ["everyone", "hosts_only", "off"], DEFAULT_LIVE_POLICY.chatMode),
|
|
3762
|
+
avLock: oneOf(o["attendee_av_lock"], ["off", "mic", "camera", "both"], DEFAULT_LIVE_POLICY.avLock),
|
|
3763
|
+
timeLimitMinutes: whole(o["time_limit_minutes"], 0),
|
|
3764
|
+
timeLimitWarningMinutes: whole(o["time_limit_warning_minutes"], DEFAULT_LIVE_POLICY.timeLimitWarningMinutes),
|
|
3765
|
+
recordingConsent: oneOf(
|
|
3766
|
+
o["recording_consent"],
|
|
3767
|
+
["notice", "ok_or_leave", "view_only_until_agree"],
|
|
3768
|
+
DEFAULT_LIVE_POLICY.recordingConsent
|
|
3769
|
+
)
|
|
3770
|
+
};
|
|
3771
|
+
}
|
|
3772
|
+
function samePolicy(a, b) {
|
|
3773
|
+
return a.chatMode === b.chatMode && a.avLock === b.avLock && a.timeLimitMinutes === b.timeLimitMinutes && a.timeLimitWarningMinutes === b.timeLimitWarningMinutes && a.recordingConsent === b.recordingConsent;
|
|
3774
|
+
}
|
|
3775
|
+
var MODERATORS = /* @__PURE__ */ new Set(["host", "cohost"]);
|
|
3776
|
+
function isLockedFor(policy, role, kind) {
|
|
3777
|
+
if (MODERATORS.has(role)) return false;
|
|
3778
|
+
return policy.avLock === "both" || (kind === "microphone" ? policy.avLock === "mic" : policy.avLock === "camera");
|
|
3779
|
+
}
|
|
3780
|
+
function consentPending(policy, role, recordingOn, given) {
|
|
3781
|
+
return recordingOn && !given && policy.recordingConsent !== "notice" && !MODERATORS.has(role);
|
|
3782
|
+
}
|
|
3783
|
+
|
|
3693
3784
|
// src/core/attendance.ts
|
|
3694
3785
|
var IDLE_MEDIA_REGION = {
|
|
3695
3786
|
permission: { microphone: "unknown", camera: "unknown" },
|
|
@@ -3760,6 +3851,11 @@ var EMPTY = {
|
|
|
3760
3851
|
presenter: null,
|
|
3761
3852
|
waitingCount: 0,
|
|
3762
3853
|
leavePolicy: DEFAULT_LEAVE_POLICY,
|
|
3854
|
+
livePolicy: DEFAULT_LIVE_POLICY,
|
|
3855
|
+
canReclaim: false,
|
|
3856
|
+
recordingConsentGiven: false,
|
|
3857
|
+
sessionStartedAt: null,
|
|
3858
|
+
mutedByHost: false,
|
|
3763
3859
|
moderationNotice: null,
|
|
3764
3860
|
actionNotice: null,
|
|
3765
3861
|
privateChatRequest: null,
|
|
@@ -3769,6 +3865,8 @@ var EMPTY = {
|
|
|
3769
3865
|
names: {},
|
|
3770
3866
|
wrapUp: null,
|
|
3771
3867
|
noteTakerRefusal: null,
|
|
3868
|
+
captionsOn: false,
|
|
3869
|
+
captionsRefusal: null,
|
|
3772
3870
|
media: IDLE_MEDIA,
|
|
3773
3871
|
mediaRegion: IDLE_MEDIA_REGION,
|
|
3774
3872
|
failure: null,
|
|
@@ -3973,7 +4071,12 @@ function createMeetStore(initial = {}) {
|
|
|
3973
4071
|
if (current.enabled === next.enabled && current.unavailable?.code === next.unavailable?.code && current.unavailable?.reason === next.unavailable?.reason && current.unavailable?.message === next.unavailable?.message) {
|
|
3974
4072
|
return;
|
|
3975
4073
|
}
|
|
3976
|
-
commit({
|
|
4074
|
+
commit({
|
|
4075
|
+
...state,
|
|
4076
|
+
media: { ...state.media, [kind]: next },
|
|
4077
|
+
// The person turned their own microphone on again: the host's mute is over.
|
|
4078
|
+
...kind === "microphone" && next.enabled && state.mutedByHost ? { mutedByHost: false } : {}
|
|
4079
|
+
});
|
|
3977
4080
|
},
|
|
3978
4081
|
reset() {
|
|
3979
4082
|
const phase = nextPhase(state.phase, { type: "reset", teardown: true }) ?? EMPTY.phase;
|
|
@@ -4011,8 +4114,7 @@ var ROOM_EVENTS = {
|
|
|
4011
4114
|
/**
|
|
4012
4115
|
* A host or co-host acted (Meet wave 2). Payload `{ meeting_id, kind, … }`:
|
|
4013
4116
|
* `muted {source, by}` · `ask-unmute {by}` · `removed {by}` — addressed to the
|
|
4014
|
-
* person concerned; `
|
|
4015
|
-
* role}` — to everyone.
|
|
4117
|
+
* person concerned; `role {identity, role}` — to everyone.
|
|
4016
4118
|
*/
|
|
4017
4119
|
moderation: "matrx.meet.moderation",
|
|
4018
4120
|
/**
|
|
@@ -4200,10 +4302,11 @@ function moderationText(kind, payload) {
|
|
|
4200
4302
|
switch (kind) {
|
|
4201
4303
|
case "muted": {
|
|
4202
4304
|
const source = text2(payload["source"]) ?? "microphone";
|
|
4203
|
-
|
|
4305
|
+
const who = payload["by_role"] === "host" || payload["by_role"] === "cohost" ? "the host" : by;
|
|
4306
|
+
return source === "microphone" ? `You've been muted by ${who}.` : source === "camera" ? `Your camera was turned off by ${who}.` : `Your screen share was stopped by ${who}.`;
|
|
4204
4307
|
}
|
|
4205
4308
|
case "ask-unmute":
|
|
4206
|
-
return `${by}
|
|
4309
|
+
return `${by === "The host" ? "The host" : by} asked you to unmute.`;
|
|
4207
4310
|
case "removed":
|
|
4208
4311
|
return `${by} removed you from this meeting.`;
|
|
4209
4312
|
default:
|
|
@@ -4229,7 +4332,7 @@ function applyModeration(store, payload, now) {
|
|
|
4229
4332
|
grants: { ...snapshot.grants, role },
|
|
4230
4333
|
moderationNotice: {
|
|
4231
4334
|
kind: "role",
|
|
4232
|
-
text: role === "host" ? "You are now the host." : role === "cohost" ? "You
|
|
4335
|
+
text: role === "host" ? "You are now the host." : role === "cohost" ? "You're now a co-host." : role === "presenter" ? "You're now a presenter." : snapshot.grants.role === "presenter" ? "You're now a participant: you can no longer present." : "You're now a participant: you are no longer a co-host.",
|
|
4233
4336
|
at: now()
|
|
4234
4337
|
}
|
|
4235
4338
|
});
|
|
@@ -4241,7 +4344,10 @@ function applyModeration(store, payload, now) {
|
|
|
4241
4344
|
case "removed": {
|
|
4242
4345
|
const sentence = moderationText(kind, payload);
|
|
4243
4346
|
if (sentence === null) return ignored("a moderation event with no sentence");
|
|
4244
|
-
store.patch({
|
|
4347
|
+
store.patch({
|
|
4348
|
+
moderationNotice: { kind, text: sentence, at: now() },
|
|
4349
|
+
...kind === "muted" && (text2(payload["source"]) ?? "microphone") === "microphone" ? { mutedByHost: true } : {}
|
|
4350
|
+
});
|
|
4245
4351
|
return HANDLED;
|
|
4246
4352
|
}
|
|
4247
4353
|
default:
|
|
@@ -5063,6 +5169,7 @@ function applyDoorRow(store, attendee) {
|
|
|
5063
5169
|
function decidedState(state) {
|
|
5064
5170
|
return WAITING_ADMISSION_STATES.includes(state) ? "expired" : state;
|
|
5065
5171
|
}
|
|
5172
|
+
var LIVE_POLICY_POLL_MS = 3e3;
|
|
5066
5173
|
function createMeetingSession(options) {
|
|
5067
5174
|
const { manager, repository, store, identity } = options;
|
|
5068
5175
|
let channel = null;
|
|
@@ -5204,6 +5311,46 @@ function createMeetingSession(options) {
|
|
|
5204
5311
|
stopWaiting();
|
|
5205
5312
|
}
|
|
5206
5313
|
}
|
|
5314
|
+
let policyTimer = null;
|
|
5315
|
+
let policyReading = false;
|
|
5316
|
+
async function readLivePolicy() {
|
|
5317
|
+
const meeting = store.snapshot().meeting;
|
|
5318
|
+
const pass = options.resolvePass?.() ?? null;
|
|
5319
|
+
if (meeting === null || pass === null || policyReading) return;
|
|
5320
|
+
policyReading = true;
|
|
5321
|
+
try {
|
|
5322
|
+
const response = await options.api.request({
|
|
5323
|
+
path: `${MEET_ROUTES.state}?meeting_id=${encodeURIComponent(meeting.id)}`,
|
|
5324
|
+
method: "GET",
|
|
5325
|
+
requireAuth: false,
|
|
5326
|
+
operation: "meet.state(policy)",
|
|
5327
|
+
headers: { [MEETING_PASS_HEADER]: pass }
|
|
5328
|
+
});
|
|
5329
|
+
if (!response.ok) return;
|
|
5330
|
+
const read = await response.json();
|
|
5331
|
+
const next = livePolicyFrom(read.live_policy);
|
|
5332
|
+
const started = read.session_started_at ? Date.parse(read.session_started_at) : NaN;
|
|
5333
|
+
const snapshot = store.snapshot();
|
|
5334
|
+
const startedAt = Number.isFinite(started) ? started : snapshot.sessionStartedAt;
|
|
5335
|
+
if (!samePolicy(snapshot.livePolicy, next) || startedAt !== snapshot.sessionStartedAt) {
|
|
5336
|
+
store.patch({ livePolicy: next, sessionStartedAt: startedAt });
|
|
5337
|
+
}
|
|
5338
|
+
} catch {
|
|
5339
|
+
} finally {
|
|
5340
|
+
policyReading = false;
|
|
5341
|
+
}
|
|
5342
|
+
}
|
|
5343
|
+
function syncLivePolicyTimer() {
|
|
5344
|
+
const inCall = store.snapshot().phase === "in_call";
|
|
5345
|
+
if (inCall && policyTimer === null) {
|
|
5346
|
+
void readLivePolicy();
|
|
5347
|
+
policyTimer = setInterval(() => void readLivePolicy(), LIVE_POLICY_POLL_MS);
|
|
5348
|
+
} else if (!inCall && policyTimer !== null) {
|
|
5349
|
+
clearInterval(policyTimer);
|
|
5350
|
+
policyTimer = null;
|
|
5351
|
+
}
|
|
5352
|
+
}
|
|
5353
|
+
const unsubscribePolicy = store.subscribe(syncLivePolicyTimer);
|
|
5207
5354
|
async function readState2() {
|
|
5208
5355
|
if (reading !== null) return reading;
|
|
5209
5356
|
const meeting = store.snapshot().meeting;
|
|
@@ -5590,6 +5737,9 @@ function createMeetingSession(options) {
|
|
|
5590
5737
|
},
|
|
5591
5738
|
dispose() {
|
|
5592
5739
|
stopWaiting();
|
|
5740
|
+
unsubscribePolicy();
|
|
5741
|
+
if (policyTimer !== null) clearInterval(policyTimer);
|
|
5742
|
+
policyTimer = null;
|
|
5593
5743
|
channel?.close();
|
|
5594
5744
|
channel = null;
|
|
5595
5745
|
meetingChannel?.close();
|
|
@@ -6907,6 +7057,7 @@ function createRoomEngine(options) {
|
|
|
6907
7057
|
lastServerUrl = token.serverUrl;
|
|
6908
7058
|
connectionPolicy = token.connectionPolicy ?? DEFAULT_CONNECTION_POLICY;
|
|
6909
7059
|
if (token.leavePolicy !== void 0) store.patch({ leavePolicy: token.leavePolicy });
|
|
7060
|
+
store.patch({ canReclaim: token.canReclaim === true });
|
|
6910
7061
|
store.patch({
|
|
6911
7062
|
localIdentity: token.identity,
|
|
6912
7063
|
breakoutRoomId: token.breakoutRoomId ?? null,
|
|
@@ -7401,13 +7552,17 @@ var MODERATION_ACTIONS = [
|
|
|
7401
7552
|
"ask_unmute",
|
|
7402
7553
|
"ask_all_unmute",
|
|
7403
7554
|
"spotlight",
|
|
7404
|
-
"
|
|
7555
|
+
"sync_presenter",
|
|
7405
7556
|
"raise_hand",
|
|
7406
7557
|
"lower_hand",
|
|
7407
7558
|
"lower_all_hands",
|
|
7408
7559
|
"make_cohost",
|
|
7560
|
+
"make_presenter",
|
|
7561
|
+
"revoke_presenter",
|
|
7562
|
+
"set_av_lock",
|
|
7409
7563
|
"revoke_cohost",
|
|
7410
7564
|
"transfer_host",
|
|
7565
|
+
"reclaim_host",
|
|
7411
7566
|
"rename",
|
|
7412
7567
|
"remove",
|
|
7413
7568
|
"report"
|
|
@@ -7433,18 +7588,17 @@ function createInRoomClient(options) {
|
|
|
7433
7588
|
function refusal2(response, operation, remedy) {
|
|
7434
7589
|
return refusalFromResponse(response, operation, remedy);
|
|
7435
7590
|
}
|
|
7436
|
-
let
|
|
7591
|
+
let toldSharing = false;
|
|
7437
7592
|
let tellChain = Promise.resolve();
|
|
7438
7593
|
store.subscribe(() => {
|
|
7439
7594
|
const local = store.snapshot().participants.find((p) => p.isLocal);
|
|
7440
7595
|
const sharing = local?.screenSharing === true;
|
|
7441
|
-
if (sharing ===
|
|
7442
|
-
|
|
7443
|
-
|
|
7444
|
-
tellChain = tellChain.then(() => client.moderate({ action: "present", on })).then(
|
|
7596
|
+
if (sharing === toldSharing || local === void 0) return;
|
|
7597
|
+
toldSharing = sharing;
|
|
7598
|
+
tellChain = tellChain.then(() => client.moderate({ action: "sync_presenter" })).then(
|
|
7445
7599
|
() => void 0,
|
|
7446
7600
|
(error) => {
|
|
7447
|
-
console.warn(`[meet] the server did not take
|
|
7601
|
+
console.warn(`[meet] the server did not take the screen-share change: ${String(error)}`);
|
|
7448
7602
|
}
|
|
7449
7603
|
);
|
|
7450
7604
|
});
|
|
@@ -7461,8 +7615,7 @@ function createInRoomClient(options) {
|
|
|
7461
7615
|
action: request.action,
|
|
7462
7616
|
...request.identity != null ? { identity: request.identity } : {},
|
|
7463
7617
|
...request.name !== void 0 ? { name: request.name } : {},
|
|
7464
|
-
...request.reason !== void 0 ? { reason: request.reason } : {}
|
|
7465
|
-
...request.on !== void 0 ? { on: request.on } : {}
|
|
7618
|
+
...request.reason !== void 0 ? { reason: request.reason } : {}
|
|
7466
7619
|
},
|
|
7467
7620
|
...hdrs !== void 0 ? { headers: hdrs } : {}
|
|
7468
7621
|
});
|
|
@@ -8339,11 +8492,13 @@ function takeMoveRequest(store) {
|
|
|
8339
8492
|
|
|
8340
8493
|
// src/core/observation.ts
|
|
8341
8494
|
function observedRole(role, standing) {
|
|
8342
|
-
if (role === "host" || role === "cohost") return role;
|
|
8495
|
+
if (role === "host" || role === "cohost" || role === "presenter") return role;
|
|
8343
8496
|
return isLinkFollower(standing) ? "guest" : "participant";
|
|
8344
8497
|
}
|
|
8345
|
-
function observedDevice(track, permission = "unknown") {
|
|
8498
|
+
function observedDevice(track, permission = "unknown", held = null) {
|
|
8499
|
+
if (held === "locked") return "locked";
|
|
8346
8500
|
if (track.enabled) return "on";
|
|
8501
|
+
if (held === "muted_by_host") return "muted_by_host";
|
|
8347
8502
|
const reason = deviceUnavailableReason(track, permission);
|
|
8348
8503
|
return reason === null ? "muted_by_me" : `unavailable:${reason}`;
|
|
8349
8504
|
}
|
|
@@ -8380,10 +8535,20 @@ function observe(input) {
|
|
|
8380
8535
|
recording: snapshot?.recording === "recording" || snapshot?.recording === "stopping",
|
|
8381
8536
|
// S6c: the autoplay region is known only inside the room (no remote audio exists elsewhere).
|
|
8382
8537
|
audioBlocked: inCall && snapshot !== null ? snapshot.mediaRegion.audioOutput === "blocked" : null,
|
|
8383
|
-
camera: deviceInPlay && snapshot !== null ? observedDevice(snapshot.media.camera, snapshot.mediaRegion.permission.camera) : null,
|
|
8384
|
-
microphone: deviceInPlay && snapshot !== null ? observedDevice(snapshot.media.microphone, snapshot.mediaRegion.permission.microphone) : null
|
|
8538
|
+
camera: deviceInPlay && snapshot !== null ? observedDevice(snapshot.media.camera, snapshot.mediaRegion.permission.camera, lockedFor(snapshot, "camera", inCall)) : null,
|
|
8539
|
+
microphone: deviceInPlay && snapshot !== null ? observedDevice(snapshot.media.microphone, snapshot.mediaRegion.permission.microphone, lockedFor(snapshot, "microphone", inCall)) : null
|
|
8385
8540
|
};
|
|
8386
8541
|
}
|
|
8542
|
+
function lockedFor(snapshot, kind, inCall) {
|
|
8543
|
+
if (!inCall) return null;
|
|
8544
|
+
const role = effectiveRole(snapshot);
|
|
8545
|
+
if (isLockedFor(snapshot.livePolicy, role, kind)) return "locked";
|
|
8546
|
+
if (snapshot.livePolicy.recordingConsent === "view_only_until_agree" && consentPending(snapshot.livePolicy, role, snapshot.recording === "recording", snapshot.recordingConsentGiven)) {
|
|
8547
|
+
return "locked";
|
|
8548
|
+
}
|
|
8549
|
+
if (kind === "microphone" && snapshot.mutedByHost) return "muted_by_host";
|
|
8550
|
+
return null;
|
|
8551
|
+
}
|
|
8387
8552
|
function staticObservation(phase, reason = null) {
|
|
8388
8553
|
return {
|
|
8389
8554
|
phase,
|