Grey icon if turned off, change exception editor ui/behavior

This commit is contained in:
Ilya Ig. Petrov 2017-02-01 18:41:10 +00:00
parent c5c1ac559e
commit ca8d753372
7 changed files with 192 additions and 107 deletions

View File

@ -106,10 +106,27 @@
},
areSettingsNotControlledFor(details) {
/*
* Possible values for levelOfControl:
*
* 1. "not_controllable"
* 2. "controlled_by_other_extensions"
* 3. "controllable_by_this_extension"
* 4. "controlled_by_this_extension"
*
* See: https://developer.chrome.com/extensions/proxy
* */
return ['controlled_by_other', 'not_controllable']
.some( (prefix) => details.levelOfControl.startsWith(prefix) );
areSettingsControllableFor(details) {
return details.levelOfControl.endsWith('this_extension');
},
areSettingsControlledFor(details) {
return details.levelOfControl.startsWith('controlled_by_this');
},

View File

@ -109,19 +109,28 @@
},
ifNotControlled: null,
ifControlled: null,
ifControllable: null,
isNotControlled(details) {
isControllable(details) {
this.ifNotControlled = window.utils.areSettingsNotControlledFor(details);
if (this.ifNotControlled) {
this.ifControllable = window.utils.areSettingsControllableFor(details);
if (this.ifControllable) {
this.ifControlled = window.utils.areSettingsControlledFor(details);
} else {
this.ifControlled = false;
}
if (this.ifControlled) {
chrome.browserAction.setIcon( {path: './icons/default-128.png'} );
} else {
chrome.browserAction.setIcon({
path: './icons/default-grayscale-128.png',
});
} else {
chrome.browserAction.setIcon( {path: './icons/default-128.png'} );
}
return this.ifNotControlled;
return this.ifControllable;
},
@ -192,7 +201,7 @@
chrome.proxy.settings.get(
{},
(details) => handlers.isNotControlled(details)
(details) => handlers.isControllable(details)
);
chrome.notifications.onClicked.addListener( function(notId) {
@ -211,7 +220,7 @@
chrome.proxy.onProxyError.addListener((details) => {
if (handlers.ifNotControlled) {
if (!handlers.ifControlled) {
return;
}
/*
@ -233,7 +242,7 @@
console.log('Proxy settings changed.', details);
const noCon = 'no-control';
if ( handlers.isNotControlled(details) ) {
if ( !handlers.isControllable(details) ) {
handlers.mayNotifyVoid(
noCon,
chrome.i18n.getMessage('noControl'),

View File

@ -296,7 +296,7 @@
keepCookedNowAsync(pacMods = mandatory(), cb = throwIfError) {
console.log('Keep cooked now...');
console.log('Keep cooked now...', cb);
if (typeof(pacMods) === 'function') {
cb = pacMods;
pacMods = this.getCurrentConfigs();

View File

@ -69,7 +69,7 @@
}
chrome.proxy.settings.get({}, (details) => {
if ( window.utils.areSettingsNotControlledFor( details ) ) {
if ( !window.utils.areSettingsControlledFor( details ) ) {
console.warn('Failed, other extension is in control.');
return cb(

View File

@ -1,10 +1,10 @@
{
"manifest_version": 2,
"name": "__MSG_extName__ 0.18",
"name": "__MSG_extName__ 0.19",
"default_locale": "ru",
"description": "__MSG_extDesc__",
"version": "0.0.0.18",
"version": "0.0.0.19",
"icons": {
"128": "/icons/default-128.png"
},
@ -37,7 +37,7 @@
]
},
"browser_action": {
"default_title": "Этот сайт благословлён 0.18",
"default_title": "Этот сайт благословлён 0.19",
"default_popup": "/pages/choose-pac-provider/index.html"
},
"options_ui": {

View File

@ -6,6 +6,7 @@
:root {
--ribbon-color: #4169e1;
--default-grey: #bfbfbf;
max-width: 27em;
}
body {
margin: 0;
@ -64,35 +65,52 @@
color: white;
}
:root:not(.if-options-page) .only-for-options-page {
display: none;
}
:root.if-options-page .hidden-for-options-page {
display: none;
}
/* ACCORDION (OR TABBED STATEFUL UI) */
.off {
display: none;
}
.acc-padded {
section[data-for] {
padding: 0.6em 0.5em 1em;
}
:root.if-options-page section[data-for] {
padding-bottom: 0.6em;
}
:root.if-options-page section[data-for]:not(:last-child) {
border-bottom: 1px solid var(--default-grey);
}
/* HIDE */
#acc-pac:not(:checked) ~ .main-nav section[data-for="acc-pac"].hideable,
#acc-exc:not(:checked) ~ .main-nav section[data-for="acc-exc"].hideable,
#acc-mods:not(:checked) ~ .main-nav section[data-for="acc-mods"].hideable,
#acc-ntf:not(:checked) ~ .main-nav section[data-for="acc-ntf"].hideable
: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-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"]
{
/* Hide, but preclude width resizes. */
height: 0px !important;
line-height: 0px !important;
padding: 0;
margin: 0;
padding-top: 0 !important;
padding-bottom: 0 !important;
margin-top: 0 !important;
margin-bottom: 0 !important;
border: none !important;
display: block;
visibility: hidden;
transform: scaleY(0);
transform: scaleY(0) !important;
}
#acc-pac:not(:checked) ~ .main-nav section[data-for="acc-pac"].hideable *,
#acc-exc:not(:checked) ~ .main-nav section[data-for="acc-exc"].hideable *,
#acc-mods:not(:checked) ~ .main-nav section[data-for="acc-mods"].hideable *,
#acc-ntf:not(:checked) ~ .main-nav section[data-for="acc-ntf"].hideable *
: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-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"] *
{
margin-top: 0 !important;
margin-bottom: 0 !important;
@ -258,27 +276,34 @@
}
/* TAB_3 EXCEPTIONS */
#exc-editor {
border-radius: 0 !important;
border: none !important;
#exc-address {
display: flex;
align-items: baseline;
width: 100%;
--exc-hieght: 1.6em;
border-bottom: 1px solid var(--ribbon-color) !important;
// I don't understand this three, but they have effect.
max-height: 1.6em !important;
min-height: 1.6em !important;
height: 1em !important;
font-size: 1em;
}
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-editor.if-yes {
#exc-address.if-yes {
background-color: lightgreen;
}
#exc-editor.if-no {
#exc-address.if-no {
background-color: pink;
}
@ -332,53 +357,51 @@
<nav class="hor-padded main-nav">
<section data-for="acc-pac" class="hideable">
<section data-for="acc-pac">
<div class="acc-padded">
<ul id="list-of-providers">
<li><input type="radio" name="pacProvider" id="none" checked> <label for="none">Отключить</label></li>
</ul>
<div id="update-message">
Обновлялись: <span class="update-date">...</span>
</div>
</div>
</section>
<section data-for="acc-exc" class="hideable">
<section data-for="acc-exc" class="only-for-options-page">
Редактор исключений доступен толко для <a href="chrome://newtab">вкладок</a>.
</section>
<section data-for="acc-exc" class="hidden-for-options-page">
<div style="display: flex; justify-content: space-around;">
<span>Проксировать</span>
<input placeholder="navalny.com" list="exc-list" name="browser" id="exc-editor"/>?
<datalist id="exc-list"></datalist>
<div>Проксировать указанный сайт?</div>
<div id="exc-address">
<span>*.</span><input placeholder="navalny.com" list="exc-list" name="browser" id="exc-editor" style=""/>
</div>
<ol class="acc-padded horizontal-list" id="exc-radio">
<datalist id="exc-list"></datalist>
<ol class="horizontal-list" id="exc-radio">
<li><input id="this-auto" type="radio" checked name="if-proxy-this-site"/> <label for="this-auto">🔄&#xFE0E; авто</label></li>
<li><input id="this-yes" type="radio" name="if-proxy-this-site"/> <label for="this-yes">&nbsp;да</label></li>
<li><input id="this-no" type="radio" name="if-proxy-this-site"/> <label for="this-no">&nbsp;нет</label></li>
</ol>
</section>
<section data-for="acc-mods" class="hideable">
<section data-for="acc-mods">
<div class="acc-padded">
<ul id="pac-mods">
<li class="control-row">
<input type="button" value="Применить" id="apply-mods" disabled/>
<a href id="reset-mods" class="link-button">К изначальным!</a>
</li>
</ul>
</div>
</section>
<section data-for="acc-ntf" class="hideable">
<section data-for="acc-ntf">
<header>Я ❤️ yведомления:</header>
<div class="acc-padded">
<ul id="list-of-handlers"></ul>
</div>
<ul id="list-of-handlers" style="margin-left: 0.4em; margin-top: 0.4em;"></ul>
</section>

View File

@ -234,13 +234,7 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
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';
}
document.documentElement.classList.add('if-options-page')
}
// EXCEPTIONS PANEL
@ -253,10 +247,6 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
const excEditor = document.getElementById('exc-editor');
if (currentTab && !currentTab.url.startsWith('chrome')) {
excEditor.value = new URL(currentTab.url).hostname;
}
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])$/;
@ -269,13 +259,24 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
};
const ifProxyHtml = '✔';
const ifNotProxyHtml = '✘';
const ifAutoHtml = '🔄';
const addOption = function addOption(host, ifProxy) {
const addOption = function addOption(host, yesNoUndefined) {
const opt = document.createElement('option');
opt.value = host;
opt.dataset.host = host;
opt.innerHTML = ifProxy ? ifProxyHtml : '✘';
switch(yesNoUndefined) {
case true:
opt.innerHTML = ifProxyHtml;
break;
case false:
opt.innerHTML = ifNotProxyHtml;
break;
default:
opt.innerHTML = ifAutoHtml;
}
const editorHost = excEditor.value.trim();
if (host === editorHost) {
excList.insertBefore( opt, excList.firstChild );
@ -319,65 +320,99 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
excEditor.onclick = excEditor.oninput = function(event) {
// If triangle button on right of datalist input clicked.
let ifTriangleClicked = false;
const ifClick = event && event.type === 'click';
{
const minIndentFromRightInPx = 15;
if( ifClick
&& !this.selectionStart && !this.selectionStart
&& event.x > this.getBoundingClientRect().right - minIndentFromRightInPx
) {
ifTriangleClicked = true;
}
}
const setInputValue = (newValue) => {
if (event && event.type === 'click') {
if (ifClick && !ifTriangleClicked) {
// Don't jerk cursor on simple clicks.
return;
}
// See bug in my comment to http://stackoverflow.com/a/32394157/521957
// The only shortcoming: first click on empty input may be still ignored.
// First click on empty input may be still ignored.
const nu = this.selectionStart + newValue.length - this.value.length;
this.value = newValue;
excEditor.dataset.moveCursorTo = nu;
window.setTimeout(moveCursorIfNeeded, 0);
}
const host = this.value.trim() || ' ';
setInputValue(host);
const host = this.value.trim();
setInputValue(ifTriangleClicked ? '' : (host || ' '));
thisAuto.checked = true;
this.classList.remove(noClass, yesClass);
let exactOpt = false;
excList.childNodes.forEach(
(opt) => {
if(opt.innerHTML === ifAutoHtml) {
return opt.remove();
}
const ifExactMatch = opt.dataset.host === host;
if (!ifExactMatch) {
return unhideOpt(opt);
}
const exactOpt = opt;
hideOpt(exactOpt);
if(exactOpt.innerHTML === ifProxyHtml) {
thisYes.checked = true;
this.classList.add(yesClass);
} else {
thisNo.checked = true;
this.classList.add(noClass);
}
exactOpt = opt;
}
);
this.parentNode.classList.remove(noClass, yesClass);
if(exactOpt) {
if(ifTriangleClicked) {
unhideOpt(exactOpt);
} else {
hideOpt(exactOpt);
if(exactOpt.innerHTML === ifProxyHtml) {
thisYes.checked = true;
this.parentNode.classList.add(yesClass);
} else {
thisNo.checked = true;
this.parentNode.classList.add(noClass);
}
}
} else if (ifTriangleClicked && host) {
addOption(host, undefined);
}
return true;
};
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]);
}
//excEditor.oninput();
}
excEditor.oninput();
document.getElementById('exc-radio').onclick = function(event) {
/* ON CLICK */
if(event.target.tagName !== 'INPUT') {
// Only label on checkbox.
return true;
}
@ -398,7 +433,7 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
}
if (thisYes.checked && !pacMods.filteredCustomsString) {
showErrors( new TypeError(
'Проксировать СВОИ сайты можно только при наличии СВОИХ прокси (см.«Модификаторы»).'
'Проксировать СВОИ сайты можно только при наличии СВОИХ прокси (см. «Модификаторы» ).'
));
return false;
}
@ -416,6 +451,7 @@ chrome.runtime.getBackgroundPage( (backgroundPage) =>
(opt) => opt.dataset.host === host && opt.remove()
);
fixUi();
console.log(excEditor, excEditor.oninput);
excEditor.oninput();
}
@ -550,7 +586,7 @@ HTTPS 11.22.33.44:8080;">${conf.value || localStorage.getItem(uiRaw) || ''}</tex
});
if( errorHandlers.ifNotControlled ) {
if( !errorHandlers.ifControllable ) {
document.getElementById('which-extension').innerHTML
= backgroundPage.utils.messages.whichExtensionHtml();
document.querySelectorAll('.if-not-controlled').forEach( (node) => {
@ -565,7 +601,7 @@ HTTPS 11.22.33.44:8080;">${conf.value || localStorage.getItem(uiRaw) || ''}</tex
const id = antiCensorRu.getCurrentPacProviderKey() || 'none';
document.querySelector('#update-' + id).click();
}
document.documentElement.style.display = '';
document.documentElement.style.display = 'initial';
console.log(Date.now() - START);