Skip to content

Commit 06eff06

Browse files
committed
feat: copy api and file browser ui tweaks
1 parent 604714d commit 06eff06

File tree

5 files changed

+590
-618
lines changed

5 files changed

+590
-618
lines changed

src/fileSystem/sftp.js

Lines changed: 59 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -226,35 +226,77 @@ class SftpClient {
226226
});
227227
}
228228

229-
copyTo(dest) {
229+
async copyTo(dest) {
230230
const src = this.#path;
231231
return new Promise((resolve, reject) => {
232232
sftp.isConnected((connectionID) => {
233233
(async () => {
234-
if (this.#notConnected(connectionID)) {
235-
try {
234+
try {
235+
if (this.#notConnected(connectionID)) {
236236
await this.connect();
237-
} catch (error) {
238-
reject(error);
239-
return;
240237
}
238+
239+
const srcStat = await this.stat();
240+
241+
if (srcStat.isDirectory) {
242+
await this.#copyDirectory(src, dest);
243+
} else {
244+
await this.#copyFile(src, dest);
245+
}
246+
247+
const finalPath = Path.join(dest, Path.basename(src));
248+
resolve(Url.join(this.#base, finalPath));
249+
} catch (error) {
250+
reject(error);
241251
}
242-
console.log(this.#safeName(src), this.#safeName(dest));
243-
sftp.copy(
244-
this.#safeName(src),
245-
this.#safeName(dest),
246-
async (_res) => {
247-
resolve(Url.join(this.#base, dest));
248-
},
249-
(err) => {
250-
reject(err);
251-
},
252-
);
253252
})();
254253
}, reject);
255254
});
256255
}
257256

257+
async #copyFile(src, dest) {
258+
const destPath = Path.join(dest, Path.basename(src));
259+
const tempFile = this.#getLocalname(src);
260+
261+
// Download source file
262+
await new Promise((resolve, reject) => {
263+
sftp.getFile(this.#safeName(src), tempFile, resolve, reject);
264+
});
265+
266+
// Upload
267+
await new Promise((resolve, reject) => {
268+
sftp.putFile(this.#safeName(destPath), tempFile, resolve, reject);
269+
});
270+
271+
// Clean up temp file
272+
try {
273+
await internalFs.delete(tempFile);
274+
} catch (error) {
275+
console.warn("Failed to cleanup temp file:", error);
276+
}
277+
}
278+
279+
async #copyDirectory(src, dest) {
280+
// Create destination directory
281+
const destDir = Path.join(dest, Path.basename(src));
282+
await new Promise((resolve, reject) => {
283+
sftp.mkdir(this.#safeName(destDir), resolve, reject);
284+
});
285+
286+
// Get contents of source directory
287+
const contents = await this.lsDir(src);
288+
289+
// Copy all items
290+
for (const item of contents) {
291+
const itemSrc = Path.join(src, item.name);
292+
if (item.isDirectory) {
293+
await this.#copyDirectory(itemSrc, destDir);
294+
} else {
295+
await this.#copyFile(itemSrc, destDir);
296+
}
297+
}
298+
}
299+
258300
moveTo(dest) {
259301
return this.rename(dest, true);
260302
}
@@ -569,11 +611,9 @@ Sftp.test = (url) => /^sftp:/.test(url);
569611
function createFs(sftp) {
570612
return {
571613
lsDir() {
572-
console.log("lsdir");
573614
return sftp.lsDir();
574615
},
575616
async readFile(encoding) {
576-
console.log("readfile");
577617
const { data } = await sftp.readFile();
578618

579619
if (encoding) {
@@ -583,45 +623,36 @@ function createFs(sftp) {
583623
return data;
584624
},
585625
async writeFile(content, encoding) {
586-
console.log("writeFile");
587626
if (typeof content === "string" && encoding) {
588627
content = await encode(content, encoding);
589628
}
590629

591630
return sftp.writeFile(content, null);
592631
},
593632
createFile(name, data) {
594-
console.log("createfile");
595633
return sftp.createFile(name, data);
596634
},
597635
createDirectory(name) {
598-
console.log("dir");
599636
return sftp.createDir(name);
600637
},
601638
delete() {
602-
console.log("delete");
603639
return sftp.delete();
604640
},
605641
copyTo(dest) {
606-
console.log("copy");
607642
dest = Url.pathname(dest);
608643
return sftp.copyTo(dest);
609644
},
610645
moveTo(dest) {
611-
console.log("move");
612646
dest = Url.pathname(dest);
613647
return sftp.moveTo(dest);
614648
},
615649
renameTo(newname) {
616-
console.log("rename");
617650
return sftp.rename(newname);
618651
},
619652
exists() {
620-
console.log("exists");
621653
return sftp.exists();
622654
},
623655
stat() {
624-
console.log("stat");
625656
return sftp.stat();
626657
},
627658
get localName() {

src/pages/fileBrowser/fileBrowser.scss

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,25 @@
5353
}
5454
&.symlink {
5555
.icon {
56-
color: rgb(255, 165, 0);
56+
position: relative;
57+
color: var(--link-text-color);
58+
&::after {
59+
content: "🔗";
60+
position: absolute;
61+
bottom: 13px;
62+
right: 10px;
63+
font-size: 0.4em;
64+
color: inherit;
65+
}
5766
}
5867

59-
.text::after {
60-
content: " (symlink)";
61-
font-size: 0.8em;
62-
color: rgb(255, 165, 0);
68+
.text {
69+
color: var(--link-text-color);
70+
&::after {
71+
content: " (symlink)";
72+
font-size: 0.8em;
73+
color: color-mix(in srgb, var(--primary-text-color) 60%, transparent);
74+
}
6375
}
6476
}
6577
}

src/plugins/sftp/src/com/foxdebug/sftp/Sftp.java

Lines changed: 0 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -589,73 +589,6 @@ public void run() {
589589
);
590590
}
591591

592-
public void copy(JSONArray args, CallbackContext callback) {
593-
cordova
594-
.getThreadPool()
595-
.execute(
596-
new Runnable() {
597-
public void run() {
598-
try {
599-
String source = args.optString(0);
600-
String destination = args.optString(1);
601-
602-
if (ssh != null && sftp != null) {
603-
try {
604-
SftpFileAttributes sourceAttrs = sftp.stat(source);
605-
606-
if (sourceAttrs.isFile()) {
607-
// file copy
608-
try (java.io.InputStream in = sftp.getInputStream(source)) {
609-
sftp.put(in, destination);
610-
}
611-
} else if (sourceAttrs.isDirectory()) {
612-
// directory copy
613-
sftp.mkdir(destination);
614-
615-
for (SftpFile file : sftp.ls(source)) {
616-
String filename = file.getFilename();
617-
if (!filename.equals(".") && !filename.equals("..")) {
618-
String sourcePath = source + "/" + filename;
619-
String destPath = destination + "/" + filename;
620-
621-
if (file.getAttributes().isDirectory()) {
622-
// Recursively copy subdirectories
623-
JSONArray subDirArgs = new JSONArray();
624-
subDirArgs.put(sourcePath);
625-
subDirArgs.put(destPath);
626-
copy(subDirArgs, callback);
627-
} else {
628-
// Copy files within directory
629-
try (
630-
java.io.InputStream in = sftp.getInputStream(
631-
sourcePath
632-
)
633-
) {
634-
sftp.put(in, destPath);
635-
}
636-
}
637-
}
638-
}
639-
}
640-
641-
callback.success();
642-
return;
643-
} catch (SftpStatusException e) {
644-
callback.error("Source does not exist: " + errMessage(e));
645-
return;
646-
}
647-
}
648-
callback.error("Not connected");
649-
} catch (
650-
SshException | IOException | TransferCancelledException e
651-
) {
652-
callback.error(errMessage(e));
653-
}
654-
}
655-
}
656-
);
657-
}
658-
659592
public void pwd(JSONArray args, CallbackContext callback) {
660593
cordova
661594
.getThreadPool()

src/plugins/sftp/www/sftp.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,6 @@ module.exports = {
4242
rename: function (oldpath, newpath, onSuccess, onFail) {
4343
cordova.exec(onSuccess, onFail, 'Sftp', 'rename', [oldpath, newpath]);
4444
},
45-
copy: function (source, destination, onSuccess, onFail) {
46-
cordova.exec(onSuccess, onFail, 'Sftp', 'copy', [source, destination]);
47-
},
4845
pwd: function (onSuccess, onFail) {
4946
cordova.exec(onSuccess, onFail, 'Sftp', 'pwd', []);
5047
},

0 commit comments

Comments
 (0)