feat: add last-turn diff view

Adds a Last turn scope to DiffView that renders OpenCode snapshot diffs from the latest user message summary without re-fetching git contents. The view hides Review in that mode and carries the selected diff scope through main and context-panel navigation.

Connects latest-turn changed-file chips in chat to the snapshot diff view on desktop and mobile, while keeping older turn chips static/read-only to avoid misleading affordances and extra subscriptions. Updates localized labels and empty states plus changelog.

Validation: bun run type-check (packages/ui); bun run lint (packages/ui).
This commit is contained in:
Bohdan Triapitsyn
2026-07-07 14:44:20 +03:00
parent 1c44146a4f
commit 292e78f067
19 changed files with 269 additions and 84 deletions
@@ -4,13 +4,11 @@ import { Popover } from '@base-ui/react/popover';
import { useDirectoryStore } from '@/stores/useDirectoryStore';
import { useIsGitRepo } from '@/stores/useGitStore';
import { useUIStore } from '@/stores/useUIStore';
import { RuntimeAPIContext } from '@/contexts/runtimeAPIContext';
import {
type ChangedFile,
type ChangedFileEntry,
FILE_EDIT_TOOLS,
extractChangedFiles,
isGitFile,
toRelativePath,
} from './changedFiles';
import { ChangedFilesList } from './ChangedFilesList';
@@ -18,7 +16,6 @@ import { changedFilesPopoverClassName, changedFilesPopoverStyle } from './change
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip';
import { Icon } from "@/components/icon/Icon";
import type { TurnActivityRecord } from './lib/turns/types';
import { toAbsoluteFilePath } from '@/lib/path-utils';
interface TurnChangedFilesDropdownProps {
activityParts: TurnActivityRecord[] | undefined;
@@ -29,7 +26,6 @@ export const TurnChangedFilesDropdown: React.FC<TurnChangedFilesDropdownProps> =
const [portalContainer, setPortalContainer] = React.useState<HTMLElement | null>(null);
const triggerButtonRef = React.useRef<HTMLButtonElement | null>(null);
const currentDirectory = useDirectoryStore((s) => s.currentDirectory);
const runtime = React.useContext(RuntimeAPIContext);
const isGitRepo = useIsGitRepo(currentDirectory);
const changedFiles = React.useMemo<ChangedFile[]>(() => {
@@ -56,24 +52,16 @@ export const TurnChangedFilesDropdown: React.FC<TurnChangedFilesDropdownProps> =
const handleOpenFile = (file: ChangedFileEntry) => {
if (!currentDirectory) return;
if (isGitFile(file)) return;
const absolutePath = toAbsoluteFilePath(currentDirectory, file.path);
const editor = runtime?.editor;
if (editor) {
void editor.openFile(absolutePath);
setIsExpanded(false);
return;
}
const store = useUIStore.getState();
const relativePath = toRelativePath(file.path, currentDirectory);
if (!store.isMobile) {
store.openContextFile(currentDirectory, absolutePath);
store.openContextDiff(currentDirectory, relativePath, false, 'turn');
setIsExpanded(false);
return;
}
store.navigateToDiff(toRelativePath(file.path, currentDirectory));
store.navigateToDiff(relativePath, false, 'turn');
store.setRightSidebarOpen(false);
setIsExpanded(false);
};