@@ -135,19 +135,18 @@ import {
135135import {
136136 collapseSidebarProjectThreadList ,
137137 expandSidebarProjectThreadList ,
138- syncSidebarProjectMappings ,
138+ resetSidebarViewState ,
139139 useSidebarIsActiveThread ,
140140 useSidebarProjectActiveRouteThreadKey ,
141141 useSidebarProjectKeys ,
142- useSidebarProjectSnapshot ,
143142 useSidebarProjectThreadListExpanded ,
144143 useSidebarThreadJumpLabel ,
145- type SidebarProjectSnapshot ,
146144} from "./sidebar/sidebarViewStore" ;
147145import { SidebarUpdatePill } from "./sidebar/SidebarUpdatePill" ;
148146import {
149147 buildSidebarPhysicalToLogicalKeyMap ,
150148 buildSidebarProjectSnapshots ,
149+ type SidebarProjectSnapshot ,
151150} from "./sidebar/sidebarProjectSnapshots" ;
152151import { useCopyToClipboard } from "~/hooks/useCopyToClipboard" ;
153152import { readEnvironmentApi } from "../environmentApi" ;
@@ -504,13 +503,12 @@ const SidebarThreadTerminalStatusIndicator = memo(
504503
505504interface SidebarThreadRowProps {
506505 threadKey : string ;
507- projectKey : string ;
506+ project : SidebarProjectSnapshot ;
508507}
509508
510509const SidebarThreadRow = memo ( function SidebarThreadRow ( props : SidebarThreadRowProps ) {
511- const { threadKey, projectKey } = props ;
510+ const { threadKey, project } = props ;
512511 const threadRef = useMemo ( ( ) => parseScopedThreadKey ( threadKey ) , [ threadKey ] ) ;
513- const project = useSidebarProjectSnapshot ( projectKey ) ;
514512 const threadSortOrder = useSettings < SidebarThreadSortOrder > (
515513 ( settings ) => settings . sidebarThreadSortOrder ,
516514 ) ;
@@ -1092,7 +1090,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThreadRowP
10921090} ) ;
10931091
10941092interface SidebarProjectThreadListProps {
1095- projectKey : string ;
1093+ project : SidebarProjectSnapshot ;
10961094 projectExpanded : boolean ;
10971095 hasOverflowingThreads : boolean ;
10981096 hiddenThreadKeys : readonly string [ ] ;
@@ -1107,7 +1105,7 @@ const SidebarProjectThreadList = memo(function SidebarProjectThreadList(
11071105 props : SidebarProjectThreadListProps ,
11081106) {
11091107 const {
1110- projectKey ,
1108+ project ,
11111109 projectExpanded,
11121110 hasOverflowingThreads,
11131111 hiddenThreadKeys,
@@ -1137,7 +1135,7 @@ const SidebarProjectThreadList = memo(function SidebarProjectThreadList(
11371135 ) : null }
11381136 { shouldShowThreadPanel &&
11391137 renderedThreadKeys . map ( ( threadKey ) => {
1140- return < SidebarThreadRow key = { threadKey } threadKey = { threadKey } projectKey = { projectKey } /> ;
1138+ return < SidebarThreadRow key = { threadKey } threadKey = { threadKey } project = { project } /> ;
11411139 } ) }
11421140
11431141 { projectExpanded && hasOverflowingThreads && ! isThreadListExpanded && (
@@ -1148,12 +1146,12 @@ const SidebarProjectThreadList = memo(function SidebarProjectThreadList(
11481146 size = "sm"
11491147 className = "h-6 w-full translate-x-0 justify-start px-2 text-left text-[10px] text-muted-foreground/60 hover:bg-accent hover:text-muted-foreground/80"
11501148 onClick = { ( ) => {
1151- expandSidebarProjectThreadList ( projectKey ) ;
1149+ expandSidebarProjectThreadList ( project . projectKey ) ;
11521150 } }
11531151 >
11541152 < span className = "flex min-w-0 flex-1 items-center gap-2" >
11551153 < SidebarProjectOverflowStatusLabel
1156- projectKey = { projectKey }
1154+ project = { project }
11571155 hiddenThreadKeys = { hiddenThreadKeys }
11581156 />
11591157 < span > Show more</ span >
@@ -1169,7 +1167,7 @@ const SidebarProjectThreadList = memo(function SidebarProjectThreadList(
11691167 size = "sm"
11701168 className = "h-6 w-full translate-x-0 justify-start px-2 text-left text-[10px] text-muted-foreground/60 hover:bg-accent hover:text-muted-foreground/80"
11711169 onClick = { ( ) => {
1172- collapseSidebarProjectThreadList ( projectKey ) ;
1170+ collapseSidebarProjectThreadList ( project . projectKey ) ;
11731171 } }
11741172 >
11751173 < span > Show less</ span >
@@ -1322,11 +1320,10 @@ const SidebarProjectHeaderStatusIndicator = memo(
13221320
13231321const SidebarProjectOverflowStatusLabel = memo ( function SidebarProjectOverflowStatusLabel ( props : {
13241322 hiddenThreadKeys : readonly string [ ] ;
1325- projectKey : string ;
1323+ project : SidebarProjectSnapshot ;
13261324} ) {
1327- const { hiddenThreadKeys, projectKey } = props ;
1328- const project = useSidebarProjectSnapshot ( projectKey ) ;
1329- if ( ! project || hiddenThreadKeys . length === 0 ) {
1325+ const { hiddenThreadKeys, project } = props ;
1326+ if ( hiddenThreadKeys . length === 0 ) {
13301327 return null ;
13311328 }
13321329 const statusInputs = useSidebarProjectStatusInputs ( project ) ;
@@ -1345,23 +1342,19 @@ const SidebarProjectOverflowStatusLabel = memo(function SidebarProjectOverflowSt
13451342} ) ;
13461343
13471344interface SidebarProjectThreadSectionProps {
1348- projectKey : string ;
1345+ project : SidebarProjectSnapshot ;
13491346 attachThreadListAutoAnimateRef : ( node : HTMLElement | null ) => void ;
13501347}
13511348
13521349const SidebarProjectThreadSection = memo ( function SidebarProjectThreadSection (
13531350 props : SidebarProjectThreadSectionProps ,
13541351) {
1355- const { projectKey, attachThreadListAutoAnimateRef } = props ;
1356- const project = useSidebarProjectSnapshot ( projectKey ) ;
1357- const isThreadListExpanded = useSidebarProjectThreadListExpanded ( projectKey ) ;
1352+ const { project, attachThreadListAutoAnimateRef } = props ;
1353+ const isThreadListExpanded = useSidebarProjectThreadListExpanded ( project . projectKey ) ;
13581354 const threadSortOrder = useSettings < SidebarThreadSortOrder > (
13591355 ( settings ) => settings . sidebarThreadSortOrder ,
13601356 ) ;
1361- if ( ! project ) {
1362- return null ;
1363- }
1364- const activeRouteThreadKey = useSidebarProjectActiveRouteThreadKey ( projectKey ) ;
1357+ const activeRouteThreadKey = useSidebarProjectActiveRouteThreadKey ( project . projectKey ) ;
13651358 const projectExpanded = useUiStateStore (
13661359 ( state ) => state . projectExpandedById [ project . projectKey ] ?? true ,
13671360 ) ;
@@ -1381,7 +1374,7 @@ const SidebarProjectThreadSection = memo(function SidebarProjectThreadSection(
13811374
13821375 return (
13831376 < SidebarProjectThreadList
1384- projectKey = { project . projectKey }
1377+ project = { project }
13851378 projectExpanded = { projectExpanded }
13861379 hasOverflowingThreads = { hasOverflowingThreads }
13871380 hiddenThreadKeys = { hiddenThreadKeys }
@@ -1395,7 +1388,7 @@ const SidebarProjectThreadSection = memo(function SidebarProjectThreadSection(
13951388} ) ;
13961389
13971390interface SidebarProjectHeaderProps {
1398- projectKey : string ;
1391+ project : SidebarProjectSnapshot ;
13991392 dragInProgressRef : React . RefObject < boolean > ;
14001393 suppressProjectClickAfterDragRef : React . RefObject < boolean > ;
14011394 suppressProjectClickForContextMenuRef : React . RefObject < boolean > ;
@@ -1405,14 +1398,13 @@ interface SidebarProjectHeaderProps {
14051398
14061399const SidebarProjectHeader = memo ( function SidebarProjectHeader ( props : SidebarProjectHeaderProps ) {
14071400 const {
1408- projectKey ,
1401+ project ,
14091402 dragInProgressRef,
14101403 suppressProjectClickAfterDragRef,
14111404 suppressProjectClickForContextMenuRef,
14121405 isManualProjectSorting,
14131406 dragHandleProps,
14141407 } = props ;
1415- const project = useSidebarProjectSnapshot ( projectKey ) ;
14161408 const defaultThreadEnvMode = useSettings < ThreadEnvMode > (
14171409 ( settings ) => settings . defaultThreadEnvMode ,
14181410 ) ;
@@ -1448,7 +1440,9 @@ const SidebarProjectHeader = memo(function SidebarProjectHeader(props: SidebarPr
14481440 } ) ;
14491441 } ,
14501442 } ) ;
1451- const projectExpanded = useUiStateStore ( ( state ) => state . projectExpandedById [ projectKey ] ?? true ) ;
1443+ const projectExpanded = useUiStateStore (
1444+ ( state ) => state . projectExpandedById [ project . projectKey ] ?? true ,
1445+ ) ;
14521446 const projectThreadCount = useSidebarProjectThreadCount ( project ) ;
14531447 const newThreadShortcutLabelOptions = useMemo (
14541448 ( ) => ( {
@@ -1463,10 +1457,6 @@ const SidebarProjectHeader = memo(function SidebarProjectHeader(props: SidebarPr
14631457 const newThreadShortcutLabel =
14641458 shortcutLabelForCommand ( keybindings , "chat.newLocal" , newThreadShortcutLabelOptions ) ??
14651459 shortcutLabelForCommand ( keybindings , "chat.new" , newThreadShortcutLabelOptions ) ;
1466- if ( ! project ) {
1467- return null ;
1468- }
1469-
14701460 const handleProjectButtonClick = useCallback (
14711461 ( event : React . MouseEvent < HTMLButtonElement > ) => {
14721462 if ( suppressProjectClickForContextMenuRef . current ) {
@@ -1489,12 +1479,12 @@ const SidebarProjectHeader = memo(function SidebarProjectHeader(props: SidebarPr
14891479 if ( selectedThreadCount > 0 ) {
14901480 clearSelection ( ) ;
14911481 }
1492- toggleProject ( projectKey ) ;
1482+ toggleProject ( project . projectKey ) ;
14931483 } ,
14941484 [
14951485 clearSelection ,
14961486 dragInProgressRef ,
1497- projectKey ,
1487+ project . projectKey ,
14981488 selectedThreadCount ,
14991489 suppressProjectClickAfterDragRef ,
15001490 suppressProjectClickForContextMenuRef ,
@@ -1509,9 +1499,9 @@ const SidebarProjectHeader = memo(function SidebarProjectHeader(props: SidebarPr
15091499 if ( dragInProgressRef . current ) {
15101500 return ;
15111501 }
1512- toggleProject ( projectKey ) ;
1502+ toggleProject ( project . projectKey ) ;
15131503 } ,
1514- [ dragInProgressRef , projectKey , toggleProject ] ,
1504+ [ dragInProgressRef , project . projectKey , toggleProject ] ,
15151505 ) ;
15161506
15171507 const handleProjectButtonPointerDownCapture = useCallback (
@@ -1733,7 +1723,7 @@ const SidebarProjectHeader = memo(function SidebarProjectHeader(props: SidebarPr
17331723} ) ;
17341724
17351725interface SidebarProjectItemProps {
1736- projectKey : string ;
1726+ project : SidebarProjectSnapshot ;
17371727 attachThreadListAutoAnimateRef : ( node : HTMLElement | null ) => void ;
17381728 dragInProgressRef : React . RefObject < boolean > ;
17391729 suppressProjectClickAfterDragRef : React . RefObject < boolean > ;
@@ -1744,7 +1734,7 @@ interface SidebarProjectItemProps {
17441734
17451735const SidebarProjectItem = memo ( function SidebarProjectItem ( props : SidebarProjectItemProps ) {
17461736 const {
1747- projectKey ,
1737+ project ,
17481738 attachThreadListAutoAnimateRef,
17491739 dragInProgressRef,
17501740 suppressProjectClickAfterDragRef,
@@ -1756,7 +1746,7 @@ const SidebarProjectItem = memo(function SidebarProjectItem(props: SidebarProjec
17561746 return (
17571747 < >
17581748 < SidebarProjectHeader
1759- projectKey = { projectKey }
1749+ project = { project }
17601750 dragInProgressRef = { dragInProgressRef }
17611751 suppressProjectClickAfterDragRef = { suppressProjectClickAfterDragRef }
17621752 suppressProjectClickForContextMenuRef = { suppressProjectClickForContextMenuRef }
@@ -1765,7 +1755,7 @@ const SidebarProjectItem = memo(function SidebarProjectItem(props: SidebarProjec
17651755 />
17661756
17671757 < SidebarProjectThreadSection
1768- projectKey = { projectKey }
1758+ project = { project }
17691759 attachThreadListAutoAnimateRef = { attachThreadListAutoAnimateRef }
17701760 />
17711761 </ >
@@ -1973,6 +1963,7 @@ const SidebarChromeFooter = memo(function SidebarChromeFooter() {
19731963} ) ;
19741964
19751965interface SidebarProjectsContentProps {
1966+ sidebarProjectByKey : ReadonlyMap < string , SidebarProjectSnapshot > ;
19761967 showArm64IntelBuildWarning : boolean ;
19771968 arm64IntelBuildWarningDescription : string | null ;
19781969 desktopUpdateButtonAction : "download" | "install" | "none" ;
@@ -2013,6 +2004,7 @@ const SidebarProjectsContent = memo(function SidebarProjectsContent(
20132004 props : SidebarProjectsContentProps ,
20142005) {
20152006 const {
2007+ sidebarProjectByKey,
20162008 showArm64IntelBuildWarning,
20172009 arm64IntelBuildWarningDescription,
20182010 desktopUpdateButtonAction,
@@ -2202,40 +2194,56 @@ const SidebarProjectsContent = memo(function SidebarProjectsContent(
22022194 items = { [ ...sortedProjectKeys ] }
22032195 strategy = { verticalListSortingStrategy }
22042196 >
2205- { sortedProjectKeys . map ( ( projectKey ) => (
2206- < SortableProjectItem key = { projectKey } projectId = { projectKey } >
2207- { ( dragHandleProps ) => (
2208- < SidebarProjectItem
2209- projectKey = { projectKey }
2210- attachThreadListAutoAnimateRef = { attachThreadListAutoAnimateRef }
2211- dragInProgressRef = { dragInProgressRef }
2212- suppressProjectClickAfterDragRef = { suppressProjectClickAfterDragRef }
2213- suppressProjectClickForContextMenuRef = {
2214- suppressProjectClickForContextMenuRef
2215- }
2216- isManualProjectSorting = { isManualProjectSorting }
2217- dragHandleProps = { dragHandleProps }
2218- />
2219- ) }
2220- </ SortableProjectItem >
2221- ) ) }
2197+ { sortedProjectKeys . map ( ( projectKey ) =>
2198+ ( ( ) => {
2199+ const project = sidebarProjectByKey . get ( projectKey ) ;
2200+ if ( ! project ) {
2201+ return null ;
2202+ }
2203+ return (
2204+ < SortableProjectItem key = { projectKey } projectId = { projectKey } >
2205+ { ( dragHandleProps ) => (
2206+ < SidebarProjectItem
2207+ project = { project }
2208+ attachThreadListAutoAnimateRef = { attachThreadListAutoAnimateRef }
2209+ dragInProgressRef = { dragInProgressRef }
2210+ suppressProjectClickAfterDragRef = { suppressProjectClickAfterDragRef }
2211+ suppressProjectClickForContextMenuRef = {
2212+ suppressProjectClickForContextMenuRef
2213+ }
2214+ isManualProjectSorting = { isManualProjectSorting }
2215+ dragHandleProps = { dragHandleProps }
2216+ />
2217+ ) }
2218+ </ SortableProjectItem >
2219+ ) ;
2220+ } ) ( ) ,
2221+ ) }
22222222 </ SortableContext >
22232223 </ SidebarMenu >
22242224 </ DndContext >
22252225 ) : (
22262226 < SidebarMenu ref = { attachProjectListAutoAnimateRef } >
2227- { sortedProjectKeys . map ( ( projectKey ) => (
2228- < SidebarProjectListRow
2229- key = { projectKey }
2230- projectKey = { projectKey }
2231- attachThreadListAutoAnimateRef = { attachThreadListAutoAnimateRef }
2232- dragInProgressRef = { dragInProgressRef }
2233- suppressProjectClickAfterDragRef = { suppressProjectClickAfterDragRef }
2234- suppressProjectClickForContextMenuRef = { suppressProjectClickForContextMenuRef }
2235- isManualProjectSorting = { isManualProjectSorting }
2236- dragHandleProps = { null }
2237- />
2238- ) ) }
2227+ { sortedProjectKeys . map ( ( projectKey ) =>
2228+ ( ( ) => {
2229+ const project = sidebarProjectByKey . get ( projectKey ) ;
2230+ if ( ! project ) {
2231+ return null ;
2232+ }
2233+ return (
2234+ < SidebarProjectListRow
2235+ key = { projectKey }
2236+ project = { project }
2237+ attachThreadListAutoAnimateRef = { attachThreadListAutoAnimateRef }
2238+ dragInProgressRef = { dragInProgressRef }
2239+ suppressProjectClickAfterDragRef = { suppressProjectClickAfterDragRef }
2240+ suppressProjectClickForContextMenuRef = { suppressProjectClickForContextMenuRef }
2241+ isManualProjectSorting = { isManualProjectSorting }
2242+ dragHandleProps = { null }
2243+ />
2244+ ) ;
2245+ } ) ( ) ,
2246+ ) }
22392247 </ SidebarMenu >
22402248 ) }
22412249
@@ -2534,11 +2542,10 @@ export default function Sidebar() {
25342542 const isManualProjectSorting = sidebarProjectSortOrder === "manual" ;
25352543
25362544 useEffect ( ( ) => {
2537- syncSidebarProjectMappings ( {
2538- projectSnapshotByKey : sidebarProjectByKey ,
2539- physicalToLogicalKey,
2540- } ) ;
2541- } , [ physicalToLogicalKey , sidebarProjectByKey ] ) ;
2545+ return ( ) => {
2546+ resetSidebarViewState ( ) ;
2547+ } ;
2548+ } , [ ] ) ;
25422549
25432550 useEffect ( ( ) => {
25442551 const onMouseDown = ( event : globalThis . MouseEvent ) => {
@@ -2669,6 +2676,7 @@ export default function Sidebar() {
26692676 />
26702677 < SidebarKeyboardController
26712678 navigateToThread = { navigateToThread }
2679+ physicalToLogicalKey = { physicalToLogicalKey }
26722680 sidebarThreadSortOrder = { sidebarThreadSortOrder }
26732681 />
26742682
@@ -2677,6 +2685,7 @@ export default function Sidebar() {
26772685 ) : (
26782686 < >
26792687 < SidebarProjectsContent
2688+ sidebarProjectByKey = { sidebarProjectByKey }
26802689 showArm64IntelBuildWarning = { showArm64IntelBuildWarning }
26812690 arm64IntelBuildWarningDescription = { arm64IntelBuildWarningDescription }
26822691 desktopUpdateButtonAction = { desktopUpdateButtonAction }
0 commit comments