Skip to content

Commit 83cc49b

Browse files
committed
fix: 修复切换文件后无法使用快捷键操作文件
1 parent 5a86528 commit 83cc49b

File tree

4 files changed

+38
-17
lines changed

4 files changed

+38
-17
lines changed

src/app/core/article/file/file-item.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import { isSkillsFolder } from "@/lib/skills/utils";
2828

2929
type Platform = 'macos' | 'windows' | 'linux' | 'unknown'
3030

31-
export function FileItem({ item }: { item: DirTree }) {
31+
export function FileItem({ item, focusSidebar }: { item: DirTree; focusSidebar?: () => void }) {
3232
const [isEditing, setIsEditing] = useState(item.isEditing)
3333
const [name, setName] = useState(item.name)
3434
const [isComposing, setIsComposing] = useState(false) // 追踪输入法合成状态
@@ -149,6 +149,8 @@ export function FileItem({ item }: { item: DirTree }) {
149149
}, [])
150150

151151
async function handleSelectFile() {
152+
// 让文件管理器获得焦点,以便响应快捷键
153+
focusSidebar?.()
152154
const currentPath = computedParentPath(item)
153155

154156
if (item.name.match(/\.(jpg|jpeg|png|gif|bmp|webp|svg)$/i)) {

src/app/core/article/file/file-manager.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ function filterFileTree(tree: DirTree[], showCloud: boolean): DirTree[] {
1919
}))
2020
}
2121

22-
function Tree({ item }: { item: DirTree }) {
22+
function Tree({ item, focusSidebar }: { item: DirTree; focusSidebar: () => void }) {
2323
const { collapsibleList, setCollapsibleList, loadCollapsibleFiles } = useArticleStore()
2424
const path = computedParentPath(item)
2525

@@ -31,19 +31,19 @@ function Tree({ item }: { item: DirTree }) {
3131
}
3232

3333
return (
34-
item.isFile ?
35-
<FileItem item={item} /> :
34+
item.isFile ?
35+
<FileItem item={item} focusSidebar={focusSidebar} /> :
3636
<li>
3737
<Collapsible
3838
onOpenChange={handleCollapse}
3939
className="group/collapsible [&[data-state=open]>button>.file-manange-item>svg:first-child]:rotate-90"
4040
open={collapsibleList.includes(path)}
4141
>
42-
<FolderItem item={item} />
42+
<FolderItem item={item} focusSidebar={focusSidebar} />
4343
<CollapsibleContent className="pl-1">
4444
<ul className="pl-2">
4545
{item.children?.map((subItem) => (
46-
<Tree key={`${subItem.name}-${subItem.parent?.name}-${subItem.sha || ''}-${subItem.isLocale}`} item={subItem} />
46+
<Tree key={`${subItem.name}-${subItem.parent?.name}-${subItem.sha || ''}-${subItem.isLocale}`} item={subItem} focusSidebar={focusSidebar} />
4747
))}
4848
</ul>
4949
</CollapsibleContent>
@@ -52,7 +52,7 @@ function Tree({ item }: { item: DirTree }) {
5252
)
5353
}
5454

55-
export function FileManager() {
55+
export function FileManager({ focusSidebar }: { focusSidebar: () => void }) {
5656
const [isDragging, setIsDragging] = useState(false)
5757
const { activeFilePath, fileTree, loadFileTree, setActiveFilePath, addFile, showCloudFiles } = useArticleStore()
5858

@@ -157,7 +157,7 @@ export function FileManager() {
157157
>
158158
</div>
159159
{filteredFileTree.map((item) => (
160-
<Tree key={`${item.name}-${item.parent?.name || ''}-${item.sha || ''}-${item.isLocale}`} item={item} />
160+
<Tree key={`${item.name}-${item.parent?.name || ''}-${item.sha || ''}-${item.isLocale}`} item={item} focusSidebar={focusSidebar} />
161161
))}
162162
<div
163163
className="flex-1 min-h-1"

src/app/core/article/file/folder-item/index.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import { FolderVectorMenu } from './folder-vector-menu'
2828
import emitter from '@/lib/emitter'
2929
import { LinkedFolder } from '@/lib/files'
3030

31-
export function FolderItem({ item }: { item: DirTree }) {
31+
export function FolderItem({ item, focusSidebar }: { item: DirTree; focusSidebar?: () => void }) {
3232
const [isEditing, setIsEditing] = useState(item.isEditing)
3333
const [name, setName] = useState(item.name)
3434
const [isComposing, setIsComposing] = useState(false)
@@ -590,6 +590,8 @@ export function FolderItem({ item }: { item: DirTree }) {
590590
}
591591

592592
async function handleSelectFolder() {
593+
// 让文件管理器获得焦点,以便响应快捷键
594+
focusSidebar?.()
593595
// 设置选中状态
594596
await setActiveFilePath(path)
595597

src/app/core/article/file/index.tsx

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -181,13 +181,21 @@ function useFileManagerShortcuts() {
181181
}
182182
}, [])
183183

184-
const handleFocusOut = useCallback(() => {
185-
// 延迟检查,因为 focusOut 会在新元素获得焦点前触发
186-
setTimeout(() => {
187-
if (sidebarRef.current && !sidebarRef.current.contains(document.activeElement)) {
184+
const handleFocusOut = useCallback((e: FocusEvent) => {
185+
// 检查焦点是否移到了 sidebar 外部
186+
// relatedTarget 是即将获得焦点的元素
187+
const newFocusedElement = e.relatedTarget as Node
188+
189+
if (sidebarRef.current && newFocusedElement) {
190+
// 如果新焦点元素不在 sidebar 内,才设置 isFocused = false
191+
if (!sidebarRef.current.contains(newFocusedElement)) {
188192
setIsFocused(false)
189193
}
190-
}, 0)
194+
} else if (!newFocusedElement) {
195+
// 如果 relatedTarget 为 null(焦点移到了文档外),设置 isFocused = false
196+
setIsFocused(false)
197+
}
198+
// 否则,焦点还在 sidebar 内,保持 isFocused = true
191199
}, [])
192200

193201
useEffect(() => {
@@ -202,12 +210,21 @@ function useFileManagerShortcuts() {
202210
}
203211
}, [handleFocusIn, handleFocusOut])
204212

205-
return { sidebarRef, isFocused }
213+
// 主动设置焦点到文件管理器
214+
const focusSidebar = useCallback(() => {
215+
setIsFocused(true)
216+
// 使用 requestAnimationFrame 确保 DOM 更新后再设置焦点
217+
requestAnimationFrame(() => {
218+
sidebarRef.current?.focus()
219+
})
220+
}, [])
221+
222+
return { sidebarRef, isFocused, focusSidebar }
206223
}
207224

208225
export function FileSidebar() {
209226
const { initCollapsibleList, initSortSettings, initShowCloudFiles } = useArticleStore()
210-
const { sidebarRef } = useFileManagerShortcuts()
227+
const { sidebarRef, focusSidebar } = useFileManagerShortcuts()
211228

212229
useEffect(() => {
213230
initCollapsibleList()
@@ -223,7 +240,7 @@ export function FileSidebar() {
223240
tabIndex={-1}
224241
>
225242
<div className="flex-1 overflow-x-hidden overflow-y-auto">
226-
<FileManager />
243+
<FileManager focusSidebar={focusSidebar} />
227244
</div>
228245
<FileFooter />
229246
</div>

0 commit comments

Comments
 (0)