fix: stop link preview flicker on hover within nested anchors - #246
fix: stop link preview flicker on hover within nested anchors#246P-CAmilE wants to merge 1 commit into
Conversation
| function onMouseOver(event) { | ||
| const anchor = event.target.closest && event.target.closest('a[href]'); | ||
| const anchor = currentAnchor(event.target); | ||
| postHover(anchor ? anchor.href : ''); | ||
| } |
There was a problem hiding this comment.
onMouseOver still posts redundant bridge messages within the same anchor
onMouseOut now correctly suppresses posts when the anchor stays the same, but onMouseOver unconditionally posts for every child element transition. Moving the cursor across <a href="/foo"><img/><span>text</span></a> produces a mouseover on <img> and then on <span>, both resolving to the same anchor and both issuing a postHover("/foo"). Each call reaches the native side, assigns hoveredLinkURL to an equal string, and triggers objectWillChange — the visual flicker is gone (thanks to the onMouseOut fix), but the redundant IPC can be eliminated by tracking the last-posted anchor reference in JS and early-returning when it hasn't changed.
Problem
Hovering a link showed the bottom-left URL preview flickering. The preview would briefly disappear and reappear while the cursor moved within the same link (especially links with nested child elements like
<img>/<span>), and would linger or clear inconsistently when leaving a link.Root cause
The injected hover script in
OraBrowserScripts.swiftusedmouseover/mouseout(which bubble) registered ondocumentwith capture, but the leave handler compared againstevent.currentTarget— which is alwaysdocument— sodocument.contains(relatedTarget)was almost always true and provided no real signal for "still inside the same anchor". The clear path only fired whenrelatedTargetwasnull(leaving the window, entering an iframe, hitting native controls), so moving between nested children of the same<a>produced alternatingmouseout-clear /mouseover-reset messages to the native side →@Published hoveredLinkURLtoggled →LinkPreviewflashed.A secondary issue:
BrowserWebContentViewhad noanimation(value:)keyed tohoveredLinkURL, so theLinkPreview's.transition(.opacity)never engaged — appearance/disappearance was a hard cut, amplifying the visual flicker.Fix
ora/Core/BrowserEngine/Scripts/OraBrowserScripts.swift(root cause)Compare the from and to anchor via
closest('a[href]')on bothevent.targetandevent.relatedTarget. Only post alinkHovermessage when the enclosing anchor actually changes:from === to→ no message → no flicker.mouseoveron a non-link area).ora/Features/Browser/Views/BrowserWebContentView.swift(visual polish)Add
.animation(.easeOut(duration: 0.12), value: tab.hoveredLinkURL)to theBrowserPageViewoverlay chain soLinkPreview's existing.transition(.opacity)actually engages — fade in/out instead of a hard cut.Verification
xcodebuild build -scheme ora -destination "platform=macOS" -project Ora.xcodeproj CODE_SIGNING_ALLOWED=NO→ BUILD SUCCEEDEDNotes
TabBrowserPageDelegate.swift— itshoveredLinkURLassignment is correct; equal values on@Publisheddon't trigger re-renders.mouseenter/mouseleave— they don't bubble, so they can't be delegated ondocumentand would require per-anchor listeners (more code, more complexity for no gain).