From 7bd4a59107e35c773e25e5a30a280dc6606d3eda Mon Sep 17 00:00:00 2001 From: CJ Pais Date: Tue, 16 Dec 2025 01:50:53 -0800 Subject: [PATCH] Fix 'history limit' not saving to settings (#463) * fix history limit not saving * update the translations as well --- src-tauri/src/lib.rs | 2 +- src/bindings.ts | 12 ++++++------ src/components/settings/HistoryLimit.tsx | 4 ++-- src/i18n/locales/de/translation.json | 6 +++--- src/i18n/locales/en/translation.json | 12 ++++++------ src/i18n/locales/es/translation.json | 10 ++++++++-- src/i18n/locales/fr/translation.json | 10 ++++++++-- src/i18n/locales/ja/translation.json | 6 +++--- src/i18n/locales/pl/translation.json | 6 +++--- src/i18n/locales/vi/translation.json | 10 ++++++++-- src/i18n/locales/zh/translation.json | 6 +++--- src/stores/settingsStore.ts | 2 +- 12 files changed, 52 insertions(+), 34 deletions(-) diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index abf6672..e39c792 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -313,7 +313,7 @@ pub fn run() { #[cfg(debug_assertions)] // <- Only export on non-release builds specta_builder .export( - Typescript::default().bigint(BigIntExportBehavior::String), + Typescript::default().bigint(BigIntExportBehavior::Number), "../src/bindings.ts", ) .expect("Failed to export typescript bindings"); diff --git a/src/bindings.ts b/src/bindings.ts index 194ac5b..7e271a4 100644 --- a/src/bindings.ts +++ b/src/bindings.ts @@ -555,7 +555,7 @@ async getHistoryEntries() : Promise> { else return { status: "error", error: e as any }; } }, -async toggleHistoryEntrySaved(id: string) : Promise> { +async toggleHistoryEntrySaved(id: number) : Promise> { try { return { status: "ok", data: await TAURI_INVOKE("toggle_history_entry_saved", { id }) }; } catch (e) { @@ -571,7 +571,7 @@ async getAudioFilePath(fileName: string) : Promise> { else return { status: "error", error: e as any }; } }, -async deleteHistoryEntry(id: string) : Promise> { +async deleteHistoryEntry(id: number) : Promise> { try { return { status: "ok", data: await TAURI_INVOKE("delete_history_entry", { id }) }; } catch (e) { @@ -579,7 +579,7 @@ async deleteHistoryEntry(id: string) : Promise> { else return { status: "error", error: e as any }; } }, -async updateHistoryLimit(limit: string) : Promise> { +async updateHistoryLimit(limit: number) : Promise> { try { return { status: "ok", data: await TAURI_INVOKE("update_history_limit", { limit }) }; } catch (e) { @@ -621,16 +621,16 @@ async isLaptop() : Promise> { /** user-defined types **/ -export type AppSettings = { bindings: Partial<{ [key in string]: ShortcutBinding }>; push_to_talk: boolean; audio_feedback: boolean; audio_feedback_volume?: number; sound_theme?: SoundTheme; start_hidden?: boolean; autostart_enabled?: boolean; update_checks_enabled?: boolean; selected_model?: string; always_on_microphone?: boolean; selected_microphone?: string | null; clamshell_microphone?: string | null; selected_output_device?: string | null; translate_to_english?: boolean; selected_language?: string; overlay_position?: OverlayPosition; debug_mode?: boolean; log_level?: LogLevel; custom_words?: string[]; model_unload_timeout?: ModelUnloadTimeout; word_correction_threshold?: number; history_limit?: string; recording_retention_period?: RecordingRetentionPeriod; paste_method?: PasteMethod; clipboard_handling?: ClipboardHandling; post_process_enabled?: boolean; post_process_provider_id?: string; post_process_providers?: PostProcessProvider[]; post_process_api_keys?: Partial<{ [key in string]: string }>; post_process_models?: Partial<{ [key in string]: string }>; post_process_prompts?: LLMPrompt[]; post_process_selected_prompt_id?: string | null; mute_while_recording?: boolean; append_trailing_space?: boolean; app_language?: string } +export type AppSettings = { bindings: Partial<{ [key in string]: ShortcutBinding }>; push_to_talk: boolean; audio_feedback: boolean; audio_feedback_volume?: number; sound_theme?: SoundTheme; start_hidden?: boolean; autostart_enabled?: boolean; update_checks_enabled?: boolean; selected_model?: string; always_on_microphone?: boolean; selected_microphone?: string | null; clamshell_microphone?: string | null; selected_output_device?: string | null; translate_to_english?: boolean; selected_language?: string; overlay_position?: OverlayPosition; debug_mode?: boolean; log_level?: LogLevel; custom_words?: string[]; model_unload_timeout?: ModelUnloadTimeout; word_correction_threshold?: number; history_limit?: number; recording_retention_period?: RecordingRetentionPeriod; paste_method?: PasteMethod; clipboard_handling?: ClipboardHandling; post_process_enabled?: boolean; post_process_provider_id?: string; post_process_providers?: PostProcessProvider[]; post_process_api_keys?: Partial<{ [key in string]: string }>; post_process_models?: Partial<{ [key in string]: string }>; post_process_prompts?: LLMPrompt[]; post_process_selected_prompt_id?: string | null; mute_while_recording?: boolean; append_trailing_space?: boolean; app_language?: string } export type AudioDevice = { index: string; name: string; is_default: boolean } export type BindingResponse = { success: boolean; binding: ShortcutBinding | null; error: string | null } export type ClipboardHandling = "dont_modify" | "copy_to_clipboard" export type CustomSounds = { start: boolean; stop: boolean } export type EngineType = "Whisper" | "Parakeet" -export type HistoryEntry = { id: string; file_name: string; timestamp: string; saved: boolean; title: string; transcription_text: string; post_processed_text: string | null; post_process_prompt: string | null } +export type HistoryEntry = { id: number; file_name: string; timestamp: number; saved: boolean; title: string; transcription_text: string; post_processed_text: string | null; post_process_prompt: string | null } export type LLMPrompt = { id: string; name: string; prompt: string } export type LogLevel = "trace" | "debug" | "info" | "warn" | "error" -export type ModelInfo = { id: string; name: string; description: string; filename: string; url: string | null; size_mb: string; is_downloaded: boolean; is_downloading: boolean; partial_size: string; is_directory: boolean; engine_type: EngineType; accuracy_score: number; speed_score: number } +export type ModelInfo = { id: string; name: string; description: string; filename: string; url: string | null; size_mb: number; is_downloaded: boolean; is_downloading: boolean; partial_size: number; is_directory: boolean; engine_type: EngineType; accuracy_score: number; speed_score: number } export type ModelLoadStatus = { is_loaded: boolean; current_model: string | null } export type ModelUnloadTimeout = "never" | "immediately" | "min_2" | "min_5" | "min_10" | "min_15" | "hour_1" | "sec_5" export type OverlayPosition = "none" | "top" | "bottom" diff --git a/src/components/settings/HistoryLimit.tsx b/src/components/settings/HistoryLimit.tsx index 4ef5d39..a597c15 100644 --- a/src/components/settings/HistoryLimit.tsx +++ b/src/components/settings/HistoryLimit.tsx @@ -16,12 +16,12 @@ export const HistoryLimit: React.FC = ({ const { t } = useTranslation(); const { getSetting, updateSetting, isUpdating } = useSettings(); - const historyLimit = Number(getSetting("history_limit") ?? "5"); + const historyLimit = getSetting("history_limit") ?? 5; const handleChange = async (event: React.ChangeEvent) => { const value = parseInt(event.target.value, 10); if (!isNaN(value) && value >= 0) { - updateSetting("history_limit", value.toString()); + updateSetting("history_limit", value); } }; diff --git a/src/i18n/locales/de/translation.json b/src/i18n/locales/de/translation.json index 50c417d..8fefed6 100644 --- a/src/i18n/locales/de/translation.json +++ b/src/i18n/locales/de/translation.json @@ -293,10 +293,10 @@ "entries": "Einträge" }, "recordingRetention": { - "title": "Aufnahme-Aufbewahrung", - "description": "Wie lange Audioaufnahmen aufbewahrt werden sollen", + "title": "Aufnahmen automatisch löschen", + "description": "Alte Aufnahmen automatisch löschen, um Speicherplatz zu sparen", "never": "Nie", - "preserveLimit": "{{count}} Aufnahmen behalten", + "preserveLimit": "Neueste {{count}} behalten", "days3": "Nach 3 Tagen", "weeks2": "Nach 2 Wochen", "months3": "Nach 3 Monaten", diff --git a/src/i18n/locales/en/translation.json b/src/i18n/locales/en/translation.json index a6a7683..a97bd27 100644 --- a/src/i18n/locales/en/translation.json +++ b/src/i18n/locales/en/translation.json @@ -293,13 +293,13 @@ "entries": "entries" }, "recordingRetention": { - "title": "Recording Retention", - "description": "How long to keep audio recordings", + "title": "Auto-Delete Recordings", + "description": "Automatically delete old recordings to save space", "never": "Never", - "preserveLimit": "Preserve {{count}} Recordings", - "days3": "After 3 Days", - "weeks2": "After 2 Weeks", - "months3": "After 3 Months", + "preserveLimit": "Keep latest {{count}}", + "days3": "After 3 days", + "weeks2": "After 2 weeks", + "months3": "After 3 months", "placeholder": "Select retention period..." }, "alwaysOnMicrophone": { diff --git a/src/i18n/locales/es/translation.json b/src/i18n/locales/es/translation.json index 3d520d0..eb8896e 100644 --- a/src/i18n/locales/es/translation.json +++ b/src/i18n/locales/es/translation.json @@ -292,8 +292,14 @@ "description": "Número máximo de entradas de historial a conservar" }, "recordingRetention": { - "title": "Retención de Grabaciones", - "description": "Cuánto tiempo conservar las grabaciones de audio" + "title": "Eliminación automática de grabaciones", + "description": "Eliminar automáticamente grabaciones antiguas para ahorrar espacio", + "never": "Nunca", + "preserveLimit": "Mantener las últimas {{count}}", + "days3": "Después de 3 días", + "weeks2": "Después de 2 semanas", + "months3": "Después de 3 meses", + "placeholder": "Seleccionar período de retención..." }, "alwaysOnMicrophone": { "label": "Micrófono Siempre Activo", diff --git a/src/i18n/locales/fr/translation.json b/src/i18n/locales/fr/translation.json index e37f022..f36cd25 100644 --- a/src/i18n/locales/fr/translation.json +++ b/src/i18n/locales/fr/translation.json @@ -293,8 +293,14 @@ "description": "Nombre maximum d'entrées d'historique à conserver" }, "recordingRetention": { - "title": "Conservation des enregistrements", - "description": "Durée de conservation des enregistrements audio" + "title": "Suppression automatique des enregistrements", + "description": "Supprimer automatiquement les anciens enregistrements pour économiser de l'espace", + "never": "Jamais", + "preserveLimit": "Conserver les {{count}} plus récents", + "days3": "Après 3 jours", + "weeks2": "Après 2 semaines", + "months3": "Après 3 mois", + "placeholder": "Sélectionner la période de conservation..." }, "alwaysOnMicrophone": { "label": "Microphone toujours actif", diff --git a/src/i18n/locales/ja/translation.json b/src/i18n/locales/ja/translation.json index 311b814..2f2ea89 100644 --- a/src/i18n/locales/ja/translation.json +++ b/src/i18n/locales/ja/translation.json @@ -293,10 +293,10 @@ "entries": "件" }, "recordingRetention": { - "title": "録音の保持", - "description": "音声録音を保持する期間", + "title": "録音の自動削除", + "description": "古い録音を自動的に削除して容量を節約", "never": "しない", - "preserveLimit": "{{count}}件の録音を保持", + "preserveLimit": "最新{{count}}件を保持", "days3": "3日後", "weeks2": "2週間後", "months3": "3ヶ月後", diff --git a/src/i18n/locales/pl/translation.json b/src/i18n/locales/pl/translation.json index 7ff9c93..6943a48 100644 --- a/src/i18n/locales/pl/translation.json +++ b/src/i18n/locales/pl/translation.json @@ -293,10 +293,10 @@ "entries": "wpisy" }, "recordingRetention": { - "title": "Retencja nagrań", - "description": "Jak długo przechowywać nagrania audio", + "title": "Automatyczne usuwanie nagrań", + "description": "Automatycznie usuwaj stare nagrania, aby zaoszczędzić miejsce", "never": "Nigdy", - "preserveLimit": "Zachowaj {{count}} nagrań", + "preserveLimit": "Zachowaj ostatnie {{count}}", "days3": "Po 3 dniach", "weeks2": "Po 2 tygodniach", "months3": "Po 3 miesiącach", diff --git a/src/i18n/locales/vi/translation.json b/src/i18n/locales/vi/translation.json index 6bca206..7d54851 100644 --- a/src/i18n/locales/vi/translation.json +++ b/src/i18n/locales/vi/translation.json @@ -293,8 +293,14 @@ "description": "Số lượng mục lịch sử tối đa cần giữ" }, "recordingRetention": { - "title": "Lưu giữ ghi âm", - "description": "Thời gian giữ các bản ghi âm" + "title": "Tự động xóa ghi âm", + "description": "Tự động xóa các bản ghi âm cũ để tiết kiệm dung lượng", + "never": "Không bao giờ", + "preserveLimit": "Giữ {{count}} bản mới nhất", + "days3": "Sau 3 ngày", + "weeks2": "Sau 2 tuần", + "months3": "Sau 3 tháng", + "placeholder": "Chọn thời gian lưu giữ..." }, "alwaysOnMicrophone": { "label": "Micrô luôn bật", diff --git a/src/i18n/locales/zh/translation.json b/src/i18n/locales/zh/translation.json index 245860b..9463e82 100644 --- a/src/i18n/locales/zh/translation.json +++ b/src/i18n/locales/zh/translation.json @@ -293,10 +293,10 @@ "entries": "条" }, "recordingRetention": { - "title": "录音保留", - "description": "保留音频录音的时长", + "title": "自动删除录音", + "description": "自动删除旧录音以节省空间", "never": "从不", - "preserveLimit": "保留 {{count}} 条录音", + "preserveLimit": "保留最新 {{count}} 条", "days3": "3 天后", "weeks2": "2 周后", "months3": "3 个月后", diff --git a/src/stores/settingsStore.ts b/src/stores/settingsStore.ts index fdf98b3..f35a6e9 100644 --- a/src/stores/settingsStore.ts +++ b/src/stores/settingsStore.ts @@ -114,7 +114,7 @@ const settingUpdaters: { paste_method: (value) => commands.changePasteMethodSetting(value as string), clipboard_handling: (value) => commands.changeClipboardHandlingSetting(value as string), - history_limit: (value) => commands.updateHistoryLimit(value as string), + history_limit: (value) => commands.updateHistoryLimit(value as number), post_process_enabled: (value) => commands.changePostProcessEnabledSetting(value as boolean), post_process_selected_prompt_id: (value) =>