From 9095a318ace8be7cc71e017ce9e70fd6262f3a1c Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 13 Nov 2026 08:46:26 +0000 Subject: [PATCH] fix(editor): wait for the add note FAB to close before opening the editor The expandable FAB wraps its buttons in a FocusScope while it is not fully closed, and removes it when its 250 ms closing animation ends. Closing the FAB and pushing the editor in the same frame (#583) made the editor take the focus first, then lose it, and the keyboard closed, when the animation ended. closeAddNoteFabIfOpen() now returns whether the FAB started to close, and the FAB waits for its closing animation (with a timeout, in case it cannot complete) before adding the note. Refs #593 Co-Authored-By: Claude --- lib/common/actions/notes/pop.dart | 9 +++++++- lib/pages/notes/widgets/add_note_fab.dart | 28 +++++++++++++++++++---- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/lib/common/actions/notes/pop.dart b/lib/common/actions/notes/pop.dart index d6c39d85..a60ba876 100644 --- a/lib/common/actions/notes/pop.dart +++ b/lib/common/actions/notes/pop.dart @@ -3,10 +3,17 @@ import '../../constants/constants.dart'; /// Closes the expandable FAB to add a note if it is open. /// /// Handles both the FAB of the notes page and the one of the label pages. -void closeAddNoteFabIfOpen() { +/// +/// Returns whether the FAB was open and has started to close. +bool closeAddNoteFabIfOpen() { + var closing = false; + for (final fabKey in [addNoteFabKey, labeledAddNoteFabKey]) { if (fabKey.currentState != null && fabKey.currentState!.isOpen) { fabKey.currentState!.toggle(); + closing = true; } } + + return closing; } diff --git a/lib/pages/notes/widgets/add_note_fab.dart b/lib/pages/notes/widgets/add_note_fab.dart index 8a53ede8..2a9ab116 100644 --- a/lib/pages/notes/widgets/add_note_fab.dart +++ b/lib/pages/notes/widgets/add_note_fab.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:flutter_expandable_fab/flutter_expandable_fab.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -23,20 +25,36 @@ class AddNoteFab extends ConsumerStatefulWidget { } class _AddNoteFabState extends ConsumerState { + /// Completed when the FAB has finished closing. + Completer? closedCompleter; + void onOpen() { canPopNotifier.update(); } void onClose() { canPopNotifier.update(); + + closedCompleter?.complete(); + closedCompleter = null; } - void onPressed(NoteType noteType) { - // Close the FAB before opening the editor, otherwise closing it during the transition removes the focus - // from the editor and closes the keyboard - closeAddNoteFabIfOpen(); + Future onPressed(NoteType noteType) async { + // Wait for the FAB to be fully closed before opening the editor. + // When the closing animation ends, the FAB removes its focus scope, which unfocuses the editor + // if it was focused in the meantime, and closes the keyboard. + final completer = closedCompleter = Completer(); + if (closeAddNoteFabIfOpen()) { + // The timeout makes sure that the note is still added if the animation could not be completed + await completer.future.timeout(const Duration(milliseconds: 500), onTimeout: () {}); + } + closedCompleter = null; + + if (!mounted) { + return; + } - addNote(context, ref, noteType: noteType); + await addNote(context, ref, noteType: noteType); } @override