From 0faffa0155621de0db45110b088942b317a61b61 Mon Sep 17 00:00:00 2001 From: Beingpax Date: Fri, 4 Jul 2025 16:11:52 +0545 Subject: [PATCH] Added auto-text formatting toggle --- .../CloudTranscriptionService.swift | 16 ++++++++++++---- VoiceInk/Services/ImportExportService.swift | 8 +++++++- .../Services/LocalTranscriptionService.swift | 4 +++- .../NativeAppleTranscriptionService.swift | 5 ++++- VoiceInk/Views/Settings/SettingsView.swift | 7 +++++++ 5 files changed, 33 insertions(+), 7 deletions(-) diff --git a/VoiceInk/Services/CloudTranscription/CloudTranscriptionService.swift b/VoiceInk/Services/CloudTranscription/CloudTranscriptionService.swift index e2cbb68..bad2b01 100644 --- a/VoiceInk/Services/CloudTranscription/CloudTranscriptionService.swift +++ b/VoiceInk/Services/CloudTranscription/CloudTranscriptionService.swift @@ -41,21 +41,29 @@ class CloudTranscriptionService: TranscriptionService { private lazy var openAICompatibleService = OpenAICompatibleTranscriptionService() func transcribe(audioURL: URL, model: any TranscriptionModel) async throws -> String { + var text: String + switch model.provider { case .groq: - return try await groqService.transcribe(audioURL: audioURL, model: model) + text = try await groqService.transcribe(audioURL: audioURL, model: model) case .elevenLabs: - return try await elevenLabsService.transcribe(audioURL: audioURL, model: model) + text = try await elevenLabsService.transcribe(audioURL: audioURL, model: model) case .deepgram: - return try await deepgramService.transcribe(audioURL: audioURL, model: model) + text = try await deepgramService.transcribe(audioURL: audioURL, model: model) case .custom: guard let customModel = model as? CustomCloudModel else { throw CloudTranscriptionError.unsupportedProvider } - return try await openAICompatibleService.transcribe(audioURL: audioURL, model: customModel) + text = try await openAICompatibleService.transcribe(audioURL: audioURL, model: customModel) default: throw CloudTranscriptionError.unsupportedProvider } + + if UserDefaults.standard.object(forKey: "IsTextFormattingEnabled") as? Bool ?? true { + text = WhisperTextFormatter.format(text) + } + + return text } diff --git a/VoiceInk/Services/ImportExportService.swift b/VoiceInk/Services/ImportExportService.swift index 7784e28..a640b88 100644 --- a/VoiceInk/Services/ImportExportService.swift +++ b/VoiceInk/Services/ImportExportService.swift @@ -19,6 +19,7 @@ struct GeneralSettings: Codable { let isSoundFeedbackEnabled: Bool? let isSystemMuteEnabled: Bool? let isFallbackWindowEnabled: Bool? + let isTextFormattingEnabled: Bool? } struct VoiceInkExportedSettings: Codable { @@ -48,6 +49,7 @@ class ImportExportService { private let keyIsAutoCopyEnabled = "IsAutoCopyEnabled" private let keyIsSoundFeedbackEnabled = "isSoundFeedbackEnabled" private let keyIsSystemMuteEnabled = "isSystemMuteEnabled" + private let keyIsTextFormattingEnabled = "IsTextFormattingEnabled" private init() { if let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String { @@ -92,7 +94,8 @@ class ImportExportService { isAutoCopyEnabled: whisperState.isAutoCopyEnabled, isSoundFeedbackEnabled: soundManager.isEnabled, isSystemMuteEnabled: mediaController.isSystemMuteEnabled, - isFallbackWindowEnabled: UserDefaults.standard.object(forKey: "isFallbackWindowEnabled") == nil ? true : UserDefaults.standard.bool(forKey: "isFallbackWindowEnabled") + isFallbackWindowEnabled: UserDefaults.standard.object(forKey: "isFallbackWindowEnabled") == nil ? true : UserDefaults.standard.bool(forKey: "isFallbackWindowEnabled"), + isTextFormattingEnabled: UserDefaults.standard.object(forKey: keyIsTextFormattingEnabled) as? Bool ?? true ) let exportedSettings = VoiceInkExportedSettings( @@ -250,6 +253,9 @@ class ImportExportService { if let fallbackEnabled = general.isFallbackWindowEnabled { UserDefaults.standard.set(fallbackEnabled, forKey: "isFallbackWindowEnabled") } + if let textFormattingEnabled = general.isTextFormattingEnabled { + UserDefaults.standard.set(textFormattingEnabled, forKey: self.keyIsTextFormattingEnabled) + } } self.showRestartAlert(message: "Settings imported successfully from \(url.lastPathComponent). All settings (including general app settings) have been applied.") diff --git a/VoiceInk/Services/LocalTranscriptionService.swift b/VoiceInk/Services/LocalTranscriptionService.swift index 64eecf7..0e5b912 100644 --- a/VoiceInk/Services/LocalTranscriptionService.swift +++ b/VoiceInk/Services/LocalTranscriptionService.swift @@ -65,7 +65,9 @@ class LocalTranscriptionService: TranscriptionService { await whisperContext.fullTranscribe(samples: data) var text = await whisperContext.getTranscription() - text = WhisperTextFormatter.format(text) + if UserDefaults.standard.object(forKey: "IsTextFormattingEnabled") as? Bool ?? true { + text = WhisperTextFormatter.format(text) + } logger.notice("✅ Local transcription completed successfully.") diff --git a/VoiceInk/Services/NativeAppleTranscriptionService.swift b/VoiceInk/Services/NativeAppleTranscriptionService.swift index 8a8bf51..2ed95bc 100644 --- a/VoiceInk/Services/NativeAppleTranscriptionService.swift +++ b/VoiceInk/Services/NativeAppleTranscriptionService.swift @@ -134,7 +134,10 @@ class NativeAppleTranscriptionService: TranscriptionService { } var finalTranscription = String(transcript.characters).trimmingCharacters(in: .whitespacesAndNewlines) - finalTranscription = WhisperTextFormatter.format(finalTranscription) + + if UserDefaults.standard.object(forKey: "IsTextFormattingEnabled") as? Bool ?? true { + finalTranscription = WhisperTextFormatter.format(finalTranscription) + } logger.notice("Native transcription successful. Length: \(finalTranscription.count) characters.") return finalTranscription diff --git a/VoiceInk/Views/Settings/SettingsView.swift b/VoiceInk/Views/Settings/SettingsView.swift index d2b4770..05d9002 100644 --- a/VoiceInk/Views/Settings/SettingsView.swift +++ b/VoiceInk/Views/Settings/SettingsView.swift @@ -15,6 +15,7 @@ struct SettingsView: View { @ObservedObject private var mediaController = MediaController.shared @AppStorage("hasCompletedOnboarding") private var hasCompletedOnboarding = true @AppStorage("isFallbackWindowEnabled") private var isFallbackWindowEnabled = true + @AppStorage("IsTextFormattingEnabled") private var isTextFormattingEnabled = true @State private var showResetOnboardingAlert = false @State private var currentShortcut = KeyboardShortcuts.getShortcut(for: .toggleMiniRecorder) @@ -101,6 +102,12 @@ struct SettingsView: View { } .toggleStyle(.switch) .help("Display a fallback window with the transcribed text when automatic pasting is not possible") + + Toggle(isOn: $isTextFormattingEnabled) { + Text("Automatic text formatting") + } + .toggleStyle(.switch) + .help("Apply intelligent text formatting with proper paragraphs and sentence structure to transcribed text") } }