simplify: move ! modes to explicit global options
This commit is contained in:
parent
33e517c4a9
commit
933191d25c
|
@ -1086,11 +1086,8 @@
|
||||||
"optionsAdvancedNewStyleAsUsercss": {
|
"optionsAdvancedNewStyleAsUsercss": {
|
||||||
"message": "Write new style as usercss"
|
"message": "Write new style as usercss"
|
||||||
},
|
},
|
||||||
"optionsAdvancedAutoSwitchScheme": {
|
|
||||||
"message": "Toggle Light/Dark Mode styles automatically"
|
|
||||||
},
|
|
||||||
"optionsAdvancedAutoSwitchSchemeNever": {
|
"optionsAdvancedAutoSwitchSchemeNever": {
|
||||||
"message": "Never"
|
"message": "Disabled. The dark/light setting in styles is ignored."
|
||||||
},
|
},
|
||||||
"optionsAdvancedAutoSwitchSchemeBySystem": {
|
"optionsAdvancedAutoSwitchSchemeBySystem": {
|
||||||
"message": "By system preference"
|
"message": "By system preference"
|
||||||
|
@ -1312,26 +1309,20 @@
|
||||||
"description": "Label for the checkbox controlling section order in the popup."
|
"description": "Label for the checkbox controlling section order in the popup."
|
||||||
},
|
},
|
||||||
"preferScheme": {
|
"preferScheme": {
|
||||||
"message": "Dark/Light mode preference:"
|
"message": "Dark/Light mode preference"
|
||||||
|
},
|
||||||
|
"preferSchemeAlways": {
|
||||||
|
"message": "Currently ignored (the style always applies) because the global Dark/Light mode is disabled"
|
||||||
},
|
},
|
||||||
"preferSchemeDark": {
|
"preferSchemeDark": {
|
||||||
"message": "Dark"
|
"message": "Dark"
|
||||||
},
|
},
|
||||||
"preferSchemeDarkOnly": {
|
|
||||||
"message": "Dark (strict)"
|
|
||||||
},
|
|
||||||
"preferSchemeLight": {
|
"preferSchemeLight": {
|
||||||
"message": "Light"
|
"message": "Light"
|
||||||
},
|
},
|
||||||
"preferSchemeLightOnly": {
|
|
||||||
"message": "Light (strict)"
|
|
||||||
},
|
|
||||||
"preferSchemeNone": {
|
"preferSchemeNone": {
|
||||||
"message": "None (always applied)"
|
"message": "None (always applied)"
|
||||||
},
|
},
|
||||||
"preferSchemeTip": {
|
|
||||||
"message": "The style will be applied in a matching Dark/Light global mode. For strict options, the mode being active is mandatory, so the style doesn't apply when the mode is 'Never'. For non-strict options, the style also applies when the user doesn't care i.e. the global mode is 'Never'."
|
|
||||||
},
|
|
||||||
"prefShowBadge": {
|
"prefShowBadge": {
|
||||||
"message": "Number of styles active for the current site",
|
"message": "Number of styles active for the current site",
|
||||||
"description": "Label for the checkbox controlling toolbar badge text."
|
"description": "Label for the checkbox controlling toolbar badge text."
|
||||||
|
|
|
@ -8,11 +8,17 @@ const colorScheme = (() => {
|
||||||
const kSTATE = 'schemeSwitcher.enabled';
|
const kSTATE = 'schemeSwitcher.enabled';
|
||||||
const kSTART = 'schemeSwitcher.nightStart';
|
const kSTART = 'schemeSwitcher.nightStart';
|
||||||
const kEND = 'schemeSwitcher.nightEnd';
|
const kEND = 'schemeSwitcher.nightEnd';
|
||||||
const SCHEMES = ['dark', 'light', 'dark!', 'light!']; // ! = only if schemeSwitcher is enabled
|
const SCHEMES = ['dark', 'light'];
|
||||||
const isDark = {never: null, system: false, time: false};
|
const isDark = {
|
||||||
|
never: null,
|
||||||
|
dark: true,
|
||||||
|
light: false,
|
||||||
|
system: false,
|
||||||
|
time: false,
|
||||||
|
};
|
||||||
let isDarkNow = false;
|
let isDarkNow = false;
|
||||||
|
|
||||||
prefs.subscribe(kSTATE, () => emitChange());
|
prefs.subscribe(kSTATE, () => update());
|
||||||
prefs.subscribe([kSTART, kEND], (key, value) => {
|
prefs.subscribe([kSTART, kEND], (key, value) => {
|
||||||
updateTimePreferDark();
|
updateTimePreferDark();
|
||||||
createAlarm(key, value);
|
createAlarm(key, value);
|
||||||
|
@ -28,17 +34,25 @@ const colorScheme = (() => {
|
||||||
onChange(listener) {
|
onChange(listener) {
|
||||||
changeListeners.add(listener);
|
changeListeners.add(listener);
|
||||||
},
|
},
|
||||||
shouldIncludeStyle({preferScheme: val}) {
|
/** @param {StyleObj | 'darkUI'} val - the string is used by the built-in dark themer */
|
||||||
return !SCHEMES.includes(val) ||
|
shouldIncludeStyle(val) {
|
||||||
!val.endsWith('!') && prefs.get(kSTATE) === 'never' ||
|
return val === 'darkUI'
|
||||||
val.startsWith('dark') === isDarkNow;
|
? isDarkNow
|
||||||
|
: prefs.get(kSTATE) === 'never' ||
|
||||||
|
!SCHEMES.includes(val = val.preferScheme) ||
|
||||||
|
isDarkNow === (val === 'dark');
|
||||||
},
|
},
|
||||||
updateSystemPreferDark(val) {
|
updateSystemPreferDark(val) {
|
||||||
emitChange('system', val);
|
update('system', val);
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function calcTime(key) {
|
||||||
|
const [h, m] = prefs.get(key).split(':');
|
||||||
|
return (h * 3600 + m * 60) * 1000;
|
||||||
|
}
|
||||||
|
|
||||||
function createAlarm(key, value) {
|
function createAlarm(key, value) {
|
||||||
const date = new Date();
|
const date = new Date();
|
||||||
const [h, m] = value.split(':');
|
const [h, m] = value.split(':');
|
||||||
|
@ -59,22 +73,20 @@ const colorScheme = (() => {
|
||||||
const val = start > end ?
|
const val = start > end ?
|
||||||
now >= start || now < end :
|
now >= start || now < end :
|
||||||
now >= start && now < end;
|
now >= start && now < end;
|
||||||
emitChange('time', val);
|
update('time', val);
|
||||||
}
|
}
|
||||||
|
|
||||||
function calcTime(key) {
|
function update(type, val) {
|
||||||
const [h, m] = prefs.get(key).split(':');
|
|
||||||
return (h * 3600 + m * 60) * 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
function emitChange(type, val) {
|
|
||||||
if (type) {
|
if (type) {
|
||||||
if (isDark[type] === val) return;
|
if (isDark[type] === val) return;
|
||||||
isDark[type] = val;
|
isDark[type] = val;
|
||||||
}
|
}
|
||||||
isDarkNow = isDark[prefs.get(kSTATE)];
|
val = isDark[prefs.get(kSTATE)];
|
||||||
|
if (isDarkNow !== val) {
|
||||||
|
isDarkNow = val;
|
||||||
for (const listener of changeListeners) {
|
for (const listener of changeListeners) {
|
||||||
listener(isDarkNow);
|
listener(isDarkNow);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -85,7 +85,7 @@
|
||||||
background: linear-gradient(0deg, hsla(180, 100%, 30%, .75) 2px, hsla(180, 100%, 30%, .2) 2px);
|
background: linear-gradient(0deg, hsla(180, 100%, 30%, .75) 2px, hsla(180, 100%, 30%, .2) 2px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media not screen, dark {
|
@media (prefers-color-scheme: dark) {
|
||||||
.CodeMirror-dialog {
|
.CodeMirror-dialog {
|
||||||
background-color: #333;
|
background-color: #333;
|
||||||
}
|
}
|
||||||
|
@ -127,7 +127,7 @@
|
||||||
.cm-s-default .cm-operator { color: #d2c057 }
|
.cm-s-default .cm-operator { color: #d2c057 }
|
||||||
.cm-s-default .cm-string { color: #f28b54 }
|
.cm-s-default .cm-string { color: #f28b54 }
|
||||||
.cm-s-default .cm-variable { color: #d9d9d9 }
|
.cm-s-default .cm-variable { color: #d9d9d9 }
|
||||||
.cm-s-default .cm-variable-2 { color: #05a }
|
.cm-s-default .cm-variable-2 { color: #72b9ff }
|
||||||
.cm-s-default .cm-variable-3 { color: #9bbbdc }
|
.cm-s-default .cm-variable-3 { color: #9bbbdc }
|
||||||
|
|
||||||
@keyframes highlight {
|
@keyframes highlight {
|
||||||
|
|
|
@ -8,9 +8,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div id="ss-scheme">
|
<div id="ss-scheme">
|
||||||
<div i18n-text="preferScheme">
|
<div i18n-text="preferScheme">
|
||||||
<a tabindex="0" data-cmd="note" i18n-title="preferSchemeTip">
|
<div><small id="ss-scheme-off" i18n-text="preferSchemeAlways" hidden></small></div>
|
||||||
<svg class="svg-icon info"><use xlink:href="#svg-icon-help"/></svg>
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
<label i18n-text-append="preferSchemeNone" class="ss-radio">
|
<label i18n-text-append="preferSchemeNone" class="ss-radio">
|
||||||
<input name="ss-scheme" type="radio" value="none">
|
<input name="ss-scheme" type="radio" value="none">
|
||||||
|
@ -18,15 +16,9 @@
|
||||||
<label i18n-text-append="preferSchemeDark" class="ss-radio">
|
<label i18n-text-append="preferSchemeDark" class="ss-radio">
|
||||||
<input name="ss-scheme" type="radio" value="dark">
|
<input name="ss-scheme" type="radio" value="dark">
|
||||||
</label>
|
</label>
|
||||||
<label i18n-text-append="preferSchemeDarkOnly" class="ss-radio">
|
|
||||||
<input name="ss-scheme" type="radio" value="dark!">
|
|
||||||
</label>
|
|
||||||
<label i18n-text-append="preferSchemeLight" class="ss-radio">
|
<label i18n-text-append="preferSchemeLight" class="ss-radio">
|
||||||
<input name="ss-scheme" type="radio" value="light">
|
<input name="ss-scheme" type="radio" value="light">
|
||||||
</label>
|
</label>
|
||||||
<label i18n-text-append="preferSchemeLightOnly" class="ss-radio">
|
|
||||||
<input name="ss-scheme" type="radio" value="light!">
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
<label i18n-text="styleIncludeLabel">
|
<label i18n-text="styleIncludeLabel">
|
||||||
<textarea id="ss-inclusions" spellcheck="false" class="w100"
|
<textarea id="ss-inclusions" spellcheck="false" class="w100"
|
||||||
|
|
|
@ -2,11 +2,12 @@
|
||||||
/* global API */// msg.js
|
/* global API */// msg.js
|
||||||
/* global editor */
|
/* global editor */
|
||||||
/* global helpPopup */// util.js
|
/* global helpPopup */// util.js
|
||||||
|
/* global prefs */
|
||||||
/* global t */// localization.js
|
/* global t */// localization.js
|
||||||
/* global debounce tryURL */// toolbox.js
|
/* global debounce tryURL */// toolbox.js
|
||||||
/* exported StyleSettings */
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
/* exported StyleSettings */
|
||||||
async function StyleSettings() {
|
async function StyleSettings() {
|
||||||
const AUTOSAVE_DELAY = 500; // same as config-dialog.js
|
const AUTOSAVE_DELAY = 500; // same as config-dialog.js
|
||||||
const SS_ID = 'styleSettings';
|
const SS_ID = 'styleSettings';
|
||||||
|
@ -31,6 +32,9 @@ async function StyleSettings() {
|
||||||
initArea('exclusions'),
|
initArea('exclusions'),
|
||||||
];
|
];
|
||||||
update();
|
update();
|
||||||
|
prefs.subscribe('schemeSwitcher.enabled', (_, val) => {
|
||||||
|
$('#ss-scheme-off', ui).hidden = val !== 'never';
|
||||||
|
}, {runNow: true});
|
||||||
window.on(SS_ID, update);
|
window.on(SS_ID, update);
|
||||||
window.on('closeHelp', () => window.off(SS_ID, update), {once: true});
|
window.on('closeHelp', () => window.off(SS_ID, update), {once: true});
|
||||||
helpPopup.show(t(SS_ID), ui, {
|
helpPopup.show(t(SS_ID), ui, {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
@media not screen, dark {
|
@media (prefers-color-scheme: dark) {
|
||||||
:root {
|
:root {
|
||||||
/* Comfortable dark themes don't use absolutes so the range is compressed */
|
/* Comfortable dark themes don't use absolutes so the range is compressed */
|
||||||
--c00: hsl(0, 0%, 80%);
|
--c00: hsl(0, 0%, 80%);
|
||||||
|
|
|
@ -45,7 +45,12 @@ setTimeout(() => !cm && showSpinner($('#header')), 200);
|
||||||
}
|
}
|
||||||
({tabId, initialUrl} = preinit);
|
({tabId, initialUrl} = preinit);
|
||||||
liveReload = initLiveReload();
|
liveReload = initLiveReload();
|
||||||
preinit.tpl.then(el => $('#ss-scheme').append(...$('#ss-scheme', el).children));
|
preinit.tpl.then(el => {
|
||||||
|
$('#ss-scheme').append(...$('#ss-scheme', el).children);
|
||||||
|
prefs.subscribe('schemeSwitcher.enabled', (_, val) => {
|
||||||
|
$('#ss-scheme-off').hidden = val !== 'never';
|
||||||
|
}, {runNow: true});
|
||||||
|
});
|
||||||
|
|
||||||
const [
|
const [
|
||||||
{dup, style, error, sourceCode},
|
{dup, style, error, sourceCode},
|
||||||
|
|
|
@ -4,12 +4,13 @@
|
||||||
/**
|
/**
|
||||||
* This file must be loaded in a <script> tag placed after all the <link> tags
|
* This file must be loaded in a <script> tag placed after all the <link> tags
|
||||||
* that contain dark themes so that the stylesheets are loaded synchronously
|
* that contain dark themes so that the stylesheets are loaded synchronously
|
||||||
* by the time this script runs. The CSS must use `@media not screen, dark {}`
|
* by the time this script runs. The CSS must use `@media (prefers-color-scheme: dark) {}`
|
||||||
* to ensure the rules are loaded before the first paint in inactive state,
|
* to ensure the rules are loaded before the first paint, then we toggle the rule here,
|
||||||
* then we activate it here.
|
* which also happens before the first paint unless the browser "yields", but that's abnormal
|
||||||
|
* and not even a problem in the most popular case of using system dark/light mode.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
API.colorScheme.shouldIncludeStyle({preferScheme: 'dark!'}).then(val => {
|
API.colorScheme.shouldIncludeStyle('darkUI').then(val => {
|
||||||
let isDark = val;
|
let isDark = val;
|
||||||
toggleDarkStyles();
|
toggleDarkStyles();
|
||||||
msg.onExtension(e => {
|
msg.onExtension(e => {
|
||||||
|
@ -21,8 +22,8 @@ API.colorScheme.shouldIncludeStyle({preferScheme: 'dark!'}).then(val => {
|
||||||
function toggleDarkStyles() {
|
function toggleDarkStyles() {
|
||||||
for (const sheet of document.styleSheets) {
|
for (const sheet of document.styleSheets) {
|
||||||
for (const {media: m} of sheet.cssRules) {
|
for (const {media: m} of sheet.cssRules) {
|
||||||
if (m && m[1] === 'dark' && (m[0] === 'screen') !== isDark) {
|
if (m && /dark/.test(m) && (m[0] === 'screen') !== isDark) {
|
||||||
m.mediaText = `${isDark ? '' : 'not '}screen, dark`;
|
m.mediaText = isDark ? 'screen,dark' : 'dark';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
15
options.html
15
options.html
|
@ -52,14 +52,14 @@
|
||||||
<h1 i18n-text="stylePreferSchemeLabel"></h1>
|
<h1 i18n-text="stylePreferSchemeLabel"></h1>
|
||||||
<div class="items">
|
<div class="items">
|
||||||
<div class="radio-group">
|
<div class="radio-group">
|
||||||
<span i18n-text="optionsAdvancedAutoSwitchScheme" class="radio-group-label"></span>
|
<label class="radio-group-item" i18n-text-append="preferSchemeDark">
|
||||||
<label class="radio-group-item">
|
<input type="radio" value="light" name="schemeSwitcher.enabled" class="radio">
|
||||||
<input type="radio" value="never" name="schemeSwitcher.enabled" class="radio">
|
|
||||||
<span i18n-text="optionsAdvancedAutoSwitchSchemeNever"></span>
|
|
||||||
</label>
|
</label>
|
||||||
<label class="radio-group-item">
|
<label class="radio-group-item" i18n-text-append="preferSchemeLight">
|
||||||
|
<input type="radio" value="dark" name="schemeSwitcher.enabled" class="radio">
|
||||||
|
</label>
|
||||||
|
<label class="radio-group-item" i18n-text-append="optionsAdvancedAutoSwitchSchemeBySystem">
|
||||||
<input type="radio" value="system" name="schemeSwitcher.enabled" class="radio">
|
<input type="radio" value="system" name="schemeSwitcher.enabled" class="radio">
|
||||||
<span i18n-text="optionsAdvancedAutoSwitchSchemeBySystem"></span>
|
|
||||||
</label>
|
</label>
|
||||||
<label class="radio-group-item">
|
<label class="radio-group-item">
|
||||||
<input type="radio" value="time" name="schemeSwitcher.enabled" class="radio">
|
<input type="radio" value="time" name="schemeSwitcher.enabled" class="radio">
|
||||||
|
@ -68,6 +68,9 @@
|
||||||
~
|
~
|
||||||
<input type="time" required id="schemeSwitcher.nightEnd">
|
<input type="time" required id="schemeSwitcher.nightEnd">
|
||||||
</label>
|
</label>
|
||||||
|
<label class="radio-group-item" i18n-text-append="optionsAdvancedAutoSwitchSchemeNever">
|
||||||
|
<input type="radio" value="never" name="schemeSwitcher.enabled" class="radio">
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user