diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2024-04-09 08:09:38 +0200 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2024-04-11 17:21:23 +0200 |
| commit | 0470304a2b365c5062b26f9d817e9f9a0c23dad4 (patch) | |
| tree | 6e0e2cf871ede93320b0bbc1097dd4ad87519101 | |
| parent | 41a01db5963e0f499c0dc23419af8ed6bd8bf772 (diff) | |
| download | mullvadvpn-0470304a2b365c5062b26f9d817e9f9a0c23dad4.tar.xz mullvadvpn-0470304a2b365c5062b26f9d817e9f9a0c23dad4.zip | |
Add view for editing custom bridge
| -rw-r--r-- | gui/src/renderer/components/AppRouter.tsx | 2 | ||||
| -rw-r--r-- | gui/src/renderer/components/EditCustomBridge.tsx | 116 | ||||
| -rw-r--r-- | gui/src/renderer/lib/routes.ts | 1 | ||||
| -rw-r--r-- | gui/src/shared/localization-contexts.ts | 1 |
4 files changed, 120 insertions, 0 deletions
diff --git a/gui/src/renderer/components/AppRouter.tsx b/gui/src/renderer/components/AppRouter.tsx index 9e4a13adc8..0f85601a92 100644 --- a/gui/src/renderer/components/AppRouter.tsx +++ b/gui/src/renderer/components/AppRouter.tsx @@ -12,6 +12,7 @@ import Connect from './Connect'; import Debug from './Debug'; import { DeviceRevokedView } from './DeviceRevokedView'; import { EditApiAccessMethod } from './EditApiAccessMethod'; +import { EditCustomBridge } from './EditCustomBridge'; import { SetupFinished, TimeAdded, @@ -92,6 +93,7 @@ export default function AppRouter() { <Route exact path={RoutePath.problemReport} component={ProblemReport} /> <Route exact path={RoutePath.debug} component={Debug} /> <Route exact path={RoutePath.selectLocation} component={SelectLocation} /> + <Route exact path={RoutePath.editCustomBridge} component={EditCustomBridge} /> <Route exact path={RoutePath.filter} component={Filter} /> </Switch> </TransitionView> diff --git a/gui/src/renderer/components/EditCustomBridge.tsx b/gui/src/renderer/components/EditCustomBridge.tsx new file mode 100644 index 0000000000..2692217ea0 --- /dev/null +++ b/gui/src/renderer/components/EditCustomBridge.tsx @@ -0,0 +1,116 @@ +import { useCallback } from 'react'; + +import { CustomProxy } from '../../shared/daemon-rpc-types'; +import { messages } from '../../shared/gettext'; +import { useBridgeSettingsUpdater } from '../lib/constraint-updater'; +import { useHistory } from '../lib/history'; +import { useBoolean } from '../lib/utilityHooks'; +import { useSelector } from '../redux/store'; +import { SettingsForm } from './cell/SettingsForm'; +import { BackAction } from './KeyboardNavigation'; +import { Layout, SettingsContainer } from './Layout'; +import { ModalAlert, ModalAlertType } from './Modal'; +import { NavigationBar, NavigationContainer, NavigationItems, TitleBarItem } from './NavigationBar'; +import { ProxyForm } from './ProxyForm'; +import SettingsHeader, { HeaderTitle } from './SettingsHeader'; +import { StyledContent, StyledNavigationScrollbars, StyledSettingsContent } from './SettingsStyles'; +import { SmallButton, SmallButtonColor } from './SmallButton'; + +export function EditCustomBridge() { + return ( + <SettingsForm> + <CustomBridgeForm /> + </SettingsForm> + ); +} + +function CustomBridgeForm() { + const history = useHistory(); + const bridgeSettingsUpdater = useBridgeSettingsUpdater(); + const bridgeSettings = useSelector((state) => state.settings.bridgeSettings); + + const [deleteDialogVisible, showDeleteDialog, hideDeleteDialog] = useBoolean(); + + // If there are no custom bridge settings, we should prompt the user to add a custom bridge. + // Otherwise, we should prompt them to edit the existing custom bridge settings. + const title = + bridgeSettings.custom === undefined + ? messages.pgettext('custom-bridge', 'Add custom bridge') + : messages.pgettext('custom-bridge', 'Edit custom bridge'); + + const onSave = useCallback( + (newBridge: CustomProxy) => { + void bridgeSettingsUpdater((bridgeSettings) => { + bridgeSettings.type = 'custom'; + bridgeSettings.custom = newBridge; + return bridgeSettings; + }); + history.pop(); + }, + [bridgeSettingsUpdater, history.pop], + ); + + const onDelete = useCallback(() => { + if (bridgeSettings.custom !== undefined) { + hideDeleteDialog(); + void bridgeSettingsUpdater((bridgeSettings) => { + bridgeSettings.type = 'normal'; + delete bridgeSettings.custom; + return bridgeSettings; + }); + history.pop(); + } + }, [bridgeSettingsUpdater, history.pop]); + + return ( + <BackAction action={history.pop}> + <Layout> + <SettingsContainer> + <NavigationContainer> + <NavigationBar> + <NavigationItems> + <TitleBarItem>{title}</TitleBarItem> + </NavigationItems> + </NavigationBar> + + <StyledNavigationScrollbars fillContainer> + <StyledContent> + <SettingsHeader> + <HeaderTitle>{title}</HeaderTitle> + </SettingsHeader> + + <StyledSettingsContent> + <ProxyForm + proxy={bridgeSettings.custom} + onSave={onSave} + onCancel={history.pop} + onDelete={bridgeSettings.custom === undefined ? undefined : showDeleteDialog} + /> + </StyledSettingsContent> + + <ModalAlert + isOpen={deleteDialogVisible} + type={ModalAlertType.warning} + gridButtons={[ + <SmallButton key="cancel" onClick={hideDeleteDialog}> + {messages.gettext('Cancel')} + </SmallButton>, + <SmallButton key="delete" color={SmallButtonColor.red} onClick={onDelete}> + {messages.gettext('Delete')} + </SmallButton>, + ]} + close={hideDeleteDialog} + title={messages.pgettext('custom-bridge', 'Delete custom bridge?')} + message={messages.pgettext( + 'custom-bridge', + 'Deleting the custom bridge will take you back to the select location view and the Automatic option will be selected instead.', + )} + /> + </StyledContent> + </StyledNavigationScrollbars> + </NavigationContainer> + </SettingsContainer> + </Layout> + </BackAction> + ); +} diff --git a/gui/src/renderer/lib/routes.ts b/gui/src/renderer/lib/routes.ts index 499157976a..1f2a3c28a7 100644 --- a/gui/src/renderer/lib/routes.ts +++ b/gui/src/renderer/lib/routes.ts @@ -25,5 +25,6 @@ export enum RoutePath { problemReport = '/settings/support/problem-report', debug = '/settings/debug', selectLocation = '/select-location', + editCustomBridge = '/select-location/edit-custom-bridge', filter = '/select-location/filter', } diff --git a/gui/src/shared/localization-contexts.ts b/gui/src/shared/localization-contexts.ts index 71a663def0..f30212025c 100644 --- a/gui/src/shared/localization-contexts.ts +++ b/gui/src/shared/localization-contexts.ts @@ -15,6 +15,7 @@ export type LocalizationContexts = | 'account-expiry' | 'select-location-view' | 'select-location-nav' + | 'custom-bridge' | 'filter-view' | 'filter-nav' | 'settings-view' |
