зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1525762: Part 4 - Support automatic dark mode fallback for default theme again. r=aswan
--HG-- extra : rebase_source : 1591ab6670e301e78d98084c852cb72e74ff7504 extra : histedit_source : ec392d6f1b93993bceed5e4bbf3d394b02342794
This commit is contained in:
Родитель
5b06eaa613
Коммит
88035afb21
|
@ -38,14 +38,16 @@ class Theme {
|
|||
* @param {string} extension Extension that created the theme.
|
||||
* @param {Integer} windowId The windowId where the theme is applied.
|
||||
*/
|
||||
constructor({extension, details, windowId, experiment}) {
|
||||
constructor({extension, details, darkDetails, windowId, experiment}) {
|
||||
this.extension = extension;
|
||||
this.details = details;
|
||||
this.darkDetails = darkDetails;
|
||||
this.windowId = windowId;
|
||||
|
||||
this.lwtStyles = {
|
||||
icons: {},
|
||||
};
|
||||
this.lwtDarkStyles = null;
|
||||
|
||||
if (experiment) {
|
||||
const canRunExperiment = AppConstants.MOZ_ALLOW_LEGACY_EXTENSIONS &&
|
||||
|
@ -78,30 +80,23 @@ class Theme {
|
|||
* properties can be found in the schema under ThemeType.
|
||||
*/
|
||||
load() {
|
||||
const {extension, details} = this;
|
||||
|
||||
if (details.colors) {
|
||||
this.loadColors(details.colors);
|
||||
this.loadDetails(this.details, this.lwtStyles);
|
||||
if (this.darkDetails) {
|
||||
this.lwtDarkStyles = {
|
||||
icons: {},
|
||||
};
|
||||
this.loadDetails(this.darkDetails, this.lwtDarkStyles);
|
||||
}
|
||||
|
||||
if (details.images) {
|
||||
this.loadImages(details.images);
|
||||
}
|
||||
|
||||
if (details.icons) {
|
||||
this.loadIcons(details.icons);
|
||||
}
|
||||
|
||||
if (details.properties) {
|
||||
this.loadProperties(details.properties);
|
||||
}
|
||||
|
||||
this.loadMetadata(extension);
|
||||
|
||||
let lwtData = {
|
||||
theme: this.lwtStyles,
|
||||
darkTheme: this.lwtDarkStyles,
|
||||
};
|
||||
|
||||
if (this.experiment) {
|
||||
lwtData.experiment = this.experiment;
|
||||
}
|
||||
|
||||
if (this.windowId) {
|
||||
lwtData.window =
|
||||
getWinUtils(windowTracker.getWindow(this.windowId)).outerWindowID;
|
||||
|
@ -109,24 +104,46 @@ class Theme {
|
|||
} else {
|
||||
windowOverrides.clear();
|
||||
defaultTheme = this;
|
||||
LightweightThemeManager.fallbackThemeData = lwtData;
|
||||
}
|
||||
onUpdatedEmitter.emit("theme-updated", this.details, this.windowId);
|
||||
|
||||
if (this.experiment) {
|
||||
lwtData.experiment = this.experiment;
|
||||
}
|
||||
LightweightThemeManager.fallbackThemeData = this.lwtStyles;
|
||||
Services.obs.notifyObservers(null,
|
||||
"lightweight-theme-styling-update",
|
||||
JSON.stringify(lwtData));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Object} details Details
|
||||
* @param {Object} styles Styles object in which to store the colors.
|
||||
*/
|
||||
loadDetails(details, styles) {
|
||||
if (details.colors) {
|
||||
this.loadColors(details.colors, styles);
|
||||
}
|
||||
|
||||
if (details.images) {
|
||||
this.loadImages(details.images, styles);
|
||||
}
|
||||
|
||||
if (details.icons) {
|
||||
this.loadIcons(details.icons, styles);
|
||||
}
|
||||
|
||||
if (details.properties) {
|
||||
this.loadProperties(details.properties, styles);
|
||||
}
|
||||
|
||||
this.loadMetadata(this.extension, styles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for loading colors found in the extension's manifest.
|
||||
*
|
||||
* @param {Object} colors Dictionary mapping color properties to values.
|
||||
* @param {Object} styles Styles object in which to store the colors.
|
||||
*/
|
||||
loadColors(colors) {
|
||||
loadColors(colors, styles) {
|
||||
for (let color of Object.keys(colors)) {
|
||||
let val = colors[color];
|
||||
|
||||
|
@ -142,27 +159,27 @@ class Theme {
|
|||
switch (color) {
|
||||
case "accentcolor":
|
||||
case "frame":
|
||||
this.lwtStyles.accentcolor = cssColor;
|
||||
styles.accentcolor = cssColor;
|
||||
break;
|
||||
case "frame_inactive":
|
||||
this.lwtStyles.accentcolorInactive = cssColor;
|
||||
styles.accentcolorInactive = cssColor;
|
||||
break;
|
||||
case "textcolor":
|
||||
case "tab_background_text":
|
||||
this.lwtStyles.textcolor = cssColor;
|
||||
styles.textcolor = cssColor;
|
||||
break;
|
||||
case "toolbar":
|
||||
this.lwtStyles.toolbarColor = cssColor;
|
||||
styles.toolbarColor = cssColor;
|
||||
break;
|
||||
case "toolbar_text":
|
||||
case "bookmark_text":
|
||||
this.lwtStyles.toolbar_text = cssColor;
|
||||
styles.toolbar_text = cssColor;
|
||||
break;
|
||||
case "icons":
|
||||
this.lwtStyles.icon_color = cssColor;
|
||||
styles.icon_color = cssColor;
|
||||
break;
|
||||
case "icons_attention":
|
||||
this.lwtStyles.icon_attention_color = cssColor;
|
||||
styles.icon_attention_color = cssColor;
|
||||
break;
|
||||
case "tab_background_separator":
|
||||
case "tab_loading":
|
||||
|
@ -195,11 +212,11 @@ class Theme {
|
|||
case "sidebar_highlight_text":
|
||||
case "toolbar_field_highlight":
|
||||
case "toolbar_field_highlight_text":
|
||||
this.lwtStyles[color] = cssColor;
|
||||
styles[color] = cssColor;
|
||||
break;
|
||||
default:
|
||||
if (this.experiment && this.experiment.colors && color in this.experiment.colors) {
|
||||
this.lwtStyles.experimental.colors[color] = cssColor;
|
||||
styles.experimental.colors[color] = cssColor;
|
||||
} else {
|
||||
const {logger} = this.extension;
|
||||
logger.warn(`Unrecognized theme property found: colors.${color}`);
|
||||
|
@ -213,8 +230,9 @@ class Theme {
|
|||
* Helper method for loading images found in the extension's manifest.
|
||||
*
|
||||
* @param {Object} images Dictionary mapping image properties to values.
|
||||
* @param {Object} styles Styles object in which to store the colors.
|
||||
*/
|
||||
loadImages(images) {
|
||||
loadImages(images, styles) {
|
||||
const {baseURI, logger} = this.extension;
|
||||
|
||||
for (let image of Object.keys(images)) {
|
||||
|
@ -227,18 +245,18 @@ class Theme {
|
|||
switch (image) {
|
||||
case "additional_backgrounds": {
|
||||
let backgroundImages = val.map(img => baseURI.resolve(img));
|
||||
this.lwtStyles.additionalBackgrounds = backgroundImages;
|
||||
styles.additionalBackgrounds = backgroundImages;
|
||||
break;
|
||||
}
|
||||
case "headerURL":
|
||||
case "theme_frame": {
|
||||
let resolvedURL = baseURI.resolve(val);
|
||||
this.lwtStyles.headerURL = resolvedURL;
|
||||
styles.headerURL = resolvedURL;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (this.experiment && this.experiment.images && image in this.experiment.images) {
|
||||
this.lwtStyles.experimental.images[image] = baseURI.resolve(val);
|
||||
styles.experimental.images[image] = baseURI.resolve(val);
|
||||
} else {
|
||||
logger.warn(`Unrecognized theme property found: images.${image}`);
|
||||
}
|
||||
|
@ -252,8 +270,9 @@ class Theme {
|
|||
* Helper method for loading icons found in the extension's manifest.
|
||||
*
|
||||
* @param {Object} icons Dictionary mapping icon properties to extension URLs.
|
||||
* @param {Object} styles Styles object in which to store the colors.
|
||||
*/
|
||||
loadIcons(icons) {
|
||||
loadIcons(icons, styles) {
|
||||
const {baseURI} = this.extension;
|
||||
|
||||
if (!Services.prefs.getBoolPref("extensions.webextensions.themes.icons.enabled")) {
|
||||
|
@ -271,7 +290,7 @@ class Theme {
|
|||
}
|
||||
let variableName = `--${icon}-icon`;
|
||||
let resolvedURL = baseURI.resolve(val);
|
||||
this.lwtStyles.icons[variableName] = resolvedURL;
|
||||
styles.icons[variableName] = resolvedURL;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,10 +300,11 @@ class Theme {
|
|||
* images or icons.
|
||||
*
|
||||
* @param {Object} properties Dictionary mapping properties to values.
|
||||
* @param {Object} styles Styles object in which to store the colors.
|
||||
*/
|
||||
loadProperties(properties) {
|
||||
let additionalBackgroundsCount = (this.lwtStyles.additionalBackgrounds &&
|
||||
this.lwtStyles.additionalBackgrounds.length) || 0;
|
||||
loadProperties(properties, styles) {
|
||||
let additionalBackgroundsCount = (styles.additionalBackgrounds &&
|
||||
styles.additionalBackgrounds.length) || 0;
|
||||
const assertValidAdditionalBackgrounds = (property, valueCount) => {
|
||||
const {logger} = this.extension;
|
||||
if (!additionalBackgroundsCount) {
|
||||
|
@ -313,7 +333,7 @@ class Theme {
|
|||
break;
|
||||
}
|
||||
|
||||
this.lwtStyles.backgroundsAlignment = val.join(",");
|
||||
styles.backgroundsAlignment = val.join(",");
|
||||
break;
|
||||
}
|
||||
case "additional_backgrounds_tiling": {
|
||||
|
@ -322,15 +342,15 @@ class Theme {
|
|||
}
|
||||
|
||||
let tiling = [];
|
||||
for (let i = 0, l = this.lwtStyles.additionalBackgrounds.length; i < l; ++i) {
|
||||
for (let i = 0, l = styles.additionalBackgrounds.length; i < l; ++i) {
|
||||
tiling.push(val[i] || "no-repeat");
|
||||
}
|
||||
this.lwtStyles.backgroundsTiling = tiling.join(",");
|
||||
styles.backgroundsTiling = tiling.join(",");
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if (this.experiment && this.experiment.properties && property in this.experiment.properties) {
|
||||
this.lwtStyles.experimental.properties[property] = val;
|
||||
styles.experimental.properties[property] = val;
|
||||
} else {
|
||||
const {logger} = this.extension;
|
||||
logger.warn(`Unrecognized theme property found: properties.${property}`);
|
||||
|
@ -346,10 +366,11 @@ class Theme {
|
|||
* consumers.
|
||||
*
|
||||
* @param {Object} extension Extension object.
|
||||
* @param {Object} styles Styles object in which to store the colors.
|
||||
*/
|
||||
loadMetadata(extension) {
|
||||
this.lwtStyles.id = extension.id;
|
||||
this.lwtStyles.version = extension.version;
|
||||
loadMetadata(extension, styles) {
|
||||
styles.id = extension.id;
|
||||
styles.version = extension.version;
|
||||
}
|
||||
|
||||
static unload(windowId) {
|
||||
|
@ -363,10 +384,10 @@ class Theme {
|
|||
} else {
|
||||
windowOverrides.clear();
|
||||
defaultTheme = emptyTheme;
|
||||
LightweightThemeManager.fallbackThemeData = null;
|
||||
}
|
||||
onUpdatedEmitter.emit("theme-updated", {}, windowId);
|
||||
|
||||
LightweightThemeManager.fallbackThemeData = null;
|
||||
Services.obs.notifyObservers(null,
|
||||
"lightweight-theme-styling-update",
|
||||
JSON.stringify(lwtData));
|
||||
|
@ -377,12 +398,12 @@ this.theme = class extends ExtensionAPI {
|
|||
onManifestEntry(entryName) {
|
||||
let {extension} = this;
|
||||
let {manifest} = extension;
|
||||
let {theme, theme_experiment} = manifest;
|
||||
|
||||
defaultTheme = new Theme({
|
||||
extension,
|
||||
details: theme,
|
||||
experiment: theme_experiment,
|
||||
details: manifest.theme,
|
||||
darkDetails: manifest.dark_theme,
|
||||
experiment: manifest.theme_experiment,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -641,6 +641,10 @@
|
|||
"theme": {
|
||||
"$ref": "ThemeType"
|
||||
},
|
||||
"dark_theme": {
|
||||
"$ref": "ThemeType",
|
||||
"optional": true
|
||||
},
|
||||
"default_locale": {
|
||||
"type": "string",
|
||||
"optional": true
|
||||
|
|
|
@ -131,18 +131,16 @@ function LightweightThemeConsumer(aDocument) {
|
|||
|
||||
Services.obs.addObserver(this, "lightweight-theme-styling-update");
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/LightweightThemeManager.jsm", this);
|
||||
|
||||
// We're responsible for notifying LightweightThemeManager when the OS is in
|
||||
// dark mode so it can activate the dark theme. We don't want this on Linux
|
||||
// as the default theme picks up the right colors from dark GTK themes.
|
||||
if (AppConstants.platform != "linux") {
|
||||
this._darkThemeMediaQuery = this._win.matchMedia("(-moz-system-dark-theme)");
|
||||
this._darkThemeMediaQuery.addListener(this.LightweightThemeManager);
|
||||
this.LightweightThemeManager.systemThemeChanged(this._darkThemeMediaQuery);
|
||||
this.darkThemeMediaQuery = this._win.matchMedia("(-moz-system-dark-theme)");
|
||||
this.darkThemeMediaQuery.addListener(this);
|
||||
}
|
||||
|
||||
this._update(this.LightweightThemeManager.currentThemeWithPersistedData);
|
||||
const {LightweightThemeManager} = ChromeUtils.import("resource://gre/modules/LightweightThemeManager.jsm");
|
||||
this._update(LightweightThemeManager.themeData);
|
||||
|
||||
this._win.addEventListener("resolutionchange", this);
|
||||
this._win.addEventListener("unload", this, { once: true });
|
||||
|
@ -150,8 +148,6 @@ function LightweightThemeConsumer(aDocument) {
|
|||
|
||||
LightweightThemeConsumer.prototype = {
|
||||
_lastData: null,
|
||||
// Whether a lightweight theme is enabled.
|
||||
_active: false,
|
||||
|
||||
observe(aSubject, aTopic, aData) {
|
||||
if (aTopic != "lightweight-theme-styling-update")
|
||||
|
@ -166,50 +162,54 @@ LightweightThemeConsumer.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
this._update(parsedData.theme, parsedData.experiment);
|
||||
this._update(parsedData, parsedData.experiment);
|
||||
},
|
||||
|
||||
handleEvent(aEvent) {
|
||||
if (aEvent.media == "(-moz-system-dark-theme)") {
|
||||
this._update(this._lastData);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (aEvent.type) {
|
||||
case "resolutionchange":
|
||||
if (this._active) {
|
||||
this._update(this._lastData);
|
||||
}
|
||||
this._update(this._lastData);
|
||||
break;
|
||||
case "unload":
|
||||
Services.obs.removeObserver(this, "lightweight-theme-styling-update");
|
||||
Services.ppmm.sharedData.delete(`theme/${this._winId}`);
|
||||
this._win.removeEventListener("resolutionchange", this);
|
||||
this._win = this._doc = null;
|
||||
if (this._darkThemeMediaQuery) {
|
||||
this._darkThemeMediaQuery.removeListener(this.LightweightThemeManager);
|
||||
this._darkThemeMediaQuery = null;
|
||||
if (this.darkThemeMediaQuery) {
|
||||
this.darkThemeMediaQuery.removeListener(this);
|
||||
this.darkThemeMediaQuery = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
_update(theme, experiment) {
|
||||
this._lastData = theme;
|
||||
if (theme) {
|
||||
theme = LightweightThemeImageOptimizer.optimize(theme, this._win.screen);
|
||||
get darkMode() {
|
||||
return this.darkThemeMediaQuery && this.darkThemeMediaQuery.matches;
|
||||
},
|
||||
|
||||
_update(themeData, experiment) {
|
||||
this._lastData = themeData;
|
||||
|
||||
let theme = themeData.theme;
|
||||
if (themeData.darkTheme && this.darkMode) {
|
||||
theme = themeData.darkTheme;
|
||||
}
|
||||
if (!theme) {
|
||||
theme = { id: DEFAULT_THEME_ID };
|
||||
}
|
||||
|
||||
let active = this._active = (theme.id != DEFAULT_THEME_ID);
|
||||
if (theme) {
|
||||
theme = LightweightThemeImageOptimizer.optimize(theme, this._win.screen);
|
||||
} else {
|
||||
theme = {};
|
||||
}
|
||||
|
||||
// The theme we're switching to can be different from the user-selected
|
||||
// theme. E.g. if the default theme is selected and the OS is in dark mode,
|
||||
// we'd silently activate the dark theme if available. We set an attribute
|
||||
// in that case so stylesheets can differentiate this from the dark theme
|
||||
// being selected explicitly by the user.
|
||||
let isDefaultThemeInDarkMode =
|
||||
theme.id == this.LightweightThemeManager.defaultDarkThemeID &&
|
||||
this.LightweightThemeManager.selectedThemeID == DEFAULT_THEME_ID &&
|
||||
this._darkThemeMediaQuery &&
|
||||
this._darkThemeMediaQuery.matches;
|
||||
let active = this._active = Object.keys(theme).length;
|
||||
|
||||
let root = this._doc.documentElement;
|
||||
|
||||
|
@ -236,13 +236,13 @@ LightweightThemeConsumer.prototype = {
|
|||
_setImage(root, active, "--lwt-additional-images", theme.additionalBackgrounds);
|
||||
_setProperties(root, active, theme);
|
||||
|
||||
if (active) {
|
||||
if (theme.id != DEFAULT_THEME_ID || this.darkMode) {
|
||||
root.setAttribute("lwtheme", "true");
|
||||
} else {
|
||||
root.removeAttribute("lwtheme");
|
||||
root.removeAttribute("lwthemetextcolor");
|
||||
}
|
||||
if (isDefaultThemeInDarkMode) {
|
||||
if (theme.id == DEFAULT_THEME_ID && this.darkMode) {
|
||||
root.setAttribute("lwt-default-theme-in-dark-mode", "true");
|
||||
} else {
|
||||
root.removeAttribute("lwt-default-theme-in-dark-mode");
|
||||
|
|
|
@ -21,7 +21,6 @@ var LightweightThemeManager = {
|
|||
} else {
|
||||
_fallbackThemeData = null;
|
||||
}
|
||||
return _fallbackThemeData;
|
||||
},
|
||||
|
||||
/*
|
||||
|
@ -32,21 +31,10 @@ var LightweightThemeManager = {
|
|||
* locally persisted resources.
|
||||
*/
|
||||
get currentThemeWithFallback() {
|
||||
return _fallbackThemeData;
|
||||
return _fallbackThemeData && _fallbackThemeData.theme;
|
||||
},
|
||||
|
||||
systemThemeChanged() {
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles system theme changes.
|
||||
*
|
||||
* @param aEvent
|
||||
* The MediaQueryListEvent associated with the system theme change.
|
||||
*/
|
||||
handleEvent(aEvent) {
|
||||
if (aEvent.media == "(-moz-system-dark-theme)") {
|
||||
// Meh.
|
||||
}
|
||||
get themeData() {
|
||||
return _fallbackThemeData || {theme: null};
|
||||
},
|
||||
};
|
||||
|
|
|
@ -15,5 +15,28 @@
|
|||
"icons": {"32": "icon.svg"},
|
||||
|
||||
"theme": {
|
||||
},
|
||||
|
||||
"dark_theme": {
|
||||
"colors": {
|
||||
"tab_background_text": "rgb(249, 249, 250)",
|
||||
"icons": "rgb(249, 249, 250, 0.7)",
|
||||
"frame": "hsl(240, 5%, 5%)",
|
||||
"popup": "#4a4a4f",
|
||||
"popup_text": "rgb(249, 249, 250)",
|
||||
"popup_border": "#27272b",
|
||||
"tab_line": "#0a84ff",
|
||||
"toolbar": "hsl(240, 1%, 20%)",
|
||||
"toolbar_bottom_separator": "hsl(240, 5%, 5%)",
|
||||
"toolbar_field": "rgb(71, 71, 73)",
|
||||
"toolbar_field_border": "rgba(249, 249, 250, 0.2)",
|
||||
"toolbar_field_separator": "#5F6670",
|
||||
"toolbar_field_text": "rgb(249, 249, 250)",
|
||||
"ntp_background": "#2A2A2E",
|
||||
"ntp_text": "rgb(249, 249, 250)",
|
||||
"sidebar": "#38383D",
|
||||
"sidebar_text": "rgb(249, 249, 250)",
|
||||
"sidebar_border": "rgba(255, 255, 255, 0.1)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче