diff options
| author | Shoubhit Dash <[email protected]> | 2026-03-23 12:55:30 +0530 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-03-23 07:25:30 +0000 |
| commit | 5ea95451dd485b15696877a9dd82c30a532b68e0 (patch) | |
| tree | 3adca097c59f528e3640e30eeabdd7ff4a686011 | |
| parent | 9239d877b9602a5a80e9e69e744abfe011f5f991 (diff) | |
| download | opencode-5ea95451dd485b15696877a9dd82c30a532b68e0.tar.gz opencode-5ea95451dd485b15696877a9dd82c30a532b68e0.zip | |
fix(app): prevent stale session hover preview on refocus (#18727)
| -rw-r--r-- | packages/app/src/pages/layout.tsx | 18 | ||||
| -rw-r--r-- | packages/app/src/pages/layout/sidebar-items.tsx | 65 |
2 files changed, 54 insertions, 29 deletions
diff --git a/packages/app/src/pages/layout.tsx b/packages/app/src/pages/layout.tsx index 0c10cc89b..88572503f 100644 --- a/packages/app/src/pages/layout.tsx +++ b/packages/app/src/pages/layout.tsx @@ -211,13 +211,22 @@ export default function Layout(props: ParentProps) { onMount(() => { const stop = () => setState("sizing", false) + const blur = () => reset() + const hide = () => { + if (document.visibilityState !== "hidden") return + reset() + } window.addEventListener("pointerup", stop) window.addEventListener("pointercancel", stop) window.addEventListener("blur", stop) + window.addEventListener("blur", blur) + document.addEventListener("visibilitychange", hide) onCleanup(() => { window.removeEventListener("pointerup", stop) window.removeEventListener("pointercancel", stop) window.removeEventListener("blur", stop) + window.removeEventListener("blur", blur) + document.removeEventListener("visibilitychange", hide) }) }) @@ -237,6 +246,12 @@ export default function Layout(props: ParentProps) { navLeave.current = undefined } + const reset = () => { + disarm() + setState("hoverSession", undefined) + setHoverProject(undefined) + } + const arm = () => { if (layout.sidebar.opened()) return if (state.hoverProject === undefined) return @@ -305,8 +320,7 @@ export default function Layout(props: ParentProps) { const clearSidebarHoverState = () => { if (layout.sidebar.opened()) return - setState("hoverSession", undefined) - setHoverProject(undefined) + reset() } const navigateWithSidebarReset = (href: string) => { diff --git a/packages/app/src/pages/layout/sidebar-items.tsx b/packages/app/src/pages/layout/sidebar-items.tsx index f8e16f3e1..a9627c5db 100644 --- a/packages/app/src/pages/layout/sidebar-items.tsx +++ b/packages/app/src/pages/layout/sidebar-items.tsx @@ -157,34 +157,45 @@ const SessionHoverPreview = (props: { messageLabel: (message: Message) => string | undefined onMessageSelect: (message: Message) => void trigger: JSX.Element -}): JSX.Element => ( - <HoverCard - openDelay={1000} - closeDelay={props.sidebarHovering() ? 600 : 0} - placement="right-start" - gutter={16} - shift={-2} - trigger={props.trigger} - open={props.hoverSession() === props.session.id} - onOpenChange={(open) => props.setHoverSession(open ? props.session.id : undefined)} - > - <Show - when={props.hoverReady()} - fallback={<div class="text-12-regular text-text-weak">{props.language.t("session.messages.loading")}</div>} +}): JSX.Element => { + let ref: HTMLDivElement | undefined + + return ( + <HoverCard + openDelay={1000} + closeDelay={props.sidebarHovering() ? 600 : 0} + placement="right-start" + gutter={16} + shift={-2} + trigger={<div ref={ref}>{props.trigger}</div>} + open={props.hoverSession() === props.session.id} + onOpenChange={(open) => { + if (!open) { + props.setHoverSession(undefined) + return + } + if (!ref?.matches(":hover")) return + props.setHoverSession(props.session.id) + }} > - <div class="overflow-y-auto overflow-x-hidden max-h-72 h-full"> - <MessageNav - messages={props.hoverMessages() ?? []} - current={undefined} - getLabel={props.messageLabel} - onMessageSelect={props.onMessageSelect} - size="normal" - class="w-60" - /> - </div> - </Show> - </HoverCard> -) + <Show + when={props.hoverReady()} + fallback={<div class="text-12-regular text-text-weak">{props.language.t("session.messages.loading")}</div>} + > + <div class="overflow-y-auto overflow-x-hidden max-h-72 h-full"> + <MessageNav + messages={props.hoverMessages() ?? []} + current={undefined} + getLabel={props.messageLabel} + onMessageSelect={props.onMessageSelect} + size="normal" + class="w-60" + /> + </div> + </Show> + </HoverCard> + ) +} export const SessionItem = (props: SessionItemProps): JSX.Element => { const params = useParams() |
