feat: add pagination to DM session
This commit is contained in:
@@ -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) => {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 = [] }) {
|
||||||
|
|||||||
@@ -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,
|
return {
|
||||||
messageData,
|
selects: store.ui.selectMessages[`user_${uid}`],
|
||||||
footprint,
|
loginUid: store.authData.uid,
|
||||||
loginUid,
|
footprint: store.footprint,
|
||||||
selects,
|
currUser: store.contacts.byId[uid],
|
||||||
} = useSelector((store) => {
|
messageData: store.message,
|
||||||
return {
|
};
|
||||||
selects: store.ui.selectMessages[`user_${uid}`],
|
}
|
||||||
loginUid: store.authData.uid,
|
);
|
||||||
footprint: store.footprint,
|
// const ref = useChatScroll(msgIds);
|
||||||
currUser: store.contacts.byId[uid],
|
|
||||||
msgIds: store.userMessage.byId[uid] || [],
|
|
||||||
messageData: store.message,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
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,25 +98,22 @@ 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);
|
const curr = messageData[mid];
|
||||||
})
|
const prev = idx == 0 ? null : messageData[feeds[idx - 1]];
|
||||||
.map((mid, idx) => {
|
const read = curr?.from_uid == loginUid || mid <= readIndex;
|
||||||
const curr = messageData[mid];
|
return renderMessageFragment({
|
||||||
const prev = idx == 0 ? null : messageData[msgIds[idx - 1]];
|
selectMode: !!selects,
|
||||||
const read = curr?.from_uid == loginUid || mid <= readIndex;
|
updateReadIndex: updateReadDebounced,
|
||||||
return renderMessageFragment({
|
read,
|
||||||
selectMode: !!selects,
|
prev,
|
||||||
updateReadIndex: updateReadDebounced,
|
curr,
|
||||||
read,
|
contextId: uid,
|
||||||
prev,
|
context: "user",
|
||||||
curr,
|
});
|
||||||
contextId: uid,
|
})}
|
||||||
context: "user",
|
|
||||||
});
|
|
||||||
})}
|
|
||||||
</StyledDMChat>
|
</StyledDMChat>
|
||||||
</Layout>
|
</Layout>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user