typing indicators work now
This commit is contained in:
@@ -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
@@ -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
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user