mirror of
https://github.com/schlagmichdoch/PairDrop.git
synced 2025-04-26 17:56:16 -04:00
first working version
This commit is contained in:
parent
f1ad168e40
commit
bda1a15750
24 changed files with 543 additions and 206 deletions
|
@ -52,12 +52,10 @@
|
|||
</file-input>
|
||||
</template>
|
||||
</div>
|
||||
<div hidden$="{{buddies.length}}" class="explanation">
|
||||
Open this page on another device
|
||||
<wbr>to share files.
|
||||
<div hidden$="{{buddies.0}}" class="explanation">
|
||||
Open this page on other devices<br> to send files.
|
||||
</div>
|
||||
<personal-avatar class="me"></personal-avatar>
|
||||
<!-- <iron-ajax id="ajax" auto url="https://yawim.com/findbuddies/{{me}}" handle-as="json" last-response="{{buddies}}"></iron-ajax> -->
|
||||
</template>
|
||||
<script>
|
||||
'use strict';
|
||||
|
@ -66,30 +64,11 @@
|
|||
properties: {
|
||||
buddies: {
|
||||
type: Array,
|
||||
value: []
|
||||
notify: true
|
||||
},
|
||||
me: {
|
||||
type: String,
|
||||
}
|
||||
},
|
||||
attached: function() {
|
||||
//Ask server every second for changes
|
||||
var ajax = this.$.ajax;
|
||||
|
||||
function request() {
|
||||
//ajax.generateRequest();
|
||||
}
|
||||
var intervalId = setInterval(request, 1000);
|
||||
document.addEventListener('visibilitychange', function() {
|
||||
if (document.hidden) {
|
||||
clearInterval(intervalId);
|
||||
intervalId = 0;
|
||||
} else {
|
||||
if (!intervalId) {
|
||||
intervalId = setInterval(request, 1000);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
_fileSelected: function(e) {
|
||||
var peerId = e.model.item.peerId;
|
||||
|
|
|
@ -13,11 +13,11 @@
|
|||
width: 80px;
|
||||
height: 80px;
|
||||
color: #4285f4;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.paper-font-body1 {
|
||||
font-size: 13px;
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.discover {
|
||||
|
@ -26,7 +26,7 @@
|
|||
</style>
|
||||
<iron-icon icon="chat:wifi-tethering"></iron-icon>
|
||||
<div class="paper-font-body1">
|
||||
SnapDrop lets you share instantly with people near by.
|
||||
Snapdrop lets you share instantly with people near by.
|
||||
</div>
|
||||
<div class="paper-font-body1 discover">
|
||||
Allow me to be discovered by: Everyone in this network.
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
@apply(--layout-vertical);
|
||||
@apply(--layout-center);
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
height: 152px;
|
||||
}
|
||||
|
||||
paper-icon-button {
|
||||
|
@ -45,7 +45,7 @@
|
|||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
margin: 4px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
</style>
|
||||
<paper-icon-button icon="{{_displayIcon}}"></paper-icon-button>
|
||||
|
@ -85,7 +85,6 @@
|
|||
if (contact.type === 'tablet') {
|
||||
return 'chat:tablet-mac';
|
||||
}
|
||||
|
||||
return 'chat:desktop-mac';
|
||||
},
|
||||
attached: function() {
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
<link rel="import" href="../bower_components/platinum-sw/platinum-sw-register.html">
|
||||
<link rel="import" href="../bower_components/paper-toast/paper-toast.html">
|
||||
<link rel="import" href="../bower_components/paper-progress/paper-progress.html">
|
||||
|
||||
|
||||
<link rel="import" href="../bower_components/neon-animation/neon-animated-pages.html">
|
||||
<!-- Configure your routes here
|
||||
<link rel="import" href="routing.html">
|
||||
-->
|
||||
<!-- Add your elements here -->
|
||||
<link rel="import" href="../styles/app-theme.html">
|
||||
<link rel="import" href="x-cards/x-card.html">
|
||||
<link rel="import" href="x-cards/x-cards.html">
|
||||
<link rel="import" href="buddy-finder/buddy-finder.html">
|
||||
<link rel="import" href="p2p-network/connection-wrapper.html">
|
||||
<link rel="import" href="file-sharing/file-receiver.html">
|
||||
|
||||
|
|
|
@ -17,13 +17,14 @@
|
|||
z-index: 101;
|
||||
}
|
||||
|
||||
b {
|
||||
.filename {
|
||||
word-break: break-all;
|
||||
word-break: break-word;
|
||||
}
|
||||
</style>
|
||||
<paper-dialog id="dialog" entry-animation="scale-up-animation" exit-animation="fade-out-animation" with-backdrop modal>
|
||||
<h2>Download File</h2>
|
||||
<p><b>{{file.name}}</b></p>
|
||||
<p><b class="filename">{{file.name}}</b></p>
|
||||
<div class="buttons">
|
||||
<paper-button dialog-dismiss on-tap="_decline">Discard</paper-button>
|
||||
<paper-button dialog-confirm on-tap="_accept" autofocus>Download</paper-button>
|
||||
|
@ -31,11 +32,11 @@
|
|||
</paper-dialog>
|
||||
<paper-dialog id="download" entry-animation="scale-up-animation" exit-animation="fade-out-animation" with-backdrop modal>
|
||||
<h2>File Received</h2>
|
||||
<p>Right Click and "Save as"...</p>
|
||||
<p>Open File or Right Click and "Save as"...</p>
|
||||
<div class="buttons">
|
||||
<paper-button dialog-dismiss>Discard</paper-button>
|
||||
<a href="{{dataUri}}" target="_blank">
|
||||
<paper-button dialog-confirm autofocus>Download</paper-button>
|
||||
<paper-button dialog-confirm autofocus>Open File</paper-button>
|
||||
</a>
|
||||
</div>
|
||||
</paper-dialog>
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -7,8 +7,11 @@ Chat.FileSelectionBehavior = {
|
|||
console.log('no files selected...');
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var file = files[i];
|
||||
this._fileSelected(files[0]); //single select
|
||||
//files.forEach(this._fileSelected.bind(this)); //multi-select
|
||||
},
|
||||
_fileSelected: function(file) {
|
||||
if (file) {
|
||||
this.fire('file-selected', {
|
||||
file: file,
|
||||
name: file.name
|
||||
|
|
|
@ -8,27 +8,17 @@
|
|||
<script>
|
||||
'use strict';
|
||||
(function() {
|
||||
function guid() {
|
||||
function s4() {
|
||||
return Math.floor((1 + Math.random()) * 0x10000)
|
||||
.toString(16)
|
||||
.substring(1);
|
||||
}
|
||||
return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
|
||||
s4() + '-' + s4() + s4() + s4();
|
||||
}
|
||||
var webRTCSupported = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection || window.webkitRTCPeerConnection;
|
||||
window.webRTCSupported = !!(window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection || window.webkitRTCPeerConnection);
|
||||
|
||||
function rtcConnectionSupported(peerId) {
|
||||
return webRTCSupported && (peerId.indexOf('rtc_') === 0);
|
||||
return window.webRTCSupported && (peerId.indexOf('rtc_') === 0);
|
||||
}
|
||||
Polymer({
|
||||
is: 'connection-wrapper',
|
||||
properties: {
|
||||
me: {
|
||||
notify: true,
|
||||
value: (webRTCSupported ? 'rtc_' : 'ws_') + guid()
|
||||
}
|
||||
notify: true
|
||||
},
|
||||
},
|
||||
behaviors: [Chat.FileTransferProtocol],
|
||||
_sendFile: function(toPeer, file) {
|
||||
|
@ -50,9 +40,17 @@
|
|||
if (!rtcConnectionSupported(toPeer)) {
|
||||
callback();
|
||||
} else {
|
||||
this.$.p2p.connectToPeer(toPeer,callback);
|
||||
this.$.p2p.connectToPeer(toPeer, callback);
|
||||
}
|
||||
},
|
||||
_onHandshake: function(event) {
|
||||
var me = event.uuid;
|
||||
console.log('i am');
|
||||
this.set('me', me);
|
||||
if (window.webRTCSupported) {
|
||||
this.$.p2p.initialize();
|
||||
}
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
|
|
@ -22,6 +22,9 @@ Chat.FileTransferProtocol = {
|
|||
console.log('FTP received sysMsg:', msg);
|
||||
|
||||
switch (msg.type) {
|
||||
case 'handshake':
|
||||
this._onHandshake(msg);
|
||||
break;
|
||||
case 'offer':
|
||||
this._onOffered(msg);
|
||||
break;
|
||||
|
|
|
@ -9,8 +9,7 @@
|
|||
is: 'p2p-network',
|
||||
properties: {
|
||||
me: {
|
||||
type: String,
|
||||
notify: true,
|
||||
type: String
|
||||
}
|
||||
},
|
||||
attached: function() {
|
||||
|
@ -22,16 +21,24 @@
|
|||
this._peer.destroy();
|
||||
}
|
||||
}.bind(this);
|
||||
this._initialize();
|
||||
},
|
||||
_initialize: function() {
|
||||
var options = {
|
||||
host: 'yawim.com',
|
||||
port: 443,
|
||||
path: 'peerjs',
|
||||
secure: true
|
||||
};
|
||||
this._peer = new Peer(this.me,options);
|
||||
initialize: function() {
|
||||
var options;
|
||||
if (window.debug) {
|
||||
options = {
|
||||
host: window.location.hostname,
|
||||
port: 3002,
|
||||
path: 'peerjs'
|
||||
};
|
||||
} else {
|
||||
options = {
|
||||
host: 'snapdrop.net',
|
||||
port: 443,
|
||||
path: 'peerjs',
|
||||
secure: true
|
||||
};
|
||||
}
|
||||
this._peer = new Peer(this.me, options);
|
||||
this._peer.on('open', function(id) {
|
||||
console.log('My peer ID is: ' + id);
|
||||
this.set('me', id);
|
||||
|
@ -53,12 +60,10 @@
|
|||
if (err.message.indexOf('Lost connection to server') > -1) {
|
||||
this._peer.destroy();
|
||||
this.set('me', this.me);
|
||||
this._initialize();
|
||||
this.async(this._initialize, 3000);
|
||||
return;
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
|
||||
},
|
||||
|
||||
connect: function(c) {
|
||||
|
@ -140,7 +145,7 @@
|
|||
conns.forEach(function(conn) {
|
||||
if (conn.label === 'file') {
|
||||
conn.send(file);
|
||||
console.log('file send');
|
||||
console.log('file send via WebRTC');
|
||||
}
|
||||
}.bind(this));
|
||||
}
|
||||
|
|
|
@ -15,13 +15,13 @@
|
|||
this.init();
|
||||
},
|
||||
init: function() {
|
||||
var websocketUrl = (window.location.protocol === 'https:' ? 'wss://' : 'ws://') + document.location.hostname + ':9001';
|
||||
var websocketUrl = (window.debug ? 'ws://' + window.location.hostname + ':3002' : 'wss://snapdrop.net') + '/binary';
|
||||
this.client = new BinaryClient(websocketUrl);
|
||||
this.client.on('stream', function(stream, meta) {
|
||||
// collect stream data
|
||||
var parts = [];
|
||||
stream.on('data', function(data) {
|
||||
console.log('part received', meta, data);
|
||||
//console.log('part received', meta, data);
|
||||
if (data.isSystemEvent) {
|
||||
if (meta) {
|
||||
data.from = meta.from;
|
||||
|
@ -45,22 +45,22 @@
|
|||
}.bind(this));
|
||||
}.bind(this));
|
||||
this.client.on('open', function(e) {
|
||||
this.cancelAsync(this.reconnectTimer);
|
||||
console.log(e);
|
||||
this.client.send({}, {
|
||||
handshake: this.me
|
||||
serverMsg: 'rtc-support',
|
||||
rtc: window.webRTCSupported
|
||||
});
|
||||
}.bind(this));
|
||||
this.client.on('error', function(e) {
|
||||
console.log(e);
|
||||
});
|
||||
this._reconnect(e);
|
||||
}.bind(this));
|
||||
this.client.on('close', function(e) {
|
||||
console.log(e);
|
||||
//try to reconnect after 3s
|
||||
this.async(this.init, 3000);
|
||||
this._reconnect(e);
|
||||
}.bind(this));
|
||||
},
|
||||
_sendFile: function(toPeer, file) {
|
||||
console.log('send file!', file);
|
||||
console.log('send file via WebSocket', file);
|
||||
this.client.send(file.file, {
|
||||
name: file.file.name,
|
||||
type: file.file.type,
|
||||
|
@ -76,6 +76,11 @@
|
|||
this.client.send(event, {
|
||||
toPeer: toPeer
|
||||
});
|
||||
},
|
||||
_reconnect: function(e) {
|
||||
console.log('disconnected', e);
|
||||
//try to reconnect after 3s
|
||||
this.reconnectTimer = this.async(this.init, 3000);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
138
app/elements/x-cards/x-card.html
Normal file
138
app/elements/x-cards/x-card.html
Normal file
|
@ -0,0 +1,138 @@
|
|||
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout.html">
|
||||
<link rel="import" href="../../bower_components/neon-animation/neon-shared-element-animatable-behavior.html">
|
||||
<link rel="import" href="../../bower_components/neon-animation/neon-animations.html">
|
||||
<link rel="import" href="../../bower_components/paper-styles/paper-styles-classes.html">
|
||||
<link rel="import" href="../../bower_components/iron-icon/iron-icon.html">
|
||||
<dom-module id="x-card">
|
||||
<template>
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
color: white;
|
||||
z-index: 3
|
||||
}
|
||||
|
||||
#placeholder {
|
||||
opacity: 0;
|
||||
background-color: #4285f4;
|
||||
@apply(--layout-fit);
|
||||
}
|
||||
|
||||
paper-icon-button {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
#container {
|
||||
@apply(--layout-fit);
|
||||
@apply(--layout-vertical);
|
||||
@apply(--layout-center-center);
|
||||
background-color: #4285f4;
|
||||
padding: 64px 32px 64px 32px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
iron-icon {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.paper-font-subhead {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
@apply(--layout-self-end);
|
||||
}
|
||||
|
||||
.center {
|
||||
@apply(--layout-vertical);
|
||||
@apply(--layout-center-center);
|
||||
}
|
||||
|
||||
#footer {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
margin-left: -160px;
|
||||
width: 320px;
|
||||
bottom: 24px;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
<paper-icon-button id="btn" icon="chat:close" on-tap="_switch"></paper-icon-button>
|
||||
<div id="placeholder"></div>
|
||||
<div id="container">
|
||||
<div class="center">
|
||||
<iron-icon icon="chat:wifi-tethering"></iron-icon>
|
||||
<div class="paper-font-headline">Snapdrop</div>
|
||||
<div class="paper-font-subhead">The easiest way to send files across devices.</div>
|
||||
</div>
|
||||
<span id="footer">Built with ♥ by <a href="mailto:robin@capira.de">Robin Linus</a></span>
|
||||
</div>
|
||||
</template>
|
||||
</dom-module>
|
||||
<script>
|
||||
(function() {
|
||||
Polymer({
|
||||
is: 'x-card',
|
||||
behaviors: [
|
||||
Polymer.NeonSharedElementAnimatableBehavior
|
||||
],
|
||||
properties: {
|
||||
animationConfig: {
|
||||
value: function() {
|
||||
return {
|
||||
'entry': [{
|
||||
name: 'ripple-animation',
|
||||
id: 'ripple',
|
||||
toPage: this
|
||||
}, {
|
||||
name: 'fade-out-animation',
|
||||
node: this.$.placeholder,
|
||||
timing: {
|
||||
delay: 250
|
||||
}
|
||||
}, {
|
||||
name: 'fade-in-animation',
|
||||
node: this.$.container,
|
||||
timing: {
|
||||
delay: 50
|
||||
}
|
||||
}],
|
||||
'exit': [{
|
||||
name: 'opaque-animation',
|
||||
node: this.$.placeholder
|
||||
}, {
|
||||
name: 'fade-out-animation',
|
||||
node: this.$.container,
|
||||
timing: {
|
||||
duration: 0
|
||||
}
|
||||
}, {
|
||||
name: 'reverse-ripple-animation',
|
||||
id: 'reverse-ripple',
|
||||
fromPage: this
|
||||
}]
|
||||
};
|
||||
}
|
||||
},
|
||||
sharedElements: {
|
||||
value: function() {
|
||||
return {
|
||||
'ripple': this.$.placeholder,
|
||||
'reverse-ripple': this.$.placeholder
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
_switch: function() {
|
||||
document.querySelector('#pages').select(0);
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
83
app/elements/x-cards/x-cards.html
Normal file
83
app/elements/x-cards/x-cards.html
Normal file
|
@ -0,0 +1,83 @@
|
|||
<link rel="import" href="../../bower_components/iron-flex-layout/iron-flex-layout.html">
|
||||
<link rel="import" href="../../bower_components/neon-animation/neon-shared-element-animatable-behavior.html">
|
||||
<link rel="import" href="../../bower_components/neon-animation/neon-animations.html">
|
||||
<link rel="import" href="../../bower_components/paper-icon-button/paper-icon-button.html">
|
||||
<dom-module id="x-cards">
|
||||
<template>
|
||||
<style>
|
||||
:host {
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#placeholder {
|
||||
opacity: 0;
|
||||
background-color: grey;
|
||||
@apply(--layout-fit);
|
||||
}
|
||||
|
||||
paper-icon-button {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
z-index: 2;
|
||||
color: #313131;
|
||||
}
|
||||
|
||||
paper-icon-button:hover {
|
||||
color: #4285f4;
|
||||
}
|
||||
</style>
|
||||
<div id="placeholder"></div>
|
||||
<div id="container">
|
||||
<paper-icon-button id="btn" icon="chat:info-outline" on-tap="_switch"></paper-icon-button>
|
||||
<content select="div"></content>
|
||||
</div>
|
||||
</template>
|
||||
</dom-module>
|
||||
<script>
|
||||
(function() {
|
||||
Polymer({
|
||||
is: 'x-cards',
|
||||
behaviors: [
|
||||
Polymer.NeonSharedElementAnimatableBehavior
|
||||
],
|
||||
properties: {
|
||||
animationConfig: {
|
||||
value: function() {
|
||||
return {
|
||||
'entry': [{
|
||||
name: 'reverse-ripple-animation',
|
||||
id: 'reverse-ripple',
|
||||
toPage: this
|
||||
}],
|
||||
'exit': [{
|
||||
name: 'fade-out-animation',
|
||||
node: this.$.container,
|
||||
timing: {
|
||||
delay: 150,
|
||||
duration: 0
|
||||
}
|
||||
}, {
|
||||
name: 'ripple-animation',
|
||||
id: 'ripple',
|
||||
fromPage: this
|
||||
}]
|
||||
};
|
||||
}
|
||||
},
|
||||
sharedElements: {
|
||||
value: function() {
|
||||
return {
|
||||
'ripple': this.$.btn,
|
||||
'reverse-ripple': this.$.btn
|
||||
};
|
||||
}
|
||||
}
|
||||
},
|
||||
_switch: function() {
|
||||
document.querySelector('#pages').select(1);
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue