diff --git a/src/components/middle/MessageList.tsx b/src/components/middle/MessageList.tsx index 3736f4144..ad9c6ae1b 100644 --- a/src/components/middle/MessageList.tsx +++ b/src/components/middle/MessageList.tsx @@ -261,7 +261,7 @@ const MessageList: FC = ({ } const { shouldAppendJoinMessage, shouldAppendJoinMessageAfterCurrent } = (() => { - if (!channelJoinInfo) return undefined; + if (!channelJoinInfo || type !== 'thread') return undefined; if (prevMessage && prevMessage.date < channelJoinInfo.joinedDate && channelJoinInfo.joinedDate <= message.date) { return { shouldAppendJoinMessage: true, shouldAppendJoinMessageAfterCurrent: false }; diff --git a/src/components/middle/message/SimilarChannels.tsx b/src/components/middle/message/SimilarChannels.tsx index d590246f5..479b7d8f1 100644 --- a/src/components/middle/message/SimilarChannels.tsx +++ b/src/components/middle/message/SimilarChannels.tsx @@ -3,14 +3,16 @@ import React, { } from '../../../lib/teact/teact'; import { getActions, getGlobal, withGlobal } from '../../../global'; -import type { ApiChat } from '../../../api/types'; +import type { ApiChat, ApiChatFullInfo } from '../../../api/types'; import { selectChat, + selectChatFullInfo, selectIsCurrentUserPremium, selectSimilarChannelIds, } from '../../../global/selectors'; import buildClassName from '../../../util/buildClassName'; +import { getServerTime } from '../../../util/serverTime'; import { formatIntegerCompact } from '../../../util/textFormat'; import useTimeout from '../../../hooks/schedulers/useTimeout'; @@ -31,6 +33,7 @@ const DEFAULT_BADGE_COLOR = '#3C3C4399'; const SHOW_CHANNELS_NUMBER = 10; const MIN_SKELETON_DELAY = 300; const MAX_SKELETON_DELAY = 2000; +const AUTO_EXPAND_TIME = 10; // Seconds from joining type OwnProps = { chatId: string; @@ -38,17 +41,19 @@ type OwnProps = { type StateProps = { similarChannelIds?: string[]; - shouldShowInChat?: boolean; - count: number; + isExpanded?: boolean; + count?: number; isCurrentUserPremium: boolean; + channelJoinInfo?: ApiChatFullInfo['joinInfo']; }; const SimilarChannels = ({ chatId, similarChannelIds, - shouldShowInChat, + isExpanded, count, isCurrentUserPremium, + channelJoinInfo, }: StateProps & OwnProps) => { const lang = useOldLang(); const { toggleChannelRecommendations, loadChannelRecommendations } = getActions(); @@ -65,49 +70,58 @@ const SimilarChannels = ({ return similarChannelIds.map((id) => selectChat(global, id)).filter(Boolean); }, [similarChannelIds]); // Show skeleton while loading similar channels - const [shoulRenderSkeleton, setShoulRenderSkeleton] = useState(!similarChannelIds); + const [shouldRenderSkeleton, setShouldRenderSkeleton] = useState(false); const firstSimilarChannels = useMemo(() => similarChannels?.slice(0, SHOW_CHANNELS_NUMBER), [similarChannels]); const areSimilarChannelsPresent = Boolean(firstSimilarChannels?.length); - useHorizontalScroll(ref, !areSimilarChannelsPresent || !shouldShowInChat || shoulRenderSkeleton, true); const isAnimating = isHiding || isShowing; const shouldRenderChannels = Boolean( - !shoulRenderSkeleton - && (shouldShowInChat || isAnimating) + !shouldRenderSkeleton + && (isExpanded || isAnimating) && areSimilarChannelsPresent, ); + useHorizontalScroll(ref, !shouldRenderChannels, true); + useEffect(() => { if (!similarChannelIds) { loadChannelRecommendations({ chatId }); } }, [chatId, similarChannelIds]); - useTimeout(() => setShoulRenderSkeleton(false), MAX_SKELETON_DELAY); + useTimeout(() => setShouldRenderSkeleton(false), MAX_SKELETON_DELAY); useEffect(() => { - if (shoulRenderSkeleton && similarChannels && shouldShowInChat) { + if (shouldRenderSkeleton && similarChannels && isExpanded) { const id = setTimeout(() => { - setShoulRenderSkeleton(false); + setShouldRenderSkeleton(false); }, MIN_SKELETON_DELAY); return () => clearTimeout(id); } return undefined; - }, [similarChannels, shouldShowInChat, shoulRenderSkeleton]); + }, [similarChannels, isExpanded, shouldRenderSkeleton]); const handleToggle = useLastCallback(() => { toggleChannelRecommendations({ chatId }); - if (shouldShowInChat) { + if (isExpanded) { markNotShowing(); markHiding(); } else { markShowing(); markNotHiding(); + setShouldRenderSkeleton(!similarChannelIds); } }); + useEffect(() => { + if (!channelJoinInfo?.joinedDate || isExpanded) return; + if (getServerTime() - channelJoinInfo.joinedDate <= AUTO_EXPAND_TIME) { + handleToggle(); + } + }, [channelJoinInfo, isExpanded]); + return (
@@ -118,7 +132,7 @@ const SimilarChannels = ({ {lang('ChannelJoined')}
- {shoulRenderSkeleton && } + {shouldRenderSkeleton && } {shouldRenderChannels && (
) : ( @@ -239,14 +253,16 @@ function MoreChannels({ export default memo( withGlobal((global, { chatId }): StateProps => { - const { similarChannelIds, shouldShowInChat, count } = selectSimilarChannelIds(global, chatId) || {}; + const { similarChannelIds, isExpanded, count } = selectSimilarChannelIds(global, chatId) || {}; const isCurrentUserPremium = selectIsCurrentUserPremium(global); + const chatFullInfo = selectChatFullInfo(global, chatId); return { similarChannelIds, - shouldShowInChat, + isExpanded, count, isCurrentUserPremium, + channelJoinInfo: chatFullInfo?.joinInfo, }; })(SimilarChannels), ); diff --git a/src/global/actions/api/chats.ts b/src/global/actions/api/chats.ts index 800ea28a2..2c0bcb8bd 100644 --- a/src/global/actions/api/chats.ts +++ b/src/global/actions/api/chats.ts @@ -61,7 +61,6 @@ import { addChats, addMessages, addSimilarBots, - addSimilarChannels, addUsers, addUserStatuses, deleteChatMessages, @@ -73,6 +72,7 @@ import { replaceChatListIds, replaceChatListLoadingParameters, replaceMessages, + replaceSimilarChannels, replaceThreadParam, replaceUserStatuses, toggleSimilarChannels, @@ -2691,7 +2691,7 @@ addActionHandler('loadChannelRecommendations', async (global, actions, payload): const chatsById = buildCollectionByKey(similarChannels, 'id'); global = getGlobal(); - global = addSimilarChannels(global, chatId || GLOBAL_SUGGESTED_CHANNELS_ID, Object.keys(chatsById), count); + global = replaceSimilarChannels(global, chatId || GLOBAL_SUGGESTED_CHANNELS_ID, Object.keys(chatsById), count); setGlobal(global); }); diff --git a/src/global/reducers/chats.ts b/src/global/reducers/chats.ts index 63a5baf93..0bd785141 100644 --- a/src/global/reducers/chats.ts +++ b/src/global/reducers/chats.ts @@ -420,12 +420,11 @@ export function addChatMembers(global: T, chat: ApiChat, }); } -export function addSimilarChannels( +export function replaceSimilarChannels( global: T, chatId: string, similarChannelIds: string[], count?: number, - shouldShowInChat = true, ) { return { ...global, @@ -436,7 +435,6 @@ export function addSimilarChannels( [chatId]: { similarChannelIds, count: count || similarChannelIds.length, - shouldShowInChat, }, }, }, @@ -457,7 +455,7 @@ export function toggleSimilarChannels( ...global.chats.similarChannelsById, [chatId]: { ...similarChannels, - shouldShowInChat: !similarChannels.shouldShowInChat, + isExpanded: !similarChannels?.isExpanded, }, }, }, diff --git a/src/global/types/globalState.ts b/src/global/types/globalState.ts index 00651edaf..e772eadce 100644 --- a/src/global/types/globalState.ts +++ b/src/global/types/globalState.ts @@ -215,14 +215,11 @@ export type GlobalState = { forDiscussionIds?: string[]; // Obtained from GetFullChat / GetFullChannel fullInfoById: Record; - similarChannelsById: Record< - string, - { - shouldShowInChat: boolean; - similarChannelIds: string[]; - count: number; - } - >; + similarChannelsById: Partial>; similarBotsById: Record; };