diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2022-11-25 11:26:23 +0100 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2022-11-25 11:26:23 +0100 |
| commit | adf299a1be11c9c8443de2d88899b686d1c31c49 (patch) | |
| tree | 079e6413cc0486e5218fb5b2443c2382a7450a8c /gui | |
| parent | 8e313e1711c0f2d2d12bbcad20d3bba98acb6cdc (diff) | |
| download | mullvadvpn-adf299a1be11c9c8443de2d88899b686d1c31c49.tar.xz mullvadvpn-adf299a1be11c9c8443de2d88899b686d1c31c49.zip | |
Add custom location item if custom location is selected
Diffstat (limited to 'gui')
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; } |
