snapdrop

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

commit dd4809f51912098a325022ea887fbea23896b6dd
parent 370003835eb55f447da102220cff672adc750c74
Author: Robin Linus <robin_woll@capira.de>
Date:   Fri, 18 Dec 2015 17:43:46 +0100

Import files from Yawim

Diffstat:
M.jshintrc | 3++-
Aapp/elements/buddy-finder/buddy-finder-button.html | 24++++++++++++++++++++++++
Aapp/elements/buddy-finder/buddy-finder.html | 85+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapp/elements/buddy-finder/user-avatar.html | 43+++++++++++++++++++++++++++++++++++++++++++
Aapp/elements/contact-item/anonymous-contact-behavior.html | 337+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mapp/elements/elements.html | 37+++++--------------------------------
Aapp/elements/file-sharing/file-drop-behavior.html | 37+++++++++++++++++++++++++++++++++++++
Aapp/elements/file-sharing/file-sharing-button-behavior.html | 36++++++++++++++++++++++++++++++++++++
Aapp/elements/file-sharing/file-sharing-button.html | 58++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapp/elements/file-sharing/file-sharing.html | 48++++++++++++++++++++++++++++++++++++++++++++++++
Aapp/elements/file-sharing/share-area.html | 18++++++++++++++++++
Aapp/elements/p2p-network/p2p-network-imports.html | 1+
Aapp/elements/p2p-network/p2p-network.html | 245+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aapp/images/avatars.jpg | 0
Aapp/images/nice_background.jpg | 0
Mapp/index.html | 124+++++++++++++++++++++++++++++++++----------------------------------------------
Mbower.json | 3++-
Mgulpfile.js | 11++---------
18 files changed, 994 insertions(+), 116 deletions(-)

diff --git a/.jshintrc b/.jshintrc @@ -19,6 +19,7 @@ "Polymer": true, "Platform": true, "page": true, - "app": true + "app": true, + "Chat": true } } diff --git a/app/elements/buddy-finder/buddy-finder-button.html b/app/elements/buddy-finder/buddy-finder-button.html @@ -0,0 +1,24 @@ +<link rel="import" href="../../../bower_components/paper-icon-button/paper-icon-button.html"> +<dom-module id="buddy-finder-button"> + <template> + <style> + :host { + display: block; + } + + paper-icon-item { + height: 60px; + } + </style> + <paper-icon-item> + <iron-icon icon="chat:wifi-tethering" item-icon></iron-icon> + Find People + </paper-icon-item> + </template> + <script> + 'use strict'; + Polymer({ + is: 'buddy-finder-button' + }); + </script> +</dom-module> diff --git a/app/elements/buddy-finder/buddy-finder.html b/app/elements/buddy-finder/buddy-finder.html @@ -0,0 +1,85 @@ +<link rel="import" href="../../../bower_components/iron-ajax/iron-ajax.html"> +<link rel="import" href="../../../bower_components/paper-styles/paper-styles.html"> +<link rel="import" href="../contact-item/contact-item.html"> +<link rel="import" href="../file-sharing/share-area.html"> +<link rel="import" href="user-avatar.html"> +<dom-module id="buddy-finder"> + <template> + <style> + :host { + display: block; + background-color: white; + @apply(--layout-fit); + @apply(--layout-vertical); + @apply(--layout-center-center); + border-left: 1px solid #ccc; + } + + .paper-font-display1 { + color: black; + text-align: center; + margin-bottom: 16px; + display: none; + } + + .buddies { + z-index: 1; + } + + .buddy { + cursor: pointer; + } + + .circles { + position: absolute; + bottom: -50px; + left: 50%; + width: 1140px; + margin-left: -570px; + height: 700px; + transform-origin: 570px 570px; + animation: grow 1.5s ease-out; + fill: transparent; + } + + .me { + position: absolute; + bottom: 30px; + left: 50%; + margin-left: -60px; + } + </style> + <div class="paper-font-display1">People near by</div> + <div class="buddies"> + <template is="dom-repeat" items="{{buddies}}"> + <share-area> + <user-avatar on-tap="_connect" contact="{{item.peerId}}" class="buddy"></user-avatar> + </share-area> + </template> + </div> + <user-avatar contact="{{me}}" class="me"></user-avatar> + <iron-ajax auto url="https://yawim.com/findbuddies/{{me}}" handle-as="json" last-response="{{buddies}}"></iron-ajax> + <svg class="circles" viewBox="-0.5 -0.5 1140 700"> + <circle class="circle" cx="570" cy="570" r="120" stroke="rgba(160,160,160,.4)"></circle> + <circle class="circle" cx="570" cy="570" r="210" stroke="rgba(160,160,160,.35)"></circle> + <circle class="circle" cx="570" cy="570" r="300" stroke="rgba(160,160,160,.3)"></circle> + <circle class="circle" cx="570" cy="570" r="390" stroke="rgba(160,160,160,.2)"></circle> + <circle class="circle" cx="570" cy="570" r="480" stroke="rgba(160,160,160,.15)"></circle> + </svg> + </template> + <script> + 'use strict'; + Polymer({ + is: 'buddy-finder', + properties: { + buddies: Array, + me: { + type: String, + } + }, + _connect: function(e) { + Polymer.dom(document).querySelector('x-app').p2p.connectToPeer(e.model.item.peerId); + } + }); + </script> +</dom-module> diff --git a/app/elements/buddy-finder/user-avatar.html b/app/elements/buddy-finder/user-avatar.html @@ -0,0 +1,43 @@ +<link rel="import" href="../contact-item/anonymous-contact-behavior.html"> +<dom-module id="user-avatar"> + <template> + <style> + :host { + display: block; + @apply(--layout-vertical); + @apply(--layout-center); + width: 120px; + } + + .avatar { + display: inline-block; + width: 52px; + height: 52px; + border-radius: 50%; + overflow: hidden; + background: #ccc; + @apply(--shadow-elevation-2dp); + } + .paper-font-subhead{ + text-align: center; + } + </style> + <div class="avatar" id="avatar" item-icon></div> + <div class="paper-font-subhead">{{_displayName}}</div> + </template> + <script> + 'use strict'; + Polymer({ + is: 'user-avatar', + behaviors:[Chat.AnonymousContactBehavior], + observers:['_computeBackgroundImg(contact.*)'], + _computeBackgroundImg:function(){ + console.log('avatar changed'); + var avatar = this.anonymousAccount(this.contact).avatar; + var style = this.$.avatar.style; + style.backgroundImage='url('+avatar.url+')'; + style.backgroundPosition=avatar.left+'px '+avatar.top+'px'; + } + }); + </script> +</dom-module> diff --git a/app/elements/contact-item/anonymous-contact-behavior.html b/app/elements/contact-item/anonymous-contact-behavior.html @@ -0,0 +1,337 @@ +<script> +'use strict'; +var Chat = window.Chat || {}; +var djb2Code = function(str) { + var hash = 5381; + for (var i = 0; i < str.length; i++) { + var character = str.charCodeAt(i); + hash = ((hash << 5) + hash) + character; /* hash * 33 + c */ + } + return hash > 0 ? hash : -hash; +}; +var animals = [ + 'Adelie', + 'Penguin', + 'Akita', + 'Bulldog', + 'Ant', + 'Fox', + 'Hare', + 'Wolf', + 'Terrier', + 'Avocet', + 'Baboon', + 'Camel', + 'Badger', + 'Barb', + 'Basenji', + 'Basking', + 'Bat', + 'Beagle', + 'Bear', + 'Collie', + 'Beaver', + 'Beetle', + 'Bichon', + 'Bird', + 'Birman', + 'Bison', + 'Bobcat', + 'Bombay', + 'Bongo', + 'Bonobo', + 'Booby', + 'Boykin', + 'Budgie', + 'Buffalo', + 'Burmese', + 'Fish', + 'Caiman', + 'Lizard', + 'Canaan', + 'Caracal', + 'Cat', + 'Catfish', + 'Cesky', + 'Fousek', + 'Chamois', + 'Cheetah', + 'Chicken', + 'Chinook', + 'Cichlid', + 'Leopard', + 'Clumber', + 'Coati', + 'Coral', + 'Tamarin', + 'Cougar', + 'Cow', + 'Coyote', + 'Crab', + 'Macaque', + 'Crane', + 'Cuscus', + 'Frog', + 'Deer', + 'Bracke', + 'Dhole', + 'Dingo', + 'Discus', + 'Dodo', + 'Dog', + 'Dogo', + 'Dolphin', + 'Donkey', + 'Drever', + 'Duck', + 'Dugong', + 'Dunker', + 'Dusky', + 'Eagle', + 'Earwig ', + 'Gorilla', + 'Echidna', + 'Emu', + 'Falcon', + 'Fennec', + 'Ferret', + 'Spitz', + 'Fly', + 'Fossa', + 'Gecko', + 'Gerbil', + 'Gharial', + 'Gibbon', + 'Giraffe', + 'Goat', + 'Oriole', + 'Goose', + 'Gopher', + 'Grouse', + 'Guppy', + 'Shark', + 'Hamster', + 'Harrier', + 'Heron', + 'Horse', + 'Human', + 'Hyena', + 'Ibis', + 'Iguana', + 'Impala', + 'Indri', + 'Insect', + 'Setter', + 'Jackal', + 'Jaguar', + 'Kakapo', + 'Kiwi', + 'Koala', + 'Lemming', + 'Lemur', + 'Liger', + 'Lion', + 'Llama', + 'Lobster', + 'Owl', + 'Lynx', + 'Mayfly', + 'Meerkat', + 'Molly', + 'Mongrel', + 'Monkey', + 'Moorhen', + 'Moose', + 'Mouse', + 'Mule', + 'Numbat', + 'Ocelot', + 'Octopus', + 'Okapi', + 'Opossum', + 'Ostrich', + 'Otter', + 'Oyster', + 'Panther', + 'Parrot', + 'Peacock', + 'Pelican', + 'Persian', + 'Pig', + 'Piranha', + 'Pointer', + 'Poodle', + 'Possum', + 'Prawn', + 'Puffin', + 'Pug', + 'Puma', + 'Pygmy', + 'Quail', + 'Quetzal', + 'Quokka', + 'Quoll', + 'Rabbit', + 'Raccoon', + 'Ragdoll', + 'Rat', + 'Robin', + 'Saola', + 'Seal', + 'Serval', + 'Sheep', + 'Shrimp', + 'Siamese', + 'Skunk', + 'Sloth', + 'Snail', + 'Snake', + 'Somali', + 'Sparrow', + 'Dogfish', + 'Sponge', + 'Squid', + 'Stoat', + 'Swan', + 'Tang', + 'Tapir', + 'Tarsier', + 'Termite', + 'Tetra', + 'Tiffany', + 'Tiger', + 'Toucan', + 'Tuatara', + 'Turkey', + 'Uakari', + 'Uguisu', + 'Vulture', + 'Wallaby', + 'Walrus', + 'Warthog', + 'Wasp', + 'Weasel', + 'Whippet', + 'Wombat', + 'Wrasse', + 'Yak', + 'Yorkie', + 'Zebra', + 'Zebu', + 'Zonkey', + 'Zorse' +]; +var bb = [ + 'Walter White', + 'Skyler White', + 'Jesse Pinkman', + 'Hank Schrader', + 'Marie Schrader', + 'Walter White, Jr.', + 'Saul Goodman', + 'Gustavo Fring', + 'Mike Ehrmantraut', + 'Lydia Rodarte-Quayle', + 'Todd Alquist', + 'Steven Gomez', + 'Detectives Kalanchoe & Munn', + 'George Merkert', + 'Sac Ramey', + 'Tim Roberts', + 'Maximino Arciniega', + 'Gale Boetticher', + 'Duane Chow', + 'Ron Forenall', + 'Barry Goodman', + 'Tyrus Kitt', + 'Chris Mara', + 'Dennis Markowski', + 'Victor', + 'Dan Wachsberger', + 'Don Eladio Vuente', + 'Juan Bolsa', + 'Hector Salamanca', + 'Tuco Salamanca', + 'Leonel Salamanca', + 'Marco Salamanca', + 'Gonzo', + 'Emilio Koyama', + 'Krazy-8 Molina', + 'Jack Welker', + 'Andrea Cantillo', + 'Brock Cantillo', + 'Jane Margolis', + 'Brandon Mayhew', + 'Combo Ortega', + 'Skinny Pete', + 'Adam Pinkman', + 'Mrs. Pinkman', + 'Jake Pinkman', + 'Wendy', + 'Huell Babineaux', + 'Ed', + 'Francesca', + 'Patrick Kuby', + 'Hugo Archuleta', + 'Ted Beneke', + 'Clovis', + 'Louis Corbett', + 'Dr. Delcavoli', + 'Lawson', + 'Donald Margolis', + 'Carmen Molina', + 'Old Joe', + 'Pamela', + 'Gretchen Schwartz', + 'Elliott Schwartz', + 'Drew Sharp', + 'Spooge', + 'Holly White', + 'Bogdan Wolynetz' +]; +Chat.AnonymousContactBehavior = { + properties: { + contact: { + type: Object, + notify: true + }, + _displayName: { + computed: '_computeDisplayName(contact)' + } + }, + _computeDisplayName: function(contact) { + if (contact === undefined || contact === null) { + return 'connecting...'; + } + if (contact === 'error' || contact === 'invite') { + return ''; + } + if (!contact.name) { + return this.anonymousAccount(contact).name; + } + return contact.name; + }, + get names() { + return bb; + }, + anonymousAccount: function(contact) { + if (contact && !contact.name) { + var peer = contact.peer || contact; + var hash = djb2Code(peer); + var i = hash % this.names.length; + var name = this.names[i]; + var marginTop = i % 2; + var marginLeft = Math.floor(i / 2) % 5; + return { + name: name, + peer: peer, + avatar: { + url: 'images/avatars.jpg', + left: -14 + 80 * marginLeft, + top: -19 + 95 * marginTop + } + }; + } + } +}; +</script> diff --git a/app/elements/elements.html b/app/elements/elements.html @@ -1,35 +1,7 @@ -<!-- -@license -Copyright (c) 2015 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt ---> - -<!-- Iron elements --> -<link rel="import" href="../bower_components/iron-flex-layout/classes/iron-flex-layout.html"> -<link rel="import" href="../bower_components/iron-icons/iron-icons.html"> -<link rel="import" href="../bower_components/iron-pages/iron-pages.html"> -<link rel="import" href="../bower_components/iron-selector/iron-selector.html"> - -<!-- Paper elements --> -<link rel="import" href="../bower_components/paper-drawer-panel/paper-drawer-panel.html"> -<link rel="import" href="../bower_components/paper-icon-button/paper-icon-button.html"> -<link rel="import" href="../bower_components/paper-item/paper-item.html"> -<link rel="import" href="../bower_components/paper-material/paper-material.html"> -<link rel="import" href="../bower_components/paper-menu/paper-menu.html"> -<link rel="import" href="../bower_components/paper-scroll-header-panel/paper-scroll-header-panel.html"> -<link rel="import" href="../bower_components/paper-styles/paper-styles-classes.html"> -<link rel="import" href="../bower_components/paper-toast/paper-toast.html"> -<link rel="import" href="../bower_components/paper-toolbar/paper-toolbar.html"> - -<!-- Uncomment next block to enable Service Worker Support (2/2) --> -<!-- <link rel="import" href="../bower_components/platinum-sw/platinum-sw-cache.html"> <link rel="import" href="../bower_components/platinum-sw/platinum-sw-register.html"> ---> +<link rel="import" href="../bower_components/paper-toast/paper-toast.html"> + <!-- Configure your routes here --> <link rel="import" href="routing.html"> @@ -37,5 +9,6 @@ subject to an additional IP rights grant found at http://polymer.github.io/PATEN <!-- Add your elements here --> <link rel="import" href="../styles/app-theme.html"> <link rel="import" href="../styles/shared-styles.html"> -<link rel="import" href="my-greeting/my-greeting.html"> -<link rel="import" href="my-list/my-list.html"> +<link rel="import" href="buddy-finder/buddy-finder.html"> +<link rel="import" href="p2p-network/p2p-network.html"> + diff --git a/app/elements/file-sharing/file-drop-behavior.html b/app/elements/file-sharing/file-drop-behavior.html @@ -0,0 +1,37 @@ +<script> +'use strict'; +Chat = window.Chat || {}; +Chat.FileDropBehavior = { + attached: function() { + var dropZone = this; + + // Optional. Show the copy icon when dragging over. Seems to only work for chrome. + dropZone.addEventListener('dragover', function(e) { + e.stopPropagation(); + e.preventDefault(); + e.dataTransfer.dropEffect = 'copy'; + this.style.transform = 'scale(1.2)'; + }); + + // Get file data on drop + dropZone.addEventListener('drop', function(e) { + e.stopPropagation(); + e.preventDefault(); + var files = e.dataTransfer.files; // Array of all files + for (var i = 0; i < files.length; i++) { + var file = files[i]; + var reader = new FileReader(); + reader.onload = function(e2) { + // finished reading file data. + console.log('file dropped'); + this.fire('file-uploaded', { + url: e2.target.result, + name: file.name + }); + }.bind(this); + reader.readAsDataURL(file); // start reading the file data. + } + }); + } +} +</script> diff --git a/app/elements/file-sharing/file-sharing-button-behavior.html b/app/elements/file-sharing/file-sharing-button-behavior.html @@ -0,0 +1,36 @@ +<script> +'use strict'; +Chat.FileSharingButtonBehavior = { + properties: { + file: { + type: String + } + }, + get fileInput(){ + var fileInput=document.querySelector('input'); + }, + attached: function() { + this.$.file.onchange = function(value) { + this.file = this.$.file.value; + console.log(this.file); + var files = this.$.file.files; + for (var i = 0; i < files.length; i++) { + var file = files[i]; + var reader = new FileReader(); + reader.onload = function(e2) { + // finished reading file data. + console.log('file dropped'); + this.fire('file-uploaded', { + url: e2.target.result, + name: file.name + }); + }.bind(this); + reader.readAsDataURL(file); // start reading the file data. + } + }.bind(this); + }, + _upload: function() { + this.$.file.click(); + } +}; +</script> diff --git a/app/elements/file-sharing/file-sharing-button.html b/app/elements/file-sharing/file-sharing-button.html @@ -0,0 +1,58 @@ +<link rel="import" href="../../../bower_components/paper-icon-button/paper-icon-button.html"> +<link rel="import" href="file-reader.html"> +<dom-module id="file-sharing-button"> + <template> + <style> + :host { + display: inline-block; + } + + #file { + margin: 0; + opacity: 0; + padding: 0; + position: absolute; + top: -10000px; + } + </style> + <paper-icon-button id="btn" icon="chat:attach-file" on-tap="_upload"></paper-icon-button> + <input id="file" type="file" value="{{file::input}}"> + </template> + <script> + 'use strict'; + Polymer({ + is: 'file-sharing-button', + properties: { + file: { + type: String + } + }, + attached: function() { + this.$.file.onchange = function(value) { + this.file = this.$.file.value; + console.log(this.file); + + var files = this.$.file.files; + for (var i = 0; i < files.length; i++) { + var file = files[i]; + var reader = new FileReader(); + reader.onload = function(e2) { + // finished reading file data. + console.log('file dropped'); + this.fire('file-uploaded', { + url: e2.target.result, + name: file.name + }); + }.bind(this); + reader.readAsDataURL(file); // start reading the file data. + } + + + }.bind(this); + }, + _upload: function() { + this.$.file.click(); + } + }); + </script> +</dom-module> diff --git a/app/elements/file-sharing/file-sharing.html b/app/elements/file-sharing/file-sharing.html @@ -0,0 +1,48 @@ +<link rel="import" href="../../../bower_components/paper-dialog/paper-dialog.html"> +<link rel="import" href="file-reader.html"> +<dom-module id="file-sharing"> + <template> + <style> + :host { + display: block; + position: fixed; + z-index: 100; + } + </style> + <paper-dialog id="dialog" entry-animation="scale-up-animation" exit-animation="fade-out-animation" with-backdro> + <h2>File Received</h2> + <p>You received file {{file.name}}</p> + <div class="buttons"> + <paper-button dialog-dismiss>Dismiss</paper-button> + <paper-button dialog-confirm on-tap="_download">Download</paper-button> + </div> + </paper-dialog> + </template> + <script> + 'use strict'; + Polymer({ + is: 'file-sharing', + attached: function() { + document.querySelector('x-app').addEventListener('file-received', function(e) { + this.fileReceived(e.detail); + }.bind(this), false); + }, + fileReceived: function(file) { + this.set('file', file); + this.$.dialog.open(); + }, + _download: function() { + var link = document.createElement('a'); + link.download = this.file.name; + // Construct the uri + var uri = this.file.url; + link.href = uri; + document.body.appendChild(link); + link.click(); + // Cleanup the DOM + document.body.removeChild(link); + //delete link; + } + }); + </script> +</dom-module> diff --git a/app/elements/file-sharing/share-area.html b/app/elements/file-sharing/share-area.html @@ -0,0 +1,18 @@ +<link rel="import" href="file-drop-behavior.html"> +<dom-module id="share-area"> + <template> + <style> + :host { + display: block; + } + </style> + <content></content> + </template> + <script> + 'use strict'; + Polymer({ + is: 'share-area', + behaviors: [Chat.FileDropBehavior] + }); + </script> +</dom-module> diff --git a/app/elements/p2p-network/p2p-network-imports.html b/app/elements/p2p-network/p2p-network-imports.html @@ -0,0 +1 @@ +<script src="../../../bower_components/peerjs/peer.min.js"></script> diff --git a/app/elements/p2p-network/p2p-network.html b/app/elements/p2p-network/p2p-network.html @@ -0,0 +1,245 @@ +<link rel="import" href="p2p-network-imports.html"> +<link rel="import" href="../../../bower_components/iron-localstorage/iron-localstorage.html"> +<dom-module id="p2p-network"> + <template> + <iron-localstorage name="peer-id" value="{{me}}" id="meStorage"> + </iron-localstorage> + <iron-localstorage name="peers" value="{{peers}}" on-iron-localstorage-load-empty="initializeDefaultPeers"> + </iron-localstorage> + </template> + <script> + 'use strict'; + Polymer({ + is: 'p2p-network', + properties: { + me: { + type: String, + notify: true, + observer: '_initialize' + }, + peers: { + type: Array, + value: [], + notify: true, + }, + peer: { + value: 'loading', + notify: true + } + }, + attached: function() { + this._connectedPeers = {}; + this._initCallbacks = []; + this._unsendMsgs = {}; + window.onunload = window.onbeforeunload = function() { + if (!!this._peer && !this._peer.destroyed) { + this._peer.destroy(); + } + }.bind(this); + }, + _initialize: function(me) { + if (!this.initialized && this.$.meStorage._loaded) { + var options = { + host: 'yawim.com', + port: 443 , + path:'peerjs', + secure: true + }; + me = me ? me : undefined; + me = me === 'null' ? undefined : me; + this._peer = new Peer(me, options); + this._peer.on('open', function(id) { + console.log('My peer ID is: ' + id); + this.set('me', id); + this._peerOpen = true; + this._initCallbacks.forEach(function(cb) { + cb(); + }); + }.bind(this)); + + this._peer.on('connection', this.connect.bind(this)); + this._peer.on('error', function(err) { + console.error(err); + //ugly hack to find out error type + if (err.message.indexOf('Could not connect to peer') > -1) { + delete this._connectedPeers[this.peer]; + this.set('peer', 'error'); + return; + } + if (err.message.indexOf('Lost connection to server') > -1) { + this._peer.destroy(); + this.initialized = false; + this._connectedPeers = {}; + this.set('me', me); + this._initialize(this.me); + return; + } + }.bind(this)); + + } + this.initialized = true; + }, + + connect: function(c) { + var peer = c.peer; + + if (c.label === 'chat') { + c.on('data', function(data) { + this.addToHistory(c.peer, data); + this.sendIReceived(c.peer, data); + }.bind(this)); + c.on('close', function() { + console.log(c.peer + ' has left the chat.'); + delete this._connectedPeers[peer]; + }.bind(this)); + + if(!this.peers){ + this.set('peers',[]); + } + var peerInContacts = this.peers.some(function(p) { + return p.peer === peer; + }); + if (!peerInContacts) { + this.push('peers', { + peer: peer + }); + } + this._connectedPeers[peer] = 1; + + this.fire('connected-to-peer', peer); + } + + if (c.label === 'file') { + c.on('data', function(data) { + // If we're getting a file, create a URL for it. + console.log('received!', data); + this.fire('file-received', { + peer: peer, + url: data.url, + name: data.name, + }); + }.bind(this)); + } + + if (c.label === 'received-channel') { + c.on('data', function(data) { + this._peerReceivedMsg(c.peer, data); + }.bind(this)); + } + //send unsend messages + if (this._unsendMsgs[peer]) { + this._unsendMsgs[peer].forEach(function(msg) { + this.send(peer, msg); + }.bind(this)); + } + }, + connectToPeer: (function() { + function request(requestedPeer) { + return function() { + var c = this._peer.connect(requestedPeer, { + label: 'chat', + metadata: { + message: 'hi i want to chat with you!' + } + }); + c.on('open', function() { + this.connect(c); + }.bind(this)); + + + var c1 = this._peer.connect(requestedPeer, { + label: 'received-channel', + }); + c1.on('open', function() { + this.connect(c1); + }.bind(this)); + + + var f = this._peer.connect(requestedPeer, { + label: 'file', + reliable: true + }); + f.on('open', function() { + this.connect(f); + }.bind(this)); + f.on('error', function(err) { + console.log(err); + }); + }; + } + return function(requestedPeer) { + if (!this._connectedPeers[requestedPeer]) { + this.set('peer', 'loading'); + if (this._peerOpen) { + request(requestedPeer).bind(this)(); + } else { + this._initCallbacks.push(request(requestedPeer).bind(this)); + } + } + }; + }()), + send: function(peerId, msg) { + var conns = this._peer.connections[peerId]; + if (conns) { + for (var i = 0; i < conns.length; i++) { + var conn = conns[i]; + if (conn.label === 'chat') { + this._addToUnsendMsgs(peerId, msg); + conn.send(msg); + this.addToHistory(conn.peer, msg); + } + } + } else { + this._addToUnsendMsgs(peerId, msg); + this.connectToPeer(peerId); + } + }, + sendFile: function(peerId, file) { + var conns = this._peer.connections[peerId]; + if (conns) { + for (var i = 0; i < conns.length; i++) { + var conn = conns[i]; + if (conn.label === 'file') { + conn.send(file); + console.log('file send'); + } + } + } + }, + _addToUnsendMsgs: function(peerId, msg) { + if (!this._unsendMsgs[peerId]) { + this._unsendMsgs[peerId] = []; + } + if (this._unsendMsgs[peerId].indexOf(msg) === -1) { + this._unsendMsgs[peerId].push(msg); + console.log('added unsend', msg); + } + }, + sendIReceived: function(peerId, msg) { + var conns = this._peer.connections[peerId]; + if (conns) { + for (var i = 0; i < conns.length; i++) { + var conn = conns[i]; + if (conn.label === 'received-channel') { + conn.send(msg); + } + } + } else { + this.connectToPeer(peerId); + } + }, + addToHistory: function(peerId, msg) { + console.log('send message', msg); + this.fire('new-message', msg); + }, + initializeDefaultPeers: function() { + this.peers = []; + }, + _peerReceivedMsg: function(peerId, msg) { + console.log('received', peerId, msg); + var i = this._unsendMsgs[peerId].indexOf(msg); + this._unsendMsgs[peerId].splice(i, 1); + } + }); + </script> +</dom-module> diff --git a/app/images/avatars.jpg b/app/images/avatars.jpg Binary files differ. diff --git a/app/images/nice_background.jpg b/app/images/nice_background.jpg Binary files differ. diff --git a/app/index.html b/app/index.html @@ -2,83 +2,61 @@ <html lang="en"> <head> - <meta charset="utf-8"> - <meta name="description" content=""> - <meta name="viewport" content="width=device-width, initial-scale=1"> - <meta name="generator" content="Share With Me!"> - <title>Share With Me!</title> - <!-- Place favicon.ico in the `app/` directory --> - - <!-- Chrome for Android theme color --> - <meta name="theme-color" content="#2E3AA1"> - - <!-- Web Application Manifest --> - <link rel="manifest" href="manifest.json"> - - <!-- Tile color for Win8 --> - <meta name="msapplication-TileColor" content="#3372DF"> - - <!-- Add to homescreen for Chrome on Android --> - <meta name="mobile-web-app-capable" content="yes"> - <meta name="application-name" content="PSK"> - <link rel="icon" sizes="192x192" href="images/touch/chrome-touch-icon-192x192.png"> - - <!-- Add to homescreen for Safari on iOS --> - <meta name="apple-mobile-web-app-capable" content="yes"> - <meta name="apple-mobile-web-app-status-bar-style" content="black"> - <meta name="apple-mobile-web-app-title" content="Share With Me!"> - <link rel="apple-touch-icon" href="images/touch/apple-touch-icon.png"> - - <!-- Tile icon for Win8 (144x144) --> - <meta name="msapplication-TileImage" content="images/touch/ms-touch-icon-144x144-precomposed.png"> - - <!-- build:css styles/main.css --> - <link rel="stylesheet" href="styles/main.css"> - <!-- endbuild--> - - <!-- build:js bower_components/webcomponentsjs/webcomponents-lite.min.js --> - <script src="bower_components/webcomponentsjs/webcomponents-lite.js"></script> - <!-- endbuild --> - - <!-- Because this project uses vulcanize this should be your only html import + <meta charset="utf-8"> + <meta name="description" content=""> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="generator" content="Share With Me!"> + <title>Share With Me!</title> + <!-- Place favicon.ico in the `app/` directory --> + <!-- Chrome for Android theme color --> + <meta name="theme-color" content="#2E3AA1"> + <!-- Web Application Manifest --> + <link rel="manifest" href="manifest.json"> + <!-- Tile color for Win8 --> + <meta name="msapplication-TileColor" content="#3372DF"> + <!-- Add to homescreen for Chrome on Android --> + <meta name="mobile-web-app-capable" content="yes"> + <meta name="application-name" content="PSK"> + <link rel="icon" sizes="192x192" href="images/touch/chrome-touch-icon-192x192.png"> + <!-- Add to homescreen for Safari on iOS --> + <meta name="apple-mobile-web-app-capable" content="yes"> + <meta name="apple-mobile-web-app-status-bar-style" content="black"> + <meta name="apple-mobile-web-app-title" content="Share With Me!"> + <link rel="apple-touch-icon" href="images/touch/apple-touch-icon.png"> + <!-- Tile icon for Win8 (144x144) --> + <meta name="msapplication-TileImage" content="images/touch/ms-touch-icon-144x144-precomposed.png"> + <!-- build:css styles/main.css --> + <link rel="stylesheet" href="styles/main.css"> + <!-- endbuild--> + <!-- build:js bower_components/webcomponentsjs/webcomponents-lite.min.js --> + <script src="bower_components/webcomponentsjs/webcomponents-lite.js"></script> + <!-- endbuild --> + <!-- Because this project uses vulcanize this should be your only html import in this file. All other imports should go in elements.html --> - <link rel="import" href="elements/elements.html"> - - <!-- For shared styles, shared-styles.html import in elements.html --> - <style is="custom-style" include="shared-styles"></style> - + <link rel="import" href="elements/elements.html"> + <!-- For shared styles, shared-styles.html import in elements.html --> + <style is="custom-style" include="shared-styles"></style> </head> <body unresolved class="fullbleed layout vertical"> - <span id="browser-sync-binding"></span> - <template is="dom-bind" id="app"> - - - <paper-toast id="toast"> - <span class="toast-hide-button" role="button" tabindex="0" onclick="app.$.toast.hide()">Ok</span> - </paper-toast> - - <!-- Uncomment next block to enable Service Worker support (1/2) --> - - <paper-toast id="caching-complete" - duration="6000" - text="Caching complete! This app will work offline."> - </paper-toast> - - <platinum-sw-register auto-register - clients-claim - skip-waiting - base-uri="bower_components/platinum-sw/bootstrap" - on-service-worker-installed="displayInstalledToast"> - <platinum-sw-cache default-cache-strategy="fastest" - cache-config-file="cache-config.json"> - </platinum-sw-cache> - </platinum-sw-register> - </template> - - <!-- build:js scripts/app.js --> - <script src="scripts/app.js"></script> - <!-- endbuild--> + <span id="browser-sync-binding"></span> + <template is="dom-bind" id="app"> + <buddy-finder me="{{me}}"></buddy-finder> + <p2p-network me="{{me}}"></p2p-network> + <paper-toast id="toast"> + <span class="toast-hide-button" role="button" tabindex="0" onclick="app.$.toast.hide()">Ok</span> + </paper-toast> + <!-- Uncomment next block to enable Service Worker support (1/2) --> + <paper-toast id="caching-complete" duration="6000" text="Caching complete! This app will work offline."> + </paper-toast> + <platinum-sw-register auto-register clients-claim skip-waiting base-uri="bower_components/platinum-sw/bootstrap" on-service-worker-installed="displayInstalledToast"> + <platinum-sw-cache default-cache-strategy="fastest" cache-config-file="cache-config.json"> + </platinum-sw-cache> + </platinum-sw-register> + </template> + <!-- build:js scripts/app.js --> + <script src="scripts/app.js"></script> + <!-- endbuild--> </body> </html> diff --git a/bower.json b/bower.json @@ -8,7 +8,8 @@ "paper-elements": "PolymerElements/paper-elements#^1.0.1", "platinum-elements": "PolymerElements/platinum-elements#^1.1.0", "polymer": "Polymer/polymer#^1.2.0", - "paper-menu": "PolymerElements/paper-menu#4fecb43601" + "paper-menu": "PolymerElements/paper-menu#4fecb43601", + "peerjs": "~0.3.14" }, "devDependencies": { "web-component-tester": "*" diff --git a/gulpfile.js b/gulpfile.js @@ -1,11 +1,4 @@ -/* -Copyright (c) 2015 The Polymer Project Authors. All rights reserved. -This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt -The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt -The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt -Code distributed by Google as part of the polymer project is also -subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt -*/ + 'use strict'; @@ -236,7 +229,7 @@ gulp.task('clean', function() { }); // Watch files for changes & reload -gulp.task('serve', ['lint', 'styles', 'elements', 'images'], function() { +gulp.task('serve', [ 'styles', 'elements', 'images'], function() { browserSync({ port: 5000, notify: false,