feat: add pagination to DM session

This commit is contained in:
zerosoul
2022-06-09 22:07:01 +08:00
parent 1506b27e99
commit 7571cc60ec
6 changed files with 67 additions and 47 deletions
+4 -4
View File
@@ -59,12 +59,12 @@ export const channelApi = createApi({
}, },
}), }),
getHistoryMessages: builder.query({ getHistoryMessages: builder.query({
query: ({ gid, mid = null, limit = 100 }) => ({ query: ({ id, mid = null, limit = 100 }) => ({
url: mid url: mid
? `/group/${gid}/history?before=${mid}&limit=${limit}` ? `/group/${id}/history?before=${mid}&limit=${limit}`
: `/group/${gid}/history?limit=${limit}`, : `/group/${id}/history?limit=${limit}`,
}), }),
async onQueryStarted(id, { dispatch, getState, queryFulfilled }) { async onQueryStarted(params, { dispatch, getState, queryFulfilled }) {
const { data: messages } = await queryFulfilled; const { data: messages } = await queryFulfilled;
if (messages?.length) { if (messages?.length) {
messages.forEach((msg) => { messages.forEach((msg) => {
+18
View File
@@ -7,6 +7,8 @@ import { updateMute } from "../slices/footprint";
import { fullfillContacts } from "../slices/contacts"; import { fullfillContacts } from "../slices/contacts";
import BASE_URL, { ContentTypes } from "../config"; import BASE_URL, { ContentTypes } from "../config";
import { onMessageSendStarted } from "./handlers"; import { onMessageSendStarted } from "./handlers";
import handleChatMessage from "../../common/hook/useStreaming/chat.handler";
export const contactApi = createApi({ export const contactApi = createApi({
reducerPath: "contactApi", reducerPath: "contactApi",
baseQuery, baseQuery,
@@ -110,10 +112,26 @@ export const contactApi = createApi({
await onMessageSendStarted.call(this, param1, param2, "user"); await onMessageSendStarted.call(this, param1, param2, "user");
}, },
}), }),
getHistoryMessages: builder.query({
query: ({ id, mid = null, limit = 100 }) => ({
url: mid
? `/user/${id}/history?before=${mid}&limit=${limit}`
: `/user/${id}/history?limit=${limit}`,
}),
async onQueryStarted(params, { dispatch, getState, queryFulfilled }) {
const { data: messages } = await queryFulfilled;
if (messages?.length) {
messages.forEach((msg) => {
handleChatMessage(msg, dispatch, getState());
});
}
},
}),
}), }),
}); });
export const { export const {
useLazyGetHistoryMessagesQuery,
useUpdateContactMutation, useUpdateContactMutation,
useUpdateMuteSettingMutation, useUpdateMuteSettingMutation,
useLazyDeleteContactQuery, useLazyDeleteContactQuery,
+7 -3
View File
@@ -1,6 +1,7 @@
import { useEffect, useState, useRef } from "react"; import { useEffect, useState, useRef } from "react";
import { useSelector } from "react-redux"; import { useSelector } from "react-redux";
import { useLazyGetHistoryMessagesQuery } from "../../app/services/channel"; import { useLazyGetHistoryMessagesQuery } from "../../app/services/channel";
import { useLazyGetHistoryMessagesQuery as useLazyGetDMHistoryMsg } from "../../app/services/contact";
const getFeedWithPagination = (config) => { const getFeedWithPagination = (config) => {
const { pageNumber = 1, pageSize = 40, mids = [], isLast = false } = const { pageNumber = 1, pageSize = 40, mids = [], isLast = false } =
@@ -39,13 +40,16 @@ const getFeedWithPagination = (config) => {
let curScrollPos = 0; let curScrollPos = 0;
let oldScroll = 0; let oldScroll = 0;
export default function useMessageFeed({ context = "channel", id = null }) { export default function useMessageFeed({ context = "channel", id = null }) {
const [loadMoreFromServer] = useLazyGetHistoryMessagesQuery(); const [loadMoreChannelMsgs] = useLazyGetHistoryMessagesQuery();
const [loadMoreDmMsgs] = useLazyGetDMHistoryMsg();
const listRef = useRef([]); const listRef = useRef([]);
const pageRef = useRef(null); const pageRef = useRef(null);
const containerRef = useRef(null); const containerRef = useRef(null);
const [hasMore, setHasMore] = useState(true); const [hasMore, setHasMore] = useState(true);
const [appends, setAppends] = useState([]); const [appends, setAppends] = useState([]);
const [items, setItems] = useState([]); const [items, setItems] = useState([]);
const loadMoreMsgsFromServer =
context == "channel" ? loadMoreChannelMsgs : loadMoreDmMsgs;
const { mids, messageData, loginUid } = useSelector((store) => { const { mids, messageData, loginUid } = useSelector((store) => {
return { return {
loginUid: store.authData.uid, loginUid: store.authData.uid,
@@ -127,9 +131,9 @@ export default function useMessageFeed({ context = "channel", id = null }) {
// 第一页 // 第一页
if (currPageInfo && currPageInfo.isFirst) { if (currPageInfo && currPageInfo.isFirst) {
const [firstMid] = currPageInfo.ids; const [firstMid] = currPageInfo.ids;
const { data: newList } = await loadMoreFromServer({ const { data: newList } = await loadMoreMsgsFromServer({
mid: firstMid, mid: firstMid,
gid: id, id,
}); });
if (newList.length == 0) { if (newList.length == 0) {
setHasMore(false); setHasMore(false);
+1 -1
View File
@@ -30,7 +30,7 @@ import {
StyledHeader, StyledHeader,
} from "./styled"; } from "./styled";
import InviteModal from "../../../common/component/InviteModal"; import InviteModal from "../../../common/component/InviteModal";
import LoadMore from "./LoadMore"; import LoadMore from "../LoadMore";
// import useChatScroll from "../../../common/hook/useChatScroll"; // import useChatScroll from "../../../common/hook/useChatScroll";
export default function ChannelChat({ cid = "", dropFiles = [] }) { export default function ChannelChat({ cid = "", dropFiles = [] }) {
+18 -20
View File
@@ -11,39 +11,40 @@ import IconHeadphone from "../../../assets/icons/headphone.svg";
import boardosIcon from "../../../assets/icons/app.boardos.svg?url"; import boardosIcon from "../../../assets/icons/app.boardos.svg?url";
import webrowseIcon from "../../../assets/icons/app.webrowse.svg?url"; import webrowseIcon from "../../../assets/icons/app.webrowse.svg?url";
import useChatScroll from "../../../common/hook/useChatScroll"; // import useChatScroll from "../../../common/hook/useChatScroll";
import { useReadMessageMutation } from "../../../app/services/message"; import { useReadMessageMutation } from "../../../app/services/message";
import Contact from "../../../common/component/Contact"; import Contact from "../../../common/component/Contact";
import Layout from "../Layout"; import Layout from "../Layout";
import { StyledHeader, StyledDMChat } from "./styled"; import { StyledHeader, StyledDMChat } from "./styled";
import LoadMore from "../LoadMore";
import { renderMessageFragment } from "../utils"; import { renderMessageFragment } from "../utils";
import useMessageFeed from "../../../common/hook/useMessageFeed";
export default function DMChat({ uid = "", dropFiles = [] }) { export default function DMChat({ uid = "", dropFiles = [] }) {
const { list: msgIds, appends, hasMore, pullUp } = useMessageFeed({
context: "user",
id: uid,
});
const [updateReadIndex] = useReadMessageMutation(); const [updateReadIndex] = useReadMessageMutation();
const updateReadDebounced = useDebounce(updateReadIndex, 300); const updateReadDebounced = useDebounce(updateReadIndex, 300);
console.log("dm files", dropFiles); console.log("dm files", dropFiles);
// const [mids, setMids] = useState([]); // const [mids, setMids] = useState([]);
const { const { currUser, messageData, footprint, loginUid, selects } = useSelector(
msgIds, (store) => {
currUser,
messageData,
footprint,
loginUid,
selects,
} = useSelector((store) => {
return { return {
selects: store.ui.selectMessages[`user_${uid}`], selects: store.ui.selectMessages[`user_${uid}`],
loginUid: store.authData.uid, loginUid: store.authData.uid,
footprint: store.footprint, footprint: store.footprint,
currUser: store.contacts.byId[uid], currUser: store.contacts.byId[uid],
msgIds: store.userMessage.byId[uid] || [],
messageData: store.message, messageData: store.message,
}; };
}); }
const ref = useChatScroll(msgIds); );
// const ref = useChatScroll(msgIds);
if (!currUser) return null; if (!currUser) return null;
// console.log("user msgs", msgs); // console.log("user msgs", msgs);
const readIndex = footprint.readUsers[uid]; const readIndex = footprint.readUsers[uid];
const feeds = [...msgIds, ...appends];
return ( return (
<Layout <Layout
to={uid} to={uid}
@@ -58,7 +59,7 @@ export default function DMChat({ uid = "", dropFiles = [] }) {
{/* <li className="tool"> {/* <li className="tool">
<img src={alertIcon} alt="opt icon" /> <img src={alertIcon} alt="opt icon" />
</li> */} </li> */}
<Tooltip tip="Favorite" placement="left"> <Tooltip tip="Saved Items" placement="left">
<Tippy <Tippy
placement="left-start" placement="left-start"
popperOptions={{ strategy: "fixed" }} popperOptions={{ strategy: "fixed" }}
@@ -97,14 +98,11 @@ export default function DMChat({ uid = "", dropFiles = [] }) {
</StyledHeader> </StyledHeader>
} }
> >
<StyledDMChat ref={ref}> <StyledDMChat id={`RUSTCHAT_FEED_user_${uid}`}>
{[...msgIds] {hasMore ? <LoadMore pullUp={pullUp} /> : null}
.sort((a, b) => { {[...feeds].map((mid, idx) => {
return Number(a) - Number(b);
})
.map((mid, idx) => {
const curr = messageData[mid]; const curr = messageData[mid];
const prev = idx == 0 ? null : messageData[msgIds[idx - 1]]; const prev = idx == 0 ? null : messageData[feeds[idx - 1]];
const read = curr?.from_uid == loginUid || mid <= readIndex; const read = curr?.from_uid == loginUid || mid <= readIndex;
return renderMessageFragment({ return renderMessageFragment({
selectMode: !!selects, selectMode: !!selects,