fix sticky browser issue

This commit is contained in:
Arjun 2026-05-05 11:41:08 +05:30
parent 0bd234ddf6
commit a76f8bae14
3 changed files with 58 additions and 17 deletions

View file

@ -2400,6 +2400,10 @@ function App() {
}
}, [runId])
const dismissBrowserOverlay = useCallback(() => {
setIsBrowserOpen(false)
}, [])
const handleNewChat = useCallback(() => {
// Invalidate any in-flight run loads (rapid switching can otherwise "pop" old conversations back in)
loadRunRequestIdRef.current += 1
@ -2623,6 +2627,7 @@ function App() {
// File tab operations
const openFileInNewTab = useCallback((path: string) => {
dismissBrowserOverlay()
const existingTab = fileTabs.find(t => t.path === path)
if (existingTab) {
setActiveFileTabId(existingTab.id)
@ -2635,11 +2640,12 @@ function App() {
setActiveFileTabId(id)
setIsGraphOpen(false)
setSelectedPath(path)
}, [fileTabs])
}, [fileTabs, dismissBrowserOverlay])
const switchFileTab = useCallback((tabId: string) => {
const tab = fileTabs.find(t => t.id === tabId)
if (!tab) return
dismissBrowserOverlay()
setActiveFileTabId(tabId)
setSelectedBackgroundTask(null)
setExpandedFrom(null)
@ -2662,7 +2668,7 @@ function App() {
setIsGraphOpen(false)
setIsSuggestedTopicsOpen(false)
setSelectedPath(tab.path)
}, [fileTabs, isRightPaneMaximized])
}, [fileTabs, isRightPaneMaximized, dismissBrowserOverlay])
const closeFileTab = useCallback((tabId: string) => {
const closingTab = fileTabs.find(t => t.id === tabId)
@ -2736,6 +2742,7 @@ function App() {
setChatTabs(prev => [...prev, { id, runId: null }])
setActiveChatTabId(id)
}
dismissBrowserOverlay()
handleNewChat()
// Left-pane "new chat" should always open full chat view.
if (selectedPath || isGraphOpen || isSuggestedTopicsOpen) {
@ -2747,7 +2754,7 @@ function App() {
setSelectedPath(null)
setIsGraphOpen(false)
setIsSuggestedTopicsOpen(false)
}, [chatTabs, activeChatTabId, handleNewChat, selectedPath, isGraphOpen, isSuggestedTopicsOpen])
}, [chatTabs, activeChatTabId, dismissBrowserOverlay, handleNewChat, selectedPath, isGraphOpen, isSuggestedTopicsOpen])
// Sidebar variant: create/switch chat tab without leaving file/graph context.
const handleNewChatTabInSidebar = useCallback(() => {
@ -2865,11 +2872,12 @@ function App() {
if (selectedPath || isGraphOpen || isSuggestedTopicsOpen) {
setExpandedFrom({ path: selectedPath, graph: isGraphOpen, suggestedTopics: isSuggestedTopicsOpen })
}
dismissBrowserOverlay()
setIsRightPaneMaximized(false)
setSelectedPath(null)
setIsGraphOpen(false)
setIsSuggestedTopicsOpen(false)
}, [selectedPath, isGraphOpen, isSuggestedTopicsOpen])
}, [selectedPath, isGraphOpen, isSuggestedTopicsOpen, dismissBrowserOverlay])
const handleCloseFullScreenChat = useCallback(() => {
if (expandedFrom) {
@ -3004,8 +3012,7 @@ function App() {
case 'chat':
setSelectedPath(null)
setIsGraphOpen(false)
// Don't touch isBrowserOpen here — chat navigation should land in
// the right sidebar when the browser overlay is active.
setIsBrowserOpen(false)
setExpandedFrom(null)
setIsRightPaneMaximized(false)
setSelectedBackgroundTask(null)
@ -3021,7 +3028,12 @@ function App() {
const navigateToView = useCallback(async (nextView: ViewState) => {
const current = currentViewState
if (viewStatesEqual(current, nextView)) return
if (viewStatesEqual(current, nextView)) {
if (isBrowserOpen) {
dismissBrowserOverlay()
}
return
}
cancelRecordingIfActive()
const nextHistory = {
@ -3030,7 +3042,7 @@ function App() {
}
setHistory(nextHistory)
await applyViewState(nextView)
}, [appendUnique, applyViewState, cancelRecordingIfActive, currentViewState, setHistory])
}, [appendUnique, applyViewState, cancelRecordingIfActive, currentViewState, setHistory, isBrowserOpen, dismissBrowserOverlay])
const navigateBack = useCallback(async () => {
const { back, forward } = historyRef.current
@ -4329,6 +4341,8 @@ function App() {
meetingSummarizing={meetingSummarizing}
meetingAvailable={voiceAvailable}
onToggleMeeting={() => { void handleToggleMeeting() }}
isSearchOpen={isSearchOpen}
isMeetingActionActive={showMeetingPermissions || meetingSummarizing || meetingTranscription.state !== 'idle'}
isBrowserOpen={isBrowserOpen}
onToggleBrowser={handleToggleBrowser}
isSuggestedTopicsOpen={isSuggestedTopicsOpen}
@ -4463,7 +4477,10 @@ function App() {
</ContentHeader>
{isBrowserOpen ? (
<BrowserPane onClose={handleCloseBrowser} />
<BrowserPane
onClose={handleCloseBrowser}
forceHidden={isSearchOpen || showMeetingPermissions}
/>
) : isSuggestedTopicsOpen ? (
<div className="flex-1 min-h-0 flex flex-col overflow-hidden">
<SuggestedTopicsView

View file

@ -49,6 +49,7 @@ const BLOCKING_OVERLAY_SLOTS = new Set([
interface BrowserPaneProps {
onClose: () => void
forceHidden?: boolean
}
const getActiveTab = (state: BrowserState) =>
@ -85,7 +86,7 @@ const getBrowserTabTitle = (tab: BrowserTabState) => {
}
}
export function BrowserPane({ onClose }: BrowserPaneProps) {
export function BrowserPane({ onClose, forceHidden = false }: BrowserPaneProps) {
const [state, setState] = useState<BrowserState>(EMPTY_STATE)
const [addressValue, setAddressValue] = useState('')
@ -175,6 +176,12 @@ export function BrowserPane({ onClose }: BrowserPaneProps) {
}, [])
const syncView = useCallback(() => {
if (forceHidden) {
lastBoundsRef.current = null
setViewVisible(false)
return null
}
const doc = viewportRef.current?.ownerDocument
if (doc && hasBlockingOverlay(doc)) {
lastBoundsRef.current = null
@ -191,7 +198,7 @@ export function BrowserPane({ onClose }: BrowserPaneProps) {
pushBounds(bounds)
setViewVisible(true)
return bounds
}, [measureBounds, pushBounds, setViewVisible])
}, [forceHidden, measureBounds, pushBounds, setViewVisible])
useEffect(() => {
syncView()

View file

@ -186,6 +186,8 @@ type SidebarContentPanelProps = {
meetingSummarizing?: boolean
meetingAvailable?: boolean
onToggleMeeting?: () => void
isSearchOpen?: boolean
isMeetingActionActive?: boolean
isBrowserOpen?: boolean
onToggleBrowser?: () => void
isSuggestedTopicsOpen?: boolean
@ -420,6 +422,8 @@ export function SidebarContentPanel({
meetingSummarizing = false,
meetingAvailable = false,
onToggleMeeting,
isSearchOpen = false,
isMeetingActionActive = false,
isBrowserOpen = false,
onToggleBrowser,
isSuggestedTopicsOpen = false,
@ -436,6 +440,9 @@ export function SidebarContentPanel({
const [loggingIn, setLoggingIn] = useState(false)
const [appUrl, setAppUrl] = useState<string | null>(null)
const { billing } = useBilling(isRowboatConnected)
const isMeetingQuickActionSelected = isMeetingActionActive
const isBrowserQuickActionSelected = isBrowserOpen && !isSearchOpen && !isMeetingQuickActionSelected
const isSuggestedTopicsQuickActionSelected = isSuggestedTopicsOpen && !isBrowserOpen
const handleRowboatLogin = useCallback(async () => {
try {
@ -533,7 +540,12 @@ export function SidebarContentPanel({
<button
type="button"
onClick={onOpenSearch}
className="flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground transition-colors"
className={cn(
"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors",
isSearchOpen
? "bg-sidebar-accent text-sidebar-accent-foreground"
: "text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"
)}
>
<SearchIcon className="size-4" />
<span>Search</span>
@ -546,9 +558,14 @@ export function SidebarContentPanel({
disabled={meetingState === 'connecting' || meetingState === 'stopping' || meetingSummarizing}
className={cn(
"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors disabled:pointer-events-none",
isMeetingQuickActionSelected
? "bg-sidebar-accent"
: "hover:bg-sidebar-accent",
meetingState === 'recording'
? "text-red-500 hover:bg-sidebar-accent"
: "text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"
? "text-red-500"
: isMeetingQuickActionSelected
? "text-sidebar-accent-foreground"
: "text-sidebar-foreground/80 hover:text-sidebar-accent-foreground"
)}
>
{meetingSummarizing || meetingState === 'connecting' ? (
@ -575,7 +592,7 @@ export function SidebarContentPanel({
onClick={onToggleBrowser}
className={cn(
"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors",
isBrowserOpen
isBrowserQuickActionSelected
? "bg-sidebar-accent text-sidebar-accent-foreground"
: "text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"
)}
@ -590,7 +607,7 @@ export function SidebarContentPanel({
onClick={onOpenSuggestedTopics}
className={cn(
"flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-sm transition-colors",
isSuggestedTopicsOpen
isSuggestedTopicsQuickActionSelected
? "bg-sidebar-accent text-sidebar-accent-foreground"
: "text-sidebar-foreground/80 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"
)}