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