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.
This commit is contained in:
Vishesh Handa
2020-09-24 23:44:32 +02:00
parent 1f32a3c10e
commit f30c52f595
11 changed files with 79 additions and 108 deletions

View File

@ -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),

View File

@ -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);
}
}

View File

@ -29,6 +29,6 @@ void main() async {
}).sendPort);
runZonedGuarded(() async {
await JournalApp.main(pref);
await JournalApp.main();
}, reportError);
}

View File

@ -372,7 +372,7 @@ class _FolderViewState extends State<FolderView> {
}
List<Widget> _buildNoteActions() {
final appState = Provider.of<StateContainer>(context).appState;
final settings = Provider.of<Settings>(context);
var extraActions = PopupMenuButton<DropDownChoices>(
onSelected: (DropDownChoices choice) {
@ -405,7 +405,7 @@ class _FolderViewState extends State<FolderView> {
onPressed: _folderViewChooserSelected,
key: const ValueKey("FolderViewSelector"),
),
if (appState.remoteGitRepoConfigured) SyncButton(),
if (settings.remoteGitRepoConfigured) SyncButton(),
IconButton(
icon: const Icon(Icons.search),
onPressed: () {

View File

@ -132,7 +132,8 @@ class _GitRemoteSettingsScreenState extends State<GitRemoteSettingsScreen> {
}
var stateContainer = Provider.of<StateContainer>(context);
var gitDir = stateContainer.appState.gitBaseDirectory;
final settings = Provider.of<Settings>(context);
var gitDir = settings.gitBaseDirectory;
// Figure out the next available folder
String repoFolderName = "journal_";

View File

@ -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<SettingsList> {
@override
Widget build(BuildContext context) {
var stateContainer = Provider.of<StateContainer>(context, listen: false);
var remoteGitConfigured = stateContainer.appState.remoteGitRepoConfigured;
var settings = Provider.of<Settings>(context);
var remoteGitConfigured = settings.remoteGitRepoConfigured;
var saveGitAuthor = (String gitAuthor) {
settings.gitAuthor = gitAuthor;

View File

@ -75,6 +75,15 @@ class Settings extends ChangeNotifier {
Set<String> 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(),
};
}

View File

@ -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<GitHostSetupScreen> {
gitCloneErrorMessage = "";
});
var stateContainer = Provider.of<StateContainer>(context);
var appState = stateContainer.appState;
var basePath = appState.gitBaseDirectory;
final settings = Provider.of<Settings>(context);
var basePath = settings.gitBaseDirectory;
// Just in case it was half cloned because of an error
String repoPath = p.join(basePath, widget.repoFolderName);

View File

@ -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<void> 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();
}
}

View File

@ -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<StateContainer>(context).appState;
var settings = Provider.of<Settings>(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: <Widget>[const Expanded(child: Divider())]);
var settings = Provider.of<Settings>(context);
return Drawer(
child: ListView(

View File

@ -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<void> 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");