metamaps--metamaps/realtime/reducer.js
2016-10-21 15:16:01 +08:00

87 lines
2.9 KiB
JavaScript

const { omit, omitBy, isNil, mapValues } = require('lodash')
const {
JOIN_MAP,
LEAVE_MAP,
JOIN_CALL,
LEAVE_CALL
} = require('../frontend/src/Metamaps/Realtime/events')
const NOT_IN_CONVERSATION = 0
const IN_CONVERSATION = 1
const addMapperToMap = (map, userId) => { return { ...map, [userId]: NOT_IN_CONVERSATION }}
module.exports = { reducer: (state = { connectedPeople: {}, liveMaps: {} }, action) => {
const { type, payload } = action
const { connectedPeople, liveMaps } = state
const map = payload && liveMaps[payload.mapid]
const mapWillEmpty = map && Object.keys(map).length === 1
const callWillFinish = map && (type === LEAVE_CALL || type === 'DISCONNECT') && Object.keys(map).length === 2
switch (type) {
case JOIN_MAP:
return {
connectedPeople: {
...connectedPeople,
[payload.userid]: {
id: payload.userid,
username: payload.username,
avatar: payload.avatar
}
},
liveMaps: {
...liveMaps,
[payload.mapid]: addMapperToMap(map || {}, payload.userid)
}
}
case LEAVE_MAP:
return {
connectedPeople: omit(connectedPeople, payload.userid),
// if the map will empty, remove it from liveMaps, if the map will not empty, just remove the mapper
liveMaps: omitBy(mapWillEmpty ? omit(liveMaps, payload.mapid) : { ...liveMaps, [payload.mapid]: omit(liveMaps[payload.mapid], payload.userid) }, isNil)
}
case JOIN_CALL:
return {
// connectedPeople stays the same
connectedPeople,
liveMaps: {
// liveMaps stays the same, except for
...liveMaps,
// the map in question
[payload.mapid]: {
// which stays the same, except for
...map,
// the user in question, which is now marked as being in a conversation
[payload.id]: IN_CONVERSATION
}
}
}
case LEAVE_CALL:
return {
// connectedPeople stays the same
connectedPeople,
liveMaps: {
// liveMaps stays the same, except for
...liveMaps,
// the map in question
[payload.mapid]: callWillFinish ? mapValues(map, () => NOT_IN_CONVERSATION) : {
// which stays the same, except for
...map,
// the user in question, which is now marked as being NOT in conversation
[payload.userid]: NOT_IN_CONVERSATION
}
}
}
case 'DISCONNECT':
const mapWithoutUser = omit(map, payload.userid)
const newMap = callWillFinish ? mapValues(mapWithoutUser, () => NOT_IN_CONVERSATION) : mapWithoutUser
return {
connectedPeople: omit(connectedPeople, payload.userid),
// if the map will empty, remove it from liveMaps, if the map will not empty, just remove the mapper
liveMaps: omitBy(mapWillEmpty ? omit(liveMaps, payload.mapid) :
{ ...liveMaps, [payload.mapid]: newMap }, isNil)
}
default:
return state
}
} }