fix(ui): keep diff refreshes targeted
This commit is contained in:
@@ -252,7 +252,10 @@ Expected model:
|
||||
|
||||
- `GitView` / `DiffView` ensure current-directory Git state when visible
|
||||
- explicit Git actions refresh status/branches/log as needed
|
||||
- successful file-mutating tools can issue a one-shot Git refresh hint
|
||||
- a mounted file-mutating tool issues a one-shot Git refresh hint when it transitions from active to successfully finalized; remounting historical completed tools does not replay the hint
|
||||
- a successful dirty save from the in-app file editor issues a path-scoped Git refresh hint; clean autosave checks remain no-ops
|
||||
- refresh hints with authoritative file paths invalidate only those cached and currently rendered diffs before status refresh; pathless tools request status reconciliation without broadly remounting DiffView
|
||||
- targeted diff remounts preserve the user's current file-section anchor and intra-file offset before paint instead of resetting the stacked view to the top
|
||||
- no root-level background Git polling
|
||||
|
||||
### PR
|
||||
|
||||
@@ -161,6 +161,32 @@ describe('useGitStore', () => {
|
||||
expect(useGitStore.getState().getDiff('/repo', 'stale.ts')).toBe(null);
|
||||
});
|
||||
|
||||
test('clears cached file contents when a git refresh hint invalidates diffs', () => {
|
||||
setDirectoryStatus(createStatus(
|
||||
{ 'src/index.ts': { insertions: 1, deletions: 1 } },
|
||||
[{ path: 'src/index.ts', index: ' ', working_dir: 'M' }],
|
||||
));
|
||||
useGitStore.getState().setDiff('/repo', 'src/index.ts', { original: 'old', modified: 'stale' });
|
||||
|
||||
useGitStore.getState().clearDiffCache('/repo');
|
||||
|
||||
expect(useGitStore.getState().getDiff('/repo', 'src/index.ts')).toBe(null);
|
||||
});
|
||||
|
||||
test('invalidates only the requested cached file contents', () => {
|
||||
setDirectoryStatus(createStatus(undefined, [
|
||||
{ path: 'src/first.ts', index: ' ', working_dir: 'M' },
|
||||
{ path: 'src/second.ts', index: ' ', working_dir: 'M' },
|
||||
]));
|
||||
useGitStore.getState().setDiff('/repo', 'src/first.ts', { original: 'a', modified: 'b' });
|
||||
useGitStore.getState().setDiff('/repo', 'src/second.ts', { original: 'c', modified: 'd' });
|
||||
|
||||
useGitStore.getState().clearDiffCache('/repo', ['src/first.ts']);
|
||||
|
||||
expect(useGitStore.getState().getDiff('/repo', 'src/first.ts')).toBe(null);
|
||||
expect(useGitStore.getState().getDiff('/repo', 'src/second.ts')?.modified).toBe('d');
|
||||
});
|
||||
|
||||
test('keeps the newest branch request when completions are reversed', async () => {
|
||||
const requests = [createDeferred<Awaited<ReturnType<GitAPI['getGitBranches']>>>(), createDeferred<Awaited<ReturnType<GitAPI['getGitBranches']>>>()];
|
||||
let index = 0;
|
||||
|
||||
@@ -71,7 +71,7 @@ interface GitStore {
|
||||
|
||||
getDiff: (directory: string, filePath: string) => { original: string; modified: string; fetchedAt: number; isBinary?: boolean } | null;
|
||||
setDiff: (directory: string, filePath: string, diff: { original: string; modified: string; isBinary?: boolean }, expectedRuntimeKey?: string) => void;
|
||||
clearDiffCache: (directory: string) => void;
|
||||
clearDiffCache: (directory: string, filePaths?: string[]) => void;
|
||||
fetchAllDiffs: (directory: string, git: GitAPI) => Promise<void>;
|
||||
prefetchDiffs: (directory: string, git: GitAPI, filePaths: string[], options?: { maxFiles?: number }) => Promise<void>;
|
||||
|
||||
@@ -974,15 +974,25 @@ export const useGitStore = create<GitStore>()(
|
||||
set({ directories: evictGlobalDiffCachesIfNeeded(newDirectories) });
|
||||
},
|
||||
|
||||
clearDiffCache: (directory) => {
|
||||
clearDiffCache: (directory, filePaths) => {
|
||||
bumpDiffFetchGeneration(directory);
|
||||
startRequest(directory, 'diff');
|
||||
const newDirectories = new Map(get().directories);
|
||||
const dirState = newDirectories.get(directory);
|
||||
if (dirState) {
|
||||
newDirectories.set(directory, { ...dirState, diffCache: new Map() });
|
||||
set({ directories: newDirectories });
|
||||
if (!dirState || dirState.diffCache.size === 0) return;
|
||||
|
||||
const nextDiffCache = new Map(dirState.diffCache);
|
||||
if (filePaths) {
|
||||
for (const filePath of filePaths) {
|
||||
nextDiffCache.delete(filePath);
|
||||
}
|
||||
} else {
|
||||
nextDiffCache.clear();
|
||||
}
|
||||
if (nextDiffCache.size === dirState.diffCache.size) return;
|
||||
|
||||
newDirectories.set(directory, { ...dirState, diffCache: nextDiffCache });
|
||||
set({ directories: newDirectories });
|
||||
},
|
||||
|
||||
fetchAllDiffs: async (directory, git) => {
|
||||
|
||||
Reference in New Issue
Block a user