Skip to content

Commit 3ab3459

Browse files
authored
fix(desktop-browser): keep error-page focus recovery inside the browser and route hard reload through recovery (#8442)
* fix(desktop-browser): keep error-page focus recovery inside the browser and route hard reload through recovery * fix(desktop-browser): recover issue-page focus only when nothing holds focus, and keep cache bypass except for hung pages * fix(desktop-browser): retry the failed URL when hard reloading a load error
1 parent 69326d2 commit 3ab3459

4 files changed

Lines changed: 30 additions & 19 deletions

File tree

‎apps/desktop/src/main/browser-agent/session.ts‎

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2012,6 +2012,22 @@ export function reloadPage(contents: WebContents): void {
20122012
contents.reload()
20132013
}
20142014

2015+
/**
2016+
* Reloads past the HTTP cache, the browser's Shift-reload. A failed or hung
2017+
* page takes the plain reload's recovery instead: a load error retries the
2018+
* URL that failed, which need not be the committed page, and a hung renderer
2019+
* must be restarted, since reloading it in place waits on the hung page.
2020+
*/
2021+
function hardReloadPage(contents: WebContents): void {
2022+
const issue = tabForContents(contents)?.pageIssue
2023+
if (issue?.kind === 'load-error' || issue?.kind === 'unresponsive') {
2024+
reloadPage(contents)
2025+
return
2026+
}
2027+
prepareExplicitNavigation(contents)
2028+
contents.reloadIgnoringCache()
2029+
}
2030+
20152031
/** Hands one page selection to the exact app window and chat hosting its tab. */
20162032
function addPageSelectionToChat(contents: WebContents, text: string): void {
20172033
if (!text.trim() || getBrowserScopeId() !== getActiveBrowserScopeId()) return
@@ -2494,8 +2510,7 @@ function initializeTabView(
24942510
return
24952511
}
24962512
if (shortcut === 'hard-reload') {
2497-
prepareExplicitNavigation(contents)
2498-
contents.reloadIgnoringCache()
2513+
hardReloadPage(contents)
24992514
return
25002515
}
25012516

@@ -3512,8 +3527,7 @@ export function handleFocusedShortcut(
35123527
reloadPage(shortcutTab.view.webContents)
35133528
return true
35143529
case 'hard-reload':
3515-
prepareExplicitNavigation(shortcutTab.view.webContents)
3516-
shortcutTab.view.webContents.reloadIgnoringCache()
3530+
hardReloadPage(shortcutTab.view.webContents)
35173531
return true
35183532
case 'back':
35193533
goBack(shortcutTab.view.webContents)

‎apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-content/components/browser-session/browser-find-bar.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ export function BrowserFindBar({ inputRef, onClose, scopeId }: BrowserFindBarPro
142142
// The panel and the global command layer both listen for these.
143143
event.stopPropagation()
144144
// Keys during an IME composition edit the composed text.
145-
if (event.nativeEvent.isComposing) return
145+
if (event.nativeEvent.isComposing || event.nativeEvent.keyCode === 229) return
146146
if (event.key === 'Escape') {
147147
event.preventDefault()
148148
dismiss()

‎apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-content/components/browser-session/browser-page-issue.tsx‎

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -125,17 +125,15 @@ export function browserPageIssueCopy(issue: BrowserPageIssue): BrowserPageIssueC
125125
}
126126
}
127127

128-
function isEditingOutside(heading: HTMLElement | null): boolean {
128+
/**
129+
* Whether nothing in Sim holds focus, as when it was in the native page that
130+
* just failed. Any focused element, from the chat composer to the omnibox,
131+
* keeps it. `document.activeElement` survives a window blur, so a caret left
132+
* in chat still counts.
133+
*/
134+
function isFocusFree(): boolean {
129135
const active = document.activeElement
130-
// activeElement survives a window blur, so a caret left in chat still counts.
131-
if (!(active instanceof HTMLElement)) return false
132-
const section = heading?.closest('section')
133-
if (section?.contains(active)) return false
134-
return (
135-
active.isContentEditable ||
136-
active instanceof HTMLInputElement ||
137-
active instanceof HTMLTextAreaElement
138-
)
136+
return !active || active === document.body
139137
}
140138

141139
/** Replaces a hidden native page and optionally claims renderer focus for keyboard recovery. */
@@ -144,9 +142,8 @@ export function BrowserPageIssueView({ issue, onReload, focusRecovery }: Browser
144142
const copy = browserPageIssueCopy(issue)
145143

146144
useEffect(() => {
147-
// Keyboard recovery for someone who was in the page; a caret in chat or
148-
// any other Sim field stays where it is.
149-
if (focusRecovery && !isEditingOutside(headingRef.current)) headingRef.current?.focus()
145+
// Keyboard recovery for someone who was in the browser.
146+
if (focusRecovery && isFocusFree()) headingRef.current?.focus()
150147
}, [focusRecovery, issue])
151148

152149
const Icon = issue.kind === 'load-error' ? Globe : CircleAlert

‎apps/sim/app/workspace/[workspaceId]/home/components/mothership-view/components/resource-content/components/browser-session/browser-session.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1157,7 +1157,7 @@ export function BrowserSession({
11571157
onKeyDown={(event) => {
11581158
event.stopPropagation()
11591159
// Keys during an IME composition edit the composed text, not the URL.
1160-
if (event.nativeEvent.isComposing) return
1160+
if (event.nativeEvent.isComposing || event.nativeEvent.keyCode === 229) return
11611161
if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
11621162
// Never move a highlight through a list that is not on screen.
11631163
if (!suggestionsOpen) return

0 commit comments

Comments
 (0)