diff options
| author | adamelmore <[email protected]> | 2026-01-25 07:58:24 -0600 |
|---|---|---|
| committer | adamelmore <[email protected]> | 2026-01-25 10:30:10 -0600 |
| commit | 2b07291e17856a2b014537542f79cc8c059487c9 (patch) | |
| tree | 8fdcc4be0692245c634dc0c8f61ef8bc4a8fa169 /packages/app/src | |
| parent | d25120680dea60b4231f12b266dc733089f3e181 (diff) | |
| download | opencode-2b07291e17856a2b014537542f79cc8c059487c9.tar.gz opencode-2b07291e17856a2b014537542f79cc8c059487c9.zip | |
fix(app): scroll to comment on click
Diffstat (limited to 'packages/app/src')
| -rw-r--r-- | packages/app/src/components/prompt-input.tsx | 7 | ||||
| -rw-r--r-- | packages/app/src/pages/session.tsx | 42 |
2 files changed, 47 insertions, 2 deletions
diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index ccff04efe..5ec0eb1ea 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -185,23 +185,26 @@ export const PromptInput: Component<PromptInputProps> = (props) => { const openComment = (item: { path: string; commentID?: string; commentOrigin?: "review" | "file" }) => { if (!item.commentID) return - comments.setFocus({ file: item.path, id: item.commentID }) - comments.setActive({ file: item.path, id: item.commentID }) + const focus = { file: item.path, id: item.commentID } + comments.setActive(focus) view().reviewPanel.open() if (item.commentOrigin === "review") { tabs().open("review") + requestAnimationFrame(() => comments.setFocus(focus)) return } if (item.commentOrigin !== "file" && commentInReview(item.path)) { tabs().open("review") + requestAnimationFrame(() => comments.setFocus(focus)) return } const tab = files.tab(item.path) tabs().open(tab) files.load(item.path) + requestAnimationFrame(() => comments.setFocus(focus)) } const recent = createMemo(() => { diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 2016870e1..5f743dcba 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -1860,6 +1860,7 @@ export default function Page() { let scrollFrame: number | undefined let pending: { x: number; y: number } | undefined let codeScroll: HTMLElement[] = [] + let focusToken = 0 const path = createMemo(() => file.pathFromTab(tab)) const state = createMemo(() => { @@ -2036,9 +2037,50 @@ export default function Page() { const target = fileComments().find((comment) => comment.id === focus.id) if (!target) return + focusToken++ + const token = focusToken + setOpenedComment(target.id) setCommenting(null) file.setSelectedLines(p, target.selection) + + const scrollTo = (attempt: number) => { + if (token !== focusToken) return + + const root = scroll + if (!root) { + if (attempt >= 120) return + requestAnimationFrame(() => scrollTo(attempt + 1)) + return + } + + const anchor = root.querySelector(`[data-comment-id="${target.id}"]`) + const ready = + anchor instanceof HTMLElement && + anchor.style.pointerEvents !== "none" && + anchor.style.opacity !== "0" + + const shadow = getRoot() + const marker = shadow ? findMarker(shadow, target.selection) : undefined + const node = (ready ? anchor : (marker ?? wrap)) as HTMLElement | undefined + if (!node) { + if (attempt >= 120) return + requestAnimationFrame(() => scrollTo(attempt + 1)) + return + } + + const rootRect = root.getBoundingClientRect() + const targetRect = node.getBoundingClientRect() + const offset = targetRect.top - rootRect.top + const next = root.scrollTop + offset - rootRect.height / 2 + targetRect.height / 2 + root.scrollTop = Math.max(0, next) + + if (ready || marker) return + if (attempt >= 120) return + requestAnimationFrame(() => scrollTo(attempt + 1)) + } + + requestAnimationFrame(() => scrollTo(0)) requestAnimationFrame(() => comments.clearFocus()) }) |
