]> source.dussan.org Git - nextcloud-server.git/commitdiff
Propagate file action changes to the file lists
authorVincent Petry <pvince81@owncloud.com>
Wed, 9 Jul 2014 10:26:33 +0000 (12:26 +0200)
committerVincent Petry <pvince81@owncloud.com>
Wed, 9 Jul 2014 10:26:33 +0000 (12:26 +0200)
Whenever an app needs to register an event late, it does that on the
original file actions object.

Since the file actions that the file list work on is a merged list, not
the original one, the registration event needs to be propagated there as
well.

apps/files/js/app.js
apps/files/js/fileactions.js
apps/files/js/filelist.js
apps/files/tests/js/appSpec.js
apps/files/tests/js/fileactionsSpec.js
apps/files_sharing/js/app.js
apps/files_sharing/tests/js/appSpec.js

index 45b6b6a0e1666b7e1ad5df4a640032e183f25dd2..6f5206fcdb60fc2c463e944a1c104a032d75d2be 100644 (file)
                        // regular actions
                        fileActions.merge(OCA.Files.fileActions);
 
-                       // in case apps would decide to register file actions later,
-                       // replace the global object with this one
-                       OCA.Files.fileActions = fileActions;
+                       this._onActionsUpdated = _.bind(this._onActionsUpdated, this);
+                       OCA.Files.fileActions.on('setDefault.app-files', this._onActionsUpdated);
+                       OCA.Files.fileActions.on('registerAction.app-files', this._onActionsUpdated);
+                       window.FileActions.on('setDefault.app-files', this._onActionsUpdated);
+                       window.FileActions.on('registerAction.app-files', this._onActionsUpdated);
 
                        this.files = OCA.Files.Files;
 
                        this._onPopState(OC.Util.History.parseUrlQuery());
                },
 
+               /**
+                * Destroy the app
+                */
+               destroy: function() {
+                       this.navigation = null;
+                       this.fileList.destroy();
+                       this.fileList = null;
+                       this.files = null;
+                       OCA.Files.fileActions.off('setDefault.app-files', this._onActionsUpdated);
+                       OCA.Files.fileActions.off('registerAction.app-files', this._onActionsUpdated);
+                       window.FileActions.off('setDefault.app-files', this._onActionsUpdated);
+                       window.FileActions.off('registerAction.app-files', this._onActionsUpdated);
+               },
+
+               _onActionsUpdated: function(ev, newAction) {
+                       // forward new action to the file list
+                       if (ev.action) {
+                               this.fileList.fileActions.registerAction(ev.action);
+                       } else if (ev.defaultAction) {
+                               this.fileList.fileActions.setDefault(
+                                       ev.defaultAction.mime,
+                                       ev.defaultAction.name
+                               );
+                       }
+               },
+
                /**
                 * Returns the container of the currently visible app.
                 *
index cbfd047e98f9c8733aa3e378651c94e10fef53ed..fd038765ea51c6c5396f87632365bc5cc042adc7 100644 (file)
                icons: {},
                currentFile: null,
 
+               /**
+                * Dummy jquery element, for events
+                */
+               $el: null,
+
                /**
                 * List of handlers to be notified whenever a register() or
                 * setDefault() was called.
                 */
-               _updateListeners: [],
+               _updateListeners: {},
 
                initialize: function() {
                        this.clear();
+                       // abusing jquery for events until we get a real event lib
+                       this.$el = $('<div class="dummy-fileactions hidden"></div>');
+                       $('body').append(this.$el);
                },
 
                /**
-                * Adds an update listener to be notified whenever register()
-                * or setDefault() has been called.
+                * Adds an event handler
                 *
+                * @param {String} eventName event name
                 * @param Function callback
                 */
-               addUpdateListener: function(callback) {
-                       if (!_.isFunction(callback)) {
-                               throw 'Argument passed to FileActions.addUpdateListener must be a function';
-                       }
-                       this._updateListeners.push(callback);
+               on: function(eventName, callback) {
+                       this.$el.on(eventName, callback);
                },
 
                /**
-                * Removes an update listener.
+                * Removes an event handler
                 *
+                * @param {String} eventName event name
                 * @param Function callback
                 */
-               removeUpdateListener: function(callback) {
-                       if (!_.isFunction(callback)) {
-                               throw 'Argument passed to FileActions.removeUpdateListener must be a function';
-                       }
-                       this._updateListeners = _.without(this._updateListeners, callback);
+               off: function(eventName, callback) {
+                       this.$el.off(eventName, callback);
                },
 
                /**
-                * Notifies the registered update listeners
+                * Notifies the event handlers
+                *
+                * @param {String} eventName event name
+                * @param {Object} data data
                 */
-               _notifyUpdateListeners: function() {
-                       for (var i = 0; i < this._updateListeners.length; i++) {
-                               this._updateListeners[i](this);
-                       }
+               _notifyUpdateListeners: function(eventName, data) {
+                       this.$el.trigger(new $.Event(eventName, data));
                },
 
                /**
                        this.defaults = _.extend(this.defaults, fileActions.defaults);
                        this.icons = _.extend(this.icons, fileActions.icons);
                },
-               register: function (mime, name, permissions, icon, action, displayName) {
+               /**
+                * @deprecated use #registerAction() instead
+                */
+               register: function(mime, name, permissions, icon, action, displayName) {
+                       return this.registerAction({
+                               name: name,
+                               mime: mime,
+                               permissions: permissions,
+                               icon: icon,
+                               actionHandler: action,
+                               displayName: displayName
+                       });
+               },
+               /**
+                * Register action
+                *
+                * @param {Object} action action object
+                * @param {String} action.name identifier of the action
+                * @param {String} action.displayName display name of the action, defaults
+                * to the name given in action.name
+                * @param {String} action.mime mime type
+                * @param {int} action.permissions permissions
+                * @param {(Function|String)} action.icon icon
+                * @param {Function} action.actionHandler function that performs the action
+                */
+               registerAction: function (action) {
+                       var mime = action.mime;
+                       var name = action.name;
                        if (!this.actions[mime]) {
                                this.actions[mime] = {};
                        }
                        this.actions[mime][name] = {
-                               action: action,
-                               permissions: permissions,
-                               displayName: displayName || t('files', name)
+                               action: action.actionHandler,
+                               permissions: action.permissions,
+                               displayName: action.displayName || t('files', name)
                        };
-                       this.icons[name] = icon;
-                       this._notifyUpdateListeners();
+                       this.icons[name] = action.icon;
+                       this._notifyUpdateListeners('registerAction', {action: action});
                },
                clear: function() {
                        this.actions = {};
                },
                setDefault: function (mime, name) {
                        this.defaults[mime] = name;
-                       this._notifyUpdateListeners();
+                       this._notifyUpdateListeners('setDefault', {defaultAction: {mime: mime, name: name}});
                },
                get: function (mime, type, permissions) {
                        var actions = this.getActions(mime, type, permissions);
index 3e311655c9100951c5c7692b365ca0a60a3bf6ef..96436d33a2c72cff513f4260c202cddf7a75af9b 100644 (file)
                 */
                destroy: function() {
                        // TODO: also unregister other event handlers
-                       this.fileActions.removeUpdateListener(this._onFileActionsUpdated);
+                       this.fileActions.off('registerAction', this._onFileActionsUpdated);
+                       this.fileActions.off('setDefault', this._onFileActionsUpdated);
                },
 
                _initFileActions: function(fileActions) {
                                this.fileActions.registerDefaultActions();
                        }
                        this._onFileActionsUpdated = _.debounce(_.bind(this._onFileActionsUpdated, this), 100);
-                       this.fileActions.addUpdateListener(this._onFileActionsUpdated);
+                       this.fileActions.on('registerAction', this._onFileActionsUpdated);
+                       this.fileActions.on('setDefault', this._onFileActionsUpdated);
                },
 
                /**
index 99a73d0b01df6f455a4a536d318e3dbc88cd9a50..77d36d59fa931f99c3fe2a969b0e5471f08249ad 100644 (file)
@@ -52,9 +52,7 @@ describe('OCA.Files.App tests', function() {
                App.initialize();
        });
        afterEach(function() {
-               App.navigation = null;
-               App.fileList = null;
-               App.files = null;
+               App.destroy();
 
                pushStateStub.restore();
                parseUrlQueryStub.restore();
index f087239de9dd69f0c1c41716e1e455db2d9cf94a..f5f18a45a75d15c7b9a6a0cf83ab918e34e8241c 100644 (file)
@@ -354,7 +354,7 @@ describe('OCA.Files.FileActions tests', function() {
                it('notifies update event handlers once after multiple changes', function() {
                        var actionStub = sinon.stub();
                        var handler = sinon.stub();
-                       FileActions.addUpdateListener(handler);
+                       FileActions.on('registerAction', handler);
                        FileActions.register(
                                        'all',
                                        'Test',
@@ -374,8 +374,8 @@ describe('OCA.Files.FileActions tests', function() {
                it('does not notifies update event handlers after unregistering', function() {
                        var actionStub = sinon.stub();
                        var handler = sinon.stub();
-                       FileActions.addUpdateListener(handler);
-                       FileActions.removeUpdateListener(handler);
+                       FileActions.on('registerAction', handler);
+                       FileActions.off('registerAction', handler);
                        FileActions.register(
                                        'all',
                                        'Test',
index 1fc13d00382bb45af2b0d69255485c114bf3adaa..1a3bfac5b97e99a42574b9680b882add4eb0b403 100644 (file)
@@ -92,6 +92,21 @@ OCA.Sharing.App = {
                }
        },
 
+       /**
+        * Destroy the app
+        */
+       destroy: function() {
+               OCA.Files.fileActions.off('setDefault.app-sharing', this._onActionsUpdated);
+               OCA.Files.fileActions.off('registerAction.app-sharing', this._onActionsUpdated);
+               this.removeSharingIn();
+               this.removeSharingOut();
+               this.removeSharingLinks();
+               this._inFileList = null;
+               this._outFileList = null;
+               this._linkFileList = null;
+               delete this._globalActionsInitialized;
+       },
+
        _createFileActions: function() {
                // inherit file actions from the files app
                var fileActions = new OCA.Files.FileActions();
@@ -100,6 +115,14 @@ OCA.Sharing.App = {
                fileActions.registerDefaultActions();
                fileActions.merge(OCA.Files.fileActions);
 
+               if (!this._globalActionsInitialized) {
+                       // in case actions are registered later
+                       this._onActionsUpdated = _.bind(this._onActionsUpdated, this);
+                       OCA.Files.fileActions.on('setDefault.app-sharing', this._onActionsUpdated);
+                       OCA.Files.fileActions.on('registerAction.app-sharing', this._onActionsUpdated);
+                       this._globalActionsInitialized = true;
+               }
+
                // when the user clicks on a folder, redirect to the corresponding
                // folder in the files app instead of opening it directly
                fileActions.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename, context) {
@@ -110,6 +133,23 @@ OCA.Sharing.App = {
                return fileActions;
        },
 
+       _onActionsUpdated: function(ev) {
+               _.each([this._inFileList, this._outFileList, this._linkFileList], function(list) {
+                       if (!list) {
+                               return;
+                       }
+
+                       if (ev.action) {
+                               list.fileActions.registerAction(ev.action);
+                       } else if (ev.defaultAction) {
+                               list.fileActions.setDefault(
+                                       ev.defaultAction.mime,
+                                       ev.defaultAction.name
+                               );
+                       }
+               });
+       },
+
        _extendFileList: function(fileList) {
                // remove size column from summary
                fileList.fileSummary.$el.find('.filesize').remove();
index 5fb269da75e15271d7b370236aaad7a35b6217b2..3f9cc61da5d3f0f89b79510780d318cd56952d2d 100644 (file)
@@ -45,12 +45,7 @@ describe('OCA.Sharing.App tests', function() {
                fileListOut = App.initSharingOut($('#app-content-sharingout'));
        });
        afterEach(function() {
-               App._inFileList = null;
-               App._outFileList = null;
-               fileListIn.destroy();
-               fileListOut.destroy();
-               fileListIn = null;
-               fileListOut = null;
+               App.destroy();
        });
 
        describe('initialization', function() {