feat: read index
This commit is contained in:
@@ -11,7 +11,7 @@ export default async function handler({ operation, data, payload }) {
|
||||
const chs = payload;
|
||||
await Promise.all(
|
||||
chs.map(({ gid, ...rest }) => {
|
||||
return table.setItem(gid, { gid, ...rest });
|
||||
return table.setItem(gid + "", { gid, ...rest });
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ export default async function handler({ operation, data, payload }) {
|
||||
const contacts = payload;
|
||||
await Promise.all(
|
||||
contacts.map(({ uid, ...rest }) => {
|
||||
return table.setItem(uid, { uid, ...rest });
|
||||
return table.setItem(uid + "", { uid, ...rest });
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -75,9 +75,10 @@ export const channelApi = createApi({
|
||||
},
|
||||
}),
|
||||
sendChannelMsg: builder.mutation({
|
||||
query: ({ id, content, type = "text" }) => ({
|
||||
query: ({ id, content, type = "text", properties = "" }) => ({
|
||||
headers: {
|
||||
"content-type": ContentTypes[type],
|
||||
"X-Properties": properties,
|
||||
},
|
||||
url: `group/${id}/send`,
|
||||
method: "POST",
|
||||
|
||||
@@ -73,9 +73,10 @@ export const contactApi = createApi({
|
||||
}),
|
||||
}),
|
||||
sendMsg: builder.mutation({
|
||||
query: ({ id, content, type = "text" }) => ({
|
||||
query: ({ id, content, type = "text", properties = "" }) => ({
|
||||
headers: {
|
||||
"content-type": ContentTypes[type],
|
||||
"X-Properties": properties,
|
||||
},
|
||||
url: `user/${id}/send`,
|
||||
method: "POST",
|
||||
|
||||
+21
-17
@@ -1,5 +1,5 @@
|
||||
import { createApi } from "@reduxjs/toolkit/query/react";
|
||||
import { batch } from "react-redux";
|
||||
// import { batch } from "react-redux";
|
||||
|
||||
import { ContentTypes } from "../config";
|
||||
import { updateReadChannels, updateReadUsers } from "../slices/footprint";
|
||||
@@ -57,27 +57,31 @@ export const messageApi = createApi({
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
async onQueryStarted(data, { dispatch, getState, queryFulfilled }) {
|
||||
const { users = [], groups = [] } = data;
|
||||
const { readUsers, readChannels } = getState().footprint.readUsers;
|
||||
const prevUsers = users.map(({ uid }) => {
|
||||
return { uid, mid: readUsers[uid] };
|
||||
});
|
||||
const prevChannels = users.map(({ gid }) => {
|
||||
return { gid, mid: readChannels[gid] };
|
||||
});
|
||||
batch(() => {
|
||||
dispatch(updateReadChannels(groups));
|
||||
async onQueryStarted(data, { dispatch, queryFulfilled }) {
|
||||
const { users = null, groups = null } = data;
|
||||
// const { readUsers, readChannels } = getState().footprint;
|
||||
// const prevUsers = users.map(({ uid }) => {
|
||||
// return { uid, mid: readUsers[uid] };
|
||||
// });
|
||||
// const prevChannels = users.map(({ gid }) => {
|
||||
// return { gid, mid: readChannels[gid] };
|
||||
// });
|
||||
// batch(() => {
|
||||
if (users) {
|
||||
dispatch(updateReadUsers(users));
|
||||
});
|
||||
}
|
||||
if (groups) {
|
||||
dispatch(updateReadChannels(groups));
|
||||
}
|
||||
// });
|
||||
try {
|
||||
await queryFulfilled;
|
||||
} catch {
|
||||
// todo
|
||||
batch(() => {
|
||||
dispatch(updateReadChannels(prevChannels));
|
||||
dispatch(updateReadUsers(prevUsers));
|
||||
});
|
||||
// batch(() => {
|
||||
// dispatch(updateReadChannels(prevChannels));
|
||||
// dispatch(updateReadUsers(prevUsers));
|
||||
// });
|
||||
}
|
||||
},
|
||||
}),
|
||||
|
||||
@@ -50,7 +50,10 @@ const contactsSlice = createSlice({
|
||||
case "create":
|
||||
{
|
||||
state.byId[uid] = { uid, ...rest };
|
||||
state.ids.push(uid);
|
||||
const idx = state.ids.findIndex((i) => i == uid);
|
||||
if (idx == -1) {
|
||||
state.ids.push(uid);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "delete":
|
||||
|
||||
@@ -83,10 +83,8 @@ export default function Contact({
|
||||
content={<Profile uid={uid} type="card" />}
|
||||
>
|
||||
<div className="avatar">
|
||||
<Avatar url={curr?.avatar} name={curr?.name} alt="avatar" />
|
||||
<div
|
||||
className={`status ${curr?.online ? "online" : "offline"}`}
|
||||
></div>
|
||||
<Avatar url={curr.avatar} name={curr.name} alt="avatar" />
|
||||
<div className={`status ${curr.online ? "online" : "offline"}`}></div>
|
||||
</div>
|
||||
</Tippy>
|
||||
{!compact && <span className="name">{curr?.name}</span>}
|
||||
|
||||
@@ -1,36 +1,41 @@
|
||||
import React, { useRef, useState, useEffect } from "react";
|
||||
import dayjs from "dayjs";
|
||||
import { useSelector, useDispatch } from "react-redux";
|
||||
import { useInViewRef } from "rooks";
|
||||
import { useSelector } from "react-redux";
|
||||
import { useInViewRef, useDebounce } from "rooks";
|
||||
import Tippy from "@tippyjs/react";
|
||||
import Reaction from "./Reaction";
|
||||
import Reply from "./Reply";
|
||||
import Profile from "../Profile";
|
||||
import Avatar from "../Avatar";
|
||||
import { readMessage } from "../../../app/slices/message";
|
||||
import { useReadMessageMutation } from "../../../app/services/message";
|
||||
import StyledWrapper from "./styled";
|
||||
import Commands from "./Commands";
|
||||
|
||||
import EditMessage from "./EditMessage";
|
||||
import renderContent from "./renderContent";
|
||||
function Message({ contextId = 0, mid = "", read = true, context = "user" }) {
|
||||
function Message({ contextId = 0, mid = "", context = "user" }) {
|
||||
const [updateReadIndex] = useReadMessageMutation();
|
||||
const updateReadDebounced = useDebounce(updateReadIndex, 300);
|
||||
const [myRef, inView] = useInViewRef();
|
||||
const [edit, setEdit] = useState(false);
|
||||
const [emojiPopVisible, setEmojiPopVisible] = useState(false);
|
||||
const [menuVisible, setMenuVisible] = useState(false);
|
||||
const disptach = useDispatch();
|
||||
const avatarRef = useRef(null);
|
||||
const { message = {}, reactionMessageData, contactsData } = useSelector(
|
||||
(store) => {
|
||||
return {
|
||||
reactionMessageData: store.reactionMessage,
|
||||
message: store.message[mid],
|
||||
contactsData: store.contacts.byId,
|
||||
};
|
||||
}
|
||||
);
|
||||
const {
|
||||
footprint,
|
||||
message = {},
|
||||
reactionMessageData,
|
||||
contactsData,
|
||||
loginUid,
|
||||
} = useSelector((store) => {
|
||||
return {
|
||||
footprint: store.footprint,
|
||||
loginUid: store.authData.uid,
|
||||
reactionMessageData: store.reactionMessage,
|
||||
message: store.message[mid] || {},
|
||||
contactsData: store.contacts.byId,
|
||||
};
|
||||
});
|
||||
const toggleMenu = () => {
|
||||
setMenuVisible((prev) => !prev);
|
||||
};
|
||||
@@ -40,38 +45,35 @@ function Message({ contextId = 0, mid = "", read = true, context = "user" }) {
|
||||
const toggleEmojiPopover = () => {
|
||||
setEmojiPopVisible((prev) => !prev);
|
||||
};
|
||||
// useEffect(() => {
|
||||
// if (!read) {
|
||||
// avatarRef.current?.scrollIntoView();
|
||||
// }
|
||||
// }, [read]);
|
||||
|
||||
// console.log("message", mid, messageData[mid]);
|
||||
|
||||
useEffect(() => {
|
||||
if (inView && !read) {
|
||||
disptach(readMessage(mid));
|
||||
const data =
|
||||
context == "user"
|
||||
? { users: [{ uid: +contextId, mid }] }
|
||||
: { groups: [{ gid: +contextId, mid }] };
|
||||
updateReadIndex(data);
|
||||
}
|
||||
}, [mid, read, inView]);
|
||||
if (!message) return null;
|
||||
const {
|
||||
reply_mid,
|
||||
from_uid: fromUid,
|
||||
created_at: time,
|
||||
sending,
|
||||
sending = false,
|
||||
content,
|
||||
thumbnail,
|
||||
content_type = "text/plain",
|
||||
edited,
|
||||
properties,
|
||||
} = message;
|
||||
const readIndex =
|
||||
context == "user"
|
||||
? footprint.readUsers[contextId]
|
||||
: footprint.readChannels[contextId];
|
||||
useEffect(() => {
|
||||
const read = fromUid == loginUid || mid <= readIndex;
|
||||
if (inView && !read) {
|
||||
const data =
|
||||
context == "user"
|
||||
? { users: [{ uid: +contextId, mid }] }
|
||||
: { groups: [{ gid: +contextId, mid }] };
|
||||
updateReadDebounced(data);
|
||||
}
|
||||
}, [mid, readIndex, inView, fromUid, loginUid]);
|
||||
const reactions = reactionMessageData[mid];
|
||||
const currUser = contactsData[fromUid] || {};
|
||||
// if (!message) return null;
|
||||
return (
|
||||
<StyledWrapper
|
||||
data-mid={mid}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// import { useState, useEffect } from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { useSelector } from "react-redux";
|
||||
// import toast from "react-hot-toast";
|
||||
// import { useNavigate } from "react-router-dom";
|
||||
@@ -23,37 +23,37 @@ export default function UploadModal({
|
||||
{ isLoading: channelSending },
|
||||
] = useSendChannelMsgMutation();
|
||||
const [sendUserMsg, { isLoading: userSending }] = useSendMsgMutation();
|
||||
// const [properties, setProperties] = useState([]);
|
||||
// useEffect(() => {
|
||||
// files.forEach((file, idx) => {
|
||||
// const { name, size, type } = file;
|
||||
// setProperties((prevs) => {
|
||||
// prevs[idx] = { name, size, type };
|
||||
// return prevs;
|
||||
// });
|
||||
// var fileReader = new FileReader();
|
||||
// fileReader.onloadend = (e) => {
|
||||
// let dataUrl = e.target.result;
|
||||
// let tmp = new Image();
|
||||
// tmp.src = dataUrl;
|
||||
// tmp.onload = function () {
|
||||
// console.log("image load", this.width, this.height);
|
||||
// setProperties((prevs) => {
|
||||
// prevs[idx].width = this.width;
|
||||
// prevs[idx].height = this.height;
|
||||
// return prevs;
|
||||
// });
|
||||
// };
|
||||
// };
|
||||
// fileReader.readAsDataURL(file);
|
||||
// });
|
||||
// }, [files]);
|
||||
const [properties, setProperties] = useState([]);
|
||||
useEffect(() => {
|
||||
files.forEach((file, idx) => {
|
||||
const { name, size, type } = file;
|
||||
setProperties((prevs) => {
|
||||
prevs[idx] = { name, size, type };
|
||||
return prevs;
|
||||
});
|
||||
// var fileReader = new FileReader();
|
||||
// fileReader.onloadend = (e) => {
|
||||
// let dataUrl = e.target.result;
|
||||
// let tmp = new Image();
|
||||
// tmp.src = dataUrl;
|
||||
// tmp.onload = function () {
|
||||
// console.log("image load", this.width, this.height);
|
||||
// setProperties((prevs) => {
|
||||
// prevs[idx].width = this.width;
|
||||
// prevs[idx].height = this.height;
|
||||
// return prevs;
|
||||
// });
|
||||
// };
|
||||
// };
|
||||
// fileReader.readAsDataURL(file);
|
||||
});
|
||||
}, [files]);
|
||||
const handleUpload = () => {
|
||||
const uploadFn = type == "user" ? sendUserMsg : sendChannelMsg;
|
||||
uploadFn({
|
||||
id: sendTo,
|
||||
content: files[0],
|
||||
// properties: properties[0],
|
||||
properties: btoa(JSON.stringify(properties[0])),
|
||||
type: "image",
|
||||
from_uid,
|
||||
});
|
||||
|
||||
@@ -2,6 +2,7 @@ import { NavLink, useNavigate } from "react-router-dom";
|
||||
import { useDrop } from "react-dnd";
|
||||
import { NativeTypes } from "react-dnd-html5-backend";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
// import { useDebounce} from "rooks";
|
||||
import { toggleChannelSetting } from "../../../app/slices/ui";
|
||||
import ChannelIcon from "../../../common/component/ChannelIcon";
|
||||
import { getUnreadCount } from "../utils";
|
||||
@@ -9,13 +10,18 @@ import { getUnreadCount } from "../utils";
|
||||
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 getUnreadCountDebounced=useDebounce(getUnreadCount,300)
|
||||
const { channel, mids, messageData, readIndex, loginUid } = useSelector(
|
||||
(store) => {
|
||||
return {
|
||||
channel: store.channels.byId[id],
|
||||
mids: store.channelMessage[id],
|
||||
messageData: store.message,
|
||||
loginUid: store.authData.uid,
|
||||
readIndex: store.footprint.readChannels[id],
|
||||
};
|
||||
}
|
||||
);
|
||||
const handleChannelSetting = (evt) => {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
@@ -39,7 +45,7 @@ const NavItem = ({ id, setFiles, contextMenuEventHandler }) => {
|
||||
}),
|
||||
}));
|
||||
const { is_public, name } = channel;
|
||||
const unreads = getUnreadCount(mids, messageData);
|
||||
const unreads = getUnreadCount({ mids, messageData, readIndex, loginUid });
|
||||
return (
|
||||
<NavLink
|
||||
data-cid={id}
|
||||
|
||||
@@ -13,12 +13,11 @@ export default function DMChat({ uid = "", dropFiles = [] }) {
|
||||
console.log("dm files", dropFiles);
|
||||
const [dragFiles, setDragFiles] = useState([]);
|
||||
// const [mids, setMids] = useState([]);
|
||||
const { msgIds, currUser, messageData, readUsers } = useSelector((store) => {
|
||||
const { msgIds, currUser, messageData } = useSelector((store) => {
|
||||
return {
|
||||
currUser: store.contacts.byId[uid],
|
||||
msgIds: store.userMessage.byId[uid] || [],
|
||||
messageData: store.message,
|
||||
readUsers: store.footprint.readUser || {},
|
||||
};
|
||||
});
|
||||
const ref = useChatScroll(msgIds);
|
||||
@@ -33,7 +32,6 @@ export default function DMChat({ uid = "", dropFiles = [] }) {
|
||||
|
||||
if (!currUser) return null;
|
||||
// console.log("user msgs", msgs);
|
||||
const readIndex = readUsers[uid] || 0;
|
||||
return (
|
||||
<Layout
|
||||
setDragFiles={setDragFiles}
|
||||
@@ -62,14 +60,11 @@ export default function DMChat({ uid = "", dropFiles = [] }) {
|
||||
})
|
||||
.map((mid, idx) => {
|
||||
const curr = messageData[mid];
|
||||
const self = curr.from_uid == currUser.uid;
|
||||
const read = self ? true : mid <= readIndex ? true : false;
|
||||
const prev = idx == 0 ? null : messageData[msgIds[idx - 1]];
|
||||
return renderMessageFragment({
|
||||
prev,
|
||||
curr,
|
||||
contextId: uid,
|
||||
read,
|
||||
context: "user",
|
||||
});
|
||||
})}
|
||||
|
||||
@@ -5,7 +5,7 @@ import relativeTime from "dayjs/plugin/relativeTime";
|
||||
import { useDrop } from "react-dnd";
|
||||
import { NativeTypes } from "react-dnd-html5-backend";
|
||||
import { useSelector } from "react-redux";
|
||||
import { renderPreviewMessage } from "./utils";
|
||||
import { renderPreviewMessage, getUnreadCount } from "./utils";
|
||||
import Contact from "../../common/component/Contact";
|
||||
dayjs.extend(relativeTime);
|
||||
const NavItem = ({ uid, mid, unreads, setFiles }) => {
|
||||
@@ -60,9 +60,32 @@ const NavItem = ({ uid, mid, unreads, setFiles }) => {
|
||||
</NavLink>
|
||||
);
|
||||
};
|
||||
export default function DMList({ sessions, setDropFiles }) {
|
||||
return sessions.map(({ uid, lastMid, unreads } = {}) => {
|
||||
if (!uid) return null;
|
||||
// mids: ChannelMsgData[channel_id],
|
||||
// messageData,
|
||||
// readIndex: readChannels[channel_id],
|
||||
// loginUid,
|
||||
export default function DMList({ uids, setDropFiles }) {
|
||||
const { userMessage, messageData, readUsers, loginUid } = useSelector(
|
||||
(store) => {
|
||||
return {
|
||||
loginUid: store.authData.uid,
|
||||
readUsers: store.footprint.readUsers,
|
||||
contactData: store.contacts.byId,
|
||||
userMessage: store.userMessage.byId,
|
||||
messageData: store.message,
|
||||
};
|
||||
}
|
||||
);
|
||||
const sessions = uids.map((uid) => {
|
||||
const mids = userMessage[uid];
|
||||
const lastMid = [...mids].pop();
|
||||
const readIndex = readUsers[uid];
|
||||
const unreads = getUnreadCount({ mids, readIndex, messageData, loginUid });
|
||||
|
||||
return { lastMid, unreads, uid };
|
||||
});
|
||||
|
||||
return sessions.map(({ lastMid, uid, unreads }) => {
|
||||
return (
|
||||
<NavItem
|
||||
key={uid}
|
||||
|
||||
@@ -16,16 +16,14 @@ import ChannelList from "./ChannelList";
|
||||
import ContactsModal from "../../common/component/ContactsModal";
|
||||
import ChannelModal from "../../common/component/ChannelModal";
|
||||
import DMList from "./DMList";
|
||||
import { getUnreadCount } from "./utils";
|
||||
|
||||
export default function ChatPage() {
|
||||
const [channelDropFiles, setChannelDropFiles] = useState([]);
|
||||
const [userDropFiles, setUserDropFiles] = useState([]);
|
||||
const { contactsData, UserMsgData, messageData } = useSelector((store) => {
|
||||
const { contactsData, sessionUids } = useSelector((store) => {
|
||||
return {
|
||||
contactsData: store.contacts.byId,
|
||||
UserMsgData: store.userMessage,
|
||||
messageData: store.message,
|
||||
sessionUids: store.userMessage.ids,
|
||||
};
|
||||
});
|
||||
const [channelModalVisible, setChannelModalVisible] = useState(false);
|
||||
@@ -43,10 +41,6 @@ export default function ChatPage() {
|
||||
listEle.classList.toggle("collapse");
|
||||
};
|
||||
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 (
|
||||
<>
|
||||
{channelModalVisible && (
|
||||
@@ -95,8 +89,8 @@ export default function ChatPage() {
|
||||
/>
|
||||
</h3>
|
||||
<nav className="nav">
|
||||
<DMList sessions={sessions} setDropFiles={setUserDropFiles} />
|
||||
{user_id && UserMsgData.ids.findIndex((i) => i == user_id) == -1 && (
|
||||
<DMList uids={sessionUids} setDropFiles={setUserDropFiles} />
|
||||
{user_id && sessionUids.findIndex((i) => i == user_id) == -1 && (
|
||||
<NavLink className="session" to={`/chat/dm/${user_id}`}>
|
||||
<Contact
|
||||
compact
|
||||
@@ -112,7 +106,6 @@ export default function ChatPage() {
|
||||
|
||||
<div className="down">
|
||||
<div className="msg"></div>
|
||||
{/* <i className="badge">3</i> */}
|
||||
</div>
|
||||
</div>
|
||||
</NavLink>
|
||||
@@ -123,11 +116,7 @@ export default function ChatPage() {
|
||||
</div>
|
||||
<div className="right">
|
||||
{channel_id && (
|
||||
<ChannelChat
|
||||
unreads={getUnreadCount(channel_id)}
|
||||
cid={channel_id}
|
||||
dropFiles={channelDropFiles}
|
||||
/>
|
||||
<ChannelChat cid={channel_id} dropFiles={channelDropFiles} />
|
||||
)}
|
||||
{user_id && <DMChat uid={user_id} dropFiles={userDropFiles} />}
|
||||
</div>
|
||||
|
||||
+31
-16
@@ -3,16 +3,38 @@ import dayjs from "dayjs";
|
||||
import { ContentTypes } from "../../app/config";
|
||||
import Divider from "../../common/component/Divider";
|
||||
import Message from "../../common/component/Message";
|
||||
export const getUnreadCount = (mids, messageData) => {
|
||||
if (!mids || !messageData) return 0;
|
||||
let unreads = 0;
|
||||
mids.forEach((id) => {
|
||||
if (messageData[id] && !messageData[id].read) {
|
||||
unreads++;
|
||||
function debounce(callback, wait = 2000, immediate = false) {
|
||||
let timeout = null;
|
||||
return function () {
|
||||
const callNow = immediate && !timeout;
|
||||
const next = () => callback.apply(this, arguments);
|
||||
clearTimeout(timeout);
|
||||
timeout = setTimeout(next, wait);
|
||||
if (callNow) {
|
||||
next();
|
||||
}
|
||||
};
|
||||
}
|
||||
export function getUnreadCount({
|
||||
mids = [],
|
||||
messageData = {},
|
||||
loginUid = 0,
|
||||
readIndex = 0,
|
||||
}) {
|
||||
console.log({ mids, loginUid, readIndex });
|
||||
// 先过滤掉from自己的
|
||||
const others = mids.filter((mid) => {
|
||||
const { from_uid } = messageData[mid];
|
||||
return from_uid != loginUid;
|
||||
});
|
||||
return unreads;
|
||||
};
|
||||
if (others.length == 0) return 0;
|
||||
if (readIndex == 0) return others.length;
|
||||
// 再过滤掉大于read-index,
|
||||
const final = others.filter((mid) => {
|
||||
return mid > readIndex;
|
||||
});
|
||||
return final.length;
|
||||
}
|
||||
export const renderPreviewMessage = (message = null) => {
|
||||
if (!message) return null;
|
||||
const { content_type, content } = message;
|
||||
@@ -52,7 +74,6 @@ export const renderMessageFragment = ({
|
||||
prev = null,
|
||||
curr = null,
|
||||
contextId = 0,
|
||||
read = true,
|
||||
context = "user",
|
||||
}) => {
|
||||
if (!curr) return null;
|
||||
@@ -71,13 +92,7 @@ export const renderMessageFragment = ({
|
||||
return (
|
||||
<React.Fragment key={mid}>
|
||||
{divider && <Divider content={divider}></Divider>}
|
||||
<Message
|
||||
read={read}
|
||||
context={context}
|
||||
mid={mid}
|
||||
key={mid}
|
||||
contextId={contextId}
|
||||
/>
|
||||
<Message context={context} mid={mid} key={mid} contextId={contextId} />
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -10,6 +10,8 @@ const StyledWrapper = styled.div`
|
||||
box-shadow: inset -1px 0px 0px rgba(0, 0, 0, 0.1);
|
||||
.list {
|
||||
margin: 12px 8px;
|
||||
overflow: scroll;
|
||||
padding-bottom: 50px;
|
||||
> .nav {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@@ -54,11 +54,13 @@ export default function usePreload() {
|
||||
getServer();
|
||||
}
|
||||
}, [rehydrated]);
|
||||
const canStreaming =
|
||||
contactsSuccess && rehydrated && !initializing && !streaming;
|
||||
useEffect(() => {
|
||||
if (rehydrated && !initializing && !streaming) {
|
||||
if (canStreaming) {
|
||||
request = startStreaming(store);
|
||||
}
|
||||
}, [rehydrated, store, streaming, initializing]);
|
||||
}, [canStreaming]);
|
||||
|
||||
// console.log("loading", contactsLoading, serverLoading, !checked);
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user