Reaction Picker: Show current reactions (#4822)
This commit is contained in:
parent
eddce446de
commit
a03db12474
@ -38,7 +38,7 @@ export type OwnProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
interface StateProps {
|
interface StateProps {
|
||||||
withCustomReactions?: boolean;
|
shouldUseFullPicker?: boolean;
|
||||||
message?: ApiMessage;
|
message?: ApiMessage;
|
||||||
story?: ApiStory | ApiStorySkipped;
|
story?: ApiStory | ApiStorySkipped;
|
||||||
isCurrentUserPremium?: boolean;
|
isCurrentUserPremium?: boolean;
|
||||||
@ -61,7 +61,7 @@ const ReactionPicker: FC<OwnProps & StateProps> = ({
|
|||||||
position,
|
position,
|
||||||
isTranslucent,
|
isTranslucent,
|
||||||
isCurrentUserPremium,
|
isCurrentUserPremium,
|
||||||
withCustomReactions,
|
shouldUseFullPicker,
|
||||||
sendAsMessage,
|
sendAsMessage,
|
||||||
chatId,
|
chatId,
|
||||||
isForEffects,
|
isForEffects,
|
||||||
@ -91,10 +91,10 @@ const ReactionPicker: FC<OwnProps & StateProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
x: storedPosition.x + (withCustomReactions ? FULL_PICKER_SHIFT_DELTA.x : LIMITED_PICKER_SHIFT_DELTA.x),
|
x: storedPosition.x + (shouldUseFullPicker ? FULL_PICKER_SHIFT_DELTA.x : LIMITED_PICKER_SHIFT_DELTA.x),
|
||||||
y: storedPosition.y + (withCustomReactions ? FULL_PICKER_SHIFT_DELTA.y : LIMITED_PICKER_SHIFT_DELTA.y),
|
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 getMenuElement = useLastCallback(() => menuRef.current);
|
||||||
const getLayout = useLastCallback(() => ({
|
const getLayout = useLastCallback(() => ({
|
||||||
@ -208,7 +208,7 @@ const ReactionPicker: FC<OwnProps & StateProps> = ({
|
|||||||
className={buildClassName(styles.menu, 'ReactionPicker')}
|
className={buildClassName(styles.menu, 'ReactionPicker')}
|
||||||
bubbleClassName={buildClassName(
|
bubbleClassName={buildClassName(
|
||||||
styles.menuContent,
|
styles.menuContent,
|
||||||
!withCustomReactions && !renderedStoryId && styles.onlyReactions,
|
!shouldUseFullPicker && !renderedStoryId && styles.onlyReactions,
|
||||||
renderedStoryId && styles.storyMenu,
|
renderedStoryId && styles.storyMenu,
|
||||||
)}
|
)}
|
||||||
withPortal
|
withPortal
|
||||||
@ -225,7 +225,7 @@ const ReactionPicker: FC<OwnProps & StateProps> = ({
|
|||||||
<StickerPicker
|
<StickerPicker
|
||||||
className=""
|
className=""
|
||||||
isHidden={!isOpen}
|
isHidden={!isOpen}
|
||||||
loadAndPlay={Boolean(isOpen && withCustomReactions)}
|
loadAndPlay={Boolean(isOpen && shouldUseFullPicker)}
|
||||||
idPrefix="message-effect"
|
idPrefix="message-effect"
|
||||||
canSendStickers={false}
|
canSendStickers={false}
|
||||||
noContextMenus={false}
|
noContextMenus={false}
|
||||||
@ -239,21 +239,22 @@ const ReactionPicker: FC<OwnProps & StateProps> = ({
|
|||||||
<CustomEmojiPicker
|
<CustomEmojiPicker
|
||||||
chatId={renderedChatId}
|
chatId={renderedChatId}
|
||||||
idPrefix="message-emoji-set-"
|
idPrefix="message-emoji-set-"
|
||||||
isHidden={!isOpen || !(withCustomReactions || renderedStoryId)}
|
isHidden={!isOpen || !(shouldUseFullPicker || renderedStoryId)}
|
||||||
loadAndPlay={Boolean(isOpen && withCustomReactions)}
|
loadAndPlay={Boolean(isOpen && shouldUseFullPicker)}
|
||||||
isReactionPicker
|
isReactionPicker
|
||||||
className={!withCustomReactions && !renderedStoryId ? styles.hidden : undefined}
|
className={!shouldUseFullPicker && !renderedStoryId ? styles.hidden : undefined}
|
||||||
selectedReactionIds={selectedReactionIds}
|
selectedReactionIds={selectedReactionIds}
|
||||||
isTranslucent={isTranslucent}
|
isTranslucent={isTranslucent}
|
||||||
onCustomEmojiSelect={renderedStoryId ? handleStoryReactionSelect : handleToggleCustomReaction}
|
onCustomEmojiSelect={renderedStoryId ? handleStoryReactionSelect : handleToggleCustomReaction}
|
||||||
onReactionSelect={renderedStoryId ? handleStoryReactionSelect : handleToggleReaction}
|
onReactionSelect={renderedStoryId ? handleStoryReactionSelect : handleToggleReaction}
|
||||||
/>
|
/>
|
||||||
{!withCustomReactions && Boolean(renderedChatId) && (
|
{!shouldUseFullPicker && Boolean(renderedChatId) && (
|
||||||
<ReactionPickerLimited
|
<ReactionPickerLimited
|
||||||
chatId={renderedChatId}
|
chatId={renderedChatId}
|
||||||
loadAndPlay={isOpen}
|
loadAndPlay={isOpen}
|
||||||
onReactionSelect={renderedStoryId ? handleStoryReactionSelect : handleToggleReaction}
|
onReactionSelect={renderedStoryId ? handleStoryReactionSelect : handleToggleReaction}
|
||||||
selectedReactionIds={selectedReactionIds}
|
selectedReactionIds={selectedReactionIds}
|
||||||
|
message={message}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
@ -276,16 +277,20 @@ export default memo(withGlobal<OwnProps>((global): StateProps => {
|
|||||||
const message = chatId && messageId ? selectChatMessage(global, chatId, messageId) : undefined;
|
const message = chatId && messageId ? selectChatMessage(global, chatId, messageId) : undefined;
|
||||||
const isPrivateChat = isUserId(chatId || storyPeerId || '');
|
const isPrivateChat = isUserId(chatId || storyPeerId || '');
|
||||||
const areSomeReactionsAllowed = chatFullInfo?.enabledReactions?.type === 'some';
|
const areSomeReactionsAllowed = chatFullInfo?.enabledReactions?.type === 'some';
|
||||||
const areCustomReactionsAllowed = chatFullInfo?.enabledReactions?.type === 'all'
|
const { maxUniqueReactions } = global.appConfig || {};
|
||||||
&& chatFullInfo?.enabledReactions?.areCustomAllowed;
|
const areAllReactionsAllowed = chatFullInfo?.enabledReactions?.type === 'all'
|
||||||
|
&& chatFullInfo?.enabledReactions?.areCustomAllowed;
|
||||||
|
|
||||||
|
const currentReactions = message?.reactions?.results;
|
||||||
|
const shouldUseCurrentReactions = Boolean(maxUniqueReactions && currentReactions
|
||||||
|
&& currentReactions.length >= maxUniqueReactions);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
message,
|
message,
|
||||||
story,
|
story,
|
||||||
position,
|
position,
|
||||||
withCustomReactions: chat?.isForbidden || areSomeReactionsAllowed
|
shouldUseFullPicker: (chat?.isForbidden || areSomeReactionsAllowed || shouldUseCurrentReactions) ? false
|
||||||
? false
|
: (areAllReactionsAllowed || isPrivateChat),
|
||||||
: areCustomReactionsAllowed || isPrivateChat,
|
|
||||||
isTranslucent: selectIsContextMenuTranslucent(global),
|
isTranslucent: selectIsContextMenuTranslucent(global),
|
||||||
isCurrentUserPremium: selectIsCurrentUserPremium(global),
|
isCurrentUserPremium: selectIsCurrentUserPremium(global),
|
||||||
sendAsMessage,
|
sendAsMessage,
|
||||||
|
|||||||
@ -1,10 +1,18 @@
|
|||||||
import type { FC } from '../../../../lib/teact/teact';
|
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 { 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 { selectChatFullInfo } from '../../../../global/selectors';
|
||||||
import buildClassName from '../../../../util/buildClassName';
|
import buildClassName from '../../../../util/buildClassName';
|
||||||
import { REM } from '../../../common/helpers/mediaDimensions';
|
import { REM } from '../../../common/helpers/mediaDimensions';
|
||||||
@ -21,6 +29,7 @@ type OwnProps = {
|
|||||||
loadAndPlay: boolean;
|
loadAndPlay: boolean;
|
||||||
onReactionSelect?: (reaction: ApiReaction) => void;
|
onReactionSelect?: (reaction: ApiReaction) => void;
|
||||||
selectedReactionIds?: string[];
|
selectedReactionIds?: string[];
|
||||||
|
message?: ApiMessage;
|
||||||
};
|
};
|
||||||
|
|
||||||
type StateProps = {
|
type StateProps = {
|
||||||
@ -29,6 +38,7 @@ type StateProps = {
|
|||||||
topReactions: ApiReaction[];
|
topReactions: ApiReaction[];
|
||||||
canAnimate?: boolean;
|
canAnimate?: boolean;
|
||||||
isSavedMessages?: boolean;
|
isSavedMessages?: boolean;
|
||||||
|
reactionsLimit?: number;
|
||||||
isCurrentUserPremium?: boolean;
|
isCurrentUserPremium?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -47,6 +57,8 @@ const ReactionPickerLimited: FC<OwnProps & StateProps> = ({
|
|||||||
topReactions,
|
topReactions,
|
||||||
selectedReactionIds,
|
selectedReactionIds,
|
||||||
onReactionSelect,
|
onReactionSelect,
|
||||||
|
message,
|
||||||
|
reactionsLimit,
|
||||||
}) => {
|
}) => {
|
||||||
// eslint-disable-next-line no-null/no-null
|
// eslint-disable-next-line no-null/no-null
|
||||||
const sharedCanvasRef = useRef<HTMLCanvasElement>(null);
|
const sharedCanvasRef = useRef<HTMLCanvasElement>(null);
|
||||||
@ -55,7 +67,15 @@ const ReactionPickerLimited: FC<OwnProps & StateProps> = ({
|
|||||||
const { width: windowWidth } = useWindowSize();
|
const { width: windowWidth } = useWindowSize();
|
||||||
const { isTouchScreen } = useAppLayout();
|
const { isTouchScreen } = useAppLayout();
|
||||||
|
|
||||||
|
const currentReactions = message?.reactions?.results;
|
||||||
|
|
||||||
|
const shouldUseCurrentReactions = reactionsLimit && currentReactions
|
||||||
|
&& currentReactions.length >= reactionsLimit;
|
||||||
|
|
||||||
const allAvailableReactions = useMemo(() => {
|
const allAvailableReactions = useMemo(() => {
|
||||||
|
if (shouldUseCurrentReactions) {
|
||||||
|
return currentReactions.map(({ reaction }) => reaction);
|
||||||
|
}
|
||||||
if (!enabledReactions) {
|
if (!enabledReactions) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@ -65,7 +85,7 @@ const ReactionPickerLimited: FC<OwnProps & StateProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
return sortReactions(enabledReactions.allowed, topReactions);
|
return sortReactions(enabledReactions.allowed, topReactions);
|
||||||
}, [availableReactions, enabledReactions, topReactions]);
|
}, [availableReactions, enabledReactions, topReactions, shouldUseCurrentReactions, currentReactions]);
|
||||||
|
|
||||||
const pickerHeight = useMemo(() => {
|
const pickerHeight = useMemo(() => {
|
||||||
const pickerWidth = Math.min(MODAL_MAX_WIDTH_REM * REM, windowWidth);
|
const pickerWidth = Math.min(MODAL_MAX_WIDTH_REM * REM, windowWidth);
|
||||||
@ -112,12 +132,15 @@ const ReactionPickerLimited: FC<OwnProps & StateProps> = ({
|
|||||||
export default memo(withGlobal<OwnProps>(
|
export default memo(withGlobal<OwnProps>(
|
||||||
(global, { chatId }): StateProps => {
|
(global, { chatId }): StateProps => {
|
||||||
const { availableReactions, topReactions } = global.reactions;
|
const { availableReactions, topReactions } = global.reactions;
|
||||||
|
|
||||||
|
const { maxUniqueReactions } = global.appConfig || {};
|
||||||
const { enabledReactions } = selectChatFullInfo(global, chatId) || {};
|
const { enabledReactions } = selectChatFullInfo(global, chatId) || {};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
enabledReactions,
|
enabledReactions,
|
||||||
availableReactions,
|
availableReactions,
|
||||||
topReactions,
|
topReactions,
|
||||||
|
reactionsLimit: maxUniqueReactions,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
)(ReactionPickerLimited));
|
)(ReactionPickerLimited));
|
||||||
|
|||||||
@ -75,10 +75,17 @@ const ReactionSelector: FC<OwnProps> = ({
|
|||||||
|
|
||||||
const areReactionsLocked = isInSavedMessages && !isCurrentUserPremium && !isInStoryViewer;
|
const areReactionsLocked = isInSavedMessages && !isCurrentUserPremium && !isInStoryViewer;
|
||||||
|
|
||||||
|
const shouldUseCurrentReactions = Boolean(maxUniqueReactions
|
||||||
|
&& currentReactions && currentReactions.length >= maxUniqueReactions);
|
||||||
|
|
||||||
const availableReactions = useMemo(() => {
|
const availableReactions = useMemo(() => {
|
||||||
const reactions = isForEffects ? effectReactions : isInSavedMessages ? defaultTagReactions
|
const reactions = (() => {
|
||||||
: (enabledReactions?.type === 'some' ? enabledReactions.allowed
|
if (shouldUseCurrentReactions) return currentReactions?.map((reaction) => reaction.reaction);
|
||||||
: allAvailableReactions?.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 filteredReactions = reactions?.map((reaction) => {
|
||||||
const isCustomReaction = 'documentId' in reaction;
|
const isCustomReaction = 'documentId' in reaction;
|
||||||
const availableReaction = allAvailableReactions?.find((r) => isSameReaction(r.reaction, reaction));
|
const availableReaction = allAvailableReactions?.find((r) => isSameReaction(r.reaction, reaction));
|
||||||
@ -87,12 +94,8 @@ const ReactionSelector: FC<OwnProps> = ({
|
|||||||
|
|
||||||
if ((!isCustomReaction && !availableReaction) || availableReaction?.isInactive) return undefined;
|
if ((!isCustomReaction && !availableReaction) || availableReaction?.isInactive) return undefined;
|
||||||
|
|
||||||
if (!isPrivate && (!enabledReactions || !canSendReaction(reaction, enabledReactions))) {
|
if (!isPrivate && !shouldUseCurrentReactions
|
||||||
return undefined;
|
&& (!enabledReactions || !canSendReaction(reaction, enabledReactions))) {
|
||||||
}
|
|
||||||
|
|
||||||
if (maxUniqueReactions && currentReactions && currentReactions.length >= maxUniqueReactions
|
|
||||||
&& !currentReactions.some(({ reaction: currentReaction }) => isSameReaction(reaction, currentReaction))) {
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +105,7 @@ const ReactionSelector: FC<OwnProps> = ({
|
|||||||
return sortReactions(filteredReactions, topReactions);
|
return sortReactions(filteredReactions, topReactions);
|
||||||
}, [
|
}, [
|
||||||
allAvailableReactions, currentReactions, defaultTagReactions, enabledReactions, isInSavedMessages, isPrivate,
|
allAvailableReactions, currentReactions, defaultTagReactions, enabledReactions, isInSavedMessages, isPrivate,
|
||||||
maxUniqueReactions, topReactions, isForEffects, effectReactions,
|
topReactions, isForEffects, effectReactions, shouldUseCurrentReactions,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const reactionsToRender = useMemo(() => {
|
const reactionsToRender = useMemo(() => {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user