summaryrefslogtreecommitdiffhomepage
path: root/gui/src/renderer/lib
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2023-10-09 10:36:33 +0200
committerOskar Nyberg <oskar@mullvad.net>2023-10-09 10:36:33 +0200
commit817866f1843b6b9366153fdfa31288af9e80c26b (patch)
tree7e921f6b1673954c80c67a9e54765d36d67560ec /gui/src/renderer/lib
parentc1f9e782da8d8cd5731fe43017f056b184f126c9 (diff)
parent9551fd134a993636ffedcbe42d8d2b1407e93ddf (diff)
downloadmullvadvpn-817866f1843b6b9366153fdfa31288af9e80c26b.tar.xz
mullvadvpn-817866f1843b6b9366153fdfa31288af9e80c26b.zip
Merge branch 'custom-lists-gui-des-198'
Diffstat (limited to 'gui/src/renderer/lib')
-rw-r--r--gui/src/renderer/lib/filter-locations.ts87
1 files changed, 52 insertions, 35 deletions
diff --git a/gui/src/renderer/lib/filter-locations.ts b/gui/src/renderer/lib/filter-locations.ts
index e2a4c5d96d..63ca56cbf2 100644
--- a/gui/src/renderer/lib/filter-locations.ts
+++ b/gui/src/renderer/lib/filter-locations.ts
@@ -1,9 +1,14 @@
import { Ownership, RelayEndpointType, RelayLocation } from '../../shared/daemon-rpc-types';
import { relayLocations } from '../../shared/gettext';
-import { SpecialLocation } from '../components/select-location/select-location-types';
+import {
+ RelayLocationCityWithVisibility,
+ RelayLocationCountryWithVisibility,
+ RelayLocationRelayWithVisibility,
+ SpecialLocation,
+} from '../components/select-location/select-location-types';
import {
IRelayLocationCityRedux,
- IRelayLocationRedux,
+ IRelayLocationCountryRedux,
IRelayLocationRelayRedux,
NormalRelaySettingsRedux,
} from '../redux/settings/reducers';
@@ -15,18 +20,18 @@ export enum EndpointType {
}
export function filterLocationsByEndPointType(
- locations: IRelayLocationRedux[],
+ locations: IRelayLocationCountryRedux[],
endpointType: EndpointType,
relaySettings?: NormalRelaySettingsRedux,
-): IRelayLocationRedux[] {
+): IRelayLocationCountryRedux[] {
return filterLocationsImpl(locations, getTunnelProtocolFilter(endpointType, relaySettings));
}
export function filterLocations(
- locations: IRelayLocationRedux[],
+ locations: IRelayLocationCountryRedux[],
ownership?: Ownership,
providers?: Array<string>,
-): IRelayLocationRedux[] {
+): IRelayLocationCountryRedux[] {
const filters = [getOwnershipFilter(ownership), getProviderFilter(providers)];
return filters.some((filter) => filter !== undefined)
@@ -74,9 +79,9 @@ function getProviderFilter(
}
function filterLocationsImpl(
- locations: Array<IRelayLocationRedux>,
+ locations: Array<IRelayLocationCountryRedux>,
filter: (relay: IRelayLocationRelayRedux) => boolean,
-): Array<IRelayLocationRedux> {
+): Array<IRelayLocationCountryRedux> {
return locations
.map((country) => ({
...country,
@@ -88,39 +93,50 @@ function filterLocationsImpl(
}
export function searchForLocations(
- countries: Array<IRelayLocationRedux>,
+ countries: Array<IRelayLocationCountryRedux>,
searchTerm: string,
-): Array<IRelayLocationRedux> {
- if (searchTerm === '') {
- return countries;
- }
-
- return countries.reduce((countries, country) => {
- const matchingCities = searchCities(country.cities, searchTerm);
- const expanded = matchingCities.length > 0;
+): Array<RelayLocationCountryWithVisibility> {
+ return countries.map((country) => {
const match =
- search(searchTerm, country.code) || search(searchTerm, relayLocations.gettext(country.name));
- const resultingCities = match ? country.cities : matchingCities;
- return expanded || match ? [...countries, { ...country, cities: resultingCities }] : countries;
- }, [] as Array<IRelayLocationRedux>);
+ searchTerm === '' ||
+ searchMatch(searchTerm, country.code) ||
+ searchMatch(searchTerm, relayLocations.gettext(country.name));
+ const cities = searchCities(country.cities, searchTerm, match);
+ const expanded = cities.some((city) => city.visible);
+ return { ...country, cities: cities, visible: expanded || match };
+ });
}
function searchCities(
cities: Array<IRelayLocationCityRedux>,
searchTerm: string,
-): Array<IRelayLocationCityRedux> {
- return cities.reduce((cities, city) => {
- const matchingRelays = city.relays.filter((relay) => search(searchTerm, relay.hostname));
- const expanded = matchingRelays.length > 0;
+ countryMatch: boolean,
+): Array<RelayLocationCityWithVisibility> {
+ return cities.map((city) => {
const match =
- search(searchTerm, city.code) || search(searchTerm, relayLocations.gettext(city.name));
- const resultingRelays = match ? city.relays : matchingRelays;
- return expanded || match ? [...cities, { ...city, relays: resultingRelays }] : cities;
- }, [] as Array<IRelayLocationCityRedux>);
+ searchTerm === '' ||
+ countryMatch ||
+ searchMatch(searchTerm, city.code) ||
+ searchMatch(searchTerm, relayLocations.gettext(city.name));
+ const relays = searchRelays(city.relays, searchTerm, match);
+ const expanded = match || relays.some((relay) => relay.visible);
+ return { ...city, relays: relays, visible: expanded };
+ });
+}
+
+function searchRelays(
+ relays: Array<IRelayLocationRelayRedux>,
+ searchTerm: string,
+ cityMatch: boolean,
+): Array<RelayLocationRelayWithVisibility> {
+ return relays.map((relay) => ({
+ ...relay,
+ visible: searchTerm === '' || cityMatch || searchMatch(searchTerm, relay.hostname),
+ }));
}
export function getLocationsExpandedBySearch(
- countries: Array<IRelayLocationRedux>,
+ countries: Array<IRelayLocationCountryRedux>,
searchTerm: string,
): Array<RelayLocation> {
return countries.reduce((locations, country) => {
@@ -130,7 +146,7 @@ export function getLocationsExpandedBySearch(
searchTerm,
);
const cityMatches = country.cities.some(
- (city) => search(searchTerm, city.code) || search(searchTerm, city.name),
+ (city) => searchMatch(searchTerm, city.code) || searchMatch(searchTerm, city.name),
);
const location = { country: country.code };
const expanded = cityMatches || cityLocations.length > 0;
@@ -144,13 +160,14 @@ function getCityLocationsExpandecBySearch(
searchTerm: string,
): Array<RelayLocation> {
return cities.reduce((locations, city) => {
- const expanded = city.relays.filter((relay) => search(searchTerm, relay.hostname)).length > 0;
- const location: RelayLocation = { city: [countryCode, city.code] };
+ const expanded =
+ city.relays.filter((relay) => searchMatch(searchTerm, relay.hostname)).length > 0;
+ const location: RelayLocation = { country: countryCode, city: city.code };
return expanded ? [...locations, location] : locations;
}, [] as Array<RelayLocation>);
}
-function search(searchTerm: string, value: string): boolean {
+export function searchMatch(searchTerm: string, value: string): boolean {
return value.toLowerCase().includes(searchTerm.toLowerCase());
}
@@ -158,5 +175,5 @@ export function filterSpecialLocations<T>(
searchTerm: string,
locations: Array<SpecialLocation<T>>,
): Array<SpecialLocation<T>> {
- return locations.filter((location) => search(searchTerm, location.label));
+ return locations.filter((location) => searchMatch(searchTerm, location.label));
}