Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
80 commits
Select commit Hold shift + click to select a range
65d9a3c
🤖 Rename ChatMetaSidebar to RightSidebar
ammar-agent Oct 17, 2025
03fdff5
🤖 Add code review UI with hunk-based review system
ammar-agent Oct 17, 2025
a8ef9c9
🤖 Fix code review: use executeBash IPC instead of direct exec
ammar-agent Oct 18, 2025
a96b2f2
🤖 Add diff base selector to code review panel
ammar-agent Oct 18, 2025
6fb52b7
🤖 Show review filters even when no changes found
ammar-agent Oct 18, 2025
458b98d
🤖 Expand Review tab to double width with animation
ammar-agent Oct 18, 2025
9b68222
🤖 Fix hysteresis: disable collapse when Review tab active
ammar-agent Oct 18, 2025
5911103
🤖 Fix branch comparison: use three-dot diff for branch refs
ammar-agent Oct 18, 2025
9e61b30
🤖 Add error display to review panel
ammar-agent Oct 18, 2025
8c07a2e
🤖 Show executed git command in empty state
ammar-agent Oct 18, 2025
7f76f31
🤖 Make command text easily selectable with label
ammar-agent Oct 18, 2025
239a826
🤖 Move command label outside container for cleaner look
ammar-agent Oct 18, 2025
2513d7a
🤖 Add diagnostic info to code review empty state
ammar-agent Oct 18, 2025
9196d9f
🤖 Add truncation support for large git diffs in code review
ammar-agent Oct 18, 2025
b5515c0
🤖 Add comprehensive tests for git diff parser
ammar-agent Oct 18, 2025
2e88e6b
🤖 Add file tree with filtering to code review pane
ammar-agent Oct 18, 2025
e1bc4ec
🤖 Expand Review tab to use more horizontal space
ammar-agent Oct 18, 2025
a1ff30e
🤖 Fix Review tab scrolling with proper flex layout
ammar-agent Oct 18, 2025
f502f4f
🤖 Add custom drag-resize for Review tab sidebar
ammar-agent Oct 18, 2025
c2e5465
🤖 Add comprehensive comments to resize implementation
ammar-agent Oct 18, 2025
874def7
🤖 Remove Tools tab and add keyboard shortcuts for tabs
ammar-agent Oct 18, 2025
dd9703a
🤖 Add COSTS_TAB and REVIEW_TAB keybinds to keybinds.ts
ammar-agent Oct 18, 2025
918eca7
🤖 Use styled Tooltip component for tab keyboard hints
ammar-agent Oct 18, 2025
18f3395
🤖 Revert to native title tooltips for tab keyboard hints
ammar-agent Oct 18, 2025
7897d7b
🤖 Add styled tooltips to tabs without disrupting layout
ammar-agent Oct 18, 2025
49aafb0
🤖 Improve Review tab styling and responsiveness
ammar-agent Oct 18, 2025
a83a41d
🤖 Refactor Review tab controls and improve UX
ammar-agent Oct 18, 2025
24358ca
🤖 Improve Review tab UX and fix responsive layout
ammar-agent Oct 18, 2025
b75ad06
🤖 Fix Review tab UX issues and improve responsiveness
ammar-agent Oct 18, 2025
1923818
🤖 Clean up Review tab UI and fix issues
ammar-agent Oct 18, 2025
5d28438
🤖 Fix responsive layout with CSS container queries
ammar-agent Oct 18, 2025
d93c5ab
🤖 Fix UX issues: ellipsis truncation, tool header responsiveness, ver…
ammar-agent Oct 18, 2025
1e51d87
Increase container query threshold to 800px for better FileTree posit…
ammar-agent Oct 18, 2025
ec47bfc
🤖 Fix renamed file filtering and EmptyState layout in Review panel
ammar-agent Oct 18, 2025
8b53178
🤖 Improve Review tab UX: LoC styling, token meter placement, button g…
ammar-agent Oct 18, 2025
8e0f632
🤖 Fix remaining UX issues: diff highlights, responsive hiding, meter …
ammar-agent Oct 18, 2025
c7c98b2
🤖 Show VerticalTokenMeter when Review tab is active - single render p…
ammar-agent Oct 18, 2025
0ca613e
🤖 Move ResizeHandle to right of VerticalTokenMeter
ammar-agent Oct 18, 2025
b111bd0
🤖 Fix diff rendering and Review UI polish
ammar-agent Oct 18, 2025
44ba59e
🤖 UX polish: status nowrap, concise warnings, shared diff rendering, …
ammar-agent Oct 18, 2025
c777fff
🤖 Fix rename detection with -M flag and comprehensive TDD
ammar-agent Oct 18, 2025
0e07e79
🤖 Robustly fix jagged diff highlighting during horizontal scroll
ammar-agent Oct 18, 2025
5a4aa6d
🤖 Fix infinite scroll from background extension
ammar-agent Oct 18, 2025
84e6048
🤖 Guaranteed fix: CSS Grid for uniform diff line widths
ammar-agent Oct 18, 2025
2ce7f9f
🤖 CSS Container Queries for Review layout collapse
ammar-agent Oct 18, 2025
f312277
🤖 Fix diff base selector: 'Diff:' → 'Base:' and show custom values
ammar-agent Oct 18, 2025
c0933e0
🤖 Unified base selector: single input with suggestions (no custom tier)
ammar-agent Oct 18, 2025
185085a
🤖 Buffer base input changes to prevent flickering
ammar-agent Oct 18, 2025
b48d3c3
🤖 Simplify Code Review tab to MVP (view-only)
ammar-agent Oct 18, 2025
84826c7
🤖 Remove accept/reject/unreviewed filters from ReviewControls
ammar-agent Oct 18, 2025
e109ea3
🤖 Scope j/k keyboard navigation to focused Review panel
ammar-agent Oct 18, 2025
27ed286
🤖 Add simple review notes feature for Code Review tab
ammar-agent Oct 18, 2025
f9a2f87
🤖 Add 'Include dirty' checkbox to Code Review controls
ammar-agent Oct 18, 2025
3842357
🤖 Fix review note UI issues
ammar-agent Oct 18, 2025
125c0bd
🤖 Simplify review note selection UI
ammar-agent Oct 18, 2025
8a992f0
🤖 Fix review note UX: drag selection and keyboard focus
ammar-agent Oct 18, 2025
4ae0f40
🤖 Include selected code in review notes and improve textarea styling
ammar-agent Oct 18, 2025
fd79732
🤖 Restore background and remove buttons from review note textarea
ammar-agent Oct 18, 2025
ab78159
🤖 Add shift-click support for line range selection
ammar-agent Oct 18, 2025
dbc5f2d
🤖 Update placeholder text for review note textarea
ammar-agent Oct 18, 2025
e37bc43
🤖 Add review note support to FileEditToolCall diffs
ammar-agent Oct 18, 2025
da3a9ae
🤖 Remove unused onReviewNote wiring
ammar-agent Oct 18, 2025
3a0cbe0
🤖 Remove drag-to-select, restore text selection for copy/paste
ammar-agent Oct 18, 2025
8bc2df9
🤖 Add refresh button to ReviewControls
ammar-agent Oct 18, 2025
9385f04
🤖 Remove unused useLayoutMode hook
ammar-agent Oct 18, 2025
7efb67d
🤖 Fix refresh button tooltip using Tooltip component
ammar-agent Oct 18, 2025
2d3d4a5
🤖 Extract common path prefix and make Clear Filter subtle
ammar-agent Oct 18, 2025
7066c5f
🤖 Fix common prefix to be display-only, keep full paths for git commands
ammar-agent Oct 18, 2025
a11ca88
🤖 Skip common prefix folders in tree display
ammar-agent Oct 18, 2025
75a1c36
🤖 DRY improvements: remove dead code, extract git command builder, co…
ammar-agent Oct 18, 2025
e178670
🤖 Fix P1 issues: resize persistence, mouse position capture, pure ren…
ammar-agent Oct 18, 2025
cd855a9
🤖 Fix HunkViewer pure rename detection
ammar-agent Oct 18, 2025
4c5bfee
🤖 Fix bash tool truncate test to match new success+truncated behavior
ammar-agent Oct 18, 2025
0b1829e
🤖 Add Set Default button for review base with global default persistence
ammar-agent Oct 18, 2025
3528955
🤖 Format AIView.tsx
ammar-agent Oct 18, 2025
30179a7
🤖 Show full file tree without scrolling in vertical layout mode
ammar-agent Oct 18, 2025
8f07c1a
🤖 Fix vertical layout: allow file tree to grow while keeping scrollbar
ammar-agent Oct 18, 2025
28830d4
🤖 Fix integration test: IPC bash uses truncate policy, not tmpfile
ammar-agent Oct 18, 2025
0abee63
🤖 Fix E2E test: Replace removed Tools tab with Code Review tab
ammar-agent Oct 18, 2025
ef602d6
🤖 Fix E2E test: Use correct tab label "Review" not "Code Review"
ammar-agent Oct 18, 2025
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
62 changes: 57 additions & 5 deletions src/components/AIView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import { RetryBarrier } from "./Messages/ChatBarrier/RetryBarrier";
import { PinnedTodoList } from "./PinnedTodoList";
import { getAutoRetryKey } from "@/constants/storage";
import { ChatInput, type ChatInputAPI } from "./ChatInput";
import { ChatMetaSidebar } from "./ChatMetaSidebar";
import { RightSidebar, type TabType } from "./RightSidebar";
import { useResizableSidebar } from "@/hooks/useResizableSidebar";
import {
shouldShowInterruptedBarrier,
mergeConsecutiveStreamErrors,
Expand Down Expand Up @@ -44,7 +45,7 @@ const ViewContainer = styled.div`

const ChatArea = styled.div`
flex: 1;
min-width: 750px;
min-width: 400px; /* Reduced from 750px to allow narrower layout when Review panel is wide */
display: flex;
flex-direction: column;
`;
Expand All @@ -64,13 +65,26 @@ const WorkspaceTitle = styled.div`
display: flex;
align-items: center;
gap: 8px;
min-width: 0; /* Allow flex children to shrink */
overflow: hidden;
`;

const WorkspacePath = styled.span`
font-family: var(--font-monospace);
color: #888;
font-weight: 400;
font-size: 11px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
`;

const WorkspaceName = styled.span`
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
min-width: 0;
`;

const TerminalIconButton = styled.button`
Expand Down Expand Up @@ -197,12 +211,33 @@ const AIViewInner: React.FC<AIViewProps> = ({
}) => {
const chatAreaRef = useRef<HTMLDivElement>(null);

// NEW: Get workspace state from store (only re-renders when THIS workspace changes)
// Track active tab to conditionally enable resize functionality
// RightSidebar notifies us of tab changes via onTabChange callback
const [activeTab, setActiveTab] = useState<TabType>("costs");
const isReviewTabActive = activeTab === "review";

// Resizable sidebar for Review tab only
// Hook encapsulates all drag logic, persistence, and constraints
// Returns width to apply to RightSidebar and startResize for handle's onMouseDown
const {
width: sidebarWidth,
isResizing,
startResize,
} = useResizableSidebar({
enabled: isReviewTabActive, // Only active on Review tab
defaultWidth: 600, // Initial width or fallback
minWidth: 300, // Can't shrink smaller
maxWidth: 1200, // Can't grow larger
storageKey: "review-sidebar-width", // Persists across sessions
});

// Get workspace state from store (only re-renders when THIS workspace changes)
const workspaceState = useWorkspaceState(workspaceId);
const aggregator = useWorkspaceAggregator(workspaceId);

// Get git status for this workspace
const gitStatus = useGitStatus(workspaceId);

const [editingMessage, setEditingMessage] = useState<{ id: string; content: string } | undefined>(
undefined
);
Expand Down Expand Up @@ -239,6 +274,11 @@ const AIViewInner: React.FC<AIViewProps> = ({
chatInputAPI.current = api;
}, []);

// Handler for review notes from Code Review tab
const handleReviewNote = useCallback((note: string) => {
chatInputAPI.current?.appendText(note);
}, []);

// Thinking level state from context
const { thinkingLevel: currentWorkspaceThinking, setThinkingLevel } = useThinking();

Expand Down Expand Up @@ -431,7 +471,9 @@ const AIViewInner: React.FC<AIViewProps> = ({
workspaceId={workspaceId}
tooltipPosition="bottom"
/>
{projectName} / {branch}
<WorkspaceName>
{projectName} / {branch}
</WorkspaceName>
<WorkspacePath>{namedWorkspacePath}</WorkspacePath>
<TooltipWrapper inline>
<TerminalIconButton onClick={handleOpenTerminal}>
Expand Down Expand Up @@ -555,7 +597,17 @@ const AIViewInner: React.FC<AIViewProps> = ({
/>
</ChatArea>

<ChatMetaSidebar key={workspaceId} workspaceId={workspaceId} chatAreaRef={chatAreaRef} />
<RightSidebar
key={workspaceId}
workspaceId={workspaceId}
workspacePath={namedWorkspacePath}
chatAreaRef={chatAreaRef}
onTabChange={setActiveTab} // Notifies us when tab changes
width={isReviewTabActive ? sidebarWidth : undefined} // Custom width only on Review tab
onStartResize={isReviewTabActive ? startResize : undefined} // Pass resize handler when Review active
isResizing={isResizing} // Pass resizing state
onReviewNote={handleReviewNote} // Pass review note handler to append to chat
/>
</ViewContainer>
);
};
Expand Down
94 changes: 62 additions & 32 deletions src/components/ChatInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ const InputSection = styled.div`
display: flex;
flex-direction: column;
gap: 8px;
container-type: inline-size; /* Enable container queries for responsive behavior */
`;

const InputControls = styled.div`
Expand All @@ -72,6 +73,12 @@ const ModeToggleWrapper = styled.div`
align-items: center;
gap: 6px;
margin-left: auto;

/* Hide mode toggle on narrow containers */
/* Note: Text area border changes color with mode, so this omission is acceptable */
@container (max-width: 700px) {
display: none;
}
`;

const StyledToggleContainer = styled.div<{ mode: UIMode }>`
Expand Down Expand Up @@ -121,11 +128,19 @@ const ModelDisplayWrapper = styled.div`
gap: 4px;
margin-right: 12px;
height: 11px;

/* Hide help indicators on narrow containers */
@container (max-width: 700px) {
.help-indicator-wrapper {
display: none;
}
}
`;

export interface ChatInputAPI {
focus: () => void;
restoreText: (text: string) => void;
appendText: (text: string) => void;
}

export interface ChatInputProps {
Expand Down Expand Up @@ -258,15 +273,26 @@ export const ChatInput: React.FC<ChatInputProps> = ({
[focusMessageInput]
);

// Method to append text to input (used by Code Review notes)
const appendText = useCallback((text: string) => {
setInput((prev) => {
// Add blank line before if there's existing content
const separator = prev.trim() ? "\n\n" : "";
return prev + separator + text;
});
// Don't focus - user wants to keep reviewing
}, []);

// Provide API to parent via callback
useEffect(() => {
if (onReady) {
onReady({
focus: focusMessageInput,
restoreText,
appendText,
});
}
}, [onReady, focusMessageInput, restoreText]);
}, [onReady, focusMessageInput, restoreText, appendText]);

useEffect(() => {
const handleGlobalKeyDown = (event: KeyboardEvent) => {
Expand Down Expand Up @@ -871,25 +897,27 @@ export const ChatInput: React.FC<ChatInputProps> = ({
recentModels={recentModels}
onComplete={() => inputRef.current?.focus()}
/>
<TooltipWrapper inline>
<HelpIndicator>?</HelpIndicator>
<Tooltip className="tooltip" align="left" width="wide">
<strong>Click to edit</strong> or use{" "}
{formatKeybind(KEYBINDS.OPEN_MODEL_SELECTOR)}
<br />
<br />
<strong>Abbreviations:</strong>
<br />• <code>/model opus</code> - Claude Opus 4.1
<br />• <code>/model sonnet</code> - Claude Sonnet 4.5
<br />
<br />
<strong>Full format:</strong>
<br />
<code>/model provider:model-name</code>
<br />
(e.g., <code>/model anthropic:claude-sonnet-4-5</code>)
</Tooltip>
</TooltipWrapper>
<span className="help-indicator-wrapper">
<TooltipWrapper inline>
<HelpIndicator>?</HelpIndicator>
<Tooltip className="tooltip" align="left" width="wide">
<strong>Click to edit</strong> or use{" "}
{formatKeybind(KEYBINDS.OPEN_MODEL_SELECTOR)}
<br />
<br />
<strong>Abbreviations:</strong>
<br />• <code>/model opus</code> - Claude Opus 4.1
<br />• <code>/model sonnet</code> - Claude Sonnet 4.5
<br />
<br />
<strong>Full format:</strong>
<br />
<code>/model provider:model-name</code>
<br />
(e.g., <code>/model anthropic:claude-sonnet-4-5</code>)
</Tooltip>
</TooltipWrapper>
</span>
</ModelDisplayWrapper>
</ChatToggles>
<ModeToggleWrapper>
Expand All @@ -903,18 +931,20 @@ export const ChatInput: React.FC<ChatInputProps> = ({
onChange={setMode}
/>
</StyledToggleContainer>
<TooltipWrapper inline>
<HelpIndicator>?</HelpIndicator>
<Tooltip className="tooltip" align="center" width="wide">
<strong>Exec Mode:</strong> AI edits files and execute commands
<br />
<br />
<strong>Plan Mode:</strong> AI proposes plans but does not edit files
<br />
<br />
Toggle with: {formatKeybind(KEYBINDS.TOGGLE_MODE)}
</Tooltip>
</TooltipWrapper>
<span className="help-indicator-wrapper">
<TooltipWrapper inline>
<HelpIndicator>?</HelpIndicator>
<Tooltip className="tooltip" align="center" width="wide">
<strong>Exec Mode:</strong> AI edits files and execute commands
<br />
<br />
<strong>Plan Mode:</strong> AI proposes plans but does not edit files
<br />
<br />
Toggle with: {formatKeybind(KEYBINDS.TOGGLE_MODE)}
</Tooltip>
</TooltipWrapper>
</span>
</ModeToggleWrapper>
</ModeTogglesRow>
</ModeToggles>
Expand Down
Loading