Compare commits

..

14 Commits

Author SHA1 Message Date
schlagmichdoch 31ec776fb3 Only handle requests with the same origin via the service worker 2025-02-25 18:19:38 +01:00
schlagmichdoch 4862ba3067 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)
2025-02-24 20:46:32 +01:00
schlagmichdoch 7639aca84c Update node dependencies 2025-02-24 20:45:12 +01:00
schlagmichdoch 8b8e5b7433
Merge pull request #385 from weblate/weblate-pairdrop-pairdrop-spa
Translations update from Hosted Weblate
2025-02-24 20:34:56 +01:00
Hosted Weblate f6f3db2df9
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 <hosted@weblate.org>
Co-authored-by: maboroshin <maboroshin@users.noreply.hosted.weblate.org>
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
2025-02-24 20:34:40 +01:00
Hosted Weblate abd3a0c47c
Translated using Weblate (Bengali)
Currently translated at 17.4% (29 of 166 strings)

Co-authored-by: Hosted Weblate <hosted@weblate.org>
Co-authored-by: Saif Mahmud <saifmahmud366@gmail.com>
Translate-URL: https://hosted.weblate.org/projects/pairdrop/pairdrop-spa/bn/
Translation: PairDrop/pairdrop-spa
2025-02-24 20:34:40 +01:00
schlagmichdoch 89734e6954
Merge pull request #389 from schlagmichdoch/button-configs
Fix buttons on about page
2025-02-24 20:33:44 +01:00
schlagmichdoch 59bd9265bc
Merge pull request #390 from schlagmichdoch/fix-sw-updates
Fix service worker updates and speed up updates
2025-02-24 20:33:20 +01:00
schlagmichdoch dbd6321fec 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 2025-02-24 20:21:16 +01:00
schlagmichdoch d18e290ad4 Add missing files to paths that get cached upon sw installation 2025-02-24 20:18:53 +01:00
schlagmichdoch d7b68e214e Prevent fetch response and cache update if response is redirected 2025-02-24 20:17:54 +01:00
schlagmichdoch 148eb79ef0 Fix alphabetical sort in supportedLocales 2025-02-24 20:09:00 +01:00
schlagmichdoch 80615c533c Update Bluesky icon from square to butterfly 2025-02-23 19:20:50 +01:00
schlagmichdoch b0b091c4f7 FIX: switch off twitter button via env var not possible (#388) 2025-02-23 19:13:44 +01:00
10 changed files with 144 additions and 81 deletions

View File

@ -36,7 +36,7 @@ If applicable, add screenshots to help explain your problem.
**Bug occurs on official PairDrop instance https://pairdrop.net/** **Bug occurs on official PairDrop instance https://pairdrop.net/**
No | Yes No | Yes
Version: v1.11.1 Version: v1.11.2
**Bug occurs on self-hosted PairDrop instance** **Bug occurs on self-hosted PairDrop instance**
No | Yes No | Yes
@ -44,7 +44,7 @@ No | Yes
**Self-Hosted Setup** **Self-Hosted Setup**
Proxy: Nginx | Apache2 Proxy: Nginx | Apache2
Deployment: docker run | docker compose | npm run start:prod Deployment: docker run | docker compose | npm run start:prod
Version: v1.11.1 Version: v1.11.2
**Additional context** **Additional context**
Add any other context about the problem here. Add any other context about the problem here.

View File

@ -45,11 +45,11 @@ This pairdrop-cli version was released alongside v1.10.4
#### Linux / Mac #### Linux / Mac
1. Download the latest _pairdrop-cli.zip_ from the [releases page](https://github.com/schlagmichdoch/PairDrop/releases) 1. Download the latest _pairdrop-cli.zip_ from the [releases page](https://github.com/schlagmichdoch/PairDrop/releases)
```shell ```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 or
```shell ```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/` 2. Unzip the archive to a folder of your choice e.g. `/usr/share/pairdrop-cli/`
```shell ```shell

22
package-lock.json generated
View File

@ -1,12 +1,12 @@
{ {
"name": "pairdrop", "name": "pairdrop",
"version": "1.11.1", "version": "1.11.2",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "pairdrop", "name": "pairdrop",
"version": "1.11.1", "version": "1.11.2",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"express": "^4.18.2", "express": "^4.18.2",
@ -318,16 +318,16 @@
} }
}, },
"node_modules/get-intrinsic": { "node_modules/get-intrinsic": {
"version": "1.2.7", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.7.tgz", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"dependencies": { "dependencies": {
"call-bind-apply-helpers": "^1.0.1", "call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1", "es-define-property": "^1.0.1",
"es-errors": "^1.3.0", "es-errors": "^1.3.0",
"es-object-atoms": "^1.0.0", "es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2", "function-bind": "^1.1.2",
"get-proto": "^1.0.0", "get-proto": "^1.0.1",
"gopd": "^1.2.0", "gopd": "^1.2.0",
"has-symbols": "^1.1.0", "has-symbols": "^1.1.0",
"hasown": "^2.0.2", "hasown": "^2.0.2",
@ -815,9 +815,9 @@
} }
}, },
"node_modules/ws": { "node_modules/ws": {
"version": "8.18.0", "version": "8.18.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.1.tgz",
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", "integrity": "sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==",
"engines": { "engines": {
"node": ">=10.0.0" "node": ">=10.0.0"
}, },

View File

@ -1,6 +1,6 @@
{ {
"name": "pairdrop", "name": "pairdrop",
"version": "1.11.1", "version": "1.11.2",
"type": "module", "type": "module",
"description": "", "description": "",
"main": "server/index.js", "main": "server/index.js",

View File

@ -668,7 +668,7 @@
</svg> </svg>
<div class="title-wrapper" dir="ltr"> <div class="title-wrapper" dir="ltr">
<h1>PairDrop</h1> <h1>PairDrop</h1>
<div class="font-subheading">v1.11.1</div> <div class="font-subheading">v1.11.2</div>
</div> </div>
<div class="font-subheading" data-i18n-key="about.claim" data-i18n-attrs="text"></div> <div class="font-subheading" data-i18n-key="about.claim" data-i18n-attrs="text"></div>
<div class="row"> <div class="row">
@ -811,9 +811,9 @@
<!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--> <!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.-->
<path d="M433 179.1c0-97.2-63.7-125.7-63.7-125.7-62.5-28.7-228.6-28.4-290.5 0 0 0-63.7 28.5-63.7 125.7 0 115.7-6.6 259.4 105.6 289.1 40.5 10.7 75.3 13 103.3 11.4 50.8-2.8 79.3-18.1 79.3-18.1l-1.7-36.9s-36.3 11.4-77.1 10.1c-40.4-1.4-83-4.4-89.6-54a102.5 102.5 0 0 1 -.9-13.9c85.6 20.9 158.7 9.1 178.8 6.7 56.1-6.7 105-41.3 111.2-72.9 9.8-49.8 9-121.5 9-121.5zm-75.1 125.2h-46.6v-114.2c0-49.7-64-51.6-64 6.9v62.5h-46.3V197c0-58.5-64-56.6-64-6.9v114.2H90.2c0-122.1-5.2-147.9 18.4-175 25.9-28.9 79.8-30.8 103.8 6.1l11.6 19.5 11.6-19.5c24.1-37.1 78.1-34.8 103.8-6.1 23.7 27.3 18.4 53 18.4 175z"></path> <path d="M433 179.1c0-97.2-63.7-125.7-63.7-125.7-62.5-28.7-228.6-28.4-290.5 0 0 0-63.7 28.5-63.7 125.7 0 115.7-6.6 259.4 105.6 289.1 40.5 10.7 75.3 13 103.3 11.4 50.8-2.8 79.3-18.1 79.3-18.1l-1.7-36.9s-36.3 11.4-77.1 10.1c-40.4-1.4-83-4.4-89.6-54a102.5 102.5 0 0 1 -.9-13.9c85.6 20.9 158.7 9.1 178.8 6.7 56.1-6.7 105-41.3 111.2-72.9 9.8-49.8 9-121.5 9-121.5zm-75.1 125.2h-46.6v-114.2c0-49.7-64-51.6-64 6.9v62.5h-46.3V197c0-58.5-64-56.6-64-6.9v114.2H90.2c0-122.1-5.2-147.9 18.4-175 25.9-28.9 79.8-30.8 103.8 6.1l11.6 19.5 11.6-19.5c24.1-37.1 78.1-34.8 103.8-6.1 23.7 27.3 18.4 53 18.4 175z"></path>
</symbol> </symbol>
<symbol id="bluesky" viewBox="0 0 448 512"> <symbol id="bluesky" viewBox="0 0 512 512">
<!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--> <!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.-->
<path d="M0 96C0 60.7 28.7 32 64 32H384c35.3 0 64 28.7 64 64V416c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V96z"></path> <path d="M111.8 62.2C170.2 105.9 233 194.7 256 242.4c23-47.6 85.8-136.4 144.2-180.2c42.1-31.6 110.3-56 110.3 21.8c0 15.5-8.9 130.5-14.1 149.2C478.2 298 412 314.6 353.1 304.5c102.9 17.5 129.1 75.5 72.5 133.5c-107.4 110.2-154.3-27.6-166.3-62.9l0 0c-1.7-4.9-2.6-7.8-3.3-7.8s-1.6 3-3.3 7.8l0 0c-12 35.3-59 173.1-166.3 62.9c-56.5-58-30.4-116 72.5-133.5C100 314.6 33.8 298 15.7 233.1C10.4 214.4 1.5 99.4 1.5 83.9c0-77.8 68.2-53.4 110.3-21.8z"/>
</symbol> </symbol>
<symbol id="custom" viewBox="0 0 512 512"> <symbol id="custom" viewBox="0 0 512 512">
<!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.--> <!--!Font Awesome Free 6.5.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2023 Fonticons, Inc.-->

View File

@ -1,6 +1,35 @@
{ {
"header": { "header": {
"about_title": "পেয়ার ড্রপ সম্পর্কে", "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": "পাঠানো ফাইল গুলো"
} }
} }

View File

@ -1,17 +1,17 @@
{ {
"footer": { "footer": {
"webrtc": "(WebRTCが無効なため)", "webrtc": "(WebRTCが無効なため)",
"public-room-devices_title": "公開ルーム内のデバイスは、接続中のネットワークと関係なくアクセスできます。", "public-room-devices_title": "公開ルーム内のデバイスは、別のネットワークからもアクセスできます。",
"display-name_data-placeholder": "読み込み中…", "display-name_data-placeholder": "読み込み中…",
"display-name_title": "デバイス名を変更する", "display-name_title": "デバイス名を変更する",
"traffic": "この通信は", "traffic": "この通信は",
"paired-devices_title": "ペアリング済みデバイスであれば、接続中のネットワークに関わらずアクセスできます。", "paired-devices_title": "ペアリング済みデバイスは、別のネットワークからもアクセスできます。",
"public-room-devices": "ルーム{{roomId}}", "public-room-devices": "ルーム{{roomId}}",
"paired-devices": "ペアリング済みデバイス", "paired-devices": "ペアリング済みデバイス",
"on-this-network": "このネットワーク", "on-this-network": "このネットワーク",
"routed": "サーバーを経由します", "routed": "サーバーを経由します",
"discovery": "このデバイスを検出可能なネットワーク:", "discovery": "このデバイスを検出可能なネットワーク:",
"on-this-network_title": "このネットワークのすべてのデバイスからアクセスできます。", "on-this-network_title": "このネットワークのすべてのデバイスからアクセスできます。",
"known-as": "このデバイスの名前:" "known-as": "このデバイスの名前:"
}, },
"notifications": { "notifications": {
@ -20,9 +20,9 @@
"message-received": "{{name}}から受信したメッセージ(クリックしてコピー)", "message-received": "{{name}}から受信したメッセージ(クリックしてコピー)",
"rate-limit-join-key": "レート制限に到達しました。10秒待ってから再度お試しください。", "rate-limit-join-key": "レート制限に到達しました。10秒待ってから再度お試しください。",
"connecting": "接続中…", "connecting": "接続中…",
"pairing-key-invalidated": "コード{{key}}が失効しました", "pairing-key-invalidated": "コード{{key}}は無効になりました",
"pairing-key-invalid": "無効なコード", "pairing-key-invalid": "無効なコード",
"connected": "接続しました", "connected": "接続済み",
"pairing-not-persistent": "このデバイスとのペアリングは解除される可能性があります", "pairing-not-persistent": "このデバイスとのペアリングは解除される可能性があります",
"text-content-incorrect": "無効なテキスト内容です", "text-content-incorrect": "無効なテキスト内容です",
"message-transfer-completed": "メッセージを送信しました", "message-transfer-completed": "メッセージを送信しました",
@ -39,7 +39,7 @@
"copied-to-clipboard-error": "コピーできませんでした。手動でコピーしてください。", "copied-to-clipboard-error": "コピーできませんでした。手動でコピーしてください。",
"pairing-success": "ペアリングしました", "pairing-success": "ペアリングしました",
"clipboard-content-incorrect": "無効なクリップボード内容です", "clipboard-content-incorrect": "無効なクリップボード内容です",
"display-name-changed-temporarily": "この接続のみデバイス名が変更されました", "display-name-changed-temporarily": "この接続のみデバイス名が変更されました",
"copied-to-clipboard": "クリップボードにコピーしました", "copied-to-clipboard": "クリップボードにコピーしました",
"offline": "オフラインです", "offline": "オフラインです",
"pairing-tabs-error": "同じWebブラウザーで開いたタブ同士でペアリングすることはできません", "pairing-tabs-error": "同じWebブラウザーで開いたタブ同士でペアリングすることはできません",
@ -79,9 +79,9 @@
"activate-share-mode-and-other-files-plural": "とその他{{count}}個のファイル", "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を開いて送信します", "activate-share-mode-base": "他のデバイスでPairDropを開いて送信します",
"no-peers-subtitle": "ペアリングや公開ルームを使用すると、他のネットワーク上のデバイスと共有できます", "no-peers-subtitle": "ペアリングや公開ルームを使うと、別のネットワークにあるデバイスと共有できます",
"activate-share-mode-shared-text": "共有されたテキスト", "activate-share-mode-shared-text": "共有されたテキスト",
"x-instructions_desktop": "左クリックでファイル送信、右クリックでメッセージ送信します", "x-instructions_desktop": "左クリックでファイル送信、右クリックでメッセージ送信",
"no-peers-title": "ファイル共有するには他のデバイスでPairDropを開きます", "no-peers-title": "ファイル共有するには他のデバイスでPairDropを開きます",
"x-instructions_data-drop-peer": "ドロップするとこのデバイスに送信します", "x-instructions_data-drop-peer": "ドロップするとこのデバイスに送信します",
"x-instructions_data-drop-bg": "送信したいデバイスの上でドロップしてください", "x-instructions_data-drop-bg": "送信したいデバイスの上でドロップしてください",
@ -94,7 +94,7 @@
"peer-ui": { "peer-ui": {
"processing": "処理中…", "processing": "処理中…",
"click-to-send-share-mode": "クリックして{{descriptor}}を送信", "click-to-send-share-mode": "クリックして{{descriptor}}を送信",
"click-to-send": "左クリックでファイル送信、右クリックでメッセージ送信します", "click-to-send": "左クリックでファイル送信、右クリックでメッセージ送信",
"waiting": "待機中…", "waiting": "待機中…",
"connection-hash": "エンドツーエンド暗号化のセキュリティを確認するには、両方のデバイスのセキュリティナンバーを確認してください", "connection-hash": "エンドツーエンド暗号化のセキュリティを確認するには、両方のデバイスのセキュリティナンバーを確認してください",
"preparing": "準備中…", "preparing": "準備中…",
@ -102,7 +102,7 @@
}, },
"dialogs": { "dialogs": {
"base64-paste-to-send": "ここをタップして{{type}}を送信", "base64-paste-to-send": "ここをタップして{{type}}を送信",
"auto-accept-instructions-2": "」を有効にすると、そのデバイスから送信されたすべてのファイルを自動的に受け入れます。", "auto-accept-instructions-2": "」が有効なら、そのデバイスが送信したすべてのファイルを自動で受け入れます。",
"receive-text-title": "メッセージを受信", "receive-text-title": "メッセージを受信",
"edit-paired-devices-title": "ペアリング設定", "edit-paired-devices-title": "ペアリング設定",
"cancel": "キャンセル", "cancel": "キャンセル",
@ -126,7 +126,7 @@
"has-sent": "が送信:", "has-sent": "が送信:",
"file-other-description-file": "とその他1個のファイル", "file-other-description-file": "とその他1個のファイル",
"close": "閉じる", "close": "閉じる",
"system-language": "システム言語", "system-language": "システム言語",
"unpair": "ペアリング解除", "unpair": "ペアリング解除",
"title-image": "画像", "title-image": "画像",
"file-other-description-file-plural": "とその他{{count}}個のファイル", "file-other-description-file-plural": "とその他{{count}}個のファイル",
@ -135,7 +135,7 @@
"language-selector-title": "言語設定", "language-selector-title": "言語設定",
"pair": "ペアリング", "pair": "ペアリング",
"hr-or": "または", "hr-or": "または",
"scan-qr-code": "もしくはQRコードをスキャンしてください。", "scan-qr-code": "QRコードをスキャンしてください。",
"input-key-on-this-device": "このコードを他のデバイスに入力するか", "input-key-on-this-device": "このコードを他のデバイスに入力するか",
"download-again": "もう一度ダウンロードする", "download-again": "もう一度ダウンロードする",
"accept": "承諾", "accept": "承諾",
@ -162,13 +162,13 @@
"share-text-title": "テキストメッセージを共有します" "share-text-title": "テキストメッセージを共有します"
}, },
"about": { "about": {
"claim": "デバイス間のファイル共有を手軽に実現します", "claim": "デバイス間でかんたんファイル共有",
"tweet_title": "PairDropのことをポストする", "tweet_title": "PairDropについてポスト",
"close-about_aria-label": "PairDropについてを閉じる", "close-about_aria-label": "PairDropについてを閉じる",
"buy-me-a-coffee_title": "コーヒーを一杯おごってください!", "buy-me-a-coffee_title": "コーヒーを一杯おごってください!",
"github_title": "PairDrop on GitHub", "github_title": "GitHub上のPairDropプロジェクト",
"faq_title": "FAQ", "faq_title": "FAQ",
"mastodon_title": "MastodonにPairDropのことをトゥートする", "mastodon_title": "MastodonでPairDropについてトゥート",
"bluesky_title": "BlueSkyでフォロー", "bluesky_title": "BlueSkyでフォロー",
"custom_title": "フォロー", "custom_title": "フォロー",
"privacypolicy_title": "プライバシーポリシーを開く" "privacypolicy_title": "プライバシーポリシーを開く"

View File

@ -5,7 +5,7 @@ class Localization {
Localization.defaultLocale = "en"; Localization.defaultLocale = "en";
Localization.supportedLocales = [ Localization.supportedLocales = [
"ar", "be", "bg", "ca", "cs", "da", "de", "en", "es", "et", "eu", "fa", "fr", "he", "hu", "id", "it", "ja", "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"]; Localization.supportedLocalesRtl = ["ar", "he"];

View File

@ -2404,7 +2404,7 @@ class Base64Dialog extends Dialog {
class AboutUI { class AboutUI {
constructor() { constructor() {
this.$donationBtn = $('donation-btn'); this.$donationBtn = $('donation-btn');
this.$twitterBtn = $('twitter-btn'); this.$twitterBtn = $('x-twitter-btn');
this.$mastodonBtn = $('mastodon-btn'); this.$mastodonBtn = $('mastodon-btn');
this.$blueskyBtn = $('bluesky-btn'); this.$blueskyBtn = $('bluesky-btn');
this.$customBtn = $('custom-btn'); this.$customBtn = $('custom-btn');

View File

@ -1,12 +1,12 @@
const cacheVersion = 'v1.11.1'; const cacheVersion = 'v1.11.2';
const cacheTitle = `pairdrop-cache-${cacheVersion}`; const cacheTitle = `pairdrop-cache-${cacheVersion}`;
const forceFetch = false; // FOR DEVELOPMENT: Set to true to always update assets instead of using cached versions
const relativePathsToCache = [ const relativePathsToCache = [
'./', './',
'index.html', 'index.html',
'manifest.json', 'manifest.json',
'styles/styles-main.css', 'styles/styles-main.css',
'styles/styles-deferred.css', 'styles/styles-deferred.css',
'scripts/browser-tabs-connector.js',
'scripts/localization.js', 'scripts/localization.js',
'scripts/main.js', 'scripts/main.js',
'scripts/network.js', 'scripts/network.js',
@ -28,14 +28,19 @@ const relativePathsToCache = [
'images/android-chrome-512x512.png', 'images/android-chrome-512x512.png',
'images/android-chrome-512x512-maskable.png', 'images/android-chrome-512x512-maskable.png',
'images/apple-touch-icon.png', 'images/apple-touch-icon.png',
'fonts/OpenSans/static/OpenSans-Medium.ttf',
'lang/ar.json', 'lang/ar.json',
'lang/be.json', 'lang/be.json',
'lang/bg.json',
'lang/ca.json', 'lang/ca.json',
'lang/cs.json', 'lang/cs.json',
'lang/da.json', 'lang/da.json',
'lang/de.json', 'lang/de.json',
'lang/en.json', 'lang/en.json',
'lang/es.json', 'lang/es.json',
'lang/et.json',
'lang/eu.json',
'lang/fa.json',
'lang/fr.json', 'lang/fr.json',
'lang/he.json', 'lang/he.json',
'lang/hu.json', 'lang/hu.json',
@ -43,15 +48,20 @@ const relativePathsToCache = [
'lang/it.json', 'lang/it.json',
'lang/ja.json', 'lang/ja.json',
'lang/kn.json', 'lang/kn.json',
'lang/ko.json',
'lang/nb.json', 'lang/nb.json',
'lang/nl.json', 'lang/nl.json',
'lang/nn.json',
'lang/pl.json', 'lang/pl.json',
'lang/pt-BR.json', 'lang/pt-BR.json',
'lang/ro.json', 'lang/ro.json',
'lang/ru.json', 'lang/ru.json',
'lang/sk.json',
'lang/ta.json',
'lang/tr.json', 'lang/tr.json',
'lang/uk.json', 'lang/uk.json',
'lang/zh-CN.json', 'lang/zh-CN.json',
'lang/zh-HK.json',
'lang/zh-TW.json' 'lang/zh-TW.json'
]; ];
const relativePathsNotToCache = [ const relativePathsNotToCache = [
@ -60,13 +70,15 @@ const relativePathsNotToCache = [
self.addEventListener('install', function(event) { self.addEventListener('install', function(event) {
// Perform install steps // Perform install steps
console.log("Cache files for sw:", cacheVersion);
event.waitUntil( event.waitUntil(
caches.open(cacheTitle) caches.open(cacheTitle)
.then(function(cache) { .then(function(cache) {
return cache return cache
.addAll(relativePathsToCache) .addAll(relativePathsToCache)
.then(_ => { .then(_ => {
console.log('All files cached.'); console.log('All files cached for sw:', cacheVersion);
self.skipWaiting();
}); });
}) })
); );
@ -76,20 +88,25 @@ self.addEventListener('install', function(event) {
const fromNetwork = (request, timeout) => const fromNetwork = (request, timeout) =>
new Promise((resolve, reject) => { new Promise((resolve, reject) => {
const timeoutId = setTimeout(reject, timeout); const timeoutId = setTimeout(reject, timeout);
fetch(request) fetch(request, {cache: "no-store"})
.then(response => { .then(response => {
if (response.redirected) {
throw new Error("Fetch is redirect. Abort usage and cache!");
}
clearTimeout(timeoutId); clearTimeout(timeoutId);
resolve(response); resolve(response);
// Prevent requests that are in relativePathsNotToCache from being cached
if (doNotCacheRequest(request)) return; if (doNotCacheRequest(request)) return;
update(request) updateCache(request)
.then(() => console.log("Cache successfully updated for", request.url)) .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 => { .catch(error => {
// Handle any errors that occurred during the fetch // 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); reject(error);
}); });
}); });
@ -111,16 +128,16 @@ const doNotCacheRequest = request => {
}; };
// cache the current page to make it available for offline // cache the current page to make it available for offline
const update = request => new Promise((resolve, reject) => { const updateCache = request => new Promise((resolve, reject) => {
if (doNotCacheRequest(request)) {
reject("Url is specifically prevented from being cached in the serviceworker.");
return;
}
caches caches
.open(cacheTitle) .open(cacheTitle)
.then(cache => .then(cache =>
fetch(request, {cache: "no-store"}) fetch(request, {cache: "no-store"})
.then(response => { .then(response => {
if (response.redirected) {
throw new Error("Fetch is redirect. Abort usage and cache!");
}
cache cache
.put(request, response) .put(request, response)
.then(() => resolve()); .then(() => resolve());
@ -129,11 +146,19 @@ const update = request => new Promise((resolve, reject) => {
); );
}); });
// general strategy when making a request (eg if online try to fetch it // general strategy when making a request:
// from cache, if something fails fetch from network. Update cache everytime files are fetched. // 1. Try to retrieve file from cache
// This way files should only be fetched if cacheVersion is changed // 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) { 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. // Requests related to Web Share Target.
event.respondWith((async () => { event.respondWith((async () => {
const share_url = await evaluateRequestData(event.request); const share_url = await evaluateRequestData(event.request);
@ -141,39 +166,48 @@ self.addEventListener('fetch', function(event) {
})()); })());
} }
else { else {
// Regular requests not related to Web Share Target. // Regular requests not related to Web Share Target:
if (forceFetch) { // If request is excluded from cache -> respondWith fromNetwork
event.respondWith(fromNetwork(event.request, 10000)); // else -> try fromCache first
}
else {
event.respondWith( event.respondWith(
fromCache(event.request) doNotCacheRequest(event.request)
? fromNetwork(event.request, 10000)
: fromCache(event.request)
.then(rsp => { .then(rsp => {
// if fromCache resolves to undefined fetch from network instead // 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 // on activation, we clean up the previously registered service workers
self.addEventListener('activate', evt => { self.addEventListener('activate', evt => {
console.log("Activate sw:", cacheVersion);
evt.waitUntil(clients.claim());
return evt.waitUntil( return evt.waitUntil(
caches.keys() caches
.keys()
.then(cacheNames => { .then(cacheNames => {
return Promise.all( return Promise.all(
cacheNames.map(cacheName => { cacheNames.map(cacheName => {
if (cacheName !== cacheTitle) { if (cacheName !== cacheTitle) {
console.log("Delete cache:", cacheName);
return caches.delete(cacheName); return caches.delete(cacheName);
} }
}) })
); );
}) })
) )
} });
);
const evaluateRequestData = function (request) { const evaluateRequestData = function (request) {
return new Promise(async (resolve) => { return new Promise(async (resolve) => {