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;
replyToPeerId?: string;
quoteText?: ApiFormattedText;
isShowingDelayNeeded?: boolean;
}
export interface ApiInputStoryReplyInfo {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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