From 9b6d92c372440297721f77672e1154167beeb434 Mon Sep 17 00:00:00 2001 From: Marck64 Date: Thu, 2 Jul 2026 20:59:22 +0200 Subject: [PATCH] refactor: Enhance sync status handling and improve UI feedback in NotesApp --- .gitignore | 2 ++ lib/app.dart | 78 ++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 66 insertions(+), 14 deletions(-) diff --git a/.gitignore b/.gitignore index 3820a95..b5d5df6 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,5 @@ app.*.map.json /android/app/debug /android/app/profile /android/app/release + +problems-report.html \ No newline at end of file diff --git a/lib/app.dart b/lib/app.dart index dcb442a..5bba32c 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -87,10 +87,10 @@ class _NotesAppState extends State case SyncStatus.waitingResponse: case SyncStatus.decrypting: case SyncStatus.syncing: - return true; - case SyncStatus.idle: case SyncStatus.synced: case SyncStatus.error: + return true; + case SyncStatus.idle: return false; } } @@ -103,6 +103,32 @@ class _NotesAppState extends State final AppPalette palette = _activePalette(); final String message = _syncErrorMessage ?? _syncDetailMessage ?? 'Sincronizando...'; final double? progress = _syncProgress; + final IconData icon; + final Color accentColor; + + switch (_syncStatus) { + case SyncStatus.preparing: + case SyncStatus.encrypting: + case SyncStatus.uploading: + case SyncStatus.waitingResponse: + case SyncStatus.decrypting: + case SyncStatus.syncing: + icon = Icons.cloud_sync_outlined; + accentColor = palette.textSecondary; + break; + case SyncStatus.synced: + icon = Icons.check_circle; + accentColor = palette.success; + break; + case SyncStatus.error: + icon = Icons.error; + accentColor = palette.destructiveAccent; + break; + case SyncStatus.idle: + icon = Icons.cloud_sync_outlined; + accentColor = palette.textSecondary; + break; + } return Material( color: palette.surfaceElevated, @@ -112,7 +138,7 @@ class _NotesAppState extends State child: Container( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), decoration: BoxDecoration( - border: Border(top: BorderSide(color: palette.border)), + border: Border(top: BorderSide(color: accentColor.withValues(alpha: 0.45))), ), child: Column( mainAxisSize: MainAxisSize.min, @@ -120,7 +146,7 @@ class _NotesAppState extends State children: [ Row( children: [ - Icon(Icons.cloud_sync_outlined, color: palette.textSecondary, size: 18), + Icon(icon, color: accentColor, size: 18), const SizedBox(width: 10), Expanded( child: Text( @@ -136,15 +162,22 @@ class _NotesAppState extends State ), ], ), - const SizedBox(height: 8), - ClipRRect( - borderRadius: BorderRadius.circular(999), - child: LinearProgressIndicator( - minHeight: 4, - value: progress, - backgroundColor: palette.borderMuted, + if (_syncStatus == SyncStatus.preparing || + _syncStatus == SyncStatus.encrypting || + _syncStatus == SyncStatus.uploading || + _syncStatus == SyncStatus.waitingResponse || + _syncStatus == SyncStatus.decrypting || + _syncStatus == SyncStatus.syncing) ...[ + const SizedBox(height: 8), + ClipRRect( + borderRadius: BorderRadius.circular(999), + child: LinearProgressIndicator( + minHeight: 4, + value: progress, + backgroundColor: palette.borderMuted, + ), ), - ), + ], ], ), ), @@ -914,8 +947,8 @@ class _NotesAppState extends State _homeRefreshToken += 1; }); - // Reset to idle after 3 seconds - Future.delayed(const Duration(seconds: 3), () { + // Keep the completion state visible briefly so it can be read. + Future.delayed(const Duration(seconds: 1), () { if (mounted && syncOperationId == _syncOperationId) { setState(() { _syncStatus = SyncStatus.idle; @@ -1039,6 +1072,23 @@ class _NotesAppState extends State ), AnimatedSwitcher( duration: const Duration(milliseconds: 180), + switchInCurve: Curves.easeOutCubic, + switchOutCurve: Curves.easeInCubic, + transitionBuilder: + (Widget child, Animation animation) { + final Animation slideAnimation = Tween( + begin: const Offset(0.0, 0.35), + end: Offset.zero, + ).animate(animation); + + return FadeTransition( + opacity: animation, + child: SlideTransition( + position: slideAnimation, + child: child, + ), + ); + }, child: _buildSyncBanner(context), ), ],