import React , { useRef } from 'react' ; import { useSelector } from 'react-redux' ; import { css } from 'linaria' ; import { State , Message } from '../../state/reducer' ; import useIsLogin from '../../hooks/useIsLogin' ; import useAction from '../../hooks/useAction' ; import { getLinkmanHistoryMessages , getDefaultGroupHistoryMessages , updateHistory , } from '../../service' ; import MessageComponent from './Message/Message' ; import Style from './MessageList.less' ; const styles = { container : css `
        flex: 1;
        position: relative;
        overflow: hidden;
    ` , unread : css `
        position: absolute;
        bottom: 6px;
        left: 50%;
        transform: translateX(-50%);
        background-color: var(--primary-color-8);
        font-size: 14px;
        color: var(--primary-text-color-9);
        padding: 3px 8px;
        border-radius: 3px;
        display: flex;
        align-items: center;
        justify-content: center;
        cursor: pointer;
    ` , } ; function MessageList ( ) { const action = useAction ( ) ; const selfId = useSelector ( ( state ) => state . user ?. _id || '' ) ; const focus = useSelector ( ( state ) => state . focus ) ; const isGroup = useSelector ( ( state ) => state . linkmans [ focus ] . type === 'group' ) ; const creator = useSelector ( ( state ) => state . linkmans [ focus ] . creator ) ; const messages = useSelector ( ( state ) => state . linkmans [ focus ] . messages ) ; const unread = useSelector ( ( state ) => state . linkmans [ focus ] . unread ) ; const isLogin = useIsLogin ( ) ; const tagColorMode = useSelector ( ( state ) => state . status . tagColorMode ) ; const $list = useRef < HTMLDivElement > ( null ) ; function clearUnread ( ) { action . setLinkmanProperty ( focus , 'unread' , 0 ) ; const messageKeys = Object . keys ( messages ) ; if ( messageKeys . length > 0 ) { updateHistory ( focus , messages [ messageKeys [ messageKeys . length - 1 ] ] . _id ) ; } } let isFetching = false ; async function handleScroll ( e ) { if ( $list . current && e . target !== $list . current ) { return ; } if ( isFetching ) { return ; } const $div = e . target as HTMLDivElement ; if ( unread && $div . scrollHeight - $div . clientHeight - $div . scrollTop > 50 ) { clearUnread ( ) ; } if ( $div . scrollTop === 0 && $div . scrollHeight > $div . clientHeight ) { isFetching = true ; let historyMessages = [ ] ; if ( isLogin ) { historyMessages = await getLinkmanHistoryMessages ( focus , Object . keys ( messages ) . length ) ; } else { historyMessages = await getDefaultGroupHistoryMessages ( Object . keys ( messages ) . length ) ; } if ( historyMessages && historyMessages . length > 0 ) { action . addLinkmanHistoryMessages ( focus , historyMessages ) ; } isFetching = false ; } } function renderMessage ( message ) { const isSelf = message . from . _id === selfId ; let shouldScroll = true ; if ( $list . current ) { const { scrollHeight , clientHeight , scrollTop } = $list . current ; shouldScroll = isSelf || scrollHeight === clientHeight || scrollTop === 0 || scrollTop > scrollHeight - clientHeight * 2 ; } let { tag } = message . from ; if ( ! tag && isGroup && message . from . _id === creator ) { tag = '群主' ; } return ( < MessageComponent key = { message . _id } id = { message . _id } linkmanId = { focus } isSelf = { isSelf } userId = { message . from . _id } avatar = { message . from . avatar } username = { message . from . username } originUsername = { message . from . originUsername } time = { message . createTime } type = { message . type } content = { message . content } tag = { tag } loading = { message . loading } percent = { message . percent } shouldScroll = { shouldScroll } tagColorMode = { tagColorMode } / > ) ; } return ( < div className = { styles . container } > < div className = { `${ Style . messageList } show-scrollbar` } onScroll = { handleScroll } ref = { $list } > { Object . values ( messages ) . map ( ( message ) => renderMessage ( message ) ) } < /div> < /div>); } export default MessageList ;