mirror of
https://github.com/stablyai/orca.git
synced 2026-10-23 00:03:52 +00:00
Clarify inherited worktree visibility settings
This commit is contained in:
@@ -634,6 +634,21 @@ describe('WorktreeVisibilityDialog', () => {
|
||||
expect(sourceRow('GSD').textContent).toContain('Using global: Hidden')
|
||||
expect(sourceRow('Other locations').textContent).toContain('Using global: Hidden')
|
||||
expect(document.querySelector('button[aria-label^="Use global for"]')).toBeNull()
|
||||
expect(document.body.textContent).toContain(
|
||||
'Sources enabled in Global Settings also apply to this project.'
|
||||
)
|
||||
})
|
||||
|
||||
it('does not show the global impact notice when inherited sources are hidden', async () => {
|
||||
mocks.state.repos = [makeRepo({ externalWorktreeVisibility: undefined })]
|
||||
mocks.state.settings = { worktreeVisibilityDefaults: { external: 'hide' } }
|
||||
|
||||
await renderDialog()
|
||||
|
||||
expect(document.body.textContent).not.toContain(
|
||||
'Sources enabled in Global Settings also apply to this project.'
|
||||
)
|
||||
expect(buttonWithText('Manage in Global Settings')).not.toBeNull()
|
||||
})
|
||||
|
||||
it('labels project overrides and resets a built-in source to global inheritance', async () => {
|
||||
|
||||
@@ -57,6 +57,7 @@ import {
|
||||
import { WorktreeVisibilityGlobalSettingsLink } from './WorktreeVisibilityGlobalSettingsLink'
|
||||
import { WorktreeVisibilityScanStatus } from './WorktreeVisibilityScanStatus'
|
||||
import { createWorktreeVisibilityUseGlobalMutation } from './worktree-visibility-use-global'
|
||||
import { hasGloballyShownWorktreeVisibilitySource } from './worktree-visibility-source-provenance'
|
||||
|
||||
export default function WorktreeVisibilityDialog(): React.JSX.Element | null {
|
||||
const activeModal = useAppStore((s) => s.activeModal)
|
||||
@@ -91,6 +92,10 @@ export default function WorktreeVisibilityDialog(): React.JSX.Element | null {
|
||||
const effectivelyToggling = isToggling || activeMutation?.kind === 'toggle'
|
||||
const visibilityDefaults = useRepoOwnerVisibilityDefaults(repo)
|
||||
const removableSourceIds = useMemo(() => getRepoCustomWorktreeVisibilitySourceIds(repo), [repo])
|
||||
const hasGloballyShownSource = useMemo(
|
||||
() => (repo ? hasGloballyShownWorktreeVisibilitySource(repo, visibilityDefaults) : false),
|
||||
[repo, visibilityDefaults]
|
||||
)
|
||||
|
||||
useLayoutEffect(() => {
|
||||
currentMutationScopeRef.current = mutationScope
|
||||
@@ -388,7 +393,7 @@ export default function WorktreeVisibilityDialog(): React.JSX.Element | null {
|
||||
onUseDefault={handleUseDefault}
|
||||
/>
|
||||
|
||||
<WorktreeVisibilityGlobalSettingsLink />
|
||||
<WorktreeVisibilityGlobalSettingsLink hasGloballyShownSource={hasGloballyShownSource} />
|
||||
|
||||
<WorktreeVisibilityScanStatus
|
||||
state={listState}
|
||||
|
||||
@@ -16,7 +16,7 @@ function openGlobalWorktreeVisibilitySettings(): void {
|
||||
store.openSettingsPage()
|
||||
}
|
||||
|
||||
export function WorktreeVisibilityGlobalSettingsLink(): React.JSX.Element {
|
||||
function GlobalSettingsButton(): React.JSX.Element {
|
||||
return (
|
||||
<Button
|
||||
type="button"
|
||||
@@ -33,3 +33,25 @@ export function WorktreeVisibilityGlobalSettingsLink(): React.JSX.Element {
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
export function WorktreeVisibilityGlobalSettingsLink({
|
||||
hasGloballyShownSource
|
||||
}: {
|
||||
hasGloballyShownSource: boolean
|
||||
}): React.JSX.Element {
|
||||
if (!hasGloballyShownSource) {
|
||||
return <GlobalSettingsButton />
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="grid gap-1 rounded-lg border border-border bg-muted/30 px-2.5 py-2">
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{translate(
|
||||
'auto.components.sidebar.WorktreeVisibilityDialog.globalSettingsApply',
|
||||
'Sources enabled in Global Settings also apply to this project.'
|
||||
)}
|
||||
</p>
|
||||
<GlobalSettingsButton />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import type { Repo, WorktreeVisibilityDefaults } from '../../../../shared/types'
|
||||
import { hasGloballyShownWorktreeVisibilitySource } from './worktree-visibility-source-provenance'
|
||||
|
||||
function repo(overrides: Partial<Repo> = {}): Repo {
|
||||
return {
|
||||
id: 'repo-1',
|
||||
path: '/repo',
|
||||
displayName: 'orca',
|
||||
badgeColor: '#000000',
|
||||
addedAt: 0,
|
||||
externalWorktreeVisibility: undefined,
|
||||
...overrides
|
||||
}
|
||||
}
|
||||
|
||||
describe('hasGloballyShownWorktreeVisibilitySource', () => {
|
||||
const shownClaude: WorktreeVisibilityDefaults = {
|
||||
external: 'hide',
|
||||
sourcePreferences: { builtIn: { claude: 'show' } }
|
||||
}
|
||||
|
||||
it('detects an inherited source enabled in global settings', () => {
|
||||
expect(hasGloballyShownWorktreeVisibilitySource(repo(), shownClaude)).toBe(true)
|
||||
})
|
||||
|
||||
it('ignores a globally enabled source overridden by the project', () => {
|
||||
expect(
|
||||
hasGloballyShownWorktreeVisibilitySource(
|
||||
repo({ worktreeVisibilitySourcePreferences: { builtIn: { claude: 'hide' } } }),
|
||||
shownClaude
|
||||
)
|
||||
).toBe(false)
|
||||
})
|
||||
|
||||
it('ignores global settings when all inherited sources are hidden', () => {
|
||||
expect(hasGloballyShownWorktreeVisibilitySource(repo(), { external: 'hide' })).toBe(false)
|
||||
})
|
||||
|
||||
it('detects an inherited custom source enabled in global settings', () => {
|
||||
expect(
|
||||
hasGloballyShownWorktreeVisibilitySource(repo(), {
|
||||
external: 'hide',
|
||||
customSources: [{ id: 'team', rootPath: '/srv/team' }],
|
||||
sourcePreferences: { custom: { team: 'show' } }
|
||||
})
|
||||
).toBe(true)
|
||||
})
|
||||
})
|
||||
@@ -5,6 +5,7 @@ import type { Repo, WorktreeVisibilityDefaults } from '../../../../shared/types'
|
||||
import {
|
||||
effectiveDefaultBuiltInWorktreeSourceVisibility,
|
||||
effectiveDefaultCustomWorktreeSourceVisibility,
|
||||
normalizeCustomWorktreeVisibilitySources,
|
||||
normalizeWorktreeVisibilitySourcePreferences
|
||||
} from '../../../../shared/worktree-visibility-sources'
|
||||
import type { WorktreeVisibilitySourceRow } from './WorktreeVisibilitySourceList'
|
||||
@@ -14,6 +15,37 @@ type SourceProvenance = {
|
||||
globalEnabled?: boolean
|
||||
}
|
||||
|
||||
export function hasGloballyShownWorktreeVisibilitySource(
|
||||
repo: Repo,
|
||||
visibilityDefaults: WorktreeVisibilityDefaults | undefined
|
||||
): boolean {
|
||||
const defaults = visibilityDefaults ?? {}
|
||||
const repoCustomSourceIds = new Set(
|
||||
normalizeCustomWorktreeVisibilitySources(repo.customWorktreeVisibilitySources)?.map(
|
||||
(source) => source.id
|
||||
) ?? []
|
||||
)
|
||||
const sources: WorktreeVisibilitySourceRow[] = [
|
||||
{ kind: 'built-in', id: 'claude' },
|
||||
{ kind: 'built-in', id: 'gsd' },
|
||||
...(normalizeCustomWorktreeVisibilitySources(defaults.customSources) ?? []).map((source) => ({
|
||||
kind: 'custom' as const,
|
||||
source
|
||||
})),
|
||||
{ kind: 'other' }
|
||||
]
|
||||
|
||||
return sources.some((source) => {
|
||||
const provenance = getWorktreeVisibilitySourceProvenance(
|
||||
repo,
|
||||
source,
|
||||
defaults,
|
||||
repoCustomSourceIds
|
||||
)
|
||||
return provenance?.kind === 'global' && provenance.globalEnabled === true
|
||||
})
|
||||
}
|
||||
|
||||
export function getWorktreeVisibilitySourceProvenance(
|
||||
repo: Repo | undefined,
|
||||
source: WorktreeVisibilitySourceRow,
|
||||
|
||||
Reference in New Issue
Block a user