@lobehub/chat 0.53.0 → 0.54.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,56 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ### [Version 0.54.1](https://github.com/lobehub/lobe-chat/compare/v0.54.0...v0.54.1)
6
+
7
+ <sup>Released on **2023-08-16**</sup>
8
+
9
+ #### 🐛 Bug Fixes
10
+
11
+ - **misc**: 修正 i18n 失效的问题.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### What's fixed
19
+
20
+ - **misc**: 修正 i18n 失效的问题, closes [#80](https://github.com/lobehub/lobe-chat/issues/80) ([b8d957b](https://github.com/lobehub/lobe-chat/commit/b8d957b))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
30
+ ## [Version 0.54.0](https://github.com/lobehub/lobe-chat/compare/v0.53.0...v0.54.0)
31
+
32
+ <sup>Released on **2023-08-15**</sup>
33
+
34
+ #### ✨ Features
35
+
36
+ - **misc**: Add new features and improve user interface and functionality.
37
+
38
+ <br/>
39
+
40
+ <details>
41
+ <summary><kbd>Improvements and Fixes</kbd></summary>
42
+
43
+ #### What's improved
44
+
45
+ - **misc**: Add new features and improve user interface and functionality ([1543bd1](https://github.com/lobehub/lobe-chat/commit/1543bd1))
46
+
47
+ </details>
48
+
49
+ <div align="right">
50
+
51
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
52
+
53
+ </div>
54
+
5
55
  ## [Version 0.53.0](https://github.com/lobehub/lobe-chat/compare/v0.52.1...v0.53.0)
6
56
 
7
57
  <sup>Released on **2023-08-15**</sup>
@@ -72,7 +72,7 @@
72
72
  },
73
73
  "inputTemplate": {
74
74
  "desc": "The latest user message will be filled into this template",
75
- "placeholder": "Enter the input template, {text} will be replaced with real-time input information",
75
+ "placeholder": "{{text}} will be replaced with real-time input information",
76
76
  "title": "User Input Preprocessing"
77
77
  },
78
78
  "title": "Chat Settings"
@@ -72,7 +72,7 @@
72
72
  },
73
73
  "inputTemplate": {
74
74
  "desc": "用户最新的一条消息会填充到此模板",
75
- "placeholder": "输入预处理模版,{text} 将替换为实时输入信息",
75
+ "placeholder": "预处理模版 {{text}} 将替换为实时输入信息",
76
76
  "title": "用户输入预处理"
77
77
  },
78
78
  "title": "聊天设置"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lobehub/chat",
3
- "version": "0.53.0",
3
+ "version": "0.54.1",
4
4
  "description": "Lobe Chat is an open-source chatbot client using LangChain, Typescript and Next.js",
5
5
  "keywords": [
6
6
  "chatbot",
Binary file
@@ -0,0 +1,77 @@
1
+ import { Icon, IconProps } from '@lobehub/ui';
2
+ import { SelectProps } from 'antd';
3
+ import { type CSSProperties, ReactNode, memo, useEffect, useState } from 'react';
4
+ import { Flexbox } from 'react-layout-kit';
5
+
6
+ import { useStyles } from './styles';
7
+
8
+ export interface SelectWithImgOptionItem {
9
+ icon?: IconProps['icon'];
10
+ img: string;
11
+ label: ReactNode;
12
+ value: string;
13
+ }
14
+
15
+ export interface SelectWithImgProps {
16
+ className?: string;
17
+ defaultValue?: SelectProps['defaultValue'];
18
+ imgClassName?: string;
19
+ imgStyle?: CSSProperties;
20
+ onChange?: (value: this['value']) => void;
21
+ options?: SelectWithImgOptionItem[];
22
+ size?: number;
23
+ style?: CSSProperties;
24
+ value?: SelectProps['value'];
25
+ }
26
+
27
+ const SelectWithImg = memo<SelectWithImgProps>(
28
+ ({
29
+ className,
30
+ style,
31
+ value,
32
+ defaultValue,
33
+ onChange,
34
+ options,
35
+ size = 100,
36
+ imgStyle,
37
+ imgClassName,
38
+ }) => {
39
+ const [currentValue, setCurrentValue] = useState(value || defaultValue);
40
+ const { styles, cx } = useStyles();
41
+
42
+ useEffect(() => {
43
+ onChange?.(currentValue);
44
+ }, [currentValue]);
45
+
46
+ return (
47
+ <Flexbox className={className} gap={8} horizontal style={style}>
48
+ {options?.map((item) => {
49
+ const isActive = value ? item.value === value : item.value === currentValue;
50
+ return (
51
+ <Flexbox
52
+ align={'center'}
53
+ className={cx(styles.container, isActive && styles.active)}
54
+ gap={4}
55
+ key={item.value}
56
+ onClick={() => setCurrentValue(item.value)}
57
+ >
58
+ <img
59
+ alt={item.value}
60
+ className={imgClassName}
61
+ src={item.img}
62
+ style={imgStyle}
63
+ width={size}
64
+ />
65
+ <Flexbox align={'center'} gap={4} horizontal>
66
+ {item.icon && <Icon icon={item.icon} />}
67
+ {item.label}
68
+ </Flexbox>
69
+ </Flexbox>
70
+ );
71
+ })}
72
+ </Flexbox>
73
+ );
74
+ },
75
+ );
76
+
77
+ export default SelectWithImg;
@@ -0,0 +1,27 @@
1
+ import { createStyles } from 'antd-style';
2
+
3
+ export const useStyles = createStyles(({ css, token }) => ({
4
+ active: css`
5
+ color: ${token.colorText};
6
+
7
+ > img {
8
+ box-shadow: 0 0 0 1px ${token.colorTextDescription};
9
+ }
10
+ `,
11
+ container: css`
12
+ cursor: pointer;
13
+ color: ${token.colorTextDescription};
14
+
15
+ > img {
16
+ overflow: hidden;
17
+ border-radius: ${token.borderRadius}px;
18
+ box-shadow: 0 0 0 1px ${token.colorBorder};
19
+ transition: all 100ms ${token.motionEaseOut};
20
+
21
+ &:hover {
22
+ border-color: ${token.colorText};
23
+ box-shadow: 0 0 0 2px ${token.colorText};
24
+ }
25
+ }
26
+ `,
27
+ }));
@@ -1,11 +1,12 @@
1
1
  import { Form, ItemGroup, SliderWithInput } from '@lobehub/ui';
2
- import { ConfigProvider, Input, Segmented, Select, Switch } from 'antd';
3
- import { useTheme } from 'antd-style';
2
+ import { ConfigProvider, Input, Select, Switch } from 'antd';
3
+ import { useTheme, useThemeMode } from 'antd-style';
4
4
  import { debounce } from 'lodash-es';
5
- import { BrainCog, MessagesSquare } from 'lucide-react';
5
+ import { BrainCog, LayoutList, MessageSquare, MessagesSquare } from 'lucide-react';
6
6
  import { memo, useMemo } from 'react';
7
7
  import { useTranslation } from 'react-i18next';
8
8
 
9
+ import SelectWithImg from '@/components/SelectWithImg';
9
10
  import { FORM_STYLE } from '@/const/layoutTokens';
10
11
  import { AgentAction } from '@/store/session/slices/agentConfig';
11
12
  import { LanguageModel } from '@/types/llm';
@@ -26,17 +27,36 @@ export interface AgentConfigProps {
26
27
  const AgentConfig = memo<AgentConfigProps>(({ config, updateConfig }) => {
27
28
  const { t } = useTranslation('setting');
28
29
  const theme = useTheme();
30
+ const { isDarkMode } = useThemeMode();
29
31
 
30
32
  const chat: SettingItemGroup = useMemo(
31
33
  () => ({
32
34
  children: [
33
35
  {
34
36
  children: (
35
- <Segmented
37
+ <SelectWithImg
38
+ imgStyle={{
39
+ background: `linear-gradient(
40
+ to bottom,
41
+ ${isDarkMode ? theme.colorBgElevated : theme.colorBgLayout},
42
+ ${theme.colorBgContainer}
43
+ )`,
44
+ }}
36
45
  options={[
37
- { label: t('settingChat.chatStyleType.type.chat'), value: 'chat' },
38
- { label: t('settingChat.chatStyleType.type.docs'), value: 'docs' },
46
+ {
47
+ icon: MessagesSquare,
48
+ img: `/images/chatmode_chat_${isDarkMode ? 'dark' : 'light'}.webp`,
49
+ label: t('settingChat.chatStyleType.type.chat'),
50
+ value: 'chat',
51
+ },
52
+ {
53
+ icon: LayoutList,
54
+ img: `/images/chatmode_docs_${isDarkMode ? 'dark' : 'light'}.webp`,
55
+ label: t('settingChat.chatStyleType.type.docs'),
56
+ value: 'docs',
57
+ },
39
58
  ]}
59
+ size={144}
40
60
  />
41
61
  ),
42
62
  label: t('settingChat.chatStyleType.title'),
@@ -80,7 +100,7 @@ const AgentConfig = memo<AgentConfigProps>(({ config, updateConfig }) => {
80
100
  name: 'compressThreshold',
81
101
  },
82
102
  ],
83
- icon: MessagesSquare,
103
+ icon: MessageSquare,
84
104
  title: t('settingChat.title'),
85
105
  }),
86
106
  [config],
@@ -3,22 +3,26 @@ import { App, ConfigProvider } from 'antd';
3
3
  import { useThemeMode } from 'antd-style';
4
4
  import 'antd/dist/reset.css';
5
5
  import Zh_CN from 'antd/locale/zh_CN';
6
+ import { changeLanguage } from 'i18next';
6
7
  import { PropsWithChildren, memo, useCallback, useEffect } from 'react';
7
8
 
8
- import { useGlobalStore } from '@/store/global';
9
+ import { createI18nNext } from '@/locales/create';
10
+ import { useGlobalStore, useOnFinishHydrationGlobal } from '@/store/global';
9
11
  import { useSessionStore } from '@/store/session';
10
12
  import { GlobalStyle } from '@/styles';
11
13
 
12
- import i18n from '../locales';
13
14
  import { useStyles } from './style';
14
15
 
16
+ const i18n = createI18nNext();
17
+
15
18
  const Layout = memo<PropsWithChildren>(({ children }) => {
16
19
  const { styles } = useStyles();
17
20
 
18
- useEffect(() => {
19
- // 用一种比较奇怪的方式import 了 18n
20
- i18n.finally(() => {});
21
- }, []);
21
+ useOnFinishHydrationGlobal((state) => {
22
+ i18n.then(() => {
23
+ changeLanguage(state.settings.language);
24
+ });
25
+ });
22
26
 
23
27
  return (
24
28
  <ConfigProvider locale={Zh_CN}>
@@ -7,12 +7,13 @@ import type { Namespaces } from '@/types/locale';
7
7
 
8
8
  import resources from './resources';
9
9
 
10
- export const createI18nNext = (namespace?: Namespaces[] | Namespaces) => {
11
- const ns: Namespaces[] = namespace
12
- ? isArray(namespace)
13
- ? ['error', 'common', ...namespace]
14
- : ['error', 'common', namespace]
15
- : ['error', 'common'];
10
+ export const createI18nNext = (params: { namespace?: Namespaces[] | Namespaces } = {}) => {
11
+ const { namespace } = params;
12
+
13
+ const ns: Namespaces[] = isArray(namespace)
14
+ ? ['error', 'common', ...namespace]
15
+ : (['error', 'common', namespace].filter(Boolean) as Namespaces[]);
16
+
16
17
  return (
17
18
  i18n
18
19
  // detect user language
@@ -23,9 +24,12 @@ export const createI18nNext = (namespace?: Namespaces[] | Namespaces) => {
23
24
  // init i18next
24
25
  // for all options read: https://www.i18next.com/overview/configuration-options
25
26
  .init({
26
- // @ts-ignore
27
27
  debug: process.env.NODE_ENV === 'development',
28
28
  defaultNS: ns,
29
+ // LanguageDetector config, refs: https://github.com/i18next/i18next-browser-languageDetector
30
+ detection: {
31
+ caches: [],
32
+ },
29
33
  fallbackLng: 'zh-CN',
30
34
  interpolation: {
31
35
  escapeValue: false, // not needed for react as it escapes by default
@@ -72,7 +72,7 @@ export default {
72
72
  },
73
73
  inputTemplate: {
74
74
  desc: '用户最新的一条消息会填充到此模板',
75
- placeholder: '输入预处理模版,{text} 将替换为实时输入信息',
75
+ placeholder: '预处理模版 {{text}} 将替换为实时输入信息',
76
76
  title: '用户输入预处理',
77
77
  },
78
78
  title: '聊天设置',
@@ -1,3 +1,15 @@
1
- const resources = {} as const;
1
+ import common from '../../../locales/en_US/common.json';
2
+ import empty from '../../../locales/en_US/empty.json';
3
+ import error from '../../../locales/en_US/error.json';
4
+ import plugin from '../../../locales/en_US/plugin.json';
5
+ import setting from '../../../locales/en_US/setting.json';
6
+
7
+ const resources = {
8
+ common,
9
+ empty,
10
+ error,
11
+ plugin,
12
+ setting,
13
+ } as const;
2
14
 
3
15
  export default resources;
@@ -16,6 +16,9 @@ const useStyles = createStyles(({ css, prefixCls, token }) => ({
16
16
  background: ${token.colorFillTertiary};
17
17
  }
18
18
  }
19
+ .${prefixCls}-collapse-content {
20
+ border-radius: 0 !important;
21
+ }
19
22
  .${prefixCls}-collapse-content-box {
20
23
  padding: 0 !important;
21
24
  }
@@ -35,7 +35,7 @@ export const FormAction = memo<{
35
35
 
36
36
  return (
37
37
  <Center gap={16} style={{ maxWidth: 300 }}>
38
- <Avatar avatar={avatar} background={theme.colorText} gap={12} size={80} />
38
+ <Avatar avatar={avatar} background={theme.colorFillContent} gap={12} size={80} />
39
39
  <Flexbox style={{ fontSize: 20 }}>{title}</Flexbox>
40
40
  <Flexbox className={styles.desc}>{description}</Flexbox>
41
41
  {children}
@@ -1,16 +1,14 @@
1
- import { ChatHeader, ChatHeaderTitle, Tag } from '@lobehub/ui';
1
+ import { ChatHeader, ChatHeaderTitle } from '@lobehub/ui';
2
2
  import Router from 'next/router';
3
3
  import { memo } from 'react';
4
4
  import { useTranslation } from 'react-i18next';
5
5
 
6
- import pkg from '@/../package.json';
7
-
8
6
  const Header = memo(() => {
9
7
  const { t } = useTranslation('setting');
10
8
 
11
9
  return (
12
10
  <ChatHeader
13
- left={<ChatHeaderTitle tag={<Tag>{`v${pkg.version}`}</Tag>} title={t('header.global')} />}
11
+ left={<ChatHeaderTitle title={t('header.global')} />}
14
12
  onBackClick={() => Router.back()}
15
13
  showBackButton
16
14
  />
@@ -1,12 +1,13 @@
1
- import { Form, type ItemGroup, SliderWithInput, ThemeSwitch } from '@lobehub/ui';
1
+ import { Form, type ItemGroup, SliderWithInput } from '@lobehub/ui';
2
2
  import { Form as AntForm, App, Button, Input, Select } from 'antd';
3
3
  import isEqual from 'fast-deep-equal';
4
4
  import { changeLanguage } from 'i18next';
5
5
  import { debounce } from 'lodash-es';
6
- import { AppWindow, Palette, Webhook } from 'lucide-react';
6
+ import { AppWindow, Monitor, Moon, Palette, Sun, Webhook } from 'lucide-react';
7
7
  import { memo, useCallback, useMemo } from 'react';
8
8
  import { useTranslation } from 'react-i18next';
9
9
 
10
+ import SelectWithImg from '@/components/SelectWithImg';
10
11
  import { FORM_STYLE } from '@/const/layoutTokens';
11
12
  import { DEFAULT_SETTINGS } from '@/const/settings';
12
13
  import AvatarWithUpload from '@/features/AvatarWithUpload';
@@ -76,18 +77,33 @@ const Common = memo(() => {
76
77
  },
77
78
  {
78
79
  children: (
79
- <ThemeSwitch
80
- labels={{
81
- auto: t('settingTheme.themeMode.auto'),
82
- dark: t('settingTheme.themeMode.dark'),
83
- light: t('settingTheme.themeMode.light'),
84
- }}
85
- onThemeSwitch={setThemeMode}
86
- themeMode={settings.themeMode}
87
- type={'select'}
80
+ <SelectWithImg
81
+ defaultValue={settings.themeMode}
82
+ onChange={setThemeMode}
83
+ options={[
84
+ {
85
+ icon: Sun,
86
+ img: '/images/theme_light.webp',
87
+ label: t('settingTheme.themeMode.light'),
88
+ value: 'light',
89
+ },
90
+ {
91
+ icon: Moon,
92
+ img: '/images/theme_dark.webp',
93
+ label: t('settingTheme.themeMode.dark'),
94
+ value: 'dark',
95
+ },
96
+ {
97
+ icon: Monitor,
98
+ img: '/images/theme_auto.webp',
99
+ label: t('settingTheme.themeMode.auto'),
100
+ value: 'auto',
101
+ },
102
+ ]}
88
103
  />
89
104
  ),
90
105
  label: t('settingTheme.themeMode.title'),
106
+ minWidth: undefined,
91
107
  },
92
108
  {
93
109
  children: (
@@ -1,46 +1,97 @@
1
- import { Segmented } from 'antd';
1
+ import { GridBackground, Icon, Logo, TabsNav } from '@lobehub/ui';
2
2
  import { createStyles } from 'antd-style';
3
+ import { PackageCheck } from 'lucide-react';
4
+ import { rgba } from 'polished';
3
5
  import { memo, useState } from 'react';
4
6
  import { useTranslation } from 'react-i18next';
5
- import { Center } from 'react-layout-kit';
7
+ import { Center, Flexbox } from 'react-layout-kit';
8
+
9
+ import pkg from '@/../package.json';
6
10
 
7
11
  import Agent from './Agent';
8
12
  import Common from './Common';
9
13
 
10
- const useStyles = createStyles(({ css, token }) => ({
14
+ const useStyles = createStyles(({ css, token, isDarkMode }) => ({
15
+ background: css`
16
+ position: absolute;
17
+ bottom: -10%;
18
+ left: 0;
19
+ width: 100%;
20
+ `,
21
+ logo: css`
22
+ position: absolute;
23
+ top: 50%;
24
+ left: 32px;
25
+ transform: translateY(-50%);
26
+ `,
11
27
  tabs: css`
28
+ position: relative;
29
+
30
+ overflow: hidden;
31
+
32
+ width: 100%;
33
+ max-width: 1024px;
34
+ height: 160px;
12
35
  padding: 4px;
36
+
37
+ background: radial-gradient(
38
+ 120% 120% at 20% 100%,
39
+ ${isDarkMode ? rgba(token.colorBgContainer, 0.5) : token.colorBgContainer} 32%,
40
+ ${isDarkMode ? token.colorPrimaryBgHover : rgba(token.colorPrimaryBgHover, 0.3)} 50%,
41
+ ${isDarkMode ? token.colorPrimaryHover : rgba(token.colorPrimaryHover, 0.3)} 100%
42
+ );
13
43
  border: 1px solid ${token.colorBorderSecondary};
14
44
  border-radius: ${token.borderRadiusLG}px;
45
+ `,
46
+ tag: css`
47
+ position: absolute;
48
+ top: 6px;
49
+ right: 12px;
50
+
51
+ font-family: ${token.fontFamilyCode};
52
+ font-size: 12px;
53
+ color: ${isDarkMode ? token.colorPrimaryBg : token.colorPrimaryActive};
15
54
 
16
- &:hover {
17
- border-color: ${token.colorBorder};
18
- }
55
+ opacity: 0.5;
19
56
  `,
20
57
  }));
21
58
 
22
59
  enum Tabs {
23
- common,
24
- agent,
60
+ agent = 'agent',
61
+ common = 'common',
25
62
  }
26
63
 
27
64
  const Settings = memo(() => {
28
65
  const [tab, setTab] = useState<Tabs>(Tabs.common);
29
- const { styles } = useStyles();
66
+ const { styles, theme } = useStyles();
30
67
  const { t } = useTranslation('setting');
31
68
 
32
69
  return (
33
70
  <Center gap={16} width={'100%'}>
34
- <div className={styles.tabs}>
35
- <Segmented
36
- onChange={(e) => setTab(e as Tabs)}
37
- options={[
38
- { label: t('tab.common'), value: Tabs.common },
39
- { label: t('tab.agent'), value: Tabs.agent },
71
+ <Flexbox align={'flex-end'} className={styles.tabs} horizontal justify={'center'}>
72
+ <GridBackground
73
+ animation
74
+ className={styles.background}
75
+ colorBack={theme.colorFillSecondary}
76
+ colorFront={theme.colorPrimary}
77
+ random
78
+ />
79
+ <TabsNav
80
+ activeKey={tab}
81
+ items={[
82
+ { key: Tabs.common, label: t('tab.common') },
83
+ { key: Tabs.agent, label: t('tab.agent') },
40
84
  ]}
41
- value={tab}
85
+ onChange={(e) => setTab(e as Tabs)}
42
86
  />
43
- </div>
87
+ <div className={styles.logo}>
88
+ <Logo extra={'Chat'} type={'text'} />
89
+ </div>
90
+ <Flexbox align={'center'} className={styles.tag} gap={4} horizontal>
91
+ <Icon icon={PackageCheck} />
92
+ <div>{`${pkg.version}`}</div>
93
+ </Flexbox>
94
+ </Flexbox>
44
95
  {tab === Tabs.common && <Common />}
45
96
  {tab === Tabs.agent && <Agent />}
46
97
  </Center>
@@ -1,25 +1,25 @@
1
1
  import Head from 'next/head';
2
- import { ReactNode, memo, useEffect } from 'react';
2
+ import { ReactNode, memo } from 'react';
3
3
  import { useTranslation } from 'react-i18next';
4
4
  import { Flexbox } from 'react-layout-kit';
5
5
 
6
6
  import SideBar from '@/features/SideBar';
7
7
  import { createI18nNext } from '@/locales/create';
8
- import { useSwitchSideBarOnInit } from '@/store/global';
8
+ import { useOnFinishHydrationGlobal, useSwitchSideBarOnInit } from '@/store/global';
9
9
  import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
10
10
 
11
- const initI18n = createI18nNext('setting');
11
+ const initI18n = createI18nNext({ namespace: 'setting' });
12
12
 
13
13
  const SettingLayout = memo<{ children: ReactNode }>(({ children }) => {
14
14
  const { t } = useTranslation('setting');
15
15
  const pageTitle = genSiteHeadTitle(t('header.global'));
16
16
 
17
- useEffect(() => {
18
- initI18n.finally();
19
- }, []);
20
-
21
17
  useSwitchSideBarOnInit('settings');
22
18
 
19
+ useOnFinishHydrationGlobal(() => {
20
+ initI18n.then(() => {});
21
+ });
22
+
23
23
  return (
24
24
  <>
25
25
  <Head>
@@ -1,2 +1,3 @@
1
1
  export * from './useHydrated';
2
+ export * from './useOnFinishHydrationGlobal';
2
3
  export * from './useSwitchSideBarOnInit';
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
2
2
 
3
3
  import { useGlobalStore } from '../store';
4
4
 
5
- export const useSettingsHydrated = () => {
5
+ export const useGlobalHydrated = () => {
6
6
  // 根据 sessions 是否有值来判断是否已经初始化
7
7
  const hasInited = !!Object.values(useGlobalStore.getState().settings).length;
8
8
 
@@ -1,18 +1,18 @@
1
1
  import { useEffect } from 'react';
2
2
 
3
- import { useGlobalStore } from '../store';
3
+ import { GlobalStore, useGlobalStore } from '../store';
4
4
 
5
5
  /**
6
6
  * 当 Session 水合完毕后才会执行的 useEffect
7
7
  * @param fn
8
8
  * @param deps
9
9
  */
10
- export const useOnFinishHydrationGlobal = (fn: () => void, deps: any[] = []) => {
10
+ export const useOnFinishHydrationGlobal = (fn: (state: GlobalStore) => void, deps: any[] = []) => {
11
11
  useEffect(() => {
12
12
  const hasRehydrated = useGlobalStore.persist.hasHydrated();
13
13
  // 只有当水合完毕后再开始做操作
14
14
  if (!hasRehydrated) return;
15
15
 
16
- fn();
16
+ fn(useGlobalStore.getState());
17
17
  }, deps);
18
18
  };
@@ -1,5 +0,0 @@
1
- import { createI18nNext } from './create';
2
-
3
- const initI18n = createI18nNext();
4
-
5
- export default initI18n;