Trending sticker sets install improved, masks sets install disallowed.

Also rpcDone() and rpcFail() now accept lambdas.
This commit is contained in:
John Preston 2016-09-19 13:18:21 +03:00
parent 6d2fc5c642
commit 227aa36627
17 changed files with 459 additions and 110 deletions

View file

@ -712,6 +712,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_stickers_return" = "Undo";
"lng_stickers_restore" = "Restore";
"lng_stickers_count" = "{count:Loading...|# sticker|# stickers}";
"lng_stickers_masks_pack" = "This is a pack of mask stickers. You can use them in the photo editor on our mobile apps.";
"lng_in_dlg_photo" = "Photo";
"lng_in_dlg_video" = "Video file";
@ -875,8 +876,11 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
"lng_reply_cant_forward" = "Sorry, no way to reply to an old message in supergroup :( Do you wish to forward it and add your comment?";
"lng_share_title" = "Share to";
"lng_share_confirm" = "Share";
"lng_share_copy_link" = "Copy share link";
"lng_share_confirm" = "Send";
"lng_share_wrong_user" = "This game was opened from a different user.";
"lng_share_game_link_copied" = "Game link copied to clipboard.";
"lng_share_done" = "Done!";
"lng_contact_phone" = "Phone number";
"lng_enter_contact_data" = "New Contact";

View file

@ -31,12 +31,15 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
#include "localstorage.h"
#include "boxes/confirmbox.h"
#include "apiwrap.h"
#include "ui/toast/toast.h"
ShareBox::ShareBox(SubmitCallback &&callback) : ItemListBox(st::boxScroll)
, _callback(std_::move(callback))
ShareBox::ShareBox(CopyCallback &&copyCallback, SubmitCallback &&submitCallback) : ItemListBox(st::boxScroll)
, _copyCallback(std_::move(copyCallback))
, _submitCallback(std_::move(submitCallback))
, _inner(this)
, _filter(this, st::boxSearchField, lang(lng_participant_filter))
, _filterCancel(this, st::boxSearchCancel)
, _copy(this, lang(lng_share_copy_link), st::defaultBoxButton)
, _share(this, lang(lng_share_confirm), st::defaultBoxButton)
, _cancel(this, lang(lng_cancel), st::cancelBoxButton)
, _topShadow(this)
@ -47,7 +50,8 @@ ShareBox::ShareBox(SubmitCallback &&callback) : ItemListBox(st::boxScroll)
connect(_inner, SIGNAL(selectedChanged()), this, SLOT(onSelectedChanged()));
connect(_inner, SIGNAL(mustScrollTo(int,int)), this, SLOT(onMustScrollTo(int,int)));
connect(_share, SIGNAL(clicked()), this, SLOT(onShare()));
connect(_copy, SIGNAL(clicked()), this, SLOT(onCopyLink()));
connect(_share, SIGNAL(clicked()), this, SLOT(onSubmit()));
connect(_cancel, SIGNAL(clicked()), this, SLOT(onClose()));
connect(scrollArea(), SIGNAL(scrolled()), this, SLOT(onScroll()));
connect(_filter, SIGNAL(changed()), this, SLOT(onFilterUpdate()));
@ -61,6 +65,8 @@ ShareBox::ShareBox(SubmitCallback &&callback) : ItemListBox(st::boxScroll)
_searchTimer.setSingleShot(true);
connect(&_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername()));
updateButtonsVisibility();
prepare();
}
@ -173,12 +179,16 @@ void ShareBox::keyPressEvent(QKeyEvent *e) {
}
void ShareBox::moveButtons() {
_copy->moveToRight(st::boxButtonPadding.right(), _share->y());
_share->moveToRight(st::boxButtonPadding.right(), height() - st::boxButtonPadding.bottom() - _share->height());
auto cancelRight = st::boxButtonPadding.right();
if (_inner->hasSelected()) {
cancelRight += _share->width() + st::boxButtonPadding.left();
}
_cancel->moveToRight(cancelRight, _share->y());
_cancel->moveToRight(st::boxButtonPadding.right() + _share->width() + st::boxButtonPadding.left(), _share->y());
}
void ShareBox::updateButtonsVisibility() {
auto hasSelected = _inner->hasSelected();
_copy->setVisible(!hasSelected);
_share->setVisible(hasSelected);
_cancel->setVisible(hasSelected);
}
void ShareBox::onFilterCancel() {
@ -190,14 +200,20 @@ void ShareBox::onFilterUpdate() {
_inner->updateFilter(_filter->getLastText());
}
void ShareBox::onShare() {
if (_callback) {
_callback(_inner->selected());
void ShareBox::onSubmit() {
if (_submitCallback) {
_submitCallback(_inner->selected());
}
}
void ShareBox::onCopyLink() {
if (_copyCallback) {
_copyCallback();
}
}
void ShareBox::onSelectedChanged() {
_share->setVisible(_inner->hasSelected());
updateButtonsVisibility();
moveButtons();
update();
}
@ -928,19 +944,76 @@ QString appendShareGameScoreUrl(const QString &url, const FullMsgId &fullId) {
namespace {
void shareGameScoreFromItem(HistoryItem *item) {
Ui::showLayer(new ShareBox([msgId = item->fullId()](const QVector<PeerData*> &result) {
MTPmessages_ForwardMessages::Flags sendFlags = MTPmessages_ForwardMessages::Flag::f_with_my_score;
MTPVector<MTPint> msgIds = MTP_vector<MTPint>(1, MTP_int(msgId.msg));
struct ShareGameScoreData {
ShareGameScoreData(const FullMsgId &msgId) : msgId(msgId) {
}
FullMsgId msgId;
OrderedSet<mtpRequestId> requests;
};
auto data = MakeShared<ShareGameScoreData>(item->fullId());
auto copyCallback = [data]() {
if (auto main = App::main()) {
if (auto item = App::histItemById(msgId)) {
for_const (auto peer, result) {
MTPVector<MTPlong> random = MTP_vector<MTPlong>(1, rand_value<MTPlong>());
MTP::send(MTPmessages_ForwardMessages(MTP_flags(sendFlags), item->history()->peer->input, msgIds, random, peer->input), main->rpcDone(&MainWidget::sentUpdatesReceived));
if (auto item = App::histItemById(data->msgId)) {
if (auto bot = item->getMessageBot()) {
if (auto markup = item->Get<HistoryMessageReplyMarkup>()) {
for (int i = 0, rowsCount = markup->rows.size(); i != rowsCount; ++i) {
auto &row = markup->rows[i];
for (int j = 0, buttonsCount = row.size(); j != buttonsCount; ++j) {
auto &button = row[j];
if (button.type == HistoryMessageReplyMarkup::Button::Type::Game) {
auto strData = QString::fromUtf8(button.data);
auto parts = strData.split(',');
t_assert(parts.size() > 1);
QApplication::clipboard()->setText(qsl("https://telegram.me/") + bot->username + qsl("?start=") + parts[1]);
Ui::Toast::Config toast;
toast.text = lang(lng_share_game_link_copied);
Ui::Toast::Show(App::wnd(), toast);
return;
}
}
}
}
}
}
}
Ui::hideLayer();
}));
};
auto submitCallback = [data](const QVector<PeerData*> &result) {
if (!data->requests.empty()) {
return; // Share clicked already.
}
auto doneCallback = [data](const MTPUpdates &updates, mtpRequestId requestId) {
if (auto main = App::main()) {
main->sentUpdatesReceived(updates);
}
data->requests.remove(requestId);
if (data->requests.empty()) {
Ui::Toast::Config toast;
toast.text = lang(lng_share_done);
Ui::Toast::Show(App::wnd(), toast);
Ui::hideLayer();
}
};
MTPmessages_ForwardMessages::Flags sendFlags = MTPmessages_ForwardMessages::Flag::f_with_my_score;
MTPVector<MTPint> msgIds = MTP_vector<MTPint>(1, MTP_int(data->msgId.msg));
if (auto main = App::main()) {
if (auto item = App::histItemById(data->msgId)) {
for_const (auto peer, result) {
MTPVector<MTPlong> random = MTP_vector<MTPlong>(1, rand_value<MTPlong>());
auto request = MTPmessages_ForwardMessages(MTP_flags(sendFlags), item->history()->peer->input, msgIds, random, peer->input);
auto callback = doneCallback;
auto requestId = MTP::send(request, rpcDone(std_::move(callback)));
data->requests.insert(requestId);
}
}
}
};
Ui::showLayer(new ShareBox(std_::move(copyCallback), std_::move(submitCallback)));
}
class GameMessageResolvedCallback : public SharedCallback<void, ChannelData*, MsgId> {

View file

@ -44,8 +44,9 @@ class ShareBox : public ItemListBox, public RPCSender {
Q_OBJECT
public:
using CopyCallback = base::lambda_unique<void()>;
using SubmitCallback = base::lambda_unique<void(const QVector<PeerData*> &)>;
ShareBox(SubmitCallback &&callback);
ShareBox(CopyCallback &&copyCallback, SubmitCallback &&submitCallback);
private slots:
void onFilterUpdate();
@ -55,7 +56,8 @@ private slots:
bool onSearchByUsername(bool searchCache = false);
void onNeedSearchByUsername();
void onShare();
void onSubmit();
void onCopyLink();
void onSelectedChanged();
void onMustScrollTo(int top, int bottom);
@ -69,16 +71,19 @@ protected:
private:
void moveButtons();
void updateButtonsVisibility();
void peopleReceived(const MTPcontacts_Found &result, mtpRequestId requestId);
bool peopleFailed(const RPCError &error, mtpRequestId requestId);
SubmitCallback _callback;
CopyCallback _copyCallback;
SubmitCallback _submitCallback;
ChildWidget<internal::ShareInner> _inner;
ChildWidget<InputField> _filter;
ChildWidget<IconedButton> _filterCancel;
ChildWidget<BoxButton> _copy;
ChildWidget<BoxButton> _share;
ChildWidget<BoxButton> _cancel;

View file

@ -234,6 +234,9 @@ void StickerSetInner::mouseReleaseEvent(QMouseEvent *e) {
void StickerSetInner::updateSelected() {
auto index = stickerFromGlobalPos(QCursor::pos());
if (isMasksSet()) {
index = -1;
}
if (index != _selected) {
startOverAnimation(_selected, 1., 0.);
_selected = index;
@ -356,6 +359,10 @@ QString StickerSetInner::shortName() const {
}
void StickerSetInner::install() {
if (isMasksSet()) {
Ui::showLayer(new InformBox(lang(lng_stickers_masks_pack)), KeepOtherLayers);
return;
}
if (_installRequest) return;
_installRequest = MTP::send(MTPmessages_InstallStickerSet(_input, MTP_bool(false)), rpcDone(&StickerSetInner::installDone), rpcFail(&StickerSetInner::installFail));
}
@ -1328,11 +1335,13 @@ void StickersBox::setup() {
if (_section == Section::Installed) {
Local::readArchivedStickers();
if (Global::ArchivedStickerSetsOrder().isEmpty()) {
_archivedRequestId = MTP::send(MTPmessages_GetArchivedStickers(MTP_long(0), MTP_int(kArchivedLimitFirstRequest)), rpcDone(&StickersBox::getArchivedDone, 0ULL));
MTPmessages_GetArchivedStickers::Flags flags = 0;
_archivedRequestId = MTP::send(MTPmessages_GetArchivedStickers(MTP_flags(flags), MTP_long(0), MTP_int(kArchivedLimitFirstRequest)), rpcDone(&StickersBox::getArchivedDone, 0ULL));
}
} else if (_section == Section::Archived) {
// Reload the archived list.
_archivedRequestId = MTP::send(MTPmessages_GetArchivedStickers(MTP_long(0), MTP_int(kArchivedLimitFirstRequest)), rpcDone(&StickersBox::getArchivedDone, 0ULL));
MTPmessages_GetArchivedStickers::Flags flags = 0;
_archivedRequestId = MTP::send(MTPmessages_GetArchivedStickers(MTP_flags(flags), MTP_long(0), MTP_int(kArchivedLimitFirstRequest)), rpcDone(&StickersBox::getArchivedDone, 0ULL));
auto &sets = Global::StickerSets();
for_const (auto setId, Global::ArchivedStickerSetsOrder()) {
@ -1414,7 +1423,8 @@ void StickersBox::checkLoadMoreArchived() {
}
}
}
_archivedRequestId = MTP::send(MTPmessages_GetArchivedStickers(MTP_long(lastId), MTP_int(kArchivedLimitPerPage)), rpcDone(&StickersBox::getArchivedDone, lastId));
MTPmessages_GetArchivedStickers::Flags flags = 0;
_archivedRequestId = MTP::send(MTPmessages_GetArchivedStickers(MTP_flags(flags), MTP_long(lastId), MTP_int(kArchivedLimitPerPage)), rpcDone(&StickersBox::getArchivedDone, lastId));
}
}
}

View file

@ -65,6 +65,10 @@ private:
void installDone(const MTPmessages_StickerSetInstallResult &result);
bool installFail(const RPCError &error);
bool isMasksSet() const {
return (_setFlags & MTPDstickerSet::Flag::f_masks);
}
QVector<FloatAnimation> _packOvers;
StickerPack _pack;
StickersByEmojiMap _emoji;

View file

@ -103,9 +103,7 @@ TextWithEntities UrlClickHandler::getExpandedLinkTextWithEntities(ExpandLinksMod
}
void HiddenUrlClickHandler::onClick(Qt::MouseButton button) const {
auto u = url();
u = tryConvertUrlToLocal(u);
auto u = tryConvertUrlToLocal(url());
if (u.startsWith(qstr("tg://"))) {
App::openLocalUrl(u);
@ -115,9 +113,7 @@ void HiddenUrlClickHandler::onClick(Qt::MouseButton button) const {
}
void BotGameUrlClickHandler::onClick(Qt::MouseButton button) const {
auto u = url();
u = tryConvertUrlToLocal(u);
auto u = tryConvertUrlToLocal(url());
if (u.startsWith(qstr("tg://"))) {
App::openLocalUrl(u);

View file

@ -29,7 +29,7 @@ public:
}
void copyToClipboard() const override {
QString u = url();
auto u = url();
if (!u.isEmpty()) {
QApplication::clipboard()->setText(u);
}

View file

@ -403,11 +403,188 @@ private:
};
template <typename R, typename ...Args>
inline Function<R, Args...> lambda_wrap_helper(base::lambda_unique<R(Args...)> &&lambda) {
inline Function<R, Args...> func_lambda_wrap_helper(base::lambda_unique<R(Args...)> &&lambda) {
return Function<R, Args...>(new LambdaFunctionImplementation<R, Args...>(std_::move(lambda)));
}
template <typename Lambda, typename = std_::enable_if_t<std_::is_rvalue_reference<Lambda&&>::value>>
inline LambdaGetFunction<decltype(&Lambda::operator())> func(Lambda &&lambda) {
return lambda_wrap_helper(LambdaGetUnique<decltype(&Lambda::operator())>(std_::move(lambda)));
return func_lambda_wrap_helper(LambdaGetUnique<decltype(&Lambda::operator())>(std_::move(lambda)));
}
// While we still use rpcDone() and rpcFail()
#include "mtproto/rpc_sender.h"
template <typename Base, typename FunctionType>
class RPCHandlerImplementation : public Base {
protected:
using Lambda = base::lambda_unique<FunctionType>;
using Parent = RPCHandlerImplementation<Base, FunctionType>;
public:
RPCHandlerImplementation(Lambda &&handler) : _handler(std_::move(handler)) {
}
protected:
Lambda _handler;
};
template <typename FunctionType>
using RPCDoneHandlerImplementation = RPCHandlerImplementation<RPCAbstractDoneHandler, FunctionType>;
template <typename R>
class RPCDoneHandlerImplementationBare : public RPCDoneHandlerImplementation<R(const mtpPrime*, const mtpPrime*)> { // done(from, end)
public:
using Parent::Parent;
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const override {
return this->_handler ? this->_handler(from, end) : void(0);
}
};
template <typename R>
class RPCDoneHandlerImplementationBareReq : public RPCDoneHandlerImplementation<R(const mtpPrime*, const mtpPrime*, mtpRequestId)> { // done(from, end, req_id)
public:
using Parent::Parent;
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const override {
return this->_handler ? this->_handler(from, end, requestId) : void(0);
}
};
template <typename R, typename T>
class RPCDoneHandlerImplementationPlain : public RPCDoneHandlerImplementation<R(const T&)> { // done(result)
public:
using Parent::Parent;
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const override {
return this->_handler ? this->_handler(T(from, end)) : void(0);
}
};
template <typename R, typename T>
class RPCDoneHandlerImplementationReq : public RPCDoneHandlerImplementation<R(const T&, mtpRequestId)> { // done(result, req_id)
public:
using Parent::Parent;
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const override {
return this->_handler ? this->_handler(T(from, end), requestId) : void(0);
}
};
template <typename R>
class RPCDoneHandlerImplementationNo : public RPCDoneHandlerImplementation<R()> { // done()
public:
using Parent::Parent;
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const override {
return this->_handler ? this->_handler() : void(0);
}
};
template <typename R>
class RPCDoneHandlerImplementationNoReq : public RPCDoneHandlerImplementation<R(mtpRequestId)> { // done(req_id)
public:
using Parent::Parent;
void operator()(mtpRequestId requestId, const mtpPrime *from, const mtpPrime *end) const override {
return this->_handler ? this->_handler(requestId) : void(0);
}
};
template <typename R>
inline RPCDoneHandlerPtr rpcDone_lambda_wrap_helper(base::lambda_unique<R(const mtpPrime*, const mtpPrime*)> &&lambda) {
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationBare<R>(std_::move(lambda)));
}
template <typename R>
inline RPCDoneHandlerPtr rpcDone_lambda_wrap_helper(base::lambda_unique<R(const mtpPrime*, const mtpPrime*, mtpRequestId)> &&lambda) {
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationBareReq<R>(std_::move(lambda)));
}
template <typename R, typename T>
inline RPCDoneHandlerPtr rpcDone_lambda_wrap_helper(base::lambda_unique<R(const T&)> &&lambda) {
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationPlain<R, T>(std_::move(lambda)));
}
template <typename R, typename T>
inline RPCDoneHandlerPtr rpcDone_lambda_wrap_helper(base::lambda_unique<R(const T&, mtpRequestId)> &&lambda) {
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationReq<R, T>(std_::move(lambda)));
}
template <typename R>
inline RPCDoneHandlerPtr rpcDone_lambda_wrap_helper(base::lambda_unique<R()> &&lambda) {
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationNo<R>(std_::move(lambda)));
}
template <typename R>
inline RPCDoneHandlerPtr rpcDone_lambda_wrap_helper(base::lambda_unique<R(mtpRequestId)> &&lambda) {
return RPCDoneHandlerPtr(new RPCDoneHandlerImplementationNoReq<R>(std_::move(lambda)));
}
template <typename Lambda, typename = std_::enable_if_t<std_::is_rvalue_reference<Lambda&&>::value>>
RPCDoneHandlerPtr rpcDone(Lambda &&lambda) {
return rpcDone_lambda_wrap_helper(LambdaGetUnique<decltype(&Lambda::operator())>(std_::move(lambda)));
}
template <typename FunctionType>
using RPCFailHandlerImplementation = RPCHandlerImplementation<RPCAbstractFailHandler, FunctionType>;
class RPCFailHandlerImplementationPlain : public RPCFailHandlerImplementation<bool(const RPCError&)> { // fail(error)
public:
using Parent::Parent;
bool operator()(mtpRequestId requestId, const RPCError &error) const override {
return _handler ? _handler(error) : true;
}
};
class RPCFailHandlerImplementationReq : public RPCFailHandlerImplementation<bool(const RPCError&, mtpRequestId)> { // fail(error, req_id)
public:
using Parent::Parent;
bool operator()(mtpRequestId requestId, const RPCError &error) const override {
return this->_handler ? this->_handler(error, requestId) : true;
}
};
class RPCFailHandlerImplementationNo : public RPCFailHandlerImplementation<bool()> { // fail()
public:
using Parent::Parent;
bool operator()(mtpRequestId requestId, const RPCError &error) const override {
return this->_handler ? this->_handler() : true;
}
};
class RPCFailHandlerImplementationNoReq : public RPCFailHandlerImplementation<bool(mtpRequestId)> { // fail(req_id)
public:
using Parent::Parent;
bool operator()(mtpRequestId requestId, const RPCError &error) const override {
return this->_handler ? this->_handler(requestId) : true;
}
};
inline RPCFailHandlerPtr rpcFail_lambda_wrap_helper(base::lambda_unique<bool(const RPCError&)> &&lambda) {
return RPCFailHandlerPtr(new RPCFailHandlerImplementationPlain(std_::move(lambda)));
}
inline RPCFailHandlerPtr rpcFail_lambda_wrap_helper(base::lambda_unique<bool(const RPCError&, mtpRequestId)> &&lambda) {
return RPCFailHandlerPtr(new RPCFailHandlerImplementationReq(std_::move(lambda)));
}
inline RPCFailHandlerPtr rpcFail_lambda_wrap_helper(base::lambda_unique<bool()> &&lambda) {
return RPCFailHandlerPtr(new RPCFailHandlerImplementationNo(std_::move(lambda)));
}
inline RPCFailHandlerPtr rpcFail_lambda_wrap_helper(base::lambda_unique<bool(mtpRequestId)> &&lambda) {
return RPCFailHandlerPtr(new RPCFailHandlerImplementationNoReq(std_::move(lambda)));
}
template <typename Lambda, typename = std_::enable_if_t<std_::is_rvalue_reference<Lambda&&>::value>>
RPCFailHandlerPtr rpcFail(Lambda &&lambda) {
return rpcFail_lambda_wrap_helper(LambdaGetUnique<decltype(&Lambda::operator())>(std_::move(lambda)));
}

View file

@ -97,17 +97,7 @@ void activateBotCommand(const HistoryItem *msg, int row, int col) {
case ButtonType::SwitchInlineSame:
case ButtonType::SwitchInline: {
if (auto m = App::main()) {
auto getMessageBot = [msg]() -> UserData* {
if (auto bot = msg->viaBot()) {
return bot;
} else if (auto bot = msg->from()->asUser()) {
return bot;
} else if (auto bot = msg->history()->peer->asUser()) {
return bot;
}
return nullptr;
};
if (auto bot = getMessageBot()) {
if (auto bot = msg->getMessageBot()) {
auto tryFastSwitch = [bot, &button, msgId = msg->id]() -> bool {
auto samePeer = (button->type == ButtonType::SwitchInlineSame);
if (samePeer) {

View file

@ -2581,7 +2581,17 @@ void HistoryMessageReplyMarkup::createFromButtonRows(const QVector<MTPKeyboardBu
} break;
case mtpc_keyboardButtonGame: {
auto &buttonData = button.c_keyboardButtonGame();
auto strData = QString::number(buttonData.vgame_id.v) + ',' + qs(buttonData.vgame_title);
auto title = qs(buttonData.vgame_title);
auto start = qs(buttonData.vstart_param);
auto charIsGoodForStartParam = [](QChar ch) {
return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || (ch == '_') || (ch == '-');
};
for (auto &ch : start) {
if (!charIsGoodForStartParam(ch)) {
ch = '_';
}
}
auto strData = QString::number(buttonData.vgame_id.v) + ',' + start + ',' + title;
buttonRow.push_back({ Button::Type::Game, qs(buttonData.vtext), strData.toUtf8(), 0 });
} break;
}
@ -6468,7 +6478,7 @@ bool HistoryMessageReply::updateData(HistoryMessage *holder, bool force) {
replyToLnk.reset(new GoToMessageClickHandler(replyToMsg->history()->peer->id, replyToMsg->id));
if (!replyToMsg->Has<HistoryMessageForwarded>()) {
if (UserData *bot = replyToMsg->viaBot()) {
if (auto bot = replyToMsg->viaBot()) {
_replyToVia.reset(new HistoryMessageVia());
_replyToVia->create(peerToUser(bot->id));
}
@ -6720,7 +6730,7 @@ HistoryMessage::HistoryMessage(History *history, MsgId id, MTPDmessage::Flags fl
if (fwd->authorOriginal()->isChannel()) {
config.originalId = fwd->id;
}
UserData *fwdViaBot = fwd->viaBot();
auto fwdViaBot = fwd->viaBot();
if (fwdViaBot) config.viaBotId = peerToUser(fwdViaBot->id);
int fwdViewsCount = fwd->viewsCount();
if (fwdViewsCount > 0) {
@ -8133,7 +8143,9 @@ bool HistoryService::prepareGameScoreText(const QString &from, QString *outText,
if (button.type == HistoryMessageReplyMarkup::Button::Type::Game) {
auto strData = QString::fromUtf8(button.data);
second = MakeShared<ReplyMarkupClickHandler>(item, i, j);
return textcmdLink(2, strData.mid(strData.indexOf(',') + 1));
auto parts = strData.split(',');
t_assert(parts.size() > 2);
return textcmdLink(2, parts.mid(2).join(','));
}
}
}

View file

@ -1061,6 +1061,16 @@ public:
}
return nullptr;
}
UserData *getMessageBot() const {
if (auto bot = viaBot()) {
return bot;
}
auto bot = from()->asUser();
if (!bot) {
bot = history()->peer->asUser();
}
return (bot && bot->botInfo) ? bot : nullptr;
};
History *history() const {
return _history;

View file

@ -3874,7 +3874,7 @@ void HistoryWidget::featuredStickersGot(const MTPmessages_FeaturedStickers &stic
if (set) {
auto it = sets.find(set->vid.v);
QString title = stickerSetTitle(*set);
auto title = stickerSetTitle(*set);
if (it == sets.cend()) {
auto setClientFlags = MTPDstickerSet_ClientFlag::f_featured | MTPDstickerSet_ClientFlag::f_not_loaded;
if (unread.contains(set->vid.v)) {
@ -5783,13 +5783,7 @@ void HistoryWidget::app_sendBotCallback(const HistoryMessageReplyMarkup::Button
bool lastKeyboardUsed = (_keyboard.forMsgId() == FullMsgId(_channel, _history->lastKeyboardId)) && (_keyboard.forMsgId() == FullMsgId(_channel, msg->id));
auto bot = msg->viaBot();
if (!bot) {
bot = msg->from()->asUser();
if (bot && !bot->botInfo) {
bot = nullptr;
}
}
auto bot = msg->getMessageBot();
using ButtonType = HistoryMessageReplyMarkup::Button::Type;
BotCallbackInfo info = { bot, msg->fullId(), row, col, (button->type == ButtonType::Game) };

View file

@ -387,9 +387,9 @@ updateBotInlineQuery#54826690 flags:# query_id:long user_id:int query:string geo
updateBotInlineSend#e48f964 flags:# user_id:int query:string geo:flags.0?GeoPoint id:string msg_id:flags.1?InputBotInlineMessageID = Update;
updateEditChannelMessage#1b3f4df7 message:Message pts:int pts_count:int = Update;
updateChannelPinnedMessage#98592475 channel_id:int id:int = Update;
updateBotCallbackQuery#81c5615f flags:# query_id:long user_id:int peer:Peer msg_id:int data:flags.0?bytes game_id:flags.1?int = Update;
updateBotCallbackQuery#4bf9a8a0 flags:# query_id:long user_id:int peer:Peer msg_id:int chat_instance:long data:flags.0?bytes game_id:flags.1?int = Update;
updateEditMessage#e40370a3 message:Message pts:int pts_count:int = Update;
updateInlineBotCallbackQuery#d618a28b flags:# query_id:long user_id:int msg_id:InputBotInlineMessageID data:flags.0?bytes game_id:flags.1?int = Update;
updateInlineBotCallbackQuery#4f2f45d1 flags:# query_id:long user_id:int msg_id:InputBotInlineMessageID chat_instance:long data:flags.0?bytes game_id:flags.1?int = Update;
updateReadChannelOutbox#25d6c9c7 channel_id:int max_id:int = Update;
updateDraftMessage#ee2bb969 peer:Peer draft:DraftMessage = Update;
updateReadFeaturedStickers#571d2742 = Update;
@ -861,7 +861,7 @@ messages.readFeaturedStickers#5b118126 id:Vector<long> = Bool;
messages.getRecentStickers#5ea192c9 flags:# attached:flags.0?true hash:int = messages.RecentStickers;
messages.saveRecentSticker#392718f8 flags:# attached:flags.0?true id:InputDocument unsave:Bool = Bool;
messages.clearRecentStickers#8999602d flags:# attached:flags.0?true = Bool;
messages.getArchivedStickers#906e241f offset_id:long limit:int = messages.ArchivedStickers;
messages.getArchivedStickers#57f17692 flags:# masks:flags.0?true offset_id:long limit:int = messages.ArchivedStickers;
messages.setGameScore#dfbc7c1f flags:# edit_message:flags.0?true peer:InputPeer id:int user_id:InputUser game_id:int score:int = Updates;
messages.setInlineGameScore#54f882f1 flags:# edit_message:flags.0?true id:InputBotInlineMessageID user_id:InputUser game_id:int score:int = Bool;
messages.getMaskStickers#65b8c79f hash:int = messages.AllStickers;

View file

@ -2997,8 +2997,9 @@ void _serialize_updateBotCallbackQuery(MTPStringLogger &to, int32 stage, int32 l
case 2: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" peer: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" msg_id: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" data: "); ++stages.back(); if (flag & MTPDupdateBotCallbackQuery::Flag::f_data) { types.push_back(mtpc_bytes+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break;
case 6: to.add(" game_id: "); ++stages.back(); if (flag & MTPDupdateBotCallbackQuery::Flag::f_game_id) { types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break;
case 5: to.add(" chat_instance: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 6: to.add(" data: "); ++stages.back(); if (flag & MTPDupdateBotCallbackQuery::Flag::f_data) { types.push_back(mtpc_bytes+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break;
case 7: to.add(" game_id: "); ++stages.back(); if (flag & MTPDupdateBotCallbackQuery::Flag::f_game_id) { types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
}
@ -3032,8 +3033,9 @@ void _serialize_updateInlineBotCallbackQuery(MTPStringLogger &to, int32 stage, i
case 1: to.add(" query_id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 2: to.add(" user_id: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" msg_id: "); ++stages.back(); types.push_back(0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 4: to.add(" data: "); ++stages.back(); if (flag & MTPDupdateInlineBotCallbackQuery::Flag::f_data) { types.push_back(mtpc_bytes+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break;
case 5: to.add(" game_id: "); ++stages.back(); if (flag & MTPDupdateInlineBotCallbackQuery::Flag::f_game_id) { types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break;
case 4: to.add(" chat_instance: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 5: to.add(" data: "); ++stages.back(); if (flag & MTPDupdateInlineBotCallbackQuery::Flag::f_data) { types.push_back(mtpc_bytes+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break;
case 6: to.add(" game_id: "); ++stages.back(); if (flag & MTPDupdateInlineBotCallbackQuery::Flag::f_game_id) { types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); } else { to.add("[ SKIPPED BY BIT 1 IN FIELD flags ]"); } break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
}
@ -8437,6 +8439,8 @@ void _serialize_messages_getRecentStickers(MTPStringLogger &to, int32 stage, int
}
void _serialize_messages_getArchivedStickers(MTPStringLogger &to, int32 stage, int32 lev, Types &types, Types &vtypes, StagesFlags &stages, StagesFlags &flags, const mtpPrime *start, const mtpPrime *end, int32 iflag) {
MTPmessages_getArchivedStickers::Flags flag(iflag);
if (stage) {
to.add(",\n").addSpaces(lev);
} else {
@ -8444,8 +8448,10 @@ void _serialize_messages_getArchivedStickers(MTPStringLogger &to, int32 stage, i
to.add("\n").addSpaces(lev);
}
switch (stage) {
case 0: to.add(" offset_id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 0: to.add(" flags: "); ++stages.back(); if (start >= end) throw Exception("start >= end in flags"); else flags.back() = *start; types.push_back(mtpc_flags); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 1: to.add(" masks: "); ++stages.back(); if (flag & MTPmessages_getArchivedStickers::Flag::f_masks) { to.add("YES [ BY BIT 0 IN FIELD flags ]"); } else { to.add("[ SKIPPED BY BIT 0 IN FIELD flags ]"); } break;
case 2: to.add(" offset_id: "); ++stages.back(); types.push_back(mtpc_long+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
case 3: to.add(" limit: "); ++stages.back(); types.push_back(mtpc_int+0); vtypes.push_back(0); stages.push_back(0); flags.push_back(0); break;
default: to.add("}"); types.pop_back(); vtypes.pop_back(); stages.pop_back(); flags.pop_back(); break;
}
}

View file

@ -284,9 +284,9 @@ enum {
mtpc_updateBotInlineSend = 0xe48f964,
mtpc_updateEditChannelMessage = 0x1b3f4df7,
mtpc_updateChannelPinnedMessage = 0x98592475,
mtpc_updateBotCallbackQuery = 0x81c5615f,
mtpc_updateBotCallbackQuery = 0x4bf9a8a0,
mtpc_updateEditMessage = 0xe40370a3,
mtpc_updateInlineBotCallbackQuery = 0xd618a28b,
mtpc_updateInlineBotCallbackQuery = 0x4f2f45d1,
mtpc_updateReadChannelOutbox = 0x25d6c9c7,
mtpc_updateDraftMessage = 0xee2bb969,
mtpc_updateReadFeaturedStickers = 0x571d2742,
@ -653,7 +653,7 @@ enum {
mtpc_messages_getRecentStickers = 0x5ea192c9,
mtpc_messages_saveRecentSticker = 0x392718f8,
mtpc_messages_clearRecentStickers = 0x8999602d,
mtpc_messages_getArchivedStickers = 0x906e241f,
mtpc_messages_getArchivedStickers = 0x57f17692,
mtpc_messages_setGameScore = 0xdfbc7c1f,
mtpc_messages_setInlineGameScore = 0x54f882f1,
mtpc_messages_getMaskStickers = 0x65b8c79f,
@ -12365,7 +12365,7 @@ public:
MTPDupdateBotCallbackQuery() {
}
MTPDupdateBotCallbackQuery(const MTPflags<MTPDupdateBotCallbackQuery::Flags> &_flags, const MTPlong &_query_id, MTPint _user_id, const MTPPeer &_peer, MTPint _msg_id, const MTPbytes &_data, MTPint _game_id) : vflags(_flags), vquery_id(_query_id), vuser_id(_user_id), vpeer(_peer), vmsg_id(_msg_id), vdata(_data), vgame_id(_game_id) {
MTPDupdateBotCallbackQuery(const MTPflags<MTPDupdateBotCallbackQuery::Flags> &_flags, const MTPlong &_query_id, MTPint _user_id, const MTPPeer &_peer, MTPint _msg_id, const MTPlong &_chat_instance, const MTPbytes &_data, MTPint _game_id) : vflags(_flags), vquery_id(_query_id), vuser_id(_user_id), vpeer(_peer), vmsg_id(_msg_id), vchat_instance(_chat_instance), vdata(_data), vgame_id(_game_id) {
}
MTPflags<MTPDupdateBotCallbackQuery::Flags> vflags;
@ -12373,6 +12373,7 @@ public:
MTPint vuser_id;
MTPPeer vpeer;
MTPint vmsg_id;
MTPlong vchat_instance;
MTPbytes vdata;
MTPint vgame_id;
};
@ -12405,13 +12406,14 @@ public:
MTPDupdateInlineBotCallbackQuery() {
}
MTPDupdateInlineBotCallbackQuery(const MTPflags<MTPDupdateInlineBotCallbackQuery::Flags> &_flags, const MTPlong &_query_id, MTPint _user_id, const MTPInputBotInlineMessageID &_msg_id, const MTPbytes &_data, MTPint _game_id) : vflags(_flags), vquery_id(_query_id), vuser_id(_user_id), vmsg_id(_msg_id), vdata(_data), vgame_id(_game_id) {
MTPDupdateInlineBotCallbackQuery(const MTPflags<MTPDupdateInlineBotCallbackQuery::Flags> &_flags, const MTPlong &_query_id, MTPint _user_id, const MTPInputBotInlineMessageID &_msg_id, const MTPlong &_chat_instance, const MTPbytes &_data, MTPint _game_id) : vflags(_flags), vquery_id(_query_id), vuser_id(_user_id), vmsg_id(_msg_id), vchat_instance(_chat_instance), vdata(_data), vgame_id(_game_id) {
}
MTPflags<MTPDupdateInlineBotCallbackQuery::Flags> vflags;
MTPlong vquery_id;
MTPint vuser_id;
MTPInputBotInlineMessageID vmsg_id;
MTPlong vchat_instance;
MTPbytes vdata;
MTPint vgame_id;
};
@ -21347,6 +21349,16 @@ public:
class MTPmessages_getArchivedStickers { // RPC method 'messages.getArchivedStickers'
public:
enum class Flag : int32 {
f_masks = (1 << 0),
MAX_FIELD = (1 << 0),
};
Q_DECLARE_FLAGS(Flags, Flag);
friend inline Flags operator~(Flag v) { return QFlag(~static_cast<int32>(v)); }
bool is_masks() const { return vflags.v & Flag::f_masks; }
MTPflags<MTPmessages_getArchivedStickers::Flags> vflags;
MTPlong voffset_id;
MTPint vlimit;
@ -21355,26 +21367,30 @@ public:
MTPmessages_getArchivedStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getArchivedStickers) {
read(from, end, cons);
}
MTPmessages_getArchivedStickers(const MTPlong &_offset_id, MTPint _limit) : voffset_id(_offset_id), vlimit(_limit) {
MTPmessages_getArchivedStickers(const MTPflags<MTPmessages_getArchivedStickers::Flags> &_flags, const MTPlong &_offset_id, MTPint _limit) : vflags(_flags), voffset_id(_offset_id), vlimit(_limit) {
}
uint32 innerLength() const {
return voffset_id.innerLength() + vlimit.innerLength();
return vflags.innerLength() + voffset_id.innerLength() + vlimit.innerLength();
}
mtpTypeId type() const {
return mtpc_messages_getArchivedStickers;
}
void read(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = mtpc_messages_getArchivedStickers) {
vflags.read(from, end);
voffset_id.read(from, end);
vlimit.read(from, end);
}
void write(mtpBuffer &to) const {
vflags.write(to);
voffset_id.write(to);
vlimit.write(to);
}
typedef MTPmessages_ArchivedStickers ResponseType;
};
Q_DECLARE_OPERATORS_FOR_FLAGS(MTPmessages_getArchivedStickers::Flags)
class MTPmessages_GetArchivedStickers : public MTPBoxed<MTPmessages_getArchivedStickers> {
public:
MTPmessages_GetArchivedStickers() {
@ -21383,7 +21399,7 @@ public:
}
MTPmessages_GetArchivedStickers(const mtpPrime *&from, const mtpPrime *end, mtpTypeId cons = 0) : MTPBoxed<MTPmessages_getArchivedStickers>(from, end, cons) {
}
MTPmessages_GetArchivedStickers(const MTPlong &_offset_id, MTPint _limit) : MTPBoxed<MTPmessages_getArchivedStickers>(MTPmessages_getArchivedStickers(_offset_id, _limit)) {
MTPmessages_GetArchivedStickers(const MTPflags<MTPmessages_getArchivedStickers::Flags> &_flags, const MTPlong &_offset_id, MTPint _limit) : MTPBoxed<MTPmessages_getArchivedStickers>(MTPmessages_getArchivedStickers(_flags, _offset_id, _limit)) {
}
};
@ -24140,14 +24156,14 @@ public:
inline static MTPupdate new_updateChannelPinnedMessage(MTPint _channel_id, MTPint _id) {
return MTPupdate(new MTPDupdateChannelPinnedMessage(_channel_id, _id));
}
inline static MTPupdate new_updateBotCallbackQuery(const MTPflags<MTPDupdateBotCallbackQuery::Flags> &_flags, const MTPlong &_query_id, MTPint _user_id, const MTPPeer &_peer, MTPint _msg_id, const MTPbytes &_data, MTPint _game_id) {
return MTPupdate(new MTPDupdateBotCallbackQuery(_flags, _query_id, _user_id, _peer, _msg_id, _data, _game_id));
inline static MTPupdate new_updateBotCallbackQuery(const MTPflags<MTPDupdateBotCallbackQuery::Flags> &_flags, const MTPlong &_query_id, MTPint _user_id, const MTPPeer &_peer, MTPint _msg_id, const MTPlong &_chat_instance, const MTPbytes &_data, MTPint _game_id) {
return MTPupdate(new MTPDupdateBotCallbackQuery(_flags, _query_id, _user_id, _peer, _msg_id, _chat_instance, _data, _game_id));
}
inline static MTPupdate new_updateEditMessage(const MTPMessage &_message, MTPint _pts, MTPint _pts_count) {
return MTPupdate(new MTPDupdateEditMessage(_message, _pts, _pts_count));
}
inline static MTPupdate new_updateInlineBotCallbackQuery(const MTPflags<MTPDupdateInlineBotCallbackQuery::Flags> &_flags, const MTPlong &_query_id, MTPint _user_id, const MTPInputBotInlineMessageID &_msg_id, const MTPbytes &_data, MTPint _game_id) {
return MTPupdate(new MTPDupdateInlineBotCallbackQuery(_flags, _query_id, _user_id, _msg_id, _data, _game_id));
inline static MTPupdate new_updateInlineBotCallbackQuery(const MTPflags<MTPDupdateInlineBotCallbackQuery::Flags> &_flags, const MTPlong &_query_id, MTPint _user_id, const MTPInputBotInlineMessageID &_msg_id, const MTPlong &_chat_instance, const MTPbytes &_data, MTPint _game_id) {
return MTPupdate(new MTPDupdateInlineBotCallbackQuery(_flags, _query_id, _user_id, _msg_id, _chat_instance, _data, _game_id));
}
inline static MTPupdate new_updateReadChannelOutbox(MTPint _channel_id, MTPint _max_id) {
return MTPupdate(new MTPDupdateReadChannelOutbox(_channel_id, _max_id));
@ -29744,7 +29760,7 @@ inline uint32 MTPupdate::innerLength() const {
}
case mtpc_updateBotCallbackQuery: {
const MTPDupdateBotCallbackQuery &v(c_updateBotCallbackQuery());
return v.vflags.innerLength() + v.vquery_id.innerLength() + v.vuser_id.innerLength() + v.vpeer.innerLength() + v.vmsg_id.innerLength() + (v.has_data() ? v.vdata.innerLength() : 0) + (v.has_game_id() ? v.vgame_id.innerLength() : 0);
return v.vflags.innerLength() + v.vquery_id.innerLength() + v.vuser_id.innerLength() + v.vpeer.innerLength() + v.vmsg_id.innerLength() + v.vchat_instance.innerLength() + (v.has_data() ? v.vdata.innerLength() : 0) + (v.has_game_id() ? v.vgame_id.innerLength() : 0);
}
case mtpc_updateEditMessage: {
const MTPDupdateEditMessage &v(c_updateEditMessage());
@ -29752,7 +29768,7 @@ inline uint32 MTPupdate::innerLength() const {
}
case mtpc_updateInlineBotCallbackQuery: {
const MTPDupdateInlineBotCallbackQuery &v(c_updateInlineBotCallbackQuery());
return v.vflags.innerLength() + v.vquery_id.innerLength() + v.vuser_id.innerLength() + v.vmsg_id.innerLength() + (v.has_data() ? v.vdata.innerLength() : 0) + (v.has_game_id() ? v.vgame_id.innerLength() : 0);
return v.vflags.innerLength() + v.vquery_id.innerLength() + v.vuser_id.innerLength() + v.vmsg_id.innerLength() + v.vchat_instance.innerLength() + (v.has_data() ? v.vdata.innerLength() : 0) + (v.has_game_id() ? v.vgame_id.innerLength() : 0);
}
case mtpc_updateReadChannelOutbox: {
const MTPDupdateReadChannelOutbox &v(c_updateReadChannelOutbox());
@ -30069,6 +30085,7 @@ inline void MTPupdate::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeI
v.vuser_id.read(from, end);
v.vpeer.read(from, end);
v.vmsg_id.read(from, end);
v.vchat_instance.read(from, end);
if (v.has_data()) { v.vdata.read(from, end); } else { v.vdata = MTPbytes(); }
if (v.has_game_id()) { v.vgame_id.read(from, end); } else { v.vgame_id = MTPint(); }
} break;
@ -30086,6 +30103,7 @@ inline void MTPupdate::read(const mtpPrime *&from, const mtpPrime *end, mtpTypeI
v.vquery_id.read(from, end);
v.vuser_id.read(from, end);
v.vmsg_id.read(from, end);
v.vchat_instance.read(from, end);
if (v.has_data()) { v.vdata.read(from, end); } else { v.vdata = MTPbytes(); }
if (v.has_game_id()) { v.vgame_id.read(from, end); } else { v.vgame_id = MTPint(); }
} break;
@ -30362,6 +30380,7 @@ inline void MTPupdate::write(mtpBuffer &to) const {
v.vuser_id.write(to);
v.vpeer.write(to);
v.vmsg_id.write(to);
v.vchat_instance.write(to);
if (v.has_data()) v.vdata.write(to);
if (v.has_game_id()) v.vgame_id.write(to);
} break;
@ -30377,6 +30396,7 @@ inline void MTPupdate::write(mtpBuffer &to) const {
v.vquery_id.write(to);
v.vuser_id.write(to);
v.vmsg_id.write(to);
v.vchat_instance.write(to);
if (v.has_data()) v.vdata.write(to);
if (v.has_game_id()) v.vgame_id.write(to);
} break;
@ -30681,15 +30701,15 @@ inline MTPupdate MTP_updateChannelPinnedMessage(MTPint _channel_id, MTPint _id)
return MTP::internal::TypeCreator::new_updateChannelPinnedMessage(_channel_id, _id);
}
Q_DECLARE_OPERATORS_FOR_FLAGS(MTPDupdateBotCallbackQuery::Flags)
inline MTPupdate MTP_updateBotCallbackQuery(const MTPflags<MTPDupdateBotCallbackQuery::Flags> &_flags, const MTPlong &_query_id, MTPint _user_id, const MTPPeer &_peer, MTPint _msg_id, const MTPbytes &_data, MTPint _game_id) {
return MTP::internal::TypeCreator::new_updateBotCallbackQuery(_flags, _query_id, _user_id, _peer, _msg_id, _data, _game_id);
inline MTPupdate MTP_updateBotCallbackQuery(const MTPflags<MTPDupdateBotCallbackQuery::Flags> &_flags, const MTPlong &_query_id, MTPint _user_id, const MTPPeer &_peer, MTPint _msg_id, const MTPlong &_chat_instance, const MTPbytes &_data, MTPint _game_id) {
return MTP::internal::TypeCreator::new_updateBotCallbackQuery(_flags, _query_id, _user_id, _peer, _msg_id, _chat_instance, _data, _game_id);
}
inline MTPupdate MTP_updateEditMessage(const MTPMessage &_message, MTPint _pts, MTPint _pts_count) {
return MTP::internal::TypeCreator::new_updateEditMessage(_message, _pts, _pts_count);
}
Q_DECLARE_OPERATORS_FOR_FLAGS(MTPDupdateInlineBotCallbackQuery::Flags)
inline MTPupdate MTP_updateInlineBotCallbackQuery(const MTPflags<MTPDupdateInlineBotCallbackQuery::Flags> &_flags, const MTPlong &_query_id, MTPint _user_id, const MTPInputBotInlineMessageID &_msg_id, const MTPbytes &_data, MTPint _game_id) {
return MTP::internal::TypeCreator::new_updateInlineBotCallbackQuery(_flags, _query_id, _user_id, _msg_id, _data, _game_id);
inline MTPupdate MTP_updateInlineBotCallbackQuery(const MTPflags<MTPDupdateInlineBotCallbackQuery::Flags> &_flags, const MTPlong &_query_id, MTPint _user_id, const MTPInputBotInlineMessageID &_msg_id, const MTPlong &_chat_instance, const MTPbytes &_data, MTPint _game_id) {
return MTP::internal::TypeCreator::new_updateInlineBotCallbackQuery(_flags, _query_id, _user_id, _msg_id, _chat_instance, _data, _game_id);
}
inline MTPupdate MTP_updateReadChannelOutbox(MTPint _channel_id, MTPint _max_id) {
return MTP::internal::TypeCreator::new_updateReadChannelOutbox(_channel_id, _max_id);

View file

@ -888,6 +888,21 @@ int StickerPanInner::countHeight(bool plain) {
return qMax(minLastH, result) + st::stickerPanPadding;
}
void StickerPanInner::installedLocally(uint64 setId) {
_installedLocallySets.insert(setId);
}
void StickerPanInner::notInstalledLocally(uint64 setId) {
_installedLocallySets.remove(setId);
}
void StickerPanInner::clearInstalledLocally() {
if (!_installedLocallySets.empty()) {
_installedLocallySets.clear();
refreshStickers();
}
}
StickerPanInner::~StickerPanInner() {
clearInlineRows(true);
deleteUnusedGifLayouts();
@ -1009,6 +1024,11 @@ void StickerPanInner::paintStickers(Painter &p, const QRect &r) {
p.drawTextLeft(add.x() - (st::featuredStickersAdd.width / 2), add.y() + textTop, width(), _addText, _addWidth);
widthForTitle -= add.width() - (st::featuredStickersAdd.width / 2);
} else {
auto add = featuredAddRect(c);
int checkx = add.left() + (add.width() - st::stickersFeaturedInstalled.width()) / 2;
int checky = add.top() + (add.height() - st::stickersFeaturedInstalled.height()) / 2;
st::stickersFeaturedInstalled.paint(p, QPoint(checkx, checky), width());
}
if (set.flags & MTPDstickerSet_ClientFlag::f_unread) {
widthForTitle -= st::stickersFeaturedUnreadSize + st::stickersFeaturedUnreadSkip;
@ -1362,6 +1382,7 @@ void StickerPanInner::hideFinish(bool completely) {
for_const (auto item, _inlineLayouts) {
itemForget(item);
}
clearInstalledLocally();
}
if (_setGifCommand && _section == Section::Gifs) {
App::insertBotCommand(qsl(""), true);
@ -1404,7 +1425,7 @@ void StickerPanInner::refreshStickers() {
_settings.hide();
}
emit refreshIcons();
emit refreshIcons(kRefreshIconsNoAnimation);
// Hack: skip over animations to the very end,
// so that currently selected sticker won't get
@ -1497,7 +1518,7 @@ void StickerPanInner::refreshSavedGifs() {
update();
}
emit refreshIcons();
emit refreshIcons(kRefreshIconsNoAnimation);
updateSelected();
}
@ -1763,7 +1784,7 @@ int StickerPanInner::refreshInlineRows(UserData *bot, const InlineCacheEntry *en
if (h != height()) resize(width(), h);
update();
emit refreshIcons();
emit refreshIcons(kRefreshIconsNoAnimation);
_lastMousePos = QCursor::pos();
updateSelected();
@ -1880,7 +1901,11 @@ void StickerPanInner::appendSet(Sets &to, uint64 setId, AppendSkip skip) {
auto it = sets.constFind(setId);
if (it == sets.cend() || it->stickers.isEmpty()) return;
if ((skip == AppendSkip::Archived) && (it->flags & MTPDstickerSet::Flag::f_archived)) return;
if ((skip == AppendSkip::Installed) && (it->flags & MTPDstickerSet::Flag::f_installed) && !(it->flags & MTPDstickerSet::Flag::f_archived)) return;
if ((skip == AppendSkip::Installed) && (it->flags & MTPDstickerSet::Flag::f_installed) && !(it->flags & MTPDstickerSet::Flag::f_archived)) {
if (!_installedLocallySets.contains(setId)) {
return;
}
}
to.push_back(Set(it->id, it->flags, it->title, it->stickers.size() + 1, it->stickers));
}
@ -2338,7 +2363,7 @@ void StickerPanInner::showStickerSet(uint64 setId) {
_section = Section::Featured;
refreshRecentStickers(true);
emit refreshIcons();
emit refreshIcons(kRefreshIconsScrollAnimation);
update();
}
@ -2364,7 +2389,7 @@ void StickerPanInner::showStickerSet(uint64 setId) {
emit scrollUpdated();
if (needRefresh) {
emit refreshIcons();
emit refreshIcons(kRefreshIconsScrollAnimation);
}
_lastMousePos = QCursor::pos();
@ -2598,7 +2623,7 @@ EmojiPan::EmojiPan(QWidget *parent) : TWidget(parent)
connect(&s_inner, SIGNAL(displaySet(quint64)), this, SLOT(onDisplaySet(quint64)));
connect(&s_inner, SIGNAL(installSet(quint64)), this, SLOT(onInstallSet(quint64)));
connect(&s_inner, SIGNAL(removeSet(quint64)), this, SLOT(onRemoveSet(quint64)));
connect(&s_inner, SIGNAL(refreshIcons()), this, SLOT(onRefreshIcons()));
connect(&s_inner, SIGNAL(refreshIcons(bool)), this, SLOT(onRefreshIcons(bool)));
connect(&e_inner, SIGNAL(needRefreshPanels()), this, SLOT(onRefreshPanels()));
connect(&s_inner, SIGNAL(needRefreshPanels()), this, SLOT(onRefreshPanels()));
@ -2986,7 +3011,7 @@ void EmojiPan::refreshSavedGifs() {
}
}
void EmojiPan::onRefreshIcons() {
void EmojiPan::onRefreshIcons(bool scrollAnimation) {
_iconOver = -1;
_iconHovers.clear();
_iconAnimations.clear();
@ -3008,7 +3033,7 @@ void EmojiPan::onRefreshIcons() {
updatePanelsPositions(s_panels, s_scroll.scrollTop());
updateSelected();
if (_stickersShown) {
validateSelectedIcon();
validateSelectedIcon(scrollAnimation ? ValidateIconAnimations::Scroll : ValidateIconAnimations::None);
updateContentHeight();
}
updateIcons();
@ -3418,7 +3443,7 @@ void EmojiPan::onScrollStickers() {
updatePanelsPositions(s_panels, st);
validateSelectedIcon(true);
validateSelectedIcon(ValidateIconAnimations::Full);
if (st + s_scroll.height() > s_scroll.scrollTopMax()) {
onInlineRequest();
}
@ -3426,7 +3451,7 @@ void EmojiPan::onScrollStickers() {
s_inner.setVisibleTopBottom(st, st + s_scroll.height());
}
void EmojiPan::validateSelectedIcon(bool animated) {
void EmojiPan::validateSelectedIcon(ValidateIconAnimations animations) {
uint64 setId = s_inner.currentSet(s_scroll.scrollTop());
int32 newSel = 0;
for (int i = 0, l = _icons.size(); i < l; ++i) {
@ -3437,14 +3462,21 @@ void EmojiPan::validateSelectedIcon(bool animated) {
}
if (newSel != _iconSel) {
_iconSel = newSel;
if (animated) {
_iconSelX.start(newSel * st::rbEmoji.width);
auto iconSelXFinal = newSel * st::rbEmoji.width;
if (animations == ValidateIconAnimations::Full) {
_iconSelX.start(iconSelXFinal);
} else {
_iconSelX = anim::ivalue(newSel * st::rbEmoji.width, newSel * st::rbEmoji.width);
_iconSelX = anim::ivalue(iconSelXFinal, iconSelXFinal);
}
auto iconsXFinal = snap((2 * newSel - 7) * int(st::rbEmoji.width) / 2, 0, _iconsMax);
if (animations == ValidateIconAnimations::None) {
_iconsX = anim::ivalue(iconsXFinal, iconsXFinal);
_a_icons.stop();
} else {
_iconsX.start(iconsXFinal);
_iconsStartAnim = getms();
_a_icons.start();
}
_iconsX.start(snap((2 * newSel - 7) * int(st::rbEmoji.width) / 2, 0, _iconsMax));
_iconsStartAnim = getms();
_a_icons.start();
updateSelected();
updateIcons();
}
@ -3467,7 +3499,7 @@ void EmojiPan::onSwitch() {
if (cShowingSavedGifs()) {
s_inner.showFinish();
}
validateSelectedIcon();
validateSelectedIcon(ValidateIconAnimations::None);
updateContentHeight();
}
_iconOver = -1;
@ -3513,7 +3545,7 @@ void EmojiPan::onInstallSet(quint64 setId) {
auto it = sets.constFind(setId);
if (it != sets.cend()) {
MTP::send(MTPmessages_InstallStickerSet(Stickers::inputSetId(*it), MTP_bool(false)), rpcDone(&EmojiPan::installSetDone), rpcFail(&EmojiPan::installSetFail, setId));
s_inner.installedLocally(setId);
Stickers::installLocally(setId);
}
}
@ -3528,6 +3560,7 @@ bool EmojiPan::installSetFail(uint64 setId, const RPCError &error) {
if (MTP::isDefaultHandledError(error)) {
return false;
}
s_inner.notInstalledLocally(setId);
Stickers::undoInstallLocally(setId);
return true;
}

View file

@ -254,6 +254,10 @@ public:
}
int countHeight(bool plain = false);
void installedLocally(uint64 setId);
void notInstalledLocally(uint64 setId);
void clearInstalledLocally();
~StickerPanInner();
protected:
@ -281,7 +285,7 @@ signals:
void installSet(quint64 setId);
void removeSet(quint64 setId);
void refreshIcons();
void refreshIcons(bool scrollAnimation);
void emptyInlineRows();
void switchToEmoji();
@ -294,6 +298,9 @@ signals:
void saveConfigDelayed(int32 delay);
private:
static constexpr bool kRefreshIconsScrollAnimation = true;
static constexpr bool kRefreshIconsNoAnimation = false;
struct Set {
Set(uint64 id, MTPDstickerSet::Flags flags, const QString &title, int32 hoversSize, const StickerPack &pack = StickerPack()) : id(id), flags(flags), title(title), hovers(hoversSize, 0), pack(pack) {
}
@ -346,6 +353,7 @@ private:
Sets _mySets;
Sets _featuredSets;
OrderedSet<uint64> _installedLocallySets;
QList<bool> _custom;
enum class Section {
@ -527,10 +535,12 @@ public:
}
public slots:
void hideStart();
void refreshStickers();
private slots:
void refreshSavedGifs();
void hideStart();
void hideFinish();
void showStart();
@ -547,7 +557,7 @@ public slots:
void onRemoveSetSure();
void onDelayedHide();
void onRefreshIcons();
void onRefreshIcons(bool scrollAnimation);
void onRefreshPanels();
void onSaveConfig();
@ -572,7 +582,12 @@ private:
void paintStickerSettingsIcon(Painter &p) const;
void paintFeaturedStickerSetsBadge(Painter &p, int iconLeft) const;
void validateSelectedIcon(bool animated = false);
enum class ValidateIconAnimations {
Full,
Scroll,
None,
};
void validateSelectedIcon(ValidateIconAnimations animations);
void updateContentHeight();
void leaveToChildEvent(QEvent *e, QWidget *child);