diff --git a/src/common/component/FileMessage/ImageMessage.tsx b/src/common/component/FileMessage/ImageMessage.tsx index 6ae52282..3f8bef0b 100644 --- a/src/common/component/FileMessage/ImageMessage.tsx +++ b/src/common/component/FileMessage/ImageMessage.tsx @@ -1,6 +1,6 @@ import { useState, useEffect, FC } from "react"; import { Ping } from '@uiball/loaders'; -// import { getDefaultSize } from "../../utils"; +import { getDefaultSize, isMobile } from "../../utils"; type Props = { uploading: boolean; @@ -20,7 +20,7 @@ const ImageMessage: FC = ({ properties }) => { const [url, setUrl] = useState(thumbnail); - // const { width = 0, height = 0 } = getDefaultSize(properties); + const { width = 0, height = 0 } = getDefaultSize(properties, { min: 200, max: isMobile() ? 300 : 480 }); useEffect(() => { const newUrl = thumbnail; const img = new Image(); @@ -34,7 +34,11 @@ const ImageMessage: FC = ({ }, [thumbnail]); return ( -
+
{uploading && (
= ({
)} = ({ cid }) => { const uids = channel ? (channel.is_public ? users.ids : channel.members) : users.ids; return
    diff --git a/src/common/utils.tsx b/src/common/utils.tsx index a736cdfc..a668fc91 100644 --- a/src/common/utils.tsx +++ b/src/common/utils.tsx @@ -50,21 +50,22 @@ export const isElementVisible = (el: Element | null) => { || el.contains(efp(rect.left, rect.bottom)) ); }; -export function getDefaultSize(size?: { width: number; height: number }, min = 480) { +export function getDefaultSize(size?: { width: number; height: number }, limit?: { min: number; max: number }) { if (!size) return { width: 0, height: 0 }; + const { min, max } = limit ?? { min: 200, max: 320 }; const { width: oWidth, height: oHeight } = size; if (oWidth == oHeight) { - const tmp = min > oWidth ? oWidth : min; + const tmp = min > oWidth ? min : (oWidth < max ? oWidth : max); return { width: tmp, height: tmp }; } const isVertical = oWidth <= oHeight; let dWidth = 0; let dHeight = 0; if (isVertical) { - dHeight = oHeight >= min ? min : oHeight; + dHeight = oHeight < min ? min : (oHeight < max ? oHeight : max); dWidth = (oWidth / oHeight) * dHeight; } else { - dWidth = oWidth >= min ? min : oWidth; + dWidth = oWidth < min ? min : (oWidth < max ? oWidth : max); dHeight = (oHeight / oWidth) * dWidth; } return { width: dWidth, height: dHeight }; diff --git a/src/routes/chat/Layout/MessageFeed.tsx b/src/routes/chat/Layout/MessageFeed.tsx index 05d9366d..a55c3d57 100644 --- a/src/routes/chat/Layout/MessageFeed.tsx +++ b/src/routes/chat/Layout/MessageFeed.tsx @@ -1,8 +1,8 @@ -import { useEffect, useRef } from 'react'; +import { memo, useEffect, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import { NavLink, useLocation } from 'react-router-dom'; import { useDebounce } from 'rooks'; -import { ViewportList } from 'react-viewport-list'; +import { ViewportList, ViewportListRef } from 'react-viewport-list'; import { useReadMessageMutation } from '../../../app/services/message'; import { useAppSelector } from '../../../app/store'; @@ -14,9 +14,9 @@ type Props = { context: "user" | "channel", id: number } - +const triggerScrollHeight = 400; const MessageFeed = ({ context, id }: Props) => { - // const listRef = useRef(null); + const listRef = useRef(null); const ref = useRef( null, ); @@ -41,17 +41,45 @@ const MessageFeed = ({ context, id }: Props) => { messageData: store.message || {} }; }); - // useEffect(() => { - // // 滚动到记忆位置 - // if (listRef && listRef.current) { - // listRef.current.scrollToIndex({ index: 5 }); - // } - // }, [context, id]); + useEffect(() => { + // 上下文有变动,则滚动到底部 + console.log("listRef", listRef); + if (listRef && listRef.current) { + const list = listRef.current; + ref.current?.classList.remove("scroll-smooth"); + list.scrollToIndex({ + index: Number.POSITIVE_INFINITY + }); + setTimeout(() => { + // tricky + ref.current?.classList.add("scroll-smooth"); + }, 150); + } + }, [context, id]); + useEffect(() => { + // 需要检测滚动位置,如果距离底部超过阈值,则不滚到底部 + if (ref && ref.current) { + const container = ref.current; + const { scrollHeight, scrollTop, offsetHeight } = container; + const deltaNum = scrollHeight - scrollTop - offsetHeight; + console.log("delta", deltaNum); + + if (deltaNum < triggerScrollHeight) { + // scroll to bottom + container.scrollTop = container.scrollHeight; + } + } + }, [mids]); + + const handleMessageListChange = (data: [number, number]) => { + const [first, last] = data; + console.log("index changed", data); + }; const readIndex = context == "channel" ? footprint.readChannels[id] : Number.POSITIVE_INFINITY; const isEmptyList = !mids || mids.length == 0; return ( -
    +
    {context == "channel" &&

    {t("welcome_channel", { name: data?.name })}

    {t("welcome_desc", { name: data?.name })}

    @@ -63,11 +91,12 @@ const MessageFeed = ({ context, id }: Props) => { )}
    } {isEmptyList ? null : @@ -92,4 +121,4 @@ const MessageFeed = ({ context, id }: Props) => { ); }; -export default MessageFeed; \ No newline at end of file +export default memo(MessageFeed); \ No newline at end of file diff --git a/src/routes/chat/SessionList/index.tsx b/src/routes/chat/SessionList/index.tsx index bc0d56eb..d0240149 100644 --- a/src/routes/chat/SessionList/index.tsx +++ b/src/routes/chat/SessionList/index.tsx @@ -1,4 +1,4 @@ -import { FC, useRef } from "react"; +import { FC, memo, useRef } from "react"; import { useState, useEffect } from "react"; import { ViewportList } from "react-viewport-list"; import Session from "./Session"; @@ -81,7 +81,6 @@ const SessionList: FC = ({ tempSession }) => { items={sessions} > {(s) => { - console.log("ssss", sessions); const { type, id, mid = 0 } = s; const key = `${type}_${id}`; return ( @@ -117,4 +116,4 @@ const SessionList: FC = ({ tempSession }) => { ); }; -export default SessionList; +export default memo(SessionList);