Skip to content

Commit 59a6072

Browse files
committed
feat: enhance UI store to manage active tab state and update related components for better navigation
1 parent dd234ad commit 59a6072

5 files changed

Lines changed: 112 additions & 2 deletions

File tree

src/renderer/src/components/layout/Layout.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@ const { Sider, Content } = AntLayout
1515
const NARROW_SCREEN_THRESHOLD = 768
1616

1717
export default function Layout() {
18-
const { sidebarCollapsed, sidebarWidth, toggleSidebar } = useUIStore()
18+
const { sidebarCollapsed, sidebarWidth, activeTab, toggleSidebar, setActiveTab } = useUIStore()
1919
const { clearSearch, setFilterFolderId } = useSearchStore()
20-
const [activeTab, setActiveTab] = useState<ActivityBarTab>('explore')
2120
const [searchOpen, setSearchOpen] = useState(false)
2221
const [isNarrowScreen, setIsNarrowScreen] = useState(false)
2322

src/renderer/src/components/layout/sidebar_items/chat/ChatHistoryTree.tsx

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ export default function ChatHistoryTree({ onChatClick, onFindInFolder }: ChatHis
5252
// 添加虚拟滚动高度状态
5353
const [virtualHeight, setVirtualHeight] = useState(800)
5454
const treeContainerRef = useRef<HTMLDivElement>(null)
55+
const treeRef = useRef<any>(null)
56+
const lastSelectedNodeIdRef = useRef<string | null>(null)
5557

5658
// 动态计算虚拟滚动高度
5759
useEffect(() => {
@@ -67,6 +69,44 @@ export default function ChatHistoryTree({ onChatClick, onFindInFolder }: ChatHis
6769
return () => window.removeEventListener('resize', calculateHeight)
6870
}, [])
6971

72+
// 展开父级文件夹并滚动到选中的节点
73+
useEffect(() => {
74+
// 只有当选中的节点真正改变时才执行滚动
75+
if (selectedNodeId && selectedNodeType === 'chat' && selectedNodeId !== lastSelectedNodeIdRef.current) {
76+
lastSelectedNodeIdRef.current = selectedNodeId
77+
78+
// 找到该聊天所在的文件夹链
79+
const chat = pages.find((p) => p.id === selectedNodeId)
80+
if (chat && chat.folderId) {
81+
const foldersToExpand: string[] = []
82+
let currentFolderId: string | undefined = chat.folderId
83+
84+
// 收集所有需要展开的父级文件夹
85+
while (currentFolderId) {
86+
foldersToExpand.push(currentFolderId)
87+
const folder = folders.find((f) => f.id === currentFolderId)
88+
currentFolderId = folder?.parentId
89+
}
90+
91+
// 展开所有父级文件夹
92+
foldersToExpand.forEach((folderId) => {
93+
const folder = folders.find((f) => f.id === folderId)
94+
if (folder && !folder.expanded) {
95+
updateFolder(folderId, { expanded: true })
96+
}
97+
})
98+
}
99+
100+
// 使用虚拟化Tree的scrollTo API滚动到选中的节点
101+
setTimeout(() => {
102+
const nodeKey = `chat-${selectedNodeId}`
103+
if (treeRef.current && treeRef.current.scrollTo) {
104+
treeRef.current.scrollTo({ key: nodeKey, align: 'auto' })
105+
}
106+
}, 300) // 增加延迟确保文件夹展开完成
107+
}
108+
}, [selectedNodeId, selectedNodeType, pages, folders, updateFolder])
109+
70110
// 解析节点键,获取节点类型和ID
71111
const parseNodeKey = useCallback(
72112
(key: React.Key): { type: 'folder' | 'chat'; id: string } | null => {
@@ -704,6 +744,7 @@ export default function ChatHistoryTree({ onChatClick, onFindInFolder }: ChatHis
704744
return (
705745
<div ref={treeContainerRef} style={{ height: '100%' }}>
706746
<Tree
747+
ref={treeRef}
707748
className="chat-history-tree"
708749
showIcon
709750
blockNode

src/renderer/src/components/layout/sidebar_items/favorites/FavoritesPanel.tsx

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,62 @@ export default function FavoritesPanel() {
3333
const { selectedFavoriteId, selectedFavoriteType, setSelectedFavorite } = useUIStore()
3434

3535
const [editingNodeKey, setEditingNodeKey] = useState<string | null>(null)
36+
const treeRef = React.useRef<any>(null)
37+
const lastSelectedFavoriteIdRef = React.useRef<string | null>(null)
3638

3739
const stats = getStats()
3840

41+
// 展开父级文件夹并滚动到选中的节点
42+
useEffect(() => {
43+
// 只有当选中的节点真正改变时才执行滚动
44+
if (selectedFavoriteId && selectedFavoriteType === 'item' && selectedFavoriteId !== lastSelectedFavoriteIdRef.current) {
45+
lastSelectedFavoriteIdRef.current = selectedFavoriteId
46+
47+
// 找到该收藏项所在的文件夹链
48+
const item = items.find((i) => i.id === selectedFavoriteId)
49+
if (item && item.folderId) {
50+
const foldersToExpand: string[] = []
51+
let currentFolderId: string | undefined = item.folderId
52+
53+
// 收集所有需要展开的父级文件夹
54+
while (currentFolderId) {
55+
foldersToExpand.push(currentFolderId)
56+
const folder = folders.find((f) => f.id === currentFolderId)
57+
currentFolderId = folder?.parentId
58+
}
59+
60+
// 展开所有父级文件夹
61+
const { updateFolder } = useFavoritesStore.getState()
62+
foldersToExpand.forEach((folderId) => {
63+
const folder = folders.find((f) => f.id === folderId)
64+
if (folder && !folder.expanded) {
65+
updateFolder(folderId, { expanded: true })
66+
}
67+
})
68+
}
69+
70+
// 滚动到选中的节点
71+
setTimeout(() => {
72+
const nodeKey = `item-${selectedFavoriteId}`
73+
74+
// 优先使用Tree的scrollTo API(如果可用)
75+
if (treeRef.current && treeRef.current.scrollTo) {
76+
treeRef.current.scrollTo({ key: nodeKey, align: 'auto' })
77+
} else {
78+
// 备用方案:使用DOM查询(适用于非虚拟化Tree)
79+
let selectedNode =
80+
document.querySelector(`.favorites-tree [data-node-key="${nodeKey}"]`) ||
81+
document.querySelector(`.favorites-tree [data-key="${nodeKey}"]`) ||
82+
document.querySelector(`.favorites-tree .ant-tree-treenode-selected`)
83+
84+
if (selectedNode) {
85+
selectedNode.scrollIntoView({ behavior: 'smooth', block: 'nearest' })
86+
}
87+
}
88+
}, 300) // 增加延迟确保文件夹展开完成
89+
}
90+
}, [selectedFavoriteId, selectedFavoriteType, items, folders])
91+
3992
// 处理搜索
4093
const handleSearch = (value: string) => {
4194
setSearchQuery(value)
@@ -578,6 +631,7 @@ export default function FavoritesPanel() {
578631
/>
579632
) : (
580633
<Tree
634+
ref={treeRef}
581635
className="favorites-tree"
582636
showIcon={false}
583637
blockNode

src/renderer/src/components/layout/tabs/TabsArea.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,13 +322,19 @@ export default function TabsArea() {
322322
setSelectedFavorite(favoriteId, 'item')
323323
// 清空聊天历史树的选中状态
324324
setSelectedNode(null, null)
325+
// 切换到收藏夹侧边栏
326+
const { setActiveTab: setSidebarTab } = useUIStore.getState()
327+
setSidebarTab('favorites')
325328
} else {
326329
// 如果是普通页面,更新聊天历史树的选中状态
327330
const page = pages.find((p) => p.id === activeKey)
328331
if (page) {
329332
setSelectedNode(activeKey, 'chat')
330333
// 清空收藏面板的选中状态
331334
setSelectedFavorite(null, null)
335+
// 切换到资源管理器侧边栏
336+
const { setActiveTab: setSidebarTab } = useUIStore.getState()
337+
setSidebarTab('explore')
332338
}
333339
}
334340
}

src/renderer/src/stores/uiStore.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export interface UIState {
1818
// 侧边栏状态
1919
sidebarCollapsed: boolean
2020
sidebarWidth: number
21+
activeTab: 'explore' | 'search' | 'tasks' | 'favorites'
2122

2223
// 消息折叠状态
2324
collapsedMessages: { [chatId: string]: string[] }
@@ -42,6 +43,7 @@ export interface UIActions {
4243
setSidebarWidth: (width: number) => void
4344
collapseSidebar: () => void
4445
expandSidebar: () => void
46+
setActiveTab: (tab: 'explore' | 'search' | 'tasks' | 'favorites') => void
4547

4648
// 消息折叠
4749
toggleMessageCollapse: (chatId: string, messageId: string) => void
@@ -67,6 +69,7 @@ const initialState: UIState = {
6769
selectedFavoriteType: null,
6870
sidebarCollapsed: false,
6971
sidebarWidth: 300,
72+
activeTab: 'explore',
7073
collapsedMessages: {},
7174
allMessagesCollapsed: {},
7275
lineageDisplayCollapsed: {}
@@ -150,6 +153,12 @@ export const useUIStore = create<UIState & UIActions>()(
150153
})
151154
},
152155

156+
setActiveTab: (tab) => {
157+
set((state) => {
158+
state.activeTab = tab
159+
})
160+
},
161+
153162
// 消息折叠
154163
toggleMessageCollapse: (chatId, messageId) => {
155164
try {
@@ -252,6 +261,7 @@ export const useUIStore = create<UIState & UIActions>()(
252261
selectedFavoriteType: state.selectedFavoriteType,
253262
sidebarCollapsed: state.sidebarCollapsed,
254263
sidebarWidth: state.sidebarWidth,
264+
activeTab: state.activeTab,
255265
collapsedMessages: state.collapsedMessages,
256266
allMessagesCollapsed: state.allMessagesCollapsed
257267
}))

0 commit comments

Comments
 (0)