fix: keep export dropdown open on failure, fix cancel during setup, fix Windows paths, translate i18n

- Export dropdown now stays open on GIF/MP4 failure and top-level catch so
  the exportError UI remains visible (previously dismissed by finally block)
- handleCancelExport always resets UI state even before exporter is constructed,
  so Cancel works during the async setup phase
- fromFileUrl() now converts forward slashes to backslashes for Windows drive
  paths (both primary and fallback parsing paths)
- Translated customFonts and color keys in es/ko/nl/zh-CN locales
This commit is contained in:
webadderall
2026-04-20 22:07:24 +10:00
parent 25426fe702
commit ce2f7147c4
7 changed files with 24 additions and 19 deletions
@@ -254,6 +254,7 @@ export async function runEditorExport({
window.close();
return;
}
keepExportDialogOpen = true;
}
} else {
const quality = settings.quality ?? config.exportQuality;
@@ -478,6 +479,7 @@ export async function runEditorExport({
window.close();
return;
}
keepExportDialogOpen = true;
}
}
@@ -501,6 +503,9 @@ export async function runEditorExport({
}
setExportError(errorMessage);
toast.error(`Export failed: ${summarizeErrorMessage(errorMessage)}`);
if (!smokeExportConfig.enabled) {
keepExportDialogOpen = true;
}
} finally {
if (restoreTime !== null) {
if (wasPlaying) {
@@ -191,16 +191,14 @@ export function useEditorExport({
}, [getRenderConfig, videoPlaybackRef, handleExport]);
const handleCancelExport = useCallback(() => {
if (exporterRef.current) {
exporterRef.current.cancel();
toast.info("Export canceled");
clearPendingExportSave();
setShowExportDropdown(false);
setIsExporting(false);
setExportProgress(null);
setExportError(null);
setExportedFilePath(undefined);
}
exporterRef.current?.cancel();
toast.info("Export canceled");
clearPendingExportSave();
setShowExportDropdown(false);
setIsExporting(false);
setExportProgress(null);
setExportError(null);
setExportedFilePath(undefined);
}, [clearPendingExportSave]);
const handleExportDropdownClose = useCallback(() => {
@@ -51,7 +51,7 @@ export function fromFileUrl(fileUrl: string): string {
}
if (/^\/[A-Za-z]:/.test(pathname)) {
return pathname.slice(1);
return pathname.slice(1).replace(/\//g, "\\");
}
return pathname;
@@ -63,7 +63,9 @@ export function fromFileUrl(fileUrl: string): string {
} catch {
// Keep raw best-effort path if percent decoding fails.
}
return fallbackPath.replace(/^\/([a-zA-Z]:)/, "$1");
const nativePath = fallbackPath.replace(/^\/([a-zA-Z]:)/, "$1");
// Convert forward slashes to backslashes only for Windows drive paths
return /^[a-zA-Z]:/.test(nativePath) ? nativePath.replace(/\//g, "\\") : nativePath;
}
}
+1 -1
View File
@@ -43,7 +43,7 @@
"blurStrength": "Fuerza del Desenfoque: {{strength}}",
"solidColor": "Color Sólido (Censura)",
"borderRadius": "Radio del Borde",
"customFonts": "Custom Fonts",
"customFonts": "Fuentes Personalizadas",
"color": "Color"
},
+2 -2
View File
@@ -44,8 +44,8 @@
"blurStrength": "블러 강도: {{strength}}",
"solidColor": "단색 (검열)",
"borderRadius": "테두리 반경",
"customFonts": "Custom Fonts",
"color": "Color"
"customFonts": "커스텀 글꼴",
"color": "색상"
},
"fontStyles": {
+2 -2
View File
@@ -44,8 +44,8 @@
"blurStrength": "Vervagingssterkte: {{strength}}",
"solidColor": "Effen Kleur (Censuur)",
"borderRadius": "Hoekradius",
"customFonts": "Custom Fonts",
"color": "Color"
"customFonts": "Aangepaste Lettertypen",
"color": "Kleur"
},
"fontStyles": {
+2 -2
View File
@@ -43,8 +43,8 @@
"blurStrength": "模糊强度: {{strength}}",
"solidColor": "纯色 (审查)",
"borderRadius": "边框半径",
"customFonts": "Custom Fonts",
"color": "Color"
"customFonts": "自定义字体",
"color": "颜色"
},
"fontStyles": {