diff --git a/VoiceInk/HotkeyManager.swift b/VoiceInk/HotkeyManager.swift index 1198db8..46787fd 100644 --- a/VoiceInk/HotkeyManager.swift +++ b/VoiceInk/HotkeyManager.swift @@ -7,6 +7,7 @@ extension KeyboardShortcuts.Name { static let toggleMiniRecorder = Self("toggleMiniRecorder") static let toggleMiniRecorder2 = Self("toggleMiniRecorder2") static let pasteLastTranscription = Self("pasteLastTranscription") + static let pasteLastEnhancement = Self("pasteLastEnhancement") static let retryLastTranscription = Self("retryLastTranscription") } @@ -434,5 +435,3 @@ class HotkeyManager: ObservableObject { } } } - - diff --git a/VoiceInk/Services/LastTranscriptionService.swift b/VoiceInk/Services/LastTranscriptionService.swift index 4ef46fa..28899e4 100644 --- a/VoiceInk/Services/LastTranscriptionService.swift +++ b/VoiceInk/Services/LastTranscriptionService.swift @@ -29,7 +29,7 @@ class LastTranscriptionService: ObservableObject { return } - let success = ClipboardManager.copyToClipboard(lastTranscription.enhancedText?.isEmpty == false ? lastTranscription.enhancedText! : lastTranscription.text) + let success = ClipboardManager.copyToClipboard(lastTranscription.text) Task { @MainActor in if success { @@ -57,13 +57,7 @@ class LastTranscriptionService: ObservableObject { return } - // Use enhanced text if available and not empty, otherwise use original text - let textToPaste: String - if let enhancedText = lastTranscription.enhancedText, !enhancedText.isEmpty { - textToPaste = enhancedText - } else { - textToPaste = lastTranscription.text - } + let textToPaste = lastTranscription.text // Delay to give the user time to release modifier keys (especially Control) DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) { @@ -71,6 +65,29 @@ class LastTranscriptionService: ObservableObject { } } + static func pasteLastEnhancement(from modelContext: ModelContext) { + guard let lastTranscription = getLastTranscription(from: modelContext) else { + Task { @MainActor in + NotificationManager.shared.showNotification( + title: "No transcription available", + type: .error + ) + } + return + } + + // Only paste if enhancement exists; this includes actual enhancement text or an error message saved in enhancedText. + guard let enhancedText = lastTranscription.enhancedText, !enhancedText.isEmpty else { + // Per requirements, do nothing when there is no enhancement. + return + } + + // Delay to allow modifier keys to be released + DispatchQueue.main.asyncAfter(deadline: .now() + 0.15) { + CursorPaster.pasteAtCursor(enhancedText + " ") + } + } + static func retryLastTranscription(from modelContext: ModelContext, whisperState: WhisperState) { Task { @MainActor in guard let lastTranscription = getLastTranscription(from: modelContext), @@ -111,4 +128,4 @@ class LastTranscriptionService: ObservableObject { } } } -} \ No newline at end of file +} \ No newline at end of file diff --git a/VoiceInk/Views/Settings/SettingsView.swift b/VoiceInk/Views/Settings/SettingsView.swift index cb9d354..54c219f 100644 --- a/VoiceInk/Views/Settings/SettingsView.swift +++ b/VoiceInk/Views/Settings/SettingsView.swift @@ -91,6 +91,26 @@ struct SettingsView: View { Spacer() } + // Paste Last Enhancement + HStack(spacing: 12) { + Text("Paste Last Enhancement") + .font(.system(size: 13, weight: .medium)) + .foregroundColor(.secondary) + + KeyboardShortcuts.Recorder(for: .pasteLastEnhancement) + .controlSize(.small) + + InfoTip( + title: "Paste Last Enhancement", + message: "Shortcut for pasting the most recent AI-enhanced text. If no enhancement exists, nothing is pasted. If the enhancement failed, the error message is pasted." + ) + + Spacer() + } + + // Add separator after Paste Last Enhancement + Divider() + // Retry Last Transcription HStack(spacing: 12) { Text("Retry Last Transcription") @@ -108,6 +128,8 @@ struct SettingsView: View { Spacer() } + Divider() + // Custom Cancel Shortcut @@ -145,6 +167,8 @@ struct SettingsView: View { } } + Divider() + // Middle-Click Toggle VStack(alignment: .leading, spacing: 12) { HStack(spacing: 8) {