fixes for various UI bugs

This commit is contained in:
or-else
2018-09-13 17:10:11 +03:00
parent 03db847d48
commit 3c20bcf6f2
+92 -69
View File
@@ -1893,7 +1893,10 @@ class TagManager extends React.Component {
} }
static getDerivedStateFromProps(nextProps, prevState) { static getDerivedStateFromProps(nextProps, prevState) {
return {tags: nextProps.tags}; if (!arrayEqual(nextProps.tags, prevState.tags) && !prevState.activated) {
return {tags: nextProps.tags};
}
return null;
} }
handleShowTagManager() { handleShowTagManager() {
@@ -1917,10 +1920,9 @@ class TagManager extends React.Component {
handleAddTag(tag) { handleAddTag(tag) {
tag = tag.trim(); tag = tag.trim();
if (tag.length > 0) { if (tag.length > 0) {
var tags = this.state.tags.slice(0); let tags = this.state.tags.slice(0);
tags.push(tag); tags.push(tag);
this.setState({tags: tags, tagInput: ''}); this.setState({tags: tags, tagInput: ''});
if (this.props.onTagsChanged) { if (this.props.onTagsChanged) {
this.props.onTagsChanged(tags); this.props.onTagsChanged(tags);
} }
@@ -1937,8 +1939,8 @@ class TagManager extends React.Component {
} }
handleSubmit() { handleSubmit() {
var tags = this.state.tags.slice(0); let tags = this.state.tags.slice(0);
var inp = this.state.tagInput.trim(); let inp = this.state.tagInput.trim();
if (inp.length > 0) { if (inp.length > 0) {
tags.push(inp); tags.push(inp);
if (this.props.onTagsChanged) { if (this.props.onTagsChanged) {
@@ -1976,7 +1978,7 @@ class TagManager extends React.Component {
<label className="small">{this.props.title}</label> <label className="small">{this.props.title}</label>
</div> </div>
{this.state.activated ? {this.state.activated ?
<div> <div>
<ChipInput <ChipInput
chips={tags} chips={tags}
avatarDisabled={true} avatarDisabled={true}
@@ -1992,14 +1994,14 @@ class TagManager extends React.Component {
<button className="white" onClick={this.handleCancel}>Cancel</button> <button className="white" onClick={this.handleCancel}>Cancel</button>
</div> </div>
: null} : null}
</div> </div>
: :
<div> <div>
<a href="javascript:;" className="flat-button" onClick={this.handleShowTagManager}> <a href="javascript:;" className="flat-button" onClick={this.handleShowTagManager}>
<i className="material-icons">edit</i> Manage tags <i className="material-icons">edit</i> Manage tags
</a> </a>
<span>{tags}</span> <span>{tags}</span>
</div> </div>
} }
</div> </div>
); );
@@ -3533,6 +3535,7 @@ class Attachment extends React.Component {
); );
} }
}; };
const NOT_FOUND_TOPIC_TITLE = "Not found";
class MessagesView extends React.Component { class MessagesView extends React.Component {
constructor(props) { constructor(props) {
@@ -3607,12 +3610,17 @@ class MessagesView extends React.Component {
return; return;
} }
var tryToResubscribe = !this.props.connected && props.connected; let topic = this.props.tinode.getTopic(props.topic);
if (!topic) {
return;
}
let newGroupTopic = Tinode.isNewGroupTopicName(props.topic);
let tryToResubscribe = !this.props.connected && props.connected;
var topic = this.props.tinode.getTopic(props.topic);
if (props.topic != this.state.topic) { if (props.topic != this.state.topic) {
var msgs = []; let msgs = [];
var subs = []; let subs = [];
// Bind the new topic to component. // Bind the new topic to component.
topic.onData = this.handleNewMessage; topic.onData = this.handleNewMessage;
@@ -3657,21 +3665,26 @@ class MessagesView extends React.Component {
}); });
if (!topic.isSubscribed() && tryToResubscribe) { if (!topic.isSubscribed() && tryToResubscribe) {
var getQuery = topic.startMetaQuery() let getQuery = topic.startMetaQuery()
.withLaterDesc() .withLaterDesc()
.withLaterSub() .withLaterSub()
.withLaterData(MESSAGES_PAGE) .withLaterData(MESSAGES_PAGE)
.withLaterDel(); .withLaterDel();
let setQuery = newGroupTopic ? props.newGroupTopicParams : undefined;
// Don't request the tags. They are useless unless the user // Don't request the tags. They are useless unless the user
// is the owner and is editing the topic. // is the owner and is editing the topic.
// getQuery = topic.getType() == 'grp' ? getQuery.withTags() : getQuery; // getQuery = topic.getType() == 'grp' ? getQuery.withTags() : getQuery;
// Show "loading" spinner. // Show "loading" spinner.
this.setState({ fetchingMessages: true }); this.setState({ fetchingMessages: true });
topic.subscribe(getQuery.build()) topic.subscribe(getQuery.build(), setQuery)
.then((ctrl) => {
this.setState({topic: ctrl.topic});
this.props.onNewTopicCreated(props.topic, ctrl.topic);
})
.catch((err) => { .catch((err) => {
this.props.onError(err.message, "err"); this.props.onError(err.message, "err");
this.setState({ this.setState({
title: "Not found", title: NOT_FOUND_TOPIC_TITLE,
avatar: null, avatar: null,
readOnly: true, readOnly: true,
writeOnly: true, writeOnly: true,
@@ -3683,20 +3696,24 @@ class MessagesView extends React.Component {
leave() { leave() {
if (this.state.topic) { if (this.state.topic) {
var oldTopic = this.props.tinode.getTopic(this.state.topic); let oldTopic = this.props.tinode.getTopic(this.state.topic);
if (oldTopic) { if (oldTopic) {
if (oldTopic.isSubscribed()) { if (oldTopic.isSubscribed()) {
oldTopic.leave(false).catch(function(err) { oldTopic.leave(false)
// do nothing .then((ctrl) => {
console.log(err); this.setState({fetchingMessages: false});
}); oldTopic.onData = undefined;
oldTopic.onAllMessagesReceived = undefined;
oldTopic.onInfo = undefined;
oldTopic.onMetaDesc = undefined;
oldTopic.onSubsUpdated = undefined;
oldTopic.onPres = undefined;
})
.catch((err) => {
// do nothing
console.log(err);
});
} }
oldTopic.onData = undefined;
oldTopic.onAllMessagesReceived = undefined;
oldTopic.onInfo = undefined;
oldTopic.onMetaDesc = undefined;
oldTopic.onSubsUpdated = undefined;
oldTopic.onPres = undefined;
} }
} }
} }
@@ -3734,6 +3751,11 @@ class MessagesView extends React.Component {
title: desc.public.fn, title: desc.public.fn,
avatar: makeImageUrl(desc.public.photo) avatar: makeImageUrl(desc.public.photo)
}); });
} else {
this.setState({
title: NOT_FOUND_TOPIC_TITLE,
avatar: null
});
} }
if (desc.acs) { if (desc.acs) {
this.setState({ this.setState({
@@ -4288,6 +4310,7 @@ class TinodeWeb extends React.Component {
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);
this.handleNewTopicCreated = this.handleNewTopicCreated.bind(this);
this.handleTopicUpdateRequest = this.handleTopicUpdateRequest.bind(this); this.handleTopicUpdateRequest = this.handleTopicUpdateRequest.bind(this);
this.handleChangePermissions = this.handleChangePermissions.bind(this); this.handleChangePermissions = this.handleChangePermissions.bind(this);
this.handleTagsUpdated = this.handleTagsUpdated.bind(this); this.handleTagsUpdated = this.handleTagsUpdated.bind(this);
@@ -4332,6 +4355,7 @@ class TinodeWeb extends React.Component {
topicSelected: '', topicSelected: '',
topicSelectedOnline: false, topicSelectedOnline: false,
topicSelectedAcs: null, topicSelectedAcs: null,
newGroupTopicParams: null,
loginDisabled: false, loginDisabled: false,
displayMobile: (window.innerWidth <= MEDIA_BREAKPOINT), displayMobile: (window.innerWidth <= MEDIA_BREAKPOINT),
showInfoPanel: false, showInfoPanel: false,
@@ -4420,30 +4444,24 @@ class TinodeWeb extends React.Component {
// Handle for hashchange event: display appropriate panels. // Handle for hashchange event: display appropriate panels.
handleHashRoute() { handleHashRoute() {
var hash = parseUrlHash(window.location.hash); var hash = parseUrlHash(window.location.hash);
// Left-side panel selector.
if (hash.path && hash.path.length > 0) { if (hash.path && hash.path.length > 0) {
// Left-side panel selector.
if (['register','settings','edit','cred','newtpk','contacts',''].includes(hash.path[0])) { if (['register','settings','edit','cred','newtpk','contacts',''].includes(hash.path[0])) {
this.setState({sidePanelSelected: hash.path[0]}); this.setState({sidePanelSelected: hash.path[0]});
} else { } else {
console.log("Unknown sidepanel view", hash.path[0]); console.log("Unknown sidepanel view", hash.path[0]);
} }
// Topic for MessagesView selector.
if (hash.path.length > 1 && hash.path[1] != this.state.topicSelected) {
this.setState({
topicSelected: Tinode.topicType(hash.path[1]) ? hash.path[1] : null
});
}
} else { } else {
// Empty hashpath // Empty hashpath
this.setState({sidePanelSelected: ''}); this.setState({sidePanelSelected: ''});
} }
// Topic for MessagesView selector.
if (hash.path.length > 1 && hash.path[1] != this.state.topicSelected) {
var tp = Tinode.topicType(hash.path[1]);
if (tp) {
this.setState({
topicSelected: hash.path[1],
topicSelectedOnline: false,
topicSelectedAcs: null
});
} else {
this.setState({topicSelected: null});
}
}
// Save validation credentials, if available. // Save validation credentials, if available.
if (hash.params.method) { if (hash.params.method) {
@@ -4771,13 +4789,7 @@ class TinodeWeb extends React.Component {
// User clicked on a contact in the side panel or deleted a contact. // User clicked on a contact in the side panel or deleted a contact.
handleTopicSelected(topicName, unused_index, online, acs) { handleTopicSelected(topicName, unused_index, online, acs) {
console.log("handleTopicSelected", topicName, online, acs);
if (topicName) { if (topicName) {
// Contact selected
if (this.state.topicSelected != topicName) {
navigateTo(setUrlTopic(window.location.hash, topicName));
}
this.setState({ this.setState({
errorText: '', errorText: '',
errorLevel: null, errorLevel: null,
@@ -4786,10 +4798,11 @@ class TinodeWeb extends React.Component {
topicSelectedAcs: acs, topicSelectedAcs: acs,
showInfoPanel: false showInfoPanel: false
}); });
} else { // Contact selected
if (this.state.topicSelected) { if (this.state.topicSelected != topicName) {
navigateTo(setUrlTopic(window.location.hash, null)); navigateTo(setUrlTopic("", topicName));
} }
} else {
// Currently selected contact deleted // Currently selected contact deleted
this.setState({ this.setState({
errorText: '', errorText: '',
@@ -4799,6 +4812,9 @@ class TinodeWeb extends React.Component {
topicSelectedAcs: null, topicSelectedAcs: null,
showInfoPanel: false showInfoPanel: false
}); });
if (this.state.topicSelected) {
navigateTo(setUrlTopic("", null));
}
} }
} }
@@ -4926,24 +4942,29 @@ class TinodeWeb extends React.Component {
navigateTo(setUrlSidePanel(window.location.hash, 'newtpk')); navigateTo(setUrlSidePanel(window.location.hash, 'newtpk'));
} }
// Create a new topic. New P2P topic requires peer's name. // Request to start a new topic. New P2P topic requires peer's name.
handleNewTopicRequest(peerName, pub, priv, tags) { handleNewTopicRequest(peerName, pub, priv, tags) {
var topic = peerName ? this.state.tinode.newTopicWith(peerName) : this.state.tinode.newTopic(); var topicName = peerName || this.state.tinode.newGroupTopicName();
var query = topic.startMetaQuery().withDesc().withSub().withData();
var setParams;
if (!peerName) { if (!peerName) {
// Creator is the owner, has access to tags. this.setState(
// Fetch default group topic tags, if any. {newGroupTopicParams: {desc: {public: pub, private: priv}, tags: tags}},
query = query.withTags(); () => {this.handleTopicSelected(topicName)}
setParams = {desc: {public: pub, private: priv}, tags: tags}; );
} else {
this.handleTopicSelected(topicName);
}
}
// New topic was creted, here is the new topic name.
handleNewTopicCreated(oldName, newName) {
console.log("handleNewTopicCreated", oldName, newName);
if (this.state.topicSelected == oldName && oldName != newName) {
// If the current URl contains the old topic name, replace it with new.
// Update the name of the selected topic first so the navigator doen't clear
// the state.
this.setState({topicSelected: newName}, () => { navigateTo(setUrlTopic("", newName)); });
} }
topic.subscribe(query.build(), setParams).then(() => {
navigateTo(setUrlSidePanel(window.location.hash, 'contacts'));
this.handleTopicSelected(topic.name, undefined,
this.state.tinode.isTopicOnline(topic.name), topic.getAccessMode());
}).catch((err) => {
this.handleError(err.message, "err");
});
} }
handleTopicUpdateRequest(topicName, pub, priv, permissions) { handleTopicUpdateRequest(topicName, pub, priv, permissions) {
@@ -5179,10 +5200,12 @@ class TinodeWeb extends React.Component {
serverAddress={this.state.serverAddress} serverAddress={this.state.serverAddress}
errorText={this.state.errorText} errorText={this.state.errorText}
errorLevel={this.state.errorLevel} errorLevel={this.state.errorLevel}
newGroupTopicParams={this.state.newGroupTopicParams}
onHideMessagesView={this.handleHideMessagesView} onHideMessagesView={this.handleHideMessagesView}
onData={this.tnData} onData={this.tnData}
onError={this.handleError} onError={this.handleError}
onNewTopicCreated={this.handleNewTopicCreated}
readTimerHandler={this.handleReadTimer} readTimerHandler={this.handleReadTimer}
showContextMenu={this.handleShowContextMenu} showContextMenu={this.handleShowContextMenu}
sendMessage={this.handleSendMessage} /> sendMessage={this.handleSendMessage} />