fix(issue 522): surface paste errors as UI toast notification (#1198)
* fix: surface paste errors as UI toast notification (#522) When pasting the transcription fails (e.g. wtype/xdotool/dotool not available or returns an error on Linux), the error was silently logged to the backend console only. Users had no idea why their text was not pasted. Emit a new 'paste-error' Tauri event from the Rust side and listen for it in the frontend App component, showing a sonner toast with the error detail — mirroring the existing 'recording-error' pattern exactly. Files changed: - src-tauri/src/actions.rs: add PasteErrorEvent struct, emit event on paste failure - src/App.tsx: add useEffect listener that shows toast.error on paste-error - src/lib/types/events.ts: add PasteErrorEvent interface - src/i18n/locales/en/translation.json: add pasteFailedTitle/pasteFailed keys * chore: apply cargo fmt and prettier formatting * add translationss --------- Co-authored-by: CJ Pais <cj@cjpais.com>
This commit is contained in:
parent
84d88f911c
commit
30b57c4295
22 changed files with 79 additions and 21 deletions
|
|
@ -612,7 +612,10 @@ impl ShortcutAction for TranscribeAction {
|
|||
"Text pasted successfully in {:?}",
|
||||
paste_time.elapsed()
|
||||
),
|
||||
Err(e) => error!("Failed to paste transcription: {}", e),
|
||||
Err(e) => {
|
||||
error!("Failed to paste transcription: {}", e);
|
||||
let _ = ah_clone.emit("paste-error", ());
|
||||
}
|
||||
}
|
||||
utils::hide_recording_overlay(&ah_clone);
|
||||
change_tray_icon(&ah_clone, TrayIconState::Idle);
|
||||
|
|
|
|||
15
src/App.tsx
15
src/App.tsx
|
|
@ -122,6 +122,21 @@ function App() {
|
|||
};
|
||||
}, [t]);
|
||||
|
||||
// Listen for paste failures and show a toast.
|
||||
// The technical error detail is logged to handy.log on the Rust side
|
||||
// (see actions.rs `error!("Failed to paste transcription: ...")`),
|
||||
// so we show a localized, user-friendly message here instead of the raw error.
|
||||
useEffect(() => {
|
||||
const unlisten = listen("paste-error", () => {
|
||||
toast.error(t("errors.pasteFailedTitle"), {
|
||||
description: t("errors.pasteFailed"),
|
||||
});
|
||||
});
|
||||
return () => {
|
||||
unlisten.then((fn) => fn());
|
||||
};
|
||||
}, [t]);
|
||||
|
||||
// Listen for model loading failures and show a toast
|
||||
useEffect(() => {
|
||||
const unlisten = listen<ModelStateEvent>("model-state-changed", (event) => {
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "لم يتم اكتشاف أي جهاز إدخال صوتي. يرجى توصيل ميكروفون أو سماعة رأس والمحاولة مرة أخرى.",
|
||||
"recordingFailed": "فشل في بدء التسجيل: {{error}}",
|
||||
"modelLoadFailed": "فشل في تحميل النموذج: {{model}}",
|
||||
"modelLoadFailedUnknown": "نموذج غير معروف"
|
||||
"modelLoadFailedUnknown": "نموذج غير معروف",
|
||||
"pasteFailedTitle": "فشل لصق النص",
|
||||
"pasteFailed": "تعذر لصق النص في التطبيق النشط."
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "لغة التطبيق",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "Не е открито аудио входно устройство. Свържете микрофон или слушалки и опитайте отново.",
|
||||
"recordingFailed": "Стартирането на записа не бе успешно: {{error}}",
|
||||
"modelLoadFailed": "Зареждането на модела не бе успешно: {{model}}",
|
||||
"modelLoadFailedUnknown": "неизвестен модел"
|
||||
"modelLoadFailedUnknown": "неизвестен модел",
|
||||
"pasteFailedTitle": "Неуспешно поставяне на текст",
|
||||
"pasteFailed": "Текстът не можа да бъде поставен в активното приложение."
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "Език на приложението",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "Nebylo detekováno žádné zvukové vstupní zařízení. Připojte mikrofon nebo sluchátka a zkuste to znovu.",
|
||||
"recordingFailed": "Nepodařilo se spustit nahrávání: {{error}}",
|
||||
"modelLoadFailed": "Nepodařilo se načíst model: {{model}}",
|
||||
"modelLoadFailedUnknown": "neznámý model"
|
||||
"modelLoadFailedUnknown": "neznámý model",
|
||||
"pasteFailedTitle": "Vložení textu se nezdařilo",
|
||||
"pasteFailed": "Text nebylo možné vložit do aktivní aplikace."
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "Jazyk aplikace",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "Es wurde kein Audio-Eingabegerät erkannt. Bitte schließen Sie ein Mikrofon oder Headset an und versuchen Sie es erneut.",
|
||||
"recordingFailed": "Aufnahme konnte nicht gestartet werden: {{error}}",
|
||||
"modelLoadFailed": "Modell konnte nicht geladen werden: {{model}}",
|
||||
"modelLoadFailedUnknown": "unbekanntes Modell"
|
||||
"modelLoadFailedUnknown": "unbekanntes Modell",
|
||||
"pasteFailedTitle": "Text konnte nicht eingefügt werden",
|
||||
"pasteFailed": "Der Text konnte nicht in die aktive Anwendung eingefügt werden."
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "Anwendungssprache",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "No audio input device was detected. Please connect a microphone or headset and try again.",
|
||||
"recordingFailed": "Failed to start recording: {{error}}",
|
||||
"modelLoadFailed": "Failed to load model: {{model}}",
|
||||
"modelLoadFailedUnknown": "unknown model"
|
||||
"modelLoadFailedUnknown": "unknown model",
|
||||
"pasteFailedTitle": "Failed to Paste Text",
|
||||
"pasteFailed": "Text could not be pasted into the active application."
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "Application Language",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "No se detectó ningún dispositivo de entrada de audio. Conecta un micrófono o auriculares e inténtalo de nuevo.",
|
||||
"recordingFailed": "Error al iniciar la grabación: {{error}}",
|
||||
"modelLoadFailed": "Error al cargar el modelo: {{model}}",
|
||||
"modelLoadFailedUnknown": "modelo desconocido"
|
||||
"modelLoadFailedUnknown": "modelo desconocido",
|
||||
"pasteFailedTitle": "Error al pegar el texto",
|
||||
"pasteFailed": "No se pudo pegar el texto en la aplicación activa."
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "Idioma de la aplicación",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "Aucun périphérique d'entrée audio n'a été détecté. Veuillez connecter un microphone ou un casque et réessayer.",
|
||||
"recordingFailed": "Échec du démarrage de l'enregistrement : {{error}}",
|
||||
"modelLoadFailed": "Échec du chargement du modèle : {{model}}",
|
||||
"modelLoadFailedUnknown": "modèle inconnu"
|
||||
"modelLoadFailedUnknown": "modèle inconnu",
|
||||
"pasteFailedTitle": "Échec du collage du texte",
|
||||
"pasteFailed": "Le texte n'a pas pu être collé dans l'application active."
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "Langue de l'application",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "לא זוהה התקן קלט שמע. חבר מיקרופון או אוזנייה ונסה שוב.",
|
||||
"recordingFailed": "הפעלת ההקלטה נכשלה: {{error}}",
|
||||
"modelLoadFailed": "טעינת המודל נכשלה: {{model}}",
|
||||
"modelLoadFailedUnknown": "מודל לא ידוע"
|
||||
"modelLoadFailedUnknown": "מודל לא ידוע",
|
||||
"pasteFailedTitle": "ההדבקה נכשלה",
|
||||
"pasteFailed": "לא ניתן היה להדביק את הטקסט ביישום הפעיל."
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "שפת האפליקציה",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "Non è stato rilevato alcun dispositivo di ingresso audio. Collega un microfono o delle cuffie e riprova.",
|
||||
"recordingFailed": "Impossibile avviare la registrazione: {{error}}",
|
||||
"modelLoadFailed": "Impossibile caricare il modello: {{model}}",
|
||||
"modelLoadFailedUnknown": "modello sconosciuto"
|
||||
"modelLoadFailedUnknown": "modello sconosciuto",
|
||||
"pasteFailedTitle": "Impossibile incollare il testo",
|
||||
"pasteFailed": "Non è stato possibile incollare il testo nell'applicazione attiva."
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "Lingua Applicazione",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "オーディオ入力デバイスが検出されませんでした。マイクまたはヘッドセットを接続してから再試行してください。",
|
||||
"recordingFailed": "録音の開始に失敗しました: {{error}}",
|
||||
"modelLoadFailed": "モデルの読み込みに失敗しました: {{model}}",
|
||||
"modelLoadFailedUnknown": "不明なモデル"
|
||||
"modelLoadFailedUnknown": "不明なモデル",
|
||||
"pasteFailedTitle": "テキストの貼り付けに失敗しました",
|
||||
"pasteFailed": "アクティブなアプリケーションにテキストを貼り付けられませんでした。"
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "アプリケーション言語",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "오디오 입력 장치가 감지되지 않았습니다. 마이크 또는 헤드셋을 연결한 후 다시 시도해 주세요.",
|
||||
"recordingFailed": "녹음을 시작하지 못했습니다: {{error}}",
|
||||
"modelLoadFailed": "모델을 불러오지 못했습니다: {{model}}",
|
||||
"modelLoadFailedUnknown": "알 수 없는 모델"
|
||||
"modelLoadFailedUnknown": "알 수 없는 모델",
|
||||
"pasteFailedTitle": "텍스트 붙여넣기 실패",
|
||||
"pasteFailed": "활성 애플리케이션에 텍스트를 붙여넣을 수 없습니다."
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "애플리케이션 언어",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "Nie wykryto żadnego urządzenia wejściowego audio. Podłącz mikrofon lub słuchawki i spróbuj ponownie.",
|
||||
"recordingFailed": "Nie udało się rozpocząć nagrywania: {{error}}",
|
||||
"modelLoadFailed": "Nie udało się załadować modelu: {{model}}",
|
||||
"modelLoadFailedUnknown": "nieznany model"
|
||||
"modelLoadFailedUnknown": "nieznany model",
|
||||
"pasteFailedTitle": "Nie udało się wkleić tekstu",
|
||||
"pasteFailed": "Nie można było wkleić tekstu do aktywnej aplikacji."
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "Język aplikacji",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "Nenhum dispositivo de entrada de áudio foi detectado. Conecte um microfone ou fone de ouvido e tente novamente.",
|
||||
"recordingFailed": "Falha ao iniciar a gravação: {{error}}",
|
||||
"modelLoadFailed": "Falha ao carregar o modelo: {{model}}",
|
||||
"modelLoadFailedUnknown": "modelo desconhecido"
|
||||
"modelLoadFailedUnknown": "modelo desconhecido",
|
||||
"pasteFailedTitle": "Falha ao colar o texto",
|
||||
"pasteFailed": "Não foi possível colar o texto no aplicativo ativo."
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "Idioma da Aplicação",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "Аудиоустройство ввода не обнаружено. Подключите микрофон или гарнитуру и попробуйте снова.",
|
||||
"recordingFailed": "Не удалось начать запись: {{error}}",
|
||||
"modelLoadFailed": "Не удалось загрузить модель: {{model}}",
|
||||
"modelLoadFailedUnknown": "неизвестная модель"
|
||||
"modelLoadFailedUnknown": "неизвестная модель",
|
||||
"pasteFailedTitle": "Не удалось вставить текст",
|
||||
"pasteFailed": "Не удалось вставить текст в активное приложение."
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "Язык приложения",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"modelLoadFailed": "Misslyckades med att ladda modell: {{model}}",
|
||||
"modelLoadFailedUnknown": "okänd modell",
|
||||
"noInputDeviceTitle": "Ingen mikrofon hittades",
|
||||
"noInputDevice": "Ingen ljudenhet hittades. Anslut en mikrofon eller ett headset och försök igen."
|
||||
"noInputDevice": "Ingen ljudenhet hittades. Anslut en mikrofon eller ett headset och försök igen.",
|
||||
"pasteFailedTitle": "Det gick inte att klistra in texten",
|
||||
"pasteFailed": "Texten kunde inte klistras in i det aktiva programmet."
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "Applikationsspråk",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "Ses giriş aygıtı algılanamadı. Lütfen bir mikrofon veya kulaklık bağlayın ve tekrar deneyin.",
|
||||
"recordingFailed": "Kayıt başlatılamadı: {{error}}",
|
||||
"modelLoadFailed": "Model yüklenemedi: {{model}}",
|
||||
"modelLoadFailedUnknown": "bilinmeyen model"
|
||||
"modelLoadFailedUnknown": "bilinmeyen model",
|
||||
"pasteFailedTitle": "Metin yapıştırılamadı",
|
||||
"pasteFailed": "Metin etkin uygulamaya yapıştırılamadı."
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "Uygulama Dili",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "Не виявлено жодного пристрою введення звуку. Підключіть мікрофон або гарнітуру та спробуйте знову.",
|
||||
"recordingFailed": "Не вдалося розпочати запис: {{error}}",
|
||||
"modelLoadFailed": "Не вдалося завантажити модель: {{model}}",
|
||||
"modelLoadFailedUnknown": "невідома модель"
|
||||
"modelLoadFailedUnknown": "невідома модель",
|
||||
"pasteFailedTitle": "Не вдалося вставити текст",
|
||||
"pasteFailed": "Не вдалося вставити текст до активної програми."
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "Мова інтерфейсу",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "Không phát hiện thiết bị đầu vào âm thanh nào. Vui lòng kết nối micrô hoặc tai nghe và thử lại.",
|
||||
"recordingFailed": "Không thể bắt đầu ghi âm: {{error}}",
|
||||
"modelLoadFailed": "Không thể tải mô hình: {{model}}",
|
||||
"modelLoadFailedUnknown": "mô hình không xác định"
|
||||
"modelLoadFailedUnknown": "mô hình không xác định",
|
||||
"pasteFailedTitle": "Không thể dán văn bản",
|
||||
"pasteFailed": "Không thể dán văn bản vào ứng dụng đang hoạt động."
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "Ngôn ngữ ứng dụng",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "未偵測到音訊輸入裝置。請連接麥克風或耳機後重試。",
|
||||
"recordingFailed": "錄音啟動失敗: {{error}}",
|
||||
"modelLoadFailed": "載入模型失敗: {{model}}",
|
||||
"modelLoadFailedUnknown": "未知模型"
|
||||
"modelLoadFailedUnknown": "未知模型",
|
||||
"pasteFailedTitle": "貼上文字失敗",
|
||||
"pasteFailed": "無法將文字貼上至目前作用中的應用程式。"
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "應用程式語言",
|
||||
|
|
|
|||
|
|
@ -597,7 +597,9 @@
|
|||
"noInputDevice": "未检测到音频输入设备。请连接麦克风或耳机后重试。",
|
||||
"recordingFailed": "录音启动失败: {{error}}",
|
||||
"modelLoadFailed": "加载模型失败: {{model}}",
|
||||
"modelLoadFailedUnknown": "未知模型"
|
||||
"modelLoadFailedUnknown": "未知模型",
|
||||
"pasteFailedTitle": "粘贴文本失败",
|
||||
"pasteFailed": "无法将文本粘贴到当前活动的应用程序中。"
|
||||
},
|
||||
"appLanguage": {
|
||||
"title": "应用语言",
|
||||
|
|
|
|||
Loading…
Reference in a new issue