Merge pull request #243 from matrix-org/dbkr/error_messages

Add better user-facing error messages
pull/21833/head
David Baker 2016-03-22 17:41:00 +00:00
commit abe4df5f1c
10 changed files with 176 additions and 21 deletions

View File

@ -46,6 +46,7 @@ module.exports.components['views.create_room.Presets'] = require('./components/v
module.exports.components['views.create_room.RoomAlias'] = require('./components/views/create_room/RoomAlias');
module.exports.components['views.dialogs.ErrorDialog'] = require('./components/views/dialogs/ErrorDialog');
module.exports.components['views.dialogs.LogoutPrompt'] = require('./components/views/dialogs/LogoutPrompt');
module.exports.components['views.dialogs.NeedToRegisterDialog'] = require('./components/views/dialogs/NeedToRegisterDialog');
module.exports.components['views.dialogs.QuestionDialog'] = require('./components/views/dialogs/QuestionDialog');
module.exports.components['views.dialogs.SetDisplayNameDialog'] = require('./components/views/dialogs/SetDisplayNameDialog');
module.exports.components['views.dialogs.TextInputDialog'] = require('./components/views/dialogs/TextInputDialog');

View File

@ -464,9 +464,18 @@ module.exports = React.createClass({
//this.notifyNewScreen('new');
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog");
var Loader = sdk.getComponent("elements.Spinner");
var modal = Modal.createDialog(Loader);
if (MatrixClientPeg.get().isGuest) {
Modal.createDialog(NeedToRegisterDialog, {
title: "Please Register",
description: "Guest users can't create new rooms. Please register to create room and start a chat."
});
return;
}
// XXX: FIXME: deduplicate this with MemberInfo's 'start chat' impl
MatrixClientPeg.get().createRoom({
preset: "private_chat",

View File

@ -575,12 +575,28 @@ module.exports = React.createClass({
});
if (!error) return;
var msg = error.message ? error.message : JSON.stringify(error);
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createDialog(ErrorDialog, {
title: "Failed to join room",
description: msg
});
// https://matrix.org/jira/browse/SYN-659
if (
error.errcode == 'M_GUEST_ACCESS_FORBIDDEN' ||
(
error.errcode == 'M_FORBIDDEN' &&
MatrixClientPeg.get().isGuest()
)
) {
var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog");
Modal.createDialog(NeedToRegisterDialog, {
title: "Failed to join the room",
description: "This room is private or inaccessible to guests. You may be able to join if you register."
});
} else {
var msg = error.message ? error.message : JSON.stringify(error);
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createDialog(ErrorDialog, {
title: "Failed to join room",
description: msg
});
}
});
this.setState({
joining: true

View File

@ -570,9 +570,15 @@ var TimelinePanel = React.createClass({
});
};
}
var message = "Vector was trying to load a specific point in this room's timeline but ";
if (error.errcode == 'M_FORBIDDEN') {
message += "you do not have permission to view the message in question.";
} else {
message += "was unable to find it.";
}
Modal.createDialog(ErrorDialog, {
title: "Failed to load event",
description: msg,
title: "Failed to load timeline position",
description: message,
onFinished: onFinished,
});
}

View File

@ -91,9 +91,9 @@ module.exports = React.createClass({
onAvatarPickerClick: function(ev) {
if (MatrixClientPeg.get().isGuest()) {
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createDialog(ErrorDialog, {
title: "Error",
var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog");
Modal.createDialog(NeedToRegisterDialog, {
title: "Please Register",
description: "Guests can't set avatars. Please register.",
});
return;

View File

@ -20,7 +20,7 @@ limitations under the License.
* title: "some text", (default: "Error")
* description: "some more text",
* button: "Button Text",
* onClose: someFunction,
* onFinished: someFunction,
* focus: true|false (default: true)
* });
*/

View File

@ -0,0 +1,76 @@
/*
Copyright 2016 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
/*
* Usage:
* Modal.createDialog(NeedToRegisterDialog, {
* title: "some text", (default: "Registration required")
* description: "some more text",
* onFinished: someFunction,
* });
*/
var React = require("react");
var dis = require("../../../dispatcher");
module.exports = React.createClass({
displayName: 'NeedToRegisterDialog',
propTypes: {
title: React.PropTypes.string,
description: React.PropTypes.oneOfType([
React.PropTypes.element,
React.PropTypes.string,
]),
onFinished: React.PropTypes.func.isRequired,
},
getDefaultProps: function() {
return {
title: "Registration required",
description: "A registered account is required for this action",
};
},
onRegisterClicked: function() {
dis.dispatch({
action: "start_upgrade_registration",
});
if (this.props.onFinished) {
this.props.onFinished();
}
},
render: function() {
return (
<div className="mx_NeedToRegisterDialog">
<div className="mx_Dialog_title">
{this.props.title}
</div>
<div className="mx_Dialog_content">
{this.props.description}
</div>
<div className="mx_Dialog_buttons">
<button onClick={this.onRegisterClicked}>
Register
</button>
<button onClick={this.props.onFinished} autoFocus={true}>
Cancel
</button>
</div>
</div>
);
}
});

View File

@ -16,8 +16,10 @@ limitations under the License.
var q = require("q");
var React = require('react');
var sdk = require('../../../index');
var Tinter = require('../../../Tinter');
var MatrixClientPeg = require("../../../MatrixClientPeg");
var Modal = require("../../../Modal");
var ROOM_COLORS = [
// magic room default values courtesy of Ribot
@ -74,12 +76,23 @@ module.exports = React.createClass({
if (originalState.primary_color !== this.state.primary_color ||
originalState.secondary_color !== this.state.secondary_color) {
console.log("ColorSettings: Saving new color");
// We would like guests to be able to set room colour but currently
// they can't, so we still send the request but display a sensible
// error if it fails.
return MatrixClientPeg.get().setRoomAccountData(
this.props.room.roomId, "org.matrix.room.color_scheme", {
primary_color: this.state.primary_color,
secondary_color: this.state.secondary_color
}
);
).catch(function(err) {
if (err.errcode == 'M_GUEST_ACCESS_FORBIDDEN') {
var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog");
Modal.createDialog(NeedToRegisterDialog, {
title: "Please Register",
description: "Saving room color settings is only available to registered users"
});
}
});
}
return q(); // no color diff
},

View File

@ -170,10 +170,18 @@ module.exports = React.createClass({
// get out of sync if we force setState here!
console.log("Mod toggle success");
}, function(err) {
Modal.createDialog(ErrorDialog, {
title: "Mod error",
description: err.message
});
if (err.errcode == 'M_GUEST_ACCESS_FORBIDDEN') {
var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog");
Modal.createDialog(NeedToRegisterDialog, {
title: "Please Register",
description: "This action cannot be performed by a guest user. Please register to be able to do this."
});
} else {
Modal.createDialog(ErrorDialog, {
title: "Mod error",
description: err.message
});
}
}
);
this.props.onFinished();
@ -293,6 +301,16 @@ module.exports = React.createClass({
}
else {
self.setState({ creatingRoom: true });
if (MatrixClientPeg.get().isGuest()) {
var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog");
Modal.createDialog(NeedToRegisterDialog, {
title: "Please Register",
description: "Guest users can't create new rooms. Please register to create room and start a chat."
});
return;
}
MatrixClientPeg.get().createRoom({
// XXX: FIXME: deduplicate this with "view_create_room" in MatrixChat
invite: [this.props.member.userId],

View File

@ -142,9 +142,18 @@ module.exports = React.createClass({
onInvite: function(inputText) {
var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
var NeedToRegisterDialog = sdk.getComponent("dialogs.NeedToRegisterDialog");
var self = this;
inputText = inputText.trim(); // react requires es5-shim so we know trim() exists
if (MatrixClientPeg.get().isGuest()) {
Modal.createDialog(NeedToRegisterDialog, {
title: "Unable to Invite",
description: "Guest user can't invite new users. Please register to be able to invite new users into a room."
});
return;
}
// email addresses and user IDs do not allow space, comma, semicolon so split
// on them for bulk inviting.
var separators =[ ";", " ", "," ];
@ -222,10 +231,17 @@ module.exports = React.createClass({
}, function(err) {
if (err !== null) {
console.error("Failed to invite: %s", JSON.stringify(err));
Modal.createDialog(ErrorDialog, {
title: "Server error whilst inviting",
description: err.message
});
if (err.errcode == 'M_FORBIDDEN') {
Modal.createDialog(ErrorDialog, {
title: "Unable to Invite",
description: "You do not have permission to invite people to this room."
});
} else {
Modal.createDialog(ErrorDialog, {
title: "Server error whilst inviting",
description: err.message
});
}
}
}).finally(function() {
self.setState({