Skip to content

Commit f8e2ffa

Browse files
authored
feat(stores/global): use jotai (#3134)
1 parent 127391c commit f8e2ffa

File tree

6 files changed

+53
-35
lines changed

6 files changed

+53
-35
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
"fast-clean": "^1.4.0",
3232
"i18next": "^25.0.1",
3333
"immer": "^10.1.1",
34+
"jotai": "^2.12.5",
3435
"mobx": "^6.13.7",
3536
"mobx-persist-store": "^1.1.8",
3637
"mobx-react-lite": "^4.1.0",

pnpm-lock.yaml

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/Header/SettingModalBtn.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,17 @@
1515
* limitations under the License.
1616
*/
1717
import { ActionIcon } from '@mantine/core';
18+
import { useSetAtom } from 'jotai';
1819

19-
import { globalStore } from '@/stores/global';
20+
import { isSettingsOpenAtom } from '@/stores/global';
2021
import IconSettings from '~icons/material-symbols/settings';
2122

2223
export const SettingModalBtn = () => {
24+
const setIsSettingsOpen = useSetAtom(isSettingsOpenAtom);
25+
2326
return (
2427
<ActionIcon
25-
onClick={() => globalStore.settings.set('isOpen', true)}
28+
onClick={() => setIsSettingsOpen(true)}
2629
variant="light"
2730
size="sm"
2831
>

src/components/page/SettingsModal.tsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,23 @@
1515
* limitations under the License.
1616
*/
1717
import { Divider, InputWrapper, Modal, Text, TextInput } from '@mantine/core';
18+
import { useAtom } from 'jotai';
1819
import { useTranslation } from 'react-i18next';
1920

2021
import { queryClient } from '@/config/global';
21-
import { globalStore } from '@/stores/global';
22+
import { adminKeyAtom, isSettingsOpenAtom } from '@/stores/global';
2223
import { sha } from '~build/git';
2324

2425
const AdminKey = () => {
2526
const { t } = useTranslation();
27+
const [adminKey, setAdminKey] = useAtom(adminKeyAtom);
28+
2629
return (
2730
<TextInput
2831
label={t('settings.adminKey')}
29-
value={globalStore.settings.adminKey}
32+
value={adminKey}
3033
onChange={(e) => {
31-
globalStore.settings.set('adminKey', e.currentTarget.value);
34+
setAdminKey(e.currentTarget.value);
3235
setTimeout(() => {
3336
queryClient.invalidateQueries();
3437
queryClient.refetchQueries();
@@ -52,11 +55,12 @@ const UICommitSha = () => {
5255

5356
export const SettingsModal = () => {
5457
const { t } = useTranslation();
58+
const [isSettingsOpen, setIsSettingsOpen] = useAtom(isSettingsOpenAtom);
5559

5660
return (
5761
<Modal
58-
opened={globalStore.settings.isOpen}
59-
onClose={() => globalStore.settings.set('isOpen', false)}
62+
opened={isSettingsOpen}
63+
onClose={() => setIsSettingsOpen(false)}
6064
centered
6165
title={t('settings.title')}
6266
>

src/config/req.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@
1717

1818
import { notifications } from '@mantine/notifications';
1919
import axios, { AxiosError, type AxiosResponse, HttpStatusCode } from 'axios';
20+
import { getDefaultStore } from 'jotai';
2021
import { stringify } from 'qs';
2122

2223
import {
2324
API_HEADER_KEY,
2425
API_PREFIX,
2526
SKIP_INTERCEPTOR_HEADER,
2627
} from '@/config/constant';
27-
import { globalStore } from '@/stores/global';
28+
import { adminKeyAtom, isSettingsOpenAtom } from '@/stores/global';
2829

2930
export const req = axios.create();
3031

@@ -40,7 +41,8 @@ req.interceptors.request.use((conf) => {
4041
});
4142
};
4243
conf.baseURL = API_PREFIX;
43-
conf.headers.set(API_HEADER_KEY, globalStore.settings.adminKey);
44+
const adminKey = getDefaultStore().get(adminKeyAtom);
45+
conf.headers.set(API_HEADER_KEY, adminKey);
4446
return conf;
4547
});
4648

@@ -84,7 +86,7 @@ req.interceptors.response.use(
8486
});
8587
// Requires to enter admin key at 401
8688
if (res.status === HttpStatusCode.Unauthorized) {
87-
globalStore.settings.set('isOpen', true);
89+
getDefaultStore().set(isSettingsOpenAtom, true);
8890
return Promise.resolve({ data: {} });
8991
}
9092
}

src/stores/global.ts

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,18 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
import { action, observable } from 'mobx';
18-
import { makePersistable } from 'mobx-persist-store';
17+
import { atom } from 'jotai';
18+
import { atomWithStorage } from 'jotai/utils';
1919

20-
/** allow store use `set(key, value)` */
21-
const set = action(function <T, K extends keyof T>(
22-
this: T,
23-
key: K extends 'set' ? never : K,
24-
value: T[K]
25-
) {
26-
this[key as K] = value;
27-
});
20+
// Admin key with persistent storage
21+
export const adminKeyAtom = atomWithStorage<string>(
22+
'settings:adminKey',
23+
'',
24+
undefined,
25+
{
26+
getOnInit: true,
27+
}
28+
);
2829

29-
const settingsStore = observable({
30-
set,
31-
isOpen: false,
32-
adminKey: '',
33-
});
34-
35-
export const globalStore = observable({
36-
settings: settingsStore,
37-
});
38-
39-
makePersistable(settingsStore, {
40-
name: 'settings',
41-
properties: ['adminKey'],
42-
storage: window.localStorage,
43-
});
30+
// Settings modal visibility state
31+
export const isSettingsOpenAtom = atom<boolean>(false);

0 commit comments

Comments
 (0)