Files
odysseus/static/js/editor/history-budget.js
T

40 lines
1.4 KiB
JavaScript

/** Adaptive bounds for raw ImageData history snapshots. */
export const MAX_HISTORY_ENTRIES = 30;
export const MAX_HISTORY_BYTES = 192 * 1024 * 1024;
function imageDataBytes(imageData) {
return Number(imageData?.data?.byteLength || imageData?.data?.length || 0);
}
export function snapshotByteSize(snapshot) {
if (!snapshot) return 0;
if (Number.isFinite(snapshot._bytes)) return snapshot._bytes;
let bytes = imageDataBytes(snapshot.wand?.imageData);
bytes += imageDataBytes(snapshot.lastSelection?.imageData);
for (const selection of snapshot.savedSelections || []) bytes += imageDataBytes(selection.imageData);
for (const group of snapshot.layerGroups || []) {
for (const mask of group.masks || []) bytes += imageDataBytes(mask.imageData);
}
for (const layer of snapshot.layers || []) {
bytes += imageDataBytes(layer.imageData);
bytes += imageDataBytes(layer.placed?.sourceImageData);
for (const mask of layer.masks || []) bytes += imageDataBytes(mask.imageData);
}
return bytes;
}
export function trimHistoryStack(
stack,
maxEntries = MAX_HISTORY_ENTRIES,
maxBytes = MAX_HISTORY_BYTES,
) {
while (stack.length > maxEntries) stack.shift();
let bytes = stack.reduce((total, snapshot) => total + snapshotByteSize(snapshot), 0);
// Keep the newest state even when one snapshot alone exceeds the budget.
while (stack.length > 1 && bytes > maxBytes) {
bytes -= snapshotByteSize(stack.shift());
}
return bytes;
}