Merge pull request #1300 from pybricks/dlech

fixes
This commit is contained in:
David Lechner
2022-11-11 13:16:24 -06:00
committed by GitHub
12 changed files with 102 additions and 5 deletions
+11 -1
View File
@@ -4,6 +4,15 @@
## [Unreleased]
## [2.0.0-beta.11] - 2022-11-11
### Fixed
- Fixed app freezing when checking for updates and update server is unreachable ([pybricks-code#1299]).
- Added delay to try to mitigate errors when flashing firmware on city hubs ([support#792]).
[pybricks-code#1299]: https://github.com/pybricks/pybricks-code/issues/1299
[support#792]: https://github.com/orgs/pybricks/discussions/792
## [2.0.0-beta.10] - 2022-11-11
### Added
@@ -486,7 +495,8 @@ Prerelease changes are documented at [support#48].
<!-- links for version headings -->
[Unreleased]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.10...HEAD
[Unreleased]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.11...HEAD
[2.0.0-beta.11]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.10...v2.0.0-beta.11
[2.0.0-beta.10]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.9...v2.0.0-beta.10
[2.0.0-beta.9]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.8...v2.0.0-beta.9
[2.0.0-beta.8]: https://github.com/pybricks/pybricks-code/compare/v2.0.0-beta.7...v2.0.0-beta.8
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@pybricks/pybricks-code",
"version": "2.0.0-beta.10",
"version": "2.0.0-beta.11",
"license": "MIT",
"author": "The Pybricks Authors",
"repository": {
+2
View File
@@ -3,6 +3,7 @@
import { ToastProps } from '@blueprintjs/core';
import alerts from './alerts/alerts';
import app from './app/alerts';
import ble from './ble/alerts';
import explorer from './explorer/alerts';
import firmware from './firmware/alerts';
@@ -12,6 +13,7 @@ import type { CreateToast } from './toasterTypes';
/** This collects alerts from all of the subsystems of the app */
const alertDomains = {
alerts,
app,
ble,
explorer,
firmware,
+5
View File
@@ -21,6 +21,11 @@ export const appDidCheckForUpdate = createAction((updateFound: boolean) => ({
updateFound,
}));
/** Action that indicates that checking for an update failed. */
export const appDidFailToCheckForUpdate = createAction(() => ({
type: 'app.action.didFailToCheckForUpdate',
}));
/* Action that indicates the browser wants to prompt the use to install the app. */
export const appDidReceiveBeforeInstallPrompt = createAction(() => ({
type: 'app.action.didBeforeInstallPrompt',
+21
View File
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
import { Intent } from '@blueprintjs/core';
import React from 'react';
import type { CreateToast } from '../../toasterTypes';
import { useI18n } from './i18n';
const UpdateServerFailure: React.VoidFunctionComponent = () => {
const i18n = useI18n();
return <p>{i18n.translate('updateServerFailure.message')}</p>;
};
export const updateServerFailure: CreateToast = (onAction) => {
return {
message: <UpdateServerFailure />,
icon: 'error',
intent: Intent.DANGER,
onDismiss: () => onAction('dismiss'),
};
};
+12
View File
@@ -0,0 +1,12 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
import { useI18n as useShopifyI18n } from '@shopify/react-i18n';
import type { TypedI18n } from '../../i18n';
import type translations from './translations/en.json';
export function useI18n(): TypedI18n<typeof translations> {
// istanbul ignore next: babel-loader rewrites this line
const [i18n] = useShopifyI18n();
return i18n;
}
+9
View File
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: MIT
// Copyright (c) 2022 The Pybricks Authors
import { updateServerFailure } from './UpdateServerFailure';
// gathers all of the alert creation functions for passing up to the top level
export default {
updateServerFailure,
};
+5
View File
@@ -0,0 +1,5 @@
{
"updateServerFailure": {
"message": "Failed to connect to update server. The Internet connection or the server may be down. Try again later."
}
}
+5
View File
@@ -9,6 +9,7 @@ import {
import {
appCheckForUpdate,
appDidCheckForUpdate,
appDidFailToCheckForUpdate,
appDidReceiveBeforeInstallPrompt,
appDidResolveInstallPrompt,
appShowInstallPrompt,
@@ -59,6 +60,10 @@ test('checkingForUpdate', () => {
reducers({ checkingForUpdate: true } as State, appDidCheckForUpdate(false))
.checkingForUpdate,
).toBe(false);
expect(
reducers({ checkingForUpdate: true } as State, appDidFailToCheckForUpdate())
.checkingForUpdate,
).toBe(false);
expect(
reducers({ checkingForUpdate: true } as State, serviceWorkerDidUpdate())
.checkingForUpdate,
+5
View File
@@ -11,6 +11,7 @@ import {
import {
appCheckForUpdate,
appDidCheckForUpdate,
appDidFailToCheckForUpdate,
appDidReceiveBeforeInstallPrompt,
appDidResolveInstallPrompt,
appShowInstallPrompt,
@@ -39,6 +40,10 @@ const checkingForUpdate: Reducer<boolean> = (state = false, action) => {
return state;
}
if (appDidFailToCheckForUpdate.matches(action)) {
return false;
}
if (serviceWorkerDidUpdate.matches(action)) {
return false;
}
+20 -3
View File
@@ -3,15 +3,18 @@
import { eventChannel } from 'redux-saga';
import { call, delay, fork, put, take, takeEvery } from 'typed-redux-saga/macro';
import { alertsShowAlert } from '../alerts/actions';
import {
serviceWorkerDidSucceed,
serviceWorkerDidUpdate,
} from '../service-worker/actions';
import * as serviceWorkerRegistration from '../serviceWorkerRegistration';
import { ensureError } from '../utils';
import { BeforeInstallPromptEvent } from '../utils/dom';
import {
appCheckForUpdate,
appDidCheckForUpdate,
appDidFailToCheckForUpdate,
appDidReceiveBeforeInstallPrompt,
appDidResolveInstallPrompt,
appReload,
@@ -36,9 +39,23 @@ function* handleAppReload(registration: ServiceWorkerRegistration): Generator {
* Must be called (forked) with serviceWorkerRegistration context set.
*/
function* handleAppCheckForUpdate(registration: ServiceWorkerRegistration): Generator {
yield* call(() => registration.update());
const updateFound = registration.installing !== null;
yield* put(appDidCheckForUpdate(updateFound));
try {
yield* call(() => registration.update());
const updateFound = registration.installing !== null;
yield* put(appDidCheckForUpdate(updateFound));
} catch (err) {
if (err instanceof TypeError) {
yield* put(alertsShowAlert('app', 'updateServerFailure'));
} else {
yield* put(
alertsShowAlert('alerts', 'unexpectedError', {
error: ensureError(err),
}),
);
}
yield* put(appDidFailToCheckForUpdate());
}
}
/**
+6
View File
@@ -393,6 +393,12 @@ function* handleFlashFirmware(action: ReturnType<typeof flashFirmware>): Generat
return;
}
// istanbul ignore if
if (process.env.NODE_ENV !== 'test') {
// give OS Bluetooth stack some time to settle
yield* delay(1000);
}
const nextMessageId = yield* getContext<() => number>('nextMessageId');
const infoAction = yield* put(infoRequest(nextMessageId()));