Inline Buttons: Support "Request Contact" (#1635)

This commit is contained in:
Alexander Zinchuk 2022-01-13 01:11:54 +01:00
parent 23d1dc6d48
commit 9e8ebe8b1c
6 changed files with 69 additions and 9 deletions

View File

@ -820,6 +820,8 @@ function buildReplyButtons(message: UniversalMessage): ApiReplyKeyboard | undefi
value = serializeBytes(button.data);
} else if (button instanceof GramJs.KeyboardButtonRequestPoll) {
type = 'requestPoll';
} else if (button instanceof GramJs.KeyboardButtonRequestPhone) {
type = 'requestSelfContact';
} else if (button instanceof GramJs.KeyboardButtonBuy) {
if (media instanceof GramJs.MessageMediaInvoice && media.receiptMsgId) {
text = 'PaymentReceipt';
@ -871,6 +873,7 @@ export function buildLocalMessage(
sticker?: ApiSticker,
gif?: ApiVideo,
poll?: ApiNewPoll,
contact?: ApiContact,
groupedId?: string,
scheduledAt?: number,
sendAs?: ApiChat | ApiUser,
@ -894,6 +897,7 @@ export function buildLocalMessage(
...(sticker && { sticker }),
...(gif && { video: gif }),
...(poll && buildNewPoll(poll, localId)),
...(contact && { contact }),
},
date: scheduledAt || Math.round(Date.now() / 1000) + serverTimeOffset,
isOutgoing: !isChannel,

View File

@ -18,6 +18,7 @@ import {
ApiReportReason,
ApiSponsoredMessage,
ApiSendMessageAction,
ApiContact,
} from '../../types';
import {
@ -201,6 +202,7 @@ export function sendMessage(
sticker,
gif,
poll,
contact,
isSilent,
scheduledAt,
groupedId,
@ -216,6 +218,7 @@ export function sendMessage(
sticker?: ApiSticker;
gif?: ApiVideo;
poll?: ApiNewPoll;
contact?: ApiContact;
isSilent?: boolean;
scheduledAt?: number;
groupedId?: string;
@ -226,7 +229,7 @@ export function sendMessage(
onProgress?: ApiOnProgress,
) {
const localMessage = buildLocalMessage(
chat, text, entities, replyingTo, attachment, sticker, gif, poll, groupedId, scheduledAt,
chat, text, entities, replyingTo, attachment, sticker, gif, poll, contact, groupedId, scheduledAt,
sendAs, serverTimeOffset,
);
onUpdate({
@ -280,6 +283,13 @@ export function sendMessage(
media = buildInputMediaDocument(gif);
} else if (poll) {
media = buildInputPoll(poll, randomId);
} else if (contact) {
media = new GramJs.InputMediaContact({
phoneNumber: contact.phoneNumber,
firstName: contact.firstName,
lastName: contact.lastName,
vcard: '',
});
}
await prevQueue;

View File

@ -296,7 +296,7 @@ export type ApiSponsoredMessage = {
};
export interface ApiKeyboardButton {
type: 'command' | 'url' | 'callback' | 'requestPoll' | 'buy' | 'NOT_SUPPORTED';
type: 'command' | 'url' | 'callback' | 'requestPoll' | 'requestSelfContact' | 'buy' | 'NOT_SUPPORTED';
text: string;
messageId: number;
value?: string;

View File

@ -1,7 +1,9 @@
import React, { FC, memo, useEffect } from '../../lib/teact/teact';
import { getDispatch, withGlobal } from '../../lib/teact/teactn';
import { ApiError, ApiInviteInfo, ApiPhoto } from '../../api/types';
import {
ApiContact, ApiError, ApiInviteInfo, ApiPhoto,
} from '../../api/types';
import getReadableErrorText from '../../util/getReadableErrorText';
import { pick } from '../../util/iteratees';
@ -20,7 +22,7 @@ type StateProps = {
};
const Dialogs: FC<StateProps> = ({ dialogs }) => {
const { dismissDialog, acceptInviteConfirmation } = getDispatch();
const { dismissDialog, acceptInviteConfirmation, sendMessage } = getDispatch();
const [isModalOpen, openModal, closeModal] = useFlag();
const lang = useLang();
@ -94,6 +96,31 @@ const Dialogs: FC<StateProps> = ({ dialogs }) => {
);
};
const renderContactRequest = (contactRequest: ApiContact) => {
const handleConfirm = () => {
sendMessage({
contact: pick(contactRequest, ['firstName', 'lastName', 'phoneNumber']),
});
closeModal();
};
return (
<Modal
isOpen={isModalOpen}
onClose={closeModal}
className="confirm"
title={lang('ShareYouPhoneNumberTitle')}
onCloseAnimationEnd={dismissDialog}
>
{lang('AreYouSureShareMyContactInfoBot')}
<div>
<Button className="confirm-dialog-button" isText onClick={handleConfirm}>{lang('OK')}</Button>
<Button className="confirm-dialog-button" isText onClick={closeModal}>{lang('Cancel')}</Button>
</div>
</Modal>
);
};
const renderError = (error: ApiError) => {
return (
<Modal
@ -111,11 +138,15 @@ const Dialogs: FC<StateProps> = ({ dialogs }) => {
);
};
const renderDialog = (dialog: ApiError | ApiInviteInfo) => {
const renderDialog = (dialog: ApiError | ApiInviteInfo | ApiContact) => {
if ('hash' in dialog) {
return renderInvite(dialog);
}
if ('phoneNumber' in dialog) {
return renderContactRequest(dialog);
}
return renderError(dialog);
};

View File

@ -2,7 +2,7 @@ import {
addReducer, getDispatch, getGlobal, setGlobal,
} from '../../../lib/teact/teactn';
import { ApiChat, ApiUser } from '../../../api/types';
import { ApiChat, ApiContact, ApiUser } from '../../../api/types';
import { InlineBotSettings } from '../../../types';
import {
@ -48,6 +48,21 @@ addReducer('clickInlineButton', (global, actions, payload) => {
case 'requestPoll':
actions.openPollModal();
break;
case 'requestSelfContact': {
const user = global.currentUserId ? selectUser(global, global.currentUserId) : undefined;
if (!user) {
return;
}
actions.showDialog({
data: {
phoneNumber: user.phoneNumber,
firstName: user.firstName,
lastName: user.lastName,
userId: user.id,
} as ApiContact,
});
break;
}
case 'buy': {
const chat = selectCurrentChat(global);
const { messageId, value } = button;

View File

@ -199,9 +199,6 @@ addReducer('sendMessage', (global, actions, payload) => {
const chat = selectChat(global, chatId)!;
actions.setReplyingToId({ messageId: undefined });
actions.clearWebPagePreview({ chatId, threadId, value: false });
const params = {
...payload,
chat,
@ -210,6 +207,9 @@ addReducer('sendMessage', (global, actions, payload) => {
sendAs: selectSendAs(global, chatId),
};
actions.setReplyingToId({ messageId: undefined });
actions.clearWebPagePreview({ chatId, threadId, value: false });
const isSingle = !payload.attachments || payload.attachments.length <= 1;
const isGrouped = !isSingle && payload.attachments && payload.attachments.length > 1;