Generate one journal entry per day

Fixes #243
This commit is contained in:
Vishesh Handa
2020-09-16 11:01:38 +02:00
parent 0b7448e535
commit 265e253584
14 changed files with 95 additions and 34 deletions

View File

@ -389,6 +389,7 @@ feature:
title: Localization title: Localization
subtitle: Allow GitJournal to be translated subtitle: Allow GitJournal to be translated
inlineTags: Inline Tags inlineTags: Inline Tags
singleJournalEntry: Single Journal Entry File per day
feature_timeline: feature_timeline:
title: Feature Timeline title: Feature Timeline

View File

@ -5,6 +5,9 @@
- text: "Implement Basic Search highlighting #14" - text: "Implement Basic Search highlighting #14"
- text: Implement basic note selection - text: Implement basic note selection
image: note_select_delete.gif image: note_select_delete.gif
- title: Single Journal entry Per Day
text: Some users prefer all the journal entries for a single day be in the same file. This matches with how Obsidian and Foam handle daily notes.
image: single_journal_entry.jpeg
improvements: improvements:
- title: Purchase Screen - title: Purchase Screen
text: Make it prettier for smaller screen sizes text: Make it prettier for smaller screen sizes

View File

@ -31,7 +31,7 @@ class ChecklistEditor extends StatefulWidget implements Editor {
@override @override
final NoteCallback discardChangesSelected; final NoteCallback discardChangesSelected;
final bool isNewNote; final bool editMode;
ChecklistEditor({ ChecklistEditor({
Key key, Key key,
@ -44,7 +44,7 @@ class ChecklistEditor extends StatefulWidget implements Editor {
@required this.editTagsSelected, @required this.editTagsSelected,
@required this.moveNoteToFolderSelected, @required this.moveNoteToFolderSelected,
@required this.discardChangesSelected, @required this.discardChangesSelected,
@required this.isNewNote, @required this.editMode,
}) : super(key: key); }) : super(key: key);
@override @override
@ -127,7 +127,7 @@ class ChecklistEditorState extends State<ChecklistEditor>
var itemTiles = <Widget>[]; var itemTiles = <Widget>[];
for (var i = 0; i < checklist.items.length; i++) { for (var i = 0; i < checklist.items.length; i++) {
var item = checklist.items[i]; var item = checklist.items[i];
var autofocus = widget.isNewNote && (i == checklist.items.length - 1); var autofocus = widget.editMode && (i == checklist.items.length - 1);
itemTiles.add(_buildTile(item, i, autofocus)); itemTiles.add(_buildTile(item, i, autofocus));
} }
itemTiles.add(AddItemButton( itemTiles.add(AddItemButton(
@ -174,7 +174,7 @@ class ChecklistEditorState extends State<ChecklistEditor>
editor: widget, editor: widget,
editorState: this, editorState: this,
noteModified: _noteModified, noteModified: _noteModified,
isNewNote: widget.isNewNote, editMode: widget.editMode,
parentFolder: widget.note.parent, parentFolder: widget.note.parent,
body: Column( body: Column(
children: <Widget>[ children: <Widget>[

View File

@ -28,7 +28,7 @@ class JournalEditor extends StatefulWidget implements Editor {
@override @override
final NoteCallback discardChangesSelected; final NoteCallback discardChangesSelected;
final bool isNewNote; final bool editMode;
JournalEditor({ JournalEditor({
Key key, Key key,
@ -41,7 +41,7 @@ class JournalEditor extends StatefulWidget implements Editor {
@required this.editTagsSelected, @required this.editTagsSelected,
@required this.moveNoteToFolderSelected, @required this.moveNoteToFolderSelected,
@required this.discardChangesSelected, @required this.discardChangesSelected,
this.isNewNote = false, this.editMode = false,
}) : super(key: key); }) : super(key: key);
@override @override
@ -92,7 +92,7 @@ class JournalEditorState extends State<JournalEditor>
JournalEditorHeader(note), JournalEditorHeader(note),
NoteBodyEditor( NoteBodyEditor(
textController: _textController, textController: _textController,
autofocus: widget.isNewNote, autofocus: widget.editMode,
onChanged: _noteTextChanged, onChanged: _noteTextChanged,
), ),
], ],
@ -103,7 +103,7 @@ class JournalEditorState extends State<JournalEditor>
editor: widget, editor: widget,
editorState: this, editorState: this,
noteModified: _noteModified, noteModified: _noteModified,
isNewNote: widget.isNewNote, editMode: widget.editMode,
parentFolder: note.parent, parentFolder: note.parent,
body: editor, body: editor,
); );
@ -117,12 +117,12 @@ class JournalEditorState extends State<JournalEditor>
} }
void _noteTextChanged() { void _noteTextChanged() {
if (_noteModified && !widget.isNewNote) { if (_noteModified && !widget.editMode) {
notifyListeners(); notifyListeners();
return; return;
} }
var newState = !(widget.isNewNote && _textController.text.trim().isEmpty); var newState = !(widget.editMode && _textController.text.trim().isEmpty);
if (newState != _noteModified) { if (newState != _noteModified) {
setState(() { setState(() {
_noteModified = newState; _noteModified = newState;

View File

@ -33,7 +33,7 @@ class MarkdownEditor extends StatefulWidget implements Editor {
@override @override
final NoteCallback discardChangesSelected; final NoteCallback discardChangesSelected;
final bool isNewNote; final bool editMode;
MarkdownEditor({ MarkdownEditor({
Key key, Key key,
@ -47,7 +47,7 @@ class MarkdownEditor extends StatefulWidget implements Editor {
@required this.editTagsSelected, @required this.editTagsSelected,
@required this.moveNoteToFolderSelected, @required this.moveNoteToFolderSelected,
@required this.discardChangesSelected, @required this.discardChangesSelected,
@required this.isNewNote, @required this.editMode,
}) : super(key: key); }) : super(key: key);
@override @override
@ -108,7 +108,7 @@ class MarkdownEditorState extends State<MarkdownEditor>
), ),
NoteBodyEditor( NoteBodyEditor(
textController: _textController, textController: _textController,
autofocus: widget.isNewNote, autofocus: widget.editMode,
onChanged: _noteTextChanged, onChanged: _noteTextChanged,
), ),
], ],
@ -137,7 +137,7 @@ class MarkdownEditorState extends State<MarkdownEditor>
editor: widget, editor: widget,
editorState: this, editorState: this,
noteModified: _noteModified, noteModified: _noteModified,
isNewNote: widget.isNewNote, editMode: widget.editMode,
parentFolder: note.parent, parentFolder: note.parent,
body: editor, body: editor,
); );
@ -162,9 +162,9 @@ class MarkdownEditorState extends State<MarkdownEditor>
Log.e("EditorHeuristics: $e"); Log.e("EditorHeuristics: $e");
logExceptionWarning(e, stackTrace); logExceptionWarning(e, stackTrace);
} }
if (_noteModified && !widget.isNewNote) return; if (_noteModified && !widget.editMode) return;
var newState = !(widget.isNewNote && _textController.text.trim().isEmpty); var newState = !(widget.editMode && _textController.text.trim().isEmpty);
if (newState != _noteModified) { if (newState != _noteModified) {
setState(() { setState(() {
_noteModified = newState; _noteModified = newState;

View File

@ -29,7 +29,7 @@ class RawEditor extends StatefulWidget implements Editor {
@override @override
final NoteCallback discardChangesSelected; final NoteCallback discardChangesSelected;
final bool isNewNote; final bool editMode;
RawEditor({ RawEditor({
Key key, Key key,
@ -42,7 +42,7 @@ class RawEditor extends StatefulWidget implements Editor {
@required this.editTagsSelected, @required this.editTagsSelected,
@required this.moveNoteToFolderSelected, @required this.moveNoteToFolderSelected,
@required this.discardChangesSelected, @required this.discardChangesSelected,
@required this.isNewNote, @required this.editMode,
}) : super(key: key); }) : super(key: key);
@override @override
@ -92,7 +92,7 @@ class RawEditorState extends State<RawEditor>
var editor = EditorScrollView( var editor = EditorScrollView(
child: _NoteEditor( child: _NoteEditor(
textController: _textController, textController: _textController,
autofocus: widget.isNewNote, autofocus: widget.editMode,
onChanged: _noteTextChanged, onChanged: _noteTextChanged,
), ),
); );
@ -101,7 +101,7 @@ class RawEditorState extends State<RawEditor>
editor: widget, editor: widget,
editorState: this, editorState: this,
noteModified: _noteModified, noteModified: _noteModified,
isNewNote: widget.isNewNote, editMode: widget.editMode,
parentFolder: note.parent, parentFolder: note.parent,
body: editor, body: editor,
); );

View File

@ -12,7 +12,7 @@ class EditorScaffold extends StatefulWidget {
final Editor editor; final Editor editor;
final EditorState editorState; final EditorState editorState;
final bool noteModified; final bool noteModified;
final bool isNewNote; final bool editMode;
final IconButton extraButton; final IconButton extraButton;
final Widget body; final Widget body;
final NotesFolderFS parentFolder; final NotesFolderFS parentFolder;
@ -21,7 +21,7 @@ class EditorScaffold extends StatefulWidget {
@required this.editor, @required this.editor,
@required this.editorState, @required this.editorState,
@required this.noteModified, @required this.noteModified,
@required this.isNewNote, @required this.editMode,
@required this.body, @required this.body,
@required this.parentFolder, @required this.parentFolder,
this.extraButton, this.extraButton,
@ -53,7 +53,7 @@ class _EditorScaffoldState extends State<EditorScaffold> {
settings.markdownDefaultView == SettingsMarkdownDefaultView.Edit; settings.markdownDefaultView == SettingsMarkdownDefaultView.Edit;
} }
if (widget.isNewNote) { if (widget.editMode) {
editingMode = true; editingMode = true;
} }

View File

@ -38,6 +38,7 @@ class Features {
Feature.customMetaData, Feature.customMetaData,
Feature.localization, Feature.localization,
Feature.inlineTags, Feature.inlineTags,
Feature.singleJournalEntry,
]; ];
static final inProgress = <String>[ static final inProgress = <String>[
@ -328,6 +329,14 @@ class Feature {
"", "",
true, true,
); );
static final singleJournalEntry = Feature(
"singleJournalEntry",
DateTime(2020, 09, 16),
tr("feature.singleJournalEntry"),
"",
true,
);
} }
// Feature Adding checklist // Feature Adding checklist

View File

@ -79,10 +79,11 @@ Widget buildFolderView({
void openNoteEditor( void openNoteEditor(
BuildContext context, BuildContext context,
Note note, Note note,
NotesFolder parentFolder, NotesFolder parentFolder, {
) async { bool editMode = false,
}) async {
var route = MaterialPageRoute( var route = MaterialPageRoute(
builder: (context) => NoteEditor.fromNote(note, parentFolder), builder: (context) => NoteEditor.fromNote(note, parentFolder, editMode: editMode),
settings: const RouteSettings(name: '/note/'), settings: const RouteSettings(name: '/note/'),
); );
var showUndoSnackBar = await Navigator.of(context).push(route); var showUndoSnackBar = await Navigator.of(context).push(route);

View File

@ -169,10 +169,22 @@ class _FolderViewState extends State<FolderView> {
fsFolder = getFolderForEditor(settings, rootFolder, editorType); fsFolder = getFolderForEditor(settings, rootFolder, editorType);
} }
var settings = Provider.of<Settings>(context);
if (editorType == EditorType.Journal) {
if (settings.journalEditorSingleNote) {
var note = await getTodayJournalEntry(fsFolder.rootFolder);
return openNoteEditor(
context,
note,
widget.notesFolder,
editMode: true,
);
}
}
var routeType = var routeType =
SettingsEditorType.fromEditorType(editorType).toInternalString(); SettingsEditorType.fromEditorType(editorType).toInternalString();
var settings = Provider.of<Settings>(context);
var extraProps = Map<String, dynamic>.from(widget.newNoteExtraProps); var extraProps = Map<String, dynamic>.from(widget.newNoteExtraProps);
if (settings.customMetaData.isNotEmpty) { if (settings.customMetaData.isNotEmpty) {
var map = MarkdownYAMLCodec.parseYamlText(settings.customMetaData); var map = MarkdownYAMLCodec.parseYamlText(settings.customMetaData);

View File

@ -37,9 +37,13 @@ class NoteEditor extends StatefulWidget {
final List<String> existingImages; final List<String> existingImages;
final Map<String, dynamic> newNoteExtraProps; final Map<String, dynamic> newNoteExtraProps;
final bool editMode;
NoteEditor.fromNote(this.note, this.parentFolderView) NoteEditor.fromNote(
: notesFolder = note.parent, this.note,
this.parentFolderView, {
this.editMode = false,
}) : notesFolder = note.parent,
defaultEditorType = null, defaultEditorType = null,
existingText = null, existingText = null,
existingImages = null, existingImages = null,
@ -52,7 +56,8 @@ class NoteEditor extends StatefulWidget {
this.existingText, this.existingText,
this.existingImages, this.existingImages,
this.newNoteExtraProps = const {}, this.newNoteExtraProps = const {},
}) : note = null; }) : note = null,
editMode = true;
@override @override
NoteEditorState createState() { NoteEditorState createState() {
@ -164,7 +169,7 @@ class NoteEditorState extends State<NoteEditor> {
editTagsSelected: _editTagsSelected, editTagsSelected: _editTagsSelected,
moveNoteToFolderSelected: _moveNoteToFolderSelected, moveNoteToFolderSelected: _moveNoteToFolderSelected,
discardChangesSelected: _discardChangesSelected, discardChangesSelected: _discardChangesSelected,
isNewNote: _isNewNote, editMode: widget.editMode
); );
case EditorType.Raw: case EditorType.Raw:
return RawEditor( return RawEditor(
@ -178,7 +183,7 @@ class NoteEditorState extends State<NoteEditor> {
editTagsSelected: _editTagsSelected, editTagsSelected: _editTagsSelected,
moveNoteToFolderSelected: _moveNoteToFolderSelected, moveNoteToFolderSelected: _moveNoteToFolderSelected,
discardChangesSelected: _discardChangesSelected, discardChangesSelected: _discardChangesSelected,
isNewNote: _isNewNote, editMode: widget.editMode
); );
case EditorType.Checklist: case EditorType.Checklist:
return ChecklistEditor( return ChecklistEditor(
@ -192,7 +197,7 @@ class NoteEditorState extends State<NoteEditor> {
editTagsSelected: _editTagsSelected, editTagsSelected: _editTagsSelected,
moveNoteToFolderSelected: _moveNoteToFolderSelected, moveNoteToFolderSelected: _moveNoteToFolderSelected,
discardChangesSelected: _discardChangesSelected, discardChangesSelected: _discardChangesSelected,
isNewNote: _isNewNote, editMode: widget.editMode
); );
case EditorType.Journal: case EditorType.Journal:
return JournalEditor( return JournalEditor(
@ -206,7 +211,7 @@ class NoteEditorState extends State<NoteEditor> {
editTagsSelected: _editTagsSelected, editTagsSelected: _editTagsSelected,
moveNoteToFolderSelected: _moveNoteToFolderSelected, moveNoteToFolderSelected: _moveNoteToFolderSelected,
discardChangesSelected: _discardChangesSelected, discardChangesSelected: _discardChangesSelected,
isNewNote: _isNewNote, editMode: widget.editMode
); );
} }
return null; return null;

View File

@ -81,6 +81,18 @@ class SettingsEditorsScreenState extends State<SettingsEditorsScreen> {
}, },
), ),
), ),
ProOverlay(
feature: Feature.singleJournalEntry,
child: SwitchListTile(
title: Text(tr("feature.singleJournalEntry")),
value: settings.journalEditorSingleNote,
onChanged: (bool newVal) {
settings.journalEditorSingleNote = newVal;
settings.save();
setState(() {});
},
),
),
]); ]);
return Scaffold( return Scaffold(

View File

@ -35,6 +35,7 @@ class Settings extends ChangeNotifier {
bool yamlHeaderEnabled = true; bool yamlHeaderEnabled = true;
String defaultNewNoteFolderSpec = ""; String defaultNewNoteFolderSpec = "";
String journalEditordefaultNewNoteFolderSpec = ""; String journalEditordefaultNewNoteFolderSpec = "";
bool journalEditorSingleNote = false;
RemoteSyncFrequency remoteSyncFrequency = RemoteSyncFrequency.Default; RemoteSyncFrequency remoteSyncFrequency = RemoteSyncFrequency.Default;
SortingField sortingField = SortingField.Default; SortingField sortingField = SortingField.Default;
@ -99,6 +100,8 @@ class Settings extends ChangeNotifier {
journalEditordefaultNewNoteFolderSpec = journalEditordefaultNewNoteFolderSpec =
pref.getString("journalEditordefaultNewNoteFolderSpec") ?? pref.getString("journalEditordefaultNewNoteFolderSpec") ??
journalEditordefaultNewNoteFolderSpec; journalEditordefaultNewNoteFolderSpec;
journalEditorSingleNote =
pref.getBool("journalEditorSingleNote") ?? journalEditorSingleNote;
remoteSyncFrequency = RemoteSyncFrequency.fromInternalString( remoteSyncFrequency = RemoteSyncFrequency.fromInternalString(
pref.getString("remoteSyncFrequency")); pref.getString("remoteSyncFrequency"));
@ -191,6 +194,8 @@ class Settings extends ChangeNotifier {
"journalEditordefaultNewNoteFolderSpec", "journalEditordefaultNewNoteFolderSpec",
journalEditordefaultNewNoteFolderSpec, journalEditordefaultNewNoteFolderSpec,
defaultSet.journalEditordefaultNewNoteFolderSpec); defaultSet.journalEditordefaultNewNoteFolderSpec);
_setBool(pref, "journalEditorSingleNote", journalEditorSingleNote,
defaultSet.journalEditorSingleNote);
_setString( _setString(
pref, pref,
"remoteSyncFrequency", "remoteSyncFrequency",
@ -300,6 +305,7 @@ class Settings extends ChangeNotifier {
"defaultNewNoteFolderSpec": defaultNewNoteFolderSpec, "defaultNewNoteFolderSpec": defaultNewNoteFolderSpec,
"journalEditordefaultNewNoteFolderSpec": "journalEditordefaultNewNoteFolderSpec":
journalEditordefaultNewNoteFolderSpec, journalEditordefaultNewNoteFolderSpec,
'journalEditorSingleNote': journalEditorSingleNote.toString(),
"defaultEditor": defaultEditor.toInternalString(), "defaultEditor": defaultEditor.toInternalString(),
"defaultView": defaultView.toInternalString(), "defaultView": defaultView.toInternalString(),
"sortingField": sortingField.toInternalString(), "sortingField": sortingField.toInternalString(),

View File

@ -93,3 +93,15 @@ String toCurlCommand(String url, Map<String, String> headers) {
Future<void> shareNote(Note note) async { Future<void> shareNote(Note note) async {
return Share.share(note.body); return Share.share(note.body);
} }
Future<Note> getTodayJournalEntry(NotesFolderFS rootFolder) async {
var today = DateTime.now();
var matches = await rootFolder.matchNotes((n) async {
var dt = n.created;
return dt.year == today.year &&
dt.month == today.month &&
dt.day == today.day;
});
return matches.isNotEmpty ? matches[0] : null;
}