updated search, better typing indicator

This commit is contained in:
or-else
2018-05-18 14:12:50 -07:00
parent e77513d44b
commit f5af1ff193
2 changed files with 42 additions and 31 deletions
+15 -12
View File
@@ -547,6 +547,14 @@ table.permission-editor td.checkbox {
padding-left: 0.5rem; padding-left: 0.5rem;
} }
/* Input with a search icon on the left */
input.search {
text-indent: 1.4rem;
}
i.search {
position: absolute;
left: .6rem;
}
/* Area which displays an error message */ /* Area which displays an error message */
.alert-box { .alert-box {
@@ -703,20 +711,15 @@ table.permission-editor td.checkbox {
/* Typing indicator: animation of the online dot */ /* Typing indicator: animation of the online dot */
.online.typing { .online.typing {
animation: typing 1.5s infinite; animation: typing 0.5s infinite;
} }
@keyframes typing { @keyframes typing {
0% { background-color: #40C040; } 0%, 100% {
25% { background-image: radial-gradient(#30D030 0%, #40C040 67%); } transform: translateX(0);
33.3% { background-image: radial-gradient(#10EE10 0%, #40C040 50%); } }
41.7% { background-image: radial-gradient(#00FF00 0%, #40C040 35%); } 50% {
50% { background-image: radial-gradient(#30D030 0%, #40C040 67%); } transform: translateX(-0.3rem);
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 {
+27 -19
View File
@@ -47,6 +47,9 @@
// Sound to play on message received. // Sound to play on message received.
var POP_SOUND = new Audio('audio/msg.mp3'); var POP_SOUND = new Audio('audio/msg.mp3');
// Unicode symbol used to clear objects
var DEL_CHAR = "\u2421";
// API key. Use https://github.com/tinode/chat/tree/master/keygen to generate your own // API key. Use https://github.com/tinode/chat/tree/master/keygen to generate your own
var API_KEY = "AQEAAAABAAD_rAp4DJh05a1HAwFT3A6K"; var API_KEY = "AQEAAAABAAD_rAp4DJh05a1HAwFT3A6K";
@@ -2390,11 +2393,15 @@
NewTopicView.SearchContacts = React.createClass({ NewTopicView.SearchContacts = React.createClass({
getInitialState: function() { getInitialState: function() {
return { return {
edited: false,
search: this.props.searchQuery search: this.props.searchQuery
}; };
}, },
componentWillReceiveProps: function(nextProps) { componentWillUnmount: function() {
this.setState({search: nextProps.searchQuery}); if (this.state.search) {
this.setState({search: ''});
this.props.onSearchContacts(DEL_CHAR);
}
}, },
handleSearchChange: function(e) { handleSearchChange: function(e) {
this.setState({search: e.target.value}); this.setState({search: e.target.value});
@@ -2403,9 +2410,16 @@
e.preventDefault(); e.preventDefault();
var query = this.state.search.trim(); var query = this.state.search.trim();
if (query.length > 0) { if (query.length > 0) {
this.setState({edited: true});
this.props.onSearchContacts(query); this.props.onSearchContacts(query);
} }
}, },
handleClear: function() {
if (this.state.edited || this.state.search) {
this.props.onSearchContacts(DEL_CHAR);
}
this.setState({search: '', edited: false});
},
handleKeyPress: function(e) { handleKeyPress: function(e) {
if (e.key === 'Enter') { if (e.key === 'Enter') {
this.handleSearch(e); this.handleSearch(e);
@@ -2415,11 +2429,13 @@
return ( return (
<div className="panel-form"> <div className="panel-form">
<div className="panel-form-row"> <div className="panel-form-row">
<input type="text" placeholder="List like email:alice@example.com, tel:17025550003..." <i className="material-icons search">search</i>
value={this.state.search} onChange={this.handleSearchChange} <input className="search" type="text"
onKeyPress={this.handleKeyPress} required autoFocus /> placeholder="List like email:alice@example.com, tel:17025550003..."
<a href="javascript:;" onClick={this.handleSearch}> value={this.state.search} onChange={this.handleSearchChange}
<i className="material-icons">search</i> onKeyPress={this.handleKeyPress} required autoFocus />
<a href="javascript:;" onClick={this.handleClear}>
<i className="material-icons">close</i>
</a> </a>
</div> </div>
</div> </div>
@@ -4095,24 +4111,17 @@
tnInitFind: function() { tnInitFind: function() {
var fnd = Tinode.getFndTopic(); var fnd = Tinode.getFndTopic();
if (fnd.isSubscribed()) { if (fnd.isSubscribed()) {
this.setState({contactsSearchQuery: fnd.private ? fnd.private.toString() : ''}); this.setState({contactsSearchQuery: ''});
this.tnFndSubsUpdated(); this.tnFndSubsUpdated();
} else { } else {
fnd.onSubsUpdated = this.tnFndSubsUpdated; fnd.onSubsUpdated = this.tnFndSubsUpdated;
fnd.onMetaDesc = this.tnFndMetaDesc;
var instance = this; var instance = this;
fnd.subscribe(fnd.startMetaQuery().withSub().withLaterDesc().withTags().build()).catch(function(err){ fnd.subscribe(fnd.startMetaQuery().withSub().withTags().build()).catch(function(err){
instance.handleError(err.message, "err"); instance.handleError(err.message, "err");
}); });
} }
}, },
tnFndMetaDesc: function(desc) {
if (desc.private) {
this.setState({contactsSearchQuery: desc.private.toString()});
}
},
tnFndSubsUpdated: function() { tnFndSubsUpdated: function() {
var contacts = []; var contacts = [];
// Don't attempt to create P2P topics which already exist. Server will reject the duplicates. // Don't attempt to create P2P topics which already exist. Server will reject the duplicates.
@@ -4127,9 +4136,8 @@
handleSearchContacts: function(query) { handleSearchContacts: function(query) {
var fnd = Tinode.getFndTopic(); var fnd = Tinode.getFndTopic();
var instance = this; var instance = this;
fnd.setMeta({desc: {private: query}}) fnd.setMeta({desc: {public: query}}).then(function(ctrl) {
.then(function(ctrl) { return fnd.getMeta(fnd.startMetaQuery().withSub().build());
return fnd.getMeta(fnd.startMetaQuery().withSub().withLaterDesc().build());
}).catch(function(err){ }).catch(function(err){
instance.handleError(err.message, "err"); instance.handleError(err.message, "err");
}); });