Use a global state for the app being in background

This commit is contained in:
Vishnu Mohandas 2021-03-03 21:33:03 +05:30
parent b2ea5fbfa0
commit 2d4fc30de3
2 changed files with 31 additions and 20 deletions

View file

@ -29,7 +29,7 @@ void main() async {
Future<void> _runInForeground() async { Future<void> _runInForeground() async {
return await _runWithLogs(() async { return await _runWithLogs(() async {
_logger.info("Starting app in foreground"); _logger.info("Starting app in foreground");
await _init(); await _init(false);
_sync(); _sync();
runApp(MyApp()); runApp(MyApp());
}); });
@ -39,13 +39,13 @@ Future _runInBackground(String taskId) async {
if (_initializationStatus == null) { if (_initializationStatus == null) {
_runWithLogs(() async { _runWithLogs(() async {
_logger.info("[BackgroundFetch] Event received: $taskId"); _logger.info("[BackgroundFetch] Event received: $taskId");
await _init(); await _init(true);
await _sync(isAppInBackground: true); await _sync(isAppInBackground: true);
BackgroundFetch.finish(taskId); BackgroundFetch.finish(taskId);
}); }, prefix: "[bg]");
} else { } else {
_logger.info("[BackgroundFetch] Event received: $taskId"); _logger.info("[BackgroundFetch] Event received: $taskId");
await _init(); await _init(true);
await _sync(isAppInBackground: true); await _sync(isAppInBackground: true);
BackgroundFetch.finish(taskId); BackgroundFetch.finish(taskId);
} }
@ -59,7 +59,7 @@ void _headlessTaskHandler(HeadlessTask task) {
} }
} }
Future<void> _init() async { Future<void> _init(bool isBackground) async {
if (_initializationStatus != null) { if (_initializationStatus != null) {
return _initializationStatus.future; return _initializationStatus.future;
} }
@ -70,7 +70,7 @@ Future<void> _init() async {
await Configuration.instance.init(); await Configuration.instance.init();
await BillingService.instance.init(); await BillingService.instance.init();
await CollectionsService.instance.init(); await CollectionsService.instance.init();
await SyncService.instance.init(); await SyncService.instance.init(isBackground);
await MemoriesService.instance.init(); await MemoriesService.instance.init();
_logger.info("Initialization done"); _logger.info("Initialization done");
_initializationStatus.complete(); _initializationStatus.complete();
@ -85,19 +85,20 @@ Future<void> _sync({bool isAppInBackground = false}) async {
_logger.info("Syncing in background"); _logger.info("Syncing in background");
} }
try { try {
await SyncService.instance.sync(isAppInBackground: isAppInBackground); await SyncService.instance.sync();
} catch (e, s) { } catch (e, s) {
_logger.severe("Sync error", e, s); _logger.severe("Sync error", e, s);
} }
} }
Future _runWithLogs(Function() function) async { Future _runWithLogs(Function() function, {String prefix = ""}) async {
await SuperLogging.main(LogConfig( await SuperLogging.main(LogConfig(
body: function, body: function,
logDirPath: (await getTemporaryDirectory()).path + "/logs", logDirPath: (await getTemporaryDirectory()).path + "/logs",
maxLogFiles: 5, maxLogFiles: 5,
sentryDsn: kDebugMode ? SENTRY_DEBUG_DSN : SENTRY_DSN, sentryDsn: kDebugMode ? SENTRY_DEBUG_DSN : SENTRY_DSN,
enableInDebugMode: true, enableInDebugMode: true,
prefix: prefix,
)); ));
} }

View file

@ -35,6 +35,7 @@ class SyncService {
final _collectionsService = CollectionsService.instance; final _collectionsService = CollectionsService.instance;
final _diffFetcher = DiffFetcher(); final _diffFetcher = DiffFetcher();
bool _syncStopRequested = false; bool _syncStopRequested = false;
bool _isBackground;
Completer<void> _existingSync; Completer<void> _existingSync;
SharedPreferences _prefs; SharedPreferences _prefs;
SyncStatusUpdate _lastSyncStatusEvent; SyncStatusUpdate _lastSyncStatusEvent;
@ -53,7 +54,7 @@ class SyncService {
_logger.info("Connectivity change detected " + result.toString()); _logger.info("Connectivity change detected " + result.toString());
if (Configuration.instance.hasConfiguredAccount() && if (Configuration.instance.hasConfiguredAccount() &&
BillingService.instance.getSubscription() != null) { BillingService.instance.getSubscription() != null) {
sync(isAppInBackground: true); sync();
} }
}); });
@ -67,7 +68,8 @@ class SyncService {
static final SyncService instance = SyncService._privateConstructor(); static final SyncService instance = SyncService._privateConstructor();
Future<void> init() async { Future<void> init(bool isBackground) async {
_isBackground = isBackground;
_prefs = await SharedPreferences.getInstance(); _prefs = await SharedPreferences.getInstance();
if (Platform.isIOS) { if (Platform.isIOS) {
_logger.info("Clearing file cache"); _logger.info("Clearing file cache");
@ -76,7 +78,7 @@ class SyncService {
} }
} }
Future<void> sync({bool isAppInBackground = false}) async { Future<void> sync() async {
_syncStopRequested = false; _syncStopRequested = false;
if (_existingSync != null) { if (_existingSync != null) {
_logger.warning("Sync already in progress, skipping."); _logger.warning("Sync already in progress, skipping.");
@ -85,7 +87,7 @@ class SyncService {
_existingSync = Completer<void>(); _existingSync = Completer<void>();
bool successful = false; bool successful = false;
try { try {
await _doSync(isAppInBackground: isAppInBackground); await _doSync();
if (_lastSyncStatusEvent != null && if (_lastSyncStatusEvent != null &&
_lastSyncStatusEvent.status != SyncStatus.applying_local_diff) { _lastSyncStatusEvent.status != SyncStatus.applying_local_diff) {
Bus.instance.fire(SyncStatusUpdate(SyncStatus.completed)); Bus.instance.fire(SyncStatusUpdate(SyncStatus.completed));
@ -146,10 +148,10 @@ class SyncService {
return _lastSyncStatusEvent; return _lastSyncStatusEvent;
} }
Future<void> _doSync({bool isAppInBackground = false}) async { Future<void> _doSync() async {
final existingLocalFileIDs = await _db.getExistingLocalFileIDs(); final existingLocalFileIDs = await _db.getExistingLocalFileIDs();
final syncStartTime = DateTime.now().microsecondsSinceEpoch; final syncStartTime = DateTime.now().microsecondsSinceEpoch;
if (isAppInBackground) { if (_isBackground) {
await PhotoManager.setIgnorePermissionCheck(true); await PhotoManager.setIgnorePermissionCheck(true);
} else { } else {
final result = await PhotoManager.requestPermission(); final result = await PhotoManager.requestPermission();
@ -262,7 +264,7 @@ class SyncService {
} }
} }
final foldersToBackUp = Configuration.instance.getPathsToBackUp(); final foldersToBackUp = Configuration.instance.getPathsToBackUp();
final filesToBeUploaded = var filesToBeUploaded =
await _db.getFilesToBeUploadedWithinFolders(foldersToBackUp); await _db.getFilesToBeUploadedWithinFolders(foldersToBackUp);
if (kDebugMode) { if (kDebugMode) {
filesToBeUploaded filesToBeUploaded
@ -281,15 +283,21 @@ class SyncService {
Bus.instance.fire(SyncStatusUpdate(SyncStatus.preparing_for_upload)); Bus.instance.fire(SyncStatusUpdate(SyncStatus.preparing_for_upload));
} }
final numberOfFilesCurrentlyUploaded =
await FilesDB.instance.getNumberOfUploadedFiles();
final futures = List<Future>(); final futures = List<Future>();
for (final uploadedFileID in updatedFileIDs) { for (final uploadedFileID in updatedFileIDs) {
final file = await _db.getUploadedFileInAnyCollection(uploadedFileID); final file = await _db.getUploadedFileInAnyCollection(uploadedFileID);
final future = _uploader.upload(file, file.collectionID).then((value) { final future =
_uploader.upload(file, file.collectionID).then((value) async {
uploadCounter++; uploadCounter++;
final newTotal = await FilesDB.instance.getNumberOfUploadedFiles();
Bus.instance Bus.instance
.fire(CollectionUpdatedEvent(collectionID: file.collectionID)); .fire(CollectionUpdatedEvent(collectionID: file.collectionID));
Bus.instance.fire(SyncStatusUpdate(SyncStatus.in_progress, Bus.instance.fire(SyncStatusUpdate(SyncStatus.in_progress,
completed: uploadCounter, total: totalUploads)); completed: newTotal - numberOfFilesCurrentlyUploaded,
total: totalUploads));
}); });
futures.add(future); futures.add(future);
} }
@ -298,17 +306,19 @@ class SyncService {
final collectionID = (await CollectionsService.instance final collectionID = (await CollectionsService.instance
.getOrCreateForPath(file.deviceFolder)) .getOrCreateForPath(file.deviceFolder))
.id; .id;
final future = _uploader.upload(file, collectionID).then((value) { final future = _uploader.upload(file, collectionID).then((value) async {
uploadCounter++; uploadCounter++;
final newTotal = await FilesDB.instance.getNumberOfUploadedFiles();
Bus.instance Bus.instance
.fire(CollectionUpdatedEvent(collectionID: file.collectionID)); .fire(CollectionUpdatedEvent(collectionID: file.collectionID));
Bus.instance.fire(SyncStatusUpdate(SyncStatus.in_progress, Bus.instance.fire(SyncStatusUpdate(SyncStatus.in_progress,
completed: uploadCounter, total: totalUploads)); completed: newTotal - numberOfFilesCurrentlyUploaded,
total: totalUploads));
}); });
futures.add(future); futures.add(future);
} }
try { try {
await Future.wait(futures, eagerError: true); await Future.wait(futures);
} on InvalidFileError { } on InvalidFileError {
// Do nothing // Do nothing
} on FileSystemException { } on FileSystemException {