forked from BasedHardware/omi
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSettingsContentView+SettingsUpdates.swift
More file actions
147 lines (135 loc) · 4.97 KB
/
Copy pathSettingsContentView+SettingsUpdates.swift
File metadata and controls
147 lines (135 loc) · 4.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
import Sparkle
import SwiftUI
import UniformTypeIdentifiers
import WebKit
extension SettingsContentView {
func openURLInDefaultBrowser(_ url: URL) {
if let appURL = NSWorkspace.shared.urlForApplication(toOpen: url) {
let configuration = NSWorkspace.OpenConfiguration()
configuration.activates = true
NSWorkspace.shared.open([url], withApplicationAt: appURL, configuration: configuration) {
_, error in
if let error {
NSLog(
"OMI SETTINGS: Failed to open browser URL %@: %@", url.absoluteString,
error.localizedDescription)
NSWorkspace.shared.open(url)
}
}
return
}
NSWorkspace.shared.open(url)
}
func updateDailySummarySettings(enabled: Bool? = nil, hour: Int? = nil) {
Task {
do {
let _ = try await APIClient.shared.updateDailySummarySettings(enabled: enabled, hour: hour)
} catch {
logError("Failed to update daily summary settings", error: error)
}
}
}
func updateNotificationSettings(enabled: Bool? = nil, frequency: Int? = nil) {
if let enabled {
// Mirror locally so NotificationService suppresses/resumes proactive notifications
// immediately when the master toggle flips, even before the backend round-trip completes.
UserDefaults.standard.set(enabled, forKey: NotificationService.masterEnabledDefaultsKey)
}
if let frequency {
// Mirror locally so NotificationService picks up the new throttle level immediately,
// even before the backend round-trip completes.
UserDefaults.standard.set(frequency, forKey: NotificationService.frequencyDefaultsKey)
}
let syncRevision = NotificationService.beginNotificationSettingsSync()
// Preserve request order and always send the complete locally desired state.
// If an earlier partial mutation fails, a later successful mutation must also
// repair that field before it is allowed to clear the pending-sync journal.
NotificationSettingsSyncCoordinator.shared.enqueue(
enabled: NotificationService.areNotificationsEnabled(),
frequency: NotificationService.currentFrequencyLevel(),
revision: syncRevision)
}
func updateLanguage(_ language: String) {
Task {
// Track language change
AnalyticsManager.shared.languageChanged(language: language)
do {
let _ = try await APIClient.shared.updateUserLanguage(language)
} catch {
logError("Failed to update language", error: error)
}
}
}
func updateRecordingPermission(_ enabled: Bool) {
Task {
do {
try await APIClient.shared.setRecordingPermission(enabled: enabled)
} catch {
logError("Failed to update recording permission", error: error)
}
}
}
func updatePrivateCloudSync(_ enabled: Bool) {
Task {
do {
try await APIClient.shared.setPrivateCloudSync(enabled: enabled)
} catch {
logError("Failed to update private cloud sync", error: error)
}
}
}
func updateTranscriptionPreferences(
singleLanguageMode: Bool? = nil, vocabulary: String? = nil
) {
Task {
do {
var vocabArray: [String]? = nil
if let vocab = vocabulary {
vocabArray = vocab.split(separator: ",")
.map { $0.trimmingCharacters(in: .whitespaces) }
.filter { !$0.isEmpty }
}
let _ = try await APIClient.shared.updateTranscriptionPreferences(
singleLanguageMode: singleLanguageMode,
vocabulary: vocabArray
)
} catch {
logError("Failed to update transcription preferences", error: error)
}
}
}
func deleteAccountAndData() {
guard !isDeletingAccount else { return }
deleteAccountError = nil
isDeletingAccount = true
AnalyticsManager.shared.deleteAccountConfirmed()
Task {
do {
guard let deletionOwner = RuntimeOwnerIdentity.currentOwnerId() else {
throw AuthError.notSignedIn
}
try await APIClient.shared.deleteAccount()
// The backend has durably admitted deletion. Persist the cleanup owner
// before any local transition so a crash/relaunch cannot restore this
// accepted account and migrate its local Rewind data into a new UID.
UserDefaults.standard.set(deletionOwner, forKey: .acceptedAccountDeletionOwnerId)
await MainActor.run {
appState.stopTranscription()
ProactiveAssistantsPlugin.shared.stopMonitoring(reason: .accountDeleted)
}
do {
try await AuthService.shared.signOut(acceptedAccountDeletion: true)
isDeletingAccount = false
} catch {
deleteAccountError = "Your account was deleted, but Omi couldn't sign you out. Quit and reopen Omi."
isDeletingAccount = false
}
} catch {
await MainActor.run {
deleteAccountError = UserFacingErrorPresentation.message(for: error, while: .accountDeletion)
isDeletingAccount = false
}
}
}
}
}