fix: server overrides user's locale/appearance (#2771)

This commit is contained in:
Hanqin Guan 2024-01-16 18:21:08 +08:00 committed by GitHub
parent 24bb3e096a
commit 15e6542f0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 17 deletions

View File

@ -82,12 +82,11 @@ const App = () => {
}, [systemStatus.customizedProfile]);
useEffect(() => {
document.documentElement.setAttribute("lang", locale);
i18n.changeLanguage(locale);
storage.set({
locale: locale,
});
if (locale === "ar") {
const { locale: storageLocale } = storage.get(["locale"]);
const currentLocale = storageLocale || userStore?.userSetting?.locale || locale;
i18n.changeLanguage(currentLocale);
document.documentElement.setAttribute("lang", currentLocale);
if (currentLocale === "ar") {
document.documentElement.setAttribute("dir", "rtl");
} else {
document.documentElement.setAttribute("dir", "ltr");
@ -95,12 +94,9 @@ const App = () => {
}, [locale]);
useEffect(() => {
storage.set({
appearance: appearance,
});
let currentAppearance = appearance;
if (appearance === "system") {
const { appearance: storageAppearance } = storage.get(["appearance"]);
let currentAppearance = (storageAppearance || userStore?.userSetting?.appearance || appearance) as Appearance;
if (currentAppearance === "system") {
currentAppearance = getSystemColorScheme();
}

View File

@ -7,10 +7,9 @@ import store, { useAppSelector } from "../";
import { setAppearance, setGlobalState, setLocale } from "../reducer/global";
export const initialGlobalState = async () => {
const { locale: storageLocale, appearance: storageAppearance } = storage.get(["locale", "appearance"]);
const defaultGlobalState = {
locale: (storageLocale || "en") as Locale,
appearance: (storageAppearance || "system") as Appearance,
locale: "en" as Locale,
appearance: "system" as Appearance,
systemStatus: {
allowSignUp: false,
disablePasswordLogin: false,
@ -44,9 +43,19 @@ export const initialGlobalState = async () => {
externalUrl: "",
},
};
// Use storageLocale > userLocale > customizedProfile.locale (server's default locale)
// Initially, storageLocale is undefined and user is not logged in, so use server's default locale.
// User can change locale in login/sign up page, set storageLocale and override userLocale after logged in.
// Otherwise, storageLocale remains undefined and if userLocale has value after user logged in, set to storageLocale and re-render.
// Otherwise, use server's default locale, set to storageLocale.
const { locale: storageLocale, appearance: storageAppearance } = storage.get(["locale", "appearance"]);
defaultGlobalState.locale =
defaultGlobalState.systemStatus.customizedProfile.locale || defaultGlobalState.locale || findNearestLanguageMatch(i18n.language);
defaultGlobalState.appearance = defaultGlobalState.systemStatus.customizedProfile.appearance || defaultGlobalState.appearance;
storageLocale ||
defaultGlobalState.systemStatus.customizedProfile.locale ||
defaultGlobalState.locale ||
findNearestLanguageMatch(i18n.language);
defaultGlobalState.appearance =
storageAppearance || defaultGlobalState.systemStatus.customizedProfile.appearance || defaultGlobalState.appearance;
}
store.dispatch(setGlobalState(defaultGlobalState));
};
@ -83,9 +92,17 @@ export const useGlobalStore = () => {
);
},
setLocale: (locale: Locale) => {
// Set storageLocale to user selected locale.
storage.set({
locale: locale,
});
store.dispatch(setLocale(locale));
},
setAppearance: (appearance: Appearance) => {
// Set storageAppearance to user selected appearance.
storage.set({
appearance: appearance,
});
store.dispatch(setAppearance(appearance));
},
};

View File

@ -1,6 +1,9 @@
import { create } from "zustand";
import { combine } from "zustand/middleware";
import { authServiceClient, userServiceClient } from "@/grpcweb";
import storage from "@/helpers/storage";
import store from "@/store";
import { setAppearance, setLocale } from "@/store/reducer/global";
import { User, UserSetting } from "@/types/proto/api/v2/user_service";
import { UserNamePrefix, extractUsernameFromName } from "./resourceName";
@ -110,6 +113,22 @@ export const useUserStore = create(
...setting,
}),
});
const userLocale = get().userSetting?.locale;
const userAppearance = get().userSetting?.appearance;
const { locale: storedLocale, appearance: storedAppearance } = storage.get(["locale", "appearance"]);
// Use storageLocale > userLocale > default locale
const locale = storedLocale || userLocale || store.getState().global.locale;
const appearance = (storedAppearance || userAppearance || store.getState().global.appearance) as Appearance;
// If storedLocale is undefined, set storageLocale to userLocale.
if (storedLocale === undefined && storedAppearance === undefined) {
storage.set({ locale: locale });
storage.set({ appearance: appearance });
}
store.dispatch(setLocale(locale));
store.dispatch(setAppearance(appearance));
return user;
},
updateUserSetting: async (userSetting: Partial<UserSetting>, updateMask: string[]) => {