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
This commit is contained in:
@@ -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.
|
||||
|
||||
+19
-2
@@ -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.
|
||||
|
||||
@@ -32,18 +32,22 @@ class MyHomePage extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _MyHomePageState extends State<MyHomePage> {
|
||||
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<MyHomePage> {
|
||||
children: <Widget>[
|
||||
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,
|
||||
),
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -2084,6 +2084,18 @@ class UpdaterBindings {
|
||||
late final _shorebird_init = _shorebird_initPtr.asFunction<
|
||||
bool Function(ffi.Pointer<AppParameters>, ffi.Pointer<ffi.Char>)>();
|
||||
|
||||
/// 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<ffi.NativeFunction<ffi.UintPtr Function()>>(
|
||||
'shorebird_current_boot_patch_number');
|
||||
late final _shorebird_current_boot_patch_number =
|
||||
_shorebird_current_boot_patch_numberPtr.asFunction<int Function()>();
|
||||
|
||||
/// 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<void Function()>();
|
||||
|
||||
/// 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.
|
||||
|
||||
@@ -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<int?> currentPatchVersion() {
|
||||
return _runInIsolate((updater) => updater.currentPatchNumber());
|
||||
Future<int?> 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<int?> 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.
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user