Sending icon is displayed in the inline keyboard callback button.

This commit is contained in:
John Preston 2016-04-06 21:02:22 +04:00
parent a728dcfca8
commit 1bc834bd5e
8 changed files with 111 additions and 54 deletions

View File

@ -38,29 +38,39 @@ namespace App {
if (MainWidget *m = main()) m->sendBotCommand(peer, cmd, replyTo);
}
void sendBotCallback(PeerData *peer, const QByteArray &data, MsgId replyTo) {
if (MainWidget *m = main()) m->sendBotCallback(peer, data, replyTo);
}
bool insertBotCommand(const QString &cmd, bool specialGif) {
if (MainWidget *m = main()) return m->insertBotCommand(cmd, specialGif);
return false;
}
void activateBotCommand(PeerData *peer, const HistoryMessageReplyMarkup::Button &button, MsgId replyTo) {
switch (button.type) {
void activateBotCommand(const HistoryItem *msg, int row, int col) {
const HistoryMessageReplyMarkup::Button *button = nullptr;
if (auto *markup = msg->Get<HistoryMessageReplyMarkup>()) {
if (row < markup->rows.size()) {
const HistoryMessageReplyMarkup::ButtonRow &buttonRow(markup->rows.at(row));
if (col < buttonRow.size()) {
button = &buttonRow.at(col);
}
}
}
if (!button) return;
switch (button->type) {
case HistoryMessageReplyMarkup::Button::Default: {
// copy string before passing it to the sending method
// the original button can be destroyed inside
sendBotCommand(peer, QString(button.text), replyTo);
// Copy string before passing it to the sending method
// because the original button can be destroyed inside.
MsgId replyTo = (msg->id > 0) ? msg->id : 0;
sendBotCommand(msg->history()->peer, QString(button->text), replyTo);
} break;
case HistoryMessageReplyMarkup::Button::Callback: {
sendBotCallback(peer, button.data, replyTo);
if (MainWidget *m = main()) {
m->app_sendBotCallback(button, msg, row, col);
}
} break;
case HistoryMessageReplyMarkup::Button::Url: {
auto url = QString::fromUtf8(button.data);
auto url = QString::fromUtf8(button->data);
HiddenUrlClickHandler(url).onClick(Qt::LeftButton);
} break;
@ -69,7 +79,7 @@ namespace App {
} break;
case HistoryMessageReplyMarkup::Button::RequestPhone: {
SharePhoneConfirmBox *box = new SharePhoneConfirmBox(peer);
SharePhoneConfirmBox *box = new SharePhoneConfirmBox(msg->history()->peer);
box->connect(box, SIGNAL(confirmed(PeerData*)), App::main(), SLOT(onSharePhoneWithBot(PeerData*)));
Ui::showLayer(box);
} break;

View File

@ -25,9 +25,8 @@ class LayeredWidget;
namespace App {
void sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyTo = 0);
void sendBotCallback(PeerData *peer, const QByteArray &data, MsgId replyTo);
bool insertBotCommand(const QString &cmd, bool specialGif = false);
void activateBotCommand(PeerData *peer, const HistoryMessageReplyMarkup::Button &button, MsgId replyTo = 0);
void activateBotCommand(const HistoryItem *msg, int row, int col);
void searchByHashtag(const QString &tag, PeerData *inPeer);
void openPeerByName(const QString &username, MsgId msgId = ShowAtUnreadMsgId, const QString &startToken = QString());
void joinGroupByHash(const QString &hash);

View File

@ -2753,19 +2753,6 @@ public:
_fullDisplayed = full;
}
protected:
void onClickImpl() const override {
if (auto button = getButton()) {
MsgId replyTo = (_item->id > 0) ? _item->id : 0;
App::activateBotCommand(_item->history()->peer, *button, replyTo);
}
}
private:
const HistoryItem *_item = nullptr;
int _row, _col;
bool _fullDisplayed = true;
// Finds the corresponding button in the items markup struct.
// If the button is not found it returns nullptr.
// Note: it is possible that we will point to the different button
@ -2782,6 +2769,16 @@ private:
return nullptr;
}
protected:
void onClickImpl() const override {
App::activateBotCommand(_item, _row, _col);
}
private:
const HistoryItem *_item = nullptr;
int _row, _col;
bool _fullDisplayed = true;
// Returns the full text of the corresponding button.
QString text() const {
if (auto button = getButton()) {
@ -2993,6 +2990,13 @@ void ReplyKeyboard::Style::paintButton(Painter &p, const ReplyKeyboard::Button &
paintButtonBg(p, rect, pressed, button.howMuchOver);
paintButtonIcon(p, rect, button.type);
if (button.type == HistoryMessageReplyMarkup::Button::Callback) {
if (const HistoryMessageReplyMarkup::Button *data = button.link->getButton()) {
if (data->requestId) {
paintButtonLoading(p, rect);
}
}
}
int tx = rect.x(), tw = rect.width();
if (tw > st::botKbFont->elidew + _st->padding * 2) {
@ -3024,21 +3028,21 @@ void HistoryMessageReplyMarkup::createFromButtonRows(const QVector<MTPKeyboardBu
for_const(const MTPKeyboardButton &button, b) {
switch (button.type()) {
case mtpc_keyboardButton: {
buttonRow.push_back({ Button::Default, qs(button.c_keyboardButton().vtext), QByteArray() });
buttonRow.push_back({ Button::Default, qs(button.c_keyboardButton().vtext), QByteArray(), 0 });
} break;
case mtpc_keyboardButtonCallback: {
const auto &buttonData(button.c_keyboardButtonCallback());
buttonRow.push_back({ Button::Callback, qs(buttonData.vtext), qba(buttonData.vdata) });
buttonRow.push_back({ Button::Callback, qs(buttonData.vtext), qba(buttonData.vdata), 0 });
} break;
case mtpc_keyboardButtonRequestGeoLocation: {
buttonRow.push_back({ Button::RequestLocation, qs(button.c_keyboardButtonRequestGeoLocation().vtext), QByteArray() });
buttonRow.push_back({ Button::RequestLocation, qs(button.c_keyboardButtonRequestGeoLocation().vtext), QByteArray(), 0 });
} break;
case mtpc_keyboardButtonRequestPhone: {
buttonRow.push_back({ Button::RequestPhone, qs(button.c_keyboardButtonRequestPhone().vtext), QByteArray() });
buttonRow.push_back({ Button::RequestPhone, qs(button.c_keyboardButtonRequestPhone().vtext), QByteArray(), 0 });
} break;
case mtpc_keyboardButtonUrl: {
const auto &buttonData(button.c_keyboardButtonUrl());
buttonRow.push_back({ Button::Url, qs(buttonData.vtext), qba(buttonData.vurl) });
buttonRow.push_back({ Button::Url, qs(buttonData.vtext), qba(buttonData.vurl), 0 });
} break;
}
}
@ -6628,7 +6632,6 @@ void HistoryMessage::KeyboardStyle::paintButtonIcon(Painter &p, const QRect &rec
style::sprite sprite;
switch (type) {
case HistoryMessageReplyMarkup::Button::Url: sprite = st::msgBotKbUrlIcon; break;
case HistoryMessageReplyMarkup::Button::Callback: sprite = st::msgBotKbCallbackIcon; break;
case HistoryMessageReplyMarkup::Button::RequestPhone: sprite = st::msgBotKbRequestPhoneIcon; break;
case HistoryMessageReplyMarkup::Button::RequestLocation: sprite = st::msgBotKbRequestLocationIcon; break;
}
@ -6637,13 +6640,18 @@ void HistoryMessage::KeyboardStyle::paintButtonIcon(Painter &p, const QRect &rec
}
}
void HistoryMessage::KeyboardStyle::paintButtonLoading(Painter &p, const QRect &rect) const {
style::sprite sprite = st::msgInvSendingImg;
p.drawSprite(rect.x() + rect.width() - sprite.pxWidth() - st::msgBotKbIconPadding, rect.y() + rect.height() - sprite.pxHeight() - st::msgBotKbIconPadding, sprite);
}
int HistoryMessage::KeyboardStyle::minButtonWidth(HistoryMessageReplyMarkup::Button::Type type) const {
int result = 2 * buttonPadding(), iconWidth = 0;
switch (type) {
case HistoryMessageReplyMarkup::Button::Url: iconWidth = st::msgBotKbUrlIcon.pxWidth(); break;
case HistoryMessageReplyMarkup::Button::Callback: iconWidth = st::msgBotKbCallbackIcon.pxWidth(); break;
case HistoryMessageReplyMarkup::Button::RequestPhone: iconWidth = st::msgBotKbRequestPhoneIcon.pxWidth(); break;
case HistoryMessageReplyMarkup::Button::RequestLocation: iconWidth = st::msgBotKbRequestLocationIcon.pxWidth(); break;
case HistoryMessageReplyMarkup::Button::Callback: iconWidth = st::msgInvSendingImg.pxWidth(); break;
}
if (iconWidth > 0) {
result = std::min(result, iconWidth + 2 * int(st::msgBotKbIconPadding));

View File

@ -1107,6 +1107,7 @@ struct HistoryMessageReplyMarkup : public BaseComponent<HistoryMessageReplyMarku
Type type;
QString text;
QByteArray data;
mutable mtpRequestId requestId;
};
using ButtonRow = QVector<Button>;
using ButtonRows = QVector<ButtonRow>;
@ -1150,6 +1151,7 @@ public:
protected:
virtual void paintButtonBg(Painter &p, const QRect &rect, bool pressed, float64 howMuchOver) const = 0;
virtual void paintButtonIcon(Painter &p, const QRect &rect, HistoryMessageReplyMarkup::Button::Type type) const = 0;
virtual void paintButtonLoading(Painter &p, const QRect &rect) const = 0;
virtual int minButtonWidth(HistoryMessageReplyMarkup::Button::Type type) const = 0;
private:
@ -2924,6 +2926,7 @@ private:
protected:
void paintButtonBg(Painter &p, const QRect &rect, bool down, float64 howMuchOver) const override;
void paintButtonIcon(Painter &p, const QRect &rect, HistoryMessageReplyMarkup::Button::Type type) const override;
void paintButtonLoading(Painter &p, const QRect &rect) const override;
int minButtonWidth(HistoryMessageReplyMarkup::Button::Type type) const override;
};

View File

@ -2174,12 +2174,15 @@ void BotKeyboard::Style::paintButtonBg(Painter &p, const QRect &rect, bool down,
}
void BotKeyboard::Style::paintButtonIcon(Painter &p, const QRect &rect, HistoryMessageReplyMarkup::Button::Type type) const {
// they should not appear here
// Buttons with icons should not appear here.
}
void BotKeyboard::Style::paintButtonLoading(Painter &p, const QRect &rect) const {
// Buttons with loading progress should not appear here.
}
int BotKeyboard::Style::minButtonWidth(HistoryMessageReplyMarkup::Button::Type type) const {
int result = 2 * buttonPadding();
// they should not appear here
return result;
}
@ -5161,7 +5164,9 @@ void HistoryWidget::sendBotCommand(PeerData *peer, const QString &cmd, MsgId rep
App::main()->sendMessage(_history, toSend, replyTo ? ((!_peer->isUser()/* && (botStatus == 0 || botStatus == 2)*/) ? replyTo : -1) : 0, false, false);
if (replyTo) {
cancelReply();
if (_replyToId == replyTo) {
cancelReply();
}
if (_keyboard.singleUse() && _keyboard.hasMarkup() && lastKeyboardUsed) {
if (_kbShown) onKbToggle(false);
_history->lastKeyboardUsed = true;
@ -5171,23 +5176,37 @@ void HistoryWidget::sendBotCommand(PeerData *peer, const QString &cmd, MsgId rep
_field.setFocus();
}
void HistoryWidget::sendBotCallback(PeerData *peer, const QByteArray &data, MsgId replyTo) {
if (!_peer || _peer != peer) return;
void HistoryWidget::app_sendBotCallback(const HistoryMessageReplyMarkup::Button *button, const HistoryItem *msg, int row, int col) {
if (msg->id < 0 || _peer != msg->history()->peer) {
return;
}
bool lastKeyboardUsed = (_keyboard.forMsgId() == FullMsgId(_channel, _history->lastKeyboardId)) && (_keyboard.forMsgId() == FullMsgId(_channel, replyTo));
bool lastKeyboardUsed = (_keyboard.forMsgId() == FullMsgId(_channel, _history->lastKeyboardId)) && (_keyboard.forMsgId() == FullMsgId(_channel, msg->id));
MTP::send(MTPmessages_GetBotCallbackAnswer(_peer->input, MTP_int(replyTo), MTP_bytes(data)), rpcDone(&HistoryWidget::botCallbackDone), rpcFail(&HistoryWidget::botCallbackFail));
BotCallbackInfo info = { msg->fullId(), row, col };
button->requestId = MTP::send(MTPmessages_GetBotCallbackAnswer(_peer->input, MTP_int(msg->id), MTP_bytes(button->data)), rpcDone(&HistoryWidget::botCallbackDone, info), rpcFail(&HistoryWidget::botCallbackFail, info));
Ui::repaintHistoryItem(msg);
if (replyTo) {
if (_replyToId == msg->id) {
cancelReply();
if (_keyboard.singleUse() && _keyboard.hasMarkup() && lastKeyboardUsed) {
if (_kbShown) onKbToggle(false);
_history->lastKeyboardUsed = true;
}
}
if (_keyboard.singleUse() && _keyboard.hasMarkup() && lastKeyboardUsed) {
if (_kbShown) onKbToggle(false);
_history->lastKeyboardUsed = true;
}
}
void HistoryWidget::botCallbackDone(const MTPmessages_BotCallbackAnswer &answer) {
void HistoryWidget::botCallbackDone(BotCallbackInfo info, const MTPmessages_BotCallbackAnswer &answer, mtpRequestId req) {
if (HistoryItem *item = App::histItemById(info.msgId)) {
if (auto *markup = item->Get<HistoryMessageReplyMarkup>()) {
if (info.row < markup->rows.size() && info.col < markup->rows.at(info.row).size()) {
if (markup->rows.at(info.row).at(info.col).requestId == req) {
markup->rows.at(info.row).at(info.col).requestId = 0;
Ui::repaintHistoryItem(item);
}
}
}
}
if (answer.type() == mtpc_messages_botCallbackAnswer) {
const auto &answerData(answer.c_messages_botCallbackAnswer());
if (answerData.has_message()) {
@ -5196,9 +5215,20 @@ void HistoryWidget::botCallbackDone(const MTPmessages_BotCallbackAnswer &answer)
}
}
bool HistoryWidget::botCallbackFail(const RPCError &error) {
bool HistoryWidget::botCallbackFail(BotCallbackInfo info, const RPCError &error, mtpRequestId req) {
if (mtpIsFlood(error)) return false;
if (HistoryItem *item = App::histItemById(info.msgId)) {
if (auto *markup = item->Get<HistoryMessageReplyMarkup>()) {
if (info.row < markup->rows.size() && info.col < markup->rows.at(info.row).size()) {
if (markup->rows.at(info.row).at(info.col).requestId == req) {
markup->rows.at(info.row).at(info.col).requestId = 0;
Ui::repaintHistoryItem(item);
}
}
}
}
return true;
}

View File

@ -374,6 +374,7 @@ private:
protected:
void paintButtonBg(Painter &p, const QRect &rect, bool down, float64 howMuchOver) const override;
void paintButtonIcon(Painter &p, const QRect &rect, HistoryMessageReplyMarkup::Button::Type type) const override;
void paintButtonLoading(Painter &p, const QRect &rect) const override;
int minButtonWidth(HistoryMessageReplyMarkup::Button::Type type) const override;
private:
@ -622,7 +623,6 @@ public:
void onListEscapePressed();
void sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyTo);
void sendBotCallback(PeerData *peer, const QByteArray &data, MsgId replyTo);
bool insertBotCommand(const QString &cmd, bool specialGif);
bool eventFilter(QObject *obj, QEvent *e) override;
@ -668,6 +668,8 @@ public:
bool isItemVisible(HistoryItem *item);
void app_sendBotCallback(const HistoryMessageReplyMarkup::Button *button, const HistoryItem *msg, int row, int col);
void ui_repaintHistoryItem(const HistoryItem *item);
void ui_repaintInlineItem(const InlineBots::Layout::ItemBase *gif);
bool ui_isInlineItemVisible(const InlineBots::Layout::ItemBase *layout);
@ -881,8 +883,12 @@ private:
void addMessagesToFront(PeerData *peer, const QVector<MTPMessage> &messages, const QVector<MTPMessageGroup> *collapsed);
void addMessagesToBack(PeerData *peer, const QVector<MTPMessage> &messages, const QVector<MTPMessageGroup> *collapsed);
void botCallbackDone(const MTPmessages_BotCallbackAnswer &answer);
bool botCallbackFail(const RPCError &error);
struct BotCallbackInfo {
FullMsgId msgId;
int row, col;
};
void botCallbackDone(BotCallbackInfo info, const MTPmessages_BotCallbackAnswer &answer, mtpRequestId req);
bool botCallbackFail(BotCallbackInfo info, const RPCError &error, mtpRequestId req);
enum ScrollChangeType {
ScrollChangeNone,

View File

@ -1524,8 +1524,8 @@ void MainWidget::sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyT
history.sendBotCommand(peer, cmd, replyTo);
}
void MainWidget::sendBotCallback(PeerData *peer, const QByteArray &data, MsgId replyTo) {
history.sendBotCallback(peer, data, replyTo);
void MainWidget::app_sendBotCallback(const HistoryMessageReplyMarkup::Button *button, const HistoryItem *msg, int row, int col) {
history.app_sendBotCallback(button, msg, row, col);
}
bool MainWidget::insertBotCommand(const QString &cmd, bool specialGif) {

View File

@ -352,7 +352,6 @@ public:
void stopAnimActive();
void sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyTo);
void sendBotCallback(PeerData *peer, const QByteArray &data, MsgId replyTo);
bool insertBotCommand(const QString &cmd, bool specialGif);
void searchMessages(const QString &query, PeerData *inPeer);
@ -442,6 +441,8 @@ public:
bool isItemVisible(HistoryItem *item);
void app_sendBotCallback(const HistoryMessageReplyMarkup::Button *button, const HistoryItem *msg, int row, int col);
void ui_repaintHistoryItem(const HistoryItem *item);
void ui_repaintInlineItem(const InlineBots::Layout::ItemBase *layout);
bool ui_isInlineItemVisible(const InlineBots::Layout::ItemBase *layout);