Support colored emoji statuses.

This commit is contained in:
John Preston 2022-08-31 12:29:09 +04:00
parent 923e725e18
commit 2d07539892
17 changed files with 224 additions and 56 deletions

View file

@ -466,6 +466,8 @@ PRIVATE
data/data_download_manager.h data/data_download_manager.h
data/data_drafts.cpp data/data_drafts.cpp
data/data_drafts.h data/data_drafts.h
data/data_emoji_statuses.cpp
data/data_emoji_statuses.h
data/data_folder.cpp data/data_folder.cpp
data/data_folder.h data/data_folder.h
data/data_file_click_handler.cpp data/data_file_click_handler.cpp

View file

@ -687,6 +687,9 @@ int PeerListRow::paintNameIconGetWidth(
? st::dialogsPremiumIconOver ? st::dialogsPremiumIconOver
: st::dialogsPremiumIcon), : st::dialogsPremiumIcon),
.scam = &(selected ? st::dialogsScamFgOver : st::dialogsScamFg), .scam = &(selected ? st::dialogsScamFgOver : st::dialogsScamFg),
.premiumFg = &(selected
? st::dialogsVerifiedIconBgOver
: st::dialogsVerifiedIconBg),
.preview = st::windowBgOver->c, .preview = st::windowBgOver->c,
.customEmojiRepaint = repaint, .customEmojiRepaint = repaint,
.now = now, .now = now,

View file

@ -435,6 +435,9 @@ EmojiListWidget::EmojiListWidget(
resizeToWidth(width()); resizeToWidth(width());
}, lifetime()); }, lifetime());
if (_mode == Mode::EmojiStatus) {
_emojiStatusColor = std::make_unique<Ui::Text::CustomEmojiColored>();
}
rpl::single( rpl::single(
rpl::empty rpl::empty
) | rpl::then( ) | rpl::then(
@ -443,6 +446,12 @@ EmojiListWidget::EmojiListWidget(
initButton(_add, tr::lng_stickers_featured_add(tr::now), false); initButton(_add, tr::lng_stickers_featured_add(tr::now), false);
initButton(_unlock, tr::lng_emoji_featured_unlock(tr::now), true); initButton(_unlock, tr::lng_emoji_featured_unlock(tr::now), true);
initButton(_restore, tr::lng_emoji_premium_restore(tr::now), true); initButton(_restore, tr::lng_emoji_premium_restore(tr::now), true);
if (const auto status = _emojiStatusColor.get()) {
status->color = anim::color(
st::stickerPanPremium1,
st::stickerPanPremium2,
0.5);
}
}, lifetime()); }, lifetime());
if (!descriptor.customRecentList.empty()) { if (!descriptor.customRecentList.empty()) {
@ -765,10 +774,11 @@ void EmojiListWidget::fillRecent() {
} }
void EmojiListWidget::fillRecentFrom(const std::vector<DocumentId> &list) { void EmojiListWidget::fillRecentFrom(const std::vector<DocumentId> &list) {
Expects(_recent.empty());
const auto test = session().isTestMode(); const auto test = session().isTestMode();
const auto owner = &session().data();
const auto statuses = &owner->emojiStatuses();
const auto manager = &owner->customEmojiManager();
_recent.clear();
_recent.reserve(list.size()); _recent.reserve(list.size());
for (const auto &id : list) { for (const auto &id : list) {
if (!id && _mode == Mode::EmojiStatus) { if (!id && _mode == Mode::EmojiStatus) {
@ -777,7 +787,7 @@ void EmojiListWidget::fillRecentFrom(const std::vector<DocumentId> &list) {
} else { } else {
_recent.push_back({ _recent.push_back({
.custom = resolveCustomRecent(id), .custom = resolveCustomRecent(id),
.id = { RecentEmojiDocument{.id = id, .test = test } }, .id = { RecentEmojiDocument{ .id = id, .test = test } },
}); });
_recentCustomIds.emplace(id); _recentCustomIds.emplace(id);
} }
@ -963,7 +973,21 @@ void EmojiListWidget::drawRecent(
bool paused, bool paused,
int index) { int index) {
_recentPainted = true; _recentPainted = true;
if (const auto emoji = std::get_if<EmojiPtr>(&_recent[index].id.data)) { auto &recent = _recent[index];
if (const auto custom = recent.custom) {
position += _innerPosition + _customPosition;
const auto paintContext = Ui::Text::CustomEmoji::Context{
.preview = st::windowBgRipple->c,
.colored = _emojiStatusColor.get(),
.size = QSize(_customSingleSize, _customSingleSize),
.now = now,
.scale = context.progress,
.position = position,
.paused = paused,
.scaled = context.expanding,
};
custom->paint(p, paintContext);
} else if (const auto emoji = std::get_if<EmojiPtr>(&recent.id.data)) {
if (_mode == Mode::EmojiStatus) { if (_mode == Mode::EmojiStatus) {
position += QPoint( position += QPoint(
(_singleSize.width() - st::stickersPremium.width()) / 2, (_singleSize.width() - st::stickersPremium.width()) / 2,
@ -973,18 +997,6 @@ void EmojiListWidget::drawRecent(
} else { } else {
drawEmoji(p, context, position, *emoji); drawEmoji(p, context, position, *emoji);
} }
} else if (const auto custom = _recent[index].custom) {
position += _innerPosition + _customPosition;
const auto paintContext = Ui::Text::CustomEmoji::Context{
.preview = st::windowBgRipple->c,
.size = QSize(_customSingleSize, _customSingleSize),
.now = now,
.scale = context.progress,
.position = position,
.paused = paused,
.scaled = context.expanding,
};
custom->paint(p, paintContext);
} else { } else {
Unexpected("Empty custom emoji in EmojiListWidget::drawRecent."); Unexpected("Empty custom emoji in EmojiListWidget::drawRecent.");
} }
@ -1013,9 +1025,12 @@ void EmojiListWidget::drawCustom(
int set, int set,
int index) { int index) {
position += _innerPosition + _customPosition; position += _innerPosition + _customPosition;
_custom[set].painted = true; auto &custom = _custom[set];
_custom[set].list[index].custom->paint(p, { custom.painted = true;
auto &entry = custom.list[index];
entry.custom->paint(p, {
.preview = st::windowBgRipple->c, .preview = st::windowBgRipple->c,
.colored = _emojiStatusColor.get(),
.size = QSize(_customSingleSize, _customSingleSize), .size = QSize(_customSingleSize, _customSingleSize),
.now = now, .now = now,
.scale = context.progress, .scale = context.progress,

View file

@ -37,6 +37,10 @@ namespace Ui::Emoji {
enum class Section; enum class Section;
} // namespace Ui::Emoji } // namespace Ui::Emoji
namespace Ui::Text {
struct CustomEmojiColored;
} // namespace Ui::Text
namespace Ui::CustomEmoji { namespace Ui::CustomEmoji {
class Loader; class Loader;
class Instance; class Instance;
@ -294,6 +298,7 @@ private:
void displaySet(uint64 setId); void displaySet(uint64 setId);
void removeSet(uint64 setId); void removeSet(uint64 setId);
void refreshColoredStatuses();
void initButton(RightButton &button, const QString &text, bool gradient); void initButton(RightButton &button, const QString &text, bool gradient);
[[nodiscard]] std::unique_ptr<Ui::RippleAnimation> createButtonRipple( [[nodiscard]] std::unique_ptr<Ui::RippleAnimation> createButtonRipple(
int section); int section);
@ -328,6 +333,7 @@ private:
std::vector<RecentOne> _recent; std::vector<RecentOne> _recent;
base::flat_set<DocumentId> _recentCustomIds; base::flat_set<DocumentId> _recentCustomIds;
base::flat_set<uint64> _repaintsScheduled; base::flat_set<uint64> _repaintsScheduled;
std::unique_ptr<Ui::Text::CustomEmojiColored> _emojiStatusColor;
bool _recentPainted = false; bool _recentPainted = false;
QVector<EmojiPtr> _emoji[kEmojiSectionCount]; QVector<EmojiPtr> _emoji[kEmojiSectionCount];
std::vector<CustomSet> _custom; std::vector<CustomSet> _custom;

View file

@ -6,10 +6,12 @@ For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/ */
#include "data/data_emoji_statuses.h" #include "data/data_emoji_statuses.h"
//
#include "main/main_session.h" #include "main/main_session.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_document.h"
#include "data/stickers/data_stickers.h"
#include "base/timer_rpl.h" #include "base/timer_rpl.h"
#include "base/call_delayed.h" #include "base/call_delayed.h"
#include "apiwrap.h" #include "apiwrap.h"

View file

@ -8,6 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/stickers/data_custom_emoji.h" #include "data/stickers/data_custom_emoji.h"
#include "chat_helpers/stickers_emoji_pack.h" #include "chat_helpers/stickers_emoji_pack.h"
#include "main/main_account.h"
#include "main/main_app_config.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "data/data_document.h" #include "data/data_document.h"
@ -78,7 +80,7 @@ public:
SizeTag tag, SizeTag tag,
int sizeOverride); int sizeOverride);
[[nodiscard]] bool resolving() const; [[nodiscard]] DocumentData *document() const;
void resolved(not_null<DocumentData*> document); void resolved(not_null<DocumentData*> document);
QString entityData() override; QString entityData() override;
@ -154,12 +156,16 @@ CustomEmojiLoader::CustomEmojiLoader(
&& sizeOverride <= std::numeric_limits<ushort>::max()); && sizeOverride <= std::numeric_limits<ushort>::max());
} }
bool CustomEmojiLoader::resolving() const { DocumentData *CustomEmojiLoader::document() const {
return v::is<Resolve>(_state); return v::match(_state, [](const Resolve &) {
return (DocumentData*)nullptr;
}, [](const auto &data) {
return data.document.get();
});
} }
void CustomEmojiLoader::resolved(not_null<DocumentData*> document) { void CustomEmojiLoader::resolved(not_null<DocumentData*> document) {
Expects(resolving()); Expects(v::is<Resolve>(_state));
auto requested = std::move(v::get<Resolve>(_state).requested); auto requested = std::move(v::get<Resolve>(_state).requested);
_state = Lookup{ document }; _state = Lookup{ document };
@ -385,6 +391,22 @@ Ui::CustomEmoji::Preview CustomEmojiLoader::preview() {
CustomEmojiManager::CustomEmojiManager(not_null<Session*> owner) CustomEmojiManager::CustomEmojiManager(not_null<Session*> owner)
: _owner(owner) : _owner(owner)
, _repaintTimer([=] { invokeRepaints(); }) { , _repaintTimer([=] { invokeRepaints(); }) {
const auto appConfig = &owner->session().account().appConfig();
appConfig->value(
) | rpl::take_while([=] {
return !_coloredSetId;
}) | rpl::start_with_next([=] {
const auto setId = appConfig->get<QString>(
"default_emoji_statuses_stickerset_id",
QString()).toULongLong();
if (setId) {
_coloredSetId = setId;
auto pending = base::take(_coloredSetPending);
for (const auto &instance : pending[setId]) {
instance->setColored();
}
}
}, _lifetime);
} }
CustomEmojiManager::~CustomEmojiManager() = default; CustomEmojiManager::~CustomEmojiManager() = default;
@ -405,12 +427,20 @@ std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
Ui::CustomEmoji::RepaintRequest request) { Ui::CustomEmoji::RepaintRequest request) {
repaintLater(instance, request); repaintLater(instance, request);
}; };
auto [loader, setId] = factory();
i = instances.emplace( i = instances.emplace(
documentId, documentId,
std::make_unique<Ui::CustomEmoji::Instance>(Loading{ std::make_unique<Ui::CustomEmoji::Instance>(Loading{
factory(), std::move(loader),
prepareNonExactPreview(documentId, tag, sizeOverride) prepareNonExactPreview(documentId, tag, sizeOverride)
}, std::move(repaint))).first; }, std::move(repaint))).first;
if (_coloredSetId) {
if (_coloredSetId == setId) {
i->second->setColored();
}
} else if (setId) {
_coloredSetPending[setId].emplace(i->second.get());
}
} else if (!i->second->hasImagePreview()) { } else if (!i->second->hasImagePreview()) {
auto preview = prepareNonExactPreview(documentId, tag, sizeOverride); auto preview = prepareNonExactPreview(documentId, tag, sizeOverride);
if (preview.isImage()) { if (preview.isImage()) {
@ -466,7 +496,7 @@ std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
SizeTag tag, SizeTag tag,
int sizeOverride) { int sizeOverride) {
return create(documentId, std::move(update), tag, sizeOverride, [&] { return create(documentId, std::move(update), tag, sizeOverride, [&] {
return createLoader(documentId, tag, sizeOverride); return createLoaderWithSetId(documentId, tag, sizeOverride);
}); });
} }
@ -476,7 +506,7 @@ std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
SizeTag tag, SizeTag tag,
int sizeOverride) { int sizeOverride) {
return create(document->id, std::move(update), tag, sizeOverride, [&] { return create(document->id, std::move(update), tag, sizeOverride, [&] {
return createLoader(document, tag, sizeOverride); return createLoaderWithSetId(document, tag, sizeOverride);
}); });
} }
@ -517,19 +547,43 @@ std::unique_ptr<Ui::CustomEmoji::Loader> CustomEmojiManager::createLoader(
not_null<DocumentData*> document, not_null<DocumentData*> document,
SizeTag tag, SizeTag tag,
int sizeOverride) { int sizeOverride) {
return std::make_unique<CustomEmojiLoader>(document, tag, sizeOverride); return createLoaderWithSetId(document, tag, sizeOverride).loader;
} }
std::unique_ptr<Ui::CustomEmoji::Loader> CustomEmojiManager::createLoader( std::unique_ptr<Ui::CustomEmoji::Loader> CustomEmojiManager::createLoader(
DocumentId documentId, DocumentId documentId,
SizeTag tag, SizeTag tag,
int sizeOverride) { int sizeOverride) {
return createLoaderWithSetId(documentId, tag, sizeOverride).loader;
}
auto CustomEmojiManager::createLoaderWithSetId(
not_null<DocumentData*> document,
SizeTag tag,
int sizeOverride
) -> LoaderWithSetId {
const auto sticker = document->sticker();
return {
std::make_unique<CustomEmojiLoader>(document, tag, sizeOverride),
sticker ? sticker->set.id : uint64()
};
}
auto CustomEmojiManager::createLoaderWithSetId(
DocumentId documentId,
SizeTag tag,
int sizeOverride
) -> LoaderWithSetId {
auto result = std::make_unique<CustomEmojiLoader>( auto result = std::make_unique<CustomEmojiLoader>(
_owner, _owner,
CustomEmojiId{ .id = documentId }, CustomEmojiId{ .id = documentId },
tag, tag,
sizeOverride); sizeOverride);
if (result->resolving()) { if (const auto document = result->document()) {
if (const auto sticker = document->sticker()) {
return { std::move(result), sticker->set.id };
}
} else {
const auto i = SizeIndex(tag); const auto i = SizeIndex(tag);
_loaders[i][documentId].push_back(base::make_weak(result.get())); _loaders[i][documentId].push_back(base::make_weak(result.get()));
_pendingForRequest.emplace(documentId); _pendingForRequest.emplace(documentId);
@ -537,8 +591,7 @@ std::unique_ptr<Ui::CustomEmoji::Loader> CustomEmojiManager::createLoader(
crl::on_main(this, [=] { request(); }); crl::on_main(this, [=] { request(); });
} }
} }
return { std::move(result), uint64() };
return result;
} }
QString CustomEmojiManager::lookupSetName(uint64 setId) { QString CustomEmojiManager::lookupSetName(uint64 setId) {
@ -564,27 +617,9 @@ void CustomEmojiManager::request() {
)).done([=](const MTPVector<MTPDocument> &result) { )).done([=](const MTPVector<MTPDocument> &result) {
for (const auto &entry : result.v) { for (const auto &entry : result.v) {
const auto document = _owner->processDocument(entry); const auto document = _owner->processDocument(entry);
const auto id = document->id; fillColoredFlags(document);
for (auto &loaders : _loaders) { processLoaders(document);
if (const auto list = loaders.take(id)) { processListeners(document);
for (const auto &weak : *list) {
if (const auto strong = weak.get()) {
strong->resolved(document);
}
}
}
}
if (const auto listeners = _resolvers.take(id)) {
for (const auto &listener : *listeners) {
const auto i = _listeners.find(listener);
if (i != end(_listeners) && i->second.remove(id)) {
if (i->second.empty()) {
_listeners.erase(i);
}
listener->customEmojiResolveDone(document);
}
}
}
requestSetFor(document); requestSetFor(document);
} }
requestFinished(); requestFinished();
@ -594,6 +629,53 @@ void CustomEmojiManager::request() {
}).send(); }).send();
} }
void CustomEmojiManager::fillColoredFlags(not_null<DocumentData*> document) {
const auto id = document->id;
const auto sticker = document->sticker();
const auto setId = sticker ? sticker->set.id : uint64();
if (!setId || (_coloredSetId && setId != _coloredSetId)) {
return;
}
for (auto &instances : _instances) {
const auto i = instances.find(id);
if (i != end(instances)) {
if (setId == _coloredSetId) {
i->second->setColored();
} else {
_coloredSetPending[setId].emplace(i->second.get());
}
}
}
}
void CustomEmojiManager::processLoaders(not_null<DocumentData*> document) {
const auto id = document->id;
for (auto &loaders : _loaders) {
if (const auto list = loaders.take(id)) {
for (const auto &weak : *list) {
if (const auto strong = weak.get()) {
strong->resolved(document);
}
}
}
}
}
void CustomEmojiManager::processListeners(not_null<DocumentData*> document) {
const auto id = document->id;
if (const auto listeners = _resolvers.take(id)) {
for (const auto &listener : *listeners) {
const auto i = _listeners.find(listener);
if (i != end(_listeners) && i->second.remove(id)) {
if (i->second.empty()) {
_listeners.erase(i);
}
listener->customEmojiResolveDone(document);
}
}
}
}
void CustomEmojiManager::requestSetFor(not_null<DocumentData*> document) { void CustomEmojiManager::requestSetFor(not_null<DocumentData*> document) {
const auto sticker = document->sticker(); const auto sticker = document->sticker();
if (!sticker || !sticker->set.id) { if (!sticker || !sticker->set.id) {

View file

@ -84,6 +84,19 @@ private:
crl::time when = 0; crl::time when = 0;
std::vector<base::weak_ptr<Ui::CustomEmoji::Instance>> instances; std::vector<base::weak_ptr<Ui::CustomEmoji::Instance>> instances;
}; };
struct LoaderWithSetId {
std::unique_ptr<Ui::CustomEmoji::Loader> loader;
uint64 setId = 0;
};
[[nodiscard]] LoaderWithSetId createLoaderWithSetId(
not_null<DocumentData*> document,
SizeTag tag,
int sizeOverride = 0);
[[nodiscard]] LoaderWithSetId createLoaderWithSetId(
DocumentId documentId,
SizeTag tag,
int sizeOverride = 0);
void request(); void request();
void requestFinished(); void requestFinished();
@ -92,6 +105,9 @@ private:
Ui::CustomEmoji::RepaintRequest request); Ui::CustomEmoji::RepaintRequest request);
void scheduleRepaintTimer(); void scheduleRepaintTimer();
void invokeRepaints(); void invokeRepaints();
void fillColoredFlags(not_null<DocumentData*> document);
void processLoaders(not_null<DocumentData*> document);
void processListeners(not_null<DocumentData*> document);
void requestSetFor(not_null<DocumentData*> document); void requestSetFor(not_null<DocumentData*> document);
[[nodiscard]] Ui::CustomEmoji::Preview prepareNonExactPreview( [[nodiscard]] Ui::CustomEmoji::Preview prepareNonExactPreview(
@ -126,14 +142,23 @@ private:
not_null<Listener*>, not_null<Listener*>,
base::flat_set<DocumentId>> _listeners; base::flat_set<DocumentId>> _listeners;
base::flat_set<DocumentId> _pendingForRequest; base::flat_set<DocumentId> _pendingForRequest;
base::flat_map<
uint64,
base::flat_set<
not_null<Ui::CustomEmoji::Instance*>>> _coloredSetPending;
mtpRequestId _requestId = 0; mtpRequestId _requestId = 0;
uint64 _coloredSetId = 0;
base::flat_map<crl::time, RepaintBunch> _repaints; base::flat_map<crl::time, RepaintBunch> _repaints;
crl::time _repaintNext = 0; crl::time _repaintNext = 0;
base::Timer _repaintTimer; base::Timer _repaintTimer;
bool _repaintTimerScheduled = false; bool _repaintTimerScheduled = false;
bool _requestSetsScheduled = false; bool _requestSetsScheduled = false;
rpl::lifetime _lifetime;
}; };
[[nodiscard]] int FrameSizeFromTag(CustomEmojiManager::SizeTag tag); [[nodiscard]] int FrameSizeFromTag(CustomEmojiManager::SizeTag tag);

View file

@ -828,6 +828,11 @@ void InnerWidget::paintPeerSearchResult(
: selected : selected
? &st::dialogsScamFgOver ? &st::dialogsScamFgOver
: &st::dialogsScamFg), : &st::dialogsScamFg),
.premiumFg = (active
? &st::dialogsVerifiedIconBgActive
: selected
? &st::dialogsVerifiedIconBgOver
: &st::dialogsVerifiedIconBg),
.preview = (active .preview = (active
? st::dialogsScamFgActive ? st::dialogsScamFgActive
: selected : selected

View file

@ -593,6 +593,11 @@ void paintRow(
: selected : selected
? &st::dialogsScamFgOver ? &st::dialogsScamFgOver
: &st::dialogsScamFg), : &st::dialogsScamFg),
.premiumFg = (active
? &st::dialogsVerifiedIconBgActive
: selected
? &st::dialogsVerifiedIconBgOver
: &st::dialogsVerifiedIconBg),
.preview = (active .preview = (active
? st::dialogsScamFgActive ? st::dialogsScamFgActive
: selected : selected

View file

@ -545,6 +545,7 @@ void TopBarWidget::paintTopBar(Painter &p) {
.verified = &st::dialogsVerifiedIcon, .verified = &st::dialogsVerifiedIcon,
.premium = &st::dialogsPremiumIcon, .premium = &st::dialogsPremiumIcon,
.scam = &st::attentionButtonFg, .scam = &st::attentionButtonFg,
.premiumFg = &st::dialogsVerifiedIconBg,
.preview = st::windowBgOver->c, .preview = st::windowBgOver->c,
.customEmojiRepaint = [=] { update(); }, .customEmojiRepaint = [=] { update(); },
.now = now, .now = now,

View file

@ -23,6 +23,7 @@ InfoToggle {
InfoPeerBadge { InfoPeerBadge {
verified: icon; verified: icon;
premium: icon; premium: icon;
premiumFg: color;
position: point; position: point;
sizeTag: int; sizeTag: int;
} }
@ -316,6 +317,7 @@ infoPremiumStar: icon {{ "profile_premium", profileVerifiedCheckBg }};
infoPeerBadge: InfoPeerBadge { infoPeerBadge: InfoPeerBadge {
verified: infoVerifiedCheck; verified: infoVerifiedCheck;
premium: infoPremiumStar; premium: infoPremiumStar;
premiumFg: profileVerifiedCheckBg;
position: infoVerifiedCheckPosition; position: infoVerifiedCheckPosition;
sizeTag: 1; // Large sizeTag: 1; // Large
} }

View file

@ -122,6 +122,7 @@ void BadgeView::setBadge(Badge badge, DocumentId emojiStatusId) {
_badge = badge; _badge = badge;
_emojiStatusId = emojiStatusId; _emojiStatusId = emojiStatusId;
_emojiStatus = nullptr; _emojiStatus = nullptr;
_emojiStatusColored = nullptr;
_view.destroy(); _view.destroy();
if (_badge == Badge::None) { if (_badge == Badge::None) {
_updated.fire({}); _updated.fire({});
@ -143,14 +144,19 @@ void BadgeView::setBadge(Badge badge, DocumentId emojiStatusId) {
_emojiStatusId, _emojiStatusId,
[raw = _view.data()] { raw->update(); }, [raw = _view.data()] { raw->update(); },
tag); tag);
_emojiStatusColored = std::make_unique<
Ui::Text::CustomEmojiColored
>();
const auto emoji = Data::FrameSizeFromTag(tag) const auto emoji = Data::FrameSizeFromTag(tag)
/ style::DevicePixelRatio(); / style::DevicePixelRatio();
_view->resize(emoji, emoji); _view->resize(emoji, emoji);
_view->paintRequest( _view->paintRequest(
) | rpl::start_with_next([=, check = _view.data()]{ ) | rpl::start_with_next([=, check = _view.data()]{
Painter p(check); Painter p(check);
_emojiStatusColored->color = _st.premiumFg->c;
_emojiStatus->paint(p, { _emojiStatus->paint(p, {
.preview = st::windowBgOver->c, .preview = st::windowBgOver->c,
.colored = _emojiStatusColored.get(),
.now = crl::now(), .now = crl::now(),
.paused = _animationPaused && _animationPaused(), .paused = _animationPaused && _animationPaused(),
}); });

View file

@ -33,6 +33,10 @@ template <typename Widget>
class SlideWrap; class SlideWrap;
} // namespace Ui } // namespace Ui
namespace Ui::Text {
struct CustomEmojiColored;
} // namespace Ui::Text
namespace Info { namespace Info {
class Controller; class Controller;
class Section; class Section;
@ -73,6 +77,7 @@ private:
const not_null<PeerData*> _peer; const not_null<PeerData*> _peer;
DocumentId _emojiStatusId = 0; DocumentId _emojiStatusId = 0;
std::unique_ptr<Ui::Text::CustomEmoji> _emojiStatus; std::unique_ptr<Ui::Text::CustomEmoji> _emojiStatus;
std::unique_ptr<Ui::Text::CustomEmojiColored> _emojiStatusColored;
base::flags<Badge> _allowed; base::flags<Badge> _allowed;
Badge _badge = Badge(); Badge _badge = Badge();
Fn<void()> _premiumClickCallback; Fn<void()> _premiumClickCallback;

View file

@ -186,6 +186,7 @@ settingsInfoNameSkip: -1px;
settingsInfoUploadLeft: 6px; settingsInfoUploadLeft: 6px;
settingsInfoPeerBadge: InfoPeerBadge { settingsInfoPeerBadge: InfoPeerBadge {
premium: icon {{ "dialogs/dialogs_premium", dialogsVerifiedIconBg }}; premium: icon {{ "dialogs/dialogs_premium", dialogsVerifiedIconBg }};
premiumFg: dialogsVerifiedIconBg;
sizeTag: 0; // Normal sizeTag: 0; // Normal
} }

View file

@ -169,9 +169,12 @@ int PeerBadge::drawGetWidth(
} }
if (!_emojiStatus) { if (!_emojiStatus) {
_emojiStatus = std::make_unique<EmojiStatus>(); _emojiStatus = std::make_unique<EmojiStatus>();
const auto size = st::emojiSize * 1.; const auto size = st::emojiSize;
const auto emoji = Ui::Text::AdjustCustomEmojiSize(st::emojiSize); const auto emoji = Ui::Text::AdjustCustomEmojiSize(size);
_emojiStatus->skip = (st::emojiSize - emoji) / 2; _emojiStatus->skip = (size - emoji) / 2;
_emojiStatus->colored = std::make_unique<
Ui::Text::CustomEmojiColored
>();
} }
if (_emojiStatus->id != id) { if (_emojiStatus->id != id) {
auto &manager = peer->session().data().customEmojiManager(); auto &manager = peer->session().data().customEmojiManager();
@ -180,8 +183,10 @@ int PeerBadge::drawGetWidth(
id, id,
descriptor.customEmojiRepaint); descriptor.customEmojiRepaint);
} }
_emojiStatus->colored->color = (*descriptor.premiumFg)->c;
_emojiStatus->emoji->paint(p, { _emojiStatus->emoji->paint(p, {
.preview = descriptor.preview, .preview = descriptor.preview,
.colored = _emojiStatus->colored.get(),
.now = descriptor.now, .now = descriptor.now,
.position = QPoint( .position = QPoint(
iconx - 2 * _emojiStatus->skip, iconx - 2 * _emojiStatus->skip,

View file

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace Ui::Text { namespace Ui::Text {
class CustomEmoji; class CustomEmoji;
struct CustomEmojiColored;
} // namespace Ui::Text } // namespace Ui::Text
namespace Ui { namespace Ui {
@ -41,6 +42,7 @@ public:
const style::icon *verified = nullptr; const style::icon *verified = nullptr;
const style::icon *premium = nullptr; const style::icon *premium = nullptr;
const style::color *scam = nullptr; const style::color *scam = nullptr;
const style::color *premiumFg = nullptr;
QColor preview; QColor preview;
Fn<void()> customEmojiRepaint; Fn<void()> customEmojiRepaint;
crl::time now = 0; crl::time now = 0;
@ -58,6 +60,7 @@ private:
struct EmojiStatus { struct EmojiStatus {
DocumentId id = 0; DocumentId id = 0;
std::unique_ptr<Ui::Text::CustomEmoji> emoji; std::unique_ptr<Ui::Text::CustomEmoji> emoji;
std::unique_ptr<Ui::Text::CustomEmojiColored> colored;
int skip = 0; int skip = 0;
}; };
std::unique_ptr<EmojiStatus> _emojiStatus; std::unique_ptr<EmojiStatus> _emojiStatus;

@ -1 +1 @@
Subproject commit 6dc6309269beb64a69e3184b671e030a2969f00e Subproject commit 51657b3c8a643c9ca2721029fd48f63390417042