fix: store reactive

pull/4394/head
Johnny 3 weeks ago
parent 01a9bb2d49
commit 9027430646

@ -70,6 +70,7 @@ const App = observer(() => {
useEffect(() => {
const currentLocale = workspaceStore.state.locale;
// This will trigger re-rendering of the whole app.
i18n.changeLanguage(currentLocale);
document.documentElement.setAttribute("lang", currentLocale);
if (["ar", "fa"].includes(currentLocale)) {
@ -101,7 +102,7 @@ const App = observer(() => {
return;
}
workspaceStore.setPartial({
workspaceStore.state.setPartial({
locale: userSetting.locale || workspaceStore.state.locale,
appearance: userSetting.appearance || workspaceStore.state.appearance,
});

@ -1,6 +1,6 @@
import { Divider, Option, Select } from "@mui/joy";
import { observer } from "mobx-react-lite";
import { userStore, workspaceStore } from "@/store/v2";
import { userStore } from "@/store/v2";
import { Visibility } from "@/types/proto/api/v1/memo_service";
import { UserSetting } from "@/types/proto/api/v1/user_service";
import { useTranslate } from "@/utils/i18n";
@ -15,7 +15,6 @@ const PreferencesSection = observer(() => {
const setting = userStore.state.userSetting as UserSetting;
const handleLocaleSelectChange = async (locale: Locale) => {
workspaceStore.setPartial({ locale });
await userStore.updateUserSetting(
{
locale,
@ -25,7 +24,6 @@ const PreferencesSection = observer(() => {
};
const handleAppearanceSelectChange = async (appearance: Appearance) => {
workspaceStore.setPartial({ appearance });
await userStore.updateUserSetting(
{
appearance,

@ -13,11 +13,11 @@ const AdminSignIn = observer(() => {
workspaceSettingStore.getWorkspaceSettingByKey(WorkspaceSettingKey.GENERAL).generalSetting || WorkspaceGeneralSetting.fromPartial({});
const handleLocaleSelectChange = (locale: Locale) => {
workspaceStore.setPartial({ locale });
workspaceStore.state.setPartial({ locale });
};
const handleAppearanceSelectChange = (appearance: Appearance) => {
workspaceStore.setPartial({ appearance });
workspaceStore.state.setPartial({ appearance });
};
return (

@ -43,11 +43,11 @@ const SignIn = observer(() => {
}, []);
const handleLocaleSelectChange = (locale: Locale) => {
workspaceStore.setPartial({ locale });
workspaceStore.state.setPartial({ locale });
};
const handleAppearanceSelectChange = (appearance: Appearance) => {
workspaceStore.setPartial({ appearance });
workspaceStore.state.setPartial({ appearance });
};
const handleSignInWithIdentityProvider = async (identityProvider: IdentityProvider) => {

@ -38,11 +38,11 @@ const SignUp = observer(() => {
};
const handleLocaleSelectChange = (locale: Locale) => {
workspaceStore.setPartial({ locale });
workspaceStore.state.setPartial({ locale });
};
const handleAppearanceSelectChange = (appearance: Appearance) => {
workspaceStore.setPartial({ appearance });
workspaceStore.state.setPartial({ appearance });
};
const handleFormSubmit = (e: React.FormEvent<HTMLFormElement>) => {

@ -1,21 +1,29 @@
import { last } from "lodash-es";
import { makeAutoObservable } from "mobx";
import { makeAutoObservable, runInAction } from "mobx";
class LocalState {
stack: string[] = [];
constructor() {
makeAutoObservable(this);
}
setPartial(partial: Partial<LocalState>) {
Object.assign(this, partial);
}
}
const dialogStore = (() => {
const state = makeAutoObservable<{
stack: string[];
}>({
stack: [],
});
const state = new LocalState();
const pushDialog = (name: string) => {
state.stack.push(name);
runInAction(() => state.stack.push(name));
};
const popDialog = () => state.stack.pop();
const popDialog = () => runInAction(() => state.stack.pop());
const removeDialog = (name: string) => {
state.stack = state.stack.filter((n) => n !== name);
runInAction(() => (state.stack = state.stack.filter((n) => n !== name)));
};
const topDialog = last(state.stack);

@ -2,27 +2,26 @@ import { makeAutoObservable } from "mobx";
import { authServiceClient, inboxServiceClient, userServiceClient } from "@/grpcweb";
import { Inbox } from "@/types/proto/api/v1/inbox_service";
import { Shortcut, User, UserSetting } from "@/types/proto/api/v1/user_service";
import workspaceStore from "./workspace";
interface LocalState {
// The name of current user. Format: `users/${uid}`
class LocalState {
currentUser?: string;
// userSetting is the setting of the current user.
userSetting?: UserSetting;
// shortcuts is the list of shortcuts of the current user.
shortcuts: Shortcut[];
// inboxes is the list of inboxes of the current user.
inboxes: Inbox[];
// userMapByName is used to cache user information.
// Key is the `user.name` and value is the `User` object.
userMapByName: Record<string, User>;
shortcuts: Shortcut[] = [];
inboxes: Inbox[] = [];
userMapByName: Record<string, User> = {};
constructor() {
makeAutoObservable(this);
}
setPartial(partial: Partial<LocalState>) {
Object.assign(this, partial);
}
}
const userStore = (() => {
const state = makeAutoObservable<LocalState>({
shortcuts: [],
inboxes: [],
userMapByName: {},
});
const state = new LocalState();
const getOrFetchUserByName = async (name: string) => {
const userMap = state.userMapByName;
@ -32,8 +31,12 @@ const userStore = (() => {
const user = await userServiceClient.getUser({
name: name,
});
userMap[name] = user;
state.userMapByName = userMap;
state.setPartial({
userMapByName: {
...userMap,
[name]: user,
},
});
return user;
};
@ -42,10 +45,12 @@ const userStore = (() => {
user,
updateMask,
});
state.userMapByName = {
...state.userMapByName,
[updatedUser.name]: updatedUser,
};
state.setPartial({
userMapByName: {
...state.userMapByName,
[updatedUser.name]: updatedUser,
},
});
};
const updateUserSetting = async (userSetting: Partial<UserSetting>, updateMask: string[]) => {
@ -53,7 +58,12 @@ const userStore = (() => {
setting: userSetting,
updateMask: updateMask,
});
state.userSetting = UserSetting.fromPartial(updatedUserSetting);
state.setPartial({
userSetting: UserSetting.fromPartial({
...state.userSetting,
...updatedUserSetting,
}),
});
};
const fetchShortcuts = async () => {
@ -62,12 +72,16 @@ const userStore = (() => {
}
const { shortcuts } = await userServiceClient.listShortcuts({ parent: state.currentUser });
state.shortcuts = shortcuts;
state.setPartial({
shortcuts,
});
};
const fetchInboxes = async () => {
const { inboxes } = await inboxServiceClient.listInboxes({});
state.inboxes = inboxes;
state.setPartial({
inboxes,
});
};
const updateInbox = async (inbox: Partial<Inbox>, updateMask: string[]) => {
@ -75,7 +89,14 @@ const userStore = (() => {
inbox,
updateMask,
});
state.inboxes = state.inboxes.map((i) => (i.name === updatedInbox.name ? updatedInbox : i));
state.setPartial({
inboxes: state.inboxes.map((i) => {
if (i.name === updatedInbox.name) {
return updatedInbox;
}
return i;
}),
});
return updatedInbox;
};
@ -94,7 +115,7 @@ export const initialUserStore = async () => {
try {
const currentUser = await authServiceClient.getAuthStatus({});
const userSetting = await userServiceClient.getUserSetting({});
Object.assign(userStore.state, {
userStore.state.setPartial({
currentUser: currentUser.name,
userSetting: UserSetting.fromPartial({
...userSetting,
@ -103,6 +124,10 @@ export const initialUserStore = async () => {
[currentUser.name]: currentUser,
},
});
workspaceStore.state.setPartial({
locale: userSetting.locale,
appearance: userSetting.appearance,
});
} catch {
// Do nothing.
}

@ -1,3 +1,4 @@
import { uniqBy } from "lodash-es";
import { makeAutoObservable } from "mobx";
import { workspaceServiceClient, workspaceSettingServiceClient } from "@/grpcweb";
import { WorkspaceProfile } from "@/types/proto/api/v1/workspace_service";
@ -6,38 +7,48 @@ import { WorkspaceSettingKey } from "@/types/proto/store/workspace_setting";
import { isValidateLocale } from "@/utils/i18n";
import { workspaceSettingNamePrefix } from "../v1";
interface LocalState {
locale: string;
appearance: string;
profile: WorkspaceProfile;
settings: WorkspaceSetting[];
class LocalState {
locale: string = "en";
appearance: string = "system";
profile: WorkspaceProfile = WorkspaceProfile.fromPartial({});
settings: WorkspaceSetting[] = [];
constructor() {
makeAutoObservable(this);
}
setPartial(partial: Partial<LocalState>) {
const finalState = {
...this,
...partial,
};
if (!isValidateLocale(finalState.locale)) {
finalState.locale = "en";
}
if (!["system", "light", "dark"].includes(finalState.appearance)) {
finalState.appearance = "system";
}
Object.assign(this, finalState);
}
}
const workspaceStore = (() => {
const state = makeAutoObservable<LocalState>({
locale: "en",
appearance: "system",
profile: WorkspaceProfile.fromPartial({}),
settings: [],
});
const state = new LocalState();
const generalSetting =
state.settings.find((setting) => setting.name === `${workspaceSettingNamePrefix}${WorkspaceSettingKey.GENERAL}`)?.generalSetting ||
WorkspaceGeneralSetting.fromPartial({});
const setPartial = (partial: Partial<LocalState>) => {
Object.assign(state, partial);
};
const fetchWorkspaceSetting = async (settingKey: WorkspaceSettingKey) => {
const setting = await workspaceSettingServiceClient.getWorkspaceSetting({ name: `${workspaceSettingNamePrefix}${settingKey}` });
state.settings.push(setting);
state.setPartial({
settings: uniqBy([setting, ...state.settings], "name"),
});
};
return {
state,
generalSetting,
setPartial,
fetchWorkspaceSetting,
};
})();
@ -50,17 +61,9 @@ export const initialWorkspaceStore = async () => {
}
const workspaceGeneralSetting = workspaceStore.generalSetting;
let locale = workspaceGeneralSetting.customProfile?.locale;
if (!isValidateLocale(locale)) {
locale = "en";
}
let appearance = workspaceGeneralSetting.customProfile?.appearance;
if (!appearance || !["system", "light", "dark"].includes(appearance)) {
appearance = "system";
}
workspaceStore.setPartial({
locale: locale,
appearance: appearance,
workspaceStore.state.setPartial({
locale: workspaceGeneralSetting.customProfile?.locale,
appearance: workspaceGeneralSetting.customProfile?.appearance,
profile: workspaceProfile,
});
};

Loading…
Cancel
Save