Skip to content

Commit bda3910

Browse files
committed
Fix search issues with custom list search
1 parent db547ed commit bda3910

File tree

14 files changed

+145
-85
lines changed

14 files changed

+145
-85
lines changed

desktop/packages/mullvad-vpn/src/renderer/components/views/select-location/SelectLocationViewContext.tsx

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import React from 'react';
22

33
import {
4-
useCustomListLocations,
5-
useFilteredCountryLocations,
4+
useFilterCountryLocations,
5+
useMapCustomListsToLocations,
6+
useMapReduxCountriesToCountryLocations,
67
useSearchCountryLocations,
8+
useSearchCustomListLocations,
79
useSelectedLocation,
810
} from '../../../features/locations/hooks';
911
import { LocationType } from '../../../features/locations/types';
@@ -17,9 +19,8 @@ type SelectLocationViewContextProps = Omit<SelectLocationViewProviderProps, 'chi
1719
setLocationType: (locationType: LocationType) => void;
1820
searchTerm: string;
1921
setSearchTerm: (value: string) => void;
20-
filteredLocations: ReturnType<typeof useFilteredCountryLocations>;
21-
searchedLocations: ReturnType<typeof useSearchCountryLocations>;
22-
customListLocations: ReturnType<typeof useCustomListLocations>;
22+
countryLocations: ReturnType<typeof useSearchCountryLocations>;
23+
customListLocations: ReturnType<typeof useSearchCustomListLocations>;
2324
};
2425

2526
const SelectLocationViewContext = React.createContext<SelectLocationViewContextProps | undefined>(
@@ -44,16 +45,23 @@ export function SelectLocationViewProvider({ children }: SelectLocationViewProvi
4445
const [searchTerm, setSearchTerm] = React.useState('');
4546
const relaySettings = useNormalRelaySettings();
4647
const selectedLocation = useSelectedLocation(locationTypeSelector);
47-
const filteredLocations = useFilteredCountryLocations(locationTypeSelector);
48-
const searchedLocations = useSearchCountryLocations(filteredLocations, searchTerm);
4948

50-
const activeSearch = searchTerm.length > 0;
49+
const filteredCountries = useFilterCountryLocations(locationTypeSelector);
50+
const filteredCountryLocations = useMapReduxCountriesToCountryLocations(
51+
locationTypeSelector,
52+
filteredCountries,
53+
);
54+
const searchedCountryLocations = useSearchCountryLocations(filteredCountryLocations, searchTerm);
5155

52-
const customListLocations = useCustomListLocations({
53-
locations: activeSearch ? searchedLocations : filteredLocations,
56+
const filteredCustomListLocations = useMapCustomListsToLocations(
57+
filteredCountryLocations,
58+
searchTerm,
5459
selectedLocation,
60+
);
61+
const searchedCustomListLocations = useSearchCustomListLocations(
62+
filteredCustomListLocations,
5563
searchTerm,
56-
});
64+
);
5765

5866
const locationType = React.useMemo(() => {
5967
const allowEntryLocations = relaySettings?.wireguard.useMultihop;
@@ -70,16 +78,14 @@ export function SelectLocationViewProvider({ children }: SelectLocationViewProvi
7078
setLocationType: setSelectLocationView,
7179
searchTerm,
7280
setSearchTerm,
73-
filteredLocations,
74-
searchedLocations,
75-
customListLocations,
81+
countryLocations: searchedCountryLocations,
82+
customListLocations: searchedCustomListLocations,
7683
}),
7784
[
78-
customListLocations,
79-
filteredLocations,
85+
searchedCustomListLocations,
86+
searchedCountryLocations,
8087
locationType,
8188
searchTerm,
82-
searchedLocations,
8389
setSearchTerm,
8490
setSelectLocationView,
8591
],

desktop/packages/mullvad-vpn/src/renderer/components/views/select-location/components/country-locations/CountryLocations.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { CountryLocation } from '../country-location';
99
import { useRelayCount } from './hooks';
1010

1111
export function CountryLocations() {
12-
const { searchedLocations } = useSelectLocationViewContext();
12+
const { countryLocations } = useSelectLocationViewContext();
1313
const { visibleRelays, totalRelays } = useRelayCount();
1414

1515
const showFilterText = visibleRelays !== totalRelays;
@@ -41,7 +41,7 @@ export function CountryLocations() {
4141
)}
4242
</SectionTitle>
4343
<FlexColumn>
44-
{searchedLocations.map((location) => {
44+
{countryLocations.map((location) => {
4545
const { key } = getLocationListItemMapProps(location, undefined);
4646
return <CountryLocation key={key} location={location} />;
4747
})}

desktop/packages/mullvad-vpn/src/renderer/components/views/select-location/components/country-locations/hooks/use-relay-count.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import { useRelayLocations } from '../../../../../../features/locations/hooks';
22
import { useSelectLocationViewContext } from '../../../SelectLocationViewContext';
33

44
export function useRelayCount() {
5-
const { searchedLocations } = useSelectLocationViewContext();
5+
const { countryLocations } = useSelectLocationViewContext();
66
const { relayLocations } = useRelayLocations();
77

8-
const visibleRelays = searchedLocations.reduce(
8+
const visibleRelays = countryLocations.reduce(
99
(countryAcc, country) =>
1010
countryAcc + country.cities.reduce((cityAcc, city) => cityAcc + city.relays.length, 0),
1111
0,
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { useSelectLocationViewContext } from '../../../SelectLocationViewContext';
22

33
export function useHasSearchedLocations() {
4-
const { searchedLocations } = useSelectLocationViewContext();
4+
const { countryLocations } = useSelectLocationViewContext();
55

6-
const hasSearchedLocations = searchedLocations.length > 0;
6+
const hasSearchedLocations = countryLocations.length > 0;
77

88
return hasSearchedLocations;
99
}

desktop/packages/mullvad-vpn/src/renderer/features/locations/hooks/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export * from './use-relay-locations';
1111
export * from './use-selected-location';
1212
export * from './use-active-filters';
1313
export * from './use-search-country-locations';
14-
export * from './use-filtered-country-locations';
14+
export * from './use-filter-country-locations';
1515
export * from './use-map-redux-countries-to-country-locations';
16-
export * from './use-custom-list-locations';
16+
export * from './use-map-custom-lists-to-locations';
17+
export * from './use-search-custom-list-locations';

desktop/packages/mullvad-vpn/src/renderer/features/locations/hooks/use-filtered-country-locations.ts renamed to desktop/packages/mullvad-vpn/src/renderer/features/locations/hooks/use-filter-country-locations.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ import { useIpVersion } from '../../tunnel/hooks';
66
import { type LocationType } from '../types';
77
import { filterLocations } from '../utils';
88
import { useOwnership, useProviders } from '.';
9-
import { useMapReduxCountriesToCountryLocations } from './use-map-redux-countries-to-country-locations';
109

11-
export function useFilteredCountryLocations(locationType: LocationType) {
10+
export function useFilterCountryLocations(locationType: LocationType) {
1211
const locations = useSelector((state) => state.settings.relayLocations);
1312
const { activeOwnership } = useOwnership();
1413
const { activeProviders } = useProviders();
@@ -18,7 +17,7 @@ export function useFilteredCountryLocations(locationType: LocationType) {
1817
const { multihop } = useMultihop();
1918
const { ipVersion } = useIpVersion();
2019

21-
const filteredRelayLocations = filterLocations({
20+
return filterLocations({
2221
locations,
2322
ownership: activeOwnership,
2423
providers: activeProviders,
@@ -29,6 +28,4 @@ export function useFilteredCountryLocations(locationType: LocationType) {
2928
obfuscation,
3029
ipVersion,
3130
});
32-
33-
return useMapReduxCountriesToCountryLocations(filteredRelayLocations, locationType);
3431
}

desktop/packages/mullvad-vpn/src/renderer/features/locations/hooks/use-custom-list-locations.ts renamed to desktop/packages/mullvad-vpn/src/renderer/features/locations/hooks/use-map-custom-lists-to-locations.ts

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import React from 'react';
2-
31
import type { RelayLocation } from '../../../../shared/daemon-rpc-types';
42
import { useCustomLists } from '../../custom-lists/hooks';
53
import {
@@ -15,21 +13,16 @@ import {
1513
searchMatchesLocation,
1614
} from '../utils';
1715

18-
export function useCustomListLocations({
19-
locations,
20-
selectedLocation,
21-
searchTerm,
22-
}: {
23-
locations: CountryLocation[];
24-
selectedLocation?: RelayLocation;
25-
searchTerm: string;
26-
}): CustomListLocation[] {
16+
export function useMapCustomListsToLocations(
17+
countryLocations: CountryLocation[],
18+
searchTerm: string,
19+
selectedLocation?: RelayLocation,
20+
): CustomListLocation[] {
2721
const { customLists } = useCustomLists();
2822

29-
const locationMap = React.useMemo(() => createLocationMap(locations), [locations]);
30-
3123
const customListLocations: CustomListLocation[] = customLists.map((customList) => {
3224
const customListMatchesSearch = searchMatchesLocation(customList.name, searchTerm);
25+
const locationMap = createLocationMap(countryLocations);
3326

3427
// Get all ids of locations that are in the custom list
3528
const customListLocationIds = customList.locations.flatMap((location) => {
@@ -43,6 +36,7 @@ export function useCustomListLocations({
4336
return location.country;
4437
});
4538

39+
// Pick the locations from the map that are in the custom list, and add custom list details to them
4640
const customListGeographicalLocations: GeographicalLocation[] = [];
4741
for (const id of customListLocationIds) {
4842
const location = locationMap.get(id);

desktop/packages/mullvad-vpn/src/renderer/features/locations/hooks/use-map-redux-countries-to-country-locations.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ import { useDisabledLocation } from './use-disabled-location';
88
import { useSelectedLocation } from './use-selected-location';
99

1010
export function useMapReduxCountriesToCountryLocations(
11-
relayList: Array<IRelayLocationCountryRedux>,
1211
locationType: LocationType,
12+
relayList: Array<IRelayLocationCountryRedux>,
1313
): CountryLocation[] {
1414
const locale = useSelector((state) => state.userInterface.locale);
1515
const selectedLocation = useSelectedLocation(locationType);
Lines changed: 11 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,19 @@
11
import React from 'react';
22

3-
import type { CityLocation, CountryLocation, RelayLocation } from '../types';
4-
import { searchMatchesLocation } from '../utils';
3+
import type { CountryLocation } from '../types';
4+
import { searchCountryAndCities } from '../utils';
55

66
export function useSearchCountryLocations(
7-
locations: CountryLocation[],
7+
countryLocations: CountryLocation[],
88
searchTerm: string,
99
): CountryLocation[] {
10-
return React.useMemo(() => formatCountriesResult(locations, searchTerm), [locations, searchTerm]);
11-
}
12-
13-
export function formatCountriesResult(countries: CountryLocation[], searchTerm: string) {
14-
if (!searchTerm) {
15-
return countries;
16-
}
17-
return countries
18-
.map((country) => {
19-
const citiesResult = formatCitiesResult(country, searchTerm);
20-
if (citiesResult.length > 0) {
21-
return { ...country, expanded: true, cities: citiesResult };
22-
}
23-
if (searchMatchesLocation(country.label, searchTerm)) {
24-
return country;
25-
}
26-
return undefined;
27-
})
28-
.filter((country) => country !== undefined);
29-
}
30-
31-
export function formatCitiesResult(country: CountryLocation, searchTerm: string): CityLocation[] {
32-
return country.cities
33-
.map((city) => {
34-
const relaysResult = formatRelaysResult(city, searchTerm);
35-
if (relaysResult.length > 0) {
36-
return { ...city, expanded: true, relays: relaysResult };
37-
}
38-
if (searchMatchesLocation(city.label, searchTerm)) {
39-
return city;
40-
}
41-
42-
return undefined;
43-
})
44-
.filter((city) => city !== undefined);
45-
}
10+
return React.useMemo(() => {
11+
if (!searchTerm) {
12+
return countryLocations;
13+
}
4614

47-
export function formatRelaysResult(city: CityLocation, searchTerm: string): RelayLocation[] {
48-
return city.relays.filter((relay) => searchMatchesLocation(relay.label, searchTerm));
15+
return countryLocations
16+
.map((country) => searchCountryAndCities(country, searchTerm))
17+
.filter((country) => country !== undefined);
18+
}, [countryLocations, searchTerm]);
4919
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from 'react';
2+
3+
import type { CustomListLocation } from '../types';
4+
import { searchCustomListAndLocations } from '../utils';
5+
6+
export function useSearchCustomListLocations(
7+
customListLocations: CustomListLocation[],
8+
searchTerm: string,
9+
): CustomListLocation[] {
10+
return React.useMemo(() => {
11+
if (!searchTerm) {
12+
return customListLocations;
13+
}
14+
15+
return customListLocations
16+
.map((customList) => searchCustomListAndLocations(customList, searchTerm))
17+
.filter((customList) => customList !== undefined);
18+
}, [customListLocations, searchTerm]);
19+
}

0 commit comments

Comments
 (0)