diff --git a/src/components/middle/message/reactions/ReactionPicker.tsx b/src/components/middle/message/reactions/ReactionPicker.tsx index 3ab0b83b0..2aff2e8d9 100644 --- a/src/components/middle/message/reactions/ReactionPicker.tsx +++ b/src/components/middle/message/reactions/ReactionPicker.tsx @@ -38,7 +38,7 @@ export type OwnProps = { }; interface StateProps { - withCustomReactions?: boolean; + shouldUseFullPicker?: boolean; message?: ApiMessage; story?: ApiStory | ApiStorySkipped; isCurrentUserPremium?: boolean; @@ -61,7 +61,7 @@ const ReactionPicker: FC = ({ position, isTranslucent, isCurrentUserPremium, - withCustomReactions, + shouldUseFullPicker, sendAsMessage, chatId, isForEffects, @@ -91,10 +91,10 @@ const ReactionPicker: FC = ({ } return { - x: storedPosition.x + (withCustomReactions ? FULL_PICKER_SHIFT_DELTA.x : LIMITED_PICKER_SHIFT_DELTA.x), - y: storedPosition.y + (withCustomReactions ? FULL_PICKER_SHIFT_DELTA.y : LIMITED_PICKER_SHIFT_DELTA.y), + x: storedPosition.x + (shouldUseFullPicker ? FULL_PICKER_SHIFT_DELTA.x : LIMITED_PICKER_SHIFT_DELTA.x), + y: storedPosition.y + (shouldUseFullPicker ? FULL_PICKER_SHIFT_DELTA.y : LIMITED_PICKER_SHIFT_DELTA.y), }; - }, [renderedStoryId, storedPosition, withCustomReactions]); + }, [renderedStoryId, storedPosition, shouldUseFullPicker]); const getMenuElement = useLastCallback(() => menuRef.current); const getLayout = useLastCallback(() => ({ @@ -208,7 +208,7 @@ const ReactionPicker: FC = ({ className={buildClassName(styles.menu, 'ReactionPicker')} bubbleClassName={buildClassName( styles.menuContent, - !withCustomReactions && !renderedStoryId && styles.onlyReactions, + !shouldUseFullPicker && !renderedStoryId && styles.onlyReactions, renderedStoryId && styles.storyMenu, )} withPortal @@ -225,7 +225,7 @@ const ReactionPicker: FC = ({ = ({ - {!withCustomReactions && Boolean(renderedChatId) && ( + {!shouldUseFullPicker && Boolean(renderedChatId) && ( )} @@ -276,16 +277,20 @@ export default memo(withGlobal((global): StateProps => { const message = chatId && messageId ? selectChatMessage(global, chatId, messageId) : undefined; const isPrivateChat = isUserId(chatId || storyPeerId || ''); const areSomeReactionsAllowed = chatFullInfo?.enabledReactions?.type === 'some'; - const areCustomReactionsAllowed = chatFullInfo?.enabledReactions?.type === 'all' - && chatFullInfo?.enabledReactions?.areCustomAllowed; + const { maxUniqueReactions } = global.appConfig || {}; + const areAllReactionsAllowed = chatFullInfo?.enabledReactions?.type === 'all' + && chatFullInfo?.enabledReactions?.areCustomAllowed; + + const currentReactions = message?.reactions?.results; + const shouldUseCurrentReactions = Boolean(maxUniqueReactions && currentReactions + && currentReactions.length >= maxUniqueReactions); return { message, story, position, - withCustomReactions: chat?.isForbidden || areSomeReactionsAllowed - ? false - : areCustomReactionsAllowed || isPrivateChat, + shouldUseFullPicker: (chat?.isForbidden || areSomeReactionsAllowed || shouldUseCurrentReactions) ? false + : (areAllReactionsAllowed || isPrivateChat), isTranslucent: selectIsContextMenuTranslucent(global), isCurrentUserPremium: selectIsCurrentUserPremium(global), sendAsMessage, diff --git a/src/components/middle/message/reactions/ReactionPickerLimited.tsx b/src/components/middle/message/reactions/ReactionPickerLimited.tsx index 68e68deea..45f97ced4 100644 --- a/src/components/middle/message/reactions/ReactionPickerLimited.tsx +++ b/src/components/middle/message/reactions/ReactionPickerLimited.tsx @@ -1,10 +1,18 @@ import type { FC } from '../../../../lib/teact/teact'; -import React, { memo, useMemo, useRef } from '../../../../lib/teact/teact'; +import React, { + memo, + useMemo, useRef, +} from '../../../../lib/teact/teact'; import { withGlobal } from '../../../../global'; -import type { ApiAvailableReaction, ApiChatReactions, ApiReaction } from '../../../../api/types'; +import type { + ApiAvailableReaction, ApiChatReactions, ApiMessage, + ApiReaction, +} from '../../../../api/types'; -import { getReactionKey, sortReactions } from '../../../../global/helpers'; +import { + getReactionKey, sortReactions, +} from '../../../../global/helpers'; import { selectChatFullInfo } from '../../../../global/selectors'; import buildClassName from '../../../../util/buildClassName'; import { REM } from '../../../common/helpers/mediaDimensions'; @@ -21,6 +29,7 @@ type OwnProps = { loadAndPlay: boolean; onReactionSelect?: (reaction: ApiReaction) => void; selectedReactionIds?: string[]; + message?: ApiMessage; }; type StateProps = { @@ -29,6 +38,7 @@ type StateProps = { topReactions: ApiReaction[]; canAnimate?: boolean; isSavedMessages?: boolean; + reactionsLimit?: number; isCurrentUserPremium?: boolean; }; @@ -47,6 +57,8 @@ const ReactionPickerLimited: FC = ({ topReactions, selectedReactionIds, onReactionSelect, + message, + reactionsLimit, }) => { // eslint-disable-next-line no-null/no-null const sharedCanvasRef = useRef(null); @@ -55,7 +67,15 @@ const ReactionPickerLimited: FC = ({ const { width: windowWidth } = useWindowSize(); const { isTouchScreen } = useAppLayout(); + const currentReactions = message?.reactions?.results; + + const shouldUseCurrentReactions = reactionsLimit && currentReactions + && currentReactions.length >= reactionsLimit; + const allAvailableReactions = useMemo(() => { + if (shouldUseCurrentReactions) { + return currentReactions.map(({ reaction }) => reaction); + } if (!enabledReactions) { return []; } @@ -65,7 +85,7 @@ const ReactionPickerLimited: FC = ({ } return sortReactions(enabledReactions.allowed, topReactions); - }, [availableReactions, enabledReactions, topReactions]); + }, [availableReactions, enabledReactions, topReactions, shouldUseCurrentReactions, currentReactions]); const pickerHeight = useMemo(() => { const pickerWidth = Math.min(MODAL_MAX_WIDTH_REM * REM, windowWidth); @@ -112,12 +132,15 @@ const ReactionPickerLimited: FC = ({ export default memo(withGlobal( (global, { chatId }): StateProps => { const { availableReactions, topReactions } = global.reactions; + + const { maxUniqueReactions } = global.appConfig || {}; const { enabledReactions } = selectChatFullInfo(global, chatId) || {}; return { enabledReactions, availableReactions, topReactions, + reactionsLimit: maxUniqueReactions, }; }, )(ReactionPickerLimited)); diff --git a/src/components/middle/message/reactions/ReactionSelector.tsx b/src/components/middle/message/reactions/ReactionSelector.tsx index c0c539fb1..40580b723 100644 --- a/src/components/middle/message/reactions/ReactionSelector.tsx +++ b/src/components/middle/message/reactions/ReactionSelector.tsx @@ -75,10 +75,17 @@ const ReactionSelector: FC = ({ const areReactionsLocked = isInSavedMessages && !isCurrentUserPremium && !isInStoryViewer; + const shouldUseCurrentReactions = Boolean(maxUniqueReactions + && currentReactions && currentReactions.length >= maxUniqueReactions); + const availableReactions = useMemo(() => { - const reactions = isForEffects ? effectReactions : isInSavedMessages ? defaultTagReactions - : (enabledReactions?.type === 'some' ? enabledReactions.allowed - : allAvailableReactions?.map((reaction) => reaction.reaction)); + const reactions = (() => { + if (shouldUseCurrentReactions) return currentReactions?.map((reaction) => reaction.reaction); + if (isForEffects) return effectReactions; + if (isInSavedMessages) return defaultTagReactions; + if (enabledReactions?.type === 'some') return enabledReactions.allowed; + return allAvailableReactions?.map((reaction) => reaction.reaction); + })(); const filteredReactions = reactions?.map((reaction) => { const isCustomReaction = 'documentId' in reaction; const availableReaction = allAvailableReactions?.find((r) => isSameReaction(r.reaction, reaction)); @@ -87,12 +94,8 @@ const ReactionSelector: FC = ({ if ((!isCustomReaction && !availableReaction) || availableReaction?.isInactive) return undefined; - if (!isPrivate && (!enabledReactions || !canSendReaction(reaction, enabledReactions))) { - return undefined; - } - - if (maxUniqueReactions && currentReactions && currentReactions.length >= maxUniqueReactions - && !currentReactions.some(({ reaction: currentReaction }) => isSameReaction(reaction, currentReaction))) { + if (!isPrivate && !shouldUseCurrentReactions + && (!enabledReactions || !canSendReaction(reaction, enabledReactions))) { return undefined; } @@ -102,7 +105,7 @@ const ReactionSelector: FC = ({ return sortReactions(filteredReactions, topReactions); }, [ allAvailableReactions, currentReactions, defaultTagReactions, enabledReactions, isInSavedMessages, isPrivate, - maxUniqueReactions, topReactions, isForEffects, effectReactions, + topReactions, isForEffects, effectReactions, shouldUseCurrentReactions, ]); const reactionsToRender = useMemo(() => {