mirror of
https://github.com/schlagmichdoch/PairDrop.git
synced 2025-04-21 15:26:17 -04:00
Tidy up code of progress animation and make it linear; Tidy up code of setting statusText for transfer notes
This commit is contained in:
parent
d70f9d762e
commit
3b772d0619
3 changed files with 111 additions and 102 deletions
|
@ -350,7 +350,7 @@ class Peer {
|
||||||
this._state = Peer.STATE_IDLE;
|
this._state = Peer.STATE_IDLE;
|
||||||
this._busy = false;
|
this._busy = false;
|
||||||
|
|
||||||
clearInterval(this._transferStatusInterval);
|
clearInterval(this._updateStatusTextInterval);
|
||||||
|
|
||||||
this._transferStatusInterval = null;
|
this._transferStatusInterval = null;
|
||||||
this._bytesTotal = 0;
|
this._bytesTotal = 0;
|
||||||
|
@ -646,23 +646,24 @@ class Peer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_setTransferStatus(status) {
|
_updateStatusText() {
|
||||||
const secondsSinceStart = Math.round((Date.now() - this._timeStartTransferComplete) / 1000);
|
const secondsSinceStart = Math.round((Date.now() - this._timeStartTransferComplete) / 1000);
|
||||||
|
|
||||||
// Wait for 10s to only show info on longer transfers and to increase precision
|
// Wait for 10s to only show info on longer transfers and to increase precision
|
||||||
if (secondsSinceStart < 10) return;
|
if (secondsSinceStart < 10) return;
|
||||||
|
|
||||||
// mode: 0 -> speed, 1 -> time left, 2 -> receive/transfer
|
// mode: 0 -> speed, 1 -> time left, 2 -> receive/transfer (statusText = null)
|
||||||
const mode = Math.round((secondsSinceStart - 10) / 5) % 3;
|
const mode = Math.round((secondsSinceStart - 10) / 5) % 3;
|
||||||
|
let statusText = null;
|
||||||
|
|
||||||
if (mode === 0) {
|
if (mode === 0) {
|
||||||
status = this._getSpeedString();
|
statusText = this._getSpeedString();
|
||||||
}
|
}
|
||||||
else if (mode === 1) {
|
else if (mode === 1) {
|
||||||
status = this._getTimeString();
|
statusText = this._getTimeString();
|
||||||
}
|
}
|
||||||
|
|
||||||
this._transferStatusString = status;
|
this._statusText = statusText;
|
||||||
}
|
}
|
||||||
|
|
||||||
_calculateSpeedKbPerSecond() {
|
_calculateSpeedKbPerSecond() {
|
||||||
|
@ -676,7 +677,7 @@ class Peer {
|
||||||
}
|
}
|
||||||
|
|
||||||
_calculateSecondsLeft() {
|
_calculateSecondsLeft() {
|
||||||
return Math.ceil(this._calculateBytesLeft() / this._calculateSpeedKbPerSecond() / 1000);
|
return Math.round(this._calculateBytesLeft() / this._calculateSpeedKbPerSecond() / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getSpeedString() {
|
_getSpeedString() {
|
||||||
|
@ -779,8 +780,8 @@ class Peer {
|
||||||
|
|
||||||
Events.fire('set-progress', {peerId: this._peerId, progress: 0, status: 'transfer'});
|
Events.fire('set-progress', {peerId: this._peerId, progress: 0, status: 'transfer'});
|
||||||
|
|
||||||
this._transferStatusString = 'transfer';
|
this._statusText = null;
|
||||||
this._transferStatusInterval = setInterval(() => this._setTransferStatus('transfer'), 1000);
|
this._updateStatusTextInterval = setInterval(() => this._updateStatusText(), 1000);
|
||||||
|
|
||||||
this._dequeueFile();
|
this._dequeueFile();
|
||||||
}
|
}
|
||||||
|
@ -823,7 +824,7 @@ class Peer {
|
||||||
|
|
||||||
this._addLog(bytesReceivedTotal);
|
this._addLog(bytesReceivedTotal);
|
||||||
|
|
||||||
Events.fire('set-progress', {peerId: this._peerId, progress: progress, status: this._transferStatusString});
|
Events.fire('set-progress', {peerId: this._peerId, progress: progress, status: 'transfer', statusText: this._statusText});
|
||||||
}
|
}
|
||||||
|
|
||||||
_onFileReceiveComplete(message) {
|
_onFileReceiveComplete(message) {
|
||||||
|
@ -918,7 +919,6 @@ class Peer {
|
||||||
this._byteLogs = [];
|
this._byteLogs = [];
|
||||||
this._filesReceived = [];
|
this._filesReceived = [];
|
||||||
this._acceptedRequest = this._pendingRequest;
|
this._acceptedRequest = this._pendingRequest;
|
||||||
this._lastProgress = 0;
|
|
||||||
|
|
||||||
this._bytesTotal = this._acceptedRequest.totalSize;
|
this._bytesTotal = this._acceptedRequest.totalSize;
|
||||||
this._bytesReceivedFiles = 0;
|
this._bytesReceivedFiles = 0;
|
||||||
|
@ -926,8 +926,8 @@ class Peer {
|
||||||
Events.fire('set-progress', {peerId: this._peerId, progress: 0, status: 'receive'});
|
Events.fire('set-progress', {peerId: this._peerId, progress: 0, status: 'receive'});
|
||||||
|
|
||||||
this._timeStartTransferComplete = Date.now();
|
this._timeStartTransferComplete = Date.now();
|
||||||
this._transferStatusString = 'receive';
|
this._statusText = null;
|
||||||
this._transferStatusInterval = setInterval(() => this._setTransferStatus('receive'), 1000);
|
this._updateStatusTextInterval = setInterval(() => this._updateStatusText(), 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._sendMessage(message);
|
this._sendMessage(message);
|
||||||
|
@ -966,7 +966,7 @@ class Peer {
|
||||||
|
|
||||||
this._addLog(bytesReceivedTotal);
|
this._addLog(bytesReceivedTotal);
|
||||||
|
|
||||||
Events.fire('set-progress', {peerId: this._peerId, progress: progress, status: this._transferStatusString});
|
Events.fire('set-progress', {peerId: this._peerId, progress: progress, status: 'receive', statusText: this._statusText});
|
||||||
}
|
}
|
||||||
|
|
||||||
_sendResendRequest(offset) {
|
_sendResendRequest(offset) {
|
||||||
|
|
|
@ -29,7 +29,7 @@ class PeersUI {
|
||||||
Events.on('peer-connecting', e => this._onPeerConnecting(e.detail));
|
Events.on('peer-connecting', e => this._onPeerConnecting(e.detail));
|
||||||
Events.on('peer-disconnected', e => this._onPeerDisconnected(e.detail));
|
Events.on('peer-disconnected', e => this._onPeerDisconnected(e.detail));
|
||||||
Events.on('peers', e => this._onPeers(e.detail));
|
Events.on('peers', e => this._onPeers(e.detail));
|
||||||
Events.on('set-progress', e => this._onSetProgress(e.detail.peerId, e.detail.progress, e.detail.status));
|
Events.on('set-progress', e => this._onSetProgress(e.detail.peerId, e.detail.progress, e.detail.status, e.detail.statusText));
|
||||||
|
|
||||||
Events.on('drop', e => this._onDrop(e));
|
Events.on('drop', e => this._onDrop(e));
|
||||||
Events.on('keydown', e => this._onKeyDown(e));
|
Events.on('keydown', e => this._onKeyDown(e));
|
||||||
|
@ -185,12 +185,12 @@ class PeersUI {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
_onSetProgress(peerId, progress, status) {
|
_onSetProgress(peerId, progress, status, statusText) {
|
||||||
const peerUI = this.peerUIs[peerId];
|
const peerUI = this.peerUIs[peerId];
|
||||||
|
|
||||||
if (!peerUI) return;
|
if (!peerUI) return;
|
||||||
|
|
||||||
peerUI.setProgressOrQueue(progress, status);
|
peerUI.queueProgressStatus(progress, status, statusText);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onDrop(e) {
|
_onDrop(e) {
|
||||||
|
@ -601,19 +601,19 @@ class PeerUI {
|
||||||
this._connected = true;
|
this._connected = true;
|
||||||
|
|
||||||
// on reconnect: reset status to saved status
|
// on reconnect: reset status to saved status
|
||||||
this.setStatus(this._oldStatus);
|
this.queueProgressStatus(null, this._oldStatus);
|
||||||
this._oldStatus = null;
|
this._oldStatus = 'idle';
|
||||||
|
|
||||||
this._connectionHash = connectionHash;
|
this._connectionHash = connectionHash;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this._connected = false;
|
this._connected = false;
|
||||||
|
|
||||||
// when connecting: / connection is lost: save old status
|
// when connecting: / connection is lost during transfer: save old status
|
||||||
if (!this._oldStatus && this._currentStatus !== "connect") {
|
if (this._isTransferringStatus(this._currentStatus)) {
|
||||||
this._oldStatus = this._currentStatus;
|
this._oldStatus = this._currentStatus;
|
||||||
this.setStatus("connect");
|
|
||||||
}
|
}
|
||||||
|
this.queueProgressStatus(null, "connect");
|
||||||
|
|
||||||
this._connectionHash = "";
|
this._connectionHash = "";
|
||||||
}
|
}
|
||||||
|
@ -688,71 +688,89 @@ class PeerUI {
|
||||||
$input.files = null; // reset input
|
$input.files = null; // reset input
|
||||||
}
|
}
|
||||||
|
|
||||||
setProgressOrQueue(progress, status) {
|
queueProgressStatus(progress = null, status = null, statusText = null) {
|
||||||
if (this._progressQueue.length > 0) {
|
clearTimeout(this._progressIdleTimeout);
|
||||||
if (progress) {
|
|
||||||
// if progress is higher than progress in queue -> overwrite in queue and cut queue at this position
|
// if progress is higher than progress in queue -> overwrite in queue and cut queue at this position
|
||||||
for (let i = 0; i < this._progressQueue.length; i++) {
|
for (let i = 0; i < this._progressQueue.length; i++) {
|
||||||
if (this._progressQueue[i].progress <= progress) {
|
if (this._progressQueue[i].progress <= progress && this._progressQueue[i].status === status) {
|
||||||
this._progressQueue[i].progress = progress;
|
this._progressQueue[i] = {progress, status, statusText};
|
||||||
this._progressQueue[i].status = status;
|
this._progressQueue.splice(i + 1);
|
||||||
this._progressQueue.splice(i + 1);
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// add to queue
|
}
|
||||||
this._progressQueue.push({progress: progress, status: status});
|
this._progressQueue.push({progress, status, statusText});
|
||||||
|
|
||||||
|
// only dequeue if not already dequeuing
|
||||||
|
if (this._progressAnimatingTimeout) return;
|
||||||
|
|
||||||
|
this.dequeueProgressStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
setNextProgressStatus() {
|
||||||
|
if (!this._progressQueue.length) {
|
||||||
|
// Queue is empty
|
||||||
|
this._progressAnimatingTimeout = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setProgress(progress, status);
|
// Queue is not empty -> set next progress
|
||||||
|
this.dequeueProgressStatus();
|
||||||
}
|
}
|
||||||
|
|
||||||
setNextProgress() {
|
dequeueProgressStatus() {
|
||||||
if (!this._progressQueue.length) return;
|
clearTimeout(this._progressAnimatingTimeout);
|
||||||
|
|
||||||
setTimeout(() => {
|
let {progress, status, statusText} = this._progressQueue.shift();
|
||||||
let next = this._progressQueue.shift()
|
|
||||||
this.setProgress(next.progress, next.status);
|
|
||||||
}, 250); // 200 ms animation + buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
setProgress(progress, status) {
|
// On complete status: set progress to 0 after 250ms and status to idle after 10s
|
||||||
this.setStatus(status);
|
if (this._isCompletedStatus(status)) {
|
||||||
|
this._progressQueue.unshift({progress: 0});
|
||||||
|
this._progressIdleTimeout = setTimeout(() => this.setStatus("idle"), 10000);
|
||||||
|
}
|
||||||
|
|
||||||
if (progress === null) return;
|
// After animation has finished -> set next progress in queue
|
||||||
|
this._progressAnimatingTimeout = setTimeout(() => this.setNextProgressStatus(), 250); // 200 ms animation + buffer
|
||||||
|
|
||||||
|
|
||||||
|
// Only change status if explicitly set
|
||||||
|
if (status) {
|
||||||
|
this.setStatus(status, statusText);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only change progress if explicitly set and differs from current
|
||||||
|
if (progress === null || progress === this._currentProgress) return;
|
||||||
|
|
||||||
const progressSpillsOverHalf = this._currentProgress < 0.5 && 0.5 < progress; // 0.5 slips through
|
const progressSpillsOverHalf = this._currentProgress < 0.5 && 0.5 < progress; // 0.5 slips through
|
||||||
const progressSpillsOverFull = progress <= 0.5 && 0.5 <= this._currentProgress && this._currentProgress < 1;
|
const progressSpillsOverFull = progress <= 0.5 && 0.5 <= this._currentProgress && this._currentProgress < 1;
|
||||||
|
|
||||||
|
// If spills over half: go to 0.5 first
|
||||||
|
// If spills over full: go to 1 first
|
||||||
if (progressSpillsOverHalf) {
|
if (progressSpillsOverHalf) {
|
||||||
this._progressQueue.unshift({progress: progress, status: status});
|
this._progressQueue.unshift({progress: 0.5}, {progress: progress});
|
||||||
this.setProgress(0.5, status);
|
this.dequeueProgressStatus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (progressSpillsOverFull) {
|
else if (progressSpillsOverFull) {
|
||||||
this._progressQueue.unshift({progress: progress, status: status});
|
this._progressQueue.unshift({progress: 1}, {progress: progress});
|
||||||
this.setProgress(1, status);
|
this.dequeueProgressStatus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progress === 0) {
|
// Clear progress after setting it to 1
|
||||||
this._currentProgress = 0;
|
if (progress === 1) {
|
||||||
this.$progress.classList.remove('animate');
|
this._progressQueue.unshift({progress: 0});
|
||||||
this.$progress.classList.remove('over50');
|
}
|
||||||
this.$progress.style.setProperty('--progress', `rotate(${360 * progress}deg)`);
|
|
||||||
this.setNextProgress();
|
// Set progress to 1 before setting to 0 if not error
|
||||||
return;
|
if (progress === 0 && this._currentProgress !== 1 && status !== 'error') {
|
||||||
}
|
this._progressQueue.unshift({progress: 1});
|
||||||
|
this.dequeueProgressStatus();
|
||||||
if (progress < this._currentProgress && status !== this._currentStatus) {
|
|
||||||
// reset progress
|
|
||||||
this._progressQueue.unshift({progress: progress, status: status});
|
|
||||||
this.setProgress(0, status);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// under 0.5 -> remove second circle
|
||||||
|
// over 0.5 -> add second circle
|
||||||
if (progress < 0.5) {
|
if (progress < 0.5) {
|
||||||
this.$progress.classList.remove('animate');
|
this.$progress.classList.remove('animate');
|
||||||
this.$progress.classList.remove('over50');
|
this.$progress.classList.remove('over50');
|
||||||
|
@ -764,62 +782,53 @@ class PeerUI {
|
||||||
this.$progress.classList.add('animate');
|
this.$progress.classList.add('animate');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progress > this._currentProgress) {
|
// Do not animate when setting progress to lower value
|
||||||
this.$progress.classList.add('animate');
|
if (progress < this._currentProgress && this._currentProgress === 1) {
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.$progress.classList.remove('animate');
|
this.$progress.classList.remove('animate');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (progress === 1) {
|
// If document is in background do not animate to prevent flickering on focus
|
||||||
// reset progress
|
if (!document.hasFocus()) {
|
||||||
this._progressQueue.unshift({progress: 0, status: status});
|
this.$progress.classList.remove('animate');
|
||||||
}
|
}
|
||||||
|
|
||||||
this._currentProgress = progress;
|
this._currentProgress = progress;
|
||||||
this.$progress.style.setProperty('--progress', `rotate(${360 * progress}deg)`);
|
this.$progress.style.setProperty('--progress', `rotate(${360 * progress}deg)`);
|
||||||
|
|
||||||
this.setNextProgress();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setStatus(status) {
|
setStatus(status, statusText = null) {
|
||||||
if (status === this._currentStatus) return;
|
|
||||||
|
|
||||||
this._currentStatus = status;
|
this._currentStatus = status;
|
||||||
|
|
||||||
clearTimeout(this.statusTimeout);
|
|
||||||
|
|
||||||
if (status === 'idle') {
|
if (status === 'idle') {
|
||||||
this.$el.removeAttribute('status');
|
this.$el.removeAttribute('status');
|
||||||
this.$el.querySelector('.status').innerText = '';
|
this.$el.querySelector('.status').innerText = '';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let statusText = {
|
if (!statusText) {
|
||||||
"connect": Localization.getTranslation("peer-ui.connecting"),
|
statusText = {
|
||||||
"prepare": Localization.getTranslation("peer-ui.preparing"),
|
"connect": Localization.getTranslation("peer-ui.connecting"),
|
||||||
"transfer": Localization.getTranslation("peer-ui.transferring"),
|
"prepare": Localization.getTranslation("peer-ui.preparing"),
|
||||||
"receive": Localization.getTranslation("peer-ui.receiving"),
|
"transfer": Localization.getTranslation("peer-ui.transferring"),
|
||||||
"process": Localization.getTranslation("peer-ui.processing"),
|
"receive": Localization.getTranslation("peer-ui.receiving"),
|
||||||
"wait": Localization.getTranslation("peer-ui.waiting"),
|
"process": Localization.getTranslation("peer-ui.processing"),
|
||||||
"transfer-complete": Localization.getTranslation("peer-ui.transfer-complete"),
|
"wait": Localization.getTranslation("peer-ui.waiting"),
|
||||||
"receive-complete": Localization.getTranslation("peer-ui.receive-complete"),
|
"transfer-complete": Localization.getTranslation("peer-ui.transfer-complete"),
|
||||||
"error": Localization.getTranslation("peer-ui.error")
|
"receive-complete": Localization.getTranslation("peer-ui.receive-complete"),
|
||||||
}[status];
|
"error": Localization.getTranslation("peer-ui.error")
|
||||||
|
}[status];
|
||||||
if (statusText) {
|
|
||||||
this.$el.setAttribute('status', status);
|
|
||||||
this.$el.querySelector('.status').innerText = statusText;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.$el.querySelector('.status').innerText = status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status.endsWith("-complete") || status === "error") {
|
this.$el.setAttribute('status', status);
|
||||||
this.statusTimeout = setTimeout(() => {
|
this.$el.querySelector('.status').innerText = statusText;
|
||||||
this.setStatus("idle");
|
}
|
||||||
}, 10000);
|
|
||||||
}
|
_isCompletedStatus(status) {
|
||||||
|
return status && (status.endsWith("-complete") || status === "error")
|
||||||
|
}
|
||||||
|
|
||||||
|
_isTransferringStatus(status) {
|
||||||
|
return status !== "connect" && !this._isCompletedStatus(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onDrop(e) {
|
_onDrop(e) {
|
||||||
|
|
|
@ -769,7 +769,7 @@ x-dialog .dialog-subheader {
|
||||||
}
|
}
|
||||||
|
|
||||||
.animate .circle {
|
.animate .circle {
|
||||||
transition: transform 200ms;
|
transition: transform 200ms linear;
|
||||||
}
|
}
|
||||||
|
|
||||||
.over50 {
|
.over50 {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue