"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": {
"message": "Enable restrictions for this tab"
},
"HighContrast": {
"message": "High contrast appearance"
},
"httpsOnly": {
"message": "Match HTTPS content only"
},

View File

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

View File

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

View File

@ -8,6 +8,9 @@
let version = browser.runtime.getManifest().version;
document.querySelector("#version").textContent = _("Version", version);
// simple general options
let opt = UI.wireOption;
opt("global", o => {
if (o) {
policy.enforced = !o.checked;
@ -30,7 +33,6 @@
});
opt("xss");
{
let button = document.querySelector("#btn-reset");
button.onclick = async () => {
@ -173,29 +175,6 @@
// 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() {
if (!UI.local.debug) return;

View File

@ -12,7 +12,7 @@
<script src="/ui/ui.js"></script>
</head>
<body>
<body id="noscript-popup">
<div id="main">
<div id="top">
<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>
</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="sites"></div>
<div id="buttons">

View File

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

View File

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

View File

@ -27,10 +27,10 @@ var UI = (() => {
}
await include(scripts);
detectHighContrast();
let inited = new Promise(resolve => {
let listener = m => {
let listener = async m => {
if (m.type === "settings") {
UI.policy = new Policy(m.policy);
UI.snapshot = UI.policy.snapshot;
@ -44,6 +44,7 @@ var UI = (() => {
}
resolve();
if (UI.onSettings) UI.onSettings();
await HighContrast.init();
}
};
browser.runtime.onMessage.addListener(listener);
@ -98,21 +99,73 @@ var UI = (() => {
async openSiteInfo(domain) {
let url = `/ui/siteInfo.html#${encodeURIComponent(domain)};${UI.tabId}`;
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;
}
};
function detectHighContrast() {
// detect high contrast
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);
if (UI.highContrast = window.getComputedStyle(canary).backgroundImage === "none") {
include("/ui/ui-hc.css");
document.documentElement.classList.toggle("hc");
}
UI.highContrast = window.getComputedStyle(canary).backgroundImage === "none";
canary.parentNode.removeChild(canary);
}
return UI.highContrast;
}
};
function fireOnChange(sitesUI, data) {
if (UI.isDirty(true)) {