summaryrefslogtreecommitdiffhomepage
path: root/gui
diff options
context:
space:
mode:
Diffstat (limited to 'gui')
-rw-r--r--gui/src/renderer/containers/SelectLocationPage.tsx217
1 files changed, 131 insertions, 86 deletions
diff --git a/gui/src/renderer/containers/SelectLocationPage.tsx b/gui/src/renderer/containers/SelectLocationPage.tsx
index 3ca4ca94ac..1c3f3ff32a 100644
--- a/gui/src/renderer/containers/SelectLocationPage.tsx
+++ b/gui/src/renderer/containers/SelectLocationPage.tsx
@@ -1,131 +1,176 @@
-import { connect } from 'react-redux';
+import { useCallback, useMemo } from 'react';
import BridgeSettingsBuilder from '../../shared/bridge-settings-builder';
import { LiftedConstraint, Ownership, RelayLocation } from '../../shared/daemon-rpc-types';
import log from '../../shared/logging';
import RelaySettingsBuilder from '../../shared/relay-settings-builder';
import SelectLocation from '../components/SelectLocation';
-import withAppContext, { IAppContext } from '../context';
+import { useAppContext } from '../context';
import { createWireguardRelayUpdater } from '../lib/constraint-updater';
import filterLocations from '../lib/filter-locations';
-import { IHistoryProps, withHistory } from '../lib/history';
+import { useHistory } from '../lib/history';
import { RoutePath } from '../lib/routes';
-import { IReduxState, ReduxDispatch } from '../redux/store';
+import { useSelector } from '../redux/store';
-const mapStateToProps = (state: IReduxState, props: IHistoryProps & IAppContext) => {
- let selectedExitLocation: RelayLocation | undefined;
- let selectedEntryLocation: RelayLocation | undefined;
- let selectedBridgeLocation: LiftedConstraint<RelayLocation> | undefined;
- let multihopEnabled = false;
+export default function SelectLocationPage() {
+ const history = useHistory();
- if ('normal' in state.settings.relaySettings) {
- const exitLocation = state.settings.relaySettings.normal.location;
- if (exitLocation !== 'any') {
- selectedExitLocation = exitLocation;
- }
- }
+ const { updateRelaySettings, connectTunnel, updateBridgeSettings } = useAppContext();
+
+ const locale = useSelector((state) => state.userInterface.locale);
+ const settings = useSelector((state) => state.settings);
+ const { relaySettings, bridgeSettings, bridgeState } = settings;
- const relaySettings = state.settings.relaySettings;
- const tunnelProtocol = 'normal' in relaySettings ? relaySettings.normal.tunnelProtocol : 'any';
+ const providers = useMemo(
+ () => ('normal' in relaySettings ? relaySettings.normal.providers : []),
+ [relaySettings],
+ );
- if (tunnelProtocol === 'openvpn' && 'normal' in state.settings.bridgeSettings) {
- selectedBridgeLocation = state.settings.bridgeSettings.normal.location;
- } else if ('normal' in relaySettings) {
- multihopEnabled = relaySettings.normal.wireguard.useMultihop;
+ const ownership = useMemo(
+ () => ('normal' in relaySettings ? relaySettings.normal.ownership : Ownership.any),
+ [relaySettings],
+ );
- const entryLocation = relaySettings.normal.wireguard.entryLocation;
- if (multihopEnabled && entryLocation !== 'any') {
- selectedEntryLocation = entryLocation;
+ const tunnelProtocol = useMemo(
+ () => ('normal' in relaySettings ? relaySettings.normal.tunnelProtocol : 'any'),
+ [relaySettings],
+ );
+
+ const selectedExitLocation = useMemo<RelayLocation | undefined>(() => {
+ if ('normal' in relaySettings) {
+ const exitLocation = relaySettings.normal.location;
+ if (exitLocation !== 'any') {
+ return exitLocation;
+ }
}
- }
+ return undefined;
+ }, [relaySettings]);
- const allowEntrySelection =
- (tunnelProtocol === 'openvpn' && state.settings.bridgeState === 'on') ||
- ((tunnelProtocol === 'any' || tunnelProtocol === 'wireguard') && multihopEnabled);
+ const selectedBridgeLocation = useMemo<LiftedConstraint<RelayLocation> | undefined>(() => {
+ return tunnelProtocol === 'openvpn' && 'normal' in bridgeSettings
+ ? bridgeSettings.normal.location
+ : undefined;
+ }, [tunnelProtocol, bridgeSettings]);
- const providers = 'normal' in relaySettings ? relaySettings.normal.providers : [];
- const ownership = 'normal' in relaySettings ? relaySettings.normal.ownership : Ownership.any;
+ const multihopEnabled = useMemo(() => {
+ return (
+ tunnelProtocol !== 'openvpn' &&
+ 'normal' in relaySettings &&
+ relaySettings.normal.wireguard.useMultihop
+ );
+ }, [tunnelProtocol, relaySettings]);
- return {
- locale: state.userInterface.locale,
- selectedExitLocation,
- selectedEntryLocation,
- selectedBridgeLocation,
- relayLocations: filterLocations(state.settings.relayLocations, providers, ownership),
- bridgeLocations: filterLocations(state.settings.bridgeLocations, providers, ownership),
- allowEntrySelection,
- tunnelProtocol,
- providers,
- ownership,
+ const selectedEntryLocation = useMemo<RelayLocation | undefined>(() => {
+ if (multihopEnabled && 'normal' in relaySettings) {
+ const entryLocation = relaySettings.normal.wireguard.entryLocation;
+ if (multihopEnabled && entryLocation !== 'any') {
+ return entryLocation;
+ }
+ }
+ return undefined;
+ }, [relaySettings, multihopEnabled]);
- onSelectEntryLocation: async (entryLocation: RelayLocation) => {
- // dismiss the view first
- props.history.dismiss();
+ const allowEntrySelection = useMemo(() => {
+ return (
+ (tunnelProtocol === 'openvpn' && bridgeState === 'on') ||
+ ((tunnelProtocol === 'any' || tunnelProtocol === 'wireguard') && multihopEnabled)
+ );
+ }, [tunnelProtocol, bridgeState, multihopEnabled]);
- const relayUpdate = createWireguardRelayUpdater(state.settings.relaySettings)
- .tunnel.wireguard((wireguard) => wireguard.entryLocation.exact(entryLocation))
- .build();
+ const relayLocations = filterLocations(settings.relayLocations, providers, ownership);
+ const bridgeLocations = filterLocations(settings.bridgeLocations, providers, ownership);
- try {
- await props.app.updateRelaySettings(relayUpdate);
- } catch (e) {
- const error = e as Error;
- log.error('Failed to select the entry location', error.message);
- }
- },
- };
-};
-const mapDispatchToProps = (_dispatch: ReduxDispatch, props: IHistoryProps & IAppContext) => {
- return {
- onClose: () => props.history.dismiss(),
- onViewFilter: () => props.history.push(RoutePath.filter),
- onSelectExitLocation: async (relayLocation: RelayLocation) => {
+ const onClose = useCallback(() => history.dismiss(), [history]);
+ const onViewFilter = useCallback(() => history.push(RoutePath.filter), [history]);
+ const onSelectExitLocation = useCallback(
+ async (relayLocation: RelayLocation) => {
// dismiss the view first
- props.history.dismiss();
-
+ history.dismiss();
try {
const relayUpdate = RelaySettingsBuilder.normal().location.fromRaw(relayLocation).build();
- await props.app.updateRelaySettings(relayUpdate);
- await props.app.connectTunnel();
+ await updateRelaySettings(relayUpdate);
+ await connectTunnel();
} catch (e) {
const error = e as Error;
log.error(`Failed to select the exit location: ${error.message}`);
}
},
- onSelectBridgeLocation: async (bridgeLocation: RelayLocation) => {
+ [connectTunnel, updateRelaySettings, history],
+ );
+ const onSelectEntryLocation = useCallback(
+ async (entryLocation: RelayLocation) => {
// dismiss the view first
- props.history.dismiss();
+ history.dismiss();
+
+ const relayUpdate = createWireguardRelayUpdater(relaySettings)
+ .tunnel.wireguard((wireguard) => wireguard.entryLocation.exact(entryLocation))
+ .build();
try {
- await props.app.updateBridgeSettings(
- new BridgeSettingsBuilder().location.fromRaw(bridgeLocation).build(),
- );
+ await updateRelaySettings(relayUpdate);
} catch (e) {
const error = e as Error;
- log.error(`Failed to select the bridge location: ${error.message}`);
+ log.error('Failed to select the entry location', error.message);
}
},
- onSelectClosestToExit: async () => {
+ [history, relaySettings, updateRelaySettings],
+ );
+ const onSelectBridgeLocation = useCallback(
+ async (bridgeLocation: RelayLocation) => {
// dismiss the view first
- props.history.dismiss();
+ history.dismiss();
try {
- await props.app.updateBridgeSettings(new BridgeSettingsBuilder().location.any().build());
+ await updateBridgeSettings(
+ new BridgeSettingsBuilder().location.fromRaw(bridgeLocation).build(),
+ );
} catch (e) {
const error = e as Error;
- log.error(`Failed to set the bridge location to closest to exit: ${error.message}`);
+ log.error(`Failed to select the bridge location: ${error.message}`);
}
},
- onClearProviders: async () => {
- await props.app.updateRelaySettings({ normal: { providers: [] } });
- },
- onClearOwnership: async () => {
- await props.app.updateRelaySettings({ normal: { ownership: Ownership.any } });
- },
- };
-};
+ [history, updateBridgeSettings],
+ );
+ const onSelectClosestToExit = useCallback(async () => {
+ history.dismiss();
+
+ try {
+ await updateBridgeSettings(new BridgeSettingsBuilder().location.any().build());
+ } catch (e) {
+ const error = e as Error;
+ log.error(`Failed to set the bridge location to closest to exit: ${error.message}`);
+ }
+ }, [updateBridgeSettings, history]);
+
+ const onClearProviders = useCallback(async () => {
+ await updateRelaySettings({ normal: { providers: [] } });
+ }, [updateRelaySettings]);
+
+ const onClearOwnership = useCallback(async () => {
+ await updateRelaySettings({ normal: { ownership: Ownership.any } });
+ }, [updateRelaySettings]);
-export default withAppContext(
- withHistory(connect(mapStateToProps, mapDispatchToProps)(SelectLocation)),
-);
+ return (
+ <SelectLocation
+ locale={locale}
+ selectedExitLocation={selectedExitLocation}
+ selectedEntryLocation={selectedEntryLocation}
+ selectedBridgeLocation={selectedBridgeLocation}
+ relayLocations={relayLocations}
+ bridgeLocations={bridgeLocations}
+ allowEntrySelection={allowEntrySelection}
+ tunnelProtocol={tunnelProtocol}
+ providers={providers}
+ ownership={ownership}
+ onClose={onClose}
+ onViewFilter={onViewFilter}
+ onSelectExitLocation={onSelectExitLocation}
+ onSelectEntryLocation={onSelectEntryLocation}
+ onSelectBridgeLocation={onSelectBridgeLocation}
+ onSelectClosestToExit={onSelectClosestToExit}
+ onClearProviders={onClearProviders}
+ onClearOwnership={onClearOwnership}
+ />
+ );
+}