Jelajahi Sumber

Feature Request: Send text instead of files

Robin Linus 9 tahun lalu
induk
melakukan
0e008a5f31

+ 22 - 9
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: {

+ 28 - 5
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">

+ 8 - 7
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];

+ 16 - 0
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>

+ 1 - 1
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);
                         }
                     });
 

+ 36 - 0
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>

File diff ditekan karena terlalu besar
+ 2 - 0
app/elements/text-sharing/linkify.html


+ 54 - 29
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>

+ 114 - 56
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>

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini