Add AI conversation assistant service. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
85 lines
2.4 KiB
Swift
85 lines
2.4 KiB
Swift
import SwiftUI
|
|
import Combine
|
|
|
|
@MainActor
|
|
class MenuBarViewModel: ObservableObject {
|
|
@Published var isAuthenticated = false
|
|
@Published var syncStatus: SyncStatus = .idle
|
|
@Published var messageCount = 0
|
|
@Published var conversationCount = 0
|
|
@Published var lastSyncText = "Never"
|
|
@Published var isSyncing = false
|
|
|
|
@Published var authCode = ""
|
|
@Published var isAuthenticating = false
|
|
@Published var authError: String?
|
|
|
|
private let apiClient = APIClient.shared
|
|
private let syncManager = SyncManager.shared
|
|
private var cancellables = Set<AnyCancellable>()
|
|
|
|
init() {
|
|
isAuthenticated = apiClient.isAuthenticated
|
|
|
|
syncManager.$isSyncing
|
|
.receive(on: DispatchQueue.main)
|
|
.sink { [weak self] syncing in
|
|
self?.isSyncing = syncing
|
|
self?.syncStatus = syncing ? .syncing : .idle
|
|
}
|
|
.store(in: &cancellables)
|
|
|
|
syncManager.$lastSync
|
|
.receive(on: DispatchQueue.main)
|
|
.sink { [weak self] date in
|
|
self?.updateLastSyncText(date)
|
|
}
|
|
.store(in: &cancellables)
|
|
|
|
syncManager.$stats
|
|
.receive(on: DispatchQueue.main)
|
|
.sink { [weak self] stats in
|
|
self?.messageCount = stats.messageCount
|
|
self?.conversationCount = stats.conversationCount
|
|
}
|
|
.store(in: &cancellables)
|
|
}
|
|
|
|
func authenticate() {
|
|
guard !authCode.isEmpty else { return }
|
|
|
|
isAuthenticating = true
|
|
authError = nil
|
|
|
|
Task {
|
|
do {
|
|
try await apiClient.verifyDevice(code: authCode)
|
|
isAuthenticated = true
|
|
authCode = ""
|
|
syncManager.startSync()
|
|
} catch {
|
|
authError = error.localizedDescription
|
|
}
|
|
isAuthenticating = false
|
|
}
|
|
}
|
|
|
|
func triggerSync() {
|
|
syncManager.syncNow()
|
|
}
|
|
|
|
func openSettings() {
|
|
NSApp.sendAction(Selector(("showSettingsWindow:")), to: nil, from: nil)
|
|
}
|
|
|
|
private func updateLastSyncText(_ date: Date?) {
|
|
guard let date = date else {
|
|
lastSyncText = "Never"
|
|
return
|
|
}
|
|
|
|
let formatter = RelativeDateTimeFormatter()
|
|
formatter.unitsStyle = .abbreviated
|
|
lastSyncText = formatter.localizedString(for: date, relativeTo: Date())
|
|
}
|
|
}
|