Handle error case for auto updater.
This commit is contained in:
parent
8a7d89c857
commit
d2648c9f62
8 changed files with 213 additions and 143 deletions
|
@ -36,26 +36,21 @@ try {
|
||||||
autoUpdater.autoDownload = !upgradeDisabled;
|
autoUpdater.autoDownload = !upgradeDisabled;
|
||||||
autoUpdater.allowPrerelease = false;
|
autoUpdater.allowPrerelease = false;
|
||||||
|
|
||||||
// This is set to true if an auto update has been downloaded through the Electron
|
const UPDATE_STATE_INIT = 0;
|
||||||
// auto-update system and is ready to install. If the user declined an update earlier,
|
const UPDATE_STATE_CHECKING = 1;
|
||||||
// it will still install on shutdown.
|
const UPDATE_STATE_UPDATES_FOUND = 2;
|
||||||
let autoUpdateDownloaded = false;
|
const UPDATE_STATE_NO_UPDATES_FOUND = 3;
|
||||||
|
const UPDATE_STATE_DOWNLOADING = 4;
|
||||||
|
const UPDATE_STATE_DOWNLOADED = 5;
|
||||||
|
let updateState = UPDATE_STATE_INIT;
|
||||||
|
let updateDownloadItem;
|
||||||
|
|
||||||
|
const isAutoUpdateSupported = ['win32', 'darwin'].includes(process.platform) || !!process.env.APPIMAGE;
|
||||||
|
|
||||||
// This is used to keep track of whether we are showing the special dialog
|
// This is used to keep track of whether we are showing the special dialog
|
||||||
// that we show on Windows after you decline an upgrade and close the app later.
|
// that we show on Windows after you decline an upgrade and close the app later.
|
||||||
let showingAutoUpdateCloseAlert = false;
|
let showingAutoUpdateCloseAlert = false;
|
||||||
|
|
||||||
// This is used to prevent downloading updates multiple times when
|
|
||||||
// using the auto updater API.
|
|
||||||
// As read in the documentation:
|
|
||||||
// "Calling autoUpdater.checkForUpdates() twice will download the update two times."
|
|
||||||
// https://www.electronjs.org/docs/latest/api/auto-updater#autoupdatercheckforupdates
|
|
||||||
let keepCheckingForUpdates = true;
|
|
||||||
|
|
||||||
let downloadUpgradeInitiated = false;
|
|
||||||
|
|
||||||
let downloadUpgradeItem;
|
|
||||||
|
|
||||||
// Keep a global reference, if you don't, they will be closed automatically when the JavaScript
|
// Keep a global reference, if you don't, they will be closed automatically when the JavaScript
|
||||||
// object is garbage collected.
|
// object is garbage collected.
|
||||||
let rendererWindow;
|
let rendererWindow;
|
||||||
|
@ -243,7 +238,8 @@ app.on('activate', () => {
|
||||||
app.on('will-quit', event => {
|
app.on('will-quit', event => {
|
||||||
if (
|
if (
|
||||||
process.platform === 'win32' &&
|
process.platform === 'win32' &&
|
||||||
autoUpdateDownloaded &&
|
updateState === UPDATE_STATE_DOWNLOADED &&
|
||||||
|
isAutoUpdateSupported &&
|
||||||
!appState.autoUpdateAccepted &&
|
!appState.autoUpdateAccepted &&
|
||||||
!showingAutoUpdateCloseAlert
|
!showingAutoUpdateCloseAlert
|
||||||
) {
|
) {
|
||||||
|
@ -327,124 +323,6 @@ ipcMain.on('get-disk-space', async (event) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on('cancel-download-upgrade', () => {
|
|
||||||
if (downloadUpgradeItem) {
|
|
||||||
// Cancel the download and execute the onCancel
|
|
||||||
// callback set in the options.
|
|
||||||
downloadUpgradeItem.cancel();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on('download-upgrade', async (event, params) => {
|
|
||||||
// Prevent downloading multiple times.
|
|
||||||
if (downloadUpgradeInitiated || downloadUpgradeItem) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const { url, options } = params;
|
|
||||||
const dir = fs.mkdtempSync(app.getPath('temp') + path.sep);
|
|
||||||
|
|
||||||
downloadUpgradeInitiated = true;
|
|
||||||
|
|
||||||
// Grab the download item's handler to allow
|
|
||||||
// cancelling the operation if required.
|
|
||||||
options.onStarted = function(downloadItem) {
|
|
||||||
downloadUpgradeItem = downloadItem;
|
|
||||||
};
|
|
||||||
options.onCancel = function() {
|
|
||||||
downloadUpgradeItem = undefined;
|
|
||||||
downloadUpgradeInitiated = false;
|
|
||||||
};
|
|
||||||
options.onProgress = function(p) {
|
|
||||||
rendererWindow.webContents.send('download-progress-update', p);
|
|
||||||
};
|
|
||||||
options.directory = dir;
|
|
||||||
options.onCompleted = function(c) {
|
|
||||||
downloadUpgradeInitiated = false;
|
|
||||||
downloadUpgradeItem = undefined;
|
|
||||||
rendererWindow.webContents.send('download-update-complete', c);
|
|
||||||
};
|
|
||||||
const win = BrowserWindow.getFocusedWindow();
|
|
||||||
await download(win, url, options).catch(e => console.log('e', e));
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on('upgrade', (event, installerPath) => {
|
|
||||||
// what to do if no shutdown in a long time?
|
|
||||||
console.log('Update downloaded to', installerPath);
|
|
||||||
console.log('The app will close and you will be prompted to install the latest version of LBRY.');
|
|
||||||
console.log('After the install is complete, please reopen the app.');
|
|
||||||
|
|
||||||
// Prevent .deb package from opening with archive manager (Ubuntu >= 20)
|
|
||||||
if (process.platform === 'linux' && !process.env.APPIMAGE) {
|
|
||||||
sudo.exec(`dpkg -i ${installerPath}`, { name: app.name }, (err, stdout, stderr) => {
|
|
||||||
if (err || stderr) {
|
|
||||||
rendererWindow.webContents.send('upgrade-installing-error');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-launch the application when the installation finishes.
|
|
||||||
app.relaunch();
|
|
||||||
app.quit();
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
app.on('quit', () => {
|
|
||||||
console.log('Launching upgrade installer at', installerPath);
|
|
||||||
// This gets triggered called after *all* other quit-related events, so
|
|
||||||
// we'll only get here if we're fully prepared and quitting for real.
|
|
||||||
shell.openPath(installerPath);
|
|
||||||
});
|
|
||||||
app.quit();
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on('check-for-updates', (event, autoDownload) => {
|
|
||||||
// Prevent downloading the same update multiple times.
|
|
||||||
if (!keepCheckingForUpdates) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
keepCheckingForUpdates = false;
|
|
||||||
autoUpdater.autoDownload = autoDownload;
|
|
||||||
autoUpdater.checkForUpdates();
|
|
||||||
});
|
|
||||||
|
|
||||||
autoUpdater.on('update-downloaded', () => {
|
|
||||||
autoUpdateDownloaded = true;
|
|
||||||
|
|
||||||
// If this download was trigger by
|
|
||||||
// autoUpdateAccepted it means, the user
|
|
||||||
// wants to install the new update but
|
|
||||||
// needed to downloaded the files first.
|
|
||||||
if (appState.autoUpdateAccepted) {
|
|
||||||
autoUpdater.quitAndInstall();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
autoUpdater.on('update-not-available', () => {
|
|
||||||
keepCheckingForUpdates = true;
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on('autoUpdateAccepted', () => {
|
|
||||||
appState.autoUpdateAccepted = true;
|
|
||||||
|
|
||||||
// quitAndInstall can only be called if the
|
|
||||||
// update has been downloaded. Since the user
|
|
||||||
// can disable auto updates, we have to make
|
|
||||||
// sure it has been downloaded first.
|
|
||||||
if (autoUpdateDownloaded) {
|
|
||||||
autoUpdater.quitAndInstall();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the update hasn't been downloaded,
|
|
||||||
// start downloading it. After it's done, the
|
|
||||||
// event 'update-downloaded' will be triggered,
|
|
||||||
// where we will be able to resume the
|
|
||||||
// update installation.
|
|
||||||
autoUpdater.downloadUpdate();
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on('version-info-requested', () => {
|
ipcMain.on('version-info-requested', () => {
|
||||||
function formatRc(ver) {
|
function formatRc(ver) {
|
||||||
// Adds dash if needed to make RC suffix SemVer friendly
|
// Adds dash if needed to make RC suffix SemVer friendly
|
||||||
|
@ -537,3 +415,147 @@ process.on('uncaughtException', error => {
|
||||||
if (daemon) daemon.quit();
|
if (daemon) daemon.quit();
|
||||||
app.exit(1);
|
app.exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Auto updater
|
||||||
|
// autoUpdater.on('download-progress', (p) => {
|
||||||
|
// rendererWindow.webContents.send('download-progress-update', p);
|
||||||
|
// });
|
||||||
|
|
||||||
|
autoUpdater.on('update-downloaded', () => {
|
||||||
|
updateState = UPDATE_STATE_DOWNLOADED;
|
||||||
|
|
||||||
|
// If this download was trigger by
|
||||||
|
// autoUpdateAccepted it means, the user
|
||||||
|
// wants to install the new update but
|
||||||
|
// needed to downloaded the files first.
|
||||||
|
if (appState.autoUpdateAccepted) {
|
||||||
|
autoUpdater.quitAndInstall();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
autoUpdater.on('update-not-available', () => {
|
||||||
|
updateState = UPDATE_STATE_NO_UPDATES_FOUND;
|
||||||
|
});
|
||||||
|
|
||||||
|
autoUpdater.on('error', () => {
|
||||||
|
updateState = UPDATE_STATE_INIT;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Manual (.deb) update
|
||||||
|
ipcMain.on('cancel-download-upgrade', () => {
|
||||||
|
if (updateDownloadItem) {
|
||||||
|
// Cancel the download and execute the onCancel
|
||||||
|
// callback set in the options.
|
||||||
|
updateDownloadItem.cancel();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on('download-upgrade', (event, params) => {
|
||||||
|
if (updateState !== UPDATE_STATE_UPDATES_FOUND) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (isAutoUpdateSupported) {
|
||||||
|
updateState = UPDATE_STATE_DOWNLOADING;
|
||||||
|
autoUpdater.downloadUpdate();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { url, options } = params;
|
||||||
|
const dir = fs.mkdtempSync(app.getPath('temp') + path.sep);
|
||||||
|
|
||||||
|
updateState = UPDATE_STATE_DOWNLOADING;
|
||||||
|
|
||||||
|
// Grab the download item's handler to allow
|
||||||
|
// cancelling the operation if required.
|
||||||
|
options.onStarted = function(downloadItem) {
|
||||||
|
updateDownloadItem = downloadItem;
|
||||||
|
};
|
||||||
|
options.onCancel = function() {
|
||||||
|
updateState = UPDATE_STATE_UPDATES_FOUND;
|
||||||
|
updateDownloadItem = undefined;
|
||||||
|
};
|
||||||
|
options.onProgress = function(p) {
|
||||||
|
rendererWindow.webContents.send('download-progress-update', p);
|
||||||
|
};
|
||||||
|
options.onCompleted = function(c) {
|
||||||
|
updateState = UPDATE_STATE_DOWNLOADED;
|
||||||
|
updateDownloadItem = undefined;
|
||||||
|
rendererWindow.webContents.send('download-update-complete', c);
|
||||||
|
};
|
||||||
|
options.directory = dir;
|
||||||
|
const win = BrowserWindow.getFocusedWindow();
|
||||||
|
download(win, url, options).catch(e => {
|
||||||
|
updateState = UPDATE_STATE_UPDATES_FOUND;
|
||||||
|
console.log('e', e);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update behavior
|
||||||
|
ipcMain.on('autoUpdateAccepted', () => {
|
||||||
|
appState.autoUpdateAccepted = true;
|
||||||
|
|
||||||
|
// quitAndInstall can only be called if the
|
||||||
|
// update has been downloaded. Since the user
|
||||||
|
// can disable auto updates, we have to make
|
||||||
|
// sure it has been downloaded first.
|
||||||
|
if (updateState === UPDATE_STATE_DOWNLOADED) {
|
||||||
|
autoUpdater.quitAndInstall();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the update hasn't been downloaded,
|
||||||
|
// start downloading it. After it's done, the
|
||||||
|
// event 'update-downloaded' will be triggered,
|
||||||
|
// where we will be able to resume the
|
||||||
|
// update installation.
|
||||||
|
updateState = UPDATE_STATE_DOWNLOADING;
|
||||||
|
autoUpdater.downloadUpdate();
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on('check-for-updates', (event, autoDownload) => {
|
||||||
|
if (![UPDATE_STATE_INIT, UPDATE_STATE_NO_UPDATES_FOUND].includes(updateState)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
updateState = UPDATE_STATE_CHECKING;
|
||||||
|
|
||||||
|
// If autoDownload is true, checkForUpdates will begin the
|
||||||
|
// download automatically.
|
||||||
|
if (autoDownload) {
|
||||||
|
updateState = UPDATE_STATE_DOWNLOADING;
|
||||||
|
}
|
||||||
|
|
||||||
|
autoUpdater.autoDownload = autoDownload;
|
||||||
|
autoUpdater.checkForUpdates();
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on('upgrade', (event, installerPath) => {
|
||||||
|
// what to do if no shutdown in a long time?
|
||||||
|
console.log('Update downloaded to', installerPath);
|
||||||
|
console.log('The app will close and you will be prompted to install the latest version of LBRY.');
|
||||||
|
console.log('After the install is complete, please reopen the app.');
|
||||||
|
|
||||||
|
// Prevent .deb package from opening with archive manager (Ubuntu >= 20)
|
||||||
|
if (process.platform === 'linux' && !process.env.APPIMAGE) {
|
||||||
|
sudo.exec(`dpkg -i ${installerPath}`, { name: app.name }, (err, stdout, stderr) => {
|
||||||
|
if (err || stderr) {
|
||||||
|
rendererWindow.webContents.send('upgrade-installing-error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-launch the application when the installation finishes.
|
||||||
|
app.relaunch();
|
||||||
|
app.quit();
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
app.on('quit', () => {
|
||||||
|
console.log('Launching upgrade installer at', installerPath);
|
||||||
|
// This gets triggered called after *all* other quit-related events, so
|
||||||
|
// we'll only get here if we're fully prepared and quitting for real.
|
||||||
|
shell.openPath(installerPath);
|
||||||
|
});
|
||||||
|
app.quit();
|
||||||
|
});
|
|
@ -57,6 +57,8 @@ export const UPDATE_REMOTE_VERSION = 'UPDATE_REMOTE_VERSION';
|
||||||
export const SKIP_UPGRADE = 'SKIP_UPGRADE';
|
export const SKIP_UPGRADE = 'SKIP_UPGRADE';
|
||||||
export const START_UPGRADE = 'START_UPGRADE';
|
export const START_UPGRADE = 'START_UPGRADE';
|
||||||
export const AUTO_UPDATE_DECLINED = 'AUTO_UPDATE_DECLINED';
|
export const AUTO_UPDATE_DECLINED = 'AUTO_UPDATE_DECLINED';
|
||||||
|
export const AUTO_UPDATE_RESET = 'AUTO_UPDATE_RESET';
|
||||||
|
export const AUTO_UPDATE_FAILED = 'AUTO_UPDATE_FAILED';
|
||||||
export const AUTO_UPDATE_DOWNLOADED = 'AUTO_UPDATE_DOWNLOADED';
|
export const AUTO_UPDATE_DOWNLOADED = 'AUTO_UPDATE_DOWNLOADED';
|
||||||
export const CLEAR_UPGRADE_TIMER = 'CLEAR_UPGRADE_TIMER';
|
export const CLEAR_UPGRADE_TIMER = 'CLEAR_UPGRADE_TIMER';
|
||||||
|
|
||||||
|
|
15
ui/index.jsx
15
ui/index.jsx
|
@ -22,6 +22,8 @@ import {
|
||||||
doUpdateDownloadProgress,
|
doUpdateDownloadProgress,
|
||||||
doNotifyUpdateAvailable,
|
doNotifyUpdateAvailable,
|
||||||
doShowUpgradeInstallationError,
|
doShowUpgradeInstallationError,
|
||||||
|
doAutoUpdateReset,
|
||||||
|
doAutoUpdateFail,
|
||||||
} from 'redux/actions/app';
|
} from 'redux/actions/app';
|
||||||
import { isURIValid } from 'util/lbryURI';
|
import { isURIValid } from 'util/lbryURI';
|
||||||
import { setSearchApi } from 'redux/actions/search';
|
import { setSearchApi } from 'redux/actions/search';
|
||||||
|
@ -129,10 +131,23 @@ ipcRenderer.on('open-uri-requested', (event, url, newSession) => {
|
||||||
handleError();
|
handleError();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
autoUpdater.on('checking-for-update', () => {
|
||||||
|
app.store.dispatch(doAutoUpdateReset());
|
||||||
|
});
|
||||||
|
|
||||||
autoUpdater.on('update-available', (e) => {
|
autoUpdater.on('update-available', (e) => {
|
||||||
|
app.store.dispatch(doAutoUpdateReset());
|
||||||
app.store.dispatch(doNotifyUpdateAvailable(e));
|
app.store.dispatch(doNotifyUpdateAvailable(e));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
autoUpdater.on('update-downloaded', () => {
|
||||||
|
app.store.dispatch(doAutoUpdateReset());
|
||||||
|
});
|
||||||
|
|
||||||
|
autoUpdater.on('error', () => {
|
||||||
|
app.store.dispatch(doAutoUpdateFail());
|
||||||
|
});
|
||||||
|
|
||||||
ipcRenderer.on('upgrade-installing-error', () => {
|
ipcRenderer.on('upgrade-installing-error', () => {
|
||||||
app.store.dispatch(doShowUpgradeInstallationError());
|
app.store.dispatch(doShowUpgradeInstallationError());
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { doAutoUpdateDeclined, doHideModal } from 'redux/actions/app';
|
import { doAutoUpdateDeclined, doHideModal } from 'redux/actions/app';
|
||||||
|
import { selectAutoUpdateFailed } from 'redux/selectors/app';
|
||||||
import ModalAutoUpdateDownloaded from './view';
|
import ModalAutoUpdateDownloaded from './view';
|
||||||
|
|
||||||
const perform = dispatch => ({
|
const select = (state, props) => ({
|
||||||
|
errorWhileUpdating: selectAutoUpdateFailed(state),
|
||||||
|
});
|
||||||
|
|
||||||
|
const perform = (dispatch) => ({
|
||||||
closeModal: () => dispatch(doHideModal()),
|
closeModal: () => dispatch(doHideModal()),
|
||||||
declineAutoUpdate: () => dispatch(doAutoUpdateDeclined()),
|
declineAutoUpdate: () => dispatch(doAutoUpdateDeclined()),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default connect(
|
export default connect(select, perform)(ModalAutoUpdateDownloaded);
|
||||||
null,
|
|
||||||
perform
|
|
||||||
)(ModalAutoUpdateDownloaded);
|
|
||||||
|
|
|
@ -7,13 +7,15 @@ import { Modal } from 'modal/modal';
|
||||||
import LastReleaseChanges from 'component/lastReleaseChanges';
|
import LastReleaseChanges from 'component/lastReleaseChanges';
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
closeModal: any => any,
|
closeModal: (any) => any,
|
||||||
declineAutoUpdate: () => any,
|
declineAutoUpdate: () => any,
|
||||||
|
errorWhileUpdating: boolean,
|
||||||
};
|
};
|
||||||
|
|
||||||
const ModalAutoUpdateDownloaded = (props: Props) => {
|
const ModalAutoUpdateDownloaded = (props: Props) => {
|
||||||
const { closeModal, declineAutoUpdate } = props;
|
const { closeModal, declineAutoUpdate, errorWhileUpdating } = props;
|
||||||
const [disabled, setDisabled] = useState(false);
|
const [disabled, setDisabled] = useState(false);
|
||||||
|
const isDownloading = disabled && !errorWhileUpdating;
|
||||||
|
|
||||||
const handleConfirm = () => {
|
const handleConfirm = () => {
|
||||||
setDisabled(true);
|
setDisabled(true);
|
||||||
|
@ -31,13 +33,14 @@ const ModalAutoUpdateDownloaded = (props: Props) => {
|
||||||
type="confirm"
|
type="confirm"
|
||||||
contentLabel={__('Upgrade Downloaded')}
|
contentLabel={__('Upgrade Downloaded')}
|
||||||
title={__('LBRY leveled up')}
|
title={__('LBRY leveled up')}
|
||||||
confirmButtonLabel={__('Upgrade Now')}
|
confirmButtonLabel={isDownloading ? __('Downloading...') : __('Upgrade Now')}
|
||||||
abortButtonLabel={__('Not Now')}
|
abortButtonLabel={__('Not Now')}
|
||||||
confirmButtonDisabled={disabled}
|
confirmButtonDisabled={isDownloading}
|
||||||
onConfirmed={handleConfirm}
|
onConfirmed={handleConfirm}
|
||||||
onAborted={handleAbort}
|
onAborted={handleAbort}
|
||||||
>
|
>
|
||||||
<LastReleaseChanges />
|
<LastReleaseChanges />
|
||||||
|
{errorWhileUpdating && <p>__('There was an error while updating. Please try again.')</p>}
|
||||||
</Modal>
|
</Modal>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -220,6 +220,18 @@ export function doNotifyUpdateAvailable(e) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function doAutoUpdateReset() {
|
||||||
|
return {
|
||||||
|
type: ACTIONS.AUTO_UPDATE_RESET,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export function doAutoUpdateFail() {
|
||||||
|
return {
|
||||||
|
type: ACTIONS.AUTO_UPDATE_FAILED,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Initiate a timer that will check for an app upgrade every 10 minutes.
|
Initiate a timer that will check for an app upgrade every 10 minutes.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -27,6 +27,7 @@ export type AppState = {
|
||||||
badgeNumber: number,
|
badgeNumber: number,
|
||||||
volume: number,
|
volume: number,
|
||||||
autoUpdateDeclined: boolean,
|
autoUpdateDeclined: boolean,
|
||||||
|
autoUpdateFailed: boolean,
|
||||||
modalsAllowed: boolean,
|
modalsAllowed: boolean,
|
||||||
downloadProgress: ?number,
|
downloadProgress: ?number,
|
||||||
upgradeDownloading: ?boolean,
|
upgradeDownloading: ?boolean,
|
||||||
|
@ -64,6 +65,7 @@ const defaultState: AppState = {
|
||||||
muted: false,
|
muted: false,
|
||||||
autoUpdateDownloaded: false,
|
autoUpdateDownloaded: false,
|
||||||
autoUpdateDeclined: false,
|
autoUpdateDeclined: false,
|
||||||
|
autoUpdateFailed: false,
|
||||||
modalsAllowed: true,
|
modalsAllowed: true,
|
||||||
hasClickedComment: false,
|
hasClickedComment: false,
|
||||||
downloadProgress: undefined,
|
downloadProgress: undefined,
|
||||||
|
@ -152,6 +154,16 @@ reducers[ACTIONS.AUTO_UPDATE_DECLINED] = (state) =>
|
||||||
autoUpdateDeclined: true,
|
autoUpdateDeclined: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
reducers[ACTIONS.AUTO_UPDATE_RESET] = (state) =>
|
||||||
|
Object.assign({}, state, {
|
||||||
|
autoUpdateFailed: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
reducers[ACTIONS.AUTO_UPDATE_FAILED] = (state) =>
|
||||||
|
Object.assign({}, state, {
|
||||||
|
autoUpdateFailed: true,
|
||||||
|
});
|
||||||
|
|
||||||
reducers[ACTIONS.UPGRADE_DOWNLOAD_COMPLETED] = (state, action) =>
|
reducers[ACTIONS.UPGRADE_DOWNLOAD_COMPLETED] = (state, action) =>
|
||||||
Object.assign({}, state, {
|
Object.assign({}, state, {
|
||||||
downloadPath: action.data.path,
|
downloadPath: action.data.path,
|
||||||
|
|
|
@ -54,6 +54,8 @@ export const selectAutoUpdateDownloaded = createSelector(selectState, (state) =>
|
||||||
|
|
||||||
export const selectAutoUpdateDeclined = createSelector(selectState, (state) => state.autoUpdateDeclined);
|
export const selectAutoUpdateDeclined = createSelector(selectState, (state) => state.autoUpdateDeclined);
|
||||||
|
|
||||||
|
export const selectAutoUpdateFailed = createSelector(selectState, (state) => state.autoUpdateFailed);
|
||||||
|
|
||||||
export const selectIsUpdateModalDisplayed = createSelector(selectState, (state) => {
|
export const selectIsUpdateModalDisplayed = createSelector(selectState, (state) => {
|
||||||
return [MODALS.AUTO_UPDATE_DOWNLOADED, MODALS.UPGRADE, MODALS.DOWNLOADING].includes(state.modal);
|
return [MODALS.AUTO_UPDATE_DOWNLOADED, MODALS.UPGRADE, MODALS.DOWNLOADING].includes(state.modal);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue