11import {
2- ArrowLeftIcon ,
3- ArrowUpDownIcon ,
4- CheckCircleIcon ,
5- ChevronRightIcon ,
6- CircleDotIcon ,
7- CloudUploadIcon ,
8- EyeIcon ,
9- EyeOffIcon ,
10- ExternalLinkIcon ,
11- FolderIcon ,
12- GitBranchIcon ,
13- GitMergeIcon ,
14- GitPullRequestIcon ,
15- LinkIcon ,
16- UserIcon ,
17- XCircleIcon ,
18- PanelLeftCloseIcon ,
19- PlusIcon ,
20- RocketIcon ,
21- SettingsIcon ,
22- TriangleAlertIcon ,
23- } from "lucide-react" ;
24- import { OkCodeMark } from "./OkCodeMark" ;
25- import { memo , useCallback , useEffect , useMemo , useRef , useState , type MouseEvent } from "react" ;
26- import {
2+ type CollisionDetection ,
3+ closestCorners ,
274 DndContext ,
285 type DragCancelEvent ,
29- type CollisionDetection ,
30- PointerSensor ,
6+ type DragEndEvent ,
317 type DragStartEvent ,
32- closestCorners ,
8+ PointerSensor ,
339 pointerWithin ,
3410 useSensor ,
3511 useSensors ,
36- type DragEndEvent ,
3712} from "@dnd-kit/core" ;
38- import { SortableContext , useSortable , verticalListSortingStrategy } from "@dnd-kit/sortable" ;
3913import { restrictToFirstScrollableAncestor , restrictToVerticalAxis } from "@dnd-kit/modifiers" ;
14+ import { SortableContext , useSortable , verticalListSortingStrategy } from "@dnd-kit/sortable" ;
4015import { CSS } from "@dnd-kit/utilities" ;
16+ import type { ThreadId as ThreadIdType } from "@okcode/contracts" ;
4117import {
4218 DEFAULT_MODEL_BY_PROVIDER ,
4319 type DesktopUpdateState ,
44- ProjectId ,
45- ThreadId ,
4620 type GitStatusResult ,
21+ type ProjectId ,
4722 type ResolvedKeybindingsConfig ,
23+ ThreadId ,
4824} from "@okcode/contracts" ;
4925import { useMutation , useQueries , useQuery , useQueryClient } from "@tanstack/react-query" ;
5026import { useLocation , useNavigate , useParams } from "@tanstack/react-router" ;
27+ import { isNonEmpty as isNonEmptyString } from "effect/String" ;
28+ import {
29+ ArrowLeftIcon ,
30+ ArrowUpDownIcon ,
31+ CheckCircleIcon ,
32+ CircleDotIcon ,
33+ CloudUploadIcon ,
34+ ExternalLinkIcon ,
35+ FolderIcon ,
36+ GitBranchIcon ,
37+ GitMergeIcon ,
38+ GitPullRequestIcon ,
39+ LinkIcon ,
40+ PanelLeftCloseIcon ,
41+ PlusIcon ,
42+ RocketIcon ,
43+ SettingsIcon ,
44+ TriangleAlertIcon ,
45+ UserIcon ,
46+ XCircleIcon ,
47+ } from "lucide-react" ;
48+ import { type MouseEvent , memo , useCallback , useEffect , useMemo , useRef , useState } from "react" ;
49+ import { CloneRepositoryDialog } from "~/components/CloneRepositoryDialog" ;
50+ import { EditableThreadTitle } from "~/components/EditableThreadTitle" ;
51+ import { useClientMode } from "~/hooks/useClientMode" ;
52+ import { useCopyToClipboard } from "~/hooks/useCopyToClipboard" ;
53+ import { useProjectTitleEditor } from "~/hooks/useProjectTitleEditor" ;
54+ import { useTheme } from "~/hooks/useTheme" ;
55+ import { useThreadTitleEditor } from "~/hooks/useThreadTitleEditor" ;
56+ import { resolveImportedProjectScripts } from "~/lib/projectImport" ;
57+ import { getProjectColor } from "~/projectColors" ;
58+ import { useRightPanelStore } from "~/rightPanelStore" ;
5159import {
5260 type SidebarProjectSortOrder ,
5361 type SidebarThreadSortOrder ,
5462 useAppSettings ,
5563} from "../appSettings" ;
56- import { isElectron } from "../env" ;
5764import { APP_BASE_NAME , APP_VERSION } from "../branding" ;
58- import { cn , isLinuxPlatform , isMacPlatform , newCommandId , newProjectId } from "../lib/utils" ;
59- import { useStore } from "../store" ;
65+ import { useComposerDraftStore } from "../composerDraftStore" ;
66+ import { isElectron } from "../env" ;
67+ import { useHandleNewThread } from "../hooks/useHandleNewThread" ;
6068import { shortcutLabelForCommand } from "../keybindings" ;
61- import { derivePendingApprovals , derivePendingUserInputs } from "../session-logic" ;
6269import { gitRemoveWorktreeMutationOptions , gitStatusQueryOptions } from "../lib/gitReactQuery" ;
70+ import { resolveServerHttpOrigin } from "../lib/runtimeBridge" ;
6371import { serverConfigQueryOptions , serverUpdateQueryOptions } from "../lib/serverReactQuery" ;
72+ import { cn , isLinuxPlatform , isMacPlatform , newCommandId , newProjectId } from "../lib/utils" ;
6473import { readNativeApi } from "../nativeApi" ;
65- import { resolveServerHttpOrigin } from "../lib/runtimeBridge" ;
66- import { useComposerDraftStore } from "../composerDraftStore" ;
67- import { useHandleNewThread } from "../hooks/useHandleNewThread" ;
74+ import { derivePendingApprovals , derivePendingUserInputs } from "../session-logic" ;
75+ import { useStore } from "../store" ;
6876import {
6977 selectThreadTerminalState ,
7078 type ThreadTerminalState ,
7179 useTerminalStateStore ,
7280} from "../terminalStateStore" ;
73- import { toastManager } from "./ui/toast" ;
81+ import { useThreadSelectionStore } from "../threadSelectionStore" ;
82+ import type { Thread } from "../types" ;
83+ import { formatWorktreePathForDisplay , getOrphanedWorktreePathForThread } from "../worktreeCleanup" ;
7484import {
7585 getArm64IntelBuildWarningDescription ,
7686 getDesktopUpdateActionError ,
7787 getDesktopUpdateButtonTooltip ,
7888 isDesktopUpdateButtonDisabled ,
7989 resolveDesktopUpdateButtonAction ,
80- shouldShowArm64IntelBuildWarning ,
8190 shouldHighlightDesktopUpdateError ,
91+ shouldShowArm64IntelBuildWarning ,
8292 shouldShowDesktopUpdateButton ,
8393 shouldToastDesktopUpdateActionResult ,
8494} from "./desktopUpdate.logic" ;
95+ import { OkCodeMark } from "./OkCodeMark" ;
96+ import {
97+ computeProjectDisambiguationPaths ,
98+ getVisibleThreadsForProject ,
99+ isActionableThreadStatus ,
100+ resolveProjectStatusIndicator ,
101+ resolveSidebarNewThreadEnvMode ,
102+ resolveThreadStatusPill ,
103+ shouldClearThreadSelectionOnMouseDown ,
104+ sortProjectsForSidebar ,
105+ sortThreadsForSidebar ,
106+ } from "./Sidebar.logic" ;
85107import { Alert , AlertAction , AlertDescription , AlertTitle } from "./ui/alert" ;
86108import { Button } from "./ui/button" ;
87109import { Collapsible , CollapsibleContent } from "./ui/collapsible" ;
88110import { Menu , MenuGroup , MenuPopup , MenuRadioGroup , MenuRadioItem , MenuTrigger } from "./ui/menu" ;
89- import { Tooltip , TooltipPopup , TooltipTrigger } from "./ui/tooltip" ;
90111import {
91112 SidebarContent ,
92113 SidebarFooter ,
@@ -102,32 +123,8 @@ import {
102123 SidebarTrigger ,
103124 useSidebar ,
104125} from "./ui/sidebar" ;
105- import { useThreadSelectionStore } from "../threadSelectionStore" ;
106- import { formatWorktreePathForDisplay , getOrphanedWorktreePathForThread } from "../worktreeCleanup" ;
107- import { isNonEmpty as isNonEmptyString } from "effect/String" ;
108- import { useTheme } from "~/hooks/useTheme" ;
109- import {
110- computeProjectDisambiguationPaths ,
111- getVisibleThreadsForProject ,
112- isActionableThreadStatus ,
113- resolveProjectStatusIndicator ,
114- resolveSidebarNewThreadEnvMode ,
115- resolveThreadStatusPill ,
116- shouldClearThreadSelectionOnMouseDown ,
117- sortProjectsForSidebar ,
118- sortThreadsForSidebar ,
119- } from "./Sidebar.logic" ;
120- import { useCopyToClipboard } from "~/hooks/useCopyToClipboard" ;
121- import { WorkspaceFileTree } from "~/components/WorkspaceFileTree" ;
122- import { EditableThreadTitle } from "~/components/EditableThreadTitle" ;
123- import { useProjectTitleEditor } from "~/hooks/useProjectTitleEditor" ;
124- import { useThreadTitleEditor } from "~/hooks/useThreadTitleEditor" ;
125- import { resolveImportedProjectScripts } from "~/lib/projectImport" ;
126- import { useClientMode } from "~/hooks/useClientMode" ;
127- import { CloneRepositoryDialog } from "~/components/CloneRepositoryDialog" ;
128- import { getProjectColor } from "~/projectColors" ;
129- import type { Thread } from "../types" ;
130- import type { ThreadId as ThreadIdType } from "@okcode/contracts" ;
126+ import { toastManager } from "./ui/toast" ;
127+ import { Tooltip , TooltipPopup , TooltipTrigger } from "./ui/tooltip" ;
131128
132129const EMPTY_KEYBINDINGS : ResolvedKeybindingsConfig = [ ] ;
133130const THREAD_PREVIEW_LIMIT = 10 ;
@@ -604,9 +601,6 @@ export default function Sidebar() {
604601 const [ expandedThreadListsByProject , setExpandedThreadListsByProject ] = useState <
605602 ReadonlySet < ProjectId >
606603 > ( ( ) => new Set ( ) ) ;
607- const [ filesCollapsedByProject , setFilesCollapsedByProject ] = useState < ReadonlySet < ProjectId > > (
608- ( ) => new Set ( ) ,
609- ) ;
610604 const dragInProgressRef = useRef ( false ) ;
611605 const suppressProjectClickAfterDragRef = useRef ( false ) ;
612606 const [ desktopUpdateState , setDesktopUpdateState ] = useState < DesktopUpdateState | null > ( null ) ;
@@ -986,7 +980,9 @@ export default function Sidebar() {
986980 ] ,
987981 ) ;
988982
989- const { copyToClipboard : copyThreadIdToClipboard } = useCopyToClipboard < { threadId : ThreadId } > ( {
983+ const { copyToClipboard : copyThreadIdToClipboard } = useCopyToClipboard < {
984+ threadId : ThreadId ;
985+ } > ( {
990986 onCopy : ( ctx ) => {
991987 toastManager . add ( {
992988 type : "success" ,
@@ -1002,7 +998,9 @@ export default function Sidebar() {
1002998 } ) ;
1003999 } ,
10041000 } ) ;
1005- const { copyToClipboard : copyPathToClipboard } = useCopyToClipboard < { path : string } > ( {
1001+ const { copyToClipboard : copyPathToClipboard } = useCopyToClipboard < {
1002+ path : string ;
1003+ } > ( {
10061004 onCopy : ( ) => {
10071005 toastManager . add ( {
10081006 type : "success" ,
@@ -1373,7 +1371,6 @@ export default function Sidebar() {
13731371 const activeProjectThread = activeThreadId
13741372 ? ( projectThreads . find ( ( thread ) => thread . id === activeThreadId ) ?? null )
13751373 : null ;
1376- const activeWorkspaceCwd = activeProjectThread ?. worktreePath ?? project . cwd ;
13771374 const isThreadListExpanded = expandedThreadListsByProject . has ( project . id ) ;
13781375 const pinnedCollapsedThread =
13791376 ! project . expanded && activeThreadId
@@ -1541,41 +1538,6 @@ export default function Sidebar() {
15411538 </ SidebarMenuSubItem >
15421539 ) }
15431540 </ SidebarMenuSub >
1544-
1545- { project . expanded && ! appSettings . sidebarHideFiles ? (
1546- < div className = "mx-1 mt-0.5 px-1" >
1547- < button
1548- type = "button"
1549- className = "mb-1 flex w-full items-center gap-1.5 px-2 text-[10px] uppercase tracking-[0.14em] text-muted-foreground/50 hover:text-muted-foreground/70"
1550- onClick = { ( ) =>
1551- setFilesCollapsedByProject ( ( current ) => {
1552- const next = new Set ( current ) ;
1553- if ( next . has ( project . id ) ) {
1554- next . delete ( project . id ) ;
1555- } else {
1556- next . add ( project . id ) ;
1557- }
1558- return next ;
1559- } )
1560- }
1561- >
1562- < ChevronRightIcon
1563- className = { cn (
1564- "size-3 shrink-0 transition-transform" ,
1565- ! filesCollapsedByProject . has ( project . id ) && "rotate-90" ,
1566- ) }
1567- />
1568- < FolderIcon className = "size-3 shrink-0" />
1569- < span > Files</ span >
1570- </ button >
1571- < WorkspaceFileTree
1572- key = { project . id }
1573- cwd = { activeWorkspaceCwd }
1574- resolvedTheme = { resolvedTheme }
1575- className = { cn ( filesCollapsedByProject . has ( project . id ) && "hidden" ) }
1576- />
1577- </ div >
1578- ) : null }
15791541 </ CollapsibleContent >
15801542 </ Collapsible >
15811543 ) ;
@@ -2004,29 +1966,17 @@ export default function Sidebar() {
20041966 render = {
20051967 < button
20061968 type = "button"
2007- aria-label = { appSettings . sidebarHideFiles ? "Show files" : "Hide files" }
2008- aria-pressed = { appSettings . sidebarHideFiles }
2009- className = { cn (
2010- "inline-flex size-5 cursor-pointer items-center justify-center rounded-md transition-colors hover:bg-accent hover:text-foreground" ,
2011- appSettings . sidebarHideFiles
2012- ? "text-muted-foreground/40"
2013- : "text-muted-foreground/60" ,
2014- ) }
2015- onClick = { ( ) =>
2016- updateSettings ( { sidebarHideFiles : ! appSettings . sidebarHideFiles } )
2017- }
1969+ aria-label = "Open file tree"
1970+ className = "inline-flex size-5 cursor-pointer items-center justify-center rounded-md text-muted-foreground/60 transition-colors hover:bg-accent hover:text-foreground"
1971+ onClick = { ( ) => {
1972+ useRightPanelStore . getState ( ) . open ( "files" ) ;
1973+ } }
20181974 />
20191975 }
20201976 >
2021- { appSettings . sidebarHideFiles ? (
2022- < EyeOffIcon className = "size-3.5" />
2023- ) : (
2024- < EyeIcon className = "size-3.5" />
2025- ) }
1977+ < FolderIcon className = "size-3.5" />
20261978 </ TooltipTrigger >
2027- < TooltipPopup side = "top" >
2028- { appSettings . sidebarHideFiles ? "Show files" : "Hide files" }
2029- </ TooltipPopup >
1979+ < TooltipPopup side = "top" > Open file tree</ TooltipPopup >
20301980 </ Tooltip >
20311981 < ProjectSortMenu
20321982 projectSortOrder = { appSettings . sidebarProjectSortOrder }
0 commit comments