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 #1300 from matrix-org/dbkr/userpicker
Browse files Browse the repository at this point in the history
Refactor ChatInviteDialog to be UserPickerDialog
  • Loading branch information
dbkr committed Aug 16, 2017
2 parents b5f959c + 753ea38 commit 252ab20
Show file tree
Hide file tree
Showing 8 changed files with 230 additions and 289 deletions.
2 changes: 0 additions & 2 deletions .eslintignore.errorfiles
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ src/components/views/create_room/CreateRoomButton.js
src/components/views/create_room/Presets.js
src/components/views/create_room/RoomAlias.js
src/components/views/dialogs/ChatCreateOrReuseDialog.js
src/components/views/dialogs/ChatInviteDialog.js
src/components/views/dialogs/DeactivateAccountDialog.js
src/components/views/dialogs/InteractiveAuthDialog.js
src/components/views/dialogs/SetMxIdDialog.js
Expand Down Expand Up @@ -114,7 +113,6 @@ src/components/views/settings/EnableNotificationsButton.js
src/ContentMessages.js
src/HtmlUtils.js
src/ImageUtils.js
src/Invite.js
src/languageHandler.js
src/linkify-matrix.js
src/Login.js
Expand Down
134 changes: 113 additions & 21 deletions src/Invite.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*
Copyright 2016 OpenMarket Ltd
Copyright 2017 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand All @@ -16,24 +17,11 @@ limitations under the License.

import MatrixClientPeg from './MatrixClientPeg';
import MultiInviter from './utils/MultiInviter';

const emailRegex = /^\S+@\S+\.\S+$/;

const mxidRegex = /^@\S+:\S+$/

export function getAddressType(inputText) {
const isEmailAddress = emailRegex.test(inputText);
const isMatrixId = mxidRegex.test(inputText);

// sanity check the input for user IDs
if (isEmailAddress) {
return 'email';
} else if (isMatrixId) {
return 'mx';
} else {
return null;
}
}
import Modal from './Modal';
import { getAddressType } from './UserAddress';
import createRoom from './createRoom';
import sdk from './';
import { _t } from './languageHandler';

export function inviteToRoom(roomId, addr) {
const addrType = getAddressType(addr);
Expand All @@ -52,12 +40,116 @@ export function inviteToRoom(roomId, addr) {
* Simpler interface to utils/MultiInviter but with
* no option to cancel.
*
* @param {roomId} The ID of the room to invite to
* @param {array} Array of strings of addresses to invite. May be matrix IDs or 3pids.
* @returns Promise
* @param {string} roomId The ID of the room to invite to
* @param {string[]} addrs Array of strings of addresses to invite. May be matrix IDs or 3pids.
* @returns {Promise} Promise
*/
export function inviteMultipleToRoom(roomId, addrs) {
const inviter = new MultiInviter(roomId);
return inviter.invite(addrs);
}

export function showStartChatInviteDialog() {
const UserPickerDialog = sdk.getComponent("dialogs.UserPickerDialog");
Modal.createTrackedDialog('Start a chat', '', UserPickerDialog, {
title: _t('Start a chat'),
description: _t("Who would you like to communicate with?"),
placeholder: _t("Email, name or matrix ID"),
button: _t("Start Chat"),
onFinished: _onStartChatFinished,
});
}

export function showRoomInviteDialog(roomId) {
const UserPickerDialog = sdk.getComponent("dialogs.UserPickerDialog");
Modal.createTrackedDialog('Chat Invite', '', UserPickerDialog, {
title: _t('Invite new room members'),
description: _t('Who would you like to add to this room?'),
button: _t('Send Invites'),
placeholder: _t("Email, name or matrix ID"),
onFinished: (shouldInvite, addrs) => {
_onRoomInviteFinished(roomId, shouldInvite, addrs);
},
});
}

function _onStartChatFinished(shouldInvite, addrs) {
if (!shouldInvite) return;

const addrTexts = addrs.map((addr) => addr.address);

if (_isDmChat(addrTexts)) {
// Start a new DM chat
createRoom({dmUserId: addrTexts[0]}).catch((err) => {
console.error(err.stack);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to invite user', '', ErrorDialog, {
title: _t("Failed to invite user"),
description: ((err && err.message) ? err.message : _t("Operation failed")),
});
});
} else {
// Start multi user chat
let room;
createRoom().then((roomId) => {
room = MatrixClientPeg.get().getRoom(roomId);
return inviteMultipleToRoom(roomId, addrTexts);
}).then((addrs) => {
return _showAnyInviteErrors(addrs, room);
}).catch((err) => {
console.error(err.stack);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to invite', '', ErrorDialog, {
title: _t("Failed to invite"),
description: ((err && err.message) ? err.message : _t("Operation failed")),
});
});
}
}

function _onRoomInviteFinished(roomId, shouldInvite, addrs) {
if (!shouldInvite) return;

const addrTexts = addrs.map((addr) => addr.address);

// Invite new users to a room
inviteMultipleToRoom(roomId, addrTexts).then((addrs) => {
const room = MatrixClientPeg.get().getRoom(roomId);
return _showAnyInviteErrors(addrs, room);
}).catch((err) => {
console.error(err.stack);
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to invite', '', ErrorDialog, {
title: _t("Failed to invite"),
description: ((err && err.message) ? err.message : _t("Operation failed")),
});
});
}

function _isDmChat(addrTexts) {
if (addrTexts.length === 1 && getAddressType(addrTexts[0])) {
return true;
} else {
return false;
}
}

function _showAnyInviteErrors(addrs, room) {
// Show user any errors
const errorList = [];
for (const addr of Object.keys(addrs)) {
if (addrs[addr] === "error") {
errorList.push(addr);
}
}

if (errorList.length > 0) {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Failed to invite the following users to the room', '', ErrorDialog, {
title: _t("Failed to invite the following users to the %(roomName)s room:", {roomName: room.name}),
description: errorList.join(", "),
});
}
return addrs;
}

54 changes: 54 additions & 0 deletions src/UserAddress.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
Copyright 2017 New Vector 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.
*/

const emailRegex = /^\S+@\S+\.\S+$/;

const mxidRegex = /^@\S+:\S+$/;

import PropTypes from 'prop-types';
export const addressTypes = [
'mx', 'email',
];

// PropType definition for an object describing
// an address that can be invited to a room (which
// could be a third party identifier or a matrix ID)
// along with some additional information about the
// address / target.
export const UserAddressType = PropTypes.shape({
addressType: PropTypes.oneOf(addressTypes).isRequired,
address: PropTypes.string.isRequired,
displayName: PropTypes.string,
avatarMxc: PropTypes.string,
// true if the address is known to be a valid address (eg. is a real
// user we've seen) or false otherwise (eg. is just an address the
// user has entered)
isKnown: PropTypes.bool,
});

export function getAddressType(inputText) {
const isEmailAddress = emailRegex.test(inputText);
const isMatrixId = mxidRegex.test(inputText);

// sanity check the input for user IDs
if (isEmailAddress) {
return 'email';
} else if (isMatrixId) {
return 'mx';
} else {
return null;
}
}
23 changes: 4 additions & 19 deletions src/components/structures/MatrixChat.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/*
Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017 Vector Creations Ltd
Copyright 2017 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -31,6 +32,7 @@ import dis from "../../dispatcher";
import Modal from "../../Modal";
import Tinter from "../../Tinter";
import sdk from '../../index';
import { showStartChatInviteDialog, showRoomInviteDialog } from '../../Invite';
import * as Rooms from '../../Rooms';
import linkifyMatrix from "../../linkify-matrix";
import * as Lifecycle from '../../Lifecycle';
Expand Down Expand Up @@ -512,7 +514,7 @@ module.exports = React.createClass({
this._createChat();
break;
case 'view_invite':
this._invite(payload.roomId);
showRoomInviteDialog(payload.roomId);
break;
case 'notifier_enabled':
this.forceUpdate();
Expand Down Expand Up @@ -766,13 +768,7 @@ module.exports = React.createClass({
dis.dispatch({action: 'view_set_mxid'});
return;
}
const ChatInviteDialog = sdk.getComponent("dialogs.ChatInviteDialog");
Modal.createTrackedDialog('Start a chat', '', ChatInviteDialog, {
title: _t('Start a chat'),
description: _t("Who would you like to communicate with?"),
placeholder: _t("Email, name or matrix ID"),
button: _t("Start Chat"),
});
showStartChatInviteDialog();
},

_createRoom: function() {
Expand Down Expand Up @@ -857,17 +853,6 @@ module.exports = React.createClass({
}).close;
},

_invite: function(roomId) {
const ChatInviteDialog = sdk.getComponent("dialogs.ChatInviteDialog");
Modal.createTrackedDialog('Chat Invite', '', ChatInviteDialog, {
title: _t('Invite new room members'),
description: _t('Who would you like to add to this room?'),
button: _t('Send Invites'),
placeholder: _t("Email, name or matrix ID"),
roomId: roomId,
});
},

_leaveRoom: function(roomId) {
const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Expand Down
Loading

0 comments on commit 252ab20

Please sign in to comment.