feat: optimize file content resolution and enhance loading state handling

- Added a fast path in FileContentResolver to skip history lookup for files created by the agent with empty original content.
- Improved loading state in FileSectionDiff to display a loading message and snippet preview when applicable.
- Adjusted header content class names in ClaudeLogsSection and button styles in CollapsibleTeamSection for better UI consistency.
- Refactored ContinuousScrollView to streamline rendering logic for file sections based on content availability.
This commit is contained in:
iliya 2026-03-15 08:24:00 +02:00
parent 05457aca0d
commit b886b6bf83
5 changed files with 48 additions and 26 deletions

View file

@ -74,6 +74,19 @@ export class FileContentResolver {
logger.debug(`Файл недоступен на диске: ${filePath}`);
}
// Fast path: if the agent created the file and it still exists on disk,
// the original content is definitely empty, so skip expensive history lookup.
const hasWriteNew = snippets.some((s) => !s.isError && s.type === 'write-new');
if (hasWriteNew && currentContent !== null) {
const result = {
original: '',
modified: currentContent,
source: 'snippet-reconstruction' as const,
};
this.cacheResult(cacheKey, result);
return result;
}
// Strategy 1: Try file-history backup
const historyResult = await this.tryFileHistoryBackup(teamName, memberName, filePath);
if (historyResult) {

View file

@ -123,7 +123,7 @@ export const ClaudeLogsSection = ({
</Tooltip>
) : undefined
}
headerContentClassName={isSidebar ? 'flex-wrap items-center gap-y-1 py-1 pr-3' : 'pr-3'}
headerContentClassName={isSidebar ? 'flex-wrap items-center gap-y-1 py-1 pr-1' : 'pr-1'}
headerExtra={sectionHeaderExtra}
defaultOpen={false}
contentClassName="pt-0 [overflow-anchor:none]"

View file

@ -85,7 +85,7 @@ export const CollapsibleTeamSection = ({
>
<button
type="button"
className={`absolute inset-0 z-0 cursor-pointer transition-colors ${isOpen ? 'rounded-t-md bg-[var(--color-section-bg-open)] hover:bg-[var(--color-section-hover-open)]' : 'rounded-md bg-[var(--color-section-bg)] hover:bg-[var(--color-section-hover)]'}`}
className={`absolute inset-0 z-0 cursor-pointer transition-colors ${isOpen ? 'rounded-t-xl bg-[var(--color-section-bg-open)] hover:bg-[var(--color-section-hover-open)]' : 'rounded-xl bg-[var(--color-section-bg)] hover:bg-[var(--color-section-hover)]'}`}
onClick={() =>
setOpen((prev) => {
const next = !prev;

View file

@ -12,7 +12,6 @@ import {
} from './CodeMirrorDiffUtils';
import { FileSectionDiff } from './FileSectionDiff';
import { FileSectionHeader } from './FileSectionHeader';
import { FileSectionPlaceholder } from './FileSectionPlaceholder';
import type { EditorView } from '@codemirror/view';
import type { FileChangeWithContent, HunkDecision } from '@shared/types';
@ -256,28 +255,25 @@ export const ContinuousScrollView = ({
onRestoreMissingFile={onRestoreMissingFile}
/>
{!isCollapsed &&
(hasContent ? (
<FileSectionDiff
file={file}
fileContent={content}
isLoading={false}
collapseUnchanged={collapseUnchanged}
onHunkAccepted={onHunkAccepted}
onHunkRejected={onHunkRejected}
onFullyViewed={onFullyViewed}
onContentChanged={onContentChanged}
onEditorViewReady={handleEditorViewReady}
discardCounter={discardCounters[filePath] ?? 0}
autoViewed={autoViewed}
isViewed={isViewed}
onSelectionChange={onSelectionChange}
globalHunkOffset={globalHunkOffsets?.[filePath] ?? 0}
totalReviewHunks={totalReviewHunks}
/>
) : (
<FileSectionPlaceholder fileName={file.relativePath} />
))}
{!isCollapsed && (
<FileSectionDiff
file={file}
fileContent={content}
isLoading={!hasContent}
collapseUnchanged={collapseUnchanged}
onHunkAccepted={onHunkAccepted}
onHunkRejected={onHunkRejected}
onFullyViewed={onFullyViewed}
onContentChanged={onContentChanged}
onEditorViewReady={handleEditorViewReady}
discardCounter={discardCounters[filePath] ?? 0}
autoViewed={autoViewed}
isViewed={isViewed}
onSelectionChange={onSelectionChange}
globalHunkOffset={globalHunkOffsets?.[filePath] ?? 0}
totalReviewHunks={totalReviewHunks}
/>
)}
</div>
);
})}

View file

@ -80,7 +80,20 @@ export const FileSectionDiff = ({
// Loading state
if (isLoading) {
return <FileSectionPlaceholder fileName={file.relativePath} />;
const hasSnippetPreview = file.snippets.some((snippet) => !snippet.isError);
if (!hasSnippetPreview) {
return <FileSectionPlaceholder fileName={file.relativePath} />;
}
return (
<div className="overflow-auto">
<div className="bg-surface-raised/40 border-b border-border px-4 py-2 text-xs text-text-muted">
Loading full diff...
</div>
<ReviewDiffContent file={file} />
<div ref={sentinelRef} className="h-1 shrink-0" />
</div>
);
}
// Resolve modified content: prefer full content, fall back to write-type snippet