Diff hunks + thread context on review comments; preview env links; hide matrix placeholder
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DgBEW6qAwgn2fcQbA2f4ZQ
This commit is contained in:
co-authored by
Claude Fable 5
parent
df0e82e372
commit
d14b6ebed3
@@ -20,6 +20,11 @@ export default function PrCard({ pr, unread }: { pr: PrSnapshot; unread: number
|
||||
{pr.branch}
|
||||
</span>
|
||||
<span>{relativeTime(pr.updatedAt)}</span>
|
||||
{pr.previewUrl && (
|
||||
<a className="preview-link" href={pr.previewUrl} target="_blank" rel="noreferrer">
|
||||
preview ↗
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
<div className="chips-row">
|
||||
<ReviewBadge pr={pr} />
|
||||
|
||||
@@ -62,14 +62,43 @@ function KindLabel({ event }: { event: TimelineEvent }) {
|
||||
if (event.kind === 'review_comment') {
|
||||
return (
|
||||
<span>
|
||||
commented{event.path ? ' on ' : ''}
|
||||
{event.path && <span className="path">{event.path.split('/').pop()}</span>}
|
||||
{event.inReplyTo ? 'replied' : 'commented'}
|
||||
{event.path ? ' on ' : ''}
|
||||
{event.path && (
|
||||
<span className="path" title={event.path}>
|
||||
{event.path.split('/').pop()}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
return <span>commented</span>;
|
||||
}
|
||||
|
||||
function DiffHunk({ hunk }: { hunk: string }) {
|
||||
return (
|
||||
<pre className="tl-diff">
|
||||
{hunk.split('\n').map((line, i) => (
|
||||
<span
|
||||
key={i}
|
||||
className={
|
||||
line.startsWith('+')
|
||||
? 'diff-add'
|
||||
: line.startsWith('-')
|
||||
? 'diff-del'
|
||||
: line.startsWith('@@')
|
||||
? 'diff-meta'
|
||||
: ''
|
||||
}
|
||||
>
|
||||
{line || ' '}
|
||||
{'\n'}
|
||||
</span>
|
||||
))}
|
||||
</pre>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Timeline() {
|
||||
const [unreadOnly, setUnreadOnly] = useState(false);
|
||||
const queryClient = useQueryClient();
|
||||
@@ -144,14 +173,18 @@ export default function Timeline() {
|
||||
readMutation.mutate({ id: e.id, read: !e.read });
|
||||
}}
|
||||
/>
|
||||
<div>
|
||||
<div className="tl-content">
|
||||
<div className="tl-kind">
|
||||
<KindLabel event={e} />
|
||||
</div>
|
||||
{e.diffHunk && !e.inReplyTo && <DiffHunk hunk={e.diffHunk} />}
|
||||
{e.inReplyTo && (
|
||||
<div className="tl-reply-ctx">
|
||||
↳ <span className="actor">{e.inReplyTo.actor}</span>:{' '}
|
||||
{e.inReplyTo.bodyExcerpt}
|
||||
<div className="tl-thread">
|
||||
{e.diffHunk && <DiffHunk hunk={e.diffHunk} />}
|
||||
<div className="tl-reply-ctx">
|
||||
<span className="actor">{e.inReplyTo.actor}</span>{' '}
|
||||
{e.inReplyTo.bodyExcerpt}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{e.bodyExcerpt && <div className="body">{e.bodyExcerpt}</div>}
|
||||
|
||||
+57
-2
@@ -288,6 +288,19 @@ button {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.preview-link {
|
||||
color: var(--accent);
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 4px;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.preview-link:hover {
|
||||
border-color: var(--accent);
|
||||
}
|
||||
|
||||
.unread-pill {
|
||||
background: var(--unread);
|
||||
color: #fff;
|
||||
@@ -580,11 +593,20 @@ a.check-row:hover {
|
||||
background: var(--unread);
|
||||
}
|
||||
|
||||
.tl-content {
|
||||
min-width: 0;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.tl-thread {
|
||||
border-left: 2px solid var(--hairline);
|
||||
padding-left: 8px;
|
||||
margin: 3px 0;
|
||||
}
|
||||
|
||||
.tl-reply-ctx {
|
||||
font-size: 12px;
|
||||
color: var(--ink-muted);
|
||||
border-left: 2px solid var(--hairline);
|
||||
padding-left: 7px;
|
||||
margin: 2px 0;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
@@ -597,6 +619,39 @@ a.check-row:hover {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.tl-diff {
|
||||
margin: 3px 0;
|
||||
padding: 6px 8px;
|
||||
border: 1px solid var(--hairline);
|
||||
border-radius: 6px;
|
||||
background: var(--page);
|
||||
font-family: ui-monospace, monospace;
|
||||
font-size: 11px;
|
||||
line-height: 1.5;
|
||||
overflow-x: auto;
|
||||
white-space: pre;
|
||||
max-height: 160px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.tl-diff .diff-add {
|
||||
color: var(--status-pass-text);
|
||||
background: var(--chip-pass-bg);
|
||||
display: inline-block;
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.tl-diff .diff-del {
|
||||
color: var(--status-fail-text);
|
||||
background: var(--chip-fail-bg);
|
||||
display: inline-block;
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.tl-diff .diff-meta {
|
||||
color: var(--ink-muted);
|
||||
}
|
||||
|
||||
.tl-item .body {
|
||||
color: var(--ink-secondary);
|
||||
font-size: 13px;
|
||||
|
||||
Reference in New Issue
Block a user