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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -10,7 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/abstract_box.h"
#include "base/timer.h"
#include "mtproto/sender.h"
#include "chat_helpers/stickers_set.h"
#include "data/stickers/data_stickers_set.h"
#include "ui/effects/animations.h"
#include "ui/special_fields.h"
@ -89,12 +89,8 @@ private:
object_ptr<Inner> takeWidget();
void returnWidget(object_ptr<Inner> widget);
Inner *widget() {
return _weak;
}
int index() const {
return _index;
}
[[nodiscard]] Inner *widget();
[[nodiscard]] int index() const;
void saveScrollTop();
int getScrollTop() const {
@ -157,228 +153,7 @@ private:
bool _allArchivedLoaded = false;
bool _someArchivedLoaded = false;
Stickers::Order _localOrder;
Stickers::Order _localRemoved;
};
// This class is hold in header because it requires Qt preprocessing.
class StickersBox::Inner
: public Ui::RpWidget
, private base::Subscriber {
Q_OBJECT
public:
using Section = StickersBox::Section;
Inner(
QWidget *parent,
not_null<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;
Data::StickersSetsOrder _localOrder;
Data::StickersSetsOrder _localRemoved;
};

View file

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

View file

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

View file

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

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

View file

@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "chat_helpers/tabbed_selector.h"
#include "chat_helpers/stickers.h"
#include "data/stickers/data_stickers.h"
#include "base/variant.h"
#include "base/timer.h"
@ -34,12 +34,9 @@ class FrameRenderer;
namespace Data {
class DocumentMedia;
class StickersSet;
} // namespace Data
namespace Stickers {
class Set;
} // namespace Stickers
namespace ChatHelpers {
struct StickerIcon;
@ -169,7 +166,7 @@ private:
struct Set {
Set(
uint64 id,
Stickers::Set *set,
Data::StickersSet *set,
MTPDstickerSet::Flags flags,
const QString &title,
const QString &shortName,
@ -181,7 +178,7 @@ private:
~Set();
uint64 id = 0;
Stickers::Set *set = nullptr;
Data::StickersSet *set = nullptr;
MTPDstickerSet::Flags flags = MTPDstickerSet::Flags();
QString title;
QString shortName;
@ -308,7 +305,7 @@ private:
void refreshSearchRows(const std::vector<uint64> *cloudSets);
void fillLocalSearchRows(const QString &query);
void fillCloudSearchRows(const std::vector<uint64> &cloudSets);
void addSearchRow(not_null<Stickers::Set*> set);
void addSearchRow(not_null<Data::StickersSet*> set);
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/stickers_list_widget.h"
#include "chat_helpers/gifs_list_widget.h"
#include "chat_helpers/stickers.h"
#include "ui/widgets/buttons.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/shadow.h"
@ -21,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/localstorage.h"
#include "data/data_channel.h"
#include "data/data_session.h"
#include "data/stickers/data_stickers.h"
#include "lang/lang_keys.h"
#include "mainwindow.h"
#include "observer_peer.h"
@ -366,7 +366,7 @@ TabbedSelector::TabbedSelector(
_showRequests.fire({});
}, lifetime());
session().data().stickersUpdated(
session().data().stickers().updated(
) | rpl::start_with_next([=] {
refreshStickers();
}, lifetime());

View file

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

View file

@ -33,6 +33,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "passport/passport_form_controller.h"
#include "window/themes/window_theme.h"
#include "lang/lang_keys.h" // tr::lng_deleted(tr::now) in user name
#include "data/stickers/data_stickers.h"
#include "data/data_media_types.h"
#include "data/data_folder.h"
#include "data/data_channel.h"
@ -222,7 +223,8 @@ Session::Session(not_null<Main::Session*> session)
, _cloudThemes(std::make_unique<CloudThemes>(session))
, _streaming(std::make_unique<Streaming>(this))
, _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());
_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) {
_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) {
const auto i = _contactViews.find(peerToUser(user->id));
if (i != _contactViews.end()) {
@ -1716,7 +1694,7 @@ bool Session::checkEntitiesAndViewsUpdate(const MTPDmessage &data) {
requestItemTextRefresh(existing);
updateDependentMessages(existing);
if (existing->mainView()) {
checkSavedGif(existing);
stickers().checkSavedGif(existing);
return true;
}
return false;
@ -1724,40 +1702,6 @@ bool Session::checkEntitiesAndViewsUpdate(const MTPDmessage &data) {
return false;
}
void Session::addSavedGif(not_null<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) {
const auto existing = data.match([](const MTPDmessageEmpty &)
-> HistoryItem* {
@ -2488,7 +2432,7 @@ void Session::documentConvert(
if (idChanged) {
cache().moveIfEmpty(oldCacheKey, original->cacheKey());
cache().moveIfEmpty(oldGoodKey, original->goodThumbnailCacheKey());
if (savedGifs().indexOf(original) >= 0) {
if (stickers().savedGifs().indexOf(original) >= 0) {
Local::writeSavedGifs();
}
}

View file

@ -8,11 +8,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "storage/storage_databases.h"
#include "chat_helpers/stickers_set.h"
#include "dialogs/dialogs_key.h"
#include "dialogs/dialogs_indexed_list.h"
#include "dialogs/dialogs_main_list.h"
#include "data/data_groups.h"
#include "data/data_cloud_file.h"
#include "data/data_notify_settings.h"
#include "history/history_location_manager.h"
#include "base/timer.h"
@ -65,6 +65,7 @@ class MediaRotation;
class Histories;
class DocumentMedia;
class PhotoMedia;
class Stickers;
class Session final {
public:
@ -106,6 +107,9 @@ public:
[[nodiscard]] Histories &histories() const {
return *_histories;
}
[[nodiscard]] Stickers &stickers() const {
return *_stickers;
}
[[nodiscard]] MsgId nextNonHistoryEntryId() {
return ++_nonHistoryEntryId;
}
@ -240,6 +244,9 @@ public:
[[nodiscard]] rpl::producer<not_null<History*>> historyChanged() const;
void sendHistoryChangeNotifications();
void notifyPinnedDialogsOrderUpdated();
[[nodiscard]] rpl::producer<> pinnedDialogsOrderUpdated() const;
void registerHeavyViewPart(not_null<ViewElement*> view);
void unregisterHeavyViewPart(not_null<ViewElement*> view);
void unloadHeavyViewParts(
@ -265,91 +272,6 @@ public:
[[nodiscard]] rpl::producer<not_null<UserData*>> megagroupParticipantAdded(
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;
MessageIdsList itemsToIds(const HistoryItemsList &items) const;
MessageIdsList itemOrItsGroup(not_null<HistoryItem*> item) const;
@ -808,11 +730,6 @@ private:
not_null<Folder*> folder,
const MTPDfolder &data);
bool stickersUpdateNeeded(crl::time lastUpdate, crl::time now) const {
constexpr auto kStickersUpdateTimeout = crl::time(3600'000);
return (lastUpdate == 0)
|| (now >= lastUpdate + kStickersUpdateTimeout);
}
void userIsContactUpdated(not_null<UserData*> user);
void setPinnedFromDialog(const Dialogs::Key &key, bool pinned);
@ -876,22 +793,6 @@ private:
rpl::event_stream<MegagroupParticipant> _megagroupParticipantAdded;
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::IndexedList _contactsList;
Dialogs::IndexedList _contactsNoChatsList;
@ -970,6 +871,8 @@ private:
not_null<const HistoryItem*>,
std::vector<not_null<ViewElement*>>> _views;
rpl::event_stream<> _pinnedDialogsOrderUpdated;
base::flat_set<not_null<ViewElement*>> _heavyViewParts;
PeerData *_topPromoted = nullptr;
@ -1006,6 +909,7 @@ private:
std::unique_ptr<Streaming> _streaming;
std::unique_ptr<MediaRotation> _mediaRotation;
std::unique_ptr<Histories> _histories;
std::unique_ptr<Stickers> _stickers;
MsgId _nonHistoryEntryId = ServerMaxMsgId;
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:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "chat_helpers/stickers.h"
#include "data/stickers/data_stickers.h"
#include "data/data_document.h"
#include "data/data_document_media.h"
#include "data/data_session.h"
#include "data/data_file_origin.h"
#include "chat_helpers/stickers_set.h"
#include "boxes/stickers_box.h"
#include "data/data_user.h"
#include "boxes/confirm_box.h"
#include "lang/lang_keys.h"
#include "history/history.h"
#include "history/history_item.h"
#include "history/history_item_components.h"
#include "apiwrap.h"
#include "storage/localstorage.h"
#include "mainwidget.h"
#include "main/main_session.h"
#include "mainwindow.h"
#include "ui/toast/toast.h"
#include "ui/emoji_config.h"
#include "ui/image/image_location_factory.h"
#include "base/unixtime.h"
#include "lottie/lottie_single_player.h"
#include "lottie/lottie_multi_player.h"
#include "facades.h"
#include "app.h"
#include "styles/style_chat_helpers.h"
namespace Stickers {
namespace {
namespace Data {
constexpr auto kDontCacheLottieAfterArea = 512 * 512;
Stickers::Stickers(not_null<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 &order = Auth().data().stickerSetsOrderRef();
Order archived;
auto &order = setsOrderRef();
StickersSetsOrder archived;
archived.reserve(v.size());
QMap<uint64, uint64> setsToRequest;
for (const auto &stickerSet : v) {
@ -60,7 +119,7 @@ void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) {
} break;
}
if (setData) {
auto set = FeedSet(*setData);
auto set = feedSet(*setData);
if (set->stickers.isEmpty()) {
setsToRequest.insert(set->id, set->access);
}
@ -73,9 +132,9 @@ void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) {
}
if (!setsToRequest.isEmpty()) {
for (auto i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) {
Auth().api().scheduleStickerSetRequest(i.key(), i.value());
session().api().scheduleStickerSetRequest(i.key(), i.value());
}
Auth().api().requestStickerSets();
session().api().requestStickerSets();
}
Local::writeInstalledStickers();
Local::writeArchivedStickers();
@ -85,15 +144,17 @@ void ApplyArchivedResult(const MTPDmessages_stickerSetInstallResultArchive &d) {
.st = &st::stickersToast,
.multiline = true,
});
// Ui::show(Box<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.
bool ApplyArchivedResultFake() {
bool Stickers::applyArchivedResultFake() {
auto sets = QVector<MTPStickerSetCovered>();
for (const auto &[id, set] : Auth().data().stickerSets()) {
for (const auto &[id, set] : this->sets()) {
const auto raw = set.get();
if ((raw->flags & MTPDstickerSet::Flag::f_installed_date)
&& !(raw->flags & MTPDstickerSet_ClientFlag::f_special)) {
@ -118,14 +179,14 @@ bool ApplyArchivedResultFake() {
if (sets.size() > 3) {
sets = sets.mid(0, 3);
}
auto fakeResult = MTP_messages_stickerSetInstallResultArchive(
auto result = MTP_messages_stickerSetInstallResultArchive(
MTP_vector<MTPStickerSetCovered>(sets));
ApplyArchivedResult(fakeResult.c_messages_stickerSetInstallResultArchive());
applyArchivedResult(result.c_messages_stickerSetInstallResultArchive());
return true;
}
void InstallLocally(uint64 setId) {
auto &sets = Auth().data().stickerSetsRef();
void Stickers::installLocally(uint64 setId) {
auto &sets = setsRef();
auto it = sets.find(setId);
if (it == sets.end()) {
return;
@ -138,7 +199,7 @@ void InstallLocally(uint64 setId) {
set->installDate = base::unixtime::now();
auto changedFlags = flags ^ set->flags;
auto &order = Auth().data().stickerSetsOrderRef();
auto &order = setsOrderRef();
int insertAtIndex = 0, currentIndex = order.indexOf(setId);
if (currentIndex != insertAtIndex) {
if (currentIndex > 0) {
@ -163,17 +224,17 @@ void InstallLocally(uint64 setId) {
Local::writeFeaturedStickers();
}
if (changedFlags & MTPDstickerSet::Flag::f_archived) {
auto index = Auth().data().archivedStickerSetsOrderRef().indexOf(setId);
auto index = archivedSetsOrderRef().indexOf(setId);
if (index >= 0) {
Auth().data().archivedStickerSetsOrderRef().removeAt(index);
archivedSetsOrderRef().removeAt(index);
Local::writeArchivedStickers();
}
}
Auth().data().notifyStickersUpdated();
notifyUpdated();
}
void UndoInstallLocally(uint64 setId) {
const auto &sets = Auth().data().stickerSets();
void Stickers::undoInstallLocally(uint64 setId) {
const auto &sets = this->sets();
const auto it = sets.find(setId);
if (it == sets.end()) {
return;
@ -183,22 +244,22 @@ void UndoInstallLocally(uint64 setId) {
set->flags &= ~MTPDstickerSet::Flag::f_installed_date;
set->installDate = TimeId(0);
auto &order = Auth().data().stickerSetsOrderRef();
auto &order = setsOrderRef();
int currentIndex = order.indexOf(setId);
if (currentIndex >= 0) {
order.removeAt(currentIndex);
}
Local::writeInstalledStickers();
Auth().data().notifyStickersUpdated();
notifyUpdated();
Ui::show(
Box<InformBox>(tr::lng_stickers_not_found(tr::now)),
Ui::LayerOption::KeepOther);
}
bool IsFaved(not_null<const DocumentData*> document) {
const auto &sets = Auth().data().stickerSets();
bool Stickers::isFaved(not_null<const DocumentData*> document) {
const auto &sets = this->sets();
const auto it = sets.find(FavedSetId);
if (it == sets.cend()) {
return false;
@ -211,7 +272,7 @@ bool IsFaved(not_null<const DocumentData*> document) {
return false;
}
void CheckFavedLimit(Set &set) {
void Stickers::checkFavedLimit(StickersSet &set) {
if (set.stickers.size() <= Global::StickersFavedLimit()) {
return;
}
@ -230,19 +291,20 @@ void CheckFavedLimit(Set &set) {
}
}
void PushFavedToFront(
Set &set,
void Stickers::pushFavedToFront(
StickersSet &set,
not_null<DocumentData*> document,
const std::vector<not_null<EmojiPtr>> &emojiList) {
set.stickers.push_front(document);
for (auto emoji : emojiList) {
set.emoji[emoji].push_front(document);
}
CheckFavedLimit(set);
checkFavedLimit(set);
}
void MoveFavedToFront(Set &set, int index) {
void Stickers::moveFavedToFront(StickersSet &set, int index) {
Expects(index > 0 && index < set.stickers.size());
auto document = set.stickers[index];
while (index-- != 0) {
set.stickers[index + 1] = set.stickers[index];
@ -259,15 +321,13 @@ void MoveFavedToFront(Set &set, int index) {
}
}
void RequestSetToPushFaved(not_null<DocumentData*> document);
void SetIsFaved(
void Stickers::setIsFaved(
not_null<DocumentData*> document,
std::optional<std::vector<not_null<EmojiPtr>>> emojiList = std::nullopt) {
auto &sets = document->owner().stickerSetsRef();
std::optional<std::vector<not_null<EmojiPtr>>> emojiList) {
auto &sets = setsRef();
auto it = sets.find(FavedSetId);
if (it == sets.end()) {
it = sets.emplace(FavedSetId, std::make_unique<Set>(
it = sets.emplace(FavedSetId, std::make_unique<StickersSet>(
&document->owner(),
FavedSetId,
uint64(0),
@ -284,22 +344,22 @@ void SetIsFaved(
return;
}
if (index > 0) {
MoveFavedToFront(*set, index);
moveFavedToFront(*set, index);
} else if (emojiList) {
PushFavedToFront(*set, document, *emojiList);
} else if (auto list = GetEmojiListFromSet(document)) {
PushFavedToFront(*set, document, *list);
pushFavedToFront(*set, document, *emojiList);
} else if (auto list = getEmojiListFromSet(document)) {
pushFavedToFront(*set, document, *list);
} else {
RequestSetToPushFaved(document);
requestSetToPushFaved(document);
return;
}
Local::writeFavedStickers();
Auth().data().notifyStickersUpdated();
Auth().api().stickerSetInstalled(FavedSetId);
notifyUpdated();
session().api().stickerSetInstalled(FavedSetId);
}
void RequestSetToPushFaved(not_null<DocumentData*> document) {
auto addAnyway = [document](std::vector<not_null<EmojiPtr>> list) {
void Stickers::requestSetToPushFaved(not_null<DocumentData*> document) {
auto addAnyway = [=](std::vector<not_null<EmojiPtr>> list) {
if (list.empty()) {
if (auto sticker = document->sticker()) {
if (auto emoji = Ui::Emoji::Find(sticker->alt)) {
@ -307,10 +367,11 @@ void RequestSetToPushFaved(not_null<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);
auto list = std::vector<not_null<EmojiPtr>>();
auto &d = result.c_messages_stickerSet();
list.reserve(d.vpacks().v.size());
@ -336,8 +397,8 @@ void RequestSetToPushFaved(not_null<DocumentData*> document) {
}));
}
void SetIsNotFaved(not_null<DocumentData*> document) {
auto &sets = Auth().data().stickerSetsRef();
void Stickers::setIsNotFaved(not_null<DocumentData*> document) {
auto &sets = setsRef();
auto it = sets.find(FavedSetId);
if (it == sets.end()) {
return;
@ -363,22 +424,22 @@ void SetIsNotFaved(not_null<DocumentData*> document) {
sets.erase(it);
}
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) {
SetIsFaved(document);
setIsFaved(document);
} else {
SetIsNotFaved(document);
setIsNotFaved(document);
}
}
void SetsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
auto &setsOrder = Auth().data().stickerSetsOrderRef();
void Stickers::setsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
auto &setsOrder = setsOrderRef();
setsOrder.clear();
auto &sets = Auth().data().stickerSetsRef();
auto &sets = setsRef();
QMap<uint64, uint64> setsToRequest;
for (auto &[id, set] : sets) {
if (!(set->flags & MTPDstickerSet::Flag::f_archived)) {
@ -389,7 +450,7 @@ void SetsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
}
for (const auto &setData : data) {
if (setData.type() == mtpc_stickerSet) {
auto set = FeedSet(setData.c_stickerSet());
auto set = feedSet(setData.c_stickerSet());
if (!(set->flags & MTPDstickerSet::Flag::f_archived) || (set->flags & MTPDstickerSet::Flag::f_official)) {
setsOrder.push_back(set->id);
if (set->stickers.isEmpty() || (set->flags & MTPDstickerSet_ClientFlag::f_not_loaded)) {
@ -399,7 +460,7 @@ void SetsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
}
}
auto writeRecent = false;
auto &recent = GetRecentPack();
auto &recent = getRecentPack();
for (auto it = sets.begin(); it != sets.end();) {
const auto set = it->second.get();
bool installed = (set->flags & MTPDstickerSet::Flag::f_installed_date);
@ -424,7 +485,7 @@ void SetsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
}
if (!setsToRequest.isEmpty()) {
auto &api = Auth().api();
auto &api = session().api();
for (auto i = setsToRequest.cbegin(), e = setsToRequest.cend(); i != e; ++i) {
api.scheduleStickerSetRequest(i.key(), i.value());
}
@ -438,12 +499,12 @@ void SetsReceived(const QVector<MTPStickerSet> &data, int32 hash) {
LOG(("API Error: received stickers hash %1 while counted hash is %2").arg(hash).arg(Local::countStickersHash()));
}
Auth().data().notifyStickersUpdated();
notifyUpdated();
}
void SetPackAndEmoji(
Set &set,
Pack &&pack,
void Stickers::setPackAndEmoji(
StickersSet &set,
StickersPack &&pack,
const std::vector<TimeId> &&dates,
const QVector<MTPStickerPack> &packs) {
set.stickers = std::move(pack);
@ -456,10 +517,10 @@ void SetPackAndEmoji(
emoji = emoji->original();
auto &stickers = pack.vdocuments().v;
auto p = Pack();
auto p = StickersPack();
p.reserve(stickers.size());
for (auto j = 0, c = stickers.size(); j != c; ++j) {
auto document = Auth().data().document(stickers[j].v);
auto document = owner().document(stickers[j].v);
if (!document || !document->sticker()) continue;
p.push_back(document);
@ -469,14 +530,14 @@ void SetPackAndEmoji(
}
}
void SpecialSetReceived(
void Stickers::specialSetReceived(
uint64 setId,
const QString &setTitle,
const QVector<MTPDocument> &items,
int32 hash,
const QVector<MTPStickerPack> &packs,
const QVector<MTPint> &usageDates) {
auto &sets = Auth().data().stickerSetsRef();
auto &sets = setsRef();
auto it = sets.find(setId);
if (items.isEmpty()) {
@ -485,8 +546,8 @@ void SpecialSetReceived(
}
} else {
if (it == sets.cend()) {
it = sets.emplace(setId, std::make_unique<Set>(
&Auth().data(),
it = sets.emplace(setId, std::make_unique<StickersSet>(
&owner(),
setId,
uint64(0),
setTitle,
@ -507,11 +568,11 @@ void SpecialSetReceived(
&& (setId == CloudRecentSetId);
auto customIt = sets.find(CustomSetId);
auto pack = Pack();
auto pack = StickersPack();
pack.reserve(items.size());
for (const auto &item : items) {
++dateIndex;
const auto document = Auth().data().processDocument(item);
const auto document = owner().processDocument(item);
if (!document->sticker()) {
continue;
}
@ -535,7 +596,7 @@ void SpecialSetReceived(
}
auto writeRecent = false;
auto &recent = GetRecentPack();
auto &recent = getRecentPack();
for (auto i = recent.begin(); i != recent.cend();) {
if (set->stickers.indexOf(i->first) >= 0 && pack.indexOf(i->first) < 0) {
i = recent.erase(i);
@ -548,7 +609,7 @@ void SpecialSetReceived(
if (pack.isEmpty()) {
sets.erase(it);
} else {
SetPackAndEmoji(*set, std::move(pack), std::move(dates), packs);
setPackAndEmoji(*set, std::move(pack), std::move(dates), packs);
}
if (writeRecent) {
@ -572,10 +633,10 @@ void SpecialSetReceived(
default: Unexpected("setId in SpecialSetReceived()");
}
Auth().data().notifyStickersUpdated();
notifyUpdated();
}
void FeaturedSetsReceived(
void Stickers::featuredSetsReceived(
const QVector<MTPStickerSetCovered> &list,
const QVector<MTPlong> &unread,
int32 hash) {
@ -589,10 +650,10 @@ void FeaturedSetsReceived(
unreadIds.end()
};
auto &setsOrder = Auth().data().featuredStickerSetsOrderRef();
auto &setsOrder = featuredSetsOrderRef();
setsOrder.clear();
auto &sets = Auth().data().stickerSetsRef();
auto &sets = setsRef();
auto setsToRequest = base::flat_map<uint64, uint64>();
for (auto &[id, set] : sets) {
// Mark for removing.
@ -605,11 +666,11 @@ void FeaturedSetsReceived(
});
});
auto it = sets.find(data->vid().v);
const auto title = GetSetTitle(*data);
const auto title = getSetTitle(*data);
const auto installDate = data->vinstalled_date().value_or_empty();
const auto thumb = data->vthumb();
const auto thumbnail = thumb
? Images::FromPhotoSize(&Auth(), *data, *thumb)
? Images::FromPhotoSize(&session(), *data, *thumb)
: ImageWithLocation();
if (it == sets.cend()) {
auto setClientFlags = MTPDstickerSet_ClientFlag::f_featured
@ -617,8 +678,8 @@ void FeaturedSetsReceived(
if (unreadMap.contains(data->vid().v)) {
setClientFlags |= MTPDstickerSet_ClientFlag::f_unread;
}
it = sets.emplace(data->vid().v, std::make_unique<Set>(
&Auth().data(),
it = sets.emplace(data->vid().v, std::make_unique<StickersSet>(
&owner(),
data->vid().v,
data->vaccess_hash().v,
title,
@ -672,14 +733,14 @@ void FeaturedSetsReceived(
it = sets.erase(it);
}
}
Auth().data().setFeaturedStickerSetsUnreadCount(unreadCount);
setFeaturedSetsUnreadCount(unreadCount);
if (Local::countFeaturedStickersHash() != hash) {
LOG(("API Error: received featured stickers hash %1 while counted hash is %2").arg(hash).arg(Local::countFeaturedStickersHash()));
}
if (!setsToRequest.empty()) {
auto &api = Auth().api();
auto &api = session().api();
for (const auto [setId, accessHash] : setsToRequest) {
api.scheduleStickerSetRequest(setId, accessHash);
}
@ -688,16 +749,16 @@ void FeaturedSetsReceived(
Local::writeFeaturedStickers();
Auth().data().notifyStickersUpdated();
notifyUpdated();
}
void GifsReceived(const QVector<MTPDocument> &items, int32 hash) {
auto &saved = Auth().data().savedGifsRef();
void Stickers::gifsReceived(const QVector<MTPDocument> &items, int32 hash) {
auto &saved = savedGifsRef();
saved.clear();
saved.reserve(items.size());
for (const auto &item : items) {
const auto document = Auth().data().processDocument(item);
const auto document = owner().processDocument(item);
if (!document->isGifv()) {
LOG(("API Error: "
"bad document returned in HistoryWidget::savedGifsGot!"));
@ -712,11 +773,10 @@ void GifsReceived(const QVector<MTPDocument> &items, int32 hash) {
Local::writeSavedGifs();
Auth().data().notifySavedGifsUpdated();
notifySavedGifsUpdated();
}
std::vector<not_null<DocumentData*>> GetListByEmoji(
not_null<Main::Session*> session,
std::vector<not_null<DocumentData*>> Stickers::getListByEmoji(
not_null<EmojiPtr> emoji,
uint64 seed) {
const auto original = emoji->original();
@ -726,7 +786,7 @@ std::vector<not_null<DocumentData*>> GetListByEmoji(
TimeId date = 0;
};
auto result = std::vector<StickerWithDate>();
auto &sets = session->data().stickerSetsRef();
auto &sets = setsRef();
auto setsToRequest = base::flat_map<uint64, uint64>();
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) {
auto it = sets.find(setId);
if (it == sets.cend() || (it->second->flags & skip)) {
@ -842,21 +904,21 @@ std::vector<not_null<DocumentData*>> GetListByEmoji(
};
addList(
session->data().stickerSetsOrder(),
setsOrder(),
MTPDstickerSet::Flag::f_archived);
//addList(
// session->data().featuredStickerSetsOrder(),
// featuredSetsOrder(),
// MTPDstickerSet::Flag::f_installed_date);
if (!setsToRequest.empty()) {
for (const auto &[setId, accessHash] : setsToRequest) {
session->api().scheduleStickerSetRequest(setId, accessHash);
session().api().scheduleStickerSetRequest(setId, accessHash);
}
session->api().requestStickerSets();
session().api().requestStickerSets();
}
if (session->settings().suggestStickersByEmoji()) {
const auto others = session->api().stickersByEmoji(original);
if (session().settings().suggestStickersByEmoji()) {
const auto others = session().api().stickersByEmoji(original);
if (!others) {
return {};
}
@ -878,14 +940,14 @@ std::vector<not_null<DocumentData*>> GetListByEmoji(
}) | ranges::to_vector;
}
std::optional<std::vector<not_null<EmojiPtr>>> GetEmojiListFromSet(
std::optional<std::vector<not_null<EmojiPtr>>> Stickers::getEmojiListFromSet(
not_null<DocumentData*> document) {
if (auto sticker = document->sticker()) {
auto &inputSet = sticker->set;
if (inputSet.type() != mtpc_inputStickerSetID) {
return std::nullopt;
}
const auto &sets = Auth().data().stickerSets();
const auto &sets = this->sets();
auto it = sets.find(inputSet.c_inputStickerSetID().vid().v);
if (it == sets.cend()) {
return std::nullopt;
@ -905,18 +967,18 @@ std::optional<std::vector<not_null<EmojiPtr>>> GetEmojiListFromSet(
return std::nullopt;
}
Set *FeedSet(const MTPDstickerSet &data) {
auto &sets = Auth().data().stickerSetsRef();
StickersSet *Stickers::feedSet(const MTPDstickerSet &data) {
auto &sets = setsRef();
auto it = sets.find(data.vid().v);
auto title = GetSetTitle(data);
auto title = getSetTitle(data);
auto flags = MTPDstickerSet::Flags(0);
const auto thumb = data.vthumb();
const auto thumbnail = thumb
? Images::FromPhotoSize(&Auth(), data, *thumb)
? Images::FromPhotoSize(&session(), data, *thumb)
: ImageWithLocation();
if (it == sets.cend()) {
it = sets.emplace(data.vid().v, std::make_unique<Set>(
&Auth().data(),
it = sets.emplace(data.vid().v, std::make_unique<StickersSet>(
&owner(),
data.vid().v,
data.vaccess_hash().v,
title,
@ -955,33 +1017,33 @@ Set *FeedSet(const MTPDstickerSet &data) {
const auto set = it->second.get();
auto changedFlags = (flags ^ set->flags);
if (changedFlags & MTPDstickerSet::Flag::f_archived) {
auto index = Auth().data().archivedStickerSetsOrder().indexOf(set->id);
auto index = archivedSetsOrder().indexOf(set->id);
if (set->flags & MTPDstickerSet::Flag::f_archived) {
if (index < 0) {
Auth().data().archivedStickerSetsOrderRef().push_front(set->id);
archivedSetsOrderRef().push_front(set->id);
}
} else if (index >= 0) {
Auth().data().archivedStickerSetsOrderRef().removeAt(index);
archivedSetsOrderRef().removeAt(index);
}
}
return it->second.get();
}
Set *FeedSetFull(const MTPmessages_StickerSet &data) {
StickersSet *Stickers::feedSetFull(const MTPmessages_StickerSet &data) {
Expects(data.type() == mtpc_messages_stickerSet);
Expects(data.c_messages_stickerSet().vset().type() == mtpc_stickerSet);
const auto &d = data.c_messages_stickerSet();
const auto &s = d.vset().c_stickerSet();
auto &sets = Auth().data().stickerSetsRef();
auto &sets = setsRef();
const auto wasArchived = [&] {
auto it = sets.find(s.vid().v);
return (it != sets.end())
&& (it->second->flags & MTPDstickerSet::Flag::f_archived);
}();
auto set = FeedSet(s);
auto set = feedSet(s);
set->flags &= ~MTPDstickerSet_ClientFlag::f_not_loaded;
@ -991,10 +1053,10 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) {
MTP_long(set->id),
MTP_long(set->access));
auto pack = Pack();
auto pack = StickersPack();
pack.reserve(d_docs.size());
for (const auto &item : d_docs) {
const auto document = Auth().data().processDocument(item);
const auto document = owner().processDocument(item);
if (!document->sticker()) continue;
pack.push_back(document);
@ -1015,7 +1077,7 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) {
}
auto writeRecent = false;
auto &recent = GetRecentPack();
auto &recent = getRecentPack();
for (auto i = recent.begin(); i != recent.cend();) {
if (set->stickers.indexOf(i->first) >= 0 && pack.indexOf(i->first) < 0) {
i = recent.erase(i);
@ -1026,8 +1088,8 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) {
}
if (pack.isEmpty()) {
int removeIndex = Auth().data().stickerSetsOrder().indexOf(set->id);
if (removeIndex >= 0) Auth().data().stickerSetsOrderRef().removeAt(removeIndex);
int removeIndex = setsOrder().indexOf(set->id);
if (removeIndex >= 0) setsOrderRef().removeAt(removeIndex);
sets.remove(set->id);
set = nullptr;
} else {
@ -1042,10 +1104,10 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) {
emoji = emoji->original();
auto &stickers = pack.vdocuments().v;
Pack p;
StickersPack p;
p.reserve(stickers.size());
for (auto j = 0, c = stickers.size(); j != c; ++j) {
auto doc = Auth().data().document(stickers[j].v);
auto doc = owner().document(stickers[j].v);
if (!doc || !doc->sticker()) continue;
p.push_back(doc);
@ -1074,12 +1136,12 @@ Set *FeedSetFull(const MTPmessages_StickerSet &data) {
}
}
Auth().data().notifyStickersUpdated();
notifyUpdated();
return set;
}
void NewSetReceived(const MTPmessages_StickerSet &data) {
void Stickers::newSetReceived(const MTPmessages_StickerSet &data) {
bool writeArchived = false;
const auto &set = data.c_messages_stickerSet();
const auto &s = set.vset().c_stickerSet();
@ -1094,7 +1156,7 @@ void NewSetReceived(const MTPmessages_StickerSet &data) {
} else if (s.is_masks()) {
return;
}
auto &order = Auth().data().stickerSetsOrderRef();
auto &order = setsOrderRef();
int32 insertAtIndex = 0, currentIndex = order.indexOf(s.vid().v);
if (currentIndex != insertAtIndex) {
if (currentIndex > 0) {
@ -1103,10 +1165,10 @@ void NewSetReceived(const MTPmessages_StickerSet &data) {
order.insert(insertAtIndex, s.vid().v);
}
FeedSetFull(data);
feedSetFull(data);
}
QString GetSetTitle(const MTPDstickerSet &s) {
QString Stickers::getSetTitle(const MTPDstickerSet &s) {
auto title = qs(s.vtitle());
if ((s.vflags().v & MTPDstickerSet::Flag::f_official) && !title.compare(qstr("Great Minds"), Qt::CaseInsensitive)) {
return tr::lng_stickers_default_set(tr::now);
@ -1114,7 +1176,7 @@ QString GetSetTitle(const MTPDstickerSet &s) {
return title;
}
RecentStickerPack &GetRecentPack() {
RecentStickerPack &Stickers::getRecentPack() {
if (cRecentStickers().isEmpty() && !cRecentStickersPreload().isEmpty()) {
const auto p = cRecentStickersPreload();
cSetRecentStickersPreload(RecentStickerPreload());
@ -1122,7 +1184,7 @@ RecentStickerPack &GetRecentPack() {
auto &recent = cRefRecentStickers();
recent.reserve(p.size());
for (const auto &preloaded : p) {
const auto document = Auth().data().document(preloaded.first);
const auto document = owner().document(preloaded.first);
if (!document || !document->sticker()) continue;
recent.push_back(qMakePair(document, preloaded.second));
@ -1131,168 +1193,4 @@ RecentStickerPack &GetRecentPack() {
return cRefRecentStickers();
}
template <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

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

View file

@ -11,29 +11,27 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
class DocumentData;
namespace Data {
class Session;
} // namespace Data
namespace Main {
class Session;
} // namespace Main
namespace Stickers {
namespace Data {
using Order = QList<uint64>;
class Session;
using StickersSetsOrder = QList<uint64>;
using SavedGifs = QVector<DocumentData*>;
using Pack = QVector<DocumentData*>;
using ByEmojiMap = QMap<EmojiPtr, Pack>;
using StickersPack = QVector<DocumentData*>;
using StickersByEmojiMap = QMap<EmojiPtr, StickersPack>;
class Set;
using Sets = base::flat_map<uint64, std::unique_ptr<Set>>;
class StickersSet;
using StickersSets = base::flat_map<uint64, std::unique_ptr<StickersSet>>;
class SetThumbnailView final {
class StickersSetThumbnailView final {
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);
@ -41,15 +39,15 @@ public:
[[nodiscard]] QByteArray content() const;
private:
const not_null<Set*> _owner;
const not_null<StickersSet*> _owner;
std::unique_ptr<Image> _image;
QByteArray _content;
};
class Set final {
class StickersSet final {
public:
Set(
StickersSet(
not_null<Data::Session*> owner,
uint64 id,
uint64 access,
@ -74,8 +72,8 @@ public:
[[nodiscard]] const ImageLocation &thumbnailLocation() const;
[[nodiscard]] int thumbnailByteSize() const;
[[nodiscard]] std::shared_ptr<SetThumbnailView> createThumbnailView();
[[nodiscard]] std::shared_ptr<SetThumbnailView> activeThumbnailView();
[[nodiscard]] std::shared_ptr<StickersSetThumbnailView> createThumbnailView();
[[nodiscard]] std::shared_ptr<StickersSetThumbnailView> activeThumbnailView();
uint64 id = 0;
uint64 access = 0;
@ -84,16 +82,16 @@ public:
int32 hash = 0;
MTPDstickerSet::Flags flags;
TimeId installDate = 0;
Pack stickers;
StickersPack covers;
StickersPack stickers;
std::vector<TimeId> dates;
Pack covers;
ByEmojiMap emoji;
StickersByEmojiMap emoji;
private:
const not_null<Data::Session*> _owner;
Data::CloudFile _thumbnail;
std::weak_ptr<SetThumbnailView> _thumbnailView;
CloudFile _thumbnail;
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_chat_filters.h"
#include "data/data_cloud_file.h"
#include "data/stickers/data_stickers.h"
#include "base/unixtime.h"
#include "lang/lang_keys.h"
#include "mainwindow.h"
@ -38,7 +39,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "window/themes/window_theme.h"
#include "observer_peer.h"
#include "chat_helpers/stickers.h"
#include "main/main_session.h"
#include "window/notifications_manager.h"
#include "window/window_session_controller.h"

View file

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

View file

@ -35,7 +35,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/report_box.h"
#include "boxes/sticker_set_box.h"
#include "chat_helpers/message_field.h"
#include "chat_helpers/stickers.h"
#include "history/history_widget.h"
#include "base/platform/base_platform_info.h"
#include "base/unixtime.h"
@ -55,6 +54,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_user.h"
#include "data/data_file_origin.h"
#include "data/data_histories.h"
#include "data/stickers/data_stickers.h"
#include "facades.h"
#include "app.h"
#include "styles/style_history.h"
@ -1731,11 +1731,11 @@ void HistoryInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
_menu->addAction(document->isStickerSetInstalled() ? tr::lng_context_pack_info(tr::now) : tr::lng_context_pack_add(tr::now), [=] {
showStickerPackInfo(document);
});
_menu->addAction(Stickers::IsFaved(document) ? tr::lng_faved_stickers_remove(tr::now) : tr::lng_faved_stickers_add(tr::now), [=] {
_menu->addAction(session().data().stickers().isFaved(document) ? tr::lng_faved_stickers_remove(tr::now) : tr::lng_faved_stickers_add(tr::now), [=] {
session().api().toggleFavedSticker(
document,
itemId,
!Stickers::IsFaved(document));
!session().data().stickers().isFaved(document));
});
}
_menu->addAction(tr::lng_context_save_image(tr::now), App::LambdaDelayed(st::defaultDropdownMenu.menu.ripple.hideDuration, this, [=] {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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