Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 4 additions & 0 deletions Sources/Fluid/ContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1916,6 +1916,9 @@ struct ContentView: View {
if typingTarget.shouldRestoreOriginalFocus {
await self.restoreFocusToRecordingTarget()
}
if let element = AutoLearnDictionaryService.shared.captureFocusedElement() {
AutoLearnDictionaryService.shared.prepareMonitoring(pastedText: finalText, element: element)
Comment thread
martin-forge marked this conversation as resolved.
Outdated
}
self.asr.typeTextToActiveField(
finalText,
preferredTargetPID: typingTarget.pid
Expand Down Expand Up @@ -1943,6 +1946,7 @@ struct ContentView: View {
aiModel: modelInfo.model,
aiProvider: modelInfo.provider
)
AutoLearnDictionaryService.shared.beginMonitoring()
Comment thread
martin-forge marked this conversation as resolved.
Outdated

NotchOverlayManager.shared.hide()
} else if shouldPersistOutputs,
Expand Down
2 changes: 2 additions & 0 deletions Sources/Fluid/Persistence/BackupService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ struct SettingsBackupPayload: Codable, Equatable {
let pauseMediaDuringTranscription: Bool
let vocabularyBoostingEnabled: Bool
let customDictionaryEntries: [SettingsStore.CustomDictionaryEntry]
let autoLearnCustomDictionaryEnabled: Bool
let autoLearnCustomDictionarySuggestions: [SettingsStore.AutoLearnSuggestion]
Comment thread
martin-forge marked this conversation as resolved.
let selectedDictationPromptID: String?
let dictationPromptOff: Bool?
let selectedEditPromptID: String?
Expand Down
64 changes: 64 additions & 0 deletions Sources/Fluid/Persistence/SettingsStore.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2186,6 +2186,8 @@ final class SettingsStore: ObservableObject {
pauseMediaDuringTranscription: self.pauseMediaDuringTranscription,
vocabularyBoostingEnabled: self.vocabularyBoostingEnabled,
customDictionaryEntries: self.customDictionaryEntries,
autoLearnCustomDictionaryEnabled: self.autoLearnCustomDictionaryEnabled,
autoLearnCustomDictionarySuggestions: self.autoLearnCustomDictionarySuggestions,
selectedDictationPromptID: self.selectedDictationPromptID,
dictationPromptOff: self.isDictationPromptOff,
selectedEditPromptID: self.selectedEditPromptID,
Expand Down Expand Up @@ -2255,6 +2257,8 @@ final class SettingsStore: ObservableObject {
self.pauseMediaDuringTranscription = payload.pauseMediaDuringTranscription
self.vocabularyBoostingEnabled = payload.vocabularyBoostingEnabled
self.customDictionaryEntries = payload.customDictionaryEntries
self.autoLearnCustomDictionaryEnabled = payload.autoLearnCustomDictionaryEnabled
self.autoLearnCustomDictionarySuggestions = payload.autoLearnCustomDictionarySuggestions

self.dictationPromptProfiles = promptProfiles
self.appPromptBindings = appPromptBindings
Expand Down Expand Up @@ -2853,6 +2857,36 @@ final class SettingsStore: ObservableObject {
}
}

enum AutoLearnSuggestionStatus: String, Codable, Hashable {
case pending
case dismissed
}

struct AutoLearnSuggestion: Codable, Identifiable, Hashable {
let id: UUID
var originalText: String
var replacement: String
var occurrences: Int
var lastObservedAt: Date
var status: AutoLearnSuggestionStatus

init(
id: UUID = UUID(),
originalText: String,
replacement: String,
occurrences: Int = 1,
lastObservedAt: Date = Date(),
status: AutoLearnSuggestionStatus = .pending
) {
self.id = id
self.originalText = originalText.trimmingCharacters(in: .whitespacesAndNewlines).lowercased()
self.replacement = replacement.trimmingCharacters(in: .whitespacesAndNewlines)
self.occurrences = occurrences
self.lastObservedAt = lastObservedAt
self.status = status
}
}

var vocabularyBoostingEnabled: Bool {
get {
let value = self.defaults.object(forKey: Keys.vocabularyBoostingEnabled)
Expand Down Expand Up @@ -2883,6 +2917,34 @@ final class SettingsStore: ObservableObject {
}
}

var autoLearnCustomDictionaryEnabled: Bool {
get {
let value = self.defaults.object(forKey: Keys.autoLearnCustomDictionaryEnabled)
return value as? Bool ?? false
}
set {
objectWillChange.send()
self.defaults.set(newValue, forKey: Keys.autoLearnCustomDictionaryEnabled)
}
}

var autoLearnCustomDictionarySuggestions: [AutoLearnSuggestion] {
get {
guard let data = defaults.data(forKey: Keys.autoLearnCustomDictionarySuggestions),
let decoded = try? JSONDecoder().decode([AutoLearnSuggestion].self, from: data)
else {
return []
}
return decoded
}
set {
objectWillChange.send()
if let encoded = try? JSONEncoder().encode(newValue) {
self.defaults.set(encoded, forKey: Keys.autoLearnCustomDictionarySuggestions)
}
}
}

// MARK: - Speech Model (Unified ASR Model Selection)

/// Unified speech recognition model selection.
Expand Down Expand Up @@ -3569,6 +3631,8 @@ private extension SettingsStore {
// Custom Dictionary
static let customDictionaryEntries = "CustomDictionaryEntries"
static let vocabularyBoostingEnabled = "VocabularyBoostingEnabled"
static let autoLearnCustomDictionaryEnabled = "AutoLearnCustomDictionaryEnabled"
static let autoLearnCustomDictionarySuggestions = "AutoLearnCustomDictionarySuggestions"

// Transcription Provider (ASR)
static let selectedTranscriptionProvider = "SelectedTranscriptionProvider"
Expand Down
Loading