Skip to content

Commit 4869894

Browse files
authored
Merge pull request #116 from altic-dev/analytics-for-fluid-coming-soon
Analytics for fluid1
2 parents 5f31d1f + 9572e40 commit 4869894

File tree

5 files changed

+321
-29
lines changed

5 files changed

+321
-29
lines changed

Sources/Fluid/Analytics/AnalyticsEvent.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ enum AnalyticsEvent: String {
2323
// Meeting transcription
2424
case meetingTranscriptionCompleted = "meeting_transcription_completed"
2525

26+
// Prompts
27+
case customPromptUsed = "custom_prompt_used"
28+
2629
// Errors
2730
case errorOccurred = "error_occurred"
2831
}

Sources/Fluid/ContentView.swift

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -738,16 +738,24 @@ struct ContentView: View {
738738
NavigationLink(value: SidebarItem.voiceEngine) {
739739
Label("Voice Engine", systemImage: "waveform")
740740
.font(.system(size: 15, weight: .medium))
741+
.padding(.leading, 18)
741742
}
742743
.listRowBackground(self.sidebarRowBackground(for: .voiceEngine))
743744

744745
NavigationLink(value: SidebarItem.aiEnhancements) {
745-
Label("AI Enhancements", systemImage: "sparkles")
746+
Label("AI Enhancements", systemImage: "brain")
746747
.font(.system(size: 15, weight: .medium))
748+
.padding(.leading, 18)
747749
}
748750
.listRowBackground(self.sidebarRowBackground(for: .aiEnhancements))
749751
}
750752

753+
NavigationLink(value: SidebarItem.preferences) {
754+
Label("Preferences", systemImage: "gearshape.fill")
755+
.font(.system(size: 15, weight: .medium))
756+
}
757+
.listRowBackground(self.sidebarRowBackground(for: .preferences))
758+
751759
NavigationLink(value: SidebarItem.commandMode) {
752760
Label("Command Mode", systemImage: "terminal.fill")
753761
.font(.system(size: 15, weight: .medium))
@@ -784,12 +792,6 @@ struct ContentView: View {
784792
}
785793
.listRowBackground(self.sidebarRowBackground(for: .history))
786794

787-
NavigationLink(value: SidebarItem.preferences) {
788-
Label("Preferences", systemImage: "gearshape.fill")
789-
.font(.system(size: 15, weight: .medium))
790-
}
791-
.listRowBackground(self.sidebarRowBackground(for: .preferences))
792-
793795
NavigationLink(value: SidebarItem.feedback) {
794796
Label("Feedback", systemImage: "envelope.fill")
795797
.font(.system(size: 15, weight: .medium))
@@ -1228,13 +1230,27 @@ struct ContentView: View {
12281230
if let profile = SettingsStore.shared.selectedDictationPromptProfile {
12291231
let promptBody = SettingsStore.stripBaseDictationPrompt(from: profile.prompt)
12301232
if !promptBody.isEmpty {
1233+
AnalyticsService.shared.capture(
1234+
.customPromptUsed,
1235+
properties: self.customPromptAnalyticsProperties(
1236+
promptSource: "profile",
1237+
overrideEmpty: nil
1238+
)
1239+
)
12311240
return SettingsStore.combineBasePrompt(with: promptBody)
12321241
}
12331242
}
12341243

12351244
// Default override (including empty string to intentionally use no system prompt)
12361245
if let override = SettingsStore.shared.defaultDictationPromptOverride {
12371246
let trimmedOverride = override.trimmingCharacters(in: .whitespacesAndNewlines)
1247+
AnalyticsService.shared.capture(
1248+
.customPromptUsed,
1249+
properties: self.customPromptAnalyticsProperties(
1250+
promptSource: "default_override",
1251+
overrideEmpty: trimmedOverride.isEmpty
1252+
)
1253+
)
12381254
// Empty override means explicitly use no system prompt
12391255
guard !trimmedOverride.isEmpty else { return override }
12401256

@@ -1245,6 +1261,28 @@ struct ContentView: View {
12451261
return SettingsStore.defaultDictationPromptText()
12461262
}
12471263

1264+
private func customPromptAnalyticsProperties(promptSource: String, overrideEmpty: Bool?) -> [String: Any] {
1265+
let providerID = SettingsStore.shared.selectedProviderID
1266+
let providerKey = self.providerKey(for: providerID)
1267+
let selectedModel = SettingsStore.shared.selectedModelByProvider[providerKey] ?? SettingsStore.shared.selectedModel ?? ""
1268+
let isCustomProvider = !ModelRepository.shared.isBuiltIn(providerID)
1269+
let providerName = isCustomProvider ? "Custom Provider" : ModelRepository.shared.displayName(for: providerID)
1270+
1271+
var properties: [String: Any] = [
1272+
"prompt_source": promptSource,
1273+
"provider_id": isCustomProvider ? "custom" : providerID,
1274+
"provider_name": providerName,
1275+
"provider_type": isCustomProvider ? "custom" : "built_in",
1276+
]
1277+
if !selectedModel.isEmpty {
1278+
properties["model"] = isCustomProvider ? "custom" : selectedModel
1279+
}
1280+
if let overrideEmpty {
1281+
properties["override_empty"] = overrideEmpty
1282+
}
1283+
return properties
1284+
}
1285+
12481286
// MARK: - Local Endpoint Detection
12491287

12501288
private func isLocalEndpoint(_ urlString: String) -> Bool {

Sources/Fluid/Persistence/SettingsStore.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ final class SettingsStore: ObservableObject {
3333
static let savedProviders = "SavedProviders"
3434
static let verifiedProviderFingerprints = "VerifiedProviderFingerprints"
3535
static let shareAnonymousAnalytics = "ShareAnonymousAnalytics"
36+
static let fluid1InterestCaptured = "Fluid1InterestCaptured"
3637
static let hotkeyShortcutKey = "HotkeyShortcutKey"
3738
static let preferredInputDeviceUID = "PreferredInputDeviceUID"
3839
static let preferredOutputDeviceUID = "PreferredOutputDeviceUID"
@@ -373,6 +374,14 @@ final class SettingsStore: ObservableObject {
373374
}
374375
}
375376

377+
var fluid1InterestCaptured: Bool {
378+
get { self.defaults.bool(forKey: Keys.fluid1InterestCaptured) }
379+
set {
380+
objectWillChange.send()
381+
self.defaults.set(newValue, forKey: Keys.fluid1InterestCaptured)
382+
}
383+
}
384+
376385
var availableModels: [String] {
377386
get { (self.defaults.array(forKey: Keys.availableAIModels) as? [String]) ?? [] }
378387
set {

Sources/Fluid/UI/AISettings/AIEnhancementSettingsView.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ struct AIEnhancementSettingsView: View {
66
@ObservedObject var promptTest: DictationPromptTestCoordinator
77
let theme: AppTheme
88
@State var expandedProviderID: String? = nil
9+
@State var providerSearchText: String = ""
10+
@State var fluid1InterestEmail: String = ""
11+
@State var fluid1InterestErrorMessage: String = ""
12+
@State var fluid1InterestIsSubmitting: Bool = false
913

1014
var body: some View {
1115
self.aiConfigurationCard

0 commit comments

Comments
 (0)