Fix crashes in HistoryWidget.

This commit is contained in:
John Preston 2020-06-30 18:14:05 +04:00
parent b7707a8a89
commit 09aff23ac9
2 changed files with 87 additions and 60 deletions

View file

@ -259,6 +259,7 @@ HistoryWidget::HistoryWidget(
QWidget *parent, QWidget *parent,
not_null<Window::SessionController*> controller) not_null<Window::SessionController*> controller)
: Window::AbstractSectionWidget(parent, controller) : Window::AbstractSectionWidget(parent, controller)
, _api(&controller->session().mtp())
, _updateEditTimeLeftDisplay([=] { updateField(); }) , _updateEditTimeLeftDisplay([=] { updateField(); })
, _fieldBarCancel(this, st::historyReplyCancel) , _fieldBarCancel(this, st::historyReplyCancel)
, _previewTimer([=] { requestPreview(); }) , _previewTimer([=] { requestPreview(); })
@ -1143,14 +1144,14 @@ void HistoryWidget::updateInlineBotQuery() {
if (_inlineBotUsername != query.username) { if (_inlineBotUsername != query.username) {
_inlineBotUsername = query.username; _inlineBotUsername = query.username;
if (_inlineBotResolveRequestId) { if (_inlineBotResolveRequestId) {
session().api().request(_inlineBotResolveRequestId).cancel(); _api.request(_inlineBotResolveRequestId).cancel();
_inlineBotResolveRequestId = 0; _inlineBotResolveRequestId = 0;
} }
if (query.lookingUpBot) { if (query.lookingUpBot) {
_inlineBot = nullptr; _inlineBot = nullptr;
_inlineLookingUpBot = true; _inlineLookingUpBot = true;
const auto username = _inlineBotUsername; const auto username = _inlineBotUsername;
_inlineBotResolveRequestId = session().api().request(MTPcontacts_ResolveUsername( _inlineBotResolveRequestId = _api.request(MTPcontacts_ResolveUsername(
MTP_string(username) MTP_string(username)
)).done([=](const MTPcontacts_ResolvedPeer &result) { )).done([=](const MTPcontacts_ResolvedPeer &result) {
inlineBotResolveDone(result); inlineBotResolveDone(result);
@ -1401,7 +1402,7 @@ void HistoryWidget::cancelSendAction(
SendAction::Type type) { SendAction::Type type) {
const auto i = _sendActionRequests.find({ history, type }); const auto i = _sendActionRequests.find({ history, type });
if (i != _sendActionRequests.end()) { if (i != _sendActionRequests.end()) {
session().api().request(i->second).cancel(); _api.request(i->second).cancel();
_sendActionRequests.erase(i); _sendActionRequests.erase(i);
} }
} }
@ -1442,7 +1443,7 @@ void HistoryWidget::updateSendAction(
case Type::ChooseContact: action = MTP_sendMessageChooseContactAction(); break; case Type::ChooseContact: action = MTP_sendMessageChooseContactAction(); break;
case Type::PlayGame: action = MTP_sendMessageGamePlayAction(); break; case Type::PlayGame: action = MTP_sendMessageGamePlayAction(); break;
} }
const auto requestId = session().api().request(MTPmessages_SetTyping( const auto requestId = _api.request(MTPmessages_SetTyping(
peer->input, peer->input,
action action
)).done([=](const MTPBool &result, mtpRequestId requestId) { )).done([=](const MTPBool &result, mtpRequestId requestId) {
@ -3058,6 +3059,7 @@ void HistoryWidget::saveEditMsg() {
sendFlags |= MTPmessages_EditMessage::Flag::f_entities; sendFlags |= MTPmessages_EditMessage::Flag::f_entities;
} }
const auto weak = Ui::MakeWeak(this);
const auto history = _history; const auto history = _history;
_saveEditMsgRequestId = history->session().api().request( _saveEditMsgRequestId = history->session().api().request(
MTPmessages_EditMessage( MTPmessages_EditMessage(
@ -3069,55 +3071,60 @@ void HistoryWidget::saveEditMsg() {
MTPReplyMarkup(), MTPReplyMarkup(),
sentEntities, sentEntities,
MTP_int(0) MTP_int(0)
)).done([=](const MTPUpdates &result, mtpRequestId requestId) { )).done([history, weak](const MTPUpdates &result, mtpRequestId requestId) {
saveEditMsgDone(history, result, requestId); SaveEditMsgDone(history, result, requestId);
}).fail([=](const RPCError &error, mtpRequestId requestId) { if (const auto strong = weak.data()) {
saveEditMsgFail(history, error, requestId); if (requestId == strong->_saveEditMsgRequestId) {
strong->_saveEditMsgRequestId = 0;
strong->cancelEdit();
}
}
}).fail([history, weak](const RPCError &error, mtpRequestId requestId) {
SaveEditMsgFail(history, error, requestId);
if (const auto strong = weak.data()) {
if (requestId == strong->_saveEditMsgRequestId) {
strong->_saveEditMsgRequestId = 0;
}
const auto &err = error.type();
if (err == qstr("MESSAGE_ID_INVALID")
|| err == qstr("CHAT_ADMIN_REQUIRED")
|| err == qstr("MESSAGE_EDIT_TIME_EXPIRED")) {
Ui::show(Box<InformBox>(tr::lng_edit_error(tr::now)));
} else if (err == qstr("MESSAGE_NOT_MODIFIED")) {
strong->cancelEdit();
} else if (err == qstr("MESSAGE_EMPTY")) {
strong->_field->selectAll();
strong->_field->setFocus();
} else {
Ui::show(Box<InformBox>(tr::lng_edit_error(tr::now)));
}
strong->update();
}
}).send(); }).send();
} }
void HistoryWidget::saveEditMsgDone( void HistoryWidget::SaveEditMsgDone(
not_null<History*> history, not_null<History*> history,
const MTPUpdates &updates, const MTPUpdates &updates,
mtpRequestId requestId) { mtpRequestId requestId) {
session().api().applyUpdates(updates); history->session().api().applyUpdates(updates);
if (requestId == _saveEditMsgRequestId) {
_saveEditMsgRequestId = 0;
cancelEdit();
}
if (auto editDraft = history->editDraft()) { if (auto editDraft = history->editDraft()) {
if (editDraft->saveRequestId == requestId) { if (editDraft->saveRequestId == requestId) {
history->clearEditDraft(); history->clearEditDraft();
session().local().writeDrafts(history); history->session().local().writeDrafts(history);
} }
} }
} }
void HistoryWidget::saveEditMsgFail( void HistoryWidget::SaveEditMsgFail(
not_null<History*> history, not_null<History*> history,
const RPCError &error, const RPCError &error,
mtpRequestId requestId) { mtpRequestId requestId) {
if (requestId == _saveEditMsgRequestId) {
_saveEditMsgRequestId = 0;
}
if (auto editDraft = history->editDraft()) { if (auto editDraft = history->editDraft()) {
if (editDraft->saveRequestId == requestId) { if (editDraft->saveRequestId == requestId) {
editDraft->saveRequestId = 0; editDraft->saveRequestId = 0;
} }
} }
const auto &err = error.type();
if (err == qstr("MESSAGE_ID_INVALID") || err == qstr("CHAT_ADMIN_REQUIRED") || err == qstr("MESSAGE_EDIT_TIME_EXPIRED")) {
Ui::show(Box<InformBox>(tr::lng_edit_error(tr::now)));
} else if (err == qstr("MESSAGE_NOT_MODIFIED")) {
cancelEdit();
} else if (err == qstr("MESSAGE_EMPTY")) {
_field->selectAll();
_field->setFocus();
} else {
Ui::show(Box<InformBox>(tr::lng_edit_error(tr::now)));
}
update();
} }
void HistoryWidget::hideSelectorControlsAnimated() { void HistoryWidget::hideSelectorControlsAnimated() {
@ -3674,6 +3681,7 @@ void HistoryWidget::app_sendBotCallback(
using ButtonType = HistoryMessageMarkupButton::Type; using ButtonType = HistoryMessageMarkupButton::Type;
BotCallbackInfo info = { BotCallbackInfo info = {
&session(),
bot, bot,
msg->fullId(), msg->fullId(),
row, row,
@ -3688,15 +3696,24 @@ void HistoryWidget::app_sendBotCallback(
flags |= MTPmessages_GetBotCallbackAnswer::Flag::f_data; flags |= MTPmessages_GetBotCallbackAnswer::Flag::f_data;
sendData = button->data; sendData = button->data;
} }
const auto weak = Ui::MakeWeak(this);
button->requestId = session().api().request(MTPmessages_GetBotCallbackAnswer( button->requestId = session().api().request(MTPmessages_GetBotCallbackAnswer(
MTP_flags(flags), MTP_flags(flags),
_peer->input, _peer->input,
MTP_int(msg->id), MTP_int(msg->id),
MTP_bytes(sendData) MTP_bytes(sendData)
)).done([=](const MTPmessages_BotCallbackAnswer &result, mtpRequestId requestId) { )).done([info, weak](const MTPmessages_BotCallbackAnswer &result, mtpRequestId requestId) {
botCallbackDone(info, result, requestId); BotCallbackDone(info, result, requestId);
}).fail([=](const RPCError &error, mtpRequestId requestId) { result.match([&](const MTPDmessages_botCallbackAnswer &data) {
botCallbackFail(info, error, requestId); const auto item = info.session->data().message(info.msgId);
if (!data.vmessage() && data.vurl() && info.game && item) {
if (const auto strong = weak.data()) {
strong->updateSendAction(item->history(), SendAction::Type::PlayGame);
}
}
});
}).fail([info](const RPCError &error, mtpRequestId requestId) {
BotCallbackFail(info, error, requestId);
}).send(); }).send();
session().data().requestItemRepaint(msg); session().data().requestItemRepaint(msg);
@ -3709,19 +3726,20 @@ void HistoryWidget::app_sendBotCallback(
} }
} }
void HistoryWidget::botCallbackDone( void HistoryWidget::BotCallbackDone(
BotCallbackInfo info, BotCallbackInfo info,
const MTPmessages_BotCallbackAnswer &answer, const MTPmessages_BotCallbackAnswer &answer,
mtpRequestId req) { mtpRequestId req) {
const auto item = session().data().message(info.msgId); const auto session = info.session;
const auto item = session->data().message(info.msgId);
const auto button = HistoryMessageMarkupButton::Get( const auto button = HistoryMessageMarkupButton::Get(
&session().data(), &session->data(),
info.msgId, info.msgId,
info.row, info.row,
info.col); info.col);
if (button && button->requestId == req) { if (button && button->requestId == req) {
button->requestId = 0; button->requestId = 0;
session().data().requestItemRepaint(item); session->data().requestItemRepaint(item);
} }
answer.match([&](const MTPDmessages_botCallbackAnswer &data) { answer.match([&](const MTPDmessages_botCallbackAnswer &data) {
if (const auto message = data.vmessage()) { if (const auto message = data.vmessage()) {
@ -3733,11 +3751,8 @@ void HistoryWidget::botCallbackDone(
} else if (const auto url = data.vurl()) { } else if (const auto url = data.vurl()) {
auto link = qs(*url); auto link = qs(*url);
if (info.game) { if (info.game) {
link = AppendShareGameScoreUrl(&session(), link, info.msgId); link = AppendShareGameScoreUrl(session, link, info.msgId);
BotGameUrlClickHandler(info.bot, link).onClick({}); BotGameUrlClickHandler(info.bot, link).onClick({});
if (item) {
updateSendAction(item->history(), SendAction::Type::PlayGame);
}
} else { } else {
UrlClickHandler::Open(link); UrlClickHandler::Open(link);
} }
@ -3745,21 +3760,21 @@ void HistoryWidget::botCallbackDone(
}); });
} }
bool HistoryWidget::botCallbackFail( void HistoryWidget::BotCallbackFail(
BotCallbackInfo info, BotCallbackInfo info,
const RPCError &error, const RPCError &error,
mtpRequestId req) { mtpRequestId req) {
// show error? // show error?
const auto owner = &info.session->data();
const auto button = HistoryMessageMarkupButton::Get( const auto button = HistoryMessageMarkupButton::Get(
&session().data(), owner,
info.msgId, info.msgId,
info.row, info.row,
info.col); info.col);
if (button && button->requestId == req) { if (button && button->requestId == req) {
button->requestId = 0; button->requestId = 0;
session().data().requestItemRepaint(session().data().message(info.msgId)); owner->requestItemRepaint(owner->message(info.msgId));
} }
return true;
} }
bool HistoryWidget::insertBotCommand(const QString &cmd) { bool HistoryWidget::insertBotCommand(const QString &cmd) {
@ -5982,21 +5997,28 @@ void HistoryWidget::pinMessage(FullMsgId itemId) {
} }
void HistoryWidget::unpinMessage(FullMsgId itemId) { void HistoryWidget::unpinMessage(FullMsgId itemId) {
const auto peer = _peer; if (!_peer) {
return;
}
UnpinMessage(_peer);
}
void HistoryWidget::UnpinMessage(not_null<PeerData*> peer) {
if (!peer) { if (!peer) {
return; return;
} }
Ui::show(Box<ConfirmBox>(tr::lng_pinned_unpin_sure(tr::now), tr::lng_pinned_unpin(tr::now), crl::guard(this, [=] { const auto session = &peer->session();
Ui::show(Box<ConfirmBox>(tr::lng_pinned_unpin_sure(tr::now), tr::lng_pinned_unpin(tr::now), crl::guard(session, [=] {
peer->clearPinnedMessage(); peer->clearPinnedMessage();
Ui::hideLayer(); Ui::hideLayer();
session().api().request(MTPmessages_UpdatePinnedMessage( session->api().request(MTPmessages_UpdatePinnedMessage(
MTP_flags(0), MTP_flags(0),
peer->input, peer->input,
MTP_int(0) MTP_int(0)
)).done([=](const MTPUpdates &result) { )).done([=](const MTPUpdates &result) {
session().api().applyUpdates(result); session->api().applyUpdates(result);
}).send(); }).send();
}))); })));
} }
@ -6155,7 +6177,7 @@ void HistoryWidget::cancelFieldAreaState() {
} }
void HistoryWidget::previewCancel() { void HistoryWidget::previewCancel() {
session().api().request(base::take(_previewRequest)).cancel(); _api.request(base::take(_previewRequest)).cancel();
_previewData = nullptr; _previewData = nullptr;
_previewLinks.clear(); _previewLinks.clear();
updatePreview(); updatePreview();
@ -6171,7 +6193,7 @@ void HistoryWidget::checkPreview() {
} }
const auto links = _parsedLinks.join(' '); const auto links = _parsedLinks.join(' ');
if (_previewLinks != links) { if (_previewLinks != links) {
session().api().request(base::take(_previewRequest)).cancel(); _api.request(base::take(_previewRequest)).cancel();
_previewLinks = links; _previewLinks = links;
if (_previewLinks.isEmpty()) { if (_previewLinks.isEmpty()) {
if (_previewData && _previewData->pendingTill >= 0) { if (_previewData && _previewData->pendingTill >= 0) {
@ -6180,7 +6202,7 @@ void HistoryWidget::checkPreview() {
} else { } else {
const auto i = _previewCache.constFind(links); const auto i = _previewCache.constFind(links);
if (i == _previewCache.cend()) { if (i == _previewCache.cend()) {
_previewRequest = session().api().request(MTPmessages_GetWebPagePreview( _previewRequest = _api.request(MTPmessages_GetWebPagePreview(
MTP_flags(0), MTP_flags(0),
MTP_string(links), MTP_string(links),
MTPVector<MTPMessageEntity>() MTPVector<MTPMessageEntity>()
@ -6204,7 +6226,7 @@ void HistoryWidget::requestPreview() {
return; return;
} }
const auto links = _previewLinks; const auto links = _previewLinks;
_previewRequest = session().api().request(MTPmessages_GetWebPagePreview( _previewRequest = _api.request(MTPmessages_GetWebPagePreview(
MTP_flags(0), MTP_flags(0),
MTP_string(links), MTP_string(links),
MTPVector<MTPMessageEntity>() MTPVector<MTPMessageEntity>()

View file

@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
#include "ui/effects/animations.h" #include "ui/effects/animations.h"
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "mtproto/sender.h"
#include "base/flags.h" #include "base/flags.h"
#include "base/timer.h" #include "base/timer.h"
@ -335,6 +336,7 @@ private:
using TabbedSelector = ChatHelpers::TabbedSelector; using TabbedSelector = ChatHelpers::TabbedSelector;
using DragState = Storage::MimeDataState; using DragState = Storage::MimeDataState;
struct BotCallbackInfo { struct BotCallbackInfo {
not_null<Main::Session*> session;
UserData *bot; UserData *bot;
FullMsgId msgId; FullMsgId msgId;
int row, col; int row, col;
@ -567,8 +569,8 @@ private:
void createUnreadBarAndResize(); void createUnreadBarAndResize();
void saveEditMsg(); void saveEditMsg();
void saveEditMsgDone(not_null<History*> history, const MTPUpdates &updates, mtpRequestId requestId); static void SaveEditMsgDone(not_null<History*> history, const MTPUpdates &updates, mtpRequestId requestId);
void saveEditMsgFail(not_null<History*> history, const RPCError &error, mtpRequestId requestId); static void SaveEditMsgFail(not_null<History*> history, const RPCError &error, mtpRequestId requestId);
void checkPreview(); void checkPreview();
void requestPreview(); void requestPreview();
@ -578,8 +580,10 @@ private:
void addMessagesToFront(PeerData *peer, const QVector<MTPMessage> &messages); void addMessagesToFront(PeerData *peer, const QVector<MTPMessage> &messages);
void addMessagesToBack(PeerData *peer, const QVector<MTPMessage> &messages); void addMessagesToBack(PeerData *peer, const QVector<MTPMessage> &messages);
void botCallbackDone(BotCallbackInfo info, const MTPmessages_BotCallbackAnswer &answer, mtpRequestId req); static void UnpinMessage(not_null<PeerData*> peer);
bool botCallbackFail(BotCallbackInfo info, const RPCError &error, mtpRequestId req);
static void BotCallbackDone(BotCallbackInfo info, const MTPmessages_BotCallbackAnswer &answer, mtpRequestId req);
static void BotCallbackFail(BotCallbackInfo info, const RPCError &error, mtpRequestId req);
void updateHistoryGeometry(bool initial = false, bool loadedDown = false, const ScrollChange &change = { ScrollChangeNone, 0 }); void updateHistoryGeometry(bool initial = false, bool loadedDown = false, const ScrollChange &change = { ScrollChangeNone, 0 });
void updateListSize(); void updateListSize();
@ -644,6 +648,7 @@ private:
void setupScheduledToggle(); void setupScheduledToggle();
void refreshScheduledToggle(); void refreshScheduledToggle();
MTP::Sender _api;
MsgId _replyToId = 0; MsgId _replyToId = 0;
Ui::Text::String _replyToName; Ui::Text::String _replyToName;
int _replyToNameVersion = 0; int _replyToNameVersion = 0;