implement auto_accept (#91) and manual unpairing via new Edit Paired Devices Dialog and a BrowserTabsConnector

This commit is contained in:
schlagmichdoch 2023-05-04 17:38:51 +02:00
parent 0ac3c5a11f
commit 241ea4f988
11 changed files with 1442 additions and 441 deletions

View file

@ -50,7 +50,7 @@ class PeersUI {
this.$displayName.addEventListener('blur', e => this._saveDisplayName(e.target.innerText));
Events.on('self-display-name-changed', e => this._insertDisplayName(e.detail));
Events.on('peer-display-name-changed', e => this._changePeerDisplayName(e.detail.peerId, e.detail.displayName));
Events.on('peer-display-name-changed', e => this._onPeerDisplayNameChanged(e));
// Load saved display name on page load
this._getSavedDisplayName().then(displayName => {
@ -87,26 +87,31 @@ class PeersUI {
if (newDisplayName === savedDisplayName) return;
if (newDisplayName) {
PersistentStorage.set('editedDisplayName', newDisplayName).then(_ => {
Events.fire('notify-user', 'Device name is changed permanently.');
}).catch(_ => {
console.log("This browser does not support IndexedDB. Use localStorage instead.");
localStorage.setItem('editedDisplayName', newDisplayName);
Events.fire('notify-user', 'Device name is changed only for this session.');
}).finally(_ => {
Events.fire('self-display-name-changed', newDisplayName);
Events.fire('broadcast-send', {type: 'self-display-name-changed', detail: newDisplayName});
});
PersistentStorage.set('editedDisplayName', newDisplayName)
.then(_ => {
Events.fire('notify-user', 'Device name is changed permanently.');
})
.catch(_ => {
console.log("This browser does not support IndexedDB. Use localStorage instead.");
localStorage.setItem('editedDisplayName', newDisplayName);
Events.fire('notify-user', 'Device name is changed only for this session.');
})
.finally(_ => {
Events.fire('self-display-name-changed', newDisplayName);
Events.fire('broadcast-send', {type: 'self-display-name-changed', detail: newDisplayName});
});
} else {
PersistentStorage.delete('editedDisplayName').catch(_ => {
console.log("This browser does not support IndexedDB. Use localStorage instead.")
localStorage.removeItem('editedDisplayName');
Events.fire('notify-user', 'Random Display name is used again.');
}).finally(_ => {
Events.fire('notify-user', 'Device name is randomly generated again.');
Events.fire('self-display-name-changed', '');
Events.fire('broadcast-send', {type: 'self-display-name-changed', detail: ''});
});
PersistentStorage.delete('editedDisplayName')
.catch(_ => {
console.log("This browser does not support IndexedDB. Use localStorage instead.")
localStorage.removeItem('editedDisplayName');
Events.fire('notify-user', 'Random Display name is used again.');
})
.finally(_ => {
Events.fire('notify-user', 'Device name is randomly generated again.');
Events.fire('self-display-name-changed', '');
Events.fire('broadcast-send', {type: 'self-display-name-changed', detail: ''});
});
}
}
@ -129,6 +134,12 @@ class PeersUI {
this.peers[peerId].name.displayName = displayName;
const peerIdNode = $(peerId);
if (peerIdNode && displayName) peerIdNode.querySelector('.name').textContent = displayName;
this._redrawPeerRoomTypes(peerId);
}
_onPeerDisplayNameChanged(e) {
if (!e.detail.displayName) return;
this._changePeerDisplayName(e.detail.peerId, e.detail.displayName);
}
_onKeyDown(e) {
@ -142,26 +153,43 @@ class PeersUI {
}
_joinPeer(peer, roomType, roomSecret) {
const existingPeer = this.peers[peer.id];
if (existingPeer) {
// peer already exists. Abort but add roomType to GUI and update roomSecret
// skip if peer is a tab on the same browser
if (!existingPeer.sameBrowser()) {
// add roomType to PeerUI
if (!existingPeer.roomTypes.includes(roomType)) {
existingPeer.roomTypes.push(roomType);
}
this._redrawPeerRoomTypes(peer.id);
if (roomType === "secret") existingPeer.roomSecret = roomSecret;
}
return;
}
peer.sameBrowser = _ => BrowserTabsConnector.peerIsSameBrowser(peer.id);
peer.roomTypes = [roomType];
peer.roomSecret = roomSecret;
if (this.peers[peer.id]) {
if (!this.peers[peer.id].roomTypes.includes(roomType)) this.peers[peer.id].roomTypes.push(roomType);
this._redrawPeer(this.peers[peer.id]);
return; // peer already exists
}
this.peers[peer.id] = peer;
}
_onPeerConnected(peerId, connectionHash) {
if(this.peers[peerId] && !$(peerId))
new PeerUI(this.peers[peerId], connectionHash);
if (!this.peers[peerId] || $(peerId)) return;
const peer = this.peers[peerId];
new PeerUI(peer, connectionHash);
}
_redrawPeer(peer) {
const peerNode = $(peer.id);
_redrawPeerRoomTypes(peerId) {
const peer = this.peers[peerId]
const peerNode = $(peerId);
if (!peerNode) return;
peerNode.classList.remove('type-ip', 'type-secret');
peer.roomTypes.forEach(roomType => peerNode.classList.add(`type-${roomType}`));
if (!peer.sameBrowser()) {
peer.roomTypes.forEach(roomType => peerNode.classList.add(`type-${roomType}`));
}
}
evaluateOverflowing() {
@ -187,7 +215,17 @@ class PeersUI {
for (const peerId in this.peers) {
const peer = this.peers[peerId];
if (peer.roomSecret === roomSecret) {
let index = peer.roomTypes.indexOf('secret');
peer.roomTypes.splice(index, 1);
peer.roomSecret = "";
if (peer.roomTypes.length) {
this._redrawPeerRoomTypes(peerId)
return;
}
this._onPeerDisconnected(peerId);
return;
}
}
}
@ -364,8 +402,9 @@ class PeerUI {
this.$el = document.createElement('x-peer');
this.$el.id = this._peer.id;
this.$el.ui = this;
this._peer.roomTypes.forEach(roomType => this.$el.classList.add(`type-${roomType}`));
this.$el.classList.add('center');
if (!this._peer.sameBrowser()) this._peer.roomTypes.forEach(roomType => this.$el.classList.add(`type-${roomType}`));
if (!this._peer.rtcSupported || !window.isRtcSupported) this.$el.classList.add('ws-peer');
this.html();
this._callbackInput = e => this._onFilesSelected(e)
@ -862,8 +901,12 @@ class ReceiveRequestDialog extends ReceiveDialog {
}
hide() {
this.$previewBox.innerHTML = '';
// clear previewBox after dialog is closed
setTimeout(_ => this.$previewBox.innerHTML = '', 300);
super.hide();
// show next request
setTimeout(_ => this._dequeueRequests(), 500);
}
}
@ -876,7 +919,7 @@ class PairDeviceDialog extends Dialog {
this.$roomKey = this.$el.querySelector('#room-key');
this.$qrCode = this.$el.querySelector('#room-key-qr-code');
this.$pairDeviceBtn = $('pair-device');
this.$clearSecretsBtn = $('clear-pair-devices');
this.$editPairedDevicesBtn = $('edit-paired-devices');
this.$footerInstructionsPairedDevices = $('and-by-paired-devices');
this.$createJoinForm = this.$el.querySelector('form');
@ -896,7 +939,7 @@ class PairDeviceDialog extends Dialog {
Events.on('pair-device-joined', e => this._pairDeviceJoined(e.detail.peerId, e.detail.roomSecret));
Events.on('pair-device-join-key-invalid', _ => this._pairDeviceJoinKeyInvalid());
Events.on('pair-device-canceled', e => this._pairDeviceCanceled(e.detail));
Events.on('clear-room-secrets', e => this._onClearRoomSecrets(e.detail))
Events.on('evaluate-number-room-secrets', _ => this._evaluateNumberRoomSecrets())
Events.on('secret-room-deleted', e => this._onSecretRoomDeleted(e.detail));
this.$el.addEventListener('paste', e => this._onPaste(e));
@ -978,7 +1021,7 @@ class PairDeviceDialog extends Dialog {
PersistentStorage.getAllRoomSecrets().then(roomSecrets => {
Events.fire('room-secrets', roomSecrets);
this._evaluateNumberRoomSecrets();
}).catch(_ => PersistentStorage.logBrowserNotCapable());
});
}
_pairDeviceInitiate() {
@ -1027,19 +1070,34 @@ class PairDeviceDialog extends Dialog {
_pairDeviceJoined(peerId, roomSecret) {
this.hide();
PersistentStorage.addRoomSecret(roomSecret).then(_ => {
Events.fire('notify-user', 'Devices paired successfully.');
const oldRoomSecret = $(peerId).ui.roomSecret;
if (oldRoomSecret) PersistentStorage.deleteRoomSecret(oldRoomSecret);
$(peerId).ui.roomSecret = roomSecret;
this._evaluateNumberRoomSecrets();
}).finally(_ => {
// skip adding to IndexedDB if peer is another tab on the same browser
if (BrowserTabsConnector.peerIsSameBrowser(peerId)) {
this._cleanUp();
})
.catch(_ => {
Events.fire('notify-user', 'Paired devices are not persistent.');
PersistentStorage.logBrowserNotCapable();
});
Events.fire('notify-user', 'Pairing of two browser tabs is not possible.');
return;
}
// if devices are paired that are already connected we must save the names at this point
const $peer = $(peerId);
let displayName, deviceName;
if ($peer) {
displayName = $peer.ui._peer.name.displayName;
deviceName = $peer.ui._peer.name.deviceName;
}
PersistentStorage.addRoomSecret(roomSecret, displayName, deviceName)
.then(_ => {
Events.fire('notify-user', 'Devices paired successfully.');
this._evaluateNumberRoomSecrets();
})
.finally(_ => {
this._cleanUp();
})
.catch(_ => {
Events.fire('notify-user', 'Paired devices are not persistent.');
PersistentStorage.logBrowserNotCapable();
});
}
_pairDeviceJoinKeyInvalid() {
@ -1064,56 +1122,120 @@ class PairDeviceDialog extends Dialog {
this.$inputRoomKeyChars.forEach(el => el.setAttribute("disabled", ""));
}
_onClearRoomSecrets() {
PersistentStorage.getAllRoomSecrets().then(roomSecrets => {
Events.fire('room-secrets-cleared', roomSecrets);
PersistentStorage.clearRoomSecrets().finally(_ => {
Events.fire('notify-user', 'All Devices unpaired.')
this._evaluateNumberRoomSecrets();
})
}).catch(_ => PersistentStorage.logBrowserNotCapable());
}
_onSecretRoomDeleted(roomSecret) {
PersistentStorage.deleteRoomSecret(roomSecret).then(_ => {
this._evaluateNumberRoomSecrets();
}).catch(e => console.error(e));
});
}
_evaluateNumberRoomSecrets() {
PersistentStorage.getAllRoomSecrets().then(roomSecrets => {
if (roomSecrets.length > 0) {
this.$clearSecretsBtn.removeAttribute('hidden');
this.$editPairedDevicesBtn.removeAttribute('hidden');
this.$footerInstructionsPairedDevices.removeAttribute('hidden');
} else {
this.$clearSecretsBtn.setAttribute('hidden', '');
this.$editPairedDevicesBtn.setAttribute('hidden', '');
this.$footerInstructionsPairedDevices.setAttribute('hidden', '');
}
Events.fire('bg-resize');
}).catch(_ => PersistentStorage.logBrowserNotCapable());
});
}
}
class ClearDevicesDialog extends Dialog {
class EditPairedDevicesDialog extends Dialog {
constructor() {
super('clear-devices-dialog');
$('clear-pair-devices').addEventListener('click', _ => this._onClearPairDevices());
let clearDevicesForm = this.$el.querySelector('form');
clearDevicesForm.addEventListener('submit', e => this._onSubmit(e));
super('edit-paired-devices-dialog');
this.$pairedDevicesWrapper = this.$el.querySelector('.paired-devices-wrapper');
$('edit-paired-devices').addEventListener('click', _ => this._onEditPairedDevices());
Events.on('peer-display-name-changed', e => this._onPeerDisplayNameChanged(e));
Events.on('keydown', e => this._onKeyDown(e));
}
_onClearPairDevices() {
this.show();
_onKeyDown(e) {
if (this.$el.attributes["show"] && e.code === "Escape") {
this.hide();
}
}
_onSubmit(e) {
e.preventDefault();
this._clearRoomSecrets();
async _initDOM() {
const roomSecretsEntries = await PersistentStorage.getAllRoomSecretEntries();
roomSecretsEntries.forEach(roomSecretsEntry => {
let $pairedDevice = document.createElement('div');
$pairedDevice.classList = ["paired-device"];
$pairedDevice.innerHTML = `
<div class="display-name">
<span>${roomSecretsEntry.display_name}</span>
</div>
<div class="device-name">
<span>${roomSecretsEntry.device_name}</span>
</div>
<div class="button-wrapper">
<label class="auto-accept">auto-accept
<input type="checkbox" ${roomSecretsEntry.auto_accept ? "checked" : ""}>
</label>
<button class="button" type="button">unpair</button>
</div>`
$pairedDevice.querySelector('input[type="checkbox"]').addEventListener('click', e => {
PersistentStorage.updateRoomSecretAutoAccept(roomSecretsEntry.secret, e.target.checked).then(roomSecretsEntry => {
Events.fire('auto-accept-updated', {
'roomSecret': roomSecretsEntry.entry.secret,
'autoAccept': e.target.checked
});
});
});
$pairedDevice.querySelector('button').addEventListener('click', e => {
PersistentStorage.deleteRoomSecret(roomSecretsEntry.secret).then(roomSecret => {
Events.fire('room-secrets-deleted', [roomSecret]);
Events.fire('evaluate-number-room-secrets');
e.target.parentNode.parentNode.remove();
});
})
this.$pairedDevicesWrapper.appendChild($pairedDevice)
})
}
hide() {
super.hide();
setTimeout(_ => {
this.$pairedDevicesWrapper.innerHTML = ""
}, 300);
}
_onEditPairedDevices() {
this._initDOM().then(_ => this.show());
}
_clearRoomSecrets() {
Events.fire('clear-room-secrets');
this.hide();
PersistentStorage.getAllRoomSecrets()
.then(roomSecrets => {
PersistentStorage.clearRoomSecrets().finally(_ => {
Events.fire('room-secrets-deleted', roomSecrets);
Events.fire('evaluate-number-room-secrets');
Events.fire('notify-user', 'All Devices unpaired.');
this.hide();
})
});
}
_onPeerDisplayNameChanged(e) {
const peerId = e.detail.peerId;
const peerNode = $(peerId);
if (!peerNode) return;
const peer = peerNode.ui._peer;
if (!peer.roomSecret) return;
PersistentStorage.updateRoomSecretNames(peer.roomSecret, peer.name.displayName, peer.name.deviceName).then(roomSecretEntry => {
console.log(`Successfully updated DisplayName and DeviceName for roomSecretEntry ${roomSecretEntry.key}`);
})
}
}
@ -1682,7 +1804,7 @@ class PersistentStorage {
PersistentStorage.logBrowserNotCapable();
return;
}
const DBOpenRequest = window.indexedDB.open('pairdrop_store', 3);
const DBOpenRequest = window.indexedDB.open('pairdrop_store', 4);
DBOpenRequest.onerror = (e) => {
PersistentStorage.logBrowserNotCapable();
console.log('Error initializing database: ');
@ -1693,27 +1815,32 @@ class PersistentStorage {
};
DBOpenRequest.onupgradeneeded = (e) => {
const db = e.target.result;
const txn = e.target.transaction;
db.onerror = e => console.log('Error loading database: ' + e);
try {
console.log(`Upgrading IndexedDB database from version ${e.oldVersion} to version ${e.newVersion}`);
if (e.oldVersion === 0) {
// initiate v1
db.createObjectStore('keyval');
} catch (error) {
console.log("Object store named 'keyval' already exists")
let roomSecretsObjectStore1 = db.createObjectStore('room_secrets', {autoIncrement: true});
roomSecretsObjectStore1.createIndex('secret', 'secret', { unique: true });
}
try {
const roomSecretsObjectStore = db.createObjectStore('room_secrets', {autoIncrement: true});
roomSecretsObjectStore.createIndex('secret', 'secret', { unique: true });
} catch (error) {
console.log("Object store named 'room_secrets' already exists")
if (e.oldVersion <= 1) {
// migrate to v2
db.createObjectStore('share_target_files');
}
try {
if (db.objectStoreNames.contains('share_target_files')) {
db.deleteObjectStore('share_target_files');
}
if (e.oldVersion <= 2) {
// migrate to v3
db.deleteObjectStore('share_target_files');
db.createObjectStore('share_target_files', {autoIncrement: true});
} catch (error) {
console.log("Object store named 'share_target_files' already exists")
}
if (e.oldVersion <= 3) {
// migrate to v4
let roomSecretsObjectStore4 = txn.objectStore('room_secrets');
roomSecretsObjectStore4.createIndex('display_name', 'display_name');
roomSecretsObjectStore4.createIndex('auto_accept', 'auto_accept');
}
}
}
@ -1746,7 +1873,7 @@ class PersistentStorage {
const DBOpenRequest = window.indexedDB.open('pairdrop_store');
DBOpenRequest.onsuccess = (e) => {
const db = e.target.result;
const transaction = db.transaction('keyval', 'readwrite');
const transaction = db.transaction('keyval', 'readonly');
const objectStore = transaction.objectStore('keyval');
const objectStoreRequest = objectStore.get(key);
objectStoreRequest.onsuccess = _ => {
@ -1779,16 +1906,21 @@ class PersistentStorage {
})
}
static addRoomSecret(roomSecret) {
static addRoomSecret(roomSecret, displayName, deviceName) {
return new Promise((resolve, reject) => {
const DBOpenRequest = window.indexedDB.open('pairdrop_store');
DBOpenRequest.onsuccess = (e) => {
const db = e.target.result;
const transaction = db.transaction('room_secrets', 'readwrite');
const objectStore = transaction.objectStore('room_secrets');
const objectStoreRequest = objectStore.add({'secret': roomSecret});
objectStoreRequest.onsuccess = _ => {
console.log(`Request successful. RoomSecret added: ${roomSecret}`);
const objectStoreRequest = objectStore.add({
'secret': roomSecret,
'display_name': displayName,
'device_name': deviceName,
'auto_accept': false
});
objectStoreRequest.onsuccess = e => {
console.log(`Request successful. RoomSecret added: ${e.target.result}`);
resolve();
}
}
@ -1798,21 +1930,26 @@ class PersistentStorage {
})
}
static getAllRoomSecrets() {
static async getAllRoomSecrets() {
const roomSecrets = await this.getAllRoomSecretEntries();
let secrets = [];
for (let i=0; i<roomSecrets.length; i++) {
secrets.push(roomSecrets[i].secret);
}
console.log(`Request successful. Retrieved ${secrets.length} room_secrets`);
return(secrets);
}
static getAllRoomSecretEntries() {
return new Promise((resolve, reject) => {
const DBOpenRequest = window.indexedDB.open('pairdrop_store');
DBOpenRequest.onsuccess = (e) => {
const db = e.target.result;
const transaction = db.transaction('room_secrets', 'readwrite');
const transaction = db.transaction('room_secrets', 'readonly');
const objectStore = transaction.objectStore('room_secrets');
const objectStoreRequest = objectStore.getAll();
objectStoreRequest.onsuccess = e => {
let secrets = [];
for (let i=0; i<e.target.result.length; i++) {
secrets.push(e.target.result[i].secret);
}
console.log(`Request successful. Retrieved ${secrets.length} room_secrets`);
resolve(secrets);
resolve(e.target.result);
}
}
DBOpenRequest.onerror = (e) => {
@ -1821,24 +1958,59 @@ class PersistentStorage {
});
}
static deleteRoomSecret(room_secret) {
static getRoomSecretEntry(roomSecret) {
return new Promise((resolve, reject) => {
const DBOpenRequest = window.indexedDB.open('pairdrop_store');
DBOpenRequest.onsuccess = (e) => {
const db = e.target.result;
const transaction = db.transaction('room_secrets', 'readonly');
const objectStore = transaction.objectStore('room_secrets');
const objectStoreRequestKey = objectStore.index("secret").getKey(roomSecret);
objectStoreRequestKey.onsuccess = e => {
const key = e.target.result;
if (!key) {
console.log(`Nothing to retrieve. Entry for room_secret not existing: ${roomSecret}`);
resolve();
return;
}
const objectStoreRequestRetrieval = objectStore.get(key);
objectStoreRequestRetrieval.onsuccess = e => {
console.log(`Request successful. Retrieved entry for room_secret: ${key}`);
resolve({
"entry": e.target.result,
"key": key
});
}
objectStoreRequestRetrieval.onerror = (e) => {
reject(e);
}
};
}
DBOpenRequest.onerror = (e) => {
reject(e);
}
});
}
static deleteRoomSecret(roomSecret) {
return new Promise((resolve, reject) => {
const DBOpenRequest = window.indexedDB.open('pairdrop_store');
DBOpenRequest.onsuccess = (e) => {
const db = e.target.result;
const transaction = db.transaction('room_secrets', 'readwrite');
const objectStore = transaction.objectStore('room_secrets');
const objectStoreRequestKey = objectStore.index("secret").getKey(room_secret);
const objectStoreRequestKey = objectStore.index("secret").getKey(roomSecret);
objectStoreRequestKey.onsuccess = e => {
if (!e.target.result) {
console.log(`Nothing to delete. room_secret not existing: ${room_secret}`);
console.log(`Nothing to delete. room_secret not existing: ${roomSecret}`);
resolve();
return;
}
const objectStoreRequestDeletion = objectStore.delete(e.target.result);
const key = e.target.result;
const objectStoreRequestDeletion = objectStore.delete(key);
objectStoreRequestDeletion.onsuccess = _ => {
console.log(`Request successful. Deleted room_secret: ${room_secret}`);
resolve();
console.log(`Request successful. Deleted room_secret: ${key}`);
resolve(roomSecret);
}
objectStoreRequestDeletion.onerror = (e) => {
reject(e);
@ -1869,22 +2041,108 @@ class PersistentStorage {
}
})
}
static updateRoomSecretNames(roomSecret, displayName, deviceName) {
return this.updateRoomSecret(roomSecret, undefined, displayName, deviceName);
}
static updateRoomSecretAutoAccept(roomSecret, autoAccept) {
return this.updateRoomSecret(roomSecret, undefined, undefined, undefined, autoAccept);
}
static updateRoomSecret(roomSecret, updatedRoomSecret = undefined, updatedDisplayName = undefined, updatedDeviceName = undefined, updatedAutoAccept = undefined) {
return new Promise((resolve, reject) => {
const DBOpenRequest = window.indexedDB.open('pairdrop_store');
DBOpenRequest.onsuccess = (e) => {
const db = e.target.result;
this.getRoomSecretEntry(roomSecret)
.then(roomSecretEntry => {
if (!roomSecretEntry) {
resolve(false);
return;
}
const transaction = db.transaction('room_secrets', 'readwrite');
const objectStore = transaction.objectStore('room_secrets');
// Do not use `updatedRoomSecret ?? roomSecretEntry.entry.secret` to ensure compatibility with older browsers
const updatedRoomSecretEntry = {
'secret': updatedRoomSecret !== undefined ? updatedRoomSecret : roomSecretEntry.entry.secret,
'display_name': updatedDisplayName !== undefined ? updatedDisplayName : roomSecretEntry.entry.display_name,
'device_name': updatedDeviceName !== undefined ? updatedDeviceName : roomSecretEntry.entry.device_name,
'auto_accept': updatedAutoAccept !== undefined ? updatedAutoAccept : roomSecretEntry.entry.auto_accept
};
const objectStoreRequestUpdate = objectStore.put(updatedRoomSecretEntry, roomSecretEntry.key);
objectStoreRequestUpdate.onsuccess = e => {
console.log(`Request successful. Updated room_secret: ${roomSecretEntry.key}`);
resolve({
"entry": updatedRoomSecretEntry,
"key": roomSecretEntry.key
});
}
objectStoreRequestUpdate.onerror = (e) => {
reject(e);
}
})
.catch(e => reject(e));
};
DBOpenRequest.onerror = e => reject(e);
})
}
}
class Broadcast {
class BrowserTabsConnector {
constructor() {
this.bc = new BroadcastChannel('pairdrop');
this.bc.addEventListener('message', e => this._onMessage(e));
Events.on('broadcast-send', e => this._broadcastMessage(e.detail));
Events.on('broadcast-send', e => this._broadcastSend(e.detail));
}
_broadcastMessage(message) {
_broadcastSend(message) {
this.bc.postMessage(message);
}
_onMessage(e) {
console.log('Broadcast message received:', e.data)
Events.fire(e.data.type, e.data.detail);
console.log('Broadcast:', e.data)
switch (e.data.type) {
case 'self-display-name-changed':
Events.fire('self-display-name-changed', e.data.detail);
break;
}
}
static peerIsSameBrowser(peerId) {
let peerIdsBrowser = JSON.parse(localStorage.getItem("peerIdsBrowser"));
return peerIdsBrowser
? peerIdsBrowser.indexOf(peerId) !== -1
: false;
}
static async addPeerIdToLocalStorage() {
const peerId = sessionStorage.getItem("peerId");
if (!peerId) return false;
let peerIdsBrowser = [];
let peerIdsBrowserOld = JSON.parse(localStorage.getItem("peerIdsBrowser"));
if (peerIdsBrowserOld) peerIdsBrowser.push(...peerIdsBrowserOld);
peerIdsBrowser.push(peerId);
peerIdsBrowser = peerIdsBrowser.filter(onlyUnique);
localStorage.setItem("peerIdsBrowser", JSON.stringify(peerIdsBrowser));
return peerId;
}
static async removePeerIdFromLocalStorage(peerId) {
let peerIdsBrowser = JSON.parse(localStorage.getItem("peerIdsBrowser"));
const index = peerIdsBrowser.indexOf(peerId);
peerIdsBrowser.splice(index, 1);
localStorage.setItem("peerIdsBrowser", JSON.stringify(peerIdsBrowser));
return peerId;
}
static removePeerIdsFromLocalStorage() {
localStorage.removeItem("peerIdsBrowser");
}
}
@ -1899,7 +2157,7 @@ class PairDrop {
const sendTextDialog = new SendTextDialog();
const receiveTextDialog = new ReceiveTextDialog();
const pairDeviceDialog = new PairDeviceDialog();
const clearDevicesDialog = new ClearDevicesDialog();
const clearDevicesDialog = new EditPairedDevicesDialog();
const base64ZipDialog = new Base64ZipDialog();
const toast = new Toast();
const notifications = new Notifications();
@ -1907,7 +2165,7 @@ class PairDrop {
const webShareTargetUI = new WebShareTargetUI();
const webFileHandlersUI = new WebFileHandlersUI();
const noSleepUI = new NoSleepUI();
const broadCast = new Broadcast();
const broadCast = new BrowserTabsConnector();
});
}
}
@ -1954,7 +2212,6 @@ Events.on('load', () => {
w = document.documentElement.clientWidth;
h = document.documentElement.clientHeight;
offset = $$('footer').offsetHeight - 33;
if (h > 800) offset += 16;
if (oldW === w && oldH === h && oldOffset === offset) return; // nothing has changed