@lobehub/lobehub 2.0.0-next.210 → 2.0.0-next.211
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
## [Version 2.0.0-next.211](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.210...v2.0.0-next.211)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2026-01-05**</sup>
|
|
8
|
+
|
|
9
|
+
#### 🐛 Bug Fixes
|
|
10
|
+
|
|
11
|
+
- **misc**: Add lost like button in discover detail page.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### What's fixed
|
|
19
|
+
|
|
20
|
+
- **misc**: Add lost like button in discover detail page, closes [#11182](https://github.com/lobehub/lobe-chat/issues/11182) ([41215d4](https://github.com/lobehub/lobe-chat/commit/41215d4))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
5
30
|
## [Version 2.0.0-next.210](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.209...v2.0.0-next.210)
|
|
6
31
|
|
|
7
32
|
<sup>Released on **2026-01-04**</sup>
|
package/changelog/v1.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/lobehub",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.211",
|
|
4
4
|
"description": "LobeHub - an open-source,comprehensive AI Agent 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",
|
|
@@ -158,7 +158,7 @@ export const GET = async (req: NextRequest, context: RouteContext) => {
|
|
|
158
158
|
// Follow queries
|
|
159
159
|
case 'follow-status': {
|
|
160
160
|
const targetUserId = Number(segments[1]);
|
|
161
|
-
if (!accessToken) {
|
|
161
|
+
if (!accessToken && !trustedClientToken) {
|
|
162
162
|
return NextResponse.json({ isFollowing: false, isMutual: false });
|
|
163
163
|
}
|
|
164
164
|
const result = await market.follows.checkFollowStatus(targetUserId);
|
|
@@ -193,7 +193,7 @@ export const GET = async (req: NextRequest, context: RouteContext) => {
|
|
|
193
193
|
case 'favorite-status': {
|
|
194
194
|
const targetType = segments[1] as 'agent' | 'plugin';
|
|
195
195
|
const targetIdOrIdentifier = segments[2];
|
|
196
|
-
if (!accessToken) {
|
|
196
|
+
if (!accessToken && !trustedClientToken) {
|
|
197
197
|
return NextResponse.json({ isFavorited: false });
|
|
198
198
|
}
|
|
199
199
|
// SDK accepts both number (targetId) and string (identifier)
|
|
@@ -236,7 +236,7 @@ export const GET = async (req: NextRequest, context: RouteContext) => {
|
|
|
236
236
|
case 'like-status': {
|
|
237
237
|
const targetType = segments[1] as 'agent' | 'plugin';
|
|
238
238
|
const targetIdOrIdentifier = segments[2];
|
|
239
|
-
if (!accessToken) {
|
|
239
|
+
if (!accessToken && !trustedClientToken) {
|
|
240
240
|
return NextResponse.json({ isLiked: false });
|
|
241
241
|
}
|
|
242
242
|
const isNumeric = /^\d+$/.test(targetIdOrIdentifier);
|
|
@@ -13,7 +13,14 @@ import {
|
|
|
13
13
|
} from '@lobehub/ui';
|
|
14
14
|
import { App } from 'antd';
|
|
15
15
|
import { createStaticStyles, cssVar, useResponsive } from 'antd-style';
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
BookTextIcon,
|
|
18
|
+
BookmarkCheckIcon,
|
|
19
|
+
BookmarkIcon,
|
|
20
|
+
CoinsIcon,
|
|
21
|
+
DotIcon,
|
|
22
|
+
HeartIcon,
|
|
23
|
+
} from 'lucide-react';
|
|
17
24
|
import qs from 'query-string';
|
|
18
25
|
import { memo, useState } from 'react';
|
|
19
26
|
import { useTranslation } from 'react-i18next';
|
|
@@ -54,8 +61,7 @@ const Header = memo<{ mobile?: boolean }>(({ mobile: isMobile }) => {
|
|
|
54
61
|
const { mobile = isMobile } = useResponsive();
|
|
55
62
|
const { isAuthenticated, signIn, session } = useMarketAuth();
|
|
56
63
|
const [favoriteLoading, setFavoriteLoading] = useState(false);
|
|
57
|
-
|
|
58
|
-
// const [likeLoading, setLikeLoading] = useState(false);
|
|
64
|
+
const [likeLoading, setLikeLoading] = useState(false);
|
|
59
65
|
|
|
60
66
|
// Set access token for social service
|
|
61
67
|
if (session?.accessToken) {
|
|
@@ -71,13 +77,13 @@ const Header = memo<{ mobile?: boolean }>(({ mobile: isMobile }) => {
|
|
|
71
77
|
|
|
72
78
|
const isFavorited = favoriteStatus?.isFavorited ?? false;
|
|
73
79
|
|
|
74
|
-
//
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
// Fetch like status
|
|
81
|
+
const { data: likeStatus, mutate: mutateLike } = useSWR(
|
|
82
|
+
identifier && isAuthenticated ? ['like-status', 'agent', identifier] : null,
|
|
83
|
+
() => socialService.checkLikeStatus('agent', identifier!),
|
|
84
|
+
{ revalidateOnFocus: false },
|
|
85
|
+
);
|
|
86
|
+
const isLiked = likeStatus?.isLiked ?? false;
|
|
81
87
|
|
|
82
88
|
const handleFavoriteClick = async () => {
|
|
83
89
|
if (!isAuthenticated) {
|
|
@@ -105,30 +111,29 @@ const Header = memo<{ mobile?: boolean }>(({ mobile: isMobile }) => {
|
|
|
105
111
|
}
|
|
106
112
|
};
|
|
107
113
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
// };
|
|
114
|
+
const handleLikeClick = async () => {
|
|
115
|
+
if (!isAuthenticated) {
|
|
116
|
+
await signIn();
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (!identifier) return;
|
|
120
|
+
setLikeLoading(true);
|
|
121
|
+
try {
|
|
122
|
+
if (isLiked) {
|
|
123
|
+
await socialService.unlike('agent', identifier);
|
|
124
|
+
message.success(t('assistant.unlikeSuccess'));
|
|
125
|
+
} else {
|
|
126
|
+
await socialService.like('agent', identifier);
|
|
127
|
+
message.success(t('assistant.likeSuccess'));
|
|
128
|
+
}
|
|
129
|
+
await mutateLike();
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.error('Like action failed:', error);
|
|
132
|
+
message.error(t('assistant.likeFailed'));
|
|
133
|
+
} finally {
|
|
134
|
+
setLikeLoading(false);
|
|
135
|
+
}
|
|
136
|
+
};
|
|
132
137
|
|
|
133
138
|
const categories = useCategory();
|
|
134
139
|
const cate = categories.find((c) => c.key === category);
|
|
@@ -186,6 +191,14 @@ const Header = memo<{ mobile?: boolean }>(({ mobile: isMobile }) => {
|
|
|
186
191
|
{title}
|
|
187
192
|
</Text>
|
|
188
193
|
</Flexbox>
|
|
194
|
+
<Tooltip title={isLiked ? t('assistant.unlike') : t('assistant.like')}>
|
|
195
|
+
<ActionIcon
|
|
196
|
+
icon={HeartIcon}
|
|
197
|
+
loading={likeLoading}
|
|
198
|
+
onClick={handleLikeClick}
|
|
199
|
+
style={isLiked ? { color: '#ff4d4f' } : undefined}
|
|
200
|
+
/>
|
|
201
|
+
</Tooltip>
|
|
189
202
|
<Tooltip title={isFavorited ? t('assistant.unfavorite') : t('assistant.favorite')}>
|
|
190
203
|
<ActionIcon
|
|
191
204
|
icon={isFavorited ? BookmarkCheckIcon : BookmarkIcon}
|