Fix #3169: Show confirmation toast after export/download (#3183)

* Fix #3169: Show confirmation toast after export/download

Adds a success toast ("Export started") after any export/download action
completes. The toast uses the existing Toast component with the same
pattern as commentSavedToast and templateSavedToast (2.2s auto-dismiss).

The toast fires from within fireShareExport on both sync and async
success paths, covering all export formats: PDF, PPTX, ZIP, HTML,
Markdown, image, JSX, and React HTML.

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>

* Gate export toast to file export formats only

The toast was previously wired inside fireShareExport for all callers,
which incorrectly showed "Export started" for template save and deploy
modal opens. Gate to pdf/pptx/zip/html/markdown only. Also fix comma
to semicolon in types.ts.

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>

---------

Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
This commit is contained in:
Stooby with two y's 2026-05-28 16:35:39 +04:00 committed by GitHub
parent b8cdf5f0ea
commit 9032fbb689
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 33 additions and 1 deletions

View file

@ -3729,15 +3729,17 @@ function HtmlViewer({
{ requestId },
);
};
const toastFormats = new Set(['pdf', 'pptx', 'zip', 'html', 'markdown']);
try {
const out = fn();
if (out && typeof (out as Promise<unknown>).then === 'function') {
(out as Promise<unknown>).then(
() => finish('success'),
() => { finish('success'); if (toastFormats.has(format)) setExportToast(t('fileViewer.exportStarted')); },
(err) => finish('failed', err instanceof Error ? err.name : 'UNKNOWN'),
);
} else {
finish('success');
if (toastFormats.has(format)) setExportToast(t('fileViewer.exportStarted'));
}
} catch (err) {
finish('failed', err instanceof Error ? err.name : 'UNKNOWN');
@ -4064,6 +4066,7 @@ function HtmlViewer({
const [commentSavedToast, setCommentSavedToast] = useState<string | null>(null);
const [templateSavedToast, setTemplateSavedToast] = useState<string | null>(null);
const [deploySavedToast, setDeploySavedToast] = useState<{ message: string; details: string } | null>(null);
const [exportToast, setExportToast] = useState<string | null>(null);
const [selectedSideCommentIds, setSelectedSideCommentIds] = useState<Set<string>>(() => new Set());
const [commentSidePanelCollapsed, setCommentSidePanelCollapsed] = useState(false);
const [strokePoints, setStrokePoints] = useState<StrokePoint[]>([]);
@ -6844,6 +6847,15 @@ function HtmlViewer({
}}
/>
) : null}
{exportToast ? (
<div className="comment-toast-anchor">
<Toast
message={exportToast}
ttlMs={2200}
onDismiss={() => setExportToast(null)}
/>
</div>
) : null}
{commentSavedToast ? (
<div className="comment-toast-anchor">
<Toast

View file

@ -1125,6 +1125,7 @@ export const ar: Dict = {
'fileViewer.exportImageFailed': 'فشل التقاط الصورة. يرجى المحاولة مرة أخرى أو استخدام أداة لقطة الشاشة في المتصفح.',
'fileViewer.exportJsx': 'تصدير كـ JSX',
'fileViewer.exportReactHtml': 'تصدير المعاينة كـ HTML',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': 'حفظ كقالب...',
'fileViewer.savingTemplate': 'جاري حفظ القالب...',
'fileViewer.savedTemplate': 'تم الحفظ باسم "{name}"',

View file

@ -1013,6 +1013,7 @@ export const de: Dict = {
'fileViewer.exportImageFailed': 'Bildaufnahme fehlgeschlagen. Bitte versuchen Sie es erneut oder verwenden Sie das Screenshot-Tool Ihres Browsers.',
'fileViewer.exportJsx': 'Als JSX exportieren',
'fileViewer.exportReactHtml': 'Vorschau als HTML exportieren',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': 'Als Template speichern…',
'fileViewer.savingTemplate': 'Template wird gespeichert…',
'fileViewer.savedTemplate': 'Als „{name}“ gespeichert',

View file

@ -1741,6 +1741,7 @@ export const en: Dict = {
'fileViewer.exportImageFailed': 'Image capture failed. Please try again or use your browser\'s screenshot tool.',
'fileViewer.exportJsx': 'Export as JSX',
'fileViewer.exportReactHtml': 'Export preview as HTML',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': 'Save as template…',
'fileViewer.savingTemplate': 'Saving template…',
'fileViewer.savedTemplate': 'Saved as "{name}"',

View file

@ -1014,6 +1014,7 @@ export const esES: Dict = {
'fileViewer.exportImageFailed': 'Error al capturar la imagen. Inténtalo de nuevo o usa la herramienta de captura de pantalla de tu navegador.',
'fileViewer.exportJsx': 'Exportar como JSX',
'fileViewer.exportReactHtml': 'Exportar vista previa como HTML',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': 'Guardar como plantilla…',
'fileViewer.savingTemplate': 'Guardando plantilla…',
'fileViewer.savedTemplate': 'Guardado como «{name}»',

View file

@ -1149,6 +1149,7 @@ export const fa: Dict = {
'fileViewer.exportImageFailed': 'گرفتن تصویر ناموفق بود. لطفاً دوباره تلاش کنید یا از ابزار اسکرین‌شات مرورگرتان استفاده کنید.',
'fileViewer.exportJsx': 'صادرکردن به JSX',
'fileViewer.exportReactHtml': 'صادرکردن پیش‌نمایش به HTML',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': 'ذخیره به عنوان قالب…',
'fileViewer.savingTemplate': 'در حال ذخیره قالب…',
'fileViewer.savedTemplate': 'به عنوان «{name}» ذخیره شد',

View file

@ -1664,6 +1664,7 @@ export const fr: Dict = {
'fileViewer.exportImageFailed': 'La capture d\'image a échoué. Veuillez réessayer ou utiliser l\'outil de capture d\'écran de votre navigateur.',
'fileViewer.exportJsx': 'Exporter en JSX',
'fileViewer.exportReactHtml': 'Exporter l\'aperçu en HTML',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': 'Enregistrer comme modèle…',
'fileViewer.savingTemplate': 'Enregistrement du modèle…',
'fileViewer.savedTemplate': 'Enregistré comme « {name} »',

View file

@ -1125,6 +1125,7 @@ export const hu: Dict = {
'fileViewer.exportImageFailed': 'A képrögzítés sikertelen. Kérjük, próbálja újra, vagy használja a böngészője képernyőkép eszközét.',
'fileViewer.exportJsx': 'Exportálás JSX-ként',
'fileViewer.exportReactHtml': 'Előnézet exportálása HTML-ként',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': 'Mentés sablonként…',
'fileViewer.savingTemplate': 'Sablon mentése…',
'fileViewer.savedTemplate': 'Mentve „{name}" néven',

View file

@ -1242,6 +1242,7 @@ export const id: Dict = {
'fileViewer.exportImageFailed': 'Gagal menangkap gambar. Silakan coba lagi atau gunakan alat tangkapan layar browser Anda.',
'fileViewer.exportJsx': 'Ekspor JSX',
'fileViewer.exportReactHtml': 'Ekspor React HTML',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': 'Simpan sebagai templat',
'fileViewer.savingTemplate': 'Menyimpan templat...',
'fileViewer.savedTemplate': 'Disimpan sebagai "{name}"',

View file

@ -1031,6 +1031,7 @@ export const it: Dict = {
'fileViewer.exportMd': 'Esporta in Markdown',
'fileViewer.exportJsx': 'Esporta in JSX',
'fileViewer.exportReactHtml': 'Esporta anteprima in HTML',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': 'Salva come modello…',
'fileViewer.savingTemplate': 'Salvataggio del modello…',
'fileViewer.savedTemplate': 'Salvato come « {name} »',

View file

@ -1012,6 +1012,7 @@ export const ja: Dict = {
'fileViewer.exportImageFailed': '画像のキャプチャに失敗しました。再試行するか、ブラウザのスクリーンショット機能をご利用ください。',
'fileViewer.exportJsx': 'JSX としてエクスポート',
'fileViewer.exportReactHtml': 'プレビューを HTML としてエクスポート',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': 'テンプレートとして保存…',
'fileViewer.savingTemplate': 'テンプレートを保存中…',
'fileViewer.savedTemplate': '"{name}" として保存しました',

View file

@ -1125,6 +1125,7 @@ export const ko: Dict = {
'fileViewer.exportImageFailed': '이미지 캡처에 실패했습니다. 다시 시도하거나 브라우저의 스크린샷 도구를 사용하세요.',
'fileViewer.exportJsx': 'JSX로 내보내기',
'fileViewer.exportReactHtml': '미리보기를 HTML로 내보내기',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': '템플릿으로 저장…',
'fileViewer.savingTemplate': '템플릿 저장 중…',
'fileViewer.savedTemplate': '"{name}"(으)로 저장됨',

View file

@ -1125,6 +1125,7 @@ export const pl: Dict = {
'fileViewer.exportImageFailed': 'Przechwytywanie obrazu nie powiodło się. Spróbuj ponownie lub użyj narzędzia do zrzutów ekranu w przeglądarce.',
'fileViewer.exportJsx': 'Eksportuj jako JSX',
'fileViewer.exportReactHtml': 'Eksportuj podgląd jako HTML',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': 'Zapisz jako szablon…',
'fileViewer.savingTemplate': 'Zapisywanie szablonu…',
'fileViewer.savedTemplate': 'Zapisano jako „{name}”',

View file

@ -1148,6 +1148,7 @@ export const ptBR: Dict = {
'fileViewer.exportImageFailed': 'Falha ao capturar a imagem. Tente novamente ou use a ferramenta de captura de tela do seu navegador.',
'fileViewer.exportJsx': 'Exportar como JSX',
'fileViewer.exportReactHtml': 'Exportar prévia como HTML',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': 'Salvar como template…',
'fileViewer.savingTemplate': 'Salvando template…',
'fileViewer.savedTemplate': 'Salvo como "{name}"',

View file

@ -1148,6 +1148,7 @@ export const ru: Dict = {
'fileViewer.exportImageFailed': 'Не удалось сделать снимок. Попробуйте ещё раз или воспользуйтесь инструментом скриншотов вашего браузера.',
'fileViewer.exportJsx': 'Экспорт как JSX',
'fileViewer.exportReactHtml': 'Экспорт предпросмотра как HTML',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': 'Сохранить как шаблон…',
'fileViewer.savingTemplate': 'Сохранение шаблона…',
'fileViewer.savedTemplate': 'Сохранено как «{name}»',

View file

@ -1057,6 +1057,7 @@ export const th: Dict = {
'fileViewer.exportImageFailed': 'การจับภาพล้มเหลว กรุณาลองอีกครั้งหรือใช้เครื่องมือจับภาพหน้าจอของเบราว์เซอร์',
'fileViewer.exportJsx': 'นำโค้ดในรูปแบบ React JSX ออก',
'fileViewer.exportReactHtml': 'แยกโหลดมาแค่โครง HTML เท่านั้น',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': 'จัดเก็บในหมวดเทมเพลต…',
'fileViewer.savingTemplate': 'ระบบคอยเซฟแม่แบบให้…',
'fileViewer.savedTemplate': 'ได้สร้างเทมเพลตใหม่ชื่อ "{name}"',

View file

@ -1112,6 +1112,7 @@ export const tr: Dict = {
'fileViewer.exportImageFailed': 'Görsel yakalama başarısız oldu. Lütfen tekrar deneyin veya tarayıcınızın ekran görüntüsü aracını kullanın.',
'fileViewer.exportJsx': 'JSX olarak dışa aktar',
'fileViewer.exportReactHtml': 'Önizlemeyi HTML olarak dışa aktar',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': 'Şablon olarak kaydet…',
'fileViewer.savingTemplate': 'Şablon kaydediliyor…',
'fileViewer.savedTemplate': '"{name}" olarak kaydedildi',

View file

@ -1167,6 +1167,7 @@ export const uk: Dict = {
'fileViewer.exportImageFailed': 'Не вдалося захопити зображення. Спробуйте ще раз або скористайтеся інструментом знімків екрана вашого браузера.',
'fileViewer.exportJsx': 'Експортувати як JSX',
'fileViewer.exportReactHtml': 'Експортувати попередній перегляд як HTML',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': 'Зберегти як шаблон…',
'fileViewer.savingTemplate': 'Збереження шаблону…',
'fileViewer.savedTemplate': 'Збережено як "{name}"',

View file

@ -1729,6 +1729,7 @@ export const zhCN: Dict = {
'fileViewer.exportImageFailed': '图片捕获失败,请重试或使用浏览器的截图工具。',
'fileViewer.exportJsx': '导出为 JSX',
'fileViewer.exportReactHtml': '导出预览 HTML',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': '保存为模板…',
'fileViewer.savingTemplate': '正在保存模板…',
'fileViewer.savedTemplate': '已保存为「{name}」',

View file

@ -1319,6 +1319,7 @@ export const zhTW: Dict = {
'fileViewer.exportImageFailed': '圖片擷取失敗,請重試或使用瀏覽器的截圖工具。',
'fileViewer.exportJsx': '匯出為 JSX',
'fileViewer.exportReactHtml': '匯出預覽 HTML',
'fileViewer.exportStarted': 'Export started',
'fileViewer.saveAsTemplate': '儲存為範本…',
'fileViewer.savingTemplate': '正在儲存範本…',
'fileViewer.savedTemplate': '已儲存為「{name}」',

View file

@ -2054,6 +2054,7 @@ export interface Dict {
'fileViewer.exportImageFailed': string;
'fileViewer.exportJsx': string;
'fileViewer.exportReactHtml': string;
'fileViewer.exportStarted': string;
'fileViewer.saveAsTemplate': string;
'fileViewer.savingTemplate': string;
'fileViewer.savedTemplate': string;