1
0
mirror of https://github.com/GitJournal/GitJournal.git synced 2025-07-20 04:42:59 +08:00

Reduce code duplication between Editors

It also makes it so much easier to implement a new editor.
This commit is contained in:
Vishesh Handa
2020-01-30 17:42:29 +01:00
parent 841e2808db
commit ddb7303fea
3 changed files with 118 additions and 141 deletions

86
lib/editors/common.dart Normal file

@ -0,0 +1,86 @@
import 'package:flutter/material.dart';
import 'package:gitjournal/core/note.dart';
typedef NoteCallback = void Function(Note);
abstract class Editor {
NoteCallback get noteDeletionSelected;
NoteCallback get noteEditorChooserSelected;
NoteCallback get exitEditorSelected;
NoteCallback get renameNoteSelected;
NoteCallback get moveNoteToFolderSelected;
}
abstract class EditorState {
Note getNote();
}
enum DropDownChoices { Rename, MoveToFolder }
AppBar buildEditorAppBar(
Editor editor,
EditorState editorState, {
List<IconButton> extraButtons,
}) {
return AppBar(
leading: IconButton(
key: const ValueKey("NewEntry"),
icon: const Icon(Icons.check),
onPressed: () {
editor.exitEditorSelected(editorState.getNote());
},
),
actions: <Widget>[
...?extraButtons,
IconButton(
icon: const Icon(Icons.library_books),
onPressed: () {
var note = editorState.getNote();
editor.noteEditorChooserSelected(note);
},
),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
var note = editorState.getNote();
editor.noteDeletionSelected(note);
},
),
PopupMenuButton<DropDownChoices>(
onSelected: (DropDownChoices choice) {
switch (choice) {
case DropDownChoices.Rename:
var note = editorState.getNote();
editor.renameNoteSelected(note);
return;
case DropDownChoices.MoveToFolder:
var note = editorState.getNote();
editor.moveNoteToFolderSelected(note);
return;
}
},
itemBuilder: (BuildContext context) =>
<PopupMenuEntry<DropDownChoices>>[
const PopupMenuItem<DropDownChoices>(
value: DropDownChoices.Rename,
child: Text('Edit File Name'),
),
const PopupMenuItem<DropDownChoices>(
value: DropDownChoices.MoveToFolder,
child: Text('Move to Folder'),
),
],
),
],
);
}
FloatingActionButton buildFAB(Editor editor, EditorState editorState) {
return FloatingActionButton(
child: const Icon(Icons.check),
onPressed: () {
editor.exitEditorSelected(editorState.getNote());
},
);
}

@ -1,18 +1,23 @@
import 'package:flutter/material.dart';
import 'package:gitjournal/core/note.dart';
import 'package:gitjournal/editors/common.dart';
import 'package:gitjournal/widgets/note_viewer.dart';
typedef NoteCallback = void Function(Note);
enum DropDownChoices { Rename, MoveToFolder }
class MarkdownEditor extends StatefulWidget {
class MarkdownEditor 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;
final bool autofocusOnEditor;
MarkdownEditor({
@ -32,7 +37,7 @@ class MarkdownEditor extends StatefulWidget {
}
}
class MarkdownEditorState extends State<MarkdownEditor> {
class MarkdownEditorState extends State<MarkdownEditor> implements EditorState {
Note note;
TextEditingController _textController = TextEditingController();
TextEditingController _titleTextController = TextEditingController();
@ -69,75 +74,18 @@ class MarkdownEditorState extends State<MarkdownEditor> {
);
Widget body = editingMode ? editor : NoteViewer(note: note);
var fab = FloatingActionButton(
child: const Icon(Icons.check),
onPressed: () {
_updateNote();
widget.exitEditorSelected(note);
},
var extraButton = IconButton(
icon: editingMode
? const Icon(Icons.remove_red_eye)
: const Icon(Icons.edit),
onPressed: _switchMode,
);
return Scaffold(
appBar: AppBar(
leading: IconButton(
key: const ValueKey("NewEntry"),
icon: const Icon(Icons.check),
onPressed: () {
_updateNote();
widget.exitEditorSelected(note);
},
),
actions: <Widget>[
IconButton(
icon: editingMode
? const Icon(Icons.remove_red_eye)
: const Icon(Icons.edit),
onPressed: _switchMode,
),
IconButton(
icon: const Icon(Icons.library_books),
onPressed: () {
_updateNote();
widget.noteEditorChooserSelected(note);
},
),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
_updateNote();
widget.noteDeletionSelected(note);
},
),
PopupMenuButton<DropDownChoices>(
onSelected: (DropDownChoices choice) {
switch (choice) {
case DropDownChoices.Rename:
_updateNote();
widget.renameNoteSelected(note);
return;
case DropDownChoices.MoveToFolder:
_updateNote();
widget.moveNoteToFolderSelected(note);
return;
}
},
itemBuilder: (BuildContext context) =>
<PopupMenuEntry<DropDownChoices>>[
const PopupMenuItem<DropDownChoices>(
value: DropDownChoices.Rename,
child: Text('Edit File Name'),
),
const PopupMenuItem<DropDownChoices>(
value: DropDownChoices.MoveToFolder,
child: Text('Move to Folder'),
),
],
),
],
),
appBar: buildEditorAppBar(widget, this, extraButtons: [extraButton]),
floatingActionButton: buildFAB(widget, this),
body: body,
floatingActionButton: fab,
);
}
@ -153,6 +101,7 @@ class MarkdownEditorState extends State<MarkdownEditor> {
note.body = _textController.text.trim();
}
@override
Note getNote() {
_updateNote();
return note;

@ -2,16 +2,20 @@ import 'package:flutter/material.dart';
import 'package:gitjournal/core/note.dart';
import 'package:gitjournal/core/note_data_serializers.dart';
import 'package:gitjournal/editors/common.dart';
typedef NoteCallback = void Function(Note);
enum DropDownChoices { Rename, MoveToFolder }
class RawEditor extends StatefulWidget {
class RawEditor 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;
RawEditor({
@ -30,7 +34,7 @@ class RawEditor extends StatefulWidget {
}
}
class RawEditorState extends State<RawEditor> {
class RawEditorState extends State<RawEditor> implements EditorState {
Note note;
TextEditingController _textController = TextEditingController();
@ -55,78 +59,16 @@ class RawEditorState extends State<RawEditor> {
),
);
var fab = FloatingActionButton(
child: const Icon(Icons.check),
onPressed: () {
_updateNote();
widget.exitEditorSelected(note);
},
);
return Scaffold(
appBar: AppBar(
leading: IconButton(
key: const ValueKey("NewEntry"),
icon: const Icon(Icons.check),
onPressed: () {
_updateNote();
widget.exitEditorSelected(note);
},
),
actions: <Widget>[
IconButton(
icon: const Icon(Icons.library_books),
onPressed: () {
_updateNote();
widget.noteEditorChooserSelected(note);
},
),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () {
_updateNote();
widget.noteDeletionSelected(note);
},
),
PopupMenuButton<DropDownChoices>(
onSelected: (DropDownChoices choice) {
switch (choice) {
case DropDownChoices.Rename:
_updateNote();
widget.renameNoteSelected(note);
return;
case DropDownChoices.MoveToFolder:
_updateNote();
widget.moveNoteToFolderSelected(note);
return;
}
},
itemBuilder: (BuildContext context) =>
<PopupMenuEntry<DropDownChoices>>[
const PopupMenuItem<DropDownChoices>(
value: DropDownChoices.Rename,
child: Text('Edit File Name'),
),
const PopupMenuItem<DropDownChoices>(
value: DropDownChoices.MoveToFolder,
child: Text('Move to Folder'),
),
],
),
],
),
appBar: buildEditorAppBar(widget, this),
floatingActionButton: buildFAB(widget, this),
body: editor,
floatingActionButton: fab,
);
}
void _updateNote() {
note.data = serializer.decode(_textController.text);
}
@override
Note getNote() {
_updateNote();
note.data = serializer.decode(_textController.text);
return note;
}
}