feat: refactor the cache
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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 ?? ""}
|
||||
|
||||
Reference in New Issue
Block a user