"High contrast appearance" option to override high contrast themes auto-detection.
This commit is contained in:
parent
e392a73a50
commit
af4ec5c169
|
@ -177,6 +177,9 @@
|
|||
"EnforceForTab": {
|
||||
"message": "Enable restrictions for this tab"
|
||||
},
|
||||
"HighContrast": {
|
||||
"message": "High contrast appearance"
|
||||
},
|
||||
"httpsOnly": {
|
||||
"message": "Match HTTPS content only"
|
||||
},
|
||||
|
|
|
@ -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"
|
||||
},
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -61,3 +61,7 @@ tr.site {
|
|||
font-size: 12px !important;
|
||||
font-family: arial sans-serif !important;
|
||||
}
|
||||
|
||||
#noscript-popup #high-contrast-chooser {
|
||||
display: block;
|
||||
}
|
||||
|
|
|
@ -409,3 +409,7 @@ legend {
|
|||
#presets .https-only {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#high-contrast-chooser {
|
||||
display: none;
|
||||
}
|
||||
|
|
83
src/ui/ui.js
83
src/ui/ui.js
|
@ -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,22 +99,74 @@ 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;
|
||||
}
|
||||
};
|
||||
|
||||
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) {
|
||||
if (UI.isDirty(true)) {
|
||||
UI.updateSettings({policy: UI.policy});
|
||||
|
|
Loading…
Reference in New Issue