From: Azul Date: Mon, 6 Apr 2020 08:54:07 +0000 (+0200) Subject: Allow opening files for editing in new tabs X-Git-Tag: v19.0.0beta3~36^2 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=refs%2Fpull%2F20185%2Fhead;p=nextcloud-server.git Allow opening files for editing in new tabs In a file list files with a default action have an href that will trigger the action. This way ctrl-click and middle button click open the default action in a new tab. In order to achieve this a new param `openfile` was introduced to the files app. It will make the files app trigger the default action for the file in question. This also allows linking to file content rather than just the details display. Introduce fileList.getDefaultActionUrl() to create a link with that param set. It's overwritten in the trashbin fileList so that anchors continue to have `#` as a href. Fix the link generation for subfolders of public shares: 58a87d0 was the last commit that touched the linkTo function in public.js. It included the params as arguments to the generateUrl function. Turns out this completely ignores the dir parameter now. The inclusion was reverted in other places so revert it here as well. Also change `dir` to `path` in the param as that is respected when following the link. Add Test for the new link url for files with default action. Remove test for multiple selects with ctrl-click as that is not what we are doing anymore. Signed-off-by: Azul --- diff --git a/apps/files/js/fileactions.js b/apps/files/js/fileactions.js index 404b6f1877e..1f6d5f798a9 100644 --- a/apps/files/js/fileactions.js +++ b/apps/files/js/fileactions.js @@ -266,7 +266,7 @@ var mime = this.getCurrentMimeType(); var type = this.getCurrentType(); var permissions = this.getCurrentPermissions(); - return this.getDefaultFileAction(mime,type, permissions); + return this.getDefaultFileAction(mime, type, permissions); }, /** diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js index ce428064337..e7d48d4bcd1 100644 --- a/apps/files/js/filelist.js +++ b/apps/files/js/filelist.js @@ -432,7 +432,7 @@ this.setupUploadEvents(this._uploader); } } - + this.triedActionOnce = false; OC.Plugins.attach('OCA.Files.FileList', this); @@ -874,16 +874,12 @@ if ($tr.hasClass('dragging')) { return; } - if (this._allowSelection && (event.ctrlKey || event.shiftKey)) { + if (this._allowSelection && event.shiftKey) { event.preventDefault(); - if (event.shiftKey) { - this._selectRange($tr); - } else { - this._selectSingle($tr); - } + this._selectRange($tr); this._lastChecked = $tr; this.updateSelectionSummary(); - } else { + } else if (!event.ctrlKey) { // clicked directly on the name if (!this._detailsView || $(event.target).is('.nametext, .name, .thumbnail') || $(event.target).closest('.nametext').length) { var filename = $tr.attr('data-file'); @@ -1320,6 +1316,31 @@ }, 0); } + if(!this.triedActionOnce) { + var id = OC.Util.History.parseUrlQuery().openfile; + if (id) { + var $tr = this.$fileList.children().filterAttr('data-id', '' + id); + var filename = $tr.attr('data-file'); + this.fileActions.currentFile = $tr.find('td'); + var dir = $tr.attr('data-path') || this.getCurrentDirectory(); + var spec = this.fileActions.getCurrentDefaultFileAction(); + if (spec && spec.action) { + spec.action(filename, { + $file: $tr, + fileList: this, + fileActions: this.fileActions, + dir: dir + }); + + } + else { + var url = this.getDownloadUrl(filename, dir, true); + OCA.Files.Files.handleDownload(url); + } + } + this.triedActionOnce = true; + } + return newTrs; }, @@ -1524,10 +1545,14 @@ td = $(''); + var spec = this.fileActions.getDefaultFileAction(mime, type, permissions); // linkUrl if (mime === 'httpd/unix-directory') { linkUrl = this.linkTo(path + '/' + name); } + else if (spec && spec.action) { + linkUrl = this.getDefaultActionUrl(path, fileData.id); + } else { linkUrl = this.getDownloadUrl(name, path, type === 'dir'); } @@ -2146,6 +2171,10 @@ return OCA.Files.Files.getDownloadUrl(files, dir || this.getCurrentDirectory(), isDir); }, + getDefaultActionUrl: function(path, id) { + return this.linkTo(path) + "&openfile="+id; + }, + getUploadUrl: function(fileName, dir) { if (_.isUndefined(dir)) { dir = this.getCurrentDirectory(); diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js index f9c1b5f31cd..ee70a1452a9 100644 --- a/apps/files/tests/js/filelistSpec.js +++ b/apps/files/tests/js/filelistSpec.js @@ -239,6 +239,33 @@ describe('OCA.Files.FileList tests', function() { expect($tr.find('.date').text()).not.toEqual('?'); expect(fileList.findFileEl('testName.txt')[0]).toEqual($tr[0]); }); + it('generates file element with url for default action when one is defined', function() { + var actionStub = sinon.stub(); + fileList.setFiles(testFiles); + fileList.fileActions.registerAction({ + mime: 'text/plain', + name: 'Test', + type: OCA.Files.FileActions.TYPE_INLINE, + permissions: OC.PERMISSION_ALL, + icon: function() { + // Specify icon for hitory button + return OC.imagePath('core','actions/history'); + }, + actionHandler: actionStub + }); + fileList.fileActions.setDefault('text/plain', 'Test'); + var fileData = new FileInfo({ + id: 18, + name: 'testName.txt', + mimetype: 'text/plain', + size: 1234, + etag: 'a01234c', + mtime: 123456 + }); + var $tr = fileList.add(fileData); + expect($tr.find('a.name').attr('href')) + .toEqual(OC.getRootPath() + '/index.php/apps/files?dir=&openfile=18'); + }); it('generates dir element with correct attributes when calling add() with dir data', function() { var fileData = new FileInfo({ id: 19, @@ -1906,36 +1933,6 @@ describe('OCA.Files.FileList tests', function() { expect($tr.find('input:checkbox').prop('checked')).toEqual(true); }); - it('Selects/deselect a file when clicking on the name while holding Ctrl', function() { - var $tr = fileList.findFileEl('One.txt'); - var $tr2 = fileList.findFileEl('Three.pdf'); - var e; - expect($tr.find('input:checkbox').prop('checked')).toEqual(false); - expect($tr2.find('input:checkbox').prop('checked')).toEqual(false); - e = new $.Event('click'); - e.ctrlKey = true; - $tr.find('td.filename .name').trigger(e); - - expect($tr.find('input:checkbox').prop('checked')).toEqual(true); - expect($tr2.find('input:checkbox').prop('checked')).toEqual(false); - - // click on second entry, does not clear the selection - e = new $.Event('click'); - e.ctrlKey = true; - $tr2.find('td.filename .name').trigger(e); - expect($tr.find('input:checkbox').prop('checked')).toEqual(true); - expect($tr2.find('input:checkbox').prop('checked')).toEqual(true); - - expect(_.pluck(fileList.getSelectedFiles(), 'name')).toEqual(['One.txt', 'Three.pdf']); - - // deselect now - e = new $.Event('click'); - e.ctrlKey = true; - $tr2.find('td.filename .name').trigger(e); - expect($tr.find('input:checkbox').prop('checked')).toEqual(true); - expect($tr2.find('input:checkbox').prop('checked')).toEqual(false); - expect(_.pluck(fileList.getSelectedFiles(), 'name')).toEqual(['One.txt']); - }); it('Selects a range when clicking on one file then Shift clicking on another one', function() { var $tr = fileList.findFileEl('One.txt'); var $tr2 = fileList.findFileEl('Three.pdf'); diff --git a/apps/files_sharing/js/public.js b/apps/files_sharing/js/public.js index aba7bbc029e..982f32dbdd9 100644 --- a/apps/files_sharing/js/public.js +++ b/apps/files_sharing/js/public.js @@ -113,9 +113,9 @@ OCA.Sharing.PublicApp = { // Show file preview if previewer is available, images are already handled by the template if (mimetype.substr(0, mimetype.indexOf('/')) !== 'image' && $('.publicpreview').length === 0) { // Trigger default action if not download TODO - var action = FileActions.getDefaultFileAction(mimetype, 'file', OC.PERMISSION_READ); - if (action && action.action) { - action($('#filename').val()); + var spec = FileActions.getDefaultFileAction(mimetype, 'file', OC.PERMISSION_READ); + if (spec && spec.action) { + spec.action($('#filename').val()); } } } @@ -248,7 +248,7 @@ OCA.Sharing.PublicApp = { }; this.fileList.linkTo = function (dir) { - return OC.generateUrl('/s/' + token + '', {dir: dir}); + return OC.generateUrl('/s/' + token + '') + '?' + OC.buildQueryString({path: dir}); }; this.fileList.generatePreviewUrl = function (urlSpec) { diff --git a/apps/files_trashbin/js/files_trashbin.js b/apps/files_trashbin/js/files_trashbin.js index f876350eb5f..ca01787c5fa 100644 --- a/apps/files_trashbin/js/files_trashbin.js +++ b/apps/files_trashbin/js/files_trashbin.js @@ -1,2 +1,2 @@ -!function(e){var t={};function i(n){if(t[n])return t[n].exports;var r=t[n]={i:n,l:!1,exports:{}};return e[n].call(r.exports,r,r.exports,i),r.l=!0,r.exports}i.m=e,i.c=t,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)i.d(n,r,function(t){return e[t]}.bind(null,r));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="/js/",i(i.s=0)}([function(e,t,i){"use strict";i.r(t);i(1),i(2),i(3);window.OCA.Trashbin=OCA.Trashbin},function(e,i){OCA.Trashbin={},OCA.Trashbin.App={_initialized:!1,client:null,initialize:function(e){if(!this._initialized){this._initialized=!0,this.client=new OC.Files.Client({host:OC.getHost(),port:OC.getPort(),root:OC.linkToRemoteBase("dav")+"/trashbin/"+OC.getCurrentUser().uid,useHTTPS:"https"===OC.getProtocol()});var i=OC.Util.History.parseUrlQuery();this.fileList=new OCA.Trashbin.FileList($("#app-content-trashbin"),{fileActions:this._createFileActions(),detailsViewEnabled:!1,scrollTo:i.scrollto,config:OCA.Files.App.getFilesConfig(),multiSelectMenu:[{name:"restore",displayName:t("files_trashbin","Restore"),iconClass:"icon-history"},{name:"delete",displayName:t("files_trashbin","Delete permanently"),iconClass:"icon-delete"}],client:this.client,shown:!0})}},_createFileActions:function(){var e=this.client,i=new OCA.Files.FileActions;return i.register("dir","Open",OC.PERMISSION_READ,"",(function(e,t){var i=t.fileList.getCurrentDirectory();t.fileList.changeDirectory(OC.joinPaths(i,e))})),i.setDefault("dir","Open"),i.registerAction({name:"Restore",displayName:t("files_trashbin","Restore"),type:OCA.Files.FileActions.TYPE_INLINE,mime:"all",permissions:OC.PERMISSION_READ,iconClass:"icon-history",actionHandler:function(i,n){var r=n.fileList,a=r.findFileEl(i);r.showFileBusyState(a,!0);var o=n.fileList.getCurrentDirectory();e.move(OC.joinPaths("trash",o,i),OC.joinPaths("restore",i),!0).then(r._removeCallback.bind(r,[i]),(function(){r.showFileBusyState(a,!1),OC.Notification.show(t("files_trashbin","Error while restoring file from trashbin"))}))}}),i.registerAction({name:"Delete",displayName:t("files_trashbin","Delete permanently"),mime:"all",permissions:OC.PERMISSION_READ,iconClass:"icon-delete",render:function(e,n,r){var a=i._makeActionLink(e,r);return a.attr("original-title",t("files_trashbin","Delete permanently")),a.children("img").attr("alt",t("files_trashbin","Delete permanently")),r.$file.find("td:last").append(a),a},actionHandler:function(i,n){var r=n.fileList;$(".tipsy").remove();var a=r.findFileEl(i);r.showFileBusyState(a,!0);var o=n.fileList.getCurrentDirectory();e.remove(OC.joinPaths("trash",o,i)).then(r._removeCallback.bind(r,[i]),(function(){r.showFileBusyState(a,!1),OC.Notification.show(t("files_trashbin","Error while removing file from trashbin"))}))}}),i}},$(document).ready((function(){$("#app-content-trashbin").one("show",(function(){OCA.Trashbin.App.initialize($("#app-content-trashbin"))}))}))},function(e,i){!function(){var e=new RegExp(/^(.+)\.d[0-9]+$/),i="{http://nextcloud.org/ns}trashbin-filename",n="{http://nextcloud.org/ns}trashbin-deletion-time",r="{http://nextcloud.org/ns}trashbin-original-location",a="{http://nextcloud.org/ns}trashbin-title";function o(t){t=OC.basename(t);var i=e.exec(t);return i&&i.length>1&&(t=i[1]),t}var s=function(e,t){this.client=t.client,this.initialize(e,t)};s.prototype=_.extend({},OCA.Files.FileList.prototype,{id:"trashbin",appName:t("files_trashbin","Deleted files"),client:null,initialize:function(){this.client.addFileInfoParser((function(e,t){var o=e.propStat[0].properties,s=o[r],l=o[a];return{displayName:o[i],mtime:1e3*parseInt(o[n],10),hasPreview:!0,path:s,extraData:l}}));var e=OCA.Files.FileList.prototype.initialize.apply(this,arguments);return this.$el.find(".undelete").click("click",_.bind(this._onClickRestoreSelected,this)),this.setSort("mtime","desc"),this.breadcrumb._makeCrumbs=function(){for(var e=OCA.Files.BreadCrumb.prototype._makeCrumbs.apply(this,[].concat(Array.prototype.slice.call(arguments),["icon-delete no-hover"])),t=1;ti.parts.length&&(n.parts.length=i.parts.length)}else{var o=[];for(r=0;r1&&(t=i[1]),t}var s=function(e,t){this.client=t.client,this.initialize(e,t)};s.prototype=_.extend({},OCA.Files.FileList.prototype,{id:"trashbin",appName:t("files_trashbin","Deleted files"),client:null,initialize:function(){this.client.addFileInfoParser((function(e,t){var o=e.propStat[0].properties,s=o[r],l=o[a];return{displayName:o[i],mtime:1e3*parseInt(o[n],10),hasPreview:!0,path:s,extraData:l}}));var e=OCA.Files.FileList.prototype.initialize.apply(this,arguments);return this.$el.find(".undelete").click("click",_.bind(this._onClickRestoreSelected,this)),this.setSort("mtime","desc"),this.breadcrumb._makeCrumbs=function(){for(var e=OCA.Files.BreadCrumb.prototype._makeCrumbs.apply(this,[].concat(Array.prototype.slice.call(arguments),["icon-delete no-hover"])),t=1;ti.parts.length&&(n.parts.length=i.parts.length)}else{var o=[];for(r=0;r 1) {\n\t\t\tname = match[1]\n\t\t}\n\t\treturn name\n\t}\n\n\t/**\n\t * @class OCA.Trashbin.FileList\n\t * @augments OCA.Files.FileList\n\t * @classdesc List of deleted files\n\t *\n\t * @param $el container element with existing markup for the #controls\n\t * and a table\n\t * @param [options] map of options\n\t */\n\tvar FileList = function($el, options) {\n\t\tthis.client = options.client\n\t\tthis.initialize($el, options)\n\t}\n\tFileList.prototype = _.extend({}, OCA.Files.FileList.prototype,\n\t\t/** @lends OCA.Trashbin.FileList.prototype */ {\n\t\tid: 'trashbin',\n\t\tappName: t('files_trashbin', 'Deleted files'),\n\t\t/** @type {OC.Files.Client} */\n\t\tclient: null,\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tinitialize: function() {\n\t\t\tthis.client.addFileInfoParser(function(response, data) {\n\t\t\t\tvar props = response.propStat[0].properties\n\t\t\t\tvar path = props[TRASHBIN_ORIGINAL_LOCATION]\n\t\t\t\tvar title = props[TRASHBIN_TITLE]\n\t\t\t\treturn {\n\t\t\t\t\tdisplayName: props[FILENAME_PROP],\n\t\t\t\t\tmtime: parseInt(props[DELETION_TIME_PROP], 10) * 1000,\n\t\t\t\t\thasPreview: true,\n\t\t\t\t\tpath: path,\n\t\t\t\t\textraData: title\n\t\t\t\t}\n\t\t\t})\n\n\t\t\tvar result = OCA.Files.FileList.prototype.initialize.apply(this, arguments)\n\t\t\tthis.$el.find('.undelete').click('click', _.bind(this._onClickRestoreSelected, this))\n\n\t\t\tthis.setSort('mtime', 'desc')\n\t\t\t/**\n\t\t\t * Override crumb making to add \"Deleted Files\" entry\n\t\t\t * and convert files with \".d\" extensions to a more\n\t\t\t * user friendly name.\n\t\t\t */\n\t\t\t\tthis.breadcrumb._makeCrumbs = function() {\n\t\t\t\t\tvar parts = OCA.Files.BreadCrumb.prototype._makeCrumbs.apply(this, [...arguments, 'icon-delete no-hover'])\n\t\t\t\t\tfor (var i = 1; i < parts.length; i++) {\n\t\t\t\t\t\tparts[i].name = getDeletedFileName(parts[i].name)\n\t\t\t\t\t}\n\t\t\t\t\treturn parts\n\t\t\t\t}\n\n\t\t\t\tOC.Plugins.attach('OCA.Trashbin.FileList', this)\n\t\t\t\treturn result\n\t\t\t},\n\n\t\t\t/**\n\t\t * Override to only return read permissions\n\t\t */\n\t\t\tgetDirectoryPermissions: function() {\n\t\t\t\treturn OC.PERMISSION_READ | OC.PERMISSION_DELETE\n\t\t\t},\n\n\t\t\t_setCurrentDir: function(targetDir) {\n\t\t\t\tOCA.Files.FileList.prototype._setCurrentDir.apply(this, arguments)\n\n\t\t\t\tvar baseDir = OC.basename(targetDir)\n\t\t\t\tif (baseDir !== '') {\n\t\t\t\t\tthis.setPageTitle(getDeletedFileName(baseDir))\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t_createRow: function() {\n\t\t\t// FIXME: MEGAHACK until we find a better solution\n\t\t\t\tvar tr = OCA.Files.FileList.prototype._createRow.apply(this, arguments)\n\t\t\t\ttr.find('td.filesize').remove()\n\t\t\t\treturn tr\n\t\t\t},\n\n\t\t\tgetAjaxUrl: function(action, params) {\n\t\t\t\tvar q = ''\n\t\t\t\tif (params) {\n\t\t\t\t\tq = '?' + OC.buildQueryString(params)\n\t\t\t\t}\n\t\t\t\treturn OC.filePath('files_trashbin', 'ajax', action + '.php') + q\n\t\t\t},\n\n\t\t\tsetupUploadEvents: function() {\n\t\t\t// override and do nothing\n\t\t\t},\n\n\t\t\tlinkTo: function(dir) {\n\t\t\t\treturn OC.linkTo('files', 'index.php') + '?view=trashbin&dir=' + encodeURIComponent(dir).replace(/%2F/g, '/')\n\t\t\t},\n\n\t\t\telementToFile: function($el) {\n\t\t\t\tvar fileInfo = OCA.Files.FileList.prototype.elementToFile($el)\n\t\t\t\tif (this.getCurrentDirectory() === '/') {\n\t\t\t\t\tfileInfo.displayName = getDeletedFileName(fileInfo.name)\n\t\t\t\t}\n\t\t\t\t// no size available\n\t\t\t\tdelete fileInfo.size\n\t\t\t\treturn fileInfo\n\t\t\t},\n\n\t\t\tupdateEmptyContent: function() {\n\t\t\t\tvar exists = this.$fileList.find('tr:first').exists()\n\t\t\t\tthis.$el.find('#emptycontent').toggleClass('hidden', exists)\n\t\t\t\tthis.$el.find('#filestable th').toggleClass('hidden', !exists)\n\t\t\t},\n\n\t\t\t_removeCallback: function(files) {\n\t\t\t\tvar $el\n\t\t\t\tfor (var i = 0; i < files.length; i++) {\n\t\t\t\t\t$el = this.remove(OC.basename(files[i]), { updateSummary: false })\n\t\t\t\t\tthis.fileSummary.remove({ type: $el.attr('data-type'), size: $el.attr('data-size') })\n\t\t\t\t}\n\t\t\t\tthis.fileSummary.update()\n\t\t\t\tthis.updateEmptyContent()\n\t\t\t},\n\n\t\t\t_onClickRestoreSelected: function(event) {\n\t\t\t\tevent.preventDefault()\n\t\t\t\tvar self = this\n\t\t\t\tvar files = _.pluck(this.getSelectedFiles(), 'name')\n\t\t\t\tfor (var i = 0; i < files.length; i++) {\n\t\t\t\t\tvar tr = this.findFileEl(files[i])\n\t\t\t\t\tthis.showFileBusyState(tr, true)\n\t\t\t\t}\n\n\t\t\t\tthis.fileMultiSelectMenu.toggleLoading('restore', true)\n\t\t\t\tvar restorePromises = files.map(function(file) {\n\t\t\t\t\treturn self.client.move(OC.joinPaths('trash', self.getCurrentDirectory(), file), OC.joinPaths('restore', file), true)\n\t\t\t\t\t\t.then(\n\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\tself._removeCallback([file])\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t)\n\t\t\t\t})\n\t\t\t\treturn Promise.all(restorePromises).then(\n\t\t\t\t\tfunction() {\n\t\t\t\t\t\tself.fileMultiSelectMenu.toggleLoading('restore', false)\n\t\t\t\t\t},\n\t\t\t\t\tfunction() {\n\t\t\t\t\t\tOC.Notification.show(t('files_trashbin', 'Error while restoring files from trashbin'))\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t},\n\n\t\t\t_onClickDeleteSelected: function(event) {\n\t\t\t\tevent.preventDefault()\n\t\t\t\tvar self = this\n\t\t\t\tvar allFiles = this.$el.find('.select-all').is(':checked')\n\t\t\t\tvar files = _.pluck(this.getSelectedFiles(), 'name')\n\t\t\t\tfor (var i = 0; i < files.length; i++) {\n\t\t\t\t\tvar tr = this.findFileEl(files[i])\n\t\t\t\t\tthis.showFileBusyState(tr, true)\n\t\t\t\t}\n\n\t\t\t\tif (allFiles) {\n\t\t\t\t\treturn this.client.remove(OC.joinPaths('trash', this.getCurrentDirectory()))\n\t\t\t\t\t\t.then(\n\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\tself.hideMask()\n\t\t\t\t\t\t\t\tself.setFiles([])\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\tOC.Notification.show(t('files_trashbin', 'Error while emptying trashbin'))\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t)\n\t\t\t\t} else {\n\t\t\t\t\tthis.fileMultiSelectMenu.toggleLoading('delete', true)\n\t\t\t\t\tvar deletePromises = files.map(function(file) {\n\t\t\t\t\t\treturn self.client.remove(OC.joinPaths('trash', self.getCurrentDirectory(), file))\n\t\t\t\t\t\t\t.then(\n\t\t\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\t\t\tself._removeCallback([file])\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t)\n\t\t\t\t\t})\n\t\t\t\t\treturn Promise.all(deletePromises).then(\n\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\tself.fileMultiSelectMenu.toggleLoading('delete', false)\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfunction() {\n\t\t\t\t\t\t\tOC.Notification.show(t('files_trashbin', 'Error while removing files from trashbin'))\n\t\t\t\t\t\t}\n\t\t\t\t\t)\n\t\t\t\t}\n\t\t\t},\n\n\t\t\t_onClickFile: function(event) {\n\t\t\t\tvar mime = $(this).parent().parent().data('mime')\n\t\t\t\tif (mime !== 'httpd/unix-directory') {\n\t\t\t\t\tevent.preventDefault()\n\t\t\t\t}\n\t\t\t\treturn OCA.Files.FileList.prototype._onClickFile.apply(this, arguments)\n\t\t\t},\n\n\t\t\tgeneratePreviewUrl: function(urlSpec) {\n\t\t\t\treturn OC.generateUrl('/apps/files_trashbin/preview?') + $.param(urlSpec)\n\t\t\t},\n\n\t\t\tgetDownloadUrl: function() {\n\t\t\t// no downloads\n\t\t\t\treturn '#'\n\t\t\t},\n\n\t\t\tupdateStorageStatistics: function() {\n\t\t\t// no op because the trashbin doesn't have\n\t\t\t// storage info like free space / used space\n\t\t\t},\n\n\t\t\tisSelectedDeletable: function() {\n\t\t\t\treturn true\n\t\t\t},\n\n\t\t\t/**\n\t\t * Returns list of webdav properties to request\n\t\t */\n\t\t\t_getWebdavProperties: function() {\n\t\t\t\treturn [FILENAME_PROP, DELETION_TIME_PROP, TRASHBIN_ORIGINAL_LOCATION, TRASHBIN_TITLE].concat(this.filesClient.getPropfindProperties())\n\t\t\t},\n\n\t\t\t/**\n\t\t * Reloads the file list using ajax call\n\t\t *\n\t\t * @returns ajax call object\n\t\t */\n\t\t\treload: function() {\n\t\t\t\tthis._selectedFiles = {}\n\t\t\t\tthis._selectionSummary.clear()\n\t\t\t\tthis.$el.find('.select-all').prop('checked', false)\n\t\t\t\tthis.showMask()\n\t\t\t\tif (this._reloadCall) {\n\t\t\t\t\tthis._reloadCall.abort()\n\t\t\t\t}\n\t\t\t\tthis._reloadCall = this.client.getFolderContents(\n\t\t\t\t\t'trash/' + this.getCurrentDirectory(), {\n\t\t\t\t\t\tincludeParent: false,\n\t\t\t\t\t\tproperties: this._getWebdavProperties()\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t\tvar callBack = this.reloadCallback.bind(this)\n\t\t\t\treturn this._reloadCall.then(callBack, callBack)\n\t\t\t},\n\t\t\treloadCallback: function(status, result) {\n\t\t\t\tdelete this._reloadCall\n\t\t\t\tthis.hideMask()\n\n\t\t\t\tif (status === 401) {\n\t\t\t\t\treturn false\n\t\t\t\t}\n\n\t\t\t\t// Firewall Blocked request?\n\t\t\t\tif (status === 403) {\n\t\t\t\t// Go home\n\t\t\t\t\tthis.changeDirectory('/')\n\t\t\t\t\tOC.Notification.show(t('files', 'This operation is forbidden'))\n\t\t\t\t\treturn false\n\t\t\t\t}\n\n\t\t\t\t// Did share service die or something else fail?\n\t\t\t\tif (status === 500) {\n\t\t\t\t// Go home\n\t\t\t\t\tthis.changeDirectory('/')\n\t\t\t\t\tOC.Notification.show(t('files', 'This directory is unavailable, please check the logs or contact the administrator'))\n\t\t\t\t\treturn false\n\t\t\t\t}\n\n\t\t\t\tif (status === 404) {\n\t\t\t\t// go back home\n\t\t\t\t\tthis.changeDirectory('/')\n\t\t\t\t\treturn false\n\t\t\t\t}\n\t\t\t\t// aborted ?\n\t\t\t\tif (status === 0) {\n\t\t\t\t\treturn true\n\t\t\t\t}\n\n\t\t\t\tthis.setFiles(result)\n\t\t\t\treturn true\n\t\t\t}\n\n\t\t})\n\n\tOCA.Trashbin.FileList = FileList\n})()\n","// style-loader: Adds some css to the DOM by adding a