summaryrefslogtreecommitdiffhomepage
path: root/gui/src
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2022-11-25 12:57:41 +0100
committerOskar Nyberg <oskar@mullvad.net>2022-11-25 12:57:41 +0100
commit29e5fadc291946de824ea36fd94a0db197f42af7 (patch)
tree2f1b8d921540a9736a96eac6ddba115624c04ac9 /gui/src
parentd5f216e2d99071958d9d635e9639971255ca61ef (diff)
downloadmullvadvpn-29e5fadc291946de824ea36fd94a0db197f42af7.tar.xz
mullvadvpn-29e5fadc291946de824ea36fd94a0db197f42af7.zip
Add filtering of special locations
Diffstat (limited to 'gui/src')
-rw-r--r--gui/src/renderer/components/select-location/CombinedLocationList.tsx (renamed from gui/src/renderer/components/select-location/LocationList.tsx)4
-rw-r--r--gui/src/renderer/components/select-location/SelectLocation.tsx91
-rw-r--r--gui/src/renderer/lib/filter-locations.ts8
3 files changed, 65 insertions, 38 deletions
diff --git a/gui/src/renderer/components/select-location/LocationList.tsx b/gui/src/renderer/components/select-location/CombinedLocationList.tsx
index 6901dcbb62..d2a13af845 100644
--- a/gui/src/renderer/components/select-location/LocationList.tsx
+++ b/gui/src/renderer/components/select-location/CombinedLocationList.tsx
@@ -11,7 +11,7 @@ import {
} from './select-location-types';
import SpecialLocationList from './SpecialLocationList';
-interface LocationListProps<T> {
+export interface CombinedLocationListProps<T> {
source: LocationList<T>;
selectedElementRef: React.Ref<HTMLDivElement>;
onSelect: (value: LocationSelection<T>) => void;
@@ -26,7 +26,7 @@ interface LocationListProps<T> {
}
// Renders the special locations and the regular locations as separate lists
-export default function CombinedLocationList<T>(props: LocationListProps<T>) {
+export default function CombinedLocationList<T>(props: CombinedLocationListProps<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 e90ba3ca5a..c26dacdd33 100644
--- a/gui/src/renderer/components/select-location/SelectLocation.tsx
+++ b/gui/src/renderer/components/select-location/SelectLocation.tsx
@@ -5,6 +5,7 @@ import { colors } from '../../../config.json';
import { Ownership } from '../../../shared/daemon-rpc-types';
import { messages } from '../../../shared/gettext';
import { useAppContext } from '../../context';
+import { filterSpecialLocations } from '../../lib/filter-locations';
import { useHistory } from '../../lib/history';
import { formatHtml } from '../../lib/html-formatter';
import { RoutePath } from '../../lib/routes';
@@ -20,7 +21,7 @@ import {
NavigationScrollbars,
TitleBarItem,
} from '../NavigationBar';
-import CombinedLocationList from './LocationList';
+import CombinedLocationList, { CombinedLocationListProps } from './CombinedLocationList';
import { useRelayListContext } from './RelayListContext';
import { ScopeBarItem } from './ScopeBar';
import { useScrollPositionContext } from './ScrollPositionContext';
@@ -258,29 +259,25 @@ function SelectLocationContent() {
const resetHeight = useCallback(() => spacePreAllocationViewRef.current?.reset(), []);
- if (searchTerm !== '' && relayList.length === 0) {
- return (
- <StyledNoResult>
- <StyledNoResultText>
- {formatHtml(
- sprintf(messages.gettext('No result for <b>%(searchTerm)s</b>.'), { searchTerm }),
- )}
- </StyledNoResultText>
- <StyledNoResultText>{messages.gettext('Try a different search.')}</StyledNoResultText>
- </StyledNoResult>
- );
- } else if (locationType === LocationType.exit) {
- const customItem: SpecialLocation<undefined> = {
- type: LocationSelectionType.special,
- label: messages.gettext('Custom'),
- value: undefined,
- selected: true,
- };
+ if (locationType === LocationType.exit) {
+ // Add "Custom" item if a custom relay is selected
+ const specialList: Array<SpecialLocation<undefined>> =
+ relaySettings === undefined
+ ? [
+ {
+ type: LocationSelectionType.special,
+ label: messages.gettext('Custom'),
+ value: undefined,
+ selected: true,
+ },
+ ]
+ : [];
+ const relayListWithSpecial = [...filterSpecialLocations(searchTerm, specialList), ...relayList];
return (
- <CombinedLocationList
+ <LocationList
key={locationType}
- source={relaySettings === undefined ? [customItem, ...relayList] : relayList}
+ source={relayListWithSpecial}
selectedElementRef={selectedLocationRef}
onSelect={onSelectExitLocation}
onExpand={expandLocation}
@@ -291,7 +288,7 @@ function SelectLocationContent() {
);
} else if (relaySettings?.tunnelProtocol !== 'openvpn') {
return (
- <CombinedLocationList
+ <LocationList
key={locationType}
source={relayList}
selectedElementRef={selectedLocationRef}
@@ -303,23 +300,26 @@ function SelectLocationContent() {
/>
);
} else {
- // Add the "Automatic" item to the list
- const automaticItem: SpecialLocation<SpecialBridgeLocationType> = {
- type: LocationSelectionType.special,
- label: messages.gettext('Automatic'),
- icon: SpecialLocationIcon.geoLocation,
- info: messages.pgettext(
- 'select-location-view',
- 'The app selects a random bridge server, but servers have a higher probability the closer they are to you.',
- ),
- value: SpecialBridgeLocationType.closestToExit,
- selected: bridgeSettings?.location === 'any',
- };
+ // Add the "Automatic" item
+ const specialList: Array<SpecialLocation<SpecialBridgeLocationType>> = [
+ {
+ type: LocationSelectionType.special,
+ label: messages.gettext('Automatic'),
+ icon: SpecialLocationIcon.geoLocation,
+ info: messages.pgettext(
+ 'select-location-view',
+ 'The app selects a random bridge server, but servers have a higher probability the closer they are to you.',
+ ),
+ value: SpecialBridgeLocationType.closestToExit,
+ selected: bridgeSettings?.location === 'any',
+ },
+ ];
+ const relayListWithSpecial = [...filterSpecialLocations(searchTerm, specialList), ...relayList];
return (
- <CombinedLocationList
+ <LocationList
key={locationType}
- source={[automaticItem, ...relayList]}
+ source={relayListWithSpecial}
selectedElementRef={selectedLocationRef}
onSelect={onSelectBridgeLocation}
onExpand={expandLocation}
@@ -330,3 +330,22 @@ function SelectLocationContent() {
);
}
}
+
+function LocationList<T>(props: CombinedLocationListProps<T>) {
+ const { searchTerm } = useSelectLocationContext();
+
+ if (searchTerm !== '' && props.source.length === 0) {
+ return (
+ <StyledNoResult>
+ <StyledNoResultText>
+ {formatHtml(
+ sprintf(messages.gettext('No result for <b>%(searchTerm)s</b>.'), { searchTerm }),
+ )}
+ </StyledNoResultText>
+ <StyledNoResultText>{messages.gettext('Try a different search.')}</StyledNoResultText>
+ </StyledNoResult>
+ );
+ } else {
+ return <CombinedLocationList {...props} />;
+ }
+}
diff --git a/gui/src/renderer/lib/filter-locations.ts b/gui/src/renderer/lib/filter-locations.ts
index 91f219b9e5..93d20f0c88 100644
--- a/gui/src/renderer/lib/filter-locations.ts
+++ b/gui/src/renderer/lib/filter-locations.ts
@@ -1,4 +1,5 @@
import { Ownership, RelayEndpointType, RelayLocation } from '../../shared/daemon-rpc-types';
+import { SpecialLocation } from '../components/select-location/select-location-types';
import {
IRelayLocationCityRedux,
IRelayLocationRedux,
@@ -149,3 +150,10 @@ function getCityLocationsExpandecBySearch(
function search(searchTerm: string, value: string): boolean {
return value.toLowerCase().includes(searchTerm.toLowerCase());
}
+
+export function filterSpecialLocations<T>(
+ searchTerm: string,
+ locations: Array<SpecialLocation<T>>,
+): Array<SpecialLocation<T>> {
+ return locations.filter((location) => search(searchTerm, location.label));
+}