Fixed crash with forbidden megagroup in App::feedChats.

ReplyMarkupClickHandler holds FullMsgId instead of HistoryItem*.
This commit is contained in:
John Preston 2016-06-15 08:36:59 +03:00
parent 893cd9e877
commit 021c8896c8
3 changed files with 43 additions and 12 deletions

View File

@ -685,7 +685,6 @@ namespace {
cdata->inputChannel = MTP_inputChannel(d.vid, d.vaccess_hash);
cdata->access = d.vaccess_hash.v;
cdata->date = d.vdate.v;
cdata->flags = d.vflags.v;
if (cdata->version < d.vversion.v) {
cdata->version = d.vversion.v;
}
@ -694,12 +693,14 @@ namespace {
} else {
cdata->setRestrictionReason(QString());
}
cdata->flags = d.vflags.v;
}
cdata->flagsUpdated();
QString uname = d.has_username() ? textOneLine(qs(d.vusername)) : QString();
cdata->setName(qs(d.vtitle), uname);
cdata->isForbidden = false;
cdata->flagsUpdated();
cdata->setPhoto(d.vphoto);
if (wasInChannel != cdata->amIn()) update.flags |= UpdateFlag::ChannelAmIn;
@ -731,6 +732,7 @@ namespace {
auto mask = mtpCastFlags(MTPDchannelForbidden::Flag::f_broadcast | MTPDchannelForbidden::Flag::f_megagroup);
cdata->flags = (cdata->flags & ~mask) | (mtpCastFlags(d.vflags) & mask);
cdata->flagsUpdated();
cdata->setName(qs(d.vtitle), QString());
@ -739,7 +741,6 @@ namespace {
cdata->date = 0;
cdata->setMembersCount(0);
cdata->isForbidden = true;
cdata->flagsUpdated();
if (wasInChannel != cdata->amIn()) update.flags |= UpdateFlag::ChannelAmIn;
if (canEditPhoto != cdata->canEditPhoto()) update.flags |= UpdateFlag::ChannelCanEditPhoto;

View File

@ -2180,7 +2180,7 @@ void HistoryBlock::removeItem(HistoryItem *item) {
class ReplyMarkupClickHandler : public LeftButtonClickHandler {
public:
ReplyMarkupClickHandler(const HistoryItem *item, int row, int col) : _item(item), _row(row), _col(col) {
ReplyMarkupClickHandler(const HistoryItem *item, int row, int col) : _itemId(item->fullId()), _row(row), _col(col) {
}
QString tooltip() const override {
@ -2216,24 +2216,34 @@ public:
// Note: it is possible that we will point to the different button
// than the one was used when constructing the handler, but not a big deal.
const HistoryMessageReplyMarkup::Button *getButton() const {
if (auto markup = _item->Get<HistoryMessageReplyMarkup>()) {
if (_row < markup->rows.size()) {
const HistoryMessageReplyMarkup::ButtonRow &row(markup->rows.at(_row));
if (_col < row.size()) {
return &row.at(_col);
if (auto item = App::histItemById(_itemId)) {
if (auto markup = item->Get<HistoryMessageReplyMarkup>()) {
if (_row < markup->rows.size()) {
const HistoryMessageReplyMarkup::ButtonRow &row(markup->rows.at(_row));
if (_col < row.size()) {
return &row.at(_col);
}
}
}
}
return nullptr;
}
// We hold only FullMsgId, not HistoryItem*, because all click handlers
// are activated async and the item may be already destroyed.
void setMessageId(const FullMsgId &msgId) {
_itemId = msgId;
}
protected:
void onClickImpl() const override {
App::activateBotCommand(_item, _row, _col);
if (auto item = App::histItemById(_itemId)) {
App::activateBotCommand(item, _row, _col);
}
}
private:
const HistoryItem *_item = nullptr;
FullMsgId _itemId;
int _row, _col;
bool _fullDisplayed = true;
@ -2270,6 +2280,16 @@ ReplyKeyboard::ReplyKeyboard(const HistoryItem *item, StylePtr &&s)
}
}
void ReplyKeyboard::updateMessageId() {
auto msgId = _item->fullId();
for_const (auto &row, _rows) {
for_const (auto &button, row) {
button.link->setMessageId(msgId);
}
}
}
void ReplyKeyboard::resize(int width, int height) {
_width = width;
@ -2775,6 +2795,15 @@ void HistoryItem::recountAttachToPrevious() {
void HistoryItem::setId(MsgId newId) {
history()->changeMsgId(id, newId);
id = newId;
// We don't need to call Notify::replyMarkupUpdated(this) and update keyboard
// in history widget, because it can't exist for an outgoing message.
// Only inline keyboards can be in outgoing messages.
if (auto markup = inlineReplyMarkup()) {
if (markup->inlineKeyboard) {
markup->inlineKeyboard->updateMessageId();
}
}
}
bool HistoryItem::canEdit(const QDateTime &cur) const {
@ -6816,7 +6845,7 @@ void HistoryMessage::initDimensions() {
}
if (replyw > _maxw) _maxw = replyw;
}
if (HistoryMessageReplyMarkup *markup = inlineReplyMarkup()) {
if (auto markup = inlineReplyMarkup()) {
if (!markup->inlineKeyboard) {
markup->inlineKeyboard.reset(new ReplyKeyboard(this, std_::make_unique<KeyboardStyle>(st::msgBotKbButton)));
}

View File

@ -905,6 +905,7 @@ public:
void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed);
void clearSelection();
void updateMessageId();
private:
const HistoryItem *_item;