Composer: Fix race conditions when sending messages (#3279)
This commit is contained in:
parent
e5ad070a27
commit
85bdbd5fa5
@ -5,15 +5,18 @@ import { getActions, withGlobal } from '../../global';
|
||||
|
||||
import type { FC } from '../../lib/teact/teact';
|
||||
import type { ApiSticker, ApiStickerSet } from '../../api/types';
|
||||
import type { MessageList } from '../../global/types';
|
||||
|
||||
import { EMOJI_SIZE_MODAL, STICKER_SIZE_MODAL, TME_LINK_PREFIX } from '../../config';
|
||||
import {
|
||||
selectCanScheduleUntilOnline,
|
||||
selectChat,
|
||||
selectCurrentMessageList,
|
||||
selectIsChatWithSelf, selectIsCurrentUserPremium,
|
||||
selectIsChatWithSelf,
|
||||
selectIsCurrentUserPremium,
|
||||
selectShouldSchedule,
|
||||
selectStickerSet, selectThreadInfo,
|
||||
selectStickerSet,
|
||||
selectThreadInfo,
|
||||
} from '../../global/selectors';
|
||||
import renderText from './helpers/renderText';
|
||||
import { copyTextToClipboard } from '../../util/clipboard';
|
||||
@ -44,6 +47,7 @@ export type OwnProps = {
|
||||
};
|
||||
|
||||
type StateProps = {
|
||||
currentMessageList?: MessageList;
|
||||
canSendStickers?: boolean;
|
||||
stickerSet?: ApiStickerSet;
|
||||
canScheduleUntilOnline?: boolean;
|
||||
@ -66,6 +70,7 @@ const StickerSetModal: FC<OwnProps & StateProps> = ({
|
||||
isSavedMessages,
|
||||
isCurrentUserPremium,
|
||||
shouldUpdateStickerSetOrder,
|
||||
currentMessageList,
|
||||
onClose,
|
||||
}) => {
|
||||
const {
|
||||
@ -109,6 +114,9 @@ const StickerSetModal: FC<OwnProps & StateProps> = ({
|
||||
}, [isOpen, fromSticker, loadStickers, stickerSetShortName, renderingStickerSet]);
|
||||
|
||||
const handleSelect = useCallback((sticker: ApiSticker, isSilent?: boolean, isScheduleRequested?: boolean) => {
|
||||
if (!currentMessageList) {
|
||||
return;
|
||||
}
|
||||
sticker = {
|
||||
...sticker,
|
||||
isPreloadedGlobally: true,
|
||||
@ -117,19 +125,20 @@ const StickerSetModal: FC<OwnProps & StateProps> = ({
|
||||
if (shouldSchedule || isScheduleRequested) {
|
||||
requestCalendar((scheduledAt) => {
|
||||
sendMessage({
|
||||
sticker, isSilent, scheduledAt,
|
||||
messageList: currentMessageList, sticker, isSilent, scheduledAt,
|
||||
});
|
||||
onClose();
|
||||
});
|
||||
} else {
|
||||
sendMessage({
|
||||
messageList: currentMessageList,
|
||||
sticker,
|
||||
isSilent,
|
||||
shouldUpdateStickerSetOrder: shouldUpdateStickerSetOrder && isAdded,
|
||||
});
|
||||
onClose();
|
||||
}
|
||||
}, [onClose, requestCalendar, sendMessage, shouldSchedule, isAdded, shouldUpdateStickerSetOrder]);
|
||||
}, [currentMessageList, shouldSchedule, requestCalendar, onClose, shouldUpdateStickerSetOrder, isAdded]);
|
||||
|
||||
const handleButtonClick = useCallback(() => {
|
||||
if (renderingStickerSet) {
|
||||
@ -270,6 +279,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
stickerSet,
|
||||
isCurrentUserPremium: selectIsCurrentUserPremium(global),
|
||||
shouldUpdateStickerSetOrder: global.settings.byKey.shouldUpdateStickerSetOrder,
|
||||
currentMessageList,
|
||||
};
|
||||
},
|
||||
)(StickerSetModal));
|
||||
|
||||
@ -5,8 +5,9 @@ import { getActions, withGlobal } from '../../global';
|
||||
import type {
|
||||
ApiContact, ApiError, ApiInviteInfo, ApiPhoto,
|
||||
} from '../../api/types';
|
||||
import type { MessageList } from '../../global/types';
|
||||
|
||||
import { selectTabState } from '../../global/selectors';
|
||||
import { selectCurrentMessageList, selectTabState } from '../../global/selectors';
|
||||
import getReadableErrorText from '../../util/getReadableErrorText';
|
||||
import { pick } from '../../util/iteratees';
|
||||
import renderText from '../common/helpers/renderText';
|
||||
@ -18,10 +19,11 @@ import Button from '../ui/Button';
|
||||
import Avatar from '../common/Avatar';
|
||||
|
||||
type StateProps = {
|
||||
currentMessageList?: MessageList;
|
||||
dialogs: (ApiError | ApiInviteInfo | ApiContact)[];
|
||||
};
|
||||
|
||||
const Dialogs: FC<StateProps> = ({ dialogs }) => {
|
||||
const Dialogs: FC<StateProps> = ({ dialogs, currentMessageList }) => {
|
||||
const {
|
||||
dismissDialog,
|
||||
acceptInviteConfirmation,
|
||||
@ -115,8 +117,13 @@ const Dialogs: FC<StateProps> = ({ dialogs }) => {
|
||||
|
||||
const renderContactRequest = (contactRequest: ApiContact) => {
|
||||
const handleConfirm = () => {
|
||||
if (!currentMessageList) {
|
||||
return;
|
||||
}
|
||||
|
||||
sendMessage({
|
||||
contact: pick(contactRequest, ['firstName', 'lastName', 'phoneNumber']),
|
||||
messageList: currentMessageList,
|
||||
});
|
||||
closeModal();
|
||||
};
|
||||
@ -194,6 +201,7 @@ export default memo(withGlobal(
|
||||
(global): StateProps => {
|
||||
return {
|
||||
dialogs: selectTabState(global).dialogs,
|
||||
currentMessageList: selectCurrentMessageList(global),
|
||||
};
|
||||
},
|
||||
)(Dialogs));
|
||||
|
||||
@ -3,8 +3,9 @@ import React, { memo, useEffect, useRef } from '../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../global';
|
||||
|
||||
import type { ApiSticker, ApiUpdateConnectionStateType } from '../../api/types';
|
||||
import type { MessageList } from '../../global/types';
|
||||
|
||||
import { selectChat } from '../../global/selectors';
|
||||
import { selectChat, selectCurrentMessageList } from '../../global/selectors';
|
||||
import { getUserIdDividend } from '../../global/helpers';
|
||||
|
||||
import useLastCallback from '../../hooks/useLastCallback';
|
||||
@ -23,6 +24,7 @@ type StateProps = {
|
||||
sticker?: ApiSticker;
|
||||
lastUnreadMessageId?: number;
|
||||
connectionState?: ApiUpdateConnectionStateType;
|
||||
currentMessageList?: MessageList;
|
||||
};
|
||||
|
||||
const INTERSECTION_DEBOUNCE_MS = 200;
|
||||
@ -31,6 +33,7 @@ const ContactGreeting: FC<OwnProps & StateProps> = ({
|
||||
sticker,
|
||||
connectionState,
|
||||
lastUnreadMessageId,
|
||||
currentMessageList,
|
||||
}) => {
|
||||
const {
|
||||
loadGreetingStickers,
|
||||
@ -62,11 +65,15 @@ const ContactGreeting: FC<OwnProps & StateProps> = ({
|
||||
}, [connectionState, markMessageListRead, lastUnreadMessageId]);
|
||||
|
||||
const handleStickerSelect = useLastCallback((selectedSticker: ApiSticker) => {
|
||||
if (!currentMessageList) {
|
||||
return;
|
||||
}
|
||||
|
||||
selectedSticker = {
|
||||
...selectedSticker,
|
||||
isPreloadedGlobally: true,
|
||||
};
|
||||
sendMessage({ sticker: selectedSticker });
|
||||
sendMessage({ sticker: selectedSticker, messageList: currentMessageList });
|
||||
});
|
||||
|
||||
return (
|
||||
@ -110,6 +117,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
? chat.lastMessage.id
|
||||
: undefined,
|
||||
connectionState: global.connectionState,
|
||||
currentMessageList: selectCurrentMessageList(global),
|
||||
};
|
||||
},
|
||||
)(ContactGreeting));
|
||||
|
||||
@ -6,7 +6,7 @@ import { requestMeasure, requestNextMutation } from '../../../lib/fasterdom/fast
|
||||
import { getActions, withGlobal } from '../../../global';
|
||||
|
||||
import type {
|
||||
TabState, MessageListType, GlobalState, ApiDraft,
|
||||
TabState, MessageListType, GlobalState, ApiDraft, MessageList,
|
||||
} from '../../../global/types';
|
||||
import type {
|
||||
ApiAttachment,
|
||||
@ -159,6 +159,7 @@ type StateProps =
|
||||
editingMessage?: ApiMessage;
|
||||
chat?: ApiChat;
|
||||
draft?: ApiDraft;
|
||||
currentMessageList?: MessageList;
|
||||
isChatWithBot?: boolean;
|
||||
isChatWithSelf?: boolean;
|
||||
isChannel?: boolean;
|
||||
@ -243,6 +244,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
editingMessage,
|
||||
chatId,
|
||||
threadId,
|
||||
currentMessageList,
|
||||
messageListType,
|
||||
draft,
|
||||
chat,
|
||||
@ -740,7 +742,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
isSilent?: boolean;
|
||||
scheduledAt?: number;
|
||||
}) => {
|
||||
if (connectionState !== 'connectionStateReady') {
|
||||
if (connectionState !== 'connectionStateReady' || !currentMessageList) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -752,6 +754,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
if (!checkSlowMode()) return;
|
||||
|
||||
sendMessage({
|
||||
messageList: currentMessageList,
|
||||
text,
|
||||
entities,
|
||||
scheduledAt,
|
||||
@ -787,7 +790,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
});
|
||||
|
||||
const handleSend = useLastCallback(async (isSilent = false, scheduledAt?: number) => {
|
||||
if (connectionState !== 'connectionStateReady') {
|
||||
if (connectionState !== 'connectionStateReady' || !currentMessageList) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -826,6 +829,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
if (!checkSlowMode()) return;
|
||||
|
||||
sendMessage({
|
||||
messageList: currentMessageList,
|
||||
text,
|
||||
entities,
|
||||
scheduledAt,
|
||||
@ -871,7 +875,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
});
|
||||
|
||||
const handleMessageSchedule = useLastCallback((
|
||||
args: ScheduledMessageArgs, scheduledAt: number,
|
||||
args: ScheduledMessageArgs, scheduledAt: number, messageList: MessageList,
|
||||
) => {
|
||||
if (args && 'queryId' in args) {
|
||||
const { id, queryId, isSilent } = args;
|
||||
@ -880,6 +884,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
queryId,
|
||||
scheduledAt,
|
||||
isSilent,
|
||||
messageList,
|
||||
});
|
||||
return;
|
||||
}
|
||||
@ -894,18 +899,19 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
} else {
|
||||
sendMessage({
|
||||
...args,
|
||||
messageList,
|
||||
scheduledAt,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
useEffectWithPrevDeps(([prevContentToBeScheduled]) => {
|
||||
if (contentToBeScheduled && contentToBeScheduled !== prevContentToBeScheduled) {
|
||||
if (currentMessageList && contentToBeScheduled && contentToBeScheduled !== prevContentToBeScheduled) {
|
||||
requestCalendar((scheduledAt) => {
|
||||
handleMessageSchedule(contentToBeScheduled, scheduledAt);
|
||||
handleMessageSchedule(contentToBeScheduled, scheduledAt, currentMessageList);
|
||||
});
|
||||
}
|
||||
}, [contentToBeScheduled, handleMessageSchedule, requestCalendar]);
|
||||
}, [contentToBeScheduled, currentMessageList, handleMessageSchedule, requestCalendar]);
|
||||
|
||||
useEffect(() => {
|
||||
if (requestedDraftText) {
|
||||
@ -940,17 +946,21 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
});
|
||||
|
||||
const handleGifSelect = useLastCallback((gif: ApiVideo, isSilent?: boolean, isScheduleRequested?: boolean) => {
|
||||
if (!currentMessageList) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (shouldSchedule || isScheduleRequested) {
|
||||
forceShowSymbolMenu();
|
||||
requestCalendar((scheduledAt) => {
|
||||
cancelForceShowSymbolMenu();
|
||||
handleMessageSchedule({ gif, isSilent }, scheduledAt);
|
||||
handleMessageSchedule({ gif, isSilent }, scheduledAt, currentMessageList);
|
||||
requestMeasure(() => {
|
||||
resetComposer(true);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
sendMessage({ gif, isSilent });
|
||||
sendMessage({ messageList: currentMessageList, gif, isSilent });
|
||||
requestMeasure(() => {
|
||||
resetComposer(true);
|
||||
});
|
||||
@ -964,6 +974,10 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
shouldPreserveInput = false,
|
||||
canUpdateStickerSetsOrder?: boolean,
|
||||
) => {
|
||||
if (!currentMessageList) {
|
||||
return;
|
||||
}
|
||||
|
||||
sticker = {
|
||||
...sticker,
|
||||
isPreloadedGlobally: true,
|
||||
@ -973,13 +987,14 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
forceShowSymbolMenu();
|
||||
requestCalendar((scheduledAt) => {
|
||||
cancelForceShowSymbolMenu();
|
||||
handleMessageSchedule({ sticker, isSilent }, scheduledAt);
|
||||
handleMessageSchedule({ sticker, isSilent }, scheduledAt, currentMessageList);
|
||||
requestMeasure(() => {
|
||||
resetComposer(shouldPreserveInput);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
sendMessage({
|
||||
messageList: currentMessageList,
|
||||
sticker,
|
||||
isSilent,
|
||||
shouldUpdateStickerSetOrder: shouldUpdateStickerSetOrder && canUpdateStickerSetsOrder,
|
||||
@ -993,7 +1008,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
const handleInlineBotSelect = useLastCallback((
|
||||
inlineResult: ApiBotInlineResult | ApiBotInlineMediaResult, isSilent?: boolean, isScheduleRequested?: boolean,
|
||||
) => {
|
||||
if (connectionState !== 'connectionStateReady') {
|
||||
if (connectionState !== 'connectionStateReady' || !currentMessageList) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1003,13 +1018,14 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
id: inlineResult.id,
|
||||
queryId: inlineResult.queryId,
|
||||
isSilent,
|
||||
}, scheduledAt);
|
||||
}, scheduledAt, currentMessageList);
|
||||
});
|
||||
} else {
|
||||
sendInlineBotResult({
|
||||
id: inlineResult.id,
|
||||
queryId: inlineResult.queryId,
|
||||
isSilent,
|
||||
messageList: currentMessageList,
|
||||
});
|
||||
}
|
||||
|
||||
@ -1032,13 +1048,17 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
});
|
||||
|
||||
const handlePollSend = useLastCallback((poll: ApiNewPoll) => {
|
||||
if (!currentMessageList) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (shouldSchedule) {
|
||||
requestCalendar((scheduledAt) => {
|
||||
handleMessageSchedule({ poll }, scheduledAt);
|
||||
handleMessageSchedule({ poll }, scheduledAt, currentMessageList);
|
||||
});
|
||||
closePollModal();
|
||||
} else {
|
||||
sendMessage({ poll });
|
||||
sendMessage({ messageList: currentMessageList, poll });
|
||||
closePollModal();
|
||||
}
|
||||
});
|
||||
@ -1046,7 +1066,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
const sendSilent = useLastCallback((additionalArgs?: ScheduledMessageArgs) => {
|
||||
if (shouldSchedule) {
|
||||
requestCalendar((scheduledAt) => {
|
||||
handleMessageSchedule({ ...additionalArgs, isSilent: true }, scheduledAt);
|
||||
handleMessageSchedule({ ...additionalArgs, isSilent: true }, scheduledAt, currentMessageList!);
|
||||
});
|
||||
} else if (additionalArgs && ('sendCompressed' in additionalArgs || 'sendGrouped' in additionalArgs)) {
|
||||
const { sendCompressed = false, sendGrouped = false } = additionalArgs;
|
||||
@ -1162,8 +1182,12 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
if (activeVoiceRecording) {
|
||||
pauseRecordingVoice();
|
||||
}
|
||||
if (!currentMessageList) {
|
||||
return;
|
||||
}
|
||||
|
||||
requestCalendar((scheduledAt) => {
|
||||
handleMessageSchedule({}, scheduledAt);
|
||||
handleMessageSchedule({}, scheduledAt, currentMessageList!);
|
||||
});
|
||||
break;
|
||||
default:
|
||||
@ -1201,7 +1225,7 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
|
||||
const handleSendScheduled = useLastCallback(() => {
|
||||
requestCalendar((scheduledAt) => {
|
||||
handleMessageSchedule({}, scheduledAt);
|
||||
handleMessageSchedule({}, scheduledAt, currentMessageList!);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1210,12 +1234,12 @@ const Composer: FC<OwnProps & StateProps> = ({
|
||||
});
|
||||
|
||||
const handleSendWhenOnline = useLastCallback(() => {
|
||||
handleMessageSchedule({}, SCHEDULED_WHEN_ONLINE);
|
||||
handleMessageSchedule({}, SCHEDULED_WHEN_ONLINE, currentMessageList!);
|
||||
});
|
||||
|
||||
const handleSendScheduledAttachments = useLastCallback((sendCompressed: boolean, sendGrouped: boolean) => {
|
||||
requestCalendar((scheduledAt) => {
|
||||
handleMessageSchedule({ sendCompressed, sendGrouped }, scheduledAt);
|
||||
handleMessageSchedule({ sendCompressed, sendGrouped }, scheduledAt, currentMessageList!);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1656,6 +1680,7 @@ export default memo(withGlobal<OwnProps>(
|
||||
canSendVoiceByPrivacy,
|
||||
attachmentSettings: global.attachmentSettings,
|
||||
slowMode,
|
||||
currentMessageList,
|
||||
};
|
||||
},
|
||||
)(Composer));
|
||||
|
||||
@ -155,6 +155,7 @@ const useEditing = (
|
||||
}
|
||||
|
||||
editMessage({
|
||||
messageList: { chatId, threadId, type },
|
||||
text,
|
||||
entities,
|
||||
});
|
||||
|
||||
@ -3,6 +3,7 @@ import React, { memo, useRef, useCallback } from '../../lib/teact/teact';
|
||||
import { getActions, withGlobal } from '../../global';
|
||||
|
||||
import type { ApiChat, ApiVideo } from '../../api/types';
|
||||
import type { MessageList } from '../../global/types';
|
||||
|
||||
import { IS_TOUCH_ENV } from '../../util/windowEnvironment';
|
||||
import {
|
||||
@ -39,6 +40,7 @@ type StateProps = {
|
||||
canScheduleUntilOnline?: boolean;
|
||||
isSavedMessages?: boolean;
|
||||
canPostInChat?: boolean;
|
||||
currentMessageList?: MessageList;
|
||||
};
|
||||
|
||||
const PRELOAD_BACKWARDS = 96; // GIF Search bot results are multiplied by 24
|
||||
@ -53,6 +55,7 @@ const GifSearch: FC<OwnProps & StateProps> = ({
|
||||
canScheduleUntilOnline,
|
||||
isSavedMessages,
|
||||
canPostInChat,
|
||||
currentMessageList,
|
||||
onClose,
|
||||
}) => {
|
||||
const {
|
||||
@ -74,19 +77,28 @@ const GifSearch: FC<OwnProps & StateProps> = ({
|
||||
|
||||
const handleGifClick = useCallback((gif: ApiVideo, isSilent?: boolean, shouldSchedule?: boolean) => {
|
||||
if (canSendGifs) {
|
||||
if (!currentMessageList) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (shouldSchedule) {
|
||||
requestCalendar((scheduledAt) => {
|
||||
sendMessage({ gif, scheduledAt, isSilent });
|
||||
sendMessage({
|
||||
messageList: currentMessageList,
|
||||
gif,
|
||||
scheduledAt,
|
||||
isSilent,
|
||||
});
|
||||
});
|
||||
} else {
|
||||
sendMessage({ gif, isSilent });
|
||||
sendMessage({ messageList: currentMessageList, gif, isSilent });
|
||||
}
|
||||
}
|
||||
|
||||
if (IS_TOUCH_ENV) {
|
||||
setGifSearchQuery({ query: undefined });
|
||||
}
|
||||
}, [canSendGifs, requestCalendar, sendMessage, setGifSearchQuery]);
|
||||
}, [canSendGifs, currentMessageList, requestCalendar]);
|
||||
|
||||
const handleSearchMoreGifs = useCallback(() => {
|
||||
searchMoreGifs();
|
||||
@ -167,6 +179,7 @@ export default memo(withGlobal(
|
||||
isSavedMessages,
|
||||
canPostInChat,
|
||||
canScheduleUntilOnline: Boolean(chatId) && selectCanScheduleUntilOnline(global, chatId),
|
||||
currentMessageList: selectCurrentMessageList(global),
|
||||
};
|
||||
},
|
||||
)(GifSearch));
|
||||
|
||||
@ -329,23 +329,20 @@ addActionHandler('switchBotInline', (global, actions, payload): ActionReturnType
|
||||
|
||||
addActionHandler('sendInlineBotResult', (global, actions, payload): ActionReturnType => {
|
||||
const {
|
||||
id, queryId, isSilent, scheduledAt,
|
||||
id, queryId, isSilent, scheduledAt, messageList,
|
||||
tabId = getCurrentTabId(),
|
||||
} = payload;
|
||||
const currentMessageList = selectCurrentMessageList(global, tabId);
|
||||
if (!currentMessageList || !id) {
|
||||
if (!id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { chatId, threadId } = currentMessageList;
|
||||
|
||||
const { chatId, threadId } = messageList;
|
||||
const chat = selectChat(global, chatId)!;
|
||||
const replyingTo = selectReplyingToId(global, chatId, threadId);
|
||||
let replyingToTopId: number | undefined;
|
||||
|
||||
if (replyingTo && threadId !== MAIN_THREAD_ID) {
|
||||
replyingToTopId = selectThreadTopMessageId(global, chatId, threadId)!;
|
||||
}
|
||||
const replyingToId = selectReplyingToId(global, chatId, threadId);
|
||||
const replyingToMessage = replyingToId ? selectChatMessage(global, chatId, replyingToId) : undefined;
|
||||
const replyingToTopId = (chat.isForum || threadId !== MAIN_THREAD_ID)
|
||||
? selectThreadTopMessageId(global, chatId, threadId)
|
||||
: replyingToMessage?.replyToTopMessageId || replyingToMessage?.replyToMessageId;
|
||||
|
||||
actions.setReplyingToId({ messageId: undefined, tabId });
|
||||
actions.clearWebPagePreview({ tabId });
|
||||
@ -354,7 +351,7 @@ addActionHandler('sendInlineBotResult', (global, actions, payload): ActionReturn
|
||||
chat,
|
||||
resultId: id,
|
||||
queryId,
|
||||
replyingTo,
|
||||
replyingTo: replyingToId || replyingToTopId,
|
||||
replyingToTopId,
|
||||
sendAs: selectSendAs(global, chatId),
|
||||
isSilent,
|
||||
|
||||
@ -235,14 +235,13 @@ addActionHandler('loadMessage', async (global, actions, payload): Promise<void>
|
||||
});
|
||||
|
||||
addActionHandler('sendMessage', (global, actions, payload): ActionReturnType => {
|
||||
const { tabId = getCurrentTabId() } = payload;
|
||||
const currentMessageList = selectCurrentMessageList(global, tabId);
|
||||
const { messageList, tabId = getCurrentTabId() } = payload;
|
||||
|
||||
if (!currentMessageList) {
|
||||
if (!messageList) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const { chatId, threadId, type } = currentMessageList;
|
||||
const { chatId, threadId, type } = messageList;
|
||||
|
||||
payload = omit(payload, ['tabId']);
|
||||
|
||||
@ -263,6 +262,7 @@ addActionHandler('sendMessage', (global, actions, payload): ActionReturnType =>
|
||||
const params = {
|
||||
...payload,
|
||||
chat,
|
||||
currentThreadId: messageList.threadId,
|
||||
replyingTo: replyingToId,
|
||||
replyingToTopId,
|
||||
noWebPage: selectNoWebPage(global, chatId, threadId),
|
||||
@ -280,7 +280,7 @@ addActionHandler('sendMessage', (global, actions, payload): ActionReturnType =>
|
||||
sendMessage(global, {
|
||||
...restParams,
|
||||
attachment: attachments ? attachments[0] : undefined,
|
||||
}, tabId);
|
||||
});
|
||||
} else if (isGrouped) {
|
||||
const {
|
||||
text, entities, attachments, ...commonParams
|
||||
@ -301,14 +301,14 @@ addActionHandler('sendMessage', (global, actions, payload): ActionReturnType =>
|
||||
entities: isFirst ? entities : undefined,
|
||||
attachment: firstAttachment,
|
||||
groupedId: restAttachments.length > 0 ? groupedId : undefined,
|
||||
}, tabId);
|
||||
});
|
||||
|
||||
restAttachments.forEach((attachment: ApiAttachment) => {
|
||||
sendMessage(global, {
|
||||
...commonParams,
|
||||
attachment,
|
||||
groupedId,
|
||||
}, tabId);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -323,14 +323,14 @@ addActionHandler('sendMessage', (global, actions, payload): ActionReturnType =>
|
||||
text,
|
||||
entities,
|
||||
replyingTo,
|
||||
}, tabId);
|
||||
});
|
||||
}
|
||||
|
||||
attachments?.forEach((attachment: ApiAttachment) => {
|
||||
sendMessage(global, {
|
||||
...commonParams,
|
||||
attachment,
|
||||
}, tabId);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -338,14 +338,15 @@ addActionHandler('sendMessage', (global, actions, payload): ActionReturnType =>
|
||||
});
|
||||
|
||||
addActionHandler('editMessage', (global, actions, payload): ActionReturnType => {
|
||||
const { text, entities, tabId = getCurrentTabId() } = payload;
|
||||
const {
|
||||
messageList, text, entities, tabId = getCurrentTabId(),
|
||||
} = payload;
|
||||
|
||||
const currentMessageList = selectCurrentMessageList(global, tabId);
|
||||
if (!currentMessageList) {
|
||||
if (!messageList) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { chatId, threadId, type: messageListType } = currentMessageList;
|
||||
const { chatId, threadId, type: messageListType } = messageList;
|
||||
const chat = selectChat(global, chatId);
|
||||
const message = selectEditingMessage(global, chatId, threadId, messageListType);
|
||||
if (!chat || !message) {
|
||||
@ -760,7 +761,9 @@ addActionHandler('loadExtendedMedia', (global, actions, payload): ActionReturnTy
|
||||
});
|
||||
|
||||
addActionHandler('forwardMessages', (global, actions, payload): ActionReturnType => {
|
||||
const { isSilent, scheduledAt, tabId = getCurrentTabId() } = payload;
|
||||
const {
|
||||
isSilent, scheduledAt, tabId = getCurrentTabId(),
|
||||
} = payload;
|
||||
|
||||
const {
|
||||
fromChatId, messageIds, toChatId, withMyScore, noAuthors, noCaptions, toThreadId,
|
||||
@ -806,6 +809,7 @@ addActionHandler('forwardMessages', (global, actions, payload): ActionReturnType
|
||||
void sendMessage(global, {
|
||||
chat: toChat,
|
||||
replyingToTopId: toThreadId,
|
||||
currentThreadId: toThreadId || MAIN_THREAD_ID,
|
||||
text,
|
||||
entities,
|
||||
sticker,
|
||||
@ -813,7 +817,7 @@ addActionHandler('forwardMessages', (global, actions, payload): ActionReturnType
|
||||
isSilent,
|
||||
scheduledAt,
|
||||
sendAs,
|
||||
}, tabId);
|
||||
});
|
||||
});
|
||||
|
||||
global = getGlobal();
|
||||
@ -1140,10 +1144,10 @@ async function sendMessage<T extends GlobalState>(global: T, params: {
|
||||
isSilent?: boolean;
|
||||
scheduledAt?: number;
|
||||
sendAs?: ApiChat | ApiUser;
|
||||
currentThreadId: number;
|
||||
replyingToTopId?: number;
|
||||
groupedId?: string;
|
||||
},
|
||||
...[tabId = getCurrentTabId()]: TabArgs<T>) {
|
||||
}) {
|
||||
let localId: number | undefined;
|
||||
const progressCallback = params.attachment ? (progress: number, messageLocalId: number) => {
|
||||
if (!uploadProgressCallbacks.has(messageLocalId)) {
|
||||
@ -1171,18 +1175,16 @@ async function sendMessage<T extends GlobalState>(global: T, params: {
|
||||
}
|
||||
|
||||
global = getGlobal();
|
||||
const currentMessageList = selectCurrentMessageList(global, tabId);
|
||||
if (!currentMessageList) {
|
||||
if (params.currentThreadId === undefined) {
|
||||
return;
|
||||
}
|
||||
const { threadId } = currentMessageList;
|
||||
|
||||
if (!params.replyingTo && threadId !== MAIN_THREAD_ID) {
|
||||
params.replyingTo = selectThreadTopMessageId(global, params.chat.id, threadId)!;
|
||||
if (!params.replyingTo && params.currentThreadId !== MAIN_THREAD_ID) {
|
||||
params.replyingTo = selectThreadTopMessageId(global, params.chat.id, params.currentThreadId)!;
|
||||
}
|
||||
|
||||
if (params.replyingTo && !params.replyingToTopId && threadId !== MAIN_THREAD_ID) {
|
||||
params.replyingToTopId = selectThreadTopMessageId(global, params.chat.id, threadId)!;
|
||||
if (params.replyingTo && !params.replyingToTopId && params.currentThreadId !== MAIN_THREAD_ID) {
|
||||
params.replyingToTopId = selectThreadTopMessageId(global, params.chat.id, params.currentThreadId)!;
|
||||
}
|
||||
|
||||
await callApi('sendMessage', params, progressCallback);
|
||||
|
||||
@ -1185,6 +1185,7 @@ export interface ActionPayloads {
|
||||
contact?: Partial<ApiContact>;
|
||||
shouldUpdateStickerSetOrder?: boolean;
|
||||
shouldGroupMessages?: boolean;
|
||||
messageList: MessageList;
|
||||
} & WithTabId;
|
||||
cancelSendingMessage: {
|
||||
chatId: string;
|
||||
@ -1216,6 +1217,7 @@ export interface ActionPayloads {
|
||||
};
|
||||
};
|
||||
editMessage: {
|
||||
messageList: MessageList;
|
||||
text: string;
|
||||
entities?: ApiMessageEntity[];
|
||||
} & WithTabId;
|
||||
@ -2067,6 +2069,7 @@ export interface ActionPayloads {
|
||||
sendInlineBotResult: {
|
||||
id: string;
|
||||
queryId: string;
|
||||
messageList: MessageList;
|
||||
isSilent?: boolean;
|
||||
scheduledAt?: number;
|
||||
} & WithTabId;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user