@ai-matrx/meet 0.7.79 → 0.7.81
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 +26 -0
- package/dist/index.cjs +55 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +8 -4
- package/dist/index.d.ts +8 -4
- package/dist/index.js +55 -19
- package/dist/index.js.map +1 -1
- package/dist/react.cjs +59 -26
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +6 -0
- package/dist/react.d.ts +6 -0
- package/dist/react.js +59 -26
- package/dist/react.js.map +1 -1
- package/package.json +4 -4
package/dist/index.d.cts
CHANGED
|
@@ -796,10 +796,10 @@ declare function unavailableFrom(error: MeetError): MediaUnavailable;
|
|
|
796
796
|
*/
|
|
797
797
|
declare const LISTEN_ONLY_NOTICE = "You're attending without a microphone \u2014 others can't hear you";
|
|
798
798
|
/**
|
|
799
|
-
* True when this participant is in the room
|
|
800
|
-
*
|
|
801
|
-
*
|
|
802
|
-
*
|
|
799
|
+
* True when this participant is in the room with NO USABLE microphone — the
|
|
800
|
+
* device was refused or is missing. A person who simply muted themselves has a
|
|
801
|
+
* working microphone and is not "attending without" one, so a mute never
|
|
802
|
+
* counts: `unavailable` is the only signal.
|
|
803
803
|
*/
|
|
804
804
|
declare function isListenOnly(media: LocalMediaState): boolean;
|
|
805
805
|
/**
|
|
@@ -2408,6 +2408,8 @@ interface MeetRoomDriver {
|
|
|
2408
2408
|
setVideoEffect?(effect: VideoEffect): Promise<void>;
|
|
2409
2409
|
/** Whether this browser can run background effects at all. */
|
|
2410
2410
|
supportsVideoEffects?(): boolean;
|
|
2411
|
+
/** Whether this browser can share a screen at all (iOS cannot). Absent = assume yes. */
|
|
2412
|
+
supportsScreenShare?(): boolean;
|
|
2411
2413
|
/**
|
|
2412
2414
|
* Attach a participant's track to a media element. Returns the detach
|
|
2413
2415
|
* function — returning it (rather than exposing `detach`) is what makes a
|
|
@@ -3463,6 +3465,8 @@ interface RoomEngine {
|
|
|
3463
3465
|
setEffects(next: Partial<MediaEffects>): Promise<void>;
|
|
3464
3466
|
/** Whether this browser can run a background effect at all (absent, never dead). */
|
|
3465
3467
|
supportsVideoEffects(): boolean;
|
|
3468
|
+
/** Whether this browser can share a screen at all — the control is ABSENT where it cannot. */
|
|
3469
|
+
supportsScreenShare(): boolean;
|
|
3466
3470
|
/** Choose the speaker (audio output) for this meeting. */
|
|
3467
3471
|
switchDevice(kind: "audioinput" | "videoinput" | "audiooutput", deviceId: string): Promise<void>;
|
|
3468
3472
|
pin(identity: ParticipantIdentity | null): void;
|
package/dist/index.d.ts
CHANGED
|
@@ -796,10 +796,10 @@ declare function unavailableFrom(error: MeetError): MediaUnavailable;
|
|
|
796
796
|
*/
|
|
797
797
|
declare const LISTEN_ONLY_NOTICE = "You're attending without a microphone \u2014 others can't hear you";
|
|
798
798
|
/**
|
|
799
|
-
* True when this participant is in the room
|
|
800
|
-
*
|
|
801
|
-
*
|
|
802
|
-
*
|
|
799
|
+
* True when this participant is in the room with NO USABLE microphone — the
|
|
800
|
+
* device was refused or is missing. A person who simply muted themselves has a
|
|
801
|
+
* working microphone and is not "attending without" one, so a mute never
|
|
802
|
+
* counts: `unavailable` is the only signal.
|
|
803
803
|
*/
|
|
804
804
|
declare function isListenOnly(media: LocalMediaState): boolean;
|
|
805
805
|
/**
|
|
@@ -2408,6 +2408,8 @@ interface MeetRoomDriver {
|
|
|
2408
2408
|
setVideoEffect?(effect: VideoEffect): Promise<void>;
|
|
2409
2409
|
/** Whether this browser can run background effects at all. */
|
|
2410
2410
|
supportsVideoEffects?(): boolean;
|
|
2411
|
+
/** Whether this browser can share a screen at all (iOS cannot). Absent = assume yes. */
|
|
2412
|
+
supportsScreenShare?(): boolean;
|
|
2411
2413
|
/**
|
|
2412
2414
|
* Attach a participant's track to a media element. Returns the detach
|
|
2413
2415
|
* function — returning it (rather than exposing `detach`) is what makes a
|
|
@@ -3463,6 +3465,8 @@ interface RoomEngine {
|
|
|
3463
3465
|
setEffects(next: Partial<MediaEffects>): Promise<void>;
|
|
3464
3466
|
/** Whether this browser can run a background effect at all (absent, never dead). */
|
|
3465
3467
|
supportsVideoEffects(): boolean;
|
|
3468
|
+
/** Whether this browser can share a screen at all — the control is ABSENT where it cannot. */
|
|
3469
|
+
supportsScreenShare(): boolean;
|
|
3466
3470
|
/** Choose the speaker (audio output) for this meeting. */
|
|
3467
3471
|
switchDevice(kind: "audioinput" | "videoinput" | "audiooutput", deviceId: string): Promise<void>;
|
|
3468
3472
|
pin(identity: ParticipantIdentity | null): void;
|
package/dist/index.js
CHANGED
|
@@ -139,6 +139,32 @@ function normalizeDeviceError(error, operation) {
|
|
|
139
139
|
);
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
|
+
function isScreenShareCancel(error) {
|
|
143
|
+
const named = (value) => typeof value?.name === "string" ? value.name : "";
|
|
144
|
+
const cause = error instanceof MeetError ? error.cause : void 0;
|
|
145
|
+
const names = [named(error), named(cause)];
|
|
146
|
+
if (names.some((name) => name === "NotAllowedError" || name === "AbortError")) return true;
|
|
147
|
+
return error instanceof MeetError && error.code === "permission-denied";
|
|
148
|
+
}
|
|
149
|
+
function normalizeScreenShareError(error, operation) {
|
|
150
|
+
if (error instanceof MeetError) return error;
|
|
151
|
+
const raw = error ?? {};
|
|
152
|
+
const message = typeof raw.message === "string" ? raw.message : String(error);
|
|
153
|
+
if (isScreenShareCancel(error)) {
|
|
154
|
+
return new MeetError(
|
|
155
|
+
"permission-denied",
|
|
156
|
+
`${operation}: screen sharing was cancelled`,
|
|
157
|
+
"Choose a screen, window or tab in the picker to share it.",
|
|
158
|
+
error
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
return new MeetError(
|
|
162
|
+
"media-unsupported",
|
|
163
|
+
`${operation}: screen sharing is not available (${message})`,
|
|
164
|
+
"This browser or device could not share a screen. You are still in the call; try a desktop browser to present.",
|
|
165
|
+
error
|
|
166
|
+
);
|
|
167
|
+
}
|
|
142
168
|
function invalidResponse(operation, detail) {
|
|
143
169
|
return new MeetError(
|
|
144
170
|
"invalid-response",
|
|
@@ -2602,7 +2628,7 @@ function unavailableFrom(error) {
|
|
|
2602
2628
|
}
|
|
2603
2629
|
var LISTEN_ONLY_NOTICE = "You're attending without a microphone \u2014 others can't hear you";
|
|
2604
2630
|
function isListenOnly(media) {
|
|
2605
|
-
return !media.microphone.enabled;
|
|
2631
|
+
return !media.microphone.enabled && media.microphone.unavailable !== null;
|
|
2606
2632
|
}
|
|
2607
2633
|
function listenOnlyNotice(media) {
|
|
2608
2634
|
return isListenOnly(media) ? LISTEN_ONLY_NOTICE : null;
|
|
@@ -3789,7 +3815,7 @@ function createLiveKitDriver(handlers, options = {}) {
|
|
|
3789
3815
|
try {
|
|
3790
3816
|
await requireRoom("setScreenShareEnabled").localParticipant.setScreenShareEnabled(enabled);
|
|
3791
3817
|
} catch (error) {
|
|
3792
|
-
throw
|
|
3818
|
+
throw normalizeScreenShareError(error, "meet.setScreenShareEnabled");
|
|
3793
3819
|
}
|
|
3794
3820
|
},
|
|
3795
3821
|
async publishData(topic, payload, to) {
|
|
@@ -3826,6 +3852,9 @@ function createLiveKitDriver(handlers, options = {}) {
|
|
|
3826
3852
|
supportsVideoEffects() {
|
|
3827
3853
|
return videoEffectsSupported();
|
|
3828
3854
|
},
|
|
3855
|
+
supportsScreenShare() {
|
|
3856
|
+
return typeof navigator !== "undefined" && typeof navigator.mediaDevices?.getDisplayMedia === "function";
|
|
3857
|
+
},
|
|
3829
3858
|
attach(identity, kind, element) {
|
|
3830
3859
|
const target = requireRoom("attach");
|
|
3831
3860
|
const source = sources?.[kind];
|
|
@@ -4340,6 +4369,7 @@ function fileDownloadPath(fileId) {
|
|
|
4340
4369
|
}
|
|
4341
4370
|
|
|
4342
4371
|
// src/core/after.ts
|
|
4372
|
+
import { toDelimited } from "@ai-matrx/kit/delimited";
|
|
4343
4373
|
import { formatDurationMs } from "@ai-matrx/kit/format";
|
|
4344
4374
|
function kindOf(person) {
|
|
4345
4375
|
if (person.isAgent) return "assistant";
|
|
@@ -4478,11 +4508,6 @@ function attendanceTotals(rows) {
|
|
|
4478
4508
|
averageMs: timed.length === 0 ? null : Math.round(timed.reduce((sum, row) => sum + (row.durationMs ?? 0), 0) / timed.length)
|
|
4479
4509
|
};
|
|
4480
4510
|
}
|
|
4481
|
-
function csvCell(value) {
|
|
4482
|
-
if (value === null) return "";
|
|
4483
|
-
const text3 = String(value);
|
|
4484
|
-
return /[",\n\r]/.test(text3) ? `"${text3.replace(/"/g, '""')}"` : text3;
|
|
4485
|
-
}
|
|
4486
4511
|
var ATTENDANCE_CSV_HEADER = [
|
|
4487
4512
|
"Meeting",
|
|
4488
4513
|
"Meeting started",
|
|
@@ -4494,11 +4519,11 @@ var ATTENDANCE_CSV_HEADER = [
|
|
|
4494
4519
|
"Admission"
|
|
4495
4520
|
];
|
|
4496
4521
|
function attendanceCsv(reports) {
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
[
|
|
4522
|
+
return toDelimited(
|
|
4523
|
+
[
|
|
4524
|
+
ATTENDANCE_CSV_HEADER,
|
|
4525
|
+
...reports.flatMap(
|
|
4526
|
+
({ meeting, rows }) => rows.map((row) => [
|
|
4502
4527
|
meeting.title,
|
|
4503
4528
|
meeting.startedAt ?? meeting.scheduledFor,
|
|
4504
4529
|
row.name,
|
|
@@ -4507,12 +4532,11 @@ function attendanceCsv(reports) {
|
|
|
4507
4532
|
row.leftAt,
|
|
4508
4533
|
row.durationMs === null ? null : Math.round(row.durationMs / 6e3) / 10,
|
|
4509
4534
|
row.admission
|
|
4510
|
-
]
|
|
4511
|
-
)
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
`;
|
|
4535
|
+
])
|
|
4536
|
+
)
|
|
4537
|
+
],
|
|
4538
|
+
{ lineEnding: "\r\n", trailingNewline: true }
|
|
4539
|
+
);
|
|
4516
4540
|
}
|
|
4517
4541
|
function recordingOffsetMs(at, recording) {
|
|
4518
4542
|
if (recording === null || recording.state !== "available") return null;
|
|
@@ -5281,7 +5305,16 @@ function createRoomEngine(options) {
|
|
|
5281
5305
|
try {
|
|
5282
5306
|
await driver.setScreenShareEnabled(enabled);
|
|
5283
5307
|
} catch (error) {
|
|
5284
|
-
|
|
5308
|
+
if (isScreenShareCancel(error)) return;
|
|
5309
|
+
const normalized = normalizeScreenShareError(error, "meet.setScreenShareEnabled");
|
|
5310
|
+
report("warn", normalized.message, normalized.remedy);
|
|
5311
|
+
store.patch({
|
|
5312
|
+
actionNotice: {
|
|
5313
|
+
text: `Screen sharing is not available. ${normalized.remedy}`,
|
|
5314
|
+
failed: true,
|
|
5315
|
+
at: now()
|
|
5316
|
+
}
|
|
5317
|
+
});
|
|
5285
5318
|
}
|
|
5286
5319
|
},
|
|
5287
5320
|
async raiseHand(raised) {
|
|
@@ -5329,6 +5362,9 @@ function createRoomEngine(options) {
|
|
|
5329
5362
|
supportsVideoEffects() {
|
|
5330
5363
|
return driver?.supportsVideoEffects?.() ?? false;
|
|
5331
5364
|
},
|
|
5365
|
+
supportsScreenShare() {
|
|
5366
|
+
return driver?.supportsScreenShare?.() ?? true;
|
|
5367
|
+
},
|
|
5332
5368
|
async switchDevice(kind, deviceId) {
|
|
5333
5369
|
if (driver === null) return;
|
|
5334
5370
|
await driver.switchDevice(kind, deviceId);
|