From 14d6b3c44d2e15cc0c8e32f25745e88293921522 Mon Sep 17 00:00:00 2001 From: randogoth Date: Fri, 19 Jun 2026 19:01:21 +0300 Subject: [PATCH] always place cursor at end of file when switching to edit mode Removes the unreliable viewport-centre cursor heuristic. Switching to edit mode now always positions the cursor at text.length and scrolls to the bottom, whether arriving from a regular tap or a long-press. The long-press scroll-to-end on initial load (view mode) is unchanged. Cleans up _cursorAtEnd flag, _editorKey / GlobalKey, _getOffsetAtViewportCenter, and the public WrappedCodeFieldState / findRenderEditable that were only needed for the removed feature. Co-Authored-By: Claude Sonnet 4.6 --- lib/codefield.dart | 4 +++- lib/note_editor.dart | 31 ++++++++++++------------------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/lib/codefield.dart b/lib/codefield.dart index cbc52b5..421f9ae 100755 --- a/lib/codefield.dart +++ b/lib/codefield.dart @@ -43,7 +43,9 @@ class _WrappedCodeFieldState extends State { @override void dispose() { - _focusNode.dispose(); + if (widget.focusNode == null) { + _focusNode.dispose(); + } super.dispose(); } diff --git a/lib/note_editor.dart b/lib/note_editor.dart index 77c32f5..23624d7 100755 --- a/lib/note_editor.dart +++ b/lib/note_editor.dart @@ -43,13 +43,11 @@ class _NoteEditorScreenState extends State { bool _isLoading = true; bool _autoSaveEnabled = false; double _fontSize = 16.0; - bool _cursorAtEnd = false; @override void initState() { super.initState(); _mode = widget.initialMode; - _cursorAtEnd = widget.scrollToEnd; _loadPreferences(); _loadNoteContent(); } @@ -86,18 +84,16 @@ class _NoteEditorScreenState extends State { _isLoading = false; }); - if (widget.initialMode == NoteMode.edit) { - WidgetsBinding.instance.addPostFrameCallback((_) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (widget.initialMode == NoteMode.edit) { _controller.selection = TextSelection.collapsed(offset: _controller.text.length); _editorFocusNode.requestFocus(); - }); - } else if (widget.scrollToEnd) { - // Two frames: first renders the content, second has a stable maxScrollExtent. - WidgetsBinding.instance.addPostFrameCallback((_) { + } else if (widget.scrollToEnd) { + // Two frames: first renders content, second has a stable maxScrollExtent. WidgetsBinding.instance.addPostFrameCallback((_) => _scrollToBottom()); - }); - } + } + }); } void _scrollToBottom() { @@ -224,15 +220,12 @@ class _NoteEditorScreenState extends State { break; case 'Mode Edit': setState(() { _mode = NoteMode.edit; }); - if (_cursorAtEnd) { - _cursorAtEnd = false; // consume once - WidgetsBinding.instance.addPostFrameCallback((_) { - _controller.selection = TextSelection.collapsed( - offset: _controller.text.length); - _editorFocusNode.requestFocus(); - _scrollToBottom(); - }); - } + WidgetsBinding.instance.addPostFrameCallback((_) { + _controller.selection = TextSelection.collapsed( + offset: _controller.text.length); + _editorFocusNode.requestFocus(); + _scrollToBottom(); + }); break; case 'Mode Preview': setState(() { _mode = NoteMode.preview; });