From 318d86e13f29acb1fc0adfd62f49d402b50071c3 Mon Sep 17 00:00:00 2001 From: Bryan Oltman Date: Tue, 20 Jun 2023 16:45:43 -0400 Subject: [PATCH] feat: add shorebird_current_boot_patch_number function (#36) * feat: add shorebird_current_boot_patch_number function * Continue support for next_patch_version * rename, return null in case of 0 --- library/include/updater.h | 12 ++++++-- library/src/c_api.rs | 21 ++++++++++++-- shorebird_code_push/example/lib/main.dart | 29 +++++++++++++++---- shorebird_code_push/example/pubspec.yaml | 2 +- .../lib/src/generated/updater_bindings.g.dart | 18 ++++++++++-- .../lib/src/shorebird_code_push.dart | 17 +++++++++-- shorebird_code_push/lib/src/updater.dart | 14 +++++++-- .../test/src/shorebird_code_push_test.dart | 19 +++++++++++- .../test/src/updater_test.dart | 19 ++++++++++-- 9 files changed, 131 insertions(+), 20 deletions(-) diff --git a/library/include/updater.h b/library/include/updater.h index 737d77b..7dfec93 100644 --- a/library/include/updater.h +++ b/library/include/updater.h @@ -55,6 +55,12 @@ SHOREBIRD_EXPORT bool shorebird_init(const struct AppParameters *c_params, const char *c_yaml); +/** + * The currently running patch number, or 0 if the release has not been + * patched. + */ +SHOREBIRD_EXPORT uintptr_t shorebird_current_boot_patch_number(void); + /** * The patch number that will boot on the next run of the app, or 0 if there is * no next patch. @@ -89,8 +95,9 @@ SHOREBIRD_EXPORT void shorebird_start_update_thread(void); /** * Tell the updater that we're launching from what it told us was the - * next patch to boot from. This will copy the next_boot patch to be - * the current_boot patch. + * next patch to boot from. This will copy the next_boot patch to be the + * current_boot patch. + * * It is required to call this function before calling * shorebird_report_launch_success or shorebird_report_launch_failure. */ @@ -108,6 +115,7 @@ SHOREBIRD_EXPORT void shorebird_report_launch_failure(void); * as having been launched successfully. We don't currently do anything * with this information, but it could be used to record a point at which * we will not roll back from. + * * This is not currently wired up to be called from the Engine. It's unclear * where best to connect it. Expo waits 5 seconds after the app launches * and then marks the launch as successful. We could do something similar. diff --git a/library/src/c_api.rs b/library/src/c_api.rs index 8e7068e..e81d09a 100644 --- a/library/src/c_api.rs +++ b/library/src/c_api.rs @@ -116,6 +116,21 @@ pub extern "C" fn shorebird_init( ) } +/// The currently running patch number, or 0 if the release has not been +/// patched. +#[no_mangle] +pub extern "C" fn shorebird_current_boot_patch_number() -> usize { + log_on_error( + || { + Ok(updater::current_boot_patch()? + .map(|p| p.number) + .unwrap_or(0)) + }, + "fetching next_boot_patch_number", + 0, + ) +} + /// The patch number that will boot on the next run of the app, or 0 if there is /// no next patch. #[no_mangle] @@ -175,8 +190,9 @@ pub extern "C" fn shorebird_start_update_thread() { } /// Tell the updater that we're launching from what it told us was the -/// next patch to boot from. This will copy the next_boot patch to be -/// the current_boot patch. +/// next patch to boot from. This will copy the next_boot patch to be the +/// current_boot patch. +/// /// It is required to call this function before calling /// shorebird_report_launch_success or shorebird_report_launch_failure. #[no_mangle] @@ -200,6 +216,7 @@ pub extern "C" fn shorebird_report_launch_failure() { /// as having been launched successfully. We don't currently do anything /// with this information, but it could be used to record a point at which /// we will not roll back from. +/// /// This is not currently wired up to be called from the Engine. It's unclear /// where best to connect it. Expo waits 5 seconds after the app launches /// and then marks the launch as successful. We could do something similar. diff --git a/shorebird_code_push/example/lib/main.dart b/shorebird_code_push/example/lib/main.dart index 23127af..1ccdc2b 100644 --- a/shorebird_code_push/example/lib/main.dart +++ b/shorebird_code_push/example/lib/main.dart @@ -32,18 +32,22 @@ class MyHomePage extends StatefulWidget { } class _MyHomePageState extends State { - final ShorebirdCodePush _shorebirdCodePush = ShorebirdCodePush(); - int? _patchVersion; + final _shorebirdCodePush = ShorebirdCodePush(); + int? _currentPatchVersion; + int? _nextPatchVersion; bool _isCheckingForUpdate = false; @override void initState() { super.initState(); - _shorebirdCodePush.currentPatchVersion().then((version) { + _shorebirdCodePush.currentPatchNumber().then((currentPatchVersion) async { + final nextPatchVersion = await _shorebirdCodePush.nextPatchNumber(); + if (!mounted) return; setState(() { - _patchVersion = version; + _currentPatchVersion = currentPatchVersion; + _nextPatchVersion = nextPatchVersion; }); }); } @@ -83,9 +87,24 @@ class _MyHomePageState extends State { children: [ const Text('Current patch version:'), Text( - _patchVersion != null ? _patchVersion.toString() : 'none', + _currentPatchVersion != null + ? _currentPatchVersion.toString() + : 'none', style: Theme.of(context).textTheme.headlineMedium, ), + if (_nextPatchVersion != null && + _nextPatchVersion != _currentPatchVersion) + Column( + mainAxisSize: MainAxisSize.min, + children: [ + const SizedBox(height: 10), + const Text('Next patch version:'), + Text( + _nextPatchVersion.toString(), + style: Theme.of(context).textTheme.headlineMedium, + ), + ], + ), const SizedBox( height: 20, ), diff --git a/shorebird_code_push/example/pubspec.yaml b/shorebird_code_push/example/pubspec.yaml index 651ecb2..7364ab5 100644 --- a/shorebird_code_push/example/pubspec.yaml +++ b/shorebird_code_push/example/pubspec.yaml @@ -2,7 +2,7 @@ name: shorebird_code_push_example description: An example demonstrating how to use the shorebird_code_push package publish_to: 'none' -version: 1.0.0+15 +version: 1.0.0+17 environment: sdk: '>=3.0.5 <4.0.0' diff --git a/shorebird_code_push/lib/src/generated/updater_bindings.g.dart b/shorebird_code_push/lib/src/generated/updater_bindings.g.dart index 6bc58c5..ca23533 100644 --- a/shorebird_code_push/lib/src/generated/updater_bindings.g.dart +++ b/shorebird_code_push/lib/src/generated/updater_bindings.g.dart @@ -2084,6 +2084,18 @@ class UpdaterBindings { late final _shorebird_init = _shorebird_initPtr.asFunction< bool Function(ffi.Pointer, ffi.Pointer)>(); + /// The currently running patch number, or 0 if the release has not been + /// patched. + int shorebird_current_boot_patch_number() { + return _shorebird_current_boot_patch_number(); + } + + late final _shorebird_current_boot_patch_numberPtr = + _lookup>( + 'shorebird_current_boot_patch_number'); + late final _shorebird_current_boot_patch_number = + _shorebird_current_boot_patch_numberPtr.asFunction(); + /// The patch number that will boot on the next run of the app, or 0 if there is /// no next patch. int shorebird_next_boot_patch_number() { @@ -2157,8 +2169,9 @@ class UpdaterBindings { _shorebird_start_update_threadPtr.asFunction(); /// Tell the updater that we're launching from what it told us was the - /// next patch to boot from. This will copy the next_boot patch to be - /// the current_boot patch. + /// next patch to boot from. This will copy the next_boot patch to be the + /// current_boot patch. + /// /// It is required to call this function before calling /// shorebird_report_launch_success or shorebird_report_launch_failure. void shorebird_report_launch_start() { @@ -2188,6 +2201,7 @@ class UpdaterBindings { /// as having been launched successfully. We don't currently do anything /// with this information, but it could be used to record a point at which /// we will not roll back from. + /// /// This is not currently wired up to be called from the Engine. It's unclear /// where best to connect it. Expo waits 5 seconds after the app launches /// and then marks the launch as successful. We could do something similar. diff --git a/shorebird_code_push/lib/src/shorebird_code_push.dart b/shorebird_code_push/lib/src/shorebird_code_push.dart index c947e7c..72fa7e9 100644 --- a/shorebird_code_push/lib/src/shorebird_code_push.dart +++ b/shorebird_code_push/lib/src/shorebird_code_push.dart @@ -22,8 +22,21 @@ class ShorebirdCodePush { /// The version of the currently-installed patch. Null if no patch is /// installed (i.e., the app is running the release version). - Future currentPatchVersion() { - return _runInIsolate((updater) => updater.currentPatchNumber()); + Future currentPatchNumber() { + return _runInIsolate((updater) { + final patchNumber = updater.currentPatchNumber(); + return patchNumber == 0 ? null : patchNumber; + }); + } + + /// 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 nextPatchNumber() { + return _runInIsolate((updater) { + final patchNumber = updater.nextPatchNumber(); + return patchNumber == 0 ? null : patchNumber; + }); } /// Creates an [Updater] in a separate isolate and runs the given function. diff --git a/shorebird_code_push/lib/src/updater.dart b/shorebird_code_push/lib/src/updater.dart index 0a11aed..8aebc67 100644 --- a/shorebird_code_push/lib/src/updater.dart +++ b/shorebird_code_push/lib/src/updater.dart @@ -18,11 +18,9 @@ class Updater { static late UpdaterBindings bindings; /// The currently active patch number. - // TODO(bryanoltman): this will return the current number + 1 if an update is - // available. It should instead always return the current patch version. int currentPatchNumber() { try { - return bindings.shorebird_next_boot_patch_number(); + return bindings.shorebird_current_boot_patch_number(); } catch (e) { return 0; } @@ -36,4 +34,14 @@ class Updater { return false; } } + + /// The next patch number that will be loaded. Will be the same as + /// currentPatchNumber if no new patch is available. + int nextPatchNumber() { + try { + return bindings.shorebird_next_boot_patch_number(); + } catch (e) { + return 0; + } + } } diff --git a/shorebird_code_push/test/src/shorebird_code_push_test.dart b/shorebird_code_push/test/src/shorebird_code_push_test.dart index 472a307..700f214 100644 --- a/shorebird_code_push/test/src/shorebird_code_push_test.dart +++ b/shorebird_code_push/test/src/shorebird_code_push_test.dart @@ -32,9 +32,26 @@ void main() { }); group('currentPatchNumber', () { + test('returns null if current patch is reported as 0', () async { + when(() => updater.currentPatchNumber()).thenReturn(0); + expect(await shorebirdCodePush.currentPatchNumber(), isNull); + }); + test('forwards the return value of updater.currentPatchNumber', () async { when(() => updater.currentPatchNumber()).thenReturn(1); - expect(await shorebirdCodePush.currentPatchVersion(), 1); + expect(await shorebirdCodePush.currentPatchNumber(), 1); + }); + }); + + group('nextPatchNumber', () { + test('returns null if current patch is reported as 0', () async { + when(() => updater.nextPatchNumber()).thenReturn(0); + expect(await shorebirdCodePush.nextPatchNumber(), isNull); + }); + + test('forwards the return value of updater.nextPatchNumber', () async { + when(() => updater.nextPatchNumber()).thenReturn(1); + expect(await shorebirdCodePush.nextPatchNumber(), 1); }); }); }); diff --git a/shorebird_code_push/test/src/updater_test.dart b/shorebird_code_push/test/src/updater_test.dart index 821860c..d895699 100644 --- a/shorebird_code_push/test/src/updater_test.dart +++ b/shorebird_code_push/test/src/updater_test.dart @@ -23,13 +23,13 @@ void main() { group('currentPatchNumber', () { test('returns 0 if shorebird_next_boot_patch_number throws', () { - when(() => updaterBindings.shorebird_next_boot_patch_number()) + when(() => updaterBindings.shorebird_current_boot_patch_number()) .thenThrow(Exception()); expect(updater.currentPatchNumber(), 0); }); test('forwards the result of shorebird_next_boot_patch_number', () { - when(() => updaterBindings.shorebird_next_boot_patch_number()) + when(() => updaterBindings.shorebird_current_boot_patch_number()) .thenReturn(123); final currentPatchNumber = updater.currentPatchNumber(); expect(currentPatchNumber, 123); @@ -53,5 +53,20 @@ void main() { expect(updater.checkForUpdate(), isFalse); }); }); + + group('nextPatchNumber', () { + test('returns 0 if shorebird_next_boot_patch_number throws', () { + when(() => updaterBindings.shorebird_next_boot_patch_number()) + .thenThrow(Exception()); + expect(updater.nextPatchNumber(), 0); + }); + + test('forwards the result of shorebird_next_boot_patch_number', () { + when(() => updaterBindings.shorebird_next_boot_patch_number()) + .thenReturn(123); + final currentPatchNumber = updater.nextPatchNumber(); + expect(currentPatchNumber, 123); + }); + }); }); }