Track only strings in BotCommand struct.

This commit is contained in:
John Preston 2021-07-01 12:49:37 +03:00
parent a8df3dcf91
commit 93d99d6173
4 changed files with 55 additions and 68 deletions

View file

@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
#include "ui/widgets/scroll_area.h" #include "ui/widgets/scroll_area.h"
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
#include "ui/text/text_options.h"
#include "ui/image/image.h" #include "ui/image/image.h"
#include "ui/effects/path_shift_gradient.h" #include "ui/effects/path_shift_gradient.h"
#include "ui/ui_utility.h" #include "ui/ui_utility.h"
@ -441,7 +442,7 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
} else if (_type == Type::BotCommands) { } else if (_type == Type::BotCommands) {
bool listAllSuggestions = _filter.isEmpty(); bool listAllSuggestions = _filter.isEmpty();
bool hasUsername = _filter.indexOf('@') > 0; bool hasUsername = _filter.indexOf('@') > 0;
base::flat_map<UserData*, bool> bots; base::flat_set<not_null<UserData*>> bots;
int32 cnt = 0; int32 cnt = 0;
if (_chat) { if (_chat) {
if (_chat->noParticipantInfo()) { if (_chat->noParticipantInfo()) {
@ -453,10 +454,10 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
} else if (!user->botInfo->inited) { } else if (!user->botInfo->inited) {
user->session().api().requestFullPeer(user); user->session().api().requestFullPeer(user);
} }
if (user->botInfo->commands.isEmpty()) { if (user->botInfo->commands.empty()) {
continue; continue;
} }
bots.emplace(user, true); bots.emplace(user);
cnt += user->botInfo->commands.size(); cnt += user->botInfo->commands.size();
} }
} }
@ -465,7 +466,7 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
_user->session().api().requestFullPeer(_user); _user->session().api().requestFullPeer(_user);
} }
cnt = _user->botInfo->commands.size(); cnt = _user->botInfo->commands.size();
bots.emplace(_user, true); bots.emplace(_user);
} else if (_channel && _channel->isMegagroup()) { } else if (_channel && _channel->isMegagroup()) {
if (_channel->mgInfo->bots.empty()) { if (_channel->mgInfo->bots.empty()) {
if (!_channel->mgInfo->botStatus) { if (!_channel->mgInfo->botStatus) {
@ -478,15 +479,25 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
} else if (!user->botInfo->inited) { } else if (!user->botInfo->inited) {
user->session().api().requestFullPeer(user); user->session().api().requestFullPeer(user);
} }
if (user->botInfo->commands.isEmpty()) { if (user->botInfo->commands.empty()) {
continue; continue;
} }
bots.emplace(user, true); bots.emplace(user);
cnt += user->botInfo->commands.size(); cnt += user->botInfo->commands.size();
} }
} }
} }
if (cnt) { if (cnt) {
const auto make = [&](
not_null<UserData*> user,
const BotCommand &command) {
return BotCommandRow{
user,
command.command,
command.description,
user->activeUserpicView()
};
};
brows.reserve(cnt); brows.reserve(cnt);
int32 botStatus = _chat ? _chat->botStatus : ((_channel && _channel->isMegagroup()) ? _channel->mgInfo->botStatus : -1); int32 botStatus = _chat ? _chat->botStatus : ((_channel && _channel->isMegagroup()) ? _channel->mgInfo->botStatus : -1);
if (_chat) { if (_chat) {
@ -498,32 +509,32 @@ void FieldAutocomplete::updateFiltered(bool resetScroll) {
} else if (!user->botInfo->inited) { } else if (!user->botInfo->inited) {
user->session().api().requestFullPeer(user); user->session().api().requestFullPeer(user);
} }
if (user->botInfo->commands.isEmpty()) { if (user->botInfo->commands.empty()) {
continue; continue;
} }
bots.remove(user); bots.remove(user);
for (auto j = 0, l = user->botInfo->commands.size(); j != l; ++j) { for (const auto &command : user->botInfo->commands) {
if (!listAllSuggestions) { if (!listAllSuggestions) {
auto toFilter = (hasUsername || botStatus == 0 || botStatus == 2) auto toFilter = (hasUsername || botStatus == 0 || botStatus == 2)
? user->botInfo->commands.at(j).command + '@' + user->username ? command.command + '@' + user->username
: user->botInfo->commands.at(j).command; : command.command;
if (!toFilter.startsWith(_filter, Qt::CaseInsensitive)/* || toFilter.size() == _filter.size()*/) { if (!toFilter.startsWith(_filter, Qt::CaseInsensitive)/* || toFilter.size() == _filter.size()*/) {
continue; continue;
} }
} }
brows.push_back({ user, &user->botInfo->commands.at(j) }); brows.push_back(make(user, command));
} }
} }
} }
if (!bots.empty()) { if (!bots.empty()) {
for (auto i = bots.cbegin(), e = bots.cend(); i != e; ++i) { for (auto i = bots.cbegin(), e = bots.cend(); i != e; ++i) {
UserData *user = i->first; const auto user = *i;
for (int32 j = 0, l = user->botInfo->commands.size(); j < l; ++j) { for (const auto &command : user->botInfo->commands) {
if (!listAllSuggestions) { if (!listAllSuggestions) {
QString toFilter = (hasUsername || botStatus == 0 || botStatus == 2) ? user->botInfo->commands.at(j).command + '@' + user->username : user->botInfo->commands.at(j).command; QString toFilter = (hasUsername || botStatus == 0 || botStatus == 2) ? command.command + '@' + user->username : command.command;
if (!toFilter.startsWith(_filter, Qt::CaseInsensitive)/* || toFilter.size() == _filter.size()*/) continue; if (!toFilter.startsWith(_filter, Qt::CaseInsensitive)/* || toFilter.size() == _filter.size()*/) continue;
} }
brows.push_back({ user, &user->botInfo->commands.at(j) }); brows.push_back(make(user, command));
} }
} }
} }
@ -940,8 +951,7 @@ void FieldAutocomplete::Inner::paintEvent(QPaintEvent *e) {
auto &row = _brows->at(i); auto &row = _brows->at(i);
const auto user = row.user; const auto user = row.user;
const auto command = row.command; auto toHighlight = row.command;
auto toHighlight = command->command;
int32 botStatus = _parent->chat() ? _parent->chat()->botStatus : ((_parent->channel() && _parent->channel()->isMegagroup()) ? _parent->channel()->mgInfo->botStatus : -1); int32 botStatus = _parent->chat() ? _parent->chat()->botStatus : ((_parent->channel() && _parent->channel()->isMegagroup()) ? _parent->channel()->mgInfo->botStatus : -1);
if (hasUsername || botStatus == 0 || botStatus == 2) { if (hasUsername || botStatus == 0 || botStatus == 2) {
toHighlight += '@' + user->username; toHighlight += '@' + user->username;
@ -959,9 +969,16 @@ void FieldAutocomplete::Inner::paintEvent(QPaintEvent *e) {
auto addleft = commandTextWidth + st::mentionPadding.left(); auto addleft = commandTextWidth + st::mentionPadding.left();
auto widthleft = mentionwidth - addleft; auto widthleft = mentionwidth - addleft;
if (widthleft > st::mentionFont->elidew && !command->descriptionText().isEmpty()) { if (!row.description.isEmpty()
&& row.descriptionText.isEmpty()) {
row.descriptionText.setText(
st::defaultTextStyle,
row.description,
Ui::NameTextOptions());
}
if (widthleft > st::mentionFont->elidew && !row.descriptionText.isEmpty()) {
p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p); p.setPen((selected ? st::mentionFgOver : st::mentionFg)->p);
command->descriptionText().drawElided(p, mentionleft + addleft, i * st::mentionHeight + st::mentionTop, widthleft); row.descriptionText.drawElided(p, mentionleft + addleft, i * st::mentionHeight + st::mentionTop, widthleft);
} }
} }
} }
@ -1063,7 +1080,7 @@ bool FieldAutocomplete::Inner::chooseAtIndex(
} else if (!_brows->empty()) { } else if (!_brows->empty()) {
if (index < _brows->size()) { if (index < _brows->size()) {
const auto user = _brows->at(index).user; const auto user = _brows->at(index).user;
const auto command = _brows->at(index).command; const auto &command = _brows->at(index).command;
const auto botStatus = _parent->chat() const auto botStatus = _parent->chat()
? _parent->chat()->botStatus ? _parent->chat()->botStatus
: ((_parent->channel() && _parent->channel()->isMegagroup()) : ((_parent->channel() && _parent->channel()->isMegagroup())
@ -1074,7 +1091,7 @@ bool FieldAutocomplete::Inner::chooseAtIndex(
|| botStatus == 2 || botStatus == 2
|| _parent->filter().indexOf('@') > 0); || _parent->filter().indexOf('@') > 0);
const auto commandString = QString("/%1%2").arg( const auto commandString = QString("/%1%2").arg(
command->command, command,
insertUsername ? ('@' + user->username) : QString()); insertUsername ? ('@' + user->username) : QString());
_botCommandChosen.fire({ commandString, method }); _botCommandChosen.fire({ commandString, method });

View file

@ -136,8 +136,10 @@ private:
struct BotCommandRow { struct BotCommandRow {
not_null<UserData*> user; not_null<UserData*> user;
not_null<const BotCommand*> command; QString command;
QString description;
std::shared_ptr<Data::CloudImageView> userpic; std::shared_ptr<Data::CloudImageView> userpic;
Ui::Text::String descriptionText;
}; };
using HashtagRows = std::vector<QString>; using HashtagRows = std::vector<QString>;

View file

@ -24,32 +24,6 @@ using UpdateFlag = Data::PeerUpdate::Flag;
} // namespace } // namespace
BotCommand::BotCommand(
const QString &command,
const QString &description)
: command(command)
, _description(description) {
}
bool BotCommand::setDescription(const QString &description) {
if (_description != description) {
_description = description;
_descriptionText = Ui::Text::String();
return true;
}
return false;
}
const Ui::Text::String &BotCommand::descriptionText() const {
if (_descriptionText.isEmpty() && !_description.isEmpty()) {
_descriptionText.setText(
st::defaultTextStyle,
_description,
Ui::NameTextOptions());
}
return _descriptionText;
}
UserData::UserData(not_null<Data::Session*> owner, PeerId id) UserData::UserData(not_null<Data::Session*> owner, PeerId id)
: PeerData(owner, id) { : PeerData(owner, id) {
} }
@ -132,7 +106,7 @@ void UserData::setBotInfoVersion(int version) {
botInfo->version = version; botInfo->version = version;
owner().userIsBotChanged(this); owner().userIsBotChanged(this);
} else if (botInfo->version < version) { } else if (botInfo->version < version) {
if (!botInfo->commands.isEmpty()) { if (!botInfo->commands.empty()) {
botInfo->commands.clear(); botInfo->commands.clear();
owner().botCommandsChanged(this); owner().botCommandsChanged(this);
} }
@ -162,17 +136,21 @@ void UserData::setBotInfo(const MTPBotInfo &info) {
int32 j = 0; int32 j = 0;
for (const auto &command : v) { for (const auto &command : v) {
command.match([&](const MTPDbotCommand &data) { command.match([&](const MTPDbotCommand &data) {
const auto cmd = qs(data.vcommand()); const auto command = qs(data.vcommand());
const auto desc = qs(data.vdescription()); const auto description = qs(data.vdescription());
if (botInfo->commands.size() <= j) { if (botInfo->commands.size() <= j) {
botInfo->commands.push_back(BotCommand(cmd, desc)); botInfo->commands.push_back({
.command = command,
.description = description,
});
changedCommands = true; changedCommands = true;
} else { } else {
if (botInfo->commands[j].command != cmd) { if (botInfo->commands[j].command != command) {
botInfo->commands[j].command = cmd; botInfo->commands[j].command = command;
changedCommands = true; changedCommands = true;
} }
if (botInfo->commands[j].setDescription(desc)) { if (botInfo->commands[j].description != description) {
botInfo->commands[j].description = description;
changedCommands = true; changedCommands = true;
} }
} }

View file

@ -10,19 +10,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_peer.h" #include "data/data_peer.h"
#include "dialogs/dialogs_key.h" #include "dialogs/dialogs_key.h"
class BotCommand { struct BotCommand {
public:
BotCommand(const QString &command, const QString &description);
bool setDescription(const QString &description);
const Ui::Text::String &descriptionText() const;
QString command; QString command;
QString description;
private:
QString _description;
mutable Ui::Text::String _descriptionText;
}; };
struct BotInfo { struct BotInfo {
@ -31,7 +21,7 @@ struct BotInfo {
bool cantJoinGroups = false; bool cantJoinGroups = false;
int version = 0; int version = 0;
QString description, inlinePlaceholder; QString description, inlinePlaceholder;
QList<BotCommand> commands; std::vector<BotCommand> commands;
Ui::Text::String text = { int(st::msgMinWidth) }; // description Ui::Text::String text = { int(st::msgMinWidth) }; // description
QString startToken, startGroupToken, shareGameShortName; QString startToken, startGroupToken, shareGameShortName;