StateContainer: Do not call setState when the notesFolder changes

The NotesFolder is now a listenable and is always accessed via Provider,
and therefore doesn't need setState to be called when it is modified.
This commit is contained in:
Vishesh Handa
2019-12-08 02:58:56 +01:00
parent ee9d38e420
commit 8a49d948f0
4 changed files with 53 additions and 107 deletions

View File

@ -49,7 +49,10 @@ class JournalApp extends StatelessWidget {
appState: appState, appState: appState,
child: ChangeNotifierProvider( child: ChangeNotifierProvider(
child: JournalApp(), child: JournalApp(),
create: (_) => appState.notesFolder, create: (_) {
assert(appState.notesFolder != null);
return appState.notesFolder;
},
), ),
)); ));
} }

View File

@ -179,8 +179,17 @@ class NotesFolder with ChangeNotifier {
void insert(int index, Note note) { void insert(int index, Note note) {
assert(note.parent == this); assert(note.parent == this);
assert(index >= 0);
note.addListener(_entityChanged); note.addListener(_entityChanged);
if (_entities.isEmpty) {
var entity = NoteFSEntity(note: note);
_entities.add(entity);
_entityMap[note.filePath] = entity;
notifyListeners();
return;
}
for (var i = 0; i < _entities.length; i++) { for (var i = 0; i < _entities.length; i++) {
var e = _entities[i]; var e = _entities[i];
if (e is NotesFolder) continue; if (e is NotesFolder) continue;

View File

@ -1,14 +1,14 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gitjournal/state_container.dart'; import 'package:provider/provider.dart';
import 'package:gitjournal/core/notes_folder.dart';
import 'journal_listing.dart'; import 'journal_listing.dart';
class HomeScreen extends StatelessWidget { class HomeScreen extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final container = StateContainer.of(context); final notesFolder = Provider.of<NotesFolder>(context);
final appState = container.appState; return JournalListingScreen(notesFolder: notesFolder);
return JournalListingScreen(notesFolder: appState.notesFolder);
} }
} }

View File

@ -4,7 +4,6 @@ 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:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:gitjournal/analytics.dart';
import 'package:gitjournal/apis/git_migration.dart'; import 'package:gitjournal/apis/git_migration.dart';
import 'package:gitjournal/appstate.dart'; import 'package:gitjournal/appstate.dart';
import 'package:gitjournal/core/note.dart'; import 'package:gitjournal/core/note.dart';
@ -68,8 +67,8 @@ class StateContainerState extends State<StateContainer> {
removeExistingRemoteClone(); removeExistingRemoteClone();
} }
_loadNotesFromDisk(); _loadNotes();
_syncNotes(); syncNotes();
} }
void removeExistingRemoteClone() async { void removeExistingRemoteClone() async {
@ -84,32 +83,10 @@ class StateContainerState extends State<StateContainer> {
} }
Future<void> _loadNotes() async { Future<void> _loadNotes() async {
// FIXME: We should report the notes that failed to load
await appState.notesFolder.loadRecursively(); await appState.notesFolder.loadRecursively();
} }
void _loadNotesFromDisk() {
Fimber.d("Loading Notes From Disk");
_loadNotes().then((void _) {
setState(() {
getAnalytics().logEvent(
name: "notes_loaded",
);
});
}).catchError((err, stack) {
setState(() {
Fimber.d("Load Notes From Disk Error: " + err.toString());
Fimber.d(stack.toString());
getAnalytics().logEvent(
name: "notes_loading_failed",
parameters: <String, dynamic>{
'error': err.toString(),
},
);
});
});
}
Future syncNotes() async { Future syncNotes() async {
if (!appState.remoteGitRepoConfigured) { if (!appState.remoteGitRepoConfigured) {
Fimber.d("Not syncing because RemoteRepo not configured"); Fimber.d("Not syncing because RemoteRepo not configured");
@ -117,37 +94,11 @@ class StateContainerState extends State<StateContainer> {
} }
await _gitRepo.sync(); await _gitRepo.sync();
try {
await _loadNotes(); await _loadNotes();
setState(() {
// TODO: Inform exactly what notes have changed?
});
} catch (err, stack) {
setState(() {
Fimber.d("Load Notes From Disk Error: " + err.toString());
Fimber.d(stack.toString());
});
}
return true; return true;
} }
void _syncNotes() {
if (!appState.remoteGitRepoConfigured) {
Fimber.d("Not syncing because RemoteRepo not configured");
return;
}
Fimber.d("Starting to syncNotes");
_gitRepo.sync().then((loaded) {
Fimber.d("NotesRepo Synced: " + loaded.toString());
_loadNotesFromDisk();
}).catchError((err) {
Fimber.d("NotesRepo Sync: " + err.toString());
});
}
void createFolder(NotesFolder parent, String folderName) async { void createFolder(NotesFolder parent, String folderName) async {
var newFolderPath = p.join(parent.folderPath, folderName); var newFolderPath = p.join(parent.folderPath, folderName);
var newFolder = NotesFolder(parent, newFolderPath); var newFolder = NotesFolder(parent, newFolderPath);
@ -156,26 +107,19 @@ class StateContainerState extends State<StateContainer> {
Fimber.d("Created New Folder: " + newFolderPath); Fimber.d("Created New Folder: " + newFolderPath);
parent.addFolder(newFolder); parent.addFolder(newFolder);
setState(() {
// Update the git repo
_gitRepo.addFolder(newFolder).then((NoteRepoResult _) { _gitRepo.addFolder(newFolder).then((NoteRepoResult _) {
_syncNotes(); syncNotes();
});
}); });
} }
void renameFolder(NotesFolder folder, String newFolderName) async { void renameFolder(NotesFolder folder, String newFolderName) async {
var oldFolderPath = folder.folderPath; var oldFolderPath = folder.folderPath;
setState(() {
folder.rename(newFolderName); folder.rename(newFolderName);
// Update the git repo
_gitRepo _gitRepo
.renameFolder(oldFolderPath, folder.folderPath) .renameFolder(oldFolderPath, folder.folderPath)
.then((NoteRepoResult _) { .then((NoteRepoResult _) {
_syncNotes(); syncNotes();
});
}); });
} }
@ -184,7 +128,6 @@ class StateContainerState extends State<StateContainer> {
} }
void removeNote(Note note) { void removeNote(Note note) {
setState(() {
note.parent.remove(note); note.parent.remove(note);
_gitRepo.removeNote(note.filePath).then((NoteRepoResult _) async { _gitRepo.removeNote(note.filePath).then((NoteRepoResult _) async {
// FIXME: Is there a way of figuring this amount dynamically? // FIXME: Is there a way of figuring this amount dynamically?
@ -192,43 +135,34 @@ class StateContainerState extends State<StateContainer> {
// We wait an aritfical amount of time, so that the user has a change to undo // We wait an aritfical amount of time, so that the user has a change to undo
// their delete operation, and that commit is not synced with the server, till then. // their delete operation, and that commit is not synced with the server, till then.
await Future.delayed(const Duration(seconds: 4)); await Future.delayed(const Duration(seconds: 4));
_syncNotes(); syncNotes();
});
}); });
} }
void undoRemoveNote(Note note, int index) { void undoRemoveNote(Note note, int index) {
setState(() {
note.parent.insert(index, note); note.parent.insert(index, note);
_gitRepo.resetLastCommit().then((NoteRepoResult _) { _gitRepo.resetLastCommit().then((NoteRepoResult _) {
_syncNotes(); syncNotes();
});
}); });
} }
void insertNote(int index, Note note) { void insertNote(int index, Note note) {
Fimber.d("State Container insertNote " + index.toString()); Fimber.d("State Container insertNote " + index.toString());
setState(() {
if (note.filePath == null || note.filePath.isEmpty) { if (note.filePath == null || note.filePath.isEmpty) {
var parentPath = note.parent != null var parentPath =
? note.parent.folderPath note.parent != null ? note.parent.folderPath : _gitRepo.notesBasePath;
: _gitRepo.notesBasePath;
note.filePath = p.join(parentPath, getFileName(note)); note.filePath = p.join(parentPath, getFileName(note));
} }
note.parent.insert(index, note); note.parent.insert(index, note);
_gitRepo.addNote(note).then((NoteRepoResult _) { _gitRepo.addNote(note).then((NoteRepoResult _) {
_syncNotes(); syncNotes();
});
}); });
} }
void updateNote(Note note) { void updateNote(Note note) {
Fimber.d("State Container updateNote"); Fimber.d("State Container updateNote");
setState(() {
// Update the git repo
_gitRepo.updateNote(note).then((NoteRepoResult _) { _gitRepo.updateNote(note).then((NoteRepoResult _) {
_syncNotes(); syncNotes();
});
}); });
} }
@ -247,11 +181,11 @@ class StateContainerState extends State<StateContainer> {
baseDirectory: appState.gitBaseDirectory, baseDirectory: appState.gitBaseDirectory,
dirName: appState.remoteGitRepoFolderName, dirName: appState.remoteGitRepoFolderName,
); );
appState.notesFolder = NotesFolder(null, _gitRepo.notesBasePath); appState.notesFolder.folderPath = _gitRepo.notesBasePath;
await _persistConfig(); await _persistConfig();
_loadNotesFromDisk(); _loadNotes();
_syncNotes(); syncNotes();
setState(() {}); setState(() {});
}(); }();