mirror of
				https://github.com/anticensority/runet-censorship-bypass.git
				synced 2025-10-31 07:57:28 +03:00 
			
		
		
		
	ProxyEditor fully works but not attached yet
This commit is contained in:
		
							parent
							
								
									61eceb7115
								
							
						
					
					
						commit
						a40f691f56
					
				|  | @ -30,7 +30,7 @@ export default function getProxyEditor(theState) { | ||||||
|       padding: 0; |       padding: 0; | ||||||
|     } |     } | ||||||
|     /* PROXY ROW */ |     /* PROXY ROW */ | ||||||
|     table.editor tr.proxyRow td:first-child { |     table.editor tr.proxyRow td:nth-child(2) { | ||||||
|       text-align: center; |       text-align: center; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -78,7 +78,8 @@ export default function getProxyEditor(theState) { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /* LAST COLUMN: BUTTONS */ |     /* LAST COLUMN: BUTTONS */ | ||||||
|     table.editor tr > *:nth-last-child(1) { |     table.editor tr > *:nth-last-child(1), | ||||||
|  |     table.editor tr.proxyRow > td:first-child { | ||||||
|       text-align: center; |       text-align: center; | ||||||
|       padding: 0; |       padding: 0; | ||||||
|       position: relative; |       position: relative; | ||||||
|  | @ -123,6 +124,10 @@ export default function getProxyEditor(theState) { | ||||||
|     return true; |     return true; | ||||||
| 
 | 
 | ||||||
|   }; |   }; | ||||||
|  |   const splitBySemi = (proxyString) => proxyString.replace(/#.*$/mg, '').trim().split(/\s*;\s*/g).filter((s) => s); | ||||||
|  |   const joinBySemi = (strs) => strs.join(';\n') + ';'; | ||||||
|  |   const normilizeProxyString = (str) => joinBySemi(splitBySemi(str)); | ||||||
|  | 
 | ||||||
|   const PROXY_TYPE_LABEL_PAIRS = [['PROXY', 'PROXY/HTTP'],['HTTPS'],['SOCKS4'],['SOCKS5'],['SOCKS']]; |   const PROXY_TYPE_LABEL_PAIRS = [['PROXY', 'PROXY/HTTP'],['HTTPS'],['SOCKS4'],['SOCKS5'],['SOCKS']]; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -181,12 +186,35 @@ export default function getProxyEditor(theState) { | ||||||
|       const hostname = elements.hostname; |       const hostname = elements.hostname; | ||||||
|       const port = elements.port; |       const port = elements.port; | ||||||
| 
 | 
 | ||||||
|       that.props.updateProxyStringRaw( |       that.props.setProxyStringRaw( | ||||||
|         `${that.props.proxyStringRaw} ${type} ${hostname}:${port};`.trim() |         `${that.props.proxyStringRaw} ${type} ${hostname}:${port};`.trim() | ||||||
|       ); |       ); | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     handleDelete(that, {proxyAsString, index}) { | ||||||
|  | 
 | ||||||
|  |       event.preventDefault(); | ||||||
|  |       const proxyStrings = splitBySemi(that.props.proxyStringRaw); | ||||||
|  |       proxyStrings.splice(index, 1); | ||||||
|  | 
 | ||||||
|  |       that.props.setProxyStringRaw( joinBySemi(proxyStrings) ); | ||||||
|  | 
 | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     raisePriority(that, {proxyAsString, index}) { | ||||||
|  | 
 | ||||||
|  |       event.preventDefault(); | ||||||
|  |       if (index < 1) { | ||||||
|  |         return; | ||||||
|  |       } | ||||||
|  |       const proxyStrings = splitBySemi(that.props.proxyStringRaw); | ||||||
|  |       proxyStrings.splice(index - 1, 2, proxyStrings[index], proxyStrings[index-1]); | ||||||
|  | 
 | ||||||
|  |       that.props.setProxyStringRaw( joinBySemi(proxyStrings) ); | ||||||
|  |        | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     handleSubmit(that, event) { |     handleSubmit(that, event) { | ||||||
| 
 | 
 | ||||||
|       event.preventDefault(); |       event.preventDefault(); | ||||||
|  | @ -201,7 +229,7 @@ export default function getProxyEditor(theState) { | ||||||
|           <table class={scopedCss.editor}> |           <table class={scopedCss.editor}> | ||||||
|             <thead> |             <thead> | ||||||
|               <tr> |               <tr> | ||||||
|                 <th>протокол</th> <th>домен / IP</th> <th>порт</th> <th> |                 <th colspan="2">протокол</th> <th>домен / IP</th> <th>порт</th> <th> | ||||||
|                   <SwitchButton title="импорт/экспорт" onClick={linkEvent(this, this.handleModeSwitch)}/> |                   <SwitchButton title="импорт/экспорт" onClick={linkEvent(this, this.handleModeSwitch)}/> | ||||||
|                 </th> |                 </th> | ||||||
|               </tr> |               </tr> | ||||||
|  | @ -209,7 +237,7 @@ export default function getProxyEditor(theState) { | ||||||
|             <tbody> |             <tbody> | ||||||
|               {/* ADD NEW PROXY STARTS. */} |               {/* ADD NEW PROXY STARTS. */} | ||||||
|               <tr class={scopedCss.addPanel}> |               <tr class={scopedCss.addPanel}> | ||||||
|                 <td> |                 <td colspan="2"> | ||||||
|                   <select reqiured |                   <select reqiured | ||||||
|                     class={scopedCss.noPad} |                     class={scopedCss.noPad} | ||||||
|                     name="proxyType" |                     name="proxyType" | ||||||
|  | @ -232,6 +260,7 @@ export default function getProxyEditor(theState) { | ||||||
|                     placeholder="89.140.125.17" |                     placeholder="89.140.125.17" | ||||||
|                     name="hostname" |                     name="hostname" | ||||||
|                     onInvalid={linkEvent(this, this.showInvalidMessage)} |                     onInvalid={linkEvent(this, this.showInvalidMessage)} | ||||||
|  |                     tabindex="1" | ||||||
|                   /> |                   /> | ||||||
|                 </td> |                 </td> | ||||||
|                 <td> |                 <td> | ||||||
|  | @ -243,6 +272,7 @@ export default function getProxyEditor(theState) { | ||||||
|                     name="port" |                     name="port" | ||||||
|                     onInvalid={linkEvent(this, this.showInvalidMessage)} |                     onInvalid={linkEvent(this, this.showInvalidMessage)} | ||||||
|                     onkeydown={onlyPort} |                     onkeydown={onlyPort} | ||||||
|  |                     tabindex="2" | ||||||
|                   /> |                   /> | ||||||
|                 </td> |                 </td> | ||||||
|                 <td> |                 <td> | ||||||
|  | @ -255,17 +285,23 @@ export default function getProxyEditor(theState) { | ||||||
|               </tr> |               </tr> | ||||||
|               {/* ADD NEW PROXY ENDS. */} |               {/* ADD NEW PROXY ENDS. */} | ||||||
|               { |               { | ||||||
|                 this.props.proxyStringRaw.split(/\s*;\s*/g).filter((s) => s).map((proxyAsString) => { |                 splitBySemi(this.props.proxyStringRaw).map((proxyAsString, index) => { | ||||||
| 
 | 
 | ||||||
|                   const [type, addr] = proxyAsString.trim().split(/\s/); |                   const [type, addr] = proxyAsString.trim().split(/\s+/); | ||||||
|                   const [hostname, port] = addr.split(':'); |                   const [hostname, port] = addr.split(':'); | ||||||
|                   return ( |                   return ( | ||||||
|                     <tr class={scopedCss.proxyRow}> |                     <tr class={scopedCss.proxyRow}> | ||||||
|                       <td>{type}</td><td>{hostname}</td><td>{port}</td> |  | ||||||
|                       <td> |                       <td> | ||||||
|                         <button type="button" title="Повысить приоритет">↑</button> |                         <button type="button" | ||||||
|                         <br/> |                           class={scopedCss.only} title="Удалить" | ||||||
|                         {/*<input type="submit" title="Удалить прокси" value="X"/>*/} |                           onClick={() => this.handleDelete(this, {proxyAsString, index})} | ||||||
|  |                         >X</button> | ||||||
|  |                       </td><td>{type}</td><td>{hostname}</td><td>{port}</td> | ||||||
|  |                       <td> | ||||||
|  |                         <button type="button" | ||||||
|  |                           class={scopedCss.only} title="Повысить приоритет" | ||||||
|  |                           onClick={() => this.raisePriority(this, {proxyAsString, index})} | ||||||
|  |                         >▲</button> | ||||||
|                       </td> |                       </td> | ||||||
|                     </tr> |                     </tr> | ||||||
|                   ); |                   ); | ||||||
|  | @ -279,14 +315,25 @@ export default function getProxyEditor(theState) { | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  |   const getInitState = () => ({ | ||||||
|  |     ifHasErrors: false, | ||||||
|  |     stashedExports: false, | ||||||
|  |   }); | ||||||
|  | 
 | ||||||
|   class ExportsEditor extends Component { |   class ExportsEditor extends Component { | ||||||
| 
 | 
 | ||||||
|     constructor(props) { |     constructor(props) { | ||||||
|  | 
 | ||||||
|       super(props); |       super(props); | ||||||
|       this.state = { |       this.state = getInitState(); | ||||||
|         ifHasErrors: false, | 
 | ||||||
|         stashedExports: false, |     } | ||||||
|       }; | 
 | ||||||
|  |     resetState(that, event) { | ||||||
|  | 
 | ||||||
|  |       that.setState(getInitState()); | ||||||
|  |       event.preventDefault(); | ||||||
|  | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     getErrorsInStashedExports() { |     getErrorsInStashedExports() { | ||||||
|  | @ -294,10 +341,7 @@ export default function getProxyEditor(theState) { | ||||||
|       if(this.state.stashedExports === false) { |       if(this.state.stashedExports === false) { | ||||||
|         return; |         return; | ||||||
|       } |       } | ||||||
|       const errors = this.state.stashedExports.trim() |       const errors = splitBySemi(this.state.stashedExports) | ||||||
|         .replace(/#.*$/mg, '') |  | ||||||
|         .split(/\s*;\s*/) |  | ||||||
|         .filter((s) => s) |  | ||||||
|         .map((proxyAsString) => { |         .map((proxyAsString) => { | ||||||
| 
 | 
 | ||||||
|           const [rawType, addr, ...rest] = proxyAsString.split(/\s+/); |           const [rawType, addr, ...rest] = proxyAsString.split(/\s+/); | ||||||
|  | @ -340,7 +384,7 @@ export default function getProxyEditor(theState) { | ||||||
|           that.props.funs.showErrors(...errors); |           that.props.funs.showErrors(...errors); | ||||||
|           return; |           return; | ||||||
|         } |         } | ||||||
|         that.props.updateProxyStringRaw(that.state.stashedExports); |         that.props.setProxyStringRaw(that.state.stashedExports); | ||||||
|       } |       } | ||||||
|       that.setState({ |       that.setState({ | ||||||
|         stashedExports: false, |         stashedExports: false, | ||||||
|  | @ -352,11 +396,9 @@ export default function getProxyEditor(theState) { | ||||||
| 
 | 
 | ||||||
|     handleTextareaChange(that, event) { |     handleTextareaChange(that, event) { | ||||||
| 
 | 
 | ||||||
|       let newVal = event.target.value.trim(); |       that.setState({ | ||||||
|       if (newVal && !newVal.endsWith(';')) { |         stashedExports: normilizeProxyString(event.target.value), | ||||||
|         newVal += ';'; |       }); | ||||||
|       } |  | ||||||
|       that.setState({stashedExports: newVal}); |  | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -369,6 +411,8 @@ export default function getProxyEditor(theState) { | ||||||
| 
 | 
 | ||||||
|     render(props) { |     render(props) { | ||||||
| 
 | 
 | ||||||
|  |       const reset = linkEvent(this, this.resetState); | ||||||
|  | 
 | ||||||
|       return ( |       return ( | ||||||
|         <form onSubmit={linkEvent(this, this.handleSubmit)}> |         <form onSubmit={linkEvent(this, this.handleSubmit)}> | ||||||
|           <table class={scopedCss.editor}> |           <table class={scopedCss.editor}> | ||||||
|  | @ -379,8 +423,8 @@ export default function getProxyEditor(theState) { | ||||||
|                     this.state.stashedExports === false |                     this.state.stashedExports === false | ||||||
|                       ? 'Жду изменений...' |                       ? 'Жду изменений...' | ||||||
|                       : (this.state.ifHasErrors |                       : (this.state.ifHasErrors | ||||||
|                           ? (<span><a href="">Сбросьте изменения</a> или поправьте</span>) |                           ? (<span><a href="" onClick={reset}>Сбросьте изменения</a> или поправьте</span>) | ||||||
|                           : (<a href="">Сбросить изменения</a>) |                           : (<a href="" onClick={reset}>Сбросить изменения</a>) | ||||||
|                         ) |                         ) | ||||||
|                   } |                   } | ||||||
|                 </th> |                 </th> | ||||||
|  | @ -440,7 +484,7 @@ PROXY foobar.com:8080; # Not HTTP!`.trim()} | ||||||
|       const props = Object.assign({ |       const props = Object.assign({ | ||||||
|         proxyStringRaw: this.state.proxyStringRaw, |         proxyStringRaw: this.state.proxyStringRaw, | ||||||
|         onSwitch: this.handleSwitch, |         onSwitch: this.handleSwitch, | ||||||
|         updateProxyStringRaw: (newVal) => this.setState({proxyStringRaw: newVal}), |         setProxyStringRaw: (newVal) => this.setState({proxyStringRaw: newVal}), | ||||||
|       }, originalProps); |       }, originalProps); | ||||||
|        |        | ||||||
|       return this.state.ifExportsMode |       return this.state.ifExportsMode | ||||||
|  |  | ||||||
|  | @ -1,389 +0,0 @@ | ||||||
| import Inferno, {linkEvent} from 'inferno'; |  | ||||||
| import Component from 'inferno-component'; |  | ||||||
| import css from 'csjs-inject'; |  | ||||||
| 
 |  | ||||||
| export default function getProxyEditor(theState) { |  | ||||||
| 
 |  | ||||||
|   const scopedCss = css` |  | ||||||
| 
 |  | ||||||
|     table.editor { |  | ||||||
|       border-collapse: collapse; |  | ||||||
|       /*border-style: hidden;*/ |  | ||||||
|       width: 100%; |  | ||||||
|       margin: 0.5em 0; |  | ||||||
|       background-color: #f3f5f6; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     table.editor ::-webkit-input-placeholder { |  | ||||||
|       color: #c9c9c9; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     table.editor td, table.editor th { |  | ||||||
|       border: 1px solid #ccc; |  | ||||||
|       text-align: left; |  | ||||||
|       height: 100%; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* ADD PANEL */ |  | ||||||
|     table.editor tr.addPanel td { |  | ||||||
|       padding: 0; |  | ||||||
|     } |  | ||||||
|     /* PROXY ROW */ |  | ||||||
|     table.editor tr.proxyRow td:first-child { |  | ||||||
|       text-align: center; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     table.editor th:not(:last-child) { |  | ||||||
|       padding: 0 0.6em; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     table.editor input:not([type="submit"]), |  | ||||||
|     table.editor select, |  | ||||||
|     table.editor select:hover { |  | ||||||
|       border: none; |  | ||||||
|       background: inherit !important; |  | ||||||
|     } |  | ||||||
|     table.editor select, |  | ||||||
|     table.editor select:hover { |  | ||||||
|       -webkit-appearance: menulist !important; |  | ||||||
|       box-shadow: none !important; |  | ||||||
|     } |  | ||||||
|     table.editor input { |  | ||||||
|       width: 100%; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* BUTTONS */ |  | ||||||
|     table.editor input[type="submit"], |  | ||||||
|     table.editor button { |  | ||||||
|       min-width: 0; |  | ||||||
|       min-height: 0; |  | ||||||
|       width: 100%; |  | ||||||
|       padding: 0; |  | ||||||
|       border: none; |  | ||||||
|     } |  | ||||||
|     .only { |  | ||||||
|       /*height: 100%;*/ |  | ||||||
|       position: absolute; |  | ||||||
|       top: 0; |  | ||||||
|       bottom: 0; |  | ||||||
|       left: 0; |  | ||||||
|       right: 0; |  | ||||||
|     } |  | ||||||
|     table.editor .add { |  | ||||||
|       font-weight: 900;	 |  | ||||||
|     } |  | ||||||
|     table.editor .export { |  | ||||||
|       padding-right: 2px; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /* LAST COLUMN: BUTTONS */ |  | ||||||
|     table.editor tr > *:nth-last-child(1) { |  | ||||||
|       text-align: center; |  | ||||||
|       padding: 0; |  | ||||||
|       position: relative; |  | ||||||
|       min-width: 1em; |  | ||||||
|     } |  | ||||||
|     /* LAST-2 COLUMN: HOSTNAME |  | ||||||
|     table.editor td:nth-last-child(3) { |  | ||||||
|       padding-left: 2px; |  | ||||||
|     }*/ |  | ||||||
|     .noPad { |  | ||||||
|       padding: 0; |  | ||||||
|     } |  | ||||||
|     .padLeft { |  | ||||||
|       padding-left: 2px; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     textarea.textarea { |  | ||||||
|       width: 100% !important; |  | ||||||
|       min-height: 100%; |  | ||||||
|       height: 6em; |  | ||||||
|       border-width: 1px 0 0 0; |  | ||||||
|       /*border: none;*/ |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     table.editor input:invalid { |  | ||||||
|       color: red !important; |  | ||||||
|       border-radius: 0; |  | ||||||
|       border-bottom: 1px dotted red !important; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|   `; |  | ||||||
| 
 |  | ||||||
|   const UI_RAW = 'ui-proxy-string-raw'; |  | ||||||
|   const MAX_PORT = 65535; |  | ||||||
|   const onlyPort = function onlyPort(event) { |  | ||||||
| 
 |  | ||||||
|     if (!event.ctrlKey && (/^\D$/.test(event.key) || /^\d$/.test(event.key) && parseInt(`${this.value}${event.key}`) > MAX_PORT)) { |  | ||||||
|       event.preventDefault(); |  | ||||||
|       return false; |  | ||||||
|     } |  | ||||||
|     // Digits, Alt, Tab, Enter, etc. |  | ||||||
|     return true; |  | ||||||
| 
 |  | ||||||
|   }; |  | ||||||
|   const PROXY_TYPE_LABEL_PAIRS = [['PROXY', 'PROXY/HTTP'],['HTTPS'],['SOCKS4'],['SOCKS5'],['SOCKS']]; |  | ||||||
| 
 |  | ||||||
|   return class ProxyEditor extends Component { |  | ||||||
| 
 |  | ||||||
|     constructor(props) { |  | ||||||
| 
 |  | ||||||
|       super(props); |  | ||||||
|       this.state = { |  | ||||||
|         proxyStringRaw: localStorage.getItem(UI_RAW) || '', |  | ||||||
|         ifExportsMode: false, |  | ||||||
| 
 |  | ||||||
|         ifChangesStashedForApply: false, |  | ||||||
|         stashedExports: false, |  | ||||||
|         ifExportsHaveErrors: false, |  | ||||||
| 
 |  | ||||||
|         newType: 'HTTPS', |  | ||||||
|       }; |  | ||||||
| 
 |  | ||||||
|       this.switchBtn = ( |  | ||||||
|         <button |  | ||||||
|           class={'emoji' + ' ' + scopedCss.export + ' ' + scopedCss.only} |  | ||||||
|           title="импорт/экспорт" |  | ||||||
|           onClick={linkEvent(this, this.handleModeSwitch)} |  | ||||||
|         >⇄</button> |  | ||||||
|       ); |  | ||||||
|        |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     handleTextareaChange(that, event) { |  | ||||||
| 
 |  | ||||||
|       that.setState({stashedExports: event.target.value}); |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
|     preventLostOfChanges() { |  | ||||||
| 
 |  | ||||||
|       window.onbeforeunload = () => true; // TODO |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     findErrorsForStashedExports() { |  | ||||||
| 
 |  | ||||||
|       const valid = true; |  | ||||||
|       if(this.state.stashedExports === false) { |  | ||||||
|         return valid; |  | ||||||
|       } |  | ||||||
|       const errors = this.state.stashedExports.trim() |  | ||||||
|         .split(/\s*;\s*/) |  | ||||||
|         .filter((s) => s) |  | ||||||
|         .map((proxyAsString) => { |  | ||||||
| 
 |  | ||||||
|           const [rawType, addr] = proxyAsString.split(/\s+/); |  | ||||||
|           const knownTypes = PROXY_TYPE_LABEL_PAIRS.map(([type, label]) => type); |  | ||||||
|           if( !knownTypes.includes(rawType.toUpperCase()) ) { |  | ||||||
|             return new Error( |  | ||||||
|               `Неверный тип ${rawType}. Известные типы: ${knownTypes.join(', ')}.` |  | ||||||
|             ); |  | ||||||
|           } |  | ||||||
|           if (!(addr && /^[^:]+:\d+$/.test(addr))) { |  | ||||||
|             return new Error( |  | ||||||
|               `Адрес прокси "${addr || ''}" не соответствует формату "<домен_или_IP>:<порт_из_цифр>".` |  | ||||||
|             ); |  | ||||||
|           } |  | ||||||
|           const [hostname, rawPort] = addr.split(':'); |  | ||||||
|           const port = parseInt(rawPort); |  | ||||||
|           if (port < 0 || port > 65535) { |  | ||||||
|             return new Error( |  | ||||||
|               `Порт "${rawPort}" должен быть целым числом от 0 до 65535.` |  | ||||||
|             ); |  | ||||||
|           } |  | ||||||
|           return false; |  | ||||||
| 
 |  | ||||||
|         }).filter((e) => e); |  | ||||||
|       return errors && errors.length ? errors : false; |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     handleModeSwitch(that, event) { |  | ||||||
|        |  | ||||||
|       event.preventDefault(); // No form submit. |  | ||||||
|       let newProxyStringRaw = that.state.proxyStringRaw; |  | ||||||
| 
 |  | ||||||
|       const doSwitch = () => that.setState({ |  | ||||||
|         ifExportsMode: !that.state.ifExportsMode, |  | ||||||
|         proxyStirngRaw: newProxyStringRaw, |  | ||||||
|         stashedExports: false, |  | ||||||
|         ifExportsHaveErrors: false, |  | ||||||
|       }); |  | ||||||
| 
 |  | ||||||
|       if (that.state.stashedExports !== false) { |  | ||||||
| 
 |  | ||||||
|         const errors = that.findErrorsForStashedExports(); |  | ||||||
|         if (!errors) { |  | ||||||
|           newProxyStringRaw = that.state.stashedExports; |  | ||||||
|         } else { |  | ||||||
|           that.setState({ifExportsHaveErrors: true}); |  | ||||||
|           return that.props.funs.showErrors(...errors); |  | ||||||
|         } |  | ||||||
|       } |  | ||||||
|       doSwitch(); |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     showInvalidMessage(that, event) { |  | ||||||
| 
 |  | ||||||
|       that.props.funs.showErrors({message: event.target.validationMessage}); |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     handleTypeSelect(that, event) { |  | ||||||
| 
 |  | ||||||
|       that.state.newType = event.target.value; |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     handleSubmit(that, event) { |  | ||||||
| 
 |  | ||||||
|       !that.state.ifExportsMode ? that.handleAdd(that, event) : that.handleModeSwitch(that, event); |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     handleAdd(that, event) { |  | ||||||
| 
 |  | ||||||
|       const form = event.target; |  | ||||||
|       const elements = Array.from(form.elements).reduce((acc, el, index) => { |  | ||||||
| 
 |  | ||||||
|         acc[el.name || index] = el.value; |  | ||||||
|         el.value = ''; |  | ||||||
|         return acc; |  | ||||||
| 
 |  | ||||||
|       }, {}); |  | ||||||
|       const type = that.state.newType; |  | ||||||
|       const hostname = elements.hostname; |  | ||||||
|       const port = elements.port; |  | ||||||
| 
 |  | ||||||
|       that.setState({proxyStringRaw: `${that.state.proxyStringRaw} ${type} ${hostname}:${port};`.trim()}); |  | ||||||
| 
 |  | ||||||
|       event.preventDefault(); |  | ||||||
| 
 |  | ||||||
|     } |  | ||||||
|     render(props) { |  | ||||||
| 
 |  | ||||||
|       return ( |  | ||||||
|         <form onSubmit={linkEvent(this, this.handleSubmit)}> |  | ||||||
|           { |  | ||||||
|             !this.state.ifExportsMode |  | ||||||
|             ? (( |  | ||||||
|               <table class={scopedCss.editor}> |  | ||||||
|                 <thead> |  | ||||||
|                   <tr> |  | ||||||
|                     <th>протокол</th> <th>домен / IP</th> <th>порт</th> <th>{this.switchBtn}</th> |  | ||||||
|                   </tr> |  | ||||||
|                 </thead> |  | ||||||
|                 <tbody> |  | ||||||
|                   {/* ADD NEW PROXY STARTS. */} |  | ||||||
|                   <tr class={scopedCss.addPanel}> |  | ||||||
|                     <td> |  | ||||||
|                       <select reqiured |  | ||||||
|                         class={scopedCss.noPad} |  | ||||||
|                         name="proxyType" |  | ||||||
|                         onChange={linkEvent(this, this.handleTypeSelect)} |  | ||||||
|                       > |  | ||||||
|                         { |  | ||||||
|                           PROXY_TYPE_LABEL_PAIRS.map( |  | ||||||
|                             ([type, label]) => |  | ||||||
|                               (<option value={type} selected={type === this.state.newType}> |  | ||||||
|                                 {label || type} |  | ||||||
|                               </option>) |  | ||||||
|                           ) |  | ||||||
|                         } |  | ||||||
|                       </select> |  | ||||||
|                     </td> |  | ||||||
|                     <td> |  | ||||||
|                       {/* LAST-2: HOSTNAME */} |  | ||||||
|                       <input required |  | ||||||
|                         class={scopedCss.noPad} |  | ||||||
|                         placeholder="89.140.125.17" value={this.state.newHostname} |  | ||||||
|                         name="hostname" |  | ||||||
|                         onInvalid={linkEvent(this, this.showInvalidMessage)} |  | ||||||
|                       /> |  | ||||||
|                     </td> |  | ||||||
|                     <td> |  | ||||||
|                       {/* LAST-1: PORT */} |  | ||||||
|                       <input required type="number" |  | ||||||
|                         class={scopedCss.noPad + ' ' + scopedCss.padLeft} style="min-width: 4em" |  | ||||||
|                         placeholder="9150" value={this.state.newPort} |  | ||||||
|                         min="0" step="1" max={MAX_PORT} pattern="[0-9]{1,5}" |  | ||||||
|                         name="port" |  | ||||||
|                         onInvalid={linkEvent(this, this.showInvalidMessage)} |  | ||||||
|                         onkeydown={onlyPort} |  | ||||||
|                       /> |  | ||||||
|                     </td> |  | ||||||
|                     <td> |  | ||||||
|                       {/* LAST */} |  | ||||||
|                       <input type="submit" class={scopedCss.add + ' ' + scopedCss.only} title="Добавить прокси" value="+"/> |  | ||||||
|                     </td> |  | ||||||
|                   </tr> |  | ||||||
|                   {/* ADD NEW PROXY ENDS. */} |  | ||||||
|                   { |  | ||||||
|                     this.state.proxyStringRaw.split(/\s*;\s*/g).filter((s) => s).map((proxyAsString) => { |  | ||||||
| 
 |  | ||||||
|                       const [type, addr] = proxyAsString.trim().split(/\s/); |  | ||||||
|                       const [hostname, port] = addr.split(':'); |  | ||||||
|                       return ( |  | ||||||
|                         <tr class={scopedCss.proxyRow}> |  | ||||||
|                           <td>{type}</td><td>{hostname}</td><td>{port}</td> |  | ||||||
|                           <td> |  | ||||||
|                             <button title="Повысить приоритет">↑</button> |  | ||||||
|                             <br/> |  | ||||||
|                             <input type="submit" title="Удалить прокси" value="X"/> |  | ||||||
|                           </td> |  | ||||||
|                         </tr> |  | ||||||
|                       ); |  | ||||||
| 
 |  | ||||||
|                     }) |  | ||||||
|                   } |  | ||||||
|                 </tbody> |  | ||||||
|               </table> |  | ||||||
| 
 |  | ||||||
|             )) : (( |  | ||||||
| 
 |  | ||||||
|               <table class={scopedCss.editor}> |  | ||||||
|                 <thead> |  | ||||||
|                   <tr> |  | ||||||
|                     <th style="width: 100%"> |  | ||||||
|                       { |  | ||||||
|                         this.state.stashedExports === false |  | ||||||
|                           ? 'Жду изменений...' |  | ||||||
|                           : (this.state.ifExportsHaveErrors |  | ||||||
|                               ? (<span><a href="">Сбросьте изменения</a> или поправьте</span>) |  | ||||||
|                               : (<a href="">Сбросить изменения</a>) |  | ||||||
|                             ) |  | ||||||
|                       } |  | ||||||
|                     </th> |  | ||||||
|                     <th style="width: 1%">{this.switchBtn}</th> |  | ||||||
|                   </tr> |  | ||||||
|                 </thead> |  | ||||||
|                 <tbody> |  | ||||||
|                   <tr> |  | ||||||
|                     <td colspan="2"><textarea |  | ||||||
|                         class={scopedCss.textarea} |  | ||||||
|                         spellcheck={false} |  | ||||||
|                         placeholder={` |  | ||||||
| SOCKS5 localhost:9050; # Tor Expert |  | ||||||
| SOCKS5 localhost:9150; # Tor Browser |  | ||||||
| HTTPS 11.22.33.44:3143; |  | ||||||
| PROXY foobar.com:8080; # Not HTTP!`.trim()} |  | ||||||
|                         onChange={linkEvent(this, this.handleTextareaChange)} |  | ||||||
|                         value={ |  | ||||||
|                           this.state.stashedExports !== false |  | ||||||
|                             ? this.state.stashedExports |  | ||||||
|                             : this.state.proxyStringRaw.replace(/\s*;\s*/g, ';\n') |  | ||||||
|                         } |  | ||||||
|                       /></td> |  | ||||||
|                   </tr> |  | ||||||
|                 </tbody> |  | ||||||
|               </table> |  | ||||||
|             )) |  | ||||||
|           } |  | ||||||
|         </form> |  | ||||||
|       ); |  | ||||||
| 
 |  | ||||||
|     }; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
| }; |  | ||||||
|  | @ -1,44 +0,0 @@ | ||||||
| import Inferno from 'inferno'; |  | ||||||
| import Component from 'inferno-component'; |  | ||||||
| import css from 'csjs-inject'; |  | ||||||
| 
 |  | ||||||
| export default function getProxyEditor(theState) { |  | ||||||
| 
 |  | ||||||
|   const scopedCss = css` |  | ||||||
| 
 |  | ||||||
|     .texty { |  | ||||||
|       width: 100%; |  | ||||||
|       max-width: 38.5em; /* ~418px, layout breaks if more */ |  | ||||||
|       height: 7em; |  | ||||||
|       margin-top: 0.3em; |  | ||||||
|       font-size: 0.9em; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|   `; |  | ||||||
| 
 |  | ||||||
|   const uiRaw = 'ui-proxy-string-raw'; |  | ||||||
| 
 |  | ||||||
|   return class ProxyEditor extends Component { |  | ||||||
| 
 |  | ||||||
|     constructor(props) { |  | ||||||
|       super(props); |  | ||||||
|       this.state = {foo: 'BAR'}; |  | ||||||
|       props.funs.setStatusTo('Hello from editor!'); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     render(props) { |  | ||||||
|     return (<textarea class={scopedCss.texty} |  | ||||||
|       onFocus={() => alert('FFF')} |  | ||||||
|       spellcheck={false} |  | ||||||
|       placeholder={ |  | ||||||
| `SOCKS5 localhost:9050; # Tor Expert |  | ||||||
| SOCKS5 localhost:9150; # Tor Browser |  | ||||||
| HTTPS 11.22.33.44:3143; |  | ||||||
| PROXY foobar.com:8080; # Not HTTP!`.trim()} |  | ||||||
|       value={props.value || localStorage.getItem(uiRaw) || ''} |  | ||||||
|     />); |  | ||||||
| 
 |  | ||||||
|   }; |  | ||||||
|   } |  | ||||||
| 
 |  | ||||||
| }; |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user