Move stickers code to Data::Stickers class.

This commit is contained in:
John Preston 2020-06-08 21:24:36 +04:00
parent 27af83267e
commit fc174f742a
39 changed files with 1461 additions and 1304 deletions

View file

@ -293,16 +293,14 @@ PRIVATE
chat_helpers/message_field.h chat_helpers/message_field.h
chat_helpers/spellchecker_common.cpp chat_helpers/spellchecker_common.cpp
chat_helpers/spellchecker_common.h chat_helpers/spellchecker_common.h
chat_helpers/stickers.cpp
chat_helpers/stickers.h
chat_helpers/stickers_emoji_pack.cpp chat_helpers/stickers_emoji_pack.cpp
chat_helpers/stickers_emoji_pack.h chat_helpers/stickers_emoji_pack.h
chat_helpers/stickers_dice_pack.cpp chat_helpers/stickers_dice_pack.cpp
chat_helpers/stickers_dice_pack.h chat_helpers/stickers_dice_pack.h
chat_helpers/stickers_list_widget.cpp chat_helpers/stickers_list_widget.cpp
chat_helpers/stickers_list_widget.h chat_helpers/stickers_list_widget.h
chat_helpers/stickers_set.cpp chat_helpers/stickers_lottie.cpp
chat_helpers/stickers_set.h chat_helpers/stickers_lottie.h
chat_helpers/tabbed_panel.cpp chat_helpers/tabbed_panel.cpp
chat_helpers/tabbed_panel.h chat_helpers/tabbed_panel.h
chat_helpers/tabbed_section.cpp chat_helpers/tabbed_section.cpp
@ -344,6 +342,10 @@ PRIVATE
core/utils.cpp core/utils.cpp
core/utils.h core/utils.h
core/version.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.cpp
data/data_abstract_structure.h data/data_abstract_structure.h
data/data_auto_download.cpp data/data_auto_download.cpp

View file

@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "data/data_histories.h" #include "data/data_histories.h"
#include "data/stickers/data_stickers.h"
#include "history/history.h" #include "history/history.h"
#include "history/history_message.h" // NewMessageFlags. #include "history/history_message.h" // NewMessageFlags.
#include "chat_helpers/message_field.h" // ConvertTextTagsToEntities. #include "chat_helpers/message_field.h" // ConvertTextTagsToEntities.
@ -192,7 +193,7 @@ void SendExistingDocument(
if (document->sticker()) { if (document->sticker()) {
if (const auto main = App::main()) { if (const auto main = App::main()) {
main->incrementSticker(document); main->incrementSticker(document);
document->owner().notifyRecentStickersUpdated(); document->owner().stickers().notifyRecentUpdated();
} }
} }
} }

View file

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_text_entities.h" #include "api/api_text_entities.h"
#include "api/api_self_destruct.h" #include "api/api_self_destruct.h"
#include "api/api_sensitive_content.h" #include "api/api_sensitive_content.h"
#include "data/stickers/data_stickers.h"
#include "data/data_drafts.h" #include "data/data_drafts.h"
#include "data/data_photo.h" #include "data/data_photo.h"
#include "data/data_web_page.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_cloud_themes.h"
#include "data/data_chat_filters.h" #include "data/data_chat_filters.h"
#include "data/data_histories.h" #include "data/data_histories.h"
#include "data/stickers/data_stickers.h"
#include "dialogs/dialogs_key.h" #include "dialogs/dialogs_key.h"
#include "core/core_cloud_password.h" #include "core/core_cloud_password.h"
#include "core/application.h" #include "core/application.h"
@ -55,7 +57,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "window/themes/window_theme.h" #include "window/themes/window_theme.h"
#include "inline_bots/inline_bot_result.h" #include "inline_bots/inline_bot_result.h"
#include "chat_helpers/message_field.h" #include "chat_helpers/message_field.h"
#include "chat_helpers/stickers.h"
#include "ui/text_options.h" #include "ui/text_options.h"
#include "ui/emoji_config.h" #include "ui/emoji_config.h"
#include "support/support_helper.h" #include "support/support_helper.h"
@ -1852,8 +1853,8 @@ void ApiWrap::requestStickerSets() {
} }
void ApiWrap::saveStickerSets( void ApiWrap::saveStickerSets(
const Stickers::Order &localOrder, const Data::StickersSetsOrder &localOrder,
const Stickers::Order &localRemoved) { const Data::StickersSetsOrder &localRemoved) {
for (auto requestId : base::take(_stickerSetDisenableRequests)) { for (auto requestId : base::take(_stickerSetDisenableRequests)) {
request(requestId).cancel(); request(requestId).cancel();
} }
@ -1861,16 +1862,16 @@ void ApiWrap::saveStickerSets(
request(base::take(_stickersClearRecentRequestId)).cancel(); request(base::take(_stickersClearRecentRequestId)).cancel();
auto writeInstalled = true, writeRecent = false, writeCloudRecent = false, writeFaved = false, writeArchived = false; auto writeInstalled = true, writeRecent = false, writeCloudRecent = false, writeFaved = false, writeArchived = false;
auto &recent = Stickers::GetRecentPack(); auto &recent = _session->data().stickers().getRecentPack();
auto &sets = _session->data().stickerSetsRef(); auto &sets = _session->data().stickers().setsRef();
_stickersOrder = localOrder; _stickersOrder = localOrder;
for (const auto removedSetId : localRemoved) { for (const auto removedSetId : localRemoved) {
if (removedSetId == Stickers::CloudRecentSetId) { if (removedSetId == Data::Stickers::CloudRecentSetId) {
if (sets.remove(Stickers::CloudRecentSetId) != 0) { if (sets.remove(Data::Stickers::CloudRecentSetId) != 0) {
writeCloudRecent = true; writeCloudRecent = true;
} }
if (sets.remove(Stickers::CustomSetId)) { if (sets.remove(Data::Stickers::CustomSetId)) {
writeInstalled = true; writeInstalled = true;
} }
if (!recent.isEmpty()) { if (!recent.isEmpty()) {
@ -1910,8 +1911,8 @@ void ApiWrap::saveStickerSets(
_stickerSetDisenableRequests.insert(requestId); _stickerSetDisenableRequests.insert(requestId);
int removeIndex = _session->data().stickerSetsOrder().indexOf(set->id); int removeIndex = _session->data().stickers().setsOrder().indexOf(set->id);
if (removeIndex >= 0) _session->data().stickerSetsOrderRef().removeAt(removeIndex); if (removeIndex >= 0) _session->data().stickers().setsOrderRef().removeAt(removeIndex);
if (!(set->flags & MTPDstickerSet_ClientFlag::f_featured) if (!(set->flags & MTPDstickerSet_ClientFlag::f_featured)
&& !(set->flags & MTPDstickerSet_ClientFlag::f_special)) { && !(set->flags & MTPDstickerSet_ClientFlag::f_special)) {
sets.erase(it); sets.erase(it);
@ -1933,7 +1934,7 @@ void ApiWrap::saveStickerSets(
} }
} }
auto &order = _session->data().stickerSetsOrderRef(); auto &order = _session->data().stickers().setsOrderRef();
order.clear(); order.clear();
for (const auto setId : std::as_const(_stickersOrder)) { for (const auto setId : std::as_const(_stickersOrder)) {
auto it = sets.find(setId); auto it = sets.find(setId);
@ -1984,7 +1985,7 @@ void ApiWrap::saveStickerSets(
if (writeArchived) Local::writeArchivedStickers(); if (writeArchived) Local::writeArchivedStickers();
if (writeCloudRecent) Local::writeRecentStickers(); if (writeCloudRecent) Local::writeRecentStickers();
if (writeFaved) Local::writeFavedStickers(); if (writeFaved) Local::writeFavedStickers();
_session->data().notifyStickersUpdated(); _session->data().stickers().notifyUpdated();
if (_stickerSetDisenableRequests.empty()) { if (_stickerSetDisenableRequests.empty()) {
stickersSaveOrder(); stickersSaveOrder();
@ -2567,7 +2568,7 @@ void ApiWrap::applyNotifySettings(
void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result) { void ApiWrap::gotStickerSet(uint64 setId, const MTPmessages_StickerSet &result) {
_stickerSetRequests.remove(setId); _stickerSetRequests.remove(setId);
Stickers::FeedSetFull(result); _session->data().stickers().feedSetFull(result);
} }
void ApiWrap::requestWebPageDelayed(WebPageData *page) { void ApiWrap::requestWebPageDelayed(WebPageData *page) {
@ -2921,13 +2922,13 @@ void ApiWrap::refreshFileReference(
}, [&](Data::FileOriginPeerPhoto data) { }, [&](Data::FileOriginPeerPhoto data) {
fail(); fail();
}, [&](Data::FileOriginStickerSet data) { }, [&](Data::FileOriginStickerSet data) {
if (data.setId == Stickers::CloudRecentSetId if (data.setId == Data::Stickers::CloudRecentSetId
|| data.setId == Stickers::RecentSetId) { || data.setId == Data::Stickers::RecentSetId) {
request(MTPmessages_GetRecentStickers( request(MTPmessages_GetRecentStickers(
MTP_flags(0), MTP_flags(0),
MTP_int(0)), MTP_int(0)),
[] { crl::on_main([] { Local::writeRecentStickers(); }); }); [] { crl::on_main([] { Local::writeRecentStickers(); }); });
} else if (data.setId == Stickers::FavedSetId) { } else if (data.setId == Data::Stickers::FavedSetId) {
request(MTPmessages_GetFavedStickers(MTP_int(0)), request(MTPmessages_GetFavedStickers(MTP_int(0)),
[] { crl::on_main([] { Local::writeFavedStickers(); }); }); [] { crl::on_main([] { Local::writeFavedStickers(); }); });
} else { } else {
@ -2979,21 +2980,25 @@ void ApiWrap::gotWebPages(ChannelData *channel, const MTPmessages_Messages &resu
} }
void ApiWrap::stickersSaveOrder() { void ApiWrap::stickersSaveOrder() {
if (_stickersOrder.size() > 1) { if (_stickersOrder.size() < 2) {
QVector<MTPlong> mtpOrder; return;
mtpOrder.reserve(_stickersOrder.size());
for_const (auto setId, _stickersOrder) {
mtpOrder.push_back(MTP_long(setId));
}
_stickersReorderRequestId = request(MTPmessages_ReorderStickerSets(MTP_flags(0), MTP_vector<MTPlong>(mtpOrder))).done([this](const MTPBool &result) {
_stickersReorderRequestId = 0;
}).fail([this](const RPCError &error) {
_stickersReorderRequestId = 0;
_session->data().setLastStickersUpdate(0);
updateStickers();
}).send();
} }
QVector<MTPlong> 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<MTPlong>(mtpOrder)
)).done([=](const MTPBool &result) {
_stickersReorderRequestId = 0;
}).fail([=](const RPCError &error) {
_stickersReorderRequestId = 0;
_session->data().stickers().setLastUpdate(0);
updateStickers();
}).send();
} }
void ApiWrap::updateStickers() { void ApiWrap::updateStickers() {
@ -3014,7 +3019,7 @@ void ApiWrap::setGroupStickerSet(not_null<ChannelData*> megagroup, const MTPInpu
megagroup->mgInfo->stickerSet = set; megagroup->mgInfo->stickerSet = set;
request(MTPchannels_SetStickers(megagroup->inputChannel, set)).send(); request(MTPchannels_SetStickers(megagroup->inputChannel, set)).send();
_session->data().notifyStickersUpdated(); _session->data().stickers().notifyUpdated();
} }
std::vector<not_null<DocumentData*>> *ApiWrap::stickersByEmoji( std::vector<not_null<DocumentData*>> *ApiWrap::stickersByEmoji(
@ -3054,7 +3059,7 @@ std::vector<not_null<DocumentData*>> *ApiWrap::stickersByEmoji(
} }
entry.hash = data.vhash().v; entry.hash = data.vhash().v;
entry.received = crl::now(); entry.received = crl::now();
_session->data().notifyStickersUpdated(); _session->data().stickers().notifyUpdated();
}).send(); }).send();
} }
if (it == _stickersByEmoji.end()) { if (it == _stickersByEmoji.end()) {
@ -3081,7 +3086,7 @@ void ApiWrap::toggleFavedSticker(
MTP_bool(!faved) MTP_bool(!faved)
)).done([=](const MTPBool &result) { )).done([=](const MTPBool &result) {
if (mtpIsTrue(result)) { if (mtpIsTrue(result)) {
Stickers::SetFaved(document, faved); _session->data().stickers().setFaved(document, faved);
} }
}).fail([=](const RPCError &error) { }).fail([=](const RPCError &error) {
(*failHandler)(error, usedFileReference); (*failHandler)(error, usedFileReference);
@ -3118,7 +3123,7 @@ void ApiWrap::toggleSavedGif(
)).done([=](const MTPBool &result) { )).done([=](const MTPBool &result) {
if (mtpIsTrue(result)) { if (mtpIsTrue(result)) {
if (saved) { if (saved) {
session().data().addSavedGif(document); _session->data().stickers().addSavedGif(document);
} }
} }
}).fail([=](const RPCError &error) { }).fail([=](const RPCError &error) {
@ -3140,19 +3145,21 @@ void ApiWrap::toggleSavedGif(
} }
void ApiWrap::requestStickers(TimeId now) { void ApiWrap::requestStickers(TimeId now) {
if (!_session->data().stickersUpdateNeeded(now) if (!_session->data().stickers().updateNeeded(now)
|| _stickersUpdateRequest) { || _stickersUpdateRequest) {
return; return;
} }
auto onDone = [this](const MTPmessages_AllStickers &result) { auto onDone = [this](const MTPmessages_AllStickers &result) {
_session->data().setLastStickersUpdate(crl::now()); _session->data().stickers().setLastUpdate(crl::now());
_stickersUpdateRequest = 0; _stickersUpdateRequest = 0;
switch (result.type()) { switch (result.type()) {
case mtpc_messages_allStickersNotModified: return; case mtpc_messages_allStickersNotModified: return;
case mtpc_messages_allStickers: { case mtpc_messages_allStickers: {
auto &d = result.c_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; } return;
default: Unexpected("Type in ApiWrap::stickersDone()"); default: Unexpected("Type in ApiWrap::stickersDone()");
} }
@ -3166,7 +3173,7 @@ void ApiWrap::requestStickers(TimeId now) {
} }
void ApiWrap::requestRecentStickers(TimeId now) { void ApiWrap::requestRecentStickers(TimeId now) {
if (!_session->data().recentStickersUpdateNeeded(now)) { if (!_session->data().stickers().recentUpdateNeeded(now)) {
return; return;
} }
requestRecentStickersWithHash(Local::countRecentStickersHash()); requestRecentStickersWithHash(Local::countRecentStickersHash());
@ -3180,15 +3187,15 @@ void ApiWrap::requestRecentStickersWithHash(int32 hash) {
MTP_flags(0), MTP_flags(0),
MTP_int(hash) MTP_int(hash)
)).done([=](const MTPmessages_RecentStickers &result) { )).done([=](const MTPmessages_RecentStickers &result) {
_session->data().setLastRecentStickersUpdate(crl::now()); _session->data().stickers().setLastRecentUpdate(crl::now());
_recentStickersUpdateRequest = 0; _recentStickersUpdateRequest = 0;
switch (result.type()) { switch (result.type()) {
case mtpc_messages_recentStickersNotModified: return; case mtpc_messages_recentStickersNotModified: return;
case mtpc_messages_recentStickers: { case mtpc_messages_recentStickers: {
auto &d = result.c_messages_recentStickers(); auto &d = result.c_messages_recentStickers();
Stickers::SpecialSetReceived( _session->data().stickers().specialSetReceived(
Stickers::CloudRecentSetId, Data::Stickers::CloudRecentSetId,
tr::lng_recent_stickers(tr::now), tr::lng_recent_stickers(tr::now),
d.vstickers().v, d.vstickers().v,
d.vhash().v, d.vhash().v,
@ -3198,7 +3205,7 @@ void ApiWrap::requestRecentStickersWithHash(int32 hash) {
default: Unexpected("Type in ApiWrap::recentStickersDone()"); default: Unexpected("Type in ApiWrap::recentStickersDone()");
} }
}).fail([=](const RPCError &error) { }).fail([=](const RPCError &error) {
_session->data().setLastRecentStickersUpdate(crl::now()); _session->data().stickers().setLastRecentUpdate(crl::now());
_recentStickersUpdateRequest = 0; _recentStickersUpdateRequest = 0;
LOG(("App Fail: Failed to get recent stickers!")); LOG(("App Fail: Failed to get recent stickers!"));
@ -3206,22 +3213,22 @@ void ApiWrap::requestRecentStickersWithHash(int32 hash) {
} }
void ApiWrap::requestFavedStickers(TimeId now) { void ApiWrap::requestFavedStickers(TimeId now) {
if (!_session->data().favedStickersUpdateNeeded(now) if (!_session->data().stickers().favedUpdateNeeded(now)
|| _favedStickersUpdateRequest) { || _favedStickersUpdateRequest) {
return; return;
} }
_favedStickersUpdateRequest = request(MTPmessages_GetFavedStickers( _favedStickersUpdateRequest = request(MTPmessages_GetFavedStickers(
MTP_int(Local::countFavedStickersHash()) MTP_int(Local::countFavedStickersHash())
)).done([=](const MTPmessages_FavedStickers &result) { )).done([=](const MTPmessages_FavedStickers &result) {
_session->data().setLastFavedStickersUpdate(crl::now()); _session->data().stickers().setLastFavedUpdate(crl::now());
_favedStickersUpdateRequest = 0; _favedStickersUpdateRequest = 0;
switch (result.type()) { switch (result.type()) {
case mtpc_messages_favedStickersNotModified: return; case mtpc_messages_favedStickersNotModified: return;
case mtpc_messages_favedStickers: { case mtpc_messages_favedStickers: {
auto &d = result.c_messages_favedStickers(); auto &d = result.c_messages_favedStickers();
Stickers::SpecialSetReceived( _session->data().stickers().specialSetReceived(
Stickers::FavedSetId, Data::Stickers::FavedSetId,
Lang::Hard::FavedSetTitle(), Lang::Hard::FavedSetTitle(),
d.vstickers().v, d.vstickers().v,
d.vhash().v, d.vhash().v,
@ -3230,7 +3237,7 @@ void ApiWrap::requestFavedStickers(TimeId now) {
default: Unexpected("Type in ApiWrap::favedStickersDone()"); default: Unexpected("Type in ApiWrap::favedStickersDone()");
} }
}).fail([=](const RPCError &error) { }).fail([=](const RPCError &error) {
_session->data().setLastFavedStickersUpdate(crl::now()); _session->data().stickers().setLastFavedUpdate(crl::now());
_favedStickersUpdateRequest = 0; _favedStickersUpdateRequest = 0;
LOG(("App Fail: Failed to get faved stickers!")); LOG(("App Fail: Failed to get faved stickers!"));
@ -3238,26 +3245,29 @@ void ApiWrap::requestFavedStickers(TimeId now) {
} }
void ApiWrap::requestFeaturedStickers(TimeId now) { void ApiWrap::requestFeaturedStickers(TimeId now) {
if (!_session->data().featuredStickersUpdateNeeded(now) if (!_session->data().stickers().featuredUpdateNeeded(now)
|| _featuredStickersUpdateRequest) { || _featuredStickersUpdateRequest) {
return; return;
} }
_featuredStickersUpdateRequest = request(MTPmessages_GetFeaturedStickers( _featuredStickersUpdateRequest = request(MTPmessages_GetFeaturedStickers(
MTP_int(Local::countFeaturedStickersHash()) MTP_int(Local::countFeaturedStickersHash())
)).done([=](const MTPmessages_FeaturedStickers &result) { )).done([=](const MTPmessages_FeaturedStickers &result) {
_session->data().setLastFeaturedStickersUpdate(crl::now()); _session->data().stickers().setLastFeaturedUpdate(crl::now());
_featuredStickersUpdateRequest = 0; _featuredStickersUpdateRequest = 0;
switch (result.type()) { switch (result.type()) {
case mtpc_messages_featuredStickersNotModified: return; case mtpc_messages_featuredStickersNotModified: return;
case mtpc_messages_featuredStickers: { case mtpc_messages_featuredStickers: {
auto &d = result.c_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; } return;
default: Unexpected("Type in ApiWrap::featuredStickersDone()"); default: Unexpected("Type in ApiWrap::featuredStickersDone()");
} }
}).fail([=](const RPCError &error) { }).fail([=](const RPCError &error) {
_session->data().setLastFeaturedStickersUpdate(crl::now()); _session->data().stickers().setLastFeaturedUpdate(crl::now());
_featuredStickersUpdateRequest = 0; _featuredStickersUpdateRequest = 0;
LOG(("App Fail: Failed to get featured stickers!")); LOG(("App Fail: Failed to get featured stickers!"));
@ -3265,26 +3275,28 @@ void ApiWrap::requestFeaturedStickers(TimeId now) {
} }
void ApiWrap::requestSavedGifs(TimeId now) { void ApiWrap::requestSavedGifs(TimeId now) {
if (!_session->data().savedGifsUpdateNeeded(now) if (!_session->data().stickers().savedGifsUpdateNeeded(now)
|| _savedGifsUpdateRequest) { || _savedGifsUpdateRequest) {
return; return;
} }
_savedGifsUpdateRequest = request(MTPmessages_GetSavedGifs( _savedGifsUpdateRequest = request(MTPmessages_GetSavedGifs(
MTP_int(Local::countSavedGifsHash()) MTP_int(Local::countSavedGifsHash())
)).done([=](const MTPmessages_SavedGifs &result) { )).done([=](const MTPmessages_SavedGifs &result) {
_session->data().setLastSavedGifsUpdate(crl::now()); _session->data().stickers().setLastSavedGifsUpdate(crl::now());
_savedGifsUpdateRequest = 0; _savedGifsUpdateRequest = 0;
switch (result.type()) { switch (result.type()) {
case mtpc_messages_savedGifsNotModified: return; case mtpc_messages_savedGifsNotModified: return;
case mtpc_messages_savedGifs: { case mtpc_messages_savedGifs: {
auto &d = result.c_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; } return;
default: Unexpected("Type in ApiWrap::savedGifsDone()"); default: Unexpected("Type in ApiWrap::savedGifsDone()");
} }
}).fail([=](const RPCError &error) { }).fail([=](const RPCError &error) {
_session->data().setLastSavedGifsUpdate(crl::now()); _session->data().stickers().setLastSavedGifsUpdate(crl::now());
_savedGifsUpdateRequest = 0; _savedGifsUpdateRequest = 0;
LOG(("App Fail: Failed to get saved gifs!")); LOG(("App Fail: Failed to get saved gifs!"));
@ -3299,8 +3311,8 @@ void ApiWrap::readFeaturedSetDelayed(uint64 setId) {
} }
void ApiWrap::readFeaturedSets() { void ApiWrap::readFeaturedSets() {
const auto &sets = _session->data().stickerSets(); const auto &sets = _session->data().stickers().sets();
auto count = _session->data().featuredStickerSetsUnreadCount(); auto count = _session->data().stickers().featuredSetsUnreadCount();
QVector<MTPlong> wrappedIds; QVector<MTPlong> wrappedIds;
wrappedIds.reserve(_featuredSetsRead.size()); wrappedIds.reserve(_featuredSetsRead.size());
for (const auto setId : _featuredSetsRead) { for (const auto setId : _featuredSetsRead) {
@ -3320,10 +3332,10 @@ void ApiWrap::readFeaturedSets() {
MTP_vector<MTPlong>(wrappedIds)); MTP_vector<MTPlong>(wrappedIds));
request(std::move(requestData)).done([=](const MTPBool &result) { request(std::move(requestData)).done([=](const MTPBool &result) {
Local::writeFeaturedStickers(); Local::writeFeaturedStickers();
_session->data().notifyStickersUpdated(); _session->data().stickers().notifyUpdated();
}).send(); }).send();
_session->data().setFeaturedStickerSetsUnreadCount(count); _session->data().stickers().setFeaturedSetsUnreadCount(count);
} }
} }

View file

@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "base/flat_map.h" #include "base/flat_map.h"
#include "base/flat_set.h" #include "base/flat_set.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
#include "chat_helpers/stickers_set.h" #include "data/stickers/data_stickers_set.h"
#include "data/data_messages.h" #include "data/data_messages.h"
class TaskQueue; class TaskQueue;
@ -260,8 +260,8 @@ public:
void scheduleStickerSetRequest(uint64 setId, uint64 access); void scheduleStickerSetRequest(uint64 setId, uint64 access);
void requestStickerSets(); void requestStickerSets();
void saveStickerSets( void saveStickerSets(
const Stickers::Order &localOrder, const Data::StickersSetsOrder &localOrder,
const Stickers::Order &localRemoved); const Data::StickersSetsOrder &localRemoved);
void updateStickers(); void updateStickers();
void requestRecentStickersForce(); void requestRecentStickersForce();
void setGroupStickerSet( void setGroupStickerSet(
@ -724,7 +724,7 @@ private:
base::Timer _draftsSaveTimer; base::Timer _draftsSaveTimer;
base::flat_set<mtpRequestId> _stickerSetDisenableRequests; base::flat_set<mtpRequestId> _stickerSetDisenableRequests;
Stickers::Order _stickersOrder; Data::StickersSetsOrder _stickersOrder;
mtpRequestId _stickersReorderRequestId = 0; mtpRequestId _stickersReorderRequestId = 0;
mtpRequestId _stickersClearRecentRequestId = 0; mtpRequestId _stickersClearRecentRequestId = 0;

View file

@ -11,8 +11,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "data/data_document_media.h" #include "data/data_document_media.h"
#include "data/stickers/data_stickers.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "chat_helpers/stickers.h"
#include "boxes/confirm_box.h" #include "boxes/confirm_box.h"
#include "core/application.h" #include "core/application.h"
#include "mtproto/sender.h" #include "mtproto/sender.h"
@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/emoji_config.h" #include "ui/emoji_config.h"
#include "lottie/lottie_multi_player.h" #include "lottie/lottie_multi_player.h"
#include "lottie/lottie_animation.h" #include "lottie/lottie_animation.h"
#include "chat_helpers/stickers_lottie.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "main/main_session.h" #include "main/main_session.h"
@ -43,6 +44,10 @@ namespace {
constexpr auto kStickersPanelPerRow = 5; constexpr auto kStickersPanelPerRow = 5;
using Data::StickersSet;
using Data::StickersPack;
using Data::StickersByEmojiMap;
} // namespace } // namespace
class StickerSetBox::Inner : public Ui::RpWidget, private base::Subscriber { class StickerSetBox::Inner : public Ui::RpWidget, private base::Subscriber {
@ -106,8 +111,8 @@ private:
MTP::Sender _api; MTP::Sender _api;
std::vector<Element> _elements; std::vector<Element> _elements;
std::unique_ptr<Lottie::MultiPlayer> _lottiePlayer; std::unique_ptr<Lottie::MultiPlayer> _lottiePlayer;
Stickers::Pack _pack; StickersPack _pack;
Stickers::ByEmojiMap _emoji; StickersByEmojiMap _emoji;
bool _loaded = false; bool _loaded = false;
uint64 _setId = 0; uint64 _setId = 0;
uint64 _setAccess = 0; uint64 _setAccess = 0;
@ -159,7 +164,7 @@ void StickerSetBox::prepare() {
_inner = setInnerWidget( _inner = setInnerWidget(
object_ptr<Inner>(this, _controller, _set), object_ptr<Inner>(this, _controller, _set),
st::stickersScroll); st::stickersScroll);
_controller->session().data().stickersUpdated( _controller->session().data().stickers().updated(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
updateButtons(); updateButtons();
}, lifetime()); }, lifetime());
@ -278,7 +283,7 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
const auto original = emoji->original(); const auto original = emoji->original();
auto &stickers = pack.vdocuments().v; auto &stickers = pack.vdocuments().v;
auto p = Stickers::Pack(); auto p = StickersPack();
p.reserve(stickers.size()); p.reserve(stickers.size());
for (auto j = 0, c = stickers.size(); j != c; ++j) { for (auto j = 0, c = stickers.size(); j != c; ++j) {
auto doc = _controller->session().data().document(stickers[j].v); 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) { data.vset().match([&](const MTPDstickerSet &set) {
_setTitle = Stickers::GetSetTitle(set); _setTitle = _controller->session().data().stickers().getSetTitle(
set);
_setShortName = qs(set.vshort_name()); _setShortName = qs(set.vshort_name());
_setId = set.vid().v; _setId = set.vid().v;
_setAccess = set.vaccess_hash().v; _setAccess = set.vaccess_hash().v;
@ -307,7 +313,7 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
} else { } else {
_setThumbnail = ImageWithLocation(); _setThumbnail = ImageWithLocation();
} }
const auto &sets = _controller->session().data().stickerSets(); const auto &sets = _controller->session().data().stickers().sets();
const auto it = sets.find(_setId); const auto it = sets.find(_setId);
if (it != sets.cend()) { if (it != sets.cend()) {
const auto set = it->second.get(); const auto set = it->second.get();
@ -350,13 +356,13 @@ rpl::producer<> StickerSetBox::Inner::updateControls() const {
void StickerSetBox::Inner::installDone( void StickerSetBox::Inner::installDone(
const MTPmessages_StickerSetInstallResult &result) { const MTPmessages_StickerSetInstallResult &result) {
auto &sets = _controller->session().data().stickerSetsRef(); auto &sets = _controller->session().data().stickers().setsRef();
bool wasArchived = (_setFlags & MTPDstickerSet::Flag::f_archived); bool wasArchived = (_setFlags & MTPDstickerSet::Flag::f_archived);
if (wasArchived) { if (wasArchived) {
auto index = _controller->session().data().archivedStickerSetsOrderRef().indexOf(_setId); auto index = _controller->session().data().stickers().archivedSetsOrderRef().indexOf(_setId);
if (index >= 0) { if (index >= 0) {
_controller->session().data().archivedStickerSetsOrderRef().removeAt(index); _controller->session().data().stickers().archivedSetsOrderRef().removeAt(index);
} }
} }
_setInstallDate = base::unixtime::now(); _setInstallDate = base::unixtime::now();
@ -366,7 +372,7 @@ void StickerSetBox::Inner::installDone(
if (it == sets.cend()) { if (it == sets.cend()) {
it = sets.emplace( it = sets.emplace(
_setId, _setId,
std::make_unique<Stickers::Set>( std::make_unique<StickersSet>(
&_controller->session().data(), &_controller->session().data(),
_setId, _setId,
_setAccess, _setAccess,
@ -385,7 +391,7 @@ void StickerSetBox::Inner::installDone(
set->stickers = _pack; set->stickers = _pack;
set->emoji = _emoji; set->emoji = _emoji;
auto &order = _controller->session().data().stickerSetsOrderRef(); auto &order = _controller->session().data().stickers().setsOrderRef();
int insertAtIndex = 0, currentIndex = order.indexOf(_setId); int insertAtIndex = 0, currentIndex = order.indexOf(_setId);
if (currentIndex != insertAtIndex) { if (currentIndex != insertAtIndex) {
if (currentIndex > 0) { if (currentIndex > 0) {
@ -394,7 +400,7 @@ void StickerSetBox::Inner::installDone(
order.insert(insertAtIndex, _setId); order.insert(insertAtIndex, _setId);
} }
const auto customIt = sets.find(Stickers::CustomSetId); const auto customIt = sets.find(Data::Stickers::CustomSetId);
if (customIt != sets.cend()) { if (customIt != sets.cend()) {
const auto custom = customIt->second.get(); const auto custom = customIt->second.get();
for (const auto sticker : std::as_const(_pack)) { for (const auto sticker : std::as_const(_pack)) {
@ -407,13 +413,14 @@ void StickerSetBox::Inner::installDone(
} }
if (result.type() == mtpc_messages_stickerSetInstallResultArchive) { if (result.type() == mtpc_messages_stickerSetInstallResultArchive) {
Stickers::ApplyArchivedResult(result.c_messages_stickerSetInstallResultArchive()); _controller->session().data().stickers().applyArchivedResult(
result.c_messages_stickerSetInstallResultArchive());
} else { } else {
if (wasArchived) { if (wasArchived) {
Local::writeArchivedStickers(); Local::writeArchivedStickers();
} }
Local::writeInstalledStickers(); Local::writeInstalledStickers();
_controller->session().data().notifyStickersUpdated(); _controller->session().data().stickers().notifyUpdated();
} }
_setInstalled.fire_copy(_setId); _setInstalled.fire_copy(_setId);
} }
@ -610,10 +617,10 @@ void StickerSetBox::Inner::setupLottie(int index) {
auto &element = _elements[index]; auto &element = _elements[index];
const auto document = element.document; const auto document = element.document;
element.animated = Stickers::LottieAnimationFromDocument( element.animated = ChatHelpers::LottieAnimationFromDocument(
getLottiePlayer(), getLottiePlayer(),
element.documentMedia.get(), element.documentMedia.get(),
Stickers::LottieSize::StickerSet, ChatHelpers::StickerLottieSize::StickerSet,
boundingBoxSize() * cIntRetinaFactor()); boundingBoxSize() * cIntRetinaFactor());
} }
@ -677,7 +684,7 @@ bool StickerSetBox::Inner::notInstalled() const {
if (!_loaded) { if (!_loaded) {
return false; return false;
} }
const auto &sets = _controller->session().data().stickerSets(); const auto &sets = _controller->session().data().stickers().sets();
const auto it = sets.find(_setId); const auto it = sets.find(_setId);
if ((it == sets.cend()) if ((it == sets.cend())
|| !(it->second->flags & MTPDstickerSet::Flag::f_installed_date) || !(it->second->flags & MTPDstickerSet::Flag::f_installed_date)

View file

@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/abstract_box.h" #include "boxes/abstract_box.h"
#include "base/timer.h" #include "base/timer.h"
#include "chat_helpers/stickers.h" #include "data/stickers/data_stickers.h"
class ConfirmBox; class ConfirmBox;

View file

@ -12,17 +12,18 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "data/data_document_media.h" #include "data/data_document_media.h"
#include "data/stickers/data_stickers.h"
#include "core/application.h" #include "core/application.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mainwidget.h" #include "mainwidget.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "chat_helpers/stickers.h"
#include "boxes/confirm_box.h" #include "boxes/confirm_box.h"
#include "boxes/sticker_set_box.h" #include "boxes/sticker_set_box.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "dialogs/dialogs_layout.h" #include "dialogs/dialogs_layout.h"
#include "lottie/lottie_single_player.h" #include "lottie/lottie_single_player.h"
#include "chat_helpers/stickers_lottie.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h" #include "ui/widgets/labels.h"
#include "ui/widgets/scroll_area.h" #include "ui/widgets/scroll_area.h"
@ -42,6 +43,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace { namespace {
using Data::StickersSet;
using Data::StickersSetsOrder;
using Data::StickersSetThumbnailView;
constexpr auto kArchivedLimitFirstRequest = 10; constexpr auto kArchivedLimitFirstRequest = 10;
constexpr auto kArchivedLimitPerPage = 30; constexpr auto kArchivedLimitPerPage = 30;
constexpr auto kHandleMegagroupSetAddressChangeTimeout = crl::time(1000); 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<Main::Session*> session,
Section section);
Inner(QWidget *parent, not_null<ChannelData*> megagroup);
base::Observable<int> scrollToY;
void setInnerFocus();
void saveGroupSet();
void rebuild();
void updateSize(int newWidth = 0);
void updateRows(); // refresh only pack cover stickers
bool appendSet(not_null<StickersSet*> set);
StickersSetsOrder getOrder() const;
StickersSetsOrder getFullOrder() const;
StickersSetsOrder getRemovedSets() const;
void setFullOrder(const StickersSetsOrder &order);
void setRemovedSets(const StickersSetsOrder &removed);
void setInstallSetCallback(Fn<void(uint64 setId)> callback) {
_installSetCallback = std::move(callback);
}
void setLoadMoreCallback(Fn<void()> callback) {
_loadMoreCallback = std::move(callback);
}
void setMinHeight(int newWidth, int minHeight);
int getVisibleTop() const {
return _visibleTop;
}
[[nodiscard]] rpl::producer<int> 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<StickersSet*> 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<StickersSet*> set;
DocumentData *sticker = nullptr;
std::shared_ptr<Data::DocumentMedia> stickerMedia;
std::shared_ptr<StickersSetThumbnailView> 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<Ui::RippleAnimation> ripple;
std::unique_ptr<Lottie::SinglePlayer> 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<MegagroupSet, int>;
class AddressField : public Ui::UsernameInput {
public:
using UsernameInput::UsernameInput;
protected:
void correctValue(
const QString &was,
int wasCursor,
QString &now,
int &nowCursor) override;
};
template <typename Check>
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*> row, int index);
void paintRowThumbnail(Painter &p, not_null<Row*> row, int left);
void paintFakeButton(Painter &p, not_null<Row*> row, int index);
void clear();
void updateCursor();
void setActionSel(int32 actionSel);
float64 aboveShadowOpacity() const;
void validateLottieAnimation(not_null<Row*> row);
void updateRowThumbnail(not_null<Row*> row);
void readVisibleSets();
void updateControlsGeometry();
void rebuildAppendSet(not_null<StickersSet*> set, int maxNameWidth);
void fillSetCover(not_null<StickersSet*> set, DocumentData **outSticker, int *outWidth, int *outHeight) const;
int fillSetCount(not_null<StickersSet*> set) const;
QString fillSetTitle(not_null<StickersSet*> set, int maxNameWidth, int *outTitleWidth) const;
void fillSetFlags(not_null<StickersSet*> 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<Main::Session*> _session;
MTP::Sender _api;
Section _section;
int32 _rowHeight;
std::vector<std::unique_ptr<Row>> _rows;
std::vector<crl::time> _shiftingStartTimes;
crl::time _aboveShadowFadeStart = 0;
anim::value _aboveShadowFadeOpacity;
Ui::Animations::Basic _shiftingAnimation;
Fn<void(uint64 setId)> _installSetCallback;
Fn<void()> _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<int> _draggingScrollDelta;
int _minHeight = 0;
int _scrollbar = 0;
ChannelData *_megagroupSet = nullptr;
MTPInputStickerSet _megagroupSetInput = MTP_inputStickerSetEmpty();
std::unique_ptr<Row> _megagroupSelectedSet;
object_ptr<AddressField> _megagroupSetField = { nullptr };
object_ptr<Ui::PlainShadow> _megagroupSelectedShadow = { nullptr };
object_ptr<Ui::CrossButton> _megagroupSelectedRemove = { nullptr };
object_ptr<Ui::BoxContentDivider> _megagroupDivider = { nullptr };
object_ptr<Ui::FlatLabel> _megagroupSubTitle = { nullptr };
base::Timer _megagroupSetAddressChangedTimer;
mtpRequestId _megagroupSetRequestId = 0;
};
StickersBox::CounterWidget::CounterWidget( StickersBox::CounterWidget::CounterWidget(
QWidget *parent, QWidget *parent,
rpl::producer<int> count) rpl::producer<int> count)
@ -120,6 +346,14 @@ void StickersBox::Tab::returnWidget(object_ptr<Inner> widget) {
Assert(_widget == _weak); Assert(_widget == _weak);
} }
StickersBox::Inner *StickersBox::Tab::widget() {
return _weak;
}
int StickersBox::Tab::index() const {
return _index;
}
void StickersBox::Tab::saveScrollTop() { void StickersBox::Tab::saveScrollTop() {
_scrollTop = widget()->getVisibleTop(); _scrollTop = widget()->getVisibleTop();
} }
@ -130,7 +364,9 @@ StickersBox::StickersBox(
Section section) Section section)
: _session(session) : _session(session)
, _tabs(this, st::stickersTabs) , _tabs(this, st::stickersTabs)
, _unreadBadge(this, _session->data().featuredStickerSetsUnreadCountValue()) , _unreadBadge(
this,
_session->data().stickers().featuredSetsUnreadCountValue())
, _section(section) , _section(section)
, _installed(0, this, session, Section::Installed) , _installed(0, this, session, Section::Installed)
, _featured(1, this, session, Section::Featured) , _featured(1, this, session, Section::Featured)
@ -143,7 +379,9 @@ StickersBox::StickersBox(QWidget*, not_null<ChannelData*> megagroup)
, _section(Section::Installed) , _section(Section::Installed)
, _installed(0, this, megagroup) , _installed(0, this, megagroup)
, _megagroupSet(megagroup) { , _megagroupSet(megagroup) {
subscribe(_installed.widget()->scrollToY, [this](int y) { onScrollToY(y); }); subscribe(_installed.widget()->scrollToY, [=](int y) {
onScrollToY(y);
});
} }
StickersBox::StickersBox( 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)) { if (_attached.widget()->appendSet(set)) {
addedSet = true; addedSet = true;
if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) { 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; _archivedRequestId = 0;
_archivedLoaded = true; _archivedLoaded = true;
if (result.type() != mtpc_messages_archivedStickers) { 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 &stickers = result.c_messages_archivedStickers();
auto &archived = _session->data().archivedStickerSetsOrderRef(); auto &archived = _session->data().stickers().archivedSetsOrderRef();
if (offsetId) { if (offsetId) {
auto index = archived.indexOf(offsetId); auto index = archived.indexOf(offsetId);
if (index >= 0) { if (index >= 0) {
@ -221,7 +461,7 @@ void StickersBox::getArchivedDone(uint64 offsetId, const MTPmessages_ArchivedSti
} }
if (!setData) continue; 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); const auto index = archived.indexOf(set->id);
if (archived.isEmpty() || index != archived.size() - 1) { if (archived.isEmpty() || index != archived.size() - 1) {
changedSets = true; changedSets = true;
@ -268,7 +508,7 @@ void StickersBox::prepare() {
setTitle(tr::lng_stickers_attached_sets()); setTitle(tr::lng_stickers_attached_sets());
} }
if (_tabs) { if (_tabs) {
if (_session->data().archivedStickerSetsOrder().isEmpty()) { if (_session->data().stickers().archivedSetsOrder().isEmpty()) {
preloadArchivedSets(); preloadArchivedSets();
} }
setNoContentMargin(true); setNoContentMargin(true);
@ -319,16 +559,17 @@ void StickersBox::prepare() {
setInnerWidget(_tab->takeWidget(), getTopSkip()); setInnerWidget(_tab->takeWidget(), getTopSkip());
setDimensions(st::boxWideWidth, st::boxMaxListHeight); setDimensions(st::boxWideWidth, st::boxMaxListHeight);
_session->data().stickersUpdated( _session->data().stickers().updated(
) | rpl::start_with_next( ) | rpl::start_with_next(
[this] { handleStickersUpdated(); }, [this] { handleStickersUpdated(); },
lifetime()); lifetime());
_session->api().updateStickers(); _session->api().updateStickers();
if (_installed.widget()) { if (_installed.widget()) {
connect(_installed.widget(), &Inner::draggingScrollDelta, [=](int delta) { _installed.widget()->draggingScrollDelta(
) | rpl::start_with_next([=](int delta) {
scrollByDraggingDelta(delta); scrollByDraggingDelta(delta);
}); }, _installed.widget()->lifetime());
if (!_megagroupSet) { if (!_megagroupSet) {
boxClosing() | rpl::start_with_next([=] { boxClosing() | rpl::start_with_next([=] {
saveChanges(); saveChanges();
@ -350,11 +591,11 @@ void StickersBox::refreshTabs() {
auto sections = QStringList(); auto sections = QStringList();
sections.push_back(tr::lng_stickers_installed_tab(tr::now).toUpper()); sections.push_back(tr::lng_stickers_installed_tab(tr::now).toUpper());
_tabIndices.push_back(Section::Installed); _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()); sections.push_back(tr::lng_stickers_featured_tab(tr::now).toUpper());
_tabIndices.push_back(Section::Featured); _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()); sections.push_back(tr::lng_stickers_archived_tab(tr::now).toUpper());
_tabIndices.push_back(Section::Archived); _tabIndices.push_back(Section::Archived);
} }
@ -371,13 +612,15 @@ void StickersBox::refreshTabs() {
} }
void StickersBox::loadMoreArchived() { void StickersBox::loadMoreArchived() {
if (_section != Section::Archived || _allArchivedLoaded || _archivedRequestId) { if (_section != Section::Archived
|| _allArchivedLoaded
|| _archivedRequestId) {
return; return;
} }
uint64 lastId = 0; uint64 lastId = 0;
const auto &order = _session->data().archivedStickerSetsOrder(); const auto &order = _session->data().stickers().archivedSetsOrder();
const auto &sets = _session->data().stickerSets(); const auto &sets = _session->data().stickers().sets();
for (auto setIt = order.cend(), e = order.cbegin(); setIt != e;) { for (auto setIt = order.cend(), e = order.cbegin(); setIt != e;) {
--setIt; --setIt;
auto it = sets.find(*setIt); auto it = sets.find(*setIt);
@ -499,7 +742,7 @@ QPixmap StickersBox::grabContentCache() {
} }
void StickersBox::installSet(uint64 setId) { void StickersBox::installSet(uint64 setId) {
const auto &sets = _session->data().stickerSets(); const auto &sets = _session->data().stickers().sets();
const auto it = sets.find(setId); const auto it = sets.find(setId);
if (it == sets.cend()) { if (it == sets.cend()) {
rebuildList(); rebuildList();
@ -523,13 +766,13 @@ void StickersBox::installSet(uint64 setId) {
rpcDone(&StickersBox::installDone), rpcDone(&StickersBox::installDone),
rpcFail(&StickersBox::installFail, setId)); rpcFail(&StickersBox::installFail, setId));
Stickers::InstallLocally(setId); _session->data().stickers().installLocally(setId);
} }
} }
void StickersBox::installDone(const MTPmessages_StickerSetInstallResult &result) { void StickersBox::installDone(const MTPmessages_StickerSetInstallResult &result) {
if (result.type() == mtpc_messages_stickerSetInstallResultArchive) { if (result.type() == mtpc_messages_stickerSetInstallResultArchive) {
Stickers::ApplyArchivedResult( _session->data().stickers().applyArchivedResult(
result.c_messages_stickerSetInstallResultArchive()); result.c_messages_stickerSetInstallResultArchive());
} }
} }
@ -537,14 +780,14 @@ void StickersBox::installDone(const MTPmessages_StickerSetInstallResult &result)
bool StickersBox::installFail(uint64 setId, const RPCError &error) { bool StickersBox::installFail(uint64 setId, const RPCError &error) {
if (MTP::isDefaultHandledError(error)) return false; 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); const auto it = sets.find(setId);
if (it == sets.cend()) { if (it == sets.cend()) {
rebuildList(); rebuildList();
return true; return true;
} }
Stickers::UndoInstallLocally(setId); _session->data().stickers().undoInstallLocally(setId);
return true; return true;
} }
@ -561,8 +804,8 @@ void StickersBox::requestArchivedSets() {
preloadArchivedSets(); preloadArchivedSets();
} }
const auto &sets = _session->data().stickerSets(); const auto &sets = _session->data().stickers().sets();
const auto &order = _session->data().archivedStickerSetsOrder(); const auto &order = _session->data().stickers().archivedSetsOrder();
for (const auto setId : order) { for (const auto setId : order) {
auto it = sets.find(setId); auto it = sets.find(setId);
if (it != sets.cend()) { if (it != sets.cend()) {
@ -596,7 +839,7 @@ void StickersBox::handleStickersUpdated() {
} else { } else {
_tab->widget()->updateRows(); _tab->widget()->updateRows();
} }
if (_session->data().archivedStickerSetsOrder().isEmpty()) { if (_session->data().stickers().archivedSetsOrder().isEmpty()) {
preloadArchivedSets(); preloadArchivedSets();
} else { } else {
refreshTabs(); refreshTabs();
@ -637,7 +880,7 @@ void StickersBox::setInnerFocus() {
StickersBox::~StickersBox() = default; StickersBox::~StickersBox() = default;
StickersBox::Inner::Row::Row( StickersBox::Inner::Row::Row(
not_null<Stickers::Set*> set, not_null<StickersSet*> set,
DocumentData *sticker, DocumentData *sticker,
int32 count, int32 count,
const QString &title, const QString &title,
@ -666,7 +909,7 @@ StickersBox::Inner::Row::Row(
StickersBox::Inner::Row::~Row() = default; StickersBox::Inner::Row::~Row() = default;
bool StickersBox::Inner::Row::isRecentSet() const { bool StickersBox::Inner::Row::isRecentSet() const {
return (set->id == Stickers::CloudRecentSetId); return (set->id == Data::Stickers::CloudRecentSetId);
} }
StickersBox::Inner::Inner( StickersBox::Inner::Inner(
@ -964,15 +1207,15 @@ void StickersBox::Inner::paintRowThumbnail(
void StickersBox::Inner::validateLottieAnimation(not_null<Row*> row) { void StickersBox::Inner::validateLottieAnimation(not_null<Row*> row) {
if (row->lottie if (row->lottie
|| !Stickers::HasLottieThumbnail( || !ChatHelpers::HasLottieThumbnail(
row->thumbnailMedia.get(), row->thumbnailMedia.get(),
row->stickerMedia.get())) { row->stickerMedia.get())) {
return; return;
} }
auto player = Stickers::LottieThumbnail( auto player = ChatHelpers::LottieThumbnail(
row->thumbnailMedia.get(), row->thumbnailMedia.get(),
row->stickerMedia.get(), row->stickerMedia.get(),
Stickers::LottieSize::SetsListThumbnail, ChatHelpers::StickerLottieSize::SetsListThumbnail,
QSize( QSize(
st::contactsPhotoSize, st::contactsPhotoSize,
st::contactsPhotoSize) * cIntRetinaFactor()); st::contactsPhotoSize) * cIntRetinaFactor());
@ -1058,7 +1301,7 @@ void StickersBox::Inner::paintFakeButton(Painter &p, not_null<Row*> row, int ind
void StickersBox::Inner::mousePressEvent(QMouseEvent *e) { void StickersBox::Inner::mousePressEvent(QMouseEvent *e) {
if (_dragging >= 0) mouseReleaseEvent(e); if (_dragging >= 0) mouseReleaseEvent(e);
_mouse = e->globalPos(); _mouse = e->globalPos();
onUpdateSelected(); updateSelected();
setPressed(_selected); setPressed(_selected);
if (_actionSel >= 0) { if (_actionSel >= 0) {
@ -1175,10 +1418,10 @@ void StickersBox::Inner::ensureRipple(const style::RippleAnimation &st, QImage m
void StickersBox::Inner::mouseMoveEvent(QMouseEvent *e) { void StickersBox::Inner::mouseMoveEvent(QMouseEvent *e) {
_mouse = e->globalPos(); _mouse = e->globalPos();
onUpdateSelected(); updateSelected();
} }
void StickersBox::Inner::onUpdateSelected() { void StickersBox::Inner::updateSelected() {
auto local = mapFromGlobal(_mouse); auto local = mapFromGlobal(_mouse);
if (_dragging >= 0) { if (_dragging >= 0) {
auto shift = 0; auto shift = 0;
@ -1214,16 +1457,14 @@ void StickersBox::Inner::onUpdateSelected() {
_shiftingStartTimes[_dragging] = 0; _shiftingStartTimes[_dragging] = 0;
shiftingAnimationCallback(now); shiftingAnimationCallback(now);
auto countDraggingScrollDelta = [this, local] { _draggingScrollDelta.fire_copy([&] {
if (local.y() < _visibleTop) { if (local.y() < _visibleTop) {
return local.y() - _visibleTop; return local.y() - _visibleTop;
} else if (local.y() >= _visibleBottom) { } else if (local.y() >= _visibleBottom) {
return local.y() + 1 - _visibleBottom; return local.y() + 1 - _visibleBottom;
} }
return 0; return 0;
}; }());
emit draggingScrollDelta(countDraggingScrollDelta());
} else { } else {
bool in = rect().marginsRemoved(QMargins(0, _itemsTop, 0, st::membersMarginBottom)).contains(local); bool in = rect().marginsRemoved(QMargins(0, _itemsTop, 0, st::membersMarginBottom)).contains(local);
auto selected = SelectedRow(); auto selected = SelectedRow();
@ -1258,7 +1499,7 @@ void StickersBox::Inner::onUpdateSelected() {
updateCursor(); updateCursor();
} }
setActionSel(actionSel); setActionSel(actionSel);
emit draggingScrollDelta(0); _draggingScrollDelta.fire(0);
} }
} }
@ -1288,7 +1529,7 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
updateCursor(); updateCursor();
_mouse = e->globalPos(); _mouse = e->globalPos();
onUpdateSelected(); updateSelected();
if (_actionDown == _actionSel && _actionSel >= 0) { if (_actionDown == _actionSel && _actionSel >= 0) {
if (_section == Section::Installed) { if (_section == Section::Installed) {
setRowRemoved(_actionDown, !_rows[_actionDown]->removed); setRowRemoved(_actionDown, !_rows[_actionDown]->removed);
@ -1339,11 +1580,15 @@ void StickersBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
void StickersBox::Inner::saveGroupSet() { void StickersBox::Inner::saveGroupSet() {
Expects(_megagroupSet != nullptr); Expects(_megagroupSet != nullptr);
auto oldId = (_megagroupSet->mgInfo->stickerSet.type() == mtpc_inputStickerSetID) ? _megagroupSet->mgInfo->stickerSet.c_inputStickerSetID().vid().v : 0; auto oldId = (_megagroupSet->mgInfo->stickerSet.type() == mtpc_inputStickerSetID)
auto newId = (_megagroupSetInput.type() == mtpc_inputStickerSetID) ? _megagroupSetInput.c_inputStickerSetID().vid().v : 0; ? _megagroupSet->mgInfo->stickerSet.c_inputStickerSetID().vid().v
: 0;
auto newId = (_megagroupSetInput.type() == mtpc_inputStickerSetID)
? _megagroupSetInput.c_inputStickerSetID().vid().v
: 0;
if (newId != oldId) { if (newId != oldId) {
_session->api().setGroupStickerSet(_megagroupSet, _megagroupSetInput); _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->removed = removed;
row->ripple.reset(); row->ripple.reset();
update(0, _itemsTop + index * _rowHeight, width(), _rowHeight); update(0, _itemsTop + index * _rowHeight, width(), _rowHeight);
onUpdateSelected(); updateSelected();
} }
} }
void StickersBox::Inner::leaveEventHook(QEvent *e) { void StickersBox::Inner::leaveEventHook(QEvent *e) {
_mouse = QPoint(-1, -1); _mouse = QPoint(-1, -1);
onUpdateSelected(); updateSelected();
} }
void StickersBox::Inner::leaveToChildEvent(QEvent *e, QWidget *child) { void StickersBox::Inner::leaveToChildEvent(QEvent *e, QWidget *child) {
_mouse = QPoint(-1, -1); _mouse = QPoint(-1, -1);
onUpdateSelected(); updateSelected();
} }
bool StickersBox::Inner::shiftingAnimationCallback(crl::time now) { bool StickersBox::Inner::shiftingAnimationCallback(crl::time now) {
@ -1473,7 +1718,7 @@ void StickersBox::Inner::handleMegagroupSetAddressChange() {
auto text = _megagroupSetField->getLastText().trimmed(); auto text = _megagroupSetField->getLastText().trimmed();
if (text.isEmpty()) { if (text.isEmpty()) {
if (_megagroupSelectedSet) { if (_megagroupSelectedSet) {
const auto &sets = _session->data().stickerSets(); const auto &sets = _session->data().stickers().sets();
const auto it = sets.find(_megagroupSelectedSet->set->id); const auto it = sets.find(_megagroupSelectedSet->set->id);
if (it != sets.cend() && !it->second->shortName.isEmpty()) { if (it != sets.cend() && !it->second->shortName.isEmpty()) {
setMegagroupSelectedSet(MTP_inputStickerSetEmpty()); setMegagroupSelectedSet(MTP_inputStickerSetEmpty());
@ -1484,7 +1729,7 @@ void StickersBox::Inner::handleMegagroupSetAddressChange() {
MTP_inputStickerSetShortName(MTP_string(text)) MTP_inputStickerSetShortName(MTP_string(text))
)).done([=](const MTPmessages_StickerSet &result) { )).done([=](const MTPmessages_StickerSet &result) {
_megagroupSetRequestId = 0; _megagroupSetRequestId = 0;
auto set = Stickers::FeedSetFull(result); auto set = _session->data().stickers().feedSetFull(result);
setMegagroupSelectedSet(MTP_inputStickerSetID( setMegagroupSelectedSet(MTP_inputStickerSetID(
MTP_long(set->id), MTP_long(set->id),
MTP_long(set->access))); MTP_long(set->access)));
@ -1511,7 +1756,7 @@ void StickersBox::Inner::rebuildMegagroupSet() {
} }
auto &inputId = _megagroupSetInput.c_inputStickerSetID(); auto &inputId = _megagroupSetInput.c_inputStickerSetID();
auto setId = inputId.vid().v; auto setId = inputId.vid().v;
const auto &sets = _session->data().stickerSets(); const auto &sets = _session->data().stickers().sets();
auto it = sets.find(setId); auto it = sets.find(setId);
if (it == sets.cend() if (it == sets.cend()
|| (it->second->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) { || (it->second->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
@ -1572,30 +1817,30 @@ void StickersBox::Inner::rebuild() {
auto maxNameWidth = countMaxNameWidth(); auto maxNameWidth = countMaxNameWidth();
clear(); clear();
const auto &order = ([&]() -> const Stickers::Order & { const auto &order = ([&]() -> const StickersSetsOrder & {
if (_section == Section::Installed) { if (_section == Section::Installed) {
auto &result = _session->data().stickerSetsOrder(); auto &result = _session->data().stickers().setsOrder();
if (_megagroupSet && result.empty()) { if (_megagroupSet && result.empty()) {
return _session->data().featuredStickerSetsOrder(); return _session->data().stickers().featuredSetsOrder();
} }
return result; return result;
} else if (_section == Section::Featured) { } 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); _rows.reserve(order.size() + 1);
_shiftingStartTimes.reserve(order.size() + 1); _shiftingStartTimes.reserve(order.size() + 1);
const auto &sets = _session->data().stickerSets(); const auto &sets = _session->data().stickers().sets();
if (_megagroupSet) { if (_megagroupSet) {
auto usingFeatured = _session->data().stickerSetsOrder().empty(); auto usingFeatured = _session->data().stickers().setsOrder().empty();
_megagroupSubTitle->setText(usingFeatured _megagroupSubTitle->setText(usingFeatured
? tr::lng_stickers_group_from_featured(tr::now) ? tr::lng_stickers_group_from_featured(tr::now)
: tr::lng_stickers_group_from_your(tr::now)); : tr::lng_stickers_group_from_your(tr::now));
updateControlsGeometry(); updateControlsGeometry();
} else if (_section == Section::Installed) { } 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()) { if (cloudIt != sets.cend() && !cloudIt->second->stickers.isEmpty()) {
rebuildAppendSet(cloudIt->second.get(), maxNameWidth); rebuildAppendSet(cloudIt->second.get(), maxNameWidth);
} }
@ -1622,7 +1867,7 @@ void StickersBox::Inner::setMegagroupSelectedSet(const MTPInputStickerSet &set)
_megagroupSetInput = set; _megagroupSetInput = set;
rebuild(); rebuild();
scrollToY.notify(0, true); scrollToY.notify(0, true);
onUpdateSelected(); updateSelected();
} }
void StickersBox::Inner::setMinHeight(int newWidth, int minHeight) { void StickersBox::Inner::setMinHeight(int newWidth, int minHeight) {
@ -1639,7 +1884,7 @@ void StickersBox::Inner::updateSize(int newWidth) {
void StickersBox::Inner::updateRows() { void StickersBox::Inner::updateRows() {
int maxNameWidth = countMaxNameWidth(); int maxNameWidth = countMaxNameWidth();
const auto &sets = _session->data().stickerSets(); const auto &sets = _session->data().stickers().sets();
for (const auto &row : _rows) { for (const auto &row : _rows) {
const auto it = sets.find(row->set->id); const auto it = sets.find(row->set->id);
if (it == sets.cend()) { if (it == sets.cend()) {
@ -1677,7 +1922,7 @@ void StickersBox::Inner::updateRows() {
update(); update();
} }
bool StickersBox::Inner::appendSet(not_null<Stickers::Set*> set) { bool StickersBox::Inner::appendSet(not_null<StickersSet*> set) {
for (const auto &row : _rows) { for (const auto &row : _rows) {
if (row->set == set) { if (row->set == set) {
return false; return false;
@ -1707,10 +1952,10 @@ int StickersBox::Inner::countMaxNameWidth() const {
} }
void StickersBox::Inner::rebuildAppendSet( void StickersBox::Inner::rebuildAppendSet(
not_null<Stickers::Set*> set, not_null<StickersSet*> set,
int maxNameWidth) { int maxNameWidth) {
bool installed = true, official = true, unread = false, archived = false, removed = false; 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); fillSetFlags(set, &installed, &official, &unread, &archived);
} }
if (_section == Section::Installed && archived) { if (_section == Section::Installed && archived) {
@ -1742,7 +1987,7 @@ void StickersBox::Inner::rebuildAppendSet(
} }
void StickersBox::Inner::fillSetCover( void StickersBox::Inner::fillSetCover(
not_null<Stickers::Set*> set, not_null<StickersSet*> set,
DocumentData **outSticker, DocumentData **outSticker,
int *outWidth, int *outWidth,
int *outHeight) const { int *outHeight) const {
@ -1780,31 +2025,31 @@ void StickersBox::Inner::fillSetCover(
*outHeight = pixh; *outHeight = pixh;
} }
int StickersBox::Inner::fillSetCount(not_null<Stickers::Set*> set) const { int StickersBox::Inner::fillSetCount(not_null<StickersSet*> set) const {
int result = set->stickers.isEmpty() int result = set->stickers.isEmpty()
? set->count ? set->count
: set->stickers.size(); : set->stickers.size();
auto added = 0; auto added = 0;
if (set->id == Stickers::CloudRecentSetId) { if (set->id == Data::Stickers::CloudRecentSetId) {
const auto &sets = _session->data().stickerSets(); const auto &sets = _session->data().stickers().sets();
auto customIt = sets.find(Stickers::CustomSetId); auto customIt = sets.find(Data::Stickers::CustomSetId);
if (customIt != sets.cend()) { if (customIt != sets.cend()) {
added = customIt->second->stickers.size(); added = customIt->second->stickers.size();
const auto &recent = Stickers::GetRecentPack(); const auto &recent = _session->data().stickers().getRecentPack();
for (const auto &sticker : recent) { for (const auto &sticker : recent) {
if (customIt->second->stickers.indexOf(sticker.first) < 0) { if (customIt->second->stickers.indexOf(sticker.first) < 0) {
++added; ++added;
} }
} }
} else { } else {
added = Stickers::GetRecentPack().size(); added = _session->data().stickers().getRecentPack().size();
} }
} }
return result + added; return result + added;
} }
QString StickersBox::Inner::fillSetTitle( QString StickersBox::Inner::fillSetTitle(
not_null<Stickers::Set*> set, not_null<StickersSet*> set,
int maxNameWidth, int maxNameWidth,
int *outTitleWidth) const { int *outTitleWidth) const {
auto result = set->title; auto result = set->title;
@ -1820,7 +2065,7 @@ QString StickersBox::Inner::fillSetTitle(
} }
void StickersBox::Inner::fillSetFlags( void StickersBox::Inner::fillSetFlags(
not_null<Stickers::Set*> set, not_null<StickersSet*> set,
bool *outInstalled, bool *outInstalled,
bool *outOfficial, bool *outOfficial,
bool *outUnread, bool *outUnread,
@ -1836,10 +2081,10 @@ void StickersBox::Inner::fillSetFlags(
} }
template <typename Check> template <typename Check>
Stickers::Order StickersBox::Inner::collectSets(Check check) const { StickersSetsOrder StickersBox::Inner::collectSets(Check check) const {
Stickers::Order result; StickersSetsOrder result;
result.reserve(_rows.size()); result.reserve(_rows.size());
for_const (auto &row, _rows) { for (const auto &row : _rows) {
if (check(row.get())) { if (check(row.get())) {
result.push_back(row->set->id); result.push_back(row->set->id);
} }
@ -1847,19 +2092,19 @@ Stickers::Order StickersBox::Inner::collectSets(Check check) const {
return result; return result;
} }
Stickers::Order StickersBox::Inner::getOrder() const { StickersSetsOrder StickersBox::Inner::getOrder() const {
return collectSets([](Row *row) { return collectSets([](Row *row) {
return !row->archived && !row->removed && !row->isRecentSet(); return !row->archived && !row->removed && !row->isRecentSet();
}); });
} }
Stickers::Order StickersBox::Inner::getFullOrder() const { StickersSetsOrder StickersBox::Inner::getFullOrder() const {
return collectSets([](Row *row) { return collectSets([](Row *row) {
return !row->isRecentSet(); return !row->isRecentSet();
}); });
} }
Stickers::Order StickersBox::Inner::getRemovedSets() const { StickersSetsOrder StickersBox::Inner::getRemovedSets() const {
return collectSets([](Row *row) { return collectSets([](Row *row) {
return row->removed; return row->removed;
}); });
@ -1875,7 +2120,7 @@ int StickersBox::Inner::getRowIndex(uint64 setId) const {
return -1; return -1;
} }
void StickersBox::Inner::setFullOrder(const Stickers::Order &order) { void StickersBox::Inner::setFullOrder(const StickersSetsOrder &order) {
for_const (auto setId, order) { for_const (auto setId, order) {
auto index = getRowIndex(setId); auto index = getRowIndex(setId);
if (index >= 0) { 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) { for (auto i = 0, count = int(_rows.size()); i != count; ++i) {
setRowRemoved(i, removed.contains(_rows[i]->set->id)); setRowRemoved(i, removed.contains(_rows[i]->set->id));
} }

View file

@ -10,7 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/abstract_box.h" #include "boxes/abstract_box.h"
#include "base/timer.h" #include "base/timer.h"
#include "mtproto/sender.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/effects/animations.h"
#include "ui/special_fields.h" #include "ui/special_fields.h"
@ -89,12 +89,8 @@ private:
object_ptr<Inner> takeWidget(); object_ptr<Inner> takeWidget();
void returnWidget(object_ptr<Inner> widget); void returnWidget(object_ptr<Inner> widget);
Inner *widget() { [[nodiscard]] Inner *widget();
return _weak; [[nodiscard]] int index() const;
}
int index() const {
return _index;
}
void saveScrollTop(); void saveScrollTop();
int getScrollTop() const { int getScrollTop() const {
@ -157,228 +153,7 @@ private:
bool _allArchivedLoaded = false; bool _allArchivedLoaded = false;
bool _someArchivedLoaded = false; bool _someArchivedLoaded = false;
Stickers::Order _localOrder; Data::StickersSetsOrder _localOrder;
Stickers::Order _localRemoved; Data::StickersSetsOrder _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<Main::Session*> session,
Section section);
Inner(QWidget *parent, not_null<ChannelData*> megagroup);
base::Observable<int> scrollToY;
void setInnerFocus();
void saveGroupSet();
void rebuild();
void updateSize(int newWidth = 0);
void updateRows(); // refresh only pack cover stickers
bool appendSet(not_null<Stickers::Set*> 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<void(uint64 setId)> callback) {
_installSetCallback = std::move(callback);
}
void setLoadMoreCallback(Fn<void()> 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<Stickers::Set*> 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<Stickers::Set*> set;
DocumentData *sticker = nullptr;
std::shared_ptr<Data::DocumentMedia> stickerMedia;
std::shared_ptr<Stickers::SetThumbnailView> 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<Ui::RippleAnimation> ripple;
std::unique_ptr<Lottie::SinglePlayer> 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<MegagroupSet, int>;
class AddressField : public Ui::UsernameInput {
public:
using UsernameInput::UsernameInput;
protected:
void correctValue(
const QString &was,
int wasCursor,
QString &now,
int &nowCursor) override;
};
template <typename Check>
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*> row, int index);
void paintRowThumbnail(Painter &p, not_null<Row*> row, int left);
void paintFakeButton(Painter &p, not_null<Row*> row, int index);
void clear();
void updateCursor();
void setActionSel(int32 actionSel);
float64 aboveShadowOpacity() const;
void validateLottieAnimation(not_null<Row*> row);
void updateRowThumbnail(not_null<Row*> row);
void readVisibleSets();
void updateControlsGeometry();
void rebuildAppendSet(not_null<Stickers::Set*> set, int maxNameWidth);
void fillSetCover(not_null<Stickers::Set*> set, DocumentData **outSticker, int *outWidth, int *outHeight) const;
int fillSetCount(not_null<Stickers::Set*> set) const;
QString fillSetTitle(not_null<Stickers::Set*> set, int maxNameWidth, int *outTitleWidth) const;
void fillSetFlags(not_null<Stickers::Set*> 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<Main::Session*> _session;
MTP::Sender _api;
Section _section;
int32 _rowHeight;
std::vector<std::unique_ptr<Row>> _rows;
std::vector<crl::time> _shiftingStartTimes;
crl::time _aboveShadowFadeStart = 0;
anim::value _aboveShadowFadeOpacity;
Ui::Animations::Basic _shiftingAnimation;
Fn<void(uint64 setId)> _installSetCallback;
Fn<void()> _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<Row> _megagroupSelectedSet;
object_ptr<AddressField> _megagroupSetField = { nullptr };
object_ptr<Ui::PlainShadow> _megagroupSelectedShadow = { nullptr };
object_ptr<Ui::CrossButton> _megagroupSelectedRemove = { nullptr };
object_ptr<Ui::BoxContentDivider> _megagroupDivider = { nullptr };
object_ptr<Ui::FlatLabel> _megagroupSubTitle = { nullptr };
base::Timer _megagroupSetAddressChangedTimer;
mtpRequestId _megagroupSetRequestId = 0;
}; };

View file

@ -14,6 +14,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_peer_values.h" #include "data/data_peer_values.h"
#include "data/data_file_origin.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 "mainwindow.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "storage/localstorage.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/widgets/scroll_area.h"
#include "ui/image/image.h" #include "ui/image/image.h"
#include "ui/ui_utility.h" #include "ui/ui_utility.h"
#include "chat_helpers/stickers.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "facades.h" #include "facades.h"
@ -172,8 +174,7 @@ inline int indexOfInFirstN(const T &v, const U &elem, int last) {
} }
internal::StickerRows FieldAutocomplete::getStickerSuggestions() { internal::StickerRows FieldAutocomplete::getStickerSuggestions() {
const auto list = Stickers::GetListByEmoji( const auto list = _controller->session().data().stickers().getListByEmoji(
&_controller->session(),
_emoji, _emoji,
_stickersSeed _stickersSeed
); );
@ -1019,9 +1020,9 @@ auto FieldAutocompleteInner::getLottieRenderer()
void FieldAutocompleteInner::setupLottie(StickerSuggestion &suggestion) { void FieldAutocompleteInner::setupLottie(StickerSuggestion &suggestion) {
const auto document = suggestion.document; const auto document = suggestion.document;
suggestion.animated = Stickers::LottiePlayerFromDocument( suggestion.animated = ChatHelpers::LottiePlayerFromDocument(
suggestion.documentMedia.get(), suggestion.documentMedia.get(),
Stickers::LottieSize::InlineResults, ChatHelpers::StickerLottieSize::InlineResults,
stickerBoundingBox() * cIntRetinaFactor(), stickerBoundingBox() * cIntRetinaFactor(),
Lottie::Quality::Default, Lottie::Quality::Default,
getLottieRenderer()); getLottieRenderer());

View file

@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/rp_widget.h" #include "ui/rp_widget.h"
#include "base/timer.h" #include "base/timer.h"
#include "base/object_ptr.h" #include "base/object_ptr.h"
#include "chat_helpers/stickers.h" #include "data/stickers/data_stickers.h"
namespace Ui { namespace Ui {
class ScrollArea; class ScrollArea;

View file

@ -15,13 +15,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "data/data_photo_media.h" #include "data/data_photo_media.h"
#include "data/data_document_media.h" #include "data/data_document_media.h"
#include "data/stickers/data_stickers.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/input_fields.h" #include "ui/widgets/input_fields.h"
#include "ui/effects/ripple_animation.h" #include "ui/effects/ripple_animation.h"
#include "ui/image/image.h" #include "ui/image/image.h"
#include "boxes/stickers_box.h" #include "boxes/stickers_box.h"
#include "inline_bots/inline_bot_result.h" #include "inline_bots/inline_bot_result.h"
#include "chat_helpers/stickers.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mainwindow.h" #include "mainwindow.h"
@ -149,8 +149,8 @@ GifsListWidget::GifsListWidget(
this, this,
[=] { sendInlineRequest(); }); [=] { sendInlineRequest(); });
controller->session().data().savedGifsUpdated( controller->session().data().stickers().savedGifsUpdated(
) | rpl::start_with_next([this] { ) | rpl::start_with_next([=] {
refreshSavedGifs(); refreshSavedGifs();
}, lifetime()); }, lifetime());
@ -511,13 +511,13 @@ void GifsListWidget::refreshSavedGifs() {
if (_section == Section::Gifs) { if (_section == Section::Gifs) {
clearInlineRows(false); clearInlineRows(false);
auto &saved = controller()->session().data().savedGifs(); const auto &saved = controller()->session().data().stickers().savedGifs();
if (!saved.isEmpty()) { if (!saved.isEmpty()) {
_rows.reserve(saved.size()); _rows.reserve(saved.size());
auto row = Row(); auto row = Row();
row.items.reserve(kInlineItemsMaxPerRow); row.items.reserve(kInlineItemsMaxPerRow);
auto sumWidth = 0; auto sumWidth = 0;
for_const (auto &gif, saved) { for (const auto &gif : saved) {
inlineRowsAddItem(gif, 0, row, sumWidth); inlineRowsAddItem(gif, 0, row, sumWidth);
} }
inlineRowFinalize(row, sumWidth, true); inlineRowFinalize(row, sumWidth, true);
@ -540,8 +540,8 @@ void GifsListWidget::clearInlineRows(bool resultsDeleted) {
_selected = _pressed = -1; _selected = _pressed = -1;
} else { } else {
clearSelection(); clearSelection();
for_const (auto &row, _rows) { for (const auto &row : std::as_const(_rows)) {
for_const (auto &item, row.items) { for (const auto &item : std::as_const(row.items)) {
item->setPosition(-1); item->setPosition(-1);
} }
} }

View file

@ -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<const DocumentData*> document);
void SetFaved(not_null<DocumentData*> document, bool faved);
void SetsReceived(const QVector<MTPStickerSet> &data, int32 hash);
void SpecialSetReceived(
uint64 setId,
const QString &setTitle,
const QVector<MTPDocument> &items,
int32 hash,
const QVector<MTPStickerPack> &packs = QVector<MTPStickerPack>(),
const QVector<MTPint> &usageDates = QVector<MTPint>());
void FeaturedSetsReceived(
const QVector<MTPStickerSetCovered> &list,
const QVector<MTPlong> &unread,
int32 hash);
void GifsReceived(const QVector<MTPDocument> &items, int32 hash);
std::vector<not_null<DocumentData*>> GetListByEmoji(
not_null<Main::Session*> session,
not_null<EmojiPtr> emoji,
uint64 seed);
std::optional<std::vector<not_null<EmojiPtr>>> GetEmojiListFromSet(
not_null<DocumentData*> 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<Lottie::SinglePlayer> LottiePlayerFromDocument(
not_null<Data::DocumentMedia*> media,
LottieSize sizeTag,
QSize box,
Lottie::Quality quality = Lottie::Quality(),
std::shared_ptr<Lottie::FrameRenderer> renderer = nullptr);
[[nodiscard]] std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument(
not_null<Data::DocumentMedia*> media,
const Lottie::ColorReplacements *replacements,
LottieSize sizeTag,
QSize box,
Lottie::Quality quality = Lottie::Quality(),
std::shared_ptr<Lottie::FrameRenderer> renderer = nullptr);
[[nodiscard]] not_null<Lottie::Animation*> LottieAnimationFromDocument(
not_null<Lottie::MultiPlayer*> player,
not_null<Data::DocumentMedia*> media,
LottieSize sizeTag,
QSize box);
[[nodiscard]] bool HasLottieThumbnail(
SetThumbnailView *thumb,
Data::DocumentMedia *media);
[[nodiscard]] std::unique_ptr<Lottie::SinglePlayer> LottieThumbnail(
SetThumbnailView *thumb,
Data::DocumentMedia *media,
LottieSize sizeTag,
QSize box,
std::shared_ptr<Lottie::FrameRenderer> renderer = nullptr);
} // namespace Stickers

View file

@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "data/data_cloud_file.h" #include "data/data_cloud_file.h"
#include "chat_helpers/stickers_lottie.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/effects/animations.h" #include "ui/effects/animations.h"
#include "ui/effects/ripple_animation.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 "lottie/lottie_animation.h"
#include "boxes/stickers_box.h" #include "boxes/stickers_box.h"
#include "inline_bots/inline_bot_result.h" #include "inline_bots/inline_bot_result.h"
#include "chat_helpers/stickers.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mainwindow.h" #include "mainwindow.h"
@ -49,6 +49,10 @@ constexpr auto kRecentDisplayLimit = 20;
constexpr auto kPreloadOfficialPages = 4; constexpr auto kPreloadOfficialPages = 4;
constexpr auto kOfficialLoadLimit = 40; constexpr auto kOfficialLoadLimit = 40;
using Data::StickersSet;
using Data::StickersPack;
using Data::StickersSetThumbnailView;
bool SetInMyList(MTPDstickerSet::Flags flags) { bool SetInMyList(MTPDstickerSet::Flags flags) {
return (flags & MTPDstickerSet::Flag::f_installed_date) return (flags & MTPDstickerSet::Flag::f_installed_date)
&& !(flags & MTPDstickerSet::Flag::f_archived); && !(flags & MTPDstickerSet::Flag::f_archived);
@ -60,7 +64,7 @@ struct StickerIcon {
StickerIcon(uint64 setId) : setId(setId) { StickerIcon(uint64 setId) : setId(setId) {
} }
StickerIcon( StickerIcon(
not_null<Stickers::Set*> set, not_null<StickersSet*> set,
DocumentData *sticker, DocumentData *sticker,
int pixw, int pixw,
int pixh) int pixh)
@ -86,12 +90,12 @@ struct StickerIcon {
} }
uint64 setId = 0; uint64 setId = 0;
Stickers::Set *set = nullptr; StickersSet *set = nullptr;
mutable std::unique_ptr<Lottie::SinglePlayer> lottie; mutable std::unique_ptr<Lottie::SinglePlayer> lottie;
mutable QPixmap savedFrame; mutable QPixmap savedFrame;
DocumentData *sticker = nullptr; DocumentData *sticker = nullptr;
ChannelData *megagroup = nullptr; ChannelData *megagroup = nullptr;
mutable std::shared_ptr<Stickers::SetThumbnailView> thumbnailMedia; mutable std::shared_ptr<StickersSetThumbnailView> thumbnailMedia;
mutable std::shared_ptr<Data::DocumentMedia> stickerMedia; mutable std::shared_ptr<Data::DocumentMedia> stickerMedia;
mutable std::shared_ptr<Data::CloudImageView> megagroupUserpic; mutable std::shared_ptr<Data::CloudImageView> megagroupUserpic;
int pixw = 0; int pixw = 0;
@ -204,7 +208,7 @@ auto StickersListWidget::PrepareStickers(
StickersListWidget::Set::Set( StickersListWidget::Set::Set(
uint64 id, uint64 id,
Stickers::Set *set, StickersSet *set,
MTPDstickerSet::Flags flags, MTPDstickerSet::Flags flags,
const QString &title, const QString &title,
const QString &shortName, const QString &shortName,
@ -368,11 +372,11 @@ void StickersListWidget::Footer::validateSelectedIcon(
auto newSelected = -1; auto newSelected = -1;
for (auto i = 0, l = int(_icons.size()); i != l; ++i) { for (auto i = 0, l = int(_icons.size()); i != l; ++i) {
if (_icons[i].setId == setId if (_icons[i].setId == setId
|| (_icons[i].setId == Stickers::FavedSetId || (_icons[i].setId == Data::Stickers::FavedSetId
&& setId == Stickers::RecentSetId)) { && setId == Data::Stickers::RecentSetId)) {
newSelected = i; newSelected = i;
break; break;
} else if (_icons[i].setId == Stickers::FavedSetId) { } else if (_icons[i].setId == Data::Stickers::FavedSetId) {
favedIconIndex = i; favedIconIndex = i;
} }
} }
@ -524,7 +528,7 @@ void StickersListWidget::Footer::mousePressEvent(QMouseEvent *e) {
if (_iconOver == SpecialOver::Settings) { if (_iconOver == SpecialOver::Settings) {
Ui::show(Box<StickersBox>( Ui::show(Box<StickersBox>(
&_pan->controller()->session(), &_pan->session(),
(hasOnlyFeaturedSets() (hasOnlyFeaturedSets()
? StickersBox::Section::Featured ? StickersBox::Section::Featured
: StickersBox::Section::Installed))); : StickersBox::Section::Installed)));
@ -718,7 +722,8 @@ void StickersListWidget::Footer::refreshIconsGeometry(
} }
bool StickersListWidget::Footer::hasOnlyFeaturedSets() const { 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 { void StickersListWidget::Footer::paintStickerSettingsIcon(Painter &p) const {
@ -736,15 +741,15 @@ void StickersListWidget::Footer::validateIconLottieAnimation(
icon.ensureMediaCreated(); icon.ensureMediaCreated();
if (icon.lottie if (icon.lottie
|| !icon.sticker || !icon.sticker
|| !Stickers::HasLottieThumbnail( || !HasLottieThumbnail(
icon.thumbnailMedia.get(), icon.thumbnailMedia.get(),
icon.stickerMedia.get())) { icon.stickerMedia.get())) {
return; return;
} }
auto player = Stickers::LottieThumbnail( auto player = LottieThumbnail(
icon.thumbnailMedia.get(), icon.thumbnailMedia.get(),
icon.stickerMedia.get(), icon.stickerMedia.get(),
Stickers::LottieSize::StickersFooter, StickerLottieSize::StickersFooter,
QSize( QSize(
st::stickerIconWidth - 2 * st::stickerIconPadding, st::stickerIconWidth - 2 * st::stickerIconPadding,
st::emojiFooterHeight - 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); icon.megagroup->paintUserpicLeft(p, icon.megagroupUserpic, x + (st::stickerIconWidth - st::stickerGroupCategorySize) / 2, _iconsTop + (st::emojiFooterHeight - st::stickerGroupCategorySize) / 2, width(), st::stickerGroupCategorySize);
} else { } else {
const auto paintedIcon = [&] { const auto paintedIcon = [&] {
if (icon.setId == Stickers::FeaturedSetId) { if (icon.setId == Data::Stickers::FeaturedSetId) {
const auto session = &_pan->session(); const auto session = &_pan->session();
return session->data().featuredStickerSetsUnreadCount() return session->data().stickers().featuredSetsUnreadCount()
? &st::stickersTrendingUnread ? &st::stickersTrendingUnread
: &st::stickersTrending; : &st::stickersTrending;
//} else if (setId == Stickers::FavedSetId) { //} else if (setId == Stickers::FavedSetId) {
@ -979,9 +984,9 @@ void StickersListWidget::preloadMoreOfficial() {
}); });
}); });
const auto covers = data.match([](const MTPDstickerSetCovered &) { const auto covers = data.match([](const MTPDstickerSetCovered &) {
return Stickers::Pack(); return StickersPack();
}, [&](const MTPDstickerSetMultiCovered &data) { }, [&](const MTPDstickerSetMultiCovered &data) {
auto result = Stickers::Pack(); auto result = StickersPack();
for (const auto &cover : data.vcovers().v) { for (const auto &cover : data.vcovers().v) {
const auto document = session().data().processDocument(cover); const auto document = session().data().processDocument(cover);
if (document->sticker()) { if (document->sticker()) {
@ -990,7 +995,7 @@ void StickersListWidget::preloadMoreOfficial() {
} }
return result; return result;
}); });
if (const auto set = Stickers::FeedSet(*setData)) { if (const auto set = session().data().stickers().feedSet(*setData)) {
if (!covers.empty()) { if (!covers.empty()) {
set->covers = covers; set->covers = covers;
} }
@ -1065,7 +1070,7 @@ bool StickersListWidget::enumerateSections(Callback callback) const {
if (set.externalLayout) { if (set.externalLayout) {
info.rowsCount = 1; info.rowsCount = 1;
info.rowsBottom = info.top + featuredRowHeight(); 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.rowsCount = 0;
info.rowsBottom = info.rowsTop + _megagroupSetButtonRect.y() + _megagroupSetButtonRect.height() + st::stickerGroupCategoryAddMargin.bottom(); info.rowsBottom = info.rowsTop + _megagroupSetButtonRect.y() + _megagroupSetButtonRect.height() + st::stickerGroupCategoryAddMargin.bottom();
} else { } else {
@ -1249,7 +1254,7 @@ void StickersListWidget::refreshSearchRows(
if (!cloudSets && _searchNextQuery.isEmpty()) { if (!cloudSets && _searchNextQuery.isEmpty()) {
showStickerSet(!_mySets.empty() showStickerSet(!_mySets.empty()
? _mySets[0].id ? _mySets[0].id
: Stickers::FeaturedSetId); : Data::Stickers::FeaturedSetId);
return; return;
} }
@ -1292,7 +1297,7 @@ void StickersListWidget::fillLocalSearchRows(const QString &query) {
return true; return true;
}; };
const auto &sets = session().data().stickerSets(); const auto &sets = session().data().stickers().sets();
for (const auto &[setId, titleWords] : _searchIndex) { for (const auto &[setId, titleWords] : _searchIndex) {
if (allSearchWordsInTitle(titleWords)) { if (allSearchWordsInTitle(titleWords)) {
if (const auto it = sets.find(setId); it != sets.end()) { if (const auto it = sets.find(setId); it != sets.end()) {
@ -1304,7 +1309,7 @@ void StickersListWidget::fillLocalSearchRows(const QString &query) {
void StickersListWidget::fillCloudSearchRows( void StickersListWidget::fillCloudSearchRows(
const std::vector<uint64> &cloudSets) { const std::vector<uint64> &cloudSets) {
const auto &sets = session().data().stickerSets(); const auto &sets = session().data().stickers().sets();
for (const auto setId : cloudSets) { for (const auto setId : cloudSets) {
if (const auto it = sets.find(setId); it != sets.end()) { if (const auto it = sets.find(setId); it != sets.end()) {
addSearchRow(it->second.get()); addSearchRow(it->second.get());
@ -1312,7 +1317,7 @@ void StickersListWidget::fillCloudSearchRows(
} }
} }
void StickersListWidget::addSearchRow(not_null<Stickers::Set*> set) { void StickersListWidget::addSearchRow(not_null<StickersSet*> set) {
_searchSets.emplace_back( _searchSets.emplace_back(
set->id, set->id,
set, set,
@ -1425,7 +1430,7 @@ void StickersListWidget::searchResultsDone(
auto &d = result.c_messages_foundStickerSets(); auto &d = result.c_messages_foundStickerSets();
for (const auto &stickerSet : d.vsets().v) { for (const auto &stickerSet : d.vsets().v) {
const MTPDstickerSet *setData = nullptr; const MTPDstickerSet *setData = nullptr;
Stickers::Pack covers; StickersPack covers;
switch (stickerSet.type()) { switch (stickerSet.type()) {
case mtpc_stickerSetCovered: { case mtpc_stickerSetCovered: {
auto &d = stickerSet.c_stickerSetCovered(); auto &d = stickerSet.c_stickerSetCovered();
@ -1448,7 +1453,7 @@ void StickersListWidget::searchResultsDone(
} }
if (!setData) continue; if (!setData) continue;
if (const auto set = Stickers::FeedSet(*setData)) { if (const auto set = session().data().stickers().feedSet(*setData)) {
if (!covers.empty()) { if (!covers.empty()) {
set->covers = covers; set->covers = covers;
} }
@ -1610,7 +1615,7 @@ void StickersListWidget::paintStickers(Painter &p, QRect clip) {
} }
if (clip.top() + clip.height() <= info.rowsTop) { if (clip.top() + clip.height() <= info.rowsTop) {
return true; 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<OverGroupAdd>(&_selected) != nullptr); auto buttonSelected = (base::get_if<OverGroupAdd>(&_selected) != nullptr);
paintMegagroupEmptySet(p, info.rowsTop, buttonSelected); paintMegagroupEmptySet(p, info.rowsTop, buttonSelected);
return true; 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. // Document should be loaded already for the animation to be set up.
Assert(sticker.documentMedia != nullptr); Assert(sticker.documentMedia != nullptr);
sticker.animated = Stickers::LottieAnimationFromDocument( sticker.animated = LottieAnimationFromDocument(
set.lottiePlayer.get(), set.lottiePlayer.get(),
sticker.documentMedia.get(), sticker.documentMedia.get(),
Stickers::LottieSize::StickersPanel, StickerLottieSize::StickersPanel,
boundingBoxSize() * cIntRetinaFactor()); boundingBoxSize() * cIntRetinaFactor());
} }
@ -1926,7 +1931,7 @@ bool StickersListWidget::hasRemoveButton(int index) const {
if (!(flags & MTPDstickerSet_ClientFlag::f_special)) { if (!(flags & MTPDstickerSet_ClientFlag::f_special)) {
return true; return true;
} }
if (set.id == Stickers::MegagroupSetId) { if (set.id == Data::Stickers::MegagroupSetId) {
Assert(_megagroupSet != nullptr); Assert(_megagroupSet != nullptr);
if (index + 1 != shownSets().size()) { if (index + 1 != shownSets().size()) {
return true; return true;
@ -1994,7 +1999,7 @@ QRect StickersListWidget::megagroupSetButtonRectFinal() const {
auto result = QRect(); auto result = QRect();
if (_section == Section::Stickers) { if (_section == Section::Stickers) {
enumerateSections([this, &result](const SectionInfo &info) { 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); result = _megagroupSetButtonRect.translated(0, info.rowsTop);
return false; return false;
} }
@ -2057,9 +2062,9 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) {
auto &set = sets[sticker->section]; auto &set = sets[sticker->section];
Assert(sticker->index >= 0 && sticker->index < set.stickers.size()); Assert(sticker->index >= 0 && sticker->index < set.stickers.size());
if (stickerHasDeleteButton(set, sticker->index) && sticker->overDelete) { if (stickerHasDeleteButton(set, sticker->index) && sticker->overDelete) {
if (set.id == Stickers::RecentSetId) { if (set.id == Data::Stickers::RecentSetId) {
removeRecentSticker(sticker->section, sticker->index); removeRecentSticker(sticker->section, sticker->index);
} else if (set.id == Stickers::FavedSetId) { } else if (set.id == Data::Stickers::FavedSetId) {
removeFavedSticker(sticker->section, sticker->index); removeFavedSticker(sticker->section, sticker->index);
} else { } else {
Unexpected("Single sticker delete click."); Unexpected("Single sticker delete click.");
@ -2085,7 +2090,7 @@ void StickersListWidget::mouseReleaseEvent(QMouseEvent *e) {
Assert(button->section >= 0 && button->section < sets.size()); Assert(button->section >= 0 && button->section < sets.size());
if (sets[button->section].externalLayout) { if (sets[button->section].externalLayout) {
installSet(sets[button->section].id); 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() auto removeLocally = sets[button->section].stickers.empty()
|| !_megagroupSet->canEditStickers(); || !_megagroupSet->canEditStickers();
removeMegagroupSet(removeLocally); removeMegagroupSet(removeLocally);
@ -2110,7 +2115,7 @@ void StickersListWidget::validateSelectedIcon(
void StickersListWidget::removeRecentSticker(int section, int index) { void StickersListWidget::removeRecentSticker(int section, int index) {
if ((_section != Section::Stickers) if ((_section != Section::Stickers)
|| (section >= int(_mySets.size())) || (section >= int(_mySets.size()))
|| (_mySets[section].id != Stickers::RecentSetId)) { || (_mySets[section].id != Data::Stickers::RecentSetId)) {
return; return;
} }
@ -2118,7 +2123,7 @@ void StickersListWidget::removeRecentSticker(int section, int index) {
bool refresh = false; bool refresh = false;
const auto &sticker = _mySets[section].stickers[index]; const auto &sticker = _mySets[section].stickers[index];
const auto document = sticker.document; 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) { for (int32 i = 0, l = recent.size(); i < l; ++i) {
if (recent.at(i).first == document) { if (recent.at(i).first == document) {
recent.removeAt(i); recent.removeAt(i);
@ -2127,8 +2132,8 @@ void StickersListWidget::removeRecentSticker(int section, int index) {
break; break;
} }
} }
auto &sets = session().data().stickerSetsRef(); auto &sets = session().data().stickers().setsRef();
auto it = sets.find(Stickers::CustomSetId); auto it = sets.find(Data::Stickers::CustomSetId);
if (it != sets.cend()) { if (it != sets.cend()) {
const auto set = it->second.get(); const auto set = it->second.get();
for (int i = 0, l = set->stickers.size(); i < l; ++i) { 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) { void StickersListWidget::removeFavedSticker(int section, int index) {
if ((_section != Section::Stickers) if ((_section != Section::Stickers)
|| (section >= int(_mySets.size())) || (section >= int(_mySets.size()))
|| (_mySets[section].id != Stickers::FavedSetId)) { || (_mySets[section].id != Data::Stickers::FavedSetId)) {
return; return;
} }
clearSelection(); clearSelection();
const auto &sticker = _mySets[section].stickers[index]; const auto &sticker = _mySets[section].stickers[index];
const auto document = sticker.document; const auto document = sticker.document;
Stickers::SetFaved(document, false); session().data().stickers().setFaved(document, false);
session().api().toggleFavedSticker( session().api().toggleFavedSticker(
document, document,
Data::FileOriginStickerSet(Stickers::FavedSetId, 0), Data::FileOriginStickerSet(Data::Stickers::FavedSetId, 0),
false); false);
} }
@ -2271,12 +2276,12 @@ void StickersListWidget::refreshStickers() {
void StickersListWidget::refreshMySets() { void StickersListWidget::refreshMySets() {
auto wasSets = base::take(_mySets); auto wasSets = base::take(_mySets);
_favedStickersMap.clear(); _favedStickersMap.clear();
_mySets.reserve(session().data().stickerSetsOrder().size() + 3); _mySets.reserve(session().data().stickers().setsOrder().size() + 3);
refreshFavedStickers(); refreshFavedStickers();
refreshRecentStickers(false); refreshRecentStickers(false);
refreshMegagroupStickers(GroupStickersPlace::Visible); refreshMegagroupStickers(GroupStickersPlace::Visible);
for (const auto setId : session().data().stickerSetsOrder()) { for (const auto setId : session().data().stickers().setsOrder()) {
const auto externalLayout = false; const auto externalLayout = false;
appendSet(_mySets, setId, externalLayout, AppendSkip::Archived); appendSet(_mySets, setId, externalLayout, AppendSkip::Archived);
} }
@ -2289,16 +2294,16 @@ void StickersListWidget::refreshFeaturedSets() {
auto wasFeaturedSetsCount = base::take(_featuredSetsCount); auto wasFeaturedSetsCount = base::take(_featuredSetsCount);
auto wereOfficial = base::take(_officialSets); auto wereOfficial = base::take(_officialSets);
_officialSets.reserve( _officialSets.reserve(
session().data().featuredStickerSetsOrder().size() session().data().stickers().featuredSetsOrder().size()
+ wereOfficial.size() + wereOfficial.size()
- wasFeaturedSetsCount); - wasFeaturedSetsCount);
for (const auto setId : session().data().featuredStickerSetsOrder()) { for (const auto setId : session().data().stickers().featuredSetsOrder()) {
const auto externalLayout = true; const auto externalLayout = true;
appendSet(_officialSets, setId, externalLayout, AppendSkip::Installed); appendSet(_officialSets, setId, externalLayout, AppendSkip::Installed);
} }
_featuredSetsCount = _officialSets.size(); _featuredSetsCount = _officialSets.size();
if (wereOfficial.size() > wasFeaturedSetsCount) { 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 from = begin(wereOfficial) + wasFeaturedSetsCount;
const auto till = end(wereOfficial); const auto till = end(wereOfficial);
for (auto i = from; i != till; ++i) { for (auto i = from; i != till; ++i) {
@ -2319,7 +2324,7 @@ void StickersListWidget::refreshFeaturedSets() {
void StickersListWidget::refreshSearchSets() { void StickersListWidget::refreshSearchSets() {
refreshSearchIndex(); refreshSearchIndex();
const auto &sets = session().data().stickerSets(); const auto &sets = session().data().stickers().sets();
for (auto &entry : _searchSets) { for (auto &entry : _searchSets) {
if (const auto it = sets.find(entry.id); it != sets.end()) { if (const auto it = sets.find(entry.id); it != sets.end()) {
const auto set = it->second.get(); const auto set = it->second.get();
@ -2356,7 +2361,7 @@ void StickersListWidget::refreshSettingsVisibility() {
void StickersListWidget::refreshFooterIcons() { void StickersListWidget::refreshFooterIcons() {
_footer->refreshIcons(ValidateIconAnimations::None); _footer->refreshIcons(ValidateIconAnimations::None);
if (_footer->hasOnlyFeaturedSets() && _section != Section::Featured) { 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 { uint64 StickersListWidget::currentSet(int yOffset) const {
if (_section == Section::Featured) { if (_section == Section::Featured) {
return Stickers::FeaturedSetId; return Data::Stickers::FeaturedSetId;
} }
const auto &sets = shownSets(); const auto &sets = shownSets();
return sets.empty() return sets.empty()
? Stickers::RecentSetId ? Data::Stickers::RecentSetId
: sets[sectionInfoByOffset(yOffset).section].id; : sets[sectionInfoByOffset(yOffset).section].id;
} }
@ -2381,7 +2386,7 @@ bool StickersListWidget::appendSet(
uint64 setId, uint64 setId,
bool externalLayout, bool externalLayout,
AppendSkip skip) { AppendSkip skip) {
const auto &sets = session().data().stickerSets(); const auto &sets = session().data().stickers().sets();
auto it = sets.find(setId); auto it = sets.find(setId);
if (it == sets.cend() if (it == sets.cend()
|| (!externalLayout && it->second->stickers.isEmpty())) { || (!externalLayout && it->second->stickers.isEmpty())) {
@ -2418,7 +2423,7 @@ void StickersListWidget::refreshRecent() {
refreshRecentStickers(); refreshRecentStickers();
} }
if (_footer && _footer->hasOnlyFeaturedSets() && _section != Section::Featured) { if (_footer && _footer->hasOnlyFeaturedSets() && _section != Section::Featured) {
showStickerSet(Stickers::FeaturedSetId); showStickerSet(Data::Stickers::FeaturedSetId);
} }
} }
@ -2426,10 +2431,10 @@ auto StickersListWidget::collectRecentStickers() -> std::vector<Sticker> {
_custom.clear(); _custom.clear();
auto result = std::vector<Sticker>(); auto result = std::vector<Sticker>();
const auto &sets = session().data().stickerSets(); const auto &sets = session().data().stickers().sets();
const auto &recent = Stickers::GetRecentPack(); const auto &recent = session().data().stickers().getRecentPack();
const auto customIt = sets.find(Stickers::CustomSetId); const auto customIt = sets.find(Data::Stickers::CustomSetId);
const auto cloudIt = sets.find(Stickers::CloudRecentSetId); const auto cloudIt = sets.find(Data::Stickers::CloudRecentSetId);
const auto customCount = (customIt != sets.cend()) const auto customCount = (customIt != sets.cend())
? customIt->second->stickers.size() ? customIt->second->stickers.size()
: 0; : 0;
@ -2479,13 +2484,13 @@ void StickersListWidget::refreshRecentStickers(bool performResize) {
auto recentPack = collectRecentStickers(); auto recentPack = collectRecentStickers();
auto recentIt = std::find_if(_mySets.begin(), _mySets.end(), [](auto &set) { 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()) { if (!recentPack.empty()) {
const auto shortName = QString(); const auto shortName = QString();
const auto externalLayout = false; const auto externalLayout = false;
auto set = Set( auto set = Set(
Stickers::RecentSetId, Data::Stickers::RecentSetId,
nullptr, nullptr,
(MTPDstickerSet::Flag::f_official (MTPDstickerSet::Flag::f_official
| MTPDstickerSet_ClientFlag::f_special), | MTPDstickerSet_ClientFlag::f_special),
@ -2512,8 +2517,8 @@ void StickersListWidget::refreshRecentStickers(bool performResize) {
void StickersListWidget::refreshFavedStickers() { void StickersListWidget::refreshFavedStickers() {
clearSelection(); clearSelection();
const auto &sets = session().data().stickerSets(); const auto &sets = session().data().stickers().sets();
const auto it = sets.find(Stickers::FavedSetId); const auto it = sets.find(Data::Stickers::FavedSetId);
if (it == sets.cend() || it->second->stickers.isEmpty()) { if (it == sets.cend() || it->second->stickers.isEmpty()) {
return; return;
} }
@ -2521,7 +2526,7 @@ void StickersListWidget::refreshFavedStickers() {
const auto externalLayout = false; const auto externalLayout = false;
const auto shortName = QString(); const auto shortName = QString();
_mySets.emplace_back( _mySets.emplace_back(
Stickers::FavedSetId, Data::Stickers::FavedSetId,
nullptr, nullptr,
(MTPDstickerSet::Flag::f_official (MTPDstickerSet::Flag::f_official
| MTPDstickerSet_ClientFlag::f_special), | MTPDstickerSet_ClientFlag::f_special),
@ -2553,7 +2558,7 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
const auto externalLayout = false; const auto externalLayout = false;
const auto count = 0; const auto count = 0;
_mySets.emplace_back( _mySets.emplace_back(
Stickers::MegagroupSetId, Data::Stickers::MegagroupSetId,
nullptr, nullptr,
MTPDstickerSet_ClientFlag::f_special | 0, MTPDstickerSet_ClientFlag::f_special | 0,
tr::lng_group_stickers(tr::now), tr::lng_group_stickers(tr::now),
@ -2579,7 +2584,7 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
return; return;
} }
auto &set = _megagroupSet->mgInfo->stickerSet.c_inputStickerSetID(); 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); const auto it = sets.find(set.vid().v);
if (it != sets.cend()) { if (it != sets.cend()) {
const auto set = it->second.get(); const auto set = it->second.get();
@ -2591,7 +2596,7 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
const auto shortName = QString(); const auto shortName = QString();
const auto externalLayout = false; const auto externalLayout = false;
_mySets.emplace_back( _mySets.emplace_back(
Stickers::MegagroupSetId, Data::Stickers::MegagroupSetId,
set, set,
MTPDstickerSet_ClientFlag::f_special | 0, MTPDstickerSet_ClientFlag::f_special | 0,
tr::lng_group_stickers(tr::now), tr::lng_group_stickers(tr::now),
@ -2609,7 +2614,7 @@ void StickersListWidget::refreshMegagroupStickers(GroupStickersPlace place) {
_api.request(MTPmessages_GetStickerSet( _api.request(MTPmessages_GetStickerSet(
_megagroupSet->mgInfo->stickerSet _megagroupSet->mgInfo->stickerSet
)).done([=](const MTPmessages_StickerSet &result) { )).done([=](const MTPmessages_StickerSet &result) {
if (const auto set = Stickers::FeedSetFull(result)) { if (const auto set = session().data().stickers().feedSetFull(result)) {
refreshStickers(); refreshStickers();
if (set->id == _megagroupSetIdRequested) { if (set->id == _megagroupSetIdRequested) {
_megagroupSetIdRequested = 0; _megagroupSetIdRequested = 0;
@ -2624,23 +2629,23 @@ std::vector<StickerIcon> StickersListWidget::fillIcons() {
auto result = std::vector<StickerIcon>(); auto result = std::vector<StickerIcon>();
result.reserve(_mySets.size() + 1); result.reserve(_mySets.size() + 1);
if (!_officialSets.empty()) { if (!_officialSets.empty()) {
result.emplace_back(Stickers::FeaturedSetId); result.emplace_back(Data::Stickers::FeaturedSetId);
} }
auto i = 0; auto i = 0;
if (i != _mySets.size() && _mySets[i].id == Stickers::FavedSetId) { if (i != _mySets.size() && _mySets[i].id == Data::Stickers::FavedSetId) {
++i; ++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; ++i;
if (result.empty() || result.back().setId != Stickers::FavedSetId) { if (result.empty() || result.back().setId != Data::Stickers::FavedSetId) {
result.emplace_back(Stickers::RecentSetId); result.emplace_back(Data::Stickers::RecentSetId);
} }
} }
for (auto l = _mySets.size(); i != l; ++i) { for (auto l = _mySets.size(); i != l; ++i) {
if (_mySets[i].id == Stickers::MegagroupSetId) { if (_mySets[i].id == Data::Stickers::MegagroupSetId) {
result.emplace_back(Stickers::MegagroupSetId); result.emplace_back(Data::Stickers::MegagroupSetId);
result.back().megagroup = _megagroupSet; result.back().megagroup = _megagroupSet;
continue; continue;
} }
@ -2702,14 +2707,14 @@ void StickersListWidget::updateSelected() {
newSelected = OverButton{ section }; newSelected = OverButton{ section };
} else if (!(sets[section].flags & MTPDstickerSet_ClientFlag::f_special)) { } else if (!(sets[section].flags & MTPDstickerSet_ClientFlag::f_special)) {
newSelected = OverSet { section }; newSelected = OverSet { section };
} else if (sets[section].id == Stickers::MegagroupSetId } else if (sets[section].id == Data::Stickers::MegagroupSetId
&& (_megagroupSet->canEditStickers() || !sets[section].stickers.empty())) { && (_megagroupSet->canEditStickers() || !sets[section].stickers.empty())) {
newSelected = OverSet { section }; newSelected = OverSet { section };
} }
} else if (p.y() >= info.rowsTop && p.y() < info.rowsBottom && sx >= 0) { } else if (p.y() >= info.rowsTop && p.y() < info.rowsBottom && sx >= 0) {
auto yOffset = p.y() - info.rowsTop; auto yOffset = p.y() - info.rowsTop;
auto &set = sets[section]; 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)) { if (_megagroupSetButtonRect.contains(stickersLeft() + sx, yOffset)) {
newSelected = OverGroupAdd {}; newSelected = OverGroupAdd {};
} }
@ -2737,20 +2742,20 @@ void StickersListWidget::updateSelected() {
} }
bool StickersListWidget::setHasTitle(const Set &set) const { bool StickersListWidget::setHasTitle(const Set &set) const {
if (set.id == Stickers::FavedSetId) { if (set.id == Data::Stickers::FavedSetId) {
return false; return false;
} else if (set.id == Stickers::RecentSetId) { } else if (set.id == Data::Stickers::RecentSetId) {
return !_mySets.empty() && _mySets[0].id == Stickers::FavedSetId; return !_mySets.empty() && _mySets[0].id == Data::Stickers::FavedSetId;
} }
return true; return true;
} }
bool StickersListWidget::stickerHasDeleteButton(const Set &set, int index) const { 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()); Assert(index >= 0 && index < _custom.size());
return _custom[index]; return _custom[index];
} }
return (set.id == Stickers::FavedSetId); return (set.id == Data::Stickers::FavedSetId);
} }
void StickersListWidget::setSelected(OverState newSelected) { void StickersListWidget::setSelected(OverState newSelected) {
@ -2819,7 +2824,7 @@ auto StickersListWidget::getLottieRenderer()
void StickersListWidget::showStickerSet(uint64 setId) { void StickersListWidget::showStickerSet(uint64 setId) {
clearSelection(); clearSelection();
if (setId == Stickers::FeaturedSetId) { if (setId == Data::Stickers::FeaturedSetId) {
if (_section != Section::Featured) { if (_section != Section::Featured) {
setSection(Section::Featured); setSection(Section::Featured);
refreshRecentStickers(true); refreshRecentStickers(true);
@ -2903,7 +2908,7 @@ void StickersListWidget::beforeHiding() {
} }
void StickersListWidget::displaySet(uint64 setId) { void StickersListWidget::displaySet(uint64 setId) {
if (setId == Stickers::MegagroupSetId) { if (setId == Data::Stickers::MegagroupSetId) {
if (_megagroupSet->canEditStickers()) { if (_megagroupSet->canEditStickers()) {
_displayingSet = true; _displayingSet = true;
checkHideWithBox(Ui::show( checkHideWithBox(Ui::show(
@ -2916,7 +2921,7 @@ void StickersListWidget::displaySet(uint64 setId) {
return; return;
} }
} }
const auto &sets = session().data().stickerSets(); const auto &sets = session().data().stickers().sets();
auto it = sets.find(setId); auto it = sets.find(setId);
if (it != sets.cend()) { if (it != sets.cend()) {
_displayingSet = true; _displayingSet = true;
@ -2937,7 +2942,7 @@ void StickersListWidget::checkHideWithBox(QPointer<Ui::BoxContent> box) {
} }
void StickersListWidget::installSet(uint64 setId) { void StickersListWidget::installSet(uint64 setId) {
const auto &sets = session().data().stickerSets(); const auto &sets = session().data().stickers().sets();
const auto it = sets.find(setId); const auto it = sets.find(setId);
if (it != sets.cend()) { if (it != sets.cend()) {
const auto set = it->second.get(); const auto set = it->second.get();
@ -2947,7 +2952,7 @@ void StickersListWidget::installSet(uint64 setId) {
_api.request(MTPmessages_GetStickerSet( _api.request(MTPmessages_GetStickerSet(
input input
)).done([=](const MTPmessages_StickerSet &result) { )).done([=](const MTPmessages_StickerSet &result) {
Stickers::FeedSetFull(result); session().data().stickers().feedSetFull(result);
sendInstallRequest(setId, input); sendInstallRequest(setId, input);
}).send(); }).send();
} else { } else {
@ -2964,15 +2969,16 @@ void StickersListWidget::sendInstallRequest(
MTP_bool(false) MTP_bool(false)
)).done([=](const MTPmessages_StickerSetInstallResult &result) { )).done([=](const MTPmessages_StickerSetInstallResult &result) {
if (result.type() == mtpc_messages_stickerSetInstallResultArchive) { if (result.type() == mtpc_messages_stickerSetInstallResultArchive) {
Stickers::ApplyArchivedResult(result.c_messages_stickerSetInstallResultArchive()); session().data().stickers().applyArchivedResult(
result.c_messages_stickerSetInstallResultArchive());
} }
}).fail([=](const RPCError &error) { }).fail([=](const RPCError &error) {
notInstalledLocally(setId); notInstalledLocally(setId);
Stickers::UndoInstallLocally(setId); session().data().stickers().undoInstallLocally(setId);
}).send(); }).send();
installedLocally(setId); installedLocally(setId);
Stickers::InstallLocally(setId); session().data().stickers().installLocally(setId);
} }
void StickersListWidget::removeMegagroupSet(bool locally) { void StickersListWidget::removeMegagroupSet(bool locally) {
@ -2982,7 +2988,7 @@ void StickersListWidget::removeMegagroupSet(bool locally) {
refreshStickers(); refreshStickers();
return; return;
} }
_removingSetId = Stickers::MegagroupSetId; _removingSetId = Data::Stickers::MegagroupSetId;
Ui::show(Box<ConfirmBox>(tr::lng_stickers_remove_group_set(tr::now), crl::guard(this, [this, group = _megagroupSet] { Ui::show(Box<ConfirmBox>(tr::lng_stickers_remove_group_set(tr::now), crl::guard(this, [this, group = _megagroupSet] {
Expects(group->mgInfo != nullptr); Expects(group->mgInfo != nullptr);
@ -2999,7 +3005,7 @@ void StickersListWidget::removeMegagroupSet(bool locally) {
} }
void StickersListWidget::removeSet(uint64 setId) { void StickersListWidget::removeSet(uint64 setId) {
const auto &sets = session().data().stickerSets(); const auto &sets = session().data().stickers().sets();
const auto it = sets.find(setId); const auto it = sets.find(setId);
if (it != sets.cend()) { if (it != sets.cend()) {
const auto set = it->second.get(); 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); auto text = tr::lng_stickers_remove_pack(tr::now, lt_sticker_pack, set->title);
Ui::show(Box<ConfirmBox>(text, tr::lng_stickers_remove_pack_confirm(tr::now), crl::guard(this, [=] { Ui::show(Box<ConfirmBox>(text, tr::lng_stickers_remove_pack_confirm(tr::now), crl::guard(this, [=] {
Ui::hideLayer(); Ui::hideLayer();
const auto &sets = session().data().stickerSets(); const auto &sets = session().data().stickers().sets();
const auto it = sets.find(_removingSetId); const auto it = sets.find(_removingSetId);
if (it != sets.cend()) { if (it != sets.cend()) {
const auto set = it->second.get(); 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(); _api.request(MTPmessages_UninstallStickerSet(MTP_inputStickerSetShortName(MTP_string(set->shortName)))).send();
} }
auto writeRecent = false; auto writeRecent = false;
auto &recent = Stickers::GetRecentPack(); auto &recent = session().data().stickers().getRecentPack();
for (auto i = recent.begin(); i != recent.cend();) { for (auto i = recent.begin(); i != recent.cend();) {
if (set->stickers.indexOf(i->first) >= 0) { if (set->stickers.indexOf(i->first) >= 0) {
i = recent.erase(i); i = recent.erase(i);
@ -3035,8 +3041,8 @@ void StickersListWidget::removeSet(uint64 setId) {
// && !(set->flags & MTPDstickerSet_ClientFlag::f_special)) { // && !(set->flags & MTPDstickerSet_ClientFlag::f_special)) {
// sets.erase(it); // sets.erase(it);
//} //}
int removeIndex = session().data().stickerSetsOrder().indexOf(_removingSetId); int removeIndex = session().data().stickers().setsOrder().indexOf(_removingSetId);
if (removeIndex >= 0) session().data().stickerSetsOrderRef().removeAt(removeIndex); if (removeIndex >= 0) session().data().stickers().setsOrderRef().removeAt(removeIndex);
refreshStickers(); refreshStickers();
Local::writeInstalledStickers(); Local::writeInstalledStickers();
if (writeRecent) Local::writeUserSettings(); if (writeRecent) Local::writeUserSettings();

View file

@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once #pragma once
#include "chat_helpers/tabbed_selector.h" #include "chat_helpers/tabbed_selector.h"
#include "chat_helpers/stickers.h" #include "data/stickers/data_stickers.h"
#include "base/variant.h" #include "base/variant.h"
#include "base/timer.h" #include "base/timer.h"
@ -34,12 +34,9 @@ class FrameRenderer;
namespace Data { namespace Data {
class DocumentMedia; class DocumentMedia;
class StickersSet;
} // namespace Data } // namespace Data
namespace Stickers {
class Set;
} // namespace Stickers
namespace ChatHelpers { namespace ChatHelpers {
struct StickerIcon; struct StickerIcon;
@ -169,7 +166,7 @@ private:
struct Set { struct Set {
Set( Set(
uint64 id, uint64 id,
Stickers::Set *set, Data::StickersSet *set,
MTPDstickerSet::Flags flags, MTPDstickerSet::Flags flags,
const QString &title, const QString &title,
const QString &shortName, const QString &shortName,
@ -181,7 +178,7 @@ private:
~Set(); ~Set();
uint64 id = 0; uint64 id = 0;
Stickers::Set *set = nullptr; Data::StickersSet *set = nullptr;
MTPDstickerSet::Flags flags = MTPDstickerSet::Flags(); MTPDstickerSet::Flags flags = MTPDstickerSet::Flags();
QString title; QString title;
QString shortName; QString shortName;
@ -308,7 +305,7 @@ private:
void refreshSearchRows(const std::vector<uint64> *cloudSets); void refreshSearchRows(const std::vector<uint64> *cloudSets);
void fillLocalSearchRows(const QString &query); void fillLocalSearchRows(const QString &query);
void fillCloudSearchRows(const std::vector<uint64> &cloudSets); void fillCloudSearchRows(const std::vector<uint64> &cloudSets);
void addSearchRow(not_null<Stickers::Set*> set); void addSearchRow(not_null<Data::StickersSet*> set);
void showPreview(); void showPreview();

View file

@ -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 <typename Method>
auto LottieCachedFromContent(
Method &&method,
Storage::Cache::Key baseKey,
uint8 keyShift,
not_null<Main::Session*> session,
const QByteArray &content,
QSize box) {
const auto key = Storage::Cache::Key{
baseKey.high,
baseKey.low + keyShift
};
const auto get = [=](FnMut<void(QByteArray &&cached)> 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 <typename Method>
auto LottieFromDocument(
Method &&method,
not_null<Data::DocumentMedia*> 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>(method),
baseKey,
keyShift,
&document->session(),
Lottie::ReadContent(data, filepath),
box);
}
return method(
Lottie::ReadContent(data, filepath),
Lottie::FrameRequest{ box });
}
std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument(
not_null<Data::DocumentMedia*> media,
StickerLottieSize sizeTag,
QSize box,
Lottie::Quality quality,
std::shared_ptr<Lottie::FrameRenderer> renderer) {
return LottiePlayerFromDocument(
media,
nullptr,
sizeTag,
box,
quality,
std::move(renderer));
}
std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument(
not_null<Data::DocumentMedia*> media,
const Lottie::ColorReplacements *replacements,
StickerLottieSize sizeTag,
QSize box,
Lottie::Quality quality,
std::shared_ptr<Lottie::FrameRenderer> renderer) {
const auto method = [&](auto &&...args) {
return std::make_unique<Lottie::SinglePlayer>(
std::forward<decltype(args)>(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<Lottie::Animation*> LottieAnimationFromDocument(
not_null<Lottie::MultiPlayer*> player,
not_null<Data::DocumentMedia*> media,
StickerLottieSize sizeTag,
QSize box) {
const auto method = [&](auto &&...args) {
return player->append(std::forward<decltype(args)>(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<Lottie::SinglePlayer> LottieThumbnail(
Data::StickersSetThumbnailView *thumb,
Data::DocumentMedia *media,
StickerLottieSize sizeTag,
QSize box,
std::shared_ptr<Lottie::FrameRenderer> 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<Lottie::SinglePlayer>(
std::forward<decltype(args)>(args)...);
};
const auto session = thumb
? &thumb->owner()->session()
: media
? &media->owner()->session()
: nullptr;
return LottieCachedFromContent(
method,
baseKey,
uint8(sizeTag),
session,
content,
box);
}
} // namespace ChatHelpers

View file

@ -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<Lottie::SinglePlayer> LottiePlayerFromDocument(
not_null<Data::DocumentMedia*> media,
StickerLottieSize sizeTag,
QSize box,
Lottie::Quality quality = Lottie::Quality(),
std::shared_ptr<Lottie::FrameRenderer> renderer = nullptr);
[[nodiscard]] std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument(
not_null<Data::DocumentMedia*> media,
const Lottie::ColorReplacements *replacements,
StickerLottieSize sizeTag,
QSize box,
Lottie::Quality quality = Lottie::Quality(),
std::shared_ptr<Lottie::FrameRenderer> renderer = nullptr);
[[nodiscard]] not_null<Lottie::Animation*> LottieAnimationFromDocument(
not_null<Lottie::MultiPlayer*> player,
not_null<Data::DocumentMedia*> media,
StickerLottieSize sizeTag,
QSize box);
[[nodiscard]] bool HasLottieThumbnail(
Data::StickersSetThumbnailView *thumb,
Data::DocumentMedia *media);
[[nodiscard]] std::unique_ptr<Lottie::SinglePlayer> LottieThumbnail(
Data::StickersSetThumbnailView *thumb,
Data::DocumentMedia *media,
StickerLottieSize sizeTag,
QSize box,
std::shared_ptr<Lottie::FrameRenderer> renderer = nullptr);
} // namespace ChatHelpers

View file

@ -10,7 +10,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/emoji_list_widget.h" #include "chat_helpers/emoji_list_widget.h"
#include "chat_helpers/stickers_list_widget.h" #include "chat_helpers/stickers_list_widget.h"
#include "chat_helpers/gifs_list_widget.h" #include "chat_helpers/gifs_list_widget.h"
#include "chat_helpers/stickers.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h" #include "ui/widgets/labels.h"
#include "ui/widgets/shadow.h" #include "ui/widgets/shadow.h"
@ -21,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/stickers/data_stickers.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mainwindow.h" #include "mainwindow.h"
#include "observer_peer.h" #include "observer_peer.h"
@ -366,7 +366,7 @@ TabbedSelector::TabbedSelector(
_showRequests.fire({}); _showRequests.fire({});
}, lifetime()); }, lifetime());
session().data().stickersUpdated( session().data().stickers().updated(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
refreshStickers(); refreshStickers();
}, lifetime()); }, lifetime());

View file

@ -17,8 +17,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "mainwidget.h" #include "mainwidget.h"
#include "core/file_utilities.h" #include "core/file_utilities.h"
#include "core/mime_type.h" #include "core/mime_type.h"
#include "chat_helpers/stickers.h" #include "data/stickers/data_stickers.h"
#include "chat_helpers/stickers_set.h" #include "data/stickers/data_stickers_set.h"
#include "media/audio/media_audio.h" #include "media/audio/media_audio.h"
#include "media/player/media_player_instance.h" #include "media/player/media_player_instance.h"
#include "media/streaming/media_streaming_loader_mtproto.h" #include "media/streaming/media_streaming_loader_mtproto.h"
@ -1208,7 +1208,7 @@ bool DocumentData::saveFromDataChecked() {
bool DocumentData::isStickerSetInstalled() const { bool DocumentData::isStickerSetInstalled() const {
Expects(sticker() != nullptr); Expects(sticker() != nullptr);
const auto &sets = _owner->stickerSets(); const auto &sets = _owner->stickers().sets();
return sticker()->set.match([&](const MTPDinputStickerSetID &data) { return sticker()->set.match([&](const MTPDinputStickerSetID &data) {
const auto i = sets.find(data.vid().v); const auto i = sets.find(data.vid().v);
return (i != sets.cend()) return (i != sets.cend())
@ -1251,8 +1251,8 @@ Data::FileOrigin DocumentData::stickerSetOrigin() const {
if (const auto data = sticker()) { if (const auto data = sticker()) {
if (const auto result = data->setOrigin()) { if (const auto result = data->setOrigin()) {
return result; return result;
} else if (Stickers::IsFaved(this)) { } else if (owner().stickers().isFaved(this)) {
return Data::FileOriginStickerSet(Stickers::FavedSetId, 0); return Data::FileOriginStickerSet(Data::Stickers::FavedSetId, 0);
} }
} }
return Data::FileOrigin(); return Data::FileOrigin();

View file

@ -33,6 +33,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "passport/passport_form_controller.h" #include "passport/passport_form_controller.h"
#include "window/themes/window_theme.h" #include "window/themes/window_theme.h"
#include "lang/lang_keys.h" // tr::lng_deleted(tr::now) in user name #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_media_types.h"
#include "data/data_folder.h" #include "data/data_folder.h"
#include "data/data_channel.h" #include "data/data_channel.h"
@ -222,7 +223,8 @@ Session::Session(not_null<Main::Session*> session)
, _cloudThemes(std::make_unique<CloudThemes>(session)) , _cloudThemes(std::make_unique<CloudThemes>(session))
, _streaming(std::make_unique<Streaming>(this)) , _streaming(std::make_unique<Streaming>(this))
, _mediaRotation(std::make_unique<MediaRotation>()) , _mediaRotation(std::make_unique<MediaRotation>())
, _histories(std::make_unique<Histories>(this)) { , _histories(std::make_unique<Histories>(this))
, _stickers(std::make_unique<Stickers>(this)) {
_cache->open(Local::cacheKey()); _cache->open(Local::cacheKey());
_bigFileCache->open(Local::cacheBigFileKey()); _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<ViewElement*> view) { void Session::registerHeavyViewPart(not_null<ViewElement*> view) {
_heavyViewParts.emplace(view); _heavyViewParts.emplace(view);
} }
@ -1473,38 +1483,6 @@ rpl::producer<not_null<UserData*>> 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<UserData*> user) { void Session::userIsContactUpdated(not_null<UserData*> user) {
const auto i = _contactViews.find(peerToUser(user->id)); const auto i = _contactViews.find(peerToUser(user->id));
if (i != _contactViews.end()) { if (i != _contactViews.end()) {
@ -1716,7 +1694,7 @@ bool Session::checkEntitiesAndViewsUpdate(const MTPDmessage &data) {
requestItemTextRefresh(existing); requestItemTextRefresh(existing);
updateDependentMessages(existing); updateDependentMessages(existing);
if (existing->mainView()) { if (existing->mainView()) {
checkSavedGif(existing); stickers().checkSavedGif(existing);
return true; return true;
} }
return false; return false;
@ -1724,40 +1702,6 @@ bool Session::checkEntitiesAndViewsUpdate(const MTPDmessage &data) {
return false; return false;
} }
void Session::addSavedGif(not_null<DocumentData*> 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<HistoryItem*> item) {
if (item->Has<HistoryMessageForwarded>()
|| (!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) { void Session::updateEditedMessage(const MTPMessage &data) {
const auto existing = data.match([](const MTPDmessageEmpty &) const auto existing = data.match([](const MTPDmessageEmpty &)
-> HistoryItem* { -> HistoryItem* {
@ -2488,7 +2432,7 @@ void Session::documentConvert(
if (idChanged) { if (idChanged) {
cache().moveIfEmpty(oldCacheKey, original->cacheKey()); cache().moveIfEmpty(oldCacheKey, original->cacheKey());
cache().moveIfEmpty(oldGoodKey, original->goodThumbnailCacheKey()); cache().moveIfEmpty(oldGoodKey, original->goodThumbnailCacheKey());
if (savedGifs().indexOf(original) >= 0) { if (stickers().savedGifs().indexOf(original) >= 0) {
Local::writeSavedGifs(); Local::writeSavedGifs();
} }
} }

View file

@ -8,11 +8,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once #pragma once
#include "storage/storage_databases.h" #include "storage/storage_databases.h"
#include "chat_helpers/stickers_set.h"
#include "dialogs/dialogs_key.h" #include "dialogs/dialogs_key.h"
#include "dialogs/dialogs_indexed_list.h" #include "dialogs/dialogs_indexed_list.h"
#include "dialogs/dialogs_main_list.h" #include "dialogs/dialogs_main_list.h"
#include "data/data_groups.h" #include "data/data_groups.h"
#include "data/data_cloud_file.h"
#include "data/data_notify_settings.h" #include "data/data_notify_settings.h"
#include "history/history_location_manager.h" #include "history/history_location_manager.h"
#include "base/timer.h" #include "base/timer.h"
@ -65,6 +65,7 @@ class MediaRotation;
class Histories; class Histories;
class DocumentMedia; class DocumentMedia;
class PhotoMedia; class PhotoMedia;
class Stickers;
class Session final { class Session final {
public: public:
@ -106,6 +107,9 @@ public:
[[nodiscard]] Histories &histories() const { [[nodiscard]] Histories &histories() const {
return *_histories; return *_histories;
} }
[[nodiscard]] Stickers &stickers() const {
return *_stickers;
}
[[nodiscard]] MsgId nextNonHistoryEntryId() { [[nodiscard]] MsgId nextNonHistoryEntryId() {
return ++_nonHistoryEntryId; return ++_nonHistoryEntryId;
} }
@ -240,6 +244,9 @@ public:
[[nodiscard]] rpl::producer<not_null<History*>> historyChanged() const; [[nodiscard]] rpl::producer<not_null<History*>> historyChanged() const;
void sendHistoryChangeNotifications(); void sendHistoryChangeNotifications();
void notifyPinnedDialogsOrderUpdated();
[[nodiscard]] rpl::producer<> pinnedDialogsOrderUpdated() const;
void registerHeavyViewPart(not_null<ViewElement*> view); void registerHeavyViewPart(not_null<ViewElement*> view);
void unregisterHeavyViewPart(not_null<ViewElement*> view); void unregisterHeavyViewPart(not_null<ViewElement*> view);
void unloadHeavyViewParts( void unloadHeavyViewParts(
@ -265,91 +272,6 @@ public:
[[nodiscard]] rpl::producer<not_null<UserData*>> megagroupParticipantAdded( [[nodiscard]] rpl::producer<not_null<UserData*>> megagroupParticipantAdded(
not_null<ChannelData*> channel) const; not_null<ChannelData*> 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<int> 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<DocumentData*> document);
void checkSavedGif(not_null<HistoryItem*> item);
HistoryItemsList idsToItems(const MessageIdsList &ids) const; HistoryItemsList idsToItems(const MessageIdsList &ids) const;
MessageIdsList itemsToIds(const HistoryItemsList &items) const; MessageIdsList itemsToIds(const HistoryItemsList &items) const;
MessageIdsList itemOrItsGroup(not_null<HistoryItem*> item) const; MessageIdsList itemOrItsGroup(not_null<HistoryItem*> item) const;
@ -808,11 +730,6 @@ private:
not_null<Folder*> folder, not_null<Folder*> folder,
const MTPDfolder &data); 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<UserData*> user); void userIsContactUpdated(not_null<UserData*> user);
void setPinnedFromDialog(const Dialogs::Key &key, bool pinned); void setPinnedFromDialog(const Dialogs::Key &key, bool pinned);
@ -876,22 +793,6 @@ private:
rpl::event_stream<MegagroupParticipant> _megagroupParticipantAdded; rpl::event_stream<MegagroupParticipant> _megagroupParticipantAdded;
rpl::event_stream<DialogsRowReplacement> _dialogsRowReplacements; rpl::event_stream<DialogsRowReplacement> _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<int> _featuredStickerSetsUnreadCount = 0;
Stickers::Sets _stickerSets;
Stickers::Order _stickerSetsOrder;
Stickers::Order _featuredStickerSetsOrder;
Stickers::Order _archivedStickerSetsOrder;
Stickers::SavedGifs _savedGifs;
Dialogs::MainList _chatsList; Dialogs::MainList _chatsList;
Dialogs::IndexedList _contactsList; Dialogs::IndexedList _contactsList;
Dialogs::IndexedList _contactsNoChatsList; Dialogs::IndexedList _contactsNoChatsList;
@ -970,6 +871,8 @@ private:
not_null<const HistoryItem*>, not_null<const HistoryItem*>,
std::vector<not_null<ViewElement*>>> _views; std::vector<not_null<ViewElement*>>> _views;
rpl::event_stream<> _pinnedDialogsOrderUpdated;
base::flat_set<not_null<ViewElement*>> _heavyViewParts; base::flat_set<not_null<ViewElement*>> _heavyViewParts;
PeerData *_topPromoted = nullptr; PeerData *_topPromoted = nullptr;
@ -1006,6 +909,7 @@ private:
std::unique_ptr<Streaming> _streaming; std::unique_ptr<Streaming> _streaming;
std::unique_ptr<MediaRotation> _mediaRotation; std::unique_ptr<MediaRotation> _mediaRotation;
std::unique_ptr<Histories> _histories; std::unique_ptr<Histories> _histories;
std::unique_ptr<Stickers> _stickers;
MsgId _nonHistoryEntryId = ServerMaxMsgId; MsgId _nonHistoryEntryId = ServerMaxMsgId;
rpl::lifetime _lifetime; rpl::lifetime _lifetime;

View file

@ -5,42 +5,101 @@ the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link: For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL 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.h"
#include "data/data_document_media.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_file_origin.h" #include "data/data_user.h"
#include "chat_helpers/stickers_set.h"
#include "boxes/stickers_box.h"
#include "boxes/confirm_box.h" #include "boxes/confirm_box.h"
#include "lang/lang_keys.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 "apiwrap.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "mainwidget.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "mainwindow.h"
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
#include "ui/emoji_config.h"
#include "ui/image/image_location_factory.h" #include "ui/image/image_location_factory.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "lottie/lottie_single_player.h"
#include "lottie/lottie_multi_player.h"
#include "facades.h" #include "facades.h"
#include "app.h"
#include "styles/style_chat_helpers.h" #include "styles/style_chat_helpers.h"
namespace Stickers { namespace Data {
namespace {
constexpr auto kDontCacheLottieAfterArea = 512 * 512; Stickers::Stickers(not_null<Session*> 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<DocumentData*> 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<HistoryItem*> item) {
if (item->Has<HistoryMessageForwarded>()
|| (!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 &v = d.vsets().v;
auto &order = Auth().data().stickerSetsOrderRef(); auto &order = setsOrderRef();
Order archived; StickersSetsOrder archived;
archived.reserve(v.size()); archived.reserve(v.size());
QMap<uint64, uint64> setsToRequest; QMap<uint64, uint64> setsToRequest;
for (const auto &stickerSet : v) { for (const auto &stickerSet : v) {
@ -60,7 +119,7 @@ void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) {
} break; } break;
} }
if (setData) { if (setData) {
auto set = FeedSet(*setData); auto set = feedSet(*setData);
if (set->stickers.isEmpty()) { if (set->stickers.isEmpty()) {
setsToRequest.insert(set->id, set->access); setsToRequest.insert(set->id, set->access);
} }
@ -73,9 +132,9 @@ void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) {
} }
if (!setsToRequest.isEmpty()) { if (!setsToRequest.isEmpty()) {
for (auto i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) { 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::writeInstalledStickers();
Local::writeArchivedStickers(); Local::writeArchivedStickers();
@ -85,15 +144,17 @@ void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) {
.st = &st::stickersToast, .st = &st::stickersToast,
.multiline = true, .multiline = true,
}); });
// Ui::show(Box<StickersBox>(archived, &Auth()), Ui::LayerOption::KeepOther); //Ui::show(
// Box<StickersBox>(archived, &session()),
// Ui::LayerOption::KeepOther);
Auth().data().notifyStickersUpdated(); notifyUpdated();
} }
// For testing: Just apply random subset or your sticker sets as archived. // For testing: Just apply random subset or your sticker sets as archived.
bool ApplyArchivedResultFake() { bool Stickers::applyArchivedResultFake() {
auto sets = QVector<MTPStickerSetCovered>(); auto sets = QVector<MTPStickerSetCovered>();
for (const auto &[id, set] : Auth().data().stickerSets()) { for (const auto &[id, set] : this->sets()) {
const auto raw = set.get(); const auto raw = set.get();
if ((raw->flags & MTPDstickerSet::Flag::f_installed_date) if ((raw->flags & MTPDstickerSet::Flag::f_installed_date)
&& !(raw->flags & MTPDstickerSet_ClientFlag::f_special)) { && !(raw->flags & MTPDstickerSet_ClientFlag::f_special)) {
@ -118,14 +179,14 @@ bool ApplyArchivedResultFake() {
if (sets.size() > 3) { if (sets.size() > 3) {
sets = sets.mid(0, 3); sets = sets.mid(0, 3);
} }
auto fakeResult = MTP_messages_stickerSetInstallResultArchive( auto result = MTP_messages_stickerSetInstallResultArchive(
MTP_vector<MTPStickerSetCovered>(sets)); MTP_vector<MTPStickerSetCovered>(sets));
ApplyArchivedResult(fakeResult.c_messages_stickerSetInstallResultArchive()); applyArchivedResult(result.c_messages_stickerSetInstallResultArchive());
return true; return true;
} }
void InstallLocally(uint64 setId) { void Stickers::installLocally(uint64 setId) {
auto &sets = Auth().data().stickerSetsRef(); auto &sets = setsRef();
auto it = sets.find(setId); auto it = sets.find(setId);
if (it == sets.end()) { if (it == sets.end()) {
return; return;
@ -138,7 +199,7 @@ void InstallLocally(uint64 setId) {
set->installDate = base::unixtime::now(); set->installDate = base::unixtime::now();
auto changedFlags = flags ^ set->flags; auto changedFlags = flags ^ set->flags;
auto &order = Auth().data().stickerSetsOrderRef(); auto &order = setsOrderRef();
int insertAtIndex = 0, currentIndex = order.indexOf(setId); int insertAtIndex = 0, currentIndex = order.indexOf(setId);
if (currentIndex != insertAtIndex) { if (currentIndex != insertAtIndex) {
if (currentIndex > 0) { if (currentIndex > 0) {
@ -163,17 +224,17 @@ void InstallLocally(uint64 setId) {
Local::writeFeaturedStickers(); Local::writeFeaturedStickers();
} }
if (changedFlags & MTPDstickerSet::Flag::f_archived) { if (changedFlags & MTPDstickerSet::Flag::f_archived) {
auto index = Auth().data().archivedStickerSetsOrderRef().indexOf(setId); auto index = archivedSetsOrderRef().indexOf(setId);
if (index >= 0) { if (index >= 0) {
Auth().data().archivedStickerSetsOrderRef().removeAt(index); archivedSetsOrderRef().removeAt(index);
Local::writeArchivedStickers(); Local::writeArchivedStickers();
} }
} }
Auth().data().notifyStickersUpdated(); notifyUpdated();
} }
void UndoInstallLocally(uint64 setId) { void Stickers::undoInstallLocally(uint64 setId) {
const auto &sets = Auth().data().stickerSets(); const auto &sets = this->sets();
const auto it = sets.find(setId); const auto it = sets.find(setId);
if (it == sets.end()) { if (it == sets.end()) {
return; return;
@ -183,22 +244,22 @@ void UndoInstallLocally(uint64 setId) {
set->flags &= ~MTPDstickerSet::Flag::f_installed_date; set->flags &= ~MTPDstickerSet::Flag::f_installed_date;
set->installDate = TimeId(0); set->installDate = TimeId(0);
auto &order = Auth().data().stickerSetsOrderRef(); auto &order = setsOrderRef();
int currentIndex = order.indexOf(setId); int currentIndex = order.indexOf(setId);
if (currentIndex >= 0) { if (currentIndex >= 0) {
order.removeAt(currentIndex); order.removeAt(currentIndex);
} }
Local::writeInstalledStickers(); Local::writeInstalledStickers();
Auth().data().notifyStickersUpdated(); notifyUpdated();
Ui::show( Ui::show(
Box<InformBox>(tr::lng_stickers_not_found(tr::now)), Box<InformBox>(tr::lng_stickers_not_found(tr::now)),
Ui::LayerOption::KeepOther); Ui::LayerOption::KeepOther);
} }
bool IsFaved(not_null<const DocumentData*> document) { bool Stickers::isFaved(not_null<const DocumentData*> document) {
const auto &sets = Auth().data().stickerSets(); const auto &sets = this->sets();
const auto it = sets.find(FavedSetId); const auto it = sets.find(FavedSetId);
if (it == sets.cend()) { if (it == sets.cend()) {
return false; return false;
@ -211,7 +272,7 @@ bool IsFaved(not_null<const DocumentData*> document) {
return false; return false;
} }
void CheckFavedLimit(Set &set) { void Stickers::checkFavedLimit(StickersSet &set) {
if (set.stickers.size() <= Global::StickersFavedLimit()) { if (set.stickers.size() <= Global::StickersFavedLimit()) {
return; return;
} }
@ -230,19 +291,20 @@ void CheckFavedLimit(Set &set) {
} }
} }
void PushFavedToFront( void Stickers::pushFavedToFront(
Set &set, StickersSet &set,
not_null<DocumentData*> document, not_null<DocumentData*> document,
const std::vector<not_null<EmojiPtr>> &emojiList) { const std::vector<not_null<EmojiPtr>> &emojiList) {
set.stickers.push_front(document); set.stickers.push_front(document);
for (auto emoji : emojiList) { for (auto emoji : emojiList) {
set.emoji[emoji].push_front(document); 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()); Expects(index > 0 && index < set.stickers.size());
auto document = set.stickers[index]; auto document = set.stickers[index];
while (index-- != 0) { while (index-- != 0) {
set.stickers[index + 1] = set.stickers[index]; set.stickers[index + 1] = set.stickers[index];
@ -259,15 +321,13 @@ void MoveFavedToFront(Set &set, int index) {
} }
} }
void RequestSetToPushFaved(not_null<DocumentData*> document); void Stickers::setIsFaved(
void SetIsFaved(
not_null<DocumentData*> document, not_null<DocumentData*> document,
std::optional<std::vector<not_null<EmojiPtr>>> emojiList = std::nullopt) { std::optional<std::vector<not_null<EmojiPtr>>> emojiList) {
auto &sets = document->owner().stickerSetsRef(); auto &sets = setsRef();
auto it = sets.find(FavedSetId); auto it = sets.find(FavedSetId);
if (it == sets.end()) { if (it == sets.end()) {
it = sets.emplace(FavedSetId, std::make_unique<Set>( it = sets.emplace(FavedSetId, std::make_unique<StickersSet>(
&document->owner(), &document->owner(),
FavedSetId, FavedSetId,
uint64(0), uint64(0),
@ -284,22 +344,22 @@ void SetIsFaved(
return; return;
} }
if (index > 0) { if (index > 0) {
MoveFavedToFront(*set, index); moveFavedToFront(*set, index);
} else if (emojiList) { } else if (emojiList) {
PushFavedToFront(*set, document, *emojiList); pushFavedToFront(*set, document, *emojiList);
} else if (auto list = GetEmojiListFromSet(document)) { } else if (auto list = getEmojiListFromSet(document)) {
PushFavedToFront(*set, document, *list); pushFavedToFront(*set, document, *list);
} else { } else {
RequestSetToPushFaved(document); requestSetToPushFaved(document);
return; return;
} }
Local::writeFavedStickers(); Local::writeFavedStickers();
Auth().data().notifyStickersUpdated(); notifyUpdated();
Auth().api().stickerSetInstalled(FavedSetId); session().api().stickerSetInstalled(FavedSetId);
} }
void RequestSetToPushFaved(not_null<DocumentData*> document) { void Stickers::requestSetToPushFaved(not_null<DocumentData*> document) {
auto addAnyway = [document](std::vector<not_null<EmojiPtr>> list) { auto addAnyway = [=](std::vector<not_null<EmojiPtr>> list) {
if (list.empty()) { if (list.empty()) {
if (auto sticker = document->sticker()) { if (auto sticker = document->sticker()) {
if (auto emoji = Ui::Emoji::Find(sticker->alt)) { if (auto emoji = Ui::Emoji::Find(sticker->alt)) {
@ -307,10 +367,11 @@ void RequestSetToPushFaved(not_null<DocumentData*> 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); Expects(result.type() == mtpc_messages_stickerSet);
auto list = std::vector<not_null<EmojiPtr>>(); auto list = std::vector<not_null<EmojiPtr>>();
auto &d = result.c_messages_stickerSet(); auto &d = result.c_messages_stickerSet();
list.reserve(d.vpacks().v.size()); list.reserve(d.vpacks().v.size());
@ -336,8 +397,8 @@ void RequestSetToPushFaved(not_null<DocumentData*> document) {
})); }));
} }
void SetIsNotFaved(not_null<DocumentData*> document) { void Stickers::setIsNotFaved(not_null<DocumentData*> document) {
auto &sets = Auth().data().stickerSetsRef(); auto &sets = setsRef();
auto it = sets.find(FavedSetId); auto it = sets.find(FavedSetId);
if (it == sets.end()) { if (it == sets.end()) {
return; return;
@ -363,22 +424,22 @@ void SetIsNotFaved(not_null<DocumentData*> document) {
sets.erase(it); sets.erase(it);
} }
Local::writeFavedStickers(); Local::writeFavedStickers();
Auth().data().notifyStickersUpdated(); notifyUpdated();
} }
void SetFaved(not_null<DocumentData*> document, bool faved) { void Stickers::setFaved(not_null<DocumentData*> document, bool faved) {
if (faved) { if (faved) {
SetIsFaved(document); setIsFaved(document);
} else { } else {
SetIsNotFaved(document); setIsNotFaved(document);
} }
} }
void SetsReceived(const QVector<MTPStickerSet> &data, int32 hash) { void Stickers::setsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
auto &setsOrder = Auth().data().stickerSetsOrderRef(); auto &setsOrder = setsOrderRef();
setsOrder.clear(); setsOrder.clear();
auto &sets = Auth().data().stickerSetsRef(); auto &sets = setsRef();
QMap<uint64, uint64> setsToRequest; QMap<uint64, uint64> setsToRequest;
for (auto &[id, set] : sets) { for (auto &[id, set] : sets) {
if (!(set->flags & MTPDstickerSet::Flag::f_archived)) { if (!(set->flags & MTPDstickerSet::Flag::f_archived)) {
@ -389,7 +450,7 @@ void SetsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
} }
for (const auto &setData : data) { for (const auto &setData : data) {
if (setData.type() == mtpc_stickerSet) { 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)) { if (!(set->flags & MTPDstickerSet::Flag::f_archived) || (set->flags & MTPDstickerSet::Flag::f_official)) {
setsOrder.push_back(set->id); setsOrder.push_back(set->id);
if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) { if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
@ -399,7 +460,7 @@ void SetsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
} }
} }
auto writeRecent = false; auto writeRecent = false;
auto &recent = GetRecentPack(); auto &recent = getRecentPack();
for (auto it = sets.begin(); it != sets.end();) { for (auto it = sets.begin(); it != sets.end();) {
const auto set = it->second.get(); const auto set = it->second.get();
bool installed = (set->flags & MTPDstickerSet::Flag::f_installed_date); bool installed = (set->flags & MTPDstickerSet::Flag::f_installed_date);
@ -424,7 +485,7 @@ void SetsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
} }
if (!setsToRequest.isEmpty()) { if (!setsToRequest.isEmpty()) {
auto &api = Auth().api(); auto &api = session().api();
for (auto i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) { for (auto i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) {
api.scheduleStickerSetRequest(i.key(), i.value()); api.scheduleStickerSetRequest(i.key(), i.value());
} }
@ -438,12 +499,12 @@ void SetsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
LOG(("API Error: received stickers hash %1 while counted hash is %2").arg(hash).arg(Local::countStickersHash())); LOG(("API Error: received stickers hash %1 while counted hash is %2").arg(hash).arg(Local::countStickersHash()));
} }
Auth().data().notifyStickersUpdated(); notifyUpdated();
} }
void SetPackAndEmoji( void Stickers::setPackAndEmoji(
Set &set, StickersSet &set,
Pack &&pack, StickersPack &&pack,
const std::vector<TimeId> &&dates, const std::vector<TimeId> &&dates,
const QVector<MTPStickerPack> &packs) { const QVector<MTPStickerPack> &packs) {
set.stickers = std::move(pack); set.stickers = std::move(pack);
@ -456,10 +517,10 @@ void SetPackAndEmoji(
emoji = emoji->original(); emoji = emoji->original();
auto &stickers = pack.vdocuments().v; auto &stickers = pack.vdocuments().v;
auto p = Pack(); auto p = StickersPack();
p.reserve(stickers.size()); p.reserve(stickers.size());
for (auto j = 0, c = stickers.size(); j != c; ++j) { 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; if (!document || !document->sticker()) continue;
p.push_back(document); p.push_back(document);
@ -469,14 +530,14 @@ void SetPackAndEmoji(
} }
} }
void SpecialSetReceived( void Stickers::specialSetReceived(
uint64 setId, uint64 setId,
const QString &setTitle, const QString &setTitle,
const QVector<MTPDocument> &items, const QVector<MTPDocument> &items,
int32 hash, int32 hash,
const QVector<MTPStickerPack> &packs, const QVector<MTPStickerPack> &packs,
const QVector<MTPint> &usageDates) { const QVector<MTPint> &usageDates) {
auto &sets = Auth().data().stickerSetsRef(); auto &sets = setsRef();
auto it = sets.find(setId); auto it = sets.find(setId);
if (items.isEmpty()) { if (items.isEmpty()) {
@ -485,8 +546,8 @@ void SpecialSetReceived(
} }
} else { } else {
if (it == sets.cend()) { if (it == sets.cend()) {
it = sets.emplace(setId, std::make_unique<Set>( it = sets.emplace(setId, std::make_unique<StickersSet>(
&Auth().data(), &owner(),
setId, setId,
uint64(0), uint64(0),
setTitle, setTitle,
@ -507,11 +568,11 @@ void SpecialSetReceived(
&& (setId == CloudRecentSetId); && (setId == CloudRecentSetId);
auto customIt = sets.find(CustomSetId); auto customIt = sets.find(CustomSetId);
auto pack = Pack(); auto pack = StickersPack();
pack.reserve(items.size()); pack.reserve(items.size());
for (const auto &item : items) { for (const auto &item : items) {
++dateIndex; ++dateIndex;
const auto document = Auth().data().processDocument(item); const auto document = owner().processDocument(item);
if (!document->sticker()) { if (!document->sticker()) {
continue; continue;
} }
@ -535,7 +596,7 @@ void SpecialSetReceived(
} }
auto writeRecent = false; auto writeRecent = false;
auto &recent = GetRecentPack(); auto &recent = getRecentPack();
for (auto i = recent.begin(); i != recent.cend();) { for (auto i = recent.begin(); i != recent.cend();) {
if (set->stickers.indexOf(i->first) >= 0 && pack.indexOf(i->first) < 0) { if (set->stickers.indexOf(i->first) >= 0 && pack.indexOf(i->first) < 0) {
i = recent.erase(i); i = recent.erase(i);
@ -548,7 +609,7 @@ void SpecialSetReceived(
if (pack.isEmpty()) { if (pack.isEmpty()) {
sets.erase(it); sets.erase(it);
} else { } else {
SetPackAndEmoji(*set, std::move(pack), std::move(dates), packs); setPackAndEmoji(*set, std::move(pack), std::move(dates), packs);
} }
if (writeRecent) { if (writeRecent) {
@ -572,10 +633,10 @@ void SpecialSetReceived(
default: Unexpected("setId in SpecialSetReceived()"); default: Unexpected("setId in SpecialSetReceived()");
} }
Auth().data().notifyStickersUpdated(); notifyUpdated();
} }
void FeaturedSetsReceived( void Stickers::featuredSetsReceived(
const QVector<MTPStickerSetCovered> &list, const QVector<MTPStickerSetCovered> &list,
const QVector<MTPlong> &unread, const QVector<MTPlong> &unread,
int32 hash) { int32 hash) {
@ -589,10 +650,10 @@ void FeaturedSetsReceived(
unreadIds.end() unreadIds.end()
}; };
auto &setsOrder = Auth().data().featuredStickerSetsOrderRef(); auto &setsOrder = featuredSetsOrderRef();
setsOrder.clear(); setsOrder.clear();
auto &sets = Auth().data().stickerSetsRef(); auto &sets = setsRef();
auto setsToRequest = base::flat_map<uint64, uint64>(); auto setsToRequest = base::flat_map<uint64, uint64>();
for (auto &[id, set] : sets) { for (auto &[id, set] : sets) {
// Mark for removing. // Mark for removing.
@ -605,11 +666,11 @@ void FeaturedSetsReceived(
}); });
}); });
auto it = sets.find(data->vid().v); 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 installDate = data->vinstalled_date().value_or_empty();
const auto thumb = data->vthumb(); const auto thumb = data->vthumb();
const auto thumbnail = thumb const auto thumbnail = thumb
? Images::FromPhotoSize(&Auth(), *data, *thumb) ? Images::FromPhotoSize(&session(), *data, *thumb)
: ImageWithLocation(); : ImageWithLocation();
if (it == sets.cend()) { if (it == sets.cend()) {
auto setClientFlags = MTPDstickerSet_ClientFlag::f_featured auto setClientFlags = MTPDstickerSet_ClientFlag::f_featured
@ -617,8 +678,8 @@ void FeaturedSetsReceived(
if (unreadMap.contains(data->vid().v)) { if (unreadMap.contains(data->vid().v)) {
setClientFlags |= MTPDstickerSet_ClientFlag::f_unread; setClientFlags |= MTPDstickerSet_ClientFlag::f_unread;
} }
it = sets.emplace(data->vid().v, std::make_unique<Set>( it = sets.emplace(data->vid().v, std::make_unique<StickersSet>(
&Auth().data(), &owner(),
data->vid().v, data->vid().v,
data->vaccess_hash().v, data->vaccess_hash().v,
title, title,
@ -672,14 +733,14 @@ void FeaturedSetsReceived(
it = sets.erase(it); it = sets.erase(it);
} }
} }
Auth().data().setFeaturedStickerSetsUnreadCount(unreadCount); setFeaturedSetsUnreadCount(unreadCount);
if (Local::countFeaturedStickersHash() != hash) { if (Local::countFeaturedStickersHash() != hash) {
LOG(("API Error: received featured stickers hash %1 while counted hash is %2").arg(hash).arg(Local::countFeaturedStickersHash())); LOG(("API Error: received featured stickers hash %1 while counted hash is %2").arg(hash).arg(Local::countFeaturedStickersHash()));
} }
if (!setsToRequest.empty()) { if (!setsToRequest.empty()) {
auto &api = Auth().api(); auto &api = session().api();
for (const auto [setId, accessHash] : setsToRequest) { for (const auto [setId, accessHash] : setsToRequest) {
api.scheduleStickerSetRequest(setId, accessHash); api.scheduleStickerSetRequest(setId, accessHash);
} }
@ -688,16 +749,16 @@ void FeaturedSetsReceived(
Local::writeFeaturedStickers(); Local::writeFeaturedStickers();
Auth().data().notifyStickersUpdated(); notifyUpdated();
} }
void GifsReceived(const QVector<MTPDocument> &items, int32 hash) { void Stickers::gifsReceived(const QVector<MTPDocument> &items, int32 hash) {
auto &saved = Auth().data().savedGifsRef(); auto &saved = savedGifsRef();
saved.clear(); saved.clear();
saved.reserve(items.size()); saved.reserve(items.size());
for (const auto &item : items) { for (const auto &item : items) {
const auto document = Auth().data().processDocument(item); const auto document = owner().processDocument(item);
if (!document->isGifv()) { if (!document->isGifv()) {
LOG(("API Error: " LOG(("API Error: "
"bad document returned in HistoryWidget::savedGifsGot!")); "bad document returned in HistoryWidget::savedGifsGot!"));
@ -712,11 +773,10 @@ void GifsReceived(const QVector<MTPDocument> &items, int32 hash) {
Local::writeSavedGifs(); Local::writeSavedGifs();
Auth().data().notifySavedGifsUpdated(); notifySavedGifsUpdated();
} }
std::vector<not_null<DocumentData*>> GetListByEmoji( std::vector<not_null<DocumentData*>> Stickers::getListByEmoji(
not_null<Main::Session*> session,
not_null<EmojiPtr> emoji, not_null<EmojiPtr> emoji,
uint64 seed) { uint64 seed) {
const auto original = emoji->original(); const auto original = emoji->original();
@ -726,7 +786,7 @@ std::vector<not_null<DocumentData*>> GetListByEmoji(
TimeId date = 0; TimeId date = 0;
}; };
auto result = std::vector<StickerWithDate>(); auto result = std::vector<StickerWithDate>();
auto &sets = session->data().stickerSetsRef(); auto &sets = setsRef();
auto setsToRequest = base::flat_map<uint64, uint64>(); auto setsToRequest = base::flat_map<uint64, uint64>();
const auto add = [&](not_null<DocumentData*> document, TimeId date) { const auto add = [&](not_null<DocumentData*> document, TimeId date) {
@ -811,7 +871,9 @@ std::vector<not_null<DocumentData*>> GetListByEmoji(
} }
} }
} }
const auto addList = [&](const Order &order, MTPDstickerSet::Flag skip) { const auto addList = [&](
const StickersSetsOrder &order,
MTPDstickerSet::Flag skip) {
for (const auto setId : order) { for (const auto setId : order) {
auto it = sets.find(setId); auto it = sets.find(setId);
if (it == sets.cend() || (it->second->flags & skip)) { if (it == sets.cend() || (it->second->flags & skip)) {
@ -842,21 +904,21 @@ std::vector<not_null<DocumentData*>> GetListByEmoji(
}; };
addList( addList(
session->data().stickerSetsOrder(), setsOrder(),
MTPDstickerSet::Flag::f_archived); MTPDstickerSet::Flag::f_archived);
//addList( //addList(
// session->data().featuredStickerSetsOrder(), // featuredSetsOrder(),
// MTPDstickerSet::Flag::f_installed_date); // MTPDstickerSet::Flag::f_installed_date);
if (!setsToRequest.empty()) { if (!setsToRequest.empty()) {
for (const auto &[setId, accessHash] : setsToRequest) { 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()) { if (session().settings().suggestStickersByEmoji()) {
const auto others = session->api().stickersByEmoji(original); const auto others = session().api().stickersByEmoji(original);
if (!others) { if (!others) {
return {}; return {};
} }
@ -878,14 +940,14 @@ std::vector<not_null<DocumentData*>> GetListByEmoji(
}) | ranges::to_vector; }) | ranges::to_vector;
} }
std::optional<std::vector<not_null<EmojiPtr>>> GetEmojiListFromSet( std::optional<std::vector<not_null<EmojiPtr>>> Stickers::getEmojiListFromSet(
not_null<DocumentData*> document) { not_null<DocumentData*> document) {
if (auto sticker = document->sticker()) { if (auto sticker = document->sticker()) {
auto &inputSet = sticker->set; auto &inputSet = sticker->set;
if (inputSet.type() != mtpc_inputStickerSetID) { if (inputSet.type() != mtpc_inputStickerSetID) {
return std::nullopt; return std::nullopt;
} }
const auto &sets = Auth().data().stickerSets(); const auto &sets = this->sets();
auto it = sets.find(inputSet.c_inputStickerSetID().vid().v); auto it = sets.find(inputSet.c_inputStickerSetID().vid().v);
if (it == sets.cend()) { if (it == sets.cend()) {
return std::nullopt; return std::nullopt;
@ -905,18 +967,18 @@ std::optional<std::vector<not_null<EmojiPtr>>> GetEmojiListFromSet(
return std::nullopt; return std::nullopt;
} }
Set *FeedSet(const MTPDstickerSet &data) { StickersSet *Stickers::feedSet(const MTPDstickerSet &data) {
auto &sets = Auth().data().stickerSetsRef(); auto &sets = setsRef();
auto it = sets.find(data.vid().v); auto it = sets.find(data.vid().v);
auto title = GetSetTitle(data); auto title = getSetTitle(data);
auto flags = MTPDstickerSet::Flags(0); auto flags = MTPDstickerSet::Flags(0);
const auto thumb = data.vthumb(); const auto thumb = data.vthumb();
const auto thumbnail = thumb const auto thumbnail = thumb
? Images::FromPhotoSize(&Auth(), data, *thumb) ? Images::FromPhotoSize(&session(), data, *thumb)
: ImageWithLocation(); : ImageWithLocation();
if (it == sets.cend()) { if (it == sets.cend()) {
it = sets.emplace(data.vid().v, std::make_unique<Set>( it = sets.emplace(data.vid().v, std::make_unique<StickersSet>(
&Auth().data(), &owner(),
data.vid().v, data.vid().v,
data.vaccess_hash().v, data.vaccess_hash().v,
title, title,
@ -955,33 +1017,33 @@ Set *FeedSet(const MTPDstickerSet &data) {
const auto set = it->second.get(); const auto set = it->second.get();
auto changedFlags = (flags ^ set->flags); auto changedFlags = (flags ^ set->flags);
if (changedFlags & MTPDstickerSet::Flag::f_archived) { 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 (set->flags & MTPDstickerSet::Flag::f_archived) {
if (index < 0) { if (index < 0) {
Auth().data().archivedStickerSetsOrderRef().push_front(set->id); archivedSetsOrderRef().push_front(set->id);
} }
} else if (index >= 0) { } else if (index >= 0) {
Auth().data().archivedStickerSetsOrderRef().removeAt(index); archivedSetsOrderRef().removeAt(index);
} }
} }
return it->second.get(); 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.type() == mtpc_messages_stickerSet);
Expects(data.c_messages_stickerSet().vset().type() == mtpc_stickerSet); Expects(data.c_messages_stickerSet().vset().type() == mtpc_stickerSet);
const auto &d = data.c_messages_stickerSet(); const auto &d = data.c_messages_stickerSet();
const auto &s = d.vset().c_stickerSet(); const auto &s = d.vset().c_stickerSet();
auto &sets = Auth().data().stickerSetsRef(); auto &sets = setsRef();
const auto wasArchived = [&] { const auto wasArchived = [&] {
auto it = sets.find(s.vid().v); auto it = sets.find(s.vid().v);
return (it != sets.end()) return (it != sets.end())
&& (it->second->flags & MTPDstickerSet::Flag::f_archived); && (it->second->flags & MTPDstickerSet::Flag::f_archived);
}(); }();
auto set = FeedSet(s); auto set = feedSet(s);
set->flags &= ~MTPDstickerSet_ClientFlag::f_not_loaded; set->flags &= ~MTPDstickerSet_ClientFlag::f_not_loaded;
@ -991,10 +1053,10 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) {
MTP_long(set->id), MTP_long(set->id),
MTP_long(set->access)); MTP_long(set->access));
auto pack = Pack(); auto pack = StickersPack();
pack.reserve(d_docs.size()); pack.reserve(d_docs.size());
for (const auto &item : d_docs) { for (const auto &item : d_docs) {
const auto document = Auth().data().processDocument(item); const auto document = owner().processDocument(item);
if (!document->sticker()) continue; if (!document->sticker()) continue;
pack.push_back(document); pack.push_back(document);
@ -1015,7 +1077,7 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) {
} }
auto writeRecent = false; auto writeRecent = false;
auto &recent = GetRecentPack(); auto &recent = getRecentPack();
for (auto i = recent.begin(); i != recent.cend();) { for (auto i = recent.begin(); i != recent.cend();) {
if (set->stickers.indexOf(i->first) >= 0 && pack.indexOf(i->first) < 0) { if (set->stickers.indexOf(i->first) >= 0 && pack.indexOf(i->first) < 0) {
i = recent.erase(i); i = recent.erase(i);
@ -1026,8 +1088,8 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) {
} }
if (pack.isEmpty()) { if (pack.isEmpty()) {
int removeIndex = Auth().data().stickerSetsOrder().indexOf(set->id); int removeIndex = setsOrder().indexOf(set->id);
if (removeIndex >= 0) Auth().data().stickerSetsOrderRef().removeAt(removeIndex); if (removeIndex >= 0) setsOrderRef().removeAt(removeIndex);
sets.remove(set->id); sets.remove(set->id);
set = nullptr; set = nullptr;
} else { } else {
@ -1042,10 +1104,10 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) {
emoji = emoji->original(); emoji = emoji->original();
auto &stickers = pack.vdocuments().v; auto &stickers = pack.vdocuments().v;
Pack p; StickersPack p;
p.reserve(stickers.size()); p.reserve(stickers.size());
for (auto j = 0, c = stickers.size(); j != c; ++j) { 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; if (!doc || !doc->sticker()) continue;
p.push_back(doc); p.push_back(doc);
@ -1074,12 +1136,12 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) {
} }
} }
Auth().data().notifyStickersUpdated(); notifyUpdated();
return set; return set;
} }
void NewSetReceived(const MTPmessages_StickerSet &data) { void Stickers::newSetReceived(const MTPmessages_StickerSet &data) {
bool writeArchived = false; bool writeArchived = false;
const auto &set = data.c_messages_stickerSet(); const auto &set = data.c_messages_stickerSet();
const auto &s = set.vset().c_stickerSet(); const auto &s = set.vset().c_stickerSet();
@ -1094,7 +1156,7 @@ void NewSetReceived(const MTPmessages_StickerSet &data) {
} else if (s.is_masks()) { } else if (s.is_masks()) {
return; return;
} }
auto &order = Auth().data().stickerSetsOrderRef(); auto &order = setsOrderRef();
int32 insertAtIndex = 0, currentIndex = order.indexOf(s.vid().v); int32 insertAtIndex = 0, currentIndex = order.indexOf(s.vid().v);
if (currentIndex != insertAtIndex) { if (currentIndex != insertAtIndex) {
if (currentIndex > 0) { if (currentIndex > 0) {
@ -1103,10 +1165,10 @@ void NewSetReceived(const MTPmessages_StickerSet &data) {
order.insert(insertAtIndex, s.vid().v); 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()); auto title = qs(s.vtitle());
if ((s.vflags().v & MTPDstickerSet::Flag::f_official) && !title.compare(qstr("Great Minds"), Qt::CaseInsensitive)) { if ((s.vflags().v & MTPDstickerSet::Flag::f_official) && !title.compare(qstr("Great Minds"), Qt::CaseInsensitive)) {
return tr::lng_stickers_default_set(tr::now); return tr::lng_stickers_default_set(tr::now);
@ -1114,7 +1176,7 @@ QString GetSetTitle(const MTPDstickerSet &s) {
return title; return title;
} }
RecentStickerPack &GetRecentPack() { RecentStickerPack &Stickers::getRecentPack() {
if (cRecentStickers().isEmpty() && !cRecentStickersPreload().isEmpty()) { if (cRecentStickers().isEmpty() && !cRecentStickersPreload().isEmpty()) {
const auto p = cRecentStickersPreload(); const auto p = cRecentStickersPreload();
cSetRecentStickersPreload(RecentStickerPreload()); cSetRecentStickersPreload(RecentStickerPreload());
@ -1122,7 +1184,7 @@ RecentStickerPack &GetRecentPack() {
auto &recent = cRefRecentStickers(); auto &recent = cRefRecentStickers();
recent.reserve(p.size()); recent.reserve(p.size());
for (const auto &preloaded : p) { 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; if (!document || !document->sticker()) continue;
recent.push_back(qMakePair(document, preloaded.second)); recent.push_back(qMakePair(document, preloaded.second));
@ -1131,168 +1193,4 @@ RecentStickerPack &GetRecentPack() {
return cRefRecentStickers(); return cRefRecentStickers();
} }
template <typename Method>
auto LottieCachedFromContent(
Method &&method,
Storage::Cache::Key baseKey,
uint8 keyShift,
not_null<Main::Session*> session,
const QByteArray &content,
QSize box) {
const auto key = Storage::Cache::Key{
baseKey.high,
baseKey.low + keyShift
};
const auto get = [=](FnMut<void(QByteArray &&cached)> 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 <typename Method>
auto LottieFromDocument(
Method &&method,
not_null<Data::DocumentMedia*> 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>(method),
baseKey,
keyShift,
&document->session(),
Lottie::ReadContent(data, filepath),
box);
}
return method(
Lottie::ReadContent(data, filepath),
Lottie::FrameRequest{ box });
}
std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument(
not_null<Data::DocumentMedia*> media,
LottieSize sizeTag,
QSize box,
Lottie::Quality quality,
std::shared_ptr<Lottie::FrameRenderer> renderer) {
return LottiePlayerFromDocument(
media,
nullptr,
sizeTag,
box,
quality,
std::move(renderer));
}
std::unique_ptr<Lottie::SinglePlayer> LottiePlayerFromDocument(
not_null<Data::DocumentMedia*> media,
const Lottie::ColorReplacements *replacements,
LottieSize sizeTag,
QSize box,
Lottie::Quality quality,
std::shared_ptr<Lottie::FrameRenderer> renderer) {
const auto method = [&](auto &&...args) {
return std::make_unique<Lottie::SinglePlayer>(
std::forward<decltype(args)>(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<Lottie::Animation*> LottieAnimationFromDocument(
not_null<Lottie::MultiPlayer*> player,
not_null<Data::DocumentMedia*> media,
LottieSize sizeTag,
QSize box) {
const auto method = [&](auto &&...args) {
return player->append(std::forward<decltype(args)>(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<Lottie::SinglePlayer> LottieThumbnail(
SetThumbnailView *thumb,
Data::DocumentMedia *media,
LottieSize sizeTag,
QSize box,
std::shared_ptr<Lottie::FrameRenderer> 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<Lottie::SinglePlayer>(
std::forward<decltype(args)>(args)...);
};
const auto session = thumb
? &thumb->owner()->session()
: media
? &media->owner()->session()
: nullptr;
return LottieCachedFromContent(
method,
baseKey,
uint8(sizeTag),
session,
content,
box);
}
} // namespace Stickers } // namespace Stickers

View file

@ -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<Session*> 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<int> 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<DocumentData*> document);
void checkSavedGif(not_null<HistoryItem*> item);
void applyArchivedResult(
const MTPDmessages_stickerSetInstallResultArchive &d);
bool applyArchivedResultFake(); // For testing.
void installLocally(uint64 setId);
void undoInstallLocally(uint64 setId);
bool isFaved(not_null<const DocumentData*> document);
void setFaved(not_null<DocumentData*> document, bool faved);
void setsReceived(const QVector<MTPStickerSet> &data, int32 hash);
void specialSetReceived(
uint64 setId,
const QString &setTitle,
const QVector<MTPDocument> &items,
int32 hash,
const QVector<MTPStickerPack> &packs = QVector<MTPStickerPack>(),
const QVector<MTPint> &usageDates = QVector<MTPint>());
void featuredSetsReceived(
const QVector<MTPStickerSetCovered> &list,
const QVector<MTPlong> &unread,
int32 hash);
void gifsReceived(const QVector<MTPDocument> &items, int32 hash);
std::vector<not_null<DocumentData*>> getListByEmoji(
not_null<EmojiPtr> emoji,
uint64 seed);
std::optional<std::vector<not_null<EmojiPtr>>> getEmojiListFromSet(
not_null<DocumentData*> 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<DocumentData*> document,
std::optional<std::vector<not_null<EmojiPtr>>> emojiList
= std::nullopt);
void setIsNotFaved(not_null<DocumentData*> document);
void pushFavedToFront(
StickersSet &set,
not_null<DocumentData*> document,
const std::vector<not_null<EmojiPtr>> &emojiList);
void moveFavedToFront(StickersSet &set, int index);
void requestSetToPushFaved(not_null<DocumentData*> document);
void setPackAndEmoji(
StickersSet &set,
StickersPack &&pack,
const std::vector<TimeId> &&dates,
const QVector<MTPStickerPack> &packs);
const not_null<Session*> _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<int> _featuredSetsUnreadCount = 0;
StickersSets _sets;
StickersSetsOrder _setsOrder;
StickersSetsOrder _featuredSetsOrder;
StickersSetsOrder _archivedSetsOrder;
SavedGifs _savedGifs;
};
} // namespace Data

View file

@ -5,7 +5,7 @@ the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link: For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL 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 "main/main_session.h"
#include "data/data_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 "ui/image/image.h"
#include "app.h" #include "app.h"
namespace Stickers { namespace Data {
SetThumbnailView::SetThumbnailView(not_null<Set*> owner) : _owner(owner) { StickersSetThumbnailView::StickersSetThumbnailView(
not_null<StickersSet*> owner)
: _owner(owner) {
} }
not_null<Set*> SetThumbnailView::owner() const { not_null<StickersSet*> StickersSetThumbnailView::owner() const {
return _owner; return _owner;
} }
void SetThumbnailView::set( void StickersSetThumbnailView::set(
not_null<Main::Session*> session, not_null<Main::Session*> session,
QByteArray content) { QByteArray content) {
auto image = App::readImage(content, nullptr, false); auto image = App::readImage(content, nullptr, false);
@ -35,15 +37,15 @@ void SetThumbnailView::set(
session->downloaderTaskFinished().notify(); session->downloaderTaskFinished().notify();
} }
Image *SetThumbnailView::image() const { Image *StickersSetThumbnailView::image() const {
return _image.get(); return _image.get();
} }
QByteArray SetThumbnailView::content() const { QByteArray StickersSetThumbnailView::content() const {
return _content; return _content;
} }
Set::Set( StickersSet::StickersSet(
not_null<Data::Session*> owner, not_null<Data::Session*> owner,
uint64 id, uint64 id,
uint64 access, uint64 access,
@ -64,21 +66,21 @@ Set::Set(
, _owner(owner) { , _owner(owner) {
} }
Data::Session &Set::owner() const { Data::Session &StickersSet::owner() const {
return *_owner; return *_owner;
} }
Main::Session &Set::session() const { Main::Session &StickersSet::session() const {
return _owner->session(); return _owner->session();
} }
MTPInputStickerSet Set::mtpInput() const { MTPInputStickerSet StickersSet::mtpInput() const {
return (id && access) return (id && access)
? MTP_inputStickerSetID(MTP_long(id), MTP_long(access)) ? MTP_inputStickerSetID(MTP_long(id), MTP_long(access))
: MTP_inputStickerSetShortName(MTP_string(shortName)); : MTP_inputStickerSetShortName(MTP_string(shortName));
} }
void Set::setThumbnail(const ImageWithLocation &data) { void StickersSet::setThumbnail(const ImageWithLocation &data) {
Data::UpdateCloudFile( Data::UpdateCloudFile(
_thumbnail, _thumbnail,
data, data,
@ -95,19 +97,19 @@ void Set::setThumbnail(const ImageWithLocation &data) {
} }
} }
bool Set::hasThumbnail() const { bool StickersSet::hasThumbnail() const {
return _thumbnail.location.valid(); return _thumbnail.location.valid();
} }
bool Set::thumbnailLoading() const { bool StickersSet::thumbnailLoading() const {
return (_thumbnail.loader != nullptr); return (_thumbnail.loader != nullptr);
} }
bool Set::thumbnailFailed() const { bool StickersSet::thumbnailFailed() const {
return (_thumbnail.flags & Data::CloudFile::Flag::Failed); return (_thumbnail.flags & Data::CloudFile::Flag::Failed);
} }
void Set::loadThumbnail() { void StickersSet::loadThumbnail() {
const auto autoLoading = false; const auto autoLoading = false;
const auto finalCheck = [=] { const auto finalCheck = [=] {
if (const auto active = activeThumbnailView()) { if (const auto active = activeThumbnailView()) {
@ -131,24 +133,24 @@ void Set::loadThumbnail() {
done); done);
} }
const ImageLocation &Set::thumbnailLocation() const { const ImageLocation &StickersSet::thumbnailLocation() const {
return _thumbnail.location; return _thumbnail.location;
} }
int Set::thumbnailByteSize() const { int StickersSet::thumbnailByteSize() const {
return _thumbnail.byteSize; return _thumbnail.byteSize;
} }
std::shared_ptr<SetThumbnailView> Set::createThumbnailView() { std::shared_ptr<StickersSetThumbnailView> StickersSet::createThumbnailView() {
if (auto active = activeThumbnailView()) { if (auto active = activeThumbnailView()) {
return active; return active;
} }
auto view = std::make_shared<SetThumbnailView>(this); auto view = std::make_shared<StickersSetThumbnailView>(this);
_thumbnailView = view; _thumbnailView = view;
return view; return view;
} }
std::shared_ptr<SetThumbnailView> Set::activeThumbnailView() { std::shared_ptr<StickersSetThumbnailView> StickersSet::activeThumbnailView() {
return _thumbnailView.lock(); return _thumbnailView.lock();
} }

View file

@ -11,29 +11,27 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class DocumentData; class DocumentData;
namespace Data {
class Session;
} // namespace Data
namespace Main { namespace Main {
class Session; class Session;
} // namespace Main } // namespace Main
namespace Stickers { namespace Data {
using Order = QList<uint64>; class Session;
using StickersSetsOrder = QList<uint64>;
using SavedGifs = QVector<DocumentData*>; using SavedGifs = QVector<DocumentData*>;
using Pack = QVector<DocumentData*>; using StickersPack = QVector<DocumentData*>;
using ByEmojiMap = QMap<EmojiPtr, Pack>; using StickersByEmojiMap = QMap<EmojiPtr, StickersPack>;
class Set; class StickersSet;
using Sets = base::flat_map<uint64, std::unique_ptr<Set>>; using StickersSets = base::flat_map<uint64, std::unique_ptr<StickersSet>>;
class SetThumbnailView final { class StickersSetThumbnailView final {
public: public:
explicit SetThumbnailView(not_null<Set*> owner); explicit StickersSetThumbnailView(not_null<StickersSet*> owner);
[[nodiscard]] not_null<Set*> owner() const; [[nodiscard]] not_null<StickersSet*> owner() const;
void set(not_null<Main::Session*> session, QByteArray content); void set(not_null<Main::Session*> session, QByteArray content);
@ -41,15 +39,15 @@ public:
[[nodiscard]] QByteArray content() const; [[nodiscard]] QByteArray content() const;
private: private:
const not_null<Set*> _owner; const not_null<StickersSet*> _owner;
std::unique_ptr<Image> _image; std::unique_ptr<Image> _image;
QByteArray _content; QByteArray _content;
}; };
class Set final { class StickersSet final {
public: public:
Set( StickersSet(
not_null<Data::Session*> owner, not_null<Data::Session*> owner,
uint64 id, uint64 id,
uint64 access, uint64 access,
@ -74,8 +72,8 @@ public:
[[nodiscard]] const ImageLocation &thumbnailLocation() const; [[nodiscard]] const ImageLocation &thumbnailLocation() const;
[[nodiscard]] int thumbnailByteSize() const; [[nodiscard]] int thumbnailByteSize() const;
[[nodiscard]] std::shared_ptr<SetThumbnailView> createThumbnailView(); [[nodiscard]] std::shared_ptr<StickersSetThumbnailView> createThumbnailView();
[[nodiscard]] std::shared_ptr<SetThumbnailView> activeThumbnailView(); [[nodiscard]] std::shared_ptr<StickersSetThumbnailView> activeThumbnailView();
uint64 id = 0; uint64 id = 0;
uint64 access = 0; uint64 access = 0;
@ -84,16 +82,16 @@ public:
int32 hash = 0; int32 hash = 0;
MTPDstickerSet::Flags flags; MTPDstickerSet::Flags flags;
TimeId installDate = 0; TimeId installDate = 0;
Pack stickers; StickersPack covers;
StickersPack stickers;
std::vector<TimeId> dates; std::vector<TimeId> dates;
Pack covers; StickersByEmojiMap emoji;
ByEmojiMap emoji;
private: private:
const not_null<Data::Session*> _owner; const not_null<Data::Session*> _owner;
Data::CloudFile _thumbnail; CloudFile _thumbnail;
std::weak_ptr<SetThumbnailView> _thumbnailView; std::weak_ptr<StickersSetThumbnailView> _thumbnailView;
}; };

View file

@ -30,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_histories.h" #include "data/data_histories.h"
#include "data/data_chat_filters.h" #include "data/data_chat_filters.h"
#include "data/data_cloud_file.h" #include "data/data_cloud_file.h"
#include "data/stickers/data_stickers.h"
#include "base/unixtime.h" #include "base/unixtime.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "mainwindow.h" #include "mainwindow.h"
@ -38,7 +39,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h" #include "apiwrap.h"
#include "window/themes/window_theme.h" #include "window/themes/window_theme.h"
#include "observer_peer.h" #include "observer_peer.h"
#include "chat_helpers/stickers.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "window/notifications_manager.h" #include "window/notifications_manager.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"

View file

@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history_item_components.h" #include "history/history_item_components.h"
#include "history/history_inner_widget.h" #include "history/history_inner_widget.h"
#include "dialogs/dialogs_indexed_list.h" #include "dialogs/dialogs_indexed_list.h"
#include "data/stickers/data_stickers.h"
#include "data/data_drafts.h" #include "data/data_drafts.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_media_types.h" #include "data/data_media_types.h"
@ -1056,7 +1057,7 @@ void History::applyMessageChanges(
if (data.type() == mtpc_messageService) { if (data.type() == mtpc_messageService) {
applyServiceChanges(item, data.c_messageService()); applyServiceChanges(item, data.c_messageService());
} }
owner().checkSavedGif(item); owner().stickers().checkSavedGif(item);
} }
void History::applyServiceChanges( void History::applyServiceChanges(

View file

@ -35,7 +35,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/report_box.h" #include "boxes/report_box.h"
#include "boxes/sticker_set_box.h" #include "boxes/sticker_set_box.h"
#include "chat_helpers/message_field.h" #include "chat_helpers/message_field.h"
#include "chat_helpers/stickers.h"
#include "history/history_widget.h" #include "history/history_widget.h"
#include "base/platform/base_platform_info.h" #include "base/platform/base_platform_info.h"
#include "base/unixtime.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_user.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "data/data_histories.h" #include "data/data_histories.h"
#include "data/stickers/data_stickers.h"
#include "facades.h" #include "facades.h"
#include "app.h" #include "app.h"
#include "styles/style_history.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), [=] { _menu->addAction(document->isStickerSetInstalled() ? tr::lng_context_pack_info(tr::now) : tr::lng_context_pack_add(tr::now), [=] {
showStickerPackInfo(document); 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( session().api().toggleFavedSticker(
document, document,
itemId, 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, [=] { _menu->addAction(tr::lng_context_save_image(tr::now), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [=] {

View file

@ -996,11 +996,11 @@ int HistoryWidget::itemTopForHighlight(
} }
void HistoryWidget::start() { void HistoryWidget::start() {
session().data().stickersUpdated( session().data().stickers().updated(
) | rpl::start_with_next([=] { ) | rpl::start_with_next([=] {
updateStickersByEmoji(); updateStickersByEmoji();
}, lifetime()); }, lifetime());
session().data().notifySavedGifsUpdated(); session().data().stickers().notifySavedGifsUpdated();
subscribe(session().api().fullPeerUpdated(), [this](PeerData *peer) { subscribe(session().api().fullPeerUpdated(), [this](PeerData *peer) {
fullPeerUpdated(peer); fullPeerUpdated(peer);
}); });

View file

@ -111,7 +111,7 @@ void ToggleFavedSticker(
document->session().api().toggleFavedSticker( document->session().api().toggleFavedSticker(
document, document,
contextId, contextId,
!Stickers::IsFaved(document)); !document->owner().stickers().isFaved(document));
} }
void AddPhotoActions( void AddPhotoActions(
@ -204,7 +204,7 @@ void AddDocumentActions(
: tr::lng_context_pack_add(tr::now)), : tr::lng_context_pack_add(tr::now)),
[=] { ShowStickerPackInfo(document); }); [=] { ShowStickerPackInfo(document); });
menu->addAction( menu->addAction(
(Stickers::IsFaved(document) (document->owner().stickers().isFaved(document)
? tr::lng_faved_stickers_remove(tr::now) ? tr::lng_faved_stickers_remove(tr::now)
: tr::lng_faved_stickers_add(tr::now)), : tr::lng_faved_stickers_add(tr::now)),
[=] { ToggleFavedSticker(document, contextId); }); [=] { ToggleFavedSticker(document, contextId); });

View file

@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_document_media.h" #include "data/data_document_media.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "lottie/lottie_single_player.h" #include "lottie/lottie_single_player.h"
#include "chat_helpers/stickers_lottie.h"
#include "styles/style_history.h" #include "styles/style_history.h"
namespace HistoryView { namespace HistoryView {
@ -293,10 +294,10 @@ void Sticker::setDiceIndex(const QString &emoji, int index) {
void Sticker::setupLottie() { void Sticker::setupLottie() {
Expects(_dataMedia != nullptr); Expects(_dataMedia != nullptr);
_lottie = Stickers::LottiePlayerFromDocument( _lottie = ChatHelpers::LottiePlayerFromDocument(
_dataMedia.get(), _dataMedia.get(),
_replacements, _replacements,
Stickers::LottieSize::MessageHistory, ChatHelpers::StickerLottieSize::MessageHistory,
_size * cIntRetinaFactor(), _size * cIntRetinaFactor(),
Lottie::Quality::High); Lottie::Quality::High);
lottieCreated(); lottieCreated();

View file

@ -13,10 +13,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "data/data_photo_media.h" #include "data/data_photo_media.h"
#include "data/data_document_media.h" #include "data/data_document_media.h"
#include "styles/style_overview.h" #include "data/stickers/data_stickers.h"
#include "styles/style_history.h" #include "chat_helpers/stickers_lottie.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_widgets.h"
#include "inline_bots/inline_bot_result.h" #include "inline_bots/inline_bot_result.h"
#include "lottie/lottie_single_player.h" #include "lottie/lottie_single_player.h"
#include "media/audio/media_audio.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/history_location_manager.h"
#include "history/view/history_view_cursor_state.h" #include "history/view/history_view_cursor_state.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "chat_helpers/stickers.h"
#include "ui/image/image.h" #include "ui/image/image.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "apiwrap.h" #include "apiwrap.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "app.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 InlineBots {
namespace Layout { namespace Layout {
@ -127,12 +128,12 @@ void Gif::setPosition(int32 position) {
void DeleteSavedGifClickHandler::onClickImpl() const { void DeleteSavedGifClickHandler::onClickImpl() const {
Auth().api().toggleSavedGif(_data, Data::FileOriginSavedGifs(), false); 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) { if (index >= 0) {
Auth().data().savedGifsRef().remove(index); Auth().data().stickers().savedGifsRef().remove(index);
Local::writeSavedGifs(); Local::writeSavedGifs();
} }
Auth().data().notifySavedGifsUpdated(); Auth().data().stickers().notifySavedGifsUpdated();
} }
int Gif::resizeGetHeight(int width) { int Gif::resizeGetHeight(int width) {
@ -523,9 +524,9 @@ QSize Sticker::getThumbSize() const {
void Sticker::setupLottie() const { void Sticker::setupLottie() const {
Expects(_dataMedia != nullptr); Expects(_dataMedia != nullptr);
_lottie = Stickers::LottiePlayerFromDocument( _lottie = ChatHelpers::LottiePlayerFromDocument(
_dataMedia.get(), _dataMedia.get(),
Stickers::LottieSize::InlineResults, ChatHelpers::StickerLottieSize::InlineResults,
QSize( QSize(
st::stickerPanSize.width() - st::buttonRadius * 2, st::stickerPanSize.width() - st::buttonRadius * 2,
st::stickerPanSize.height() - st::buttonRadius * 2 st::stickerPanSize.height() - st::buttonRadius * 2

View file

@ -27,6 +27,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_scheduled_messages.h" #include "data/data_scheduled_messages.h"
#include "data/data_file_origin.h" #include "data/data_file_origin.h"
#include "data/data_histories.h" #include "data/data_histories.h"
#include "data/stickers/data_stickers.h"
#include "api/api_text_entities.h" #include "api/api_text_entities.h"
#include "ui/special_buttons.h" #include "ui/special_buttons.h"
#include "ui/widgets/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 "window/window_connecting_widget.h"
#include "chat_helpers/tabbed_selector.h" // TabbedSelector::refreshStickers #include "chat_helpers/tabbed_selector.h" // TabbedSelector::refreshStickers
#include "chat_helpers/message_field.h" #include "chat_helpers/message_field.h"
#include "chat_helpers/stickers.h"
#include "info/info_memento.h" #include "info/info_memento.h"
#include "info/info_controller.h" #include "info/info_controller.h"
#include "observer_peer.h" #include "observer_peer.h"
@ -3212,8 +3212,8 @@ void MainWidget::start() {
if (const auto availableAt = Local::ReadExportSettings().availableAt) { if (const auto availableAt = Local::ReadExportSettings().availableAt) {
session().data().suggestStartExport(availableAt); session().data().suggestStartExport(availableAt);
} }
session().data().notifyStickersUpdated(); session().data().stickers().notifyUpdated();
session().data().notifySavedGifsUpdated(); session().data().stickers().notifySavedGifsUpdated();
_history->start(); _history->start();
@ -3362,15 +3362,15 @@ void MainWidget::incrementSticker(DocumentData *sticker) {
} }
bool writeRecentStickers = false; bool writeRecentStickers = false;
auto &sets = session().data().stickerSetsRef(); auto &sets = session().data().stickers().setsRef();
auto it = sets.find(Stickers::CloudRecentSetId); auto it = sets.find(Data::Stickers::CloudRecentSetId);
if (it == sets.cend()) { if (it == sets.cend()) {
if (it == sets.cend()) { if (it == sets.cend()) {
it = sets.emplace( it = sets.emplace(
Stickers::CloudRecentSetId, Data::Stickers::CloudRecentSetId,
std::make_unique<Stickers::Set>( std::make_unique<Data::StickersSet>(
&session().data(), &session().data(),
Stickers::CloudRecentSetId, Data::Stickers::CloudRecentSetId,
uint64(0), uint64(0),
tr::lng_recent_stickers(tr::now), tr::lng_recent_stickers(tr::now),
QString(), QString(),
@ -3410,7 +3410,7 @@ void MainWidget::incrementSticker(DocumentData *sticker) {
set->dates.insert(set->dates.begin(), base::unixtime::now()); set->dates.insert(set->dates.begin(), base::unixtime::now());
} }
set->stickers.push_front(sticker); 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) { for (const auto emoji : *emojiList) {
set->emoji[emoji].push_front(sticker); 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. // Remove that sticker from old recent, now it is in cloud recent stickers.
bool writeOldRecent = false; bool writeOldRecent = false;
auto &recent = Stickers::GetRecentPack(); auto &recent = session().data().stickers().getRecentPack();
for (auto i = recent.begin(), e = recent.end(); i != e; ++i) { for (auto i = recent.begin(), e = recent.end(); i != e; ++i) {
if (i->first == sticker) { if (i->first == sticker) {
writeOldRecent = true; writeOldRecent = true;
@ -3446,7 +3446,7 @@ void MainWidget::incrementSticker(DocumentData *sticker) {
// Remove that sticker from custom stickers, now it is in cloud recent stickers. // Remove that sticker from custom stickers, now it is in cloud recent stickers.
bool writeInstalledStickers = false; bool writeInstalledStickers = false;
auto customIt = sets.find(Stickers::CustomSetId); auto customIt = sets.find(Data::Stickers::CustomSetId);
if (customIt != sets.cend()) { if (customIt != sets.cend()) {
const auto custom = customIt->second.get(); const auto custom = customIt->second.get();
int removeIndex = custom->stickers.indexOf(sticker); int removeIndex = custom->stickers.indexOf(sticker);
@ -3469,8 +3469,9 @@ void MainWidget::incrementSticker(DocumentData *sticker) {
} }
void MainWidget::activate() { void MainWidget::activate() {
if (_a_show.animating()) return; if (_a_show.animating()) {
if (!_mainSection) { return;
} else if (!_mainSection) {
if (_hider) { if (_hider) {
_dialogs->setInnerFocus(); _dialogs->setInnerFocus();
} else if (App::wnd() && !Ui::isLayerShown()) { } else if (App::wnd() && !Ui::isLayerShown()) {
@ -3479,7 +3480,9 @@ void MainWidget::activate() {
const auto path = cSendPaths()[0]; const auto path = cSendPaths()[0];
if (path.startsWith(interpret)) { if (path.startsWith(interpret)) {
cSetSendPaths(QStringList()); cSetSendPaths(QStringList());
const auto error = Support::InterpretSendPath(path.mid(interpret.size())); const auto error = Support::InterpretSendPath(
_controller,
path.mid(interpret.size()));
if (!error.isEmpty()) { if (!error.isEmpty()) {
Ui::show(Box<InformBox>(error)); Ui::show(Box<InformBox>(error));
} }
@ -4519,45 +4522,45 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
////// Cloud sticker sets ////// Cloud sticker sets
case mtpc_updateNewStickerSet: { case mtpc_updateNewStickerSet: {
const auto &d = update.c_updateNewStickerSet(); const auto &d = update.c_updateNewStickerSet();
Stickers::NewSetReceived(d.vstickerset()); session().data().stickers().newSetReceived(d.vstickerset());
} break; } break;
case mtpc_updateStickerSetsOrder: { case mtpc_updateStickerSetsOrder: {
auto &d = update.c_updateStickerSetsOrder(); auto &d = update.c_updateStickerSetsOrder();
if (!d.is_masks()) { if (!d.is_masks()) {
const auto &order = d.vorder().v; const auto &order = d.vorder().v;
const auto &sets = session().data().stickerSets(); const auto &sets = session().data().stickers().sets();
Stickers::Order result; Data::StickersSetsOrder result;
for (const auto &item : order) { for (const auto &item : order) {
if (sets.find(item.v) == sets.cend()) { if (sets.find(item.v) == sets.cend()) {
break; break;
} }
result.push_back(item.v); result.push_back(item.v);
} }
if (result.size() != session().data().stickerSetsOrder().size() if (result.size() != session().data().stickers().setsOrder().size()
|| result.size() != order.size()) { || result.size() != order.size()) {
session().data().setLastStickersUpdate(0); session().data().stickers().setLastUpdate(0);
session().api().updateStickers(); session().api().updateStickers();
} else { } else {
session().data().stickerSetsOrderRef() = std::move(result); session().data().stickers().setsOrderRef() = std::move(result);
Local::writeInstalledStickers(); Local::writeInstalledStickers();
session().data().notifyStickersUpdated(); session().data().stickers().notifyUpdated();
} }
} }
} break; } break;
case mtpc_updateStickerSets: { case mtpc_updateStickerSets: {
session().data().setLastStickersUpdate(0); session().data().stickers().setLastUpdate(0);
session().api().updateStickers(); session().api().updateStickers();
} break; } break;
case mtpc_updateRecentStickers: { case mtpc_updateRecentStickers: {
session().data().setLastRecentStickersUpdate(0); session().data().stickers().setLastRecentUpdate(0);
session().api().updateStickers(); session().api().updateStickers();
} break; } break;
case mtpc_updateFavedStickers: { case mtpc_updateFavedStickers: {
session().data().setLastFavedStickersUpdate(0); session().data().stickers().setLastFavedUpdate(0);
session().api().updateStickers(); session().api().updateStickers();
} break; } break;
@ -4565,13 +4568,13 @@ void MainWidget::feedUpdate(const MTPUpdate &update) {
// We read some of the featured stickers, perhaps not all of them. // 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 // Here we don't know what featured sticker sets were read, so we
// request all of them once again. // request all of them once again.
session().data().setLastFeaturedStickersUpdate(0); session().data().stickers().setLastFeaturedUpdate(0);
session().api().updateStickers(); session().api().updateStickers();
} break; } break;
////// Cloud saved GIFs ////// Cloud saved GIFs
case mtpc_updateSavedGifs: { case mtpc_updateSavedGifs: {
session().data().setLastSavedGifsUpdate(0); session().data().stickers().setLastSavedGifsUpdate(0);
session().api().updateStickers(); session().api().updateStickers();
} break; } break;

View file

@ -23,6 +23,7 @@
#include "data/data_peer_values.h" #include "data/data_peer_values.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_cloud_file.h" #include "data/data_cloud_file.h"
#include "data/stickers/data_stickers.h"
#include "dialogs/dialogs_layout.h" #include "dialogs/dialogs_layout.h"
#include "ui/emoji_config.h" #include "ui/emoji_config.h"
#include "history/history.h" #include "history/history.h"
@ -31,7 +32,6 @@
#include "mainwindow.h" #include "mainwindow.h"
#include "observer_peer.h" #include "observer_peer.h"
#include "base/platform/mac/base_utilities_mac.h" #include "base/platform/mac/base_utilities_mac.h"
#include "chat_helpers/stickers.h"
#include "styles/style_dialogs.h" #include "styles/style_dialogs.h"
#include "styles/style_media_player.h" #include "styles/style_media_player.h"
#include "styles/style_settings.h" #include "styles/style_settings.h"
@ -220,8 +220,8 @@ inline std::optional<QString> RestrictionToSendStickers() {
} }
QString TitleRecentlyUsed() { QString TitleRecentlyUsed() {
const auto &sets = Auth().data().stickerSets(); const auto &sets = Auth().data().stickers().sets();
const auto it = sets.find(Stickers::CloudRecentSetId); const auto it = sets.find(Data::Stickers::CloudRecentSetId);
if (it != sets.cend()) { if (it != sets.cend()) {
return it->second->title; return it->second->title;
} }
@ -351,8 +351,8 @@ void AppendStickerSet(std::vector<PickerScrubberItem> &to, uint64 setId) {
} }
void AppendRecentStickers(std::vector<PickerScrubberItem> &to) { void AppendRecentStickers(std::vector<PickerScrubberItem> &to) {
const auto &sets = Auth().data().stickerSets(); const auto &sets = Auth().data().stickers().sets();
const auto cloudIt = sets.find(Stickers::CloudRecentSetId); const auto cloudIt = sets.find(Data::Stickers::CloudRecentSetId);
const auto cloudCount = (cloudIt != sets.cend()) const auto cloudCount = (cloudIt != sets.cend())
? cloudIt->second->stickers.size() ? cloudIt->second->stickers.size()
: 0; : 0;
@ -360,20 +360,20 @@ void AppendRecentStickers(std::vector<PickerScrubberItem> &to) {
to.emplace_back(PickerScrubberItem(cloudIt->second->title)); to.emplace_back(PickerScrubberItem(cloudIt->second->title));
auto count = 0; auto count = 0;
for (const auto document : cloudIt->second->stickers) { for (const auto document : cloudIt->second->stickers) {
if (Stickers::IsFaved(document)) { if (document->owner().stickers().isFaved(document)) {
continue; continue;
} }
to.emplace_back(PickerScrubberItem(document)); 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)); to.emplace_back(PickerScrubberItem(recent.first));
} }
} }
void AppendFavedStickers(std::vector<PickerScrubberItem> &to) { void AppendFavedStickers(std::vector<PickerScrubberItem> &to) {
const auto &sets = Auth().data().stickerSets(); const auto &sets = Auth().data().stickers().sets();
const auto it = sets.find(Stickers::FavedSetId); const auto it = sets.find(Data::Stickers::FavedSetId);
const auto count = (it != sets.cend()) const auto count = (it != sets.cend())
? it->second->stickers.size() ? it->second->stickers.size()
: 0; : 0;

View file

@ -11,11 +11,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/serialize_common.h" #include "storage/serialize_common.h"
#include "storage/storage_encrypted_file.h" #include "storage/storage_encrypted_file.h"
#include "storage/storage_clear_legacy.h" #include "storage/storage_clear_legacy.h"
#include "chat_helpers/stickers.h"
#include "data/data_drafts.h" #include "data/data_drafts.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_document_media.h" #include "data/data_document_media.h"
#include "data/stickers/data_stickers.h"
#include "boxes/send_files_box.h" #include "boxes/send_files_box.h"
#include "base/flags.h" #include "base/flags.h"
#include "base/platform/base_platform_file_utilities.h" #include "base/platform/base_platform_file_utilities.h"
@ -2182,6 +2182,14 @@ void _writeUserSettings() {
: QByteArray(); : QByteArray();
auto callSettings = serializeCallSettings(); 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)); uint32 size = 24 * (sizeof(quint32) + sizeof(qint32));
size += sizeof(quint32) + Serialize::stringSize(Global::AskDownloadPath() ? QString() : Global::DownloadPath()) + Serialize::bytearraySize(Global::AskDownloadPath() ? QByteArray() : Global::DownloadPathBookmark()); 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) + 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) + Serialize::stringSize(cDialogLastPath());
size += sizeof(quint32) + 3 * sizeof(qint32); size += sizeof(quint32) + 3 * sizeof(qint32);
size += sizeof(quint32) + 2 * sizeof(qint32); size += sizeof(quint32) + 2 * sizeof(qint32);
@ -2233,21 +2241,9 @@ void _writeUserSettings() {
data.stream << quint32(dbiSessionSettings) << userData; data.stream << quint32(dbiSessionSettings) << userData;
} }
data.stream << quint32(dbiPlaybackSpeed) << qint32(Global::VoiceMsgPlaybackDoubled() ? 2 : 1); data.stream << quint32(dbiPlaybackSpeed) << qint32(Global::VoiceMsgPlaybackDoubled() ? 2 : 1);
data.stream << quint32(dbiRecentEmoji) << recentEmojiPreloadData;
{
data.stream << quint32(dbiRecentEmoji) << recentEmojiPreloadData;
}
data.stream << quint32(dbiEmojiVariants) << cEmojiVariants(); data.stream << quint32(dbiEmojiVariants) << cEmojiVariants();
{ data.stream << quint32(dbiRecentStickers) << recentStickers;
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;
}
if (!Global::HiddenPinnedMessages().isEmpty()) { if (!Global::HiddenPinnedMessages().isEmpty()) {
data.stream << quint32(dbiHiddenPinnedMessages) << Global::HiddenPinnedMessages(); 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) { const auto writeInfo = [&](int count) {
stream stream
<< quint64(set.id) << quint64(set.id)
@ -3475,12 +3471,15 @@ enum class StickerSetCheckResult {
Abort, Abort,
}; };
// CheckSet is a functor on Stickers::Set, which returns a StickerSetCheckResult. // CheckSet is a functor on Data::StickersSet, which returns a StickerSetCheckResult.
template <typename CheckSet> template <typename CheckSet>
void _writeStickerSets(FileKey &stickersKey, CheckSet checkSet, const Stickers::Order &order) { void _writeStickerSets(
FileKey &stickersKey,
CheckSet checkSet,
const Data::StickersSetsOrder &order) {
if (!_working()) return; if (!_working()) return;
const auto &sets = Auth().data().stickerSets(); const auto &sets = Auth().data().stickers().sets();
if (sets.empty()) { if (sets.empty()) {
if (stickersKey) { if (stickersKey) {
ClearKey(stickersKey); ClearKey(stickersKey);
@ -3567,7 +3566,10 @@ void _writeStickerSets(FileKey &stickersKey, CheckSet checkSet, const Stickers::
file.writeEncrypted(data); 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; FileReadDescriptor stickers;
if (!ReadEncryptedFile(stickers, stickersKey)) { if (!ReadEncryptedFile(stickers, stickersKey)) {
ClearKey(stickersKey); ClearKey(stickersKey);
@ -3581,7 +3583,7 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr,
stickersKey = 0; stickersKey = 0;
}; };
auto &sets = Auth().data().stickerSetsRef(); auto &sets = Auth().data().stickers().setsRef();
if (outOrder) outOrder->clear(); if (outOrder) outOrder->clear();
quint32 versionTag = 0; quint32 versionTag = 0;
@ -3635,16 +3637,16 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr,
} }
setFlags = MTPDstickerSet::Flags::from_raw(setFlagsValue); setFlags = MTPDstickerSet::Flags::from_raw(setFlagsValue);
if (setId == Stickers::DefaultSetId) { if (setId == Data::Stickers::DefaultSetId) {
setTitle = tr::lng_stickers_default_set(tr::now); setTitle = tr::lng_stickers_default_set(tr::now);
setFlags |= MTPDstickerSet::Flag::f_official | MTPDstickerSet_ClientFlag::f_special; setFlags |= MTPDstickerSet::Flag::f_official | MTPDstickerSet_ClientFlag::f_special;
} else if (setId == Stickers::CustomSetId) { } else if (setId == Data::Stickers::CustomSetId) {
setTitle = qsl("Custom stickers"); setTitle = qsl("Custom stickers");
setFlags |= MTPDstickerSet_ClientFlag::f_special; setFlags |= MTPDstickerSet_ClientFlag::f_special;
} else if (setId == Stickers::CloudRecentSetId) { } else if (setId == Data::Stickers::CloudRecentSetId) {
setTitle = tr::lng_recent_stickers(tr::now); setTitle = tr::lng_recent_stickers(tr::now);
setFlags |= MTPDstickerSet_ClientFlag::f_special; setFlags |= MTPDstickerSet_ClientFlag::f_special;
} else if (setId == Stickers::FavedSetId) { } else if (setId == Data::Stickers::FavedSetId) {
setTitle = Lang::Hard::FavedSetTitle(); setTitle = Lang::Hard::FavedSetTitle();
setFlags |= MTPDstickerSet_ClientFlag::f_special; setFlags |= MTPDstickerSet_ClientFlag::f_special;
} else if (!setId) { } else if (!setId) {
@ -3655,7 +3657,7 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr,
if (it == sets.cend()) { if (it == sets.cend()) {
// We will set this flags from order lists when reading those stickers. // We will set this flags from order lists when reading those stickers.
setFlags &= ~(MTPDstickerSet::Flag::f_installed_date | MTPDstickerSet_ClientFlag::f_featured); setFlags &= ~(MTPDstickerSet::Flag::f_installed_date | MTPDstickerSet_ClientFlag::f_featured);
it = sets.emplace(setId, std::make_unique<Stickers::Set>( it = sets.emplace(setId, std::make_unique<Data::StickersSet>(
&Auth().data(), &Auth().data(),
setId, setId,
setAccess, setAccess,
@ -3713,7 +3715,7 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr,
if (datesCount != scnt) { if (datesCount != scnt) {
return failed(); return failed();
} }
const auto fillDates = (set->id == Stickers::CloudRecentSetId) const auto fillDates = (set->id == Data::Stickers::CloudRecentSetId)
&& (set->stickers.size() == datesCount); && (set->stickers.size() == datesCount);
if (fillDates) { if (fillDates) {
set->dates.clear(); set->dates.clear();
@ -3737,7 +3739,7 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr,
QString emojiString; QString emojiString;
qint32 stickersCount; qint32 stickersCount;
stickers.stream >> emojiString >> stickersCount; stickers.stream >> emojiString >> stickersCount;
Stickers::Pack pack; Data::StickersPack pack;
pack.reserve(stickersCount); pack.reserve(stickersCount);
for (int32 k = 0; k < stickersCount; ++k) { for (int32 k = 0; k < stickersCount; ++k) {
quint64 id; quint64 id;
@ -3797,8 +3799,8 @@ void _readStickerSets(FileKey &stickersKey, Stickers::Order *outOrder = nullptr,
void writeInstalledStickers() { void writeInstalledStickers() {
if (!Global::started()) return; if (!Global::started()) return;
_writeStickerSets(_installedStickersKey, [](const Stickers::Set &set) { _writeStickerSets(_installedStickersKey, [](const Data::StickersSet &set) {
if (set.id == Stickers::CloudRecentSetId || set.id == Stickers::FavedSetId) { // separate files for them if (set.id == Data::Stickers::CloudRecentSetId || set.id == Data::Stickers::FavedSetId) { // separate files for them
return StickerSetCheckResult::Skip; return StickerSetCheckResult::Skip;
} else if (set.flags & MTPDstickerSet_ClientFlag::f_special) { } else if (set.flags & MTPDstickerSet_ClientFlag::f_special) {
if (set.stickers.isEmpty()) { // all other special are "installed" if (set.stickers.isEmpty()) { // all other special are "installed"
@ -3812,14 +3814,15 @@ void writeInstalledStickers() {
return StickerSetCheckResult::Skip; return StickerSetCheckResult::Skip;
} }
return StickerSetCheckResult::Write; return StickerSetCheckResult::Write;
}, Auth().data().stickerSetsOrder()); }, Auth().data().stickers().setsOrder());
} }
void writeFeaturedStickers() { void writeFeaturedStickers() {
if (!Global::started()) return; if (!Global::started()) return;
_writeStickerSets(_featuredStickersKey, [](const Stickers::Set &set) { _writeStickerSets(_featuredStickersKey, [](const Data::StickersSet &set) {
if (set.id == Stickers::CloudRecentSetId || set.id == Stickers::FavedSetId) { // separate files for them if (set.id == Data::Stickers::CloudRecentSetId
|| set.id == Data::Stickers::FavedSetId) { // separate files for them
return StickerSetCheckResult::Skip; return StickerSetCheckResult::Skip;
} else if (set.flags & MTPDstickerSet_ClientFlag::f_special) { } else if (set.flags & MTPDstickerSet_ClientFlag::f_special) {
return StickerSetCheckResult::Skip; return StickerSetCheckResult::Skip;
@ -3831,40 +3834,40 @@ void writeFeaturedStickers() {
return StickerSetCheckResult::Skip; return StickerSetCheckResult::Skip;
} }
return StickerSetCheckResult::Write; return StickerSetCheckResult::Write;
}, Auth().data().featuredStickerSetsOrder()); }, Auth().data().stickers().featuredSetsOrder());
} }
void writeRecentStickers() { void writeRecentStickers() {
if (!Global::started()) return; if (!Global::started()) return;
_writeStickerSets(_recentStickersKey, [](const Stickers::Set &set) { _writeStickerSets(_recentStickersKey, [](const Data::StickersSet &set) {
if (set.id != Stickers::CloudRecentSetId || set.stickers.isEmpty()) { if (set.id != Data::Stickers::CloudRecentSetId || set.stickers.isEmpty()) {
return StickerSetCheckResult::Skip; return StickerSetCheckResult::Skip;
} }
return StickerSetCheckResult::Write; return StickerSetCheckResult::Write;
}, Stickers::Order()); }, Data::StickersSetsOrder());
} }
void writeFavedStickers() { void writeFavedStickers() {
if (!Global::started()) return; if (!Global::started()) return;
_writeStickerSets(_favedStickersKey, [](const Stickers::Set &set) { _writeStickerSets(_favedStickersKey, [](const Data::StickersSet &set) {
if (set.id != Stickers::FavedSetId || set.stickers.isEmpty()) { if (set.id != Data::Stickers::FavedSetId || set.stickers.isEmpty()) {
return StickerSetCheckResult::Skip; return StickerSetCheckResult::Skip;
} }
return StickerSetCheckResult::Write; return StickerSetCheckResult::Write;
}, Stickers::Order()); }, Data::StickersSetsOrder());
} }
void writeArchivedStickers() { void writeArchivedStickers() {
if (!Global::started()) return; 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()) { if (!(set.flags & MTPDstickerSet::Flag::f_archived) || set.stickers.isEmpty()) {
return StickerSetCheckResult::Skip; return StickerSetCheckResult::Skip;
} }
return StickerSetCheckResult::Write; return StickerSetCheckResult::Write;
}, Auth().data().archivedStickerSetsOrder()); }, Auth().data().stickers().archivedSetsOrder());
} }
void importOldRecentStickers() { void importOldRecentStickers() {
@ -3878,20 +3881,20 @@ void importOldRecentStickers() {
return; return;
} }
auto &sets = Auth().data().stickerSetsRef(); auto &sets = Auth().data().stickers().setsRef();
sets.clear(); sets.clear();
auto &order = Auth().data().stickerSetsOrderRef(); auto &order = Auth().data().stickers().setsOrderRef();
order.clear(); order.clear();
auto &recent = cRefRecentStickers(); auto &recent = cRefRecentStickers();
recent.clear(); recent.clear();
const auto def = sets.emplace( const auto def = sets.emplace(
Stickers::DefaultSetId, Data::Stickers::DefaultSetId,
std::make_unique<Stickers::Set>( std::make_unique<Data::StickersSet>(
&Auth().data(), &Auth().data(),
Stickers::DefaultSetId, Data::Stickers::DefaultSetId,
uint64(0), uint64(0),
tr::lng_stickers_default_set(tr::now), tr::lng_stickers_default_set(tr::now),
QString(), QString(),
@ -3902,10 +3905,10 @@ void importOldRecentStickers() {
| MTPDstickerSet_ClientFlag::f_special), | MTPDstickerSet_ClientFlag::f_special),
kDefaultStickerInstallDate)).first->second.get(); kDefaultStickerInstallDate)).first->second.get();
const auto custom = sets.emplace( const auto custom = sets.emplace(
Stickers::CustomSetId, Data::Stickers::CustomSetId,
std::make_unique<Stickers::Set>( std::make_unique<Data::StickersSet>(
&Auth().data(), &Auth().data(),
Stickers::CustomSetId, Data::Stickers::CustomSetId,
uint64(0), uint64(0),
qsl("Custom stickers"), qsl("Custom stickers"),
QString(), QString(),
@ -3967,12 +3970,12 @@ void importOldRecentStickers() {
} }
} }
if (def->stickers.isEmpty()) { if (def->stickers.isEmpty()) {
sets.remove(Stickers::DefaultSetId); sets.remove(Data::Stickers::DefaultSetId);
} else { } else {
order.push_front(Stickers::DefaultSetId); order.push_front(Data::Stickers::DefaultSetId);
} }
if (custom->stickers.isEmpty()) { if (custom->stickers.isEmpty()) {
sets.remove(Stickers::CustomSetId); sets.remove(Data::Stickers::CustomSetId);
} }
writeInstalledStickers(); writeInstalledStickers();
@ -3988,21 +3991,21 @@ void readInstalledStickers() {
return importOldRecentStickers(); return importOldRecentStickers();
} }
Auth().data().stickerSetsRef().clear(); Auth().data().stickers().setsRef().clear();
_readStickerSets( _readStickerSets(
_installedStickersKey, _installedStickersKey,
&Auth().data().stickerSetsOrderRef(), &Auth().data().stickers().setsOrderRef(),
MTPDstickerSet::Flag::f_installed_date); MTPDstickerSet::Flag::f_installed_date);
} }
void readFeaturedStickers() { void readFeaturedStickers() {
_readStickerSets( _readStickerSets(
_featuredStickersKey, _featuredStickersKey,
&Auth().data().featuredStickerSetsOrderRef(), &Auth().data().stickers().featuredSetsOrderRef(),
MTPDstickerSet::Flags() | MTPDstickerSet_ClientFlag::f_featured); MTPDstickerSet::Flags() | MTPDstickerSet_ClientFlag::f_featured);
const auto &sets = Auth().data().stickerSets(); const auto &sets = Auth().data().stickers().sets();
const auto &order = Auth().data().featuredStickerSetsOrder(); const auto &order = Auth().data().stickers().featuredSetsOrder();
int unreadCount = 0; int unreadCount = 0;
for (const auto setId : order) { for (const auto setId : order) {
auto it = sets.find(setId); auto it = sets.find(setId);
@ -4011,7 +4014,7 @@ void readFeaturedStickers() {
++unreadCount; ++unreadCount;
} }
} }
Auth().data().setFeaturedStickerSetsUnreadCount(unreadCount); Auth().data().stickers().setFeaturedSetsUnreadCount(unreadCount);
} }
void readRecentStickers() { void readRecentStickers() {
@ -4025,7 +4028,7 @@ void readFavedStickers() {
void readArchivedStickers() { void readArchivedStickers() {
static bool archivedStickersRead = false; static bool archivedStickersRead = false;
if (!archivedStickersRead) { if (!archivedStickersRead) {
_readStickerSets(_archivedStickersKey, &Auth().data().archivedStickerSetsOrderRef()); _readStickerSets(_archivedStickersKey, &Auth().data().stickers().archivedSetsOrderRef());
archivedStickersRead = true; archivedStickersRead = true;
} }
} }
@ -4039,7 +4042,7 @@ int32 countDocumentVectorHash(const QVector<DocumentData*> vector) {
} }
int32 countSpecialStickerSetHash(uint64 setId) { int32 countSpecialStickerSetHash(uint64 setId) {
const auto &sets = Auth().data().stickerSets(); const auto &sets = Auth().data().stickers().sets();
const auto it = sets.find(setId); const auto it = sets.find(setId);
if (it != sets.cend()) { if (it != sets.cend()) {
return countDocumentVectorHash(it->second->stickers); return countDocumentVectorHash(it->second->stickers);
@ -4050,13 +4053,13 @@ int32 countSpecialStickerSetHash(uint64 setId) {
int32 countStickersHash(bool checkOutdatedInfo) { int32 countStickersHash(bool checkOutdatedInfo) {
auto result = Api::HashInit(); auto result = Api::HashInit();
bool foundOutdated = false; bool foundOutdated = false;
const auto &sets = Auth().data().stickerSets(); const auto &sets = Auth().data().stickers().sets();
const auto &order = Auth().data().stickerSetsOrder(); const auto &order = Auth().data().stickers().setsOrder();
for (auto i = order.cbegin(), e = order.cend(); i != e; ++i) { for (auto i = order.cbegin(), e = order.cend(); i != e; ++i) {
auto it = sets.find(*i); auto it = sets.find(*i);
if (it != sets.cend()) { if (it != sets.cend()) {
const auto set = it->second.get(); const auto set = it->second.get();
if (set->id == Stickers::DefaultSetId) { if (set->id == Data::Stickers::DefaultSetId) {
foundOutdated = true; foundOutdated = true;
} else if (!(set->flags & MTPDstickerSet_ClientFlag::f_special) } else if (!(set->flags & MTPDstickerSet_ClientFlag::f_special)
&& !(set->flags & MTPDstickerSet::Flag::f_archived)) { && !(set->flags & MTPDstickerSet::Flag::f_archived)) {
@ -4070,17 +4073,17 @@ int32 countStickersHash(bool checkOutdatedInfo) {
} }
int32 countRecentStickersHash() { int32 countRecentStickersHash() {
return countSpecialStickerSetHash(Stickers::CloudRecentSetId); return countSpecialStickerSetHash(Data::Stickers::CloudRecentSetId);
} }
int32 countFavedStickersHash() { int32 countFavedStickersHash() {
return countSpecialStickerSetHash(Stickers::FavedSetId); return countSpecialStickerSetHash(Data::Stickers::FavedSetId);
} }
int32 countFeaturedStickersHash() { int32 countFeaturedStickersHash() {
auto result = Api::HashInit(); auto result = Api::HashInit();
const auto &sets = Auth().data().stickerSets(); const auto &sets = Auth().data().stickers().sets();
const auto &featured = Auth().data().featuredStickerSetsOrder(); const auto &featured = Auth().data().stickers().featuredSetsOrder();
for (const auto setId : featured) { for (const auto setId : featured) {
Api::HashUpdate(result, setId); Api::HashUpdate(result, setId);
@ -4094,13 +4097,13 @@ int32 countFeaturedStickersHash() {
} }
int32 countSavedGifsHash() { int32 countSavedGifsHash() {
return countDocumentVectorHash(Auth().data().savedGifs()); return countDocumentVectorHash(Auth().data().stickers().savedGifs());
} }
void writeSavedGifs() { void writeSavedGifs() {
if (!_working()) return; if (!_working()) return;
auto &saved = Auth().data().savedGifs(); auto &saved = Auth().data().stickers().savedGifs();
if (saved.isEmpty()) { if (saved.isEmpty()) {
if (_savedGifsKey) { if (_savedGifsKey) {
ClearKey(_savedGifsKey); ClearKey(_savedGifsKey);
@ -4140,7 +4143,7 @@ void readSavedGifs() {
return; return;
} }
auto &saved = Auth().data().savedGifsRef(); auto &saved = Auth().data().stickers().savedGifsRef();
const auto failed = [&] { const auto failed = [&] {
ClearKey(_savedGifsKey); ClearKey(_savedGifsKey);
_savedGifsKey = 0; _savedGifsKey = 0;

View file

@ -8,8 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/serialize_document.h" #include "storage/serialize_document.h"
#include "storage/serialize_common.h" #include "storage/serialize_common.h"
#include "chat_helpers/stickers.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/stickers/data_stickers.h"
#include "ui/image/image.h" #include "ui/image/image.h"
#include "main/main_session.h" #include "main/main_session.h"
@ -91,10 +91,10 @@ DocumentData *Document::readFromStreamHelper(int streamAppVersion, QDataStream &
if (typeOfSet == StickerSetTypeEmpty) { if (typeOfSet == StickerSetTypeEmpty) {
attributes.push_back(MTP_documentAttributeSticker(MTP_flags(0), MTP_string(alt), MTP_inputStickerSetEmpty(), MTPMaskCoords())); attributes.push_back(MTP_documentAttributeSticker(MTP_flags(0), MTP_string(alt), MTP_inputStickerSetEmpty(), MTPMaskCoords()));
} else if (info) { } else if (info) {
if (info->setId == Stickers::DefaultSetId if (info->setId == Data::Stickers::DefaultSetId
|| info->setId == Stickers::CloudRecentSetId || info->setId == Data::Stickers::CloudRecentSetId
|| info->setId == Stickers::FavedSetId || info->setId == Data::Stickers::FavedSetId
|| info->setId == Stickers::CustomSetId) { || info->setId == Data::Stickers::CustomSetId) {
typeOfSet = StickerSetTypeEmpty; typeOfSet = StickerSetTypeEmpty;
} }

View file

@ -571,7 +571,9 @@ QString ChatOccupiedString(not_null<History*> history) {
: hand + ' ' + name + " is here"; : hand + ' ' + name + " is here";
} }
QString InterpretSendPath(const QString &path) { QString InterpretSendPath(
not_null<Window::SessionController*> window,
const QString &path) {
QFile f(path); QFile f(path);
if (!f.open(QIODevice::ReadOnly)) { if (!f.open(QIODevice::ReadOnly)) {
return "App Error: Could not open interpret file: " + path; return "App Error: Could not open interpret file: " + path;
@ -584,7 +586,7 @@ QString InterpretSendPath(const QString &path) {
auto caption = QString(); auto caption = QString();
for (const auto &line : lines) { for (const auto &line : lines) {
if (line.startsWith(qstr("from: "))) { 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."; return "App Error: Wrong current user.";
} }
} else if (line.startsWith(qstr("channel: "))) { } else if (line.startsWith(qstr("channel: "))) {
@ -604,7 +606,7 @@ QString InterpretSendPath(const QString &path) {
return "App Error: Invalid command: " + line; return "App Error: Invalid command: " + line;
} }
} }
const auto history = Auth().data().historyLoaded(toId); const auto history = window->session().data().historyLoaded(toId);
if (!history) { if (!history) {
return "App Error: Could not find channel with id: " + QString::number(peerToChannel(toId)); return "App Error: Could not find channel with id: " + QString::number(peerToChannel(toId));
} }

View file

@ -107,6 +107,8 @@ private:
QString ChatOccupiedString(not_null<History*> history); QString ChatOccupiedString(not_null<History*> history);
QString InterpretSendPath(const QString &path); QString InterpretSendPath(
not_null<Window::SessionController*> window,
const QString &path);
} // namespace Support } // namespace Support

View file

@ -9,7 +9,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/cache/storage_cache_database.h" #include "storage/cache/storage_cache_database.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "chat_helpers/stickers.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "app.h" #include "app.h"

View file

@ -11,11 +11,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_photo_media.h" #include "data/data_photo_media.h"
#include "data/data_document.h" #include "data/data_document.h"
#include "data/data_document_media.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/image/image.h"
#include "ui/emoji_config.h" #include "ui/emoji_config.h"
#include "lottie/lottie_single_player.h" #include "lottie/lottie_single_player.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "chat_helpers/stickers.h"
#include "window/window_session_controller.h" #include "window/window_session_controller.h"
#include "styles/style_layers.h" #include "styles/style_layers.h"
#include "styles/style_chat_helpers.h" #include "styles/style_chat_helpers.h"
@ -174,7 +175,7 @@ void MediaPreviewWidget::fillEmojiString() {
return; return;
} }
if (auto sticker = _document->sticker()) { if (auto sticker = _document->sticker()) {
if (auto list = Stickers::GetEmojiListFromSet(_document)) { if (auto list = _document->owner().stickers().getEmojiListFromSet(_document)) {
_emojiList = std::move(*list); _emojiList = std::move(*list);
while (_emojiList.size() > kStickerPreviewEmojiLimit) { while (_emojiList.size() > kStickerPreviewEmojiLimit) {
_emojiList.pop_back(); _emojiList.pop_back();