Do not reparse every note on any change

Earlier whenever anything changed we would discard all the Notes +
NotesFolders in memory, and reconstruct the hierarchy. This would means
Notes which haven't changed at all, still need to parsed all over again.

Now we only reload what has actually changed.

This should result in a huge performance boost.

We still shouldn't be loading everything on boot, but that's a different
problem.
This commit is contained in:
Vishesh Handa
2019-12-08 01:56:59 +01:00
parent 62207eb6c7
commit 1eb9611140

View File

@ -8,10 +8,12 @@ import 'note.dart';
import 'note_fs_entity.dart'; import 'note_fs_entity.dart';
class NotesFolder with ChangeNotifier { class NotesFolder with ChangeNotifier {
NotesFolder parent; final NotesFolder parent;
List<NoteFSEntity> _entities = [];
String folderPath; String folderPath;
List<NoteFSEntity> _entities = [];
Map<String, NoteFSEntity> _entityMap = {};
NotesFolder(this.parent, this.folderPath); NotesFolder(this.parent, this.folderPath);
@override @override
@ -91,18 +93,25 @@ class NotesFolder with ChangeNotifier {
// FIXME: This should not reconstruct the Notes or NotesFolders once constructed. // FIXME: This should not reconstruct the Notes or NotesFolders once constructed.
Future<void> load() async { Future<void> load() async {
final dir = Directory(folderPath); Set<String> pathsFound = {};
_entities.forEach((e) {
if (e.isFolder) {
e.folder.dispose();
} else {
e.note.dispose();
}
});
_entities = [];
var entitiesAdded = false;
var entitiesRemoved = false;
final dir = Directory(folderPath);
var lister = dir.list(recursive: false, followLinks: false); var lister = dir.list(recursive: false, followLinks: false);
await for (var fsEntity in lister) { await for (var fsEntity in lister) {
if (fsEntity is Link) {
continue;
}
// If already seen before
var existingNoteFSEntity = _entityMap[fsEntity.path];
if (existingNoteFSEntity != null) {
pathsFound.add(fsEntity.path);
continue;
}
if (fsEntity is Directory) { if (fsEntity is Directory) {
var subFolder = NotesFolder(this, fsEntity.path); var subFolder = NotesFolder(this, fsEntity.path);
if (subFolder.name.startsWith('.')) { if (subFolder.name.startsWith('.')) {
@ -112,6 +121,10 @@ class NotesFolder with ChangeNotifier {
var noteFSEntity = NoteFSEntity(folder: subFolder); var noteFSEntity = NoteFSEntity(folder: subFolder);
_entities.add(noteFSEntity); _entities.add(noteFSEntity);
_entityMap[fsEntity.path] = noteFSEntity;
pathsFound.add(fsEntity.path);
entitiesAdded = true;
continue; continue;
} }
@ -123,9 +136,32 @@ class NotesFolder with ChangeNotifier {
var noteFSEntity = NoteFSEntity(note: note); var noteFSEntity = NoteFSEntity(note: note);
_entities.add(noteFSEntity); _entities.add(noteFSEntity);
_entityMap[fsEntity.path] = noteFSEntity;
pathsFound.add(fsEntity.path);
entitiesAdded = true;
} }
if (_entities.isNotEmpty) { Set<String> pathsRemoved = _entityMap.keys.toSet().difference(pathsFound);
pathsRemoved.forEach((path) {
var e = _entityMap[path];
assert(e != null);
if (e.isFolder) {
e.folder.removeListener(_entityChanged);
} else {
e.note.removeListener(_entityChanged);
}
_entityMap.remove(path);
});
_entities.removeWhere((e) {
String path = e.isFolder ? e.folder.folderPath : e.note.filePath;
return pathsRemoved.contains(path);
});
entitiesRemoved = pathsRemoved.isNotEmpty;
if (entitiesAdded || entitiesRemoved) {
notifyListeners(); notifyListeners();
} }
} }