mirror of
https://github.com/anticensority/runet-censorship-bypass.git
synced 2024-11-30 13:23:44 +03:00
Mend exceptions and their UI
This commit is contained in:
parent
b0cc0e1f2c
commit
36a86be3d4
|
@ -9,6 +9,7 @@
|
|||
const kitchenStartsMark = '\n\n//%#@@@@@@ PAC_KITCHEN_STARTS @@@@@@#%';
|
||||
const kitchenState = window.utils.createStorage('pac-kitchen-');
|
||||
const ifIncontinence = 'if-incontinence';
|
||||
const modsKey = 'mods';
|
||||
|
||||
// Don't keep objects in defaults or at least freeze them!
|
||||
const configs = {
|
||||
|
@ -45,6 +46,9 @@
|
|||
},
|
||||
exceptions: {
|
||||
dflt: null,
|
||||
},
|
||||
ifMindExceptions: {
|
||||
dflt: true,
|
||||
label: 'учитывать исключения',
|
||||
desc: 'Учитывать сайты, добавленные вручную. Только для своих прокси! Без своих прокси работать не будет.',
|
||||
index: 5,
|
||||
|
@ -71,7 +75,7 @@
|
|||
|
||||
const getCurrentConfigs = function getCurrentConfigs() {
|
||||
|
||||
const mods = kitchenState('mods');
|
||||
const mods = kitchenState(modsKey);
|
||||
return new PacModifiers(mods || {});
|
||||
|
||||
};
|
||||
|
@ -82,9 +86,11 @@
|
|||
return Object.keys(configs).reduce((arr, key) => {
|
||||
|
||||
const conf = configs[key]
|
||||
if(typeof(conf.index) === 'number') {
|
||||
arr[conf.index] = conf;
|
||||
conf.value = pacMods[key];
|
||||
conf.key = key;
|
||||
}
|
||||
return arr;
|
||||
|
||||
}, []);
|
||||
|
@ -132,7 +138,9 @@
|
|||
this.filteredCustomsString = '';
|
||||
}
|
||||
|
||||
if (this.exceptions) {
|
||||
this.included = this.excluded = undefined;
|
||||
if (this.ifMindExceptions && this.exceptions) {
|
||||
console.log('Exceptions:', this.exceptions);
|
||||
this.included = [];
|
||||
this.excluded = [];
|
||||
for(const host of Object.keys(this.exceptions)) {
|
||||
|
@ -298,7 +306,7 @@
|
|||
} catch(e) {
|
||||
return cb(e);
|
||||
}
|
||||
kitchenState('mods', pacMods);
|
||||
kitchenState(modsKey, pacMods);
|
||||
}
|
||||
this._tryNowAsync(
|
||||
(err, res, ...warns) => {
|
||||
|
@ -326,9 +334,11 @@
|
|||
|
||||
resetToDefaultsVoid() {
|
||||
|
||||
kitchenState('mods', null);
|
||||
// Pruge all but exceptions.
|
||||
const exceptions = kitchenState(modsKey).exceptions;
|
||||
kitchenState(modsKey, null);
|
||||
kitchenState(ifIncontinence, null);
|
||||
this.keepCookedNowAsync({});
|
||||
this.keepCookedNowAsync({exceptions: exceptions});
|
||||
|
||||
},
|
||||
|
||||
|
|
|
@ -46,8 +46,8 @@
|
|||
|
||||
.if-not-controlled {
|
||||
display: none;
|
||||
background-color: red;
|
||||
|
||||
background-color: red;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
|
@ -304,6 +304,13 @@
|
|||
border: none !important;
|
||||
}
|
||||
|
||||
option.if-proxied {
|
||||
color: var(--ribbon-color);
|
||||
}
|
||||
option:not(.if-proxied) {
|
||||
color: red;
|
||||
}
|
||||
|
||||
#exc-flex-container {
|
||||
position: relative;
|
||||
display: flex;
|
||||
|
@ -379,7 +386,7 @@
|
|||
|
||||
<header>Проксировать этот сайт?</header>
|
||||
<div class="acc-padded" id="exc-flex-container">
|
||||
<ul style="padding-right: 1em">
|
||||
<ul style="padding-right: 1em" id="exc-radio">
|
||||
<li><input id="this-auto" type="radio" checked name="if-proxy-this-site"/> <label for="this-auto">🔄︎ авто</label></li>
|
||||
<li><input id="this-yes" type="radio" name="if-proxy-this-site"/> <label for="this-yes">✔ да</label></li>
|
||||
<li><input id="this-no" type="radio" name="if-proxy-this-site"/> <label for="this-no">✘ нет</label></li>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
'use strict';
|
||||
|
||||
const START = Date.now();
|
||||
|
||||
document.getElementById('pac-mods').onchange = function() {
|
||||
|
@ -12,23 +13,6 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
|
|||
backgroundPage.apis.errorHandlers.installListenersOnAsync(
|
||||
window, 'PUP', async() => {
|
||||
|
||||
const currentTab = await new Promise(
|
||||
(resolve) => chrome.tabs.query(
|
||||
{ active: true, currentWindow: true },
|
||||
([tab]) => resolve(tab)
|
||||
)
|
||||
);
|
||||
|
||||
if ( !currentTab || currentTab.url.startsWith('chrome://extensions/?options=') ) {
|
||||
const hidClass = 'hideable';
|
||||
for(const el of document.querySelectorAll('.' + hidClass)) {
|
||||
el.classList.remove(hidClass);
|
||||
}
|
||||
for(const el of document.querySelectorAll('.hidden-for-options-page')) {
|
||||
el.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
const getStatus = () => document.querySelector('#status');
|
||||
|
||||
const setStatusTo = (msg) => {
|
||||
|
@ -239,59 +223,190 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
|
|||
};
|
||||
}
|
||||
|
||||
// IF INSIDE OPTIONS
|
||||
|
||||
const currentTab = await new Promise(
|
||||
(resolve) => chrome.tabs.query(
|
||||
{ active: true, currentWindow: true },
|
||||
([tab]) => resolve(tab)
|
||||
)
|
||||
);
|
||||
|
||||
const ifInsideOptions = !currentTab || currentTab.url.startsWith('chrome://extensions/?options=');
|
||||
if (ifInsideOptions) {
|
||||
const hidClass = 'hideable';
|
||||
for(const el of document.querySelectorAll('.' + hidClass)) {
|
||||
el.classList.remove(hidClass);
|
||||
}
|
||||
for(const el of document.querySelectorAll('.hidden-for-options-page')) {
|
||||
el.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
// EXCEPTIONS PANEL
|
||||
/*
|
||||
Iterating and modifying select.selectedOptions
|
||||
at the same time is buggy, iterate this way instead:
|
||||
[...select.selectedOptions]
|
||||
*/
|
||||
|
||||
{
|
||||
|
||||
if (currentTab && !currentTab.url.startsWith('chrome')) {
|
||||
document.getElementById('except-editor').value = new URL(currentTab.url).hostname;
|
||||
}
|
||||
|
||||
const pacKitchen = backgroundPage.apis.pacKitchen;
|
||||
|
||||
{
|
||||
|
||||
const pacMods = pacKitchen.getPacMods();
|
||||
const exc = pacMods.exceptions || {};
|
||||
const excEditor = document.getElementById('except-editor');
|
||||
|
||||
const addOption = function addOption(host) {
|
||||
if (currentTab && !currentTab.url.startsWith('chrome')) {
|
||||
excEditor.value = new URL(currentTab.url).hostname;
|
||||
}
|
||||
|
||||
const excSelect = document.getElementById('exceptions-select');
|
||||
|
||||
excEditor.onkeyup = function() {
|
||||
|
||||
this.value = this.value.trim();
|
||||
for(const opt of excSelect.options) {
|
||||
let commonChars = 0;
|
||||
for( const i in this.value ) {
|
||||
if (this.value.charAt(i) !== opt.value.charAt(i)) {
|
||||
break;
|
||||
}
|
||||
++commonChars;
|
||||
}
|
||||
opt.style.order = commonChars;
|
||||
}
|
||||
return true;
|
||||
|
||||
};
|
||||
|
||||
const thisYes = document.getElementById('this-yes');
|
||||
const thisNo = document.getElementById('this-no');
|
||||
const ifProxiedClass = 'if-proxied';
|
||||
|
||||
excSelect.onclick = function(event) {
|
||||
|
||||
// Only one item may be selecte at a time.
|
||||
// Spread op is used to fight weird bug with iterator.
|
||||
for(const sopt of [...this.selectedOptions]) {
|
||||
sopt.selected = false;
|
||||
}
|
||||
const opt = event.target;
|
||||
opt.selected = true;
|
||||
if (opt.classList.contains(ifProxiedClass)) {
|
||||
thisYes.checked = true;
|
||||
} else {
|
||||
thisNo.checked = true;
|
||||
}
|
||||
excEditor.value = opt.value.trim();
|
||||
|
||||
};
|
||||
|
||||
const addOption = function addOption(host, ifProxy) {
|
||||
|
||||
const opt = document.createElement('option');
|
||||
opt.text = host;
|
||||
document.getElementById('exceptions-select').add(opt);
|
||||
if(ifProxy) {
|
||||
opt.classList.add(ifProxiedClass);
|
||||
};
|
||||
const editorHost = excEditor.value.trim();
|
||||
if (host === editorHost) {
|
||||
excSelect.insertBefore( opt, excSelect.firstChild );
|
||||
opt.click();
|
||||
} else {
|
||||
excSelect.add(opt);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for(const host of Object.keys(exc).sort()) {
|
||||
addOption(host);
|
||||
}
|
||||
|
||||
document.getElementById('this-yes').onclick = function() {
|
||||
{ // Populate select box.
|
||||
|
||||
const pacMods = pacKitchen.getPacMods();
|
||||
if (!pacMods.filteredCustomsString) {
|
||||
for(const host of Object.keys(pacMods.exceptions || {}).sort()) {
|
||||
addOption(host, pacMods.exceptions[host]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
};
|
||||
|
||||
document.getElementById('exc-radio').onclick = function(event) {
|
||||
|
||||
if( !['LABEL', 'INPUT'].includes( event.target.tagName ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const _host = excEditor.value.trim();
|
||||
const pacMods = pacKitchen.getPacMods();
|
||||
pacMods.exceptions = pacMods.exceptions || {};
|
||||
|
||||
let fixSelectBox;
|
||||
|
||||
if (document.getElementById('this-auto').checked) {
|
||||
delete pacMods.exceptions[_host];
|
||||
fixSelectBox = () => {
|
||||
|
||||
for(const sopt of [...excSelect.selectedOptions]) {
|
||||
const shost = sopt.value.trim();
|
||||
delete pacMods.exceptions[shost];
|
||||
sopt.remove();
|
||||
}
|
||||
excEditor.value = '';
|
||||
|
||||
}
|
||||
} else {
|
||||
// YES or NO.
|
||||
if (!validateHost(_host)) {
|
||||
return false;
|
||||
}
|
||||
if (thisYes.checked && !pacMods.filteredCustomsString) {
|
||||
showErrors( new TypeError(
|
||||
'Проксировать СВОИ сайты можно только при наличии СВОИХ прокси (см.«Модификаторы»).'
|
||||
));
|
||||
return false;
|
||||
}
|
||||
const host = document.getElementById('except-editor').value;
|
||||
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;
|
||||
pacMods.exceptions[_host] = thisYes.checked;
|
||||
|
||||
if (excSelect.selectedIndex === -1) {
|
||||
// Add new.
|
||||
fixSelectBox = () => addOption(_host, thisYes.checked);
|
||||
} else {
|
||||
// Edit selected.
|
||||
fixSelectBox = () => {
|
||||
|
||||
for(const sopt of [...excSelect.selectedOptions]) {
|
||||
sopt.value = _host;
|
||||
if (thisYes.checked) {
|
||||
sopt.classList.add(ifProxiedClass);
|
||||
} else {
|
||||
sopt.classList.remove(ifProxiedClass);
|
||||
}
|
||||
}
|
||||
|
||||
pacMods.exceptions = pacMods.exceptions || {};
|
||||
pacMods.exceptions[host] = true;
|
||||
pacKitchen.keepCookedNowAsync(
|
||||
pacMods,
|
||||
(err) => err
|
||||
? showErrors(err)
|
||||
: addOption(host)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
conduct(
|
||||
'Применяем исключения...',
|
||||
(cb) => pacKitchen.keepCookedNowAsync(pacMods, cb),
|
||||
'Исключения применены.',
|
||||
fixSelectBox
|
||||
);
|
||||
return true;
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
@ -301,7 +416,6 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
|
|||
const _firstChild = modPanel.firstChild;
|
||||
const keyToLi = {};
|
||||
const customProxyStringKey = 'customProxyStringRaw';
|
||||
const uiRaw = 'ui-proxy-string-raw';
|
||||
|
||||
for(const conf of pacKitchen.getOrderedConfigs()) {
|
||||
|
||||
|
@ -317,6 +431,7 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
|
|||
if (key !== customProxyStringKey) {
|
||||
li.innerHTML += infoSign(conf.desc);
|
||||
} else {
|
||||
const uiRaw = 'ui-proxy-string-raw';
|
||||
li.innerHTML += `<a href="${conf.url}" class="info-sign info-url">🛈</a><br/>
|
||||
<textarea
|
||||
spellcheck="false"
|
||||
|
@ -336,22 +451,25 @@ HTTPS 11.22.33.44:8080;">${conf.value || localStorage.getItem(uiRaw) || ''}</tex
|
|||
};
|
||||
document.getElementById('apply-mods').onclick = () => {
|
||||
|
||||
const configs = Object.keys(keyToLi).reduce( (configs, key) => {
|
||||
const oldMods = pacKitchen.getPacMods();
|
||||
for(const key of Object.keys(keyToLi)) {
|
||||
oldMods[key] = keyToLi[key].querySelector('input').checked;
|
||||
};
|
||||
|
||||
if (key !== customProxyStringKey) {
|
||||
configs[key] = keyToLi[key].querySelector('input').checked;
|
||||
} else {
|
||||
configs[key] = keyToLi[key].querySelector('input').checked
|
||||
&& keyToLi[key].querySelector('textarea').value.trim();
|
||||
}
|
||||
return configs;
|
||||
{
|
||||
// OWN PROXY
|
||||
|
||||
}, {});
|
||||
const taVal = keyToLi[customProxyStringKey].querySelector('textarea').value;
|
||||
if (configs[customProxyStringKey] !== false) {
|
||||
const liPs = keyToLi[customProxyStringKey];
|
||||
oldMods[customProxyStringKey]
|
||||
= liPs.querySelector('input').checked
|
||||
&& liPs.querySelector('textarea').value.trim();
|
||||
|
||||
const taVal = liPs.querySelector('textarea').value;
|
||||
if (oldMods[customProxyStringKey] !== false) {
|
||||
const ifValid = taVal
|
||||
.replace(/#.*$/mg)
|
||||
.split(/\s*[;\n\r]+\s*/g)
|
||||
.filter( (str) => str )
|
||||
.every(
|
||||
(str) =>
|
||||
/^(?:DIRECT|(?:(?:HTTPS?|PROXY|SOCKS(?:4|5))\s+\S+))$/g
|
||||
|
@ -362,13 +480,16 @@ HTTPS 11.22.33.44:8080;">${conf.value || localStorage.getItem(uiRaw) || ''}</tex
|
|||
'Неверный формат своих прокси. Свертесь с <a href="https://rebrand.ly/ac-own-proxy" data-in-bg="true">документацией</a>.'
|
||||
))
|
||||
}
|
||||
configs[customProxyStringKey] = taVal;
|
||||
oldMods[customProxyStringKey] = taVal;
|
||||
} else {
|
||||
localStorage.setItem(uiRaw, taVal);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
conduct(
|
||||
'Применяем настройки...',
|
||||
(cb) => pacKitchen.keepCookedNowAsync(configs, cb),
|
||||
(cb) => pacKitchen.keepCookedNowAsync(oldMods, cb),
|
||||
'Настройки применены.',
|
||||
() => { document.getElementById('apply-mods').disabled = true; }
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue
Block a user