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_MIN_CARD_HEIGHT = 122;
|
||||
const VIRTUAL_OPTION_GRID_THRESHOLD = 12;
|
||||
const WORKFLOW_OPTION_PREVIEW_WIDTH = 512;
|
||||
const WORKFLOW_OPTION_PREVIEW_QUALITY = 62;
|
||||
const WORKFLOW_OPTION_PREVIEW_EAGER_COUNT = 10;
|
||||
const WORKFLOW_OPTION_PREVIEW_PREFETCH_COUNT = 12;
|
||||
const WORKFLOW_OPTION_NEXT_PREVIEW_PREFETCH_COUNT = 24;
|
||||
const WORKFLOW_OPTION_PREFETCH_CACHE_LIMIT = 320;
|
||||
const WORKFLOW_OPTION_PREVIEW_WIDTH = 360;
|
||||
const WORKFLOW_OPTION_PREVIEW_QUALITY = 58;
|
||||
const WORKFLOW_OPTION_PREVIEW_EAGER_COUNT = 4;
|
||||
const WORKFLOW_OPTION_NEXT_PREVIEW_PREFETCH_COUNT = 6;
|
||||
const WORKFLOW_OPTION_PREFETCH_CACHE_LIMIT = 48;
|
||||
const WORKFLOW_OPTION_PREFETCH_BATCH_SIZE = 2;
|
||||
|
||||
function isLikelyStoredWorkflowPreview(url: string, sourceUrl?: string | null) {
|
||||
const source = String(sourceUrl || "").trim();
|
||||
@ -182,10 +182,81 @@ function trimWorkflowPreviewImageCache(
|
||||
while (cache.size > limit) {
|
||||
const firstKey = cache.keys().next().value;
|
||||
if (!firstKey) return;
|
||||
const image = cache.get(firstKey);
|
||||
if (image) {
|
||||
image.src = "";
|
||||
}
|
||||
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 {
|
||||
progress: ReturnType<typeof getAgentWorkflowProgress>;
|
||||
}
|
||||
@ -1177,12 +1248,6 @@ function AgentWorkflowPanelDarkV2Component({
|
||||
const urls = new Set<string>();
|
||||
|
||||
if (embedded) {
|
||||
appendWorkflowOptionPreviewUrls(
|
||||
urls,
|
||||
activeEmbeddedOptionLevel?.options,
|
||||
WORKFLOW_OPTION_PREVIEW_PREFETCH_COUNT
|
||||
);
|
||||
|
||||
const currentSelectedOption =
|
||||
activeEmbeddedOptionLevel?.selectedOption || null;
|
||||
appendWorkflowOptionPreviewUrls(
|
||||
@ -1227,11 +1292,6 @@ function AgentWorkflowPanelDarkV2Component({
|
||||
}
|
||||
}
|
||||
} else {
|
||||
appendWorkflowOptionPreviewUrls(
|
||||
urls,
|
||||
flattenedResolvedSteps[0]?.step.options,
|
||||
WORKFLOW_OPTION_PREVIEW_PREFETCH_COUNT
|
||||
);
|
||||
appendWorkflowOptionPreviewUrls(
|
||||
urls,
|
||||
flattenedResolvedSteps[1]?.step.options,
|
||||
@ -1361,24 +1421,23 @@ function AgentWorkflowPanelDarkV2Component({
|
||||
workflowPreviewPrefetchedUrlsRef.current.add(src);
|
||||
});
|
||||
|
||||
scheduleWorkflowIdleTask(() => {
|
||||
urlsToPrefetch.forEach((src, index) => {
|
||||
const image = new Image();
|
||||
image.decoding = "async";
|
||||
(
|
||||
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);
|
||||
return preloadWorkflowOptionPreviewImages({
|
||||
urls: urlsToPrefetch,
|
||||
cache: workflowPreviewImageCacheRef.current,
|
||||
markPrefetched: workflowPreviewPrefetchedUrlsRef.current,
|
||||
});
|
||||
}, [workflowOptionPreviewPrefetchUrls]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
workflowPreviewImageCacheRef.current.forEach((image) => {
|
||||
image.src = "";
|
||||
});
|
||||
workflowPreviewImageCacheRef.current.clear();
|
||||
workflowPreviewPrefetchedUrlsRef.current.clear();
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!embedded || !activeEmbeddedStepEntry) {
|
||||
return;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user