mirror of
https://github.com/nextcloud/server.git
synced 2026-05-19 16:39:59 -04:00
Smooth time remaining, bitrate and stabilize user information
Besides the existing moving average, a smoothing factor is introduced for the time remaining display as well as the bitrate. Furthermore, half of the buffer needs to be filled before the first prediction is displayed to the user. This reduces volatile and jumping durations towards the user and improves usability. Signed-off-by: Cyrill H. <phlogi@posteo.de> Co-authored-by: Carl Schwan <carl@carlschwan.eu>
This commit is contained in:
parent
722bbf642b
commit
baa1573a99
1 changed files with 40 additions and 14 deletions
|
|
@ -955,6 +955,7 @@ OC.Uploader.prototype = _.extend({
|
|||
type: 'PUT',
|
||||
dropZone: options.dropZone, // restrict dropZone to content div
|
||||
autoUpload: false,
|
||||
progressInterval: 300, // increased from the default of 100ms for more stable behvaviour when predicting remaining time
|
||||
sequentialUploads: false,
|
||||
limitConcurrentUploads: 4,
|
||||
/**
|
||||
|
|
@ -1197,7 +1198,7 @@ OC.Uploader.prototype = _.extend({
|
|||
|
||||
if (this._supportAjaxUploadWithProgress()) {
|
||||
//remaining time
|
||||
var lastUpdate, lastSize, bufferSize, buffer, bufferIndex, bufferIndex2, bufferTotal;
|
||||
var lastUpdate, lastSize, bufferSize, buffer, bufferIndex, bufferTotal, smoothRemainingSeconds, smoothBitrate;
|
||||
|
||||
var dragging = false;
|
||||
|
||||
|
|
@ -1215,11 +1216,15 @@ OC.Uploader.prototype = _.extend({
|
|||
// initial remaining time variables
|
||||
lastUpdate = new Date().getTime();
|
||||
lastSize = 0;
|
||||
bufferSize = 20;
|
||||
bufferSize = 20; // length of the ring buffer
|
||||
buffer = [];
|
||||
bufferIndex = 0;
|
||||
bufferIndex2 = 0;
|
||||
bufferIndex = 0; // index of the ring buffer, runs from 0 to bufferSize continuously
|
||||
bufferTotal = 0;
|
||||
newTotal = 0;
|
||||
smoothing = 0.02; // smoothing factor for EMA
|
||||
h = '';
|
||||
bufferFilled = false;
|
||||
|
||||
for(var i = 0; i < bufferSize; i++){
|
||||
buffer[i] = 0;
|
||||
}
|
||||
|
|
@ -1238,33 +1243,54 @@ OC.Uploader.prototype = _.extend({
|
|||
var diffUpdate = (thisUpdate - lastUpdate)/1000; // eg. 2s
|
||||
lastUpdate = thisUpdate;
|
||||
var diffSize = data.loaded - lastSize;
|
||||
if (diffSize <= 0) {
|
||||
diffSize = lastSize;
|
||||
}
|
||||
lastSize = data.loaded;
|
||||
diffSize = diffSize / diffUpdate; // apply timing factor, eg. 1MiB/2s = 0.5MiB/s, unit is byte per second
|
||||
var remainingSeconds = ((total - data.loaded) / diffSize);
|
||||
|
||||
if(remainingSeconds >= 0) {
|
||||
// bufferTotal holds the sum of all entries in the buffer, initially 0 like the entries itself
|
||||
// substract current entry from total and add the current value to total
|
||||
bufferTotal = bufferTotal - (buffer[bufferIndex]) + remainingSeconds;
|
||||
// put current value to the entry
|
||||
buffer[bufferIndex] = remainingSeconds; //buffer to make it smoother
|
||||
|
||||
bufferIndex = (bufferIndex + 1) % bufferSize;
|
||||
bufferIndex2++;
|
||||
}
|
||||
var smoothRemainingSeconds;
|
||||
if (bufferIndex2 > 0 && bufferIndex2 < 20) {
|
||||
smoothRemainingSeconds = bufferTotal / bufferIndex2;
|
||||
} else if (bufferSize > 0) {
|
||||
if (bufferIndex === bufferSize - 1) {
|
||||
bufferFilled = true;
|
||||
}
|
||||
//console.log('#', ' idx: ',bufferIndex, ' Total: ', bufferTotal, ' remainSeconds: ', remainingSeconds, ' during: ', diffUpdate);
|
||||
|
||||
if (smoothRemainingSeconds === null) {
|
||||
smoothRemainingSeconds = bufferTotal / bufferSize;
|
||||
} else {
|
||||
smoothRemainingSeconds = 1;
|
||||
} else{
|
||||
smoothRemainingSeconds = smoothing * (bufferTotal / bufferSize) + ((1-smoothing) * smoothRemainingSeconds);
|
||||
}
|
||||
|
||||
var h = moment.duration(smoothRemainingSeconds, "seconds").humanize();
|
||||
if (!(smoothRemainingSeconds >= 0 && smoothRemainingSeconds < 14400)) {
|
||||
if (bufferIndex % 4 === 0) {
|
||||
h = moment.duration(smoothRemainingSeconds, "seconds").humanize({m: 50, h: 50});
|
||||
}
|
||||
|
||||
// wait for the buffer to be at least half filled, approximately takes 3s
|
||||
if (!(smoothRemainingSeconds >= 0 && smoothRemainingSeconds < 14400) || (bufferFilled == false && bufferIndex < bufferSize/2)) {
|
||||
// show "Uploading ..." for durations longer than 4 hours
|
||||
h = t('files', 'Uploading …');
|
||||
}
|
||||
|
||||
// smooth bitrate
|
||||
if (smoothBitrate === null) {
|
||||
smoothBitrate = data.bitrate;
|
||||
} else{
|
||||
smoothBitrate = smoothing * data.bitrate + ((1-smoothing) * smoothBitrate);
|
||||
}
|
||||
|
||||
self._setProgressBarText(h, h, t('files', '{loadedSize} of {totalSize} ({bitrate})' , {
|
||||
loadedSize: OC.Util.humanFileSize(data.loaded),
|
||||
totalSize: OC.Util.humanFileSize(total),
|
||||
bitrate: OC.Util.humanFileSize(data.bitrate / 8) + '/s'
|
||||
bitrate: OC.Util.humanFileSize(smoothBitrate / 8) + '/s'
|
||||
}));
|
||||
self._setProgressBarValue(progress);
|
||||
self.trigger('progressall', e, data);
|
||||
|
|
|
|||
Loading…
Reference in a new issue