diff --git a/src/commands/autoUpdate.js b/src/commands/autoUpdate.js index e4e466a0..23bef623 100644 --- a/src/commands/autoUpdate.js +++ b/src/commands/autoUpdate.js @@ -23,6 +23,7 @@ const cmd: Command = createCommand('main:autoUpdate', () => const handleDownload = async info => { try { + sendStatus('checking') const appUpdater = await createElectronAppUpdater({ feedURL: UPDATE_CHECK_FEED, updateVersion: info.version, diff --git a/src/components/Updater/Banner.js b/src/components/Updater/Banner.js index d0d0321e..9c30daae 100644 --- a/src/components/Updater/Banner.js +++ b/src/components/Updater/Banner.js @@ -2,11 +2,17 @@ import React, { PureComponent } from 'react' import styled from 'styled-components' +import { Trans } from 'react-i18next' +import { urls } from 'config/urls' import { radii } from 'styles/theme' +import { openURL } from 'helpers/linking' -import TranslatedError from 'components/TranslatedError' +import Spinner from 'components/base/Spinner' import Box from 'components/base/Box' +import IconUpdate from 'icons/Update' +import IconDonjon from 'icons/Donjon' +import IconWarning from 'icons/TriangleWarning' import { withUpdaterContext } from './UpdaterContext' import type { UpdaterContextType } from './UpdaterContext' @@ -17,38 +23,98 @@ type Props = { export const VISIBLE_STATUS = ['download-progress', 'checking', 'check-success', 'error'] +type Content = { + Icon: React$ComponentType<*>, + message: React$Node, + Right?: React$ComponentType<*>, +} + +type RightProps = { + downloadProgress: number, // eslint-disable-line react/no-unused-prop-types + quitAndInstall: () => void, // eslint-disable-line react/no-unused-prop-types + reDownload: () => void, // eslint-disable-line react/no-unused-prop-types +} + +const CONTENT_BY_STATUS: { [_: string]: Content } = { + 'download-progress': { + Icon: Spinner, + message: , + Right: ({ downloadProgress }: RightProps) => ( + + ), + }, + checking: { + Icon: IconDonjon, + message: , + }, + 'check-success': { + Icon: IconUpdate, + message: , + Right: ({ quitAndInstall }: RightProps) => ( + + + + ), + }, + error: { + Icon: IconWarning, + message: , + Right: ({ reDownload }: RightProps) => ( + + + + ), + }, +} + class UpdaterTopBanner extends PureComponent { + reDownload = () => { + openURL(urls.liveHome) + } + render() { const { context } = this.props - const { status, quitAndInstall, downloadProgress, error } = context + const { status, quitAndInstall, downloadProgress } = context if (!VISIBLE_STATUS.includes(status)) return null + const content: ?Content = CONTENT_BY_STATUS[status] + if (!content) return null + + const { Icon, message, Right } = content + return ( - {status === 'download-progress' && `Downloading update... ${Math.round(downloadProgress)}%`} - {status === 'checking' && `Verifying update...`} - {status === 'error' && - error && ( -
- {'Error during update. Please download again.'} - - - -
- )} - {status === 'check-success' && ( -
- {'Update ready to install. '} - {'install now'} -
+ {Icon && ( + + {/* $FlowFixMe let me do my stuff, flow */} + + + )} + {message} + {Right && ( + + + )}
) } } +const IconContainer = styled.div` + margin-right: 15px; + display: flex; + align-items: center; +` + const Container = styled(Box).attrs({ + horizontal: true, + align: 'center', py: '8px', px: 3, bg: p => (p.status === 'error' ? 'alertRed' : 'wallet'), @@ -56,20 +122,19 @@ const Container = styled(Box).attrs({ mt: -20, mb: 20, fontSize: 4, + ff: 'Open Sans|SemiBold', })` border-radius: ${radii[1]}px; ` -const DownloadLink = styled.span` +const FakeLink = styled.span` color: white; text-decoration: underline; cursor: pointer; ` -const ErrorContainer = styled.div` - margin-top: 10px; - font-family: monospace; - font-size: 10px; +const RightContainer = styled.div` + margin-left: auto; ` export default withUpdaterContext(UpdaterTopBanner) diff --git a/src/components/Updater/UpdateDot.js b/src/components/Updater/UpdateDot.js index 01a34bb5..65a81a98 100644 --- a/src/components/Updater/UpdateDot.js +++ b/src/components/Updater/UpdateDot.js @@ -1,7 +1,7 @@ // @flow import React from 'react' -import styled, { keyframes } from 'styled-components' +import styled from 'styled-components' import { colors } from 'styles/theme' @@ -13,15 +13,6 @@ type Props = { context: UpdaterContextType, } -const rotate = keyframes` - 0% { - transform: rotate(0deg); - } - 100% { - transform: rotate(360deg); - } -` - const getColor = ({ status }: { status: UpdateStatus }) => status === 'error' ? colors.alertRed : colors.wallet @@ -36,53 +27,11 @@ const Dot = styled.div` border-radius: 50%; ` -const Spinner = styled.div` - opacity: 0.5; - position: absolute; - top: -3px; - left: -3px; - animation: ${rotate} 1.5s linear infinite; - width: 14px; - height: 14px; - - &:before { - content: ''; - position: absolute; - right: 0; - bottom: 0; - width: 4px; - height: 4px; - background-color: ${colors.wallet}; - border-radius: 50%; - } - - &:after { - content: ''; - position: absolute; - width: 4px; - height: 4px; - background-color: ${colors.wallet}; - border-radius: 50%; - } -` - function UpdateDot(props: Props) { const { context } = props const { status } = context if (!VISIBLE_STATUS.includes(status)) return null - const showSpinner = status === 'download-progress' || status === 'checking' - return ( -
- {showSpinner && } - -
- ) -} - -const styles = { - container: { - position: 'relative', - }, + return } export default withUpdaterContext(UpdateDot) diff --git a/src/config/urls.js b/src/config/urls.js index 1e0d5376..d022acdf 100644 --- a/src/config/urls.js +++ b/src/config/urls.js @@ -1,6 +1,8 @@ // @flow export const urls = { + liveHome: 'https://www.ledger.com/pages/ledger-live', + // Social twitter: 'https://twitter.com/LedgerHQ', github: 'https://github.com/LedgerHQ/ledger-live-desktop', diff --git a/src/icons/Donjon.js b/src/icons/Donjon.js new file mode 100644 index 00000000..1353a6a7 --- /dev/null +++ b/src/icons/Donjon.js @@ -0,0 +1,39 @@ +// @flow + +import React, { Fragment } from 'react' + +const path = ( + + + + + + + + +) + +export default ({ size, ...p }: { size: number }) => ( + + {path} + +) diff --git a/src/icons/TriangleWarning.js b/src/icons/TriangleWarning.js index c53743bd..72062996 100644 --- a/src/icons/TriangleWarning.js +++ b/src/icons/TriangleWarning.js @@ -9,8 +9,17 @@ const path = ( /> ) -export default ({ height, width, ...p }: { height: number, width: number }) => ( - +export default ({ + height, + width, + size, + ...p +}: { + height?: number, + width?: number, + size?: number, +}) => ( + {path} ) diff --git a/static/i18n/en/app.json b/static/i18n/en/app.json index 5f7804a6..bf20ecbf 100644 --- a/static/i18n/en/app.json +++ b/static/i18n/en/app.json @@ -478,8 +478,13 @@ } }, "update": { - "newVersionReady": "A new update is available", - "relaunch": "Update now" + "downloadInProgress": "Downloading update...", + "downloadProgress": "{{progress}}% completed", + "checking": "Checking update...", + "checkSuccess": "Update ready to install", + "quitAndInstall": "Install now", + "error": "Error during update. Please download again", + "reDownload": "Download again" }, "crash": { "oops": "Oops, something went wrong",