better error handling and reporting
This commit is contained in:
+42
-8
@@ -505,17 +505,52 @@ table.permission-editor td.checkbox {
|
||||
|
||||
|
||||
/* Area which displays an error message */
|
||||
#alert-box {
|
||||
background-color: transparent;
|
||||
height: 0;
|
||||
.alert-box {
|
||||
position: relative;
|
||||
display: none;
|
||||
overflow: hidden;
|
||||
padding: 1rem 1.5rem 1rem 0.5rem;
|
||||
}
|
||||
#alert-box.error-alert {
|
||||
padding: 0.5rem;
|
||||
.alert-box .cancel {
|
||||
position: absolute;
|
||||
right: 0.25rem;
|
||||
top: 0.5rem;
|
||||
}
|
||||
|
||||
.alert-box.error {
|
||||
display: block;
|
||||
background-color: #ffcdd2;
|
||||
border-color: #d32f2f;
|
||||
border-bottom: 1px solid #ffbfc8;
|
||||
color: #b71c1c;
|
||||
height: auto;
|
||||
}
|
||||
.alert-box.warning {
|
||||
display: block;
|
||||
background-color: #fff9c4;
|
||||
border-bottom: 1px solid #fff59d;
|
||||
color: #607d8b;
|
||||
}
|
||||
.alert-box .cancel .material-icons {
|
||||
font-size: 1rem;
|
||||
}
|
||||
.alert-box.error .cancel .material-icons {
|
||||
color: #b71c1c;
|
||||
}
|
||||
.alert-box.warning .cancel .material-icons {
|
||||
color: #757575;
|
||||
}
|
||||
.alert-box .icon {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
.alert-box .icon .material-icons {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
.alert-box.warning .icon .material-icons {
|
||||
color: #fbc02d;
|
||||
}
|
||||
.alert-box.error .icon .material-icons {
|
||||
color: #ef5350;
|
||||
}
|
||||
|
||||
/* List of contacts */
|
||||
@@ -1488,7 +1523,6 @@ ul.tabbar li.active > a:after {
|
||||
border-top: 0.35rem solid #1e88e5;
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
-webkit-animation: spin 1.5s linear infinite;
|
||||
animation: spin 1.5s linear infinite;
|
||||
}
|
||||
|
||||
|
||||
@@ -521,8 +521,6 @@ Sample JSON representation of the text above:
|
||||
return a.at - b.at;
|
||||
});
|
||||
|
||||
console.log(spans);
|
||||
|
||||
// Denormalize entities into spans. Create a copy of the objects to leave
|
||||
// original Drafty object unchanged.
|
||||
spans = spans.map(function(s) {
|
||||
@@ -536,8 +534,6 @@ Sample JSON representation of the text above:
|
||||
return {tp: tp, data: data, at: s.at, len: s.len};
|
||||
});
|
||||
|
||||
console.log(spans);
|
||||
|
||||
return forEach(txt, 0, txt.length, spans, formatter, context);
|
||||
},
|
||||
|
||||
|
||||
+159
-90
@@ -15,9 +15,9 @@
|
||||
<!-- Styles for local elements -->
|
||||
<link rel="stylesheet" href="css/base.css" />
|
||||
<!-- ReactJs scripts -->
|
||||
<script src="https://unpkg.com/react@15.4/dist/react.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@15.4/dist/react-dom.js"></script>
|
||||
<script src="https://unpkg.com/babel-standalone@6.24.0/babel.min.js"></script>
|
||||
<script src="https://unpkg.com/react@15/dist/react.min.js"></script>
|
||||
<script src="https://unpkg.com/react-dom@15/dist/react-dom.min.js"></script>
|
||||
<script src="https://unpkg.com/babel-standalone@6.26.0/babel.min.js"></script>
|
||||
<script src="tinode.js"></script>
|
||||
<script src="drafty.js"></script>
|
||||
</head>
|
||||
@@ -133,7 +133,7 @@
|
||||
/* BEGIN Context Menu: popup/dropdown menu */
|
||||
|
||||
// Function is used by context menu to set permissions.
|
||||
function topicPermissionSetter(mode, topicName, uid) {
|
||||
function topicPermissionSetter(mode, topicName, uid, errorHandler) {
|
||||
var topic = Tinode.getTopic(topicName);
|
||||
if (!topic) {
|
||||
console.log("Topic not found: " + topicName);
|
||||
@@ -151,7 +151,14 @@
|
||||
} else {
|
||||
am = topic.getAccessMode().updateWant(mode).getWant();
|
||||
}
|
||||
topic.setMeta({sub: {user: uid, mode: am}});
|
||||
var instance = this;
|
||||
topic.setMeta({sub: {user: uid, mode: am}}).catch(function(err) {
|
||||
if (errorHandler) {
|
||||
errorHandler(err.message, "err");
|
||||
} else {
|
||||
console.log(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Context menu items.
|
||||
@@ -164,6 +171,7 @@
|
||||
console.log("Topic not found: " + topicName);
|
||||
return;
|
||||
}
|
||||
|
||||
topic.delMessagesAll(false).then(function(){
|
||||
console.log("refresh message list");
|
||||
});
|
||||
@@ -232,7 +240,7 @@
|
||||
e.stopPropagation();
|
||||
this.props.hide();
|
||||
var item = this.props.items[e.currentTarget.dataset.id];
|
||||
item.handler(this.props.topic, this.props.user);
|
||||
item.handler(this.props.topic, this.props.user, this.props.onError);
|
||||
},
|
||||
|
||||
render: function() {
|
||||
@@ -280,13 +288,17 @@
|
||||
/* END Popup/dropdown menu */
|
||||
|
||||
/* The X menu to be displayed in title bars */
|
||||
var MenuCancel = React.createClass({
|
||||
render: function() {
|
||||
class MenuCancel extends React.PureComponent {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<a href="#" onClick={this.props.onCancel}><i className="material-icons">close</i></a>
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
class LoadSpinner extends React.PureComponent {
|
||||
render() {
|
||||
@@ -714,31 +726,20 @@
|
||||
login: this.props.login,
|
||||
password: '',
|
||||
hostName: this.props.serverAddress,
|
||||
errorCleared: false
|
||||
};
|
||||
},
|
||||
clearError: function() {
|
||||
if (!this.state.errorCleared) {
|
||||
this.props.onClearError();
|
||||
this.setState({errorCleared: true});
|
||||
}
|
||||
},
|
||||
handleLoginChange: function(e) {
|
||||
this.clearError();
|
||||
this.setState({login: e.target.value});
|
||||
},
|
||||
handlePasswordChange: function(e) {
|
||||
this.clearError();
|
||||
this.setState({password: e.target.value});
|
||||
},
|
||||
handleServerAddressChange: function(name) {
|
||||
this.clearError();
|
||||
this.setState({hostName: name});
|
||||
this.props.onServerAddressChange(name);
|
||||
},
|
||||
handleSubmit: function(e) {
|
||||
e.preventDefault();
|
||||
this.setState({errorCleared: false});
|
||||
this.props.onLogin(this.state.login.trim(), this.state.password.trim());
|
||||
},
|
||||
|
||||
@@ -1000,20 +1001,11 @@
|
||||
</div>
|
||||
);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
var SidepanelView = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
showErrorText: true
|
||||
};
|
||||
},
|
||||
handleClearErrorText: function() {
|
||||
this.setState({showErrorText: false});
|
||||
},
|
||||
handleLoginRequested: function(login, password) {
|
||||
this.props.onLoginRequest(login, password);
|
||||
this.setState({showErrorText: true});
|
||||
},
|
||||
render: function() {
|
||||
var title = null;
|
||||
@@ -1046,17 +1038,16 @@
|
||||
onNewTopic={this.props.onNewTopic}
|
||||
onCancel={this.props.onCancel} />
|
||||
|
||||
<SidepanelView.ErrorPanel
|
||||
showError={this.state.showErrorText}
|
||||
errorText={this.props.errorText} />
|
||||
<ErrorPanel
|
||||
level={this.props.errorLevel}
|
||||
text={this.props.errorText} />
|
||||
|
||||
{this.props.state === 'login' ?
|
||||
<LoginView login={this.props.login}
|
||||
disabled={this.props.loginDisabled}
|
||||
serverAddress={this.props.serverAddress}
|
||||
onLogin={this.handleLoginRequested}
|
||||
onServerAddressChange={this.props.onConnectionSettings}
|
||||
onClearError={this.handleClearErrorText} /> :
|
||||
onServerAddressChange={this.props.onConnectionSettings} /> :
|
||||
|
||||
this.props.state === 'register' ?
|
||||
<CreateAccountView
|
||||
@@ -1095,16 +1086,31 @@
|
||||
}
|
||||
});
|
||||
|
||||
SidepanelView.ErrorPanel = React.createClass({
|
||||
var ErrorPanel = React.createClass({
|
||||
getInitialState: function() {
|
||||
return {
|
||||
show: false,
|
||||
};
|
||||
},
|
||||
|
||||
componentWillReceiveProps: function(newProps) {
|
||||
this.setState({show: !(!newProps.level)});
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
this.setState({show: false});
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var errorClass = null;
|
||||
var errorText = ' ';
|
||||
if (this.props.errorText && this.props.showError) {
|
||||
errorClass = "error-alert";
|
||||
errorText = this.props.errorText;
|
||||
}
|
||||
var icon = this.props.level == "err" ? "error": "warning";
|
||||
return (
|
||||
<div id="alert-box" className={errorClass}>{errorText}</div>
|
||||
<div className={this.state.show ?
|
||||
(this.props.level == "err" ? "alert-box error" : "alert-box warning") :
|
||||
"alert-box"}>
|
||||
<div className="icon"><i className="material-icons">{icon}</i></div>
|
||||
{this.props.text}
|
||||
<div className="cancel"><MenuCancel onCancel={this.hide} /></div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -1891,8 +1897,6 @@
|
||||
resetDesc: function(topic) {
|
||||
var defacs = topic.getDefaultAccess() || {};
|
||||
var acs = topic.getAccessMode();
|
||||
console.log("InfoView: reset desc");
|
||||
console.log(topic.public);
|
||||
this.setState({
|
||||
owner: acs && acs.isOwner(),
|
||||
admin: acs && acs.isAdmin(),
|
||||
@@ -2104,6 +2108,10 @@
|
||||
<MenuCancel onCancel={this.props.onCancel} />
|
||||
</div>
|
||||
</div>
|
||||
{this.props.displayMobile ?
|
||||
<ErrorPanel
|
||||
level={this.props.errorLevel}
|
||||
text={this.props.errorText} /> : null}
|
||||
{this.state.showMemberPanel ?
|
||||
<GroupManager
|
||||
members={this.state.contactList}
|
||||
@@ -2381,6 +2389,7 @@
|
||||
this.propsChange(nextProps);
|
||||
},
|
||||
propsChange: function(props) {
|
||||
var instance = this;
|
||||
if (!props || !props.topic) {
|
||||
this.setState({messages: [], topic: null});
|
||||
this.leave();
|
||||
@@ -2405,7 +2414,9 @@
|
||||
.withLaterDesc()
|
||||
.withLaterSub()
|
||||
.withLaterData(MESSAGES_PAGE)
|
||||
.build());
|
||||
.build()).catch(function(err){
|
||||
instance.props.onError(err.message, "err");
|
||||
});
|
||||
}
|
||||
|
||||
// The user switched to the new topic before the timer for
|
||||
@@ -2425,7 +2436,10 @@
|
||||
var oldTopic = Tinode.getTopic(this.state.topic);
|
||||
if (oldTopic) {
|
||||
if (oldTopic.isSubscribed()) {
|
||||
oldTopic.leave(false);
|
||||
oldTopic.leave(false).catch(function(err) {
|
||||
// do nothing
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
oldTopic.onData = undefined;
|
||||
oldTopic.onInfo = undefined;
|
||||
@@ -2454,6 +2468,9 @@
|
||||
newState.fetchingMessages = true;
|
||||
topic.getMessagesPage(MESSAGES_PAGE).then(function() {
|
||||
instance.setState({fetchingMessages: false});
|
||||
}).catch(function(err) {
|
||||
instance.setState({fetchingMessages: false});
|
||||
instance.props.onError(err.message, "err");
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -2623,6 +2640,10 @@
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
{this.props.displayMobile ?
|
||||
<ErrorPanel
|
||||
level={this.props.errorLevel}
|
||||
text={this.props.errorText} /> : null}
|
||||
<LoadSpinner show={this.state.fetchingMessages} />
|
||||
<div id="messages-panel" ref={this.handleScrollReference}>
|
||||
<ul id="scroller" className={chatBoxClass}>
|
||||
@@ -2770,6 +2791,8 @@
|
||||
password: '',
|
||||
myUserId: null,
|
||||
errorText: '',
|
||||
errorLevel: null,
|
||||
liveConnection: navigator.onLine,
|
||||
topicSelected: '',
|
||||
loginDisabled: false,
|
||||
subscriptions: {},
|
||||
@@ -2788,7 +2811,11 @@
|
||||
};
|
||||
},
|
||||
componentDidMount: function() {
|
||||
var instance = this;
|
||||
window.addEventListener('resize', this.handleResize);
|
||||
window.addEventListener('online', function(e) { instance.handleOnline(true); });
|
||||
window.addEventListener('offline', function(e) { instance.handleOnline(false); });
|
||||
|
||||
Tinode.enableLogging(true, true);
|
||||
Tinode.onConnect = this.handleConnected;
|
||||
Tinode.onDisconnect = this.handleDisconnect;
|
||||
@@ -2798,25 +2825,39 @@
|
||||
tnSetup: function(serverAddress, transport) {
|
||||
Tinode.setup(APP_NAME, serverAddress, API_KEY, transport);
|
||||
},
|
||||
componentWillUnmount: function(){
|
||||
window.removeEventListener('resize', this.handleResize);
|
||||
},
|
||||
handleResize: function(){
|
||||
handleResize: function() {
|
||||
var mobile = document.documentElement.clientWidth <= MEDIA_BREAKPOINT;
|
||||
if (this.state.displayMobile != mobile) {
|
||||
this.setState({displayMobile: mobile});
|
||||
}
|
||||
},
|
||||
handleOnline: function(online) {
|
||||
var newState = {liveConnection: online};
|
||||
if (online) {
|
||||
this.handleError("", null);
|
||||
} else {
|
||||
this.handleError("No connection", "warn");
|
||||
}
|
||||
this.setState({liveConnection: online});
|
||||
},
|
||||
|
||||
handleError: function(err, level) {
|
||||
this.setState({errorText: err, errorLevel: level});
|
||||
},
|
||||
|
||||
// User clicked Login button in the side panel.
|
||||
handleLoginRequest: function(login, password) {
|
||||
var instance = this;
|
||||
this.setState({loginDisabled: true, errorText: '', login: login, password: password});
|
||||
this.setState({loginDisabled: true, login: login, password: password});
|
||||
this.handleError("", null);
|
||||
|
||||
if (Tinode.isConnected()) {
|
||||
this.doLogin(login, password);
|
||||
} else {
|
||||
Tinode.connect().catch(function(err) {
|
||||
// Socket error
|
||||
instance.setState({loginDisabled: false, errorText: err.message});
|
||||
instance.setState({loginDisabled: false});
|
||||
instance.handleError(err.message, "err");
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -2844,39 +2885,33 @@
|
||||
if (promise) {
|
||||
promise.then(function() {
|
||||
instance.handleLoginSuccessful(instance);
|
||||
})
|
||||
.catch(function(err) {
|
||||
}).catch(function(err) {
|
||||
// Login failed, report error
|
||||
instance.setState({loginDisabled: false, errorText: err.message});
|
||||
instance.setState({loginDisabled: false});
|
||||
instance.handleError(err.message, "err");
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
handleLoginSuccessful: function(instance) {
|
||||
instance.setState({errorText: ''});
|
||||
instance.handleError("", null);
|
||||
|
||||
// Logged in fine, subscribe to 'me' attaching callbacks from the contacts view.
|
||||
var me = Tinode.getMeTopic();
|
||||
me.onMetaDesc = instance.tnMeMetaDesc;
|
||||
instance.setState({sidePanelSelected: "contacts", myUserId: Tinode.getCurrentUserID()});
|
||||
// Subscribe, fetch topic desc, the list of subscriptions. Messages are not fetched.
|
||||
me.subscribe(me.startMetaQuery().withLaterSub().withDesc().build());
|
||||
me.subscribe(me.startMetaQuery().withLaterSub().withDesc().build()).catch(function(err){
|
||||
instance.handleError(err.message, "err");
|
||||
});
|
||||
},
|
||||
|
||||
handleDisconnect: function(err) {
|
||||
this.setState({
|
||||
sidePanelSelected: 'login',
|
||||
sidePanelTitle: null,
|
||||
sidePanelAvatar: null,
|
||||
dialogSelected: null,
|
||||
myUserId: null,
|
||||
errorText: err && err.message ? err.message : 'disconnected',
|
||||
topicSelected: '',
|
||||
errorText: err && err.message ? err.message : 'Disconnected',
|
||||
errorLevel: err && err.message ? "err" : "warn",
|
||||
loginDisabled: false,
|
||||
subscriptions: {},
|
||||
showInfoPanel: false,
|
||||
infoPanelShowMembers: false,
|
||||
mobilePanel: 'sidepanel',
|
||||
contextMenuVisible: false,
|
||||
contextMenuBounds: null,
|
||||
contextMenuClickAt: null,
|
||||
@@ -2907,11 +2942,14 @@
|
||||
var fnd = Tinode.getFndTopic();
|
||||
fnd.onSubsUpdated = this.tnFndSubsUpdated;
|
||||
fnd.onMetaDesc = this.tnFndMetaDesc;
|
||||
var instance = this;
|
||||
if (fnd.isSubscribed()) {
|
||||
this.setState({contactsSearchQuery: fnd.private ? fnd.private.toString() : ''});
|
||||
this.tnFndSubsUpdated();
|
||||
} else {
|
||||
fnd.subscribe(fnd.startMetaQuery().withSub().withLaterDesc().build());
|
||||
fnd.subscribe(fnd.startMetaQuery().withSub().withLaterDesc().build()).catch(function(err){
|
||||
instance.handleError(err.message, "err");
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -2933,10 +2971,13 @@
|
||||
@param query {Array} is an array of contacts to search for
|
||||
*/
|
||||
handleSearchContacts: function(query) {
|
||||
var fnd = Tinode.getFndTopic();
|
||||
fnd.setMeta({desc: {private: query}}).then(function(ctrl) {
|
||||
fnd.getMeta(fnd.startMetaQuery().withSub().withLaterDesc().build());
|
||||
});
|
||||
var fnd = Tinode.getFndTopic();
|
||||
var instance = this;
|
||||
fnd.setMeta({desc: {private: query}}).then(function(ctrl) {
|
||||
fnd.getMeta(fnd.startMetaQuery().withSub().withLaterDesc().build());
|
||||
}).catch(function(err){
|
||||
instance.handleError(err.message, "err");
|
||||
});
|
||||
},
|
||||
|
||||
// User clicked on a contact in the side panel or deleted a contact.
|
||||
@@ -2968,14 +3009,19 @@
|
||||
// User clicked on a message send button.
|
||||
handleSendMessage: function(msg) {
|
||||
var topic = Tinode.getTopic(this.state.topicSelected);
|
||||
var instance = this;
|
||||
// Check if the message is formatted.
|
||||
var dft = Drafty.parse(msg);
|
||||
if (Drafty.isPlainText(dft)) {
|
||||
// The message is simple text. Sned if as text/plain.
|
||||
topic.publish(msg);
|
||||
topic.publish(msg).catch(function(err) {
|
||||
instance.handleError(err.message, "err");
|
||||
});;
|
||||
} else {
|
||||
// Formatted message. Send it as a Drafty object.
|
||||
topic.publish(dft, undefined, Drafty.getContentType());
|
||||
topic.publish(dft, undefined, Drafty.getContentType()).catch(function(err) {
|
||||
instance.handleError(err.message, "err");
|
||||
});
|
||||
}
|
||||
},
|
||||
// User chose a Sign Up menu item.
|
||||
@@ -2990,21 +3036,24 @@
|
||||
.then(function() {
|
||||
return Tinode.createAccountBasic(login_, password_,
|
||||
{public: public_, private: private_, tags: tags_});
|
||||
})
|
||||
.then(function() {
|
||||
}).then(function() {
|
||||
instance.handleLoginSuccessful(instance);
|
||||
})
|
||||
.catch(function(err) {
|
||||
instance.setState({errorText: err.message});
|
||||
}).catch(function(err) {
|
||||
instance.handleError(err.message, "err");
|
||||
});
|
||||
},
|
||||
|
||||
handleUpdateAccountRequest: function(password, pub, priv) {
|
||||
var instance = this;
|
||||
if (pub || priv) {
|
||||
Tinode.getMeTopic().setMeta({desc: {public: pub, private: priv}});
|
||||
Tinode.getMeTopic().setMeta({desc: {public: pub, private: priv}}).catch(function(err) {
|
||||
instance.handleError(err.message, "err");
|
||||
});
|
||||
}
|
||||
if (password) {
|
||||
Tinode.updateAccountBasic(null, Tinode.getCurrentLogin(), password);
|
||||
Tinode.updateAccountBasic(null, Tinode.getCurrentLogin(), password).catch(function(err) {
|
||||
instance.handleError(err.message, "err");
|
||||
});
|
||||
}
|
||||
},
|
||||
// User chose Settings menu item.
|
||||
@@ -3043,7 +3092,6 @@
|
||||
|
||||
topic.subscribe(query.build(), setParams).then(function() {
|
||||
instance.setState({
|
||||
errorText: '',
|
||||
topicSelected: topic.name,
|
||||
sidePanelSelected: 'contacts',
|
||||
mobilePanel: 'topic-view',
|
||||
@@ -3051,11 +3099,12 @@
|
||||
infoPanelShowMembers: peerName ? false : true
|
||||
});
|
||||
}).catch(function(err) {
|
||||
instance.setState({errorText: err.message});
|
||||
instance.handleError(err.message, "err");
|
||||
});
|
||||
},
|
||||
|
||||
handleTopicUpdateRequest: function(topicName, pub, priv, permissions) {
|
||||
var instance = this;
|
||||
var topic = Tinode.getTopic(topicName);
|
||||
if (topic) {
|
||||
var params = {};
|
||||
@@ -3068,11 +3117,14 @@
|
||||
if (permissions) {
|
||||
params.defacs = permissions;
|
||||
}
|
||||
topic.setMeta({desc: params});
|
||||
topic.setMeta({desc: params}).catch(function(err) {
|
||||
instance.handleError(err.message, "err");
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
handleChangePermissions: function(topicName, mode, uid) {
|
||||
var instance = this;
|
||||
var topic = Tinode.getTopic(topicName);
|
||||
if (topic) {
|
||||
var am = topic.getAccessMode();
|
||||
@@ -3083,7 +3135,9 @@
|
||||
am.updateWant(mode);
|
||||
mode = am.getWant();
|
||||
}
|
||||
topic.setMeta({sub: {user: uid, mode: mode}});
|
||||
topic.setMeta({sub: {user: uid, mode: mode}}).catch(function(err) {
|
||||
instance.handleError(err.message, "err");
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
@@ -3100,6 +3154,8 @@
|
||||
showInfoPanel: false,
|
||||
infoPanelShowMembers: false
|
||||
});
|
||||
}).catch(function(err) {
|
||||
instance.handleError(err.message, "err");
|
||||
});
|
||||
},
|
||||
|
||||
@@ -3171,9 +3227,12 @@
|
||||
});
|
||||
}
|
||||
|
||||
var instance = this;
|
||||
if (removed && removed.length > 0) {
|
||||
removed.map(function(uid) {
|
||||
topic.delSubscription(uid);
|
||||
topic.delSubscription(uid).catch(function(err) {
|
||||
instance.handleError(err.message, "err");
|
||||
});;
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -3194,11 +3253,12 @@
|
||||
user={this.state.contextMenuUser}
|
||||
items={this.state.contextMenuItems}
|
||||
hide={this.handleHideContextMenu}
|
||||
onAction={this.handleContextMenuAction} />
|
||||
onAction={this.handleContextMenuAction}
|
||||
onError={this.handleError} />
|
||||
|
||||
<SidepanelView
|
||||
displayMobile={this.state.displayMobile}
|
||||
hideSelf={(this.state.displayMobile && this.state.mobilePanel !== 'sidepanel')}
|
||||
hideSelf={this.state.displayMobile && this.state.mobilePanel !== 'sidepanel'}
|
||||
state={this.state.sidePanelSelected}
|
||||
title={this.state.sidePanelTitle}
|
||||
avatar={this.state.sidePanelAvatar}
|
||||
@@ -3207,6 +3267,7 @@
|
||||
myUserId={this.state.myUserId}
|
||||
loginDisabled={this.state.loginDisabled}
|
||||
errorText={this.state.errorText}
|
||||
errorLevel={this.state.errorLevel}
|
||||
topicSelected={this.state.topicSelected}
|
||||
|
||||
serverAddress={this.state.serverAddress}
|
||||
@@ -3230,7 +3291,6 @@
|
||||
showContextMenu={this.handleShowContextMenu} />
|
||||
|
||||
<MessagesView
|
||||
onHideMessagesView={this.handleHideMessagesView}
|
||||
displayMobile={this.state.displayMobile}
|
||||
hideSelf={(this.state.displayMobile &&
|
||||
(this.state.mobilePanel !== 'topic-view' || this.state.showInfoPanel))}
|
||||
@@ -3238,15 +3298,24 @@
|
||||
myUserId={this.state.myUserId}
|
||||
serverVersion={this.state.serverVersion}
|
||||
serverAddress={this.state.serverAddress}
|
||||
errorText={this.state.errorText}
|
||||
errorLevel={this.state.errorLevel}
|
||||
|
||||
onHideMessagesView={this.handleHideMessagesView}
|
||||
onData={this.tnData}
|
||||
onError={this.handleError}
|
||||
showContextMenu={this.handleShowContextMenu}
|
||||
sendMessage={this.handleSendMessage} />
|
||||
|
||||
{this.state.showInfoPanel ?
|
||||
<InfoView
|
||||
displayMobile={this.state.displayMobile}
|
||||
topic={this.state.topicSelected}
|
||||
foundContacts={this.state.foundContacts}
|
||||
myUserId={this.state.myUserId}
|
||||
errorText={this.state.errorText}
|
||||
errorLevel={this.state.errorLevel}
|
||||
|
||||
showMemberPanel={this.state.infoPanelShowMembers}
|
||||
onTopicDescUpdate={this.handleTopicUpdateRequest}
|
||||
onCancel={this.handleHideInfoView}
|
||||
|
||||
Reference in New Issue
Block a user