Add faved stickers set loading and saving.

Also move stickers loading methods to ApiWrap.
This commit is contained in:
John Preston 2017-08-02 18:07:28 +03:00
parent b0cc61c621
commit 667eb288d7
20 changed files with 507 additions and 426 deletions

View File

@ -884,6 +884,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
"lng_emoji_hide_panel" = "Click here to hide the emoji sidebar";
"lng_recent_stickers" = "Frequently used";
"lng_faved_stickers" = "Favorite stickers";
"lng_switch_stickers" = "Stickers";
"lng_switch_emoji" = "Emoji";
"lng_switch_gifs" = "GIFs";

View File

@ -41,6 +41,7 @@ constexpr auto kReloadChannelMembersTimeout = 1000; // 1 second wait before relo
constexpr auto kSaveCloudDraftTimeout = 1000; // save draft to the cloud with 1 sec extra delay
constexpr auto kSaveDraftBeforeQuitTimeout = 1500; // give the app 1.5 secs to save drafts to cloud when quitting
constexpr auto kSmallDelayMs = 5;
constexpr auto kStickersUpdateTimeout = 3600000; // update not more than once in an hour
} // namespace
@ -803,7 +804,7 @@ void ApiWrap::saveStickerSets(const Stickers::Order &localOrder, const Stickers:
request(base::take(_stickersReorderRequestId)).cancel();
request(base::take(_stickersClearRecentRequestId)).cancel();
auto writeInstalled = true, writeRecent = false, writeCloudRecent = false, writeArchived = false;
auto writeInstalled = true, writeRecent = false, writeCloudRecent = false, writeFaved = false, writeArchived = false;
auto &recent = cGetRecentStickers();
auto &sets = Global::RefStickerSets();
@ -909,6 +910,7 @@ void ApiWrap::saveStickerSets(const Stickers::Order &localOrder, const Stickers:
if (writeRecent) Local::writeUserSettings();
if (writeArchived) Local::writeArchivedStickers();
if (writeCloudRecent) Local::writeRecentStickers();
if (writeFaved) Local::writeFavedStickers();
emit App::main()->stickersUpdated();
if (_stickerSetDisenableRequests.isEmpty()) {
@ -1528,11 +1530,379 @@ void ApiWrap::stickersSaveOrder() {
}).fail([this](const RPCError &error) {
_stickersReorderRequestId = 0;
Global::SetLastStickersUpdate(0);
App::main()->updateStickers();
updateStickers();
}).send();
}
}
void ApiWrap::updateStickers() {
auto now = getms(true);
if (!Global::LastStickersUpdate() || now >= Global::LastStickersUpdate() + kStickersUpdateTimeout) {
if (!_stickersUpdateRequest) {
_stickersUpdateRequest = request(MTPmessages_GetAllStickers(MTP_int(Local::countStickersHash(true)))).done([this](const MTPmessages_AllStickers &result) {
stickersGot(result);
}).fail([this](const RPCError &error) {
LOG(("App Fail: Failed to get stickers!"));
Global::SetLastStickersUpdate(getms(true));
_stickersUpdateRequest = 0;
}).send();
}
}
if (!Global::LastRecentStickersUpdate() || now >= Global::LastRecentStickersUpdate() + kStickersUpdateTimeout) {
if (!_recentStickersUpdateRequest) {
_recentStickersUpdateRequest = request(MTPmessages_GetRecentStickers(MTP_flags(0), MTP_int(Local::countRecentStickersHash()))).done([this](const MTPmessages_RecentStickers &result) {
recentStickersGot(result);
}).fail([this](const RPCError &error) {
LOG(("App Fail: Failed to get recent stickers!"));
Global::SetLastRecentStickersUpdate(getms(true));
_recentStickersUpdateRequest = 0;
}).send();
}
}
if (!Global::LastFavedStickersUpdate() || now >= Global::LastFavedStickersUpdate() + kStickersUpdateTimeout) {
if (!_favedStickersUpdateRequest) {
_favedStickersUpdateRequest = request(MTPmessages_GetFavedStickers(MTP_int(Local::countFavedStickersHash()))).done([this](const MTPmessages_FavedStickers &result) {
favedStickersGot(result);
}).fail([this](const RPCError &error) {
LOG(("App Fail: Failed to get faved stickers!"));
Global::SetLastFavedStickersUpdate(getms(true));
_favedStickersUpdateRequest = 0;
}).send();
}
}
if (!Global::LastFeaturedStickersUpdate() || now >= Global::LastFeaturedStickersUpdate() + kStickersUpdateTimeout) {
if (!_featuredStickersUpdateRequest) {
_featuredStickersUpdateRequest = request(MTPmessages_GetFeaturedStickers(MTP_int(Local::countFeaturedStickersHash()))).done([this](const MTPmessages_FeaturedStickers &result) {
featuredStickersGot(result);
}).fail([this](const RPCError &error) {
LOG(("App Fail: Failed to get featured stickers!"));
Global::SetLastFeaturedStickersUpdate(getms(true));
_featuredStickersUpdateRequest = 0;
}).send();
}
}
if (!cLastSavedGifsUpdate() || now >= cLastSavedGifsUpdate() + kStickersUpdateTimeout) {
if (!_savedGifsUpdateRequest) {
_savedGifsUpdateRequest = request(MTPmessages_GetSavedGifs(MTP_int(Local::countSavedGifsHash()))).done([this](const MTPmessages_SavedGifs &result) {
savedGifsGot(result);
}).fail([this](const RPCError &error) {
LOG(("App Fail: Failed to get saved gifs!"));
cSetLastSavedGifsUpdate(getms(true));
_savedGifsUpdateRequest = 0;
}).send();
}
}
}
void ApiWrap::stickersGot(const MTPmessages_AllStickers &stickers) {
Global::SetLastStickersUpdate(getms(true));
_stickersUpdateRequest = 0;
if (stickers.type() != mtpc_messages_allStickers) return;
auto &d = stickers.c_messages_allStickers();
auto &d_sets = d.vsets.v;
auto &setsOrder = Global::RefStickerSetsOrder();
setsOrder.clear();
auto &sets = Global::RefStickerSets();
QMap<uint64, uint64> setsToRequest;
for (auto &set : sets) {
if (!(set.flags & MTPDstickerSet::Flag::f_archived)) {
set.flags &= ~MTPDstickerSet::Flag::f_installed; // mark for removing
}
}
for_const (auto &setData, d_sets) {
if (setData.type() == mtpc_stickerSet) {
auto set = Stickers::feedSet(setData.c_stickerSet());
if (!(set->flags & MTPDstickerSet::Flag::f_archived) || (set->flags & MTPDstickerSet::Flag::f_official)) {
setsOrder.push_back(set->id);
if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
setsToRequest.insert(set->id, set->access);
}
}
}
}
bool writeRecent = false;
RecentStickerPack &recent(cGetRecentStickers());
for (Stickers::Sets::iterator it = sets.begin(), e = sets.end(); it != e;) {
bool installed = (it->flags & MTPDstickerSet::Flag::f_installed);
bool featured = (it->flags & MTPDstickerSet_ClientFlag::f_featured);
bool special = (it->flags & MTPDstickerSet_ClientFlag::f_special);
bool archived = (it->flags & MTPDstickerSet::Flag::f_archived);
if (!installed) { // remove not mine sets from recent stickers
for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) {
if (it->stickers.indexOf(i->first) >= 0) {
i = recent.erase(i);
writeRecent = true;
} else {
++i;
}
}
}
if (installed || featured || special || archived) {
++it;
} else {
it = sets.erase(it);
}
}
if (Local::countStickersHash() != d.vhash.v) {
LOG(("API Error: received stickers hash %1 while counted hash is %2").arg(d.vhash.v).arg(Local::countStickersHash()));
}
if (!setsToRequest.isEmpty() && App::api()) {
for (QMap<uint64, uint64>::const_iterator i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) {
App::api()->scheduleStickerSetRequest(i.key(), i.value());
}
App::api()->requestStickerSets();
}
Local::writeInstalledStickers();
if (writeRecent) Local::writeUserSettings();
if (App::main()) emit App::main()->stickersUpdated();
}
void ApiWrap::recentStickersGot(const MTPmessages_RecentStickers &stickers) {
Global::SetLastRecentStickersUpdate(getms(true));
_recentStickersUpdateRequest = 0;
if (stickers.type() != mtpc_messages_recentStickers) return;
auto &d = stickers.c_messages_recentStickers();
insertSpecialStickersSet(Stickers::CloudRecentSetId, lang(lng_recent_stickers), d.vstickers, d.vhash);
if (Local::countRecentStickersHash() != d.vhash.v) {
LOG(("API Error: received stickers hash %1 while counted hash is %2").arg(d.vhash.v).arg(Local::countRecentStickersHash()));
}
Local::writeRecentStickers();
if (App::main()) emit App::main()->stickersUpdated();
}
void ApiWrap::favedStickersGot(const MTPmessages_FavedStickers &stickers) {
Global::SetLastFavedStickersUpdate(getms(true));
_favedStickersUpdateRequest = 0;
if (stickers.type() != mtpc_messages_favedStickers) return;
auto &d = stickers.c_messages_favedStickers();
insertSpecialStickersSet(Stickers::FavedSetId, lang(lng_faved_stickers), d.vstickers, d.vhash);
if (Local::countRecentStickersHash() != d.vhash.v) {
LOG(("API Error: received stickers hash %1 while counted hash is %2").arg(d.vhash.v).arg(Local::countRecentStickersHash()));
}
Local::writeRecentStickers();
if (App::main()) emit App::main()->stickersUpdated();
}
void ApiWrap::insertSpecialStickersSet(uint64 setId, const QString &setTitle, const MTPVector<MTPDocument> &items, MTPint hash) {
auto &sets = Global::RefStickerSets();
auto it = sets.find(setId);
auto &d_docs = items.v;
if (d_docs.isEmpty()) {
if (it != sets.cend()) {
sets.erase(it);
}
} else {
if (it == sets.cend()) {
it = sets.insert(setId, Stickers::Set(Stickers::FavedSetId, 0, setTitle, QString(), 0, 0, qFlags(MTPDstickerSet_ClientFlag::f_special)));
} else {
it->title = setTitle;
}
it->hash = hash.v;
auto custom = sets.find(Stickers::CustomSetId);
auto pack = StickerPack();
pack.reserve(d_docs.size());
for_const (auto &mtpDocument, d_docs) {
auto document = App::feedDocument(mtpDocument);
if (!document || !document->sticker()) continue;
pack.push_back(document);
if (custom != sets.cend()) {
auto index = custom->stickers.indexOf(document);
if (index >= 0) {
custom->stickers.removeAt(index);
}
}
}
if (custom != sets.cend() && custom->stickers.isEmpty()) {
sets.erase(custom);
custom = sets.end();
}
auto writeRecent = false;
auto &recent = cGetRecentStickers();
for (auto i = recent.begin(); i != recent.cend();) {
if (it->stickers.indexOf(i->first) >= 0 && pack.indexOf(i->first) < 0) {
i = recent.erase(i);
writeRecent = true;
} else {
++i;
}
}
if (pack.isEmpty()) {
sets.erase(it);
} else {
it->stickers = pack;
it->emoji.clear();
}
if (writeRecent) {
Local::writeUserSettings();
}
}
}
void ApiWrap::featuredStickersGot(const MTPmessages_FeaturedStickers &stickers) {
Global::SetLastFeaturedStickersUpdate(getms(true));
_featuredStickersUpdateRequest = 0;
if (stickers.type() != mtpc_messages_featuredStickers) return;
auto &d = stickers.c_messages_featuredStickers();
OrderedSet<uint64> unread;
for_const (auto &unreadSetId, d.vunread.v) {
unread.insert(unreadSetId.v);
}
auto &d_sets = d.vsets.v;
auto &setsOrder = Global::RefFeaturedStickerSetsOrder();
setsOrder.clear();
auto &sets = Global::RefStickerSets();
QMap<uint64, uint64> setsToRequest;
for (auto &set : sets) {
set.flags &= ~MTPDstickerSet_ClientFlag::f_featured; // mark for removing
}
for (int i = 0, l = d_sets.size(); i != l; ++i) {
auto &setData = d_sets[i];
const MTPDstickerSet *set = nullptr;
switch (setData.type()) {
case mtpc_stickerSetCovered: {
auto &d = setData.c_stickerSetCovered();
if (d.vset.type() == mtpc_stickerSet) {
set = &d.vset.c_stickerSet();
}
} break;
case mtpc_stickerSetMultiCovered: {
auto &d = setData.c_stickerSetMultiCovered();
if (d.vset.type() == mtpc_stickerSet) {
set = &d.vset.c_stickerSet();
}
} break;
}
if (set) {
auto it = sets.find(set->vid.v);
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)) {
setClientFlags |= MTPDstickerSet_ClientFlag::f_unread;
}
it = sets.insert(set->vid.v, Stickers::Set(set->vid.v, set->vaccess_hash.v, title, qs(set->vshort_name), set->vcount.v, set->vhash.v, set->vflags.v | setClientFlags));
} else {
it->access = set->vaccess_hash.v;
it->title = title;
it->shortName = qs(set->vshort_name);
auto clientFlags = it->flags & (MTPDstickerSet_ClientFlag::f_featured | MTPDstickerSet_ClientFlag::f_unread | MTPDstickerSet_ClientFlag::f_not_loaded | MTPDstickerSet_ClientFlag::f_special);
it->flags = set->vflags.v | clientFlags;
it->flags |= MTPDstickerSet_ClientFlag::f_featured;
if (unread.contains(it->id)) {
it->flags |= MTPDstickerSet_ClientFlag::f_unread;
} else {
it->flags &= ~MTPDstickerSet_ClientFlag::f_unread;
}
if (it->count != set->vcount.v || it->hash != set->vhash.v || it->emoji.isEmpty()) {
it->count = set->vcount.v;
it->hash = set->vhash.v;
it->flags |= MTPDstickerSet_ClientFlag::f_not_loaded; // need to request this set
}
}
setsOrder.push_back(set->vid.v);
if (it->stickers.isEmpty() || (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
setsToRequest.insert(set->vid.v, set->vaccess_hash.v);
}
}
}
int unreadCount = 0;
for (auto it = sets.begin(), e = sets.end(); it != e;) {
bool installed = (it->flags & MTPDstickerSet::Flag::f_installed);
bool featured = (it->flags & MTPDstickerSet_ClientFlag::f_featured);
bool special = (it->flags & MTPDstickerSet_ClientFlag::f_special);
bool archived = (it->flags & MTPDstickerSet::Flag::f_archived);
if (installed || featured || special || archived) {
if (featured && (it->flags & MTPDstickerSet_ClientFlag::f_unread)) {
++unreadCount;
}
++it;
} else {
it = sets.erase(it);
}
}
if (Global::FeaturedStickerSetsUnreadCount() != unreadCount) {
Global::SetFeaturedStickerSetsUnreadCount(unreadCount);
Global::RefFeaturedStickerSetsUnreadCountChanged().notify();
}
if (Local::countFeaturedStickersHash() != d.vhash.v) {
LOG(("API Error: received featured stickers hash %1 while counted hash is %2").arg(d.vhash.v).arg(Local::countFeaturedStickersHash()));
}
if (!setsToRequest.isEmpty() && App::api()) {
for (QMap<uint64, uint64>::const_iterator i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) {
App::api()->scheduleStickerSetRequest(i.key(), i.value());
}
App::api()->requestStickerSets();
}
Local::writeFeaturedStickers();
if (App::main()) emit App::main()->stickersUpdated();
}
void ApiWrap::savedGifsGot(const MTPmessages_SavedGifs &gifs) {
cSetLastSavedGifsUpdate(getms(true));
_savedGifsUpdateRequest = 0;
if (gifs.type() != mtpc_messages_savedGifs) return;
auto &d = gifs.c_messages_savedGifs();
auto &gifsList = d.vgifs.v;
auto &saved = cRefSavedGifs();
saved.clear();
saved.reserve(gifsList.size());
for (auto &gif : gifsList) {
auto document = App::feedDocument(gif);
if (!document || !document->isGifv()) {
LOG(("API Error: bad document returned in HistoryWidget::savedGifsGot!"));
continue;
}
saved.push_back(document);
}
if (Local::countSavedGifsHash() != d.vhash.v) {
LOG(("API Error: received saved gifs hash %1 while counted hash is %2").arg(d.vhash.v).arg(Local::countSavedGifsHash()));
}
Local::writeSavedGifs();
AuthSession::Current().data().savedGifsUpdated().notify();
}
void ApiWrap::applyUpdatesNoPtsCheck(const MTPUpdates &updates) {
switch (updates.type()) {
case mtpc_updateShortMessage: {

View File

@ -69,6 +69,7 @@ public:
void scheduleStickerSetRequest(uint64 setId, uint64 access);
void requestStickerSets();
void saveStickerSets(const Stickers::Order &localOrder, const Stickers::Order &localRemoved);
void updateStickers();
void joinChannel(ChannelData *channel);
void leaveChannel(ChannelData *channel);
@ -131,6 +132,13 @@ private:
void stickerSetDisenabled(mtpRequestId requestId);
void stickersSaveOrder();
void stickersGot(const MTPmessages_AllStickers &stickers);
void recentStickersGot(const MTPmessages_RecentStickers &stickers);
void favedStickersGot(const MTPmessages_FavedStickers &stickers);
void featuredStickersGot(const MTPmessages_FeaturedStickers &stickers);
void savedGifsGot(const MTPmessages_SavedGifs &gifs);
void insertSpecialStickersSet(uint64 setId, const QString &setTitle, const MTPVector<MTPDocument> &items, MTPint hash);
gsl::not_null<AuthSession*> _session;
mtpRequestId _changelogSubscription = 0;
@ -171,6 +179,12 @@ private:
mtpRequestId _stickersReorderRequestId = 0;
mtpRequestId _stickersClearRecentRequestId = 0;
mtpRequestId _stickersUpdateRequest = 0;
mtpRequestId _recentStickersUpdateRequest = 0;
mtpRequestId _favedStickersUpdateRequest = 0;
mtpRequestId _featuredStickersUpdateRequest = 0;
mtpRequestId _savedGifsUpdateRequest = 0;
QMap<mtpTypeId, mtpRequestId> _privacySaveRequests;
mtpRequestId _contactsStatusesRequestId = 0;

View File

@ -1140,7 +1140,7 @@ namespace {
AuthSession::Current().data().savedGifsUpdated().notify();
cSetLastSavedGifsUpdate(0);
App::main()->updateStickers();
AuthSession::Current().api().updateStickers();
}
}
@ -1757,6 +1757,8 @@ namespace {
if (it != Global::StickerSets().cend()) {
if (it->id == Stickers::CloudRecentSetId) {
Local::writeRecentStickers();
} else if (it->id == Stickers::FavedSetId) {
Local::writeFavedStickers();
} else if (it->flags & MTPDstickerSet::Flag::f_archived) {
Local::writeArchivedStickers();
} else if (it->flags & MTPDstickerSet::Flag::f_installed) {

View File

@ -115,7 +115,7 @@ StickerSetBox::Inner::Inner(QWidget *parent, const MTPInputStickerSet &set) : TW
case mtpc_inputStickerSetShortName: _setShortName = qs(set.c_inputStickerSetShortName().vshort_name); break;
}
MTP::send(MTPmessages_GetStickerSet(_input), rpcDone(&Inner::gotSet), rpcFail(&Inner::failedSet));
App::main()->updateStickers();
AuthSession::Current().api().updateStickers();
subscribe(AuthSession::CurrentDownloaderTaskFinished(), [this] { update(); });

View File

@ -269,7 +269,7 @@ void StickersBox::prepare() {
setDimensions(st::boxWideWidth, (_section == Section::ArchivedPart) ? st::sessionsHeight : st::boxMaxListHeight);
connect(App::main(), SIGNAL(stickersUpdated()), this, SLOT(onStickersUpdated()));
App::main()->updateStickers();
AuthSession::Current().api().updateStickers();
if (_installed.widget()) {
connect(_installed.widget(), SIGNAL(draggingScrollDelta(int)), this, SLOT(onDraggingScrollDelta(int)));

View File

@ -1025,6 +1025,7 @@ void StickersListWidget::refreshStickers() {
_mySets.reserve(Global::StickerSetsOrder().size() + 1);
refreshRecentStickers(false);
refreshFavedStickers();
for_const (auto setId, Global::StickerSetsOrder()) {
appendSet(_mySets, setId, AppendSkip::Archived);
}
@ -1171,6 +1172,16 @@ void StickersListWidget::refreshRecentStickers(bool performResize) {
}
}
void StickersListWidget::refreshFavedStickers() {
clearSelection();
auto &sets = Global::StickerSets();
auto it = sets.constFind(Stickers::CloudRecentSetId);
if (it == sets.cend() || it->stickers.isEmpty()) {
return;
}
_mySets.push_back(Set(Stickers::FavedSetId, MTPDstickerSet::Flag::f_official | MTPDstickerSet_ClientFlag::f_special, lang(lng_faved_stickers), it->stickers.size() * 2, it->stickers));
}
void StickersListWidget::fillIcons(QList<StickerIcon> &icons) {
icons.clear();
icons.reserve(_mySets.size() + 1);

View File

@ -49,7 +49,6 @@ public:
void showStickerSet(uint64 setId);
void refreshStickers();
void refreshRecentStickers(bool resize = true);
void fillIcons(QList<StickerIcon> &icons);
bool preventAutoHide();
@ -133,6 +132,9 @@ private:
void installSet(quint64 setId);
void removeSet(quint64 setId);
void refreshRecentStickers(bool resize = true);
void refreshFavedStickers();
void updateSelected();
void setSelected(OverState newSelected);
void setPressed(OverState newPressed);

View File

@ -34,6 +34,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
#include "lang/lang_keys.h"
#include "mainwindow.h"
#include "observer_peer.h"
#include "apiwrap.h"
namespace ChatHelpers {
namespace {
@ -486,7 +487,7 @@ void TabbedSelector::hideFinished() {
}
void TabbedSelector::showStarted() {
emit updateStickers();
AuthSession::Current().api().updateStickers();
currentTab()->widget()->refreshRecent();
currentTab()->widget()->preloadImages();
_a_slide.finish();

View File

@ -105,8 +105,6 @@ signals:
void photoSelected(PhotoData *photo);
void inlineResultSelected(InlineBots::Result *result, UserData *bot);
void updateStickers();
void cancelled();
void slideFinished();
void checkForHide();

View File

@ -619,6 +619,7 @@ struct Data {
int32 SavedGifsLimit = 200;
int32 EditTimeLimit = 172800;
int32 StickersRecentLimit = 30;
int32 StickersFavedLimit = 30; // TODO
int32 PinnedDialogsCountMax = 5;
QString InternalLinksDomain = qsl("https://t.me/");
int32 CallReceiveTimeoutMs = 20000;
@ -636,6 +637,7 @@ struct Data {
Stickers::Order StickerSetsOrder;
TimeMs LastStickersUpdate = 0;
TimeMs LastRecentStickersUpdate = 0;
TimeMs LastFavedStickersUpdate = 0;
Stickers::Order FeaturedStickerSetsOrder;
int FeaturedStickerSetsUnreadCount = 0;
base::Observable<void> FeaturedStickerSetsUnreadCountChanged;
@ -740,6 +742,7 @@ DefineVar(Global, int32, PushChatLimit);
DefineVar(Global, int32, SavedGifsLimit);
DefineVar(Global, int32, EditTimeLimit);
DefineVar(Global, int32, StickersRecentLimit);
DefineVar(Global, int32, StickersFavedLimit);
DefineVar(Global, int32, PinnedDialogsCountMax);
DefineVar(Global, QString, InternalLinksDomain);
DefineVar(Global, int32, CallReceiveTimeoutMs);
@ -757,6 +760,7 @@ DefineVar(Global, Stickers::Sets, StickerSets);
DefineVar(Global, Stickers::Order, StickerSetsOrder);
DefineVar(Global, TimeMs, LastStickersUpdate);
DefineVar(Global, TimeMs, LastRecentStickersUpdate);
DefineVar(Global, TimeMs, LastFavedStickersUpdate);
DefineVar(Global, Stickers::Order, FeaturedStickerSetsOrder);
DefineVar(Global, int, FeaturedStickerSetsUnreadCount);
DefineRefVar(Global, base::Observable<void>, FeaturedStickerSetsUnreadCountChanged);

View File

@ -244,12 +244,13 @@ enum Flags {
namespace Stickers {
constexpr uint64 DefaultSetId = 0; // for backward compatibility
constexpr uint64 CustomSetId = 0xFFFFFFFFFFFFFFFFULL;
constexpr uint64 RecentSetId = 0xFFFFFFFFFFFFFFFEULL; // for emoji/stickers panel, should not appear in Sets
constexpr uint64 NoneSetId = 0xFFFFFFFFFFFFFFFDULL; // for emoji/stickers panel, should not appear in Sets
constexpr uint64 CloudRecentSetId = 0xFFFFFFFFFFFFFFFCULL; // for cloud-stored recent stickers
constexpr uint64 FeaturedSetId = 0xFFFFFFFFFFFFFFFBULL; // for emoji/stickers panel, should not appear in Sets
constexpr auto DefaultSetId = 0; // for backward compatibility
constexpr auto CustomSetId = 0xFFFFFFFFFFFFFFFFULL;
constexpr auto RecentSetId = 0xFFFFFFFFFFFFFFFEULL; // for emoji/stickers panel, should not appear in Sets
constexpr auto NoneSetId = 0xFFFFFFFFFFFFFFFDULL; // for emoji/stickers panel, should not appear in Sets
constexpr auto CloudRecentSetId = 0xFFFFFFFFFFFFFFFCULL; // for cloud-stored recent stickers
constexpr auto FeaturedSetId = 0xFFFFFFFFFFFFFFFBULL; // for emoji/stickers panel, should not appear in Sets
constexpr auto FavedSetId = 0xFFFFFFFFFFFFFFFAULL; // for cloud-stored faved stickers
struct Set {
Set(uint64 id, uint64 access, const QString &title, const QString &shortName, int32 count, int32 hash, MTPDstickerSet::Flags flags)
: id(id)
@ -330,6 +331,7 @@ DeclareVar(int32, PushChatLimit);
DeclareVar(int32, SavedGifsLimit);
DeclareVar(int32, EditTimeLimit);
DeclareVar(int32, StickersRecentLimit);
DeclareVar(int32, StickersFavedLimit);
DeclareVar(int32, PinnedDialogsCountMax);
DeclareVar(QString, InternalLinksDomain);
DeclareVar(int32, CallReceiveTimeoutMs);
@ -349,6 +351,7 @@ DeclareVar(Stickers::Sets, StickerSets);
DeclareVar(Stickers::Order, StickerSetsOrder);
DeclareVar(TimeMs, LastStickersUpdate);
DeclareVar(TimeMs, LastRecentStickersUpdate);
DeclareVar(TimeMs, LastFavedStickersUpdate);
DeclareVar(Stickers::Order, FeaturedStickerSetsOrder);
DeclareVar(int, FeaturedStickerSetsUnreadCount);
DeclareRefVar(base::Observable<void>, FeaturedStickerSetsUnreadCountChanged);

View File

@ -172,7 +172,6 @@ test_ptr<TestClass> tmp = { nullptr };
namespace {
constexpr auto kStickersUpdateTimeout = 3600000; // update not more than once in an hour
constexpr auto kSaveTabbedSelectorSectionTimeoutMs = 1000;
constexpr auto kMessagesPerPageFirst = 30;
constexpr auto kMessagesPerPage = 50;
@ -662,7 +661,6 @@ HistoryWidget::HistoryWidget(QWidget *parent, gsl::not_null<Window::Controller*>
connect(_tabbedSelector, SIGNAL(stickerSelected(DocumentData*)), this, SLOT(onStickerSend(DocumentData*)));
connect(_tabbedSelector, SIGNAL(photoSelected(PhotoData*)), this, SLOT(onPhotoSend(PhotoData*)));
connect(_tabbedSelector, SIGNAL(inlineResultSelected(InlineBots::Result*,UserData*)), this, SLOT(onInlineResultSend(InlineBots::Result*,UserData*)));
connect(_tabbedSelector, SIGNAL(updateStickers()), this, SLOT(updateStickers()));
connect(&_sendActionStopTimer, SIGNAL(timeout()), this, SLOT(onCancelSendAction()));
connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreviewTimeout()));
connect(Media::Capture::instance(), SIGNAL(error()), this, SLOT(onRecordError()));
@ -1319,30 +1317,6 @@ void HistoryWidget::onRecordUpdate(quint16 level, qint32 samples) {
}
}
void HistoryWidget::updateStickers() {
auto now = getms(true);
if (!Global::LastStickersUpdate() || now >= Global::LastStickersUpdate() + kStickersUpdateTimeout) {
if (!_stickersUpdateRequest) {
_stickersUpdateRequest = MTP::send(MTPmessages_GetAllStickers(MTP_int(Local::countStickersHash(true))), rpcDone(&HistoryWidget::stickersGot), rpcFail(&HistoryWidget::stickersFailed));
}
}
if (!Global::LastRecentStickersUpdate() || now >= Global::LastRecentStickersUpdate() + kStickersUpdateTimeout) {
if (!_recentStickersUpdateRequest) {
_recentStickersUpdateRequest = MTP::send(MTPmessages_GetRecentStickers(MTP_flags(0), MTP_int(Local::countRecentStickersHash())), rpcDone(&HistoryWidget::recentStickersGot), rpcFail(&HistoryWidget::recentStickersFailed));
}
}
if (!Global::LastFeaturedStickersUpdate() || now >= Global::LastFeaturedStickersUpdate() + kStickersUpdateTimeout) {
if (!_featuredStickersUpdateRequest) {
_featuredStickersUpdateRequest = MTP::send(MTPmessages_GetFeaturedStickers(MTP_int(Local::countFeaturedStickersHash())), rpcDone(&HistoryWidget::featuredStickersGot), rpcFail(&HistoryWidget::featuredStickersFailed));
}
}
if (!cLastSavedGifsUpdate() || now >= cLastSavedGifsUpdate() + kStickersUpdateTimeout) {
if (!_savedGifsUpdateRequest) {
_savedGifsUpdateRequest = MTP::send(MTPmessages_GetSavedGifs(MTP_int(Local::countSavedGifsHash())), rpcDone(&HistoryWidget::savedGifsGot), rpcFail(&HistoryWidget::savedGifsFailed));
}
}
}
void HistoryWidget::notify_botCommandsChanged(UserData *user) {
if (_peer && (_peer == user || !_peer->isUser())) {
if (_fieldAutocomplete->clearFilteredBotCommands()) {
@ -1458,324 +1432,6 @@ bool HistoryWidget::cmd_previous_chat() {
return false;
}
void HistoryWidget::stickersGot(const MTPmessages_AllStickers &stickers) {
Global::SetLastStickersUpdate(getms(true));
_stickersUpdateRequest = 0;
if (stickers.type() != mtpc_messages_allStickers) return;
auto &d = stickers.c_messages_allStickers();
auto &d_sets = d.vsets.v;
auto &setsOrder = Global::RefStickerSetsOrder();
setsOrder.clear();
auto &sets = Global::RefStickerSets();
QMap<uint64, uint64> setsToRequest;
for (auto &set : sets) {
if (!(set.flags & MTPDstickerSet::Flag::f_archived)) {
set.flags &= ~MTPDstickerSet::Flag::f_installed; // mark for removing
}
}
for_const (auto &setData, d_sets) {
if (setData.type() == mtpc_stickerSet) {
auto set = Stickers::feedSet(setData.c_stickerSet());
if (!(set->flags & MTPDstickerSet::Flag::f_archived) || (set->flags & MTPDstickerSet::Flag::f_official)) {
setsOrder.push_back(set->id);
if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
setsToRequest.insert(set->id, set->access);
}
}
}
}
bool writeRecent = false;
RecentStickerPack &recent(cGetRecentStickers());
for (Stickers::Sets::iterator it = sets.begin(), e = sets.end(); it != e;) {
bool installed = (it->flags & MTPDstickerSet::Flag::f_installed);
bool featured = (it->flags & MTPDstickerSet_ClientFlag::f_featured);
bool special = (it->flags & MTPDstickerSet_ClientFlag::f_special);
bool archived = (it->flags & MTPDstickerSet::Flag::f_archived);
if (!installed) { // remove not mine sets from recent stickers
for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) {
if (it->stickers.indexOf(i->first) >= 0) {
i = recent.erase(i);
writeRecent = true;
} else {
++i;
}
}
}
if (installed || featured || special || archived) {
++it;
} else {
it = sets.erase(it);
}
}
if (Local::countStickersHash() != d.vhash.v) {
LOG(("API Error: received stickers hash %1 while counted hash is %2").arg(d.vhash.v).arg(Local::countStickersHash()));
}
if (!setsToRequest.isEmpty() && App::api()) {
for (QMap<uint64, uint64>::const_iterator i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) {
App::api()->scheduleStickerSetRequest(i.key(), i.value());
}
App::api()->requestStickerSets();
}
Local::writeInstalledStickers();
if (writeRecent) Local::writeUserSettings();
if (App::main()) emit App::main()->stickersUpdated();
}
bool HistoryWidget::stickersFailed(const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false;
LOG(("App Fail: Failed to get stickers!"));
Global::SetLastStickersUpdate(getms(true));
_stickersUpdateRequest = 0;
return true;
}
void HistoryWidget::recentStickersGot(const MTPmessages_RecentStickers &stickers) {
Global::SetLastRecentStickersUpdate(getms(true));
_recentStickersUpdateRequest = 0;
if (stickers.type() != mtpc_messages_recentStickers) return;
auto &d = stickers.c_messages_recentStickers();
auto &sets = Global::RefStickerSets();
auto it = sets.find(Stickers::CloudRecentSetId);
auto &d_docs = d.vstickers.v;
if (d_docs.isEmpty()) {
if (it != sets.cend()) {
sets.erase(it);
}
} else {
if (it == sets.cend()) {
it = sets.insert(Stickers::CloudRecentSetId, Stickers::Set(Stickers::CloudRecentSetId, 0, lang(lng_recent_stickers), QString(), 0, 0, qFlags(MTPDstickerSet_ClientFlag::f_special)));
} else {
it->title = lang(lng_recent_stickers);
}
it->hash = d.vhash.v;
auto custom = sets.find(Stickers::CustomSetId);
StickerPack pack;
pack.reserve(d_docs.size());
for (int32 i = 0, l = d_docs.size(); i != l; ++i) {
DocumentData *doc = App::feedDocument(d_docs.at(i));
if (!doc || !doc->sticker()) continue;
pack.push_back(doc);
if (custom != sets.cend()) {
int32 index = custom->stickers.indexOf(doc);
if (index >= 0) {
custom->stickers.removeAt(index);
}
}
}
if (custom != sets.cend() && custom->stickers.isEmpty()) {
sets.erase(custom);
custom = sets.end();
}
bool writeRecent = false;
RecentStickerPack &recent(cGetRecentStickers());
for (RecentStickerPack::iterator i = recent.begin(); i != recent.cend();) {
if (it->stickers.indexOf(i->first) >= 0 && pack.indexOf(i->first) < 0) {
i = recent.erase(i);
writeRecent = true;
} else {
++i;
}
}
if (pack.isEmpty()) {
sets.erase(it);
} else {
it->stickers = pack;
it->emoji.clear();
}
if (writeRecent) {
Local::writeUserSettings();
}
}
if (Local::countRecentStickersHash() != d.vhash.v) {
LOG(("API Error: received stickers hash %1 while counted hash is %2").arg(d.vhash.v).arg(Local::countRecentStickersHash()));
}
Local::writeRecentStickers();
if (App::main()) emit App::main()->stickersUpdated();
}
bool HistoryWidget::recentStickersFailed(const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false;
LOG(("App Fail: Failed to get recent stickers!"));
Global::SetLastRecentStickersUpdate(getms(true));
_recentStickersUpdateRequest = 0;
return true;
}
void HistoryWidget::featuredStickersGot(const MTPmessages_FeaturedStickers &stickers) {
Global::SetLastFeaturedStickersUpdate(getms(true));
_featuredStickersUpdateRequest = 0;
if (stickers.type() != mtpc_messages_featuredStickers) return;
auto &d = stickers.c_messages_featuredStickers();
OrderedSet<uint64> unread;
for_const (auto &unreadSetId, d.vunread.v) {
unread.insert(unreadSetId.v);
}
auto &d_sets = d.vsets.v;
auto &setsOrder = Global::RefFeaturedStickerSetsOrder();
setsOrder.clear();
auto &sets = Global::RefStickerSets();
QMap<uint64, uint64> setsToRequest;
for (auto &set : sets) {
set.flags &= ~MTPDstickerSet_ClientFlag::f_featured; // mark for removing
}
for (int i = 0, l = d_sets.size(); i != l; ++i) {
auto &setData = d_sets[i];
const MTPDstickerSet *set = nullptr;
switch (setData.type()) {
case mtpc_stickerSetCovered: {
auto &d = setData.c_stickerSetCovered();
if (d.vset.type() == mtpc_stickerSet) {
set = &d.vset.c_stickerSet();
}
} break;
case mtpc_stickerSetMultiCovered: {
auto &d = setData.c_stickerSetMultiCovered();
if (d.vset.type() == mtpc_stickerSet) {
set = &d.vset.c_stickerSet();
}
} break;
}
if (set) {
auto it = sets.find(set->vid.v);
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)) {
setClientFlags |= MTPDstickerSet_ClientFlag::f_unread;
}
it = sets.insert(set->vid.v, Stickers::Set(set->vid.v, set->vaccess_hash.v, title, qs(set->vshort_name), set->vcount.v, set->vhash.v, set->vflags.v | setClientFlags));
} else {
it->access = set->vaccess_hash.v;
it->title = title;
it->shortName = qs(set->vshort_name);
auto clientFlags = it->flags & (MTPDstickerSet_ClientFlag::f_featured | MTPDstickerSet_ClientFlag::f_unread | MTPDstickerSet_ClientFlag::f_not_loaded | MTPDstickerSet_ClientFlag::f_special);
it->flags = set->vflags.v | clientFlags;
it->flags |= MTPDstickerSet_ClientFlag::f_featured;
if (unread.contains(it->id)) {
it->flags |= MTPDstickerSet_ClientFlag::f_unread;
} else {
it->flags &= ~MTPDstickerSet_ClientFlag::f_unread;
}
if (it->count != set->vcount.v || it->hash != set->vhash.v || it->emoji.isEmpty()) {
it->count = set->vcount.v;
it->hash = set->vhash.v;
it->flags |= MTPDstickerSet_ClientFlag::f_not_loaded; // need to request this set
}
}
setsOrder.push_back(set->vid.v);
if (it->stickers.isEmpty() || (it->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
setsToRequest.insert(set->vid.v, set->vaccess_hash.v);
}
}
}
int unreadCount = 0;
for (auto it = sets.begin(), e = sets.end(); it != e;) {
bool installed = (it->flags & MTPDstickerSet::Flag::f_installed);
bool featured = (it->flags & MTPDstickerSet_ClientFlag::f_featured);
bool special = (it->flags & MTPDstickerSet_ClientFlag::f_special);
bool archived = (it->flags & MTPDstickerSet::Flag::f_archived);
if (installed || featured || special || archived) {
if (featured && (it->flags & MTPDstickerSet_ClientFlag::f_unread)) {
++unreadCount;
}
++it;
} else {
it = sets.erase(it);
}
}
if (Global::FeaturedStickerSetsUnreadCount() != unreadCount) {
Global::SetFeaturedStickerSetsUnreadCount(unreadCount);
Global::RefFeaturedStickerSetsUnreadCountChanged().notify();
}
if (Local::countFeaturedStickersHash() != d.vhash.v) {
LOG(("API Error: received featured stickers hash %1 while counted hash is %2").arg(d.vhash.v).arg(Local::countFeaturedStickersHash()));
}
if (!setsToRequest.isEmpty() && App::api()) {
for (QMap<uint64, uint64>::const_iterator i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) {
App::api()->scheduleStickerSetRequest(i.key(), i.value());
}
App::api()->requestStickerSets();
}
Local::writeFeaturedStickers();
if (App::main()) emit App::main()->stickersUpdated();
}
bool HistoryWidget::featuredStickersFailed(const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false;
LOG(("App Fail: Failed to get featured stickers!"));
Global::SetLastFeaturedStickersUpdate(getms(true));
_featuredStickersUpdateRequest = 0;
return true;
}
void HistoryWidget::savedGifsGot(const MTPmessages_SavedGifs &gifs) {
cSetLastSavedGifsUpdate(getms(true));
_savedGifsUpdateRequest = 0;
if (gifs.type() != mtpc_messages_savedGifs) return;
auto &d = gifs.c_messages_savedGifs();
auto &gifsList = d.vgifs.v;
auto &saved = cRefSavedGifs();
saved.clear();
saved.reserve(gifsList.size());
for (auto &gif : gifsList) {
auto document = App::feedDocument(gif);
if (!document || !document->isGifv()) {
LOG(("API Error: bad document returned in HistoryWidget::savedGifsGot!"));
continue;
}
saved.push_back(document);
}
if (Local::countSavedGifsHash() != d.vhash.v) {
LOG(("API Error: received saved gifs hash %1 while counted hash is %2").arg(d.vhash.v).arg(Local::countSavedGifsHash()));
}
Local::writeSavedGifs();
AuthSession::Current().data().savedGifsUpdated().notify();
}
void HistoryWidget::saveGif(DocumentData *doc) {
if (doc->isGifv() && cSavedGifs().indexOf(doc) != 0) {
MTPInputDocument mtpInput = doc->mtpInput();
@ -1791,16 +1447,6 @@ void HistoryWidget::saveGifDone(DocumentData *doc, const MTPBool &result) {
}
}
bool HistoryWidget::savedGifsFailed(const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false;
LOG(("App Fail: Failed to get saved gifs!"));
cSetLastSavedGifsUpdate(getms(true));
_savedGifsUpdateRequest = 0;
return true;
}
void HistoryWidget::clearReplyReturns() {
_replyReturns.clear();
_replyReturn = 0;

View File

@ -452,8 +452,6 @@ public slots:
void onDraftSave(bool delayed = false);
void onCloudDraftSave();
void updateStickers();
void onRecordError();
void onRecordDone(QByteArray result, VoiceWaveform waveform, qint32 samples);
void onRecordUpdate(quint16 level, qint32 samples);
@ -683,22 +681,6 @@ private:
void countHistoryShowFrom();
mtpRequestId _stickersUpdateRequest = 0;
void stickersGot(const MTPmessages_AllStickers &stickers);
bool stickersFailed(const RPCError &error);
mtpRequestId _recentStickersUpdateRequest = 0;
void recentStickersGot(const MTPmessages_RecentStickers &stickers);
bool recentStickersFailed(const RPCError &error);
mtpRequestId _featuredStickersUpdateRequest = 0;
void featuredStickersGot(const MTPmessages_FeaturedStickers &stickers);
bool featuredStickersFailed(const RPCError &error);
mtpRequestId _savedGifsUpdateRequest = 0;
void savedGifsGot(const MTPmessages_SavedGifs &gifs);
bool savedGifsFailed(const RPCError &error);
enum class TextUpdateEvent {
SaveDraft = 0x01,
SendTyping = 0x02,

View File

@ -709,10 +709,6 @@ void MainWidget::updateMutedIn(int32 seconds) {
_updateMutedTimer.start(ms);
}
void MainWidget::updateStickers() {
_history->updateStickers();
}
void MainWidget::onUpdateMuted() {
App::updateMuted();
}
@ -3933,6 +3929,7 @@ void MainWidget::start(const MTPUser *self) {
Local::readInstalledStickers();
Local::readFeaturedStickers();
Local::readRecentStickers();
Local::readFavedStickers();
Local::readSavedGifs();
_history->start();
@ -5308,7 +5305,7 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
}
if (result.size() != Global::StickerSetsOrder().size() || result.size() != order.size()) {
Global::SetLastStickersUpdate(0);
App::main()->updateStickers();
AuthSession::Current().api().updateStickers();
} else {
Global::SetStickerSetsOrder(result);
Local::writeInstalledStickers();
@ -5319,12 +5316,17 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
case mtpc_updateStickerSets: {
Global::SetLastStickersUpdate(0);
App::main()->updateStickers();
AuthSession::Current().api().updateStickers();
} break;
case mtpc_updateRecentStickers: {
Global::SetLastStickersUpdate(0);
App::main()->updateStickers();
Global::SetLastRecentStickersUpdate(0);
AuthSession::Current().api().updateStickers();
} break;
case mtpc_updateFavedStickers: {
Global::SetLastFavedStickersUpdate(0);
AuthSession::Current().api().updateStickers();
} break;
case mtpc_updateReadFeaturedStickers: {
@ -5332,13 +5334,13 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
// Here we don't know what featured sticker sets were read, so we
// request all of them once again.
Global::SetLastFeaturedStickersUpdate(0);
App::main()->updateStickers();
AuthSession::Current().api().updateStickers();
} break;
////// Cloud saved GIFs
case mtpc_updateSavedGifs: {
cSetLastSavedGifsUpdate(0);
App::main()->updateStickers();
AuthSession::Current().api().updateStickers();
} break;
////// Cloud drafts

View File

@ -355,8 +355,6 @@ public:
void gameUpdated(GameData *game);
void updateMutedIn(int32 seconds);
void updateStickers();
void choosePeer(PeerId peerId, MsgId showAtMsgId); // does offerPeer or showPeerHistory
void clearBotStartToken(PeerData *peer);

View File

@ -605,6 +605,7 @@ void Instance::Private::configLoadDone(const MTPConfig &result) {
Global::SetSavedGifsLimit(data.vsaved_gifs_limit.v);
Global::SetEditTimeLimit(data.vedit_time_limit.v);
Global::SetStickersRecentLimit(data.vstickers_recent_limit.v);
Global::SetStickersFavedLimit(data.vstickers_faved_limit.v);
Global::SetPinnedDialogsCountMax(data.vpinned_dialogs_count_max.v);
Messenger::Instance().setInternalLinkDomain(qs(data.vme_url_prefix));
Global::SetCallReceiveTimeoutMs(data.vcall_receive_timeout_ms.v);

View File

@ -504,6 +504,7 @@ enum { // Local Storage Keys
lskSavedGifs = 0x0f, // no data
lskStickersKeys = 0x10, // no data
lskTrustedBots = 0x11, // no data
lskFavedStickers = 0x12, // no data
};
enum {
@ -577,6 +578,7 @@ enum {
dbiAuthSessionData = 0x4d,
dbiLangPackKey = 0x4e,
dbiConnectionType = 0x4f,
dbiStickersFavedLimit = 0x50,
dbiEncryptedWithSalt = 333,
dbiEncrypted = 444,
@ -611,7 +613,7 @@ TrustedBots _trustedBots;
bool _trustedBotsRead = false;
FileKey _recentStickersKeyOld = 0;
FileKey _installedStickersKey = 0, _featuredStickersKey = 0, _recentStickersKey = 0, _archivedStickersKey = 0;
FileKey _installedStickersKey = 0, _featuredStickersKey = 0, _recentStickersKey = 0, _favedStickersKey = 0, _archivedStickersKey = 0;
FileKey _savedGifsKey = 0;
FileKey _backgroundKey = 0;
@ -920,6 +922,14 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting
Global::SetStickersRecentLimit(limit);
} break;
case dbiStickersFavedLimit: {
qint32 limit;
stream >> limit;
if (!_checkStreamStatus(stream)) return false;
Global::SetStickersFavedLimit(limit);
} break;
case dbiMegagroupSizeMax: {
qint32 maxSize;
stream >> maxSize;
@ -1969,7 +1979,7 @@ ReadMapState _readMap(const QByteArray &pass) {
qint64 storageImagesSize = 0, storageStickersSize = 0, storageAudiosSize = 0;
quint64 locationsKey = 0, reportSpamStatusesKey = 0, trustedBotsKey = 0;
quint64 recentStickersKeyOld = 0;
quint64 installedStickersKey = 0, featuredStickersKey = 0, recentStickersKey = 0, archivedStickersKey = 0;
quint64 installedStickersKey = 0, featuredStickersKey = 0, recentStickersKey = 0, favedStickersKey = 0, archivedStickersKey = 0;
quint64 savedGifsKey = 0;
quint64 backgroundKey = 0, userSettingsKey = 0, recentHashtagsAndBotsKey = 0, savedPeersKey = 0;
while (!map.stream.atEnd()) {
@ -2060,6 +2070,9 @@ ReadMapState _readMap(const QByteArray &pass) {
case lskStickersKeys: {
map.stream >> installedStickersKey >> featuredStickersKey >> recentStickersKey >> archivedStickersKey;
} break;
case lskFavedStickers: {
map.stream >> favedStickersKey;
} break;
case lskSavedGifsOld: {
quint64 key;
map.stream >> key;
@ -2097,6 +2110,7 @@ ReadMapState _readMap(const QByteArray &pass) {
_installedStickersKey = installedStickersKey;
_featuredStickersKey = featuredStickersKey;
_recentStickersKey = recentStickersKey;
_favedStickersKey = favedStickersKey;
_archivedStickersKey = archivedStickersKey;
_savedGifsKey = savedGifsKey;
_savedPeersKey = savedPeersKey;
@ -2175,6 +2189,7 @@ void _writeMap(WriteMapWhen when) {
if (_installedStickersKey || _featuredStickersKey || _recentStickersKey || _archivedStickersKey) {
mapSize += sizeof(quint32) + 4 * sizeof(quint64);
}
if (_favedStickersKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_savedGifsKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_savedPeersKey) mapSize += sizeof(quint32) + sizeof(quint64);
if (_backgroundKey) mapSize += sizeof(quint32) + sizeof(quint64);
@ -2227,6 +2242,9 @@ void _writeMap(WriteMapWhen when) {
mapData.stream << quint32(lskStickersKeys);
mapData.stream << quint64(_installedStickersKey) << quint64(_featuredStickersKey) << quint64(_recentStickersKey) << quint64(_archivedStickersKey);
}
if (_favedStickersKey) {
mapData.stream << quint32(lskFavedStickers) << quint64(_favedStickersKey);
}
if (_savedGifsKey) {
mapData.stream << quint32(lskSavedGifs) << quint64(_savedGifsKey);
}
@ -2354,13 +2372,14 @@ void writeSettings() {
if (_langPackKey) {
size += sizeof(quint32) + sizeof(quint64);
}
size += sizeof(quint32) + sizeof(qint32) * 7;
size += sizeof(quint32) + sizeof(qint32) * 8;
EncryptedDescriptor data(size);
data.stream << quint32(dbiChatSizeMax) << qint32(Global::ChatSizeMax());
data.stream << quint32(dbiMegagroupSizeMax) << qint32(Global::MegagroupSizeMax());
data.stream << quint32(dbiSavedGifsLimit) << qint32(Global::SavedGifsLimit());
data.stream << quint32(dbiStickersRecentLimit) << qint32(Global::StickersRecentLimit());
data.stream << quint32(dbiStickersFavedLimit) << qint32(Global::StickersFavedLimit());
data.stream << quint32(dbiAutoStart) << qint32(cAutoStart());
data.stream << quint32(dbiStartMinimized) << qint32(cStartMinimized());
data.stream << quint32(dbiSendToMenu) << qint32(cSendToMenu());
@ -2419,7 +2438,7 @@ void reset() {
_storageWebFilesSize = 0;
_locationsKey = _reportSpamStatusesKey = _trustedBotsKey = 0;
_recentStickersKeyOld = 0;
_installedStickersKey = _featuredStickersKey = _recentStickersKey = _archivedStickersKey = 0;
_installedStickersKey = _featuredStickersKey = _recentStickersKey = _favedStickersKey = _archivedStickersKey = 0;
_savedGifsKey = 0;
_backgroundKey = _userSettingsKey = _recentHashtagsAndBotsKey = _savedPeersKey = 0;
_oldMapVersion = _oldSettingsVersion = 0;
@ -3334,6 +3353,9 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr,
} else if (setId == Stickers::CloudRecentSetId) {
setTitle = lang(lng_recent_stickers);
setFlags |= qFlags(MTPDstickerSet_ClientFlag::f_special);
} else if (setId == Stickers::FavedSetId) {
setTitle = lang(lng_faved_stickers);
setFlags |= qFlags(MTPDstickerSet_ClientFlag::f_special);
} else if (setId) {
if (readingInstalled && outOrder && stickers.version < 9061) {
outOrder->push_back(setId);
@ -3431,7 +3453,7 @@ void writeInstalledStickers() {
if (!Global::started()) return;
_writeStickerSets(_installedStickersKey, [](const Stickers::Set &set) {
if (set.id == Stickers::CloudRecentSetId) { // separate file for recent
if (set.id == Stickers::CloudRecentSetId || set.id == Stickers::FavedSetId) { // separate files for them
return StickerSetCheckResult::Skip;
} else if (set.flags & MTPDstickerSet_ClientFlag::f_special) {
if (set.stickers.isEmpty()) { // all other special are "installed"
@ -3452,7 +3474,7 @@ void writeFeaturedStickers() {
if (!Global::started()) return;
_writeStickerSets(_featuredStickersKey, [](const Stickers::Set &set) {
if (set.id == Stickers::CloudRecentSetId) { // separate file for recent
if (set.id == Stickers::CloudRecentSetId || set.id == Stickers::FavedSetId) { // separate files for them
return StickerSetCheckResult::Skip;
} else if (set.flags & MTPDstickerSet_ClientFlag::f_special) {
return StickerSetCheckResult::Skip;
@ -3478,6 +3500,17 @@ void writeRecentStickers() {
}, Stickers::Order());
}
void writeFavedStickers() {
if (!Global::started()) return;
_writeStickerSets(_favedStickersKey, [](const Stickers::Set &set) {
if (set.id != Stickers::FavedSetId || set.stickers.isEmpty()) {
return StickerSetCheckResult::Skip;
}
return StickerSetCheckResult::Write;
}, Stickers::Order());
}
void writeArchivedStickers() {
if (!Global::started()) return;
@ -3595,6 +3628,10 @@ void readRecentStickers() {
_readStickerSets(_recentStickersKey);
}
void readFavedStickers() {
_readStickerSets(_favedStickersKey);
}
void readArchivedStickers() {
static bool archivedStickersRead = false;
if (!archivedStickersRead) {
@ -3603,6 +3640,25 @@ void readArchivedStickers() {
}
}
int32 countDocumentVectorHash(const QVector<DocumentData*> vector) {
uint32 acc = 0;
for_const (auto doc, vector) {
auto docId = doc->id;
acc = (acc * 20261) + uint32(docId >> 32);
acc = (acc * 20261) + uint32(docId & 0xFFFFFFFF);
}
return int32(acc & 0x7FFFFFFF);
}
int32 countSpecialStickerSetHash(uint64 setId) {
auto &sets = Global::StickerSets();
auto it = sets.constFind(setId);
if (it != sets.cend()) {
return countDocumentVectorHash(it->stickers);
}
return 0;
}
int32 countStickersHash(bool checkOutdatedInfo) {
uint32 acc = 0;
bool foundOutdated = false;
@ -3623,17 +3679,11 @@ int32 countStickersHash(bool checkOutdatedInfo) {
}
int32 countRecentStickersHash() {
uint32 acc = 0;
auto &sets = Global::StickerSets();
auto it = sets.constFind(Stickers::CloudRecentSetId);
if (it != sets.cend()) {
for_const (auto doc, it->stickers) {
auto docId = doc->id;
acc = (acc * 20261) + uint32(docId >> 32);
acc = (acc * 20261) + uint32(docId & 0xFFFFFFFF);
}
}
return int32(acc & 0x7FFFFFFF);
return countSpecialStickerSetHash(Stickers::CloudRecentSetId);
}
int32 countFavedStickersHash() {
return countSpecialStickerSetHash(Stickers::FavedSetId);
}
int32 countFeaturedStickersHash() {
@ -3653,20 +3703,13 @@ int32 countFeaturedStickersHash() {
}
int32 countSavedGifsHash() {
uint32 acc = 0;
auto &saved = cSavedGifs();
for_const (auto doc, saved) {
auto docId = doc->id;
acc = (acc * 20261) + uint32(docId >> 32);
acc = (acc * 20261) + uint32(docId & 0xFFFFFFFF);
}
return int32(acc & 0x7FFFFFFF);
return countDocumentVectorHash(cSavedGifs());
}
void writeSavedGifs() {
if (!_working()) return;
const SavedGifs &saved(cSavedGifs());
auto &saved = cSavedGifs();
if (saved.isEmpty()) {
if (_savedGifsKey) {
clearKey(_savedGifsKey);

View File

@ -141,13 +141,16 @@ void cancelTask(TaskId id);
void writeInstalledStickers();
void writeFeaturedStickers();
void writeRecentStickers();
void writeFavedStickers();
void writeArchivedStickers();
void readInstalledStickers();
void readFeaturedStickers();
void readRecentStickers();
void readFavedStickers();
void readArchivedStickers();
int32 countStickersHash(bool checkOutdatedInfo = false);
int32 countRecentStickersHash();
int32 countFavedStickersHash();
int32 countFeaturedStickersHash();
void writeSavedGifs();

View File

@ -92,7 +92,7 @@ DocumentData *Document::readFromStreamHelper(int streamAppVersion, QDataStream &
if (typeOfSet == StickerSetTypeEmpty) {
attributes.push_back(MTP_documentAttributeSticker(MTP_flags(0), MTP_string(alt), MTP_inputStickerSetEmpty(), MTPMaskCoords()));
} else if (info) {
if (info->setId == Stickers::DefaultSetId || info->setId == Stickers::CloudRecentSetId || info->setId == Stickers::CustomSetId) {
if (info->setId == Stickers::DefaultSetId || info->setId == Stickers::CloudRecentSetId || info->setId == Stickers::FavedSetId || info->setId == Stickers::CustomSetId) {
typeOfSet = StickerSetTypeEmpty;
}