-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(shorebird_code_push): add download update functionality (#37)
* feat: add shorebird_current_boot_patch_number function * Continue support for next_patch_version * rename, return null in case of 0 * feat(shorebird_code_push): add download update functionality * rename defaultValue to fallbackValue * add forTest constructor to ShorebirdCodePush
- Loading branch information
1 parent
318d86e
commit 62ed676
Showing
5 changed files
with
162 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,49 +1,110 @@ | ||
import 'dart:isolate'; | ||
|
||
import 'package:meta/meta.dart'; | ||
import 'package:shorebird_code_push/src/updater.dart'; | ||
|
||
/// A logging function for errors arising from interacting with the native code. | ||
/// | ||
/// Used to override the default behavior of using [print]. | ||
typedef ShorebirdLog = void Function(Object? object); | ||
|
||
/// A function that constructs an [Updater] instance. Used for testing. | ||
@visibleForTesting | ||
typedef UpdaterBuilder = Updater Function(); | ||
|
||
/// {@template shorebird_code_push} | ||
/// Get info about your Shorebird code push app. | ||
/// {@endtemplate} | ||
class ShorebirdCodePush { | ||
/// {@macro shorebird_code_push} | ||
ShorebirdCodePush({ | ||
Updater Function()? createUpdater, // for testing | ||
}) : _createUpdater = createUpdater ?? Updater.new; | ||
this.logError = print, | ||
}) : _buildUpdater = Updater.new; | ||
|
||
/// A test-only constructor that allows overriding the Updater constructor. | ||
@visibleForTesting | ||
ShorebirdCodePush.forTest({ | ||
required this.logError, | ||
required UpdaterBuilder buildUpdater, | ||
}) : _buildUpdater = buildUpdater; | ||
|
||
/// Logs error messages arising from interacting with the native code. | ||
/// | ||
/// Defaults to [print]. | ||
final ShorebirdLog logError; | ||
|
||
final Updater Function() _createUpdater; | ||
final UpdaterBuilder _buildUpdater; | ||
static const _loggingPrefix = '[ShorebirdCodePush]'; | ||
|
||
/// Checks whether a new patch is available for download. | ||
/// | ||
/// Runs in a separate isolate to avoid blocking the UI thread. | ||
Future<bool> checkForUpdate() { | ||
return _runInIsolate((updater) => updater.checkForUpdate()); | ||
return _runInIsolate( | ||
(updater) => updater.checkForUpdate(), | ||
fallbackValue: false, | ||
); | ||
} | ||
|
||
/// The version of the currently-installed patch. Null if no patch is | ||
/// installed (i.e., the app is running the release version). | ||
Future<int?> currentPatchNumber() { | ||
return _runInIsolate((updater) { | ||
final patchNumber = updater.currentPatchNumber(); | ||
return patchNumber == 0 ? null : patchNumber; | ||
}); | ||
return _runInIsolate( | ||
(updater) { | ||
final patchNumber = updater.currentPatchNumber(); | ||
return patchNumber == 0 ? null : patchNumber; | ||
}, | ||
fallbackValue: null, | ||
); | ||
} | ||
|
||
/// The version of the patch that will be run on the next app launch. If no | ||
/// new patch has been downloaded, this will be the same as | ||
/// [currentPatchNumber]. | ||
Future<int?> nextPatchNumber() { | ||
return _runInIsolate((updater) { | ||
final patchNumber = updater.nextPatchNumber(); | ||
return patchNumber == 0 ? null : patchNumber; | ||
}); | ||
return _runInIsolate( | ||
(updater) { | ||
final patchNumber = updater.nextPatchNumber(); | ||
return patchNumber == 0 ? null : patchNumber; | ||
}, | ||
fallbackValue: null, | ||
); | ||
} | ||
|
||
/// Downloads the latest patch, if available. | ||
Future<void> downloadUpdate() async { | ||
await _runInIsolate( | ||
(updater) => updater.downloadUpdate(), | ||
fallbackValue: null, | ||
); | ||
} | ||
|
||
void _logError(Object error) { | ||
final logMessage = '$_loggingPrefix $error'; | ||
if (error is ArgumentError) { | ||
// ffi function lookup failures manifest as ArgumentErrors. | ||
logError( | ||
''' | ||
$logMessage | ||
This is likely because you are not running with the Shorebird Flutter engine (that is, if you ran with `flutter run` instead of `shorebird run`).''', | ||
); | ||
} else { | ||
logError(logMessage); | ||
} | ||
} | ||
|
||
/// Creates an [Updater] in a separate isolate and runs the given function. | ||
Future<T> _runInIsolate<T>(T Function(Updater updater) f) async { | ||
return Isolate.run(() { | ||
/// Creates an [Updater] in a separate isolate and runs the given function. If | ||
/// an error occurs, the error is logged and [fallbackValue] is returned. | ||
Future<T> _runInIsolate<T>( | ||
T Function(Updater updater) f, { | ||
required T fallbackValue, | ||
}) async { | ||
try { | ||
// Create a new Updater in the new isolate. | ||
return f(_createUpdater()); | ||
}); | ||
return await Isolate.run(() => f(_buildUpdater())); | ||
} catch (error) { | ||
_logError(error); | ||
return fallbackValue; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters