Merge pull request #9538 from owncloud/fileactions-cleanup
Propagate file action changes to the file lists
This commit is contained in:
commit
e391108ebc
7 changed files with 137 additions and 43 deletions
|
@ -32,9 +32,11 @@
|
||||||
// regular actions
|
// regular actions
|
||||||
fileActions.merge(OCA.Files.fileActions);
|
fileActions.merge(OCA.Files.fileActions);
|
||||||
|
|
||||||
// in case apps would decide to register file actions later,
|
this._onActionsUpdated = _.bind(this._onActionsUpdated, this);
|
||||||
// replace the global object with this one
|
OCA.Files.fileActions.on('setDefault.app-files', this._onActionsUpdated);
|
||||||
OCA.Files.fileActions = fileActions;
|
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.files = OCA.Files.Files;
|
||||||
|
|
||||||
|
@ -59,6 +61,32 @@
|
||||||
this._onPopState(OC.Util.History.parseUrlQuery());
|
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.
|
* Returns the container of the currently visible app.
|
||||||
*
|
*
|
||||||
|
|
|
@ -23,48 +23,52 @@
|
||||||
icons: {},
|
icons: {},
|
||||||
currentFile: null,
|
currentFile: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy jquery element, for events
|
||||||
|
*/
|
||||||
|
$el: null,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List of handlers to be notified whenever a register() or
|
* List of handlers to be notified whenever a register() or
|
||||||
* setDefault() was called.
|
* setDefault() was called.
|
||||||
*/
|
*/
|
||||||
_updateListeners: [],
|
_updateListeners: {},
|
||||||
|
|
||||||
initialize: function() {
|
initialize: function() {
|
||||||
this.clear();
|
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()
|
* Adds an event handler
|
||||||
* or setDefault() has been called.
|
|
||||||
*
|
*
|
||||||
|
* @param {String} eventName event name
|
||||||
* @param Function callback
|
* @param Function callback
|
||||||
*/
|
*/
|
||||||
addUpdateListener: function(callback) {
|
on: function(eventName, callback) {
|
||||||
if (!_.isFunction(callback)) {
|
this.$el.on(eventName, callback);
|
||||||
throw 'Argument passed to FileActions.addUpdateListener must be a function';
|
|
||||||
}
|
|
||||||
this._updateListeners.push(callback);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes an update listener.
|
* Removes an event handler
|
||||||
*
|
*
|
||||||
|
* @param {String} eventName event name
|
||||||
* @param Function callback
|
* @param Function callback
|
||||||
*/
|
*/
|
||||||
removeUpdateListener: function(callback) {
|
off: function(eventName, callback) {
|
||||||
if (!_.isFunction(callback)) {
|
this.$el.off(eventName, callback);
|
||||||
throw 'Argument passed to FileActions.removeUpdateListener must be a function';
|
|
||||||
}
|
|
||||||
this._updateListeners = _.without(this._updateListeners, callback);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notifies the registered update listeners
|
* Notifies the event handlers
|
||||||
|
*
|
||||||
|
* @param {String} eventName event name
|
||||||
|
* @param {Object} data data
|
||||||
*/
|
*/
|
||||||
_notifyUpdateListeners: function() {
|
_notifyUpdateListeners: function(eventName, data) {
|
||||||
for (var i = 0; i < this._updateListeners.length; i++) {
|
this.$el.trigger(new $.Event(eventName, data));
|
||||||
this._updateListeners[i](this);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -87,17 +91,44 @@
|
||||||
this.defaults = _.extend(this.defaults, fileActions.defaults);
|
this.defaults = _.extend(this.defaults, fileActions.defaults);
|
||||||
this.icons = _.extend(this.icons, fileActions.icons);
|
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]) {
|
if (!this.actions[mime]) {
|
||||||
this.actions[mime] = {};
|
this.actions[mime] = {};
|
||||||
}
|
}
|
||||||
this.actions[mime][name] = {
|
this.actions[mime][name] = {
|
||||||
action: action,
|
action: action.actionHandler,
|
||||||
permissions: permissions,
|
permissions: action.permissions,
|
||||||
displayName: displayName || t('files', name)
|
displayName: action.displayName || t('files', name)
|
||||||
};
|
};
|
||||||
this.icons[name] = icon;
|
this.icons[name] = action.icon;
|
||||||
this._notifyUpdateListeners();
|
this._notifyUpdateListeners('registerAction', {action: action});
|
||||||
},
|
},
|
||||||
clear: function() {
|
clear: function() {
|
||||||
this.actions = {};
|
this.actions = {};
|
||||||
|
@ -108,7 +139,7 @@
|
||||||
},
|
},
|
||||||
setDefault: function (mime, name) {
|
setDefault: function (mime, name) {
|
||||||
this.defaults[mime] = name;
|
this.defaults[mime] = name;
|
||||||
this._notifyUpdateListeners();
|
this._notifyUpdateListeners('setDefault', {defaultAction: {mime: mime, name: name}});
|
||||||
},
|
},
|
||||||
get: function (mime, type, permissions) {
|
get: function (mime, type, permissions) {
|
||||||
var actions = this.getActions(mime, type, permissions);
|
var actions = this.getActions(mime, type, permissions);
|
||||||
|
|
|
@ -172,7 +172,8 @@
|
||||||
*/
|
*/
|
||||||
destroy: function() {
|
destroy: function() {
|
||||||
// TODO: also unregister other event handlers
|
// 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) {
|
_initFileActions: function(fileActions) {
|
||||||
|
@ -182,7 +183,8 @@
|
||||||
this.fileActions.registerDefaultActions();
|
this.fileActions.registerDefaultActions();
|
||||||
}
|
}
|
||||||
this._onFileActionsUpdated = _.debounce(_.bind(this._onFileActionsUpdated, this), 100);
|
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);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -52,9 +52,7 @@ describe('OCA.Files.App tests', function() {
|
||||||
App.initialize();
|
App.initialize();
|
||||||
});
|
});
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
App.navigation = null;
|
App.destroy();
|
||||||
App.fileList = null;
|
|
||||||
App.files = null;
|
|
||||||
|
|
||||||
pushStateStub.restore();
|
pushStateStub.restore();
|
||||||
parseUrlQueryStub.restore();
|
parseUrlQueryStub.restore();
|
||||||
|
|
|
@ -354,7 +354,7 @@ describe('OCA.Files.FileActions tests', function() {
|
||||||
it('notifies update event handlers once after multiple changes', function() {
|
it('notifies update event handlers once after multiple changes', function() {
|
||||||
var actionStub = sinon.stub();
|
var actionStub = sinon.stub();
|
||||||
var handler = sinon.stub();
|
var handler = sinon.stub();
|
||||||
FileActions.addUpdateListener(handler);
|
FileActions.on('registerAction', handler);
|
||||||
FileActions.register(
|
FileActions.register(
|
||||||
'all',
|
'all',
|
||||||
'Test',
|
'Test',
|
||||||
|
@ -374,8 +374,8 @@ describe('OCA.Files.FileActions tests', function() {
|
||||||
it('does not notifies update event handlers after unregistering', function() {
|
it('does not notifies update event handlers after unregistering', function() {
|
||||||
var actionStub = sinon.stub();
|
var actionStub = sinon.stub();
|
||||||
var handler = sinon.stub();
|
var handler = sinon.stub();
|
||||||
FileActions.addUpdateListener(handler);
|
FileActions.on('registerAction', handler);
|
||||||
FileActions.removeUpdateListener(handler);
|
FileActions.off('registerAction', handler);
|
||||||
FileActions.register(
|
FileActions.register(
|
||||||
'all',
|
'all',
|
||||||
'Test',
|
'Test',
|
||||||
|
|
|
@ -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() {
|
_createFileActions: function() {
|
||||||
// inherit file actions from the files app
|
// inherit file actions from the files app
|
||||||
var fileActions = new OCA.Files.FileActions();
|
var fileActions = new OCA.Files.FileActions();
|
||||||
|
@ -100,6 +115,14 @@ OCA.Sharing.App = {
|
||||||
fileActions.registerDefaultActions();
|
fileActions.registerDefaultActions();
|
||||||
fileActions.merge(OCA.Files.fileActions);
|
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
|
// when the user clicks on a folder, redirect to the corresponding
|
||||||
// folder in the files app instead of opening it directly
|
// folder in the files app instead of opening it directly
|
||||||
fileActions.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename, context) {
|
fileActions.register('dir', 'Open', OC.PERMISSION_READ, '', function (filename, context) {
|
||||||
|
@ -110,6 +133,23 @@ OCA.Sharing.App = {
|
||||||
return fileActions;
|
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) {
|
_extendFileList: function(fileList) {
|
||||||
// remove size column from summary
|
// remove size column from summary
|
||||||
fileList.fileSummary.$el.find('.filesize').remove();
|
fileList.fileSummary.$el.find('.filesize').remove();
|
||||||
|
|
|
@ -45,12 +45,7 @@ describe('OCA.Sharing.App tests', function() {
|
||||||
fileListOut = App.initSharingOut($('#app-content-sharingout'));
|
fileListOut = App.initSharingOut($('#app-content-sharingout'));
|
||||||
});
|
});
|
||||||
afterEach(function() {
|
afterEach(function() {
|
||||||
App._inFileList = null;
|
App.destroy();
|
||||||
App._outFileList = null;
|
|
||||||
fileListIn.destroy();
|
|
||||||
fileListOut.destroy();
|
|
||||||
fileListIn = null;
|
|
||||||
fileListOut = null;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('initialization', function() {
|
describe('initialization', function() {
|
||||||
|
|
Loading…
Reference in a new issue