mirror of
https://github.com/GitJournal/GitJournal.git
synced 2025-06-27 17:29:50 +08:00
Hookup the Journal app to git
Now notes are saved in the git repo, and immediately synced. This is not the best implementation, as the notes are being reloaded a lot, and the error handling is terrible (I miss golang). But it's the first working poc.
This commit is contained in:
@ -26,23 +26,37 @@ buildGitButtons() {
|
|||||||
),
|
),
|
||||||
RaisedButton(
|
RaisedButton(
|
||||||
child: Text("Git Clone"),
|
child: Text("Git Clone"),
|
||||||
onPressed: gitClone,
|
onPressed: () async {
|
||||||
|
gitClone("root@bcn.vhanda.in:git/test", "journal");
|
||||||
|
},
|
||||||
),
|
),
|
||||||
RaisedButton(
|
RaisedButton(
|
||||||
child: Text("Git Pull"),
|
child: Text("Git Pull"),
|
||||||
onPressed: gitPull,
|
onPressed: () async {
|
||||||
|
gitPull("journal");
|
||||||
|
},
|
||||||
),
|
),
|
||||||
RaisedButton(
|
RaisedButton(
|
||||||
child: Text("Git Add"),
|
child: Text("Git Add"),
|
||||||
onPressed: gitAdd,
|
onPressed: () async {
|
||||||
|
await gitAdd("journal", "1");
|
||||||
|
},
|
||||||
),
|
),
|
||||||
RaisedButton(
|
RaisedButton(
|
||||||
child: Text("Git Push"),
|
child: Text("Git Push"),
|
||||||
onPressed: gitPush,
|
onPressed: () async {
|
||||||
|
gitPush("journal");
|
||||||
|
},
|
||||||
),
|
),
|
||||||
RaisedButton(
|
RaisedButton(
|
||||||
child: Text("Git Commit"),
|
child: Text("Git Commit"),
|
||||||
onPressed: gitCommit,
|
onPressed: () async {
|
||||||
),
|
gitCommit(
|
||||||
|
gitFolder: "journal",
|
||||||
|
authorEmail: "noemail@example.com",
|
||||||
|
authorName: "Vishesh Handa",
|
||||||
|
message: "Default message from GitJournal",
|
||||||
|
);
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -5,24 +5,9 @@ import 'package:journal/app.dart';
|
|||||||
import 'package:journal/gitapp.dart';
|
import 'package:journal/gitapp.dart';
|
||||||
import 'package:journal/state_container.dart';
|
import 'package:journal/state_container.dart';
|
||||||
|
|
||||||
/*
|
|
||||||
import 'note.dart';
|
|
||||||
|
|
||||||
Future<List<Note>> fetchNotes() async {
|
|
||||||
final response = await http.get('http://192.168.1.132:8000/notes');
|
|
||||||
final responseJson = json.decode(response.body);
|
|
||||||
|
|
||||||
var notes = <Note>[];
|
|
||||||
for (var postJson in responseJson) {
|
|
||||||
notes.add(new Note.fromJson(postJson));
|
|
||||||
}
|
|
||||||
|
|
||||||
return notes;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(new StateContainer(
|
runApp(new StateContainer(
|
||||||
child: GitApp(),
|
child: JournalApp(),
|
||||||
|
//child: GitApp(),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -49,21 +49,34 @@ class Note implements Comparable {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'Note{id: $id, body: $body, createdAt: $created}';
|
return 'Note{id: $id, body: $body, created: $created}';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int compareTo(other) => created.compareTo(other.created);
|
int compareTo(other) {
|
||||||
|
if (other == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return created.compareTo(other.created);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppState {
|
class AppState {
|
||||||
bool isLoading;
|
bool isLoadingFromDisk;
|
||||||
|
bool localStateModified;
|
||||||
|
|
||||||
|
bool isLoadingRemoteState;
|
||||||
|
bool remoteStateModified;
|
||||||
|
|
||||||
List<Note> notes;
|
List<Note> notes;
|
||||||
|
|
||||||
AppState({
|
AppState({
|
||||||
this.isLoading = false,
|
this.isLoadingFromDisk = false,
|
||||||
|
this.localStateModified = false,
|
||||||
|
this.isLoadingRemoteState = false,
|
||||||
|
this.remoteStateModified = false,
|
||||||
this.notes = const [],
|
this.notes = const [],
|
||||||
});
|
});
|
||||||
|
|
||||||
factory AppState.loading() => AppState(isLoading: true);
|
//factory AppState.loading() => AppState(isLoading: true);
|
||||||
}
|
}
|
||||||
|
@ -9,12 +9,12 @@ import 'package:uuid/uuid.dart';
|
|||||||
import 'package:journal/note.dart';
|
import 'package:journal/note.dart';
|
||||||
import 'package:journal/storage/serializers.dart';
|
import 'package:journal/storage/serializers.dart';
|
||||||
import 'package:journal/storage/notes_repository.dart';
|
import 'package:journal/storage/notes_repository.dart';
|
||||||
import 'package:journal/storage/file_storage.dart';
|
import 'package:journal/storage/git_storage.dart';
|
||||||
import 'package:journal/storage/git.dart';
|
import 'package:journal/storage/git.dart';
|
||||||
|
|
||||||
Future<Directory> getNotesDir() async {
|
Future<Directory> getNotesDir() async {
|
||||||
var appDir = await getGitBaseDirectory();
|
var appDir = await getGitBaseDirectory();
|
||||||
var dir = new Directory(p.join(appDir.path, "notes"));
|
var dir = new Directory(p.join(appDir.path, "journal"));
|
||||||
await dir.create();
|
await dir.create();
|
||||||
|
|
||||||
return dir;
|
return dir;
|
||||||
@ -40,56 +40,80 @@ class StateContainer extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class StateContainerState extends State<StateContainer> {
|
class StateContainerState extends State<StateContainer> {
|
||||||
AppState appState = AppState.loading();
|
AppState appState = AppState();
|
||||||
NoteRepository noteRepo = new FileStorage(
|
|
||||||
|
NoteRepository noteRepo = new GitNoteRepository(
|
||||||
getDirectory: getNotesDir,
|
getDirectory: getNotesDir,
|
||||||
noteSerializer: new MarkdownYAMLSerializer(),
|
dirName: "journal",
|
||||||
fileNameGenerator: (Note note) => note.id,
|
gitCloneUrl: "root@bcn.vhanda.in:git/test",
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
|
||||||
|
_loadNotesFromDisk();
|
||||||
|
_syncNotes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _loadNotesFromDisk() {
|
||||||
|
print("Loading Notes From Disk");
|
||||||
|
appState.isLoadingFromDisk = true;
|
||||||
noteRepo.listNotes().then((loadedNotes) {
|
noteRepo.listNotes().then((loadedNotes) {
|
||||||
setState(() {
|
setState(() {
|
||||||
appState = AppState(notes: loadedNotes);
|
appState.isLoadingFromDisk = false;
|
||||||
|
appState.notes = loadedNotes;
|
||||||
});
|
});
|
||||||
}).catchError((err) {
|
}).catchError((err, stack) {
|
||||||
setState(() {
|
setState(() {
|
||||||
print("Load Notes Error:");
|
print("Load Notes From Disk Error: " + err.toString());
|
||||||
print(err);
|
print(stack.toString());
|
||||||
appState.isLoading = false;
|
appState.isLoadingFromDisk = false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void addNote(Note note) {
|
void _syncNotes() {
|
||||||
setState(() {
|
print("Starting to syncNOtes");
|
||||||
note.id = new Uuid().v4();
|
this.noteRepo.sync().then((loaded) {
|
||||||
appState.notes.insert(0, note);
|
print("NotesRepo Synced: " + loaded.toString());
|
||||||
noteRepo.addNote(note);
|
_loadNotesFromDisk();
|
||||||
|
}).catchError((err) {
|
||||||
|
print("NotesRepo Sync: " + err.toString());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void addNote(Note note) {
|
||||||
|
insertNote(0, note);
|
||||||
|
}
|
||||||
|
|
||||||
void removeNote(Note note) {
|
void removeNote(Note note) {
|
||||||
setState(() {
|
setState(() {
|
||||||
appState.notes.remove(note);
|
appState.notes.remove(note);
|
||||||
noteRepo.removeNote(note);
|
noteRepo.removeNote(note).then((NoteRepoResult _) {
|
||||||
|
_syncNotes();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertNote(int index, Note note) {
|
void insertNote(int index, Note note) {
|
||||||
setState(() {
|
setState(() {
|
||||||
|
print("insertNote: " + note.toString());
|
||||||
|
if (note.id == null || note.id.isEmpty) {
|
||||||
|
note.id = new Uuid().v4();
|
||||||
|
}
|
||||||
appState.notes.insert(index, note);
|
appState.notes.insert(index, note);
|
||||||
noteRepo.addNote(note);
|
noteRepo.addNote(note).then((NoteRepoResult _) {
|
||||||
|
_syncNotes();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: Implement this!
|
|
||||||
void updateNote(Note note) {
|
void updateNote(Note note) {
|
||||||
setState(() {
|
setState(() {
|
||||||
noteRepo.updateNote(note);
|
noteRepo.updateNote(note).then((NoteRepoResult _) {
|
||||||
|
_syncNotes();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,13 @@ class FileStorage implements NoteRepository {
|
|||||||
var lister = dir.list(recursive: false);
|
var lister = dir.list(recursive: false);
|
||||||
await for (var fileEntity in lister) {
|
await for (var fileEntity in lister) {
|
||||||
Note note = await _loadNote(fileEntity);
|
Note note = await _loadNote(fileEntity);
|
||||||
|
if (note == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (note.id == null) {
|
||||||
|
String filename = p.basename(fileEntity.path);
|
||||||
|
note.id = filename;
|
||||||
|
}
|
||||||
notes.add(note);
|
notes.add(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,30 +54,33 @@ class FileStorage implements NoteRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> addNote(Note note) async {
|
Future<NoteRepoResult> addNote(Note note) async {
|
||||||
final dir = await getDirectory();
|
final dir = await getDirectory();
|
||||||
var filePath = p.join(dir.path, fileNameGenerator(note));
|
var filePath = p.join(dir.path, fileNameGenerator(note));
|
||||||
|
|
||||||
var file = new File(filePath);
|
var file = new File(filePath);
|
||||||
|
if (file == null) {
|
||||||
|
return NoteRepoResult(error: true);
|
||||||
|
}
|
||||||
var contents = noteSerializer.encode(note);
|
var contents = noteSerializer.encode(note);
|
||||||
await file.writeAsString(contents);
|
await file.writeAsString(contents);
|
||||||
|
|
||||||
return true;
|
return NoteRepoResult(noteFilePath: filePath, error: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> removeNote(Note note) async {
|
Future<NoteRepoResult> removeNote(Note note) async {
|
||||||
final dir = await getDirectory();
|
final dir = await getDirectory();
|
||||||
var filePath = p.join(dir.path, fileNameGenerator(note));
|
var filePath = p.join(dir.path, fileNameGenerator(note));
|
||||||
|
|
||||||
var file = new File(filePath);
|
var file = new File(filePath);
|
||||||
await file.delete();
|
await file.delete();
|
||||||
|
|
||||||
return true;
|
return NoteRepoResult(noteFilePath: filePath, error: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<bool> updateNote(Note note) async {
|
Future<NoteRepoResult> updateNote(Note note) async {
|
||||||
return addNote(note);
|
return addNote(note);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,8 +91,8 @@ class FileStorage implements NoteRepository {
|
|||||||
|
|
||||||
Future<Directory> saveNotes(List<Note> notes) async {
|
Future<Directory> saveNotes(List<Note> notes) async {
|
||||||
final dir = await getDirectory();
|
final dir = await getDirectory();
|
||||||
await dir.delete(recursive: true);
|
// FIXME: Why do we need to delete everything?
|
||||||
await dir.create();
|
// await dir.delete(recursive: true);
|
||||||
|
|
||||||
for (var note in notes) {
|
for (var note in notes) {
|
||||||
var filePath = p.join(dir.path, fileNameGenerator(note));
|
var filePath = p.join(dir.path, fileNameGenerator(note));
|
||||||
|
@ -13,12 +13,12 @@ Future<Directory> getGitBaseDirectory() async {
|
|||||||
return new Directory(path);
|
return new Directory(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future gitClone() async {
|
Future gitClone(String cloneUrl, String folderName) async {
|
||||||
print("Going to git clone");
|
print("Going to git clone");
|
||||||
try {
|
try {
|
||||||
await _platform.invokeMethod('gitClone', {
|
await _platform.invokeMethod('gitClone', {
|
||||||
'cloneUrl': "root@bcn.vhanda.in:git/test",
|
'cloneUrl': cloneUrl,
|
||||||
'folderName': "journal",
|
'folderName': folderName,
|
||||||
});
|
});
|
||||||
print("Done");
|
print("Done");
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
@ -36,11 +36,11 @@ Future generateSSHKeys() async {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future gitPull() async {
|
Future gitPull(String folderName) async {
|
||||||
print("Going to git pull");
|
print("Going to git pull");
|
||||||
try {
|
try {
|
||||||
await _platform.invokeMethod('gitPull', {
|
await _platform.invokeMethod('gitPull', {
|
||||||
'folderName': "journal",
|
'folderName': folderName,
|
||||||
});
|
});
|
||||||
print("Done");
|
print("Done");
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
@ -48,12 +48,12 @@ Future gitPull() async {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future gitAdd() async {
|
Future gitAdd(String gitFolder, String filePattern) async {
|
||||||
print("Going to git add");
|
print("Going to git add: " + filePattern);
|
||||||
try {
|
try {
|
||||||
await _platform.invokeMethod('gitAdd', {
|
await _platform.invokeMethod('gitAdd', {
|
||||||
'folderName': "journal",
|
'folderName': gitFolder,
|
||||||
'filePattern': ".",
|
'filePattern': filePattern,
|
||||||
});
|
});
|
||||||
print("Done");
|
print("Done");
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
@ -61,12 +61,12 @@ Future gitAdd() async {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future gitRm() async {
|
Future gitRm(String gitFolder, String filePattern) async {
|
||||||
print("Going to git rm");
|
print("Going to git rm");
|
||||||
try {
|
try {
|
||||||
await _platform.invokeMethod('gitRm', {
|
await _platform.invokeMethod('gitRm', {
|
||||||
'folderName': "journal",
|
'folderName': gitFolder,
|
||||||
'filePattern': "1",
|
'filePattern': filePattern,
|
||||||
});
|
});
|
||||||
print("Done");
|
print("Done");
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
@ -74,11 +74,11 @@ Future gitRm() async {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future gitPush() async {
|
Future gitPush(String folderName) async {
|
||||||
print("Going to git push");
|
print("Going to git push");
|
||||||
try {
|
try {
|
||||||
await _platform.invokeMethod('gitPush', {
|
await _platform.invokeMethod('gitPush', {
|
||||||
'folderName': "journal",
|
'folderName': folderName,
|
||||||
});
|
});
|
||||||
print("Done");
|
print("Done");
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
@ -86,14 +86,19 @@ Future gitPush() async {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future gitCommit() async {
|
Future gitCommit({
|
||||||
|
String gitFolder,
|
||||||
|
String authorName,
|
||||||
|
String authorEmail,
|
||||||
|
String message,
|
||||||
|
}) async {
|
||||||
print("Going to git commit");
|
print("Going to git commit");
|
||||||
try {
|
try {
|
||||||
await _platform.invokeMethod('gitCommit', {
|
await _platform.invokeMethod('gitCommit', {
|
||||||
'folderName': "journal",
|
'folderName': gitFolder,
|
||||||
'authorName': "Vishesh Handa",
|
'authorName': authorName,
|
||||||
'authorEmail': "noemail@example.com",
|
'authorEmail': authorEmail,
|
||||||
'message': "Default message from GitJournal",
|
'message': message,
|
||||||
});
|
});
|
||||||
print("Done");
|
print("Done");
|
||||||
} on PlatformException catch (e) {
|
} on PlatformException catch (e) {
|
||||||
|
108
lib/storage/git_storage.dart
Normal file
108
lib/storage/git_storage.dart
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:path/path.dart' as p;
|
||||||
|
|
||||||
|
import 'package:journal/note.dart';
|
||||||
|
import 'package:journal/storage/git.dart';
|
||||||
|
import 'package:journal/storage/serializers.dart';
|
||||||
|
import 'package:journal/storage/file_storage.dart';
|
||||||
|
import 'package:journal/storage/notes_repository.dart';
|
||||||
|
|
||||||
|
class GitNoteRepository implements NoteRepository {
|
||||||
|
final FileStorage _fileStorage;
|
||||||
|
final String gitCloneUrl;
|
||||||
|
final String dirName;
|
||||||
|
|
||||||
|
bool cloned = false;
|
||||||
|
bool checkForCloned = false;
|
||||||
|
|
||||||
|
final Future<Directory> Function() getDirectory;
|
||||||
|
|
||||||
|
GitNoteRepository({
|
||||||
|
@required this.gitCloneUrl,
|
||||||
|
@required this.dirName,
|
||||||
|
@required this.getDirectory,
|
||||||
|
}) : _fileStorage = FileStorage(
|
||||||
|
noteSerializer: new MarkdownYAMLSerializer(),
|
||||||
|
fileNameGenerator: (Note note) => note.id,
|
||||||
|
getDirectory: getDirectory,
|
||||||
|
) {
|
||||||
|
// FIXME: This isn't correct. The gitUrl might not be cloned at this point!
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<NoteRepoResult> addNote(Note note) async {
|
||||||
|
print("Calling gitStorage addNote");
|
||||||
|
var result = await _fileStorage.addNote(note);
|
||||||
|
if (result.error) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
var baseDir = await this.getDirectory();
|
||||||
|
var filePath = result.noteFilePath.replaceFirst(baseDir.path + "/", "");
|
||||||
|
|
||||||
|
await gitAdd(this.dirName, filePath);
|
||||||
|
await gitCommit(
|
||||||
|
gitFolder: this.dirName,
|
||||||
|
authorEmail: "noemail@example.com",
|
||||||
|
authorName: "Vishesh Handa",
|
||||||
|
message: "Added Journal entry",
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<NoteRepoResult> removeNote(Note note) async {
|
||||||
|
var result = await _fileStorage.addNote(note);
|
||||||
|
if (result.error) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
var baseDir = await this.getDirectory();
|
||||||
|
var filePath = result.noteFilePath.replaceFirst(baseDir.path + "/", "");
|
||||||
|
|
||||||
|
await gitRm(this.dirName, filePath);
|
||||||
|
await gitCommit(
|
||||||
|
gitFolder: this.dirName,
|
||||||
|
authorEmail: "noemail@example.com",
|
||||||
|
authorName: "Vishesh Handa",
|
||||||
|
message: "Added Journal entry",
|
||||||
|
);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<NoteRepoResult> updateNote(Note note) async {
|
||||||
|
return this.addNote(note);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<List<Note>> listNotes() {
|
||||||
|
return _fileStorage.listNotes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<bool> sync() async {
|
||||||
|
print("Starting Sync");
|
||||||
|
if (!checkForCloned) {
|
||||||
|
var baseDir = await this.getDirectory();
|
||||||
|
var dotGitDir = new Directory(p.join(baseDir.path, ".git"));
|
||||||
|
cloned = await dotGitDir.exists();
|
||||||
|
checkForCloned = true;
|
||||||
|
}
|
||||||
|
if (!cloned) {
|
||||||
|
await gitClone(this.gitCloneUrl, this.dirName);
|
||||||
|
cloned = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
await gitPull(this.dirName);
|
||||||
|
await gitPush(this.dirName);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@ -1,13 +1,25 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
import 'package:journal/note.dart';
|
import 'package:journal/note.dart';
|
||||||
|
|
||||||
|
class NoteRepoResult {
|
||||||
|
bool error;
|
||||||
|
String noteFilePath;
|
||||||
|
|
||||||
|
NoteRepoResult({
|
||||||
|
@required this.error,
|
||||||
|
this.noteFilePath,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
abstract class NoteRepository {
|
abstract class NoteRepository {
|
||||||
// TODO: Better error message!
|
// TODO: Better error message!
|
||||||
Future<bool> sync();
|
Future<bool> sync();
|
||||||
|
|
||||||
Future<bool> addNote(Note note);
|
Future<NoteRepoResult> addNote(Note note);
|
||||||
Future<bool> updateNote(Note note);
|
Future<NoteRepoResult> updateNote(Note note);
|
||||||
Future<bool> removeNote(Note note);
|
Future<NoteRepoResult> removeNote(Note note);
|
||||||
|
|
||||||
Future<List<Note>> listNotes();
|
Future<List<Note>> listNotes();
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user