Skip to content

Commit b628165

Browse files
WIP
1 parent 748d4f0 commit b628165

31 files changed

+281
-68
lines changed

desktop/packages/mullvad-vpn/src/renderer/components/views/download-update/components/Footer/Footer.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ export const Footer = () => {
2525
const showReportProblemButton = useShowReportProblemButton();
2626

2727
return (
28-
<StyledFlex $gap="medium" $padding="medium" $flexDirection="column">
28+
<StyledFlex $gap="medium" $padding="large" $flexDirection="column">
2929
<AnimateHeight expanded={showDownloadDetails}>
3030
<DownloadDetails />
3131
</AnimateHeight>
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1+
import { Flex } from '../../../../../../../lib/components';
12
import { DownloadProgress, Label } from './components';
23
import { useShowDownloadProgress } from './hooks';
34

45
export function DownloadDetails() {
56
const showDownloadProgress = useShowDownloadProgress();
67

78
return (
8-
<>
9+
<Flex $gap="medium" $flexDirection="column">
910
<Label />
1011
{showDownloadProgress ? <DownloadProgress /> : null}
11-
</>
12+
</Flex>
1213
);
1314
}

desktop/packages/mullvad-vpn/src/renderer/components/views/download-update/components/Footer/components/DownloadDetails/components/Label/Label.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import { useAppUpgradeEvent } from '../../../../../../hooks';
22
import {
33
DownloadProgress,
44
DownloadStarted,
5-
ErrorMessage,
65
StartingInstaller,
6+
UpgradeError,
77
VerifyingInstaller,
88
} from './components';
99

@@ -20,7 +20,7 @@ export function Label() {
2020
case 'APP_UPGRADE_EVENT_STARTING_INSTALLER':
2121
return <StartingInstaller />;
2222
case 'APP_UPGRADE_EVENT_ERROR':
23-
return <ErrorMessage />;
23+
return <UpgradeError />;
2424
default:
2525
return null;
2626
}

desktop/packages/mullvad-vpn/src/renderer/components/views/download-update/components/Footer/components/DownloadDetails/components/Label/components/ErrorMessage.tsx

-18
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { ErrorMessage, StartingInstallerFailed } from './components';
2+
import { useShowErrorMessage, useShowStartingInstallerFailed } from './hooks';
3+
4+
export function UpgradeError() {
5+
const showErrorMessage = useShowErrorMessage();
6+
const showStartingInstallerFailed = useShowStartingInstallerFailed();
7+
8+
return (
9+
<>
10+
{showErrorMessage ? <ErrorMessage /> : null}
11+
{showStartingInstallerFailed ? <StartingInstallerFailed /> : null}
12+
</>
13+
);
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import styled from 'styled-components';
2+
3+
import { Flex, LabelTiny } from '../../../../../../../../../../../../../lib/components';
4+
import { Colors } from '../../../../../../../../../../../../../lib/foundations';
5+
import { useTexts } from './hooks';
6+
7+
// TODO: If we add different variants we should actually use them
8+
// maybe add this as a generic component?
9+
const Indicator = styled.div<{ variant?: 'error' | 'warning' }>`
10+
min-width: 10px;
11+
min-height: 10px;
12+
border-radius: 50%;
13+
background-color: ${({ variant }) => (variant === 'error' ? Colors.red : Colors.yellow)};
14+
`;
15+
16+
export function ErrorMessage() {
17+
const texts = useTexts();
18+
19+
return (
20+
<Flex $gap="small" $alignItems="baseline" $flexDirection="row">
21+
<Indicator variant="error" />
22+
<Flex $flexDirection="column">
23+
{texts.map((text) => (
24+
<LabelTiny key={text}>{text}</LabelTiny>
25+
))}
26+
</Flex>
27+
</Flex>
28+
);
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { AppUpgradeError } from '../../../../../../../../../../../../../../../shared/daemon-rpc-types';
2+
import { messages } from '../../../../../../../../../../../../../../../shared/gettext';
3+
import { useAppUpgradeEvent } from '../../../../../../../../../../../hooks';
4+
import { useIsBlocked } from '../../../../../../../../../hooks';
5+
6+
export const useTexts = () => {
7+
const isBlocked = useIsBlocked();
8+
const appUpgradeEvent = useAppUpgradeEvent();
9+
10+
if (isBlocked) {
11+
return [
12+
// TRANSLATORS: Label displayed when an error occurred due to the connection being blocked
13+
messages.pgettext('download-update-view', 'Connection blocked.'),
14+
// TRANSLATORS: Complimentary label displayed when an error occurred due to the connection being blocked
15+
messages.pgettext('download-update-view', 'Try changing server or other settings.'),
16+
];
17+
}
18+
19+
if (appUpgradeEvent?.type === 'APP_UPGRADE_EVENT_ERROR') {
20+
switch (appUpgradeEvent.error) {
21+
case AppUpgradeError.downloadFailed:
22+
return [
23+
// TRANSLATORS: Label displayed when an error occurred due to the download failing
24+
messages.pgettext('download-update-view', 'Download failed.'),
25+
// TRANSLATORS: Complimentary label displayed when an error occurred due to the download failing
26+
messages.pgettext(
27+
'download-update-view',
28+
'Check your connection and/or firewall then try again. If this problem persists, please contact support.',
29+
),
30+
];
31+
case AppUpgradeError.startInstallerFailed:
32+
return [
33+
// TRANSLATORS: Label displayed when an error occurred due to the installer failing to start
34+
messages.pgettext('download-update-view', 'Connection blocked.'),
35+
// TRANSLATORS: Complimentary displayed when an error occurred due to the installer failing to start
36+
messages.pgettext('download-update-view', 'Try changing server or other settings'),
37+
];
38+
case AppUpgradeError.verificationFailed:
39+
return [
40+
// TRANSLATORS: Label displayed when an error occurred due to the installer failed verification
41+
messages.pgettext(
42+
'download-update-view',
43+
'Verification failed. Try again. If this problem persists, please contact support.',
44+
),
45+
];
46+
default:
47+
break;
48+
}
49+
}
50+
51+
return [
52+
// TRANSLATORS: Label displayed when an unknown error occurred
53+
messages.pgettext('download-update-view', 'An unknown error occurred.'),
54+
// TRANSLATORS: Complimentary label displayed when an unknown error occurred
55+
messages.pgettext(
56+
'download-update-view',
57+
'Please try again. If this problem persists, please contact support.',
58+
),
59+
];
60+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './ErrorMessage';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { messages } from '../../../../../../../../../../../../../shared/gettext';
2+
import { Flex, Icon, LabelTiny } from '../../../../../../../../../../../../lib/components';
3+
import { Colors } from '../../../../../../../../../../../../lib/foundations';
4+
5+
export function StartingInstallerFailed() {
6+
return (
7+
<Flex $gap="small">
8+
<Icon icon="checkmark" color={Colors.green} size="small" />
9+
<LabelTiny>
10+
{
11+
// TRANSLATORS: Label displayed above a progress bar when the update is ready to be installed
12+
messages.pgettext('download-update-view', 'Verification successful! Ready to install.')
13+
}
14+
</LabelTiny>
15+
</Flex>
16+
);
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './ErrorMessage';
2+
export * from './StartingInstallerFailed';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './useShowErrorMessage';
2+
export * from './useShowStartingInstallerFailed';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { useShowStartingInstallerFailed } from './useShowStartingInstallerFailed';
2+
3+
export const useShowErrorMessage = () => {
4+
const showStartingInstallerFailed = useShowStartingInstallerFailed();
5+
6+
const showErrorMessage = !showStartingInstallerFailed;
7+
8+
return showErrorMessage;
9+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { AppUpgradeError } from '../../../../../../../../../../../../../shared/daemon-rpc-types';
2+
import { useGetHasAppUpgradeError } from '../../../../../../../../../hooks';
3+
4+
export const useShowStartingInstallerFailed = () => {
5+
const getHasAppUpgradeError = useGetHasAppUpgradeError();
6+
const hasErrorStartInstallerFailed = getHasAppUpgradeError(AppUpgradeError.startInstallerFailed);
7+
8+
const showStartingInstallerFailed = hasErrorStartInstallerFailed;
9+
10+
return showStartingInstallerFailed;
11+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './UpgradeError';
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
export * from './DownloadProgress';
22
export * from './DownloadStarted';
3-
export * from './ErrorMessage';
43
export * from './StartingInstaller';
4+
export * from './UpgradeError';
55
export * from './VerifyingInstaller';
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
import { useIsBlocked } from '../../../hooks';
1+
import { useHasUpgradeError, useIsBlocked } from '../../../hooks';
22

33
export const useShowDownloadProgress = () => {
4+
const hasUpgradeError = useHasUpgradeError();
45
const isBlocked = useIsBlocked();
56

6-
const showDownloadProgress = !isBlocked;
7+
const showDownloadProgress = !hasUpgradeError && !isBlocked;
78

89
return showDownloadProgress;
910
};

desktop/packages/mullvad-vpn/src/renderer/components/views/download-update/components/Footer/components/UpgradeButton/hooks/useDisabled.ts

+6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
import { useAppUpgradeEvent } from '../../../../../hooks';
2+
import { useIsBlocked } from '../../../hooks';
23

34
export const useDisabled = () => {
45
const appUpgradeEvent = useAppUpgradeEvent();
6+
const isBlocked = useIsBlocked();
7+
8+
if (isBlocked) {
9+
return true;
10+
}
511

612
switch (appUpgradeEvent?.type) {
713
case 'APP_UPGRADE_EVENT_DOWNLOAD_PROGRESS':
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,32 @@
11
import { AppUpgradeError } from '../../../../../../../../../shared/daemon-rpc-types';
22
import { messages } from '../../../../../../../../../shared/gettext';
3-
import { useAppUpgradeEvent } from '../../../../../hooks';
3+
import {
4+
useAppUpgradeEvent,
5+
useGetHasAppUpgradeError,
6+
useIsAppUpgradeDownloaded,
7+
} from '../../../../../hooks';
48

59
export const useText = () => {
6-
const event = useAppUpgradeEvent();
10+
const appUpgradeEvent = useAppUpgradeEvent();
11+
const isAppUpgradeDownloaded = useIsAppUpgradeDownloaded();
12+
const getHasAppUpgradeError = useGetHasAppUpgradeError();
713

8-
// TODO: Handle more cases when we should present 'Install Update' and
9-
// do it better/more concise than here.
10-
if (event?.type) {
11-
if (event.type === 'APP_UPGRADE_EVENT_ERROR') {
12-
if (event.error === AppUpgradeError.startInstallerFailed) {
13-
return messages.pgettext('download-update-view', 'Install update');
14-
}
15-
}
16-
17-
if (event.type === 'APP_UPGRADE_EVENT_ABORTED') {
18-
const upgradeDownloaded = false;
19-
if (upgradeDownloaded) {
20-
// TRANSLATORS: Button text to install an update
21-
return messages.pgettext('download-update-view', 'Install update');
22-
}
14+
if (isAppUpgradeDownloaded) {
15+
const appUpgradeEventAborted = appUpgradeEvent?.type === 'APP_UPGRADE_EVENT_ABORTED';
16+
const hasErrorStartInstallerFailed = getHasAppUpgradeError(
17+
AppUpgradeError.startInstallerFailed,
18+
);
19+
if (appUpgradeEventAborted || hasErrorStartInstallerFailed) {
20+
// TRANSLATORS: Button text to install an update
21+
return messages.pgettext('download-update-view', 'Install update');
2322
}
2423
}
2524

26-
switch (event?.type) {
27-
case 'APP_UPGRADE_EVENT_ABORTED':
28-
// TRANSLATORS: Button text to install an update
29-
return messages.pgettext('download-update-view', 'Install update');
30-
case 'APP_UPGRADE_EVENT_STARTING_INSTALLER':
31-
case 'APP_UPGRADE_EVENT_DOWNLOAD_PROGRESS':
32-
case 'APP_UPGRADE_EVENT_DOWNLOAD_STARTED':
33-
case 'APP_UPGRADE_EVENT_VERIFYING_INSTALLER':
34-
// TRANSLATORS: Button text to cancel the download of an update
35-
return messages.pgettext('download-update-view', 'Cancel');
36-
default:
37-
// TRANSLATORS: Button text to download and install an update
38-
return messages.pgettext('download-update-view', 'Download and install');
25+
if (appUpgradeEvent?.type === 'APP_UPGRADE_EVENT_ERROR') {
26+
// TRANSLATORS: Button text to retry download of an update
27+
return messages.pgettext('download-update-view', 'Retry download');
3928
}
29+
30+
// TRANSLATORS: Button text to download and install an update
31+
return messages.pgettext('download-update-view', 'Download and install');
4032
};

desktop/packages/mullvad-vpn/src/renderer/components/views/download-update/components/Footer/hooks/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
export * from './useHasUpgradeError';
12
export * from './useIsBlocked';
23
export * from './useShowCancelButton';
34
export * from './useShowDownloadDetails';
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { useAppUpgradeEvent } from '../../../hooks';
2+
3+
export const useHasUpgradeError = () => {
4+
const appUpgradeEvent = useAppUpgradeEvent();
5+
6+
const hasUpgradeError = appUpgradeEvent?.type === 'APP_UPGRADE_EVENT_ERROR';
7+
8+
return hasUpgradeError;
9+
};
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1+
import { useSelector } from '../../../../../../redux/store';
2+
13
export const useIsBlocked = () => {
2-
// TODO: Verify if lockdown mode is enabled and user is not connected.
3-
const isBlocked = false;
4+
const isBlocked = useSelector((state) => state.connection.isBlocked);
45

56
return isBlocked;
67
};
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,16 @@
1+
import { useAppUpgradeEvent } from '../../../hooks';
2+
13
export const useShowCancelButton = () => {
2-
const showCancelButton = false;
4+
const appUpgradeEvent = useAppUpgradeEvent();
5+
6+
switch (appUpgradeEvent?.type) {
7+
case 'APP_UPGRADE_EVENT_DOWNLOAD_PROGRESS':
8+
case 'APP_UPGRADE_EVENT_DOWNLOAD_STARTED':
9+
case 'APP_UPGRADE_EVENT_STARTING_INSTALLER':
10+
case 'APP_UPGRADE_EVENT_VERIFYING_INSTALLER':
11+
return true;
312

4-
return showCancelButton;
13+
default:
14+
return false;
15+
}
516
};
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
import { useAppUpgradeEvent } from '../../../hooks';
2+
13
export const useShowDownloadDetails = () => {
2-
const showDownloadDetails = false;
4+
const appUpgradeEvent = useAppUpgradeEvent();
5+
6+
const showDownloadDetails = appUpgradeEvent !== undefined;
37

48
return showDownloadDetails;
59
};
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1+
import { useAppUpgradeEvent } from '../../../hooks';
2+
13
export const useShowReportProblemButton = () => {
2-
const showReportProblemButton = false;
4+
const appUpgradeEvent = useAppUpgradeEvent();
5+
6+
switch (appUpgradeEvent?.type) {
7+
case 'APP_UPGRADE_EVENT_ERROR':
8+
case 'APP_UPGRADE_EVENT_DOWNLOAD_STARTED':
9+
return true;
310

4-
return showReportProblemButton;
11+
default:
12+
return false;
13+
}
514
};

0 commit comments

Comments
 (0)