diff --git a/extensions/chromium/runet-censorship-bypass/src/extension-common/35-pac-kitchen-api.js b/extensions/chromium/runet-censorship-bypass/src/extension-common/35-pac-kitchen-api.js index a2aa381..98e03c2 100644 --- a/extensions/chromium/runet-censorship-bypass/src/extension-common/35-pac-kitchen-api.js +++ b/extensions/chromium/runet-censorship-bypass/src/extension-common/35-pac-kitchen-api.js @@ -65,25 +65,27 @@ desc: 'Учитывать сайты, добавленные вручную. Только для своих прокси-серверов! Без своих прокси работать не будет.', order: 6, }, - ifProxyErrors: { - dflt: false, - category: 'exceptions', - label: 'проксировать выбранные ошибки', - desc: 'Предлагать добавить сайт в исключения при выбранных ошибках', - order: 7, - }, customProxyStringRaw: { dflt: '', category: 'ownProxies', label: 'использовать СВОИ прокси', url: 'https://rebrand.ly/ac-own-proxy', - order: 8, + order: 7, }, ifProxyMoreDomains: { + ifDisabled: true, dflt: false, category: 'ownProxies', label: 'проксировать .onion, .i2p и OpenNIC', desc: 'Проксировать особые домены. Необходима поддержка со стороны прокси.', + order: 8, + }, + ifProxyErrors: { + ifDisabled: true, + dflt: false, + category: 'ownProxies', + label: 'проксировать избранные ошибки', + desc: 'Предлагать добавить сайт в исключения при выбранных ошибках.', order: 9, }, diff --git a/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/choose-pac-provider/index.html b/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/choose-pac-provider/index.html index ed9397a..318f4fd 100644 --- a/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/choose-pac-provider/index.html +++ b/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/choose-pac-provider/index.html @@ -8,8 +8,10 @@ --ribbon-color: #4169e1; --blue-bg: dodgerblue; --default-grey: #bfbfbf; - --mild-hr: #d3d3d3; - --hr: #bababa; + --cr-options-headline: #d3d3d3; + --cr-icon-selected: #d7d7d7; + --cr-popup-border: #bababa; + --cr-grey-panel: #f2f2f2; max-width: 28em; } body { @@ -70,7 +72,7 @@ } hr { border: none; - border-top: 1px solid var(--hr); + border-top: 1px solid var(--cr-popup-border); margin: 0 0 0.6em 0; padding: 0; } @@ -143,12 +145,18 @@ section[data-for] { padding: 0.6em 0 1em; } + section[data-for] li label { + display: inline-block; /* Needed for ::first-letter below. */ + } + section[data-for] li label::first-letter { + text-transform: uppercase; + } :root.if-options-page section[data-for] { padding-bottom: 0.6em; } :root.if-options-page section[data-for]:not(:last-child), - .underlined { - border-bottom: 1px solid var(--mild-hr); + .underlined { + border-bottom: 1px solid var(--cr-options-headline); } /* HIDE starts. */ @@ -157,8 +165,8 @@ :root:not(.if-options-page) #acc-own-mods:not(:checked) ~ .main-nav section[data-for="acc-own-mods"], :root:not(.if-options-page) #acc-mods:not(:checked) ~ .main-nav section[data-for="acc-mods"], :root:not(.if-options-page) #acc-ntf:not(:checked) ~ .main-nav section[data-for="acc-ntf"], - /* One button shared between two sections: */ - :root:not(.if-options-page) #acc-own-mods:not(:checked) + #acc-mods:not(:checked) ~ .main-nav #apply-mods-button + /* One button shared between two sections: */ + :root:not(.if-options-page) #acc-own-mods:not(:checked) + #acc-mods:not(:checked) ~ .main-nav #apply-mods-section { /* Hide, but preclude width resizes. */ height: 0px !important; @@ -177,8 +185,8 @@ :root:not(.if-options-page) #acc-own-mods:not(:checked) ~ .main-nav section[data-for="acc-own-mods"] *, :root:not(.if-options-page) #acc-mods:not(:checked) ~ .main-nav section[data-for="acc-mods"] *, :root:not(.if-options-page) #acc-ntf:not(:checked) ~ .main-nav section[data-for="acc-ntf"] *, - /* One button shared between two sections: */ - :root:not(.if-options-page) #acc-own-mods:not(:checked) + #acc-mods:not(:checked) ~ .main-nav #apply-mods-button * + /* One button shared between two sections: */ + :root:not(.if-options-page) #acc-own-mods:not(:checked) + #acc-mods:not(:checked) ~ .main-nav #apply-mods-section * { margin-top: 0 !important; margin-bottom: 0 !important; @@ -186,7 +194,7 @@ /* HIDE ends. */ .nav-labels { - background-color: var(--chrome-grey); + background-color: var(--cr-grey-panel); text-align: center; } .nav-labels li label { @@ -242,6 +250,11 @@ /* INFO SIGNS */ + input:disabled + .label-container label { + color: var(--default-grey); + pointer-events: none; + } + .info-row { position: relative; } @@ -302,7 +315,7 @@ width: calc(25% + 0.6em); } - /* TAB_1 PAC PROVIDER */ + /* TAB_1: PAC PROVIDER */ .update-button { visibility: hidden; @@ -323,14 +336,8 @@ margin-top: 0.5em; } - /* TAB_2 PAC MODS */ + /* TAB_2: PAC MODS */ - #pac-mods label { - display: block; - } - #pac-mods label:first-letter { - text-transform: uppercase; - } #mods-custom-proxy-string-raw ~ textarea { width: 100%; height: 7em; @@ -341,53 +348,63 @@ display: none; } - /* TAB_3 EXCEPTIONS */ - #exc-address-container { - display: flex; - align-items: center; - width: 100%; - } - #exc-address-container > a { - border-bottom: 1px solid transparent; - margin-left: 0.2em; - } - #exc-address { - width: 100%; - display: flex; - align-items: baseline; - --exc-hieght: 1.6em; - font-size: 1em; - border-bottom: 1px solid var(--ribbon-color) !important; - } - input#exc-editor { - border: none; - width: 100%; - background: inherit; - /* The two below align '.' (dot) vertically. */ - max-height: var(--exc-hieght) !important; - min-height: var(--exc-hieght) !important; - } - #exc-radio { - display: flex; - justify-content: space-around; - margin-top: 0.5em; - } - [name="if-proxy-this-site"]:checked + label { - font-weight: bold; - } - #exc-address.if-yes { - background-color: lightgreen; - } - #exc-address.if-no { - background-color: pink; - } + /* TAB_3: EXCEPTIONS */ - option.if-proxied { - color: var(--ribbon-color); - } - option:not(.if-proxied) { - color: red; - } + /* EXC-EDITOR starts. */ + #exc-address-container { + display: flex; + align-items: center; + width: 100%; + } + #exc-address-container > a { + border-bottom: 1px solid transparent; + margin-left: 0.2em; + } + #exc-address { + width: 100%; + display: flex; + align-items: baseline; + --exc-hieght: 1.6em; + font-size: 1em; + border-bottom: 1px solid var(--ribbon-color) !important; + } + input#exc-editor { + border: none; + width: 100%; + background: inherit; + /* The two below align '.' (dot) vertically. */ + max-height: var(--exc-hieght) !important; + min-height: var(--exc-hieght) !important; + } + #exc-radio { + display: flex; + justify-content: space-around; + margin-top: 0.5em; + } + [name="if-proxy-this-site"]:checked + label { + font-weight: bold; + } + #exc-address.if-yes { + background-color: lightgreen; + } + #exc-address.if-no { + background-color: pink; + } + + option.if-proxied { + color: var(--ribbon-color); + } + option:not(.if-proxied) { + color: red; + } + + /* EXC-EDITOR ends. */ + #exc-mods { + padding-top: 1em; + } + #exc-mods input#mods-if-mind-exceptions:not(:checked) + .label-container label { + color: red; + } /* CONTROL RAW = BUTTON + LINK */ @@ -401,7 +418,7 @@ margin: 1em 0 1em 0; } - .hor-flex > input:not([type="button"]) { + .hor-flex input:not([type="button"]) { align-self: flex-end; } .label-container { @@ -495,41 +512,44 @@
-
Проксировать указанный сайт?
-
-
- *. -
- - -
- -
    -
  1. -
  2. -
  3. -
  4. -
+ > + + + +
    +
  1. + +
  2. +
  3. +
  4. +
+
+
- +
-
- - К изначальным! -
+
+ + К изначальным! +
Я yведомления:
diff --git a/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/choose-pac-provider/index.js b/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/choose-pac-provider/index.js index 957deb7..26b60f6 100644 --- a/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/choose-pac-provider/index.js +++ b/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/choose-pac-provider/index.js @@ -1,13 +1,21 @@ 'use strict'; const START = Date.now(); +{ -document.getElementById('pac-mods').onchange = function() { + const enableButton = function enablebutton() { - this.classList.add('changed'); - document.getElementById('apply-mods').disabled = false; + this.classList.add('changed'); + document.getElementById('apply-mods').disabled = false; -}; + }; + ['pac-mods', 'own-mods'].forEach((id) => { + + document.getElementById(id).onchange = enableButton; + + }); + +} chrome.runtime.getBackgroundPage( (backgroundPage) => backgroundPage.apis.errorHandlers.installListenersOn( @@ -131,7 +139,13 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => const inputs = document.querySelectorAll('input'); for ( let i = 0; i < inputs.length; i++ ) { - inputs[i].disabled = val === 'on' ? false : true; + const input = inputs[i]; + if (val === 'off') { + input.dataset.previousDisabledValue = input.disabled; + input.disabled = true; + } else { + input.disabled = input.dataset.previousDisabledValue === 'true'; + } } }; @@ -176,18 +190,22 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => const appendInfoRow = (mountEl, conf, inputTypeName, inputId, htmlAfterLabel = '') => { mountEl.classList.add('info-row', 'hor-flex'); + if (conf.ifDisabled) { + mountEl.title = 'В РАЗРАБОТКЕ!'; + } mountEl.innerHTML = ` - +
- + ${htmlAfterLabel}
` + (conf.desc ? infoSign(conf.desc) : infoUrl(conf.url)); }; - { - const ul = document.querySelector('#list-of-providers'); - const _firstChild = ul.firstChild; + { // PAC-PROVIDERS starts. + + const ul = document.getElementById('list-of-providers'); + const _firstChildOrNull = ul.firstChild; for( const provConf of antiCensorRu.getSortedEntriesForProviders() ) { @@ -204,16 +222,11 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => ); return false; }; - ul.insertBefore( li, _firstChild ); + ul.insertBefore( li, _firstChildOrNull ); } checkChosenProvider(); - } - const radios = [].slice.apply( - document.querySelectorAll('[name=pacProvider]') - ); - for(const radio of radios) { - radio.onclick = function(event) { + const radioClickHandler = function radioClickHandler(event) { if ( event.target.id === ( @@ -240,7 +253,14 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => } return false; }; - } + + document.querySelectorAll('input[name=pacProvider]').forEach((radio) => { + + radio.onclick = radioClickHandler; + + }); + + } // PAC-PROVIDERS ends. // IF MINI @@ -266,275 +286,337 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => { // KITCHEN PANELS starts. const pacKitchen = backgroundPage.apis.pacKitchen; + const camelToDash = (name) => name.replace(/([A-Z])/g, (_, p) => '-' + p.toLowerCase()); + const modKeyToLi = {}; + + const applyMods = function applyMods(newMods) { + + conduct( + 'Применяем настройки...', + (cb) => pacKitchen.keepCookedNowAsync(newMods, cb), + 'Настройки применены.', + () => { + + document.getElementById('apply-mods').disabled = true; + + } + ); + + }; { // EXCEPTIONS TAB starts. - const excEditor = document.getElementById('exc-editor'); + { // EXC-MODS starts. - const validateHost = function validateHost(host) { + const emodsList = document.getElementById('exc-mods'); + const _firstChildOrNull = emodsList.firstChild; - const ValidHostnameRegex = /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/; - if(!ValidHostnameRegex.test(host)) { - showErrors(new TypeError('Должно быть только доменное имя, без протокола, порта и пути. Попробуйте ещё раз.')); - return false; - } - return true; + for(const conf of pacKitchen.getOrderedConfigs('exceptions')) { - }; + const key = conf.key; + const iddy = 'mods-' + camelToDash(conf.key); + const li = document.createElement('li'); + appendInfoRow(li, conf, `type="checkbox" ${conf.value ? 'checked' : ''}`, iddy); + emodsList.insertBefore( li, _firstChildOrNull ); + modKeyToLi[key] = li; + li.querySelector('input').onclick = function() { - const labelIfProxied = '✔'; - const labelIfNotProxied = '✘'; - const labelIfAuto = '↻'; + const oldMods = pacKitchen.getPacMods(); + oldMods[key] = this.checked; + applyMods(oldMods); - const addOption = function addOption(host, yesNoUndefined) { - - const opt = document.createElement('option'); - // `value` may be changed for hiding line in the tooltip. - opt.value = host; - opt.dataset.host = host; - switch(yesNoUndefined) { - case true: - opt.label = labelIfProxied; - break; - case false: - opt.label = labelIfNotProxied; - break; - default: - opt.label = labelIfAuto; - } - const editorHost = excEditor.value.trim(); - if (host === editorHost) { - excList.insertBefore( opt, excList.firstChild ); - } else { - excList.appendChild(opt); - } - return opt; - - }; - - const thisYes = document.getElementById('this-yes'); - const thisNo = document.getElementById('this-no'); - const thisAuto = document.getElementById('this-auto'); - const yesClass = 'if-yes'; - const noClass = 'if-no'; - - function moveCursorIfNeeded() { - - const nu = excEditor.dataset.moveCursorTo; - if(nu !== undefined) { - excEditor.setSelectionRange(nu, nu); - delete excEditor.dataset.moveCursorTo; - } - - } - - const hideOpt = (opt) => opt.value = '\n'; - const unhideOptAndAddSpace = (opt) => opt.value = opt.dataset.host + ' '; - - const excList = document.getElementById('exc-list'); - - excEditor.onkeydown = function(event) { - - moveCursorIfNeeded(); - if(event.key === 'Enter') { - // Hide all. - excList.childNodes.forEach( hideOpt ); - } - return true; - - }; - - const renderExceptionsPanelFromExcList = function renderExceptionsPanelFromExcList(event) { - - // If triangle button on right of datalist input clicked. - - let ifTriangleClicked = false; - const ifClick = event && event.type === 'click'; - - { - const maxIndentFromRightInPx = 15; - ifTriangleClicked = ifClick - && !excEditor.selectionStart && !excEditor.selectionEnd - && event.x > excEditor.getBoundingClientRect().right - maxIndentFromRightInPx; - } - - const setInputValue = (newValue) => { - - if (ifClick && !ifTriangleClicked) { - // Don't jerk cursor on simple clicks. - return; - } - // See bug in my comment to http://stackoverflow.com/a/32394157/521957 - // First click on empty input may be still ignored. - const nu = excEditor.selectionStart + newValue.length - excEditor.value.length; - excEditor.value = newValue; - excEditor.dataset.moveCursorTo = nu; - window.setTimeout(moveCursorIfNeeded, 0); + }; }; - const originalHost = excEditor.value.trim(); - const ifInit = !event; - const currentHost = ifTriangleClicked ? '' : (originalHost || (ifInit ? '' : ' ')); - setInputValue(currentHost); + }// EXC-MODS ends. - let exactOpt = false; - let editedOpt = false; - excList.childNodes.forEach( - (opt) => { + { // EXC-EDITOR starts. - unhideOptAndAddSpace(opt); + const excEditor = document.getElementById('exc-editor'); - if(opt.label === labelIfAuto) { - editedOpt = opt; + const validateHost = function validateHost(host) { + + const ValidHostnameRegex = /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/; + if(!ValidHostnameRegex.test(host)) { + showErrors(new TypeError('Должно быть только доменное имя, без протокола, порта и пути. Попробуйте ещё раз.')); + return false; + } + return true; + + }; + + const labelIfProxied = '✔'; + const labelIfNotProxied = '✘'; + const labelIfAuto = '↻'; + + const addOption = function addOption(host, yesNoUndefined) { + + const opt = document.createElement('option'); + // `value` may be changed for hiding line in the tooltip. + opt.value = host; + opt.dataset.host = host; + switch(yesNoUndefined) { + case true: + opt.label = labelIfProxied; + break; + case false: + opt.label = labelIfNotProxied; + break; + default: + opt.label = labelIfAuto; + } + const editorHost = excEditor.value.trim(); + if (host === editorHost) { + excList.insertBefore( opt, excList.firstChild ); + } else { + excList.appendChild(opt); + } + return opt; + + }; + + const thisYes = document.getElementById('this-yes'); + const thisNo = document.getElementById('this-no'); + const thisAuto = document.getElementById('this-auto'); + const yesClass = 'if-yes'; + const noClass = 'if-no'; + + function moveCursorIfNeeded() { + + const nu = excEditor.dataset.moveCursorTo; + if(nu !== undefined) { + excEditor.setSelectionRange(nu, nu); + delete excEditor.dataset.moveCursorTo; + } + + } + + const hideOpt = (opt) => opt.value = '\n'; + const unhideOptAndAddSpace = (opt) => opt.value = opt.dataset.host + ' '; + + const excList = document.getElementById('exc-list'); + + excEditor.onkeydown = function(event) { + + moveCursorIfNeeded(); + if(event.key === 'Enter') { + // Hide all. + excList.childNodes.forEach( hideOpt ); + } + return true; + + }; + + const renderExceptionsPanelFromExcList = function renderExceptionsPanelFromExcList(event) { + + // If triangle button on right of datalist input clicked. + + let ifTriangleClicked = false; + const ifClick = event && event.type === 'click'; + + { + const maxIndentFromRightInPx = 15; + ifTriangleClicked = ifClick + && !excEditor.selectionStart && !excEditor.selectionEnd + && event.x > excEditor.getBoundingClientRect().right - maxIndentFromRightInPx; + } + + const setInputValue = (newValue) => { + + if (ifClick && !ifTriangleClicked) { + // Don't jerk cursor on simple clicks. return; } - if (opt.dataset.host === originalHost) { - exactOpt = opt; + // See bug in my comment to http://stackoverflow.com/a/32394157/521957 + // First click on empty input may be still ignored. + const nu = excEditor.selectionStart + newValue.length - excEditor.value.length; + excEditor.value = newValue; + excEditor.dataset.moveCursorTo = nu; + window.setTimeout(moveCursorIfNeeded, 0); + + }; + + const originalHost = excEditor.value.trim(); + const ifInit = !event; + const currentHost = ifTriangleClicked ? '' : (originalHost || (ifInit ? '' : ' ')); + setInputValue(currentHost); + + let exactOpt = false; + let editedOpt = false; + excList.childNodes.forEach( + (opt) => { + + unhideOptAndAddSpace(opt); + + if(opt.label === labelIfAuto) { + editedOpt = opt; + return; + } + if (opt.dataset.host === originalHost) { + exactOpt = opt; + } + } + ); - } - ); + thisAuto.checked = true; + excEditor.parentNode.classList.remove(noClass, yesClass); - thisAuto.checked = true; - excEditor.parentNode.classList.remove(noClass, yesClass); - - const ifInputEmpty = !originalHost; - if (ifTriangleClicked || ifInputEmpty) { - // Show all opts. - if (editedOpt) { - // Example of editedOpt.value: 'abcde ' <- Mind the space (see unhideOptAndAddSpace)! - const ifBackspacedOneChar = ifInputEmpty && editedOpt.value.length < 3; - if (ifBackspacedOneChar) { - editedOpt.remove(); + const ifInputEmpty = !originalHost; + if (ifTriangleClicked || ifInputEmpty) { + // Show all opts. + if (editedOpt) { + // Example of editedOpt.value: 'abcde ' <- Mind the space (see unhideOptAndAddSpace)! + const ifBackspacedOneChar = ifInputEmpty && editedOpt.value.length < 3; + if (ifBackspacedOneChar) { + editedOpt.remove(); + } } - } - return true; - } - - if (editedOpt) { - const ifEditedOptAlreadyExists = editedOpt.dataset.host === originalHost; - if(ifEditedOptAlreadyExists) { - hideOpt(editedOpt); return true; } - // Not exact! Update! - editedOpt.remove(); - } - if (!exactOpt) { - editedOpt = addOption(originalHost, undefined); - if (!ifClick) { - // New value was typed -- don't show tooltip. - hideOpt(editedOpt); - } - return true; - } - - // Exact found! - excList.childNodes.forEach(hideOpt); - if(exactOpt.label === labelIfProxied) { - thisYes.checked = true; - excEditor.parentNode.classList.add(yesClass); - } else { - thisNo.checked = true; - excEditor.parentNode.classList.add(noClass); - } - return true; - - }; - - excEditor.onclick = excEditor.oninput = renderExceptionsPanelFromExcList; - - if (currentTab && !currentTab.url.startsWith('chrome')) { - excEditor.value = new URL(currentTab.url).hostname; - } else { - // Show placeholder. - excEditor.value = ''; - } - - { // Populate selector. - - const pacMods = pacKitchen.getPacMods(); - for(const host of Object.keys(pacMods.exceptions || {}).sort()) { - addOption(host, pacMods.exceptions[host]); - } - renderExceptionsPanelFromExcList(); // Colorize input. - - } - - document.getElementById('exc-radio').onclick = function(event) { - - /* ON CLICK */ - if(event.target.tagName !== 'INPUT') { - // Only label on checkbox. - return true; - } - - const host = excEditor.value.trim(); - - const pacMods = pacKitchen.getPacMods(); - pacMods.exceptions = pacMods.exceptions || {}; - - let fixOptions; - const curOptOrNull = excList.querySelector(`[data-host="${host}"]`); - - if (thisAuto.checked) { - delete pacMods.exceptions[host]; - fixOptions = () => { - curOptOrNull && curOptOrNull.remove(); - } - } else { - // YES or NO checked. - const ifYesClicked = thisYes.checked; - if (!validateHost(host)) { - return false; - } - if (ifYesClicked && !pacMods.filteredCustomsString) { - showErrors( new TypeError( - 'Проксировать СВОИ сайты можно только при наличии СВОИХ прокси (см. «Модификаторы» ). Нет своих прокси, удовлетворяющих вашим требованиям.' - )); - return false; - } - //const ifNew = !(host in pacMods.exceptions); - pacMods.exceptions[host] = ifYesClicked; - // Change label. - fixOptions = () => { - if (curOptOrNull) { - curOptOrNull.label = ifYesClicked ? labelIfProxied : labelIfNotProxied; - } else { - addOption(host, ifYesClicked); + if (editedOpt) { + const ifEditedOptAlreadyExists = editedOpt.dataset.host === originalHost; + if(ifEditedOptAlreadyExists) { + hideOpt(editedOpt); + return true; } - }; + // Not exact! Update! + editedOpt.remove(); + } + + if (!exactOpt) { + editedOpt = addOption(originalHost, undefined); + if (!ifClick) { + // New value was typed -- don't show tooltip. + hideOpt(editedOpt); + } + return true; + } + + // Exact found! + excList.childNodes.forEach(hideOpt); + if(exactOpt.label === labelIfProxied) { + thisYes.checked = true; + excEditor.parentNode.classList.add(yesClass); + } else { + thisNo.checked = true; + excEditor.parentNode.classList.add(noClass); + } + return true; + + }; + + excEditor.onclick = excEditor.oninput = renderExceptionsPanelFromExcList; + + if (currentTab && !currentTab.url.startsWith('chrome')) { + excEditor.value = new URL(currentTab.url).hostname; + } else { + // Show placeholder. + excEditor.value = ''; } - conduct( - 'Применяем исключения...', - (cb) => pacKitchen.keepCookedNowAsync(pacMods, cb), - 'Исключения применены. Не забывайте о кэше!', - () => { - - fixOptions(); - // Window may be closed before this line executes. - renderExceptionsPanelFromExcList(); + { // Populate selector. + const pacMods = pacKitchen.getPacMods(); + for(const host of Object.keys(pacMods.exceptions || {}).sort()) { + addOption(host, pacMods.exceptions[host]); } - ); - return false; // Don't check before operation is finished. + renderExceptionsPanelFromExcList(); // Colorize input. - }; + } + + document.getElementById('exc-radio').onclick = function(event) { + + /* ON CLICK */ + if(event.target.tagName !== 'INPUT') { + // Only label on checkbox. + return true; + } + + const host = excEditor.value.trim(); + + const pacMods = pacKitchen.getPacMods(); + pacMods.exceptions = pacMods.exceptions || {}; + + let fixOptions; + const curOptOrNull = excList.querySelector(`[data-host="${host}"]`); + + if (thisAuto.checked) { + delete pacMods.exceptions[host]; + fixOptions = () => { + curOptOrNull && curOptOrNull.remove(); + } + } else { + // YES or NO checked. + const ifYesClicked = thisYes.checked; + if (!validateHost(host)) { + return false; + } + if (ifYesClicked && !pacMods.filteredCustomsString) { + showErrors( new TypeError( + 'Проксировать СВОИ сайты можно только при наличии СВОИХ прокси (см. «Модификаторы» ). Нет своих прокси, удовлетворяющих вашим требованиям.' + )); + return false; + } + //const ifNew = !(host in pacMods.exceptions); + pacMods.exceptions[host] = ifYesClicked; + // Change label. + fixOptions = () => { + if (curOptOrNull) { + curOptOrNull.label = ifYesClicked ? labelIfProxied : labelIfNotProxied; + } else { + addOption(host, ifYesClicked); + } + }; + } + + conduct( + 'Применяем исключения...', + (cb) => pacKitchen.keepCookedNowAsync(pacMods, cb), + 'Исключения применены. Не забывайте о кэше!', + () => { + + fixOptions(); + // Window may be closed before this line executes. + renderExceptionsPanelFromExcList(); + + } + ); + return false; // Don't check before operation is finished. + + }; + + } // EXC-EDITOR ends. } // EXCEPTIONS TAB ends. - const camelToDash = (name) => name.replace(/([A-Z])/g, (_, p) => '-' + p.toLowerCase()); + { // PAC MODS TAB starts. + + const modsList = document.getElementById('pac-mods'); + const _firstChildOrNull = modsList.firstChild; + + for(const conf of pacKitchen.getOrderedConfigs('general')) { + + const key = conf.key; + const iddy = 'mods-' + camelToDash(conf.key); + const li = document.createElement('li'); + appendInfoRow(li, conf, `type="checkbox" ${conf.value ? 'checked' : ''}`, iddy); + modsList.insertBefore( li, _firstChildOrNull ); + modKeyToLi[key] = li; + + }; + + } // PAC MODS TAB ends. + + const customProxyStringKey = 'customProxyStringRaw'; + const uiRaw = 'ui-proxy-string-raw'; { // OWN PROXIES TAB starts. - const ownsList = document.getElementById('own-proxies'); - const _firstChild = ownsList.firstChild; - const keyToLi = {}; - const customProxyStringKey = 'customProxyStringRaw'; - const uiRaw = 'ui-proxy-string-raw'; + const ownsList = document.getElementById('own-mods'); + const _firstChildOrNull = ownsList.firstChild; for(const conf of pacKitchen.getOrderedConfigs('ownProxies')) { @@ -561,39 +643,26 @@ PROXY foobar.com:8080; # Not HTTP!">${conf.value || localStorage.getItem(uiRaw) }; } - ownsList.insertBefore( li, _firstChild ); + ownsList.insertBefore( li, _firstChildOrNull ); + modKeyToLi[key] = li; } } // OWN PROXIES TAB ends. - { // PAC MODS TAB starts. + { // APPLY MODS PANEL starts. - const modsList = document.getElementById('pac-mods'); - const _firstChild = modsList.firstChild; - const keyToLi = {}; - - for(const conf of pacKitchen.getOrderedConfigs('general')) { - - const key = conf.key; - const iddy = 'mods-' + camelToDash(conf.key); - const li = document.createElement('li'); - appendInfoRow(li, conf, `type="checkbox" ${conf.value ? 'checked' : ''}`, iddy); - keyToLi[key] = li; - modsList.insertBefore( li, _firstChild ); - - }; document.getElementById('apply-mods').onclick = () => { const oldMods = pacKitchen.getPacMods(); - for(const key of Object.keys(keyToLi)) { - oldMods[key] = keyToLi[key].querySelector('input').checked; + for(const key of Object.keys(modKeyToLi)) { + oldMods[key] = modKeyToLi[key].querySelector('input').checked; }; { // OWN PROXY - const liPs = keyToLi[customProxyStringKey]; + const liPs = modKeyToLi[customProxyStringKey]; oldMods[customProxyStringKey] = liPs.querySelector('input').checked && liPs.querySelector('textarea').value.trim(); @@ -621,17 +690,7 @@ PROXY foobar.com:8080; # Not HTTP!">${conf.value || localStorage.getItem(uiRaw) } } - - conduct( - 'Применяем настройки...', - (cb) => pacKitchen.keepCookedNowAsync(oldMods, cb), - 'Настройки применены.', - () => { - - document.getElementById('apply-mods').disabled = true; - - } - ); + applyMods(oldMods); }; @@ -653,9 +712,9 @@ PROXY foobar.com:8080; # Not HTTP!">${conf.value || localStorage.getItem(uiRaw) () => window.close() ); - }; + } - } // PAC MODS TAB ends. + } // APPLY MODS PANEL ends. } // KITCHEN PANELS ends. diff --git a/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/exceptions/index.js b/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/exceptions/index.js index a20eb9d..78d3f5e 100644 --- a/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/exceptions/index.js +++ b/extensions/chromium/runet-censorship-bypass/src/extension-common/pages/exceptions/index.js @@ -16,7 +16,8 @@ chrome.runtime.getBackgroundPage( (backgroundPage) => # Комментарии НЕ сохраняются! # Сначала идёт список проксируемых сайтов, # затем ==== на отдельной строке, -# затем исключённые сайты, отсортированные с конца строки. +# затем исключённые сайты. +# Сортировка — с конца строки. # ПРОКСИРОВАТЬ: