From fc174f742a28bcd2a3d1a71fd8d494a673f72578 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 8 Jun 2020 21:24:36 +0400 Subject: [PATCH] Move stickers code to Data::Stickers class. --- Telegram/CMakeLists.txt | 10 +- Telegram/SourceFiles/api/api_sending.cpp | 3 +- Telegram/SourceFiles/apiwrap.cpp | 130 +++-- Telegram/SourceFiles/apiwrap.h | 8 +- .../SourceFiles/boxes/sticker_set_box.cpp | 43 +- Telegram/SourceFiles/boxes/sticker_set_box.h | 2 +- Telegram/SourceFiles/boxes/stickers_box.cpp | 399 +++++++++++--- Telegram/SourceFiles/boxes/stickers_box.h | 235 +------- .../chat_helpers/field_autocomplete.cpp | 11 +- .../chat_helpers/field_autocomplete.h | 2 +- .../chat_helpers/gifs_list_widget.cpp | 14 +- Telegram/SourceFiles/chat_helpers/stickers.h | 125 ----- .../chat_helpers/stickers_list_widget.cpp | 192 +++---- .../chat_helpers/stickers_list_widget.h | 13 +- .../chat_helpers/stickers_lottie.cpp | 191 +++++++ .../chat_helpers/stickers_lottie.h | 74 +++ .../chat_helpers/tabbed_selector.cpp | 4 +- Telegram/SourceFiles/data/data_document.cpp | 10 +- Telegram/SourceFiles/data/data_session.cpp | 82 +-- Telegram/SourceFiles/data/data_session.h | 118 +--- .../stickers/data_stickers.cpp} | 506 +++++++----------- .../SourceFiles/data/stickers/data_stickers.h | 212 ++++++++ .../stickers/data_stickers_set.cpp} | 44 +- .../stickers/data_stickers_set.h} | 44 +- .../dialogs/dialogs_inner_widget.cpp | 2 +- Telegram/SourceFiles/history/history.cpp | 3 +- .../history/history_inner_widget.cpp | 6 +- .../SourceFiles/history/history_widget.cpp | 4 +- .../view/history_view_context_menu.cpp | 4 +- .../view/media/history_view_sticker.cpp | 5 +- .../inline_bot_layout_internal.cpp | 21 +- Telegram/SourceFiles/mainwidget.cpp | 55 +- .../SourceFiles/platform/mac/mac_touchbar.mm | 18 +- Telegram/SourceFiles/storage/localstorage.cpp | 147 ++--- .../storage/serialize_document.cpp | 10 +- .../SourceFiles/support/support_helper.cpp | 8 +- Telegram/SourceFiles/support/support_helper.h | 4 +- Telegram/SourceFiles/ui/image/image.cpp | 1 - .../window/window_media_preview.cpp | 5 +- 39 files changed, 1461 insertions(+), 1304 deletions(-) delete mode 100644 Telegram/SourceFiles/chat_helpers/stickers.h create mode 100644 Telegram/SourceFiles/chat_helpers/stickers_lottie.cpp create mode 100644 Telegram/SourceFiles/chat_helpers/stickers_lottie.h rename Telegram/SourceFiles/{chat_helpers/stickers.cpp => data/stickers/data_stickers.cpp} (71%) create mode 100644 Telegram/SourceFiles/data/stickers/data_stickers.h rename Telegram/SourceFiles/{chat_helpers/stickers_set.cpp => data/stickers/data_stickers_set.cpp} (70%) rename Telegram/SourceFiles/{chat_helpers/stickers_set.h => data/stickers/data_stickers_set.h} (67%) diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 9dfcd6155..d3c8186b0 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -293,16 +293,14 @@ PRIVATE chat_helpers/message_field.h chat_helpers/spellchecker_common.cpp chat_helpers/spellchecker_common.h - chat_helpers/stickers.cpp - chat_helpers/stickers.h chat_helpers/stickers_emoji_pack.cpp chat_helpers/stickers_emoji_pack.h chat_helpers/stickers_dice_pack.cpp chat_helpers/stickers_dice_pack.h chat_helpers/stickers_list_widget.cpp chat_helpers/stickers_list_widget.h - chat_helpers/stickers_set.cpp - chat_helpers/stickers_set.h + chat_helpers/stickers_lottie.cpp + chat_helpers/stickers_lottie.h chat_helpers/tabbed_panel.cpp chat_helpers/tabbed_panel.h chat_helpers/tabbed_section.cpp @@ -344,6 +342,10 @@ PRIVATE core/utils.cpp core/utils.h core/version.h + data/stickers/data_stickers_set.cpp + data/stickers/data_stickers_set.h + data/stickers/data_stickers.cpp + data/stickers/data_stickers.h data/data_abstract_structure.cpp data/data_abstract_structure.h data/data_auto_download.cpp diff --git a/Telegram/SourceFiles/api/api_sending.cpp b/Telegram/SourceFiles/api/api_sending.cpp index b0b8b4cc9..97ff21621 100644 --- a/Telegram/SourceFiles/api/api_sending.cpp +++ b/Telegram/SourceFiles/api/api_sending.cpp @@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" #include "data/data_file_origin.h" #include "data/data_histories.h" +#include "data/stickers/data_stickers.h" #include "history/history.h" #include "history/history_message.h" // NewMessageFlags. #include "chat_helpers/message_field.h" // ConvertTextTagsToEntities. @@ -192,7 +193,7 @@ void SendExistingDocument( if (document->sticker()) { if (const auto main = App::main()) { main->incrementSticker(document); - document->owner().notifyRecentStickersUpdated(); + document->owner().stickers().notifyRecentUpdated(); } } } diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp index d4086c9e0..e3866dc75 100644 --- a/Telegram/SourceFiles/apiwrap.cpp +++ b/Telegram/SourceFiles/apiwrap.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "api/api_text_entities.h" #include "api/api_self_destruct.h" #include "api/api_sensitive_content.h" +#include "data/stickers/data_stickers.h" #include "data/data_drafts.h" #include "data/data_photo.h" #include "data/data_web_page.h" @@ -28,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_cloud_themes.h" #include "data/data_chat_filters.h" #include "data/data_histories.h" +#include "data/stickers/data_stickers.h" #include "dialogs/dialogs_key.h" #include "core/core_cloud_password.h" #include "core/application.h" @@ -55,7 +57,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/themes/window_theme.h" #include "inline_bots/inline_bot_result.h" #include "chat_helpers/message_field.h" -#include "chat_helpers/stickers.h" #include "ui/text_options.h" #include "ui/emoji_config.h" #include "support/support_helper.h" @@ -1852,8 +1853,8 @@ void ApiWrap::requestStickerSets() { } void ApiWrap::saveStickerSets( - const Stickers::Order &localOrder, - const Stickers::Order &localRemoved) { + const Data::StickersSetsOrder &localOrder, + const Data::StickersSetsOrder &localRemoved) { for (auto requestId : base::take(_stickerSetDisenableRequests)) { request(requestId).cancel(); } @@ -1861,16 +1862,16 @@ void ApiWrap::saveStickerSets( request(base::take(_stickersClearRecentRequestId)).cancel(); auto writeInstalled = true, writeRecent = false, writeCloudRecent = false, writeFaved = false, writeArchived = false; - auto &recent = Stickers::GetRecentPack(); - auto &sets = _session->data().stickerSetsRef(); + auto &recent = _session->data().stickers().getRecentPack(); + auto &sets = _session->data().stickers().setsRef(); _stickersOrder = localOrder; for (const auto removedSetId : localRemoved) { - if (removedSetId == Stickers::CloudRecentSetId) { - if (sets.remove(Stickers::CloudRecentSetId) != 0) { + if (removedSetId == Data::Stickers::CloudRecentSetId) { + if (sets.remove(Data::Stickers::CloudRecentSetId) != 0) { writeCloudRecent = true; } - if (sets.remove(Stickers::CustomSetId)) { + if (sets.remove(Data::Stickers::CustomSetId)) { writeInstalled = true; } if (!recent.isEmpty()) { @@ -1910,8 +1911,8 @@ void ApiWrap::saveStickerSets( _stickerSetDisenableRequests.insert(requestId); - int removeIndex = _session->data().stickerSetsOrder().indexOf(set->id); - if (removeIndex >= 0) _session->data().stickerSetsOrderRef().removeAt(removeIndex); + int removeIndex = _session->data().stickers().setsOrder().indexOf(set->id); + if (removeIndex >= 0) _session->data().stickers().setsOrderRef().removeAt(removeIndex); if (!(set->flags & MTPDstickerSet_ClientFlag::f_featured) && !(set->flags & MTPDstickerSet_ClientFlag::f_special)) { sets.erase(it); @@ -1933,7 +1934,7 @@ void ApiWrap::saveStickerSets( } } - auto &order = _session->data().stickerSetsOrderRef(); + auto &order = _session->data().stickers().setsOrderRef(); order.clear(); for (const auto setId : std::as_const(_stickersOrder)) { auto it = sets.find(setId); @@ -1984,7 +1985,7 @@ void ApiWrap::saveStickerSets( if (writeArchived) Local::writeArchivedStickers(); if (writeCloudRecent) Local::writeRecentStickers(); if (writeFaved) Local::writeFavedStickers(); - _session->data().notifyStickersUpdated(); + _session->data().stickers().notifyUpdated(); if (_stickerSetDisenableRequests.empty()) { stickersSaveOrder(); @@ -2567,7 +2568,7 @@ void ApiWrap::applyNotifySettings( void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result) { _stickerSetRequests.remove(setId); - Stickers::FeedSetFull(result); + _session->data().stickers().feedSetFull(result); } void ApiWrap::requestWebPageDelayed(WebPageData *page) { @@ -2921,13 +2922,13 @@ void ApiWrap::refreshFileReference( }, [&](Data::FileOriginPeerPhoto data) { fail(); }, [&](Data::FileOriginStickerSet data) { - if (data.setId == Stickers::CloudRecentSetId - || data.setId == Stickers::RecentSetId) { + if (data.setId == Data::Stickers::CloudRecentSetId + || data.setId == Data::Stickers::RecentSetId) { request(MTPmessages_GetRecentStickers( MTP_flags(0), MTP_int(0)), [] { crl::on_main([] { Local::writeRecentStickers(); }); }); - } else if (data.setId == Stickers::FavedSetId) { + } else if (data.setId == Data::Stickers::FavedSetId) { request(MTPmessages_GetFavedStickers(MTP_int(0)), [] { crl::on_main([] { Local::writeFavedStickers(); }); }); } else { @@ -2979,21 +2980,25 @@ void ApiWrap::gotWebPages(ChannelData *channel, const MTPmessages_Messages &resu } void ApiWrap::stickersSaveOrder() { - if (_stickersOrder.size() > 1) { - QVector mtpOrder; - mtpOrder.reserve(_stickersOrder.size()); - for_const (auto setId, _stickersOrder) { - mtpOrder.push_back(MTP_long(setId)); - } - - _stickersReorderRequestId = request(MTPmessages_ReorderStickerSets(MTP_flags(0), MTP_vector(mtpOrder))).done([this](const MTPBool &result) { - _stickersReorderRequestId = 0; - }).fail([this](const RPCError &error) { - _stickersReorderRequestId = 0; - _session->data().setLastStickersUpdate(0); - updateStickers(); - }).send(); + if (_stickersOrder.size() < 2) { + return; } + QVector mtpOrder; + mtpOrder.reserve(_stickersOrder.size()); + for (const auto setId : std::as_const(_stickersOrder)) { + mtpOrder.push_back(MTP_long(setId)); + } + + _stickersReorderRequestId = request(MTPmessages_ReorderStickerSets( + MTP_flags(0), + MTP_vector(mtpOrder) + )).done([=](const MTPBool &result) { + _stickersReorderRequestId = 0; + }).fail([=](const RPCError &error) { + _stickersReorderRequestId = 0; + _session->data().stickers().setLastUpdate(0); + updateStickers(); + }).send(); } void ApiWrap::updateStickers() { @@ -3014,7 +3019,7 @@ void ApiWrap::setGroupStickerSet(not_null megagroup, const MTPInpu megagroup->mgInfo->stickerSet = set; request(MTPchannels_SetStickers(megagroup->inputChannel, set)).send(); - _session->data().notifyStickersUpdated(); + _session->data().stickers().notifyUpdated(); } std::vector> *ApiWrap::stickersByEmoji( @@ -3054,7 +3059,7 @@ std::vector> *ApiWrap::stickersByEmoji( } entry.hash = data.vhash().v; entry.received = crl::now(); - _session->data().notifyStickersUpdated(); + _session->data().stickers().notifyUpdated(); }).send(); } if (it == _stickersByEmoji.end()) { @@ -3081,7 +3086,7 @@ void ApiWrap::toggleFavedSticker( MTP_bool(!faved) )).done([=](const MTPBool &result) { if (mtpIsTrue(result)) { - Stickers::SetFaved(document, faved); + _session->data().stickers().setFaved(document, faved); } }).fail([=](const RPCError &error) { (*failHandler)(error, usedFileReference); @@ -3118,7 +3123,7 @@ void ApiWrap::toggleSavedGif( )).done([=](const MTPBool &result) { if (mtpIsTrue(result)) { if (saved) { - session().data().addSavedGif(document); + _session->data().stickers().addSavedGif(document); } } }).fail([=](const RPCError &error) { @@ -3140,19 +3145,21 @@ void ApiWrap::toggleSavedGif( } void ApiWrap::requestStickers(TimeId now) { - if (!_session->data().stickersUpdateNeeded(now) + if (!_session->data().stickers().updateNeeded(now) || _stickersUpdateRequest) { return; } auto onDone = [this](const MTPmessages_AllStickers &result) { - _session->data().setLastStickersUpdate(crl::now()); + _session->data().stickers().setLastUpdate(crl::now()); _stickersUpdateRequest = 0; switch (result.type()) { case mtpc_messages_allStickersNotModified: return; case mtpc_messages_allStickers: { auto &d = result.c_messages_allStickers(); - Stickers::SetsReceived(d.vsets().v, d.vhash().v); + _session->data().stickers().setsReceived( + d.vsets().v, + d.vhash().v); } return; default: Unexpected("Type in ApiWrap::stickersDone()"); } @@ -3166,7 +3173,7 @@ void ApiWrap::requestStickers(TimeId now) { } void ApiWrap::requestRecentStickers(TimeId now) { - if (!_session->data().recentStickersUpdateNeeded(now)) { + if (!_session->data().stickers().recentUpdateNeeded(now)) { return; } requestRecentStickersWithHash(Local::countRecentStickersHash()); @@ -3180,15 +3187,15 @@ void ApiWrap::requestRecentStickersWithHash(int32 hash) { MTP_flags(0), MTP_int(hash) )).done([=](const MTPmessages_RecentStickers &result) { - _session->data().setLastRecentStickersUpdate(crl::now()); + _session->data().stickers().setLastRecentUpdate(crl::now()); _recentStickersUpdateRequest = 0; switch (result.type()) { case mtpc_messages_recentStickersNotModified: return; case mtpc_messages_recentStickers: { auto &d = result.c_messages_recentStickers(); - Stickers::SpecialSetReceived( - Stickers::CloudRecentSetId, + _session->data().stickers().specialSetReceived( + Data::Stickers::CloudRecentSetId, tr::lng_recent_stickers(tr::now), d.vstickers().v, d.vhash().v, @@ -3198,7 +3205,7 @@ void ApiWrap::requestRecentStickersWithHash(int32 hash) { default: Unexpected("Type in ApiWrap::recentStickersDone()"); } }).fail([=](const RPCError &error) { - _session->data().setLastRecentStickersUpdate(crl::now()); + _session->data().stickers().setLastRecentUpdate(crl::now()); _recentStickersUpdateRequest = 0; LOG(("App Fail: Failed to get recent stickers!")); @@ -3206,22 +3213,22 @@ void ApiWrap::requestRecentStickersWithHash(int32 hash) { } void ApiWrap::requestFavedStickers(TimeId now) { - if (!_session->data().favedStickersUpdateNeeded(now) + if (!_session->data().stickers().favedUpdateNeeded(now) || _favedStickersUpdateRequest) { return; } _favedStickersUpdateRequest = request(MTPmessages_GetFavedStickers( MTP_int(Local::countFavedStickersHash()) )).done([=](const MTPmessages_FavedStickers &result) { - _session->data().setLastFavedStickersUpdate(crl::now()); + _session->data().stickers().setLastFavedUpdate(crl::now()); _favedStickersUpdateRequest = 0; switch (result.type()) { case mtpc_messages_favedStickersNotModified: return; case mtpc_messages_favedStickers: { auto &d = result.c_messages_favedStickers(); - Stickers::SpecialSetReceived( - Stickers::FavedSetId, + _session->data().stickers().specialSetReceived( + Data::Stickers::FavedSetId, Lang::Hard::FavedSetTitle(), d.vstickers().v, d.vhash().v, @@ -3230,7 +3237,7 @@ void ApiWrap::requestFavedStickers(TimeId now) { default: Unexpected("Type in ApiWrap::favedStickersDone()"); } }).fail([=](const RPCError &error) { - _session->data().setLastFavedStickersUpdate(crl::now()); + _session->data().stickers().setLastFavedUpdate(crl::now()); _favedStickersUpdateRequest = 0; LOG(("App Fail: Failed to get faved stickers!")); @@ -3238,26 +3245,29 @@ void ApiWrap::requestFavedStickers(TimeId now) { } void ApiWrap::requestFeaturedStickers(TimeId now) { - if (!_session->data().featuredStickersUpdateNeeded(now) + if (!_session->data().stickers().featuredUpdateNeeded(now) || _featuredStickersUpdateRequest) { return; } _featuredStickersUpdateRequest = request(MTPmessages_GetFeaturedStickers( MTP_int(Local::countFeaturedStickersHash()) )).done([=](const MTPmessages_FeaturedStickers &result) { - _session->data().setLastFeaturedStickersUpdate(crl::now()); + _session->data().stickers().setLastFeaturedUpdate(crl::now()); _featuredStickersUpdateRequest = 0; switch (result.type()) { case mtpc_messages_featuredStickersNotModified: return; case mtpc_messages_featuredStickers: { auto &d = result.c_messages_featuredStickers(); - Stickers::FeaturedSetsReceived(d.vsets().v, d.vunread().v, d.vhash().v); + _session->data().stickers().featuredSetsReceived( + d.vsets().v, + d.vunread().v, + d.vhash().v); } return; default: Unexpected("Type in ApiWrap::featuredStickersDone()"); } }).fail([=](const RPCError &error) { - _session->data().setLastFeaturedStickersUpdate(crl::now()); + _session->data().stickers().setLastFeaturedUpdate(crl::now()); _featuredStickersUpdateRequest = 0; LOG(("App Fail: Failed to get featured stickers!")); @@ -3265,26 +3275,28 @@ void ApiWrap::requestFeaturedStickers(TimeId now) { } void ApiWrap::requestSavedGifs(TimeId now) { - if (!_session->data().savedGifsUpdateNeeded(now) + if (!_session->data().stickers().savedGifsUpdateNeeded(now) || _savedGifsUpdateRequest) { return; } _savedGifsUpdateRequest = request(MTPmessages_GetSavedGifs( MTP_int(Local::countSavedGifsHash()) )).done([=](const MTPmessages_SavedGifs &result) { - _session->data().setLastSavedGifsUpdate(crl::now()); + _session->data().stickers().setLastSavedGifsUpdate(crl::now()); _savedGifsUpdateRequest = 0; switch (result.type()) { case mtpc_messages_savedGifsNotModified: return; case mtpc_messages_savedGifs: { auto &d = result.c_messages_savedGifs(); - Stickers::GifsReceived(d.vgifs().v, d.vhash().v); + _session->data().stickers().gifsReceived( + d.vgifs().v, + d.vhash().v); } return; default: Unexpected("Type in ApiWrap::savedGifsDone()"); } }).fail([=](const RPCError &error) { - _session->data().setLastSavedGifsUpdate(crl::now()); + _session->data().stickers().setLastSavedGifsUpdate(crl::now()); _savedGifsUpdateRequest = 0; LOG(("App Fail: Failed to get saved gifs!")); @@ -3299,8 +3311,8 @@ void ApiWrap::readFeaturedSetDelayed(uint64 setId) { } void ApiWrap::readFeaturedSets() { - const auto &sets = _session->data().stickerSets(); - auto count = _session->data().featuredStickerSetsUnreadCount(); + const auto &sets = _session->data().stickers().sets(); + auto count = _session->data().stickers().featuredSetsUnreadCount(); QVector wrappedIds; wrappedIds.reserve(_featuredSetsRead.size()); for (const auto setId : _featuredSetsRead) { @@ -3320,10 +3332,10 @@ void ApiWrap::readFeaturedSets() { MTP_vector(wrappedIds)); request(std::move(requestData)).done([=](const MTPBool &result) { Local::writeFeaturedStickers(); - _session->data().notifyStickersUpdated(); + _session->data().stickers().notifyUpdated(); }).send(); - _session->data().setFeaturedStickerSetsUnreadCount(count); + _session->data().stickers().setFeaturedSetsUnreadCount(count); } } diff --git a/Telegram/SourceFiles/apiwrap.h b/Telegram/SourceFiles/apiwrap.h index 948c93ddf..33631a9d7 100644 --- a/Telegram/SourceFiles/apiwrap.h +++ b/Telegram/SourceFiles/apiwrap.h @@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/flat_map.h" #include "base/flat_set.h" #include "mtproto/sender.h" -#include "chat_helpers/stickers_set.h" +#include "data/stickers/data_stickers_set.h" #include "data/data_messages.h" class TaskQueue; @@ -260,8 +260,8 @@ public: void scheduleStickerSetRequest(uint64 setId, uint64 access); void requestStickerSets(); void saveStickerSets( - const Stickers::Order &localOrder, - const Stickers::Order &localRemoved); + const Data::StickersSetsOrder &localOrder, + const Data::StickersSetsOrder &localRemoved); void updateStickers(); void requestRecentStickersForce(); void setGroupStickerSet( @@ -724,7 +724,7 @@ private: base::Timer _draftsSaveTimer; base::flat_set _stickerSetDisenableRequests; - Stickers::Order _stickersOrder; + Data::StickersSetsOrder _stickersOrder; mtpRequestId _stickersReorderRequestId = 0; mtpRequestId _stickersClearRecentRequestId = 0; diff --git a/Telegram/SourceFiles/boxes/sticker_set_box.cpp b/Telegram/SourceFiles/boxes/sticker_set_box.cpp index 4402afb0b..d4c560d9d 100644 --- a/Telegram/SourceFiles/boxes/sticker_set_box.cpp +++ b/Telegram/SourceFiles/boxes/sticker_set_box.cpp @@ -11,8 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_session.h" #include "data/data_file_origin.h" #include "data/data_document_media.h" +#include "data/stickers/data_stickers.h" #include "lang/lang_keys.h" -#include "chat_helpers/stickers.h" #include "boxes/confirm_box.h" #include "core/application.h" #include "mtproto/sender.h" @@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/emoji_config.h" #include "lottie/lottie_multi_player.h" #include "lottie/lottie_animation.h" +#include "chat_helpers/stickers_lottie.h" #include "window/window_session_controller.h" #include "base/unixtime.h" #include "main/main_session.h" @@ -43,6 +44,10 @@ namespace { constexpr auto kStickersPanelPerRow = 5; +using Data::StickersSet; +using Data::StickersPack; +using Data::StickersByEmojiMap; + } // namespace class StickerSetBox::Inner : public Ui::RpWidget, private base::Subscriber { @@ -106,8 +111,8 @@ private: MTP::Sender _api; std::vector _elements; std::unique_ptr _lottiePlayer; - Stickers::Pack _pack; - Stickers::ByEmojiMap _emoji; + StickersPack _pack; + StickersByEmojiMap _emoji; bool _loaded = false; uint64 _setId = 0; uint64 _setAccess = 0; @@ -159,7 +164,7 @@ void StickerSetBox::prepare() { _inner = setInnerWidget( object_ptr(this, _controller, _set), st::stickersScroll); - _controller->session().data().stickersUpdated( + _controller->session().data().stickers().updated( ) | rpl::start_with_next([=] { updateButtons(); }, lifetime()); @@ -278,7 +283,7 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) { const auto original = emoji->original(); auto &stickers = pack.vdocuments().v; - auto p = Stickers::Pack(); + auto p = StickersPack(); p.reserve(stickers.size()); for (auto j = 0, c = stickers.size(); j != c; ++j) { auto doc = _controller->session().data().document(stickers[j].v); @@ -291,7 +296,8 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) { }); } data.vset().match([&](const MTPDstickerSet &set) { - _setTitle = Stickers::GetSetTitle(set); + _setTitle = _controller->session().data().stickers().getSetTitle( + set); _setShortName = qs(set.vshort_name()); _setId = set.vid().v; _setAccess = set.vaccess_hash().v; @@ -307,7 +313,7 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) { } else { _setThumbnail = ImageWithLocation(); } - const auto &sets = _controller->session().data().stickerSets(); + const auto &sets = _controller->session().data().stickers().sets(); const auto it = sets.find(_setId); if (it != sets.cend()) { const auto set = it->second.get(); @@ -350,13 +356,13 @@ rpl::producer<> StickerSetBox::Inner::updateControls() const { void StickerSetBox::Inner::installDone( const MTPmessages_StickerSetInstallResult &result) { - auto &sets = _controller->session().data().stickerSetsRef(); + auto &sets = _controller->session().data().stickers().setsRef(); bool wasArchived = (_setFlags & MTPDstickerSet::Flag::f_archived); if (wasArchived) { - auto index = _controller->session().data().archivedStickerSetsOrderRef().indexOf(_setId); + auto index = _controller->session().data().stickers().archivedSetsOrderRef().indexOf(_setId); if (index >= 0) { - _controller->session().data().archivedStickerSetsOrderRef().removeAt(index); + _controller->session().data().stickers().archivedSetsOrderRef().removeAt(index); } } _setInstallDate = base::unixtime::now(); @@ -366,7 +372,7 @@ void StickerSetBox::Inner::installDone( if (it == sets.cend()) { it = sets.emplace( _setId, - std::make_unique( + std::make_unique( &_controller->session().data(), _setId, _setAccess, @@ -385,7 +391,7 @@ void StickerSetBox::Inner::installDone( set->stickers = _pack; set->emoji = _emoji; - auto &order = _controller->session().data().stickerSetsOrderRef(); + auto &order = _controller->session().data().stickers().setsOrderRef(); int insertAtIndex = 0, currentIndex = order.indexOf(_setId); if (currentIndex != insertAtIndex) { if (currentIndex > 0) { @@ -394,7 +400,7 @@ void StickerSetBox::Inner::installDone( order.insert(insertAtIndex, _setId); } - const auto customIt = sets.find(Stickers::CustomSetId); + const auto customIt = sets.find(Data::Stickers::CustomSetId); if (customIt != sets.cend()) { const auto custom = customIt->second.get(); for (const auto sticker : std::as_const(_pack)) { @@ -407,13 +413,14 @@ void StickerSetBox::Inner::installDone( } if (result.type() == mtpc_messages_stickerSetInstallResultArchive) { - Stickers::ApplyArchivedResult(result.c_messages_stickerSetInstallResultArchive()); + _controller->session().data().stickers().applyArchivedResult( + result.c_messages_stickerSetInstallResultArchive()); } else { if (wasArchived) { Local::writeArchivedStickers(); } Local::writeInstalledStickers(); - _controller->session().data().notifyStickersUpdated(); + _controller->session().data().stickers().notifyUpdated(); } _setInstalled.fire_copy(_setId); } @@ -610,10 +617,10 @@ void StickerSetBox::Inner::setupLottie(int index) { auto &element = _elements[index]; const auto document = element.document; - element.animated = Stickers::LottieAnimationFromDocument( + element.animated = ChatHelpers::LottieAnimationFromDocument( getLottiePlayer(), element.documentMedia.get(), - Stickers::LottieSize::StickerSet, + ChatHelpers::StickerLottieSize::StickerSet, boundingBoxSize() * cIntRetinaFactor()); } @@ -677,7 +684,7 @@ bool StickerSetBox::Inner::notInstalled() const { if (!_loaded) { return false; } - const auto &sets = _controller->session().data().stickerSets(); + const auto &sets = _controller->session().data().stickers().sets(); const auto it = sets.find(_setId); if ((it == sets.cend()) || !(it->second->flags & MTPDstickerSet::Flag::f_installed_date) diff --git a/Telegram/SourceFiles/boxes/sticker_set_box.h b/Telegram/SourceFiles/boxes/sticker_set_box.h index ae01ba020..a051febbd 100644 --- a/Telegram/SourceFiles/boxes/sticker_set_box.h +++ b/Telegram/SourceFiles/boxes/sticker_set_box.h @@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/abstract_box.h" #include "base/timer.h" -#include "chat_helpers/stickers.h" +#include "data/stickers/data_stickers.h" class ConfirmBox; diff --git a/Telegram/SourceFiles/boxes/stickers_box.cpp b/Telegram/SourceFiles/boxes/stickers_box.cpp index 8e21da0d1..871ea3106 100644 --- a/Telegram/SourceFiles/boxes/stickers_box.cpp +++ b/Telegram/SourceFiles/boxes/stickers_box.cpp @@ -12,17 +12,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_channel.h" #include "data/data_file_origin.h" #include "data/data_document_media.h" +#include "data/stickers/data_stickers.h" #include "core/application.h" #include "lang/lang_keys.h" #include "mainwidget.h" #include "mainwindow.h" -#include "chat_helpers/stickers.h" #include "boxes/confirm_box.h" #include "boxes/sticker_set_box.h" #include "apiwrap.h" #include "storage/localstorage.h" #include "dialogs/dialogs_layout.h" #include "lottie/lottie_single_player.h" +#include "chat_helpers/stickers_lottie.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" #include "ui/widgets/scroll_area.h" @@ -42,6 +43,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace { +using Data::StickersSet; +using Data::StickersSetsOrder; +using Data::StickersSetThumbnailView; + constexpr auto kArchivedLimitFirstRequest = 10; constexpr auto kArchivedLimitPerPage = 30; constexpr auto kHandleMegagroupSetAddressChangeTimeout = crl::time(1000); @@ -63,6 +68,227 @@ private: }; + +// This class is hold in header because it requires Qt preprocessing. +class StickersBox::Inner + : public Ui::RpWidget + , private base::Subscriber { +public: + using Section = StickersBox::Section; + + Inner( + QWidget *parent, + not_null session, + Section section); + Inner(QWidget *parent, not_null megagroup); + + base::Observable scrollToY; + void setInnerFocus(); + + void saveGroupSet(); + + void rebuild(); + void updateSize(int newWidth = 0); + void updateRows(); // refresh only pack cover stickers + bool appendSet(not_null set); + + StickersSetsOrder getOrder() const; + StickersSetsOrder getFullOrder() const; + StickersSetsOrder getRemovedSets() const; + + void setFullOrder(const StickersSetsOrder &order); + void setRemovedSets(const StickersSetsOrder &removed); + + void setInstallSetCallback(Fn callback) { + _installSetCallback = std::move(callback); + } + void setLoadMoreCallback(Fn callback) { + _loadMoreCallback = std::move(callback); + } + + void setMinHeight(int newWidth, int minHeight); + + int getVisibleTop() const { + return _visibleTop; + } + + [[nodiscard]] rpl::producer draggingScrollDelta() const { + return _draggingScrollDelta.events(); + } + + ~Inner(); + +protected: + void visibleTopBottomUpdated( + int visibleTop, + int visibleBottom) override; + + void paintEvent(QPaintEvent *e) override; + void resizeEvent(QResizeEvent *e) override; + void mousePressEvent(QMouseEvent *e) override; + void mouseMoveEvent(QMouseEvent *e) override; + void mouseReleaseEvent(QMouseEvent *e) override; + void leaveEventHook(QEvent *e) override; + void leaveToChildEvent(QEvent *e, QWidget *child) override; + +private: + struct Row { + Row( + not_null set, + DocumentData *sticker, + int32 count, + const QString &title, + int titleWidth, + bool installed, + bool official, + bool unread, + bool archived, + bool removed, + int32 pixw, + int32 pixh); + ~Row(); + + bool isRecentSet() const; + + const not_null set; + DocumentData *sticker = nullptr; + std::shared_ptr stickerMedia; + std::shared_ptr thumbnailMedia; + int32 count = 0; + QString title; + int titleWidth = 0; + bool installed = false; + bool official = false; + bool unread = false; + bool archived = false; + bool removed = false; + int32 pixw = 0; + int32 pixh = 0; + anim::value yadd; + std::unique_ptr ripple; + std::unique_ptr lottie; + }; + struct MegagroupSet { + inline bool operator==(const MegagroupSet &other) const { + return true; + } + inline bool operator!=(const MegagroupSet &other) const { + return false; + } + }; + using SelectedRow = base::optional_variant; + class AddressField : public Ui::UsernameInput { + public: + using UsernameInput::UsernameInput; + + protected: + void correctValue( + const QString &was, + int wasCursor, + QString &now, + int &nowCursor) override; + + }; + + template + StickersSetsOrder collectSets(Check check) const; + + void updateSelected(); + + void checkLoadMore(); + void updateScrollbarWidth(); + int getRowIndex(uint64 setId) const; + void setRowRemoved(int index, bool removed); + + void setSelected(SelectedRow selected); + void setActionDown(int newActionDown); + void setPressed(SelectedRow pressed); + void setup(); + QRect relativeButtonRect(bool removeButton) const; + void ensureRipple(const style::RippleAnimation &st, QImage mask, bool removeButton); + + bool shiftingAnimationCallback(crl::time now); + void paintRow(Painter &p, not_null row, int index); + void paintRowThumbnail(Painter &p, not_null row, int left); + void paintFakeButton(Painter &p, not_null row, int index); + void clear(); + void updateCursor(); + void setActionSel(int32 actionSel); + float64 aboveShadowOpacity() const; + void validateLottieAnimation(not_null row); + void updateRowThumbnail(not_null row); + + void readVisibleSets(); + + void updateControlsGeometry(); + void rebuildAppendSet(not_null set, int maxNameWidth); + void fillSetCover(not_null set, DocumentData **outSticker, int *outWidth, int *outHeight) const; + int fillSetCount(not_null set) const; + QString fillSetTitle(not_null set, int maxNameWidth, int *outTitleWidth) const; + void fillSetFlags(not_null set, bool *outInstalled, bool *outOfficial, bool *outUnread, bool *outArchived); + void rebuildMegagroupSet(); + void fixupMegagroupSetAddress(); + void handleMegagroupSetAddressChange(); + void setMegagroupSelectedSet(const MTPInputStickerSet &set); + + int countMaxNameWidth() const; + + const not_null _session; + MTP::Sender _api; + + Section _section; + + int32 _rowHeight; + + std::vector> _rows; + std::vector _shiftingStartTimes; + crl::time _aboveShadowFadeStart = 0; + anim::value _aboveShadowFadeOpacity; + Ui::Animations::Basic _shiftingAnimation; + + Fn _installSetCallback; + Fn _loadMoreCallback; + + int _visibleTop = 0; + int _visibleBottom = 0; + int _itemsTop = 0; + + int _actionSel = -1; + int _actionDown = -1; + + QString _addText; + int _addWidth = 0; + QString _undoText; + int _undoWidth = 0; + + int _buttonHeight = 0; + + QPoint _mouse; + bool _inDragArea = false; + SelectedRow _selected; + SelectedRow _pressed; + QPoint _dragStart; + int _started = -1; + int _dragging = -1; + int _above = -1; + rpl::event_stream _draggingScrollDelta; + + int _minHeight = 0; + + int _scrollbar = 0; + ChannelData *_megagroupSet = nullptr; + MTPInputStickerSet _megagroupSetInput = MTP_inputStickerSetEmpty(); + std::unique_ptr _megagroupSelectedSet; + object_ptr _megagroupSetField = { nullptr }; + object_ptr _megagroupSelectedShadow = { nullptr }; + object_ptr _megagroupSelectedRemove = { nullptr }; + object_ptr _megagroupDivider = { nullptr }; + object_ptr _megagroupSubTitle = { nullptr }; + base::Timer _megagroupSetAddressChangedTimer; + mtpRequestId _megagroupSetRequestId = 0; + +}; + StickersBox::CounterWidget::CounterWidget( QWidget *parent, rpl::producer count) @@ -120,6 +346,14 @@ void StickersBox::Tab::returnWidget(object_ptr widget) { Assert(_widget == _weak); } +StickersBox::Inner *StickersBox::Tab::widget() { + return _weak; +} + +int StickersBox::Tab::index() const { + return _index; +} + void StickersBox::Tab::saveScrollTop() { _scrollTop = widget()->getVisibleTop(); } @@ -130,7 +364,9 @@ StickersBox::StickersBox( Section section) : _session(session) , _tabs(this, st::stickersTabs) -, _unreadBadge(this, _session->data().featuredStickerSetsUnreadCountValue()) +, _unreadBadge( + this, + _session->data().stickers().featuredSetsUnreadCountValue()) , _section(section) , _installed(0, this, session, Section::Installed) , _featured(1, this, session, Section::Featured) @@ -143,7 +379,9 @@ StickersBox::StickersBox(QWidget*, not_null megagroup) , _section(Section::Installed) , _installed(0, this, megagroup) , _megagroupSet(megagroup) { - subscribe(_installed.widget()->scrollToY, [this](int y) { onScrollToY(y); }); + subscribe(_installed.widget()->scrollToY, [=](int y) { + onScrollToY(y); + }); } StickersBox::StickersBox( @@ -165,7 +403,7 @@ void StickersBox::showAttachedStickers() { }); }); - if (const auto set = Stickers::FeedSet(*setData)) { + if (const auto set = _session->data().stickers().feedSet(*setData)) { if (_attached.widget()->appendSet(set)) { addedSet = true; if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) { @@ -183,7 +421,9 @@ void StickersBox::showAttachedStickers() { } } -void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedStickers &result) { +void StickersBox::getArchivedDone( + uint64 offsetId, + const MTPmessages_ArchivedStickers &result) { _archivedRequestId = 0; _archivedLoaded = true; if (result.type() != mtpc_messages_archivedStickers) { @@ -191,7 +431,7 @@ void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedSti } auto &stickers = result.c_messages_archivedStickers(); - auto &archived = _session->data().archivedStickerSetsOrderRef(); + auto &archived = _session->data().stickers().archivedSetsOrderRef(); if (offsetId) { auto index = archived.indexOf(offsetId); if (index >= 0) { @@ -221,7 +461,7 @@ void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedSti } if (!setData) continue; - if (const auto set = Stickers::FeedSet(*setData)) { + if (const auto set = _session->data().stickers().feedSet(*setData)) { const auto index = archived.indexOf(set->id); if (archived.isEmpty() || index != archived.size() - 1) { changedSets = true; @@ -268,7 +508,7 @@ void StickersBox::prepare() { setTitle(tr::lng_stickers_attached_sets()); } if (_tabs) { - if (_session->data().archivedStickerSetsOrder().isEmpty()) { + if (_session->data().stickers().archivedSetsOrder().isEmpty()) { preloadArchivedSets(); } setNoContentMargin(true); @@ -319,16 +559,17 @@ void StickersBox::prepare() { setInnerWidget(_tab->takeWidget(), getTopSkip()); setDimensions(st::boxWideWidth, st::boxMaxListHeight); - _session->data().stickersUpdated( + _session->data().stickers().updated( ) | rpl::start_with_next( [this] { handleStickersUpdated(); }, lifetime()); _session->api().updateStickers(); if (_installed.widget()) { - connect(_installed.widget(), &Inner::draggingScrollDelta, [=](int delta) { + _installed.widget()->draggingScrollDelta( + ) | rpl::start_with_next([=](int delta) { scrollByDraggingDelta(delta); - }); + }, _installed.widget()->lifetime()); if (!_megagroupSet) { boxClosing() | rpl::start_with_next([=] { saveChanges(); @@ -350,11 +591,11 @@ void StickersBox::refreshTabs() { auto sections = QStringList(); sections.push_back(tr::lng_stickers_installed_tab(tr::now).toUpper()); _tabIndices.push_back(Section::Installed); - if (!_session->data().featuredStickerSetsOrder().isEmpty()) { + if (!_session->data().stickers().featuredSetsOrder().isEmpty()) { sections.push_back(tr::lng_stickers_featured_tab(tr::now).toUpper()); _tabIndices.push_back(Section::Featured); } - if (!_session->data().archivedStickerSetsOrder().isEmpty()) { + if (!_session->data().stickers().archivedSetsOrder().isEmpty()) { sections.push_back(tr::lng_stickers_archived_tab(tr::now).toUpper()); _tabIndices.push_back(Section::Archived); } @@ -371,13 +612,15 @@ void StickersBox::refreshTabs() { } void StickersBox::loadMoreArchived() { - if (_section != Section::Archived || _allArchivedLoaded || _archivedRequestId) { + if (_section != Section::Archived + || _allArchivedLoaded + || _archivedRequestId) { return; } uint64 lastId = 0; - const auto &order = _session->data().archivedStickerSetsOrder(); - const auto &sets = _session->data().stickerSets(); + const auto &order = _session->data().stickers().archivedSetsOrder(); + const auto &sets = _session->data().stickers().sets(); for (auto setIt = order.cend(), e = order.cbegin(); setIt != e;) { --setIt; auto it = sets.find(*setIt); @@ -499,7 +742,7 @@ QPixmap StickersBox::grabContentCache() { } void StickersBox::installSet(uint64 setId) { - const auto &sets = _session->data().stickerSets(); + const auto &sets = _session->data().stickers().sets(); const auto it = sets.find(setId); if (it == sets.cend()) { rebuildList(); @@ -523,13 +766,13 @@ void StickersBox::installSet(uint64 setId) { rpcDone(&StickersBox::installDone), rpcFail(&StickersBox::installFail, setId)); - Stickers::InstallLocally(setId); + _session->data().stickers().installLocally(setId); } } void StickersBox::installDone(const MTPmessages_StickerSetInstallResult &result) { if (result.type() == mtpc_messages_stickerSetInstallResultArchive) { - Stickers::ApplyArchivedResult( + _session->data().stickers().applyArchivedResult( result.c_messages_stickerSetInstallResultArchive()); } } @@ -537,14 +780,14 @@ void StickersBox::installDone(const MTPmessages_StickerSetInstallResult &result) bool StickersBox::installFail(uint64 setId, const RPCError &error) { if (MTP::isDefaultHandledError(error)) return false; - const auto &sets = _session->data().stickerSets(); + const auto &sets = _session->data().stickers().sets(); const auto it = sets.find(setId); if (it == sets.cend()) { rebuildList(); return true; } - Stickers::UndoInstallLocally(setId); + _session->data().stickers().undoInstallLocally(setId); return true; } @@ -561,8 +804,8 @@ void StickersBox::requestArchivedSets() { preloadArchivedSets(); } - const auto &sets = _session->data().stickerSets(); - const auto &order = _session->data().archivedStickerSetsOrder(); + const auto &sets = _session->data().stickers().sets(); + const auto &order = _session->data().stickers().archivedSetsOrder(); for (const auto setId : order) { auto it = sets.find(setId); if (it != sets.cend()) { @@ -596,7 +839,7 @@ void StickersBox::handleStickersUpdated() { } else { _tab->widget()->updateRows(); } - if (_session->data().archivedStickerSetsOrder().isEmpty()) { + if (_session->data().stickers().archivedSetsOrder().isEmpty()) { preloadArchivedSets(); } else { refreshTabs(); @@ -637,7 +880,7 @@ void StickersBox::setInnerFocus() { StickersBox::~StickersBox() = default; StickersBox::Inner::Row::Row( - not_null set, + not_null set, DocumentData *sticker, int32 count, const QString &title, @@ -666,7 +909,7 @@ StickersBox::Inner::Row::Row( StickersBox::Inner::Row::~Row() = default; bool StickersBox::Inner::Row::isRecentSet() const { - return (set->id == Stickers::CloudRecentSetId); + return (set->id == Data::Stickers::CloudRecentSetId); } StickersBox::Inner::Inner( @@ -964,15 +1207,15 @@ void StickersBox::Inner::paintRowThumbnail( void StickersBox::Inner::validateLottieAnimation(not_null row) { if (row->lottie - || !Stickers::HasLottieThumbnail( + || !ChatHelpers::HasLottieThumbnail( row->thumbnailMedia.get(), row->stickerMedia.get())) { return; } - auto player = Stickers::LottieThumbnail( + auto player = ChatHelpers::LottieThumbnail( row->thumbnailMedia.get(), row->stickerMedia.get(), - Stickers::LottieSize::SetsListThumbnail, + ChatHelpers::StickerLottieSize::SetsListThumbnail, QSize( st::contactsPhotoSize, st::contactsPhotoSize) * cIntRetinaFactor()); @@ -1058,7 +1301,7 @@ void StickersBox::Inner::paintFakeButton(Painter &p, not_null row, int ind void StickersBox::Inner::mousePressEvent(QMouseEvent *e) { if (_dragging >= 0) mouseReleaseEvent(e); _mouse = e->globalPos(); - onUpdateSelected(); + updateSelected(); setPressed(_selected); if (_actionSel >= 0) { @@ -1175,10 +1418,10 @@ void StickersBox::Inner::ensureRipple(const style::RippleAnimation &st, QImage m void StickersBox::Inner::mouseMoveEvent(QMouseEvent *e) { _mouse = e->globalPos(); - onUpdateSelected(); + updateSelected(); } -void StickersBox::Inner::onUpdateSelected() { +void StickersBox::Inner::updateSelected() { auto local = mapFromGlobal(_mouse); if (_dragging >= 0) { auto shift = 0; @@ -1214,16 +1457,14 @@ void StickersBox::Inner::onUpdateSelected() { _shiftingStartTimes[_dragging] = 0; shiftingAnimationCallback(now); - auto countDraggingScrollDelta = [this, local] { + _draggingScrollDelta.fire_copy([&] { if (local.y() < _visibleTop) { return local.y() - _visibleTop; } else if (local.y() >= _visibleBottom) { return local.y() + 1 - _visibleBottom; } return 0; - }; - - emit draggingScrollDelta(countDraggingScrollDelta()); + }()); } else { bool in = rect().marginsRemoved(QMargins(0, _itemsTop, 0, st::membersMarginBottom)).contains(local); auto selected = SelectedRow(); @@ -1258,7 +1499,7 @@ void StickersBox::Inner::onUpdateSelected() { updateCursor(); } setActionSel(actionSel); - emit draggingScrollDelta(0); + _draggingScrollDelta.fire(0); } } @@ -1288,7 +1529,7 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) { updateCursor(); _mouse = e->globalPos(); - onUpdateSelected(); + updateSelected(); if (_actionDown == _actionSel && _actionSel >= 0) { if (_section == Section::Installed) { setRowRemoved(_actionDown, !_rows[_actionDown]->removed); @@ -1339,11 +1580,15 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) { void StickersBox::Inner::saveGroupSet() { Expects(_megagroupSet != nullptr); - auto oldId = (_megagroupSet->mgInfo->stickerSet.type() == mtpc_inputStickerSetID) ? _megagroupSet->mgInfo->stickerSet.c_inputStickerSetID().vid().v : 0; - auto newId = (_megagroupSetInput.type() == mtpc_inputStickerSetID) ? _megagroupSetInput.c_inputStickerSetID().vid().v : 0; + auto oldId = (_megagroupSet->mgInfo->stickerSet.type() == mtpc_inputStickerSetID) + ? _megagroupSet->mgInfo->stickerSet.c_inputStickerSetID().vid().v + : 0; + auto newId = (_megagroupSetInput.type() == mtpc_inputStickerSetID) + ? _megagroupSetInput.c_inputStickerSetID().vid().v + : 0; if (newId != oldId) { _session->api().setGroupStickerSet(_megagroupSet, _megagroupSetInput); - _session->api().stickerSetInstalled(Stickers::MegagroupSetId); + _session->api().stickerSetInstalled(Data::Stickers::MegagroupSetId); } } @@ -1353,18 +1598,18 @@ void StickersBox::Inner::setRowRemoved(int index, bool removed) { row->removed = removed; row->ripple.reset(); update(0, _itemsTop + index * _rowHeight, width(), _rowHeight); - onUpdateSelected(); + updateSelected(); } } void StickersBox::Inner::leaveEventHook(QEvent *e) { _mouse = QPoint(-1, -1); - onUpdateSelected(); + updateSelected(); } void StickersBox::Inner::leaveToChildEvent(QEvent *e, QWidget *child) { _mouse = QPoint(-1, -1); - onUpdateSelected(); + updateSelected(); } bool StickersBox::Inner::shiftingAnimationCallback(crl::time now) { @@ -1473,7 +1718,7 @@ void StickersBox::Inner::handleMegagroupSetAddressChange() { auto text = _megagroupSetField->getLastText().trimmed(); if (text.isEmpty()) { if (_megagroupSelectedSet) { - const auto &sets = _session->data().stickerSets(); + const auto &sets = _session->data().stickers().sets(); const auto it = sets.find(_megagroupSelectedSet->set->id); if (it != sets.cend() && !it->second->shortName.isEmpty()) { setMegagroupSelectedSet(MTP_inputStickerSetEmpty()); @@ -1484,7 +1729,7 @@ void StickersBox::Inner::handleMegagroupSetAddressChange() { MTP_inputStickerSetShortName(MTP_string(text)) )).done([=](const MTPmessages_StickerSet &result) { _megagroupSetRequestId = 0; - auto set = Stickers::FeedSetFull(result); + auto set = _session->data().stickers().feedSetFull(result); setMegagroupSelectedSet(MTP_inputStickerSetID( MTP_long(set->id), MTP_long(set->access))); @@ -1511,7 +1756,7 @@ void StickersBox::Inner::rebuildMegagroupSet() { } auto &inputId = _megagroupSetInput.c_inputStickerSetID(); auto setId = inputId.vid().v; - const auto &sets = _session->data().stickerSets(); + const auto &sets = _session->data().stickers().sets(); auto it = sets.find(setId); if (it == sets.cend() || (it->second->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) { @@ -1572,30 +1817,30 @@ void StickersBox::Inner::rebuild() { auto maxNameWidth = countMaxNameWidth(); clear(); - const auto &order = ([&]() -> const Stickers::Order & { + const auto &order = ([&]() -> const StickersSetsOrder & { if (_section == Section::Installed) { - auto &result = _session->data().stickerSetsOrder(); + auto &result = _session->data().stickers().setsOrder(); if (_megagroupSet && result.empty()) { - return _session->data().featuredStickerSetsOrder(); + return _session->data().stickers().featuredSetsOrder(); } return result; } else if (_section == Section::Featured) { - return _session->data().featuredStickerSetsOrder(); + return _session->data().stickers().featuredSetsOrder(); } - return _session->data().archivedStickerSetsOrder(); + return _session->data().stickers().archivedSetsOrder(); })(); _rows.reserve(order.size() + 1); _shiftingStartTimes.reserve(order.size() + 1); - const auto &sets = _session->data().stickerSets(); + const auto &sets = _session->data().stickers().sets(); if (_megagroupSet) { - auto usingFeatured = _session->data().stickerSetsOrder().empty(); + auto usingFeatured = _session->data().stickers().setsOrder().empty(); _megagroupSubTitle->setText(usingFeatured ? tr::lng_stickers_group_from_featured(tr::now) : tr::lng_stickers_group_from_your(tr::now)); updateControlsGeometry(); } else if (_section == Section::Installed) { - auto cloudIt = sets.find(Stickers::CloudRecentSetId); + auto cloudIt = sets.find(Data::Stickers::CloudRecentSetId); if (cloudIt != sets.cend() && !cloudIt->second->stickers.isEmpty()) { rebuildAppendSet(cloudIt->second.get(), maxNameWidth); } @@ -1622,7 +1867,7 @@ void StickersBox::Inner::setMegagroupSelectedSet(const MTPInputStickerSet &set) _megagroupSetInput = set; rebuild(); scrollToY.notify(0, true); - onUpdateSelected(); + updateSelected(); } void StickersBox::Inner::setMinHeight(int newWidth, int minHeight) { @@ -1639,7 +1884,7 @@ void StickersBox::Inner::updateSize(int newWidth) { void StickersBox::Inner::updateRows() { int maxNameWidth = countMaxNameWidth(); - const auto &sets = _session->data().stickerSets(); + const auto &sets = _session->data().stickers().sets(); for (const auto &row : _rows) { const auto it = sets.find(row->set->id); if (it == sets.cend()) { @@ -1677,7 +1922,7 @@ void StickersBox::Inner::updateRows() { update(); } -bool StickersBox::Inner::appendSet(not_null set) { +bool StickersBox::Inner::appendSet(not_null set) { for (const auto &row : _rows) { if (row->set == set) { return false; @@ -1707,10 +1952,10 @@ int StickersBox::Inner::countMaxNameWidth() const { } void StickersBox::Inner::rebuildAppendSet( - not_null set, + not_null set, int maxNameWidth) { bool installed = true, official = true, unread = false, archived = false, removed = false; - if (set->id != Stickers::CloudRecentSetId) { + if (set->id != Data::Stickers::CloudRecentSetId) { fillSetFlags(set, &installed, &official, &unread, &archived); } if (_section == Section::Installed && archived) { @@ -1742,7 +1987,7 @@ void StickersBox::Inner::rebuildAppendSet( } void StickersBox::Inner::fillSetCover( - not_null set, + not_null set, DocumentData **outSticker, int *outWidth, int *outHeight) const { @@ -1780,31 +2025,31 @@ void StickersBox::Inner::fillSetCover( *outHeight = pixh; } -int StickersBox::Inner::fillSetCount(not_null set) const { +int StickersBox::Inner::fillSetCount(not_null set) const { int result = set->stickers.isEmpty() ? set->count : set->stickers.size(); auto added = 0; - if (set->id == Stickers::CloudRecentSetId) { - const auto &sets = _session->data().stickerSets(); - auto customIt = sets.find(Stickers::CustomSetId); + if (set->id == Data::Stickers::CloudRecentSetId) { + const auto &sets = _session->data().stickers().sets(); + auto customIt = sets.find(Data::Stickers::CustomSetId); if (customIt != sets.cend()) { added = customIt->second->stickers.size(); - const auto &recent = Stickers::GetRecentPack(); + const auto &recent = _session->data().stickers().getRecentPack(); for (const auto &sticker : recent) { if (customIt->second->stickers.indexOf(sticker.first) < 0) { ++added; } } } else { - added = Stickers::GetRecentPack().size(); + added = _session->data().stickers().getRecentPack().size(); } } return result + added; } QString StickersBox::Inner::fillSetTitle( - not_null set, + not_null set, int maxNameWidth, int *outTitleWidth) const { auto result = set->title; @@ -1820,7 +2065,7 @@ QString StickersBox::Inner::fillSetTitle( } void StickersBox::Inner::fillSetFlags( - not_null set, + not_null set, bool *outInstalled, bool *outOfficial, bool *outUnread, @@ -1836,10 +2081,10 @@ void StickersBox::Inner::fillSetFlags( } template -Stickers::Order StickersBox::Inner::collectSets(Check check) const { - Stickers::Order result; +StickersSetsOrder StickersBox::Inner::collectSets(Check check) const { + StickersSetsOrder result; result.reserve(_rows.size()); - for_const (auto &row, _rows) { + for (const auto &row : _rows) { if (check(row.get())) { result.push_back(row->set->id); } @@ -1847,19 +2092,19 @@ Stickers::Order StickersBox::Inner::collectSets(Check check) const { return result; } -Stickers::Order StickersBox::Inner::getOrder() const { +StickersSetsOrder StickersBox::Inner::getOrder() const { return collectSets([](Row *row) { return !row->archived && !row->removed && !row->isRecentSet(); }); } -Stickers::Order StickersBox::Inner::getFullOrder() const { +StickersSetsOrder StickersBox::Inner::getFullOrder() const { return collectSets([](Row *row) { return !row->isRecentSet(); }); } -Stickers::Order StickersBox::Inner::getRemovedSets() const { +StickersSetsOrder StickersBox::Inner::getRemovedSets() const { return collectSets([](Row *row) { return row->removed; }); @@ -1875,7 +2120,7 @@ int StickersBox::Inner::getRowIndex(uint64 setId) const { return -1; } -void StickersBox::Inner::setFullOrder(const Stickers::Order &order) { +void StickersBox::Inner::setFullOrder(const StickersSetsOrder &order) { for_const (auto setId, order) { auto index = getRowIndex(setId); if (index >= 0) { @@ -1889,7 +2134,7 @@ void StickersBox::Inner::setFullOrder(const Stickers::Order &order) { } } -void StickersBox::Inner::setRemovedSets(const Stickers::Order &removed) { +void StickersBox::Inner::setRemovedSets(const StickersSetsOrder &removed) { for (auto i = 0, count = int(_rows.size()); i != count; ++i) { setRowRemoved(i, removed.contains(_rows[i]->set->id)); } diff --git a/Telegram/SourceFiles/boxes/stickers_box.h b/Telegram/SourceFiles/boxes/stickers_box.h index 8cc3e03b5..217682bc4 100644 --- a/Telegram/SourceFiles/boxes/stickers_box.h +++ b/Telegram/SourceFiles/boxes/stickers_box.h @@ -10,7 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/abstract_box.h" #include "base/timer.h" #include "mtproto/sender.h" -#include "chat_helpers/stickers_set.h" +#include "data/stickers/data_stickers_set.h" #include "ui/effects/animations.h" #include "ui/special_fields.h" @@ -89,12 +89,8 @@ private: object_ptr takeWidget(); void returnWidget(object_ptr widget); - Inner *widget() { - return _weak; - } - int index() const { - return _index; - } + [[nodiscard]] Inner *widget(); + [[nodiscard]] int index() const; void saveScrollTop(); int getScrollTop() const { @@ -157,228 +153,7 @@ private: bool _allArchivedLoaded = false; bool _someArchivedLoaded = false; - Stickers::Order _localOrder; - Stickers::Order _localRemoved; - -}; - -// This class is hold in header because it requires Qt preprocessing. -class StickersBox::Inner - : public Ui::RpWidget - , private base::Subscriber { - Q_OBJECT - -public: - using Section = StickersBox::Section; - - Inner( - QWidget *parent, - not_null session, - Section section); - Inner(QWidget *parent, not_null megagroup); - - base::Observable scrollToY; - void setInnerFocus(); - - void saveGroupSet(); - - void rebuild(); - void updateSize(int newWidth = 0); - void updateRows(); // refresh only pack cover stickers - bool appendSet(not_null set); - - Stickers::Order getOrder() const; - Stickers::Order getFullOrder() const; - Stickers::Order getRemovedSets() const; - - void setFullOrder(const Stickers::Order &order); - void setRemovedSets(const Stickers::Order &removed); - - void setInstallSetCallback(Fn callback) { - _installSetCallback = std::move(callback); - } - void setLoadMoreCallback(Fn callback) { - _loadMoreCallback = std::move(callback); - } - - void setMinHeight(int newWidth, int minHeight); - - int getVisibleTop() const { - return _visibleTop; - } - - ~Inner(); - -protected: - void visibleTopBottomUpdated( - int visibleTop, - int visibleBottom) override; - - void paintEvent(QPaintEvent *e) override; - void resizeEvent(QResizeEvent *e) override; - void mousePressEvent(QMouseEvent *e) override; - void mouseMoveEvent(QMouseEvent *e) override; - void mouseReleaseEvent(QMouseEvent *e) override; - void leaveEventHook(QEvent *e) override; - void leaveToChildEvent(QEvent *e, QWidget *child) override; - -signals: - void draggingScrollDelta(int delta); - -public slots: - void onUpdateSelected(); - -private: - struct Row { - Row( - not_null set, - DocumentData *sticker, - int32 count, - const QString &title, - int titleWidth, - bool installed, - bool official, - bool unread, - bool archived, - bool removed, - int32 pixw, - int32 pixh); - ~Row(); - - bool isRecentSet() const; - - const not_null set; - DocumentData *sticker = nullptr; - std::shared_ptr stickerMedia; - std::shared_ptr thumbnailMedia; - int32 count = 0; - QString title; - int titleWidth = 0; - bool installed = false; - bool official = false; - bool unread = false; - bool archived = false; - bool removed = false; - int32 pixw = 0; - int32 pixh = 0; - anim::value yadd; - std::unique_ptr ripple; - std::unique_ptr lottie; - }; - struct MegagroupSet { - inline bool operator==(const MegagroupSet &other) const { - return true; - } - inline bool operator!=(const MegagroupSet &other) const { - return false; - } - }; - using SelectedRow = base::optional_variant; - class AddressField : public Ui::UsernameInput { - public: - using UsernameInput::UsernameInput; - - protected: - void correctValue( - const QString &was, - int wasCursor, - QString &now, - int &nowCursor) override; - - }; - - template - Stickers::Order collectSets(Check check) const; - - void checkLoadMore(); - void updateScrollbarWidth(); - int getRowIndex(uint64 setId) const; - void setRowRemoved(int index, bool removed); - - void setSelected(SelectedRow selected); - void setActionDown(int newActionDown); - void setPressed(SelectedRow pressed); - void setup(); - QRect relativeButtonRect(bool removeButton) const; - void ensureRipple(const style::RippleAnimation &st, QImage mask, bool removeButton); - - bool shiftingAnimationCallback(crl::time now); - void paintRow(Painter &p, not_null row, int index); - void paintRowThumbnail(Painter &p, not_null row, int left); - void paintFakeButton(Painter &p, not_null row, int index); - void clear(); - void updateCursor(); - void setActionSel(int32 actionSel); - float64 aboveShadowOpacity() const; - void validateLottieAnimation(not_null row); - void updateRowThumbnail(not_null row); - - void readVisibleSets(); - - void updateControlsGeometry(); - void rebuildAppendSet(not_null set, int maxNameWidth); - void fillSetCover(not_null set, DocumentData **outSticker, int *outWidth, int *outHeight) const; - int fillSetCount(not_null set) const; - QString fillSetTitle(not_null set, int maxNameWidth, int *outTitleWidth) const; - void fillSetFlags(not_null set, bool *outInstalled, bool *outOfficial, bool *outUnread, bool *outArchived); - void rebuildMegagroupSet(); - void fixupMegagroupSetAddress(); - void handleMegagroupSetAddressChange(); - void setMegagroupSelectedSet(const MTPInputStickerSet &set); - - int countMaxNameWidth() const; - - const not_null _session; - MTP::Sender _api; - - Section _section; - - int32 _rowHeight; - - std::vector> _rows; - std::vector _shiftingStartTimes; - crl::time _aboveShadowFadeStart = 0; - anim::value _aboveShadowFadeOpacity; - Ui::Animations::Basic _shiftingAnimation; - - Fn _installSetCallback; - Fn _loadMoreCallback; - - int _visibleTop = 0; - int _visibleBottom = 0; - int _itemsTop = 0; - - int _actionSel = -1; - int _actionDown = -1; - - QString _addText; - int _addWidth = 0; - QString _undoText; - int _undoWidth = 0; - - int _buttonHeight = 0; - - QPoint _mouse; - bool _inDragArea = false; - SelectedRow _selected; - SelectedRow _pressed; - QPoint _dragStart; - int _started = -1; - int _dragging = -1; - int _above = -1; - - int _minHeight = 0; - - int _scrollbar = 0; - ChannelData *_megagroupSet = nullptr; - MTPInputStickerSet _megagroupSetInput = MTP_inputStickerSetEmpty(); - std::unique_ptr _megagroupSelectedSet; - object_ptr _megagroupSetField = { nullptr }; - object_ptr _megagroupSelectedShadow = { nullptr }; - object_ptr _megagroupSelectedRemove = { nullptr }; - object_ptr _megagroupDivider = { nullptr }; - object_ptr _megagroupSubTitle = { nullptr }; - base::Timer _megagroupSetAddressChangedTimer; - mtpRequestId _megagroupSetRequestId = 0; + Data::StickersSetsOrder _localOrder; + Data::StickersSetsOrder _localRemoved; }; diff --git a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp index 55f1588ca..27dac2b80 100644 --- a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp +++ b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp @@ -14,6 +14,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_user.h" #include "data/data_peer_values.h" #include "data/data_file_origin.h" +#include "data/data_session.h" +#include "data/stickers/data_stickers.h" +#include "chat_helpers/stickers_lottie.h" #include "mainwindow.h" #include "apiwrap.h" #include "storage/localstorage.h" @@ -21,7 +24,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/scroll_area.h" #include "ui/image/image.h" #include "ui/ui_utility.h" -#include "chat_helpers/stickers.h" #include "base/unixtime.h" #include "window/window_session_controller.h" #include "facades.h" @@ -172,8 +174,7 @@ inline int indexOfInFirstN(const T &v, const U &elem, int last) { } internal::StickerRows FieldAutocomplete::getStickerSuggestions() { - const auto list = Stickers::GetListByEmoji( - &_controller->session(), + const auto list = _controller->session().data().stickers().getListByEmoji( _emoji, _stickersSeed ); @@ -1019,9 +1020,9 @@ auto FieldAutocompleteInner::getLottieRenderer() void FieldAutocompleteInner::setupLottie(StickerSuggestion &suggestion) { const auto document = suggestion.document; - suggestion.animated = Stickers::LottiePlayerFromDocument( + suggestion.animated = ChatHelpers::LottiePlayerFromDocument( suggestion.documentMedia.get(), - Stickers::LottieSize::InlineResults, + ChatHelpers::StickerLottieSize::InlineResults, stickerBoundingBox() * cIntRetinaFactor(), Lottie::Quality::Default, getLottieRenderer()); diff --git a/Telegram/SourceFiles/chat_helpers/field_autocomplete.h b/Telegram/SourceFiles/chat_helpers/field_autocomplete.h index c55cce2fd..69127992c 100644 --- a/Telegram/SourceFiles/chat_helpers/field_autocomplete.h +++ b/Telegram/SourceFiles/chat_helpers/field_autocomplete.h @@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/rp_widget.h" #include "base/timer.h" #include "base/object_ptr.h" -#include "chat_helpers/stickers.h" +#include "data/stickers/data_stickers.h" namespace Ui { class ScrollArea; diff --git a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp index 9bce21d4f..c7626f32e 100644 --- a/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/gifs_list_widget.cpp @@ -15,13 +15,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_file_origin.h" #include "data/data_photo_media.h" #include "data/data_document_media.h" +#include "data/stickers/data_stickers.h" #include "ui/widgets/buttons.h" #include "ui/widgets/input_fields.h" #include "ui/effects/ripple_animation.h" #include "ui/image/image.h" #include "boxes/stickers_box.h" #include "inline_bots/inline_bot_result.h" -#include "chat_helpers/stickers.h" #include "storage/localstorage.h" #include "lang/lang_keys.h" #include "mainwindow.h" @@ -149,8 +149,8 @@ GifsListWidget::GifsListWidget( this, [=] { sendInlineRequest(); }); - controller->session().data().savedGifsUpdated( - ) | rpl::start_with_next([this] { + controller->session().data().stickers().savedGifsUpdated( + ) | rpl::start_with_next([=] { refreshSavedGifs(); }, lifetime()); @@ -511,13 +511,13 @@ void GifsListWidget::refreshSavedGifs() { if (_section == Section::Gifs) { clearInlineRows(false); - auto &saved = controller()->session().data().savedGifs(); + const auto &saved = controller()->session().data().stickers().savedGifs(); if (!saved.isEmpty()) { _rows.reserve(saved.size()); auto row = Row(); row.items.reserve(kInlineItemsMaxPerRow); auto sumWidth = 0; - for_const (auto &gif, saved) { + for (const auto &gif : saved) { inlineRowsAddItem(gif, 0, row, sumWidth); } inlineRowFinalize(row, sumWidth, true); @@ -540,8 +540,8 @@ void GifsListWidget::clearInlineRows(bool resultsDeleted) { _selected = _pressed = -1; } else { clearSelection(); - for_const (auto &row, _rows) { - for_const (auto &item, row.items) { + for (const auto &row : std::as_const(_rows)) { + for (const auto &item : std::as_const(row.items)) { item->setPosition(-1); } } diff --git a/Telegram/SourceFiles/chat_helpers/stickers.h b/Telegram/SourceFiles/chat_helpers/stickers.h deleted file mode 100644 index be8f8d650..000000000 --- a/Telegram/SourceFiles/chat_helpers/stickers.h +++ /dev/null @@ -1,125 +0,0 @@ -/* -This file is part of Telegram Desktop, -the official desktop application for the Telegram messaging service. - -For license and copyright information please follow this link: -https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL -*/ -#pragma once - -#include "mtproto/sender.h" - -class DocumentData; - -namespace Data { -class DocumentMedia; -} // namespace Data - -namespace Main { -class Session; -} // namespace Main - -namespace Storage { -namespace Cache { -struct Key; -} // namespace Cache -} // namespace Storage - -namespace Lottie { -class SinglePlayer; -class MultiPlayer; -class FrameRenderer; -class Animation; -enum class Quality : char; -struct ColorReplacements; -} // namespace Lottie - -namespace Stickers { - -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 -constexpr auto MegagroupSetId = 0xFFFFFFFFFFFFFFEFULL; // for setting up megagroup sticker set - -class Set; -class SetThumbnailView; - -void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d); -bool ApplyArchivedResultFake(); // For testing. -void InstallLocally(uint64 setId); -void UndoInstallLocally(uint64 setId); -bool IsFaved(not_null document); -void SetFaved(not_null document, bool faved); - -void SetsReceived(const QVector &data, int32 hash); -void SpecialSetReceived( - uint64 setId, - const QString &setTitle, - const QVector &items, - int32 hash, - const QVector &packs = QVector(), - const QVector &usageDates = QVector()); -void FeaturedSetsReceived( - const QVector &list, - const QVector &unread, - int32 hash); -void GifsReceived(const QVector &items, int32 hash); - -std::vector> GetListByEmoji( - not_null session, - not_null emoji, - uint64 seed); -std::optional>> GetEmojiListFromSet( - not_null document); - -Set *FeedSet(const MTPDstickerSet &data); -Set *FeedSetFull(const MTPmessages_StickerSet &data); -void NewSetReceived(const MTPmessages_StickerSet &data); - -QString GetSetTitle(const MTPDstickerSet &s); - -RecentStickerPack &GetRecentPack(); - -enum class LottieSize : uchar { - MessageHistory, - StickerSet, - StickersPanel, - StickersFooter, - SetsListThumbnail, - InlineResults, -}; - -[[nodiscard]] std::unique_ptr LottiePlayerFromDocument( - not_null media, - LottieSize sizeTag, - QSize box, - Lottie::Quality quality = Lottie::Quality(), - std::shared_ptr renderer = nullptr); -[[nodiscard]] std::unique_ptr LottiePlayerFromDocument( - not_null media, - const Lottie::ColorReplacements *replacements, - LottieSize sizeTag, - QSize box, - Lottie::Quality quality = Lottie::Quality(), - std::shared_ptr renderer = nullptr); -[[nodiscard]] not_null LottieAnimationFromDocument( - not_null player, - not_null media, - LottieSize sizeTag, - QSize box); - -[[nodiscard]] bool HasLottieThumbnail( - SetThumbnailView *thumb, - Data::DocumentMedia *media); -[[nodiscard]] std::unique_ptr LottieThumbnail( - SetThumbnailView *thumb, - Data::DocumentMedia *media, - LottieSize sizeTag, - QSize box, - std::shared_ptr renderer = nullptr); - -} // namespace Stickers diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp index 3d26a4d70..c5e1a0dbd 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp @@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_channel.h" #include "data/data_file_origin.h" #include "data/data_cloud_file.h" +#include "chat_helpers/stickers_lottie.h" #include "ui/widgets/buttons.h" #include "ui/effects/animations.h" #include "ui/effects/ripple_animation.h" @@ -22,7 +23,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lottie/lottie_animation.h" #include "boxes/stickers_box.h" #include "inline_bots/inline_bot_result.h" -#include "chat_helpers/stickers.h" #include "storage/localstorage.h" #include "lang/lang_keys.h" #include "mainwindow.h" @@ -49,6 +49,10 @@ constexpr auto kRecentDisplayLimit = 20; constexpr auto kPreloadOfficialPages = 4; constexpr auto kOfficialLoadLimit = 40; +using Data::StickersSet; +using Data::StickersPack; +using Data::StickersSetThumbnailView; + bool SetInMyList(MTPDstickerSet::Flags flags) { return (flags & MTPDstickerSet::Flag::f_installed_date) && !(flags & MTPDstickerSet::Flag::f_archived); @@ -60,7 +64,7 @@ struct StickerIcon { StickerIcon(uint64 setId) : setId(setId) { } StickerIcon( - not_null set, + not_null set, DocumentData *sticker, int pixw, int pixh) @@ -86,12 +90,12 @@ struct StickerIcon { } uint64 setId = 0; - Stickers::Set *set = nullptr; + StickersSet *set = nullptr; mutable std::unique_ptr lottie; mutable QPixmap savedFrame; DocumentData *sticker = nullptr; ChannelData *megagroup = nullptr; - mutable std::shared_ptr thumbnailMedia; + mutable std::shared_ptr thumbnailMedia; mutable std::shared_ptr stickerMedia; mutable std::shared_ptr megagroupUserpic; int pixw = 0; @@ -204,7 +208,7 @@ auto StickersListWidget::PrepareStickers( StickersListWidget::Set::Set( uint64 id, - Stickers::Set *set, + StickersSet *set, MTPDstickerSet::Flags flags, const QString &title, const QString &shortName, @@ -368,11 +372,11 @@ void StickersListWidget::Footer::validateSelectedIcon( auto newSelected = -1; for (auto i = 0, l = int(_icons.size()); i != l; ++i) { if (_icons[i].setId == setId - || (_icons[i].setId == Stickers::FavedSetId - && setId == Stickers::RecentSetId)) { + || (_icons[i].setId == Data::Stickers::FavedSetId + && setId == Data::Stickers::RecentSetId)) { newSelected = i; break; - } else if (_icons[i].setId == Stickers::FavedSetId) { + } else if (_icons[i].setId == Data::Stickers::FavedSetId) { favedIconIndex = i; } } @@ -524,7 +528,7 @@ void StickersListWidget::Footer::mousePressEvent(QMouseEvent *e) { if (_iconOver == SpecialOver::Settings) { Ui::show(Box( - &_pan->controller()->session(), + &_pan->session(), (hasOnlyFeaturedSets() ? StickersBox::Section::Featured : StickersBox::Section::Installed))); @@ -718,7 +722,8 @@ void StickersListWidget::Footer::refreshIconsGeometry( } bool StickersListWidget::Footer::hasOnlyFeaturedSets() const { - return (_icons.size() == 1) && (_icons[0].setId == Stickers::FeaturedSetId); + return (_icons.size() == 1) + && (_icons[0].setId == Data::Stickers::FeaturedSetId); } void StickersListWidget::Footer::paintStickerSettingsIcon(Painter &p) const { @@ -736,15 +741,15 @@ void StickersListWidget::Footer::validateIconLottieAnimation( icon.ensureMediaCreated(); if (icon.lottie || !icon.sticker - || !Stickers::HasLottieThumbnail( + || !HasLottieThumbnail( icon.thumbnailMedia.get(), icon.stickerMedia.get())) { return; } - auto player = Stickers::LottieThumbnail( + auto player = LottieThumbnail( icon.thumbnailMedia.get(), icon.stickerMedia.get(), - Stickers::LottieSize::StickersFooter, + StickerLottieSize::StickersFooter, QSize( st::stickerIconWidth - 2 * st::stickerIconPadding, st::emojiFooterHeight - 2 * st::stickerIconPadding @@ -825,9 +830,9 @@ void StickersListWidget::Footer::paintSetIcon( icon.megagroup->paintUserpicLeft(p, icon.megagroupUserpic, x + (st::stickerIconWidth - st::stickerGroupCategorySize) / 2, _iconsTop + (st::emojiFooterHeight - st::stickerGroupCategorySize) / 2, width(), st::stickerGroupCategorySize); } else { const auto paintedIcon = [&] { - if (icon.setId == Stickers::FeaturedSetId) { + if (icon.setId == Data::Stickers::FeaturedSetId) { const auto session = &_pan->session(); - return session->data().featuredStickerSetsUnreadCount() + return session->data().stickers().featuredSetsUnreadCount() ? &st::stickersTrendingUnread : &st::stickersTrending; //} else if (setId == Stickers::FavedSetId) { @@ -979,9 +984,9 @@ void StickersListWidget::preloadMoreOfficial() { }); }); const auto covers = data.match([](const MTPDstickerSetCovered &) { - return Stickers::Pack(); + return StickersPack(); }, [&](const MTPDstickerSetMultiCovered &data) { - auto result = Stickers::Pack(); + auto result = StickersPack(); for (const auto &cover : data.vcovers().v) { const auto document = session().data().processDocument(cover); if (document->sticker()) { @@ -990,7 +995,7 @@ void StickersListWidget::preloadMoreOfficial() { } return result; }); - if (const auto set = Stickers::FeedSet(*setData)) { + if (const auto set = session().data().stickers().feedSet(*setData)) { if (!covers.empty()) { set->covers = covers; } @@ -1065,7 +1070,7 @@ bool StickersListWidget::enumerateSections(Callback callback) const { if (set.externalLayout) { info.rowsCount = 1; info.rowsBottom = info.top + featuredRowHeight(); - } else if (set.id == Stickers::MegagroupSetId && !info.count) { + } else if (set.id == Data::Stickers::MegagroupSetId && !info.count) { info.rowsCount = 0; info.rowsBottom = info.rowsTop + _megagroupSetButtonRect.y() + _megagroupSetButtonRect.height() + st::stickerGroupCategoryAddMargin.bottom(); } else { @@ -1249,7 +1254,7 @@ void StickersListWidget::refreshSearchRows( if (!cloudSets && _searchNextQuery.isEmpty()) { showStickerSet(!_mySets.empty() ? _mySets[0].id - : Stickers::FeaturedSetId); + : Data::Stickers::FeaturedSetId); return; } @@ -1292,7 +1297,7 @@ void StickersListWidget::fillLocalSearchRows(const QString &query) { return true; }; - const auto &sets = session().data().stickerSets(); + const auto &sets = session().data().stickers().sets(); for (const auto &[setId, titleWords] : _searchIndex) { if (allSearchWordsInTitle(titleWords)) { if (const auto it = sets.find(setId); it != sets.end()) { @@ -1304,7 +1309,7 @@ void StickersListWidget::fillLocalSearchRows(const QString &query) { void StickersListWidget::fillCloudSearchRows( const std::vector &cloudSets) { - const auto &sets = session().data().stickerSets(); + const auto &sets = session().data().stickers().sets(); for (const auto setId : cloudSets) { if (const auto it = sets.find(setId); it != sets.end()) { addSearchRow(it->second.get()); @@ -1312,7 +1317,7 @@ void StickersListWidget::fillCloudSearchRows( } } -void StickersListWidget::addSearchRow(not_null set) { +void StickersListWidget::addSearchRow(not_null set) { _searchSets.emplace_back( set->id, set, @@ -1425,7 +1430,7 @@ void StickersListWidget::searchResultsDone( auto &d = result.c_messages_foundStickerSets(); for (const auto &stickerSet : d.vsets().v) { const MTPDstickerSet *setData = nullptr; - Stickers::Pack covers; + StickersPack covers; switch (stickerSet.type()) { case mtpc_stickerSetCovered: { auto &d = stickerSet.c_stickerSetCovered(); @@ -1448,7 +1453,7 @@ void StickersListWidget::searchResultsDone( } if (!setData) continue; - if (const auto set = Stickers::FeedSet(*setData)) { + if (const auto set = session().data().stickers().feedSet(*setData)) { if (!covers.empty()) { set->covers = covers; } @@ -1610,7 +1615,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) { } if (clip.top() + clip.height() <= info.rowsTop) { return true; - } else if (set.id == Stickers::MegagroupSetId && set.stickers.empty()) { + } else if (set.id == Data::Stickers::MegagroupSetId && set.stickers.empty()) { auto buttonSelected = (base::get_if(&_selected) != nullptr); paintMegagroupEmptySet(p, info.rowsTop, buttonSelected); return true; @@ -1796,10 +1801,10 @@ void StickersListWidget::setupLottie(Set &set, int section, int index) { // Document should be loaded already for the animation to be set up. Assert(sticker.documentMedia != nullptr); - sticker.animated = Stickers::LottieAnimationFromDocument( + sticker.animated = LottieAnimationFromDocument( set.lottiePlayer.get(), sticker.documentMedia.get(), - Stickers::LottieSize::StickersPanel, + StickerLottieSize::StickersPanel, boundingBoxSize() * cIntRetinaFactor()); } @@ -1926,7 +1931,7 @@ bool StickersListWidget::hasRemoveButton(int index) const { if (!(flags & MTPDstickerSet_ClientFlag::f_special)) { return true; } - if (set.id == Stickers::MegagroupSetId) { + if (set.id == Data::Stickers::MegagroupSetId) { Assert(_megagroupSet != nullptr); if (index + 1 != shownSets().size()) { return true; @@ -1994,7 +1999,7 @@ QRect StickersListWidget::megagroupSetButtonRectFinal() const { auto result = QRect(); if (_section == Section::Stickers) { enumerateSections([this, &result](const SectionInfo &info) { - if (shownSets()[info.section].id == Stickers::MegagroupSetId) { + if (shownSets()[info.section].id == Data::Stickers::MegagroupSetId) { result = _megagroupSetButtonRect.translated(0, info.rowsTop); return false; } @@ -2057,9 +2062,9 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) { auto &set = sets[sticker->section]; Assert(sticker->index >= 0 && sticker->index < set.stickers.size()); if (stickerHasDeleteButton(set, sticker->index) && sticker->overDelete) { - if (set.id == Stickers::RecentSetId) { + if (set.id == Data::Stickers::RecentSetId) { removeRecentSticker(sticker->section, sticker->index); - } else if (set.id == Stickers::FavedSetId) { + } else if (set.id == Data::Stickers::FavedSetId) { removeFavedSticker(sticker->section, sticker->index); } else { Unexpected("Single sticker delete click."); @@ -2085,7 +2090,7 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) { Assert(button->section >= 0 && button->section < sets.size()); if (sets[button->section].externalLayout) { installSet(sets[button->section].id); - } else if (sets[button->section].id == Stickers::MegagroupSetId) { + } else if (sets[button->section].id == Data::Stickers::MegagroupSetId) { auto removeLocally = sets[button->section].stickers.empty() || !_megagroupSet->canEditStickers(); removeMegagroupSet(removeLocally); @@ -2110,7 +2115,7 @@ void StickersListWidget::validateSelectedIcon( void StickersListWidget::removeRecentSticker(int section, int index) { if ((_section != Section::Stickers) || (section >= int(_mySets.size())) - || (_mySets[section].id != Stickers::RecentSetId)) { + || (_mySets[section].id != Data::Stickers::RecentSetId)) { return; } @@ -2118,7 +2123,7 @@ void StickersListWidget::removeRecentSticker(int section, int index) { bool refresh = false; const auto &sticker = _mySets[section].stickers[index]; const auto document = sticker.document; - auto &recent = Stickers::GetRecentPack(); + auto &recent = session().data().stickers().getRecentPack(); for (int32 i = 0, l = recent.size(); i < l; ++i) { if (recent.at(i).first == document) { recent.removeAt(i); @@ -2127,8 +2132,8 @@ void StickersListWidget::removeRecentSticker(int section, int index) { break; } } - auto &sets = session().data().stickerSetsRef(); - auto it = sets.find(Stickers::CustomSetId); + auto &sets = session().data().stickers().setsRef(); + auto it = sets.find(Data::Stickers::CustomSetId); if (it != sets.cend()) { const auto set = it->second.get(); for (int i = 0, l = set->stickers.size(); i < l; ++i) { @@ -2153,17 +2158,17 @@ void StickersListWidget::removeRecentSticker(int section, int index) { void StickersListWidget::removeFavedSticker(int section, int index) { if ((_section != Section::Stickers) || (section >= int(_mySets.size())) - || (_mySets[section].id != Stickers::FavedSetId)) { + || (_mySets[section].id != Data::Stickers::FavedSetId)) { return; } clearSelection(); const auto &sticker = _mySets[section].stickers[index]; const auto document = sticker.document; - Stickers::SetFaved(document, false); + session().data().stickers().setFaved(document, false); session().api().toggleFavedSticker( document, - Data::FileOriginStickerSet(Stickers::FavedSetId, 0), + Data::FileOriginStickerSet(Data::Stickers::FavedSetId, 0), false); } @@ -2271,12 +2276,12 @@ void StickersListWidget::refreshStickers() { void StickersListWidget::refreshMySets() { auto wasSets = base::take(_mySets); _favedStickersMap.clear(); - _mySets.reserve(session().data().stickerSetsOrder().size() + 3); + _mySets.reserve(session().data().stickers().setsOrder().size() + 3); refreshFavedStickers(); refreshRecentStickers(false); refreshMegagroupStickers(GroupStickersPlace::Visible); - for (const auto setId : session().data().stickerSetsOrder()) { + for (const auto setId : session().data().stickers().setsOrder()) { const auto externalLayout = false; appendSet(_mySets, setId, externalLayout, AppendSkip::Archived); } @@ -2289,16 +2294,16 @@ void StickersListWidget::refreshFeaturedSets() { auto wasFeaturedSetsCount = base::take(_featuredSetsCount); auto wereOfficial = base::take(_officialSets); _officialSets.reserve( - session().data().featuredStickerSetsOrder().size() + session().data().stickers().featuredSetsOrder().size() + wereOfficial.size() - wasFeaturedSetsCount); - for (const auto setId : session().data().featuredStickerSetsOrder()) { + for (const auto setId : session().data().stickers().featuredSetsOrder()) { const auto externalLayout = true; appendSet(_officialSets, setId, externalLayout, AppendSkip::Installed); } _featuredSetsCount = _officialSets.size(); if (wereOfficial.size() > wasFeaturedSetsCount) { - const auto &sets = session().data().stickerSets(); + const auto &sets = session().data().stickers().sets(); const auto from = begin(wereOfficial) + wasFeaturedSetsCount; const auto till = end(wereOfficial); for (auto i = from; i != till; ++i) { @@ -2319,7 +2324,7 @@ void StickersListWidget::refreshFeaturedSets() { void StickersListWidget::refreshSearchSets() { refreshSearchIndex(); - const auto &sets = session().data().stickerSets(); + const auto &sets = session().data().stickers().sets(); for (auto &entry : _searchSets) { if (const auto it = sets.find(entry.id); it != sets.end()) { const auto set = it->second.get(); @@ -2356,7 +2361,7 @@ void StickersListWidget::refreshSettingsVisibility() { void StickersListWidget::refreshFooterIcons() { _footer->refreshIcons(ValidateIconAnimations::None); if (_footer->hasOnlyFeaturedSets() && _section != Section::Featured) { - showStickerSet(Stickers::FeaturedSetId); + showStickerSet(Data::Stickers::FeaturedSetId); } } @@ -2368,11 +2373,11 @@ void StickersListWidget::preloadImages() { uint64 StickersListWidget::currentSet(int yOffset) const { if (_section == Section::Featured) { - return Stickers::FeaturedSetId; + return Data::Stickers::FeaturedSetId; } const auto &sets = shownSets(); return sets.empty() - ? Stickers::RecentSetId + ? Data::Stickers::RecentSetId : sets[sectionInfoByOffset(yOffset).section].id; } @@ -2381,7 +2386,7 @@ bool StickersListWidget::appendSet( uint64 setId, bool externalLayout, AppendSkip skip) { - const auto &sets = session().data().stickerSets(); + const auto &sets = session().data().stickers().sets(); auto it = sets.find(setId); if (it == sets.cend() || (!externalLayout && it->second->stickers.isEmpty())) { @@ -2418,7 +2423,7 @@ void StickersListWidget::refreshRecent() { refreshRecentStickers(); } if (_footer && _footer->hasOnlyFeaturedSets() && _section != Section::Featured) { - showStickerSet(Stickers::FeaturedSetId); + showStickerSet(Data::Stickers::FeaturedSetId); } } @@ -2426,10 +2431,10 @@ auto StickersListWidget::collectRecentStickers() -> std::vector { _custom.clear(); auto result = std::vector(); - const auto &sets = session().data().stickerSets(); - const auto &recent = Stickers::GetRecentPack(); - const auto customIt = sets.find(Stickers::CustomSetId); - const auto cloudIt = sets.find(Stickers::CloudRecentSetId); + const auto &sets = session().data().stickers().sets(); + const auto &recent = session().data().stickers().getRecentPack(); + const auto customIt = sets.find(Data::Stickers::CustomSetId); + const auto cloudIt = sets.find(Data::Stickers::CloudRecentSetId); const auto customCount = (customIt != sets.cend()) ? customIt->second->stickers.size() : 0; @@ -2479,13 +2484,13 @@ void StickersListWidget::refreshRecentStickers(bool performResize) { auto recentPack = collectRecentStickers(); auto recentIt = std::find_if(_mySets.begin(), _mySets.end(), [](auto &set) { - return set.id == Stickers::RecentSetId; + return set.id == Data::Stickers::RecentSetId; }); if (!recentPack.empty()) { const auto shortName = QString(); const auto externalLayout = false; auto set = Set( - Stickers::RecentSetId, + Data::Stickers::RecentSetId, nullptr, (MTPDstickerSet::Flag::f_official | MTPDstickerSet_ClientFlag::f_special), @@ -2512,8 +2517,8 @@ void StickersListWidget::refreshRecentStickers(bool performResize) { void StickersListWidget::refreshFavedStickers() { clearSelection(); - const auto &sets = session().data().stickerSets(); - const auto it = sets.find(Stickers::FavedSetId); + const auto &sets = session().data().stickers().sets(); + const auto it = sets.find(Data::Stickers::FavedSetId); if (it == sets.cend() || it->second->stickers.isEmpty()) { return; } @@ -2521,7 +2526,7 @@ void StickersListWidget::refreshFavedStickers() { const auto externalLayout = false; const auto shortName = QString(); _mySets.emplace_back( - Stickers::FavedSetId, + Data::Stickers::FavedSetId, nullptr, (MTPDstickerSet::Flag::f_official | MTPDstickerSet_ClientFlag::f_special), @@ -2553,7 +2558,7 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) { const auto externalLayout = false; const auto count = 0; _mySets.emplace_back( - Stickers::MegagroupSetId, + Data::Stickers::MegagroupSetId, nullptr, MTPDstickerSet_ClientFlag::f_special | 0, tr::lng_group_stickers(tr::now), @@ -2579,7 +2584,7 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) { return; } auto &set = _megagroupSet->mgInfo->stickerSet.c_inputStickerSetID(); - const auto &sets = session().data().stickerSets(); + const auto &sets = session().data().stickers().sets(); const auto it = sets.find(set.vid().v); if (it != sets.cend()) { const auto set = it->second.get(); @@ -2591,7 +2596,7 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) { const auto shortName = QString(); const auto externalLayout = false; _mySets.emplace_back( - Stickers::MegagroupSetId, + Data::Stickers::MegagroupSetId, set, MTPDstickerSet_ClientFlag::f_special | 0, tr::lng_group_stickers(tr::now), @@ -2609,7 +2614,7 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) { _api.request(MTPmessages_GetStickerSet( _megagroupSet->mgInfo->stickerSet )).done([=](const MTPmessages_StickerSet &result) { - if (const auto set = Stickers::FeedSetFull(result)) { + if (const auto set = session().data().stickers().feedSetFull(result)) { refreshStickers(); if (set->id == _megagroupSetIdRequested) { _megagroupSetIdRequested = 0; @@ -2624,23 +2629,23 @@ std::vector StickersListWidget::fillIcons() { auto result = std::vector(); result.reserve(_mySets.size() + 1); if (!_officialSets.empty()) { - result.emplace_back(Stickers::FeaturedSetId); + result.emplace_back(Data::Stickers::FeaturedSetId); } auto i = 0; - if (i != _mySets.size() && _mySets[i].id == Stickers::FavedSetId) { + if (i != _mySets.size() && _mySets[i].id == Data::Stickers::FavedSetId) { ++i; - result.emplace_back(Stickers::FavedSetId); + result.emplace_back(Data::Stickers::FavedSetId); } - if (i != _mySets.size() && _mySets[i].id == Stickers::RecentSetId) { + if (i != _mySets.size() && _mySets[i].id == Data::Stickers::RecentSetId) { ++i; - if (result.empty() || result.back().setId != Stickers::FavedSetId) { - result.emplace_back(Stickers::RecentSetId); + if (result.empty() || result.back().setId != Data::Stickers::FavedSetId) { + result.emplace_back(Data::Stickers::RecentSetId); } } for (auto l = _mySets.size(); i != l; ++i) { - if (_mySets[i].id == Stickers::MegagroupSetId) { - result.emplace_back(Stickers::MegagroupSetId); + if (_mySets[i].id == Data::Stickers::MegagroupSetId) { + result.emplace_back(Data::Stickers::MegagroupSetId); result.back().megagroup = _megagroupSet; continue; } @@ -2702,14 +2707,14 @@ void StickersListWidget::updateSelected() { newSelected = OverButton{ section }; } else if (!(sets[section].flags & MTPDstickerSet_ClientFlag::f_special)) { newSelected = OverSet { section }; - } else if (sets[section].id == Stickers::MegagroupSetId + } else if (sets[section].id == Data::Stickers::MegagroupSetId && (_megagroupSet->canEditStickers() || !sets[section].stickers.empty())) { newSelected = OverSet { section }; } } else if (p.y() >= info.rowsTop && p.y() < info.rowsBottom && sx >= 0) { auto yOffset = p.y() - info.rowsTop; auto &set = sets[section]; - if (set.id == Stickers::MegagroupSetId && set.stickers.empty()) { + if (set.id == Data::Stickers::MegagroupSetId && set.stickers.empty()) { if (_megagroupSetButtonRect.contains(stickersLeft() + sx, yOffset)) { newSelected = OverGroupAdd {}; } @@ -2737,20 +2742,20 @@ void StickersListWidget::updateSelected() { } bool StickersListWidget::setHasTitle(const Set &set) const { - if (set.id == Stickers::FavedSetId) { + if (set.id == Data::Stickers::FavedSetId) { return false; - } else if (set.id == Stickers::RecentSetId) { - return !_mySets.empty() && _mySets[0].id == Stickers::FavedSetId; + } else if (set.id == Data::Stickers::RecentSetId) { + return !_mySets.empty() && _mySets[0].id == Data::Stickers::FavedSetId; } return true; } bool StickersListWidget::stickerHasDeleteButton(const Set &set, int index) const { - if (set.id == Stickers::RecentSetId) { + if (set.id == Data::Stickers::RecentSetId) { Assert(index >= 0 && index < _custom.size()); return _custom[index]; } - return (set.id == Stickers::FavedSetId); + return (set.id == Data::Stickers::FavedSetId); } void StickersListWidget::setSelected(OverState newSelected) { @@ -2819,7 +2824,7 @@ auto StickersListWidget::getLottieRenderer() void StickersListWidget::showStickerSet(uint64 setId) { clearSelection(); - if (setId == Stickers::FeaturedSetId) { + if (setId == Data::Stickers::FeaturedSetId) { if (_section != Section::Featured) { setSection(Section::Featured); refreshRecentStickers(true); @@ -2903,7 +2908,7 @@ void StickersListWidget::beforeHiding() { } void StickersListWidget::displaySet(uint64 setId) { - if (setId == Stickers::MegagroupSetId) { + if (setId == Data::Stickers::MegagroupSetId) { if (_megagroupSet->canEditStickers()) { _displayingSet = true; checkHideWithBox(Ui::show( @@ -2916,7 +2921,7 @@ void StickersListWidget::displaySet(uint64 setId) { return; } } - const auto &sets = session().data().stickerSets(); + const auto &sets = session().data().stickers().sets(); auto it = sets.find(setId); if (it != sets.cend()) { _displayingSet = true; @@ -2937,7 +2942,7 @@ void StickersListWidget::checkHideWithBox(QPointer box) { } void StickersListWidget::installSet(uint64 setId) { - const auto &sets = session().data().stickerSets(); + const auto &sets = session().data().stickers().sets(); const auto it = sets.find(setId); if (it != sets.cend()) { const auto set = it->second.get(); @@ -2947,7 +2952,7 @@ void StickersListWidget::installSet(uint64 setId) { _api.request(MTPmessages_GetStickerSet( input )).done([=](const MTPmessages_StickerSet &result) { - Stickers::FeedSetFull(result); + session().data().stickers().feedSetFull(result); sendInstallRequest(setId, input); }).send(); } else { @@ -2964,15 +2969,16 @@ void StickersListWidget::sendInstallRequest( MTP_bool(false) )).done([=](const MTPmessages_StickerSetInstallResult &result) { if (result.type() == mtpc_messages_stickerSetInstallResultArchive) { - Stickers::ApplyArchivedResult(result.c_messages_stickerSetInstallResultArchive()); + session().data().stickers().applyArchivedResult( + result.c_messages_stickerSetInstallResultArchive()); } }).fail([=](const RPCError &error) { notInstalledLocally(setId); - Stickers::UndoInstallLocally(setId); + session().data().stickers().undoInstallLocally(setId); }).send(); installedLocally(setId); - Stickers::InstallLocally(setId); + session().data().stickers().installLocally(setId); } void StickersListWidget::removeMegagroupSet(bool locally) { @@ -2982,7 +2988,7 @@ void StickersListWidget::removeMegagroupSet(bool locally) { refreshStickers(); return; } - _removingSetId = Stickers::MegagroupSetId; + _removingSetId = Data::Stickers::MegagroupSetId; Ui::show(Box(tr::lng_stickers_remove_group_set(tr::now), crl::guard(this, [this, group = _megagroupSet] { Expects(group->mgInfo != nullptr); @@ -2999,7 +3005,7 @@ void StickersListWidget::removeMegagroupSet(bool locally) { } void StickersListWidget::removeSet(uint64 setId) { - const auto &sets = session().data().stickerSets(); + const auto &sets = session().data().stickers().sets(); const auto it = sets.find(setId); if (it != sets.cend()) { const auto set = it->second.get(); @@ -3007,7 +3013,7 @@ void StickersListWidget::removeSet(uint64 setId) { auto text = tr::lng_stickers_remove_pack(tr::now, lt_sticker_pack, set->title); Ui::show(Box(text, tr::lng_stickers_remove_pack_confirm(tr::now), crl::guard(this, [=] { Ui::hideLayer(); - const auto &sets = session().data().stickerSets(); + const auto &sets = session().data().stickers().sets(); const auto it = sets.find(_removingSetId); if (it != sets.cend()) { const auto set = it->second.get(); @@ -3017,7 +3023,7 @@ void StickersListWidget::removeSet(uint64 setId) { _api.request(MTPmessages_UninstallStickerSet(MTP_inputStickerSetShortName(MTP_string(set->shortName)))).send(); } auto writeRecent = false; - auto &recent = Stickers::GetRecentPack(); + auto &recent = session().data().stickers().getRecentPack(); for (auto i = recent.begin(); i != recent.cend();) { if (set->stickers.indexOf(i->first) >= 0) { i = recent.erase(i); @@ -3035,8 +3041,8 @@ void StickersListWidget::removeSet(uint64 setId) { // && !(set->flags & MTPDstickerSet_ClientFlag::f_special)) { // sets.erase(it); //} - int removeIndex = session().data().stickerSetsOrder().indexOf(_removingSetId); - if (removeIndex >= 0) session().data().stickerSetsOrderRef().removeAt(removeIndex); + int removeIndex = session().data().stickers().setsOrder().indexOf(_removingSetId); + if (removeIndex >= 0) session().data().stickers().setsOrderRef().removeAt(removeIndex); refreshStickers(); Local::writeInstalledStickers(); if (writeRecent) Local::writeUserSettings(); diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h index 549730d24..8ac39583a 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h +++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h @@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "chat_helpers/tabbed_selector.h" -#include "chat_helpers/stickers.h" +#include "data/stickers/data_stickers.h" #include "base/variant.h" #include "base/timer.h" @@ -34,12 +34,9 @@ class FrameRenderer; namespace Data { class DocumentMedia; +class StickersSet; } // namespace Data -namespace Stickers { -class Set; -} // namespace Stickers - namespace ChatHelpers { struct StickerIcon; @@ -169,7 +166,7 @@ private: struct Set { Set( uint64 id, - Stickers::Set *set, + Data::StickersSet *set, MTPDstickerSet::Flags flags, const QString &title, const QString &shortName, @@ -181,7 +178,7 @@ private: ~Set(); uint64 id = 0; - Stickers::Set *set = nullptr; + Data::StickersSet *set = nullptr; MTPDstickerSet::Flags flags = MTPDstickerSet::Flags(); QString title; QString shortName; @@ -308,7 +305,7 @@ private: void refreshSearchRows(const std::vector *cloudSets); void fillLocalSearchRows(const QString &query); void fillCloudSearchRows(const std::vector &cloudSets); - void addSearchRow(not_null set); + void addSearchRow(not_null set); void showPreview(); diff --git a/Telegram/SourceFiles/chat_helpers/stickers_lottie.cpp b/Telegram/SourceFiles/chat_helpers/stickers_lottie.cpp new file mode 100644 index 000000000..497c9bfa1 --- /dev/null +++ b/Telegram/SourceFiles/chat_helpers/stickers_lottie.cpp @@ -0,0 +1,191 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "chat_helpers/stickers_lottie.h" + +#include "lottie/lottie_single_player.h" +#include "lottie/lottie_multi_player.h" +#include "data/stickers/data_stickers_set.h" +#include "data/data_document.h" +#include "data/data_document_media.h" +#include "data/data_session.h" +#include "data/data_file_origin.h" +#include "storage/cache/storage_cache_database.h" +#include "main/main_session.h" + +namespace ChatHelpers { +namespace { + +constexpr auto kDontCacheLottieAfterArea = 512 * 512; + +} // namespace + +template +auto LottieCachedFromContent( + Method &&method, + Storage::Cache::Key baseKey, + uint8 keyShift, + not_null session, + const QByteArray &content, + QSize box) { + const auto key = Storage::Cache::Key{ + baseKey.high, + baseKey.low + keyShift + }; + const auto get = [=](FnMut handler) { + session->data().cacheBigFile().get( + key, + std::move(handler)); + }; + const auto weak = base::make_weak(session.get()); + const auto put = [=](QByteArray &&cached) { + crl::on_main(weak, [=, data = std::move(cached)]() mutable { + weak->data().cacheBigFile().put(key, std::move(data)); + }); + }; + return method( + get, + put, + content, + Lottie::FrameRequest{ box }); +} + +template +auto LottieFromDocument( + Method &&method, + not_null media, + uint8 keyShift, + QSize box) { + const auto document = media->owner(); + const auto data = media->bytes(); + const auto filepath = document->filepath(); + if (box.width() * box.height() > kDontCacheLottieAfterArea) { + // Don't use frame caching for large stickers. + return method( + Lottie::ReadContent(data, filepath), + Lottie::FrameRequest{ box }); + } + if (const auto baseKey = document->bigFileBaseCacheKey()) { + return LottieCachedFromContent( + std::forward(method), + baseKey, + keyShift, + &document->session(), + Lottie::ReadContent(data, filepath), + box); + } + return method( + Lottie::ReadContent(data, filepath), + Lottie::FrameRequest{ box }); +} + +std::unique_ptr LottiePlayerFromDocument( + not_null media, + StickerLottieSize sizeTag, + QSize box, + Lottie::Quality quality, + std::shared_ptr renderer) { + return LottiePlayerFromDocument( + media, + nullptr, + sizeTag, + box, + quality, + std::move(renderer)); +} + +std::unique_ptr LottiePlayerFromDocument( + not_null media, + const Lottie::ColorReplacements *replacements, + StickerLottieSize sizeTag, + QSize box, + Lottie::Quality quality, + std::shared_ptr renderer) { + const auto method = [&](auto &&...args) { + return std::make_unique( + std::forward(args)..., + quality, + replacements, + std::move(renderer)); + }; + const auto tag = replacements ? replacements->tag : uint8(0); + const auto keyShift = ((tag << 4) & 0xF0) | (uint8(sizeTag) & 0x0F); + return LottieFromDocument(method, media, uint8(keyShift), box); +} + +not_null LottieAnimationFromDocument( + not_null player, + not_null media, + StickerLottieSize sizeTag, + QSize box) { + const auto method = [&](auto &&...args) { + return player->append(std::forward(args)...); + }; + return LottieFromDocument(method, media, uint8(sizeTag), box); +} + +bool HasLottieThumbnail( + Data::StickersSetThumbnailView *thumb, + Data::DocumentMedia *media) { + if (thumb) { + return !thumb->content().isEmpty(); + } else if (!media) { + return false; + } + const auto document = media->owner(); + if (const auto info = document->sticker()) { + if (!info->animated) { + return false; + } + media->automaticLoad(document->stickerSetOrigin(), nullptr); + if (!media->loaded()) { + return false; + } + return document->bigFileBaseCacheKey().valid(); + } + return false; +} + +std::unique_ptr LottieThumbnail( + Data::StickersSetThumbnailView *thumb, + Data::DocumentMedia *media, + StickerLottieSize sizeTag, + QSize box, + std::shared_ptr renderer) { + const auto baseKey = thumb + ? thumb->owner()->thumbnailLocation().file().bigFileBaseCacheKey() + : media + ? media->owner()->bigFileBaseCacheKey() + : Storage::Cache::Key(); + if (!baseKey) { + return nullptr; + } + const auto content = thumb + ? thumb->content() + : Lottie::ReadContent(media->bytes(), media->owner()->filepath()); + if (content.isEmpty()) { + return nullptr; + } + const auto method = [](auto &&...args) { + return std::make_unique( + std::forward(args)...); + }; + const auto session = thumb + ? &thumb->owner()->session() + : media + ? &media->owner()->session() + : nullptr; + return LottieCachedFromContent( + method, + baseKey, + uint8(sizeTag), + session, + content, + box); +} + +} // namespace ChatHelpers diff --git a/Telegram/SourceFiles/chat_helpers/stickers_lottie.h b/Telegram/SourceFiles/chat_helpers/stickers_lottie.h new file mode 100644 index 000000000..43a694e0e --- /dev/null +++ b/Telegram/SourceFiles/chat_helpers/stickers_lottie.h @@ -0,0 +1,74 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +namespace Storage { +namespace Cache { +struct Key; +} // namespace Cache +} // namespace Storage + +namespace Lottie { +class SinglePlayer; +class MultiPlayer; +class FrameRenderer; +class Animation; +enum class Quality : char; +struct ColorReplacements; +} // namespace Lottie + +namespace Main { +class Session; +} // namespace Main + +namespace Data { +class DocumentMedia; +class StickersSetThumbnailView; +} // namespace Data + +namespace ChatHelpers { + +enum class StickerLottieSize : uchar { + MessageHistory, + StickerSet, + StickersPanel, + StickersFooter, + SetsListThumbnail, + InlineResults, +}; + +[[nodiscard]] std::unique_ptr LottiePlayerFromDocument( + not_null media, + StickerLottieSize sizeTag, + QSize box, + Lottie::Quality quality = Lottie::Quality(), + std::shared_ptr renderer = nullptr); +[[nodiscard]] std::unique_ptr LottiePlayerFromDocument( + not_null media, + const Lottie::ColorReplacements *replacements, + StickerLottieSize sizeTag, + QSize box, + Lottie::Quality quality = Lottie::Quality(), + std::shared_ptr renderer = nullptr); +[[nodiscard]] not_null LottieAnimationFromDocument( + not_null player, + not_null media, + StickerLottieSize sizeTag, + QSize box); + +[[nodiscard]] bool HasLottieThumbnail( + Data::StickersSetThumbnailView *thumb, + Data::DocumentMedia *media); +[[nodiscard]] std::unique_ptr LottieThumbnail( + Data::StickersSetThumbnailView *thumb, + Data::DocumentMedia *media, + StickerLottieSize sizeTag, + QSize box, + std::shared_ptr renderer = nullptr); + +} // namespace ChatHelpers diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp index 4a6c50e58..3185964a4 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp +++ b/Telegram/SourceFiles/chat_helpers/tabbed_selector.cpp @@ -10,7 +10,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "chat_helpers/emoji_list_widget.h" #include "chat_helpers/stickers_list_widget.h" #include "chat_helpers/gifs_list_widget.h" -#include "chat_helpers/stickers.h" #include "ui/widgets/buttons.h" #include "ui/widgets/labels.h" #include "ui/widgets/shadow.h" @@ -21,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/localstorage.h" #include "data/data_channel.h" #include "data/data_session.h" +#include "data/stickers/data_stickers.h" #include "lang/lang_keys.h" #include "mainwindow.h" #include "observer_peer.h" @@ -366,7 +366,7 @@ TabbedSelector::TabbedSelector( _showRequests.fire({}); }, lifetime()); - session().data().stickersUpdated( + session().data().stickers().updated( ) | rpl::start_with_next([=] { refreshStickers(); }, lifetime()); diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp index ebab26a36..e7d4f40cc 100644 --- a/Telegram/SourceFiles/data/data_document.cpp +++ b/Telegram/SourceFiles/data/data_document.cpp @@ -17,8 +17,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "mainwidget.h" #include "core/file_utilities.h" #include "core/mime_type.h" -#include "chat_helpers/stickers.h" -#include "chat_helpers/stickers_set.h" +#include "data/stickers/data_stickers.h" +#include "data/stickers/data_stickers_set.h" #include "media/audio/media_audio.h" #include "media/player/media_player_instance.h" #include "media/streaming/media_streaming_loader_mtproto.h" @@ -1208,7 +1208,7 @@ bool DocumentData::saveFromDataChecked() { bool DocumentData::isStickerSetInstalled() const { Expects(sticker() != nullptr); - const auto &sets = _owner->stickerSets(); + const auto &sets = _owner->stickers().sets(); return sticker()->set.match([&](const MTPDinputStickerSetID &data) { const auto i = sets.find(data.vid().v); return (i != sets.cend()) @@ -1251,8 +1251,8 @@ Data::FileOrigin DocumentData::stickerSetOrigin() const { if (const auto data = sticker()) { if (const auto result = data->setOrigin()) { return result; - } else if (Stickers::IsFaved(this)) { - return Data::FileOriginStickerSet(Stickers::FavedSetId, 0); + } else if (owner().stickers().isFaved(this)) { + return Data::FileOriginStickerSet(Data::Stickers::FavedSetId, 0); } } return Data::FileOrigin(); diff --git a/Telegram/SourceFiles/data/data_session.cpp b/Telegram/SourceFiles/data/data_session.cpp index 4435f15fd..10c3e768b 100644 --- a/Telegram/SourceFiles/data/data_session.cpp +++ b/Telegram/SourceFiles/data/data_session.cpp @@ -33,6 +33,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "passport/passport_form_controller.h" #include "window/themes/window_theme.h" #include "lang/lang_keys.h" // tr::lng_deleted(tr::now) in user name +#include "data/stickers/data_stickers.h" #include "data/data_media_types.h" #include "data/data_folder.h" #include "data/data_channel.h" @@ -222,7 +223,8 @@ Session::Session(not_null session) , _cloudThemes(std::make_unique(session)) , _streaming(std::make_unique(this)) , _mediaRotation(std::make_unique()) -, _histories(std::make_unique(this)) { +, _histories(std::make_unique(this)) +, _stickers(std::make_unique(this)) { _cache->open(Local::cacheKey()); _bigFileCache->open(Local::cacheBigFileKey()); @@ -1378,6 +1380,14 @@ void Session::sendHistoryChangeNotifications() { } } +void Session::notifyPinnedDialogsOrderUpdated() { + _pinnedDialogsOrderUpdated.fire({}); +} + +rpl::producer<> Session::pinnedDialogsOrderUpdated() const { + return _pinnedDialogsOrderUpdated.events(); +} + void Session::registerHeavyViewPart(not_null view) { _heavyViewParts.emplace(view); } @@ -1473,38 +1483,6 @@ rpl::producer> Session::megagroupParticipantAdded( }); } -void Session::notifyStickersUpdated() { - _stickersUpdated.fire({}); -} - -rpl::producer<> Session::stickersUpdated() const { - return _stickersUpdated.events(); -} - -void Session::notifyRecentStickersUpdated() { - _recentStickersUpdated.fire({}); -} - -rpl::producer<> Session::recentStickersUpdated() const { - return _recentStickersUpdated.events(); -} - -void Session::notifySavedGifsUpdated() { - _savedGifsUpdated.fire({}); -} - -rpl::producer<> Session::savedGifsUpdated() const { - return _savedGifsUpdated.events(); -} - -void Session::notifyPinnedDialogsOrderUpdated() { - _pinnedDialogsOrderUpdated.fire({}); -} - -rpl::producer<> Session::pinnedDialogsOrderUpdated() const { - return _pinnedDialogsOrderUpdated.events(); -} - void Session::userIsContactUpdated(not_null user) { const auto i = _contactViews.find(peerToUser(user->id)); if (i != _contactViews.end()) { @@ -1716,7 +1694,7 @@ bool Session::checkEntitiesAndViewsUpdate(const MTPDmessage &data) { requestItemTextRefresh(existing); updateDependentMessages(existing); if (existing->mainView()) { - checkSavedGif(existing); + stickers().checkSavedGif(existing); return true; } return false; @@ -1724,40 +1702,6 @@ bool Session::checkEntitiesAndViewsUpdate(const MTPDmessage &data) { return false; } -void Session::addSavedGif(not_null document) { - const auto index = _savedGifs.indexOf(document); - if (!index) { - return; - } - if (index > 0) { - _savedGifs.remove(index); - } - _savedGifs.push_front(document); - if (_savedGifs.size() > Global::SavedGifsLimit()) { - _savedGifs.pop_back(); - } - Local::writeSavedGifs(); - - notifySavedGifsUpdated(); - setLastSavedGifsUpdate(0); - session().api().updateStickers(); -} - -void Session::checkSavedGif(not_null item) { - if (item->Has() - || (!item->out() - && item->history()->peer != session().user())) { - return; - } - if (const auto media = item->media()) { - if (const auto document = media->document()) { - if (document->isGifv()) { - addSavedGif(document); - } - } - } -} - void Session::updateEditedMessage(const MTPMessage &data) { const auto existing = data.match([](const MTPDmessageEmpty &) -> HistoryItem* { @@ -2488,7 +2432,7 @@ void Session::documentConvert( if (idChanged) { cache().moveIfEmpty(oldCacheKey, original->cacheKey()); cache().moveIfEmpty(oldGoodKey, original->goodThumbnailCacheKey()); - if (savedGifs().indexOf(original) >= 0) { + if (stickers().savedGifs().indexOf(original) >= 0) { Local::writeSavedGifs(); } } diff --git a/Telegram/SourceFiles/data/data_session.h b/Telegram/SourceFiles/data/data_session.h index 33629cd9a..012a53978 100644 --- a/Telegram/SourceFiles/data/data_session.h +++ b/Telegram/SourceFiles/data/data_session.h @@ -8,11 +8,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "storage/storage_databases.h" -#include "chat_helpers/stickers_set.h" #include "dialogs/dialogs_key.h" #include "dialogs/dialogs_indexed_list.h" #include "dialogs/dialogs_main_list.h" #include "data/data_groups.h" +#include "data/data_cloud_file.h" #include "data/data_notify_settings.h" #include "history/history_location_manager.h" #include "base/timer.h" @@ -65,6 +65,7 @@ class MediaRotation; class Histories; class DocumentMedia; class PhotoMedia; +class Stickers; class Session final { public: @@ -106,6 +107,9 @@ public: [[nodiscard]] Histories &histories() const { return *_histories; } + [[nodiscard]] Stickers &stickers() const { + return *_stickers; + } [[nodiscard]] MsgId nextNonHistoryEntryId() { return ++_nonHistoryEntryId; } @@ -240,6 +244,9 @@ public: [[nodiscard]] rpl::producer> historyChanged() const; void sendHistoryChangeNotifications(); + void notifyPinnedDialogsOrderUpdated(); + [[nodiscard]] rpl::producer<> pinnedDialogsOrderUpdated() const; + void registerHeavyViewPart(not_null view); void unregisterHeavyViewPart(not_null view); void unloadHeavyViewParts( @@ -265,91 +272,6 @@ public: [[nodiscard]] rpl::producer> megagroupParticipantAdded( not_null channel) const; - void notifyStickersUpdated(); - [[nodiscard]] rpl::producer<> stickersUpdated() const; - void notifyRecentStickersUpdated(); - [[nodiscard]] rpl::producer<> recentStickersUpdated() const; - void notifySavedGifsUpdated(); - [[nodiscard]] rpl::producer<> savedGifsUpdated() const; - void notifyPinnedDialogsOrderUpdated(); - [[nodiscard]] rpl::producer<> pinnedDialogsOrderUpdated() const; - - bool stickersUpdateNeeded(crl::time now) const { - return stickersUpdateNeeded(_lastStickersUpdate, now); - } - void setLastStickersUpdate(crl::time update) { - _lastStickersUpdate = update; - } - bool recentStickersUpdateNeeded(crl::time now) const { - return stickersUpdateNeeded(_lastRecentStickersUpdate, now); - } - void setLastRecentStickersUpdate(crl::time update) { - if (update) { - notifyRecentStickersUpdated(); - } - _lastRecentStickersUpdate = update; - } - bool favedStickersUpdateNeeded(crl::time now) const { - return stickersUpdateNeeded(_lastFavedStickersUpdate, now); - } - void setLastFavedStickersUpdate(crl::time update) { - _lastFavedStickersUpdate = update; - } - bool featuredStickersUpdateNeeded(crl::time now) const { - return stickersUpdateNeeded(_lastFeaturedStickersUpdate, now); - } - void setLastFeaturedStickersUpdate(crl::time update) { - _lastFeaturedStickersUpdate = update; - } - bool savedGifsUpdateNeeded(crl::time now) const { - return stickersUpdateNeeded(_lastSavedGifsUpdate, now); - } - void setLastSavedGifsUpdate(crl::time update) { - _lastSavedGifsUpdate = update; - } - int featuredStickerSetsUnreadCount() const { - return _featuredStickerSetsUnreadCount.current(); - } - void setFeaturedStickerSetsUnreadCount(int count) { - _featuredStickerSetsUnreadCount = count; - } - [[nodiscard]] rpl::producer featuredStickerSetsUnreadCountValue() const { - return _featuredStickerSetsUnreadCount.value(); - } - const Stickers::Sets &stickerSets() const { - return _stickerSets; - } - Stickers::Sets &stickerSetsRef() { - return _stickerSets; - } - const Stickers::Order &stickerSetsOrder() const { - return _stickerSetsOrder; - } - Stickers::Order &stickerSetsOrderRef() { - return _stickerSetsOrder; - } - const Stickers::Order &featuredStickerSetsOrder() const { - return _featuredStickerSetsOrder; - } - Stickers::Order &featuredStickerSetsOrderRef() { - return _featuredStickerSetsOrder; - } - const Stickers::Order &archivedStickerSetsOrder() const { - return _archivedStickerSetsOrder; - } - Stickers::Order &archivedStickerSetsOrderRef() { - return _archivedStickerSetsOrder; - } - const Stickers::SavedGifs &savedGifs() const { - return _savedGifs; - } - Stickers::SavedGifs &savedGifsRef() { - return _savedGifs; - } - - void addSavedGif(not_null document); - void checkSavedGif(not_null item); - HistoryItemsList idsToItems(const MessageIdsList &ids) const; MessageIdsList itemsToIds(const HistoryItemsList &items) const; MessageIdsList itemOrItsGroup(not_null item) const; @@ -808,11 +730,6 @@ private: not_null folder, const MTPDfolder &data); - bool stickersUpdateNeeded(crl::time lastUpdate, crl::time now) const { - constexpr auto kStickersUpdateTimeout = crl::time(3600'000); - return (lastUpdate == 0) - || (now >= lastUpdate + kStickersUpdateTimeout); - } void userIsContactUpdated(not_null user); void setPinnedFromDialog(const Dialogs::Key &key, bool pinned); @@ -876,22 +793,6 @@ private: rpl::event_stream _megagroupParticipantAdded; rpl::event_stream _dialogsRowReplacements; - rpl::event_stream<> _stickersUpdated; - rpl::event_stream<> _recentStickersUpdated; - rpl::event_stream<> _savedGifsUpdated; - rpl::event_stream<> _pinnedDialogsOrderUpdated; - crl::time _lastStickersUpdate = 0; - crl::time _lastRecentStickersUpdate = 0; - crl::time _lastFavedStickersUpdate = 0; - crl::time _lastFeaturedStickersUpdate = 0; - crl::time _lastSavedGifsUpdate = 0; - rpl::variable _featuredStickerSetsUnreadCount = 0; - Stickers::Sets _stickerSets; - Stickers::Order _stickerSetsOrder; - Stickers::Order _featuredStickerSetsOrder; - Stickers::Order _archivedStickerSetsOrder; - Stickers::SavedGifs _savedGifs; - Dialogs::MainList _chatsList; Dialogs::IndexedList _contactsList; Dialogs::IndexedList _contactsNoChatsList; @@ -970,6 +871,8 @@ private: not_null, std::vector>> _views; + rpl::event_stream<> _pinnedDialogsOrderUpdated; + base::flat_set> _heavyViewParts; PeerData *_topPromoted = nullptr; @@ -1006,6 +909,7 @@ private: std::unique_ptr _streaming; std::unique_ptr _mediaRotation; std::unique_ptr _histories; + std::unique_ptr _stickers; MsgId _nonHistoryEntryId = ServerMaxMsgId; rpl::lifetime _lifetime; diff --git a/Telegram/SourceFiles/chat_helpers/stickers.cpp b/Telegram/SourceFiles/data/stickers/data_stickers.cpp similarity index 71% rename from Telegram/SourceFiles/chat_helpers/stickers.cpp rename to Telegram/SourceFiles/data/stickers/data_stickers.cpp index b7e2a7cb7..adc0358fd 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers.cpp +++ b/Telegram/SourceFiles/data/stickers/data_stickers.cpp @@ -5,42 +5,101 @@ the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ -#include "chat_helpers/stickers.h" +#include "data/stickers/data_stickers.h" #include "data/data_document.h" -#include "data/data_document_media.h" #include "data/data_session.h" -#include "data/data_file_origin.h" -#include "chat_helpers/stickers_set.h" -#include "boxes/stickers_box.h" +#include "data/data_user.h" #include "boxes/confirm_box.h" #include "lang/lang_keys.h" +#include "history/history.h" +#include "history/history_item.h" +#include "history/history_item_components.h" #include "apiwrap.h" #include "storage/localstorage.h" -#include "mainwidget.h" #include "main/main_session.h" -#include "mainwindow.h" #include "ui/toast/toast.h" -#include "ui/emoji_config.h" #include "ui/image/image_location_factory.h" #include "base/unixtime.h" -#include "lottie/lottie_single_player.h" -#include "lottie/lottie_multi_player.h" #include "facades.h" -#include "app.h" #include "styles/style_chat_helpers.h" -namespace Stickers { -namespace { +namespace Data { -constexpr auto kDontCacheLottieAfterArea = 512 * 512; +Stickers::Stickers(not_null owner) : _owner(owner) { +} -} // namespace +Session &Stickers::owner() const { + return *_owner; +} -void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) { +Main::Session &Stickers::session() const { + return _owner->session(); +} + +void Stickers::notifyUpdated() { + _updated.fire({}); +} + +rpl::producer<> Stickers::updated() const { + return _updated.events(); +} + +void Stickers::notifyRecentUpdated() { + _recentUpdated.fire({}); +} + +rpl::producer<> Stickers::recentUpdated() const { + return _recentUpdated.events(); +} + +void Stickers::notifySavedGifsUpdated() { + _savedGifsUpdated.fire({}); +} + +rpl::producer<> Stickers::savedGifsUpdated() const { + return _savedGifsUpdated.events(); +} + +void Stickers::addSavedGif(not_null document) { + const auto index = _savedGifs.indexOf(document); + if (!index) { + return; + } + if (index > 0) { + _savedGifs.remove(index); + } + _savedGifs.push_front(document); + if (_savedGifs.size() > Global::SavedGifsLimit()) { + _savedGifs.pop_back(); + } + Local::writeSavedGifs(); + + notifySavedGifsUpdated(); + setLastSavedGifsUpdate(0); + session().api().updateStickers(); +} + +void Stickers::checkSavedGif(not_null item) { + if (item->Has() + || (!item->out() + && item->history()->peer != session().user())) { + return; + } + if (const auto media = item->media()) { + if (const auto document = media->document()) { + if (document->isGifv()) { + addSavedGif(document); + } + } + } +} + +void Stickers::applyArchivedResult( + const MTPDmessages_stickerSetInstallResultArchive &d) { auto &v = d.vsets().v; - auto &order = Auth().data().stickerSetsOrderRef(); - Order archived; + auto &order = setsOrderRef(); + StickersSetsOrder archived; archived.reserve(v.size()); QMap setsToRequest; for (const auto &stickerSet : v) { @@ -60,7 +119,7 @@ void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) { } break; } if (setData) { - auto set = FeedSet(*setData); + auto set = feedSet(*setData); if (set->stickers.isEmpty()) { setsToRequest.insert(set->id, set->access); } @@ -73,9 +132,9 @@ void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) { } if (!setsToRequest.isEmpty()) { for (auto i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) { - Auth().api().scheduleStickerSetRequest(i.key(), i.value()); + session().api().scheduleStickerSetRequest(i.key(), i.value()); } - Auth().api().requestStickerSets(); + session().api().requestStickerSets(); } Local::writeInstalledStickers(); Local::writeArchivedStickers(); @@ -85,15 +144,17 @@ void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) { .st = &st::stickersToast, .multiline = true, }); -// Ui::show(Box(archived, &Auth()), Ui::LayerOption::KeepOther); + //Ui::show( + // Box(archived, &session()), + // Ui::LayerOption::KeepOther); - Auth().data().notifyStickersUpdated(); + notifyUpdated(); } // For testing: Just apply random subset or your sticker sets as archived. -bool ApplyArchivedResultFake() { +bool Stickers::applyArchivedResultFake() { auto sets = QVector(); - for (const auto &[id, set] : Auth().data().stickerSets()) { + for (const auto &[id, set] : this->sets()) { const auto raw = set.get(); if ((raw->flags & MTPDstickerSet::Flag::f_installed_date) && !(raw->flags & MTPDstickerSet_ClientFlag::f_special)) { @@ -118,14 +179,14 @@ bool ApplyArchivedResultFake() { if (sets.size() > 3) { sets = sets.mid(0, 3); } - auto fakeResult = MTP_messages_stickerSetInstallResultArchive( + auto result = MTP_messages_stickerSetInstallResultArchive( MTP_vector(sets)); - ApplyArchivedResult(fakeResult.c_messages_stickerSetInstallResultArchive()); + applyArchivedResult(result.c_messages_stickerSetInstallResultArchive()); return true; } -void InstallLocally(uint64 setId) { - auto &sets = Auth().data().stickerSetsRef(); +void Stickers::installLocally(uint64 setId) { + auto &sets = setsRef(); auto it = sets.find(setId); if (it == sets.end()) { return; @@ -138,7 +199,7 @@ void InstallLocally(uint64 setId) { set->installDate = base::unixtime::now(); auto changedFlags = flags ^ set->flags; - auto &order = Auth().data().stickerSetsOrderRef(); + auto &order = setsOrderRef(); int insertAtIndex = 0, currentIndex = order.indexOf(setId); if (currentIndex != insertAtIndex) { if (currentIndex > 0) { @@ -163,17 +224,17 @@ void InstallLocally(uint64 setId) { Local::writeFeaturedStickers(); } if (changedFlags & MTPDstickerSet::Flag::f_archived) { - auto index = Auth().data().archivedStickerSetsOrderRef().indexOf(setId); + auto index = archivedSetsOrderRef().indexOf(setId); if (index >= 0) { - Auth().data().archivedStickerSetsOrderRef().removeAt(index); + archivedSetsOrderRef().removeAt(index); Local::writeArchivedStickers(); } } - Auth().data().notifyStickersUpdated(); + notifyUpdated(); } -void UndoInstallLocally(uint64 setId) { - const auto &sets = Auth().data().stickerSets(); +void Stickers::undoInstallLocally(uint64 setId) { + const auto &sets = this->sets(); const auto it = sets.find(setId); if (it == sets.end()) { return; @@ -183,22 +244,22 @@ void UndoInstallLocally(uint64 setId) { set->flags &= ~MTPDstickerSet::Flag::f_installed_date; set->installDate = TimeId(0); - auto &order = Auth().data().stickerSetsOrderRef(); + auto &order = setsOrderRef(); int currentIndex = order.indexOf(setId); if (currentIndex >= 0) { order.removeAt(currentIndex); } Local::writeInstalledStickers(); - Auth().data().notifyStickersUpdated(); + notifyUpdated(); Ui::show( Box(tr::lng_stickers_not_found(tr::now)), Ui::LayerOption::KeepOther); } -bool IsFaved(not_null document) { - const auto &sets = Auth().data().stickerSets(); +bool Stickers::isFaved(not_null document) { + const auto &sets = this->sets(); const auto it = sets.find(FavedSetId); if (it == sets.cend()) { return false; @@ -211,7 +272,7 @@ bool IsFaved(not_null document) { return false; } -void CheckFavedLimit(Set &set) { +void Stickers::checkFavedLimit(StickersSet &set) { if (set.stickers.size() <= Global::StickersFavedLimit()) { return; } @@ -230,19 +291,20 @@ void CheckFavedLimit(Set &set) { } } -void PushFavedToFront( - Set &set, +void Stickers::pushFavedToFront( + StickersSet &set, not_null document, const std::vector> &emojiList) { set.stickers.push_front(document); for (auto emoji : emojiList) { set.emoji[emoji].push_front(document); } - CheckFavedLimit(set); + checkFavedLimit(set); } -void MoveFavedToFront(Set &set, int index) { +void Stickers::moveFavedToFront(StickersSet &set, int index) { Expects(index > 0 && index < set.stickers.size()); + auto document = set.stickers[index]; while (index-- != 0) { set.stickers[index + 1] = set.stickers[index]; @@ -259,15 +321,13 @@ void MoveFavedToFront(Set &set, int index) { } } -void RequestSetToPushFaved(not_null document); - -void SetIsFaved( +void Stickers::setIsFaved( not_null document, - std::optional>> emojiList = std::nullopt) { - auto &sets = document->owner().stickerSetsRef(); + std::optional>> emojiList) { + auto &sets = setsRef(); auto it = sets.find(FavedSetId); if (it == sets.end()) { - it = sets.emplace(FavedSetId, std::make_unique( + it = sets.emplace(FavedSetId, std::make_unique( &document->owner(), FavedSetId, uint64(0), @@ -284,22 +344,22 @@ void SetIsFaved( return; } if (index > 0) { - MoveFavedToFront(*set, index); + moveFavedToFront(*set, index); } else if (emojiList) { - PushFavedToFront(*set, document, *emojiList); - } else if (auto list = GetEmojiListFromSet(document)) { - PushFavedToFront(*set, document, *list); + pushFavedToFront(*set, document, *emojiList); + } else if (auto list = getEmojiListFromSet(document)) { + pushFavedToFront(*set, document, *list); } else { - RequestSetToPushFaved(document); + requestSetToPushFaved(document); return; } Local::writeFavedStickers(); - Auth().data().notifyStickersUpdated(); - Auth().api().stickerSetInstalled(FavedSetId); + notifyUpdated(); + session().api().stickerSetInstalled(FavedSetId); } -void RequestSetToPushFaved(not_null document) { - auto addAnyway = [document](std::vector> list) { +void Stickers::requestSetToPushFaved(not_null document) { + auto addAnyway = [=](std::vector> list) { if (list.empty()) { if (auto sticker = document->sticker()) { if (auto emoji = Ui::Emoji::Find(sticker->alt)) { @@ -307,10 +367,11 @@ void RequestSetToPushFaved(not_null document) { } } } - SetIsFaved(document, std::move(list)); + setIsFaved(document, std::move(list)); }; - MTP::send(MTPmessages_GetStickerSet(document->sticker()->set), rpcDone([document, addAnyway](const MTPmessages_StickerSet &result) { + MTP::send(MTPmessages_GetStickerSet(document->sticker()->set), rpcDone([=](const MTPmessages_StickerSet &result) { Expects(result.type() == mtpc_messages_stickerSet); + auto list = std::vector>(); auto &d = result.c_messages_stickerSet(); list.reserve(d.vpacks().v.size()); @@ -336,8 +397,8 @@ void RequestSetToPushFaved(not_null document) { })); } -void SetIsNotFaved(not_null document) { - auto &sets = Auth().data().stickerSetsRef(); +void Stickers::setIsNotFaved(not_null document) { + auto &sets = setsRef(); auto it = sets.find(FavedSetId); if (it == sets.end()) { return; @@ -363,22 +424,22 @@ void SetIsNotFaved(not_null document) { sets.erase(it); } Local::writeFavedStickers(); - Auth().data().notifyStickersUpdated(); + notifyUpdated(); } -void SetFaved(not_null document, bool faved) { +void Stickers::setFaved(not_null document, bool faved) { if (faved) { - SetIsFaved(document); + setIsFaved(document); } else { - SetIsNotFaved(document); + setIsNotFaved(document); } } -void SetsReceived(const QVector &data, int32 hash) { - auto &setsOrder = Auth().data().stickerSetsOrderRef(); +void Stickers::setsReceived(const QVector &data, int32 hash) { + auto &setsOrder = setsOrderRef(); setsOrder.clear(); - auto &sets = Auth().data().stickerSetsRef(); + auto &sets = setsRef(); QMap setsToRequest; for (auto &[id, set] : sets) { if (!(set->flags & MTPDstickerSet::Flag::f_archived)) { @@ -389,7 +450,7 @@ void SetsReceived(const QVector &data, int32 hash) { } for (const auto &setData : data) { if (setData.type() == mtpc_stickerSet) { - auto set = FeedSet(setData.c_stickerSet()); + auto set = 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)) { @@ -399,7 +460,7 @@ void SetsReceived(const QVector &data, int32 hash) { } } auto writeRecent = false; - auto &recent = GetRecentPack(); + auto &recent = getRecentPack(); for (auto it = sets.begin(); it != sets.end();) { const auto set = it->second.get(); bool installed = (set->flags & MTPDstickerSet::Flag::f_installed_date); @@ -424,7 +485,7 @@ void SetsReceived(const QVector &data, int32 hash) { } if (!setsToRequest.isEmpty()) { - auto &api = Auth().api(); + auto &api = session().api(); for (auto i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) { api.scheduleStickerSetRequest(i.key(), i.value()); } @@ -438,12 +499,12 @@ void SetsReceived(const QVector &data, int32 hash) { LOG(("API Error: received stickers hash %1 while counted hash is %2").arg(hash).arg(Local::countStickersHash())); } - Auth().data().notifyStickersUpdated(); + notifyUpdated(); } -void SetPackAndEmoji( - Set &set, - Pack &&pack, +void Stickers::setPackAndEmoji( + StickersSet &set, + StickersPack &&pack, const std::vector &&dates, const QVector &packs) { set.stickers = std::move(pack); @@ -456,10 +517,10 @@ void SetPackAndEmoji( emoji = emoji->original(); auto &stickers = pack.vdocuments().v; - auto p = Pack(); + auto p = StickersPack(); p.reserve(stickers.size()); for (auto j = 0, c = stickers.size(); j != c; ++j) { - auto document = Auth().data().document(stickers[j].v); + auto document = owner().document(stickers[j].v); if (!document || !document->sticker()) continue; p.push_back(document); @@ -469,14 +530,14 @@ void SetPackAndEmoji( } } -void SpecialSetReceived( +void Stickers::specialSetReceived( uint64 setId, const QString &setTitle, const QVector &items, int32 hash, const QVector &packs, const QVector &usageDates) { - auto &sets = Auth().data().stickerSetsRef(); + auto &sets = setsRef(); auto it = sets.find(setId); if (items.isEmpty()) { @@ -485,8 +546,8 @@ void SpecialSetReceived( } } else { if (it == sets.cend()) { - it = sets.emplace(setId, std::make_unique( - &Auth().data(), + it = sets.emplace(setId, std::make_unique( + &owner(), setId, uint64(0), setTitle, @@ -507,11 +568,11 @@ void SpecialSetReceived( && (setId == CloudRecentSetId); auto customIt = sets.find(CustomSetId); - auto pack = Pack(); + auto pack = StickersPack(); pack.reserve(items.size()); for (const auto &item : items) { ++dateIndex; - const auto document = Auth().data().processDocument(item); + const auto document = owner().processDocument(item); if (!document->sticker()) { continue; } @@ -535,7 +596,7 @@ void SpecialSetReceived( } auto writeRecent = false; - auto &recent = GetRecentPack(); + auto &recent = getRecentPack(); for (auto i = recent.begin(); i != recent.cend();) { if (set->stickers.indexOf(i->first) >= 0 && pack.indexOf(i->first) < 0) { i = recent.erase(i); @@ -548,7 +609,7 @@ void SpecialSetReceived( if (pack.isEmpty()) { sets.erase(it); } else { - SetPackAndEmoji(*set, std::move(pack), std::move(dates), packs); + setPackAndEmoji(*set, std::move(pack), std::move(dates), packs); } if (writeRecent) { @@ -572,10 +633,10 @@ void SpecialSetReceived( default: Unexpected("setId in SpecialSetReceived()"); } - Auth().data().notifyStickersUpdated(); + notifyUpdated(); } -void FeaturedSetsReceived( +void Stickers::featuredSetsReceived( const QVector &list, const QVector &unread, int32 hash) { @@ -589,10 +650,10 @@ void FeaturedSetsReceived( unreadIds.end() }; - auto &setsOrder = Auth().data().featuredStickerSetsOrderRef(); + auto &setsOrder = featuredSetsOrderRef(); setsOrder.clear(); - auto &sets = Auth().data().stickerSetsRef(); + auto &sets = setsRef(); auto setsToRequest = base::flat_map(); for (auto &[id, set] : sets) { // Mark for removing. @@ -605,11 +666,11 @@ void FeaturedSetsReceived( }); }); auto it = sets.find(data->vid().v); - const auto title = GetSetTitle(*data); + const auto title = getSetTitle(*data); const auto installDate = data->vinstalled_date().value_or_empty(); const auto thumb = data->vthumb(); const auto thumbnail = thumb - ? Images::FromPhotoSize(&Auth(), *data, *thumb) + ? Images::FromPhotoSize(&session(), *data, *thumb) : ImageWithLocation(); if (it == sets.cend()) { auto setClientFlags = MTPDstickerSet_ClientFlag::f_featured @@ -617,8 +678,8 @@ void FeaturedSetsReceived( if (unreadMap.contains(data->vid().v)) { setClientFlags |= MTPDstickerSet_ClientFlag::f_unread; } - it = sets.emplace(data->vid().v, std::make_unique( - &Auth().data(), + it = sets.emplace(data->vid().v, std::make_unique( + &owner(), data->vid().v, data->vaccess_hash().v, title, @@ -672,14 +733,14 @@ void FeaturedSetsReceived( it = sets.erase(it); } } - Auth().data().setFeaturedStickerSetsUnreadCount(unreadCount); + setFeaturedSetsUnreadCount(unreadCount); if (Local::countFeaturedStickersHash() != hash) { LOG(("API Error: received featured stickers hash %1 while counted hash is %2").arg(hash).arg(Local::countFeaturedStickersHash())); } if (!setsToRequest.empty()) { - auto &api = Auth().api(); + auto &api = session().api(); for (const auto [setId, accessHash] : setsToRequest) { api.scheduleStickerSetRequest(setId, accessHash); } @@ -688,16 +749,16 @@ void FeaturedSetsReceived( Local::writeFeaturedStickers(); - Auth().data().notifyStickersUpdated(); + notifyUpdated(); } -void GifsReceived(const QVector &items, int32 hash) { - auto &saved = Auth().data().savedGifsRef(); +void Stickers::gifsReceived(const QVector &items, int32 hash) { + auto &saved = savedGifsRef(); saved.clear(); saved.reserve(items.size()); for (const auto &item : items) { - const auto document = Auth().data().processDocument(item); + const auto document = owner().processDocument(item); if (!document->isGifv()) { LOG(("API Error: " "bad document returned in HistoryWidget::savedGifsGot!")); @@ -712,11 +773,10 @@ void GifsReceived(const QVector &items, int32 hash) { Local::writeSavedGifs(); - Auth().data().notifySavedGifsUpdated(); + notifySavedGifsUpdated(); } -std::vector> GetListByEmoji( - not_null session, +std::vector> Stickers::getListByEmoji( not_null emoji, uint64 seed) { const auto original = emoji->original(); @@ -726,7 +786,7 @@ std::vector> GetListByEmoji( TimeId date = 0; }; auto result = std::vector(); - auto &sets = session->data().stickerSetsRef(); + auto &sets = setsRef(); auto setsToRequest = base::flat_map(); const auto add = [&](not_null document, TimeId date) { @@ -811,7 +871,9 @@ std::vector> GetListByEmoji( } } } - const auto addList = [&](const Order &order, MTPDstickerSet::Flag skip) { + const auto addList = [&]( + const StickersSetsOrder &order, + MTPDstickerSet::Flag skip) { for (const auto setId : order) { auto it = sets.find(setId); if (it == sets.cend() || (it->second->flags & skip)) { @@ -842,21 +904,21 @@ std::vector> GetListByEmoji( }; addList( - session->data().stickerSetsOrder(), + setsOrder(), MTPDstickerSet::Flag::f_archived); //addList( - // session->data().featuredStickerSetsOrder(), + // featuredSetsOrder(), // MTPDstickerSet::Flag::f_installed_date); if (!setsToRequest.empty()) { for (const auto &[setId, accessHash] : setsToRequest) { - session->api().scheduleStickerSetRequest(setId, accessHash); + session().api().scheduleStickerSetRequest(setId, accessHash); } - session->api().requestStickerSets(); + session().api().requestStickerSets(); } - if (session->settings().suggestStickersByEmoji()) { - const auto others = session->api().stickersByEmoji(original); + if (session().settings().suggestStickersByEmoji()) { + const auto others = session().api().stickersByEmoji(original); if (!others) { return {}; } @@ -878,14 +940,14 @@ std::vector> GetListByEmoji( }) | ranges::to_vector; } -std::optional>> GetEmojiListFromSet( +std::optional>> Stickers::getEmojiListFromSet( not_null document) { if (auto sticker = document->sticker()) { auto &inputSet = sticker->set; if (inputSet.type() != mtpc_inputStickerSetID) { return std::nullopt; } - const auto &sets = Auth().data().stickerSets(); + const auto &sets = this->sets(); auto it = sets.find(inputSet.c_inputStickerSetID().vid().v); if (it == sets.cend()) { return std::nullopt; @@ -905,18 +967,18 @@ std::optional>> GetEmojiListFromSet( return std::nullopt; } -Set *FeedSet(const MTPDstickerSet &data) { - auto &sets = Auth().data().stickerSetsRef(); +StickersSet *Stickers::feedSet(const MTPDstickerSet &data) { + auto &sets = setsRef(); auto it = sets.find(data.vid().v); - auto title = GetSetTitle(data); + auto title = getSetTitle(data); auto flags = MTPDstickerSet::Flags(0); const auto thumb = data.vthumb(); const auto thumbnail = thumb - ? Images::FromPhotoSize(&Auth(), data, *thumb) + ? Images::FromPhotoSize(&session(), data, *thumb) : ImageWithLocation(); if (it == sets.cend()) { - it = sets.emplace(data.vid().v, std::make_unique( - &Auth().data(), + it = sets.emplace(data.vid().v, std::make_unique( + &owner(), data.vid().v, data.vaccess_hash().v, title, @@ -955,33 +1017,33 @@ Set *FeedSet(const MTPDstickerSet &data) { const auto set = it->second.get(); auto changedFlags = (flags ^ set->flags); if (changedFlags & MTPDstickerSet::Flag::f_archived) { - auto index = Auth().data().archivedStickerSetsOrder().indexOf(set->id); + auto index = archivedSetsOrder().indexOf(set->id); if (set->flags & MTPDstickerSet::Flag::f_archived) { if (index < 0) { - Auth().data().archivedStickerSetsOrderRef().push_front(set->id); + archivedSetsOrderRef().push_front(set->id); } } else if (index >= 0) { - Auth().data().archivedStickerSetsOrderRef().removeAt(index); + archivedSetsOrderRef().removeAt(index); } } return it->second.get(); } -Set *FeedSetFull(const MTPmessages_StickerSet &data) { +StickersSet *Stickers::feedSetFull(const MTPmessages_StickerSet &data) { Expects(data.type() == mtpc_messages_stickerSet); Expects(data.c_messages_stickerSet().vset().type() == mtpc_stickerSet); const auto &d = data.c_messages_stickerSet(); const auto &s = d.vset().c_stickerSet(); - auto &sets = Auth().data().stickerSetsRef(); + auto &sets = setsRef(); const auto wasArchived = [&] { auto it = sets.find(s.vid().v); return (it != sets.end()) && (it->second->flags & MTPDstickerSet::Flag::f_archived); }(); - auto set = FeedSet(s); + auto set = feedSet(s); set->flags &= ~MTPDstickerSet_ClientFlag::f_not_loaded; @@ -991,10 +1053,10 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) { MTP_long(set->id), MTP_long(set->access)); - auto pack = Pack(); + auto pack = StickersPack(); pack.reserve(d_docs.size()); for (const auto &item : d_docs) { - const auto document = Auth().data().processDocument(item); + const auto document = owner().processDocument(item); if (!document->sticker()) continue; pack.push_back(document); @@ -1015,7 +1077,7 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) { } auto writeRecent = false; - auto &recent = GetRecentPack(); + auto &recent = getRecentPack(); for (auto i = recent.begin(); i != recent.cend();) { if (set->stickers.indexOf(i->first) >= 0 && pack.indexOf(i->first) < 0) { i = recent.erase(i); @@ -1026,8 +1088,8 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) { } if (pack.isEmpty()) { - int removeIndex = Auth().data().stickerSetsOrder().indexOf(set->id); - if (removeIndex >= 0) Auth().data().stickerSetsOrderRef().removeAt(removeIndex); + int removeIndex = setsOrder().indexOf(set->id); + if (removeIndex >= 0) setsOrderRef().removeAt(removeIndex); sets.remove(set->id); set = nullptr; } else { @@ -1042,10 +1104,10 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) { emoji = emoji->original(); auto &stickers = pack.vdocuments().v; - Pack p; + StickersPack p; p.reserve(stickers.size()); for (auto j = 0, c = stickers.size(); j != c; ++j) { - auto doc = Auth().data().document(stickers[j].v); + auto doc = owner().document(stickers[j].v); if (!doc || !doc->sticker()) continue; p.push_back(doc); @@ -1074,12 +1136,12 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) { } } - Auth().data().notifyStickersUpdated(); + notifyUpdated(); return set; } -void NewSetReceived(const MTPmessages_StickerSet &data) { +void Stickers::newSetReceived(const MTPmessages_StickerSet &data) { bool writeArchived = false; const auto &set = data.c_messages_stickerSet(); const auto &s = set.vset().c_stickerSet(); @@ -1094,7 +1156,7 @@ void NewSetReceived(const MTPmessages_StickerSet &data) { } else if (s.is_masks()) { return; } - auto &order = Auth().data().stickerSetsOrderRef(); + auto &order = setsOrderRef(); int32 insertAtIndex = 0, currentIndex = order.indexOf(s.vid().v); if (currentIndex != insertAtIndex) { if (currentIndex > 0) { @@ -1103,10 +1165,10 @@ void NewSetReceived(const MTPmessages_StickerSet &data) { order.insert(insertAtIndex, s.vid().v); } - FeedSetFull(data); + feedSetFull(data); } -QString GetSetTitle(const MTPDstickerSet &s) { +QString Stickers::getSetTitle(const MTPDstickerSet &s) { auto title = qs(s.vtitle()); if ((s.vflags().v & MTPDstickerSet::Flag::f_official) && !title.compare(qstr("Great Minds"), Qt::CaseInsensitive)) { return tr::lng_stickers_default_set(tr::now); @@ -1114,7 +1176,7 @@ QString GetSetTitle(const MTPDstickerSet &s) { return title; } -RecentStickerPack &GetRecentPack() { +RecentStickerPack &Stickers::getRecentPack() { if (cRecentStickers().isEmpty() && !cRecentStickersPreload().isEmpty()) { const auto p = cRecentStickersPreload(); cSetRecentStickersPreload(RecentStickerPreload()); @@ -1122,7 +1184,7 @@ RecentStickerPack &GetRecentPack() { auto &recent = cRefRecentStickers(); recent.reserve(p.size()); for (const auto &preloaded : p) { - const auto document = Auth().data().document(preloaded.first); + const auto document = owner().document(preloaded.first); if (!document || !document->sticker()) continue; recent.push_back(qMakePair(document, preloaded.second)); @@ -1131,168 +1193,4 @@ RecentStickerPack &GetRecentPack() { return cRefRecentStickers(); } -template -auto LottieCachedFromContent( - Method &&method, - Storage::Cache::Key baseKey, - uint8 keyShift, - not_null session, - const QByteArray &content, - QSize box) { - const auto key = Storage::Cache::Key{ - baseKey.high, - baseKey.low + keyShift - }; - const auto get = [=](FnMut handler) { - session->data().cacheBigFile().get( - key, - std::move(handler)); - }; - const auto weak = base::make_weak(session.get()); - const auto put = [=](QByteArray &&cached) { - crl::on_main(weak, [=, data = std::move(cached)]() mutable { - weak->data().cacheBigFile().put(key, std::move(data)); - }); - }; - return method( - get, - put, - content, - Lottie::FrameRequest{ box }); -} - -template -auto LottieFromDocument( - Method &&method, - not_null media, - uint8 keyShift, - QSize box) { - const auto document = media->owner(); - const auto data = media->bytes(); - const auto filepath = document->filepath(); - if (box.width() * box.height() > kDontCacheLottieAfterArea) { - // Don't use frame caching for large stickers. - return method( - Lottie::ReadContent(data, filepath), - Lottie::FrameRequest{ box }); - } - if (const auto baseKey = document->bigFileBaseCacheKey()) { - return LottieCachedFromContent( - std::forward(method), - baseKey, - keyShift, - &document->session(), - Lottie::ReadContent(data, filepath), - box); - } - return method( - Lottie::ReadContent(data, filepath), - Lottie::FrameRequest{ box }); -} - -std::unique_ptr LottiePlayerFromDocument( - not_null media, - LottieSize sizeTag, - QSize box, - Lottie::Quality quality, - std::shared_ptr renderer) { - return LottiePlayerFromDocument( - media, - nullptr, - sizeTag, - box, - quality, - std::move(renderer)); -} - -std::unique_ptr LottiePlayerFromDocument( - not_null media, - const Lottie::ColorReplacements *replacements, - LottieSize sizeTag, - QSize box, - Lottie::Quality quality, - std::shared_ptr renderer) { - const auto method = [&](auto &&...args) { - return std::make_unique( - std::forward(args)..., - quality, - replacements, - std::move(renderer)); - }; - const auto tag = replacements ? replacements->tag : uint8(0); - const auto keyShift = ((tag << 4) & 0xF0) | (uint8(sizeTag) & 0x0F); - return LottieFromDocument(method, media, uint8(keyShift), box); -} - -not_null LottieAnimationFromDocument( - not_null player, - not_null media, - LottieSize sizeTag, - QSize box) { - const auto method = [&](auto &&...args) { - return player->append(std::forward(args)...); - }; - return LottieFromDocument(method, media, uint8(sizeTag), box); -} - -bool HasLottieThumbnail( - SetThumbnailView *thumb, - Data::DocumentMedia *media) { - if (thumb) { - return !thumb->content().isEmpty(); - } else if (!media) { - return false; - } - const auto document = media->owner(); - if (const auto info = document->sticker()) { - if (!info->animated) { - return false; - } - media->automaticLoad(document->stickerSetOrigin(), nullptr); - if (!media->loaded()) { - return false; - } - return document->bigFileBaseCacheKey().valid(); - } - return false; -} - -std::unique_ptr LottieThumbnail( - SetThumbnailView *thumb, - Data::DocumentMedia *media, - LottieSize sizeTag, - QSize box, - std::shared_ptr renderer) { - const auto baseKey = thumb - ? thumb->owner()->thumbnailLocation().file().bigFileBaseCacheKey() - : media - ? media->owner()->bigFileBaseCacheKey() - : Storage::Cache::Key(); - if (!baseKey) { - return nullptr; - } - const auto content = thumb - ? thumb->content() - : Lottie::ReadContent(media->bytes(), media->owner()->filepath()); - if (content.isEmpty()) { - return nullptr; - } - const auto method = [](auto &&...args) { - return std::make_unique( - std::forward(args)...); - }; - const auto session = thumb - ? &thumb->owner()->session() - : media - ? &media->owner()->session() - : nullptr; - return LottieCachedFromContent( - method, - baseKey, - uint8(sizeTag), - session, - content, - box); -} - } // namespace Stickers diff --git a/Telegram/SourceFiles/data/stickers/data_stickers.h b/Telegram/SourceFiles/data/stickers/data_stickers.h new file mode 100644 index 000000000..78f9ba702 --- /dev/null +++ b/Telegram/SourceFiles/data/stickers/data_stickers.h @@ -0,0 +1,212 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "mtproto/sender.h" +#include "data/stickers/data_stickers_set.h" +#include "settings.h" + +class HistoryItem; +class DocumentData; + +namespace Main { +class Session; +} // namespace Main + +namespace Data { + +class Session; +class DocumentMedia; + +class Stickers final { +public: + explicit Stickers(not_null owner); + + [[nodiscard]] Session &owner() const; + [[nodiscard]] Main::Session &session() const; + + // for backward compatibility + static constexpr auto DefaultSetId = 0; + static constexpr auto CustomSetId = 0xFFFFFFFFFFFFFFFFULL; + + // For stickers panel, should not appear in Sets. + static constexpr auto RecentSetId = 0xFFFFFFFFFFFFFFFEULL; + static constexpr auto NoneSetId = 0xFFFFFFFFFFFFFFFDULL; + static constexpr auto FeaturedSetId = 0xFFFFFFFFFFFFFFFBULL; + + // For cloud-stored recent stickers. + static constexpr auto CloudRecentSetId = 0xFFFFFFFFFFFFFFFCULL; + + // For cloud-stored faved stickers. + static constexpr auto FavedSetId = 0xFFFFFFFFFFFFFFFAULL; + + // For setting up megagroup sticker set. + static constexpr auto MegagroupSetId = 0xFFFFFFFFFFFFFFEFULL; + + void notifyUpdated(); + [[nodiscard]] rpl::producer<> updated() const; + void notifyRecentUpdated(); + [[nodiscard]] rpl::producer<> recentUpdated() const; + void notifySavedGifsUpdated(); + [[nodiscard]] rpl::producer<> savedGifsUpdated() const; + + bool updateNeeded(crl::time now) const { + return updateNeeded(_lastUpdate, now); + } + void setLastUpdate(crl::time update) { + _lastUpdate = update; + } + bool recentUpdateNeeded(crl::time now) const { + return updateNeeded(_lastRecentUpdate, now); + } + void setLastRecentUpdate(crl::time update) { + if (update) { + notifyRecentUpdated(); + } + _lastRecentUpdate = update; + } + bool favedUpdateNeeded(crl::time now) const { + return updateNeeded(_lastFavedUpdate, now); + } + void setLastFavedUpdate(crl::time update) { + _lastFavedUpdate = update; + } + bool featuredUpdateNeeded(crl::time now) const { + return updateNeeded(_lastFeaturedUpdate, now); + } + void setLastFeaturedUpdate(crl::time update) { + _lastFeaturedUpdate = update; + } + bool savedGifsUpdateNeeded(crl::time now) const { + return updateNeeded(_lastSavedGifsUpdate, now); + } + void setLastSavedGifsUpdate(crl::time update) { + _lastSavedGifsUpdate = update; + } + int featuredSetsUnreadCount() const { + return _featuredSetsUnreadCount.current(); + } + void setFeaturedSetsUnreadCount(int count) { + _featuredSetsUnreadCount = count; + } + [[nodiscard]] rpl::producer featuredSetsUnreadCountValue() const { + return _featuredSetsUnreadCount.value(); + } + const StickersSets &sets() const { + return _sets; + } + StickersSets &setsRef() { + return _sets; + } + const StickersSetsOrder &setsOrder() const { + return _setsOrder; + } + StickersSetsOrder &setsOrderRef() { + return _setsOrder; + } + const StickersSetsOrder &featuredSetsOrder() const { + return _featuredSetsOrder; + } + StickersSetsOrder &featuredSetsOrderRef() { + return _featuredSetsOrder; + } + const StickersSetsOrder &archivedSetsOrder() const { + return _archivedSetsOrder; + } + StickersSetsOrder &archivedSetsOrderRef() { + return _archivedSetsOrder; + } + const SavedGifs &savedGifs() const { + return _savedGifs; + } + SavedGifs &savedGifsRef() { + return _savedGifs; + } + + void addSavedGif(not_null document); + void checkSavedGif(not_null item); + + void applyArchivedResult( + const MTPDmessages_stickerSetInstallResultArchive &d); + bool applyArchivedResultFake(); // For testing. + void installLocally(uint64 setId); + void undoInstallLocally(uint64 setId); + bool isFaved(not_null document); + void setFaved(not_null document, bool faved); + + void setsReceived(const QVector &data, int32 hash); + void specialSetReceived( + uint64 setId, + const QString &setTitle, + const QVector &items, + int32 hash, + const QVector &packs = QVector(), + const QVector &usageDates = QVector()); + void featuredSetsReceived( + const QVector &list, + const QVector &unread, + int32 hash); + void gifsReceived(const QVector &items, int32 hash); + + std::vector> getListByEmoji( + not_null emoji, + uint64 seed); + std::optional>> getEmojiListFromSet( + not_null document); + + StickersSet *feedSet(const MTPDstickerSet &data); + StickersSet *feedSetFull(const MTPmessages_StickerSet &data); + void newSetReceived(const MTPmessages_StickerSet &data); + + QString getSetTitle(const MTPDstickerSet &s); + + RecentStickerPack &getRecentPack(); + +private: + bool updateNeeded(crl::time lastUpdate, crl::time now) const { + constexpr auto kUpdateTimeout = crl::time(3600'000); + return (lastUpdate == 0) + || (now >= lastUpdate + kUpdateTimeout); + } + void checkFavedLimit(StickersSet &set); + void setIsFaved( + not_null document, + std::optional>> emojiList + = std::nullopt); + void setIsNotFaved(not_null document); + void pushFavedToFront( + StickersSet &set, + not_null document, + const std::vector> &emojiList); + void moveFavedToFront(StickersSet &set, int index); + void requestSetToPushFaved(not_null document); + void setPackAndEmoji( + StickersSet &set, + StickersPack &&pack, + const std::vector &&dates, + const QVector &packs); + + const not_null _owner; + rpl::event_stream<> _updated; + rpl::event_stream<> _recentUpdated; + rpl::event_stream<> _savedGifsUpdated; + crl::time _lastUpdate = 0; + crl::time _lastRecentUpdate = 0; + crl::time _lastFavedUpdate = 0; + crl::time _lastFeaturedUpdate = 0; + crl::time _lastSavedGifsUpdate = 0; + rpl::variable _featuredSetsUnreadCount = 0; + StickersSets _sets; + StickersSetsOrder _setsOrder; + StickersSetsOrder _featuredSetsOrder; + StickersSetsOrder _archivedSetsOrder; + SavedGifs _savedGifs; + +}; + +} // namespace Data diff --git a/Telegram/SourceFiles/chat_helpers/stickers_set.cpp b/Telegram/SourceFiles/data/stickers/data_stickers_set.cpp similarity index 70% rename from Telegram/SourceFiles/chat_helpers/stickers_set.cpp rename to Telegram/SourceFiles/data/stickers/data_stickers_set.cpp index c4f5f4092..6c922191d 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_set.cpp +++ b/Telegram/SourceFiles/data/stickers/data_stickers_set.cpp @@ -5,7 +5,7 @@ the official desktop application for the Telegram messaging service. For license and copyright information please follow this link: https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ -#include "chat_helpers/stickers_set.h" +#include "data/stickers/data_stickers_set.h" #include "main/main_session.h" #include "data/data_session.h" @@ -14,16 +14,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/image/image.h" #include "app.h" -namespace Stickers { +namespace Data { -SetThumbnailView::SetThumbnailView(not_null owner) : _owner(owner) { +StickersSetThumbnailView::StickersSetThumbnailView( + not_null owner) +: _owner(owner) { } -not_null SetThumbnailView::owner() const { +not_null StickersSetThumbnailView::owner() const { return _owner; } -void SetThumbnailView::set( +void StickersSetThumbnailView::set( not_null session, QByteArray content) { auto image = App::readImage(content, nullptr, false); @@ -35,15 +37,15 @@ void SetThumbnailView::set( session->downloaderTaskFinished().notify(); } -Image *SetThumbnailView::image() const { +Image *StickersSetThumbnailView::image() const { return _image.get(); } -QByteArray SetThumbnailView::content() const { +QByteArray StickersSetThumbnailView::content() const { return _content; } -Set::Set( +StickersSet::StickersSet( not_null owner, uint64 id, uint64 access, @@ -64,21 +66,21 @@ Set::Set( , _owner(owner) { } -Data::Session &Set::owner() const { +Data::Session &StickersSet::owner() const { return *_owner; } -Main::Session &Set::session() const { +Main::Session &StickersSet::session() const { return _owner->session(); } -MTPInputStickerSet Set::mtpInput() const { +MTPInputStickerSet StickersSet::mtpInput() const { return (id && access) ? MTP_inputStickerSetID(MTP_long(id), MTP_long(access)) : MTP_inputStickerSetShortName(MTP_string(shortName)); } -void Set::setThumbnail(const ImageWithLocation &data) { +void StickersSet::setThumbnail(const ImageWithLocation &data) { Data::UpdateCloudFile( _thumbnail, data, @@ -95,19 +97,19 @@ void Set::setThumbnail(const ImageWithLocation &data) { } } -bool Set::hasThumbnail() const { +bool StickersSet::hasThumbnail() const { return _thumbnail.location.valid(); } -bool Set::thumbnailLoading() const { +bool StickersSet::thumbnailLoading() const { return (_thumbnail.loader != nullptr); } -bool Set::thumbnailFailed() const { +bool StickersSet::thumbnailFailed() const { return (_thumbnail.flags & Data::CloudFile::Flag::Failed); } -void Set::loadThumbnail() { +void StickersSet::loadThumbnail() { const auto autoLoading = false; const auto finalCheck = [=] { if (const auto active = activeThumbnailView()) { @@ -131,24 +133,24 @@ void Set::loadThumbnail() { done); } -const ImageLocation &Set::thumbnailLocation() const { +const ImageLocation &StickersSet::thumbnailLocation() const { return _thumbnail.location; } -int Set::thumbnailByteSize() const { +int StickersSet::thumbnailByteSize() const { return _thumbnail.byteSize; } -std::shared_ptr Set::createThumbnailView() { +std::shared_ptr StickersSet::createThumbnailView() { if (auto active = activeThumbnailView()) { return active; } - auto view = std::make_shared(this); + auto view = std::make_shared(this); _thumbnailView = view; return view; } -std::shared_ptr Set::activeThumbnailView() { +std::shared_ptr StickersSet::activeThumbnailView() { return _thumbnailView.lock(); } diff --git a/Telegram/SourceFiles/chat_helpers/stickers_set.h b/Telegram/SourceFiles/data/stickers/data_stickers_set.h similarity index 67% rename from Telegram/SourceFiles/chat_helpers/stickers_set.h rename to Telegram/SourceFiles/data/stickers/data_stickers_set.h index 41565dd3f..cb4249c54 100644 --- a/Telegram/SourceFiles/chat_helpers/stickers_set.h +++ b/Telegram/SourceFiles/data/stickers/data_stickers_set.h @@ -11,29 +11,27 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL class DocumentData; -namespace Data { -class Session; -} // namespace Data - namespace Main { class Session; } // namespace Main -namespace Stickers { +namespace Data { -using Order = QList; +class Session; + +using StickersSetsOrder = QList; using SavedGifs = QVector; -using Pack = QVector; -using ByEmojiMap = QMap; +using StickersPack = QVector; +using StickersByEmojiMap = QMap; -class Set; -using Sets = base::flat_map>; +class StickersSet; +using StickersSets = base::flat_map>; -class SetThumbnailView final { +class StickersSetThumbnailView final { public: - explicit SetThumbnailView(not_null owner); + explicit StickersSetThumbnailView(not_null owner); - [[nodiscard]] not_null owner() const; + [[nodiscard]] not_null owner() const; void set(not_null session, QByteArray content); @@ -41,15 +39,15 @@ public: [[nodiscard]] QByteArray content() const; private: - const not_null _owner; + const not_null _owner; std::unique_ptr _image; QByteArray _content; }; -class Set final { +class StickersSet final { public: - Set( + StickersSet( not_null owner, uint64 id, uint64 access, @@ -74,8 +72,8 @@ public: [[nodiscard]] const ImageLocation &thumbnailLocation() const; [[nodiscard]] int thumbnailByteSize() const; - [[nodiscard]] std::shared_ptr createThumbnailView(); - [[nodiscard]] std::shared_ptr activeThumbnailView(); + [[nodiscard]] std::shared_ptr createThumbnailView(); + [[nodiscard]] std::shared_ptr activeThumbnailView(); uint64 id = 0; uint64 access = 0; @@ -84,16 +82,16 @@ public: int32 hash = 0; MTPDstickerSet::Flags flags; TimeId installDate = 0; - Pack stickers; + StickersPack covers; + StickersPack stickers; std::vector dates; - Pack covers; - ByEmojiMap emoji; + StickersByEmojiMap emoji; private: const not_null _owner; - Data::CloudFile _thumbnail; - std::weak_ptr _thumbnailView; + CloudFile _thumbnail; + std::weak_ptr _thumbnailView; }; diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 9dc59155e..f48f07f37 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -30,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_histories.h" #include "data/data_chat_filters.h" #include "data/data_cloud_file.h" +#include "data/stickers/data_stickers.h" #include "base/unixtime.h" #include "lang/lang_keys.h" #include "mainwindow.h" @@ -38,7 +39,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "apiwrap.h" #include "window/themes/window_theme.h" #include "observer_peer.h" -#include "chat_helpers/stickers.h" #include "main/main_session.h" #include "window/notifications_manager.h" #include "window/window_session_controller.h" diff --git a/Telegram/SourceFiles/history/history.cpp b/Telegram/SourceFiles/history/history.cpp index 96b1f786e..5fba0d408 100644 --- a/Telegram/SourceFiles/history/history.cpp +++ b/Telegram/SourceFiles/history/history.cpp @@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_item_components.h" #include "history/history_inner_widget.h" #include "dialogs/dialogs_indexed_list.h" +#include "data/stickers/data_stickers.h" #include "data/data_drafts.h" #include "data/data_session.h" #include "data/data_media_types.h" @@ -1056,7 +1057,7 @@ void History::applyMessageChanges( if (data.type() == mtpc_messageService) { applyServiceChanges(item, data.c_messageService()); } - owner().checkSavedGif(item); + owner().stickers().checkSavedGif(item); } void History::applyServiceChanges( diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index c0eb794f8..2ce1d8602 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -35,7 +35,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/report_box.h" #include "boxes/sticker_set_box.h" #include "chat_helpers/message_field.h" -#include "chat_helpers/stickers.h" #include "history/history_widget.h" #include "base/platform/base_platform_info.h" #include "base/unixtime.h" @@ -55,6 +54,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_user.h" #include "data/data_file_origin.h" #include "data/data_histories.h" +#include "data/stickers/data_stickers.h" #include "facades.h" #include "app.h" #include "styles/style_history.h" @@ -1731,11 +1731,11 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) { _menu->addAction(document->isStickerSetInstalled() ? tr::lng_context_pack_info(tr::now) : tr::lng_context_pack_add(tr::now), [=] { showStickerPackInfo(document); }); - _menu->addAction(Stickers::IsFaved(document) ? tr::lng_faved_stickers_remove(tr::now) : tr::lng_faved_stickers_add(tr::now), [=] { + _menu->addAction(session().data().stickers().isFaved(document) ? tr::lng_faved_stickers_remove(tr::now) : tr::lng_faved_stickers_add(tr::now), [=] { session().api().toggleFavedSticker( document, itemId, - !Stickers::IsFaved(document)); + !session().data().stickers().isFaved(document)); }); } _menu->addAction(tr::lng_context_save_image(tr::now), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [=] { diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 60445cc3c..2a4dbdf37 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -996,11 +996,11 @@ int HistoryWidget::itemTopForHighlight( } void HistoryWidget::start() { - session().data().stickersUpdated( + session().data().stickers().updated( ) | rpl::start_with_next([=] { updateStickersByEmoji(); }, lifetime()); - session().data().notifySavedGifsUpdated(); + session().data().stickers().notifySavedGifsUpdated(); subscribe(session().api().fullPeerUpdated(), [this](PeerData *peer) { fullPeerUpdated(peer); }); diff --git a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp index b8ec2414a..38a8fbb78 100644 --- a/Telegram/SourceFiles/history/view/history_view_context_menu.cpp +++ b/Telegram/SourceFiles/history/view/history_view_context_menu.cpp @@ -111,7 +111,7 @@ void ToggleFavedSticker( document->session().api().toggleFavedSticker( document, contextId, - !Stickers::IsFaved(document)); + !document->owner().stickers().isFaved(document)); } void AddPhotoActions( @@ -204,7 +204,7 @@ void AddDocumentActions( : tr::lng_context_pack_add(tr::now)), [=] { ShowStickerPackInfo(document); }); menu->addAction( - (Stickers::IsFaved(document) + (document->owner().stickers().isFaved(document) ? tr::lng_faved_stickers_remove(tr::now) : tr::lng_faved_stickers_add(tr::now)), [=] { ToggleFavedSticker(document, contextId); }); diff --git a/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp b/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp index 1a55b9691..3f4ef0371 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp @@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_document_media.h" #include "data/data_file_origin.h" #include "lottie/lottie_single_player.h" +#include "chat_helpers/stickers_lottie.h" #include "styles/style_history.h" namespace HistoryView { @@ -293,10 +294,10 @@ void Sticker::setDiceIndex(const QString &emoji, int index) { void Sticker::setupLottie() { Expects(_dataMedia != nullptr); - _lottie = Stickers::LottiePlayerFromDocument( + _lottie = ChatHelpers::LottiePlayerFromDocument( _dataMedia.get(), _replacements, - Stickers::LottieSize::MessageHistory, + ChatHelpers::StickerLottieSize::MessageHistory, _size * cIntRetinaFactor(), Lottie::Quality::High); lottieCreated(); diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp index 7bd6f7c6f..6a19cd9f7 100644 --- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp +++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp @@ -13,10 +13,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_file_origin.h" #include "data/data_photo_media.h" #include "data/data_document_media.h" -#include "styles/style_overview.h" -#include "styles/style_history.h" -#include "styles/style_chat_helpers.h" -#include "styles/style_widgets.h" +#include "data/stickers/data_stickers.h" +#include "chat_helpers/stickers_lottie.h" #include "inline_bots/inline_bot_result.h" #include "lottie/lottie_single_player.h" #include "media/audio/media_audio.h" @@ -25,12 +23,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_location_manager.h" #include "history/view/history_view_cursor_state.h" #include "storage/localstorage.h" -#include "chat_helpers/stickers.h" #include "ui/image/image.h" #include "main/main_session.h" #include "apiwrap.h" #include "lang/lang_keys.h" #include "app.h" +#include "styles/style_overview.h" +#include "styles/style_history.h" +#include "styles/style_chat_helpers.h" +#include "styles/style_widgets.h" namespace InlineBots { namespace Layout { @@ -127,12 +128,12 @@ void Gif::setPosition(int32 position) { void DeleteSavedGifClickHandler::onClickImpl() const { Auth().api().toggleSavedGif(_data, Data::FileOriginSavedGifs(), false); - const auto index = Auth().data().savedGifs().indexOf(_data); + const auto index = Auth().data().stickers().savedGifs().indexOf(_data); if (index >= 0) { - Auth().data().savedGifsRef().remove(index); + Auth().data().stickers().savedGifsRef().remove(index); Local::writeSavedGifs(); } - Auth().data().notifySavedGifsUpdated(); + Auth().data().stickers().notifySavedGifsUpdated(); } int Gif::resizeGetHeight(int width) { @@ -523,9 +524,9 @@ QSize Sticker::getThumbSize() const { void Sticker::setupLottie() const { Expects(_dataMedia != nullptr); - _lottie = Stickers::LottiePlayerFromDocument( + _lottie = ChatHelpers::LottiePlayerFromDocument( _dataMedia.get(), - Stickers::LottieSize::InlineResults, + ChatHelpers::StickerLottieSize::InlineResults, QSize( st::stickerPanSize.width() - st::buttonRadius * 2, st::stickerPanSize.height() - st::buttonRadius * 2 diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index b804041ca..054adc3eb 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_scheduled_messages.h" #include "data/data_file_origin.h" #include "data/data_histories.h" +#include "data/stickers/data_stickers.h" #include "api/api_text_entities.h" #include "ui/special_buttons.h" #include "ui/widgets/buttons.h" @@ -43,7 +44,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "window/window_connecting_widget.h" #include "chat_helpers/tabbed_selector.h" // TabbedSelector::refreshStickers #include "chat_helpers/message_field.h" -#include "chat_helpers/stickers.h" #include "info/info_memento.h" #include "info/info_controller.h" #include "observer_peer.h" @@ -3212,8 +3212,8 @@ void MainWidget::start() { if (const auto availableAt = Local::ReadExportSettings().availableAt) { session().data().suggestStartExport(availableAt); } - session().data().notifyStickersUpdated(); - session().data().notifySavedGifsUpdated(); + session().data().stickers().notifyUpdated(); + session().data().stickers().notifySavedGifsUpdated(); _history->start(); @@ -3362,15 +3362,15 @@ void MainWidget::incrementSticker(DocumentData *sticker) { } bool writeRecentStickers = false; - auto &sets = session().data().stickerSetsRef(); - auto it = sets.find(Stickers::CloudRecentSetId); + auto &sets = session().data().stickers().setsRef(); + auto it = sets.find(Data::Stickers::CloudRecentSetId); if (it == sets.cend()) { if (it == sets.cend()) { it = sets.emplace( - Stickers::CloudRecentSetId, - std::make_unique( + Data::Stickers::CloudRecentSetId, + std::make_unique( &session().data(), - Stickers::CloudRecentSetId, + Data::Stickers::CloudRecentSetId, uint64(0), tr::lng_recent_stickers(tr::now), QString(), @@ -3410,7 +3410,7 @@ void MainWidget::incrementSticker(DocumentData *sticker) { set->dates.insert(set->dates.begin(), base::unixtime::now()); } set->stickers.push_front(sticker); - if (const auto emojiList = Stickers::GetEmojiListFromSet(sticker)) { + if (const auto emojiList = session().data().stickers().getEmojiListFromSet(sticker)) { for (const auto emoji : *emojiList) { set->emoji[emoji].push_front(sticker); } @@ -3427,7 +3427,7 @@ void MainWidget::incrementSticker(DocumentData *sticker) { // Remove that sticker from old recent, now it is in cloud recent stickers. bool writeOldRecent = false; - auto &recent = Stickers::GetRecentPack(); + auto &recent = session().data().stickers().getRecentPack(); for (auto i = recent.begin(), e = recent.end(); i != e; ++i) { if (i->first == sticker) { writeOldRecent = true; @@ -3446,7 +3446,7 @@ void MainWidget::incrementSticker(DocumentData *sticker) { // Remove that sticker from custom stickers, now it is in cloud recent stickers. bool writeInstalledStickers = false; - auto customIt = sets.find(Stickers::CustomSetId); + auto customIt = sets.find(Data::Stickers::CustomSetId); if (customIt != sets.cend()) { const auto custom = customIt->second.get(); int removeIndex = custom->stickers.indexOf(sticker); @@ -3469,8 +3469,9 @@ void MainWidget::incrementSticker(DocumentData *sticker) { } void MainWidget::activate() { - if (_a_show.animating()) return; - if (!_mainSection) { + if (_a_show.animating()) { + return; + } else if (!_mainSection) { if (_hider) { _dialogs->setInnerFocus(); } else if (App::wnd() && !Ui::isLayerShown()) { @@ -3479,7 +3480,9 @@ void MainWidget::activate() { const auto path = cSendPaths()[0]; if (path.startsWith(interpret)) { cSetSendPaths(QStringList()); - const auto error = Support::InterpretSendPath(path.mid(interpret.size())); + const auto error = Support::InterpretSendPath( + _controller, + path.mid(interpret.size())); if (!error.isEmpty()) { Ui::show(Box(error)); } @@ -4519,45 +4522,45 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { ////// Cloud sticker sets case mtpc_updateNewStickerSet: { const auto &d = update.c_updateNewStickerSet(); - Stickers::NewSetReceived(d.vstickerset()); + session().data().stickers().newSetReceived(d.vstickerset()); } break; case mtpc_updateStickerSetsOrder: { auto &d = update.c_updateStickerSetsOrder(); if (!d.is_masks()) { const auto &order = d.vorder().v; - const auto &sets = session().data().stickerSets(); - Stickers::Order result; + const auto &sets = session().data().stickers().sets(); + Data::StickersSetsOrder result; for (const auto &item : order) { if (sets.find(item.v) == sets.cend()) { break; } result.push_back(item.v); } - if (result.size() != session().data().stickerSetsOrder().size() + if (result.size() != session().data().stickers().setsOrder().size() || result.size() != order.size()) { - session().data().setLastStickersUpdate(0); + session().data().stickers().setLastUpdate(0); session().api().updateStickers(); } else { - session().data().stickerSetsOrderRef() = std::move(result); + session().data().stickers().setsOrderRef() = std::move(result); Local::writeInstalledStickers(); - session().data().notifyStickersUpdated(); + session().data().stickers().notifyUpdated(); } } } break; case mtpc_updateStickerSets: { - session().data().setLastStickersUpdate(0); + session().data().stickers().setLastUpdate(0); session().api().updateStickers(); } break; case mtpc_updateRecentStickers: { - session().data().setLastRecentStickersUpdate(0); + session().data().stickers().setLastRecentUpdate(0); session().api().updateStickers(); } break; case mtpc_updateFavedStickers: { - session().data().setLastFavedStickersUpdate(0); + session().data().stickers().setLastFavedUpdate(0); session().api().updateStickers(); } break; @@ -4565,13 +4568,13 @@ void MainWidget::feedUpdate(const MTPUpdate &update) { // We read some of the featured stickers, perhaps not all of them. // Here we don't know what featured sticker sets were read, so we // request all of them once again. - session().data().setLastFeaturedStickersUpdate(0); + session().data().stickers().setLastFeaturedUpdate(0); session().api().updateStickers(); } break; ////// Cloud saved GIFs case mtpc_updateSavedGifs: { - session().data().setLastSavedGifsUpdate(0); + session().data().stickers().setLastSavedGifsUpdate(0); session().api().updateStickers(); } break; diff --git a/Telegram/SourceFiles/platform/mac/mac_touchbar.mm b/Telegram/SourceFiles/platform/mac/mac_touchbar.mm index 6322cf68c..4396e0558 100644 --- a/Telegram/SourceFiles/platform/mac/mac_touchbar.mm +++ b/Telegram/SourceFiles/platform/mac/mac_touchbar.mm @@ -23,6 +23,7 @@ #include "data/data_peer_values.h" #include "data/data_session.h" #include "data/data_cloud_file.h" +#include "data/stickers/data_stickers.h" #include "dialogs/dialogs_layout.h" #include "ui/emoji_config.h" #include "history/history.h" @@ -31,7 +32,6 @@ #include "mainwindow.h" #include "observer_peer.h" #include "base/platform/mac/base_utilities_mac.h" -#include "chat_helpers/stickers.h" #include "styles/style_dialogs.h" #include "styles/style_media_player.h" #include "styles/style_settings.h" @@ -220,8 +220,8 @@ inline std::optional RestrictionToSendStickers() { } QString TitleRecentlyUsed() { - const auto &sets = Auth().data().stickerSets(); - const auto it = sets.find(Stickers::CloudRecentSetId); + const auto &sets = Auth().data().stickers().sets(); + const auto it = sets.find(Data::Stickers::CloudRecentSetId); if (it != sets.cend()) { return it->second->title; } @@ -351,8 +351,8 @@ void AppendStickerSet(std::vector &to, uint64 setId) { } void AppendRecentStickers(std::vector &to) { - const auto &sets = Auth().data().stickerSets(); - const auto cloudIt = sets.find(Stickers::CloudRecentSetId); + const auto &sets = Auth().data().stickers().sets(); + const auto cloudIt = sets.find(Data::Stickers::CloudRecentSetId); const auto cloudCount = (cloudIt != sets.cend()) ? cloudIt->second->stickers.size() : 0; @@ -360,20 +360,20 @@ void AppendRecentStickers(std::vector &to) { to.emplace_back(PickerScrubberItem(cloudIt->second->title)); auto count = 0; for (const auto document : cloudIt->second->stickers) { - if (Stickers::IsFaved(document)) { + if (document->owner().stickers().isFaved(document)) { continue; } to.emplace_back(PickerScrubberItem(document)); } } - for (const auto recent : Stickers::GetRecentPack()) { + for (const auto recent : Auth().data().stickers().getRecentPack()) { to.emplace_back(PickerScrubberItem(recent.first)); } } void AppendFavedStickers(std::vector &to) { - const auto &sets = Auth().data().stickerSets(); - const auto it = sets.find(Stickers::FavedSetId); + const auto &sets = Auth().data().stickers().sets(); + const auto it = sets.find(Data::Stickers::FavedSetId); const auto count = (it != sets.cend()) ? it->second->stickers.size() : 0; diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp index 6de526f78..8c1e9c8c0 100644 --- a/Telegram/SourceFiles/storage/localstorage.cpp +++ b/Telegram/SourceFiles/storage/localstorage.cpp @@ -11,11 +11,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/serialize_common.h" #include "storage/storage_encrypted_file.h" #include "storage/storage_clear_legacy.h" -#include "chat_helpers/stickers.h" #include "data/data_drafts.h" #include "data/data_user.h" #include "data/data_session.h" #include "data/data_document_media.h" +#include "data/stickers/data_stickers.h" #include "boxes/send_files_box.h" #include "base/flags.h" #include "base/platform/base_platform_file_utilities.h" @@ -2182,6 +2182,14 @@ void _writeUserSettings() { : QByteArray(); auto callSettings = serializeCallSettings(); + auto recentStickers = cRecentStickersPreload(); + if (recentStickers.isEmpty() && Main::Session::Exists()) { + recentStickers.reserve(Auth().data().stickers().getRecentPack().size()); + for (const auto &pair : std::as_const(Auth().data().stickers().getRecentPack())) { + recentStickers.push_back(qMakePair(pair.first->id, pair.second)); + } + } + uint32 size = 24 * (sizeof(quint32) + sizeof(qint32)); size += sizeof(quint32) + Serialize::stringSize(Global::AskDownloadPath() ? QString() : Global::DownloadPath()) + Serialize::bytearraySize(Global::AskDownloadPath() ? QByteArray() : Global::DownloadPathBookmark()); @@ -2191,7 +2199,7 @@ void _writeUserSettings() { } size += sizeof(quint32) + sizeof(qint32) + cEmojiVariants().size() * (sizeof(uint32) + sizeof(uint64)); - size += sizeof(quint32) + sizeof(qint32) + (cRecentStickersPreload().isEmpty() ? Stickers::GetRecentPack().size() : cRecentStickersPreload().size()) * (sizeof(uint64) + sizeof(ushort)); + size += sizeof(quint32) + sizeof(qint32) + recentStickers.size() * (sizeof(uint64) + sizeof(ushort)); size += sizeof(quint32) + Serialize::stringSize(cDialogLastPath()); size += sizeof(quint32) + 3 * sizeof(qint32); size += sizeof(quint32) + 2 * sizeof(qint32); @@ -2233,21 +2241,9 @@ void _writeUserSettings() { data.stream << quint32(dbiSessionSettings) << userData; } data.stream << quint32(dbiPlaybackSpeed) << qint32(Global::VoiceMsgPlaybackDoubled() ? 2 : 1); - - { - data.stream << quint32(dbiRecentEmoji) << recentEmojiPreloadData; - } + data.stream << quint32(dbiRecentEmoji) << recentEmojiPreloadData; data.stream << quint32(dbiEmojiVariants) << cEmojiVariants(); - { - auto v = cRecentStickersPreload(); - if (v.isEmpty()) { - v.reserve(Stickers::GetRecentPack().size()); - for_const (auto &pair, Stickers::GetRecentPack()) { - v.push_back(qMakePair(pair.first->id, pair.second)); - } - } - data.stream << quint32(dbiRecentStickers) << v; - } + data.stream << quint32(dbiRecentStickers) << recentStickers; if (!Global::HiddenPinnedMessages().isEmpty()) { data.stream << quint32(dbiHiddenPinnedMessages) << Global::HiddenPinnedMessages(); } @@ -3427,7 +3423,7 @@ void cancelTask(TaskId id) { } } -void _writeStickerSet(QDataStream &stream, const Stickers::Set &set) { +void _writeStickerSet(QDataStream &stream, const Data::StickersSet &set) { const auto writeInfo = [&](int count) { stream << quint64(set.id) @@ -3475,12 +3471,15 @@ enum class StickerSetCheckResult { Abort, }; -// CheckSet is a functor on Stickers::Set, which returns a StickerSetCheckResult. +// CheckSet is a functor on Data::StickersSet, which returns a StickerSetCheckResult. template -void _writeStickerSets(FileKey &stickersKey, CheckSet checkSet, const Stickers::Order &order) { +void _writeStickerSets( + FileKey &stickersKey, + CheckSet checkSet, + const Data::StickersSetsOrder &order) { if (!_working()) return; - const auto &sets = Auth().data().stickerSets(); + const auto &sets = Auth().data().stickers().sets(); if (sets.empty()) { if (stickersKey) { ClearKey(stickersKey); @@ -3567,7 +3566,10 @@ void _writeStickerSets(FileKey &stickersKey, CheckSet checkSet, const Stickers:: file.writeEncrypted(data); } -void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr, MTPDstickerSet::Flags readingFlags = 0) { +void _readStickerSets( + FileKey &stickersKey, + Data::StickersSetsOrder *outOrder = nullptr, + MTPDstickerSet::Flags readingFlags = 0) { FileReadDescriptor stickers; if (!ReadEncryptedFile(stickers, stickersKey)) { ClearKey(stickersKey); @@ -3581,7 +3583,7 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr, stickersKey = 0; }; - auto &sets = Auth().data().stickerSetsRef(); + auto &sets = Auth().data().stickers().setsRef(); if (outOrder) outOrder->clear(); quint32 versionTag = 0; @@ -3635,16 +3637,16 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr, } setFlags = MTPDstickerSet::Flags::from_raw(setFlagsValue); - if (setId == Stickers::DefaultSetId) { + if (setId == Data::Stickers::DefaultSetId) { setTitle = tr::lng_stickers_default_set(tr::now); setFlags |= MTPDstickerSet::Flag::f_official | MTPDstickerSet_ClientFlag::f_special; - } else if (setId == Stickers::CustomSetId) { + } else if (setId == Data::Stickers::CustomSetId) { setTitle = qsl("Custom stickers"); setFlags |= MTPDstickerSet_ClientFlag::f_special; - } else if (setId == Stickers::CloudRecentSetId) { + } else if (setId == Data::Stickers::CloudRecentSetId) { setTitle = tr::lng_recent_stickers(tr::now); setFlags |= MTPDstickerSet_ClientFlag::f_special; - } else if (setId == Stickers::FavedSetId) { + } else if (setId == Data::Stickers::FavedSetId) { setTitle = Lang::Hard::FavedSetTitle(); setFlags |= MTPDstickerSet_ClientFlag::f_special; } else if (!setId) { @@ -3655,7 +3657,7 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr, if (it == sets.cend()) { // We will set this flags from order lists when reading those stickers. setFlags &= ~(MTPDstickerSet::Flag::f_installed_date | MTPDstickerSet_ClientFlag::f_featured); - it = sets.emplace(setId, std::make_unique( + it = sets.emplace(setId, std::make_unique( &Auth().data(), setId, setAccess, @@ -3713,7 +3715,7 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr, if (datesCount != scnt) { return failed(); } - const auto fillDates = (set->id == Stickers::CloudRecentSetId) + const auto fillDates = (set->id == Data::Stickers::CloudRecentSetId) && (set->stickers.size() == datesCount); if (fillDates) { set->dates.clear(); @@ -3737,7 +3739,7 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr, QString emojiString; qint32 stickersCount; stickers.stream >> emojiString >> stickersCount; - Stickers::Pack pack; + Data::StickersPack pack; pack.reserve(stickersCount); for (int32 k = 0; k < stickersCount; ++k) { quint64 id; @@ -3797,8 +3799,8 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr, void writeInstalledStickers() { if (!Global::started()) return; - _writeStickerSets(_installedStickersKey, [](const Stickers::Set &set) { - if (set.id == Stickers::CloudRecentSetId || set.id == Stickers::FavedSetId) { // separate files for them + _writeStickerSets(_installedStickersKey, [](const Data::StickersSet &set) { + if (set.id == Data::Stickers::CloudRecentSetId || set.id == Data::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" @@ -3812,14 +3814,15 @@ void writeInstalledStickers() { return StickerSetCheckResult::Skip; } return StickerSetCheckResult::Write; - }, Auth().data().stickerSetsOrder()); + }, Auth().data().stickers().setsOrder()); } void writeFeaturedStickers() { if (!Global::started()) return; - _writeStickerSets(_featuredStickersKey, [](const Stickers::Set &set) { - if (set.id == Stickers::CloudRecentSetId || set.id == Stickers::FavedSetId) { // separate files for them + _writeStickerSets(_featuredStickersKey, [](const Data::StickersSet &set) { + if (set.id == Data::Stickers::CloudRecentSetId + || set.id == Data::Stickers::FavedSetId) { // separate files for them return StickerSetCheckResult::Skip; } else if (set.flags & MTPDstickerSet_ClientFlag::f_special) { return StickerSetCheckResult::Skip; @@ -3831,40 +3834,40 @@ void writeFeaturedStickers() { return StickerSetCheckResult::Skip; } return StickerSetCheckResult::Write; - }, Auth().data().featuredStickerSetsOrder()); + }, Auth().data().stickers().featuredSetsOrder()); } void writeRecentStickers() { if (!Global::started()) return; - _writeStickerSets(_recentStickersKey, [](const Stickers::Set &set) { - if (set.id != Stickers::CloudRecentSetId || set.stickers.isEmpty()) { + _writeStickerSets(_recentStickersKey, [](const Data::StickersSet &set) { + if (set.id != Data::Stickers::CloudRecentSetId || set.stickers.isEmpty()) { return StickerSetCheckResult::Skip; } return StickerSetCheckResult::Write; - }, Stickers::Order()); + }, Data::StickersSetsOrder()); } void writeFavedStickers() { if (!Global::started()) return; - _writeStickerSets(_favedStickersKey, [](const Stickers::Set &set) { - if (set.id != Stickers::FavedSetId || set.stickers.isEmpty()) { + _writeStickerSets(_favedStickersKey, [](const Data::StickersSet &set) { + if (set.id != Data::Stickers::FavedSetId || set.stickers.isEmpty()) { return StickerSetCheckResult::Skip; } return StickerSetCheckResult::Write; - }, Stickers::Order()); + }, Data::StickersSetsOrder()); } void writeArchivedStickers() { if (!Global::started()) return; - _writeStickerSets(_archivedStickersKey, [](const Stickers::Set &set) { + _writeStickerSets(_archivedStickersKey, [](const Data::StickersSet &set) { if (!(set.flags & MTPDstickerSet::Flag::f_archived) || set.stickers.isEmpty()) { return StickerSetCheckResult::Skip; } return StickerSetCheckResult::Write; - }, Auth().data().archivedStickerSetsOrder()); + }, Auth().data().stickers().archivedSetsOrder()); } void importOldRecentStickers() { @@ -3878,20 +3881,20 @@ void importOldRecentStickers() { return; } - auto &sets = Auth().data().stickerSetsRef(); + auto &sets = Auth().data().stickers().setsRef(); sets.clear(); - auto &order = Auth().data().stickerSetsOrderRef(); + auto &order = Auth().data().stickers().setsOrderRef(); order.clear(); auto &recent = cRefRecentStickers(); recent.clear(); const auto def = sets.emplace( - Stickers::DefaultSetId, - std::make_unique( + Data::Stickers::DefaultSetId, + std::make_unique( &Auth().data(), - Stickers::DefaultSetId, + Data::Stickers::DefaultSetId, uint64(0), tr::lng_stickers_default_set(tr::now), QString(), @@ -3902,10 +3905,10 @@ void importOldRecentStickers() { | MTPDstickerSet_ClientFlag::f_special), kDefaultStickerInstallDate)).first->second.get(); const auto custom = sets.emplace( - Stickers::CustomSetId, - std::make_unique( + Data::Stickers::CustomSetId, + std::make_unique( &Auth().data(), - Stickers::CustomSetId, + Data::Stickers::CustomSetId, uint64(0), qsl("Custom stickers"), QString(), @@ -3967,12 +3970,12 @@ void importOldRecentStickers() { } } if (def->stickers.isEmpty()) { - sets.remove(Stickers::DefaultSetId); + sets.remove(Data::Stickers::DefaultSetId); } else { - order.push_front(Stickers::DefaultSetId); + order.push_front(Data::Stickers::DefaultSetId); } if (custom->stickers.isEmpty()) { - sets.remove(Stickers::CustomSetId); + sets.remove(Data::Stickers::CustomSetId); } writeInstalledStickers(); @@ -3988,21 +3991,21 @@ void readInstalledStickers() { return importOldRecentStickers(); } - Auth().data().stickerSetsRef().clear(); + Auth().data().stickers().setsRef().clear(); _readStickerSets( _installedStickersKey, - &Auth().data().stickerSetsOrderRef(), + &Auth().data().stickers().setsOrderRef(), MTPDstickerSet::Flag::f_installed_date); } void readFeaturedStickers() { _readStickerSets( _featuredStickersKey, - &Auth().data().featuredStickerSetsOrderRef(), + &Auth().data().stickers().featuredSetsOrderRef(), MTPDstickerSet::Flags() | MTPDstickerSet_ClientFlag::f_featured); - const auto &sets = Auth().data().stickerSets(); - const auto &order = Auth().data().featuredStickerSetsOrder(); + const auto &sets = Auth().data().stickers().sets(); + const auto &order = Auth().data().stickers().featuredSetsOrder(); int unreadCount = 0; for (const auto setId : order) { auto it = sets.find(setId); @@ -4011,7 +4014,7 @@ void readFeaturedStickers() { ++unreadCount; } } - Auth().data().setFeaturedStickerSetsUnreadCount(unreadCount); + Auth().data().stickers().setFeaturedSetsUnreadCount(unreadCount); } void readRecentStickers() { @@ -4025,7 +4028,7 @@ void readFavedStickers() { void readArchivedStickers() { static bool archivedStickersRead = false; if (!archivedStickersRead) { - _readStickerSets(_archivedStickersKey, &Auth().data().archivedStickerSetsOrderRef()); + _readStickerSets(_archivedStickersKey, &Auth().data().stickers().archivedSetsOrderRef()); archivedStickersRead = true; } } @@ -4039,7 +4042,7 @@ int32 countDocumentVectorHash(const QVector vector) { } int32 countSpecialStickerSetHash(uint64 setId) { - const auto &sets = Auth().data().stickerSets(); + const auto &sets = Auth().data().stickers().sets(); const auto it = sets.find(setId); if (it != sets.cend()) { return countDocumentVectorHash(it->second->stickers); @@ -4050,13 +4053,13 @@ int32 countSpecialStickerSetHash(uint64 setId) { int32 countStickersHash(bool checkOutdatedInfo) { auto result = Api::HashInit(); bool foundOutdated = false; - const auto &sets = Auth().data().stickerSets(); - const auto &order = Auth().data().stickerSetsOrder(); + const auto &sets = Auth().data().stickers().sets(); + const auto &order = Auth().data().stickers().setsOrder(); for (auto i = order.cbegin(), e = order.cend(); i != e; ++i) { auto it = sets.find(*i); if (it != sets.cend()) { const auto set = it->second.get(); - if (set->id == Stickers::DefaultSetId) { + if (set->id == Data::Stickers::DefaultSetId) { foundOutdated = true; } else if (!(set->flags & MTPDstickerSet_ClientFlag::f_special) && !(set->flags & MTPDstickerSet::Flag::f_archived)) { @@ -4070,17 +4073,17 @@ int32 countStickersHash(bool checkOutdatedInfo) { } int32 countRecentStickersHash() { - return countSpecialStickerSetHash(Stickers::CloudRecentSetId); + return countSpecialStickerSetHash(Data::Stickers::CloudRecentSetId); } int32 countFavedStickersHash() { - return countSpecialStickerSetHash(Stickers::FavedSetId); + return countSpecialStickerSetHash(Data::Stickers::FavedSetId); } int32 countFeaturedStickersHash() { auto result = Api::HashInit(); - const auto &sets = Auth().data().stickerSets(); - const auto &featured = Auth().data().featuredStickerSetsOrder(); + const auto &sets = Auth().data().stickers().sets(); + const auto &featured = Auth().data().stickers().featuredSetsOrder(); for (const auto setId : featured) { Api::HashUpdate(result, setId); @@ -4094,13 +4097,13 @@ int32 countFeaturedStickersHash() { } int32 countSavedGifsHash() { - return countDocumentVectorHash(Auth().data().savedGifs()); + return countDocumentVectorHash(Auth().data().stickers().savedGifs()); } void writeSavedGifs() { if (!_working()) return; - auto &saved = Auth().data().savedGifs(); + auto &saved = Auth().data().stickers().savedGifs(); if (saved.isEmpty()) { if (_savedGifsKey) { ClearKey(_savedGifsKey); @@ -4140,7 +4143,7 @@ void readSavedGifs() { return; } - auto &saved = Auth().data().savedGifsRef(); + auto &saved = Auth().data().stickers().savedGifsRef(); const auto failed = [&] { ClearKey(_savedGifsKey); _savedGifsKey = 0; diff --git a/Telegram/SourceFiles/storage/serialize_document.cpp b/Telegram/SourceFiles/storage/serialize_document.cpp index 072942075..0799e4241 100644 --- a/Telegram/SourceFiles/storage/serialize_document.cpp +++ b/Telegram/SourceFiles/storage/serialize_document.cpp @@ -8,8 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/serialize_document.h" #include "storage/serialize_common.h" -#include "chat_helpers/stickers.h" #include "data/data_session.h" +#include "data/stickers/data_stickers.h" #include "ui/image/image.h" #include "main/main_session.h" @@ -91,10 +91,10 @@ 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::FavedSetId - || info->setId == Stickers::CustomSetId) { + if (info->setId == Data::Stickers::DefaultSetId + || info->setId == Data::Stickers::CloudRecentSetId + || info->setId == Data::Stickers::FavedSetId + || info->setId == Data::Stickers::CustomSetId) { typeOfSet = StickerSetTypeEmpty; } diff --git a/Telegram/SourceFiles/support/support_helper.cpp b/Telegram/SourceFiles/support/support_helper.cpp index 3b8c6d361..9b7785c96 100644 --- a/Telegram/SourceFiles/support/support_helper.cpp +++ b/Telegram/SourceFiles/support/support_helper.cpp @@ -571,7 +571,9 @@ QString ChatOccupiedString(not_null history) { : hand + ' ' + name + " is here"; } -QString InterpretSendPath(const QString &path) { +QString InterpretSendPath( + not_null window, + const QString &path) { QFile f(path); if (!f.open(QIODevice::ReadOnly)) { return "App Error: Could not open interpret file: " + path; @@ -584,7 +586,7 @@ QString InterpretSendPath(const QString &path) { auto caption = QString(); for (const auto &line : lines) { if (line.startsWith(qstr("from: "))) { - if (Auth().userId() != line.mid(qstr("from: ").size()).toInt()) { + if (window->session().userId() != line.mid(qstr("from: ").size()).toInt()) { return "App Error: Wrong current user."; } } else if (line.startsWith(qstr("channel: "))) { @@ -604,7 +606,7 @@ QString InterpretSendPath(const QString &path) { return "App Error: Invalid command: " + line; } } - const auto history = Auth().data().historyLoaded(toId); + const auto history = window->session().data().historyLoaded(toId); if (!history) { return "App Error: Could not find channel with id: " + QString::number(peerToChannel(toId)); } diff --git a/Telegram/SourceFiles/support/support_helper.h b/Telegram/SourceFiles/support/support_helper.h index 46cf1b468..1352705fa 100644 --- a/Telegram/SourceFiles/support/support_helper.h +++ b/Telegram/SourceFiles/support/support_helper.h @@ -107,6 +107,8 @@ private: QString ChatOccupiedString(not_null history); -QString InterpretSendPath(const QString &path); +QString InterpretSendPath( + not_null window, + const QString &path); } // namespace Support diff --git a/Telegram/SourceFiles/ui/image/image.cpp b/Telegram/SourceFiles/ui/image/image.cpp index 6fce4b879..ceeff1125 100644 --- a/Telegram/SourceFiles/ui/image/image.cpp +++ b/Telegram/SourceFiles/ui/image/image.cpp @@ -9,7 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "storage/cache/storage_cache_database.h" #include "data/data_session.h" -#include "chat_helpers/stickers.h" #include "main/main_session.h" #include "app.h" diff --git a/Telegram/SourceFiles/window/window_media_preview.cpp b/Telegram/SourceFiles/window/window_media_preview.cpp index 4ed7bf3a1..2b571a371 100644 --- a/Telegram/SourceFiles/window/window_media_preview.cpp +++ b/Telegram/SourceFiles/window/window_media_preview.cpp @@ -11,11 +11,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_photo_media.h" #include "data/data_document.h" #include "data/data_document_media.h" +#include "data/data_session.h" +#include "data/stickers/data_stickers.h" #include "ui/image/image.h" #include "ui/emoji_config.h" #include "lottie/lottie_single_player.h" #include "main/main_session.h" -#include "chat_helpers/stickers.h" #include "window/window_session_controller.h" #include "styles/style_layers.h" #include "styles/style_chat_helpers.h" @@ -174,7 +175,7 @@ void MediaPreviewWidget::fillEmojiString() { return; } if (auto sticker = _document->sticker()) { - if (auto list = Stickers::GetEmojiListFromSet(_document)) { + if (auto list = _document->owner().stickers().getEmojiListFromSet(_document)) { _emojiList = std::move(*list); while (_emojiList.size() > kStickerPreviewEmojiLimit) { _emojiList.pop_back();