fix: throttle workflow preview preloading
This commit is contained in:
parent
edc24cb956
commit
4e49e5e5b5
@ -111,12 +111,12 @@ const VIRTUAL_OPTION_GRID_GAP = 16;
|
|||||||
const VIRTUAL_OPTION_GRID_MAX_HEIGHT = 640;
|
const VIRTUAL_OPTION_GRID_MAX_HEIGHT = 640;
|
||||||
const VIRTUAL_OPTION_GRID_MIN_CARD_HEIGHT = 122;
|
const VIRTUAL_OPTION_GRID_MIN_CARD_HEIGHT = 122;
|
||||||
const VIRTUAL_OPTION_GRID_THRESHOLD = 12;
|
const VIRTUAL_OPTION_GRID_THRESHOLD = 12;
|
||||||
const WORKFLOW_OPTION_PREVIEW_WIDTH = 512;
|
const WORKFLOW_OPTION_PREVIEW_WIDTH = 360;
|
||||||
const WORKFLOW_OPTION_PREVIEW_QUALITY = 62;
|
const WORKFLOW_OPTION_PREVIEW_QUALITY = 58;
|
||||||
const WORKFLOW_OPTION_PREVIEW_EAGER_COUNT = 10;
|
const WORKFLOW_OPTION_PREVIEW_EAGER_COUNT = 4;
|
||||||
const WORKFLOW_OPTION_PREVIEW_PREFETCH_COUNT = 12;
|
const WORKFLOW_OPTION_NEXT_PREVIEW_PREFETCH_COUNT = 6;
|
||||||
const WORKFLOW_OPTION_NEXT_PREVIEW_PREFETCH_COUNT = 24;
|
const WORKFLOW_OPTION_PREFETCH_CACHE_LIMIT = 48;
|
||||||
const WORKFLOW_OPTION_PREFETCH_CACHE_LIMIT = 320;
|
const WORKFLOW_OPTION_PREFETCH_BATCH_SIZE = 2;
|
||||||
|
|
||||||
function isLikelyStoredWorkflowPreview(url: string, sourceUrl?: string | null) {
|
function isLikelyStoredWorkflowPreview(url: string, sourceUrl?: string | null) {
|
||||||
const source = String(sourceUrl || "").trim();
|
const source = String(sourceUrl || "").trim();
|
||||||
@ -182,10 +182,81 @@ function trimWorkflowPreviewImageCache(
|
|||||||
while (cache.size > limit) {
|
while (cache.size > limit) {
|
||||||
const firstKey = cache.keys().next().value;
|
const firstKey = cache.keys().next().value;
|
||||||
if (!firstKey) return;
|
if (!firstKey) return;
|
||||||
|
const image = cache.get(firstKey);
|
||||||
|
if (image) {
|
||||||
|
image.src = "";
|
||||||
|
}
|
||||||
cache.delete(firstKey);
|
cache.delete(firstKey);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function shouldSkipWorkflowPreviewPrefetch() {
|
||||||
|
if (typeof document !== "undefined" && document.visibilityState === "hidden") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const connection = (typeof navigator !== "undefined"
|
||||||
|
? (navigator as Navigator & {
|
||||||
|
connection?: { saveData?: boolean };
|
||||||
|
}).connection
|
||||||
|
: null);
|
||||||
|
return Boolean(connection?.saveData);
|
||||||
|
}
|
||||||
|
|
||||||
|
function preloadWorkflowOptionPreviewImages(params: {
|
||||||
|
urls: string[];
|
||||||
|
cache: Map<string, HTMLImageElement>;
|
||||||
|
markPrefetched: Set<string>;
|
||||||
|
}) {
|
||||||
|
if (typeof window === "undefined" || params.urls.length === 0) {
|
||||||
|
return () => {};
|
||||||
|
}
|
||||||
|
|
||||||
|
let cancelled = false;
|
||||||
|
let cleanupIdleTask: (() => void) | null = null;
|
||||||
|
const urls = params.urls.slice();
|
||||||
|
|
||||||
|
const preloadNextBatch = () => {
|
||||||
|
if (cancelled || shouldSkipWorkflowPreviewPrefetch()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const batch = urls.splice(0, WORKFLOW_OPTION_PREFETCH_BATCH_SIZE);
|
||||||
|
for (const src of batch) {
|
||||||
|
if (cancelled || params.cache.has(src)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const image = new Image();
|
||||||
|
image.decoding = "async";
|
||||||
|
(
|
||||||
|
image as HTMLImageElement & {
|
||||||
|
fetchPriority?: "high" | "low" | "auto";
|
||||||
|
}
|
||||||
|
).fetchPriority = "low";
|
||||||
|
image.onerror = () => {
|
||||||
|
params.cache.delete(src);
|
||||||
|
params.markPrefetched.delete(src);
|
||||||
|
};
|
||||||
|
image.src = src;
|
||||||
|
params.cache.set(src, image);
|
||||||
|
}
|
||||||
|
|
||||||
|
trimWorkflowPreviewImageCache(params.cache);
|
||||||
|
|
||||||
|
if (urls.length > 0) {
|
||||||
|
cleanupIdleTask = scheduleWorkflowIdleTask(preloadNextBatch, 900);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
cleanupIdleTask = scheduleWorkflowIdleTask(preloadNextBatch, 700);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
cancelled = true;
|
||||||
|
cleanupIdleTask?.();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
interface WorkflowPanelDerivedState {
|
interface WorkflowPanelDerivedState {
|
||||||
progress: ReturnType<typeof getAgentWorkflowProgress>;
|
progress: ReturnType<typeof getAgentWorkflowProgress>;
|
||||||
}
|
}
|
||||||
@ -1177,12 +1248,6 @@ function AgentWorkflowPanelDarkV2Component({
|
|||||||
const urls = new Set<string>();
|
const urls = new Set<string>();
|
||||||
|
|
||||||
if (embedded) {
|
if (embedded) {
|
||||||
appendWorkflowOptionPreviewUrls(
|
|
||||||
urls,
|
|
||||||
activeEmbeddedOptionLevel?.options,
|
|
||||||
WORKFLOW_OPTION_PREVIEW_PREFETCH_COUNT
|
|
||||||
);
|
|
||||||
|
|
||||||
const currentSelectedOption =
|
const currentSelectedOption =
|
||||||
activeEmbeddedOptionLevel?.selectedOption || null;
|
activeEmbeddedOptionLevel?.selectedOption || null;
|
||||||
appendWorkflowOptionPreviewUrls(
|
appendWorkflowOptionPreviewUrls(
|
||||||
@ -1227,11 +1292,6 @@ function AgentWorkflowPanelDarkV2Component({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
appendWorkflowOptionPreviewUrls(
|
|
||||||
urls,
|
|
||||||
flattenedResolvedSteps[0]?.step.options,
|
|
||||||
WORKFLOW_OPTION_PREVIEW_PREFETCH_COUNT
|
|
||||||
);
|
|
||||||
appendWorkflowOptionPreviewUrls(
|
appendWorkflowOptionPreviewUrls(
|
||||||
urls,
|
urls,
|
||||||
flattenedResolvedSteps[1]?.step.options,
|
flattenedResolvedSteps[1]?.step.options,
|
||||||
@ -1361,24 +1421,23 @@ function AgentWorkflowPanelDarkV2Component({
|
|||||||
workflowPreviewPrefetchedUrlsRef.current.add(src);
|
workflowPreviewPrefetchedUrlsRef.current.add(src);
|
||||||
});
|
});
|
||||||
|
|
||||||
scheduleWorkflowIdleTask(() => {
|
return preloadWorkflowOptionPreviewImages({
|
||||||
urlsToPrefetch.forEach((src, index) => {
|
urls: urlsToPrefetch,
|
||||||
const image = new Image();
|
cache: workflowPreviewImageCacheRef.current,
|
||||||
image.decoding = "async";
|
markPrefetched: workflowPreviewPrefetchedUrlsRef.current,
|
||||||
(
|
});
|
||||||
image as HTMLImageElement & {
|
|
||||||
fetchPriority?: "high" | "low" | "auto";
|
|
||||||
}
|
|
||||||
).fetchPriority =
|
|
||||||
index < WORKFLOW_OPTION_PREVIEW_EAGER_COUNT ? "high" : "low";
|
|
||||||
image.src = src;
|
|
||||||
workflowPreviewImageCacheRef.current.set(src, image);
|
|
||||||
});
|
|
||||||
|
|
||||||
trimWorkflowPreviewImageCache(workflowPreviewImageCacheRef.current);
|
|
||||||
}, 80);
|
|
||||||
}, [workflowOptionPreviewPrefetchUrls]);
|
}, [workflowOptionPreviewPrefetchUrls]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
workflowPreviewImageCacheRef.current.forEach((image) => {
|
||||||
|
image.src = "";
|
||||||
|
});
|
||||||
|
workflowPreviewImageCacheRef.current.clear();
|
||||||
|
workflowPreviewPrefetchedUrlsRef.current.clear();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!embedded || !activeEmbeddedStepEntry) {
|
if (!embedded || !activeEmbeddedStepEntry) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user