filefive 1.3.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,10 +8,18 @@ FileFive is a free open-source SFTP/FTP client and file manager with intuitive a
8
8
 
9
9
  It is installed as a Node.js package and uses the web browser as GUI.
10
10
 
11
- FileFive has a unique set of features and may be an alternative to FileZilla, Cyberduck, Transmit, ForkLift and Commander One.
11
+ FileFive has a unique set of features and may be an alternative to FileZilla, Cyberduck, Transmit, and ForkLift.
12
12
 
13
13
  <p align="center">
14
- <img src="https://github.com/miroshnikov/filefive/blob/main/screenshot.png" alt="FileFive" />
14
+ <img src="https://github.com/miroshnikov/filefive/blob/main/docs/screenshots/screenshot-1.png" alt="FileFive" />
15
+ </p>
16
+ <p align="center">
17
+ <details>
18
+ <summary>More screenshots</summary>
19
+ <img src="https://github.com/miroshnikov/filefive/blob/main/docs/screenshots/screenshot-2.png" alt="FileFive"/>
20
+ <img src="https://github.com/miroshnikov/filefive/blob/main/docs/screenshots/screenshot-3.png" alt="FileFive"/>
21
+ <img src="https://github.com/miroshnikov/filefive/blob/main/docs/screenshots/screenshot-4.png" alt="FileFive"/>
22
+ </details>
15
23
  </p>
16
24
 
17
25
  ## Installation
@@ -40,8 +48,10 @@ Options:
40
48
  - Minimalistic and intuitive UI, mimicing the look and feel of VSCode Explorer view
41
49
  - Search/filter files using wildcards and JavaScript Regular Expressions
42
50
  - Synchronized browsing
51
+ - Copy files keeping relative paths, allows synchronization files in nested folders in one click
43
52
  - Remote file editing
44
- - Connections/servers are plain files stored on your filesystem in the `~/.f5/connections` folder
53
+ - Files' Git statuses (uses your machine's Git installation)
54
+ - Connections/servers are plain files stored on your filesystem, no need to export/import
45
55
  - Easy to backup connections and settings in `~/.f5` folder, e.g. by putting them into a Git repo
46
56
  - Drag & drop, copy & paste files support
47
57
  - Use browser tabs to browse more than one server or transfer files simultaneously
package/dist/App.js CHANGED
@@ -14,9 +14,9 @@ const RemoteWatcher_1 = __importDefault(require("./RemoteWatcher"));
14
14
  const Queue_1 = require("./queues/Queue");
15
15
  const Password_1 = __importDefault(require("./Password"));
16
16
  const commands_1 = require("./commands");
17
- const transform_1 = __importDefault(require("./transform"));
18
17
  const Local_1 = require("./Local");
19
18
  const URI_1 = require("./utils/URI");
19
+ const Local_2 = __importDefault(require("./transformers/Local"));
20
20
  class App {
21
21
  static async bootstrap(handle, emitter, opener) {
22
22
  const dataPath = (0, node_path_1.join)((0, node_os_1.homedir)(), '.f5');
@@ -39,7 +39,7 @@ class App {
39
39
  watch: ({ dir }) => commands_1.commands.watch(dir, this.localWatcher, this.remoteWatcher, this.fileWatcher),
40
40
  unwatch: ({ dir }) => commands_1.commands.unwatch(dir, this.localWatcher, this.remoteWatcher, this.fileWatcher),
41
41
  refresh: ({ dir }) => this.remoteWatcher.refresh(dir),
42
- copy: ({ src, dest, move, filter, sid }) => commands_1.commands.copy(src, dest, move, filter, sid),
42
+ copy: ({ src, dest, move, filter, root, sid }) => commands_1.commands.copy(src, dest, move, filter, root, sid),
43
43
  duplicate: ({ src, filter }) => commands_1.commands.duplicate(src, filter),
44
44
  remove: ({ files }) => commands_1.commands.remove(files, connPath),
45
45
  clear: ({ file }) => commands_1.commands.clear(file),
@@ -57,8 +57,11 @@ class App {
57
57
  this.onError = (error) => emitError(error);
58
58
  const emitDir = emitter('dir');
59
59
  const sendDirContent = (uri, files) => emitDir({ uri, files });
60
- this.localWatcher = new LocalWatcher_1.default((path, files) => sendDirContent((0, URI_1.createURI)(types_1.LocalFileSystemID, path), files.map(f => ({ ...f, URI: (0, URI_1.createURI)(types_1.LocalFileSystemID, f.path) }))), path => this.onError({ type: types_1.FailureType.MissingDir, uri: (0, URI_1.createURI)(types_1.LocalFileSystemID, path) }));
61
- this.remoteWatcher = new RemoteWatcher_1.default(sendDirContent, uri => this.onError({ type: types_1.FailureType.MissingDir, uri }), transform_1.default);
60
+ this.localWatcher = new LocalWatcher_1.default(async (path, files) => {
61
+ const transformer = new Local_2.default();
62
+ sendDirContent((0, URI_1.createURI)(types_1.LocalFileSystemID, path), await transformer.transform(path, files.map(f => ({ ...f, URI: (0, URI_1.createURI)(types_1.LocalFileSystemID, f.path) }))));
63
+ }, path => this.onError({ type: types_1.FailureType.MissingDir, uri: (0, URI_1.createURI)(types_1.LocalFileSystemID, path) }));
64
+ this.remoteWatcher = new RemoteWatcher_1.default(sendDirContent, uri => this.onError({ type: types_1.FailureType.MissingDir, uri }));
62
65
  const emitFile = emitter('file');
63
66
  const sendFileStat = (path, stat) => emitFile({ path, stat });
64
67
  this.fileWatcher = new FileWatcher_1.default(sendFileStat);
@@ -7,10 +7,9 @@ const node_path_1 = require("node:path");
7
7
  const Local_1 = require("./Local");
8
8
  const ReferenceCountMap_1 = __importDefault(require("./utils/ReferenceCountMap"));
9
9
  class default_1 {
10
- constructor(listener, onMissing, transform = (files) => files) {
10
+ constructor(listener, onMissing) {
11
11
  this.listener = listener;
12
12
  this.onMissing = onMissing;
13
- this.transform = transform;
14
13
  this.watched = new ReferenceCountMap_1.default;
15
14
  }
16
15
  watch(dir) {
@@ -24,14 +23,14 @@ class default_1 {
24
23
  }
25
24
  }
26
25
  try {
27
- this.listener(dir, this.transform((0, Local_1.list)(dir)), event, target);
26
+ this.listener(dir, (0, Local_1.list)(dir), event, target);
28
27
  }
29
28
  catch (e) {
30
29
  this.watched.del(dir);
31
30
  this.onMissing(dir);
32
31
  }
33
32
  }));
34
- const files = this.transform((0, Local_1.list)(dir));
33
+ const files = (0, Local_1.list)(dir);
35
34
  this.listener(dir, files);
36
35
  return files;
37
36
  }
@@ -20,7 +20,7 @@ async function open(file, onLoad) {
20
20
  try {
21
21
  const tmpDir = await (0, promises_1.mkdtemp)((0, node_path_1.join)((0, node_os_1.tmpdir)(), 'f5-'));
22
22
  const tmpName = (0, node_path_1.join)(tmpDir, (0, node_path_1.basename)(path));
23
- return commands_1.commands.copy([file], (0, URI_1.createURI)(types_1.LocalFileSystemID, tmpDir), false, null, null, () => {
23
+ return commands_1.commands.copy([file], (0, URI_1.createURI)(types_1.LocalFileSystemID, tmpDir), false, null, null, null, () => {
24
24
  files.set(tmpName, { file, deletion: resetDeletion(tmpName, null), sending: false, changed: false });
25
25
  watcher.watch(tmpName);
26
26
  onLoad(tmpName);
@@ -8,10 +8,9 @@ const ReferenceCountMap_1 = __importDefault(require("./utils/ReferenceCountMap")
8
8
  const Connection_1 = __importDefault(require("./Connection"));
9
9
  const URI_1 = require("./utils/URI");
10
10
  class RemoteWatcher {
11
- constructor(listener, onMissing, transform = (files) => files) {
11
+ constructor(listener, onMissing) {
12
12
  this.listener = listener;
13
13
  this.onMissing = onMissing;
14
- this.transform = transform;
15
14
  this.watched = new ReferenceCountMap_1.default;
16
15
  }
17
16
  watch(uri) {
@@ -34,8 +33,8 @@ class RemoteWatcher {
34
33
  list(uri) {
35
34
  const { id, path } = (0, URI_1.parseURI)(uri);
36
35
  Connection_1.default.list(id, path)
37
- .then(files => this.listener(uri, this.transform(files)))
38
- .catch(e => {
36
+ .then(files => this.listener(uri, files))
37
+ .catch(() => {
39
38
  this.watched.del(uri);
40
39
  this.onMissing(uri);
41
40
  });
@@ -14,7 +14,7 @@ const Upload_1 = __importDefault(require("../queues/Upload"));
14
14
  const uniqid_1 = __importDefault(require("../utils/uniqid"));
15
15
  const App_1 = __importDefault(require("../App"));
16
16
  const ramda_1 = require("ramda");
17
- function default_1(src, dest, move, filter, sid, onComplete = () => { }) {
17
+ function default_1(src, dest, move, filter, root, sid, onComplete = () => { }) {
18
18
  if (!src.length) {
19
19
  return;
20
20
  }
@@ -43,7 +43,7 @@ function default_1(src, dest, move, filter, sid, onComplete = () => { }) {
43
43
  if (fromId == toId) {
44
44
  queueType = move ? types_1.QueueType.Move : types_1.QueueType.Copy;
45
45
  connection = fromId;
46
- queue = new Copy_1.default(connection, from, toPath, filter, state => App_1.default.onQueueUpdate(id, { type: types_1.QueueEventType.Update, state }), onConflict.bind(queue), error => {
46
+ queue = new Copy_1.default(connection, from, toPath, filter, root, state => App_1.default.onQueueUpdate(id, { type: types_1.QueueEventType.Update, state }), onConflict.bind(queue), error => {
47
47
  App_1.default.onError({
48
48
  type: types_1.FailureType.RemoteError,
49
49
  id: fromId,
@@ -55,11 +55,13 @@ function default_1(src, dest, move, filter, sid, onComplete = () => { }) {
55
55
  queueType = (0, URI_1.isLocal)(dest) ? types_1.QueueType.Download : types_1.QueueType.Upload;
56
56
  connection = queueType == types_1.QueueType.Download ? fromId : toId;
57
57
  queue = queueType == types_1.QueueType.Download ?
58
- new Download_1.default(connection, from, toPath, filter, state => App_1.default.onQueueUpdate(id, { type: types_1.QueueEventType.Update, state }), onConflict.bind(queue), error => App_1.default.onError(error), onFinish) :
59
- new Upload_1.default(connection, from, toPath, filter, state => App_1.default.onQueueUpdate(id, { type: types_1.QueueEventType.Update, state }), onConflict.bind(queue), error => App_1.default.onError(error), onFinish, App_1.default.remoteWatcher);
58
+ new Download_1.default(connection, from, toPath, filter, root, state => App_1.default.onQueueUpdate(id, { type: types_1.QueueEventType.Update, state }), onConflict.bind(queue), error => App_1.default.onError(error), onFinish) :
59
+ new Upload_1.default(connection, from, toPath, filter, root, state => App_1.default.onQueueUpdate(id, { type: types_1.QueueEventType.Update, state }), onConflict.bind(queue), error => App_1.default.onError(error), onFinish, App_1.default.remoteWatcher);
60
60
  }
61
61
  Queue_1.queues.set(id, queue);
62
- queue.create();
63
- setTimeout(() => App_1.default.onQueueUpdate(id, { type: types_1.QueueEventType.Create, queueType, connection }), 100);
62
+ setTimeout(() => {
63
+ App_1.default.onQueueUpdate(id, { type: types_1.QueueEventType.Create, queueType, connection });
64
+ queue.create();
65
+ }, 100);
64
66
  return id;
65
67
  }
package/dist/index.js CHANGED
@@ -33,7 +33,7 @@ app.use(express_1.default.json());
33
33
  app.use(express_1.default.static((0, path_1.resolve)(__dirname, 'public')));
34
34
  app.use(express_1.default.static((0, path_1.resolve)(__dirname, '../dist/public')));
35
35
  const server = app.listen(port, async () => {
36
- console.log(`Listening on http://localhost:${port}`);
36
+ console.log(`FileFive is up on http://localhost:${port}`);
37
37
  if (process.env.NODE_ENV !== 'development') {
38
38
  (await open).default(`http://localhost:${port}`);
39
39
  }
@@ -60,7 +60,7 @@ app.post('/api/upload', upload.array('files'), async function (req, res) {
60
60
  await (0, promises_1.rename)(path, fnm);
61
61
  src.push(fnm);
62
62
  }
63
- commands_1.commands.copy(src.map(path => (0, URI_1.createURI)(types_1.LocalFileSystemID, path)), req.body['to'], true, null, null, () => src.forEach(path => (0, promises_1.rm)(path, { force: true })));
63
+ commands_1.commands.copy(src.map(path => (0, URI_1.createURI)(types_1.LocalFileSystemID, path)), req.body['to'], true, null, null, null, () => src.forEach(path => (0, promises_1.rm)(path, { force: true })));
64
64
  }
65
65
  res.json(true);
66
66
  });