diff --git a/lib/app.dart b/lib/app.dart index 61f4e82..2f992a4 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -245,12 +245,15 @@ class _QuickCaptureBarState extends ConsumerState<_QuickCaptureBar> { } Future _drainQueue() async { + if (!mounted) return; final queue = ref.read(captureQueueProvider); if (queue.isEmpty) return; final api = ref.read(quickCaptureApiProvider); for (final text in List.from(queue)) { + if (!mounted) break; try { final result = await api.capture(text); + if (!mounted) break; await ref.read(captureQueueProvider.notifier).dequeue(text); switch (result.type) { case 'note': @@ -263,7 +266,7 @@ class _QuickCaptureBarState extends ConsumerState<_QuickCaptureBar> { break; // Still offline — stop draining. } catch (_) { // Server/parse error — remove to avoid infinite retries. - await ref.read(captureQueueProvider.notifier).dequeue(text); + if (mounted) await ref.read(captureQueueProvider.notifier).dequeue(text); } } } diff --git a/lib/data/api/chat_api.dart b/lib/data/api/chat_api.dart index 4707e16..c3dfef0 100644 --- a/lib/data/api/chat_api.dart +++ b/lib/data/api/chat_api.dart @@ -92,7 +92,7 @@ class ChatApi { String currentEvent = ''; await for (final chunk in stream) { - buf.write(utf8.decode(chunk)); + buf.write(utf8.decode(chunk, allowMalformed: true)); final raw = buf.toString(); final lines = raw.split('\n'); diff --git a/lib/providers/chat_provider.dart b/lib/providers/chat_provider.dart index 1d53d05..4b4e687 100644 --- a/lib/providers/chat_provider.dart +++ b/lib/providers/chat_provider.dart @@ -90,6 +90,7 @@ class MessagesNotifier extends FamilyAsyncNotifier, int> { await for (final chunk in repo.streamGeneration(convId)) { streamedContent = true; final msgs = state.requireValue; + if (msgs.isEmpty) continue; final updated = msgs.last.copyWith(content: msgs.last.content + chunk); state = AsyncData([...msgs.sublist(0, msgs.length - 1), updated]); } diff --git a/lib/screens/notes/note_edit_screen.dart b/lib/screens/notes/note_edit_screen.dart index 51f3fcd..1296c0f 100644 --- a/lib/screens/notes/note_edit_screen.dart +++ b/lib/screens/notes/note_edit_screen.dart @@ -20,7 +20,16 @@ class _NoteEditScreenState extends ConsumerState { final _contentController = TextEditingController(); bool _preview = false; bool _saving = false; - bool _loaded = false; + + // Future is created once in initState so FutureBuilder never restarts it. + late final Future _initFuture; + + @override + void initState() { + super.initState(); + _initFuture = + widget.noteId != null ? _loadExisting() : Future.value(); + } @override void dispose() { @@ -30,15 +39,10 @@ class _NoteEditScreenState extends ConsumerState { } Future _loadExisting() async { - if (_loaded || widget.noteId == null) { - _loaded = true; - return; - } final note = await ref.read(notesRepositoryProvider).getOne(widget.noteId!); _titleController.text = note.title; _contentController.text = note.body; - _loaded = true; } Future _delete() async { @@ -97,7 +101,7 @@ class _NoteEditScreenState extends ConsumerState { @override Widget build(BuildContext context) { return FutureBuilder( - future: _loadExisting(), + future: _initFuture, builder: (context, snapshot) { return Scaffold( appBar: AppBar( @@ -159,7 +163,6 @@ class _NoteEditScreenState extends ConsumerState { expands: true, keyboardType: TextInputType.multiline, textAlignVertical: TextAlignVertical.top, - onChanged: (_) => setState(() {}), ), ), ), diff --git a/lib/screens/tasks/task_edit_screen.dart b/lib/screens/tasks/task_edit_screen.dart index 1a87f79..9a164ce 100644 --- a/lib/screens/tasks/task_edit_screen.dart +++ b/lib/screens/tasks/task_edit_screen.dart @@ -23,7 +23,16 @@ class _TaskEditScreenState extends ConsumerState { TaskPriority _priority = TaskPriority.medium; DateTime? _dueDate; bool _saving = false; - bool _loaded = false; + + // Future is created once in initState so FutureBuilder never restarts it. + late final Future _initFuture; + + @override + void initState() { + super.initState(); + _initFuture = + widget.taskId != null ? _loadExisting() : Future.value(); + } @override void dispose() { @@ -33,17 +42,13 @@ class _TaskEditScreenState extends ConsumerState { } Future _loadExisting() async { - if (_loaded || widget.taskId == null) { - _loaded = true; - return; - } - final task = await ref.read(tasksRepositoryProvider).getOne(widget.taskId!); + final task = + await ref.read(tasksRepositoryProvider).getOne(widget.taskId!); _titleController.text = task.title; _descController.text = task.description ?? ''; _status = task.status; _priority = task.priority; _dueDate = task.dueDate; - _loaded = true; } Future _save() async { @@ -117,7 +122,7 @@ class _TaskEditScreenState extends ConsumerState { @override Widget build(BuildContext context) { return FutureBuilder( - future: _loadExisting(), + future: _initFuture, builder: (context, snapshot) { return Scaffold( appBar: AppBar(