Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 17 additions & 66 deletions packages/kilo-vscode/tests/fixtures/inline-comment-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,80 +5,31 @@ import type { PRReviewRequest } from "../../src/shared/pr-comment-actions"
const { window, root, messages, node, button, input, type, last, respond, wait, mount } =
await harness<PRReviewRequest>()
const { PRCommentForm } = await import("../../webview-ui/agent-manager/pr/PRCommentForm")
const saved: string[] = []
const sent: string[] = []
let cancelled = 0
let completed = 0
let reads = 0
const initial = () => {
reads++
return ""
}
const release = mount(() => (
<>
<div id="local">
<PRCommentForm
inline
action="local"
worktreeId="inline-test"
file="example.ts"
side="RIGHT"
startLine={2}
endLine={2}
selectedText="return 1"
submitOnEnter
onSubmit={(body) => saved.push(body)}
onSend={(body) => sent.push(body)}
onCancel={() => cancelled++}
onEscape={() => cancelled++}
/>
</div>
<div id="remote">
<PRCommentForm
inline
action="line"
worktreeId="inline-test"
prNumber={1}
prUrl="https://github.com/example/fixture/pull/1"
snapshotId="snapshot"
path="example.ts"
side="RIGHT"
startLine={2}
endLine={2}
initialBody={initial()}
onSuccess={() => completed++}
onCancel={() => cancelled++}
/>
</div>
</>
<div id="remote">
<PRCommentForm
inline
action="line"
worktreeId="inline-test"
prNumber={1}
prUrl="https://github.com/example/fixture/pull/1"
snapshotId="snapshot"
path="example.ts"
side="RIGHT"
startLine={2}
endLine={2}
Comment thread
marius-kilocode marked this conversation as resolved.
onSuccess={() => completed++}
onCancel={() => cancelled++}
/>
</div>
))
await wait()
const local = node("#local")
const remote = node("#remote")
assert.equal(root.querySelector('[data-slot="comment-toolbar"]'), null, "no second toolbar in inline forms")
assert.equal(button("submit", local).textContent, "Save local")
assert.equal(button("send", local).textContent, "Send")
assert.equal(button("send", local).getAttribute("aria-label"), "Send to agent")
assert.equal(button("submit", remote).textContent, "Post to GitHub")
assert.equal(button("discard", remote).textContent, "Cancel")
const before = reads
type(local, "Preview **this**")
assert.equal(reads, before, "typing in one form does not invalidate unrelated drafts")
button("preview", local).click()
await wait()
assert.match(node('[data-slot="comment-preview"]', local).textContent ?? "", /Preview this/)
button("write", local).click()
assert.equal(document.activeElement, input(local))
input(local).dispatchEvent(new window.KeyboardEvent("keydown", { key: "Enter", shiftKey: true, bubbles: true }))
assert.equal(saved.length, 0, "Shift+Enter does not submit")
input(local).dispatchEvent(new window.KeyboardEvent("keydown", { key: "Enter", isComposing: true, bubbles: true }))
assert.equal(saved.length, 0, "IME confirmation does not submit")
input(local).dispatchEvent(new window.KeyboardEvent("keydown", { key: "Enter", bubbles: true }))
assert.deepEqual(saved, ["Preview **this**"])
assert.equal(messages.length, 0, "local save never requests a GitHub write")
type(local, "Send this")
button("send", local).click()
assert.deepEqual(sent, ["Send this"])
type(remote, "Review this line")
button("submit", remote).click()
const request = last()
Expand All @@ -92,7 +43,7 @@ assert.match(remote.textContent ?? "", /Snapshot changed/)
button("submit", remote).click()
respond(last(), {})
assert.equal(completed, 1)
button("cancel", local).click()
button("discard", remote).click()
assert.equal(cancelled, 1)
release()
await window.happyDOM.close()
90 changes: 16 additions & 74 deletions packages/kilo-vscode/webview-ui/agent-manager/pr/PRCommentForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,29 +27,10 @@ interface Draft {
type Props = {
projectId?: string
worktreeId: string
/** Submit on plain Enter. Diff composers keep their existing Enter-to-send behavior. */
submitOnEnter?: boolean
/** Called when Escape is pressed in the editor. */
onEscape?: () => void
inline?: boolean
} & (
| { action: "reply"; threadId: string }
| { action: "create"; prNumber: number; prUrl: string }
| {
projectId?: string
worktreeId: string
action: "local"
file: string
side: "LEFT" | "RIGHT"
startLine: number
endLine: number
selectedText: string
initialBody?: string
onBodyChange?: (body: string) => void
onSubmit: (body: string, selectedText: string) => void
onSend: (body: string, selectedText: string) => void
onCancel: () => void
}
| {
action: "diff"
worktreeId: string
Expand Down Expand Up @@ -119,7 +100,7 @@ const decisions = [
{ event: "REQUEST_CHANGES", action: "review-request-changes", label: "agentManager.pr.review.requestChanges" },
] as const

// The form supports local, inline, reply, edit, and review actions in one shared UI.
// The form supports diff, inline, reply, edit, and review actions in one shared UI.
Comment thread
marius-kilocode marked this conversation as resolved.
// eslint-disable-next-line complexity
export function PRCommentForm(props: Props) {
const { t } = useLanguage()
Expand All @@ -133,15 +114,9 @@ export function PRCommentForm(props: Props) {
props.projectId,
props.worktreeId,
props.action,
props.action === "reply"
? props.threadId
: props.action === "local" || props.action === "diff"
? props.file
: props.prUrl,
props.action === "reply" ? props.threadId : props.action === "diff" ? props.file : props.prUrl,
props.action === "edit" ? props.commentId : undefined,
props.action === "local" || props.action === "diff"
? [props.file, props.side, props.startLine, props.endLine]
: undefined,
props.action === "diff" ? [props.file, props.side, props.startLine, props.endLine] : undefined,
props.action === "diff" ? [props.github?.prNumber, props.github?.snapshotId] : undefined,
props.action === "line" ? [props.snapshotId, props.path, props.side, props.startLine, props.endLine] : undefined,
props.action === "review" ? [props.snapshotId, props.head] : undefined,
Expand All @@ -153,12 +128,12 @@ export function PRCommentForm(props: Props) {
}
const state = () =>
drafts[key()] ??
((props.action === "line" || props.action === "local" || props.action === "diff") && props.initialBody
((props.action === "line" || props.action === "diff") && props.initialBody
? { ...blank, body: props.initialBody }
: blank)
const [collapsed, setCollapsed] = createSignal<string>()
const compact = () => props.action === "reply" || props.action === "create"
const cancellable = () => props.action === "edit" || props.action === "local" || props.action === "diff" || compact()
const cancellable = () => props.action === "edit" || props.action === "diff" || compact()
const expanded = () =>
!!state().pending || state().open || (collapsed() !== key() && !!(state().body || state().error))
const placeholder = () =>
Expand All @@ -169,7 +144,7 @@ export function PRCommentForm(props: Props) {
? t("agentManager.pr.comment.reply")
: props.action === "review"
? t("agentManager.pr.review.summary")
: props.action === "create" || props.action === "line" || props.action === "local" || props.action === "diff"
: props.action === "create" || props.action === "line" || props.action === "diff"
? t("agentManager.pr.comment.add")
: t("common.edit")
const ready = () =>
Expand Down Expand Up @@ -215,7 +190,7 @@ export function PRCommentForm(props: Props) {

function cancel() {
if (state().pending) return
if (props.action === "local" || props.action === "diff") {
if (props.action === "diff") {
patch({ body: "", error: undefined, preview: false, sent: undefined })
props.onCancel()
return
Expand Down Expand Up @@ -281,11 +256,6 @@ export function PRCommentForm(props: Props) {
: !ready()
)
return
if (props.action === "local") {
patch({ body: "", error: undefined, preview: false, sent: undefined })
props.onSubmit(body, props.selectedText)
return
}
const id = key()
const requestId = crypto.randomUUID()
const route = { projectId: props.projectId, worktreeId: props.worktreeId }
Expand Down Expand Up @@ -476,16 +446,10 @@ export function PRCommentForm(props: Props) {
disabled={!!state().pending}
onChange={(body) => {
patch({ body, sent: undefined })
if (props.action === "line" || props.action === "local" || props.action === "diff")
props.onBodyChange?.(body)
if (props.action === "line" || props.action === "diff") props.onBodyChange?.(body)
}}
onKeyDown={(event: KeyboardEvent) => {
if (event.isComposing || event.keyCode === 229) return
if (event.key === "Escape" && props.onEscape) {
event.preventDefault()
props.onEscape()
return
}
if (props.action === "diff") {
if (event.key !== "Enter" || event.shiftKey) return
// Cmd/Ctrl+Enter saves the comment. Plain Enter sends it to Kilo,
Expand All @@ -506,10 +470,6 @@ export function PRCommentForm(props: Props) {
submit()
return
}
if (props.submitOnEnter && !event.shiftKey) {
event.preventDefault()
submit()
}
}}
/>
</div>
Expand Down Expand Up @@ -652,7 +612,7 @@ export function PRCommentForm(props: Props) {
</Show>
<Button
data-action="submit"
variant={props.inline && props.action === "local" ? "secondary" : "primary"}
variant="primary"
size="small"
disabled={!ready()}
onClick={() => submit()}
Expand All @@ -664,32 +624,14 @@ export function PRCommentForm(props: Props) {
? t("agentManager.pr.comment.replySending")
: props.inline && props.action === "line"
? t("diffViewer.comment.postToGithub")
: props.inline && props.action === "local"
? t("diffViewer.comment.saveLocal")
: props.action === "reply"
? t("agentManager.pr.comment.reply")
: props.action === "review"
? t("agentManager.pr.review.title")
: props.action === "create" || props.action === "line" || props.action === "local"
? t("agentManager.pr.comment.addSubmit")
: t("common.save")}
: props.action === "reply"
? t("agentManager.pr.comment.reply")
: props.action === "review"
? t("agentManager.pr.review.title")
: props.action === "create" || props.action === "line"
? t("agentManager.pr.comment.addSubmit")
: t("common.save")}
</Button>
<Show when={props.action === "local"}>
<Button
data-action="send"
aria-label={t("diffViewer.comment.sendToAgent")}
title={t("diffViewer.comment.sendToAgent")}
variant="primary"
size="small"
disabled={!ready()}
onClick={() => {
if (props.action !== "local") return
props.onSend(state().body, props.selectedText)
}}
>
{t("prompt.action.send")}
</Button>
</Show>
<Show when={cancellable()}>
<Button
data-action="cancel"
Expand Down
2 changes: 0 additions & 2 deletions packages/kilo-vscode/webview-ui/src/i18n/ar.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions packages/kilo-vscode/webview-ui/src/i18n/br.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions packages/kilo-vscode/webview-ui/src/i18n/bs.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions packages/kilo-vscode/webview-ui/src/i18n/da.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions packages/kilo-vscode/webview-ui/src/i18n/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1343,8 +1343,6 @@ export const dict = {
"Von Kilo während der aktuellen Sitzung geänderte Dateien, basierend auf Snapshots pro Runde. Wird beim Start einer neuen Sitzung zurückgesetzt.",
"diffViewer.group.session": "Sitzung",
"diffViewer.group.git": "Git",
"diffViewer.comment.saveLocal": "Lokal speichern",
"diffViewer.comment.sendToAgent": "An Agent senden",
"diffViewer.comment.postToGithub": "Auf GitHub veröffentlichen",
"diffViewer.comment.loadFailed": "Die Änderungen des Pull Requests konnten nicht geladen werden.",
"diffViewer.comment.unavailable": "Diese Zeile ist im aktuellen Snapshot des Pull Requests nicht verfügbar.",
Expand Down
2 changes: 0 additions & 2 deletions packages/kilo-vscode/webview-ui/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1308,8 +1308,6 @@ export const dict = {
"diffViewer.group.git": "Git",
"diffViewer.notice.snapshotsDisabled":
"Snapshots are disabled for this repository. Please edit your configuration files in order to display session changes.",
"diffViewer.comment.saveLocal": "Save local",
"diffViewer.comment.sendToAgent": "Send to agent",
"diffViewer.comment.postToGithub": "Post to GitHub",
"diffViewer.comment.loadFailed": "Could not load the pull request changes.",
"diffViewer.comment.unavailable": "This line is not available in the current pull request snapshot.",
Expand Down
2 changes: 0 additions & 2 deletions packages/kilo-vscode/webview-ui/src/i18n/es.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions packages/kilo-vscode/webview-ui/src/i18n/fa.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions packages/kilo-vscode/webview-ui/src/i18n/fr.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions packages/kilo-vscode/webview-ui/src/i18n/it.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions packages/kilo-vscode/webview-ui/src/i18n/ja.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions packages/kilo-vscode/webview-ui/src/i18n/ko.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading