@lobehub/chat 1.49.2 → 1.49.3
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 +25 -0
- package/changelog/v1.json +9 -0
- package/package.json +1 -1
- package/src/app/(main)/discover/(list)/(home)/features/AssistantList.tsx +13 -7
- package/src/app/(main)/discover/(list)/(home)/features/ModelList.tsx +1 -4
- package/src/app/(main)/discover/(list)/(home)/features/PluginList.tsx +7 -4
- package/src/app/(main)/discover/(list)/assistants/features/Card.tsx +74 -55
- package/src/app/(main)/discover/(list)/assistants/features/List.tsx +20 -10
- package/src/app/(main)/discover/(list)/models/features/Card.tsx +34 -32
- package/src/app/(main)/discover/(list)/models/features/List.tsx +12 -7
- package/src/app/(main)/discover/(list)/plugins/features/Card.tsx +52 -43
- package/src/app/(main)/discover/(list)/plugins/features/List.tsx +20 -10
- package/src/app/(main)/settings/_layout/Mobile/Header.tsx +9 -6
package/CHANGELOG.md
CHANGED
@@ -2,6 +2,31 @@
|
|
2
2
|
|
3
3
|
# Changelog
|
4
4
|
|
5
|
+
### [Version 1.49.3](https://github.com/lobehub/lobe-chat/compare/v1.49.2...v1.49.3)
|
6
|
+
|
7
|
+
<sup>Released on **2025-01-27**</sup>
|
8
|
+
|
9
|
+
#### 🐛 Bug Fixes
|
10
|
+
|
11
|
+
- **misc**: Fix discover ssr hydration error.
|
12
|
+
|
13
|
+
<br/>
|
14
|
+
|
15
|
+
<details>
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
17
|
+
|
18
|
+
#### What's fixed
|
19
|
+
|
20
|
+
- **misc**: Fix discover ssr hydration error, closes [#5605](https://github.com/lobehub/lobe-chat/issues/5605) ([e3702a6](https://github.com/lobehub/lobe-chat/commit/e3702a6))
|
21
|
+
|
22
|
+
</details>
|
23
|
+
|
24
|
+
<div align="right">
|
25
|
+
|
26
|
+
[](#readme-top)
|
27
|
+
|
28
|
+
</div>
|
29
|
+
|
5
30
|
### [Version 1.49.2](https://github.com/lobehub/lobe-chat/compare/v1.49.1...v1.49.2)
|
6
31
|
|
7
32
|
<sup>Released on **2025-01-27**</sup>
|
package/changelog/v1.json
CHANGED
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@lobehub/chat",
|
3
|
-
"version": "1.49.
|
3
|
+
"version": "1.49.3",
|
4
4
|
"description": "Lobe Chat - an open-source, high-performance chatbot framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
5
5
|
"keywords": [
|
6
6
|
"framework",
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import { Grid } from '@lobehub/ui';
|
2
|
-
import Link from 'next/link';
|
3
2
|
import { memo } from 'react';
|
4
3
|
import urlJoin from 'url-join';
|
5
4
|
|
@@ -11,14 +10,21 @@ const AssistantList = memo<{ data: DiscoverAssistantItem[] }>(({ data }) => {
|
|
11
10
|
return (
|
12
11
|
<Grid maxItemWidth={280} rows={4}>
|
13
12
|
{data.slice(0, 8).map((item) => (
|
14
|
-
<
|
15
|
-
|
16
|
-
|
13
|
+
<Card
|
14
|
+
href={urlJoin('/discover/assistant/', item.identifier)}
|
15
|
+
key={item.identifier}
|
16
|
+
showCategory
|
17
|
+
{...item}
|
18
|
+
/>
|
17
19
|
))}
|
18
20
|
{data.slice(8, 16).map((item) => (
|
19
|
-
<
|
20
|
-
|
21
|
-
|
21
|
+
<Card
|
22
|
+
href={urlJoin('/discover/assistant/', item.identifier)}
|
23
|
+
key={item.identifier}
|
24
|
+
showCategory
|
25
|
+
variant={'compact'}
|
26
|
+
{...item}
|
27
|
+
/>
|
22
28
|
))}
|
23
29
|
</Grid>
|
24
30
|
);
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import { Grid } from '@lobehub/ui';
|
2
|
-
import Link from 'next/link';
|
3
2
|
import { memo } from 'react';
|
4
3
|
import urlJoin from 'url-join';
|
5
4
|
|
@@ -11,9 +10,7 @@ const ModelList = memo<{ data: DiscoverModelItem[] }>(({ data }) => {
|
|
11
10
|
return (
|
12
11
|
<Grid maxItemWidth={280} rows={4}>
|
13
12
|
{data.map((item) => (
|
14
|
-
<
|
15
|
-
<Card {...item} />
|
16
|
-
</Link>
|
13
|
+
<Card {...item} href={urlJoin('/discover/model/', item.identifier)} key={item.identifier} />
|
17
14
|
))}
|
18
15
|
</Grid>
|
19
16
|
);
|
@@ -1,5 +1,4 @@
|
|
1
1
|
import { Grid } from '@lobehub/ui';
|
2
|
-
import Link from 'next/link';
|
3
2
|
import { memo } from 'react';
|
4
3
|
import urlJoin from 'url-join';
|
5
4
|
|
@@ -11,9 +10,13 @@ const PluginList = memo<{ data: DiscoverPlugintem[] }>(({ data }) => {
|
|
11
10
|
return (
|
12
11
|
<Grid maxItemWidth={280} rows={4}>
|
13
12
|
{data.map((item) => (
|
14
|
-
<
|
15
|
-
|
16
|
-
|
13
|
+
<Card
|
14
|
+
showCategory
|
15
|
+
variant={'compact'}
|
16
|
+
{...item}
|
17
|
+
href={urlJoin('/discover/plugin/', item.identifier)}
|
18
|
+
key={item.identifier}
|
19
|
+
/>
|
17
20
|
))}
|
18
21
|
</Grid>
|
19
22
|
);
|
@@ -3,6 +3,7 @@ import { Skeleton, Typography } from 'antd';
|
|
3
3
|
import { createStyles } from 'antd-style';
|
4
4
|
import { startCase } from 'lodash-es';
|
5
5
|
import dynamic from 'next/dynamic';
|
6
|
+
import { useRouter } from 'next/navigation';
|
6
7
|
import qs from 'query-string';
|
7
8
|
import { CSSProperties, memo } from 'react';
|
8
9
|
import { Center, Flexbox } from 'react-layout-kit';
|
@@ -26,8 +27,6 @@ const useStyles = createStyles(({ css, token, isDarkMode }) => ({
|
|
26
27
|
opacity: ${isDarkMode ? 0.9 : 0.4};
|
27
28
|
`,
|
28
29
|
container: css`
|
29
|
-
cursor: pointer;
|
30
|
-
|
31
30
|
position: relative;
|
32
31
|
|
33
32
|
overflow: hidden;
|
@@ -64,18 +63,19 @@ const useStyles = createStyles(({ css, token, isDarkMode }) => ({
|
|
64
63
|
export interface AssistantCardProps
|
65
64
|
extends Omit<DiscoverAssistantItem, 'suggestions' | 'socialData' | 'config'> {
|
66
65
|
className?: string;
|
66
|
+
href: string;
|
67
67
|
showCategory?: boolean;
|
68
68
|
style?: CSSProperties;
|
69
69
|
variant?: 'default' | 'compact';
|
70
70
|
}
|
71
71
|
|
72
72
|
const AssistantCard = memo<AssistantCardProps>(
|
73
|
-
({ showCategory, className, meta, createdAt, author, variant, style }) => {
|
73
|
+
({ showCategory, className, meta, createdAt, author, variant, style, href }) => {
|
74
74
|
const { avatar, title, description, tags = [], category } = meta;
|
75
75
|
const { cx, styles, theme } = useStyles();
|
76
76
|
const categoryItem = useCategoryItem(category, 12);
|
77
77
|
const isCompact = variant === 'compact';
|
78
|
-
|
78
|
+
const router = useRouter();
|
79
79
|
const user = (
|
80
80
|
<Flexbox
|
81
81
|
align={'center'}
|
@@ -90,60 +90,79 @@ const AssistantCard = memo<AssistantCardProps>(
|
|
90
90
|
|
91
91
|
return (
|
92
92
|
<Flexbox className={cx(styles.container, className)} gap={24} style={style}>
|
93
|
-
{!isCompact &&
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
horizontal
|
99
|
-
justify={'space-between'}
|
100
|
-
style={{ position: 'relative' }}
|
101
|
-
width={'100%'}
|
93
|
+
{!isCompact && (
|
94
|
+
<div
|
95
|
+
onClick={() => {
|
96
|
+
router.push(href);
|
97
|
+
}}
|
102
98
|
>
|
103
|
-
<
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
{
|
114
|
-
|
115
|
-
|
116
|
-
</Flexbox>
|
117
|
-
{isCompact ? (
|
118
|
-
<Avatar avatar={avatar} size={40} style={{ display: 'block' }} title={title} />
|
119
|
-
) : (
|
120
|
-
<Center
|
121
|
-
flex={'none'}
|
122
|
-
height={64}
|
123
|
-
style={{
|
124
|
-
background: theme.colorBgContainer,
|
125
|
-
borderRadius: '50%',
|
126
|
-
marginTop: -6,
|
127
|
-
overflow: 'hidden',
|
128
|
-
zIndex: 2,
|
129
|
-
}}
|
130
|
-
width={64}
|
99
|
+
<CardBanner avatar={avatar} />
|
100
|
+
</div>
|
101
|
+
)}
|
102
|
+
<Flexbox gap={12} padding={16}>
|
103
|
+
<Link href={href}>
|
104
|
+
<Flexbox gap={12}>
|
105
|
+
<Flexbox
|
106
|
+
align={isCompact ? 'flex-start' : 'flex-end'}
|
107
|
+
gap={16}
|
108
|
+
horizontal
|
109
|
+
justify={'space-between'}
|
110
|
+
style={{ position: 'relative' }}
|
111
|
+
width={'100%'}
|
131
112
|
>
|
132
|
-
<
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
113
|
+
<Flexbox
|
114
|
+
gap={8}
|
115
|
+
style={{
|
116
|
+
overflow: 'hidden',
|
117
|
+
paddingTop: isCompact ? 4 : 0,
|
118
|
+
position: 'relative',
|
119
|
+
}}
|
120
|
+
>
|
121
|
+
<Title
|
122
|
+
className={styles.title}
|
123
|
+
ellipsis={{ rows: 1, tooltip: title }}
|
124
|
+
level={3}
|
125
|
+
style={{ fontSize: isCompact ? 16 : 18 }}
|
126
|
+
>
|
127
|
+
{title}
|
128
|
+
</Title>
|
129
|
+
{isCompact && user}
|
130
|
+
</Flexbox>
|
131
|
+
|
132
|
+
{isCompact ? (
|
133
|
+
<Avatar avatar={avatar} size={40} style={{ display: 'block' }} title={title} />
|
134
|
+
) : (
|
135
|
+
<Center
|
136
|
+
flex={'none'}
|
137
|
+
height={64}
|
138
|
+
style={{
|
139
|
+
background: theme.colorBgContainer,
|
140
|
+
borderRadius: '50%',
|
141
|
+
marginTop: -6,
|
142
|
+
overflow: 'hidden',
|
143
|
+
zIndex: 2,
|
144
|
+
}}
|
145
|
+
width={64}
|
146
|
+
>
|
147
|
+
<Avatar avatar={avatar} size={56} style={{ display: 'block' }} title={title} />
|
148
|
+
</Center>
|
149
|
+
)}
|
150
|
+
</Flexbox>
|
151
|
+
|
152
|
+
{!isCompact && (
|
153
|
+
<Flexbox gap={8} horizontal style={{ fontSize: 12 }}>
|
154
|
+
{user}
|
155
|
+
<time className={styles.time} dateTime={new Date(createdAt).toISOString()}>
|
156
|
+
{createdAt}
|
157
|
+
</time>
|
158
|
+
</Flexbox>
|
159
|
+
)}
|
160
|
+
<Paragraph className={styles.desc} ellipsis={{ rows: 2 }}>
|
161
|
+
{description}
|
162
|
+
</Paragraph>
|
142
163
|
</Flexbox>
|
143
|
-
|
144
|
-
|
145
|
-
{description}
|
146
|
-
</Paragraph>
|
164
|
+
</Link>
|
165
|
+
|
147
166
|
<Flexbox gap={6} horizontal style={{ flexWrap: 'wrap' }}>
|
148
167
|
{showCategory && categoryItem ? (
|
149
168
|
<Link href={urlJoin('/discover/assistants', categoryItem.key)}>
|
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
import { Grid } from '@lobehub/ui';
|
4
4
|
import { Empty } from 'antd';
|
5
|
-
import Link from 'next/link';
|
6
5
|
import { memo, useMemo } from 'react';
|
7
6
|
import { useTranslation } from 'react-i18next';
|
8
7
|
import urlJoin from 'url-join';
|
@@ -42,9 +41,13 @@ const List = memo<ListProps>(({ category, mobile, searchKeywords, items = [] })
|
|
42
41
|
data={all}
|
43
42
|
initialItemCount={24}
|
44
43
|
itemContent={(_, item) => (
|
45
|
-
<
|
46
|
-
|
47
|
-
|
44
|
+
<Card
|
45
|
+
href={urlJoin('/discover/assistant/', item.identifier)}
|
46
|
+
key={item.identifier}
|
47
|
+
showCategory
|
48
|
+
variant={'compact'}
|
49
|
+
{...item}
|
50
|
+
/>
|
48
51
|
)}
|
49
52
|
style={{
|
50
53
|
minHeight: '75vh',
|
@@ -59,9 +62,12 @@ const List = memo<ListProps>(({ category, mobile, searchKeywords, items = [] })
|
|
59
62
|
<Title>{t('assistants.recentSubmits')}</Title>
|
60
63
|
<Grid maxItemWidth={280} rows={4}>
|
61
64
|
{recent.map((item) => (
|
62
|
-
<
|
63
|
-
|
64
|
-
|
65
|
+
<Card
|
66
|
+
href={urlJoin('/discover/assistant/', item.identifier)}
|
67
|
+
key={item.identifier}
|
68
|
+
showCategory={!category}
|
69
|
+
{...item}
|
70
|
+
/>
|
65
71
|
))}
|
66
72
|
</Grid>
|
67
73
|
{last && last?.length > 0 && (
|
@@ -71,9 +77,13 @@ const List = memo<ListProps>(({ category, mobile, searchKeywords, items = [] })
|
|
71
77
|
data={last}
|
72
78
|
initialItemCount={12}
|
73
79
|
itemContent={(_, item) => (
|
74
|
-
<
|
75
|
-
|
76
|
-
|
80
|
+
<Card
|
81
|
+
href={urlJoin('/discover/assistant/', item.identifier)}
|
82
|
+
key={item.identifier}
|
83
|
+
showCategory={!category}
|
84
|
+
variant={'compact'}
|
85
|
+
{...item}
|
86
|
+
/>
|
77
87
|
)}
|
78
88
|
style={{
|
79
89
|
minHeight: '75vh',
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import { ModelIcon } from '@lobehub/icons';
|
2
2
|
import { Typography } from 'antd';
|
3
3
|
import { createStyles } from 'antd-style';
|
4
|
+
import Link from 'next/link';
|
4
5
|
import { CSSProperties, memo } from 'react';
|
5
6
|
import { useTranslation } from 'react-i18next';
|
6
7
|
import { Flexbox } from 'react-layout-kit';
|
@@ -16,8 +17,6 @@ const useStyles = createStyles(({ css, token, isDarkMode }) => ({
|
|
16
17
|
opacity: ${isDarkMode ? 0.9 : 0.4};
|
17
18
|
`,
|
18
19
|
container: css`
|
19
|
-
cursor: pointer;
|
20
|
-
|
21
20
|
position: relative;
|
22
21
|
|
23
22
|
overflow: hidden;
|
@@ -69,53 +68,56 @@ const useStyles = createStyles(({ css, token, isDarkMode }) => ({
|
|
69
68
|
|
70
69
|
export interface ModelCardProps extends DiscoverModelItem {
|
71
70
|
className?: string;
|
71
|
+
href: string;
|
72
72
|
showCategory?: boolean;
|
73
73
|
style?: CSSProperties;
|
74
74
|
}
|
75
75
|
|
76
|
-
const ModelCard = memo<ModelCardProps>(({ className, meta, identifier, style }) => {
|
76
|
+
const ModelCard = memo<ModelCardProps>(({ className, meta, identifier, style, href }) => {
|
77
77
|
const { description, title, functionCall, vision, contextWindowTokens } = meta;
|
78
78
|
const { t } = useTranslation('models');
|
79
79
|
const { cx, styles } = useStyles();
|
80
80
|
|
81
81
|
return (
|
82
|
-
<
|
83
|
-
<Flexbox
|
84
|
-
gap={12}
|
85
|
-
padding={16}
|
86
|
-
style={{ overflow: 'hidden', position: 'relative' }}
|
87
|
-
width={'100%'}
|
88
|
-
>
|
82
|
+
<Link href={href}>
|
83
|
+
<Flexbox className={cx(styles.container, className)} gap={24} key={identifier} style={style}>
|
89
84
|
<Flexbox
|
90
|
-
align={'center'}
|
91
85
|
gap={12}
|
92
|
-
|
86
|
+
padding={16}
|
93
87
|
style={{ overflow: 'hidden', position: 'relative' }}
|
94
88
|
width={'100%'}
|
95
89
|
>
|
96
|
-
<
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
90
|
+
<Flexbox
|
91
|
+
align={'center'}
|
92
|
+
gap={12}
|
93
|
+
horizontal
|
94
|
+
style={{ overflow: 'hidden', position: 'relative' }}
|
95
|
+
width={'100%'}
|
96
|
+
>
|
97
|
+
<ModelIcon model={identifier} size={32} type={'avatar'} />
|
98
|
+
<Flexbox style={{ overflow: 'hidden', position: 'relative' }}>
|
99
|
+
<Title className={styles.title} ellipsis={{ rows: 1, tooltip: title }} level={3}>
|
100
|
+
{title}
|
101
|
+
</Title>
|
102
|
+
<Paragraph className={styles.id} ellipsis={{ rows: 1 }}>
|
103
|
+
{identifier}
|
104
|
+
</Paragraph>
|
105
|
+
</Flexbox>
|
104
106
|
</Flexbox>
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
)}
|
107
|
+
{description && (
|
108
|
+
<Paragraph className={styles.desc} ellipsis={{ rows: 2 }}>
|
109
|
+
{t(`${identifier}.description`)}
|
110
|
+
</Paragraph>
|
111
|
+
)}
|
111
112
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
113
|
+
<ModelFeatureTags
|
114
|
+
functionCall={functionCall}
|
115
|
+
tokens={contextWindowTokens}
|
116
|
+
vision={vision}
|
117
|
+
/>
|
118
|
+
</Flexbox>
|
117
119
|
</Flexbox>
|
118
|
-
</
|
120
|
+
</Link>
|
119
121
|
);
|
120
122
|
});
|
121
123
|
|
@@ -1,7 +1,6 @@
|
|
1
1
|
'use client';
|
2
2
|
|
3
3
|
import { Empty } from 'antd';
|
4
|
-
import Link from 'next/link';
|
5
4
|
import { memo } from 'react';
|
6
5
|
import { useTranslation } from 'react-i18next';
|
7
6
|
import urlJoin from 'url-join';
|
@@ -32,9 +31,12 @@ const List = memo<ListProps>(({ category, searchKeywords, items = [] }) => {
|
|
32
31
|
data={items}
|
33
32
|
initialItemCount={24}
|
34
33
|
itemContent={(_, item) => (
|
35
|
-
<
|
36
|
-
|
37
|
-
|
34
|
+
<Card
|
35
|
+
href={urlJoin('/discover/model', item.identifier)}
|
36
|
+
key={item.identifier}
|
37
|
+
showCategory
|
38
|
+
{...item}
|
39
|
+
/>
|
38
40
|
)}
|
39
41
|
style={{
|
40
42
|
minHeight: '75vh',
|
@@ -51,9 +53,12 @@ const List = memo<ListProps>(({ category, searchKeywords, items = [] }) => {
|
|
51
53
|
data={items}
|
52
54
|
initialItemCount={24}
|
53
55
|
itemContent={(_, item) => (
|
54
|
-
<
|
55
|
-
|
56
|
-
|
56
|
+
<Card
|
57
|
+
href={urlJoin('/discover/model/', item.identifier)}
|
58
|
+
key={item.identifier}
|
59
|
+
showCategory={!category}
|
60
|
+
{...item}
|
61
|
+
/>
|
57
62
|
)}
|
58
63
|
style={{
|
59
64
|
minHeight: '75vh',
|
@@ -25,8 +25,6 @@ const useStyles = createStyles(({ css, token, isDarkMode }) => ({
|
|
25
25
|
opacity: ${isDarkMode ? 0.9 : 0.4};
|
26
26
|
`,
|
27
27
|
container: css`
|
28
|
-
cursor: pointer;
|
29
|
-
|
30
28
|
position: relative;
|
31
29
|
|
32
30
|
overflow: hidden;
|
@@ -66,13 +64,14 @@ const useStyles = createStyles(({ css, token, isDarkMode }) => ({
|
|
66
64
|
interface PluginCardProps
|
67
65
|
extends Omit<DiscoverPlugintem, 'manifest' | 'suggestions' | 'socialData'> {
|
68
66
|
className?: string;
|
67
|
+
href: string;
|
69
68
|
showCategory?: boolean;
|
70
69
|
style?: CSSProperties;
|
71
70
|
variant?: 'default' | 'compact';
|
72
71
|
}
|
73
72
|
|
74
73
|
const PluginCard = memo<PluginCardProps>(
|
75
|
-
({ className, showCategory, meta, createdAt, author, variant, style }) => {
|
74
|
+
({ className, showCategory, meta, createdAt, author, variant, style, href }) => {
|
76
75
|
const { avatar, title, description, tags = [], category } = meta;
|
77
76
|
const categoryItem = useCategoryItem(category, 12);
|
78
77
|
const { cx, styles, theme } = useStyles();
|
@@ -81,47 +80,57 @@ const PluginCard = memo<PluginCardProps>(
|
|
81
80
|
return (
|
82
81
|
<Flexbox className={cx(styles.container, className)} gap={24} style={style}>
|
83
82
|
{!isCompact && <CardBanner avatar={avatar} />}
|
84
|
-
<Flexbox
|
85
|
-
<
|
86
|
-
<
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
flex={'none'}
|
94
|
-
height={64}
|
95
|
-
style={{
|
96
|
-
background: theme.colorBgContainer,
|
97
|
-
borderRadius: '50%',
|
98
|
-
marginTop: -6,
|
99
|
-
overflow: 'hidden',
|
100
|
-
zIndex: 2,
|
101
|
-
}}
|
102
|
-
width={64}
|
83
|
+
<Flexbox gap={12} padding={16}>
|
84
|
+
<Link href={href}>
|
85
|
+
<Flexbox gap={12}>
|
86
|
+
<Flexbox
|
87
|
+
align={'flex-end'}
|
88
|
+
gap={16}
|
89
|
+
horizontal
|
90
|
+
justify={'space-between'}
|
91
|
+
width={'100%'}
|
103
92
|
>
|
104
|
-
<
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
style={{ display: 'block' }}
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
93
|
+
<Title className={styles.title} ellipsis={{ rows: 1, tooltip: title }} level={3}>
|
94
|
+
{title}
|
95
|
+
</Title>
|
96
|
+
{isCompact ? (
|
97
|
+
<Avatar avatar={avatar} size={40} style={{ display: 'block' }} title={title} />
|
98
|
+
) : (
|
99
|
+
<Center
|
100
|
+
flex={'none'}
|
101
|
+
height={64}
|
102
|
+
style={{
|
103
|
+
background: theme.colorBgContainer,
|
104
|
+
borderRadius: '50%',
|
105
|
+
marginTop: -6,
|
106
|
+
overflow: 'hidden',
|
107
|
+
zIndex: 2,
|
108
|
+
}}
|
109
|
+
width={64}
|
110
|
+
>
|
111
|
+
<Avatar
|
112
|
+
alt={title}
|
113
|
+
avatar={avatar}
|
114
|
+
size={56}
|
115
|
+
style={{ display: 'block' }}
|
116
|
+
title={title}
|
117
|
+
/>
|
118
|
+
</Center>
|
119
|
+
)}
|
120
|
+
</Flexbox>
|
121
|
+
<Flexbox gap={8} horizontal style={{ fontSize: 12 }}>
|
122
|
+
<div style={{ color: theme.colorTextSecondary }}>@{author}</div>
|
123
|
+
{!isCompact && (
|
124
|
+
<time className={styles.time} dateTime={new Date(createdAt).toISOString()}>
|
125
|
+
{createdAt}
|
126
|
+
</time>
|
127
|
+
)}
|
128
|
+
</Flexbox>
|
129
|
+
<Paragraph className={styles.desc} ellipsis={{ rows: 2 }}>
|
130
|
+
{description}
|
131
|
+
</Paragraph>
|
132
|
+
</Flexbox>
|
133
|
+
</Link>
|
125
134
|
<Flexbox gap={6} horizontal style={{ flexWrap: 'wrap' }}>
|
126
135
|
{showCategory && categoryItem ? (
|
127
136
|
<Link href={urlJoin('/discover/plugins', categoryItem.key)}>
|
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
import { Grid } from '@lobehub/ui';
|
4
4
|
import { Empty } from 'antd';
|
5
|
-
import Link from 'next/link';
|
6
5
|
import { memo, useMemo } from 'react';
|
7
6
|
import { useTranslation } from 'react-i18next';
|
8
7
|
import urlJoin from 'url-join';
|
@@ -41,9 +40,13 @@ const List = memo<ListProps>(({ category, mobile, searchKeywords, items = [] })
|
|
41
40
|
data={all}
|
42
41
|
initialItemCount={24}
|
43
42
|
itemContent={(_, item) => (
|
44
|
-
<
|
45
|
-
|
46
|
-
|
43
|
+
<Card
|
44
|
+
showCategory
|
45
|
+
variant={'compact'}
|
46
|
+
{...item}
|
47
|
+
href={urlJoin('/discover/plugin/', item.identifier)}
|
48
|
+
key={item.identifier}
|
49
|
+
/>
|
47
50
|
)}
|
48
51
|
style={{
|
49
52
|
minHeight: '75vh',
|
@@ -58,9 +61,12 @@ const List = memo<ListProps>(({ category, mobile, searchKeywords, items = [] })
|
|
58
61
|
<Title>{t('plugins.recentSubmits')}</Title>
|
59
62
|
<Grid maxItemWidth={280} rows={4}>
|
60
63
|
{recent.map((item) => (
|
61
|
-
<
|
62
|
-
|
63
|
-
|
64
|
+
<Card
|
65
|
+
showCategory={!category}
|
66
|
+
{...item}
|
67
|
+
href={urlJoin('/discover/plugin/', item.identifier)}
|
68
|
+
key={item.identifier}
|
69
|
+
/>
|
64
70
|
))}
|
65
71
|
</Grid>
|
66
72
|
{last && last?.length > 0 && (
|
@@ -70,9 +76,13 @@ const List = memo<ListProps>(({ category, mobile, searchKeywords, items = [] })
|
|
70
76
|
data={last}
|
71
77
|
initialItemCount={12}
|
72
78
|
itemContent={(_, item) => (
|
73
|
-
<
|
74
|
-
|
75
|
-
|
79
|
+
<Card
|
80
|
+
showCategory={!category}
|
81
|
+
variant={'compact'}
|
82
|
+
{...item}
|
83
|
+
href={urlJoin('/discover/plugin/', item.identifier)}
|
84
|
+
key={item.identifier}
|
85
|
+
/>
|
76
86
|
)}
|
77
87
|
style={{
|
78
88
|
minHeight: '75vh',
|
@@ -2,13 +2,15 @@
|
|
2
2
|
|
3
3
|
import { MobileNavBar, MobileNavBarTitle } from '@lobehub/ui';
|
4
4
|
import { Tag } from 'antd';
|
5
|
-
import { useRouter, useSearchParams } from 'next/navigation';
|
6
5
|
import { memo } from 'react';
|
7
6
|
import { useTranslation } from 'react-i18next';
|
8
7
|
import { Flexbox } from 'react-layout-kit';
|
9
8
|
|
10
9
|
import { useActiveSettingsKey } from '@/hooks/useActiveTabKey';
|
10
|
+
import { useQueryRoute } from '@/hooks/useQueryRoute';
|
11
|
+
import { useShowMobileWorkspace } from '@/hooks/useShowMobileWorkspace';
|
11
12
|
import { SettingsTabs } from '@/store/global/initialState';
|
13
|
+
import { useSessionStore } from '@/store/session';
|
12
14
|
import { useUserStore } from '@/store/user';
|
13
15
|
import { authSelectors } from '@/store/user/selectors';
|
14
16
|
import { mobileHeaderSticky } from '@/styles/mobileHeader';
|
@@ -16,14 +18,15 @@ import { mobileHeaderSticky } from '@/styles/mobileHeader';
|
|
16
18
|
const Header = memo(() => {
|
17
19
|
const { t } = useTranslation('setting');
|
18
20
|
|
19
|
-
const router =
|
20
|
-
const
|
21
|
+
const router = useQueryRoute();
|
22
|
+
const showMobileWorkspace = useShowMobileWorkspace();
|
21
23
|
const activeSettingsKey = useActiveSettingsKey();
|
22
|
-
|
24
|
+
const isSessionActive = useSessionStore((s) => !!s.activeId);
|
23
25
|
const enableAuth = useUserStore(authSelectors.enabledAuth);
|
26
|
+
|
24
27
|
const handleBackClick = () => {
|
25
|
-
if (
|
26
|
-
router.push(
|
28
|
+
if (isSessionActive && showMobileWorkspace) {
|
29
|
+
router.push('/chat');
|
27
30
|
} else {
|
28
31
|
router.push(enableAuth ? '/me/settings' : '/me');
|
29
32
|
}
|