mirror of
https://github.com/schlagmichdoch/PairDrop.git
synced 2026-04-23 07:30:54 +08:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d6287c4cf0 | |||
| c83e55b448 | |||
| 49160f9b02 | |||
| 7be2830a08 | |||
| 1f3dd080a0 | |||
| 5d709966af | |||
| 99b0c6ff01 | |||
| 76e08927de | |||
| 9118b0ae06 | |||
| b36105b1cf | |||
| ad4f727d19 | |||
| f048c4f1bd | |||
| 6c1672ba25 | |||
| caf19bdb45 | |||
| 5dcda58ce5 | |||
| 4a5a2ceb67 | |||
| 214d557feb |
@@ -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.10.6
|
Version: v1.10.7
|
||||||
|
|
||||||
**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.10.6
|
Version: v1.10.7
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context about the problem here.
|
Add any other context about the problem here.
|
||||||
|
|||||||
@@ -3,133 +3,127 @@
|
|||||||
<img src="public/images/android-chrome-512x512.png" alt="Logo" width="150" height="150">
|
<img src="public/images/android-chrome-512x512.png" alt="Logo" width="150" height="150">
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
<h1>PairDrop</h1>
|
# _Send it_, with [PairDrop](https://pairdrop.net)
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Local file sharing in your browser. Inspired by Apple's AirDrop.
|
Local file sharing <a href="https://pairdrop.net"><strong>in your web browser</strong></a>.
|
||||||
<br />
|
|
||||||
<a href="https://pairdrop.net"><strong>Explore »</strong></a>
|
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<a href="https://github.com/schlagmichdoch/PairDrop/issues">Report Bug</a>
|
<a href="https://github.com/schlagmichdoch/PairDrop/issues">Report a bug</a>
|
||||||
·
|
<br />
|
||||||
<a href="https://github.com/schlagmichdoch/PairDrop/issues">Request Feature</a>
|
<a href="https://github.com/schlagmichdoch/PairDrop/issues">Request feature</a>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
[PairDrop](https://pairdrop.net) is a sublime alternative to AirDrop that works on all platforms.
|
File sharing on your local network that works on all platforms.
|
||||||
|
|
||||||
- File Sharing on your local network
|
- A multi-platform AirDrop-like solution that works.
|
||||||
- Send images, documents or text via peer to peer connection to devices on the same local network.
|
- Send images, documents or text via peer-to-peer connection to devices on the same local network.
|
||||||
- Internet Transfers
|
- Internet transfers
|
||||||
- Join temporary public rooms to transfer files easily over the internet!
|
- Join temporary public rooms to transfer files easily over the Internet.
|
||||||
- Web-Application
|
- Web-app
|
||||||
- As it is web based, it runs on all devices.
|
- Works on all devices with a modern web-browser.
|
||||||
|
|
||||||
|
Send a file from your phone to your laptop?
|
||||||
|
<br>Share photos in original quality with friends using Android and iOS?
|
||||||
|
<br>Share private files peer-to-peer between Linux systems?
|
||||||
|
|
||||||
You want to quickly send a file from your phone to your laptop?
|
<img src="docs/pairdrop_screenshot_mobile.gif" alt="Screenshot GIF showing PairDrop in use" style="width: 300px">
|
||||||
<br>You want to share photos in original quality with friends that use a mixture of Android and iOS?
|
|
||||||
<br>You want to share private files peer to peer between Linux systems?
|
|
||||||
<br>AirDrop is unreliable again?
|
|
||||||
<br>_Send it with PairDrop!_
|
|
||||||
|
|
||||||
Developed based on [Snapdrop](https://github.com/RobinLinus/snapdrop)
|
## Differences to the [Snapdrop](https://github.com/RobinLinus/snapdrop) it is based on
|
||||||
|
<details><summary>List view</summary>
|
||||||
|
|
||||||
## Differences to Snapdrop
|
### Paired Devices and Public Rooms — Internet Transfer
|
||||||
<details><summary>Click to expand</summary>
|
* Transfer files over the Internet between paired devices or by entering temporary public rooms.
|
||||||
|
* Connect to devices in complex network environments (public Wi-Fi, company network, iCloud Private Relay, VPN, etc.).
|
||||||
### Paired Devices and Public Rooms - Internet Transfer
|
|
||||||
* Transfer files over the internet between paired devices or by entering temporary public rooms.
|
|
||||||
* Connect to devices in complex network environments (public Wi-Fi, company network, Apple Private Relay, VPN etc.).
|
|
||||||
* Connect to devices on your mobile hotspot.
|
* Connect to devices on your mobile hotspot.
|
||||||
* Devices outside your local network that are behind a NAT are connected automatically via the PairDrop TURN server.
|
* Devices outside of your local network that are behind a NAT are auto-connected via the PairDrop TURN server.
|
||||||
* Connect to devices on your mobile hotspot.
|
* Connect to devices on your mobile hotspot.
|
||||||
* You will always discover devices on your local network. Paired devices and devices in the same public room are shown additionally.
|
* Devices from the local network, in the same public room, or previously paired are shown.
|
||||||
|
|
||||||
#### Persistent Device Pairing
|
#### Persistent Device Pairing
|
||||||
* Pair your devices via a 6-digit code or a QR-Code.
|
|
||||||
* Paired devices will always find each other via shared secrets independently of their local network.
|
Always connect to known devices
|
||||||
* Paired devices are persistent. You find your devices even after reopening PairDrop.
|
|
||||||
* You can edit and unpair devices easily
|
* Pair devices via a 6-digit code or a QR-Code.
|
||||||
* Ideal to always connect easily to your own devices
|
* Paired devices always find each other via shared secrets independently of their local network.
|
||||||
|
* Pairing is persistent. You find your devices even after reopening PairDrop.
|
||||||
|
* You can edit and unpair devices easily.
|
||||||
|
|
||||||
#### Temporary Public Rooms
|
#### Temporary Public Rooms
|
||||||
* Enter a public room via a 5-letter code or a QR-Code.
|
|
||||||
* Enter a public room to temporarily connect to devices outside your local network.
|
|
||||||
* All devices in the same public room see each other mutually.
|
|
||||||
* Public rooms are temporary. Public rooms are left as soon as PairDrop is closed.
|
|
||||||
* Ideal to connect easily to others in complex network situations or over the internet.
|
|
||||||
|
|
||||||
### [Improved UI for sending/receiving files](https://github.com/RobinLinus/snapdrop/issues/560)
|
Connect to others in complex network situations, or over the Internet.
|
||||||
* Files are transferred only after a request is accepted first. On transfer completion files are downloaded automatically if possible.
|
|
||||||
|
* Enter a public room via a 5-letter code or a QR-code.
|
||||||
|
* Enter a public room to temporarily connect to devices outside your local network.
|
||||||
|
* All devices in the same public room see each other.
|
||||||
|
* Public rooms are temporary. Closing PairDrop leaves all rooms.
|
||||||
|
|
||||||
|
### [Improved UI for Sending/Receiving Files](https://github.com/RobinLinus/snapdrop/issues/560)
|
||||||
|
* Files are transferred after a request is accepted. Files are auto-downloaded upon completing a transfer, if possible.
|
||||||
* Multiple files are downloaded as a ZIP file
|
* Multiple files are downloaded as a ZIP file
|
||||||
* On iOS and Android, in addition to downloading, files can be shared or saved to the gallery via the Share menu.
|
* Download, share or save to gallery via the "Share" menu on Android and iOS.
|
||||||
* Multiple files are transferred at once with an overall progress indicator
|
* Multiple files are transferred at once with an overall progress indicator.
|
||||||
|
|
||||||
### Send Files or Text Directly From Share Menu, Context Menu or CLI
|
### Send Files or Text Directly From Share Menu, Context Menu or CLI
|
||||||
* [Send files directly from context menu on Windows](docs/how-to.md#send-multiple-files-and-directories-directly-from-context-menu-on-windows)
|
* [Send files directly from context menu on Ubuntu (using Nautilus)](docs/how-to.md#send-multiple-files-and-directories-directly-from-context-menu-on-ubuntu-using-nautilus)
|
||||||
* [Send files directly from context menu on Ubuntu (using Nautilus)](/docs/how-to.md#send-multiple-files-and-directories-directly-from-context-menu-on-ubuntu-using-nautilus)
|
* [Send files directly from the context menu on Windows](docs/how-to.md#send-files-directly-from-context-menu-on-windows)
|
||||||
* [Send files directly from share menu on iOS](docs/how-to.md#send-directly-from-share-menu-on-ios)
|
* [Send directly from the "Share" menu on iOS](docs/how-to.md#send-directly-from-share-menu-on-ios)
|
||||||
* [Send files directly from share menu on Android](docs/how-to.md#send-directly-from-share-menu-on-android)
|
* [Send directly from the "Share" menu on Android](docs/how-to.md#send-directly-from-share-menu-on-android)
|
||||||
* [Send files directly via command-line interface](docs/how-to.md#send-directly-via-command-line-interface)
|
* [Send directly via the command-line interface](docs/how-to.md#send-directly-via-command-line-interface)
|
||||||
|
|
||||||
### Other changes
|
### Other Changes
|
||||||
* Change your display name permanently to easily differentiate your devices
|
* Change your display name to easily differentiate your devices.
|
||||||
* [Paste files/text and choose the recipient afterwords ](https://github.com/RobinLinus/snapdrop/pull/534)
|
* [Paste files/text and choose the recipient afterwards ](https://github.com/RobinLinus/snapdrop/pull/534)
|
||||||
* [Prevent devices from sleeping on file transfer](https://github.com/RobinLinus/snapdrop/pull/413)
|
* [Prevent devices from sleeping on file transfer](https://github.com/RobinLinus/snapdrop/pull/413)
|
||||||
* Warn user before PairDrop is closed on file transfer
|
* Warn user before PairDrop is closed on file transfer
|
||||||
* Open PairDrop on multiple tabs simultaneously (Thanks [@willstott101](https://github.com/willstott101))
|
* Open PairDrop on multiple tabs simultaneously (Thanks [@willstott101](https://github.com/willstott101))
|
||||||
* [Video and Audio preview](https://github.com/RobinLinus/snapdrop/pull/455) (Thanks [@victorwads](https://github.com/victorwads))
|
* [Video and audio preview](https://github.com/RobinLinus/snapdrop/pull/455) (Thanks [@victorwads](https://github.com/victorwads))
|
||||||
* Switch theme back to auto/system after darkmode or lightmode is enabled
|
* Switch theme back to auto/system after dark or light mode is on
|
||||||
* Node-only implementation (Thanks [@Bellisario](https://github.com/Bellisario))
|
* Node-only implementation (Thanks [@Bellisario](https://github.com/Bellisario))
|
||||||
* Automatic restart on error (Thanks [@KaKi87](https://github.com/KaKi87))
|
* Auto-restart on error (Thanks [@KaKi87](https://github.com/KaKi87))
|
||||||
* Lots of stability fixes (Thanks [@MWY001](https://github.com/MWY001) [@skiby7](https://github.com/skiby7) and [@willstott101](https://github.com/willstott101))
|
* Lots of stability fixes (Thanks [@MWY001](https://github.com/MWY001) [@skiby7](https://github.com/skiby7) and [@willstott101](https://github.com/willstott101))
|
||||||
* To host PairDrop on your local network (e.g. on Raspberry Pi): [All peers connected with private IPs are discoverable by each other](https://github.com/RobinLinus/snapdrop/pull/558)
|
* To host PairDrop on your local network (e.g. on Raspberry Pi): [All peers connected with private IPs are discoverable by each other](https://github.com/RobinLinus/snapdrop/pull/558)
|
||||||
* When hosting PairDrop yourself you can [set your own STUN/TURN servers](docs/host-your-own.md#specify-stunturn-servers)
|
* When hosting PairDrop yourself, you can [set your own STUN/TURN servers](docs/host-your-own.md#specify-stunturn-servers)
|
||||||
* Built-in translations via [Weblate](https://hosted.weblate.org/engage/pairdrop/)
|
* Translations.
|
||||||
* Airy design (Thanks [@Avieshek](https://linktr.ee/avieshek/))
|
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## Screenshots
|
## Translate PairDrop on [Hosted Weblate](https://hosted.weblate.org/engage/pairdrop/)
|
||||||
<img src="docs/pairdrop_screenshot_mobile.gif" alt="Gif of Screenshots that show PairDrop in use" style="width: 300px">
|
|
||||||
|
|
||||||
## PairDrop is built with the following awesome technologies:
|
|
||||||
* Vanilla HTML5 / ES6 / CSS3 frontend
|
|
||||||
* [WebRTC](http://webrtc.org/) / [WebSockets](http://www.websocket.org/)
|
|
||||||
* [NodeJS](https://nodejs.org/en/) backend
|
|
||||||
* [Progressive Web App](https://wikipedia.org/wiki/Progressive_Web_App)
|
|
||||||
* [IndexedDB API](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API)
|
|
||||||
* [Weblate](https://weblate.org/) Web based localization tool
|
|
||||||
* [zip.js](https://github.com/gildas-lormeau/zip.js) JavaScript library to zip and unzip files ([BSD 3-Clause License](licenses/BSD_3-Clause-zip-js))
|
|
||||||
* [NoSleep](https://github.com/richtr/NoSleep.js) JavaScript library to prevent display sleep and enable wake lock in any Android or iOS web browser ([MIT License](licenses/MIT-NoSleep))
|
|
||||||
* [heic2any](https://github.com/alexcorvi/heic2any) JavaScript library to convert HEIC/HEIF images to PNG/GIF/JPEG ([MIT License](licenses/MIT-heic2any))
|
|
||||||
* [cyrb53](https://github.com/bryc) Super fast hash function
|
|
||||||
|
|
||||||
Have any questions? Read our [FAQ](docs/faq.md).
|
|
||||||
|
|
||||||
You can [host your own instance with Docker](docs/host-your-own.md).
|
|
||||||
|
|
||||||
|
|
||||||
## Support PairDrop
|
|
||||||
<a href="https://www.buymeacoffee.com/pairdrop" target="_blank">
|
|
||||||
<img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" >
|
|
||||||
</a>
|
|
||||||
|
|
||||||
PairDrop is free and always will be.
|
|
||||||
Still, we have to pay for the domain and the server.
|
|
||||||
|
|
||||||
To contribute and support, please use BuyMeACoffee via the button above.
|
|
||||||
|
|
||||||
Thanks a lot for supporting free and open software!
|
|
||||||
|
|
||||||
## Translate PairDrop
|
|
||||||
<a href="https://hosted.weblate.org/engage/pairdrop/">
|
<a href="https://hosted.weblate.org/engage/pairdrop/">
|
||||||
<img src="https://hosted.weblate.org/widget/pairdrop/pairdrop-spa/open-graph.png" alt="Translation status" style="width: 300px" />
|
<img src="https://hosted.weblate.org/widget/pairdrop/horizontal-blue.svg" alt="Translation status" style="width: 300px" />
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
## How to contribute
|
## Built with the following awesome technologies:
|
||||||
|
* Vanilla HTML5 / JS ES6 / CSS 3 frontend
|
||||||
|
* [WebRTC](http://webrtc.org/) / WebSockets
|
||||||
|
* [Node.js](https://nodejs.org/en/) backend
|
||||||
|
* [Progressive web app (PWA)](https://en.wikipedia.org/wiki/Progressive_web_app) unified functionality
|
||||||
|
* [IndexedDB API](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API) storage handling
|
||||||
|
* [zip.js](https://gildas-lormeau.github.io/zip.js/) library
|
||||||
|
* [cyrb53](https://github.com/bryc/code/blob/master/jshash/experimental/cyrb53.js) super-fast hash function
|
||||||
|
* [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
|
||||||
|
|
||||||
|
[FAQ](docs/faq.md)
|
||||||
|
|
||||||
|
[Host your own instance with Docker or Node.js](docs/host-your-own.md).
|
||||||
|
|
||||||
|
## Support
|
||||||
|
<a href="https://www.buymeacoffee.com/pairdrop" target="_blank">
|
||||||
|
<img src="https://cdn.buymeacoffee.com/buttons/v2/default-blue.png" alt="Buy me a coffee" style="height: 60px !important;width: 217px !important;" >
|
||||||
|
</a>
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
PairDrop is libre, and always will be. \
|
||||||
|
I footed the bill for the domain and the server, and you can help create great softeare by supporting me. \
|
||||||
|
Please use BuyMeACoffee via the button above. \
|
||||||
|
Thanks a lot for supporting copylefted libre software!
|
||||||
|
|
||||||
|
## Contributing
|
||||||
Feel free to [open an issue](https://github.com/schlagmichdoch/pairdrop/issues/new/choose) or a
|
Feel free to [open an issue](https://github.com/schlagmichdoch/pairdrop/issues/new/choose) or a
|
||||||
[pull request](https://github.com/schlagmichdoch/pairdrop/pulls) but follow
|
[pull request](https://github.com/schlagmichdoch/pairdrop/pulls), following the
|
||||||
[Contributing Guidelines](CONTRIBUTING.md).
|
[Contributing Guidelines](CONTRIBUTING.md).
|
||||||
|
|||||||
+3
-3
@@ -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.10.6/pairdrop-cli.zip"
|
wget "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.10.7/pairdrop-cli.zip"
|
||||||
```
|
```
|
||||||
or
|
or
|
||||||
```shell
|
```shell
|
||||||
curl -LO "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.10.6/pairdrop-cli.zip"
|
curl -LO "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.10.7/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
|
||||||
@@ -125,7 +125,7 @@ It is possible to send multiple files with PairDrop via the context menu by addi
|
|||||||
```
|
```
|
||||||
3. Make the shell file _send-with-pairdrop_ executable
|
3. Make the shell file _send-with-pairdrop_ executable
|
||||||
```shell
|
```shell
|
||||||
chmod +x ~/.local/share/nautilus/scripts/send-with-pairdrop`
|
chmod +x ~/.local/share/nautilus/scripts/send-with-pairdrop
|
||||||
```
|
```
|
||||||
4. You are done! You can now send multiple files and directories directly via PairDrop:
|
4. You are done! You can now send multiple files and directories directly via PairDrop:
|
||||||
|
|
||||||
|
|||||||
Generated
+2
-2
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "pairdrop",
|
"name": "pairdrop",
|
||||||
"version": "1.10.6",
|
"version": "1.10.7",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "pairdrop",
|
"name": "pairdrop",
|
||||||
"version": "1.10.6",
|
"version": "1.10.7",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pairdrop",
|
"name": "pairdrop",
|
||||||
"version": "1.10.6",
|
"version": "1.10.7",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "server/index.js",
|
"main": "server/index.js",
|
||||||
|
|||||||
+1
-1
@@ -582,7 +582,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.10.6</div>
|
<div class="font-subheading">v1.10.7</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">
|
||||||
|
|||||||
+51
-33
@@ -5,9 +5,9 @@
|
|||||||
"display-name_data-placeholder": "Caricamento…",
|
"display-name_data-placeholder": "Caricamento…",
|
||||||
"display-name_title": "Modifica il nome del tuo dispositivo permanentemente",
|
"display-name_title": "Modifica il nome del tuo dispositivo permanentemente",
|
||||||
"traffic": "Il traffico è",
|
"traffic": "Il traffico è",
|
||||||
"paired-devices_title": "Puoi essere rilevato dai dispositivi abbinati in ogni momento, indipendentemente dalla rete.",
|
"paired-devices_title": "Puoi essere rilevato dai dispositivi associati in ogni momento, indipendentemente dalla rete.",
|
||||||
"public-room-devices": "nella stanza {{roomId}}",
|
"public-room-devices": "nella stanza {{roomId}}",
|
||||||
"paired-devices": "da dispositivi abbinati",
|
"paired-devices": "da dispositivi associati",
|
||||||
"on-this-network": "su questa rete",
|
"on-this-network": "su questa rete",
|
||||||
"routed": "instradato attraverso il server",
|
"routed": "instradato attraverso il server",
|
||||||
"discovery": "Puoi essere rilevato:",
|
"discovery": "Puoi essere rilevato:",
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
"known-as": "Sei visibile come:"
|
"known-as": "Sei visibile come:"
|
||||||
},
|
},
|
||||||
"header": {
|
"header": {
|
||||||
"cancel-share-mode": "Fatto",
|
"cancel-share-mode": "Annulla",
|
||||||
"theme-auto_title": "Adatta il tema al sistema automaticamente",
|
"theme-auto_title": "Adatta il tema al sistema automaticamente",
|
||||||
"install_title": "Installa PairDrop",
|
"install_title": "Installa PairDrop",
|
||||||
"theme-dark_title": "Usa sempre il tema scuro",
|
"theme-dark_title": "Usa sempre il tema scuro",
|
||||||
@@ -26,13 +26,15 @@
|
|||||||
"language-selector_title": "Imposta Lingua",
|
"language-selector_title": "Imposta Lingua",
|
||||||
"about_title": "Informazioni su PairDrop",
|
"about_title": "Informazioni su PairDrop",
|
||||||
"about_aria-label": "Apri Informazioni su PairDrop",
|
"about_aria-label": "Apri Informazioni su PairDrop",
|
||||||
"theme-light_title": "Usa sempre il tema chiaro"
|
"theme-light_title": "Usa sempre il tema chiaro",
|
||||||
|
"edit-share-mode": "Modifica",
|
||||||
|
"expand_title": "Espandi la riga dei pulsanti nell'intestazione"
|
||||||
},
|
},
|
||||||
"instructions": {
|
"instructions": {
|
||||||
"x-instructions_mobile": "Tocca per inviare file o tocco prolungato per inviare un messaggio",
|
"x-instructions_mobile": "Tocca per inviare file o tocco prolungato per inviare un messaggio",
|
||||||
"x-instructions-share-mode_desktop": "Clicca per inviare",
|
"x-instructions-share-mode_desktop": "Clicca per inviare {{descriptor}}",
|
||||||
"activate-share-mode-and-other-files-plural": "e altri {{count}} files",
|
"activate-share-mode-and-other-files-plural": "e altri {{count}} files",
|
||||||
"x-instructions-share-mode_mobile": "Tocca per inviare",
|
"x-instructions-share-mode_mobile": "Tocca per inviare {{descriptor}}",
|
||||||
"activate-share-mode-base": "Apri PairDrop su altri dispositivi per inviare",
|
"activate-share-mode-base": "Apri PairDrop su altri dispositivi per inviare",
|
||||||
"no-peers-subtitle": "Abbina dispositivi o entra in una stanza pubblica per essere rilevabile su altre reti",
|
"no-peers-subtitle": "Abbina dispositivi o entra in una stanza pubblica per essere rilevabile su altre reti",
|
||||||
"activate-share-mode-shared-text": "testo condiviso",
|
"activate-share-mode-shared-text": "testo condiviso",
|
||||||
@@ -41,23 +43,26 @@
|
|||||||
"x-instructions_data-drop-peer": "Rilascia per inviare al peer",
|
"x-instructions_data-drop-peer": "Rilascia per inviare al peer",
|
||||||
"x-instructions_data-drop-bg": "Rilascia per selezionare il destinatario",
|
"x-instructions_data-drop-bg": "Rilascia per selezionare il destinatario",
|
||||||
"no-peers_data-drop-bg": "Rilascia per selezionare il destinatario",
|
"no-peers_data-drop-bg": "Rilascia per selezionare il destinatario",
|
||||||
"webrtc-requirement": "Per usare questa istanza di PairDrop, devi attivare WebRTC!"
|
"webrtc-requirement": "Per usare questa istanza di PairDrop, devi attivare WebRTC!",
|
||||||
|
"activate-share-mode-shared-file": "file condiviso",
|
||||||
|
"activate-share-mode-shared-files-plural": "{{count}} files condivisi",
|
||||||
|
"activate-share-mode-and-other-file": "ed 1 altro file"
|
||||||
},
|
},
|
||||||
"dialogs": {
|
"dialogs": {
|
||||||
"auto-accept-instructions-2": "per accettare automaticamente tutti i files inviati da quel dispositivo.",
|
"auto-accept-instructions-2": "per accettare automaticamente tutti i files inviati da quel dispositivo.",
|
||||||
"edit-paired-devices-title": "Modifica Dispositivi Abbinati",
|
"edit-paired-devices-title": "Modifica Dispositivi Associati",
|
||||||
"cancel": "Annulla",
|
"cancel": "Annulla",
|
||||||
"auto-accept-instructions-1": "Attiva",
|
"auto-accept-instructions-1": "Attiva",
|
||||||
"pair-devices-title": "Abbina Dispositivi Permanentemente",
|
"pair-devices-title": "Associa Dispositivi Permanentemente",
|
||||||
"temporary-public-room-title": "Stanza Pubblica Temporanea",
|
"temporary-public-room-title": "Stanza Pubblica Temporanea",
|
||||||
"close": "Chiudi",
|
"close": "Chiudi",
|
||||||
"unpair": "Dissocia",
|
"unpair": "Dissocia",
|
||||||
"pair": "Abbina",
|
"pair": "Associa",
|
||||||
"scan-qr-code": "o scannerizza il codice QR.",
|
"scan-qr-code": "o scannerizza il codice QR.",
|
||||||
"input-key-on-this-device": "Inserisci questo codice su un altro dispositivo",
|
"input-key-on-this-device": "Inserisci questo codice su un altro dispositivo",
|
||||||
"paired-devices-wrapper_data-empty": "Nessun dispositivo abbinato.",
|
"paired-devices-wrapper_data-empty": "Nessun dispositivo associato.",
|
||||||
"enter-key-from-another-device": "Inserisci il codice dell'altro dispositivo qui.",
|
"enter-key-from-another-device": "Inserisci il codice dell'altro dispositivo qui.",
|
||||||
"auto-accept": "accetta-automaticamente",
|
"auto-accept": "accetta automaticamente",
|
||||||
"input-room-id-on-another-device": "Inserisci l'ID di questa stanza su un altro dispositivo",
|
"input-room-id-on-another-device": "Inserisci l'ID di questa stanza su un altro dispositivo",
|
||||||
"enter-room-id-from-another-device": "Inserisci l'ID stanza da un altro dispositivo per accedere alla stanza.",
|
"enter-room-id-from-another-device": "Inserisci l'ID stanza da un altro dispositivo per accedere alla stanza.",
|
||||||
"base64-paste-to-send": "Incolla qui per inviare {{type}}",
|
"base64-paste-to-send": "Incolla qui per inviare {{type}}",
|
||||||
@@ -71,7 +76,7 @@
|
|||||||
"join": "Unisciti",
|
"join": "Unisciti",
|
||||||
"title-image-plural": "Immagini",
|
"title-image-plural": "Immagini",
|
||||||
"send": "Invia",
|
"send": "Invia",
|
||||||
"base64-tap-to-paste": "Tocca qui per incollare {{type}}",
|
"base64-tap-to-paste": "Tocca qui per condividere {{type}}",
|
||||||
"base64-text": "testo",
|
"base64-text": "testo",
|
||||||
"copy": "Copia",
|
"copy": "Copia",
|
||||||
"file-other-description-image": "e 1 altra immagine",
|
"file-other-description-image": "e 1 altra immagine",
|
||||||
@@ -82,7 +87,7 @@
|
|||||||
"title-image": "Immagine",
|
"title-image": "Immagine",
|
||||||
"file-other-description-file-plural": "e altri {{count}} files",
|
"file-other-description-file-plural": "e altri {{count}} files",
|
||||||
"would-like-to-share": "vorrebbe condividere",
|
"would-like-to-share": "vorrebbe condividere",
|
||||||
"send-message-to": "Invia un messaggio a",
|
"send-message-to": "A:",
|
||||||
"language-selector-title": "Imposta Lingua",
|
"language-selector-title": "Imposta Lingua",
|
||||||
"hr-or": "OPPURE",
|
"hr-or": "OPPURE",
|
||||||
"download-again": "Scarica ancora",
|
"download-again": "Scarica ancora",
|
||||||
@@ -92,11 +97,20 @@
|
|||||||
"send-message-title": "Invia Messaggio",
|
"send-message-title": "Invia Messaggio",
|
||||||
"file-other-description-image-plural": "e {{count}} altre immagini",
|
"file-other-description-image-plural": "e {{count}} altre immagini",
|
||||||
"message_title": "Inserire messaggio da inviare",
|
"message_title": "Inserire messaggio da inviare",
|
||||||
"pair-devices-qr-code_title": "Clicca per copiare il link di abbinamento di questo dispositivo",
|
"pair-devices-qr-code_title": "Clicca per copiare il link di associazione a questo dispositivo",
|
||||||
"public-room-qr-code_title": "Clicca per copirare il link della stanza pubblica"
|
"public-room-qr-code_title": "Clicca per copirare il link della stanza pubblica",
|
||||||
|
"message_placeholder": "Testo",
|
||||||
|
"paired-device-removed": "Il dispositivo associato è stato rimosso.",
|
||||||
|
"base64-title-files": "Condividi Files",
|
||||||
|
"base64-title-text": "Condividi Testo",
|
||||||
|
"share-text-subtitle": "Modifica messaggio prima dell'invio:",
|
||||||
|
"share-text-checkbox": "Mostra sempre questa casella di dialogo quando si condivide del testo",
|
||||||
|
"approve": "accetta",
|
||||||
|
"share-text-title": "Condividi Messaggio di Testo",
|
||||||
|
"close-toast_title": "Chiudi notifica"
|
||||||
},
|
},
|
||||||
"notifications": {
|
"notifications": {
|
||||||
"request-title": "{{name}} vorrebbe trasferire {{count}} {{descriptor}}",
|
"request-title": "{{name}} vorrebbe inviare {{count}} {{descriptor}}",
|
||||||
"unfinished-transfers-warning": "Ci sono dei trasferimenti in corso. Sei sicuro di voler chiudere PairDrop?",
|
"unfinished-transfers-warning": "Ci sono dei trasferimenti in corso. Sei sicuro di voler chiudere PairDrop?",
|
||||||
"message-received": "Messaggio ricevuto da {{name}} - Clicca per copiare",
|
"message-received": "Messaggio ricevuto da {{name}} - Clicca per copiare",
|
||||||
"rate-limit-join-key": "Limite raggiunto. Aspetta 10 secondi e riprova.",
|
"rate-limit-join-key": "Limite raggiunto. Aspetta 10 secondi e riprova.",
|
||||||
@@ -104,22 +118,22 @@
|
|||||||
"pairing-key-invalidated": "Il codice {{key}} è stato invalidato",
|
"pairing-key-invalidated": "Il codice {{key}} è stato invalidato",
|
||||||
"pairing-key-invalid": "Codice non valido",
|
"pairing-key-invalid": "Codice non valido",
|
||||||
"connected": "Connesso",
|
"connected": "Connesso",
|
||||||
"pairing-not-persistent": "I dispositivi abbinati non sono persistenti",
|
"pairing-not-persistent": "I dispositivi associati non sono permanenti",
|
||||||
"text-content-incorrect": "Il contenuto testuale non è corretto",
|
"text-content-incorrect": "Il contenuto di testo è errato",
|
||||||
"message-transfer-completed": "Trasferimento del messaggio completato",
|
"message-transfer-completed": "Trasferimento del messaggio completato",
|
||||||
"file-transfer-completed": "Trasferimento file completato",
|
"file-transfer-completed": "Trasferimento file completato",
|
||||||
"file-content-incorrect": "Il contenuto del file non è corretto",
|
"file-content-incorrect": "Il contenuto del file è errato",
|
||||||
"files-incorrect": "I file non sono corretti",
|
"files-incorrect": "I file sono errati",
|
||||||
"selected-peer-left": "Peer selezionato ha abbandonato",
|
"selected-peer-left": "Il peer selezionato ha abbandonato",
|
||||||
"link-received": "Link ricevuto da {{name}} - Clicca per aprire",
|
"link-received": "Link ricevuto da {{name}} - Clicca per aprire",
|
||||||
"online": "Sei di nuovo online",
|
"online": "Sei di nuovo online",
|
||||||
"public-room-left": "Ha lasciato la stanza pubblica {{publicRoomId}}",
|
"public-room-left": "Hai abbandonato la stanza pubblica {{publicRoomId}}",
|
||||||
"copied-text": "Testo copiato negli appunti",
|
"copied-text": "Testo copiato negli appunti",
|
||||||
"display-name-random-again": "Il nome visualizzato è generato casualmente un'altra volta",
|
"display-name-random-again": "Il nome visualizzato viene di nuovo generato casualmente",
|
||||||
"display-name-changed-permanently": "Il nome visualizzato è cambiato permanentemente",
|
"display-name-changed-permanently": "Il nome visualizzato è cambiato definitivamente",
|
||||||
"copied-to-clipboard-error": "La copia non è possibile. Copia manualmente.",
|
"copied-to-clipboard-error": "La funzione di copia non è possibile. Copia manualmente.",
|
||||||
"pairing-success": "Dispositivi abbinati",
|
"pairing-success": "Dispositivi associati",
|
||||||
"clipboard-content-incorrect": "Il contenuto copiato non è corretto",
|
"clipboard-content-incorrect": "Il contenuto copiato è errato",
|
||||||
"display-name-changed-temporarily": "Il nome visualizzato è cambiato solo per questa sessione",
|
"display-name-changed-temporarily": "Il nome visualizzato è cambiato solo per questa sessione",
|
||||||
"copied-to-clipboard": "Copiato negli appunti",
|
"copied-to-clipboard": "Copiato negli appunti",
|
||||||
"offline": "Sei offline",
|
"offline": "Sei offline",
|
||||||
@@ -128,14 +142,14 @@
|
|||||||
"click-to-download": "Clicca per scaricare",
|
"click-to-download": "Clicca per scaricare",
|
||||||
"pairing-cleared": "Tutti i dispositivi sono stati dissociati",
|
"pairing-cleared": "Tutti i dispositivi sono stati dissociati",
|
||||||
"notifications-enabled": "Notifiche attivate",
|
"notifications-enabled": "Notifiche attivate",
|
||||||
"online-requirement-pairing": "Devi essere online per abbinare dispositivi",
|
"online-requirement-pairing": "Devi essere online per associare dispositivi",
|
||||||
"ios-memory-limit": "L'invio di file a dispositivi iOS è possibile solo 200 MB alla volta",
|
"ios-memory-limit": "L'invio di file a dispositivi iOS è possibile solo 200 MB alla volta",
|
||||||
"online-requirement-public-room": "Devi essere online per creare una stanza pubblica",
|
"online-requirement-public-room": "Devi essere online per creare una stanza pubblica",
|
||||||
"copied-text-error": "Scrittura negli appunti fallita. Copia manualmente!",
|
"copied-text-error": "Scrittura negli appunti fallita. Copia manualmente!",
|
||||||
"download-successful": "{{descriptor}} scaricato",
|
"download-successful": "{{descriptor}} scaricato",
|
||||||
"click-to-show": "Clicca per mostrare",
|
"click-to-show": "Clicca per mostrare",
|
||||||
"notifications-permissions-error": "Il permesso all'invio delle notifiche è stato negato poiché l'utente ha ignorato varie volte le richieste di permesso. Ciò può essere ripristinato nelle \"informazioni sito\" cliccando sull'icona a forma di lucchetto vicino alla barra degli indirizzi.",
|
"notifications-permissions-error": "Il permesso all'invio delle notifiche è stato negato poiché l'utente ha ignorato varie volte le richieste di permesso. Ciò può essere ripristinato nelle \"informazioni sito\" cliccando sull'icona a forma di lucchetto vicino alla barra degli indirizzi.",
|
||||||
"pair-url-copied-to-clipboard": "Link di abbinamento copiato negli appunti",
|
"pair-url-copied-to-clipboard": "Link di associazione copiato negli appunti",
|
||||||
"room-url-copied-to-clipboard": "Link della stanza copiato negli appunti"
|
"room-url-copied-to-clipboard": "Link della stanza copiato negli appunti"
|
||||||
},
|
},
|
||||||
"peer-ui": {
|
"peer-ui": {
|
||||||
@@ -151,14 +165,18 @@
|
|||||||
"claim": "Il modo più semplice per trasferire files tra dispositivi",
|
"claim": "Il modo più semplice per trasferire files tra dispositivi",
|
||||||
"tweet_title": "Twitta riguardo PairDrop",
|
"tweet_title": "Twitta riguardo PairDrop",
|
||||||
"close-about_aria-label": "Chiudi Informazioni su PairDrop",
|
"close-about_aria-label": "Chiudi Informazioni su PairDrop",
|
||||||
"buy-me-a-coffee_title": "Comprami un caffè!",
|
"buy-me-a-coffee_title": "Offrimi un caffè!",
|
||||||
"github_title": "PairDrop su GitHub",
|
"github_title": "PairDrop su GitHub",
|
||||||
"faq_title": "Domande Frequenti"
|
"faq_title": "Domande Frequenti",
|
||||||
|
"mastodon_title": "Scrivi su Mastodon di PairDrop",
|
||||||
|
"bluesky_title": "Seguici su BlueSky",
|
||||||
|
"custom_title": "Seguici",
|
||||||
|
"privacypolicy_title": "Apri la nostra policy sulla privacy"
|
||||||
},
|
},
|
||||||
"document-titles": {
|
"document-titles": {
|
||||||
"file-transfer-requested": "Trasferimento File Richiesto",
|
"file-transfer-requested": "Trasferimento File Richiesto",
|
||||||
"image-transfer-requested": "Trasferimento Immagine Richiesto",
|
"image-transfer-requested": "Trasferimento Immagine Richiesto",
|
||||||
"message-received-plural": "{{count}} Messaggi ricevuti",
|
"message-received-plural": "{{count}} Messaggi Ricevuti",
|
||||||
"message-received": "Messaggio ricevuto",
|
"message-received": "Messaggio ricevuto",
|
||||||
"file-received": "File Ricevuto",
|
"file-received": "File Ricevuto",
|
||||||
"file-received-plural": "{{count}} Files Ricevuti"
|
"file-received-plural": "{{count}} Files Ricevuti"
|
||||||
|
|||||||
+138
-60
@@ -172,31 +172,34 @@ class PeersUI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onDrop(e) {
|
_onDrop(e) {
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if (this.shareMode.active || Dialog.anyDialogShown()) return;
|
if (this.shareMode.active || Dialog.anyDialogShown()) return;
|
||||||
|
|
||||||
if (!$$('x-peer') || !$$('x-peer').contains(e.target)) {
|
e.preventDefault();
|
||||||
if (e.dataTransfer.files.length > 0) {
|
|
||||||
Events.fire('activate-share-mode', {files: e.dataTransfer.files});
|
|
||||||
} else {
|
|
||||||
for (let i=0; i<e.dataTransfer.items.length; i++) {
|
|
||||||
if (e.dataTransfer.items[i].type === "text/plain") {
|
|
||||||
e.dataTransfer.items[i].getAsString(text => {
|
|
||||||
Events.fire('activate-share-mode', {text: text});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._onDragEnd();
|
this._onDragEnd();
|
||||||
|
|
||||||
|
if ($$('x-peer') || !$$('x-peer').contains(e.target)) return; // dropped on peer
|
||||||
|
|
||||||
|
const files = e.dataTransfer.files;
|
||||||
|
const text = e.dataTransfer.getData("text");
|
||||||
|
|
||||||
|
if (files.length > 0) {
|
||||||
|
Events.fire('activate-share-mode', {
|
||||||
|
files: files
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if(text.length > 0) {
|
||||||
|
Events.fire('activate-share-mode', {
|
||||||
|
text: text
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onDragOver(e) {
|
_onDragOver(e) {
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if (this.shareMode.active || Dialog.anyDialogShown()) return;
|
if (this.shareMode.active || Dialog.anyDialogShown()) return;
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
this.$xInstructions.setAttribute('drop-bg', true);
|
this.$xInstructions.setAttribute('drop-bg', true);
|
||||||
this.$xNoPeers.setAttribute('drop-bg', true);
|
this.$xNoPeers.setAttribute('drop-bg', true);
|
||||||
}
|
}
|
||||||
@@ -590,6 +593,9 @@ class PeerUI {
|
|||||||
_onFilesSelected(e) {
|
_onFilesSelected(e) {
|
||||||
const $input = e.target;
|
const $input = e.target;
|
||||||
const files = $input.files;
|
const files = $input.files;
|
||||||
|
|
||||||
|
if (files.length === 0) return;
|
||||||
|
|
||||||
Events.fire('files-selected', {
|
Events.fire('files-selected', {
|
||||||
files: files,
|
files: files,
|
||||||
to: this._peer.id
|
to: this._peer.id
|
||||||
@@ -630,29 +636,28 @@ class PeerUI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_onDrop(e) {
|
_onDrop(e) {
|
||||||
e.preventDefault();
|
|
||||||
|
|
||||||
if (PeerUI._shareMode.active || Dialog.anyDialogShown()) return;
|
if (PeerUI._shareMode.active || Dialog.anyDialogShown()) return;
|
||||||
|
|
||||||
if (e.dataTransfer.files.length > 0) {
|
e.preventDefault();
|
||||||
Events.fire('files-selected', {
|
|
||||||
files: e.dataTransfer.files,
|
|
||||||
to: this._peer.id
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
for (let i=0; i<e.dataTransfer.items.length; i++) {
|
|
||||||
if (e.dataTransfer.items[i].type === "text/plain") {
|
|
||||||
e.dataTransfer.items[i].getAsString(text => {
|
|
||||||
Events.fire('send-text', {
|
|
||||||
text: text,
|
|
||||||
to: this._peer.id
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this._onDragEnd();
|
this._onDragEnd();
|
||||||
|
|
||||||
|
const peerId = this._peer.id;
|
||||||
|
const files = e.dataTransfer.files;
|
||||||
|
const text = e.dataTransfer.getData("text");
|
||||||
|
|
||||||
|
if (files.length > 0) {
|
||||||
|
Events.fire('files-selected', {
|
||||||
|
files: files,
|
||||||
|
to: peerId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else if (text.length > 0) {
|
||||||
|
Events.fire('send-text', {
|
||||||
|
text: text,
|
||||||
|
to: peerId
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_onDragOver() {
|
_onDragOver() {
|
||||||
@@ -1896,6 +1901,8 @@ class SendTextDialog extends Dialog {
|
|||||||
this.$submit = this.$el.querySelector('button[type="submit"]');
|
this.$submit = this.$el.querySelector('button[type="submit"]');
|
||||||
this.$form.addEventListener('submit', e => this._onSubmit(e));
|
this.$form.addEventListener('submit', e => this._onSubmit(e));
|
||||||
this.$text.addEventListener('input', _ => this._onInput());
|
this.$text.addEventListener('input', _ => this._onInput());
|
||||||
|
this.$text.addEventListener('paste', e => this._onPaste(e));
|
||||||
|
this.$text.addEventListener('drop', e => this._onDrop(e));
|
||||||
|
|
||||||
Events.on('text-recipient', e => this._onRecipient(e.detail.peerId, e.detail.deviceName));
|
Events.on('text-recipient', e => this._onRecipient(e.detail.peerId, e.detail.deviceName));
|
||||||
Events.on('keydown', e => this._onKeyDown(e));
|
Events.on('keydown', e => this._onKeyDown(e));
|
||||||
@@ -1914,6 +1921,40 @@ class SendTextDialog extends Dialog {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async _onDrop(e) {
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
const text = e.dataTransfer.getData("text");
|
||||||
|
const selection = window.getSelection();
|
||||||
|
|
||||||
|
if (selection.rangeCount) {
|
||||||
|
selection.deleteFromDocument();
|
||||||
|
selection.getRangeAt(0).insertNode(document.createTextNode(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
this._onInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onPaste(e) {
|
||||||
|
e.preventDefault()
|
||||||
|
|
||||||
|
const text = (e.clipboardData || window.clipboardData).getData('text');
|
||||||
|
const selection = window.getSelection();
|
||||||
|
|
||||||
|
if (selection.rangeCount) {
|
||||||
|
selection.deleteFromDocument();
|
||||||
|
const textNode = document.createTextNode(text);
|
||||||
|
const range = document.createRange();
|
||||||
|
range.setStart(textNode, textNode.length);
|
||||||
|
range.collapse(true);
|
||||||
|
selection.getRangeAt(0).insertNode(textNode);
|
||||||
|
selection.removeAllRanges();
|
||||||
|
selection.addRange(range);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._onInput();
|
||||||
|
}
|
||||||
|
|
||||||
_textEmpty() {
|
_textEmpty() {
|
||||||
return !this.$text.innerText || this.$text.innerText === "\n";
|
return !this.$text.innerText || this.$text.innerText === "\n";
|
||||||
}
|
}
|
||||||
@@ -1997,12 +2038,22 @@ class ReceiveTextDialog extends Dialog {
|
|||||||
window.blop.play();
|
window.blop.play();
|
||||||
this._receiveTextQueue.push({text: text, peerId: peerId});
|
this._receiveTextQueue.push({text: text, peerId: peerId});
|
||||||
this._setDocumentTitleMessages();
|
this._setDocumentTitleMessages();
|
||||||
|
changeFavicon("images/favicon-96x96-notification.png");
|
||||||
|
|
||||||
if (this.isShown()) return;
|
if (this.isShown()) return;
|
||||||
|
|
||||||
this._dequeueRequests();
|
this._dequeueRequests();
|
||||||
}
|
}
|
||||||
|
|
||||||
_dequeueRequests() {
|
_dequeueRequests() {
|
||||||
if (!this._receiveTextQueue.length) return;
|
if (!this._receiveTextQueue.length) {
|
||||||
|
this.$text.innerHTML = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._setDocumentTitleMessages();
|
||||||
|
changeFavicon("images/favicon-96x96-notification.png");
|
||||||
|
|
||||||
let {text, peerId} = this._receiveTextQueue.shift();
|
let {text, peerId} = this._receiveTextQueue.shift();
|
||||||
this._showReceiveTextDialog(text, peerId);
|
this._showReceiveTextDialog(text, peerId);
|
||||||
}
|
}
|
||||||
@@ -2013,41 +2064,68 @@ class ReceiveTextDialog extends Dialog {
|
|||||||
this.$displayName.classList.add($(peerId).ui._badgeClassName());
|
this.$displayName.classList.add($(peerId).ui._badgeClassName());
|
||||||
|
|
||||||
this.$text.innerText = text;
|
this.$text.innerText = text;
|
||||||
this.$text.classList.remove('text-center');
|
|
||||||
|
|
||||||
// Beautify text if text is short
|
// Beautify text if text is not too long
|
||||||
if (text.length < 2000) {
|
if (this.$text.innerText.length <= 300000) {
|
||||||
// replace URLs with actual links
|
// Hacky workaround to replace URLs with link nodes in all cases
|
||||||
this.$text.innerHTML = this.$text.innerHTML
|
// 1. Use text variable, find all valid URLs via regex and replace URLs with placeholder
|
||||||
.replace(/(^|<br>|\s|")((https?:\/\/|www.)(([a-z]|[A-Z]|[0-9]|[\-_~:\/?#\[\]@!$&'()*+,;=%]){2,}\.)(([a-z]|[A-Z]|[0-9]|[\-_~:\/?#\[\]@!$&'()*+,;=%.]){2,}))/g,
|
// 2. Use html variable, find placeholders with regex and replace them with link nodes
|
||||||
(match, whitespace, url) => {
|
|
||||||
let link = url;
|
|
||||||
|
|
||||||
// prefix www.example.com with http protocol to prevent it from being a relative link
|
let $textShadow = document.createElement('div');
|
||||||
if (link.startsWith('www')) {
|
$textShadow.innerText = text;
|
||||||
link = "http://" + link
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if link is valid
|
let linkNodes = {};
|
||||||
if (isUrlValid(link)) {
|
let searchHTML = $textShadow.innerHTML;
|
||||||
return `${whitespace}<a href="${link}" target="_blank">${url}</a>`;
|
const p = "@";
|
||||||
}
|
const pRgx = new RegExp(`${p}\\d+`, 'g');
|
||||||
else {
|
let occP = searchHTML.match(pRgx) || [];
|
||||||
return match;
|
|
||||||
|
let m = 0;
|
||||||
|
|
||||||
|
const allowedDomainChars = "a-zA-Z0-9áàäčçđéèêŋńñóòôöšŧüžæøåëìíîïðùúýþćěłřśţźǎǐǒǔǥǧǩǯəʒâûœÿãõāēīōūăąĉċďĕėęĝğġģĥħĩĭįıĵķĸĺļľņňŏőŕŗŝşťũŭůűųŵŷżאבגדהוזחטיךכלםמןנסעףפץצקרשתװױײ";
|
||||||
|
const urlRgx = new RegExp(`(^|\\n|\\s|["><\\-_~:\\/?#\\[\\]@!$&'()*+,;=%.])(((https?:\\/\\/)?(?:[${allowedDomainChars}](?:[${allowedDomainChars}-]{0,61}[${allowedDomainChars}])?\\.)+[${allowedDomainChars}][${allowedDomainChars}-]{0,61}[${allowedDomainChars}])(:?\\d*)\\/?([${allowedDomainChars}_\\/\\-#.]*)(\\?([${allowedDomainChars}\\-_~:\\/?#\\[\\]@!$&'()*+,;=%.]*))?)`, 'g');
|
||||||
|
|
||||||
|
$textShadow.innerText = text.replace(urlRgx,
|
||||||
|
(match, whitespaceOrSpecial, url, g3, scheme) => {
|
||||||
|
let link = url;
|
||||||
|
|
||||||
|
// prefix www.example.com with http protocol to prevent it from being a relative link
|
||||||
|
if (!scheme && link.startsWith('www')) {
|
||||||
|
link = "http://" + link
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isUrlValid(link)) {
|
||||||
|
// 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] = `<a href="${link}" target="_blank">${url}</a>`;
|
||||||
|
return `${whitespaceOrSpecial}${linkNodePlaceholder}`;
|
||||||
|
}
|
||||||
|
// link is not valid -> do not replace
|
||||||
|
return match;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
this.$text.innerHTML = $textShadow.innerHTML.replace(pRgx,
|
||||||
|
(m) => {
|
||||||
|
let urlNode = linkNodes[m];
|
||||||
|
return urlNode ? urlNode : m;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this._evaluateOverflowing(this.$text);
|
this._evaluateOverflowing(this.$text);
|
||||||
|
|
||||||
this._setDocumentTitleMessages();
|
|
||||||
|
|
||||||
changeFavicon("images/favicon-96x96-notification.png");
|
|
||||||
this.show();
|
this.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
_setDocumentTitleMessages() {
|
_setDocumentTitleMessages() {
|
||||||
document.title = !this._receiveTextQueue.length
|
document.title = this._receiveTextQueue.length <= 1
|
||||||
? `${ Localization.getTranslation("document-titles.message-received") } - PairDrop`
|
? `${ Localization.getTranslation("document-titles.message-received") } - PairDrop`
|
||||||
: `${ Localization.getTranslation("document-titles.message-received-plural", null, {count: this._receiveTextQueue.length + 1}) } - PairDrop`;
|
: `${ Localization.getTranslation("document-titles.message-received-plural", null, {count: this._receiveTextQueue.length + 1}) } - PairDrop`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const cacheVersion = 'v1.10.6';
|
const cacheVersion = 'v1.10.7';
|
||||||
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 forceFetch = false; // FOR DEVELOPMENT: Set to true to always update assets instead of using cached versions
|
||||||
const relativePathsToCache = [
|
const relativePathsToCache = [
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
display: block;
|
display: block;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
resize: none;
|
resize: none;
|
||||||
line-height: 16px;
|
|
||||||
max-height: 350px;
|
max-height: 350px;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
word-wrap: anywhere;
|
word-wrap: anywhere;
|
||||||
|
|||||||
@@ -626,12 +626,15 @@ x-dialog:not([show]) x-background {
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
z-index: -1;
|
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
background-color: var(--accent-color);
|
background-color: var(--accent-color);
|
||||||
transition: opacity 300ms;
|
transition: opacity 300ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-button:before {
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
|
||||||
.btn:not([disabled]):hover:before,
|
.btn:not([disabled]):hover:before,
|
||||||
.icon-button:hover:before {
|
.icon-button:hover:before {
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
|
|||||||
Reference in New Issue
Block a user