Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Keep all theme-updating logic together #107177

Merged
merged 3 commits into from
Jan 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustdoc/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ impl Options {
// these values up both in `dataset` and in the storage API, so it needs to be able
// to convert the names back and forth. Despite doing this kebab-case to
// StudlyCaps transformation automatically, the JS DOM API does not provide a
// mechanism for doing the just transformation on a string. So we want to avoid
// mechanism for doing just the transformation on a string. So we want to avoid
// the StudlyCaps representation in the `dataset` property.
//
// We solve this by replacing all the `-`s with `_`s. We do that here, when we
Expand Down
4 changes: 2 additions & 2 deletions src/librustdoc/html/static/js/settings.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// Local js definitions:
/* global getSettingValue, getVirtualKey, updateLocalStorage, updateSystemTheme */
/* global getSettingValue, getVirtualKey, updateLocalStorage, updateTheme */
/* global addClass, removeClass, onEach, onEachLazy, blurHandler, elemIsInParent */
/* global MAIN_ID, getVar, getSettingsButton */

Expand All @@ -19,7 +19,7 @@
case "theme":
case "preferred-dark-theme":
case "preferred-light-theme":
updateSystemTheme();
updateTheme();
updateLightAndDark();
break;
case "line-numbers":
Expand Down
112 changes: 52 additions & 60 deletions src/librustdoc/html/static/js/storage.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,79 +153,74 @@ function switchTheme(styleElem, mainStyleElem, newThemeName, saveTheme) {
}
}

// This function is called from "main.js".
// eslint-disable-next-line no-unused-vars
function useSystemTheme(value) {
if (value === undefined) {
value = true;
}

updateLocalStorage("use-system-theme", value);

// update the toggle if we're on the settings page
const toggle = document.getElementById("use-system-theme");
if (toggle && toggle instanceof HTMLInputElement) {
toggle.checked = value;
}
}

const updateSystemTheme = (function() {
if (!window.matchMedia) {
// fallback to the CSS computed value
return () => {
const cssTheme = getComputedStyle(document.documentElement)
.getPropertyValue("content");

switchTheme(
window.currentTheme,
window.mainTheme,
JSON.parse(cssTheme) || "light",
true
);
const updateTheme = (function() {
/**
* Update the current theme to match whatever the current combination of
* * the preference for using the system theme
* (if this is the case, the value of preferred-light-theme, if the
* system theme is light, otherwise if dark, the value of
* preferred-dark-theme.)
* * the preferred theme
* … dictates that it should be.
*/
function updateTheme() {
const use = (theme, saveTheme) => {
switchTheme(window.currentTheme, window.mainTheme, theme, saveTheme);
};
}

// only listen to (prefers-color-scheme: dark) because light is the default
const mql = window.matchMedia("(prefers-color-scheme: dark)");

function handlePreferenceChange(mql) {
const use = theme => {
switchTheme(window.currentTheme, window.mainTheme, theme, true);
};
// maybe the user has disabled the setting in the meantime!
if (getSettingValue("use-system-theme") !== "false") {
const lightTheme = getSettingValue("preferred-light-theme") || "light";
const darkTheme = getSettingValue("preferred-dark-theme") || "dark";

if (mql.matches) {
use(darkTheme);
if (isDarkMode()) {
use(darkTheme, true);
} else {
// prefers a light theme, or has no preference
use(lightTheme);
use(lightTheme, true);
}
// note: we save the theme so that it doesn't suddenly change when
// the user disables "use-system-theme" and reloads the page or
// navigates to another page
} else {
use(getSettingValue("theme"));
use(getSettingValue("theme"), false);
}
}

mql.addListener(handlePreferenceChange);
// This is always updated below to a function () => bool.
let isDarkMode;

return () => {
handlePreferenceChange(mql);
};
})();
// Determine the function for isDarkMode, and if we have
// `window.matchMedia`, set up an event listener on the preferred color
// scheme.
//
// Otherwise, fall back to the prefers-color-scheme value CSS captured in
// the "content" property.
if (window.matchMedia) {
// only listen to (prefers-color-scheme: dark) because light is the default
const mql = window.matchMedia("(prefers-color-scheme: dark)");

function switchToSavedTheme() {
switchTheme(
window.currentTheme,
window.mainTheme,
getSettingValue("theme") || "light",
false
);
}
isDarkMode = () => mql.matches;

if (mql.addEventListener) {
mql.addEventListener("change", updateTheme);
} else {
// This is deprecated, see:
// https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList/addListener
mql.addListener(updateTheme);
}
} else {
// fallback to the CSS computed value
const cssContent = getComputedStyle(document.documentElement)
.getPropertyValue("content");
// (Note: the double-quotes come from that this is a CSS value, which
// might be a length, string, etc.)
const cssColorScheme = cssContent || "\"light\"";
isDarkMode = () => (cssColorScheme === "\"dark\"");
}

return updateTheme;
})();

if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) {
// update the preferred dark theme if the user is already using a dark theme
Expand All @@ -235,13 +230,10 @@ if (getSettingValue("use-system-theme") !== "false" && window.matchMedia) {
&& darkThemes.indexOf(localStoredTheme) >= 0) {
updateLocalStorage("preferred-dark-theme", localStoredTheme);
}

// call the function to initialize the theme at least once!
updateSystemTheme();
} else {
switchToSavedTheme();
}

updateTheme();

if (getSettingValue("source-sidebar-show") === "true") {
// At this point in page load, `document.body` is not available yet.
// Set a class on the `<html>` element instead.
Expand All @@ -259,6 +251,6 @@ if (getSettingValue("source-sidebar-show") === "true") {
// specifically when talking to a remote website with no caching.
window.addEventListener("pageshow", ev => {
if (ev.persisted) {
setTimeout(switchToSavedTheme, 0);
setTimeout(updateTheme, 0);
}
});