Add common.loading locale key and cancellable capture test overlay

Add missing common.loading i18n key to en/ru locales. Add close button
and ESC key support to the overlay spinner so users can cancel running
capture tests. Uses AbortController to abort the in-flight fetch request.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-18 17:20:09 +03:00
parent fb1086b309
commit c79b7367da
5 changed files with 58 additions and 3 deletions

View File

@@ -298,6 +298,7 @@ export async function runTemplateTest() {
const template = window.currentTestingTemplate;
showOverlaySpinner(t('templates.test.running'), captureDuration);
const signal = window._overlayAbortController?.signal;
try {
const response = await fetchWithAuth('/capture-templates/test', {
@@ -307,7 +308,8 @@ export async function runTemplateTest() {
engine_config: template.engine_config,
display_index: parseInt(displayIndex),
capture_duration: captureDuration
})
}),
signal
});
if (!response.ok) {
@@ -319,6 +321,7 @@ export async function runTemplateTest() {
localStorage.setItem('lastTestDisplayIndex', displayIndex);
displayTestResults(result);
} catch (error) {
if (error.name === 'AbortError') return;
console.error('Error running test:', error);
hideOverlaySpinner();
showToast(t('templates.test.error.failed'), 'error');
@@ -980,11 +983,13 @@ export async function runStreamTest() {
if (!_currentTestStreamId) return;
const captureDuration = parseFloat(document.getElementById('test-stream-duration').value);
showOverlaySpinner(t('streams.test.running'), captureDuration);
const signal = window._overlayAbortController?.signal;
try {
const response = await fetchWithAuth(`/picture-sources/${_currentTestStreamId}/test`, {
method: 'POST',
body: JSON.stringify({ capture_duration: captureDuration })
body: JSON.stringify({ capture_duration: captureDuration }),
signal
});
if (!response.ok) {
const error = await response.json();
@@ -995,6 +1000,7 @@ export async function runStreamTest() {
const fullImageSrc = result.full_capture.full_image || result.full_capture.image;
openLightbox(fullImageSrc, buildTestStatsHtml(result));
} catch (error) {
if (error.name === 'AbortError') return;
console.error('Error running stream test:', error);
hideOverlaySpinner();
showToast(t('streams.test.error.failed') + ': ' + error.message, 'error');
@@ -1057,11 +1063,13 @@ export async function runPPTemplateTest() {
const captureDuration = parseFloat(document.getElementById('test-pp-duration').value);
showOverlaySpinner(t('postprocessing.test.running'), captureDuration);
const signal = window._overlayAbortController?.signal;
try {
const response = await fetchWithAuth(`/postprocessing-templates/${_currentTestPPTemplateId}/test`, {
method: 'POST',
body: JSON.stringify({ source_stream_id: sourceStreamId, capture_duration: captureDuration })
body: JSON.stringify({ source_stream_id: sourceStreamId, capture_duration: captureDuration }),
signal
});
if (!response.ok) {
const error = await response.json();
@@ -1072,6 +1080,7 @@ export async function runPPTemplateTest() {
const fullImageSrc = result.full_capture.full_image || result.full_capture.image;
openLightbox(fullImageSrc, buildTestStatsHtml(result));
} catch (error) {
if (error.name === 'AbortError') return;
console.error('Error running PP template test:', error);
hideOverlaySpinner();
showToast(t('postprocessing.test.error.failed') + ': ' + error.message, 'error');