From 3c20bcf6f28ca3016901881eb0533b6678876521 Mon Sep 17 00:00:00 2001 From: or-else Date: Thu, 13 Sep 2018 17:10:11 +0300 Subject: [PATCH] fixes for various UI bugs --- src/webapp.jsx | 161 ++++++++++++++++++++++++++++--------------------- 1 file changed, 92 insertions(+), 69 deletions(-) diff --git a/src/webapp.jsx b/src/webapp.jsx index 2377cbe5..01ccbce5 100644 --- a/src/webapp.jsx +++ b/src/webapp.jsx @@ -1893,7 +1893,10 @@ class TagManager extends React.Component { } static getDerivedStateFromProps(nextProps, prevState) { - return {tags: nextProps.tags}; + if (!arrayEqual(nextProps.tags, prevState.tags) && !prevState.activated) { + return {tags: nextProps.tags}; + } + return null; } handleShowTagManager() { @@ -1917,10 +1920,9 @@ class TagManager extends React.Component { handleAddTag(tag) { tag = tag.trim(); if (tag.length > 0) { - var tags = this.state.tags.slice(0); + let tags = this.state.tags.slice(0); tags.push(tag); this.setState({tags: tags, tagInput: ''}); - if (this.props.onTagsChanged) { this.props.onTagsChanged(tags); } @@ -1937,8 +1939,8 @@ class TagManager extends React.Component { } handleSubmit() { - var tags = this.state.tags.slice(0); - var inp = this.state.tagInput.trim(); + let tags = this.state.tags.slice(0); + let inp = this.state.tagInput.trim(); if (inp.length > 0) { tags.push(inp); if (this.props.onTagsChanged) { @@ -1976,7 +1978,7 @@ class TagManager extends React.Component { {this.state.activated ? -
+
Cancel
: null} -
+ : -
- - edit Manage tags - - {tags} -
+
+ + edit Manage tags + + {tags} +
} ); @@ -3533,6 +3535,7 @@ class Attachment extends React.Component { ); } }; +const NOT_FOUND_TOPIC_TITLE = "Not found"; class MessagesView extends React.Component { constructor(props) { @@ -3607,12 +3610,17 @@ class MessagesView extends React.Component { 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) { - var msgs = []; - var subs = []; + let msgs = []; + let subs = []; // Bind the new topic to component. topic.onData = this.handleNewMessage; @@ -3657,21 +3665,26 @@ class MessagesView extends React.Component { }); if (!topic.isSubscribed() && tryToResubscribe) { - var getQuery = topic.startMetaQuery() + let getQuery = topic.startMetaQuery() .withLaterDesc() .withLaterSub() .withLaterData(MESSAGES_PAGE) .withLaterDel(); + let setQuery = newGroupTopic ? props.newGroupTopicParams : undefined; // Don't request the tags. They are useless unless the user // is the owner and is editing the topic. // getQuery = topic.getType() == 'grp' ? getQuery.withTags() : getQuery; // Show "loading" spinner. 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) => { this.props.onError(err.message, "err"); this.setState({ - title: "Not found", + title: NOT_FOUND_TOPIC_TITLE, avatar: null, readOnly: true, writeOnly: true, @@ -3683,20 +3696,24 @@ class MessagesView extends React.Component { leave() { 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.isSubscribed()) { - oldTopic.leave(false).catch(function(err) { - // do nothing - console.log(err); - }); + oldTopic.leave(false) + .then((ctrl) => { + 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, avatar: makeImageUrl(desc.public.photo) }); + } else { + this.setState({ + title: NOT_FOUND_TOPIC_TITLE, + avatar: null + }); } if (desc.acs) { this.setState({ @@ -4288,6 +4310,7 @@ class TinodeWeb extends React.Component { this.handleSidepanelCancel = this.handleSidepanelCancel.bind(this); this.handleNewTopic = this.handleNewTopic.bind(this); this.handleNewTopicRequest = this.handleNewTopicRequest.bind(this); + this.handleNewTopicCreated = this.handleNewTopicCreated.bind(this); this.handleTopicUpdateRequest = this.handleTopicUpdateRequest.bind(this); this.handleChangePermissions = this.handleChangePermissions.bind(this); this.handleTagsUpdated = this.handleTagsUpdated.bind(this); @@ -4332,6 +4355,7 @@ class TinodeWeb extends React.Component { topicSelected: '', topicSelectedOnline: false, topicSelectedAcs: null, + newGroupTopicParams: null, loginDisabled: false, displayMobile: (window.innerWidth <= MEDIA_BREAKPOINT), showInfoPanel: false, @@ -4420,30 +4444,24 @@ class TinodeWeb extends React.Component { // Handle for hashchange event: display appropriate panels. handleHashRoute() { var hash = parseUrlHash(window.location.hash); - // Left-side panel selector. if (hash.path && hash.path.length > 0) { + // Left-side panel selector. if (['register','settings','edit','cred','newtpk','contacts',''].includes(hash.path[0])) { this.setState({sidePanelSelected: hash.path[0]}); } else { 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 { // Empty hashpath 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. 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. handleTopicSelected(topicName, unused_index, online, acs) { - console.log("handleTopicSelected", topicName, online, acs); - if (topicName) { - // Contact selected - if (this.state.topicSelected != topicName) { - navigateTo(setUrlTopic(window.location.hash, topicName)); - } this.setState({ errorText: '', errorLevel: null, @@ -4786,10 +4798,11 @@ class TinodeWeb extends React.Component { topicSelectedAcs: acs, showInfoPanel: false }); - } else { - if (this.state.topicSelected) { - navigateTo(setUrlTopic(window.location.hash, null)); + // Contact selected + if (this.state.topicSelected != topicName) { + navigateTo(setUrlTopic("", topicName)); } + } else { // Currently selected contact deleted this.setState({ errorText: '', @@ -4799,6 +4812,9 @@ class TinodeWeb extends React.Component { topicSelectedAcs: null, showInfoPanel: false }); + if (this.state.topicSelected) { + navigateTo(setUrlTopic("", null)); + } } } @@ -4926,24 +4942,29 @@ class TinodeWeb extends React.Component { 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) { - var topic = peerName ? this.state.tinode.newTopicWith(peerName) : this.state.tinode.newTopic(); - var query = topic.startMetaQuery().withDesc().withSub().withData(); - var setParams; + var topicName = peerName || this.state.tinode.newGroupTopicName(); if (!peerName) { - // Creator is the owner, has access to tags. - // Fetch default group topic tags, if any. - query = query.withTags(); - setParams = {desc: {public: pub, private: priv}, tags: tags}; + this.setState( + {newGroupTopicParams: {desc: {public: pub, private: priv}, tags: tags}}, + () => {this.handleTopicSelected(topicName)} + ); + } 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) { @@ -5179,10 +5200,12 @@ class TinodeWeb extends React.Component { serverAddress={this.state.serverAddress} errorText={this.state.errorText} errorLevel={this.state.errorLevel} + newGroupTopicParams={this.state.newGroupTopicParams} onHideMessagesView={this.handleHideMessagesView} onData={this.tnData} onError={this.handleError} + onNewTopicCreated={this.handleNewTopicCreated} readTimerHandler={this.handleReadTimer} showContextMenu={this.handleShowContextMenu} sendMessage={this.handleSendMessage} />