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:
parent
05457aca0d
commit
b886b6bf83
5 changed files with 48 additions and 26 deletions
|
|
@ -74,6 +74,19 @@ export class FileContentResolver {
|
||||||
logger.debug(`Файл недоступен на диске: ${filePath}`);
|
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
|
// Strategy 1: Try file-history backup
|
||||||
const historyResult = await this.tryFileHistoryBackup(teamName, memberName, filePath);
|
const historyResult = await this.tryFileHistoryBackup(teamName, memberName, filePath);
|
||||||
if (historyResult) {
|
if (historyResult) {
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,7 @@ export const ClaudeLogsSection = ({
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
) : undefined
|
) : 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}
|
headerExtra={sectionHeaderExtra}
|
||||||
defaultOpen={false}
|
defaultOpen={false}
|
||||||
contentClassName="pt-0 [overflow-anchor:none]"
|
contentClassName="pt-0 [overflow-anchor:none]"
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ export const CollapsibleTeamSection = ({
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
type="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={() =>
|
onClick={() =>
|
||||||
setOpen((prev) => {
|
setOpen((prev) => {
|
||||||
const next = !prev;
|
const next = !prev;
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import {
|
||||||
} from './CodeMirrorDiffUtils';
|
} from './CodeMirrorDiffUtils';
|
||||||
import { FileSectionDiff } from './FileSectionDiff';
|
import { FileSectionDiff } from './FileSectionDiff';
|
||||||
import { FileSectionHeader } from './FileSectionHeader';
|
import { FileSectionHeader } from './FileSectionHeader';
|
||||||
import { FileSectionPlaceholder } from './FileSectionPlaceholder';
|
|
||||||
|
|
||||||
import type { EditorView } from '@codemirror/view';
|
import type { EditorView } from '@codemirror/view';
|
||||||
import type { FileChangeWithContent, HunkDecision } from '@shared/types';
|
import type { FileChangeWithContent, HunkDecision } from '@shared/types';
|
||||||
|
|
@ -256,28 +255,25 @@ export const ContinuousScrollView = ({
|
||||||
onRestoreMissingFile={onRestoreMissingFile}
|
onRestoreMissingFile={onRestoreMissingFile}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{!isCollapsed &&
|
{!isCollapsed && (
|
||||||
(hasContent ? (
|
<FileSectionDiff
|
||||||
<FileSectionDiff
|
file={file}
|
||||||
file={file}
|
fileContent={content}
|
||||||
fileContent={content}
|
isLoading={!hasContent}
|
||||||
isLoading={false}
|
collapseUnchanged={collapseUnchanged}
|
||||||
collapseUnchanged={collapseUnchanged}
|
onHunkAccepted={onHunkAccepted}
|
||||||
onHunkAccepted={onHunkAccepted}
|
onHunkRejected={onHunkRejected}
|
||||||
onHunkRejected={onHunkRejected}
|
onFullyViewed={onFullyViewed}
|
||||||
onFullyViewed={onFullyViewed}
|
onContentChanged={onContentChanged}
|
||||||
onContentChanged={onContentChanged}
|
onEditorViewReady={handleEditorViewReady}
|
||||||
onEditorViewReady={handleEditorViewReady}
|
discardCounter={discardCounters[filePath] ?? 0}
|
||||||
discardCounter={discardCounters[filePath] ?? 0}
|
autoViewed={autoViewed}
|
||||||
autoViewed={autoViewed}
|
isViewed={isViewed}
|
||||||
isViewed={isViewed}
|
onSelectionChange={onSelectionChange}
|
||||||
onSelectionChange={onSelectionChange}
|
globalHunkOffset={globalHunkOffsets?.[filePath] ?? 0}
|
||||||
globalHunkOffset={globalHunkOffsets?.[filePath] ?? 0}
|
totalReviewHunks={totalReviewHunks}
|
||||||
totalReviewHunks={totalReviewHunks}
|
/>
|
||||||
/>
|
)}
|
||||||
) : (
|
|
||||||
<FileSectionPlaceholder fileName={file.relativePath} />
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
|
||||||
|
|
@ -80,7 +80,20 @@ export const FileSectionDiff = ({
|
||||||
|
|
||||||
// Loading state
|
// Loading state
|
||||||
if (isLoading) {
|
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
|
// Resolve modified content: prefer full content, fall back to write-type snippet
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue