|
|
|
@ -1,17 +1,16 @@
|
|
|
|
|
import * as React from 'react';
|
|
|
|
|
import { FieldConfig } from '../FieldTypes/config';
|
|
|
|
|
import { FieldDropdown } from '../FieldTypes/dropdown';
|
|
|
|
|
import { FieldNumber } from '../FieldTypes/number';
|
|
|
|
|
import { FieldString } from '../FieldTypes/string';
|
|
|
|
|
import { connect } from '../redux';
|
|
|
|
|
import { FileSystemConfig } from '../types/fileSystemConfig';
|
|
|
|
|
import type { FieldFactory, FSCChanged, FSCChangedMultiple } from './fields';
|
|
|
|
|
|
|
|
|
|
function proxy(config: FileSystemConfig, onChange: FSCChanged<'proxy'>): React.ReactElement {
|
|
|
|
|
function hostAndPort(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 <React.Fragment>
|
|
|
|
|
<p>{new Date().toString()}</p>
|
|
|
|
|
<FieldString label="Proxy Host" value={config.proxy!.host} onChange={onChangeHost}
|
|
|
|
|
description="Hostname or IP address of the proxy." />
|
|
|
|
|
<FieldNumber label="Proxy Port" value={config.proxy!.port} onChange={onChangePort}
|
|
|
|
@ -19,77 +18,56 @@ function proxy(config: FileSystemConfig, onChange: FSCChanged<'proxy'>): React.R
|
|
|
|
|
</React.Fragment>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
interface HopFieldProps {
|
|
|
|
|
config: FileSystemConfig;
|
|
|
|
|
configs: [name: string, label: string][];
|
|
|
|
|
onChange: FSCChanged<'hop'>;
|
|
|
|
|
}
|
|
|
|
|
const HopField = connect(({ config, configs, onChange }: HopFieldProps) => {
|
|
|
|
|
const callback = (newValue?: [string, string]) => onChange('hop', newValue?.[0]);
|
|
|
|
|
function hop(config: FileSystemConfig, onChange: FSCChanged<'hop'>): React.ReactElement {
|
|
|
|
|
const callback = (newValue?: FileSystemConfig) => onChange('hop', newValue?.name);
|
|
|
|
|
const description = 'Use another configuration as proxy, using a SSH tunnel through the targeted config to the actual remote system';
|
|
|
|
|
const displayName = (item: [string, string]) => item[1];
|
|
|
|
|
const value = config.hop ? [config.hop, configs.find(c => c[0] === config.hop)?.[1] || config.hop] as const : undefined;
|
|
|
|
|
return <FieldDropdown key="hop" label="Hop" {...{ value, values: configs, description, displayName } as const} onChange={callback} optional />;
|
|
|
|
|
})<Pick<HopFieldProps, 'configs'>>(state => {
|
|
|
|
|
const pairs = new Map<string, string>();
|
|
|
|
|
for (const { name, label } of state.data.configs) {
|
|
|
|
|
pairs.set(name, label || name);
|
|
|
|
|
}
|
|
|
|
|
return { configs: Array.from(pairs) };
|
|
|
|
|
});
|
|
|
|
|
return <FieldConfig key="hop" label="Hop" onChange={callback} value={config.hop} description={description} />;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
enum ProxyType { http, socks4, socks5, hop }
|
|
|
|
|
const ProxyTypeNames: Record<ProxyType, string> = {
|
|
|
|
|
[ProxyType.http]: 'HTTP',
|
|
|
|
|
[ProxyType.socks4]: 'SOCKS 4',
|
|
|
|
|
[ProxyType.socks5]: 'SOCKS 5',
|
|
|
|
|
[ProxyType.hop]: 'SSH Hop',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
function Merged(props: { config: FileSystemConfig, onChange: FSCChanged, onChangeMultiple: FSCChangedMultiple }): React.ReactElement | null {
|
|
|
|
|
const { config, onChange, onChangeMultiple } = props;
|
|
|
|
|
const [showHop, setShowHop] = React.useState(!!config.hop);
|
|
|
|
|
function callback(newValue?: ProxyType) {
|
|
|
|
|
if (!newValue) {
|
|
|
|
|
setShowHop(false);
|
|
|
|
|
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,
|
|
|
|
|
});
|
|
|
|
|
if (newValue === ProxyType.hop) {
|
|
|
|
|
setShowHop(true);
|
|
|
|
|
return onChangeMultiple({ proxy: undefined });
|
|
|
|
|
}
|
|
|
|
|
setShowHop(false);
|
|
|
|
|
return onChangeMultiple({
|
|
|
|
|
['_hop' as any]: undefined,
|
|
|
|
|
hop: undefined,
|
|
|
|
|
proxy: {
|
|
|
|
|
host: '',
|
|
|
|
|
port: 22,
|
|
|
|
|
...config.proxy,
|
|
|
|
|
type: newType,
|
|
|
|
|
type: ProxyType[newValue] as any,
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
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]);
|
|
|
|
|
const values: ProxyType[] = [ProxyType.hop, ProxyType.socks4, ProxyType.socks5, ProxyType.http];
|
|
|
|
|
const type = config.proxy?.type;
|
|
|
|
|
const value = (config.hop || showHop) ? ProxyType.hop : (type && ProxyType[type]);
|
|
|
|
|
return <React.Fragment key="proxy">
|
|
|
|
|
<FieldDropdown key="proxy" label="Proxy" {...{ value, values, description } as const} onChange={callback} optional />
|
|
|
|
|
{showHop && <HopField config={config} onChange={onChange} />}
|
|
|
|
|
{config.proxy && proxy(config, onChange)}
|
|
|
|
|
<FieldDropdown key="proxy" label="Proxy" {...{ value, values, description } as const} displayName={i => ProxyTypeNames[i!]} onChange={callback} optional />
|
|
|
|
|
{(config.hop || showHop) && hop(config, onChange)}
|
|
|
|
|
{config.proxy && hostAndPort(config, onChange)}
|
|
|
|
|
</React.Fragment>;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const PROXY_FIELD: FieldFactory = merged;
|
|
|
|
|
export const PROXY_FIELD: FieldFactory = (config, onChange, onChangeMultiple) =>
|
|
|
|
|
<Merged config={config} onChange={onChange} onChangeMultiple={onChangeMultiple} />;
|
|
|
|
|