mirror of
				https://github.com/anticensority/runet-censorship-bypass.git
				synced 2025-10-30 23:47:56 +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; | ||||
|     } | ||||
|     /* PROXY ROW */ | ||||
|     table.editor tr.proxyRow td:first-child { | ||||
|     table.editor tr.proxyRow td:nth-child(2) { | ||||
|       text-align: center; | ||||
|     } | ||||
| 
 | ||||
|  | @ -78,7 +78,8 @@ export default function getProxyEditor(theState) { | |||
|     } | ||||
| 
 | ||||
|     /* 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; | ||||
|       padding: 0; | ||||
|       position: relative; | ||||
|  | @ -123,6 +124,10 @@ export default function getProxyEditor(theState) { | |||
|     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']]; | ||||
| 
 | ||||
| 
 | ||||
|  | @ -181,12 +186,35 @@ export default function getProxyEditor(theState) { | |||
|       const hostname = elements.hostname; | ||||
|       const port = elements.port; | ||||
| 
 | ||||
|       that.props.updateProxyStringRaw( | ||||
|       that.props.setProxyStringRaw( | ||||
|         `${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) { | ||||
| 
 | ||||
|       event.preventDefault(); | ||||
|  | @ -201,7 +229,7 @@ export default function getProxyEditor(theState) { | |||
|           <table class={scopedCss.editor}> | ||||
|             <thead> | ||||
|               <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)}/> | ||||
|                 </th> | ||||
|               </tr> | ||||
|  | @ -209,7 +237,7 @@ export default function getProxyEditor(theState) { | |||
|             <tbody> | ||||
|               {/* ADD NEW PROXY STARTS. */} | ||||
|               <tr class={scopedCss.addPanel}> | ||||
|                 <td> | ||||
|                 <td colspan="2"> | ||||
|                   <select reqiured | ||||
|                     class={scopedCss.noPad} | ||||
|                     name="proxyType" | ||||
|  | @ -232,6 +260,7 @@ export default function getProxyEditor(theState) { | |||
|                     placeholder="89.140.125.17" | ||||
|                     name="hostname" | ||||
|                     onInvalid={linkEvent(this, this.showInvalidMessage)} | ||||
|                     tabindex="1" | ||||
|                   /> | ||||
|                 </td> | ||||
|                 <td> | ||||
|  | @ -243,6 +272,7 @@ export default function getProxyEditor(theState) { | |||
|                     name="port" | ||||
|                     onInvalid={linkEvent(this, this.showInvalidMessage)} | ||||
|                     onkeydown={onlyPort} | ||||
|                     tabindex="2" | ||||
|                   /> | ||||
|                 </td> | ||||
|                 <td> | ||||
|  | @ -255,17 +285,23 @@ export default function getProxyEditor(theState) { | |||
|               </tr> | ||||
|               {/* 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(':'); | ||||
|                   return ( | ||||
|                     <tr class={scopedCss.proxyRow}> | ||||
|                       <td>{type}</td><td>{hostname}</td><td>{port}</td> | ||||
|                       <td> | ||||
|                         <button type="button" title="Повысить приоритет">↑</button> | ||||
|                         <br/> | ||||
|                         {/*<input type="submit" title="Удалить прокси" value="X"/>*/} | ||||
|                         <button type="button" | ||||
|                           class={scopedCss.only} title="Удалить" | ||||
|                           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> | ||||
|                     </tr> | ||||
|                   ); | ||||
|  | @ -279,14 +315,25 @@ export default function getProxyEditor(theState) { | |||
|     } | ||||
|   } | ||||
| 
 | ||||
|   const getInitState = () => ({ | ||||
|     ifHasErrors: false, | ||||
|     stashedExports: false, | ||||
|   }); | ||||
| 
 | ||||
|   class ExportsEditor extends Component { | ||||
| 
 | ||||
|     constructor(props) { | ||||
| 
 | ||||
|       super(props); | ||||
|       this.state = { | ||||
|         ifHasErrors: false, | ||||
|         stashedExports: false, | ||||
|       }; | ||||
|       this.state = getInitState(); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     resetState(that, event) { | ||||
| 
 | ||||
|       that.setState(getInitState()); | ||||
|       event.preventDefault(); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     getErrorsInStashedExports() { | ||||
|  | @ -294,10 +341,7 @@ export default function getProxyEditor(theState) { | |||
|       if(this.state.stashedExports === false) { | ||||
|         return; | ||||
|       } | ||||
|       const errors = this.state.stashedExports.trim() | ||||
|         .replace(/#.*$/mg, '') | ||||
|         .split(/\s*;\s*/) | ||||
|         .filter((s) => s) | ||||
|       const errors = splitBySemi(this.state.stashedExports) | ||||
|         .map((proxyAsString) => { | ||||
| 
 | ||||
|           const [rawType, addr, ...rest] = proxyAsString.split(/\s+/); | ||||
|  | @ -340,7 +384,7 @@ export default function getProxyEditor(theState) { | |||
|           that.props.funs.showErrors(...errors); | ||||
|           return; | ||||
|         } | ||||
|         that.props.updateProxyStringRaw(that.state.stashedExports); | ||||
|         that.props.setProxyStringRaw(that.state.stashedExports); | ||||
|       } | ||||
|       that.setState({ | ||||
|         stashedExports: false, | ||||
|  | @ -352,11 +396,9 @@ export default function getProxyEditor(theState) { | |||
| 
 | ||||
|     handleTextareaChange(that, event) { | ||||
| 
 | ||||
|       let newVal = event.target.value.trim(); | ||||
|       if (newVal && !newVal.endsWith(';')) { | ||||
|         newVal += ';'; | ||||
|       } | ||||
|       that.setState({stashedExports: newVal}); | ||||
|       that.setState({ | ||||
|         stashedExports: normilizeProxyString(event.target.value), | ||||
|       }); | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|  | @ -369,6 +411,8 @@ export default function getProxyEditor(theState) { | |||
| 
 | ||||
|     render(props) { | ||||
| 
 | ||||
|       const reset = linkEvent(this, this.resetState); | ||||
| 
 | ||||
|       return ( | ||||
|         <form onSubmit={linkEvent(this, this.handleSubmit)}> | ||||
|           <table class={scopedCss.editor}> | ||||
|  | @ -379,8 +423,8 @@ export default function getProxyEditor(theState) { | |||
|                     this.state.stashedExports === false | ||||
|                       ? 'Жду изменений...' | ||||
|                       : (this.state.ifHasErrors | ||||
|                           ? (<span><a href="">Сбросьте изменения</a> или поправьте</span>) | ||||
|                           : (<a href="">Сбросить изменения</a>) | ||||
|                           ? (<span><a href="" onClick={reset}>Сбросьте изменения</a> или поправьте</span>) | ||||
|                           : (<a href="" onClick={reset}>Сбросить изменения</a>) | ||||
|                         ) | ||||
|                   } | ||||
|                 </th> | ||||
|  | @ -440,7 +484,7 @@ PROXY foobar.com:8080; # Not HTTP!`.trim()} | |||
|       const props = Object.assign({ | ||||
|         proxyStringRaw: this.state.proxyStringRaw, | ||||
|         onSwitch: this.handleSwitch, | ||||
|         updateProxyStringRaw: (newVal) => this.setState({proxyStringRaw: newVal}), | ||||
|         setProxyStringRaw: (newVal) => this.setState({proxyStringRaw: newVal}), | ||||
|       }, originalProps); | ||||
|        | ||||
|       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