From 2e0332218bd08a88bf632d29edf0db09221a87ef Mon Sep 17 00:00:00 2001 From: Fedor Katurov Date: Wed, 9 Sep 2020 13:32:28 +0700 Subject: [PATCH] messages form at the bottom --- .../dialogs/BetterScrollDialog/index.tsx | 4 +- .../dialogs/ProfileDialog/index.tsx | 11 +++ src/containers/profile/ProfileInfo/index.tsx | 16 ++-- .../profile/ProfileMessages/index.tsx | 86 ++++++++++++++----- .../profile/ProfileMessages/styles.scss | 15 ++++ 5 files changed, 97 insertions(+), 35 deletions(-) diff --git a/src/containers/dialogs/BetterScrollDialog/index.tsx b/src/containers/dialogs/BetterScrollDialog/index.tsx index 3b5c54b7..eb580ae9 100644 --- a/src/containers/dialogs/BetterScrollDialog/index.tsx +++ b/src/containers/dialogs/BetterScrollDialog/index.tsx @@ -1,6 +1,6 @@ -import React, { FC, MouseEventHandler, useEffect, useRef, ReactElement } from 'react'; +import React, { FC, MouseEventHandler, ReactElement, useEffect, useRef, } from 'react'; import * as styles from './styles.scss'; -import { enableBodyScroll, disableBodyScroll } from 'body-scroll-lock'; +import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock'; import { Icon } from '~/components/input/Icon'; import { LoaderCircle } from '~/components/input/LoaderCircle'; diff --git a/src/containers/dialogs/ProfileDialog/index.tsx b/src/containers/dialogs/ProfileDialog/index.tsx index 26ba39f0..4e361af5 100644 --- a/src/containers/dialogs/ProfileDialog/index.tsx +++ b/src/containers/dialogs/ProfileDialog/index.tsx @@ -12,6 +12,7 @@ import pick from 'ramda/es/pick'; import { CoverBackdrop } from '~/components/containers/CoverBackdrop'; import { ProfileSettings } from '~/components/profile/ProfileSettings'; import { ProfileAccounts } from '~/components/profile/ProfileAccounts'; +import { MessageForm } from '~/components/profile/MessageForm'; const TAB_CONTENT = { profile: , @@ -31,6 +32,14 @@ const mapDispatchToProps = { type IProps = IDialogProps & ReturnType & typeof mapDispatchToProps & {}; +const PROFILE_HEADERS = { + // messages: , +}; + +const PROFILE_FOOTERS = { + messages: , +}; + const ProfileDialogUnconnected: FC = ({ onRequestClose, authSetProfile, @@ -51,8 +60,10 @@ const ProfileDialogUnconnected: FC = ({ user={user} tab={tab} setTab={setTab} + content={PROFILE_HEADERS[tab]} /> } + footer={PROFILE_FOOTERS[tab]} backdrop={} onClose={onRequestClose} > diff --git a/src/containers/profile/ProfileInfo/index.tsx b/src/containers/profile/ProfileInfo/index.tsx index adcb160f..f70c7c70 100644 --- a/src/containers/profile/ProfileInfo/index.tsx +++ b/src/containers/profile/ProfileInfo/index.tsx @@ -1,12 +1,10 @@ -import React, { FC } from 'react'; +import React, { FC, ReactNode } from 'react'; import { IUser } from '~/redux/auth/types'; import styles from './styles.scss'; import { Group } from '~/components/containers/Group'; import { Placeholder } from '~/components/placeholders/Placeholder'; -import { getURL, getPrettyDate } from '~/utils/dom'; -import { PRESETS } from '~/constants/urls'; +import { getPrettyDate } from '~/utils/dom'; import { ProfileTabs } from '../ProfileTabs'; -import { MessageForm } from '~/components/profile/MessageForm'; import { ProfileAvatar } from '../ProfileAvatar'; interface IProps { @@ -17,13 +15,11 @@ interface IProps { is_own?: boolean; setTab?: (tab: string) => void; + + content?: ReactNode; } -const TAB_HEADERS = { - messages: , -}; - -const ProfileInfo: FC = ({ user, tab, is_loading, is_own, setTab }) => ( +const ProfileInfo: FC = ({ user, tab, is_loading, is_own, setTab, content = null }) => (
@@ -41,7 +37,7 @@ const ProfileInfo: FC = ({ user, tab, is_loading, is_own, setTab }) => ( - {TAB_HEADERS[tab] || null} + {content}
); diff --git a/src/containers/profile/ProfileMessages/index.tsx b/src/containers/profile/ProfileMessages/index.tsx index 7700f048..de3d4e9e 100644 --- a/src/containers/profile/ProfileMessages/index.tsx +++ b/src/containers/profile/ProfileMessages/index.tsx @@ -1,10 +1,9 @@ -import React, { FC, useCallback, useEffect, useState } from 'react'; +import React, { FC, useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react'; import { connect } from 'react-redux'; import { selectAuthProfile, selectAuthUser } from '~/redux/auth/selectors'; import styles from './styles.scss'; import * as AUTH_ACTIONS from '~/redux/messages/actions'; import { Message } from '~/components/profile/Message'; -import { Group } from '~/components/containers/Group'; import pick from 'ramda/es/pick'; import { NodeNoComments } from '~/components/node/NodeNoComments'; import { selectMessages } from '~/redux/messages/selectors'; @@ -29,6 +28,8 @@ const ProfileMessagesUnconnected: FC = ({ messagesGetMessages, messagesDeleteMessage, }) => { + const wasAtBottom = useRef(true); + const [wrap, setWrap] = useState(null); const [editingMessageId, setEditingMessageId] = useState(0); const onEditMessage = useCallback((id: number) => setEditingMessageId(id), [setEditingMessageId]); @@ -55,32 +56,71 @@ const ProfileMessagesUnconnected: FC = ({ return () => clearTimeout(timer); }, [profile.user, messages.messages]); + const storeRef = useCallback( + (div: HTMLDivElement) => { + if (!div || !div.parentElement) return; + const parent = div.parentElement; + parent.scrollTo(0, parent.scrollHeight); + setWrap(div); + }, + [setWrap] + ); + + useLayoutEffect(() => { + const parent = wrap?.parentElement; + + if (!parent) return; + + if (wasAtBottom.current) { + parent.scrollTo(0, parent.scrollHeight); + } + }, [messages.messages]); + + const onScroll = useCallback(() => { + const parent = wrap?.parentElement; + + if (!parent) return; + + const scrollPos = parent.scrollTop + parent.clientHeight; + wasAtBottom.current = parent.scrollHeight - scrollPos < 40; + }, [wrap]); + + useEffect(() => { + const parent = wrap?.parentElement; + if (!parent) return; + + parent.addEventListener('scroll', onScroll); + return () => parent.removeEventListener('scroll', onScroll); + }, [wrap, onScroll]); + if (!messages.messages.length || profile.is_loading) return ; return ( - - {messages.messages - .filter(message => !!message.text) - .map(( - message // TODO: show files / memo - ) => ( - - ))} + messages.messages.length > 0 && ( +
+ {messages.messages + .filter(message => !!message.text) + .map(( + message // TODO: show files / memo + ) => ( + + ))} - {!messages.is_loading_messages && messages.messages.length > 0 && ( -
Когда-нибудь здесь будут еще сообщения
- )} - + {!messages.is_loading_messages && messages.messages.length > 0 && ( +
Когда-нибудь здесь будут еще сообщения
+ )} +
+ ) ); }; diff --git a/src/containers/profile/ProfileMessages/styles.scss b/src/containers/profile/ProfileMessages/styles.scss index 197da902..45f4072f 100644 --- a/src/containers/profile/ProfileMessages/styles.scss +++ b/src/containers/profile/ProfileMessages/styles.scss @@ -1,6 +1,21 @@ .messages { padding: $gap; background: $node_bg; + display: flex; + flex-direction: column-reverse !important; + overflow: auto; + + & > * { + margin: $gap / 2 0; + + &:last-child { + margin-top: 0; + } + + &:first-child { + margin-bottom: 0; + } + } } .placeholder {