pixelplanet/src/store/reducers/chat.js
2022-09-04 23:31:02 +02:00

194 lines
4.2 KiB
JavaScript

import { MAX_CHAT_MESSAGES } from '../../core/constants';
const initialState = {
/*
* {
* cid: [
* name,
* type,
* lastTs,
* ],
* cid2: [
* name,
* type,
* lastTs,
* dmUserId,
* ],
* ...
* }
*/
channels: {},
// [[uId, userName], [userId2, userName2],...]
blocked: [],
// { cid: [message1,message2,message3,...]}
messages: {},
};
// used to give every message a unique incrementing key
let msgId = 0;
export default function chat(
state = initialState,
action,
) {
switch (action.type) {
case 's/REC_ME':
case 's/LOGIN': {
// making sure object keys are numbers
const channels = {};
const channelsJson = action.channels;
const cids = Object.keys(channelsJson);
for (let i = 0; i < cids.length; i += 1) {
const cid = cids[i];
channels[Number(cid)] = channelsJson[cid];
}
return {
...state,
channels,
blocked: action.blocked,
};
}
case 's/LOGOUT': {
const channels = { ...state.channels };
const messages = { ...state.messages };
const keys = Object.keys(channels);
for (let i = 0; i < keys.length; i += 1) {
const cid = keys[i];
if (channels[cid][1] !== 0) {
delete messages[cid];
delete channels[cid];
}
}
return {
...state,
channels,
blocked: [],
messages,
};
}
case 's/BLOCK_USER': {
const { userId, userName } = action;
const blocked = [
...state.blocked,
[userId, userName],
];
/*
* remove DM channel if exists
*/
const channels = { ...state.channels };
const chanKeys = Object.keys(channels);
for (let i = 0; i < chanKeys.length; i += 1) {
const cid = chanKeys[i];
if (channels[cid][1] === 1 && channels[cid][3] === userId) {
delete channels[cid];
return {
...state,
channels,
blocked,
};
}
}
return {
...state,
blocked,
};
}
case 's/UNBLOCK_USER': {
const { userId } = action;
const blocked = state.blocked.filter((bl) => (bl[0] !== userId));
return {
...state,
blocked,
};
}
case 's/ADD_CHAT_CHANNEL': {
const { channel } = action;
const cid = Number(Object.keys(channel)[0]);
if (state.channels[cid]) {
return state;
}
return {
...state,
channels: {
...state.channels,
...channel,
},
};
}
case 's/REMOVE_CHAT_CHANNEL': {
const { cid } = action;
if (!state.channels[cid]) {
return state;
}
const channels = { ...state.channels };
const messages = { ...state.messages };
delete messages[cid];
delete channels[cid];
return {
...state,
channels,
messages,
};
}
case 's/REC_CHAT_MESSAGE': {
const {
name, text, country, channel, user,
} = action;
if (!state.messages[channel] || !state.channels[channel]) {
return state;
}
const ts = Math.round(Date.now() / 1000);
msgId += 1;
const messages = {
...state.messages,
[channel]: [
...state.messages[channel],
[name, text, country, user, ts, msgId],
],
};
if (messages[channel].length > MAX_CHAT_MESSAGES) {
messages[channel].splice(0, 2);
}
/*
* update timestamp of last message
*/
const channelArray = [...state.channels[channel]];
channelArray[2] = Date.now();
return {
...state,
channels: {
...state.channels,
[channel]: channelArray,
},
messages,
};
}
case 's/REC_CHAT_HISTORY': {
const { cid, history } = action;
for (let i = 0; i < history.length; i += 1) {
msgId += 1;
history[i].push(msgId);
}
return {
...state,
messages: {
...state.messages,
[cid]: history,
},
};
}
default:
return state;
}
}