Merge pull request #736 from matrix-org/luke/chat-create-or-reuse-dialog
Allow user to choose from existing DMs on new chatpull/21833/head
						commit
						b7f1b1a424
					
				|  | @ -75,6 +75,8 @@ import views$create_room$RoomAlias from './components/views/create_room/RoomAlia | |||
| views$create_room$RoomAlias && (module.exports.components['views.create_room.RoomAlias'] = views$create_room$RoomAlias); | ||||
| import views$dialogs$BaseDialog from './components/views/dialogs/BaseDialog'; | ||||
| views$dialogs$BaseDialog && (module.exports.components['views.dialogs.BaseDialog'] = views$dialogs$BaseDialog); | ||||
| import views$dialogs$ChatCreateOrReuseDialog from './components/views/dialogs/ChatCreateOrReuseDialog'; | ||||
| views$dialogs$ChatCreateOrReuseDialog && (module.exports.components['views.dialogs.ChatCreateOrReuseDialog'] = views$dialogs$ChatCreateOrReuseDialog); | ||||
| 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'; | ||||
|  |  | |||
|  | @ -0,0 +1,111 @@ | |||
| /* | ||||
| 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 dis from '../../../dispatcher'; | ||||
| import MatrixClientPeg from '../../../MatrixClientPeg'; | ||||
| import DMRoomMap from '../../../utils/DMRoomMap'; | ||||
| import AccessibleButton from '../elements/AccessibleButton'; | ||||
| import Unread from '../../../Unread'; | ||||
| import classNames from 'classnames'; | ||||
| import createRoom from '../../../createRoom'; | ||||
| 
 | ||||
| export default class CreateOrReuseChatDialog extends React.Component { | ||||
| 
 | ||||
|     constructor(props) { | ||||
|         super(props); | ||||
|         this.onNewDMClick = this.onNewDMClick.bind(this); | ||||
|         this.onRoomTileClick = this.onRoomTileClick.bind(this); | ||||
|     } | ||||
| 
 | ||||
|     onNewDMClick() { | ||||
|         createRoom({dmUserId: this.props.userId}); | ||||
|         this.props.onFinished(true); | ||||
|     } | ||||
| 
 | ||||
|     onRoomTileClick(roomId) { | ||||
|         dis.dispatch({ | ||||
|             action: 'view_room', | ||||
|             room_id: roomId, | ||||
|         }); | ||||
|         this.props.onFinished(true); | ||||
|     } | ||||
| 
 | ||||
|     render() { | ||||
|         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) { | ||||
|                 const me = room.getMember(client.credentials.userId); | ||||
|                 const highlight = ( | ||||
|                     room.getUnreadNotificationCount('highlight') > 0 || | ||||
|                     me.membership == "invite" | ||||
|                 ); | ||||
|                 tiles.push( | ||||
|                     <RoomTile key={room.roomId} room={room} | ||||
|                         collapsed={false} | ||||
|                         selected={false} | ||||
|                         unread={Unread.doesRoomHaveUnreadMessages(room)} | ||||
|                         highlight={highlight} | ||||
|                         isInvite={me.membership == "invite"} | ||||
|                         onClick={this.onRoomTileClick} | ||||
|                     /> | ||||
|                 ); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         const labelClasses = classNames({ | ||||
|             mx_MemberInfo_createRoom_label: true, | ||||
|             mx_RoomTile_name: true, | ||||
|         }); | ||||
|         const startNewChat = <AccessibleButton | ||||
|             className="mx_MemberInfo_createRoom" | ||||
|             onClick={this.onNewDMClick} | ||||
|         > | ||||
|             <div className="mx_RoomTile_avatar"> | ||||
|                 <img src="img/create-big.svg" width="26" height="26" /> | ||||
|             </div> | ||||
|             <div className={labelClasses}><i>Start new chat</i></div> | ||||
|         </AccessibleButton>; | ||||
| 
 | ||||
|         const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog'); | ||||
|         return ( | ||||
|             <BaseDialog className='mx_CreateOrReuseChatDialog' | ||||
|                 onFinished={() => { | ||||
|                     this.props.onFinished(false) | ||||
|                 }} | ||||
|                 title='Create a new chat or reuse an existing one' | ||||
|             > | ||||
|                 You already have existing direct chats with this user: | ||||
|                 {tiles} | ||||
|                 {startNewChat} | ||||
|             </BaseDialog> | ||||
|         ); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| CreateOrReuseChatDialog.propTyps = { | ||||
|     userId: React.PropTypes.string.isRequired, | ||||
|     onFinished: React.PropTypes.func.isRequired, | ||||
| }; | ||||
|  | @ -111,18 +111,27 @@ module.exports = React.createClass({ | |||
|             if (inviteList === null) return; | ||||
|         } | ||||
| 
 | ||||
|         const addrTexts = inviteList.map(addr => addr.address); | ||||
|         if (inviteList.length > 0) { | ||||
|             if (this._isDmChat(inviteList)) { | ||||
|             if (this._isDmChat(addrTexts)) { | ||||
|                 const userId = inviteList[0].address; | ||||
|                 // Direct Message chat
 | ||||
|                 var room = this._getDirectMessageRoom(inviteList[0]); | ||||
|                 if (room) { | ||||
|                     // A Direct Message room already exists for this user and you
 | ||||
|                     // so go straight to that room
 | ||||
|                     dis.dispatch({ | ||||
|                         action: 'view_room', | ||||
|                         room_id: room.roomId, | ||||
|                 const rooms = this._getDirectMessageRooms(userId); | ||||
|                 if (rooms.length > 0) { | ||||
|                     // A Direct Message room already exists for this user, so select a
 | ||||
|                     // room from a list that is similar to the one in MemberInfo panel
 | ||||
|                     const ChatCreateOrReuseDialog = sdk.getComponent( | ||||
|                         "views.dialogs.ChatCreateOrReuseDialog" | ||||
|                     ); | ||||
|                     Modal.createDialog(ChatCreateOrReuseDialog, { | ||||
|                         userId: userId, | ||||
|                         onFinished: (success) => { | ||||
|                             if (success) { | ||||
|                                 this.props.onFinished(true, inviteList[0]); | ||||
|                             } | ||||
|                             // else show this ChatInviteDialog again
 | ||||
|                         } | ||||
|                     }); | ||||
|                     this.props.onFinished(true, inviteList[0]); | ||||
|                 } else { | ||||
|                     this._startChat(inviteList); | ||||
|                 } | ||||
|  | @ -267,22 +276,20 @@ module.exports = React.createClass({ | |||
|         if (this._cancelThreepidLookup) this._cancelThreepidLookup(); | ||||
|     }, | ||||
| 
 | ||||
|     _getDirectMessageRoom: function(addr) { | ||||
|     _getDirectMessageRooms: function(addr) { | ||||
|         const dmRoomMap = new DMRoomMap(MatrixClientPeg.get()); | ||||
|         var dmRooms = dmRoomMap.getDMRoomsForUserId(addr); | ||||
|         if (dmRooms.length > 0) { | ||||
|             // Cycle through all the DM rooms and find the first non forgotten or parted room
 | ||||
|             for (let i = 0; i < dmRooms.length; i++) { | ||||
|                 let room = MatrixClientPeg.get().getRoom(dmRooms[i]); | ||||
|                 if (room) { | ||||
|                     const me = room.getMember(MatrixClientPeg.get().credentials.userId); | ||||
|                     if (me.membership == 'join') { | ||||
|                         return room; | ||||
|                     } | ||||
|         const dmRooms = dmRoomMap.getDMRoomsForUserId(addr); | ||||
|         const rooms = []; | ||||
|         dmRooms.forEach(dmRoom => { | ||||
|             let room = MatrixClientPeg.get().getRoom(dmRoom); | ||||
|             if (room) { | ||||
|                 const me = room.getMember(MatrixClientPeg.get().credentials.userId); | ||||
|                 if (me.membership == 'join') { | ||||
|                     rooms.push(room); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         return null; | ||||
|         }); | ||||
|         return rooms; | ||||
|     }, | ||||
| 
 | ||||
|     _startChat: function(addrs) { | ||||
|  | @ -381,8 +388,11 @@ module.exports = React.createClass({ | |||
|         return false; | ||||
|     }, | ||||
| 
 | ||||
|     _isDmChat: function(addrs) { | ||||
|         if (addrs.length === 1 && getAddressType(addrs[0]) === "mx" && !this.props.roomId) { | ||||
|     _isDmChat: function(addrTexts) { | ||||
|         if (addrTexts.length === 1 && | ||||
|             getAddressType(addrTexts[0]) === "mx" && | ||||
|             !this.props.roomId | ||||
|         ) { | ||||
|             return true; | ||||
|         } else { | ||||
|             return false; | ||||
|  |  | |||
|  | @ -553,6 +553,13 @@ module.exports = WithMatrixClient(React.createClass({ | |||
|         Modal.createDialog(ImageView, params, "mx_Dialog_lightbox"); | ||||
|     }, | ||||
| 
 | ||||
|     onRoomTileClick(roomId) { | ||||
|         dis.dispatch({ | ||||
|             action: 'view_room', | ||||
|             room_id: roomId, | ||||
|         }); | ||||
|     }, | ||||
| 
 | ||||
|     _renderDevices: function() { | ||||
|         if (!this._enableDevices) { | ||||
|             return null; | ||||
|  | @ -613,6 +620,7 @@ module.exports = WithMatrixClient(React.createClass({ | |||
|                             unread={Unread.doesRoomHaveUnreadMessages(room)} | ||||
|                             highlight={highlight} | ||||
|                             isInvite={me.membership == "invite"} | ||||
|                             onClick={this.onRoomTileClick} | ||||
|                         /> | ||||
|                     ); | ||||
|                 } | ||||
|  |  | |||
|  | @ -19,7 +19,6 @@ limitations under the License. | |||
| var React = require('react'); | ||||
| var ReactDOM = require("react-dom"); | ||||
| var classNames = require('classnames'); | ||||
| var dis = require("../../../dispatcher"); | ||||
| var MatrixClientPeg = require('../../../MatrixClientPeg'); | ||||
| import DMRoomMap from '../../../utils/DMRoomMap'; | ||||
| var sdk = require('../../../index'); | ||||
|  | @ -35,6 +34,7 @@ module.exports = React.createClass({ | |||
|     propTypes: { | ||||
|         connectDragSource: React.PropTypes.func, | ||||
|         connectDropTarget: React.PropTypes.func, | ||||
|         onClick: React.PropTypes.func, | ||||
|         isDragging: React.PropTypes.bool, | ||||
| 
 | ||||
|         room: React.PropTypes.object.isRequired, | ||||
|  | @ -100,10 +100,9 @@ module.exports = React.createClass({ | |||
|     }, | ||||
| 
 | ||||
|     onClick: function() { | ||||
|         dis.dispatch({ | ||||
|             action: 'view_room', | ||||
|             room_id: this.props.room.roomId, | ||||
|         }); | ||||
|         if (this.props.onClick) { | ||||
|             this.props.onClick(this.props.room.roomId); | ||||
|         } | ||||
|     }, | ||||
| 
 | ||||
|     onMouseEnter: function() { | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Luke Barnard
						Luke Barnard