diff --git a/webview/src/ConfigEditor/fields.tsx b/webview/src/ConfigEditor/fields.tsx index 268dec9..d8ec823 100644 --- a/webview/src/ConfigEditor/fields.tsx +++ b/webview/src/ConfigEditor/fields.tsx @@ -5,9 +5,11 @@ import { FieldNumber } from 'src/FieldTypes/number'; import { FieldPath } from 'src/FieldTypes/path'; import { FieldString } from 'src/FieldTypes/string'; import { FileSystemConfig, invalidConfigName } from 'src/types/fileSystemConfig'; +import { PROXY_FIELD } from './proxyFields'; export type FieldChanged = (field: K, newValue: V) => void; export type FSCChanged = FieldChanged; +export type FSCChangedMultiple = (newConfig: Partial) => void; function pathValidator(value?: string): string | null { if (!value) return null; @@ -100,5 +102,8 @@ export function passphrase(config: FileSystemConfig, onChange: FSCChanged<'passp return } -type FieldFactory = (config: FileSystemConfig, onChange: FSCChanged) => React.ReactElement; -export const FIELDS: FieldFactory[] = [name, merge, label, putty, host, port, root, agent, username, password, privateKeyPath, passphrase]; +export type FieldFactory = (config: FileSystemConfig, onChange: FSCChanged, onChangeMultiple: FSCChangedMultiple) => React.ReactElement | null; +export const FIELDS: FieldFactory[] = [ + name, merge, label, putty, host, port, + root, agent, username, password, privateKeyPath, passphrase, + PROXY_FIELD]; diff --git a/webview/src/ConfigEditor/index.tsx b/webview/src/ConfigEditor/index.tsx index c0d80ef..c261d5a 100644 --- a/webview/src/ConfigEditor/index.tsx +++ b/webview/src/ConfigEditor/index.tsx @@ -31,7 +31,7 @@ class ConfigEditor extends React.Component {

{formatConfigLocation(oldConfig._location!)}

- {Fields.FIELDS.map(f => f(newConfig, this.onChange)).filter(e => e)} + {Fields.FIELDS.map(f => f(newConfig, this.onChange, this.onChangeMultiple)).filter(e => e)}
{group => @@ -45,6 +45,10 @@ class ConfigEditor extends React.Component { console.log(`Changed field '${key}' to: ${value}`); this.props.setNewConfig({ ...this.props.newConfig, [key]: value }); }; + protected onChangeMultiple: Fields.FSCChangedMultiple = (newConfig) => { + console.log('Overwriting config fields:', newConfig); + this.props.setNewConfig({ ...this.props.newConfig, ...newConfig }); + }; } interface SubState { view: IConfigEditorState }; diff --git a/webview/src/ConfigEditor/proxyFields.tsx b/webview/src/ConfigEditor/proxyFields.tsx new file mode 100644 index 0000000..2b70f04 --- /dev/null +++ b/webview/src/ConfigEditor/proxyFields.tsx @@ -0,0 +1,83 @@ +import * as React from 'react'; +import { FieldDropdown } from 'src/FieldTypes/dropdown'; +import { FieldDropdownWithInput } from 'src/FieldTypes/dropdownwithinput'; +import { FieldNumber } from 'src/FieldTypes/number'; +import { FieldString } from 'src/FieldTypes/string'; +import { FileSystemConfig } from 'src/types/fileSystemConfig'; +import { FieldFactory, FSCChanged, FSCChangedMultiple } from './fields'; + +export function proxy(config: FileSystemConfig, onChange: FSCChanged<'proxy'>): React.ReactElement { + const onChangeHost = (host: string) => onChange('proxy', { ...config.proxy!, host }); + const onChangePort = (port: number) => onChange('proxy', { ...config.proxy!, port }); + console.log('Current config:', config); + return +

{new Date().toString()}

+ + +
; +} + +export function hop(config: FileSystemConfig, onChange: FSCChanged<'hop'>): React.ReactElement { + const callback = (newValue?: string) => onChange('hop', newValue); + const description = 'Use another configuration as proxy, using a SSH tunnel through the targeted config to the actual remote system'; + const values = ['TO', ' DO']; + return ; +} + +const ProxyTypeToString = { + http: 'HTTP', + socks4: 'SOCKS 4', + socks5: 'SOCKS 5', +} as const; +const ProxyStringToType = { + 'HTTP': 'http', + 'SOCKS 4': 'socks4', + 'SOCKS 5': 'socks5', + 'SSH Hop': 'hop', +} as const; +type ProxyStrings = keyof typeof ProxyStringToType; + +export function merged(config: FileSystemConfig, onChange: FSCChanged, onChangeMultiple: FSCChangedMultiple): React.ReactElement | null { + function callback(newValue?: ProxyStrings) { + // Fields starting with _ don't get saved to file + // We use it here so we know when to display the hop stuff + if (!newValue) { + return onChangeMultiple({ + ['_hop' as any]: undefined, + hop: undefined, + proxy: undefined, + }); + } + const newType = ProxyStringToType[newValue]; + if (newType === 'hop') { + return onChangeMultiple({ + ['_hop' as any]: true, + proxy: undefined, + }); + } + return onChangeMultiple({ + ['_hop' as any]: undefined, + hop: undefined, + proxy: { + host: '', + port: 22, + ...config.proxy, + type: newType, + } + }); + } + const description = 'The type of proxy to use when connecting to the remote system'; + const values: ProxyStrings[] = ['SSH Hop', 'SOCKS 4', 'SOCKS 5', 'HTTP']; + const showHop = config.hop || (config as any)._hop; + const type = config.proxy && config.proxy.type; + const value = showHop ? 'SSH Hop' : (type && ProxyTypeToString[type]); + return + key="proxy" label="Proxy" {...{ value, values, description }} onChange={callback} optional={true} /> + {showHop && hop(config, onChange)} + {config.proxy && proxy(config, onChange)} + ; +} + +export const PROXY_FIELD: FieldFactory = merged; \ No newline at end of file