mirror of
https://github.com/schlagmichdoch/PairDrop.git
synced 2025-04-21 07:16:18 -04:00
Speed up initial load while still preventing css layout shift; Tidy up ui.js
This commit is contained in:
parent
2578803a78
commit
ed2f1b0c61
8 changed files with 353 additions and 312 deletions
|
@ -38,7 +38,7 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body translate="no">
|
<body translate="no">
|
||||||
<header class="row-reverse">
|
<header class="row-reverse opacity-0">
|
||||||
<a href="#about" class="icon-button" data-i18n-key="header.about" data-i18n-attrs="title aria-label">
|
<a href="#about" class="icon-button" data-i18n-key="header.about" data-i18n-attrs="title aria-label">
|
||||||
<svg class="icon">
|
<svg class="icon">
|
||||||
<use xlink:href="#info-outline"></use>
|
<use xlink:href="#info-outline"></use>
|
||||||
|
@ -96,11 +96,11 @@
|
||||||
<div id="cancel-paste-mode" class="button" data-i18n-key="header.cancel-paste-mode" data-i18n-attrs="text" hidden></div>
|
<div id="cancel-paste-mode" class="button" data-i18n-key="header.cancel-paste-mode" data-i18n-attrs="text" hidden></div>
|
||||||
</header>
|
</header>
|
||||||
<!-- Center -->
|
<!-- Center -->
|
||||||
<div id="center">
|
<div id="center" class="opacity-0">
|
||||||
<!-- Peers -->
|
<!-- Peers -->
|
||||||
<div class="x-peers-filler"></div>
|
<div class="x-peers-filler"></div>
|
||||||
<x-peers class="center"></x-peers>
|
<x-peers class="center"></x-peers>
|
||||||
<x-no-peers data-i18n-key="instructions.no-peers" data-i18n-attrs="data-drop-bg">
|
<x-no-peers class="no-animation-on-load" data-i18n-key="instructions.no-peers" data-i18n-attrs="data-drop-bg">
|
||||||
<h2 data-i18n-key="instructions.no-peers-title" data-i18n-attrs="text"></h2>
|
<h2 data-i18n-key="instructions.no-peers-title" data-i18n-attrs="text"></h2>
|
||||||
<div data-i18n-key="instructions.no-peers-subtitle" data-i18n-attrs="text"></div>
|
<div data-i18n-key="instructions.no-peers-subtitle" data-i18n-attrs="text"></div>
|
||||||
</x-no-peers>
|
</x-no-peers>
|
||||||
|
@ -109,7 +109,7 @@
|
||||||
</x-instructions>
|
</x-instructions>
|
||||||
</div>
|
</div>
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<footer class="column">
|
<footer class="column opacity-0">
|
||||||
<svg class="icon logo">
|
<svg class="icon logo">
|
||||||
<use xlink:href="#wifi-tethering"></use>
|
<use xlink:href="#wifi-tethering"></use>
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -466,14 +466,14 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- About Page -->
|
<!-- About Page -->
|
||||||
<x-about id="about" class="full center column">
|
<x-about id="about" class="full center column">
|
||||||
<header class="row-reverse fade-in">
|
<header class="row-reverse">
|
||||||
<a href="#" class="close icon-button" data-i18n-key="about.close-about" data-i18n-attrs="aria-label">
|
<a href="#" class="close icon-button" data-i18n-key="about.close-about" data-i18n-attrs="aria-label">
|
||||||
<svg class="icon">
|
<svg class="icon">
|
||||||
<use xlink:href="#close-icon"></use>
|
<use xlink:href="#close-icon"></use>
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
</header>
|
</header>
|
||||||
<section class="center column fade-in">
|
<section class="center column">
|
||||||
<svg class="icon logo">
|
<svg class="icon logo">
|
||||||
<use xlink:href="#wifi-tethering"></use>
|
<use xlink:href="#wifi-tethering"></use>
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -507,7 +507,7 @@
|
||||||
</section>
|
</section>
|
||||||
<x-background></x-background>
|
<x-background></x-background>
|
||||||
</x-about>
|
</x-about>
|
||||||
<canvas class="circles"></canvas>
|
<canvas class="circles opacity-0"></canvas>
|
||||||
<!-- SVG Icon Library -->
|
<!-- SVG Icon Library -->
|
||||||
<svg style="display: none;">
|
<svg style="display: none;">
|
||||||
<symbol id="wifi-tethering" viewBox="0 0 24 24">
|
<symbol id="wifi-tethering" viewBox="0 0 24 24">
|
||||||
|
@ -587,7 +587,7 @@
|
||||||
<script src="scripts/theme.js"></script>
|
<script src="scripts/theme.js"></script>
|
||||||
<script src="scripts/network.js"></script>
|
<script src="scripts/network.js"></script>
|
||||||
<script src="scripts/ui.js"></script>
|
<script src="scripts/ui.js"></script>
|
||||||
<script src="scripts/util.js" async></script>
|
<script src="scripts/util.js"></script>
|
||||||
<script src="scripts/QRCode.min.js" async></script>
|
<script src="scripts/QRCode.min.js" async></script>
|
||||||
<script src="scripts/zip.min.js" async></script>
|
<script src="scripts/zip.min.js" async></script>
|
||||||
<script src="scripts/NoSleep.min.js" async></script>
|
<script src="scripts/NoSleep.min.js" async></script>
|
||||||
|
|
|
@ -36,27 +36,15 @@ class PeersUI {
|
||||||
Events.on('drop', e => this._onDrop(e));
|
Events.on('drop', e => this._onDrop(e));
|
||||||
Events.on('keydown', e => this._onKeyDown(e));
|
Events.on('keydown', e => this._onKeyDown(e));
|
||||||
|
|
||||||
this.$header = document.querySelector('body > header')
|
|
||||||
this.$xPeers = $$('x-peers');
|
this.$xPeers = $$('x-peers');
|
||||||
this.$xNoPeers = $$('x-no-peers');
|
this.$xNoPeers = $$('x-no-peers');
|
||||||
this.$xInstructions = $$('x-instructions');
|
this.$xInstructions = $$('x-instructions');
|
||||||
this.$center = $$('#center');
|
this.$center = $$('#center');
|
||||||
this.$logo = $$('footer .icon.logo');
|
this.$footer = $$('footer');
|
||||||
this.$discoveryWrapper = $$('footer .discovery-wrapper');
|
this.$discoveryWrapper = $$('footer .discovery-wrapper');
|
||||||
this.$knownAsWrapper = $$('footer .known-as-wrapper');
|
|
||||||
|
|
||||||
this.$header.style.opacity = "1";
|
Events.on('peer-added', _ => this._evaluateOverflowing());
|
||||||
this.$xPeers.style.opacity = "1";
|
Events.on('bg-resize', _ => this._evaluateOverflowing());
|
||||||
this.$xNoPeers.style.opacity = "1";
|
|
||||||
this.$xInstructions.style.opacity = "0.5";
|
|
||||||
this.$center.style.opacity = "1";
|
|
||||||
this.$logo.style.opacity = "1";
|
|
||||||
this.$discoveryWrapper.style.opacity = "1";
|
|
||||||
this.$knownAsWrapper.style.opacity = "1";
|
|
||||||
|
|
||||||
|
|
||||||
Events.on('peer-added', _ => this.evaluateOverflowing());
|
|
||||||
Events.on('bg-resize', _ => this.evaluateOverflowing());
|
|
||||||
|
|
||||||
this.$displayName = $('display-name');
|
this.$displayName = $('display-name');
|
||||||
|
|
||||||
|
@ -75,11 +63,45 @@ class PeersUI {
|
||||||
if (displayName) Events.fire('self-display-name-changed', displayName);
|
if (displayName) Events.fire('self-display-name-changed', displayName);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Events.on('evaluate-footer-badges', _ => this._evaluateFooterBadges())
|
||||||
|
|
||||||
/* prevent animation on load */
|
this.fadedIn = false;
|
||||||
|
|
||||||
|
this.$header = document.querySelector('header.opacity-0');
|
||||||
|
Events.on('header-evaluated', () => this._fadeInHeader());
|
||||||
|
}
|
||||||
|
|
||||||
|
_fadeInHeader() {
|
||||||
|
//prevent flickering
|
||||||
|
setTimeout(() => this.$header.classList.remove('opacity-0'), 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
_fadeInUI() {
|
||||||
|
if (this.fadedIn) return;
|
||||||
|
|
||||||
|
this.fadedIn = true;
|
||||||
|
|
||||||
|
this.$center.classList.remove('opacity-0');
|
||||||
|
this.$footer.classList.remove('opacity-0');
|
||||||
|
|
||||||
|
// Prevent flickering on load
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
this.$xNoPeers.style.animationIterationCount = "1";
|
this.$xNoPeers.classList.remove('no-animation-on-load');
|
||||||
}, 300);
|
}, 600);
|
||||||
|
|
||||||
|
Events.fire('ui-faded-in');
|
||||||
|
}
|
||||||
|
|
||||||
|
_evaluateFooterBadges() {
|
||||||
|
if (this.$discoveryWrapper.querySelectorAll('div:last-of-type > span[hidden]').length < 2) {
|
||||||
|
this.$discoveryWrapper.classList.remove('row');
|
||||||
|
this.$discoveryWrapper.classList.add('column');
|
||||||
|
} else {
|
||||||
|
this.$discoveryWrapper.classList.remove('column');
|
||||||
|
this.$discoveryWrapper.classList.add('row');
|
||||||
|
}
|
||||||
|
Events.fire('redraw-canvas');
|
||||||
|
this._fadeInUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
_insertDisplayName(displayName) {
|
_insertDisplayName(displayName) {
|
||||||
|
@ -162,6 +184,11 @@ class PeersUI {
|
||||||
if (document.querySelectorAll('x-dialog[show]').length === 0 && window.pasteMode.activated && e.code === "Escape") {
|
if (document.querySelectorAll('x-dialog[show]').length === 0 && window.pasteMode.activated && e.code === "Escape") {
|
||||||
Events.fire('deactivate-paste-mode');
|
Events.fire('deactivate-paste-mode');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// close About PairDrop page on Escape
|
||||||
|
if (e.key === "Escape") {
|
||||||
|
window.location.hash = '#';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPeerJoined(msg) {
|
_onPeerJoined(msg) {
|
||||||
|
@ -207,7 +234,7 @@ class PeersUI {
|
||||||
Object.keys(peer._roomIds).forEach(roomType => peerNode.classList.add(`type-${roomType}`));
|
Object.keys(peer._roomIds).forEach(roomType => peerNode.classList.add(`type-${roomType}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
|
@ -223,7 +250,7 @@ class PeersUI {
|
||||||
const $peer = $(peerId);
|
const $peer = $(peerId);
|
||||||
if (!$peer) return;
|
if (!$peer) return;
|
||||||
$peer.remove();
|
$peer.remove();
|
||||||
this.evaluateOverflowing();
|
this._evaluateOverflowing();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onRoomTypeRemoved(peerId, roomType) {
|
_onRoomTypeRemoved(peerId, roomType) {
|
||||||
|
@ -608,7 +635,6 @@ class Dialog {
|
||||||
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]');
|
||||||
this.$discoveryWrapper = $$('footer .discovery-wrapper');
|
|
||||||
|
|
||||||
Events.on('peer-disconnected', e => this._onPeerDisconnected(e.detail));
|
Events.on('peer-disconnected', e => this._onPeerDisconnected(e.detail));
|
||||||
}
|
}
|
||||||
|
@ -629,7 +655,7 @@ class Dialog {
|
||||||
window.blur();
|
window.blur();
|
||||||
}
|
}
|
||||||
document.title = 'PairDrop';
|
document.title = 'PairDrop';
|
||||||
document.changeFavicon("images/favicon-96x96.png");
|
changeFavicon("images/favicon-96x96.png");
|
||||||
this.correspondingPeerId = undefined;
|
this.correspondingPeerId = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,17 +665,6 @@ class Dialog {
|
||||||
Events.fire('notify-user', Localization.getTranslation("notifications.selected-peer-left"));
|
Events.fire('notify-user', Localization.getTranslation("notifications.selected-peer-left"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
evaluateFooterBadges() {
|
|
||||||
if (this.$discoveryWrapper.querySelectorAll('div:last-of-type > span[hidden]').length < 2) {
|
|
||||||
this.$discoveryWrapper.classList.remove('row');
|
|
||||||
this.$discoveryWrapper.classList.add('column');
|
|
||||||
} else {
|
|
||||||
this.$discoveryWrapper.classList.remove('column');
|
|
||||||
this.$discoveryWrapper.classList.add('row');
|
|
||||||
}
|
|
||||||
Events.fire('bg-resize');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class LanguageSelectDialog extends Dialog {
|
class LanguageSelectDialog extends Dialog {
|
||||||
|
@ -929,7 +944,7 @@ class ReceiveFileDialog extends ReceiveDialog {
|
||||||
document.title = files.length === 1
|
document.title = files.length === 1
|
||||||
? `${ Localization.getTranslation("document-titles.file-received") } - PairDrop`
|
? `${ Localization.getTranslation("document-titles.file-received") } - PairDrop`
|
||||||
: `${ Localization.getTranslation("document-titles.file-received-plural", null, {count: files.length}) } - PairDrop`;
|
: `${ Localization.getTranslation("document-titles.file-received-plural", null, {count: files.length}) } - PairDrop`;
|
||||||
document.changeFavicon("images/favicon-96x96-notification.png");
|
changeFavicon("images/favicon-96x96-notification.png");
|
||||||
|
|
||||||
Events.fire('set-progress', {peerId: peerId, progress: 1, status: 'process'})
|
Events.fire('set-progress', {peerId: peerId, progress: 1, status: 'process'})
|
||||||
this.show();
|
this.show();
|
||||||
|
@ -1026,7 +1041,7 @@ class ReceiveRequestDialog extends ReceiveDialog {
|
||||||
this.$receiveTitle.innerText = transferRequestTitle;
|
this.$receiveTitle.innerText = transferRequestTitle;
|
||||||
|
|
||||||
document.title = `${transferRequestTitle} - PairDrop`;
|
document.title = `${transferRequestTitle} - PairDrop`;
|
||||||
document.changeFavicon("images/favicon-96x96-notification.png");
|
changeFavicon("images/favicon-96x96-notification.png");
|
||||||
this.show();
|
this.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1190,7 +1205,6 @@ class PairDeviceDialog extends Dialog {
|
||||||
this.$closeBtn.addEventListener('click', _ => this._close());
|
this.$closeBtn.addEventListener('click', _ => this._close());
|
||||||
|
|
||||||
Events.on('keydown', e => this._onKeyDown(e));
|
Events.on('keydown', e => this._onKeyDown(e));
|
||||||
Events.on('ws-connected', _ => this._onWsConnected());
|
|
||||||
Events.on('ws-disconnected', _ => this.hide());
|
Events.on('ws-disconnected', _ => this.hide());
|
||||||
Events.on('pair-device-initiated', e => this._onPairDeviceInitiated(e.detail));
|
Events.on('pair-device-initiated', e => this._onPairDeviceInitiated(e.detail));
|
||||||
Events.on('pair-device-joined', e => this._onPairDeviceJoined(e.detail.peerId, e.detail.roomSecret));
|
Events.on('pair-device-joined', e => this._onPairDeviceJoined(e.detail.peerId, e.detail.roomSecret));
|
||||||
|
@ -1205,6 +1219,8 @@ class PairDeviceDialog extends Dialog {
|
||||||
this.evaluateUrlAttributes();
|
this.evaluateUrlAttributes();
|
||||||
|
|
||||||
this.pairPeer = {};
|
this.pairPeer = {};
|
||||||
|
|
||||||
|
this._evaluateNumberRoomSecrets();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onKeyDown(e) {
|
_onKeyDown(e) {
|
||||||
|
@ -1229,10 +1245,6 @@ class PairDeviceDialog extends Dialog {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onWsConnected() {
|
|
||||||
this._evaluateNumberRoomSecrets();
|
|
||||||
}
|
|
||||||
|
|
||||||
_pairDeviceInitiate() {
|
_pairDeviceInitiate() {
|
||||||
Events.fire('pair-device-initiate');
|
Events.fire('pair-device-initiate');
|
||||||
}
|
}
|
||||||
|
@ -1380,16 +1392,17 @@ class PairDeviceDialog extends Dialog {
|
||||||
}
|
}
|
||||||
|
|
||||||
_evaluateNumberRoomSecrets() {
|
_evaluateNumberRoomSecrets() {
|
||||||
PersistentStorage.getAllRoomSecrets().then(roomSecrets => {
|
PersistentStorage.getAllRoomSecrets()
|
||||||
if (roomSecrets.length > 0) {
|
.then(roomSecrets => {
|
||||||
this.$editPairedDevicesHeaderBtn.removeAttribute('hidden');
|
if (roomSecrets.length > 0) {
|
||||||
this.$footerInstructionsPairedDevices.removeAttribute('hidden');
|
this.$editPairedDevicesHeaderBtn.removeAttribute('hidden');
|
||||||
} else {
|
this.$footerInstructionsPairedDevices.removeAttribute('hidden');
|
||||||
this.$editPairedDevicesHeaderBtn.setAttribute('hidden', '');
|
} else {
|
||||||
this.$footerInstructionsPairedDevices.setAttribute('hidden', '');
|
this.$editPairedDevicesHeaderBtn.setAttribute('hidden', '');
|
||||||
}
|
this.$footerInstructionsPairedDevices.setAttribute('hidden', '');
|
||||||
super.evaluateFooterBadges();
|
}
|
||||||
});
|
Events.fire('evaluate-footer-badges');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1397,10 +1410,10 @@ class EditPairedDevicesDialog extends Dialog {
|
||||||
constructor() {
|
constructor() {
|
||||||
super('edit-paired-devices-dialog');
|
super('edit-paired-devices-dialog');
|
||||||
this.$pairedDevicesWrapper = this.$el.querySelector('.paired-devices-wrapper');
|
this.$pairedDevicesWrapper = this.$el.querySelector('.paired-devices-wrapper');
|
||||||
this.$footerInstructionsPairedDevices = $$('.discovery-wrapper .badge-room-secret');
|
this.$footerBadgePairedDevices = $$('.discovery-wrapper .badge-room-secret');
|
||||||
|
|
||||||
$('edit-paired-devices').addEventListener('click', _ => this._onEditPairedDevices());
|
$('edit-paired-devices').addEventListener('click', _ => this._onEditPairedDevices());
|
||||||
this.$footerInstructionsPairedDevices.addEventListener('click', _ => this._onEditPairedDevices());
|
this.$footerBadgePairedDevices.addEventListener('click', _ => this._onEditPairedDevices());
|
||||||
|
|
||||||
Events.on('peer-display-name-changed', e => this._onPeerDisplayNameChanged(e));
|
Events.on('peer-display-name-changed', e => this._onPeerDisplayNameChanged(e));
|
||||||
Events.on('keydown', e => this._onKeyDown(e));
|
Events.on('keydown', e => this._onKeyDown(e));
|
||||||
|
@ -1508,7 +1521,7 @@ class PublicRoomDialog extends Dialog {
|
||||||
this.$leaveBtn = this.$el.querySelector('.leave-room');
|
this.$leaveBtn = this.$el.querySelector('.leave-room');
|
||||||
this.$joinSubmitBtn = this.$el.querySelector('button[type="submit"]');
|
this.$joinSubmitBtn = this.$el.querySelector('button[type="submit"]');
|
||||||
this.$headerBtnJoinPublicRoom = $('join-public-room');
|
this.$headerBtnJoinPublicRoom = $('join-public-room');
|
||||||
this.$footerInstructionsPublicRoomDevices = $$('.discovery-wrapper .badge-room-public-id');
|
this.$footerBadgePublicRoomDevices = $$('.discovery-wrapper .badge-room-public-id');
|
||||||
|
|
||||||
|
|
||||||
this.$form.addEventListener('submit', e => this._onSubmit(e));
|
this.$form.addEventListener('submit', e => this._onSubmit(e));
|
||||||
|
@ -1516,7 +1529,7 @@ class PublicRoomDialog extends Dialog {
|
||||||
this.$leaveBtn.addEventListener('click', _ => this._leavePublicRoom())
|
this.$leaveBtn.addEventListener('click', _ => this._leavePublicRoom())
|
||||||
|
|
||||||
this.$headerBtnJoinPublicRoom.addEventListener('click', _ => this._onHeaderBtnClick());
|
this.$headerBtnJoinPublicRoom.addEventListener('click', _ => this._onHeaderBtnClick());
|
||||||
this.$footerInstructionsPublicRoomDevices.addEventListener('click', _ => this._onHeaderBtnClick());
|
this.$footerBadgePublicRoomDevices.addEventListener('click', _ => this._onHeaderBtnClick());
|
||||||
|
|
||||||
this.inputKeyContainer = new InputKeyContainer(
|
this.inputKeyContainer = new InputKeyContainer(
|
||||||
this.$el.querySelector('.input-key-container'),
|
this.$el.querySelector('.input-key-container'),
|
||||||
|
@ -1598,12 +1611,12 @@ class PublicRoomDialog extends Dialog {
|
||||||
setFooterBadge() {
|
setFooterBadge() {
|
||||||
if (!this.roomId) return;
|
if (!this.roomId) return;
|
||||||
|
|
||||||
this.$footerInstructionsPublicRoomDevices.innerText = Localization.getTranslation("footer.public-room-devices", null, {
|
this.$footerBadgePublicRoomDevices.innerText = Localization.getTranslation("footer.public-room-devices", null, {
|
||||||
roomId: this.roomId.toUpperCase()
|
roomId: this.roomId.toUpperCase()
|
||||||
});
|
});
|
||||||
this.$footerInstructionsPublicRoomDevices.removeAttribute('hidden');
|
this.$footerBadgePublicRoomDevices.removeAttribute('hidden');
|
||||||
|
|
||||||
super.evaluateFooterBadges();
|
Events.fire('evaluate-footer-badges');
|
||||||
}
|
}
|
||||||
|
|
||||||
_getShareRoomURL() {
|
_getShareRoomURL() {
|
||||||
|
@ -1715,8 +1728,8 @@ class PublicRoomDialog extends Dialog {
|
||||||
this.roomId = null;
|
this.roomId = null;
|
||||||
this.inputKeyContainer._cleanUp();
|
this.inputKeyContainer._cleanUp();
|
||||||
sessionStorage.removeItem('public_room_id');
|
sessionStorage.removeItem('public_room_id');
|
||||||
this.$footerInstructionsPublicRoomDevices.setAttribute('hidden', '');
|
this.$footerBadgePublicRoomDevices.setAttribute('hidden', '');
|
||||||
super.evaluateFooterBadges();
|
Events.fire('evaluate-footer-badges');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1847,7 +1860,7 @@ class ReceiveTextDialog extends Dialog {
|
||||||
|
|
||||||
this._setDocumentTitleMessages();
|
this._setDocumentTitleMessages();
|
||||||
|
|
||||||
document.changeFavicon("images/favicon-96x96-notification.png");
|
changeFavicon("images/favicon-96x96-notification.png");
|
||||||
this.show();
|
this.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2057,15 +2070,20 @@ class Notifications {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
// Check if the browser supports notifications
|
// Check if the browser supports notifications
|
||||||
if (!('Notification' in window)) return;
|
if (!('Notification' in window)) {
|
||||||
|
Events.fire('header-evaluated');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check whether notification permissions have already been granted
|
// Check whether notification permissions have already been granted
|
||||||
if (Notification.permission !== 'granted') {
|
if (Notification.permission !== 'granted') {
|
||||||
this.$button = $('notification');
|
this.$headerNotificationButton = $('notification');
|
||||||
this.$button.removeAttribute('hidden');
|
this.$headerNotificationButton.removeAttribute('hidden');
|
||||||
this.$button.addEventListener('click', _ => this._requestPermission());
|
this.$headerNotificationButton.addEventListener('click', _ => this._requestPermission());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Events.fire('header-evaluated');
|
||||||
|
|
||||||
Events.on('text-received', e => this._messageNotification(e.detail.text, e.detail.peerId));
|
Events.on('text-received', e => this._messageNotification(e.detail.text, e.detail.peerId));
|
||||||
Events.on('files-received', e => this._downloadNotification(e.detail.files));
|
Events.on('files-received', e => this._downloadNotification(e.detail.files));
|
||||||
Events.on('files-transfer-request', e => this._requestNotification(e.detail.request, e.detail.peerId));
|
Events.on('files-transfer-request', e => this._requestNotification(e.detail.request, e.detail.peerId));
|
||||||
|
@ -2078,7 +2096,7 @@ class Notifications {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Events.fire('notify-user', Localization.getTranslation("notifications.notifications-enabled"));
|
Events.fire('notify-user', Localization.getTranslation("notifications.notifications-enabled"));
|
||||||
this.$button.setAttribute('hidden', "");
|
this.$headerNotificationButton.setAttribute('hidden', "");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2460,7 +2478,7 @@ class PersistentStorage {
|
||||||
return(secrets);
|
return(secrets);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logBrowserNotCapable();
|
this.logBrowserNotCapable();
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2678,12 +2696,71 @@ class BrowserTabsConnector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class BackgroundCanvas {
|
||||||
|
constructor() {
|
||||||
|
this.c = $$('canvas');
|
||||||
|
this.cCtx = this.c.getContext('2d');
|
||||||
|
this.$footer = $$('footer');
|
||||||
|
|
||||||
|
Events.on('bg-resize', _ => this.init());
|
||||||
|
Events.on('redraw-canvas', _ => this.init());
|
||||||
|
Events.on('translation-loaded', _ => this.init());
|
||||||
|
|
||||||
|
//fade-in on load
|
||||||
|
Events.on('ui-faded-in', _ => this._fadeIn());
|
||||||
|
|
||||||
|
window.onresize = _ => Events.fire('bg-resize');
|
||||||
|
}
|
||||||
|
|
||||||
|
_fadeIn() {
|
||||||
|
this.c.classList.remove('opacity-0');
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
let oldW = this.w;
|
||||||
|
let oldH = this.h;
|
||||||
|
let oldOffset = this.offset
|
||||||
|
this.w = document.documentElement.clientWidth;
|
||||||
|
this.h = document.documentElement.clientHeight;
|
||||||
|
this.offset = this.$footer.offsetHeight - 27;
|
||||||
|
if (this.h >= 800) this.offset += 10;
|
||||||
|
|
||||||
|
if (oldW === this.w && oldH === this.h && oldOffset === this.offset) return; // nothing has changed
|
||||||
|
|
||||||
|
this.c.width = this.w;
|
||||||
|
this.c.height = this.h;
|
||||||
|
this.x0 = this.w / 2;
|
||||||
|
this.y0 = this.h - this.offset;
|
||||||
|
this.dw = Math.round(Math.max(this.w, this.h, 1000) / 13);
|
||||||
|
|
||||||
|
this.drawCircles(this.cCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
drawCircle(ctx, radius) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
let opacity = Math.max(0, 0.3 * (1 - 1 * radius / Math.max(this.w, this.h)));
|
||||||
|
ctx.strokeStyle = `rgba(128, 128, 128, ${opacity})`;
|
||||||
|
ctx.arc(this.x0, this.y0, radius, 0, 2 * Math.PI);
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
drawCircles(ctx) {
|
||||||
|
ctx.clearRect(0, 0, this.w, this.h);
|
||||||
|
for (let i = 0; i < 13; i++) {
|
||||||
|
this.drawCircle(ctx, this.dw * i + 33 + 66);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class PairDrop {
|
class PairDrop {
|
||||||
constructor() {
|
constructor() {
|
||||||
Events.on('initial-translation-loaded', _ => {
|
Events.on('initial-translation-loaded', _ => {
|
||||||
const server = new ServerConnection();
|
const server = new ServerConnection();
|
||||||
const peers = new PeersManager(server);
|
const peers = new PeersManager(server);
|
||||||
const peersUI = new PeersUI();
|
const peersUI = new PeersUI();
|
||||||
|
const backgroundCanvas = new BackgroundCanvas();
|
||||||
const languageSelectDialog = new LanguageSelectDialog();
|
const languageSelectDialog = new LanguageSelectDialog();
|
||||||
const receiveFileDialog = new ReceiveFileDialog();
|
const receiveFileDialog = new ReceiveFileDialog();
|
||||||
const receiveRequestDialog = new ReceiveRequestDialog();
|
const receiveRequestDialog = new ReceiveRequestDialog();
|
||||||
|
@ -2708,7 +2785,6 @@ const persistentStorage = new PersistentStorage();
|
||||||
const pairDrop = new PairDrop();
|
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 => {
|
||||||
|
@ -2726,63 +2802,3 @@ window.addEventListener('beforeinstallprompt', e => {
|
||||||
}
|
}
|
||||||
return e.preventDefault();
|
return e.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Background Circles
|
|
||||||
Events.on('load', () => {
|
|
||||||
let c = $$('canvas');
|
|
||||||
let cCtx = c.getContext('2d');
|
|
||||||
let x0, y0, w, h, dw, offset;
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
let oldW = w;
|
|
||||||
let oldH = h;
|
|
||||||
let oldOffset = offset
|
|
||||||
w = document.documentElement.clientWidth;
|
|
||||||
h = document.documentElement.clientHeight;
|
|
||||||
offset = $$('footer').offsetHeight - 27;
|
|
||||||
if (h > 800) offset += 10;
|
|
||||||
|
|
||||||
if (oldW === w && oldH === h && oldOffset === offset) return; // nothing has changed
|
|
||||||
|
|
||||||
c.width = w;
|
|
||||||
c.height = h;
|
|
||||||
x0 = w / 2;
|
|
||||||
y0 = h - offset;
|
|
||||||
dw = Math.round(Math.max(w, h, 1000) / 13);
|
|
||||||
|
|
||||||
drawCircles(cCtx, dw);
|
|
||||||
c.style.opacity = "1";
|
|
||||||
}
|
|
||||||
|
|
||||||
Events.on('translation-loaded', _ => init());
|
|
||||||
Events.on('bg-resize', _ => init());
|
|
||||||
window.onresize = _ => Events.fire('bg-resize');
|
|
||||||
|
|
||||||
function drawCircle(ctx, radius) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.lineWidth = 2;
|
|
||||||
let opacity = 0.3 * (1 - 1.2 * radius / Math.max(w, h));
|
|
||||||
ctx.strokeStyle = `rgba(128, 128, 128, ${opacity})`;
|
|
||||||
ctx.arc(x0, y0, radius, 0, 2 * Math.PI);
|
|
||||||
ctx.stroke();
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawCircles(ctx, frame) {
|
|
||||||
ctx.clearRect(0, 0, w, h);
|
|
||||||
for (let i = 0; i < 13; i++) {
|
|
||||||
drawCircle(ctx, dw * i + frame + 33);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
document.changeFavicon = function (src) {
|
|
||||||
document.querySelector('[rel="icon"]').href = src;
|
|
||||||
document.querySelector('[rel="shortcut icon"]').href = src;
|
|
||||||
}
|
|
||||||
|
|
||||||
// close About PairDrop page on Escape
|
|
||||||
window.addEventListener("keydown", (e) => {
|
|
||||||
if (e.key === "Escape") {
|
|
||||||
window.location.hash = '#';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
|
@ -406,3 +406,8 @@ function onlyUnique (value, index, array) {
|
||||||
function getUrlWithoutArguments() {
|
function getUrlWithoutArguments() {
|
||||||
return `${window.location.protocol}//${window.location.host}${window.location.pathname}`;
|
return `${window.location.protocol}//${window.location.host}${window.location.pathname}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function changeFavicon(src) {
|
||||||
|
document.querySelector('[rel="icon"]').href = src;
|
||||||
|
document.querySelector('[rel="shortcut icon"]').href = src;
|
||||||
|
}
|
||||||
|
|
|
@ -273,6 +273,9 @@ x-noscript {
|
||||||
0% {
|
0% {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#center {
|
#center {
|
||||||
|
@ -417,10 +420,6 @@ x-no-peers {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
height: 137px;
|
height: 137px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
animation: fade-in 600ms;
|
|
||||||
animation-fill-mode: backwards;
|
|
||||||
/* prevent flickering on load */
|
|
||||||
animation-iteration-count: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
x-no-peers h2,
|
x-no-peers h2,
|
||||||
|
@ -613,7 +612,6 @@ footer .logo {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
margin-top: -10px;
|
margin-top: -10px;
|
||||||
animation: ease-in;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.discovery-wrapper {
|
.discovery-wrapper {
|
||||||
|
@ -1228,22 +1226,23 @@ button::-moz-focus-inner {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#about:not(:target) header.fade-in {
|
#about:not(:target) header {
|
||||||
transition-delay: 400ms;
|
transition-delay: 400ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
#about:target header.fade-in {
|
#about:target header {
|
||||||
transition-delay: 100ms;
|
transition-delay: 100ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
#about .fade-in {
|
#about > * {
|
||||||
transition: opacity 300ms ease 300ms;
|
transition: opacity 300ms ease 300ms;
|
||||||
will-change: opacity;
|
will-change: opacity;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
#about:not(:target) .fade-in {
|
#about:not(:target) > header,
|
||||||
opacity: 0 !important;
|
#about:not(:target) > section {
|
||||||
|
opacity: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
transition-delay: 0s;
|
transition-delay: 0s;
|
||||||
}
|
}
|
||||||
|
@ -1422,17 +1421,17 @@ x-peers:empty~x-instructions {
|
||||||
|
|
||||||
/* Prevent Cumulative Layout Shift */
|
/* Prevent Cumulative Layout Shift */
|
||||||
|
|
||||||
body > header,
|
.fade-in {
|
||||||
canvas,
|
animation: fade-in 600ms;
|
||||||
#center,
|
animation-fill-mode: backwards;
|
||||||
x-no-peers,
|
}
|
||||||
x-peers,
|
|
||||||
x-instructions,
|
.no-animation-on-load {
|
||||||
footer > .icon.logo,
|
animation-iteration-count: 0;
|
||||||
.discovery-wrapper,
|
}
|
||||||
.known-as-wrapper {
|
|
||||||
transition: opacity 0.5s ease 0.1s;
|
.opacity-0 {
|
||||||
opacity: 0; /* will be set to 1 after initial translation is loaded */
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Responsive Styles */
|
/* Responsive Styles */
|
||||||
|
|
|
@ -38,7 +38,7 @@
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body translate="no">
|
<body translate="no">
|
||||||
<header class="row-reverse">
|
<header class="row-reverse opacity-0">
|
||||||
<a href="#about" class="icon-button" data-i18n-key="header.about" data-i18n-attrs="title aria-label">
|
<a href="#about" class="icon-button" data-i18n-key="header.about" data-i18n-attrs="title aria-label">
|
||||||
<svg class="icon">
|
<svg class="icon">
|
||||||
<use xlink:href="#info-outline"></use>
|
<use xlink:href="#info-outline"></use>
|
||||||
|
@ -96,11 +96,11 @@
|
||||||
<div id="cancel-paste-mode" class="button" data-i18n-key="header.cancel-paste-mode" data-i18n-attrs="text" hidden></div>
|
<div id="cancel-paste-mode" class="button" data-i18n-key="header.cancel-paste-mode" data-i18n-attrs="text" hidden></div>
|
||||||
</header>
|
</header>
|
||||||
<!-- Center -->
|
<!-- Center -->
|
||||||
<div id="center">
|
<div id="center" class="opacity-0">
|
||||||
<!-- Peers -->
|
<!-- Peers -->
|
||||||
<div class="x-peers-filler"></div>
|
<div class="x-peers-filler"></div>
|
||||||
<x-peers class="center"></x-peers>
|
<x-peers class="center"></x-peers>
|
||||||
<x-no-peers data-i18n-key="instructions.no-peers" data-i18n-attrs="data-drop-bg">
|
<x-no-peers class="no-animation-on-load" data-i18n-key="instructions.no-peers" data-i18n-attrs="data-drop-bg">
|
||||||
<h2 data-i18n-key="instructions.no-peers-title" data-i18n-attrs="text"></h2>
|
<h2 data-i18n-key="instructions.no-peers-title" data-i18n-attrs="text"></h2>
|
||||||
<div data-i18n-key="instructions.no-peers-subtitle" data-i18n-attrs="text"></div>
|
<div data-i18n-key="instructions.no-peers-subtitle" data-i18n-attrs="text"></div>
|
||||||
</x-no-peers>
|
</x-no-peers>
|
||||||
|
@ -114,7 +114,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<footer class="column">
|
<footer class="column opacity-0">
|
||||||
<svg class="icon logo">
|
<svg class="icon logo">
|
||||||
<use xlink:href="#wifi-tethering"></use>
|
<use xlink:href="#wifi-tethering"></use>
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -471,14 +471,14 @@
|
||||||
</div>
|
</div>
|
||||||
<!-- About Page -->
|
<!-- About Page -->
|
||||||
<x-about id="about" class="full center column">
|
<x-about id="about" class="full center column">
|
||||||
<header class="row-reverse fade-in">
|
<header class="row-reverse">
|
||||||
<a href="#" class="close icon-button" data-i18n-key="about.close-about" data-i18n-attrs="aria-label">
|
<a href="#" class="close icon-button" data-i18n-key="about.close-about" data-i18n-attrs="aria-label">
|
||||||
<svg class="icon">
|
<svg class="icon">
|
||||||
<use xlink:href="#close-icon"></use>
|
<use xlink:href="#close-icon"></use>
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
</header>
|
</header>
|
||||||
<section class="center column fade-in">
|
<section class="center column">
|
||||||
<svg class="icon logo">
|
<svg class="icon logo">
|
||||||
<use xlink:href="#wifi-tethering"></use>
|
<use xlink:href="#wifi-tethering"></use>
|
||||||
</svg>
|
</svg>
|
||||||
|
@ -512,7 +512,7 @@
|
||||||
</section>
|
</section>
|
||||||
<x-background></x-background>
|
<x-background></x-background>
|
||||||
</x-about>
|
</x-about>
|
||||||
<canvas class="circles"></canvas>
|
<canvas class="circles opacity-0"></canvas>
|
||||||
<!-- SVG Icon Library -->
|
<!-- SVG Icon Library -->
|
||||||
<svg style="display: none;">
|
<svg style="display: none;">
|
||||||
<symbol id="wifi-tethering" viewBox="0 0 24 24">
|
<symbol id="wifi-tethering" viewBox="0 0 24 24">
|
||||||
|
@ -592,7 +592,7 @@
|
||||||
<script src="scripts/theme.js"></script>
|
<script src="scripts/theme.js"></script>
|
||||||
<script src="scripts/network.js"></script>
|
<script src="scripts/network.js"></script>
|
||||||
<script src="scripts/ui.js"></script>
|
<script src="scripts/ui.js"></script>
|
||||||
<script src="scripts/util.js" async></script>
|
<script src="scripts/util.js"></script>
|
||||||
<script src="scripts/QRCode.min.js" async></script>
|
<script src="scripts/QRCode.min.js" async></script>
|
||||||
<script src="scripts/zip.min.js" async></script>
|
<script src="scripts/zip.min.js" async></script>
|
||||||
<script src="scripts/NoSleep.min.js" async></script>
|
<script src="scripts/NoSleep.min.js" async></script>
|
||||||
|
|
|
@ -36,27 +36,15 @@ class PeersUI {
|
||||||
Events.on('drop', e => this._onDrop(e));
|
Events.on('drop', e => this._onDrop(e));
|
||||||
Events.on('keydown', e => this._onKeyDown(e));
|
Events.on('keydown', e => this._onKeyDown(e));
|
||||||
|
|
||||||
this.$header = document.querySelector('body > header')
|
|
||||||
this.$xPeers = $$('x-peers');
|
this.$xPeers = $$('x-peers');
|
||||||
this.$xNoPeers = $$('x-no-peers');
|
this.$xNoPeers = $$('x-no-peers');
|
||||||
this.$xInstructions = $$('x-instructions');
|
this.$xInstructions = $$('x-instructions');
|
||||||
this.$center = $$('#center');
|
this.$center = $$('#center');
|
||||||
this.$logo = $$('footer .icon.logo');
|
this.$footer = $$('footer');
|
||||||
this.$discoveryWrapper = $$('footer .discovery-wrapper');
|
this.$discoveryWrapper = $$('footer .discovery-wrapper');
|
||||||
this.$knownAsWrapper = $$('footer .known-as-wrapper');
|
|
||||||
|
|
||||||
this.$header.style.opacity = "1";
|
Events.on('peer-added', _ => this._evaluateOverflowing());
|
||||||
this.$xPeers.style.opacity = "1";
|
Events.on('bg-resize', _ => this._evaluateOverflowing());
|
||||||
this.$xNoPeers.style.opacity = "1";
|
|
||||||
this.$xInstructions.style.opacity = "0.5";
|
|
||||||
this.$center.style.opacity = "1";
|
|
||||||
this.$logo.style.opacity = "1";
|
|
||||||
this.$discoveryWrapper.style.opacity = "1";
|
|
||||||
this.$knownAsWrapper.style.opacity = "1";
|
|
||||||
|
|
||||||
|
|
||||||
Events.on('peer-added', _ => this.evaluateOverflowing());
|
|
||||||
Events.on('bg-resize', _ => this.evaluateOverflowing());
|
|
||||||
|
|
||||||
this.$displayName = $('display-name');
|
this.$displayName = $('display-name');
|
||||||
|
|
||||||
|
@ -75,11 +63,45 @@ class PeersUI {
|
||||||
if (displayName) Events.fire('self-display-name-changed', displayName);
|
if (displayName) Events.fire('self-display-name-changed', displayName);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Events.on('evaluate-footer-badges', _ => this._evaluateFooterBadges())
|
||||||
|
|
||||||
/* prevent animation on load */
|
this.fadedIn = false;
|
||||||
|
|
||||||
|
this.$header = document.querySelector('header.opacity-0');
|
||||||
|
Events.on('header-evaluated', () => this._fadeInHeader());
|
||||||
|
}
|
||||||
|
|
||||||
|
_fadeInHeader() {
|
||||||
|
//prevent flickering
|
||||||
|
setTimeout(() => this.$header.classList.remove('opacity-0'), 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
_fadeInUI() {
|
||||||
|
if (this.fadedIn) return;
|
||||||
|
|
||||||
|
this.fadedIn = true;
|
||||||
|
|
||||||
|
this.$center.classList.remove('opacity-0');
|
||||||
|
this.$footer.classList.remove('opacity-0');
|
||||||
|
|
||||||
|
// Prevent flickering on load
|
||||||
setTimeout(_ => {
|
setTimeout(_ => {
|
||||||
this.$xNoPeers.style.animationIterationCount = "1";
|
this.$xNoPeers.classList.remove('no-animation-on-load');
|
||||||
}, 300);
|
}, 600);
|
||||||
|
|
||||||
|
Events.fire('ui-faded-in');
|
||||||
|
}
|
||||||
|
|
||||||
|
_evaluateFooterBadges() {
|
||||||
|
if (this.$discoveryWrapper.querySelectorAll('div:last-of-type > span[hidden]').length < 2) {
|
||||||
|
this.$discoveryWrapper.classList.remove('row');
|
||||||
|
this.$discoveryWrapper.classList.add('column');
|
||||||
|
} else {
|
||||||
|
this.$discoveryWrapper.classList.remove('column');
|
||||||
|
this.$discoveryWrapper.classList.add('row');
|
||||||
|
}
|
||||||
|
Events.fire('redraw-canvas');
|
||||||
|
this._fadeInUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
_insertDisplayName(displayName) {
|
_insertDisplayName(displayName) {
|
||||||
|
@ -162,6 +184,11 @@ class PeersUI {
|
||||||
if (document.querySelectorAll('x-dialog[show]').length === 0 && window.pasteMode.activated && e.code === "Escape") {
|
if (document.querySelectorAll('x-dialog[show]').length === 0 && window.pasteMode.activated && e.code === "Escape") {
|
||||||
Events.fire('deactivate-paste-mode');
|
Events.fire('deactivate-paste-mode');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// close About PairDrop page on Escape
|
||||||
|
if (e.key === "Escape") {
|
||||||
|
window.location.hash = '#';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onPeerJoined(msg) {
|
_onPeerJoined(msg) {
|
||||||
|
@ -207,7 +234,7 @@ class PeersUI {
|
||||||
Object.keys(peer._roomIds).forEach(roomType => peerNode.classList.add(`type-${roomType}`));
|
Object.keys(peer._roomIds).forEach(roomType => peerNode.classList.add(`type-${roomType}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
||||||
|
@ -223,7 +250,7 @@ class PeersUI {
|
||||||
const $peer = $(peerId);
|
const $peer = $(peerId);
|
||||||
if (!$peer) return;
|
if (!$peer) return;
|
||||||
$peer.remove();
|
$peer.remove();
|
||||||
this.evaluateOverflowing();
|
this._evaluateOverflowing();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onRoomTypeRemoved(peerId, roomType) {
|
_onRoomTypeRemoved(peerId, roomType) {
|
||||||
|
@ -610,7 +637,6 @@ class Dialog {
|
||||||
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]');
|
||||||
this.$discoveryWrapper = $$('footer .discovery-wrapper');
|
|
||||||
|
|
||||||
Events.on('peer-disconnected', e => this._onPeerDisconnected(e.detail));
|
Events.on('peer-disconnected', e => this._onPeerDisconnected(e.detail));
|
||||||
}
|
}
|
||||||
|
@ -631,7 +657,7 @@ class Dialog {
|
||||||
window.blur();
|
window.blur();
|
||||||
}
|
}
|
||||||
document.title = 'PairDrop';
|
document.title = 'PairDrop';
|
||||||
document.changeFavicon("images/favicon-96x96.png");
|
changeFavicon("images/favicon-96x96.png");
|
||||||
this.correspondingPeerId = undefined;
|
this.correspondingPeerId = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,17 +667,6 @@ class Dialog {
|
||||||
Events.fire('notify-user', Localization.getTranslation("notifications.selected-peer-left"));
|
Events.fire('notify-user', Localization.getTranslation("notifications.selected-peer-left"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
evaluateFooterBadges() {
|
|
||||||
if (this.$discoveryWrapper.querySelectorAll('div:last-of-type > span[hidden]').length < 2) {
|
|
||||||
this.$discoveryWrapper.classList.remove('row');
|
|
||||||
this.$discoveryWrapper.classList.add('column');
|
|
||||||
} else {
|
|
||||||
this.$discoveryWrapper.classList.remove('column');
|
|
||||||
this.$discoveryWrapper.classList.add('row');
|
|
||||||
}
|
|
||||||
Events.fire('bg-resize');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class LanguageSelectDialog extends Dialog {
|
class LanguageSelectDialog extends Dialog {
|
||||||
|
@ -931,7 +946,7 @@ class ReceiveFileDialog extends ReceiveDialog {
|
||||||
document.title = files.length === 1
|
document.title = files.length === 1
|
||||||
? `${ Localization.getTranslation("document-titles.file-received") } - PairDrop`
|
? `${ Localization.getTranslation("document-titles.file-received") } - PairDrop`
|
||||||
: `${ Localization.getTranslation("document-titles.file-received-plural", null, {count: files.length}) } - PairDrop`;
|
: `${ Localization.getTranslation("document-titles.file-received-plural", null, {count: files.length}) } - PairDrop`;
|
||||||
document.changeFavicon("images/favicon-96x96-notification.png");
|
changeFavicon("images/favicon-96x96-notification.png");
|
||||||
|
|
||||||
Events.fire('set-progress', {peerId: peerId, progress: 1, status: 'process'})
|
Events.fire('set-progress', {peerId: peerId, progress: 1, status: 'process'})
|
||||||
this.show();
|
this.show();
|
||||||
|
@ -1028,7 +1043,7 @@ class ReceiveRequestDialog extends ReceiveDialog {
|
||||||
this.$receiveTitle.innerText = transferRequestTitle;
|
this.$receiveTitle.innerText = transferRequestTitle;
|
||||||
|
|
||||||
document.title = `${transferRequestTitle} - PairDrop`;
|
document.title = `${transferRequestTitle} - PairDrop`;
|
||||||
document.changeFavicon("images/favicon-96x96-notification.png");
|
changeFavicon("images/favicon-96x96-notification.png");
|
||||||
this.show();
|
this.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1192,7 +1207,6 @@ class PairDeviceDialog extends Dialog {
|
||||||
this.$closeBtn.addEventListener('click', _ => this._close());
|
this.$closeBtn.addEventListener('click', _ => this._close());
|
||||||
|
|
||||||
Events.on('keydown', e => this._onKeyDown(e));
|
Events.on('keydown', e => this._onKeyDown(e));
|
||||||
Events.on('ws-connected', _ => this._onWsConnected());
|
|
||||||
Events.on('ws-disconnected', _ => this.hide());
|
Events.on('ws-disconnected', _ => this.hide());
|
||||||
Events.on('pair-device-initiated', e => this._onPairDeviceInitiated(e.detail));
|
Events.on('pair-device-initiated', e => this._onPairDeviceInitiated(e.detail));
|
||||||
Events.on('pair-device-joined', e => this._onPairDeviceJoined(e.detail.peerId, e.detail.roomSecret));
|
Events.on('pair-device-joined', e => this._onPairDeviceJoined(e.detail.peerId, e.detail.roomSecret));
|
||||||
|
@ -1207,6 +1221,8 @@ class PairDeviceDialog extends Dialog {
|
||||||
this.evaluateUrlAttributes();
|
this.evaluateUrlAttributes();
|
||||||
|
|
||||||
this.pairPeer = {};
|
this.pairPeer = {};
|
||||||
|
|
||||||
|
this._evaluateNumberRoomSecrets();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onKeyDown(e) {
|
_onKeyDown(e) {
|
||||||
|
@ -1231,10 +1247,6 @@ class PairDeviceDialog extends Dialog {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onWsConnected() {
|
|
||||||
this._evaluateNumberRoomSecrets();
|
|
||||||
}
|
|
||||||
|
|
||||||
_pairDeviceInitiate() {
|
_pairDeviceInitiate() {
|
||||||
Events.fire('pair-device-initiate');
|
Events.fire('pair-device-initiate');
|
||||||
}
|
}
|
||||||
|
@ -1382,16 +1394,17 @@ class PairDeviceDialog extends Dialog {
|
||||||
}
|
}
|
||||||
|
|
||||||
_evaluateNumberRoomSecrets() {
|
_evaluateNumberRoomSecrets() {
|
||||||
PersistentStorage.getAllRoomSecrets().then(roomSecrets => {
|
PersistentStorage.getAllRoomSecrets()
|
||||||
if (roomSecrets.length > 0) {
|
.then(roomSecrets => {
|
||||||
this.$editPairedDevicesHeaderBtn.removeAttribute('hidden');
|
if (roomSecrets.length > 0) {
|
||||||
this.$footerInstructionsPairedDevices.removeAttribute('hidden');
|
this.$editPairedDevicesHeaderBtn.removeAttribute('hidden');
|
||||||
} else {
|
this.$footerInstructionsPairedDevices.removeAttribute('hidden');
|
||||||
this.$editPairedDevicesHeaderBtn.setAttribute('hidden', '');
|
} else {
|
||||||
this.$footerInstructionsPairedDevices.setAttribute('hidden', '');
|
this.$editPairedDevicesHeaderBtn.setAttribute('hidden', '');
|
||||||
}
|
this.$footerInstructionsPairedDevices.setAttribute('hidden', '');
|
||||||
super.evaluateFooterBadges();
|
}
|
||||||
});
|
Events.fire('evaluate-footer-badges');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1399,10 +1412,10 @@ class EditPairedDevicesDialog extends Dialog {
|
||||||
constructor() {
|
constructor() {
|
||||||
super('edit-paired-devices-dialog');
|
super('edit-paired-devices-dialog');
|
||||||
this.$pairedDevicesWrapper = this.$el.querySelector('.paired-devices-wrapper');
|
this.$pairedDevicesWrapper = this.$el.querySelector('.paired-devices-wrapper');
|
||||||
this.$footerInstructionsPairedDevices = $$('.discovery-wrapper .badge-room-secret');
|
this.$footerBadgePairedDevices = $$('.discovery-wrapper .badge-room-secret');
|
||||||
|
|
||||||
$('edit-paired-devices').addEventListener('click', _ => this._onEditPairedDevices());
|
$('edit-paired-devices').addEventListener('click', _ => this._onEditPairedDevices());
|
||||||
this.$footerInstructionsPairedDevices.addEventListener('click', _ => this._onEditPairedDevices());
|
this.$footerBadgePairedDevices.addEventListener('click', _ => this._onEditPairedDevices());
|
||||||
|
|
||||||
Events.on('peer-display-name-changed', e => this._onPeerDisplayNameChanged(e));
|
Events.on('peer-display-name-changed', e => this._onPeerDisplayNameChanged(e));
|
||||||
Events.on('keydown', e => this._onKeyDown(e));
|
Events.on('keydown', e => this._onKeyDown(e));
|
||||||
|
@ -1510,7 +1523,7 @@ class PublicRoomDialog extends Dialog {
|
||||||
this.$leaveBtn = this.$el.querySelector('.leave-room');
|
this.$leaveBtn = this.$el.querySelector('.leave-room');
|
||||||
this.$joinSubmitBtn = this.$el.querySelector('button[type="submit"]');
|
this.$joinSubmitBtn = this.$el.querySelector('button[type="submit"]');
|
||||||
this.$headerBtnJoinPublicRoom = $('join-public-room');
|
this.$headerBtnJoinPublicRoom = $('join-public-room');
|
||||||
this.$footerInstructionsPublicRoomDevices = $$('.discovery-wrapper .badge-room-public-id');
|
this.$footerBadgePublicRoomDevices = $$('.discovery-wrapper .badge-room-public-id');
|
||||||
|
|
||||||
|
|
||||||
this.$form.addEventListener('submit', e => this._onSubmit(e));
|
this.$form.addEventListener('submit', e => this._onSubmit(e));
|
||||||
|
@ -1518,7 +1531,7 @@ class PublicRoomDialog extends Dialog {
|
||||||
this.$leaveBtn.addEventListener('click', _ => this._leavePublicRoom())
|
this.$leaveBtn.addEventListener('click', _ => this._leavePublicRoom())
|
||||||
|
|
||||||
this.$headerBtnJoinPublicRoom.addEventListener('click', _ => this._onHeaderBtnClick());
|
this.$headerBtnJoinPublicRoom.addEventListener('click', _ => this._onHeaderBtnClick());
|
||||||
this.$footerInstructionsPublicRoomDevices.addEventListener('click', _ => this._onHeaderBtnClick());
|
this.$footerBadgePublicRoomDevices.addEventListener('click', _ => this._onHeaderBtnClick());
|
||||||
|
|
||||||
this.inputKeyContainer = new InputKeyContainer(
|
this.inputKeyContainer = new InputKeyContainer(
|
||||||
this.$el.querySelector('.input-key-container'),
|
this.$el.querySelector('.input-key-container'),
|
||||||
|
@ -1600,12 +1613,12 @@ class PublicRoomDialog extends Dialog {
|
||||||
setFooterBadge() {
|
setFooterBadge() {
|
||||||
if (!this.roomId) return;
|
if (!this.roomId) return;
|
||||||
|
|
||||||
this.$footerInstructionsPublicRoomDevices.innerText = Localization.getTranslation("footer.public-room-devices", null, {
|
this.$footerBadgePublicRoomDevices.innerText = Localization.getTranslation("footer.public-room-devices", null, {
|
||||||
roomId: this.roomId.toUpperCase()
|
roomId: this.roomId.toUpperCase()
|
||||||
});
|
});
|
||||||
this.$footerInstructionsPublicRoomDevices.removeAttribute('hidden');
|
this.$footerBadgePublicRoomDevices.removeAttribute('hidden');
|
||||||
|
|
||||||
super.evaluateFooterBadges();
|
Events.fire('evaluate-footer-badges');
|
||||||
}
|
}
|
||||||
|
|
||||||
_getShareRoomURL() {
|
_getShareRoomURL() {
|
||||||
|
@ -1717,8 +1730,8 @@ class PublicRoomDialog extends Dialog {
|
||||||
this.roomId = null;
|
this.roomId = null;
|
||||||
this.inputKeyContainer._cleanUp();
|
this.inputKeyContainer._cleanUp();
|
||||||
sessionStorage.removeItem('public_room_id');
|
sessionStorage.removeItem('public_room_id');
|
||||||
this.$footerInstructionsPublicRoomDevices.setAttribute('hidden', '');
|
this.$footerBadgePublicRoomDevices.setAttribute('hidden', '');
|
||||||
super.evaluateFooterBadges();
|
Events.fire('evaluate-footer-badges');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1849,7 +1862,7 @@ class ReceiveTextDialog extends Dialog {
|
||||||
|
|
||||||
this._setDocumentTitleMessages();
|
this._setDocumentTitleMessages();
|
||||||
|
|
||||||
document.changeFavicon("images/favicon-96x96-notification.png");
|
changeFavicon("images/favicon-96x96-notification.png");
|
||||||
this.show();
|
this.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2059,15 +2072,20 @@ class Notifications {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
// Check if the browser supports notifications
|
// Check if the browser supports notifications
|
||||||
if (!('Notification' in window)) return;
|
if (!('Notification' in window)) {
|
||||||
|
Events.fire('header-evaluated');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check whether notification permissions have already been granted
|
// Check whether notification permissions have already been granted
|
||||||
if (Notification.permission !== 'granted') {
|
if (Notification.permission !== 'granted') {
|
||||||
this.$button = $('notification');
|
this.$headerNotificationButton = $('notification');
|
||||||
this.$button.removeAttribute('hidden');
|
this.$headerNotificationButton.removeAttribute('hidden');
|
||||||
this.$button.addEventListener('click', _ => this._requestPermission());
|
this.$headerNotificationButton.addEventListener('click', _ => this._requestPermission());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Events.fire('header-evaluated');
|
||||||
|
|
||||||
Events.on('text-received', e => this._messageNotification(e.detail.text, e.detail.peerId));
|
Events.on('text-received', e => this._messageNotification(e.detail.text, e.detail.peerId));
|
||||||
Events.on('files-received', e => this._downloadNotification(e.detail.files));
|
Events.on('files-received', e => this._downloadNotification(e.detail.files));
|
||||||
Events.on('files-transfer-request', e => this._requestNotification(e.detail.request, e.detail.peerId));
|
Events.on('files-transfer-request', e => this._requestNotification(e.detail.request, e.detail.peerId));
|
||||||
|
@ -2080,7 +2098,7 @@ class Notifications {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Events.fire('notify-user', Localization.getTranslation("notifications.notifications-enabled"));
|
Events.fire('notify-user', Localization.getTranslation("notifications.notifications-enabled"));
|
||||||
this.$button.setAttribute('hidden', "");
|
this.$headerNotificationButton.setAttribute('hidden', "");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2462,7 +2480,7 @@ class PersistentStorage {
|
||||||
return(secrets);
|
return(secrets);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logBrowserNotCapable();
|
this.logBrowserNotCapable();
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2680,12 +2698,71 @@ class BrowserTabsConnector {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class BackgroundCanvas {
|
||||||
|
constructor() {
|
||||||
|
this.c = $$('canvas');
|
||||||
|
this.cCtx = this.c.getContext('2d');
|
||||||
|
this.$footer = $$('footer');
|
||||||
|
|
||||||
|
Events.on('bg-resize', _ => this.init());
|
||||||
|
Events.on('redraw-canvas', _ => this.init());
|
||||||
|
Events.on('translation-loaded', _ => this.init());
|
||||||
|
|
||||||
|
//fade-in on load
|
||||||
|
Events.on('ui-faded-in', _ => this._fadeIn());
|
||||||
|
|
||||||
|
window.onresize = _ => Events.fire('bg-resize');
|
||||||
|
}
|
||||||
|
|
||||||
|
_fadeIn() {
|
||||||
|
this.c.classList.remove('opacity-0');
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
let oldW = this.w;
|
||||||
|
let oldH = this.h;
|
||||||
|
let oldOffset = this.offset
|
||||||
|
this.w = document.documentElement.clientWidth;
|
||||||
|
this.h = document.documentElement.clientHeight;
|
||||||
|
this.offset = this.$footer.offsetHeight - 27;
|
||||||
|
if (this.h >= 800) this.offset += 10;
|
||||||
|
|
||||||
|
if (oldW === this.w && oldH === this.h && oldOffset === this.offset) return; // nothing has changed
|
||||||
|
|
||||||
|
this.c.width = this.w;
|
||||||
|
this.c.height = this.h;
|
||||||
|
this.x0 = this.w / 2;
|
||||||
|
this.y0 = this.h - this.offset;
|
||||||
|
this.dw = Math.round(Math.max(this.w, this.h, 1000) / 13);
|
||||||
|
|
||||||
|
this.drawCircles(this.cCtx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
drawCircle(ctx, radius) {
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.lineWidth = 2;
|
||||||
|
let opacity = Math.max(0, 0.3 * (1 - 1 * radius / Math.max(this.w, this.h)));
|
||||||
|
ctx.strokeStyle = `rgba(128, 128, 128, ${opacity})`;
|
||||||
|
ctx.arc(this.x0, this.y0, radius, 0, 2 * Math.PI);
|
||||||
|
ctx.stroke();
|
||||||
|
}
|
||||||
|
|
||||||
|
drawCircles(ctx) {
|
||||||
|
ctx.clearRect(0, 0, this.w, this.h);
|
||||||
|
for (let i = 0; i < 13; i++) {
|
||||||
|
this.drawCircle(ctx, this.dw * i + 33 + 66);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class PairDrop {
|
class PairDrop {
|
||||||
constructor() {
|
constructor() {
|
||||||
Events.on('initial-translation-loaded', _ => {
|
Events.on('initial-translation-loaded', _ => {
|
||||||
const server = new ServerConnection();
|
const server = new ServerConnection();
|
||||||
const peers = new PeersManager(server);
|
const peers = new PeersManager(server);
|
||||||
const peersUI = new PeersUI();
|
const peersUI = new PeersUI();
|
||||||
|
const backgroundCanvas = new BackgroundCanvas();
|
||||||
const languageSelectDialog = new LanguageSelectDialog();
|
const languageSelectDialog = new LanguageSelectDialog();
|
||||||
const receiveFileDialog = new ReceiveFileDialog();
|
const receiveFileDialog = new ReceiveFileDialog();
|
||||||
const receiveRequestDialog = new ReceiveRequestDialog();
|
const receiveRequestDialog = new ReceiveRequestDialog();
|
||||||
|
@ -2710,7 +2787,6 @@ const persistentStorage = new PersistentStorage();
|
||||||
const pairDrop = new PairDrop();
|
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 => {
|
||||||
|
@ -2728,62 +2804,3 @@ window.addEventListener('beforeinstallprompt', e => {
|
||||||
}
|
}
|
||||||
return e.preventDefault();
|
return e.preventDefault();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Background Circles
|
|
||||||
Events.on('load', () => {
|
|
||||||
let c = $$('canvas');
|
|
||||||
let cCtx = c.getContext('2d');
|
|
||||||
let x0, y0, w, h, dw, offset;
|
|
||||||
|
|
||||||
function init() {
|
|
||||||
let oldW = w;
|
|
||||||
let oldH = h;
|
|
||||||
let oldOffset = offset
|
|
||||||
w = document.documentElement.clientWidth;
|
|
||||||
h = document.documentElement.clientHeight;
|
|
||||||
offset = $$('footer').offsetHeight - 27;
|
|
||||||
|
|
||||||
if (oldW === w && oldH === h && oldOffset === offset) return; // nothing has changed
|
|
||||||
|
|
||||||
c.width = w;
|
|
||||||
c.height = h;
|
|
||||||
x0 = w / 2;
|
|
||||||
y0 = h - offset;
|
|
||||||
dw = Math.round(Math.max(w, h, 1000) / 13);
|
|
||||||
|
|
||||||
drawCircles(cCtx, dw);
|
|
||||||
c.style.opacity = "1";
|
|
||||||
}
|
|
||||||
|
|
||||||
Events.on('translation-loaded', _ => init());
|
|
||||||
Events.on('bg-resize', _ => init());
|
|
||||||
window.onresize = _ => Events.fire('bg-resize');
|
|
||||||
|
|
||||||
function drawCircle(ctx, radius) {
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.lineWidth = 2;
|
|
||||||
let opacity = 0.3 * (1 - 1.2 * radius / Math.max(w, h));
|
|
||||||
ctx.strokeStyle = `rgba(128, 128, 128, ${opacity})`;
|
|
||||||
ctx.arc(x0, y0, radius, 0, 2 * Math.PI);
|
|
||||||
ctx.stroke();
|
|
||||||
}
|
|
||||||
|
|
||||||
function drawCircles(ctx, frame) {
|
|
||||||
ctx.clearRect(0, 0, w, h);
|
|
||||||
for (let i = 0; i < 13; i++) {
|
|
||||||
drawCircle(ctx, dw * i + frame + 33);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
document.changeFavicon = function (src) {
|
|
||||||
document.querySelector('[rel="icon"]').href = src;
|
|
||||||
document.querySelector('[rel="shortcut icon"]').href = src;
|
|
||||||
}
|
|
||||||
|
|
||||||
// close About PairDrop page on Escape
|
|
||||||
window.addEventListener("keydown", (e) => {
|
|
||||||
if (e.key === "Escape") {
|
|
||||||
window.location.hash = '#';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
|
@ -407,6 +407,11 @@ function getUrlWithoutArguments() {
|
||||||
return `${window.location.protocol}//${window.location.host}${window.location.pathname}`;
|
return `${window.location.protocol}//${window.location.host}${window.location.pathname}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function changeFavicon(src) {
|
||||||
|
document.querySelector('[rel="icon"]').href = src;
|
||||||
|
document.querySelector('[rel="shortcut icon"]').href = src;
|
||||||
|
}
|
||||||
|
|
||||||
function arrayBufferToBase64(buffer) {
|
function arrayBufferToBase64(buffer) {
|
||||||
var binary = '';
|
var binary = '';
|
||||||
var bytes = new Uint8Array(buffer);
|
var bytes = new Uint8Array(buffer);
|
||||||
|
|
|
@ -274,6 +274,9 @@ x-noscript {
|
||||||
0% {
|
0% {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#center {
|
#center {
|
||||||
|
@ -422,10 +425,6 @@ x-no-peers {
|
||||||
padding: 8px;
|
padding: 8px;
|
||||||
height: 137px;
|
height: 137px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
animation: fade-in 600ms;
|
|
||||||
animation-fill-mode: backwards;
|
|
||||||
/* prevent flickering on load */
|
|
||||||
animation-iteration-count: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
x-no-peers h2,
|
x-no-peers h2,
|
||||||
|
@ -643,7 +642,6 @@ footer .logo {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
color: var(--primary-color);
|
color: var(--primary-color);
|
||||||
margin-top: -10px;
|
margin-top: -10px;
|
||||||
animation: ease-in;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.discovery-wrapper {
|
.discovery-wrapper {
|
||||||
|
@ -1258,22 +1256,23 @@ button::-moz-focus-inner {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#about:not(:target) header.fade-in {
|
#about:not(:target) header {
|
||||||
transition-delay: 400ms;
|
transition-delay: 400ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
#about:target header.fade-in {
|
#about:target header {
|
||||||
transition-delay: 100ms;
|
transition-delay: 100ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
#about .fade-in {
|
#about > * {
|
||||||
transition: opacity 300ms ease 300ms;
|
transition: opacity 300ms ease 300ms;
|
||||||
will-change: opacity;
|
will-change: opacity;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
||||||
#about:not(:target) .fade-in {
|
#about:not(:target) > header,
|
||||||
opacity: 0 !important;
|
#about:not(:target) > section {
|
||||||
|
opacity: 0;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
transition-delay: 0s;
|
transition-delay: 0s;
|
||||||
}
|
}
|
||||||
|
@ -1452,17 +1451,17 @@ x-peers:empty~x-instructions {
|
||||||
|
|
||||||
/* Prevent Cumulative Layout Shift */
|
/* Prevent Cumulative Layout Shift */
|
||||||
|
|
||||||
body > header,
|
.fade-in {
|
||||||
canvas,
|
animation: fade-in 600ms;
|
||||||
#center,
|
animation-fill-mode: backwards;
|
||||||
x-no-peers,
|
}
|
||||||
x-peers,
|
|
||||||
x-instructions,
|
.no-animation-on-load {
|
||||||
footer > .icon.logo,
|
animation-iteration-count: 0;
|
||||||
.discovery-wrapper,
|
}
|
||||||
.known-as-wrapper {
|
|
||||||
transition: opacity 0.5s ease 0.1s;
|
.opacity-0 {
|
||||||
opacity: 0; /* will be set to 1 after initial translation is loaded */
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Responsive Styles */
|
/* Responsive Styles */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue