Skip to content

Commit ea7164f

Browse files
committed
fix: keyboard navigation fixes and scroll support added
1 parent 0f336ab commit ea7164f

File tree

8 files changed

+63
-45
lines changed

8 files changed

+63
-45
lines changed

extension/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@
138138
"@tippy.js/react": "^3.1.1",
139139
"@types/react-window": "^1.8.5",
140140
"classnames": "^2.3.2",
141+
"pubsub-js": "^1.9.4",
141142
"react": "^17.0.2",
142143
"react-dom": "^17.0.2",
143144
"react-window": "^1.8.8"

extension/src/SidebarProvider.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export class SidebarProvider implements vscode.WebviewViewProvider {
9191
}
9292
// Open and the show the user the file they want to see
9393
const doc = await vscode.workspace.openTextDocument(data.value);
94-
const editor = await vscode.window.showTextDocument(doc, { preserveFocus: false, preview: false });
94+
const editor = await vscode.window.showTextDocument(doc, { preserveFocus: true, preview: false });
9595
break;
9696
}
9797

extension/src/webviews/components/Tree/Node/Node.tsx

+2-26
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@ import { faChevronDown, faChevronRight } from '@fortawesome/free-solid-svg-icons
33
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
44
import classNames from 'classnames';
55
import { ListChildComponentProps } from 'react-window'
6-
import { DispatchContext, renderProvider, StateContext } from '../../../pages/sidebar';
6+
import { renderProvider, StateContext } from '../../../pages/sidebar';
77
import { INode } from '../../../Tree';
88
import InfoPanel from './InfoPanel';
9-
import { useKeyBindings } from '../../../hooks/useKeyBindings';
109

1110

1211
const Node: React.FC<ListChildComponentProps<INode[]>> = ({
@@ -18,42 +17,19 @@ const Node: React.FC<ListChildComponentProps<INode[]>> = ({
1817

1918
const { activeNode, focussedNode } = useContext(StateContext);
2019
const nodeRef = useRef<HTMLDivElement>(null);
21-
const dispatch = useContext(DispatchContext);
22-
2320

2421
const toggleNode = (e) => {
2522
e.stopPropagation();
2623
renderProvider.toggleNode(node);
2724
};
2825

2926
const onClick = () => {
30-
if (!node.thirdParty) {
31-
dispatch({
32-
type: "UPDATE_ACTIVE_NODE",
33-
payload: node.id
34-
});
35-
viewFile();
36-
}
27+
renderProvider.visitNode(node);
3728
}
3829
const paddingLeft = 15 * node.level;
3930
const indentationStyle: React.CSSProperties = {
4031
paddingLeft
4132
}
42-
// Function that will capture the file path of the current node clicked on + send a message to the extension
43-
const viewFile = () => {
44-
// Edge case to verify that there is in fact a file path for the current node
45-
if (node.filePath) {
46-
vscodeApi.postMessage({
47-
type: "onViewFile",
48-
value: node.filePath
49-
});
50-
// since we call
51-
setTimeout(() => {
52-
// console.log(document.querySelector('.sidebar'))
53-
(document.querySelector('.sidebar') as HTMLDivElement)?.click?.();
54-
}, 3000);
55-
}
56-
};
5733

5834
return (
5935
<div ref={nodeRef} onClick={onClick} className={classNames('node-container', {

extension/src/webviews/components/Tree/Tree.tsx

+34-11
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
import React, { useContext, useEffect, useRef } from 'react';
22
import { FixedSizeList } from 'react-window';
3+
import PubSub from 'pubsub-js';
34
import { ACTIONS } from '../../actions';
45
import { useKeyBindings } from '../../hooks/useKeyBindings';
56
import { DispatchContext, renderProvider, StateContext } from '../../pages/sidebar';
67
import Navigation from '../../service/Navigation';
78
import { INode } from '../../Tree';
89
import Node from './Node/Node';
10+
import { PubSubEvents } from '../../constants/PubSubEvents';
911

1012
interface IProps {
1113
}
@@ -27,24 +29,38 @@ const Tree: React.FC<IProps> = () => {
2729
if (message.type === "onActiveTextEditor") {
2830
const node = renderProvider.filePathMap.get(message.value);
2931
if (node) {
30-
listRef.current?.scrollToItem(node.index, "smart");
31-
dispatch({
32-
type: ACTIONS.UPDATE_ACTIVE_NODE,
33-
payload: node.id
34-
});
32+
scrollToNode(node);
3533
}
3634
}
3735
});
36+
const subscription = PubSub.subscribe(PubSubEvents.SCROLL_TO_NODE, (_, nodeId) => {
37+
const node = renderProvider.rowMap.get(nodeId);
38+
if (node) {
39+
scrollToNode(node);
40+
}
41+
})
42+
return () => {
43+
PubSub.unsubscribe(subscription);
44+
}
3845
}, []);
3946

47+
const scrollToNode = (node: INode) => {
48+
if (node) {
49+
listRef.current?.scrollToItem(node.index, "smart");
50+
dispatch({
51+
type: ACTIONS.UPDATE_ACTIVE_NODE,
52+
payload: node.id
53+
});
54+
}
55+
};
56+
4057
useKeyBindings((keyCode) => {
4158
const node = focussedNode ? renderProvider.rowMap.get(focussedNode as string) : null;
42-
console.log(focussedNode,node)
4359
if (node) {
4460
navigateHandler(keyCode, node);
4561
}
4662
},
47-
['ArrowUp', 'ArrowDown', 'ArrowRight', 'ArrowLeft'], focussedNode);
63+
['ArrowUp', 'ArrowDown', 'ArrowRight', 'ArrowLeft', 'Enter'], focussedNode);
4864

4965

5066
return (<FixedSizeList
@@ -96,14 +112,21 @@ const navigateHandler = (keyCode, node: INode) => {
96112
break;
97113
}
98114
case 'ArrowUp': {
99-
Navigation.moveUp(node)
115+
Navigation.moveUp(node);
100116
break;
101117
}
102118
case 'ArrowDown': {
103-
Navigation.moveDown(node)
119+
Navigation.moveDown(node);
120+
break;
121+
}
122+
case 'Enter': {
123+
renderProvider.visitNode(node);
124+
break;
125+
}
126+
default: {
104127
break;
105128
}
106129
}
107-
}
130+
};
108131

109-
export default Tree;
132+
export default Tree;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export const PubSubEvents = {
2+
SCROLL_TO_NODE: 'SCROLL_TO_NODE'
3+
}

extension/src/webviews/hooks/useKeyBindings.tsx

-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import { useEffect } from "react";
22

33
export function useKeyBindings(callback: (keyCode: string) => void, keyCodes: string[], dependency): void {
44
const handler = ({ code }: KeyboardEvent) => {
5-
console.log(code)
65
if (keyCodes.includes(code)) {
76
callback(code);
87
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
import PubSub from 'pubsub-js';
12
import { ACTIONS } from "../actions";
3+
import { PubSubEvents } from '../constants/PubSubEvents';
24
import { renderProvider } from "../pages/sidebar";
35
import { INode } from "../Tree";
46

@@ -9,14 +11,15 @@ export default class Navigation {
911
}
1012

1113
static moveDown(node: INode) {
12-
const index = Math.max(node.index + 1, renderProvider.data.length - 1);
14+
const index = Math.min(node.index + 1, renderProvider.data.length - 1);
1315
Navigation.move(index);
1416
}
1517
private static move(index: number) {
16-
const prevNode = renderProvider.data[index];
18+
const node = renderProvider.data[index];
1719
renderProvider.dispatch({
1820
type: ACTIONS.UPDATE_FOCUSSED_NODE,
19-
payload: prevNode.id
21+
payload: node.id
2022
});
23+
PubSub.publish(PubSubEvents.SCROLL_TO_NODE, node.id);
2124
}
2225
}

extension/src/webviews/service/RenderProvider.ts

+16-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { ACTIONS } from "../actions";
2-
import { INode, IRawNode, Tree } from "../Tree";
2+
import { INode} from "../Tree";
33

44
type TExpandCollapse = Record<string, boolean>;
55

@@ -61,7 +61,6 @@ export default class RenderProvider {
6161
this.rowMap = new Map();
6262
const result = this.filterData([this.rawTree]);
6363
this.flattenData(result);
64-
console.log(result)
6564
}
6665

6766
/**
@@ -153,11 +152,25 @@ export default class RenderProvider {
153152
this.updateNodes();
154153
}
155154

155+
visitNode(node: INode) {
156+
if (!node.thirdParty) {
157+
this.dispatch({
158+
type: ACTIONS.UPDATE_ACTIVE_NODE,
159+
payload: node.id
160+
});
161+
if (node.filePath) {
162+
vscodeApi.postMessage({
163+
type: "onViewFile",
164+
value: node.filePath
165+
});
166+
}
167+
}
168+
}
169+
156170
setGridExpandedState(gridExpandedState: ExpandedState = null) {
157171
this.gridExpandedState = gridExpandedState;
158172
this.expandCollapseConfig = {};
159173
this.updateNodes();
160-
console.log('gridExpandedState');
161174
}
162175

163176
search(searchString: string) {

0 commit comments

Comments
 (0)