diff --git a/frontend/src/components/DiffCard.tsx b/frontend/src/components/DiffCard.tsx index c224363b..2a776475 100644 --- a/frontend/src/components/DiffCard.tsx +++ b/frontend/src/components/DiffCard.tsx @@ -24,6 +24,7 @@ import type { TaskAttempt } from 'shared/types'; import { useReview, type ReviewDraft } from '@/contexts/ReviewProvider'; import { CommentWidgetLine } from '@/components/diff/CommentWidgetLine'; import { ReviewCommentRenderer } from '@/components/diff/ReviewCommentRenderer'; +import { useDiffViewMode } from '@/stores/useDiffViewStore'; type Props = { diff: Diff; @@ -53,6 +54,7 @@ export default function DiffCard({ const { config } = useUserSystem(); const theme = getActualTheme(config?.theme); const { comments, drafts, setDraft } = useReview(); + const globalMode = useDiffViewMode(); const oldName = diff.oldPath || undefined; const newName = diff.newPath || oldName || 'unknown'; @@ -247,7 +249,9 @@ export default function DiffCard({ diffViewWrap={false} diffViewTheme={theme} diffViewHighlight - diffViewMode={DiffModeEnum.Unified} + diffViewMode={ + globalMode === 'split' ? DiffModeEnum.Split : DiffModeEnum.Unified + } diffViewFontSize={12} diffViewAddWidget onAddWidgetClick={handleAddWidgetClick} diff --git a/frontend/src/components/NormalizedConversation/EditDiffRenderer.tsx b/frontend/src/components/NormalizedConversation/EditDiffRenderer.tsx index def0aa2e..ca44542f 100644 --- a/frontend/src/components/NormalizedConversation/EditDiffRenderer.tsx +++ b/frontend/src/components/NormalizedConversation/EditDiffRenderer.tsx @@ -11,6 +11,8 @@ import { getHighLightLanguageFromPath } from '@/utils/extToLanguage'; import { getActualTheme } from '@/utils/theme'; import '@/styles/diff-style-overrides.css'; import '@/styles/edit-diff-overrides.css'; +import { useDiffViewMode } from '@/stores/useDiffViewStore'; +import DiffViewSwitch from '@/components/diff-view-switch'; type Props = { path: string; @@ -67,6 +69,7 @@ function EditDiffRenderer({ const [expanded, setExpanded] = useExpandable(expansionKey, false); const theme = getActualTheme(config?.theme); + const globalMode = useDiffViewMode(); const { hunks, hideLineNumbers, additions, deletions, isValidDiff } = useMemo( () => processUnifiedDiff(unifiedDiff, hasLineNumbers), @@ -104,13 +107,20 @@ function EditDiffRenderer({ {expanded && (
+
+ +
{isValidDiff ? ( ) : ( diff --git a/frontend/src/components/diff-view-switch.tsx b/frontend/src/components/diff-view-switch.tsx new file mode 100644 index 00000000..9500a1cc --- /dev/null +++ b/frontend/src/components/diff-view-switch.tsx @@ -0,0 +1,66 @@ +import { Columns, FileText } from 'lucide-react'; +import { Button } from '@/components/ui/button'; +import { cn } from '@/lib/utils'; +import { useDiffViewMode, useDiffViewStore } from '@/stores/useDiffViewStore'; + +type Props = { + className?: string; + size?: 'xs' | 'sm'; +}; + +/** + * Segmented switch for Inline vs Split diff modes. + * - Left segment: Inline (Unified) + * - Right segment: Split + * Uses global Zustand store so changing here updates all diffs. + */ +export default function DiffViewSwitch({ className, size = 'xs' }: Props) { + const mode = useDiffViewMode(); + const setMode = useDiffViewStore((s) => s.setMode); + + const isUnified = mode === 'unified'; + + return ( +
+ + +
+ ); +} diff --git a/frontend/src/components/tasks/TaskDetails/DiffTab.tsx b/frontend/src/components/tasks/TaskDetails/DiffTab.tsx index a87783ee..2f0cdd7f 100644 --- a/frontend/src/components/tasks/TaskDetails/DiffTab.tsx +++ b/frontend/src/components/tasks/TaskDetails/DiffTab.tsx @@ -2,6 +2,7 @@ import { useDiffEntries } from '@/hooks/useDiffEntries'; import { useMemo, useCallback, useState, useEffect } from 'react'; import { Loader } from '@/components/ui/loader'; import { Button } from '@/components/ui/button'; +import DiffViewSwitch from '@/components/diff-view-switch'; import DiffCard from '@/components/DiffCard'; import { useDiffSummary } from '@/hooks/useDiffSummary'; import type { TaskAttempt } from 'shared/types'; @@ -131,14 +132,17 @@ function DiffTabContent({ -{deleted} - +
+ + +
)} diff --git a/frontend/src/stores/useDiffViewStore.ts b/frontend/src/stores/useDiffViewStore.ts new file mode 100644 index 00000000..31cf54c2 --- /dev/null +++ b/frontend/src/stores/useDiffViewStore.ts @@ -0,0 +1,19 @@ +import { create } from 'zustand'; + +export type DiffViewMode = 'unified' | 'split'; + +type State = { + mode: DiffViewMode; + setMode: (mode: DiffViewMode) => void; + toggle: () => void; +}; + +export const useDiffViewStore = create((set) => ({ + mode: 'unified', + setMode: (mode) => set({ mode }), + toggle: () => + set((s) => ({ mode: s.mode === 'unified' ? 'split' : 'unified' })), +})); + +export const useDiffViewMode = () => useDiffViewStore((s) => s.mode); +export const useToggleDiffViewMode = () => useDiffViewStore((s) => s.toggle);