snapdrop

A Progressive Web App for local file sharing
git clone http://git.hanabi.in/repos/snapdrop.git
Log | Files | Refs | README | LICENSE

commit 026361fd8f2519daf9d76dd38facaa40f94b9e68
parent 6147e5200b3ec6cbe5144a000c5766fea07323b3
Author: Fasih Ahmad Fakhri <fasihahmadfakhri@gmail.com>
Date:   Wed, 16 Dec 2020 11:29:23 +0530

Merge branch 'master' into master
Diffstat:
MREADME.md | 20++++++--------------
Mclient/index.html | 19+++++++++----------
Mclient/scripts/network.js | 4++--
Mclient/scripts/ui.js | 10++++++----
Mclient/styles.css | 29++++++++++++++++++++++++++---
Mdocs/faq.md | 16++++++++++++++--
Mdocs/local-dev.md | 12+++++++-----
Mserver/index.js | 21+++++++++++++++------
8 files changed, 85 insertions(+), 46 deletions(-)

diff --git a/README.md b/README.md @@ -5,13 +5,16 @@ #### Snapdrop is built with the following awesome technologies: * Vanilla HTML5 / ES6 / CSS3 -* Progressive Web App +* [Progressive Web App](https://de.wikipedia.org/wiki/Progressive_Web_App) * [WebRTC](http://webrtc.org/) * [WebSockets](http://www.websocket.org/) * [NodeJS](https://nodejs.org/en/) -* [Material Design](https://material.google.com/) -> If you want to self-host your own instance, [you can with docker.](/docs/local-dev.md) + +> Have any questions? You can read our [FAQ](/docs/faq.md). + +> If you want to self-host your own instance, [you can with docker](/docs/local-dev.md). + ## Support the Snapdrop Community Snapdrop is free. Still, we have to pay for the server. If you want to contribute, please use PayPal: @@ -27,15 +30,4 @@ Alternatively, you can become a [Github Sponsor](https://github.com/sponsors/Rob Thanks a lot for supporting free and open software! -> Have any questions? You can read our [FAQ](/docs/faq.md) - - - -## Apps -1. [Snapdrop PWA](/docs/faq.md) <!-- Don't know how to do a direct link --> - - 1. [Snapdrop Desktop App](https://github.com/infin1tyy/snapdrop-desktop) built on top of Electron. (Thanks to [Infin1tyy!](https://github.com/infin1tyy/)). - - 1. Feel free to make one :) - diff --git a/client/index.html b/client/index.html @@ -59,16 +59,16 @@ <!-- Peers --> <x-peers class="center"></x-peers> <x-no-peers> - <h2>Open Snapdrop on other devices to send files.</h2> + <h2>Open Snapdrop on other devices to send files</h2> </x-no-peers> - <x-instructions desktop="Click to send files or right click to send a message." mobile="Tap to send files or long tap to send a message."></x-instructions> + <x-instructions desktop="Click to send files or right click to send a message" mobile="Tap to send files or long tap to send a message"></x-instructions> <!-- Footer --> <footer class="column"> <svg class="icon logo"> <use xlink:href="#wifi-tethering" /> </svg> - <div id="displayName">The easiest way to transfer data across devices.</div> - <div class="font-body2">Allow me to be discovered by: Everyone in this network.</div> + <div id="displayName" placeholder="The easiest way to transfer data across devices"></div> + <div class="font-body2">You can be discovered by everyone on this network</div> </footer> <!-- Receive Dialog --> <x-dialog id="receiveDialog"> @@ -90,7 +90,7 @@ <x-background class="full center"> <x-paper shadow="2"> <h3>Send a Message</h3> - <input id="textInput" placeholder="Send a message" autocomplete="off" autofocus> + <textarea id="textInput" placeholder="Send a message" autocomplete="off" autofocus></textarea> <div class="row-reverse"> <button class="button" type="submit" close>Send</button> <a class="button" close>Cancel</a> @@ -130,7 +130,7 @@ <use xlink:href="#wifi-tethering" /> </svg> <h1>Snapdrop</h1> - <div class="font-subheading">The easiest way to transfer files across devices.</div> + <div class="font-subheading">The easiest way to transfer files across devices</div> <div class="row"> <a class="icon-button" target="_blank" href="https://github.com/RobinLinus/snapdrop" title="Snapdrop on Github" rel="noreferrer"> <svg class="icon"> @@ -147,7 +147,7 @@ <use xlink:href="#twitter" /> </svg> </a> - <a class="icon-button" target="_blank" href="https://github.com/RobinLinus/snapdrop/docs/faq.md" title="Frequently asked questions" rel="noreferrer"> + <a class="icon-button" target="_blank" href="https://github.com/RobinLinus/snapdrop/blob/master/docs/faq.md" title="Frequently asked questions" rel="noreferrer"> <svg class="icon"> <use xlink:href="#help-outline" /> </svg> @@ -214,7 +214,7 @@ <noscript> <x-noscript class="full center column"> <h1>Enable Javascript</h1> - <h3>Snapdrop works only with Javascript.</h3> + <h3>Snapdrop works only with Javascript</h3> </x-noscript> <style> x-noscript { @@ -228,4 +228,4 @@ } </style> </noscript> -</body> -\ No newline at end of file +</body> diff --git a/client/scripts/network.js b/client/scripts/network.js @@ -41,8 +41,8 @@ class ServerConnection { case 'ping': this.send({ type: 'pong' }); break; - case 'displayName': - Events.fire('displayName', msg); + case 'display-name': + Events.fire('display-name', msg); break; default: console.error('WS: unkown message type', msg); diff --git a/client/scripts/ui.js b/client/scripts/ui.js @@ -6,8 +6,8 @@ window.isProductionEnvironment = !window.location.host.startsWith('localhost'); window.iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream; // set display name -Events.on('displayName', e => { - $("displayName").textContent = "You are known as " + e.detail.message; +Events.on('display-name', e => { + $('displayName').textContent = 'You are known as ' + e.detail.message; }); class PeersUI { @@ -70,7 +70,7 @@ class PeerUI { html() { return ` - <label class="column center"> + <label class="column center" title="Click to send files or right click to send a text"> <input type="file" multiple> <x-icon shadow="1"> <svg class="icon"><use xlink:href="#"/></svg> @@ -473,7 +473,9 @@ class WebShareTargetUI { let shareTargetText = title ? title : ''; shareTargetText += text ? shareTargetText ? ' ' + text : text : ''; - shareTargetText += url ? shareTargetText ? ' ' + url : url : ''; + + if(url) shareTargetText = url; // We share only the Link - no text. Because link-only text becomes clickable. + if (!shareTargetText) return; window.shareTargetText = shareTargetText; history.pushState({}, 'URL Rewrite', '/'); diff --git a/client/styles.css b/client/styles.css @@ -261,7 +261,7 @@ x-peer[transfer] x-icon { } x-peer[transfer] .status:before { - content: 'Transfering...'; + content: 'Transferring...'; } x-peer x-icon { @@ -292,6 +292,7 @@ footer { right: 0; align-items: center; padding: 0 0 16px 0; + text-align: center; } footer .logo { @@ -365,9 +366,22 @@ x-dialog a{ -webkit-user-select: all; -moz-user-select: all; user-select: all; + white-space: pre; } +#receiveTextDialog #text a { + cursor: pointer; +} +#receiveTextDialog #text a:hover { + text-decoration: underline; +} + +#receiveTextDialog h3{ + /* Select the received text when double-clicking the dialog */ + user-select: none; + pointer-events: none; +} /* Button */ @@ -449,16 +463,19 @@ button::-moz-focus-inner { /* Text Input */ -input { +input, +textarea { width: 100%; box-sizing: border-box; border: none; outline: none; padding: 16px 24px; - border-radius: 50px; + border-radius: 16px; margin: 8px 0; line-height: 16px; font-size: 14px; + font-family: inherit; + resize: none; } @@ -549,6 +566,11 @@ input { } +/* Generic placeholder */ +[placeholder]:empty:before { + content: attr(placeholder); +} + /* Toast */ .toast-container { @@ -590,6 +612,7 @@ x-instructions { opacity: 0.5; transition: opacity 300ms; z-index: -1; + text-align: center; } x-instructions:before { diff --git a/docs/faq.md b/docs/faq.md @@ -32,4 +32,17 @@ We are not trying to optimize for some edge-cases. We are optimizing the user fl * Fix bugs and make a pull request. * Do security analysis and suggestions -[< Back](/README.md) -\ No newline at end of file + + +## Apps +1. [Snapdrop PWA](/docs/faq.md) <!-- Don't know how to do a direct link --> + +1. [Snapdrop Desktop App](https://github.com/infin1tyy/snapdrop-desktop) built on top of Electron. (Thanks to [Infin1tyy!](https://github.com/infin1tyy/)). + +1. [Snapdrop Android App](https://github.com/fm-sys/snapdrop-android) allows you to also send files directly from other apps via the share action. + +1. Feel free to make one :) + + + +[< Back](/README.md) diff --git a/docs/local-dev.md b/docs/local-dev.md @@ -9,12 +9,15 @@ Then, clone the repository: cd snapdrop docker-compose up -d ``` +Now point your browser to `http://localhost:8080`. + +- To restart the containers run `docker-compose restart`. +- To stop the containers run `docker-compose stop`. +- To display the nodejs logs for debugging run `docker logs snapdrop_node_1`. + -To restart the containers run `docker-compose restart`. -To stop the containers run `docker-compose stop`. -Now point your browser to `http://localhost:8080`. ## Testing PWA related features PWAs require that the app is served under a correctly set up and trusted TLS endpoint. @@ -41,4 +44,4 @@ By default, the server listens on port 3000. For an nginx configuration example, see `docker/nginx/default.conf`. -[< Back](/README.md) -\ No newline at end of file +[< Back](/README.md) diff --git a/server/index.js b/server/index.js @@ -1,5 +1,4 @@ const parser = require('ua-parser-js'); -const { uniqueNamesGenerator, animals, colors } = require('unique-names-generator'); class SnapdropServer { @@ -20,7 +19,7 @@ class SnapdropServer { this._keepAlive(peer); // send displayName - this._send(peer, { type: 'displayName', message: peer.name.displayName }); + this._send(peer, { type: 'display-name', message: peer.name.displayName }); } _onHeaders(headers, response) { @@ -36,7 +35,7 @@ class SnapdropServer { } catch (e) { return; // TODO: handle malformed JSON } - + switch (message.type) { case 'disconnect': this._leaveRoom(sender); @@ -186,13 +185,22 @@ class Peer { } _setName(req) { - var ua = parser(req.headers['user-agent']); + let ua = parser(req.headers['user-agent']); + + + let displayName = ua.os.name.replace('Mac OS', 'Mac') + ' '; + if (ua.device.model) { + displayName += ua.device.model; + } else { + displayName += ua.browser.name; + } + this.name = { model: ua.device.model, os: ua.os.name, browser: ua.browser.name, type: ua.device.type, - displayName: uniqueNamesGenerator({ length: 2, separator: ' ', dictionaries: [colors, animals], style: 'capital' }) + displayName: displayName }; } @@ -231,4 +239,4 @@ class Peer { }; } -const server = new SnapdropServer(process.env.PORT || 3000); +const server = new SnapdropServer(process.env.PORT || 3000); +\ No newline at end of file