@lobehub/chat 0.74.0 → 0.75.0
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 +61 -0
- package/README.md +26 -5
- package/README.zh-CN.md +25 -4
- package/locales/en_US/market.json +12 -0
- package/locales/en_US/plugin.json +11 -2
- package/locales/en_US/setting.json +3 -1
- package/locales/ru_RU/market.json +12 -0
- package/locales/ru_RU/plugin.json +44 -49
- package/locales/ru_RU/setting.json +3 -1
- package/locales/zh_CN/common.json +1 -1
- package/locales/zh_CN/market.json +12 -0
- package/locales/zh_CN/plugin.json +19 -5
- package/locales/zh_CN/setting.json +62 -14
- package/package.json +5 -4
- package/scripts/i18nWorkflow/const.ts +19 -0
- package/scripts/i18nWorkflow/genDefaultLocale.ts +19 -0
- package/scripts/i18nWorkflow/genDiff.ts +50 -0
- package/scripts/i18nWorkflow/genResources.ts +26 -0
- package/scripts/i18nWorkflow/index.ts +15 -0
- package/scripts/i18nWorkflow/utils.ts +85 -0
- package/src/const/layoutTokens.ts +3 -1
- package/src/const/market.ts +15 -0
- package/src/const/url.ts +29 -4
- package/src/features/AgentSetting/AgentConfig/index.tsx +1 -2
- package/src/features/AgentSetting/AgentPlugin/MarketSettingModal.tsx +1 -1
- package/src/features/AgentSetting/store/initialState.ts +1 -1
- package/src/features/MobileTabBar/index.tsx +2 -2
- package/src/features/SideBar/TopActions.tsx +2 -2
- package/src/locales/default/market.ts +12 -0
- package/src/locales/resources/en_US.ts +2 -0
- package/src/locales/resources/ru_RU.ts +2 -0
- package/src/locales/resources/zh_CN.ts +2 -0
- package/src/pages/chat/features/Conversation/Input/{Action.tsx → ActionBar/ActionLeft.tsx} +2 -2
- package/src/pages/chat/features/Conversation/Input/ActionBar/ActionRight.tsx +36 -0
- package/src/pages/chat/features/Conversation/Input/Desktop.tsx +40 -0
- package/src/pages/chat/features/Conversation/Input/Footer/SaveTopic.tsx +27 -0
- package/src/pages/chat/features/Conversation/Input/Footer/index.tsx +35 -0
- package/src/pages/chat/features/Conversation/Input/Mobile.tsx +12 -0
- package/src/pages/chat/features/Conversation/Input/index.tsx +20 -38
- package/src/pages/chat/features/SessionList/Header/Desktop.tsx +6 -13
- package/src/pages/chat/features/SessionList/Header/Mobile.tsx +1 -1
- package/src/pages/chat/features/SessionList/List/AddButton.tsx +1 -1
- package/src/pages/chat/features/SessionList/List/Item/index.tsx +4 -3
- package/src/pages/chat/features/SessionList/List/index.tsx +1 -3
- package/src/pages/chat/features/SessionList/Mobile.tsx +2 -12
- package/src/pages/chat/features/SessionSearchBar/index.tsx +26 -0
- package/src/pages/chat/features/Sidebar/Topic/index.tsx +18 -6
- package/src/pages/chat/features/Sidebar/TopicSearchBar/index.tsx +24 -0
- package/src/pages/chat/features/Sidebar/index.tsx +2 -9
- package/src/pages/market/features/AgentCard/AgentCardBanner.tsx +64 -0
- package/src/pages/market/features/AgentCard/AgentCardItem.tsx +57 -0
- package/src/pages/market/features/AgentCard/Loading.tsx +13 -0
- package/src/pages/market/features/AgentCard/index.tsx +37 -0
- package/src/pages/market/features/AgentCard/style.ts +22 -0
- package/src/pages/market/features/AgentSearchBar/index.tsx +26 -0
- package/src/pages/market/features/Header/Desktop.tsx +15 -4
- package/src/pages/market/features/Header/Mobile.tsx +7 -24
- package/src/pages/market/features/SideBar/AgentInfo/Comment.tsx +16 -0
- package/src/pages/market/features/SideBar/AgentInfo/Header.tsx +68 -0
- package/src/pages/market/features/SideBar/AgentInfo/Loading.tsx +61 -0
- package/src/pages/market/features/SideBar/AgentInfo/TokenTag.tsx +25 -0
- package/src/pages/market/features/SideBar/AgentInfo/index.tsx +68 -0
- package/src/pages/market/features/SideBar/AgentInfo/style.ts +46 -0
- package/src/pages/market/features/SideBar/Desktop.tsx +70 -0
- package/src/pages/market/features/SideBar/Mobile.tsx +36 -0
- package/src/pages/market/features/SideBar/index.tsx +23 -0
- package/src/pages/market/features/TagList/index.tsx +29 -0
- package/src/pages/market/index.page.tsx +11 -2
- package/src/pages/market/layout.mobile.tsx +8 -7
- package/src/pages/market/layout.tsx +39 -1
- package/src/pages/settings/features/Header/Desktop.tsx +2 -4
- package/src/pages/settings/features/Header/Mobile.tsx +1 -1
- package/src/pages/settings/features/Settings/Common.tsx +1 -2
- package/src/pages/settings/features/Settings/index.tsx +17 -4
- package/src/services/agentMarket.ts +21 -0
- package/src/store/global/initialState.ts +1 -2
- package/src/store/market/action.ts +57 -0
- package/src/store/market/index.ts +3 -0
- package/src/store/market/initialState.ts +17 -0
- package/src/store/market/selectors.ts +36 -0
- package/src/store/market/store.ts +51 -0
- package/src/store/session/slices/session/action.ts +5 -3
- package/src/store/session/slices/session/initialState.ts +2 -0
- package/src/store/session/slices/session/reducers/session.test.ts +4 -4
- package/src/types/market.ts +19 -0
- package/src/types/meta.ts +1 -1
- package/src/utils/filter.ts +1 -1
- package/src/utils/findDuplicates.ts +22 -0
- package/scripts/genDefaultLocale.ts +0 -18
- package/scripts/genResources.ts +0 -51
- package/scripts/toc.ts +0 -7
- package/src/components/Empty/index.tsx +0 -63
- package/src/components/Empty/style.ts +0 -31
- package/src/components/SelectWithImg/index.tsx +0 -97
- package/src/components/SelectWithImg/styles.ts +0 -43
- package/src/pages/chat/features/Conversation/Input/ActionRight.tsx +0 -31
- package/src/pages/chat/features/Conversation/Input/Footer.tsx +0 -49
- /package/src/components/{ManifestPreviewer.tsx → ManifestPreviewer/index.tsx} +0 -0
- /package/src/pages/chat/features/Conversation/Input/{Token.tsx → ActionBar/Token.tsx} +0 -0
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import { ChatHeader,
|
|
1
|
+
import { ChatHeader, Icon, Logo } from '@lobehub/ui';
|
|
2
|
+
import { Button } from 'antd';
|
|
2
3
|
import { createStyles } from 'antd-style';
|
|
4
|
+
import { Bot } from 'lucide-react';
|
|
3
5
|
import Link from 'next/link';
|
|
4
6
|
import { memo } from 'react';
|
|
5
7
|
import { useTranslation } from 'react-i18next';
|
|
6
8
|
|
|
9
|
+
import { AGENTS_INDEX_GITHUB } from '@/const/url';
|
|
10
|
+
|
|
7
11
|
export const useStyles = createStyles(({ css, token }) => ({
|
|
8
12
|
logo: css`
|
|
9
13
|
color: ${token.colorText};
|
|
@@ -13,16 +17,23 @@ export const useStyles = createStyles(({ css, token }) => ({
|
|
|
13
17
|
|
|
14
18
|
const Header = memo(() => {
|
|
15
19
|
const { styles } = useStyles();
|
|
16
|
-
const { t } = useTranslation('
|
|
20
|
+
const { t } = useTranslation('market');
|
|
17
21
|
|
|
18
22
|
return (
|
|
19
23
|
<ChatHeader
|
|
20
24
|
left={
|
|
21
25
|
<Link href={'/'}>
|
|
22
|
-
<Logo className={styles.logo} extra={
|
|
26
|
+
<Logo className={styles.logo} extra={'Discover'} size={36} type={'text'} />
|
|
23
27
|
</Link>
|
|
24
28
|
}
|
|
25
|
-
right={
|
|
29
|
+
right={
|
|
30
|
+
<Button
|
|
31
|
+
icon={<Icon icon={Bot} />}
|
|
32
|
+
onClick={() => window.open(AGENTS_INDEX_GITHUB, '__blank')}
|
|
33
|
+
>
|
|
34
|
+
{t('submitAgent')}
|
|
35
|
+
</Button>
|
|
36
|
+
}
|
|
26
37
|
/>
|
|
27
38
|
);
|
|
28
39
|
});
|
|
@@ -1,39 +1,22 @@
|
|
|
1
1
|
import { ActionIcon, Logo, MobileNavBar } from '@lobehub/ui';
|
|
2
|
-
import {
|
|
3
|
-
import { MessageSquarePlus, Settings2 } from 'lucide-react';
|
|
2
|
+
import { Settings2 } from 'lucide-react';
|
|
4
3
|
import Router from 'next/router';
|
|
5
4
|
import { memo } from 'react';
|
|
6
5
|
|
|
7
6
|
import AvatarWithUpload from '@/features/AvatarWithUpload';
|
|
8
|
-
import { useSessionStore } from '@/store/session';
|
|
9
|
-
|
|
10
|
-
export const useStyles = createStyles(({ css, token }) => ({
|
|
11
|
-
logo: css`
|
|
12
|
-
fill: ${token.colorText};
|
|
13
|
-
`,
|
|
14
|
-
top: css`
|
|
15
|
-
position: sticky;
|
|
16
|
-
top: 0;
|
|
17
|
-
`,
|
|
18
|
-
}));
|
|
19
7
|
|
|
20
8
|
const Header = memo(() => {
|
|
21
|
-
const [createSession] = useSessionStore((s) => [s.createSession]);
|
|
22
|
-
|
|
23
9
|
return (
|
|
24
10
|
<MobileNavBar
|
|
25
11
|
center={<Logo type={'text'} />}
|
|
26
12
|
left={<AvatarWithUpload size={28} style={{ marginLeft: 8 }} />}
|
|
27
13
|
right={
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}}
|
|
35
|
-
/>
|
|
36
|
-
</>
|
|
14
|
+
<ActionIcon
|
|
15
|
+
icon={Settings2}
|
|
16
|
+
onClick={() => {
|
|
17
|
+
Router.push({ pathname: `/settings` });
|
|
18
|
+
}}
|
|
19
|
+
/>
|
|
37
20
|
}
|
|
38
21
|
/>
|
|
39
22
|
);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Giscus } from '@lobehub/ui';
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
|
|
4
|
+
const Comment = memo<{ identifier: string }>(({ identifier }) => (
|
|
5
|
+
<Giscus
|
|
6
|
+
category="General"
|
|
7
|
+
categoryId="DIC_kwDOKON5YM4CZNRJ"
|
|
8
|
+
id="lobehub"
|
|
9
|
+
mapping="specific"
|
|
10
|
+
repo="lobehub/lobe-chat-agents"
|
|
11
|
+
repoId="R_kgDOKON5YA"
|
|
12
|
+
term={identifier}
|
|
13
|
+
/>
|
|
14
|
+
));
|
|
15
|
+
|
|
16
|
+
export default Comment;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Avatar, Tag } from '@lobehub/ui';
|
|
2
|
+
import { Button, Typography } from 'antd';
|
|
3
|
+
import { startCase } from 'lodash-es';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
import { Center } from 'react-layout-kit';
|
|
7
|
+
|
|
8
|
+
import { useGlobalStore } from '@/store/global';
|
|
9
|
+
import { agentMarketSelectors, useMarketStore } from '@/store/market';
|
|
10
|
+
import { useSessionStore } from '@/store/session';
|
|
11
|
+
|
|
12
|
+
import { useStyles } from './style';
|
|
13
|
+
|
|
14
|
+
const { Link } = Typography;
|
|
15
|
+
|
|
16
|
+
const Header = memo(() => {
|
|
17
|
+
const { t } = useTranslation('market');
|
|
18
|
+
const { styles, theme } = useStyles();
|
|
19
|
+
|
|
20
|
+
const createSession = useSessionStore((s) => s.createSession);
|
|
21
|
+
const switchSideBar = useGlobalStore((s) => s.switchSideBar);
|
|
22
|
+
const agentItem = useMarketStore(agentMarketSelectors.currentAgentItem);
|
|
23
|
+
|
|
24
|
+
const { meta, createAt, author, homepage, config } = agentItem;
|
|
25
|
+
const { avatar, title, description, tags, backgroundColor } = meta;
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<Center className={styles.container} gap={16}>
|
|
29
|
+
<Avatar
|
|
30
|
+
avatar={avatar}
|
|
31
|
+
background={backgroundColor || theme.colorFillTertiary}
|
|
32
|
+
className={styles.avatar}
|
|
33
|
+
size={100}
|
|
34
|
+
/>
|
|
35
|
+
<div className={styles.title}>{title}</div>
|
|
36
|
+
<Center gap={6} horizontal style={{ flexWrap: 'wrap' }}>
|
|
37
|
+
{(tags as string[]).map((tag: string, index) => (
|
|
38
|
+
<Tag
|
|
39
|
+
key={index}
|
|
40
|
+
onClick={() => useMarketStore.setState({ searchKeywords: tag })}
|
|
41
|
+
style={{ margin: 0 }}
|
|
42
|
+
>
|
|
43
|
+
{startCase(tag).trim()}
|
|
44
|
+
</Tag>
|
|
45
|
+
))}
|
|
46
|
+
</Center>
|
|
47
|
+
<div className={styles.desc}>{description}</div>
|
|
48
|
+
<Link className={styles.author} href={homepage} target={'_blank'}>
|
|
49
|
+
@{author}
|
|
50
|
+
</Link>
|
|
51
|
+
<Button
|
|
52
|
+
block
|
|
53
|
+
onClick={() => {
|
|
54
|
+
if (!agentItem) return;
|
|
55
|
+
|
|
56
|
+
createSession({ config, meta });
|
|
57
|
+
switchSideBar('chat');
|
|
58
|
+
}}
|
|
59
|
+
type={'primary'}
|
|
60
|
+
>
|
|
61
|
+
{t('addAgent')}
|
|
62
|
+
</Button>
|
|
63
|
+
<div className={styles.date}>{createAt}</div>
|
|
64
|
+
</Center>
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
export default Header;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { Skeleton } from 'antd';
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
import { Center, Flexbox } from 'react-layout-kit';
|
|
4
|
+
|
|
5
|
+
import { useStyles } from './style';
|
|
6
|
+
|
|
7
|
+
const Loading = memo(() => {
|
|
8
|
+
const { styles } = useStyles();
|
|
9
|
+
return (
|
|
10
|
+
<>
|
|
11
|
+
<Center className={styles.container} gap={16} style={{ paddingTop: 80 }}>
|
|
12
|
+
<Skeleton.Avatar active shape={'circle'} size={100} />
|
|
13
|
+
<Skeleton
|
|
14
|
+
active
|
|
15
|
+
className={styles.loading}
|
|
16
|
+
paragraph={{
|
|
17
|
+
rows: 3,
|
|
18
|
+
style: {
|
|
19
|
+
alignItems: 'center',
|
|
20
|
+
display: 'flex',
|
|
21
|
+
flexDirection: 'column',
|
|
22
|
+
},
|
|
23
|
+
width: ['60%', '80%', '20%'],
|
|
24
|
+
}}
|
|
25
|
+
title={{
|
|
26
|
+
style: {
|
|
27
|
+
alignSelf: 'center',
|
|
28
|
+
marginBottom: 0,
|
|
29
|
+
},
|
|
30
|
+
width: '50%',
|
|
31
|
+
}}
|
|
32
|
+
/>
|
|
33
|
+
<Skeleton.Button active block />
|
|
34
|
+
<Skeleton
|
|
35
|
+
active
|
|
36
|
+
className={styles.loading}
|
|
37
|
+
paragraph={{
|
|
38
|
+
rows: 1,
|
|
39
|
+
style: {
|
|
40
|
+
alignItems: 'center',
|
|
41
|
+
display: 'flex',
|
|
42
|
+
flexDirection: 'column',
|
|
43
|
+
marginBottom: 0,
|
|
44
|
+
},
|
|
45
|
+
width: ['20%'],
|
|
46
|
+
}}
|
|
47
|
+
title={false}
|
|
48
|
+
/>
|
|
49
|
+
</Center>
|
|
50
|
+
<Center gap={16} style={{ padding: 16 }}>
|
|
51
|
+
<Flexbox gap={16} horizontal>
|
|
52
|
+
<Skeleton.Button active size={'small'} />
|
|
53
|
+
<Skeleton.Button active size={'small'} />
|
|
54
|
+
</Flexbox>
|
|
55
|
+
<Skeleton active paragraph={{ rows: 6 }} title={false} />
|
|
56
|
+
</Center>
|
|
57
|
+
</>
|
|
58
|
+
);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
export default Loading;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createStyles } from 'antd-style';
|
|
2
|
+
import { encode } from 'gpt-tokenizer';
|
|
3
|
+
import { memo, useMemo } from 'react';
|
|
4
|
+
|
|
5
|
+
const useStyles = createStyles(
|
|
6
|
+
({ css, token }) => css`
|
|
7
|
+
padding: 2px 5px;
|
|
8
|
+
|
|
9
|
+
font-size: 12px;
|
|
10
|
+
line-height: 1;
|
|
11
|
+
color: ${token.colorBgLayout};
|
|
12
|
+
|
|
13
|
+
background: ${token.colorText};
|
|
14
|
+
border-radius: 12px;
|
|
15
|
+
`,
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const TokenTag = memo<{ systemRole: string }>(({ systemRole }) => {
|
|
19
|
+
const { styles } = useStyles();
|
|
20
|
+
const value = useMemo(() => encode(systemRole).length, [systemRole]);
|
|
21
|
+
|
|
22
|
+
return <div className={styles}>{value}</div>;
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export default TokenTag;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Markdown, TabsNav } from '@lobehub/ui';
|
|
2
|
+
import { memo, useState } from 'react';
|
|
3
|
+
import { useTranslation } from 'react-i18next';
|
|
4
|
+
import { Flexbox } from 'react-layout-kit';
|
|
5
|
+
|
|
6
|
+
import TokenTag from '@/pages/market/features/SideBar/AgentInfo/TokenTag';
|
|
7
|
+
import { useMarketStore } from '@/store/market';
|
|
8
|
+
|
|
9
|
+
import AgentCardBanner from '../../AgentCard/AgentCardBanner';
|
|
10
|
+
import Comment from './Comment';
|
|
11
|
+
import Header from './Header';
|
|
12
|
+
import Loading from './Loading';
|
|
13
|
+
import { useStyles } from './style';
|
|
14
|
+
|
|
15
|
+
enum InfoTabs {
|
|
16
|
+
comment = 'comment',
|
|
17
|
+
prompt = 'prompt',
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const AgentModalInner = memo(() => {
|
|
21
|
+
const [useFetchAgent, currentIdentifier] = useMarketStore((s) => [
|
|
22
|
+
s.useFetchAgent,
|
|
23
|
+
s.currentIdentifier,
|
|
24
|
+
]);
|
|
25
|
+
const { styles } = useStyles();
|
|
26
|
+
const { data, isLoading } = useFetchAgent(currentIdentifier);
|
|
27
|
+
const { t } = useTranslation('market');
|
|
28
|
+
const [tab, setTab] = useState<string>(InfoTabs.prompt);
|
|
29
|
+
|
|
30
|
+
if (isLoading || !data?.meta) return <Loading />;
|
|
31
|
+
|
|
32
|
+
const { config, meta, identifier } = data;
|
|
33
|
+
const { systemRole } = config;
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<>
|
|
37
|
+
<AgentCardBanner mask meta={meta} size={10} style={{ height: 120, marginBottom: -60 }} />
|
|
38
|
+
<Header />
|
|
39
|
+
<Flexbox align={'center'}>
|
|
40
|
+
<TabsNav
|
|
41
|
+
activeKey={tab}
|
|
42
|
+
className={styles.nav}
|
|
43
|
+
items={[
|
|
44
|
+
{
|
|
45
|
+
key: InfoTabs.prompt,
|
|
46
|
+
label: (
|
|
47
|
+
<Flexbox align={'center'} gap={8} horizontal>
|
|
48
|
+
{t('sidebar.prompt')} <TokenTag systemRole={systemRole} />
|
|
49
|
+
</Flexbox>
|
|
50
|
+
),
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
key: InfoTabs.comment,
|
|
54
|
+
label: t('sidebar.comment'),
|
|
55
|
+
},
|
|
56
|
+
]}
|
|
57
|
+
onChange={setTab}
|
|
58
|
+
/>
|
|
59
|
+
</Flexbox>
|
|
60
|
+
<Flexbox style={{ padding: 16 }}>
|
|
61
|
+
{tab === InfoTabs.prompt && <Markdown fullFeaturedCodeBlock>{systemRole}</Markdown>}
|
|
62
|
+
{tab === InfoTabs.comment && <Comment identifier={identifier} />}
|
|
63
|
+
</Flexbox>
|
|
64
|
+
</>
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
export default AgentModalInner;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { createStyles } from 'antd-style';
|
|
2
|
+
|
|
3
|
+
export const useStyles = createStyles(({ css, token }) => ({
|
|
4
|
+
author: css`
|
|
5
|
+
font-size: 12px;
|
|
6
|
+
`,
|
|
7
|
+
|
|
8
|
+
avatar: css`
|
|
9
|
+
flex: none;
|
|
10
|
+
`,
|
|
11
|
+
container: css`
|
|
12
|
+
position: relative;
|
|
13
|
+
padding: 16px 16px 24px;
|
|
14
|
+
border-bottom: 1px solid ${token.colorBorderSecondary};
|
|
15
|
+
`,
|
|
16
|
+
date: css`
|
|
17
|
+
font-size: 12px;
|
|
18
|
+
color: ${token.colorTextDescription};
|
|
19
|
+
`,
|
|
20
|
+
desc: css`
|
|
21
|
+
color: ${token.colorTextDescription};
|
|
22
|
+
text-align: center;
|
|
23
|
+
`,
|
|
24
|
+
loading: css`
|
|
25
|
+
.ant-skeleton-content {
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
}
|
|
29
|
+
`,
|
|
30
|
+
nav: css`
|
|
31
|
+
padding-top: 4px;
|
|
32
|
+
|
|
33
|
+
.ant-tabs-tab {
|
|
34
|
+
margin: 4px !important;
|
|
35
|
+
|
|
36
|
+
+ .ant-tabs-tab {
|
|
37
|
+
margin: 4px !important;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
`,
|
|
41
|
+
title: css`
|
|
42
|
+
font-size: 20px;
|
|
43
|
+
font-weight: 600;
|
|
44
|
+
text-align: center;
|
|
45
|
+
`,
|
|
46
|
+
}));
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { DraggablePanel, DraggablePanelBody, DraggablePanelContainer } from '@lobehub/ui';
|
|
2
|
+
import { createStyles } from 'antd-style';
|
|
3
|
+
import { ReactNode, memo, useState } from 'react';
|
|
4
|
+
|
|
5
|
+
import SafeSpacing from '@/components/SafeSpacing';
|
|
6
|
+
import { MARKET_SIDEBAR_WIDTH } from '@/const/layoutTokens';
|
|
7
|
+
import { agentMarketSelectors, useMarketStore } from '@/store/market';
|
|
8
|
+
|
|
9
|
+
const useStyles = createStyles(({ css, token, stylish }) => ({
|
|
10
|
+
content: css`
|
|
11
|
+
display: flex;
|
|
12
|
+
flex-direction: column;
|
|
13
|
+
`,
|
|
14
|
+
drawer: css`
|
|
15
|
+
background: ${token.colorBgLayout};
|
|
16
|
+
`,
|
|
17
|
+
header: css`
|
|
18
|
+
border-bottom: 1px solid ${token.colorBorder};
|
|
19
|
+
`,
|
|
20
|
+
noScrollbar: stylish.noScrollbar,
|
|
21
|
+
}));
|
|
22
|
+
|
|
23
|
+
const SideBar = memo<{ children: ReactNode }>(({ children }) => {
|
|
24
|
+
const { styles } = useStyles();
|
|
25
|
+
const [tempId, setTempId] = useState<string>('');
|
|
26
|
+
const [showAgentSidebar, deactivateAgent, activateAgent] = useMarketStore((s) => [
|
|
27
|
+
agentMarketSelectors.showSideBar(s),
|
|
28
|
+
s.deactivateAgent,
|
|
29
|
+
s.activateAgent,
|
|
30
|
+
]);
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<DraggablePanel
|
|
34
|
+
className={styles.drawer}
|
|
35
|
+
classNames={{
|
|
36
|
+
content: styles.content,
|
|
37
|
+
}}
|
|
38
|
+
expand={showAgentSidebar}
|
|
39
|
+
minWidth={MARKET_SIDEBAR_WIDTH}
|
|
40
|
+
mode={'fixed'}
|
|
41
|
+
onExpandChange={(show) => {
|
|
42
|
+
if (!show) {
|
|
43
|
+
setTempId(useMarketStore.getState().currentIdentifier);
|
|
44
|
+
deactivateAgent();
|
|
45
|
+
} else if (tempId) {
|
|
46
|
+
activateAgent(tempId);
|
|
47
|
+
}
|
|
48
|
+
}}
|
|
49
|
+
placement={'right'}
|
|
50
|
+
>
|
|
51
|
+
<DraggablePanelContainer
|
|
52
|
+
style={{
|
|
53
|
+
flex: 'none',
|
|
54
|
+
height: '100vh',
|
|
55
|
+
minWidth: MARKET_SIDEBAR_WIDTH,
|
|
56
|
+
}}
|
|
57
|
+
>
|
|
58
|
+
<SafeSpacing />
|
|
59
|
+
<DraggablePanelBody
|
|
60
|
+
className={styles.noScrollbar}
|
|
61
|
+
style={{ padding: 0, position: 'relative' }}
|
|
62
|
+
>
|
|
63
|
+
{children}
|
|
64
|
+
</DraggablePanelBody>
|
|
65
|
+
</DraggablePanelContainer>
|
|
66
|
+
</DraggablePanel>
|
|
67
|
+
);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
export default SideBar;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ActionIcon } from '@lobehub/ui';
|
|
2
|
+
import { Drawer } from 'antd';
|
|
3
|
+
import { useTheme } from 'antd-style';
|
|
4
|
+
import { X } from 'lucide-react';
|
|
5
|
+
import { PropsWithChildren, memo } from 'react';
|
|
6
|
+
import { useTranslation } from 'react-i18next';
|
|
7
|
+
|
|
8
|
+
import { agentMarketSelectors, useMarketStore } from '@/store/market';
|
|
9
|
+
|
|
10
|
+
const Mobile = memo<PropsWithChildren>(({ children }) => {
|
|
11
|
+
const theme = useTheme();
|
|
12
|
+
const [showAgentSidebar, deactivateAgent] = useMarketStore((s) => [
|
|
13
|
+
agentMarketSelectors.showSideBar(s),
|
|
14
|
+
s.deactivateAgent,
|
|
15
|
+
]);
|
|
16
|
+
|
|
17
|
+
const { t } = useTranslation('market');
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Drawer
|
|
21
|
+
bodyStyle={{ padding: 0 }}
|
|
22
|
+
closeIcon={<ActionIcon icon={X} size={{ blockSize: 32, fontSize: 20 }} />}
|
|
23
|
+
drawerStyle={{ background: theme.colorBgContainer }}
|
|
24
|
+
headerStyle={{ padding: '8px 4px' }}
|
|
25
|
+
height={'75vh'}
|
|
26
|
+
onClose={deactivateAgent}
|
|
27
|
+
open={showAgentSidebar}
|
|
28
|
+
placement={'bottom'}
|
|
29
|
+
title={t('sidebar.title')}
|
|
30
|
+
>
|
|
31
|
+
{children}
|
|
32
|
+
</Drawer>
|
|
33
|
+
);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export default Mobile;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { useResponsive } from 'antd-style';
|
|
2
|
+
import { memo } from 'react';
|
|
3
|
+
import { Flexbox } from 'react-layout-kit';
|
|
4
|
+
|
|
5
|
+
import AgentInfo from './AgentInfo';
|
|
6
|
+
import Desktop from './Desktop';
|
|
7
|
+
import Mobile from './Mobile';
|
|
8
|
+
|
|
9
|
+
const SideBar = memo(() => {
|
|
10
|
+
const { mobile } = useResponsive();
|
|
11
|
+
|
|
12
|
+
const Render = mobile ? Mobile : Desktop;
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
<Render>
|
|
16
|
+
<Flexbox>
|
|
17
|
+
<AgentInfo />
|
|
18
|
+
</Flexbox>
|
|
19
|
+
</Render>
|
|
20
|
+
);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
export default SideBar;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Button } from 'antd';
|
|
2
|
+
import isEqual from 'fast-deep-equal';
|
|
3
|
+
import { startCase } from 'lodash-es';
|
|
4
|
+
import { memo } from 'react';
|
|
5
|
+
import { Flexbox } from 'react-layout-kit';
|
|
6
|
+
|
|
7
|
+
import { agentMarketSelectors, useMarketStore } from '@/store/market';
|
|
8
|
+
|
|
9
|
+
const TagList = memo(() => {
|
|
10
|
+
const agentTagList = useMarketStore(agentMarketSelectors.getAgentTagList, isEqual);
|
|
11
|
+
const keywords = useMarketStore((s) => s.searchKeywords);
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<Flexbox gap={8} horizontal style={{ flexWrap: 'wrap' }}>
|
|
15
|
+
{agentTagList.map((item) => (
|
|
16
|
+
<Button
|
|
17
|
+
key={item}
|
|
18
|
+
onClick={() => useMarketStore.setState({ searchKeywords: item })}
|
|
19
|
+
size={'small'}
|
|
20
|
+
type={keywords === item ? 'primary' : 'default'}
|
|
21
|
+
>
|
|
22
|
+
{startCase(item)}
|
|
23
|
+
</Button>
|
|
24
|
+
))}
|
|
25
|
+
</Flexbox>
|
|
26
|
+
);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
export default TagList;
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { useResponsive } from 'antd-style';
|
|
2
2
|
import Head from 'next/head';
|
|
3
|
-
import { memo } from 'react';
|
|
3
|
+
import { memo, useEffect } from 'react';
|
|
4
4
|
import { useTranslation } from 'react-i18next';
|
|
5
5
|
|
|
6
|
+
import { useMarketStore } from '@/store/market';
|
|
6
7
|
import { genSiteHeadTitle } from '@/utils/genSiteHeadTitle';
|
|
7
8
|
|
|
9
|
+
import AgentCard from './features/AgentCard';
|
|
10
|
+
import AgentSearchBar from './features/AgentSearchBar';
|
|
8
11
|
import DesktopLayout from './layout';
|
|
9
12
|
import MobileLayout from './layout.mobile';
|
|
10
13
|
|
|
@@ -13,6 +16,11 @@ const Market = memo(() => {
|
|
|
13
16
|
const pageTitle = genSiteHeadTitle(t('tab.market'));
|
|
14
17
|
const { mobile } = useResponsive();
|
|
15
18
|
|
|
19
|
+
useEffect(() => {
|
|
20
|
+
// refs: https://github.com/pmndrs/zustand/blob/main/docs/integrations/persisting-store-data.md#hashydrated
|
|
21
|
+
useMarketStore.persist.rehydrate();
|
|
22
|
+
}, []);
|
|
23
|
+
|
|
16
24
|
const RenderLayout = mobile ? MobileLayout : DesktopLayout;
|
|
17
25
|
|
|
18
26
|
return (
|
|
@@ -21,7 +29,8 @@ const Market = memo(() => {
|
|
|
21
29
|
<title>{pageTitle}</title>
|
|
22
30
|
</Head>
|
|
23
31
|
<RenderLayout>
|
|
24
|
-
<
|
|
32
|
+
<AgentSearchBar />
|
|
33
|
+
<AgentCard />
|
|
25
34
|
</RenderLayout>
|
|
26
35
|
</>
|
|
27
36
|
);
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
import { ReactNode, memo } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { Flexbox } from 'react-layout-kit';
|
|
3
3
|
|
|
4
4
|
import AppMobileLayout from '@/layout/AppMobileLayout';
|
|
5
|
-
import
|
|
5
|
+
import SideBar from '@/pages/market/features/SideBar';
|
|
6
6
|
|
|
7
7
|
import Header from './features/Header';
|
|
8
8
|
|
|
9
|
-
const
|
|
10
|
-
useSwitchSideBarOnInit('chat');
|
|
11
|
-
|
|
9
|
+
const MarketLayout = memo<{ children: ReactNode }>(({ children }) => {
|
|
12
10
|
return (
|
|
13
11
|
<AppMobileLayout navBar={<Header />} showTabBar>
|
|
14
|
-
<
|
|
12
|
+
<Flexbox flex={1} gap={16} style={{ padding: 16 }}>
|
|
13
|
+
{children}
|
|
14
|
+
</Flexbox>
|
|
15
|
+
<SideBar />
|
|
15
16
|
</AppMobileLayout>
|
|
16
17
|
);
|
|
17
18
|
});
|
|
18
19
|
|
|
19
|
-
export default
|
|
20
|
+
export default MarketLayout;
|
|
@@ -1,10 +1,30 @@
|
|
|
1
|
+
import { GridBackground } from '@lobehub/ui';
|
|
2
|
+
import { createStyles } from 'antd-style';
|
|
1
3
|
import { PropsWithChildren, memo } from 'react';
|
|
2
4
|
import { Center, Flexbox } from 'react-layout-kit';
|
|
3
5
|
|
|
6
|
+
import SafeSpacing from '@/components/SafeSpacing';
|
|
7
|
+
import { MAX_WIDTH } from '@/const/layoutTokens';
|
|
8
|
+
|
|
4
9
|
import AppLayout from '../../layout/AppLayout';
|
|
5
10
|
import Header from './features/Header';
|
|
11
|
+
import SideBar from './features/SideBar';
|
|
12
|
+
|
|
13
|
+
const useStyles = createStyles(({ css }) => ({
|
|
14
|
+
background: css`
|
|
15
|
+
width: 80%;
|
|
16
|
+
margin: -60px 0 -20px;
|
|
17
|
+
`,
|
|
18
|
+
title: css`
|
|
19
|
+
z-index: 2;
|
|
20
|
+
margin-top: 24px;
|
|
21
|
+
font-size: 56px;
|
|
22
|
+
font-weight: 800;
|
|
23
|
+
`,
|
|
24
|
+
}));
|
|
6
25
|
|
|
7
26
|
const MarketLayout = memo<PropsWithChildren>(({ children }) => {
|
|
27
|
+
const { theme, styles } = useStyles();
|
|
8
28
|
return (
|
|
9
29
|
<AppLayout>
|
|
10
30
|
<Flexbox
|
|
@@ -14,7 +34,25 @@ const MarketLayout = memo<PropsWithChildren>(({ children }) => {
|
|
|
14
34
|
style={{ position: 'relative' }}
|
|
15
35
|
>
|
|
16
36
|
<Header />
|
|
17
|
-
<
|
|
37
|
+
<Flexbox flex={1} height={'calc(100vh - 64px)'} horizontal>
|
|
38
|
+
<Flexbox align={'center'} flex={1} style={{ overflow: 'auto', padding: 16 }}>
|
|
39
|
+
<SafeSpacing />
|
|
40
|
+
|
|
41
|
+
<Flexbox gap={16} style={{ maxWidth: MAX_WIDTH, position: 'relative', width: '100%' }}>
|
|
42
|
+
<Center>
|
|
43
|
+
<h1 className={styles.title}>Find & Use The Best Agents</h1>
|
|
44
|
+
<GridBackground
|
|
45
|
+
animation
|
|
46
|
+
className={styles.background}
|
|
47
|
+
colorFront={theme.colorText}
|
|
48
|
+
random
|
|
49
|
+
/>
|
|
50
|
+
</Center>
|
|
51
|
+
{children}
|
|
52
|
+
</Flexbox>
|
|
53
|
+
</Flexbox>
|
|
54
|
+
<SideBar />
|
|
55
|
+
</Flexbox>
|
|
18
56
|
</Flexbox>
|
|
19
57
|
</AppLayout>
|
|
20
58
|
);
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import { ChatHeader, ChatHeaderTitle } from '@lobehub/ui';
|
|
2
|
+
import Router from 'next/router';
|
|
2
3
|
import { memo } from 'react';
|
|
3
4
|
import { useTranslation } from 'react-i18next';
|
|
4
5
|
|
|
5
|
-
import { useSessionStore } from '@/store/session';
|
|
6
|
-
|
|
7
6
|
const Index = memo(() => {
|
|
8
7
|
const { t } = useTranslation('setting');
|
|
9
|
-
const [switchBackToChat] = useSessionStore((s) => [s.switchBackToChat]);
|
|
10
8
|
|
|
11
9
|
return (
|
|
12
10
|
<ChatHeader
|
|
13
11
|
left={<ChatHeaderTitle title={t('header.global')} />}
|
|
14
|
-
onBackClick={
|
|
12
|
+
onBackClick={() => Router.back()}
|
|
15
13
|
showBackButton
|
|
16
14
|
/>
|
|
17
15
|
);
|