Composer Embedded Message: Suppress animation on chat open (#4594)

This commit is contained in:
Alexander Zinchuk 2024-06-12 18:10:39 +02:00
parent c04014b7a1
commit 7954bd9c28
9 changed files with 48 additions and 29 deletions

View File

@ -409,7 +409,6 @@ export interface ApiInputMessageReplyInfo {
replyToTopId?: number; replyToTopId?: number;
replyToPeerId?: string; replyToPeerId?: string;
quoteText?: ApiFormattedText; quoteText?: ApiFormattedText;
isShowingDelayNeeded?: boolean;
} }
export interface ApiInputStoryReplyInfo { export interface ApiInputStoryReplyInfo {

View File

@ -1649,6 +1649,9 @@ const Composer: FC<OwnProps & StateProps> = ({
<ComposerEmbeddedMessage <ComposerEmbeddedMessage
onClear={handleEmbeddedClear} onClear={handleEmbeddedClear}
shouldForceShowEditing={Boolean(shouldForceShowEditing && editingMessage)} shouldForceShowEditing={Boolean(shouldForceShowEditing && editingMessage)}
chatId={chatId}
threadId={threadId}
messageListType={messageListType}
/> />
<WebPagePreview <WebPagePreview
chatId={chatId} chatId={chatId}

View File

@ -7,13 +7,14 @@ import { getActions, withGlobal } from '../../../global';
import type { import type {
ApiChat, ApiInputMessageReplyInfo, ApiMessage, ApiPeer, ApiChat, ApiInputMessageReplyInfo, ApiMessage, ApiPeer,
} from '../../../api/types'; } from '../../../api/types';
import type { MessageListType } from '../../../global/types';
import type { ThreadId } from '../../../types/index';
import { stripCustomEmoji } from '../../../global/helpers'; import { stripCustomEmoji } from '../../../global/helpers';
import { import {
selectCanAnimateInterface, selectCanAnimateInterface,
selectChat, selectChat,
selectChatMessage, selectChatMessage,
selectCurrentMessageList,
selectDraft, selectDraft,
selectEditingId, selectEditingId,
selectEditingMessage, selectEditingMessage,
@ -35,7 +36,6 @@ import useLang from '../../../hooks/useLang';
import useLastCallback from '../../../hooks/useLastCallback'; import useLastCallback from '../../../hooks/useLastCallback';
import useMenuPosition from '../../../hooks/useMenuPosition'; import useMenuPosition from '../../../hooks/useMenuPosition';
import useShowTransition from '../../../hooks/useShowTransition'; import useShowTransition from '../../../hooks/useShowTransition';
import useAsyncRendering from '../../right/hooks/useAsyncRendering';
import { ClosableEmbeddedMessage } from '../../common/embedded/EmbeddedMessage'; import { ClosableEmbeddedMessage } from '../../common/embedded/EmbeddedMessage';
import Icon from '../../common/Icon'; import Icon from '../../common/Icon';
@ -60,16 +60,19 @@ type StateProps = {
isContextMenuDisabled?: boolean; isContextMenuDisabled?: boolean;
isReplyToDiscussion?: boolean; isReplyToDiscussion?: boolean;
isInChangingRecipientMode?: boolean; isInChangingRecipientMode?: boolean;
isChangingChats?: boolean; shouldPreventComposerAnimation?: boolean;
senderChat?: ApiChat; senderChat?: ApiChat;
}; };
type OwnProps = { type OwnProps = {
onClear?: () => void; onClear?: () => void;
shouldForceShowEditing?: boolean; shouldForceShowEditing?: boolean;
chatId: string;
threadId: ThreadId;
messageListType: MessageListType;
}; };
const FORWARD_RENDERING_DELAY = 300; const CLOSE_DURATION = 350;
const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
replyInfo, replyInfo,
@ -87,7 +90,7 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
isReplyToDiscussion, isReplyToDiscussion,
onClear, onClear,
isInChangingRecipientMode, isInChangingRecipientMode,
isChangingChats, shouldPreventComposerAnimation,
senderChat, senderChat,
}) => { }) => {
const { const {
@ -99,6 +102,7 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
setForwardNoAuthors, setForwardNoAuthors,
setForwardNoCaptions, setForwardNoCaptions,
exitForwardMode, exitForwardMode,
setShouldPreventComposerAnimation,
} = getActions(); } = getActions();
// eslint-disable-next-line no-null/no-null // eslint-disable-next-line no-null/no-null
const ref = useRef<HTMLDivElement>(null); const ref = useRef<HTMLDivElement>(null);
@ -109,27 +113,28 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
const isReplyWithQuote = Boolean(replyInfo?.quoteText); const isReplyWithQuote = Boolean(replyInfo?.quoteText);
const isForwarding = Boolean(forwardedMessagesCount); const isForwarding = Boolean(forwardedMessagesCount);
const isShown = Boolean(
((replyInfo || editingId) && message && !isInChangingRecipientMode) const isShown = (() => {
|| (sender && forwardedMessagesCount), if (isInChangingRecipientMode) return false;
); if (sender && isForwarding) return true;
const canAnimate = useAsyncRendering( if (message && (replyInfo || editingId)) return true;
[isShown, isForwarding], return false;
isShown && isChangingChats ? FORWARD_RENDERING_DELAY : undefined, })();
);
const { const {
shouldRender, transitionClassNames, shouldRender, transitionClassNames,
} = useShowTransition( } = useShowTransition(
canAnimate && isShown && !isReplyToTopicStart && !isReplyToDiscussion, isShown && !isReplyToTopicStart && !isReplyToDiscussion,
undefined, undefined,
!shouldAnimate, !shouldAnimate,
undefined, undefined,
!shouldAnimate, !shouldAnimate,
CLOSE_DURATION,
!shouldAnimate,
); );
useEffect(() => { useEffect(() => {
if (canAnimate && replyInfo?.isShowingDelayNeeded) { if (shouldPreventComposerAnimation) {
updateDraftReplyInfo({ isShowingDelayNeeded: false }); setShouldPreventComposerAnimation({ shouldPreventComposerAnimation: false });
} }
}); });
@ -370,22 +375,20 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
}; };
export default memo(withGlobal<OwnProps>( export default memo(withGlobal<OwnProps>(
(global, { shouldForceShowEditing }): StateProps => { (global, {
const { chatId, threadId, type: messageListType } = selectCurrentMessageList(global) || {}; shouldForceShowEditing, chatId, threadId, messageListType,
if (!chatId || !threadId || !messageListType) { }): StateProps => {
return {};
}
const { const {
forwardMessages: { forwardMessages: {
fromChatId, toChatId, messageIds: forwardMessageIds, noAuthors, noCaptions, isModalShown, fromChatId, toChatId, messageIds: forwardMessageIds, noAuthors, noCaptions, isModalShown,
}, },
shouldPreventComposerAnimation,
} = selectTabState(global); } = selectTabState(global);
const editingId = messageListType === 'scheduled' const editingId = messageListType === 'scheduled'
? selectEditingScheduledId(global, chatId) ? selectEditingScheduledId(global, chatId)
: selectEditingId(global, chatId, threadId); : selectEditingId(global, chatId, threadId);
const shouldAnimate = selectCanAnimateInterface(global); const shouldAnimate = selectCanAnimateInterface(global) && !shouldPreventComposerAnimation;
const isForwarding = toChatId === chatId; const isForwarding = toChatId === chatId;
const forwardedMessages = forwardMessageIds?.map((id) => selectChatMessage(global, fromChatId!, id)!); const forwardedMessages = forwardMessageIds?.map((id) => selectChatMessage(global, fromChatId!, id)!);
@ -394,7 +397,6 @@ export default memo(withGlobal<OwnProps>(
const replyToPeerId = replyInfo?.replyToPeerId; const replyToPeerId = replyInfo?.replyToPeerId;
const senderChat = replyToPeerId ? selectChat(global, replyToPeerId) : undefined; const senderChat = replyToPeerId ? selectChat(global, replyToPeerId) : undefined;
const isChangingChats = isForwarding || replyInfo?.isShowingDelayNeeded;
let message: ApiMessage | undefined; let message: ApiMessage | undefined;
if (replyInfo && !shouldForceShowEditing) { if (replyInfo && !shouldForceShowEditing) {
message = selectChatMessage(global, replyInfo.replyToPeerId || chatId, replyInfo.replyToMsgId); message = selectChatMessage(global, replyInfo.replyToPeerId || chatId, replyInfo.replyToMsgId);
@ -452,7 +454,7 @@ export default memo(withGlobal<OwnProps>(
isContextMenuDisabled, isContextMenuDisabled,
isReplyToDiscussion, isReplyToDiscussion,
isInChangingRecipientMode: isModalShown, isInChangingRecipientMode: isModalShown,
isChangingChats, shouldPreventComposerAnimation,
senderChat, senderChat,
}; };
}, },

View File

@ -361,6 +361,7 @@ const ContextMenuContainer: FC<OwnProps & StateProps> = ({
updateDraftReplyInfo({ updateDraftReplyInfo({
replyToMsgId: message.id, replyToMsgId: message.id,
quoteText: canQuoteSelection && selectionRange ? getSelectionAsFormattedText(selectionRange) : undefined, quoteText: canQuoteSelection && selectionRange ? getSelectionAsFormattedText(selectionRange) : undefined,
replyToPeerId: undefined,
}); });
closeMenu(); closeMenu();
}); });

View File

@ -138,7 +138,7 @@ export default function useOuterHandlers(
function handleContainerDoubleClick() { function handleContainerDoubleClick() {
if (IS_TOUCH_ENV || !canReply) return; if (IS_TOUCH_ENV || !canReply) return;
updateDraftReplyInfo({ replyToMsgId: messageId }); updateDraftReplyInfo({ replyToMsgId: messageId, replyToPeerId: undefined, quoteText: undefined });
} }
function stopPropagation(e: React.MouseEvent<HTMLDivElement, MouseEvent>) { function stopPropagation(e: React.MouseEvent<HTMLDivElement, MouseEvent>) {

View File

@ -1831,7 +1831,6 @@ addActionHandler('openChatOrTopicWithReplyInDraft', (global, actions, payload):
...currentReplyInfo, ...currentReplyInfo,
replyToPeerId, replyToPeerId,
type: 'message', type: 'message',
isShowingDelayNeeded: true,
}; };
moveReplyToNewDraft(global, threadId, newReply, toChatId); moveReplyToNewDraft(global, threadId, newReply, toChatId);

View File

@ -47,6 +47,7 @@ addActionHandler('processOpenChatOrThread', (global, actions, payload): ActionRe
global = updateTabState(global, { global = updateTabState(global, {
activeReactions: {}, activeReactions: {},
shouldPreventComposerAnimation: true,
}, tabId); }, tabId);
} }

View File

@ -162,7 +162,9 @@ addActionHandler('replyToNextMessage', (global, actions, payload): ActionReturnT
? Number(chatMessageKeys[newIndex]) ? Number(chatMessageKeys[newIndex])
: undefined; : undefined;
} }
actions.updateDraftReplyInfo({ replyToMsgId: messageId, tabId }); actions.updateDraftReplyInfo({
replyToMsgId: messageId, replyToPeerId: undefined, quoteText: undefined, tabId,
});
actions.focusMessage({ actions.focusMessage({
chatId, chatId,
threadId, threadId,
@ -496,6 +498,13 @@ addActionHandler('focusMessage', (global, actions, payload): ActionReturnType =>
return undefined; return undefined;
}); });
addActionHandler('setShouldPreventComposerAnimation', (global, actions, payload): ActionReturnType => {
const { shouldPreventComposerAnimation, tabId = getCurrentTabId() } = payload;
return updateTabState(global, {
shouldPreventComposerAnimation,
}, tabId);
});
addActionHandler('openForwardMenu', (global, actions, payload): ActionReturnType => { addActionHandler('openForwardMenu', (global, actions, payload): ActionReturnType => {
const { const {
fromChatId, messageIds, storyId, groupedId, withMyScore, tabId = getCurrentTabId(), fromChatId, messageIds, storyId, groupedId, withMyScore, tabId = getCurrentTabId(),

View File

@ -229,6 +229,7 @@ export type TabState = {
isBlurred?: boolean; isBlurred?: boolean;
isMasterTab: boolean; isMasterTab: boolean;
isInactive?: boolean; isInactive?: boolean;
shouldPreventComposerAnimation?: boolean;
inviteHash?: string; inviteHash?: string;
canInstall?: boolean; canInstall?: boolean;
isChatInfoShown: boolean; isChatInfoShown: boolean;
@ -2527,6 +2528,10 @@ export interface ActionPayloads {
photo: ApiPhoto; photo: ApiPhoto;
isFallback?: boolean; isFallback?: boolean;
}; };
// Composer
setShouldPreventComposerAnimation: {
shouldPreventComposerAnimation: boolean;
} & WithTabId;
// Forwards // Forwards
openForwardMenu: { openForwardMenu: {