diff --git a/apps/whispering/src-tauri/Cargo.toml b/apps/whispering/src-tauri/Cargo.toml index 09fc1d185c..14e5d63727 100644 --- a/apps/whispering/src-tauri/Cargo.toml +++ b/apps/whispering/src-tauri/Cargo.toml @@ -12,6 +12,10 @@ cargo-target-macos-version = "10.15" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[[bin]] +name = "whispering" +path = "src/main.rs" + [lib] # The `_lib` suffix may seem redundant but it is necessary # to make the lib name unique and wouldn't conflict with the bin name. diff --git a/apps/whispering/src-tauri/tauri.conf.json b/apps/whispering/src-tauri/tauri.conf.json index 17488314d7..03e586b7d1 100644 --- a/apps/whispering/src-tauri/tauri.conf.json +++ b/apps/whispering/src-tauri/tauri.conf.json @@ -21,9 +21,8 @@ "createUpdaterArtifacts": true, "macOS": { "entitlements": "entitlements.plist", - "hardenedRuntime": true, - "minimumSystemVersion": "10.15", - "signingIdentity": "Developer ID Application: Braden Wong (3C7J97QA5Z)" + "hardenedRuntime": false, + "minimumSystemVersion": "10.15" }, "linux": { "appimage": { diff --git a/apps/whispering/src/lib/commands.ts b/apps/whispering/src/lib/commands.ts index aaf9c02d20..ecbb67ebf7 100644 --- a/apps/whispering/src/lib/commands.ts +++ b/apps/whispering/src/lib/commands.ts @@ -1,61 +1,86 @@ import { rpc } from '$lib/query'; + import type { ShortcutTriggerState } from './services/_shortcut-trigger-state'; type SatisfiedCommand = { + callback: () => void; id: string; - title: string; on: ShortcutTriggerState; - callback: () => void; + title: string; }; export const commands = [ { - id: 'pushToTalk', title: 'Push to talk', - on: 'Both', callback: () => rpc.commands.toggleManualRecording.execute(undefined), + id: 'pushToTalk', + on: 'Both', }, { - id: 'toggleManualRecording', title: 'Toggle recording', - on: 'Pressed', callback: () => rpc.commands.toggleManualRecording.execute(undefined), + id: 'toggleManualRecording', + on: 'Pressed', }, { - id: 'startManualRecording', title: 'Start recording', - on: 'Pressed', callback: () => rpc.commands.startManualRecording.execute(undefined), + id: 'startManualRecording', + on: 'Pressed', }, { - id: 'stopManualRecording', title: 'Stop recording', - on: 'Pressed', callback: () => rpc.commands.stopManualRecording.execute(undefined), + id: 'stopManualRecording', + on: 'Pressed', }, { - id: 'cancelManualRecording', title: 'Cancel recording', - on: 'Pressed', callback: () => rpc.commands.cancelManualRecording.execute(undefined), + id: 'cancelManualRecording', + on: 'Pressed', }, { - id: 'startVadRecording', title: 'Start voice activated recording', - on: 'Pressed', callback: () => rpc.commands.startVadRecording.execute(undefined), + id: 'startVadRecording', + on: 'Pressed', }, { - id: 'stopVadRecording', title: 'Stop voice activated recording', - on: 'Pressed', callback: () => rpc.commands.stopVadRecording.execute(undefined), + id: 'stopVadRecording', + on: 'Pressed', }, { - id: 'toggleVadRecording', title: 'Toggle voice activated recording', - on: 'Pressed', callback: () => rpc.commands.toggleVadRecording.execute(undefined), + id: 'toggleVadRecording', + on: 'Pressed', + }, + { + title: 'Cycle through favorite output languages', + callback: () => rpc.commands.toggleOutputLanguage.execute(undefined), + id: 'toggleOutputLanguage', + on: 'Pressed', + }, + { + title: 'Switch to favorite language #1', + callback: () => rpc.commands.setOutputLanguageSlot.execute({ slot: 1 }), + id: 'setOutputLanguageSlot1', + on: 'Pressed', + }, + { + title: 'Switch to favorite language #2', + callback: () => rpc.commands.setOutputLanguageSlot.execute({ slot: 2 }), + id: 'setOutputLanguageSlot2', + on: 'Pressed', + }, + { + title: 'Switch to favorite language #3', + callback: () => rpc.commands.setOutputLanguageSlot.execute({ slot: 3 }), + id: 'setOutputLanguageSlot3', + on: 'Pressed', }, ] as const satisfies SatisfiedCommand[]; diff --git a/apps/whispering/src/lib/components/ConfirmationDialog.svelte b/apps/whispering/src/lib/components/ConfirmationDialog.svelte index 38bc4ad8c3..e70717cb77 100644 --- a/apps/whispering/src/lib/components/ConfirmationDialog.svelte +++ b/apps/whispering/src/lib/components/ConfirmationDialog.svelte @@ -8,29 +8,26 @@ let confirmText = $state(''); let onConfirm = () => {}; return { + close() { + isOpen = false; + }, + get confirmText() { + return confirmText; + }, get isOpen() { return isOpen; }, set isOpen(v) { isOpen = v; }, - get title() { - return title; - }, - get subtitle() { - return subtitle; - }, - get confirmText() { - return confirmText; - }, get onConfirm() { return onConfirm; }, open(dialog: { - title: string; - subtitle: string; confirmText: string; onConfirm: () => void; + subtitle: string; + title: string; }) { title = dialog.title; subtitle = dialog.subtitle; @@ -38,8 +35,11 @@ onConfirm = dialog.onConfirm; isOpen = true; }, - close() { - isOpen = false; + get subtitle() { + return subtitle; + }, + get title() { + return title; }, }; } diff --git a/apps/whispering/src/lib/components/MoreDetailsDialog.svelte b/apps/whispering/src/lib/components/MoreDetailsDialog.svelte index 129b0dee0c..107f0d30b0 100644 --- a/apps/whispering/src/lib/components/MoreDetailsDialog.svelte +++ b/apps/whispering/src/lib/components/MoreDetailsDialog.svelte @@ -13,17 +13,8 @@ >([]); return { - get isOpen() { - return isOpen; - }, - set isOpen(value: boolean) { - isOpen = value; - }, - get title() { - return title; - }, - get description() { - return description; + get buttons() { + return buttons; }, get content() { if (typeof content === 'string') { @@ -34,18 +25,24 @@ } return JSON.stringify(content, null, 2); }, - get buttons() { - return buttons; + get description() { + return description; + }, + get isOpen() { + return isOpen; + }, + set isOpen(value: boolean) { + isOpen = value; }, open: (payload: { - title: string; - description: string; - content: unknown; buttons?: { label: string; onClick: () => void; variant?: 'default' | 'destructive'; }[]; + content: unknown; + description: string; + title: string; }) => { title = payload.title; description = payload.description; @@ -53,13 +50,16 @@ buttons = payload.buttons ?? []; isOpen = true; }, + get title() { + return title; + }, }; })(); diff --git a/apps/whispering/src/lib/components/NavItems.svelte b/apps/whispering/src/lib/components/NavItems.svelte index 321e34cd62..a212e458dd 100644 --- a/apps/whispering/src/lib/components/NavItems.svelte +++ b/apps/whispering/src/lib/components/NavItems.svelte @@ -1,10 +1,7 @@ diff --git a/apps/whispering/src/lib/components/UpdateDialog.svelte b/apps/whispering/src/lib/components/UpdateDialog.svelte index b7cdbb7e05..d029caabb8 100644 --- a/apps/whispering/src/lib/components/UpdateDialog.svelte +++ b/apps/whispering/src/lib/components/UpdateDialog.svelte @@ -2,39 +2,36 @@ import type { Update } from '@tauri-apps/plugin-updater'; export const updateDialog = createUpdateDialog(); - export type UpdateInfo = Pick< + export type UpdateInfo = null | Pick< Update, - 'version' | 'date' | 'body' | 'downloadAndInstall' - > | null; + 'body' | 'date' | 'downloadAndInstall' | 'version' + >; function createUpdateDialog() { let isOpen = $state(false); - let update = $state(null); + let update = $state(null); let downloadProgress = $state(0); let downloadTotal = $state(0); - let error = $state(null); + let error = $state(null); return { - get isOpen() { - return isOpen; + close() { + isOpen = false; }, - set isOpen(v) { - isOpen = v; + get error() { + return error; }, - get update() { - return update; + get isDownloadComplete() { + return downloadTotal > 0 && downloadProgress >= downloadTotal && !error; }, get isDownloading() { return downloadTotal > 0 && downloadProgress < downloadTotal && !error; }, - get isDownloadComplete() { - return downloadTotal > 0 && downloadProgress >= downloadTotal && !error; - }, - get progressPercentage() { - return downloadTotal > 0 ? (downloadProgress / downloadTotal) * 100 : 0; + get isOpen() { + return isOpen; }, - get error() { - return error; + set isOpen(v) { + isOpen = v; }, open(newUpdate: UpdateInfo) { update = newUpdate; @@ -43,28 +40,31 @@ downloadTotal = 0; error = null; }, - close() { - isOpen = false; + get progressPercentage() { + return downloadTotal > 0 ? (downloadProgress / downloadTotal) * 100 : 0; + }, + setError(err: null | string) { + error = err; + downloadTotal = 0; + }, + get update() { + return update; }, updateProgress(progress: number, total: number) { downloadProgress = progress; downloadTotal = total; }, - setError(err: string | null) { - error = err; - downloadTotal = 0; - }, }; } - {#snippet trigger({ tooltipProps, tooltip })} + {#snippet trigger({ tooltip, tooltipProps })} {@render children?.()} diff --git a/apps/whispering/src/lib/components/WhisperingTooltip.svelte b/apps/whispering/src/lib/components/WhisperingTooltip.svelte index af555fdda1..9ab8f4bd55 100644 --- a/apps/whispering/src/lib/components/WhisperingTooltip.svelte +++ b/apps/whispering/src/lib/components/WhisperingTooltip.svelte @@ -1,19 +1,20 @@ @@ -30,8 +31,8 @@ {#snippet child({ props: tooltipProps })} {@render trigger?.({ - tooltipProps: mergeProps(tooltipProps, restProps), tooltip, + tooltipProps: mergeProps(tooltipProps, restProps), })} {/snippet} diff --git a/apps/whispering/src/lib/components/copyable/CopyToClipboardButton.svelte b/apps/whispering/src/lib/components/copyable/CopyToClipboardButton.svelte index 6d3e535b05..5d3a7d8432 100644 --- a/apps/whispering/src/lib/components/copyable/CopyToClipboardButton.svelte +++ b/apps/whispering/src/lib/components/copyable/CopyToClipboardButton.svelte @@ -1,29 +1,36 @@ @@ -52,6 +53,13 @@ copyToClipboard.mutate( { text: textToCopy }, { + onError: (error) => { + rpc.notify.error.execute({ + title: `Error copying ${contentDescription} to clipboard`, + description: error.message, + action: { error, type: 'more-details' }, + }); + }, onSuccess: () => { hasCopied = true; setTimeout(() => { @@ -62,13 +70,6 @@ description: textToCopy, }); }, - onError: (error) => { - rpc.notify.error.execute({ - title: `Error copying ${contentDescription} to clipboard`, - description: error.message, - action: { type: 'more-details', error }, - }); - }, }, )} style={viewTransitionName diff --git a/apps/whispering/src/lib/components/copyable/CopyablePre.svelte b/apps/whispering/src/lib/components/copyable/CopyablePre.svelte index f107f36318..0beef19ded 100644 --- a/apps/whispering/src/lib/components/copyable/CopyablePre.svelte +++ b/apps/whispering/src/lib/components/copyable/CopyablePre.svelte @@ -1,13 +1,13 @@ diff --git a/apps/whispering/src/lib/components/copyable/CopyableTextareaExpandsToDialog.svelte b/apps/whispering/src/lib/components/copyable/CopyableTextareaExpandsToDialog.svelte index 947b57a662..80c7eab822 100644 --- a/apps/whispering/src/lib/components/copyable/CopyableTextareaExpandsToDialog.svelte +++ b/apps/whispering/src/lib/components/copyable/CopyableTextareaExpandsToDialog.svelte @@ -1,12 +1,13 @@ diff --git a/apps/whispering/src/lib/components/labeled/LabeledSelect.svelte b/apps/whispering/src/lib/components/labeled/LabeledSelect.svelte index 4a6d8e1de5..ec03f40a28 100644 --- a/apps/whispering/src/lib/components/labeled/LabeledSelect.svelte +++ b/apps/whispering/src/lib/components/labeled/LabeledSelect.svelte @@ -1,43 +1,44 @@ diff --git a/apps/whispering/src/lib/components/labeled/LabeledTextarea.svelte b/apps/whispering/src/lib/components/labeled/LabeledTextarea.svelte index 570c251cec..6e7c14b3db 100644 --- a/apps/whispering/src/lib/components/labeled/LabeledTextarea.svelte +++ b/apps/whispering/src/lib/components/labeled/LabeledTextarea.svelte @@ -1,23 +1,24 @@ diff --git a/apps/whispering/src/lib/components/settings/WhisperModelSelector.svelte b/apps/whispering/src/lib/components/settings/WhisperModelSelector.svelte index 90b9a6e916..5854d43013 100644 --- a/apps/whispering/src/lib/components/settings/WhisperModelSelector.svelte +++ b/apps/whispering/src/lib/components/settings/WhisperModelSelector.svelte @@ -1,63 +1,63 @@ diff --git a/apps/whispering/src/lib/components/settings/api-key-inputs/AnthropicApiKeyInput.svelte b/apps/whispering/src/lib/components/settings/api-key-inputs/AnthropicApiKeyInput.svelte index 5c3211c608..bf91d0e394 100644 --- a/apps/whispering/src/lib/components/settings/api-key-inputs/AnthropicApiKeyInput.svelte +++ b/apps/whispering/src/lib/components/settings/api-key-inputs/AnthropicApiKeyInput.svelte @@ -1,7 +1,7 @@ import { LabeledInput } from '$lib/components/labeled/index.js'; - import { Button } from '@repo/ui/button'; import { settings } from '$lib/stores/settings.svelte'; + import { Button } from '@repo/ui/button'; import { LabeledInput } from '$lib/components/labeled/index.js'; - import { Button } from '@repo/ui/button'; import { settings } from '$lib/stores/settings.svelte'; + import { Button } from '@repo/ui/button'; import { LabeledInput } from '$lib/components/labeled/index.js'; - import { Button } from '@repo/ui/button'; import { settings } from '$lib/stores/settings.svelte'; + import { Button } from '@repo/ui/button'; import { LabeledInput } from '$lib/components/labeled/index.js'; - import { Button } from '@repo/ui/button'; import { settings } from '$lib/stores/settings.svelte'; + import { Button } from '@repo/ui/button'; import { LabeledInput } from '$lib/components/labeled/index.js'; - import { Button } from '@repo/ui/button'; import { settings } from '$lib/stores/settings.svelte'; + import { Button } from '@repo/ui/button'; import WhisperingButton from '$lib/components/WhisperingButton.svelte'; - import * as Command from '@repo/ui/command'; - import * as Popover from '@repo/ui/popover'; - import { useCombobox } from '@repo/ui/hooks'; import { rpc } from '$lib/query'; import { settings } from '$lib/stores/settings.svelte'; + import { CheckIcon, MicIcon, RefreshCwIcon } from '@lucide/svelte'; + import * as Command from '@repo/ui/command'; + import { useCombobox } from '@repo/ui/hooks'; + import * as Popover from '@repo/ui/popover'; import { cn } from '@repo/ui/utils'; import { createQuery } from '@tanstack/svelte-query'; - import { CheckIcon, MicIcon, RefreshCwIcon } from '@lucide/svelte'; let { mode = 'manual' diff --git a/apps/whispering/src/lib/components/settings/selectors/TranscriptionSelector.svelte b/apps/whispering/src/lib/components/settings/selectors/TranscriptionSelector.svelte index 2445480c20..7b3b05ca26 100644 --- a/apps/whispering/src/lib/components/settings/selectors/TranscriptionSelector.svelte +++ b/apps/whispering/src/lib/components/settings/selectors/TranscriptionSelector.svelte @@ -1,10 +1,6 @@ diff --git a/apps/whispering/src/routes/(config)/global-shortcut/+page.svelte b/apps/whispering/src/routes/(config)/global-shortcut/+page.svelte index 25756248e9..c7729d1c39 100644 --- a/apps/whispering/src/routes/(config)/global-shortcut/+page.svelte +++ b/apps/whispering/src/routes/(config)/global-shortcut/+page.svelte @@ -1,8 +1,8 @@ diff --git a/apps/whispering/src/routes/(config)/install-ffmpeg/+page.svelte b/apps/whispering/src/routes/(config)/install-ffmpeg/+page.svelte index 32fa08c5a0..2da6925d00 100644 --- a/apps/whispering/src/routes/(config)/install-ffmpeg/+page.svelte +++ b/apps/whispering/src/routes/(config)/install-ffmpeg/+page.svelte @@ -1,22 +1,22 @@ diff --git a/apps/whispering/src/routes/(config)/recordings/RenderAudioUrl.svelte b/apps/whispering/src/routes/(config)/recordings/RenderAudioUrl.svelte index d1750423ff..59a7310671 100644 --- a/apps/whispering/src/routes/(config)/recordings/RenderAudioUrl.svelte +++ b/apps/whispering/src/routes/(config)/recordings/RenderAudioUrl.svelte @@ -1,10 +1,11 @@ diff --git a/apps/whispering/src/routes/(config)/recordings/row-actions/EditRecordingModal.svelte b/apps/whispering/src/routes/(config)/recordings/row-actions/EditRecordingModal.svelte index 159714ffb6..2e1f7b1c68 100644 --- a/apps/whispering/src/routes/(config)/recordings/row-actions/EditRecordingModal.svelte +++ b/apps/whispering/src/routes/(config)/recordings/row-actions/EditRecordingModal.svelte @@ -1,16 +1,17 @@ @@ -47,7 +48,7 @@ Customize your Whispering experience. {:then v} {#if v.isOutdated} - {@const { latestVersion, currentVersion, latestReleaseUrl } = v} + {@const { currentVersion, latestReleaseUrl, latestVersion } = v} Customize your experience for Whispering {currentVersion} (latest { confirmationDialog.open({ title: 'Reset All Settings', - subtitle: - 'This will reset all settings to their default values. This action cannot be undone.', confirmText: 'Reset Settings', onConfirm: () => { settings.reset(); @@ -84,6 +83,8 @@ description: 'All settings have been reset to defaults.', }); }, + subtitle: + 'This will reset all settings to their default values. This action cannot be undone.', }); }} class="shrink-0" diff --git a/apps/whispering/src/routes/(config)/settings/+page.svelte b/apps/whispering/src/routes/(config)/settings/+page.svelte index 61071ed2c0..afa96a83b1 100644 --- a/apps/whispering/src/routes/(config)/settings/+page.svelte +++ b/apps/whispering/src/routes/(config)/settings/+page.svelte @@ -3,10 +3,10 @@ LabeledSelect, LabeledSwitch, } from '$lib/components/labeled/index.js'; - import { Button } from '@repo/ui/button'; - import { Separator } from '@repo/ui/separator'; import { ALWAYS_ON_TOP_OPTIONS } from '$lib/constants/ui'; import { settings } from '$lib/stores/settings.svelte'; + import { Button } from '@repo/ui/button'; + import { Separator } from '@repo/ui/separator'; @@ -67,8 +67,8 @@ id="recording-retention-strategy" label="Auto Delete Recordings" items={[ - { value: 'keep-forever', label: 'Keep All Recordings' }, - { value: 'limit-count', label: 'Keep Limited Number' }, + { label: 'Keep All Recordings', value: 'keep-forever' }, + { label: 'Keep Limited Number', value: 'limit-count' }, ] as const} selected={settings.value['database.recordingRetentionStrategy']} onSelectedChange={(selected) => { @@ -82,12 +82,12 @@ id="max-recording-count" label="Maximum Recordings" items={[ - { value: '0', label: '0 Recordings (Never Save)' }, - { value: '5', label: '5 Recordings' }, - { value: '10', label: '10 Recordings' }, - { value: '25', label: '25 Recordings' }, - { value: '50', label: '50 Recordings' }, - { value: '100', label: '100 Recordings' }, + { label: '0 Recordings (Never Save)', value: '0' }, + { label: '5 Recordings', value: '5' }, + { label: '10 Recordings', value: '10' }, + { label: '25 Recordings', value: '25' }, + { label: '50 Recordings', value: '50' }, + { label: '100 Recordings', value: '100' }, ]} selected={settings.value['database.maxRecordingCount']} onSelectedChange={(selected) => { diff --git a/apps/whispering/src/routes/(config)/settings/SidebarNav.svelte b/apps/whispering/src/routes/(config)/settings/SidebarNav.svelte index bbd5f3ceb3..4b37ebfe94 100644 --- a/apps/whispering/src/routes/(config)/settings/SidebarNav.svelte +++ b/apps/whispering/src/routes/(config)/settings/SidebarNav.svelte @@ -13,18 +13,18 @@ { title: 'Sound', href: '/settings/sound' }, { title: 'Shortcuts', - href: '/settings/shortcuts/local', activePathPrefix: '/settings/shortcuts', + href: '/settings/shortcuts/local', }, { title: 'Privacy & Analytics', href: '/settings/analytics' }, ] satisfies { - title: string; - href: string; /** * If provided, the item is considered active if the current pathname starts with this prefix. * Otherwise, it is considered active if the current pathname is exactly equal to the item's href. */ activePathPrefix?: string; + href: string; + title: string; }[]; const [send, receive] = crossfade({ diff --git a/apps/whispering/src/routes/(config)/settings/analytics/+page.svelte b/apps/whispering/src/routes/(config)/settings/analytics/+page.svelte index 438f63414d..a91e7d72ad 100644 --- a/apps/whispering/src/routes/(config)/settings/analytics/+page.svelte +++ b/apps/whispering/src/routes/(config)/settings/analytics/+page.svelte @@ -1,17 +1,17 @@ diff --git a/apps/whispering/src/routes/(config)/settings/recording/+page.svelte b/apps/whispering/src/routes/(config)/settings/recording/+page.svelte index c3c50ba2ea..ee51b57602 100644 --- a/apps/whispering/src/routes/(config)/settings/recording/+page.svelte +++ b/apps/whispering/src/routes/(config)/settings/recording/+page.svelte @@ -1,33 +1,34 @@ diff --git a/apps/whispering/src/routes/(config)/settings/shortcuts/global/+page.svelte b/apps/whispering/src/routes/(config)/settings/shortcuts/global/+page.svelte index fcd475ce9d..4fc7ecf275 100644 --- a/apps/whispering/src/routes/(config)/settings/shortcuts/global/+page.svelte +++ b/apps/whispering/src/routes/(config)/settings/shortcuts/global/+page.svelte @@ -1,11 +1,12 @@ diff --git a/apps/whispering/src/routes/(config)/settings/shortcuts/keyboard-shortcut-recorder/GlobalKeyboardShortcutRecorder.svelte b/apps/whispering/src/routes/(config)/settings/shortcuts/keyboard-shortcut-recorder/GlobalKeyboardShortcutRecorder.svelte index bd23c91091..d9aed20075 100644 --- a/apps/whispering/src/routes/(config)/settings/shortcuts/keyboard-shortcut-recorder/GlobalKeyboardShortcutRecorder.svelte +++ b/apps/whispering/src/routes/(config)/settings/shortcuts/keyboard-shortcut-recorder/GlobalKeyboardShortcutRecorder.svelte @@ -1,26 +1,28 @@ diff --git a/apps/whispering/src/routes/(config)/settings/shortcuts/keyboard-shortcut-recorder/KeyboardShortcutRecorder.svelte b/apps/whispering/src/routes/(config)/settings/shortcuts/keyboard-shortcut-recorder/KeyboardShortcutRecorder.svelte index 12e5fa7264..90a43fbfeb 100644 --- a/apps/whispering/src/routes/(config)/settings/shortcuts/keyboard-shortcut-recorder/KeyboardShortcutRecorder.svelte +++ b/apps/whispering/src/routes/(config)/settings/shortcuts/keyboard-shortcut-recorder/KeyboardShortcutRecorder.svelte @@ -1,27 +1,29 @@ diff --git a/apps/whispering/src/routes/(config)/settings/shortcuts/keyboard-shortcut-recorder/ShortcutFormatHelp.svelte b/apps/whispering/src/routes/(config)/settings/shortcuts/keyboard-shortcut-recorder/ShortcutFormatHelp.svelte index 93b020bc19..e83778dfad 100644 --- a/apps/whispering/src/routes/(config)/settings/shortcuts/keyboard-shortcut-recorder/ShortcutFormatHelp.svelte +++ b/apps/whispering/src/routes/(config)/settings/shortcuts/keyboard-shortcut-recorder/ShortcutFormatHelp.svelte @@ -1,10 +1,5 @@ diff --git a/apps/whispering/src/routes/(config)/settings/shortcuts/keyboard-shortcut-recorder/ShortcutTable.svelte b/apps/whispering/src/routes/(config)/settings/shortcuts/keyboard-shortcut-recorder/ShortcutTable.svelte index a7e808d4fa..49462014d2 100644 --- a/apps/whispering/src/routes/(config)/settings/shortcuts/keyboard-shortcut-recorder/ShortcutTable.svelte +++ b/apps/whispering/src/routes/(config)/settings/shortcuts/keyboard-shortcut-recorder/ShortcutTable.svelte @@ -1,15 +1,16 @@ diff --git a/apps/whispering/src/routes/(config)/settings/sound/+page.svelte b/apps/whispering/src/routes/(config)/settings/sound/+page.svelte index 4fc57fcbae..c306d283b8 100644 --- a/apps/whispering/src/routes/(config)/settings/sound/+page.svelte +++ b/apps/whispering/src/routes/(config)/settings/sound/+page.svelte @@ -1,7 +1,7 @@ diff --git a/apps/whispering/src/routes/(config)/settings/transcription/+page.svelte b/apps/whispering/src/routes/(config)/settings/transcription/+page.svelte index fdab1ddd5e..c129d36865 100644 --- a/apps/whispering/src/routes/(config)/settings/transcription/+page.svelte +++ b/apps/whispering/src/routes/(config)/settings/transcription/+page.svelte @@ -1,42 +1,108 @@ @@ -71,8 +137,8 @@ id="openai-model" label="OpenAI Model" items={OPENAI_TRANSCRIPTION_MODELS.map((model) => ({ - value: model.name, label: model.name, + value: model.name, ...model, }))} selected={settings.value['transcription.openai.model']} @@ -99,8 +165,8 @@ id="groq-model" label="Groq Model" items={GROQ_MODELS.map((model) => ({ - value: model.name, label: model.name, + value: model.name, ...model, }))} selected={settings.value['transcription.groq.model']} @@ -127,8 +193,8 @@ id="deepgram-model" label="Deepgram Model" items={DEEPGRAM_TRANSCRIPTION_MODELS.map((model) => ({ - value: model.name, label: model.name, + value: model.name, ...model, }))} selected={settings.value['transcription.deepgram.model']} @@ -143,8 +209,8 @@ id="elevenlabs-model" label="ElevenLabs Model" items={ELEVENLABS_TRANSCRIPTION_MODELS.map((model) => ({ - value: model.name, label: model.name, + value: model.name, ...model, }))} selected={settings.value['transcription.elevenlabs.model']} @@ -407,6 +473,70 @@ placeholder="Select a language" /> + + + + Language Toggle Shortcuts + + Configure up to 3 favorite languages for quick switching via keyboard shortcuts + + + + {#if (settings.value['transcription.favoriteLanguages'] ?? ['en', 'ja', 'zh']).length > 0} + {#each (settings.value['transcription.favoriteLanguages'] ?? ['en', 'ja', 'zh']) as language, i} + {@const slotNumber = i + 1} + + + + Slot {slotNumber} + + + + {getLanguageLabel(language)} + + + Language code: {language} + + + + + Remove (coming soon) + + + {/each} + {/if} + + {#if (settings.value['transcription.favoriteLanguages'] ?? ['en', 'ja', 'zh']).length < 3} + + 💡 Tip: You can add more favorite languages by editing the settings manually + + {/if} + + + + Keyboard shortcuts: + + Toggle between languages: Configure in Settings → Shortcuts + Jump to Slot 1/2/3: Configure in Settings → Shortcuts + + + { + settings.updateKey('transcription.favoriteLanguages', ['en', 'ja', 'zh']); + }} + > + Reset to defaults + + + + + diff --git a/apps/whispering/src/routes/(config)/transformations/+page.svelte b/apps/whispering/src/routes/(config)/transformations/+page.svelte index e16deae4ee..440500ec6f 100644 --- a/apps/whispering/src/routes/(config)/transformations/+page.svelte +++ b/apps/whispering/src/routes/(config)/transformations/+page.svelte @@ -1,7 +1,17 @@ @@ -68,6 +68,13 @@ type="submit" onclick={() => createTransformation.mutate($state.snapshot(transformation), { + onError: (error) => { + rpc.notify.error.execute({ + title: 'Failed to create transformation!', + description: 'Your transformation could not be created.', + action: { error, type: 'more-details' }, + }); + }, onSuccess: () => { isDialogOpen = false; transformation = generateDefaultTransformation(); @@ -77,13 +84,6 @@ 'Your transformation has been created successfully.', }); }, - onError: (error) => { - rpc.notify.error.execute({ - title: 'Failed to create transformation!', - description: 'Your transformation could not be created.', - action: { type: 'more-details', error }, - }); - }, })} > Create diff --git a/apps/whispering/src/routes/(config)/transformations/EditTransformationModal.svelte b/apps/whispering/src/routes/(config)/transformations/EditTransformationModal.svelte index 35c9ab9e34..ad381833e6 100644 --- a/apps/whispering/src/routes/(config)/transformations/EditTransformationModal.svelte +++ b/apps/whispering/src/routes/(config)/transformations/EditTransformationModal.svelte @@ -1,15 +1,17 @@ @@ -141,10 +143,16 @@ onclick={() => { confirmationDialog.open({ title: 'Delete transformation', - subtitle: 'Are you sure? This action cannot be undone.', confirmText: 'Delete', onConfirm: () => { deleteTransformation.mutate($state.snapshot(transformation), { + onError: (error) => { + rpc.notify.error.execute({ + title: 'Failed to delete transformation!', + description: 'Your transformation could not be deleted.', + action: { error, type: 'more-details' }, + }); + }, onSuccess: () => { isDialogOpen = false; rpc.notify.success.execute({ @@ -153,15 +161,9 @@ 'Your transformation has been deleted successfully.', }); }, - onError: (error) => { - rpc.notify.error.execute({ - title: 'Failed to delete transformation!', - description: 'Your transformation could not be deleted.', - action: { type: 'more-details', error }, - }); - }, }); }, + subtitle: 'Are you sure? This action cannot be undone.', }); }} variant="destructive" @@ -182,6 +184,13 @@ { updateTransformation.mutate($state.snapshot(workingCopy), { + onError: (error) => { + rpc.notify.error.execute({ + title: 'Failed to update transformation!', + description: 'Your transformation could not be updated.', + action: { error, type: 'more-details' }, + }); + }, onSuccess: () => { rpc.notify.success.execute({ title: 'Updated transformation!', @@ -190,13 +199,6 @@ }); isDialogOpen = false; }, - onError: (error) => { - rpc.notify.error.execute({ - title: 'Failed to update transformation!', - description: 'Your transformation could not be updated.', - action: { type: 'more-details', error }, - }); - }, }); }} disabled={updateTransformation.isPending || !isWorkingCopyDirty} diff --git a/apps/whispering/src/routes/(config)/transformations/MarkTransformationActiveButton.svelte b/apps/whispering/src/routes/(config)/transformations/MarkTransformationActiveButton.svelte index fe184389c5..cbf8255d57 100644 --- a/apps/whispering/src/routes/(config)/transformations/MarkTransformationActiveButton.svelte +++ b/apps/whispering/src/routes/(config)/transformations/MarkTransformationActiveButton.svelte @@ -1,17 +1,18 @@
+ {getLanguageLabel(language)} +
+ Language code: {language} +
Keyboard shortcuts: