Skip to content

Commit

Permalink
Merge branch 'master' of github.com:openstyles/stylus
Browse files Browse the repository at this point in the history
  • Loading branch information
louisgv committed Feb 17, 2022
2 parents 25d6280 + 6fb2727 commit 793f02b
Show file tree
Hide file tree
Showing 36 changed files with 749 additions and 455 deletions.
35 changes: 19 additions & 16 deletions _locales/en/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -623,18 +623,6 @@
"message": "Update style",
"description": "Label for update button"
},
"installPreferSchemeLabel": {
"message": "The style should be applied:"
},
"installPreferSchemeNone": {
"message": "Always"
},
"installPreferSchemeDark": {
"message": "In Dark Mode"
},
"installPreferSchemeLight": {
"message": "In Light Mode"
},
"installUpdate": {
"message": "Install update",
"description": "Label for the button to install an update for a single style"
Expand Down Expand Up @@ -1098,11 +1086,8 @@
"optionsAdvancedNewStyleAsUsercss": {
"message": "Write new style as usercss"
},
"optionsAdvancedAutoSwitchScheme": {
"message": "Toggle Light/Dark Mode styles automatically"
},
"optionsAdvancedAutoSwitchSchemeNever": {
"message": "Never"
"message": "Disabled. The dark/light setting in styles is ignored."
},
"optionsAdvancedAutoSwitchSchemeBySystem": {
"message": "By system preference"
Expand Down Expand Up @@ -1153,6 +1138,9 @@
"message": "Options",
"description": "Heading for options section on manage page."
},
"optionsIconAuto": {
"message": "Match the Dark/Light mode"
},
"optionsIconDark": {
"message": "Dark browser themes"
},
Expand Down Expand Up @@ -1323,6 +1311,21 @@
"message": "Styles before commands",
"description": "Label for the checkbox controlling section order in the popup."
},
"preferScheme": {
"message": "Dark/Light mode preference"
},
"preferSchemeAlways": {
"message": "Currently ignored (the style always applies) because the global Dark/Light mode is disabled"
},
"preferSchemeDark": {
"message": "Dark"
},
"preferSchemeLight": {
"message": "Light"
},
"preferSchemeNone": {
"message": "None (always applied)"
},
"prefShowBadge": {
"message": "Number of styles active for the current site",
"description": "Label for the checkbox controlling toolbar badge text."
Expand Down
122 changes: 57 additions & 65 deletions background/color-scheme.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,33 +4,59 @@
'use strict';

const colorScheme = (() => {
let systemPreferDark = false;
let timePreferDark = false;
const changeListeners = new Set();
const kSTATE = 'schemeSwitcher.enabled';
const kSTART = 'schemeSwitcher.nightStart';
const kEND = 'schemeSwitcher.nightEnd';
const SCHEMES = ['dark', 'light'];
const isDark = {
never: null,
dark: true,
light: false,
system: false,
time: false,
};
let isDarkNow = false;

const checkTime = ['schemeSwitcher.nightStart', 'schemeSwitcher.nightEnd'];
prefs.subscribe(checkTime, (key, value) => {
prefs.subscribe(kSTATE, () => update());
prefs.subscribe([kSTART, kEND], (key, value) => {
updateTimePreferDark();
createAlarm(key, value);
});
checkTime.forEach(key => createAlarm(key, prefs.get(key)));

prefs.subscribe(['schemeSwitcher.enabled'], emitChange);

chrome.alarms.onAlarm.addListener(info => {
if (checkTime.includes(info.name)) {
}, {runNow: true});
chrome.alarms.onAlarm.addListener(({name}) => {
if (name === kSTART || name === kEND) {
updateTimePreferDark();
}
});

updateSystemPreferDark();
updateTimePreferDark();
return {
SCHEMES,
onChange(listener) {
changeListeners.add(listener);
},
/** @param {StyleObj | 'darkUI'} val - the string is used by the built-in dark themer */
shouldIncludeStyle(val) {
return val === 'darkUI'
? isDarkNow
: prefs.get(kSTATE) === 'never' ||
!SCHEMES.includes(val = val.preferScheme) ||
isDarkNow === (val === 'dark');
},
updateSystemPreferDark(val) {
update('system', val);
return true;
},
};

return {shouldIncludeStyle, onChange, updateSystemPreferDark};
function calcTime(key) {
const [h, m] = prefs.get(key).split(':');
return (h * 3600 + m * 60) * 1000;
}

function createAlarm(key, value) {
const date = new Date();
applyDate(date, value);
const [h, m] = value.split(':');
date.setHours(h, m, 0, 0);
if (date.getTime() < Date.now()) {
date.setDate(date.getDate() + 1);
}
Expand All @@ -40,61 +66,27 @@ const colorScheme = (() => {
});
}

function shouldIncludeStyle(style) {
const isDark = style.preferScheme === 'dark';
const isLight = style.preferScheme === 'light';
if (!isDark && !isLight) {
return true;
}
const switcherState = prefs.get('schemeSwitcher.enabled');
if (switcherState === 'never') {
return true;
}
if (switcherState === 'system') {
return systemPreferDark && isDark ||
!systemPreferDark && isLight;
}
return timePreferDark && isDark ||
!timePreferDark && isLight;
}

function updateSystemPreferDark() {
const oldValue = systemPreferDark;
systemPreferDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (systemPreferDark !== oldValue) {
emitChange();
}
return true;
}

function updateTimePreferDark() {
const oldValue = timePreferDark;
const date = new Date();
const now = date.getTime();
applyDate(date, prefs.get('schemeSwitcher.nightStart'));
const start = date.getTime();
applyDate(date, prefs.get('schemeSwitcher.nightEnd'));
const end = date.getTime();
timePreferDark = start > end ?
const now = Date.now() - new Date().setHours(0, 0, 0, 0);
const start = calcTime(kSTART);
const end = calcTime(kEND);
const val = start > end ?
now >= start || now < end :
now >= start && now < end;
if (timePreferDark !== oldValue) {
emitChange();
}
update('time', val);
}

function applyDate(date, time) {
const [h, m] = time.split(':').map(Number);
date.setHours(h, m, 0, 0);
}

function onChange(listener) {
changeListeners.add(listener);
}

function emitChange() {
for (const listener of changeListeners) {
listener();
function update(type, val) {
if (type) {
if (isDark[type] === val) return;
isDark[type] = val;
}
val = isDark[prefs.get(kSTATE)];
if (isDarkNow !== val) {
isDarkNow = val;
for (const listener of changeListeners) {
listener(isDarkNow);
}
}
}
})();
16 changes: 11 additions & 5 deletions background/icon-manager.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/* global API */// msg.js
/* global addAPI bgReady */// common.js
/* global colorScheme */
/* global prefs */
/* global tabMan */
/* global CHROME FIREFOX UA debounce ignoreChromeError */// toolbox.js
Expand All @@ -13,7 +14,7 @@ const iconMan = (() => {
const badgeOvr = {color: '', text: ''};
// https://github.com/openstyles/stylus/issues/1287 Fenix can't use custom ImageData
const FIREFOX_ANDROID = FIREFOX && UA.mobile;

let isDark;
// https://github.com/openstyles/stylus/issues/335
let hasCanvas = FIREFOX_ANDROID ? false : loadImage(`/images/icon/${ICON_SIZES[0]}.png`)
.then(({data}) => (hasCanvas = data.some(b => b !== 255)));
Expand All @@ -37,13 +38,17 @@ const iconMan = (() => {
chrome.webNavigation.onCommitted.addListener(({tabId, frameId}) => {
if (!frameId) tabMan.set(tabId, 'styleIds', undefined);
});

chrome.runtime.onConnect.addListener(port => {
if (port.name === 'iframe') {
port.onDisconnect.addListener(onPortDisconnected);
}
});

colorScheme.onChange(val => {
isDark = val;
if (prefs.get('iconset') === -1) {
debounce(refreshAllIcons);
}
});
bgReady.all.then(() => {
prefs.subscribe([
'disableAll',
Expand Down Expand Up @@ -95,9 +100,10 @@ const iconMan = (() => {
}

function getIconName(hasStyles = false) {
const iconset = prefs.get('iconset') === 1 ? 'light/' : '';
const i = prefs.get('iconset');
const prefix = i === 0 || i === -1 && isDark ? '' : 'light/';
const postfix = prefs.get('disableAll') ? 'x' : !hasStyles ? 'w' : '';
return `${iconset}$SIZE$${postfix}`;
return `${prefix}$SIZE$${postfix}`;
}

function refreshIcon(tabId, force = false) {
Expand Down
13 changes: 7 additions & 6 deletions background/style-manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,11 @@ const styleMan = (() => {
handleDraft(port);
}
});
// function handleColorScheme() {
colorScheme.onChange(() => {
for (const {style: data} of dataMap.values()) {
if (data.preferScheme === 'dark' || data.preferScheme === 'light') {
broadcastStyleUpdated(data, 'colorScheme', undefined, false);
colorScheme.onChange(value => {
msg.broadcastExtension({method: 'colorScheme', value});
for (const {style} of dataMap.values()) {
if (colorScheme.SCHEMES.includes(style.preferScheme)) {
broadcastStyleUpdated(style, 'colorScheme');
}
}
});
Expand Down Expand Up @@ -320,7 +320,8 @@ const styleMan = (() => {
async config(id, prop, value) {
if (ready.then) await ready;
const style = Object.assign({}, id2style(id));
style[prop] = value;
const {preview = {}} = dataMap.get(id);
style[prop] = preview[prop] = value;
return saveStyle(style, {reason: 'config'});
},
};
Expand Down
14 changes: 7 additions & 7 deletions content/apply.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,12 @@
xo.observe(el);
};

// FIXME: move this to background page when following bugs are fixed:
// https://bugzil.la/1587723, https://crbug.com/968651
const mqDark = matchMedia('(prefers-color-scheme: dark)');
mqDark.onchange = e => API.colorScheme.updateSystemPreferDark(e.matches);
mqDark.onchange(mqDark);

// Declare all vars before init() or it'll throw due to "temporal dead zone" of const/let
const ready = init();

Expand All @@ -70,13 +76,6 @@
window.addEventListener(orphanEventId, orphanCheck, true);
}

// detect media change in content script
// FIXME: move this to background page when following bugs are fixed:
// https://bugzilla.mozilla.org/show_bug.cgi?id=1561546
// https://bugs.chromium.org/p/chromium/issues/detail?id=968651
const media = window.matchMedia('(prefers-color-scheme: dark)');
media.addListener(() => API.colorScheme.updateSystemPreferDark().catch(console.error));

function onInjectorUpdate() {
if (!isOrphaned) {
updateCount();
Expand Down Expand Up @@ -265,6 +264,7 @@
// In Chrome content script is orphaned on an extension update/reload
// so we need to detach event listeners
window.removeEventListener(orphanEventId, orphanCheck, true);
mqDark.onchange = null;
isOrphaned = true;
setTimeout(styleInjector.clear, 1000); // avoiding FOUC
tryCatch(msg.off, applyOnMessage);
Expand Down
2 changes: 2 additions & 0 deletions edit.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">

<link href="global.css" rel="stylesheet">
<link href="global-dark.css" rel="stylesheet">
<link id="cm-theme" rel="stylesheet">

<script src="js/polyfill.js"></script>
Expand Down Expand Up @@ -239,6 +240,7 @@
<link href="js/color/color-picker.css" rel="stylesheet">
<link href="edit/codemirror-default.css" rel="stylesheet">
<link href="edit/edit.css" rel="stylesheet">
<script src="js/dark-themer.js"></script> <!-- must be last in HEAD to avoid FOUC -->
</head>

<body id="stylus-edit">
Expand Down
Loading

0 comments on commit 793f02b

Please sign in to comment.