diff --git a/src/renderer/src/components/editor/CombinedDiffViewer.tsx b/src/renderer/src/components/editor/CombinedDiffViewer.tsx index 021a376ac6c..c873f7fff00 100644 --- a/src/renderer/src/components/editor/CombinedDiffViewer.tsx +++ b/src/renderer/src/components/editor/CombinedDiffViewer.tsx @@ -187,6 +187,12 @@ export default function CombinedDiffViewer({ const [sectionHeights, setSectionHeights] = useState>({}) const [clearNotesDialogOpen, setClearNotesDialogOpen] = useState(false) const [isClearingNotes, setIsClearingNotes] = useState(false) + const clearNotesDialogVisible = clearNotesDialogOpen && (diffCommentCount > 0 || isClearingNotes) + if (clearNotesDialogOpen && !clearNotesDialogVisible) { + // Why: notes may be cleared outside this dialog; keep the modal closed in + // the same render instead of showing an empty confirmation for one frame. + setClearNotesDialogOpen(false) + } const [notesCopied, setNotesCopied] = useState(false) const mountedRef = useRef(true) // Why: copy feedback is created by the copy action, so the same handler owns @@ -674,10 +680,17 @@ export default function CombinedDiffViewer({ () => createCombinedDiffSectionIndexMap(sections), [sections] ) - const [activeTreeSectionKey, setActiveTreeSectionKey] = useState(null) - useEffect(() => { - setActiveTreeSectionKey(null) - }, [entrySignature]) + const [activeTreeSectionState, setActiveTreeSectionState] = useState<{ + entrySignature: string + key: string | null + }>(() => ({ entrySignature, key: null })) + const activeTreeSectionKey = + activeTreeSectionState.entrySignature === entrySignature ? activeTreeSectionState.key : null + if (activeTreeSectionState.entrySignature !== entrySignature) { + // Why: the tree highlight belongs to one diff entry set and must not flash + // on another entry set before an Effect reset would run. + setActiveTreeSectionState({ entrySignature, key: null }) + } const viewedSectionKeys = React.useMemo( () => new Set(sections.filter((section) => !section.loading).map((section) => section.key)), [sections] @@ -693,10 +706,13 @@ export default function CombinedDiffViewer({ scrollToIndex: (index) => virtualizer.scrollToIndex(index, { align: 'start' }) }) if (navigatedIndex !== null) { - setActiveTreeSectionKey(sectionsRef.current[navigatedIndex]?.key ?? null) + setActiveTreeSectionState({ + entrySignature, + key: sectionsRef.current[navigatedIndex]?.key ?? null + }) } }, - [sectionIndexByKey, toggleSection, treeMode, virtualizer] + [entrySignature, sectionIndexByKey, toggleSection, treeMode, virtualizer] ) const setAllSectionsCollapsed = useCallback((collapsed: boolean) => { @@ -1010,12 +1026,6 @@ export default function CombinedDiffViewer({ [updateCombinedDiffScrollbar] ) - useEffect(() => { - if (diffCommentCount === 0 && !isClearingNotes) { - setClearNotesDialogOpen(false) - } - }, [diffCommentCount, isClearingNotes]) - const handleCopyNotes = useCallback(async (): Promise => { if (diffCommentCount === 0) { return @@ -1368,7 +1378,7 @@ export default function CombinedDiffViewer({ { if (!open && !isClearingNotes) { setClearNotesDialogOpen(false)