Merge pull request #46244 from skyc1e/fix/desktop-explorer-refresh

fix(desktop): keep file tree refresh clickable
This commit is contained in:
Dominik 2026-06-16 01:52:00 +02:00 committed by GitHub
parent 423d24780b
commit 9d2ec8d35a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 80 additions and 5 deletions

View file

@ -0,0 +1,75 @@
import { cleanup, fireEvent, render, screen, waitFor } from '@testing-library/react'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { HermesReadDirResult } from '@/global'
import { $connection, setCurrentCwd } from '@/store/session'
import { resetProjectTreeState } from './files/use-project-tree'
import { RightSidebarPane } from './index'
const readDir = vi.fn<(path: string) => Promise<HermesReadDirResult>>()
const selectPaths = vi.fn()
function ok(entries: { name: string; path: string; isDirectory: boolean }[]): HermesReadDirResult {
return { entries }
}
function installBridge() {
;(
window as unknown as {
hermesDesktop: {
readDir: typeof readDir
selectPaths: typeof selectPaths
}
}
).hermesDesktop = { readDir, selectPaths }
}
describe('RightSidebarPane', () => {
beforeEach(() => {
$connection.set(null)
resetProjectTreeState()
setCurrentCwd('/repo')
readDir.mockReset()
selectPaths.mockReset()
readDir.mockResolvedValue(ok([{ name: 'README.md', path: '/repo/README.md', isDirectory: false }]))
selectPaths.mockResolvedValue(['/repo-next'])
installBridge()
})
afterEach(() => {
cleanup()
$connection.set(null)
setCurrentCwd('')
resetProjectTreeState()
delete (window as unknown as { hermesDesktop?: unknown }).hermesDesktop
})
it('refreshes the current tree without opening the folder picker', async () => {
const onChangeCwd = vi.fn()
render(<RightSidebarPane onActivateFile={vi.fn()} onActivateFolder={vi.fn()} onChangeCwd={onChangeCwd} />)
await waitFor(() => expect(screen.getByRole('button', { name: 'Refresh tree' }).hasAttribute('disabled')).toBe(false))
readDir.mockClear()
fireEvent.click(screen.getByRole('button', { name: 'Refresh tree' }))
await waitFor(() => expect(readDir).toHaveBeenCalledWith('/repo'))
expect(selectPaths).not.toHaveBeenCalled()
fireEvent.click(screen.getByRole('button', { name: 'Open folder' }))
await waitFor(() =>
expect(selectPaths).toHaveBeenCalledWith({
defaultPath: '/repo',
directories: true,
multiple: false,
title: 'Change working directory'
})
)
await waitFor(() => expect(onChangeCwd).toHaveBeenCalledWith('/repo-next'))
})
})

View file

@ -126,12 +126,12 @@ interface FilesystemTabProps extends FileTreeBodyProps {
onRefresh: () => void
}
// Sidebar palette + hover-reveal: refresh tracks label hover; collapse-all
// stays visible while any folder is expanded.
// Sidebar palette + hover-reveal: header actions stay reachable while moving
// from the project label to the action buttons.
const HEADER_ACTION_CLASS =
'text-sidebar-foreground/70 hover:bg-sidebar-accent! hover:text-sidebar-accent-foreground! focus-visible:ring-sidebar-ring'
const HEADER_ACTION_LABEL_REVEAL = `${HEADER_ACTION_CLASS} pointer-events-none opacity-0 transition-opacity focus-visible:pointer-events-auto focus-visible:opacity-100 peer-focus-visible/project-label:pointer-events-auto peer-focus-visible/project-label:opacity-100 peer-hover/project-label:pointer-events-auto peer-hover/project-label:opacity-100`
const HEADER_ACTION_LABEL_REVEAL = `${HEADER_ACTION_CLASS} pointer-events-none opacity-0 transition-opacity focus-visible:pointer-events-auto focus-visible:opacity-100 group-focus-within/project-header:pointer-events-auto group-focus-within/project-header:opacity-100 group-hover/project-header:pointer-events-auto group-hover/project-header:opacity-100`
function FilesystemTab({
canCollapse,
@ -158,7 +158,7 @@ function FilesystemTab({
return (
<div className="flex min-h-0 flex-1 flex-col">
<RightSidebarSectionHeader>
<div className="peer/project-label flex min-w-0 flex-1">
<div className="flex min-w-0 flex-1">
<button
className="flex w-full min-w-0 items-center rounded-md text-left hover:text-(--ui-text-secondary)"
onClick={() => void onChangeFolder()}
@ -216,7 +216,7 @@ function FilesystemTab({
}
export function RightSidebarSectionHeader({ children }: { children: ReactNode }) {
return <div className="flex h-7 shrink-0 items-center px-2.5">{children}</div>
return <div className="group/project-header flex h-7 shrink-0 items-center px-2.5">{children}</div>
}
interface FileTreeBodyProps {