add long-press gesture to open note scrolled to end
Long-pressing a note in the list opens it in view mode with the scroll position at the bottom of the file. Switching to edit mode the first time positions the cursor at the end of the text and scrolls there too, so the user can immediately append content. Implementation: - NoteEditorScreen gains a scrollToEnd parameter (default false) - A ScrollController is attached to the view/edit SingleChildScrollView - After content loads with scrollToEnd=true, two post-frame callbacks fire (first renders the content, second has a stable maxScrollExtent) then jumpTo(maxScrollExtent) - _cursorAtEnd flag is consumed on the first Mode Edit switch: sets selection to text.length, requests focus, and scrolls to bottom - NoteListScreen ListTile gets onLongPress that navigates with scrollToEnd: true and reloads on return Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f91484d6d4
commit
db13702e54
2 changed files with 42 additions and 2 deletions
|
|
@ -14,10 +14,10 @@ import 'codefield.dart';
|
|||
|
||||
class NoteEditorScreen extends StatefulWidget {
|
||||
final File note;
|
||||
final String? notesDirectoryPath; // ✅ Add this
|
||||
final String? notesDirectoryPath;
|
||||
final bool isDarkMode;
|
||||
|
||||
final NoteMode initialMode;
|
||||
final bool scrollToEnd;
|
||||
|
||||
const NoteEditorScreen({
|
||||
super.key,
|
||||
|
|
@ -25,6 +25,7 @@ class NoteEditorScreen extends StatefulWidget {
|
|||
required this.isDarkMode,
|
||||
required this.notesDirectoryPath,
|
||||
this.initialMode = NoteMode.view,
|
||||
this.scrollToEnd = false,
|
||||
});
|
||||
|
||||
@override
|
||||
|
|
@ -38,14 +39,17 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
|
|||
late String _initialContent;
|
||||
late NoteMode _mode;
|
||||
final FocusNode _editorFocusNode = FocusNode();
|
||||
final ScrollController _scrollController = ScrollController();
|
||||
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();
|
||||
}
|
||||
|
|
@ -88,6 +92,17 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
|
|||
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((_) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) => _scrollToBottom());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _scrollToBottom() {
|
||||
if (_scrollController.hasClients) {
|
||||
_scrollController.jumpTo(_scrollController.position.maxScrollExtent);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -160,6 +175,7 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
|
|||
_controller.removeListener(_onTextChanged);
|
||||
_controller.dispose();
|
||||
_editorFocusNode.dispose();
|
||||
_scrollController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
|
|
@ -208,6 +224,15 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
|
|||
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();
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 'Mode Preview':
|
||||
setState(() { _mode = NoteMode.preview; });
|
||||
|
|
@ -362,6 +387,7 @@ class _NoteEditorScreenState extends State<NoteEditorScreen> {
|
|||
data: CodeThemeData(
|
||||
styles: widget.isDarkMode ? nightTheme : dayTheme),
|
||||
child: SingleChildScrollView(
|
||||
controller: _scrollController,
|
||||
child: WrappedCodeField(
|
||||
wrap: true,
|
||||
controller: _controller,
|
||||
|
|
|
|||
|
|
@ -943,6 +943,20 @@ Happy note taking! ✨
|
|||
setState(() {}); // ✅ Force UI refresh
|
||||
}
|
||||
},
|
||||
onLongPress: () async {
|
||||
await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => NoteEditorScreen(
|
||||
note: noteFile,
|
||||
isDarkMode: widget.isDarkMode,
|
||||
notesDirectoryPath: notesDirectoryPath,
|
||||
scrollToEnd: true,
|
||||
),
|
||||
),
|
||||
);
|
||||
if (context.mounted) _loadNotes();
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue