Composer: Bot keyboard should open automatically (#1372)
This commit is contained in:
parent
3635d312ce
commit
fbb401dac9
@ -16,7 +16,7 @@ import {
|
|||||||
ApiWebPage,
|
ApiWebPage,
|
||||||
ApiMessageEntity,
|
ApiMessageEntity,
|
||||||
ApiFormattedText,
|
ApiFormattedText,
|
||||||
ApiKeyboardButtons,
|
ApiReplyKeyboard,
|
||||||
ApiKeyboardButton,
|
ApiKeyboardButton,
|
||||||
ApiChat,
|
ApiChat,
|
||||||
ApiThreadInfo,
|
ApiThreadInfo,
|
||||||
@ -138,7 +138,9 @@ export function buildApiMessageWithChatId(chatId: number, mtpMessage: UniversalM
|
|||||||
|
|
||||||
const { replyToMsgId, replyToTopId } = mtpMessage.replyTo || {};
|
const { replyToMsgId, replyToTopId } = mtpMessage.replyTo || {};
|
||||||
const isEdited = mtpMessage.editDate && !mtpMessage.editHide;
|
const isEdited = mtpMessage.editDate && !mtpMessage.editHide;
|
||||||
const { inlineButtons, keyboardButtons } = buildReplyButtons(mtpMessage) || {};
|
const {
|
||||||
|
inlineButtons, keyboardButtons, keyboardPlaceholder, isKeyboardSingleUse,
|
||||||
|
} = buildReplyButtons(mtpMessage) || {};
|
||||||
const forwardInfo = mtpMessage.fwdFrom && buildApiMessageForwardInfo(mtpMessage.fwdFrom, isChatWithSelf);
|
const forwardInfo = mtpMessage.fwdFrom && buildApiMessageForwardInfo(mtpMessage.fwdFrom, isChatWithSelf);
|
||||||
const { replies, mediaUnread: isMediaUnread, postAuthor } = mtpMessage;
|
const { replies, mediaUnread: isMediaUnread, postAuthor } = mtpMessage;
|
||||||
const groupedId = mtpMessage.groupedId && mtpMessage.groupedId.toString();
|
const groupedId = mtpMessage.groupedId && mtpMessage.groupedId.toString();
|
||||||
@ -165,7 +167,7 @@ export function buildApiMessageWithChatId(chatId: number, mtpMessage: UniversalM
|
|||||||
isInAlbum,
|
isInAlbum,
|
||||||
}),
|
}),
|
||||||
inlineButtons,
|
inlineButtons,
|
||||||
...(keyboardButtons && { keyboardButtons }),
|
...(keyboardButtons && { keyboardButtons, keyboardPlaceholder, isKeyboardSingleUse }),
|
||||||
...(shouldHideKeyboardButtons && { shouldHideKeyboardButtons }),
|
...(shouldHideKeyboardButtons && { shouldHideKeyboardButtons }),
|
||||||
...(mtpMessage.viaBotId && { viaBotId: mtpMessage.viaBotId }),
|
...(mtpMessage.viaBotId && { viaBotId: mtpMessage.viaBotId }),
|
||||||
...(replies && replies.comments && { threadInfo: buildThreadInfo(replies, mtpMessage.id, chatId) }),
|
...(replies && replies.comments && { threadInfo: buildThreadInfo(replies, mtpMessage.id, chatId) }),
|
||||||
@ -693,9 +695,7 @@ function buildAction(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildReplyButtons(message: UniversalMessage): {
|
function buildReplyButtons(message: UniversalMessage): ApiReplyKeyboard | undefined {
|
||||||
[K in 'inlineButtons' | 'keyboardButtons']?: ApiKeyboardButtons
|
|
||||||
} | undefined {
|
|
||||||
const { id: messageId, replyMarkup, media } = message;
|
const { id: messageId, replyMarkup, media } = message;
|
||||||
|
|
||||||
if (!replyMarkup) {
|
if (!replyMarkup) {
|
||||||
@ -756,7 +756,13 @@ function buildReplyButtons(message: UniversalMessage): {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
return { [replyMarkup instanceof GramJs.ReplyKeyboardMarkup ? 'keyboardButtons' : 'inlineButtons']: markup };
|
return {
|
||||||
|
[replyMarkup instanceof GramJs.ReplyKeyboardMarkup ? 'keyboardButtons' : 'inlineButtons']: markup,
|
||||||
|
...(replyMarkup instanceof GramJs.ReplyKeyboardMarkup && {
|
||||||
|
keyboardPlaceholder: replyMarkup.placeholder,
|
||||||
|
isKeyboardSingleUse: replyMarkup.singleUse,
|
||||||
|
}),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFilenameFromDocument(document: GramJs.Document, defaultBase = 'file') {
|
function getFilenameFromDocument(document: GramJs.Document, defaultBase = 'file') {
|
||||||
|
|||||||
@ -243,6 +243,8 @@ export interface ApiMessage {
|
|||||||
hasUnreadMention?: boolean;
|
hasUnreadMention?: boolean;
|
||||||
inlineButtons?: ApiKeyboardButtons;
|
inlineButtons?: ApiKeyboardButtons;
|
||||||
keyboardButtons?: ApiKeyboardButtons;
|
keyboardButtons?: ApiKeyboardButtons;
|
||||||
|
keyboardPlaceholder?: string;
|
||||||
|
isKeyboardSingleUse?: boolean;
|
||||||
viaBotId?: number;
|
viaBotId?: number;
|
||||||
threadInfo?: ApiThreadInfo;
|
threadInfo?: ApiThreadInfo;
|
||||||
adminTitle?: string;
|
adminTitle?: string;
|
||||||
@ -272,6 +274,12 @@ export interface ApiKeyboardButton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type ApiKeyboardButtons = ApiKeyboardButton[][];
|
export type ApiKeyboardButtons = ApiKeyboardButton[][];
|
||||||
|
export type ApiReplyKeyboard = {
|
||||||
|
keyboardPlaceholder?: string;
|
||||||
|
isKeyboardSingleUse?: boolean;
|
||||||
|
} & {
|
||||||
|
[K in 'inlineButtons' | 'keyboardButtons']?: ApiKeyboardButtons;
|
||||||
|
};
|
||||||
|
|
||||||
export type ApiMessageSearchType = 'text' | 'media' | 'documents' | 'links' | 'audio' | 'profilePhoto';
|
export type ApiMessageSearchType = 'text' | 'media' | 'documents' | 'links' | 'audio' | 'profilePhoto';
|
||||||
export type ApiGlobalMessageSearchType = 'text' | 'media' | 'documents' | 'links' | 'audio' | 'voice';
|
export type ApiGlobalMessageSearchType = 'text' | 'media' | 'documents' | 'links' | 'audio' | 'voice';
|
||||||
|
|||||||
@ -31,7 +31,6 @@ export { default as SymbolMenu } from '../components/middle/composer/SymbolMenu'
|
|||||||
export { default as AttachMenu } from '../components/middle/composer/AttachMenu';
|
export { default as AttachMenu } from '../components/middle/composer/AttachMenu';
|
||||||
export { default as MentionTooltip } from '../components/middle/composer/MentionTooltip';
|
export { default as MentionTooltip } from '../components/middle/composer/MentionTooltip';
|
||||||
export { default as StickerTooltip } from '../components/middle/composer/StickerTooltip';
|
export { default as StickerTooltip } from '../components/middle/composer/StickerTooltip';
|
||||||
export { default as BotKeyboardMenu } from '../components/middle/composer/BotKeyboardMenu';
|
|
||||||
export { default as CustomSendMenu } from '../components/middle/composer/CustomSendMenu';
|
export { default as CustomSendMenu } from '../components/middle/composer/CustomSendMenu';
|
||||||
export { default as DropArea } from '../components/middle/composer/DropArea';
|
export { default as DropArea } from '../components/middle/composer/DropArea';
|
||||||
export { default as TextFormatter } from '../components/middle/composer/TextFormatter';
|
export { default as TextFormatter } from '../components/middle/composer/TextFormatter';
|
||||||
|
|||||||
@ -1,15 +0,0 @@
|
|||||||
import React, { FC, memo } from '../../../lib/teact/teact';
|
|
||||||
import { OwnProps } from './BotKeyboardMenu';
|
|
||||||
import { Bundles } from '../../../util/moduleLoader';
|
|
||||||
|
|
||||||
import useModuleLoader from '../../../hooks/useModuleLoader';
|
|
||||||
|
|
||||||
const BotKeyboardMenuAsync: FC<OwnProps> = (props) => {
|
|
||||||
const { isOpen } = props;
|
|
||||||
const BotKeyboardMenu = useModuleLoader(Bundles.Extra, 'BotKeyboardMenu', !isOpen);
|
|
||||||
|
|
||||||
// eslint-disable-next-line react/jsx-props-no-spreading
|
|
||||||
return BotKeyboardMenu ? <BotKeyboardMenu {...props} /> : undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default memo(BotKeyboardMenuAsync);
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
.KeyboardMenu {
|
.BotKeyboardMenu {
|
||||||
.bubble {
|
.bubble {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
max-width: 27rem;
|
max-width: 27rem;
|
||||||
@ -40,6 +40,7 @@
|
|||||||
&:hover {
|
&:hover {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
border-color: var(--color-primary-shade);
|
border-color: var(--color-primary-shade);
|
||||||
|
background: var(--color-primary-shade);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import React, { FC, memo } from '../../../lib/teact/teact';
|
import React, { FC, memo, useEffect } from '../../../lib/teact/teact';
|
||||||
import { withGlobal } from '../../../lib/teact/teactn';
|
import { withGlobal } from '../../../lib/teact/teactn';
|
||||||
|
|
||||||
import { GlobalActions } from '../../../global/types';
|
import { GlobalActions } from '../../../global/types';
|
||||||
@ -8,6 +8,7 @@ import { IS_TOUCH_ENV } from '../../../util/environment';
|
|||||||
import { pick } from '../../../util/iteratees';
|
import { pick } from '../../../util/iteratees';
|
||||||
import { selectChatMessage, selectCurrentMessageList } from '../../../modules/selectors';
|
import { selectChatMessage, selectCurrentMessageList } from '../../../modules/selectors';
|
||||||
import useMouseInside from '../../../hooks/useMouseInside';
|
import useMouseInside from '../../../hooks/useMouseInside';
|
||||||
|
import useFlag from '../../../hooks/useFlag';
|
||||||
|
|
||||||
import Menu from '../../ui/Menu';
|
import Menu from '../../ui/Menu';
|
||||||
import Button from '../../ui/Button';
|
import Button from '../../ui/Button';
|
||||||
@ -30,6 +31,17 @@ const BotKeyboardMenu: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
isOpen, message, onClose, clickInlineButton,
|
isOpen, message, onClose, clickInlineButton,
|
||||||
}) => {
|
}) => {
|
||||||
const [handleMouseEnter, handleMouseLeave] = useMouseInside(isOpen, onClose);
|
const [handleMouseEnter, handleMouseLeave] = useMouseInside(isOpen, onClose);
|
||||||
|
const { isKeyboardSingleUse } = message || {};
|
||||||
|
const [forceOpen, markForceOpen, unmarkForceOpen] = useFlag(true);
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
unmarkForceOpen();
|
||||||
|
onClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
markForceOpen();
|
||||||
|
}, [markForceOpen, message]);
|
||||||
|
|
||||||
if (!message || !message.keyboardButtons) {
|
if (!message || !message.keyboardButtons) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -37,16 +49,15 @@ const BotKeyboardMenu: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Menu
|
<Menu
|
||||||
isOpen={isOpen}
|
isOpen={isOpen || forceOpen}
|
||||||
autoClose
|
autoClose={isKeyboardSingleUse}
|
||||||
positionX="right"
|
positionX="right"
|
||||||
positionY="bottom"
|
positionY="bottom"
|
||||||
onClose={onClose}
|
onClose={handleClose}
|
||||||
className="KeyboardMenu"
|
className="BotKeyboardMenu"
|
||||||
onCloseAnimationEnd={onClose}
|
onCloseAnimationEnd={handleClose}
|
||||||
onMouseEnter={!IS_TOUCH_ENV ? handleMouseEnter : undefined}
|
onMouseEnter={!IS_TOUCH_ENV ? handleMouseEnter : undefined}
|
||||||
onMouseLeave={!IS_TOUCH_ENV ? handleMouseLeave : undefined}
|
onMouseLeave={!IS_TOUCH_ENV ? handleMouseLeave : undefined}
|
||||||
noCloseOnBackdrop={!IS_TOUCH_ENV}
|
|
||||||
>
|
>
|
||||||
<div className="content">
|
<div className="content">
|
||||||
{message.keyboardButtons.map((row) => (
|
{message.keyboardButtons.map((row) => (
|
||||||
|
|||||||
@ -33,6 +33,7 @@ import {
|
|||||||
selectEditingMessage,
|
selectEditingMessage,
|
||||||
selectIsChatWithSelf,
|
selectIsChatWithSelf,
|
||||||
selectChatUser,
|
selectChatUser,
|
||||||
|
selectChatMessage,
|
||||||
} from '../../../modules/selectors';
|
} from '../../../modules/selectors';
|
||||||
import {
|
import {
|
||||||
getAllowedAttachmentOptions,
|
getAllowedAttachmentOptions,
|
||||||
@ -77,7 +78,7 @@ import MentionTooltip from './MentionTooltip.async';
|
|||||||
import CustomSendMenu from './CustomSendMenu.async';
|
import CustomSendMenu from './CustomSendMenu.async';
|
||||||
import StickerTooltip from './StickerTooltip.async';
|
import StickerTooltip from './StickerTooltip.async';
|
||||||
import EmojiTooltip from './EmojiTooltip.async';
|
import EmojiTooltip from './EmojiTooltip.async';
|
||||||
import BotKeyboardMenu from './BotKeyboardMenu.async';
|
import BotKeyboardMenu from './BotKeyboardMenu';
|
||||||
import MessageInput from './MessageInput';
|
import MessageInput from './MessageInput';
|
||||||
import ComposerEmbeddedMessage from './ComposerEmbeddedMessage';
|
import ComposerEmbeddedMessage from './ComposerEmbeddedMessage';
|
||||||
import AttachmentModal from './AttachmentModal.async';
|
import AttachmentModal from './AttachmentModal.async';
|
||||||
@ -113,6 +114,7 @@ type StateProps = {
|
|||||||
isPaymentModalOpen?: boolean;
|
isPaymentModalOpen?: boolean;
|
||||||
isReceiptModalOpen?: boolean;
|
isReceiptModalOpen?: boolean;
|
||||||
botKeyboardMessageId?: number;
|
botKeyboardMessageId?: number;
|
||||||
|
botKeyboardPlaceholder?: string;
|
||||||
withScheduledButton?: boolean;
|
withScheduledButton?: boolean;
|
||||||
shouldSchedule?: boolean;
|
shouldSchedule?: boolean;
|
||||||
canScheduleUntilOnline?: boolean;
|
canScheduleUntilOnline?: boolean;
|
||||||
@ -178,6 +180,7 @@ const Composer: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
isPaymentModalOpen,
|
isPaymentModalOpen,
|
||||||
isReceiptModalOpen,
|
isReceiptModalOpen,
|
||||||
botKeyboardMessageId,
|
botKeyboardMessageId,
|
||||||
|
botKeyboardPlaceholder,
|
||||||
withScheduledButton,
|
withScheduledButton,
|
||||||
stickersForEmoji,
|
stickersForEmoji,
|
||||||
groupChatMembers,
|
groupChatMembers,
|
||||||
@ -851,7 +854,9 @@ const Composer: FC<OwnProps & StateProps & DispatchProps> = ({
|
|||||||
id="message-input-text"
|
id="message-input-text"
|
||||||
html={!attachments.length ? html : ''}
|
html={!attachments.length ? html : ''}
|
||||||
placeholder={
|
placeholder={
|
||||||
activeVoiceRecording && windowWidth <= SCREEN_WIDTH_TO_HIDE_PLACEHOLDER ? '' : lang('Message')
|
activeVoiceRecording && windowWidth <= SCREEN_WIDTH_TO_HIDE_PLACEHOLDER
|
||||||
|
? ''
|
||||||
|
: botKeyboardPlaceholder || lang('Message')
|
||||||
}
|
}
|
||||||
forcedPlaceholder={inlineBotHelp}
|
forcedPlaceholder={inlineBotHelp}
|
||||||
shouldSetFocus={isSymbolMenuOpen}
|
shouldSetFocus={isSymbolMenuOpen}
|
||||||
@ -1006,6 +1011,8 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
const { language } = global.settings.byKey;
|
const { language } = global.settings.byKey;
|
||||||
const baseEmojiKeywords = global.emojiKeywords[BASE_EMOJI_KEYWORD_LANG];
|
const baseEmojiKeywords = global.emojiKeywords[BASE_EMOJI_KEYWORD_LANG];
|
||||||
const emojiKeywords = language !== BASE_EMOJI_KEYWORD_LANG ? global.emojiKeywords[language] : undefined;
|
const emojiKeywords = language !== BASE_EMOJI_KEYWORD_LANG ? global.emojiKeywords[language] : undefined;
|
||||||
|
const botKeyboardMessageId = messageWithActualBotKeyboard ? messageWithActualBotKeyboard.id : undefined;
|
||||||
|
const keyboardMessage = botKeyboardMessageId ? selectChatMessage(global, chatId, botKeyboardMessageId) : undefined;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
editingMessage: selectEditingMessage(global, chatId, threadId, messageListType),
|
editingMessage: selectEditingMessage(global, chatId, threadId, messageListType),
|
||||||
@ -1026,7 +1033,8 @@ export default memo(withGlobal<OwnProps>(
|
|||||||
&& Boolean(scheduledIds && scheduledIds.length)
|
&& Boolean(scheduledIds && scheduledIds.length)
|
||||||
),
|
),
|
||||||
shouldSchedule: messageListType === 'scheduled',
|
shouldSchedule: messageListType === 'scheduled',
|
||||||
botKeyboardMessageId: messageWithActualBotKeyboard ? messageWithActualBotKeyboard.id : undefined,
|
botKeyboardMessageId,
|
||||||
|
botKeyboardPlaceholder: keyboardMessage ? keyboardMessage.keyboardPlaceholder : undefined,
|
||||||
isForwarding: chatId === global.forwardMessages.toChatId,
|
isForwarding: chatId === global.forwardMessages.toChatId,
|
||||||
isPollModalOpen: global.isPollModalOpen,
|
isPollModalOpen: global.isPollModalOpen,
|
||||||
stickersForEmoji: global.stickers.forEmoji.stickers,
|
stickersForEmoji: global.stickers.forEmoji.stickers,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user