Channels: Support reply in another chat (#4798)
This commit is contained in:
parent
23b6e5e66d
commit
8d34fb3c20
@ -113,7 +113,7 @@ const ForwardRecipientPicker: FC<OwnProps & StateProps> = ({
|
||||
<RecipientPicker
|
||||
isOpen={isOpen}
|
||||
className={renderingIsStory ? 'component-theme-dark' : undefined}
|
||||
searchPlaceholder={lang('ForwardTo')}
|
||||
searchPlaceholder={lang(isForwarding ? 'ForwardTo' : 'ReplyToDialog')}
|
||||
onSelectRecipient={handleSelectRecipient}
|
||||
onClose={handleClose}
|
||||
onCloseAnimationEnd={unmarkIsShown}
|
||||
|
||||
@ -201,8 +201,8 @@ export default memo(withGlobal<OwnProps>(
|
||||
const { messageIds: selectedMessageIds } = tabState.selectedMessages || {};
|
||||
const hasProtectedMessage = chatId ? selectHasProtectedMessage(global, chatId, selectedMessageIds) : false;
|
||||
const canForward = !isSchedule && chatId ? selectCanForwardMessages(global, chatId, selectedMessageIds) : false;
|
||||
const isForwardModalOpen = tabState.forwardMessages.isModalShown;
|
||||
const isAnyModalOpen = Boolean(isForwardModalOpen || tabState.requestedDraft
|
||||
const isShareMessageModalOpen = tabState.isShareMessageModalShown;
|
||||
const isAnyModalOpen = Boolean(isShareMessageModalOpen || tabState.requestedDraft
|
||||
|| tabState.requestedAttachBotInChat || tabState.requestedAttachBotInstall);
|
||||
|
||||
return {
|
||||
|
||||
@ -400,8 +400,9 @@ export default memo(withGlobal<OwnProps>(
|
||||
}): StateProps => {
|
||||
const {
|
||||
forwardMessages: {
|
||||
fromChatId, toChatId, messageIds: forwardMessageIds, noAuthors, noCaptions, isModalShown,
|
||||
fromChatId, toChatId, messageIds: forwardMessageIds, noAuthors, noCaptions,
|
||||
},
|
||||
isShareMessageModalShown: isModalShown,
|
||||
shouldPreventComposerAnimation,
|
||||
} = selectTabState(global);
|
||||
|
||||
|
||||
@ -19,6 +19,7 @@ import { MAIN_THREAD_ID } from '../../../api/types';
|
||||
import { PREVIEW_AVATAR_COUNT, SERVICE_NOTIFICATIONS_USER_ID } from '../../../config';
|
||||
import {
|
||||
areReactionsEmpty,
|
||||
getHasAdminRight,
|
||||
getIsDownloading,
|
||||
getMessageDownloadableMedia,
|
||||
getMessageVideo,
|
||||
@ -127,6 +128,8 @@ type StateProps = {
|
||||
canPlayAnimatedEmojis?: boolean;
|
||||
isReactionPickerOpen?: boolean;
|
||||
isInSavedMessages?: boolean;
|
||||
isChannel?: boolean;
|
||||
canPostMessagesInChannel?: boolean;
|
||||
};
|
||||
|
||||
const selection = window.getSelection();
|
||||
@ -187,6 +190,8 @@ const ContextMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
isInSavedMessages,
|
||||
onClose,
|
||||
onCloseAnimationEnd,
|
||||
isChannel,
|
||||
canPostMessagesInChannel,
|
||||
}) => {
|
||||
const {
|
||||
openThread,
|
||||
@ -194,6 +199,7 @@ const ContextMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
setEditingId,
|
||||
pinMessage,
|
||||
openForwardMenu,
|
||||
openReplyMenu,
|
||||
faveSticker,
|
||||
unfaveSticker,
|
||||
toggleMessageSelection,
|
||||
@ -357,11 +363,16 @@ const ContextMenuContainer: FC<OwnProps & StateProps> = ({
|
||||
});
|
||||
|
||||
const handleReply = useLastCallback(() => {
|
||||
updateDraftReplyInfo({
|
||||
replyToMsgId: message.id,
|
||||
quoteText: canQuoteSelection && selectionRange ? getSelectionAsFormattedText(selectionRange) : undefined,
|
||||
replyToPeerId: undefined,
|
||||
});
|
||||
const quoteText = canQuoteSelection && selectionRange ? getSelectionAsFormattedText(selectionRange) : undefined;
|
||||
if (isChannel && !canPostMessagesInChannel) {
|
||||
openReplyMenu({ fromChatId: message.chatId, messageId: message.id, quoteText });
|
||||
} else {
|
||||
updateDraftReplyInfo({
|
||||
replyToMsgId: message.id,
|
||||
quoteText,
|
||||
replyToPeerId: undefined,
|
||||
});
|
||||
}
|
||||
closeMenu();
|
||||
});
|
||||
|
||||
@ -705,6 +716,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
const isPinned = messageListType === 'pinned';
|
||||
const isScheduled = messageListType === 'scheduled';
|
||||
const isChannel = chat && isChatChannel(chat);
|
||||
const canPostMessagesInChannel = isChannel && getHasAdminRight(chat, 'postMessages');
|
||||
const isLocal = isMessageLocal(message);
|
||||
const hasTtl = hasMessageTtl(message);
|
||||
const canShowSeenBy = Boolean(!isLocal
|
||||
@ -787,6 +799,8 @@ export default memo(withGlobal<OwnProps>(
|
||||
canPlayAnimatedEmojis: selectCanPlayAnimatedEmojis(global),
|
||||
isReactionPickerOpen: selectIsReactionPickerOpen(global),
|
||||
isInSavedMessages,
|
||||
isChannel,
|
||||
canPostMessagesInChannel,
|
||||
};
|
||||
},
|
||||
)(ContextMenuContainer));
|
||||
|
||||
@ -1121,6 +1121,7 @@ addActionHandler('forwardMessages', (global, actions, payload): ActionReturnType
|
||||
global = getGlobal();
|
||||
global = updateTabState(global, {
|
||||
forwardMessages: {},
|
||||
isShareMessageModalShown: false,
|
||||
}, tabId);
|
||||
setGlobal(global);
|
||||
});
|
||||
@ -1827,11 +1828,12 @@ addActionHandler('openChatOrTopicWithReplyInDraft', (global, actions, payload):
|
||||
|
||||
global = getGlobal();
|
||||
|
||||
const tabState = selectTabState(global, tabId);
|
||||
const replyingInfo = tabState.replyingMessage;
|
||||
|
||||
global = updateTabState(global, {
|
||||
forwardMessages: {
|
||||
...selectTabState(global, tabId).forwardMessages,
|
||||
isModalShown: false,
|
||||
},
|
||||
isShareMessageModalShown: false,
|
||||
replyingMessage: {},
|
||||
}, tabId);
|
||||
setGlobal(global);
|
||||
|
||||
@ -1843,7 +1845,16 @@ addActionHandler('openChatOrTopicWithReplyInDraft', (global, actions, payload):
|
||||
const threadId = topicId || MAIN_THREAD_ID;
|
||||
const currentChatId = currentChat.id;
|
||||
|
||||
const currentReplyInfo = selectDraft(global, currentChatId, currentThreadId)?.replyInfo;
|
||||
const newReplyInfo = {
|
||||
type: 'message',
|
||||
replyToMsgId: replyingInfo.messageId,
|
||||
replyToTopId: replyingInfo.toThreadId,
|
||||
replyToPeerId: currentChatId,
|
||||
quoteText: replyingInfo.quoteText,
|
||||
} as ApiInputMessageReplyInfo;
|
||||
|
||||
const currentReplyInfo = replyingInfo.messageId
|
||||
? newReplyInfo : selectDraft(global, currentChatId, currentThreadId)?.replyInfo;
|
||||
if (!currentReplyInfo) return;
|
||||
|
||||
if (!selectReplyCanBeSentToChat(global, toChatId, currentChatId, currentReplyInfo)) {
|
||||
@ -1896,8 +1907,8 @@ addActionHandler('setForwardChatOrTopic', async (global, actions, payload): Prom
|
||||
...selectTabState(global, tabId).forwardMessages,
|
||||
toChatId: chatId,
|
||||
toThreadId: topicId,
|
||||
isModalShown: false,
|
||||
},
|
||||
isShareMessageModalShown: false,
|
||||
}, tabId);
|
||||
setGlobal(global);
|
||||
actions.openThread({ chatId, threadId: topicId || MAIN_THREAD_ID, tabId });
|
||||
@ -1947,6 +1958,7 @@ addActionHandler('forwardStory', (global, actions, payload): ActionReturnType =>
|
||||
global = getGlobal();
|
||||
global = updateTabState(global, {
|
||||
forwardMessages: {},
|
||||
isShareMessageModalShown: false,
|
||||
}, tabId);
|
||||
setGlobal(global);
|
||||
});
|
||||
|
||||
@ -61,6 +61,7 @@ addActionHandler('processOpenChatOrThread', (global, actions, payload): ActionRe
|
||||
contentToBeScheduled: undefined,
|
||||
...(chatId !== selectTabState(global, tabId).forwardMessages.toChatId && {
|
||||
forwardMessages: {},
|
||||
isShareMessageModalShown: false,
|
||||
}),
|
||||
}, tabId);
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ addActionHandler('openMediaViewer', (global, actions, payload): ActionReturnType
|
||||
withDynamicLoading,
|
||||
},
|
||||
forwardMessages: {},
|
||||
isShareMessageModalShown: false,
|
||||
}, tabId);
|
||||
});
|
||||
|
||||
|
||||
@ -515,6 +515,20 @@ addActionHandler('setShouldPreventComposerAnimation', (global, actions, payload)
|
||||
}, tabId);
|
||||
});
|
||||
|
||||
addActionHandler('openReplyMenu', (global, actions, payload): ActionReturnType => {
|
||||
const {
|
||||
fromChatId, messageId, quoteText, tabId = getCurrentTabId(),
|
||||
} = payload;
|
||||
return updateTabState(global, {
|
||||
replyingMessage: {
|
||||
fromChatId,
|
||||
messageId,
|
||||
quoteText,
|
||||
},
|
||||
isShareMessageModalShown: true,
|
||||
}, tabId);
|
||||
});
|
||||
|
||||
addActionHandler('openForwardMenu', (global, actions, payload): ActionReturnType => {
|
||||
const {
|
||||
fromChatId, messageIds, storyId, groupedId, withMyScore, tabId = getCurrentTabId(),
|
||||
@ -528,9 +542,9 @@ addActionHandler('openForwardMenu', (global, actions, payload): ActionReturnType
|
||||
fromChatId,
|
||||
messageIds: groupedMessageIds || messageIds,
|
||||
storyId,
|
||||
isModalShown: true,
|
||||
withMyScore,
|
||||
},
|
||||
isShareMessageModalShown: true,
|
||||
}, tabId);
|
||||
});
|
||||
|
||||
@ -540,10 +554,10 @@ addActionHandler('changeRecipient', (global, actions, payload): ActionReturnType
|
||||
forwardMessages: {
|
||||
...selectTabState(global, tabId).forwardMessages,
|
||||
toChatId: undefined,
|
||||
isModalShown: true,
|
||||
noAuthors: false,
|
||||
noCaptions: false,
|
||||
},
|
||||
isShareMessageModalShown: true,
|
||||
}, tabId);
|
||||
});
|
||||
|
||||
@ -575,7 +589,9 @@ addActionHandler('exitForwardMode', (global, actions, payload): ActionReturnType
|
||||
const { tabId = getCurrentTabId() } = payload || {};
|
||||
|
||||
global = updateTabState(global, {
|
||||
isShareMessageModalShown: false,
|
||||
forwardMessages: {},
|
||||
replyingMessage: {},
|
||||
}, tabId);
|
||||
setGlobal(global);
|
||||
});
|
||||
|
||||
@ -349,8 +349,12 @@ export const INITIAL_TAB_STATE: TabState = {
|
||||
isMuted: false,
|
||||
},
|
||||
|
||||
isShareMessageModalShown: false,
|
||||
|
||||
forwardMessages: {},
|
||||
|
||||
replyingMessage: {},
|
||||
|
||||
pollResults: {},
|
||||
|
||||
payment: {},
|
||||
|
||||
@ -655,9 +655,13 @@ export function selectAllowedMessageActions<T extends GlobalState>(global: T, me
|
||||
|
||||
const threadInfo = selectThreadInfo(global, message.chatId, threadId);
|
||||
const isMessageThread = Boolean(!threadInfo?.isCommentsInfo && threadInfo?.fromChannelId);
|
||||
const canReply = !isLocal && !isServiceNotification && !chat.isForbidden
|
||||
&& getCanPostInChat(chat, threadId, isMessageThread, chatFullInfo)
|
||||
&& (!messageTopic || !messageTopic.isClosed || messageTopic.isOwner || getHasAdminRight(chat, 'manageTopics'));
|
||||
const canPostInChat = getCanPostInChat(chat, threadId, isMessageThread, chatFullInfo);
|
||||
const canReply = (() => {
|
||||
if (isLocal || isServiceNotification) return false;
|
||||
if (isChatChannel(chat)) return true;
|
||||
if (!canPostInChat || chat.isForbidden) return false;
|
||||
return !messageTopic || !messageTopic.isClosed || messageTopic.isOwner || getHasAdminRight(chat, 'manageTopics');
|
||||
})();
|
||||
|
||||
const hasPinPermission = isPrivate || (
|
||||
chat.isCreator
|
||||
@ -945,8 +949,8 @@ export function selectIsForwardModalOpen<T extends GlobalState>(
|
||||
global: T,
|
||||
...[tabId = getCurrentTabId()]: TabArgs<T>
|
||||
) {
|
||||
const { forwardMessages } = selectTabState(global, tabId);
|
||||
return Boolean(forwardMessages.isModalShown);
|
||||
const { isShareMessageModalShown } = selectTabState(global, tabId);
|
||||
return Boolean(isShareMessageModalShown);
|
||||
}
|
||||
|
||||
export function selectCommonBoxChatId<T extends GlobalState>(global: T, messageId: number) {
|
||||
|
||||
@ -491,8 +491,17 @@ export type TabState = {
|
||||
loadingMessageId: number;
|
||||
};
|
||||
|
||||
isShareMessageModalShown?: boolean;
|
||||
|
||||
replyingMessage: {
|
||||
fromChatId?: string;
|
||||
messageId?: number;
|
||||
quoteText?: ApiFormattedText;
|
||||
toChatId?: string;
|
||||
toThreadId?: ThreadId;
|
||||
};
|
||||
|
||||
forwardMessages: {
|
||||
isModalShown?: boolean;
|
||||
fromChatId?: string;
|
||||
messageIds?: number[];
|
||||
storyId?: number;
|
||||
@ -2625,6 +2634,13 @@ export interface ActionPayloads {
|
||||
shouldPreventComposerAnimation: boolean;
|
||||
} & WithTabId;
|
||||
|
||||
// Replies
|
||||
openReplyMenu: {
|
||||
fromChatId: string;
|
||||
messageId?: number;
|
||||
quoteText?: ApiFormattedText;
|
||||
} & WithTabId;
|
||||
|
||||
// Forwards
|
||||
openForwardMenu: {
|
||||
fromChatId: string;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user