Forward Recipient Picker: Fix forwarding messages when reply exists (#4615)

This commit is contained in:
Alexander Zinchuk 2024-06-12 18:11:02 +02:00
parent 28f48340e8
commit 8a7d6f8c07
5 changed files with 50 additions and 55 deletions

View File

@ -1012,7 +1012,7 @@ const Composer: FC<OwnProps & StateProps> = ({
lastMessageSendTimeSeconds.current = getServerTime(); lastMessageSendTimeSeconds.current = getServerTime();
clearDraft({ chatId, isLocalOnly: true }); clearDraft({ chatId, isLocalOnly: true, shouldKeepReply: isForwarding });
if (IS_IOS && messageInput && messageInput === document.activeElement) { if (IS_IOS && messageInput && messageInput === document.activeElement) {
applyIosAutoCapitalizationFix(messageInput); applyIosAutoCapitalizationFix(messageInput);

View File

@ -5,13 +5,10 @@ import React, {
import { getActions, getGlobal, withGlobal } from '../../global'; import { getActions, getGlobal, withGlobal } from '../../global';
import type { ThreadId } from '../../types'; import type { ThreadId } from '../../types';
import { MAIN_THREAD_ID } from '../../api/types';
import { getChatTitle, getUserFirstOrLastName, isUserId } from '../../global/helpers'; import { getChatTitle, getUserFirstOrLastName, isUserId } from '../../global/helpers';
import { import {
selectChat, selectChat,
selectCurrentChat,
selectDraft,
selectTabState, selectTabState,
selectUser, selectUser,
} from '../../global/selectors'; } from '../../global/selectors';
@ -30,7 +27,7 @@ interface StateProps {
currentUserId?: string; currentUserId?: string;
isManyMessages?: boolean; isManyMessages?: boolean;
isStory?: boolean; isStory?: boolean;
isReplying?: boolean; isForwarding?: boolean;
} }
const ForwardRecipientPicker: FC<OwnProps & StateProps> = ({ const ForwardRecipientPicker: FC<OwnProps & StateProps> = ({
@ -38,7 +35,7 @@ const ForwardRecipientPicker: FC<OwnProps & StateProps> = ({
currentUserId, currentUserId,
isManyMessages, isManyMessages,
isStory, isStory,
isReplying, isForwarding,
}) => { }) => {
const { const {
openChatOrTopicWithReplyInDraft, openChatOrTopicWithReplyInDraft,
@ -96,13 +93,13 @@ const ForwardRecipientPicker: FC<OwnProps & StateProps> = ({
} else { } else {
const chatId = recipientId; const chatId = recipientId;
const topicId = threadId ? Number(threadId) : undefined; const topicId = threadId ? Number(threadId) : undefined;
if (isReplying) { if (isForwarding) {
openChatOrTopicWithReplyInDraft({ chatId, topicId });
} else {
setForwardChatOrTopic({ chatId, topicId }); setForwardChatOrTopic({ chatId, topicId });
} else {
openChatOrTopicWithReplyInDraft({ chatId, topicId });
} }
} }
}, [currentUserId, isManyMessages, isStory, lang, isReplying]); }, [currentUserId, isManyMessages, isStory, lang, isForwarding]);
const handleClose = useCallback(() => { const handleClose = useCallback(() => {
exitForwardMode(); exitForwardMode();
@ -126,12 +123,11 @@ const ForwardRecipientPicker: FC<OwnProps & StateProps> = ({
export default memo(withGlobal<OwnProps>((global): StateProps => { export default memo(withGlobal<OwnProps>((global): StateProps => {
const { messageIds, storyId } = selectTabState(global).forwardMessages; const { messageIds, storyId } = selectTabState(global).forwardMessages;
const currentChatId = selectCurrentChat(global)?.id; const isForwarding = (messageIds && messageIds.length > 0);
const isReplying = currentChatId && selectDraft(global, currentChatId, MAIN_THREAD_ID)?.replyInfo;
return { return {
currentUserId: global.currentUserId, currentUserId: global.currentUserId,
isManyMessages: (messageIds?.length || 0) > 1, isManyMessages: (messageIds?.length || 0) > 1,
isStory: Boolean(storyId), isStory: Boolean(storyId),
isReplying: Boolean(isReplying), isForwarding,
}; };
})(ForwardRecipientPicker)); })(ForwardRecipientPicker));

View File

@ -116,8 +116,8 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
const isShown = (() => { const isShown = (() => {
if (isInChangingRecipientMode) return false; if (isInChangingRecipientMode) return false;
if (sender && isForwarding) return true;
if (message && (replyInfo || editingId)) return true; if (message && (replyInfo || editingId)) return true;
if (sender && isForwarding) return true;
return false; return false;
})(); })();
@ -139,12 +139,12 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
}); });
const clearEmbedded = useLastCallback(() => { const clearEmbedded = useLastCallback(() => {
if (replyInfo && !shouldForceShowEditing) { if (editingId) {
resetDraftReplyInfo();
} else if (editingId) {
setEditingId({ messageId: undefined }); setEditingId({ messageId: undefined });
} else if (forwardedMessagesCount) { } else if (forwardedMessagesCount) {
exitForwardMode(); exitForwardMode();
} else if (replyInfo && !shouldForceShowEditing) {
resetDraftReplyInfo();
} }
onClear?.(); onClear?.();
}); });
@ -210,15 +210,15 @@ const ComposerEmbeddedMessage: FC<OwnProps & StateProps> = ({
); );
const leftIcon = useMemo(() => { const leftIcon = useMemo(() => {
if (isShowingReply) {
return 'reply';
}
if (editingId) { if (editingId) {
return 'edit'; return 'edit';
} }
if (isForwarding) { if (isForwarding) {
return 'forward'; return 'forward';
} }
if (isShowingReply) {
return 'reply';
}
return undefined; return undefined;
}, [editingId, isForwarding, isShowingReply]); }, [editingId, isForwarding, isShowingReply]);
@ -398,25 +398,18 @@ export default memo(withGlobal<OwnProps>(
const senderChat = replyToPeerId ? selectChat(global, replyToPeerId) : undefined; const senderChat = replyToPeerId ? selectChat(global, replyToPeerId) : undefined;
let message: ApiMessage | undefined; let message: ApiMessage | undefined;
if (replyInfo && !shouldForceShowEditing) { if (editingId) {
message = selectChatMessage(global, replyInfo.replyToPeerId || chatId, replyInfo.replyToMsgId);
} else if (editingId) {
message = selectEditingMessage(global, chatId, threadId, messageListType); message = selectEditingMessage(global, chatId, threadId, messageListType);
} else if (isForwarding && forwardMessageIds!.length === 1) { } else if (isForwarding && forwardMessageIds!.length === 1) {
message = forwardedMessages?.[0]; message = forwardedMessages?.[0];
} else if (replyInfo && !shouldForceShowEditing) {
message = selectChatMessage(global, replyInfo.replyToPeerId || chatId, replyInfo.replyToMsgId);
} }
let sender: ApiPeer | undefined; let sender: ApiPeer | undefined;
if (replyInfo && message && !shouldForceShowEditing) {
const { forwardInfo } = message;
const isChatWithSelf = selectIsChatWithSelf(global, chatId);
if (forwardInfo && (forwardInfo.isChannelPost || isChatWithSelf)) {
sender = selectForwardedSender(global, message);
}
if (!sender && (!forwardInfo?.hiddenUserName || Boolean(replyInfo.quoteText))) { if (editingId && message) {
sender = selectSender(global, message); sender = selectSender(global, message);
}
} else if (isForwarding) { } else if (isForwarding) {
if (message) { if (message) {
sender = selectForwardedSender(global, message); sender = selectForwardedSender(global, message);
@ -427,8 +420,16 @@ export default memo(withGlobal<OwnProps>(
if (!sender) { if (!sender) {
sender = selectPeer(global, fromChatId!); sender = selectPeer(global, fromChatId!);
} }
} else if (editingId && message) { } else if (replyInfo && message && !shouldForceShowEditing) {
sender = selectSender(global, message); const { forwardInfo } = message;
const isChatWithSelf = selectIsChatWithSelf(global, chatId);
if (forwardInfo && (forwardInfo.isChannelPost || isChatWithSelf)) {
sender = selectForwardedSender(global, message);
}
if (!sender && (!forwardInfo?.hiddenUserName || Boolean(replyInfo.quoteText))) {
sender = selectSender(global, message);
}
} }
const forwardsHaveCaptions = forwardedMessages?.some((forward) => ( const forwardsHaveCaptions = forwardedMessages?.some((forward) => (

View File

@ -317,7 +317,9 @@ addActionHandler('sendMessage', (global, actions, payload): ActionReturnType =>
const chat = selectChat(global, chatId!)!; const chat = selectChat(global, chatId!)!;
const draft = selectDraft(global, chatId!, threadId!); const draft = selectDraft(global, chatId!, threadId!);
const draftReplyInfo = !isStoryReply ? draft?.replyInfo : undefined; const isForwarding = selectTabState(global, tabId).forwardMessages?.messageIds?.length;
const draftReplyInfo = !isForwarding && !isStoryReply ? draft?.replyInfo : undefined;
const storyReplyInfo = isStoryReply ? { const storyReplyInfo = isStoryReply ? {
type: 'story', type: 'story',
@ -1795,11 +1797,6 @@ addActionHandler('openChatOrTopicWithReplyInDraft', (global, actions, payload):
global = getGlobal(); global = getGlobal();
if (!selectReplyCanBeSentToChat(global, toChatId, tabId)) {
actions.showNotification({ message: translate('Chat.SendNotAllowedText'), tabId });
return;
}
global = updateTabState(global, { global = updateTabState(global, {
forwardMessages: { forwardMessages: {
...selectTabState(global, tabId).forwardMessages, ...selectTabState(global, tabId).forwardMessages,
@ -1809,23 +1806,27 @@ addActionHandler('openChatOrTopicWithReplyInDraft', (global, actions, payload):
setGlobal(global); setGlobal(global);
const currentChat = selectCurrentChat(global, tabId); const currentChat = selectCurrentChat(global, tabId);
if (!currentChat) return; const currentThreadId = selectCurrentMessageList(global, tabId)?.threadId;
if (!currentChat || !currentThreadId) return;
const threadId = topicId || MAIN_THREAD_ID; const threadId = topicId || MAIN_THREAD_ID;
const currentChatId = currentChat.id; const currentChatId = currentChat.id;
const currentReplyInfo = selectDraft(global, currentChatId, threadId)?.replyInfo; const currentReplyInfo = selectDraft(global, currentChatId, currentThreadId)?.replyInfo;
if (!currentReplyInfo) return; if (!currentReplyInfo) return;
if (!selectReplyCanBeSentToChat(global, toChatId, currentChatId, currentReplyInfo)) {
actions.showNotification({ message: translate('Chat.SendNotAllowedText'), tabId });
return;
}
if (!currentReplyInfo.replyToPeerId && toChatId === currentChat.id) return; if (!currentReplyInfo.replyToPeerId && toChatId === currentChat.id) return;
const getPeerId = () => { const getPeerId = () => {
if (!currentReplyInfo?.replyToPeerId) return currentChatId; if (!currentReplyInfo?.replyToPeerId) return currentChatId;
return currentReplyInfo.replyToPeerId === toChatId ? undefined : currentReplyInfo.replyToPeerId; return currentReplyInfo.replyToPeerId === toChatId ? undefined : currentReplyInfo.replyToPeerId;
}; };
const currentThreadId = selectCurrentMessageList(global, tabId)?.threadId;
if (!currentThreadId) {
return;
}
const replyToPeerId = getPeerId(); const replyToPeerId = getPeerId();
const newReply: ApiInputMessageReplyInfo = { const newReply: ApiInputMessageReplyInfo = {
...currentReplyInfo, ...currentReplyInfo,
@ -1869,7 +1870,6 @@ addActionHandler('setForwardChatOrTopic', async (global, actions, payload): Prom
}, },
}, tabId); }, tabId);
setGlobal(global); setGlobal(global);
actions.openThread({ chatId, threadId: topicId || MAIN_THREAD_ID, tabId }); actions.openThread({ chatId, threadId: topicId || MAIN_THREAD_ID, tabId });
actions.closeMediaViewer({ tabId }); actions.closeMediaViewer({ tabId });
actions.exitMessageSelectMode({ tabId }); actions.exitMessageSelectMode({ tabId });

View File

@ -1363,15 +1363,13 @@ export function selectRequestedMessageTranslationLanguage<T extends GlobalState>
export function selectReplyCanBeSentToChat<T extends GlobalState>( export function selectReplyCanBeSentToChat<T extends GlobalState>(
global: T, global: T,
toChatId: string, toChatId: string,
...[tabId = getCurrentTabId()]: TabArgs<T> fromChatId: string,
replyInfo: ApiInputMessageReplyInfo,
) { ) {
const currentChat = selectCurrentChat(global, tabId); if (!replyInfo.replyToMsgId) return false;
if (!currentChat) return false; const fromRealChatId = replyInfo?.replyToPeerId ?? fromChatId;
const replyInfo = selectDraft(global, currentChat.id, MAIN_THREAD_ID)?.replyInfo; if (toChatId === fromRealChatId) return true;
if (!replyInfo || !replyInfo.replyToMsgId) return false; const chatMessages = selectChatMessages(global, fromRealChatId!);
const fromChatId = replyInfo?.replyToPeerId ?? currentChat.id;
if (toChatId === fromChatId) return true;
const chatMessages = selectChatMessages(global, fromChatId!);
const message = chatMessages[replyInfo.replyToMsgId]; const message = chatMessages[replyInfo.replyToMsgId];
return !isExpiredMessage(message); return !isExpiredMessage(message);