diff --git a/src/components/middle/MessageList.scss b/src/components/middle/MessageList.scss index 8e5f98788..8cc20b600 100644 --- a/src/components/middle/MessageList.scss +++ b/src/components/middle/MessageList.scss @@ -217,29 +217,6 @@ text-align: left; } - & > .bot-info { - max-width: 80%; - display: flex; - flex-direction: column; - - background: var(--pattern-color); - color: white; - font-size: calc(var(--message-text-size, 1rem) - 0.0625rem); - line-height: 1.75; - border-radius: var(--border-radius-messages); - overflow: hidden; - text-align: initial; - - & > .bot-info-description { - padding: 0.5rem 1rem; - } - - .bot-info-title { - font-weight: 500; - margin-bottom: 0.25rem; - } - } - .text-entity-link { color: inherit !important; text-decoration: underline; diff --git a/src/components/middle/MessageList.tsx b/src/components/middle/MessageList.tsx index 8f421748c..dc5e06cb1 100644 --- a/src/components/middle/MessageList.tsx +++ b/src/components/middle/MessageList.tsx @@ -10,7 +10,7 @@ import { requestForcedReflow, forceMeasure, requestMeasure } from '../../lib/fas import type { FC } from '../../lib/teact/teact'; import { getActions, getGlobal, withGlobal } from '../../global'; import type { - ApiBotInfo, ApiMessage, ApiRestrictionReason, ApiTopic, + ApiMessage, ApiRestrictionReason, ApiTopic, } from '../../api/types'; import { MAIN_THREAD_ID } from '../../api/types'; @@ -33,7 +33,6 @@ import { selectIsInSelectMode, selectIsChatWithSelf, selectBot, - selectIsChatBotNotStarted, selectScrollOffset, selectThreadTopMessageId, selectChatScheduledMessages, @@ -42,7 +41,6 @@ import { selectLastScrollOffset, selectThreadInfo, selectTabState, - selectUserFullInfo, selectChatFullInfo, selectPerformanceSettingsValue, } from '../../global/selectors'; @@ -51,31 +49,23 @@ import { isUserId, isChatWithRepliesBot, isChatGroup, - getBotCoverMediaHash, - getDocumentMediaHash, - getVideoDimensions, - getPhotoFullDimensions, isLocalMessageId, } from '../../global/helpers'; import { orderBy } from '../../util/iteratees'; -import { DPR } from '../../util/windowEnvironment'; import { debounce, onTickEnd } from '../../util/schedulers'; import buildClassName from '../../util/buildClassName'; import { groupMessages } from './helpers/groupMessages'; import { preventMessageInputBlur } from './helpers/preventMessageInputBlur'; import resetScroll from '../../util/resetScroll'; import animateScroll, { isAnimatingScroll, restartCurrentScrollAnimation } from '../../util/animateScroll'; -import renderText from '../common/helpers/renderText'; import useLastCallback from '../../hooks/useLastCallback'; import { useStateRef } from '../../hooks/useStateRef'; import useSyncEffect from '../../hooks/useSyncEffect'; import useStickyDates from './hooks/useStickyDates'; import { dispatchHeavyAnimationEvent } from '../../hooks/useHeavyAnimationCheck'; -import useLang from '../../hooks/useLang'; import useInterval from '../../hooks/useInterval'; import useNativeCopySelectedMessages from '../../hooks/useNativeCopySelectedMessages'; -import useMedia from '../../hooks/useMedia'; import useLayoutEffectWithPrevDeps from '../../hooks/useLayoutEffectWithPrevDeps'; import useEffectWithPrevDeps from '../../hooks/useEffectWithPrevDeps'; import useContainerHeight from './hooks/useContainerHeight'; @@ -85,8 +75,7 @@ import Loading from '../ui/Loading'; import MessageListContent from './MessageListContent'; import ContactGreeting from './ContactGreeting'; import NoMessages from './NoMessages'; -import Skeleton from '../ui/Skeleton'; -import OptimizedVideo from '../ui/OptimizedVideo'; +import MessageListBotInfo from './MessageListBotInfo'; import './MessageList.scss'; @@ -124,8 +113,6 @@ type StateProps = { focusingId?: number; isSelectModeActive?: boolean; lastMessage?: ApiMessage; - isLoadingBotInfo?: boolean; - botInfo?: ApiBotInfo; threadTopMessageId?: number; hasLinkedChat?: boolean; topic?: ApiTopic; @@ -173,8 +160,6 @@ const MessageList: FC = ({ focusingId, isSelectModeActive, lastMessage, - isLoadingBotInfo, - botInfo, threadTopMessageId, hasLinkedChat, withBottomShift, @@ -210,15 +195,6 @@ const MessageList: FC = ({ const isScrollTopJustUpdatedRef = useRef(false); const shouldAnimateAppearanceRef = useRef(Boolean(lastMessage)); - const botInfoPhotoUrl = useMedia(botInfo?.photo ? getBotCoverMediaHash(botInfo.photo) : undefined); - const botInfoGifUrl = useMedia(botInfo?.gif ? getDocumentMediaHash(botInfo.gif) : undefined); - const botInfoDimensions = botInfo?.photo ? getPhotoFullDimensions(botInfo.photo) : botInfo?.gif - ? getVideoDimensions(botInfo.gif) : undefined; - const botInfoRealDimensions = botInfoDimensions && { - width: botInfoDimensions.width / DPR, - height: botInfoDimensions.height / DPR, - }; - const areMessagesLoaded = Boolean(messageIds); useSyncEffect(() => { @@ -533,8 +509,6 @@ const MessageList: FC = ({ } }, [isSelectModeActive]); - const lang = useLang(); - const isPrivate = Boolean(chatId && isUserId(chatId)); const withUsers = Boolean((!isPrivate && !isChannelChat) || isChatWithSelf || isRepliesChat); const noAvatars = Boolean(!withUsers || isChannelChat); @@ -554,8 +528,6 @@ const MessageList: FC = ({ const isEmptyTopic = messageIds?.length === 1 && messagesById?.[messageIds[0]]?.content.action?.type === 'topicCreate'; - const isBotInfoEmpty = botInfo && !botInfo.description && !botInfo.gif && !botInfo.photo; - const className = buildClassName( 'MessageList custom-scroll', noAvatars && 'no-avatars', @@ -568,6 +540,8 @@ const MessageList: FC = ({ !isReady && 'is-animating', ); + const hasMessages = (messageIds && messageGroups) || lastMessage; + return (
= ({ {restrictionReason ? restrictionReason.text : `This is a private ${isChannelChat ? 'channel' : 'chat'}`}
- ) : botInfo ? ( -
- {isLoadingBotInfo && {lang('Loading')}} - {isBotInfoEmpty && !isLoadingBotInfo && {lang('NoMessages')}} - {botInfo && ( -
- {botInfoPhotoUrl && ( - Bot info - )} - {botInfoGifUrl && ( - - )} - {botInfoDimensions && !botInfoPhotoUrl && !botInfoGifUrl && ( - - )} - {botInfo.description && ( -
-

{lang('BotInfoTitle')}

- {renderText(botInfo.description, ['br', 'emoji', 'links'])} -
- )} -
- )} -
+ ) : isBot && !hasMessages ? ( + ) : shouldRenderGreeting ? ( ) : messageIds && (!messageGroups || isGroupChatJustCreated || isEmptyTopic) ? ( @@ -635,7 +567,7 @@ const MessageList: FC = ({ isChatWithSelf={isChatWithSelf} isGroupChatJustCreated={isGroupChatJustCreated} /> - ) : ((messageIds && messageGroups) || lastMessage) ? ( + ) : hasMessages ? ( = ({ threadTopMessageId={threadTopMessageId} hasLinkedChat={hasLinkedChat} isSchedule={messageGroups ? type === 'scheduled' : false} + shouldRenderBotInfo={isBot} noAppearanceAnimation={!messageGroups || !shouldAnimateAppearanceRef.current} onFabToggle={onFabToggle} onNotchToggle={onNotchToggle} @@ -699,17 +632,7 @@ export default memo(withGlobal( && !messageIds && !chat.unreadCount && !focusingId && lastMessage && !lastMessage.groupedId ); - const chatBot = selectBot(global, chatId)!; - let isLoadingBotInfo = false; - let botInfo; - if (selectIsChatBotNotStarted(global, chatId)) { - const chatBotFullInfo = selectUserFullInfo(global, chatBot.id); - if (chatBotFullInfo) { - botInfo = chatBotFullInfo.botInfo; - } else { - isLoadingBotInfo = true; - } - } + const chatBot = selectBot(global, chatId); const topic = chat.topics?.[threadId]; const chatFullInfo = !isUserId(chatId) ? selectChatFullInfo(global, chatId) : undefined; @@ -732,8 +655,6 @@ export default memo(withGlobal( isViewportNewest: type !== 'thread' || selectIsViewportNewest(global, chatId, threadId), focusingId, isSelectModeActive: selectIsInSelectMode(global), - isLoadingBotInfo, - botInfo, threadTopMessageId, hasLinkedChat: chatFullInfo ? Boolean(chatFullInfo.linkedChatId) : undefined, topic, diff --git a/src/components/middle/MessageListBotInfo.module.scss b/src/components/middle/MessageListBotInfo.module.scss new file mode 100644 index 000000000..7b45dd3c0 --- /dev/null +++ b/src/components/middle/MessageListBotInfo.module.scss @@ -0,0 +1,30 @@ +.root { + width: 100%; + height: 100%; + display: flex; + align-items: center; + justify-content: center; +} + +.bot-info { + max-width: 80%; + display: flex; + flex-direction: column; + + background: var(--pattern-color); + color: white; + font-size: calc(var(--message-text-size, 1rem) - 0.0625rem); + line-height: 1.75; + border-radius: var(--border-radius-messages); + overflow: hidden; + text-align: initial; +} + +.bot-info-description { + padding: 0.5rem 1rem; +} + +.bot-info-title { + font-weight: 500; + margin-bottom: 0.25rem; +} diff --git a/src/components/middle/MessageListBotInfo.tsx b/src/components/middle/MessageListBotInfo.tsx new file mode 100644 index 000000000..9a86baf6c --- /dev/null +++ b/src/components/middle/MessageListBotInfo.tsx @@ -0,0 +1,125 @@ +import React, { memo } from '../../lib/teact/teact'; +import { withGlobal } from '../../global'; + +import type { FC } from '../../lib/teact/teact'; +import type { ApiBotInfo } from '../../api/types'; + +import { DPR } from '../../util/windowEnvironment'; +import renderText from '../common/helpers/renderText'; +import { + getBotCoverMediaHash, + getDocumentMediaHash, + getPhotoFullDimensions, + getVideoDimensions, +} from '../../global/helpers'; +import buildStyle from '../../util/buildStyle'; +import buildClassName from '../../util/buildClassName'; +import { selectBot, selectUserFullInfo } from '../../global/selectors'; +import useMedia from '../../hooks/useMedia'; +import useLang from '../../hooks/useLang'; + +import OptimizedVideo from '../ui/OptimizedVideo'; +import Skeleton from '../ui/Skeleton'; + +import styles from './MessageListBotInfo.module.scss'; + +type OwnProps = { + chatId: string; + isInMessageList?: boolean; +}; + +type StateProps = { + botInfo?: ApiBotInfo; + isLoadingBotInfo?: boolean; +}; + +const MessageListBotInfo: FC = ({ + botInfo, + isLoadingBotInfo, + isInMessageList, +}) => { + const lang = useLang(); + + const botInfoPhotoUrl = useMedia(botInfo?.photo ? getBotCoverMediaHash(botInfo.photo) : undefined); + const botInfoGifUrl = useMedia(botInfo?.gif ? getDocumentMediaHash(botInfo.gif) : undefined); + const botInfoDimensions = botInfo?.photo ? getPhotoFullDimensions(botInfo.photo) : botInfo?.gif + ? getVideoDimensions(botInfo.gif) : undefined; + const botInfoRealDimensions = botInfoDimensions && { + width: botInfoDimensions.width / DPR, + height: botInfoDimensions.height / DPR, + }; + const isBotInfoEmpty = botInfo && !botInfo.description && !botInfo.gif && !botInfo.photo; + + const { width, height } = botInfoRealDimensions || {}; + + const isEmptyOrLoading = isBotInfoEmpty || isLoadingBotInfo; + + if (isEmptyOrLoading && isInMessageList) return undefined; + + return ( +
+ {isLoadingBotInfo && {lang('Loading')}} + {isBotInfoEmpty && !isLoadingBotInfo && {lang('NoMessages')}} + {botInfo && ( +
+ {botInfoPhotoUrl && ( + Bot info + )} + {botInfoGifUrl && ( + + )} + {botInfoDimensions && !botInfoPhotoUrl && !botInfoGifUrl && ( + + )} + {botInfo.description && ( +
+

{lang('BotInfoTitle')}

+ {renderText(botInfo.description, ['br', 'emoji', 'links'])} +
+ )} +
+ )} +
+ ); +}; + +export default memo(withGlobal( + (global, { chatId }) => { + const chatBot = selectBot(global, chatId); + let isLoadingBotInfo = false; + let botInfo; + if (chatBot) { + const chatBotFullInfo = selectUserFullInfo(global, chatBot.id); + if (chatBotFullInfo) { + botInfo = chatBotFullInfo.botInfo; + } else { + isLoadingBotInfo = true; + } + } + return { + botInfo, + isLoadingBotInfo, + }; + }, +)(MessageListBotInfo)); diff --git a/src/components/middle/MessageListContent.tsx b/src/components/middle/MessageListContent.tsx index ddf9091ab..f355706c9 100644 --- a/src/components/middle/MessageListContent.tsx +++ b/src/components/middle/MessageListContent.tsx @@ -26,6 +26,7 @@ import usePrevious from '../../hooks/usePrevious'; import Message from './message/Message'; import SponsoredMessage from './message/SponsoredMessage'; import ActionMessage from './ActionMessage'; +import MessageListBotInfo from './MessageListBotInfo'; interface OwnProps { isCurrentUserPremium?: boolean; @@ -49,6 +50,7 @@ interface OwnProps { threadTopMessageId: number | undefined; hasLinkedChat: boolean | undefined; isSchedule: boolean; + shouldRenderBotInfo?: boolean; noAppearanceAnimation: boolean; onFabToggle: AnyToVoidFunction; onNotchToggle: AnyToVoidFunction; @@ -79,6 +81,7 @@ const MessageListContent: FC = ({ threadTopMessageId, hasLinkedChat, isSchedule, + shouldRenderBotInfo, noAppearanceAnimation, onFabToggle, onNotchToggle, @@ -275,6 +278,7 @@ const MessageListContent: FC = ({ return (
{withHistoryTriggers &&
} + {shouldRenderBotInfo && } {dateGroups.flat()} {!isCurrentUserPremium && isViewportNewest && (