Browse Source

Polishing the update Banner

develop
meriadec 6 years ago
parent
commit
7c9fb0d314
No known key found for this signature in database GPG Key ID: 1D2FC2305E2CB399
  1. 1
      src/commands/autoUpdate.js
  2. 111
      src/components/Updater/Banner.js
  3. 55
      src/components/Updater/UpdateDot.js
  4. 2
      src/config/urls.js
  5. 39
      src/icons/Donjon.js
  6. 13
      src/icons/TriangleWarning.js
  7. 9
      static/i18n/en/app.json

1
src/commands/autoUpdate.js

@ -23,6 +23,7 @@ const cmd: Command<Input, Result> = createCommand('main:autoUpdate', () =>
const handleDownload = async info => {
try {
sendStatus('checking')
const appUpdater = await createElectronAppUpdater({
feedURL: UPDATE_CHECK_FEED,
updateVersion: info.version,

111
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: <Trans i18nKey="update.downloadInProgress" />,
Right: ({ downloadProgress }: RightProps) => (
<Trans i18nKey="update.downloadProgress" values={{ progress: downloadProgress }} />
),
},
checking: {
Icon: IconDonjon,
message: <Trans i18nKey="update.checking" />,
},
'check-success': {
Icon: IconUpdate,
message: <Trans i18nKey="update.checkSuccess" />,
Right: ({ quitAndInstall }: RightProps) => (
<FakeLink onClick={quitAndInstall}>
<Trans i18nKey="update.quitAndInstall" />
</FakeLink>
),
},
error: {
Icon: IconWarning,
message: <Trans i18nKey="update.error" />,
Right: ({ reDownload }: RightProps) => (
<FakeLink onClick={reDownload}>
<Trans i18nKey="update.reDownload" />
</FakeLink>
),
},
}
class UpdaterTopBanner extends PureComponent<Props> {
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 (
<Container status={status}>
{status === 'download-progress' && `Downloading update... ${Math.round(downloadProgress)}%`}
{status === 'checking' && `Verifying update...`}
{status === 'error' &&
error && (
<div>
{'Error during update. Please download again.'}
<ErrorContainer>
<TranslatedError error={error} />
</ErrorContainer>
</div>
)}
{status === 'check-success' && (
<div>
{'Update ready to install. '}
<DownloadLink onClick={quitAndInstall}>{'install now'}</DownloadLink>
</div>
{Icon && (
<IconContainer>
{/* $FlowFixMe let me do my stuff, flow */}
<Icon size={16} />
</IconContainer>
)}
{message}
{Right && (
<RightContainer>
<Right
downloadProgress={downloadProgress}
quitAndInstall={quitAndInstall}
reDownload={this.reDownload}
/>
</RightContainer>
)}
</Container>
)
}
}
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)

55
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 (
<div style={styles.container}>
{showSpinner && <Spinner />}
<Dot status={status} />
</div>
)
}
const styles = {
container: {
position: 'relative',
},
return <Dot status={status} />
}
export default withUpdaterContext(UpdateDot)

2
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',

39
src/icons/Donjon.js

@ -0,0 +1,39 @@
// @flow
import React, { Fragment } from 'react'
const path = (
<Fragment>
<path
fill="currentColor"
d="m1085.1 267.76v-110.55c0-7.85 3.74-12.45 9-12.21l-144.56-80.23a33.93 33.93 0 0 1 10.11 23.23v110.55z"
/>
<path
fill="currentColor"
d="m1336 406.28v-110.55c0-7.18 3.14-11.6 7.67-12.14l-141.41-78.52a34.34 34.34 0 0 1 8.29 21.4l-0.07 110.53z"
/>
<polygon
fill="currentColor"
transform="translate(206.55 -4.4141e-6)"
points="1254.9 715.08 1167.2 814.98 627.52 515.62 627.52 368.78"
/>
<path
fill="currentColor"
d="m332.03 295.73v110.55l125.52-69.28v-110.55c0-10.18 6.24-21.87 13.94-26.12l97.6-53.87c7.7-4.25 13.94 0.55 13.94 10.73v110.55l125.52-69.24v-110.55c0-10.18 6.24-21.87 13.94-26.12l111.58-61.83-0.11 18.69 0.11 350.09-627.41 346.3-0.11-350.08c0-10.18 6.24-21.87 13.94-26.12l97.59-53.88c7.7-4.25 13.95 0.55 13.95 10.73z"
/>
<path
fill="currentColor"
d="m1175.8 1193.4 2.8-121.54c1.28-55.46-31.41-116.37-72.65-135.34-41.24-19-76 10.88-77.3 66.34l-2.8 121.54z"
/>
<path
fill="currentColor"
d="m294.46 814.91q1.86 205.53 76.34 387.56 67.47 166.41 186.66 290.1 107.94 114.69 236.09 166.43a98.88 98.88 0 0 0 40.48 9v-1152.4z"
/>
</Fragment>
)
export default ({ size, ...p }: { size: number }) => (
<svg viewBox="0 0 1668 1668" width={size} {...p}>
{path}
</svg>
)

13
src/icons/TriangleWarning.js

@ -9,8 +9,17 @@ const path = (
/>
)
export default ({ height, width, ...p }: { height: number, width: number }) => (
<svg viewBox="0 0 17 17" height={height} width={width} {...p}>
export default ({
height,
width,
size,
...p
}: {
height?: number,
width?: number,
size?: number,
}) => (
<svg viewBox="0 0 17 17" height={height || size} width={width || size} {...p}>
{path}
</svg>
)

9
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",

Loading…
Cancel
Save