@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
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { memo } from 'react';
|
|
4
|
+
import { Flexbox } from 'react-layout-kit';
|
|
5
|
+
|
|
6
|
+
import HeaderContent from '@/app/(main)/chat/settings/features/HeaderContent';
|
|
7
|
+
import Menu from '@/components/Menu';
|
|
8
|
+
import { useQuery } from '@/hooks/useQuery';
|
|
9
|
+
import { useQueryRoute } from '@/hooks/useQueryRoute';
|
|
10
|
+
import { ChatSettingsTabs } from '@/store/global/initialState';
|
|
11
|
+
|
|
12
|
+
import { useCategory } from './useCategory';
|
|
13
|
+
|
|
14
|
+
const CategoryContent = memo(() => {
|
|
15
|
+
const cateItems = useCategory();
|
|
16
|
+
const router = useQueryRoute();
|
|
17
|
+
const { tab = ChatSettingsTabs.Meta } = useQuery();
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<>
|
|
21
|
+
<Menu
|
|
22
|
+
items={cateItems}
|
|
23
|
+
onClick={({ key }) => {
|
|
24
|
+
router.replace('/chat/settings/modal', { query: { tab: key } });
|
|
25
|
+
}}
|
|
26
|
+
selectable
|
|
27
|
+
selectedKeys={[tab as any]}
|
|
28
|
+
variant={'compact'}
|
|
29
|
+
/>
|
|
30
|
+
<Flexbox align={'center'} gap={8} paddingInline={8} width={'100%'}>
|
|
31
|
+
<HeaderContent modal />
|
|
32
|
+
</Flexbox>
|
|
33
|
+
</>
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export default CategoryContent;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Icon } from '@lobehub/ui';
|
|
2
|
+
import { Blocks, Bot, BrainCog, MessagesSquare, Mic2, UserCircle } from 'lucide-react';
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { useTranslation } from 'react-i18next';
|
|
5
|
+
|
|
6
|
+
import type { MenuProps } from '@/components/Menu';
|
|
7
|
+
import { ChatSettingsTabs } from '@/store/global/initialState';
|
|
8
|
+
|
|
9
|
+
interface UseCategoryOptions {
|
|
10
|
+
mobile?: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const useCategory = ({ mobile }: UseCategoryOptions = {}) => {
|
|
14
|
+
const { t } = useTranslation('setting');
|
|
15
|
+
const iconSize = mobile ? { fontSize: 20 } : undefined;
|
|
16
|
+
|
|
17
|
+
const cateItems: MenuProps['items'] = useMemo(
|
|
18
|
+
() => [
|
|
19
|
+
{
|
|
20
|
+
icon: <Icon icon={UserCircle} size={iconSize} />,
|
|
21
|
+
key: ChatSettingsTabs.Meta,
|
|
22
|
+
label: t('settingAgent.title'),
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
icon: <Icon icon={Bot} size={iconSize} />,
|
|
26
|
+
key: ChatSettingsTabs.Prompt,
|
|
27
|
+
label: t('settingAgent.prompt.title'),
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
icon: <Icon icon={MessagesSquare} size={iconSize} />,
|
|
31
|
+
key: ChatSettingsTabs.Chat,
|
|
32
|
+
label: t('settingChat.title'),
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
icon: <Icon icon={BrainCog} size={iconSize} />,
|
|
36
|
+
key: ChatSettingsTabs.Modal,
|
|
37
|
+
label: t('settingModel.title'),
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
icon: <Icon icon={Mic2} size={iconSize} />,
|
|
41
|
+
key: ChatSettingsTabs.TTS,
|
|
42
|
+
label: t('settingTTS.title'),
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
icon: <Icon icon={Blocks} size={iconSize} />,
|
|
46
|
+
key: ChatSettingsTabs.Plugin,
|
|
47
|
+
label: t('settingPlugin.title'),
|
|
48
|
+
},
|
|
49
|
+
],
|
|
50
|
+
[t],
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
return cateItems;
|
|
54
|
+
};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Skeleton } from 'antd';
|
|
4
|
+
import isEqual from 'fast-deep-equal';
|
|
5
|
+
import dynamic from 'next/dynamic';
|
|
6
|
+
import { PropsWithChildren, memo } from 'react';
|
|
7
|
+
import { useTranslation } from 'react-i18next';
|
|
8
|
+
|
|
9
|
+
import StoreUpdater from '@/features/AgentSetting/StoreUpdater';
|
|
10
|
+
import { Provider, createStore } from '@/features/AgentSetting/store';
|
|
11
|
+
import { useAgentStore } from '@/store/agent';
|
|
12
|
+
import { agentSelectors } from '@/store/agent/slices/chat';
|
|
13
|
+
import { useSessionStore } from '@/store/session';
|
|
14
|
+
import { sessionMetaSelectors } from '@/store/session/selectors';
|
|
15
|
+
|
|
16
|
+
import SettingModalLayout from '../../../_layout/SettingModalLayout';
|
|
17
|
+
|
|
18
|
+
const CategoryContent = dynamic(() => import('./features/CategoryContent'), {
|
|
19
|
+
loading: () => <Skeleton paragraph={{ rows: 6 }} title={false} />,
|
|
20
|
+
ssr: false,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
const Layout = memo<PropsWithChildren>(({ children }) => {
|
|
24
|
+
const { t } = useTranslation('setting');
|
|
25
|
+
const id = useSessionStore((s) => s.activeId);
|
|
26
|
+
const config = useAgentStore(agentSelectors.currentAgentConfig, isEqual);
|
|
27
|
+
const meta = useSessionStore(sessionMetaSelectors.currentAgentMeta, isEqual);
|
|
28
|
+
const [updateAgentConfig] = useAgentStore((s) => [s.updateAgentConfig]);
|
|
29
|
+
|
|
30
|
+
const [updateAgentMeta] = useSessionStore((s) => [
|
|
31
|
+
s.updateSessionMeta,
|
|
32
|
+
sessionMetaSelectors.currentAgentTitle(s),
|
|
33
|
+
]);
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<SettingModalLayout
|
|
37
|
+
category={<CategoryContent />}
|
|
38
|
+
desc={t('header.sessionDesc')}
|
|
39
|
+
title={t('header.session')}
|
|
40
|
+
>
|
|
41
|
+
<Provider createStore={createStore}>
|
|
42
|
+
<StoreUpdater
|
|
43
|
+
config={config}
|
|
44
|
+
id={id}
|
|
45
|
+
meta={meta}
|
|
46
|
+
onConfigChange={updateAgentConfig}
|
|
47
|
+
onMetaChange={updateAgentMeta}
|
|
48
|
+
/>
|
|
49
|
+
{children}
|
|
50
|
+
</Provider>
|
|
51
|
+
</SettingModalLayout>
|
|
52
|
+
);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
export default Layout;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import dynamic from 'next/dynamic';
|
|
4
|
+
|
|
5
|
+
import { useQuery } from '@/hooks/useQuery';
|
|
6
|
+
import { ChatSettingsTabs } from '@/store/global/initialState';
|
|
7
|
+
|
|
8
|
+
import Skeleton from './loading';
|
|
9
|
+
|
|
10
|
+
const loading = () => <Skeleton />;
|
|
11
|
+
|
|
12
|
+
const AgentMeta = dynamic(() => import('@/features/AgentSetting/AgentMeta'), {
|
|
13
|
+
loading,
|
|
14
|
+
ssr: false,
|
|
15
|
+
});
|
|
16
|
+
const AgentChat = dynamic(() => import('@/features/AgentSetting/AgentChat'), {
|
|
17
|
+
loading,
|
|
18
|
+
ssr: false,
|
|
19
|
+
});
|
|
20
|
+
const AgentPrompt = dynamic(() => import('@/features/AgentSetting/AgentPrompt'), {
|
|
21
|
+
loading,
|
|
22
|
+
ssr: false,
|
|
23
|
+
});
|
|
24
|
+
const AgentPlugin = dynamic(() => import('@/features/AgentSetting/AgentPlugin'), {
|
|
25
|
+
loading,
|
|
26
|
+
ssr: false,
|
|
27
|
+
});
|
|
28
|
+
const AgentModal = dynamic(() => import('@/features/AgentSetting/AgentModal'), {
|
|
29
|
+
loading,
|
|
30
|
+
ssr: false,
|
|
31
|
+
});
|
|
32
|
+
const AgentTTS = dynamic(() => import('@/features/AgentSetting/AgentTTS'), { loading, ssr: false });
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* @description: Agent Settings Modal (intercepting route: /chat/settings/modal )
|
|
36
|
+
* @refs: https://github.com/lobehub/lobe-chat/discussions/2295#discussioncomment-9290942
|
|
37
|
+
*/
|
|
38
|
+
|
|
39
|
+
const Page = () => {
|
|
40
|
+
const { tab = ChatSettingsTabs.Meta } = useQuery();
|
|
41
|
+
return (
|
|
42
|
+
<>
|
|
43
|
+
{tab === ChatSettingsTabs.Meta && <AgentMeta />}
|
|
44
|
+
{tab === ChatSettingsTabs.Prompt && <AgentPrompt modal />}
|
|
45
|
+
{tab === ChatSettingsTabs.Chat && <AgentChat />}
|
|
46
|
+
{tab === ChatSettingsTabs.Modal && <AgentModal />}
|
|
47
|
+
{tab === ChatSettingsTabs.TTS && <AgentTTS />}
|
|
48
|
+
{tab === ChatSettingsTabs.Plugin && <AgentPlugin />}
|
|
49
|
+
</>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
Page.displayName = 'AgentSettingModal';
|
|
54
|
+
|
|
55
|
+
export default Page;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { Modal } from '@lobehub/ui';
|
|
4
|
+
import { useRouter } from 'next/navigation';
|
|
5
|
+
import { PropsWithChildren, memo, useState } from 'react';
|
|
6
|
+
|
|
7
|
+
const SessionSettingsModal = memo<PropsWithChildren>(({ children }) => {
|
|
8
|
+
const [open, setOpen] = useState(true);
|
|
9
|
+
const router = useRouter();
|
|
10
|
+
|
|
11
|
+
return (
|
|
12
|
+
<Modal
|
|
13
|
+
afterClose={() => {
|
|
14
|
+
router.back();
|
|
15
|
+
}}
|
|
16
|
+
footer={null}
|
|
17
|
+
onCancel={() => setOpen(false)}
|
|
18
|
+
open={open}
|
|
19
|
+
styles={{
|
|
20
|
+
body: { display: 'flex', minHeight: 'min(75vh, 750px)', overflow: 'hidden', padding: 0 },
|
|
21
|
+
}}
|
|
22
|
+
title={false}
|
|
23
|
+
width={1024}
|
|
24
|
+
>
|
|
25
|
+
{children}
|
|
26
|
+
</Modal>
|
|
27
|
+
);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
export default SessionSettingsModal;
|
package/src/app/layout.tsx
CHANGED
|
@@ -12,9 +12,10 @@ import { isMobileDevice } from '@/utils/responsive';
|
|
|
12
12
|
|
|
13
13
|
type RootLayoutProps = {
|
|
14
14
|
children: ReactNode;
|
|
15
|
+
modal: ReactNode;
|
|
15
16
|
};
|
|
16
17
|
|
|
17
|
-
const RootLayout = async ({ children }: RootLayoutProps) => {
|
|
18
|
+
const RootLayout = async ({ children, modal }: RootLayoutProps) => {
|
|
18
19
|
const cookieStore = cookies();
|
|
19
20
|
|
|
20
21
|
const lang = cookieStore.get(LOBE_LOCALE_COOKIE);
|
|
@@ -24,7 +25,10 @@ const RootLayout = async ({ children }: RootLayoutProps) => {
|
|
|
24
25
|
<html dir={direction} lang={lang?.value || DEFAULT_LANG} suppressHydrationWarning>
|
|
25
26
|
<body>
|
|
26
27
|
<GlobalProvider>
|
|
27
|
-
<AuthProvider>
|
|
28
|
+
<AuthProvider>
|
|
29
|
+
{children}
|
|
30
|
+
{modal}
|
|
31
|
+
</AuthProvider>
|
|
28
32
|
</GlobalProvider>
|
|
29
33
|
<Analytics />
|
|
30
34
|
<SpeedInsights />
|
|
@@ -8,7 +8,11 @@ const { Item } = List;
|
|
|
8
8
|
const useStyles = createStyles(({ css, token, isDarkMode }) => ({
|
|
9
9
|
container: css`
|
|
10
10
|
position: relative;
|
|
11
|
-
|
|
11
|
+
|
|
12
|
+
gap: 12px;
|
|
13
|
+
|
|
14
|
+
padding: 16px !important;
|
|
15
|
+
|
|
12
16
|
background: ${isDarkMode ? token.colorBgLayout : token.colorBgContainer};
|
|
13
17
|
border-radius: 0;
|
|
14
18
|
`,
|
|
@@ -1,10 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { useRouter } from 'next/navigation';
|
|
3
|
-
|
|
1
|
+
import { useOpenChatSettings } from '@/hooks/useInterceptingRoutes';
|
|
4
2
|
import { useGlobalStore } from '@/store/global';
|
|
5
3
|
import { useSessionStore } from '@/store/session';
|
|
6
4
|
import { sessionSelectors } from '@/store/session/selectors';
|
|
7
|
-
import { pathString } from '@/utils/url';
|
|
8
5
|
|
|
9
6
|
import { OnAvatarsClick, RenderMessage } from '../types';
|
|
10
7
|
import { AssistantMessage } from './Assistant';
|
|
@@ -22,18 +19,18 @@ export const renderMessages: Record<string, RenderMessage> = {
|
|
|
22
19
|
export const useAvatarsClick = (): OnAvatarsClick => {
|
|
23
20
|
const [isInbox] = useSessionStore((s) => [sessionSelectors.isInboxSession(s)]);
|
|
24
21
|
const [toggleSystemRole] = useGlobalStore((s) => [s.toggleSystemRole]);
|
|
25
|
-
const
|
|
26
|
-
const router = useRouter();
|
|
22
|
+
const openChatSettings = useOpenChatSettings();
|
|
27
23
|
|
|
28
24
|
return (role) => {
|
|
29
25
|
switch (role) {
|
|
30
26
|
case 'assistant': {
|
|
31
|
-
return () =>
|
|
32
|
-
isInbox
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
27
|
+
return () => {
|
|
28
|
+
if (!isInbox) {
|
|
29
|
+
toggleSystemRole(true);
|
|
30
|
+
} else {
|
|
31
|
+
openChatSettings();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
37
34
|
}
|
|
38
35
|
}
|
|
39
36
|
};
|
|
@@ -14,10 +14,12 @@ import { useMarketStore } from '@/store/market';
|
|
|
14
14
|
|
|
15
15
|
const { Paragraph } = Typography;
|
|
16
16
|
|
|
17
|
-
const useStyles = createStyles(({ css, token }) => ({
|
|
17
|
+
const useStyles = createStyles(({ css, token, responsive }) => ({
|
|
18
18
|
card: css`
|
|
19
19
|
position: relative;
|
|
20
20
|
|
|
21
|
+
overflow: hidden;
|
|
22
|
+
|
|
21
23
|
height: 100%;
|
|
22
24
|
min-height: 110px;
|
|
23
25
|
padding: 16px;
|
|
@@ -30,6 +32,10 @@ const useStyles = createStyles(({ css, token }) => ({
|
|
|
30
32
|
&:hover {
|
|
31
33
|
background: ${token.colorBgElevated};
|
|
32
34
|
}
|
|
35
|
+
|
|
36
|
+
${responsive.mobile} {
|
|
37
|
+
min-height: 72px;
|
|
38
|
+
}
|
|
33
39
|
`,
|
|
34
40
|
cardDesc: css`
|
|
35
41
|
margin-block: 0 !important;
|
|
@@ -48,15 +54,18 @@ const useStyles = createStyles(({ css, token }) => ({
|
|
|
48
54
|
`,
|
|
49
55
|
}));
|
|
50
56
|
|
|
51
|
-
const AgentsSuggest = memo(() => {
|
|
57
|
+
const AgentsSuggest = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
52
58
|
const { t } = useTranslation('welcome');
|
|
59
|
+
|
|
53
60
|
const [sliceStart, setSliceStart] = useState(0);
|
|
54
61
|
const useFetchAgentList = useMarketStore((s) => s.useFetchAgentList);
|
|
55
62
|
const { isLoading } = useFetchAgentList();
|
|
56
63
|
const agentList = useMarketStore((s) => s.agentList, isEqual);
|
|
57
64
|
const { styles } = useStyles();
|
|
58
65
|
|
|
59
|
-
const
|
|
66
|
+
const agentLength = mobile ? 3 : 4;
|
|
67
|
+
|
|
68
|
+
const loadingCards = Array.from({ length: agentLength }).map((_, index) => (
|
|
60
69
|
<Flexbox className={styles.card} key={index}>
|
|
61
70
|
<Skeleton active avatar paragraph={{ rows: 2 }} title={false} />
|
|
62
71
|
</Flexbox>
|
|
@@ -64,15 +73,15 @@ const AgentsSuggest = memo(() => {
|
|
|
64
73
|
|
|
65
74
|
const cards = useMemo(
|
|
66
75
|
() =>
|
|
67
|
-
agentList.slice(sliceStart, sliceStart +
|
|
76
|
+
agentList.slice(sliceStart, sliceStart + agentLength).map((agent) => (
|
|
68
77
|
<Link href={`/market?agent=${agent.identifier}`} key={agent.identifier}>
|
|
69
78
|
<Flexbox className={styles.card} gap={8} horizontal>
|
|
70
79
|
<Avatar avatar={agent.meta.avatar} style={{ flex: 'none' }} />
|
|
71
|
-
<Flexbox gap={8}>
|
|
80
|
+
<Flexbox gap={mobile ? 2 : 8} style={{ overflow: 'hidden', width: '100%' }}>
|
|
72
81
|
<Paragraph className={styles.cardTitle} ellipsis={{ rows: 1 }}>
|
|
73
82
|
{agent.meta.title}
|
|
74
83
|
</Paragraph>
|
|
75
|
-
<Paragraph className={styles.cardDesc} ellipsis={{ rows: 2 }}>
|
|
84
|
+
<Paragraph className={styles.cardDesc} ellipsis={{ rows: mobile ? 1 : 2 }}>
|
|
76
85
|
{agent.meta.description}
|
|
77
86
|
</Paragraph>
|
|
78
87
|
</Flexbox>
|
|
@@ -13,7 +13,7 @@ import { USAGE_DOCUMENTS } from '@/const/url';
|
|
|
13
13
|
import { useSendMessage } from '@/features/ChatInput/useSend';
|
|
14
14
|
import { useChatStore } from '@/store/chat';
|
|
15
15
|
|
|
16
|
-
const useStyles = createStyles(({ css, token }) => ({
|
|
16
|
+
const useStyles = createStyles(({ css, token, responsive }) => ({
|
|
17
17
|
card: css`
|
|
18
18
|
cursor: pointer;
|
|
19
19
|
|
|
@@ -27,6 +27,10 @@ const useStyles = createStyles(({ css, token }) => ({
|
|
|
27
27
|
&:hover {
|
|
28
28
|
background: ${token.colorBgElevated};
|
|
29
29
|
}
|
|
30
|
+
|
|
31
|
+
${responsive.mobile} {
|
|
32
|
+
padding: 8px 16px;
|
|
33
|
+
}
|
|
30
34
|
`,
|
|
31
35
|
icon: css`
|
|
32
36
|
color: ${token.colorTextSecondary};
|
|
@@ -52,10 +56,11 @@ const qa = shuffle([
|
|
|
52
56
|
'q13',
|
|
53
57
|
'q14',
|
|
54
58
|
'q15',
|
|
55
|
-
])
|
|
59
|
+
]);
|
|
56
60
|
|
|
57
|
-
const QuestionSuggest = memo(() => {
|
|
61
|
+
const QuestionSuggest = memo<{ mobile?: boolean }>(({ mobile }) => {
|
|
58
62
|
const [updateInputMessage] = useChatStore((s) => [s.updateInputMessage]);
|
|
63
|
+
|
|
59
64
|
const { t } = useTranslation('welcome');
|
|
60
65
|
const { styles } = useStyles();
|
|
61
66
|
const sendMessage = useSendMessage();
|
|
@@ -73,7 +78,7 @@ const QuestionSuggest = memo(() => {
|
|
|
73
78
|
</Link>
|
|
74
79
|
</Flexbox>
|
|
75
80
|
<Flexbox gap={8} horizontal wrap={'wrap'}>
|
|
76
|
-
{qa.map((item) => {
|
|
81
|
+
{qa.slice(0, mobile ? 2 : 5).map((item) => {
|
|
77
82
|
const text = t(`guide.qa.${item}` as any);
|
|
78
83
|
return (
|
|
79
84
|
<Flexbox
|
|
@@ -6,6 +6,8 @@ import { memo, useEffect, useState } from 'react';
|
|
|
6
6
|
import { useTranslation } from 'react-i18next';
|
|
7
7
|
import { Center, Flexbox } from 'react-layout-kit';
|
|
8
8
|
|
|
9
|
+
import { useIsMobile } from '@/hooks/useIsMobile';
|
|
10
|
+
|
|
9
11
|
import AgentsSuggest from './AgentsSuggest';
|
|
10
12
|
import QuestionSuggest from './QuestionSuggest';
|
|
11
13
|
|
|
@@ -40,7 +42,7 @@ const InboxWelcome = memo(() => {
|
|
|
40
42
|
const { t } = useTranslation('welcome');
|
|
41
43
|
const [greeting, setGreeting] = useState<'morning' | 'noon' | 'afternoon' | 'night'>();
|
|
42
44
|
const { styles } = useStyles();
|
|
43
|
-
|
|
45
|
+
const mobile = useIsMobile();
|
|
44
46
|
useEffect(() => {
|
|
45
47
|
const now = new Date();
|
|
46
48
|
const hours = now.getHours();
|
|
@@ -66,8 +68,8 @@ const InboxWelcome = memo(() => {
|
|
|
66
68
|
<Markdown className={styles.desc} variant={'chat'}>
|
|
67
69
|
{t('guide.defaultMessage')}
|
|
68
70
|
</Markdown>
|
|
69
|
-
<AgentsSuggest />
|
|
70
|
-
<QuestionSuggest />
|
|
71
|
+
<AgentsSuggest mobile={mobile} />
|
|
72
|
+
<QuestionSuggest mobile={mobile} />
|
|
71
73
|
</Flexbox>
|
|
72
74
|
</Center>
|
|
73
75
|
);
|
|
@@ -22,7 +22,6 @@ const useStyles = createStyles(({ css, token }) => {
|
|
|
22
22
|
background-color: transparent;
|
|
23
23
|
}
|
|
24
24
|
`,
|
|
25
|
-
|
|
26
25
|
loader: css`
|
|
27
26
|
transform: translateX(-${size * 2}px);
|
|
28
27
|
|
|
@@ -125,6 +124,9 @@ const useStyles = createStyles(({ css, token }) => {
|
|
|
125
124
|
}
|
|
126
125
|
}
|
|
127
126
|
`,
|
|
127
|
+
wrapper: css`
|
|
128
|
+
font-size: inherit;
|
|
129
|
+
`,
|
|
128
130
|
};
|
|
129
131
|
});
|
|
130
132
|
|
|
@@ -237,6 +239,7 @@ const DataImporter = memo<DataImporterProps>(({ children, onFinishImport }) => {
|
|
|
237
239
|
|
|
238
240
|
return false;
|
|
239
241
|
}}
|
|
242
|
+
className={styles.wrapper}
|
|
240
243
|
maxCount={1}
|
|
241
244
|
showUploadList={false}
|
|
242
245
|
>
|
|
@@ -6,6 +6,7 @@ import { rgba } from 'polished';
|
|
|
6
6
|
import { memo, useMemo } from 'react';
|
|
7
7
|
import { useTranslation } from 'react-i18next';
|
|
8
8
|
|
|
9
|
+
import { useOpenSettings } from '@/hooks/useInterceptingRoutes';
|
|
9
10
|
import { SidebarTabKey } from '@/store/global/initialState';
|
|
10
11
|
|
|
11
12
|
const useStyles = createStyles(({ css, token }) => ({
|
|
@@ -24,6 +25,7 @@ interface Props {
|
|
|
24
25
|
export default memo<Props>(({ className, tabBarKey }) => {
|
|
25
26
|
const { t } = useTranslation('common');
|
|
26
27
|
const { styles } = useStyles();
|
|
28
|
+
const openSettings = useOpenSettings();
|
|
27
29
|
const router = useRouter();
|
|
28
30
|
const items: MobileTabBarProps['items'] = useMemo(
|
|
29
31
|
() => [
|
|
@@ -48,9 +50,7 @@ export default memo<Props>(({ className, tabBarKey }) => {
|
|
|
48
50
|
{
|
|
49
51
|
icon: (active) => <Icon className={active ? styles.active : undefined} icon={User} />,
|
|
50
52
|
key: SidebarTabKey.Setting,
|
|
51
|
-
onClick:
|
|
52
|
-
router.push('/settings');
|
|
53
|
-
},
|
|
53
|
+
onClick: openSettings,
|
|
54
54
|
title: t('tab.setting'),
|
|
55
55
|
},
|
|
56
56
|
],
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { Tooltip } from '@lobehub/ui';
|
|
2
|
+
import { Tag } from 'antd';
|
|
3
|
+
import { useTheme } from 'antd-style';
|
|
4
|
+
import { CSSProperties, memo, useMemo } from 'react';
|
|
5
|
+
import { useTranslation } from 'react-i18next';
|
|
6
|
+
|
|
7
|
+
export enum PlanType {
|
|
8
|
+
Preview = 'preview',
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface PlanTagProps {
|
|
12
|
+
type?: PlanType;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const PlanTag = memo<PlanTagProps>(({ type = PlanType.Preview }) => {
|
|
16
|
+
const { t } = useTranslation('common');
|
|
17
|
+
const theme = useTheme();
|
|
18
|
+
const tag: {
|
|
19
|
+
desc: string;
|
|
20
|
+
style: CSSProperties;
|
|
21
|
+
title: string;
|
|
22
|
+
} = useMemo(() => {
|
|
23
|
+
switch (type) {
|
|
24
|
+
case PlanType.Preview: {
|
|
25
|
+
return {
|
|
26
|
+
desc: t('userPanel.preview'),
|
|
27
|
+
style: {
|
|
28
|
+
background: theme.colorFill,
|
|
29
|
+
},
|
|
30
|
+
title: 'Preview',
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}, []);
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<Tooltip title={tag.desc}>
|
|
38
|
+
<Tag bordered={false} style={{ ...tag.style, borderRadius: 12, cursor: 'pointer' }}>
|
|
39
|
+
{tag.title}
|
|
40
|
+
</Tag>
|
|
41
|
+
</Tooltip>
|
|
42
|
+
);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
export default PlanTag;
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
import { createStyles } from 'antd-style';
|
|
4
4
|
import { memo } from 'react';
|
|
5
5
|
import { useTranslation } from 'react-i18next';
|
|
6
|
-
import { Flexbox } from 'react-layout-kit';
|
|
6
|
+
import { Flexbox, FlexboxProps } from 'react-layout-kit';
|
|
7
7
|
|
|
8
|
-
import
|
|
8
|
+
import PlanTag from '@/features/User/PlanTag';
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
import UserAvatar, { type UserAvatarProps } from './UserAvatar';
|
|
11
|
+
|
|
12
|
+
const DEFAULT_USERNAME = 'LobeChat';
|
|
11
13
|
|
|
12
14
|
const useStyles = createStyles(({ css, token }) => ({
|
|
13
15
|
nickname: css`
|
|
@@ -21,19 +23,34 @@ const useStyles = createStyles(({ css, token }) => ({
|
|
|
21
23
|
`,
|
|
22
24
|
}));
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
export interface UserInfoProps extends FlexboxProps {
|
|
27
|
+
avatarProps?: Partial<UserAvatarProps>;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const UserInfo = memo<UserInfoProps>(({ avatarProps, ...rest }) => {
|
|
25
31
|
const { t } = useTranslation('common');
|
|
26
32
|
const { styles, theme } = useStyles();
|
|
27
33
|
|
|
28
34
|
const DEFAULT_NICKNAME = t('userPanel.defaultNickname');
|
|
29
35
|
|
|
30
36
|
return (
|
|
31
|
-
<Flexbox
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
<Flexbox
|
|
38
|
+
align={'center'}
|
|
39
|
+
gap={12}
|
|
40
|
+
horizontal
|
|
41
|
+
justify={'space-between'}
|
|
42
|
+
paddingBlock={12}
|
|
43
|
+
paddingInline={12}
|
|
44
|
+
{...rest}
|
|
45
|
+
>
|
|
46
|
+
<Flexbox align={'center'} gap={12} horizontal>
|
|
47
|
+
<UserAvatar background={theme.colorFill} size={48} {...avatarProps} />
|
|
48
|
+
<Flexbox flex={1} gap={6}>
|
|
49
|
+
<div className={styles.nickname}>{DEFAULT_NICKNAME}</div>
|
|
50
|
+
<div className={styles.username}>{DEFAULT_USERNAME}</div>
|
|
51
|
+
</Flexbox>
|
|
36
52
|
</Flexbox>
|
|
53
|
+
<PlanTag />
|
|
37
54
|
</Flexbox>
|
|
38
55
|
);
|
|
39
56
|
});
|