feat: refactor the cache

This commit is contained in:
zerosoul
2022-03-04 10:15:30 +08:00
parent b6b0a0c5ef
commit acd007fb71
28 changed files with 622 additions and 341 deletions
+28 -15
View File
@@ -57,7 +57,12 @@ const StyledWrapper = styled.div`
right: 0;
}
`;
export default function AvatarUploader({ url = "", name = "", uploadImage }) {
export default function AvatarUploader({
url = "",
name = "",
uploadImage,
disabled = false,
}) {
const [uploading, setUploading] = useState(false);
const [currSrc, setCurrSrc] = useState("");
useEffect(() => {
@@ -80,21 +85,29 @@ export default function AvatarUploader({ url = "", name = "", uploadImage }) {
<StyledWrapper>
<div className="avatar">
<img src={currSrc} alt="avatar" />
<div className="tip">{uploading ? `Uploading` : `Change Avatar`}</div>
<input
multiple={false}
onChange={handleUpload}
type="file"
accept="image/*"
name="avatar"
id="avatar"
/>
{!disabled && (
<>
<div className="tip">
{uploading ? `Uploading` : `Change Avatar`}
</div>
<input
multiple={false}
onChange={handleUpload}
type="file"
accept="image/*"
name="avatar"
id="avatar"
/>
</>
)}
</div>
<img
src="https://static.nicegoodthings.com/project/rustchat/icon.avatar.uploader.svg"
alt="icon"
className="icon"
/>
{!disabled && (
<img
src="https://static.nicegoodthings.com/project/rustchat/icon.avatar.uploader.svg"
alt="icon"
className="icon"
/>
)}
</StyledWrapper>
);
}
+71 -48
View File
@@ -17,10 +17,9 @@ import {
import {
updateToken,
clearAuthData,
setUsersVersion,
setAfterMid,
updateLoginedUserByLogs,
} from "../../../app/slices/auth.data";
import { setUsersVersion, setAfterMid } from "../../../app/slices/visit.mark";
import { addChannelMsg } from "../../../app/slices/message.channel";
import { addUserMsg } from "../../../app/slices/message.user";
@@ -161,50 +160,74 @@ const NotificationHub = ({ usersVersion = 0, afterMid = 0 }) => {
dispatch(deleteChannel(data.gid));
break;
case "chat":
// console.log("chat data", data);
if (data.gid) {
// channel msg
const { gid, ...rest } = data;
console.log("compare", rest, currUser, rest.from_uid != currUser.uid);
const isSelf = rest.from_uid == currUser.uid;
dispatch(
addChannelMsg({
id: gid,
// 自己发的 就不用标记未读
unread: !isSelf,
...rest,
})
);
// group message notification
if (!isSelf) {
showNotification({
body: rest.content,
data: {
path: `/chat/channel/${gid}`,
},
});
}
} else {
// user msg
const isSelf = data.from_uid == currUser.uid;
dispatch(
addUserMsg({
id: data.from_uid,
unread: !isSelf,
...data,
})
);
if (!isSelf) {
showNotification({
body: data.content,
data: {
path: `/chat/dm/${data.from_uid}`,
},
});
{
// console.log("chat data", data);
const {
detail: { target },
} = data;
const {
created_at,
mid,
from_uid,
detail: { content, content_type, expires_in, type },
} = data;
if (typeof target.gid !== "undefined") {
// channel msg
const gid = target.gid;
const isSelf = from_uid == currUser.uid;
dispatch(
addChannelMsg({
id: gid,
from_uid,
// 自己发的 就不用标记未读
unread: !isSelf,
created_at,
mid,
content,
content_type,
expires_in,
type,
})
);
// group message notification
if (!isSelf) {
showNotification({
body: content,
data: {
path: `/chat/channel/${gid}`,
},
});
}
} else {
// user msg
const isSelf = data.from_uid == currUser.uid;
dispatch(
addUserMsg({
// 此处需要特别注意
id: isSelf ? target.uid : from_uid,
from_uid: from_uid,
unread: !isSelf,
created_at,
mid,
content,
content_type,
expires_in,
type,
})
);
if (!isSelf) {
showNotification({
body: data.content,
data: {
path: `/chat/dm/${data.from_uid}`,
},
});
}
}
// 更新after_mid
dispatch(setAfterMid({ mid: data.mid }));
}
// 更新after_mid
dispatch(setAfterMid({ mid: data.mid }));
break;
default:
@@ -214,7 +237,7 @@ const NotificationHub = ({ usersVersion = 0, afterMid = 0 }) => {
};
return null;
};
// function compareToken(prevHub, nextHub) {
// return prevHub.token === nextHub.token;
// }
export default React.memo(NotificationHub);
function compareToken(prevHub, nextHub) {
return prevHub.token === nextHub.token;
}
export default React.memo(NotificationHub, compareToken);
@@ -1,14 +1,20 @@
// import React from "react";
import { useEffect } from "react";
import { useEffect, useState } from "react";
import styled from "styled-components";
import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
import { clearAuthData } from "../../../app/slices/auth.data";
import { toggleSetting } from "../../../app/slices/ui";
import { clearAuthData } from "../../../app/slices/auth.data";
import { clearMark } from "../../../app/slices/visit.mark";
import { clearChannels } from "../../../app/slices/channels";
import { clearContacts } from "../../../app/slices/contacts";
import { clearChannelMsg } from "../../../app/slices/message.channel";
import { clearUserMsg } from "../../../app/slices/message.user";
import { clearPendingMsg } from "../../../app/slices/message.pending";
// import BASE_URL from "../../app/config";
import { useLazyLogoutQuery } from "../../../app/services/auth";
import Button from "../styled/Button";
import Checkbox from "../styled/Checkbox";
const StyledConfirm = styled.div`
padding: 32px;
filter: drop-shadow(0px 25px 50px rgba(31, 41, 55, 0.25));
@@ -20,12 +26,26 @@ const StyledConfirm = styled.div`
color: #374151;
margin-bottom: 16px;
}
.desc {
.desc,
.clear {
font-weight: normal;
font-size: 14px;
line-height: 20px;
color: #6b7280;
margin-bottom: 64px;
margin-bottom: 12px;
}
.clear {
display: flex;
justify-content: flex-end;
align-items: center;
.txt {
cursor: pointer;
color: orange;
margin-right: 12px;
}
input {
cursor: pointer;
}
}
.btns {
width: 100%;
@@ -37,24 +57,48 @@ const StyledConfirm = styled.div`
`;
import Modal from "../Modal";
export default function LogoutConfirmModal({ closeModal }) {
const [clearLocal, setClearLocal] = useState(false);
const dispatch = useDispatch();
const navigate = useNavigate();
const [logout, { isLoading, isSuccess }] = useLazyLogoutQuery();
const handleLogout = () => {
logout();
};
const handleCheck = (evt) => {
setClearLocal(evt.target.checked);
};
useEffect(() => {
if (isSuccess) {
dispatch(toggleSetting());
if (clearLocal) {
console.log("clear all store");
dispatch(clearMark());
dispatch(clearChannelMsg());
dispatch(clearUserMsg());
dispatch(clearChannels());
dispatch(clearContacts());
dispatch(clearPendingMsg());
}
dispatch(clearAuthData());
// closeModal();
dispatch(toggleSetting());
navigate("/login");
}
}, [isSuccess]);
}, [isSuccess, clearLocal]);
return (
<Modal id="modal-modal">
<StyledConfirm className="animate__animated animate__fadeInDown animate__faster">
<h3 className="title">Log Out</h3>
<p className="desc">Are you sure want to log out this account?</p>
<div className="clear">
<label htmlFor="clear_cb" className="txt">
Clear local data
</label>
<Checkbox
name="clear_cb"
checked={clearLocal}
onChange={handleCheck}
/>
</div>
<div className="btns">
<Button onClick={closeModal}>Cancel</Button>
<Button onClick={handleLogout} className="danger">
+14 -7
View File
@@ -1,6 +1,6 @@
import { useState, useEffect } from "react";
import styled from "styled-components";
// import { useSelector } from "react-redux";
import { useSelector } from "react-redux";
import {
useGetServerQuery,
useUpdateServerMutation,
@@ -66,6 +66,7 @@ const StyledWrapper = styled.div`
}
`;
export default function Overview() {
const currUser = useSelector((store) => store.authData.user);
const [changed, setChanged] = useState(false);
const [values, setValues] = useState(null);
const { data, refetch } = useGetServerQuery();
@@ -118,28 +119,33 @@ export default function Overview() {
if (!values) return null;
const { name, description, logo } = values;
const isAdmin = currUser?.is_admin;
return (
<StyledWrapper>
<div className="logo">
<div className="preview">
<LogoUploader
disabled={!isAdmin}
url={uploadSuccess ? `${logo}?t=${new Date().getTime()}` : logo}
name={name}
uploadImage={uploadLogo}
/>
</div>
<div className="upload">
<div className="tip">
Minimum size is 128x128, We recommend at least 512x512 for the
server. Max size limited to 5M.
{isAdmin && (
<div className="upload">
<div className="tip">
Minimum size is 128x128, We recommend at least 512x512 for the
server. Max size limited to 5M.
</div>
<button className="btn">Upload Image</button>
</div>
<button className="btn">Upload Image</button>
</div>
)}
</div>
<div className="inputs">
<div className="input">
<Label htmlFor="name">Server Name</Label>
<Input
disabled={!isAdmin}
data-type="name"
onChange={handleChange}
value={name}
@@ -151,6 +157,7 @@ export default function Overview() {
<div className="input">
<Label htmlFor="desc">Server Description</Label>
<Textarea
disabled={!isAdmin}
data-type="description"
onChange={handleChange}
value={description ?? ""}