Files
odysseus/static/js/editor/ai-operation.js
T
pewdiepie-archdaemon 2e8413a54a Preserve preview harness, editor, email and task improvements
Snapshot current maintainer-preview application changes and regression fixtures for integration into lab. Excludes local runtime data, evaluation outputs and source backups. Focused Python regression selection: 140 passed; full suite not certified.
2026-10-01 01:34:26 +00:00

46 lines
1.5 KiB
JavaScript

// Capture repeat clicks before tool handlers can start another request.
export function beginAIOperation(button, onCancel) {
const controller = new AbortController();
const title = button.title;
button.disabled = false;
button.title = 'Cancel running action';
button.setAttribute('aria-busy', 'true');
const cancel = event => {
event.preventDefault();
event.stopImmediatePropagation();
if (!controller.signal.aborted) {
controller.abort();
onCancel?.();
}
};
button.addEventListener('click', cancel, true);
return {
signal: controller.signal,
finish() {
button.removeEventListener('click', cancel, true);
button.title = title;
button.removeAttribute('aria-busy');
},
};
}
export function decodeAIImage(base64, signal) {
return new Promise((resolve, reject) => {
const image = new Image();
const cleanup = () => {
image.onload = image.onerror = null;
signal.removeEventListener('abort', abort);
};
const abort = () => {
cleanup();
image.src = '';
reject(new DOMException('Cancelled', 'AbortError'));
};
if (signal.aborted) { abort(); return; }
signal.addEventListener('abort', abort, { once: true });
image.onload = () => { cleanup(); resolve(image); };
image.onerror = () => { cleanup(); reject(new Error('Failed to decode result image')); };
image.src = base64.startsWith('data:') ? base64 : 'data:image/png;base64,' + base64;
});
}