mirror of
https://github.com/GitJournal/GitJournal.git
synced 2025-06-27 09:06:43 +08:00
Connect the AppState to the Folders
Now when adding/editing/removing a note, it gets modified from the directory it was present in. There is no longer a just a plain list of all notes, but always a tree of notes, which are inside Folders.
This commit is contained in:
@ -1,6 +1,5 @@
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:fimber/fimber.dart';
|
||||
import 'package:gitjournal/core/note.dart';
|
||||
import 'package:gitjournal/core/notes_folder.dart';
|
||||
|
||||
class AppState {
|
||||
@ -24,11 +23,10 @@ class AppState {
|
||||
String gitBaseDirectory = "";
|
||||
|
||||
bool get hasJournalEntries {
|
||||
return notes.isNotEmpty;
|
||||
return notesFolder.hasNotes;
|
||||
}
|
||||
|
||||
List<Note> notes = [];
|
||||
NotesFolder noteFolder;
|
||||
NotesFolder notesFolder;
|
||||
|
||||
AppState(SharedPreferences pref) {
|
||||
localGitRepoConfigured = pref.getBool("localGitRepoConfigured") ?? false;
|
||||
|
@ -3,6 +3,8 @@ import 'dart:io';
|
||||
import 'package:gitjournal/storage/serializers.dart';
|
||||
import 'package:gitjournal/utils/datetime.dart';
|
||||
|
||||
import 'notes_folder.dart';
|
||||
|
||||
enum NoteLoadState {
|
||||
None,
|
||||
Loading,
|
||||
@ -11,7 +13,9 @@ enum NoteLoadState {
|
||||
}
|
||||
|
||||
class Note implements Comparable<Note> {
|
||||
NotesFolder parent;
|
||||
String filePath = "";
|
||||
|
||||
DateTime _created;
|
||||
NoteData _data = NoteData();
|
||||
|
||||
@ -20,7 +24,7 @@ class Note implements Comparable<Note> {
|
||||
var _loadState = NoteLoadState.None;
|
||||
var _serializer = MarkdownYAMLSerializer();
|
||||
|
||||
Note([this.filePath]) {
|
||||
Note(this.parent, [this.filePath]) {
|
||||
_created = _created ?? DateTime(0, 0, 0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,11 @@
|
||||
import 'note.dart';
|
||||
import 'notes_folder.dart';
|
||||
|
||||
// FIXME: Maybe the parent should be a part of the Note, and the NoteFolder
|
||||
// or maybe also a part of the NoteFolder
|
||||
class NoteFSEntity {
|
||||
NotesFolder parent;
|
||||
NotesFolder folder;
|
||||
Note note;
|
||||
|
||||
NoteFSEntity(this.parent, {this.folder, this.note}) {
|
||||
NoteFSEntity({this.folder, this.note}) {
|
||||
assert(folder != null || note != null);
|
||||
}
|
||||
|
||||
|
@ -15,11 +15,11 @@ class FolderListingScreen extends StatelessWidget {
|
||||
final appState = container.appState;
|
||||
|
||||
var treeView = FolderTreeView(
|
||||
rootFolder: appState.noteFolder,
|
||||
rootFolder: appState.notesFolder,
|
||||
onFolderSelected: (NotesFolder folder) {
|
||||
var route = MaterialPageRoute(
|
||||
builder: (context) => JournalListingScreen(
|
||||
noteFolder: folder,
|
||||
notesFolder: folder,
|
||||
),
|
||||
);
|
||||
Navigator.of(context).push(route);
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gitjournal/core/note.dart';
|
||||
import 'package:gitjournal/core/notes_folder.dart';
|
||||
import 'package:gitjournal/state_container.dart';
|
||||
import 'package:gitjournal/widgets/journal_editor_header.dart';
|
||||
import 'package:gitjournal/storage/serializers.dart';
|
||||
@ -8,14 +9,15 @@ enum NoteEditorDropDownChoices { Discard, SwitchEditor }
|
||||
|
||||
class JournalEditor extends StatefulWidget {
|
||||
final Note note;
|
||||
final NotesFolder notesFolder;
|
||||
|
||||
JournalEditor() : note = null;
|
||||
JournalEditor.fromNote(this.note);
|
||||
JournalEditor.fromNote(this.note) : notesFolder = null;
|
||||
JournalEditor.newNote(this.notesFolder) : note = null;
|
||||
|
||||
@override
|
||||
JournalEditorState createState() {
|
||||
if (note == null) {
|
||||
return JournalEditorState();
|
||||
return JournalEditorState.newNote(notesFolder);
|
||||
} else {
|
||||
return JournalEditorState.fromNote(note);
|
||||
}
|
||||
@ -23,13 +25,14 @@ class JournalEditor extends StatefulWidget {
|
||||
}
|
||||
|
||||
class JournalEditorState extends State<JournalEditor> {
|
||||
Note note = Note();
|
||||
Note note;
|
||||
final bool newNote;
|
||||
TextEditingController _textController = TextEditingController();
|
||||
bool rawEditor = false;
|
||||
final serializer = MarkdownYAMLSerializer();
|
||||
|
||||
JournalEditorState() : newNote = true {
|
||||
JournalEditorState.newNote(NotesFolder folder) : newNote = true {
|
||||
note = Note(folder);
|
||||
note.created = DateTime.now();
|
||||
}
|
||||
|
||||
|
@ -12,10 +12,10 @@ import 'package:gitjournal/widgets/journal_list.dart';
|
||||
import 'package:gitjournal/themes.dart';
|
||||
|
||||
class JournalListingScreen extends StatelessWidget {
|
||||
final NotesFolder noteFolder;
|
||||
final NotesFolder notesFolder;
|
||||
final bool recursive;
|
||||
|
||||
JournalListingScreen({@required this.noteFolder, this.recursive = false});
|
||||
JournalListingScreen({@required this.notesFolder, this.recursive = false});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -27,7 +27,9 @@ class JournalListingScreen extends StatelessWidget {
|
||||
child: Icon(Icons.add),
|
||||
);
|
||||
|
||||
var allNotes = recursive ? noteFolder.getAllNotes() : noteFolder.getNotes();
|
||||
var allNotes =
|
||||
recursive ? notesFolder.getAllNotes() : notesFolder.getNotes();
|
||||
allNotes.sort((a, b) => b.compareTo(a));
|
||||
|
||||
Widget journalList = JournalList(
|
||||
notes: allNotes,
|
||||
@ -76,7 +78,8 @@ class JournalListingScreen extends StatelessWidget {
|
||||
}
|
||||
|
||||
void _newPost(BuildContext context) {
|
||||
var route = MaterialPageRoute(builder: (context) => JournalEditor());
|
||||
var route = MaterialPageRoute(
|
||||
builder: (context) => JournalEditor.newNote(notesFolder));
|
||||
Navigator.of(context).push(route);
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ class StateContainerState extends State<StateContainer> {
|
||||
dirName: appState.localGitRepoPath,
|
||||
);
|
||||
}
|
||||
appState.noteFolder = NotesFolder(noteRepo.notesBasePath);
|
||||
appState.notesFolder = NotesFolder(null, noteRepo.notesBasePath);
|
||||
|
||||
// Just a fail safe
|
||||
if (!appState.remoteGitRepoConfigured) {
|
||||
@ -79,25 +79,16 @@ class StateContainerState extends State<StateContainer> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<Note>> _loadNotes() async {
|
||||
await appState.noteFolder.loadRecursively();
|
||||
var notes = appState.noteFolder.getAllNotes();
|
||||
notes.sort((a, b) => b.compareTo(a));
|
||||
|
||||
return notes;
|
||||
Future<void> _loadNotes() async {
|
||||
await appState.notesFolder.loadRecursively();
|
||||
}
|
||||
|
||||
void _loadNotesFromDisk() {
|
||||
Fimber.d("Loading Notes From Disk");
|
||||
_loadNotes().then((loadedNotes) {
|
||||
_loadNotes().then((void _) {
|
||||
setState(() {
|
||||
appState.notes = loadedNotes;
|
||||
|
||||
getAnalytics().logEvent(
|
||||
name: "notes_loaded",
|
||||
parameters: <String, dynamic>{
|
||||
'count': loadedNotes.length,
|
||||
},
|
||||
);
|
||||
});
|
||||
}).catchError((err, stack) {
|
||||
@ -124,9 +115,9 @@ class StateContainerState extends State<StateContainer> {
|
||||
await noteRepo.sync();
|
||||
|
||||
try {
|
||||
var loadedNotes = await _loadNotes();
|
||||
await _loadNotes();
|
||||
setState(() {
|
||||
appState.notes = loadedNotes;
|
||||
// TODO: Inform exactly what notes have changed?
|
||||
});
|
||||
} catch (err, stack) {
|
||||
setState(() {
|
||||
@ -159,8 +150,8 @@ class StateContainerState extends State<StateContainer> {
|
||||
|
||||
void removeNote(Note note) {
|
||||
setState(() {
|
||||
appState.notes.remove(note);
|
||||
noteRepo.removeNote(note).then((NoteRepoResult _) async {
|
||||
note.parent.remove(note);
|
||||
noteRepo.removeNote(note.filePath).then((NoteRepoResult _) async {
|
||||
// FIXME: Is there a way of figuring this amount dynamically?
|
||||
// The '4 seconds' is taken from snack_bar.dart -> _kSnackBarDisplayDuration
|
||||
// We wait an aritfical amount of time, so that the user has a change to undo
|
||||
@ -173,7 +164,7 @@ class StateContainerState extends State<StateContainer> {
|
||||
|
||||
void undoRemoveNote(Note note, int index) {
|
||||
setState(() {
|
||||
appState.notes.insert(index, note);
|
||||
note.parent.insert(index, note);
|
||||
noteRepo.resetLastCommit().then((NoteRepoResult _) {
|
||||
_syncNotes();
|
||||
});
|
||||
@ -181,12 +172,15 @@ class StateContainerState extends State<StateContainer> {
|
||||
}
|
||||
|
||||
void insertNote(int index, Note note) {
|
||||
Fimber.d("State Container insertNote");
|
||||
Fimber.d("State Container insertNote " + index.toString());
|
||||
setState(() {
|
||||
if (note.filePath == null || note.filePath.isEmpty) {
|
||||
note.filePath = p.join(noteRepo.notesBasePath, getFileName(note));
|
||||
var parentPath = note.parent != null
|
||||
? note.parent.folderPath
|
||||
: noteRepo.notesBasePath;
|
||||
note.filePath = p.join(parentPath, getFileName(note));
|
||||
}
|
||||
appState.notes.insert(index, note);
|
||||
note.parent.insert(index, note);
|
||||
noteRepo.addNote(note).then((NoteRepoResult _) {
|
||||
_syncNotes();
|
||||
});
|
||||
@ -196,14 +190,7 @@ class StateContainerState extends State<StateContainer> {
|
||||
void updateNote(Note note) {
|
||||
Fimber.d("State Container updateNote");
|
||||
setState(() {
|
||||
// Update that specific note
|
||||
for (var i = 0; i < appState.notes.length; i++) {
|
||||
var n = appState.notes[i];
|
||||
if (n.filePath == note.filePath) {
|
||||
appState.notes[i] = note;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the git repo
|
||||
noteRepo.updateNote(note).then((NoteRepoResult _) {
|
||||
_syncNotes();
|
||||
});
|
||||
@ -225,7 +212,7 @@ class StateContainerState extends State<StateContainer> {
|
||||
baseDirectory: appState.gitBaseDirectory,
|
||||
dirName: appState.remoteGitRepoFolderName,
|
||||
);
|
||||
appState.noteFolder = NotesFolder(noteRepo.notesBasePath);
|
||||
appState.notesFolder = NotesFolder(null, noteRepo.notesBasePath);
|
||||
|
||||
await _persistConfig();
|
||||
_loadNotesFromDisk();
|
||||
|
@ -50,9 +50,9 @@ class GitNoteRepository {
|
||||
return NoteRepoResult(noteFilePath: note.filePath, error: false);
|
||||
}
|
||||
|
||||
Future<NoteRepoResult> removeNote(Note note) async {
|
||||
Future<NoteRepoResult> removeNote(String noteFilePath) async {
|
||||
var gitDir = p.join(baseDirectory, dirName);
|
||||
var pathSpec = note.filePath.replaceFirst(gitDir, "").substring(1);
|
||||
var pathSpec = noteFilePath.replaceFirst(gitDir, "").substring(1);
|
||||
|
||||
// We are not calling note.remove() as gitRm will also remove the file
|
||||
await _gitRepo.rm(pathSpec);
|
||||
@ -60,7 +60,7 @@ class GitNoteRepository {
|
||||
message: "Removed Journal entry",
|
||||
);
|
||||
|
||||
return NoteRepoResult(noteFilePath: note.filePath, error: false);
|
||||
return NoteRepoResult(noteFilePath: noteFilePath, error: false);
|
||||
}
|
||||
|
||||
Future<NoteRepoResult> resetLastCommit() async {
|
||||
|
@ -25,11 +25,11 @@ void main() {
|
||||
n1Path = p.join(tempDir.path, "1.md");
|
||||
n2Path = p.join(tempDir.path, "2.md");
|
||||
|
||||
var n1 = Note(n1Path);
|
||||
var n1 = Note(null, n1Path);
|
||||
n1.body = "test";
|
||||
n1.created = dt;
|
||||
|
||||
var n2 = Note(n2Path);
|
||||
var n2 = Note(null, n2Path);
|
||||
n2.data = NoteData("test2", props);
|
||||
|
||||
notes = [n1, n2];
|
||||
@ -49,7 +49,7 @@ void main() {
|
||||
|
||||
var loadedNotes = <Note>[];
|
||||
await Future.forEach(notes, (origNote) async {
|
||||
var note = Note(origNote.filePath);
|
||||
var note = Note(null, origNote.filePath);
|
||||
var r = await note.load();
|
||||
expect(r, NoteLoadState.Loaded);
|
||||
|
||||
|
Reference in New Issue
Block a user