refactor: update read index with debounce

This commit is contained in:
zerosoul
2022-04-06 16:29:03 +08:00
parent a590839aff
commit 8ea1219fe0
4 changed files with 86 additions and 53 deletions
+22 -28
View File
@@ -1,40 +1,38 @@
import React, { useRef, useState, useEffect } from "react";
import dayjs from "dayjs";
import { useSelector } from "react-redux";
import { useInViewRef, useDebounce } from "rooks";
import { useInViewRef } from "rooks";
import Tippy from "@tippyjs/react";
import Reaction from "./Reaction";
import Reply from "./Reply";
import Profile from "../Profile";
import Avatar from "../Avatar";
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 = "", context = "user" }) {
const [updateReadIndex] = useReadMessageMutation();
const updateReadDebounced = useDebounce(updateReadIndex, 300);
function Message({
contextId = 0,
mid = "",
context = "user",
updateReadIndex,
read = true,
}) {
const [myRef, inView] = useInViewRef();
const [edit, setEdit] = useState(false);
const avatarRef = useRef(null);
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 { message = {}, reactionMessageData, contactsData } = useSelector(
(store) => {
return {
reactionMessageData: store.reactionMessage,
message: store.message[mid] || {},
contactsData: store.contacts.byId,
};
}
);
const toggleEditMessage = () => {
setEdit((prev) => !prev);
@@ -51,20 +49,16 @@ function Message({ contextId = 0, mid = "", context = "user" }) {
edited,
properties,
} = message;
const readIndex =
context == "user"
? footprint.readUsers[contextId]
: footprint.readChannels[contextId];
useEffect(() => {
const read = fromUid == loginUid || mid <= readIndex;
if (inView && !read) {
if (!read) {
const data =
context == "user"
? { users: [{ uid: +contextId, mid }] }
: { groups: [{ gid: +contextId, mid }] };
updateReadDebounced(data);
updateReadIndex(data);
}
}, [mid, readIndex, inView, fromUid, loginUid]);
}, [mid, read]);
const reactions = reactionMessageData[mid];
const currUser = contactsData[fromUid] || {};
// if (!message) return null;
+20 -3
View File
@@ -1,6 +1,7 @@
import { useState } from "react";
import { useDebounce } from "rooks";
import { useSelector } from "react-redux";
import { useReadMessageMutation } from "../../../app/services/message";
import useChatScroll from "../../../common/hook/useChatScroll";
import ChannelIcon from "../../../common/component/ChannelIcon";
import Send from "../../../common/component/Send";
@@ -21,11 +22,22 @@ import AddMemberModal from "./AddMemberModal";
export default function ChannelChat({ cid = "", dropFiles = [] }) {
// const containerRef = useRef(null);
const [updateReadIndex] = useReadMessageMutation();
const updateReadDebounced = useDebounce(updateReadIndex, 300);
const [membersVisible, setMembersVisible] = useState(true);
const [addMemberModalVisible, setAddMemberModalVisible] = useState(false);
// const dispatch = useDispatch();
const { msgIds, userIds, data, messageData } = useSelector((store) => {
const {
msgIds,
userIds,
data,
messageData,
loginUid,
footprint,
} = useSelector((store) => {
return {
footprint: store.footprint,
loginUid: store.authData.uid,
msgIds: store.channelMessage[cid] || [],
userIds: store.contacts.ids,
data: store.channels.byId[cid] || {},
@@ -45,6 +57,7 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
const { name, description, is_public, members = [] } = data;
const memberIds = members.length == 0 ? userIds : members;
console.log("channel message list", msgIds);
const readIndex = footprint.readChannels[cid];
return (
<>
{addMemberModalVisible && (
@@ -113,9 +126,13 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
return Number(a) - Number(b);
})
.map((mid, idx) => {
const prev = idx == 0 ? null : messageData[msgIds[idx - 1]];
const curr = messageData[mid];
if (!curr) return null;
const prev = idx == 0 ? null : messageData[msgIds[idx - 1]];
const read = curr?.from_uid == loginUid || mid <= readIndex;
return renderMessageFragment({
updateReadIndex: updateReadDebounced,
read,
prev,
curr,
contextId: cid,
+20 -7
View File
@@ -1,28 +1,38 @@
// import { useState, useEffect } from "react";
import { useSelector } from "react-redux";
import { useDebounce } from "rooks";
import addIcon from "../../../assets/icons/add.person.svg?url";
import callIcon from "../../../assets/icons/call.svg?url";
import videoIcon from "../../../assets/icons/video.svg?url";
import useChatScroll from "../../../common/hook/useChatScroll";
import Send from "../../../common/component/Send";
import { useReadMessageMutation } from "../../../app/services/message";
import Contact from "../../../common/component/Contact";
import Layout from "../Layout";
import { StyledHeader, StyledDMChat } from "./styled";
import { renderMessageFragment } from "../utils";
export default function DMChat({ uid = "", dropFiles = [] }) {
const [updateReadIndex] = useReadMessageMutation();
const updateReadDebounced = useDebounce(updateReadIndex, 300);
console.log("dm files", dropFiles);
// const [mids, setMids] = useState([]);
const { msgIds, currUser, messageData } = useSelector((store) => {
return {
currUser: store.contacts.byId[uid],
msgIds: store.userMessage.byId[uid] || [],
messageData: store.message,
};
});
const { msgIds, currUser, messageData, footprint, loginUid } = useSelector(
(store) => {
return {
loginUid: store.authData.uid,
footprint: store.footprint,
currUser: store.contacts.byId[uid],
msgIds: store.userMessage.byId[uid] || [],
messageData: store.message,
};
}
);
const ref = useChatScroll(msgIds);
if (!currUser) return null;
// console.log("user msgs", msgs);
const readIndex = footprint.readUsers[uid];
return (
<Layout
to={uid}
@@ -54,7 +64,10 @@ export default function DMChat({ uid = "", dropFiles = [] }) {
.map((mid, idx) => {
const curr = messageData[mid];
const prev = idx == 0 ? null : messageData[msgIds[idx - 1]];
const read = curr?.from_uid == loginUid || mid <= readIndex;
return renderMessageFragment({
updateReadIndex: updateReadDebounced,
read,
prev,
curr,
contextId: uid,
+24 -15
View File
@@ -3,18 +3,18 @@ import dayjs from "dayjs";
import { ContentTypes } from "../../app/config";
import Divider from "../../common/component/Divider";
import Message from "../../common/component/Message";
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();
}
};
}
// 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 = {},
@@ -22,10 +22,10 @@ export function getUnreadCount({
readIndex = 0,
}) {
console.log({ mids, loginUid, readIndex });
// 先过滤掉from自己的
// 先过滤掉空信息和from自己的
const others = mids.filter((mid) => {
const { from_uid = 0 } = messageData[mid] || {};
return from_uid != loginUid;
return messageData[mid] && from_uid != loginUid;
});
if (others.length == 0) return 0;
if (readIndex == 0) return others.length;
@@ -71,6 +71,8 @@ export const renderPreviewMessage = (message = null) => {
return res;
};
export const renderMessageFragment = ({
read = true,
updateReadIndex,
prev = null,
curr = null,
contextId = 0,
@@ -92,7 +94,14 @@ export const renderMessageFragment = ({
return (
<React.Fragment key={mid}>
{divider && <Divider content={divider}></Divider>}
<Message context={context} mid={mid} key={mid} contextId={contextId} />
<Message
updateReadIndex={updateReadIndex}
read={read}
context={context}
mid={mid}
key={mid}
contextId={contextId}
/>
</React.Fragment>
);
};