snapdrop

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

commit e66598d77f4828fc409f1e3d148b9d2cec8d2ec8
parent 2b3698ece067ce09c36aa6ad653336b72b5e66af
Author: Robin Linus <robin_woll@capira.de>
Date:   Wed, 10 Feb 2016 08:58:09 -0600

Squashed commit of the following:

commit dd00d53895b824fbe4170c4a34b104303f722ccd
Merge: 2b3698e cb9ea12
Author: Robin Linus <robin_woll@capira.de>
Date:   Wed Feb 10 00:27:32 2016 -0600

    Merge branch 'name-device' into merge123

    # Conflicts:
    #	app/elements/buddy-finder/buddy-avatar.html
    #	app/elements/buddy-finder/buddy-finder.html
    #	app/elements/buddy-finder/personal-avatar.html
    #	app/index.html

commit cb9ea1235001f0cc23514cb622ce711cdc0538af
Author: Robin Linus <robin_woll@capira.de>
Date:   Tue Feb 9 23:43:49 2016 -0600

    #13 Feature Request: Name your device

commit 6fa43b56f4e705a19e68b62bc671a4948b6968fb
Author: Robin Linus <robin_woll@capira.de>
Date:   Fri Jan 1 19:54:56 2016 +0100

    Initial

commit fc55c86f5cf95039355d85be7409e68f27246696
Author: Robin Linus <robin_woll@capira.de>
Date:   Fri Jan 1 18:06:27 2016 +0100

    Fix fullscreen layout on iOS

Diffstat:
Mapp/elements/buddy-finder/buddy-avatar.html | 34++++++++++++++++++++++++----------
Mapp/elements/buddy-finder/buddy-finder.html | 1+
Aapp/elements/buddy-finder/device-name-dialog.html | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Aapp/elements/buddy-finder/device-name.html | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mapp/elements/buddy-finder/personal-avatar.html | 24+++++++++++++++++++++---
Mapp/elements/p2p-network/connection-wrapper.html | 3+++
Aapp/images/touch/JZH3ff5.png | 0
Mserver/ws-server.js | 18+++++++++++++++---
8 files changed, 210 insertions(+), 16 deletions(-)

diff --git a/app/elements/buddy-finder/buddy-avatar.html b/app/elements/buddy-finder/buddy-avatar.html @@ -31,8 +31,8 @@ .paper-font-subhead { text-align: center; - line-height: 22px; - margin-top: 2px; + margin-top: 0px; + line-height: 18px; } .paper-font-body1 { @@ -40,7 +40,8 @@ width: 100%; font-size: 13px; color: grey; - line-height: 13px; + margin-top: 0px !important; + line-height: 16px; } :host, @@ -91,11 +92,19 @@ }, status: { type: String, - value: '' + value: '', + }, + defaultStatus: { + computed: '_computeDefaultStatus(contact)' } }, _computeDisplayName: function(contact) { - contact = contact.name; + if (!contact.name.os) { + return contact.name; + } + return this._computeDeviceName(contact.name); + }, + _computeDeviceName: function(contact) { if (contact.model) { return contact.os + ' ' + contact.model; } @@ -103,7 +112,7 @@ return contact.os + ' ' + contact.browser; }, _computeDisplayIcon: function(contact) { - contact = contact.name; + contact = contact.device || contact.name; if (contact.type === 'mobile') { return 'chat:phone-iphone'; } @@ -112,6 +121,11 @@ } return 'chat:desktop-mac'; }, + _computeDefaultStatus: function(contact) { + var status = contact.device ? this._computeDeviceName(contact.device) : ''; + this.status = status; + return status; + }, attached: function() { this.async(function() { app.conn.addEventListener('file-offered', function(e) { @@ -131,21 +145,21 @@ }.bind(this), false); app.conn.addEventListener('upload-complete', function(e) { if (e.detail.from === this.contact.peerId) { - this.status = ''; + this.status = this.defaultStatus; } }.bind(this), false); app.conn.addEventListener('download-complete', function(e) { if (e.detail.from === this.contact.peerId) { - this.status = ''; + this.status = this.defaultStatus; } }.bind(this), false); app.conn.addEventListener('file-declined', function(e) { if (e.detail.from === this.contact.peerId) { - this.status = ''; + this.status = this.defaultStatus; } }.bind(this), false); app.conn.addEventListener('upload-error', function(e) { - this.status = ''; + this.status = this.defaultStatus; }.bind(this), false); }, 200); } diff --git a/app/elements/buddy-finder/buddy-finder.html b/app/elements/buddy-finder/buddy-finder.html @@ -102,6 +102,7 @@ opacity: 1; } } + </style> <div class="explanation2" hidden$="{{!_showExplanation}}"> Tap to send File. diff --git a/app/elements/buddy-finder/device-name-dialog.html b/app/elements/buddy-finder/device-name-dialog.html @@ -0,0 +1,51 @@ +<link rel="import" href="../../bower_components/paper-dialog/paper-dialog.html"> +<link rel="import" href="../../bower_components/paper-input/paper-input.html"> +<dom-module id="device-name-dialog"> + <template> + <style> + :host { + display: block; + } + + paper-dialog { + width: 400px; + max-width: 90% + } + </style> + <paper-dialog id="dialog" entry-animation="scale-up-animation" exit-animation="fade-out-animation" with-backdrop> + <h2>Name this Device</h2> + <p> + <paper-input id="input" value="{{deviceName}}" label="Name this Device" char-counter maxlength="18" on-keypress="_keyPressed" autofocus></paper-input> + </p> + <div class="buttons"> + <paper-button dialog-dismiss>Cancel</paper-button> + <paper-button on-tap="_save">Rename</paper-button> + </div> + </paper-dialog> + </template> + <script> + 'use strict'; + Polymer({ + is: 'device-name-dialog', + properties: { + deviceName: { + notify: true + } + }, + open: function() { + this.$.dialog.open(); + }, + _keyPressed: function(e) { + if (e.which === 13 || e.charCode === 13) { + this.$.input.inputElement.blur(); + this._save(); + } + }, + _save: function() { + this.$.dialog.close(); + this.fire('save-device-name', this.deviceName); + } + + }); + </script> +</dom-module> diff --git a/app/elements/buddy-finder/device-name.html b/app/elements/buddy-finder/device-name.html @@ -0,0 +1,95 @@ +<link rel="import" href="../../bower_components/paper-input/paper-input.html"> +<link rel="import" href="../../bower_components/iron-localstorage/iron-localstorage.html"> +<link rel="import" href="device-name-dialog.html"> +<dom-module id="device-name"> + <template> + <style> + :host { + display: inline-block; + cursor: pointer; + } + + .name-label { + @apply(--paper-font-subhead); + text-align: center; + cursor: pointer; + width: 160px; + line-height: 18px !important; + } + + :root { + /* Label and underline color when the input is not focused */ + --paper-input-container-color: #333; + /* Label and underline color when the input is focused */ + --paper-input-container-focus-color: #4285f4; + /* Label and underline color when the input is invalid */ + --paper-input-container-invalid-color: red; + /* Input foreground color */ + --paper-input-container-input-color: #333; + } + + @media all and (max-height: 370px) { + :host {} + } + + paper-dialog { + width: 300px; + text-align: left; + } + </style> + <div class="name-label" hidden$="{{name}}">My Name</div> + <div class="name-label" hidden$="{{!name}}">{{name}}</div> + <iron-localstorage name="device-name" value="{{name}}" iron-localstorage-load="_nameChanged"></iron-localstorage> + </template> + <script> + 'use strict'; + Polymer({ + is: 'device-name', + properties: { + name: { + observer: '_nameChanged' + } + }, + open: function() { + this.deviceNameDialog.open(); + }, + _nameChanged: function(name) { + if (!name) { + return; + } + this.cancelAsync(this.timer); + this.timer = this.async(function() { + if (!app.conn.notifyServer) { + this._nameChanged(name); + return; + } + this._sendNameToServer(name); + + }, 300); + + }, + _sendNameToServer: function(name) { + app.conn.notifyServer({ + serverMsg: 'device-name', + name: name + }); + }, + _initialize: function() { + console.log('initialize name'); + }, + get deviceNameDialog() { + var deviceNameDialog = document.querySelector('device-name-dialog'); + if (!deviceNameDialog) { + deviceNameDialog = Polymer.Base.create('device-name-dialog'); + deviceNameDialog.addEventListener('save-device-name', function(e) { + this.name = e.detail; + console.log(this.name); + }.bind(this)); + document.body.appendChild(deviceNameDialog); + }; + deviceNameDialog.deviceName = this.name; + return deviceNameDialog; + } + }); + </script> +</dom-module> diff --git a/app/elements/buddy-finder/personal-avatar.html b/app/elements/buddy-finder/personal-avatar.html @@ -1,5 +1,6 @@ <link rel="import" href="../../bower_components/iron-icon/iron-icon.html"> <link rel="import" href="../../styles/icons.html"> +<link rel="import" href="device-name.html"> <dom-module id="personal-avatar"> <template> <style> @@ -11,6 +12,13 @@ bottom: 16px; left: 50%; margin-left: -180px; + z-index: 12; + cursor: pointer; + } + + :host:hover iron-icon, + :host:hover device-name { + color: #3367d6; } iron-icon { @@ -44,11 +52,15 @@ height: 32px; margin-bottom: 2px; } + .slogan { + display: none; + } } </style> + <device-name id="deviceName"></device-name> <iron-icon icon="chat:wifi-tethering"></iron-icon> - <div class="paper-font-body1"> - Easily transfer data across devices. + <div class="paper-font-body1 slogan"> + The easiest way to transfer data across devices. </div> <div class="paper-font-body1 discover"> Allow me to be discovered by: Everyone in this network. @@ -57,7 +69,13 @@ <script> 'use strict'; Polymer({ - is: 'personal-avatar' + is: 'personal-avatar', + listeners: { + 'tap': '_openDeviceNameDialog' + }, + _openDeviceNameDialog: function() { + this.$.deviceName.open(); + } }); </script> </dom-module> diff --git a/app/elements/p2p-network/connection-wrapper.html b/app/elements/p2p-network/connection-wrapper.html @@ -49,6 +49,9 @@ if (window.webRTCSupported) { this.$.p2p.initialize(); } + }, + notifyServer: function(msg) { + this.$.ws.client.send({}, msg); } }); })(); diff --git a/app/images/touch/JZH3ff5.png b/app/images/touch/JZH3ff5.png Binary files differ. diff --git a/server/ws-server.js b/server/ws-server.js @@ -47,11 +47,11 @@ exports.create = function(server) { } // Wait for new user connections bs.on('connection', function(client) { - //console.log('connection received!', client._socket.upgradeReq.connection.remoteAddress); client.uuidRaw = guid(); //ip is hashed to prevent injections by spoofing the 'x-forwarded-for' header - client.hashedIp = hash(getIP(client._socket)); + client.hashedIp = 1; + // client.hashedIp = hash(getIP(client._socket)); client.deviceName = getDeviceName(client._socket.upgradeReq); @@ -62,10 +62,20 @@ exports.create = function(server) { client.send({ isSystemEvent: true, type: 'handshake', + name: client.deviceName, uuid: client.uuid }); return; } + if (meta && meta.serverMsg === 'device-name') { + //max name length = 40 + if (meta.name && meta.name.length > 40) { + return; + } + client.name = meta.name; + return; + } + meta.from = client.uuid; // broadcast to the other client @@ -104,7 +114,8 @@ exports.create = function(server) { socket: client, contact: { peerId: client.uuid, - name: client.deviceName, + name: client.name || client.deviceName, + device: client.name ? client.deviceName : undefined } }); }); @@ -129,6 +140,7 @@ exports.create = function(server) { isSystemEvent: true, type: 'buddies' }; + //send only if state changed if (currState !== socket.lastState) { socket.send(msg); socket.lastState = currState;