fix: handle multi-file tool diffs safely

Split multi-file patches before diff rendering
Fixed hook dependency lint warnings
This commit is contained in:
Bohdan Triapitsyn
2026-04-26 16:58:07 +03:00
parent 8f3707a5f4
commit 209ffc16e4
22 changed files with 116 additions and 57 deletions
@@ -429,6 +429,7 @@ export const ChangesSection: React.FC<ChangesSectionProps> = ({
revertingPaths,
rowPaddingClassName,
selectedPaths,
t,
toggleDirectoryExpanded,
toggleDirectorySelection,
]);
@@ -66,7 +66,7 @@ export const ConflictDialog: React.FC<ConflictDialogProps> = ({
.finally(() => {
setIsLoading(false);
});
}, [open, directory]);
}, [open, directory, t]);
const buildConflictContext = React.useCallback(async (): Promise<{
visibleText: string;
@@ -252,7 +252,7 @@ export const IntegrateCommitsSection: React.FC<{
{ text: context.payloadText, synthetic: true },
]);
setActiveMainTab('chat');
}, [currentSessionId, setActiveMainTab, buildConflictContext, openNewSessionDraft, setPendingInputText, setPendingSyntheticParts]);
}, [currentSessionId, setActiveMainTab, buildConflictContext, openNewSessionDraft, setPendingInputText, setPendingSyntheticParts, t]);
const handleMove = React.useCallback(async () => {
if (ui.kind !== 'ready') return;
@@ -288,7 +288,7 @@ export const IntegrateCommitsSection: React.FC<{
if (next) setUi({ kind: 'ready', plan: next });
else setUi({ kind: 'idle' });
}
}, [ui, onRefresh, repoRoot, sourceBranch, targetBranch, conflictStorageKey]);
}, [ui, onRefresh, repoRoot, sourceBranch, targetBranch, conflictStorageKey, t]);
const handleAbort = React.useCallback(async () => {
if (ui.kind !== 'conflict') return;
@@ -303,7 +303,7 @@ export const IntegrateCommitsSection: React.FC<{
if (next) setUi({ kind: 'ready', plan: next });
else setUi({ kind: 'idle' });
}
}, [ui, repoRoot, sourceBranch, targetBranch, conflictStorageKey]);
}, [ui, repoRoot, sourceBranch, targetBranch, conflictStorageKey, t]);
const handleContinue = React.useCallback(async () => {
if (ui.kind !== 'conflict') return;
@@ -330,7 +330,7 @@ export const IntegrateCommitsSection: React.FC<{
const message = e instanceof Error ? e.message : String(e);
toast.error(t('gitView.integrate.cherryPickContinueFailedToast'), { description: message });
}
}, [ui, repoRoot, sourceBranch, targetBranch, onRefresh, conflictStorageKey]);
}, [ui, repoRoot, sourceBranch, targetBranch, onRefresh, conflictStorageKey, t]);
if (!repoRoot || !sourceBranch) {
return null;
@@ -538,7 +538,7 @@ export const PullRequestSection: React.FC<{
} finally {
setIsLoadingCheckDetails(false);
}
}, [directory, github, pr]);
}, [directory, github, pr, t]);
const openCommentsDialog = React.useCallback(async () => {
if (!github?.prContext) {
@@ -561,7 +561,7 @@ export const PullRequestSection: React.FC<{
} finally {
setIsLoadingCommentsDetails(false);
}
}, [directory, github, pr]);
}, [directory, github, pr, t]);
const formatTimestamp = React.useCallback((value?: string) => {
if (!value) return '';
@@ -650,7 +650,7 @@ export const PullRequestSection: React.FC<{
currentAgentName: currentAgentName ?? null,
currentVariant: currentVariant ?? null,
};
}, [currentSessionId]);
}, [currentSessionId, t]);
const dispatchSyntheticPrompt = React.useCallback((
target: ChatDispatchTarget,
@@ -674,7 +674,7 @@ export const PullRequestSection: React.FC<{
const message = e instanceof Error ? e.message : String(e);
toast.error(t('gitView.pr.toast.sendMessageFailed'), { description: message });
});
}, []);
}, [t]);
const renderCheckRunSummary = React.useCallback((run: GitHubCheckRun) => {
const status = run.status || 'unknown';
@@ -804,7 +804,7 @@ export const PullRequestSection: React.FC<{
) : null}
</div>
);
}, [expandedCheckStepKeys, formatTimestamp]);
}, [expandedCheckStepKeys, formatTimestamp, t]);
const sendFailedChecksToChat = React.useCallback(async () => {
setActiveMainTab('chat');
@@ -860,7 +860,7 @@ export const PullRequestSection: React.FC<{
const message = e instanceof Error ? e.message : String(e);
toast.error(t('gitView.pr.toast.loadChecksFailed'), { description: message });
}
}, [directory, dispatchSyntheticPrompt, github, pr, resolveChatDispatchTarget, setActiveMainTab]);
}, [directory, dispatchSyntheticPrompt, github, pr, resolveChatDispatchTarget, setActiveMainTab, t]);
const sendCommentsToChat = React.useCallback(async () => {
setActiveMainTab('chat');
@@ -899,7 +899,7 @@ export const PullRequestSection: React.FC<{
const message = e instanceof Error ? e.message : String(e);
toast.error(t('gitView.pr.toast.loadPrCommentsFailed'), { description: message });
}
}, [directory, dispatchSyntheticPrompt, github, pr, resolveChatDispatchTarget, setActiveMainTab]);
}, [directory, dispatchSyntheticPrompt, github, pr, resolveChatDispatchTarget, setActiveMainTab, t]);
const sendSingleCommentToChat = React.useCallback(async (comment: TimelineCommentItem) => {
setCommentsDialogOpen(false);
@@ -1142,7 +1142,7 @@ export const PullRequestSection: React.FC<{
} finally {
setIsGenerating(false);
}
}, [additionalContext, branch, directory, isGenerating, onGeneratedDescription, targetBaseBranch]);
}, [additionalContext, branch, directory, isGenerating, onGeneratedDescription, targetBaseBranch, t]);
const createPr = React.useCallback(async () => {
if (!github?.prCreate) {
@@ -1188,7 +1188,7 @@ export const PullRequestSection: React.FC<{
} finally {
setIsCreating(false);
}
}, [body, branch, directory, draft, github, prStatusKey, refresh, scheduleActionRefresh, selectedRemote, targetBaseBranch, title, updatePrStatus]);
}, [body, branch, directory, draft, github, prStatusKey, refresh, scheduleActionRefresh, selectedRemote, targetBaseBranch, title, updatePrStatus, t]);
const mergePr = React.useCallback(async (pr: GitHubPullRequest) => {
if (!github?.prMerge) {
@@ -1214,7 +1214,7 @@ export const PullRequestSection: React.FC<{
} finally {
setIsMerging(false);
}
}, [directory, github, mergeMethod, refresh, scheduleActionRefresh]);
}, [directory, github, mergeMethod, refresh, scheduleActionRefresh, t]);
const markReady = React.useCallback(async (pr: GitHubPullRequest) => {
if (!github?.prReady) {
@@ -1236,7 +1236,7 @@ export const PullRequestSection: React.FC<{
} finally {
setIsMarkingReady(false);
}
}, [directory, github, refresh, scheduleActionRefresh]);
}, [directory, github, refresh, scheduleActionRefresh, t]);
const updatePr = React.useCallback(async (pr: GitHubPullRequest) => {
if (!github?.prUpdate) {
@@ -1277,7 +1277,7 @@ export const PullRequestSection: React.FC<{
} finally {
setIsUpdating(false);
}
}, [directory, editBody, editTitle, github, prStatusKey, refresh, scheduleActionRefresh, updatePrStatus]);
}, [directory, editBody, editTitle, github, prStatusKey, refresh, scheduleActionRefresh, updatePrStatus, t]);
if (!canShow) {
return null;