mirror of
https://github.com/GitJournal/GitJournal.git
synced 2025-06-30 19:36:25 +08:00
Refactor: Remove FileStorage
With this, the application compiles again. And note editing is working again. This is was the first of some small refactors in order to implement both async note loading and a support for directories.
This commit is contained in:
@ -100,6 +100,7 @@ int gj_git_rm(const char *git_base_path, const char *pattern)
|
|||||||
char *paths[] = {(char *)pattern};
|
char *paths[] = {(char *)pattern};
|
||||||
git_strarray pathspec = {paths, 1};
|
git_strarray pathspec = {paths, 1};
|
||||||
|
|
||||||
|
gj_log_internal("Calling git rm with pathspec %s", pattern);
|
||||||
err = git_index_remove_all(index, &pathspec, rm_match_cb, (void *)git_base_path);
|
err = git_index_remove_all(index, &pathspec, rm_match_cb, (void *)git_base_path);
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -25,8 +25,6 @@ class Note implements Comparable<Note> {
|
|||||||
created = created ?? DateTime(0, 0, 0, 0, 0, 0, 0, 0);
|
created = created ?? DateTime(0, 0, 0, 0, 0, 0, 0, 0);
|
||||||
props = props ?? <String, dynamic>{};
|
props = props ?? <String, dynamic>{};
|
||||||
body = body ?? "";
|
body = body ?? "";
|
||||||
|
|
||||||
assert(filePath != null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasValidDate() {
|
bool hasValidDate() {
|
||||||
@ -80,6 +78,8 @@ class Note implements Comparable<Note> {
|
|||||||
|
|
||||||
// FIXME: What about error handling?
|
// FIXME: What about error handling?
|
||||||
Future<void> save() async {
|
Future<void> save() async {
|
||||||
|
assert(filePath != null);
|
||||||
|
|
||||||
if (hasValidDate()) {
|
if (hasValidDate()) {
|
||||||
props['created'] = toIso8601WithTimezone(created);
|
props['created'] = toIso8601WithTimezone(created);
|
||||||
}
|
}
|
||||||
|
@ -217,7 +217,7 @@ class StateContainerState extends State<StateContainer> {
|
|||||||
Fimber.d("State Container insertNote");
|
Fimber.d("State Container insertNote");
|
||||||
setState(() {
|
setState(() {
|
||||||
if (note.filePath == null || note.filePath.isEmpty) {
|
if (note.filePath == null || note.filePath.isEmpty) {
|
||||||
note.filePath = getFileName(note);
|
note.filePath = p.join(noteRepo.notesBasePath, getFileName(note));
|
||||||
}
|
}
|
||||||
appState.notes.insert(index, note);
|
appState.notes.insert(index, note);
|
||||||
appState.hasJournalEntries = true;
|
appState.hasJournalEntries = true;
|
||||||
|
@ -1,108 +0,0 @@
|
|||||||
import 'dart:async';
|
|
||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:fimber/fimber.dart';
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:journal/note.dart';
|
|
||||||
import 'package:journal/storage/notes_repository.dart';
|
|
||||||
import 'package:journal/storage/serializers.dart';
|
|
||||||
import 'package:path/path.dart' as p;
|
|
||||||
|
|
||||||
/// Each Note is saved in a different file
|
|
||||||
/// Each note must have a fileName which ends in a .md
|
|
||||||
class FileStorage implements NoteRepository {
|
|
||||||
final String baseDirectory;
|
|
||||||
final NoteSerializer noteSerializer;
|
|
||||||
|
|
||||||
FileStorage({
|
|
||||||
@required this.baseDirectory,
|
|
||||||
@required this.noteSerializer,
|
|
||||||
}) {
|
|
||||||
assert(baseDirectory != null);
|
|
||||||
assert(baseDirectory.isNotEmpty);
|
|
||||||
Fimber.d("FileStorage Directory: " + baseDirectory);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<List<Note>> listNotes() async {
|
|
||||||
final dir = Directory(baseDirectory);
|
|
||||||
|
|
||||||
var notes = <Note>[];
|
|
||||||
var lister = dir.list(recursive: false);
|
|
||||||
await for (var fileEntity in lister) {
|
|
||||||
Note note = await _loadNote(fileEntity);
|
|
||||||
if (note == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!note.filePath.toLowerCase().endsWith('.md')) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
notes.add(note);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reverse sort
|
|
||||||
notes.sort((a, b) => b.compareTo(a));
|
|
||||||
return notes;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<Note> _loadNote(FileSystemEntity entity) async {
|
|
||||||
if (entity is! File) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
var file = entity as File;
|
|
||||||
final string = await file.readAsString();
|
|
||||||
|
|
||||||
var note = noteSerializer.decode(string);
|
|
||||||
note.filePath = p.basename(entity.path);
|
|
||||||
return note;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<NoteRepoResult> addNote(Note note) async {
|
|
||||||
var filePath = p.join(baseDirectory, note.filePath);
|
|
||||||
Fimber.d("FileStorage: Adding note in " + filePath);
|
|
||||||
|
|
||||||
var file = File(filePath);
|
|
||||||
if (file == null) {
|
|
||||||
return NoteRepoResult(error: true);
|
|
||||||
}
|
|
||||||
var contents = noteSerializer.encode(note);
|
|
||||||
await file.writeAsString(contents);
|
|
||||||
|
|
||||||
return NoteRepoResult(noteFilePath: filePath, error: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<NoteRepoResult> removeNote(Note note) async {
|
|
||||||
var filePath = p.join(baseDirectory, note.filePath);
|
|
||||||
|
|
||||||
var file = File(filePath);
|
|
||||||
await file.delete();
|
|
||||||
|
|
||||||
return NoteRepoResult(noteFilePath: filePath, error: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<NoteRepoResult> updateNote(Note note) async {
|
|
||||||
return addNote(note);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Future<bool> sync() async {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<Directory> saveNotes(List<Note> notes) async {
|
|
||||||
final dir = Directory(baseDirectory);
|
|
||||||
|
|
||||||
for (var note in notes) {
|
|
||||||
var filePath = p.join(dir.path, note.filePath);
|
|
||||||
|
|
||||||
var file = File(filePath);
|
|
||||||
var contents = noteSerializer.encode(note);
|
|
||||||
await file.writeAsString(contents);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,37 +1,37 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:fimber/fimber.dart';
|
import 'package:fimber/fimber.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:journal/apis/git.dart';
|
import 'package:journal/apis/git.dart';
|
||||||
import 'package:journal/note.dart';
|
import 'package:journal/note.dart';
|
||||||
import 'package:journal/settings.dart';
|
import 'package:journal/settings.dart';
|
||||||
import 'package:journal/storage/file_storage.dart';
|
|
||||||
import 'package:journal/storage/notes_repository.dart';
|
import 'package:journal/storage/notes_repository.dart';
|
||||||
import 'package:journal/storage/serializers.dart';
|
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
|
|
||||||
class GitNoteRepository implements NoteRepository {
|
class GitNoteRepository implements NoteRepository {
|
||||||
final FileStorage _fileStorage;
|
|
||||||
final String dirName;
|
final String dirName;
|
||||||
final String subDirName;
|
final String subDirName;
|
||||||
|
final String baseDirectory;
|
||||||
|
String notesBasePath;
|
||||||
final GitRepo _gitRepo;
|
final GitRepo _gitRepo;
|
||||||
|
|
||||||
bool cloned = false;
|
bool cloned = false;
|
||||||
bool checkForCloned = false;
|
bool checkForCloned = false;
|
||||||
|
|
||||||
|
// vHanda: This no longer needs to be so complex. It will only ever take the baseDirectory + dirName
|
||||||
|
// The directory should already exist!
|
||||||
GitNoteRepository({
|
GitNoteRepository({
|
||||||
@required this.dirName,
|
@required this.dirName,
|
||||||
@required this.subDirName,
|
@required this.subDirName,
|
||||||
@required String baseDirectory,
|
@required this.baseDirectory,
|
||||||
}) : _fileStorage = FileStorage(
|
}) : _gitRepo = GitRepo(
|
||||||
noteSerializer: MarkdownYAMLSerializer(),
|
|
||||||
baseDirectory: p.join(baseDirectory, dirName, subDirName),
|
|
||||||
),
|
|
||||||
_gitRepo = GitRepo(
|
|
||||||
folderName: dirName,
|
folderName: dirName,
|
||||||
authorEmail: Settings.instance.gitAuthorEmail,
|
authorEmail: Settings.instance.gitAuthorEmail,
|
||||||
authorName: Settings.instance.gitAuthor,
|
authorName: Settings.instance.gitAuthor,
|
||||||
);
|
) {
|
||||||
|
notesBasePath = p.join(baseDirectory, dirName, subDirName);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<NoteRepoResult> addNote(Note note) async {
|
Future<NoteRepoResult> addNote(Note note) async {
|
||||||
@ -39,36 +39,27 @@ class GitNoteRepository implements NoteRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<NoteRepoResult> _addNote(Note note, String commitMessage) async {
|
Future<NoteRepoResult> _addNote(Note note, String commitMessage) async {
|
||||||
var result = await _fileStorage.addNote(note);
|
await note.save();
|
||||||
if (result.error) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
await _gitRepo.add(".");
|
await _gitRepo.add(".");
|
||||||
await _gitRepo.commit(
|
await _gitRepo.commit(
|
||||||
message: commitMessage,
|
message: commitMessage,
|
||||||
);
|
);
|
||||||
|
|
||||||
return result;
|
return NoteRepoResult(noteFilePath: note.filePath, error: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<NoteRepoResult> removeNote(Note note) async {
|
Future<NoteRepoResult> removeNote(Note note) async {
|
||||||
var result = await _fileStorage.addNote(note);
|
var gitDir = p.join(baseDirectory, dirName);
|
||||||
if (result.error) {
|
var pathSpec = note.filePath.replaceFirst(gitDir, "").substring(1);
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: '/' is not valid on all platforms
|
// We are not calling note.remove() as gitRm will also remove the file
|
||||||
var baseDir = _fileStorage.baseDirectory;
|
await _gitRepo.rm(pathSpec);
|
||||||
var filePath = result.noteFilePath.replaceFirst(baseDir + "/", "");
|
|
||||||
|
|
||||||
await _gitRepo.rm(filePath);
|
|
||||||
await _gitRepo.commit(
|
await _gitRepo.commit(
|
||||||
message: "Removed Journal entry",
|
message: "Removed Journal entry",
|
||||||
);
|
);
|
||||||
|
|
||||||
return result;
|
return NoteRepoResult(noteFilePath: note.filePath, error: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<NoteRepoResult> resetLastCommit() async {
|
Future<NoteRepoResult> resetLastCommit() async {
|
||||||
@ -82,8 +73,22 @@ class GitNoteRepository implements NoteRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<List<Note>> listNotes() {
|
Future<List<Note>> listNotes() async {
|
||||||
return _fileStorage.listNotes();
|
final dir = Directory(notesBasePath);
|
||||||
|
|
||||||
|
var notes = <Note>[];
|
||||||
|
var lister = dir.list(recursive: false);
|
||||||
|
await for (var fileEntity in lister) {
|
||||||
|
var note = Note(filePath: fileEntity.path);
|
||||||
|
if (!note.filePath.toLowerCase().endsWith('.md')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
notes.add(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reverse sort
|
||||||
|
notes.sort((a, b) => b.compareTo(a));
|
||||||
|
return notes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
name: journal
|
name: journal
|
||||||
description: A Journaling App Built on top of Git
|
description: A Journaling App Built on top of Git
|
||||||
version: 1.1.12+10
|
version: 1.1.13+10
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
|
Reference in New Issue
Block a user