feat: pagination message feed

This commit is contained in:
zerosoul
2022-05-24 21:40:18 +08:00
parent 2e64c7a686
commit 1f6bfa1629
6 changed files with 254 additions and 62 deletions
+51
View File
@@ -0,0 +1,51 @@
// import { useRef, useEffect } from "react";
import styled from "styled-components";
import { Waveform } from "@uiball/loaders";
const Styled = styled.div`
display: flex;
justify-content: center;
align-items: center;
width: 100%;
padding: 8px;
/* background-color: #eee; */
`;
export default function LoadMore() {
// const ref = useRef(undefined);
// useEffect(() => {
// const observer = new IntersectionObserver(
// (entries) => {
// entries.forEach((entry) => {
// const intersecting = entry.isIntersecting;
// // const currEle = entry.target;
// if (intersecting && loadMore) {
// // load more
// console.log("inview");
// loadMore();
// }
// });
// },
// { threshold: 0 }
// );
// const currEle = ref?.current;
// if (currEle) {
// observer.observe(ref.current);
// }
// return () => {
// if (currEle) {
// observer.unobserve(currEle);
// }
// };
// }, [ref]);
return (
<Styled>
<Waveform
className="loading"
size={24}
lineWeight={5}
speed={1}
color="#ccc"
/>
</Styled>
);
}
+72 -56
View File
@@ -2,12 +2,15 @@ import { useState, useEffect } from "react";
import { useDebounce } from "rooks";
import { NavLink, useLocation } from "react-router-dom";
import Tippy from "@tippyjs/react";
import InfiniteScroll from "react-infinite-scroller";
import { useDispatch, useSelector } from "react-redux";
import PinList from "./PinList";
import LoadMore from "./LoadMore";
import FavList from "../FavList";
import { useReadMessageMutation } from "../../../app/services/message";
import { updateRemeberedNavs } from "../../../app/slices/ui";
import useChatScroll from "../../../common/hook/useChatScroll";
// import useChatScroll from "../../../common/hook/useChatScroll";
import useMessageFeed from "../../../common/hook/useMessageFeed";
import ChannelIcon from "../../../common/component/ChannelIcon";
import Tooltip from "../../../common/component/Tooltip";
import Contact from "../../../common/component/Contact";
@@ -23,15 +26,14 @@ import IconHeadphone from "../../../assets/icons/headphone.svg";
import boardosIcon from "../../../assets/icons/app.boardos.svg?url";
import webrowseIcon from "../../../assets/icons/app.webrowse.svg?url";
import addIcon from "../../../assets/icons/add.svg?url";
import {
// StyledNotification,
StyledContacts,
StyledChannelChat,
StyledHeader,
} from "./styled";
import { StyledContacts, StyledChannelChat, StyledHeader } from "./styled";
import InviteModal from "../../../common/component/InviteModal";
export default function ChannelChat({ cid = "", dropFiles = [] }) {
const { list: msgIdList, appends, hasMore, pullUp } = useMessageFeed({
context: "channel",
id: cid,
});
const [toolVisible, setToolVisible] = useState("");
const { pathname } = useLocation();
const dispatch = useDispatch();
@@ -41,7 +43,6 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
const [addMemberModalVisible, setAddMemberModalVisible] = useState(false);
const {
selects,
msgIds,
userIds,
data,
messageData,
@@ -54,16 +55,16 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
footprint: store.footprint,
loginUser: store.contacts.byId[store.authData.uid],
loginUid: store.authData.uid,
msgIds: store.channelMessage[cid] || [],
userIds: store.contacts.ids,
data: store.channels.byId[cid] || {},
messageData: store.message || {},
};
});
const ref = useChatScroll(msgIds);
// const ref = useChatScroll(mids);
// const handleClearUnreads = () => {
// dispatch(readMessage(msgIds));
// };
// remember the route while switching out
useEffect(() => {
dispatch(updateRemeberedNavs());
return () => {
@@ -83,9 +84,9 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
? userIds
: members.slice(0).sort((n) => (n == owner ? -1 : 0));
const addVisible = loginUser?.is_admin || owner == loginUid;
console.log("channel message list", msgIds);
const readIndex = footprint.readChannels[cid];
const pinCount = data?.pinned_messages?.length || 0;
const finalHasMore = selects ? false : hasMore;
return (
<>
{addMemberModalVisible && (
@@ -99,21 +100,11 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
aside={
<>
<ul className="tools">
{/* <li className="tool">
<Tooltip tip="Search" placement="left">
<img src={searchIcon} alt="opt icon" />
</Tooltip>
</li> */}
<li className="tool">
<Tooltip tip="Voice/Video Chat" placement="left">
<IconHeadphone />
</Tooltip>
</li>
{/* <li className="tool">
<Tooltip tip="Notifications" placement="left">
<img src={alertIcon} alt="opt icon" />
</Tooltip>
</li> */}
<Tooltip
tip="Pin"
placement="left"
@@ -231,41 +222,66 @@ export default function ChannelChat({ cid = "", dropFiles = [] }) {
) : null
}
>
<StyledChannelChat ref={ref}>
<div className="info">
<h2 className="title">Welcome to #{name} !</h2>
<p className="desc">This is the start of the #{name} channel. </p>
<NavLink
to={`/setting/channel/${cid}?f=${pathname}`}
className="edit"
>
<EditIcon className="icon" />
Edit Channel
</NavLink>
</div>
<div className="feed">
{[...msgIds]
.sort((a, b) => {
return Number(a) - Number(b);
})
.map((mid, idx) => {
const curr = messageData[mid];
if (!curr) return null;
const isFirst = idx == 0;
const prev = idx == 0 ? null : messageData[msgIds[idx - 1]];
const read = curr?.from_uid == loginUid || mid <= readIndex;
return renderMessageFragment({
selectMode: !!selects,
updateReadIndex: updateReadDebounced,
read,
isFirst,
prev,
curr,
contextId: cid,
context: "channel",
});
})}
</div>
<StyledChannelChat>
{!hasMore && (
<div className="info">
<h2 className="title">Welcome to #{name} !</h2>
<p className="desc">This is the start of the #{name} channel. </p>
<NavLink
to={`/setting/channel/${cid}?f=${pathname}`}
className="edit"
>
<EditIcon className="icon" />
Edit Channel
</NavLink>
</div>
)}
{/* <div className="feed"> */}
<InfiniteScroll
threshold={50}
hasMore={hasMore}
useWindow={false}
loader={<LoadMore />}
isReverse={true}
loadMore={pullUp}
>
{msgIdList.map((mid, idx) => {
const curr = messageData[mid];
if (!curr) return null;
const isFirst = idx == 0;
const prev = idx == 0 ? null : messageData[msgIdList[idx - 1]];
const read = curr?.from_uid == loginUid || mid <= readIndex;
return renderMessageFragment({
selectMode: !!selects,
updateReadIndex: updateReadDebounced,
read,
isFirst,
prev,
curr,
contextId: cid,
context: "channel",
});
})}
</InfiniteScroll>
{appends.map((mid, idx) => {
const curr = messageData[mid];
if (!curr) return null;
const isFirst = idx == 0;
const prev =
idx == 0 ? msgIdList.slice(-1)[0] : messageData[appends[idx - 1]];
const read = curr?.from_uid == loginUid || mid <= readIndex;
return renderMessageFragment({
selectMode: !!selects,
updateReadIndex: updateReadDebounced,
read,
isFirst,
prev,
curr,
contextId: cid,
context: "channel",
});
})}
{/* </div> */}
</StyledChannelChat>
{/* {unreads != 0 && (
<StyledNotification>
+8 -5
View File
@@ -86,7 +86,8 @@ export const StyledChannelChat = styled.article`
width: 100%;
height: 100%;
height: -webkit-fill-available;
overflow: auto;
overflow-x: hidden;
overflow-y: auto;
> .info {
padding-top: 62px;
display: flex;
@@ -127,8 +128,10 @@ export const StyledChannelChat = styled.article`
text-fill-color: transparent;
}
}
> .feed {
/* display: flex;
flex-direction: column-reverse; */
}
/* > .feed {
overflow-anchor: none;
> div {
overflow-anchor: auto;
}
} */
`;