commit 0e008a5f31985d251722f89c693aed878d04d30f
parent ce61dc7c60a9bb80c046bb2fa2cbfa7fc9d12bcd
Author: Robin Linus <robin_woll@capira.de>
Date: Sat, 2 Jan 2016 14:23:51 +0100
Feature Request: Send text instead of files
Diffstat:
9 files changed, 285 insertions(+), 107 deletions(-)
diff --git a/app/elements/buddy-finder/buddy-avatar.html b/app/elements/buddy-finder/buddy-avatar.html
@@ -1,14 +1,16 @@
<link rel="import" href="../../bower_components/paper-icon-button/paper-icon-button.html">
<link rel="import" href="../file-sharing/file-input-behavior.html">
+<link rel="import" href="../text-sharing/text-input-behavior.html">
<dom-module id="buddy-avatar">
<template>
<style>
:host {
display: block;
@apply(--layout-vertical);
- @apply(--layout-center);
+ @apply(--layout-center-center);
width: 120px;
- height: 152px;
+ height: 124px;
+ cursor: pointer;
}
paper-icon-button {
@@ -29,6 +31,8 @@
.paper-font-subhead {
text-align: center;
+ line-height: 22px;
+ margin-top: 2px;
}
.paper-font-body1 {
@@ -36,7 +40,7 @@
width: 100%;
font-size: 13px;
color: grey;
- margin-top: 2px;
+ line-height: 13px;
}
:host,
@@ -46,25 +50,34 @@
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
- margin-top: 4px;
}
-
+
:host([only1]) {
@apply(--layout-fit);
@apply(--layout-horizontal);
@apply(--layout-center-center);
cursor: pointer;
}
+
+ .container {
+ @apply(--layout-vertical);
+ @apply(--layout-center);
+ height: 112px;
+ padding-top: 16px;
+ display: block;
+ }
</style>
- <paper-icon-button icon="{{_displayIcon}}"></paper-icon-button>
- <div class="paper-font-subhead">{{_displayName}}</div>
- <div class="paper-font-body1">{{status}}</div>
+ <div class="container">
+ <paper-icon-button icon="{{_displayIcon}}"></paper-icon-button>
+ <div class="paper-font-subhead">{{_displayName}}</div>
+ <div class="paper-font-body1">{{status}}</div>
+ </div>
</template>
<script>
'use strict';
Polymer({
is: 'buddy-avatar',
- behaviors: [Chat.FileInputBehavior],
+ behaviors: [Chat.FileInputBehavior, Chat.TextInputBehavior],
properties: {
contact: Object,
_displayName: {
diff --git a/app/elements/buddy-finder/buddy-finder.html b/app/elements/buddy-finder/buddy-finder.html
@@ -28,10 +28,6 @@
@apply(--layout-wrap);
}
- .buddy {
- cursor: pointer;
- }
-
.explanation {
@apply(--paper-font-headline);
color: #4285f4;
@@ -60,10 +56,37 @@
}
}
+ @media all and (max-height: 440px) {
+ .buddies {
+ padding-top: 48px;
+ @apply(--layout-self-start);
+ }
+ }
+
+ .explanation2 {
+ display: none;
+ }
+
+ @media all and (min-height: 640px) {
+ .explanation2 {
+ display: block;
+ position: absolute;
+ top: 128px;
+ width: 296px;
+ margin-left: -148px;
+ left: 50%;
+ @apply(--paper-font-title);
+ color: #7baaf7;
+ text-align: center;
+ }
+ }
</style>
+ <div class="explanation2" hidden$="{{!buddies.0}}">
+ Tap to send File.<br>Long Press to send Text.
+ </div>
<div class="buddies">
<template is="dom-repeat" items="{{buddies}}">
- <buddy-avatar on-file-selected="_fileSelected" only$="{{!buddies.1}}" contact="{{item}}" class="buddy"></buddy-avatar>
+ <buddy-avatar on-file-selected="_fileSelected" only$="{{!buddies.1}}" contact="{{item}}"></buddy-avatar>
</template>
</div>
<div hidden$="{{buddies.0}}" class="explanation">
diff --git a/app/elements/file-sharing/file-button-behavior.html b/app/elements/file-sharing/file-button-behavior.html
@@ -23,13 +23,14 @@ Chat.FileButtonBehaviorImpl = {
var files = this.fileInput.files;
this.notifyFilesSelection(files);
}.bind(this);
- },
- listeners: {
- 'tap': '_openDialog'
- },
- _openDialog: function() {
- this.fileInput.value = null;
- this.fileInput.click();
+ this.addEventListener('click', function(e) {
+ var button = e.which || e.button;
+ if (button !== 1) {
+ return;
+ }
+ this.fileInput.value = null;
+ this.fileInput.click();
+ }.bind(this), false);
}
};
Chat.FileButtonBehavior = [Chat.FileButtonBehaviorImpl, Chat.FileSelectionBehavior];
diff --git a/app/elements/p2p-network/file-transfer-protocol.html b/app/elements/p2p-network/file-transfer-protocol.html
@@ -43,6 +43,9 @@ Chat.FileTransferProtocol = {
case 'buddies':
this._onBuddies(msg);
break;
+ case 'text':
+ this._onTextReceived(msg);
+ break;
}
},
sendFile: function(peerId, file) {
@@ -135,6 +138,19 @@ Chat.FileTransferProtocol = {
},
_onBuddies: function(msg) {
this.set('buddies', msg.buddies);
+ },
+ sendText: function(toPeer, text) {
+ console.log('FTP send text:', text, 'To:', toPeer);
+ this.connectToPeer(toPeer, function() {
+ this._sendSystemEvent(toPeer, {
+ type: 'text',
+ text: text
+ });
+ }.bind(this));
+
+ },
+ _onTextReceived: function(msg) {
+ this.fire('text-received', msg);
}
};
</script>
diff --git a/app/elements/p2p-network/p2p-network.html b/app/elements/p2p-network/p2p-network.html
@@ -108,7 +108,7 @@
s.on('error', function(err) {
console.log(err);
if (err.message.indexOf('Connection is not open') > -1) {
- console.err('Handle this error!!');
+ console.error('Handle this error!!', err);
}
});
diff --git a/app/elements/text-sharing/clipboard-behavior.html b/app/elements/text-sharing/clipboard-behavior.html
@@ -0,0 +1,36 @@
+<script>
+'use strict';
+(function(document) {
+ var copyTextarea = document.createElement('textarea');
+ copyTextarea.setAttribute('id', 'clipboard-textarea');
+ var style = copyTextarea.style;
+ style.position = 'absolute';
+ style.top = '-10000px';
+ document.body.appendChild(copyTextarea);
+
+ window.Chat.ClipboardBehavior = {
+ copyToClipboard: function(content) {
+ copyTextarea.value = content;
+ var range = document.createRange();
+ range.selectNode(copyTextarea);
+ window.getSelection().addRange(range);
+
+ try {
+ // Now that we've selected the anchor text, execute the copy command
+ var successful = document.execCommand('copy');
+ if (successful) {
+ app.displayToast('Copied text to clipboard. Paste it where you want!');
+ } else {
+ console.log('failed to copy to clipboard', successful);
+ }
+ } catch (err) {
+ console.log('Oops, unable to copy', err);
+ }
+
+ // Remove the selections - NOTE: Should use
+ // removeRange(range) when it is supported
+ window.getSelection().removeAllRanges();
+ }
+ };
+}(document));
+</script>
diff --git a/app/elements/text-sharing/linkify.html b/app/elements/text-sharing/linkify.html
@@ -0,0 +1,5 @@
+<script>
+'use strict';
+!function(){"use strict";function t(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);t.prototype=Object.create(n&&n.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(t,n):t.__proto__=n)}function n(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")}function e(t,n,e,o){for(var r=0,i=t.length,a=[],s=void 0;i>r&&(s=n.next(t[r]));)n=s,r++;if(r>=i)return[];for(;i-1>r;)s=new h(o),a.push(s),n.on(t[r],s),n=s,r++;return s=new h(e),a.push(s),n.on(t[i-1],s),a}function o(t,n){if("function"!=typeof n&&null!==n)throw new TypeError("Super expression must either be null or a function, not "+typeof n);t.prototype=Object.create(n&&n.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),n&&(Object.setPrototypeOf?Object.setPrototypeOf(t,n):t.__proto__=n)}function r(t,n){if(!(t instanceof n))throw new TypeError("Cannot call a class as a function")}function i(t){return t instanceof d||t instanceof P}function a(t){return t}function s(t,n){return"url"===n?"_blank":null}function u(t){return t=t||{},{attributes:t.linkAttributes||null,defaultProtocol:t.defaultProtocol||"http",events:t.events||null,format:t.format||a,formatHref:t.formatHref||a,newLine:t.newLine||!1,nl2br:!!t.newLine||t.nl2br||!1,tagName:t.tagName||"a",target:t.target||s,linkClass:t.linkClass||"linkified"}}function c(t){for(var n=arguments.length,e=Array(n>1?n-1:0),o=1;n>o;o++)e[o-1]=arguments[o];return"function"==typeof t?t.apply(void 0,e):t}function l(t){if(t&&t.__esModule)return t;var n={};if(null!=t)for(var e in t)Object.prototype.hasOwnProperty.call(t,e)&&(n[e]=t[e]);return n["default"]=t,n}var p={__esModule:!0},f=function(){function t(e){n(this,t),this.j=[],this.T=e||null}return t.prototype.on=function(t,n){if(t instanceof Array)for(var e=0;e<t.length;e++)this.j.push([t[e],n]);else this.j.push([t,n])},t.prototype.next=function(t){for(var n=0;n<this.j.length;n++){var e=this.j[n],o=e[1];if(this.test(t,e[0]))return o}return!1},t.prototype.accepts=function(){return!!this.T},t.prototype.test=function(t,n){return t===n},t.prototype.emit=function(){return this.T},t}(),h=function(e){function o(){n(this,o),e.apply(this,arguments)}return t(o,e),o.prototype.test=function(t,n){return t===n||n instanceof RegExp&&n.test(t)},o}(f),g=function(e){function o(){n(this,o),e.apply(this,arguments)}return t(o,e),o.prototype.test=function(t,n){return t instanceof n},o}(f);p.CharacterState=h,p.TokenState=g,p.stateify=e;var m={__esModule:!0},y=function(){function t(n){r(this,t),this.v=n}return t.prototype.toString=function(){return this.v+""},t}(),d=function(t){function n(){r(this,n),t.apply(this,arguments)}return o(n,t),n}(y),b=function(t){function n(){r(this,n),t.call(this,"@")}return o(n,t),n}(y),v=function(t){function n(){r(this,n),t.call(this,":")}return o(n,t),n}(y),x=function(t){function n(){r(this,n),t.call(this,".")}return o(n,t),n}(y),k=function(t){function n(){r(this,n),t.apply(this,arguments)}return o(n,t),n}(y),w=function(t){function n(){r(this,n),t.apply(this,arguments)}return o(n,t),n}(y),O=function(t){function n(){r(this,n),t.call(this,"\n")}return o(n,t),n}(y),E=function(t){function n(){r(this,n),t.apply(this,arguments)}return o(n,t),n}(y),L=function(t){function n(){r(this,n),t.call(this,"+")}return o(n,t),n}(y),S=function(t){function n(){r(this,n),t.call(this,"#")}return o(n,t),n}(y),A=function(t){function n(){r(this,n),t.apply(this,arguments)}return o(n,t),n}(y),C=function(t){function n(){r(this,n),t.call(this,"?")}return o(n,t),n}(y),T=function(t){function n(){r(this,n),t.call(this,"/")}return o(n,t),n}(y),N=function(t){function n(){r(this,n),t.apply(this,arguments)}return o(n,t),n}(y),P=function(t){function n(){r(this,n),t.apply(this,arguments)}return o(n,t),n}(y),j=function(t){function n(){r(this,n),t.apply(this,arguments)}return o(n,t),n}(y),z=function(t){function n(){r(this,n),t.call(this,"{")}return o(n,t),n}(y),R=function(t){function n(){r(this,n),t.call(this,"[")}return o(n,t),n}(y),_=function(t){function n(){r(this,n),t.call(this,"(")}return o(n,t),n}(y),U=function(t){function n(){r(this,n),t.call(this,"}")}return o(n,t),n}(y),M=function(t){function n(){r(this,n),t.call(this,"]")}return o(n,t),n}(y),B=function(t){function n(){r(this,n),t.call(this,")")}return o(n,t),n}(y),D={Base:y,DOMAIN:d,AT:b,COLON:v,DOT:x,PUNCTUATION:k,LOCALHOST:w,NL:O,NUM:E,PLUS:L,POUND:S,QUERY:C,PROTOCOL:A,SLASH:T,SYM:N,TLD:P,WS:j,OPENBRACE:z,OPENBRACKET:R,OPENPAREN:_,CLOSEBRACE:U,CLOSEBRACKET:M,CLOSEPAREN:B},H=function(){function t(n){r(this,t),this.v=n,this.type="token",this.isLink=!1}return t.prototype.toString=function(){for(var t=[],n=0;n<this.v.length;n++)t.push(this.v[n].toString());return t.join("")},t.prototype.toHref=function(){return this.toString()},t.prototype.toObject=function(){return{type:this.type,value:this.toString(),href:this.toHref(0>=arguments.length||void 0===arguments[0]?"http":arguments[0])}},t}(),q=function(t){function n(e){r(this,n),t.call(this,e),this.type="email",this.isLink=!0}return o(n,t),n.prototype.toHref=function(){return"mailto:"+this.toString()},n}(H),I=function(t){function n(e){r(this,n),t.call(this,e),this.type="text"}return o(n,t),n}(H),K=function(t){function n(e){r(this,n),t.call(this,e),this.type="nl"}return o(n,t),n}(H),Y=function(t){function n(e){r(this,n),t.call(this,e),this.type="url",this.isLink=!0}return o(n,t),n.prototype.toHref=function(){for(var t=0>=arguments.length||void 0===arguments[0]?"http":arguments[0],n=!1,e=!1,o=this.v,r=[],a=0;o[a]instanceof A;)n=!0,r.push(o[a].toString().toLowerCase()),a++;for(;o[a]instanceof T;)e=!0,r.push(o[a].toString()),a++;for(;i(o[a]);)r.push(o[a].toString().toLowerCase()),a++;for(;a<o.length;a++)r.push(o[a].toString());return r=r.join(""),n||e||(r=t+"://"+r),r},n.prototype.hasProtocol=function(){return this.v[0]instanceof A},n}(H),Q={Base:H,EMAIL:q,NL:K,TEXT:I,URL:Y};m.text=D,m.multi=Q;var W={__esModule:!0},X=m,Z=p,F=function(t){return new Z.TokenState(t)},G=X.text.DOMAIN,J=X.text.AT,V=X.text.COLON,$=X.text.DOT,tt=X.text.PUNCTUATION,nt=X.text.LOCALHOST,et=X.text.NL,ot=X.text.NUM,rt=X.text.PLUS,it=X.text.POUND,at=X.text.PROTOCOL,st=X.text.QUERY,ut=X.text.SLASH,ct=X.text.SYM,lt=X.text.TLD,pt=X.text.OPENBRACE,ft=X.text.OPENBRACKET,ht=X.text.OPENPAREN,gt=X.text.CLOSEBRACE,mt=X.text.CLOSEBRACKET,yt=X.text.CLOSEPAREN,dt=X.multi.EMAIL,bt=X.multi.NL,vt=X.multi.TEXT,xt=X.multi.URL,kt=F(),wt=F(),Ot=F(),Et=F(),Lt=F(),St=F(),At=F(xt),Ct=F(),Tt=F(xt),Nt=F(),Pt=F(),jt=F(xt),zt=F(),Rt=F(xt),_t=F(xt),Ut=F(),Mt=F(),Bt=F(),Dt=F(),Ht=F(xt),qt=F(xt),It=F(xt),Kt=F(),Yt=F(),Qt=F(),Wt=F(),Xt=F(),Zt=F(dt),Ft=F(),Gt=F(dt),Jt=F(),Vt=F(),$t=F(),tn=F(bt);kt.on(et,tn),kt.on(at,wt),kt.on(ut,Ot),wt.on(ut,Ot),Ot.on(ut,Et),kt.on(lt,Lt),kt.on(G,Lt),kt.on(nt,At),kt.on(ot,Lt),Et.on(lt,Nt),Et.on(G,Nt),Et.on(ot,Nt),Et.on(nt,jt),Lt.on($,St),Nt.on($,Pt),Wt.on($,Xt),St.on(lt,At),St.on(G,Lt),St.on(ot,Lt),St.on(nt,Lt),Pt.on(lt,jt),Pt.on(G,Nt),Pt.on(ot,Nt),Pt.on(nt,Nt),Xt.on(lt,Zt),Xt.on(G,Wt),Xt.on(ot,Wt),Xt.on(nt,Wt),At.on($,St),jt.on($,Pt),Zt.on($,Xt),At.on(V,Ct),At.on(ut,_t),Ct.on(ot,Tt),Tt.on(ut,_t),jt.on(V,zt),jt.on(ut,_t),zt.on(ot,Rt),Rt.on(ut,_t),Zt.on(V,Ft),Ft.on(ot,Gt);var nn=[G,J,nt,ot,rt,it,at,ut,lt],en=[V,$,st,tt,gt,mt,yt,pt,ft,ht,ct];_t.on(pt,Mt),_t.on(ft,Bt),_t.on(ht,Dt),Ut.on(pt,Mt),Ut.on(ft,Bt),Ut.on(ht,Dt),Mt.on(gt,_t),Bt.on(mt,_t),Dt.on(yt,_t),Ht.on(gt,_t),qt.on(mt,_t),It.on(yt,_t),Kt.on(gt,_t),Yt.on(mt,_t),Qt.on(yt,_t),Mt.on(nn,Ht),Bt.on(nn,qt),Dt.on(nn,It),Mt.on(en,Kt),Bt.on(en,Yt),Dt.on(en,Qt),Ht.on(nn,Ht),qt.on(nn,qt),It.on(nn,It),Ht.on(en,Ht),qt.on(en,qt),It.on(en,It),Kt.on(nn,Ht),Yt.on(nn,qt),Qt.on(nn,It),Kt.on(en,Kt),Yt.on(en,Yt),Qt.on(en,Qt),_t.on(nn,_t),Ut.on(nn,_t),_t.on(en,Ut),Ut.on(en,Ut);var on=[G,ot,rt,it,st,ct,lt];Lt.on(on,Jt),Lt.on(J,Vt),St.on(on,Jt),At.on(on,Jt),At.on(J,Vt),Jt.on(on,Jt),Jt.on(J,Vt),Jt.on($,$t),$t.on(on,Jt),Vt.on(lt,Wt),Vt.on(G,Wt),Vt.on(nt,Zt);var rn=function(t){for(var n=t.length,e=0,o=[],r=[];n>e;){for(var i=kt,a=null,s=null,u=0,c=null,l=-1;n>e&&!(a=i.next(t[e]));)r.push(t[e++]);for(;n>e&&(s=a||i.next(t[e]));)a=null,i=s,i.accepts()?(l=0,c=i):l>=0&&l++,e++,u++;if(0>l)for(u=e-u;e>u;u++)r.push(t[u]);else 0<r.length&&(o.push(new vt(r)),r=[]),e-=l,u-=l,i=c.emit(),o.push(new i(t.slice(e-u,e)))}return 0<r.length&&o.push(new vt(r)),o},an=X.multi,sn=kt;W.State=Z.TokenState,W.TOKENS=an,W.run=rn,W.start=sn;var un={__esModule:!0},cn=m,ln=p,pn="abogado ac academy accountants active actor ad adult ae aero af ag agency ai airforce al allfinanz alsace am an android ao aq aquarelle ar archi army arpa as asia associates at attorney au auction audio autos aw ax axa az ba band bar bargains bayern bb bd be beer berlin best bf bg bh bi bid bike bio biz bj black blackfriday bloomberg blue bm bmw bn bnpparibas bo boo boutique br brussels bs bt budapest build builders business buzz bv bw by bz bzh ca cab cal camera camp cancerresearch capetown capital caravan cards care career careers casa cash cat catering cc cd center ceo cern cf cg ch channel cheap christmas chrome church ci citic city ck cl claims cleaning click clinic clothing club cm cn co coach codes coffee college cologne com community company computer condos construction consulting contractors cooking cool coop country cr credit creditcard cricket crs cruises cu cuisinella cv cw cx cy cymru cz dad dance dating day de deals degree delivery democrat dental dentist desi diamonds diet digital direct directory discount dj dk dm dnp do domains durban dvag dz eat ec edu education ee eg email emerck energy engineer engineering enterprises equipment er es esq estate et eu eurovision eus events everbank exchange expert exposed fail farm fashion feedback fi finance financial firmdale fish fishing fitness fj fk flights florist flsmidth fly fm fo foo forsale foundation fr frl frogans fund furniture futbol ga gal gallery gb gbiz gd ge gent gf gg gh gi gift gifts gives gl glass gle global globo gm gmail gmo gmx gn google gop gov gp gq gr graphics gratis green gripe gs gt gu guide guitars guru gw gy hamburg haus healthcare help here hiphop hiv hk hm hn holdings holiday homes horse host hosting house how hr ht hu ibm id ie il im immo immobilien in industries info ing ink institute insure int international investments io iq ir irish is it je jetzt jm jo jobs joburg jp juegos kaufen ke kg kh ki kim kitchen kiwi km kn koeln kp kr krd kred kw ky kz la lacaixa land latrobe lawyer lb lc lds lease legal lgbt li life lighting limited limo link lk loans london lotto lr ls lt ltda lu luxe luxury lv ly ma madrid maison management mango market marketing mc md me media meet melbourne meme memorial menu mg mh miami mil mini mk ml mm mn mo mobi moda moe monash money mormon mortgage moscow motorcycles mov mp mq mr ms mt mu museum mv mw mx my mz na nagoya name navy nc ne net network neustar new nexus nf ng ngo nhk ni ninja nl no np nr nra nrw nu nyc nz okinawa om ong onl ooo org organic otsuka ovh pa paris partners parts party pe pf pg ph pharmacy photo photography photos physio pics pictures pink pizza pk pl place plumbing pm pn pohl poker porn post pr praxi press pro prod productions prof properties property ps pt pub pw py qa qpon quebec re realtor recipes red rehab reise reisen reit ren rentals repair report republican rest restaurant reviews rich rio rip ro rocks rodeo rs rsvp ru ruhr rw ryukyu sa saarland sarl sb sc sca scb schmidt schule science scot sd se services sexy sg sh shiksha shoes si singles sj sk sl sm sn so social software sohu solar solutions soy space spiegel sr st su supplies supply support surf surgery suzuki sv sx sy sydney systems sz taipei tatar tattoo tax tc td technology tel tf tg th tienda tips tirol tj tk tl tm tn to today tokyo tools top town toys tp tr trade training travel trust tt tui tv tw tz ua ug uk university uno uol us uy uz va vacations vc ve vegas ventures versicherung vet vg vi viajes villas vision vlaanderen vn vodka vote voting voto voyage vu wales wang watch webcam website wed wedding wf whoswho wien wiki williamhill wme work works world ws wtc wtf xxx xyz yachts yandex ye yoga yokohama youtube yt za zip zm zone zw".split(" "),fn=/[0-9]/,hn=/[a-z0-9]/,gn=":",mn=[],yn=function(t){return new ln.CharacterState(t)},dn=cn.text.DOMAIN,bn=cn.text.LOCALHOST,vn=cn.text.NUM,xn=cn.text.PROTOCOL,kn=cn.text.TLD,wn=cn.text.WS,On=yn(),En=yn(vn),Ln=yn(dn),Sn=yn(),An=yn(wn);On.on("@",yn(cn.text.AT)),On.on(".",yn(cn.text.DOT)),On.on("+",yn(cn.text.PLUS)),On.on("#",yn(cn.text.POUND)),On.on("?",yn(cn.text.QUERY)),On.on("/",yn(cn.text.SLASH)),On.on(gn,yn(cn.text.COLON)),On.on("{",yn(cn.text.OPENBRACE)),On.on("[",yn(cn.text.OPENBRACKET)),On.on("(",yn(cn.text.OPENPAREN)),On.on("}",yn(cn.text.CLOSEBRACE)),On.on("]",yn(cn.text.CLOSEBRACKET)),On.on(")",yn(cn.text.CLOSEPAREN)),On.on(/[,;!]/,yn(cn.text.PUNCTUATION)),On.on(/\n/,yn(cn.text.NL)),On.on(/\s/,An),An.on(/[^\S\n]/,An);for(var Cn=0;Cn<pn.length;Cn++){var Tn=ln.stateify(pn[Cn],On,kn,dn);mn.push.apply(mn,Tn)}var Nn=ln.stateify("file",On,dn,dn),Pn=ln.stateify("ftp",On,dn,dn),jn=ln.stateify("http",On,dn,dn);mn.push.apply(mn,Nn),mn.push.apply(mn,Pn),mn.push.apply(mn,jn);var zn=Nn.pop(),Rn=Pn.pop(),_n=jn.pop(),Un=yn(dn),Mn=yn(xn);Rn.on("s",Un),_n.on("s",Un),mn.push(Un),zn.on(gn,Mn),Rn.on(gn,Mn),_n.on(gn,Mn),Un.on(gn,Mn);var Bn=ln.stateify("localhost",On,bn,dn);for(mn.push.apply(mn,Bn),On.on(fn,En),En.on("-",Sn),En.on(fn,En),En.on(hn,Ln),Ln.on("-",Sn),Ln.on(hn,Ln),Cn=0;Cn<mn.length;Cn++)mn[Cn].on("-",Sn),mn[Cn].on(hn,Ln);Sn.on("-",Sn),Sn.on(fn,Ln),Sn.on(hn,Ln),On.on(/./,yn(cn.text.SYM));var Dn=function(t){for(var n=t.replace(/[A-Z]/g,function(t){return t.toLowerCase()}),e=t.length,o=[],r=0;e>r;){for(var i=On,a=null,s=0,u=null,c=-1;e>r&&(a=i.next(n[r]));)i=a,i.accepts()?(c=0,u=i):c>=0&&c++,s++,r++;0>c||(r-=c,s-=c,i=u.emit(),o.push(new i(t.substr(r-s,s))))}return o},Hn=On;un.State=ln.CharacterState,un.TOKENS=cn.text,un.run=Dn,un.start=Hn;var qn={__esModule:!0};qn.normalize=u,qn.resolve=c;var In={__esModule:!0},Kn=qn,Yn=l(Kn),Qn=un,Wn=l(Qn),Xn=W,Zn=l(Xn);Array.isArray||(Array.isArray=function(t){return"[object Array]"===Object.prototype.toString.call(t)});var Fn=function(t){return Zn.run(Wn.run(t))},Gn=function(t){for(var n=1>=arguments.length||void 0===arguments[1]?null:arguments[1],e=Fn(t),o=[],r=0;r<e.length;r++)!e[r].isLink||n&&e[r].type!==n||o.push(e[r].toObject());return o},Jn=function(t){var n=1>=arguments.length||void 0===arguments[1]?null:arguments[1],e=Fn(t);return 1===e.length&&e[0].isLink&&(!n||e[0].type===n)};In.find=Gn,In.options=Yn,In.parser=Zn,In.scanner=Wn,In.test=Jn,In.tokenize=Fn,window.linkify=In}();
+!function(e){"use strict";function t(e,t,n){var r=n[n.length-1];e.replaceChild(r,t);for(var o=n.length-2;o>=0;o--)e.insertBefore(n[o],r),r=n[o]}function n(e,t,n){for(var r=[],o=0;o<e.length;o++){var i=e[o];if(i.isLink){var l=i.toHref(t.defaultProtocol),s=a.resolve(t.format,i.toString(),i.type),f=a.resolve(t.formatHref,l,i.type),u=a.resolve(t.attributes,l,i.type),d=a.resolve(t.tagName,l,i.type),v=a.resolve(t.linkClass,l,i.type),c=a.resolve(t.target,l,i.type),m=a.resolve(t.events,l,i.type),p=n.createElement(d);if(p.setAttribute("href",f),p.setAttribute("class",v),c&&p.setAttribute("target",c),u)for(var h in u)p.setAttribute(h,u[h]);if(m)for(var g in m)p.addEventListener?p.addEventListener(g,m[g]):p.attachEvent&&p.attachEvent("on"+g,m[g]);p.appendChild(n.createTextNode(s)),r.push(p)}else"nl"===i.type&&t.nl2br?r.push(n.createElement("br")):r.push(n.createTextNode(i.toString()))}return r}function r(e,o,a){if(!e||"object"!=typeof e||e.nodeType!==l)throw new Error("Cannot linkify "+e+" - Invalid DOM Node type");if("A"===e.tagName)return e;for(var f=e.firstChild;f;){switch(f.nodeType){case l:r(f,o,a);break;case s:var u=f.nodeValue,d=i(u),v=n(d,o,a);t(e,f,v),f=v[v.length-1]}f=f.nextSibling}return e}function o(e,t){var n=arguments.length<=2||void 0===arguments[2]?null:arguments[2];try{n=n||window&&window.document||global&&global.document}catch(o){}if(!n)throw new Error("Cannot find document implementation. If you are in a non-browser environment like Node.js, pass the document implementation as the third argument to linkifyElement.");return t=a.normalize(t),r(e,t,n)}var i=e.tokenize,a=e.options,l=1,s=3;o.helper=r,o.normalize=a.normalize,window.linkifyElement=o}(window.linkify);
+</script>
+\ No newline at end of file
diff --git a/app/elements/text-sharing/text-input-behavior.html b/app/elements/text-sharing/text-input-behavior.html
@@ -1,34 +1,59 @@
+<link rel="import" href="text-input-dialog.html">
<script>
'use strict';
window.Chat = window.Chat || {};
-Chat.TextInputBehavior = {
- get textInput() {
- var textInput = Polymer.dom(this).querySelector('.textInput');
- if (!textInput) {
- textInput = document.createElement('input');
- textInput.type = 'file';
- textInput.multiple = 'true';
- textInput.className = 'textInput';
- textInput.style.position = 'fixed';
- textInput.style.top = '-10000px';
- textInput.style.left = '-10000px';
- textInput.style.opacity = 0;
- Polymer.dom(this).appendChild(textInput);
+(function() {
+ var textInput = Polymer.Base.create('text-input-dialog');
+ textInput.className = 'textInput';
+ document.body.appendChild(textInput);
+ Chat.TextInputBehavior = {
+ properties: {
+ contact: Object,
+ },
+ get textInput() {
+ var textInput = Polymer.dom(document).querySelector('.textInput');
+ return textInput;
+ },
+ openTextDialog: function() {
+ this.textInput.open(this.contact);
+ },
+
+ listeners: {
+ 'contextmenu': '_handleContextMenu',
+ 'down': '_handleDown',
+ 'up': '_handleUp',
+ },
+ _handleContextMenu: function(ev) {
+ ev.preventDefault();
+ ev.stopPropagation();
+ ev.cancelBubble = true;
+ this.cancelAsync(this.pressTimer);
+ this.openTextDialog();
+ return false;
+ },
+ _handleUp: function(e) {
+ this.cancelAsync(this.pressTimer);
+ },
+ _handleDown: function(ev) {
+ this.pressTimer = this.async(function() {
+ this.openTextDialog();
+ ev.preventDefault();
+ ev.stopPropagation();
+ ev.cancelBubble = true;
+ return false;
+ }, 1100);
+ },
+
+ attached: function() {
+ // this.addEventListener('mousedown', function(e) {
+ // clearTimeout(this.pressTimer);
+ // }.bind(this), false);
+ // this.addEventListener('mousup', function(e) {
+ // this.pressTimer = window.setTimeout(function() {
+ // this.openTextDialog();
+ // }, 1500);
+ // }.bind(this), false);
}
- return textInput;
- },
- attached: function() {
- this.textInput.onchange = function() {
- var files = this.textInput.files;
- this.notifyFilesSelection(files);
- }.bind(this);
- },
- listeners: {
- 'tap': '_openDialog'
- },
- _openDialog: function() {
- this.textInput.value = null;
- this.textInput.click();
- }
-};
+ };
+}());
</script>
diff --git a/app/elements/text-sharing/text-input-dialog.html b/app/elements/text-sharing/text-input-dialog.html
@@ -4,7 +4,10 @@
<link rel="import" href="../../bower_components/neon-animation/animations/fade-out-animation.html">
<link rel="import" href="../../bower_components/iron-pages/iron-pages.html">
<link rel="import" href="../../bower_components/paper-spinner/paper-spinner.html">
-<link rel="import" href="../../bower_components/paper-spinner/paper-textarea.html">
+<link rel="import" href="../../bower_components/paper-input/paper-textarea.html">
+<link rel="import" href="linkify.html">
+<link rel="import" href="clipboard-behavior.html">
+<link rel="import" href="../sound-notification/sound-notification-behavior.html">
<dom-module id="text-input-dialog">
<template>
<style>
@@ -12,92 +15,147 @@
display: block;
}
- #dialog,
- #download {
- width: 300px;
+ #sendDialog,
+ #receiveDialog {
+ width: 324px;
z-index: 101;
+ max-height: 320px;
+ overflow: hidden;
+ margin: 16px;
}
- .filename {
+ @media all and (max-height: 600px) {
+ #sendDialog {
+ padding-top: 24px;
+ top:0px !important;
+ }
+ }
+
+ #receivedText {
word-break: break-all;
word-break: break-word;
}
-
+
paper-textarea {
- height: 200px;
+ max-height: 200px;
+ width: calc(100% - 48px);
+ overflow-x: hidden;
+ overflow-y: auto;
+ }
+
+ #receivedText {
+ max-height: 200px;
+ overflow: hidden;
+ width: calc(100% - 48px);
+ text-overflow: ellipsis;
+ -webkit-line-clamp: 9;
+ clamp: 9;
}
</style>
- <paper-dialog id="dialog" entry-animation="scale-up-animation" exit-animation="fade-out-animation" with-backdrop modal>
+ <paper-dialog id="sendDialog" entry-animation="scale-up-animation" exit-animation="fade-out-animation" with-backdrop modal>
<h2>Send Text</h2>
- <paper-textarea label="Enter Text"></paper-textarea>
+ <paper-textarea id="textInput" label="Enter Text" value="{{textToSend}}" autofocus></paper-textarea>
<div class="buttons">
- <paper-button dialog-dismiss on-tap="_decline">Discard</paper-button>
- <paper-button dialog-confirm on-tap="_accept" autofocus>Send</paper-button>
+ <paper-button dialog-dismiss>Discard</paper-button>
+ <paper-button dialog-dismiss on-tap="_send">Send</paper-button>
</div>
</paper-dialog>
- <paper-dialog id="download" entry-animation="scale-up-animation" exit-animation="fade-out-animation" with-backdrop modal>
+ <paper-dialog id="receiveDialog" entry-animation="scale-up-animation" exit-animation="fade-out-animation" with-backdrop modal>
<h2>Text Received</h2>
- <p>Open File or Right Click and "Save as"...</p>
+ <div>
+ <div id="receivedText">
+ </div>
+ </div>
<div class="buttons">
<paper-button dialog-dismiss>Discard</paper-button>
- <a href="{{dataUri}}" target="_blank">
- <paper-button dialog-confirm autofocus>Open File</paper-button>
+ <a href="tel:{{tel}}" hidden$="{{!tel}}">
+ <paper-button dialog-dismiss>Call</paper-button>
</a>
+ <paper-button on-tap="_copy" autofocus>Copy</paper-button>
</div>
</paper-dialog>
</template>
<script>
'use strict';
(function() {
+ /*
+ *
+ * /^\+?[0-9x]*$/ is the first usuful Text sent via Snapdrop 2015/1/2 5:30
+ *
+ */
+ var phoneNumbers = /^\+?[0-9x/ ]*$/;
Polymer({
is: 'text-input-dialog',
- open: function() {
- this.$.dialog.open();
+ behaviors: [Chat.ClipboardBehavior,Chat.SoundNotificationBehavior],
+ properties: {
+ textToSend: {
+ type: String
+ },
+ receivedText: {
+ type: String
+ },
+ contact: {
+ type: Object
+ },
+ tel: {
+ computed: '_isPhoneNumber(receivedText)',
+ value: false
+ }
},
- attached: function() {
- // this.async(function() {
- // app.conn.addEventListener('file-offer', function(e) {
- // this.file = e.detail;
- // this.$.dialog.open();
- // }.bind(this), false);
- // app.conn.addEventListener('file-received', function(e) {
- // this._fileReceived(e.detail);
- // }.bind(this), false);
- // app.conn.addEventListener('file-declined', function(e) {
- // app.displayToast('User declined file ' + e.detail.name);
- // }.bind(this), false);
- // app.conn.addEventListener('upload-complete', function(e) {
- // app.displayToast('User received file ' + e.detail.name);
- // }.bind(this), false);
- // app.conn.addEventListener('upload-error', function(e) {
- // app.displayToast('The other device did not respond. Please try again.');
- // }.bind(this), false);
- // }, 200);
+ open: function(contact) {
+ this.contact = contact;
+ this.$.sendDialog.open();
},
- _fileReceived: function(file) {
- this.downloadURI(file);
+ attached: function() {
+ this.async(function() {
+ app.conn.addEventListener('text-received', function(e) {
+ var receivedText = e.detail.text;
+ this.receivedText = receivedText;
+ this.$.receivedText.textContent = receivedText;
+ window.linkifyElement(this.$.receivedText, {}, document);
+ this.$.receiveDialog.open();
+ this.playSound();
+ }.bind(this), false);
+ }, 200);
+
+ this.$.textInput.addEventListener('keypress', function(e) {
+ if (e.which === 13 || e.charCode === 13) {
+ var key;
+ var isShift;
+ if (window.event) {
+ key = window.event.keyCode;
+ isShift = !!window.event.shiftKey; // typecast to boolean
+ } else {
+ key = e.which;
+ isShift = !!e.shiftKey;
+ }
+ if (!isShift) {
+ e.preventDefault();
+ e.stopPropagation();
+ this._send();
+ }
+ }
+ }.bind(this), false);
},
- _decline: function() {
- app.conn.decline(this.file);
+ _send: function() {
+ this.$.sendDialog.close();
+ app.conn.sendText(this.contact.peerId, this.textToSend);
},
- _accept: function() {
- app.conn.accept(this.file);
+ _copy: function() {
+ this.copyToClipboard(this.receivedText);
+
+ this.$.receiveDialog.close();
+ console.log('text copied', this.receivedText);
},
- downloadURI: function(file) {
- var link = document.createElement('a');
- var uri = (window.URL || window.webkitURL).createObjectURL(file.blob);
- if (typeof link.download !== 'undefined') {
- //download attribute is supported
- link.href = uri;
- link.download = file.name || 'blank';
- document.body.appendChild(link);
- link.click();
- document.body.removeChild(link);
- } else {
- this.dataUri = uri;
- this.$.download.open();
+ _isPhoneNumber: function(text) {
+ if (!text || text.length < 5 || text.length > 100) {
+ return false;
}
- }
+ if (phoneNumbers.test(text)) {
+ return text;
+ }
+
+ },
});
}());
</script>