added file drag and drop
mellbacon committed
May 7, 2023 at 16:43 UTC
326fff7c339ffaa4b543779e2f3fb0308855a625
4 files changed
+78
-11
src-tauri/tauri.conf.json
+2
-1
@@ -119,7 +119,8 @@
119
"width": 800,
120
"minWidth": 680,
121
"minHeight": 430,
122
- "decorations": false
122
+ "decorations": false,
123
+ "fileDropEnabled": false
124
}
125
]
126
}
src/lib/FileTree.svelte
+8
-4
@@ -1,7 +1,13 @@
1
<script lang="ts">
2
import FileTreeView from "./FileTree/FileTreeView.svelte";
3
+ export let tree = $filetree;
4
4
- let data = [{
5
+</script>
6
+
7
+<script lang="ts" context="module">
8
+ import { writable } from "svelte/store";
9
+
10
+ export let filetree = writable([{
11
id: 0, label: "FakeDir", path:"FakeDir/", children: [
12
{id: 1, label: "src", path:"FakeDir/src", children: [
13
{id: 2, label: "dist", path:"FakeDir/src/dist/", children: [
@@ -18,9 +24,7 @@
24
{id: 11, label: "misc3.nucleus", path:"FakeDir/Misc/misc3.nucleus",},
25
]},
26
],
21
- }]
22
- export let tree = data;
23
-
27
+ }]);
28
</script>
29
30
{#if tree.length === 0}
src/lib/FileTree/FileTreeList.svelte
+57
-3
@@ -8,6 +8,9 @@
8
9
import FileTreeNode, { computeTreeLeafDepth } from "./FileTreeNode.svelte";
10
import Directory from "../../util/icons/Directory.svelte";
11
+ import Sortable from 'sortablejs';
12
+ import { afterUpdate, onMount } from "svelte";
13
+ import {filetree} from "../FileTree.svelte";
14
15
export let root = false;
16
export let isroot = false;
@@ -20,10 +23,61 @@
23
let expanded = _expansionState[label] || false;
24
let ref = null;
25
let refLabel = null;
26
+ let refChildren = null;
27
let selected = false;
28
29
let icon = Directory;
30
31
+ onMount(() => {
32
+
33
+ })
34
+
35
+ function findNode(nodeid, tree = null) {
36
+ if (!tree) {
37
+ tree = $filetree;
38
+ if (nodeid === tree[0].id) {
39
+ return tree[0];
40
+ }
41
+ }
42
+ for (let node of tree) {
43
+ if (nodeid === node.id) {
44
+ return node;
45
+ }
46
+ else if (node.children) {
47
+ let n = findNode(nodeid, node.children);
48
+ if (n) {
49
+ return n;
50
+ }
51
+ continue;
52
+ }
53
+ }
54
+ }
55
+
56
+ function dragstart(e) {
57
+ let data = {element: `filetree-node-${id}`, id:id, type: "parent"};
58
+ e.dataTransfer.setData("text/plain", JSON.stringify(data));
59
+ }
60
+
61
+ function drop(e) {
62
+ let data = JSON.parse(e.dataTransfer.getData("text/plain"))
63
+ let el = document.getElementById(data.element);
64
+ let from = el.parentElement;
65
+ let to = e.target.parentElement.parentElement;
66
+
67
+ let fromid = from.getAttribute("data-id");
68
+ let toid = to.getAttribute("data-id");
69
+
70
+ const element = findNode(parseInt(data.id));
71
+ const fromlist = findNode(parseInt(fromid));
72
+ const tolist = findNode(parseInt(toid));
73
+
74
+ fromlist.children.splice(fromlist.children.indexOf(element), 1);
75
+ tolist.children = [...tolist.children, element];
76
+
77
+ from.removeChild(el);
78
+ to.appendChild(el);
79
+ }
80
+
81
const toggleExpansion = (event) => {
82
for (let nodes of document.getElementsByClassName("tree-label")) {
83
nodes.classList.remove("selected")
@@ -60,9 +114,9 @@
114
{/if}
115
{/each}
116
{:else}
63
- <li id={id} bind:this={ref} class="treenode" class:root={isroot}>
117
+ <li id={`filetree-node-${id}`} bind:this={ref} class="treenode" class:root={isroot}>
118
<!-- svelte-ignore a11y-click-events-have-key-events -->
65
- <div bind:this={refLabel} class:selected class="tree-label" on:click={toggleExpansion}>
119
+ <div bind:this={refLabel} class:selected class="tree-label" on:click={toggleExpansion} draggable={true} on:dragstart={dragstart}>
120
<span class="arrow" class:arrowDown>▶</span>
121
{#if icon}
122
<svelte:component this={icon} />
@@ -70,7 +124,7 @@
124
<div class="item-label">{label}</div>
125
</div>
126
{#if expanded}
73
- <ul role="group" class="tree-children">
127
+ <ul role="group" bind:this={refChildren} data-id={id} class="tree-children" on:dragover|preventDefault on:drop|stopPropagation={drop}>
128
{#each children as child (child.id) }
129
{#if Array.isArray(child.children)}
130
<svelte:self on:nodeselect {...child}></svelte:self>
src/lib/FileTree/FileTreeNode.svelte
+11
-3
@@ -18,7 +18,6 @@
18
import { createEventDispatcher } from "svelte";
19
import File from "../../util/icons/File.svelte";
20
21
-
21
export let id;
22
export let label;
23
export let path;
@@ -29,6 +28,15 @@
28
let refLabel = null;
29
let icon = File;
30
31
+ function dragstart(e) {
32
+ e.dataTransfer.setData(
33
+ "text/html",
34
+ e.target.parentElement.outerHTML
35
+ );
36
+ let data = {element: `filetree-node-${id}`, id:id, type: "node"};
37
+ e.dataTransfer.setData("text/plain", JSON.stringify(data));
38
+ }
39
+
40
const offset = () => computeTreeLeafDepth(refLabel) + (icon ? 2 : 1);
41
42
const dispatch = createEventDispatcher();
@@ -56,9 +64,9 @@
64
}
65
}}></svelte:window>
66
59
-<li id={id} bind:this={ref} class="treenode">
67
+<li id={`filetree-node-${id}`} bind:this={ref} class="treenode">
68
<!-- svelte-ignore a11y-click-events-have-key-events -->
61
- <div bind:this={refLabel} class="tree-label" class:selected on:click={(e) => {handleSelect(treenode, e)}}>
69
+ <div bind:this={refLabel} class="tree-label" class:selected on:click={(e) => {handleSelect(treenode, e)}} draggable={true} on:dragstart={dragstart}>
70
<span class="no-arrow"></span>
71
{#if icon}
72
<svelte:component this={icon} />