diff --git a/public/index.html b/public/index.html
index cf286cc..290fd01 100644
--- a/public/index.html
+++ b/public/index.html
@@ -216,7 +216,7 @@
- File Transfer Completed
+
diff --git a/public/scripts/network.js b/public/scripts/network.js
index 55bce53..6ccbf17 100644
--- a/public/scripts/network.js
+++ b/public/scripts/network.js
@@ -12,7 +12,7 @@ class ServerConnection {
Events.on('beforeunload', _ => this._disconnect());
Events.on('pagehide', _ => this._disconnect());
document.addEventListener('visibilitychange', _ => this._onVisibilityChange());
- if (navigator.connection) navigator.connection.addEventListener('change', _ => this._disconnect());
+ if (navigator.connection) navigator.connection.addEventListener('change', _ => this._reconnect());
Events.on('reconnect', _ => this._reconnect());
Events.on('room-secrets', e => this._sendRoomSecrets(e.detail));
Events.on('room-secret-deleted', e => this.send({ type: 'room-secret-deleted', roomSecret: e.detail}));
@@ -152,9 +152,10 @@ class ServerConnection {
_onDisconnect() {
console.log('WS: server disconnected');
- Events.fire('notify-user', 'Connection lost. Retrying...');
+ Events.fire('notify-user', 'Server connection lost. Retrying...');
clearTimeout(this._reconnectTimer);
- this._reconnectTimer = setTimeout(_ => this._connect(), 1000);
+ this._reconnectTimer = setTimeout(_ => this._connect(), 5000);
+ this._connect();
Events.fire('ws-disconnected');
}
@@ -298,8 +299,6 @@ class Peer {
}
async sendFiles() {
- console.debug("sendFiles")
- console.debug(this.zipFileRequested);
this._filesQueue.push({zipFile: this.zipFileRequested, fileHeader: this._fileHeaderRequested});
this._fileHeaderRequested = null
if (this._busy) return;
@@ -429,7 +428,7 @@ class Peer {
}
async _onFileReceived(zipBlob, fileHeader) {
- Events.fire('set-progress', {peerId: this._peerId, progress: 0, status: 'wait'});
+ Events.fire('set-progress', {peerId: this._peerId, progress: 0, status: 'process'});
this._busy = false;
this.sendJSON({type: 'file-transfer-complete'});
@@ -563,9 +562,17 @@ class RTCPeer extends Peer {
channel.binaryType = 'arraybuffer';
channel.onmessage = e => this._onMessage(e.data);
channel.onclose = _ => this._onChannelClosed();
+ Events.on('beforeunload', _ => this._closeChannel());
+ Events.on('pagehide', _ => this._closeChannel());
this._channel = channel;
}
+ _closeChannel() {
+ this._channel.onclose = null;
+ this._conn.close();
+ this._conn = null;
+ }
+
_onChannelClosed() {
console.log('RTC: channel closed', this._peerId);
Events.fire('peer-disconnected', this._peerId);
@@ -603,7 +610,7 @@ class RTCPeer extends Peer {
}
_send(message) {
- if (!this._channel) return this.refresh();
+ if (!this._channel) this.refresh();
this._channel.send(message);
}
@@ -617,8 +624,6 @@ class RTCPeer extends Peer {
refresh() {
// check if channel is open. otherwise create one
- console.debug("refresh:");
- console.debug(this._conn);
if (this._isConnected() || this._isConnecting()) return;
this._connect(this._peerId, this._isCaller);
}
@@ -652,8 +657,7 @@ class PeersManager {
Events.on('respond-to-files-transfer-request', e => this._onRespondToFileTransferRequest(e.detail))
Events.on('send-text', e => this._onSendText(e.detail));
Events.on('peer-joined', e => this._onPeerJoined(e.detail));
- Events.on('peer-left', e => this._onPeerLeft(e.detail));
- Events.on('ws-disconnected', _ => this._clearPeers());
+ Events.on('peer-disconnected', e => this._onPeerLeft(e.detail));
Events.on('secret-room-deleted', e => this._onSecretRoomDeleted(e.detail));
}
@@ -699,20 +703,15 @@ class PeersManager {
}
_onFilesSelected(message) {
- const files = this._addTypeIfMissing(message.files);
- this.peers[message.to].requestFileTransfer(files);
- }
-
- _addTypeIfMissing(files) {
- let filesWithType = [], file;
- for (let i=0; i this._onPeerLeft(peerId));
- }
- }
-
_onSecretRoomDeleted(roomSecret) {
for (const peerId in this.peers) {
const peer = this.peers[peerId];
diff --git a/public/scripts/ui.js b/public/scripts/ui.js
index 558affa..d18794e 100644
--- a/public/scripts/ui.js
+++ b/public/scripts/ui.js
@@ -19,14 +19,12 @@ class PeersUI {
constructor() {
Events.on('peer-joined', e => this._onPeerJoined(e.detail));
- Events.on('peer-left', e => this._onPeerLeft(e.detail));
Events.on('peer-connected', e => this._onPeerConnected(e.detail));
Events.on('peer-disconnected', e => this._onPeerDisconnected(e.detail));
Events.on('peers', e => this._onPeers(e.detail));
Events.on('set-progress', e => this._onSetProgress(e.detail));
Events.on('paste', e => this._onPaste(e));
- Events.on('ws-disconnected', _ => this._clearPeers());
- Events.on('secret-room-deleted', _ => this._clearPeers('secret'));
+ Events.on('secret-room-deleted', e => this._onSecretRoomDeleted(e.detail));
Events.on('activate-paste-mode', e => this._activatePasteMode(e.detail.files, e.detail.text));
this.peers = {};
@@ -88,16 +86,11 @@ class PeersUI {
if ($$('x-peers:empty')) setTimeout(_ => window.animateBackground(true), 1750); // Start animation again
}
- _onPeerLeft(peerId) {
- this._onPeerDisconnected(peerId);
- delete this.peers[peerId];
- }
-
_onSecretRoomDeleted(roomSecret) {
for (const peerId in this.peers) {
const peer = this.peers[peerId];
if (peer.roomSecret === roomSecret) {
- this._onPeerLeft(peerId);
+ this._onPeerDisconnected(peerId);
}
}
}
@@ -108,16 +101,6 @@ class PeersUI {
$peer.ui.setProgress(progress.progress, progress.status)
}
- _clearPeers(roomType = 'all') {
- for (const peerId in this.peers) {
- if (roomType === 'all' || this.peers[peerId].roomType === roomType) {
- const peerNode = $(peerId);
- if(peerNode) peerNode.remove();
- delete this.peers[peerId];
- }
- }
- }
-
_onDrop(e) {
e.preventDefault();
if (!$$('x-peer') || !$$('x-peer').contains(e.target)) {
@@ -429,7 +412,7 @@ class Dialog {
this.$el = $(id);
this.$el.querySelectorAll('[close]').forEach(el => el.addEventListener('click', _ => this.hide()))
this.$autoFocus = this.$el.querySelector('[autofocus]');
- if (hideOnDisconnect) Events.on('ws-disconnected', _ => this.hide());
+ if (hideOnDisconnect) Events.on('peer-disconnected', e => this._onPeerDisconnected(e.detail));
}
show() {
@@ -445,6 +428,14 @@ class Dialog {
}
document.title = 'PairDrop';
document.changeFavicon("images/favicon-96x96.png");
+ if (this.correspondingPeerId) setTimeout(_ => this.correspondingPeerId = undefined, 300);
+ }
+
+ _onPeerDisconnected(peerId) {
+ if (this.correspondingPeerId && this.correspondingPeerId === peerId) {
+ this.hide();
+ Events.fire('notify-user', 'Selected peer left.')
+ }
}
}
@@ -600,7 +591,7 @@ class ReceiveFileDialog extends ReceiveDialog {
Events.fire('set-progress', {
peerId: peerId,
progress: 1,
- status: 'wait'
+ status: 'process'
})
this.$shareOrDownloadBtn.click();
}).catch(r => console.error(r));
@@ -631,8 +622,6 @@ class ReceiveRequestDialog extends ReceiveDialog {
this.$declineRequestBtn.addEventListener('click', _ => this._respondToFileTransferRequest(false));
Events.on('files-transfer-request', e => this._onRequestFileTransfer(e.detail.request, e.detail.peerId))
- Events.on('peer-left', e => this._onPeerDisconnectedOrLeft(e.detail))
- Events.on('peer-disconnected', e => this._onPeerDisconnectedOrLeft(e.detail))
Events.on('keydown', e => this._onKeyDown(e));
}
@@ -643,15 +632,8 @@ class ReceiveRequestDialog extends ReceiveDialog {
}
}
- _onPeerDisconnectedOrLeft(peerId) {
- if (peerId === this.requestingPeerId) {
- this._respondToFileTransferRequest(false)
- this.hide();
- }
- }
-
_onRequestFileTransfer(request, peerId) {
- this.requestingPeerId = peerId;
+ this.correspondingPeerId = peerId;
this.requestedHeader = request.header;
const peer = $(peerId);
@@ -693,13 +675,12 @@ class ReceiveRequestDialog extends ReceiveDialog {
_respondToFileTransferRequest(accepted) {
Events.fire('respond-to-files-transfer-request', {
- to: this.requestingPeerId,
+ to: this.correspondingPeerId,
header: this.requestedHeader,
accepted: accepted
})
- this.requestingPeerId = null;
if (accepted) {
- Events.fire('set-progress', {peerId: this._peerId, progress: 0, status: 'wait'});
+ Events.fire('set-progress', {peerId: this.correspondingPeerId, progress: 0, status: 'wait'});
NoSleepUI.enable();
}
}
@@ -732,6 +713,7 @@ class PairDeviceDialog extends Dialog {
Events.on('keydown', e => this._onKeyDown(e));
Events.on('ws-connected', _ => this._onWsConnected());
+ Events.on('ws-disconnected', _ => this.hide());
Events.on('pair-device-initiated', e => this._pairDeviceInitiated(e.detail));
Events.on('pair-device-joined', e => this._pairDeviceJoined(e.detail));
Events.on('pair-device-join-key-invalid', _ => this._pairDeviceJoinKeyInvalid());
@@ -976,8 +958,8 @@ class SendTextDialog extends Dialog {
}
}
- _onRecipient(recipient) {
- this._recipient = recipient;
+ _onRecipient(peerId) {
+ this.correspondingPeerId = peerId;
this.show();
const range = document.createRange();
@@ -991,7 +973,7 @@ class SendTextDialog extends Dialog {
_send() {
Events.fire('send-text', {
- to: this._recipient,
+ to: this.correspondingPeerId,
text: this.$text.innerText
});
this.$text.value = "";
@@ -1096,13 +1078,14 @@ class Base64ZipDialog extends Dialog {
class Toast extends Dialog {
constructor() {
super('toast');
- Events.on('notify-user', e => this._onNotifiy(e.detail));
+ Events.on('notify-user', e => this._onNotify(e.detail));
}
- _onNotifiy(message) {
+ _onNotify(message) {
+ if (this.hideTimeout) clearTimeout(this.hideTimeout);
this.$el.textContent = message;
this.show();
- setTimeout(_ => this.hide(), 3000);
+ this.hideTimeout = setTimeout(_ => this.hide(), 3000);
}
}
diff --git a/public/service-worker.js b/public/service-worker.js
index 3870f54..2f22f8e 100644
--- a/public/service-worker.js
+++ b/public/service-worker.js
@@ -1,17 +1,23 @@
-var CACHE_NAME = 'pairdrop-cache-v4';
-var urlsToCache = [
- 'index.html',
- './',
- 'styles.css',
- 'scripts/network.js',
- 'scripts/ui.js',
- 'scripts/util.js',
- 'scripts/qrcode.js',
- 'scripts/zip.min.js',
- 'scripts/NoSleep.min.js',
- 'scripts/theme.js',
- 'sounds/blop.mp3',
- 'images/favicon-96x96.png'
+const CACHE_NAME = 'pairdrop-cache-v4';
+const urlsToCache = [
+ 'index.html',
+ './',
+ 'styles.css',
+ 'scripts/network.js',
+ 'scripts/ui.js',
+ 'scripts/util.js',
+ 'scripts/qrcode.js',
+ 'scripts/zip.min.js',
+ 'scripts/NoSleep.min.js',
+ 'scripts/theme.js',
+ 'sounds/blop.mp3',
+ 'images/favicon-96x96.png',
+ 'images/favicon-96x96-notification.png',
+ 'images/android-chrome-192x192.png',
+ 'images/android-chrome-192x192-maskable.png',
+ 'images/android-chrome-512x512.png',
+ 'images/android-chrome-512x512-maskable.png',
+ 'images/apple-touch-icon.png',
];
self.addEventListener('install', function(event) {
diff --git a/public/styles.css b/public/styles.css
index 78e44f4..a2289a4 100644
--- a/public/styles.css
+++ b/public/styles.css
@@ -320,6 +320,10 @@ x-peer[status=wait] .status:before {
content: 'Waiting...';
}
+x-peer[status=process] .status:before {
+ content: 'Processing...';
+}
+
x-peer:not([status]) .status,
x-peer[status] .device-name {
display: none;
@@ -527,6 +531,8 @@ x-dialog .row-reverse {
max-width: 80%;
overflow: hidden;
text-overflow: ellipsis;
+ word-break: break-all;
+ max-height: 1rem;
}
.file-size{