mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-14 10:35:11 +00:00
+11
-1
@@ -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
@@ -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": {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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'),
|
||||
};
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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,
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"updateServerFailure": {
|
||||
"message": "Failed to connect to update server. The Internet connection or the server may be down. Try again later."
|
||||
}
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
@@ -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
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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()));
|
||||
|
||||
Reference in New Issue
Block a user