diff --git a/lib/app.dart b/lib/app.dart index faecd1a7..f4429cbd 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -4,7 +4,6 @@ import 'dart:io'; import 'package:flutter/foundation.dart' as foundation; import 'package:flutter/material.dart'; -import 'package:dart_git/git.dart'; import 'package:device_info/device_info.dart'; import 'package:dynamic_theme/dynamic_theme.dart'; import 'package:easy_localization/easy_localization.dart'; @@ -20,7 +19,6 @@ import 'package:shared_preferences/shared_preferences.dart'; import 'package:gitjournal/analytics.dart'; import 'package:gitjournal/app_router.dart'; import 'package:gitjournal/app_settings.dart'; -import 'package:gitjournal/appstate.dart'; import 'package:gitjournal/iap.dart'; import 'package:gitjournal/repository.dart'; import 'package:gitjournal/settings.dart'; @@ -28,12 +26,9 @@ import 'package:gitjournal/themes.dart'; import 'package:gitjournal/utils/logger.dart'; class JournalApp extends StatefulWidget { - final AppState appState; - static Future main(SharedPreferences pref) async { await Log.init(); - var appState = AppState(); var settings = Settings(); settings.load(pref); @@ -46,41 +41,20 @@ class JournalApp extends StatefulWidget { } _sendAppUpdateEvent(appSettings); - var dir = await getApplicationDocumentsDirectory(); - appState.gitBaseDirectory = dir.path; + final gitBaseDirectory = (await getApplicationDocumentsDirectory()).path; + final cacheDir = (await getApplicationSupportDirectory()).path; - await settings.migrate(pref, appState.gitBaseDirectory); + await settings.migrate(pref, gitBaseDirectory); - var gitRepoDir = settings.buildRepoPath(appState.gitBaseDirectory); - - var repoDirStat = File(gitRepoDir).statSync(); - if (repoDirStat.type != FileSystemEntityType.directory) { - settings.folderName = "journal"; - - Log.i("Calling GitInit at: $gitRepoDir"); - await GitRepository.init(gitRepoDir); - - settings.save(); - } else { - var gitRepo = await GitRepository.load(gitRepoDir); - var remotes = gitRepo.config.remotes; - appState.remoteGitRepoConfigured = remotes.isNotEmpty; - } - - appState.cacheDir = (await getApplicationSupportDirectory()).path; + var repo = await Repository.load(gitBaseDirectory, cacheDir, settings); Widget app = ChangeNotifierProvider.value( value: settings, - child: ChangeNotifierProvider( - create: (_) { - return Repository(appState: appState, settings: settings); - }, - child: ChangeNotifierProvider( - child: JournalApp(appState), - create: (_) { - assert(appState.notesFolder != null); - return appState.notesFolder; - }, + child: ChangeNotifierProvider.value( + value: repo, + child: ChangeNotifierProvider.value( + child: JournalApp(), + value: repo.notesFolder, ), ), ); @@ -169,7 +143,7 @@ class JournalApp extends StatefulWidget { static final analytics = Analytics(); static bool isInDebugMode = false; - JournalApp(this.appState); + JournalApp(); @override _JournalAppState createState() => _JournalAppState(); diff --git a/lib/app_router.dart b/lib/app_router.dart index 3838f7c0..638c9ef5 100644 --- a/lib/app_router.dart +++ b/lib/app_router.dart @@ -39,7 +39,7 @@ class AppRouter { Route generateRoute( RouteSettings routeSettings, - Repository stateContainer, + Repository repository, String sharedText, List sharedImages, ) { @@ -49,7 +49,7 @@ class AppRouter { settings: routeSettings, pageBuilder: (_, __, ___) => _screenForRoute( route, - stateContainer, + repository, settings, sharedText, sharedImages, @@ -64,7 +64,7 @@ class AppRouter { settings: routeSettings, builder: (context) => _screenForRoute( route, - stateContainer, + repository, settings, sharedText, sharedImages, @@ -74,7 +74,7 @@ class AppRouter { Widget _screenForRoute( String route, - Repository stateContainer, + Repository repository, Settings settings, String sharedText, List sharedImages, @@ -96,7 +96,7 @@ class AppRouter { return GitHostSetupScreen( repoFolderName: settings.folderName, remoteName: "origin", - onCompletedFunction: stateContainer.completeGitHostSetup, + onCompletedFunction: repository.completeGitHostSetup, ); case '/onBoarding': return OnBoardingScreen(); @@ -113,7 +113,7 @@ class AppRouter { Log.i("New Note - $route"); Log.i("EditorType: $et"); - var rootFolder = stateContainer.appState.notesFolder; + var rootFolder = repository.notesFolder; sharedText = null; sharedImages = null; diff --git a/lib/appstate.dart b/lib/appstate.dart deleted file mode 100644 index 3ae55506..00000000 --- a/lib/appstate.dart +++ /dev/null @@ -1,25 +0,0 @@ -import 'package:gitjournal/core/notes_folder_fs.dart'; - -enum SyncStatus { - Unknown, - Done, - Pulling, - Pushing, - Error, -} - -class AppState { - SyncStatus syncStatus = SyncStatus.Unknown; - int numChanges = 0; - - bool get hasJournalEntries { - return notesFolder.hasNotes; - } - - NotesFolderFS notesFolder; - - var gitBaseDirectory = ""; - var cacheDir = ""; - - bool remoteGitRepoConfigured = false; -} diff --git a/lib/repository.dart b/lib/repository.dart index 6d6106de..f3fb861c 100644 --- a/lib/repository.dart +++ b/lib/repository.dart @@ -9,7 +9,6 @@ import 'package:path/path.dart' as p; import 'package:synchronized/synchronized.dart'; import 'package:gitjournal/analytics.dart'; -import 'package:gitjournal/appstate.dart'; import 'package:gitjournal/core/git_repo.dart'; import 'package:gitjournal/core/note.dart'; import 'package:gitjournal/core/notes_cache.dart'; @@ -20,8 +19,15 @@ import 'package:gitjournal/features.dart'; import 'package:gitjournal/settings.dart'; import 'package:gitjournal/utils/logger.dart'; +enum SyncStatus { + Unknown, + Done, + Pulling, + Pushing, + Error, +} + class Repository with ChangeNotifier { - final AppState appState; final Settings settings; final _opLock = Lock(); @@ -35,19 +41,78 @@ class Repository with ChangeNotifier { String repoPath; - Repository({@required this.appState, @required this.settings}) { - repoPath = settings.buildRepoPath(appState.gitBaseDirectory); + SyncStatus syncStatus = SyncStatus.Unknown; + int numChanges = 0; + bool get hasJournalEntries { + return notesFolder.hasNotes; + } + + NotesFolderFS notesFolder; + + final String gitBaseDirectory; + final String cacheDir; + + bool remoteGitRepoConfigured = false; + + static Future load( + String gitBaseDir, String cacheDir, Settings settings) async { + var repoPath = settings.buildRepoPath(gitBaseDir); + + var repoDirStat = File(repoPath).statSync(); + /* + if (Platform.isIOS && + repoDirStat.type == FileSystemEntityType.notFound && + gitRepoDir.contains("iCloud~io~gitjournal~gitjournal")) { + Log.e("Cannot access iCloud Dir any more"); + Log.e("Reverting back to internal dir"); + settings.storeInternally = true; + settings.save(); + gitRepoDir = settings.buildRepoPath(appState.gitBaseDirectory); + repoDirStat = File(gitRepoDir).statSync(); + }*/ + + var remoteConfigured = false; + + if (repoDirStat.type != FileSystemEntityType.directory) { + settings.folderName = "journal"; + + Log.i("Calling GitInit at: $repoPath"); + await GitRepository.init(repoPath); + + settings.save(); + } else { + var gitRepo = await GitRepository.load(repoPath); + var remotes = gitRepo.config.remotes; + remoteConfigured = remotes.isNotEmpty; + } + + return Repository._internal( + repoPath: repoPath, + gitBaseDirectory: gitBaseDir, + cacheDir: cacheDir, + remoteGitRepoConfigured: remoteConfigured, + settings: settings, + ); + } + + Repository._internal({ + @required this.repoPath, + @required this.gitBaseDirectory, + @required this.cacheDir, + @required this.settings, + @required this.remoteGitRepoConfigured, + }) { _gitRepo = GitNoteRepository(gitDirPath: repoPath, settings: settings); - appState.notesFolder = NotesFolderFS(null, _gitRepo.gitDirPath, settings); + notesFolder = NotesFolderFS(null, _gitRepo.gitDirPath, settings); // Makes it easier to filter the analytics getAnalytics().firebase.setUserProperty( name: 'onboarded', - value: appState.remoteGitRepoConfigured.toString(), + value: remoteGitRepoConfigured.toString(), ); - var cachePath = p.join(appState.cacheDir, "cache.json"); + var cachePath = p.join(cacheDir, "cache.json"); _notesCache = NotesCache( filePath: cachePath, notesBasePath: _gitRepo.gitDirPath, @@ -59,7 +124,7 @@ class Repository with ChangeNotifier { } void _loadFromCache() async { - await _notesCache.load(appState.notesFolder); + await _notesCache.load(notesFolder); Log.i("Finished loading the notes cache"); await _loadNotes(); @@ -69,22 +134,22 @@ class Repository with ChangeNotifier { Future _loadNotes() async { // FIXME: We should report the notes that failed to load return _loadLock.synchronized(() async { - await appState.notesFolder.loadRecursively(); - await _notesCache.buildCache(appState.notesFolder); + await notesFolder.loadRecursively(); + await _notesCache.buildCache(notesFolder); - appState.numChanges = await _gitRepo.numChanges(); + numChanges = await _gitRepo.numChanges(); notifyListeners(); }); } Future syncNotes({bool doNotThrow = false}) async { - if (!appState.remoteGitRepoConfigured) { + if (!remoteGitRepoConfigured) { Log.d("Not syncing because RemoteRepo not configured"); return true; } logEvent(Event.RepoSynced); - appState.syncStatus = SyncStatus.Pulling; + syncStatus = SyncStatus.Pulling; notifyListeners(); Future noteLoadingFuture; @@ -92,7 +157,7 @@ class Repository with ChangeNotifier { await _gitRepo.fetch(); await _gitRepo.merge(); - appState.syncStatus = SyncStatus.Pushing; + syncStatus = SyncStatus.Pushing; notifyListeners(); noteLoadingFuture = _loadNotes(); @@ -100,12 +165,12 @@ class Repository with ChangeNotifier { await _gitRepo.push(); Log.d("Synced!"); - appState.syncStatus = SyncStatus.Done; - appState.numChanges = 0; + syncStatus = SyncStatus.Done; + numChanges = 0; notifyListeners(); } catch (e, stacktrace) { Log.e("Failed to Sync", ex: e, stacktrace: stacktrace); - appState.syncStatus = SyncStatus.Error; + syncStatus = SyncStatus.Error; notifyListeners(); if (shouldLogGitException(e)) { await logException(e, stacktrace); @@ -138,7 +203,7 @@ class Repository with ChangeNotifier { _gitRepo.addFolder(newFolder).then((NoteRepoResult _) { _syncNotes(); - appState.numChanges += 1; + numChanges += 1; notifyListeners(); }); }); @@ -154,7 +219,7 @@ class Repository with ChangeNotifier { folder.parentFS.removeFolder(folder); _gitRepo.removeFolder(folder).then((NoteRepoResult _) { _syncNotes(); - appState.numChanges += 1; + numChanges += 1; notifyListeners(); }); }); @@ -174,7 +239,7 @@ class Repository with ChangeNotifier { .renameFolder(oldFolderPath, folder.folderPath) .then((NoteRepoResult _) { _syncNotes(); - appState.numChanges += 1; + numChanges += 1; notifyListeners(); }); }); @@ -191,7 +256,7 @@ class Repository with ChangeNotifier { _gitRepo.renameNote(oldNotePath, note.filePath).then((NoteRepoResult _) { _syncNotes(); - appState.numChanges += 1; + numChanges += 1; notifyListeners(); }); }); @@ -209,7 +274,7 @@ class Repository with ChangeNotifier { _gitRepo.renameFile(oldPath, newPath).then((NoteRepoResult _) { _syncNotes(); - appState.numChanges += 1; + numChanges += 1; notifyListeners(); }); }); @@ -229,7 +294,7 @@ class Repository with ChangeNotifier { _gitRepo.moveNote(oldNotePath, note.filePath).then((NoteRepoResult _) { _syncNotes(); - appState.numChanges += 1; + numChanges += 1; notifyListeners(); }); }); @@ -248,7 +313,7 @@ class Repository with ChangeNotifier { _gitRepo.addNote(note).then((NoteRepoResult _) { _syncNotes(); - appState.numChanges += 1; + numChanges += 1; notifyListeners(); }); }); @@ -263,7 +328,7 @@ class Repository with ChangeNotifier { // FIXME: What if the Note hasn't yet been saved? note.parent.remove(note); _gitRepo.removeNote(note).then((NoteRepoResult _) async { - appState.numChanges += 1; + numChanges += 1; notifyListeners(); // FIXME: Is there a way of figuring this amount dynamically? // The '4 seconds' is taken from snack_bar.dart -> _kSnackBarDisplayDuration @@ -284,7 +349,7 @@ class Repository with ChangeNotifier { note.parent.add(note); _gitRepo.resetLastCommit().then((NoteRepoResult _) { _syncNotes(); - appState.numChanges -= 1; + numChanges -= 1; notifyListeners(); }); }); @@ -301,7 +366,7 @@ class Repository with ChangeNotifier { _gitRepo.updateNote(note).then((NoteRepoResult _) { _syncNotes(); - appState.numChanges += 1; + numChanges += 1; notifyListeners(); }); }); @@ -319,7 +384,7 @@ class Repository with ChangeNotifier { await config.saveToFS(); _gitRepo.addFolderConfig(config).then((NoteRepoResult _) { _syncNotes(); - appState.numChanges += 1; + numChanges += 1; notifyListeners(); }); }); @@ -327,7 +392,7 @@ class Repository with ChangeNotifier { void completeGitHostSetup(String repoFolderName, String remoteName) { () async { - var repoPath = p.join(appState.gitBaseDirectory, repoFolderName); + var repoPath = p.join(gitBaseDirectory, repoFolderName); Log.i("completeGitHostSetup repoPath: $repoPath"); _gitRepo = GitNoteRepository(gitDirPath: repoPath, settings: settings); @@ -374,8 +439,8 @@ class Repository with ChangeNotifier { this.repoPath = repoPath; _notesCache.clear(); - appState.remoteGitRepoConfigured = true; - appState.notesFolder.reset(repoPath); + remoteGitRepoConfigured = true; + notesFolder.reset(repoPath); settings.folderName = repoFolderName; settings.save(); @@ -393,7 +458,7 @@ class Repository with ChangeNotifier { } Future moveRepoToPath() async { - var newRepoPath = settings.buildRepoPath(appState.gitBaseDirectory); + var newRepoPath = settings.buildRepoPath(gitBaseDirectory); if (newRepoPath != repoPath) { Log.i("Old Path: $repoPath"); @@ -407,7 +472,7 @@ class Repository with ChangeNotifier { _gitRepo = GitNoteRepository(gitDirPath: repoPath, settings: settings); _notesCache.clear(); - appState.notesFolder.reset(repoPath); + notesFolder.reset(repoPath); notifyListeners(); _loadNotes(); diff --git a/lib/screens/folder_view.dart b/lib/screens/folder_view.dart index f456c3d1..21726675 100644 --- a/lib/screens/folder_view.dart +++ b/lib/screens/folder_view.dart @@ -407,7 +407,7 @@ class _FolderViewState extends State { } List _buildNoteActions() { - final appState = Provider.of(context).appState; + final repo = Provider.of(context); var extraActions = PopupMenuButton( key: const ValueKey("PopupMenu"), @@ -443,7 +443,7 @@ class _FolderViewState extends State { onPressed: _folderViewChooserSelected, key: const ValueKey("FolderViewSelector"), ), - if (appState.remoteGitRepoConfigured) SyncButton(), + if (repo.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 3eac5bed..c3d68c14 100644 --- a/lib/screens/settings_git_remote.dart +++ b/lib/screens/settings_git_remote.dart @@ -164,8 +164,8 @@ class _GitRemoteSettingsScreenState extends State { return; } - var stateContainer = Provider.of(context, listen: false); - var gitDir = stateContainer.appState.gitBaseDirectory; + var repo = Provider.of(context, listen: false); + var gitDir = repo.gitBaseDirectory; // Figure out the next available folder String repoFolderName = "journal_"; @@ -184,7 +184,7 @@ class _GitRemoteSettingsScreenState extends State { builder: (context) => GitHostSetupScreen( repoFolderName: repoFolderName, remoteName: 'origin', - onCompletedFunction: stateContainer.completeGitHostSetup, + onCompletedFunction: repo.completeGitHostSetup, ), settings: const RouteSettings(name: '/setupRemoteGit'), ); diff --git a/lib/screens/settings_screen.dart b/lib/screens/settings_screen.dart index 585e8035..a5cdbc5b 100644 --- a/lib/screens/settings_screen.dart +++ b/lib/screens/settings_screen.dart @@ -65,8 +65,7 @@ class SettingsListState extends State { Widget build(BuildContext context) { var settings = Provider.of(context); var appSettings = Provider.of(context); - final stateContainer = Provider.of(context); - final appState = stateContainer.appState; + final repo = Provider.of(context); var saveGitAuthor = (String gitAuthor) { settings.gitAuthor = gitAuthor; @@ -228,7 +227,7 @@ class SettingsListState extends State { ); Navigator.of(context).push(route); }, - enabled: appState.remoteGitRepoConfigured, + enabled: repo.remoteGitRepoConfigured, ), const SizedBox(height: 16.0), ListTile( @@ -302,7 +301,7 @@ class SettingsListState extends State { settings.save(); setState(() {}); - stateContainer.moveRepoToPath(); + repo.moveRepoToPath(); } else { var req = await Permission.storage.request(); if (req.isDenied) { @@ -311,7 +310,7 @@ class SettingsListState extends State { settings.save(); setState(() {}); - stateContainer.moveRepoToPath(); + repo.moveRepoToPath(); return; } settings.storeInternally = true; @@ -323,7 +322,7 @@ class SettingsListState extends State { settings.save(); setState(() {}); - stateContainer.moveRepoToPath(); + repo.moveRepoToPath(); return; } @@ -332,7 +331,7 @@ class SettingsListState extends State { settings.save(); setState(() {}); - stateContainer.moveRepoToPath(); + repo.moveRepoToPath(); return; } }, @@ -359,7 +358,7 @@ class SettingsListState extends State { } } settings.save(); - stateContainer.moveRepoToPath(); + repo.moveRepoToPath(); setState(() {}); }, diff --git a/lib/setup/screens.dart b/lib/setup/screens.dart index b661104e..d155a564 100644 --- a/lib/setup/screens.dart +++ b/lib/setup/screens.dart @@ -492,8 +492,8 @@ class GitHostSetupScreenState extends State { gitCloneErrorMessage = ""; }); - var stateContainer = Provider.of(context, listen: false); - var basePath = stateContainer.appState.gitBaseDirectory; + var repo = Provider.of(context, listen: false); + var basePath = repo.gitBaseDirectory; var settings = Provider.of(context, listen: false); var repoPath = p.join(basePath, widget.repoFolderName); diff --git a/lib/widgets/app_drawer.dart b/lib/widgets/app_drawer.dart index 9634168c..3beb2147 100644 --- a/lib/widgets/app_drawer.dart +++ b/lib/widgets/app_drawer.dart @@ -21,12 +21,12 @@ class AppDrawer extends StatelessWidget { @override Widget build(BuildContext context) { Widget setupGitButton; - var appState = Provider.of(context).appState; + var repo = Provider.of(context); var appSettings = Provider.of(context); var textStyle = Theme.of(context).textTheme.bodyText1; var currentRoute = ModalRoute.of(context).settings.name; - if (!appState.remoteGitRepoConfigured) { + if (!repo.remoteGitRepoConfigured) { setupGitButton = ListTile( leading: Icon(Icons.sync, color: textStyle.color), title: Text(tr('drawer.setup'), style: textStyle), diff --git a/lib/widgets/sync_button.dart b/lib/widgets/sync_button.dart index 230d5ef7..a19e702c 100644 --- a/lib/widgets/sync_button.dart +++ b/lib/widgets/sync_button.dart @@ -8,7 +8,6 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:git_bindings/git_bindings.dart'; import 'package:provider/provider.dart'; -import 'package:gitjournal/appstate.dart'; import 'package:gitjournal/repository.dart'; import 'package:gitjournal/utils.dart'; @@ -41,7 +40,7 @@ class _SyncButtonState extends State { @override Widget build(BuildContext context) { - final appState = Provider.of(context).appState; + final repo = Provider.of(context); if (_connectivity == ConnectivityResult.none) { return GitPendingChangesBadge( @@ -53,7 +52,7 @@ class _SyncButtonState extends State { ), ); } - if (appState.syncStatus == SyncStatus.Pulling) { + if (repo.syncStatus == SyncStatus.Pulling) { return BlinkingIcon( child: GitPendingChangesBadge( child: IconButton( @@ -64,7 +63,7 @@ class _SyncButtonState extends State { ); } - if (appState.syncStatus == SyncStatus.Pushing) { + if (repo.syncStatus == SyncStatus.Pushing) { return BlinkingIcon( child: GitPendingChangesBadge( child: IconButton( @@ -87,8 +86,8 @@ class _SyncButtonState extends State { void _syncRepo() async { try { - final container = Provider.of(context, listen: false); - await container.syncNotes(); + final repo = Provider.of(context, listen: false); + await repo.syncNotes(); } on GitException catch (e) { showSnackbar(context, tr('widgets.SyncButton.error', args: [e.cause])); } catch (e) { @@ -97,9 +96,8 @@ class _SyncButtonState extends State { } IconData _syncStatusIcon() { - final container = Provider.of(context); - final appState = container.appState; - switch (appState.syncStatus) { + final repo = Provider.of(context); + switch (repo.syncStatus) { case SyncStatus.Error: return Icons.cloud_off; @@ -172,11 +170,11 @@ class GitPendingChangesBadge extends StatelessWidget { color: darkMode ? Colors.black : Colors.white, ); - final appState = Provider.of(context).appState; + final repo = Provider.of(context); return Badge( - badgeContent: Text(appState.numChanges.toString(), style: style), - showBadge: appState.numChanges != 0, + badgeContent: Text(repo.numChanges.toString(), style: style), + showBadge: repo.numChanges != 0, badgeColor: theme.iconTheme.color, position: BadgePosition.topRight(top: 10.0, right: 4.0), child: child,