From f30c52f595bbcd64c68e17a2e99d0b96cfd8b252 Mon Sep 17 00:00:00 2001 From: Vishesh Handa Date: Thu, 24 Sep 2020 23:44:32 +0200 Subject: [PATCH] Move all persistent state from AppState to Settings This way all the persistant state of the app is managed from the same place. It makes everything much easier. Also, it's required for when GitJournal supports multiple repositories. --- lib/app.dart | 33 ++++++++++---------- lib/appstate.dart | 45 ---------------------------- lib/main.dart | 2 +- lib/screens/folder_view.dart | 4 +-- lib/screens/settings_git_remote.dart | 3 +- lib/screens/settings_screen.dart | 5 +--- lib/settings.dart | 27 +++++++++++++++++ lib/setup/screens.dart | 6 ++-- lib/state_container.dart | 41 +++++++++++++------------ lib/widgets/app_drawer.dart | 6 ++-- test_driver/main.dart | 15 +++++----- 11 files changed, 79 insertions(+), 108 deletions(-) diff --git a/lib/app.dart b/lib/app.dart index 048f56ee..9002006b 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -15,7 +15,6 @@ import 'package:path_provider/path_provider.dart'; import 'package:provider/provider.dart'; import 'package:quick_actions/quick_actions.dart'; import 'package:receive_sharing_intent/receive_sharing_intent.dart'; -import 'package:shared_preferences/shared_preferences.dart'; import 'package:gitjournal/analytics.dart'; import 'package:gitjournal/appstate.dart'; @@ -41,12 +40,10 @@ import 'setup/screens.dart'; class JournalApp extends StatefulWidget { final AppState appState; - static Future main(SharedPreferences pref) async { + static Future main() async { await Log.init(); - var appState = AppState(pref); - appState.dumpToLog(); - + var appState = AppState(); var settings = Settings.instance; Log.i("Setting ${settings.toLoggableMap()}"); @@ -54,38 +51,38 @@ class JournalApp extends StatefulWidget { _enableAnalyticsIfPossible(settings); } - if (appState.gitBaseDirectory.isEmpty) { + if (settings.gitBaseDirectory.isEmpty) { var dir = await getApplicationDocumentsDirectory(); - appState.gitBaseDirectory = dir.path; - appState.save(pref); + settings.gitBaseDirectory = dir.path; + settings.save(); } - if (!Directory(appState.gitBaseDirectory).existsSync()) { + if (!Directory(settings.gitBaseDirectory).existsSync()) { Log.w("Applications Documents Directory no longer exists"); var dir = await getApplicationDocumentsDirectory(); - appState.gitBaseDirectory = dir.path; - appState.save(pref); + settings.gitBaseDirectory = dir.path; + settings.save(); Log.i("New Documents Directory Path ${dir.path}"); } - if (appState.localGitRepoConfigured == false) { + if (settings.localGitRepoConfigured == false) { // FIXME: What about exceptions! - appState.localGitRepoFolderName = "journal_local"; + settings.localGitRepoFolderName = "journal_local"; var repoPath = p.join( - appState.gitBaseDirectory, - appState.localGitRepoFolderName, + settings.gitBaseDirectory, + settings.localGitRepoFolderName, ); await GitRepository.init(repoPath); - appState.localGitRepoConfigured = true; - appState.save(pref); + settings.localGitRepoConfigured = true; + settings.save(); } var app = ChangeNotifierProvider.value( value: settings, child: ChangeNotifierProvider( create: (_) { - return StateContainer(appState); + return StateContainer(appState, settings); }, child: ChangeNotifierProvider( child: JournalApp(appState), diff --git a/lib/appstate.dart b/lib/appstate.dart index 078f7281..be1a5ae9 100644 --- a/lib/appstate.dart +++ b/lib/appstate.dart @@ -1,7 +1,4 @@ -import 'package:shared_preferences/shared_preferences.dart'; - import 'package:gitjournal/core/notes_folder_fs.dart'; -import 'package:gitjournal/utils/logger.dart'; enum SyncStatus { Unknown, @@ -12,54 +9,12 @@ enum SyncStatus { } class AppState { - // - // Saved on Disk - // - // FIXME: These should be figured out by querying the 'git remotes' - String localGitRepoFolderName = ""; - bool localGitRepoConfigured = false; - - String remoteGitRepoFolderName = ""; - bool remoteGitRepoConfigured = false; - SyncStatus syncStatus = SyncStatus.Unknown; int numChanges = 0; - // - // Temporary - // - /// This is the directory where all the git repos are stored - String gitBaseDirectory = ""; - bool get hasJournalEntries { return notesFolder.hasNotes; } NotesFolderFS notesFolder; - - AppState(SharedPreferences pref) { - localGitRepoConfigured = pref.getBool("localGitRepoConfigured") ?? false; - remoteGitRepoConfigured = pref.getBool("remoteGitRepoConfigured") ?? false; - localGitRepoFolderName = pref.getString("localGitRepoPath") ?? ""; - remoteGitRepoFolderName = pref.getString("remoteGitRepoPath") ?? ""; - gitBaseDirectory = pref.getString("gitBaseDirectory") ?? ""; - } - - void dumpToLog() { - Log.i(" ---- Settings ---- "); - Log.i("localGitRepoConfigured: $localGitRepoConfigured"); - Log.i("remoteGitRepoConfigured: $remoteGitRepoConfigured"); - Log.i("localGitRepoFolderName: $localGitRepoFolderName"); - Log.i("remoteGitRepoFolderName: $remoteGitRepoFolderName"); - Log.i("gitBaseDirectory: $gitBaseDirectory"); - Log.i(" ------------------ "); - } - - Future save(SharedPreferences pref) async { - await pref.setBool("localGitRepoConfigured", localGitRepoConfigured); - await pref.setBool("remoteGitRepoConfigured", remoteGitRepoConfigured); - await pref.setString("localGitRepoPath", localGitRepoFolderName); - await pref.setString("remoteGitRepoPath", remoteGitRepoFolderName); - await pref.setString("gitBaseDirectory", gitBaseDirectory); - } } diff --git a/lib/main.dart b/lib/main.dart index 8fe062a7..ccba210d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -29,6 +29,6 @@ void main() async { }).sendPort); runZonedGuarded(() async { - await JournalApp.main(pref); + await JournalApp.main(); }, reportError); } diff --git a/lib/screens/folder_view.dart b/lib/screens/folder_view.dart index c3e911a7..50fd4ee8 100644 --- a/lib/screens/folder_view.dart +++ b/lib/screens/folder_view.dart @@ -372,7 +372,7 @@ class _FolderViewState extends State { } List _buildNoteActions() { - final appState = Provider.of(context).appState; + final settings = Provider.of(context); var extraActions = PopupMenuButton( onSelected: (DropDownChoices choice) { @@ -405,7 +405,7 @@ class _FolderViewState extends State { onPressed: _folderViewChooserSelected, key: const ValueKey("FolderViewSelector"), ), - if (appState.remoteGitRepoConfigured) SyncButton(), + if (settings.remoteGitRepoConfigured) SyncButton(), IconButton( icon: const Icon(Icons.search), onPressed: () { diff --git a/lib/screens/settings_git_remote.dart b/lib/screens/settings_git_remote.dart index a4a69752..dd8756c4 100644 --- a/lib/screens/settings_git_remote.dart +++ b/lib/screens/settings_git_remote.dart @@ -132,7 +132,8 @@ class _GitRemoteSettingsScreenState extends State { } var stateContainer = Provider.of(context); - var gitDir = stateContainer.appState.gitBaseDirectory; + final settings = Provider.of(context); + var gitDir = settings.gitBaseDirectory; // Figure out the next available folder String repoFolderName = "journal_"; diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index 96841190..8cb59259 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -18,7 +18,6 @@ import 'package:gitjournal/screens/settings_note_metadata.dart'; import 'package:gitjournal/screens/settings_tags.dart'; import 'package:gitjournal/screens/settings_widgets.dart'; import 'package:gitjournal/settings.dart'; -import 'package:gitjournal/state_container.dart'; import 'package:gitjournal/utils.dart'; import 'package:gitjournal/widgets/folder_selection_dialog.dart'; import 'package:gitjournal/widgets/pro_overlay.dart'; @@ -55,10 +54,8 @@ class SettingsListState extends State { @override Widget build(BuildContext context) { - var stateContainer = Provider.of(context, listen: false); - - var remoteGitConfigured = stateContainer.appState.remoteGitRepoConfigured; var settings = Provider.of(context); + var remoteGitConfigured = settings.remoteGitRepoConfigured; var saveGitAuthor = (String gitAuthor) { settings.gitAuthor = gitAuthor; diff --git a/lib/settings.dart b/lib/settings.dart index bfca15e7..85ba19ef 100644 --- a/lib/settings.dart +++ b/lib/settings.dart @@ -75,6 +75,15 @@ class Settings extends ChangeNotifier { Set inlineTagPrefixes = {'#'}; + // From AppState + String localGitRepoFolderName = ""; + bool localGitRepoConfigured = false; + + String remoteGitRepoFolderName = ""; + bool remoteGitRepoConfigured = false; + + String gitBaseDirectory = ""; + void load(SharedPreferences pref) { onBoardingCompleted = pref.getBool("onBoardingCompleted") ?? false; @@ -158,6 +167,13 @@ class Settings extends ChangeNotifier { inlineTagPrefixes = pref.getStringList("inlineTagPrefixes")?.toSet() ?? inlineTagPrefixes; + + // From AppState + localGitRepoConfigured = pref.getBool("localGitRepoConfigured") ?? false; + remoteGitRepoConfigured = pref.getBool("remoteGitRepoConfigured") ?? false; + localGitRepoFolderName = pref.getString("localGitRepoPath") ?? ""; + remoteGitRepoFolderName = pref.getString("remoteGitRepoPath") ?? ""; + gitBaseDirectory = pref.getString("gitBaseDirectory") ?? ""; } Future save() async { @@ -245,6 +261,12 @@ class Settings extends ChangeNotifier { pref.setInt("settingsVersion", version); + pref.setBool("localGitRepoConfigured", localGitRepoConfigured); + pref.setBool("remoteGitRepoConfigured", remoteGitRepoConfigured); + pref.setString("localGitRepoPath", localGitRepoFolderName); + pref.setString("remoteGitRepoPath", remoteGitRepoFolderName); + pref.setString("gitBaseDirectory", gitBaseDirectory); + notifyListeners(); } @@ -330,6 +352,11 @@ class Settings extends ChangeNotifier { 'swipeToDelete': swipeToDelete.toString(), 'inlineTagPrefixes': inlineTagPrefixes.join(' '), 'emojiParser': emojiParser.toString(), + 'localGitRepoConfigured': localGitRepoConfigured.toString(), + 'remoteGitRepoConfigured': remoteGitRepoConfigured.toString(), + 'localGitRepoFolderName': localGitRepoFolderName.toString(), + 'remoteGitRepoFolderName': remoteGitRepoFolderName.toString(), + 'gitBaseDirectory': gitBaseDirectory.toString(), }; } diff --git a/lib/setup/screens.dart b/lib/setup/screens.dart index 759b7889..21d22cf8 100644 --- a/lib/setup/screens.dart +++ b/lib/setup/screens.dart @@ -21,7 +21,6 @@ import 'package:gitjournal/setup/clone_url.dart'; import 'package:gitjournal/setup/loading_error.dart'; import 'package:gitjournal/setup/repo_selector.dart'; import 'package:gitjournal/setup/sshkey.dart'; -import 'package:gitjournal/state_container.dart'; import 'package:gitjournal/utils.dart'; import 'package:gitjournal/utils/logger.dart'; @@ -468,9 +467,8 @@ class GitHostSetupScreenState extends State { gitCloneErrorMessage = ""; }); - var stateContainer = Provider.of(context); - var appState = stateContainer.appState; - var basePath = appState.gitBaseDirectory; + final settings = Provider.of(context); + var basePath = settings.gitBaseDirectory; // Just in case it was half cloned because of an error String repoPath = p.join(basePath, widget.repoFolderName); diff --git a/lib/state_container.dart b/lib/state_container.dart index 5562348f..d234f397 100644 --- a/lib/state_container.dart +++ b/lib/state_container.dart @@ -5,7 +5,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:path/path.dart' as p; -import 'package:shared_preferences/shared_preferences.dart'; import 'package:synchronized/synchronized.dart'; import 'package:gitjournal/analytics.dart'; @@ -23,6 +22,7 @@ import 'package:gitjournal/utils/logger.dart'; class StateContainer with ChangeNotifier { final AppState appState; + final Settings settings; final _opLock = Lock(); final _loadLock = Lock(); @@ -33,33 +33,33 @@ class StateContainer with ChangeNotifier { GitNoteRepository _gitRepo; NotesCache _notesCache; - StateContainer(this.appState) { - assert(appState.localGitRepoConfigured); + StateContainer(this.appState, this.settings) { + assert(settings.localGitRepoConfigured); String repoPath; - if (appState.remoteGitRepoConfigured) { + if (settings.remoteGitRepoConfigured) { repoPath = - p.join(appState.gitBaseDirectory, appState.remoteGitRepoFolderName); - } else if (appState.localGitRepoConfigured) { + p.join(settings.gitBaseDirectory, settings.remoteGitRepoFolderName); + } else if (settings.localGitRepoConfigured) { repoPath = - p.join(appState.gitBaseDirectory, appState.localGitRepoFolderName); + p.join(settings.gitBaseDirectory, settings.localGitRepoFolderName); } _gitRepo = GitNoteRepository(gitDirPath: repoPath); appState.notesFolder = NotesFolderFS(null, _gitRepo.gitDirPath); // Just a fail safe - if (!appState.remoteGitRepoConfigured) { + if (!settings.remoteGitRepoConfigured) { removeExistingRemoteClone(); } // Makes it easier to filter the analytics getAnalytics().firebase.setUserProperty( name: 'onboarded', - value: appState.remoteGitRepoConfigured.toString(), + value: settings.remoteGitRepoConfigured.toString(), ); - var cachePath = p.join(appState.gitBaseDirectory, "cache.json"); + var cachePath = p.join(settings.gitBaseDirectory, "cache.json"); _notesCache = NotesCache( filePath: cachePath, notesBasePath: _gitRepo.gitDirPath, @@ -79,7 +79,7 @@ class StateContainer with ChangeNotifier { void removeExistingRemoteClone() async { var remoteGitDir = Directory( - p.join(appState.gitBaseDirectory, appState.remoteGitRepoFolderName)); + p.join(settings.gitBaseDirectory, settings.remoteGitRepoFolderName)); var dotGitDir = Directory(p.join(remoteGitDir.path, ".git")); bool exists = dotGitDir.existsSync(); @@ -100,7 +100,7 @@ class StateContainer with ChangeNotifier { } Future syncNotes({bool doNotThrow = false}) async { - if (!appState.remoteGitRepoConfigured) { + if (!settings.remoteGitRepoConfigured) { Log.d("Not syncing because RemoteRepo not configured"); return true; } @@ -348,21 +348,21 @@ class StateContainer with ChangeNotifier { void completeGitHostSetup(String repoFolderName) { () async { - var reconfiguringRemote = appState.remoteGitRepoConfigured; + var reconfiguringRemote = settings.remoteGitRepoConfigured; - appState.remoteGitRepoConfigured = true; - appState.remoteGitRepoFolderName = repoFolderName; + settings.remoteGitRepoConfigured = true; + settings.remoteGitRepoFolderName = repoFolderName; if (!reconfiguringRemote) { await migrateGitRepo( - fromGitBasePath: appState.localGitRepoFolderName, - toGitBaseFolder: appState.remoteGitRepoFolderName, - gitBasePath: appState.gitBaseDirectory, + fromGitBasePath: settings.localGitRepoFolderName, + toGitBaseFolder: settings.remoteGitRepoFolderName, + gitBasePath: settings.gitBaseDirectory, ); } var repoPath = - p.join(appState.gitBaseDirectory, appState.remoteGitRepoFolderName); + p.join(settings.gitBaseDirectory, settings.remoteGitRepoFolderName); _gitRepo = GitNoteRepository(gitDirPath: repoPath); appState.notesFolder.reset(_gitRepo.gitDirPath); @@ -376,7 +376,6 @@ class StateContainer with ChangeNotifier { } Future _persistConfig() async { - var pref = await SharedPreferences.getInstance(); - await appState.save(pref); + await settings.save(); } } diff --git a/lib/widgets/app_drawer.dart b/lib/widgets/app_drawer.dart index 771b9cb2..857f338c 100644 --- a/lib/widgets/app_drawer.dart +++ b/lib/widgets/app_drawer.dart @@ -13,7 +13,6 @@ import 'package:url_launcher/url_launcher.dart'; import 'package:gitjournal/analytics.dart'; import 'package:gitjournal/settings.dart'; -import 'package:gitjournal/state_container.dart'; import 'package:gitjournal/utils.dart'; import 'package:gitjournal/utils/logger.dart'; @@ -21,11 +20,11 @@ class AppDrawer extends StatelessWidget { @override Widget build(BuildContext context) { Widget setupGitButton; - var appState = Provider.of(context).appState; + var settings = Provider.of(context); var textStyle = Theme.of(context).textTheme.bodyText1; var currentRoute = ModalRoute.of(context).settings.name; - if (!appState.remoteGitRepoConfigured) { + if (!settings.remoteGitRepoConfigured) { setupGitButton = ListTile( leading: Icon(Icons.sync, color: textStyle.color), title: Text(tr('drawer.setup'), style: textStyle), @@ -43,7 +42,6 @@ class AppDrawer extends StatelessWidget { } var divider = Row(children: [const Expanded(child: Divider())]); - var settings = Provider.of(context); return Drawer( child: ListView( diff --git a/test_driver/main.dart b/test_driver/main.dart index c5e9ddfa..cc38283f 100644 --- a/test_driver/main.dart +++ b/test_driver/main.dart @@ -4,7 +4,6 @@ import 'package:flutter_driver/driver_extension.dart'; import 'package:path_provider/path_provider.dart'; import 'package:gitjournal/app.dart'; -import 'package:gitjournal/appstate.dart'; import 'package:gitjournal/settings.dart'; import 'package:gitjournal/utils/datetime.dart'; @@ -19,20 +18,20 @@ void main() async { Settings.instance.load(pref); await populateWithData(pref); - await JournalApp.main(pref); + await JournalApp.main(); } // Generate lots of notes and folders better screenshots Future populateWithData(SharedPreferences pref) async { var dir = await getApplicationDocumentsDirectory(); - var appState = AppState(pref); - appState.gitBaseDirectory = dir.path; - appState.localGitRepoConfigured = true; - appState.localGitRepoFolderName = "journal_local"; - appState.save(pref); + var settings = Settings.instance; + settings.gitBaseDirectory = dir.path; + settings.localGitRepoConfigured = true; + settings.localGitRepoFolderName = "journal_local"; + settings.save(); - var repoPath = p.join(dir.path, appState.localGitRepoFolderName); + var repoPath = p.join(dir.path, settings.localGitRepoFolderName); await GitRepository.init(repoPath); print("Filling fake data in $repoPath");