Skip to content

Commit 8802373

Browse files
committed
feat(code): remove right sidebar
1 parent f600d9a commit 8802373

33 files changed

+503
-351
lines changed

apps/code/src/renderer/components/GlobalEventHandlers.tsx

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1+
import { useReviewNavigationStore } from "@features/code-review/stores/reviewNavigationStore";
12
import { useFolders } from "@features/folders/hooks/useFolders";
23
import { usePanelLayoutStore } from "@features/panels/store/panelLayoutStore";
3-
import { useRightSidebarStore } from "@features/right-sidebar";
44
import { useSettingsDialogStore } from "@features/settings/stores/settingsDialogStore";
55
import { useSidebarData } from "@features/sidebar/hooks/useSidebarData";
66
import { useVisualTaskOrder } from "@features/sidebar/hooks/useVisualTaskOrder";
@@ -46,7 +46,12 @@ export function GlobalEventHandlers({
4646
const { data: workspaces = {} } = useWorkspaces();
4747
const clearAllLayouts = usePanelLayoutStore((state) => state.clearAllLayouts);
4848
const toggleLeftSidebar = useSidebarStore((state) => state.toggle);
49-
const toggleRightSidebar = useRightSidebarStore((state) => state.toggle);
49+
const setReviewMode = useReviewNavigationStore(
50+
(state) => state.setReviewMode,
51+
);
52+
const getReviewMode = useReviewNavigationStore(
53+
(state) => state.getReviewMode,
54+
);
5055

5156
const currentTaskId = view.type === "task-detail" ? view.data?.id : undefined;
5257
const { workspace: currentWorkspace, handleToggleFocus } = useFocusWorkspace(
@@ -163,8 +168,14 @@ export function GlobalEventHandlers({
163168
useHotkeys(SHORTCUTS.SETTINGS, handleOpenSettings, globalOptions);
164169
useHotkeys(SHORTCUTS.GO_BACK, goBack, globalOptions);
165170
useHotkeys(SHORTCUTS.GO_FORWARD, goForward, globalOptions);
171+
const handleToggleReview = useCallback(() => {
172+
if (!currentTaskId) return;
173+
const mode = getReviewMode(currentTaskId);
174+
setReviewMode(currentTaskId, mode === "closed" ? "split" : "closed");
175+
}, [currentTaskId, getReviewMode, setReviewMode]);
176+
166177
useHotkeys(SHORTCUTS.TOGGLE_LEFT_SIDEBAR, toggleLeftSidebar, globalOptions);
167-
useHotkeys(SHORTCUTS.TOGGLE_RIGHT_SIDEBAR, toggleRightSidebar, globalOptions);
178+
useHotkeys(SHORTCUTS.TOGGLE_REVIEW_PANEL, handleToggleReview, globalOptions);
168179
useHotkeys(SHORTCUTS.SHORTCUTS_SHEET, onToggleShortcutsSheet, globalOptions);
169180
useHotkeys(SHORTCUTS.INBOX, navigateToInbox, globalOptions);
170181
useHotkeys(SHORTCUTS.PREV_TASK, handlePrevTask, globalOptions, [

apps/code/src/renderer/components/HeaderRow.tsx

Lines changed: 10 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1+
import { DiffStatsBadge } from "@features/code-review/components/DiffStatsBadge";
12
import { CloudGitInteractionHeader } from "@features/git-interaction/components/CloudGitInteractionHeader";
23
import { GitInteractionHeader } from "@features/git-interaction/components/GitInteractionHeader";
3-
import { RightSidebarTrigger } from "@features/right-sidebar/components/RightSidebarTrigger";
4-
import { useRightSidebarStore } from "@features/right-sidebar/stores/rightSidebarStore";
54
import { SidebarTrigger } from "@features/sidebar/components/SidebarTrigger";
65
import { useSidebarStore } from "@features/sidebar/stores/sidebarStore";
76
import { useWorkspace } from "@features/workspace/hooks/useWorkspace";
@@ -24,19 +23,9 @@ export function HeaderRow() {
2423
const isResizing = useSidebarStore((state) => state.isResizing);
2524
const setIsResizing = useSidebarStore((state) => state.setIsResizing);
2625

27-
const rightSidebarOpen = useRightSidebarStore((state) => state.open);
28-
const rightSidebarWidth = useRightSidebarStore((state) => state.width);
29-
const rightSidebarIsResizing = useRightSidebarStore(
30-
(state) => state.isResizing,
31-
);
32-
const setRightSidebarIsResizing = useRightSidebarStore(
33-
(state) => state.setIsResizing,
34-
);
35-
3626
const activeTaskId = view.type === "task-detail" ? view.data?.id : undefined;
3727
const activeWorkspace = useWorkspace(activeTaskId);
3828
const isCloudTask = activeWorkspace?.mode === "cloud";
39-
const showRightSidebarSection = view.type === "task-detail";
4029

4130
const handleLeftSidebarMouseDown = (e: React.MouseEvent) => {
4231
e.preventDefault();
@@ -45,13 +34,6 @@ export function HeaderRow() {
4534
document.body.style.userSelect = "none";
4635
};
4736

48-
const handleRightSidebarMouseDown = (e: React.MouseEvent) => {
49-
e.preventDefault();
50-
setRightSidebarIsResizing(true);
51-
document.body.style.cursor = "col-resize";
52-
document.body.style.userSelect = "none";
53-
};
54-
5537
return (
5638
<Flex
5739
align="center"
@@ -108,45 +90,24 @@ export function HeaderRow() {
10890
</Flex>
10991
)}
11092

111-
{showRightSidebarSection && view.type === "task-detail" && view.data && (
93+
{view.type === "task-detail" && view.data && (
11294
<Flex
11395
align="center"
114-
justify={rightSidebarOpen ? "between" : "end"}
115-
px="3"
96+
gap="3"
97+
pr="3"
11698
style={{
117-
width: rightSidebarOpen ? `${rightSidebarWidth}px` : undefined,
118-
minWidth: rightSidebarOpen ? `${COLLAPSED_WIDTH}px` : undefined,
11999
height: "100%",
120-
borderLeft: "1px solid var(--gray-6)",
121-
transition: rightSidebarIsResizing
122-
? "none"
123-
: "width 0.2s ease-in-out",
124-
position: "relative",
100+
flexShrink: 0,
125101
}}
126102
>
127-
<RightSidebarTrigger />
128-
{rightSidebarOpen &&
129-
(isCloudTask ? (
103+
<div className="no-drag">
104+
{isCloudTask ? (
130105
<CloudGitInteractionHeader taskId={view.data.id} />
131106
) : (
132107
<GitInteractionHeader taskId={view.data.id} />
133-
))}
134-
{rightSidebarOpen && (
135-
<Box
136-
onMouseDown={handleRightSidebarMouseDown}
137-
className="no-drag"
138-
style={{
139-
position: "absolute",
140-
left: 0,
141-
top: 0,
142-
bottom: 0,
143-
width: "4px",
144-
cursor: "col-resize",
145-
backgroundColor: "transparent",
146-
zIndex: 100,
147-
}}
148-
/>
149-
)}
108+
)}
109+
</div>
110+
<DiffStatsBadge task={view.data} />
150111
</Flex>
151112
)}
152113
</Flex>

apps/code/src/renderer/components/MainLayout.tsx

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { ArchivedTasksView } from "@features/archive/components/ArchivedTasksVie
77
import { CommandMenu } from "@features/command/components/CommandMenu";
88
import { CommandCenterView } from "@features/command-center/components/CommandCenterView";
99
import { InboxView } from "@features/inbox/components/InboxView";
10-
import { RightSidebar, RightSidebarContent } from "@features/right-sidebar";
1110
import { FolderSettingsView } from "@features/settings/components/FolderSettingsView";
1211
import { SettingsDialog } from "@features/settings/components/SettingsDialog";
1312
import { MainSidebar } from "@features/sidebar/components/MainSidebar";
@@ -82,12 +81,6 @@ export function MainLayout() {
8281

8382
{view.type === "skills" && <SkillsView />}
8483
</Box>
85-
86-
{view.type === "task-detail" && view.data && (
87-
<RightSidebar>
88-
<RightSidebarContent taskId={view.data.id} task={view.data} />
89-
</RightSidebar>
90-
)}
9184
</Flex>
9285

9386
<CommandMenu open={commandMenuOpen} onOpenChange={setCommandMenuOpen} />

apps/code/src/renderer/constants/keyboard-shortcuts.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export const SHORTCUTS = {
88
GO_BACK: "mod+[",
99
GO_FORWARD: "mod+]",
1010
TOGGLE_LEFT_SIDEBAR: "mod+b",
11-
TOGGLE_RIGHT_SIDEBAR: "mod+shift+b",
11+
TOGGLE_REVIEW_PANEL: "mod+shift+b",
1212
PREV_TASK: "mod+shift+[,ctrl+shift+tab",
1313
NEXT_TASK: "mod+shift+],ctrl+tab",
1414
CLOSE_TAB: "mod+w",
@@ -112,9 +112,9 @@ export const KEYBOARD_SHORTCUTS: KeyboardShortcut[] = [
112112
category: "navigation",
113113
},
114114
{
115-
id: "toggle-right-sidebar",
116-
keys: SHORTCUTS.TOGGLE_RIGHT_SIDEBAR,
117-
description: "Toggle right sidebar",
115+
id: "toggle-review-panel",
116+
keys: SHORTCUTS.TOGGLE_REVIEW_PANEL,
117+
description: "Toggle review panel",
118118
category: "navigation",
119119
},
120120
{

apps/code/src/renderer/features/code-review/components/CloudReviewPage.tsx

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { useCloudChangedFiles } from "@features/task-detail/hooks/useCloudChange
22
import type { FileDiffMetadata } from "@pierre/diffs";
33
import { processFile } from "@pierre/diffs";
44
import { Flex, Spinner, Text } from "@radix-ui/themes";
5+
import { useReviewNavigationStore } from "@renderer/features/code-review/stores/reviewNavigationStore";
56
import type { ChangedFile, Task } from "@shared/types";
67
import { useMemo } from "react";
78
import { useReviewComment } from "../hooks/useReviewComment";
@@ -15,13 +16,16 @@ import {
1516
} from "./ReviewShell";
1617

1718
interface CloudReviewPageProps {
18-
taskId: string;
1919
task: Task;
2020
}
2121

22-
export function CloudReviewPage({ taskId, task }: CloudReviewPageProps) {
22+
export function CloudReviewPage({ task }: CloudReviewPageProps) {
23+
const taskId = task.id;
24+
const isReviewOpen = useReviewNavigationStore(
25+
(s) => (s.reviewModes[taskId] ?? "closed") !== "closed",
26+
);
2327
const { effectiveBranch, prUrl, isRunActive, remoteFiles, isLoading } =
24-
useCloudChangedFiles(taskId, task);
28+
useCloudChangedFiles(taskId, task, isReviewOpen);
2529
const onComment = useReviewComment(taskId);
2630

2731
const allPaths = useMemo(() => remoteFiles.map((f) => f.path), [remoteFiles]);
@@ -64,6 +68,7 @@ export function CloudReviewPage({ taskId, task }: CloudReviewPageProps) {
6468
return (
6569
<ReviewShell
6670
taskId={taskId}
71+
task={task}
6772
fileCount={remoteFiles.length}
6873
linesAdded={linesAdded}
6974
linesRemoved={linesRemoved}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { Tooltip } from "@components/ui/Tooltip";
2+
import { useGitQueries } from "@features/git-interaction/hooks/useGitQueries";
3+
import { computeDiffStats } from "@features/git-interaction/utils/diffStats";
4+
import { useCwd } from "@features/sidebar/hooks/useCwd";
5+
import { useCloudChangedFiles } from "@features/task-detail/hooks/useCloudChangedFiles";
6+
import { useWorkspace } from "@features/workspace/hooks/useWorkspace";
7+
import { GitDiff } from "@phosphor-icons/react";
8+
import { Flex, Text } from "@radix-ui/themes";
9+
import {
10+
formatHotkey,
11+
SHORTCUTS,
12+
} from "@renderer/constants/keyboard-shortcuts";
13+
import { useReviewNavigationStore } from "@renderer/features/code-review/stores/reviewNavigationStore";
14+
import type { Task } from "@shared/types";
15+
import { useMemo } from "react";
16+
17+
interface DiffStatsBadgeProps {
18+
task: Task;
19+
}
20+
21+
function useChangedFileStats(task: Task) {
22+
const taskId = task.id;
23+
const workspace = useWorkspace(taskId);
24+
const isCloud =
25+
workspace?.mode === "cloud" || task.latest_run?.environment === "cloud";
26+
const repoPath = useCwd(taskId);
27+
28+
const { diffStats: localDiffStats } = useGitQueries(
29+
isCloud ? undefined : repoPath,
30+
);
31+
32+
const { changedFiles: cloudFiles } = useCloudChangedFiles(taskId, task);
33+
34+
return useMemo(() => {
35+
if (isCloud) {
36+
const stats = computeDiffStats(cloudFiles);
37+
return {
38+
filesChanged: stats.filesChanged,
39+
linesAdded: stats.linesAdded,
40+
linesRemoved: stats.linesRemoved,
41+
};
42+
}
43+
return {
44+
filesChanged: localDiffStats.filesChanged,
45+
linesAdded: localDiffStats.linesAdded,
46+
linesRemoved: localDiffStats.linesRemoved,
47+
};
48+
}, [isCloud, cloudFiles, localDiffStats]);
49+
}
50+
51+
export function DiffStatsBadge({ task }: DiffStatsBadgeProps) {
52+
const taskId = task.id;
53+
const { filesChanged, linesAdded, linesRemoved } = useChangedFileStats(task);
54+
const reviewMode = useReviewNavigationStore(
55+
(s) => s.reviewModes[taskId] ?? "closed",
56+
);
57+
const setReviewMode = useReviewNavigationStore((s) => s.setReviewMode);
58+
59+
const hasChanges = filesChanged > 0;
60+
61+
const isOpen = reviewMode !== "closed";
62+
63+
const handleClick = () => {
64+
setReviewMode(taskId, isOpen ? "closed" : "split");
65+
};
66+
67+
return (
68+
<Tooltip
69+
content={isOpen ? "Close review panel" : "Open review panel"}
70+
shortcut={formatHotkey(SHORTCUTS.TOGGLE_REVIEW_PANEL)}
71+
side="bottom"
72+
>
73+
<button
74+
type="button"
75+
onClick={handleClick}
76+
className={`no-drag inline-flex h-6 cursor-pointer items-center gap-1 rounded-[var(--radius-1)] border-none px-1.5 font-mono text-[11px] text-[var(--gray-11)] transition-colors duration-100 hover:bg-[var(--gray-a3)] ${isOpen ? "bg-[var(--gray-a3)]" : "bg-transparent"}`}
77+
>
78+
<GitDiff size={14} style={{ flexShrink: 0 }} />
79+
{hasChanges ? (
80+
<Flex align="center" gap="1">
81+
{linesAdded > 0 && (
82+
<Text style={{ color: "var(--green-9)", fontSize: "11px" }}>
83+
+{linesAdded}
84+
</Text>
85+
)}
86+
{linesRemoved > 0 && (
87+
<Text style={{ color: "var(--red-9)", fontSize: "11px" }}>
88+
-{linesRemoved}
89+
</Text>
90+
)}
91+
</Flex>
92+
) : (
93+
<Text style={{ color: "var(--gray-9)", fontSize: "11px" }}>0</Text>
94+
)}
95+
</button>
96+
</Tooltip>
97+
);
98+
}

apps/code/src/renderer/features/code-review/components/ReviewPage.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { makeFileKey } from "@features/git-interaction/utils/fileKey";
22
import { usePanelLayoutStore } from "@features/panels/store/panelLayoutStore";
3-
import { isTabActiveInTree } from "@features/panels/store/panelStoreHelpers";
43
import { useCwd } from "@features/sidebar/hooks/useCwd";
54
import type { parsePatchFiles } from "@pierre/diffs";
65
import { Flex, Text } from "@radix-ui/themes";
6+
import { useReviewNavigationStore } from "@renderer/features/code-review/stores/reviewNavigationStore";
77
import { useTRPC } from "@renderer/trpc/client";
8-
import type { ChangedFile } from "@shared/types";
8+
import type { ChangedFile, Task } from "@shared/types";
99
import { useQuery } from "@tanstack/react-query";
1010
import { useMemo } from "react";
1111
import { useReviewComment } from "../hooks/useReviewComment";
@@ -22,17 +22,16 @@ import {
2222
} from "./ReviewShell";
2323

2424
interface ReviewPageProps {
25-
taskId: string;
25+
task: Task;
2626
}
2727

28-
export function ReviewPage({ taskId }: ReviewPageProps) {
28+
export function ReviewPage({ task }: ReviewPageProps) {
29+
const taskId = task.id;
2930
const repoPath = useCwd(taskId);
3031
const openFile = usePanelLayoutStore((s) => s.openFile);
31-
const isReviewTabActive = usePanelLayoutStore((s) => {
32-
const layout = s.getLayout(taskId);
33-
if (!layout) return false;
34-
return isTabActiveInTree(layout.panelTree, "review");
35-
});
32+
const isReviewOpen = useReviewNavigationStore(
33+
(s) => (s.reviewModes[taskId] ?? "closed") !== "closed",
34+
);
3635
const onComment = useReviewComment(taskId);
3736

3837
const {
@@ -46,7 +45,7 @@ export function ReviewPage({ taskId }: ReviewPageProps) {
4645
allPaths,
4746
diffLoading,
4847
refetch,
49-
} = useReviewDiffs(repoPath, isReviewTabActive);
48+
} = useReviewDiffs(repoPath, isReviewOpen);
5049

5150
const {
5251
diffOptions,
@@ -86,6 +85,7 @@ export function ReviewPage({ taskId }: ReviewPageProps) {
8685
return (
8786
<ReviewShell
8887
taskId={taskId}
88+
task={task}
8989
fileCount={totalFileCount}
9090
linesAdded={linesAdded}
9191
linesRemoved={linesRemoved}

0 commit comments

Comments
 (0)