summaryrefslogtreecommitdiffhomepage
path: root/gui/src
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2022-11-25 11:26:23 +0100
committerOskar Nyberg <oskar@mullvad.net>2022-11-25 11:26:23 +0100
commitadf299a1be11c9c8443de2d88899b686d1c31c49 (patch)
tree079e6413cc0486e5218fb5b2443c2382a7450a8c /gui/src
parent8e313e1711c0f2d2d12bbcad20d3bba98acb6cdc (diff)
downloadmullvadvpn-adf299a1be11c9c8443de2d88899b686d1c31c49.tar.xz
mullvadvpn-adf299a1be11c9c8443de2d88899b686d1c31c49.zip
Add custom location item if custom location is selected
Diffstat (limited to 'gui/src')
-rw-r--r--gui/src/renderer/components/select-location/LocationList.tsx2
-rw-r--r--gui/src/renderer/components/select-location/SelectLocation.tsx34
-rw-r--r--gui/src/renderer/components/select-location/SpecialLocationList.tsx29
-rw-r--r--gui/src/renderer/components/select-location/select-location-hooks.ts43
-rw-r--r--gui/src/renderer/components/select-location/select-location-types.ts6
5 files changed, 70 insertions, 44 deletions
diff --git a/gui/src/renderer/components/select-location/LocationList.tsx b/gui/src/renderer/components/select-location/LocationList.tsx
index 9db10ff519..6901dcbb62 100644
--- a/gui/src/renderer/components/select-location/LocationList.tsx
+++ b/gui/src/renderer/components/select-location/LocationList.tsx
@@ -26,7 +26,7 @@ interface LocationListProps<T> {
}
// Renders the special locations and the regular locations as separate lists
-export default function LocationsList<T>(props: LocationListProps<T>) {
+export default function CombinedLocationList<T>(props: LocationListProps<T>) {
const specialLocations = props.source.filter(isSpecialLocation);
const relayLocations = props.source.filter(isRelayLocation);
diff --git a/gui/src/renderer/components/select-location/SelectLocation.tsx b/gui/src/renderer/components/select-location/SelectLocation.tsx
index e129acc033..e90ba3ca5a 100644
--- a/gui/src/renderer/components/select-location/SelectLocation.tsx
+++ b/gui/src/renderer/components/select-location/SelectLocation.tsx
@@ -20,11 +20,15 @@ import {
NavigationScrollbars,
TitleBarItem,
} from '../NavigationBar';
-import LocationList from './LocationList';
+import CombinedLocationList from './LocationList';
import { useRelayListContext } from './RelayListContext';
import { ScopeBarItem } from './ScopeBar';
import { useScrollPositionContext } from './ScrollPositionContext';
-import { useOnSelectBridgeLocation, useOnSelectLocation } from './select-location-hooks';
+import {
+ useOnSelectBridgeLocation,
+ useOnSelectEntryLocation,
+ useOnSelectExitLocation,
+} from './select-location-hooks';
import {
LocationSelectionType,
LocationType,
@@ -245,7 +249,8 @@ function SelectLocationContent() {
const { locationType, searchTerm } = useSelectLocationContext();
const { selectedLocationRef, spacePreAllocationViewRef } = useScrollPositionContext();
const { relayList, expandLocation, collapseLocation, onBeforeExpand } = useRelayListContext();
- const onSelectLocation = useOnSelectLocation();
+ const onSelectExitLocation = useOnSelectExitLocation();
+ const onSelectEntryLocation = useOnSelectEntryLocation();
const onSelectBridgeLocation = useOnSelectBridgeLocation();
const relaySettings = useNormalRelaySettings();
@@ -265,12 +270,19 @@ function SelectLocationContent() {
</StyledNoResult>
);
} else if (locationType === LocationType.exit) {
+ const customItem: SpecialLocation<undefined> = {
+ type: LocationSelectionType.special,
+ label: messages.gettext('Custom'),
+ value: undefined,
+ selected: true,
+ };
+
return (
- <LocationList
+ <CombinedLocationList
key={locationType}
- source={relayList}
+ source={relaySettings === undefined ? [customItem, ...relayList] : relayList}
selectedElementRef={selectedLocationRef}
- onSelect={onSelectLocation}
+ onSelect={onSelectExitLocation}
onExpand={expandLocation}
onCollapse={collapseLocation}
onWillExpand={onBeforeExpand}
@@ -279,11 +291,11 @@ function SelectLocationContent() {
);
} else if (relaySettings?.tunnelProtocol !== 'openvpn') {
return (
- <LocationList
+ <CombinedLocationList
key={locationType}
source={relayList}
selectedElementRef={selectedLocationRef}
- onSelect={onSelectLocation}
+ onSelect={onSelectEntryLocation}
onExpand={expandLocation}
onCollapse={collapseLocation}
onWillExpand={onBeforeExpand}
@@ -302,14 +314,12 @@ function SelectLocationContent() {
),
value: SpecialBridgeLocationType.closestToExit,
selected: bridgeSettings?.location === 'any',
- disabled: false,
};
- const bridgeRelayList = [automaticItem, ...relayList];
return (
- <LocationList
+ <CombinedLocationList
key={locationType}
- source={bridgeRelayList}
+ source={[automaticItem, ...relayList]}
selectedElementRef={selectedLocationRef}
onSelect={onSelectBridgeLocation}
onExpand={expandLocation}
diff --git a/gui/src/renderer/components/select-location/SpecialLocationList.tsx b/gui/src/renderer/components/select-location/SpecialLocationList.tsx
index 98179a0c78..cbed2cf358 100644
--- a/gui/src/renderer/components/select-location/SpecialLocationList.tsx
+++ b/gui/src/renderer/components/select-location/SpecialLocationList.tsx
@@ -61,24 +61,29 @@ function SpecialLocationRow<T>(props: SpecialLocationRowProps<T>) {
}
}, [props.source.selected, props.onSelect, props.source.value]);
+ const icon = props.source.selected ? 'icon-tick' : props.source.icon ?? undefined;
const selectedRef = props.source.selected ? props.selectedElementRef : undefined;
return (
<StyledLocationRowContainerWithMargin ref={selectedRef}>
<StyledLocationRowButton onClick={onSelect} selected={props.source.selected}>
- <StyledSpecialLocationIcon
- source={props.source.selected ? 'icon-tick' : props.source.icon}
- tintColor={colors.white}
- height={22}
- width={22}
- />
+ {icon && (
+ <StyledSpecialLocationIcon
+ source={icon}
+ tintColor={colors.white}
+ height={22}
+ width={22}
+ />
+ )}
<StyledLocationRowLabel>{props.source.label}</StyledLocationRowLabel>
</StyledLocationRowButton>
- <StyledLocationRowIcon
- as={StyledSpecialLocationInfoButton}
- message={props.source.info}
- selected={props.source.selected}
- aria-label={messages.pgettext('accessibility', 'info')}
- />
+ {props.source.info && (
+ <StyledLocationRowIcon
+ as={StyledSpecialLocationInfoButton}
+ message={props.source.info}
+ selected={props.source.selected}
+ aria-label={messages.pgettext('accessibility', 'info')}
+ />
+ )}
</StyledLocationRowContainerWithMargin>
);
}
diff --git a/gui/src/renderer/components/select-location/select-location-hooks.ts b/gui/src/renderer/components/select-location/select-location-hooks.ts
index a0f407b790..a1d54b435d 100644
--- a/gui/src/renderer/components/select-location/select-location-hooks.ts
+++ b/gui/src/renderer/components/select-location/select-location-hooks.ts
@@ -16,23 +16,17 @@ import {
} from './select-location-types';
import { useSelectLocationContext } from './SelectLocationContainer';
-export function useOnSelectLocation() {
+export function useOnSelectExitLocation() {
+ const onSelectLocation = useOnSelectLocation();
const history = useHistory();
- const { updateRelaySettings, connectTunnel } = useAppContext();
- const { locationType, setLocationType } = useSelectLocationContext();
- const baseRelaySettings = useSelector((state) => state.settings.relaySettings);
+ const { connectTunnel } = useAppContext();
- const onSelectLocation = useCallback(async (relayUpdate: RelaySettingsUpdate) => {
- try {
- await updateRelaySettings(relayUpdate);
- } catch (e) {
- const error = e as Error;
- log.error(`Failed to select the exit location: ${error.message}`);
- }
- }, []);
+ return useCallback(
+ async (relayLocation: LocationSelection<undefined>) => {
+ if (relayLocation.value === undefined) {
+ throw new Error('relayLocation should never be undefiend');
+ }
- const onSelectExitLocation = useCallback(
- async (relayLocation: LocationSelection<never>) => {
history.dismiss();
const relayUpdate = RelaySettingsBuilder.normal()
.location.fromRaw(relayLocation.value)
@@ -42,16 +36,33 @@ export function useOnSelectLocation() {
},
[history],
);
+}
+
+export function useOnSelectEntryLocation() {
+ const onSelectLocation = useOnSelectLocation();
+ const { setLocationType } = useSelectLocationContext();
+ const baseRelaySettings = useSelector((state) => state.settings.relaySettings);
- const onSelectEntryLocation = useCallback(async (entryLocation: LocationSelection<never>) => {
+ return useCallback(async (entryLocation: LocationSelection<never>) => {
setLocationType(LocationType.exit);
const relayUpdate = createWireguardRelayUpdater(baseRelaySettings)
.tunnel.wireguard((wireguard) => wireguard.entryLocation.exact(entryLocation.value))
.build();
await onSelectLocation(relayUpdate);
}, []);
+}
- return locationType === LocationType.exit ? onSelectExitLocation : onSelectEntryLocation;
+function useOnSelectLocation() {
+ const { updateRelaySettings } = useAppContext();
+
+ return useCallback(async (relayUpdate: RelaySettingsUpdate) => {
+ try {
+ await updateRelaySettings(relayUpdate);
+ } catch (e) {
+ const error = e as Error;
+ log.error(`Failed to select the exit location: ${error.message}`);
+ }
+ }, []);
}
export function useOnSelectBridgeLocation() {
diff --git a/gui/src/renderer/components/select-location/select-location-types.ts b/gui/src/renderer/components/select-location/select-location-types.ts
index 3fbd2ef0c2..6d895deeec 100644
--- a/gui/src/renderer/components/select-location/select-location-types.ts
+++ b/gui/src/renderer/components/select-location/select-location-types.ts
@@ -33,10 +33,10 @@ export enum SpecialLocationIcon {
export interface SpecialLocation<T> {
type: LocationSelectionType.special;
label: string;
- icon: SpecialLocationIcon;
- info: string;
+ icon?: SpecialLocationIcon;
+ info?: string;
value: T;
- disabled: boolean;
+ disabled?: boolean;
selected: boolean;
}