From 1717ded9f51071f372dea905e7133a3020d65b53 Mon Sep 17 00:00:00 2001 From: Quinn Ftw Date: Mon, 29 Dec 2025 01:08:05 -0800 Subject: [PATCH] fix(conversation-assistant): fix stats not updating in UI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace entire SyncStats struct to trigger @Published notification (mutating struct properties doesn't emit Combine events) - Wrap Timer callbacks with @MainActor to fix Swift 6 concurrency warnings - Use proper weak self capture in verification polling 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .../Sources/ConversationAssistantApp.swift | 9 ++++---- .../macos/Sources/Services/SyncManager.swift | 21 +++++++++++++++---- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/features/conversation-assistant/macos/Sources/ConversationAssistantApp.swift b/features/conversation-assistant/macos/Sources/ConversationAssistantApp.swift index b3a572d17..06fc87980 100644 --- a/features/conversation-assistant/macos/Sources/ConversationAssistantApp.swift +++ b/features/conversation-assistant/macos/Sources/ConversationAssistantApp.swift @@ -55,16 +55,15 @@ class AppDelegate: NSObject, NSApplicationDelegate { NSLog("ConversationAssistant: Starting verification polling...") Timer.scheduledTimer(withTimeInterval: 3.0, repeats: true) { [weak self] timer in NSLog("ConversationAssistant: Polling for verification...") - Task { + Task { @MainActor [weak self] in + guard let self = self else { return } do { - let verified = try await self?.apiClient.checkVerification() ?? false + let verified = try await self.apiClient.checkVerification() NSLog("ConversationAssistant: Verification check result: \(verified)") if verified { timer.invalidate() NSLog("ConversationAssistant: Device verified! Starting sync...") - await MainActor.run { - self?.syncManager.startSync() - } + self.syncManager.startSync() } } catch { NSLog("ConversationAssistant: Verification check error: \(error)") diff --git a/features/conversation-assistant/macos/Sources/Services/SyncManager.swift b/features/conversation-assistant/macos/Sources/Services/SyncManager.swift index b93514078..4273487ac 100644 --- a/features/conversation-assistant/macos/Sources/Services/SyncManager.swift +++ b/features/conversation-assistant/macos/Sources/Services/SyncManager.swift @@ -4,6 +4,11 @@ import Combine struct SyncStats { var messageCount: Int = 0 var conversationCount: Int = 0 + + init(messageCount: Int = 0, conversationCount: Int = 0) { + self.messageCount = messageCount + self.conversationCount = conversationCount + } } @MainActor @@ -40,7 +45,9 @@ class SyncManager: ObservableObject { // Schedule periodic sync every 30 seconds syncTimer = Timer.scheduledTimer(withTimeInterval: 30, repeats: true) { [weak self] _ in - self?.syncNow() + Task { @MainActor in + self?.syncNow() + } } } @@ -101,12 +108,18 @@ class SyncManager: ObservableObject { NSLog("SyncManager: Synced \(synced) messages") } - stats.conversationCount = conversations.count - stats.messageCount += totalSynced + // Replace entire struct to trigger @Published notification + let newStats = SyncStats( + messageCount: stats.messageCount + totalSynced, + conversationCount: conversations.count + ) + stats = newStats + NSLog("SyncManager: Stats updated - messages: \(newStats.messageCount), conversations: \(newStats.conversationCount)") + let newSyncTime = Date() lastSync = newSyncTime UserDefaults.standard.set(newSyncTime, forKey: "lastSync") - NSLog("SyncManager: Sync complete - \(totalSynced) messages synced, lastSync set to \(newSyncTime)") + NSLog("SyncManager: Sync complete - \(totalSynced) new messages synced, lastSync set to \(newSyncTime)") } catch { NSLog("SyncManager: Sync failed: \(error.localizedDescription)")