Skip to content

Commit

Permalink
Merge pull request #12652 from tomasz-grobelny/operation_progress_imp…
Browse files Browse the repository at this point in the history
…rovements3

Operation progress improvements
  • Loading branch information
skjnldsv authored Feb 14, 2019
2 parents e65f7f0 + 08919eb commit 6a3f4e4
Show file tree
Hide file tree
Showing 12 changed files with 525 additions and 288 deletions.
62 changes: 31 additions & 31 deletions apps/files/js/file-upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,11 @@ OC.Uploader.prototype = _.extend({
*/
fileList: null,

/**
* @type OCA.Files.OperationProgressBar
*/
progressBar: null,

/**
* @type OC.Files.Client
*/
Expand Down Expand Up @@ -759,14 +764,6 @@ OC.Uploader.prototype = _.extend({
callbacks.onNoConflicts(selection);
},

_hideProgressBar: function() {
var self = this;
$('#uploadprogresswrapper .stop').fadeOut();
$('#uploadprogressbar').fadeOut(function() {
self.$uploadEl.trigger(new $.Event('resized'));
});
},

_updateProgressBarOnUploadStop: function() {
if (this._pendingUploadDoneCount === 0) {
// All the uploads ended and there is no pending operation, so hide
Expand All @@ -780,17 +777,31 @@ OC.Uploader.prototype = _.extend({
return;
}

$('#uploadprogressbar .label .mobile').text(t('core', '…'));
$('#uploadprogressbar .label .desktop').text(t('core', 'Processing files …'));
this._setProgressBarText(t('core', 'Processing files …'), t('core', '…'));

// Nothing is being uploaded at this point, and the pending operations
// can not be cancelled, so the cancel button should be hidden.
$('#uploadprogresswrapper .stop').fadeOut();
this._hideCancelButton();
},

_hideProgressBar: function() {
this.progressBar.hideProgressBar();
},

_hideCancelButton: function() {
this.progressBar.hideCancelButton();
},

_showProgressBar: function() {
$('#uploadprogressbar').fadeIn();
this.$uploadEl.trigger(new $.Event('resized'));
this.progressBar.showProgressBar();
},

_setProgressBarValue: function(value) {
this.progressBar.setProgressBarValue(value);
},

_setProgressBarText: function(textDesktop, textMobile, title) {
this.progressBar.setProgressBarText(textDesktop, textMobile, title);
},

/**
Expand Down Expand Up @@ -826,6 +837,7 @@ OC.Uploader.prototype = _.extend({
options = options || {};

this.fileList = options.fileList;
this.progressBar = options.progressBar;
this.filesClient = options.filesClient || OC.Files.getClient();
this.davClient = new OC.Files.Client({
host: this.filesClient.getHost(),
Expand All @@ -839,7 +851,7 @@ OC.Uploader.prototype = _.extend({
this.$uploadEl = $uploadEl;

if ($uploadEl.exists()) {
$('#uploadprogresswrapper .stop').on('click', function() {
this.progressBar.on('cancel', function() {
self.cancelUploads();
});

Expand Down Expand Up @@ -1099,16 +1111,8 @@ OC.Uploader.prototype = _.extend({
// add progress handlers
fileupload.on('fileuploadstart', function(e, data) {
self.log('progress handle fileuploadstart', e, data);
$('#uploadprogresswrapper .stop').show();
$('#uploadprogresswrapper .label').show();
$('#uploadprogressbar').progressbar({value: 0});
$('#uploadprogressbar .ui-progressbar-value').
html('<em class="label inner"><span class="desktop">'
+ t('files', 'Uploading …')
+ '</span><span class="mobile">'
+ t('files', '…')
+ '</span></em>');
$('#uploadprogressbar').tooltip({placement: 'bottom'});
self._setProgressBarText(t('files', 'Uploading …'), t('files', '…'));
self._setProgressBarValue(0);
self._showProgressBar();
// initial remaining time variables
lastUpdate = new Date().getTime();
Expand Down Expand Up @@ -1158,16 +1162,12 @@ OC.Uploader.prototype = _.extend({
// show "Uploading ..." for durations longer than 4 hours
h = t('files', 'Uploading …');
}
$('#uploadprogressbar .label .mobile').text(h);
$('#uploadprogressbar .label .desktop').text(h);
$('#uploadprogressbar').attr('original-title',
t('files', '{loadedSize} of {totalSize} ({bitrate})' , {
self._setProgressBarText(h, h, t('files', '{loadedSize} of {totalSize} ({bitrate})' , {
loadedSize: humanFileSize(data.loaded),
totalSize: humanFileSize(data.total),
bitrate: humanFileSize(data.bitrate / 8) + '/s'
})
);
$('#uploadprogressbar').progressbar('value', progress);
}));
self._setProgressBarValue(progress);
self.trigger('progressall', e, data);
});
fileupload.on('fileuploadstop', function(e, data) {
Expand Down
143 changes: 68 additions & 75 deletions apps/files/js/filelist.js
Original file line number Diff line number Diff line change
Expand Up @@ -386,11 +386,16 @@
});
}

this._operationProgressBar = new OCA.Files.OperationProgressBar();
this._operationProgressBar.render();
this.$el.find('#uploadprogresswrapper').replaceWith(this._operationProgressBar.$el);

if (options.enableUpload) {
// TODO: auto-create this element
var $uploadEl = this.$el.find('#file_upload_start');
if ($uploadEl.exists()) {
this._uploader = new OC.Uploader($uploadEl, {
progressBar: this._operationProgressBar,
fileList: this,
filesClient: this.filesClient,
dropZone: $('#content'),
Expand Down Expand Up @@ -2206,21 +2211,39 @@
remove: function(name, options){
options = options || {};
var fileEl = this.findFileEl(name);
var fileId = fileEl.data('id');
var index = fileEl.index();
if (!fileEl.length) {
return null;
var fileData = _.findWhere(this.files, {name: name});
if (!fileData) {
return;
}
var fileId = fileData.id;
if (this._selectedFiles[fileId]) {
// remove from selection first
this._selectFileEl(fileEl, false);
this.updateSelectionSummary();
}
if (this._selectedFiles[fileId]) {
delete this._selectedFiles[fileId];
this._selectionSummary.remove(fileData);
this.updateSelectionSummary();
}
var index = this.files.findIndex(function(el){return el.name==name;});
this.files.splice(index, 1);

// TODO: improve performance on batch update
this.isEmpty = !this.files.length;
if (typeof(options.updateSummary) === 'undefined' || !!options.updateSummary) {
this.updateEmptyContent();
this.fileSummary.remove({type: fileData.type, size: fileData.size}, true);
}

if (!fileEl.length) {
return null;
}

if (this._dragOptions && (fileEl.data('permissions') & OC.PERMISSION_DELETE)) {
// file is only draggable when delete permissions are set
fileEl.find('td.filename').draggable('destroy');
}
this.files.splice(index, 1);
if (this._currentFileModel && this._currentFileModel.get('id') === fileId) {
// Note: in the future we should call destroy() directly on the model
// and the model will take care of the deletion.
Expand All @@ -2230,12 +2253,6 @@
this._updateDetailsView(null);
}
fileEl.remove();
// TODO: improve performance on batch update
this.isEmpty = !this.files.length;
if (typeof(options.updateSummary) === 'undefined' || !!options.updateSummary) {
this.updateEmptyContent();
this.fileSummary.remove({type: fileEl.attr('data-type'), size: fileEl.attr('data-size')}, true);
}

var lastIndex = this.$fileList.children().length;
// if there are less elements visible than one page
Expand Down Expand Up @@ -2282,29 +2299,6 @@
fileNames = [fileNames];
}

function Semaphore(max) {
var counter = 0;
var waiting = [];

this.acquire = function() {
if(counter < max) {
counter++;
return new Promise(function(resolve) { resolve(); });
} else {
return new Promise(function(resolve) { waiting.push(resolve); });
}
};

this.release = function() {
counter--;
if (waiting.length > 0 && counter < max) {
counter++;
var promise = waiting.shift();
promise();
}
};
}

var moveFileFunction = function(fileName) {
var $tr = self.findFileEl(fileName);
self.showFileBusyState($tr, true);
Expand All @@ -2316,7 +2310,7 @@
return self.filesClient.move(dir + fileName, targetPath + fileName)
.done(function() {
// if still viewing the same directory
if (OC.joinPaths(self.getCurrentDirectory(), '/') === dir) {
if (OC.joinPaths(self.getCurrentDirectory(), '/') === OC.joinPaths(dir, '/')) {
// recalculate folder size
var oldFile = self.findFileEl(target);
var newFile = self.findFileEl(fileName);
Expand All @@ -2325,7 +2319,6 @@
oldFile.data('size', newSize);
oldFile.find('td.filesize').text(OC.Util.humanFileSize(newSize));

// TODO: also update entry in FileList.files
self.remove(fileName);
}
})
Expand All @@ -2345,22 +2338,33 @@
self.showFileBusyState($tr, false);
});
};
return this.reportOperationProgress(fileNames, moveFileFunction, callback);
},

_reflect: function (promise){
return promise.then(function(v){ return {};}, function(e){ return {};});
},

var mcSemaphore = new Semaphore(10);
reportOperationProgress: function (fileNames, operationFunction, callback){
var self = this;
self._operationProgressBar.showProgressBar(false);
var mcSemaphore = new OCA.Files.Semaphore(5);
var counter = 0;
var promises = _.map(fileNames, function(arg) {
return mcSemaphore.acquire().then(function(){
moveFileFunction(arg).then(function(){
return operationFunction(arg).always(function(){
mcSemaphore.release();
counter++;
self._operationProgressBar.setProgressBarValue(100.0*counter/fileNames.length);
});
});
});

return Promise.all(promises).then(function(){
return Promise.all(_.map(promises, self._reflect)).then(function(){
if (callback) {
callback();
}
self._operationProgressBar.hideProgressBar();
});
},

Expand All @@ -2385,7 +2389,7 @@
if (!_.isArray(fileNames)) {
fileNames = [fileNames];
}
_.each(fileNames, function(fileName) {
var copyFileFunction = function(fileName) {
var $tr = self.findFileEl(fileName);
self.showFileBusyState($tr, true);
if (targetPath.charAt(targetPath.length - 1) !== '/') {
Expand Down Expand Up @@ -2441,12 +2445,12 @@
}
}
}
self.filesClient.copy(dir + fileName, targetPathAndName)
return self.filesClient.copy(dir + fileName, targetPathAndName)
.done(function () {
filesToNotify.push(fileName);

// if still viewing the same directory
if (OC.joinPaths(self.getCurrentDirectory(), '/') === dir) {
if (OC.joinPaths(self.getCurrentDirectory(), '/') === OC.joinPaths(dir, '/')) {
// recalculate folder size
var oldFile = self.findFileEl(target);
var newFile = self.findFileEl(fileName);
Expand Down Expand Up @@ -2513,11 +2517,8 @@
}
}
});
});

if (callback) {
callback();
}
};
return this.reportOperationProgress(fileNames, copyFileFunction, callback);
},

/**
Expand Down Expand Up @@ -2939,53 +2940,45 @@
// delete all files in directory
files = _.pluck(this.files, 'name');
}
if (files) {
this.showFileBusyState(files, true);
}
// Finish any existing actions
if (this.lastAction) {
this.lastAction();
}

dir = dir || this.getCurrentDirectory();

function removeFromList(file) {
var fileEl = self.remove(file, {updateSummary: false});
// FIXME: not sure why we need this after the
// element isn't even in the DOM any more
fileEl.find('.selectCheckBox').prop('checked', false);
fileEl.removeClass('selected');
self.fileSummary.remove({type: fileEl.attr('data-type'), size: fileEl.attr('data-size')});
// TODO: this info should be returned by the ajax call!
self.updateEmptyContent();
self.fileSummary.update();
self.updateSelectionSummary();
// FIXME: don't repeat this, do it once all files are done
self.updateStorageStatistics();
self.updateStorageQuotas();
}

_.each(files, function(file) {
self.filesClient.remove(dir + '/' + file)
var removeFunction = function(fileName) {
var $tr = self.findFileEl(fileName);
self.showFileBusyState($tr, true);
return self.filesClient.remove(dir + '/' + fileName)
.done(function() {
removeFromList(file);
if (OC.joinPaths(self.getCurrentDirectory(), '/') === OC.joinPaths(dir, '/')) {
self.remove(fileName);
}
})
.fail(function(status) {
if (status === 404) {
// the file already did not exist, remove it from the list
removeFromList(file);
if (OC.joinPaths(self.getCurrentDirectory(), '/') === OC.joinPaths(dir, '/')) {
self.remove(fileName);
}
} else {
// only reset the spinner for that one file
OC.Notification.show(t('files', 'Error deleting file "{fileName}".',
{fileName: file}), {type: 'error'}
{fileName: fileName}), {type: 'error'}
);
var deleteAction = self.findFileEl(file).find('.action.delete');
deleteAction.removeClass('icon-loading-small').addClass('icon-delete');
self.showFileBusyState(files, false);
}
})
.always(function() {
self.showFileBusyState($tr, false);
});
});
};
return this.reportOperationProgress(files, removeFunction).then(function(){
self.updateStorageStatistics();
self.updateStorageQuotas();
});
},

/**
* Creates the file summary section
*/
Expand Down
Loading

0 comments on commit 6a3f4e4

Please sign in to comment.