@@ -245,8 +245,31 @@ const ProjectNavigationSidebarInner = (
245245 const nonKonnectProjects = projects . filter ( p => ! p . konnectControlPlaneId ) ;
246246 const konnectProjects = projects . filter ( p => p . konnectControlPlaneId != null ) ;
247247 const [ filterInputValue , setFilterInputValue ] = useState ( projectNavigationSidebarFilter || '' ) ;
248+ const [ konnectFilterInputValue , setKonnectFilterInputValue ] = useState ( konnectFilter || '' ) ;
249+
250+ useEffect ( ( ) => {
251+ // Keep input state aligned with storage only when organization context switches.
252+ // Read directly from localStorage to bypass react-use's stale state on key change.
253+ const readLocalStorageString = ( key : string ) : string => {
254+ try {
255+ const raw = localStorage . getItem ( key ) ;
256+ if ( raw == null ) {
257+ return '' ;
258+ }
259+ const parsed : unknown = JSON . parse ( raw ) ;
260+ return typeof parsed === 'string' ? parsed : '' ;
261+ } catch {
262+ return '' ;
263+ }
264+ } ;
265+ setFilterInputValue ( readLocalStorageString ( `${ organizationId } :project-navigation-sidebar-filter` ) ) ;
266+ setKonnectFilterInputValue ( readLocalStorageString ( `${ organizationId } :project-navigation-konnect-filter` ) ) ;
267+ } , [ organizationId ] ) ;
268+
248269 // Debounce update filter
249270 reactUse . useDebounce ( ( ) => setProjectNavigationSidebarFilter ( filterInputValue ) , 300 , [ filterInputValue ] ) ;
271+ reactUse . useDebounce ( ( ) => setKonnectFilter ( konnectFilterInputValue ) , 300 , [ konnectFilterInputValue ] ) ;
272+ const activeFilter = ( ( isProjectTabActive ? projectNavigationSidebarFilter : konnectFilter ) || '' ) . trim ( ) ;
250273 // ref to cache queried workspaces by project id
251274 const cachedWorkspacesRef = useRef < Map < string , Workspace [ ] > > ( new Map ( ) ) ;
252275 // ref to cache queried collection children (request & requestGroups) data and meta by workspace id
@@ -444,12 +467,12 @@ const ProjectNavigationSidebarInner = (
444467 } ;
445468
446469 useEffect ( ( ) => {
447- if ( projectNavigationSidebarFilter ) {
470+ if ( projectNavigationSidebarFilter || konnectFilter ) {
448471 window . main . trackAnalyticsEvent ( {
449472 event : AnalyticsEvent . projectListFiltered ,
450473 } ) ;
451474 }
452- } , [ projectNavigationSidebarFilter ] ) ;
475+ } , [ projectNavigationSidebarFilter , konnectFilter ] ) ;
453476
454477 useEffect ( ( ) => {
455478 getAllRemoteFilesByProjectId ( ) ;
@@ -492,6 +515,7 @@ const ProjectNavigationSidebarInner = (
492515 const buildWorkspaceAndCollectionData = async ( ) => {
493516 const items : FlatItem [ ] = [ ] ;
494517 // Array of project and collection workspace ids that should get data from db
518+ const activeFilterLower = activeFilter . toLowerCase ( ) ;
495519
496520 const projectIds = projectsWithPresence . map ( p => p . _id ) ;
497521 const collectionWorkspaceIds : string [ ] = [ ] ;
@@ -502,7 +526,7 @@ const ProjectNavigationSidebarInner = (
502526 if (
503527 wk . scope === 'collection' &&
504528 // Fetch collection children and meta if 1) the workspace is expanded or 2) there is an active filter
505- ( ! ! projectNavigationSidebarFilter || ( expandedProjectAndWorkspaceIds || [ ] ) . includes ( wk . _id ) )
529+ ( ! ! activeFilter || ( expandedProjectAndWorkspaceIds || [ ] ) . includes ( wk . _id ) )
506530 ) {
507531 collectionWorkspaceIds . push ( wk . _id ) ;
508532 }
@@ -544,7 +568,7 @@ const ProjectNavigationSidebarInner = (
544568 : [ ] ;
545569 const allWorkspaces = [ ...sortedWorkspaces , ...unsyncedWorkspaces ] ;
546570 // If there is no workspace under the project, show an empty workspace if no active filter
547- if ( allWorkspaces . length === 0 && ! projectNavigationSidebarFilter ) {
571+ if ( allWorkspaces . length === 0 && ! activeFilter ) {
548572 items . push ( {
549573 kind : 'emptyProject' ,
550574 organizationId,
@@ -556,6 +580,15 @@ const ProjectNavigationSidebarInner = (
556580
557581 for ( const workspace of allWorkspaces ) {
558582 if ( workspace . scope === 'unsynced' ) {
583+ // When a filter is active, show the unsynced workspace only if its name matches the filter.
584+ const unsyncedWorkspaceMatchesFilter =
585+ ! activeFilter ||
586+ Boolean (
587+ fuzzyMatchAll ( activeFilterLower , [ workspace . name ?. toLowerCase ( ) || '' ] , {
588+ splitSpace : true ,
589+ loose : true ,
590+ } ) ?. indexes ,
591+ ) ;
559592 items . push ( {
560593 kind : 'unsyncedWorkspace' ,
561594 organizationId,
@@ -566,7 +599,7 @@ const ProjectNavigationSidebarInner = (
566599 ...workspace ,
567600 } ,
568601 collapsed : false ,
569- hidden : isProjectCollapsed ,
602+ hidden : activeFilter ? ! unsyncedWorkspaceMatchesFilter : isProjectCollapsed ,
570603 } ) ;
571604 } else {
572605 const { scope, _id : workspaceId } = workspace as Workspace ;
@@ -589,7 +622,7 @@ const ProjectNavigationSidebarInner = (
589622 // build collection children if it's a collection workspace and parent workspace and project are not collapsed or there is an active filter
590623 const shouldHideCollectionChildren = isWorkspaceCollapsed || isProjectCollapsed ;
591624 let collectionChildren =
592- ( ! shouldHideCollectionChildren || ! ! projectNavigationSidebarFilter ) && allRequestsAndMetaInWorkspace
625+ ( ! shouldHideCollectionChildren || ! ! activeFilter ) && allRequestsAndMetaInWorkspace
593626 ? flattenCollectionChildren (
594627 workspaceId ,
595628 shouldHideCollectionChildren ,
@@ -598,13 +631,13 @@ const ProjectNavigationSidebarInner = (
598631 )
599632 : [ ] ;
600633
601- if ( projectNavigationSidebarFilter ) {
634+ if ( activeFilter ) {
602635 // apply filter to collection children first
603- collectionChildren = filterCollection ( collectionChildren , projectNavigationSidebarFilter ) ;
636+ collectionChildren = filterCollection ( collectionChildren , activeFilter ) ;
604637 const collectionChildMatchesFilter = collectionChildren . some ( child => ! child . hidden ) ;
605638 const workspaceMatchesFilter = Boolean (
606639 fuzzyMatchAll (
607- projectNavigationSidebarFilter . toLowerCase ( ) ,
640+ activeFilterLower ,
608641 // Todo: support remote files (cloud sync) in filter
609642 [ workspace . name ?. toLowerCase ( ) || '' ] ,
610643 { splitSpace : true , loose : true } ,
@@ -618,9 +651,7 @@ const ProjectNavigationSidebarInner = (
618651 const pinnedCollectionChildren = shouldHideCollectionChildren
619652 ? [ ]
620653 : // Filter out pinned requests by pinned attribute. Besides, when there is an active filter, also filter out un-matched requests.
621- collectionChildren . filter (
622- child => child . pinned && ! ( projectNavigationSidebarFilter ? child . hidden : false ) ,
623- ) ;
654+ collectionChildren . filter ( child => child . pinned && ! ( activeFilter ? child . hidden : false ) ) ;
624655
625656 if ( pinnedCollectionChildren . length > 0 ) {
626657 items . push ( {
@@ -665,7 +696,7 @@ const ProjectNavigationSidebarInner = (
665696 if (
666697 models . requestGroup . isRequestGroupId ( child . doc . _id ) &&
667698 child . children ?. length === 0 &&
668- ! projectNavigationSidebarFilter
699+ ! activeFilter
669700 ) {
670701 // If there is a request group with no children, add an empty folder node
671702 items . push ( {
@@ -681,7 +712,7 @@ const ProjectNavigationSidebarInner = (
681712 }
682713 } ) ;
683714
684- if ( collectionChildren . length === 0 && ! shouldHideCollectionChildren && ! projectNavigationSidebarFilter ) {
715+ if ( collectionChildren . length === 0 && ! shouldHideCollectionChildren && ! activeFilter ) {
685716 items . push ( {
686717 kind : 'emptyCollection' ,
687718 organizationId,
@@ -695,20 +726,18 @@ const ProjectNavigationSidebarInner = (
695726 }
696727
697728 // If project or any of its descendant workspace/collection child matches the filter, show the project; otherwise hide
698- if ( projectNavigationSidebarFilter ) {
699- const projectMatchesFilter = project . name
700- ?. toLowerCase ( )
701- . includes ( projectNavigationSidebarFilter . toLowerCase ( ) ) ;
729+ if ( activeFilter ) {
730+ const projectMatchesFilter = project . name ?. toLowerCase ( ) . includes ( activeFilterLower ) ;
702731 const hasVisibleWorkspace = items . some (
703- i => i . kind === 'workspace' && i . project . _id === projectId && ! i . hidden ,
732+ i => ( i . kind === 'workspace' || i . kind === 'unsyncedWorkspace' ) && i . project . _id === projectId && ! i . hidden ,
704733 ) ;
705734 const shouldHideProject = ! projectMatchesFilter && ! hasVisibleWorkspace ;
706735 items . find ( i => i . kind === 'project' && i . doc . _id === projectId ) ! . hidden = shouldHideProject ;
707736 }
708737 }
709738
710739 // If there is an active filter, expand all items to show matched results and their ancestors
711- if ( projectNavigationSidebarFilter ) {
740+ if ( activeFilter ) {
712741 items . forEach ( item => {
713742 if ( 'collapsed' in item ) {
714743 item . collapsed = false ;
@@ -720,13 +749,13 @@ const ProjectNavigationSidebarInner = (
720749 } ;
721750 buildWorkspaceAndCollectionData ( ) ;
722751 } , [
752+ activeFilter ,
723753 collectionSortOrders ,
724754 projectWorkspaceSortOrder ,
725755 expandedProjectAndWorkspaceIds ,
726756 isProjectTabActive ,
727757 localWorkspaceOrders ,
728758 organizationId ,
729- projectNavigationSidebarFilter ,
730759 projectsWithPresence ,
731760 unsyncedFilesByProjectId ,
732761 ] ) ;
@@ -776,21 +805,21 @@ const ProjectNavigationSidebarInner = (
776805 const toggleProjectOrWorkspace = useCallback (
777806 ( projectOrWorkspaceId : string ) => {
778807 // Do not update toggle state if there is an active filter
779- if ( ! projectNavigationSidebarFilter ) {
808+ if ( ! activeFilter ) {
780809 const expandedIds = expandedProjectAndWorkspaceIds || [ ] ;
781810 const isExpanded = expandedIds . includes ( projectOrWorkspaceId ) ;
782811 setExpandedProjectAndWorkspaceIds (
783812 isExpanded ? expandedIds . filter ( id => id !== projectOrWorkspaceId ) : [ ...expandedIds , projectOrWorkspaceId ] ,
784813 ) ;
785814 }
786815 } ,
787- [ expandedProjectAndWorkspaceIds , projectNavigationSidebarFilter , setExpandedProjectAndWorkspaceIds ] ,
816+ [ expandedProjectAndWorkspaceIds , activeFilter , setExpandedProjectAndWorkspaceIds ] ,
788817 ) ;
789818
790819 const expandProjectOrWorkspaces = useCallback (
791820 ( projectOrWorkspaceIds : string [ ] ) => {
792821 // Do not update toggle state if there is an active filter
793- if ( ! projectNavigationSidebarFilter ) {
822+ if ( ! activeFilter ) {
794823 const expandedIds = expandedProjectAndWorkspaceIds || [ ] ;
795824 const newExpandedIds = Array . from ( new Set ( [ ...expandedIds , ...projectOrWorkspaceIds ] ) ) ;
796825 // Avoid updating state if there is no change in expanded ids to prevent unnecessary re-render
@@ -800,7 +829,7 @@ const ProjectNavigationSidebarInner = (
800829 }
801830 }
802831 } ,
803- [ expandedProjectAndWorkspaceIds , projectNavigationSidebarFilter , setExpandedProjectAndWorkspaceIds ] ,
832+ [ expandedProjectAndWorkspaceIds , activeFilter , setExpandedProjectAndWorkspaceIds ] ,
804833 ) ;
805834
806835 useImperativeHandle (
@@ -819,7 +848,7 @@ const ProjectNavigationSidebarInner = (
819848 return ;
820849 }
821850
822- if ( projectNavigationSidebarFilter ) {
851+ if ( activeFilter ) {
823852 return ;
824853 }
825854
@@ -926,7 +955,7 @@ const ProjectNavigationSidebarInner = (
926955 } , previousFlatItems ) ,
927956 ) ;
928957 } ,
929- [ projectNavigationSidebarFilter ] ,
958+ [ activeFilter ] ,
930959 ) ;
931960
932961 const parentRef = useRef < HTMLDivElement > ( null ) ;
@@ -996,9 +1025,9 @@ const ProjectNavigationSidebarInner = (
9961025 < >
9971026 < div className = "flex justify-between gap-1 p-(--padding-sm)" >
9981027 < SidebarSearchField
999- value = { isProjectTabActive ? filterInputValue : ( konnectFilter ?? '' ) }
1028+ value = { isProjectTabActive ? filterInputValue : konnectFilterInputValue }
10001029 isDisabled = { projects . length === 0 }
1001- onChange = { isProjectTabActive ? setFilterInputValue : setKonnectFilter }
1030+ onChange = { isProjectTabActive ? setFilterInputValue : setKonnectFilterInputValue }
10021031 />
10031032 { isProjectTabActive ? (
10041033 ! isScratchPad && < NewProjectButton onPress = { onCreateProject } isDisabled = { projects . length === 0 } />
0 commit comments