You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
import*asReactfrom'react';import{ItemTreeNode,TransformedDataAndSetter,virtualRootId}from'~Workflowish/mvc/model';import{OmniBarState}from'../States';import{SpecializedPropsFactory}from'.';import{FocusActions}from'~Workflowish/Item';import{getDefaultOmnibarState}from'..';import{expandParentsAndFocusItem}from'./utilities';typeSearchState={searchText: string,selectionIdx: number}constHighlightStatesArray=["SEARCH_UNCOLLAPSE","SEARCH_MATCH","SEARCH_SELECTED"]asconst;exporttypeHighlightStates=typeofHighlightStatesArray[number];exportconstNO_MATCH="";exportconstsearchPropsFactory: SpecializedPropsFactory=(omniBarState: OmniBarState,setOmniBarState: React.Dispatch<React.SetStateAction<OmniBarState>>,transformedDataAndSetter: TransformedDataAndSetter,itemsRefDictionary: Record<string,FocusActions>)=>{const{ rootNode, nMatches, currentMatchId }=searchTransformFromOmnibarState(transformedDataAndSetter.transformedData.rootNode,omniBarState,setOmniBarState);constmatchMessage=nMatches>0 ? `${omniBarState.selectionIdx+1} / ${nMatches} matches` : "No matches"constscrollToCurrentItem=()=>itemsRefDictionary[currentMatchId]?.scrollThisIntoView();constfocusOriginalItem=()=>itemsRefDictionary[omniBarState.preOmnibarFocusItemId||""]?.focusThis();constexpandCurrentItem=()=>{if(currentMatchId!=NO_MATCH){expandParentsAndFocusItem(transformedDataAndSetter,itemsRefDictionary,currentMatchId);}};return{omnibarKeyHandler: makeSearchKeyEventHandler(setOmniBarState,scrollToCurrentItem,focusOriginalItem,expandCurrentItem),
rootNode,extraAnnotations: omniBarState.barContents.length ? <span>{matchMessage}</span> : <></>}}constsearchTransformFromOmnibarState=(rootNode: ItemTreeNode,omniBarState: OmniBarState,setOmniBarState: React.Dispatch<React.SetStateAction<OmniBarState>>): ReturnType<typeofsearchTransform>=>{const{ searchState, setSearchState }=omniBarStateProxy(omniBarState,setOmniBarState);returnsearchTransform(rootNode,searchState,setSearchState);}constomniBarStateProxy=(omniBarState: OmniBarState,setOmnibarState: React.Dispatch<React.SetStateAction<OmniBarState>>): {searchState: SearchState,setSearchState: React.Dispatch<React.SetStateAction<SearchState>>}=>{const omniBarStateToSearchState =(omniBarState: OmniBarState): SearchState=>{letsearchText=omniBarState.barContents;if(searchText.startsWith(">")){searchText="";}return{selectionIdx: omniBarState.selectionIdx,
searchText
}};return{searchState: omniBarStateToSearchState(omniBarState),setSearchState: (newSearchStateOrSetter: SearchState|((old: SearchState)=>SearchState))=>{setOmnibarState((omniBarState: OmniBarState): OmniBarState=>{
let searchStateToSet: SearchState=omniBarStateToSearchState(omniBarState);if(typeofnewSearchStateOrSetter=="function"){searchStateToSet=newSearchStateOrSetter(searchStateToSet);}else{searchStateToSet=newSearchStateOrSetter;}constsearchPartialState: Partial<SearchState> = searchStateToSet;
delete searchPartialState.searchText; // TODO: Surely there's a more idiomatic way to delete one property of an item to convert it into another
return {
...omniBarState,barContents: searchStateToSet.searchText,selectionIdx: searchStateToSet.selectionIdx}})}};}constsearchTransform=(rootNode: ItemTreeNode,searchParams: SearchState,setSearchParams: React.Dispatch<React.SetStateAction<SearchState>>): {rootNode: ItemTreeNode,nMatches: number,currentMatchId: string,currentMatchParentChain: string[]}=>{// TODO: room for optimization here to omit the DFS if there is no search text, but be careful!constnodeStack: Array<ItemTreeNode>=[rootNode];typeDFSMetadata={passCount: numbernode: ItemTreeNode,isMatch: boolean,dfsOrder: number,parentChain: string[]}letdfsOrder=0;constdfsSeenList: Record<string,DFSMetadata>={[rootNode.id]: {passCount: 1,node: rootNode,isMatch: false,
dfsOrder,parentChain: [rootNode.id]}};rootNode.searchHighlight=rootNode.searchHighlight.filter(state=>!HighlightStatesArray.includes(stateasHighlightStates));letnMatches=0;letcurrentMatchId=NO_MATCH;letcurrentMatchParentChain: string[]=[];while(nodeStack.length){consttop: ItemTreeNode=nodeStack.pop()asItemTreeNode;if(dfsSeenList[top.id].passCount==1){dfsSeenList[top.id].passCount++;dfsSeenList[top.id].dfsOrder=dfsOrder;dfsOrder++;nodeStack.push(top);// Emit all my children to the stacktop.children.forEach(child=>{dfsSeenList[child.id]={passCount: 1,node: child,isMatch: false,dfsOrder: -1,parentChain: [...dfsSeenList[top.id].parentChain,child.id]}child.searchHighlight=child.searchHighlight.filter(state=>!HighlightStatesArray.includes(stateasHighlightStates));});constreversedChildrenForDFS=[...top.children].reverse();nodeStack.push(...reversedChildrenForDFS);}elseif(dfsSeenList[top.id].passCount==2){if(searchParams.searchText.length>0&&top.data.toLowerCase().includes(searchParams.searchText.toLowerCase())){top.searchHighlight.push("SEARCH_MATCH");if(top.id!=virtualRootId){dfsSeenList[top.id].isMatch=true;}nMatches++;}constshouldUncollapse=top.children.reduce((shouldUncollapse,child)=>shouldUncollapse||child.searchHighlight.includes("SEARCH_UNCOLLAPSE")||child.searchHighlight.includes("SEARCH_MATCH"),false);if(shouldUncollapse){top.searchHighlight.push("SEARCH_UNCOLLAPSE");}}}constsearchMatchArray=Object.values(dfsSeenList).sort((a: DFSMetadata,b: DFSMetadata)=>a.dfsOrder-b.dfsOrder).filter((i: DFSMetadata)=>i.isMatch);if(searchMatchArray.length>0){if(searchParams.selectionIdx<0){setSearchParams({ ...searchParams,selectionIdx: 0});}elseif(searchParams.selectionIdx>searchMatchArray.length-1){setSearchParams({ ...searchParams,selectionIdx: searchMatchArray.length-1});}else{searchMatchArray[searchParams.selectionIdx].node.searchHighlight.push("SEARCH_SELECTED");currentMatchId=searchMatchArray[searchParams.selectionIdx].node.id;currentMatchParentChain=searchMatchArray[searchParams.selectionIdx].parentChain;}}return{rootNode: { ...rootNode},nMatches,currentMatchId,currentMatchParentChain};}exportconstmakeSearchKeyEventHandler=(setOmniBarState: React.Dispatch<React.SetStateAction<OmniBarState>>,scrollToCurrentItem: ()=>void,focusOriginalItem: ()=>void,expandParentsAndFocusItem: ()=>void)=>{return(evt: React.KeyboardEvent)=>{if(evt.key=="ArrowUp"){setOmniBarState((oldState)=>({ ...oldState,selectionIdx: oldState.selectionIdx-1}))window.setTimeout(scrollToCurrentItem,1);}elseif(evt.key=="ArrowDown"){setOmniBarState((oldState)=>({ ...oldState,selectionIdx: oldState.selectionIdx+1}))window.setTimeout(scrollToCurrentItem,1);}elseif(evt.key=="Enter"){setOmniBarState(getDefaultOmnibarState());expandParentsAndFocusItem()}elseif(evt.key=="Escape"){// Todo: This seems common to the command specialization - do some code dedupsetOmniBarState(getDefaultOmnibarState());focusOriginalItem();}else{// Search query was changedwindow.setTimeout(scrollToCurrentItem,1);}}}
The text was updated successfully, but these errors were encountered:
https://api.github.com/acenturyandabit/workflowish/blob/d9dac81df2e15a1b543aaf24406286b3278b7042/src/Workflowish/Subcomponents/OmnibarWrapper/Specializations/search.tsx#L85
The text was updated successfully, but these errors were encountered: