Skip to content

Commit 56a5ff4

Browse files
committed
✨ Multiple Entry drag and drop with copy or move
This version has the full implementation of drag and drop within the program. Without key pressed, the files will be copied. With the shift key, they will be moved. The cmd key will cancel the drop. All selected files with the current cursor will be effected.
1 parent 0e8396c commit 56a5ff4

File tree

6 files changed

+107
-56
lines changed

6 files changed

+107
-56
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ I've created multiple open source resources (I have around 80 GitHub repositorie
5252
## Current Feature Set
5353

5454
- Dual pane file manager with vim style model hotkeys for navigation and action launching.
55-
- Drag and Drop works for copying single file or directory (the current cursor location) within the application itself.
55+
- Drag and Drop works for copying or moving the current cursor and all selected files or directories (the current cursor location) within the application itself. If no keys pressed, it will be copied. If shift key is pressed, it will be moved. The drag begins with the current cursor.
5656
- Command Prompt for executing commands (`:` in any mode or `<ctrl>p` in normal mode).
5757
- Fully extendable with extensions using the extensions API
5858
- Fully extendable to alternate file systems
@@ -344,6 +344,10 @@ hotkeys or command prompt. They are loaded and used in a different way as well.
344344
| `createNewMode` | Allows the creation of a new mode for keyboard commands. |
345345
| `changeMode` | Change to mode given. |
346346
| `switchView` | Change to new program view. Currently `filemanager` or `preferences`. |
347+
| `copyEntriesCommand` | Copy the entry list to the destination entry. |
348+
| `moveEntriesCommand` | Move the entry list to the destination entry. |
349+
| `deleteEntriesCommand` | Delete the entry list |
350+
| `editEntriesCommand` | Edit the entry |
347351

348352
## Creating Themes
349353

public/bundle.bin

2.22 KB
Binary file not shown.

public/bundle.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/components/Entry.svelte

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -200,16 +200,39 @@
200200
}
201201
202202
function dragStart(e) {
203-
e.dataTransfer.dropEffect = 'copy';
203+
if(e.shiftKey) {
204+
e.dataTransfer.dropEffect = 'move';
205+
} else {
206+
e.dataTransfer.dropEffect = 'copy';
207+
}
208+
const lconfig = get(config);
209+
var flist = lconfig.extensions.getExtCommand('getSelectedFiles').command();
210+
var included = false;
211+
var data = [];
212+
flist.map(item => {
213+
data.push(utilities.appendPath(item.dir, item.name) + "|" + item.type);
214+
if(item.name === entry.name) included = true;
215+
});
204216
const file = utilities.appendPath(entry.dir, entry.name);
205-
e.dataTransfer.setData('text/plain', file + "|" + entry.type);
217+
if(!included) {
218+
data.push(file + "|" + entry.type);
219+
}
220+
e.dataTransfer.setData('text/plain', data.join('\n'));
206221
e.dataTransfer.setData('text/uri-url', "file://" + file);
207222
e.dataTransfer.setData("text/x-moz-url", "file://"+file);
208223
e.dataTransfer.setData("application/x-moz-file-promise-url", "file://" + file);
209224
}
210225
211226
function dropFiles(e,type) {
227+
var shiftKey = e.shiftKey;
212228
switch(type) {
229+
case 'over':
230+
if(e.shiftKey) {
231+
e.dataTransfer.dropEffect = 'move';
232+
} else {
233+
e.dataTransfer.dropEffect = 'copy';
234+
}
235+
break;
213236
case 'drop':
214237
//
215238
// Create the drop to entry.
@@ -225,28 +248,34 @@
225248
//
226249
// Create the entries from the drop.
227250
//
228-
const dataTrans = e.dataTransfer.getData('text/plain');
251+
const dataTransArray = e.dataTransfer.getData('text/plain').split('\n');
229252
const lconfig = get(config);
230-
const parts = dataTrans.split('|');
231-
if(parts[1] === '1') {
232-
dirPath = parts[0];
233-
var fdir = utilities.splitFilePath(dirPath);
234-
const nwDir = utilities.appendPath(toEntry.dir, fdir.name);
235-
utilities.makeDir(nwDir);
236-
toEntry.dir = nwDir;
237-
} else {
238-
const result = utilities.splitFilePath(parts[0]);
239-
dirPath = result.dir;
240-
fileName = result.name;
241-
}
242253
var fromEntries = [];
243-
fromEntries.push({
244-
dir: dirPath,
245-
name: fileName,
246-
fileSystemType: entry.fileSystemType,
247-
fileSystem: entry.fileSystem
254+
dataTransArray.forEach(dataTrans => {
255+
const parts = dataTrans.split('|');
256+
if(parts[1] === '1') {
257+
dirPath = parts[0];
258+
var fdir = utilities.splitFilePath(dirPath);
259+
const nwDir = utilities.appendPath(toEntry.dir, fdir.name);
260+
utilities.makeDir(nwDir);
261+
toEntry.dir = nwDir;
262+
} else {
263+
const result = utilities.splitFilePath(parts[0]);
264+
dirPath = result.dir;
265+
fileName = result.name;
266+
}
267+
fromEntries.push({
268+
dir: dirPath,
269+
name: fileName,
270+
fileSystemType: entry.fileSystemType,
271+
fileSystem: entry.fileSystem
272+
});
248273
});
249-
lconfig.extensions.getExtCommand('copyEntriesCommand').command(fromEntries, toEntry);
274+
if(shiftKey) {
275+
lconfig.extensions.getExtCommand('moveEntriesCommand').command(fromEntries, toEntry);
276+
} else {
277+
lconfig.extensions.getExtCommand('copyEntriesCommand').command(fromEntries, toEntry);
278+
}
250279
break;
251280
default:
252281
break;

src/components/FileManager.svelte

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,9 @@
658658
extensions.addExtCommand('changeMode', 'Change to mode given.', changeMode);
659659
extensions.addExtCommand('switchView', 'Switch the active program view.', switchView);
660660
extensions.addExtCommand('copyEntriesCommand', 'Copy the list of entries to new location.', copyEntriesCommand);
661+
extensions.addExtCommand('moveEntriesCommand', 'Move the list of entries to the new location.', moveEntriesCommand);
662+
extensions.addExtCommand('deleteEntriesCommand', 'Delete the list of entries.', deleteEntriesCommand);
663+
extensions.addExtCommand('editEntryCommand', 'Edit the given entry.', editEntryCommand);
661664
}
662665
663666
function installDefaultCommands() {
@@ -1194,14 +1197,16 @@
11941197
11951198
function deleteEntries() {
11961199
var entries = getSelectedFiles();
1197-
var sel = true;
11981200
if(entries.length === 0) {
11991201
//
12001202
// Get the entry at the current cursor
12011203
//
12021204
entries.push(localCurrentCursor.entry);
1203-
sel = false;
12041205
}
1206+
deleteEntriesCommand(entries);
1207+
}
1208+
1209+
function deleteEntriesCommand(entries) {
12051210
msgBoxConfig = {
12061211
title: "Deleting Entries",
12071212
noShowButton: true
@@ -1331,7 +1336,6 @@
13311336
}
13321337
13331338
async function swapPanels() {
1334-
var cfile = localCurrentCursor.entry.name;
13351339
var npane = localCurrentCursor.pane === 'left' ? 'right' : 'left';
13361340
tmp = localCurrentLeftFile;
13371341
currentLeftFile.set(localCurrentRightFile);
@@ -1347,11 +1351,15 @@
13471351
}
13481352
13491353
function editEntry() {
1354+
editEntryCommand(localCurrentCursor.entry);
1355+
}
1356+
1357+
function editEntryCommand(entry) {
13501358
if(localFS.fileExists(userEditor)) {
13511359
//
13521360
// There is an editor defined by the user. Use it.
13531361
//
1354-
var file = localFS.appendPath(localCurrentCursor.entry.dir, localCurrentCursor.entry.name);
1362+
var file = localFS.appendPath(entry.dir, entry.name);
13551363
var editor = localFS.readFile(userEditor).toString().trim();
13561364
if(editor.endsWith('.app')) {
13571365
localFS.openFileWithProgram(editor, file);
@@ -1375,7 +1383,7 @@
13751383
//
13761384
// Open with the system default editor.
13771385
//
1378-
openFile(localCurrentCursor.entry);
1386+
openFile(entry);
13791387
}
13801388
}
13811389
@@ -1407,15 +1415,17 @@
14071415
14081416
function moveEntries() {
14091417
var entries = getSelectedFiles();
1410-
var sel = true;
14111418
if(entries.length === 0) {
14121419
//
14131420
// Get the entry at the current cursor
14141421
//
14151422
entries.push(localCurrentCursor.entry);
1416-
sel = false;
14171423
}
14181424
var otherPane = localCurrentCursor.pane === 'left' ? localCurrentRightFile.entry : localCurrentLeftFile.entry;
1425+
moveEntriesCommand(entries, otherPane);
1426+
}
1427+
1428+
function moveEntriesCommand(entries, otherPane) {
14191429
msgBoxConfig = {
14201430
title: "Moving Entries",
14211431
noShowButton: true

src/components/Pane.svelte

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,16 @@
7878
}
7979
8080
function dropFiles(e,type) {
81+
var shiftKey = e.shiftKey;
8182
switch(type) {
83+
case 'over':
84+
if(e.shiftKey) {
85+
e.dataTransfer.dropEffect = 'move';
86+
} else {
87+
e.dataTransfer.dropEffect = 'copy';
88+
}
89+
break;
8290
case 'drop':
83-
//
84-
// Get the drop information.
85-
//
86-
const dataTrans = e.dataTransfer.getData('text/plain');
87-
const lconfig = get(config);
88-
8991
//
9092
// Get the local information for dropping into.
9193
//
@@ -115,26 +117,34 @@
115117
//
116118
// Process the information from the drop.
117119
//
120+
const dataTransArray = e.dataTransfer.getData('text/plain').split('\n');
121+
const lconfig = get(config);
118122
var fromEntries = [];
119-
const parts = dataTrans.split('|');
120-
if(parts[1] === '1') {
121-
dirPath = parts[0];
122-
var fdir = utilities.splitFilePath(dirPath);
123-
const nwDir = utilities.appendPath(toEntry.dir, fdir.name);
124-
utilities.makeDir(nwDir);
125-
toEntry.dir = nwDir;
123+
dataTransArray.forEach(dataTrans => {
124+
const parts = dataTrans.split('|');
125+
if(parts[1] === '1') {
126+
dirPath = parts[0];
127+
var fdir = utilities.splitFilePath(dirPath);
128+
const nwDir = utilities.appendPath(toEntry.dir, fdir.name);
129+
utilities.makeDir(nwDir);
130+
toEntry.dir = nwDir;
131+
} else {
132+
const result = utilities.splitFilePath(parts[0]);
133+
dirPath = result.dir;
134+
fileName = result.name;
135+
}
136+
fromEntries.push({
137+
dir: dirPath,
138+
name: fileName,
139+
fileSystemType: utilities.type,
140+
fileSystem: utilities
141+
});
142+
});
143+
if(shiftKey) {
144+
lconfig.extensions.getExtCommand('moveEntriesCommand').command(fromEntries, toEntry);
126145
} else {
127-
const result = utilities.splitFilePath(parts[0]);
128-
dirPath = result.dir;
129-
fileName = result.name;
146+
lconfig.extensions.getExtCommand('copyEntriesCommand').command(fromEntries, toEntry);
130147
}
131-
fromEntries.push({
132-
dir: dirPath,
133-
name: fileName,
134-
fileSystemType: toEntry.fileSystemType,
135-
fileSystem: toEntry.fileSystem
136-
});
137-
lconfig.extensions.getExtCommand('copyEntriesCommand').command(fromEntries, toEntry);
138148
break;
139149
default:
140150
break;
@@ -164,8 +174,6 @@
164174
nEntry.dir = curPane.path;
165175
nEntry.name = '';
166176
}
167-
console.log(nEntry);
168-
169177
currentCursor.set({
170178
pane: pane,
171179
entry: nEntry

0 commit comments

Comments
 (0)