mirror of
https://github.com/stablyai/orca.git
synced 2026-11-03 10:37:35 +00:00
fix: dismiss chat naming error card before opening settings (#34655)
This commit is contained in:
@@ -50,7 +50,11 @@ function ChatTab(): React.JSX.Element {
|
||||
title="Repair the login flow"
|
||||
icon={<span />}
|
||||
programName="Claude"
|
||||
alert={naming ? <NativeChatNamingErrorBlock naming={naming} /> : undefined}
|
||||
alert={
|
||||
naming
|
||||
? (dismiss) => <NativeChatNamingErrorBlock naming={naming} onDismiss={dismiss} />
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
<button>chat tab</button>
|
||||
</TabHoverCard>
|
||||
@@ -95,15 +99,6 @@ describe('chat tab naming failure', () => {
|
||||
expect(screen.getAllByRole('button', { name: 'view error' }).length).toBeGreaterThan(0)
|
||||
const settingsButtons = screen.queryAllByRole('button', { name: 'Settings' })
|
||||
expect(settingsButtons.length > 0).toBe(!web)
|
||||
if (!web) {
|
||||
fireEvent.click(settingsButtons[0])
|
||||
expect(settings.openSettingsPage).toHaveBeenCalledOnce()
|
||||
expect(settings.openSettingsTarget).toHaveBeenCalledExactlyOnceWith({
|
||||
pane: 'chat',
|
||||
repoId: null,
|
||||
sectionId: 'chat-names'
|
||||
})
|
||||
}
|
||||
const regenerate = screen.queryAllByRole('button', { name: 'Regenerate name' })
|
||||
expect(regenerate.length > 0).toBe(supported)
|
||||
if (supported) {
|
||||
@@ -122,6 +117,25 @@ describe('chat tab naming failure', () => {
|
||||
await act(async () => acceptance.resolve(true))
|
||||
expect(screen.queryAllByRole('button', { name: 'Regenerating…' })).toHaveLength(0)
|
||||
}
|
||||
if (!web) {
|
||||
settings.openSettingsPage.mockImplementationOnce(() => {
|
||||
expect(screen.queryByText("Couldn't name this chat")).toBeNull()
|
||||
})
|
||||
fireEvent.click(settingsButtons[0])
|
||||
expect(screen.queryByText("Couldn't name this chat")).toBeNull()
|
||||
expect(settings.openSettingsPage).toHaveBeenCalledOnce()
|
||||
expect(settings.openSettingsTarget).toHaveBeenCalledExactlyOnceWith({
|
||||
pane: 'chat',
|
||||
repoId: null,
|
||||
sectionId: 'chat-names'
|
||||
})
|
||||
fireEvent.pointerLeave(screen.getByRole('button', { name: 'chat tab' }))
|
||||
fireEvent.pointerMove(screen.getByRole('button', { name: 'chat tab' }), {
|
||||
pointerType: 'mouse'
|
||||
})
|
||||
act(() => vi.advanceTimersByTime(TAB_TOOLTIP_DELAY_MS))
|
||||
expect(screen.getAllByText("Couldn't name this chat").length).toBeGreaterThan(0)
|
||||
}
|
||||
}
|
||||
)
|
||||
})
|
||||
|
||||
@@ -13,9 +13,11 @@ function regenerateLabel(naming: NativeChatNamingFailureControls): string {
|
||||
}
|
||||
|
||||
export function NativeChatNamingErrorBlock({
|
||||
naming
|
||||
naming,
|
||||
onDismiss
|
||||
}: {
|
||||
naming: NativeChatNamingFailureControls
|
||||
onDismiss?: () => void
|
||||
}): React.JSX.Element {
|
||||
return (
|
||||
<div className="space-y-1 border-t border-border pt-2" data-tab-hover-card-naming-error>
|
||||
@@ -57,6 +59,7 @@ export function NativeChatNamingErrorBlock({
|
||||
variant="ghost"
|
||||
size="chip"
|
||||
onClick={() => {
|
||||
onDismiss?.()
|
||||
const store = useAppStore.getState()
|
||||
store.openSettingsPage()
|
||||
store.openSettingsTarget({ pane: 'chat', repoId: null, sectionId: 'chat-names' })
|
||||
|
||||
@@ -223,12 +223,8 @@ export default function SortableTab({
|
||||
dragListeners?.onPointerDown as ((event: React.PointerEvent<Element>) => void) | undefined
|
||||
)
|
||||
}}
|
||||
onMouseDown={(e) => {
|
||||
// Why: block middle-click auto-scroll; don't close here — removing the element pre-mouseup triggers a Linux X11 paste.
|
||||
if (e.button === 1) {
|
||||
e.preventDefault()
|
||||
}
|
||||
}}
|
||||
// Why: block middle-click auto-scroll; don't close here — removing the element pre-mouseup triggers a Linux X11 paste.
|
||||
onMouseDown={preventMiddleButtonDefault}
|
||||
onMouseUp={preventMiddleButtonDefault}
|
||||
onAuxClick={(e) => {
|
||||
if (isEditing) {
|
||||
@@ -390,7 +386,11 @@ export default function SortableTab({
|
||||
progress={programProgress}
|
||||
/>
|
||||
}
|
||||
alert={naming ? <NativeChatNamingErrorBlock naming={naming} /> : undefined}
|
||||
alert={
|
||||
naming
|
||||
? (dismiss) => <NativeChatNamingErrorBlock naming={naming} onDismiss={dismiss} />
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{tabRoot}
|
||||
</TabHoverCard>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { ReactNode, SyntheticEvent } from 'react'
|
||||
import { useState, type ReactNode, type SyntheticEvent } from 'react'
|
||||
import { flushSync } from 'react-dom'
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
|
||||
|
||||
export function TabHoverCard({
|
||||
@@ -15,11 +16,14 @@ export function TabHoverCard({
|
||||
programName: string
|
||||
description?: string
|
||||
/** Controls below the program row; the card then stays open under the pointer. */
|
||||
alert?: ReactNode
|
||||
alert?: ReactNode | ((dismiss: () => void) => ReactNode)
|
||||
}): React.JSX.Element {
|
||||
const [open, setOpen] = useState(false)
|
||||
// Remove the portal before navigation can start rendering a slower destination.
|
||||
const dismiss = () => flushSync(() => setOpen(false))
|
||||
const interactive = alert !== undefined && alert !== null
|
||||
return (
|
||||
<Tooltip disableHoverableContent={!interactive}>
|
||||
<Tooltip open={open} onOpenChange={setOpen} disableHoverableContent={!interactive}>
|
||||
<TooltipTrigger
|
||||
asChild
|
||||
onFocus={(event) => {
|
||||
@@ -61,7 +65,7 @@ export function TabHoverCard({
|
||||
</span>
|
||||
<span className="min-w-0 break-all">{programName}</span>
|
||||
</div>
|
||||
{alert}
|
||||
{typeof alert === 'function' ? alert(dismiss) : alert}
|
||||
</div>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
Reference in New Issue
Block a user