mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 05:07:10 +02:00
Allow wearing collectibles from emoji status.
This commit is contained in:
parent
d0132c0f7b
commit
fecddb5203
23 changed files with 278 additions and 68 deletions
|
@ -2373,6 +2373,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_group_stickers_add" = "Choose sticker set";
|
||||
"lng_group_emoji" = "Select Emoji Pack";
|
||||
"lng_group_emoji_description" = "Choose an emoji pack that will be available to all members within the group.";
|
||||
"lng_collectible_emoji" = "Collectibles";
|
||||
|
||||
"lng_premium" = "Premium";
|
||||
"lng_premium_free" = "Free";
|
||||
|
|
|
@ -265,7 +265,7 @@ struct IconSelector {
|
|||
const auto manager = &controller->session().data().customEmojiManager();
|
||||
|
||||
auto factory = [=](DocumentId id, Fn<void()> repaint)
|
||||
-> std::unique_ptr<Ui::Text::CustomEmoji> {
|
||||
-> std::unique_ptr<Ui::Text::CustomEmoji> {
|
||||
const auto tag = Data::CustomEmojiManager::SizeTag::Large;
|
||||
if (id == kDefaultIconId) {
|
||||
return std::make_unique<DefaultIconEmoji>(
|
||||
|
@ -288,7 +288,7 @@ struct IconSelector {
|
|||
.show = controller->uiShow(),
|
||||
.mode = EmojiListWidget::Mode::TopicIcon,
|
||||
.paused = Window::PausedIn(controller, PauseReason::Layer),
|
||||
.customRecentList = recent(),
|
||||
.customRecentList = DocumentListToRecent(recent()),
|
||||
.customRecentFactory = std::move(factory),
|
||||
.st = &st::reactPanelEmojiPan,
|
||||
}),
|
||||
|
@ -297,7 +297,7 @@ struct IconSelector {
|
|||
icons->requestDefaultIfUnknown();
|
||||
icons->defaultUpdates(
|
||||
) | rpl::start_with_next([=] {
|
||||
selector->provideRecent(recent());
|
||||
selector->provideRecent(DocumentListToRecent(recent()));
|
||||
}, selector->lifetime());
|
||||
|
||||
placeFooter(selector->createFooter());
|
||||
|
|
|
@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
|
||||
#include "apiwrap.h"
|
||||
#include "base/event_filter.h"
|
||||
#include "chat_helpers/emoji_list_widget.h"
|
||||
#include "chat_helpers/tabbed_panel.h"
|
||||
#include "chat_helpers/tabbed_selector.h"
|
||||
#include "core/ui_integration.h"
|
||||
|
@ -491,7 +492,8 @@ object_ptr<Ui::RpWidget> AddReactionsSelector(
|
|||
panelList.erase(
|
||||
ranges::remove(panelList, paid->selectAnimation->id),
|
||||
end(panelList));
|
||||
panel->selector()->provideRecentEmoji(panelList);
|
||||
panel->selector()->provideRecentEmoji(
|
||||
ChatHelpers::DocumentListToRecent(panelList));
|
||||
panel->setDesiredHeightValues(
|
||||
1.,
|
||||
st::emojiPanMinHeight / 2,
|
||||
|
|
|
@ -40,6 +40,7 @@ TabbedSearch {
|
|||
|
||||
ComposeIcons {
|
||||
settings: icon;
|
||||
collectibles: icon;
|
||||
|
||||
recent: icon;
|
||||
recentActive: icon;
|
||||
|
@ -587,6 +588,7 @@ sendBoxAlbumGroupButtonMediaDelete: icon {{ "send_media/send_media_delete", roun
|
|||
|
||||
defaultComposeIcons: ComposeIcons {
|
||||
settings: icon {{ "emoji/emoji_settings", emojiIconFg }};
|
||||
collectibles: icon {{ "menu/unique", emojiIconFg }};
|
||||
|
||||
recent: icon {{ "emoji/emoji_recent", emojiIconFg }};
|
||||
recentActive: icon {{ "emoji/emoji_recent", emojiSubIconFgActive }};
|
||||
|
|
|
@ -18,6 +18,7 @@ struct ComposeFeatures {
|
|||
bool attachBotsMenu : 1 = true;
|
||||
bool inlineBots : 1 = true;
|
||||
bool megagroupSet : 1 = true;
|
||||
bool collectibleStatus : 1 = false;
|
||||
bool stickersSettings : 1 = true;
|
||||
bool openStickerSets : 1 = true;
|
||||
bool autocompleteHashtags : 1 = true;
|
||||
|
|
|
@ -30,6 +30,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "boxes/sticker_set_box.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "layout/layout_position.h"
|
||||
#include "data/data_emoji_statuses.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_channel.h"
|
||||
|
@ -134,6 +135,7 @@ struct EmojiListWidget::CustomEmojiInstance {
|
|||
};
|
||||
|
||||
struct EmojiListWidget::RecentOne {
|
||||
std::shared_ptr<Data::EmojiStatusCollectible> collectible;
|
||||
Ui::Text::CustomEmoji *custom = nullptr;
|
||||
RecentEmojiId id;
|
||||
mutable QImage premiumLock;
|
||||
|
@ -447,6 +449,13 @@ void EmojiColorPicker::drawVariant(QPainter &p, int variant) {
|
|||
w.y() + _innerPosition.y());
|
||||
}
|
||||
|
||||
std::vector<EmojiStatusId> DocumentListToRecent(
|
||||
const std::vector<DocumentId> &documents) {
|
||||
return documents | ranges::views::transform([](DocumentId id) {
|
||||
return EmojiStatusId{ .documentId = id };
|
||||
}) | ranges::to_vector;
|
||||
}
|
||||
|
||||
EmojiListWidget::EmojiListWidget(
|
||||
QWidget *parent,
|
||||
not_null<Window::SessionController*> controller,
|
||||
|
@ -510,6 +519,11 @@ EmojiListWidget::EmojiListWidget(
|
|||
refreshCustom();
|
||||
}
|
||||
}, lifetime());
|
||||
} else if (_mode == Mode::EmojiStatus && _features.collectibleStatus) {
|
||||
session().data().emojiStatuses().collectiblesUpdates(
|
||||
) | rpl::start_with_next([=] {
|
||||
refreshCustom();
|
||||
}, lifetime());
|
||||
}
|
||||
|
||||
_customSingleSize = Data::FrameSizeFromTag(
|
||||
|
@ -656,7 +670,8 @@ void EmojiListWidget::applyNextSearchQuery() {
|
|||
void EmojiListWidget::showPreview() {
|
||||
if (const auto over = std::get_if<OverEmoji>(&_pressed)) {
|
||||
if (const auto custom = lookupCustomEmoji(over)) {
|
||||
_show->showMediaPreview(custom->stickerSetOrigin(), custom);
|
||||
const auto document = custom.document;
|
||||
_show->showMediaPreview(document->stickerSetOrigin(), document);
|
||||
_previewShown = true;
|
||||
}
|
||||
}
|
||||
|
@ -706,7 +721,7 @@ void EmojiListWidget::appendPremiumSearchResults() {
|
|||
}
|
||||
|
||||
void EmojiListWidget::provideRecent(
|
||||
const std::vector<DocumentId> &customRecentList) {
|
||||
const std::vector<EmojiStatusId> &customRecentList) {
|
||||
clearSelection();
|
||||
fillRecentFrom(customRecentList);
|
||||
resizeToWidth(width());
|
||||
|
@ -1094,7 +1109,8 @@ void EmojiListWidget::fillRecent() {
|
|||
}
|
||||
}
|
||||
|
||||
void EmojiListWidget::fillRecentFrom(const std::vector<DocumentId> &list) {
|
||||
void EmojiListWidget::fillRecentFrom(
|
||||
const std::vector<EmojiStatusId> &list) {
|
||||
const auto test = session().isTestMode();
|
||||
_recent.clear();
|
||||
_recent.reserve(list.size());
|
||||
|
@ -1113,11 +1129,17 @@ void EmojiListWidget::fillRecentFrom(const std::vector<DocumentId> &list) {
|
|||
});
|
||||
_recentCustomIds.emplace(fakeId);
|
||||
} else {
|
||||
const auto documentId = id.collectible
|
||||
? id.collectible->documentId
|
||||
: id.documentId;
|
||||
_recent.push_back({
|
||||
.custom = resolveCustomRecent(id),
|
||||
.id = { RecentEmojiDocument{ .id = id, .test = test } },
|
||||
.collectible = id.collectible,
|
||||
.custom = resolveCustomRecent(documentId),
|
||||
.id = {
|
||||
RecentEmojiDocument{ .id = documentId, .test = test },
|
||||
},
|
||||
});
|
||||
_recentCustomIds.emplace(id);
|
||||
_recentCustomIds.emplace(documentId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1158,8 +1180,12 @@ void EmojiListWidget::fillRecentMenu(
|
|||
const auto over = OverEmoji{ section, index };
|
||||
const auto emoji = lookupOverEmoji(&over);
|
||||
const auto custom = lookupCustomEmoji(&over);
|
||||
if (custom && custom->sticker()) {
|
||||
const auto sticker = custom->sticker();
|
||||
if (custom.collectible) {
|
||||
return;
|
||||
}
|
||||
const auto document = custom.document;
|
||||
if (document && document->sticker()) {
|
||||
const auto sticker = document->sticker();
|
||||
const auto emoji = sticker->alt;
|
||||
const auto setId = sticker->set.id;
|
||||
if (!emoji.isEmpty()) {
|
||||
|
@ -1168,7 +1194,7 @@ void EmojiListWidget::fillRecentMenu(
|
|||
EntityType::CustomEmoji,
|
||||
0,
|
||||
int(emoji.size()),
|
||||
Data::SerializeCustomEmojiId(custom)
|
||||
Data::SerializeCustomEmojiId(document)
|
||||
});
|
||||
addAction(tr::lng_emoji_copy(tr::now), [=] {
|
||||
TextUtilities::SetClipboardText(data);
|
||||
|
@ -1192,8 +1218,8 @@ void EmojiListWidget::fillRecentMenu(
|
|||
auto id = RecentEmojiId{ emoji };
|
||||
if (custom) {
|
||||
id.data = RecentEmojiDocument{
|
||||
.id = custom->id,
|
||||
.test = custom->session().isTestMode(),
|
||||
.id = custom.document->id,
|
||||
.test = custom.document->session().isTestMode(),
|
||||
};
|
||||
}
|
||||
addAction(tr::lng_emoji_remove_recent(tr::now), crl::guard(this, [=] {
|
||||
|
@ -1229,7 +1255,7 @@ void EmojiListWidget::fillEmojiStatusMenu(
|
|||
int section,
|
||||
int index) {
|
||||
const auto chosen = lookupCustomEmoji(index, section);
|
||||
if (!chosen) {
|
||||
if (!chosen || chosen.collectible) {
|
||||
return;
|
||||
}
|
||||
const auto selectWith = [=](TimeId scheduled) {
|
||||
|
@ -1464,6 +1490,27 @@ void EmojiListWidget::drawCollapsedBadge(
|
|||
text);
|
||||
}
|
||||
|
||||
void EmojiListWidget::drawCollectible(
|
||||
QPainter &p,
|
||||
QPoint position,
|
||||
Data::EmojiStatusCollectible *collectible) {
|
||||
if (!collectible) {
|
||||
return;
|
||||
}
|
||||
const auto inner = QRect(position, st::emojiPanArea);
|
||||
auto gradient = QRadialGradient(inner.center(), inner.height() / 2);
|
||||
gradient.setStops({
|
||||
{ 0., collectible->centerColor },
|
||||
{ 1., collectible->edgeColor },
|
||||
});
|
||||
p.setBrush(gradient);
|
||||
p.setPen(Qt::NoPen);
|
||||
p.drawRoundedRect(
|
||||
inner,
|
||||
st::emojiPanRadius,
|
||||
st::emojiPanRadius);
|
||||
}
|
||||
|
||||
void EmojiListWidget::drawRecent(
|
||||
QPainter &p,
|
||||
const ExpandingContext &context,
|
||||
|
@ -1500,12 +1547,14 @@ void EmojiListWidget::drawRecent(
|
|||
|
||||
auto q = Painter(&_premiumMarkFrameCache);
|
||||
_emojiPaintContext->position = QPoint();
|
||||
drawCollectible(q, position, recent.collectible.get());
|
||||
custom->paint(q, *_emojiPaintContext);
|
||||
q.end();
|
||||
|
||||
p.drawImage(exactPosition, _premiumMarkFrameCache);
|
||||
} else {
|
||||
_emojiPaintContext->position = exactPosition;
|
||||
drawCollectible(p, position, recent.collectible.get());
|
||||
custom->paint(p, *_emojiPaintContext);
|
||||
}
|
||||
} else if (const auto emoji = std::get_if<EmojiPtr>(&recent.id.data)) {
|
||||
|
@ -1560,6 +1609,7 @@ void EmojiListWidget::drawCustom(
|
|||
_emojiPaintContext->position = position
|
||||
+ _innerPosition
|
||||
+ _customPosition;
|
||||
drawCollectible(p, position, entry.collectible.get());
|
||||
entry.custom->paint(p, *_emojiPaintContext);
|
||||
}
|
||||
|
||||
|
@ -1573,12 +1623,14 @@ bool EmojiListWidget::checkPickerHide() {
|
|||
return false;
|
||||
}
|
||||
|
||||
DocumentData *EmojiListWidget::lookupCustomEmoji(
|
||||
EmojiListWidget::ResolvedCustom EmojiListWidget::lookupCustomEmoji(
|
||||
const OverEmoji *over) const {
|
||||
return over ? lookupCustomEmoji(over->index, over->section) : nullptr;
|
||||
return over
|
||||
? lookupCustomEmoji(over->index, over->section)
|
||||
: ResolvedCustom();
|
||||
}
|
||||
|
||||
DocumentData *EmojiListWidget::lookupCustomEmoji(
|
||||
EmojiListWidget::ResolvedCustom EmojiListWidget::lookupCustomEmoji(
|
||||
int index,
|
||||
int section) const {
|
||||
if (_searchMode) {
|
||||
|
@ -1586,22 +1638,23 @@ DocumentData *EmojiListWidget::lookupCustomEmoji(
|
|||
const auto document = std::get_if<RecentEmojiDocument>(
|
||||
&_searchResults[index].id.data);
|
||||
if (document) {
|
||||
return session().data().document(document->id);
|
||||
return { session().data().document(document->id) };
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
} else if (section == int(Section::Recent) && index < _recent.size()) {
|
||||
const auto document = std::get_if<RecentEmojiDocument>(
|
||||
&_recent[index].id.data);
|
||||
if (document) {
|
||||
return session().data().document(document->id);
|
||||
return { session().data().document(document->id) };
|
||||
}
|
||||
} else if (section >= _staticCount
|
||||
&& index < _custom[section - _staticCount].list.size()) {
|
||||
auto &set = _custom[section - _staticCount];
|
||||
return set.list[index].document;
|
||||
auto &entry = set.list[index];
|
||||
return { entry.document, entry.collectible };
|
||||
}
|
||||
return nullptr;
|
||||
return {};
|
||||
}
|
||||
|
||||
EmojiPtr EmojiListWidget::lookupOverEmoji(const OverEmoji *over) const {
|
||||
|
@ -1643,9 +1696,11 @@ EmojiChosen EmojiListWidget::lookupChosen(
|
|||
}
|
||||
|
||||
FileChosen EmojiListWidget::lookupChosen(
|
||||
not_null<DocumentData*> custom,
|
||||
ResolvedCustom custom,
|
||||
const OverEmoji *over,
|
||||
Api::SendOptions options) {
|
||||
Expects(custom.document != nullptr);
|
||||
|
||||
_grabbingChosen = true;
|
||||
const auto guard = gsl::finally([&] { _grabbingChosen = false; });
|
||||
const auto rect = over ? emojiRect(over->section, over->index) : QRect();
|
||||
|
@ -1655,13 +1710,14 @@ FileChosen EmojiListWidget::lookupChosen(
|
|||
) : QRect();
|
||||
|
||||
return {
|
||||
.document = custom,
|
||||
.document = custom.document,
|
||||
.options = options,
|
||||
.messageSendingFrom = {
|
||||
.type = Ui::MessageSendingAnimationFrom::Type::Emoji,
|
||||
.globalStartGeometry = over ? mapToGlobal(emoji) : QRect(),
|
||||
.frame = over ? Ui::GrabWidgetToImage(this, emoji) : QImage(),
|
||||
},
|
||||
.collectible = custom.collectible,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1791,6 +1847,8 @@ void EmojiListWidget::displaySet(uint64 setId) {
|
|||
} else {
|
||||
return;
|
||||
}
|
||||
} else if (setId == Data::Stickers::CollectibleSetId) {
|
||||
return;
|
||||
}
|
||||
const auto &sets = session().data().stickers().sets();
|
||||
auto it = sets.find(setId);
|
||||
|
@ -1829,6 +1887,7 @@ void EmojiListWidget::removeSet(uint64 setId) {
|
|||
Assert(i != end(_custom));
|
||||
const auto removeLocally = !_megagroupSet->canEditEmoji();
|
||||
removeMegagroupSet(removeLocally);
|
||||
} else if (setId == Data::Stickers::CollectibleSetId) {
|
||||
} else if (auto box = MakeConfirmRemoveSetBox(&session(), labelSt, setId)) {
|
||||
checkHideWithBox(std::move(box));
|
||||
}
|
||||
|
@ -1932,6 +1991,8 @@ bool EmojiListWidget::hasRemoveButton(int index) const {
|
|||
return true;
|
||||
}
|
||||
return !set.list.empty() && _megagroupSet->canEditEmoji();
|
||||
} else if (set.id == Data::Stickers::CollectibleSetId) {
|
||||
return false;
|
||||
}
|
||||
return set.canRemove && !set.premiumRequired;
|
||||
}
|
||||
|
@ -1961,7 +2022,8 @@ bool EmojiListWidget::hasAddButton(int index) const {
|
|||
const auto &set = _custom[index - _staticCount];
|
||||
return !set.canRemove
|
||||
&& !set.premiumRequired
|
||||
&& set.id != Data::Stickers::MegagroupSetId;
|
||||
&& set.id != Data::Stickers::MegagroupSetId
|
||||
&& set.id != Data::Stickers::CollectibleSetId;
|
||||
}
|
||||
|
||||
QRect EmojiListWidget::addButtonRect(int index) const {
|
||||
|
@ -1990,8 +2052,9 @@ bool EmojiListWidget::hasButton(int index) const {
|
|||
} else if (index >= _staticCount
|
||||
&& index < _staticCount + _custom.size()) {
|
||||
const auto &custom = _custom[index - _staticCount];
|
||||
return (custom.id != Data::Stickers::MegagroupSetId)
|
||||
|| custom.canRemove;
|
||||
return (custom.id != Data::Stickers::CollectibleSetId)
|
||||
&& ((custom.id != Data::Stickers::MegagroupSetId)
|
||||
|| custom.canRemove);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -2019,6 +2082,7 @@ QRect EmojiListWidget::buttonRect(
|
|||
auto EmojiListWidget::rightButton(int index) const -> const RightButton & {
|
||||
Expects(index >= _staticCount
|
||||
&& index < _staticCount + _custom.size());
|
||||
|
||||
return hasAddButton(index)
|
||||
? _add
|
||||
: _custom[index - _staticCount].canRemove
|
||||
|
@ -2304,6 +2368,7 @@ void EmojiListWidget::refreshCustom() {
|
|||
.premiumRequired = premium && premiumMayBeBought,
|
||||
});
|
||||
};
|
||||
refreshEmojiStatusCollectibles();
|
||||
refreshMegagroupStickers(push, GroupStickersPlace::Visible);
|
||||
for (const auto setId : owner->stickers().emojiSetsOrder()) {
|
||||
push(setId, true);
|
||||
|
@ -2404,6 +2469,44 @@ not_null<Ui::Text::CustomEmoji*> EmojiListWidget::resolveCustomRecent(
|
|||
).first->second.emoji.get();
|
||||
}
|
||||
|
||||
void EmojiListWidget::refreshEmojiStatusCollectibles() {
|
||||
if (_mode != Mode::EmojiStatus || !_features.collectibleStatus) {
|
||||
return;
|
||||
}
|
||||
const auto type = Data::EmojiStatuses::Type::Collectibles;
|
||||
const auto &list = session().data().emojiStatuses().list(type);
|
||||
if (list.empty()) {
|
||||
return;
|
||||
}
|
||||
const auto setId = Data::Stickers::CollectibleSetId;
|
||||
auto set = std::vector<CustomOne>();
|
||||
set.reserve(list.size());
|
||||
for (const auto &status : list) {
|
||||
const auto documentId = status.collectible
|
||||
? status.collectible->documentId
|
||||
: status.documentId;
|
||||
const auto document = session().data().document(documentId);
|
||||
if (const auto sticker = document->sticker()) {
|
||||
set.push_back({
|
||||
.collectible = status.collectible,
|
||||
.custom = resolveCustomEmoji(document, setId),
|
||||
.document = document,
|
||||
.emoji = Ui::Emoji::Find(sticker->alt),
|
||||
});
|
||||
}
|
||||
}
|
||||
const auto collectibles = session().data().stickers().collectibleSet();
|
||||
_custom.push_back({
|
||||
.id = setId,
|
||||
.set = collectibles,
|
||||
.thumbnailDocument = nullptr,
|
||||
.title = collectibles->title,
|
||||
.list = std::move(set),
|
||||
.canRemove = false,
|
||||
.premiumRequired = !session().premium(),
|
||||
});
|
||||
}
|
||||
|
||||
void EmojiListWidget::refreshMegagroupStickers(
|
||||
Fn<void(uint64 setId, bool installed)> push,
|
||||
GroupStickersPlace place) {
|
||||
|
@ -2638,8 +2741,11 @@ void EmojiListWidget::setSelected(OverState newSelected) {
|
|||
} else if (_previewShown && _pressed != _selected) {
|
||||
if (const auto over = std::get_if<OverEmoji>(&_selected)) {
|
||||
if (const auto custom = lookupCustomEmoji(over)) {
|
||||
const auto document = custom.document;
|
||||
_pressed = _selected;
|
||||
_show->showMediaPreview(custom->stickerSetOrigin(), custom);
|
||||
_show->showMediaPreview(
|
||||
document->stickerSetOrigin(),
|
||||
document);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,12 +83,15 @@ enum class EmojiListMode {
|
|||
MessageEffects,
|
||||
};
|
||||
|
||||
[[nodiscard]] std::vector<EmojiStatusId> DocumentListToRecent(
|
||||
const std::vector<DocumentId> &documents);
|
||||
|
||||
struct EmojiListDescriptor {
|
||||
std::shared_ptr<Show> show;
|
||||
EmojiListMode mode = EmojiListMode::Full;
|
||||
Fn<QColor()> customTextColor;
|
||||
Fn<bool()> paused;
|
||||
std::vector<DocumentId> customRecentList;
|
||||
std::vector<EmojiStatusId> customRecentList;
|
||||
Fn<std::unique_ptr<Ui::Text::CustomEmoji>(
|
||||
DocumentId,
|
||||
Fn<void()>)> customRecentFactory;
|
||||
|
@ -137,7 +140,7 @@ public:
|
|||
[[nodiscard]] rpl::producer<> jumpedToPremium() const;
|
||||
[[nodiscard]] rpl::producer<> escapes() const;
|
||||
|
||||
void provideRecent(const std::vector<DocumentId> &customRecentList);
|
||||
void provideRecent(const std::vector<EmojiStatusId> &customRecentList);
|
||||
|
||||
void prepareExpanding();
|
||||
void paintExpanding(
|
||||
|
@ -186,6 +189,7 @@ private:
|
|||
bool collapsed = false;
|
||||
};
|
||||
struct CustomOne {
|
||||
std::shared_ptr<Data::EmojiStatusCollectible> collectible;
|
||||
not_null<Ui::Text::CustomEmoji*> custom;
|
||||
not_null<DocumentData*> document;
|
||||
EmojiPtr emoji = nullptr;
|
||||
|
@ -253,6 +257,14 @@ private:
|
|||
int finalHeight = 0;
|
||||
bool expanding = false;
|
||||
};
|
||||
struct ResolvedCustom {
|
||||
DocumentData *document = nullptr;
|
||||
std::shared_ptr<Data::EmojiStatusCollectible> collectible;
|
||||
|
||||
explicit operator bool() const {
|
||||
return document != nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Callback>
|
||||
bool enumerateSections(Callback callback) const;
|
||||
|
@ -271,6 +283,7 @@ private:
|
|||
Visible,
|
||||
Hidden,
|
||||
};
|
||||
void refreshEmojiStatusCollectibles();
|
||||
void refreshMegagroupStickers(
|
||||
Fn<void(uint64 setId, bool installed)> push,
|
||||
GroupStickersPlace place);
|
||||
|
@ -296,22 +309,26 @@ private:
|
|||
int index);
|
||||
|
||||
[[nodiscard]] EmojiPtr lookupOverEmoji(const OverEmoji *over) const;
|
||||
[[nodiscard]] DocumentData *lookupCustomEmoji(
|
||||
[[nodiscard]] ResolvedCustom lookupCustomEmoji(
|
||||
const OverEmoji *over) const;
|
||||
[[nodiscard]] DocumentData *lookupCustomEmoji(
|
||||
[[nodiscard]] ResolvedCustom lookupCustomEmoji(
|
||||
int index,
|
||||
int section) const;
|
||||
[[nodiscard]] EmojiChosen lookupChosen(
|
||||
EmojiPtr emoji,
|
||||
not_null<const OverEmoji*> over);
|
||||
[[nodiscard]] FileChosen lookupChosen(
|
||||
not_null<DocumentData*> custom,
|
||||
ResolvedCustom custom,
|
||||
const OverEmoji *over,
|
||||
Api::SendOptions options = Api::SendOptions());
|
||||
void selectEmoji(EmojiChosen data);
|
||||
void selectCustom(FileChosen data);
|
||||
void paint(Painter &p, ExpandingContext context, QRect clip);
|
||||
void drawCollapsedBadge(QPainter &p, QPoint position, int count);
|
||||
void drawCollectible(
|
||||
QPainter &p,
|
||||
QPoint position,
|
||||
Data::EmojiStatusCollectible *collectible);
|
||||
void drawRecent(
|
||||
QPainter &p,
|
||||
const ExpandingContext &context,
|
||||
|
@ -370,7 +387,7 @@ private:
|
|||
void repaintCustom(uint64 setId);
|
||||
|
||||
void fillRecent();
|
||||
void fillRecentFrom(const std::vector<DocumentId> &list);
|
||||
void fillRecentFrom(const std::vector<EmojiStatusId> &list);
|
||||
[[nodiscard]] not_null<Ui::Text::CustomEmoji*> resolveCustomEmoji(
|
||||
not_null<DocumentData*> document,
|
||||
uint64 setId);
|
||||
|
|
|
@ -1467,6 +1467,8 @@ void StickersListFooter::paintSetIconToCache(
|
|||
return &st().icons.people;
|
||||
} else if (const auto section = SetIdEmojiSection(icon.setId)) {
|
||||
return sectionIcon(*section, selected);
|
||||
} else if (icon.setId == Data::Stickers::CollectibleSetId) {
|
||||
return &st().icons.collectibles;
|
||||
}
|
||||
return sectionIcon(Section::Recent, selected);
|
||||
}());
|
||||
|
|
|
@ -1017,7 +1017,7 @@ void TabbedSelector::setCurrentPeer(PeerData *peer) {
|
|||
}
|
||||
|
||||
void TabbedSelector::provideRecentEmoji(
|
||||
const std::vector<DocumentId> &customRecentList) {
|
||||
const std::vector<EmojiStatusId> &customRecentList) {
|
||||
for (const auto &tab : _tabs) {
|
||||
if (tab.type() == SelectorTab::Emoji) {
|
||||
const auto emoji = static_cast<EmojiListWidget*>(tab.widget());
|
||||
|
|
|
@ -62,6 +62,7 @@ struct FileChosen {
|
|||
not_null<DocumentData*> document;
|
||||
Api::SendOptions options;
|
||||
Ui::MessageSendingAnimationFrom messageSendingFrom;
|
||||
std::shared_ptr<Data::EmojiStatusCollectible> collectible;
|
||||
TextWithTags caption;
|
||||
};
|
||||
|
||||
|
@ -154,7 +155,7 @@ public:
|
|||
void refreshStickers();
|
||||
void setCurrentPeer(PeerData *peer);
|
||||
void provideRecentEmoji(
|
||||
const std::vector<DocumentId> &customRecentList);
|
||||
const std::vector<EmojiStatusId> &customRecentList);
|
||||
|
||||
void hideFinished();
|
||||
void showStarted();
|
||||
|
|
|
@ -84,6 +84,10 @@ void EmojiStatuses::refreshChannelColored() {
|
|||
requestChannelColored();
|
||||
}
|
||||
|
||||
void EmojiStatuses::refreshCollectibles() {
|
||||
requestCollectibles();
|
||||
}
|
||||
|
||||
void EmojiStatuses::refreshRecentDelayed() {
|
||||
if (_recentRequestId || _recentRequestScheduled) {
|
||||
return;
|
||||
|
@ -103,6 +107,7 @@ const std::vector<EmojiStatusId> &EmojiStatuses::list(Type type) const {
|
|||
case Type::Colored: return _colored;
|
||||
case Type::ChannelDefault: return _channelDefault;
|
||||
case Type::ChannelColored: return _channelColored;
|
||||
case Type::Collectibles: return _collectibles;
|
||||
}
|
||||
Unexpected("Type in EmojiStatuses::list.");
|
||||
}
|
||||
|
@ -371,6 +376,7 @@ void EmojiStatuses::requestColored() {
|
|||
_coloredRequestId = 0;
|
||||
result.match([&](const MTPDmessages_stickerSet &data) {
|
||||
updateColored(data);
|
||||
refreshCollectibles();
|
||||
}, [](const MTPDmessages_stickerSetNotModified &) {
|
||||
LOG(("API Error: Unexpected messages.stickerSetNotModified."));
|
||||
});
|
||||
|
@ -418,6 +424,25 @@ void EmojiStatuses::requestChannelColored() {
|
|||
}).send();
|
||||
}
|
||||
|
||||
void EmojiStatuses::requestCollectibles() {
|
||||
if (_collectiblesRequestId) {
|
||||
return;
|
||||
}
|
||||
auto &api = _owner->session().api();
|
||||
_collectiblesRequestId = api.request(
|
||||
MTPaccount_GetCollectibleEmojiStatuses(MTP_long(_collectiblesHash))
|
||||
).done([=](const MTPaccount_EmojiStatuses &result) {
|
||||
_collectiblesRequestId = 0;
|
||||
result.match([&](const MTPDaccount_emojiStatuses &data) {
|
||||
updateCollectibles(data);
|
||||
}, [&](const MTPDaccount_emojiStatusesNotModified &) {
|
||||
});
|
||||
}).fail([=] {
|
||||
_collectiblesRequestId = 0;
|
||||
_collectiblesHash = 0;
|
||||
}).send();
|
||||
}
|
||||
|
||||
void EmojiStatuses::updateRecent(const MTPDaccount_emojiStatuses &data) {
|
||||
_recentHash = data.vhash().v;
|
||||
_recent = parse(data);
|
||||
|
@ -462,6 +487,13 @@ void EmojiStatuses::updateChannelColored(
|
|||
_channelColoredUpdated.fire({});
|
||||
}
|
||||
|
||||
void EmojiStatuses::updateCollectibles(
|
||||
const MTPDaccount_emojiStatuses &data) {
|
||||
_collectiblesHash = data.vhash().v;
|
||||
_collectibles = parse(data);
|
||||
_collectiblesUpdated.fire({});
|
||||
}
|
||||
|
||||
void EmojiStatuses::set(EmojiStatusId id, TimeId until) {
|
||||
set(_owner->session().user(), id, until);
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ public:
|
|||
void refreshColored();
|
||||
void refreshChannelDefault();
|
||||
void refreshChannelColored();
|
||||
void refreshCollectibles();
|
||||
|
||||
enum class Type {
|
||||
Recent,
|
||||
|
@ -103,12 +104,14 @@ private:
|
|||
void requestColored();
|
||||
void requestChannelDefault();
|
||||
void requestChannelColored();
|
||||
void requestCollectibles();
|
||||
|
||||
void updateRecent(const MTPDaccount_emojiStatuses &data);
|
||||
void updateDefault(const MTPDaccount_emojiStatuses &data);
|
||||
void updateColored(const MTPDmessages_stickerSet &data);
|
||||
void updateChannelDefault(const MTPDaccount_emojiStatuses &data);
|
||||
void updateChannelColored(const MTPDmessages_stickerSet &data);
|
||||
void updateCollectibles(const MTPDaccount_emojiStatuses &data);
|
||||
|
||||
void processClearingIn(TimeId wait);
|
||||
void processClearing();
|
||||
|
@ -153,6 +156,7 @@ private:
|
|||
mtpRequestId _channelColoredRequestId = 0;
|
||||
|
||||
mtpRequestId _collectiblesRequestId = 0;
|
||||
uint64 _collectiblesHash = 0;
|
||||
|
||||
base::flat_map<not_null<PeerData*>, mtpRequestId> _sentRequests;
|
||||
|
||||
|
|
|
@ -814,6 +814,25 @@ void Stickers::setPackAndEmoji(
|
|||
}
|
||||
}
|
||||
|
||||
not_null<StickersSet*> Stickers::collectibleSet() {
|
||||
const auto setId = CollectibleSetId;
|
||||
auto &sets = setsRef();
|
||||
auto it = sets.find(setId);
|
||||
if (it == sets.cend()) {
|
||||
it = sets.emplace(setId, std::make_unique<StickersSet>(
|
||||
&owner(),
|
||||
setId,
|
||||
uint64(0), // accessHash
|
||||
uint64(0), // hash
|
||||
tr::lng_collectible_emoji(tr::now),
|
||||
QString(),
|
||||
0, // count
|
||||
SetFlag::Special,
|
||||
TimeId(0))).first;
|
||||
}
|
||||
return it->second.get();
|
||||
}
|
||||
|
||||
void Stickers::specialSetReceived(
|
||||
uint64 setId,
|
||||
const QString &setTitle,
|
||||
|
|
|
@ -65,6 +65,9 @@ public:
|
|||
// For setting up megagroup sticker set.
|
||||
static constexpr auto MegagroupSetId = 0xFFFFFFFFFFFFFFEFULL;
|
||||
|
||||
// For collectible emoji statuses.
|
||||
static constexpr auto CollectibleSetId = 0xFFFFFFFFFFFFFFF8ULL;
|
||||
|
||||
void notifyUpdated(StickersType type);
|
||||
[[nodiscard]] rpl::producer<StickersType> updated() const;
|
||||
[[nodiscard]] rpl::producer<> updated(StickersType type) const;
|
||||
|
@ -244,6 +247,8 @@ public:
|
|||
[[nodiscard]] auto getEmojiListFromSet(not_null<DocumentData*> document)
|
||||
-> std::optional<std::vector<not_null<EmojiPtr>>>;
|
||||
|
||||
[[nodiscard]] not_null<StickersSet*> collectibleSet();
|
||||
|
||||
not_null<StickersSet*> feedSet(const MTPStickerSet &data);
|
||||
not_null<StickersSet*> feedSet(const MTPStickerSetCovered &data);
|
||||
not_null<StickersSet*> feedSetFull(const MTPDmessages_stickerSet &data);
|
||||
|
|
|
@ -33,6 +33,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_changes.h"
|
||||
#include "data/data_chat_filters.h"
|
||||
#include "data/data_send_action.h"
|
||||
#include "data/data_star_gift.h"
|
||||
#include "data/data_emoji_statuses.h"
|
||||
#include "data/data_folder.h"
|
||||
#include "data/data_forum.h"
|
||||
#include "data/data_forum_topic.h"
|
||||
|
@ -1300,6 +1302,15 @@ void History::newItemAdded(not_null<HistoryItem*> item) {
|
|||
if (const auto topic = item->topic()) {
|
||||
topic->applyItemAdded(item);
|
||||
}
|
||||
if (const auto media = item->media()) {
|
||||
if (const auto gift = media->gift()) {
|
||||
if (const auto unique = gift->unique.get()) {
|
||||
if (unique->ownerId == session().userPeerId()) {
|
||||
owner().emojiStatuses().refreshCollectibles();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void History::registerClientSideMessage(not_null<HistoryItem*> item) {
|
||||
|
|
|
@ -522,9 +522,7 @@ auto UniqueGiftBg(
|
|||
p.setBrush(Qt::transparent);
|
||||
p.drawRoundedRect(inner, radius, radius);
|
||||
}
|
||||
auto gradient = QRadialGradient(
|
||||
inner.center(),
|
||||
inner.height() / 2);
|
||||
auto gradient = QRadialGradient(inner.center(), inner.height() / 2);
|
||||
gradient.setStops({
|
||||
{ 0., gift->backdrop.centerColor },
|
||||
{ 1., gift->backdrop.edgeColor },
|
||||
|
|
|
@ -1047,7 +1047,7 @@ void Selector::createList() {
|
|||
.show = _show,
|
||||
.mode = _listMode,
|
||||
.paused = _paused ? _paused : [] { return false; },
|
||||
.customRecentList = std::move(recentList),
|
||||
.customRecentList = DocumentListToRecent(recentList),
|
||||
.customRecentFactory = _unifiedFactoryOwner->factory(),
|
||||
.freeEffects = std::move(freeEffects),
|
||||
.st = st,
|
||||
|
|
|
@ -70,7 +70,7 @@ EmojiStatusPanel::~EmojiStatusPanel() {
|
|||
}
|
||||
}
|
||||
|
||||
void EmojiStatusPanel::setChooseFilter(Fn<bool(DocumentId)> filter) {
|
||||
void EmojiStatusPanel::setChooseFilter(Fn<bool(EmojiStatusId)> filter) {
|
||||
_chooseFilter = std::move(filter);
|
||||
}
|
||||
|
||||
|
@ -83,6 +83,7 @@ void EmojiStatusPanel::show(
|
|||
.button = button,
|
||||
.animationSizeTag = animationSizeTag,
|
||||
.ensureAddedEmojiId = controller->session().user()->emojiStatusId(),
|
||||
.withCollectibles = true,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -116,20 +117,14 @@ void EmojiStatusPanel::show(Descriptor &&descriptor) {
|
|||
if (now && !ranges::contains(list, now)) {
|
||||
list.push_back(now);
|
||||
}
|
||||
auto tmp = std::vector<DocumentId>();
|
||||
for (const auto &id : list) {
|
||||
if (id.documentId) { // todo collectibles
|
||||
tmp.push_back(id.documentId);
|
||||
}
|
||||
}
|
||||
_panel->selector()->provideRecentEmoji(tmp);
|
||||
_panel->selector()->provideRecentEmoji(list);
|
||||
};
|
||||
if (descriptor.backgroundEmojiMode) {
|
||||
controller->session().api().peerPhoto().emojiListValue(
|
||||
Api::PeerPhoto::EmojiListType::Background
|
||||
) | rpl::start_with_next([=](std::vector<DocumentId> &&list) {
|
||||
auto tmp = std::vector<EmojiStatusId>();
|
||||
for (const auto &id : list) { // todo collectibles
|
||||
for (const auto &id : list) {
|
||||
tmp.push_back(EmojiStatusId{ .documentId = id });
|
||||
}
|
||||
feed(std::move(tmp));
|
||||
|
@ -203,6 +198,8 @@ void EmojiStatusPanel::create(const Descriptor &descriptor) {
|
|||
using Mode = ChatHelpers::TabbedSelector::Mode;
|
||||
const auto controller = descriptor.controller;
|
||||
const auto body = controller->window().widget()->bodyWidget();
|
||||
auto features = ChatHelpers::ComposeFeatures();
|
||||
features.collectibleStatus = descriptor.withCollectibles;
|
||||
_panel = base::make_unique_q<ChatHelpers::TabbedPanel>(
|
||||
body,
|
||||
controller,
|
||||
|
@ -221,6 +218,7 @@ void EmojiStatusPanel::create(const Descriptor &descriptor) {
|
|||
? Mode::ChannelStatus
|
||||
: Mode::EmojiStatus),
|
||||
.customTextColor = descriptor.customTextColor,
|
||||
.features = features,
|
||||
}));
|
||||
_customTextColor = descriptor.customTextColor;
|
||||
_backgroundEmojiMode = descriptor.backgroundEmojiMode;
|
||||
|
@ -233,7 +231,7 @@ void EmojiStatusPanel::create(const Descriptor &descriptor) {
|
|||
_panel->hide();
|
||||
|
||||
struct Chosen {
|
||||
DocumentId id = 0;
|
||||
EmojiStatusId id;
|
||||
TimeId until = 0;
|
||||
Ui::MessageSendingAnimationFrom animation;
|
||||
};
|
||||
|
@ -246,7 +244,10 @@ void EmojiStatusPanel::create(const Descriptor &descriptor) {
|
|||
auto statusChosen = _panel->selector()->customEmojiChosen(
|
||||
) | rpl::map([=](ChatHelpers::FileChosen data) {
|
||||
return Chosen{
|
||||
.id = data.document->id,
|
||||
.id = {
|
||||
data.collectible ? DocumentId() : data.document->id,
|
||||
data.collectible,
|
||||
},
|
||||
.until = data.options.scheduled,
|
||||
.animation = data.messageSendingFrom,
|
||||
};
|
||||
|
@ -264,8 +265,8 @@ void EmojiStatusPanel::create(const Descriptor &descriptor) {
|
|||
) | rpl::start_with_next([=](const Chosen &chosen) {
|
||||
const auto owner = &controller->session().data();
|
||||
startAnimation(owner, body, chosen.id, chosen.animation);
|
||||
_someCustomChosen.fire({ { chosen.id }, chosen.until });
|
||||
_panel->hideAnimated(); // todo collectibles
|
||||
_someCustomChosen.fire({ chosen.id, chosen.until });
|
||||
_panel->hideAnimated();
|
||||
}, _panel->lifetime());
|
||||
} else {
|
||||
const auto weak = Ui::MakeWeak(_panel.get());
|
||||
|
@ -276,8 +277,8 @@ void EmojiStatusPanel::create(const Descriptor &descriptor) {
|
|||
const auto owner = &controller->session().data();
|
||||
if (weak) {
|
||||
startAnimation(owner, body, chosen.id, chosen.animation);
|
||||
} // todo collectibles
|
||||
owner->emojiStatuses().set({ chosen.id }, chosen.until);
|
||||
}
|
||||
owner->emojiStatuses().set(chosen.id, chosen.until);
|
||||
};
|
||||
|
||||
rpl::merge(
|
||||
|
@ -301,7 +302,7 @@ void EmojiStatusPanel::create(const Descriptor &descriptor) {
|
|||
|
||||
bool EmojiStatusPanel::filter(
|
||||
not_null<Window::SessionController*> controller,
|
||||
DocumentId chosenId) const {
|
||||
EmojiStatusId chosenId) const {
|
||||
if (_chooseFilter) {
|
||||
return _chooseFilter(chosenId);
|
||||
} else if (chosenId && !controller->session().premium()) {
|
||||
|
@ -314,13 +315,16 @@ bool EmojiStatusPanel::filter(
|
|||
void EmojiStatusPanel::startAnimation(
|
||||
not_null<Data::Session*> owner,
|
||||
not_null<Ui::RpWidget*> body,
|
||||
DocumentId statusId,
|
||||
EmojiStatusId statusId,
|
||||
Ui::MessageSendingAnimationFrom from) {
|
||||
if (!_panelButton || !statusId) {
|
||||
return;
|
||||
}
|
||||
const auto documentId = statusId.collectible
|
||||
? statusId.collectible->documentId
|
||||
: statusId.documentId;
|
||||
auto args = Ui::ReactionFlyAnimationArgs{
|
||||
.id = { { statusId } },
|
||||
.id = { { documentId } },
|
||||
.flyIcon = from.frame,
|
||||
.flyFrom = body->mapFromGlobal(from.globalStartGeometry),
|
||||
.forceFirstFrame = _backgroundEmojiMode,
|
||||
|
|
|
@ -40,7 +40,7 @@ public:
|
|||
EmojiStatusPanel();
|
||||
~EmojiStatusPanel();
|
||||
|
||||
void setChooseFilter(Fn<bool(DocumentId)> filter);
|
||||
void setChooseFilter(Fn<bool(EmojiStatusId)> filter);
|
||||
|
||||
void show(
|
||||
not_null<Window::SessionController*> controller,
|
||||
|
@ -56,6 +56,7 @@ public:
|
|||
Fn<QColor()> customTextColor;
|
||||
bool backgroundEmojiMode = false;
|
||||
bool channelStatusMode = false;
|
||||
bool withCollectibles = false;
|
||||
};
|
||||
void show(Descriptor &&descriptor);
|
||||
void repaint();
|
||||
|
@ -74,17 +75,17 @@ private:
|
|||
void create(const Descriptor &descriptor);
|
||||
[[nodiscard]] bool filter(
|
||||
not_null<Window::SessionController*> controller,
|
||||
DocumentId chosenId) const;
|
||||
EmojiStatusId chosenId) const;
|
||||
|
||||
void startAnimation(
|
||||
not_null<Data::Session*> owner,
|
||||
not_null<Ui::RpWidget*> body,
|
||||
DocumentId statusId,
|
||||
EmojiStatusId statusId,
|
||||
Ui::MessageSendingAnimationFrom from);
|
||||
|
||||
base::unique_qptr<ChatHelpers::TabbedPanel> _panel;
|
||||
Fn<QColor()> _customTextColor;
|
||||
Fn<bool(DocumentId)> _chooseFilter;
|
||||
Fn<bool(EmojiStatusId)> _chooseFilter;
|
||||
QPointer<QWidget> _panelButton;
|
||||
std::unique_ptr<Ui::EmojiFlyAnimation> _animation;
|
||||
rpl::event_stream<CustomChosen> _someCustomChosen;
|
||||
|
|
|
@ -243,7 +243,7 @@ EmojiSelector::Selector EmojiSelector::createEmojiList(
|
|||
.show = _controller->uiShow(),
|
||||
.mode = ChatHelpers::EmojiListMode::UserpicBuilder,
|
||||
.paused = [=] { return true; },
|
||||
.customRecentList = _lastRecent,
|
||||
.customRecentList = ChatHelpers::DocumentListToRecent(_lastRecent),
|
||||
.customRecentFactory = [=](DocumentId id, Fn<void()> repaint) {
|
||||
return manager->create(id, std::move(repaint), tag);
|
||||
},
|
||||
|
|
|
@ -618,6 +618,7 @@ storiesEmojiPan: EmojiPan(defaultEmojiPan) {
|
|||
}
|
||||
icons: ComposeIcons {
|
||||
settings: icon {{ "emoji/emoji_settings", storiesComposeGrayIcon }};
|
||||
collectibles: icon {{ "menu/unique", storiesComposeGrayIcon }};
|
||||
|
||||
recent: icon {{ "emoji/emoji_recent", storiesComposeGrayIcon }};
|
||||
recentActive: icon {{ "emoji/emoji_recent", storiesComposeWhiteText }};
|
||||
|
|
|
@ -137,7 +137,8 @@ DocumentData *Document::readFromStreamHelper(
|
|||
|| info->setId == Data::Stickers::CloudRecentSetId
|
||||
|| info->setId == Data::Stickers::CloudRecentAttachedSetId
|
||||
|| info->setId == Data::Stickers::FavedSetId
|
||||
|| info->setId == Data::Stickers::CustomSetId) {
|
||||
|| info->setId == Data::Stickers::CustomSetId
|
||||
|| info->setId == Data::Stickers::CollectibleSetId) {
|
||||
typeOfSet = StickerSetTypeEmpty;
|
||||
}
|
||||
|
||||
|
|
|
@ -2193,7 +2193,8 @@ void Account::writeInstalledStickers() {
|
|||
writeStickerSets(_installedStickersKey, [](const Data::StickersSet &set) {
|
||||
if (set.id == Data::Stickers::CloudRecentSetId
|
||||
|| set.id == Data::Stickers::FavedSetId
|
||||
|| set.id == Data::Stickers::CloudRecentAttachedSetId) {
|
||||
|| set.id == Data::Stickers::CloudRecentAttachedSetId
|
||||
|| set.id == Data::Stickers::CollectibleSetId) {
|
||||
// separate files for them
|
||||
return StickerSetCheckResult::Skip;
|
||||
} else if (set.flags & SetFlag::Special) {
|
||||
|
@ -2220,7 +2221,8 @@ void Account::writeFeaturedStickers() {
|
|||
writeStickerSets(_featuredStickersKey, [](const Data::StickersSet &set) {
|
||||
if (set.id == Data::Stickers::CloudRecentSetId
|
||||
|| set.id == Data::Stickers::FavedSetId
|
||||
|| set.id == Data::Stickers::CloudRecentAttachedSetId) {
|
||||
|| set.id == Data::Stickers::CloudRecentAttachedSetId
|
||||
|| set.id == Data::Stickers::CollectibleSetId) {
|
||||
// separate files for them
|
||||
return StickerSetCheckResult::Skip;
|
||||
} else if ((set.flags & SetFlag::Special)
|
||||
|
|
Loading…
Add table
Reference in a new issue