Overview
Context: Sync feedback is currently buried in two places:
SettingsScreen shows the last sync report (notes pulled/pushed, conflicts, duration)
NotebookSidebar has a sync button with no feedback at all — tapping it calls triggerSync() but nothing visually changes
There is no persistent sync status visible in the main app. A user who just synced has no way to know whether it succeeded without opening Settings.
This issue adds a small sync status icon to the NotebookSidebar header that reflects the current state.
What needs to be done
Step 1 — State in AppState
Step 2 — Icon in NotebookSidebar
Step 3 — Last sync time
Goal
The user can glance at the sync icon in the sidebar and immediately know: is sync idle, currently running, or broken? Hovering/long-pressing shows the last sync time or error. No need to open Settings for basic sync health.
Where to look
app/lib/widgets/notebook_sidebar.dart — the sync IconButton in the header
app/lib/services/app_state.dart — triggerSync(), add SyncState enum and fields
app/lib/services/api_client.dart — getSyncStatus() already returns notes_pulled, notes_pushed, duration_seconds
Testing steps
Related to: #17, #25, #26
Overview
Context: Sync feedback is currently buried in two places:
SettingsScreenshows the last sync report (notes pulled/pushed, conflicts, duration)NotebookSidebarhas a sync button with no feedback at all — tapping it callstriggerSync()but nothing visually changesThere is no persistent sync status visible in the main app. A user who just synced has no way to know whether it succeeded without opening Settings.
This issue adds a small sync status icon to the
NotebookSidebarheader that reflects the current state.What needs to be done
Step 1 — State in
AppStateSyncStateenum with three values:idle,syncing,errorSyncState _syncState = SyncState.idletoAppStatewith a public getterAppState.triggerSync():_syncState = SyncState.syncingandnotifyListeners()before the API call_syncState = SyncState.idleon success_syncState = SyncState.erroron failureString? _lastSyncErrorto store the error message when_syncState == SyncState.errorStep 2 — Icon in
NotebookSidebarnotebook_sidebar.dart, replace the current plainIconButtonsync button with a widget that readsAppState.syncState:idle→ cloud-done icon (Icons.cloud_done_outlined), grey tintsyncing→ a smallCircularProgressIndicator(size ~16px) in place of the iconerror→ cloud-error icon (Icons.cloud_off_outlined), red tintTooltipon the icon showing the last sync time (fromgetSyncStatus()) or the error messageStep 3 — Last sync time
triggerSync(), callApiClient.getSyncStatus()and store_lastSyncTimeinAppStateGoal
The user can glance at the sync icon in the sidebar and immediately know: is sync idle, currently running, or broken? Hovering/long-pressing shows the last sync time or error. No need to open Settings for basic sync health.
Where to look
app/lib/widgets/notebook_sidebar.dart— the syncIconButtonin the headerapp/lib/services/app_state.dart—triggerSync(), addSyncStateenum and fieldsapp/lib/services/api_client.dart—getSyncStatus()already returnsnotes_pulled,notes_pushed,duration_secondsTesting steps
idlestate (noterror)Related to: #17, #25, #26