package app import ( "fmt" "time" "go.uber.org/zap" "codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/internal/service/sync" ) // SyncStatusData represents the current sync status for the frontend type SyncStatusData struct { IsSyncing bool `json:"is_syncing"` LastSyncTime string `json:"last_sync_time,omitempty"` LastSyncSuccess bool `json:"last_sync_success"` LastSyncError string `json:"last_sync_error,omitempty"` CollectionsSynced bool `json:"collections_synced"` FilesSynced bool `json:"files_synced"` FullySynced bool `json:"fully_synced"` } // SyncResultData represents the result of a sync operation type SyncResultData struct { CollectionsProcessed int `json:"collections_processed"` CollectionsAdded int `json:"collections_added"` CollectionsUpdated int `json:"collections_updated"` CollectionsDeleted int `json:"collections_deleted"` FilesProcessed int `json:"files_processed"` FilesAdded int `json:"files_added"` FilesUpdated int `json:"files_updated"` FilesDeleted int `json:"files_deleted"` Errors []string `json:"errors,omitempty"` } // GetSyncStatus returns the current sync status func (a *Application) GetSyncStatus() (*SyncStatusData, error) { status, err := a.syncService.GetSyncStatus(a.ctx) if err != nil { a.logger.Error("Failed to get sync status", zap.Error(err)) return nil, fmt.Errorf("failed to get sync status: %w", err) } return &SyncStatusData{ IsSyncing: false, LastSyncTime: time.Now().Format(time.RFC3339), LastSyncSuccess: true, LastSyncError: "", CollectionsSynced: status.CollectionsSynced, FilesSynced: status.FilesSynced, FullySynced: status.FullySynced, }, nil } // TriggerSync triggers a full sync of collections and files func (a *Application) TriggerSync() error { a.logger.Info("Manual sync triggered") // Get current session for email session, err := a.authService.GetCurrentSession(a.ctx) if err != nil { a.logger.Error("Failed to get session for sync", zap.Error(err)) return fmt.Errorf("not authenticated: %w", err) } // Get the stored password for decryption var password string if a.passwordStore.HasPassword(session.Email) { password, err = a.passwordStore.GetPassword(session.Email) if err != nil { a.logger.Warn("Failed to get stored password, sync will skip decryption", zap.Error(err)) } } else { a.logger.Warn("No stored password, sync will skip decryption") } input := &sync.SyncInput{ BatchSize: 50, MaxBatches: 100, Password: password, } result, err := a.syncService.SyncAll(a.ctx, input) if err != nil { a.logger.Error("Sync failed", zap.Error(err)) return fmt.Errorf("sync failed: %w", err) } a.logger.Info("Sync completed", zap.Int("collections_added", result.CollectionsAdded), zap.Int("files_added", result.FilesAdded), zap.Int("errors", len(result.Errors))) return nil } // TriggerSyncWithResult triggers a full sync and returns the result func (a *Application) TriggerSyncWithResult() (*SyncResultData, error) { a.logger.Info("Manual sync with result triggered") // Get current session for email session, err := a.authService.GetCurrentSession(a.ctx) if err != nil { a.logger.Error("Failed to get session for sync", zap.Error(err)) return nil, fmt.Errorf("not authenticated: %w", err) } // Get the stored password for decryption var password string if a.passwordStore.HasPassword(session.Email) { password, err = a.passwordStore.GetPassword(session.Email) if err != nil { a.logger.Warn("Failed to get stored password, sync will skip decryption", zap.Error(err)) } } else { a.logger.Warn("No stored password, sync will skip decryption") } input := &sync.SyncInput{ BatchSize: 50, MaxBatches: 100, Password: password, } result, err := a.syncService.SyncAll(a.ctx, input) if err != nil { a.logger.Error("Sync failed", zap.Error(err)) return nil, fmt.Errorf("sync failed: %w", err) } return &SyncResultData{ CollectionsProcessed: result.CollectionsProcessed, CollectionsAdded: result.CollectionsAdded, CollectionsUpdated: result.CollectionsUpdated, CollectionsDeleted: result.CollectionsDeleted, FilesProcessed: result.FilesProcessed, FilesAdded: result.FilesAdded, FilesUpdated: result.FilesUpdated, FilesDeleted: result.FilesDeleted, Errors: result.Errors, }, nil } // ResetSync resets all sync state for a fresh sync func (a *Application) ResetSync() error { a.logger.Info("Resetting sync state") return a.syncService.ResetSync(a.ctx) }