mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-25 14:53:32 +08:00
commit
bf82a29b60
@ -38,6 +38,7 @@ vi.mock('../../i18n', () => ({
|
|||||||
'permMode.permShell': 'Run shell commands',
|
'permMode.permShell': 'Run shell commands',
|
||||||
'permMode.permPackages': 'Install packages',
|
'permMode.permPackages': 'Install packages',
|
||||||
'permMode.enableBypassBtn': 'Enable bypass',
|
'permMode.enableBypassBtn': 'Enable bypass',
|
||||||
|
'permMode.disabledDuringTurn': 'Cannot switch permissions while session is active',
|
||||||
'common.cancel': 'Cancel',
|
'common.cancel': 'Cancel',
|
||||||
'tabs.close': 'Close',
|
'tabs.close': 'Close',
|
||||||
}[key] ?? key),
|
}[key] ?? key),
|
||||||
@ -159,4 +160,46 @@ describe('PermissionModeSelector', () => {
|
|||||||
expect(screen.getByText('C:\\Users\\LinTan\\MyScript\\test5')).toBeInTheDocument()
|
expect(screen.getByText('C:\\Users\\LinTan\\MyScript\\test5')).toBeInTheDocument()
|
||||||
expect(screen.queryByText('C:\\Users\\LinTan')).not.toBeInTheDocument()
|
expect(screen.queryByText('C:\\Users\\LinTan')).not.toBeInTheDocument()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('disables the trigger button when the session turn is active', () => {
|
||||||
|
const setSessionPermissionMode = vi.fn()
|
||||||
|
useChatStore.setState({
|
||||||
|
setSessionPermissionMode,
|
||||||
|
sessions: {
|
||||||
|
'current-tab': { chatState: 'thinking' },
|
||||||
|
},
|
||||||
|
} as Partial<ReturnType<typeof useChatStore.getState>>)
|
||||||
|
useSessionStore.setState({
|
||||||
|
activeSessionId: 'current-tab',
|
||||||
|
sessions: [
|
||||||
|
{
|
||||||
|
id: 'current-tab',
|
||||||
|
title: 'Current',
|
||||||
|
createdAt: '2026-05-24T00:00:00.000Z',
|
||||||
|
modifiedAt: '2026-05-24T00:00:00.000Z',
|
||||||
|
messageCount: 1,
|
||||||
|
projectPath: '/repo',
|
||||||
|
projectRoot: '/repo',
|
||||||
|
workDir: '/repo',
|
||||||
|
workDirExists: true,
|
||||||
|
permissionMode: 'default',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
useTabStore.setState({
|
||||||
|
activeTabId: 'current-tab',
|
||||||
|
tabs: [{ sessionId: 'current-tab', title: 'Current', type: 'session', status: 'idle' }],
|
||||||
|
})
|
||||||
|
|
||||||
|
render(<PermissionModeSelector />)
|
||||||
|
|
||||||
|
const trigger = screen.getByRole('button', { name: 'Ask permissions' })
|
||||||
|
expect(trigger).toBeDisabled()
|
||||||
|
expect(trigger).toHaveAttribute('title', 'Cannot switch permissions while session is active')
|
||||||
|
|
||||||
|
fireEvent.click(trigger)
|
||||||
|
// Menu should not open when disabled
|
||||||
|
expect(screen.queryByRole('menu')).not.toBeInTheDocument()
|
||||||
|
expect(setSessionPermissionMode).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@ -36,6 +36,10 @@ export function PermissionModeSelector({ workDir: workDirProp, compact = false,
|
|||||||
const setSessionPermissionMode = useChatStore((s) => s.setSessionPermissionMode)
|
const setSessionPermissionMode = useChatStore((s) => s.setSessionPermissionMode)
|
||||||
const activeTabId = useTabStore((s) => s.activeTabId)
|
const activeTabId = useTabStore((s) => s.activeTabId)
|
||||||
const sessions = useSessionStore((s) => s.sessions)
|
const sessions = useSessionStore((s) => s.sessions)
|
||||||
|
const chatState = useChatStore((s) =>
|
||||||
|
activeTabId ? s.sessions[activeTabId]?.chatState ?? 'idle' : 'idle',
|
||||||
|
)
|
||||||
|
const isTurnActive = chatState !== 'idle'
|
||||||
const [open, setOpen] = useState(false)
|
const [open, setOpen] = useState(false)
|
||||||
const [confirmDialog, setConfirmDialog] = useState(false)
|
const [confirmDialog, setConfirmDialog] = useState(false)
|
||||||
const ref = useRef<HTMLDivElement>(null)
|
const ref = useRef<HTMLDivElement>(null)
|
||||||
@ -179,15 +183,16 @@ export function PermissionModeSelector({ workDir: workDirProp, compact = false,
|
|||||||
return (
|
return (
|
||||||
<div ref={ref} className="relative">
|
<div ref={ref} className="relative">
|
||||||
<button
|
<button
|
||||||
onClick={() => setOpen(!open)}
|
onClick={() => { if (!isTurnActive) setOpen(!open) }}
|
||||||
|
disabled={isTurnActive}
|
||||||
aria-label={MODE_LABELS[currentMode]}
|
aria-label={MODE_LABELS[currentMode]}
|
||||||
aria-haspopup="menu"
|
aria-haspopup="menu"
|
||||||
aria-expanded={open}
|
aria-expanded={open}
|
||||||
aria-controls={open ? menuId : undefined}
|
aria-controls={open ? menuId : undefined}
|
||||||
title={compact ? MODE_LABELS[currentMode] : undefined}
|
title={isTurnActive ? t('permMode.disabledDuringTurn') : (compact ? MODE_LABELS[currentMode] : undefined)}
|
||||||
className={`flex items-center bg-[var(--color-surface-container-low)] font-medium text-[var(--color-text-secondary)] transition-colors hover:bg-[var(--color-surface-hover)] ${
|
className={`flex items-center bg-[var(--color-surface-container-low)] font-medium text-[var(--color-text-secondary)] transition-colors ${
|
||||||
compactButtonClass
|
isTurnActive ? 'opacity-50 cursor-not-allowed' : 'hover:bg-[var(--color-surface-hover)]'
|
||||||
}`}
|
} ${compactButtonClass}`}
|
||||||
>
|
>
|
||||||
<span className="material-symbols-outlined text-[14px]">{MODE_ICONS[currentMode]}</span>
|
<span className="material-symbols-outlined text-[14px]">{MODE_ICONS[currentMode]}</span>
|
||||||
{!compact && (
|
{!compact && (
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user