diff --git a/src/component-index.js b/src/component-index.js index 869d60f204..67c09e61a6 100644 --- a/src/component-index.js +++ b/src/component-index.js @@ -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'); diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js index c16b80ec62..459847ce88 100644 --- a/src/components/structures/MatrixChat.js +++ b/src/components/structures/MatrixChat.js @@ -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", diff --git a/src/components/structures/RoomView.js b/src/components/structures/RoomView.js index 4598b7b9c8..7f4d8ea91a 100644 --- a/src/components/structures/RoomView.js +++ b/src/components/structures/RoomView.js @@ -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 diff --git a/src/components/structures/TimelinePanel.js b/src/components/structures/TimelinePanel.js index d28b0b448f..fe0a435b7e 100644 --- a/src/components/structures/TimelinePanel.js +++ b/src/components/structures/TimelinePanel.js @@ -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, }); } diff --git a/src/components/structures/UserSettings.js b/src/components/structures/UserSettings.js index 99198ac691..2ba9caa4e3 100644 --- a/src/components/structures/UserSettings.js +++ b/src/components/structures/UserSettings.js @@ -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; diff --git a/src/components/views/dialogs/ErrorDialog.js b/src/components/views/dialogs/ErrorDialog.js index c3f4ca6a55..b3278dfcfe 100644 --- a/src/components/views/dialogs/ErrorDialog.js +++ b/src/components/views/dialogs/ErrorDialog.js @@ -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) * }); */ diff --git a/src/components/views/dialogs/NeedToRegisterDialog.js b/src/components/views/dialogs/NeedToRegisterDialog.js new file mode 100644 index 0000000000..a6b548881e --- /dev/null +++ b/src/components/views/dialogs/NeedToRegisterDialog.js @@ -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 ( +
+
+ {this.props.title} +
+
+ {this.props.description} +
+
+ + +
+
+ ); + } +}); diff --git a/src/components/views/room_settings/ColorSettings.js b/src/components/views/room_settings/ColorSettings.js index bf931b6c05..fff97ea817 100644 --- a/src/components/views/room_settings/ColorSettings.js +++ b/src/components/views/room_settings/ColorSettings.js @@ -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 }, diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js index e1765acdcf..fd08b393e4 100644 --- a/src/components/views/rooms/MemberInfo.js +++ b/src/components/views/rooms/MemberInfo.js @@ -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], diff --git a/src/components/views/rooms/MemberList.js b/src/components/views/rooms/MemberList.js index b15e5bdc94..102e33dbd4 100644 --- a/src/components/views/rooms/MemberList.js +++ b/src/components/views/rooms/MemberList.js @@ -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({