feat: read index

This commit is contained in:
zerosoul
2022-03-20 17:41:09 +08:00
parent 8366be7182
commit b60160cd50
16 changed files with 179 additions and 138 deletions
+14 -8
View File
@@ -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}
+1 -6
View File
@@ -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",
});
})}
+27 -4
View File
@@ -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}
+5 -16
View File
@@ -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
View File
@@ -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>
);
};
+2
View File
@@ -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;
+4 -2
View File
@@ -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 {