updated search, better typing indicator
This commit is contained in:
+15
-12
@@ -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
@@ -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");
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user