message sounds, fix in searching for contacts

This commit is contained in:
or-else
2018-08-25 16:43:27 +03:00
parent 996dad96c1
commit 4aadff8ab3
2 changed files with 95 additions and 48 deletions
+4 -4
View File
@@ -1339,14 +1339,14 @@ ul.tabbar > li {
ul.tabbar > li > a { ul.tabbar > li > a {
position: relative; position: relative;
padding-top: 0.75rem; padding-top: 0.75rem;
text-decoration: none;
text-transform: uppercase;
display: block; display: block;
min-width: 6rem; min-width: 6.5rem;
text-align: center; text-align: center;
line-height: 2rem; line-height: 2rem;
font-weight: 400; font-weight: 400;
font-size: 1.1rem; font-size: 1.25rem;
font-variant: small-caps;
text-decoration: none;
color: rgba(33,150,243,0.6); color: rgba(33,150,243,0.6);
overflow: hidden; overflow: hidden;
box-shadow: inset 0 -2px 2.5px -1px rgba(0,0,0,0.25); box-shadow: inset 0 -2px 2.5px -1px rgba(0,0,0,0.25);
+91 -44
View File
@@ -1429,16 +1429,22 @@ class SettingsView extends React.PureComponent {
super(props); super(props);
this.state = { this.state = {
transport: "def" transport: props.transport || "def",
messageSounds: props.messageSounds
}; };
this.handleSubmit = this.handleSubmit.bind(this); this.handleSubmit = this.handleSubmit.bind(this);
this.handleMessageSoundsToggle = this.handleMessageSoundsToggle.bind(this);
this.handleTransportSelected = this.handleTransportSelected.bind(this); this.handleTransportSelected = this.handleTransportSelected.bind(this);
} }
handleSubmit(e) { handleSubmit(e) {
e.preventDefault(); e.preventDefault();
this.props.onUpdate(null, this.state.transport); this.props.onUpdate(null, this.state.transport, this.state.messageSounds);
}
handleMessageSoundsToggle(unused, checked) {
this.setState({messageSounds: checked});
} }
handleTransportSelected(e) { handleTransportSelected(e) {
@@ -1463,10 +1469,20 @@ class SettingsView extends React.PureComponent {
}); });
return ( return (
<form id="settings-form" onSubmit={this.handleSubmit}> <form id="settings-form" onSubmit={this.handleSubmit}>
<label className="small">Wire transport:</label> <div className="panel-form-row">
<ul className="quoted"> <label forHtml="message-sound">Message sound:</label>
{transportOptions} <CheckBox id="message-sound"
</ul> checked={this.state.messageSounds}
onChange={this.handleMessageSoundsToggle} />
</div>
<div className="panel-form-row">
<label className="small">Wire transport:</label>
</div>
<div className="panel-form-row">
<ul className="quoted">
{transportOptions}
</ul>
</div>
<div className="dialog-buttons"> <div className="dialog-buttons">
<button type="submit" className="blue">Update</button> <button type="submit" className="blue">Update</button>
</div> </div>
@@ -1587,7 +1603,7 @@ class SidepanelView extends React.Component {
disabled={this.props.loginDisabled} disabled={this.props.loginDisabled}
serverAddress={this.props.serverAddress} serverAddress={this.props.serverAddress}
onLogin={this.handleLoginRequested} onLogin={this.handleLoginRequested}
onServerAddressChange={this.props.onConnectionSettings} /> : onServerAddressChange={this.props.onGlobalSettings} /> :
view === 'register' ? view === 'register' ?
<CreateAccountView <CreateAccountView
@@ -1596,8 +1612,11 @@ class SidepanelView extends React.Component {
onError={this.props.onError} /> : onError={this.props.onError} /> :
view === 'settings' ? view === 'settings' ?
<SettingsView onCancel={this.props.onCancel} <SettingsView
onUpdate={this.props.onConnectionSettings} transport={this.props.transport}
messageSounds={this.props.messageSounds}
onCancel={this.props.onCancel}
onUpdate={this.props.onGlobalSettings}
/> : /> :
view === 'edit' ? view === 'edit' ?
@@ -1614,6 +1633,7 @@ class SidepanelView extends React.Component {
connected={this.props.connected} connected={this.props.connected}
topicSelected={this.props.topicSelected} topicSelected={this.props.topicSelected}
showContextMenu={this.props.showContextMenu} showContextMenu={this.props.showContextMenu}
messageSounds={this.props.messageSounds}
onTopicSelected={this.props.onTopicSelected} onTopicSelected={this.props.onTopicSelected}
onAcsChange={this.props.onAcsChange} onAcsChange={this.props.onAcsChange}
onOnlineChange={this.props.onOnlineChange} /> : onOnlineChange={this.props.onOnlineChange} /> :
@@ -2037,16 +2057,15 @@ class UnreadBadge extends React.PureComponent {
/* Contact's labels: [you], [muted], [blocked], etc */ /* Contact's labels: [you], [muted], [blocked], etc */
// FIXME: this class is unused. // FIXME: this class is unused.
class ContactBadges_UNUSED_REMOVE extends React.Component { class ContactBadges_UNUSED_REMOVE extends React.PureComponent {
render() { render() {
var badges = null; let badges = null;
if (this.props.badges && this.props.badges.length > 0) { if (this.props.badges && this.props.badges.length > 0) {
var count = 0;
badges = []; badges = [];
this.props.badges.map(function(b) { this.props.badges.map(function(b) {
var style = "badge" + (b.color ? " " + b.color : ""); var style = "badge" + (b.color ? " " + b.color : "");
badges.push(<span className={style} key={count}>{b.name}</span>); // Badge names are expected to be unique, so using the name as the key.
count ++; badges.push(<span className={style} key={b.name}>{b.name}</span>);
}); });
} }
return badges; return badges;
@@ -2107,12 +2126,12 @@ class ContactsView extends React.Component {
// New message received // New message received
// Skip update if the topic is currently open, otherwise the badge will annoyingly flash. // Skip update if the topic is currently open, otherwise the badge will annoyingly flash.
if (this.props.topicSelected !== cont.topic) { if (this.props.topicSelected !== cont.topic) {
// Disable sound for now. Need to add a config option. if (this.props.messageSounds) {
// POP_SOUND.play(); POP_SOUND.play();
}
this.resetContactList(); this.resetContactList();
} else if (document.hidden) { } else if (document.hidden && this.props.messageSounds) {
// Disable sound for now. POP_SOUND.play();
// POP_SOUND.play();
} }
} else if (what === "recv") { } else if (what === "recv") {
// Explicitly ignoring "recv" -- it causes no visible updates to contact list. // Explicitly ignoring "recv" -- it causes no visible updates to contact list.
@@ -2434,8 +2453,7 @@ class NewTopicView extends React.Component {
this.state = { this.state = {
tabSelected: "p2p", tabSelected: "p2p",
searchQuery: props.contactsSearchQuery, searchQuery: props.contactsSearchQuery,
contactList: props.foundContacts, contactList: props.foundContacts
contactSelected: null
}; };
this.handleTabClick = this.handleTabClick.bind(this); this.handleTabClick = this.handleTabClick.bind(this);
@@ -2448,17 +2466,24 @@ class NewTopicView extends React.Component {
this.props.onInitFind(); this.props.onInitFind();
} }
componentWillReceiveProps(nextProps) { componentWillReceiveProps_DISABLED(props) {
this.setState({ this.setState({
searchQuery: props.contactsSearchQuery,
contactList: props.foundContacts
});
}
static getDerivedStateFromProps(nextProps, prevState){
return {
searchQuery: nextProps.contactsSearchQuery, searchQuery: nextProps.contactsSearchQuery,
contactList: nextProps.foundContacts contactList: nextProps.foundContacts
}); };
} }
handleTabClick(e) { handleTabClick(e) {
e.preventDefault(); e.preventDefault();
window.location.hash = addUrlParam(window.location.hash, 'tab', e.currentTarget.dataset.id); window.location.hash = addUrlParam(window.location.hash, 'tab', e.currentTarget.dataset.id);
this.setState({tabSelected: e.currentTarget.dataset.id, contactSelected: null}); this.setState({tabSelected: e.currentTarget.dataset.id});
} }
handleContactSelected(sel) { handleContactSelected(sel) {
@@ -2483,10 +2508,10 @@ class NewTopicView extends React.Component {
<div className="flex-column"> <div className="flex-column">
<ul className="tabbar"> <ul className="tabbar">
<li className={this.state.tabSelected === "p2p" ? "active" : null}> <li className={this.state.tabSelected === "p2p" ? "active" : null}>
<a href="javascript:;" data-id="p2p" onClick={this.handleTabClick}>1:1</a> <a href="javascript:;" data-id="p2p" onClick={this.handleTabClick}>find</a>
</li> </li>
<li className={this.state.tabSelected === "grp" ? "active" : null}> <li className={this.state.tabSelected === "grp" ? "active" : null}>
<a href="javascript:;" data-id="grp" onClick={this.handleTabClick}>group</a> <a href="javascript:;" data-id="grp" onClick={this.handleTabClick}>new group</a>
</li> </li>
<li className={this.state.tabSelected === "byid" ? "active" : null}> <li className={this.state.tabSelected === "byid" ? "active" : null}>
<a href="javascript:;" data-id="byid" onClick={this.handleTabClick}>by id</a> <a href="javascript:;" data-id="byid" onClick={this.handleTabClick}>by id</a>
@@ -2606,7 +2631,7 @@ class SearchContacts extends React.Component {
this.handleSearchChange = this.handleSearchChange.bind(this); this.handleSearchChange = this.handleSearchChange.bind(this);
this.handleSearch = this.handleSearch.bind(this); this.handleSearch = this.handleSearch.bind(this);
this.handleClear = this.handleClear.bind(this); this.handleClear = this.handleClear.bind(this);
this.handleKeyPress = this.handleKeyPress.bind(this); this.handleKeyDown = this.handleKeyDown.bind(this);
} }
componentWillUnmount() { componentWillUnmount() {
@@ -2626,6 +2651,8 @@ class SearchContacts extends React.Component {
if (query.length > 0) { if (query.length > 0) {
this.setState({edited: true}); this.setState({edited: true});
this.props.onSearchContacts(query); this.props.onSearchContacts(query);
} else if (this.props.searchQuery) {
this.props.onSearchContacts(DEL_CHAR);
} }
} }
@@ -2636,9 +2663,11 @@ class SearchContacts extends React.Component {
this.setState({search: '', edited: false}); this.setState({search: '', edited: false});
} }
handleKeyPress(e) { handleKeyDown(e) {
if (e.key === 'Enter') { if (e.key === 'Enter') {
this.handleSearch(e); this.handleSearch(e);
} else if (e.key === 'Escape') {
this.handleClear();
} }
} }
@@ -2650,7 +2679,7 @@ class SearchContacts extends React.Component {
<input className="search" type="text" <input className="search" type="text"
placeholder="List like email:alice@example.com, tel:17025550003..." placeholder="List like email:alice@example.com, tel:17025550003..."
value={this.state.search} onChange={this.handleSearchChange} value={this.state.search} onChange={this.handleSearchChange}
onKeyPress={this.handleKeyPress} required autoFocus /> onKeyDown={this.handleKeyDown} required autoFocus />
<a href="javascript:;" onClick={this.handleClear}> <a href="javascript:;" onClick={this.handleClear}>
<i className="material-icons">close</i> <i className="material-icons">close</i>
</a> </a>
@@ -4301,7 +4330,7 @@ class TinodeWeb extends React.Component {
this.handleUpdateAccountRequest = this.handleUpdateAccountRequest.bind(this); this.handleUpdateAccountRequest = this.handleUpdateAccountRequest.bind(this);
this.handleUpdateAccountTagsRequest = this.handleUpdateAccountTagsRequest.bind(this); this.handleUpdateAccountTagsRequest = this.handleUpdateAccountTagsRequest.bind(this);
this.handleSettings = this.handleSettings.bind(this); this.handleSettings = this.handleSettings.bind(this);
this.handleConnectionSettings = this.handleConnectionSettings.bind(this); this.handleGlobalSettings = this.handleGlobalSettings.bind(this);
this.handleSidepanelCancel = this.handleSidepanelCancel.bind(this); this.handleSidepanelCancel = this.handleSidepanelCancel.bind(this);
this.handleNewTopic = this.handleNewTopic.bind(this); this.handleNewTopic = this.handleNewTopic.bind(this);
this.handleNewTopicRequest = this.handleNewTopicRequest.bind(this); this.handleNewTopicRequest = this.handleNewTopicRequest.bind(this);
@@ -4323,10 +4352,14 @@ class TinodeWeb extends React.Component {
} }
getBlankState() { getBlankState() {
let settings = localStorage.getObject("settings") || {};
return { return {
connected: false, connected: false,
transport: null, transport: settings.transport || null,
serverAddress: detectServerAddress(), serverAddress: settings.serverAddress || detectServerAddress(),
// "On" is the default, so saving the "off" state.
messageSounds: !settings.messageSoundsOff,
sidePanelSelected: 'login', sidePanelSelected: 'login',
sidePanelTitle: null, sidePanelTitle: null,
sidePanelAvatar: null, sidePanelAvatar: null,
@@ -4351,7 +4384,7 @@ class TinodeWeb extends React.Component {
contextMenuParams: null, contextMenuParams: null,
contextMenuItems: [], contextMenuItems: [],
serverVersion: 'no connection', serverVersion: 'no connection',
contactsSearchQuery: '', contactsSearchQuery: undefined,
foundContacts: [], foundContacts: [],
credMethod: undefined, credMethod: undefined,
credCode: undefined credCode: undefined
@@ -4640,9 +4673,8 @@ class TinodeWeb extends React.Component {
this.tnFndSubsUpdated(); this.tnFndSubsUpdated();
} else { } else {
fnd.onSubsUpdated = this.tnFndSubsUpdated; fnd.onSubsUpdated = this.tnFndSubsUpdated;
var instance = this; fnd.subscribe(fnd.startMetaQuery().withSub().withTags().build()).catch((err) => {
fnd.subscribe(fnd.startMetaQuery().withSub().withTags().build()).catch(function(err){ this.handleError(err.message, "err");
instance.handleError(err.message, "err");
}); });
} }
} }
@@ -4655,16 +4687,17 @@ class TinodeWeb extends React.Component {
}); });
this.setState({foundContacts: contacts}); this.setState({foundContacts: contacts});
} }
/** Called when the user enters a contact into the contact search field in the NewAccount panel /** Called when the user enters a contact into the contact search field in the NewAccount panel
@param query {Array} is an array of contacts to search for @param query {Array} is an array of contacts to search for
*/ */
handleSearchContacts(query) { handleSearchContacts(query) {
var fnd = Tinode.getFndTopic(); var fnd = Tinode.getFndTopic();
var instance = this; this.setState({contactsSearchQuery: query == DEL_CHAR ? '' : query});
fnd.setMeta({desc: {public: query}}).then(function(ctrl) { fnd.setMeta({desc: {public: query}}).then((ctrl) => {
return fnd.getMeta(fnd.startMetaQuery().withSub().build()); return fnd.getMeta(fnd.startMetaQuery().withSub().build());
}).catch(function(err){ }).catch((err) => {
instance.handleError(err.message, "err"); this.handleError(err.message, "err");
}); });
} }
@@ -4794,11 +4827,23 @@ class TinodeWeb extends React.Component {
window.location.hash = setUrlSidePanel(window.location.hash, this.state.myUserId ? 'edit' : 'settings'); window.location.hash = setUrlSidePanel(window.location.hash, this.state.myUserId ? 'edit' : 'settings');
} }
// User updated connection parameters - transport and server address // User updated global parameters.
handleConnectionSettings(serverAddress, transport) { handleGlobalSettings(serverAddress, transport, messageSounds) {
transport = transport || this.state.transport; transport = transport || this.state.transport;
serverAddress = serverAddress || this.state.serverAddress; serverAddress = serverAddress || this.state.serverAddress;
this.setState({serverAddress: serverAddress, transport: transport, sidePanelSelected: 'login'}); messageSounds = (typeof messageSounds == 'boolean') ? messageSounds : this.state.messageSounds;
this.setState({
serverAddress: serverAddress,
transport: transport,
messageSounds: messageSounds,
sidePanelSelected: 'login'
});
localStorage.setObject({
serverAddress: serverAddress,
messageSoundsOff: !messageSounds,
transport: this.state.transport
});
TinodeWeb.tnSetup(serverAddress, transport); TinodeWeb.tnSetup(serverAddress, transport);
} }
@@ -5028,8 +5073,10 @@ class TinodeWeb extends React.Component {
credMethod={this.state.credMethod} credMethod={this.state.credMethod}
credCode={this.state.credCode} credCode={this.state.credCode}
transport={this.state.transport}
messageSounds={this.state.messageSounds}
serverAddress={this.state.serverAddress} serverAddress={this.state.serverAddress}
onConnectionSettings={this.handleConnectionSettings} onGlobalSettings={this.handleGlobalSettings}
onSignUp={this.handleNewAccount} onSignUp={this.handleNewAccount}
onSettings={this.handleSettings} onSettings={this.handleSettings}