mirror of
https://github.com/GitJournal/GitJournal.git
synced 2025-07-21 07:03:25 +08:00
OrgEditor
This commit is contained in:

committed by
Vishesh Handa

parent
746c374d48
commit
93cf6433d6
@ -159,6 +159,7 @@ settings:
|
||||
journalEditor: Journal Editor
|
||||
defaultFolder: Default Folder
|
||||
checklistEditor: Checklist Editor
|
||||
orgEditor: Org Editor
|
||||
rawEditor: Raw Editor
|
||||
choose: Choose Editor
|
||||
sortingField:
|
||||
|
@ -46,11 +46,7 @@ enum NoteLoadState {
|
||||
Error,
|
||||
}
|
||||
|
||||
enum NoteType {
|
||||
Unknown,
|
||||
Checklist,
|
||||
Journal,
|
||||
}
|
||||
enum NoteType { Unknown, Checklist, Journal, Org }
|
||||
|
||||
class NoteFileFormatInfo {
|
||||
static List<String> allowedExtensions = ['.md', '.org', '.txt'];
|
||||
|
197
lib/editors/org_editor.dart
Normal file
197
lib/editors/org_editor.dart
Normal file
@ -0,0 +1,197 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
|
||||
import 'package:gitjournal/core/md_yaml_doc_codec.dart';
|
||||
import 'package:gitjournal/core/note.dart';
|
||||
import 'package:gitjournal/editors/common.dart';
|
||||
import 'package:gitjournal/editors/disposable_change_notifier.dart';
|
||||
import 'package:gitjournal/editors/undo_redo.dart';
|
||||
import 'package:gitjournal/widgets/editor_scroll_view.dart';
|
||||
|
||||
class OrgEditor extends StatefulWidget implements Editor {
|
||||
final Note note;
|
||||
final bool noteModified;
|
||||
|
||||
@override
|
||||
final NoteCallback noteDeletionSelected;
|
||||
@override
|
||||
final NoteCallback noteEditorChooserSelected;
|
||||
@override
|
||||
final NoteCallback exitEditorSelected;
|
||||
@override
|
||||
final NoteCallback renameNoteSelected;
|
||||
@override
|
||||
final NoteCallback editTagsSelected;
|
||||
@override
|
||||
final NoteCallback moveNoteToFolderSelected;
|
||||
@override
|
||||
final NoteCallback discardChangesSelected;
|
||||
|
||||
final bool editMode;
|
||||
|
||||
OrgEditor({
|
||||
Key key,
|
||||
@required this.note,
|
||||
@required this.noteModified,
|
||||
@required this.noteDeletionSelected,
|
||||
@required this.noteEditorChooserSelected,
|
||||
@required this.exitEditorSelected,
|
||||
@required this.renameNoteSelected,
|
||||
@required this.editTagsSelected,
|
||||
@required this.moveNoteToFolderSelected,
|
||||
@required this.discardChangesSelected,
|
||||
@required this.editMode,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
OrgEditorState createState() {
|
||||
return OrgEditorState(note);
|
||||
}
|
||||
}
|
||||
|
||||
class OrgEditorState extends State<OrgEditor>
|
||||
with DisposableChangeNotifier
|
||||
implements EditorState {
|
||||
Note note;
|
||||
bool _noteModified;
|
||||
TextEditingController _textController;
|
||||
UndoRedoStack _undoRedoStack;
|
||||
|
||||
final serializer = MarkdownYAMLCodec();
|
||||
|
||||
OrgEditorState(this.note) {
|
||||
_textController = TextEditingController(text: serializer.encode(note.data));
|
||||
_undoRedoStack = UndoRedoStack();
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_noteModified = widget.noteModified;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_textController.dispose();
|
||||
|
||||
super.disposeListenables();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(OrgEditor oldWidget) {
|
||||
super.didUpdateWidget(oldWidget);
|
||||
|
||||
if (oldWidget.noteModified != widget.noteModified) {
|
||||
_noteModified = widget.noteModified;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var editor = EditorScrollView(
|
||||
child: _NoteEditor(
|
||||
textController: _textController,
|
||||
autofocus: widget.editMode,
|
||||
onChanged: _noteTextChanged,
|
||||
),
|
||||
);
|
||||
|
||||
return EditorScaffold(
|
||||
editor: widget,
|
||||
editorState: this,
|
||||
noteModified: _noteModified,
|
||||
editMode: widget.editMode,
|
||||
parentFolder: note.parent,
|
||||
body: editor,
|
||||
onUndoSelected: _undo,
|
||||
onRedoSelected: _redo,
|
||||
undoAllowed: _undoRedoStack.undoPossible,
|
||||
redoAllowed: _undoRedoStack.redoPossible,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Note getNote() {
|
||||
note.data = serializer.decode(_textController.text);
|
||||
return note;
|
||||
}
|
||||
|
||||
void _noteTextChanged() {
|
||||
notifyListeners();
|
||||
|
||||
var editState = TextEditorState.fromValue(_textController.value);
|
||||
var redraw = _undoRedoStack.textChanged(editState);
|
||||
if (redraw) {
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
if (_noteModified) return;
|
||||
setState(() {
|
||||
_noteModified = true;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> addImage(File file) async {
|
||||
await getNote().addImage(file);
|
||||
setState(() {
|
||||
_textController.text = note.body;
|
||||
_noteModified = true;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
bool get noteModified => _noteModified;
|
||||
|
||||
Future<void> _undo() async {
|
||||
var es = _undoRedoStack.undo();
|
||||
_textController.value = es.toValue();
|
||||
setState(() {
|
||||
// To Redraw the undo/redo button state
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _redo() async {
|
||||
var es = _undoRedoStack.redo();
|
||||
_textController.value = es.toValue();
|
||||
setState(() {
|
||||
// To Redraw the undo/redo button state
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class _NoteEditor extends StatelessWidget {
|
||||
final TextEditingController textController;
|
||||
final bool autofocus;
|
||||
final Function onChanged;
|
||||
|
||||
_NoteEditor({this.textController, this.autofocus, this.onChanged});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var style = Theme.of(context)
|
||||
.textTheme
|
||||
.subtitle1
|
||||
.copyWith(fontFamily: "Roboto Mono");
|
||||
|
||||
return TextField(
|
||||
autofocus: autofocus,
|
||||
keyboardType: TextInputType.multiline,
|
||||
maxLines: null,
|
||||
style: style,
|
||||
decoration: InputDecoration(
|
||||
hintText: tr('editors.common.defaultBodyHint'),
|
||||
border: InputBorder.none,
|
||||
isDense: true,
|
||||
),
|
||||
controller: textController,
|
||||
textCapitalization: TextCapitalization.sentences,
|
||||
scrollPadding: const EdgeInsets.all(0.0),
|
||||
onChanged: (_) => onChanged(),
|
||||
);
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:gitjournal/editors/org_editor.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'package:gitjournal/core/md_yaml_doc.dart';
|
||||
@ -79,7 +80,7 @@ class NoteEditor extends StatefulWidget {
|
||||
}
|
||||
}
|
||||
|
||||
enum EditorType { Markdown, Raw, Checklist, Journal }
|
||||
enum EditorType { Markdown, Raw, Checklist, Journal, Org }
|
||||
|
||||
class NoteEditorState extends State<NoteEditor> with WidgetsBindingObserver {
|
||||
Note note;
|
||||
@ -90,6 +91,7 @@ class NoteEditorState extends State<NoteEditor> with WidgetsBindingObserver {
|
||||
final _markdownEditorKey = GlobalKey<MarkdownEditorState>();
|
||||
final _checklistEditorKey = GlobalKey<ChecklistEditorState>();
|
||||
final _journalEditorKey = GlobalKey<JournalEditorState>();
|
||||
final _orgEditorKey = GlobalKey<OrgEditorState>();
|
||||
|
||||
bool get _isNewNote {
|
||||
return widget.note == null;
|
||||
@ -138,6 +140,9 @@ class NoteEditorState extends State<NoteEditor> with WidgetsBindingObserver {
|
||||
case NoteType.Checklist:
|
||||
editorType = EditorType.Checklist;
|
||||
break;
|
||||
case NoteType.Org:
|
||||
editorType = EditorType.Org;
|
||||
break;
|
||||
case NoteType.Unknown:
|
||||
editorType = widget.notesFolder.config.defaultEditor;
|
||||
break;
|
||||
@ -147,7 +152,7 @@ class NoteEditorState extends State<NoteEditor> with WidgetsBindingObserver {
|
||||
// Org files
|
||||
if (note.fileFormat == NoteFileFormat.OrgMode &&
|
||||
editorType == EditorType.Markdown) {
|
||||
editorType = EditorType.Raw;
|
||||
editorType = EditorType.Org;
|
||||
}
|
||||
|
||||
// Txt files
|
||||
@ -166,6 +171,7 @@ class NoteEditorState extends State<NoteEditor> with WidgetsBindingObserver {
|
||||
@override
|
||||
void didChangeAppLifecycleState(AppLifecycleState state) {
|
||||
Log.i("Note Edit State: $state");
|
||||
|
||||
if (state != AppLifecycleState.resumed) {
|
||||
var note = _getNoteFromEditor();
|
||||
if (!_noteModified(note)) return;
|
||||
@ -245,6 +251,20 @@ class NoteEditorState extends State<NoteEditor> with WidgetsBindingObserver {
|
||||
discardChangesSelected: _discardChangesSelected,
|
||||
editMode: widget.editMode,
|
||||
);
|
||||
case EditorType.Org:
|
||||
return OrgEditor(
|
||||
key: _orgEditorKey,
|
||||
note: note,
|
||||
noteModified: _noteModified(note),
|
||||
noteDeletionSelected: _noteDeletionSelected,
|
||||
noteEditorChooserSelected: _noteEditorChooserSelected,
|
||||
exitEditorSelected: _exitEditorSelected,
|
||||
renameNoteSelected: _renameNoteSelected,
|
||||
editTagsSelected: _editTagsSelected,
|
||||
moveNoteToFolderSelected: _moveNoteToFolderSelected,
|
||||
discardChangesSelected: _discardChangesSelected,
|
||||
editMode: widget.editMode,
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@ -388,6 +408,8 @@ class NoteEditorState extends State<NoteEditor> with WidgetsBindingObserver {
|
||||
return _checklistEditorKey.currentState.getNote();
|
||||
case EditorType.Journal:
|
||||
return _journalEditorKey.currentState.getNote();
|
||||
case EditorType.Org:
|
||||
return _orgEditorKey.currentState.getNote();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -661,6 +661,7 @@ class SettingsEditorType {
|
||||
SettingsEditorType('settings.editors.journalEditor', "Journal");
|
||||
static const Checklist =
|
||||
SettingsEditorType('settings.editors.checklistEditor', "Checklist");
|
||||
static const Org = SettingsEditorType('settings.editors.orgEditor', "Org");
|
||||
static const Default = Markdown;
|
||||
|
||||
final String _str;
|
||||
@ -700,6 +701,8 @@ class SettingsEditorType {
|
||||
return SettingsEditorType.Markdown;
|
||||
case EditorType.Journal:
|
||||
return SettingsEditorType.Journal;
|
||||
case EditorType.Org:
|
||||
return SettingsEditorType.Org;
|
||||
}
|
||||
return SettingsEditorType.Default;
|
||||
}
|
||||
|
@ -57,6 +57,8 @@ class NoteEditorSelector extends StatelessWidget {
|
||||
tr('settings.editors.journalEditor'),
|
||||
FontAwesomeIcons.book,
|
||||
),
|
||||
_buildTile(context, EditorType.Org, tr('settings.editors.orgEditor'),
|
||||
FontAwesomeIcons.horseHead)
|
||||
],
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
);
|
||||
|
Reference in New Issue
Block a user