Skip to content

Commit 6e88d32

Browse files
feat: rework Update:Available modal
chore: remove wtf legacy colors object, reference legacy colors directly chore: remove wtf legacy colors object, reference legacy colors directly
1 parent 9eb8463 commit 6e88d32

File tree

15 files changed

+292
-343
lines changed

15 files changed

+292
-343
lines changed

packages/components/src/components/Image/images.ts

-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ export const SVG_IMAGES = {
1818
DEVICE_ANOTHER_SESSION: 'device-another-session.svg',
1919
CONNECT_DEVICE: 'connect-device.svg',
2020
ERROR_404: 'error-404.svg',
21-
EARLY_ACCESS: 'early-access.svg',
22-
EARLY_ACCESS_DISABLE: 'early-access-disable.svg',
2321
INVITY_LOGO: 'invity-logo.svg',
2422
COINMARKET_AVATAR: 'coinmarket-avatar.svg',
2523
COINMARKET_SUCCESS: 'coinmarket-success.svg',

packages/components/src/config/colors.ts

+15-4
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,31 @@
11
import { boxShadows, colorVariants } from '@trezor/theme';
22

3-
// TODO: button hover color could be derived from its based color by applying something like opacity/darkening
4-
// same goes for gradients
3+
// TODO: button hover color could be derived from its based color
4+
// by applying something like opacity/darkening, same goes for gradients
55

66
type LightThemeProps = typeof intermediaryTheme.light;
77
type DarkThemeProps = typeof intermediaryTheme.dark;
88

9-
// extracts values for common props (eg. NEUE_BG_GREEN: "#00854D" | "#e3ede0")
9+
// Extracts values for common props (eg. NEUE_BG_GREEN: "#00854D" | "#e3ede0")
1010
type CommonThemeProps = {
1111
[K in keyof LightThemeProps & keyof DarkThemeProps]: LightThemeProps[K] | DarkThemeProps[K];
1212
};
1313

1414
type PropsOnlyInLightTheme = Omit<LightThemeProps, keyof DarkThemeProps>;
1515
type PropsOnlyInDarkTheme = Omit<DarkThemeProps, keyof LightThemeProps>;
1616

17-
// all common theme props and their values are nicely listed, props that are specific to given theme are marked optional
17+
/**
18+
* IMPORTANT:
19+
*
20+
* You have to do this in the every package where you are accessing these theme props
21+
* 1) create `styled.d.ts` file in the root of the project with overwrite of DefaultTheme
22+
* 2) add `typescript-styled-plugin` into the packages devDependencies
23+
*
24+
* See `suite` package for reference.
25+
*/
26+
27+
// All common theme props and their values are nicely listed,
28+
// props that are specific to given theme are marked optional.
1829
export type SuiteThemeColors = CommonThemeProps &
1930
Partial<PropsOnlyInDarkTheme> &
2031
Partial<PropsOnlyInLightTheme>;

packages/suite-data/files/images/svg/early-access-disable.svg

-10
This file was deleted.

packages/suite-data/files/images/svg/early-access.svg

-8
This file was deleted.

packages/suite-desktop-ui/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"@types/react": "18.2.79",
3737
"@types/react-dom": "18.2.19",
3838
"stylelint": "^16.2.1",
39-
"stylelint-config-standard": "^36.0.0"
39+
"stylelint-config-standard": "^36.0.0",
40+
"typescript-styled-plugin": "^0.18.3"
4041
}
4142
}

packages/suite-desktop-ui/src/support/DesktopUpdater.tsx

+8-12
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import {
1818
import { UpdateState } from 'src/reducers/suite/desktopUpdateReducer';
1919
import { ModalContextProvider } from 'src/support/suite/ModalContext';
2020
import { getAppUpdatePayload } from 'src/utils/suite/analytics';
21-
import { selectRouteName } from 'src/reducers/suite/routerReducer';
2221

2322
import { Available } from './DesktopUpdater/Available';
2423
import { Downloading } from './DesktopUpdater/Downloading';
@@ -33,11 +32,8 @@ interface DesktopUpdaterProps {
3332
export const DesktopUpdater = ({ children }: DesktopUpdaterProps) => {
3433
const dispatch = useDispatch();
3534
const { desktopUpdate } = useSelector(state => state);
36-
const routeName = useSelector(selectRouteName);
3735

38-
// Closing a modal opened by auto updater outside of device settings might confuse some users,
39-
// especially on app start if closing it unexpectedly by clicking outside.
40-
const isSettingsRoute = routeName === 'settings-index';
36+
const desktopUpdateState = desktopUpdate.state;
4137

4238
useEffect(() => {
4339
desktopApi.on('update/allow-prerelease', params => dispatch(allowPrerelease(params)));
@@ -90,41 +86,41 @@ export const DesktopUpdater = ({ children }: DesktopUpdaterProps) => {
9086
}
9187

9288
// Non visible states
93-
if ([UpdateState.Checking, UpdateState.NotAvailable].includes(desktopUpdate.state)) {
89+
if ([UpdateState.Checking, UpdateState.NotAvailable].includes(desktopUpdateState)) {
9490
return false;
9591
}
9692

9793
const isEarlyAccessState = [
9894
UpdateState.EarlyAccessDisable,
9995
UpdateState.EarlyAccessEnable,
100-
].includes(desktopUpdate.state);
96+
].includes(desktopUpdateState);
10197

10298
// Enable to setup Early Access even after updater error (when desktopUpdate.latest is undefined).
10399
if (!isEarlyAccessState && !desktopUpdate.latest) {
104100
return false;
105101
}
106102

107103
return true;
108-
}, [desktopUpdate.modalVisibility, desktopUpdate.state, desktopUpdate.latest]);
104+
}, [desktopUpdate.modalVisibility, desktopUpdateState, desktopUpdate.latest]);
109105

110106
const getUpdateModal = () => {
111-
switch (desktopUpdate.state) {
107+
switch (desktopUpdateState) {
112108
case UpdateState.EarlyAccessEnable:
113109
return <EarlyAccessEnable hideWindow={hideWindow} />;
114110
case UpdateState.EarlyAccessDisable:
115111
return <EarlyAccessDisable hideWindow={hideWindow} />;
116112
case UpdateState.Available:
117113
return (
118114
<Available
119-
hideWindow={hideWindow}
115+
onCancel={hideWindow}
120116
latest={desktopUpdate.latest}
121-
isCancelable={isSettingsRoute}
117+
isAutomaticUpdateEnabled={desktopUpdate.isAutomaticUpdateEnabled}
122118
/>
123119
);
124120
case UpdateState.Downloading:
125121
return <Downloading hideWindow={hideWindow} progress={desktopUpdate.progress} />;
126122
case UpdateState.Ready:
127-
return <Ready hideWindow={hideWindow} isCancelable={isSettingsRoute} />;
123+
return <Ready hideWindow={hideWindow} />;
128124
default:
129125
return null;
130126
}
Original file line numberDiff line numberDiff line change
@@ -1,119 +1,177 @@
1+
import { ReactNode } from 'react';
2+
13
import styled from 'styled-components';
24

3-
import { Button, H2, Link, Markdown } from '@trezor/components';
5+
import {
6+
Card,
7+
Checkbox,
8+
Column,
9+
ElevationUp,
10+
Icon,
11+
Link,
12+
Markdown,
13+
NewModal,
14+
Paragraph,
15+
Row,
16+
Text,
17+
useElevation,
18+
} from '@trezor/components';
419
import { desktopApi, UpdateInfo } from '@trezor/suite-desktop-api';
5-
import { borders } from '@trezor/theme';
20+
import { borders, Elevation, mapElevationToBackground, spacings, spacingsPx } from '@trezor/theme';
621

7-
import { Translation, Modal } from 'src/components/suite';
22+
import { Translation } from 'src/components/suite';
823
import { useDispatch } from 'src/hooks/suite';
924
import { getReleaseUrl } from 'src/services/github';
1025
import { download } from 'src/actions/suite/desktopUpdateActions';
1126

12-
// eslint-disable-next-line local-rules/no-override-ds-component
13-
const GreenH2 = styled(H2)`
14-
text-align: left;
15-
color: ${({ theme }) => theme.legacy.TYPE_GREEN};
16-
`;
17-
18-
const ChangelogWrapper = styled.div`
19-
margin: 20px 0;
20-
background: ${({ theme }) => theme.legacy.BG_GREY};
21-
border-radius: ${borders.radii.xs};
27+
const ChangelogWrapper = styled.div<{ $elevation: Elevation }>`
28+
background-color: ${({ theme, $elevation }) => mapElevationToBackground({ theme, $elevation })};
29+
border-radius: ${borders.radii.md};
2230
max-height: 400px;
2331
overflow-y: auto;
24-
padding: 16px 20px;
32+
padding: ${spacingsPx.md} ${spacingsPx.xl};
2533
`;
2634

27-
// eslint-disable-next-line local-rules/no-override-ds-component
28-
const StyledLink = styled(Link)`
29-
align-self: start;
35+
const GrayTag = styled.div`
36+
border-radius: ${borders.radii.full};
37+
background-color: ${({ theme }) => theme.backgroundNeutralSubtleOnElevation0};
38+
padding: ${spacingsPx.xxxs} ${spacingsPx.xs};
39+
color: ${({ theme }) => theme.textSubdued};
3040
`;
3141

32-
const StyledModal = styled(Modal)`
33-
${Modal.BottomBar} {
34-
> * {
35-
flex: 1;
36-
}
37-
}
42+
const GreenTag = styled.div`
43+
display: flex;
44+
align-items: center;
45+
gap: ${spacingsPx.xxs};
46+
border-radius: ${borders.radii.full};
47+
background-color: ${({ theme }) => theme.backgroundPrimarySubtleOnElevation0};
48+
padding: ${spacingsPx.xxxs} ${spacingsPx.xs};
3849
`;
3950

51+
const NewTag = () => (
52+
<GreenTag>
53+
<Icon name="sparkleFilled" variant="primary" size="small" />
54+
<Text variant="primary">
55+
<Translation id="TR_UPDATE_MODAL_ENABLE_AUTO_UPDATES_NEW_TAG" />
56+
</Text>
57+
</GreenTag>
58+
);
59+
60+
const Changelog = ({ children }: { children: ReactNode }) => {
61+
const { elevation } = useElevation();
62+
63+
return <ChangelogWrapper $elevation={elevation}>{children}</ChangelogWrapper>;
64+
};
65+
4066
interface VersionNameProps {
4167
latestVersion?: string;
4268
prerelease: boolean;
4369
}
4470

4571
const getVersionName = ({ latestVersion, prerelease }: VersionNameProps): string => {
46-
if (!latestVersion) {
47-
// fallback for undefined version
72+
if (latestVersion === undefined) {
4873
return '';
4974
}
50-
if (!prerelease) {
51-
// regular case
75+
76+
if (prerelease !== undefined) {
5277
return latestVersion;
5378
}
79+
5480
if (!latestVersion.includes('-')) {
55-
// add beta label for pre-releases, but prevent versions like '21.10.1-alpha-beta'
5681
return `${latestVersion}-beta`;
5782
}
5883

59-
// fallback for pre-release versions already including some pre-release components
6084
return latestVersion;
6185
};
6286

6387
interface AvailableProps {
64-
hideWindow: () => void;
65-
isCancelable: boolean;
66-
latest?: UpdateInfo;
88+
onCancel: () => void;
89+
latest: UpdateInfo | undefined;
90+
isAutomaticUpdateEnabled: boolean;
6791
}
6892

69-
export const Available = ({ hideWindow, isCancelable, latest }: AvailableProps) => {
93+
export const Available = ({ onCancel, latest, isAutomaticUpdateEnabled }: AvailableProps) => {
7094
const dispatch = useDispatch();
7195

7296
const downloadUpdate = () => {
7397
dispatch(download());
7498
desktopApi.downloadUpdate();
7599
};
76100

101+
const suiteCurrentVersion = process.env.VERSION || '';
102+
const suiteNewVersion = getVersionName({
103+
latestVersion: latest?.version,
104+
prerelease: !!latest?.prerelease,
105+
});
106+
107+
const handleToggleAutoUpdateClick = () =>
108+
desktopApi.setAutomaticUpdateEnabled(!isAutomaticUpdateEnabled);
109+
77110
return (
78-
<StyledModal
111+
<NewModal
79112
heading={<Translation id="TR_UPDATE_MODAL_AVAILABLE_HEADING" />}
80-
isCancelable={isCancelable}
81-
onCancel={hideWindow}
82-
bottomBarComponents={
113+
description={
114+
<Translation
115+
id="TR_UPDATE_MODAL_YOUR_VERSION"
116+
values={{ version: suiteCurrentVersion }}
117+
/>
118+
}
119+
onCancel={onCancel}
120+
bottomContent={
83121
<>
84-
<Button onClick={hideWindow} variant="tertiary">
85-
<Translation id="TR_UPDATE_MODAL_NOT_NOW" />
86-
</Button>
87-
<Button onClick={downloadUpdate} variant="primary">
122+
<NewModal.Button onClick={downloadUpdate} variant="primary">
88123
<Translation id="TR_UPDATE_MODAL_START_DOWNLOAD" />
89-
</Button>
124+
</NewModal.Button>
125+
<NewModal.Button onClick={onCancel} variant="tertiary">
126+
<Translation id="TR_UPDATE_MODAL_NOT_NOW" />
127+
</NewModal.Button>
90128
</>
91129
}
92130
>
93-
<GreenH2>
94-
<Translation
95-
id="TR_VERSION_HAS_BEEN_RELEASED"
96-
values={{
97-
version: getVersionName({
98-
latestVersion: latest?.version,
99-
prerelease: !!latest?.prerelease,
100-
}),
101-
}}
102-
/>
103-
</GreenH2>
104-
105-
<ChangelogWrapper>
106-
{latest?.changelog ? (
107-
<Markdown>{latest?.changelog}</Markdown>
108-
) : (
109-
<Translation id="TR_COULD_NOT_RETRIEVE_CHANGELOG" />
110-
)}
111-
</ChangelogWrapper>
112-
<StyledLink variant="nostyle" href={getReleaseUrl(latest?.version ?? '')}>
113-
<Button variant="tertiary" icon="github">
114-
<Translation id="TR_CHANGELOG_ON_GITHUB" />
115-
</Button>
116-
</StyledLink>
117-
</StyledModal>
131+
<Column gap={spacings.xs} alignItems="start">
132+
<div>
133+
<Paragraph typographyStyle="highlight" variant="primary">
134+
<Translation
135+
id="TR_VERSION_HAS_RELEASED"
136+
values={{ version: suiteNewVersion }}
137+
/>
138+
</Paragraph>
139+
<Paragraph typographyStyle="hint" variant="tertiary">
140+
<Translation id="TR_WERE_CONSTANTLY_WORKING_TO_IMPROVE" />
141+
</Paragraph>
142+
</div>
143+
144+
<ElevationUp>
145+
<Changelog>
146+
{latest?.changelog ? (
147+
<Markdown>{latest?.changelog}</Markdown>
148+
) : (
149+
<Translation id="TR_COULD_NOT_RETRIEVE_CHANGELOG" />
150+
)}
151+
</Changelog>
152+
</ElevationUp>
153+
154+
<Row justifyContent="space-between" width="100%">
155+
<Link variant="nostyle" href={getReleaseUrl(latest?.version ?? '')}>
156+
<GrayTag>
157+
<Translation id="TR_READ_ALL_ON_GITHUB" />
158+
</GrayTag>
159+
</Link>
160+
161+
{latest?.releaseDate && <Text variant="tertiary">{latest?.releaseDate}</Text>}
162+
</Row>
163+
164+
<ElevationUp>
165+
<Card>
166+
<Row justifyContent="start" gap={spacings.xs}>
167+
<Checkbox onClick={handleToggleAutoUpdateClick}>
168+
<Translation id="TR_UPDATE_MODAL_ENABLE_AUTO_UPDATES" />
169+
</Checkbox>
170+
<NewTag />
171+
</Row>
172+
</Card>
173+
</ElevationUp>
174+
</Column>
175+
</NewModal>
118176
);
119177
};

0 commit comments

Comments
 (0)