Skip to content

Commit 25b3d7f

Browse files
committed
Refine feature settings UI copy and layout
1 parent a5c9678 commit 25b3d7f

10 files changed

Lines changed: 507 additions & 81 deletions

Voxt/Settings/FeatureSettingsPageSections+LanguageTools.swift

Lines changed: 23 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,27 @@ extension FeatureSettingsView {
66
title: featureSettingsLocalized("Translation"),
77
subtitle: featureSettingsLocalized("Configure the speech path, translation engine, target language, and prompt behavior for translation mode."),
88
iconKind: .translation,
9-
pills: translationPills
9+
pills: translationPills,
10+
showsHeroHeader: false
1011
) {
11-
FeatureSettingsCard(title: featureSettingsLocalized("Translation Flow")) {
12-
FeatureSettingSection(title: featureSettingsLocalized("Speech Recognition"), detail: featureSettingsLocalized("Choose the ASR model that feeds the translation pipeline.")) {
12+
FeatureSettingsCard(title: "") {
13+
FeatureSettingSection(title: "", detail: "") {
1314
FeatureSelectorRow(
14-
title: featureSettingsLocalized("ASR Model"),
15+
title: featureSettingsLocalized("Speech Model"),
1516
value: asrSelectionSummary(featureSettings.translation.asrSelectionID),
1617
action: { selectorSheet = .translationASR }
1718
)
1819
}
1920

20-
FeatureSettingSection(title: featureSettingsLocalized("Translation Model"), detail: featureSettingsLocalized("Select an LLM or use Whisper direct translation when the ASR path supports it.")) {
21+
FeatureSettingSection(title: "", detail: "") {
2122
FeatureSelectorRow(
2223
title: featureSettingsLocalized("Translation Model"),
2324
value: translationSelectionSummary(featureSettings.translation.modelSelectionID),
2425
action: { selectorSheet = .translationModel }
2526
)
2627
}
2728

28-
FeatureInlinePickerRow(title: featureSettingsLocalized("Target Language"), detail: featureSettingsLocalized("Move the shared translation language setting here so the behavior stays feature-local.")) {
29+
FeatureInlinePickerRow(title: featureSettingsLocalized("Target Language"), detail: "") {
2930
SettingsMenuPicker(
3031
selection: binding(
3132
get: { featureSettings.translation.targetLanguage },
@@ -41,28 +42,17 @@ extension FeatureSettingsView {
4142

4243
FeatureEmbeddedFieldGroup {
4344
FeatureToggleRow(
44-
title: featureSettingsLocalized("Translate selected text with translation shortcut"),
45-
detail: featureSettingsLocalized("If text is selected, the translation shortcut translates the selection directly instead of starting a recording."),
45+
title: featureSettingsLocalized("Show Translation Result for Selected Text"),
46+
detail: "",
4647
isOn: binding(
47-
get: { featureSettings.translation.replaceSelectedText },
48-
set: { featureSettings.translation.replaceSelectedText = $0 }
48+
get: { featureSettings.translation.showResultWindow },
49+
set: { featureSettings.translation.showResultWindow = $0 }
4950
)
5051
)
51-
52-
if featureSettings.translation.replaceSelectedText {
53-
FeatureToggleRow(
54-
title: featureSettingsLocalized("Replace Selected Text"),
55-
detail: featureSettingsLocalized("When enabled, selected-text translation replaces the current selection directly. When disabled, Voxt opens a result window after completion instead."),
56-
isOn: binding(
57-
get: { !featureSettings.translation.showResultWindow },
58-
set: { featureSettings.translation.showResultWindow = !$0 }
59-
)
60-
)
61-
}
6252
}
6353

6454
if featureSettings.translation.modelSelectionID.translationSelection != .whisperDirectTranslate {
65-
FeatureSettingSection(title: featureSettingsLocalized("Prompt"), detail: featureSettingsLocalized("Prompt controls are shown only when the selected translation model supports prompt-based generation.")) {
55+
FeatureSettingSection(title: "", detail: "") {
6656
FeaturePromptSection(
6757
title: featureSettingsLocalized("Translation Prompt"),
6858
text: promptBinding(
@@ -72,7 +62,7 @@ extension FeatureSettingsView {
7262
),
7363
defaultText: AppPromptDefaults.text(for: .translation),
7464
variables: ModelSettingsPromptVariables.translation,
75-
guidance: PromptAuthoringGuidance.translation,
65+
guidance: "",
7666
persistChanges: { prompt in
7767
FeatureSettingsStore.saveTranslationPrompt(prompt)
7868
}
@@ -93,26 +83,27 @@ extension FeatureSettingsView {
9383
title: featureSettingsLocalized("Rewrite"),
9484
subtitle: featureSettingsLocalized("Set the ASR and text model pairing used for rewrite mode, then tune the rewrite-specific prompt and follow-up shortcut."),
9585
iconKind: .rewrite,
96-
pills: rewritePills
86+
pills: rewritePills,
87+
showsHeroHeader: false
9788
) {
98-
FeatureSettingsCard(title: featureSettingsLocalized("Rewrite Flow")) {
99-
FeatureSettingSection(title: featureSettingsLocalized("Speech Recognition"), detail: featureSettingsLocalized("Choose the speech model that feeds rewrite mode.")) {
89+
FeatureSettingsCard(title: "") {
90+
FeatureSettingSection(title: "", detail: "") {
10091
FeatureSelectorRow(
101-
title: featureSettingsLocalized("ASR Model"),
92+
title: featureSettingsLocalized("Speech Model"),
10293
value: asrSelectionSummary(featureSettings.rewrite.asrSelectionID),
10394
action: { selectorSheet = .rewriteASR }
10495
)
10596
}
10697

107-
FeatureSettingSection(title: featureSettingsLocalized("Rewrite Model"), detail: featureSettingsLocalized("Pick the text model used to rewrite, rephrase, or clean captured content.")) {
98+
FeatureSettingSection(title: "", detail: "") {
10899
FeatureSelectorRow(
109-
title: featureSettingsLocalized("LLM Model"),
100+
title: featureSettingsLocalized("Enhancement Model"),
110101
value: llmSelectionSummary(featureSettings.rewrite.llmSelectionID),
111102
action: { selectorSheet = .rewriteLLM }
112103
)
113104
}
114105

115-
FeatureSettingSection(title: featureSettingsLocalized("Prompt"), detail: featureSettingsLocalized("Prompt templates stay local to rewrite mode and no longer live in the shared model page.")) {
106+
FeatureSettingSection(title: "", detail: "") {
116107
FeaturePromptSection(
117108
title: featureSettingsLocalized("Rewrite Prompt"),
118109
text: promptBinding(
@@ -122,7 +113,7 @@ extension FeatureSettingsView {
122113
),
123114
defaultText: AppPromptDefaults.text(for: .rewrite),
124115
variables: ModelSettingsPromptVariables.rewrite,
125-
guidance: PromptAuthoringGuidance.rewrite,
116+
guidance: "",
126117
persistChanges: { prompt in
127118
FeatureSettingsStore.saveRewritePrompt(prompt)
128119
}
@@ -131,7 +122,7 @@ extension FeatureSettingsView {
131122

132123
FeatureContinueShortcutRow(
133124
title: featureSettingsLocalized("Continue Shortcut"),
134-
detail: featureSettingsLocalized("Use this key in rewrite continue mode to start the next follow-up recording from the OverLazy answer view."),
125+
detail: "",
135126
shortcut: binding(
136127
get: { featureSettings.rewrite.continueShortcut },
137128
set: { featureSettings.rewrite.continueShortcut = $0 }

Voxt/Settings/FeatureSettingsPageSections+Transcription.swift

Lines changed: 32 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4,47 +4,30 @@ extension FeatureSettingsView {
44
var transcriptionContent: some View {
55
featurePage(
66
title: featureSettingsLocalized("Transcription"),
7-
subtitle: featureSettingsLocalized("Choose the speech model for standard transcription, then optionally add LLM cleanup and app-aware enhancement."),
7+
subtitle: featureSettingsLocalized("Choose a speech model, then add text enhancement if needed."),
88
iconKind: .transcription,
9-
pills: transcriptionPills
9+
pills: transcriptionPills,
10+
showsHeroHeader: false
1011
) {
11-
FeatureSettingsCard(title: featureSettingsLocalized("Model Pipeline")) {
12-
FeatureSettingSection(title: featureSettingsLocalized("Speech Recognition"), detail: featureSettingsLocalized("This model handles the first-pass transcript.")) {
12+
FeatureSettingsCard(title: "") {
13+
FeatureSettingSection(title: "", detail: "") {
1314
FeatureSelectorRow(
14-
title: featureSettingsLocalized("ASR Model"),
15+
title: featureSettingsLocalized("Speech Model"),
1516
value: asrSelectionSummary(featureSettings.transcription.asrSelectionID),
1617
action: { selectorSheet = .transcriptionASR }
1718
)
1819
}
1920

2021
FeatureToggleRow(
21-
title: featureSettingsLocalized("Enable LLM Enhancement"),
22-
detail: featureSettingsLocalized("Use a second language model pass to clean punctuation, structure, and readability."),
22+
title: featureSettingsLocalized("Text Enhancement"),
23+
detail: "",
2324
isOn: transcriptionLLMEnabledBinding
2425
)
2526

26-
FeatureToggleRow(
27-
title: featureSettingsLocalized("Enable App Enhancement"),
28-
detail: featureSettingsLocalized("Use different enhancement prompts for different apps or browser pages."),
29-
isOn: binding(
30-
get: { featureSettings.rewrite.appEnhancementEnabled },
31-
set: { featureSettings.rewrite.appEnhancementEnabled = $0 }
32-
)
33-
)
34-
35-
FeatureToggleRow(
36-
title: featureSettingsLocalized("Enable Notes"),
37-
detail: featureSettingsLocalized("Add segmented notes during transcription. Once enabled, Notes appears in the Feature menu and supports a dedicated trigger key."),
38-
isOn: binding(
39-
get: { featureSettings.transcription.notes.enabled },
40-
set: { featureSettings.transcription.notes.enabled = $0 }
41-
)
42-
)
43-
4427
if featureSettings.transcription.llmEnabled {
45-
FeatureSettingSection(title: featureSettingsLocalized("Text Enhancement"), detail: featureSettingsLocalized("Only configured and installed models can be selected here.")) {
28+
FeatureSettingSection(title: "", detail: "") {
4629
FeatureSelectorRow(
47-
title: featureSettingsLocalized("LLM Model"),
30+
title: featureSettingsLocalized("Enhancement Model"),
4831
value: llmSelectionSummary(featureSettings.transcription.llmSelectionID),
4932
action: { selectorSheet = .transcriptionLLM }
5033
)
@@ -57,13 +40,22 @@ extension FeatureSettingsView {
5740
),
5841
defaultText: AppPromptDefaults.text(for: .enhancement),
5942
variables: ModelSettingsPromptVariables.enhancement,
60-
guidance: PromptAuthoringGuidance.enhancement,
43+
guidance: "",
6144
persistChanges: { prompt in
6245
FeatureSettingsStore.saveTranscriptionPrompt(prompt)
6346
}
6447
)
6548
}
6649
}
50+
51+
FeatureToggleRow(
52+
title: featureSettingsLocalized("Notes"),
53+
detail: "",
54+
isOn: binding(
55+
get: { featureSettings.transcription.notes.enabled },
56+
set: { featureSettings.transcription.notes.enabled = $0 }
57+
)
58+
)
6759
}
6860
}
6961
}
@@ -73,29 +65,30 @@ extension FeatureSettingsView {
7365
title: featureSettingsLocalized("Notes"),
7466
subtitle: featureSettingsLocalized("Capture key points during recording. Notes stay separate and get short AI titles."),
7567
iconKind: .note,
76-
pills: notePills
68+
pills: notePills,
69+
showsHeroHeader: false
7770
) {
78-
FeatureSettingsCard(title: featureSettingsLocalized("Notes Workflow")) {
71+
FeatureSettingsCard(title: "") {
7972
FeatureNoteShortcutRow(
80-
title: featureSettingsLocalized("Note Trigger"),
73+
title: featureSettingsLocalized("Trigger Key"),
8174
detail: featureSettingsLocalized("Use this key while a live transcription session is recording to save the current transcript tail as a note and insert a note marker into the OverLazy preview."),
8275
shortcut: binding(
8376
get: { featureSettings.transcription.notes.triggerShortcut },
8477
set: { featureSettings.transcription.notes.triggerShortcut = $0 }
8578
)
8679
)
8780

88-
FeatureSettingSection(title: featureSettingsLocalized("Title Generation"), detail: featureSettingsLocalized("This model generates the short floating-card title for each saved note.")) {
81+
FeatureSettingSection(title: "", detail: "") {
8982
FeatureSelectorRow(
90-
title: featureSettingsLocalized("Note Title Model"),
83+
title: featureSettingsLocalized("Title Model"),
9184
value: llmSelectionSummary(featureSettings.transcription.notes.titleModelSelectionID),
9285
action: { selectorSheet = .transcriptionNoteTitle }
9386
)
9487
}
9588

9689
FeatureToggleRow(
97-
title: featureSettingsLocalized("Note Audio"),
98-
detail: featureSettingsLocalized("Play a short reminder sound each time the note trigger is pressed during a live transcription session."),
90+
title: featureSettingsLocalized("Sound"),
91+
detail: "",
9992
isOn: binding(
10093
get: { featureSettings.transcription.notes.soundEnabled },
10194
set: { featureSettings.transcription.notes.soundEnabled = $0 }
@@ -104,8 +97,8 @@ extension FeatureSettingsView {
10497

10598
if featureSettings.transcription.notes.soundEnabled {
10699
FeatureNoteSoundPresetRow(
107-
title: featureSettingsLocalized("Note Sound Preset"),
108-
detail: featureSettingsLocalized("Choose the reminder sound used when a note is captured, and preview it here."),
100+
title: featureSettingsLocalized("Sound Preset"),
101+
detail: "",
109102
picker: {
110103
SettingsMenuPicker(
111104
selection: binding(
@@ -126,14 +119,14 @@ extension FeatureSettingsView {
126119
}
127120

128121
FeatureSettingSection(
129-
title: featureSettingsLocalized("Obsidian Sync"),
122+
title: "",
130123
detail: ""
131124
) {
132125
noteObsidianSyncSection
133126
}
134127

135128
FeatureSettingSection(
136-
title: featureSettingsLocalized("Reminders Sync"),
129+
title: "",
137130
detail: ""
138131
) {
139132
noteRemindersSyncSection

Voxt/Settings/FeatureSettingsPageSupport.swift

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,14 @@ extension FeatureSettingsView {
6767

6868
var rewritePills: [FeatureSummaryPill] {
6969
[
70-
FeatureSummaryPill(title: featureSettingsLocalized("Audio Model"), value: shortSummary(asrSelectionSummary(featureSettings.rewrite.asrSelectionID))),
71-
FeatureSummaryPill(title: featureSettingsLocalized("Enhancement Model"), value: shortSummary(llmSelectionSummary(featureSettings.rewrite.llmSelectionID)))
70+
FeatureSummaryPill(
71+
title: featureSettingsLocalized("Audio Model"),
72+
value: shortSummary(asrSelectionSummary(featureSettings.rewrite.asrSelectionID), maxLength: 52)
73+
),
74+
FeatureSummaryPill(
75+
title: featureSettingsLocalized("Enhancement Model"),
76+
value: shortSummary(llmSelectionSummary(featureSettings.rewrite.llmSelectionID), maxLength: 52)
77+
)
7278
]
7379
}
7480

@@ -85,17 +91,20 @@ extension FeatureSettingsView {
8591
iconKind: SettingsSidebarIconKind? = nil,
8692
systemImageName: String? = nil,
8793
pills: [FeatureSummaryPill],
94+
showsHeroHeader: Bool = true,
8895
@ViewBuilder content: () -> Content
8996
) -> some View {
9097
ScrollView {
9198
VStack(alignment: .leading, spacing: 18) {
92-
FeatureHeroCard(
93-
title: title,
94-
subtitle: subtitle,
95-
iconKind: iconKind,
96-
systemImageName: systemImageName,
97-
pills: pills
98-
)
99+
if showsHeroHeader || !pills.isEmpty {
100+
FeatureHeroCard(
101+
title: showsHeroHeader ? title : "",
102+
subtitle: showsHeroHeader ? subtitle : "",
103+
iconKind: showsHeroHeader ? iconKind : nil,
104+
systemImageName: showsHeroHeader ? systemImageName : nil,
105+
pills: pills
106+
)
107+
}
99108

100109
content()
101110
}

Voxt/Settings/FeatureShortcutSettingsComponents.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ struct FeatureShortcutCaptureRow: View {
1717
@State private var pendingCapturedHotkey: HotkeyPreference.Hotkey?
1818

1919
var body: some View {
20-
VStack(alignment: .leading, spacing: 12) {
20+
VStack(alignment: .leading, spacing: showsHeader ? 12 : 0) {
2121
if showsHeader {
2222
VStack(alignment: .leading, spacing: 4) {
2323
Text(title)
@@ -141,12 +141,14 @@ struct FeatureNoteShortcutRow: View {
141141
struct FeatureContinueShortcutRow: View {
142142
let title: String
143143
let detail: String
144+
var showsHeader = false
144145
@Binding var shortcut: TranscriptionContinueShortcutSettings
145146

146147
var body: some View {
147148
FeatureShortcutCaptureRow(
148149
title: title,
149150
detail: detail,
151+
showsHeader: showsHeader,
150152
hotkey: Binding(
151153
get: { shortcut.hotkey },
152154
set: { capturedHotkey in

0 commit comments

Comments
 (0)