summaryrefslogtreecommitdiffhomepage
path: root/gui/src
diff options
context:
space:
mode:
authorOskar <oskar@mullvad.net>2024-10-18 16:29:56 +0200
committerOskar <oskar@mullvad.net>2024-10-22 14:27:04 +0200
commit06f2c13285084ddf7ad9e904efd554d4569adc3e (patch)
tree02b7391297ca416eff7b788e7e30530647477cfa /gui/src
parentd339daefa6784a1e734ab20bb4a7db9fc8482ec5 (diff)
downloadmullvadvpn-06f2c13285084ddf7ad9e904efd554d4569adc3e.tar.xz
mullvadvpn-06f2c13285084ddf7ad9e904efd554d4569adc3e.zip
Show message instead of entry list
Diffstat (limited to 'gui/src')
-rw-r--r--gui/src/renderer/components/select-location/SelectLocation.tsx175
-rw-r--r--gui/src/renderer/components/select-location/SelectLocationStyles.tsx22
2 files changed, 112 insertions, 85 deletions
diff --git a/gui/src/renderer/components/select-location/SelectLocation.tsx b/gui/src/renderer/components/select-location/SelectLocation.tsx
index 01297f5630..438fdc430d 100644
--- a/gui/src/renderer/components/select-location/SelectLocation.tsx
+++ b/gui/src/renderer/components/select-location/SelectLocation.tsx
@@ -1,7 +1,7 @@
import { useCallback, useState } from 'react';
import { sprintf } from 'sprintf-js';
-import { colors } from '../../../config.json';
+import { colors, strings } from '../../../config.json';
import { Ownership } from '../../../shared/daemon-rpc-types';
import { messages } from '../../../shared/gettext';
import { useRelaySettingsUpdater } from '../../lib/constraint-updater';
@@ -39,14 +39,14 @@ import { useSelectLocationContext } from './SelectLocationContainer';
import {
StyledClearFilterButton,
StyledContent,
+ StyledDaitaSettingsButton,
StyledFilter,
StyledFilterRow,
- StyledHeaderSubTitle,
StyledNavigationBarAttachment,
- StyledNoResult,
- StyledNoResultText,
StyledScopeBar,
StyledSearchBar,
+ StyledSelectionUnavailable,
+ StyledSelectionUnavailableText,
} from './SelectLocationStyles';
import { SpacePreAllocationView } from './SpacePreAllocationView';
import {
@@ -163,81 +163,69 @@ export default function SelectLocation() {
</ScopeBarItem>
<ScopeBarItem>{messages.pgettext('select-location-view', 'Exit')}</ScopeBarItem>
</StyledScopeBar>
-
- {tunnelProtocol === 'openvpn' ? (
- <StyledHeaderSubTitle>
- {messages.pgettext(
- 'select-location-view',
- 'While connected, your traffic will be routed through two secure locations, the entry point (a bridge server) and the exit point (a VPN server).',
- )}
- </StyledHeaderSubTitle>
- ) : (
- <StyledHeaderSubTitle>
- {messages.pgettext(
- 'select-location-view',
- 'While connected, your traffic will be routed through two secure locations, the entry point and the exit point (needs to be two different VPN servers).',
- )}
- </StyledHeaderSubTitle>
- )}
</>
)}
- {showFilters && (
- <StyledFilterRow>
- {messages.pgettext('select-location-view', 'Filtered:')}
+ {locationType === LocationType.entry && daita && !directOnly ? null : (
+ <>
+ {showFilters && (
+ <StyledFilterRow>
+ {messages.pgettext('select-location-view', 'Filtered:')}
- {showOwnershipFilter && (
- <StyledFilter>
- {ownershipFilterLabel(ownership)}
- <StyledClearFilterButton
- aria-label={messages.gettext('Clear')}
- onClick={onClearOwnership}>
- <ImageView
- height={16}
- width={16}
- source="icon-close"
- tintColor={colors.white60}
- tintHoverColor={colors.white80}
- />
- </StyledClearFilterButton>
- </StyledFilter>
- )}
+ {showOwnershipFilter && (
+ <StyledFilter>
+ {ownershipFilterLabel(ownership)}
+ <StyledClearFilterButton
+ aria-label={messages.gettext('Clear')}
+ onClick={onClearOwnership}>
+ <ImageView
+ height={16}
+ width={16}
+ source="icon-close"
+ tintColor={colors.white60}
+ tintHoverColor={colors.white80}
+ />
+ </StyledClearFilterButton>
+ </StyledFilter>
+ )}
- {showProvidersFilter && (
- <StyledFilter>
- {sprintf(
- messages.pgettext(
- 'select-location-view',
- 'Providers: %(numberOfProviders)d',
- ),
- { numberOfProviders: filteredProviders.length },
+ {showProvidersFilter && (
+ <StyledFilter>
+ {sprintf(
+ messages.pgettext(
+ 'select-location-view',
+ 'Providers: %(numberOfProviders)d',
+ ),
+ { numberOfProviders: filteredProviders.length },
+ )}
+ <StyledClearFilterButton
+ aria-label={messages.gettext('Clear')}
+ onClick={onClearProviders}>
+ <ImageView
+ height={16}
+ width={16}
+ source="icon-close"
+ tintColor={colors.white60}
+ tintHoverColor={colors.white80}
+ />
+ </StyledClearFilterButton>
+ </StyledFilter>
)}
- <StyledClearFilterButton
- aria-label={messages.gettext('Clear')}
- onClick={onClearProviders}>
- <ImageView
- height={16}
- width={16}
- source="icon-close"
- tintColor={colors.white60}
- tintHoverColor={colors.white80}
- />
- </StyledClearFilterButton>
- </StyledFilter>
- )}
- {showDaitaFilter && (
- <StyledFilter>
- {sprintf(
- messages.pgettext('select-location-view', 'Setting: %(settingName)s'),
- { settingName: 'DAITA' },
+ {showDaitaFilter && (
+ <StyledFilter>
+ {sprintf(
+ messages.pgettext('select-location-view', 'Setting: %(settingName)s'),
+ { settingName: 'DAITA' },
+ )}
+ </StyledFilter>
)}
- </StyledFilter>
+ </StyledFilterRow>
)}
- </StyledFilterRow>
- )}
- <StyledSearchBar searchTerm={searchValue} onSearch={updateSearchTerm} />
+ <StyledSearchBar searchTerm={searchValue} onSearch={updateSearchTerm} />
+ </>
+ )}
</StyledNavigationBarAttachment>
<NavigationScrollbars ref={scrollViewRef}>
@@ -273,6 +261,9 @@ function SelectLocationContent() {
const [onSelectEntryRelay, onSelectEntrySpecial] = useOnSelectEntryLocation();
const [onSelectBridgeRelay, onSelectBridgeSpecial] = useOnSelectBridgeLocation();
+ const daita = useSelector((state) => state.settings.wireguard.daita?.enabled ?? false);
+ const directOnly = useSelector((state) => state.settings.wireguard.daita?.directOnly ?? false);
+
const relaySettings = useNormalRelaySettings();
const bridgeSettings = useSelector((state) => state.settings.bridgeSettings);
@@ -311,6 +302,10 @@ function SelectLocationContent() {
</>
);
} else if (relaySettings?.tunnelProtocol !== 'openvpn') {
+ if (daita && !directOnly) {
+ return <DisabledEntrySelection />;
+ }
+
return (
<>
<CustomLists selectedElementRef={selectedLocationRef} onSelect={onSelectEntryRelay} />
@@ -409,15 +404,47 @@ function NoSearchResult(props: NoSearchResultProps) {
}
return (
- <StyledNoResult>
- <StyledNoResultText>
+ <StyledSelectionUnavailable>
+ <StyledSelectionUnavailableText>
{formatHtml(
sprintf(messages.gettext('No result for <b>%(searchTerm)s</b>.'), {
searchTerm,
}),
)}
- </StyledNoResultText>
- <StyledNoResultText>{messages.gettext('Try a different search.')}</StyledNoResultText>
- </StyledNoResult>
+ </StyledSelectionUnavailableText>
+ <StyledSelectionUnavailableText>
+ {messages.gettext('Try a different search.')}
+ </StyledSelectionUnavailableText>
+ </StyledSelectionUnavailable>
+ );
+}
+
+function DisabledEntrySelection() {
+ const { push } = useHistory();
+
+ const multihop = messages.pgettext('settings-view', 'Multihop');
+ const directOnly = messages.gettext('Direct only');
+
+ const navigateToDaitaSettings = useCallback(() => {
+ push(RoutePath.daitaSettings);
+ }, [push]);
+
+ return (
+ <StyledSelectionUnavailable>
+ <StyledSelectionUnavailableText>
+ {sprintf(
+ messages.pgettext(
+ 'select-location-view',
+ '%(daita)s overrides %(multihop)s. To use %(multihop)s, please enable “%(directOnly)s” or disable %(daita)s in the %(daita)s settings.',
+ ),
+ { daita: strings.daita, multihop, directOnly },
+ )}
+ </StyledSelectionUnavailableText>
+ <StyledDaitaSettingsButton onClick={navigateToDaitaSettings}>
+ {sprintf(messages.pgettext('select-location-view', 'Go to %(daita)s settings'), {
+ daita: strings.daita,
+ })}
+ </StyledDaitaSettingsButton>
+ </StyledSelectionUnavailable>
);
}
diff --git a/gui/src/renderer/components/select-location/SelectLocationStyles.tsx b/gui/src/renderer/components/select-location/SelectLocationStyles.tsx
index fd401c8e8c..ff83a6fc8d 100644
--- a/gui/src/renderer/components/select-location/SelectLocationStyles.tsx
+++ b/gui/src/renderer/components/select-location/SelectLocationStyles.tsx
@@ -4,7 +4,7 @@ import { colors } from '../../../config.json';
import * as Cell from '../cell';
import { normalText, tinyText } from '../common-styles';
import SearchBar from '../SearchBar';
-import { HeaderSubTitle } from '../SettingsHeader';
+import { SmallButton } from '../SmallButton';
import { ScopeBar } from './ScopeBar';
export const StyledContent = styled.div({
@@ -15,17 +15,17 @@ export const StyledContent = styled.div({
});
export const StyledScopeBar = styled(ScopeBar)({
- marginBottom: '14px',
+ marginBottom: '16px',
});
export const StyledNavigationBarAttachment = styled.div({
- padding: '0 16px 14px',
+ padding: '0 16px 16px',
});
export const StyledFilterRow = styled.div({
...tinyText,
color: colors.white,
- margin: '0 6px 14px',
+ margin: '0 6px 16px',
});
export const StyledFilter = styled.div({
@@ -48,26 +48,26 @@ export const StyledClearFilterButton = styled.div({
backgroundColor: 'transparent',
});
-export const StyledHeaderSubTitle = styled(HeaderSubTitle)({
- display: 'block',
- margin: '0 6px 14px',
-});
-
export const StyledSearchBar = styled(SearchBar)({
margin: '0 6px',
});
-export const StyledNoResult = styled(Cell.CellFooter)({
+export const StyledSelectionUnavailable = styled(Cell.CellFooter)({
display: 'flex',
flexDirection: 'column',
paddingTop: 0,
marginTop: 0,
});
-export const StyledNoResultText = styled(Cell.CellFooterText)({
+export const StyledSelectionUnavailableText = styled(Cell.CellFooterText)({
textAlign: 'center',
});
export const StyledAllLocationsTitle = styled(Cell.Label)(normalText, {
fontWeight: 'normal',
});
+
+export const StyledDaitaSettingsButton = styled(SmallButton)({
+ marginLeft: 0,
+ marginTop: '24px',
+});