From dd61fe58829993afc5d826ea2d73c8234f11c88b Mon Sep 17 00:00:00 2001 From: zerosoul Date: Tue, 31 May 2022 10:59:10 +0800 Subject: [PATCH] chore: stash updates --- src/common/hook/useMessageFeed.js | 106 +++---- src/routes/chat/ChannelChat/LoadMore.js | 59 ++-- src/routes/chat/ChannelChat/index.haodong.js | 287 +++++++++++++++++++ src/routes/chat/ChannelChat/styled.tmp.js | 142 +++++++++ 4 files changed, 499 insertions(+), 95 deletions(-) create mode 100644 src/routes/chat/ChannelChat/index.haodong.js create mode 100644 src/routes/chat/ChannelChat/styled.tmp.js diff --git a/src/common/hook/useMessageFeed.js b/src/common/hook/useMessageFeed.js index b0e6a110..32770094 100644 --- a/src/common/hook/useMessageFeed.js +++ b/src/common/hook/useMessageFeed.js @@ -1,7 +1,8 @@ import { useEffect, useState, useRef } from "react"; import { useSelector } from "react-redux"; const getFeedWithPagination = (config) => { - const { pageNumber = 1, pageSize = 20, mids = [] } = config || {}; + const { pageNumber = 1, pageSize = 10, mids = [], isLast = false } = + config || {}; const shadowMids = mids.slice(0); if (shadowMids.length == 0) @@ -12,30 +13,27 @@ const getFeedWithPagination = (config) => { ids: [], }; shadowMids.sort((a, b) => { - return Number(b) - Number(a); + return Number(a) - Number(b); }); console.log("message pagination", shadowMids); const pageCount = Math.ceil(shadowMids.length / pageSize); + const computedPageNumber = isLast ? pageCount : pageNumber; const ids = shadowMids.slice( - (pageNumber - 1) * pageSize, - pageNumber * pageSize + (computedPageNumber - 1) * pageSize, + computedPageNumber * pageSize ); - const info = { - isFirst: pageNumber == 1, - isLast: pageNumber == pageCount, + return { pageCount, pageSize, - pageNumber, + pageNumber: computedPageNumber, ids, }; - console.log("get page Info", info); - return info; }; export default function useMessageFeed({ context = "channel", id = null }) { const listRef = useRef([]); const pageRef = useRef(null); const [hasMore, setHasMore] = useState(true); - // const [appends, setAppends] = useState([]); + const [appends, setAppends] = useState([]); const [items, setItems] = useState([]); const { mids, messageData } = useSelector((store) => { return { @@ -51,72 +49,46 @@ export default function useMessageFeed({ context = "channel", id = null }) { pageRef.current = []; setItems([]); setHasMore(true); - // setAppends([]); + setAppends([]); }, [context, id]); - // useEffect(() => { - // if (appends.length) { - // const feedsWrapperEle = document.querySelector( - // `#RUSTCHAT_FEED_${context}_${id}` - // ); - // if (feedsWrapperEle) { - // feedsWrapperEle.scrollTop = feedsWrapperEle.scrollHeight; - // } - // } - // }, [appends, context, id]); useEffect(() => { - const container = document.querySelector("#ScrollFeedWrapper"); - const handler = (e) => { - e.preventDefault(); - var n = 0; - if ("deltaY" in e) n = 1 === e.deltaMode ? 20 * -e.deltaY : -e.deltaY; - else if ("wheelDeltaY" in e) n = (e.wheelDeltaY / 120) * 20; - else if ("wheelDelta" in e) n = (e.wheelDelta / 120) * 20; - else { - // if (!("detail"in e)) - // return void a.v(e, "invalid wheel event: "); - n = (-e.detail / 3) * 20; + if (appends.length) { + const feedsWrapperEle = document.querySelector( + `#RUSTCHAT_FEED_${context}_${id}` + ); + if (feedsWrapperEle) { + feedsWrapperEle.scrollTop = feedsWrapperEle.scrollHeight; } - container.scrollTop += n; - }; - if (container) { - container.addEventListener("wheel", handler); } - return () => { - if (container) { - container.removeEventListener("wheel", handler); - } - }; - }, []); - + }, [appends, context, id]); useEffect(() => { if (listRef.current.length == 0) { // 初次 - const pageInfo = getFeedWithPagination({ mids }); - console.log("pull down 2", pageInfo); + const pageInfo = getFeedWithPagination({ mids, isLast: true }); + console.log("pull up 2", pageInfo); pageRef.current = pageInfo; listRef.current = pageInfo.ids; setItems(listRef.current); console.log("message pageInfo", mids, pageInfo); } else { // 追加 - const lastMid = listRef.current[0]; + const lastMid = listRef.current.slice(-1); const sorteds = mids.slice(0).sort((a, b) => { - return Number(b) - Number(a); + return Number(a) - Number(b); }); - const prepends = sorteds.filter((s) => s > lastMid); - if (prepends.length) { - setItems((prevs) => [...prepends, ...prevs]); + const appends = sorteds.filter((s) => s > lastMid); + if (appends.length) { + setAppends(appends); } - console.log("prepends", prepends, items); + console.log("appends", appends); } }, [mids]); - const pullDown = () => { - // 向下加载 + const pullUp = () => { const currPageInfo = pageRef.current; - console.log("pull down", currPageInfo); - // 最后一页 - if (currPageInfo && currPageInfo.isLast) { - setHasMore(true); + console.log("pull up", currPageInfo); + // 第一页 + if (currPageInfo && currPageInfo.pageNumber == 1) { + setHasMore(false); return; } let pageInfo = null; @@ -124,28 +96,32 @@ export default function useMessageFeed({ context = "channel", id = null }) { // 初始化 pageInfo = getFeedWithPagination({ mids, + isLast: true, }); } else { - const nextPageNumber = currPageInfo.pageNumber + 1; + const prevPageNumber = currPageInfo.pageNumber - 1; pageInfo = getFeedWithPagination({ mids, - pageNumber: nextPageNumber, + pageNumber: prevPageNumber, }); } pageRef.current = pageInfo; - listRef.current = [...listRef.current, ...pageInfo.ids]; + listRef.current = [...pageInfo.ids, ...listRef.current]; setTimeout(() => { setItems(listRef.current); console.log("pull up", currPageInfo, listRef.current); - setHasMore(!pageInfo.isLast); - }, 1000); + setHasMore(pageInfo.pageNumber !== 1); + }, 800); + }; + const pullDown = () => { + // 向下加载 }; return { mids, - // appends, + appends, hasMore, - // pullUp, + pullUp, pullDown, list: items, }; diff --git a/src/routes/chat/ChannelChat/LoadMore.js b/src/routes/chat/ChannelChat/LoadMore.js index 87ef7fdd..78d6edbe 100644 --- a/src/routes/chat/ChannelChat/LoadMore.js +++ b/src/routes/chat/ChannelChat/LoadMore.js @@ -1,9 +1,8 @@ -import { useRef, useEffect } from "react"; +// import { useRef, useEffect } from "react"; import styled from "styled-components"; import { Waveform } from "@uiball/loaders"; const Styled = styled.div` - margin-top: 80px; display: flex; justify-content: center; align-items: center; @@ -11,35 +10,35 @@ const Styled = styled.div` padding: 30px 0; /* background-color: #eee; */ `; -export default function LoadMore({ pullDown = null }) { - const ref = useRef(undefined); - useEffect(() => { - const observer = new IntersectionObserver( - (entries) => { - entries.forEach((entry) => { - const intersecting = entry.isIntersecting; - // const currEle = entry.target; - if (intersecting && pullDown) { - // load more - console.log("inview"); - pullDown(); - } - }); - }, - { threshold: 0 } - ); - const currEle = ref?.current; - if (currEle) { - observer.observe(ref.current); - } - return () => { - if (currEle) { - observer.unobserve(currEle); - } - }; - }, [ref, pullDown]); +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 ( - + { + return { + selects: store.ui.selectMessages[`channel_${cid}`], + 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 handleClearUnreads = () => { + // dispatch(readMessage(msgIds)); + // }; + useEffect(() => { + dispatch(updateRemeberedNavs()); + return () => { + dispatch(updateRemeberedNavs({ path: pathname })); + }; + }, [pathname]); + + const toggleMembersVisible = () => { + setMembersVisible((prev) => !prev); + }; + const toggleAddVisible = () => { + setAddMemberModalVisible((prev) => !prev); + }; + if (!data) return null; + const { name, description, is_public, members = [], owner } = data; + const memberIds = is_public + ? 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; + return ( + <> + {addMemberModalVisible && ( + + )} + +
    +
  • + + + +
  • + + { + setToolVisible("pin"); + }} + onHide={() => { + setToolVisible(""); + }} + placement="left-start" + popperOptions={{ strategy: "fixed" }} + offset={[0, 80]} + interactive + trigger="click" + content={} + > +
  • 0 ? "badge" : ""} ${ + toolVisible == "pin" ? "active" : "" + } `} + data-count={pinCount} + > + +
  • +
    +
    + + { + setToolVisible("favorite"); + }} + onHide={() => { + setToolVisible(""); + }} + placement="left-start" + popperOptions={{ strategy: "fixed" }} + offset={[0, 180]} + interactive + trigger="click" + content={} + > +
  • + +
  • +
    +
    +
  • + + + +
  • +
+
+
    +
  • + + app icon + +
  • +
  • + + app icon + +
  • +
+ + } + header={ + +
+ + {name} + {description} +
+
+ } + contacts={ + membersVisible ? ( + <> + + {addVisible && ( +
+ +
Add members
+
+ )} + {memberIds.map((uid) => { + return ( + + ); + })} +
+ + ) : null + } + > + + {/*
*/} + {[...msgIds].map((mid, idx) => { + const curr = messageData[mid]; + if (!curr) return null; + const isFirst = idx == 0; + const prev = + idx == msgIds.length - 1 ? 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", + }); + })} + {hasMore ? ( + + ) : ( +
+

Welcome to #{name} !

+

This is the start of the #{name} channel.

+ + + Edit Channel + +
+ )} + {/*
*/} +
+ {/* {unreads != 0 && ( + +
+ {unreads} new messages + {msgs.lastAccess + ? `since ${dayjs(msgs.lastAccess).format("YYYY-MM-DD h:mm:ss A")}` + : ""} +
+ +
+ )} */} +
+ + ); +} diff --git a/src/routes/chat/ChannelChat/styled.tmp.js b/src/routes/chat/ChannelChat/styled.tmp.js new file mode 100644 index 00000000..517ae40b --- /dev/null +++ b/src/routes/chat/ChannelChat/styled.tmp.js @@ -0,0 +1,142 @@ +import styled from "styled-components"; +export const StyledHeader = styled.header` + height: 100%; + display: flex; + align-items: center; + justify-content: space-between; + .txt { + display: flex; + align-items: center; + gap: 5px; + .title { + font-size: 16px; + line-height: 24px; + color: #1c1c1e; + } + .desc { + margin-left: 8px; + font-weight: normal; + font-size: 16px; + line-height: 24px; + color: #616161; + } + } +`; +export const StyledNotification = styled.div` + padding: 3px 8px; + font-style: normal; + font-weight: 600; + font-size: 12px; + line-height: 18px; + color: #fff; + position: absolute; + top: 0; + left: 10px; + width: 900px; + height: 24px; + background: linear-gradient(135deg, #3c8ce7 0%, #00eaff 100%); + border-radius: 0px 0px 8px 8px; + display: flex; + align-items: center; + justify-content: space-between; + .clear { + cursor: pointer; + color: inherit; + border: none; + background: none; + outline: none; + } +`; +export const StyledContacts = styled.div` + display: flex; + flex-direction: column; + gap: 5px; + /* todo */ + width: 226px; + height: calc(100vh - 56px - 22px); + overflow-y: scroll; + padding: 8px; + box-shadow: inset 1px 0px 0px rgba(0, 0, 0, 0.1); + > .add { + cursor: pointer; + display: flex; + align-items: center; + justify-content: flex-start; + gap: 4px; + padding: 10px; + border-radius: 8px; + user-select: none; + &:hover { + background: rgba(116, 127, 141, 0.1); + } + .icon { + width: 24px; + height: 24px; + } + .txt { + font-weight: 600; + font-size: 14px; + line-height: 20px; + color: #52525b; + } + } +`; +export const StyledChannelChat = styled.article` + padding: 18px 16px; + width: 100%; + height: 100%; + height: -webkit-fill-available; + overflow-x: hidden; + overflow-y: auto; + transform: rotate(180deg) translateZ(0); + direction: rtl; + /* display: flex; + flex-direction: column-reverse; */ + > div, + > hr { + direction: ltr; + transform: rotate(180deg); + } + > .info { + padding-top: 62px; + display: flex; + flex-direction: column; + align-items: flex-start; + gap: 8px; + .title { + font-weight: bold; + font-size: 36px; + line-height: 44px; + } + .desc { + color: #78787c; + font-weight: 500; + font-size: 16px; + line-height: 24px; + } + .edit { + display: flex; + align-items: center; + gap: 4px; + .icon { + width: 16px; + height: 16px; + path { + fill: #3c8ce7; + } + } + padding: 0; + font-style: normal; + font-weight: 500; + font-size: 16px; + line-height: 24px; + background: linear-gradient(135deg, #3c8ce7 0%, #00eaff 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + text-fill-color: transparent; + } + } + /* > .feed { + } */ +`;