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
+24 -61
View File
@@ -1,12 +1,13 @@
import { useEffect, useState } from "react";
import { useSelector, useDispatch } from "react-redux";
import dayjs from "dayjs";
// import dayjs from "dayjs";
import useChatScroll from "../../../common/hook/useChatScroll";
import Message from "../../../common/component/Message";
import ChannelIcon from "../../../common/component/ChannelIcon";
import Send from "../../../common/component/Send";
import { clearChannelMsgUnread } from "../../../app/slices/message.channel";
// import { readMessage } from "../../../app/slices/message";
import Contact from "../../../common/component/Contact";
import Layout from "../Layout";
import {
@@ -16,37 +17,29 @@ import {
StyledHeader,
} from "./styled";
export default function ChannelChat({
cid = "",
unreads = 0,
data = {},
dropFiles = [],
}) {
export default function ChannelChat({ cid = "", dropFiles = [] }) {
// const containerRef = useRef(null);
const [dragFiles, setDragFiles] = useState([]);
const dispatch = useDispatch();
const { msgs, users } = useSelector((store) => {
// const dispatch = useDispatch();
const { msgIds, userIds, data } = useSelector((store) => {
return {
msgs: store.channelMessage[cid] || {},
users: store.contacts,
msgIds: store.channelMessage[cid] || [],
userIds: store.contacts.ids,
data: store.channels.byId[cid],
};
});
const handleClearUnreads = () => {
dispatch(clearChannelMsgUnread(cid));
};
const ref = useChatScroll(msgIds);
// const handleClearUnreads = () => {
// dispatch(readMessage(msgIds));
// };
useEffect(() => {
if (dropFiles.length) {
setDragFiles(dropFiles);
}
}, [dropFiles]);
const { name, description, is_public, members = [] } = data;
const filteredUsers =
members.length == 0
? users
: users.filter((u) => {
return members.includes(u.uid);
});
console.log("channel message list", msgs);
const memberIds = members.length == 0 ? userIds : members;
console.log("channel message list", msgIds);
return (
<Layout
setDragFiles={setDragFiles}
@@ -82,61 +75,31 @@ export default function ChannelChat({
}
contacts={
<StyledContacts>
{filteredUsers.map(({ name, uid }) => {
return <Contact key={name} uid={uid} popover />;
{memberIds.map((uid) => {
return <Contact key={uid} uid={uid} popover />;
})}
</StyledContacts>
}
>
<StyledChannelChat>
<div className="wrapper">
<div className="wrapper" ref={ref}>
<div className="info">
<h2 className="title">Welcome to #{name} !</h2>
<p className="desc">This is the start of the #{name} channel. </p>
{/* <button className="edit">Edit Channel</button> */}
</div>
<div className="chat">
{Object.entries(msgs)
.sort(([, msg1], [, msg2]) => {
return msg1.created_at - msg2.created_at;
})
.map(([mid, msg], idx) => {
if (!msg) return null;
const {
likes = {},
pending = false,
from_uid,
content,
content_type,
created_at,
unread,
edited,
reply,
} = msg;
return (
<Message
reply={reply}
edited={edited}
likes={likes}
pending={pending}
content_type={content_type}
unread={unread}
gid={cid}
mid={mid}
key={idx}
time={created_at}
fromUid={from_uid}
content={content}
/>
);
})}
{msgIds.map((mid, idx) => {
// if (!msg) return null;
return <Message contextId={cid} mid={mid} key={idx} />;
})}
</div>
</div>
<Send dragFiles={dragFiles} id={cid} type="channel" name={name} />
<div className="placeholder"></div>
</StyledChannelChat>
{unreads != 0 && (
{/* {unreads != 0 && (
<StyledNotification>
<div className="content">
{unreads} new messages
@@ -148,7 +111,7 @@ export default function ChannelChat({
Mark As Read
</button>
</StyledNotification>
)}
)} */}
</Layout>
);
}
+19 -10
View File
@@ -2,19 +2,26 @@
import { NavLink, useNavigate } from "react-router-dom";
import { useDrop } from "react-dnd";
import { NativeTypes } from "react-dnd-html5-backend";
import { useDispatch } from "react-redux";
import { useDispatch, useSelector } from "react-redux";
import useContextMenu from "../../common/hook/useContextMenu";
import ContextMenu from "../../common/component/ContextMenu";
import { toggleChannelSetting } from "../../app/slices/ui";
import ChannelIcon from "../../common/component/ChannelIcon";
const NavItem = ({ data, setFiles, contextMenuEventHandler }) => {
import getUnreadCount from "./getUnreadCount";
const NavItem = ({ id, setFiles, contextMenuEventHandler }) => {
const dispatch = useDispatch();
const navigate = useNavigate();
const { channel, mids, messageData } = useSelector((store) => {
return {
channel: store.channels.byId[id],
mids: store.channelMessage[id],
messageData: store.message,
};
});
const handleChannelSetting = (evt) => {
evt.preventDefault();
evt.stopPropagation();
dispatch(toggleChannelSetting(data.id));
dispatch(toggleChannelSetting(id));
};
const [{ isActive }, drop] = useDrop(() => ({
accept: [NativeTypes.FILE],
@@ -22,7 +29,7 @@ const NavItem = ({ data, setFiles, contextMenuEventHandler }) => {
if (dataTransfer.files.length) {
// console.log(files, rest);
setFiles([...dataTransfer.files]);
navigate(`/chat/channel/${data.id}`);
navigate(`/chat/channel/${id}`);
// 重置
setTimeout(() => {
setFiles([]);
@@ -33,7 +40,8 @@ const NavItem = ({ data, setFiles, contextMenuEventHandler }) => {
isActive: monitor.canDrop() && monitor.isOver(),
}),
}));
const { id, is_public, name, unreads } = data;
const { is_public, name } = channel;
const unreads = getUnreadCount(mids, messageData);
return (
<NavLink
onContextMenu={contextMenuEventHandler}
@@ -57,7 +65,8 @@ const NavItem = ({ data, setFiles, contextMenuEventHandler }) => {
</NavLink>
);
};
export default function ChannelList({ channels, setDropFiles }) {
export default function ChannelList({ setDropFiles }) {
const channelIds = useSelector((store) => store.channels.ids);
const {
visible: contextMenuVisible,
posX,
@@ -67,12 +76,12 @@ export default function ChannelList({ channels, setDropFiles }) {
} = useContextMenu();
return (
<>
{channels.map(({ id, is_public, name, description, unreads }) => {
{channelIds.map((cid) => {
return (
<NavItem
contextMenuEventHandler={handleContextMenuEvent}
key={id}
data={{ id, is_public, name, description, unreads }}
key={cid}
id={cid}
setFiles={setDropFiles}
/>
);
+15 -46
View File
@@ -1,5 +1,6 @@
import { useState, useEffect } from "react";
import { useSelector } from "react-redux";
import useChatScroll from "../../../common/hook/useChatScroll";
import Message from "../../../common/component/Message";
import Send from "../../../common/component/Send";
import Contact from "../../../common/component/Contact";
@@ -10,19 +11,17 @@ import { StyledHeader, StyledDMChat } from "./styled";
export default function DMChat({ uid = "", dropFiles = [] }) {
console.log("dm files", dropFiles);
const [dragFiles, setDragFiles] = useState([]);
const contacts = useSelector((store) => store.contacts);
const { msgs } = useSelector((store) => {
// const [mids, setMids] = useState([]);
const { msgIds, currUser } = useSelector((store) => {
return {
msgs: store.userMessage[uid] || {},
currUser: store.contacts.byId[uid],
msgIds: store.userMessage.byId[uid] || [],
};
});
const [currUser, setCurrUser] = useState(null);
useEffect(() => {
console.log({ uid });
if (uid && contacts) {
setCurrUser(contacts.find((c) => c.uid == uid));
}
}, [uid, contacts]);
const ref = useChatScroll(msgIds);
// useEffect(() => {
// setMids(msgIds);
// }, [msgIds]);
useEffect(() => {
if (dropFiles.length) {
setDragFiles(dropFiles);
@@ -67,42 +66,12 @@ export default function DMChat({ uid = "", dropFiles = [] }) {
}
>
<StyledDMChat>
<div className="chat">
{Object.entries(msgs)
.sort(([, msg1], [, msg2]) => {
return msg1.created_at - msg2.created_at;
})
.map(([mid, msg], idx) => {
if (!msg) return null;
// console.log("user msg", msg);
const {
likes = {},
from_uid,
content,
content_type,
created_at,
unread,
pending = false,
edited,
reply,
} = msg;
return (
<Message
reply={reply}
likes={likes}
edited={edited}
pending={pending}
content_type={content_type}
unread={unread}
fromUid={from_uid}
mid={mid}
key={idx}
time={created_at}
uid={uid}
content={content}
/>
);
})}
<div className="chat" ref={ref}>
{msgIds.map((mid) => {
// if (!msg) return null;
// console.log("user msg", msg);
return <Message mid={mid} key={mid} contextId={uid} />;
})}
</div>
</StyledDMChat>
<div className="placeholder"></div>
+2 -3
View File
@@ -45,13 +45,12 @@ export const StyledHeader = styled.header`
export const StyledDMChat = styled.article`
position: relative;
width: 100%;
padding-top: 25px;
/* margin-bottom: 120px; */
padding-top: 20px;
> .chat {
display: flex;
flex-direction: column;
padding: 0 16px;
padding-top: 10px;
padding-top: 15px;
padding-bottom: 25px;
height: calc(100vh - 56px - 80px);
overflow-y: scroll;
+19 -10
View File
@@ -4,9 +4,16 @@ import dayjs from "dayjs";
import relativeTime from "dayjs/plugin/relativeTime";
import { useDrop } from "react-dnd";
import { NativeTypes } from "react-dnd-html5-backend";
import { useSelector } from "react-redux";
import Contact from "../../common/component/Contact";
dayjs.extend(relativeTime);
const NavItem = ({ data, setFiles }) => {
const NavItem = ({ uid, mid, unreads, setFiles }) => {
const { currMsg, currUser } = useSelector((store) => {
return {
currUser: store.contacts.byId[uid],
currMsg: store.message[mid],
};
});
const navigate = useNavigate();
const [{ isActive }, drop] = useDrop(() => ({
accept: [NativeTypes.FILE],
@@ -14,7 +21,7 @@ const NavItem = ({ data, setFiles }) => {
if (dataTransfer.files.length) {
// console.log(files, rest);
setFiles([...dataTransfer.files]);
navigate(`/chat/dm/${data.uid}`);
navigate(`/chat/dm/${uid}`);
// 重置
setTimeout(() => {
setFiles([]);
@@ -25,7 +32,7 @@ const NavItem = ({ data, setFiles }) => {
isActive: monitor.canDrop() && monitor.isOver(),
}),
}));
const { uid, user, lastMsg, unreads } = data;
if (!currUser || !currMsg) return null;
return (
<NavLink
ref={drop}
@@ -33,15 +40,15 @@ const NavItem = ({ data, setFiles }) => {
className={`session ${isActive ? "drop_over" : ""}`}
to={`/chat/dm/${uid}`}
>
<Contact compact interactive={false} className="avatar" uid={user.uid} />
<Contact compact interactive={false} className="avatar" uid={uid} />
<div className="details">
<div className="up">
<span className="name">{user.name}</span>
<time>{dayjs(lastMsg.created_at).fromNow()}</time>
<span className="name">{currUser.name}</span>
{currMsg && <time>{dayjs(currMsg.created_at).fromNow()}</time>}
</div>
<div className="down">
<div className="msg">{lastMsg.content}</div>
{currMsg && <div className="msg">{currMsg.content}</div>}
{unreads > 0 && <i className="badge">{unreads}</i>}
</div>
</div>
@@ -49,12 +56,14 @@ const NavItem = ({ data, setFiles }) => {
);
};
export default function DMList({ sessions, setDropFiles }) {
return sessions.map(({ uid, user, lastMsg, unreads } = {}) => {
if (!user) return null;
return sessions.map(({ uid, lastMid, unreads } = {}) => {
if (!uid) return null;
return (
<NavItem
key={uid}
data={{ uid, user, lastMsg, unreads }}
uid={uid}
mid={lastMid}
unreads={unreads}
setFiles={setDropFiles}
/>
);
+12
View File
@@ -0,0 +1,12 @@
const getUnreadCount = (mids, messageData) => {
if (!mids || !messageData) return 0;
let unreads = 0;
mids.forEach((id) => {
if (!messageData[id].read) {
unreads++;
}
});
return unreads;
};
export default getUnreadCount;
+18 -36
View File
@@ -16,20 +16,18 @@ import ChannelList from "./ChannelList";
import ContactsModal from "../../common/component/ContactsModal";
import ChannelModal from "../../common/component/ChannelModal";
import DMList from "./DMList";
import getUnreadCount from "./getUnreadCount";
export default function ChatPage() {
const [channelDropFiles, setChannelDropFiles] = useState([]);
const [userDropFiles, setUserDropFiles] = useState([]);
const { contacts, channels, UserMsgData, ChannelMsgData } = useSelector(
(store) => {
return {
contacts: store.contacts,
channels: store.channels,
UserMsgData: store.userMessage,
ChannelMsgData: store.channelMessage,
};
}
);
const { contactsData, UserMsgData, messageData } = useSelector((store) => {
return {
contactsData: store.contacts.byId,
UserMsgData: store.userMessage,
messageData: store.message,
};
});
const [channelModalVisible, setChannelModalVisible] = useState(false);
const [contactsModalVisible, setContactsModalVisible] = useState(false);
const { channel_id, user_id } = useParams();
@@ -39,31 +37,19 @@ export default function ChatPage() {
const toggleChannelModalVisible = () => {
setChannelModalVisible((prev) => !prev);
};
const getUnreadCount = (gid) => {
return Object.values(ChannelMsgData[gid] || {}).filter((m) => m.unread)
.length;
};
// const getUnreadCount = (gid) => {
// return Object.values(ChannelMsgData[gid] || {}).filter((m) => m.read)
// .length;
// };
const handleToggleExpand = (evt) => {
const { currentTarget } = evt;
const listEle = currentTarget.parentElement.parentElement;
listEle.classList.toggle("collapse");
};
if (!contacts) return null;
const tmpSessionUser = contacts.find((c) => c.uid == user_id);
const transformedChannels = Object.entries(channels).map(([key, obj]) => {
const unreads = Object.values(ChannelMsgData[key] || {}).filter(
(m) => m.unread
).length;
return { id: key, ...obj, unreads };
});
const sessions = Object.keys(UserMsgData).map((uid) => {
let currUser = contacts.find((c) => c.uid == uid);
if (!currUser) return undefined;
let lastMid = Object.keys(UserMsgData[uid]).sort().pop();
let unreads = Object.values(UserMsgData[uid] || {}).filter((m) => m.unread)
.length;
let lastMsg = UserMsgData[uid][lastMid];
return { user: currUser, unreads, uid, lastMsg };
const tmpSessionUser = contactsData[user_id];
const sessions = UserMsgData.ids.map((uid) => {
const unreads = getUnreadCount(UserMsgData.byId[uid], messageData);
return { uid, unreads, lastMid: [...UserMsgData.byId[uid]].pop() };
});
return (
<>
@@ -93,10 +79,7 @@ export default function ChatPage() {
/>
</h3>
<nav className="nav">
<ChannelList
channels={transformedChannels}
setDropFiles={setChannelDropFiles}
/>
<ChannelList setDropFiles={setChannelDropFiles} />
</nav>
</div>
<div className="list dms">
@@ -117,7 +100,7 @@ export default function ChatPage() {
</h3>
<nav className="nav">
<DMList sessions={sessions} setDropFiles={setUserDropFiles} />
{user_id && !Object.keys(UserMsgData).includes(user_id) && (
{user_id && UserMsgData.ids.findIndex((i) => i == user_id) == -1 && (
<NavLink className="session" to={`/chat/dm/${user_id}`}>
<Contact
compact
@@ -147,7 +130,6 @@ export default function ChatPage() {
<ChannelChat
unreads={getUnreadCount(channel_id)}
cid={channel_id}
data={channels[channel_id]}
dropFiles={channelDropFiles}
/>
)}
-91
View File
@@ -1,91 +0,0 @@
// import React from "react";
// import toast from "react-hot-toast";
import { useState, useEffect } from "react";
import { useSelector } from "react-redux";
import { NavLink } from "react-router-dom";
import { BsChatText } from "react-icons/bs";
import { RiUserAddLine } from "react-icons/ri";
import { IoShareOutline } from "react-icons/io5";
import styled from "styled-components";
import Avatar from "../../common/component/Avatar";
const StyledWrapper = styled.div`
display: flex;
flex-direction: column;
justify-content: center;
align-items: flex-start;
margin-top: 80px;
width: 432px;
gap: 4px;
.avatar {
width: 80px;
height: 80px;
border-radius: 50%;
}
.name {
font-weight: bold;
font-size: 18px;
line-height: 100%;
color: #1c1c1e;
}
.email {
font-weight: normal;
font-size: 14px;
line-height: 20px;
color: #78787c;
}
.icons {
display: flex;
align-items: center;
padding: 26px 0;
gap: 28px;
.icon {
}
}
.line {
width: 100%;
height: 1px;
border: none;
background-color: rgba(0, 0, 0, 0.1);
}
`;
export default function Profile({ uid = null }) {
const contacts = useSelector((store) => store.contacts);
const [profile, setProfile] = useState(null);
useEffect(() => {
if (contacts && contacts) {
setProfile(contacts.find((c) => c.uid == uid));
} else {
setProfile(null);
}
}, [uid, contacts]);
if (!profile) return null;
console.log({ profile });
const { name, email, avatar } = profile;
return (
<StyledWrapper>
<Avatar className="avatar" url={avatar} name={name} />
<h2 className="name">{name}</h2>
<span className="email">{email}</span>
<ul className="icons">
<li className="icon chat">
<NavLink to={`/chat/dm/${uid}`}>
<BsChatText size={20} color="#616161" />
</NavLink>
</li>
<li className="icon add">
{/* <NavLink to={`/chat/dm/${uid}`}> */}
<RiUserAddLine size={20} color="#616161" />
{/* </NavLink> */}
</li>
<li className="icon share">
{/* <NavLink to={`/chat/dm/${uid}`}> */}
<IoShareOutline size={20} color="#616161" />
{/* </NavLink> */}
</li>
</ul>
<hr className="line" />
</StyledWrapper>
);
}
+6 -6
View File
@@ -10,20 +10,20 @@ import StyledWrapper from "./styled";
export default function ContactsPage() {
const { user_id } = useParams();
const contacts = useSelector((store) => store.contacts);
const contactIds = useSelector((store) => store.contacts.ids);
console.log({ contacts, user_id });
if (!contacts) return null;
console.log({ contactIds, user_id });
if (!contactIds) return null;
return (
<StyledWrapper>
<div className="left">
<Search />
<div className="list">
<nav className="nav">
{contacts.map(({ uid, status }) => {
{contactIds.map((uid) => {
return (
<NavLink key={uid} className="session" to={`/contacts/${uid}`}>
<Contact uid={uid} status={status} />
<Contact uid={uid} />
</NavLink>
);
})}
@@ -33,7 +33,7 @@ export default function ContactsPage() {
</div>
{user_id && (
<div className="right">
<Profile data={contacts.find((c) => c.uid == user_id)} />
<Profile uid={user_id} />
</div>
)}
</StyledWrapper>
+1 -1
View File
@@ -40,7 +40,7 @@ export default function Loading() {
useEffect(() => {
const inter = setTimeout(() => {
setReloadVisible(true);
}, 10000);
}, 15000);
return () => {
clearTimeout(inter);
+36 -42
View File
@@ -14,7 +14,7 @@ import ChannelSettingModal from "../../common/component/ChannelSetting";
import ChatIcon from "../../assets/icons/chat.svg";
import ContactIcon from "../../assets/icons/contact.svg";
import NotificationHub from "../../common/component/NotificationHub";
// import NotificationHub from "../../common/component/NotificationHub";
export default function HomePage() {
const dispatch = useDispatch();
@@ -29,51 +29,45 @@ export default function HomePage() {
const toggleExpand = () => {
dispatch(toggleMenuExpand());
};
console.log({ data, error, success });
if (loading) {
console.log("index loading", loading, ready);
if (loading || !ready) {
return <Loading />;
}
return (
<>
<NotificationHub />
{ready ? (
<StyledWrapper>
<div className={`col left ${menuExpand ? "expand" : ""}`}>
<ServerDropList
data={data?.server}
memberCount={data.contacts?.length}
expand={menuExpand}
/>
<nav className="nav">
<NavLink className="link" to={"/chat"}>
<img src={ChatIcon} alt="chat icon" />{" "}
{menuExpand && (
<span className="animate__animated animate__fadeIn">
Chat
</span>
)}
</NavLink>
<NavLink className="link" to={"/contacts"}>
<img src={ContactIcon} alt="contact icon" />{" "}
{menuExpand && (
<span className="animate__animated animate__fadeIn">
Contacts
</span>
)}
</NavLink>
</nav>
<div className="divider"></div>
<Tools expand={menuExpand} />
<Menu toggle={toggleExpand} expand={menuExpand} />
{/* <CurrentUser expand={menuExpand} /> */}
</div>
<div className="col right">
<Outlet />
</div>
</StyledWrapper>
) : (
<Loading />
)}
{/* <NotificationHub /> */}
<StyledWrapper>
<div className={`col left ${menuExpand ? "expand" : ""}`}>
<ServerDropList
data={data?.server}
memberCount={data.contacts?.length}
expand={menuExpand}
/>
<nav className="nav">
<NavLink className="link" to={"/chat"}>
<img src={ChatIcon} alt="chat icon" />{" "}
{menuExpand && (
<span className="animate__animated animate__fadeIn">Chat</span>
)}
</NavLink>
<NavLink className="link" to={"/contacts"}>
<img src={ContactIcon} alt="contact icon" />{" "}
{menuExpand && (
<span className="animate__animated animate__fadeIn">
Contacts
</span>
)}
</NavLink>
</nav>
<div className="divider"></div>
<Tools expand={menuExpand} />
<Menu toggle={toggleExpand} expand={menuExpand} />
{/* <CurrentUser expand={menuExpand} /> */}
</div>
<div className="col right">
<Outlet />
</div>
</StyledWrapper>
{setting && <SettingModal />}
{channelSetting && <ChannelSettingModal id={channelSetting} />}
</>
+25 -10
View File
@@ -3,8 +3,9 @@ import { useDispatch } from "react-redux";
import { useNavigate } from "react-router-dom";
import initCache, { useRehydrate } from "../../app/cache";
import { useLazyGetContactsQuery } from "../../app/services/contact";
import { clearAuthData, setUserData } from "../../app/slices/auth.data";
import { setContacts } from "../../app/slices/contacts";
import { useLazyInitStreamingQuery } from "../../app/services/streaming";
import { resetAuthData, setUid } from "../../app/slices/auth.data";
import { fullfillContacts } from "../../app/slices/contacts";
// import { useGetChannelsQuery } from "../../app/services/channel";
import { useLazyGetServerQuery } from "../../app/services/server";
@@ -14,7 +15,8 @@ import { KEY_UID } from "../../app/config";
// refetchOnMountOrArgChange: true,
// };
export default function usePreload() {
const { rehydrate, cacheFirst } = useRehydrate();
const { rehydrate, rehydrated } = useRehydrate();
const [initStreaming, { isLoading: streaming }] = useLazyInitStreamingQuery();
const [checked, setChecked] = useState(false);
const dispatch = useDispatch();
const navigate = useNavigate();
@@ -40,31 +42,44 @@ export default function usePreload() {
initCache();
rehydrate();
}, []);
useEffect(() => {
getContacts();
getServer();
}, []);
// rehydrate();
if (rehydrated) {
getContacts();
getServer();
}
}, [rehydrated]);
useEffect(() => {
if (checked && rehydrated) {
initStreaming({}, false);
}
}, [checked, rehydrated]);
useEffect(() => {
const local_uid = localStorage.getItem(KEY_UID);
if (contacts) {
const matchedUser = contacts.find((c) => c.uid == local_uid);
console.log("wtf", contacts, matchedUser);
if (!matchedUser) {
// 用户已注销或被禁用
console.log("no matched user, redirect to login");
dispatch(clearAuthData());
dispatch(resetAuthData());
navigate("/login");
} else {
const markedContacts = contacts.map((u) => {
return u.uid == matchedUser.uid ? { ...u, online: true } : u;
});
dispatch(setUserData(matchedUser));
dispatch(setContacts(markedContacts));
dispatch(setUid(matchedUser.uid));
dispatch(fullfillContacts(markedContacts));
setChecked(true);
}
}
}, [contacts]);
console.log("loading", contactsLoading, serverLoading, !checked, streaming);
return {
loading: contactsLoading || serverLoading || !checked || !cacheFirst,
loading:
contactsLoading || serverLoading || !checked || !rehydrated || streaming,
error: contactsError && serverError,
success: contactsSuccess && serverSuccess,
data: {
+1
View File
@@ -57,6 +57,7 @@ export default function LoginPage() {
useEffect(() => {
if (isSuccess && data) {
// 更新本地认证信息
console.log("login data", data);
toast.success("login success");
dispatch(setAuthData(data));
navigateTo("/");