@lobehub/chat 0.152.12 → 0.153.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 +50 -0
- package/README.md +8 -8
- package/README.zh-CN.md +8 -8
- package/locales/ar/common.json +2 -0
- package/locales/bg-BG/common.json +2 -0
- package/locales/de-DE/common.json +2 -0
- package/locales/en-US/common.json +2 -0
- package/locales/es-ES/common.json +2 -0
- package/locales/fr-FR/common.json +2 -0
- package/locales/it-IT/common.json +2 -0
- package/locales/ja-JP/common.json +2 -0
- package/locales/ko-KR/common.json +2 -0
- package/locales/nl-NL/common.json +2 -0
- package/locales/pl-PL/common.json +2 -0
- package/locales/pt-BR/common.json +2 -0
- package/locales/ru-RU/common.json +2 -0
- package/locales/tr-TR/common.json +2 -0
- package/locales/vi-VN/common.json +2 -0
- package/locales/zh-CN/common.json +2 -0
- package/locales/zh-TW/common.json +2 -0
- package/package.json +1 -1
- package/src/app/(main)/(mobile)/me/features/AvatarBanner.tsx +12 -40
- package/src/app/(main)/(mobile)/me/features/Header.tsx +37 -0
- package/src/app/(main)/(mobile)/me/features/style.ts +29 -0
- package/src/app/(main)/(mobile)/me/layout.tsx +7 -1
- package/src/app/(main)/(mobile)/me/loading.tsx +22 -7
- package/src/app/(main)/(mobile)/me/page.tsx +4 -5
- package/src/app/(main)/@nav/_layout/Mobile.tsx +2 -2
- package/src/app/(main)/chat/(desktop)/features/ChatHeader/Main.tsx +4 -9
- package/src/app/(main)/chat/(desktop)/features/SideBar/SystemRole/index.tsx +5 -6
- package/src/app/(main)/chat/features/SettingButton.tsx +3 -17
- package/src/app/(main)/chat/features/TopicListContent/Header.tsx +1 -1
- package/src/app/(main)/chat/settings/_layout/Desktop/Header.tsx +2 -1
- package/src/app/(main)/chat/settings/_layout/Mobile/Header.tsx +2 -1
- package/src/app/(main)/chat/settings/modal/page.tsx +23 -0
- package/src/app/(main)/market/@detail/features/{AgentDetailContent/index.tsx → AgentDetailContent.tsx} +6 -12
- package/src/app/(main)/market/@detail/features/Banner.tsx +46 -0
- package/src/app/(main)/market/@detail/features/{AgentDetailContent/Header.tsx → Header.tsx} +4 -18
- package/src/app/(main)/market/@detail/features/{AgentDetailContent/Loading.tsx → Loading.tsx} +5 -4
- package/src/app/(main)/market/@detail/features/{AgentDetailContent/style.ts → style.ts} +0 -3
- package/src/app/(main)/market/features/AgentCard/AgentCardBanner.tsx +13 -8
- package/src/app/(main)/market/loading.tsx +13 -1
- package/src/app/(main)/settings/@category/features/CategoryContent.tsx +5 -1
- package/src/app/(main)/settings/modal/page.tsx +27 -0
- package/src/app/@modal/(.)settings/modal/index.tsx +40 -0
- package/src/app/@modal/(.)settings/modal/layout.tsx +32 -0
- package/src/app/@modal/(.)settings/modal/loading.tsx +5 -0
- package/src/app/@modal/(.)settings/modal/page.tsx +19 -0
- package/src/app/@modal/_layout/SettingModalLayout.tsx +59 -0
- package/src/app/@modal/chat/(.)settings/modal/features/CategoryContent.tsx +37 -0
- package/src/app/@modal/chat/(.)settings/modal/features/useCategory.tsx +54 -0
- package/src/app/@modal/chat/(.)settings/modal/layout.tsx +55 -0
- package/src/app/@modal/chat/(.)settings/modal/loading.tsx +5 -0
- package/src/app/@modal/chat/(.)settings/modal/page.tsx +55 -0
- package/src/app/@modal/default.tsx +3 -0
- package/src/app/@modal/error.tsx +5 -0
- package/src/app/@modal/layout.tsx +30 -0
- package/src/app/@modal/loading.tsx +5 -0
- package/src/app/layout.tsx +6 -2
- package/src/components/Cell/Divider.tsx +2 -0
- package/src/components/Cell/index.tsx +5 -1
- package/src/components/server/MobileNavLayout.tsx +1 -0
- package/src/features/Conversation/Messages/index.ts +9 -12
- package/src/features/Conversation/components/InboxWelcome/AgentsSuggest.tsx +15 -6
- package/src/features/Conversation/components/InboxWelcome/QuestionSuggest.tsx +9 -4
- package/src/features/Conversation/components/InboxWelcome/index.tsx +5 -3
- package/src/features/DataImporter/index.tsx +4 -1
- package/src/features/MobileTabBar/index.tsx +3 -3
- package/src/features/User/PlanTag.tsx +45 -0
- package/src/features/User/UserInfo.tsx +26 -9
- package/src/features/User/UserPanel/useMenu.tsx +31 -16
- package/src/hooks/useInterceptingRoutes.test.ts +70 -0
- package/src/hooks/useInterceptingRoutes.ts +46 -0
- package/src/hooks/useQuery.test.ts +0 -1
- package/src/hooks/useQuery.ts +2 -1
- package/src/layout/GlobalProvider/StoreInitialization.tsx +12 -5
- package/src/locales/default/common.ts +4 -2
- package/src/store/global/initialState.ts +9 -0
- package/src/styles/mobileHeader.ts +7 -0
- package/src/features/User/UserPanel/UserInfo.tsx +0 -35
- /package/src/app/(main)/market/@detail/features/{AgentDetailContent/Comment.tsx → Comment.tsx} +0 -0
- /package/src/app/(main)/market/@detail/features/{AgentDetailContent/TokenTag.tsx → TokenTag.tsx} +0 -0
- /package/src/{app/(main)/chat/components → components}/SidebarHeader/index.tsx +0 -0
|
@@ -1,21 +1,18 @@
|
|
|
1
1
|
import { Avatar, ChatHeaderTitle } from '@lobehub/ui';
|
|
2
2
|
import { Skeleton } from 'antd';
|
|
3
|
-
import { useRouter } from 'next/navigation';
|
|
4
3
|
import { memo } from 'react';
|
|
5
4
|
import { useTranslation } from 'react-i18next';
|
|
6
5
|
import { Flexbox } from 'react-layout-kit';
|
|
7
6
|
|
|
7
|
+
import { useOpenChatSettings } from '@/hooks/useInterceptingRoutes';
|
|
8
8
|
import { useSessionStore } from '@/store/session';
|
|
9
9
|
import { sessionMetaSelectors, sessionSelectors } from '@/store/session/selectors';
|
|
10
|
-
import { pathString } from '@/utils/url';
|
|
11
10
|
|
|
12
11
|
import Tags from './Tags';
|
|
13
12
|
|
|
14
13
|
const Main = memo(() => {
|
|
15
14
|
const { t } = useTranslation('chat');
|
|
16
15
|
|
|
17
|
-
const router = useRouter();
|
|
18
|
-
|
|
19
16
|
const [init, isInbox, title, description, avatar, backgroundColor] = useSessionStore((s) => [
|
|
20
17
|
sessionSelectors.isSomeSessionActive(s),
|
|
21
18
|
sessionSelectors.isInboxSession(s),
|
|
@@ -25,6 +22,8 @@ const Main = memo(() => {
|
|
|
25
22
|
sessionMetaSelectors.currentAgentBackgroundColor(s),
|
|
26
23
|
]);
|
|
27
24
|
|
|
25
|
+
const openChatSettings = useOpenChatSettings();
|
|
26
|
+
|
|
28
27
|
const displayTitle = isInbox ? t('inbox.title') : title;
|
|
29
28
|
const displayDesc = isInbox ? t('inbox.desc') : description;
|
|
30
29
|
|
|
@@ -42,11 +41,7 @@ const Main = memo(() => {
|
|
|
42
41
|
<Avatar
|
|
43
42
|
avatar={avatar}
|
|
44
43
|
background={backgroundColor}
|
|
45
|
-
onClick={
|
|
46
|
-
isInbox
|
|
47
|
-
? router.push('/settings/agent')
|
|
48
|
-
: router.push(pathString('/chat/settings', { search: location.search }))
|
|
49
|
-
}
|
|
44
|
+
onClick={openChatSettings}
|
|
50
45
|
size={40}
|
|
51
46
|
title={title}
|
|
52
47
|
/>
|
|
@@ -1,28 +1,27 @@
|
|
|
1
1
|
import { ActionIcon, EditableMessage } from '@lobehub/ui';
|
|
2
2
|
import { Skeleton } from 'antd';
|
|
3
3
|
import { Edit } from 'lucide-react';
|
|
4
|
-
import { useRouter } from 'next/navigation';
|
|
5
4
|
import { memo, useState } from 'react';
|
|
6
5
|
import { useTranslation } from 'react-i18next';
|
|
7
6
|
import { Flexbox } from 'react-layout-kit';
|
|
8
7
|
import useMergeState from 'use-merge-value';
|
|
9
8
|
|
|
9
|
+
import SidebarHeader from '@/components/SidebarHeader';
|
|
10
10
|
import AgentInfo from '@/features/AgentInfo';
|
|
11
|
+
import { useOpenChatSettings } from '@/hooks/useInterceptingRoutes';
|
|
11
12
|
import { useAgentStore } from '@/store/agent';
|
|
12
13
|
import { agentSelectors } from '@/store/agent/selectors';
|
|
13
14
|
import { useGlobalStore } from '@/store/global';
|
|
15
|
+
import { ChatSettingsTabs } from '@/store/global/initialState';
|
|
14
16
|
import { useSessionStore } from '@/store/session';
|
|
15
17
|
import { sessionMetaSelectors, sessionSelectors } from '@/store/session/selectors';
|
|
16
|
-
import { pathString } from '@/utils/url';
|
|
17
18
|
|
|
18
|
-
import SidebarHeader from '../../../../components/SidebarHeader';
|
|
19
19
|
import { useStyles } from './style';
|
|
20
20
|
|
|
21
21
|
const SystemRole = memo(() => {
|
|
22
|
-
const router = useRouter();
|
|
23
22
|
const [editing, setEditing] = useState(false);
|
|
24
23
|
const { styles } = useStyles();
|
|
25
|
-
|
|
24
|
+
const openChatSettings = useOpenChatSettings(ChatSettingsTabs.Prompt);
|
|
26
25
|
const [init, meta] = useSessionStore((s) => [
|
|
27
26
|
sessionSelectors.isSomeSessionActive(s),
|
|
28
27
|
sessionMetaSelectors.currentAgentMeta(s),
|
|
@@ -93,7 +92,7 @@ const SystemRole = memo(() => {
|
|
|
93
92
|
onAvatarClick={() => {
|
|
94
93
|
setOpen(false);
|
|
95
94
|
setEditing(false);
|
|
96
|
-
|
|
95
|
+
openChatSettings();
|
|
97
96
|
}}
|
|
98
97
|
style={{ marginBottom: 16 }}
|
|
99
98
|
/>
|
|
@@ -4,30 +4,16 @@ import { memo } from 'react';
|
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
5
|
|
|
6
6
|
import { DESKTOP_HEADER_ICON_SIZE, MOBILE_HEADER_ICON_SIZE } from '@/const/layoutTokens';
|
|
7
|
-
import {
|
|
8
|
-
import { useGlobalStore } from '@/store/global';
|
|
9
|
-
import { SidebarTabKey } from '@/store/global/initialState';
|
|
10
|
-
import { useSessionStore } from '@/store/session';
|
|
11
|
-
import { sessionSelectors } from '@/store/session/selectors';
|
|
7
|
+
import { useOpenChatSettings } from '@/hooks/useInterceptingRoutes';
|
|
12
8
|
|
|
13
9
|
const SettingButton = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
14
|
-
const isInbox = useSessionStore(sessionSelectors.isInboxSession);
|
|
15
10
|
const { t } = useTranslation('common');
|
|
16
|
-
const
|
|
11
|
+
const openChatSettings = useOpenChatSettings();
|
|
17
12
|
|
|
18
13
|
return (
|
|
19
14
|
<ActionIcon
|
|
20
15
|
icon={AlignJustify}
|
|
21
|
-
onClick={
|
|
22
|
-
if (isInbox) {
|
|
23
|
-
useGlobalStore.setState({
|
|
24
|
-
sidebarKey: SidebarTabKey.Setting,
|
|
25
|
-
});
|
|
26
|
-
router.push('/settings/agent');
|
|
27
|
-
} else {
|
|
28
|
-
router.push('/chat/settings');
|
|
29
|
-
}
|
|
30
|
-
}}
|
|
16
|
+
onClick={openChatSettings}
|
|
31
17
|
size={mobile ? MOBILE_HEADER_ICON_SIZE : DESKTOP_HEADER_ICON_SIZE}
|
|
32
18
|
title={t('header.session', { ns: 'setting' })}
|
|
33
19
|
/>
|
|
@@ -5,10 +5,10 @@ import { memo, useMemo, useState } from 'react';
|
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
6
|
import { Flexbox } from 'react-layout-kit';
|
|
7
7
|
|
|
8
|
+
import SidebarHeader from '@/components/SidebarHeader';
|
|
8
9
|
import { useChatStore } from '@/store/chat';
|
|
9
10
|
import { topicSelectors } from '@/store/chat/selectors';
|
|
10
11
|
|
|
11
|
-
import SidebarHeader from '../../components/SidebarHeader';
|
|
12
12
|
import TopicSearchBar from './TopicSearchBar';
|
|
13
13
|
|
|
14
14
|
const Header = memo(() => {
|
|
@@ -5,9 +5,10 @@ import { useRouter } from 'next/navigation';
|
|
|
5
5
|
import { memo } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
|
|
8
|
-
import HeaderContent from '@/app/(main)/chat/settings/features/HeaderContent';
|
|
9
8
|
import { pathString } from '@/utils/url';
|
|
10
9
|
|
|
10
|
+
import HeaderContent from '../../features/HeaderContent';
|
|
11
|
+
|
|
11
12
|
const Header = memo(() => {
|
|
12
13
|
const { t } = useTranslation('setting');
|
|
13
14
|
const router = useRouter();
|
|
@@ -5,10 +5,11 @@ import { useRouter } from 'next/navigation';
|
|
|
5
5
|
import { memo } from 'react';
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
|
|
8
|
-
import HeaderContent from '@/app/(main)/chat/settings/features/HeaderContent';
|
|
9
8
|
import { mobileHeaderSticky } from '@/styles/mobileHeader';
|
|
10
9
|
import { pathString } from '@/utils/url';
|
|
11
10
|
|
|
11
|
+
import HeaderContent from '../../features/HeaderContent';
|
|
12
|
+
|
|
12
13
|
const Header = memo(() => {
|
|
13
14
|
const { t } = useTranslation('setting');
|
|
14
15
|
const router = useRouter();
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useLayoutEffect } from 'react';
|
|
4
|
+
|
|
5
|
+
import { useQueryRoute } from '@/hooks/useQueryRoute';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @description: Chat Settings Modal (intercepting routes fallback when hard refresh)
|
|
9
|
+
* @example: /chat/settings/modal?tab=prompt => /chat/settings
|
|
10
|
+
* @refs: https://github.com/lobehub/lobe-chat/discussions/2295#discussioncomment-9290942
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const ChatSettingsModalFallback = () => {
|
|
14
|
+
const router = useQueryRoute();
|
|
15
|
+
|
|
16
|
+
useLayoutEffect(() => {
|
|
17
|
+
router.replace('/chat/settings', { query: { tab: '' } });
|
|
18
|
+
}, []);
|
|
19
|
+
|
|
20
|
+
return null;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export default ChatSettingsModalFallback;
|
|
@@ -5,21 +5,20 @@ import { memo, useState } from 'react';
|
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
6
|
import { Flexbox } from 'react-layout-kit';
|
|
7
7
|
|
|
8
|
-
import
|
|
8
|
+
import Banner from '@/app/(main)/market/@detail/features/Banner';
|
|
9
9
|
import { useMarketStore } from '@/store/market';
|
|
10
10
|
|
|
11
11
|
import Comment from './Comment';
|
|
12
12
|
import Header from './Header';
|
|
13
13
|
import Loading from './Loading';
|
|
14
14
|
import TokenTag from './TokenTag';
|
|
15
|
-
import { useStyles } from './style';
|
|
16
15
|
|
|
17
16
|
enum InfoTabs {
|
|
18
17
|
comment = 'comment',
|
|
19
18
|
prompt = 'prompt',
|
|
20
19
|
}
|
|
21
20
|
|
|
22
|
-
const
|
|
21
|
+
const AgentDetailContent = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
23
22
|
const [useFetchAgent, currentIdentifier] = useMarketStore((s) => [
|
|
24
23
|
s.useFetchAgent,
|
|
25
24
|
s.currentIdentifier,
|
|
@@ -27,7 +26,6 @@ const AgentModalInner = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
|
27
26
|
const { t } = useTranslation('market');
|
|
28
27
|
const [tab, setTab] = useState<string>(InfoTabs.prompt);
|
|
29
28
|
const { data, isLoading } = useFetchAgent(currentIdentifier);
|
|
30
|
-
const { styles } = useStyles();
|
|
31
29
|
|
|
32
30
|
if (isLoading || !data?.meta) return <Loading />;
|
|
33
31
|
|
|
@@ -36,16 +34,11 @@ const AgentModalInner = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
|
36
34
|
|
|
37
35
|
return (
|
|
38
36
|
<>
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
size={800}
|
|
42
|
-
style={{ height: 120, marginBottom: -60 }}
|
|
43
|
-
/>
|
|
44
|
-
<Header mobile={mobile} />
|
|
37
|
+
<Banner avatar={meta.avatar} backgroundColor={meta.backgroundColor} mobile={mobile} />
|
|
38
|
+
<Header />
|
|
45
39
|
<Flexbox align={'center'}>
|
|
46
40
|
<TabsNav
|
|
47
41
|
activeKey={tab}
|
|
48
|
-
className={styles.nav}
|
|
49
42
|
items={[
|
|
50
43
|
{
|
|
51
44
|
key: InfoTabs.prompt,
|
|
@@ -61,6 +54,7 @@ const AgentModalInner = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
|
61
54
|
},
|
|
62
55
|
]}
|
|
63
56
|
onChange={setTab}
|
|
57
|
+
style={{ paddingTop: 8 }}
|
|
64
58
|
variant={'compact'}
|
|
65
59
|
/>
|
|
66
60
|
</Flexbox>
|
|
@@ -76,4 +70,4 @@ const AgentModalInner = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
|
76
70
|
);
|
|
77
71
|
});
|
|
78
72
|
|
|
79
|
-
export default
|
|
73
|
+
export default AgentDetailContent;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Avatar } from '@lobehub/ui';
|
|
2
|
+
import { Skeleton } from 'antd';
|
|
3
|
+
import { useTheme } from 'antd-style';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
import { Center, Flexbox } from 'react-layout-kit';
|
|
6
|
+
|
|
7
|
+
import AgentCardBanner from '../../features/AgentCard/AgentCardBanner';
|
|
8
|
+
|
|
9
|
+
const Banner = memo<{
|
|
10
|
+
avatar?: string;
|
|
11
|
+
backgroundColor?: string;
|
|
12
|
+
loading?: boolean;
|
|
13
|
+
mobile?: boolean;
|
|
14
|
+
}>(({ avatar, backgroundColor, mobile, loading }) => {
|
|
15
|
+
const theme = useTheme();
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<Flexbox align={'center'}>
|
|
19
|
+
<AgentCardBanner
|
|
20
|
+
avatar={loading ? undefined : avatar}
|
|
21
|
+
size={800}
|
|
22
|
+
style={{ height: 120, marginBottom: -60 }}
|
|
23
|
+
/>
|
|
24
|
+
<Center
|
|
25
|
+
flex={'none'}
|
|
26
|
+
height={120}
|
|
27
|
+
style={{
|
|
28
|
+
backgroundColor:
|
|
29
|
+
backgroundColor || mobile ? theme.colorBgElevated : theme.colorBgContainer,
|
|
30
|
+
borderRadius: '50%',
|
|
31
|
+
overflow: 'hidden',
|
|
32
|
+
zIndex: 2,
|
|
33
|
+
}}
|
|
34
|
+
width={120}
|
|
35
|
+
>
|
|
36
|
+
{loading ? (
|
|
37
|
+
<Skeleton.Avatar active size={100} />
|
|
38
|
+
) : (
|
|
39
|
+
<Avatar animation avatar={avatar} shape={'circle'} size={100} />
|
|
40
|
+
)}
|
|
41
|
+
</Center>
|
|
42
|
+
</Flexbox>
|
|
43
|
+
);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
export default Banner;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Tag } from '@lobehub/ui';
|
|
2
2
|
import { App, Button, Typography } from 'antd';
|
|
3
3
|
import isEqual from 'fast-deep-equal';
|
|
4
4
|
import { startCase } from 'lodash-es';
|
|
@@ -16,18 +16,18 @@ import { useStyles } from './style';
|
|
|
16
16
|
|
|
17
17
|
const { Link } = Typography;
|
|
18
18
|
|
|
19
|
-
const Header = memo
|
|
19
|
+
const Header = memo(() => {
|
|
20
20
|
const setSearchKeywords = useMarketStore((s) => s.setSearchKeywords);
|
|
21
21
|
const router = useRouter();
|
|
22
22
|
const { t } = useTranslation('market');
|
|
23
|
-
const { styles
|
|
23
|
+
const { styles } = useStyles();
|
|
24
24
|
const createSession = useSessionStore((s) => s.createSession);
|
|
25
25
|
const agentItem = useMarketStore(agentMarketSelectors.currentAgentItem, isEqual);
|
|
26
26
|
|
|
27
27
|
const { message } = App.useApp();
|
|
28
28
|
|
|
29
29
|
const { meta, createAt, author, homepage, config } = agentItem;
|
|
30
|
-
const {
|
|
30
|
+
const { title, description, tags } = meta;
|
|
31
31
|
|
|
32
32
|
const isMobile = useIsMobile();
|
|
33
33
|
|
|
@@ -47,20 +47,6 @@ const Header = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
|
47
47
|
|
|
48
48
|
return (
|
|
49
49
|
<Center className={styles.container} gap={16}>
|
|
50
|
-
<Center
|
|
51
|
-
flex={'none'}
|
|
52
|
-
height={120}
|
|
53
|
-
style={{
|
|
54
|
-
backgroundColor:
|
|
55
|
-
backgroundColor || mobile ? theme.colorBgElevated : theme.colorBgContainer,
|
|
56
|
-
borderRadius: '50%',
|
|
57
|
-
overflow: 'hidden',
|
|
58
|
-
zIndex: 2,
|
|
59
|
-
}}
|
|
60
|
-
width={120}
|
|
61
|
-
>
|
|
62
|
-
<Avatar animation avatar={avatar} size={100} />
|
|
63
|
-
</Center>
|
|
64
50
|
<h2 className={styles.title}>{title}</h2>
|
|
65
51
|
<Center gap={6} horizontal style={{ flexWrap: 'wrap' }}>
|
|
66
52
|
{(tags as string[]).map((tag: string, index) => (
|
package/src/app/(main)/market/@detail/features/{AgentDetailContent/Loading.tsx → Loading.tsx}
RENAMED
|
@@ -2,25 +2,26 @@ import { Skeleton } from 'antd';
|
|
|
2
2
|
import { memo } from 'react';
|
|
3
3
|
import { Center, Flexbox } from 'react-layout-kit';
|
|
4
4
|
|
|
5
|
+
import Banner from './Banner';
|
|
5
6
|
import { useStyles } from './style';
|
|
6
7
|
|
|
7
8
|
const Loading = memo(() => {
|
|
8
9
|
const { styles } = useStyles();
|
|
9
10
|
return (
|
|
10
11
|
<>
|
|
11
|
-
<
|
|
12
|
-
|
|
12
|
+
<Banner loading />
|
|
13
|
+
<Center className={styles.container} gap={16}>
|
|
13
14
|
<Skeleton
|
|
14
15
|
active
|
|
15
16
|
className={styles.loading}
|
|
16
17
|
paragraph={{
|
|
17
|
-
rows:
|
|
18
|
+
rows: 2,
|
|
18
19
|
style: {
|
|
19
20
|
alignItems: 'center',
|
|
20
21
|
display: 'flex',
|
|
21
22
|
flexDirection: 'column',
|
|
22
23
|
},
|
|
23
|
-
width: ['60%', '80%'
|
|
24
|
+
width: ['60%', '80%'],
|
|
24
25
|
}}
|
|
25
26
|
title={{
|
|
26
27
|
style: {
|
|
@@ -22,6 +22,7 @@ export const useStyles = createStyles(({ css, token }) => ({
|
|
|
22
22
|
|
|
23
23
|
interface AgentCardBannerProps extends DivProps {
|
|
24
24
|
avatar?: string;
|
|
25
|
+
loading?: boolean;
|
|
25
26
|
mask?: boolean;
|
|
26
27
|
maskColor?: string;
|
|
27
28
|
size?: number;
|
|
@@ -29,22 +30,26 @@ interface AgentCardBannerProps extends DivProps {
|
|
|
29
30
|
|
|
30
31
|
const AgentCardBanner = memo<AgentCardBannerProps>(
|
|
31
32
|
({ avatar, className, size = 600, children, ...props }) => {
|
|
32
|
-
const { styles, cx } = useStyles();
|
|
33
|
+
const { styles, theme, cx } = useStyles();
|
|
33
34
|
|
|
34
35
|
return (
|
|
35
36
|
<Flexbox
|
|
36
37
|
align={'center'}
|
|
37
38
|
className={cx(styles.banner, className)}
|
|
38
39
|
justify={'center'}
|
|
40
|
+
style={avatar ? {} : { backgroundColor: theme.colorFillTertiary }}
|
|
41
|
+
width={'100%'}
|
|
39
42
|
{...props}
|
|
40
43
|
>
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
{avatar && (
|
|
45
|
+
<Avatar
|
|
46
|
+
alt={'banner'}
|
|
47
|
+
avatar={avatar}
|
|
48
|
+
className={styles.bannerImg}
|
|
49
|
+
shape={'square'}
|
|
50
|
+
size={size}
|
|
51
|
+
/>
|
|
52
|
+
)}
|
|
48
53
|
{children}
|
|
49
54
|
</Flexbox>
|
|
50
55
|
);
|
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
1
3
|
import { Skeleton } from 'antd';
|
|
4
|
+
import { Flexbox } from 'react-layout-kit';
|
|
2
5
|
|
|
3
|
-
export default () =>
|
|
6
|
+
export default () => (
|
|
7
|
+
<Flexbox gap={16}>
|
|
8
|
+
<Skeleton.Input active block />
|
|
9
|
+
<Skeleton paragraph={{ rows: 8 }} style={{ marginBlock: 24 }} title={false} />
|
|
10
|
+
<Skeleton.Button active />
|
|
11
|
+
<Skeleton paragraph={{ rows: 8 }} style={{ marginBlock: 24 }} title={false} />
|
|
12
|
+
<Skeleton.Button active />
|
|
13
|
+
<Skeleton paragraph={{ rows: 8 }} style={{ marginBlock: 24 }} title={false} />
|
|
14
|
+
</Flexbox>
|
|
15
|
+
);
|
|
@@ -21,7 +21,11 @@ const CategoryContent = memo<{ modal?: boolean }>(({ modal }) => {
|
|
|
21
21
|
<Menu
|
|
22
22
|
items={cateItems}
|
|
23
23
|
onClick={({ key }) => {
|
|
24
|
-
|
|
24
|
+
if (modal) {
|
|
25
|
+
router.replace('/settings/modal', { query: { tab: key } });
|
|
26
|
+
} else {
|
|
27
|
+
router.push(urlJoin('/settings', key));
|
|
28
|
+
}
|
|
25
29
|
}}
|
|
26
30
|
selectable
|
|
27
31
|
selectedKeys={[modal ? tab : (activeTab as any)]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useLayoutEffect } from 'react';
|
|
4
|
+
import urlJoin from 'url-join';
|
|
5
|
+
|
|
6
|
+
import { useQuery } from '@/hooks/useQuery';
|
|
7
|
+
import { useQueryRoute } from '@/hooks/useQueryRoute';
|
|
8
|
+
import { SettingsTabs } from '@/store/global/initialState';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @description: Settings Modal (intercepting routes fallback when hard refresh)
|
|
12
|
+
* @example: /settings/modal?tab=common => /settings/common
|
|
13
|
+
* @refs: https://github.com/lobehub/lobe-chat/discussions/2295#discussioncomment-9290942
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const SettingsModalFallback = () => {
|
|
17
|
+
const { tab = SettingsTabs.Common } = useQuery();
|
|
18
|
+
const router = useQueryRoute();
|
|
19
|
+
|
|
20
|
+
useLayoutEffect(() => {
|
|
21
|
+
router.replace(urlJoin('/settings', tab as SettingsTabs), { query: { tab: '' } });
|
|
22
|
+
}, []);
|
|
23
|
+
|
|
24
|
+
return null;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default SettingsModalFallback;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import dynamic from 'next/dynamic';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
|
|
6
|
+
import { useQuery } from '@/hooks/useQuery';
|
|
7
|
+
import { SettingsTabs } from '@/store/global/initialState';
|
|
8
|
+
|
|
9
|
+
import Skeleton from './loading';
|
|
10
|
+
|
|
11
|
+
const loading = () => <Skeleton />;
|
|
12
|
+
|
|
13
|
+
const Common = dynamic(() => import('@/app/(main)/settings/common'), { loading, ssr: false });
|
|
14
|
+
const About = dynamic(() => import('@/app/(main)/settings/about'), { loading, ssr: false });
|
|
15
|
+
const LLM = dynamic(() => import('@/app/(main)/settings/llm'), { loading, ssr: false });
|
|
16
|
+
const TTS = dynamic(() => import('@/app/(main)/settings/tts'), { loading, ssr: false });
|
|
17
|
+
const Agent = dynamic(() => import('@/app/(main)/settings/agent'), { loading, ssr: false });
|
|
18
|
+
const Sync = dynamic(() => import('@/app/(main)/settings/sync'), { loading, ssr: false });
|
|
19
|
+
|
|
20
|
+
interface SettingsModalProps {
|
|
21
|
+
browser?: string;
|
|
22
|
+
mobile?: boolean;
|
|
23
|
+
os?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const SettingsModal = memo<SettingsModalProps>(({ browser, os, mobile }) => {
|
|
27
|
+
const { tab = SettingsTabs.Common } = useQuery();
|
|
28
|
+
return (
|
|
29
|
+
<>
|
|
30
|
+
{tab === SettingsTabs.Common && <Common />}
|
|
31
|
+
{tab === SettingsTabs.Sync && <Sync browser={browser} mobile={mobile} os={os} />}
|
|
32
|
+
{tab === SettingsTabs.LLM && <LLM />}
|
|
33
|
+
{tab === SettingsTabs.TTS && <TTS />}
|
|
34
|
+
{tab === SettingsTabs.Agent && <Agent />}
|
|
35
|
+
{tab === SettingsTabs.About && <About mobile={mobile} />}
|
|
36
|
+
</>
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
export default SettingsModal;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Skeleton } from 'antd';
|
|
4
|
+
import dynamic from 'next/dynamic';
|
|
5
|
+
import { PropsWithChildren, memo } from 'react';
|
|
6
|
+
|
|
7
|
+
import SettingModalLayout from '../../_layout/SettingModalLayout';
|
|
8
|
+
|
|
9
|
+
const CategoryContent = dynamic(
|
|
10
|
+
() => import('@/app/(main)/settings/@category/features/CategoryContent'),
|
|
11
|
+
{ loading: () => <Skeleton paragraph={{ rows: 6 }} title={false} />, ssr: false },
|
|
12
|
+
);
|
|
13
|
+
const UpgradeAlert = dynamic(() => import('@/app/(main)/settings/features/UpgradeAlert'), {
|
|
14
|
+
ssr: false,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const Layout = memo<PropsWithChildren>(({ children }) => {
|
|
18
|
+
return (
|
|
19
|
+
<SettingModalLayout
|
|
20
|
+
category={
|
|
21
|
+
<>
|
|
22
|
+
<CategoryContent modal />
|
|
23
|
+
<UpgradeAlert />
|
|
24
|
+
</>
|
|
25
|
+
}
|
|
26
|
+
>
|
|
27
|
+
{children}
|
|
28
|
+
</SettingModalLayout>
|
|
29
|
+
);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
export default Layout;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { gerServerDeviceInfo, isMobileDevice } from '@/utils/responsive';
|
|
2
|
+
|
|
3
|
+
import SettingsModal from './index';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @description: Settings Modal (intercepting route: /settings/modal )
|
|
7
|
+
* @refs: https://github.com/lobehub/lobe-chat/discussions/2295#discussioncomment-9290942
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const Page = () => {
|
|
11
|
+
const isMobile = isMobileDevice();
|
|
12
|
+
const { os, browser } = gerServerDeviceInfo();
|
|
13
|
+
|
|
14
|
+
return <SettingsModal browser={browser} mobile={isMobile} os={os} />;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
Page.displayName = 'SettingModal';
|
|
18
|
+
|
|
19
|
+
export default Page;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { useResponsive, useTheme, useThemeMode } from 'antd-style';
|
|
4
|
+
import { ReactNode, memo, useRef } from 'react';
|
|
5
|
+
import { Flexbox } from 'react-layout-kit';
|
|
6
|
+
|
|
7
|
+
import Header from '@/app/(main)/settings/_layout/Desktop/Header';
|
|
8
|
+
import SideBar from '@/app/(main)/settings/_layout/Desktop/SideBar';
|
|
9
|
+
|
|
10
|
+
interface SettingLayoutProps {
|
|
11
|
+
category: ReactNode;
|
|
12
|
+
children: ReactNode;
|
|
13
|
+
desc?: string;
|
|
14
|
+
title?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const SettingModalLayout = memo<SettingLayoutProps>(({ children, category, desc, title }) => {
|
|
18
|
+
const ref = useRef<any>(null);
|
|
19
|
+
const theme = useTheme();
|
|
20
|
+
const { isDarkMode } = useThemeMode();
|
|
21
|
+
const { md = true } = useResponsive();
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<>
|
|
25
|
+
{md ? (
|
|
26
|
+
<SideBar
|
|
27
|
+
desc={desc}
|
|
28
|
+
style={{
|
|
29
|
+
background: isDarkMode ? theme.colorBgContainer : theme.colorFillTertiary,
|
|
30
|
+
borderColor: theme.colorFillTertiary,
|
|
31
|
+
}}
|
|
32
|
+
title={title}
|
|
33
|
+
>
|
|
34
|
+
{category}
|
|
35
|
+
</SideBar>
|
|
36
|
+
) : (
|
|
37
|
+
<Header getContainer={() => ref.current}>{category}</Header>
|
|
38
|
+
)}
|
|
39
|
+
<Flexbox
|
|
40
|
+
align={'center'}
|
|
41
|
+
gap={64}
|
|
42
|
+
style={{
|
|
43
|
+
background: isDarkMode ? theme.colorFillQuaternary : theme.colorBgElevated,
|
|
44
|
+
overflowX: 'hidden',
|
|
45
|
+
overflowY: 'auto',
|
|
46
|
+
paddingBlock: 40,
|
|
47
|
+
paddingInline: 56,
|
|
48
|
+
}}
|
|
49
|
+
width={'100%'}
|
|
50
|
+
>
|
|
51
|
+
{children}
|
|
52
|
+
</Flexbox>
|
|
53
|
+
</>
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
SettingModalLayout.displayName = 'SettingModalLayout';
|
|
58
|
+
|
|
59
|
+
export default SettingModalLayout;
|