mirror of
https://github.com/GitJournal/GitJournal.git
synced 2025-09-13 23:04:12 +08:00
Add a RawEditing option
This way one can directly modify the YAML to add whatever tags they want.
This commit is contained in:
@ -13,7 +13,7 @@ enum NoteLoadState {
|
|||||||
class Note implements Comparable<Note> {
|
class Note implements Comparable<Note> {
|
||||||
String filePath = "";
|
String filePath = "";
|
||||||
DateTime created;
|
DateTime created;
|
||||||
NoteData data = NoteData();
|
NoteData _data = NoteData();
|
||||||
|
|
||||||
DateTime _fileLastModified;
|
DateTime _fileLastModified;
|
||||||
|
|
||||||
@ -32,6 +32,37 @@ class Note implements Comparable<Note> {
|
|||||||
data.body = newBody;
|
data.body = newBody;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NoteData get data {
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
set data(NoteData data) {
|
||||||
|
_data = data;
|
||||||
|
|
||||||
|
if (data.props.containsKey("created")) {
|
||||||
|
var createdStr = data.props['created'].toString();
|
||||||
|
try {
|
||||||
|
created = DateTime.parse(data.props['created']).toLocal();
|
||||||
|
} catch (ex) {
|
||||||
|
// Ignore it
|
||||||
|
}
|
||||||
|
|
||||||
|
if (created == null) {
|
||||||
|
var regex = RegExp(
|
||||||
|
r"(\d{4})-(\d{2})-(\d{2})T(\d{2})\:(\d{2})\:(\d{2})\+(\d{2})\:(\d{2})");
|
||||||
|
if (regex.hasMatch(createdStr)) {
|
||||||
|
// FIXME: Handle the timezone!
|
||||||
|
createdStr = createdStr.substring(0, 19);
|
||||||
|
created = DateTime.parse(createdStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (created == null) {
|
||||||
|
created = DateTime(0, 0, 0, 0, 0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool hasValidDate() {
|
bool hasValidDate() {
|
||||||
// Arbitrary number, when we set the year = 0, it becomes 1, somehow
|
// Arbitrary number, when we set the year = 0, it becomes 1, somehow
|
||||||
return created.year > 10;
|
return created.year > 10;
|
||||||
@ -58,29 +89,6 @@ class Note implements Comparable<Note> {
|
|||||||
final string = await file.readAsString();
|
final string = await file.readAsString();
|
||||||
data = _serializer.decode(string);
|
data = _serializer.decode(string);
|
||||||
|
|
||||||
if (data.props.containsKey("created")) {
|
|
||||||
var createdStr = data.props['created'].toString();
|
|
||||||
try {
|
|
||||||
created = DateTime.parse(data.props['created']).toLocal();
|
|
||||||
} catch (ex) {
|
|
||||||
// Ignore it
|
|
||||||
}
|
|
||||||
|
|
||||||
if (created == null) {
|
|
||||||
var regex = RegExp(
|
|
||||||
r"(\d{4})-(\d{2})-(\d{2})T(\d{2})\:(\d{2})\:(\d{2})\+(\d{2})\:(\d{2})");
|
|
||||||
if (regex.hasMatch(createdStr)) {
|
|
||||||
// FIXME: Handle the timezone!
|
|
||||||
createdStr = createdStr.substring(0, 19);
|
|
||||||
created = DateTime.parse(createdStr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (created == null) {
|
|
||||||
created = DateTime(0, 0, 0, 0, 0, 0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
_fileLastModified = file.lastModifiedSync();
|
_fileLastModified = file.lastModifiedSync();
|
||||||
_loadState = NoteLoadState.Loaded;
|
_loadState = NoteLoadState.Loaded;
|
||||||
|
|
||||||
|
@ -2,6 +2,9 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:gitjournal/note.dart';
|
import 'package:gitjournal/note.dart';
|
||||||
import 'package:gitjournal/state_container.dart';
|
import 'package:gitjournal/state_container.dart';
|
||||||
import 'package:gitjournal/widgets/note_header.dart';
|
import 'package:gitjournal/widgets/note_header.dart';
|
||||||
|
import 'package:gitjournal/storage/serializers.dart';
|
||||||
|
|
||||||
|
enum NoteEditorDropDownChoices { Discard, RawEditor }
|
||||||
|
|
||||||
class NoteEditor extends StatefulWidget {
|
class NoteEditor extends StatefulWidget {
|
||||||
final Note note;
|
final Note note;
|
||||||
@ -23,6 +26,8 @@ class NoteEditorState extends State<NoteEditor> {
|
|||||||
Note note = Note();
|
Note note = Note();
|
||||||
final bool newNote;
|
final bool newNote;
|
||||||
TextEditingController _textController = TextEditingController();
|
TextEditingController _textController = TextEditingController();
|
||||||
|
bool rawEditor = false;
|
||||||
|
final serializer = MarkdownYAMLSerializer();
|
||||||
|
|
||||||
NoteEditorState() : newNote = true {
|
NoteEditorState() : newNote = true {
|
||||||
note.created = DateTime.now();
|
note.created = DateTime.now();
|
||||||
@ -34,19 +39,15 @@ class NoteEditorState extends State<NoteEditor> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var bodyWidget = Form(
|
Widget editor = Column(
|
||||||
child: TextFormField(
|
children: <Widget>[
|
||||||
autofocus: true,
|
NoteHeader(note),
|
||||||
keyboardType: TextInputType.multiline,
|
NoteMarkdownEditor(_textController),
|
||||||
maxLines: null,
|
],
|
||||||
decoration: InputDecoration(
|
|
||||||
hintText: 'Write here',
|
|
||||||
border: InputBorder.none,
|
|
||||||
),
|
|
||||||
controller: _textController,
|
|
||||||
textCapitalization: TextCapitalization.sentences,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
if (rawEditor) {
|
||||||
|
editor = NoteMarkdownEditor(_textController);
|
||||||
|
}
|
||||||
|
|
||||||
var title = newNote ? "Journal Entry" : "Edit Journal Entry";
|
var title = newNote ? "Journal Entry" : "Edit Journal Entry";
|
||||||
var newJournalScreen = Scaffold(
|
var newJournalScreen = Scaffold(
|
||||||
@ -57,7 +58,11 @@ class NoteEditorState extends State<NoteEditor> {
|
|||||||
icon: Icon(Icons.check),
|
icon: Icon(Icons.check),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
final stateContainer = StateContainer.of(context);
|
final stateContainer = StateContainer.of(context);
|
||||||
|
if (rawEditor == false) {
|
||||||
note.body = _textController.text;
|
note.body = _textController.text;
|
||||||
|
} else {
|
||||||
|
note.data = serializer.decode(_textController.text);
|
||||||
|
}
|
||||||
if (note.body.isNotEmpty) {
|
if (note.body.isNotEmpty) {
|
||||||
newNote
|
newNote
|
||||||
? stateContainer.addNote(note)
|
? stateContainer.addNote(note)
|
||||||
@ -67,27 +72,44 @@ class NoteEditorState extends State<NoteEditor> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
actions: <Widget>[
|
actions: <Widget>[
|
||||||
IconButton(
|
PopupMenuButton<NoteEditorDropDownChoices>(
|
||||||
icon: Icon(Icons.close),
|
onSelected: (NoteEditorDropDownChoices choice) {
|
||||||
onPressed: () {
|
switch (choice) {
|
||||||
|
case NoteEditorDropDownChoices.Discard:
|
||||||
if (_noteModified()) {
|
if (_noteModified()) {
|
||||||
showDialog(context: context, builder: _buildAlertDialog);
|
showDialog(context: context, builder: _buildAlertDialog);
|
||||||
} else {
|
} else {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case NoteEditorDropDownChoices.RawEditor:
|
||||||
|
setState(() {
|
||||||
|
rawEditor = true;
|
||||||
|
var noteData =
|
||||||
|
NoteData(_textController.text, note.data.props);
|
||||||
|
_textController.text = serializer.encode(noteData);
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
itemBuilder: (BuildContext context) =>
|
||||||
|
<PopupMenuEntry<NoteEditorDropDownChoices>>[
|
||||||
|
const PopupMenuItem<NoteEditorDropDownChoices>(
|
||||||
|
value: NoteEditorDropDownChoices.Discard,
|
||||||
|
child: Text('Discard'),
|
||||||
|
),
|
||||||
|
const PopupMenuItem<NoteEditorDropDownChoices>(
|
||||||
|
value: NoteEditorDropDownChoices.RawEditor,
|
||||||
|
child: Text('RawEditor'),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
child: Column(
|
child: editor,
|
||||||
children: <Widget>[
|
|
||||||
NoteHeader(note),
|
|
||||||
bodyWidget,
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -127,9 +149,36 @@ class NoteEditorState extends State<NoteEditor> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (note != null) {
|
if (note != null) {
|
||||||
|
if (rawEditor) {
|
||||||
|
return serializer.encode(note.data) != noteContent;
|
||||||
|
} else {
|
||||||
return noteContent != note.body;
|
return noteContent != note.body;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class NoteMarkdownEditor extends StatelessWidget {
|
||||||
|
final TextEditingController textController;
|
||||||
|
|
||||||
|
NoteMarkdownEditor(this.textController);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Form(
|
||||||
|
child: TextFormField(
|
||||||
|
autofocus: true,
|
||||||
|
keyboardType: TextInputType.multiline,
|
||||||
|
maxLines: null,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: 'Write here',
|
||||||
|
border: InputBorder.none,
|
||||||
|
),
|
||||||
|
controller: textController,
|
||||||
|
textCapitalization: TextCapitalization.sentences,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
name: gitjournal
|
name: gitjournal
|
||||||
description: A Journaling App Built on top of Git
|
description: A Journaling App Built on top of Git
|
||||||
version: 1.1.14+10
|
version: 1.1.15+10
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
|
Reference in New Issue
Block a user