Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Merge pull request #243 from matrix-org/dbkr/error_messages
Browse files Browse the repository at this point in the history
Add better user-facing error messages
  • Loading branch information
dbkr committed Mar 22, 2016
2 parents 0737d89 + 87d853d commit abe4df5
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 21 deletions.
1 change: 1 addition & 0 deletions src/component-index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down
9 changes: 9 additions & 0 deletions src/components/structures/MatrixChat.js
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
28 changes: 22 additions & 6 deletions src/components/structures/RoomView.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 8 additions & 2 deletions src/components/structures/TimelinePanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
});
}
Expand Down
6 changes: 3 additions & 3 deletions src/components/structures/UserSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion src/components/views/dialogs/ErrorDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)
* });
*/
Expand Down
76 changes: 76 additions & 0 deletions src/components/views/dialogs/NeedToRegisterDialog.js
Original file line number Diff line number Diff line change
@@ -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>
);
}
});
15 changes: 14 additions & 1 deletion src/components/views/room_settings/ColorSettings.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
},
Expand Down
26 changes: 22 additions & 4 deletions src/components/views/rooms/MemberInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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],
Expand Down
24 changes: 20 additions & 4 deletions src/components/views/rooms/MemberList.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 =[ ";", " ", "," ];
Expand Down Expand Up @@ -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({
Expand Down

0 comments on commit abe4df5

Please sign in to comment.