From 7c2cde03b7827856b900b1cd9ed6130cac140d68 Mon Sep 17 00:00:00 2001 From: Vishesh Handa Date: Thu, 30 Jan 2020 18:41:27 +0100 Subject: [PATCH] Add the first draft of a TodoEditor It's a small proof of concept and still needs a lot of work. --- lib/editors/todo_editor.dart | 187 +++++++++++++++++++++++++++++++++++ lib/screens/note_editor.dart | 25 ++++- 2 files changed, 211 insertions(+), 1 deletion(-) create mode 100644 lib/editors/todo_editor.dart diff --git a/lib/editors/todo_editor.dart b/lib/editors/todo_editor.dart new file mode 100644 index 00000000..e2a6c2e3 --- /dev/null +++ b/lib/editors/todo_editor.dart @@ -0,0 +1,187 @@ +import 'package:flutter/material.dart'; + +import 'package:gitjournal/core/note.dart'; +import 'package:gitjournal/editors/common.dart'; + +class TodoEditor extends StatefulWidget implements Editor { + final Note note; + + @override + final NoteCallback noteDeletionSelected; + @override + final NoteCallback noteEditorChooserSelected; + @override + final NoteCallback exitEditorSelected; + @override + final NoteCallback renameNoteSelected; + @override + final NoteCallback moveNoteToFolderSelected; + + TodoEditor({ + Key key, + @required this.note, + @required this.noteDeletionSelected, + @required this.noteEditorChooserSelected, + @required this.exitEditorSelected, + @required this.renameNoteSelected, + @required this.moveNoteToFolderSelected, + }) : super(key: key); + + @override + TodoEditorState createState() { + return TodoEditorState(note); + } +} + +class TodoEditorState extends State implements EditorState { + Note note; + List todos; + TextEditingController _titleTextController = TextEditingController(); + + TodoEditorState(this.note) { + _titleTextController = TextEditingController(text: note.title); + + todos = [ + TodoItem(false, "First Item"), + TodoItem(true, "Second Item"), + TodoItem(false, "Third Item"), + ]; + } + + @override + void dispose() { + _titleTextController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + var todoItemTiles = []; + todos.forEach((TodoItem todo) { + todoItemTiles.add(_buildTile(todo)); + }); + + print("Building " + todos.toString()); + var todoList = ListView( + children: todoItemTiles, + ); + + // FIXME: The body needs to be scrollable + + var titleEditor = Padding( + padding: const EdgeInsets.all(16.0), + child: _NoteTitleEditor(_titleTextController), + ); + + return Scaffold( + appBar: buildEditorAppBar(widget, this), + floatingActionButton: buildFAB(widget, this), + body: Column( + children: [titleEditor, Expanded(child: todoList)], + ), + ); + } + + @override + Note getNote() { + note.title = _titleTextController.text.trim(); + return note; + } + + TodoItemTile _buildTile(TodoItem todo) { + return TodoItemTile( + todo: todo, + statusChanged: (val) { + setState(() { + todo.checked = val; + }); + }, + ); + } +} + +class _NoteTitleEditor extends StatelessWidget { + final TextEditingController textController; + + _NoteTitleEditor(this.textController); + + @override + Widget build(BuildContext context) { + var style = Theme.of(context).textTheme.title; + + return TextField( + keyboardType: TextInputType.text, + maxLines: 1, + style: style, + decoration: const InputDecoration( + hintText: 'Title', + border: InputBorder.none, + isDense: true, + ), + controller: textController, + textCapitalization: TextCapitalization.sentences, + ); + } +} + +class TodoItem { + bool checked; + String body; + + TodoItem(this.checked, this.body); + + @override + String toString() { + return 'TodoItem($checked, "$body")'; + } +} + +class TodoItemTile extends StatefulWidget { + final TodoItem todo; + final Function statusChanged; + + TodoItemTile({@required this.todo, @required this.statusChanged}); + + @override + _TodoItemTileState createState() => _TodoItemTileState(); +} + +class _TodoItemTileState extends State { + TextEditingController _textController; + + @override + void initState() { + super.initState(); + _textController = TextEditingController(text: widget.todo.body); + } + + @override + Widget build(BuildContext context) { + var style = Theme.of(context).textTheme.subhead; + + var editor = TextField( + keyboardType: TextInputType.text, + maxLines: 1, + style: style, + textCapitalization: TextCapitalization.sentences, + controller: _textController, + decoration: const InputDecoration( + border: InputBorder.none, + isDense: true, + ), + ); + + return ListTile( + leading: Checkbox( + value: widget.todo.checked, + onChanged: widget.statusChanged, + ), + title: editor, + trailing: IconButton( + icon: Icon(Icons.cancel), + onPressed: () {}, + ), + dense: true, + ); + } +} diff --git a/lib/screens/note_editor.dart b/lib/screens/note_editor.dart index 3f5af7a3..3485e34d 100644 --- a/lib/screens/note_editor.dart +++ b/lib/screens/note_editor.dart @@ -5,12 +5,15 @@ import 'package:gitjournal/core/note.dart'; import 'package:gitjournal/core/notes_folder.dart'; import 'package:gitjournal/editors/markdown_editor.dart'; import 'package:gitjournal/editors/raw_editor.dart'; +import 'package:gitjournal/editors/todo_editor.dart'; import 'package:gitjournal/state_container.dart'; import 'package:gitjournal/core/note_data_serializers.dart'; import 'package:gitjournal/utils.dart'; import 'package:gitjournal/widgets/folder_selection_dialog.dart'; import 'package:gitjournal/widgets/rename_dialog.dart'; +final todoEditorEnabled = false; + class NoteEditor extends StatefulWidget { final Note note; final NotesFolder notesFolder; @@ -28,7 +31,7 @@ class NoteEditor extends StatefulWidget { } } -enum EditorType { Markdown, Raw } +enum EditorType { Markdown, Raw, Todo } class NoteEditorState extends State { Note note; @@ -37,6 +40,7 @@ class NoteEditorState extends State { final _rawEditorKey = GlobalKey(); final _markdownEditorKey = GlobalKey(); + final _todoEditorKey = GlobalKey(); bool get _isNewNote { return widget.note == null; @@ -85,6 +89,16 @@ class NoteEditorState extends State { renameNoteSelected: _renameNoteSelected, moveNoteToFolderSelected: _moveNoteToFolderSelected, ); + case EditorType.Todo: + return TodoEditor( + key: _todoEditorKey, + note: note, + noteDeletionSelected: _noteDeletionSelected, + noteEditorChooserSelected: _noteEditorChooserSelected, + exitEditorSelected: _exitEditorSelected, + renameNoteSelected: _renameNoteSelected, + moveNoteToFolderSelected: _moveNoteToFolderSelected, + ); } return null; } @@ -106,6 +120,13 @@ class NoteEditorState extends State { groupValue: editorType, onChanged: (EditorType et) => Navigator.of(context).pop(et), ), + if (todoEditorEnabled) + RadioListTile( + title: const Text("Todo Editor"), + value: EditorType.Todo, + groupValue: editorType, + onChanged: (EditorType et) => Navigator.of(context).pop(et), + ), ]; return AlertDialog( @@ -225,6 +246,8 @@ class NoteEditorState extends State { return _markdownEditorKey.currentState.getNote(); case EditorType.Raw: return _rawEditorKey.currentState.getNote(); + case EditorType.Todo: + return _todoEditorKey.currentState.getNote(); } return null; }