refactor: lots updates

This commit is contained in:
zerosoul
2022-03-14 11:32:00 +08:00
parent 5d363b5a5f
commit 46cfda76d0
83 changed files with 2018 additions and 1486 deletions
+19 -44
View File
@@ -1,13 +1,7 @@
import { createSlice } from "@reduxjs/toolkit";
import BASE_URL, {
KEY_REFRESH_TOKEN,
KEY_TOKEN,
KEY_UID,
KEY_EXPIRE,
} from "../config";
import { getNonNullValues } from "../../common/utils";
import { KEY_REFRESH_TOKEN, KEY_TOKEN, KEY_UID, KEY_EXPIRE } from "../config";
const initialState = {
user: null,
uid: null,
token: localStorage.getItem(KEY_TOKEN),
expireTime: localStorage.getItem(KEY_EXPIRE) || new Date().getTime(),
refreshToken: localStorage.getItem(KEY_REFRESH_TOKEN),
@@ -17,8 +11,13 @@ const authDataSlice = createSlice({
initialState,
reducers: {
setAuthData(state, action) {
const { user, token, refresh_token, expired_in = 0 } = action.payload;
state.user = user;
const {
user: { uid },
token,
refresh_token,
expired_in = 0,
} = action.payload;
state.uid = uid;
state.token = token;
state.refreshToken = refresh_token;
// 当前时间往后推expire时长
@@ -29,43 +28,20 @@ const authDataSlice = createSlice({
localStorage.setItem(KEY_EXPIRE, expireTime);
localStorage.setItem(KEY_TOKEN, token);
localStorage.setItem(KEY_REFRESH_TOKEN, refresh_token);
localStorage.setItem(KEY_UID, user.uid);
localStorage.setItem(KEY_UID, uid);
},
setUserData(state, action) {
const user = action.payload;
state.user = user;
},
updateLoginedUserByLogs(state, action) {
const logs = action.payload;
logs.forEach(({ action, uid, ...rest }) => {
switch (action) {
case "update":
{
const vals = getNonNullValues(rest);
console.log("update vals", vals);
if (Object.keys(vals).includes("avatar_updated_at")) {
vals.avatar = `${BASE_URL}/resource/avatar?uid=${uid}&t=${vals.avatar_updated_at}`;
}
state.user = { ...state.user, ...vals };
}
break;
default:
break;
}
});
},
clearAuthData(state) {
resetAuthData() {
console.log("clear auth data");
state.user = null;
state.token = null;
state.refreshToken = null;
// remove local data
localStorage.removeItem(KEY_EXPIRE);
localStorage.removeItem(KEY_TOKEN);
localStorage.removeItem(KEY_REFRESH_TOKEN);
localStorage.removeItem(KEY_UID);
return initialState;
},
setUid(state, action) {
const uid = action.payload;
state.uid = uid;
},
updateToken(state, action) {
const { token, refresh_token, expired_in } = action.payload;
@@ -81,10 +57,9 @@ const authDataSlice = createSlice({
},
});
export const {
updateToken,
setAuthData,
setUserData,
clearAuthData,
updateLoginedUserByLogs,
resetAuthData,
setUid,
updateToken,
} = authDataSlice.actions;
export default authDataSlice.reducer;
+29 -31
View File
@@ -1,55 +1,53 @@
import { createSlice } from "@reduxjs/toolkit";
const initialState = {};
const initialState = {
ids: [],
byId: {},
};
const channelsSlice = createSlice({
name: `channels`,
initialState,
reducers: {
clearChannels() {
resetChannels() {
return initialState;
},
setChannels(state, action) {
fullfillChannels(state, action) {
console.log("set channels store", state);
const chs = action.payload || [];
return Array.isArray(chs)
? Object.fromEntries(
chs.map((c) => {
const { gid, ...rest } = c;
return [gid, rest];
})
)
: chs;
},
updateChannel(state, action) {
// console.log("set channels store", action);
const { id, name, description } = action.payload;
const oObj = state[id];
const newObj = { ...oObj, name, description };
state[id] = newObj;
state.ids = chs.map(({ gid }) => gid);
state.byId = Object.fromEntries(
chs.map((c) => {
const { gid } = c;
return [gid, c];
})
);
},
addChannel(state, action) {
// console.log("set channels store", action);
const ch = action.payload;
const { gid, ...rest } = ch;
state[gid] = rest;
state.ids.push(gid);
state.byId[gid] = rest;
},
deleteChannel(state, action) {
updateChannel(state, action) {
// console.log("set channels store", action);
const { id, ...rest } = action.payload;
state.byId[id] = { ...state.byId[id], ...rest };
},
removeChannel(state, action) {
const gid = action.payload;
delete state[gid];
const idx = state.ids.findIndex((i) => i == gid);
if (idx > -1) {
state.ids.splice(idx, 1);
delete state.byId[gid];
}
},
// clearAuthData(state) {
// console.log("clear auth data");
// state.user = null;
// state.token = null;
// state.refreshToken = null;
// },
},
});
export const {
clearChannels,
setChannels,
resetChannels,
fullfillChannels,
addChannel,
deleteChannel,
updateChannel,
removeChannel,
} = channelsSlice.actions;
export default channelsSlice.reducer;
+29 -30
View File
@@ -1,21 +1,31 @@
import { createSlice } from "@reduxjs/toolkit";
import { getNonNullValues } from "../../common/utils";
const initialState = [];
const initialState = {
ids: [],
byId: {},
};
const contactsSlice = createSlice({
name: `contacts`,
initialState,
reducers: {
clearContacts() {
resetContacts() {
return initialState;
},
setContacts(state, action) {
console.log("set Contacts store", state);
fullfillContacts(state, action) {
console.log("set Contacts store", action);
const contacts = action.payload || [];
return contacts;
state.ids = contacts.map(({ uid }) => uid);
state.byId = Object.fromEntries(
contacts.map((c) => {
const { uid } = c;
return [uid, c];
})
);
},
removeContact(state, action) {
const uid = action.payload;
return state.filter((c) => c.uid != uid);
state.ids = state.ids.filter((i) => i != uid);
delete state.byId[uid];
},
updateUsersByLogs(state, action) {
const changeLogs = action.payload;
@@ -24,34 +34,25 @@ const contactsSlice = createSlice({
case "update":
{
const vals = getNonNullValues(rest);
const curr = state.find(({ uid: id }) => id == uid);
console.log("update vals", vals, curr);
if (curr) {
if (state.byId[uid]) {
Object.keys(vals).forEach((k) => {
curr[k] = vals[k];
state.byId[uid][k] = vals[k];
});
}
}
break;
case "create":
{
const idx = state.findIndex((o) => {
return o.uid == uid;
});
if (idx > -1) {
state.splice(idx, 1, { uid, ...rest });
} else {
state.push({ uid, ...rest });
}
state.byId[uid] = { uid, ...rest };
state.ids.push(uid);
}
break;
case "delete":
{
const idx = state.findIndex((o) => {
return o.uid == uid;
});
const idx = state.ids.findIndex((i) => i == uid);
if (idx > -1) {
state.splice(idx, 1);
state.ids.splice(idx, 1);
delete state.byId[uid];
}
}
break;
@@ -63,21 +64,19 @@ const contactsSlice = createSlice({
},
updateUsersStatus(state, action) {
const onlines = action.payload;
onlines.forEach((item) => {
const { uid, online = false } = item;
const curr = state.find(({ uid: id }) => id == uid);
onlines.forEach((data) => {
const { uid, online = false } = data;
// console.log("update user status", curr, online);
if (curr) {
curr.online = online;
if (state.byId[uid]) {
state.byId[uid].online = online;
}
});
},
},
});
export const {
clearContacts,
setContacts,
removeContact,
resetContacts,
fullfillContacts,
updateUsersByLogs,
updateUsersStatus,
} = contactsSlice.actions;
+32
View File
@@ -0,0 +1,32 @@
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
usersVersion: 0,
afterMid: 0,
};
const footprintSlice = createSlice({
name: "footprint",
initialState,
reducers: {
resetFootprint() {
return initialState;
},
fullfillFootprint(state, action) {
return action.payload;
},
updateUsersVersion(state, action) {
const usersVersion = action.payload;
state.usersVersion = usersVersion;
},
updateAfterMid(state, action) {
const afterMid = action.payload;
state.afterMid = afterMid;
},
},
});
export const {
resetFootprint,
fullfillFootprint,
updateAfterMid,
updateUsersVersion,
} = footprintSlice.actions;
export default footprintSlice.reducer;
+18 -47
View File
@@ -1,67 +1,38 @@
import { createSlice } from "@reduxjs/toolkit";
import {
msgReaction,
msgAdd,
msgSetRead,
msgClearUnread,
msgUpdate,
msgDelete,
msgAddPending,
msgRemovePending,
msgReplacePending,
} from "./message.handler";
const initialState = {};
const channelMsgSlice = createSlice({
name: "channelMessage",
initialState,
reducers: {
clearChannelMsg() {
resetChannelMsg() {
return initialState;
},
initChannelMsg(state, action) {
fullfillChannelMsg(state, action) {
return action.payload;
},
addChannelMsg(state, action) {
msgAdd(state, action.payload);
const { id, mid } = action.payload;
if (state[id]) {
if (state[id].findIndex((id) => id == mid) > -1) return;
state[id].push(mid);
} else {
state[id] = [mid];
}
},
deleteChannelMsg(state, action) {
msgDelete(state, action.payload);
},
updateChannelMsg(state, action) {
msgUpdate(state, action.payload);
},
likeChannelMsg(state, action) {
msgReaction(state, action.payload);
},
setChannelMsgRead(state, action) {
msgSetRead(state, action.payload);
},
clearChannelMsgUnread(state, action) {
msgClearUnread(state, action.payload);
},
addChannelPendingMsg(state, action) {
msgAddPending(state, action.payload);
},
replaceChannelPendingMsg(state, action) {
msgReplacePending(state, action.payload);
},
removeChannelPendingMsg(state, action) {
msgRemovePending(state, action.payload);
removeChannelMsg(state, action) {
const { id, mid } = action.payload;
if (state[id]) {
const idx = state[id].findIndex((i) => i == mid);
state[id].splice(idx, 1);
}
},
},
});
export const {
updateChannelMsg,
deleteChannelMsg,
likeChannelMsg,
clearChannelMsg,
initChannelMsg,
clearChannelMsgUnread,
setChannelMsgRead,
resetChannelMsg,
fullfillChannelMsg,
addChannelMsg,
addChannelPendingMsg,
replaceChannelPendingMsg,
removeChannelPendingMsg,
removeChannelMsg,
} = channelMsgSlice.actions;
export default channelMsgSlice.reducer;
-130
View File
@@ -1,130 +0,0 @@
import { isObjectEqual } from "../../common/utils";
export const msgReaction = (state, payload) => {
const { id, from_uid, mid, action: reaction } = payload;
console.log("msg reaction: likes", id, mid, from_uid, reaction);
if (state[id] && state[id][mid]) {
if (!state[id][mid].likes) {
console.log("msg reaction: initial ");
state[id][mid].likes = {};
}
const currLikes = state[id][mid].likes;
// state[id][mid].likes = currLikes ? [...currLikes, reaction] : [reaction];
if (currLikes[reaction]) {
if (currLikes[reaction].includes(from_uid)) {
const idx = currLikes[reaction].findIndex((id) => {
return id == from_uid;
});
console.log("remove reaction", currLikes[reaction], idx, from_uid);
currLikes[reaction].splice(idx, 1);
} else {
currLikes[reaction].push(from_uid);
}
} else {
currLikes[reaction] = [from_uid];
}
// state[id][mid].likes = currLikes;
}
};
export const msgAdd = (state, payload) => {
const {
id,
content,
created_at,
mid,
reply_mid = null,
from_uid,
content_type,
unread = true,
} = payload;
const newMsg = { content, content_type, created_at, from_uid, unread };
if (reply_mid && state[id][reply_mid]) {
newMsg.reply = { mid: reply_mid, ...state[id][reply_mid] };
}
if (state[id]) {
let replaceMsg = state[id][mid];
// 如果存在,并且新消息和缓存消息不一样,则替换掉,并且改为已读(可能有问题)
if (replaceMsg) {
const copyMsg = { ...replaceMsg };
if (!isObjectEqual(copyMsg, newMsg)) {
state[id][mid] = { ...newMsg, unread: false };
}
} else {
state[id][mid] = newMsg;
}
} else {
state[id] = { [mid]: newMsg };
}
};
export const msgAddPending = (state, payload) => {
const {
id,
content,
created_at,
local_mid,
reply_mid = null,
from_uid,
content_type,
unread = false,
} = payload;
const newMsg = { content, content_type, created_at, from_uid, unread };
if (reply_mid && state[id][reply_mid]) {
newMsg.reply = { mid: reply_mid, ...state[id][reply_mid] };
}
if (state[id]) {
state[id][local_mid] = newMsg;
} else {
state[id] = { [local_mid]: newMsg };
}
};
export const msgReplacePending = (state, payload) => {
const { id, local_mid, server_mid } = payload;
if (state[id] && state[id][local_mid]) {
// 先赋值,再去delete
state[id] = Object.fromEntries(
Object.entries(state[id]).map(([key, obj]) => {
return key == local_mid ? [server_mid, obj] : [key, obj];
})
);
// state[id][server_mid] = { ...state[id][local_mid] };
// delete state[id][local_mid];
}
};
export const msgRemovePending = (state, payload) => {
const { id, local_mid } = payload;
if (state[id] && state[id][local_mid]) {
delete state[id][local_mid];
}
};
export const msgSetRead = (state, payload) => {
const { id, mid } = payload;
console.log("set read", id, mid);
if (state[id] && state[id][mid]) {
state[id][mid].unread = false;
}
};
export const msgDelete = (state, payload) => {
const { id, mid } = payload;
console.log("delete message", id, mid);
if (state[id][mid]) {
// state[id][mid].removed = true;
delete state[id][mid];
}
};
export const msgClearUnread = (state, id) => {
console.log("set all unread", id);
Object.entries(state[id]).forEach(([, obj]) => {
obj.unread = false;
});
};
export const msgUpdate = (state, payload) => {
const { id, mid, content, time } = payload;
console.log("update channel message", id, mid);
if (state[id][mid]) {
state[id][mid].content = content;
state[id][mid].edited = time;
}
};
+64
View File
@@ -0,0 +1,64 @@
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
replying: {},
};
const messageSlice = createSlice({
name: "message",
initialState,
reducers: {
resetMessage() {
return initialState;
},
fullfillMessage(state, action) {
return action.payload;
},
updateMessage(state, action) {
const { mid, ...rest } = action.payload;
state[mid] = { ...state[mid], ...rest };
},
readMessage(state, action) {
const mids = Array.isArray(action.payload)
? action.payload
: [action.payload];
mids.forEach((id) => {
if (state[id]) {
state[id].read = true;
}
});
},
addMessage(state, action) {
const { mid, sending } = action.payload;
// 如果是正发送,并且已存在,则不覆盖
if (sending && state[mid]) return;
state[mid] = action.payload;
},
removeMessage(state, action) {
const mid = action.payload;
delete state[mid];
},
addReplyingMessage(state, action) {
const { id, mid } = action.payload;
console.log("to ", id, mid);
state.replying[id] = mid;
},
removeReplyingMessage(state, action) {
const id = action.payload;
if (state.replying[id]) {
delete state.replying[id];
}
},
},
});
export const {
resetMessage,
fullfillMessage,
setMessage,
updateMessage,
readMessage,
addMessage,
removeMessage,
addReplyingMessage,
removeReplyingMessage,
} = messageSlice.actions;
export default messageSlice.reducer;
-47
View File
@@ -1,47 +0,0 @@
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
reply: {},
user: {},
channel: {},
};
const pendingMessageSlice = createSlice({
name: "pendingMessage",
initialState,
reducers: {
clearPendingMsg() {
return initialState;
},
addPendingMessage(state, action) {
const { type = "user", msg } = action.payload;
const { id, mid } = msg;
const curr = state[type][id] || {};
curr[mid] = { ...msg, pending: true };
state[type][id] = curr;
},
setReplyMessage(state, action) {
const { id, msg } = action.payload;
console.log("reply to ", id, msg);
state.reply[id] = msg;
},
removeReplyMessage(state, action) {
const id = action.payload;
if (state.reply[id]) {
delete state.reply[id];
}
},
removePendingMessage(state, action) {
const { id, mid, type = "user" } = action.payload;
console.log("remove msg", type, id, mid);
delete state[type][id][mid];
},
},
});
export const {
clearPendingMsg,
addPendingMessage,
removePendingMessage,
removeReplyMessage,
setReplyMessage,
} = pendingMessageSlice.actions;
export default pendingMessageSlice.reducer;
+39
View File
@@ -0,0 +1,39 @@
import { createSlice } from "@reduxjs/toolkit";
const initialState = {};
const reactionMessageSlice = createSlice({
name: "reactionMessage",
initialState,
reducers: {
resetReactionMessage() {
return initialState;
},
fullfillReactionMessage(state, action) {
return action.payload;
},
toggleReactionMessage(state, action) {
const { from_uid, mid, action: reaction } = action.payload;
console.log("msg reaction", mid, from_uid, reaction);
if (!state[mid]) {
state[mid] = {};
}
if (state[mid][reaction]) {
const reactionUids = state[mid][reaction];
const idx = reactionUids.findIndex((id) => id == from_uid);
if (idx > -1) {
reactionUids.splice(idx, 1);
} else {
reactionUids.push(from_uid);
}
} else {
state[mid][reaction] = [from_uid];
}
},
},
});
export const {
resetReactionMessage,
fullfillReactionMessage,
toggleReactionMessage,
} = reactionMessageSlice.actions;
export default reactionMessageSlice.reducer;
+25 -44
View File
@@ -1,61 +1,42 @@
import { createSlice } from "@reduxjs/toolkit";
import {
msgReaction,
msgAdd,
msgSetRead,
msgUpdate,
msgDelete,
msgAddPending,
msgRemovePending,
msgReplacePending,
} from "./message.handler";
const initialState = {};
const initialState = {
ids: [],
byId: {},
};
const userMsgSlice = createSlice({
name: "userMessage",
initialState,
reducers: {
clearUserMsg() {
resetUserMsg() {
return initialState;
},
initUserMsg(state, action) {
return action.payload;
fullfillUserMsg(state, action) {
state.ids = Object.keys(action.payload);
state.byId = action.payload;
},
addUserMsg(state, action) {
msgAdd(state, action.payload);
const { id, mid } = action.payload;
if (state.byId[id]) {
if (state.byId[id].findIndex((id) => id == mid) > -1) return;
state.byId[id].push(mid);
} else {
state.byId[id] = [mid];
state.ids.push(id);
}
},
likeUserMsg(state, action) {
msgReaction(state, action.payload);
},
updateUserMsg(state, action) {
msgUpdate(state, action.payload);
},
deleteUserMsg(state, action) {
msgDelete(state, action.payload);
},
setUserMsgRead(state, action) {
msgSetRead(state, action.payload);
},
addUserPendingMsg(state, action) {
msgAddPending(state, action.payload);
},
replaceUserPendingMsg(state, action) {
msgReplacePending(state, action.payload);
},
removeUserPendingMsg(state, action) {
msgRemovePending(state, action.payload);
removeUserMsg(state, action) {
const { id, mid } = action.payload;
if (state.byId[id]) {
const idx = state.byId[id].findIndex((i) => i == mid);
state.byId[id].splice(idx, 1);
}
},
},
});
export const {
updateUserMsg,
likeUserMsg,
deleteUserMsg,
clearUserMsg,
initUserMsg,
resetUserMsg,
fullfillUserMsg,
addUserMsg,
setUserMsgRead,
addUserPendingMsg,
replaceUserPendingMsg,
removeUserPendingMsg,
removeUserMsg,
} = userMsgSlice.actions;
export default userMsgSlice.reducer;
+7
View File
@@ -0,0 +1,7 @@
reset
fullfill
set
add
update
remove
toggle
-38
View File
@@ -1,38 +0,0 @@
import { createSlice } from "@reduxjs/toolkit";
import { KEY_AFTER_MID, KEY_USERS_VERSION, KEY_UID } from "../config";
const initialState = {
usersVersion: null,
afterMid: null,
};
const visitMarkSlice = createSlice({
name: "visitMark",
initialState,
reducers: {
clearMark() {
return initialState;
},
setMark(state, action) {
const mark = action.payload;
return mark;
},
setUsersVersion(state, action) {
const { version } = action.payload;
state.usersVersion = version;
let currUid = localStorage.getItem(KEY_UID);
localStorage.setItem(`${KEY_USERS_VERSION}_${currUid}`, version);
},
setAfterMid(state, action) {
const { mid } = action.payload;
state.afterMid = mid;
let currUid = localStorage.getItem(KEY_UID);
localStorage.setItem(`${KEY_AFTER_MID}_${currUid}`, mid);
},
},
});
export const {
setMark,
setUsersVersion,
setAfterMid,
clearMark,
} = visitMarkSlice.actions;
export default visitMarkSlice.reducer;