From 667eb288d7742ddca6810976e0e2515d2ffb39ef Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 2 Aug 2017 18:07:28 +0300 Subject: [PATCH] Add faved stickers set loading and saving. Also move stickers loading methods to ApiWrap. --- Telegram/Resources/langs/lang.strings | 1 + Telegram/SourceFiles/apiwrap.cpp | 374 +++++++++++++++++- Telegram/SourceFiles/apiwrap.h | 14 + Telegram/SourceFiles/app.cpp | 4 +- .../SourceFiles/boxes/sticker_set_box.cpp | 2 +- Telegram/SourceFiles/boxes/stickers_box.cpp | 2 +- .../chat_helpers/stickers_list_widget.cpp | 11 + .../chat_helpers/stickers_list_widget.h | 4 +- .../chat_helpers/tabbed_selector.cpp | 3 +- .../chat_helpers/tabbed_selector.h | 2 - Telegram/SourceFiles/facades.cpp | 4 + Telegram/SourceFiles/facades.h | 15 +- .../SourceFiles/history/history_widget.cpp | 354 ----------------- Telegram/SourceFiles/history/history_widget.h | 18 - Telegram/SourceFiles/mainwidget.cpp | 22 +- Telegram/SourceFiles/mainwidget.h | 2 - Telegram/SourceFiles/mtproto/mtp_instance.cpp | 1 + Telegram/SourceFiles/storage/localstorage.cpp | 95 +++-- Telegram/SourceFiles/storage/localstorage.h | 3 + .../storage/serialize_document.cpp | 2 +- 20 files changed, 507 insertions(+), 426 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 28a6afdacc..ade7663549 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -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"; diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index dd8d9bf2c9..e0ae6bd518 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -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 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::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 &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 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 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::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: { diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index ed347e6db6..470444d8e4 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -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 &items, MTPint hash); + gsl::not_null _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 _privacySaveRequests; mtpRequestId _contactsStatusesRequestId = 0; diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp index 4bfe73efff..863aaae718 100644 --- a/Telegram/SourceFiles/app.cpp +++ b/Telegram/SourceFiles/app.cpp @@ -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) { diff --git a/Telegram/SourceFiles/boxes/sticker_set_box.cpp b/Telegram/SourceFiles/boxes/sticker_set_box.cpp index fd0972f322..c74883b981 100644 --- a/Telegram/SourceFiles/boxes/sticker_set_box.cpp +++ b/Telegram/SourceFiles/boxes/sticker_set_box.cpp @@ -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(); }); diff --git a/Telegram/SourceFiles/boxes/stickers_box.cpp b/Telegram/SourceFiles/boxes/stickers_box.cpp index 61610a9099..b6fd8b5d6b 100644 --- a/Telegram/SourceFiles/boxes/stickers_box.cpp +++ b/Telegram/SourceFiles/boxes/stickers_box.cpp @@ -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))); diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp index 29788b088a..6b4744b45e 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp @@ -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 &icons) { icons.clear(); icons.reserve(_mySets.size() + 1); diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h index 239305d2e5..b98aa46566 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h @@ -49,7 +49,6 @@ public: void showStickerSet(uint64 setId); void refreshStickers(); - void refreshRecentStickers(bool resize = true); void fillIcons(QList &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); diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp index 5d3f6274f7..17587b5570 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp @@ -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(); diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h index 48d9f2538a..b6815fcc16 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.h +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.h @@ -105,8 +105,6 @@ signals: void photoSelected(PhotoData *photo); void inlineResultSelected(InlineBots::Result *result, UserData *bot); - void updateStickers(); - void cancelled(); void slideFinished(); void checkForHide(); diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index e72de6e3fd..85d613c6ef 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -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 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, FeaturedStickerSetsUnreadCountChanged); diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index e7113572cd..4f154cfd94 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -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, FeaturedStickerSetsUnreadCountChanged); diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 2eb7798308..b1ef3d3e53 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -172,7 +172,6 @@ test_ptr 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 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 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::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 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 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::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; diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 77f82901bd..6cefc581f8 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -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, diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 80fb66160a..9d847eab24 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -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 diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index a6c5786e3a..e585926a4f 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -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); diff --git a/Telegram/SourceFiles/mtproto/mtp_instance.cpp b/Telegram/SourceFiles/mtproto/mtp_instance.cpp index 894e7ba190..e71241e571 100644 --- a/Telegram/SourceFiles/mtproto/mtp_instance.cpp +++ b/Telegram/SourceFiles/mtproto/mtp_instance.cpp @@ -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); diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp index 07c16f89e7..cadc48763b 100644 --- a/Telegram/SourceFiles/storage/localstorage.cpp +++ b/Telegram/SourceFiles/storage/localstorage.cpp @@ -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 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); diff --git a/Telegram/SourceFiles/storage/localstorage.h b/Telegram/SourceFiles/storage/localstorage.h index e00ea2c08c..5bbe576999 100644 --- a/Telegram/SourceFiles/storage/localstorage.h +++ b/Telegram/SourceFiles/storage/localstorage.h @@ -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(); diff --git a/Telegram/SourceFiles/storage/serialize_document.cpp b/Telegram/SourceFiles/storage/serialize_document.cpp index 13af9a7de4..9e7cca44c7 100644 --- a/Telegram/SourceFiles/storage/serialize_document.cpp +++ b/Telegram/SourceFiles/storage/serialize_document.cpp @@ -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; }