Message: Click on "via" bot username should prepend it into Message Input

This commit is contained in:
Alexander Zinchuk 2025-09-09 20:26:15 +02:00
parent 98212de7aa
commit 77449ad407
2 changed files with 47 additions and 30 deletions

View File

@ -1,7 +1,5 @@
import type { FC, TeactNode } from '../../lib/teact/teact'; import type { FC, TeactNode } from '../../lib/teact/teact';
import { import { memo, useEffect, useMemo, useRef, useSignal, useState } from '../../lib/teact/teact';
memo, useEffect, useMemo, useRef, useSignal, useState,
} from '../../lib/teact/teact';
import { getActions, getGlobal, withGlobal } from '../../global'; import { getActions, getGlobal, withGlobal } from '../../global';
import type { import type {
@ -32,9 +30,7 @@ import type {
ApiVideo, ApiVideo,
ApiWebPage, ApiWebPage,
} from '../../api/types'; } from '../../api/types';
import type { import type { GlobalState, TabState } from '../../global/types';
GlobalState, TabState,
} from '../../global/types';
import type { import type {
IAnchorPosition, IAnchorPosition,
InlineBotSettings, InlineBotSettings,
@ -559,13 +555,15 @@ const Composer: FC<OwnProps & StateProps> = ({
canSendStickers, canSendGifs, canAttachMedia, canAttachPolls, canAttachEmbedLinks, canAttachToDoLists, canSendStickers, canSendGifs, canAttachMedia, canAttachPolls, canAttachEmbedLinks, canAttachToDoLists,
canSendVoices, canSendPlainText, canSendAudios, canSendVideos, canSendPhotos, canSendDocuments, canSendVoices, canSendPlainText, canSendAudios, canSendVideos, canSendPhotos, canSendDocuments,
} = useMemo( } = useMemo(
() => getAllowedAttachmentOptions(chat, () => getAllowedAttachmentOptions(
chat,
chatFullInfo, chatFullInfo,
isChatWithBot, isChatWithBot,
isChatWithSelf, isChatWithSelf,
isInStoryViewer, isInStoryViewer,
paidMessagesStars, paidMessagesStars,
isInScheduledList), isInScheduledList,
),
[chat, chatFullInfo, isChatWithBot, isChatWithSelf, isInStoryViewer, paidMessagesStars, isInScheduledList], [chat, chatFullInfo, isChatWithBot, isChatWithSelf, isInStoryViewer, paidMessagesStars, isInScheduledList],
); );
@ -597,7 +595,9 @@ const Composer: FC<OwnProps & StateProps> = ({
} }
}, [hasWebPagePreview]); }, [hasWebPagePreview]);
const insertHtmlAndUpdateCursor = useLastCallback((newHtml: string, inInputId: string = editableInputId) => { const insertHtmlAndUpdateCursor = useLastCallback((
newHtml: string, inInputId: string = editableInputId, shouldPrepend = false,
) => {
if (inInputId === editableInputId && isComposerBlocked) return; if (inInputId === editableInputId && isComposerBlocked) return;
const selection = window.getSelection()!; const selection = window.getSelection()!;
let messageInput: HTMLDivElement; let messageInput: HTMLDivElement;
@ -607,7 +607,7 @@ const Composer: FC<OwnProps & StateProps> = ({
messageInput = document.getElementById(inInputId) as HTMLDivElement; messageInput = document.getElementById(inInputId) as HTMLDivElement;
} }
if (selection.rangeCount) { if (selection.rangeCount && !shouldPrepend) {
const selectionRange = selection.getRangeAt(0); const selectionRange = selection.getRangeAt(0);
if (isSelectionInsideInput(selectionRange, inInputId)) { if (isSelectionInsideInput(selectionRange, inInputId)) {
insertHtmlInSelection(newHtml); insertHtmlInSelection(newHtml);
@ -616,7 +616,7 @@ const Composer: FC<OwnProps & StateProps> = ({
} }
} }
setHtml(`${getHtml()}${newHtml}`); setHtml(!shouldPrepend ? `${getHtml()}${newHtml}` : `${newHtml}${getHtml()}`);
// If selection is outside of input, set cursor at the end of input // If selection is outside of input, set cursor at the end of input
requestNextMutation(() => { requestNextMutation(() => {
@ -634,10 +634,10 @@ const Composer: FC<OwnProps & StateProps> = ({
}); });
const insertFormattedTextAndUpdateCursor = useLastCallback(( const insertFormattedTextAndUpdateCursor = useLastCallback((
text: ApiFormattedText, inInputId: string = editableInputId, text: ApiFormattedText, inInputId: string = editableInputId, shouldPrepend = false,
) => { ) => {
const newHtml = getTextWithEntitiesAsHtml(text); const newHtml = getTextWithEntitiesAsHtml(text);
insertHtmlAndUpdateCursor(newHtml, inInputId); insertHtmlAndUpdateCursor(newHtml, inInputId, shouldPrepend);
}); });
const insertCustomEmojiAndUpdateCursor = useLastCallback((emoji: ApiSticker, inInputId: string = editableInputId) => { const insertCustomEmojiAndUpdateCursor = useLastCallback((emoji: ApiSticker, inInputId: string = editableInputId) => {
@ -1320,7 +1320,7 @@ const Composer: FC<OwnProps & StateProps> = ({
useEffect(() => { useEffect(() => {
if (requestedDraft) { if (requestedDraft) {
insertFormattedTextAndUpdateCursor(requestedDraft); insertFormattedTextAndUpdateCursor(requestedDraft, undefined, true);
resetOpenChatWithDraft(); resetOpenChatWithDraft();
requestNextMutation(() => { requestNextMutation(() => {
@ -1433,24 +1433,28 @@ const Composer: FC<OwnProps & StateProps> = ({
if (isInScheduledList || isScheduleRequested) { if (isInScheduledList || isScheduleRequested) {
requestCalendar((scheduledAt) => { requestCalendar((scheduledAt) => {
handleActionWithPaymentConfirmation(handleMessageSchedule, handleActionWithPaymentConfirmation(
handleMessageSchedule,
{ {
id: inlineResult.id, id: inlineResult.id,
queryId: inlineResult.queryId, queryId: inlineResult.queryId,
isSilent, isSilent,
}, },
scheduledAt, scheduledAt,
currentMessageList!); currentMessageList!,
);
}); });
} else { } else {
handleActionWithPaymentConfirmation(sendInlineBotResult, handleActionWithPaymentConfirmation(
sendInlineBotResult,
{ {
id: inlineResult.id, id: inlineResult.id,
queryId: inlineResult.queryId, queryId: inlineResult.queryId,
threadId, threadId,
chatId, chatId,
isSilent, isSilent,
}); },
);
} }
const messageInput = document.querySelector<HTMLDivElement>(editableInputCssSelector); const messageInput = document.querySelector<HTMLDivElement>(editableInputCssSelector);
@ -1846,10 +1850,12 @@ const Composer: FC<OwnProps & StateProps> = ({
const handleSendScheduledAttachments = useLastCallback( const handleSendScheduledAttachments = useLastCallback(
(sendCompressed: boolean, sendGrouped: boolean, isInvertedMedia?: true) => { (sendCompressed: boolean, sendGrouped: boolean, isInvertedMedia?: true) => {
requestCalendar((scheduledAt) => { requestCalendar((scheduledAt) => {
handleActionWithPaymentConfirmation(handleMessageSchedule, handleActionWithPaymentConfirmation(
handleMessageSchedule,
{ sendCompressed, sendGrouped, isInvertedMedia }, { sendCompressed, sendGrouped, isInvertedMedia },
scheduledAt, scheduledAt,
currentMessageList!); currentMessageList!,
);
}); });
}, },
); );
@ -1865,7 +1871,7 @@ const Composer: FC<OwnProps & StateProps> = ({
}); });
const handleStopEffect = useLastCallback(() => { const handleStopEffect = useLastCallback(() => {
hideEffectInComposer({ }); hideEffectInComposer({});
}); });
const onSend = useMemo(() => { const onSend = useMemo(() => {
@ -2006,8 +2012,16 @@ const Composer: FC<OwnProps & StateProps> = ({
</filter> </filter>
</defs> </defs>
<g fill="none" fill-rule="evenodd"> <g fill="none" fill-rule="evenodd">
<path d="M6 17H0V0c.193 2.84.876 5.767 2.05 8.782.904 2.325 2.446 4.485 4.625 6.48A1 1 0 016 17z" fill="#000" filter="url(#composerAppendix)" /> <path
<path d="M6 17H0V0c.193 2.84.876 5.767 2.05 8.782.904 2.325 2.446 4.485 4.625 6.48A1 1 0 016 17z" fill="#FFF" className="corner" /> d="M6 17H0V0c.193 2.84.876 5.767 2.05 8.782.904 2.325 2.446 4.485 4.625 6.48A1 1 0 016 17z"
fill="#000"
filter="url(#composerAppendix)"
/>
<path
d="M6 17H0V0c.193 2.84.876 5.767 2.05 8.782.904 2.325 2.446 4.485 4.625 6.48A1 1 0 016 17z"
fill="#FFF"
className="corner"
/>
</g> </g>
</svg> </svg>
)} )}

View File

@ -1,15 +1,12 @@
import { getActions } from '../../../../global'; import { getActions } from '../../../../global';
import type { import type { ApiMessage, ApiPeer, ApiStory, ApiTopic, ApiUser, ApiWebPage } from '../../../../api/types';
ApiMessage, ApiPeer, ApiStory, ApiTopic, ApiUser,
ApiWebPage,
} from '../../../../api/types';
import type { OldLangFn } from '../../../../hooks/useOldLang'; import type { OldLangFn } from '../../../../hooks/useOldLang';
import type { IAlbum, ThreadId } from '../../../../types'; import type { IAlbum, ThreadId } from '../../../../types';
import { MAIN_THREAD_ID } from '../../../../api/types'; import { MAIN_THREAD_ID } from '../../../../api/types';
import { MediaViewerOrigin } from '../../../../types'; import { MediaViewerOrigin } from '../../../../types';
import { getMessagePhoto, getWebPagePhoto, getWebPageVideo } from '../../../../global/helpers'; import { getMainUsername, getMessagePhoto, getWebPagePhoto, getWebPageVideo } from '../../../../global/helpers';
import { getMessageReplyInfo } from '../../../../global/helpers/replies'; import { getMessageReplyInfo } from '../../../../global/helpers/replies';
import { tryParseDeepLink } from '../../../../util/deepLinkParser'; import { tryParseDeepLink } from '../../../../util/deepLinkParser';
@ -58,7 +55,7 @@ export default function useInnerHandlers({
lastPlaybackTimestamp?: number; lastPlaybackTimestamp?: number;
}) { }) {
const { const {
openChat, showNotification, focusMessage, openMediaViewer, openAudioPlayer, openChat, openChatWithDraft, showNotification, focusMessage, openMediaViewer, openAudioPlayer,
markMessagesRead, cancelUploadMedia, sendPollVote, openForwardMenu, markMessagesRead, cancelUploadMedia, sendPollVote, openForwardMenu,
openChatLanguageModal, openThread, openStoryViewer, searchChatMediaMessages, openChatLanguageModal, openThread, openStoryViewer, searchChatMediaMessages,
} = getActions(); } = getActions();
@ -90,7 +87,13 @@ export default function useInnerHandlers({
return; return;
} }
openChat({ id: botSender.id }); openChatWithDraft({
chatId,
threadId,
text: {
text: `@${getMainUsername(botSender)} `,
},
});
}); });
const handleReplyClick = useLastCallback((): void => { const handleReplyClick = useLastCallback((): void => {