@@ -144,22 +144,37 @@ class AppState extends ChangeNotifier {
144144 );
145145
146146 Future <void > loadNotebooks () async {
147- _notebooks = await client.getNotebooks ();
148- notifyListeners ();
147+ try {
148+ _notebooks = await client.getNotebooks ();
149+ notifyListeners ();
150+ } catch (e) {
151+ await _handleBackendFailure (e);
152+ rethrow ;
153+ }
149154 }
150155
151156 Future <api.Notebook > createNotebook (String name, String color) async {
152- final nb = await client.createNotebook (name: name, color: color);
153- _notebooks.insert (0 , nb);
154- notifyListeners ();
155- return nb;
157+ try {
158+ final nb = await client.createNotebook (name: name, color: color);
159+ _notebooks.insert (0 , nb);
160+ notifyListeners ();
161+ return nb;
162+ } catch (e) {
163+ await _handleBackendFailure (e);
164+ rethrow ;
165+ }
156166 }
157167
158168 Future <void > deleteNotebook (String id) async {
159- await client.deleteNotebook (id);
160- _notebooks.removeWhere ((n) => n.id == id);
161- if (_selectedNotebook? .id == id) { _selectedNotebook = null ; _notes = []; }
162- notifyListeners ();
169+ try {
170+ await client.deleteNotebook (id);
171+ _notebooks.removeWhere ((n) => n.id == id);
172+ if (_selectedNotebook? .id == id) { _selectedNotebook = null ; _notes = []; }
173+ notifyListeners ();
174+ } catch (e) {
175+ await _handleBackendFailure (e);
176+ rethrow ;
177+ }
163178 }
164179
165180 void selectNotebook (api.Notebook ? nb) {
@@ -171,35 +186,58 @@ class AppState extends ChangeNotifier {
171186 Future <void > loadNotes ({String ? notebookId, String ? search}) async {
172187 _isLoading = true ;
173188 notifyListeners ();
174- try { _notes = await client.getNotes (notebookId: notebookId, search: search); }
175- catch (_) {}
189+ try {
190+ _notes = await client.getNotes (notebookId: notebookId, search: search);
191+ } catch (e) {
192+ await _handleBackendFailure (e);
193+ }
176194 _isLoading = false ;
177195 notifyListeners ();
178196 }
179197
180198 Future <api.Note > createNote ({required String title, required String noteType, String template = 'blank' }) async {
181- final note = await client.createNote (
182- title: title, noteType: noteType,
183- notebookId: _selectedNotebook? .id, template: template);
184- _notes.insert (0 , note);
185- notifyListeners ();
186- return note;
199+ try {
200+ final note = await client.createNote (
201+ title: title, noteType: noteType,
202+ notebookId: _selectedNotebook? .id, template: template);
203+ _notes.insert (0 , note);
204+ notifyListeners ();
205+ return note;
206+ } catch (e) {
207+ await _handleBackendFailure (e);
208+ rethrow ;
209+ }
187210 }
188211
189212 Future <void > deleteNote (String id) async {
190- await client.deleteNote (id);
191- _notes.removeWhere ((n) => n.id == id);
192- if (_selectedNote? .id == id) _selectedNote = null ;
193- notifyListeners ();
213+ try {
214+ await client.deleteNote (id);
215+ _notes.removeWhere ((n) => n.id == id);
216+ if (_selectedNote? .id == id) _selectedNote = null ;
217+ notifyListeners ();
218+ } catch (e) {
219+ await _handleBackendFailure (e);
220+ rethrow ;
221+ }
194222 }
195223
196224 Future <void > updateNoteTitle (String id, String title) async {
197- await client.updateNote (id, title: title);
198- await loadNotes (notebookId: _selectedNotebook? .id);
225+ try {
226+ await client.updateNote (id, title: title);
227+ await loadNotes (notebookId: _selectedNotebook? .id);
228+ } catch (e) {
229+ await _handleBackendFailure (e);
230+ rethrow ;
231+ }
199232 }
200233
201234 Future <void > savePageText (String noteId, int pageNum, String content) async {
202- await client.savePageText (noteId, pageNum, content);
235+ try {
236+ await client.savePageText (noteId, pageNum, content);
237+ } catch (e) {
238+ await _handleBackendFailure (e);
239+ rethrow ;
240+ }
203241 }
204242
205243 void selectNote (api.Note ? note) { _selectedNote = note; notifyListeners (); }
@@ -214,6 +252,7 @@ class AppState extends ChangeNotifier {
214252 } catch (e) {
215253 final message = 'Sync failed: $e ' ;
216254 _finishSync (error: message);
255+ await _handleBackendFailure (e);
217256 return message;
218257 }
219258 }
@@ -232,10 +271,25 @@ class AppState extends ChangeNotifier {
232271 return result;
233272 } catch (e) {
234273 _finishSync (error: 'Sync failed: $e ' );
274+ await _handleBackendFailure (e);
235275 rethrow ;
236276 }
237277 }
238278
279+ /// Marks the backend as unavailable after an API call fails mid-session and
280+ /// refreshes [_notebooks] /[_notes] from the local SQLite store so the UI can
281+ /// keep working offline. Reuses the same flag and message as the
282+ /// startup-time path so the existing offline banner kicks in unchanged.
283+ Future <void > _handleBackendFailure (Object _) async {
284+ final wasAvailable = _isBackendAvailable;
285+ _isBackendAvailable = false ;
286+ _backendErrorMessage = 'Offline mode — backend unavailable' ;
287+ if (wasAvailable) {
288+ await _loadLocalFallback ();
289+ }
290+ notifyListeners ();
291+ }
292+
239293 void _beginSync () {
240294 _isSyncing = true ;
241295 _syncError = null ;
0 commit comments