Skip to content

Commit 601720e

Browse files
committed
feat: replace bookmarking functionality with starring feature across chat components
1 parent 59a6072 commit 601720e

13 files changed

Lines changed: 147 additions & 137 deletions

File tree

src/renderer/src/components/pages/chat/ChatHeader.tsx

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ import { Button, Dropdown, Space, App, Tooltip, Input } from 'antd'
33
import {
44
ExportOutlined,
55
DownOutlined,
6-
UpOutlined,
7-
BranchesOutlined,
86
EditOutlined,
97
HeartOutlined,
108
HeartFilled,
9+
StarOutlined,
10+
StarFilled,
1111
MoreOutlined
1212
} from '@ant-design/icons'
1313
import type { MenuProps } from 'antd'
@@ -90,6 +90,12 @@ export default function ChatHeader({
9090
setIsEditingTitle(true)
9191
}
9292

93+
// 处理页面星标切换
94+
const handleTogglePageStar = () => {
95+
const currentStarred = chat?.starred || false
96+
updatePage(chatId, { starred: !currentStarred })
97+
}
98+
9399
// 保存标题
94100
const handleSaveTitle = () => {
95101
const trimmedTitle = editingTitle.trim()
@@ -331,10 +337,10 @@ export default function ChatHeader({
331337
metadata.push(`用户消息: ${userMessages}`)
332338
metadata.push(`AI消息: ${assistantMessages}`)
333339

334-
// 书签消息
335-
const bookmarkedMessages = messages.filter((m) => m.isBookmarked).length
336-
if (bookmarkedMessages > 0) {
337-
metadata.push(`书签消息: ${bookmarkedMessages}`)
340+
// 星标消息
341+
const starredMessages = messages.filter((m) => m.starred).length
342+
if (starredMessages > 0) {
343+
metadata.push(`星标消息: ${starredMessages}`)
338344
}
339345

340346
// 当前路径信息
@@ -382,6 +388,20 @@ export default function ChatHeader({
382388
<h3 className="chat-title" style={{ cursor: 'help', margin: 0 }}>
383389
{chatTitle || '未命名聊天'}
384390
</h3>
391+
</Tooltip>
392+
<Tooltip title={chat?.starred ? '取消星标' : '添加星标'}>
393+
<Button
394+
type="text"
395+
size="small"
396+
icon={chat?.starred ? <StarFilled /> : <StarOutlined />}
397+
onClick={handleTogglePageStar}
398+
style={{
399+
opacity: isHoveringTitle || chat?.starred ? 1 : 0,
400+
transition: 'opacity 0.2s',
401+
visibility: isHoveringTitle || chat?.starred ? 'visible' : 'hidden',
402+
color: chat?.starred ? '#faad14' : undefined
403+
}}
404+
/>
385405
</Tooltip>
386406
<Button
387407
type="text"

src/renderer/src/components/pages/chat/ChatLogic.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ interface ChatLogicProps {
2626
onContinueMessage: (messageId: string) => Promise<void>
2727
onEditMessage: (messageId: string, newContent: string) => Promise<void>
2828
onEditAndResendMessage: (messageId: string, newContent: string) => Promise<void>
29-
onToggleBookmark: (messageId: string) => void
29+
onToggleStar: (messageId: string) => void
3030
onModelChangeForMessage: (messageId: string, newModelId: string) => Promise<void>
3131
onDeleteMessage: (messageId: string) => Promise<void>
3232
onTriggerFollowUpQuestion: () => Promise<void>
@@ -216,7 +216,7 @@ export default function ChatLogic({
216216
onContinueMessage: messageOperations.handleContinueMessage,
217217
onEditMessage: messageOperations.handleEditMessage,
218218
onEditAndResendMessage: messageOperations.handleEditAndResendMessage,
219-
onToggleBookmark: messageOperations.handleToggleBookmark,
219+
onToggleStar: messageOperations.handleToggleStar,
220220
onModelChangeForMessage: messageOperations.handleModelChangeForMessage,
221221
onDeleteMessage: messageOperations.handleDeleteMessage,
222222
onTriggerFollowUpQuestion: handleTriggerFollowUpQuestion

src/renderer/src/components/pages/chat/ChatWindow.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ const ChatWindow = forwardRef<ChatWindowRef, ChatWindowProps>(({ chatId }, ref)
379379
onContinueMessage,
380380
onEditMessage,
381381
onEditAndResendMessage,
382-
onToggleBookmark,
382+
onToggleStar,
383383
onModelChangeForMessage,
384384
onDeleteMessage,
385385
onTriggerFollowUpQuestion
@@ -448,7 +448,7 @@ const ChatWindow = forwardRef<ChatWindowRef, ChatWindowProps>(({ chatId }, ref)
448448
onContinueMessage={onContinueMessage}
449449
onEditMessage={onEditMessage}
450450
onEditAndResendMessage={onEditAndResendMessage}
451-
onToggleBookmark={onToggleBookmark}
451+
onToggleStar={onToggleStar}
452452
onAddToFavorites={handleAddToFavorites}
453453
onFavoriteTextFragment={handleFavoriteTextFragment}
454454
onModelChange={onModelChangeForMessage}

src/renderer/src/components/pages/chat/MessageItem.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ interface MessageItemProps {
4040
onContinue?: (messageId: string) => void
4141
onEdit?: (messageId: string, newContent: string) => void
4242
onEditAndResend?: (messageId: string, newContent: string) => void
43-
onToggleBookmark?: (messageId: string) => void
43+
onToggleStar?: (messageId: string) => void
4444
onAddToFavorites?: (messageId: string) => void
4545
onFavoriteTextFragment?: (messageId: string, text: string) => void
4646
onModelChange?: (messageId: string, newModelId: string) => void
@@ -81,7 +81,7 @@ const MessageItem = React.memo(
8181
onContinue,
8282
onEdit,
8383
onEditAndResend,
84-
onToggleBookmark,
84+
onToggleStar,
8585
onAddToFavorites,
8686
onFavoriteTextFragment,
8787
onModelChange,
@@ -120,7 +120,7 @@ const MessageItem = React.memo(
120120
onContinue,
121121
onEdit,
122122
onEditAndResend,
123-
onToggleBookmark,
123+
onToggleStar,
124124
onAddToFavorites,
125125
onModelChange,
126126
onDelete,
@@ -230,7 +230,7 @@ const MessageItem = React.memo(
230230
<div
231231
ref={messageRef}
232232
data-message-id={message.id}
233-
className={`message-item ${message.role === 'user' ? 'user-message' : 'assistant-message'}${message.isBookmarked ? ' bookmarked' : ''}${message.hasError ? ' has-error' : ''}`}
233+
className={`message-item ${message.role === 'user' ? 'user-message' : 'assistant-message'}${message.starred ? ' starred' : ''}${message.hasError ? ' has-error' : ''}`}
234234
>
235235
<div className="message-avatar">
236236
<Avatar
@@ -309,14 +309,14 @@ const MessageItem = React.memo(
309309
<div className={`message-actions ${isLastMessage ? 'visible' : ''}`}>
310310
<MessageActionButtons
311311
role={message.role}
312-
isBookmarked={message.isBookmarked || false}
312+
starred={message.starred || false}
313313
isCurrentlyStreaming={isCurrentlyStreaming}
314314
isEditing={messageActions.isEditing}
315315
hasChildren={hasChildren}
316316
isLoading={isLoading}
317317
onCopy={messageActions.handleCopy}
318318
onCopyAsImage={imageExport.handleCopyAsImage}
319-
onToggleBookmark={messageActions.handleToggleBookmark}
319+
onToggleStar={messageActions.handleToggleStar}
320320
onAddToFavorites={onAddToFavorites ? handleAddMessageToFavorites : undefined}
321321
onEdit={messageActions.handleEdit}
322322
onRetry={onRetry ? messageActions.handleRetry : undefined}
@@ -388,7 +388,7 @@ const MessageItem = React.memo(
388388
prevProps.message.content !== nextProps.message.content ||
389389
prevProps.message.reasoning_content !== nextProps.message.reasoning_content ||
390390
prevProps.message.isStreaming !== nextProps.message.isStreaming ||
391-
prevProps.message.isBookmarked !== nextProps.message.isBookmarked ||
391+
prevProps.message.starred !== nextProps.message.starred ||
392392
prevProps.message.modelId !== nextProps.message.modelId ||
393393
prevProps.message.attachments !== nextProps.message.attachments ||
394394
prevProps.message.hasError !== nextProps.message.hasError

src/renderer/src/components/pages/chat/MessageList.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ interface MessageListProps {
2020
onContinueMessage?: (messageId: string) => void
2121
onEditMessage?: (messageId: string, newContent: string) => void
2222
onEditAndResendMessage?: (messageId: string, newContent: string) => void
23-
onToggleBookmark?: (messageId: string) => void
23+
onToggleStar?: (messageId: string) => void
2424
onAddToFavorites?: (messageId: string) => void
2525
onFavoriteTextFragment?: (messageId: string, text: string) => void
2626
onModelChange?: (messageId: string, newModelId: string) => void
@@ -50,7 +50,7 @@ const MessageList = React.memo(function MessageList({
5050
onContinueMessage,
5151
onEditMessage,
5252
onEditAndResendMessage,
53-
onToggleBookmark,
53+
onToggleStar,
5454
onAddToFavorites,
5555
onFavoriteTextFragment,
5656
onModelChange,
@@ -503,7 +503,7 @@ const MessageList = React.memo(function MessageList({
503503
onContinue={onContinueMessage}
504504
onEdit={onEditMessage}
505505
onEditAndResend={onEditAndResendMessage}
506-
onToggleBookmark={onToggleBookmark}
506+
onToggleStar={onToggleStar}
507507
onAddToFavorites={onAddToFavorites}
508508
onFavoriteTextFragment={onFavoriteTextFragment}
509509
onModelChange={onModelChange}

src/renderer/src/components/pages/chat/MessageTreeSidebar.tsx

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import {
77
MessageOutlined,
88
ExpandAltOutlined,
99
CompressOutlined,
10-
BookOutlined,
11-
BookFilled,
10+
StarOutlined,
11+
StarFilled,
1212
UpOutlined,
1313
DownOutlined,
1414
RightOutlined,
@@ -277,51 +277,51 @@ const MessageTreeSidebar: React.FC<MessageTreeSidebarProps> = ({
277277
const userMessages = messages.filter((msg) => msg.role === 'user').length
278278
const aiMessages = messages.filter((msg) => msg.role === 'assistant').length
279279
const branches = messages.filter((msg) => msg.children && msg.children.length > 1).length
280-
const bookmarkedMessages = messages
281-
.filter((msg) => msg.isBookmarked)
280+
const starredMessages = messages
281+
.filter((msg) => msg.starred)
282282
.sort((a, b) => a.timestamp - b.timestamp)
283283

284284
return {
285285
totalMessages,
286286
userMessages,
287287
aiMessages,
288288
branches,
289-
bookmarked: bookmarkedMessages.length,
290-
bookmarkedMessages
289+
starred: starredMessages.length,
290+
starredMessages
291291
}
292292
}, [messages])
293293

294-
// 当前书签消息的索引
295-
const currentBookmarkedIndex = useMemo(() => {
296-
if (stats.bookmarkedMessages.length === 0 || !selectedMessageId) {
294+
// 当前星标消息的索引
295+
const currentStarredIndex = useMemo(() => {
296+
if (stats.starredMessages.length === 0 || !selectedMessageId) {
297297
return -1
298298
}
299-
return stats.bookmarkedMessages.findIndex((msg) => msg.id === selectedMessageId)
300-
}, [stats.bookmarkedMessages, selectedMessageId])
299+
return stats.starredMessages.findIndex((msg) => msg.id === selectedMessageId)
300+
}, [stats.starredMessages, selectedMessageId])
301301

302-
// 跳转到指定的书签消息
303-
const navigateToBookmarked = (direction: 'prev' | 'next') => {
304-
if (stats.bookmarkedMessages.length === 0) return
302+
// 跳转到指定的星标消息
303+
const navigateToStarred = (direction: 'prev' | 'next') => {
304+
if (stats.starredMessages.length === 0) return
305305

306306
let targetIndex: number
307-
if (currentBookmarkedIndex === -1) {
308-
// 如果当前没有选中书签消息,跳转到第一个
307+
if (currentStarredIndex === -1) {
308+
// 如果当前没有选中星标消息,跳转到第一个
309309
targetIndex = 0
310310
} else {
311311
if (direction === 'prev') {
312312
targetIndex =
313-
currentBookmarkedIndex > 0
314-
? currentBookmarkedIndex - 1
315-
: stats.bookmarkedMessages.length - 1
313+
currentStarredIndex > 0
314+
? currentStarredIndex - 1
315+
: stats.starredMessages.length - 1
316316
} else {
317317
targetIndex =
318-
currentBookmarkedIndex < stats.bookmarkedMessages.length - 1
319-
? currentBookmarkedIndex + 1
318+
currentStarredIndex < stats.starredMessages.length - 1
319+
? currentStarredIndex + 1
320320
: 0
321321
}
322322
}
323323

324-
const targetMessage = stats.bookmarkedMessages[targetIndex]
324+
const targetMessage = stats.starredMessages[targetIndex]
325325
if (targetMessage && onNodeSelect) {
326326
onNodeSelect(targetMessage.id)
327327
}
@@ -489,25 +489,25 @@ const MessageTreeSidebar: React.FC<MessageTreeSidebarProps> = ({
489489
<BranchesOutlined />
490490
<Text type="secondary">{stats.branches}</Text>
491491
</div>
492-
{stats.bookmarked > 0 && (
493-
<div className="stat-item stat-item-bookmarked-collapsed">
494-
<BookFilled />
495-
<Text type="secondary">{stats.bookmarked}</Text>
496-
<div className="bookmarked-navigation-collapsed">
492+
{stats.starred > 0 && (
493+
<div className="stat-item stat-item-starred-collapsed">
494+
<StarOutlined />
495+
<Text type="secondary">{stats.starred}</Text>
496+
<div className="starred-navigation-collapsed">
497497
<Button
498498
type="text"
499499
size="small"
500500
icon={<UpOutlined />}
501-
onClick={() => navigateToBookmarked('prev')}
502-
title="上一个书签"
501+
onClick={() => navigateToStarred('prev')}
502+
title="上一个星标"
503503
className="nav-btn-collapsed"
504504
/>
505505
<Button
506506
type="text"
507507
size="small"
508508
icon={<DownOutlined />}
509-
onClick={() => navigateToBookmarked('next')}
510-
title="下一个书签"
509+
onClick={() => navigateToStarred('next')}
510+
title="下一个星标"
511511
className="nav-btn-collapsed"
512512
/>
513513
</div>
@@ -601,34 +601,34 @@ const MessageTreeSidebar: React.FC<MessageTreeSidebarProps> = ({
601601
{stats.branches}个分支
602602
</Text>
603603
</div>
604-
{stats.bookmarked > 0 && (
605-
<div className="stat-item stat-item-bookmarked">
606-
<div className="bookmarked-info">
607-
<BookOutlined />
604+
{stats.starred > 0 && (
605+
<div className="stat-item stat-item-starred">
606+
<div className="starred-info">
607+
<StarOutlined />
608608
<Text type="secondary" style={{ fontSize: '12px' }}>
609-
{stats.bookmarked}个书签
610-
{currentBookmarkedIndex >= 0 && (
611-
<span className="bookmarked-position">
612-
{` (${currentBookmarkedIndex + 1}/${stats.bookmarked})`}
609+
{stats.starred}个星标
610+
{currentStarredIndex >= 0 && (
611+
<span className="starred-position">
612+
{` (${currentStarredIndex + 1}/${stats.starred})`}
613613
</span>
614614
)}
615615
</Text>
616616
</div>
617-
<div className="bookmarked-navigation">
617+
<div className="starred-navigation">
618618
<Button
619619
type="text"
620620
size="small"
621621
icon={<UpOutlined />}
622-
onClick={() => navigateToBookmarked('prev')}
623-
title="上一个书签"
622+
onClick={() => navigateToStarred('prev')}
623+
title="上一个星标"
624624
className="nav-btn"
625625
/>
626626
<Button
627627
type="text"
628628
size="small"
629629
icon={<DownOutlined />}
630-
onClick={() => navigateToBookmarked('next')}
631-
title="下一个书签"
630+
onClick={() => navigateToStarred('next')}
631+
title="下一个星标"
632632
className="nav-btn"
633633
/>
634634
</div>
@@ -694,7 +694,7 @@ const MessageTreeSidebar: React.FC<MessageTreeSidebarProps> = ({
694694
<div
695695
className={`path-node ${
696696
selectedMessageId === node.messageId ? 'selected' : ''
697-
} ${node.message.isBookmarked ? 'bookmarked' : ''}`}
697+
} ${node.message.starred ? 'starred' : ''}`}
698698
onClick={() => handleNodeSelect(node.messageId)}
699699
data-role={node.message.role}
700700
>
@@ -705,7 +705,7 @@ const MessageTreeSidebar: React.FC<MessageTreeSidebarProps> = ({
705705
<div className="path-node-info">
706706
<div className="path-node-role">
707707
{node.message.role === 'user' ? '用户' : 'AI'}
708-
{node.message.isBookmarked && <BookFilled className="bookmark-icon" />}
708+
{node.message.starred && <StarFilled className="star-icon" />}
709709
</div>
710710
<div className="path-node-time">
711711
<RelativeTime timestamp={node.message.timestamp} />
@@ -748,7 +748,7 @@ const MessageTreeSidebar: React.FC<MessageTreeSidebarProps> = ({
748748
key={sibling.id}
749749
className={`sibling-node ${
750750
selectedMessageId === sibling.id ? 'selected' : ''
751-
} ${sibling.isBookmarked ? 'bookmarked' : ''}`}
751+
} ${sibling.starred ? 'starred' : ''}`}
752752
onClick={() => handleNodeSelect(sibling.id)}
753753
data-role={sibling.role}
754754
>
@@ -759,7 +759,7 @@ const MessageTreeSidebar: React.FC<MessageTreeSidebarProps> = ({
759759
<div className="sibling-node-info">
760760
<div className="sibling-node-role">
761761
{sibling.role === 'user' ? '用户' : 'AI'}
762-
{sibling.isBookmarked && <BookFilled className="bookmark-icon" />}
762+
{sibling.starred && <StarFilled className="star-icon" />}
763763
</div>
764764
<div className="sibling-node-time">
765765
<RelativeTime timestamp={sibling.timestamp} />

0 commit comments

Comments
 (0)