fix(sidebar): preserve reset for matching visibility overrides

This commit is contained in:
Brennan Benson
2026-08-13 17:49:05 -07:00
parent a6a9a6a482
commit 9fb9bd2e68
8 changed files with 111 additions and 6 deletions
@@ -363,6 +363,7 @@ export default function WorktreeVisibilityDialog(): React.JSX.Element | null {
onAdd={handleAddSource}
onRemove={handleRemoveSource}
onToggle={handleSourceToggle}
onUseDefault={handleUseDefault}
/>
<WorktreeVisibilityGlobalSettingsLink repo={repo} visibilityDefaults={visibilityDefaults} />
@@ -0,0 +1,70 @@
// @vitest-environment happy-dom
import { act } from 'react'
import { createRoot, type Root } from 'react-dom/client'
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import type { ReactNode } from 'react'
import type { Repo } from '../../../../shared/types'
import WorktreeVisibilitySourceList from './WorktreeVisibilitySourceList'
vi.mock('@/components/ui/tooltip', () => ({
Tooltip: ({ children }: { children: ReactNode }) => <>{children}</>,
TooltipTrigger: ({ children }: { children: ReactNode }) => <>{children}</>,
TooltipContent: ({ children }: { children: ReactNode }) => <>{children}</>
}))
let container: HTMLDivElement
let root: Root
beforeEach(() => {
container = document.createElement('div')
document.body.appendChild(container)
root = createRoot(container)
})
afterEach(() => {
act(() => root.unmount())
container.remove()
})
describe('WorktreeVisibilitySourceList', () => {
it('offers a reset when a project override already matches the global value', async () => {
const onUseDefault = vi.fn()
const repo: Repo = {
id: 'repo-1',
path: '/repo',
displayName: 'orca',
badgeColor: '#000000',
addedAt: 0,
worktreeVisibilitySourcePreferences: { builtIn: { claude: 'show' } }
}
act(() => {
root.render(
<WorktreeVisibilitySourceList
repo={repo}
visibilityDefaults={{
external: 'hide',
sourcePreferences: { builtIn: { claude: 'show' } }
}}
disabled={false}
onAdd={async () => 'added'}
onRemove={async () => {}}
onToggle={async () => {}}
onUseDefault={onUseDefault}
/>
)
})
const reset = container.querySelector<HTMLButtonElement>(
'button[aria-label="Use global for Claude Code"]'
)
expect(reset).not.toBeNull()
expect(container.querySelectorAll('button[aria-label^="Use global for "]')).toHaveLength(1)
expect(reset?.closest('[data-source-row]')?.textContent).not.toContain(
'Overriding global setting'
)
await act(async () => reset?.click())
expect(onUseDefault).toHaveBeenCalledWith({ kind: 'built-in', id: 'claude' })
})
})
@@ -57,6 +57,7 @@ type Props = {
onAdd: (rootPath: string) => Promise<WorktreeVisibilitySourceAddResult>
onRemove: (source: CustomWorktreeVisibilitySource) => Promise<void>
onToggle: (source: WorktreeVisibilitySourceRow, enabled: boolean) => Promise<void>
onUseDefault?: (source: WorktreeVisibilitySourceRow) => Promise<void>
}
const EMPTY_VISIBILITY_DEFAULTS: WorktreeVisibilityDefaults = {}
@@ -151,7 +152,8 @@ export default function WorktreeVisibilitySourceList({
sourceDefaultsDisabled = false,
onAdd,
onRemove,
onToggle
onToggle,
onUseDefault
}: Props): React.JSX.Element {
const customSources = useMemo(
() =>
@@ -230,6 +232,8 @@ export default function WorktreeVisibilitySourceList({
const visibility = sourceVisibility(repo, source, visibilityDefaults, repoCustomSourceIds)
const note = getWorktreeVisibilitySourceNote(provenance)
const overrideNotice = getWorktreeVisibilityOverrideNotice(provenance, visibility)
const matchingOverride =
provenance?.kind === 'project-override' && provenance.globalVisibility === visibility
return (
<div
key={key}
@@ -285,6 +289,26 @@ export default function WorktreeVisibilitySourceList({
</TooltipContent>
</Tooltip>
) : null}
{matchingOverride && onUseDefault ? (
<Button
type="button"
variant="link"
size="xs"
className="h-auto px-1"
disabled={sourceDisabled}
aria-label={translate(
'auto.components.sidebar.WorktreeVisibilitySourceList.useGlobalFor',
'Use global for {{value0}}',
{ value0: accessibleLabel }
)}
onClick={() => void onUseDefault(source)}
>
{translate(
'auto.components.sidebar.WorktreeVisibilitySourceList.useGlobal',
'Use global'
)}
</Button>
) : null}
<ToggleGroup
type="single"
variant="outline"
+3 -1
View File
@@ -5452,7 +5452,9 @@
"show": "Show",
"hide": "Hide",
"overridingGlobal": "Overriding global setting: {{value0}}",
"projectOnly": "Added in this project only."
"projectOnly": "Added in this project only.",
"useGlobalFor": "Use global for {{value0}}",
"useGlobal": "Use global"
}
},
"shared": {
+3 -1
View File
@@ -4728,7 +4728,9 @@
"show": "Mostrar",
"hide": "Ocultar",
"overridingGlobal": "Anulando la configuración global: {{value0}}",
"projectOnly": "Añadida solo en este proyecto."
"projectOnly": "Añadida solo en este proyecto.",
"useGlobalFor": "Usar la configuración global para {{value0}}",
"useGlobal": "Usar global"
},
"add": {
"repo": {
+3 -1
View File
@@ -4709,7 +4709,9 @@
"show": "表示",
"hide": "非表示",
"overridingGlobal": "グローバル設定を上書き中: {{value0}}",
"projectOnly": "このプロジェクトにのみ追加されています。"
"projectOnly": "このプロジェクトにのみ追加されています。",
"useGlobalFor": "{{value0}} にグローバル設定を使用",
"useGlobal": "グローバルを使用"
},
"add": {
"repo": {
+3 -1
View File
@@ -4709,7 +4709,9 @@
"show": "표시",
"hide": "숨김",
"overridingGlobal": "전역 설정 재정의 중: {{value0}}",
"projectOnly": "이 프로젝트에만 추가되었습니다."
"projectOnly": "이 프로젝트에만 추가되었습니다.",
"useGlobalFor": "{{value0}}에 전역 설정 사용",
"useGlobal": "전역 사용"
},
"add": {
"repo": {
+3 -1
View File
@@ -4721,7 +4721,9 @@
"show": "显示",
"hide": "隐藏",
"overridingGlobal": "正在覆盖全局设置:{{value0}}",
"projectOnly": "仅在此项目中添加。"
"projectOnly": "仅在此项目中添加。",
"useGlobalFor": "为 {{value0}} 使用全局设置",
"useGlobal": "使用全局设置"
},
"add": {
"repo": {