Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions apps/hook/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ import {
startAnnotateServer,
handleAnnotateServerReady,
} from "@plannotator/server/annotate";
import { type DiffType, getVcsContext, runVcsDiff, gitRuntime } from "@plannotator/server/vcs";
import { type DiffType, type FileMetadata, getVcsContext, runVcsDiff, gitRuntime } from "@plannotator/server/vcs";
import { loadConfig, resolveDefaultDiffType, resolveUseJina } from "@plannotator/shared/config";
import { htmlToMarkdown } from "@plannotator/shared/html-to-markdown";
import { urlToMarkdown } from "@plannotator/shared/url-to-markdown";
Expand Down Expand Up @@ -216,6 +216,7 @@ if (args[0] === "sessions") {
let initialDiffType: DiffType | undefined;
let agentCwd: string | undefined;
let worktreeCleanup: (() => void | Promise<void>) | undefined;
let initialFileMeta: Record<string, FileMetadata> | undefined;

if (isPRMode) {
// --- PR Review Mode ---
Expand Down Expand Up @@ -388,11 +389,12 @@ if (args[0] === "sessions") {
} else {
// --- Local Review Mode ---
gitContext = await getVcsContext();
initialDiffType = gitContext.vcsType === "p4" ? "p4-default" : resolveDefaultDiffType(loadConfig());
initialDiffType = gitContext.vcsType === "p4" ? "p4-default" : gitContext.vcsType === "gitbutler" ? "gitbutler:workspace" : resolveDefaultDiffType(loadConfig());
const diffResult = await runVcsDiff(initialDiffType, gitContext.defaultBranch);
rawPatch = diffResult.patch;
gitRef = diffResult.label;
diffError = diffResult.error;
initialFileMeta = diffResult.fileMeta;
}

const reviewProject = (await detectProjectName()) ?? "_unknown";
Expand All @@ -402,6 +404,7 @@ if (args[0] === "sessions") {
rawPatch,
gitRef,
error: diffError,
fileMeta: initialFileMeta,
origin: detectedOrigin,
diffType: gitContext ? (initialDiffType ?? "unstaged") : undefined,
gitContext,
Expand Down
18 changes: 15 additions & 3 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion packages/review-editor/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ import {
REVIEW_PR_COMMENTS_PANEL_ID,
REVIEW_PR_CHECKS_PANEL_ID,
} from './dock/reviewPanelTypes';
import type { DiffFile } from './types';
import type { DiffFile, FileMetadata } from './types';
import type { DiffOption, WorktreeInfo, GitContext } from '@plannotator/shared/types';
import type { PRMetadata } from '@plannotator/shared/pr-provider';
import { altKey } from '@plannotator/ui/utils/platform';
Expand Down Expand Up @@ -155,6 +155,7 @@ const ReviewApp: React.FC = () => {
const [gitUser, setGitUser] = useState<string | undefined>();
const [isWSL, setIsWSL] = useState(false);
const [diffType, setDiffType] = useState<string>('uncommitted');
const [fileMeta, setFileMeta] = useState<Record<string, FileMetadata> | null>(null);
const [gitContext, setGitContext] = useState<GitContext | null>(null);
const [agentCwd, setAgentCwd] = useState<string | null>(null);
const [isLoadingDiff, setIsLoadingDiff] = useState(false);
Expand Down Expand Up @@ -656,6 +657,7 @@ const ReviewApp: React.FC = () => {
setFiles(apiFiles);
if (data.origin) setOrigin(data.origin);
if (data.diffType) setDiffType(data.diffType);
if (data.fileMeta) setFileMeta(data.fileMeta);
if (data.gitContext) setGitContext(data.gitContext);
if (data.agentCwd) setAgentCwd(data.agentCwd);
if (data.sharingEnabled !== undefined) setSharingEnabled(data.sharingEnabled);
Expand Down Expand Up @@ -912,6 +914,7 @@ const ReviewApp: React.FC = () => {
setDiffData(prev => prev ? { ...prev, rawPatch: data.rawPatch, gitRef: data.gitRef, diffType: data.diffType } : prev);
setFiles(nextFiles);
setDiffType(data.diffType);
setFileMeta(data.fileMeta ?? null);
setActiveFileIndex(0);
setPendingSelection(null);
setDiffError(data.error || null);
Expand Down Expand Up @@ -1662,6 +1665,9 @@ const ReviewApp: React.FC = () => {
activeWorktreePath={activeWorktreePath}
onSelectWorktree={handleWorktreeSwitch}
currentBranch={gitContext?.currentBranch}
vcsType={gitContext?.vcsType}
fileMeta={fileMeta ?? undefined}
hideLaneLabel={diffType.startsWith('gitbutler:') && diffType !== 'gitbutler:workspace'}
stagedFiles={stagedFiles}
onCopyRawDiff={handleCopyDiff}
canCopyRawDiff={!!diffData?.rawPatch}
Expand Down
10 changes: 9 additions & 1 deletion packages/review-editor/components/FileTree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import type { DiffOption, WorktreeInfo } from '@plannotator/shared/types';
import { buildFileTree, getAncestorPaths, getAllFolderPaths } from '../utils/buildFileTree';
import { FileTreeNodeItem } from './FileTreeNode';
import { getReviewSearchSideLabel, type ReviewSearchFileGroup, type ReviewSearchMatch } from '../utils/reviewSearch';
import type { DiffFile } from '../types';
import type { DiffFile, FileMetadata } from '../types';
import { OverlayScrollArea } from '@plannotator/ui/components/OverlayScrollArea';

interface FileTreeProps {
Expand All @@ -27,6 +27,9 @@ interface FileTreeProps {
activeWorktreePath?: string | null;
onSelectWorktree?: (path: string | null) => void;
currentBranch?: string;
vcsType?: string;
fileMeta?: Record<string, FileMetadata>;
hideLaneLabel?: boolean;
stagedFiles?: Set<string>;
onCopyRawDiff?: () => void;
canCopyRawDiff?: boolean;
Expand Down Expand Up @@ -66,6 +69,9 @@ export const FileTree: React.FC<FileTreeProps> = ({
activeWorktreePath,
onSelectWorktree,
currentBranch,
vcsType,
fileMeta,
hideLaneLabel,
stagedFiles,
onCopyRawDiff,
canCopyRawDiff = false,
Expand Down Expand Up @@ -391,6 +397,8 @@ export const FileTree: React.FC<FileTreeProps> = ({
hideViewedFiles={hideViewedFiles}
getAnnotationCount={getAnnotationCount}
stagedFiles={stagedFiles}
fileMeta={fileMeta}
hideLaneLabel={hideLaneLabel}
/>
))
)}
Expand Down
28 changes: 28 additions & 0 deletions packages/review-editor/components/FileTreeNode.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import type { FileTreeNode as TreeNode } from '../utils/buildFileTree';
import type { FileMetadata } from '../types';

interface FileTreeNodeProps {
node: TreeNode;
Expand All @@ -13,6 +14,8 @@ interface FileTreeNodeProps {
hideViewedFiles: boolean;
getAnnotationCount: (filePath: string) => number;
stagedFiles?: Set<string>;
fileMeta?: Record<string, FileMetadata>;
hideLaneLabel?: boolean;
}

function hasVisibleChildren(
Expand Down Expand Up @@ -44,6 +47,8 @@ export const FileTreeNodeItem: React.FC<FileTreeNodeProps> = ({
hideViewedFiles,
getAnnotationCount,
stagedFiles,
fileMeta,
hideLaneLabel,
}) => {
const paddingLeft = 4 + node.depth * 8;

Expand Down Expand Up @@ -92,6 +97,8 @@ export const FileTreeNodeItem: React.FC<FileTreeNodeProps> = ({
hideViewedFiles={hideViewedFiles}
getAnnotationCount={getAnnotationCount}
stagedFiles={stagedFiles}
fileMeta={fileMeta}
hideLaneLabel={hideLaneLabel}
/>
))}
</>
Expand All @@ -103,6 +110,7 @@ export const FileTreeNodeItem: React.FC<FileTreeNodeProps> = ({
const isViewed = viewedFiles.has(node.path);
const isStaged = stagedFiles?.has(node.path) ?? false;
const annotationCount = getAnnotationCount(node.path);
const meta = fileMeta?.[node.path];

if (hideViewedFiles && isViewed && !isActive) {
return null;
Expand Down Expand Up @@ -141,6 +149,26 @@ export const FileTreeNodeItem: React.FC<FileTreeNodeProps> = ({
{isStaged && (
<span className="text-primary font-medium" title="Staged (git add)">+</span>
)}
{meta && meta.lanes && (() => {
const srcChar = meta.source === 'committed' ? 'C' : meta.source === 'uncommitted' ? 'S' : meta.source === 'mixed' ? 'M' : null;
const srcWord = meta.source === 'committed' ? 'committed' : meta.source === 'uncommitted' ? 'staged' : meta.source === 'mixed' ? 'committed + staged' : null;
const srcColor = meta.source === 'committed' ? 'text-blue-400' : meta.source === 'uncommitted' ? 'text-orange-400' : meta.source === 'mixed' ? 'text-purple-400' : 'text-muted-foreground/60';
const laneLabel = meta.lanes.length === 1 ? meta.lanes[0] : `${meta.lanes.length} lanes`;
const hoverTitle = (() => {
if (meta.laneDetails && meta.laneDetails.length > 1) {
return meta.laneDetails
.map((d) => `${d.source === 'committed' ? 'committed' : 'staged'} to ${d.lane}`)
.join(', ');
}
if (srcWord && laneLabel) return `${srcWord} to ${meta.lanes.join(', ')}`;
if (srcWord) return srcWord;
return meta.lanes.join(', ');
})();
const displayLabel = [srcChar, hideLaneLabel ? null : laneLabel].filter(Boolean).join(' · ');
return displayLabel ? (
<span title={hoverTitle} className={`font-medium leading-none ${srcColor}`}>{displayLabel}</span>
) : null;
})()}
{annotationCount > 0 && (
<span className="text-primary font-medium">{annotationCount}</span>
)}
Expand Down
2 changes: 2 additions & 0 deletions packages/review-editor/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ export interface DiffFile {
additions: number;
deletions: number;
}

export type { FileMetadata } from "@plannotator/shared/types";
Loading