Skip to content

Commit 5007aba

Browse files
committed
feat: support TreeView Drag API
1 parent 9c0b433 commit 5007aba

16 files changed

Lines changed: 1726 additions & 127 deletions

File tree

packages/core-common/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,4 @@ export * from './markdown';
3434
export * from './settings';
3535
export * from './utils';
3636
export * from './clipboard';
37+
export * from './mime';

packages/core-common/src/mime.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
export const Mimes = Object.freeze({
2+
text: 'text/plain',
3+
binary: 'application/octet-stream',
4+
unknown: 'application/unknown',
5+
markdown: 'text/markdown',
6+
latex: 'text/latex',
7+
uriList: 'text/uri-list',
8+
});

packages/extension/src/browser/components/extension-tree-view-node.tsx

Lines changed: 92 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import cls from 'classnames';
2-
import React from 'react';
2+
import React, { CSSProperties, FC, MouseEvent, ReactNode, useCallback, useEffect, useState, DragEvent } from 'react';
33

44
import { INodeRendererProps, ClasslistComposite, PromptHandle, TreeNodeType } from '@opensumi/ide-components';
55
import { Loading } from '@opensumi/ide-components';
@@ -19,23 +19,21 @@ export interface ITreeViewNodeProps {
1919
defaultLeftPadding?: number;
2020
leftPadding?: number;
2121
decorations?: ClasslistComposite;
22-
onTwistierClick?: (
23-
ev: React.MouseEvent,
24-
item: ExtensionTreeNode | ExtensionCompositeTreeNode,
25-
type: TreeNodeType,
26-
) => void;
27-
onClick: (ev: React.MouseEvent, item: ExtensionTreeNode | ExtensionCompositeTreeNode, type: TreeNodeType) => void;
28-
onContextMenu?: (
29-
ev: React.MouseEvent,
30-
item: ExtensionTreeNode | ExtensionCompositeTreeNode,
31-
type: TreeNodeType,
32-
) => void;
22+
onTwistierClick?: (ev: MouseEvent, item: ExtensionTreeNode | ExtensionCompositeTreeNode, type: TreeNodeType) => void;
23+
onClick: (ev: MouseEvent, item: ExtensionTreeNode | ExtensionCompositeTreeNode, type: TreeNodeType) => void;
24+
onContextMenu?: (ev: MouseEvent, item: ExtensionTreeNode | ExtensionCompositeTreeNode, type: TreeNodeType) => void;
25+
onDragStart?: (ev: MouseEvent, item: ExtensionTreeNode | ExtensionCompositeTreeNode) => void;
26+
onDragEnter?: (ev: MouseEvent, item: ExtensionTreeNode | ExtensionCompositeTreeNode) => void;
27+
onDrop?: (ev: MouseEvent, item: ExtensionTreeNode | ExtensionCompositeTreeNode) => void;
28+
onDragOver?: (ev: MouseEvent, item: ExtensionTreeNode | ExtensionCompositeTreeNode) => void;
29+
onDragLeave?: (ev: MouseEvent, item: ExtensionTreeNode | ExtensionCompositeTreeNode) => void;
3330
decorationService: IDecorationsService;
31+
draggable: boolean;
3432
}
3533

3634
export type TreeViewNodeRenderedProps = ITreeViewNodeProps & INodeRendererProps;
3735

38-
export const TreeViewNode: React.FC<TreeViewNodeRenderedProps> = ({
36+
export const TreeViewNode: FC<TreeViewNodeRenderedProps> = ({
3937
item,
4038
onClick,
4139
onContextMenu,
@@ -46,10 +44,16 @@ export const TreeViewNode: React.FC<TreeViewNodeRenderedProps> = ({
4644
defaultLeftPadding = 8,
4745
treeViewId,
4846
decorationService,
47+
draggable,
48+
onDragStart,
49+
onDragEnter,
50+
onDragLeave,
51+
onDragOver,
52+
onDrop,
4953
}: TreeViewNodeRenderedProps) => {
50-
const [decoration, setDecoration] = React.useState(item.uri && decorationService.getDecoration(item.uri, false));
54+
const [decoration, setDecoration] = useState(item.uri && decorationService.getDecoration(item.uri, false));
5155

52-
React.useEffect(() => {
56+
useEffect(() => {
5357
const disposable = decorationService.onDidChangeDecorations((e) => {
5458
if (item.uri && e.affectsResource(item.uri)) {
5559
setDecoration(decorationService.getDecoration(item.uri, false));
@@ -62,30 +66,74 @@ export const TreeViewNode: React.FC<TreeViewNodeRenderedProps> = ({
6266

6367
const themeService = useInjectable<IThemeService>(IThemeService);
6468

65-
const handleClick = (ev: React.MouseEvent) => {
66-
if (itemType === TreeNodeType.TreeNode || itemType === TreeNodeType.CompositeTreeNode) {
67-
onClick(ev, item, itemType);
68-
}
69-
};
70-
71-
const handlerTwistierClick = (ev: React.MouseEvent) => {
72-
if (itemType === TreeNodeType.TreeNode || itemType === TreeNodeType.CompositeTreeNode) {
73-
if (onTwistierClick) {
74-
onTwistierClick(ev, item, itemType);
75-
} else {
69+
const handleClick = useCallback(
70+
(ev: MouseEvent) => {
71+
if (itemType === TreeNodeType.TreeNode || itemType === TreeNodeType.CompositeTreeNode) {
7672
onClick(ev, item, itemType);
7773
}
78-
}
79-
};
74+
},
75+
[item, itemType, onClick],
76+
);
8077

81-
const handleContextMenu = (ev: React.MouseEvent) => {
82-
if (ev.nativeEvent.which === 0 || !onContextMenu) {
83-
return;
84-
}
85-
if (itemType === TreeNodeType.TreeNode || itemType === TreeNodeType.CompositeTreeNode) {
86-
onContextMenu(ev, item, itemType);
87-
}
88-
};
78+
const handlerTwistierClick = useCallback(
79+
(ev: MouseEvent) => {
80+
if (itemType === TreeNodeType.TreeNode || itemType === TreeNodeType.CompositeTreeNode) {
81+
if (onTwistierClick) {
82+
onTwistierClick(ev, item, itemType);
83+
} else {
84+
onClick(ev, item, itemType);
85+
}
86+
}
87+
},
88+
[itemType, onTwistierClick, onClick],
89+
);
90+
91+
const handleContextMenu = useCallback(
92+
(ev: MouseEvent) => {
93+
if (ev.nativeEvent.which === 0 || !onContextMenu) {
94+
return;
95+
}
96+
if (itemType === TreeNodeType.TreeNode || itemType === TreeNodeType.CompositeTreeNode) {
97+
onContextMenu(ev, item, itemType);
98+
}
99+
},
100+
[item, itemType, onContextMenu],
101+
);
102+
103+
const handleDragStart = useCallback(
104+
(event: DragEvent) => {
105+
onDragStart && onDragStart(event, item);
106+
},
107+
[item, onDragStart],
108+
);
109+
110+
const handleDragEnter = useCallback(
111+
(event: DragEvent) => {
112+
onDragEnter && onDragEnter(event, item);
113+
},
114+
[item, onDragEnter],
115+
);
116+
117+
const handleDragLeave = useCallback(
118+
(event: DragEvent) => {
119+
onDragLeave && onDragLeave(event, item);
120+
},
121+
[item, onDragLeave],
122+
);
123+
124+
const handleDragOver = useCallback(
125+
(event: DragEvent) => {
126+
onDragOver && onDragOver(event, item);
127+
},
128+
[item, onDragOver],
129+
);
130+
131+
const handleDrop = useCallback(
132+
(event: DragEvent) => {
133+
onDrop && onDrop(event, item);
134+
},
135+
[item, onDrop],
136+
);
89137

90138
const isDirectory = itemType === TreeNodeType.CompositeTreeNode;
91139
const paddingLeft = isDirectory
@@ -96,7 +144,7 @@ export const TreeViewNode: React.FC<TreeViewNodeRenderedProps> = ({
96144
height: TREE_VIEW_NODE_HEIGHT,
97145
lineHeight: `${TREE_VIEW_NODE_HEIGHT}px`,
98146
paddingLeft,
99-
} as React.CSSProperties;
147+
} as CSSProperties;
100148

101149
const renderFolderToggle = (node: ExtensionCompositeTreeNode | PromptHandle, clickHandler: any) => {
102150
if (decorations && decorations?.classlist.indexOf(styles.mod_loading) > -1) {
@@ -119,7 +167,7 @@ export const TreeViewNode: React.FC<TreeViewNodeRenderedProps> = ({
119167
const renderDisplayName = (node: ExtensionCompositeTreeNode | ExtensionTreeNode) => {
120168
const displayName = () => {
121169
if (node.highlights) {
122-
let hightlightSnaps: React.ReactNode[] = [];
170+
let hightlightSnaps: ReactNode[] = [];
123171
let endIndex = 0;
124172
const hightlights = node.highlights.sort((a, b) => a[0] - b[0]);
125173
hightlightSnaps = hightlights.map((highlight, index: number) => {
@@ -213,11 +261,16 @@ export const TreeViewNode: React.FC<TreeViewNodeRenderedProps> = ({
213261
key={item.id}
214262
onClick={handleClick}
215263
onContextMenu={handleContextMenu}
264+
onDragStart={handleDragStart}
265+
onDragOver={handleDragOver}
266+
onDragEnter={handleDragEnter}
267+
onDragLeave={handleDragLeave}
268+
onDrop={handleDrop}
216269
title={getItemTooltip()}
217270
className={cls(styles.tree_view_node, decorations ? decorations.classlist : null)}
218271
data-id={item.id}
219272
style={fileTreeNodeStyle}
220-
draggable={itemType === TreeNodeType.TreeNode || itemType === TreeNodeType.CompositeTreeNode}
273+
draggable={draggable}
221274
>
222275
<div className={cls(styles.tree_view_node_content)}>
223276
{renderTwice(item)}

0 commit comments

Comments
 (0)