@@ -60,15 +60,15 @@ class RoomsPane extends React.Component {
RoomsPane.propTypes = {
loginUserName: PropTypes.string.isRequired,
params: PropTypes.shape({
- roomName: PropTypes.string
+ roomNameHash: PropTypes.string
}),
- roomMap: ImmutablePropTypes.orderedMap.isRequired,
+ rooms: ImmutablePropTypes.record.isRequired,
roomActions: PropTypes.object.isRequired
};
const mapStateToProps = (state) => ({
- roomMap: state.rooms.get("roomMap"),
- loginUserName: state.login.get("username")
+ loginUserName: state.login.get("username"),
+ rooms: state.rooms
});
const mapDispatchToProps = (dispatch) => ({
diff --git a/src/createRoutes.js b/src/createRoutes.js
index 1fc3c2c..2865873 100644
--- a/src/createRoutes.js
+++ b/src/createRoutes.js
@@ -24,7 +24,7 @@ const createRoutes = (store) => {
-
+
);
diff --git a/src/reducers/rooms.js b/src/reducers/rooms.js
index 88f7476..0d036b1 100644
--- a/src/reducers/rooms.js
+++ b/src/reducers/rooms.js
@@ -1,5 +1,7 @@
import Immutable from "immutable";
+import OrderedMap from "../utils/OrderedMap";
+
import {
ROOM_JOIN,
ROOM_LEAVE,
@@ -9,48 +11,9 @@ import {
SOCKET_RECEIVE_MESSAGE
} from "../constants/ActionTypes";
-const initialState = Immutable.Map({
- roomMap: Immutable.OrderedMap(),
- roomNameByHash: Immutable.Map()
-});
+const initialState = OrderedMap();
const reduceRoomList = (state, roomList) => {
- const roomMap = state.get("roomMap");
- const roomNameByHash = state.get("roomNameByHash");
-
- // First sort the room list by room name
- roomList.sort(([ roomName1 ], [ roomName2 ]) => {
- if (roomName1 < roomName2) {
- return -1;
- } else if (roomName1 > roomName2) {
- return 1;
- }
- return 0;
- });
-
- // Then build the new rooms map
- let newRoomMap = Immutable.OrderedMap();
-
- for (const [ roomName, newRoomData ] of roomList) {
- // Get the old room data.
- let roomData = roomMap.get(roomName);
- if (roomData) {
- // Scrap the old message list, we only want the new message list.
- roomData.remove("messages");
- } else {
- // If the room did not exist, make up an empty one.
- roomData = Immutable.Map();
- }
- // Merge the old data and the new data, overwriting with new data if
- // conflicting.
- const mergedRoomData = roomData.merge(newRoomData);
- // Insert that in the new room map.
- newRoomMap = newRoomMap.set(roomName, mergedRoomData);
- }
-
- return state
- .set("roomMap", newRoomMap)
- .set("roomNameByHash", roomNameByHash);
};
const reduceReceiveMessageRoom = (roomData, { variant, data }) => {
@@ -79,7 +42,7 @@ const reduceReceiveMessage = (state, message) => {
case "RoomMessageResponse":
{
const { room_name } = data;
- return state.updateIn(["roomMap", data.room_name], (roomData) => {
+ return state.updateByName(data.room_name, (roomData) => {
if (roomData) {
return reduceReceiveMessageRoom(roomData, message);
} else {
@@ -90,7 +53,16 @@ const reduceReceiveMessage = (state, message) => {
}
case "RoomListResponse":
- return reduceRoomList(state, data.rooms);
+ return state.updateAll(data.rooms, (newData, oldData) => {
+ if (oldData) {
+ // Remove the messages array, we want to overwrite it
+ // completely.
+ oldData.remove("messages");
+ } else {
+ oldData = Immutable.Map();
+ }
+ return oldData.merge(newData);
+ });
default:
return state;
@@ -125,7 +97,7 @@ export default (state = initialState, action) => {
case ROOM_SHOW_USERS:
case ROOM_HIDE_USERS:
{
- return state.updateIn(["roomMap", payload], (roomData) => {
+ return state.updateByName(payload, (roomData) => {
if (roomData) {
return reduceRoom(roomData, action);
} else {
diff --git a/src/styles/styles.scss b/src/styles/styles.scss
index 717199e..b9c1a7c 100644
--- a/src/styles/styles.scss
+++ b/src/styles/styles.scss
@@ -33,6 +33,10 @@ html {
header {
margin: 0;
padding: 1.5em 2em;
+ display: flex;
+ flex-flow: row;
+ justify-content: space-around;
+ width: 100%;
}
header h1 {
diff --git a/src/utils/OrderedMap.js b/src/utils/OrderedMap.js
new file mode 100644
index 0000000..b370a0f
--- /dev/null
+++ b/src/utils/OrderedMap.js
@@ -0,0 +1,70 @@
+import Immutable from "immutable";
+import md5 from "md5";
+
+const MapRecord = Immutable.Record({
+ byName: Immutable.OrderedMap(),
+ byHash: Immutable.Map()
+});
+
+class OrderedMap extends MapRecord {
+ constructor(arg) {
+ super(arg);
+ }
+
+ getByName(name) {
+ return this.getIn(["byName", name]);
+ }
+
+ setByName(name, data) {
+ let thisModified = this;
+ if (!this.getByName(name)) {
+ // That key was not there yet, add hash -> name mapping.
+ thisModified = this.setIn(["byHash", md5(name)], name);
+ }
+ // Add data to map.
+ return thisModified.setIn(["byName", name], data);
+ }
+
+ updateByName(name, updater) {
+ return this.updateIn(["byName", name], updater);
+ }
+
+ getNameByHash(hash) {
+ return this.getIn(["byHash", hash]);
+ }
+
+ updateAll(nameAndDataList, merger) {
+ const { byName } = this;
+ let { byHash } = this;
+
+ // First sort the room list by room name
+ nameAndDataList.sort(([ name1 ], [ name2 ]) => {
+ if (name1 < name2) {
+ return -1;
+ } else if (name1 > name2) {
+ return 1;
+ }
+ return 0;
+ });
+
+ // Then build the new map.
+ let newByName = Immutable.OrderedMap();
+
+ for (const [ name, newData ] of nameAndDataList) {
+ // Get the old room data.
+ let data = byName.get(name);
+ if (!data) {
+ // Add the hash -> name mapping.
+ byHash = byHash.set(md5(name), name);
+ }
+ // Merge the old data and the new data using the provided function.
+ const mergedData = merger(newData, data);
+ // Insert that in the new room map.
+ newByName = newByName.set(name, mergedData);
+ }
+
+ return new OrderedMap({ byName: newByName, byHash });
+ }
+}
+
+export default () => new OrderedMap();