diff --git a/src/SignupStages.js b/src/SignupStages.js
index cdb9d5989b..1441682c85 100644
--- a/src/SignupStages.js
+++ b/src/SignupStages.js
@@ -149,6 +149,7 @@ class EmailIdentityStage extends Stage {
nextLink
).then(function(response) {
self.sid = response.sid;
+ self.signupInstance.setIdSid(self.sid);
return self._completeVerify();
}).then(function(request) {
request.poll_for_success = true;
diff --git a/src/component-index.js b/src/component-index.js
index b357472ad7..62d26d4ce7 100644
--- a/src/component-index.js
+++ b/src/component-index.js
@@ -77,6 +77,8 @@ import views$dialogs$BaseDialog from './components/views/dialogs/BaseDialog';
views$dialogs$BaseDialog && (module.exports.components['views.dialogs.BaseDialog'] = views$dialogs$BaseDialog);
import views$dialogs$ChatInviteDialog from './components/views/dialogs/ChatInviteDialog';
views$dialogs$ChatInviteDialog && (module.exports.components['views.dialogs.ChatInviteDialog'] = views$dialogs$ChatInviteDialog);
+import views$dialogs$ConfirmUserActionDialog from './components/views/dialogs/ConfirmUserActionDialog';
+views$dialogs$ConfirmUserActionDialog && (module.exports.components['views.dialogs.ConfirmUserActionDialog'] = views$dialogs$ConfirmUserActionDialog);
import views$dialogs$DeactivateAccountDialog from './components/views/dialogs/DeactivateAccountDialog';
views$dialogs$DeactivateAccountDialog && (module.exports.components['views.dialogs.DeactivateAccountDialog'] = views$dialogs$DeactivateAccountDialog);
import views$dialogs$ErrorDialog from './components/views/dialogs/ErrorDialog';
diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js
index 87cd2645db..72680a3eac 100644
--- a/src/components/structures/MatrixChat.js
+++ b/src/components/structures/MatrixChat.js
@@ -217,6 +217,12 @@ module.exports = React.createClass({
window.localStorage.getItem('mx_team_token') ||
window.sessionStorage.getItem('mx_team_token');
+ // Some users have ended up with "undefined" as their local storage team token,
+ // treat that as undefined.
+ if (this._teamToken === "undefined") {
+ this._teamToken = undefined;
+ }
+
if (this._teamToken) {
console.info(`Team token set to ${this._teamToken}`);
}
@@ -904,14 +910,6 @@ module.exports = React.createClass({
onUserClick: function(event, userId) {
event.preventDefault();
- // var MemberInfo = sdk.getComponent('rooms.MemberInfo');
- // var member = new Matrix.RoomMember(null, userId);
- // ContextualMenu.createMenu(MemberInfo, {
- // member: member,
- // right: window.innerWidth - event.pageX,
- // top: event.pageY
- // });
-
var member = new Matrix.RoomMember(null, userId);
if (!member) { return; }
dis.dispatch({
diff --git a/src/components/views/dialogs/ConfirmUserActionDialog.js b/src/components/views/dialogs/ConfirmUserActionDialog.js
new file mode 100644
index 0000000000..fbe719710b
--- /dev/null
+++ b/src/components/views/dialogs/ConfirmUserActionDialog.js
@@ -0,0 +1,83 @@
+/*
+Copyright 2017 Vector Creations 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.
+*/
+
+import React from 'react';
+import sdk from '../../../index';
+import classnames from 'classnames';
+
+/*
+ * A dialog for confirming an operation on another user.
+ * Takes a user ID and a verb, displays the target user prominently
+ * such that it should be easy to confirm that the operation is being
+ * performed on the right person, and displays the operation prominently
+ * to make it obvious what is going to happen.
+ * Also tweaks the style for 'dangerous' actions (albeit only with colour)
+ */
+export default React.createClass({
+ displayName: 'ConfirmUserActionDialog',
+ propTypes: {
+ member: React.PropTypes.object.isRequired, // matrix-js-sdk member object
+ action: React.PropTypes.string.isRequired, // eg. 'Ban'
+ danger: React.PropTypes.bool,
+ onFinished: React.PropTypes.func.isRequired,
+ },
+
+ defaultProps: {
+ danger: false,
+ },
+
+ onOk: function() {
+ this.props.onFinished(true);
+ },
+
+ onCancel: function() {
+ this.props.onFinished(false);
+ },
+
+ render: function() {
+ const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
+ const MemberAvatar = sdk.getComponent("views.avatars.MemberAvatar");
+
+ const title = this.props.action + " this person?";
+ const confirmButtonClass = classnames({
+ 'mx_Dialog_primary': true,
+ 'danger': this.props.danger,
+ });
+ return (
+
+
- You are about to taken to a third-party site so you can authenticate your account for use with {integrationsUrl}.
+ You are about to be taken to a third-party site so you can
+ authenticate your account for use with {integrationsUrl}.
Do you wish to continue?
,
button: "Continue",
diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js
index d33b8f3524..fc2df0a5cc 100644
--- a/src/components/views/rooms/MemberInfo.js
+++ b/src/components/views/rooms/MemberInfo.js
@@ -1,5 +1,6 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2017 Vector Creations Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -25,16 +26,16 @@ limitations under the License.
* 'muted': boolean,
* 'isTargetMod': boolean
*/
-var React = require('react');
-var classNames = require('classnames');
-var dis = require("../../../dispatcher");
-var Modal = require("../../../Modal");
-var sdk = require('../../../index');
-var createRoom = require('../../../createRoom');
-var DMRoomMap = require('../../../utils/DMRoomMap');
-var Unread = require('../../../Unread');
-var Receipt = require('../../../utils/Receipt');
-var WithMatrixClient = require('../../../wrappers/WithMatrixClient');
+import React from 'react';
+import classNames from 'classnames';
+import dis from '../../../dispatcher';
+import Modal from '../../../Modal';
+import sdk from '../../../index';
+import createRoom from '../../../createRoom';
+import DMRoomMap from '../../../utils/DMRoomMap';
+import Unread from '../../../Unread';
+import { findReadReceiptFromUserId } from '../../../utils/Receipt';
+import WithMatrixClient from '../../../wrappers/WithMatrixClient';
import AccessibleButton from '../elements/AccessibleButton';
module.exports = WithMatrixClient(React.createClass({
@@ -43,13 +44,6 @@ module.exports = WithMatrixClient(React.createClass({
propTypes: {
matrixClient: React.PropTypes.object.isRequired,
member: React.PropTypes.object.isRequired,
- onFinished: React.PropTypes.func,
- },
-
- getDefaultProps: function() {
- return {
- onFinished: function() {}
- };
},
getInitialState: function() {
@@ -164,7 +158,7 @@ module.exports = WithMatrixClient(React.createClass({
onRoomReceipt: function(receiptEvent, room) {
// because if we read a notification, it will affect notification count
// only bother updating if there's a receipt from us
- if (Receipt.findReadReceiptFromUserId(receiptEvent, this.props.matrixClient.credentials.userId)) {
+ if (findReadReceiptFromUserId(receiptEvent, this.props.matrixClient.credentials.userId)) {
this.forceUpdate();
}
},
@@ -224,46 +218,64 @@ module.exports = WithMatrixClient(React.createClass({
},
onKick: function() {
- var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
- var roomId = this.props.member.roomId;
- var target = this.props.member.userId;
- this.setState({ updating: this.state.updating + 1 });
- this.props.matrixClient.kick(roomId, target).then(function() {
- // NO-OP; rely on the m.room.member event coming down else we could
- // get out of sync if we force setState here!
- console.log("Kick success");
- }, function(err) {
- Modal.createDialog(ErrorDialog, {
- title: "Kick error",
- description: err.message
+ const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog");
+ Modal.createDialog(ConfirmUserActionDialog, {
+ member: this.props.member,
+ action: 'Kick',
+ danger: true,
+ onFinished: (proceed) => {
+ if (!proceed) return;
+
+ this.setState({ updating: this.state.updating + 1 });
+ this.props.matrixClient.kick(
+ this.props.member.roomId, this.props.member.userId,
+ ).then(function() {
+ // NO-OP; rely on the m.room.member event coming down else we could
+ // get out of sync if we force setState here!
+ console.log("Kick success");
+ }, function(err) {
+ const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
+ Modal.createDialog(ErrorDialog, {
+ title: "Kick error",
+ description: err.message
+ });
+ }
+ ).finally(()=>{
+ this.setState({ updating: this.state.updating - 1 });
});
}
- ).finally(()=>{
- this.setState({ updating: this.state.updating - 1 });
});
- this.props.onFinished();
},
onBan: function() {
- var ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
- var roomId = this.props.member.roomId;
- var target = this.props.member.userId;
- this.setState({ updating: this.state.updating + 1 });
- this.props.matrixClient.ban(roomId, target).then(
- function() {
- // NO-OP; rely on the m.room.member event coming down else we could
- // get out of sync if we force setState here!
- console.log("Ban success");
- }, function(err) {
- Modal.createDialog(ErrorDialog, {
- title: "Ban error",
- description: err.message
+ const ConfirmUserActionDialog = sdk.getComponent("dialogs.ConfirmUserActionDialog");
+ Modal.createDialog(ConfirmUserActionDialog, {
+ member: this.props.member,
+ action: 'Ban',
+ danger: true,
+ onFinished: (proceed) => {
+ if (!proceed) return;
+
+ this.setState({ updating: this.state.updating + 1 });
+ this.props.matrixClient.ban(
+ this.props.member.roomId, this.props.member.userId,
+ ).then(
+ function() {
+ // NO-OP; rely on the m.room.member event coming down else we could
+ // get out of sync if we force setState here!
+ console.log("Ban success");
+ }, function(err) {
+ const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
+ Modal.createDialog(ErrorDialog, {
+ title: "Ban error",
+ description: err.message,
+ });
+ }
+ ).finally(()=>{
+ this.setState({ updating: this.state.updating - 1 });
});
- }
- ).finally(()=>{
- this.setState({ updating: this.state.updating - 1 });
+ },
});
- this.props.onFinished();
},
onMuteToggle: function() {
@@ -272,14 +284,12 @@ module.exports = WithMatrixClient(React.createClass({
var target = this.props.member.userId;
var room = this.props.matrixClient.getRoom(roomId);
if (!room) {
- this.props.onFinished();
return;
}
var powerLevelEvent = room.currentState.getStateEvents(
"m.room.power_levels", ""
);
if (!powerLevelEvent) {
- this.props.onFinished();
return;
}
var isMuted = this.state.muted;
@@ -314,7 +324,6 @@ module.exports = WithMatrixClient(React.createClass({
this.setState({ updating: this.state.updating - 1 });
});
}
- this.props.onFinished();
},
onModToggle: function() {
@@ -323,19 +332,16 @@ module.exports = WithMatrixClient(React.createClass({
var target = this.props.member.userId;
var room = this.props.matrixClient.getRoom(roomId);
if (!room) {
- this.props.onFinished();
return;
}
var powerLevelEvent = room.currentState.getStateEvents(
"m.room.power_levels", ""
);
if (!powerLevelEvent) {
- this.props.onFinished();
return;
}
var me = room.getMember(this.props.matrixClient.credentials.userId);
if (!me) {
- this.props.onFinished();
return;
}
var defaultLevel = powerLevelEvent.getContent().users_default;
@@ -366,7 +372,6 @@ module.exports = WithMatrixClient(React.createClass({
).finally(()=>{
this.setState({ updating: this.state.updating - 1 });
});
- this.props.onFinished();
},
_applyPowerChange: function(roomId, target, powerLevel, powerLevelEvent) {
@@ -386,7 +391,6 @@ module.exports = WithMatrixClient(React.createClass({
).finally(()=>{
this.setState({ updating: this.state.updating - 1 });
}).done();
- this.props.onFinished();
},
onPowerChange: function(powerLevel) {
@@ -396,14 +400,12 @@ module.exports = WithMatrixClient(React.createClass({
var room = this.props.matrixClient.getRoom(roomId);
var self = this;
if (!room) {
- this.props.onFinished();
return;
}
var powerLevelEvent = room.currentState.getStateEvents(
"m.room.power_levels", ""
);
if (!powerLevelEvent) {
- this.props.onFinished();
return;
}
if (powerLevelEvent.getContent().users) {
@@ -422,9 +424,6 @@ module.exports = WithMatrixClient(React.createClass({
if (confirmed) {
self._applyPowerChange(roomId, target, powerLevel, powerLevelEvent);
}
- else {
- self.props.onFinished();
- }
},
});
}
@@ -440,7 +439,6 @@ module.exports = WithMatrixClient(React.createClass({
onNewDMClick: function() {
this.setState({ updating: this.state.updating + 1 });
createRoom({dmUserId: this.props.member.userId}).finally(() => {
- this.props.onFinished();
this.setState({ updating: this.state.updating - 1 });
}).done();
},
@@ -450,7 +448,6 @@ module.exports = WithMatrixClient(React.createClass({
action: 'leave_room',
room_id: this.props.member.roomId,
});
- this.props.onFinished();
},
_calculateOpsPermissions: function(member) {