Skip to content
Closed
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
14 changes: 14 additions & 0 deletions packages/ui/src/components/session-review.css
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,20 @@
color: var(--icon-diff-modified-base);
}

[data-slot="session-review-large-diff-badge"] {
font-family: var(--font-family-sans);
font-size: var(--font-size-small);
font-weight: var(--font-weight-medium);
color: var(--text-weak);
}

[data-slot="session-review-large-diff-warning"] {
font-family: var(--font-family-sans);
font-size: var(--font-size-small);
font-weight: var(--font-weight-medium);
color: var(--text-warning, var(--icon-diff-modified-base));
}

[data-slot="session-review-file-container"] {
padding: 0;
}
Expand Down
78 changes: 72 additions & 6 deletions packages/ui/src/components/session-review.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { useDiffComponent } from "../context/diff"
import { useI18n } from "../context/i18n"
import { getDirectory, getFilename } from "@opencode-ai/util/path"
import { checksum } from "@opencode-ai/util/encode"
import { createEffect, createMemo, createSignal, For, Match, Show, Switch, type JSX } from "solid-js"
import { createEffect, createMemo, createSignal, For, Match, onCleanup, Show, Switch, type JSX } from "solid-js"
import { createStore } from "solid-js/store"
import { type FileContent, type FileDiff } from "@opencode-ai/sdk/v2"
import { PreloadMultiFileDiffResult } from "@pierre/diffs/ssr"
Expand Down Expand Up @@ -170,32 +170,84 @@ function markerTop(wrapper: HTMLElement, marker: HTMLElement) {
return rect.top - wrapperRect.top + Math.max(0, (rect.height - 20) / 2)
}

const LARGE_DIFF_THRESHOLD = 500

function diffLines(diff: FileDiff) {
return (diff.additions ?? 0) + (diff.deletions ?? 0)
}

function isLargeDiff(diff: FileDiff) {
return diffLines(diff) > LARGE_DIFF_THRESHOLD
}

export const SessionReview = (props: SessionReviewProps) => {
let scroll: HTMLDivElement | undefined
let focusToken = 0
const i18n = useI18n()
const diffComponent = useDiffComponent()
const anchors = new Map<string, HTMLElement>()
const [store, setStore] = createStore({
open: props.diffs.length > 10 ? [] : props.diffs.map((d) => d.file),
open: props.diffs.length > 10 ? [] : props.diffs.filter((d) => !isLargeDiff(d)).map((d) => d.file),
})

const [selection, setSelection] = createSignal<SessionReviewSelection | null>(null)
const [commenting, setCommenting] = createSignal<SessionReviewSelection | null>(null)
const [opened, setOpened] = createSignal<SessionReviewFocus | null>(null)
const [confirmed, setConfirmed] = createSignal<Set<string>>(new Set())
let confirmTimer: ReturnType<typeof setTimeout> | undefined
onCleanup(() => {
clearTimeout(confirmTimer)
const current = open()
if (!current || current.length === 0) return
const large = largeDiffs()
if (large.size === 0) return
const filtered = current.filter((f) => !large.has(f))
if (filtered.length === current.length) return
props.onOpenChange?.(filtered)
})

const open = () => props.open ?? store.open
const diffStyle = () => props.diffStyle ?? (props.split ? "split" : "unified")
const hasDiffs = () => props.diffs.length > 0

const handleChange = (open: string[]) => {
props.onOpenChange?.(open)
const largeDiffs = createMemo(() => {
const map = new Map<string, number>()
for (const d of props.diffs) {
if (isLargeDiff(d)) map.set(d.file, diffLines(d))
}
return map
})

const handleChange = (next: string[]) => {
const current = open() ?? []
const added = next.filter((f) => !current.includes(f))
const needsConfirm = added.filter((f) => largeDiffs().has(f) && !confirmed().has(f))

if (needsConfirm.length > 0) {
clearTimeout(confirmTimer)
setConfirmed((prev: Set<string>) => {
const s = new Set(prev)
for (const f of needsConfirm) s.add(f)
return s
})
confirmTimer = setTimeout(() => setConfirmed(new Set()), 3000)
const filtered = next.filter((f) => !needsConfirm.includes(f))
if (filtered.length !== current.length || filtered.some((f, i) => f !== current[i])) {
props.onOpenChange?.(filtered)
if (props.open !== undefined) return
setStore("open", filtered)
}
return
}

clearTimeout(confirmTimer)
props.onOpenChange?.(next)
if (props.open !== undefined) return
setStore("open", open)
setStore("open", next)
}

const handleExpandOrCollapseAll = () => {
const next = open().length > 0 ? [] : props.diffs.map((d) => d.file)
const next = open().length > 0 ? [] : props.diffs.filter((d) => !isLargeDiff(d)).map((d) => d.file)
handleChange(next)
}

Expand Down Expand Up @@ -537,6 +589,20 @@ export const SessionReview = (props: SessionReviewProps) => {
</div>
</div>
<div data-slot="session-review-trigger-actions">
<Show when={isLargeDiff(diff) && confirmed().has(diff.file) && !open().includes(diff.file)}>
<span data-slot="session-review-large-diff-warning">
{i18n.t("ui.sessionReview.largeDiff.clickToExpand", {
lines: String(diffLines(diff)),
})}
</span>
</Show>
<Show when={isLargeDiff(diff) && !confirmed().has(diff.file)}>
<span data-slot="session-review-large-diff-badge">
{i18n.t("ui.sessionReview.largeDiff.label", {
lines: String(diffLines(diff)),
})}
</span>
</Show>
<Switch>
<Match when={isAdded()}>
<span data-slot="session-review-change" data-type="added">
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/i18n/ar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export const dict = {
"ui.sessionReview.change.added": "مضاف",
"ui.sessionReview.change.removed": "محذوف",
"ui.sessionReview.change.modified": "معدل",
"ui.sessionReview.largeDiff.label": "{{lines}} سطر",
"ui.sessionReview.largeDiff.clickToExpand": "{{lines}} سطر — انقر مرة أخرى للتوسيع",

"ui.lineComment.label.prefix": "تعليق على ",
"ui.lineComment.label.suffix": "",
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/i18n/br.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export const dict = {
"ui.sessionReview.change.added": "Adicionado",
"ui.sessionReview.change.removed": "Removido",
"ui.sessionReview.change.modified": "Modificado",
"ui.sessionReview.largeDiff.label": "{{lines}} linhas",
"ui.sessionReview.largeDiff.clickToExpand": "{{lines}} linhas — clique novamente para expandir",

"ui.lineComment.label.prefix": "Comentar em ",
"ui.lineComment.label.suffix": "",
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/i18n/bs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export const dict = {
"ui.sessionReview.change.added": "Dodano",
"ui.sessionReview.change.removed": "Uklonjeno",
"ui.sessionReview.change.modified": "Izmijenjeno",
"ui.sessionReview.largeDiff.label": "{{lines}} linija",
"ui.sessionReview.largeDiff.clickToExpand": "{{lines}} linija — kliknite ponovo za proširenje",

"ui.lineComment.label.prefix": "Komentar na ",
"ui.lineComment.label.suffix": "",
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/i18n/da.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export const dict = {
"ui.sessionReview.change.added": "Tilføjet",
"ui.sessionReview.change.removed": "Fjernet",
"ui.sessionReview.change.modified": "Ændret",
"ui.sessionReview.largeDiff.label": "{{lines}} linjer",
"ui.sessionReview.largeDiff.clickToExpand": "{{lines}} linjer — klik igen for at udvide",
"ui.lineComment.label.prefix": "Kommenter på ",
"ui.lineComment.label.suffix": "",
"ui.lineComment.editorLabel.prefix": "Kommenterer på ",
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/i18n/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export const dict = {
"ui.sessionReview.change.added": "Hinzugefügt",
"ui.sessionReview.change.removed": "Entfernt",
"ui.sessionReview.change.modified": "Geändert",
"ui.sessionReview.largeDiff.label": "{{lines}} Zeilen",
"ui.sessionReview.largeDiff.clickToExpand": "{{lines}} Zeilen — erneut klicken zum Aufklappen",
"ui.lineComment.label.prefix": "Kommentar zu ",
"ui.lineComment.label.suffix": "",
"ui.lineComment.editorLabel.prefix": "Kommentiere ",
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export const dict = {
"ui.sessionReview.change.added": "Added",
"ui.sessionReview.change.removed": "Removed",
"ui.sessionReview.change.modified": "Modified",
"ui.sessionReview.largeDiff.label": "{{lines}} lines",
"ui.sessionReview.largeDiff.clickToExpand": "{{lines}} lines — click again to expand",

"ui.lineComment.label.prefix": "Comment on ",
"ui.lineComment.label.suffix": "",
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/i18n/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export const dict = {
"ui.sessionReview.change.added": "Añadido",
"ui.sessionReview.change.removed": "Eliminado",
"ui.sessionReview.change.modified": "Modificado",
"ui.sessionReview.largeDiff.label": "{{lines}} líneas",
"ui.sessionReview.largeDiff.clickToExpand": "{{lines}} líneas — clic de nuevo para expandir",

"ui.lineComment.label.prefix": "Comentar en ",
"ui.lineComment.label.suffix": "",
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/i18n/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export const dict = {
"ui.sessionReview.change.added": "Ajouté",
"ui.sessionReview.change.removed": "Supprimé",
"ui.sessionReview.change.modified": "Modifié",
"ui.sessionReview.largeDiff.label": "{{lines}} lignes",
"ui.sessionReview.largeDiff.clickToExpand": "{{lines}} lignes — cliquez à nouveau pour développer",

"ui.lineComment.label.prefix": "Commenter sur ",
"ui.lineComment.label.suffix": "",
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/i18n/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export const dict = {
"ui.sessionReview.change.added": "追加",
"ui.sessionReview.change.removed": "削除",
"ui.sessionReview.change.modified": "変更",
"ui.sessionReview.largeDiff.label": "{{lines}} 行",
"ui.sessionReview.largeDiff.clickToExpand": "{{lines}} 行 — もう一度クリックで展開",
"ui.lineComment.label.prefix": "",
"ui.lineComment.label.suffix": "へのコメント",
"ui.lineComment.editorLabel.prefix": "",
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/i18n/ko.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export const dict = {
"ui.sessionReview.change.added": "추가됨",
"ui.sessionReview.change.removed": "삭제됨",
"ui.sessionReview.change.modified": "수정됨",
"ui.sessionReview.largeDiff.label": "{{lines}}줄",
"ui.sessionReview.largeDiff.clickToExpand": "{{lines}}줄 — 다시 클릭하여 펼치기",

"ui.lineComment.label.prefix": "",
"ui.lineComment.label.suffix": "에 댓글 달기",
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/i18n/no.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ export const dict: Record<Keys, string> = {
"ui.sessionReview.change.added": "Lagt til",
"ui.sessionReview.change.removed": "Fjernet",
"ui.sessionReview.change.modified": "Endret",
"ui.sessionReview.largeDiff.label": "{{lines}} linjer",
"ui.sessionReview.largeDiff.clickToExpand": "{{lines}} linjer — klikk igjen for å utvide",

"ui.lineComment.label.prefix": "Kommenter på ",
"ui.lineComment.label.suffix": "",
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/i18n/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export const dict = {
"ui.sessionReview.change.added": "Dodano",
"ui.sessionReview.change.removed": "Usunięto",
"ui.sessionReview.change.modified": "Zmodyfikowano",
"ui.sessionReview.largeDiff.label": "{{lines}} linii",
"ui.sessionReview.largeDiff.clickToExpand": "{{lines}} linii — kliknij ponownie, aby rozwinąć",
"ui.lineComment.label.prefix": "Komentarz do ",
"ui.lineComment.label.suffix": "",
"ui.lineComment.editorLabel.prefix": "Komentowanie: ",
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/i18n/ru.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ export const dict = {
"ui.sessionReview.change.added": "Добавлено",
"ui.sessionReview.change.removed": "Удалено",
"ui.sessionReview.change.modified": "Изменено",
"ui.sessionReview.largeDiff.label": "{{lines}} строк",
"ui.sessionReview.largeDiff.clickToExpand": "{{lines}} строк — нажмите ещё раз для раскрытия",
"ui.lineComment.label.prefix": "Комментарий к ",
"ui.lineComment.label.suffix": "",
"ui.lineComment.editorLabel.prefix": "Комментирование: ",
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/i18n/th.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export const dict = {
"ui.sessionReview.change.added": "เพิ่ม",
"ui.sessionReview.change.removed": "ลบ",
"ui.sessionReview.change.modified": "แก้ไข",
"ui.sessionReview.largeDiff.label": "{{lines}} บรรทัด",
"ui.sessionReview.largeDiff.clickToExpand": "{{lines}} บรรทัด — คลิกอีกครั้งเพื่อขยาย",

"ui.lineComment.label.prefix": "แสดงความคิดเห็นบน ",
"ui.lineComment.label.suffix": "",
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/i18n/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export const dict = {
"ui.sessionReview.change.added": "已添加",
"ui.sessionReview.change.removed": "已移除",
"ui.sessionReview.change.modified": "已修改",
"ui.sessionReview.largeDiff.label": "{{lines}} 行",
"ui.sessionReview.largeDiff.clickToExpand": "{{lines}} 行 — 再次点击展开",

"ui.lineComment.label.prefix": "评论 ",
"ui.lineComment.label.suffix": "",
Expand Down
2 changes: 2 additions & 0 deletions packages/ui/src/i18n/zht.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ export const dict = {
"ui.sessionReview.change.added": "已新增",
"ui.sessionReview.change.removed": "已移除",
"ui.sessionReview.change.modified": "已修改",
"ui.sessionReview.largeDiff.label": "{{lines}} 行",
"ui.sessionReview.largeDiff.clickToExpand": "{{lines}} 行 — 再次點擊展開",

"ui.lineComment.label.prefix": "評論 ",
"ui.lineComment.label.suffix": "",
Expand Down
Loading