diff --git a/index.js b/index.js index f894c04..0a66535 100644 --- a/index.js +++ b/index.js @@ -54,7 +54,8 @@ const RTC_CONFIG = process.env.RTC_CONFIG let rateLimit = false; if (process.argv.includes('--rate-limit') || process.env.RATE_LIMIT === "true") { rateLimit = 5; -} else { +} +else { let envRateLimit = parseInt(process.env.RATE_LIMIT); if (!isNaN(envRateLimit)) { rateLimit = envRateLimit; @@ -126,7 +127,8 @@ if (RATE_LIMIT) { if (WS_FALLBACK) { app.use(express.static('public_included_ws_fallback')); -} else { +} +else { app.use(express.static('public')); } @@ -159,7 +161,8 @@ const server = http.createServer(app); if (LOCALHOST_ONLY) { server.listen(PORT, '127.0.0.1'); -} else { +} +else { server.listen(PORT); } @@ -670,9 +673,11 @@ class Peer { _setIP(request) { if (request.headers['cf-connecting-ip']) { this.ip = request.headers['cf-connecting-ip'].split(/\s*,\s*/)[0]; - } else if (request.headers['x-forwarded-for']) { + } + else if (request.headers['x-forwarded-for']) { this.ip = request.headers['x-forwarded-for'].split(/\s*,\s*/)[0]; - } else { + } + else { this.ip = request.connection.remoteAddress; } @@ -748,7 +753,8 @@ class Peer { let peerIdHash = searchParams.get("peer_id_hash"); if (peerId && Peer.isValidUuid(peerId) && this.isPeerIdHashValid(peerId, peerIdHash)) { this.id = peerId; - } else { + } + else { this.id = crypto.randomUUID(); } } @@ -769,7 +775,8 @@ class Peer { if (ua.device.model) { deviceName += ua.device.model; - } else { + } + else { deviceName += ua.browser.name; } diff --git a/public/scripts/localization.js b/public/scripts/localization.js index 62b11aa..877cfb0 100644 --- a/public/scripts/localization.js +++ b/public/scripts/localization.js @@ -15,7 +15,8 @@ class Localization { ? storedLanguageCode : Localization.systemLocale; - Localization.setTranslation(Localization.initialLocale) + Localization + .setTranslation(Localization.initialLocale) .then(_ => { console.log("Initial translation successful."); Events.fire("initial-translation-loaded"); @@ -50,7 +51,8 @@ class Localization { if (Localization.isRTLLanguage(locale)) { htmlRootNode.setAttribute('dir', 'rtl'); - } else { + } + else { htmlRootNode.removeAttribute('dir'); } @@ -112,7 +114,8 @@ class Localization { let attr = attrs[i]; if (attr === "text") { element.innerText = Localization.getTranslation(key); - } else { + } + else { if (attr.startsWith("data-")) { let dataAttr = attr.substring(5); element.dataset.dataAttr = Localization.getTranslation(key, attr); @@ -156,7 +159,8 @@ class Localization { console.warn(`Missing translation entry for your language ${Localization.locale.toUpperCase()}. Using ${Localization.defaultLocale.toUpperCase()} instead.`, key, attr); console.warn(`Translate this string here: https://hosted.weblate.org/browse/pairdrop/pairdrop-spa/${Localization.locale.toLowerCase()}/?q=${key}`) console.log("Help translating PairDrop: https://hosted.weblate.org/engage/pairdrop/"); - } else { + } + else { console.warn("Missing translation in default language:", key, attr); } } diff --git a/public/scripts/network.js b/public/scripts/network.js index 53bff2f..629c998 100644 --- a/public/scripts/network.js +++ b/public/scripts/network.js @@ -191,16 +191,19 @@ class ServerConnection { sessionStorage.setItem('peer_id_hash', msg.peerIdHash); // Add peerId to localStorage to mark it for other PairDrop tabs on the same browser - BrowserTabsConnector.addPeerIdToLocalStorage().then(peerId => { - if (!peerId) return; - console.log("successfully added peerId to localStorage"); + BrowserTabsConnector + .addPeerIdToLocalStorage() + .then(peerId => { + if (!peerId) return; + console.log("successfully added peerId to localStorage"); - // Only now join rooms - Events.fire('join-ip-room'); - PersistentStorage.getAllRoomSecrets().then(roomSecrets => { - Events.fire('room-secrets', roomSecrets); + // Only now join rooms + Events.fire('join-ip-room'); + PersistentStorage.getAllRoomSecrets() + .then(roomSecrets => { + Events.fire('room-secrets', roomSecrets); + }); }); - }); Events.fire('display-name', msg); } @@ -223,9 +226,11 @@ class ServerConnection { this.send({ type: 'disconnect' }); const peerId = sessionStorage.getItem('peer_id'); - BrowserTabsConnector.removePeerIdFromLocalStorage(peerId).then(_ => { - console.log("successfully removed peerId from localStorage"); - }); + BrowserTabsConnector + .removePeerIdFromLocalStorage(peerId) + .then(_ => { + console.log("successfully removed peerId from localStorage"); + }); if (!this._socket) return; @@ -318,7 +323,8 @@ class Peer { // -> do not delete duplicates and do not regenerate room secrets if (!this._isSameBrowser() && roomType === "secret" && this._isPaired() && this._getPairSecret() !== roomId) { // multiple roomSecrets with same peer -> delete old roomSecret - PersistentStorage.deleteRoomSecret(this._getPairSecret()) + PersistentStorage + .deleteRoomSecret(this._getPairSecret()) .then(deletedRoomSecret => { if (deletedRoomSecret) console.log("Successfully deleted duplicate room secret with same peer: ", deletedRoomSecret); }); @@ -348,7 +354,8 @@ class Peer { return; } - PersistentStorage.getRoomSecretEntry(this._getPairSecret()) + PersistentStorage + .getRoomSecretEntry(this._getPairSecret()) .then(roomSecretEntry => { const autoAccept = roomSecretEntry ? roomSecretEntry.entry.auto_accept @@ -379,13 +386,16 @@ class Peer { if (width && height) { canvas.width = width; canvas.height = height; - } else if (width) { + } + else if (width) { canvas.width = width; canvas.height = Math.floor(imageHeight * width / imageWidth) - } else if (height) { + } + else if (height) { canvas.width = Math.floor(imageWidth * height / imageHeight); canvas.height = height; - } else { + } + else { canvas.width = imageWidth; canvas.height = imageHeight } @@ -397,9 +407,11 @@ class Peer { resolve(dataUrl); } image.onerror = _ => reject(`Could not create an image thumbnail from type ${file.type}`); - }).then(dataUrl => { + }) + .then(dataUrl => { return dataUrl; - }).catch(e => console.error(e)); + }) + .catch(e => console.error(e)); } async requestFileTransfer(files) { @@ -634,7 +646,8 @@ class Peer { this._busy = false; Events.fire('notify-user', Localization.getTranslation("notifications.file-transfer-completed")); Events.fire('files-sent'); // used by 'Snapdrop & PairDrop for Android' app - } else { + } + else { this._dequeueFile(); } } @@ -697,7 +710,8 @@ class RTCPeer extends Peer { if (this._isCaller) { this._openChannel(); - } else { + } + else { this._conn.ondatachannel = e => this._onChannelOpened(e); } } @@ -727,7 +741,8 @@ class RTCPeer extends Peer { _onDescription(description) { // description.sdp = description.sdp.replace('b=AS:30', 'b=AS:1638400'); - this._conn.setLocalDescription(description) + this._conn + .setLocalDescription(description) .then(_ => this._sendSignal({ sdp: description })) .catch(e => this._onError(e)); } @@ -741,16 +756,20 @@ class RTCPeer extends Peer { if (!this._conn) this._connect(); if (message.sdp) { - this._conn.setRemoteDescription(message.sdp) + this._conn + .setRemoteDescription(message.sdp) .then(_ => { if (message.sdp.type === 'offer') { - return this._conn.createAnswer() + return this._conn + .createAnswer() .then(d => this._onDescription(d)); } }) .catch(e => this._onError(e)); - } else if (message.ice) { - this._conn.addIceCandidate(new RTCIceCandidate(message.ice)) + } + else if (message.ice) { + this._conn + .addIceCandidate(new RTCIceCandidate(message.ice)) .catch(e => this._onError(e)); } } @@ -997,10 +1016,11 @@ class PeersManager { // If no peers are connected anymore, we can safely assume that no other tab on the same browser is connected: // Tidy up peerIds in localStorage if (Object.keys(this.peers).length === 0) { - BrowserTabsConnector.removeOtherPeerIdsFromLocalStorage().then(peerIds => { - if (!peerIds) return; - console.log("successfully removed other peerIds from localStorage"); - }); + BrowserTabsConnector.removeOtherPeerIdsFromLocalStorage() + .then(peerIds => { + if (!peerIds) return; + console.log("successfully removed other peerIds from localStorage"); + }); } } } @@ -1050,16 +1070,19 @@ class PeersManager { if (peer._getRoomTypes().length > 1) { peer._removeRoomType(roomType); - } else { + } + else { Events.fire('peer-disconnected', peerId); } } _onRoomSecretRegenerated(message) { - PersistentStorage.updateRoomSecret(message.oldRoomSecret, message.newRoomSecret).then(_ => { - console.log("successfully regenerated room secret"); - Events.fire("room-secrets", [message.newRoomSecret]); - }) + PersistentStorage + .updateRoomSecret(message.oldRoomSecret, message.newRoomSecret) + .then(_ => { + console.log("successfully regenerated room secret"); + Events.fire("room-secrets", [message.newRoomSecret]); + }) } _notifyPeersDisplayNameChanged(newDisplayName) { diff --git a/public/scripts/theme.js b/public/scripts/theme.js index 81cf0b2..33ea0b3 100644 --- a/public/scripts/theme.js +++ b/public/scripts/theme.js @@ -1,78 +1,83 @@ (function(){ - const prefersDarkTheme = window.matchMedia('(prefers-color-scheme: dark)').matches; - const prefersLightTheme = window.matchMedia('(prefers-color-scheme: light)').matches; + const prefersDarkTheme = window.matchMedia('(prefers-color-scheme: dark)').matches; + const prefersLightTheme = window.matchMedia('(prefers-color-scheme: light)').matches; - const $themeAuto = document.getElementById('theme-auto'); - const $themeLight = document.getElementById('theme-light'); - const $themeDark = document.getElementById('theme-dark'); + const $themeAuto = document.getElementById('theme-auto'); + const $themeLight = document.getElementById('theme-light'); + const $themeDark = document.getElementById('theme-dark'); - let currentTheme = localStorage.getItem('theme'); + let currentTheme = localStorage.getItem('theme'); - if (currentTheme === 'dark') { - setModeToDark(); - } else if (currentTheme === 'light') { - setModeToLight(); - } - - $themeAuto.addEventListener('click', _ => { - if (currentTheme) { - setModeToAuto(); - } else { - setModeToDark(); + if (currentTheme === 'dark') { + setModeToDark(); } - }); - $themeLight.addEventListener('click', _ => { - if (currentTheme !== 'light') { - setModeToLight(); - } else { - setModeToAuto(); + else if (currentTheme === 'light') { + setModeToLight(); } - }); - $themeDark.addEventListener('click', _ => { - if (currentTheme !== 'dark') { - setModeToDark(); - } else { - setModeToLight(); + + $themeAuto.addEventListener('click', _ => { + if (currentTheme) { + setModeToAuto(); + } + else { + setModeToDark(); + } + }); + $themeLight.addEventListener('click', _ => { + if (currentTheme !== 'light') { + setModeToLight(); + } + else { + setModeToAuto(); + } + }); + $themeDark.addEventListener('click', _ => { + if (currentTheme !== 'dark') { + setModeToDark(); + } + else { + setModeToLight(); + } + }); + + function setModeToDark() { + document.body.classList.remove('light-theme'); + document.body.classList.add('dark-theme'); + localStorage.setItem('theme', 'dark'); + currentTheme = 'dark'; + + $themeAuto.classList.remove("selected"); + $themeLight.classList.remove("selected"); + $themeDark.classList.add("selected"); } - }); - function setModeToDark() { - document.body.classList.remove('light-theme'); - document.body.classList.add('dark-theme'); - localStorage.setItem('theme', 'dark'); - currentTheme = 'dark'; + function setModeToLight() { + document.body.classList.remove('dark-theme'); + document.body.classList.add('light-theme'); + localStorage.setItem('theme', 'light'); + currentTheme = 'light'; - $themeAuto.classList.remove("selected"); - $themeLight.classList.remove("selected"); - $themeDark.classList.add("selected"); - } - - function setModeToLight() { - document.body.classList.remove('dark-theme'); - document.body.classList.add('light-theme'); - localStorage.setItem('theme', 'light'); - currentTheme = 'light'; - - $themeAuto.classList.remove("selected"); - $themeLight.classList.add("selected"); - $themeDark.classList.remove("selected"); - } - - function setModeToAuto() { - document.body.classList.remove('dark-theme'); - document.body.classList.remove('light-theme'); - if (prefersDarkTheme) { - document.body.classList.add('dark-theme'); - } else if (prefersLightTheme) { - document.body.classList.add('light-theme'); + $themeAuto.classList.remove("selected"); + $themeLight.classList.add("selected"); + $themeDark.classList.remove("selected"); } - localStorage.removeItem('theme'); - currentTheme = undefined; - $themeAuto.classList.add("selected"); - $themeLight.classList.remove("selected"); - $themeDark.classList.remove("selected"); - } + function setModeToAuto() { + document.body.classList.remove('dark-theme'); + document.body.classList.remove('light-theme'); + if (prefersDarkTheme) { + document.body.classList.add('dark-theme'); + } + else if (prefersLightTheme) { + document.body.classList.add('light-theme'); + } + localStorage.removeItem('theme'); + currentTheme = undefined; + + $themeAuto.classList.add("selected"); + $themeLight.classList.remove("selected"); + $themeDark.classList.remove("selected"); + } })(); diff --git a/public/scripts/ui.js b/public/scripts/ui.js index 6b8a0fa..6545966 100644 --- a/public/scripts/ui.js +++ b/public/scripts/ui.js @@ -64,10 +64,13 @@ class PeersUI { } _loadSavedDisplayName() { - this._getSavedDisplayName().then(displayName => { - console.log("Retrieved edited display name:", displayName) - if (displayName) Events.fire('self-display-name-changed', displayName); - }); + this._getSavedDisplayName() + .then(displayName => { + console.log("Retrieved edited display name:", displayName) + if (displayName) { + Events.fire('self-display-name-changed', displayName); + } + }); } _onDisplayName(displayName){ @@ -104,7 +107,8 @@ class PeersUI { if (this.$discoveryWrapper.querySelectorAll('div:last-of-type > span[hidden]').length < 2) { this.$discoveryWrapper.classList.remove('row'); this.$discoveryWrapper.classList.add('column'); - } else { + } + else { this.$discoveryWrapper.classList.remove('column'); this.$discoveryWrapper.classList.add('row'); } @@ -147,7 +151,8 @@ class PeersUI { Events.fire('self-display-name-changed', newDisplayName); Events.fire('broadcast-send', {type: 'self-display-name-changed', detail: newDisplayName}); }); - } else { + } + else { PersistentStorage.delete('editedDisplayName') .catch(_ => { console.log("This browser does not support IndexedDB. Use localStorage instead.") @@ -188,8 +193,12 @@ class PeersUI { this._changePeerDisplayName(e.detail.peerId, e.detail.displayName); } + _noDialogShown() { + return document.querySelectorAll('x-dialog[show]').length === 0; + } + _onKeyDown(e) { - if (document.querySelectorAll('x-dialog[show]').length === 0 && window.pasteMode.activated && e.code === "Escape") { + if (this._noDialogShown() && window.pasteMode.activated && e.code === "Escape") { Events.fire('deactivate-paste-mode'); } @@ -245,7 +254,8 @@ class PeersUI { _evaluateOverflowing() { if (this.$xPeers.clientHeight < this.$xPeers.scrollHeight) { this.$xPeers.classList.add('overflowing'); - } else { + } + else { this.$xPeers.classList.remove('overflowing'); } } @@ -319,9 +329,11 @@ class PeersUI { if (files.length === 1) { descriptor = `${files[0].name}`; - } else if (files.length > 1) { + } + else if (files.length > 1) { descriptor = `${files[0].name}
${andOtherFiles}`; - } else { + } + else { descriptor = sharedText; } @@ -380,7 +392,8 @@ class PeersUI { files: files, to: peerId }); - } else if (text.length > 0) { + } + else if (text.length > 0) { Events.fire('send-text', { text: text, to: peerId @@ -408,7 +421,8 @@ class PeerUI { let input = ''; if (window.pasteMode.activated) { title = Localization.getTranslation("peer-ui.click-to-send-paste-mode", null, {descriptor: window.pasteMode.descriptor}); - } else { + } + else { title = Localization.getTranslation("peer-ui.click-to-send"); input = ''; } @@ -498,7 +512,8 @@ class PeerUI { this.$el.addEventListener('contextmenu', this._callbackContextMenu); this.$el.addEventListener('touchstart', this._callbackTouchStart); this.$el.addEventListener('touchend', this._callbackTouchEnd); - } else { + } + else { // Remove Events Normal Mode this.$el.removeEventListener('click', this._callbackClickSleep); this.$el.removeEventListener('touchstart', this._callbackTouchStartSleep); @@ -566,7 +581,8 @@ class PeerUI { const $progress = this.$el.querySelector('.progress'); if (0.5 < progress && progress < 1) { $progress.classList.add('over50'); - } else { + } + else { $progress.classList.remove('over50'); } if (progress < 1) { @@ -582,7 +598,8 @@ class PeerUI { this.$el.querySelector('.status').innerText = statusName; this.currentStatus = status; } - } else { + } + else { this.$el.removeAttribute('status'); this.$el.querySelector('.status').innerHTML = ''; progress = 0; @@ -627,7 +644,8 @@ class PeerUI { _onTouchEnd(e) { if (Date.now() - this._touchStart < 500) { clearTimeout(this._touchTimer); - } else if (this._touchTimer) { // this was a long tap + } + else if (this._touchTimer) { // this was a long tap e.preventDefault(); Events.fire('text-recipient', { peerId: this._peer.id, @@ -641,7 +659,9 @@ class PeerUI { class Dialog { constructor(id) { this.$el = $(id); - this.$el.querySelectorAll('[close]').forEach(el => el.addEventListener('click', _ => this.hide())); + this.$el.querySelectorAll('[close]').forEach(el => { + el.addEventListener('click', _ => this.hide()) + }); this.$autoFocus = this.$el.querySelector('[autofocus]'); Events.on('peer-disconnected', e => this._onPeerDisconnected(e.detail)); @@ -699,7 +719,8 @@ class LanguageSelectDialog extends Dialog { show() { if (Localization.isSystemLocale()) { this.$languageButtons[0].focus(); - } else { + } + else { let locale = Localization.getLocale(); for (let i=0; i= 1073741824) { return Math.round(10 * bytes / 1073741824) / 10 + ' GB'; - } else if (bytes >= 1048576) { + } + else if (bytes >= 1048576) { return Math.round(bytes / 1048576) + ' MB'; - } else if (bytes > 1024) { + } + else if (bytes > 1024) { return Math.round(bytes / 1024) + ' KB'; - } else { + } + else { return bytes + ' Bytes'; } } @@ -761,7 +786,8 @@ class ReceiveDialog extends Dialog { fileOther = imagesOnly ? Localization.getTranslation("dialogs.file-other-description-image") : Localization.getTranslation("dialogs.file-other-description-file"); - } else if (files.length >= 2) { + } + else if (files.length >= 2) { fileOther = imagesOnly ? Localization.getTranslation("dialogs.file-other-description-image-plural", null, {count: files.length - 1}) : Localization.getTranslation("dialogs.file-other-description-file-plural", null, {count: files.length - 1}); @@ -845,7 +871,8 @@ class ReceiveFileDialog extends ReceiveDialog { if (Object.keys(previewElement).indexOf(mime) === -1) { resolve(false); - } else { + } + else { let element = document.createElement(previewElement[mime]); element.controls = true; element.onload = _ => { @@ -875,7 +902,8 @@ class ReceiveFileDialog extends ReceiveDialog { descriptor = imagesOnly ? Localization.getTranslation("dialogs.title-image") : Localization.getTranslation("dialogs.title-file"); - } else { + } + else { descriptor = imagesOnly ? Localization.getTranslation("dialogs.title-image-plural") : Localization.getTranslation("dialogs.title-file-plural"); @@ -937,7 +965,8 @@ class ReceiveFileDialog extends ReceiveDialog { tmpZipBtn.download = filenameDownload; tmpZipBtn.href = url; tmpZipBtn.click(); - } else { + } + else { this._downloadFilesIndividually(files); } @@ -960,7 +989,8 @@ class ReceiveFileDialog extends ReceiveDialog { setTimeout(() => { if (canShare) { this.$shareBtn.click(); - } else { + } + else { this.$downloadBtn.click(); } }, 500); @@ -969,7 +999,8 @@ class ReceiveFileDialog extends ReceiveDialog { .then(canPreview => { if (canPreview) { console.log('the file is able to preview'); - } else { + } + else { console.log('the file is not able to preview'); } }) @@ -1132,10 +1163,12 @@ class InputKeyContainer { if (e.key === "Backspace" && previousSibling && !e.target.value) { previousSibling.value = ''; previousSibling.focus(); - } else if (e.key === "ArrowRight" && nextSibling) { + } + else if (e.key === "ArrowRight" && nextSibling) { e.preventDefault(); nextSibling.focus(); - } else if (e.key === "ArrowLeft" && previousSibling) { + } + else if (e.key === "ArrowLeft" && previousSibling) { e.preventDefault(); previousSibling.focus(); } @@ -1171,7 +1204,8 @@ class InputKeyContainer { _evaluateKeyChars() { if (this.$inputKeyContainer.querySelectorAll('input:placeholder-shown').length > 0) { this._onNotAllCharsFilled(); - } else { + } + else { this._onAllCharsFilled(); const lastCharFocused = document.activeElement === this.$inputKeyChars[this.$inputKeyChars.length - 1]; @@ -1241,7 +1275,10 @@ class PairDeviceDialog extends Dialog { _onPaste(e) { e.preventDefault(); - let pastedKey = e.clipboardData.getData("Text").replace(/\D/g,'').substring(0, 6); + let pastedKey = e.clipboardData + .getData("Text") + .replace(/\D/g,'') + .substring(0, 6); this.inputKeyContainer._onPaste(pastedKey); } @@ -1364,7 +1401,8 @@ class PairDeviceDialog extends Dialog { deviceName = $peer.ui._peer.name.deviceName; } - PersistentStorage.addRoomSecret(roomSecret, displayName, deviceName) + PersistentStorage + .addRoomSecret(roomSecret, displayName, deviceName) .then(_ => { Events.fire('notify-user', Localization.getTranslation("notifications.pairing-success")); this._evaluateNumberRoomSecrets(); @@ -1405,18 +1443,22 @@ class PairDeviceDialog extends Dialog { } _onSecretRoomDeleted(roomSecret) { - PersistentStorage.deleteRoomSecret(roomSecret).then(_ => { - this._evaluateNumberRoomSecrets(); - }); + PersistentStorage + .deleteRoomSecret(roomSecret) + .then(_ => { + this._evaluateNumberRoomSecrets(); + }); } _evaluateNumberRoomSecrets() { - PersistentStorage.getAllRoomSecrets() + PersistentStorage + .getAllRoomSecrets() .then(roomSecrets => { if (roomSecrets.length > 0) { this.$editPairedDevicesHeaderBtn.removeAttribute('hidden'); this.$footerInstructionsPairedDevices.removeAttribute('hidden'); - } else { + } + else { this.$editPairedDevicesHeaderBtn.setAttribute('hidden', ''); this.$footerInstructionsPairedDevices.setAttribute('hidden', ''); } @@ -1450,45 +1492,51 @@ class EditPairedDevicesDialog extends Dialog { const autoAcceptString = Localization.getTranslation("dialogs.auto-accept").toLowerCase(); const roomSecretsEntries = await PersistentStorage.getAllRoomSecretEntries(); - roomSecretsEntries.forEach(roomSecretsEntry => { - let $pairedDevice = document.createElement('div'); - $pairedDevice.classList = ["paired-device"]; + roomSecretsEntries + .forEach(roomSecretsEntry => { + let $pairedDevice = document.createElement('div'); + $pairedDevice.classList = ["paired-device"]; - $pairedDevice.innerHTML = ` -
- ${roomSecretsEntry.display_name} -
-
- ${roomSecretsEntry.device_name} -
-
- - -
` + $pairedDevice.innerHTML = ` +
+ ${roomSecretsEntry.display_name} +
+
+ ${roomSecretsEntry.device_name} +
+
+ + +
` - $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('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(); - }); + $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.html = ""; + this.$pairedDevicesWrapper.appendChild($pairedDevice) }) - - this.$pairedDevicesWrapper.html = ""; - this.$pairedDevicesWrapper.appendChild($pairedDevice) - }) - } hide() { @@ -1503,14 +1551,17 @@ class EditPairedDevicesDialog extends Dialog { } _clearRoomSecrets() { - PersistentStorage.getAllRoomSecrets() + PersistentStorage + .getAllRoomSecrets() .then(roomSecrets => { - PersistentStorage.clearRoomSecrets().finally(() => { - Events.fire('room-secrets-deleted', roomSecrets); - Events.fire('evaluate-number-room-secrets'); - Events.fire('notify-user', Localization.getTranslation("notifications.pairing-cleared")); - this.hide(); - }) + PersistentStorage + .clearRoomSecrets() + .finally(() => { + Events.fire('room-secrets-deleted', roomSecrets); + Events.fire('evaluate-number-room-secrets'); + Events.fire('notify-user', Localization.getTranslation("notifications.pairing-cleared")); + this.hide(); + }) }); } @@ -1524,9 +1575,11 @@ class EditPairedDevicesDialog extends Dialog { if (!peer || !peer._roomIds["secret"]) return; - PersistentStorage.updateRoomSecretNames(peer._roomIds["secret"], peer.name.displayName, peer.name.deviceName).then(roomSecretEntry => { - console.log(`Successfully updated DisplayName and DeviceName for roomSecretEntry ${roomSecretEntry.key}`); - }) + PersistentStorage + .updateRoomSecretNames(peer._roomIds["secret"], peer.name.displayName, peer.name.deviceName) + .then(roomSecretEntry => { + console.log(`Successfully updated DisplayName and DeviceName for roomSecretEntry ${roomSecretEntry.key}`); + }) } } @@ -1589,7 +1642,8 @@ class PublicRoomDialog extends Dialog { _onHeaderBtnClick() { if (this.roomId) { this.show(); - } else { + } + else { this._createPublicRoom(); } } @@ -1782,7 +1836,8 @@ class SendTextDialog extends Dialog { if (e.code === "Escape") { this.hide(); - } else if (e.code === "Enter" && (e.ctrlKey || e.metaKey)) { + } + else if (e.code === "Enter" && (e.ctrlKey || e.metaKey)) { if (this._textInputEmpty()) return; this._send(); } @@ -1795,7 +1850,8 @@ class SendTextDialog extends Dialog { _onChange(e) { if (this._textInputEmpty()) { this.$submit.setAttribute('disabled', ''); - } else { + } + else { this.$submit.removeAttribute('disabled'); } } @@ -1853,7 +1909,8 @@ class ReceiveTextDialog extends Dialog { if (e.code === "KeyC" && (e.ctrlKey || e.metaKey)) { await this._onCopy() this.hide(); - } else if (e.code === "Escape") { + } + else if (e.code === "Escape") { this.hide(); } } @@ -1903,7 +1960,8 @@ class ReceiveTextDialog extends Dialog { async _onCopy() { const sanitizedText = this.$text.innerText.replace(/\u00A0/gm, ' '); - navigator.clipboard.writeText(sanitizedText) + navigator.clipboard + .writeText(sanitizedText) .then(_ => { Events.fire('notify-user', Localization.getTranslation("notifications.copied-to-clipboard")); this.hide(); @@ -1937,7 +1995,8 @@ class Base64ZipDialog extends Dialog { // ?base64text=paste // base64 encoded string is ready to be pasted from clipboard this.preparePasting('text'); - } else if (base64Text === 'hash') { + } + else if (base64Text === 'hash') { // ?base64text=hash#BASE64ENCODED // base64 encoded string is url hash which is never sent to server and faster (recommended) this.processBase64Text(base64Hash) @@ -1947,7 +2006,8 @@ class Base64ZipDialog extends Dialog { }).finally(() => { this.hide(); }); - } else { + } + else { // ?base64text=BASE64ENCODED // base64 encoded string was part of url param (not recommended) this.processBase64Text(base64Text) @@ -1958,7 +2018,8 @@ class Base64ZipDialog extends Dialog { this.hide(); }); } - } else if (base64Zip) { + } + else if (base64Zip) { this.show(); if (base64Zip === "hash") { // ?base64zip=hash#BASE64ENCODED @@ -1970,7 +2031,8 @@ class Base64ZipDialog extends Dialog { }).finally(() => { this.hide(); }); - } else { + } + else { // ?base64zip=paste || ?base64zip=true this.preparePasting('files'); } @@ -1991,7 +2053,8 @@ class Base64ZipDialog extends Dialog { this.$pasteBtn.innerText = Localization.getTranslation("dialogs.base64-tap-to-paste", null, {type: translateType}); this._clickCallback = _ => this.processClipboard(type); this.$pasteBtn.addEventListener('click', _ => this._clickCallback()); - } else { + } + else { console.log("`navigator.clipboard.readText()` is not available on your browser.\nOn Firefox you can set `dom.events.asyncClipboard.readText` to true under `about:config` for convenience.") this.$pasteBtn.setAttribute('hidden', ''); this.$fallbackTextarea.setAttribute('placeholder', Localization.getTranslation("dialogs.base64-paste-to-send", null, {type: translateType})); @@ -2030,7 +2093,8 @@ class Base64ZipDialog extends Dialog { try { if (type === 'text') { await this.processBase64Text(base64); - } else { + } + else { await this.processBase64Zip(base64); } } catch(_) { @@ -2161,7 +2225,8 @@ class Notifications { if (/^((https?:\/\/|www)[abcdefghijklmnopqrstuvwxyz0123456789\-._~:\/?#\[\]@!$&'()*+,;=]+)$/.test(message.toLowerCase())) { const notification = this._notify(Localization.getTranslation("notifications.link-received", null, {name: peerDisplayName}), message); this._bind(notification, _ => window.open(message, '_blank', "noreferrer")); - } else { + } + else { const notification = this._notify(Localization.getTranslation("notifications.message-received", null, {name: peerDisplayName}), message); this._bind(notification, _ => this._copyText(message, notification)); } @@ -2180,13 +2245,15 @@ class Notifications { let title; if (files.length === 1) { title = `${files[0].name}`; - } else { + } + else { let fileOther; if (files.length === 2) { fileOther = imagesOnly ? Localization.getTranslation("dialogs.file-other-description-image") : Localization.getTranslation("dialogs.file-other-description-file"); - } else { + } + else { fileOther = imagesOnly ? Localization.getTranslation("dialogs.file-other-description-image-plural", null, {count: files.length - 1}) : Localization.getTranslation("dialogs.file-other-description-file-plural", null, {count: files.length - 1}); @@ -2215,17 +2282,19 @@ class Notifications { descriptor = imagesOnly ? Localization.getTranslation("dialogs.title-image") : Localization.getTranslation("dialogs.title-file"); - } else { + } + else { descriptor = imagesOnly ? Localization.getTranslation("dialogs.title-image-plural") : Localization.getTranslation("dialogs.title-file-plural"); } - let title = Localization.getTranslation("notifications.request-title", null, { - name: displayName, - count: request.header.length, - descriptor: descriptor.toLowerCase() - }); + let title = Localization + .getTranslation("notifications.request-title", null, { + name: displayName, + count: request.header.length, + descriptor: descriptor.toLowerCase() + }); const notification = this._notify(title, Localization.getTranslation("notifications.click-to-show")); } @@ -2240,17 +2309,23 @@ class Notifications { if (await navigator.clipboard.writeText(message)) { notification.close(); this._notify(Localization.getTranslation("notifications.copied-text")); - } else { + } + else { this._notify(Localization.getTranslation("notifications.copied-text-error")); } } _bind(notification, handler) { if (notification.then) { - notification.then(_ => serviceWorker.getNotifications().then(_ => { - serviceWorker.addEventListener('notificationclick', handler); - })); - } else { + notification.then(_ => { + serviceWorker + .getNotifications() + .then(_ => { + serviceWorker.addEventListener('notificationclick', handler); + }) + }); + } + else { notification.onclick = handler; } } @@ -2289,14 +2364,17 @@ class WebShareTargetUI { if (url) { shareTargetText = url; // we share only the link - no text. - } else if (title && text) { + } + else if (title && text) { shareTargetText = title + '\r\n' + text; - } else { + } + else { shareTargetText = title + text; } Events.fire('activate-paste-mode', {files: [], text: shareTargetText}) - } else if (share_target_type === "files") { + } + else if (share_target_type === "files") { let openRequest = window.indexedDB.open('pairdrop_store') openRequest.onsuccess = e => { const db = e.target.result; @@ -2818,7 +2896,8 @@ const pairDrop = new PairDrop(); const localization = new Localization(); if ('serviceWorker' in navigator) { - navigator.serviceWorker.register('/service-worker.js') + navigator.serviceWorker + .register('/service-worker.js') .then(serviceWorker => { console.log('Service Worker registered'); window.serviceWorker = serviceWorker diff --git a/public/scripts/util.js b/public/scripts/util.js index 921094b..7272d1b 100644 --- a/public/scripts/util.js +++ b/public/scripts/util.js @@ -55,7 +55,8 @@ const zipper = (() => { const blobURL = URL.createObjectURL(await zipWriter.close()); zipWriter = null; return blobURL; - } else { + } + else { throw new Error("Zip file closed"); } }, @@ -64,7 +65,8 @@ const zipper = (() => { const file = new File([await zipWriter.close()], filename, {type: "application/zip"}); zipWriter = null; return file; - } else { + } + else { throw new Error("Zip file closed"); } }, diff --git a/public/service-worker.js b/public/service-worker.js index 81a1b5f..752cb46 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -90,16 +90,19 @@ self.addEventListener('fetch', function(event) { const share_url = await evaluateRequestData(event.request); return Response.redirect(encodeURI(share_url), 302); })()); - } else { + } + else { // Regular requests not related to Web Share Target. if (forceFetch) { event.respondWith(fromNetwork(event.request, 10000)); - } else { + } + else { event.respondWith( - fromCache(event.request).then(rsp => { - // if fromCache resolves to undefined fetch from network instead - return rsp || fromNetwork(event.request, 10000); - }) + fromCache(event.request) + .then(rsp => { + // if fromCache resolves to undefined fetch from network instead + return rsp || fromNetwork(event.request, 10000); + }) ); } } @@ -109,15 +112,16 @@ self.addEventListener('fetch', function(event) { // on activation, we clean up the previously registered service workers self.addEventListener('activate', evt => { return evt.waitUntil( - caches.keys().then(cacheNames => { - return Promise.all( - cacheNames.map(cacheName => { - if (cacheName !== cacheTitle) { - return caches.delete(cacheName); - } - }) - ); - }) + caches.keys() + .then(cacheNames => { + return Promise.all( + cacheNames.map(cacheName => { + if (cacheName !== cacheTitle) { + return caches.delete(cacheName); + } + }) + ); + }) ) } ); @@ -157,7 +161,8 @@ const evaluateRequestData = function (request) { DBOpenRequest.onerror = _ => { resolve(pairDropUrl); } - } else { + } + else { let urlArgument = '?share-target=text'; if (title) urlArgument += `&title=${title}`; diff --git a/public_included_ws_fallback/scripts/localization.js b/public_included_ws_fallback/scripts/localization.js index 62b11aa..877cfb0 100644 --- a/public_included_ws_fallback/scripts/localization.js +++ b/public_included_ws_fallback/scripts/localization.js @@ -15,7 +15,8 @@ class Localization { ? storedLanguageCode : Localization.systemLocale; - Localization.setTranslation(Localization.initialLocale) + Localization + .setTranslation(Localization.initialLocale) .then(_ => { console.log("Initial translation successful."); Events.fire("initial-translation-loaded"); @@ -50,7 +51,8 @@ class Localization { if (Localization.isRTLLanguage(locale)) { htmlRootNode.setAttribute('dir', 'rtl'); - } else { + } + else { htmlRootNode.removeAttribute('dir'); } @@ -112,7 +114,8 @@ class Localization { let attr = attrs[i]; if (attr === "text") { element.innerText = Localization.getTranslation(key); - } else { + } + else { if (attr.startsWith("data-")) { let dataAttr = attr.substring(5); element.dataset.dataAttr = Localization.getTranslation(key, attr); @@ -156,7 +159,8 @@ class Localization { console.warn(`Missing translation entry for your language ${Localization.locale.toUpperCase()}. Using ${Localization.defaultLocale.toUpperCase()} instead.`, key, attr); console.warn(`Translate this string here: https://hosted.weblate.org/browse/pairdrop/pairdrop-spa/${Localization.locale.toLowerCase()}/?q=${key}`) console.log("Help translating PairDrop: https://hosted.weblate.org/engage/pairdrop/"); - } else { + } + else { console.warn("Missing translation in default language:", key, attr); } } diff --git a/public_included_ws_fallback/scripts/network.js b/public_included_ws_fallback/scripts/network.js index 5a279a1..719a478 100644 --- a/public_included_ws_fallback/scripts/network.js +++ b/public_included_ws_fallback/scripts/network.js @@ -204,16 +204,19 @@ class ServerConnection { sessionStorage.setItem('peer_id_hash', msg.peerIdHash); // Add peerId to localStorage to mark it for other PairDrop tabs on the same browser - BrowserTabsConnector.addPeerIdToLocalStorage().then(peerId => { - if (!peerId) return; - console.log("successfully added peerId to localStorage"); + BrowserTabsConnector + .addPeerIdToLocalStorage() + .then(peerId => { + if (!peerId) return; + console.log("successfully added peerId to localStorage"); - // Only now join rooms - Events.fire('join-ip-room'); - PersistentStorage.getAllRoomSecrets().then(roomSecrets => { - Events.fire('room-secrets', roomSecrets); + // Only now join rooms + Events.fire('join-ip-room'); + PersistentStorage.getAllRoomSecrets() + .then(roomSecrets => { + Events.fire('room-secrets', roomSecrets); + }); }); - }); Events.fire('display-name', msg); } @@ -236,9 +239,11 @@ class ServerConnection { this.send({ type: 'disconnect' }); const peerId = sessionStorage.getItem('peer_id'); - BrowserTabsConnector.removePeerIdFromLocalStorage(peerId).then(_ => { - console.log("successfully removed peerId from localStorage"); - }); + BrowserTabsConnector + .removePeerIdFromLocalStorage(peerId) + .then(_ => { + console.log("successfully removed peerId from localStorage"); + }); if (!this._socket) return; @@ -331,7 +336,8 @@ class Peer { // -> do not delete duplicates and do not regenerate room secrets if (!this._isSameBrowser() && roomType === "secret" && this._isPaired() && this._getPairSecret() !== roomId) { // multiple roomSecrets with same peer -> delete old roomSecret - PersistentStorage.deleteRoomSecret(this._getPairSecret()) + PersistentStorage + .deleteRoomSecret(this._getPairSecret()) .then(deletedRoomSecret => { if (deletedRoomSecret) console.log("Successfully deleted duplicate room secret with same peer: ", deletedRoomSecret); }); @@ -361,7 +367,8 @@ class Peer { return; } - PersistentStorage.getRoomSecretEntry(this._getPairSecret()) + PersistentStorage + .getRoomSecretEntry(this._getPairSecret()) .then(roomSecretEntry => { const autoAccept = roomSecretEntry ? roomSecretEntry.entry.auto_accept @@ -392,13 +399,16 @@ class Peer { if (width && height) { canvas.width = width; canvas.height = height; - } else if (width) { + } + else if (width) { canvas.width = width; canvas.height = Math.floor(imageHeight * width / imageWidth) - } else if (height) { + } + else if (height) { canvas.width = Math.floor(imageWidth * height / imageHeight); canvas.height = height; - } else { + } + else { canvas.width = imageWidth; canvas.height = imageHeight } @@ -410,9 +420,11 @@ class Peer { resolve(dataUrl); } image.onerror = _ => reject(`Could not create an image thumbnail from type ${file.type}`); - }).then(dataUrl => { + }) + .then(dataUrl => { return dataUrl; - }).catch(e => console.error(e)); + }) + .catch(e => console.error(e)); } async requestFileTransfer(files) { @@ -647,7 +659,8 @@ class Peer { this._busy = false; Events.fire('notify-user', Localization.getTranslation("notifications.file-transfer-completed")); Events.fire('files-sent'); // used by 'Snapdrop & PairDrop for Android' app - } else { + } + else { this._dequeueFile(); } } @@ -710,7 +723,8 @@ class RTCPeer extends Peer { if (this._isCaller) { this._openChannel(); - } else { + } + else { this._conn.ondatachannel = e => this._onChannelOpened(e); } } @@ -740,7 +754,8 @@ class RTCPeer extends Peer { _onDescription(description) { // description.sdp = description.sdp.replace('b=AS:30', 'b=AS:1638400'); - this._conn.setLocalDescription(description) + this._conn + .setLocalDescription(description) .then(_ => this._sendSignal({ sdp: description })) .catch(e => this._onError(e)); } @@ -754,16 +769,20 @@ class RTCPeer extends Peer { if (!this._conn) this._connect(); if (message.sdp) { - this._conn.setRemoteDescription(message.sdp) + this._conn + .setRemoteDescription(message.sdp) .then(_ => { if (message.sdp.type === 'offer') { - return this._conn.createAnswer() + return this._conn + .createAnswer() .then(d => this._onDescription(d)); } }) .catch(e => this._onError(e)); - } else if (message.ice) { - this._conn.addIceCandidate(new RTCIceCandidate(message.ice)) + } + else if (message.ice) { + this._conn + .addIceCandidate(new RTCIceCandidate(message.ice)) .catch(e => this._onError(e)); } } @@ -1007,7 +1026,8 @@ class PeersManager { if (window.isRtcSupported && rtcSupported) { this.peers[peerId] = new RTCPeer(this._server,isCaller, peerId, roomType, roomId); - } else { + } + else { this.peers[peerId] = new WSPeer(this._server, isCaller, peerId, roomType, roomId); } } @@ -1063,10 +1083,11 @@ class PeersManager { // If no peers are connected anymore, we can safely assume that no other tab on the same browser is connected: // Tidy up peerIds in localStorage if (Object.keys(this.peers).length === 0) { - BrowserTabsConnector.removeOtherPeerIdsFromLocalStorage().then(peerIds => { - if (!peerIds) return; - console.log("successfully removed other peerIds from localStorage"); - }); + BrowserTabsConnector.removeOtherPeerIdsFromLocalStorage() + .then(peerIds => { + if (!peerIds) return; + console.log("successfully removed other peerIds from localStorage"); + }); } } } @@ -1124,16 +1145,19 @@ class PeersManager { if (peer._getRoomTypes().length > 1) { peer._removeRoomType(roomType); - } else { + } + else { Events.fire('peer-disconnected', peerId); } } _onRoomSecretRegenerated(message) { - PersistentStorage.updateRoomSecret(message.oldRoomSecret, message.newRoomSecret).then(_ => { - console.log("successfully regenerated room secret"); - Events.fire("room-secrets", [message.newRoomSecret]); - }) + PersistentStorage + .updateRoomSecret(message.oldRoomSecret, message.newRoomSecret) + .then(_ => { + console.log("successfully regenerated room secret"); + Events.fire("room-secrets", [message.newRoomSecret]); + }) } _notifyPeersDisplayNameChanged(newDisplayName) { diff --git a/public_included_ws_fallback/scripts/theme.js b/public_included_ws_fallback/scripts/theme.js index 81cf0b2..33ea0b3 100644 --- a/public_included_ws_fallback/scripts/theme.js +++ b/public_included_ws_fallback/scripts/theme.js @@ -1,78 +1,83 @@ (function(){ - const prefersDarkTheme = window.matchMedia('(prefers-color-scheme: dark)').matches; - const prefersLightTheme = window.matchMedia('(prefers-color-scheme: light)').matches; + const prefersDarkTheme = window.matchMedia('(prefers-color-scheme: dark)').matches; + const prefersLightTheme = window.matchMedia('(prefers-color-scheme: light)').matches; - const $themeAuto = document.getElementById('theme-auto'); - const $themeLight = document.getElementById('theme-light'); - const $themeDark = document.getElementById('theme-dark'); + const $themeAuto = document.getElementById('theme-auto'); + const $themeLight = document.getElementById('theme-light'); + const $themeDark = document.getElementById('theme-dark'); - let currentTheme = localStorage.getItem('theme'); + let currentTheme = localStorage.getItem('theme'); - if (currentTheme === 'dark') { - setModeToDark(); - } else if (currentTheme === 'light') { - setModeToLight(); - } - - $themeAuto.addEventListener('click', _ => { - if (currentTheme) { - setModeToAuto(); - } else { - setModeToDark(); + if (currentTheme === 'dark') { + setModeToDark(); } - }); - $themeLight.addEventListener('click', _ => { - if (currentTheme !== 'light') { - setModeToLight(); - } else { - setModeToAuto(); + else if (currentTheme === 'light') { + setModeToLight(); } - }); - $themeDark.addEventListener('click', _ => { - if (currentTheme !== 'dark') { - setModeToDark(); - } else { - setModeToLight(); + + $themeAuto.addEventListener('click', _ => { + if (currentTheme) { + setModeToAuto(); + } + else { + setModeToDark(); + } + }); + $themeLight.addEventListener('click', _ => { + if (currentTheme !== 'light') { + setModeToLight(); + } + else { + setModeToAuto(); + } + }); + $themeDark.addEventListener('click', _ => { + if (currentTheme !== 'dark') { + setModeToDark(); + } + else { + setModeToLight(); + } + }); + + function setModeToDark() { + document.body.classList.remove('light-theme'); + document.body.classList.add('dark-theme'); + localStorage.setItem('theme', 'dark'); + currentTheme = 'dark'; + + $themeAuto.classList.remove("selected"); + $themeLight.classList.remove("selected"); + $themeDark.classList.add("selected"); } - }); - function setModeToDark() { - document.body.classList.remove('light-theme'); - document.body.classList.add('dark-theme'); - localStorage.setItem('theme', 'dark'); - currentTheme = 'dark'; + function setModeToLight() { + document.body.classList.remove('dark-theme'); + document.body.classList.add('light-theme'); + localStorage.setItem('theme', 'light'); + currentTheme = 'light'; - $themeAuto.classList.remove("selected"); - $themeLight.classList.remove("selected"); - $themeDark.classList.add("selected"); - } - - function setModeToLight() { - document.body.classList.remove('dark-theme'); - document.body.classList.add('light-theme'); - localStorage.setItem('theme', 'light'); - currentTheme = 'light'; - - $themeAuto.classList.remove("selected"); - $themeLight.classList.add("selected"); - $themeDark.classList.remove("selected"); - } - - function setModeToAuto() { - document.body.classList.remove('dark-theme'); - document.body.classList.remove('light-theme'); - if (prefersDarkTheme) { - document.body.classList.add('dark-theme'); - } else if (prefersLightTheme) { - document.body.classList.add('light-theme'); + $themeAuto.classList.remove("selected"); + $themeLight.classList.add("selected"); + $themeDark.classList.remove("selected"); } - localStorage.removeItem('theme'); - currentTheme = undefined; - $themeAuto.classList.add("selected"); - $themeLight.classList.remove("selected"); - $themeDark.classList.remove("selected"); - } + function setModeToAuto() { + document.body.classList.remove('dark-theme'); + document.body.classList.remove('light-theme'); + if (prefersDarkTheme) { + document.body.classList.add('dark-theme'); + } + else if (prefersLightTheme) { + document.body.classList.add('light-theme'); + } + localStorage.removeItem('theme'); + currentTheme = undefined; + + $themeAuto.classList.add("selected"); + $themeLight.classList.remove("selected"); + $themeDark.classList.remove("selected"); + } })(); diff --git a/public_included_ws_fallback/scripts/ui.js b/public_included_ws_fallback/scripts/ui.js index 705d398..3cde8da 100644 --- a/public_included_ws_fallback/scripts/ui.js +++ b/public_included_ws_fallback/scripts/ui.js @@ -64,10 +64,13 @@ class PeersUI { } _loadSavedDisplayName() { - this._getSavedDisplayName().then(displayName => { - console.log("Retrieved edited display name:", displayName) - if (displayName) Events.fire('self-display-name-changed', displayName); - }); + this._getSavedDisplayName() + .then(displayName => { + console.log("Retrieved edited display name:", displayName) + if (displayName) { + Events.fire('self-display-name-changed', displayName); + } + }); } _onDisplayName(displayName){ @@ -104,7 +107,8 @@ class PeersUI { if (this.$discoveryWrapper.querySelectorAll('div:last-of-type > span[hidden]').length < 2) { this.$discoveryWrapper.classList.remove('row'); this.$discoveryWrapper.classList.add('column'); - } else { + } + else { this.$discoveryWrapper.classList.remove('column'); this.$discoveryWrapper.classList.add('row'); } @@ -147,7 +151,8 @@ class PeersUI { Events.fire('self-display-name-changed', newDisplayName); Events.fire('broadcast-send', {type: 'self-display-name-changed', detail: newDisplayName}); }); - } else { + } + else { PersistentStorage.delete('editedDisplayName') .catch(_ => { console.log("This browser does not support IndexedDB. Use localStorage instead.") @@ -188,8 +193,12 @@ class PeersUI { this._changePeerDisplayName(e.detail.peerId, e.detail.displayName); } + _isAnyDialogShown() { + return document.querySelectorAll('x-dialog[show]').length === 0; + } + _onKeyDown(e) { - if (document.querySelectorAll('x-dialog[show]').length === 0 && window.pasteMode.activated && e.code === "Escape") { + if (this._isAnyDialogShown() && window.pasteMode.activated && e.code === "Escape") { Events.fire('deactivate-paste-mode'); } @@ -245,7 +254,8 @@ class PeersUI { _evaluateOverflowing() { if (this.$xPeers.clientHeight < this.$xPeers.scrollHeight) { this.$xPeers.classList.add('overflowing'); - } else { + } + else { this.$xPeers.classList.remove('overflowing'); } } @@ -319,9 +329,11 @@ class PeersUI { if (files.length === 1) { descriptor = `${files[0].name}`; - } else if (files.length > 1) { + } + else if (files.length > 1) { descriptor = `${files[0].name}
${andOtherFiles}`; - } else { + } + else { descriptor = sharedText; } @@ -380,7 +392,8 @@ class PeersUI { files: files, to: peerId }); - } else if (text.length > 0) { + } + else if (text.length > 0) { Events.fire('send-text', { text: text, to: peerId @@ -408,7 +421,8 @@ class PeerUI { let input = ''; if (window.pasteMode.activated) { title = Localization.getTranslation("peer-ui.click-to-send-paste-mode", null, {descriptor: window.pasteMode.descriptor}); - } else { + } + else { title = Localization.getTranslation("peer-ui.click-to-send"); input = ''; } @@ -500,7 +514,8 @@ class PeerUI { this.$el.addEventListener('contextmenu', this._callbackContextMenu); this.$el.addEventListener('touchstart', this._callbackTouchStart); this.$el.addEventListener('touchend', this._callbackTouchEnd); - } else { + } + else { // Remove Events Normal Mode this.$el.removeEventListener('click', this._callbackClickSleep); this.$el.removeEventListener('touchstart', this._callbackTouchStartSleep); @@ -568,7 +583,8 @@ class PeerUI { const $progress = this.$el.querySelector('.progress'); if (0.5 < progress && progress < 1) { $progress.classList.add('over50'); - } else { + } + else { $progress.classList.remove('over50'); } if (progress < 1) { @@ -584,7 +600,8 @@ class PeerUI { this.$el.querySelector('.status').innerText = statusName; this.currentStatus = status; } - } else { + } + else { this.$el.removeAttribute('status'); this.$el.querySelector('.status').innerHTML = ''; progress = 0; @@ -629,7 +646,8 @@ class PeerUI { _onTouchEnd(e) { if (Date.now() - this._touchStart < 500) { clearTimeout(this._touchTimer); - } else if (this._touchTimer) { // this was a long tap + } + else if (this._touchTimer) { // this was a long tap e.preventDefault(); Events.fire('text-recipient', { peerId: this._peer.id, @@ -643,7 +661,9 @@ class PeerUI { class Dialog { constructor(id) { this.$el = $(id); - this.$el.querySelectorAll('[close]').forEach(el => el.addEventListener('click', _ => this.hide())); + this.$el.querySelectorAll('[close]').forEach(el => { + el.addEventListener('click', _ => this.hide()) + }); this.$autoFocus = this.$el.querySelector('[autofocus]'); Events.on('peer-disconnected', e => this._onPeerDisconnected(e.detail)); @@ -701,7 +721,8 @@ class LanguageSelectDialog extends Dialog { show() { if (Localization.isSystemLocale()) { this.$languageButtons[0].focus(); - } else { + } + else { let locale = Localization.getLocale(); for (let i=0; i= 1073741824) { return Math.round(10 * bytes / 1073741824) / 10 + ' GB'; - } else if (bytes >= 1048576) { + } + else if (bytes >= 1048576) { return Math.round(bytes / 1048576) + ' MB'; - } else if (bytes > 1024) { + } + else if (bytes > 1024) { return Math.round(bytes / 1024) + ' KB'; - } else { + } + else { return bytes + ' Bytes'; } } @@ -763,7 +788,8 @@ class ReceiveDialog extends Dialog { fileOther = imagesOnly ? Localization.getTranslation("dialogs.file-other-description-image") : Localization.getTranslation("dialogs.file-other-description-file"); - } else if (files.length >= 2) { + } + else if (files.length >= 2) { fileOther = imagesOnly ? Localization.getTranslation("dialogs.file-other-description-image-plural", null, {count: files.length - 1}) : Localization.getTranslation("dialogs.file-other-description-file-plural", null, {count: files.length - 1}); @@ -847,7 +873,8 @@ class ReceiveFileDialog extends ReceiveDialog { if (Object.keys(previewElement).indexOf(mime) === -1) { resolve(false); - } else { + } + else { let element = document.createElement(previewElement[mime]); element.controls = true; element.onload = _ => { @@ -877,7 +904,8 @@ class ReceiveFileDialog extends ReceiveDialog { descriptor = imagesOnly ? Localization.getTranslation("dialogs.title-image") : Localization.getTranslation("dialogs.title-file"); - } else { + } + else { descriptor = imagesOnly ? Localization.getTranslation("dialogs.title-image-plural") : Localization.getTranslation("dialogs.title-file-plural"); @@ -939,7 +967,8 @@ class ReceiveFileDialog extends ReceiveDialog { tmpZipBtn.download = filenameDownload; tmpZipBtn.href = url; tmpZipBtn.click(); - } else { + } + else { this._downloadFilesIndividually(files); } @@ -962,7 +991,8 @@ class ReceiveFileDialog extends ReceiveDialog { setTimeout(() => { if (canShare) { this.$shareBtn.click(); - } else { + } + else { this.$downloadBtn.click(); } }, 500); @@ -971,7 +1001,8 @@ class ReceiveFileDialog extends ReceiveDialog { .then(canPreview => { if (canPreview) { console.log('the file is able to preview'); - } else { + } + else { console.log('the file is not able to preview'); } }) @@ -1134,10 +1165,12 @@ class InputKeyContainer { if (e.key === "Backspace" && previousSibling && !e.target.value) { previousSibling.value = ''; previousSibling.focus(); - } else if (e.key === "ArrowRight" && nextSibling) { + } + else if (e.key === "ArrowRight" && nextSibling) { e.preventDefault(); nextSibling.focus(); - } else if (e.key === "ArrowLeft" && previousSibling) { + } + else if (e.key === "ArrowLeft" && previousSibling) { e.preventDefault(); previousSibling.focus(); } @@ -1173,7 +1206,8 @@ class InputKeyContainer { _evaluateKeyChars() { if (this.$inputKeyContainer.querySelectorAll('input:placeholder-shown').length > 0) { this._onNotAllCharsFilled(); - } else { + } + else { this._onAllCharsFilled(); const lastCharFocused = document.activeElement === this.$inputKeyChars[this.$inputKeyChars.length - 1]; @@ -1243,7 +1277,10 @@ class PairDeviceDialog extends Dialog { _onPaste(e) { e.preventDefault(); - let pastedKey = e.clipboardData.getData("Text").replace(/\D/g,'').substring(0, 6); + let pastedKey = e.clipboardData + .getData("Text") + .replace(/\D/g,'') + .substring(0, 6); this.inputKeyContainer._onPaste(pastedKey); } @@ -1366,7 +1403,8 @@ class PairDeviceDialog extends Dialog { deviceName = $peer.ui._peer.name.deviceName; } - PersistentStorage.addRoomSecret(roomSecret, displayName, deviceName) + PersistentStorage + .addRoomSecret(roomSecret, displayName, deviceName) .then(_ => { Events.fire('notify-user', Localization.getTranslation("notifications.pairing-success")); this._evaluateNumberRoomSecrets(); @@ -1407,18 +1445,22 @@ class PairDeviceDialog extends Dialog { } _onSecretRoomDeleted(roomSecret) { - PersistentStorage.deleteRoomSecret(roomSecret).then(_ => { - this._evaluateNumberRoomSecrets(); - }); + PersistentStorage + .deleteRoomSecret(roomSecret) + .then(_ => { + this._evaluateNumberRoomSecrets(); + }); } _evaluateNumberRoomSecrets() { - PersistentStorage.getAllRoomSecrets() + PersistentStorage + .getAllRoomSecrets() .then(roomSecrets => { if (roomSecrets.length > 0) { this.$editPairedDevicesHeaderBtn.removeAttribute('hidden'); this.$footerInstructionsPairedDevices.removeAttribute('hidden'); - } else { + } + else { this.$editPairedDevicesHeaderBtn.setAttribute('hidden', ''); this.$footerInstructionsPairedDevices.setAttribute('hidden', ''); } @@ -1452,45 +1494,51 @@ class EditPairedDevicesDialog extends Dialog { const autoAcceptString = Localization.getTranslation("dialogs.auto-accept").toLowerCase(); const roomSecretsEntries = await PersistentStorage.getAllRoomSecretEntries(); - roomSecretsEntries.forEach(roomSecretsEntry => { - let $pairedDevice = document.createElement('div'); - $pairedDevice.classList = ["paired-device"]; + roomSecretsEntries + .forEach(roomSecretsEntry => { + let $pairedDevice = document.createElement('div'); + $pairedDevice.classList = ["paired-device"]; - $pairedDevice.innerHTML = ` -
- ${roomSecretsEntry.display_name} -
-
- ${roomSecretsEntry.device_name} -
-
- - -
` + $pairedDevice.innerHTML = ` +
+ ${roomSecretsEntry.display_name} +
+
+ ${roomSecretsEntry.device_name} +
+
+ + +
` - $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('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(); - }); + $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.html = ""; + this.$pairedDevicesWrapper.appendChild($pairedDevice) }) - - this.$pairedDevicesWrapper.html = ""; - this.$pairedDevicesWrapper.appendChild($pairedDevice) - }) - } hide() { @@ -1505,14 +1553,17 @@ class EditPairedDevicesDialog extends Dialog { } _clearRoomSecrets() { - PersistentStorage.getAllRoomSecrets() + PersistentStorage + .getAllRoomSecrets() .then(roomSecrets => { - PersistentStorage.clearRoomSecrets().finally(() => { - Events.fire('room-secrets-deleted', roomSecrets); - Events.fire('evaluate-number-room-secrets'); - Events.fire('notify-user', Localization.getTranslation("notifications.pairing-cleared")); - this.hide(); - }) + PersistentStorage + .clearRoomSecrets() + .finally(() => { + Events.fire('room-secrets-deleted', roomSecrets); + Events.fire('evaluate-number-room-secrets'); + Events.fire('notify-user', Localization.getTranslation("notifications.pairing-cleared")); + this.hide(); + }) }); } @@ -1526,9 +1577,11 @@ class EditPairedDevicesDialog extends Dialog { if (!peer || !peer._roomIds["secret"]) return; - PersistentStorage.updateRoomSecretNames(peer._roomIds["secret"], peer.name.displayName, peer.name.deviceName).then(roomSecretEntry => { - console.log(`Successfully updated DisplayName and DeviceName for roomSecretEntry ${roomSecretEntry.key}`); - }) + PersistentStorage + .updateRoomSecretNames(peer._roomIds["secret"], peer.name.displayName, peer.name.deviceName) + .then(roomSecretEntry => { + console.log(`Successfully updated DisplayName and DeviceName for roomSecretEntry ${roomSecretEntry.key}`); + }) } } @@ -1591,7 +1644,8 @@ class PublicRoomDialog extends Dialog { _onHeaderBtnClick() { if (this.roomId) { this.show(); - } else { + } + else { this._createPublicRoom(); } } @@ -1784,7 +1838,8 @@ class SendTextDialog extends Dialog { if (e.code === "Escape") { this.hide(); - } else if (e.code === "Enter" && (e.ctrlKey || e.metaKey)) { + } + else if (e.code === "Enter" && (e.ctrlKey || e.metaKey)) { if (this._textInputEmpty()) return; this._send(); } @@ -1797,7 +1852,8 @@ class SendTextDialog extends Dialog { _onChange(e) { if (this._textInputEmpty()) { this.$submit.setAttribute('disabled', ''); - } else { + } + else { this.$submit.removeAttribute('disabled'); } } @@ -1855,7 +1911,8 @@ class ReceiveTextDialog extends Dialog { if (e.code === "KeyC" && (e.ctrlKey || e.metaKey)) { await this._onCopy() this.hide(); - } else if (e.code === "Escape") { + } + else if (e.code === "Escape") { this.hide(); } } @@ -1905,7 +1962,8 @@ class ReceiveTextDialog extends Dialog { async _onCopy() { const sanitizedText = this.$text.innerText.replace(/\u00A0/gm, ' '); - navigator.clipboard.writeText(sanitizedText) + navigator.clipboard + .writeText(sanitizedText) .then(_ => { Events.fire('notify-user', Localization.getTranslation("notifications.copied-to-clipboard")); this.hide(); @@ -1939,7 +1997,8 @@ class Base64ZipDialog extends Dialog { // ?base64text=paste // base64 encoded string is ready to be pasted from clipboard this.preparePasting('text'); - } else if (base64Text === 'hash') { + } + else if (base64Text === 'hash') { // ?base64text=hash#BASE64ENCODED // base64 encoded string is url hash which is never sent to server and faster (recommended) this.processBase64Text(base64Hash) @@ -1949,7 +2008,8 @@ class Base64ZipDialog extends Dialog { }).finally(() => { this.hide(); }); - } else { + } + else { // ?base64text=BASE64ENCODED // base64 encoded string was part of url param (not recommended) this.processBase64Text(base64Text) @@ -1960,7 +2020,8 @@ class Base64ZipDialog extends Dialog { this.hide(); }); } - } else if (base64Zip) { + } + else if (base64Zip) { this.show(); if (base64Zip === "hash") { // ?base64zip=hash#BASE64ENCODED @@ -1972,7 +2033,8 @@ class Base64ZipDialog extends Dialog { }).finally(() => { this.hide(); }); - } else { + } + else { // ?base64zip=paste || ?base64zip=true this.preparePasting('files'); } @@ -1993,7 +2055,8 @@ class Base64ZipDialog extends Dialog { this.$pasteBtn.innerText = Localization.getTranslation("dialogs.base64-tap-to-paste", null, {type: translateType}); this._clickCallback = _ => this.processClipboard(type); this.$pasteBtn.addEventListener('click', _ => this._clickCallback()); - } else { + } + else { console.log("`navigator.clipboard.readText()` is not available on your browser.\nOn Firefox you can set `dom.events.asyncClipboard.readText` to true under `about:config` for convenience.") this.$pasteBtn.setAttribute('hidden', ''); this.$fallbackTextarea.setAttribute('placeholder', Localization.getTranslation("dialogs.base64-paste-to-send", null, {type: translateType})); @@ -2032,7 +2095,8 @@ class Base64ZipDialog extends Dialog { try { if (type === 'text') { await this.processBase64Text(base64); - } else { + } + else { await this.processBase64Zip(base64); } } catch(_) { @@ -2163,7 +2227,8 @@ class Notifications { if (/^((https?:\/\/|www)[abcdefghijklmnopqrstuvwxyz0123456789\-._~:\/?#\[\]@!$&'()*+,;=]+)$/.test(message.toLowerCase())) { const notification = this._notify(Localization.getTranslation("notifications.link-received", null, {name: peerDisplayName}), message); this._bind(notification, _ => window.open(message, '_blank', "noreferrer")); - } else { + } + else { const notification = this._notify(Localization.getTranslation("notifications.message-received", null, {name: peerDisplayName}), message); this._bind(notification, _ => this._copyText(message, notification)); } @@ -2182,13 +2247,15 @@ class Notifications { let title; if (files.length === 1) { title = `${files[0].name}`; - } else { + } + else { let fileOther; if (files.length === 2) { fileOther = imagesOnly ? Localization.getTranslation("dialogs.file-other-description-image") : Localization.getTranslation("dialogs.file-other-description-file"); - } else { + } + else { fileOther = imagesOnly ? Localization.getTranslation("dialogs.file-other-description-image-plural", null, {count: files.length - 1}) : Localization.getTranslation("dialogs.file-other-description-file-plural", null, {count: files.length - 1}); @@ -2217,17 +2284,19 @@ class Notifications { descriptor = imagesOnly ? Localization.getTranslation("dialogs.title-image") : Localization.getTranslation("dialogs.title-file"); - } else { + } + else { descriptor = imagesOnly ? Localization.getTranslation("dialogs.title-image-plural") : Localization.getTranslation("dialogs.title-file-plural"); } - let title = Localization.getTranslation("notifications.request-title", null, { - name: displayName, - count: request.header.length, - descriptor: descriptor.toLowerCase() - }); + let title = Localization + .getTranslation("notifications.request-title", null, { + name: displayName, + count: request.header.length, + descriptor: descriptor.toLowerCase() + }); const notification = this._notify(title, Localization.getTranslation("notifications.click-to-show")); } @@ -2242,17 +2311,23 @@ class Notifications { if (await navigator.clipboard.writeText(message)) { notification.close(); this._notify(Localization.getTranslation("notifications.copied-text")); - } else { + } + else { this._notify(Localization.getTranslation("notifications.copied-text-error")); } } _bind(notification, handler) { if (notification.then) { - notification.then(_ => serviceWorker.getNotifications().then(_ => { - serviceWorker.addEventListener('notificationclick', handler); - })); - } else { + notification.then(_ => { + serviceWorker + .getNotifications() + .then(_ => { + serviceWorker.addEventListener('notificationclick', handler); + }) + }); + } + else { notification.onclick = handler; } } @@ -2291,14 +2366,17 @@ class WebShareTargetUI { if (url) { shareTargetText = url; // we share only the link - no text. - } else if (title && text) { + } + else if (title && text) { shareTargetText = title + '\r\n' + text; - } else { + } + else { shareTargetText = title + text; } Events.fire('activate-paste-mode', {files: [], text: shareTargetText}) - } else if (share_target_type === "files") { + } + else if (share_target_type === "files") { let openRequest = window.indexedDB.open('pairdrop_store') openRequest.onsuccess = e => { const db = e.target.result; @@ -2820,7 +2898,8 @@ const pairDrop = new PairDrop(); const localization = new Localization(); if ('serviceWorker' in navigator) { - navigator.serviceWorker.register('/service-worker.js') + navigator.serviceWorker + .register('/service-worker.js') .then(serviceWorker => { console.log('Service Worker registered'); window.serviceWorker = serviceWorker diff --git a/public_included_ws_fallback/scripts/util.js b/public_included_ws_fallback/scripts/util.js index 740325b..a6cae64 100644 --- a/public_included_ws_fallback/scripts/util.js +++ b/public_included_ws_fallback/scripts/util.js @@ -55,7 +55,8 @@ const zipper = (() => { const blobURL = URL.createObjectURL(await zipWriter.close()); zipWriter = null; return blobURL; - } else { + } + else { throw new Error("Zip file closed"); } }, @@ -64,7 +65,8 @@ const zipper = (() => { const file = new File([await zipWriter.close()], filename, {type: "application/zip"}); zipWriter = null; return file; - } else { + } + else { throw new Error("Zip file closed"); } }, diff --git a/public_included_ws_fallback/service-worker.js b/public_included_ws_fallback/service-worker.js index d344408..54f4ebc 100644 --- a/public_included_ws_fallback/service-worker.js +++ b/public_included_ws_fallback/service-worker.js @@ -90,16 +90,19 @@ self.addEventListener('fetch', function(event) { const share_url = await evaluateRequestData(event.request); return Response.redirect(encodeURI(share_url), 302); })()); - } else { + } + else { // Regular requests not related to Web Share Target. if (forceFetch) { event.respondWith(fromNetwork(event.request, 10000)); - } else { + } + else { event.respondWith( - fromCache(event.request).then(rsp => { - // if fromCache resolves to undefined fetch from network instead - return rsp || fromNetwork(event.request, 10000); - }) + fromCache(event.request) + .then(rsp => { + // if fromCache resolves to undefined fetch from network instead + return rsp || fromNetwork(event.request, 10000); + }) ); } } @@ -109,15 +112,16 @@ self.addEventListener('fetch', function(event) { // on activation, we clean up the previously registered service workers self.addEventListener('activate', evt => { return evt.waitUntil( - caches.keys().then(cacheNames => { - return Promise.all( - cacheNames.map(cacheName => { - if (cacheName !== cacheTitle) { - return caches.delete(cacheName); - } - }) - ); - }) + caches.keys() + .then(cacheNames => { + return Promise.all( + cacheNames.map(cacheName => { + if (cacheName !== cacheTitle) { + return caches.delete(cacheName); + } + }) + ); + }) ) } ); @@ -157,7 +161,8 @@ const evaluateRequestData = function (request) { DBOpenRequest.onerror = _ => { resolve(pairDropUrl); } - } else { + } + else { let urlArgument = '?share-target=text'; if (title) urlArgument += `&title=${title}`;