@skippr/live-agent-sdk 0.97.0 → 0.98.0
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/dist/esm/lib-exports.js
CHANGED
|
@@ -4976,6 +4976,7 @@ function accessibleName(element, options = {}) {
|
|
|
4976
4976
|
var REF_PREFIX = "r-";
|
|
4977
4977
|
var VALUE_MAX_CHARS = 80;
|
|
4978
4978
|
var HREF_MAX_CHARS = 60;
|
|
4979
|
+
var TABLE_ROW_MAX_CHARS = 160;
|
|
4979
4980
|
var PAGE_CONTENT_MAX_BYTES = 14000;
|
|
4980
4981
|
var NODE_LIMIT = 1500;
|
|
4981
4982
|
var SENSITIVE_IFRAME_HOSTS = [
|
|
@@ -5321,8 +5322,9 @@ function ensureStableRef(element) {
|
|
|
5321
5322
|
function formatNodeAsLine(entry) {
|
|
5322
5323
|
const indent = " ".repeat(entry.depth);
|
|
5323
5324
|
const namePart = entry.name ? ` "${escapeAttributeValue(entry.name)}"` : "";
|
|
5325
|
+
const refPart = entry.ref ? ` ${entry.ref}` : "";
|
|
5324
5326
|
const attrsPart = entry.attrs.length > 0 ? ` ${entry.attrs.join(" ")}` : "";
|
|
5325
|
-
return `${indent}${entry.role}${namePart}
|
|
5327
|
+
return `${indent}${entry.role}${namePart}${refPart}${attrsPart}`;
|
|
5326
5328
|
}
|
|
5327
5329
|
function shouldSkipSubtree(element) {
|
|
5328
5330
|
if (element.id === WIDGET_ROOT_ID)
|
|
@@ -5350,13 +5352,66 @@ function getSameOriginIframeBody(element) {
|
|
|
5350
5352
|
return null;
|
|
5351
5353
|
}
|
|
5352
5354
|
}
|
|
5353
|
-
function
|
|
5355
|
+
function normalizeText(text) {
|
|
5356
|
+
return (text ?? "").replace(/\s+/g, " ").trim();
|
|
5357
|
+
}
|
|
5358
|
+
function formatTableRowText(row) {
|
|
5359
|
+
const cellValues = Array.from(row.children).filter((cell) => cell.tagName === "TD" || cell.tagName === "TH").map((cell) => normalizeText(cell.textContent).slice(0, VALUE_MAX_CHARS));
|
|
5360
|
+
return cellValues.join(" | ").slice(0, TABLE_ROW_MAX_CHARS).trim();
|
|
5361
|
+
}
|
|
5362
|
+
function isTableHeaderRow(row) {
|
|
5363
|
+
return Array.from(row.children).some((cell) => cell.tagName === "TH");
|
|
5364
|
+
}
|
|
5365
|
+
function directTextOfElement(element) {
|
|
5366
|
+
let combinedText = "";
|
|
5367
|
+
for (const childNode of Array.from(element.childNodes)) {
|
|
5368
|
+
if (childNode.nodeType === Node.TEXT_NODE)
|
|
5369
|
+
combinedText += `${childNode.textContent} `;
|
|
5370
|
+
}
|
|
5371
|
+
return normalizeText(combinedText);
|
|
5372
|
+
}
|
|
5373
|
+
var REFLESS_TEXT_ENTRY_REF = "";
|
|
5374
|
+
function collectRefLessTextLeaf(text, depth, rect, entries) {
|
|
5375
|
+
entries.push({
|
|
5376
|
+
depth,
|
|
5377
|
+
role: "text",
|
|
5378
|
+
name: text.slice(0, VALUE_MAX_CHARS),
|
|
5379
|
+
ref: REFLESS_TEXT_ENTRY_REF,
|
|
5380
|
+
attrs: [],
|
|
5381
|
+
area: rect.width * rect.height
|
|
5382
|
+
});
|
|
5383
|
+
}
|
|
5384
|
+
function collectTableRowAsSingleEntry(row, depth, rect, entries) {
|
|
5385
|
+
const rowText = formatTableRowText(row);
|
|
5386
|
+
if (!rowText)
|
|
5387
|
+
return false;
|
|
5388
|
+
entries.push({
|
|
5389
|
+
depth,
|
|
5390
|
+
role: "row",
|
|
5391
|
+
name: rowText,
|
|
5392
|
+
ref: ensureStableRef(row),
|
|
5393
|
+
attrs: isTableHeaderRow(row) ? ["header"] : [],
|
|
5394
|
+
area: rect.width * rect.height
|
|
5395
|
+
});
|
|
5396
|
+
for (const child of Array.from(row.children)) {
|
|
5397
|
+
walkAndCollect(child, depth + 1, entries, true);
|
|
5398
|
+
}
|
|
5399
|
+
return true;
|
|
5400
|
+
}
|
|
5401
|
+
function walkAndCollect(element, depth, entries, suppressTextLeaves = false) {
|
|
5354
5402
|
if (shouldSkipSubtree(element))
|
|
5355
5403
|
return;
|
|
5356
5404
|
const rect = element.getBoundingClientRect();
|
|
5405
|
+
if (element.tagName === "TR") {
|
|
5406
|
+
if (!isVisible(element, rect))
|
|
5407
|
+
return;
|
|
5408
|
+
if (collectTableRowAsSingleEntry(element, depth, rect, entries))
|
|
5409
|
+
return;
|
|
5410
|
+
}
|
|
5357
5411
|
const role = inferRole(element) ?? (isCursorClickable(element, rect) ? "button" : null);
|
|
5358
5412
|
const isVisibleAndEmittable = role !== null && isVisible(element, rect) && shouldEmitElement(element, role);
|
|
5359
5413
|
let childDepth = depth;
|
|
5414
|
+
let childSuppressTextLeaves = suppressTextLeaves;
|
|
5360
5415
|
if (isVisibleAndEmittable && role) {
|
|
5361
5416
|
const ref = ensureStableRef(element);
|
|
5362
5417
|
const name = accessibleName(element);
|
|
@@ -5369,12 +5424,20 @@ function walkAndCollect(element, depth, entries) {
|
|
|
5369
5424
|
area: rect.width * rect.height
|
|
5370
5425
|
});
|
|
5371
5426
|
childDepth = depth + 1;
|
|
5427
|
+
const nameAlreadyCoversSubtreeText = name !== "";
|
|
5428
|
+
if (nameAlreadyCoversSubtreeText)
|
|
5429
|
+
childSuppressTextLeaves = true;
|
|
5430
|
+
} else if (!suppressTextLeaves) {
|
|
5431
|
+
const ownText = directTextOfElement(element);
|
|
5432
|
+
if (ownText && isVisible(element, rect)) {
|
|
5433
|
+
collectRefLessTextLeaf(ownText, depth, rect, entries);
|
|
5434
|
+
}
|
|
5372
5435
|
}
|
|
5373
5436
|
if (role === "iframe") {
|
|
5374
5437
|
const iframeBody = getSameOriginIframeBody(element);
|
|
5375
5438
|
if (iframeBody) {
|
|
5376
5439
|
for (const child of Array.from(iframeBody.children)) {
|
|
5377
|
-
walkAndCollect(child, childDepth, entries);
|
|
5440
|
+
walkAndCollect(child, childDepth, entries, childSuppressTextLeaves);
|
|
5378
5441
|
}
|
|
5379
5442
|
}
|
|
5380
5443
|
return;
|
|
@@ -5382,15 +5445,19 @@ function walkAndCollect(element, depth, entries) {
|
|
|
5382
5445
|
if (role && isBlindRegion(role))
|
|
5383
5446
|
return;
|
|
5384
5447
|
for (const child of Array.from(element.children)) {
|
|
5385
|
-
walkAndCollect(child, childDepth, entries);
|
|
5448
|
+
walkAndCollect(child, childDepth, entries, childSuppressTextLeaves);
|
|
5386
5449
|
}
|
|
5387
5450
|
}
|
|
5388
|
-
|
|
5451
|
+
var TRUNCATION_DROP_ORDER_BY_ROLE = { text: 0, row: 1 };
|
|
5452
|
+
function truncationDropOrder(entry) {
|
|
5453
|
+
return TRUNCATION_DROP_ORDER_BY_ROLE[entry.role] ?? 2;
|
|
5454
|
+
}
|
|
5455
|
+
function dropInformationalEntriesFirstUntilUnderLimit(entries) {
|
|
5389
5456
|
if (entries.length <= NODE_LIMIT)
|
|
5390
5457
|
return entries;
|
|
5391
5458
|
const indexedEntries = entries.map((entry, index2) => ({ entry, index: index2 }));
|
|
5392
|
-
const
|
|
5393
|
-
const indicesToDrop = new Set(
|
|
5459
|
+
const entriesMostDroppableFirst = indexedEntries.slice(1).sort((a, b) => truncationDropOrder(a.entry) - truncationDropOrder(b.entry) || a.entry.area - b.entry.area);
|
|
5460
|
+
const indicesToDrop = new Set(entriesMostDroppableFirst.slice(0, entries.length - NODE_LIMIT).map((indexed) => indexed.index));
|
|
5394
5461
|
const keptEntries = [];
|
|
5395
5462
|
for (let i = 0;i < entries.length; i++) {
|
|
5396
5463
|
if (!indicesToDrop.has(i))
|
|
@@ -5415,7 +5482,7 @@ function buildAccessibilityTree() {
|
|
|
5415
5482
|
}
|
|
5416
5483
|
}
|
|
5417
5484
|
const exceededNodeLimit = collectedEntries.length > NODE_LIMIT;
|
|
5418
|
-
const finalEntries = exceededNodeLimit ?
|
|
5485
|
+
const finalEntries = exceededNodeLimit ? dropInformationalEntriesFirstUntilUnderLimit(collectedEntries) : collectedEntries;
|
|
5419
5486
|
const treeLines = finalEntries.map(formatNodeAsLine);
|
|
5420
5487
|
let pageContent = treeLines.join(`
|
|
5421
5488
|
`);
|
|
@@ -5790,21 +5857,46 @@ function paintCursorOverlay(ctx, transform, brand = DEFAULT_BRAND_PALETTE) {
|
|
|
5790
5857
|
}
|
|
5791
5858
|
|
|
5792
5859
|
// src/capture/snapdom.ts
|
|
5860
|
+
var UNLOADABLE_IMAGE_PLACEHOLDER_FILL = "#e2e8f0";
|
|
5861
|
+
function placeholderForUnloadableImage({
|
|
5862
|
+
width = 100,
|
|
5863
|
+
height = 100
|
|
5864
|
+
}) {
|
|
5865
|
+
const placeholderSvg = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}"><rect width="100%" height="100%" fill="${UNLOADABLE_IMAGE_PLACEHOLDER_FILL}"/></svg>`;
|
|
5866
|
+
return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(placeholderSvg)}`;
|
|
5867
|
+
}
|
|
5793
5868
|
var cachedSnapdomModule = null;
|
|
5794
5869
|
function loadSnapdom() {
|
|
5795
|
-
if (!cachedSnapdomModule)
|
|
5870
|
+
if (!cachedSnapdomModule) {
|
|
5796
5871
|
cachedSnapdomModule = import("@zumer/snapdom");
|
|
5872
|
+
}
|
|
5797
5873
|
return cachedSnapdomModule;
|
|
5798
5874
|
}
|
|
5875
|
+
function preCacheSnapshotResources() {
|
|
5876
|
+
loadSnapdom().then(({ preCache }) => preCache(document, { embedFonts: true })).catch(() => {
|
|
5877
|
+
return;
|
|
5878
|
+
});
|
|
5879
|
+
}
|
|
5799
5880
|
async function snapToCanvas(element, options = {}) {
|
|
5800
5881
|
const snapdomModule = await loadSnapdom();
|
|
5801
|
-
|
|
5882
|
+
const optionsWithEngineDefaults = {
|
|
5883
|
+
embedFonts: true,
|
|
5884
|
+
fallbackURL: placeholderForUnloadableImage,
|
|
5885
|
+
...options,
|
|
5886
|
+
snap: snapdomModule.snapdom
|
|
5887
|
+
};
|
|
5888
|
+
return snapdomModule.snapdom.toCanvas(element, optionsWithEngineDefaults);
|
|
5802
5889
|
}
|
|
5803
5890
|
|
|
5804
5891
|
// src/components/DomCapture.tsx
|
|
5805
5892
|
var SNAPSHOT_INTERVAL_MS = 3000;
|
|
5806
5893
|
var A11Y_PUBLISH_INTERVAL_MS = 2000;
|
|
5807
5894
|
var FIRST_SNAPSHOT_DELAY_MS = 400;
|
|
5895
|
+
var RASTERIZE_TIMEOUT_MS = 1e4;
|
|
5896
|
+
var FULL_QUALITY_TIMEOUTS_BEFORE_COOLDOWN = 1;
|
|
5897
|
+
var FAST_CAPTURES_BEFORE_FULL_QUALITY_RETRY = 10;
|
|
5898
|
+
var RASTERIZE_TIMED_OUT = Symbol("rasterize-timed-out");
|
|
5899
|
+
var SCROLL_SETTLE_MS = 300;
|
|
5808
5900
|
var CAPTURE_PRESET = ScreenSharePresets2.h1080fps30;
|
|
5809
5901
|
var CAPTURE_FPS = CAPTURE_PRESET.encoding.maxFramerate ?? 30;
|
|
5810
5902
|
var CAPTURE_BITRATE = 4000000;
|
|
@@ -5812,15 +5904,20 @@ var DOM_SNAPSHOT_GZIP_THRESHOLD_BYTES = 14000;
|
|
|
5812
5904
|
var MAX_CANVAS_DPR = 1.5;
|
|
5813
5905
|
var CONSECUTIVE_FAILURES_BEFORE_REPORT = 3;
|
|
5814
5906
|
var textEncoder4 = new TextEncoder;
|
|
5907
|
+
var SNAPSHOT_EXCLUDE_SELECTORS = [`#${WIDGET_ROOT_ID}`, `[${PRIVATE_ATTR}]`];
|
|
5908
|
+
function isCapturableIframe(element) {
|
|
5909
|
+
return isSameOriginIframe(element) && !isSensitiveIframe(element);
|
|
5910
|
+
}
|
|
5815
5911
|
function shouldIncludeInSnapshot(element) {
|
|
5816
|
-
if (
|
|
5817
|
-
return true;
|
|
5818
|
-
if (element.id === WIDGET_ROOT_ID)
|
|
5819
|
-
return false;
|
|
5820
|
-
if (element.hasAttribute?.(PRIVATE_ATTR))
|
|
5912
|
+
if (element instanceof HTMLIFrameElement && !isCapturableIframe(element))
|
|
5821
5913
|
return false;
|
|
5822
5914
|
return true;
|
|
5823
5915
|
}
|
|
5916
|
+
function shouldIncludeInFirstFrame(element) {
|
|
5917
|
+
if (element.tagName === "IMG")
|
|
5918
|
+
return false;
|
|
5919
|
+
return shouldIncludeInSnapshot(element);
|
|
5920
|
+
}
|
|
5824
5921
|
function createPublishingCanvas() {
|
|
5825
5922
|
const dprBoost = Math.min(window.devicePixelRatio || 1, MAX_CANVAS_DPR);
|
|
5826
5923
|
const canvas = document.createElement("canvas");
|
|
@@ -5841,22 +5938,23 @@ function getCanvasCaptureStream(canvas, fps) {
|
|
|
5841
5938
|
}
|
|
5842
5939
|
return captureStreamFn.call(canvas, fps);
|
|
5843
5940
|
}
|
|
5844
|
-
async function rasterizeViewportToPageLayer(width, height) {
|
|
5845
|
-
const
|
|
5941
|
+
async function rasterizeViewportToPageLayer(width, height, { skipCrossOriginImageSettling, includeImages }) {
|
|
5942
|
+
const requestedDpr = Math.min(window.devicePixelRatio || 1, MAX_CANVAS_DPR);
|
|
5943
|
+
const viewportWidthAtCaptureStart = window.innerWidth;
|
|
5846
5944
|
const snapshotCanvas = await snapToCanvas(document.documentElement, {
|
|
5847
|
-
|
|
5848
|
-
|
|
5945
|
+
exclude: SNAPSHOT_EXCLUDE_SELECTORS,
|
|
5946
|
+
excludeMode: "remove",
|
|
5947
|
+
filter: includeImages ? shouldIncludeInSnapshot : shouldIncludeInFirstFrame,
|
|
5948
|
+
filterMode: "hide",
|
|
5849
5949
|
backgroundColor: "#ffffff",
|
|
5850
|
-
fast:
|
|
5851
|
-
dpr
|
|
5950
|
+
fast: skipCrossOriginImageSettling,
|
|
5951
|
+
dpr: requestedDpr,
|
|
5952
|
+
clip: "viewport"
|
|
5852
5953
|
});
|
|
5853
|
-
const
|
|
5854
|
-
const
|
|
5855
|
-
const
|
|
5856
|
-
const
|
|
5857
|
-
const fitScale = Math.min(width / sourceWidth, height / sourceHeight);
|
|
5858
|
-
const destWidth = sourceWidth * fitScale;
|
|
5859
|
-
const destHeight = sourceHeight * fitScale;
|
|
5954
|
+
const canvasPixelsPerCssPixel = viewportWidthAtCaptureStart > 0 ? snapshotCanvas.width / viewportWidthAtCaptureStart : requestedDpr;
|
|
5955
|
+
const fitScale = Math.min(width / snapshotCanvas.width, height / snapshotCanvas.height);
|
|
5956
|
+
const destWidth = snapshotCanvas.width * fitScale;
|
|
5957
|
+
const destHeight = snapshotCanvas.height * fitScale;
|
|
5860
5958
|
const destX = (width - destWidth) / 2;
|
|
5861
5959
|
const destY = (height - destHeight) / 2;
|
|
5862
5960
|
const layer = document.createElement("canvas");
|
|
@@ -5867,10 +5965,14 @@ async function rasterizeViewportToPageLayer(width, height) {
|
|
|
5867
5965
|
throw new Error("Failed to get 2D context for page layer");
|
|
5868
5966
|
layerCtx.fillStyle = "#ffffff";
|
|
5869
5967
|
layerCtx.fillRect(0, 0, width, height);
|
|
5870
|
-
layerCtx.drawImage(snapshotCanvas,
|
|
5968
|
+
layerCtx.drawImage(snapshotCanvas, destX, destY, destWidth, destHeight);
|
|
5871
5969
|
return {
|
|
5872
5970
|
canvas: layer,
|
|
5873
|
-
viewportToCanvas: {
|
|
5971
|
+
viewportToCanvas: {
|
|
5972
|
+
scale: canvasPixelsPerCssPixel * fitScale,
|
|
5973
|
+
offsetX: destX,
|
|
5974
|
+
offsetY: destY
|
|
5975
|
+
}
|
|
5874
5976
|
};
|
|
5875
5977
|
}
|
|
5876
5978
|
function compositePageAndCursorOverlay(ctx, canvas, cachedPage, brand) {
|
|
@@ -5894,6 +5996,12 @@ async function gzipIfBeneficial(snapshotBytes) {
|
|
|
5894
5996
|
return { bytes: snapshotBytes, compressionFlag: 0 };
|
|
5895
5997
|
}
|
|
5896
5998
|
}
|
|
5999
|
+
function frameWithCompressionFlag(compressionFlag, payload) {
|
|
6000
|
+
const frame = new Uint8Array(payload.byteLength + 1);
|
|
6001
|
+
frame[0] = compressionFlag;
|
|
6002
|
+
frame.set(payload, 1);
|
|
6003
|
+
return frame;
|
|
6004
|
+
}
|
|
5897
6005
|
async function buildDomSnapshotFrame() {
|
|
5898
6006
|
const a11yTree = buildAccessibilityTree();
|
|
5899
6007
|
const snapshotJson = JSON.stringify({
|
|
@@ -5906,14 +6014,12 @@ async function buildDomSnapshotFrame() {
|
|
|
5906
6014
|
});
|
|
5907
6015
|
const snapshotBytes = textEncoder4.encode(snapshotJson);
|
|
5908
6016
|
const { bytes, compressionFlag } = await gzipIfBeneficial(snapshotBytes);
|
|
5909
|
-
|
|
5910
|
-
frame[0] = compressionFlag;
|
|
5911
|
-
frame.set(bytes, 1);
|
|
5912
|
-
return frame;
|
|
6017
|
+
return frameWithCompressionFlag(compressionFlag, bytes);
|
|
5913
6018
|
}
|
|
5914
6019
|
function reportCaptureError(localParticipant) {
|
|
5915
6020
|
try {
|
|
5916
|
-
|
|
6021
|
+
const payload = textEncoder4.encode(JSON.stringify({ type: "capture_error" }));
|
|
6022
|
+
localParticipant.publishData(frameWithCompressionFlag(0, payload), {
|
|
5917
6023
|
reliable: true,
|
|
5918
6024
|
topic: DOM_SNAPSHOT_TOPIC
|
|
5919
6025
|
}).catch(() => {
|
|
@@ -5956,12 +6062,18 @@ function DomCapture({ pushOrTapMicMode = false }) {
|
|
|
5956
6062
|
return;
|
|
5957
6063
|
videoTrack.contentHint = "text";
|
|
5958
6064
|
didStartRef.current = true;
|
|
6065
|
+
preCacheSnapshotResources();
|
|
5959
6066
|
let cancelled = false;
|
|
5960
6067
|
let snapshotInFlight = false;
|
|
5961
6068
|
let a11yPublishInFlight = false;
|
|
5962
6069
|
let a11yPublishPending = false;
|
|
5963
6070
|
let consecutiveCaptureFailures = 0;
|
|
5964
6071
|
let cachedPage = null;
|
|
6072
|
+
let rasterizeSequence = 0;
|
|
6073
|
+
let lastCommittedSequence = 0;
|
|
6074
|
+
let firstFrameCommitted = false;
|
|
6075
|
+
let capturesUntilFullQualityRetry = 0;
|
|
6076
|
+
let consecutiveFullQualityTimeouts = 0;
|
|
5965
6077
|
if (!pushOrTapMicMode && !localParticipant.isMicrophoneEnabled) {
|
|
5966
6078
|
localParticipant.setMicrophoneEnabled(true).catch((error) => console.error("Failed to enable microphone:", error));
|
|
5967
6079
|
}
|
|
@@ -5977,16 +6089,61 @@ function DomCapture({ pushOrTapMicMode = false }) {
|
|
|
5977
6089
|
for (const track of canvasStream.getTracks())
|
|
5978
6090
|
track.stop();
|
|
5979
6091
|
});
|
|
5980
|
-
const
|
|
5981
|
-
if (cancelled ||
|
|
6092
|
+
const commitPageLayerIfNewest = (sequence, page) => {
|
|
6093
|
+
if (cancelled || pausedRef.current || sequence <= lastCommittedSequence)
|
|
6094
|
+
return false;
|
|
6095
|
+
lastCommittedSequence = sequence;
|
|
6096
|
+
cachedPage = page;
|
|
6097
|
+
compositePageAndCursorOverlay(ctx, canvas, page, brandRef.current);
|
|
6098
|
+
firstFrameCommitted = true;
|
|
6099
|
+
return true;
|
|
6100
|
+
};
|
|
6101
|
+
const rasterizeAndCommitWaitingOutTimeout = async (options) => {
|
|
6102
|
+
const sequence = ++rasterizeSequence;
|
|
6103
|
+
const captureInProgress = rasterizeViewportToPageLayer(canvas.width, canvas.height, options);
|
|
6104
|
+
const captureOrTimeout = await Promise.race([
|
|
6105
|
+
captureInProgress,
|
|
6106
|
+
new Promise((resolve) => setTimeout(() => resolve(RASTERIZE_TIMED_OUT), RASTERIZE_TIMEOUT_MS))
|
|
6107
|
+
]);
|
|
6108
|
+
if (captureOrTimeout === RASTERIZE_TIMED_OUT) {
|
|
6109
|
+
captureInProgress.then((lateCapture) => commitPageLayerIfNewest(sequence, lateCapture)).catch(() => {
|
|
6110
|
+
return;
|
|
6111
|
+
});
|
|
6112
|
+
return { timedOut: true };
|
|
6113
|
+
}
|
|
6114
|
+
commitPageLayerIfNewest(sequence, captureOrTimeout);
|
|
6115
|
+
return { timedOut: false };
|
|
6116
|
+
};
|
|
6117
|
+
let followUpRefreshQueued = false;
|
|
6118
|
+
const refreshPageAndComposite = async ({ queueWhenBusy = false } = {}) => {
|
|
6119
|
+
if (cancelled || snapshotInFlight || pausedRef.current) {
|
|
6120
|
+
if (snapshotInFlight && !cancelled && queueWhenBusy)
|
|
6121
|
+
followUpRefreshQueued = true;
|
|
5982
6122
|
return;
|
|
6123
|
+
}
|
|
5983
6124
|
snapshotInFlight = true;
|
|
5984
6125
|
try {
|
|
5985
|
-
|
|
5986
|
-
|
|
5987
|
-
|
|
5988
|
-
|
|
6126
|
+
const isImagelessFirstFrame = !firstFrameCommitted;
|
|
6127
|
+
const useFullQuality = firstFrameCommitted && capturesUntilFullQualityRetry === 0;
|
|
6128
|
+
const { timedOut } = await rasterizeAndCommitWaitingOutTimeout({
|
|
6129
|
+
skipCrossOriginImageSettling: !useFullQuality,
|
|
6130
|
+
includeImages: !isImagelessFirstFrame
|
|
6131
|
+
});
|
|
6132
|
+
if (isImagelessFirstFrame && firstFrameCommitted)
|
|
6133
|
+
followUpRefreshQueued = true;
|
|
5989
6134
|
consecutiveCaptureFailures = 0;
|
|
6135
|
+
if (useFullQuality) {
|
|
6136
|
+
if (timedOut) {
|
|
6137
|
+
consecutiveFullQualityTimeouts += 1;
|
|
6138
|
+
if (consecutiveFullQualityTimeouts >= FULL_QUALITY_TIMEOUTS_BEFORE_COOLDOWN) {
|
|
6139
|
+
capturesUntilFullQualityRetry = FAST_CAPTURES_BEFORE_FULL_QUALITY_RETRY;
|
|
6140
|
+
}
|
|
6141
|
+
} else {
|
|
6142
|
+
consecutiveFullQualityTimeouts = 0;
|
|
6143
|
+
}
|
|
6144
|
+
} else if (capturesUntilFullQualityRetry > 0) {
|
|
6145
|
+
capturesUntilFullQualityRetry -= 1;
|
|
6146
|
+
}
|
|
5990
6147
|
} catch {
|
|
5991
6148
|
if (cancelled)
|
|
5992
6149
|
return;
|
|
@@ -5996,6 +6153,10 @@ function DomCapture({ pushOrTapMicMode = false }) {
|
|
|
5996
6153
|
}
|
|
5997
6154
|
} finally {
|
|
5998
6155
|
snapshotInFlight = false;
|
|
6156
|
+
if (followUpRefreshQueued && !cancelled) {
|
|
6157
|
+
followUpRefreshQueued = false;
|
|
6158
|
+
refreshPageAndComposite();
|
|
6159
|
+
}
|
|
5999
6160
|
}
|
|
6000
6161
|
};
|
|
6001
6162
|
let overlayAnimationFrame = null;
|
|
@@ -6061,20 +6222,30 @@ function DomCapture({ pushOrTapMicMode = false }) {
|
|
|
6061
6222
|
});
|
|
6062
6223
|
const cleanupSnapshotRequest = onSnapshotRequest(() => {
|
|
6063
6224
|
tickA11yPublish();
|
|
6064
|
-
refreshPageAndComposite();
|
|
6225
|
+
refreshPageAndComposite({ queueWhenBusy: true });
|
|
6065
6226
|
});
|
|
6227
|
+
let scrollSettleTimer = null;
|
|
6228
|
+
const refreshOnceScrollSettles = () => {
|
|
6229
|
+
if (scrollSettleTimer)
|
|
6230
|
+
clearTimeout(scrollSettleTimer);
|
|
6231
|
+
scrollSettleTimer = setTimeout(() => {
|
|
6232
|
+
tickA11yPublish();
|
|
6233
|
+
refreshPageAndComposite({ queueWhenBusy: true });
|
|
6234
|
+
}, SCROLL_SETTLE_MS);
|
|
6235
|
+
};
|
|
6236
|
+
window.addEventListener("scroll", refreshOnceScrollSettles, { passive: true, capture: true });
|
|
6066
6237
|
let snapshotTimer = null;
|
|
6067
6238
|
const scheduleNextSnapshot = (delay) => {
|
|
6068
6239
|
if (cancelled)
|
|
6069
6240
|
return;
|
|
6070
|
-
snapshotTimer = setTimeout(
|
|
6071
|
-
|
|
6241
|
+
snapshotTimer = setTimeout(() => {
|
|
6242
|
+
refreshPageAndComposite();
|
|
6072
6243
|
scheduleNextSnapshot(SNAPSHOT_INTERVAL_MS);
|
|
6073
6244
|
}, delay);
|
|
6074
6245
|
};
|
|
6075
6246
|
scheduleNextSnapshot(FIRST_SNAPSHOT_DELAY_MS);
|
|
6076
6247
|
tickA11yPublish();
|
|
6077
|
-
const a11yPublishTimer = setInterval(tickA11yPublish, A11Y_PUBLISH_INTERVAL_MS);
|
|
6248
|
+
const a11yPublishTimer = setInterval(() => void tickA11yPublish(), A11Y_PUBLISH_INTERVAL_MS);
|
|
6078
6249
|
freezeCaptureRef.current = () => {
|
|
6079
6250
|
pausedRef.current = true;
|
|
6080
6251
|
drawPausedOverlay(canvas, ctx);
|
|
@@ -6091,6 +6262,9 @@ function DomCapture({ pushOrTapMicMode = false }) {
|
|
|
6091
6262
|
resumeCaptureRef.current = null;
|
|
6092
6263
|
if (snapshotTimer)
|
|
6093
6264
|
clearTimeout(snapshotTimer);
|
|
6265
|
+
if (scrollSettleTimer)
|
|
6266
|
+
clearTimeout(scrollSettleTimer);
|
|
6267
|
+
window.removeEventListener("scroll", refreshOnceScrollSettles, { capture: true });
|
|
6094
6268
|
clearInterval(a11yPublishTimer);
|
|
6095
6269
|
if (overlayAnimationFrame !== null)
|
|
6096
6270
|
cancelAnimationFrame(overlayAnimationFrame);
|