Merge branch 'cats'

This commit is contained in:
ilyaigpetrov 2017-04-21 15:18:45 -07:00
commit 5cac8779c3
4 changed files with 213 additions and 146 deletions

View File

@ -19,53 +19,72 @@
dflt: false, dflt: false,
label: 'проксировать только HTTP<em>S</em>-сайты', label: 'проксировать только HTTP<em>S</em>-сайты',
desc: 'Проксировать только сайты, доступные по шифрованному протоколу HTTP<em>S</em>. Прокси и провайдер смогут видеть только адреса проксируемых HTTP<em>S</em>-сайтов, но не их содержимое. Используйте, если вы не доверяете прокси-серверам ваш HTTP-трафик. Разумеется, что с этой опцией разблокировка HTTP-сайтов работать не будет.', desc: 'Проксировать только сайты, доступные по шифрованному протоколу HTTP<em>S</em>. Прокси и провайдер смогут видеть только адреса проксируемых HTTP<em>S</em>-сайтов, но не их содержимое. Используйте, если вы не доверяете прокси-серверам ваш HTTP-трафик. Разумеется, что с этой опцией разблокировка HTTP-сайтов работать не будет.',
index: 0, order: 0,
}, },
ifUseSecureProxiesOnly: { ifUseSecureProxiesOnly: {
dflt: false, dflt: false,
label: 'только шифрованная связь с прокси', label: 'только шифрованная связь с прокси',
desc: 'Шифровать соединение до прокси от провайдера, используя только прокси типа HTTPS или локальный Tor. Провайдер всё же сможет видеть адреса (но не содержимое) проксируемых ресурсов из протокола DNS (даже с Tor). Опция вряд ли может быть вам полезна, т.к. шифруется не весь трафик, а лишь разблокируемые ресурсы.', desc: 'Шифровать соединение до прокси от провайдера, используя только прокси типа HTTPS или локальный Tor. Провайдер всё же сможет видеть адреса (но не содержимое) проксируемых ресурсов из протокола DNS (даже с Tor). Опция вряд ли может быть вам полезна, т.к. шифруется не весь трафик, а лишь разблокируемые ресурсы.',
index: 1, order: 1,
}, },
ifProhibitDns: { ifProhibitDns: {
dflt: false, dflt: false,
label: 'запретить опредление по IP/DNS', label: 'запретить опредление по IP/DNS',
desc: 'Пытается запретить скрипту использовать DNS, без которого определение блокировки по IP работать не будет (т.е. будет разблокироваться меньше сайтов). Используйте, чтобы получить прирост в производительности или если вам кажется, что мы проксируем слишком много сайтов. Запрет действует только для скрипта, браузер и др.программы продолжат использование DNS.', desc: 'Пытается запретить скрипту использовать DNS, без которого определение блокировки по IP работать не будет (т.е. будет разблокироваться меньше сайтов). Используйте, чтобы получить прирост в производительности или если вам кажется, что мы проксируем слишком много сайтов. Запрет действует только для скрипта, браузер и др.программы продолжат использование DNS.',
index: 2, order: 2,
}, },
ifProxyOrDie: { ifProxyOrDie: {
dflt: true, dflt: true,
ifDfltMods: true, ifDfltMods: true,
label: 'проксируй или умри!', label: 'проксируй или умри!',
desc: 'Запрещает соединение с сайтами напрямую без прокси в случаях, когда все прокси отказывают. Например, если все ВАШИ прокси вдруг недоступны, то добавленные вручную сайты открываться не будут совсем. Однако смысл опции в том, что она препятствует занесению прокси в чёрные списки Хрома. Рекомендуется не отключать.', desc: 'Запрещает соединение с сайтами напрямую без прокси в случаях, когда все прокси отказывают. Например, если все ВАШИ прокси вдруг недоступны, то добавленные вручную сайты открываться не будут совсем. Однако смысл опции в том, что она препятствует занесению прокси в чёрные списки Хрома. Рекомендуется не отключать.',
index: 3, order: 3,
}, },
ifUsePacScriptProxies: { ifUsePacScriptProxies: {
dflt: true, dflt: true,
category: 'ownProxies',
label: 'использовать прокси PAC-скрипта', label: 'использовать прокси PAC-скрипта',
desc: 'Использовать прокси-сервера от авторов PAC-скрипта.', desc: 'Использовать прокси-сервера от авторов PAC-скрипта.',
index: 4, order: 4,
}, },
ifUseLocalTor: { ifUseLocalTor: {
dflt: false, dflt: false,
category: 'ownProxies',
label: 'использовать СВОЙ локальный Tor', label: 'использовать СВОЙ локальный Tor',
desc: 'Установите <a href="https://rebrand.ly/ac-tor">Tor</a> на свой компьютер и используйте его как прокси-сервер. <a href="https://rebrand.ly/ac-tor">ВАЖНО</a>', desc: 'Установите <a href="https://rebrand.ly/ac-tor">Tor</a> на свой компьютер и используйте его как прокси-сервер. <a href="https://rebrand.ly/ac-tor">ВАЖНО</a>',
index: 5, order: 5,
}, },
exceptions: { exceptions: {
category: 'exceptions',
dflt: null, dflt: null,
}, },
ifMindExceptions: { ifMindExceptions: {
dflt: true, dflt: true,
category: 'exceptions',
label: 'учитывать исключения', label: 'учитывать исключения',
desc: 'Учитывать сайты, добавленные вручную. Только для своих прокси-серверов! Без своих прокси работать не будет.', desc: 'Учитывать сайты, добавленные вручную. Только для своих прокси-серверов! Без своих прокси работать не будет.',
index: 6, order: 6,
},
ifProxyErrors: {
dflt: false,
category: 'exceptions',
label: 'проксировать <a href>выбранные</a> ошибки',
desc: 'Предлагать добавить сайт в исключения при выбранных ошибках',
order: 7,
}, },
customProxyStringRaw: { customProxyStringRaw: {
dflt: '', dflt: '',
category: 'ownProxies',
label: 'использовать СВОИ прокси', label: 'использовать СВОИ прокси',
url: 'https://rebrand.ly/ac-own-proxy', url: 'https://rebrand.ly/ac-own-proxy',
index: 7, order: 8,
},
ifProxyMoreDomains: {
dflt: false,
category: 'ownProxies',
label: 'проксировать .onion, .i2p и OpenNIC',
desc: 'Проксировать особые домены. Необходима поддержка со стороны прокси.',
order: 9,
}, },
}; };
@ -91,20 +110,24 @@
}; };
const getOrderedConfigsForUser = function getOrderedConfigs() { const getOrderedConfigsForUser = function getOrderedConfigs(category) {
const pacMods = getCurrentConfigs(); const pacMods = getCurrentConfigs();
return Object.keys(configs).reduce((arr, key) => { return Object.keys(configs)
.sort((keyA, keyB) => configs[keyA].order - configs[keyB].order)
.reduce((arr, key) => {
const conf = configs[key]; const conf = configs[key];
if(typeof(conf.index) === 'number') { if(typeof(conf.order) === 'number') {
arr[conf.index] = conf; if(!category || category === (conf.category || 'general')) {
conf.value = pacMods[key]; arr.push(conf);
conf.key = key; conf.value = pacMods[key];
} conf.key = key;
return arr; }
}
return arr;
}, []); }, []);
}; };

View File

@ -213,7 +213,7 @@
getSortedEntriesForProviders() { getSortedEntriesForProviders() {
return Object.entries(this.pacProviders).sort((entryA, entryB) => entryA[1].order - entryB[1].order); return Object.entries(this.pacProviders).sort((entryA, entryB) => entryA[1].order - entryB[1].order).map(([key, prov]) => Object.assign({key: key}, prov));
}, },

View File

@ -82,6 +82,10 @@
padding-left: 1.4em; padding-left: 1.4em;
padding-right: 1.4em; padding-right: 1.4em;
} }
.horizontal-list,
.horizontal-list li {
line-height: 100%;
}
.horizontal-list li { .horizontal-list li {
display: inline-block; display: inline-block;
} }
@ -147,6 +151,7 @@
:root:not(.if-options-page) #acc-pac:not(:checked) ~ .main-nav section[data-for="acc-pac"], :root:not(.if-options-page) #acc-pac:not(:checked) ~ .main-nav section[data-for="acc-pac"],
:root:not(.if-options-page) #acc-exc:not(:checked) ~ .main-nav section[data-for="acc-exc"], :root:not(.if-options-page) #acc-exc:not(:checked) ~ .main-nav section[data-for="acc-exc"],
:root:not(.if-options-page) #acc-own:not(:checked) ~ .main-nav section[data-for="acc-own"],
:root:not(.if-options-page) #acc-mods:not(:checked) ~ .main-nav section[data-for="acc-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"] :root:not(.if-options-page) #acc-ntf:not(:checked) ~ .main-nav section[data-for="acc-ntf"]
{ {
@ -164,6 +169,7 @@
} }
:root:not(.if-options-page) #acc-pac:not(:checked) ~ .main-nav section[data-for="acc-pac"] *, :root:not(.if-options-page) #acc-pac:not(:checked) ~ .main-nav section[data-for="acc-pac"] *,
:root:not(.if-options-page) #acc-exc:not(:checked) ~ .main-nav section[data-for="acc-exc"] *, :root:not(.if-options-page) #acc-exc:not(:checked) ~ .main-nav section[data-for="acc-exc"] *,
:root:not(.if-options-page) #acc-own:not(:checked) ~ .main-nav section[data-for="acc-own"] *,
:root:not(.if-options-page) #acc-mods:not(:checked) ~ .main-nav section[data-for="acc-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"] * :root:not(.if-options-page) #acc-ntf:not(:checked) ~ .main-nav section[data-for="acc-ntf"] *
{ {
@ -171,47 +177,50 @@
margin-bottom: 0 !important; margin-bottom: 0 !important;
} }
.nav-labels { .nav-labels {
background-color: #eef;
text-align: center; text-align: center;
} }
.nav-labels li label { .nav-labels li label {
display: inline-block; display: inline-block;
border: 2px solid var(--blue-bg); border: 1px solid var(--blue-bg);
border-radius: 0.7em; border-radius: 0.2em;
background-color: white; background-color: white;
color: var(--ribbon-color); color: var(--ribbon-color);
padding: 0.2em 0.65em 0.3em 0.4em; padding: 0.2em 0.3em 0.3em 0.2em;
line-height: 0.9em; line-height: 0.8em;
margin: 0.1em 0; margin: 0.1em 0;
} }
.nav-labels li label:hover { .nav-labels li label:hover {
background-color: var(--blue-bg); background-color: var(--blue-bg);
color: white; color: white;
/*
border-color: white; border-color: white;
border-style: dotted; border-style: dotted;*/
} }
/* CHECKED LABELS */ /* CHECKED LABELS */
#acc-pac:checked ~ .nav-labels label[for="acc-pac"]:not(:hover), #acc-pac:checked ~ .nav-labels label[for="acc-pac"]:not(:hover),
#acc-exc:checked ~ .nav-labels label[for="acc-exc"]:not(:hover), #acc-exc:checked ~ .nav-labels label[for="acc-exc"]:not(:hover),
#acc-own:checked ~ .nav-labels label[for="acc-own"]:not(:hover),
#acc-mods:checked ~ .nav-labels label[for="acc-mods"]:not(:hover), #acc-mods:checked ~ .nav-labels label[for="acc-mods"]:not(:hover),
#acc-ntf:checked ~ .nav-labels label[for="acc-ntf"]:not(:hover) #acc-ntf:checked ~ .nav-labels label[for="acc-ntf"]:not(:hover)
{ {
background-color: var(--blue-bg); background-color: var(--blue-bg);
color: white; color: white;
line-height: 0.8em;
} }
/* ★★★★★ */ /* ★★★★★ */
.nav-labels label:before { .nav-labels label:before {
content: '★ '; content: '★';
padding-right: 0.1em;
visibility: hidden; visibility: hidden;
} }
.nav-labels li label:hover:before, .nav-labels li label:hover:before,
#acc-pac:checked ~ .nav-labels label[for="acc-pac"]:before, #acc-pac:checked ~ .nav-labels label[for="acc-pac"]:before,
#acc-exc:checked ~ .nav-labels label[for="acc-exc"]:before, #acc-exc:checked ~ .nav-labels label[for="acc-exc"]:before,
#acc-own:checked ~ .nav-labels label[for="acc-own"]:before,
#acc-mods:checked ~ .nav-labels label[for="acc-mods"]:before, #acc-mods:checked ~ .nav-labels label[for="acc-mods"]:before,
#acc-ntf:checked ~ .nav-labels label[for="acc-ntf"]:before #acc-ntf:checked ~ .nav-labels label[for="acc-ntf"]:before
{ {
@ -435,15 +444,17 @@
<input type="radio" name="accordion" class="off" id="acc-pac" checked/> <input type="radio" name="accordion" class="off" id="acc-pac" checked/>
<input type="radio" name="accordion" class="off" id="acc-exc"/> <input type="radio" name="accordion" class="off" id="acc-exc"/>
<input type="radio" name="accordion" class="off" id="acc-own"/>
<input type="radio" name="accordion" class="off" id="acc-mods"/> <input type="radio" name="accordion" class="off" id="acc-mods"/>
<input type="radio" name="accordion" class="off" id="acc-ntf"/> <input type="radio" name="accordion" class="off" id="acc-ntf"/>
<nav class="nav-labels horizontal-list hidden-for-options-page"> <nav class="nav-labels hidden-for-options-page">
<ul> <ul class='horizontal-list'>
<li><label for="acc-pac" class="nav-label">PAC-скрипт</label></li> <li><label for="acc-pac" class="nav-label">PAC-скрипт</label></li>
<li><label for="acc-exc" class="nav-label">Исключения</label></li>
<li><label for="acc-own" class="nav-label">Свои прокси</label></li>
<li><label for="acc-mods" class="nav-label">Модификаторы</label></li> <li><label for="acc-mods" class="nav-label">Модификаторы</label></li>
<li><label for="acc-exc" class="nav-label">Исключения</label></li> <li><label for="acc-ntf" class="nav-label">Уведомления</label></li>
<li><label for="acc-ntf" class="nav-label">Уведомления</label></li>
</ul> </ul>
<hr/> <hr/>
</nav> </nav>
@ -496,6 +507,17 @@
</section> </section>
<section data-for="acc-own">
<ul id="own-proxies">
<li class="control-row hor-flex">
<input type="button" value="Применить" id="apply-mods" disabled/>
<a href id="bar-reset-mods">К изначальным!</a>
</li>
</ul>
</section>
<section data-for="acc-mods"> <section data-for="acc-mods">
<ul id="pac-mods"> <ul id="pac-mods">

View File

@ -158,11 +158,9 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
}; };
const infoIcon = ` const infoIcon = `<svg class="icon" style="position: relative; top: 0.08em">
<svg class="icon" <use xlink:href="#icon-info"></use>
style="position: relative; top: 0.08em"><use xlink:href="#icon-info"></use></svg> </svg>`;
<!--span style="font-size: 1.3em" class="emoji">🛈(looks huge)</span-->
`;
const infoSign = function infoSign(tooltip) { const infoSign = function infoSign(tooltip) {
@ -173,22 +171,31 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
}; };
const infoUrl = (url) => `<a href="${url}" class="right-bottom-icon info-url">${infoIcon}</a>`;
const appendInfoRow = (mountEl, conf, inputTypeName, inputId, htmlAfterLabel = '') => {
mountEl.classList.add('info-row', 'hor-flex');
mountEl.innerHTML = `
<input ${inputTypeName} id="${inputId}">
<div class="label-container">
<label for="${inputId}"> ${conf.label}</label>
${htmlAfterLabel}
</div>` + (conf.desc ? infoSign(conf.desc) : infoUrl(conf.url));
};
{ {
const ul = document.querySelector('#list-of-providers'); const ul = document.querySelector('#list-of-providers');
const _firstChild = ul.firstChild; const _firstChild = ul.firstChild;
for( for(
const [providerKey, provider] of antiCensorRu.getSortedEntriesForProviders() const provConf of antiCensorRu.getSortedEntriesForProviders()
) { ) {
const li = document.createElement('li'); const li = document.createElement('li');
li.classList.add('info-row', 'hor-flex'); appendInfoRow(li, provConf, 'type="radio" name="pacProvider"', provConf.key, `
li.innerHTML = ` &nbsp;<a href class="link-button update-button"
<input type="radio" name="pacProvider" id="${providerKey}"> id="update-${provConf.key}">[обновить]</a>
<div class="label-container"> `);
<label for="${providerKey}"> ${provider.label}</label>
&nbsp;<a href class="link-button update-button"
id="update-${providerKey}">[обновить]</a>
</div>` +
infoSign(provider.desc);
li.querySelector('.link-button').onclick = li.querySelector('.link-button').onclick =
() => { () => {
conduct( conduct(
@ -255,13 +262,12 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
document.documentElement.classList.add('if-options-page'); document.documentElement.classList.add('if-options-page');
} }
// EXCEPTIONS PANEL
{ { // KITCHEN PANELS starts.
const pacKitchen = backgroundPage.apis.pacKitchen; const pacKitchen = backgroundPage.apis.pacKitchen;
{ { // EXCEPTIONS TAB starts.
const excEditor = document.getElementById('exc-editor'); const excEditor = document.getElementById('exc-editor');
@ -518,124 +524,140 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
}; };
} } // EXCEPTIONS TAB ends.
// PAC MODS PANEL const camelToDash = (name) => name.replace(/([A-Z])/g, (_, p) => '-' + p.toLowerCase());
const modPanel = document.getElementById('pac-mods'); { // OWN PROXIES TAB starts.
const _firstChild = modPanel.firstChild;
const keyToLi = {};
const customProxyStringKey = 'customProxyStringRaw';
const uiRaw = 'ui-proxy-string-raw';
for(const conf of pacKitchen.getOrderedConfigs()) { const ownsList = document.getElementById('own-proxies');
const _firstChild = ownsList.firstChild;
const keyToLi = {};
const customProxyStringKey = 'customProxyStringRaw';
const uiRaw = 'ui-proxy-string-raw';
const key = conf.key; for(const conf of pacKitchen.getOrderedConfigs('ownProxies')) {
const iddy = 'mods-' + conf.key.replace(/([A-Z])/g, (_, p) => '-' + p.toLowerCase());
const li = document.createElement('li');
li.classList.add('info-row', 'hor-flex');
keyToLi[key] = li;
const ifMultiline = key === customProxyStringKey;
li.innerHTML = `
<input type="checkbox" id="${iddy}" ${ conf.value ? 'checked' : '' }/>
<div class="label-container">
<label for="${iddy}"> ${ conf.label }</label>
</div>`;
if (!ifMultiline) { const key = conf.key;
li.innerHTML += infoSign(conf.desc); const iddy = 'mods-' + camelToDash(conf.key);
} else { const li = document.createElement('li');
li.style.flexWrap = 'wrap'; appendInfoRow(li, conf, `type="checkbox" ${conf.value ? 'checked' : ''}`, iddy);
li.innerHTML += `<a href="${conf.url}" class="right-bottom-icon info-url">${infoIcon}</a>
<textarea const ifMultiline = key === customProxyStringKey;
spellcheck="false" if (ifMultiline) {
placeholder="SOCKS5 localhost:9050; # Tor Expert li.style.flexWrap = 'wrap';
li.innerHTML += `
<textarea
spellcheck="false"
placeholder="SOCKS5 localhost:9050; # Tor Expert
SOCKS5 localhost:9150; # Tor Browser SOCKS5 localhost:9150; # Tor Browser
HTTPS 11.22.33.44:3143; HTTPS 11.22.33.44:3143;
PROXY foobar.com:8080; # Not HTTP!">${conf.value || localStorage.getItem(uiRaw) || ''}</textarea>`; PROXY foobar.com:8080; # Not HTTP!">${conf.value || localStorage.getItem(uiRaw) || ''}</textarea>
li.querySelector('textarea').onkeyup = function() { `;
li.querySelector('textarea').onkeyup = function() {
this.dispatchEvent( new Event('change', {'bubbles': true}) ); this.dispatchEvent( new Event('change', {'bubbles': true}) );
};
}
ownsList.insertBefore( li, _firstChild );
};
} }
modPanel.insertBefore( li, _firstChild ); } // OWN PROXIES TAB ends.
}; { // PAC MODS TAB starts.
document.getElementById('apply-mods').onclick = () => {
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;
};
{
// OWN PROXY
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 ifValidArr = taVal
.trim()
.replace(/#.*$/mg, '')
.split(/\s*[;\n\r]+\s*/g)
.filter( (str) => str );
const ifValid = ifValidArr.every(
(str) =>
/^(?:DIRECT|(?:(?:HTTPS|PROXY|SOCKS(?:4|5)?)\s+\S+))$/g
.test(str.trim())
);
if (!(ifValidArr.length && ifValid)) {
return showErrors(new TypeError(
'Неверный формат своих прокси. Свертесь с <a href="https://rebrand.ly/ac-own-proxy" data-in-bg="true">документацией</a>.'
));
}
oldMods[customProxyStringKey] = taVal;
} else {
localStorage.setItem(uiRaw, taVal);
}
}
conduct(
'Применяем настройки...',
(cb) => pacKitchen.keepCookedNowAsync(oldMods, cb),
'Настройки применены.',
() => {
document.getElementById('apply-mods').disabled = true;
}
);
const oldMods = pacKitchen.getPacMods();
for(const key of Object.keys(keyToLi)) {
oldMods[key] = keyToLi[key].querySelector('input').checked;
}; };
{ document.getElementById('reset-mods').onclick = () => {
// OWN PROXY
const liPs = keyToLi[customProxyStringKey]; const ifSure = backgroundPage.confirm('Сбросить все модификаторы и ИСКЛЮЧЕНИЯ?');
oldMods[customProxyStringKey] if (!ifSure) {
= liPs.querySelector('input').checked return false;
&& liPs.querySelector('textarea').value.trim();
const taVal = liPs.querySelector('textarea').value;
if (oldMods[customProxyStringKey] !== false) {
const ifValidArr = taVal
.trim()
.replace(/#.*$/mg, '')
.split(/\s*[;\n\r]+\s*/g)
.filter( (str) => str );
const ifValid = ifValidArr.every(
(str) =>
/^(?:DIRECT|(?:(?:HTTPS|PROXY|SOCKS(?:4|5)?)\s+\S+))$/g
.test(str.trim())
);
if (!(ifValidArr.length && ifValid)) {
return showErrors(new TypeError(
'Неверный формат своих прокси. Свертесь с <a href="https://rebrand.ly/ac-own-proxy" data-in-bg="true">документацией</a>.'
));
}
oldMods[customProxyStringKey] = taVal;
} else {
localStorage.setItem(uiRaw, taVal);
} }
conduct(
'Сбрасываем...',
(cb) => {
} pacKitchen.resetToDefaults();
backgroundPage.utils.fireRequest('ip-to-host-reset-to-defaults', cb);
conduct( },
'Применяем настройки...', 'Откройте окно заново для отображения эффекта.',
(cb) => pacKitchen.keepCookedNowAsync(oldMods, cb), () => window.close()
'Настройки применены.', );
() => {
document.getElementById('apply-mods').disabled = true; };
} } // PAC MODS TAB ends.
);
}; } // KITCHEN PANELS ends.
document.getElementById('reset-mods').onclick = () => {
const ifSure = backgroundPage.confirm('Сбросить все модификаторы и ИСКЛЮЧЕНИЯ?');
if (!ifSure) {
return false;
}
conduct(
'Сбрасываем...',
(cb) => {
pacKitchen.resetToDefaults();
backgroundPage.utils.fireRequest('ip-to-host-reset-to-defaults', cb);
},
'Откройте окно заново для отображения эффекта.',
() => window.close()
);
};
}
// NOTIFICATIONS PANEL // NOTIFICATIONS PANEL