diff --git a/apps/remix-ide/src/app/files/fileProvider.ts b/apps/remix-ide/src/app/files/fileProvider.ts
index a0368aaf73..81c8c740ec 100644
--- a/apps/remix-ide/src/app/files/fileProvider.ts
+++ b/apps/remix-ide/src/app/files/fileProvider.ts
@@ -287,7 +287,7 @@ export default class FileProvider {
// ^ ret does not accept path starting with '/'
}
}
- console.log(`resolveDirectory ${path} took ${Date.now() - startTime} ms`)
+ //console.log(`resolveDirectory ${path} took ${Date.now() - startTime} ms`)
if (cb) cb(null, ret)
return ret
} catch (error) {
diff --git a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx
index 09db5cb396..c6d714691e 100644
--- a/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx
+++ b/libs/remix-ui/workspace/src/lib/components/file-explorer.tsx
@@ -369,13 +369,12 @@ export const FileExplorer = (props: FileExplorerProps) => {
}
}, [props])
- const handleTreeClick = (e: SyntheticEvent) => {
- console.log('tree click', e.target)
- // find any parent of e.target that has a data-path attribute
- // if found, call handleClickFolder with that path
- // if not found, do nothing
+ const handleTreeClick = (event: SyntheticEvent) => {
+ event.stopPropagation()
+ console.log('tree click', event.target)
- let target = e.target as HTMLElement
+
+ let target = event.target as HTMLElement
while (target && target.getAttribute && !target.getAttribute('data-path')) {
target = target.parentElement
}
@@ -384,11 +383,15 @@ export const FileExplorer = (props: FileExplorerProps) => {
const type = target.getAttribute('data-type')
if (path && type === 'file') {
console.log('tree click', path)
- handleClickFile(path, type as WorkspaceElement)
+
+ if (state.focusEdit.element !== path) handleClickFile(path, type)
+
} else if (path && type === 'folder') {
console.log('tree click', path)
- handleClickFolder(path, type)
+ if (state.focusEdit.element !== path) handleClickFolder(path, type)
+
}
+ if (props.showIconsMenu === true) props.hideIconsMenu(!props.showIconsMenu)
}
}
@@ -436,7 +439,9 @@ export const FileExplorer = (props: FileExplorerProps) => {
editModeOff={editModeOff}
files={files}
expandPath={props.expandPath}
- handleContextMenu={handleContextMenu}
+ handleContextMenu={handleContextMenu}
+ moveFile={handleFileMove}
+ moveFolder={handleFolderMove}
/>
@@ -449,14 +454,3 @@ export const FileExplorer = (props: FileExplorerProps) => {
}
export default FileExplorer
-
-/*
-
- */
diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx
new file mode 100644
index 0000000000..eb13a760e2
--- /dev/null
+++ b/libs/remix-ui/workspace/src/lib/components/flat-tree-drop.tsx
@@ -0,0 +1,50 @@
+import React, { SyntheticEvent, startTransition, useEffect, useRef, useState } from 'react'
+import { FileType } from '../types'
+import { getEventTarget } from '../utils/getEventTarget'
+import { extractParentFromKey } from '@remix-ui/helper'
+interface FlatTreeDropProps {
+ moveFile: (dest: string, src: string) => void
+ moveFolder: (dest: string, src: string) => void
+ getFlatTreeItem: (path: string) => FileType
+ dragSource: FileType
+ children: React.ReactNode
+}
+export const FlatTreeDrop = (props: FlatTreeDropProps) => {
+
+ const { getFlatTreeItem, dragSource, moveFile, moveFolder } = props
+ const onDragOver = async (e: SyntheticEvent) => {
+ //setShowMouseOverTarget(false)
+ e.preventDefault()
+ const target = await getEventTarget(e)
+ }
+
+ const onDrop = async (event: SyntheticEvent) => {
+ event.preventDefault()
+ console.log('drop', event)
+ const target = await getEventTarget(event)
+ const dragDestination = getFlatTreeItem(target.path)
+ console.log(getFlatTreeItem)
+ console.log('drop', target, dragDestination, dragSource)
+
+ if (dragDestination.isDirectory) {
+ if (dragSource.isDirectory) {
+ moveFolder(dragDestination.path, dragSource.path)
+ } else {
+ moveFile(dragDestination.path, dragSource.path)
+ }
+ } else {
+ const path = extractParentFromKey(dragDestination.path) || '/'
+
+ if (dragSource.isDirectory) {
+ moveFolder(path, dragSource.path)
+ } else {
+ moveFile(path, dragSource.path)
+ }
+ }
+ }
+
+
+ return (
{props.children}
)
+}
\ No newline at end of file
diff --git a/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx b/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx
index 3bcac80525..2428da3bd2 100644
--- a/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx
+++ b/libs/remix-ui/workspace/src/lib/components/flat-tree.tsx
@@ -5,6 +5,8 @@ import { ROOT_PATH } from '../utils/constants'
import { getPathIcon } from '@remix-ui/helper';
import { Virtuoso } from 'react-virtuoso'
import { RecursiveItemInput } from './file-recursive-item-input';
+import { FlatTreeDrop } from './flat-tree-drop';
+import { getEventTarget } from '../utils/getEventTarget';
interface FlatTreeProps {
files: { [x: string]: Record },
@@ -16,6 +18,8 @@ interface FlatTreeProps {
handleContextMenu: (pageX: number, pageY: number, path: string, content: string, type: string) => void
handleTreeClick: (e: SyntheticEvent) => void
treeRef: React.MutableRefObject
+ moveFile: (dest: string, src: string) => void
+ moveFolder: (dest: string, src: string) => void
}
let mouseTimer: any = {
@@ -24,7 +28,7 @@ let mouseTimer: any = {
}
export const FlatTree = (props: FlatTreeProps) => {
- const { files, expandPath, focusEdit, editModeOff, handleTreeClick } = props
+ const { files, expandPath, focusEdit, editModeOff, handleTreeClick, moveFile, moveFolder } = props
const [flatTree, setFlatTree] = useState<{ [x: string]: FileType }>({})
const [hover, setHover] = useState('')
const [mouseOverTarget, setMouseOverTarget] = useState<{
@@ -37,13 +41,12 @@ export const FlatTree = (props: FlatTreeProps) => {
}
}>(null)
const [showMouseOverTarget, setShowMouseOverTarget] = useState(false)
+ const [dragSource, setDragSource] = useState()
+ const [isDragging, setIsDragging] = useState(false)
const ref = useRef(null)
const [size, setSize] = useState(0)
-
-
-
const labelClass = (file: FileType) =>
props.focusEdit.element === file.path
? 'bg-light'
@@ -72,9 +75,6 @@ export const FlatTree = (props: FlatTreeProps) => {
setFlatTree(flatTree)
}, [props])
-
-
-
const getIndentLevelDiv = (path: string) => {
// remove double slash
path = path.replace(/\/\//g, '/')
@@ -83,33 +83,7 @@ export const FlatTree = (props: FlatTreeProps) => {
const pathArray = path.split('/')
const level = pathArray.length - 1
const indent = level * 10
- return ()
- }
-
- const getEventTarget = async (e: any, useLabel: boolean = false) => {
- let target = e.target as HTMLElement
- while (target && target.getAttribute && !target.getAttribute(useLabel? 'data-label-path' : 'data-path')) {
- target = target.parentElement
- }
- if (target && target.getAttribute) {
- const path = target.getAttribute(useLabel? 'data-label-path' : 'data-path')
- const type = target.getAttribute(useLabel? 'data-label-type' : 'data-type')
- const position = target.getBoundingClientRect()
- // get size of element
-
- const endPosition = {
- top: position.top - position.height * 2 + 4,
- left: position.left ,
- }
-
- const content = target.textContent
- return {
- path,
- type,
- content,
- position: endPosition
- }
- }
+ return ()
}
const handleContextMenu = async (e: any) => {
@@ -121,22 +95,32 @@ export const FlatTree = (props: FlatTreeProps) => {
}
}
- const onDragEnd = (event: SyntheticEvent) => {
- console.log('drag end', event)
+ const onDragStart = async (event: SyntheticEvent) => {
+ console.log('drag start', event)
+ const target = await getEventTarget(event)
+ console.log(flatTree[target.path], target.path)
+ setDragSource(flatTree[target.path])
+ setIsDragging(true)
}
- const onDrop = async (event: SyntheticEvent) => {
- event.preventDefault()
- console.log('drop', event)
- const target = await getEventTarget(event)
- console.log('drop', target)
+ useEffect(() => {
+ console.log('drag source', dragSource)
+ if(isDragging) {
+ mouseTimer = {
+ path: null,
+ timer: null
+ }
+ }
+ },[isDragging])
+
+ const onDragEnd = (event: SyntheticEvent) => {
+ setIsDragging(false)
+ console.log('drag end', event)
}
- const onDragOver = async (e: SyntheticEvent) => {
- e.preventDefault()
- //console.log('drag over', e)
- const target = await getEventTarget(e)
- //console.log('drag over', target)
+ const getFlatTreeItem = (path: string) => {
+ console.log('get flat tree item', path, flatTree[path])
+ return flatTree[path]
}
const onMouseMove = async (e: any) => {
@@ -196,14 +180,20 @@ export const FlatTree = (props: FlatTreeProps) => {
{focusEdit && file.path && focusEdit.element === file.path ?
:
- {file.name}
+
{file.name}
}
)
}
return (<>
-
- {showMouseOverTarget && mouseOverTarget &&
+
+
+ {showMouseOverTarget && mouseOverTarget && !isDragging &&
{
{mouseOverTarget && mouseOverTarget.path}
- }
-
Row(index)}
- />
-
+ }
+ Row(index)}
+ />
+
+
>)
}
\ No newline at end of file
diff --git a/libs/remix-ui/workspace/src/lib/utils/getEventTarget.ts b/libs/remix-ui/workspace/src/lib/utils/getEventTarget.ts
new file mode 100644
index 0000000000..e61cc7a226
--- /dev/null
+++ b/libs/remix-ui/workspace/src/lib/utils/getEventTarget.ts
@@ -0,0 +1,25 @@
+export const getEventTarget = async (e: any, useLabel: boolean = false) => {
+ let target = e.target as HTMLElement
+ while (target && target.getAttribute && !target.getAttribute(useLabel? 'data-label-path' : 'data-path')) {
+ target = target.parentElement
+ }
+ if (target && target.getAttribute) {
+ const path = target.getAttribute(useLabel? 'data-label-path' : 'data-path')
+ const type = target.getAttribute(useLabel? 'data-label-type' : 'data-type')
+ const position = target.getBoundingClientRect()
+ // get size of element
+
+ const endPosition = {
+ top: position.top - position.height * 2 + 4,
+ left: position.left ,
+ }
+
+ const content = target.textContent
+ return {
+ path,
+ type,
+ content,
+ position: endPosition
+ }
+ }
+}
\ No newline at end of file