mirror of
https://github.com/GitJournal/GitJournal.git
synced 2025-09-13 06:33:00 +08:00

It's nice to sometimes use the RawEditor to edit something and then later you want to see what it looks, and having to switch to the Markdown Editor for that is very annoying.
208 lines
5.1 KiB
Dart
208 lines
5.1 KiB
Dart
import 'dart:io';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:gitjournal/core/note.dart';
|
|
import 'package:gitjournal/core/notes_folder.dart';
|
|
import 'package:gitjournal/editors/common.dart';
|
|
import 'package:gitjournal/editors/disposable_change_notifier.dart';
|
|
import 'package:gitjournal/editors/heuristics.dart';
|
|
import 'package:gitjournal/editors/note_body_editor.dart';
|
|
import 'package:gitjournal/editors/note_title_editor.dart';
|
|
import 'package:gitjournal/error_reporting.dart';
|
|
import 'package:gitjournal/utils/logger.dart';
|
|
import 'package:gitjournal/widgets/editor_scroll_view.dart';
|
|
|
|
class MarkdownEditor extends StatefulWidget implements Editor {
|
|
final Note note;
|
|
final NotesFolder parentFolder;
|
|
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 isNewNote;
|
|
|
|
MarkdownEditor({
|
|
Key key,
|
|
@required this.note,
|
|
@required this.parentFolder,
|
|
@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.isNewNote,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
MarkdownEditorState createState() {
|
|
return MarkdownEditorState(note);
|
|
}
|
|
}
|
|
|
|
class MarkdownEditorState extends State<MarkdownEditor>
|
|
with DisposableChangeNotifier
|
|
implements EditorState {
|
|
Note note;
|
|
TextEditingController _textController = TextEditingController();
|
|
TextEditingController _titleTextController = TextEditingController();
|
|
|
|
String _oldText;
|
|
|
|
bool _noteModified;
|
|
|
|
MarkdownEditorState(this.note) {
|
|
_textController = TextEditingController(text: note.body);
|
|
_titleTextController = TextEditingController(text: note.title);
|
|
_oldText = note.body;
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_noteModified = widget.noteModified;
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_textController.dispose();
|
|
_titleTextController.dispose();
|
|
|
|
super.disposeListenables();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
void didUpdateWidget(MarkdownEditor oldWidget) {
|
|
super.didUpdateWidget(oldWidget);
|
|
|
|
if (oldWidget.noteModified != widget.noteModified) {
|
|
_noteModified = widget.noteModified;
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
var editor = EditorScrollView(
|
|
child: Column(
|
|
children: <Widget>[
|
|
NoteTitleEditor(
|
|
_titleTextController,
|
|
_noteTextChanged,
|
|
),
|
|
NoteBodyEditor(
|
|
textController: _textController,
|
|
autofocus: widget.isNewNote,
|
|
onChanged: _noteTextChanged,
|
|
),
|
|
],
|
|
),
|
|
);
|
|
|
|
/*
|
|
|
|
var settings = Provider.of<Settings>(context);
|
|
if (settings.experimentalMarkdownToolbar && editingMode) {
|
|
body = Container(
|
|
child: Column(
|
|
children: <Widget>[
|
|
Expanded(child: editor),
|
|
MarkdownToolBar(
|
|
textController: _textController,
|
|
),
|
|
],
|
|
mainAxisSize: MainAxisSize.min,
|
|
),
|
|
);
|
|
}
|
|
*/
|
|
|
|
return EditorScaffold(
|
|
editor: widget,
|
|
editorState: this,
|
|
noteModified: _noteModified,
|
|
isNewNote: widget.isNewNote,
|
|
parentFolder: note.parent,
|
|
body: editor,
|
|
);
|
|
}
|
|
|
|
void _updateNote() {
|
|
note.title = _titleTextController.text.trim();
|
|
note.body = _textController.text.trim();
|
|
note.type = NoteType.Unknown;
|
|
}
|
|
|
|
@override
|
|
Note getNote() {
|
|
_updateNote();
|
|
return note;
|
|
}
|
|
|
|
void _noteTextChanged() {
|
|
try {
|
|
_applyHeuristics();
|
|
} catch (e, stackTrace) {
|
|
Log.e("EditorHeuristics: $e");
|
|
logExceptionWarning(e, stackTrace);
|
|
}
|
|
if (_noteModified && !widget.isNewNote) return;
|
|
|
|
var newState = !(widget.isNewNote && _textController.text.trim().isEmpty);
|
|
if (newState != _noteModified) {
|
|
setState(() {
|
|
_noteModified = newState;
|
|
});
|
|
}
|
|
|
|
notifyListeners();
|
|
}
|
|
|
|
void _applyHeuristics() {
|
|
var selection = _textController.selection;
|
|
if (selection.baseOffset != selection.extentOffset) {
|
|
_oldText = _textController.text;
|
|
return;
|
|
}
|
|
|
|
var r =
|
|
autoAddBulletList(_oldText, _textController.text, selection.baseOffset);
|
|
_oldText = _textController.text;
|
|
|
|
if (r == null) {
|
|
return;
|
|
}
|
|
|
|
_textController.text = r.text;
|
|
_textController.selection = TextSelection.collapsed(offset: r.cursorPos);
|
|
}
|
|
|
|
@override
|
|
Future<void> addImage(File file) async {
|
|
await getNote().addImage(file);
|
|
setState(() {
|
|
_textController.text = note.body;
|
|
_noteModified = true;
|
|
});
|
|
}
|
|
|
|
@override
|
|
bool get noteModified => _noteModified;
|
|
}
|