diff --git a/src/components/RoomList.js b/src/components/RoomList.js index 45dadf0..971ecc4 100644 --- a/src/components/RoomList.js +++ b/src/components/RoomList.js @@ -13,11 +13,11 @@ class RoomList extends React.Component { } render() { - const { selected, rooms, roomActions } = this.props; + const { selected, roomMap, roomActions } = this.props; const children = []; - for (const [room_name, room_data] of rooms) { + for (const [room_name, room_data] of roomMap) { const onClick = (event) => { roomActions.select(room_name); }; @@ -43,7 +43,7 @@ class RoomList extends React.Component { } RoomList.propTypes = { - rooms: PropTypes.object.isRequired, + roomMap: PropTypes.object.isRequired, roomActions: PropTypes.shape({ getList: PropTypes.func.isRequired }).isRequired, diff --git a/src/containers/RoomsPane.js b/src/containers/RoomsPane.js index 5debe7d..09ce6d6 100644 --- a/src/containers/RoomsPane.js +++ b/src/containers/RoomsPane.js @@ -15,7 +15,7 @@ class RoomsPane extends React.Component { } render() { - const { loginUserName, params, rooms, roomActions } = this.props; + const { loginUserName, params, roomMap, roomActions } = this.props; let roomName; let roomChat; @@ -23,7 +23,7 @@ class RoomsPane extends React.Component { if (params && params.roomName) { roomName = decodeURIComponent(atob(params.roomName)); - const { membership, messages, showUsers } = rooms.get(roomName); + const { membership, messages, showUsers } = roomMap.get(roomName); const room = { name: roomName, membership, @@ -42,7 +42,7 @@ class RoomsPane extends React.Component { return (
@@ -59,12 +59,12 @@ RoomsPane.propTypes = { params: PropTypes.shape({ roomName: PropTypes.string }), - rooms: ImmutablePropTypes.orderedMap.isRequired, - roomActions: PropTypes.object.isRequired + roomMap: ImmutablePropTypes.orderedMap.isRequired, + roomActions: PropTypes.object.isRequired }; const mapStateToProps = (state) => ({ - rooms: state.rooms.rooms, + roomMap: state.rooms.roomMap, loginUserName: state.login.username }); diff --git a/src/reducers/rooms.js b/src/reducers/rooms.js index 26ee3e7..5dbc7ad 100644 --- a/src/reducers/rooms.js +++ b/src/reducers/rooms.js @@ -10,10 +10,13 @@ import { } from "../constants/ActionTypes"; const initialState = { - rooms: Immutable.OrderedMap() + roomMap: Immutable.OrderedMap(), + roomNameByHash: Immutable.Map() }; -const reduceRoomList = (oldRoomMap, roomList) => { +const reduceRoomList = (state, roomList) => { + const { roomMap, roomNameByHash } = state; + // First sort the room list by room name roomList.sort(([ roomName1 ], [ roomName2 ]) => { if (roomName1 < roomName2) { @@ -31,123 +34,124 @@ const reduceRoomList = (oldRoomMap, roomList) => { // Transform room_data.messages to an immutable list. newRoomData.messages = Immutable.List(newRoomData.messages); // Get the old room data. - const oldRoomData = oldRoomMap.get(roomName); + const roomData = roomMap.get(roomName); // Merge the old data and the new data, overwriting with new data if // conflicting. const mergedRoomData = { - ...oldRoomData, + ...roomData, ...newRoomData }; newRoomMap = newRoomMap.set(roomName, mergedRoomData); } - return newRoomMap; + return { + ...state, + roomMap: newRoomMap, + roomNameByHash + }; }; -const reduceReceiveMessage = (rooms, { variant, data }) => { +const reduceReceiveMessageRoom = (roomData, { variant, data }) => { switch (variant) { case "RoomJoinResponse": - { - const { room_name } = data; - const room = rooms.get(room_name); - return rooms.set(room_name, { - ...room, + return { + ...roomData, membership: "Member" - }); - } + }; case "RoomLeaveResponse": - { - const room_name = data; - const room = rooms.get(room_name); - return rooms.set(room_name, { - ...room, + return { + ...roomData, membership: "NonMember" - }); - } - - case "RoomListResponse": - return reduceRoomList(rooms, data.rooms); + }; case "RoomMessageResponse": { - const { room_name, user_name, message } = data; - const room_data = rooms.get(room_name); - if (!room_data) { - console.log(`Error: room "${room_name} not found`); - return rooms; - } - const new_room_data = { - ...room_data, - messages: room_data.messages.push({ user_name, message }) + const { user_name, message } = data; + return { + ...roomData, + messages: roomData.messages.push({ user_name, message }) }; - return rooms.set(room_name, new_room_data); } - - default: - return rooms; } }; -export default (state = initialState, action) => { - const { type, payload } = action; - switch (type) { - case SOCKET_RECEIVE_MESSAGE: +const reduceReceiveMessage = (state, message) => { + const { variant, data } = message; + switch (variant) { + case "RoomJoinResponse": + case "RoomLeaveResponse": + case "RoomMessageResponse": + { + const { room_name } = data; + const roomData = state.roomMap.get(room_name); + const roomMap = state.roomMap.set(room_name, + reduceReceiveMessageRoom(roomData, { variant, data }) + ); return { ...state, - rooms: reduceReceiveMessage(state.rooms, payload) + roomMap }; + } - case ROOM_MESSAGE: + case "RoomListResponse": + return reduceRoomList(state, data.rooms); + + default: return state; + } +}; +const reduceRoom = (roomData, { type, payload }) => { + switch (type) { case ROOM_JOIN: - { - const rooms = state.rooms.set(payload, { - ...state.rooms.get(payload), - membership: "Joining" - }); return { - ...state, - rooms + ...roomData, + membership: "Joining" }; - } case ROOM_LEAVE: - { - const rooms = state.rooms.set(payload, { - ...state.rooms.get(payload), - membership: "Leaving" - }); return { - ...state, - rooms + ...roomData, + membership: "Leaving" }; - } case ROOM_SHOW_USERS: - { - const rooms = state.rooms.set(payload, { - ...state.rooms.get(payload), + return { + ...roomData, showUsers: true - }); + }; + + case ROOM_HIDE_USERS: return { - ...state, - rooms + ...roomData, + showUsers: false }; - } + } +}; + +export default (state = initialState, action) => { + const { type, payload } = action; + switch (type) { + case SOCKET_RECEIVE_MESSAGE: + return reduceReceiveMessage(state, payload); + + case ROOM_JOIN: + case ROOM_LEAVE: + case ROOM_SHOW_USERS: case ROOM_HIDE_USERS: { - const rooms = state.rooms.set(payload, { - ...state.rooms.get(payload), - showUsers: false - }); + const roomData = state.roomMap.get(payload); + const roomMap = state.roomMap.set(payload, + reduceRoom(roomData, action) + ); return { ...state, - rooms + roomMap }; } + case ROOM_MESSAGE: default: return state; }