mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 10:11:41 -05:00
remembering last used inline bots, showing them in mentions dropdown, 9015006 beta
This commit is contained in:
parent
85f46cef8c
commit
cb2df51af6
15 changed files with 308 additions and 198 deletions
|
@ -705,10 +705,11 @@ void Application::checkMapVersion() {
|
||||||
if (Local::oldMapVersion() < AppVersion) {
|
if (Local::oldMapVersion() < AppVersion) {
|
||||||
if (Local::oldMapVersion()) {
|
if (Local::oldMapVersion()) {
|
||||||
QString versionFeatures;
|
QString versionFeatures;
|
||||||
if (cDevVersion() && Local::oldMapVersion() < 9014) {
|
if (cDevVersion() && Local::oldMapVersion() < 9016) {
|
||||||
versionFeatures = QString::fromUtf8("\xe2\x80\x94 Sticker management: manually rearrange your sticker packs, pack order is now synced across all your devices\n\xe2\x80\x94 Click and hold on a sticker to preview it before sending\n\xe2\x80\x94 New context menu for chats in chats list\n\xe2\x80\x94 Support for all existing emoji");// .replace('@', qsl("@") + QChar(0x200D));
|
// versionFeatures = QString::fromUtf8("\xe2\x80\x94 Sticker management: manually rearrange your sticker packs, pack order is now synced across all your devices\n\xe2\x80\x94 Click and hold on a sticker to preview it before sending\n\xe2\x80\x94 New context menu for chats in chats list\n\xe2\x80\x94 Support for all existing emoji");// .replace('@', qsl("@") + QChar(0x200D));
|
||||||
|
versionFeatures = lng_new_version_text(lt_gifs_link, qsl("https://telegram.org/blog/gif-revolution"), lt_bots_link, qsl("https://telegram.org/blog/inline-bots")).trimmed();
|
||||||
} else if (Local::oldMapVersion() < 9015) {
|
} else if (Local::oldMapVersion() < 9015) {
|
||||||
// versionFeatures = lang(lng_new_version_text).trimmed();
|
versionFeatures = lng_new_version_text(lt_gifs_link, qsl("https://telegram.org/blog/gif-revolution"), lt_bots_link, qsl("https://telegram.org/blog/inline-bots")).trimmed();
|
||||||
} else {
|
} else {
|
||||||
versionFeatures = lang(lng_new_version_minor).trimmed();
|
versionFeatures = lang(lng_new_version_minor).trimmed();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
|
||||||
static const int32 AppVersion = 9015;
|
static const int32 AppVersion = 9015;
|
||||||
static const wchar_t *AppVersionStr = L"0.9.15";
|
static const wchar_t *AppVersionStr = L"0.9.15";
|
||||||
static const bool DevVersion = false;
|
static const bool DevVersion = false;
|
||||||
#define BETA_VERSION (9015005ULL) // just comment this line to build public version
|
#define BETA_VERSION (9015006ULL) // just comment this line to build public version
|
||||||
|
|
||||||
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
|
static const wchar_t *AppNameOld = L"Telegram Win (Unofficial)";
|
||||||
static const wchar_t *AppName = L"Telegram Desktop";
|
static const wchar_t *AppName = L"Telegram Desktop";
|
||||||
|
@ -87,6 +87,7 @@ enum {
|
||||||
AverageGifSize = 320 * 240,
|
AverageGifSize = 320 * 240,
|
||||||
WaitBeforeGifPause = 200, // wait 200ms for gif draw before pausing it
|
WaitBeforeGifPause = 200, // wait 200ms for gif draw before pausing it
|
||||||
InlineBotRequestDelay = 400, // wait 400ms before context bot realtime request
|
InlineBotRequestDelay = 400, // wait 400ms before context bot realtime request
|
||||||
|
RecentInlineBotsLimit = 10,
|
||||||
|
|
||||||
AVBlockSize = 4096, // 4Kb for ffmpeg blocksize
|
AVBlockSize = 4096, // 4Kb for ffmpeg blocksize
|
||||||
|
|
||||||
|
|
|
@ -163,7 +163,7 @@ void DialogsInner::paintRegion(Painter &p, const QRegion ®ion, bool paintingO
|
||||||
PeerData *act = App::main()->activePeer();
|
PeerData *act = App::main()->activePeer();
|
||||||
MsgId actId = App::main()->activeMsgId();
|
MsgId actId = App::main()->activeMsgId();
|
||||||
for (; from < to; ++from) {
|
for (; from < to; ++from) {
|
||||||
bool active = ((_filterResults[from]->history->peer == act) || (_filterResults[from]->history->peer->migrateTo() && _filterResults[from]->history->peer->migrateTo() == act)) && !actId;
|
bool active = ((_filterResults[from]->history->peer == act) || (_filterResults[from]->history->peer->migrateTo() && _filterResults[from]->history->peer->migrateTo() == act)) && !actId;
|
||||||
bool selected = (from == _filteredSel) || (_filterResults[from]->history->peer == _menuPeer);
|
bool selected = (from == _filteredSel) || (_filterResults[from]->history->peer == _menuPeer);
|
||||||
_filterResults[from]->paint(p, w, active, selected, paintingOther);
|
_filterResults[from]->paint(p, w, active, selected, paintingOther);
|
||||||
p.translate(0, st::dlgHeight);
|
p.translate(0, st::dlgHeight);
|
||||||
|
@ -872,7 +872,7 @@ void DialogsInner::onHashtagFilterUpdate(QStringRef newFilter) {
|
||||||
}
|
}
|
||||||
_hashtagFilter = newFilter.toString();
|
_hashtagFilter = newFilter.toString();
|
||||||
if (cRecentSearchHashtags().isEmpty() && cRecentWriteHashtags().isEmpty()) {
|
if (cRecentSearchHashtags().isEmpty() && cRecentWriteHashtags().isEmpty()) {
|
||||||
Local::readRecentHashtags();
|
Local::readRecentHashtagsAndBots();
|
||||||
}
|
}
|
||||||
const RecentHashtagPack &recent(cRecentSearchHashtags());
|
const RecentHashtagPack &recent(cRecentSearchHashtags());
|
||||||
_hashtagResults.clear();
|
_hashtagResults.clear();
|
||||||
|
@ -1385,7 +1385,7 @@ void DialogsInner::loadPeerPhotos(int32 yFrom) {
|
||||||
if (from < _filterResults.size()) {
|
if (from < _filterResults.size()) {
|
||||||
int32 to = (yTo / int32(st::dlgHeight)) + 1, w = width();
|
int32 to = (yTo / int32(st::dlgHeight)) + 1, w = width();
|
||||||
if (to > _filterResults.size()) to = _filterResults.size();
|
if (to > _filterResults.size()) to = _filterResults.size();
|
||||||
|
|
||||||
for (; from < to; ++from) {
|
for (; from < to; ++from) {
|
||||||
_filterResults[from]->history->peer->photo->load();
|
_filterResults[from]->history->peer->photo->load();
|
||||||
}
|
}
|
||||||
|
@ -1434,7 +1434,7 @@ bool DialogsInner::choosePeer() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cSetRecentSearchHashtags(recent);
|
cSetRecentSearchHashtags(recent);
|
||||||
Local::writeRecentHashtags();
|
Local::writeRecentHashtagsAndBots();
|
||||||
emit refreshHashtags();
|
emit refreshHashtags();
|
||||||
|
|
||||||
selByMouse = true;
|
selByMouse = true;
|
||||||
|
@ -1487,7 +1487,7 @@ void DialogsInner::saveRecentHashtags(const QString &text) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found && cRecentWriteHashtags().isEmpty() && cRecentSearchHashtags().isEmpty()) {
|
if (!found && cRecentWriteHashtags().isEmpty() && cRecentSearchHashtags().isEmpty()) {
|
||||||
Local::readRecentHashtags();
|
Local::readRecentHashtagsAndBots();
|
||||||
recent = cRecentSearchHashtags();
|
recent = cRecentSearchHashtags();
|
||||||
}
|
}
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -1495,7 +1495,7 @@ void DialogsInner::saveRecentHashtags(const QString &text) {
|
||||||
}
|
}
|
||||||
if (found) {
|
if (found) {
|
||||||
cSetRecentSearchHashtags(recent);
|
cSetRecentSearchHashtags(recent);
|
||||||
Local::writeRecentHashtags();
|
Local::writeRecentHashtagsAndBots();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3766,7 +3766,7 @@ void MentionsInner::paintEvent(QPaintEvent *e) {
|
||||||
if (selected) {
|
if (selected) {
|
||||||
p.fillRect(0, i * st::mentionHeight, width(), st::mentionHeight, st::mentionBgOver->b);
|
p.fillRect(0, i * st::mentionHeight, width(), st::mentionHeight, st::mentionBgOver->b);
|
||||||
int skip = (st::mentionHeight - st::notifyClose.icon.pxHeight()) / 2;
|
int skip = (st::mentionHeight - st::notifyClose.icon.pxHeight()) / 2;
|
||||||
if (!_hrows->isEmpty()) p.drawPixmap(QPoint(width() - st::notifyClose.icon.pxWidth() - skip, i * st::mentionHeight + skip), App::sprite(), st::notifyClose.icon);
|
if (!_hrows->isEmpty() || (!_mrows->isEmpty() && i < _recentInlineBotsInRows)) p.drawPixmap(QPoint(width() - st::notifyClose.icon.pxWidth() - skip, i * st::mentionHeight + skip), App::sprite(), st::notifyClose.icon);
|
||||||
}
|
}
|
||||||
p.setPen(st::black->p);
|
p.setPen(st::black->p);
|
||||||
if (!_mrows->isEmpty()) {
|
if (!_mrows->isEmpty()) {
|
||||||
|
@ -3902,6 +3902,10 @@ bool MentionsInner::select() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MentionsInner::setRecentInlineBotsInRows(int32 bots) {
|
||||||
|
_recentInlineBotsInRows = bots;
|
||||||
|
}
|
||||||
|
|
||||||
QString MentionsInner::getSelected() const {
|
QString MentionsInner::getSelected() const {
|
||||||
int32 maxSel = (_mrows->isEmpty() ? (_hrows->isEmpty() ? _brows->size() : _hrows->size()) : _mrows->size());
|
int32 maxSel = (_mrows->isEmpty() ? (_hrows->isEmpty() ? _brows->size() : _hrows->size()) : _mrows->size());
|
||||||
if (_sel >= 0 && _sel < maxSel) {
|
if (_sel >= 0 && _sel < maxSel) {
|
||||||
|
@ -3930,20 +3934,32 @@ void MentionsInner::mousePressEvent(QMouseEvent *e) {
|
||||||
_mouseSel = true;
|
_mouseSel = true;
|
||||||
onUpdateSelected(true);
|
onUpdateSelected(true);
|
||||||
if (e->button() == Qt::LeftButton) {
|
if (e->button() == Qt::LeftButton) {
|
||||||
if (_overDelete && _sel >= 0 && _sel < _hrows->size()) {
|
if (_overDelete && _sel >= 0 && _sel < (_mrows->isEmpty() ? _hrows->size() : _recentInlineBotsInRows)) {
|
||||||
_mousePos = mapToGlobal(e->pos());
|
_mousePos = mapToGlobal(e->pos());
|
||||||
|
bool removed = false;
|
||||||
QString toRemove = _hrows->at(_sel);
|
if (_mrows->isEmpty()) {
|
||||||
RecentHashtagPack recent(cRecentWriteHashtags());
|
QString toRemove = _hrows->at(_sel);
|
||||||
for (RecentHashtagPack::iterator i = recent.begin(); i != recent.cend();) {
|
RecentHashtagPack &recent(cRefRecentWriteHashtags());
|
||||||
if (i->first == toRemove) {
|
for (RecentHashtagPack::iterator i = recent.begin(); i != recent.cend();) {
|
||||||
i = recent.erase(i);
|
if (i->first == toRemove) {
|
||||||
} else {
|
i = recent.erase(i);
|
||||||
++i;
|
removed = true;
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
UserData *toRemove = _mrows->at(_sel);
|
||||||
|
RecentInlineBots &recent(cRefRecentInlineBots());
|
||||||
|
int32 index = recent.indexOf(toRemove);
|
||||||
|
if (index >= 0) {
|
||||||
|
recent.remove(index);
|
||||||
|
removed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cSetRecentWriteHashtags(recent);
|
if (removed) {
|
||||||
Local::writeRecentHashtags();
|
Local::writeRecentHashtagsAndBots();
|
||||||
|
}
|
||||||
_parent->updateFiltered();
|
_parent->updateFiltered();
|
||||||
|
|
||||||
_mouseSel = true;
|
_mouseSel = true;
|
||||||
|
@ -3980,8 +3996,8 @@ void MentionsInner::onUpdateSelected(bool force) {
|
||||||
if ((!force && !rect().contains(mouse)) || !_mouseSel) return;
|
if ((!force && !rect().contains(mouse)) || !_mouseSel) return;
|
||||||
|
|
||||||
int w = width(), mouseY = mouse.y();
|
int w = width(), mouseY = mouse.y();
|
||||||
_overDelete = _mrows->isEmpty() && (mouse.x() >= w - st::mentionHeight);
|
|
||||||
int32 sel = mouseY / int32(st::mentionHeight), maxSel = _mrows->isEmpty() ? (_hrows->isEmpty() ? _brows->size() : _hrows->size()) : _mrows->size();
|
int32 sel = mouseY / int32(st::mentionHeight), maxSel = _mrows->isEmpty() ? (_hrows->isEmpty() ? _brows->size() : _hrows->size()) : _mrows->size();
|
||||||
|
_overDelete = (!_hrows->isEmpty() || (!_mrows->isEmpty() && sel < _recentInlineBotsInRows)) ? (mouse.x() >= w - st::mentionHeight) : false;
|
||||||
if (sel < 0 || sel >= maxSel) {
|
if (sel < 0 || sel >= maxSel) {
|
||||||
sel = -1;
|
sel = -1;
|
||||||
}
|
}
|
||||||
|
@ -4043,15 +4059,23 @@ void MentionsDropdown::paintEvent(QPaintEvent *e) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MentionsDropdown::showFiltered(PeerData *peer, QString start) {
|
void MentionsDropdown::showFiltered(PeerData *peer, QString query, bool start) {
|
||||||
|
if (query.isEmpty() || (peer->isUser() && query.at(0) == '@' && (!start || cRecentInlineBots().isEmpty()))) {
|
||||||
|
if (!isHidden()) {
|
||||||
|
hideStart();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
_chat = peer->asChat();
|
_chat = peer->asChat();
|
||||||
_user = peer->asUser();
|
_user = peer->asUser();
|
||||||
_channel = peer->asChannel();
|
_channel = peer->asChannel();
|
||||||
start = start.toLower();
|
query = query.toLower();
|
||||||
bool toDown = (_filter != start);
|
bool toDown = (_filter != query);
|
||||||
if (toDown) {
|
if (toDown) {
|
||||||
_filter = start;
|
_filter = query;
|
||||||
}
|
}
|
||||||
|
_addInlineBots = start;
|
||||||
|
|
||||||
updateFiltered(toDown);
|
updateFiltered(toDown);
|
||||||
}
|
}
|
||||||
|
@ -4063,13 +4087,34 @@ bool MentionsDropdown::clearFilteredBotCommands() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MentionsDropdown::updateFiltered(bool toDown) {
|
void MentionsDropdown::updateFiltered(bool toDown) {
|
||||||
int32 now = unixtime();
|
int32 now = unixtime(), recentInlineBots = 0;
|
||||||
MentionRows rows;
|
MentionRows mrows;
|
||||||
HashtagRows hrows;
|
HashtagRows hrows;
|
||||||
BotCommandRows brows;
|
BotCommandRows brows;
|
||||||
|
if (_filter.at(0) == '@') {
|
||||||
|
if (_chat) {
|
||||||
|
mrows.reserve((_addInlineBots ? cRecentInlineBots().size() : 0) + (_chat->participants.isEmpty() ? _chat->lastAuthors.size() : _chat->participants.size()));
|
||||||
|
} else if (_channel && _channel->isMegagroup()) {
|
||||||
|
if (_channel->mgInfo->lastParticipants.isEmpty() || _channel->lastParticipantsCountOutdated()) {
|
||||||
|
} else {
|
||||||
|
mrows.reserve((_addInlineBots ? cRecentInlineBots().size() : 0) + _channel->mgInfo->lastParticipants.size());
|
||||||
|
}
|
||||||
|
} else if (_addInlineBots) {
|
||||||
|
mrows.reserve(cRecentInlineBots().size());
|
||||||
|
}
|
||||||
|
if (_addInlineBots) {
|
||||||
|
for (RecentInlineBots::const_iterator i = cRecentInlineBots().cbegin(), e = cRecentInlineBots().cend(); i != e; ++i) {
|
||||||
|
UserData *user = *i;
|
||||||
|
if (user->username.isEmpty()) continue;
|
||||||
|
if (_filter.size() > 1 && (!user->username.startsWith(_filter.midRef(1), Qt::CaseInsensitive) || user->username.size() + 1 == _filter.size())) continue;
|
||||||
|
mrows.push_back(user);
|
||||||
|
++recentInlineBots;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (_filter.at(0) == '@' && _chat) {
|
if (_filter.at(0) == '@' && _chat) {
|
||||||
QMultiMap<int32, UserData*> ordered;
|
QMultiMap<int32, UserData*> ordered;
|
||||||
rows.reserve(_chat->participants.isEmpty() ? _chat->lastAuthors.size() : _chat->participants.size());
|
mrows.reserve(mrows.size() + (_chat->participants.isEmpty() ? _chat->lastAuthors.size() : _chat->participants.size()));
|
||||||
if (_chat->noParticipantInfo()) {
|
if (_chat->noParticipantInfo()) {
|
||||||
if (App::api()) App::api()->requestFullPeer(_chat);
|
if (App::api()) App::api()->requestFullPeer(_chat);
|
||||||
} else if (!_chat->participants.isEmpty()) {
|
} else if (!_chat->participants.isEmpty()) {
|
||||||
|
@ -4084,7 +4129,7 @@ void MentionsDropdown::updateFiltered(bool toDown) {
|
||||||
UserData *user = *i;
|
UserData *user = *i;
|
||||||
if (user->username.isEmpty()) continue;
|
if (user->username.isEmpty()) continue;
|
||||||
if (_filter.size() > 1 && (!user->username.startsWith(_filter.midRef(1), Qt::CaseInsensitive) || user->username.size() + 1 == _filter.size())) continue;
|
if (_filter.size() > 1 && (!user->username.startsWith(_filter.midRef(1), Qt::CaseInsensitive) || user->username.size() + 1 == _filter.size())) continue;
|
||||||
rows.push_back(user);
|
mrows.push_back(user);
|
||||||
if (!ordered.isEmpty()) {
|
if (!ordered.isEmpty()) {
|
||||||
ordered.remove(App::onlineForSort(user, now), user);
|
ordered.remove(App::onlineForSort(user, now), user);
|
||||||
}
|
}
|
||||||
|
@ -4092,7 +4137,7 @@ void MentionsDropdown::updateFiltered(bool toDown) {
|
||||||
if (!ordered.isEmpty()) {
|
if (!ordered.isEmpty()) {
|
||||||
for (QMultiMap<int32, UserData*>::const_iterator i = ordered.cend(), b = ordered.cbegin(); i != b;) {
|
for (QMultiMap<int32, UserData*>::const_iterator i = ordered.cend(), b = ordered.cbegin(); i != b;) {
|
||||||
--i;
|
--i;
|
||||||
rows.push_back(i.value());
|
mrows.push_back(i.value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (_filter.at(0) == '@' && _channel && _channel->isMegagroup()) {
|
} else if (_filter.at(0) == '@' && _channel && _channel->isMegagroup()) {
|
||||||
|
@ -4100,12 +4145,12 @@ void MentionsDropdown::updateFiltered(bool toDown) {
|
||||||
if (_channel->mgInfo->lastParticipants.isEmpty() || _channel->lastParticipantsCountOutdated()) {
|
if (_channel->mgInfo->lastParticipants.isEmpty() || _channel->lastParticipantsCountOutdated()) {
|
||||||
if (App::api()) App::api()->requestLastParticipants(_channel);
|
if (App::api()) App::api()->requestLastParticipants(_channel);
|
||||||
} else {
|
} else {
|
||||||
rows.reserve(_channel->mgInfo->lastParticipants.size());
|
mrows.reserve(mrows.size() + _channel->mgInfo->lastParticipants.size());
|
||||||
for (MegagroupInfo::LastParticipants::const_iterator i = _channel->mgInfo->lastParticipants.cbegin(), e = _channel->mgInfo->lastParticipants.cend(); i != e; ++i) {
|
for (MegagroupInfo::LastParticipants::const_iterator i = _channel->mgInfo->lastParticipants.cbegin(), e = _channel->mgInfo->lastParticipants.cend(); i != e; ++i) {
|
||||||
UserData *user = *i;
|
UserData *user = *i;
|
||||||
if (user->username.isEmpty()) continue;
|
if (user->username.isEmpty()) continue;
|
||||||
if (_filter.size() > 1 && (!user->username.startsWith(_filter.midRef(1), Qt::CaseInsensitive) || user->username.size() + 1 == _filter.size())) continue;
|
if (_filter.size() > 1 && (!user->username.startsWith(_filter.midRef(1), Qt::CaseInsensitive) || user->username.size() + 1 == _filter.size())) continue;
|
||||||
rows.push_back(user);
|
mrows.push_back(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (_filter.at(0) == '#') {
|
} else if (_filter.at(0) == '#') {
|
||||||
|
@ -4184,7 +4229,8 @@ void MentionsDropdown::updateFiltered(bool toDown) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rowsUpdated(rows, hrows, brows, toDown);
|
rowsUpdated(mrows, hrows, brows, toDown);
|
||||||
|
_inner.setRecentInlineBotsInRows(recentInlineBots);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MentionsDropdown::rowsUpdated(const MentionRows &mrows, const HashtagRows &hrows, const BotCommandRows &brows, bool toDown) {
|
void MentionsDropdown::rowsUpdated(const MentionRows &mrows, const HashtagRows &hrows, const BotCommandRows &brows, bool toDown) {
|
||||||
|
|
|
@ -736,6 +736,8 @@ public:
|
||||||
bool moveSel(int direction);
|
bool moveSel(int direction);
|
||||||
bool select();
|
bool select();
|
||||||
|
|
||||||
|
void setRecentInlineBotsInRows(int32 bots);
|
||||||
|
|
||||||
QString getSelected() const;
|
QString getSelected() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -756,6 +758,7 @@ private:
|
||||||
MentionRows *_mrows;
|
MentionRows *_mrows;
|
||||||
HashtagRows *_hrows;
|
HashtagRows *_hrows;
|
||||||
BotCommandRows *_brows;
|
BotCommandRows *_brows;
|
||||||
|
int32 _recentInlineBotsInRows;
|
||||||
int32 _sel;
|
int32 _sel;
|
||||||
bool _mouseSel;
|
bool _mouseSel;
|
||||||
QPoint _mousePos;
|
QPoint _mousePos;
|
||||||
|
@ -775,7 +778,7 @@ public:
|
||||||
void fastHide();
|
void fastHide();
|
||||||
|
|
||||||
bool clearFilteredBotCommands();
|
bool clearFilteredBotCommands();
|
||||||
void showFiltered(PeerData *peer, QString start);
|
void showFiltered(PeerData *peer, QString query, bool start);
|
||||||
void updateFiltered(bool toDown = false);
|
void updateFiltered(bool toDown = false);
|
||||||
void setBoundings(QRect boundings);
|
void setBoundings(QRect boundings);
|
||||||
|
|
||||||
|
@ -820,7 +823,7 @@ private:
|
||||||
HashtagRows _hrows;
|
HashtagRows _hrows;
|
||||||
BotCommandRows _brows;
|
BotCommandRows _brows;
|
||||||
|
|
||||||
void rowsUpdated(const MentionRows &rows, const HashtagRows &hrows, const BotCommandRows &brows, bool toDown);
|
void rowsUpdated(const MentionRows &mrows, const HashtagRows &hrows, const BotCommandRows &brows, bool toDown);
|
||||||
|
|
||||||
ScrollArea _scroll;
|
ScrollArea _scroll;
|
||||||
MentionsInner _inner;
|
MentionsInner _inner;
|
||||||
|
@ -830,6 +833,7 @@ private:
|
||||||
ChannelData *_channel;
|
ChannelData *_channel;
|
||||||
QString _filter;
|
QString _filter;
|
||||||
QRect _boundings;
|
QRect _boundings;
|
||||||
|
bool _addInlineBots;
|
||||||
|
|
||||||
int32 _width, _height;
|
int32 _width, _height;
|
||||||
bool _hiding;
|
bool _hiding;
|
||||||
|
|
|
@ -129,7 +129,7 @@ namespace Ui {
|
||||||
|
|
||||||
void showPeerHistoryAsync(const PeerId &peer, MsgId msgId) {
|
void showPeerHistoryAsync(const PeerId &peer, MsgId msgId) {
|
||||||
if (MainWidget *m = App::main()) {
|
if (MainWidget *m = App::main()) {
|
||||||
QMetaObject::invokeMethod(m, SLOT(ui_showPeerHistoryAsync(quint64,qint32)), Qt::QueuedConnection, Q_ARG(quint64, peer), Q_ARG(qint32, msgId));
|
QMetaObject::invokeMethod(m, "ui_showPeerHistoryAsync", Qt::QueuedConnection, Q_ARG(quint64, peer), Q_ARG(qint32, msgId));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -270,7 +270,9 @@ EmojiPtr FlatTextarea::getSingleEmoji() const {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlatTextarea::getMentionHashtagBotCommandStart(QString &start, UserData *&inlineBot, QString &inlineBotUsername) const {
|
QString FlatTextarea::getMentionHashtagBotCommandPart(bool &start, UserData *&inlineBot, QString &inlineBotUsername) const {
|
||||||
|
start = false;
|
||||||
|
|
||||||
// check inline bot query
|
// check inline bot query
|
||||||
const QString &text(getLastText());
|
const QString &text(getLastText());
|
||||||
int32 inlineUsernameStart = 1, inlineUsernameLength = 0, size = text.size();
|
int32 inlineUsernameStart = 1, inlineUsernameLength = 0, size = text.size();
|
||||||
|
@ -301,13 +303,12 @@ void FlatTextarea::getMentionHashtagBotCommandStart(QString &start, UserData *&i
|
||||||
inlineBot = InlineBotLookingUpData;
|
inlineBot = InlineBotLookingUpData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inlineBot == InlineBotLookingUpData) return;
|
if (inlineBot == InlineBotLookingUpData) return QString();
|
||||||
|
|
||||||
if (inlineBot && (!inlineBot->botInfo || inlineBot->botInfo->inlinePlaceholder.isEmpty())) {
|
if (inlineBot && (!inlineBot->botInfo || inlineBot->botInfo->inlinePlaceholder.isEmpty())) {
|
||||||
inlineBot = 0;
|
inlineBot = 0;
|
||||||
} else {
|
} else {
|
||||||
start = text.mid(inlineUsernameStart + inlineUsernameLength + 1);
|
return text.mid(inlineUsernameStart + inlineUsernameLength + 1);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
inlineUsernameLength = 0;
|
inlineUsernameLength = 0;
|
||||||
|
@ -319,7 +320,7 @@ void FlatTextarea::getMentionHashtagBotCommandStart(QString &start, UserData *&i
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 pos = textCursor().position();
|
int32 pos = textCursor().position();
|
||||||
if (textCursor().anchor() != pos) return;
|
if (textCursor().anchor() != pos) return QString();
|
||||||
|
|
||||||
// check mention / hashtag / bot command
|
// check mention / hashtag / bot command
|
||||||
QTextDocument *doc(document());
|
QTextDocument *doc(document());
|
||||||
|
@ -339,29 +340,33 @@ void FlatTextarea::getMentionHashtagBotCommandStart(QString &start, UserData *&i
|
||||||
for (int i = pos - p; i > 0; --i) {
|
for (int i = pos - p; i > 0; --i) {
|
||||||
if (t.at(i - 1) == '@') {
|
if (t.at(i - 1) == '@') {
|
||||||
if ((pos - p - i < 1 || t.at(i).isLetter()) && (i < 2 || !(t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_'))) {
|
if ((pos - p - i < 1 || t.at(i).isLetter()) && (i < 2 || !(t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_'))) {
|
||||||
start = t.mid(i - 1, pos - p - i + 1);
|
start = (i == 1) && (p == 0);
|
||||||
|
return t.mid(i - 1, pos - p - i + 1);
|
||||||
} else if ((pos - p - i < 1 || t.at(i).isLetter()) && i > 2 && (t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_') && !mentionInCommand) {
|
} else if ((pos - p - i < 1 || t.at(i).isLetter()) && i > 2 && (t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_') && !mentionInCommand) {
|
||||||
mentionInCommand = true;
|
mentionInCommand = true;
|
||||||
--i;
|
--i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return;
|
return QString();
|
||||||
} else if (t.at(i - 1) == '#') {
|
} else if (t.at(i - 1) == '#') {
|
||||||
if (i < 2 || !(t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_')) {
|
if (i < 2 || !(t.at(i - 2).isLetterOrNumber() || t.at(i - 2) == '_')) {
|
||||||
start = t.mid(i - 1, pos - p - i + 1);
|
start = (i == 1) && (p == 0);
|
||||||
|
return t.mid(i - 1, pos - p - i + 1);
|
||||||
}
|
}
|
||||||
return;
|
return QString();
|
||||||
} else if (t.at(i - 1) == '/') {
|
} else if (t.at(i - 1) == '/') {
|
||||||
if (i < 2) {
|
if (i < 2) {
|
||||||
start = t.mid(i - 1, pos - p - i + 1);
|
start = (i == 1) && (p == 0);
|
||||||
|
return t.mid(i - 1, pos - p - i + 1);
|
||||||
}
|
}
|
||||||
return;
|
return QString();
|
||||||
}
|
}
|
||||||
if (pos - p - i > 127 || (!mentionInCommand && (pos - p - i > 63))) break;
|
if (pos - p - i > 127 || (!mentionInCommand && (pos - p - i > 63))) break;
|
||||||
if (!t.at(i - 1).isLetterOrNumber() && t.at(i - 1) != '_') break;
|
if (!t.at(i - 1).isLetterOrNumber() && t.at(i - 1) != '_') break;
|
||||||
}
|
}
|
||||||
return;
|
break;
|
||||||
}
|
}
|
||||||
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FlatTextarea::onMentionHashtagOrBotCommandInsert(QString str) {
|
void FlatTextarea::onMentionHashtagOrBotCommandInsert(QString str) {
|
||||||
|
|
|
@ -64,7 +64,7 @@ public:
|
||||||
QSize minimumSizeHint() const;
|
QSize minimumSizeHint() const;
|
||||||
|
|
||||||
EmojiPtr getSingleEmoji() const;
|
EmojiPtr getSingleEmoji() const;
|
||||||
void getMentionHashtagBotCommandStart(QString &start, UserData *&contextBot, QString &contextBotUsername) const;
|
QString getMentionHashtagBotCommandPart(bool &start, UserData *&contextBot, QString &contextBotUsername) const;
|
||||||
void removeSingleEmoji();
|
void removeSingleEmoji();
|
||||||
bool hasText() const;
|
bool hasText() const;
|
||||||
|
|
||||||
|
|
|
@ -5338,8 +5338,9 @@ void HistoryWidget::onCheckMentionDropdown() {
|
||||||
if (!_history || _a_show.animating()) return;
|
if (!_history || _a_show.animating()) return;
|
||||||
|
|
||||||
UserData *bot = _inlineBot;
|
UserData *bot = _inlineBot;
|
||||||
QString start, inlineBotUsername(_inlineBotUsername);
|
bool start = false;
|
||||||
_field.getMentionHashtagBotCommandStart(start, _inlineBot, _inlineBotUsername);
|
QString inlineBotUsername(_inlineBotUsername);
|
||||||
|
QString query = _field.getMentionHashtagBotCommandPart(start, _inlineBot, _inlineBotUsername);
|
||||||
if (inlineBotUsername != _inlineBotUsername) {
|
if (inlineBotUsername != _inlineBotUsername) {
|
||||||
if (_inlineBotResolveRequestId) {
|
if (_inlineBotResolveRequestId) {
|
||||||
Notify::inlineBotRequesting(false);
|
Notify::inlineBotRequesting(false);
|
||||||
|
@ -5359,10 +5360,10 @@ void HistoryWidget::onCheckMentionDropdown() {
|
||||||
if (_inlineBot != bot) {
|
if (_inlineBot != bot) {
|
||||||
updateFieldPlaceholder();
|
updateFieldPlaceholder();
|
||||||
}
|
}
|
||||||
if (_inlineBot->username == (cTestMode() ? qstr("contextbot") : qstr("gif")) && start.isEmpty()) {
|
if (_inlineBot->username == (cTestMode() ? qstr("contextbot") : qstr("gif")) && query.isEmpty()) {
|
||||||
_emojiPan.clearInlineBot();
|
_emojiPan.clearInlineBot();
|
||||||
} else {
|
} else {
|
||||||
_emojiPan.queryInlineBot(_inlineBot, start);
|
_emojiPan.queryInlineBot(_inlineBot, query);
|
||||||
}
|
}
|
||||||
if (!_attachMention.isHidden()) {
|
if (!_attachMention.isHidden()) {
|
||||||
_attachMention.hideStart();
|
_attachMention.hideStart();
|
||||||
|
@ -5373,16 +5374,12 @@ void HistoryWidget::onCheckMentionDropdown() {
|
||||||
_field.finishPlaceholder();
|
_field.finishPlaceholder();
|
||||||
}
|
}
|
||||||
_emojiPan.clearInlineBot();
|
_emojiPan.clearInlineBot();
|
||||||
if (!start.isEmpty()) {
|
if (!query.isEmpty()) {
|
||||||
if (start.at(0) == '#' && cRecentWriteHashtags().isEmpty() && cRecentSearchHashtags().isEmpty()) Local::readRecentHashtags();
|
if (query.at(0) == '#' && cRecentWriteHashtags().isEmpty() && cRecentSearchHashtags().isEmpty()) Local::readRecentHashtagsAndBots();
|
||||||
if (start.at(0) == '@' && _peer->isUser()) return;
|
if (query.at(0) == '@' && cRecentInlineBots().isEmpty()) Local::readRecentHashtagsAndBots();
|
||||||
if (start.at(0) == '/' && _peer->isUser() && !_peer->asUser()->botInfo) return;
|
if (query.at(0) == '/' && _peer->isUser() && !_peer->asUser()->botInfo) return;
|
||||||
_attachMention.showFiltered(_peer, start);
|
|
||||||
} else {
|
|
||||||
if (!_attachMention.isHidden()) {
|
|
||||||
_attachMention.hideStart();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
_attachMention.showFiltered(_peer, query, start);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6428,6 +6425,18 @@ void HistoryWidget::onInlineResultSend(InlineResult *result, UserData *bot) {
|
||||||
_saveDraftStart = getms();
|
_saveDraftStart = getms();
|
||||||
onDraftSave();
|
onDraftSave();
|
||||||
|
|
||||||
|
RecentInlineBots &bots(cRefRecentInlineBots());
|
||||||
|
int32 index = bots.indexOf(bot);
|
||||||
|
if (index) {
|
||||||
|
if (index > 0) {
|
||||||
|
bots.removeAt(index);
|
||||||
|
} else if (bots.size() >= RecentInlineBotsLimit) {
|
||||||
|
bots.resize(RecentInlineBotsLimit - 1);
|
||||||
|
}
|
||||||
|
bots.push_front(bot);
|
||||||
|
Local::writeRecentHashtagsAndBots();
|
||||||
|
}
|
||||||
|
|
||||||
onCheckMentionDropdown();
|
onCheckMentionDropdown();
|
||||||
if (!_attachType.isHidden()) _attachType.hideStart();
|
if (!_attachType.isHidden()) _attachType.hideStart();
|
||||||
|
|
||||||
|
|
|
@ -538,22 +538,22 @@ namespace {
|
||||||
FileKey _dataNameKey = 0;
|
FileKey _dataNameKey = 0;
|
||||||
|
|
||||||
enum { // Local Storage Keys
|
enum { // Local Storage Keys
|
||||||
lskUserMap = 0x00,
|
lskUserMap = 0x00,
|
||||||
lskDraft = 0x01, // data: PeerId peer
|
lskDraft = 0x01, // data: PeerId peer
|
||||||
lskDraftPosition = 0x02, // data: PeerId peer
|
lskDraftPosition = 0x02, // data: PeerId peer
|
||||||
lskImages = 0x03, // data: StorageKey location
|
lskImages = 0x03, // data: StorageKey location
|
||||||
lskLocations = 0x04, // no data
|
lskLocations = 0x04, // no data
|
||||||
lskStickerImages = 0x05, // data: StorageKey location
|
lskStickerImages = 0x05, // data: StorageKey location
|
||||||
lskAudios = 0x06, // data: StorageKey location
|
lskAudios = 0x06, // data: StorageKey location
|
||||||
lskRecentStickersOld = 0x07, // no data
|
lskRecentStickersOld = 0x07, // no data
|
||||||
lskBackground = 0x08, // no data
|
lskBackground = 0x08, // no data
|
||||||
lskUserSettings = 0x09, // no data
|
lskUserSettings = 0x09, // no data
|
||||||
lskRecentHashtags = 0x0a, // no data
|
lskRecentHashtagsAndBots = 0x0a, // no data
|
||||||
lskStickers = 0x0b, // no data
|
lskStickers = 0x0b, // no data
|
||||||
lskSavedPeers = 0x0c, // no data
|
lskSavedPeers = 0x0c, // no data
|
||||||
lskReportSpamStatuses = 0x0d, // no data
|
lskReportSpamStatuses = 0x0d, // no data
|
||||||
lskSavedGifsOld = 0x0e,
|
lskSavedGifsOld = 0x0e, // no data
|
||||||
lskSavedGifs = 0x0f,
|
lskSavedGifs = 0x0f, // no data
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef QMap<PeerId, FileKey> DraftsMap;
|
typedef QMap<PeerId, FileKey> DraftsMap;
|
||||||
|
@ -581,8 +581,8 @@ namespace {
|
||||||
bool _backgroundWasRead = false;
|
bool _backgroundWasRead = false;
|
||||||
|
|
||||||
FileKey _userSettingsKey = 0;
|
FileKey _userSettingsKey = 0;
|
||||||
FileKey _recentHashtagsKey = 0;
|
FileKey _recentHashtagsAndBotsKey = 0;
|
||||||
bool _recentHashtagsWereRead = false;
|
bool _recentHashtagsAndBotsWereRead = false;
|
||||||
|
|
||||||
FileKey _savedPeersKey = 0;
|
FileKey _savedPeersKey = 0;
|
||||||
|
|
||||||
|
@ -726,18 +726,20 @@ namespace {
|
||||||
_fileLocationAliases.insert(MediaKey(kfirst, ksecond), MediaKey(vfirst, vsecond));
|
_fileLocationAliases.insert(MediaKey(kfirst, ksecond), MediaKey(vfirst, vsecond));
|
||||||
}
|
}
|
||||||
|
|
||||||
_storageWebFilesSize = 0;
|
if (!locations.stream.atEnd()) {
|
||||||
_webFilesMap.clear();
|
_storageWebFilesSize = 0;
|
||||||
|
_webFilesMap.clear();
|
||||||
|
|
||||||
quint32 webLocationsCount;
|
quint32 webLocationsCount;
|
||||||
locations.stream >> webLocationsCount;
|
locations.stream >> webLocationsCount;
|
||||||
for (quint32 i = 0; i < webLocationsCount; ++i) {
|
for (quint32 i = 0; i < webLocationsCount; ++i) {
|
||||||
QString url;
|
QString url;
|
||||||
quint64 key;
|
quint64 key;
|
||||||
qint32 size;
|
qint32 size;
|
||||||
locations.stream >> url >> key >> size;
|
locations.stream >> url >> key >> size;
|
||||||
_webFilesMap.insert(url, FileDesc(key, size));
|
_webFilesMap.insert(url, FileDesc(key, size));
|
||||||
_storageWebFilesSize += size;
|
_storageWebFilesSize += size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1667,7 +1669,7 @@ namespace {
|
||||||
qint64 storageImagesSize = 0, storageStickersSize = 0, storageAudiosSize = 0;
|
qint64 storageImagesSize = 0, storageStickersSize = 0, storageAudiosSize = 0;
|
||||||
quint64 locationsKey = 0, reportSpamStatusesKey = 0;
|
quint64 locationsKey = 0, reportSpamStatusesKey = 0;
|
||||||
quint64 recentStickersKeyOld = 0, stickersKey = 0, savedGifsKey = 0;
|
quint64 recentStickersKeyOld = 0, stickersKey = 0, savedGifsKey = 0;
|
||||||
quint64 backgroundKey = 0, userSettingsKey = 0, recentHashtagsKey = 0, savedPeersKey = 0;
|
quint64 backgroundKey = 0, userSettingsKey = 0, recentHashtagsAndBotsKey = 0, savedPeersKey = 0;
|
||||||
while (!map.stream.atEnd()) {
|
while (!map.stream.atEnd()) {
|
||||||
quint32 keyType;
|
quint32 keyType;
|
||||||
map.stream >> keyType;
|
map.stream >> keyType;
|
||||||
|
@ -1744,8 +1746,8 @@ namespace {
|
||||||
case lskUserSettings: {
|
case lskUserSettings: {
|
||||||
map.stream >> userSettingsKey;
|
map.stream >> userSettingsKey;
|
||||||
} break;
|
} break;
|
||||||
case lskRecentHashtags: {
|
case lskRecentHashtagsAndBots: {
|
||||||
map.stream >> recentHashtagsKey;
|
map.stream >> recentHashtagsAndBotsKey;
|
||||||
} break;
|
} break;
|
||||||
case lskStickers: {
|
case lskStickers: {
|
||||||
map.stream >> stickersKey;
|
map.stream >> stickersKey;
|
||||||
|
@ -1788,7 +1790,7 @@ namespace {
|
||||||
_savedPeersKey = savedPeersKey;
|
_savedPeersKey = savedPeersKey;
|
||||||
_backgroundKey = backgroundKey;
|
_backgroundKey = backgroundKey;
|
||||||
_userSettingsKey = userSettingsKey;
|
_userSettingsKey = userSettingsKey;
|
||||||
_recentHashtagsKey = recentHashtagsKey;
|
_recentHashtagsAndBotsKey = recentHashtagsAndBotsKey;
|
||||||
_oldMapVersion = mapData.version;
|
_oldMapVersion = mapData.version;
|
||||||
if (_oldMapVersion < AppVersion) {
|
if (_oldMapVersion < AppVersion) {
|
||||||
_mapChanged = true;
|
_mapChanged = true;
|
||||||
|
@ -1861,7 +1863,7 @@ namespace {
|
||||||
if (_savedPeersKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
if (_savedPeersKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||||
if (_backgroundKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
if (_backgroundKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||||
if (_userSettingsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
if (_userSettingsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||||
if (_recentHashtagsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
if (_recentHashtagsAndBotsKey) mapSize += sizeof(quint32) + sizeof(quint64);
|
||||||
EncryptedDescriptor mapData(mapSize);
|
EncryptedDescriptor mapData(mapSize);
|
||||||
if (!_draftsMap.isEmpty()) {
|
if (!_draftsMap.isEmpty()) {
|
||||||
mapData.stream << quint32(lskDraft) << quint32(_draftsMap.size());
|
mapData.stream << quint32(lskDraft) << quint32(_draftsMap.size());
|
||||||
|
@ -1917,8 +1919,8 @@ namespace {
|
||||||
if (_userSettingsKey) {
|
if (_userSettingsKey) {
|
||||||
mapData.stream << quint32(lskUserSettings) << quint64(_userSettingsKey);
|
mapData.stream << quint32(lskUserSettings) << quint64(_userSettingsKey);
|
||||||
}
|
}
|
||||||
if (_recentHashtagsKey) {
|
if (_recentHashtagsAndBotsKey) {
|
||||||
mapData.stream << quint32(lskRecentHashtags) << quint64(_recentHashtagsKey);
|
mapData.stream << quint32(lskRecentHashtagsAndBots) << quint64(_recentHashtagsAndBotsKey);
|
||||||
}
|
}
|
||||||
map.writeEncrypted(mapData);
|
map.writeEncrypted(mapData);
|
||||||
|
|
||||||
|
@ -2187,7 +2189,7 @@ namespace Local {
|
||||||
_storageWebFilesSize = 0;
|
_storageWebFilesSize = 0;
|
||||||
_locationsKey = _reportSpamStatusesKey = 0;
|
_locationsKey = _reportSpamStatusesKey = 0;
|
||||||
_recentStickersKeyOld = _stickersKey = _savedGifsKey = 0;
|
_recentStickersKeyOld = _stickersKey = _savedGifsKey = 0;
|
||||||
_backgroundKey = _userSettingsKey = _recentHashtagsKey = _savedPeersKey = 0;
|
_backgroundKey = _userSettingsKey = _recentHashtagsAndBotsKey = _savedPeersKey = 0;
|
||||||
_oldMapVersion = _oldSettingsVersion = 0;
|
_oldMapVersion = _oldSettingsVersion = 0;
|
||||||
_mapChanged = true;
|
_mapChanged = true;
|
||||||
_writeMap(WriteMapNow);
|
_writeMap(WriteMapNow);
|
||||||
|
@ -3258,89 +3260,6 @@ namespace Local {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeRecentHashtags() {
|
|
||||||
if (!_working()) return;
|
|
||||||
|
|
||||||
const RecentHashtagPack &write(cRecentWriteHashtags()), &search(cRecentSearchHashtags());
|
|
||||||
if (write.isEmpty() && search.isEmpty()) readRecentHashtags();
|
|
||||||
if (write.isEmpty() && search.isEmpty()) {
|
|
||||||
if (_recentHashtagsKey) {
|
|
||||||
clearKey(_recentHashtagsKey);
|
|
||||||
_recentHashtagsKey = 0;
|
|
||||||
_mapChanged = true;
|
|
||||||
}
|
|
||||||
_writeMap();
|
|
||||||
} else {
|
|
||||||
if (!_recentHashtagsKey) {
|
|
||||||
_recentHashtagsKey = genKey();
|
|
||||||
_mapChanged = true;
|
|
||||||
_writeMap(WriteMapFast);
|
|
||||||
}
|
|
||||||
quint32 size = sizeof(quint32) * 2, writeCnt = 0, searchCnt = 0;
|
|
||||||
for (RecentHashtagPack::const_iterator i = write.cbegin(); i != write.cend(); ++i) {
|
|
||||||
if (!i->first.isEmpty()) {
|
|
||||||
size += _stringSize(i->first) + sizeof(quint16);
|
|
||||||
++writeCnt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (RecentHashtagPack::const_iterator i = search.cbegin(); i != search.cend(); ++i) {
|
|
||||||
if (!i->first.isEmpty()) {
|
|
||||||
size += _stringSize(i->first) + sizeof(quint16);
|
|
||||||
++searchCnt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EncryptedDescriptor data(size);
|
|
||||||
data.stream << quint32(writeCnt) << quint32(searchCnt);
|
|
||||||
for (RecentHashtagPack::const_iterator i = write.cbegin(); i != write.cend(); ++i) {
|
|
||||||
if (!i->first.isEmpty()) data.stream << i->first << quint16(i->second);
|
|
||||||
}
|
|
||||||
for (RecentHashtagPack::const_iterator i = search.cbegin(); i != search.cend(); ++i) {
|
|
||||||
if (!i->first.isEmpty()) data.stream << i->first << quint16(i->second);
|
|
||||||
}
|
|
||||||
FileWriteDescriptor file(_recentHashtagsKey);
|
|
||||||
file.writeEncrypted(data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void readRecentHashtags() {
|
|
||||||
if (_recentHashtagsWereRead) return;
|
|
||||||
_recentHashtagsWereRead = true;
|
|
||||||
|
|
||||||
if (!_recentHashtagsKey) return;
|
|
||||||
|
|
||||||
FileReadDescriptor hashtags;
|
|
||||||
if (!readEncryptedFile(hashtags, _recentHashtagsKey)) {
|
|
||||||
clearKey(_recentHashtagsKey);
|
|
||||||
_recentHashtagsKey = 0;
|
|
||||||
_writeMap();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
quint32 writeCount = 0, searchCount = 0;
|
|
||||||
hashtags.stream >> writeCount >> searchCount;
|
|
||||||
|
|
||||||
QString tag;
|
|
||||||
quint16 count;
|
|
||||||
|
|
||||||
RecentHashtagPack write, search;
|
|
||||||
if (writeCount) {
|
|
||||||
write.reserve(writeCount);
|
|
||||||
for (uint32 i = 0; i < writeCount; ++i) {
|
|
||||||
hashtags.stream >> tag >> count;
|
|
||||||
write.push_back(qMakePair(tag.trimmed(), count));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (searchCount) {
|
|
||||||
search.reserve(searchCount);
|
|
||||||
for (uint32 i = 0; i < searchCount; ++i) {
|
|
||||||
hashtags.stream >> tag >> count;
|
|
||||||
search.push_back(qMakePair(tag.trimmed(), count));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cSetRecentWriteHashtags(write);
|
|
||||||
cSetRecentSearchHashtags(search);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 _peerSize(PeerData *peer) {
|
uint32 _peerSize(PeerData *peer) {
|
||||||
uint32 result = sizeof(quint64) + sizeof(quint64) + _storageImageLocationSize();
|
uint32 result = sizeof(quint64) + sizeof(quint64) + _storageImageLocationSize();
|
||||||
if (peer->isUser()) {
|
if (peer->isUser()) {
|
||||||
|
@ -3370,7 +3289,7 @@ namespace Local {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _writePeer(QDataStream &stream, PeerData *peer) {
|
void _writePeer(QDataStream &stream, PeerData *peer, int32 fileVersion = AppVersion) {
|
||||||
stream << quint64(peer->id) << quint64(peer->photoId);
|
stream << quint64(peer->id) << quint64(peer->photoId);
|
||||||
_writeStorageImageLocation(stream, peer->photoLoc);
|
_writeStorageImageLocation(stream, peer->photoLoc);
|
||||||
if (peer->isUser()) {
|
if (peer->isUser()) {
|
||||||
|
@ -3380,6 +3299,9 @@ namespace Local {
|
||||||
if (AppVersion >= 9012) {
|
if (AppVersion >= 9012) {
|
||||||
stream << qint32(user->flags);
|
stream << qint32(user->flags);
|
||||||
}
|
}
|
||||||
|
if (AppVersion >= 9016 || fileVersion >= 9016) {
|
||||||
|
stream << (user->botInfo ? user->botInfo->inlinePlaceholder : QString());
|
||||||
|
}
|
||||||
stream << qint32(user->onlineTill) << qint32(user->contact) << qint32(user->botInfo ? user->botInfo->version : -1);
|
stream << qint32(user->onlineTill) << qint32(user->contact) << qint32(user->botInfo ? user->botInfo->version : -1);
|
||||||
} else if (peer->isChat()) {
|
} else if (peer->isChat()) {
|
||||||
ChatData *chat = peer->asChat();
|
ChatData *chat = peer->asChat();
|
||||||
|
@ -3396,25 +3318,31 @@ namespace Local {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerData *_readPeer(FileReadDescriptor &from) {
|
PeerData *_readPeer(FileReadDescriptor &from, int32 fileVersion = 0) {
|
||||||
PeerData *result = 0;
|
PeerData *result = 0;
|
||||||
quint64 peerId = 0, photoId = 0;
|
quint64 peerId = 0, photoId = 0;
|
||||||
from.stream >> peerId >> photoId;
|
from.stream >> peerId >> photoId;
|
||||||
|
|
||||||
StorageImageLocation photoLoc(_readStorageImageLocation(from));
|
StorageImageLocation photoLoc(_readStorageImageLocation(from));
|
||||||
|
|
||||||
|
result = App::peerLoaded(peerId);
|
||||||
|
if (result && result->loaded) return result;
|
||||||
|
|
||||||
result = App::peer(peerId);
|
result = App::peer(peerId);
|
||||||
result->loaded = true;
|
result->loaded = true;
|
||||||
if (result->isUser()) {
|
if (result->isUser()) {
|
||||||
UserData *user = result->asUser();
|
UserData *user = result->asUser();
|
||||||
|
|
||||||
QString first, last, phone, username;
|
QString first, last, phone, username, inlinePlaceholder;
|
||||||
quint64 access;
|
quint64 access;
|
||||||
qint32 flags = 0, onlineTill, contact, botInfoVersion;
|
qint32 flags = 0, onlineTill, contact, botInfoVersion;
|
||||||
from.stream >> first >> last >> phone >> username >> access;
|
from.stream >> first >> last >> phone >> username >> access;
|
||||||
if (from.version >= 9012) {
|
if (from.version >= 9012) {
|
||||||
from.stream >> flags;
|
from.stream >> flags;
|
||||||
}
|
}
|
||||||
|
if (from.version >= 9016 || fileVersion >= 9016) {
|
||||||
|
from.stream >> inlinePlaceholder;
|
||||||
|
}
|
||||||
from.stream >> onlineTill >> contact >> botInfoVersion;
|
from.stream >> onlineTill >> contact >> botInfoVersion;
|
||||||
|
|
||||||
bool showPhone = !isServiceUser(user->id) && (peerToUser(user->id) != MTP::authedId()) && (contact <= 0);
|
bool showPhone = !isServiceUser(user->id) && (peerToUser(user->id) != MTP::authedId()) && (contact <= 0);
|
||||||
|
@ -3427,6 +3355,9 @@ namespace Local {
|
||||||
user->onlineTill = onlineTill;
|
user->onlineTill = onlineTill;
|
||||||
user->contact = contact;
|
user->contact = contact;
|
||||||
user->setBotInfoVersion(botInfoVersion);
|
user->setBotInfoVersion(botInfoVersion);
|
||||||
|
if (!inlinePlaceholder.isEmpty() && user->botInfo) {
|
||||||
|
user->botInfo->inlinePlaceholder = inlinePlaceholder;
|
||||||
|
}
|
||||||
|
|
||||||
if (peerToUser(user->id) == MTP::authedId()) {
|
if (peerToUser(user->id) == MTP::authedId()) {
|
||||||
user->input = MTP_inputPeerSelf();
|
user->input = MTP_inputPeerSelf();
|
||||||
|
@ -3489,6 +3420,113 @@ namespace Local {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void writeRecentHashtagsAndBots() {
|
||||||
|
if (!_working()) return;
|
||||||
|
|
||||||
|
const RecentHashtagPack &write(cRecentWriteHashtags()), &search(cRecentSearchHashtags());
|
||||||
|
const RecentInlineBots &bots(cRecentInlineBots());
|
||||||
|
if (write.isEmpty() && search.isEmpty() && bots.isEmpty()) readRecentHashtagsAndBots();
|
||||||
|
if (write.isEmpty() && search.isEmpty() && bots.isEmpty()) {
|
||||||
|
if (_recentHashtagsAndBotsKey) {
|
||||||
|
clearKey(_recentHashtagsAndBotsKey);
|
||||||
|
_recentHashtagsAndBotsKey = 0;
|
||||||
|
_mapChanged = true;
|
||||||
|
}
|
||||||
|
_writeMap();
|
||||||
|
} else {
|
||||||
|
if (!_recentHashtagsAndBotsKey) {
|
||||||
|
_recentHashtagsAndBotsKey = genKey();
|
||||||
|
_mapChanged = true;
|
||||||
|
_writeMap(WriteMapFast);
|
||||||
|
}
|
||||||
|
quint32 size = sizeof(quint32) * 3, writeCnt = 0, searchCnt = 0, botsCnt = cRecentInlineBots().size();
|
||||||
|
for (RecentHashtagPack::const_iterator i = write.cbegin(), e = write.cend(); i != e; ++i) {
|
||||||
|
if (!i->first.isEmpty()) {
|
||||||
|
size += _stringSize(i->first) + sizeof(quint16);
|
||||||
|
++writeCnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (RecentHashtagPack::const_iterator i = search.cbegin(), e = search.cend(); i != e; ++i) {
|
||||||
|
if (!i->first.isEmpty()) {
|
||||||
|
size += _stringSize(i->first) + sizeof(quint16);
|
||||||
|
++searchCnt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (RecentInlineBots::const_iterator i = bots.cbegin(), e = bots.cend(); i != e; ++i) {
|
||||||
|
size += _peerSize(*i);
|
||||||
|
}
|
||||||
|
|
||||||
|
EncryptedDescriptor data(size);
|
||||||
|
data.stream << quint32(writeCnt) << quint32(searchCnt);
|
||||||
|
for (RecentHashtagPack::const_iterator i = write.cbegin(), e = write.cend(); i != e; ++i) {
|
||||||
|
if (!i->first.isEmpty()) data.stream << i->first << quint16(i->second);
|
||||||
|
}
|
||||||
|
for (RecentHashtagPack::const_iterator i = search.cbegin(), e = search.cend(); i != e; ++i) {
|
||||||
|
if (!i->first.isEmpty()) data.stream << i->first << quint16(i->second);
|
||||||
|
}
|
||||||
|
data.stream << quint32(botsCnt);
|
||||||
|
for (RecentInlineBots::const_iterator i = bots.cbegin(), e = bots.cend(); i != e; ++i) {
|
||||||
|
_writePeer(data.stream, *i, 9016);
|
||||||
|
}
|
||||||
|
FileWriteDescriptor file(_recentHashtagsAndBotsKey);
|
||||||
|
file.writeEncrypted(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void readRecentHashtagsAndBots() {
|
||||||
|
if (_recentHashtagsAndBotsWereRead) return;
|
||||||
|
_recentHashtagsAndBotsWereRead = true;
|
||||||
|
|
||||||
|
if (!_recentHashtagsAndBotsKey) return;
|
||||||
|
|
||||||
|
FileReadDescriptor hashtags;
|
||||||
|
if (!readEncryptedFile(hashtags, _recentHashtagsAndBotsKey)) {
|
||||||
|
clearKey(_recentHashtagsAndBotsKey);
|
||||||
|
_recentHashtagsAndBotsKey = 0;
|
||||||
|
_writeMap();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint32 writeCount = 0, searchCount = 0, botsCount = 0;
|
||||||
|
hashtags.stream >> writeCount >> searchCount;
|
||||||
|
|
||||||
|
QString tag;
|
||||||
|
quint16 count;
|
||||||
|
|
||||||
|
RecentHashtagPack write, search;
|
||||||
|
RecentInlineBots bots;
|
||||||
|
if (writeCount) {
|
||||||
|
write.reserve(writeCount);
|
||||||
|
for (uint32 i = 0; i < writeCount; ++i) {
|
||||||
|
hashtags.stream >> tag >> count;
|
||||||
|
write.push_back(qMakePair(tag.trimmed(), count));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (searchCount) {
|
||||||
|
search.reserve(searchCount);
|
||||||
|
for (uint32 i = 0; i < searchCount; ++i) {
|
||||||
|
hashtags.stream >> tag >> count;
|
||||||
|
search.push_back(qMakePair(tag.trimmed(), count));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cSetRecentWriteHashtags(write);
|
||||||
|
cSetRecentSearchHashtags(search);
|
||||||
|
|
||||||
|
if (!hashtags.stream.atEnd()) {
|
||||||
|
hashtags.stream >> botsCount;
|
||||||
|
if (botsCount) {
|
||||||
|
bots.reserve(botsCount);
|
||||||
|
for (uint32 i = 0; i < botsCount; ++i) {
|
||||||
|
PeerData *peer = _readPeer(hashtags, 9016);
|
||||||
|
if (peer && peer->isUser() && peer->asUser()->botInfo && !peer->asUser()->botInfo->inlinePlaceholder.isEmpty() && !peer->asUser()->username.isEmpty()) {
|
||||||
|
bots.push_back(peer->asUser());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cSetRecentInlineBots(bots);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void writeSavedPeers() {
|
void writeSavedPeers() {
|
||||||
if (!_working()) return;
|
if (!_working()) return;
|
||||||
|
|
||||||
|
@ -3651,8 +3689,8 @@ namespace Local {
|
||||||
_stickersKey = 0;
|
_stickersKey = 0;
|
||||||
_mapChanged = true;
|
_mapChanged = true;
|
||||||
}
|
}
|
||||||
if (_recentHashtagsKey) {
|
if (_recentHashtagsAndBotsKey) {
|
||||||
_recentHashtagsKey = 0;
|
_recentHashtagsAndBotsKey = 0;
|
||||||
_mapChanged = true;
|
_mapChanged = true;
|
||||||
}
|
}
|
||||||
if (_savedPeersKey) {
|
if (_savedPeersKey) {
|
||||||
|
|
|
@ -157,8 +157,8 @@ namespace Local {
|
||||||
void writeBackground(int32 id, const QImage &img);
|
void writeBackground(int32 id, const QImage &img);
|
||||||
bool readBackground();
|
bool readBackground();
|
||||||
|
|
||||||
void writeRecentHashtags();
|
void writeRecentHashtagsAndBots();
|
||||||
void readRecentHashtags();
|
void readRecentHashtagsAndBots();
|
||||||
|
|
||||||
void addSavedPeer(PeerData *peer, const QDateTime &position);
|
void addSavedPeer(PeerData *peer, const QDateTime &position);
|
||||||
void removeSavedPeer(PeerData *peer);
|
void removeSavedPeer(PeerData *peer);
|
||||||
|
|
|
@ -1349,7 +1349,7 @@ void MainWidget::saveRecentHashtags(const QString &text) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found && cRecentWriteHashtags().isEmpty() && cRecentSearchHashtags().isEmpty()) {
|
if (!found && cRecentWriteHashtags().isEmpty() && cRecentSearchHashtags().isEmpty()) {
|
||||||
Local::readRecentHashtags();
|
Local::readRecentHashtagsAndBots();
|
||||||
recent = cRecentWriteHashtags();
|
recent = cRecentWriteHashtags();
|
||||||
}
|
}
|
||||||
found = true;
|
found = true;
|
||||||
|
@ -1357,7 +1357,7 @@ void MainWidget::saveRecentHashtags(const QString &text) {
|
||||||
}
|
}
|
||||||
if (found) {
|
if (found) {
|
||||||
cSetRecentWriteHashtags(recent);
|
cSetRecentWriteHashtags(recent);
|
||||||
Local::writeRecentHashtags();
|
Local::writeRecentHashtagsAndBots();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,6 +121,8 @@ int32 gSavedGifsLimit = 100;
|
||||||
|
|
||||||
RecentHashtagPack gRecentWriteHashtags, gRecentSearchHashtags;
|
RecentHashtagPack gRecentWriteHashtags, gRecentSearchHashtags;
|
||||||
|
|
||||||
|
RecentInlineBots gRecentInlineBots;
|
||||||
|
|
||||||
bool gPasswordRecovered = false;
|
bool gPasswordRecovered = false;
|
||||||
int32 gPasscodeBadTries = 0;
|
int32 gPasscodeBadTries = 0;
|
||||||
uint64 gPasscodeLastTry = 0;
|
uint64 gPasscodeLastTry = 0;
|
||||||
|
|
|
@ -230,9 +230,13 @@ DeclareSetting(bool, ShowingSavedGifs);
|
||||||
DeclareSetting(int32, SavedGifsLimit);
|
DeclareSetting(int32, SavedGifsLimit);
|
||||||
|
|
||||||
typedef QList<QPair<QString, ushort> > RecentHashtagPack;
|
typedef QList<QPair<QString, ushort> > RecentHashtagPack;
|
||||||
DeclareSetting(RecentHashtagPack, RecentWriteHashtags);
|
DeclareRefSetting(RecentHashtagPack, RecentWriteHashtags);
|
||||||
DeclareSetting(RecentHashtagPack, RecentSearchHashtags);
|
DeclareSetting(RecentHashtagPack, RecentSearchHashtags);
|
||||||
|
|
||||||
|
class UserData;
|
||||||
|
typedef QVector<UserData*> RecentInlineBots;
|
||||||
|
DeclareRefSetting(RecentInlineBots, RecentInlineBots);
|
||||||
|
|
||||||
DeclareSetting(bool, PasswordRecovered);
|
DeclareSetting(bool, PasswordRecovered);
|
||||||
|
|
||||||
DeclareSetting(int32, PasscodeBadTries);
|
DeclareSetting(int32, PasscodeBadTries);
|
||||||
|
|
|
@ -34,8 +34,8 @@ IDI_ICON1 ICON "SourceFiles\\art\\icon256.ico"
|
||||||
//
|
//
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION 0,9,15,5
|
FILEVERSION 0,9,15,6
|
||||||
PRODUCTVERSION 0,9,15,5
|
PRODUCTVERSION 0,9,15,6
|
||||||
FILEFLAGSMASK 0x3fL
|
FILEFLAGSMASK 0x3fL
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
FILEFLAGS 0x1L
|
FILEFLAGS 0x1L
|
||||||
|
@ -51,10 +51,10 @@ BEGIN
|
||||||
BLOCK "040904b0"
|
BLOCK "040904b0"
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "Telegram Messenger LLP"
|
VALUE "CompanyName", "Telegram Messenger LLP"
|
||||||
VALUE "FileVersion", "0.9.15.5"
|
VALUE "FileVersion", "0.9.15.6"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2013"
|
VALUE "LegalCopyright", "Copyright (C) 2013"
|
||||||
VALUE "ProductName", "Telegram Desktop"
|
VALUE "ProductName", "Telegram Desktop"
|
||||||
VALUE "ProductVersion", "0.9.15.5"
|
VALUE "ProductVersion", "0.9.15.6"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
BLOCK "VarFileInfo"
|
BLOCK "VarFileInfo"
|
||||||
|
|
Loading…
Add table
Reference in a new issue