Diff streaming improvement (#459)
* Diffs are PatchType * Added files don't have old content * Improve styles * Lints * Update readme
This commit is contained in:
committed by
GitHub
parent
0fdc73f8b7
commit
bbcf00093b
@@ -1,7 +1,3 @@
|
|||||||
> [!IMPORTANT]
|
|
||||||
> We're re-writing the codebase, expect a delayed response to feedback until that's shipped. The current version on NPM is stable and we expect to be releasing alpha builds of V2 within days.
|
|
||||||
> You can track progress [here](https://github.com/BloopAI/vibe-kanban/tree/deployments).
|
|
||||||
|
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://vibekanban.com">
|
<a href="https://vibekanban.com">
|
||||||
<picture>
|
<picture>
|
||||||
@@ -15,7 +11,7 @@
|
|||||||
<p align="center">Get 10X more out of Claude Code, Gemini CLI, Codex, Amp and other coding agents...</p>
|
<p align="center">Get 10X more out of Claude Code, Gemini CLI, Codex, Amp and other coding agents...</p>
|
||||||
<p align="center">
|
<p align="center">
|
||||||
<a href="https://www.npmjs.com/package/vibe-kanban"><img alt="npm" src="https://img.shields.io/npm/v/vibe-kanban?style=flat-square" /></a>
|
<a href="https://www.npmjs.com/package/vibe-kanban"><img alt="npm" src="https://img.shields.io/npm/v/vibe-kanban?style=flat-square" /></a>
|
||||||
<a href="https://github.com/BloopAI/vibe-kanban/blob/main/.github/workflows/publish.yml"><img alt="Build status" src="https://img.shields.io/github/actions/workflow/status/bloopai/vibe-kanban/.github%2Fworkflows%2Fpublish.yml?style=flat-square&branch=dev" /></a>
|
<a href="https://github.com/BloopAI/vibe-kanban/blob/main/.github/workflows/publish.yml"><img alt="Build status" src="https://img.shields.io/github/actions/workflow/status/BloopAI/vibe-kanban/.github%2Fworkflows%2Fpublish.yml" /></a>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -342,26 +342,37 @@ impl GitService {
|
|||||||
let mut file_diffs = Vec::new();
|
let mut file_diffs = Vec::new();
|
||||||
|
|
||||||
diff.foreach(
|
diff.foreach(
|
||||||
&mut |delta, _progress| {
|
&mut |delta, _| {
|
||||||
// Skip unreadable entries
|
|
||||||
if delta.status() == Delta::Unreadable {
|
if delta.status() == Delta::Unreadable {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let old_file = delta
|
let status = delta.status();
|
||||||
|
|
||||||
|
// Only build old_file for non-added entries
|
||||||
|
let old_file = if matches!(status, Delta::Added) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
delta
|
||||||
.old_file()
|
.old_file()
|
||||||
.path()
|
.path()
|
||||||
.map(|path| self.create_file_details(path, &delta.old_file().id(), repo));
|
.map(|p| self.create_file_details(p, &delta.old_file().id(), repo))
|
||||||
|
};
|
||||||
|
|
||||||
let new_file = delta
|
// Only build new_file for non-deleted entries
|
||||||
|
let new_file = if matches!(status, Delta::Deleted) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
delta
|
||||||
.new_file()
|
.new_file()
|
||||||
.path()
|
.path()
|
||||||
.map(|path| self.create_file_details(path, &delta.new_file().id(), repo));
|
.map(|p| self.create_file_details(p, &delta.new_file().id(), repo))
|
||||||
|
};
|
||||||
|
|
||||||
file_diffs.push(Diff {
|
file_diffs.push(Diff {
|
||||||
old_file,
|
old_file,
|
||||||
new_file,
|
new_file,
|
||||||
hunks: vec![], // Left empty as requested
|
hunks: vec![], // still empty
|
||||||
});
|
});
|
||||||
|
|
||||||
true
|
true
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { generateDiffFile } from '@git-diff-view/file';
|
import { generateDiffFile } from '@git-diff-view/file';
|
||||||
import { useDiffStream } from '@/hooks/useDiffStream';
|
import { useDiffEntries } from '@/hooks/useDiffEntries';
|
||||||
import { useMemo, useContext, useCallback, useState, useEffect } from 'react';
|
import { useMemo, useContext, useCallback, useState, useEffect } from 'react';
|
||||||
import { TaskSelectedAttemptContext } from '@/components/context/taskDetailsContext.ts';
|
import { TaskSelectedAttemptContext } from '@/components/context/taskDetailsContext.ts';
|
||||||
import { Diff } from 'shared/types';
|
import { Diff } from 'shared/types';
|
||||||
@@ -10,13 +10,13 @@ import DiffCard from '@/components/DiffCard';
|
|||||||
function DiffTab() {
|
function DiffTab() {
|
||||||
const { selectedAttempt } = useContext(TaskSelectedAttemptContext);
|
const { selectedAttempt } = useContext(TaskSelectedAttemptContext);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const { data, error } = useDiffStream(selectedAttempt?.id ?? null, true);
|
const { diffs, error } = useDiffEntries(selectedAttempt?.id ?? null, true);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (data && Object.keys(data?.entries).length > 0 && loading) {
|
if (diffs.length > 0 && loading) {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
}
|
}
|
||||||
}, [data]);
|
}, [diffs, loading]);
|
||||||
|
|
||||||
const createDiffFile = useCallback((diff: Diff) => {
|
const createDiffFile = useCallback((diff: Diff) => {
|
||||||
const oldFileName = diff.oldFile?.fileName || 'old';
|
const oldFileName = diff.oldFile?.fileName || 'old';
|
||||||
@@ -42,12 +42,10 @@ function DiffTab() {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const diffFiles = useMemo(() => {
|
const diffFiles = useMemo(() => {
|
||||||
if (!data) return [];
|
return diffs
|
||||||
return Object.values(data.entries)
|
.map((diff) => createDiffFile(diff))
|
||||||
.filter((e: any) => e?.type === 'DIFF')
|
|
||||||
.map((e: any) => createDiffFile(e.content as Diff))
|
|
||||||
.filter((diffFile) => diffFile !== null);
|
.filter((diffFile) => diffFile !== null);
|
||||||
}, [data, createDiffFile]);
|
}, [diffs, createDiffFile]);
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
27
frontend/src/hooks/useDiffEntries.ts
Normal file
27
frontend/src/hooks/useDiffEntries.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { useMemo } from 'react';
|
||||||
|
import { useDiffStream } from './useDiffStream';
|
||||||
|
import type { Diff, PatchType } from 'shared/types';
|
||||||
|
|
||||||
|
interface UseDiffEntriesResult {
|
||||||
|
diffs: Diff[];
|
||||||
|
isConnected: boolean;
|
||||||
|
error: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useDiffEntries = (
|
||||||
|
attemptId: string | null,
|
||||||
|
enabled: boolean
|
||||||
|
): UseDiffEntriesResult => {
|
||||||
|
const { data, isConnected, error } = useDiffStream(attemptId, enabled);
|
||||||
|
|
||||||
|
const diffs = useMemo(() => {
|
||||||
|
if (!data) return [];
|
||||||
|
return Object.values(data.entries)
|
||||||
|
.filter(
|
||||||
|
(e): e is Extract<PatchType, { type: 'DIFF' }> => e?.type === 'DIFF'
|
||||||
|
)
|
||||||
|
.map((e) => e.content);
|
||||||
|
}, [data]);
|
||||||
|
|
||||||
|
return { diffs, isConnected, error };
|
||||||
|
};
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { useCallback } from 'react';
|
import { useCallback } from 'react';
|
||||||
import type { Diff } from 'shared/types';
|
import type { PatchType } from 'shared/types';
|
||||||
import { useJsonPatchStream } from './useJsonPatchStream';
|
import { useJsonPatchStream } from './useJsonPatchStream';
|
||||||
|
|
||||||
interface DiffState {
|
interface DiffState {
|
||||||
entries: Record<string, Diff>;
|
entries: Record<string, PatchType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UseDiffStreamResult {
|
interface UseDiffStreamResult {
|
||||||
|
|||||||
@@ -366,7 +366,11 @@
|
|||||||
--diff-border--: var(--background);
|
--diff-border--: var(--background);
|
||||||
--diff-add-content--: hsl(var(--console-success) / 0.2);
|
--diff-add-content--: hsl(var(--console-success) / 0.2);
|
||||||
--diff-del-content--: hsl(var(--console-error) / 0.2);
|
--diff-del-content--: hsl(var(--console-error) / 0.2);
|
||||||
--diff-add-lineNumber--: hsl(var(--console-success) / 0.2);
|
--diff-add-lineNumber--: color-mix(
|
||||||
|
in srgb,
|
||||||
|
hsl(var(--console-success)) 20%,
|
||||||
|
hsl(var(--background)) 80%
|
||||||
|
);
|
||||||
--diff-del-lineNumber--: hsl(var(--console-error) / 0.2);
|
--diff-del-lineNumber--: hsl(var(--console-error) / 0.2);
|
||||||
--diff-plain-content--: hsl(var(--background));
|
--diff-plain-content--: hsl(var(--background));
|
||||||
--diff-expand-content--: hsl(var(--background));
|
--diff-expand-content--: hsl(var(--background));
|
||||||
|
|||||||
Reference in New Issue
Block a user