From 793660e42f0c220e33673e4a1bd49794dac78ff3 Mon Sep 17 00:00:00 2001 From: Vishesh Handa Date: Sat, 2 May 2020 02:28:30 +0200 Subject: [PATCH] ChecklistEditor: Improve focus handling It's still a bit of a mess. I seem to be hitting this bug - https://github.com/flutter/flutter/issues/20706 which others are also hitting, but it seems to be closed despite a clearly reproduce test case. --- lib/core/checklist.dart | 2 ++ lib/editors/checklist_editor.dart | 54 +++++++++++++++++++++++-------- 2 files changed, 43 insertions(+), 13 deletions(-) diff --git a/lib/core/checklist.dart b/lib/core/checklist.dart index 79143b1f..0a3dd74c 100644 --- a/lib/core/checklist.dart +++ b/lib/core/checklist.dart @@ -158,6 +158,7 @@ class Checklist { var prevItem = items.last; item.lineNo = prevItem.lineNo + 1; + items.add(item); _lines.insert(item.lineNo, item.toString()); } @@ -183,6 +184,7 @@ class Checklist { if (index == items.length) { var prevItem = items.last; item.lineNo = prevItem.lineNo + 1; + items.add(item); _lines.insert(item.lineNo, item.toString()); return; } diff --git a/lib/editors/checklist_editor.dart b/lib/editors/checklist_editor.dart index 64fa1df4..2237f2f4 100644 --- a/lib/editors/checklist_editor.dart +++ b/lib/editors/checklist_editor.dart @@ -49,7 +49,9 @@ class ChecklistEditor extends StatefulWidget implements Editor { class ChecklistEditorState extends State implements EditorState { Checklist checklist; - var focusNodes = {}; + var focusNodes = {}; + var keys = {}; + TextEditingController _titleTextController = TextEditingController(); bool _noteModified; @@ -67,9 +69,8 @@ class ChecklistEditorState extends State var item = checklist.buildItem(false, ""); checklist.addItem(item); } - for (var item in checklist.items) { - focusNodes[item] = FocusScopeNode(); + keys[UniqueKey()] = item; } } @@ -79,6 +80,29 @@ class ChecklistEditorState extends State super.dispose(); } + UniqueKey _getKey(ChecklistItem item) { + for (var e in keys.entries) { + if (e.value == item) { + return e.key; + } + } + + var key = UniqueKey(); + keys[key] = item; + return key; + } + + FocusScopeNode _getFn(ChecklistItem item) { + var key = _getKey(item); + + var fn = focusNodes[key]; + if (fn == null) { + fn = FocusScopeNode(); + focusNodes[key] = fn; + } + return fn; + } + @override Widget build(BuildContext context) { var itemTiles = []; @@ -92,13 +116,14 @@ class ChecklistEditorState extends State onPressed: () { _noteTextChanged(); setState(() { - var fn = FocusScopeNode(); var item = checklist.buildItem(false, ""); + var fn = _getFn(item); + checklist.addItem(item); - focusNodes[item] = fn; // FIXME: Make this happen on the next build Timer(const Duration(milliseconds: 50), () { + FocusScope.of(context).requestFocus(); FocusScope.of(context).requestFocus(fn); }); }); @@ -156,7 +181,7 @@ class ChecklistEditorState extends State return ChecklistItemTile( key: UniqueKey(), item: item, - focusNode: focusNodes[item], + focusNode: _getFn(item), isNewNote: autofocus, statusChanged: (bool newVal) { setState(() { @@ -181,16 +206,19 @@ class ChecklistEditorState extends State FocusNode fn; if (nextIndex >= 0) { var nextItemForFocus = checklist.items[nextIndex]; - fn = focusNodes[nextItemForFocus]; + fn = _getFn(nextItemForFocus); print("Giving focus to $nextItemForFocus"); } - focusNodes.remove(item); + var k = _getKey(item); + focusNodes.remove(k); + keys.remove(k); checklist.removeItem(item); // FIXME: Make this happen on the next build - Timer(const Duration(milliseconds: 300), () { + Timer(const Duration(milliseconds: 200), () { if (fn != null) { + FocusScope.of(context).requestFocus(); FocusScope.of(context).requestFocus(fn); } }); @@ -199,14 +227,14 @@ class ChecklistEditorState extends State itemFinished: () { _noteTextChanged(); setState(() { - var fn = FocusScopeNode(); var item = checklist.buildItem(false, ""); + var fn = _getFn(item); checklist.insertItem(index + 1, item); - focusNodes[item] = fn; // FIXME: Make this happen on the next build Timer(const Duration(milliseconds: 50), () { print("Asking focus to ${index + 1}"); + FocusScope.of(context).requestFocus(); FocusScope.of(context).requestFocus(fn); }); }); @@ -252,6 +280,7 @@ class _ChecklistItemTileState extends State { _textController.addListener(() { widget.textChanged(_textController.value.text); }); + assert(widget.focusNode != null); widget.focusNode.addListener(_onFocus); } @@ -264,8 +293,7 @@ class _ChecklistItemTileState extends State { } void _onFocus() { - setState(() {}); // rebuild to hide close button - SystemChannels.textInput.invokeMethod('TextInput.show'); + setState(() {}); // rebuild to show/hide close button } @override