"High contrast appearance" option to override high contrast themes auto-detection.

This commit is contained in:
hackademix 2018-08-13 01:33:40 +02:00
parent e392a73a50
commit af4ec5c169
8 changed files with 99 additions and 41 deletions

View File

@ -177,6 +177,9 @@
"EnforceForTab": { "EnforceForTab": {
"message": "Enable restrictions for this tab" "message": "Enable restrictions for this tab"
}, },
"HighContrast": {
"message": "High contrast appearance"
},
"httpsOnly": { "httpsOnly": {
"message": "Match HTTPS content only" "message": "Match HTTPS content only"
}, },

View File

@ -176,6 +176,9 @@
"EnforceForTab": { "EnforceForTab": {
"message": "Attiva le restrizioni per questa scheda" "message": "Attiva le restrizioni per questa scheda"
}, },
"HighContrast": {
"message": "Aspetto ad alto contrasto"
},
"httpsOnly": { "httpsOnly": {
"message": "Consenti solo contenuti veicolati tramite HTTPS" "message": "Consenti solo contenuti veicolati tramite HTTPS"
}, },

View File

@ -14,7 +14,7 @@
<script src="/common/locale.js"></script> <script src="/common/locale.js"></script>
<script src="/ui/ui.js"></script> <script src="/ui/ui.js"></script>
</head> </head>
<body> <body id="noscript-options">
<div id="header"> <div id="header">
<h1>__MSG_OptionsLong__</h1> <h1>__MSG_OptionsLong__</h1>
<div> <div>
@ -89,6 +89,12 @@
<label for="opt-showFullAddresses" id="lbl-showFullAddresses">__MSG_ShowFullAddresses__</label> <label for="opt-showFullAddresses" id="lbl-showFullAddresses">__MSG_ShowFullAddresses__</label>
</span> </span>
</div> </div>
<div class="opt-group">
<span id="highContrast-opt">
<input type="checkbox" id="opt-highContrast">
<label for="opt-highContrast" id="lbl-highContrast">__MSG_HighContrast__</label>
</span>
</div>
</div> </div>
<h3 class="flextabs__tab"><button class="flextabs__toggle">__MSG_SectionAdvanced__</button></h3> <h3 class="flextabs__tab"><button class="flextabs__toggle">__MSG_SectionAdvanced__</button></h3>

View File

@ -8,6 +8,9 @@
let version = browser.runtime.getManifest().version; let version = browser.runtime.getManifest().version;
document.querySelector("#version").textContent = _("Version", version); document.querySelector("#version").textContent = _("Version", version);
// simple general options // simple general options
let opt = UI.wireOption;
opt("global", o => { opt("global", o => {
if (o) { if (o) {
policy.enforced = !o.checked; policy.enforced = !o.checked;
@ -30,7 +33,6 @@
}); });
opt("xss"); opt("xss");
{ {
let button = document.querySelector("#btn-reset"); let button = document.querySelector("#btn-reset");
button.onclick = async () => { button.onclick = async () => {
@ -173,29 +175,6 @@
// UTILITY FUNCTIONS // UTILITY FUNCTIONS
async function opt(name, storage = "sync", onchange) {
let input = document.querySelector(`#opt-${name}`);
if (!input) {
debug("Checkbox not found %s", name);
return;
}
if (typeof storage === "function") {
input.onchange = e => storage(input);
input.checked = storage(null);
} else {
let obj = UI[storage];
if (!obj) log(storage);
input.checked = obj[name];
if (onchange) onchange(input.checked);
input.onchange = async () => {
obj[name] = input.checked;
await UI.updateSettings({[storage]: obj});
if (onchange) onchange(obj[name]);
}
}
}
function updateRawPolicyEditor() { function updateRawPolicyEditor() {
if (!UI.local.debug) return; if (!UI.local.debug) return;

View File

@ -12,7 +12,7 @@
<script src="/ui/ui.js"></script> <script src="/ui/ui.js"></script>
</head> </head>
<body> <body id="noscript-popup">
<div id="main"> <div id="main">
<div id="top"> <div id="top">
<a aria-role="button" id="close" class="close icon">__MSG_Close__</a> <a aria-role="button" id="close" class="close icon">__MSG_Close__</a>
@ -30,6 +30,12 @@
<a aria-role="button" id="revoke-temp" class="toggle icon">__MSG_RevokeTemp__</a> <a aria-role="button" id="revoke-temp" class="toggle icon">__MSG_RevokeTemp__</a>
</div> </div>
<div id="message" class="hidden"></div> <div id="message" class="hidden"></div>
<div id="high-contrast-chooser" class="opt-group">
<span id="highContrast-opt">
<input type="checkbox" id="opt-highContrast">
<label for="opt-highContrast" id="lbl-highContrast">__MSG_HighContrast__</label>
</span>
</div>
<div id="content"></div> <div id="content"></div>
<div id="sites"></div> <div id="sites"></div>
<div id="buttons"> <div id="buttons">

View File

@ -61,3 +61,7 @@ tr.site {
font-size: 12px !important; font-size: 12px !important;
font-family: arial sans-serif !important; font-family: arial sans-serif !important;
} }
#noscript-popup #high-contrast-chooser {
display: block;
}

View File

@ -409,3 +409,7 @@ legend {
#presets .https-only { #presets .https-only {
display: none; display: none;
} }
#high-contrast-chooser {
display: none;
}

View File

@ -27,10 +27,10 @@ var UI = (() => {
} }
await include(scripts); await include(scripts);
detectHighContrast();
let inited = new Promise(resolve => { let inited = new Promise(resolve => {
let listener = m => { let listener = async m => {
if (m.type === "settings") { if (m.type === "settings") {
UI.policy = new Policy(m.policy); UI.policy = new Policy(m.policy);
UI.snapshot = UI.policy.snapshot; UI.snapshot = UI.policy.snapshot;
@ -44,6 +44,7 @@ var UI = (() => {
} }
resolve(); resolve();
if (UI.onSettings) UI.onSettings(); if (UI.onSettings) UI.onSettings();
await HighContrast.init();
} }
}; };
browser.runtime.onMessage.addListener(listener); browser.runtime.onMessage.addListener(listener);
@ -98,22 +99,74 @@ var UI = (() => {
async openSiteInfo(domain) { async openSiteInfo(domain) {
let url = `/ui/siteInfo.html#${encodeURIComponent(domain)};${UI.tabId}`; let url = `/ui/siteInfo.html#${encodeURIComponent(domain)};${UI.tabId}`;
browser.tabs.create({url}); browser.tabs.create({url});
},
wireOption(name, storage = "sync", onchange) {
let input = document.querySelector(`#opt-${name}`);
if (!input) {
debug("Checkbox not found %s", name);
return;
}
if (typeof storage === "function") {
input.onchange = e => storage(input);
input.checked = storage(null);
} else {
let obj = UI[storage];
if (!obj) log(storage);
input.checked = obj[name];
if (onchange) onchange(input.checked);
input.onchange = async () => {
obj[name] = input.checked;
await UI.updateSettings({[storage]: obj});
if (onchange) onchange(obj[name]);
}
}
return input;
}
};
var HighContrast = {
css: null,
async init() {
this.widget = UI.wireOption("highContrast", "local", value => {
UI.highContrast = value;
this.toggle();
});
await this.toggle();
},
async toggle() {
let hc = "highContrast" in UI ? UI.highContrast : await this.detect();
if (hc) {
if (this.css) {
document.documentElement.appendChild(this.css);
} else {
this.css = await include("/ui/ui-hc.css")
}
} else if (this.css) {
this.css.remove();
}
document.documentElement.classList.toggle("hc", hc);
if (this.widget) {
this.widget.checked = hc;
}
},
detect() {
if ("highContrast" in UI.local) {
UI.highContrast = UI.local.highContrast;
} else {
// auto-detect
let canary = document.createElement("input");
canary.className="https-only";
canary.style.display = "none";
document.body.appendChild(canary);
UI.highContrast = window.getComputedStyle(canary).backgroundImage === "none";
canary.parentNode.removeChild(canary);
}
return UI.highContrast;
} }
}; };
function detectHighContrast() {
// detect high contrast
let canary = document.createElement("input");
canary.className="https-only";
canary.style.display = "none";
document.body.appendChild(canary);
if (UI.highContrast = window.getComputedStyle(canary).backgroundImage === "none") {
include("/ui/ui-hc.css");
document.documentElement.classList.toggle("hc");
}
canary.parentNode.removeChild(canary);
}
function fireOnChange(sitesUI, data) { function fireOnChange(sitesUI, data) {
if (UI.isDirty(true)) { if (UI.isDirty(true)) {
UI.updateSettings({policy: UI.policy}); UI.updateSettings({policy: UI.policy});