Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions Sources/Fluid/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ enum ShortcutRecordingTarget: Hashable {
case .primaryDictation:
return "Primary Dictation Shortcut"
case .secondaryDictation:
return "Secondary Dictation Shortcut"
return "AI Prompt Dictation Shortcut"
case .command:
return "Command Mode"
case .edit:
Expand Down Expand Up @@ -491,6 +491,9 @@ struct ContentView: View {
}

private func handlePromptShortcutEnabledChange(_ isEnabled: Bool) {
if isEnabled, SettingsStore.shared.dictationPromptSelection(for: .secondary) == .off {
SettingsStore.shared.setDictationPromptSelection(.default, for: .secondary)
Comment on lines +494 to +495

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Select the private-AI prompt when enabling the shortcut

When Private AI is installed and verified and the secondary selection is currently Off, enabling this shortcut forces .default, even though the picker disables external/default prompts in that configuration. DictationAIPostProcessingGate.isConfigured rejects a non-.privateAI selection whose resolved route uses Private AI, so the new “AI Prompt Dictation” shortcut silently produces unprocessed transcription. Select .privateAI when PrivateAIProviderPromptFormat.isAvailable() and use .default otherwise.

Useful? React with 👍 / 👎.

}
SettingsStore.shared.promptModeShortcutEnabled = isEnabled
self.hotkeyManager?.updatePromptModeShortcutEnabled(isEnabled)

Expand Down Expand Up @@ -1147,8 +1150,7 @@ struct ContentView: View {
switch target {
case .secondaryDictation:
self.isPromptModeShortcutEnabled = enabled
SettingsStore.shared.promptModeShortcutEnabled = enabled
self.hotkeyManager?.updatePromptModeShortcutEnabled(enabled)
self.handlePromptShortcutEnabledChange(enabled)
case .command:
self.isCommandModeShortcutEnabled = enabled
SettingsStore.shared.commandModeShortcutEnabled = enabled
Expand Down Expand Up @@ -1773,13 +1775,15 @@ struct ContentView: View {
primaryDictationShortcuts: self.$primaryDictationShortcuts,
activeShortcutRecordingTarget: self.$activeShortcutRecordingTarget,
shortcutRecordingMessage: self.$shortcutRecordingMessage,
promptModeShortcut: self.$promptModeHotkeyShortcut,
commandModeShortcut: self.$commandModeHotkeyShortcut,
rewriteShortcut: self.$rewriteModeHotkeyShortcut,
cancelRecordingShortcut: self.$cancelRecordingHotkeyShortcut,
pasteLastTranscriptionShortcut: self.$pasteLastTranscriptionHotkeyShortcut,
commandModeShortcutEnabled: self.$isCommandModeShortcutEnabled,
rewriteShortcutEnabled: self.$isRewriteModeShortcutEnabled,
pasteLastTranscriptionShortcutEnabled: self.$isPasteLastTranscriptionShortcutEnabled,
promptModeShortcutEnabled: self.$isPromptModeShortcutEnabled,
hotkeyManagerInitialized: self.$hotkeyManagerInitialized,
hotkeyMode: self.$hotkeyMode,
enableStreamingPreview: self.$enableStreamingPreview,
Expand Down
24 changes: 24 additions & 0 deletions Sources/Fluid/UI/SettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ struct SettingsView: View {
@Binding var primaryDictationShortcuts: [HotkeyShortcut]
@Binding var activeShortcutRecordingTarget: ShortcutRecordingTarget?
@Binding var shortcutRecordingMessage: String?
@Binding var promptModeShortcut: HotkeyShortcut
@Binding var commandModeShortcut: HotkeyShortcut?
@Binding var rewriteShortcut: HotkeyShortcut
@Binding var cancelRecordingShortcut: HotkeyShortcut
@Binding var pasteLastTranscriptionShortcut: HotkeyShortcut?
@Binding var commandModeShortcutEnabled: Bool
@Binding var rewriteShortcutEnabled: Bool
@Binding var pasteLastTranscriptionShortcutEnabled: Bool
@Binding var promptModeShortcutEnabled: Bool
@Binding var hotkeyManagerInitialized: Bool
@Binding var hotkeyMode: HotkeyActivationMode
@Binding var enableStreamingPreview: Bool
Expand Down Expand Up @@ -709,6 +711,28 @@ struct SettingsView: View {
self.dictationPromptPicker(for: .primary)
Divider().opacity(0.2).padding(.vertical, 4)

self.shortcutRow(
content: .init(
icon: "sparkles",
iconColor: .secondary,
title: "AI Prompt Dictation",
description: "Transcribe and improve speech with a selected AI prompt"
Comment on lines +718 to +719

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Add the new shortcut to settings search

The new row has neither a SettingsSearchTarget nor an entry in SettingsSearchIndex.entries, unlike each surrounding shortcut setting. Consequently, searching for the exact visible name “AI Prompt Dictation” produces no result and shows the no-matches state, making this newly exposed control undiscoverable through the settings search. Add a dedicated target/index entry and attach it to this row.

Useful? React with 👍 / 👎.

),
shortcut: self.promptModeShortcut,
isRecording: self.isRecording(.secondaryDictation),
isAnyRecordingActive: self.isRecordingAnyShortcut,
recordingMessage: self.isRecording(.secondaryDictation) ? self.shortcutRecordingMessage : nil,
isEnabled: self.$promptModeShortcutEnabled,
requiresShortcutToEnable: true,
Comment on lines +725 to +726

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate the stored shortcut before enabling it

If the disabled prompt-mode shortcut overlaps a shortcut configured while it was disabled—for example, primary dictation was changed to the default prompt shortcut, Right Shift—this toggle enables it without running shortcutConflictMessage. GlobalHotkeyManager checks prompt mode before primary dictation, so the existing primary shortcut is then hijacked by prompt mode. Validate conflicts on enable or require recording a nonconflicting shortcut before activation.

Useful? React with 👍 / 👎.

onChangePressed: {
DebugLogger.shared.debug("Starting to record new AI prompt shortcut", source: "SettingsView")
self.shortcutRecordingMessage = nil
self.activeShortcutRecordingTarget = .secondaryDictation
}
)
self.dictationPromptPicker(for: .secondary)
Comment on lines +714 to +733

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 AI shortcut omitted from search

The new shortcut row and secondary prompt picker have no settings-search target or anchor, so searches for terms such as “AI Prompt” or “secondary” cannot navigate to or highlight these controls and can surface unrelated settings instead.

Knowledge Base Used: Settings and onboarding

Prompt To Fix With AI
This is a comment left during a code review.
Path: Sources/Fluid/UI/SettingsView.swift
Line: 714-733

Comment:
**AI shortcut omitted from search**

The new shortcut row and secondary prompt picker have no settings-search target or anchor, so searches for terms such as “AI Prompt” or “secondary” cannot navigate to or highlight these controls and can surface unrelated settings instead.

**Knowledge Base Used:** [Settings and onboarding](https://app.greptile.com/altic/-/custom-context/knowledge-base/altic-dev/fluidvoice/-/docs/settings-and-onboarding.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex

Divider().opacity(0.2).padding(.vertical, 4)

self.shortcutRow(
content: .init(
icon: "terminal.fill",
Expand Down
Loading