From 66cf03405c5826827d82cdacdf83e5e6b0a6d582 Mon Sep 17 00:00:00 2001 From: Anders Evenrud Date: Mon, 17 Aug 2020 19:42:23 +0200 Subject: [PATCH] Added client side directory VFS watch (#57) --- __tests__/utils/vfs.js | 2 ++ src/config.js | 2 +- src/filesystem.js | 13 ++++++++++--- src/utils/vfs.js | 43 +++++++++++++++++++++++++++++++++++++++++- 4 files changed, 55 insertions(+), 5 deletions(-) diff --git a/__tests__/utils/vfs.js b/__tests__/utils/vfs.js index 05d566b0..b964afd1 100644 --- a/__tests__/utils/vfs.js +++ b/__tests__/utils/vfs.js @@ -232,6 +232,8 @@ describe('utils.vfs#basename', () => { describe('utils.vfs#pathname', () => { test('Should resolve', () => { expect(vfs.pathname('home:/foo/bar')).toBe('home:/foo'); + expect(vfs.pathname('home:/foo')).toBe('home:/'); + expect(vfs.pathname('home:/')).toBe('home:/'); }); }); diff --git a/src/config.js b/src/config.js index 50bc2946..3c0d6164 100644 --- a/src/config.js +++ b/src/config.js @@ -236,7 +236,7 @@ export const defaultConfiguration = { }, vfs: { - watch: false, + watch: true, defaultPath: 'home:/', defaultAdapter: 'system', adapters: {}, diff --git a/src/filesystem.js b/src/filesystem.js index 605d75d6..8137bb77 100644 --- a/src/filesystem.js +++ b/src/filesystem.js @@ -30,7 +30,7 @@ import * as VFS from './vfs'; import {EventEmitter} from '@osjs/event-emitter'; -import {parseMontpointPrefix, filterMountByGroups} from './utils/vfs'; +import {parseMontpointPrefix, filterMountByGroups, createWatchEvents} from './utils/vfs'; import defaultAdapter from './adapters/vfs/null'; import systemAdapter from './adapters/vfs/system'; import appsAdapter from './adapters/vfs/apps'; @@ -233,7 +233,14 @@ export default class Filesystem extends EventEmitter { _request(method, ...args) { const ev = `osjs/vfs:${method}`; - const done = () => this.core.emit(`${ev}:done`, ...args); + const done = (error) => { + this.core.emit(`${ev}:done`, ...args); + + if (!error && this.core.config('vfs.watch')) { + const eva = createWatchEvents(method, args); + eva.forEach(([e, a]) => this.core.emit(e, a)); + } + }; this.core.emit(ev, ...args); @@ -243,7 +250,7 @@ export default class Filesystem extends EventEmitter { return result; }) .catch(error => { - done(); + done(error); throw error; }); } diff --git a/src/utils/vfs.js b/src/utils/vfs.js index a20c76d1..cca05cf4 100644 --- a/src/utils/vfs.js +++ b/src/utils/vfs.js @@ -310,7 +310,12 @@ export const basename = path => path.split('/').reverse()[0]; */ export const pathname = path => { const split = path.split('/'); - split.splice(split.length - 1, 1); + if (split.length === 2) { + split[1] = ''; + } else { + split.splice(split.length - 1, 1); + } + return split.join('/'); }; @@ -341,3 +346,39 @@ export const filterMountByGroups = userGroups => (mountGroups, strict = true) => ? mountGroups[strict ? 'every' : 'some'](g => userGroups.indexOf(g) !== -1) : true; + +/** + * Creates a list of VFS events to simulate server-side + * file watching + * @return {object[]} + */ +export const createWatchEvents = (method, args) => { + const events = []; + const options = args[args.length - 1] || {}; + + const movement = ['move', 'rename', 'copy'].indexOf(method) !== -1; + const invalid = ['readdir', 'download', 'url', 'exists', 'readfile', 'search', 'stat'].indexOf(method) !== -1; + const path = i => typeof i === 'string' ? i : i.path; + + if (!invalid) { + const obj = { + method, + source: path(args[0]), + pid: options.pid + }; + + events.push(['osjs/vfs:directoryChanged', { + ...obj, + path: pathname(path(args[0])), + }]); + + if (movement) { + events.push(['osjs/vfs:directoryChanged', { + ...obj, + path: pathname(path(args[1])) + }]); + } + } + + return events; +};