Files
MajoorWaldi-ComfyUI-Majoor-…/ui/features/viewer/floatingViewerLoader.ts
T

127 lines
4.7 KiB
TypeScript

import { ensureViewerMetadataAsset } from "./genInfo.js";
import { getAssetMetadata, getFileMetadataScoped } from "../../api/client.js";
import { MFV_MODES } from "./floatingViewerConstants.js";
import { revokeDetachedFloatingViewerPreviewBlobs } from "./floatingViewerMode.js";
const IMAGEOPS_LIVE_SOURCE = "imageops-live-preview";
function _isImageOpsLive(fileData: any) {
return String(fileData?._source || "") === IMAGEOPS_LIVE_SOURCE;
}
export function loadFloatingViewerMediaA(viewer: any, fileData: any, { autoMode = false }: { autoMode?: boolean } = {}): void {
const prev = viewer._mediaA || null;
const isLive = _isImageOpsLive(fileData);
// Live ImageOps frames re-emit every ~150ms. Resetting the user's
// pan/zoom on every frame would defeat the MFV's interactive zoom.
// Preserve it as long as the streamed node hasn't changed.
const sameNodeStream =
isLive &&
_isImageOpsLive(prev) &&
String(prev?._nodeId || "") === String(fileData?._nodeId || "");
viewer._mediaA = fileData || null;
revokeDetachedFloatingViewerPreviewBlobs(viewer, [prev]);
if (!sameNodeStream) {
viewer._resetMfvZoom();
}
if (autoMode && viewer._mode !== MFV_MODES.SIMPLE && viewer._mode !== MFV_MODES.GRAPH) {
viewer._mode = MFV_MODES.SIMPLE;
viewer._updateModeBtnUI();
}
viewer._refresh();
// ImageOps live previews are transient client-side canvas snapshots;
// there is no backend asset to fetch metadata for. Skip the API round
// trip entirely (also avoids the enrichment-vs-new-emission race).
if (viewer._mediaA && !isLive && typeof ensureViewerMetadataAsset === "function") {
const gen = ++viewer._refreshGen;
(async () => {
try {
const enriched = await ensureViewerMetadataAsset(viewer._mediaA, {
getAssetMetadata,
getFileMetadataScoped,
});
if (viewer._refreshGen !== gen) return;
if (enriched && typeof enriched === "object") {
viewer._mediaA = enriched;
viewer._refresh();
}
} catch (e: any) {
console.debug?.("[MFV] metadata enrich error", e);
}
})();
}
}
export function loadFloatingViewerMediaPair(viewer: any, a: any, b: any): void {
const previousMedia = [viewer._mediaA, viewer._mediaB];
viewer._mediaA = a || null;
viewer._mediaB = b || null;
revokeDetachedFloatingViewerPreviewBlobs(viewer, previousMedia);
viewer._resetMfvZoom();
if (viewer._mode === MFV_MODES.SIMPLE) {
viewer._mode = MFV_MODES.AB;
viewer._updateModeBtnUI();
}
const gen = ++viewer._refreshGen;
const hydrate = async (asset: any) => {
if (!asset) return asset;
try {
const enriched = await ensureViewerMetadataAsset(asset, {
getAssetMetadata,
getFileMetadataScoped,
});
return enriched || asset;
} catch {
return asset;
}
};
(async () => {
const [A, B] = await Promise.all([hydrate(viewer._mediaA), hydrate(viewer._mediaB)]);
if (viewer._refreshGen !== gen) return;
viewer._mediaA = A || null;
viewer._mediaB = B || null;
viewer._refresh();
})();
}
export function loadFloatingViewerMediaQuad(viewer: any, a: any, b: any, c: any, d: any): void {
const previousMedia = [viewer._mediaA, viewer._mediaB, viewer._mediaC, viewer._mediaD];
viewer._mediaA = a || null;
viewer._mediaB = b || null;
viewer._mediaC = c || null;
viewer._mediaD = d || null;
revokeDetachedFloatingViewerPreviewBlobs(viewer, previousMedia);
viewer._resetMfvZoom();
if (viewer._mode !== MFV_MODES.GRID) {
viewer._mode = MFV_MODES.GRID;
viewer._updateModeBtnUI();
}
const gen = ++viewer._refreshGen;
const hydrate = async (asset: any) => {
if (!asset) return asset;
try {
const enriched = await ensureViewerMetadataAsset(asset, {
getAssetMetadata,
getFileMetadataScoped,
});
return enriched || asset;
} catch {
return asset;
}
};
(async () => {
const [A, B, C, D] = await Promise.all([
hydrate(viewer._mediaA),
hydrate(viewer._mediaB),
hydrate(viewer._mediaC),
hydrate(viewer._mediaD),
]);
if (viewer._refreshGen !== gen) return;
viewer._mediaA = A || null;
viewer._mediaB = B || null;
viewer._mediaC = C || null;
viewer._mediaD = D || null;
viewer._refresh();
})();
}