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