diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index 5a367aa61..18c1d98a7 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -170,6 +170,36 @@ export const PromptInput: Component = (props) => { const tabs = createMemo(() => layout.tabs(sessionKey)) const view = createMemo(() => layout.view(sessionKey)) + const commentInReview = (path: string) => { + const sessionID = params.id + if (!sessionID) return false + + const diffs = sync.data.session_diff[sessionID] + if (!diffs) return false + return diffs.some((diff) => diff.file === path) + } + + const openComment = (item: { path: string; commentID?: string; commentOrigin?: "review" | "file" }) => { + if (!item.commentID) return + + comments.setFocus({ file: item.path, id: item.commentID }) + view().reviewPanel.open() + + if (item.commentOrigin === "review") { + tabs().open("review") + return + } + + if (item.commentOrigin !== "file" && commentInReview(item.path)) { + tabs().open("review") + return + } + + const tab = files.tab(item.path) + tabs().open(tab) + files.load(item.path) + } + const recent = createMemo(() => { const all = tabs().all() const active = tabs().active() @@ -1481,6 +1511,7 @@ export const PromptInput: Component = (props) => { selection: item.selection, comment: item.comment, commentID: item.commentID, + commentOrigin: item.commentOrigin, preview: item.preview, }) } @@ -1547,6 +1578,7 @@ export const PromptInput: Component = (props) => { selection: item.selection, comment: item.comment, commentID: item.commentID, + commentOrigin: item.commentOrigin, preview: item.preview, }) } @@ -1700,10 +1732,7 @@ export const PromptInput: Component = (props) => { "cursor-pointer hover:bg-surface-interactive-weak": !!item.commentID, }} onClick={() => { - if (!item.commentID) return - comments.setFocus({ file: item.path, id: item.commentID }) - view().reviewPanel.open() - tabs().open("review") + openComment(item) }} >
diff --git a/packages/app/src/context/prompt.tsx b/packages/app/src/context/prompt.tsx index 6b9d5cc0d..99fab6c19 100644 --- a/packages/app/src/context/prompt.tsx +++ b/packages/app/src/context/prompt.tsx @@ -44,6 +44,7 @@ export type FileContextItem = { selection?: FileSelection comment?: string commentID?: string + commentOrigin?: "review" | "file" preview?: string } diff --git a/packages/app/src/pages/session.tsx b/packages/app/src/pages/session.tsx index 2fc4ab62c..46b41d509 100644 --- a/packages/app/src/pages/session.tsx +++ b/packages/app/src/pages/session.tsx @@ -27,6 +27,7 @@ import { DiffChanges } from "@opencode-ai/ui/diff-changes" import { ResizeHandle } from "@opencode-ai/ui/resize-handle" import { Tabs } from "@opencode-ai/ui/tabs" import { useCodeComponent } from "@opencode-ai/ui/context/code" +import { LineCommentAnchor } from "@opencode-ai/ui/line-comment" import { SessionTurn } from "@opencode-ai/ui/session-turn" import { createAutoScroll } from "@opencode-ai/ui/hooks" import { SessionReview } from "@opencode-ai/ui/session-review" @@ -535,6 +536,7 @@ export default function Page() { selection: SelectedLineRange comment: string preview?: string + origin?: "review" | "file" }) => { const selection = selectionFromLines(input.selection) const preview = input.preview ?? selectionPreview(input.file, selection) @@ -549,6 +551,7 @@ export default function Page() { selection, comment: input.comment, commentID: saved.id, + commentOrigin: input.origin, preview, }) } @@ -1463,7 +1466,7 @@ export default function Page() { diffs={diffs} view={view} diffStyle="unified" - onLineComment={addCommentToContext} + onLineComment={(comment) => addCommentToContext({ ...comment, origin: "review" })} comments={comments.all()} focusedComment={comments.focus()} onFocusedCommentChange={comments.setFocus} @@ -1782,7 +1785,7 @@ export default function Page() { view={view} diffStyle={layout.review.diffStyle()} onDiffStyleChange={layout.review.setDiffStyle} - onLineComment={addCommentToContext} + onLineComment={(comment) => addCommentToContext({ ...comment, origin: "review" })} comments={comments.all()} focusedComment={comments.focus()} onFocusedCommentChange={comments.setFocus} @@ -1974,6 +1977,22 @@ export default function Page() { requestAnimationFrame(() => textarea?.focus()) }) + createEffect(() => { + const focus = comments.focus() + const p = path() + if (!focus || !p) return + if (focus.file !== p) return + if (activeTab() !== tab) return + + const target = fileComments().find((comment) => comment.id === focus.id) + if (!target) return + + setOpenedComment(target.id) + setCommenting(null) + file.setSelectedLines(p, target.selection) + requestAnimationFrame(() => comments.clearFocus()) + }) + const renderCode = (source: string, wrapperClass: string) => (
{ @@ -2016,125 +2035,109 @@ export default function Page() { /> {(comment) => ( -
{ + const p = path() + if (!p) return + file.setSelectedLines(p, comment.selection) + }} + onClick={() => { + const p = path() + if (!p) return + setCommenting(null) + setOpenedComment((current) => (current === comment.id ? null : comment.id)) + file.setSelectedLines(p, comment.selection) }} > - - -
-
-
- {comment.comment} -
-
- Comment on {commentLabel(comment.selection)} -
-
+
+
+ {comment.comment}
- -
+
+ Comment on {commentLabel(comment.selection)} +
+
+ )} {(range) => ( -
- -
{ - const target = e.relatedTarget as Node | null - if (!target || !e.currentTarget.contains(target)) { + textarea?.focus()} + onPopoverFocusOut={(e) => { + const target = e.relatedTarget as Node | null + if (!target || !e.currentTarget.contains(target)) { + setCommenting(null) + } + }} + > +
+