diff --git a/src/components/structures/MatrixChat.js b/src/components/structures/MatrixChat.js
index af3f4d2598..e093e9dff9 100644
--- a/src/components/structures/MatrixChat.js
+++ b/src/components/structures/MatrixChat.js
@@ -1458,20 +1458,16 @@ export default createReactClass({
if (SettingsStore.isFeatureEnabled("feature_cross_signing")) {
cli.on("crypto.verification.request", request => {
- let requestObserver;
- if (request.event.getRoomId()) {
- requestObserver = new KeyVerificationStateObserver(
- request.event, MatrixClientPeg.get());
- }
-
- if (!requestObserver || requestObserver.pending) {
+ console.log(`MatrixChat got a .request ${request.channel.transactionId}`, request.event.getRoomId());
+ if (request.pending) {
+ console.log(`emitting toast for verification request with txnid ${request.channel.transactionId}`, request.event && request.event.getId());
dis.dispatch({
action: "show_toast",
toast: {
key: request.event.getId(),
title: _t("Verification Request"),
icon: "verification",
- props: {request, requestObserver},
+ props: {request},
component: sdk.getComponent("toasts.VerificationRequestToast"),
},
});
diff --git a/src/components/structures/RightPanel.js b/src/components/structures/RightPanel.js
index ff987a8f30..f5648a6d02 100644
--- a/src/components/structures/RightPanel.js
+++ b/src/components/structures/RightPanel.js
@@ -160,6 +160,7 @@ export default class RightPanel extends React.Component {
groupId: payload.groupId,
member: payload.member,
event: payload.event,
+ verificationRequest: payload.verificationRequest,
});
}
}
@@ -168,6 +169,7 @@ export default class RightPanel extends React.Component {
const MemberList = sdk.getComponent('rooms.MemberList');
const MemberInfo = sdk.getComponent('rooms.MemberInfo');
const UserInfo = sdk.getComponent('right_panel.UserInfo');
+ const EncryptionPanel = sdk.getComponent('right_panel.EncryptionPanel');
const ThirdPartyMemberInfo = sdk.getComponent('rooms.ThirdPartyMemberInfo');
const NotificationPanel = sdk.getComponent('structures.NotificationPanel');
const FilePanel = sdk.getComponent('structures.FilePanel');
@@ -235,6 +237,8 @@ export default class RightPanel extends React.Component {
panel = ;
} else if (this.state.phase === RIGHT_PANEL_PHASES.FilePanel) {
panel = ;
+ } else if (this.state.phase === RIGHT_PANEL_PHASES.EncryptionPanel) {
+ panel = ;
}
const classes = classNames("mx_RightPanel", "mx_fadable", {
diff --git a/src/components/structures/ToastContainer.js b/src/components/structures/ToastContainer.js
index a8dca35747..a9c8267d0d 100644
--- a/src/components/structures/ToastContainer.js
+++ b/src/components/structures/ToastContainer.js
@@ -26,6 +26,7 @@ export default class ToastContainer extends React.Component {
}
componentDidMount() {
+ console.log("ToastContainer mounted");
this._dispatcherRef = dis.register(this.onAction);
}
diff --git a/src/components/views/dialogs/DeviceVerifyDialog.js b/src/components/views/dialogs/DeviceVerifyDialog.js
index 6408245452..ca05d74964 100644
--- a/src/components/views/dialogs/DeviceVerifyDialog.js
+++ b/src/components/views/dialogs/DeviceVerifyDialog.js
@@ -100,9 +100,15 @@ export default class DeviceVerifyDialog extends React.Component {
if (!verifyingOwnDevice && SettingsStore.getValue("feature_cross_signing")) {
const roomId = await ensureDMExistsAndOpen(this.props.userId);
// throws upon cancellation before having started
- this._verifier = await client.requestVerificationDM(
+ const request = await client.requestVerificationDM(
this.props.userId, roomId, [verificationMethods.SAS],
);
+ await request.waitFor(r => r.ready || r.started);
+ if (request.ready) {
+ this._verifier = request.beginKeyVerification(verificationMethods.SAS);
+ } else {
+ this._verifier = request.verifier;
+ }
} else {
this._verifier = client.beginKeyVerification(
verificationMethods.SAS, this.props.userId, this.props.device.deviceId,
diff --git a/src/components/views/messages/MKeyVerificationRequest.js b/src/components/views/messages/MKeyVerificationRequest.js
index 4faa1b20aa..f31a823ac9 100644
--- a/src/components/views/messages/MKeyVerificationRequest.js
+++ b/src/components/views/messages/MKeyVerificationRequest.js
@@ -17,48 +17,62 @@ limitations under the License.
import React from 'react';
import PropTypes from 'prop-types';
import MatrixClientPeg from '../../../MatrixClientPeg';
-import {verificationMethods} from 'matrix-js-sdk/lib/crypto';
import sdk from '../../../index';
-import Modal from "../../../Modal";
import { _t } from '../../../languageHandler';
-import KeyVerificationStateObserver, {getNameForEventRoom, userLabelForEventRoom}
+import {getNameForEventRoom, userLabelForEventRoom}
from '../../../utils/KeyVerificationStateObserver';
+import dis from "../../../dispatcher";
+import {RIGHT_PANEL_PHASES} from "../../../stores/RightPanelStorePhases";
export default class MKeyVerificationRequest extends React.Component {
constructor(props) {
super(props);
- this.keyVerificationState = new KeyVerificationStateObserver(this.props.mxEvent, MatrixClientPeg.get(), () => {
- this.setState(this._copyState());
- });
- this.state = this._copyState();
- }
-
- _copyState() {
- const {accepted, done, cancelled, cancelPartyUserId, otherPartyUserId} = this.keyVerificationState;
- return {accepted, done, cancelled, cancelPartyUserId, otherPartyUserId};
}
componentDidMount() {
- this.keyVerificationState.attach();
+ const request = this.props.mxEvent.verificationRequest;
+ if (request) {
+ request.on("change", this._onRequestChanged);
+ }
}
componentWillUnmount() {
- this.keyVerificationState.detach();
+ const request = this.props.mxEvent.verificationRequest;
+ if (request) {
+ request.off("change", this._onRequestChanged);
+ }
}
- _onAcceptClicked = () => {
- const IncomingSasDialog = sdk.getComponent('views.dialogs.IncomingSasDialog');
- // todo: validate event, for example if it has sas in the methods.
- const verifier = MatrixClientPeg.get().acceptVerificationDM(this.props.mxEvent, verificationMethods.SAS);
- Modal.createTrackedDialog('Incoming Verification', '', IncomingSasDialog, {
- verifier,
- }, null, /* priority = */ false, /* static = */ true);
+ _onRequestChanged = () => {
+ this.forceUpdate();
};
- _onRejectClicked = () => {
- // todo: validate event, for example if it has sas in the methods.
- const verifier = MatrixClientPeg.get().acceptVerificationDM(this.props.mxEvent, verificationMethods.SAS);
- verifier.cancel("User declined");
+ _onAcceptClicked = async () => {
+ const request = this.props.mxEvent.verificationRequest;
+ if (request) {
+ try {
+ await request.accept();
+ dis.dispatch({action: "show_right_panel"});
+ dis.dispatch({
+ action: "set_right_panel_phase",
+ phase: RIGHT_PANEL_PHASES.EncryptionPanel,
+ verificationRequest: request,
+ });
+ } catch (err) {
+ console.error(err.message);
+ }
+ }
+ };
+
+ _onRejectClicked = async () => {
+ const request = this.props.mxEvent.verificationRequest;
+ if (request) {
+ try {
+ await request.cancel();
+ } catch (err) {
+ console.error(err.message);
+ }
+ }
};
_acceptedLabel(userId) {
@@ -83,45 +97,43 @@ export default class MKeyVerificationRequest extends React.Component {
render() {
const {mxEvent} = this.props;
- const fromUserId = mxEvent.getSender();
- const content = mxEvent.getContent();
- const toUserId = content.to;
- const client = MatrixClientPeg.get();
- const myUserId = client.getUserId();
- const isOwn = fromUserId === myUserId;
+ const request = mxEvent.verificationRequest;
let title;
let subtitle;
let stateNode;
- if (this.state.accepted || this.state.cancelled) {
+ if (!request) {
+ return
This is an invalid request, ho ho ho!
;
+ }
+
+ if (request.ready || request.started || request.cancelled) {
let stateLabel;
- if (this.state.accepted) {
- stateLabel = this._acceptedLabel(toUserId);
- } else if (this.state.cancelled) {
- stateLabel = this._cancelledLabel(this.state.cancelPartyUserId);
+ if (request.ready || request.started) {
+ stateLabel = this._acceptedLabel(request.receivingUserId);
+ } else if (request.cancelled) {
+ stateLabel = this._cancelledLabel(request.cancellingUserId);
}
stateNode = ({stateLabel}
);
}
- if (toUserId === myUserId) { // request sent to us
+ if (!request.initiatedByMe) {
title = ({
- _t("%(name)s wants to verify", {name: getNameForEventRoom(fromUserId, mxEvent)})}
);
+ _t("%(name)s wants to verify", {name: getNameForEventRoom(request.requestingUserId, mxEvent)})});
subtitle = ({
- userLabelForEventRoom(fromUserId, mxEvent)}
);
- const isResolved = !(this.state.accepted || this.state.cancelled || this.state.done);
- if (isResolved) {
+ userLabelForEventRoom(request.requestingUserId, mxEvent)});
+ if (request.requested) {
const FormButton = sdk.getComponent("elements.FormButton");
stateNode = (
);
}
- } else if (isOwn) { // request sent by us
+ } else { // request sent by us
title = ({
_t("You sent a verification request")}
);
subtitle = ({
- userLabelForEventRoom(this.state.otherPartyUserId, mxEvent)}
);
+ userLabelForEventRoom(request.receivingUserId, mxEvent)});
}
if (title) {
diff --git a/src/components/views/right_panel/EncryptionPanel.js b/src/components/views/right_panel/EncryptionPanel.js
new file mode 100644
index 0000000000..2050ad8072
--- /dev/null
+++ b/src/components/views/right_panel/EncryptionPanel.js
@@ -0,0 +1,33 @@
+/*
+Copyright 2015, 2016 OpenMarket Ltd
+Copyright 2017, 2018 Vector Creations Ltd
+Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
+Copyright 2019 The Matrix.org Foundation C.I.C.
+
+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';
+
+export default class EncryptionPanel extends React.PureComponent {
+ render() {
+ const request = this.props.verificationRequest;
+ if (request) {
+ return got a request, go straight to wizard
;
+ } else if (this.props.member) {
+ return show encryption options for member {this.props.member.name}
;
+ } else {
+ return nada
;
+ }
+ }
+}
diff --git a/src/components/views/right_panel/RoomHeaderButtons.js b/src/components/views/right_panel/RoomHeaderButtons.js
index f59159d1d9..2b5ea3aa27 100644
--- a/src/components/views/right_panel/RoomHeaderButtons.js
+++ b/src/components/views/right_panel/RoomHeaderButtons.js
@@ -27,6 +27,7 @@ import {RIGHT_PANEL_PHASES} from "../../../stores/RightPanelStorePhases";
const MEMBER_PHASES = [
RIGHT_PANEL_PHASES.RoomMemberList,
RIGHT_PANEL_PHASES.RoomMemberInfo,
+ RIGHT_PANEL_PHASES.EncryptionPanel,
RIGHT_PANEL_PHASES.Room3pidMemberInfo,
];
diff --git a/src/stores/RightPanelStore.js b/src/stores/RightPanelStore.js
index 02775b847b..1b3cb3d64b 100644
--- a/src/stores/RightPanelStore.js
+++ b/src/stores/RightPanelStore.js
@@ -123,7 +123,11 @@ export default class RightPanelStore extends Store {
if (payload.action === 'view_room' || payload.action === 'view_group') {
// Reset to the member list if we're viewing member info
- const memberInfoPhases = [RIGHT_PANEL_PHASES.RoomMemberInfo, RIGHT_PANEL_PHASES.Room3pidMemberInfo];
+ const memberInfoPhases = [
+ RIGHT_PANEL_PHASES.RoomMemberInfo,
+ RIGHT_PANEL_PHASES.Room3pidMemberInfo,
+ RIGHT_PANEL_PHASES.EncryptionPanel,
+ ];
if (memberInfoPhases.includes(this._state.lastRoomPhase)) {
this._setState({lastRoomPhase: RIGHT_PANEL_PHASES.RoomMemberList, lastRoomPhaseParams: {}});
}
diff --git a/src/stores/RightPanelStorePhases.js b/src/stores/RightPanelStorePhases.js
index 96807ebf5b..7783f960d6 100644
--- a/src/stores/RightPanelStorePhases.js
+++ b/src/stores/RightPanelStorePhases.js
@@ -22,7 +22,7 @@ export const RIGHT_PANEL_PHASES = Object.freeze({
NotificationPanel: 'NotificationPanel',
RoomMemberInfo: 'RoomMemberInfo',
Room3pidMemberInfo: 'Room3pidMemberInfo',
-
+ EncryptionPanel: 'EncryptionPanel',
// Group stuff
GroupMemberList: 'GroupMemberList',
GroupRoomList: 'GroupRoomList',
diff --git a/src/utils/KeyVerificationStateObserver.js b/src/utils/KeyVerificationStateObserver.js
index 2f7c0367ad..7e33c29214 100644
--- a/src/utils/KeyVerificationStateObserver.js
+++ b/src/utils/KeyVerificationStateObserver.js
@@ -161,6 +161,7 @@ export default class KeyVerificationStateObserver {
}
this.otherPartyUserId = fromUserId === this._client.getUserId() ? toUserId : fromUserId;
+ console.log("KeyVerificationStateObserver update for txnId", this._requestEvent.getId(), {accepted: this.accepted, cancelled: this.cancelled, done: this.done});
}
}