From 892e84c834a33ef4b974234864f3759a80cb87d5 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Sun, 18 Feb 2024 00:05:00 +0100 Subject: [PATCH 001/133] Update Support paragraph (fixes #274) --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 02621f3..7e0a149 100644 --- a/README.md +++ b/README.md @@ -119,9 +119,9 @@ Connect to others in complex network situations, or over the Internet.
PairDrop is libre, and always will be. \ -I footed the bill for the domain and the server, and you can help create great softeare by supporting me. \ -Please use BuyMeACoffee via the button above. \ -Thanks a lot for supporting copylefted libre software! +If you find it useful and want to support free and open-source software, please consider donating using the button above. \ +I footed the bill for the domain and the server, and you can help create and maintain great software by supporting me. \ +Thank you very much for your contribution! ## Contributing Feel free to [open an issue](https://github.com/schlagmichdoch/pairdrop/issues/new/choose) or a From 3c1bc9f82feb49b2f024a4153a6aee3f89750265 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Sun, 18 Feb 2024 01:15:52 +0100 Subject: [PATCH 002/133] Update answer for saving images to the iOS gallery and add linebreaks for better readability --- docs/faq.md | 53 +++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 6 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index 651a826..5b0365e 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -5,18 +5,22 @@ Help! I can't install the PWA! +
+ if you are using a Chromium-based browser (Chrome, Edge, Vivaldi, Brave, etc.), you can easily install PairDrop PWA on your desktop by clicking the install-button in the top-right corner while on [pairdrop.net](https://pairdrop.net). Example on how to install a pwa with Edge On Firefox, PWAs are installable via [this browser extensions](https://addons.mozilla.org/de/firefox/addon/pwas-for-firefox/) +
Self-Hosted Instance? To be able to install the PWA from a self-hosted instance, the connection needs to be [established through HTTPS](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Installable_PWAs). See [this host your own section](https://github.com/schlagmichdoch/PairDrop/blob/master/docs/host-your-own.md#testing-pwa-related-features) for more info. +
@@ -26,7 +30,9 @@ See [this host your own section](https://github.com/schlagmichdoch/PairDrop/blob Shortcuts? -Shortcuts +
+ +Available shortcuts: - Send a message with `CTRL + ENTER` - Close all "Send" and "Pair" dialogs by pressing `Esc`. - Copy a received message to the clipboard with `CTRL/⌘ + C`. @@ -40,12 +46,20 @@ Shortcuts How to save images directly to the gallery on iOS? -Apparently, iOS does not allow images shared from a website to be saved to the gallery directly. -It simply does not offer that option for images shared from a website. +
-iOS Shortcuts saves the day: +~~Apparently, iOS does not allow images shared from a website to be saved to the gallery directly.~~ +~~It simply does not offer that option for images shared from a website.~~ + +~~iOS Shortcuts saves the day:~~ \ I created a simple iOS shortcut that takes your photos and saves them to your gallery: https://routinehub.co/shortcut/13988/ + +Update: \ +Apparently, this was only a bug that is fixed in recent iOS version (https://github.com/WebKit/WebKit/pull/13111). \ +If you use an older affected iOS version this might still be of use. \ +Luckily, you can now simply use `Save Image`/`Save X Images` 🎉 +
@@ -55,10 +69,13 @@ https://routinehub.co/shortcut/13988/ Is it possible to send files or text directly from the "Context" or "Share" menu? +
+ Yes, it finally is. * [Send files directly from the "Context" menu on Windows](/docs/how-to.md#send-files-directly-from-context-menu-on-windows) * [Send directly from the "Share" menu on iOS](/docs/how-to.md#send-directly-from-share-menu-on-ios) * [Send directly from the "Share" menu on Android](/docs/how-to.md#send-directly-from-share-menu-on-android) +
@@ -68,9 +85,12 @@ Yes, it finally is. Is it possible to send files or text directly via CLI? +
+ Yes. * [Send directly from a command-line interface](/docs/how-to.md#send-directly-via-command-line-interface) +
@@ -80,11 +100,14 @@ Yes. Are there any third-party Apps? +
+ These third-party apps are compatible with PairDrop: 1. [Snapdrop Android App](https://github.com/fm-sys/snapdrop-android) 2. [Snapdrop for Firefox (Addon)](https://github.com/ueen/SnapdropFirefoxAddon) 3. Feel free to make one :) +
@@ -94,6 +117,8 @@ These third-party apps are compatible with PairDrop: What about the connection? Is it a P2P connection directly from device to device or is there any third-party-server? +
+ It uses a WebRTC peer-to-peer connection. WebRTC needs a signaling server that is only used to establish a connection. The server is not involved in the file transfer. @@ -109,6 +134,7 @@ to learn more about STUN, TURN and WebRTC. If you host your own instance and want to support devices that do not support WebRTC, you can [start the PairDrop instance with an activated WebSocket fallback](https://github.com/schlagmichdoch/PairDrop/blob/master/docs/host-your-own.md#websocket-fallback-for-vpn). +
@@ -118,6 +144,8 @@ you can [start the PairDrop instance with an activated WebSocket fallback](https What about privacy? Will files be saved on third-party servers? +
+ Files are sent directly between peers. PairDrop doesn't even use a database. If curious, study [the server](https://github.com/schlagmichdoch/pairdrop/blob/master/index.js). @@ -130,6 +158,7 @@ If your devices are paired and behind a NAT, the PairDrop TURN Server is used to route your files and messages. See the [Technical Documentation](technical-documentation.md#encryption-webrtc-stun-and-turn) to learn more about STUN, TURN and WebRTC. +
@@ -139,10 +168,13 @@ to learn more about STUN, TURN and WebRTC. What about security? Are my files encrypted while sent between the computers? +
+ Yes. Your files are sent using WebRTC, encrypting them in transit. To ensure the connection is secure and there is no [MITM](https://wikiless.org/wiki/Man-in-the-middle_attack), compare the security number shown under the device name on both devices. The security number is different for every connection. +
@@ -152,6 +184,8 @@ The security number is different for every connection. Transferring many files with paired devices takes too long +
+ Naturally, if traffic needs to be routed through the TURN server because your devices are behind different NATs, transfer speed decreases. @@ -164,6 +198,7 @@ which omits the need of the TURN server. You can also use mobile hotspots on phones to do that. Then, all data should be sent directly between devices and not use your data plan. +
@@ -173,6 +208,8 @@ Then, all data should be sent directly between devices and not use your data pla Why don't you implement feature xyz? +
+ Snapdrop and PairDrop are a study in radical simplicity. The user interface is insanely simple. Features are chosen very carefully because complexity grows quadratically @@ -184,7 +221,6 @@ Don't be sad. We may decline your feature request for the sake of simplicity. Read *Insanely Simple: The Obsession that Drives Apple's Success*, and/or *Thinking, Fast and Slow* to learn more. -
@@ -194,12 +230,14 @@ and/or *Thinking, Fast and Slow* to learn more. Snapdrop and PairDrop are awesome. How can I support them? +
+ * [Buy me a coffee](https://www.buymeacoffee.com/pairdrop) to pay for the domain and the server, and support libre software. * [File bugs, give feedback, submit suggestions](https://github.com/schlagmichdoch/pairdrop/issues) * Share PairDrop on social media. * Fix bugs and make a pull request. * Do some security analysis and make suggestions. -* To support the original Snapdrop and its creator go to [his GitHub page](https://github.com/RobinLinus/snapdrop) +
@@ -209,7 +247,10 @@ and/or *Thinking, Fast and Slow* to learn more. How does it work? +
+ [See here for info about the technical implementation](/docs/technical-documentation.md) +
From be46e7d4afb45a64ad1f791520972751f39686da Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Thu, 22 Feb 2024 16:03:35 +0100 Subject: [PATCH 003/133] Add some more info to the FAQ --- docs/faq.md | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index 5b0365e..76d82b0 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -7,17 +7,34 @@
-if you are using a Chromium-based browser (Chrome, Edge, Vivaldi, Brave, etc.), you can easily install PairDrop PWA on your desktop -by clicking the install-button in the top-right corner while on [pairdrop.net](https://pairdrop.net). +Here is a good guide on how to install PWAs on different platforms: \ +https://www.cdc.gov/niosh/mining/content/hearingloss/installPWA.html + + +**Chromium-based browser on Desktop (Chrome, Edge, Vivaldi, Brave, etc.)** \ +Easily install PairDrop PWA on your desktop by clicking the install-button in the top-right corner while on [pairdrop.net](https://pairdrop.net). Example on how to install a pwa with Edge +**Desktop Firefox** \ On Firefox, PWAs are installable via [this browser extensions](https://addons.mozilla.org/de/firefox/addon/pwas-for-firefox/) +**Android** \ +PWAs are installable only by using Google Chrome or Samsung Browser: +1. Visit [pairdrop.net](https://pairdrop.net) +2. Click _Install_ on the installation pop-up or use the three-dot-menu and click on _Add to Home screen_ +3. Click _Add_ on the pop-up + +**iOS** \ +PWAs are installable only by using Safari: +1. Visit [pairdrop.net](https://pairdrop.net) +2. Click on the share icon +3. Click _Add to Home Screen_ +4. Click _Add_ in the top right corner +
-Self-Hosted Instance? - +**Self-Hosted Instance?** \ To be able to install the PWA from a self-hosted instance, the connection needs to be [established through HTTPS](https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps/Installable_PWAs). See [this host your own section](https://github.com/schlagmichdoch/PairDrop/blob/master/docs/host-your-own.md#testing-pwa-related-features) for more info. @@ -227,7 +244,7 @@ and/or *Thinking, Fast and Slow* to learn more.
- Snapdrop and PairDrop are awesome. How can I support them? + PairDrop is awesome. How can I support it?
@@ -235,8 +252,9 @@ and/or *Thinking, Fast and Slow* to learn more. * [Buy me a coffee](https://www.buymeacoffee.com/pairdrop) to pay for the domain and the server, and support libre software. * [File bugs, give feedback, submit suggestions](https://github.com/schlagmichdoch/pairdrop/issues) * Share PairDrop on social media. -* Fix bugs and make a pull request. +* Fix bugs and create a pull request. * Do some security analysis and make suggestions. +* Participate in [active discussions](https://github.com/schlagmichdoch/PairDrop/discussions)
From 6ca37bd390fb2de302234d7d293b2cc880bc70b1 Mon Sep 17 00:00:00 2001 From: Cody Andersan <107530422+codyandersan@users.noreply.github.com> Date: Sun, 31 Mar 2024 08:42:03 +0530 Subject: [PATCH 004/133] Update README.md Removed duplicate feature. --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index 7e0a149..245dc79 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,6 @@ Send a file from your phone to your laptop? * Connect to devices in complex network environments (public Wi-Fi, company network, iCloud Private Relay, VPN, etc.). * Connect to devices on your mobile hotspot. * Devices outside of your local network that are behind a NAT are auto-connected via the PairDrop TURN server. -* Connect to devices on your mobile hotspot. * Devices from the local network, in the same public room, or previously paired are shown. #### Persistent Device Pairing From 35f47d9063c806ea5c9ca540836cf274a0bc820b Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Wed, 17 Apr 2024 20:38:33 +0200 Subject: [PATCH 005/133] Fix inner text being cleared when viewing next received text from queue + prevent skipping of queue entry when timing is bad by checking for existing timeout Co-authored-by: klmkyo --- public/scripts/ui.js | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/public/scripts/ui.js b/public/scripts/ui.js index af35524..c9bd365 100644 --- a/public/scripts/ui.js +++ b/public/scripts/ui.js @@ -2017,6 +2017,7 @@ class ReceiveTextDialog extends Dialog { this.$displayName = this.$el.querySelector('.display-name'); this._receiveTextQueue = []; + this._hideTimeout = null; } selectionEmpty() { @@ -2040,17 +2041,12 @@ class ReceiveTextDialog extends Dialog { this._setDocumentTitleMessages(); changeFavicon("images/favicon-96x96-notification.png"); - if (this.isShown()) return; + if (this.isShown() || this._hideTimeout) return; this._dequeueRequests(); } _dequeueRequests() { - if (!this._receiveTextQueue.length) { - this.$text.innerHTML = ""; - return; - } - this._setDocumentTitleMessages(); changeFavicon("images/favicon-96x96-notification.png"); @@ -2145,9 +2141,16 @@ class ReceiveTextDialog extends Dialog { hide() { super.hide(); - setTimeout(() => { - this._dequeueRequests(); - this.$text.innerHTML = ""; + + // If queue is empty -> clear text field | else -> open next message + this._hideTimeout = setTimeout(() => { + if (!this._receiveTextQueue.length) { + this.$text.innerHTML = ""; + } + else { + this._dequeueRequests(); + } + this._hideTimeout = null; }, 500); } } From 08aa1e62a4024a7222c0b7a0868142e22abf3dc9 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Wed, 17 Apr 2024 20:55:15 +0200 Subject: [PATCH 006/133] Translated using Weblate (Portuguese (Brazil)) Currently translated at 96.9% (161 of 166 strings) Translated using Weblate (Portuguese (Brazil)) Currently translated at 96.9% (161 of 166 strings) Co-authored-by: Hosted Weblate Co-authored-by: Richard Willian Co-authored-by: schlagmichdoch Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/pt_BR/ Translation: PairDrop/pairdrop-spa --- public/lang/pt-BR.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/lang/pt-BR.json b/public/lang/pt-BR.json index c495db0..fa1b50d 100644 --- a/public/lang/pt-BR.json +++ b/public/lang/pt-BR.json @@ -11,7 +11,7 @@ "pair-device_title": "Emparelhar seus dispositivos permanentemente", "edit-paired-devices_title": "Editar dispositivos emparelhados", "join-public-room_title": "Entrar em uma sala pública temporariamente", - "cancel-share-mode": "Concluído", + "cancel-share-mode": "Cancelar", "edit-share-mode": "Editar" }, "instructions": { @@ -22,8 +22,8 @@ "x-instructions_mobile": "Toque para enviar arquivos ou toque e segure para enviar uma mensagem", "x-instructions_data-drop-peer": "Solte para enviar para o par", "x-instructions_data-drop-bg": "Solte para selecionar o destinatário", - "x-instructions-share-mode_desktop": "Clique para enviar", - "x-instructions-share-mode_mobile": "Toque para enviar", + "x-instructions-share-mode_desktop": "Clique para enviar {{descriptor}}", + "x-instructions-share-mode_mobile": "Toque para enviar {{descriptor}}", "activate-share-mode-base": "Abra o PairDrop em outros dispositivos para enviar", "activate-share-mode-and-other-files-plural": "e {{count}} outros arquivos", "activate-share-mode-shared-text": "texto compartilhado", From 63717aae82e2d944fbad414a719246e4551dcd04 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Wed, 17 Apr 2024 20:55:15 +0200 Subject: [PATCH 007/133] Translated using Weblate (Russian) Currently translated at 87.3% (145 of 166 strings) Translated using Weblate (Russian) Currently translated at 87.3% (145 of 166 strings) Co-authored-by: Drako 1 Co-authored-by: Hosted Weblate Co-authored-by: schlagmichdoch Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/ru/ Translation: PairDrop/pairdrop-spa --- public/lang/ru.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/public/lang/ru.json b/public/lang/ru.json index 1bbc591..e23f900 100644 --- a/public/lang/ru.json +++ b/public/lang/ru.json @@ -11,14 +11,15 @@ "theme-dark_title": "Всегда использовать темную тему", "theme-light_title": "Всегда использовать светлую тему", "join-public-room_title": "Войти на время в публичную комнату", - "language-selector_title": "Выбрать язык" + "language-selector_title": "Выбрать язык", + "edit-share-mode": "Редактировать" }, "instructions": { "x-instructions_desktop": "Нажмите, чтобы отправить файлы, или щелкните правой кнопкой мыши, чтобы отправить сообщение", "no-peers_data-drop-bg": "Отпустите, чтобы выбрать получателя", - "x-instructions-share-mode_desktop": "Нажмите, чтобы отправить", + "x-instructions-share-mode_desktop": "Нажмите, чтобы отправить {{descriptor}}", "x-instructions_data-drop-bg": "Отпустите, чтобы выбрать получателя", - "x-instructions-share-mode_mobile": "Прикоснитесь, чтобы отправить", + "x-instructions-share-mode_mobile": "Прикоснитесь, чтобы отправить {{descriptor}}", "x-instructions_data-drop-peer": "Отпустите, чтобы послать узлу", "x-instructions_mobile": "Прикоснитесь коротко, чтобы отправить файлы, или долго, чтобы отправить сообщение", "no-peers-title": "Откройте PairDrop на других устройствах, чтобы отправить файлы", From 9c98bc3e9b0fc81bb237da20834261a0f10149ab Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Wed, 17 Apr 2024 20:55:15 +0200 Subject: [PATCH 008/133] Translated using Weblate (Japanese) Currently translated at 98.1% (163 of 166 strings) Co-authored-by: schlagmichdoch Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/ja/ Translation: PairDrop/pairdrop-spa --- public/lang/ja.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/lang/ja.json b/public/lang/ja.json index 4ce93bc..f25fb32 100644 --- a/public/lang/ja.json +++ b/public/lang/ja.json @@ -75,9 +75,9 @@ }, "instructions": { "x-instructions_mobile": "タップしてファイルを送信または長押ししてメッセージを送信します", - "x-instructions-share-mode_desktop": "クリックして送信", + "x-instructions-share-mode_desktop": "クリックして{{descriptor}}送信", "activate-share-mode-and-other-files-plural": "とその他{{count}}個のファイル", - "x-instructions-share-mode_mobile": "タップして送信", + "x-instructions-share-mode_mobile": "タップして{{descriptor}}送信", "activate-share-mode-base": "他のデバイスでPairDropを開いて送信します", "no-peers-subtitle": "デバイスをペア設定するかパブリックルームに参加すると、他のネットワーク上からも見つけられるようになります", "activate-share-mode-shared-text": "共有されたテキスト", From cce97a64964f6c8844b20bb3ce15d82c7d936e08 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Wed, 17 Apr 2024 20:55:15 +0200 Subject: [PATCH 009/133] Translated using Weblate (Hungarian) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 100.0% (166 of 166 strings) Translated using Weblate (Hungarian) Currently translated at 100.0% (166 of 166 strings) Translated using Weblate (Hungarian) Currently translated at 47.5% (79 of 166 strings) Added translation using Weblate (Hungarian) Co-authored-by: Balázs Szeles Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/hu/ Translation: PairDrop/pairdrop-spa --- public/lang/hu.json | 184 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 public/lang/hu.json diff --git a/public/lang/hu.json b/public/lang/hu.json new file mode 100644 index 0000000..7584f24 --- /dev/null +++ b/public/lang/hu.json @@ -0,0 +1,184 @@ +{ + "header": { + "language-selector_title": "Nyelv beállítása", + "theme-auto_title": "Téma automatikusan rendszerhez igazítása", + "about_aria-label": "\"A PairDrop-ról\" megnyitása", + "theme-light_title": "Mindig világos téma használata", + "theme-dark_title": "Mindig sötét téma használata", + "notification_title": "Értesítések engedélyezése", + "install_title": "PairDrop telepítése", + "edit-paired-devices_title": "Párosított eszközök szerkeztése", + "cancel-share-mode": "Mégse", + "edit-share-mode": "Szerkesztés", + "expand_title": "Fejléc gombsorának kibővítése", + "about_title": "A PairDrop-ról", + "pair-device_title": "Eszközei végleges párosítása", + "join-public-room_title": "Ideiglenes csatlakozás a nyilvános szobához" + }, + "instructions": { + "no-peers-title": "Nyissa meg a PairDrop-ot más eszközökön a fájlok küldéséhez", + "no-peers_data-drop-bg": "Engedje el a címzett kiválasztásához", + "x-instructions_desktop": "Kattintson a fájlküldéshez, vagy kattintson jobb gombbal üzenet küldéséhez", + "x-instructions_data-drop-peer": "Engedje el a partnernek való küldéshez", + "x-instructions_data-drop-bg": "Engedje el a címzett kiválasztásához", + "activate-share-mode-base": "Nyissa meg a PairDrop-ot más eszközökön a küldéséhez", + "activate-share-mode-and-other-file": "és egy másik fájl", + "activate-share-mode-and-other-files-plural": "és {{count}} másik fájl", + "activate-share-mode-shared-file": "megosztott fájl", + "activate-share-mode-shared-files-plural": "{{count}} megosztott fájl", + "x-instructions_mobile": "Koppintson a fájlküldéshez, vagy nyomja hosszan üzenet küldéséhez", + "x-instructions-share-mode_desktop": "Kattintson a {{descriptor}} küldéséhez", + "x-instructions-share-mode_mobile": "Koppintson a {{descriptor}} küldéséhez", + "activate-share-mode-shared-text": "megosztott szöveg", + "webrtc-requirement": "Ezen PairDrop példány használatához engedélyezni kell a WebRTC-t!", + "no-peers-subtitle": "Párosítsa eszközeit vagy lépjen be egy nyilvános szobába, hogy más hálózatokon is felfedezhető legyen" + }, + "footer": { + "known-as": "Ön így látható:", + "display-name_data-placeholder": "Betöltés…", + "display-name_title": "Az eszköze nevének végleges megváltoztatása", + "discovery": "Ön felfedezhető:", + "on-this-network_title": "Mindenki által felfedezhető a hálózaton.", + "paired-devices": "a csatlakoztatott eszközök által", + "public-room-devices": "a {{roomId}} szobában", + "traffic": "A forgalom", + "routed": "a szerveren van átirányítva", + "webrtc": "ha nem elérhető a WebRTC.", + "on-this-network": "ezen a hálózaton", + "paired-devices_title": "A párosított eszközeid által minden esetben felfedezhető a hálózaton, a hálózattól függetlenül.", + "public-room-devices_title": "Mindenki által felfedezhető ebben a nyilvános szobában, a hálózattól függetlenül." + }, + "dialogs": { + "input-key-on-this-device": "Írja be ezt a kódot egy másik eszközön", + "pair-devices-title": "Eszközök végleges párosítása", + "temporary-public-room-title": "Ideiglenes nyilvános szoba", + "input-room-id-on-another-device": "Írja be ezt a szobakódot egy másik eszközön", + "enter-room-id-from-another-device": "Írja be a szobakódot egy másik eszközről a szobához való csatlakozáshoz.", + "cancel": "Mégse", + "pair": "Párosítás", + "edit-paired-devices-title": "Párosított eszközök szerkesztése", + "unpair": "Párosítás megszüntetése", + "paired-device-removed": "Párosított eszköz eltávolítva.", + "paired-devices-wrapper_data-empty": "Nincs párosított eszköz.", + "auto-accept": "automatikus elfogadás", + "close": "Bezárás", + "join": "Csatlakozás", + "would-like-to-share": "szeretne megosztani", + "accept": "Elfogadás", + "has-sent": "küldött:", + "share": "Megosztás", + "send-message-title": "Üzenet küldése", + "send-message-to": "Neki:", + "receive-text-title": "Üzenet érkezett", + "base64-processing": "Feldolgozás…", + "scan-qr-code": "vagy olvassa be a QR-kódot.", + "auto-accept-instructions-1": "Aktiválás", + "auto-accept-instructions-2": "hogy automatikusan elfogadja az adott eszközről küldött összes fájlt.", + "leave": "Kilépés", + "decline": "Elutasítás", + "download": "Letöltés", + "send": "Küldés", + "message_title": "Írja be a küldeni kívánt üzenetet", + "message_placeholder": "Szöveg", + "copy": "Másolás", + "base64-title-files": "Fájlok megosztása", + "base64-title-text": "Szöveg megosztása", + "enter-key-from-another-device": "Ide írja be a kódot egy másik eszközről.", + "hr-or": "VAGY", + "base64-text": "szöveg", + "base64-tap-to-paste": "Koppintson ide a {{type}} megosztásához", + "base64-paste-to-send": "Illessze be a ide a vágólapja tartalmát a {{type}} megosztásához", + "base64-files": "fájlok", + "file-other-description-image": "és egy másik kép", + "file-other-description-file": "és egy másik fájl", + "file-other-description-image-plural": "és {{count}} másik kép", + "file-other-description-file-plural": "és {{count}} másik fájl", + "title-image": "Kép", + "title-file": "Fájl", + "title-image-plural": "Képek", + "title-file-plural": "Fájlok", + "receive-title": "{{descriptor}} érkezett", + "download-again": "Letöltés újra", + "language-selector-title": "Nyelv beállítása", + "system-language": "Rendszer nyelve", + "approve": "jóváhagyás", + "share-text-title": "Szöveges üzenet megosztása", + "share-text-subtitle": "Üzenet szerkesztése küldés előtt:", + "share-text-checkbox": "Mindig mutassa ezt a párbeszédablakot üzenet megosztásakor", + "close-toast_title": "Értesítés bezárása", + "public-room-qr-code_title": "Kattintson a szoba linkjének másolásához", + "pair-devices-qr-code_title": "Kattintson az eszköz párosításához való link másolásához" + }, + "notifications": { + "online-requirement-pairing": "Online kell lennie készülékek párosításához", + "link-received": "Link érkezett tőle: {{name}} - Kattintson a megnyitáshoz", + "selected-peer-left": "A kiválasztott partner kilépett", + "display-name-changed-permanently": "A megjelenített neved véglegesen meg lett változtatva", + "download-successful": "{{descriptor}} letöltve", + "pairing-tabs-error": "Két böngészőlap párosítása lehetetlen", + "display-name-random-again": "A megjelenített neved véletlenszerűen újra lett generálva", + "pairing-key-invalid": "Érvénytelen kulcs", + "pairing-cleared": "Minden eszköz párosítása megszüntetve", + "public-room-id-invalid": "Érvénytelen szobakód", + "copied-to-clipboard": "Vágólapra másolva", + "copied-to-clipboard-error": "Másolás nem lehetséges. Manuális másolás szükséges.", + "text-content-incorrect": "A szöveg tartalma helytelen", + "file-content-incorrect": "A fájl tartalma helytelen", + "pair-url-copied-to-clipboard": "Az eszköz párosítására való link másolva a vágólapra", + "notifications-enabled": "Értesítések engedélyezve", + "request-title": "{{name}} szeretne küldeni: {{count}} {{descriptor}}", + "copied-text-error": "A vágólapra való írás nem sikerült. Manuális másolás szükséges.", + "click-to-download": "Kattintson a letöltéshez", + "click-to-show": "Kattintson a megjelenítéshez", + "connected": "Csatlakoztatva", + "online": "Újra online lett", + "connecting": "Csatlakozás…", + "files-incorrect": "A fájlok helytelenek", + "file-transfer-completed": "A fájlok küldése sikeres", + "message-transfer-completed": "Üzenet küldése sikeres", + "unfinished-transfers-warning": "Befejezetlen átvitelek folyamatban. Biztosan be akarja zárni a PairDrop-ot?", + "pairing-success": "Eszközök párosítva", + "pairing-not-persistent": "A párosított eszközök nem maradandóak", + "pairing-key-invalidated": "{{key}} kulcs érvénytelenítve", + "public-room-left": "{{publicRoomId}} szoba elhagyva", + "online-requirement-public-room": "Online kell lennie szoba készítéséhez", + "ios-memory-limit": "Egyszerre csak 200 MB-os fájlátvitel lehetséges iOS-re való küldéskor", + "room-url-copied-to-clipboard": "A nyilvános szoba linkje másolva a vágólapra", + "clipboard-content-incorrect": "A vágólap tartalma helytelen", + "copied-text": "Szöveg másolva a vágólapra", + "message-received": "Üzenet érkezett tőle: {{name}} - Kattintson a másoláshoz", + "notifications-permissions-error": "Az értesítések engedélye letiltásra került, mivel a felhasználó többször is elutasította az engedélykérést. Ez visszaállítható az oldalinformációkban, amely az URL-sáv melletti lakat ikonra kattintva érhet el.", + "offline": "Ön offline", + "rate-limit-join-key": "Az átviteli sebességhatár elérte a határt. Várjon 10 másodpercet, és próbálja meg újra.", + "display-name-changed-temporarily": "A megjelenített neved meg lett változtatva csak erre a munkamenetre" + }, + "about": { + "close-about_aria-label": "A PairDrop-ról bezárása", + "github_title": "PairDrop a GitHub-on", + "buy-me-a-coffee_title": "Vegyél nekem egy kávét!", + "mastodon_title": "Írj a PairDrop-ról Mastodon-on", + "bluesky_title": "Kövess minket a BlueSky-on", + "faq_title": "Gyakran ismételt kérdések", + "claim": "Az eszközök közötti fájlátvitel legegyszerűbb módja", + "tweet_title": "Tweetelj a PairDrop-ról", + "custom_title": "Kövess minket", + "privacypolicy_title": "Nyisd meg az adatvédelmi szabályzatunkat" + }, + "document-titles": { + "file-received": "Fájl érkezett", + "file-received-plural": "{{count}} fájl érkezett", + "image-transfer-requested": "Képátvitel kérelmezve", + "message-received": "Üzenet érkezett", + "message-received-plural": "{{count}} üzenet érkezett", + "file-transfer-requested": "Fájlátvitel kérelmezve" + }, + "peer-ui": { + "preparing": "Előkészítés…", + "click-to-send-share-mode": "Kattintson a {{descriptor}} küldéséhez", + "waiting": "Várakozás…", + "processing": "Feldolgozás…", + "transferring": "Átvitel…", + "click-to-send": "Kattintson fájlok küldéséhez vagy kattintson jobb gombbal üzenet küldéséhez", + "connection-hash": "A végpontok közötti titkosítás biztonságának ellenőrzéséhez hasonlítsa össze ezt a biztonsági számot mindkét eszközön" + } +} From e07255398fd77f71a0e4c203aef15113d5000a07 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Wed, 17 Apr 2024 20:55:15 +0200 Subject: [PATCH 010/133] Added translation using Weblate (Hebrew) Co-authored-by: Hosted Weblate Co-authored-by: schlagmichdoch --- public/lang/he.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 public/lang/he.json diff --git a/public/lang/he.json b/public/lang/he.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/public/lang/he.json @@ -0,0 +1 @@ +{} From 6330f09486bee9f6024c1456b65640f839fe9f42 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Wed, 17 Apr 2024 20:55:15 +0200 Subject: [PATCH 011/133] Translated using Weblate (Polish) Currently translated at 100.0% (166 of 166 strings) Added translation using Weblate (Polish) Co-authored-by: Ash Mad Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/pl/ Translation: PairDrop/pairdrop-spa --- public/lang/pl.json | 184 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 public/lang/pl.json diff --git a/public/lang/pl.json b/public/lang/pl.json new file mode 100644 index 0000000..1f2f593 --- /dev/null +++ b/public/lang/pl.json @@ -0,0 +1,184 @@ +{ + "header": { + "language-selector_title": "Ustaw język", + "about_aria-label": "Otwórz \"O PairDrop\"", + "theme-light_title": "Zawsze używaj jasnego motywu", + "theme-dark_title": "Zawsze używaj ciemnego motywu", + "pair-device_title": "Sparuj swoje urządzenia na stałe", + "edit-paired-devices_title": "Edytuj sparowane urządzenia", + "join-public-room_title": "Dołącz tymczasowo do pokoju publicznego", + "cancel-share-mode": "Anuluj", + "edit-share-mode": "Edytuj", + "expand_title": "Rozwiń rząd przycisków", + "about_title": "O PairDrop", + "theme-auto_title": "Dostosuj motyw do motywu systemowego", + "notification_title": "Włącz powiadomienia", + "install_title": "Zainstaluj PairDrop" + }, + "instructions": { + "no-peers_data-drop-bg": "Zwolnij, aby wybrać odbiorcę", + "no-peers-title": "Otwórz PairDrop na innych urządzeniach, aby wysłać pliki", + "x-instructions_desktop": "Kliknij, aby wysłać pliki lub kliknij prawym przyciskiem myszy, aby wysłać wiadomość", + "x-instructions_mobile": "Naciśnij, aby wysłać pliki lub naciśnij i przytrzymaj, aby wysłać wiadomość", + "x-instructions_data-drop-bg": "Zwolnij, aby wybrać odbiorcę", + "x-instructions-share-mode_desktop": "Kliknij, aby wysłać {{descriptor}}", + "x-instructions-share-mode_mobile": "Naciśnij, aby wysłać {{descriptor}}", + "activate-share-mode-base": "Otwórz PairDrop na innych urządzeniach, aby wysłać", + "activate-share-mode-and-other-file": "i 1 inny plik", + "activate-share-mode-shared-text": "udostępniony tekst", + "activate-share-mode-shared-file": "udostępniony plik", + "no-peers-subtitle": "Sparuj urządzenia lub wejdź do pokoju publicznego, aby być widocznym w innych sieciach", + "x-instructions_data-drop-peer": "Zwolnij, aby wysłać do odbiorcy", + "activate-share-mode-and-other-files-plural": "i {{count}} innych plików", + "activate-share-mode-shared-files-plural": "{{count}} udostępnionych plików", + "webrtc-requirement": "Aby móc korzystać z tej instancji PairDrop, należy włączyć WebRTC!" + }, + "footer": { + "known-as": "Jesteś widoczny jako:", + "display-name_data-placeholder": "Ładowanie…", + "display-name_title": "Edytuj nazwę swojego urządzenia na stałe", + "on-this-network": "w tej sieci", + "on-this-network_title": "Możesz być znaleziony przez każdego w tej sieci.", + "paired-devices": "przez sparowane urządzenia", + "discovery": "Możesz być wykryty:", + "paired-devices_title": "Możesz zostać wykryty przez sparowane urządzenia przez cały czas, niezależnie od sieci.", + "public-room-devices": "w pokoju {{roomId}}", + "public-room-devices_title": "Możesz zostać wykryty przez urządzenia w tym pokoju publicznym, niezależnie od sieci.", + "routed": "przesyłane przez serwer", + "webrtc": "jeśli WebRTC jest niedostępny.", + "traffic": "Transmisja jest" + }, + "dialogs": { + "pair-devices-title": "Sparuj Urządzenia Na Stałe", + "enter-key-from-another-device": "Wpisz tu klucz z innego urządzenia.", + "temporary-public-room-title": "Tymczasowy Pokój Publiczny", + "enter-room-id-from-another-device": "Wprowadź ID pokoju z innego urządzenia, aby wejść do pokoju.", + "hr-or": "LUB", + "pair": "Sparuj", + "cancel": "Anuluj", + "edit-paired-devices-title": "Edycja Sparowanych Urządzeń", + "unpair": "Rozłącz sparowanie", + "paired-devices-wrapper_data-empty": "Brak sparowanych urządzeń.", + "auto-accept-instructions-1": "Aktywuj", + "auto-accept-instructions-2": ", aby automatycznie przyjąć wszystkie pliki wysłane z tego urządzenia.", + "auto-accept": "samoczynne potwierdzanie", + "close": "Zamknij", + "join": "Dołącz", + "leave": "Opuść", + "accept": "Akceptuj", + "decline": "Odrzuć", + "has-sent": "wysłał:", + "share": "Udostępnij", + "send-message-title": "Wyślij Wiadomość", + "send-message-to": "Do:", + "message_title": "Wprowadź wiadomość do wysłania", + "message_placeholder": "Tekst", + "receive-text-title": "Wiadomość Odebrana", + "copy": "Kopiuj", + "base64-title-files": "Udostępnij Pliki", + "base64-title-text": "Udostępnij Tekst", + "base64-processing": "Przetwarzanie…", + "base64-tap-to-paste": "Naciśnij tutaj, aby udostępnić {{type}}", + "base64-text": "tekst", + "base64-files": "pliki", + "file-other-description-image": "i 1 inny obraz", + "file-other-description-image-plural": "i {{count}} innych obrazów", + "file-other-description-file-plural": "i {{count}} innych plików", + "title-image": "Obraz", + "title-image-plural": "Obrazy", + "title-file-plural": "Pliki", + "receive-title": "{{descriptor}} Otrzymano", + "download-again": "Pobierz ponownie", + "download": "Pobierz", + "language-selector-title": "Ustaw Język", + "system-language": "Język Systemu", + "file-other-description-file": "i 1 inny plik", + "pair-devices-qr-code_title": "Kliknij, aby skopiować odnośnik do sparowania urządzenia", + "approve": "zatwierdź", + "share-text-subtitle": "Edytuj wiadomość przed wysłaniem:", + "share-text-checkbox": "Zawsze pokazuj to okno, gdy udostępniasz tekst", + "paired-device-removed": "Sparowane urządzenie zostało usunięte.", + "would-like-to-share": "chciałby udostępnić", + "input-key-on-this-device": "Wprowadź ten klucz na innym urządzeniu", + "send": "Wyślij", + "scan-qr-code": "lub zeskanuj kod QR.", + "base64-paste-to-send": "Wklej tutaj, aby udostępnić {{type}}", + "title-file": "Plik", + "input-room-id-on-another-device": "Wprowadź ID tego pokoju na innym urządzeniu", + "public-room-qr-code_title": "Kliknij, aby skopiować odnośnik do pokoju publicznego", + "share-text-title": "Udostępnij Wiadomość Tekstową", + "close-toast_title": "Zamknij powiadomienie" + }, + "about": { + "close-about_aria-label": "Zamknij \"O PairDrop\"", + "claim": "Najłatwiejszy sposób na przesyłanie plików między urządzeniami", + "buy-me-a-coffee_title": "Kup me kawę!", + "mastodon_title": "Napisz o PairDrop na Mastodonie", + "bluesky_title": "Śledź nas na BlueSky", + "custom_title": "Śledź nas", + "privacypolicy_title": "Otwórz naszą Politykę Prywatności", + "faq_title": "Często zadawane pytania (FAQ)", + "github_title": "PairDrop na GitHub", + "tweet_title": "Tweetnij o PairDrop" + }, + "notifications": { + "display-name-changed-permanently": "Wyświetlana nazwa została zmieniona na stałe", + "display-name-random-again": "Wyświetlana nazwa została ponownie wygenerowana", + "download-successful": "{{descriptor}} pobrano", + "pairing-tabs-error": "Sparowanie dwóch kart w przeglądarce jest niemożliwe", + "pairing-success": "Sparowane urządzenia", + "pairing-key-invalid": "Nieprawidłowy klucz", + "pairing-key-invalidated": "Klucz {{key}} unieważniony", + "public-room-id-invalid": "Nieprawidłowe ID pokoju", + "pairing-cleared": "Wszystkie urządzenia rozłączone", + "public-room-left": "Opuściłeś pokój publiczny {{publicRoomId}}", + "copied-to-clipboard-error": "Kopiowanie niemożliwe. Skopiuj ręcznie.", + "text-content-incorrect": "Treść tekstu jest nieprawidłowa", + "file-content-incorrect": "Zawartość pliku jest nieprawidłowa", + "clipboard-content-incorrect": "Zawartość schowka jest nieprawidłowa", + "pair-url-copied-to-clipboard": "Link do sparowania tego urządzenia skopiowano do schowka", + "link-received": "Otrzymano link od {{name}} - Kliknij, aby otworzyć", + "message-received": "Otrzymano wiadomość od {{name}} - Kliknij, aby skopiować", + "click-to-download": "Kliknij, aby pobrać", + "request-title": "{{name}} chciałby przesłać {{count}} {{descriptor}}", + "click-to-show": "Kliknij, żeby pokazać", + "copied-text": "Tekst skopiowany do schowka", + "copied-text-error": "Zapis do schowka nie powiódł się. Skopiuj ręcznie!", + "offline": "Jesteś offline", + "online": "Jesteś znów online", + "connected": "Połączony", + "online-requirement-pairing": "Aby sparować urządzenia, musisz być online", + "online-requirement-public-room": "Aby utworzyć pokój publiczny, musisz być online", + "connecting": "Łączenie…", + "files-incorrect": "Pliki są nieprawidłowe", + "file-transfer-completed": "Przesyłanie plików zakończone", + "ios-memory-limit": "Jednorazowe przesyłanie plików do iOS jest możliwe tylko do 200 MB", + "message-transfer-completed": "Przesyłanie wiadomości zakończone", + "unfinished-transfers-warning": "Istnieją niedokończone transfery. Czy na pewno chcesz zamknąć PairDrop?", + "rate-limit-join-key": "Osiągnięto limit. Poczekaj 10 sekund i spróbuj ponownie.", + "selected-peer-left": "Wybrany uczestnik opuścił", + "display-name-changed-temporarily": "Wyświetlana nazwa została zmieniona na czas tej sesji", + "pairing-not-persistent": "Połączenie sparowanych urządzeń nie jest trwałe", + "copied-to-clipboard": "Skopiowano do schowka", + "room-url-copied-to-clipboard": "Link do publicznego pokoju skopiowano do schowka", + "notifications-enabled": "Powiadomienia włączone", + "notifications-permissions-error": "Uprawnienia do powiadomień zostały zablokowane, ponieważ użytkownik kilkakrotnie odrzucił monit o pozwolenie na nie. Można je zresetować w \"Informacjach o [stronie]\", do których można uzyskać dostęp, klikając ikonę kłódki obok paska adresu URL." + }, + "document-titles": { + "file-received": "Plik Odebrany", + "file-received-plural": "{{count}} Plików Odebranych", + "file-transfer-requested": "Zażądano Przesłania Pliku", + "image-transfer-requested": "Zażądano Przesłania Obrazu", + "message-received": "Otrzymano Wiadomość", + "message-received-plural": "{{count}} Wiadomości Odebranych" + }, + "peer-ui": { + "click-to-send-share-mode": "Kliknij, aby wysłać {{descriptor}}", + "click-to-send": "Kliknij, aby wysłać pliki lub kliknij prawym przyciskiem myszy, aby wysłać wiadomość", + "connection-hash": "Aby sprawdzić bezpieczeństwo szyfrowania end-to-end, porównaj ten numer bezpieczeństwa na obu urządzeniach", + "preparing": "Przygotowanie…", + "waiting": "Oczekiwanie…", + "processing": "Przetwarzanie…", + "transferring": "Przesyłanie…" + } +} From 61861df99e1d68c8dd3203d17762bf79d0e679dc Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Wed, 17 Apr 2024 20:55:15 +0200 Subject: [PATCH 012/133] Translated using Weblate (Arabic) Currently translated at 83.7% (139 of 166 strings) Co-authored-by: schlagmichdoch Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/ar/ Translation: PairDrop/pairdrop-spa --- public/lang/ar.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/lang/ar.json b/public/lang/ar.json index b29d338..a3c333e 100644 --- a/public/lang/ar.json +++ b/public/lang/ar.json @@ -71,9 +71,9 @@ }, "instructions": { "x-instructions_mobile": "انقر لإرسال الملفات أو انقر لفترة طويلة لإرسال رسالة", - "x-instructions-share-mode_desktop": "انقر للإرسال", + "x-instructions-share-mode_desktop": "انقر للإرسال {{descriptor}}", "activate-share-mode-and-other-files-plural": "و{{count}} ملفات أخرى", - "x-instructions-share-mode_mobile": "انقر للإرسال", + "x-instructions-share-mode_mobile": "انقر للإرسال {{descriptor}}", "activate-share-mode-base": "افتح PairDrop على الأجهزة الأخرى للإرسال", "no-peers-subtitle": "قم بإقران الأجهزة أو ادخل إلى غرفة عامة لتتمكن من أن تكتشف على الشبكات الأخرى", "activate-share-mode-shared-text": "النص المشترك", From 3cc2ab99b54ace3e21018da35eba6c1030866034 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Wed, 17 Apr 2024 20:55:15 +0200 Subject: [PATCH 013/133] Translated using Weblate (Indonesian) Currently translated at 93.9% (156 of 166 strings) Co-authored-by: schlagmichdoch Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/id/ Translation: PairDrop/pairdrop-spa --- public/lang/id.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/lang/id.json b/public/lang/id.json index 5159c4b..ba921a1 100644 --- a/public/lang/id.json +++ b/public/lang/id.json @@ -75,9 +75,9 @@ }, "instructions": { "x-instructions_mobile": "Ketuk untuk mengirim file atau ketuk lama untuk mengirim pesan", - "x-instructions-share-mode_desktop": "Klik untuk mengirim", + "x-instructions-share-mode_desktop": "Klik untuk mengirim {{descriptor}}", "activate-share-mode-and-other-files-plural": "dan {{count}} file lainnya", - "x-instructions-share-mode_mobile": "Ketuk untuk mengirim", + "x-instructions-share-mode_mobile": "Ketuk untuk mengirim {{descriptor}}", "activate-share-mode-base": "Buka PairDrop di perangkat lain untuk berkirim", "no-peers-subtitle": "Pasangkan perangkat atau masuk ke ruang publik agar dapat terdeteksi di jaringan lain", "activate-share-mode-shared-text": "teks bersama", From 46b6b38ad52f259c215e46789a4d5dcd97272908 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Wed, 17 Apr 2024 20:55:15 +0200 Subject: [PATCH 014/133] Translated using Weblate (Dutch) Currently translated at 100.0% (166 of 166 strings) Translated using Weblate (Dutch) Currently translated at 100.0% (166 of 166 strings) Co-authored-by: Arne Cuperus Co-authored-by: Hosted Weblate Co-authored-by: schlagmichdoch Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/nl/ Translation: PairDrop/pairdrop-spa --- public/lang/nl.json | 45 +++++++++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/public/lang/nl.json b/public/lang/nl.json index 6287ed8..801c34a 100644 --- a/public/lang/nl.json +++ b/public/lang/nl.json @@ -52,7 +52,10 @@ "online-requirement-public-room": "U moet online zijn om een openbare kamer te maken", "copied-text-error": "Schrijven naar klembord mislukt. Kopieer handmatig!", "download-successful": "{{descriptor}} downloaden", - "click-to-show": "Klik om te tonen" + "click-to-show": "Klik om te tonen", + "pair-url-copied-to-clipboard": "Koppeling om dit apparaat te koppelen is gekopieerd naar het klembord", + "room-url-copied-to-clipboard": "Koppeling naar openbare kamer gekopieerd naar klembord", + "notifications-permissions-error": "Meldingsmachtiging is geblokkeerd, omdat de gebruiker het machtigingsverzoek meerdere keren heeft afgewezen. Dit kan worden gereset in instellingen van de website, welke toegangelijk is door te klikken op het sloticoon naast de URL-balk." }, "header": { "cancel-share-mode": "Klaar", @@ -66,13 +69,15 @@ "language-selector_title": "Taal Selecteren", "about_title": "Over PairDrop", "about_aria-label": "Open Over PairDrop", - "theme-light_title": "Altijd lichte modus gebruiken" + "theme-light_title": "Altijd lichte modus gebruiken", + "expand_title": "Knoppenrij uitvouwen", + "edit-share-mode": "Bewerken" }, "instructions": { "x-instructions_mobile": "Tik om bestanden te versturen of houdt vast om een bericht te sturen", - "x-instructions-share-mode_desktop": "Klik om te verzenden", + "x-instructions-share-mode_desktop": "Klik om te verzenden {{descriptor}}", "activate-share-mode-and-other-files-plural": "en {{count}} andere bestanden", - "x-instructions-share-mode_mobile": "Tik om te verzenden", + "x-instructions-share-mode_mobile": "Tik om te verzenden {{descriptor}}", "activate-share-mode-base": "Open PairDrop op andere apparaten om te verzenden", "no-peers-subtitle": "Koppel apparaten of betreed een openbare ruimte om op andere netwerken zichtbaar te worden", "activate-share-mode-shared-text": "gedeelde tekst", @@ -80,7 +85,11 @@ "no-peers-title": "Open PairDrop op andere apparaten om bestanden te versturen", "x-instructions_data-drop-peer": "Laat los om naar peer te versturen", "x-instructions_data-drop-bg": "Loslaten om ontvanger te selecteren", - "no-peers_data-drop-bg": "Loslaten om ontvanger te kiezen" + "no-peers_data-drop-bg": "Loslaten om ontvanger te kiezen", + "activate-share-mode-and-other-file": "en 1 ander bestand", + "activate-share-mode-shared-file": "gedeeld bestand", + "activate-share-mode-shared-files-plural": "{{count}} gedeelde bestanden", + "webrtc-requirement": "Om deze PairDrop instantie te kunnen gebruiken, moet WebRTC geactiveerd zijn!" }, "peer-ui": { "processing": "Verwerken…", @@ -92,7 +101,7 @@ "transferring": "Overdragen…" }, "dialogs": { - "base64-paste-to-send": "Plak hier om {{type}} te versturen", + "base64-paste-to-send": "Plak klembord hier om {{type}} te versturen", "auto-accept-instructions-2": "om automatisch alle bestanden van dat apparaat te accepteren.", "receive-text-title": "Bericht Ontvangen", "edit-paired-devices-title": "Gekoppelde Apparaten Bewerken", @@ -108,7 +117,7 @@ "join": "Betreden", "title-image-plural": "Afbeeldingen", "send": "Verzenden", - "base64-tap-to-paste": "Hier tikken om {{type}} te plakken", + "base64-tap-to-paste": "Hier tikken om {{type}} te delen", "base64-text": "tekst", "copy": "Kopiëren", "file-other-description-image": "en één andere afbeelding", @@ -122,7 +131,7 @@ "title-image": "Afbeelding", "file-other-description-file-plural": "en {{count}} andere bestanden", "would-like-to-share": "zou graag het volgende willen delen", - "send-message-to": "Verstuur een bericht naar", + "send-message-to": "Aan:", "language-selector-title": "Taal Instellen", "pair": "Koppel", "hr-or": "OF", @@ -138,7 +147,19 @@ "send-message-title": "Bericht Sturen", "input-room-id-on-another-device": "Voer de kamer ID in op een ander apparaat", "file-other-description-image-plural": "en {{count}} andere afbeeldingen", - "enter-room-id-from-another-device": "Voer de kamer ID van een ander apparaat hier in." + "enter-room-id-from-another-device": "Voer de kamer ID van een ander apparaat hier in.", + "paired-device-removed": "Gekoppelde apparaten zijn verwijderd.", + "message_title": "Voer bericht in om te versturen", + "message_placeholder": "Tekst", + "base64-title-files": "Deel Bestanden", + "base64-title-text": "Deel Tekst", + "public-room-qr-code_title": "Klik, om de link naar deze openbare ruimte te kopiëren", + "approve": "goedkeuren", + "share-text-title": "Gedeeld Tekst Bericht", + "share-text-checkbox": "Deze dialoog altijd tonen bij het delen van tekst", + "close-toast_title": "Bericht sluiten", + "pair-devices-qr-code_title": "Klik om de koppeling te kopiëren om dit apparaat te koppelen", + "share-text-subtitle": "Bewerk bericht voor verzending:" }, "about": { "claim": "De makkelijkste manier om bestanden tussen apparaten te versturen", @@ -146,7 +167,11 @@ "close-about_aria-label": "Sluit Over PairDrop", "buy-me-a-coffee_title": "Koop een kopje koffie voor mij!", "github_title": "PairDrop op GitHub", - "faq_title": "Veel gestelde vragen" + "faq_title": "Veel gestelde vragen", + "mastodon_title": "Schrijf over PairDrop op Mastodon", + "bluesky_title": "Volg ons op BlueSky", + "custom_title": "Volg ons", + "privacypolicy_title": "Open ons privacybeleid" }, "document-titles": { "file-transfer-requested": "Bestandsoverdracht verzocht", From f0cfb4833d168b7ec9029b37fef177dd2cd5767a Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Wed, 17 Apr 2024 20:55:15 +0200 Subject: [PATCH 015/133] Translated using Weblate (French) Currently translated at 98.7% (164 of 166 strings) Co-authored-by: Hosted Weblate Co-authored-by: Thumuss <42680097+Thumuss@users.noreply.github.com> Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/fr/ Translation: PairDrop/pairdrop-spa --- public/lang/fr.json | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/public/lang/fr.json b/public/lang/fr.json index b77ed96..e72eefc 100644 --- a/public/lang/fr.json +++ b/public/lang/fr.json @@ -11,7 +11,9 @@ "pair-device_title": "Associez vos appareils de manière permanente", "edit-paired-devices_title": "Gérer les appareils couplés", "join-public-room_title": "Rejoindre temporairement la salle publique", - "cancel-share-mode": "Terminé" + "cancel-share-mode": "Terminé", + "edit-share-mode": "Modifier", + "expand_title": "Agrandir entête bouton ligne" }, "instructions": { "no-peers_data-drop-bg": "Déposer pour choisir le destinataire", @@ -21,11 +23,15 @@ "x-instructions_mobile": "Appuyez pour envoyer des fichiers ou appuyez longuement pour envoyer un message", "x-instructions_data-drop-peer": "Déposer pour envoyer au destinataire", "x-instructions_data-drop-bg": "Lâcher pour choisir le destinataire", - "x-instructions-share-mode_desktop": "Cliquez pour envoyer", - "x-instructions-share-mode_mobile": "Appuyez pour envoyer", + "x-instructions-share-mode_desktop": "Cliquez pour envoyer {{descriptor}}", + "x-instructions-share-mode_mobile": "Appuyez pour envoyer {{descriptor}}", "activate-share-mode-base": "Ouvrez PairDrop sur d'autres appareils pour envoyer", "activate-share-mode-and-other-files-plural": "et {{count}} autres fichiers", - "activate-share-mode-shared-text": "texte partagé" + "activate-share-mode-shared-text": "texte partagé", + "activate-share-mode-shared-file": "fichier partagé", + "webrtc-requirement": "Pour utiliser cette instance de PairDrop, WebRTC doit être activé !", + "activate-share-mode-shared-files-plural": "{{count}} fichiers partagés", + "activate-share-mode-and-other-file": "et un autre fichier" }, "footer": { "known-as": "Vous êtes connu comme :", @@ -70,13 +76,13 @@ "share": "Partage", "download": "Télécharger", "send-message-title": "Envoyer un message", - "send-message-to": "Envoyer un message à", + "send-message-to": "À :", "send": "Envoyer", "receive-text-title": "Message reçu", "copy": "Copier", "base64-processing": "Traitement…", - "base64-tap-to-paste": "Appuyez ici pour coller {{type}}", - "base64-paste-to-send": "Coller ici pour envoyer {{type}}", + "base64-tap-to-paste": "Appuyez ici pour partager {{type}}", + "base64-paste-to-send": "Coller ici pour partager {{type}}", "base64-text": "texte", "base64-files": "fichiers", "file-other-description-image": "et 1 autre image", @@ -93,7 +99,16 @@ "system-language": "Langue du système", "message_title": "Insérer un message à envoyer", "pair-devices-qr-code_title": "Cliquer pour copier pour appairer l'appareil", - "public-room-qr-code_title": "Cliquez pour copier le lien vers le salon public" + "public-room-qr-code_title": "Cliquez pour copier le lien vers le salon public", + "base64-title-text": "Texte partagé", + "paired-device-removed": "L'appareil connecté a été enlevé.", + "message_placeholder": "Texte", + "base64-title-files": "Fichiers partagés", + "approve": "approuve", + "share-text-title": "Partage le message", + "share-text-subtitle": "Modifier le message avant l'envoi :", + "share-text-checkbox": "Toujours montrer ce dialogue quand du texte est partagé", + "close-toast_title": "Fermer la notification" }, "about": { "close-about_aria-label": "Fermer à propos de PairDrop", @@ -101,7 +116,10 @@ "github_title": "PairDrop sur GitHub", "buy-me-a-coffee_title": "Achetez-moi un café !", "tweet_title": "Tweet à propos de PairDrop", - "faq_title": "Questions fréquemment posées" + "faq_title": "Questions fréquemment posées", + "bluesky_title": "Suis-nous sur BlueSky", + "custom_title": "Suis-nous", + "privacypolicy_title": "Ouvert sur notre politique de confidentialité" }, "notifications": { "display-name-changed-permanently": "Le nom d'affichage est modifié de manière permanente", From fd0c32faad9adda9b1c3297fcb3876227a0f5920 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Wed, 17 Apr 2024 20:55:15 +0200 Subject: [PATCH 016/133] Added translation using Weblate (Finnish) Co-authored-by: Hosted Weblate Co-authored-by: Unknowwed --- public/lang/fi.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 public/lang/fi.json diff --git a/public/lang/fi.json b/public/lang/fi.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/public/lang/fi.json @@ -0,0 +1 @@ +{} From add361c28435af9e353f55b668b65217b593fc30 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Wed, 17 Apr 2024 20:55:15 +0200 Subject: [PATCH 017/133] Translated using Weblate (Chinese (Traditional)) Currently translated at 100.0% (166 of 166 strings) Added translation using Weblate (Chinese (Traditional)) Co-authored-by: Hosted Weblate Co-authored-by: hugoalh Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/zh_Hant/ Translation: PairDrop/pairdrop-spa --- public/lang/zh-Hant.json | 184 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 public/lang/zh-Hant.json diff --git a/public/lang/zh-Hant.json b/public/lang/zh-Hant.json new file mode 100644 index 0000000..8733e29 --- /dev/null +++ b/public/lang/zh-Hant.json @@ -0,0 +1,184 @@ +{ + "header": { + "language-selector_title": "設定語言", + "theme-auto_title": "自動使用系統主題", + "cancel-share-mode": "取消", + "edit-share-mode": "編輯", + "expand_title": "展開標題按鈕列", + "about_title": "關於 PairDrop", + "about_aria-label": "開啟關於 PairDrop", + "theme-dark_title": "總是使用深色主題", + "notification_title": "啟用通知", + "install_title": "安裝 PairDrop", + "pair-device_title": "永久配對你的裝置", + "edit-paired-devices_title": "編輯已配對的裝置", + "join-public-room_title": "暫時加入公共房間", + "theme-light_title": "總是使用淺色主題" + }, + "instructions": { + "no-peers_data-drop-bg": "釋放以選擇接收者", + "no-peers-subtitle": "配對裝置或加入一個公共房間以便在其他網路上可見", + "x-instructions_mobile": "輕觸以發送檔案或輕觸並按住以發送一則訊息", + "x-instructions_data-drop-bg": "釋放以選擇接收者", + "x-instructions-share-mode_desktop": "點擊以發送 {{descriptor}}", + "activate-share-mode-and-other-file": "和另外 1 個檔案", + "activate-share-mode-and-other-files-plural": "和另外 {{count}} 個檔案", + "activate-share-mode-shared-text": "已分享的文字", + "activate-share-mode-shared-file": "已分享的檔案", + "webrtc-requirement": "要使用此 PairDrop 實例,必須啟用 WebRTC!", + "no-peers-title": "在其他裝置上開啟 PairDrop 以傳送檔案", + "x-instructions_desktop": "點擊以發送檔案或右鍵點擊以發送一則訊息", + "x-instructions_data-drop-peer": "釋放以發送到此裝置", + "x-instructions-share-mode_mobile": "輕觸以發送 {{descriptor}}", + "activate-share-mode-base": "在其他裝置上開啟 PairDrop 以傳送", + "activate-share-mode-shared-files-plural": "{{count}} 個已分享的檔案" + }, + "footer": { + "display-name_data-placeholder": "正在載入中…", + "known-as": "此裝置名稱為:", + "display-name_title": "編輯此裝置名稱並儲存", + "discovery": "可見於:", + "on-this-network": "在這個網路上", + "paired-devices_title": "無論在任何網路,已配對的裝置都是隨時可見。", + "public-room-devices": "在房間 {{roomId}} 中", + "traffic": "流量將會", + "on-this-network_title": "在這個網路上的每個人都可以見到你。", + "paired-devices": "已配對的裝置", + "public-room-devices_title": "無論在任何網路,此公共房間中的裝置都是隨時可見。", + "routed": "途經伺服器", + "webrtc": "如果無法使用 WebRTC。" + }, + "dialogs": { + "pair-devices-title": "永久配對裝置", + "scan-qr-code": "或掃描 QR 圖碼。", + "input-key-on-this-device": "在另一台裝置上輸入此密鑰", + "temporary-public-room-title": "臨時公共房間", + "input-room-id-on-another-device": "在另一台裝置上輸入此房間編號", + "enter-room-id-from-another-device": "在此輸入房間編號以加入房間。", + "hr-or": "或者", + "pair": "配對", + "cancel": "取消", + "paired-devices-wrapper_data-empty": "沒有已配對的裝置。", + "auto-accept-instructions-1": "啟用", + "auto-accept": "自動接收", + "auto-accept-instructions-2": "以自動接受從該裝置發送的所有檔案。", + "close": "關閉", + "join": "加入", + "send": "發送", + "receive-text-title": "收到訊息", + "base64-tap-to-paste": "輕觸此處以分享 {{type}}", + "base64-text": "文字", + "base64-files": "檔案", + "file-other-description-file": "和另外 1 個檔案", + "file-other-description-image-plural": "和另外 {{count}} 張圖片", + "file-other-description-file-plural": "和另外 {{count}} 個檔案", + "title-image": "圖片", + "title-file": "檔案", + "title-image-plural": "圖片", + "title-file-plural": "檔案", + "receive-title": "收到 {{descriptor}}", + "download-again": "再次下載", + "language-selector-title": "設定語言", + "system-language": "使用系統語言", + "public-room-qr-code_title": "點擊以複製連結到公共房間", + "pair-devices-qr-code_title": "點擊以複製連結以配對此裝置", + "approve": "批准", + "share-text-title": "分享文字訊息", + "share-text-subtitle": "發送前編輯訊息:", + "share-text-checkbox": "分享文字時總是顯示此對話框", + "enter-key-from-another-device": "在此輸入另一台裝置的密鑰。", + "edit-paired-devices-title": "編輯已配對的裝置", + "unpair": "取消配對", + "paired-device-removed": "已刪除已配對的裝置。", + "leave": "離開", + "accept": "接受", + "would-like-to-share": "想要分享", + "decline": "拒絕", + "has-sent": "已發送:", + "share": "分享", + "message_title": "輸入要傳送的訊息", + "download": "下載", + "send-message-to": "發送至:", + "message_placeholder": "文字", + "copy": "複製", + "send-message-title": "發送訊息", + "base64-title-files": "分享檔案", + "base64-title-text": "分享文字", + "base64-processing": "正在處理中…", + "base64-paste-to-send": "將剪貼簿貼到此處以分享 {{type}}", + "file-other-description-image": "和另外 1 張圖片", + "close-toast_title": "關閉通知" + }, + "about": { + "claim": "跨裝置傳輸檔案的最簡單方法", + "github_title": "GitHub 上的 PairDrop", + "tweet_title": "發佈關於 PairDrop 的推文", + "mastodon_title": "在 Mastodon 上撰寫有關 PairDrop 的文章", + "close-about_aria-label": "關閉關於 PairDrop", + "buy-me-a-coffee_title": "給我買一杯咖啡吧!", + "bluesky_title": "在 Bluesky 上關注我們", + "custom_title": "關注我們", + "privacypolicy_title": "開啟我們的隱私權政策", + "faq_title": "常見問題" + }, + "notifications": { + "display-name-changed-permanently": "裝置名稱已更改並儲存", + "display-name-changed-temporarily": "裝置名稱已更改並只限於此會話", + "display-name-random-again": "裝置名稱已再次隨機生成", + "download-successful": "{{descriptor}} 已下載", + "pairing-success": "裝置已配對", + "pairing-not-persistent": "已配對的裝置不是永久的", + "pairing-key-invalid": "無效的密鑰", + "pairing-key-invalidated": "密鑰 {{key}} 已失效", + "pairing-cleared": "所有裝置均已解除配對", + "public-room-id-invalid": "無效的房間編號", + "public-room-left": "已離開公共房間 {{publicRoomId}}", + "copied-to-clipboard": "已複製到剪貼簿", + "pair-url-copied-to-clipboard": "已將與此裝置配對的連結複製到剪貼簿", + "room-url-copied-to-clipboard": "已將公共房間的連結複製到剪貼簿", + "copied-to-clipboard-error": "無法複製。請手動複製。", + "text-content-incorrect": "文字內容不正確", + "file-content-incorrect": "檔案內容不正確", + "notifications-enabled": "已啟用通知", + "notifications-permissions-error": "由於使用者多次取消權限請求提示,通知權限已被封鎖。這可以在頁面資訊中重置,點擊網址欄旁邊的鎖定圖示以存取頁面資訊。", + "link-received": "收到 {{name}} 的連結—點擊以開啟", + "message-received": "收到 {{name}} 的訊息—點擊以複製", + "click-to-show": "點擊以顯示", + "copied-text": "已將文字複製到剪貼簿", + "copied-text-error": "無法複製到剪貼簿。請手動複製!", + "offline": "已離線", + "online": "已重新在線", + "connected": "已連接", + "online-requirement-pairing": "你需要在線才能配對裝置", + "online-requirement-public-room": "你需要在線才能創建公共房間", + "connecting": "正在連接中…", + "files-incorrect": "檔案不正確", + "file-transfer-completed": "檔案傳輸已完成", + "ios-memory-limit": "向 iOS 發送檔案每次只能最大 200 MB", + "message-transfer-completed": "訊息傳輸已完成", + "unfinished-transfers-warning": "還有未完成的傳輸。你確定要關閉 PairDrop 嗎?", + "rate-limit-join-key": "已達到速率限制。請等待 10 秒鐘,然後再試一次。", + "selected-peer-left": "選定的對象已離開", + "pairing-tabs-error": "將兩個網頁瀏覽器分頁進行配對是不可能的", + "clipboard-content-incorrect": "剪貼簿內容不正確", + "click-to-download": "點擊以下載", + "request-title": "{{name}} 想要發送 {{count}} 個 {{descriptor}}" + }, + "document-titles": { + "file-received": "檔案已收到", + "file-received-plural": "已收到 {{count}} 個檔案", + "file-transfer-requested": "已請求檔案傳輸", + "image-transfer-requested": "已請求圖片傳輸", + "message-received": "已收到訊息", + "message-received-plural": "已收到 {{count}} 條訊息" + }, + "peer-ui": { + "click-to-send-share-mode": "點擊以發送 {{descriptor}}", + "click-to-send": "點擊以發送檔案或右鍵點擊以發送一則訊息", + "preparing": "正在準備中…", + "waiting": "正在等待中…", + "processing": "正在處理中…", + "transferring": "正在傳輸中…", + "connection-hash": "若要驗證端對端加密的安全性,請在兩台裝置上比較此安全編號" + } +} From 5e79ef0d9f551493793641f9a714955d9a42a128 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Wed, 17 Apr 2024 20:55:15 +0200 Subject: [PATCH 018/133] Added translation using Weblate (Yue (Traditional)) Co-authored-by: Hosted Weblate Co-authored-by: hugoalh --- public/lang/yue-Hant.json | 1 + 1 file changed, 1 insertion(+) create mode 100644 public/lang/yue-Hant.json diff --git a/public/lang/yue-Hant.json b/public/lang/yue-Hant.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/public/lang/yue-Hant.json @@ -0,0 +1 @@ +{} From 05827b12ca1c4695435d50d1fe50bb9d27290436 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Wed, 17 Apr 2024 21:33:10 +0200 Subject: [PATCH 019/133] Rename new Chinese translation files to match their browser language strings --- public/lang/{yue-Hant.json => zh-HK.json} | 0 public/lang/{zh-Hant.json => zh-TW.json} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename public/lang/{yue-Hant.json => zh-HK.json} (100%) rename public/lang/{zh-Hant.json => zh-TW.json} (100%) diff --git a/public/lang/yue-Hant.json b/public/lang/zh-HK.json similarity index 100% rename from public/lang/yue-Hant.json rename to public/lang/zh-HK.json diff --git a/public/lang/zh-Hant.json b/public/lang/zh-TW.json similarity index 100% rename from public/lang/zh-Hant.json rename to public/lang/zh-TW.json From c8484ab104959025a0c431ee87c6ebd2870832f7 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Thu, 18 Apr 2024 16:16:36 +0200 Subject: [PATCH 020/133] Enable Hungarian, Polish, and Traditional Chinese Translations --- public/index.html | 17 ++++++++++++++++- public/scripts/localization.js | 2 +- public/service-worker.js | 5 ++++- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/public/index.html b/public/index.html index 15922f3..f7df927 100644 --- a/public/index.html +++ b/public/index.html @@ -230,6 +230,11 @@   -   (Kannada) + + + + + + + + + - From 43c071b37fca336bb1001e9ca5577ba4bfdda0d8 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Tue, 11 Feb 2025 12:14:58 +0100 Subject: [PATCH 085/133] Enable Bulgarian, Estonian, Basque, Persian, Norwegian Nynorsk, Slovak, Tamil, Hant Script, and Korean translations --- public/index.html | 45 ++++++++++++++++++++++++++++++++++ public/scripts/localization.js | 5 +++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/public/index.html b/public/index.html index 8a95679..c50dbe7 100644 --- a/public/index.html +++ b/public/index.html @@ -202,6 +202,11 @@   -   (Norwegian Bokmål) + + + + + + + + +
diff --git a/public/scripts/localization.js b/public/scripts/localization.js index ca07a93..454f84d 100644 --- a/public/scripts/localization.js +++ b/public/scripts/localization.js @@ -3,7 +3,10 @@ class Localization { Localization.$htmlRoot = document.querySelector('html'); Localization.defaultLocale = "en"; - Localization.supportedLocales = ["ar", "be", "ca", "cs", "da", "de", "en", "es", "fr", "he", "hu", "id", "it", "ja", "kn", "nb", "nl", "pl", "pt-BR", "ro", "ru", "tr", "uk", "zh-CN", "zh-TW"]; + Localization.supportedLocales = [ + "ar", "be", "bg", "ca", "cs", "da", "de", "en", "es", "et", "eu", "fa", "fr", "he", "hu", "id", "it", "ja", + "kn", "ko", "nb", "nn", "nl", "pl", "pt-BR", "ro", "ru", "sk", "ta", "tr", "uk", "zh-CN", "zh-HK", "zh-TW" + ]; Localization.supportedLocalesRtl = ["ar", "he"]; Localization.translations = {}; From 8f8708c5fbc6c9a5704e18dfd868f9c1fe34e4b6 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Tue, 11 Feb 2025 14:33:32 +0100 Subject: [PATCH 086/133] Fix loading of default/backup translations --- public/scripts/localization.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/public/scripts/localization.js b/public/scripts/localization.js index 454f84d..ec915a5 100644 --- a/public/scripts/localization.js +++ b/public/scripts/localization.js @@ -51,13 +51,14 @@ class Localization { } async setInitialTranslation() { + await Localization.fetchDefaultTranslations(); await Localization.setTranslation(Localization.initialLocale) } static async setTranslation(locale) { if (!locale) locale = Localization.systemLocale; - await Localization.setLocale(locale) + await Localization.fetchTranslations(locale) await Localization.translatePage(); if (Localization.localeIsRtl(locale)) { @@ -78,10 +79,12 @@ class Localization { Events.fire("translation-loaded"); } - static async setLocale(newLocale) { - if (newLocale === Localization.locale) return false; + static async fetchDefaultTranslations() { + Localization.translationsDefaultLocale = await Localization.fetchTranslationsFor(Localization.defaultLocale); + } - Localization.defaultTranslations = await Localization.fetchTranslationsFor(Localization.defaultLocale); + static async fetchTranslations(newLocale) { + if (newLocale === Localization.locale) return false; const newTranslations = await Localization.fetchTranslationsFor(newLocale); From 14bfc1948a7b1b236d4ccc5c99940e8cd65b065b Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Tue, 11 Feb 2025 14:42:41 +0100 Subject: [PATCH 087/133] Update node dependencies --- package-lock.json | 325 ++++++++++++++++++++++++++++------------------ 1 file changed, 196 insertions(+), 129 deletions(-) diff --git a/package-lock.json b/package-lock.json index 42a0b80..9673a7d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37,9 +37,9 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, "node_modules/body-parser": { - "version": "1.20.2", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", - "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -49,7 +49,7 @@ "http-errors": "2.0.0", "iconv-lite": "0.4.24", "on-finished": "2.4.1", - "qs": "6.11.0", + "qs": "6.13.0", "raw-body": "2.5.2", "type-is": "~1.6.18", "unpipe": "1.0.0" @@ -67,16 +67,25 @@ "node": ">= 0.8" } }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "node_modules/call-bind-apply-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", + "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", "dependencies": { - "es-define-property": "^1.0.0", "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", + "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "get-intrinsic": "^1.2.6" }, "engines": { "node": ">= 0.4" @@ -105,9 +114,9 @@ } }, "node_modules/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "engines": { "node": ">= 0.6" } @@ -125,22 +134,6 @@ "ms": "2.0.0" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -158,26 +151,36 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/encodeurl": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", - "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "engines": { "node": ">= 0.8" } }, "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "engines": { "node": ">= 0.4" } @@ -190,6 +193,17 @@ "node": ">= 0.4" } }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -204,36 +218,36 @@ } }, "node_modules/express": { - "version": "4.19.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", - "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.2", + "body-parser": "1.20.3", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.6.0", + "cookie": "0.7.1", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "1.2.0", + "finalhandler": "1.3.1", "fresh": "0.5.2", "http-errors": "2.0.0", - "merge-descriptors": "1.0.1", + "merge-descriptors": "1.0.3", "methods": "~1.1.2", "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "0.1.7", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", - "qs": "6.11.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "0.18.0", - "serve-static": "1.15.0", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", "statuses": "2.0.1", "type-is": "~1.6.18", @@ -242,6 +256,10 @@ }, "engines": { "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" } }, "node_modules/express-rate-limit": { @@ -259,12 +277,12 @@ } }, "node_modules/finalhandler": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", - "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "dependencies": { "debug": "2.6.9", - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "on-finished": "2.4.1", "parseurl": "~1.3.3", @@ -300,15 +318,20 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", + "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" + "get-proto": "^1.0.0", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -317,32 +340,22 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gopd": { + "node_modules/get-proto": { "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "dependencies": { - "get-intrinsic": "^1.1.3" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 0.4" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "engines": { "node": ">= 0.4" }, @@ -351,9 +364,9 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "engines": { "node": ">= 0.4" }, @@ -411,6 +424,14 @@ "node": ">= 0.10" } }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -420,9 +441,12 @@ } }, "node_modules/merge-descriptors": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/methods": { "version": "1.1.2", @@ -476,9 +500,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", - "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "engines": { "node": ">= 0.4" }, @@ -506,9 +530,9 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==" }, "node_modules/proxy-addr": { "version": "2.0.7", @@ -523,11 +547,11 @@ } }, "node_modules/qs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", - "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dependencies": { - "side-channel": "^1.0.4" + "side-channel": "^1.0.6" }, "engines": { "node": ">=0.6" @@ -583,9 +607,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/send": { - "version": "0.18.0", - "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", - "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -605,55 +629,98 @@ "node": ">= 0.8.0" } }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" }, "node_modules/serve-static": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", - "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", "dependencies": { - "encodeurl": "~1.0.2", + "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "parseurl": "~1.3.3", - "send": "0.18.0" + "send": "0.19.0" }, "engines": { "node": ">= 0.8.0" } }, - "node_modules/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", "dependencies": { - "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" }, "engines": { "node": ">= 0.4" From 659b53b5faf6c99e076992cc61a6890c56a60f54 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Tue, 11 Feb 2025 14:52:44 +0100 Subject: [PATCH 088/133] Increase version to v1.10.11 ## Enhancements - Prevent referrer in created links in message ## Fixes - Prevent wrong `start_url` when installing PairDrop PWA from sub path (#329) - Hotfix: Disable thumbnail creation for HEIC/HEIF files until PR #350 is merged (hotfix for #336) ## Languages - New Language Bulgarian - New Language Estonian - New Language Basque - New Language Persian - New Language Norwegian Nynorsk - New Language Slovak - New Language Tamil - New Language Hant Script - New Language Korean - Translations updates from Hosted Weblate (Indonesian, Arabic, Italian, Czech, Japanese, Ukrainian, Russian, German, Portuguese (Brazil)) --- .github/ISSUE_TEMPLATE/bug-report.md | 4 ++-- docs/how-to.md | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- public/index.html | 2 +- public/service-worker.js | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index 8039a04..419d837 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -36,7 +36,7 @@ If applicable, add screenshots to help explain your problem. **Bug occurs on official PairDrop instance https://pairdrop.net/** No | Yes -Version: v1.10.10 +Version: v1.10.11 **Bug occurs on self-hosted PairDrop instance** No | Yes @@ -44,7 +44,7 @@ No | Yes **Self-Hosted Setup** Proxy: Nginx | Apache2 Deployment: docker run | docker compose | npm run start:prod -Version: v1.10.10 +Version: v1.10.11 **Additional context** Add any other context about the problem here. diff --git a/docs/how-to.md b/docs/how-to.md index 6513b13..7d899db 100644 --- a/docs/how-to.md +++ b/docs/how-to.md @@ -45,11 +45,11 @@ This pairdrop-cli version was released alongside v1.10.4 #### Linux / Mac 1. Download the latest _pairdrop-cli.zip_ from the [releases page](https://github.com/schlagmichdoch/PairDrop/releases) ```shell - wget "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.10.10/pairdrop-cli.zip" + wget "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.10.11/pairdrop-cli.zip" ``` or ```shell - curl -LO "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.10.10/pairdrop-cli.zip" + curl -LO "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.10.11/pairdrop-cli.zip" ``` 2. Unzip the archive to a folder of your choice e.g. `/usr/share/pairdrop-cli/` ```shell diff --git a/package-lock.json b/package-lock.json index 9673a7d..8812cb9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pairdrop", - "version": "1.10.10", + "version": "1.10.11", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pairdrop", - "version": "1.10.10", + "version": "1.10.11", "license": "ISC", "dependencies": { "express": "^4.18.2", diff --git a/package.json b/package.json index 5ed2324..f4fd629 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pairdrop", - "version": "1.10.10", + "version": "1.10.11-", "type": "module", "description": "", "main": "server/index.js", diff --git a/public/index.html b/public/index.html index c50dbe7..5dec40a 100644 --- a/public/index.html +++ b/public/index.html @@ -667,7 +667,7 @@

PairDrop

-
v1.10.10
+
v1.10.11
diff --git a/public/service-worker.js b/public/service-worker.js index c247828..c6420fe 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -1,4 +1,4 @@ -const cacheVersion = 'v1.10.10'; +const cacheVersion = 'v1.10.11'; const cacheTitle = `pairdrop-cache-${cacheVersion}`; const forceFetch = false; // FOR DEVELOPMENT: Set to true to always update assets instead of using cached versions const relativePathsToCache = [ From 44c0f3dbaadb9f4925fa4d410057bd772e7e06cb Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Mon, 11 Nov 2024 15:37:04 +0100 Subject: [PATCH 089/133] Check for BroadcastChannel availability before instantiating it --- public/scripts/browser-tabs-connector.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/public/scripts/browser-tabs-connector.js b/public/scripts/browser-tabs-connector.js index da9c43e..2ce99af 100644 --- a/public/scripts/browser-tabs-connector.js +++ b/public/scripts/browser-tabs-connector.js @@ -1,5 +1,7 @@ class BrowserTabsConnector { constructor() { + if (!('BroadcastChannel' in window)) return; + this.bc = new BroadcastChannel('pairdrop'); this.bc.addEventListener('message', e => this._onMessage(e)); Events.on('broadcast-send', e => this._broadcastSend(e.detail)); From c52eeda3ffbfcfa5c0e1a0c6601f7522944cfefe Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Wed, 12 Feb 2025 00:35:24 +0100 Subject: [PATCH 090/133] Add BrowserStack to README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9fd70f1..3400704 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,7 @@ Connect to others in complex network situations, or over the Internet. * [NoSleep](https://github.com/richtr/NoSleep.js) display sleep, add wake lock ([MIT](licenses/MIT-NoSleep)) * [heic2any](https://github.com/alexcorvi/heic2any) HEIC/HEIF to PNG/GIF/JPEG ([MIT](licenses/MIT-heic2any)) * [Weblate](https://weblate.org/) web-based localization tool +* [BrowserStack](https://www.browserstack.com/) This project is tested with BrowserStack [FAQ](docs/faq.md) From 940da7948cb9957f0614fe62e4ea39939ebf8314 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Thu, 13 Feb 2025 10:24:27 +0100 Subject: [PATCH 091/133] Stop usage of public class fields in order to support Safari 13.1 --- public/scripts/ui.js | 39 +++++++++++++++++---------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/public/scripts/ui.js b/public/scripts/ui.js index 873e612..93d4ae2 100644 --- a/public/scripts/ui.js +++ b/public/scripts/ui.js @@ -18,11 +18,12 @@ class PeersUI { this.peers = {}; - this.shareMode = {}; - this.shareMode.active = false; - this.shareMode.descriptor = ""; - this.shareMode.files = []; - this.shareMode.text = ""; + this.shareMode = { + active: false, + descriptor: "", + files: [], + text: "" + } Events.on('peer-joined', e => this._onPeerJoined(e.detail)); Events.on('peer-added', _ => this._evaluateOverflowingPeers()); @@ -394,12 +395,6 @@ class PeersUI { class PeerUI { - static _badgeClassNames = ["badge-room-ip", "badge-room-secret", "badge-room-public-id"]; - static _shareMode = { - active: false, - descriptor: "" - }; - constructor(peer, connectionHash, shareMode) { this.$xInstructions = $$('x-instructions'); this.$xPeers = $$('x-peers'); @@ -409,7 +404,7 @@ class PeerUI { `${connectionHash.substring(0, 4)} ${connectionHash.substring(4, 8)} ${connectionHash.substring(8, 12)} ${connectionHash.substring(12, 16)}`; // This is needed if the ShareMode is started BEFORE the PeerUI is drawn. - PeerUI._shareMode = shareMode; + this._shareMode = shareMode; this._initDom(); @@ -421,8 +416,8 @@ class PeerUI { } html() { - let title= PeerUI._shareMode.active - ? Localization.getTranslation("peer-ui.click-to-send-share-mode", null, {descriptor: PeerUI._shareMode.descriptor}) + let title= this._shareMode.active + ? Localization.getTranslation("peer-ui.click-to-send-share-mode", null, {descriptor: this._shareMode.descriptor}) : Localization.getTranslation("peer-ui.click-to-send"); this.$el.innerHTML = ` @@ -485,8 +480,8 @@ class PeerUI { _onShareModeChanged(active = false, descriptor = "") { // This is needed if the ShareMode is started AFTER the PeerUI is drawn. - PeerUI._shareMode.active = active; - PeerUI._shareMode.descriptor = descriptor; + this._shareMode.active = active; + this._shareMode.descriptor = descriptor; this._evaluateShareMode(); this._bindListeners(); @@ -494,12 +489,12 @@ class PeerUI { _evaluateShareMode() { let title; - if (!PeerUI._shareMode.active) { + if (!this._shareMode.active) { title = Localization.getTranslation("peer-ui.click-to-send"); this.$input.removeAttribute('disabled'); } else { - title = Localization.getTranslation("peer-ui.click-to-send-share-mode", null, {descriptor: PeerUI._shareMode.descriptor}); + title = Localization.getTranslation("peer-ui.click-to-send-share-mode", null, {descriptor: this._shareMode.descriptor}); this.$input.setAttribute('disabled', true); } this.$label.setAttribute('title', title); @@ -520,7 +515,7 @@ class PeerUI { } _bindListeners() { - if(!PeerUI._shareMode.active) { + if(!this._shareMode.active) { // Remove Events Share mode this.$el.removeEventListener('pointerdown', this._callbackPointerDown); @@ -636,7 +631,7 @@ class PeerUI { } _onDrop(e) { - if (PeerUI._shareMode.active || Dialog.anyDialogShown()) return; + if (this._shareMode.active || Dialog.anyDialogShown()) return; e.preventDefault(); @@ -1974,7 +1969,7 @@ class SendTextDialog extends Dialog { _onRecipient(peerId, deviceName) { this.correspondingPeerId = peerId; this.$peerDisplayName.innerText = deviceName; - this.$peerDisplayName.classList.remove(...PeerUI._badgeClassNames); + this.$peerDisplayName.classList.remove("badge-room-ip", "badge-room-secret", "badge-room-public-id"); this.$peerDisplayName.classList.add($(peerId).ui._badgeClassName()); this.show(); @@ -2056,7 +2051,7 @@ class ReceiveTextDialog extends Dialog { _showReceiveTextDialog(text, peerId) { this.$displayName.innerText = $(peerId).ui._displayName(); - this.$displayName.classList.remove(...PeerUI._badgeClassNames); + this.$displayName.classList.remove("badge-room-ip", "badge-room-secret", "badge-room-public-id"); this.$displayName.classList.add($(peerId).ui._badgeClassName()); this.$text.innerText = text; From f7fe303fa768f59d04906c17d76fa0b6ffb8cfe4 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Thu, 13 Feb 2025 11:39:10 +0100 Subject: [PATCH 092/133] Fix background css for clients iOS < 13.1 --- public/styles/styles-main.css | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/public/styles/styles-main.css b/public/styles/styles-main.css index 9401d45..cff0d1d 100644 --- a/public/styles/styles-main.css +++ b/public/styles/styles-main.css @@ -696,7 +696,6 @@ button::-moz-focus-inner { /* Info Animation */ - #about { color: white; z-index: 32; @@ -752,9 +751,11 @@ button::-moz-focus-inner { height: var(--size); z-index: -1; background: var(--primary-color); - background-image: radial-gradient(circle at calc(50% - 36px), var(--accent-color) 0%, color-mix(in srgb, var(--accent-color) 40%, black) 80%); + background-image: radial-gradient(circle at calc(50% - 36px), var(--primary-color) 0%, black 80%); --crop-size: 0px; clip-path: circle(var(--crop-size)); + /* For clients < iOS 13.1 */ + -webkit-clip-path: circle(var(--crop-size)); } html:not([dir="rtl"]) #about x-background { From ec520248b82a74a17f25a832b45f1e32fccb8ec3 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Thu, 13 Feb 2025 12:53:04 +0100 Subject: [PATCH 093/133] Remove duplicate instruction --- public/scripts/ui.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/public/scripts/ui.js b/public/scripts/ui.js index 93d4ae2..e1887cb 100644 --- a/public/scripts/ui.js +++ b/public/scripts/ui.js @@ -278,8 +278,6 @@ class PeersUI { descriptorInstructions = Localization.getTranslation("instructions.activate-share-mode-shared-file"); } - files = await mime.addMissingMimeTypesToFiles(files); - if (files[0].type.split('/')[0] === 'image') { try { let imageUrl = await getThumbnailAsDataUrl(files[0], 80, null, 0.9); From 351e7d42c9eece9ceaffcb64114546527725fa8a Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Thu, 13 Feb 2025 12:52:33 +0100 Subject: [PATCH 094/133] Fix share mode by converting FileList to Array --- public/scripts/network.js | 2 +- public/scripts/ui.js | 16 +++++++++++----- public/scripts/util.js | 10 +++++----- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/public/scripts/network.js b/public/scripts/network.js index 9128442..c92befc 100644 --- a/public/scripts/network.js +++ b/public/scripts/network.js @@ -1082,7 +1082,7 @@ class PeersManager { } async _onFilesSelected(message) { - let files = await mime.addMissingMimeTypesToFiles(message.files); + let files = mime.addMissingMimeTypesToFiles(message.files); await this.peers[message.to].requestFileTransfer(files); } diff --git a/public/scripts/ui.js b/public/scripts/ui.js index e1887cb..c988db7 100644 --- a/public/scripts/ui.js +++ b/public/scripts/ui.js @@ -179,10 +179,13 @@ class PeersUI { this._onDragEnd(); - if ($$('x-peer') || !$$('x-peer').contains(e.target)) return; // dropped on peer + if ($$('x-peer') && $$('x-peer').contains(e.target)) return; // dropped on peer - const files = e.dataTransfer.files; - const text = e.dataTransfer.getData("text"); + let files = e.dataTransfer.files; + let text = e.dataTransfer.getData("text"); + + // convert FileList to Array + files = [...files]; if (files.length > 0) { Events.fire('activate-share-mode', { @@ -215,8 +218,11 @@ class PeersUI { if (this.shareMode.active || Dialog.anyDialogShown()) return; e.preventDefault() - const files = e.clipboardData.files; - const text = e.clipboardData.getData("Text"); + let files = e.clipboardData.files; + let text = e.clipboardData.getData("Text"); + + // convert FileList to Array + files = [...files]; if (files.length > 0) { Events.fire('activate-share-mode', {files: files}); diff --git a/public/scripts/util.js b/public/scripts/util.js index 7d6c54a..08a790f 100644 --- a/public/scripts/util.js +++ b/public/scripts/util.js @@ -396,20 +396,20 @@ const mime = (() => { } return { - async guessMimeByFilename(filename) { + guessMimeByFilename(filename) { const split = filename.split('.'); if (split.length === 1) { // Filename does not include suffix - return ""; + return false; } const suffix = split[split.length - 1].toLowerCase(); - return suffixToMimeMap[suffix] || ""; + return suffixToMimeMap[suffix]; }, - async addMissingMimeTypesToFiles(files) { + addMissingMimeTypesToFiles(files) { // if filetype is empty guess via suffix otherwise leave unchanged for (let i = 0; i < files.length; i++) { if (!files[i].type) { - files[i] = new File([files[i]], files[i].name, {type: await mime.guessMimeByFilename(files[i].name) || ""}); + files[i] = new File([files[i]], files[i].name, {type: mime.guessMimeByFilename(files[i].name) || ""}); } } return files; From efc360e1063ae7dde1424b5934464f9a4f91dd34 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Thu, 13 Feb 2025 12:53:47 +0100 Subject: [PATCH 095/133] Remove text selection prevention to enable pasting for Firefox users --- public/styles/styles-main.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/public/styles/styles-main.css b/public/styles/styles-main.css index cff0d1d..5cff395 100644 --- a/public/styles/styles-main.css +++ b/public/styles/styles-main.css @@ -11,10 +11,6 @@ body { overflow-x: hidden; overscroll-behavior: none; overflow-y: hidden; - /* Only allow selection on message and pair key */ - -webkit-user-select: none; - -moz-user-select: none; - user-select: none; transition: color 300ms; } From 629328c2f614b4077bdc58d5839ccdc6979618a9 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Thu, 13 Feb 2025 20:07:25 +0100 Subject: [PATCH 096/133] Use css instead of JS to detect offset on high viewports --- public/scripts/ui-main.js | 1 - public/styles/styles-main.css | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/public/scripts/ui-main.js b/public/scripts/ui-main.js index bbdece4..3289ee7 100644 --- a/public/scripts/ui-main.js +++ b/public/scripts/ui-main.js @@ -357,7 +357,6 @@ class BackgroundCanvas { 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 diff --git a/public/styles/styles-main.css b/public/styles/styles-main.css index 5cff395..c36634a 100644 --- a/public/styles/styles-main.css +++ b/public/styles/styles-main.css @@ -899,7 +899,7 @@ x-peers:empty~x-instructions { @media screen and (min-height: 800px) { footer { - margin-bottom: 16px; + padding-bottom: 10px; } } From 8a833cd69dae86519d60b11ee5e094f232772c31 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Thu, 13 Feb 2025 20:07:38 +0100 Subject: [PATCH 097/133] Make PWA standalone --- public/manifest.json | 2 +- public/scripts/main.js | 2 +- public/styles/styles-main.css | 7 +++++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/public/manifest.json b/public/manifest.json index 5198d81..edcf69a 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -26,7 +26,7 @@ } ], "background_color": "#efefef", - "display": "minimal-ui", + "display": "standalone", "theme_color": "#3367d6", "screenshots" : [ { diff --git a/public/scripts/main.js b/public/scripts/main.js index 8960ed2..9929627 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -81,7 +81,7 @@ class PairDrop { } onPwaInstallable(e) { - if (!window.matchMedia('(display-mode: minimal-ui)').matches) { + if (!window.matchMedia('(display-mode: standalone)').matches) { // only display install btn when not installed this.$headerInstallBtn.removeAttribute('hidden'); this.$headerInstallBtn.addEventListener('click', () => { diff --git a/public/styles/styles-main.css b/public/styles/styles-main.css index c36634a..bbf3ddf 100644 --- a/public/styles/styles-main.css +++ b/public/styles/styles-main.css @@ -909,6 +909,13 @@ x-peers:empty~x-instructions { } } +/* PWA Standalone styles */ +@media all and (display-mode: standalone) { + footer { + padding-bottom: 34px; + } +} + /* Constants */ :root { From 82b329fea84416ab4c6d0208e6a5b758698d9828 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Fri, 14 Feb 2025 15:36:35 +0100 Subject: [PATCH 098/133] Fix padding of auto-accept instruction --- public/index.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/index.html b/public/index.html index 5dec40a..bd391e7 100644 --- a/public/index.html +++ b/public/index.html @@ -416,12 +416,12 @@

-
-

+

+
-

+
From dabfe581248edbc49ff0abd0fdad9c28d8e658bd Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Fri, 14 Feb 2025 15:47:17 +0100 Subject: [PATCH 099/133] Fix word-break of base64zip button on mobile --- public/styles/styles-main.css | 1 - 1 file changed, 1 deletion(-) diff --git a/public/styles/styles-main.css b/public/styles/styles-main.css index 5cff395..8be401e 100644 --- a/public/styles/styles-main.css +++ b/public/styles/styles-main.css @@ -587,7 +587,6 @@ x-dialog:not([show]) x-background { font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; - white-space: nowrap; cursor: pointer; user-select: none; background: inherit; From 02c95dde9d411a585c5473991cbb1ce7fc1eeef6 Mon Sep 17 00:00:00 2001 From: Chris Lovett Date: Fri, 14 Feb 2025 10:17:10 -0500 Subject: [PATCH 100/133] Updated Twitter (X) icon and URL --- public/index.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/public/index.html b/public/index.html index 5dec40a..748e275 100644 --- a/public/index.html +++ b/public/index.html @@ -681,9 +681,9 @@ - + - + ${url}`; - return `${whitespaceOrSpecial}${linkNodePlaceholder}`; - } + if (!isUrlValid(link)) { // link is not valid -> do not replace return match; - }); + } + + // link is valid -> replace with link node placeholder + // find linkNodePlaceholder that is not yet present in text node + m++; + while (occP.includes(`${p}${m}`)) { + m++; + } + let linkNodePlaceholder = `${p}${m}`; + + // add linkNodePlaceholder to text node and save a reference to linkNodes object + linkNodes[linkNodePlaceholder] = `${url}`; + return `${whitespace}${linkNodePlaceholder}`; + } + + text = text.replace(rgxUrlAll, replaceMatchWithPlaceholder); + $textShadow.innerText = text.replace(rgxMailAll, replaceMatchWithPlaceholder); this.$text.innerHTML = $textShadow.innerHTML.replace(pRgx, diff --git a/public/scripts/util.js b/public/scripts/util.js index 08a790f..1dcc388 100644 --- a/public/scripts/util.js +++ b/public/scripts/util.js @@ -590,7 +590,7 @@ async function decodeBase64Text(base64) { function isUrlValid(url) { try { - let urlObj = new URL(url); + new URL(url); return true; } catch (e) { From 8a3c60d3a677d5dcd9b28d0b91f4de61be29db11 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Fri, 14 Feb 2025 20:54:15 +0100 Subject: [PATCH 103/133] Bring back optimized background animation --- public/scripts/ui-main.js | 183 +++++++++++++++++++++++++++----------- public/scripts/ui.js | 10 +++ 2 files changed, 140 insertions(+), 53 deletions(-) diff --git a/public/scripts/ui-main.js b/public/scripts/ui-main.js index bbdece4..682dbe3 100644 --- a/public/scripts/ui-main.js +++ b/public/scripts/ui-main.js @@ -333,65 +333,142 @@ class FooterUI { class BackgroundCanvas { constructor() { - this.c = $$('canvas'); - this.cCtx = this.c.getContext('2d'); - this.$footer = $$('footer'); + this.canvas = $$('canvas'); + this.initAnimation(); + } + + initAnimation() { + let c = this.canvas; + let cCtx = c.getContext('2d'); + let $footer = $$('footer'); + + let x0, y0, w, h, dw, offset, baseColor, baseOpacity; + + let offscreenCanvases; + let shareMode = false; + + let animate = true; + let currentFrame = 0; + + let fpsInterval, now, then, elapsed; + + let speed = 1.5; + + function init() { + let oldW = w; + let oldH = h; + let oldOffset = offset + w = document.documentElement.clientWidth; + h = document.documentElement.clientHeight; + offset = $footer.offsetHeight - 33; + if (h > 800) offset += 16; + + if (oldW === w && oldH === h && oldOffset === offset) return; // nothing has changed + + c.width = w; + c.height = h; + x0 = w / 2; + y0 = h - offset; + dw = Math.round(Math.max(w, h, 1000) / 12); + + drawCircles(cCtx, 0); + + // enforce redrawing of frames + offscreenCanvases = {true: [], false: []}; + } + + function drawCircle(ctx, radius) { + ctx.lineWidth = 2; + + baseColor = shareMode ? '168 168 255' : '168 168 168'; + baseOpacity = shareMode ? 0.8 : 0.4; + + let opacity = baseOpacity * radius / (dw * 8); + if (radius > dw * 5) { + opacity *= (6 * dw - radius) / dw + } + ctx.strokeStyle = `rgb(${baseColor} / ${opacity})`; + ctx.beginPath(); + ctx.arc(x0, y0, radius, 0, 2 * Math.PI); + ctx.stroke(); + } + + function drawCircles(ctx, frame) { + for (let i = 6; i >= 0; i--) { + drawCircle(ctx, dw * i + speed * frame + 33); + } + } + + function createOffscreenCanvas(frame) { + let canvas = document.createElement("canvas"); + canvas.width = c.width; + canvas.height = c.height; + offscreenCanvases[shareMode][frame] = canvas; + let ctx = canvas.getContext('2d'); + drawCircles(ctx, frame); + } + + function drawFrame(frame) { + cCtx.clearRect(0, 0, w, h); + + if (!offscreenCanvases[shareMode][frame]) { + createOffscreenCanvas(frame); + } + cCtx.drawImage(offscreenCanvases[shareMode][frame], 0, 0); + } + + function startAnimating(fps) { + fpsInterval = 1000 / fps; + then = Date.now(); + animateBg(); + } + + function animateBg() { + requestAnimationFrame(animateBg); + + now = Date.now(); + elapsed = now - then; + // if not enough time has elapsed, do not draw the next frame -> abort + if (elapsed < fpsInterval) { + return; + } + + then = now - (elapsed % fpsInterval); + + if (animate) { + currentFrame = (currentFrame + 1) % (dw/speed); + drawFrame(currentFrame); + } + } + + function switchAnimation(state) { + animate = state; + console.debug(state) + } + + function redrawOnShareModeChange(active) { + shareMode = active + } + + init(); + startAnimating(30) // redraw canvas - Events.on('resize', _ => this.init()); - Events.on('redraw-canvas', _ => this.init()); - Events.on('translation-loaded', _ => this.init()); + Events.on('resize', _ => init()); + Events.on('redraw-canvas', _ => init()); + Events.on('translation-loaded', _ => init()); // ShareMode - Events.on('share-mode-changed', e => this.onShareModeChanged(e.detail.active)); + Events.on('share-mode-changed', e => redrawOnShareModeChange(e.detail.active)); + + // Start and stop animation + Events.on('background-animation', e => switchAnimation(e.detail.animate)) + + Events.on('offline', _ => switchAnimation(false)); + Events.on('online', _ => switchAnimation(true)); } async 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.baseColor = '165, 165, 165'; - this.baseOpacity = 0.3; - - this.drawCircles(this.cCtx); - } - - onShareModeChanged(active) { - this.baseColor = active ? '165, 165, 255' : '165, 165, 165'; - this.baseOpacity = active ? 0.5 : 0.3; - this.drawCircles(this.cCtx); - } - - - drawCircle(ctx, radius) { - ctx.beginPath(); - ctx.lineWidth = 2; - let opacity = Math.max(0, this.baseOpacity * (1 - 1.2 * radius / Math.max(this.w, this.h))); - ctx.strokeStyle = `rgba(${this.baseColor}, ${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); - } + this.canvas.classList.remove('opacity-0'); } } \ No newline at end of file diff --git a/public/scripts/ui.js b/public/scripts/ui.js index c988db7..835eaae 100644 --- a/public/scripts/ui.js +++ b/public/scripts/ui.js @@ -150,10 +150,17 @@ class PeersUI { } _onPeerDisconnected(peerId) { + // Remove peer from UI const $peer = $(peerId); if (!$peer) return; $peer.remove(); this._evaluateOverflowingPeers(); + + // If no peer is shown -> start background animation again + if ($$('x-peers:empty')) { + Events.fire('background-animation', {animate: true}); + } + } _onRoomTypeRemoved(peerId, roomType) { @@ -417,6 +424,9 @@ class PeerUI { // ShareMode Events.on('share-mode-changed', e => this._onShareModeChanged(e.detail.active, e.detail.descriptor)); + + // Stop background animation + Events.fire('background-animation', {animate: false}); } html() { From f0e72506175c43939bee38887a0acf794e2fffc3 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Sun, 16 Feb 2025 00:52:34 +0100 Subject: [PATCH 104/133] Use time based approach to smoothen reduced framerate --- public/scripts/ui-main.js | 91 ++++++++++++++++++++++++--------------- 1 file changed, 57 insertions(+), 34 deletions(-) diff --git a/public/scripts/ui-main.js b/public/scripts/ui-main.js index 682dbe3..a8c4a1f 100644 --- a/public/scripts/ui-main.js +++ b/public/scripts/ui-main.js @@ -344,15 +344,26 @@ class BackgroundCanvas { let x0, y0, w, h, dw, offset, baseColor, baseOpacity; - let offscreenCanvases; + let offscreenCanvases = {false: [], true: []}; let shareMode = false; + let startTime; let animate = true; - let currentFrame = 0; + let speed = 0.4; + let fps = 300; + let maxFrames = fps / speed; - let fpsInterval, now, then, elapsed; - - let speed = 1.5; + for (let frame = 0; frame < maxFrames; frame++) { + let canvas = document.createElement("canvas"); + offscreenCanvases[false][frame] = { + "redraw": true, + "canvas": canvas + }; + offscreenCanvases[true][frame] = { + "redraw": true, + "canvas": canvas + }; + } function init() { let oldW = w; @@ -360,8 +371,8 @@ class BackgroundCanvas { let oldOffset = offset w = document.documentElement.clientWidth; h = document.documentElement.clientHeight; - offset = $footer.offsetHeight - 33; - if (h > 800) offset += 16; + offset = $footer.offsetHeight - 28; + if (h > 800) offset += 11; if (oldW === w && oldH === h && oldOffset === offset) return; // nothing has changed @@ -369,12 +380,15 @@ class BackgroundCanvas { c.height = h; x0 = w / 2; y0 = h - offset; - dw = Math.round(Math.max(w, h, 1000) / 12); + dw = Math.round(Math.max(w, h, 1000) / 15); - drawCircles(cCtx, 0); + drawFrame(currentFrame); // enforce redrawing of frames - offscreenCanvases = {true: [], false: []}; + for (let frame = 0; frame < maxFrames; frame++) { + offscreenCanvases[true][frame]["redraw"] = true; + offscreenCanvases[false][frame]["redraw"] = true; + } } function drawCircle(ctx, radius) { @@ -383,8 +397,11 @@ class BackgroundCanvas { baseColor = shareMode ? '168 168 255' : '168 168 168'; baseOpacity = shareMode ? 0.8 : 0.4; - let opacity = baseOpacity * radius / (dw * 8); - if (radius > dw * 5) { + let opacity = Math.max(0, baseOpacity * (1 - 1.2 * radius / Math.max(w, h))); + if (radius < dw) { + opacity *= (radius - 33) / (dw - 33) + } + else if (radius > dw * 5) { opacity *= (6 * dw - radius) / dw } ctx.strokeStyle = `rgb(${baseColor} / ${opacity})`; @@ -394,16 +411,16 @@ class BackgroundCanvas { } function drawCircles(ctx, frame) { - for (let i = 6; i >= 0; i--) { - drawCircle(ctx, dw * i + speed * frame + 33); + ctx.clearRect(0, 0, w, h); + for (let i = 5; i >= 0; i--) { + drawCircle(ctx, dw * i + speed * dw * frame / fps + 33); } } - function createOffscreenCanvas(frame) { - let canvas = document.createElement("canvas"); + function drawOffscreenCanvas(frame) { + let canvas = offscreenCanvases[shareMode][frame]["canvas"]; canvas.width = c.width; canvas.height = c.height; - offscreenCanvases[shareMode][frame] = canvas; let ctx = canvas.getContext('2d'); drawCircles(ctx, frame); } @@ -411,39 +428,45 @@ class BackgroundCanvas { function drawFrame(frame) { cCtx.clearRect(0, 0, w, h); - if (!offscreenCanvases[shareMode][frame]) { - createOffscreenCanvas(frame); + if (offscreenCanvases[shareMode][frame]["redraw"]) { + drawOffscreenCanvas(frame); } - cCtx.drawImage(offscreenCanvases[shareMode][frame], 0, 0); + cCtx.drawImage(offscreenCanvases[shareMode][frame]["canvas"], 0, 0); } - function startAnimating(fps) { - fpsInterval = 1000 / fps; - then = Date.now(); + function startAnimating() { + startTime = Date.now(); animateBg(); } + let currentFrame = 0; function animateBg() { - requestAnimationFrame(animateBg); + let now = Date.now(); - now = Date.now(); - elapsed = now - then; - // if not enough time has elapsed, do not draw the next frame -> abort - if (elapsed < fpsInterval) { + if (!animate) { + // Animation stopped -> don't draw next frame return; } - then = now - (elapsed % fpsInterval); + let timeSinceLastFullCycle = (now - startTime) % (1000 / speed); + let nextFrame = Math.trunc(fps * timeSinceLastFullCycle / 1000); - if (animate) { - currentFrame = (currentFrame + 1) % (dw/speed); - drawFrame(currentFrame); + // Only draw frame if it differs from current frame + if (nextFrame !== currentFrame) { + drawFrame(nextFrame); + currentFrame = nextFrame; } + + requestAnimationFrame(animateBg); } function switchAnimation(state) { + if (!animate && state) { + // animation starts again. Set startTime to specific value to prevent frame jump + startTime = Date.now() - 1000 * currentFrame / fps; + } animate = state; - console.debug(state) + animateBg(); } function redrawOnShareModeChange(active) { @@ -451,7 +474,7 @@ class BackgroundCanvas { } init(); - startAnimating(30) + startAnimating(); // redraw canvas Events.on('resize', _ => init()); From 16523843bd7bd6241854666a51ae3bff9155809d Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Sun, 16 Feb 2025 19:23:04 +0100 Subject: [PATCH 105/133] Use OffscreenCanvas on supported browsers to offload canvas drawing to a service worker thread --- public/scripts/canvas-worker.js | 135 ++++++++++++++++++ public/scripts/ui-main.js | 241 ++++++++++++++++++++------------ public/service-worker.js | 1 + 3 files changed, 288 insertions(+), 89 deletions(-) create mode 100644 public/scripts/canvas-worker.js diff --git a/public/scripts/canvas-worker.js b/public/scripts/canvas-worker.js new file mode 100644 index 0000000..e7e6bc7 --- /dev/null +++ b/public/scripts/canvas-worker.js @@ -0,0 +1,135 @@ +self.onmessage = (e) => { + switch (e.data.type) { + case "createCanvas": createCanvas(e.data); + break; + case "initCanvas": initCanvas(e.data.footerOffsetHeight, e.data.clientWidth, e.data.clientHeight); + break; + case "startAnimation": startAnimation(); + break; + case "onShareModeChange": onShareModeChange(e.data.active); + break; + case "switchAnimation": switchAnimation(e.data.animate); + break; + } +}; + +let baseColorNormal; +let baseColorShareMode; +let baseOpacityNormal; +let baseOpacityShareMode; +let speed; +let fps; + +let c; +let cCtx; + +let x0, y0, w, h, dw, offset; + +let startTime; +let animate = true; +let currentFrame = 0; +let lastFrame; +let baseColor; +let baseOpacity; + +function createCanvas(data) { + baseColorNormal = data.baseColorNormal; + baseColorShareMode = data.baseColorShareMode; + baseOpacityNormal = data.baseOpacityNormal; + baseOpacityShareMode = data.baseOpacityShareMode; + speed = data.speed; + fps = data.fps; + + c = data.canvas; + cCtx = c.getContext("2d"); + + lastFrame = fps / speed - 1; + baseColor = baseColorNormal; + baseOpacity = baseOpacityNormal; +} + +function initCanvas(footerOffsetHeight, clientWidth, clientHeight) { + let oldW = w; + let oldH = h; + let oldOffset = offset; + w = clientWidth; + h = clientHeight; + offset = footerOffsetHeight - 28; + if (h > 800) offset += 11; + + 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.min(Math.max(w, h), 800) / 10); + + drawFrame(currentFrame); +} + +function startAnimation() { + startTime = Date.now(); + animateBg(); +} + +function switchAnimation(state) { + if (!animate && state) { + // animation starts again. Set startTime to specific value to prevent frame jump + startTime = Date.now() - 1000 * currentFrame / fps; + } + animate = state; + requestAnimationFrame(animateBg); +} + +function onShareModeChange(active) { + baseColor = active ? baseColorShareMode : baseColorNormal; + baseOpacity = active ? baseOpacityShareMode : baseOpacityNormal; + drawFrame(currentFrame); +} + +function drawCircle(ctx, radius) { + ctx.lineWidth = 2; + + let opacity = Math.max(0, baseOpacity * (1 - 1.2 * radius / Math.max(w, h))); + if (radius > dw * 7) { + opacity *= (8 * dw - radius) / dw + } + + ctx.strokeStyle = `rgb(${baseColor} / ${opacity})`; + ctx.beginPath(); + ctx.arc(x0, y0, radius, 0, 2 * Math.PI); + ctx.stroke(); +} + +function drawCircles(ctx, frame) { + ctx.clearRect(0, 0, w, h); + for (let i = 7; i >= 0; i--) { + drawCircle(ctx, dw * i + speed * dw * frame / fps + 33); + } +} + +function drawFrame(frame) { + cCtx.clearRect(0, 0, w, h); + drawCircles(cCtx, frame); +} + +function animateBg() { + let now = Date.now(); + + if (!animate && currentFrame === lastFrame) { + // Animation stopped and cycle finished -> stop drawing frames + return; + } + + let timeSinceLastFullCycle = (now - startTime) % (1000 / speed); + let nextFrame = Math.trunc(fps * timeSinceLastFullCycle / 1000); + + // Only draw frame if it differs from current frame + if (nextFrame !== currentFrame) { + drawFrame(nextFrame); + currentFrame = nextFrame; + } + + requestAnimationFrame(animateBg); +} \ No newline at end of file diff --git a/public/scripts/ui-main.js b/public/scripts/ui-main.js index a8c4a1f..3dbd612 100644 --- a/public/scripts/ui-main.js +++ b/public/scripts/ui-main.js @@ -333,45 +333,93 @@ class FooterUI { class BackgroundCanvas { constructor() { - this.canvas = $$('canvas'); + this.$canvas = $$('canvas'); + this.$footer = $$('footer'); + this.initAnimation(); } + async fadeIn() { + this.$canvas.classList.remove('opacity-0'); + } + initAnimation() { - let c = this.canvas; - let cCtx = c.getContext('2d'); - let $footer = $$('footer'); + this.baseColorNormal = '168 168 168'; + this.baseColorShareMode = '168 168 255'; + this.baseOpacityNormal = 0.4; + this.baseOpacityShareMode = 0.8; + this.speed = 0.4; + this.fps = 40; - let x0, y0, w, h, dw, offset, baseColor, baseOpacity; + // if browser supports OffscreenCanvas + // -> put canvas drawing into serviceworker to unblock main thread + // otherwise + // -> use main thread + let {init, startAnimation, switchAnimation, onShareModeChange} = + this.$canvas.transferControlToOffscreen + ? this.initAnimationOffscreen() + : this.initAnimationOnscreen(); - let offscreenCanvases = {false: [], true: []}; - let shareMode = false; + init(); + startAnimation(); + + // redraw canvas + Events.on('resize', _ => init()); + Events.on('redraw-canvas', _ => init()); + Events.on('translation-loaded', _ => init()); + + // ShareMode + Events.on('share-mode-changed', e => onShareModeChange(e.detail.active)); + + // Start and stop animation + Events.on('background-animation', e => switchAnimation(e.detail.animate)) + Events.on('offline', _ => switchAnimation(false)); + Events.on('online', _ => switchAnimation(true)); + } + + initAnimationOnscreen() { + let $canvas = this.$canvas; + let $footer = this.$footer; + + let baseColorNormal = this.baseColorNormal; + let baseColorShareMode = this.baseColorShareMode; + let baseOpacityNormal = this.baseOpacityNormal; + let baseOpacityShareMode = this.baseOpacityShareMode; + let speed = this.speed; + let fps = this.fps; + + let c; + let cCtx; + + let x0, y0, w, h, dw, offset; let startTime; let animate = true; - let speed = 0.4; - let fps = 300; - let maxFrames = fps / speed; + let currentFrame = 0; + let lastFrame; + let baseColor; + let baseOpacity; - for (let frame = 0; frame < maxFrames; frame++) { - let canvas = document.createElement("canvas"); - offscreenCanvases[false][frame] = { - "redraw": true, - "canvas": canvas - }; - offscreenCanvases[true][frame] = { - "redraw": true, - "canvas": canvas - }; + function createCanvas() { + c = $canvas; + cCtx = c.getContext('2d'); + + lastFrame = fps / speed - 1; + baseColor = baseColorNormal; + baseOpacity = baseOpacityNormal; } function init() { + initCanvas($footer.offsetHeight, document.documentElement.clientWidth, document.documentElement.clientHeight); + } + + function initCanvas(footerOffsetHeight, clientWidth, clientHeight) { let oldW = w; let oldH = h; - let oldOffset = offset - w = document.documentElement.clientWidth; - h = document.documentElement.clientHeight; - offset = $footer.offsetHeight - 28; + let oldOffset = offset; + w = clientWidth; + h = clientHeight; + offset = footerOffsetHeight - 28; if (h > 800) offset += 11; if (oldW === w && oldH === h && oldOffset === offset) return; // nothing has changed @@ -380,30 +428,39 @@ class BackgroundCanvas { c.height = h; x0 = w / 2; y0 = h - offset; - dw = Math.round(Math.max(w, h, 1000) / 15); + dw = Math.round(Math.min(Math.max(w, h), 800) / 10); drawFrame(currentFrame); + } - // enforce redrawing of frames - for (let frame = 0; frame < maxFrames; frame++) { - offscreenCanvases[true][frame]["redraw"] = true; - offscreenCanvases[false][frame]["redraw"] = true; + function startAnimation() { + startTime = Date.now(); + animateBg(); + } + + function switchAnimation(state) { + if (!animate && state) { + // animation starts again. Set startTime to specific value to prevent frame jump + startTime = Date.now() - 1000 * currentFrame / fps; } + animate = state; + requestAnimationFrame(animateBg); + } + + function onShareModeChange(active) { + baseColor = active ? baseColorShareMode : baseColorNormal; + baseOpacity = active ? baseOpacityShareMode : baseOpacityNormal; + drawFrame(currentFrame); } function drawCircle(ctx, radius) { ctx.lineWidth = 2; - baseColor = shareMode ? '168 168 255' : '168 168 168'; - baseOpacity = shareMode ? 0.8 : 0.4; - let opacity = Math.max(0, baseOpacity * (1 - 1.2 * radius / Math.max(w, h))); - if (radius < dw) { - opacity *= (radius - 33) / (dw - 33) - } - else if (radius > dw * 5) { - opacity *= (6 * dw - radius) / dw + if (radius > dw * 7) { + opacity *= (8 * dw - radius) / dw } + ctx.strokeStyle = `rgb(${baseColor} / ${opacity})`; ctx.beginPath(); ctx.arc(x0, y0, radius, 0, 2 * Math.PI); @@ -412,39 +469,21 @@ class BackgroundCanvas { function drawCircles(ctx, frame) { ctx.clearRect(0, 0, w, h); - for (let i = 5; i >= 0; i--) { + for (let i = 7; i >= 0; i--) { drawCircle(ctx, dw * i + speed * dw * frame / fps + 33); } } - function drawOffscreenCanvas(frame) { - let canvas = offscreenCanvases[shareMode][frame]["canvas"]; - canvas.width = c.width; - canvas.height = c.height; - let ctx = canvas.getContext('2d'); - drawCircles(ctx, frame); - } - function drawFrame(frame) { cCtx.clearRect(0, 0, w, h); - - if (offscreenCanvases[shareMode][frame]["redraw"]) { - drawOffscreenCanvas(frame); - } - cCtx.drawImage(offscreenCanvases[shareMode][frame]["canvas"], 0, 0); + drawCircles(cCtx, frame); } - function startAnimating() { - startTime = Date.now(); - animateBg(); - } - - let currentFrame = 0; function animateBg() { let now = Date.now(); - if (!animate) { - // Animation stopped -> don't draw next frame + if (!animate && currentFrame === lastFrame) { + // Animation stopped and cycle finished -> stop drawing frames return; } @@ -460,38 +499,62 @@ class BackgroundCanvas { requestAnimationFrame(animateBg); } - function switchAnimation(state) { - if (!animate && state) { - // animation starts again. Set startTime to specific value to prevent frame jump - startTime = Date.now() - 1000 * currentFrame / fps; - } - animate = state; - animateBg(); - } + createCanvas(); - function redrawOnShareModeChange(active) { - shareMode = active - } - - init(); - startAnimating(); - - // redraw canvas - Events.on('resize', _ => init()); - Events.on('redraw-canvas', _ => init()); - Events.on('translation-loaded', _ => init()); - - // ShareMode - Events.on('share-mode-changed', e => redrawOnShareModeChange(e.detail.active)); - - // Start and stop animation - Events.on('background-animation', e => switchAnimation(e.detail.animate)) - - Events.on('offline', _ => switchAnimation(false)); - Events.on('online', _ => switchAnimation(true)); + return {init, startAnimation, switchAnimation, onShareModeChange}; } - async fadeIn() { - this.canvas.classList.remove('opacity-0'); + initAnimationOffscreen() { + console.log("Use OffscreenCanvas to draw background animation.") + + let baseColorNormal = this.baseColorNormal; + let baseColorShareMode = this.baseColorShareMode; + let baseOpacityNormal = this.baseOpacityNormal; + let baseOpacityShareMode = this.baseOpacityShareMode; + let speed = this.speed; + let fps = this.fps; + let $canvas = this.$canvas; + let $footer = this.$footer; + + const offscreen = $canvas.transferControlToOffscreen(); + const worker = new Worker("scripts/canvas-worker.js"); + + function createCanvas() { + worker.postMessage({ + type: "createCanvas", + canvas: offscreen, + baseColorNormal: baseColorNormal, + baseColorShareMode: baseColorShareMode, + baseOpacityNormal: baseOpacityNormal, + baseOpacityShareMode: baseOpacityShareMode, + speed: speed, + fps: fps + }, [offscreen]); + } + + function init() { + worker.postMessage({ + type: "initCanvas", + footerOffsetHeight: $footer.offsetHeight, + clientWidth: document.documentElement.clientWidth, + clientHeight: document.documentElement.clientHeight + }); + } + + function startAnimation() { + worker.postMessage({ type: "startAnimation" }); + } + + function onShareModeChange(active) { + worker.postMessage({ type: "onShareModeChange", active: active }); + } + + function switchAnimation(animate) { + worker.postMessage({ type: "switchAnimation", animate: animate }); + } + + createCanvas(); + + return {init, startAnimation, switchAnimation, onShareModeChange}; } } \ No newline at end of file diff --git a/public/service-worker.js b/public/service-worker.js index c6420fe..f022b11 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -17,6 +17,7 @@ const relativePathsToCache = [ 'scripts/ui-main.js', 'scripts/util.js', 'scripts/zip.min.js', + 'scripts/canvas-worker.js', 'sounds/blop.mp3', 'sounds/blop.ogg', 'images/favicon-96x96.png', From ae68ede3f37445caa56b2b08ef307ff32490b38e Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Sun, 16 Feb 2025 19:29:14 +0100 Subject: [PATCH 106/133] Put worker and libraries in subfolders --- public/scripts/{ => libs}/heic2any.min.js | 0 public/scripts/{ => libs}/no-sleep.min.js | 0 public/scripts/{ => libs}/qr-code.min.js | 0 public/scripts/{ => libs}/zip.min.js | 0 public/scripts/main.js | 8 ++++---- public/scripts/ui-main.js | 2 +- public/scripts/{ => worker}/canvas-worker.js | 0 public/service-worker.js | 9 +++++---- 8 files changed, 10 insertions(+), 9 deletions(-) rename public/scripts/{ => libs}/heic2any.min.js (100%) rename public/scripts/{ => libs}/no-sleep.min.js (100%) rename public/scripts/{ => libs}/qr-code.min.js (100%) rename public/scripts/{ => libs}/zip.min.js (100%) rename public/scripts/{ => worker}/canvas-worker.js (100%) diff --git a/public/scripts/heic2any.min.js b/public/scripts/libs/heic2any.min.js similarity index 100% rename from public/scripts/heic2any.min.js rename to public/scripts/libs/heic2any.min.js diff --git a/public/scripts/no-sleep.min.js b/public/scripts/libs/no-sleep.min.js similarity index 100% rename from public/scripts/no-sleep.min.js rename to public/scripts/libs/no-sleep.min.js diff --git a/public/scripts/qr-code.min.js b/public/scripts/libs/qr-code.min.js similarity index 100% rename from public/scripts/qr-code.min.js rename to public/scripts/libs/qr-code.min.js diff --git a/public/scripts/zip.min.js b/public/scripts/libs/zip.min.js similarity index 100% rename from public/scripts/zip.min.js rename to public/scripts/libs/zip.min.js diff --git a/public/scripts/main.js b/public/scripts/main.js index 8960ed2..6ab999a 100644 --- a/public/scripts/main.js +++ b/public/scripts/main.js @@ -14,10 +14,10 @@ class PairDrop { "scripts/util.js", "scripts/network.js", "scripts/ui.js", - "scripts/qr-code.min.js", - "scripts/zip.min.js", - "scripts/no-sleep.min.js", - "scripts/heic2any.min.js" + "scripts/libs/heic2any.min.js", + "scripts/libs/no-sleep.min.js", + "scripts/libs/qr-code.min.js", + "scripts/libs/zip.min.js" ]; this.registerServiceWorker(); diff --git a/public/scripts/ui-main.js b/public/scripts/ui-main.js index 3dbd612..f9ecbad 100644 --- a/public/scripts/ui-main.js +++ b/public/scripts/ui-main.js @@ -517,7 +517,7 @@ class BackgroundCanvas { let $footer = this.$footer; const offscreen = $canvas.transferControlToOffscreen(); - const worker = new Worker("scripts/canvas-worker.js"); + const worker = new Worker("scripts/worker/canvas-worker.js"); function createCanvas() { worker.postMessage({ diff --git a/public/scripts/canvas-worker.js b/public/scripts/worker/canvas-worker.js similarity index 100% rename from public/scripts/canvas-worker.js rename to public/scripts/worker/canvas-worker.js diff --git a/public/service-worker.js b/public/service-worker.js index f022b11..07e2c50 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -10,14 +10,15 @@ const relativePathsToCache = [ 'scripts/localization.js', 'scripts/main.js', 'scripts/network.js', - 'scripts/no-sleep.min.js', 'scripts/persistent-storage.js', - 'scripts/qr-code.min.js', 'scripts/ui.js', 'scripts/ui-main.js', 'scripts/util.js', - 'scripts/zip.min.js', - 'scripts/canvas-worker.js', + 'scripts/worker/canvas-worker.js', + 'scripts/libs/heic2any.min.js', + 'scripts/libs/no-sleep.min.js', + 'scripts/libs/qr-code.min.js', + 'scripts/libs/zip.min.js', 'sounds/blop.mp3', 'sounds/blop.ogg', 'images/favicon-96x96.png', From 8eea54f8dd022fb67a4454ee0f93c7f8413cac86 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Sun, 16 Feb 2025 23:20:43 +0100 Subject: [PATCH 107/133] Make sure older webkit/blink based browsers are able to render opacity of circles --- public/scripts/ui-main.js | 9 ++++++++- public/scripts/worker/canvas-worker.js | 10 +++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/public/scripts/ui-main.js b/public/scripts/ui-main.js index f9ecbad..6a7dd44 100644 --- a/public/scripts/ui-main.js +++ b/public/scripts/ui-main.js @@ -461,7 +461,14 @@ class BackgroundCanvas { opacity *= (8 * dw - radius) / dw } - ctx.strokeStyle = `rgb(${baseColor} / ${opacity})`; + if (ctx.setStrokeColor) { + // older blink/webkit browsers do not understand opacity in strokeStyle. Use deprecated setStrokeColor + let baseColorRgb = baseColor.split(" "); + ctx.setStrokeColor(baseColorRgb[0], baseColorRgb[1], baseColorRgb[2], opacity); + } + else { + ctx.strokeStyle = `rgb(${baseColor} / ${opacity})`; + } ctx.beginPath(); ctx.arc(x0, y0, radius, 0, 2 * Math.PI); ctx.stroke(); diff --git a/public/scripts/worker/canvas-worker.js b/public/scripts/worker/canvas-worker.js index e7e6bc7..1428bc1 100644 --- a/public/scripts/worker/canvas-worker.js +++ b/public/scripts/worker/canvas-worker.js @@ -96,7 +96,15 @@ function drawCircle(ctx, radius) { opacity *= (8 * dw - radius) / dw } - ctx.strokeStyle = `rgb(${baseColor} / ${opacity})`; + if (ctx.setStrokeColor) { + // older blink/webkit based browsers do not understand opacity in strokeStyle. Use deprecated setStrokeColor instead + // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeStyle#webkitblink-specific_note + let baseColorRgb = baseColor.split(" "); + ctx.setStrokeColor(baseColorRgb[0], baseColorRgb[1], baseColorRgb[2], opacity); + } + else { + ctx.strokeStyle = `rgb(${baseColor} / ${opacity})`; + } ctx.beginPath(); ctx.arc(x0, y0, radius, 0, 2 * Math.PI); ctx.stroke(); From ec0012ecd1d27133051452b822eb96843a9290f8 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Sun, 16 Feb 2025 23:23:27 +0100 Subject: [PATCH 108/133] Speed up animation slightly --- public/scripts/ui-main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/scripts/ui-main.js b/public/scripts/ui-main.js index 6a7dd44..812a4ae 100644 --- a/public/scripts/ui-main.js +++ b/public/scripts/ui-main.js @@ -348,7 +348,7 @@ class BackgroundCanvas { this.baseColorShareMode = '168 168 255'; this.baseOpacityNormal = 0.4; this.baseOpacityShareMode = 0.8; - this.speed = 0.4; + this.speed = 0.5; this.fps = 40; // if browser supports OffscreenCanvas From 09e4e5d289eb11793fea8b6fba6e54f9bfbe79e3 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Sun, 16 Feb 2025 23:47:35 +0100 Subject: [PATCH 109/133] Prevent background animation from being cut on devices with a notch --- public/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/index.html b/public/index.html index 5dec40a..d1873b2 100644 --- a/public/index.html +++ b/public/index.html @@ -6,7 +6,7 @@ PairDrop | Transfer Files Cross-Platform. No Setup, No Signup. - + From 61caa43ce9cef1b126c3d491a54a10f04127af18 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 17 Feb 2025 05:37:36 +0100 Subject: [PATCH 110/133] Translated using Weblate (Basque) Currently translated at 100.0% (166 of 166 strings) Co-authored-by: Hosted Weblate Co-authored-by: xabirequejo Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/eu/ Translation: PairDrop/pairdrop-spa --- public/lang/eu.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/lang/eu.json b/public/lang/eu.json index 2e528b3..bcae982 100644 --- a/public/lang/eu.json +++ b/public/lang/eu.json @@ -73,7 +73,7 @@ "copied-text": "Testua arbelera kopiatu da", "online": "Berriro zaude linean", "unfinished-transfers-warning": "Amaitu gabeko trukatzeak daude. Ziur PairDrop itxi nahi duzula?", - "selected-peer-left": "Falta diren hautatutako kideak", + "selected-peer-left": "Hautatutako kideak alde egin du", "pairing-key-invalidated": "{{key}} gakoa baliogabetu da" }, "dialogs": { From 43ce64d68abc078bfc42a1ed07a58ae27f941347 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 17 Feb 2025 05:37:37 +0100 Subject: [PATCH 111/133] Translated using Weblate (Bengali) Currently translated at 1.2% (2 of 166 strings) Added translation using Weblate (Bengali) Co-authored-by: Hosted Weblate Co-authored-by: Saif Mahmud Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/bn/ Translation: PairDrop/pairdrop-spa --- public/lang/bn.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 public/lang/bn.json diff --git a/public/lang/bn.json b/public/lang/bn.json new file mode 100644 index 0000000..4f3f52a --- /dev/null +++ b/public/lang/bn.json @@ -0,0 +1,6 @@ +{ + "header": { + "about_title": "পেয়ার ড্রপ সম্পর্কে", + "install_title": "পেয়ার ড্রপ ইন্সটল করুন" + } +} From 9f4309c866ce689c8de90545907e3835accd1f36 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 17 Feb 2025 05:37:37 +0100 Subject: [PATCH 112/133] =?UTF-8?q?Translated=20using=20Weblate=20(Norwegi?= =?UTF-8?q?an=20Bokm=C3=A5l)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 100.0% (166 of 166 strings) Co-authored-by: Hosted Weblate Co-authored-by: Tobbz Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/nb_NO/ Translation: PairDrop/pairdrop-spa --- public/lang/nb.json | 98 +++++++++++++++++++++++++++++++++------------ 1 file changed, 72 insertions(+), 26 deletions(-) diff --git a/public/lang/nb.json b/public/lang/nb.json index d9a4022..468ea19 100644 --- a/public/lang/nb.json +++ b/public/lang/nb.json @@ -3,50 +3,62 @@ "edit-paired-devices_title": "Rediger sammenkoblede enheter", "about_title": "Om PairDrop", "about_aria-label": "Åpne «Om PairDrop»", - "theme-auto_title": "Juster drakt til system", + "theme-auto_title": "Juster drakt til system automatisk", "theme-light_title": "Alltid bruk lys drakt", "theme-dark_title": "Alltid bruk mørk drakt", "notification_title": "Skru på varslinger", "cancel-share-mode": "Ferdig", "install_title": "Installer PairDrop", - "pair-device_title": "Sammenkoble enhet", - "language-selector_title": "Velg språk" + "pair-device_title": "Sammenkoble dine enheter permanent", + "language-selector_title": "Velg språk", + "edit-share-mode": "Rediger", + "expand_title": "Utvid overskriftknapprad", + "join-public-room_title": "Bli med i et offentlig rom midlertidig" }, "footer": { "webrtc": "hvis WebRTC ikke er tilgjengelig.", "display-name_data-placeholder": "Laster inn…", - "display-name_title": "Rediger det vedvarende enhetsnavnet ditt", + "display-name_title": "Rediger ditt enhetsnavn permanent", "traffic": "Trafikken", "on-this-network": "på dette nettverket", "known-as": "Du er kjent som:", - "paired-devices": "sammenkoblede enheter", - "routed": "Sendes gjennom tjeneren" + "paired-devices": "av sammenkoblede enheter", + "routed": "Sendes gjennom tjeneren", + "discovery": "Du kan bli oppdaget:", + "on-this-network_title": "Du kan bli oppdaget av alle på dette nettverket.", + "paired-devices_title": "Du kan alltid bli oppdaget av sammenkoblede enheter uavhengig av nettverk.", + "public-room-devices_title": "Du kan bli oppdaget av enheter i dette offentlige rommet uavhengig av nettverk.", + "public-room-devices": "i rom {{roomId}}" }, "instructions": { "x-instructions_desktop": "Klikk for å sende filer, eller høyreklikk for å sende en melding", "x-instructions_mobile": "Trykk for å sende filer, eller lang-trykk for å sende en melding", "x-instructions_data-drop-bg": "Slipp for å velge mottager", - "x-instructions-share-mode_desktop": "Klikk for å sende", + "x-instructions-share-mode_desktop": "Klikk for å sende {{descriptor}}", "no-peers_data-drop-bg": "Slipp for å velge mottager", "no-peers-title": "Åpne PairDrop på andre enheter for å sende filer", - "no-peers-subtitle": "Sammenkoble enheter for å kunne oppdages på andre nettverk", + "no-peers-subtitle": "Sammenkoble enheter eller bli med i et offentlig rom for å kunne oppdages på andre nettverk", "x-instructions_data-drop-peer": "Slipp for å sende til likemann", - "x-instructions-share-mode_mobile": "Trykk for å sende", + "x-instructions-share-mode_mobile": "Trykk for å sende {{descriptor}}", "activate-share-mode-base": "Åpne PairDrop på andre enheter for å sende", "activate-share-mode-and-other-files-plural": "og {{count}} andre filer", - "activate-share-mode-shared-text": "delt tekst" + "activate-share-mode-shared-text": "delt tekst", + "activate-share-mode-and-other-file": "og 1 annen fil", + "activate-share-mode-shared-file": "delt fil", + "activate-share-mode-shared-files-plural": "{{count}} delte filer", + "webrtc-requirement": "For å bruke denne PairDrop-økten, må WebRTC være aktivert!" }, "dialogs": { "input-key-on-this-device": "Skriv inn denne nøkkelen på en annen enhet", - "pair-devices-title": "Sammenkoble enheter", + "pair-devices-title": "Sammenkoble Enheter Permanent", "would-like-to-share": "ønsker å dele", "auto-accept-instructions-2": "for å godkjenne alle filer sendt fra den enheten automatisk.", "paired-devices-wrapper_data-empty": "Ingen sammenkoblede enheter.", - "enter-key-from-another-device": "Skriv inn nøkkel fra en annen enhet for å fortsette.", - "edit-paired-devices-title": "Rediger sammenkoblede enheter", + "enter-key-from-another-device": "Skriv inn nøkkel fra en annen enhet her.", + "edit-paired-devices-title": "Rediger Sammenkoblede Enheter", "accept": "Godta", "has-sent": "har sendt:", - "base64-paste-to-send": "Trykk her for å sende {{type}}", + "base64-paste-to-send": "Lim inn her for å dele {{type}}", "base64-text": "tekst", "base64-files": "filer", "file-other-description-image-plural": "og {{count}} andre bilder", @@ -64,9 +76,9 @@ "receive-text-title": "Melding mottatt", "auto-accept": "auto-godkjenn", "share": "Del", - "send-message-to": "Send en melding til", + "send-message-to": "Til:", "send": "Send", - "base64-tap-to-paste": "Trykk her for å lime inn {{type}}", + "base64-tap-to-paste": "Trykk her for å dele {{type}}", "file-other-description-image": "og ett annet bilde", "file-other-description-file-plural": "og {{count}} andre filer", "title-file-plural": "Filer", @@ -74,7 +86,28 @@ "file-other-description-file": "og én annen fil", "title-image": "Bilde", "title-file": "Fil", - "title-image-plural": "Bilder" + "title-image-plural": "Bilder", + "join": "Bli med", + "share-text-checkbox": "Alltid vis denne dialogen ved deling av tekst", + "language-selector-title": "Velg Språk", + "unpair": "Fjern sammenkobling", + "temporary-public-room-title": "Midlertidig Offentlig Rom", + "input-room-id-on-another-device": "Legg inn denne rom-IDen på en annen enhet", + "hr-or": "ELLER", + "leave": "Forlat", + "paired-device-removed": "Sammenkoblet enhet har blitt fjernet.", + "message_title": "Sett inn meldingen du vil sende", + "message_placeholder": "Tekst", + "base64-title-files": "Delte filer", + "system-language": "Systemspråk", + "public-room-qr-code_title": "Trykk for å kopiere lenke til offentlig rom", + "pair-devices-qr-code_title": "Trykk for å kopiere lenken til å sammenkoble denne enheten", + "approve": "godkjenn", + "share-text-title": "Del Tekstmelding", + "share-text-subtitle": "Rediger melding før sending:", + "close-toast_title": "Lukk varsel", + "enter-room-id-from-another-device": "Legg inn rom-ID fra en annen enhet for å bli med i rommet.", + "base64-title-text": "Delt Tekst" }, "about": { "close-about_aria-label": "Lukk «Om PairDrop»", @@ -82,7 +115,11 @@ "claim": "Den enkleste måten å overføre filer mellom enheter", "buy-me-a-coffee_title": "Spander drikke!", "tweet_title": "Tvitre om PairDrop", - "github_title": "PairDrop på GitHub" + "github_title": "PairDrop på GitHub", + "mastodon_title": "Skriv om PairDrop på Mastadon", + "bluesky_title": "Følg oss på BlueSky", + "custom_title": "Følg oss", + "privacypolicy_title": "Åpne vår personvernerklæring" }, "notifications": { "copied-to-clipboard": "Kopiert til utklippstavlen", @@ -95,7 +132,7 @@ "file-transfer-completed": "Filoverføring utført", "selected-peer-left": "Valgt likemann dro", "pairing-key-invalid": "Ugyldig nøkkel", - "connecting": "Kobler til …", + "connecting": "Kobler til…", "pairing-not-persistent": "Sammenkoblede enheter er ikke vedvarende", "offline": "Du er frakoblet", "online-requirement": "Du må være på nett for å koble sammen enheter.", @@ -110,28 +147,37 @@ "pairing-success": "Enheter sammenkoblet", "pairing-cleared": "Sammenkobling av alle enheter opphevet", "pairing-key-invalidated": "Nøkkel {{key}} ugyldiggjort", - "copied-text-error": "Kunne ikke legge innhold i utklkippstavlen. Kopier manuelt!", + "copied-text-error": "Kunne ikke legge innhold i utklippstavlen. Kopier manuelt!", "clipboard-content-incorrect": "Utklippstavleinnholdet er uriktig", "link-received": "Lenke mottatt av {{name}} - Klikk for å åpne", "request-title": "{{name}} ønsker å overføre {{count}} {{descriptor}}", "message-received": "Melding mottatt av {{name}} - Klikk for å åpne", "files-incorrect": "Filene er uriktige", "ios-memory-limit": "Forsendelse av filer til iOS er kun mulig opptil 200 MB av gangen", - "unfinished-transfers-warning": "Lukk med ufullførte overføringer?", - "rate-limit-join-key": "Forsøksgrense overskredet. Vent 10 sek. og prøv igjen." + "unfinished-transfers-warning": "Det er ufullførte overføringer. Er du sikker på at du vil lukke PairDrop?", + "rate-limit-join-key": "Grense nådd. Vent 10 sekunder og prøv igjen.", + "copied-to-clipboard-error": "Kopiering ikke mulig, Kopier manuelt.", + "public-room-id-invalid": "Ugyldig rom-ID", + "public-room-left": "Forlot offentlig rom {{publicRoomId}}", + "room-url-copied-to-clipboard": "Lenke for offentlig rom kopiert til utklippstavle", + "online-requirement-pairing": "Du må være på nett for å sammenkoble enheter", + "online-requirement-public-room": "Du må være på nett for å opprette et offentlig rom", + "pair-url-copied-to-clipboard": "Lenke for sammenkobling til denne enheten kopiert til utklipstavle", + "notifications-permissions-error": "Varlseltillatelse har blitt blokkert fordi brukeren har avvist forespørselen flere ganger. Dette kan tilbakestilles i Sideinnformasjon som kan bli funnet ved å trykke på låseikonet ved siden av URL-feltet." }, "document-titles": { "file-received": "Fil mottatt", "file-received-plural": "{{count}} filer mottatt", "message-received": "Melding mottatt", "file-transfer-requested": "Filoverføring forespurt", - "message-received-plural": "{{count}} meldinger mottatt" + "message-received-plural": "{{count}} meldinger mottatt", + "image-transfer-requested": "Blideoverføring forespurt" }, "peer-ui": { - "preparing": "Forbereder …", + "preparing": "Forbereder…", "waiting": "Venter…", - "processing": "Behandler …", - "transferring": "Overfører …", + "processing": "Behandler…", + "transferring": "Overfører…", "click-to-send": "Klikk for å sende filer, eller høyreklikk for å sende en melding", "click-to-send-share-mode": "Klikk for å sende {{descriptor}}", "connection-hash": "Sammenlign dette sikkerhetsnummeret på begge enhetene for å bekrefte ende-til-ende -krypteringen" From b8a973f037aa40de5300afd820368aa2ed347515 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Mon, 17 Feb 2025 11:52:07 +0100 Subject: [PATCH 113/133] Fix background animation size on 4k screens and decrease base opacity --- public/scripts/ui-main.js | 6 +++--- public/scripts/worker/canvas-worker.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/public/scripts/ui-main.js b/public/scripts/ui-main.js index 01ad2ab..95cb3ba 100644 --- a/public/scripts/ui-main.js +++ b/public/scripts/ui-main.js @@ -346,10 +346,10 @@ class BackgroundCanvas { initAnimation() { this.baseColorNormal = '168 168 168'; this.baseColorShareMode = '168 168 255'; - this.baseOpacityNormal = 0.4; + this.baseOpacityNormal = 0.3; this.baseOpacityShareMode = 0.8; this.speed = 0.5; - this.fps = 40; + this.fps = 60; // if browser supports OffscreenCanvas // -> put canvas drawing into serviceworker to unblock main thread @@ -427,7 +427,7 @@ class BackgroundCanvas { c.height = h; x0 = w / 2; y0 = h - offset; - dw = Math.round(Math.min(Math.max(w, h), 800) / 10); + dw = Math.round(Math.min(Math.max(0.6 * w, h)) / 10); drawFrame(currentFrame); } diff --git a/public/scripts/worker/canvas-worker.js b/public/scripts/worker/canvas-worker.js index 26ec1f0..055c328 100644 --- a/public/scripts/worker/canvas-worker.js +++ b/public/scripts/worker/canvas-worker.js @@ -62,7 +62,7 @@ function initCanvas(footerOffsetHeight, clientWidth, clientHeight) { c.height = h; x0 = w / 2; y0 = h - offset; - dw = Math.round(Math.min(Math.max(w, h), 800) / 10); + dw = Math.round(Math.min(Math.max(0.6 * w, h)) / 10); drawFrame(currentFrame); } From 800d492da55382944dcd0655131e1908d220f322 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Mon, 17 Feb 2025 12:36:49 +0100 Subject: [PATCH 114/133] Fix animation color on older webkit/blink based browsers --- public/scripts/ui-main.js | 4 ++-- public/scripts/worker/canvas-worker.js | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/public/scripts/ui-main.js b/public/scripts/ui-main.js index 95cb3ba..1af7c37 100644 --- a/public/scripts/ui-main.js +++ b/public/scripts/ui-main.js @@ -462,8 +462,8 @@ class BackgroundCanvas { if (ctx.setStrokeColor) { // older blink/webkit browsers do not understand opacity in strokeStyle. Use deprecated setStrokeColor - let baseColorRgb = baseColor.split(" "); - ctx.setStrokeColor(baseColorRgb[0], baseColorRgb[1], baseColorRgb[2], opacity); + // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeStyle#webkitblink-specific_note + ctx.setStrokeColor("grey", opacity); } else { ctx.strokeStyle = `rgb(${baseColor} / ${opacity})`; diff --git a/public/scripts/worker/canvas-worker.js b/public/scripts/worker/canvas-worker.js index 055c328..ff2650f 100644 --- a/public/scripts/worker/canvas-worker.js +++ b/public/scripts/worker/canvas-worker.js @@ -98,8 +98,7 @@ function drawCircle(ctx, radius) { if (ctx.setStrokeColor) { // older blink/webkit based browsers do not understand opacity in strokeStyle. Use deprecated setStrokeColor instead // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/strokeStyle#webkitblink-specific_note - let baseColorRgb = baseColor.split(" "); - ctx.setStrokeColor(baseColorRgb[0], baseColorRgb[1], baseColorRgb[2], opacity); + ctx.setStrokeColor("grey", opacity); } else { ctx.strokeStyle = `rgb(${baseColor} / ${opacity})`; From fa992498fbbad363c878acd1c42ee41df6ba5db7 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Mon, 17 Feb 2025 13:15:51 +0100 Subject: [PATCH 115/133] Revert "Prevent background animation from being cut on devices with a notch" This reverts commit 09e4e5d289eb11793fea8b6fba6e54f9bfbe79e3. --- public/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/index.html b/public/index.html index 8e3a1ec..e47983f 100644 --- a/public/index.html +++ b/public/index.html @@ -6,7 +6,7 @@ PairDrop | Transfer Files Cross-Platform. No Setup, No Signup. - + From ef61cc4dfe8376eb138ff3b6919c62ccacf909d4 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Mon, 17 Feb 2025 13:33:07 +0100 Subject: [PATCH 116/133] Update node dependencies --- package-lock.json | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/package-lock.json b/package-lock.json index 8812cb9..3fc7477 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,7 @@ "packages": { "": { "name": "pairdrop", - "version": "1.10.11", + "version": "1.11.0", "license": "ISC", "dependencies": { "express": "^4.18.2", @@ -68,9 +68,9 @@ } }, "node_modules/call-bind-apply-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", - "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" @@ -263,9 +263,9 @@ } }, "node_modules/express-rate-limit": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.3.1.tgz", - "integrity": "sha512-BbaryvkY4wEgDqLgD18/NSy2lDO2jTuT9Y8c1Mpx0X63Yz0sYd5zN6KPe7UvpuSVvV33T6RaE1o1IVZQjHMYgw==", + "version": "7.5.0", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.0.tgz", + "integrity": "sha512-eB5zbQh5h+VenMPM3fh+nw1YExi5nMr6HUCR62ELSP11huvxm/Uir1H1QEyTkk5QX6A58pX6NmaTMceKZ0Eodg==", "engines": { "node": ">= 16" }, @@ -273,7 +273,7 @@ "url": "https://github.com/sponsors/express-rate-limit" }, "peerDependencies": { - "express": "4 || 5 || ^5.0.0-beta.1" + "express": "^4.11 || 5 || ^5.0.0-beta.1" } }, "node_modules/finalhandler": { @@ -758,9 +758,9 @@ } }, "node_modules/ua-parser-js": { - "version": "1.0.38", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.38.tgz", - "integrity": "sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ==", + "version": "1.0.40", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.40.tgz", + "integrity": "sha512-z6PJ8Lml+v3ichVojCiB8toQJBuwR42ySM4ezjXIqXK3M0HczmKQ3LF4rhU55PfD99KEEXQG6yb7iOMyvYuHew==", "funding": [ { "type": "opencollective", @@ -775,6 +775,9 @@ "url": "https://github.com/sponsors/faisalman" } ], + "bin": { + "ua-parser-js": "script/cli.js" + }, "engines": { "node": "*" } @@ -812,9 +815,9 @@ } }, "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "engines": { "node": ">=10.0.0" }, From b3c61f4bafb1884de789eda3cbe56c16b44d16ce Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Mon, 17 Feb 2025 13:50:15 +0100 Subject: [PATCH 117/133] Increase version to v1.11.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Enhancements - Make PWA standalone (#264) - Bring back background animation after performance optimization (#285) - Add support for Safari 11-15 (#358) - Update Twitter icon and URL to (X) (Thanks @realchrislovett) - Update node dependencies ## Fixes - Fix pasting of files on background to invoke share-mode and make it available on Firefox (#370) - Fix padding issue on EditPairedDevicesDialog and Base64Dialog - Fix hydration of URLs into links in received messages that have exclamation marks in path ## Languages - Translations updates from Hosted Weblate (Basque, Norwegian Bokmål) --- .github/ISSUE_TEMPLATE/bug-report.md | 4 ++-- docs/how-to.md | 4 ++-- package-lock.json | 2 +- package.json | 2 +- public/index.html | 2 +- public/service-worker.js | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index 419d837..5263696 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -36,7 +36,7 @@ If applicable, add screenshots to help explain your problem. **Bug occurs on official PairDrop instance https://pairdrop.net/** No | Yes -Version: v1.10.11 +Version: v1.11.0 **Bug occurs on self-hosted PairDrop instance** No | Yes @@ -44,7 +44,7 @@ No | Yes **Self-Hosted Setup** Proxy: Nginx | Apache2 Deployment: docker run | docker compose | npm run start:prod -Version: v1.10.11 +Version: v1.11.0 **Additional context** Add any other context about the problem here. diff --git a/docs/how-to.md b/docs/how-to.md index 7d899db..fcad02f 100644 --- a/docs/how-to.md +++ b/docs/how-to.md @@ -45,11 +45,11 @@ This pairdrop-cli version was released alongside v1.10.4 #### Linux / Mac 1. Download the latest _pairdrop-cli.zip_ from the [releases page](https://github.com/schlagmichdoch/PairDrop/releases) ```shell - wget "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.10.11/pairdrop-cli.zip" + wget "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.11.0/pairdrop-cli.zip" ``` or ```shell - curl -LO "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.10.11/pairdrop-cli.zip" + curl -LO "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.11.0/pairdrop-cli.zip" ``` 2. Unzip the archive to a folder of your choice e.g. `/usr/share/pairdrop-cli/` ```shell diff --git a/package-lock.json b/package-lock.json index 3fc7477..bdc9acd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "pairdrop", - "version": "1.10.11", + "version": "1.11.0", "lockfileVersion": 3, "requires": true, "packages": { diff --git a/package.json b/package.json index f4fd629..b36e5d7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pairdrop", - "version": "1.10.11-", + "version": "1.11.0", "type": "module", "description": "", "main": "server/index.js", diff --git a/public/index.html b/public/index.html index e47983f..45df0e4 100644 --- a/public/index.html +++ b/public/index.html @@ -668,7 +668,7 @@

PairDrop

-
v1.10.11
+
v1.11.0
diff --git a/public/service-worker.js b/public/service-worker.js index 07e2c50..551f25e 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -1,4 +1,4 @@ -const cacheVersion = 'v1.10.11'; +const cacheVersion = 'v1.11.0'; const cacheTitle = `pairdrop-cache-${cacheVersion}`; const forceFetch = false; // FOR DEVELOPMENT: Set to true to always update assets instead of using cached versions const relativePathsToCache = [ From a39d8cdc845e6356d9eae2a907aa4bf5576f818a Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Mon, 17 Feb 2025 19:20:17 +0100 Subject: [PATCH 118/133] Fix chromium filename by defaulting mime to "application/octet-stream" --- public/scripts/network.js | 5 ++--- public/scripts/util.js | 5 +++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/public/scripts/network.js b/public/scripts/network.js index c92befc..4382597 100644 --- a/public/scripts/network.js +++ b/public/scripts/network.js @@ -1082,7 +1082,7 @@ class PeersManager { } async _onFilesSelected(message) { - let files = mime.addMissingMimeTypesToFiles(message.files); + let files = mime.addMissingMimeTypesToFiles([...message.files]); await this.peers[message.to].requestFileTransfer(files); } @@ -1306,9 +1306,8 @@ class FileDigester { const blob = new Blob(this._buffer) this._buffer = null; this._callback(new File([blob], this._name, { - type: this._mime, + type: this._mime || "application/octet-stream", lastModified: new Date().getTime() })); } - } diff --git a/public/scripts/util.js b/public/scripts/util.js index 1dcc388..24e2626 100644 --- a/public/scripts/util.js +++ b/public/scripts/util.js @@ -392,7 +392,8 @@ const mime = (() => { "vob": "video/x-ms-vob", "wmv": "video/x-ms-wmv", "avi": "video/x-msvideo", - "*": "video/x-sgi-movie" + "*": "video/x-sgi-movie", + "kdbx": "application/x-keepass2" } return { @@ -409,7 +410,7 @@ const mime = (() => { // if filetype is empty guess via suffix otherwise leave unchanged for (let i = 0; i < files.length; i++) { if (!files[i].type) { - files[i] = new File([files[i]], files[i].name, {type: mime.guessMimeByFilename(files[i].name) || ""}); + files[i] = new File([files[i]], files[i].name, {type: mime.guessMimeByFilename(files[i].name) || "application/octet-stream"}); } } return files; From 547038c9bca43a8281f422b902ed7885a439733d Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Mon, 17 Feb 2025 19:32:54 +0100 Subject: [PATCH 119/133] Fix file name display if no file extension is present --- public/scripts/ui.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/public/scripts/ui.js b/public/scripts/ui.js index cf4d014..25171ae 100644 --- a/public/scripts/ui.js +++ b/public/scripts/ui.js @@ -873,7 +873,9 @@ class ReceiveDialog extends Dialog { const fileName = files[0].name; const fileNameSplit = fileName.split('.'); - const fileExtension = '.' + fileNameSplit[fileNameSplit.length - 1]; + const fileExtension = fileNameSplit.length > 1 + ? '.' + fileNameSplit[fileNameSplit.length - 1] + : ''; this.$fileStem.innerText = fileName.substring(0, fileName.length - fileExtension.length); this.$fileExtension.innerText = fileExtension; this.$fileSize.innerText = this._formatFileSize(totalSize); From aa09da3076ac1ee610b5bd60c0b178a157f21d73 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Tue, 18 Feb 2025 13:34:01 +0100 Subject: [PATCH 120/133] Translated using Weblate (Japanese) Currently translated at 100.0% (166 of 166 strings) Co-authored-by: maboroshin Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/ja/ Translation: PairDrop/pairdrop-spa --- public/lang/ja.json | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/public/lang/ja.json b/public/lang/ja.json index 6184de8..d4e8fdb 100644 --- a/public/lang/ja.json +++ b/public/lang/ja.json @@ -12,7 +12,7 @@ "routed": "サーバーを経由します", "discovery": "このデバイスを検出可能なネットワーク:", "on-this-network_title": "このネットワーク上のすべてのデバイスからアクセスできます。", - "known-as": "他のデバイスに表示される名前:" + "known-as": "このデバイスの名前:" }, "notifications": { "request-title": "{{name}}は{{count}}個の{{descriptor}}を共有しようとしています", @@ -25,7 +25,7 @@ "connected": "接続しました", "pairing-not-persistent": "このデバイスとのペアリングは解除される可能性があります", "text-content-incorrect": "無効なテキスト内容です", - "message-transfer-completed": "メッセージの送信が完了しました", + "message-transfer-completed": "メッセージを送信しました", "file-transfer-completed": "ファイル転送が完了しました", "file-content-incorrect": "無効なファイル内容です", "files-incorrect": "ファイルが間違っています", @@ -59,7 +59,7 @@ }, "header": { "cancel-share-mode": "キャンセル", - "theme-auto_title": "システムテーマに合わせる", + "theme-auto_title": "システムのテーマに合わせる", "install_title": "PairDropをインストール", "theme-dark_title": "常にダークテーマを使用する", "pair-device_title": "他のデバイスとペアリングする", @@ -74,7 +74,7 @@ "expand_title": "ヘッダーボタン列を拡大する" }, "instructions": { - "x-instructions_mobile": "タップでファイルを送信、長押しでメッセージを送信します", + "x-instructions_mobile": "タップでファイル送信、長押しでメッセージ送信", "x-instructions-share-mode_desktop": "クリックして{{descriptor}}を送信", "activate-share-mode-and-other-files-plural": "とその他{{count}}個のファイル", "x-instructions-share-mode_mobile": "タップして{{descriptor}}を送信", @@ -82,7 +82,7 @@ "no-peers-subtitle": "ペアリングや公開ルームを使用すると、他のネットワーク上のデバイスと共有できます", "activate-share-mode-shared-text": "共有されたテキスト", "x-instructions_desktop": "左クリックでファイルを送信、右クリックでメッセージを送信します", - "no-peers-title": "ファイルを共有するには他のデバイスでPairDropを開いてください", + "no-peers-title": "ファイル共有するには他のデバイスでPairDropを開きます", "x-instructions_data-drop-peer": "ドロップするとこのデバイスに送信します", "x-instructions_data-drop-bg": "送信したいデバイスの上でドロップしてください", "no-peers_data-drop-bg": "送信したいデバイスの上でドロップしてください", @@ -103,7 +103,7 @@ "dialogs": { "base64-paste-to-send": "ここをタップして{{type}}を送信", "auto-accept-instructions-2": "」を有効にすると、そのデバイスから送信されたすべてのファイルを自動的に受け入れます。", - "receive-text-title": "メッセージを受信しました", + "receive-text-title": "メッセージを受信", "edit-paired-devices-title": "ペアリング設定", "cancel": "キャンセル", "auto-accept-instructions-1": "「", @@ -123,14 +123,14 @@ "file-other-description-image": "とその他1個の画像", "temporary-public-room-title": "公開ルーム", "base64-files": "ファイル", - "has-sent": "が送信しました:", + "has-sent": "が送信:", "file-other-description-file": "とその他1個のファイル", "close": "閉じる", "system-language": "システム言語", "unpair": "ペアリング解除", "title-image": "画像", "file-other-description-file-plural": "とその他{{count}}個のファイル", - "would-like-to-share": "が以下のファイルを共有しようとしています", + "would-like-to-share": "がこれを共有しています", "send-message-to": "このデバイスにメッセージを送信:", "language-selector-title": "言語設定", "pair": "ペアリング", @@ -174,8 +174,8 @@ "privacypolicy_title": "プライバシーポリシーを開く" }, "document-titles": { - "file-transfer-requested": "ファイルの転送がリクエストされました", - "image-transfer-requested": "画像の転送がリクエストされました", + "file-transfer-requested": "ファイル転送の要求があります", + "image-transfer-requested": "画像の転送の要求があります", "message-received-plural": "{{count}}個のメッセージを受信しました", "message-received": "メッセージを受信しました", "file-received": "ファイルを受信しました", From 341fa7fdf06b1caeeb538afe1f353c8f6ad30a2c Mon Sep 17 00:00:00 2001 From: Chris Lovett <57230137+realchrislovett@users.noreply.github.com> Date: Wed, 19 Feb 2025 05:46:00 -0500 Subject: [PATCH 121/133] Restore desktop Chrome PWA button (#383) * Restore desktop Chrome PWA button with start_url ./ --- public/manifest.json | 1 + 1 file changed, 1 insertion(+) diff --git a/public/manifest.json b/public/manifest.json index edcf69a..3cced84 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -26,6 +26,7 @@ } ], "background_color": "#efefef", + "start_url": "./", "display": "standalone", "theme_color": "#3367d6", "screenshots" : [ From c7b7badb3d65279a7902fc4f8c733d0c1516ca17 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Wed, 19 Feb 2025 12:24:41 +0100 Subject: [PATCH 122/133] Increase version to v1.11.1 ## Fixes - Fix PWA install button on chromium based browsers (#383) (Thanks @realchrislovett) - Fix wrong file extension on chromium based browsers if mime type is not set (#355) ## Languages - Translations updates from Hosted Weblate (Japanese) --- .github/ISSUE_TEMPLATE/bug-report.md | 4 ++-- docs/how-to.md | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- public/index.html | 2 +- public/service-worker.js | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index 5263696..6883691 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -36,7 +36,7 @@ If applicable, add screenshots to help explain your problem. **Bug occurs on official PairDrop instance https://pairdrop.net/** No | Yes -Version: v1.11.0 +Version: v1.11.1 **Bug occurs on self-hosted PairDrop instance** No | Yes @@ -44,7 +44,7 @@ No | Yes **Self-Hosted Setup** Proxy: Nginx | Apache2 Deployment: docker run | docker compose | npm run start:prod -Version: v1.11.0 +Version: v1.11.1 **Additional context** Add any other context about the problem here. diff --git a/docs/how-to.md b/docs/how-to.md index fcad02f..e1cb4da 100644 --- a/docs/how-to.md +++ b/docs/how-to.md @@ -45,11 +45,11 @@ This pairdrop-cli version was released alongside v1.10.4 #### Linux / Mac 1. Download the latest _pairdrop-cli.zip_ from the [releases page](https://github.com/schlagmichdoch/PairDrop/releases) ```shell - wget "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.11.0/pairdrop-cli.zip" + wget "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.11.1/pairdrop-cli.zip" ``` or ```shell - curl -LO "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.11.0/pairdrop-cli.zip" + curl -LO "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.11.1/pairdrop-cli.zip" ``` 2. Unzip the archive to a folder of your choice e.g. `/usr/share/pairdrop-cli/` ```shell diff --git a/package-lock.json b/package-lock.json index bdc9acd..0a2d466 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pairdrop", - "version": "1.11.0", + "version": "1.11.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pairdrop", - "version": "1.11.0", + "version": "1.11.1", "license": "ISC", "dependencies": { "express": "^4.18.2", diff --git a/package.json b/package.json index b36e5d7..7542a9b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pairdrop", - "version": "1.11.0", + "version": "1.11.1", "type": "module", "description": "", "main": "server/index.js", diff --git a/public/index.html b/public/index.html index 45df0e4..9ede262 100644 --- a/public/index.html +++ b/public/index.html @@ -668,7 +668,7 @@

PairDrop

-
v1.11.0
+
v1.11.1
diff --git a/public/service-worker.js b/public/service-worker.js index 551f25e..eb3601f 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -1,4 +1,4 @@ -const cacheVersion = 'v1.11.0'; +const cacheVersion = 'v1.11.1'; const cacheTitle = `pairdrop-cache-${cacheVersion}`; const forceFetch = false; // FOR DEVELOPMENT: Set to true to always update assets instead of using cached versions const relativePathsToCache = [ From b0b091c4f761f9e952d8cc065eff9efbd9b40de7 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Sun, 23 Feb 2025 19:13:44 +0100 Subject: [PATCH 123/133] FIX: switch off twitter button via env var not possible (#388) --- public/scripts/ui.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/scripts/ui.js b/public/scripts/ui.js index 25171ae..42da3bc 100644 --- a/public/scripts/ui.js +++ b/public/scripts/ui.js @@ -2404,7 +2404,7 @@ class Base64Dialog extends Dialog { class AboutUI { constructor() { this.$donationBtn = $('donation-btn'); - this.$twitterBtn = $('twitter-btn'); + this.$twitterBtn = $('x-twitter-btn'); this.$mastodonBtn = $('mastodon-btn'); this.$blueskyBtn = $('bluesky-btn'); this.$customBtn = $('custom-btn'); From 80615c533c7ed483c3913bdf19c0b10226e8fe78 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Sun, 23 Feb 2025 19:20:50 +0100 Subject: [PATCH 124/133] Update Bluesky icon from square to butterfly --- public/index.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/index.html b/public/index.html index 9ede262..6bdc88e 100644 --- a/public/index.html +++ b/public/index.html @@ -811,9 +811,9 @@ - - - + + + From 148eb79ef0c53877857a863d7de7bdccf7adaef8 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Mon, 24 Feb 2025 20:09:00 +0100 Subject: [PATCH 125/133] Fix alphabetical sort in supportedLocales --- public/scripts/localization.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/scripts/localization.js b/public/scripts/localization.js index ec915a5..5121d0c 100644 --- a/public/scripts/localization.js +++ b/public/scripts/localization.js @@ -5,7 +5,7 @@ class Localization { Localization.defaultLocale = "en"; Localization.supportedLocales = [ "ar", "be", "bg", "ca", "cs", "da", "de", "en", "es", "et", "eu", "fa", "fr", "he", "hu", "id", "it", "ja", - "kn", "ko", "nb", "nn", "nl", "pl", "pt-BR", "ro", "ru", "sk", "ta", "tr", "uk", "zh-CN", "zh-HK", "zh-TW" + "kn", "ko", "nb", "nl", "nn", "pl", "pt-BR", "ro", "ru", "sk", "ta", "tr", "uk", "zh-CN", "zh-HK", "zh-TW" ]; Localization.supportedLocalesRtl = ["ar", "he"]; From d7b68e214ed60ac078544dad96cc32d07c0a4a21 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Mon, 24 Feb 2025 20:17:54 +0100 Subject: [PATCH 126/133] Prevent fetch response and cache update if response is redirected --- public/service-worker.js | 86 +++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 37 deletions(-) diff --git a/public/service-worker.js b/public/service-worker.js index eb3601f..30c2007 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -1,6 +1,5 @@ const cacheVersion = 'v1.11.1'; const cacheTitle = `pairdrop-cache-${cacheVersion}`; -const forceFetch = false; // FOR DEVELOPMENT: Set to true to always update assets instead of using cached versions const relativePathsToCache = [ './', 'index.html', @@ -76,20 +75,25 @@ self.addEventListener('install', function(event) { const fromNetwork = (request, timeout) => new Promise((resolve, reject) => { const timeoutId = setTimeout(reject, timeout); - fetch(request) + fetch(request, {cache: "no-store"}) .then(response => { + if (response.redirected) { + throw new Error("Fetch is redirect. Abort usage and cache!"); + } + clearTimeout(timeoutId); resolve(response); + // Prevent requests that are in relativePathsNotToCache from being cached if (doNotCacheRequest(request)) return; - update(request) + updateCache(request) .then(() => console.log("Cache successfully updated for", request.url)) - .catch(reason => console.log("Cache could not be updated for", request.url, "Reason:", reason)); + .catch(err => console.log("Cache could not be updated for", request.url, err)); }) .catch(error => { // Handle any errors that occurred during the fetch - console.error(`Could not fetch ${request.url}. Are you online?`); + console.error(`Could not fetch ${request.url}.`); reject(error); }); }); @@ -111,16 +115,16 @@ const doNotCacheRequest = request => { }; // cache the current page to make it available for offline -const update = request => new Promise((resolve, reject) => { - if (doNotCacheRequest(request)) { - reject("Url is specifically prevented from being cached in the serviceworker."); - return; - } +const updateCache = request => new Promise((resolve, reject) => { caches .open(cacheTitle) .then(cache => fetch(request, {cache: "no-store"}) .then(response => { + if (response.redirected) { + throw new Error("Fetch is redirect. Abort usage and cache!"); + } + cache .put(request, response) .then(() => resolve()); @@ -129,9 +133,10 @@ const update = request => new Promise((resolve, reject) => { ); }); -// general strategy when making a request (eg if online try to fetch it -// from cache, if something fails fetch from network. Update cache everytime files are fetched. -// This way files should only be fetched if cacheVersion is changed +// general strategy when making a request: +// 1. Try to retrieve file from cache +// 2. If cache is not available: Fetch from network and update cache. +// This way, cached files are only updated if the cacheVersion is changed self.addEventListener('fetch', function(event) { if (event.request.method === "POST") { // Requests related to Web Share Target. @@ -141,39 +146,46 @@ self.addEventListener('fetch', function(event) { })()); } else { - // Regular requests not related to Web Share Target. - if (forceFetch) { - event.respondWith(fromNetwork(event.request, 10000)); - } - else { - event.respondWith( - fromCache(event.request) + // Regular requests not related to Web Share Target: + // If request is excluded from cache -> respondWith fromNetwork + // else -> try fromCache first + event.respondWith( + doNotCacheRequest(event.request) + ? fromNetwork(event.request, 10000) + : fromCache(event.request) .then(rsp => { // if fromCache resolves to undefined fetch from network instead - return rsp || fromNetwork(event.request, 10000); + if (!rsp) { + throw new Error("No match found."); + } + return rsp; }) - ); - } + .catch(error => { + console.error("Could not retrieve request from cache:", event.request.url, error); + return fromNetwork(event.request, 10000); + }) + ); } }); // on activation, we clean up the previously registered service workers self.addEventListener('activate', evt => { - return evt.waitUntil( - caches.keys() - .then(cacheNames => { - return Promise.all( - cacheNames.map(cacheName => { - if (cacheName !== cacheTitle) { - return caches.delete(cacheName); - } - }) - ); - }) - ) - } -); + return evt.waitUntil( + caches + .keys() + .then(cacheNames => { + return Promise.all( + cacheNames.map(cacheName => { + if (cacheName !== cacheTitle) { + console.log("Delete cache:", cacheName); + return caches.delete(cacheName); + } + }) + ); + }) + ) +}); const evaluateRequestData = function (request) { return new Promise(async (resolve) => { From d18e290ad42f6a4d83d0c251a8fda07f4b901382 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Mon, 24 Feb 2025 20:18:53 +0100 Subject: [PATCH 127/133] Add missing files to paths that get cached upon sw installation --- public/service-worker.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/public/service-worker.js b/public/service-worker.js index 30c2007..12ca3c1 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -6,6 +6,7 @@ const relativePathsToCache = [ 'manifest.json', 'styles/styles-main.css', 'styles/styles-deferred.css', + 'scripts/browser-tabs-connector.js', 'scripts/localization.js', 'scripts/main.js', 'scripts/network.js', @@ -27,14 +28,19 @@ const relativePathsToCache = [ 'images/android-chrome-512x512.png', 'images/android-chrome-512x512-maskable.png', 'images/apple-touch-icon.png', + 'fonts/OpenSans/static/OpenSans-Medium.ttf', 'lang/ar.json', 'lang/be.json', + 'lang/bg.json', 'lang/ca.json', 'lang/cs.json', 'lang/da.json', 'lang/de.json', 'lang/en.json', 'lang/es.json', + 'lang/et.json', + 'lang/eu.json', + 'lang/fa.json', 'lang/fr.json', 'lang/he.json', 'lang/hu.json', @@ -42,15 +48,20 @@ const relativePathsToCache = [ 'lang/it.json', 'lang/ja.json', 'lang/kn.json', + 'lang/ko.json', 'lang/nb.json', 'lang/nl.json', + 'lang/nn.json', 'lang/pl.json', 'lang/pt-BR.json', 'lang/ro.json', 'lang/ru.json', + 'lang/sk.json', + 'lang/ta.json', 'lang/tr.json', 'lang/uk.json', 'lang/zh-CN.json', + 'lang/zh-HK.json', 'lang/zh-TW.json' ]; const relativePathsNotToCache = [ From dbd6321fecee8639992b2b6724176721ed436103 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Mon, 24 Feb 2025 20:21:16 +0100 Subject: [PATCH 128/133] Speed up update process by skipping waiting and claiming currently open pages -> no need to close all tabs in order to get an update anymore --- public/service-worker.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/public/service-worker.js b/public/service-worker.js index 12ca3c1..ad5e7ea 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -69,14 +69,16 @@ const relativePathsNotToCache = [ ] self.addEventListener('install', function(event) { - // Perform install steps + // Perform install steps + console.log("Cache files for sw:", cacheVersion); event.waitUntil( caches.open(cacheTitle) .then(function(cache) { return cache .addAll(relativePathsToCache) .then(_ => { - console.log('All files cached.'); + console.log('All files cached for sw:', cacheVersion); + self.skipWaiting(); }); }) ); @@ -182,6 +184,8 @@ self.addEventListener('fetch', function(event) { // on activation, we clean up the previously registered service workers self.addEventListener('activate', evt => { + console.log("Activate sw:", cacheVersion); + evt.waitUntil(clients.claim()); return evt.waitUntil( caches .keys() From abd3a0c47c5c4346e17d80267e205024cc5a01e9 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 24 Feb 2025 03:01:56 +0100 Subject: [PATCH 129/133] Translated using Weblate (Bengali) Currently translated at 17.4% (29 of 166 strings) Co-authored-by: Hosted Weblate Co-authored-by: Saif Mahmud Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/bn/ Translation: PairDrop/pairdrop-spa --- public/lang/bn.json | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/public/lang/bn.json b/public/lang/bn.json index 4f3f52a..1795d97 100644 --- a/public/lang/bn.json +++ b/public/lang/bn.json @@ -1,6 +1,35 @@ { "header": { "about_title": "পেয়ার ড্রপ সম্পর্কে", - "install_title": "পেয়ার ড্রপ ইন্সটল করুন" + "install_title": "পেয়ার ড্রপ ইন্সটল করুন", + "pair-device_title": "ডিভাইস স্থায়ী ভাবে যুক্ত করুন", + "cancel-share-mode": "বাতিল", + "theme-light_title": "সবসময় সাদা থিম ব্যাবহার", + "language-selector_title": "ভাষা সেট করুন", + "about_aria-label": "পেয়ারড্রপ সম্পর্কে", + "theme-auto_title": "থিমের ধরন ডিভাইস অনুযায়ী", + "theme-dark_title": "সবসময় কালো থিব ব্যাবহার", + "notification_title": "নোটিফিকেশন চালু করুন", + "edit-paired-devices_title": "যুক্ত ডিভাইস সম্পাদনা করুন", + "join-public-room_title": "সাময়িক ভাবে পাবলিক রুমে জয়েন করুন", + "edit-share-mode": "সম্পাদনা", + "expand_title": "হেডার বোতামের সারিটি বড় করুন" + }, + "instructions": { + "activate-share-mode-and-other-file": "আর একটি ফাইল যোগ করুন", + "activate-share-mode-shared-file": "পাঠানো ফাইল", + "no-peers-subtitle": "ডিভাইস প্রদর্শিত হতে নতুন ডিভাইস যুক্ত করুন অথবা পাবলিক রুমে জয়েন দিন", + "no-peers-title": "ফাইল পাঠানোর জন্য অন্যান্য ডিভাইসে পেয়ারড্রপ খুলুন", + "x-instructions_data-drop-bg": "প্রাপক নির্বাচন করতে ছেড়ে দিন", + "no-peers_data-drop-bg": "প্রাপক নির্বাচন ছেড়ে দিন", + "x-instructions_desktop": "ফাইল পাঠাতে ক্লিক করুন অথবা মেসেজ পাঠাতে ডানে চাপুন", + "x-instructions_mobile": "ফাইল পাঠাতে ক্লিক করুন অথবা বেশি চেপে মেসেজ পাঠান", + "x-instructions_data-drop-peer": "পিয়ারকে পাঠানোর জন্য রিলিজ করুন", + "x-instructions-share-mode_desktop": "পাঠাতে ক্লিক করুন", + "x-instructions-share-mode_mobile": "পাঠাতে ক্লিক করুন", + "activate-share-mode-base": "অন্য ডিভাইসে পাঠাতে পেয়ারড্রপ খুলুন", + "activate-share-mode-and-other-files-plural": "অন্য ফাইল যোগ করুন", + "activate-share-mode-shared-text": "পাঠানো টেক্সট", + "activate-share-mode-shared-files-plural": "পাঠানো ফাইল গুলো" } } From f6f3db2df96276a10528ffa141513b11ebba592e Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 24 Feb 2025 03:01:56 +0100 Subject: [PATCH 130/133] Translated using Weblate (Japanese) Currently translated at 100.0% (166 of 166 strings) Translated using Weblate (Japanese) Currently translated at 100.0% (166 of 166 strings) Translated using Weblate (Japanese) Currently translated at 100.0% (166 of 166 strings) Translated using Weblate (Japanese) Currently translated at 100.0% (166 of 166 strings) Co-authored-by: Hosted Weblate Co-authored-by: maboroshin Co-authored-by: mottcha <89951503+mottcha@users.noreply.github.com> Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/ja/ Translation: PairDrop/pairdrop-spa --- public/lang/ja.json | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/public/lang/ja.json b/public/lang/ja.json index d4e8fdb..949621a 100644 --- a/public/lang/ja.json +++ b/public/lang/ja.json @@ -1,17 +1,17 @@ { "footer": { "webrtc": "(WebRTCが無効なため)", - "public-room-devices_title": "公開ルーム内のデバイスは、接続中のネットワークと関係なくアクセスできます。", + "public-room-devices_title": "公開ルーム内のデバイスは、別のネットワークからもアクセスできます。", "display-name_data-placeholder": "読み込み中…", "display-name_title": "デバイス名を変更する", "traffic": "この通信は", - "paired-devices_title": "ペアリング済みデバイスであれば、接続中のネットワークに関わらずアクセスできます。", + "paired-devices_title": "ペアリング済みデバイスは、別のネットワークからもアクセスできます。", "public-room-devices": "ルーム{{roomId}}", "paired-devices": "ペアリング済みデバイス", - "on-this-network": "このネットワーク上", + "on-this-network": "このネットワーク内", "routed": "サーバーを経由します", "discovery": "このデバイスを検出可能なネットワーク:", - "on-this-network_title": "このネットワーク上のすべてのデバイスからアクセスできます。", + "on-this-network_title": "このネットワーク内のすべてのデバイスからアクセスできます。", "known-as": "このデバイスの名前:" }, "notifications": { @@ -20,9 +20,9 @@ "message-received": "{{name}}から受信したメッセージ(クリックしてコピー)", "rate-limit-join-key": "レート制限に到達しました。10秒待ってから再度お試しください。", "connecting": "接続中…", - "pairing-key-invalidated": "コード{{key}}が失効しました", + "pairing-key-invalidated": "コード{{key}}は無効になりました", "pairing-key-invalid": "無効なコード", - "connected": "接続しました", + "connected": "接続済み", "pairing-not-persistent": "このデバイスとのペアリングは解除される可能性があります", "text-content-incorrect": "無効なテキスト内容です", "message-transfer-completed": "メッセージを送信しました", @@ -39,7 +39,7 @@ "copied-to-clipboard-error": "コピーできませんでした。手動でコピーしてください。", "pairing-success": "ペアリングしました", "clipboard-content-incorrect": "無効なクリップボード内容です", - "display-name-changed-temporarily": "この接続のみデバイス名が変更されました", + "display-name-changed-temporarily": "この接続でのみデバイス名が変更されました", "copied-to-clipboard": "クリップボードにコピーしました", "offline": "オフラインです", "pairing-tabs-error": "同じWebブラウザーで開いたタブ同士でペアリングすることはできません", @@ -79,9 +79,9 @@ "activate-share-mode-and-other-files-plural": "とその他{{count}}個のファイル", "x-instructions-share-mode_mobile": "タップして{{descriptor}}を送信", "activate-share-mode-base": "他のデバイスでPairDropを開いて送信します", - "no-peers-subtitle": "ペアリングや公開ルームを使用すると、他のネットワーク上のデバイスと共有できます", + "no-peers-subtitle": "ペアリングや公開ルームを使うと、別のネットワークにあるデバイスと共有できます", "activate-share-mode-shared-text": "共有されたテキスト", - "x-instructions_desktop": "左クリックでファイルを送信、右クリックでメッセージを送信します", + "x-instructions_desktop": "左クリックでファイル送信、右クリックでメッセージ送信", "no-peers-title": "ファイル共有するには他のデバイスでPairDropを開きます", "x-instructions_data-drop-peer": "ドロップするとこのデバイスに送信します", "x-instructions_data-drop-bg": "送信したいデバイスの上でドロップしてください", @@ -94,7 +94,7 @@ "peer-ui": { "processing": "処理中…", "click-to-send-share-mode": "クリックして{{descriptor}}を送信", - "click-to-send": "左クリックでファイルを送信、右クリックでメッセージを送信します", + "click-to-send": "左クリックでファイル送信、右クリックでメッセージ送信", "waiting": "待機中…", "connection-hash": "エンドツーエンド暗号化のセキュリティを確認するには、両方のデバイスのセキュリティナンバーを確認してください", "preparing": "準備中…", @@ -102,7 +102,7 @@ }, "dialogs": { "base64-paste-to-send": "ここをタップして{{type}}を送信", - "auto-accept-instructions-2": "」を有効にすると、そのデバイスから送信されたすべてのファイルを自動的に受け入れます。", + "auto-accept-instructions-2": "」が有効なら、そのデバイスが送信したすべてのファイルを自動で受け入れます。", "receive-text-title": "メッセージを受信", "edit-paired-devices-title": "ペアリング設定", "cancel": "キャンセル", @@ -126,7 +126,7 @@ "has-sent": "が送信:", "file-other-description-file": "とその他1個のファイル", "close": "閉じる", - "system-language": "システム言語", + "system-language": "システムの言語", "unpair": "ペアリング解除", "title-image": "画像", "file-other-description-file-plural": "とその他{{count}}個のファイル", @@ -135,7 +135,7 @@ "language-selector-title": "言語設定", "pair": "ペアリング", "hr-or": "または", - "scan-qr-code": "もしくはQRコードをスキャンしてください。", + "scan-qr-code": "QRコードをスキャンしてください。", "input-key-on-this-device": "このコードを他のデバイスに入力するか", "download-again": "もう一度ダウンロードする", "accept": "承諾", @@ -162,13 +162,13 @@ "share-text-title": "テキストメッセージを共有します" }, "about": { - "claim": "デバイス間のファイル共有を手軽に実現します", - "tweet_title": "PairDropのことをポストする", + "claim": "デバイス間でかんたんファイル共有", + "tweet_title": "PairDropについてポスト", "close-about_aria-label": "PairDropについてを閉じる", "buy-me-a-coffee_title": "コーヒーを一杯おごってください!", - "github_title": "PairDrop on GitHub", + "github_title": "GitHub上のPairDropプロジェクト", "faq_title": "FAQ", - "mastodon_title": "MastodonにPairDropのことをトゥートする", + "mastodon_title": "MastodonでPairDropについてトゥート", "bluesky_title": "BlueSkyでフォロー", "custom_title": "フォロー", "privacypolicy_title": "プライバシーポリシーを開く" From 7639aca84c0fb2400a970844d658571aedf4050f Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Mon, 24 Feb 2025 20:45:12 +0100 Subject: [PATCH 131/133] Update node dependencies --- package-lock.json | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0a2d466..7d76ba5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -318,16 +318,16 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", - "integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", + "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", - "get-proto": "^1.0.0", + "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", @@ -815,9 +815,9 @@ } }, "node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==", "engines": { "node": ">=10.0.0" }, From 4862ba3067be1a0f2e0d1e94861dc9200b5bfeea Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Mon, 24 Feb 2025 20:46:32 +0100 Subject: [PATCH 132/133] Increase version to v1.11.2 ## Enhancements - Speed up update process by skipping waiting and claiming currently open pages -> no need to close all tabs in order to get an update anymore - Update Bluesky icon from square to butterfly - Update node dependencies ## Fixes - Prevent service-worker from responding with redirect (fixes #384) - Fix: switch off twitter button via env var not possible (#388) - Add missing files to paths that get cached upon sw installation ## Languages - Translations updates from Hosted Weblate (Japanese) --- .github/ISSUE_TEMPLATE/bug-report.md | 4 ++-- docs/how-to.md | 4 ++-- package-lock.json | 4 ++-- package.json | 2 +- public/index.html | 2 +- public/service-worker.js | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug-report.md b/.github/ISSUE_TEMPLATE/bug-report.md index 6883691..5abfbb4 100644 --- a/.github/ISSUE_TEMPLATE/bug-report.md +++ b/.github/ISSUE_TEMPLATE/bug-report.md @@ -36,7 +36,7 @@ If applicable, add screenshots to help explain your problem. **Bug occurs on official PairDrop instance https://pairdrop.net/** No | Yes -Version: v1.11.1 +Version: v1.11.2 **Bug occurs on self-hosted PairDrop instance** No | Yes @@ -44,7 +44,7 @@ No | Yes **Self-Hosted Setup** Proxy: Nginx | Apache2 Deployment: docker run | docker compose | npm run start:prod -Version: v1.11.1 +Version: v1.11.2 **Additional context** Add any other context about the problem here. diff --git a/docs/how-to.md b/docs/how-to.md index e1cb4da..df6d3a1 100644 --- a/docs/how-to.md +++ b/docs/how-to.md @@ -45,11 +45,11 @@ This pairdrop-cli version was released alongside v1.10.4 #### Linux / Mac 1. Download the latest _pairdrop-cli.zip_ from the [releases page](https://github.com/schlagmichdoch/PairDrop/releases) ```shell - wget "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.11.1/pairdrop-cli.zip" + wget "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.11.2/pairdrop-cli.zip" ``` or ```shell - curl -LO "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.11.1/pairdrop-cli.zip" + curl -LO "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.11.2/pairdrop-cli.zip" ``` 2. Unzip the archive to a folder of your choice e.g. `/usr/share/pairdrop-cli/` ```shell diff --git a/package-lock.json b/package-lock.json index 7d76ba5..be60a08 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "pairdrop", - "version": "1.11.1", + "version": "1.11.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "pairdrop", - "version": "1.11.1", + "version": "1.11.2", "license": "ISC", "dependencies": { "express": "^4.18.2", diff --git a/package.json b/package.json index 7542a9b..e4032f6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "pairdrop", - "version": "1.11.1", + "version": "1.11.2", "type": "module", "description": "", "main": "server/index.js", diff --git a/public/index.html b/public/index.html index 6bdc88e..70eda5b 100644 --- a/public/index.html +++ b/public/index.html @@ -668,7 +668,7 @@

PairDrop

-
v1.11.1
+
v1.11.2
diff --git a/public/service-worker.js b/public/service-worker.js index ad5e7ea..47822ae 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -1,4 +1,4 @@ -const cacheVersion = 'v1.11.1'; +const cacheVersion = 'v1.11.2'; const cacheTitle = `pairdrop-cache-${cacheVersion}`; const relativePathsToCache = [ './', From 31ec776fb304fd7ddf0eeffba41b1631f712887b Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Tue, 25 Feb 2025 18:19:38 +0100 Subject: [PATCH 133/133] Only handle requests with the same origin via the service worker --- public/service-worker.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/public/service-worker.js b/public/service-worker.js index 47822ae..e1f4f45 100644 --- a/public/service-worker.js +++ b/public/service-worker.js @@ -151,7 +151,14 @@ const updateCache = request => new Promise((resolve, reject) => { // 2. If cache is not available: Fetch from network and update cache. // This way, cached files are only updated if the cacheVersion is changed self.addEventListener('fetch', function(event) { - if (event.request.method === "POST") { + const swOrigin = new URL(self.location.href).origin; + const requestOrigin = new URL(event.request.url).origin; + + if (swOrigin !== requestOrigin) { + // Do not handle requests from other origin + event.respondWith(fetch(event.request)); + } + else if (event.request.method === "POST") { // Requests related to Web Share Target. event.respondWith((async () => { const share_url = await evaluateRequestData(event.request);