Skip to content

Commit bd8f0fb

Browse files
author
mgabor3141
committed
Split GAAV mode into separate text formatting settings
- Replace single GAAV mode toggle with three independent settings: - Uppercase First Letter (default: on) - Add Trailing Period (default: on) - Add Trailing Space (default: off, new feature) - Use positive framing for all settings (on = apply formatting) - Add automatic migration from legacy GAAV mode setting - Preserve existing behavior for users with GAAV enabled - Update UI to group settings under 'Text Formatting' section - Rename applyGAAVFormatting to applyTranscriptionFormatting - Add double-space prevention for trailing space feature
1 parent 501428b commit bd8f0fb

File tree

4 files changed

+111
-30
lines changed

4 files changed

+111
-30
lines changed

Sources/Fluid/ContentView.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,7 +1523,7 @@ struct ContentView: View {
15231523
}
15241524

15251525
let result = await self.processTextWithAI(transcribedText, overrideSystemPrompt: promptTest.draftPromptText)
1526-
let finalText = ASRService.applyGAAVFormatting(result)
1526+
let finalText = ASRService.applyTranscriptionFormatting(result)
15271527
promptTest.lastOutputText = finalText
15281528
return
15291529
}
@@ -1579,9 +1579,9 @@ struct ContentView: View {
15791579
self.menuBarManager.setProcessing(false)
15801580
}
15811581

1582-
// Apply GAAV formatting as the FINAL step (after AI post-processing)
1583-
// This ensures the user's preference for no capitalization/period is respected
1584-
finalText = ASRService.applyGAAVFormatting(finalText)
1582+
// Apply text formatting as the FINAL step (after AI post-processing)
1583+
// This ensures the user's formatting preferences are respected
1584+
finalText = ASRService.applyTranscriptionFormatting(finalText)
15851585

15861586
DebugLogger.shared.info("Transcription finalized (chars: \(finalText.count))", source: "ContentView")
15871587

Sources/Fluid/Persistence/SettingsStore.swift

Lines changed: 50 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ final class SettingsStore: ObservableObject {
1717
self.migrateProviderAPIKeysIfNeeded()
1818
self.scrubSavedProviderAPIKeys()
1919
self.migrateDictationPromptProfilesIfNeeded()
20+
self.migrateGAAVModeIfNeeded()
2021
}
2122

2223
// Keys
@@ -82,8 +83,14 @@ final class SettingsStore: ObservableObject {
8283
static let removeFillerWordsEnabled = "RemoveFillerWordsEnabled"
8384

8485
// GAAV Mode (removes capitalization and trailing punctuation)
86+
// Legacy key - kept for migration purposes
8587
static let gaavModeEnabled = "GAAVModeEnabled"
8688

89+
// Text Formatting Options (replaces GAAV Mode)
90+
static let uppercaseFirstLetter = "UppercaseFirstLetter"
91+
static let addTrailingPeriod = "AddTrailingPeriod"
92+
static let insertTrailingSpace = "InsertTrailingSpace"
93+
8794
// Custom Dictionary
8895
static let customDictionaryEntries = "CustomDictionaryEntries"
8996

@@ -1253,6 +1260,26 @@ final class SettingsStore: ObservableObject {
12531260
DebugLogger.shared.info("Migrated legacy custom dictation prompt to a prompt profile", source: "SettingsStore")
12541261
}
12551262

1263+
private func migrateGAAVModeIfNeeded() {
1264+
// Migration path from legacy GAAV mode to separate text formatting settings.
1265+
// If user had GAAV mode enabled, disable both uppercase and period (inverted logic).
1266+
guard let legacyValue = defaults.object(forKey: Keys.gaavModeEnabled) as? Bool,
1267+
legacyValue == true else {
1268+
// No migration needed - either never set or was false
1269+
return
1270+
}
1271+
1272+
// Migrate: GAAV enabled → disable uppercase and period (inverted from old behavior)
1273+
self.uppercaseFirstLetter = false
1274+
self.addTrailingPeriod = false
1275+
// Note: insertTrailingSpace stays false (new feature, not part of original GAAV)
1276+
1277+
// Remove legacy key to prevent re-migration
1278+
defaults.removeObject(forKey: Keys.gaavModeEnabled)
1279+
1280+
DebugLogger.shared.info("Migrated GAAV mode to separate text formatting settings", source: "SettingsStore")
1281+
}
1282+
12561283
private func scrubSavedProviderAPIKeys() {
12571284
guard let data = defaults.data(forKey: Keys.savedProviders),
12581285
var decoded = try? JSONDecoder().decode([SavedProvider].self, from: data) else { return }
@@ -1429,16 +1456,32 @@ final class SettingsStore: ObservableObject {
14291456
}
14301457
}
14311458

1432-
// MARK: - GAAV Mode
1459+
// MARK: - Text Formatting Options
1460+
1461+
/// Automatically capitalize the first letter of transcriptions.
1462+
var uppercaseFirstLetter: Bool {
1463+
get { self.defaults.object(forKey: Keys.uppercaseFirstLetter) as? Bool ?? true }
1464+
set {
1465+
objectWillChange.send()
1466+
self.defaults.set(newValue, forKey: Keys.uppercaseFirstLetter)
1467+
}
1468+
}
1469+
1470+
/// Add a period at the end of transcriptions.
1471+
var addTrailingPeriod: Bool {
1472+
get { self.defaults.object(forKey: Keys.addTrailingPeriod) as? Bool ?? true }
1473+
set {
1474+
objectWillChange.send()
1475+
self.defaults.set(newValue, forKey: Keys.addTrailingPeriod)
1476+
}
1477+
}
14331478

1434-
/// GAAV Mode: Removes first letter capitalization and trailing period from transcriptions.
1435-
/// Useful for search queries, form fields, or casual text input where sentence formatting is unwanted.
1436-
/// Feature requested by maxgaav – thank you for the suggestion!
1437-
var gaavModeEnabled: Bool {
1438-
get { self.defaults.object(forKey: Keys.gaavModeEnabled) as? Bool ?? false }
1479+
/// Insert a space after the transcription for easier continuation.
1480+
var insertTrailingSpace: Bool {
1481+
get { self.defaults.object(forKey: Keys.insertTrailingSpace) as? Bool ?? false }
14391482
set {
14401483
objectWillChange.send()
1441-
self.defaults.set(newValue, forKey: Keys.gaavModeEnabled)
1484+
self.defaults.set(newValue, forKey: Keys.insertTrailingSpace)
14421485
}
14431486
}
14441487

Sources/Fluid/Services/ASRService.swift

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2220,26 +2220,33 @@ final class ASRService: ObservableObject {
22202220
return result
22212221
}
22222222

2223-
// MARK: - GAAV Mode Formatting
2223+
// MARK: - Text Formatting
22242224

2225-
/// Applies GAAV mode formatting: removes first letter capitalization and trailing period.
2226-
/// This is useful for search queries, form fields, or casual text input.
2227-
///
2228-
/// Feature requested by maxgaav – thank you for the suggestion!
2229-
static func applyGAAVFormatting(_ text: String) -> String {
2230-
guard SettingsStore.shared.gaavModeEnabled else { return text }
2225+
/// Applies user-configured text formatting options:
2226+
/// - Uppercase first letter: capitalizes the first character
2227+
/// - Add trailing period: adds a period at the end
2228+
/// - Insert trailing space: adds a space after the transcription
2229+
static func applyTranscriptionFormatting(_ text: String) -> String {
22312230
guard !text.isEmpty else { return text }
22322231

22332232
var result = text
2233+
let settings = SettingsStore.shared
2234+
2235+
// Lowercase the first character (if uppercase setting is disabled)
2236+
if !settings.uppercaseFirstLetter,
2237+
let first = result.first, first.isUppercase
2238+
{
2239+
result = first.lowercased() + result.dropFirst()
2240+
}
22342241

2235-
// Remove trailing period (if present)
2236-
if result.hasSuffix(".") {
2242+
// Remove trailing period (if period setting is disabled and one exists)
2243+
if !settings.addTrailingPeriod && result.hasSuffix(".") {
22372244
result.removeLast()
22382245
}
22392246

2240-
// Lowercase the first character (if it's uppercase)
2241-
if let first = result.first, first.isUppercase {
2242-
result = first.lowercased() + result.dropFirst()
2247+
// Add trailing space (if setting enabled, result is non-empty, and doesn't already end with space)
2248+
if settings.insertTrailingSpace && !result.isEmpty && !result.hasSuffix(" ") {
2249+
result += " "
22432250
}
22442251

22452252
return result

Sources/Fluid/UI/SettingsView.swift

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -509,14 +509,45 @@ struct SettingsView: View {
509509
)
510510
Divider().opacity(0.2)
511511

512-
self.optionToggleRow(
513-
title: "GAAV Mode",
514-
description: "Remove first letter capitalization and trailing period. Useful for search queries, form fields, or casual text.\nFeature requested by MaxGaav.",
515-
isOn: Binding(
516-
get: { SettingsStore.shared.gaavModeEnabled },
517-
set: { SettingsStore.shared.gaavModeEnabled = $0 }
512+
// MARK: - Text Formatting Section
513+
514+
VStack(alignment: .leading, spacing: 8) {
515+
Text("Text Formatting")
516+
.font(.subheadline.weight(.medium))
517+
.foregroundStyle(.secondary)
518+
.padding(.bottom, 4)
519+
520+
self.optionToggleRow(
521+
title: "Uppercase First Letter",
522+
description: "Automatically capitalize the first letter of transcriptions.",
523+
isOn: Binding(
524+
get: { SettingsStore.shared.uppercaseFirstLetter },
525+
set: { SettingsStore.shared.uppercaseFirstLetter = $0 }
526+
)
518527
)
519-
)
528+
Divider().opacity(0.2)
529+
530+
self.optionToggleRow(
531+
title: "Add Trailing Period",
532+
description: "Add a period at the end of transcriptions.",
533+
isOn: Binding(
534+
get: { SettingsStore.shared.addTrailingPeriod },
535+
set: { SettingsStore.shared.addTrailingPeriod = $0 }
536+
)
537+
)
538+
Divider().opacity(0.2)
539+
540+
self.optionToggleRow(
541+
title: "Add Trailing Space",
542+
description: "Insert a space after the transcription for easier continuation.",
543+
isOn: Binding(
544+
get: { SettingsStore.shared.insertTrailingSpace },
545+
set: { SettingsStore.shared.insertTrailingSpace = $0 }
546+
)
547+
)
548+
}
549+
.padding(.top, 4)
550+
520551
Divider().opacity(0.2)
521552

522553
self.optionToggleRow(

0 commit comments

Comments
 (0)