summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorOskar Nyberg <oskar@mullvad.net>2022-11-22 09:56:12 +0100
committerOskar Nyberg <oskar@mullvad.net>2022-11-24 16:26:28 +0100
commit7cb83a297635c6f196b17d219e24f364eecd862f (patch)
treed23fb82abcf3f9d9000c6d360761882c7bb16749
parent9b9065063733cc27d14ed0ab55b56333a265c4c7 (diff)
downloadmullvadvpn-7cb83a297635c6f196b17d219e24f364eecd862f.tar.xz
mullvadvpn-7cb83a297635c6f196b17d219e24f364eecd862f.zip
Expand search results on first render after search
-rw-r--r--gui/src/renderer/components/select-location/RelayListContext.tsx67
-rw-r--r--gui/src/renderer/components/select-location/SelectLocation.tsx2
-rw-r--r--gui/src/renderer/lib/filter-locations.ts4
3 files changed, 53 insertions, 20 deletions
diff --git a/gui/src/renderer/components/select-location/RelayListContext.tsx b/gui/src/renderer/components/select-location/RelayListContext.tsx
index b599c0e2ed..954ddaff70 100644
--- a/gui/src/renderer/components/select-location/RelayListContext.tsx
+++ b/gui/src/renderer/components/select-location/RelayListContext.tsx
@@ -1,4 +1,4 @@
-import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';
+import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
import { compareRelayLocation, RelayLocation } from '../../../shared/daemon-rpc-types';
import {
@@ -39,6 +39,7 @@ interface RelayListContext {
expandedContentHeight: number,
invokedByUser: boolean,
) => void;
+ expandSearchResults: (searchTerm: string) => void;
}
type ExpandedLocations = Partial<Record<LocationType, Array<RelayLocation>>>;
@@ -64,12 +65,6 @@ export function RelayListContextProvider(props: RelayListContextProviderProps) {
const [expandedLocationsMap, setExpandedLocations] = useState<ExpandedLocations>(() =>
defaultExpandedLocations(relaySettings, bridgeSettings),
);
- const {
- expandedLocations,
- expandLocation,
- collapseLocation,
- onBeforeExpand,
- } = useExpandedLocations(expandedLocationsMap, setExpandedLocations);
// Filters the relays to only keep the ones of the desired endpoint type, e.g. "wireguard",
// "openvpn" or "bridge"
@@ -90,10 +85,26 @@ export function RelayListContextProvider(props: RelayListContextProviderProps) {
}, [relaySettings?.ownership, relaySettings?.providers, relayListForEndpointType]);
// Filters the relays based on the provided search term
+ const prevRelayListForSearch = useRef<Array<IRelayLocationRedux>>([]);
const relayListForSearch = useMemo(() => {
- return searchForLocations(relayListForFilters, searchTerm);
+ // It shouldn't search for just one letter
+ if (searchTerm.length === 1) {
+ return prevRelayListForSearch.current;
+ }
+
+ const relayList = searchForLocations(relayListForFilters, searchTerm);
+ prevRelayListForSearch.current = relayList;
+ return relayList;
}, [relayListForFilters, searchTerm]);
+ const {
+ expandedLocations,
+ expandLocation,
+ collapseLocation,
+ onBeforeExpand,
+ expandSearchResults,
+ } = useExpandedLocations(expandedLocationsMap, setExpandedLocations, relayListForFilters);
+
// Prepares all relays and combines the data needed for rendering them
const relayList = useRelayList(relayListForSearch, expandedLocations);
@@ -103,25 +114,21 @@ export function RelayListContextProvider(props: RelayListContextProviderProps) {
expandLocation,
collapseLocation,
onBeforeExpand,
+ expandSearchResults,
}),
- [relayList, expandLocation, collapseLocation, onBeforeExpand],
+ [relayList, expandLocation, collapseLocation, onBeforeExpand, expandSearchResults],
);
- // Calculate expanded locations when location change
- useEffect(() => {
- if (searchTerm === '') {
- setExpandedLocations(defaultExpandedLocations(relaySettings, bridgeSettings));
- }
- }, [searchTerm]);
-
+ // Expand locations when filters are changed
useEffect(() => {
- if (searchTerm !== '') {
+ // It shouldn't search for just one letter
+ if (searchTerm.length > 1) {
setExpandedLocations((expandedLocations) => ({
...expandedLocations,
[locationType]: getLocationsExpandedBySearch(relayListForFilters, searchTerm),
}));
}
- }, [relayListForFilters, searchTerm]);
+ }, [relayListForFilters]);
return <relayListContext.Provider value={value}>{props.children}</relayListContext.Provider>;
}
@@ -203,15 +210,18 @@ function useExpandedLocations(
setExpandedLocations: (
arg: ExpandedLocations | ((prev: ExpandedLocations) => ExpandedLocations),
) => void,
+ filteredLocations: Array<IRelayLocationRedux>,
) {
const { locationType } = useSelectLocationContext();
const { spacePreAllocationViewRef, scrollViewRef } = useScrollPositionContext();
+ const relaySettings = useNormalRelaySettings();
+ const bridgeSettings = useNormalBridgeSettings();
const expandLocation = useCallback(
(location: RelayLocation) => {
setExpandedLocations((expandedLocations) => ({
...expandedLocations,
- [locationType]: [...(expandedLocationsMap[locationType] ?? []), location],
+ [locationType]: [...(expandedLocations[locationType] ?? []), location],
}));
},
[locationType],
@@ -221,7 +231,7 @@ function useExpandedLocations(
(location: RelayLocation) => {
setExpandedLocations((expandedLocations) => ({
...expandedLocations,
- [locationType]: expandedLocationsMap[locationType]!.filter(
+ [locationType]: expandedLocations[locationType]!.filter(
(item) => !compareRelayLocation(location, item),
),
}));
@@ -229,6 +239,7 @@ function useExpandedLocations(
[locationType],
);
+ // Called before expansion to make room for expansion and to scroll to fit the element
const onBeforeExpand = useCallback(
(locationRect: DOMRect, expandedContentHeight: number, invokedByUser: boolean) => {
if (invokedByUser) {
@@ -240,11 +251,27 @@ function useExpandedLocations(
[],
);
+ // Expand search results when searching
+ const expandSearchResults = useCallback(
+ (searchTerm: string) => {
+ if (searchTerm === '') {
+ setExpandedLocations(defaultExpandedLocations(relaySettings, bridgeSettings));
+ } else if (searchTerm.length > 1) {
+ setExpandedLocations((expandedLocations) => ({
+ ...expandedLocations,
+ [locationType]: getLocationsExpandedBySearch(filteredLocations, searchTerm),
+ }));
+ }
+ },
+ [relaySettings, bridgeSettings, locationType, filteredLocations],
+ );
+
return {
expandedLocations: expandedLocationsMap[locationType],
expandLocation,
collapseLocation,
onBeforeExpand,
+ expandSearchResults,
};
}
diff --git a/gui/src/renderer/components/select-location/SelectLocation.tsx b/gui/src/renderer/components/select-location/SelectLocation.tsx
index 2c170724ed..1ec7417f35 100644
--- a/gui/src/renderer/components/select-location/SelectLocation.tsx
+++ b/gui/src/renderer/components/select-location/SelectLocation.tsx
@@ -55,6 +55,7 @@ export default function SelectLocation() {
spacePreAllocationViewRef,
} = useScrollPositionContext();
const { locationType, setLocationType, searchTerm, setSearchTerm } = useSelectLocationContext();
+ const { expandSearchResults } = useRelayListContext();
const relaySettings = useNormalRelaySettings();
const ownership = relaySettings?.ownership ?? Ownership.any;
@@ -90,6 +91,7 @@ export default function SelectLocation() {
const updateSearchTerm = useCallback(
(value: string) => {
resetScrollPositions();
+ expandSearchResults(value);
setSearchTerm(value);
},
[resetScrollPositions],
diff --git a/gui/src/renderer/lib/filter-locations.ts b/gui/src/renderer/lib/filter-locations.ts
index 5352df41bd..91f219b9e5 100644
--- a/gui/src/renderer/lib/filter-locations.ts
+++ b/gui/src/renderer/lib/filter-locations.ts
@@ -89,6 +89,10 @@ export function searchForLocations(
countries: Array<IRelayLocationRedux>,
searchTerm: string,
): Array<IRelayLocationRedux> {
+ if (searchTerm === '') {
+ return countries;
+ }
+
return countries.reduce((countries, country) => {
const matchingCities = searchCities(country.cities, searchTerm);
const expanded = matchingCities.length > 0;