Diff viewer
In reviewLive · web
Unified ↔ Split: toggle the view (tab to it, Enter / Space)
@@ -1,9 +1,11 @@
package com.nockerl.app.net
/** Exponential backoff for SSE reconnects. */
import kotlin.random.Random
/** Exponential backoff for SSE reconnects, capped + jittered. */
fun nextDelay(attempt: Int): Long {
val base = minOf(15_000L, 1_000L shl attempt)
return base
val base = minOf(30_000L, 1_000L shl attempt)
return base + Random.nextLong(250)
}
fun shouldRetry(code: Int): Boolean = code in 500..599
Collapsed context: long unchanged runs fold behind an Expand button
@@ -1,15 +1,15 @@
import { Hono } from 'hono';
for await (const ev of bus.subscribe(id, since)) {
await sse.writeSSE({ data: JSON.stringify(ev) });
await sse.writeSSE({ event: ev.type, data: JSON.stringify(ev) });
}
});
});
export default app;
Showing the unified view · the diff is the real LCS computeLineDiff. The island is live.
// Web: React, consuming @dizyx/nockerl-tokens. (Web is the laggard platform. Spec + live demo,// not yet exported from @dizyx/nockerl-react; promotion is tracked.)
export function ReviewDiff({ before, after }: { before: string; after: string }) { return ( <DiffViewer path="app/src/main/java/com/nockerl/app/net/Backoff.kt" language="kotlin" prev={before} next={after} view="unified" // 'unified' | 'split' (old left / new right) collapseContext={3} // fold runs of unchanged lines behind an Expand control /> );}// Android: Jetpack Compose (canonical). The diff surface lives in chat/ui as// DiffView, fed by the LCS computeLineDiff in chat/domain. It renders the file// header, +/- gutter, and warm added/removed washes; split view is web-only.import com.nockerl.app.chat.domain.DiffLineimport com.nockerl.app.chat.domain.DiffLineTypeimport com.nockerl.app.chat.domain.computeLineDiff
// computeLineDiff(old, new) → List<DiffLine>, each ADDED / REMOVED / UNCHANGED// with a 1-based lineNumber. Pass old = "" for a new file (all-green additions).val diffLines: List<DiffLine> = computeLineDiff(old = before, new = after)
// DiffView is internal to ToolCallCard.kt. It takes the path (for the header),// the computed lines, and the resulting content (the copy button writes it):DiffView( filePath = "app/.../net/Backoff.kt", diffLines = diffLines, newContent = after,)// macOS: SwiftUI (Nockerl Voice). No diff viewer ships yet; Voice has no// Edit/Write tool surface to render. The intended API mirrors the web component,// rendered in the mono well (see the Code block page) once Voice gains tool cards://// DiffViewer(path: "Backoff.kt", language: .kotlin,// prev: before, next: after, view: .unified)//// Today, a before/after is shown as two raw .monospaced Text blocks, ad hoc.Parameters
Section titled “Parameters”| Prop | Type | Default | Description |
|---|---|---|---|
path * | string | File path in the header: the directory is muted, the basename emphasized. | |
prev * | string | Pre-change source. Diffed against next via the LCS computeLineDiff. | |
next * | string | Post-change source. Pass prev="" for a new file (all-added). | |
language | 'typescript' | 'kotlin' | 'swift' | Drives the cyan-soft language pill in the header. | |
view | 'unified' | 'split' | 'unified' | Unified (one column, +/- gutter) or split (old left / new right, equal columns). |
collapseContext | number | 0 | Fold unchanged runs longer than this behind an Expand control. 0 = never fold. Unified only. |
The header shows a +N / -M add/remove stat (warm status), each hunk gets an
@@ -a,b +c,d @@ band, and a removed→added pair gets an intra-line word
highlight on the changed span. Added = status.success wash, removed =
status.error wash, context = muted, never the brand cyan, never color-alone.
| Parameter | Type | Default | Description |
|---|---|---|---|
filePath * | String | DiffView header path; the basename is shown beside the EditNote icon. | |
diffLines * | List<DiffLine> | From computeLineDiff(old, new). Each DiffLine(type, text, lineNumber) is ADDED / REMOVED / UNCHANGED. | |
newContent * | String | The resulting content the header copy button writes to the clipboard. | |
old / new | String | computeLineDiff(old, new) inputs. old = "" → all-green new file; returns emptyList() past 500 combined lines (raw fallback). | |
DiffLineType | enum | ADDED · REMOVED · UNCHANGED. Drives the wash (success / error / transparent) + the + / - / space prefix. |
SwiftUI ships no diff viewer. Voice has no Edit/Write tool surface yet, so there
is nothing to diff; a before/after would be two raw .monospaced Text blocks.
| Style | Type | Default | Description |
|---|---|---|---|
.font(.system(design: .monospaced)) | View modifier | The only mono affordance today: no file header, gutter, +/- glyph, washes, hunks, or split. Queued behind the Code block surface. |