From 488762bbce23630a277e781f27ae4dcdf57ba88e Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Thu, 18 Apr 2024 22:26:27 +0200 Subject: [PATCH 001/111] Update faq.md Co-authored-by: babstar99 --- docs/faq.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index 76d82b0..90eed40 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -165,7 +165,7 @@ you can [start the PairDrop instance with an activated WebSocket fallback](https 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). +If curious, study [the signaling server](https://github.com/schlagmichdoch/PairDrop/blob/master/server/ws-server.js). WebRTC encrypts the files in transit. If the devices are on the same network, @@ -188,9 +188,8 @@ to learn more about STUN, TURN and WebRTC.
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. +Still you have to trust the PairDrop server. To ensure the connection is secure and there is no [MITM](https://wikiless.org/wiki/Man-in-the-middle_attack) there is a plan to make PairDrop +zero trust by encrypting the signaling and implementing a verification process. See [issue #180](https://github.com/schlagmichdoch/PairDrop/issues/180) to keep updated.
From 78d9ba45d39a63d37e63bbaffbff15e31276c2ce Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 1 Jul 2024 18:33:00 +0200 Subject: [PATCH 002/111] Translated using Weblate (Turkish) Currently translated at 0.0% (0 of 166 strings) Translated using Weblate (Turkish) Currently translated at 82.5% (137 of 166 strings) Co-authored-by: Enhar Ukalo Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/tr/ Translation: PairDrop/pairdrop-spa --- public/lang/tr.json | 190 ++++++++++++++++++++++---------------------- 1 file changed, 95 insertions(+), 95 deletions(-) diff --git a/public/lang/tr.json b/public/lang/tr.json index dce1d1d..ab9c121 100644 --- a/public/lang/tr.json +++ b/public/lang/tr.json @@ -1,163 +1,163 @@ { "header": { "about_title": "PairDrop Hakkında", - "about_aria-label": "PairDrop Hakkındayı Aç", - "theme-auto_title": "Temayı sisteme uyarla", - "theme-light_title": "Daima açık tema kullan", - "theme-dark_title": "Daima koyu tema kullan", + "about_aria-label": "PairDrop Hakkında'yı Aç", + "theme-auto_title": "Temayı sisteme otomatik olarak adapte et", + "theme-light_title": "Her zaman açık temayı kullan", + "theme-dark_title": "Her zaman koyu temayı kullan", "notification_title": "Bildirimleri etkinleştir", "install_title": "PairDrop'u Yükle", - "pair-device_title": "Cihazı kalıcı olarak eşle", - "edit-paired-devices_title": "Eşleştirilmiş cihazları düzenle", - "cancel-share-mode": "Bitti", - "join-public-room_title": "Geçici olarak genel odaya katılın", - "language-selector_title": "Dili Seç", + "pair-device_title": "Cihazlarınızı kalıcı olarak eşleştirin", + "edit-paired-devices_title": "Eşleşmiş cihazları düzenle", + "cancel-share-mode": "İptal Et", + "join-public-room_title": "Geçici olarak ortak odaya katıl", + "language-selector_title": "Dili Ayarla", "edit-share-mode": "Düzenle", - "expand_title": "Başlık düğmesi satırını genişlet" + "expand_title": "Başlık buton satırını genişlet" }, "instructions": { "no-peers_data-drop-bg": "Alıcıyı seçmek için bırakın", - "x-instructions_mobile": "Dosya göndermek için dokun veya mesaj göndermek için uzun dokun", - "x-instructions-share-mode_desktop": "{{descriptor}} kişisine göndermek için tıkla", + "x-instructions_mobile": "Dosya göndermek için dokunun veya mesaj göndermek için uzun dokunun", + "x-instructions-share-mode_desktop": "{{descriptor}} göndermek için tıklayın", "activate-share-mode-and-other-files-plural": "ve {{count}} diğer dosya", - "x-instructions-share-mode_mobile": "{{descriptor}} kişisine göndermek için dokun", + "x-instructions-share-mode_mobile": "{{descriptor}} göndermek için dokunun", "activate-share-mode-base": "Göndermek için diğer cihazlarda PairDrop'u açın", - "no-peers-subtitle": "Diğer ağlarda keşfedilebilir olmak için cihazları eşleştirin veya ortak bir odaya girin", + "no-peers-subtitle": "Cihazları eşleştirin veya keşfedilebilir olmak için ortak bir odaya girin", "activate-share-mode-shared-text": "paylaşılan metin", - "x-instructions_desktop": "Dosya göndermek için tıkla veya mesaj göndermek için sağ tıkla", + "x-instructions_desktop": "Dosya göndermek için tıklayın veya mesaj göndermek için sağ tıklayın", "no-peers-title": "Dosya göndermek için diğer cihazlarda PairDrop'u açın", - "x-instructions_data-drop-peer": "Göndermek için serbest bırak", + "x-instructions_data-drop-peer": "Eşleştiriciye göndermek için bırakın", "x-instructions_data-drop-bg": "Alıcıyı seçmek için bırakın", - "webrtc-requirement": "Bu PairDrop örneğini kullanmak için WebRTC etkinleştirilmelidir!", - "activate-share-mode-shared-files-plural": "{{count}} adet paylaşılan dosya", + "webrtc-requirement": "Bu PairDrop örneğini kullanmak için WebRTC etkin olmalı!", + "activate-share-mode-shared-files-plural": "{{count}} paylaşılan dosya", "activate-share-mode-shared-file": "paylaşılan dosya", - "activate-share-mode-and-other-file": "ve 1 dosya" + "activate-share-mode-and-other-file": "ve 1 diğer dosya" }, "footer": { "display-name_data-placeholder": "Yükleniyor…", - "display-name_title": "Cihazının adını kalıcı olarak düzenle", + "display-name_title": "Cihaz adınızı kalıcı olarak düzenleyin", "webrtc": "WebRTC mevcut değilse.", - "public-room-devices_title": "Genel odada ağdan bağımsız olarak cihazlar tarafından keşfedilebilirsiniz.", + "public-room-devices_title": "Ağdan bağımsız olarak bu ortak odadaki cihazlar tarafından keşfedilebilir olabilirsiniz.", "traffic": "Trafik", - "paired-devices_title": "Eşleştirilmiş cihazlarda ağdan bağımsız olarak her zaman keşfedilebilirsiniz.", - "public-room-devices": "{{roomId}} odası", + "paired-devices_title": "Ağdan bağımsız olarak her zaman eşleştirilmiş cihazlar tarafından keşfedilebilir olabilirsiniz.", + "public-room-devices": "{{roomId}} odasında", "paired-devices": "eşleştirilmiş cihazlar tarafından", - "on-this-network": "bu ağ üzerinde", - "routed": "sunucu üzerinden yönlendirilir", - "discovery": "Keşfedilebilirsin:", - "on-this-network_title": "Bu ağdaki herkes tarafından keşfedilebilirsiniz.", - "known-as": "Bilinen adın:" + "on-this-network": "bu ağda", + "routed": "sunucu üzerinden yönlendirilmiş", + "discovery": "Keşfedilebilir durumdasınız:", + "on-this-network_title": "Bu ağdaki herkes tarafından keşfedilebilir olabilirsiniz.", + "known-as": "Şu adla biliniyorsunuz:" }, "dialogs": { "cancel": "İptal", - "edit-paired-devices-title": "Eşleştirilmiş Cihazları Düzenle", - "base64-paste-to-send": "{{type}} paylaşmak için buraya yapıştır", - "auto-accept-instructions-2": "böylelikle cihazdan gönderilen tüm dosyaları otomatik olarak kabul eder.", + "edit-paired-devices-title": "Eşleşmiş Cihazları Düzenle", + "base64-paste-to-send": "{{type}} paylaşmak için buraya yapıştırın", + "auto-accept-instructions-2": "bu cihazdan gönderilen tüm dosyaları otomatik olarak kabul etmek için.", "receive-text-title": "Mesaj Alındı", - "auto-accept-instructions-1": "Etkinleştir", - "pair-devices-title": "Cihazları Kalıcı Eşleştir", + "auto-accept-instructions-1": "Aktive et", + "pair-devices-title": "Cihazları Kalıcı Olarak Eşleştir", "download": "İndir", "title-file": "Dosya", "base64-processing": "İşleniyor…", "decline": "Reddet", "receive-title": "{{descriptor}} Alındı", "leave": "Ayrıl", - "message_title": "Göndermek için mesaj girin", + "message_title": "Göndermek için mesaj ekle", "join": "Katıl", "title-image-plural": "Resimler", "send": "Gönder", - "base64-tap-to-paste": "{{type}} paylaşmak için buraya dokun", + "base64-tap-to-paste": "{{type}} paylaşmak için buraya dokunun", "base64-text": "metin", "copy": "Kopyala", "file-other-description-image": "ve 1 diğer resim", - "pair-devices-qr-code_title": "Bu cihazı eşleştirmek üzere bağlantıyı kopyalamak için tıklayın", - "temporary-public-room-title": "Geçici Genel Oda", + "pair-devices-qr-code_title": "Bu cihazı eşleştirmek için bağlantıyı kopyalamak için tıklayın", + "temporary-public-room-title": "Geçici Ortak Oda", "base64-files": "dosyalar", "has-sent": "gönderdi:", "file-other-description-file": "ve 1 diğer dosya", - "public-room-qr-code_title": "Genel odanın bağlantı linkini kopyalamak için tıkla", + "public-room-qr-code_title": "Ortak oda bağlantısını kopyalamak için tıklayın", "close": "Kapat", "system-language": "Sistem Dili", - "unpair": "Eşlemeyi Kaldır", + "unpair": "Eşleşmeyi Kaldır", "title-image": "Resim", "file-other-description-file-plural": "ve {{count}} diğer dosya", "would-like-to-share": "paylaşmak istiyor", - "send-message-to": "Kime:", - "language-selector-title": "Dili Seç", - "pair": "Eşle", + "send-message-to": "Alıcı:", + "language-selector-title": "Dili Ayarla", + "pair": "Eşleştir", "hr-or": "VEYA", "scan-qr-code": "veya QR kodunu tarayın.", - "input-key-on-this-device": "Bu anahtarı başka bir cihazda girin", + "input-key-on-this-device": "Bu anahtarı başka bir cihaza girin", "download-again": "Tekrar indir", "accept": "Kabul Et", - "paired-devices-wrapper_data-empty": "Eşlenmiş cihaz yok.", - "enter-key-from-another-device": "Buraya başka bir cihazdan anahtar girin.", + "paired-devices-wrapper_data-empty": "Eşleşmiş cihaz yok.", + "enter-key-from-another-device": "Başka bir cihazdan alınan anahtarı buraya girin.", "share": "Paylaş", - "auto-accept": "otomatik-kabul", + "auto-accept": "otomatik kabul", "title-file-plural": "Dosyalar", "send-message-title": "Mesaj Gönder", - "input-room-id-on-another-device": "Bu ID'yi diğer cihaza girin", + "input-room-id-on-another-device": "Bu oda kimliğini başka bir cihaza girin", "file-other-description-image-plural": "ve {{count}} diğer resim", - "enter-room-id-from-another-device": "Odaya katılmak için diğer cihazın ID'sini girin.", + "enter-room-id-from-another-device": "Odaya katılmak için başka bir cihazdan oda kimliğini girin.", "message_placeholder": "Metin", - "close-toast_title": "Bildirimleri kapat", - "share-text-checkbox": "Metin paylaşırken her zaman bu pencereyi göster", + "close-toast_title": "Bildirim kapat", + "share-text-checkbox": "Metin paylaşırken her zaman bu iletişim kutusunu göster", "base64-title-files": "Dosyaları Paylaş", "approve": "onayla", - "paired-device-removed": "Eşleştirilmiş cihaz kaldırıldı.", - "share-text-title": "Kısa Mesaj Paylaş", - "share-text-subtitle": "Göndermeden önce mesajı düzenle:", - "base64-title-text": "Metin Paylaş" + "paired-device-removed": "Eşleşmiş cihaz kaldırıldı.", + "share-text-title": "Metin Mesajı Paylaş", + "share-text-subtitle": "Göndermeden önce mesajı düzenleyin:", + "base64-title-text": "Metni Paylaş" }, "notifications": { "request-title": "{{name}} {{count}} {{descriptor}} transfer etmek istiyor", - "unfinished-transfers-warning": "Bitmemiş transferler var. PairDrop'u kapatmak istediğinize emin misiniz?", - "message-received": "Mesaj {{name}} tarafından alındı - Kopyalamak için tıkla", - "notifications-permissions-error": "Kullanıcı izin isteğini birkaç kez reddettiği için bildirimler engellenmiştir. URL çubuğunun yanındaki kilit simgesine tıklayarak sıfırlanabilir.", - "rate-limit-join-key": "İstek sınırına ulaşıldı. 10 saniye bekleyin ve tekrar deneyin.", - "pair-url-copied-to-clipboard": "Bu cihazı eşleştirmek için bağlantı linki panoya kopyalandı", - "connecting": "Bağlanılıyor…", - "pairing-key-invalidated": "{{key}} anahtarı geçersiz", + "unfinished-transfers-warning": "Tamamlanmamış transferler var. PairDrop'u kapatmak istediğinizden emin misiniz?", + "message-received": "{{name}} tarafından mesaj alındı - Kopyalamak için tıklayın", + "notifications-permissions-error": "Bildirim izinleri birkaç kez reddedildiği için engellendi. Bu, URL çubuğunun yanındaki kilit simgesine tıklayarak erişilebilen Sayfa Bilgilerinde sıfırlanabilir.", + "rate-limit-join-key": "Hız sınırına ulaşıldı. 10 saniye bekleyin ve tekrar deneyin.", + "pair-url-copied-to-clipboard": "Bu cihazı eşleştirmek için bağlantı panoya kopyalandı", + "connecting": "Bağlanıyor…", + "pairing-key-invalidated": "Anahtar {{key}} geçersiz kılındı", "pairing-key-invalid": "Geçersiz anahtar", - "connected": "Bağlandı", - "pairing-not-persistent": "Eşleştirilmiş cihazlar kalıcı değildir", - "text-content-incorrect": "Metin içeriği yanlış", + "connected": "Bağlı", + "pairing-not-persistent": "Eşleşmiş cihazlar kalıcı değil", + "text-content-incorrect": "Metin içeriği hatalı", "message-transfer-completed": "Mesaj transferi tamamlandı", - "file-transfer-completed": "Dosya transferi bitti", - "file-content-incorrect": "Dosya içeriği yanlış", - "files-incorrect": "Dosyalar yanlış", - "selected-peer-left": "Seçili aygıt ayrıldı", - "link-received": "Link {{name}} tarafından alındı - Açmak için tıkla", - "online": "Tekrar çevrimiçisin", - "public-room-left": "{{publicRoomId}} genel odasından ayrıldın", + "file-transfer-completed": "Dosya transferi tamamlandı", + "file-content-incorrect": "Dosya içeriği hatalı", + "files-incorrect": "Dosyalar hatalı", + "selected-peer-left": "Seçilen eş ayrıldı", + "link-received": "{{name}} tarafından bağlantı alındı - Açmak için tıklayın", + "online": "Tekrar çevrimiçisiniz", + "public-room-left": "Ortak odadan ayrıldı {{publicRoomId}}", "copied-text": "Metin panoya kopyalandı", - "display-name-random-again": "Mevcut adın tekrardan rastgele oluşturuldu", - "display-name-changed-permanently": "Mevcut adın kalıcı olarak değiştirildi", - "copied-to-clipboard-error": "Kopyalama mümkün değil. Manuel olarak kopyalayın.", + "display-name-random-again": "Görünen ad tekrar rastgele oluşturuldu", + "display-name-changed-permanently": "Görünen ad kalıcı olarak değiştirildi", + "copied-to-clipboard-error": "Kopyalama mümkün değil. Elle kopyalayın.", "pairing-success": "Cihazlar eşleştirildi", - "clipboard-content-incorrect": "Pano içeriği yanlış", - "display-name-changed-temporarily": "Mevcut adın yalnızca bu oturum için değiştirildi", + "clipboard-content-incorrect": "Panodaki içerik hatalı", + "display-name-changed-temporarily": "Görünen ad sadece bu oturum için değiştirildi", "copied-to-clipboard": "Panoya kopyalandı", - "offline": "Çevrimdışısın", - "pairing-tabs-error": "İki web tarayıcı sekmesini eşleştirmek mümkün değildir", - "public-room-id-invalid": "Geçersiz oda ID'si", - "click-to-download": "İndirmek için tıkla", - "pairing-cleared": "Tüm cihazlar eşleştirmeden çıkarıldı", + "offline": "Çevrimdışısınız", + "pairing-tabs-error": "İki web tarayıcı sekmesini eşleştirmek imkansız", + "public-room-id-invalid": "Geçersiz oda kimliği", + "click-to-download": "İndirmek için tıklayın", + "pairing-cleared": "Tüm cihazların eşleşmesi kaldırıldı", "notifications-enabled": "Bildirimler etkinleştirildi", - "online-requirement-pairing": "Cihazları eşleştirmek için çevrimiçi olmanız lazım", - "ios-memory-limit": "iOS'a tek seferde sadece 200MB'a kadar dosya gönderebilirsin", - "online-requirement-public-room": "Genel oda oluşturmak için çevrimiçi olmanız lazım", - "room-url-copied-to-clipboard": "Genel oda bağlantı linki panoya kopyalandı", - "copied-text-error": "Panoya kopyalanamadı. Lütfen manuel olarak kopyalayın!", + "online-requirement-pairing": "Cihazları eşleştirmek için çevrimiçi olmalısınız", + "ios-memory-limit": "iOS'a dosya göndermek sadece bir seferde 200 MB'a kadar mümkündür", + "online-requirement-public-room": "Ortak oda oluşturmak için çevrimiçi olmalısınız", + "room-url-copied-to-clipboard": "Ortak oda bağlantısı panoya kopyalandı", + "copied-text-error": "Panoya yazma başarısız oldu. Elle kopyalayın!", "download-successful": "{{descriptor}} indirildi", - "click-to-show": "Görmek için tıkla" + "click-to-show": "Göstermek için tıklayın" }, "peer-ui": { "processing": "İşleniyor…", - "click-to-send-share-mode": "{{descriptor}} göndermek için tıkla", - "click-to-send": "Dosya göndermek için tıkla veya mesaj göndermek için sağ tıkla", + "click-to-send-share-mode": "{{descriptor}} göndermek için tıklayın", + "click-to-send": "Dosya göndermek için tıklayın veya mesaj göndermek için sağ tıklayın", "waiting": "Bekleniyor…", - "connection-hash": "Uçtan uca şifrelemenin güvenliğini doğrulamak için her iki cihazda da bu güvenlik numarasını karşılaştırın", + "connection-hash": "Uçtan uca şifrelemenin güvenliğini doğrulamak için, bu güvenlik numarasını her iki cihazda da karşılaştırın", "preparing": "Hazırlanıyor…", "transferring": "Transfer ediliyor…" }, @@ -165,17 +165,17 @@ "claim": "Cihazlar arasında dosya aktarmanın en kolay yolu", "tweet_title": "PairDrop hakkında tweet at", "close-about_aria-label": "PairDrop Hakkında'yı Kapat", - "buy-me-a-coffee_title": "Bana bir kahve al!", + "buy-me-a-coffee_title": "Bana bir kahve ısmarla!", "github_title": "GitHub'da PairDrop", "faq_title": "Sıkça sorulan sorular", "custom_title": "Bizi takip edin", - "privacypolicy_title": "Gizlilik politikamızı açın", - "mastodon_title": "Mastodon'da PairDrop hakkında yazın", - "bluesky_title": "Bizi BlueSky'da takip edin" + "privacypolicy_title": "Gizlilik politikamızı aç", + "mastodon_title": "Mastodon'da PairDrop hakkında yaz", + "bluesky_title": "BlueSky'da bizi takip edin" }, "document-titles": { "file-transfer-requested": "Dosya Transferi Talep Edildi", - "image-transfer-requested": "Görüntü Aktarımı Talep Edildi", + "image-transfer-requested": "Görüntü Transferi Talep Edildi", "message-received-plural": "{{count}} Mesaj Alındı", "message-received": "Mesaj Alındı", "file-received": "Dosya Alındı", From fda19dc8193900d1859630979c1490eebdd8aa8f Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 1 Jul 2024 18:33:00 +0200 Subject: [PATCH 003/111] Translated using Weblate (Danish) Currently translated at 99.3% (165 of 166 strings) Added translation using Weblate (Danish) Co-authored-by: Halfdan Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/da/ Translation: PairDrop/pairdrop-spa --- public/lang/da.json | 184 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 public/lang/da.json diff --git a/public/lang/da.json b/public/lang/da.json new file mode 100644 index 0000000..f193527 --- /dev/null +++ b/public/lang/da.json @@ -0,0 +1,184 @@ +{ + "notifications": { + "public-room-left": "Forlod det offentlige rum {{publicRoomId}}", + "room-url-copied-to-clipboard": "Link til offentligt rum kopieret til udklipsholder", + "notifications-enabled": "Notifikationer aktiveret", + "notifications-permissions-error": "Notifikationstilladelsen er blevet blokeret, da brugeren har afvist tilladelsesprompten flere gange. Dette kan nulstilles i sideoplysninger, som du kan få adgang til ved at klikke på låseikonet ved siden af URL-linjen.", + "copied-text-error": "Skrivning til udklipsholder mislykkedes. Kopier manuelt!", + "ios-memory-limit": "Det er kun muligt at sende filer til iOS op til 200 MB på én gang", + "display-name-random-again": "Vist navn genereres tilfældigt igen", + "display-name-changed-permanently": "Det viste navn blec ændret permanent", + "display-name-changed-temporarily": "Vist navn blev kun ændret for denne session", + "download-successful": "{{descriptor}} hentet", + "pairing-tabs-error": "Det er umuligt at parre to webbrowserfaner", + "pairing-success": "Enheder parret", + "pairing-not-persistent": "Parrede enheder er ikke vedvarende", + "pairing-key-invalid": "Ugyldig nøgle", + "pairing-key-invalidated": "Nøglen {{key}} er ugyldig", + "pairing-cleared": "Alle enheder er frakoblet", + "public-room-id-invalid": "Ugyldigt rum-id", + "copied-to-clipboard": "Kopieret til udklipsholder", + "pair-url-copied-to-clipboard": "Link til at parre denne enhed kopieret til udklipsholder", + "copied-to-clipboard-error": "Kopiering ikke mulig. Kopier manuelt.", + "text-content-incorrect": "Tekstindholdet er forkert", + "file-content-incorrect": "Filens indhold er forkert", + "clipboard-content-incorrect": "Udklipsholderens indhold er forkert", + "link-received": "Link modtaget af {{name}} - Klik for at åbne", + "message-received": "Besked modtaget af {{name}} - Klik for at kopiere", + "click-to-download": "Klik for at hente", + "request-title": "{{name}} vil gerne overføre {{count}} {{descriptor}}", + "click-to-show": "Klik for at vise", + "copied-text": "Kopieret tekst til udklipsholder", + "offline": "Du er offline", + "online": "Du er online igen", + "connected": "Forbundet", + "online-requirement-pairing": "Du skal være online for at parre enheder", + "online-requirement-public-room": "Du skal være online for at oprette et offentligt rum", + "connecting": "Forbinder…", + "files-incorrect": "Filerne er forkerte", + "file-transfer-completed": "Filoverførsel gennemført", + "message-transfer-completed": "Beskedoverførsel gennemført", + "unfinished-transfers-warning": "Der er uafsluttede overførsler. Er du sikker på, at du vil lukke PairDrop?", + "rate-limit-join-key": "Satsgrænsen er nået. Vent 10 sekunder, og prøv igen.", + "selected-peer-left": "Valgt peer forlod" + }, + "dialogs": { + "message_placeholder": "Tekst", + "base64-files": "filer", + "file-other-description-image": "og 1 andet billede", + "file-other-description-file": "og 1 anden fil", + "download-again": "Hent igen", + "system-language": "Systemsprog", + "pair-devices-qr-code_title": "Klik for at kopiere linket for at parre denne enhed", + "enter-key-from-another-device": "Indtast nøgle fra en anden enhed her.", + "temporary-public-room-title": "Midlertidigt offentligt rum", + "edit-paired-devices-title": "Rediger parrede enheder", + "auto-accept-instructions-2": "for automatisk at acceptere alle filer sendt fra den pågældende enhed.", + "pair-devices-title": "Par enheder permanent", + "input-key-on-this-device": "Indtast denne nøgle på en anden enhed", + "scan-qr-code": "eller scan QR-koden.", + "input-room-id-on-another-device": "Indtast dette rum-id på en anden enhed", + "enter-room-id-from-another-device": "Indtast rum-id fra en anden enhed for at deltage i rummet.", + "hr-or": "ELLER", + "pair": "Par", + "cancel": "Annuller", + "unpair": "Fjern parring", + "paired-device-removed": "Parret enhed er blevet fjernet.", + "paired-devices-wrapper_data-empty": "Ingen parrede enheder.", + "auto-accept-instructions-1": "Aktiver", + "auto-accept": "auto-accepter", + "close": "Luk", + "join": "Forbinde", + "leave": "Forlad", + "would-like-to-share": "gerne vil dele", + "accept": "Accepter", + "decline": "Nægt", + "has-sent": "har sendt:", + "share": "Del", + "download": "Hent", + "send-message-title": "Send besked", + "send-message-to": "Til:", + "message_title": "Indsæt besked for at sende", + "send": "Send", + "receive-text-title": "Besked modtaget", + "copy": "Kopier", + "base64-title-files": "Del filer", + "base64-title-text": "Del tekst", + "base64-processing": "Behandler…", + "base64-tap-to-paste": "Tryk her for at dele {{type}}", + "base64-paste-to-send": "Indsæt udklipsholder her for at dele {{type}}", + "base64-text": "tekst", + "file-other-description-image-plural": "og {{count}} andre billeder", + "file-other-description-file-plural": "og {{count}} andre filer", + "title-image": "Billede", + "title-file": "Fil", + "title-image-plural": "Billeder", + "title-file-plural": "Filer", + "receive-title": "{{descriptor}} Modtaget", + "language-selector-title": "Indstil sprog", + "public-room-qr-code_title": "Klik for at kopiere linket til det offentlige rum", + "approve": "godkend", + "share-text-title": "Del tekstbesked", + "share-text-subtitle": "Rediger besked, før du sender:", + "share-text-checkbox": "Vis altid denne dialogboks, når du deler tekst", + "close-toast_title": "Luk besked" + }, + "about": { + "claim": "Den nemmeste måde at overføre filer på tværs af enheder", + "faq_title": "Ofte stillede spørgsmål", + "close-about_aria-label": "Luk Om PairDrop", + "github_title": "PairDrop på GitHub", + "buy-me-a-coffee_title": "Køb mig en kop kaffe!", + "tweet_title": "Tweet om PairDrop", + "mastodon_title": "Skriv om PairDrop på Mastodon", + "bluesky_title": "Følg os på BlueSky", + "custom_title": "Følg os", + "privacypolicy_title": "Åbn vores privatlivspolitik" + }, + "header": { + "language-selector_title": "Indstil sprog", + "about_aria-label": "Åbn Om PairDrop", + "theme-auto_title": "Tilpas temaet til systemet automatisk", + "theme-light_title": "Brug altid lyst tema", + "theme-dark_title": "Brug altid mørkt tema", + "notification_title": "Aktiver notifikationer", + "install_title": "Installer PairDrop", + "pair-device_title": "Par dine enheder permanent", + "edit-paired-devices_title": "Rediger parrede enheder", + "join-public-room_title": "Deltag midlertidigt i det offentlige rum", + "cancel-share-mode": "Annuller", + "edit-share-mode": "Redigere", + "expand_title": "Udvid overskriftsknaprækken", + "about_title": "Om PairDrop" + }, + "instructions": { + "no-peers-subtitle": "Par enheder, eller gå ind i et offentligt rum for at være synlig på andre netværk", + "x-instructions_desktop": "Klik for at sende filer eller højreklik for at sende en besked", + "activate-share-mode-base": "Åbn PairDrop på andre enheder for at sende", + "no-peers_data-drop-bg": "Slip for at vælge modtager", + "no-peers-title": "Åbn PairDrop på andre enheder for at sende filer", + "x-instructions_mobile": "Tryk for at sende filer, eller tryk længe for at sende en besked", + "x-instructions_data-drop-peer": "Slip for at sende til peer", + "x-instructions_data-drop-bg": "Slip for at vælge modtager", + "x-instructions-share-mode_desktop": "Klik for at sende {{descriptor}}", + "x-instructions-share-mode_mobile": "Tryk for at sende {{descriptor}}", + "activate-share-mode-and-other-file": "og 1 anden fil", + "activate-share-mode-and-other-files-plural": "og {{count}} andre filer", + "activate-share-mode-shared-text": "delt tekst", + "activate-share-mode-shared-file": "delt fil", + "activate-share-mode-shared-files-plural": "{{count}} delte filer", + "webrtc-requirement": "For at bruge denne PairDrop-instans skal WebRTC være aktiveret!" + }, + "footer": { + "on-this-network_title": "Du kan blive opdaget af alle på dette netværk.", + "public-room-devices_title": "Du kan blive opdaget af enheder i dette offentlige rum uafhængigt af netværket.", + "known-as": "Du er kendt som:", + "display-name_data-placeholder": "Indlæser…", + "display-name_title": "Rediger dit enhedsnavn permanent", + "discovery": "Du kan blive opdaget:", + "on-this-network": "på dette netværk", + "paired-devices": "af parrede enheder", + "paired-devices_title": "Du kan til enhver tid blive opdaget af parrede enheder uafhængigt af netværket.", + "public-room-devices": "i rum {{roomId}}", + "traffic": "Trafikken er", + "routed": "dirigeret gennem serveren", + "webrtc": "hvis WebRTC ikke er tilgængelig." + }, + "document-titles": { + "file-received": "Fil modtaget", + "file-received-plural": "{{count}} Filer modtaget", + "file-transfer-requested": "Filoverførsel anmodet", + "image-transfer-requested": "Billedoverførsel anmodet", + "message-received": "Besked modtaget", + "message-received-plural": "{{count}} meddelelser modtaget" + }, + "peer-ui": { + "click-to-send-share-mode": "Klik for at sende {{descriptor}}", + "click-to-send": "Klik for at sende filer eller højreklik for at sende en besked", + "connection-hash": "For at kontrollere sikkerheden for end-to-end-kryptering skal du sammenligne dette sikkerhedsnummer på begge enheder", + "preparing": "Forbereder…", + "waiting": "Venter…", + "processing": "Behandler…", + "transferring": "Overfører…" + } +} From e53e4adcdf5d8f4a00ded2ac4b823f2d014336b2 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 1 Jul 2024 18:33:00 +0200 Subject: [PATCH 004/111] Translated using Weblate (Russian) Currently translated at 88.5% (147 of 166 strings) Co-authored-by: Ed Asriyan Co-authored-by: Hosted Weblate Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/ru/ Translation: PairDrop/pairdrop-spa --- public/lang/ru.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/public/lang/ru.json b/public/lang/ru.json index e23f900..5e7b041 100644 --- a/public/lang/ru.json +++ b/public/lang/ru.json @@ -93,7 +93,9 @@ "temporary-public-room-title": "Временная публичная комната", "message_title": "Вставьте сообщение для отправки", "pair-devices-qr-code_title": "Нажмите, чтобы скопировать ссылку для привязки этого устройства", - "public-room-qr-code_title": "Нажмите, чтобы скопировать ссылку на публичную комнату" + "public-room-qr-code_title": "Нажмите, чтобы скопировать ссылку на публичную комнату", + "message_placeholder": "Текст", + "paired-device-removed": "Связанное устройство удалено." }, "about": { "close-about-aria-label": "Закрыть страницу \"О сервисе\"", From ff92e606ff56d35e9057f719513fdd77d6156476 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 1 Jul 2024 18:33:00 +0200 Subject: [PATCH 005/111] Translated using Weblate (Belarusian) Currently translated at 100.0% (166 of 166 strings) Translated using Weblate (Belarusian) Currently translated at 56.6% (94 of 166 strings) Added translation using Weblate (Belarusian) Co-authored-by: Hosted Weblate Co-authored-by: Troja Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/be/ Translation: PairDrop/pairdrop-spa --- public/lang/be.json | 184 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 public/lang/be.json diff --git a/public/lang/be.json b/public/lang/be.json new file mode 100644 index 0000000..13af5eb --- /dev/null +++ b/public/lang/be.json @@ -0,0 +1,184 @@ +{ + "header": { + "about_aria-label": "Адкрыйце Аб PairDrop", + "about_title": "Аб PairDrop", + "theme-auto_title": "Аўтаматычная адаптацыя тэмы да сістэмы", + "theme-light_title": "Заўсёды выкарыстоўваць светлую тэму", + "theme-dark_title": "Заўсёды выкарыстоўваць цёмную тэму", + "notification_title": "Уключыць апавяшчэнні", + "edit-paired-devices_title": "Рэдагаваць злучаныя прылады", + "join-public-room_title": "Часова далучыцца да публічнага пакоя", + "cancel-share-mode": "Адмяніць", + "language-selector_title": "Задаць мову", + "install_title": "Усталяваць PairDrop", + "pair-device_title": "Злучыце свае прылады назаўжды", + "edit-share-mode": "Рэдагаваць", + "expand_title": "Разгарнуць радок кнопак" + }, + "instructions": { + "no-peers_data-drop-bg": "Адпусціце, каб выбраць атрымальніка", + "no-peers-title": "Адкрыйце PairDrop на іншых прыладах, каб адправіць файлы", + "x-instructions_data-drop-peer": "Адпусціце, каб адправіць вузлу", + "x-instructions_data-drop-bg": "Адпусціце, каб выбраць атрымальніка", + "x-instructions-share-mode_mobile": "Дакраніцеся, каб адправіць {{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-files-plural": "{{count}} агульных файлаў", + "webrtc-requirement": "Каб выкарыстоўваць гэты асобнік Pair Drop, WebRTC павінен быць уключаны!", + "no-peers-subtitle": "Злучыце прылады або ўвайдзіце ў публічны пакой, каб вас маглі выявіць з іншых сетак", + "x-instructions_mobile": "Дакраніцеся, каб адправіць файлы, або доўга трымайце, каб адправіць паведамленне", + "x-instructions-share-mode_desktop": "Націсніце, каб адправіць {{descriptor}}", + "x-instructions_desktop": "Націсніце, каб адправіць файлы, або націсніце правай кнопкай мышы, каб адправіць паведамленне", + "activate-share-mode-base": "Адкрыйце PairDrop на іншых прыладах, каб адправіць", + "activate-share-mode-shared-file": "агульны файл" + }, + "footer": { + "known-as": "Вы вядомыя як:", + "display-name_data-placeholder": "Загрузка…", + "discovery": "Вас могуць выявіць:", + "on-this-network_title": "Вас можа знайсці кожны ў гэтай сетцы.", + "paired-devices": "з дапамогай злучаных прылад", + "public-room-devices_title": "Вас могуць выявіць прылады ў гэтай публічнай пакоі незалежна ад сеткі.", + "traffic": "Рух", + "display-name_title": "Зменіце назву сваёй прылады назаўжды", + "on-this-network": "у гэтай сетцы", + "paired-devices_title": "Злучаныя прылады заўсёды могуць вас выявіць незалежна ад сеткі.", + "public-room-devices": "у пакоі {{roomId}}", + "webrtc": ", калі WebRTC недаступны.", + "routed": "накіроўваецца праз сервер" + }, + "dialogs": { + "hr-or": "АБО", + "cancel": "Адмяніць", + "pair": "Злучыць", + "unpair": "Разлучыць", + "paired-devices-wrapper_data-empty": "Няма злучаных прылад.", + "auto-accept": "аўтаматычнае прыняцце", + "close": "Закрыць", + "join": "Далучыцца", + "leave": "Пакінуць", + "decline": "Адмовіць", + "share": "Падзяліцца", + "copy": "Капіяваць", + "title-image": "Малюнак", + "system-language": "Мова сістэмы", + "public-room-qr-code_title": "Націсніце, каб скапіяваць спасылку на публічны пакой", + "title-file": "Файл", + "title-file-plural": "Файлы", + "message_placeholder": "Тэкст", + "language-selector-title": "Задаць мову", + "send-message-title": "Адправіць паведамленне", + "scan-qr-code": "або сканаваць QR-код.", + "enter-room-id-from-another-device": "Увядзіце ID пакоя з іншай прылады, каб далучыцца да пакоя.", + "edit-paired-devices-title": "Рэдагаваць злучаныя прылады", + "auto-accept-instructions-1": "Актываваць", + "auto-accept-instructions-2": ", каб аўтаматычна прымаць усе файлы, адпраўленыя з гэтай прылады.", + "accept": "Прыняць", + "download": "Спампаваць", + "download-again": "Спампаваць яшчэ раз", + "pair-devices-qr-code_title": "Націсніце, каб скапіраваць спасылку для спалучэння гэтай прылады", + "approve": "сцвердзіць", + "pair-devices-title": "Пастаяннае злучэнне прылад", + "enter-key-from-another-device": "Увядзіце тут ключ з іншай прылады.", + "temporary-public-room-title": "Часовы публічны пакой", + "input-room-id-on-another-device": "Увядзіце гэты ID пакоя на іншай прыладзе", + "paired-device-removed": "Злучаная прылада была выдалена.", + "would-like-to-share": "хацеў бы падзяліцца", + "send-message-to": "Каму:", + "message_title": "Устаўце паведамленне для адпраўкі", + "has-sent": "адправіў:", + "base64-processing": "Апрацоўка…", + "send": "Адправіць", + "base64-title-text": "Падзяліцца тэкстам", + "base64-title-files": "Падзяліцца файламі", + "base64-tap-to-paste": "Дакраніцеся тут, каб падзяліцца {{type}}", + "file-other-description-image": "і 1 іньшы малюнак", + "file-other-description-image-plural": "і {{count}} іншых малюнкаў", + "file-other-description-file-plural": "і {{count}} іншых файлаў", + "title-image-plural": "Малюнкі", + "share-text-subtitle": "Рэдагаваць паведамленне перад адпраўкай:", + "share-text-title": "Падзяліцца тэкставым паведамленнем", + "close-toast_title": "Закрыць апавяшчэнне", + "receive-text-title": "Паведамленне атрымана", + "input-key-on-this-device": "Увядзіце гэты ключ на іншай прыладзе", + "base64-files": "файлы", + "base64-text": "тэкст", + "base64-paste-to-send": "Устаўце сюды буфер абмену, каб падзяліцца {{type}}", + "file-other-description-file": "і 1 іньшы файл", + "receive-title": "{{descriptor}} атрымана", + "share-text-checkbox": "Заўсёды паказваць гэта дыялогавае акно пры абагульванні тэксту" + }, + "about": { + "buy-me-a-coffee_title": "Купіць мне кавы!", + "mastodon_title": "Напішыце пра PairDrop на Mastodon", + "tweet_title": "Твіт пра PairDrop", + "github_title": "PairDrop на GitHub", + "custom_title": "Сачыце за намі", + "bluesky_title": "Сачыце за намі на BlueSky", + "faq_title": "Часта задаюць пытанні", + "close-about_aria-label": "Закрыць Аб PairDrop", + "claim": "Самы просты спосаб перадачы файлаў паміж прыладамі", + "privacypolicy_title": "Адкрыйце нашу палітыку прыватнасці" + }, + "notifications": { + "link-received": "Спасылка атрымана {{name}} - Націсніце, каб адкрыць", + "message-received": "Паведамленне атрымана {{name}} - Націсніце, каб скапіяваць", + "click-to-download": "Націсніце, каб спампаваць", + "click-to-show": "Націсніце, каб паказаць", + "copied-text-error": "Памылка запісу ў буфер абмену. Скапіруйце ўручную!", + "online": "Вы зноў у сетцы", + "online-requirement-public-room": "Вы павінны быць падлучаныя да сеткі, каб стварыць агульны пакой", + "connecting": "Падключэнне…", + "public-room-id-invalid": "Несапраўдны ID пакоя", + "notifications-permissions-error": "Дазвол на апавяшчэнні быў заблакіраваны, бо карыстальнік некалькі разоў адхіляў запыт на дазвол. Гэта можна скінуць у меню \"Аб старонцы\", доступ да якой можна атрымаць, націснуўшы на значок замка побач з радком URL.", + "request-title": "{{name}} хоча перадаць {{count}} {{descriptor}}", + "copied-text": "Тэкст скапіраваны ў буфер абмену", + "offline": "Вы па-за сеткай", + "connected": "Падключана", + "online-requirement-pairing": "Вы павінны быць падлучаныя да сеткі для спалучэння прылад", + "pairing-key-invalidated": "Ключ {{key}} несапраўдны", + "display-name-random-again": "Адлюстраванае імя зноў згенеравалася выпадковым чынам", + "download-successful": "{{descriptor}} спампавана", + "pairing-tabs-error": "Злучэнне дзвюх укладак вэб-браўзера немагчыма", + "display-name-changed-permanently": "Адлюстроўванае імя было зменена назаўжды", + "pairing-cleared": "Усе прылады раз'яднаны", + "room-url-copied-to-clipboard": "Спасылка на публічны пакой скапіравана ў буфер абмену", + "public-room-left": "Пакінуць публічны пакой {{publicRoomId}}", + "text-content-incorrect": "Змест тэксту няправільны", + "clipboard-content-incorrect": "Змест буфера абмену няправільны", + "notifications-enabled": "Апавяшчэнні ўключаны", + "files-incorrect": "Няправільныя файлы", + "file-transfer-completed": "Перадача файла завершана", + "selected-peer-left": "Выбраны вузел выйшаў", + "copied-to-clipboard": "Скапіравана ў буфер абмену", + "pair-url-copied-to-clipboard": "Спасылка для злучэння гэтай прылады скапіравана ў буфер абмену", + "pairing-success": "Злучаныя прылады", + "copied-to-clipboard-error": "Капіраванне немагчымае. Скапіруйце ўручную.", + "file-content-incorrect": "Змест файла няправільны", + "pairing-not-persistent": "Злучаныя прылады не з'яўляюцца пастаяннымі", + "pairing-key-invalid": "Несапраўдны ключ", + "display-name-changed-temporarily": "Адлюстраванае імя зменена толькі для гэтага сеансу", + "ios-memory-limit": "Адначасовая адпраўка файлаў на iOS магчымая толькі да 200 МБ", + "message-transfer-completed": "Перадача паведамлення завершана", + "unfinished-transfers-warning": "Ёсць незавершаныя перадачы. Вы ўпэўнены, што хочаце закрыць PairDrop?", + "rate-limit-join-key": "Ліміт хуткасці дасягнуты. Пачакайце 10 секунд і паўтарыце спробу." + }, + "peer-ui": { + "preparing": "Падрыхтоўка…", + "waiting": "Чаканне…", + "transferring": "Перадача…", + "processing": "Апрацоўка…", + "click-to-send-share-mode": "Націсніце, каб адправіць {{descriptor}}", + "connection-hash": "Каб праверыць бяспеку скразнога шыфравання, параўнайце гэты нумар бяспекі на абедзвюх прыладах", + "click-to-send": "Націсніце, каб адправіць файлы, або націсніце правай кнопкай мышы, каб адправіць паведамленне" + }, + "document-titles": { + "file-received": "Файл атрыманы", + "image-transfer-requested": "Запытана перадача малюнкаў", + "message-received": "Паведамленне атрымана", + "message-received-plural": "Атрымана {{count}} паведамленняў", + "file-received-plural": "Атрымана {{count}} файлаў", + "file-transfer-requested": "Запытана перадача файла" + } +} From 1eefd4720f4d7138b16cf2cd4ead01c3c8215b46 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 1 Jul 2024 18:33:01 +0200 Subject: [PATCH 006/111] 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: 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 | 152 ++++++++++++++++++++++---------------------- 1 file changed, 76 insertions(+), 76 deletions(-) diff --git a/public/lang/ja.json b/public/lang/ja.json index f25fb32..c6a5dad 100644 --- a/public/lang/ja.json +++ b/public/lang/ja.json @@ -1,17 +1,17 @@ { "footer": { - "webrtc": "WebRTCが利用できない場合。", - "public-room-devices_title": "このデバイスはネットワークと関係なく、このパブリックルームのデバイスにより発見される可能性があります。", + "webrtc": "(WebRTCが無効なため)", + "public-room-devices_title": "公開ルーム内のデバイスは、接続中のネットワークと関係なくアクセスできます。", "display-name_data-placeholder": "読み込み中…", - "display-name_title": "永続的なデバイス名を編集する", - "traffic": "トラフィックは", - "paired-devices_title": "このデバイスはネットワークと関係なく、常にペア設定したデバイスにより発見される可能性があります。", - "public-room-devices": "ルーム{{roomId}}上", - "paired-devices": "ペア設定したデバイス", + "display-name_title": "デバイス名を変更する", + "traffic": "この通信は", + "paired-devices_title": "ペアリング済みデバイスであれば、接続中のネットワークに関わらずアクセスできます。", + "public-room-devices": "ルーム{{roomId}}", + "paired-devices": "ペアリング済みデバイス", "on-this-network": "このネットワーク上", "routed": "サーバーを経由します", - "discovery": "このデバイスは以下で発見される可能性があります:", - "on-this-network_title": "このデバイスはこのネットワーク上の誰にでも発見される可能性があります。", + "discovery": "このデバイスを検出可能なネットワーク:", + "on-this-network_title": "このネットワーク上のすべてのデバイスからアクセスできます。", "known-as": "他のデバイスに表示される名前:" }, "notifications": { @@ -23,50 +23,50 @@ "pairing-key-invalidated": "コード{{key}}が失効しました", "pairing-key-invalid": "無効なコード", "connected": "接続しました", - "pairing-not-persistent": "ペア設定されたデバイスは永続化されていません", - "text-content-incorrect": "テキストの内容が不正です", + "pairing-not-persistent": "このデバイスとのペアリングは解除される可能性があります", + "text-content-incorrect": "無効なテキスト内容です", "message-transfer-completed": "メッセージの送信が完了しました", - "file-transfer-completed": "ファイルの転送が完了しました", - "file-content-incorrect": "ファイルの内容が不正です", + "file-transfer-completed": "ファイル転送が完了しました", + "file-content-incorrect": "無効なファイル内容です", "files-incorrect": "ファイルが間違っています", - "selected-peer-left": "選択した相手が退出しました", + "selected-peer-left": "選択したデバイスが退出しました", "link-received": "{{name}}から受信したリンク(クリックして開く)", "online": "オンラインに復帰しました", - "public-room-left": "パブリックルーム{{publicRoomId}}から退出しました", + "public-room-left": "公開ルーム{{publicRoomId}}から退出しました", "copied-text": "テキストをクリップボードにコピーしました", - "display-name-random-again": "表示名がもう一度ランダムに生成されました", - "display-name-changed-permanently": "永続的な表示名が変更されました", + "display-name-random-again": "新しいランダムなデバイス名に変更されました", + "display-name-changed-permanently": "デバイス名が変更されました", "copied-to-clipboard-error": "コピーできませんでした。手動でコピーしてください。", - "pairing-success": "デバイスがペア設定されました", - "clipboard-content-incorrect": "クリップボードの内容が不正です", - "display-name-changed-temporarily": "このセッションでの表示名が変更されました", + "pairing-success": "ペアリングしました", + "clipboard-content-incorrect": "無効なクリップボード内容です", + "display-name-changed-temporarily": "この接続のみデバイス名が変更されました", "copied-to-clipboard": "クリップボードにコピーしました", "offline": "オフラインです", - "pairing-tabs-error": "同じWebブラウザーの2つのタブをペア設定することはできません", + "pairing-tabs-error": "同じWebブラウザーで開いたタブ同士でペアリングすることはできません", "public-room-id-invalid": "無効なルームID", "click-to-download": "クリックしてダウンロード", - "pairing-cleared": "全てのデバイスのペア設定を解除しました", - "notifications-enabled": "通知が有効です", - "online-requirement-pairing": "デバイスをペア設定するにはオンラインである必要があります", + "pairing-cleared": "全てのデバイスとのペアリングを解除しました", + "notifications-enabled": "通知が有効になりました", + "online-requirement-pairing": "ペアリングするにはオンラインである必要があります", "ios-memory-limit": "iOSへのファイル送信は一度に200MBまでしかできません", - "online-requirement-public-room": "パブリックルームを作成するにはオンラインである必要があります", + "online-requirement-public-room": "公開ルームを作成するにはオンラインである必要があります", "copied-text-error": "クリップボードにコピーできませんでした。手動でコピーしてください。", "download-successful": "{{descriptor}}をダウンロードしました", "click-to-show": "クリックして表示", - "notifications-permissions-error": "ユーザーが権限のプロンプトを何度か閉じたため、通知の権限がブロックされました。これは、URL バーの横にある鍵アイコンをクリックしてアクセスできるページ情報からリセットできます。", - "pair-url-copied-to-clipboard": "このデバイスをペア設定するリンクをクリップボードにコピーしました", - "room-url-copied-to-clipboard": "パブリックルームへのリンクをクリップボードにコピーしました" + "notifications-permissions-error": "通知がブロックされました。これはユーザーが通知許可を何度も拒否したためです。これをリセットするには、URLバーの隣にある鍵アイコンをクリックして、ページ情報にアクセスしてください。", + "pair-url-copied-to-clipboard": "このデバイスとペアリングするリンクをクリップボードにコピーしました", + "room-url-copied-to-clipboard": "公開ルームへのリンクをクリップボードにコピーしました" }, "header": { - "cancel-share-mode": "完了", - "theme-auto_title": "テーマをシステムの設定に自動的に合わせる", + "cancel-share-mode": "キャンセル", + "theme-auto_title": "システムテーマに合わせる", "install_title": "PairDropをインストール", "theme-dark_title": "常にダークテーマを使用する", - "pair-device_title": "あなたのデバイスを永続的にペア設定する", - "join-public-room_title": "パブリックルームに一時的に参加する", + "pair-device_title": "他のデバイスとペアリングする", + "join-public-room_title": "公開ルームに参加する", "notification_title": "通知を有効にする", - "edit-paired-devices_title": "ペア設定したデバイスを編集する", - "language-selector_title": "言語を設定", + "edit-paired-devices_title": "ペアリング設定", + "language-selector_title": "言語設定", "about_title": "PairDropについて", "about_aria-label": "PairDropについてを開く", "theme-light_title": "常にライトテーマを使用する", @@ -74,19 +74,19 @@ "expand_title": "ヘッダーボタン列を拡大する" }, "instructions": { - "x-instructions_mobile": "タップしてファイルを送信または長押ししてメッセージを送信します", - "x-instructions-share-mode_desktop": "クリックして{{descriptor}}送信", + "x-instructions_mobile": "タップでファイルを送信、長押しでメッセージを送信します", + "x-instructions-share-mode_desktop": "クリックして{{descriptor}}を送信", "activate-share-mode-and-other-files-plural": "とその他{{count}}個のファイル", - "x-instructions-share-mode_mobile": "タップして{{descriptor}}送信", + "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": "左クリックしてファイルを送信または右クリックしてメッセージを送信します", - "no-peers-title": "他のデバイスでPairDropを開いてファイルを送信します", - "x-instructions_data-drop-peer": "離すとこの相手に送信します", - "x-instructions_data-drop-bg": "送信したい相手の上で離してください", - "no-peers_data-drop-bg": "送信したい相手の上で離してください", - "activate-share-mode-and-other-file": "もう1つの別のファイル", + "x-instructions_desktop": "左クリックでファイルを送信、右クリックでメッセージを送信します", + "no-peers-title": "ファイルを共有するには他のデバイスでPairDropを開いてください", + "x-instructions_data-drop-peer": "ドロップするとこのデバイスに送信します", + "x-instructions_data-drop-bg": "送信したいデバイスの上でドロップしてください", + "no-peers_data-drop-bg": "送信したいデバイスの上でドロップしてください", + "activate-share-mode-and-other-file": "とその他1個のファイル", "activate-share-mode-shared-file": "共有されたファイル", "activate-share-mode-shared-files-plural": "{{count}}個の共有されたファイル", "webrtc-requirement": "このPairDropインスタンスを使用するには、WebRTCを有効にする必要があります!" @@ -94,20 +94,20 @@ "peer-ui": { "processing": "処理中…", "click-to-send-share-mode": "クリックして{{descriptor}}を送信", - "click-to-send": "クリックしてファイルを送信または右クリックしてメッセージを送信します", + "click-to-send": "左クリックでファイルを送信、右クリックでメッセージを送信します", "waiting": "待機中…", - "connection-hash": "エンドツーエンド暗号化のセキュリティを確認するには、両方のデバイスのセキュリティナンバーを確認します", + "connection-hash": "エンドツーエンド暗号化のセキュリティを確認するには、両方のデバイスのセキュリティナンバーを確認してください", "preparing": "準備中…", "transferring": "転送中…" }, "dialogs": { "base64-paste-to-send": "ここをタップして{{type}}を送信", - "auto-accept-instructions-2": "そのデバイスから送信される全てのファイルを自動的に承諾します。", + "auto-accept-instructions-2": "」を有効にすると、そのデバイスから送信されたすべてのファイルを自動的に受け入れます。", "receive-text-title": "メッセージを受信しました", - "edit-paired-devices-title": "ペア設定したデバイスを編集", + "edit-paired-devices-title": "ペアリング設定", "cancel": "キャンセル", - "auto-accept-instructions-1": "有効化", - "pair-devices-title": "デバイスを永続的にペア設定", + "auto-accept-instructions-1": "「", + "pair-devices-title": "新規ペアリング", "download": "ダウンロード", "title-file": "ファイル", "base64-processing": "処理中…", @@ -117,58 +117,58 @@ "join": "参加", "title-image-plural": "複数の画像", "send": "送信", - "base64-tap-to-paste": "ここをタップして{{type}}を貼り付け", + "base64-tap-to-paste": "ここをタップして{{type}}を共有", "base64-text": "テキスト", "copy": "コピー", - "file-other-description-image": "と1個の他の画像", - "temporary-public-room-title": "一時的なパブリックルーム", + "file-other-description-image": "とその他1個の画像", + "temporary-public-room-title": "公開ルーム", "base64-files": "ファイル", "has-sent": "が送信しました:", - "file-other-description-file": "と1個の他のファイル", + "file-other-description-file": "とその他1個のファイル", "close": "閉じる", - "system-language": "システムの言語", - "unpair": "ペア解除", + "system-language": "システム言語", + "unpair": "ペアリング解除", "title-image": "画像", - "file-other-description-file-plural": "と{{count}}個の他のファイル", + "file-other-description-file-plural": "とその他{{count}}個のファイル", "would-like-to-share": "が以下のファイルを共有しようとしています", "send-message-to": "このデバイスにメッセージを送信:", - "language-selector-title": "言語を設定", - "pair": "ペア設定", + "language-selector-title": "言語設定", + "pair": "ペアリング", "hr-or": "または", - "scan-qr-code": "もしくはQRコードをスキャンします。", - "input-key-on-this-device": "このキーを他のデバイスに入力する", + "scan-qr-code": "もしくはQRコードをスキャンしてください。", + "input-key-on-this-device": "このコードを他のデバイスに入力するか", "download-again": "もう一度ダウンロードする", "accept": "承諾", - "paired-devices-wrapper_data-empty": "ペア設定したデバイスはありません。", - "enter-key-from-another-device": "他のデバイスに表示されたキーをここに入力します。", + "paired-devices-wrapper_data-empty": "ペアリングしたデバイスはありません。", + "enter-key-from-another-device": "他のデバイスに表示されたコードを入力してください。", "share": "共有", "auto-accept": "自動承諾", "title-file-plural": "複数のファイル", "send-message-title": "メッセージを送信", - "input-room-id-on-another-device": "このルームIDを他のデバイスに入力", - "file-other-description-image-plural": "と{{count}}個の他の画像", - "enter-room-id-from-another-device": "他のデバイスに表示された参加したいルームのIDを入力します。", + "input-room-id-on-another-device": "このルームIDを他のデバイスに入力するか", + "file-other-description-image-plural": "とその他{{count}}個の画像", + "enter-room-id-from-another-device": "他のデバイスに表示されたルームIDを入力してください。", "message_title": "送信するメッセージを挿入", - "pair-devices-qr-code_title": "クリックしてこのデバイスをペア設定するリンクをコピー", - "public-room-qr-code_title": "クリックしてパブリックルームへのリンクをコピー", - "paired-device-removed": "ペア設定されたデバイスが削除されました。", + "pair-devices-qr-code_title": "クリックしてこのデバイスとペアリングするリンクをコピー", + "public-room-qr-code_title": "クリックして公開ルームへのリンクをコピー", + "paired-device-removed": "ペアリングを解除しました。", "message_placeholder": "テキスト", "base64-title-files": "共有されたファイル", "base64-title-text": "テキストを共有", - "approve": "承諾", + "approve": "OK", "share-text-subtitle": "送信する前にメッセージを編集する:", - "share-text-checkbox": "テキストを共有するときに常にこのダイアログを表示する", + "share-text-checkbox": "テキスト共有する際、毎回この画面を表示する", "close-toast_title": "通知を閉じる", "share-text-title": "テキストメッセージを共有します" }, "about": { - "claim": "デバイス間でファイルを転送する最も簡単な方法", - "tweet_title": "PairDropについてツイートする", + "claim": "デバイス間のファイル共有を手軽に実現します", + "tweet_title": "PairDropのことをポストする", "close-about_aria-label": "PairDropについてを閉じる", - "buy-me-a-coffee_title": "コーヒーをおごってください!", - "github_title": "GitHubでPairDropを見る", + "buy-me-a-coffee_title": "コーヒーを一杯おごってください!", + "github_title": "PairDrop on GitHub", "faq_title": "FAQ", - "mastodon_title": "MastodonにPairDropについて書く", + "mastodon_title": "MastodonにPairDropのことをトゥートする", "bluesky_title": "BlueSkyでフォロー", "custom_title": "フォロー", "privacypolicy_title": "プライバシーポリシーを開く" From 971917bc777ea9e3a268e93aca20dfb84dab307c Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 1 Jul 2024 18:33:01 +0200 Subject: [PATCH 007/111] Translated using Weblate (French) Currently translated at 100.0% (166 of 166 strings) Translated using Weblate (Czech) Currently translated at 3.0% (5 of 166 strings) Added translation using Weblate (Czech) Translated using Weblate (Catalan) Currently translated at 100.0% (166 of 166 strings) Co-authored-by: Guillaume Dorce Co-authored-by: Hosted Weblate Co-authored-by: Netleak Co-authored-by: gmassipg Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/ca/ Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/cs/ Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/fr/ Translation: PairDrop/pairdrop-spa --- public/lang/ca.json | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/public/lang/ca.json b/public/lang/ca.json index 15bd7ce..c04e68f 100644 --- a/public/lang/ca.json +++ b/public/lang/ca.json @@ -30,7 +30,8 @@ "cancel-share-mode": "Cancel·lar", "about_title": "Sobre PairDrop", "about_aria-label": "Obre Sobre PairDrop", - "theme-light_title": "Utilitza sempre el mode clar" + "theme-light_title": "Utilitza sempre el mode clar", + "expand_title": "Expandeix la fila de botons de la capçalera" }, "dialogs": { "message_placeholder": "Text", @@ -166,7 +167,11 @@ "close-about_aria-label": "Tanca Sobre PairDrop", "buy-me-a-coffee_title": "Convida'm a un cafè!", "github_title": "PairDrop a GitHub", - "faq_title": "Preguntes freqüents" + "faq_title": "Preguntes freqüents", + "mastodon_title": "Escriu sobre PairDrop a Mastodon", + "bluesky_title": "Segueix-nos a BlueSky", + "custom_title": "Segueix-nos", + "privacypolicy_title": "Obre la nostra política de privacitat" }, "document-titles": { "file-transfer-requested": "Transferència de Fitxers Sol·licitada", From 27a698c762461099dfd0c27019af0fce3e803d90 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 1 Jul 2024 18:33:01 +0200 Subject: [PATCH 008/111] Translated using Weblate (French) Currently translated at 100.0% (166 of 166 strings) Translated using Weblate (Czech) Currently translated at 3.0% (5 of 166 strings) Added translation using Weblate (Czech) Translated using Weblate (Catalan) Currently translated at 100.0% (166 of 166 strings) Co-authored-by: Guillaume Dorce Co-authored-by: Hosted Weblate Co-authored-by: Netleak Co-authored-by: gmassipg Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/ca/ Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/cs/ Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/fr/ Translation: PairDrop/pairdrop-spa --- public/lang/cs.json | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 public/lang/cs.json diff --git a/public/lang/cs.json b/public/lang/cs.json new file mode 100644 index 0000000..9eb47f6 --- /dev/null +++ b/public/lang/cs.json @@ -0,0 +1,9 @@ +{ + "header": { + "about_aria-label": "Otevřít o PairDrop", + "about_title": "O službě PairDrop", + "language-selector_title": "Nastavit jazyk", + "theme-auto_title": "Automatické přizpůsobení tématu systému", + "pair-device_title": "Spárovat zařízení permanentně" + } +} From 1a254765fef8eb0d383ecfeaea17046e4a9f4892 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 1 Jul 2024 18:33:01 +0200 Subject: [PATCH 009/111] Translated using Weblate (Hebrew) Currently translated at 100.0% (166 of 166 strings) Co-authored-by: Hosted Weblate Co-authored-by: Liraz Shalom Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/he/ Translation: PairDrop/pairdrop-spa --- public/lang/he.json | 185 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 184 insertions(+), 1 deletion(-) diff --git a/public/lang/he.json b/public/lang/he.json index 0967ef4..c1d1ee7 100644 --- a/public/lang/he.json +++ b/public/lang/he.json @@ -1 +1,184 @@ -{} +{ + "header": { + "about_title": "אודות PairDrop", + "theme-light_title": "השתמש תמיד במצב בהיר", + "install_title": "התקן את PairDrop", + "edit-share-mode": "עריכה", + "expand_title": "הרחב את שורת כפתור הכותרת", + "language-selector_title": "שינוי השפה", + "about_aria-label": "פתח אודות PairDrop", + "theme-auto_title": "התאם את הרקע למערכת באופן אוטומטי", + "theme-dark_title": "השתמש תמיד במצב כהה", + "notification_title": "הפעל התראות", + "pair-device_title": "התאם את המכשירים שלך לתמיד", + "edit-paired-devices_title": "עריכת מכשירים מתואמים", + "join-public-room_title": "הצטרף לחדר ציבורי באופן זמני", + "cancel-share-mode": "ביטול" + }, + "instructions": { + "no-peers-subtitle": "תאם מכשירים או היכנס לחדר ציבורי כדי להיות ניתן לגילוי ברשתות אחרות", + "x-instructions_data-drop-bg": "שחרר כדי לבחור נמען", + "activate-share-mode-and-other-file": "וקובץ 1 אחר", + "activate-share-mode-base": "פתח את PairDrop על מכשירים אחרים כדי לשלוח", + "activate-share-mode-shared-file": "קובץ משותף", + "activate-share-mode-shared-files-plural": "{{count}} קבצים משותפים", + "webrtc-requirement": "כדי להשתמש בPairdrop, WebRTC מוכרח להיות מופעל!", + "no-peers_data-drop-bg": "שחרר כדי לבחור את הנמען", + "no-peers-title": "פתח את PairDrop במכשירים אחרים כדי לשלוח קבצים", + "x-instructions_desktop": "לחץ כדי לשלוח קבצים או בצע לחיצה ימנית כדי לשלוח הודעה", + "x-instructions_mobile": "גע כדי לשלוח קבצים או בצע נגיעה ארוכה כדי לשלוח הודעה", + "x-instructions_data-drop-peer": "שחרר כדי לשלוח למכשיר", + "x-instructions-share-mode_desktop": "לחץ כדי לשלוח {{descriptor}}", + "x-instructions-share-mode_mobile": "גע כדי לשלוח {{descriptor}}", + "activate-share-mode-and-other-files-plural": "ו{{count}} קבצים אחרים", + "activate-share-mode-shared-text": "טקסט משותף" + }, + "footer": { + "paired-devices_title": "הנך ניתן לגילוי על ידי מכשירים מתואמים בכל עת ללא תלות ברשת.", + "on-this-network": "ברשת הזו", + "on-this-network_title": "אתה ניתן לגילוי על ידי כולם ברשת הזו.", + "display-name_data-placeholder": "טוען…", + "display-name_title": "שנה את שם המכשיר שלך לתמיד", + "known-as": "הנך ידוע כ:", + "discovery": "הנך ניתן לגילוי:", + "paired-devices": "על ידי מכשירים מתואמים", + "public-room-devices": "בחדר {{roomId}}", + "public-room-devices_title": "הנך ניתן לגילוי על ידי מכשירים בחדר הציבורי הזה ללא תלות ברשת.", + "traffic": "הנתונים", + "routed": "מנותבים דרך השרת", + "webrtc": "אם WebRTC אינו זמין." + }, + "dialogs": { + "input-room-id-on-another-device": "הזן את מזהה החדר הזה במכשיר אחר", + "edit-paired-devices-title": "ערוך מכשירים מתואמים", + "paired-device-removed": "המכשיר המתואם הוסר.", + "download-again": "הורד שוב", + "public-room-qr-code_title": "לחץ כדי להעתיק את הקישור לחדר הציבורי", + "auto-accept-instructions-2": "כדי לקבל באופן אוטומטי את כל הקבצים שנשלחים ממכשיר זה.", + "title-file-plural": "קבצים", + "receive-title": "{{descriptor}} התקבל", + "download": "הורד", + "send-message-title": "שלח הודעה", + "message_placeholder": "טקסט", + "receive-text-title": "ההודעה התקבלה", + "base64-text": "טקסט", + "share-text-checkbox": "תמיד הצג את חלונית זו כאשר טקסט משותף", + "system-language": "שפת המערכת", + "title-file": "קובץ", + "pair-devices-title": "תאם מכשירים לתמיד", + "input-key-on-this-device": "הזן את הקוד הזה במכשיר אחר", + "scan-qr-code": "או סרוק את הברקוד.", + "enter-key-from-another-device": "הזן את הקוד ממכשיר אחר כאן.", + "temporary-public-room-title": "חדר ציבורי זמני", + "enter-room-id-from-another-device": "הזן מזהה חדר ממכשיר אחר כדי להצטרף לחדר.", + "hr-or": "או", + "pair": "תאם", + "cancel": "ביטול", + "unpair": "בטל התאמה", + "paired-devices-wrapper_data-empty": "אין מכשירים מתואמים.", + "auto-accept-instructions-1": "הפעל", + "auto-accept": "קבלה אוטומטית", + "close": "סגירה", + "join": "הצטרף", + "leave": "עזוב", + "would-like-to-share": "רוצה לשתף", + "accept": "קבל", + "decline": "סרב", + "has-sent": "שלח:", + "share": "שתף", + "send-message-to": "אל:", + "message_title": "הזן את ההודעה לשליחה", + "send": "שלח", + "copy": "העתק", + "base64-title-files": "שתף קבצים", + "base64-title-text": "שתף טקסט", + "base64-processing": "מעבד…", + "base64-tap-to-paste": "גע כאן כדי לשתף {{type}}", + "base64-paste-to-send": "הדבק כאן כדי לשתף {{type}}", + "base64-files": "קבצים", + "file-other-description-image": "ותמונה 1 אחרת", + "file-other-description-file": "וקובץ 1 אחר", + "file-other-description-image-plural": "ו{{count}} תמונות אחרות", + "file-other-description-file-plural": "ו{{count}} קבצים אחרים", + "title-image": "תמונה", + "title-image-plural": "תמונות", + "language-selector-title": "הגדר שפה", + "pair-devices-qr-code_title": "לחץ כדי להעתיק את הקישור כדי לבצע תיאום עם מכשיר זה", + "approve": "אשר", + "share-text-title": "שתף הודעת טקסט", + "share-text-subtitle": "ערוך את ההודעה לפני השליחה:", + "close-toast_title": "סגירת ההתראה" + }, + "about": { + "mastodon_title": "כתוב על PairDrop בMastodon", + "buy-me-a-coffee_title": "קנה לי קפה!", + "claim": "הדרך הקלה ביותר להעברת קבצים בין מכשירים", + "github_title": "PairDrop בGitHub", + "tweet_title": "צייץ על PairDrop", + "custom_title": "עקוב אחרינו", + "bluesky_title": "עקוב אחרינו בBlueSky", + "privacypolicy_title": "פתח את מדיניות הפרטיות שלנו", + "faq_title": "שאלות נפוצות", + "close-about_aria-label": "סגירת אודות PairDrop" + }, + "notifications": { + "display-name-changed-permanently": "שם התצוגה משתנה לתמיד", + "download-successful": "{{descriptor}} הורד", + "notifications-permissions-error": "ההרשאה להתראות נחסמה עקב סגירת חלונית בקשת ההרשאה מספר פעמים. אתה יכול לאפס זאת במידע על דף זה שניתן לגישה באמצעות לחיצה על אייקון המנעול ליד שורת הכתובת.", + "click-to-show": "לחץ כדי להציג", + "connecting": "מתחבר…", + "online": "הנך מחובר שוב לאינטרנט", + "pairing-cleared": "כל ההתאמות למכשירים הוסרו", + "pair-url-copied-to-clipboard": "הקישור להתאמת המכשיר הזה הועתק", + "connected": "מחובר", + "online-requirement-pairing": "אתה צריך להיות מחובר לאינטרנט כדי לתאם מכשירים", + "online-requirement-public-room": "אתה צריך להיות מחובר כדי ליצור חדר ציבורי", + "files-incorrect": "הקבצים שגויים", + "unfinished-transfers-warning": "יש עוד העברות שלא הסתיימו. אתה בטוח שאתה רוצה לסגור את PairDrop?", + "rate-limit-join-key": "הגעת למגבלה. חכה 10 שניות ונסה שנית.", + "selected-peer-left": "המכשיר הנבחר עזב", + "display-name-changed-temporarily": "שם התצוגה משתנה להפעלה זו בלבד", + "display-name-random-again": "שם התצוגה נוצר שוב באופן אקראי", + "pairing-tabs-error": "תיאום בין שני כרטיסיות בדפדפן אינו אפשרי", + "pairing-success": "המכשירים תואמו", + "pairing-not-persistent": "המכשירים המתואמים אינם קבועים", + "pairing-key-invalid": "קוד שגוי", + "pairing-key-invalidated": "הקוד {{key}} לא תקף עוד", + "public-room-id-invalid": "מזהה חדר שגוי", + "public-room-left": "עזבת את החדר הציבורי {{publicRoomId}}", + "copied-to-clipboard": "הועתק", + "room-url-copied-to-clipboard": "הקישור לחדר הציבורי הועתק", + "copied-to-clipboard-error": "העתקה אינה אפשרית. העתק ידנית.", + "text-content-incorrect": "תוכן הטקסט שגוי", + "file-content-incorrect": "תוכן הקובץ שגוי", + "clipboard-content-incorrect": "התוכן שהודבק שגוי", + "notifications-enabled": "ההתראות אופשרו", + "link-received": "קישור התקבל מ{{name}} - לחץ כדי לפתוח", + "message-received": "הודעה התקבלה מ{{name}} - לחץ כדי להעתיק", + "click-to-download": "לחץ כדי להוריד", + "request-title": "{{name}} רוצה לשלוח {{count}} {{descriptor}}", + "copied-text": "הטקסט הועתק", + "copied-text-error": "ההעתקה נכשלה. העתק ידנית!", + "offline": "הנך לא מחובר לאינטרנט", + "file-transfer-completed": "העברת הקובץ הושלמה בהצלחה", + "ios-memory-limit": "שליחת קבצים למכשירי iOS אפשרית רק עד 200 MB בבת אחת", + "message-transfer-completed": "העברת ההודעה הושלמה בהצלחה" + }, + "peer-ui": { + "click-to-send": "לחץ כדי לשלוח קבצים או בצע לחיצה ימנית כדי לשלוח הודעה", + "click-to-send-share-mode": "לחץ כדי לשלוח {{descriptor}}", + "connection-hash": "כדי לאמת את האבטחה של ההצפנה מצד לצד, השווה את מספר אבטחה זה בין שני המכשירים", + "preparing": "מתכונן…", + "waiting": "מחכה…", + "processing": "מעבד…", + "transferring": "מעביר…" + }, + "document-titles": { + "file-received": "הקובץ התקבל", + "file-received-plural": "{{count}} קבצים התקבלו", + "file-transfer-requested": "העברת קבצים מתבקשת", + "image-transfer-requested": "העברת תמונות מתבקשת", + "message-received": "התקבלה הודעה", + "message-received-plural": "{{count}} הודעות התקבלו" + } +} From 74e5e2286f5d54ac54d80251f11674a20d90c6b7 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 1 Jul 2024 18:33:01 +0200 Subject: [PATCH 010/111] Translated using Weblate (French) Currently translated at 100.0% (166 of 166 strings) Translated using Weblate (Czech) Currently translated at 3.0% (5 of 166 strings) Added translation using Weblate (Czech) Translated using Weblate (Catalan) Currently translated at 100.0% (166 of 166 strings) Co-authored-by: Guillaume Dorce Co-authored-by: Hosted Weblate Co-authored-by: Netleak Co-authored-by: gmassipg Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/ca/ Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/cs/ Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/fr/ Translation: PairDrop/pairdrop-spa --- public/lang/fr.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/public/lang/fr.json b/public/lang/fr.json index e72eefc..3c782ea 100644 --- a/public/lang/fr.json +++ b/public/lang/fr.json @@ -82,7 +82,7 @@ "copy": "Copier", "base64-processing": "Traitement…", "base64-tap-to-paste": "Appuyez ici pour partager {{type}}", - "base64-paste-to-send": "Coller ici pour partager {{type}}", + "base64-paste-to-send": "Coller le presse-papiers ici pour partager {{type}}", "base64-text": "texte", "base64-files": "fichiers", "file-other-description-image": "et 1 autre image", @@ -119,7 +119,8 @@ "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é" + "privacypolicy_title": "Ouvert sur notre politique de confidentialité", + "mastodon_title": "Écrire à propos de PairDrop sur Mastodon" }, "notifications": { "display-name-changed-permanently": "Le nom d'affichage est modifié de manière permanente", From 5625cb0ca657253d67cd982abcfebe0d342fc801 Mon Sep 17 00:00:00 2001 From: Hosted Weblate Date: Mon, 1 Jul 2024 18:33:01 +0200 Subject: [PATCH 011/111] Translated using Weblate (Korean) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently translated at 13.2% (22 of 166 strings) Added translation using Weblate (Korean) Co-authored-by: Hosted Weblate Co-authored-by: 뉴윈연구소 Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/ko/ Translation: PairDrop/pairdrop-spa --- public/lang/ko.json | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 public/lang/ko.json diff --git a/public/lang/ko.json b/public/lang/ko.json new file mode 100644 index 0000000..d367ce7 --- /dev/null +++ b/public/lang/ko.json @@ -0,0 +1,29 @@ +{ + "header": { + "notification_title": "알림 켜기", + "edit-paired-devices_title": "연결된 기기 편집하기", + "install_title": "PairDrop 설치", + "theme-dark_title": "항상 다크 테마 사용", + "about_title": "PairDrop에 대하여", + "language-selector_title": "언어 설정", + "about_aria-label": "PairDrop에 대하여 보기", + "theme-light_title": "항상 라이트 테마 사용", + "theme-auto_title": "시스템에 맞춰 테마 자동 적용", + "join-public-room_title": "일시적으로 공개 방에 참여하기", + "cancel-share-mode": "취소", + "edit-share-mode": "편집", + "pair-device_title": "영구적으로 기기 연결하기", + "expand_title": "머리글 버튼 행 펼치기" + }, + "instructions": { + "no-peers-subtitle": "장치를 연결하거나 공개 방에 들어가 다른 네트워크에서 검색 가능하게 하세요", + "no-peers_data-drop-bg": "해제하여 수신자 선택하기", + "x-instructions_mobile": "탭하여 파일을 보내거나 길게 탭하여 메시지를 보내세요", + "x-instructions_desktop": "클릭해 파일을 보내거나 오른쪽 클릭으로 메시지를 보내세요", + "no-peers-title": "다른 장치에서 PairDrop을 열어 파일 보내기", + "x-instructions_data-drop-bg": "해제하여 수신자 선택하기", + "x-instructions-share-mode_desktop": "클릭하여 {{descriptor}} 보내기", + "x-instructions-share-mode_mobile": "탭하여 {{descriptor}} 보내기", + "activate-share-mode-base": "다른 기기에서 PairDrop을 열어 보내기" + } +} From 5dd36da9621e5296a39cb07119e665ced1dec5f0 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Mon, 1 Jul 2024 18:47:26 +0200 Subject: [PATCH 012/111] Enable Belarusian, Danish, and Hebrew translations --- public/index.html | 15 +++++++++++++++ public/scripts/localization.js | 4 ++-- public/service-worker.js | 3 +++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/public/index.html b/public/index.html index 94c4f64..e62a112 100644 --- a/public/index.html +++ b/public/index.html @@ -192,11 +192,21 @@   -   (Arabic) + + + + + + - From 43c071b37fca336bb1001e9ca5577ba4bfdda0d8 Mon Sep 17 00:00:00 2001 From: schlagmichdoch Date: Tue, 11 Feb 2025 12:14:58 +0100 Subject: [PATCH 063/111] 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 064/111] 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 065/111] 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 066/111] 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 067/111] 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 068/111] 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 069/111] 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 070/111] 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 071/111] 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 072/111] 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 073/111] 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 074/111] 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 075/111] 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 076/111] 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 077/111] 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 078/111] 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 081/111] 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 082/111] 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 083/111] 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 084/111] 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 085/111] 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 086/111] 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 087/111] 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 088/111] 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 089/111] 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 090/111] =?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 091/111] 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 092/111] 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 093/111] 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 094/111] 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 095/111] 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 096/111] 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 097/111] 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 098/111] 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 099/111] 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 100/111] 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 101/111] 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 102/111] 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 103/111] 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 104/111] 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 105/111] 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 106/111] 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 107/111] 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 108/111] 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 109/111] 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 110/111] 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 111/111] 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);