Merge pull request #3286 from matrix-org/travis/immutable-dms/basic
Reuse DMs whenever possible instead of asking to reuse them
This commit is contained in:
commit
07d6fa7fdb
6 changed files with 39 additions and 269 deletions
|
@ -54,7 +54,7 @@ export function showStartChatInviteDialog() {
|
||||||
placeholder: _t("Email, name or Matrix ID"),
|
placeholder: _t("Email, name or Matrix ID"),
|
||||||
validAddressTypes,
|
validAddressTypes,
|
||||||
button: _t("Start Chat"),
|
button: _t("Start Chat"),
|
||||||
onFinished: _onStartChatFinished,
|
onFinished: _onStartDmFinished,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +96,8 @@ export function isValid3pidInvite(event) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
function _onStartChatFinished(shouldInvite, addrs) {
|
// TODO: Immutable DMs replaces this
|
||||||
|
function _onStartDmFinished(shouldInvite, addrs) {
|
||||||
if (!shouldInvite) return;
|
if (!shouldInvite) return;
|
||||||
|
|
||||||
const addrTexts = addrs.map((addr) => addr.address);
|
const addrTexts = addrs.map((addr) => addr.address);
|
||||||
|
@ -104,32 +105,19 @@ function _onStartChatFinished(shouldInvite, addrs) {
|
||||||
if (_isDmChat(addrTexts)) {
|
if (_isDmChat(addrTexts)) {
|
||||||
const rooms = _getDirectMessageRooms(addrTexts[0]);
|
const rooms = _getDirectMessageRooms(addrTexts[0]);
|
||||||
if (rooms.length > 0) {
|
if (rooms.length > 0) {
|
||||||
// A Direct Message room already exists for this user, so select a
|
// A Direct Message room already exists for this user, so reuse it
|
||||||
// room from a list that is similar to the one in MemberInfo panel
|
|
||||||
const ChatCreateOrReuseDialog = sdk.getComponent("views.dialogs.ChatCreateOrReuseDialog");
|
|
||||||
const close = Modal.createTrackedDialog('Create or Reuse', '', ChatCreateOrReuseDialog, {
|
|
||||||
userId: addrTexts[0],
|
|
||||||
onNewDMClick: () => {
|
|
||||||
dis.dispatch({
|
|
||||||
action: 'start_chat',
|
|
||||||
user_id: addrTexts[0],
|
|
||||||
});
|
|
||||||
close(true);
|
|
||||||
},
|
|
||||||
onExistingRoomSelected: (roomId) => {
|
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'view_room',
|
action: 'view_room',
|
||||||
room_id: roomId,
|
room_id: rooms[0],
|
||||||
|
should_peek: false,
|
||||||
|
joining: false,
|
||||||
});
|
});
|
||||||
close(true);
|
|
||||||
},
|
|
||||||
}).close;
|
|
||||||
} else {
|
} else {
|
||||||
// Start a new DM chat
|
// Start a new DM chat
|
||||||
createRoom({dmUserId: addrTexts[0]}).catch((err) => {
|
createRoom({dmUserId: addrTexts[0]}).catch((err) => {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createTrackedDialog('Failed to invite user', '', ErrorDialog, {
|
Modal.createTrackedDialog('Failed to start chat', '', ErrorDialog, {
|
||||||
title: _t("Failed to invite user"),
|
title: _t("Failed to start chat"),
|
||||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -138,8 +126,8 @@ function _onStartChatFinished(shouldInvite, addrs) {
|
||||||
// Start a new DM chat
|
// Start a new DM chat
|
||||||
createRoom({dmUserId: addrTexts[0]}).catch((err) => {
|
createRoom({dmUserId: addrTexts[0]}).catch((err) => {
|
||||||
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
|
||||||
Modal.createTrackedDialog('Failed to invite user', '', ErrorDialog, {
|
Modal.createTrackedDialog('Failed to start chat', '', ErrorDialog, {
|
||||||
title: _t("Failed to invite user"),
|
title: _t("Failed to start chat"),
|
||||||
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
description: ((err && err.message) ? err.message : _t("Operation failed")),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -181,6 +169,7 @@ function _onRoomInviteFinished(roomId, shouldInvite, addrs) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Immutable DMs replaces this
|
||||||
function _isDmChat(addrTexts) {
|
function _isDmChat(addrTexts) {
|
||||||
if (addrTexts.length === 1 && getAddressType(addrTexts[0]) === 'mx-user-id') {
|
if (addrTexts.length === 1 && getAddressType(addrTexts[0]) === 'mx-user-id') {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -343,7 +343,6 @@ const FeaturedUser = React.createClass({
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'view_start_chat_or_reuse',
|
action: 'view_start_chat_or_reuse',
|
||||||
user_id: this.props.summaryInfo.user_id,
|
user_id: this.props.summaryInfo.user_id,
|
||||||
go_home_on_cancel: false,
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -584,7 +584,7 @@ export default React.createClass({
|
||||||
this._setMxId(payload);
|
this._setMxId(payload);
|
||||||
break;
|
break;
|
||||||
case 'view_start_chat_or_reuse':
|
case 'view_start_chat_or_reuse':
|
||||||
this._chatCreateOrReuse(payload.user_id, payload.go_home_on_cancel);
|
this._chatCreateOrReuse(payload.user_id);
|
||||||
break;
|
break;
|
||||||
case 'view_create_chat':
|
case 'view_create_chat':
|
||||||
showStartChatInviteDialog();
|
showStartChatInviteDialog();
|
||||||
|
@ -945,12 +945,7 @@ export default React.createClass({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_chatCreateOrReuse: function(userId, goHomeOnCancel) {
|
_chatCreateOrReuse: function(userId) {
|
||||||
if (goHomeOnCancel === undefined) goHomeOnCancel = true;
|
|
||||||
|
|
||||||
const ChatCreateOrReuseDialog = sdk.getComponent(
|
|
||||||
'views.dialogs.ChatCreateOrReuseDialog',
|
|
||||||
);
|
|
||||||
// Use a deferred action to reshow the dialog once the user has registered
|
// Use a deferred action to reshow the dialog once the user has registered
|
||||||
if (MatrixClientPeg.get().isGuest()) {
|
if (MatrixClientPeg.get().isGuest()) {
|
||||||
// No point in making 2 DMs with welcome bot. This assumes view_set_mxid will
|
// No point in making 2 DMs with welcome bot. This assumes view_set_mxid will
|
||||||
|
@ -975,30 +970,23 @@ export default React.createClass({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const close = Modal.createTrackedDialog('Chat create or reuse', '', ChatCreateOrReuseDialog, {
|
// TODO: Immutable DMs replaces this
|
||||||
userId: userId,
|
|
||||||
onFinished: (success) => {
|
const client = MatrixClientPeg.get();
|
||||||
if (!success && goHomeOnCancel) {
|
const dmRoomMap = new DMRoomMap(client);
|
||||||
// Dialog cancelled, default to home
|
const dmRooms = dmRoomMap.getDMRoomsForUserId(userId);
|
||||||
dis.dispatch({ action: 'view_home_page' });
|
|
||||||
}
|
if (dmRooms.length > 0) {
|
||||||
},
|
dis.dispatch({
|
||||||
onNewDMClick: () => {
|
action: 'view_room',
|
||||||
|
room_id: dmRooms[0],
|
||||||
|
});
|
||||||
|
} else {
|
||||||
dis.dispatch({
|
dis.dispatch({
|
||||||
action: 'start_chat',
|
action: 'start_chat',
|
||||||
user_id: userId,
|
user_id: userId,
|
||||||
});
|
});
|
||||||
// Close the dialog, indicate success (calls onFinished(true))
|
}
|
||||||
close(true);
|
|
||||||
},
|
|
||||||
onExistingRoomSelected: (roomId) => {
|
|
||||||
dis.dispatch({
|
|
||||||
action: 'view_room',
|
|
||||||
room_id: roomId,
|
|
||||||
});
|
|
||||||
close(true);
|
|
||||||
},
|
|
||||||
}).close;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_leaveRoomWarnings: function(roomId) {
|
_leaveRoomWarnings: function(roomId) {
|
||||||
|
|
|
@ -1,203 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2017 Vector Creations Ltd
|
|
||||||
Copyright 2018 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import sdk from '../../../index';
|
|
||||||
import { _t } from '../../../languageHandler';
|
|
||||||
import MatrixClientPeg from '../../../MatrixClientPeg';
|
|
||||||
import DMRoomMap from '../../../utils/DMRoomMap';
|
|
||||||
import AccessibleButton from '../elements/AccessibleButton';
|
|
||||||
import Unread from '../../../Unread';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
|
|
||||||
export default class ChatCreateOrReuseDialog extends React.Component {
|
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
this.onFinished = this.onFinished.bind(this);
|
|
||||||
this.onRoomTileClick = this.onRoomTileClick.bind(this);
|
|
||||||
|
|
||||||
this.state = {
|
|
||||||
tiles: [],
|
|
||||||
profile: {
|
|
||||||
displayName: null,
|
|
||||||
avatarUrl: null,
|
|
||||||
},
|
|
||||||
profileError: null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillMount() {
|
|
||||||
const client = MatrixClientPeg.get();
|
|
||||||
|
|
||||||
const dmRoomMap = new DMRoomMap(client);
|
|
||||||
const dmRooms = dmRoomMap.getDMRoomsForUserId(this.props.userId);
|
|
||||||
|
|
||||||
const RoomTile = sdk.getComponent("rooms.RoomTile");
|
|
||||||
|
|
||||||
const tiles = [];
|
|
||||||
for (const roomId of dmRooms) {
|
|
||||||
const room = client.getRoom(roomId);
|
|
||||||
if (room && room.getMyMembership() === "join") {
|
|
||||||
const member = room.getMember(this.props.userId);
|
|
||||||
if (!member || member.membership !== "join") {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isInvite = room.getMyMembership() === "invite";
|
|
||||||
const highlight = room.getUnreadNotificationCount('highlight') > 0 || isInvite;
|
|
||||||
tiles.push(
|
|
||||||
<RoomTile key={room.roomId} room={room}
|
|
||||||
transparent={true}
|
|
||||||
collapsed={false}
|
|
||||||
selected={false}
|
|
||||||
unread={Unread.doesRoomHaveUnreadMessages(room)}
|
|
||||||
highlight={highlight}
|
|
||||||
isInvite={isInvite}
|
|
||||||
onClick={this.onRoomTileClick}
|
|
||||||
/>,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
tiles: tiles,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (tiles.length === 0) {
|
|
||||||
this.setState({
|
|
||||||
busyProfile: true,
|
|
||||||
});
|
|
||||||
MatrixClientPeg.get().getProfileInfo(this.props.userId).done((resp) => {
|
|
||||||
const profile = {
|
|
||||||
displayName: resp.displayname,
|
|
||||||
avatarUrl: null,
|
|
||||||
};
|
|
||||||
if (resp.avatar_url) {
|
|
||||||
profile.avatarUrl = MatrixClientPeg.get().mxcUrlToHttp(
|
|
||||||
resp.avatar_url, 48, 48, "crop",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
this.setState({
|
|
||||||
busyProfile: false,
|
|
||||||
profile: profile,
|
|
||||||
});
|
|
||||||
}, (err) => {
|
|
||||||
console.error(
|
|
||||||
'Unable to get profile for user ' + this.props.userId + ':',
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
this.setState({
|
|
||||||
busyProfile: false,
|
|
||||||
profileError: err,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onRoomTileClick(roomId) {
|
|
||||||
this.props.onExistingRoomSelected(roomId);
|
|
||||||
}
|
|
||||||
|
|
||||||
onFinished() {
|
|
||||||
this.props.onFinished(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
let title = '';
|
|
||||||
let content = null;
|
|
||||||
if (this.state.tiles.length > 0) {
|
|
||||||
// Show the existing rooms with a "+" to add a new dm
|
|
||||||
title = _t('Create a new chat or reuse an existing one');
|
|
||||||
const labelClasses = classNames({
|
|
||||||
mx_MemberInfo_createRoom_label: true,
|
|
||||||
mx_RoomTile_name: true,
|
|
||||||
});
|
|
||||||
const startNewChat = <AccessibleButton
|
|
||||||
className="mx_MemberInfo_createRoom"
|
|
||||||
onClick={this.props.onNewDMClick}
|
|
||||||
>
|
|
||||||
<div className="mx_RoomTile_avatar">
|
|
||||||
<img src={require("../../../../res/img/create-big.svg")} width="26" height="26" />
|
|
||||||
</div>
|
|
||||||
<div className={labelClasses}><i>{ _t("Start new chat") }</i></div>
|
|
||||||
</AccessibleButton>;
|
|
||||||
content = <div className="mx_Dialog_content" id='mx_Dialog_content'>
|
|
||||||
{ _t('You already have existing direct chats with this user:') }
|
|
||||||
<div className="mx_ChatCreateOrReuseDialog_tiles">
|
|
||||||
{ this.state.tiles }
|
|
||||||
{ startNewChat }
|
|
||||||
</div>
|
|
||||||
</div>;
|
|
||||||
} else {
|
|
||||||
// Show the avatar, name and a button to confirm that a new chat is requested
|
|
||||||
const BaseAvatar = sdk.getComponent('avatars.BaseAvatar');
|
|
||||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
|
||||||
const Spinner = sdk.getComponent('elements.Spinner');
|
|
||||||
title = _t('Start chatting');
|
|
||||||
|
|
||||||
let profile = null;
|
|
||||||
if (this.state.busyProfile) {
|
|
||||||
profile = <Spinner />;
|
|
||||||
} else if (this.state.profileError) {
|
|
||||||
profile = <div className="error" role="alert">
|
|
||||||
Unable to load profile information for { this.props.userId }
|
|
||||||
</div>;
|
|
||||||
} else {
|
|
||||||
profile = <div className="mx_ChatCreateOrReuseDialog_profile">
|
|
||||||
<BaseAvatar
|
|
||||||
name={this.state.profile.displayName || this.props.userId}
|
|
||||||
url={this.state.profile.avatarUrl}
|
|
||||||
width={48} height={48}
|
|
||||||
/>
|
|
||||||
<div className="mx_ChatCreateOrReuseDialog_profile_name">
|
|
||||||
{ this.state.profile.displayName || this.props.userId }
|
|
||||||
</div>
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
content = <div>
|
|
||||||
<div className="mx_Dialog_content" id='mx_Dialog_content'>
|
|
||||||
<p>
|
|
||||||
{ _t('Click on the button below to start chatting!') }
|
|
||||||
</p>
|
|
||||||
{ profile }
|
|
||||||
</div>
|
|
||||||
<DialogButtons primaryButton={_t('Start Chatting')}
|
|
||||||
onPrimaryButtonClick={this.props.onNewDMClick} focus={true} />
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
|
||||||
return (
|
|
||||||
<BaseDialog className='mx_ChatCreateOrReuseDialog'
|
|
||||||
onFinished={this.onFinished}
|
|
||||||
title={title}
|
|
||||||
contentId='mx_Dialog_content'
|
|
||||||
>
|
|
||||||
{ content }
|
|
||||||
</BaseDialog>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ChatCreateOrReuseDialog.propTypes = {
|
|
||||||
userId: PropTypes.string.isRequired,
|
|
||||||
// Called when clicking outside of the dialog
|
|
||||||
onFinished: PropTypes.func.isRequired,
|
|
||||||
onNewDMClick: PropTypes.func.isRequired,
|
|
||||||
onExistingRoomSelected: PropTypes.func.isRequired,
|
|
||||||
};
|
|
|
@ -789,6 +789,7 @@ module.exports = React.createClass({
|
||||||
let spinner;
|
let spinner;
|
||||||
|
|
||||||
if (this.props.member.userId !== this.context.matrixClient.credentials.userId) {
|
if (this.props.member.userId !== this.context.matrixClient.credentials.userId) {
|
||||||
|
// TODO: Immutable DMs replaces a lot of this
|
||||||
const dmRoomMap = new DMRoomMap(this.context.matrixClient);
|
const dmRoomMap = new DMRoomMap(this.context.matrixClient);
|
||||||
// dmRooms will not include dmRooms that we have been invited into but did not join.
|
// dmRooms will not include dmRooms that we have been invited into but did not join.
|
||||||
// Because DMRoomMap runs off account_data[m.direct] which is only set on join of dm room.
|
// Because DMRoomMap runs off account_data[m.direct] which is only set on join of dm room.
|
||||||
|
@ -830,7 +831,7 @@ module.exports = React.createClass({
|
||||||
mx_MemberInfo_createRoom_label: true,
|
mx_MemberInfo_createRoom_label: true,
|
||||||
mx_RoomTile_name: true,
|
mx_RoomTile_name: true,
|
||||||
});
|
});
|
||||||
const startNewChat = <AccessibleButton
|
let startNewChat = <AccessibleButton
|
||||||
className="mx_MemberInfo_createRoom"
|
className="mx_MemberInfo_createRoom"
|
||||||
onClick={this.onNewDMClick}
|
onClick={this.onNewDMClick}
|
||||||
>
|
>
|
||||||
|
@ -840,6 +841,8 @@ module.exports = React.createClass({
|
||||||
<div className={labelClasses}><i>{ _t("Start a chat") }</i></div>
|
<div className={labelClasses}><i>{ _t("Start a chat") }</i></div>
|
||||||
</AccessibleButton>;
|
</AccessibleButton>;
|
||||||
|
|
||||||
|
if (tiles.length > 0) startNewChat = null; // Don't offer a button for a new chat if we have one.
|
||||||
|
|
||||||
startChat = <div>
|
startChat = <div>
|
||||||
<h3>{ _t("Direct chats") }</h3>
|
<h3>{ _t("Direct chats") }</h3>
|
||||||
{ tiles }
|
{ tiles }
|
||||||
|
|
|
@ -114,7 +114,7 @@
|
||||||
"Invite new room members": "Invite new room members",
|
"Invite new room members": "Invite new room members",
|
||||||
"Who would you like to add to this room?": "Who would you like to add to this room?",
|
"Who would you like to add to this room?": "Who would you like to add to this room?",
|
||||||
"Send Invites": "Send Invites",
|
"Send Invites": "Send Invites",
|
||||||
"Failed to invite user": "Failed to invite user",
|
"Failed to start chat": "Failed to start chat",
|
||||||
"Operation failed": "Operation failed",
|
"Operation failed": "Operation failed",
|
||||||
"Failed to invite": "Failed to invite",
|
"Failed to invite": "Failed to invite",
|
||||||
"Failed to invite users to the room:": "Failed to invite users to the room:",
|
"Failed to invite users to the room:": "Failed to invite users to the room:",
|
||||||
|
@ -1124,12 +1124,6 @@
|
||||||
"Unable to load commit detail: %(msg)s": "Unable to load commit detail: %(msg)s",
|
"Unable to load commit detail: %(msg)s": "Unable to load commit detail: %(msg)s",
|
||||||
"Unavailable": "Unavailable",
|
"Unavailable": "Unavailable",
|
||||||
"Changelog": "Changelog",
|
"Changelog": "Changelog",
|
||||||
"Create a new chat or reuse an existing one": "Create a new chat or reuse an existing one",
|
|
||||||
"Start new chat": "Start new chat",
|
|
||||||
"You already have existing direct chats with this user:": "You already have existing direct chats with this user:",
|
|
||||||
"Start chatting": "Start chatting",
|
|
||||||
"Click on the button below to start chatting!": "Click on the button below to start chatting!",
|
|
||||||
"Start Chatting": "Start Chatting",
|
|
||||||
"You cannot delete this message. (%(code)s)": "You cannot delete this message. (%(code)s)",
|
"You cannot delete this message. (%(code)s)": "You cannot delete this message. (%(code)s)",
|
||||||
"Removing…": "Removing…",
|
"Removing…": "Removing…",
|
||||||
"Confirm Removal": "Confirm Removal",
|
"Confirm Removal": "Confirm Removal",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue