mirror of
https://github.com/HangarMC/Hangar.git
synced 2025-02-17 15:01:42 +08:00
chore: cleanup setting handling
This commit is contained in:
parent
6b3bff23e0
commit
f0fced8cd7
@ -8,8 +8,7 @@ import type { HangarNuxtError } from "~/types/components/error";
|
||||
const runtimeConfig = useRuntimeConfig();
|
||||
const authStore = useAuthStore();
|
||||
const settingsStore = useSettingsStore();
|
||||
settingsStore.loadSettingsClient();
|
||||
settingsStore.setupMobile();
|
||||
await settingsStore.loadSettingsClient();
|
||||
useAccentColor();
|
||||
settingsLog("render for user", authStore.user?.name, "with darkmode", settingsStore.darkMode);
|
||||
|
||||
|
@ -1,97 +0,0 @@
|
||||
import localeParser from "accept-language-parser";
|
||||
import { type ComputedRef, type Ref, watch } from "vue";
|
||||
import { type H3Event, setResponseHeader } from "h3";
|
||||
|
||||
export function useSettingsHelper(
|
||||
ssr: boolean,
|
||||
userData: ComputedRef<{ hasUser: boolean; theme?: string; language?: string }>,
|
||||
getThemeCookie: () => string | undefined | null,
|
||||
setTheme: (dark: boolean) => void,
|
||||
saveSettings: () => Promise<void>,
|
||||
darkMode: Ref<boolean>,
|
||||
locale: Ref<string>,
|
||||
i18n: ReturnType<typeof useI18n>
|
||||
) {
|
||||
function loadSettingsServer(event: H3Event) {
|
||||
if (!ssr) return;
|
||||
let newLocale;
|
||||
let theme;
|
||||
if (userData.value.hasUser) {
|
||||
newLocale = userData.value.language || "en";
|
||||
theme = userData.value.theme || "white";
|
||||
settingsLog("user is logged in, locale = " + newLocale + ", theme = " + theme);
|
||||
} else {
|
||||
const acceptLanguageHeader = useRequestHeader("accept-language");
|
||||
if (acceptLanguageHeader) {
|
||||
const supportedLocales = useNuxtApp().$i18n.availableLocales;
|
||||
console.log("supported locales", supportedLocales);
|
||||
const pickedLocale = localeParser.pick(supportedLocales, acceptLanguageHeader);
|
||||
if (!pickedLocale) {
|
||||
settingsLog("user is not logged in and could not pick locale from header, using default...", supportedLocales, acceptLanguageHeader);
|
||||
newLocale = "en";
|
||||
} else {
|
||||
settingsLog("user is not logged in, picking from locale header, locale = " + pickedLocale, supportedLocales, acceptLanguageHeader);
|
||||
newLocale = pickedLocale;
|
||||
}
|
||||
} else {
|
||||
settingsLog("using default locale cause there was no header...");
|
||||
newLocale = "en";
|
||||
}
|
||||
|
||||
const cookie = getThemeCookie();
|
||||
if (cookie) {
|
||||
settingsLog("user is not logged in, using theme from cookie", cookie);
|
||||
theme = cookie === "dark" ? "dark" : "light";
|
||||
} else {
|
||||
setResponseHeader(event, "Accept-CH", "Sec-CH-Prefers-Color-Scheme");
|
||||
setResponseHeader(event, "Vary", "Sec-CH-Prefers-Color-Scheme");
|
||||
setResponseHeader(event, "Critical-CH", "Sec-CH-Prefers-Color-Scheme");
|
||||
const themeHeader = useRequestHeader("sec-ch-prefers-color-scheme");
|
||||
if (themeHeader) {
|
||||
settingsLog("user is not logged in, using theme from header", themeHeader);
|
||||
theme = themeHeader === "dark" ? "dark" : "light";
|
||||
} else {
|
||||
settingsLog("user is not logged in and we got no theme header, using default...", themeHeader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
locale.value = newLocale;
|
||||
setTheme(theme === "dark");
|
||||
}
|
||||
|
||||
watch(darkMode, async (newMode) => {
|
||||
if (ssr) return;
|
||||
await saveSettings();
|
||||
});
|
||||
|
||||
watch(locale, async (newLocale) => {
|
||||
if (!newLocale) return;
|
||||
i18n.locale.value = newLocale;
|
||||
await i18n.loadLocaleMessages(newLocale);
|
||||
|
||||
if (ssr) return;
|
||||
await saveSettings();
|
||||
});
|
||||
|
||||
function loadSettingsClient() {
|
||||
if (ssr) return;
|
||||
let darkMode: boolean;
|
||||
|
||||
const cookie = getThemeCookie();
|
||||
if (userData.value && userData.value.theme) {
|
||||
darkMode = userData.value.theme === "dark";
|
||||
settingsLog("user is logged in, darkmode = " + darkMode);
|
||||
} else if (cookie) {
|
||||
darkMode = cookie === "dark";
|
||||
settingsLog("user is not logged in, using cookie, darkmode = " + darkMode);
|
||||
} else {
|
||||
darkMode = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||
settingsLog("user is not logged in, using media query, darkmode = " + darkMode);
|
||||
}
|
||||
|
||||
setTheme(darkMode);
|
||||
}
|
||||
|
||||
return { loadSettingsServer, loadSettingsClient };
|
||||
}
|
@ -10,8 +10,7 @@ if (!(props.error?.data?.dummyError === true)) {
|
||||
// keep in sync with app.vue, cause reasons
|
||||
const authStore = useAuthStore();
|
||||
const settingsStore = useSettingsStore();
|
||||
settingsStore.loadSettingsClient();
|
||||
settingsStore.setupMobile();
|
||||
await settingsStore.loadSettingsClient();
|
||||
useAccentColor();
|
||||
settingsLog("render for user", authStore.user?.name, "with darkmode", settingsStore.darkMode);
|
||||
useHead({
|
||||
|
@ -1,6 +1,6 @@
|
||||
export default defineNuxtRouteMiddleware((to, from) => {
|
||||
export default defineNuxtRouteMiddleware(async (to, from) => {
|
||||
if (!process.server || to.fullPath.includes("/@vite")) return;
|
||||
const event = useRequestEvent();
|
||||
|
||||
useSettingsStore().loadSettingsServer(event);
|
||||
if (!event) return;
|
||||
await useSettingsStore().loadSettingsServer(event);
|
||||
});
|
||||
|
@ -1,6 +1,5 @@
|
||||
<script lang="ts" setup>
|
||||
const i18n = useI18n();
|
||||
const settings = useSettingsStore();
|
||||
|
||||
const accentColors = [
|
||||
{ value: "blue", text: "Blue" },
|
||||
@ -24,10 +23,16 @@ const accentColors = [
|
||||
];
|
||||
const accentColor = useAccentColor();
|
||||
|
||||
const locale = ref(i18n.locale);
|
||||
const languages = (useRuntimeConfig().public.i18n.configLocales as { code: string; name: string }[]).map((locale) => ({
|
||||
value: locale.code,
|
||||
text: locale.name,
|
||||
}));
|
||||
|
||||
watch(locale, async (newLocale) => {
|
||||
await i18n.loadLocaleMessages(newLocale);
|
||||
i18n.locale.value = newLocale;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -37,6 +42,6 @@ const languages = (useRuntimeConfig().public.i18n.configLocales as { code: strin
|
||||
<InputSelect v-model="accentColor" :values="accentColors" :label="i18n.t('auth.settings.misc.accentColor')" />
|
||||
|
||||
<Alert type="warning" class="my-4">Translations are experimental!</Alert>
|
||||
<InputSelect v-model="settings.locale" :values="languages" :label="i18n.t('auth.settings.misc.language')" />
|
||||
<InputSelect v-model="locale" :values="languages" :label="i18n.t('auth.settings.misc.language')" />
|
||||
</div>
|
||||
</template>
|
||||
|
@ -1,101 +1,129 @@
|
||||
import { watch } from "vue";
|
||||
import { type H3Event, setResponseHeader } from "h3";
|
||||
import localeParser from "accept-language-parser";
|
||||
|
||||
export const useSettingsStore = defineStore("settings", () => {
|
||||
settingsLog("defineSettingsStore");
|
||||
const darkMode = ref(false);
|
||||
const locale = ref("en");
|
||||
|
||||
const mobile = ref(true); // True cause mobile first!!
|
||||
const mobileBreakPoint = 700;
|
||||
const darkMode = ref<boolean>();
|
||||
|
||||
function toggleDarkMode() {
|
||||
darkMode.value = !unref(darkMode);
|
||||
settingsLog("toggleDarkMode", darkMode.value);
|
||||
}
|
||||
|
||||
function enableDarkMode() {
|
||||
darkMode.value = true;
|
||||
settingsLog("enableDarkMode", darkMode.value);
|
||||
}
|
||||
|
||||
function disableDarkMode() {
|
||||
darkMode.value = false;
|
||||
settingsLog("disableDarkMode", darkMode.value);
|
||||
}
|
||||
|
||||
function toggleMobile() {
|
||||
mobile.value = !unref(mobile);
|
||||
}
|
||||
|
||||
function enableMobile() {
|
||||
mobile.value = true;
|
||||
}
|
||||
|
||||
function disableMobile() {
|
||||
mobile.value = false;
|
||||
}
|
||||
|
||||
const authStore = useAuthStore();
|
||||
const userData = computed(() => {
|
||||
return {
|
||||
hasUser: Boolean(authStore.user),
|
||||
theme: authStore.user?.theme,
|
||||
language: authStore.user?.language,
|
||||
};
|
||||
});
|
||||
const i18n = useNuxtApp().$i18n;
|
||||
|
||||
async function saveSettings() {
|
||||
const store = useAuthStore();
|
||||
const data = {
|
||||
theme: darkMode.value ? "dark" : "light",
|
||||
language: locale.value,
|
||||
language: useNuxtApp().$i18n.locale.value,
|
||||
};
|
||||
try {
|
||||
await useInternalApi("users/" + (store.user?.name || "anon") + "/settings/", "post", data);
|
||||
await useInternalApi("users/" + (authStore.user?.name || "anon") + "/settings/", "post", data);
|
||||
if (authStore.user) {
|
||||
authStore.user.theme = data.theme;
|
||||
authStore.user.language = data.language;
|
||||
}
|
||||
} catch (e) {
|
||||
settingsLog("cant save settings", e);
|
||||
}
|
||||
}
|
||||
|
||||
const { loadSettingsServer, loadSettingsClient } = useSettingsHelper(
|
||||
import.meta.env.SSR,
|
||||
userData,
|
||||
() => useCookie("HANGAR_theme").value,
|
||||
(dark) => (darkMode.value = dark),
|
||||
saveSettings,
|
||||
darkMode,
|
||||
locale,
|
||||
useNuxtApp().$i18n
|
||||
);
|
||||
|
||||
function setupMobile() {
|
||||
if (import.meta.env.SSR) return;
|
||||
// For checking if on mobile or not
|
||||
if (innerWidth <= mobileBreakPoint && !mobile.value) {
|
||||
enableMobile();
|
||||
} else if (innerWidth > mobileBreakPoint && mobile) {
|
||||
disableMobile();
|
||||
}
|
||||
addEventListener("resize", () => {
|
||||
if (innerWidth <= mobileBreakPoint && !mobile.value) {
|
||||
enableMobile();
|
||||
} else if (innerWidth > mobileBreakPoint && mobile) {
|
||||
disableMobile();
|
||||
function setupWatcher() {
|
||||
watch([darkMode, () => i18n.locale.value], async (newSettings, oldSettings) => {
|
||||
if (import.meta.env.SSR) return;
|
||||
if (newSettings[0] === (authStore.user?.theme === "dark") && newSettings[1] === authStore.user?.language) {
|
||||
settingsLog("settings did not change, not saving");
|
||||
return;
|
||||
}
|
||||
await saveSettings();
|
||||
});
|
||||
}
|
||||
|
||||
async function loadSettingsServer(event: H3Event) {
|
||||
if (!import.meta.env.SSR) return;
|
||||
let newLocale: string;
|
||||
let newDarkMode: boolean;
|
||||
if (authStore.user) {
|
||||
newLocale = authStore.user.language || "en";
|
||||
newDarkMode = (authStore.user.theme || "light") === "dark";
|
||||
settingsLog("user is logged in, locale = " + newLocale + ", darkMode = " + darkMode.value);
|
||||
} else {
|
||||
const acceptLanguageHeader = useRequestHeader("accept-language");
|
||||
if (acceptLanguageHeader) {
|
||||
const supportedLocales = useNuxtApp().$i18n.availableLocales;
|
||||
const pickedLocale = localeParser.pick(supportedLocales, acceptLanguageHeader);
|
||||
if (!pickedLocale) {
|
||||
settingsLog("user is not logged in and could not pick locale from header, using default...", supportedLocales, acceptLanguageHeader);
|
||||
newLocale = "en";
|
||||
} else {
|
||||
settingsLog("user is not logged in, picking from locale header, locale = " + pickedLocale, supportedLocales, acceptLanguageHeader);
|
||||
newLocale = pickedLocale;
|
||||
}
|
||||
} else {
|
||||
settingsLog("using default locale cause there was no header...");
|
||||
newLocale = "en";
|
||||
}
|
||||
|
||||
const cookie = useCookie("HANGAR_theme").value;
|
||||
if (cookie) {
|
||||
settingsLog("user is not logged in, using theme from cookie", cookie);
|
||||
newDarkMode = cookie === "dark";
|
||||
} else {
|
||||
setResponseHeader(event, "Accept-CH", "Sec-CH-Prefers-Color-Scheme");
|
||||
setResponseHeader(event, "Vary", "Sec-CH-Prefers-Color-Scheme");
|
||||
setResponseHeader(event, "Critical-CH", "Sec-CH-Prefers-Color-Scheme");
|
||||
const themeHeader = useRequestHeader("sec-ch-prefers-color-scheme");
|
||||
if (themeHeader) {
|
||||
settingsLog("user is not logged in, using theme from header", themeHeader);
|
||||
newDarkMode = themeHeader === "dark";
|
||||
} else {
|
||||
settingsLog("user is not logged in and we got no theme header, using default...", themeHeader);
|
||||
newDarkMode = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await i18n.loadLocaleMessages(newLocale);
|
||||
i18n.locale.value = newLocale;
|
||||
darkMode.value = newDarkMode;
|
||||
}
|
||||
|
||||
async function loadSettingsClient() {
|
||||
if (import.meta.env.SSR) return;
|
||||
setupWatcher();
|
||||
|
||||
const cookie = useCookie("HANGAR_theme").value;
|
||||
let newDarkMode;
|
||||
if (authStore.user?.theme) {
|
||||
newDarkMode = authStore.user?.theme === "dark";
|
||||
settingsLog("user is logged in, darkmode = " + darkMode.value);
|
||||
} else if (cookie) {
|
||||
newDarkMode = cookie === "dark";
|
||||
settingsLog("user is not logged in, using cookie, darkmode = " + darkMode.value);
|
||||
} else {
|
||||
newDarkMode = window.matchMedia("(prefers-color-scheme: dark)").matches;
|
||||
settingsLog("user is not logged in, using media query, darkmode = " + darkMode.value);
|
||||
}
|
||||
|
||||
let newLocale = authStore.user?.language;
|
||||
if (newLocale) {
|
||||
settingsLog("user is logged in, language = " + newLocale);
|
||||
} else {
|
||||
newLocale = "en";
|
||||
settingsLog("user is not logged in, using default language");
|
||||
}
|
||||
|
||||
await i18n.loadLocaleMessages(newLocale);
|
||||
i18n.locale.value = newLocale;
|
||||
darkMode.value = newDarkMode;
|
||||
}
|
||||
|
||||
return {
|
||||
darkMode,
|
||||
toggleDarkMode,
|
||||
enableDarkMode,
|
||||
disableDarkMode,
|
||||
mobile,
|
||||
toggleMobile,
|
||||
enableMobile,
|
||||
disableMobile,
|
||||
mobileBreakPoint,
|
||||
loadSettingsServer,
|
||||
loadSettingsClient,
|
||||
setupMobile,
|
||||
locale,
|
||||
};
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user