Files
pybricks-code/src/app/reducers.ts
T
David Lechner b2e098f2dd app: catch error when checking for updates
ServiceWorkerRegistration.update() can raise exceptions, so we need to
catch and handle them, otherwise it will crash redux sagas and the app
will stop responding.

Fixes: https://github.com/pybricks/pybricks-code/issues/1299
2022-11-11 13:00:40 -06:00

107 lines
2.5 KiB
TypeScript

// SPDX-License-Identifier: MIT
// Copyright (c) 2020-2022 The Pybricks Authors
//
// Manages state the app in general.
import { Reducer, combineReducers } from 'redux';
import {
serviceWorkerDidSucceed,
serviceWorkerDidUpdate,
} from '../service-worker/actions';
import {
appCheckForUpdate,
appDidCheckForUpdate,
appDidFailToCheckForUpdate,
appDidReceiveBeforeInstallPrompt,
appDidResolveInstallPrompt,
appShowInstallPrompt,
didInstall,
} from './actions';
/** Indicates that the service worker was successfully registered. */
const isServiceWorkerRegistered: Reducer<boolean> = (state = false, action) => {
if (serviceWorkerDidSucceed.matches(action)) {
return true;
}
return state;
};
const checkingForUpdate: Reducer<boolean> = (state = false, action) => {
if (appCheckForUpdate.matches(action)) {
return true;
}
if (appDidCheckForUpdate.matches(action)) {
if (!action.updateFound) {
return false;
}
// otherwise we wait for service worker to download everything
return state;
}
if (appDidFailToCheckForUpdate.matches(action)) {
return false;
}
if (serviceWorkerDidUpdate.matches(action)) {
return false;
}
return state;
};
const updateAvailable: Reducer<boolean> = (state = false, action) => {
if (serviceWorkerDidUpdate.matches(action)) {
return true;
}
return state;
};
/**
* Indicates that the app has received the BeforeInstallPromptEvent but the
* app has not been installed yet.
*/
const hasUnresolvedInstallPrompt: Reducer<boolean> = (state = false, action) => {
if (appDidReceiveBeforeInstallPrompt.matches(action)) {
return true;
}
if (didInstall.matches(action)) {
return false;
}
return state;
};
/** Indicates that the browser install prompt is active. */
const promptingInstall: Reducer<boolean> = (state = false, action) => {
if (appShowInstallPrompt.matches(action)) {
return true;
}
if (appDidResolveInstallPrompt.matches(action)) {
return false;
}
return state;
};
const readyForOfflineUse: Reducer<boolean> = (state = false, action) => {
if (serviceWorkerDidSucceed.matches(action)) {
return true;
}
return state;
};
export default combineReducers({
isServiceWorkerRegistered,
checkingForUpdate,
updateAvailable,
hasUnresolvedInstallPrompt,
promptingInstall,
readyForOfflineUse,
});