diff --git a/electron/index.js b/electron/index.js index 3626c0b5d..f49eeb6aa 100644 --- a/electron/index.js +++ b/electron/index.js @@ -417,9 +417,9 @@ process.on('uncaughtException', error => { }); // Auto updater -// autoUpdater.on('download-progress', (p) => { -// rendererWindow.webContents.send('download-progress-update', p); -// }); +autoUpdater.on('download-progress', () => { + updateState = UPDATE_STATE_DOWNLOADING; +}); autoUpdater.on('update-downloaded', () => { updateState = UPDATE_STATE_DOWNLOADED; @@ -434,6 +434,9 @@ autoUpdater.on('update-downloaded', () => { }); autoUpdater.on('update-available', () => { + if (updateState === UPDATE_STATE_DOWNLOADING) { + return; + } updateState = UPDATE_STATE_UPDATES_FOUND; }); @@ -442,6 +445,10 @@ autoUpdater.on('update-not-available', () => { }); autoUpdater.on('error', () => { + if (updateState === UPDATE_STATE_DOWNLOADING) { + updateState = UPDATE_STATE_UPDATES_FOUND; + return; + } updateState = UPDATE_STATE_INIT; }); @@ -507,6 +514,10 @@ ipcMain.on('autoUpdateAccepted', () => { return; } + if (updateState !== UPDATE_STATE_UPDATES_FOUND) { + return; + } + // If the update hasn't been downloaded, // start downloading it. After it's done, the // event 'update-downloaded' will be triggered, diff --git a/ui/constants/action_types.js b/ui/constants/action_types.js index 470f44c7f..8846c944a 100644 --- a/ui/constants/action_types.js +++ b/ui/constants/action_types.js @@ -60,6 +60,7 @@ 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_DOWNLOADING = 'AUTO_UPDATE_DOWNLOADING'; export const CLEAR_UPGRADE_TIMER = 'CLEAR_UPGRADE_TIMER'; // Wallet diff --git a/ui/index.jsx b/ui/index.jsx index 00b72e6df..75b823b0e 100644 --- a/ui/index.jsx +++ b/ui/index.jsx @@ -22,6 +22,7 @@ import { doUpdateDownloadProgress, doNotifyUpdateAvailable, doShowUpgradeInstallationError, + doAutoUpdateDownloading, doAutoUpdateReset, doAutoUpdateFail, } from 'redux/actions/app'; @@ -131,12 +132,15 @@ ipcRenderer.on('open-uri-requested', (event, url, newSession) => { handleError(); }); +autoUpdater.on('download-progress', () => { + app.store.dispatch(doAutoUpdateDownloading()); +}); + autoUpdater.on('checking-for-update', () => { app.store.dispatch(doAutoUpdateReset()); }); autoUpdater.on('update-available', (e) => { - app.store.dispatch(doAutoUpdateReset()); app.store.dispatch(doNotifyUpdateAvailable(e)); }); diff --git a/ui/modal/modalAutoUpdateDownloaded/index.js b/ui/modal/modalAutoUpdateDownloaded/index.js index 2b98538dd..299565bc6 100644 --- a/ui/modal/modalAutoUpdateDownloaded/index.js +++ b/ui/modal/modalAutoUpdateDownloaded/index.js @@ -1,10 +1,12 @@ import { connect } from 'react-redux'; import { doAutoUpdateDeclined, doHideModal } from 'redux/actions/app'; -import { selectAutoUpdateFailed } from 'redux/selectors/app'; +import { selectAutoUpdateFailed, selectAutoUpdateDownloading, selectIsUpgradeAvailable } from 'redux/selectors/app'; import ModalAutoUpdateDownloaded from './view'; const select = (state, props) => ({ errorWhileUpdating: selectAutoUpdateFailed(state), + isDownloading: selectAutoUpdateDownloading(state), + isUpdateAvailable: selectIsUpgradeAvailable(state), }); const perform = (dispatch) => ({ diff --git a/ui/modal/modalAutoUpdateDownloaded/view.jsx b/ui/modal/modalAutoUpdateDownloaded/view.jsx index ed03fe5b3..bef4b967c 100644 --- a/ui/modal/modalAutoUpdateDownloaded/view.jsx +++ b/ui/modal/modalAutoUpdateDownloaded/view.jsx @@ -1,5 +1,5 @@ // @flow -import React, { useState } from 'react'; +import React, { useState, useEffect } from 'react'; // @if TARGET='app' import { ipcRenderer } from 'electron'; // @endif @@ -10,15 +10,16 @@ type Props = { closeModal: (any) => any, declineAutoUpdate: () => any, errorWhileUpdating: boolean, + isDownloading: boolean, + isUpdateAvailable: boolean, }; const ModalAutoUpdateDownloaded = (props: Props) => { - const { closeModal, declineAutoUpdate, errorWhileUpdating } = props; - const [disabled, setDisabled] = useState(false); - const isDownloading = disabled && !errorWhileUpdating; + const { closeModal, declineAutoUpdate, errorWhileUpdating, isDownloading, isUpdateAvailable } = props; + const [waitingForAutoUpdateResponse, setWaitingForAutoUpdateResponse] = useState(false); const handleConfirm = () => { - setDisabled(true); + setWaitingForAutoUpdateResponse(true); ipcRenderer.send('autoUpdateAccepted'); }; @@ -27,6 +28,10 @@ const ModalAutoUpdateDownloaded = (props: Props) => { closeModal(); }; + useEffect(() => { + setWaitingForAutoUpdateResponse(false); + }, [errorWhileUpdating, isDownloading, isUpdateAvailable]); + return ( { contentLabel={__('Upgrade Downloaded')} title={__('LBRY leveled up')} confirmButtonLabel={isDownloading ? __('Downloading...') : __('Upgrade Now')} - abortButtonLabel={__('Not Now')} - confirmButtonDisabled={isDownloading} + abortButtonLabel={isDownloading ? __('Keep browsing') : __('Not Now')} + confirmButtonDisabled={!isUpdateAvailable || isDownloading || waitingForAutoUpdateResponse} onConfirmed={handleConfirm} onAborted={handleAbort} > diff --git a/ui/redux/actions/app.js b/ui/redux/actions/app.js index f4aaa2c46..359f3a15f 100644 --- a/ui/redux/actions/app.js +++ b/ui/redux/actions/app.js @@ -220,6 +220,12 @@ export function doNotifyUpdateAvailable(e) { }; } +export function doAutoUpdateDownloading() { + return { + type: ACTIONS.AUTO_UPDATE_DOWNLOADING, + }; +} + export function doAutoUpdateReset() { return { type: ACTIONS.AUTO_UPDATE_RESET, diff --git a/ui/redux/reducers/app.js b/ui/redux/reducers/app.js index 41ec971b5..10c25dfaf 100644 --- a/ui/redux/reducers/app.js +++ b/ui/redux/reducers/app.js @@ -26,6 +26,7 @@ export type AppState = { hasSignature: boolean, badgeNumber: number, volume: number, + autoUpdateDownloading: boolean, autoUpdateDeclined: boolean, autoUpdateFailed: boolean, modalsAllowed: boolean, @@ -63,6 +64,7 @@ const defaultState: AppState = { upgradeSkipped: sessionStorage.getItem('upgradeSkipped') === 'true', // @endif muted: false, + autoUpdateDownloading: false, autoUpdateDownloaded: false, autoUpdateDeclined: false, autoUpdateFailed: false, @@ -144,9 +146,18 @@ reducers[ACTIONS.UPGRADE_CANCELLED] = (state) => modal: null, }); +reducers[ACTIONS.AUTO_UPDATE_DOWNLOADING] = (state) => + Object.assign({}, state, { + autoUpdateDownloading: true, + autoUpdateDownloaded: false, + autoUpdateFailed: false, + }); + reducers[ACTIONS.AUTO_UPDATE_DOWNLOADED] = (state) => Object.assign({}, state, { + autoUpdateDownloading: false, autoUpdateDownloaded: true, + autoUpdateFailed: false, }); reducers[ACTIONS.AUTO_UPDATE_DECLINED] = (state) => @@ -157,10 +168,14 @@ reducers[ACTIONS.AUTO_UPDATE_DECLINED] = (state) => reducers[ACTIONS.AUTO_UPDATE_RESET] = (state) => Object.assign({}, state, { autoUpdateFailed: false, + autoUpdateDownloading: false, + autoUpdateDownloaded: false, }); reducers[ACTIONS.AUTO_UPDATE_FAILED] = (state) => Object.assign({}, state, { + autoUpdateDownloading: false, + autoUpdateDownloaded: false, autoUpdateFailed: true, }); diff --git a/ui/redux/selectors/app.js b/ui/redux/selectors/app.js index e6ce5c75b..2d0d75bc0 100644 --- a/ui/redux/selectors/app.js +++ b/ui/redux/selectors/app.js @@ -62,6 +62,8 @@ export const selectAutoUpdateDeclined = createSelector(selectState, (state) => s export const selectAutoUpdateFailed = createSelector(selectState, (state) => state.autoUpdateFailed); +export const selectAutoUpdateDownloading = createSelector(selectState, (state) => state.autoUpdateDownloading); + export const selectIsUpdateModalDisplayed = createSelector(selectState, (state) => { return [MODALS.AUTO_UPDATE_DOWNLOADED, MODALS.UPGRADE, MODALS.DOWNLOADING].includes(state.modal); });