@ai-matrx/meet 0.7.81 → 0.7.82

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 CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog — `@ai-matrx/meet`
2
2
 
3
+ ## 0.7.82
4
+
5
+ - Screen share: a SYSTEM or POLICY block (Chrome/Edge "Permission denied by system", a
6
+ permissions-policy / `display-capture` block, SecurityError) now shows a short notice with the
7
+ remedy (macOS Screen Recording, administrator) and the person stays in the call. A plain
8
+ `NotAllowedError` is a closed picker in Chrome but is indistinguishable from a block in Firefox and
9
+ Safari, so the first one stays silent and the second in a row shows the same notice. New
10
+ `classifyScreenShareError`; `isScreenShareCancel` is now true only for the ambiguous case.
11
+ - Guards: `in-call-phase-guard.test.ts` fails if any action other than join / rejoin / moveToBreakout
12
+ can call `fail()`; the real `supportsScreenShare` browser check is tested in `livekit-driver.test.ts`.
13
+
14
+ **Consumer action:** none.
15
+
3
16
  ## 0.7.81
4
17
 
5
18
  **Three live defects, one class: an in-call action never changes the call phase.**
package/dist/index.cjs CHANGED
@@ -350,22 +350,45 @@ function normalizeDeviceError(error, operation) {
350
350
  );
351
351
  }
352
352
  }
353
- function isScreenShareCancel(error) {
354
- const named = (value) => typeof value?.name === "string" ? value.name : "";
353
+ var SYSTEM_BLOCK = /by system|permissions?[- ]policy|display-capture|disallowed|not allowed by the system/i;
354
+ function classifyScreenShareError(error) {
355
+ const read = (value, key) => {
356
+ const v = value?.[key];
357
+ return typeof v === "string" ? v : "";
358
+ };
355
359
  const cause = error instanceof MeetError ? error.cause : void 0;
356
- const names = [named(error), named(cause)];
357
- if (names.some((name) => name === "NotAllowedError" || name === "AbortError")) return true;
358
- return error instanceof MeetError && error.code === "permission-denied";
360
+ const denied = [error, cause].some((value) => {
361
+ const name = read(value, "name");
362
+ return name === "NotAllowedError" || name === "AbortError" || name === "SecurityError";
363
+ });
364
+ if (denied) {
365
+ const text3 = [read(error, "message"), read(cause, "message")].join(" ");
366
+ return SYSTEM_BLOCK.test(text3) || [error, cause].some((v) => read(v, "name") === "SecurityError") ? "blocked" : "ambiguous";
367
+ }
368
+ if (error instanceof MeetError && error.code === "permission-denied" && cause === void 0) {
369
+ return "ambiguous";
370
+ }
371
+ return "other";
359
372
  }
373
+ var SCREEN_SHARE_BLOCKED_REMEDY = "Your browser or computer is blocking screen sharing. On a Mac, open System Settings > Privacy & Security > Screen Recording, turn it on for your browser, then restart the browser. On a work computer, ask your administrator. You are still in the call.";
360
374
  function normalizeScreenShareError(error, operation) {
361
375
  if (error instanceof MeetError) return error;
362
376
  const raw = error ?? {};
363
377
  const message = typeof raw.message === "string" ? raw.message : String(error);
364
- if (isScreenShareCancel(error)) {
378
+ const kind = classifyScreenShareError(error);
379
+ if (kind === "blocked") {
380
+ return new MeetError(
381
+ "permission-denied",
382
+ `${operation}: screen sharing is blocked (${message})`,
383
+ SCREEN_SHARE_BLOCKED_REMEDY,
384
+ error
385
+ );
386
+ }
387
+ if (kind === "ambiguous") {
365
388
  return new MeetError(
366
389
  "permission-denied",
367
- `${operation}: screen sharing was cancelled`,
368
- "Choose a screen, window or tab in the picker to share it.",
390
+ `${operation}: screen sharing was cancelled or refused`,
391
+ "Choose a screen, window or tab in the picker to share it. If no picker appeared, " + SCREEN_SHARE_BLOCKED_REMEDY,
369
392
  error
370
393
  );
371
394
  }
@@ -5125,6 +5148,7 @@ function createRoomEngine(options) {
5125
5148
  function report(level, message, remedy) {
5126
5149
  options.onDiagnostic?.(remedy === void 0 ? { level, message } : { level, message, remedy });
5127
5150
  }
5151
+ let ambiguousShareDenials = 0;
5128
5152
  function fail(error, operation) {
5129
5153
  const normalized = normalizeMeetError(error, operation);
5130
5154
  store.patch({
@@ -5515,17 +5539,17 @@ function createRoomEngine(options) {
5515
5539
  if (driver === null) return;
5516
5540
  try {
5517
5541
  await driver.setScreenShareEnabled(enabled);
5542
+ ambiguousShareDenials = 0;
5518
5543
  } catch (error) {
5519
- if (isScreenShareCancel(error)) return;
5544
+ const kind = classifyScreenShareError(error);
5545
+ if (kind === "ambiguous") {
5546
+ ambiguousShareDenials += 1;
5547
+ if (ambiguousShareDenials < 2) return;
5548
+ }
5520
5549
  const normalized = normalizeScreenShareError(error, "meet.setScreenShareEnabled");
5521
5550
  report("warn", normalized.message, normalized.remedy);
5522
- store.patch({
5523
- actionNotice: {
5524
- text: `Screen sharing is not available. ${normalized.remedy}`,
5525
- failed: true,
5526
- at: now()
5527
- }
5528
- });
5551
+ const text3 = kind === "other" ? `Screen sharing is not available. ${normalized.remedy}` : `Screen sharing did not start. ${SCREEN_SHARE_BLOCKED_REMEDY}`;
5552
+ store.patch({ actionNotice: { text: text3, failed: true, at: now() } });
5529
5553
  }
5530
5554
  },
5531
5555
  async raiseHand(raised) {