Rewrite cosmetics and theme preferences (#1292)

- Cosmetics and theme preferences are now only stored in cookies instead
  of a combination of both cookies and state.

- The theme plugin now supports client hints. This allows the server
  to render a page using the client-preferred theme provided it supplies
  this information (any browser other than Firefox), helping to avoid an
  annoying flash while the page is hydrating.

- The previous workaround using the Nitro plugin has been removed. Its
  functionality is now handled by the Nuxt theme plugin with cleaner
  code.

- All pages and components now use the new plugins.
This commit is contained in:
Sasha Sorokin
2024-07-13 21:20:43 +02:00
committed by GitHub
parent ce4250281f
commit 8704d3acb3
21 changed files with 268 additions and 248 deletions

View File

@@ -1,52 +0,0 @@
export const useCosmetics = () =>
useState("cosmetics", () => {
const cosmetics = useCookie("cosmetics", {
maxAge: 60 * 60 * 24 * 365 * 10,
sameSite: "lax",
secure: true,
httpOnly: false,
path: "/",
});
if (!cosmetics.value) {
cosmetics.value = {
searchLayout: false,
projectLayout: false,
advancedRendering: true,
externalLinksNewTab: true,
notUsingBlockers: false,
hideModrinthAppPromos: false,
preferredDarkTheme: "dark",
searchDisplayMode: {
mod: "list",
plugin: "list",
resourcepack: "gallery",
modpack: "list",
shader: "gallery",
datapack: "list",
user: "list",
collection: "list",
},
hideStagingBanner: false,
};
}
return cosmetics.value;
});
export const saveCosmetics = () => {
const cosmetics = useCosmetics();
console.log("SAVING COSMETICS:");
console.log(cosmetics);
const cosmeticsCookie = useCookie("cosmetics", {
maxAge: 60 * 60 * 24 * 365 * 10,
sameSite: "lax",
secure: true,
httpOnly: false,
path: "/",
});
cosmeticsCookie.value = cosmetics.value;
};

View File

@@ -0,0 +1,7 @@
export function useTheme() {
return useNuxtApp().$theme;
}
export function useCosmetics() {
return useNuxtApp().$cosmetics;
}

View File

@@ -1,58 +0,0 @@
export const useTheme = () =>
useState("theme", () => {
const colorMode = useCookie("color-mode", {
maxAge: 60 * 60 * 24 * 365 * 10,
sameSite: "lax",
secure: true,
httpOnly: false,
path: "/",
});
if (!colorMode.value) {
colorMode.value = {
value: "dark",
preference: "system",
};
}
if (colorMode.value.preference !== "system") {
colorMode.value.value = colorMode.value.preference;
}
return colorMode.value;
});
export const updateTheme = (value, updatePreference = false) => {
const theme = useTheme();
const cosmetics = useCosmetics();
const themeCookie = useCookie("color-mode", {
maxAge: 60 * 60 * 24 * 365 * 10,
sameSite: "lax",
secure: true,
httpOnly: false,
path: "/",
});
if (value === "system") {
theme.value.preference = "system";
const colorSchemeQueryList = window.matchMedia("(prefers-color-scheme: light)");
if (colorSchemeQueryList.matches) {
theme.value.value = "light";
} else {
theme.value.value = cosmetics.value.preferredDarkTheme;
}
} else {
theme.value.value = value;
if (updatePreference) theme.value.preference = value;
}
if (import.meta.client) {
document.documentElement.className = `${theme.value.value}-mode`;
}
themeCookie.value = theme.value;
};
export const DARK_THEMES = ["dark", "oled", "retro"];

View File

@@ -0,0 +1,14 @@
/**
* Creates a computed reference that uses a provide getter function called with an argument representing the current mount state of the component.
* @param getter A getter function that will run with `mounted` argument representing whether or not the component is mounted.
* @returns A computed reference that changes when component becomes mounted or unmounted.
*/
export function useMountedValue<T>(getter: (isMounted: boolean) => T) {
const mounted = ref(getCurrentInstance()?.isMounted ?? false);
onMounted(() => (mounted.value = true));
onUnmounted(() => (mounted.value = false));
return computed(() => getter(mounted.value));
}