diff --git a/lib/core/services/annotation_sync_service.dart b/lib/core/services/annotation_sync_service.dart index 54eb4e4..9cfdd5e 100644 --- a/lib/core/services/annotation_sync_service.dart +++ b/lib/core/services/annotation_sync_service.dart @@ -15,24 +15,26 @@ class AnnotationSyncService { AnnotationSyncService({ required ApiClient apiClient, required StorageService storageService, - }) : _apiClient = apiClient, - _storageService = storageService; + }) : _apiClient = apiClient, + _storageService = storageService; /// Downloads annotations from server and merges with local storage. /// /// For each page, compares server's lastModified with local lastModified. /// If server is newer, overwrites local. Local annotations that are newer /// are preserved. - Future syncFromServer(String sheetUuid) async { + Future syncAnnotationsFromServer(String sheetUuid) async { try { _log.info('Syncing annotations from server for sheet $sheetUuid'); // Fetch all annotations from server final serverAnnotations = await _apiClient.fetchAnnotations(sheetUuid); + _log.fine('Fetched annotations from server for sheet $sheetUuid'); + // Get all local annotations with metadata - final localAnnotations = - await _storageService.readAllAnnotationsWithMetadata(sheetUuid); + final localAnnotations = await _storageService + .readAllAnnotationsWithMetadata(sheetUuid); int updatedCount = 0; @@ -118,7 +120,8 @@ class AnnotationSyncService { return false; } catch (e) { _log.warning( - 'Unexpected error uploading annotation, queuing for later: $e'); + 'Unexpected error uploading annotation, queuing for later: $e', + ); await _queueForLaterUpload( sheetUuid: sheetUuid, page: page, diff --git a/lib/features/sheet_viewer/sheet_viewer_page.dart b/lib/features/sheet_viewer/sheet_viewer_page.dart index 9ce0641..33a89d9 100644 --- a/lib/features/sheet_viewer/sheet_viewer_page.dart +++ b/lib/features/sheet_viewer/sheet_viewer_page.dart @@ -40,6 +40,7 @@ class _SheetViewerPageState extends State PdfDocument? _document; late Future _documentLoaded; + late Future _annotationsLoaded; int _currentPage = 1; int _totalPages = 1; bool _isPaintMode = false; @@ -69,6 +70,15 @@ class _SheetViewerPageState extends State FullScreen.setFullScreen(widget.config.fullscreen); } _documentLoaded = _loadPdf(); + _syncAnnotations(); + } + + void _syncAnnotations() { + setState(() { + _annotationsLoaded = _syncService.syncAnnotationsFromServer( + widget.sheet.uuid, + ); + }); } @override @@ -97,20 +107,22 @@ class _SheetViewerPageState extends State } else { // Native: use file cache final file = await widget.apiClient.getPdfFileCached(widget.sheet.uuid); + _log.fine("Found file, opening..."); _document = await PdfDocument.openFile(file.path); widget.sheet.availableOffline = true; } + _log.fine("Pdf loaded"); + setState(() { _totalPages = _document!.pages.length; }); - // Sync annotations from server (downloads newer versions) - await _syncService.syncFromServer(widget.sheet.uuid); - // Load annotations for current page(s) await _loadAnnotationsForCurrentPages(); + _log.fine("Annotations loaded"); + return true; } @@ -304,6 +316,26 @@ class _SheetViewerPageState extends State : 'Enter Fullscreen', onPressed: _toggleFullscreen, ), + FutureBuilder( + future: _annotationsLoaded, + builder: (context, snapshot) { + if (snapshot.hasError) { + _log.warning('Error loading annotations', snapshot.error); + return IconButton( + onPressed: _syncAnnotations, + icon: Icon(Icons.error, color: Colors.red), + ); + } + if (snapshot.connectionState == ConnectionState.done) { + _loadAnnotationsForCurrentPages(); + return IconButton( + onPressed: _syncAnnotations, + icon: Icon(Icons.refresh), + ); + } + return const CircularProgressIndicator(); + }, + ), IconButton( icon: Icon(_isPaintMode ? Icons.brush : Icons.brush_outlined), tooltip: _isPaintMode ? 'Exit Paint Mode' : 'Enter Paint Mode',