typing indicators work now

This commit is contained in:
or-else
2017-09-14 15:36:34 -07:00
parent e3d95eafe1
commit a6e59936e2
3 changed files with 34 additions and 12 deletions
-1
View File
@@ -18,7 +18,6 @@ Background pattern from http://subtlepatterns.com/, commercial and non-commercia
* Cannot send images or other media. * Cannot send images or other media.
* Cannot delete messages. * Cannot delete messages.
* No typing indicators.
* No indication of chat status (muted, blocked, etc.). * No indication of chat status (muted, blocked, etc.).
* Browser push notifications are missing. * Browser push notifications are missing.
* No encryption. * No encryption.
+18 -5
View File
@@ -628,6 +628,24 @@ table.permission-editor td.checkbox {
background-color: #C0C0C0; background-color: #C0C0C0;
} }
/* Typing indicator: animation of the online dot */
.online.typing {
animation: typing 1.5s infinite;
}
@keyframes typing {
0% { background-color: #40C040; }
25% { background-image: radial-gradient(#30D030 0%, #40C040 67%); }
33.3% { background-image: radial-gradient(#10EE10 0%, #40C040 50%); }
41.7% { background-image: radial-gradient(#00FF00 0%, #40C040 35%); }
50% { background-image: radial-gradient(#30D030 0%, #40C040 67%); }
58.3% { background-image: radial-gradient(#10EE10 0%, #40C040 50%); }
66.7% { background-image: radial-gradient(#00FF00 0%, #40C040 35%); }
75% { background-image: radial-gradient(#30D030 0%, #40C040 67%); }
83.3% { background-image: radial-gradient(#10EE10 0%, #40C040 50%); }
91.6% { background-image: radial-gradient(#00FF00 0%, #40C040 35%); }
}
.contact-box .checkmark.material-icons { .contact-box .checkmark.material-icons {
display: inline-block; display: inline-block;
width: 1.5rem; width: 1.5rem;
@@ -1474,11 +1492,6 @@ ul.tabbar li.active > a:after {
animation: spin 1.5s linear infinite; animation: spin 1.5s linear infinite;
} }
@-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
@keyframes spin { @keyframes spin {
0% { transform: rotate(0deg); } 0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); } 100% { transform: rotate(360deg); }
+16 -6
View File
@@ -36,7 +36,7 @@
var API_KEY = "AQEAAAABAAD_rAp4DJh05a1HAwFT3A6K"; var API_KEY = "AQEAAAABAAD_rAp4DJh05a1HAwFT3A6K";
// Minimum time between two keypress notifications, milliseconds. // Minimum time between two keypress notifications, milliseconds.
var KEYPRESS_DELAY = 5*1000; var KEYPRESS_DELAY = 3*1000;
// Delay before sending a {note} for reciving a message, milliseconds. // Delay before sending a {note} for reciving a message, milliseconds.
var RECEIVED_DELAY = 500; var RECEIVED_DELAY = 500;
@@ -2352,7 +2352,8 @@
topic: '', topic: '',
title: '', title: '',
avatar: null, avatar: null,
scrollPosition: 0 scrollPosition: 0,
typingIndicator: false
}; };
}, },
@@ -2500,9 +2501,17 @@
}, },
handleInfoReceipt: function(info) { handleInfoReceipt: function(info) {
switch (info.what) { switch (info.what) {
case "kp": case "kp": {
console.log("show typing notification"); clearTimeout(this.keyPressTimer);
var instance = this;
this.keyPressTimer = setTimeout(function() {
instance.setState({typingIndicator: false});
}, KEYPRESS_DELAY + 1000);
if (!this.state.typingIndicator) {
this.setState({typingIndicator: true});
}
break; break;
}
case "read": case "read":
case "recv": case "recv":
// Redraw due to changed recv/read status. // Redraw due to changed recv/read status.
@@ -2583,11 +2592,12 @@
if (cont.online) { if (cont.online) {
lastSeen = "online now"; lastSeen = "online now";
} else if (cont.seen) { } else if (cont.seen) {
lastSeen = "Last seen: " + shortDateFormat(cont.seen.when); lastSeen = "Last active: " + shortDateFormat(cont.seen.when);
// TODO(gene): also handle user agent in c.seen.ua // TODO(gene): also handle user agent in c.seen.ua
} }
} }
var avatar = this.state.avatar || true; var avatar = this.state.avatar || true;
var online = cont && cont.online ? "online" + (this.state.typingIndicator ? " typing" : "") : "offline";
component = ( component = (
<div id="topic-view" className={this.props.hideSelf ? 'nodisplay' : null}> <div id="topic-view" className={this.props.hideSelf ? 'nodisplay' : null}>
<div id="topic-caption-panel" className="caption-panel"> <div id="topic-caption-panel" className="caption-panel">
@@ -2600,7 +2610,7 @@
<div className="avatar-box"> <div className="avatar-box">
<LetterTile avatar={avatar} <LetterTile avatar={avatar}
topic={this.state.topic} title={this.state.title} /> topic={this.state.topic} title={this.state.title} />
<span className="online" /> <span className={online} />
</div> </div>
<div id="topic-title-group"> <div id="topic-title-group">
<div id="topic-title" className="panel-title">{this.state.title}</div> <div id="topic-title" className="panel-title">{this.state.title}</div>