feat(conversation-assistant): add Force Sync button for full resync

When normal sync doesn't pick up new data (only syncs since lastSync),
Force Sync clears server data and resyncs all messages from scratch.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Quinn Ftw 2025-12-29 22:58:35 -08:00
parent 241cce2ea6
commit 36bcf89c87
2 changed files with 37 additions and 10 deletions

View file

@ -126,19 +126,34 @@ struct MenuBarView: View {
Spacer()
// Sync Button
Button(action: viewModel.triggerSync) {
HStack {
if viewModel.isSyncing {
ProgressView()
.scaleEffect(0.7)
// Sync Buttons
HStack(spacing: 8) {
Button(action: viewModel.triggerSync) {
HStack {
if viewModel.isSyncing && !viewModel.isResetting {
ProgressView()
.scaleEffect(0.7)
}
Text(viewModel.isSyncing && !viewModel.isResetting ? "Syncing..." : "Sync Now")
}
Text(viewModel.isSyncing ? "Syncing..." : "Sync Now")
.frame(maxWidth: .infinity)
}
.frame(maxWidth: .infinity)
.buttonStyle(.borderedProminent)
.disabled(viewModel.isSyncing || viewModel.isResetting || viewModel.needsFullDiskAccess)
Button(action: viewModel.forceSync) {
HStack {
if viewModel.isResetting {
ProgressView()
.scaleEffect(0.7)
}
Text(viewModel.isResetting ? "Resetting..." : "Force Sync")
}
.frame(maxWidth: .infinity)
}
.buttonStyle(.bordered)
.disabled(viewModel.isSyncing || viewModel.isResetting || viewModel.needsFullDiskAccess)
}
.buttonStyle(.borderedProminent)
.disabled(viewModel.isSyncing || viewModel.needsFullDiskAccess)
.padding()
}
.padding(.vertical)

View file

@ -9,6 +9,7 @@ class MenuBarViewModel: ObservableObject {
@Published var conversationCount = 0
@Published var lastSyncText = "Never"
@Published var isSyncing = false
@Published var isResetting = false
@Published var needsFullDiskAccess = false
@Published var syncErrorMessage: String?
@ -68,6 +69,13 @@ class MenuBarViewModel: ObservableObject {
}
.store(in: &cancellables)
syncManager.$isResetting
.receive(on: DispatchQueue.main)
.sink { [weak self] resetting in
self?.isResetting = resetting
}
.store(in: &cancellables)
// Register device on startup if not authenticated
if !isAuthenticated {
registerDevice()
@ -124,6 +132,10 @@ class MenuBarViewModel: ObservableObject {
syncManager.syncNow()
}
func forceSync() {
syncManager.resetAndResync()
}
func openFullDiskAccessSettings() {
syncManager.openFullDiskAccessSettings()
}