2
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-08-22 02:07:24 +00:00

Get rid of registerImageEmoji/registerInternalEmoji.

This commit is contained in:
John Preston 2025-08-04 22:27:08 +04:00
parent b876605e93
commit b4272c306d
56 changed files with 402 additions and 720 deletions

View File

@ -1116,8 +1116,16 @@ moderateBoxExpandInnerSkip: 2px;
moderateBoxExpandFont: font(11px);
moderateBoxExpandToggleSize: 4px;
moderateBoxExpandToggleFourStrokes: 3px;
moderateBoxExpandIcon: icon{{ "info/edit/expand_arrow_small-flip_vertical", windowActiveTextFg }};
moderateBoxExpandIconDown: icon{{ "info/edit/expand_arrow_small", windowActiveTextFg }};
moderateBoxExpandIcon: IconEmoji{
icon: icon{{ "info/edit/expand_arrow_small-flip_vertical", windowActiveTextFg }};
padding: margins(-2px, -1px, 0px, 0px);
useIconColor: true;
}
moderateBoxExpandIconDown: IconEmoji{
icon: icon{{ "info/edit/expand_arrow_small", windowActiveTextFg }};
padding: margins(-2px, -1px, 0px, 0px);
useIconColor: true;
}
moderateBoxDividerLabel: FlatLabel(boxDividerLabel) {
palette: TextPalette(defaultTextPalette) {
selectLinkFg: windowActiveTextFg;

View File

@ -403,22 +403,10 @@ void CreateModerateMessagesBox(
const auto container = wrap->entity();
wrap->toggle(false, anim::type::instant);
const auto session = &participants.front()->session();
const auto emojiMargin = QMargins(
-st::moderateBoxExpandInnerSkip,
-st::moderateBoxExpandInnerSkip / 2,
0,
0);
const auto emojiUp = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::moderateBoxExpandIcon,
emojiMargin,
false));
const auto emojiDown = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::moderateBoxExpandIconDown,
emojiMargin,
false));
const auto emojiUp = Ui::Text::IconEmoji(
&st::moderateBoxExpandIcon);
const auto emojiDown = Ui::Text::IconEmoji(
&st::moderateBoxExpandIconDown);
auto label = object_ptr<Ui::FlatLabel>(
inner,
@ -463,9 +451,7 @@ void CreateModerateMessagesBox(
Ui::Text::WithEntities);
}) | rpl::flatten_latest(
) | rpl::start_with_next([=](const TextWithEntities &text) {
raw->setMarkedText(
Ui::Text::Link(text, u"internal:"_q),
Core::TextContext({ .session = session }));
raw->setMarkedText(Ui::Text::Link(text, u"internal:"_q));
}, label->lifetime());
Ui::AddSkip(inner);

View File

@ -15,7 +15,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/background_box.h"
#include "boxes/stickers_box.h"
#include "chat_helpers/compose/compose_show.h"
#include "core/ui_integration.h" // TextContext
#include "data/stickers/data_custom_emoji.h"
#include "data/stickers/data_stickers.h"
#include "data/data_changes.h"
@ -164,7 +163,6 @@ private:
void updateText();
const uint32 _level;
const TextWithEntities _icon;
const Ui::Text::MarkedContext _context;
Ui::Text::String _text;
bool _minimal = false;
@ -460,22 +458,12 @@ LevelBadge::LevelBadge(
uint32 level,
not_null<Main::Session*> session)
: Ui::RpWidget(parent)
, _level(level)
, _icon(Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::settingsLevelBadgeLock,
QMargins(0, st::settingsLevelBadgeLockSkip, 0, 0),
false)))
, _context(Core::TextContext({
.session = session,
.repaint = [this] { update(); },
})) {
, _level(level) {
updateText();
}
void LevelBadge::updateText() {
auto text = _icon;
text.append(' ');
auto text = Ui::Text::IconEmoji(&st::settingsLevelBadgeLock).append(' ');
if (!_minimal) {
text.append(tr::lng_boost_level(
tr::now,
@ -490,7 +478,7 @@ void LevelBadge::updateText() {
st,
text,
kMarkupTextOptions,
_context);
Ui::Text::MarkedContext{ .repaint = [=] { update(); } });
const auto &padding = st::settingsColorSamplePadding;
QWidget::resize(
_text.maxWidth() + rect::m::sum::h(padding),

View File

@ -29,6 +29,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h"
#include "history/history_item_helpers.h" // GetErrorForSending.
#include "history/view/history_view_group_call_bar.h" // GenerateUserpics...
#include "info/channel_statistics/earn/earn_icons.h"
#include "lang/lang_keys.h"
#include "main/main_session.h"
#include "qr/qr_generate.h"
@ -42,6 +43,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/controls/userpic_button.h"
#include "ui/painter.h"
#include "ui/rect.h"
#include "ui/text/custom_emoji_helper.h"
#include "ui/text/format_values.h"
#include "ui/text/text_utilities.h"
#include "ui/toast/toast.h"
@ -247,6 +249,9 @@ private:
const Role _role = Role::Joined;
rpl::variable<LinkData> _data;
Ui::Text::CustomEmojiHelper _emojiHelper;
TextWithEntities _creditsEmoji;
base::unique_qptr<Ui::PopupMenu> _menu;
rpl::event_stream<Processed> _processed;
@ -408,6 +413,8 @@ Controller::Controller(
const auto current = _data.current();
_link = current.link;
_revoked = current.revoked;
_creditsEmoji = _emojiHelper.paletteDependent(
Ui::Earn::IconCreditsEmoji());
}
rpl::producer<LinkData> Controller::dataValue() const {
@ -725,7 +732,7 @@ void Controller::setupAboveJoinedWidget() {
? tr::lng_group_invite_subscription_info_title(
tr::now,
lt_emoji,
session().data().customEmojiManager().creditsEmoji(),
_creditsEmoji,
lt_price,
{ QString::number(current.subscription.credits) },
lt_multiplier,
@ -736,15 +743,12 @@ void Controller::setupAboveJoinedWidget() {
: tr::lng_group_invite_subscription_info_title_none(
tr::now,
lt_emoji,
session().data().customEmojiManager().creditsEmoji(),
_creditsEmoji,
lt_price,
{ QString::number(current.subscription.credits) },
Ui::Text::WithEntities),
kMarkupTextOptions,
Core::TextContext({
.session = &session(),
.repaint = [=] { widget->update(); },
}));
_emojiHelper.context([=] { widget->update(); }));
auto &lifetime = widget->lifetime();
const auto rateValue = lifetime.make_state<rpl::variable<float64>>(
session().credits().rateValue(_peer));
@ -991,11 +995,11 @@ void Controller::rowClicked(not_null<PeerListRow*> row) {
tr::lng_credits_subscription_subtitle(
tr::now,
lt_emoji,
session->data().customEmojiManager().creditsEmoji(),
_creditsEmoji,
lt_cost,
{ QString::number(data.subscription.credits) },
Ui::Text::WithEntities),
Core::TextContext({ .session = session }));
_emojiHelper.context());
const auto subtitle2 = box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
box,

View File

@ -886,32 +886,18 @@ rpl::producer<int> AddSlowmodeSlider(
return secondsCount->value();
}
void AddBoostsUnrestrictLabels(
not_null<Ui::VerticalLayout*> container,
not_null<Main::Session*> session) {
void AddBoostsUnrestrictLabels(not_null<Ui::VerticalLayout*> container) {
const auto labels = container->add(
object_ptr<Ui::FixedHeightWidget>(container, st::normalFont->height),
st::slowmodeLabelsMargin);
const auto manager = &session->data().customEmojiManager();
const auto one = Ui::Text::SingleCustomEmoji(
manager->registerInternalEmoji(
st::boostMessageIcon,
st::boostMessageIconPadding));
const auto many = Ui::Text::SingleCustomEmoji(
manager->registerInternalEmoji(
st::boostsMessageIcon,
st::boostsMessageIconPadding));
const auto context = Core::TextContext({
.session = session,
.customEmojiLoopLimit = 1,
});
const auto one = Ui::Text::IconEmoji(&st::boostMessageIcon);
const auto many = Ui::Text::IconEmoji(&st::boostsMessageIcon);
for (auto i = 0; i != kBoostsUnrestrictValues; ++i) {
const auto label = Ui::CreateChild<Ui::FlatLabel>(
labels,
st::boostsUnrestrictLabel);
label->setMarkedText(
TextWithEntities(i ? many : one).append(QString::number(i + 1)),
context);
TextWithEntities(i ? many : one).append(QString::number(i + 1)));
rpl::combine(
labels->widthValue(),
label->widthValue()
@ -977,7 +963,7 @@ rpl::producer<int> AddBoostsUnrestrictSlider(
const auto inner = outer->entity();
AddBoostsUnrestrictLabels(inner, &peer->session());
AddBoostsUnrestrictLabels(inner);
const auto slider = inner->add(
object_ptr<Ui::MediaSlider>(inner, st::localStorageLimitSlider),

View File

@ -455,7 +455,7 @@ void SendCreditsBox(
lt_count,
rpl::single(form->invoice.amount) | tr::to_count(),
lt_emoji,
rpl::single(CreditsEmojiSmall(session)),
rpl::single(CreditsEmojiSmall()),
Ui::Text::RichLangValue),
state->confirmButtonBusy.value()
) | rpl::map([](TextWithEntities &&text, bool busy) {
@ -502,16 +502,13 @@ void SendCreditsBox(
}
}
TextWithEntities CreditsEmoji(not_null<Main::Session*> session) {
return Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::settingsPremiumIconStar,
QMargins{ 0, -st::moderateBoxExpandInnerSkip, 0, 0 },
true),
TextWithEntities CreditsEmoji() {
return Ui::Text::IconEmoji(
&st::starIconEmojiLarge,
QString(QChar(0x2B50)));
}
TextWithEntities CreditsEmojiSmall(not_null<Main::Session*> session) {
TextWithEntities CreditsEmojiSmall() {
return Ui::Text::IconEmoji(
&st::starIconEmoji,
QString(QChar(0x2B50)));

View File

@ -32,11 +32,9 @@ void SendCreditsBox(
std::shared_ptr<Payments::CreditsFormData> data,
Fn<void()> sent);
[[nodiscard]] TextWithEntities CreditsEmoji(
not_null<Main::Session*> session);
[[nodiscard]] TextWithEntities CreditsEmoji();
[[nodiscard]] TextWithEntities CreditsEmojiSmall(
not_null<Main::Session*> session);
[[nodiscard]] TextWithEntities CreditsEmojiSmall();
not_null<FlatLabel*> SetButtonMarkedLabel(
not_null<RpWidget*> button,

View File

@ -843,9 +843,8 @@ void SendFilesBox::refreshPriceTag() {
QPainter(raw).drawImage(0, 0, _priceTagBg);
}, raw->lifetime());
const auto session = &_show->session();
auto price = _price.value() | rpl::map([=](uint64 amount) {
auto result = Ui::Text::Colorized(Ui::CreditsEmoji(session));
auto result = Ui::Text::Colorized(Ui::CreditsEmoji());
result.append(Lang::FormatCountDecimal(amount));
return result;
});
@ -857,10 +856,10 @@ void SendFilesBox::refreshPriceTag() {
raw,
QString(),
st::paidTagLabel);
std::move(text) | rpl::start_with_next([=](TextWithEntities &&text) {
label->setMarkedText(text, Core::TextContext({
.session = session,
}));
std::move(
text
) | rpl::start_with_next([=](const TextWithEntities &text) {
label->setMarkedText(text);
}, label->lifetime());
label->show();
label->sizeValue() | rpl::start_with_next([=](QSize size) {

View File

@ -54,6 +54,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "history/history.h"
#include "history/history_item.h"
#include "history/history_item_helpers.h"
#include "info/channel_statistics/earn/earn_icons.h"
#include "info/peer_gifts/info_peer_gifts_common.h"
#include "info/profile/info_profile_icon.h"
#include "lang/lang_keys.h"
@ -82,6 +83,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/new_badges.h"
#include "ui/painter.h"
#include "ui/rect.h"
#include "ui/text/custom_emoji_helper.h"
#include "ui/text/format_values.h"
#include "ui/text/text_utilities.h"
#include "ui/toast/toast.h"
@ -1194,8 +1196,9 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
}
[[nodiscard]] Text::String TabTextForPrice(
not_null<Main::Session*> session,
int price) {
int price,
TextWithEntities creditsIcon,
Ui::Text::MarkedContext context) {
const auto simple = [](const QString &text) {
return Text::String(st::semiboldTextStyle, text);
};
@ -1210,13 +1213,12 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
} else if (price == kPriceTabResale) {
return simple(tr::lng_gift_stars_tabs_resale(tr::now));
}
auto &manager = session->data().customEmojiManager();
auto result = Text::String();
result.setMarkedText(
st::semiboldTextStyle,
manager.creditsEmoji().append(QString::number(price)),
creditsIcon.append(QString::number(price)),
kMarkupTextOptions,
Core::TextContext({ .session = session }));
context);
return result;
}
@ -1636,7 +1638,6 @@ struct GiftPriceTabs {
object_ptr<RpWidget> widget;
};
[[nodiscard]] GiftPriceTabs MakeGiftsPriceTabs(
not_null<Window::SessionController*> window,
not_null<PeerData*> peer,
rpl::producer<std::vector<GiftTypeStars>> gifts,
bool hasMyUnique) {
@ -1745,7 +1746,6 @@ struct GiftPriceTabs {
state->priceTab = state->buttons[index].price;
};
const auto session = &peer->session();
state->prices.value(
) | rpl::start_with_next([=](const std::vector<int> &prices) {
auto x = st::giftBoxTabsMargin.left();
@ -1759,12 +1759,18 @@ struct GiftPriceTabs {
currentPrice = kPriceTabAll;
}
state->active = -1;
auto helper = Ui::Text::CustomEmojiHelper();
const auto creditsIcon = helper.paletteDependent(
Ui::Earn::IconCreditsEmoji());
for (auto i = 0, count = int(prices.size()); i != count; ++i) {
const auto price = prices[i];
auto &button = state->buttons[i];
if (button.text.isEmpty() || button.price != price) {
button.price = price;
button.text = TabTextForPrice(session, price);
button.text = TabTextForPrice(
price,
creditsIcon,
helper.context());
}
button.active = (price == currentPrice);
if (button.active) {
@ -2177,7 +2183,6 @@ void SoldOutBox(
void AddUpgradeButton(
not_null<Ui::VerticalLayout*> container,
not_null<Main::Session*> session,
int cost,
not_null<PeerData*> peer,
Fn<void(bool)> toggled,
@ -2190,7 +2195,8 @@ void AddUpgradeButton(
button->toggleOn(rpl::single(false))->toggledValue(
) | rpl::start_with_next(toggled, button->lifetime());
auto star = session->data().customEmojiManager().creditsEmoji();
auto helper = Ui::Text::CustomEmojiHelper();
auto star = helper.paletteDependent(Ui::Earn::IconCreditsEmoji());
const auto label = Ui::CreateChild<Ui::FlatLabel>(
button,
tr::lng_gift_send_unique(
@ -2201,7 +2207,7 @@ void AddUpgradeButton(
Text::WithEntities),
st::boxLabel,
st::defaultPopupMenu,
Core::TextContext({ .session = session }));
helper.context());
label->show();
label->setAttribute(Qt::WA_TransparentForMouseEvents);
button->widthValue() | rpl::start_with_next([=](int outer) {
@ -2355,7 +2361,7 @@ void SendGiftBox(
});
auto cost = state->details.value(
) | rpl::map([session](const GiftDetails &details) {
) | rpl::map([](const GiftDetails &details) {
return v::match(details.descriptor, [&](const GiftTypePremium &data) {
const auto stars = (details.byStars && data.stars)
? data.stars
@ -2363,7 +2369,7 @@ void SendGiftBox(
? data.cost
: 0;
if (stars) {
return CreditsEmojiSmall(session).append(
return CreditsEmojiSmall().append(
Lang::FormatCountDecimal(std::abs(stars)));
}
return TextWithEntities{
@ -2372,7 +2378,7 @@ void SendGiftBox(
}, [&](const GiftTypeStars &data) {
const auto amount = std::abs(data.info.stars)
+ (details.upgraded ? data.info.starsToUpgrade : 0);
return CreditsEmojiSmall(session).append(
return CreditsEmojiSmall().append(
Lang::FormatCountDecimal(amount));
});
});
@ -2448,8 +2454,7 @@ void SendGiftBox(
const auto showing = std::make_shared<bool>();
AddDivider(container);
AddSkip(container);
AddUpgradeButton(container, session, costToUpgrade, peer, [=](
bool on) {
AddUpgradeButton(container, costToUpgrade, peer, [=](bool on) {
auto now = state->details.current();
now.upgraded = on;
state->details = std::move(now);
@ -3027,7 +3032,6 @@ void AddBlock(
state->gifts = GiftsStars(&window->session(), peer);
auto tabs = MakeGiftsPriceTabs(
window,
peer,
state->gifts.value(),
!state->my.list.empty() && !peer->isSelf());
@ -4445,11 +4449,7 @@ void ShowUniqueGiftWearBox(
u"wear_collectibles"_q);
}
});
const auto lock = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::historySendDisabledIcon,
st::giftBoxLockMargins,
true));
const auto lock = Ui::Text::IconEmoji(&st::giftBoxLock);
auto label = rpl::combine(
tr::lng_gift_wear_start(),
Data::AmPremiumValue(&show->session())
@ -4936,7 +4936,6 @@ void UpgradeBox(
box->setStyle(preview ? st::giftBox : st::upgradeGiftBox);
const auto cost = args.cost;
const auto session = &controller->session();
auto buttonText = preview ? tr::lng_box_ok() : rpl::single(QString());
const auto button = box->addButton(std::move(buttonText), [=] {
if (preview) {
@ -4961,7 +4960,8 @@ void UpgradeBox(
UpgradeGift(controller, args.savedId, keepDetails, cost, done);
});
if (!preview) {
auto star = session->data().customEmojiManager().creditsEmoji();
auto helper = Ui::Text::CustomEmojiHelper();
auto star = helper.paletteDependent(Ui::Earn::IconCreditsEmoji());
SetButtonMarkedLabel(
button,
(cost
@ -4972,7 +4972,7 @@ void UpgradeBox(
CreditsAmount{ cost }))),
Ui::Text::WithEntities)
: tr::lng_gift_upgrade_confirm(Ui::Text::WithEntities)),
&controller->session(),
helper.context(),
st::creditsBoxButtonLabel,
&st::giftBox.button.textFg);
}

View File

@ -2232,8 +2232,7 @@ ItemPreview MediaInvoice::toPreview(ToPreviewOptions options) const {
? parent()->translatedText()
: parent()->originalText());
const auto hasMiniImages = !images.empty();
auto nice = Ui::Text::Colorized(
Ui::CreditsEmojiSmall(&parent()->history()->session()));
auto nice = Ui::Text::Colorized(Ui::CreditsEmojiSmall());
nice.append(WithCaptionNotificationText(type, caption, hasMiniImages));
return {
.text = std::move(nice),

View File

@ -16,6 +16,7 @@ struct PremiumSubscriptionOption {
QString costPerMonth;
QString costNoDiscount;
QString costTotal;
QString currency;
QString total;
QString botUrl;
};

View File

@ -41,7 +41,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h"
#include "styles/style_chat.h"
#include "styles/style_chat_helpers.h"
#include "styles/style_credits.h" // giftBoxByStarsStyle
namespace Data {
namespace {
@ -101,10 +100,6 @@ private:
: FrameSizeFromTag(tag);
}
[[nodiscard]] QString InternalPrefix() {
return u"internal:"_q;
}
[[nodiscard]] QString UserpicEmojiPrefix() {
return u"userpic:"_q;
}
@ -570,8 +565,6 @@ std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
const auto original = data.mid(ForceStaticPrefix().size());
return std::make_unique<Ui::Text::FirstFrameEmoji>(
create(original, std::move(update), tag, sizeOverride));
} else if (data.startsWith(InternalPrefix())) {
return internal(data);
} else if (data.startsWith(UserpicEmojiPrefix())) {
const auto ratio = style::DevicePixelRatio();
const auto size = EmojiSizeFromTag(tag) / ratio;
@ -619,26 +612,6 @@ std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
});
}
std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::internal(
QStringView data) {
const auto v = data.mid(InternalPrefix().size()).split(',');
if (v.size() != 5 && v.size() != 1) {
return nullptr;
}
const auto index = v[0].toInt();
Assert(index >= 0 && index < _internalEmoji.size());
auto &info = _internalEmoji[index];
const auto padding = (v.size() == 5)
? QMargins(v[1].toInt(), v[2].toInt(), v[3].toInt(), v[4].toInt())
: QMargins();
return std::make_unique<Ui::CustomEmoji::Internal>(
data.toString(),
info.image,
padding,
info.textColor);
}
std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::userpic(
QStringView data,
Fn<void()> update,
@ -1021,65 +994,6 @@ uint64 CustomEmojiManager::coloredSetId() const {
return _coloredSetId;
}
TextWithEntities CustomEmojiManager::creditsEmoji(QMargins padding) {
return Ui::Text::SingleCustomEmoji(registerInternalEmoji(
u"builtin:credits_emoji"_q,
Ui::GenerateStars(st::normalFont->height, 1),
padding,
false));
}
TextWithEntities CustomEmojiManager::ministarEmoji(QMargins padding) {
return Ui::Text::SingleCustomEmoji(registerInternalEmoji(
u"builtin:ministar_emoji"_q,
Ui::GenerateStars(st::giftBoxByStarsStyle.font->height, 1),
padding,
false));
}
QString CustomEmojiManager::registerInternalEmoji(
const QString &key,
QImage emoji,
QMargins padding,
bool textColor) {
auto i = _imageEmoji.find(key);
if (i == end(_imageEmoji)) {
i = _imageEmoji.emplace(
key,
registerImageEmoji(std::move(emoji), textColor)).first;
}
return i->second + InternalPadding(padding);
}
QString CustomEmojiManager::registerImageEmoji(
QImage emoji,
bool textColor) {
_internalEmoji.push_back({ std::move(emoji), textColor });
return InternalPrefix() + QString::number(_internalEmoji.size() - 1);
}
QString CustomEmojiManager::registerInternalEmoji(
const style::icon &icon,
QMargins padding,
bool textColor) {
const auto i = _iconEmoji.find(&icon);
if (i != end(_iconEmoji)) {
return i->second + InternalPadding(padding);
}
auto image = QImage(
icon.size() * style::DevicePixelRatio(),
QImage::Format_ARGB32_Premultiplied);
image.fill(Qt::transparent);
image.setDevicePixelRatio(style::DevicePixelRatio());
auto p = QPainter(&image);
icon.paint(p, 0, 0, icon.width());
p.end();
const auto result = registerImageEmoji(std::move(image), textColor);
_iconEmoji.emplace(&icon, result);
return result + InternalPadding(padding);
}
[[nodiscard]] QString CustomEmojiManager::peerUserpicEmojiData(
not_null<PeerData*> peer,
QMargins padding,

View File

@ -83,16 +83,6 @@ public:
[[nodiscard]] Main::Session &session() const;
[[nodiscard]] Session &owner() const;
[[nodiscard]] QString registerInternalEmoji(
const QString &key,
QImage emoji,
QMargins padding = {},
bool textColor = true);
[[nodiscard]] QString registerInternalEmoji(
const style::icon &icon,
QMargins padding = {},
bool textColor = true);
[[nodiscard]] QString peerUserpicEmojiData(
not_null<PeerData*> peer,
QMargins padding = {},
@ -101,7 +91,6 @@ public:
[[nodiscard]] uint64 coloredSetId() const;
[[nodiscard]] TextWithEntities creditsEmoji(QMargins padding = {});
[[nodiscard]] TextWithEntities ministarEmoji(QMargins padding = {});
private:
static constexpr auto kSizeCount = int(SizeTag::kCount);
@ -128,7 +117,6 @@ private:
DocumentId documentId,
SizeTag tag,
int sizeOverride = 0);
[[nodiscard]] QString registerImageEmoji(QImage emoji, bool textColor);
void request();
void requestFinished();
@ -154,8 +142,6 @@ private:
SizeTag tag,
int sizeOverride,
LoaderFactory factory);
[[nodiscard]] std::unique_ptr<Ui::Text::CustomEmoji> internal(
QStringView data);
[[nodiscard]] std::unique_ptr<Ui::Text::CustomEmoji> userpic(
QStringView data,
Fn<void()> update,
@ -192,11 +178,6 @@ private:
bool _repaintTimerScheduled = false;
bool _requestSetsScheduled = false;
std::vector<InternalEmojiData> _internalEmoji;
base::flat_map<not_null<const style::icon*>, QString> _iconEmoji;
base::flat_map<QString, QString> _imageEmoji;
#if 0 // inject-to-on_main
crl::time _repaintsLastAdded = 0;
rpl::lifetime _repaintsLifetime;

View File

@ -556,7 +556,10 @@ dialogsMiniForward: DialogsMiniIcon {
skipMedia: 2px;
}
dialogsMiniReplyIcon: icon {{ "mini_forward-flip_horizontal", attentionButtonFg, point(0px, 2px) }};
dialogsMiniReplyIcon: IconEmoji {
icon: icon {{ "mini_forward-flip_horizontal", attentionButtonFg }};
padding: margins(0px, 2px, 0px, 0px);
}
dialogsMiniReplyStory: DialogsMiniIcon {
icon: ThreeStateIcon {
@ -799,8 +802,10 @@ dialogsSearchTagSkip: point(8px, 4px);
dialogsSearchTagBottom: 10px;
dialogsSearchTagLocked: icon{{ "dialogs/mini_tag_lock", lightButtonFgOver }};
dialogsSearchTagPromo: defaultTextStyle;
dialogsSearchTagArrow: icon{{ "dialogs/mini_arrow", windowSubTextFg }};
dialogsSearchTagArrowPadding: margins(-6px, 3px, 0px, 0px);
dialogsSearchTagArrow: IconEmoji {
icon: icon{{ "dialogs/mini_arrow", windowSubTextFg }};
padding: margins(-6px, 3px, 0px, 0px);
}
dialogsSearchTagPromoLeft: 6px;
dialogsSearchTagPromoRight: 1px;
dialogsSearchTagPromoSkip: 6px;

View File

@ -52,24 +52,14 @@ namespace {
});
}
[[nodiscard]] Ui::Text::String FillAdditionalText(
not_null<Data::Session*> owner,
int width) {
auto emoji = Ui::Text::SingleCustomEmoji(
owner->customEmojiManager().registerInternalEmoji(
st::dialogsSearchTagArrow,
st::dialogsSearchTagArrowPadding));
[[nodiscard]] Ui::Text::String FillAdditionalText(int width) {
auto emoji = Ui::Text::IconEmoji(&st::dialogsSearchTagArrow);
auto result = Ui::Text::String();
const auto context = Core::TextContext({
.session = &owner->session(),
.customEmojiLoopLimit = 1,
});
const auto attempt = [&](const auto &phrase) {
result.setMarkedText(
st::dialogsSearchTagPromo,
phrase(tr::now, lt_arrow, emoji, Ui::Text::WithEntities),
kMarkupTextOptions,
context);
kMarkupTextOptions);
return result.maxWidth() < width;
};
if (attempt(tr::lng_add_tag_phrase_long)
@ -230,7 +220,7 @@ void SearchTags::layout() {
if (_tags.size() == 1 && _tags.front().promo) {
_additionalLeft = x - skip.x() + st::dialogsSearchTagPromoSkip;
const auto additionalWidth = _width - _additionalLeft;
_additionalText = FillAdditionalText(_owner, additionalWidth);
_additionalText = FillAdditionalText(additionalWidth);
} else {
_additionalText = {};
}

View File

@ -594,13 +594,9 @@ void PaintRow(
}),
Text::WithEntities);
if (draft && draft->reply) {
auto &data = thread->owner().customEmojiManager();
draftText = Ui::Text::Colorized(
Ui::Text::SingleCustomEmoji(
data.registerInternalEmoji(
st::dialogsMiniReplyIcon,
{},
true))).append(std::move(draftText));
Ui::Text::IconEmoji(&st::dialogsMiniReplyIcon)
).append(std::move(draftText));
}
const auto context = Core::TextContext({
.session = &thread->session(),

View File

@ -47,6 +47,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/controls/swipe_handler.h"
#include "ui/effects/ripple_animation.h"
#include "ui/toast/toast.h"
#include "ui/text/custom_emoji_helper.h"
#include "ui/text/custom_emoji_text_badge.h"
#include "ui/text/text_utilities.h"
#include "ui/widgets/menu/menu_add_action_callback_factory.h"
#include "ui/widgets/buttons.h"
@ -154,34 +156,6 @@ struct EntryMenuDescriptor {
};
}
[[nodiscard]] QImage MakeNewBadgeImage() {
auto text = Ui::Text::String(
st::settingsPremiumNewBadge.style,
tr::lng_premium_summary_new_badge(tr::now));
const auto size = QSize(text.maxWidth(), text.minHeight());
const auto padding = st::settingsPremiumNewBadgePadding;
const auto full = size.grownBy(padding);
const auto ratio = style::DevicePixelRatio();
auto result = QImage(full * ratio, QImage::Format_ARGB32_Premultiplied);
result.setDevicePixelRatio(ratio);
result.fill(Qt::transparent);
auto p = QPainter(&result);
auto hq = PainterHighQualityEnabler(p);
p.setPen(Qt::NoPen);
p.setBrush(st::windowBgActive);
const auto r = padding.left();
p.drawRoundedRect(0, 0, full.width(), full.height(), r, r);
p.setPen(st::windowFgActive);
text.draw(p, { .position = { padding.left(), padding.top() } });
p.end();
return result;
}
void FillEntryMenu(
const Ui::Menu::MenuCallback &add,
EntryMenuDescriptor &&descriptor) {
@ -1453,25 +1427,20 @@ void Suggestions::setupTabs() {
},
};
const auto manager = &_controller->session().data().customEmojiManager();
const auto badgeData = manager->registerInternalEmoji(
u"posts_search_new_badge"_q,
MakeNewBadgeImage(),
st::badgeEmojiMargin,
false);
auto helper = Ui::Text::CustomEmojiHelper();
auto sections = std::vector<TextWithEntities>();
for (const auto key : _tabKeys) {
const auto i = labels.find(key);
Assert(i != end(labels));
auto text = TextWithEntities{ i->second };
if (key.tab == Tab::Posts) {
text.append(' ').append(Ui::Text::SingleCustomEmoji(badgeData));
text.append(' ').append(helper.paletteDependent(
Ui::Text::CustomEmojiTextBadge(
tr::lng_premium_summary_new_badge(tr::now))));
}
sections.push_back(std::move(text));
}
_tabs->setSections(sections, Core::TextContext({
.session = &_controller->session(),
}));
_tabs->setSections(sections, helper.context());
_tabs->sectionActivated(
) | rpl::start_with_next([=](int section) {
Assert(section >= 0 && section < _tabKeys.size());

View File

@ -143,11 +143,10 @@ template <typename T>
}
[[nodiscard]] TextWithEntities AmountAndStarCurrency(
not_null<Main::Session*> session,
int64 amount,
const QString &currency) {
if (currency == Ui::kCreditsCurrency) {
return Ui::CreditsEmojiSmall(session).append(
return Ui::CreditsEmojiSmall().append(
Lang::FormatCountDecimal(std::abs(amount)));
}
return { Ui::FillAmountAndCurrency(amount, currency) };
@ -4602,10 +4601,7 @@ void HistoryItem::createServiceFromMtp(const MTPDmessageService &message) {
payment->recurringInit = data.is_recurring_init();
payment->recurringUsed = data.is_recurring_used();
payment->isCreditsCurrency = (currency == Ui::kCreditsCurrency);
payment->amount = AmountAndStarCurrency(
&_history->session(),
amount,
currency);
payment->amount = AmountAndStarCurrency(amount, currency);
payment->invoiceLink = std::make_shared<LambdaClickHandler>([=](
ClickContext context) {
using namespace Payments;
@ -5037,10 +5033,7 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
: tr::lng_action_payment_bot_done)(
tr::now,
lt_amount,
AmountAndStarCurrency(
&_history->session(),
data.vtotal_amount().v,
qs(data.vcurrency())),
AmountAndStarCurrency(data.vtotal_amount().v, qs(data.vcurrency())),
Ui::Text::WithEntities);
return result;
};
@ -5418,7 +5411,7 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
session->giftBoxStickersPacks().load();
const auto amount = action.vamount().v;
const auto currency = qs(action.vcurrency());
const auto cost = AmountAndStarCurrency(session, amount, currency);
const auto cost = AmountAndStarCurrency(amount, currency);
const auto anonymous = _from->isServiceUser();
if (anonymous) {
result.text = tr::lng_action_gift_received_anonymous(
@ -5645,7 +5638,6 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
const auto isSelf = (_from->id == _from->session().userPeerId());
const auto peer = isSelf ? _history->peer : _from;
const auto cost = AmountAndStarCurrency(
&_history->session(),
action.vamount().value_or_empty(),
qs(action.vcurrency().value_or_empty()));
result.links.push_back(peer->createOpenLink());
@ -5755,7 +5747,7 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
lt_peer,
Ui::Text::Link(refund->peer->name(), 1), // Link 1.
lt_amount,
AmountAndStarCurrency(&_history->session(), amount, currency),
AmountAndStarCurrency(amount, currency),
Ui::Text::WithEntities);
return result;
};
@ -5768,10 +5760,7 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
_history->session().giftBoxStickersPacks().load();
const auto amount = action.vamount().v;
const auto currency = qs(action.vcurrency());
const auto cost = AmountAndStarCurrency(
&_history->session(),
amount,
currency);
const auto cost = AmountAndStarCurrency(amount, currency);
const auto anonymous = _from->isServiceUser();
if (anonymous) {
result.text = tr::lng_action_gift_received_anonymous(
@ -5805,10 +5794,7 @@ void HistoryItem::setServiceMessageByAction(const MTPmessageAction &action) {
_history->session().giftBoxStickersPacks().tonLoad();
const auto amount = action.vamount().v;
const auto currency = qs(action.vcurrency());
const auto cost = AmountAndStarCurrency(
&_history->session(),
amount,
currency);
const auto cost = AmountAndStarCurrency(amount, currency);
const auto anonymous = _from->isServiceUser();
if (anonymous) {
result.text = tr::lng_action_gift_received_anonymous(

View File

@ -55,6 +55,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "support/support_helper.h"
#include "styles/style_boxes.h"
#include "styles/style_chat.h"
#include "styles/style_credits.h"
#include "styles/style_dialogs.h" // dialogsMiniReplyStory.
#include "styles/style_settings.h"
#include "styles/style_widgets.h"
@ -747,11 +748,6 @@ ReplyKeyboard::ReplyKeyboard(
const auto context = _item->fullId();
const auto rowCount = int(markup->data.rows.size());
_rows.reserve(rowCount);
const auto buttonEmoji = Ui::Text::SingleCustomEmoji(
owner->customEmojiManager().registerInternalEmoji(
st::settingsPremiumIconStar,
QMargins(0, -st::moderateBoxExpandInnerSkip, 0, 0),
true));
for (auto i = 0; i != rowCount; ++i) {
const auto &row = markup->data.rows[i];
const auto rowSize = int(row.size());
@ -786,7 +782,8 @@ ReplyKeyboard::ReplyKeyboard(
auto firstPart = true;
for (const auto &part : text.split(QChar(0x2B50))) {
if (!firstPart) {
result.append(buttonEmoji);
result.append(Ui::Text::IconEmoji(
&st::starIconEmojiLarge));
}
result.append(part);
firstPart = false;
@ -805,11 +802,7 @@ ReplyKeyboard::ReplyKeyboard(
button.text.setMarkedText(
_st->textStyle(),
TextUtilities::SingleLine(textWithEntities),
kMarkupTextOptions,
Core::TextContext({
.session = &item->history()->owner().session(),
.repaint = [=] { _st->repaint(item); },
}));
kMarkupTextOptions);
} else {
button.text.setText(
_st->textStyle(),

View File

@ -152,16 +152,17 @@ StarsTonPriceInput AddStarsTonPriceInput(
const auto session = args.session;
const auto added = st::boxRowPadding - st::defaultSubsectionTitlePadding;
const auto manager = &session->data().customEmojiManager();
auto helper = Ui::Text::CustomEmojiHelper();
const auto makeIcon = [&](
not_null<QWidget*> parent,
TextWithEntities text) {
Ui::Text::PaletteDependentEmoji emoji) {
auto text = helper.paletteDependent(std::move(emoji));
return Ui::CreateChild<Ui::FlatLabel>(
parent,
rpl::single(text),
rpl::single(std::move(text)),
st::defaultFlatLabel,
st::defaultPopupMenu,
Core::TextContext({ .session = session }));
helper.context());
};
const auto starsWrap = container->add(
@ -193,7 +194,9 @@ StarsTonPriceInput AddStarsTonPriceInput(
: QString()),
args.starsMax);
const auto starsField = ownedStarsField.data();
const auto starsIcon = makeIcon(starsField, manager->creditsEmoji());
const auto starsIcon = makeIcon(
starsField,
Ui::Earn::IconCreditsEmoji());
starsFieldWrap->widthValue() | rpl::start_with_next([=](int width) {
starsIcon->move(st::starsFieldIconPosition);
@ -241,14 +244,7 @@ StarsTonPriceInput AddStarsTonPriceInput(
? (args.price.whole() * Ui::kNanosInOne + args.price.nano())
: 0)));
const auto tonField = ownedTonField.data();
const auto tonIcon = makeIcon(tonField, Ui::Text::SingleCustomEmoji(
manager->registerInternalEmoji(
u"ton_price_field_emoji"_q,
Ui::Earn::IconCurrencyColored(
st::tonFieldIconSize,
st::currencyFg->c),
st::channelEarnCurrencyCommonMargins,
false)));
const auto tonIcon = makeIcon(tonField, Ui::Earn::IconCurrencyEmoji());
tonFieldWrap->widthValue() | rpl::start_with_next([=](int width) {
tonIcon->move(st::tonFieldIconPosition);
@ -652,15 +648,11 @@ void ChooseSuggestPriceBox(
priceInput.submits
) | rpl::start_with_next(state->save, box->lifetime());
auto helper = Ui::Text::CustomEmojiHelper();
const auto button = box->addButton(rpl::single(QString()), state->save);
const auto coloredTonIcon = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
u"ton_price_suggest_save"_q,
Ui::Earn::IconCurrencyColored(
st::tonFieldIconSize,
st::currencyFg->c),
st::suggestPriceTonIconMargins));
button->setContext(Core::TextContext({ .session = &peer->session() }));
const auto coloredTonIcon = helper.paletteDependent(
Ui::Earn::IconCurrencyEmoji());
button->setContext(helper.context());
button->setText(state->price.value(
) | rpl::map([=](CreditsAmount price) {
if (args.mode == SuggestMode::Change) {
@ -901,20 +893,15 @@ void SuggestOptions::updateTexts() {
}
TextWithEntities SuggestOptions::composeText() const {
const auto manager = &_peer->owner().customEmojiManager();
const auto top = st::giftBoxByStarsStarTop;
auto helper = Ui::Text::CustomEmojiHelper();
const auto amount = _values.price().ton()
? Ui::Text::SingleCustomEmoji(
manager->registerInternalEmoji(
u"ton_price_preview_emoji"_q,
Ui::Earn::IconCurrencyColored(
st::suggestBarTonIconSize,
st::currencyFg->c),
st::suggestBarTonIconMargins,
false)).append(
Lang::FormatCreditsAmountDecimal(_values.price()))
: manager->ministarEmoji({ 0, top, 0, 0 }).append(
Lang::FormatCreditsAmountDecimal(_values.price()));
? helper.paletteDependent(Ui::Earn::IconCurrencyEmoji({
.size = st::suggestBarTonIconSize,
.margin = st::suggestBarTonIconMargins,
})).append(Lang::FormatCreditsAmountDecimal(_values.price()))
: helper.paletteDependent(
Ui::Earn::IconCreditsEmojiSmall()
).append(Lang::FormatCreditsAmountDecimal(_values.price()));
const auto date = langDateTime(base::unixtime::parse(_values.date));
if (!_values.price() && !_values.date) {
return tr::lng_suggest_bar_text(tr::now, Ui::Text::WithEntities);

View File

@ -576,30 +576,19 @@ void Message::refreshRightBadge() {
_rightBadgeHasBoosts = 1;
const auto many = (boosts > 1);
const auto &icon = many
? st::boostsMessageIcon
: st::boostMessageIcon;
const auto padding = many
? st::boostsMessageIconPadding
: st::boostMessageIconPadding;
const auto owner = &item->history()->owner();
auto added = Ui::Text::SingleCustomEmoji(
owner->customEmojiManager().registerInternalEmoji(icon, padding)
auto added = Ui::Text::IconEmoji(many
? &st::boostsMessageIcon
: &st::boostMessageIcon
).append(many ? QString::number(boosts) : QString());
badge.append(' ').append(Ui::Text::Colorized(added, 1));
}
if (badge.empty()) {
_rightBadge.clear();
} else {
const auto context = Core::TextContext({
.session = &item->history()->session(),
.customEmojiLoopLimit = 1,
});
_rightBadge.setMarkedText(
st::defaultTextStyle,
badge,
Ui::NameTextOptions(),
context);
Ui::NameTextOptions());
}
}

View File

@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/chat/chat_style.h"
#include "ui/effects/ripple_animation.h"
#include "ui/effects/spoiler_mess.h"
#include "ui/text/custom_emoji_helper.h"
#include "ui/text/text_options.h"
#include "ui/text/text_utilities.h"
#include "ui/painter.h"
@ -103,23 +104,6 @@ constexpr auto kNonExpandedLinesLimit = 5;
return style::colorizeImage(result, white);
}
[[nodiscard]] TextWithEntities TaskDoneIcon(
not_null<Main::Session*> session) {
return Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
u"task_done_reply_preview"_q,
MakeTaskDoneImage(),
QMargins(0, st::lineWidth, st::lineWidth, 0)));
}
[[nodiscard]] TextWithEntities TaskIcon(not_null<Main::Session*> session) {
return Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
u"task_not_done_reply_preview"_q,
MakeTaskImage(),
QMargins(0, st::lineWidth, st::lineWidth, 0)));
}
} // namespace
void ValidateBackgroundEmoji(
@ -322,13 +306,23 @@ void Reply::update(
&& !fields.quote.empty();
_hasQuoteIcon = hasQuoteIcon ? 1 : 0;
const auto session = &view->history()->session();
const auto repaint = [=] { item->customEmojiRepaint(); };
auto helper = Ui::Text::CustomEmojiHelper(Core::TextContext({
.session = &view->history()->session(),
.repaint = repaint,
}));
const auto text = (!_displaying && data->unavailable())
? TextWithEntities()
: task
? Ui::Text::Colorized(task->completionDate
? TaskDoneIcon(session)
: TaskIcon(session)).append(task->text)
? helper.image({
.image = MakeTaskDoneImage(),
.margin = QMargins(0, st::lineWidth, st::lineWidth, 0),
})
: helper.image({
.image = MakeTaskImage(),
.margin = QMargins(0, st::lineWidth, st::lineWidth, 0),
})).append(task->text)
: (message && (fields.quote.empty() || !fields.manualQuote))
? message->inReplyText()
: !fields.quote.empty()
@ -345,16 +339,11 @@ void Reply::update(
.ignoreTopic = true,
}).text
: TextWithEntities();
const auto repaint = [=] { item->customEmojiRepaint(); };
const auto context = Core::TextContext({
.session = &view->history()->session(),
.repaint = repaint,
});
_text.setMarkedText(
st::defaultTextStyle,
text,
_multiline ? Ui::ItemTextDefaultOptions() : Ui::DialogTextOptions(),
context);
helper.context());
updateName(view, data);
@ -550,15 +539,16 @@ void Reply::updateName(
: 0;
auto nameFull = TextWithEntities();
if (displayAsExternal && !groupNameAdded && !fields.storyId) {
nameFull.append(PeerEmoji(history, sender));
nameFull.append(PeerEmoji(sender));
}
nameFull.append(name);
if (groupNameAdded) {
nameFull.append(' ').append(PeerEmoji(history, externalPeer));
nameFull.append(' ').append(PeerEmoji(externalPeer));
nameFull.append(externalPeer->name());
} else if (originalNameAdded) {
nameFull.append(' ').append(ForwardEmoji(&history->owner()));
nameFull.append(forwarded->originalSender
nameFull.append(' ').append(
st::historyReplyForward
).append(forwarded->originalSender
? forwarded->originalSender->name()
: forwarded->originalHiddenSenderInfo->name);
}
@ -936,34 +926,16 @@ void Reply::stopLastRipple() {
}
}
TextWithEntities Reply::PeerEmoji(
not_null<History*> history,
PeerData *peer) {
return PeerEmoji(&history->owner(), peer);
}
TextWithEntities Reply::PeerEmoji(
not_null<Data::Session*> owner,
PeerData *peer) {
TextWithEntities Reply::PeerEmoji(PeerData *peer) {
using namespace std;
const auto icon = !peer
? pair(&st::historyReplyUser, st::historyReplyUserPadding)
? &st::historyReplyUser
: peer->isBroadcast()
? pair(&st::historyReplyChannel, st::historyReplyChannelPadding)
? &st::historyReplyChannel
: (peer->isChannel() || peer->isChat())
? pair(&st::historyReplyGroup, st::historyReplyGroupPadding)
: pair(&st::historyReplyUser, st::historyReplyUserPadding);
return Ui::Text::SingleCustomEmoji(
owner->customEmojiManager().registerInternalEmoji(
*icon.first,
icon.second));
}
TextWithEntities Reply::ForwardEmoji(not_null<Data::Session*> owner) {
return Ui::Text::SingleCustomEmoji(
owner->customEmojiManager().registerInternalEmoji(
st::historyReplyForward,
st::historyReplyForwardPadding));
? &st::historyReplyGroup
: &st::historyReplyUser;
return Ui::Text::IconEmoji(icon);
}
TextWithEntities Reply::ComposePreviewName(
@ -996,11 +968,11 @@ TextWithEntities Reply::ComposePreviewName(
auto nameFull = TextWithEntities();
using namespace HistoryView;
if (displayAsExternal && !groupNameAdded) {
nameFull.append(Reply::PeerEmoji(history, sender));
nameFull.append(Reply::PeerEmoji(sender));
}
nameFull.append(shorten ? sender->shortName() : sender->name());
if (groupNameAdded) {
nameFull.append(' ').append(Reply::PeerEmoji(history, toPeer));
nameFull.append(' ').append(Reply::PeerEmoji(toPeer));
nameFull.append(toPeer->name());
}
return (quote

View File

@ -99,14 +99,7 @@ public:
return _link;
}
[[nodiscard]] static TextWithEntities PeerEmoji(
not_null<History*> history,
PeerData *peer);
[[nodiscard]] static TextWithEntities PeerEmoji(
not_null<Data::Session*> owner,
PeerData *peer);
[[nodiscard]] static TextWithEntities ForwardEmoji(
not_null<Data::Session*> owner);
[[nodiscard]] static TextWithEntities PeerEmoji(PeerData *peer);
[[nodiscard]] static TextWithEntities ComposePreviewName(
not_null<History*> history,
not_null<HistoryItem*> to,

View File

@ -241,14 +241,12 @@ void Media::drawPurchasedTag(
if (!amount) {
return;
}
const auto session = &item->history()->session();
auto text = Ui::Text::Colorized(Ui::CreditsEmojiSmall(session));
auto text = Ui::Text::Colorized(Ui::CreditsEmojiSmall());
text.append(Lang::FormatCountDecimal(amount));
purchased->text.setMarkedText(
st::defaultTextStyle,
text,
kMarkupTextOptions,
Core::TextContext({ .session = session }));
kMarkupTextOptions);
}
const auto st = context.st;
@ -403,8 +401,7 @@ void Media::drawSpoilerTag(
tr::lng_sensitive_tag(tr::now));
iconSkip = st::mediaMenuIconStealth.width() * 1.4;
} else {
const auto session = &history()->session();
auto price = Ui::Text::Colorized(Ui::CreditsEmoji(session));
auto price = Ui::Text::Colorized(Ui::CreditsEmoji());
price.append(Lang::FormatCountDecimal(tag->price));
text.setMarkedText(
st::semiboldTextStyle,
@ -413,8 +410,7 @@ void Media::drawSpoilerTag(
lt_price,
price,
Ui::Text::WithEntities),
kMarkupTextOptions,
Core::TextContext({ .session = session }));
kMarkupTextOptions);
}
const auto width = iconSkip + text.maxWidth();
const auto inner = QRect(0, 0, width, text.minHeight());

View File

@ -238,12 +238,7 @@ constexpr auto kSponsoredUserpicLines = 2;
? tr::lng_view_button_collection(tr::now)
: QString());
if (page->iv) {
const auto manager = &page->owner().customEmojiManager();
const auto &icon = st::historyIvIcon;
const auto padding = st::historyIvIconPadding;
return Ui::Text::SingleCustomEmoji(
manager->registerInternalEmoji(icon, padding)
).append(text);
return Ui::Text::IconEmoji(&st::historyIvIcon).append(text);
}
return { text };
}

View File

@ -601,8 +601,7 @@ object_ptr<Ui::BoxContent> JoinStarRefBox(
Ui::AddSkip(box->verticalLayout(), st::defaultVerticalListSkip * 3);
if (const auto average = program.revenuePerUser) {
const auto layout = box->verticalLayout();
const auto session = &initialRecipient->session();
auto text = Ui::Text::Colorized(Ui::CreditsEmoji(session));
auto text = Ui::Text::Colorized(Ui::CreditsEmoji());
text.append(Lang::FormatCreditsAmountRounded(average));
layout->add(
object_ptr<Ui::FlatLabel>(
@ -613,8 +612,7 @@ object_ptr<Ui::BoxContent> JoinStarRefBox(
Ui::Text::Wrapped(text, EntityType::Bold)),
Ui::Text::WithEntities),
st::starrefRevenueText,
st::defaultPopupMenu,
Core::TextContext({ .session = session })),
st::defaultPopupMenu),
st::boxRowPadding);
Ui::AddSkip(layout, st::defaultVerticalListSkip);
}

View File

@ -148,4 +148,8 @@ botEarnLockedButtonLabel: FlatLabel(channelEarnOverviewMajorLabel) {
font: font(10px semibold);
}
}
botEarnButtonLockMargins: margins(-2px, 4px, 0px, 0px);
botEarnButtonLock: IconEmoji {
icon: icon{{ "chat/mini_lock", premiumButtonFg }};
padding: margins(-2px, 4px, 0px, 0px);
}

View File

@ -7,9 +7,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "info/channel_statistics/earn/earn_icons.h"
#include "ui/effects/credits_graphics.h"
#include "ui/effects/premium_graphics.h"
#include "ui/text/text_custom_emoji.h"
#include "ui/text/custom_emoji_instance.h"
#include "ui/rect.h"
#include "styles/style_credits.h"
#include "styles/style_menu_icons.h"
#include "styles/style_widgets.h"
#include "styles/style_info.h" // infoIconReport.
@ -144,9 +146,38 @@ QImage MenuIconCredits() {
std::unique_ptr<Ui::Text::CustomEmoji> MakeCurrencyIconEmoji(
const style::font &font,
const QColor &c) {
return std::make_unique<Ui::Text::StaticCustomEmoji>(
IconCurrencyColored(font, c),
u"currency_icon:%1:%2"_q.arg(font->height).arg(c.name()));
return std::make_unique<Ui::CustomEmoji::Internal>(
u"currency_icon:%1:%2"_q.arg(font->height).arg(c.name()),
IconCurrencyColored(font, c));
}
Ui::Text::PaletteDependentEmoji IconCreditsEmoji(
IconDescriptor descriptor) {
return { .factory = [=] {
return Ui::GenerateStars(
descriptor.size ? descriptor.size : st::normalFont->height,
1);
}, .margin = descriptor.margin.value_or(QMargins()) };
}
Ui::Text::PaletteDependentEmoji IconCurrencyEmoji(
IconDescriptor descriptor) {
return { .factory = [=] {
return IconCurrencyColored(
descriptor.size ? descriptor.size : st::earnTonIconSize,
st::currencyFg->c);
}, .margin = descriptor.margin.value_or(st::earnTonIconMargin) };
}
Ui::Text::PaletteDependentEmoji IconCreditsEmojiSmall() {
return IconCreditsEmoji({
.size = st::giftBoxByStarsStyle.font->height,
.margin = QMargins{ 0, st::giftBoxByStarsStarTop, 0, 0 },
});
}
Ui::Text::PaletteDependentEmoji IconCurrencyEmojiSmall() {
return IconCreditsEmoji({});
}
} // namespace Ui::Earn

View File

@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "ui/text/custom_emoji_helper.h"
namespace Ui::Text {
class CustomEmoji;
} // namespace Ui::Text
@ -26,4 +28,16 @@ std::unique_ptr<Ui::Text::CustomEmoji> MakeCurrencyIconEmoji(
const style::font &font,
const QColor &c);
struct IconDescriptor {
int size = 0;
std::optional<QMargins> margin;
};
[[nodiscard]] Ui::Text::PaletteDependentEmoji IconCreditsEmoji(
IconDescriptor descriptor = {});
[[nodiscard]] Ui::Text::PaletteDependentEmoji IconCurrencyEmoji(
IconDescriptor descriptor = {});
[[nodiscard]] Ui::Text::PaletteDependentEmoji IconCreditsEmojiSmall();
[[nodiscard]] Ui::Text::PaletteDependentEmoji IconCurrencyEmojiSmall();
} // namespace Ui::Earn

View File

@ -418,43 +418,30 @@ void InnerWidget::fill() {
std::optional<bool> isIn,
std::optional<QMargins> margins) {
const auto &st = label->st();
auto icon = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
(!isIn
? u"stats_row_ton_some"_q
: (*isIn)
? u"stats_row_ton_in"_q
: u"stats_row_ton_out"_q),
Ui::Earn::IconCurrencyColored(
st.style.font,
!isIn
? st::currencyFg->c
: (*isIn)
? st::boxTextFgGood->c
: st::menuIconAttentionColor->c),
margins ? *margins : st::channelEarnCurrencyCommonMargins,
false));
const auto prepended = !isIn
? TextWithEntities()
: TextWithEntities::Simple((*isIn) ? QChar('+') : kMinus);
std::move(
value
) | rpl::start_with_next([=](CreditsAmount v) {
auto helper = Ui::Text::CustomEmojiHelper();
auto icon = helper.paletteDependent({ .factory = [=] {
return Ui::Earn::IconCurrencyColored(
st.style.font,
!isIn
? st::currencyFg->c
: (*isIn)
? st::boxTextFgGood->c
: st::menuIconAttentionColor->c);
}, .margin = margins
? *margins
: st::channelEarnCurrencyCommonMargins });
label->setMarkedText(
base::duplicate(prepended).append(icon).append(MajorPart(v)),
Core::TextContext({ .session = session }));
helper.context());
}, label->lifetime());
};
const auto bigCurrencyIcon = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
u"stats_row_ton_big"_q,
Ui::Earn::IconCurrencyColored(
st::boxTitle.style.font,
st::currencyFg->c),
st::channelEarnCurrencyLearnMargins,
false));
const auto arrow = Ui::Text::IconEmoji(&st::textMoreIconEmoji);
const auto addAboutWithLearn = [&](const tr::phrase<lngtag_link> &text) {
auto label = Ui::CreateLabelWithCustomEmoji(
@ -475,6 +462,14 @@ void InnerWidget::fill() {
_show->showBox(Box([=](not_null<Ui::GenericBox*> box) {
box->setNoContentMargin(true);
auto emojiHelper = Ui::Text::CustomEmojiHelper();
const auto bigCurrencyIcon = emojiHelper.paletteDependent({
.factory = [=] {
return Ui::Earn::IconCurrencyColored(
st::boxTitle.style.font,
st::currencyFg->c);
}, .margin = st::channelEarnCurrencyLearnMargins });
const auto content = box->verticalLayout().get();
Ui::AddSkip(content);
@ -586,7 +581,7 @@ void InnerWidget::fill() {
Ui::Text::Link(bigCurrencyIcon, 1)),
Ui::Text::RichLangValue
),
Core::TextContext({ .session = session }),
emojiHelper.context(),
st::boxTitle)))->entity();
const auto diamonds = l->lifetime().make_state<int>(0);
l->setLink(1, std::make_shared<LambdaClickHandler>([=] {

View File

@ -430,6 +430,10 @@ infoEditContactCover: InfoProfileCover(infoProfileCover) {
}
infoEditContactPersonalLeft: 6px;
infoRatingDeductedBadge: RoundButton(customEmojiTextBadge) {
textBg: windowSubTextFg;
}
infoProfileInaccessibleUserpic: icon {{ "info/inaccessible_userpic", historyPeerUserpicFg }};
infoVerifiedCheckPosition: point(4px, 2px);
@ -1275,3 +1279,6 @@ collectionEditMenuToggle: IconButton(infoTopBarMenu) {
rippleAreaSize: 40px;
ripple: defaultRippleAnimationBgOver;
}
earnTonIconSize: 16px;
earnTonIconMargin: margins(0px, 2px, 0px, 0px);

View File

@ -742,6 +742,10 @@ Delegate::Delegate(not_null<Main::Session*> session, GiftButtonMode mode)
st::giftBoxHiddenMark,
RectPart::Center))
, _mode(mode) {
_ministarEmoji = _emojiHelper.paletteDependent(
Ui::Earn::IconCreditsEmojiSmall());
_starEmoji = _emojiHelper.paletteDependent(
Ui::Earn::IconCreditsEmoji());
}
Delegate::Delegate(Delegate &&other) = default;
@ -749,7 +753,7 @@ Delegate::Delegate(Delegate &&other) = default;
Delegate::~Delegate() = default;
TextWithEntities Delegate::star() {
return _session->data().customEmojiManager().creditsEmoji();
return _starEmoji;
}
TextWithEntities Delegate::monostar() {
@ -761,13 +765,11 @@ TextWithEntities Delegate::monoton() {
}
TextWithEntities Delegate::ministar() {
const auto owner = &_session->data();
const auto top = st::giftBoxByStarsStarTop;
return owner->customEmojiManager().ministarEmoji({ 0, top, 0, 0 });
return _ministarEmoji;
}
Ui::Text::MarkedContext Delegate::textContext() {
return Core::TextContext({ .session = _session });
return _emojiHelper.context();
}
QSize Delegate::buttonSize() {

View File

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_star_gift.h"
#include "ui/abstract_button.h"
#include "ui/effects/premium_stars_colored.h"
#include "ui/text/custom_emoji_helper.h"
#include "ui/text/text.h"
class StickerPremiumMark;
@ -237,6 +238,9 @@ private:
QSize _single;
QImage _bg;
GiftButtonMode _mode = GiftButtonMode::Full;
Ui::Text::CustomEmojiHelper _emojiHelper;
TextWithEntities _ministarEmoji;
TextWithEntities _starEmoji;
};

View File

@ -855,6 +855,7 @@ rpl::producer<CreditsAmount> AddCurrencyAction(
not_null<Controller*> controller) {
struct State final {
rpl::variable<CreditsAmount> balance;
Ui::Text::CustomEmojiHelper helper;
};
const auto state = wrap->lifetime().make_state<State>();
const auto parentController = controller->parentController();
@ -906,14 +907,11 @@ rpl::producer<CreditsAmount> AddCurrencyAction(
const auto &st = st::infoSharedMediaButton;
const auto button = wrapButton->entity();
const auto name = Ui::CreateChild<Ui::FlatLabel>(button, st.rightLabel);
const auto icon = Ui::Text::SingleCustomEmoji(
user->owner().customEmojiManager().registerInternalEmoji(
u"profile_ton_section_icon"_q,
Ui::Earn::IconCurrencyColored(
st.rightLabel.style.font,
st.rightLabel.textFg->c),
st::channelEarnCurrencyCommonMargins,
false));
const auto icon = state->helper.paletteDependent({ .factory = [=] {
return Ui::Earn::IconCurrencyColored(
st.rightLabel.style.font,
st.rightLabel.textFg->c);
}, .margin = st::channelEarnCurrencyCommonMargins });
name->show();
rpl::combine(
button->widthValue(),
@ -932,10 +930,7 @@ rpl::producer<CreditsAmount> AddCurrencyAction(
.append(QChar(' '))
.append(Info::ChannelEarn::MajorPart(balance))
.append(Info::ChannelEarn::MinorPart(balance)),
Core::TextContext({
.session = &user->session(),
.repaint = [=] { name->update(); },
}));
state->helper.context());
name->resizeToNaturalWidth(available);
name->moveToRight(st::settingsButtonRightSkip, st.padding.top());
}, name->lifetime());
@ -988,7 +983,10 @@ rpl::producer<CreditsAmount> AddCreditsAction(
const auto &st = st::infoSharedMediaButton;
const auto button = wrapButton->entity();
const auto name = Ui::CreateChild<Ui::FlatLabel>(button, st.rightLabel);
const auto icon = user->owner().customEmojiManager().creditsEmoji();
auto helper = Ui::Text::CustomEmojiHelper();
const auto icon = helper.paletteDependent(Ui::Earn::IconCreditsEmoji());
const auto context = helper.context([=] { name->update(); });
name->show();
rpl::combine(
button->widthValue(),
@ -1006,10 +1004,7 @@ rpl::producer<CreditsAmount> AddCreditsAction(
base::duplicate(icon)
.append(QChar(' '))
.append(Lang::FormatCreditsAmountDecimal(balance)),
Core::TextContext({
.session = &user->session(),
.repaint = [=] { name->update(); },
}));
context);
name->resizeToNaturalWidth(available);
name->moveToRight(st::settingsButtonRightSkip, st.padding.top());
}, name->lifetime());

View File

@ -1215,13 +1215,13 @@ CreditsController::CreditsController(CreditsDescriptor d)
if (data.startsWith(u"ton"_q)) {
const auto in = data.split(u":"_q)[1].startsWith(u"in"_q);
return std::make_unique<Ui::Text::ShiftedEmoji>(
std::make_unique<Ui::Text::StaticCustomEmoji>(
std::make_unique<Ui::CustomEmoji::Internal>(
data.toString(),
Ui::Earn::IconCurrencyColored(
st::tonFieldIconSize,
in
? st::boxTextFgGood->c
: st::menuIconAttentionColor->c),
data.toString()),
: st::menuIconAttentionColor->c)),
QPoint(0, st::lineWidth));
}
const auto desc = DeserializeCreditsRowDescriptionData(

View File

@ -276,10 +276,7 @@ struct MadePrivacyBadge {
not_null<Data::Session*> owner,
PeerData *peer,
QString name) {
auto result = Ui::Text::SingleCustomEmoji(
owner->customEmojiManager().registerInternalEmoji(
st::storiesRepostIcon,
st::storiesRepostIconPadding));
auto result = Ui::Text::IconEmoji(&st::storiesRepostIcon);
if (peer) {
result.append(Ui::Text::SingleCustomEmoji(
owner->customEmojiManager().peerUserpicEmojiData(

View File

@ -240,7 +240,7 @@ void RepostView::recountDimensions() {
}
auto nameFull = TextWithEntities();
nameFull.append(HistoryView::Reply::PeerEmoji(owner, _sourcePeer));
nameFull.append(HistoryView::Reply::PeerEmoji(_sourcePeer));
nameFull.append(name);
auto context = Core::TextContext({
.session = &_story->session(),

View File

@ -1074,8 +1074,10 @@ storiesRepostSimpleStyle: QuoteStyle(defaultQuoteStyle) {
outline: 0px;
radius: 10px;
}
storiesRepostIcon: icon {{ "mediaview/mini_repost", windowFg }};
storiesRepostIconPadding: margins(0px, 4px, 2px, 0px);
storiesRepostIcon: IconEmoji{
icon: icon {{ "mediaview/mini_repost", windowFg }};
padding: margins(0px, 4px, 2px, 0px);
}
storiesRepostUserpicPadding: margins(0px, 1px, 4px, 0px);
mediaviewSponsoredButton: RoundButton(defaultActiveButton) {

View File

@ -176,19 +176,13 @@ void ShowPaidReactionDetails(
auto submitText = [=](rpl::producer<int> amount) {
auto nice = std::move(amount) | rpl::map([=](int count) {
return Ui::CreditsEmojiSmall(session).append(
return Ui::CreditsEmojiSmall().append(
Lang::FormatCountDecimal(count));
});
return tr::lng_paid_react_send(
lt_price,
std::move(nice),
Ui::Text::RichLangValue
) | rpl::map([=](TextWithEntities &&text) {
return Ui::TextWithContext{
.text = std::move(text),
.context = Core::TextContext({ .session = session }),
};
});
Ui::Text::RichLangValue);
};
auto top = std::vector<Ui::PaidReactionTop>();
const auto add = [&](const Data::MessageReactionsTopPaid &entry) {

View File

@ -545,10 +545,8 @@ void PaidReactionsBox(
st::creditsBoxButtonLabel);
args.submit(
state->chosen.value()
) | rpl::start_with_next([=](const TextWithContext &text) {
buttonLabel->setMarkedText(
text.text,
text.context);
) | rpl::start_with_next([=](const TextWithEntities &text) {
buttonLabel->setMarkedText(text);
}, buttonLabel->lifetime());
buttonLabel->setTextColorOverride(
box->getDelegate()->style().button.textFg->c);

View File

@ -23,11 +23,6 @@ class BoxContent;
class GenericBox;
class DynamicImage;
struct TextWithContext {
TextWithEntities text;
Text::MarkedContext context;
};
struct PaidReactionTop {
QString name;
std::shared_ptr<DynamicImage> photo;
@ -45,7 +40,7 @@ struct PaidReactionBoxArgs {
not_null<Main::Session*> session;
QString channel;
Fn<rpl::producer<TextWithContext>(rpl::producer<int> amount)> submit;
Fn<rpl::producer<TextWithEntities>(rpl::producer<int> amount)> submit;
rpl::producer<CreditsAmount> balanceValue;
Fn<void(int, uint64)> send;
};

View File

@ -141,7 +141,6 @@ settingsPremiumNewBadge: FlatLabel(defaultFlatLabel) {
}
settingsPremiumNewBadgePosition: point(4px, 1px);
settingsPremiumNewBadgePadding: margins(4px, 1px, 4px, 1px);
badgeEmojiMargin: margins(0px, 2px, 0px, 0px);
settingsTTLChatsOff: icon {{ "settings/ttl/autodelete_off", windowSubTextFg }};
settingsTTLChatsOn: icon {{ "settings/ttl/autodelete_on", windowActiveTextFg }};
@ -598,8 +597,11 @@ settingsColorButton: SettingsButton(settingsButton) {
settingsColorRadioMargin: 17px;
settingsColorRadioSkip: 13px;
settingsColorRadioStroke: 2px;
settingsLevelBadgeLock: icon {{ "chat/mini_lock", premiumButtonFg }};
settingsLevelBadgeLockSkip: 4px;
settingsLevelBadgeLock: IconEmoji{
icon: icon {{ "chat/mini_lock", premiumButtonFg }};
padding: margins(0px, 4px, 0px, 0px);
useIconColor: true;
}
messagePrivacyTopSkip: 8px;
messagePrivacyRadioSkip: 6px;

View File

@ -38,6 +38,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/effects/premium_graphics.h"
#include "ui/effects/premium_top_bar.h"
#include "ui/layers/generic_box.h"
#include "ui/text/custom_emoji_instance.h"
#include "ui/text/format_values.h"
#include "ui/painter.h"
#include "ui/rect.h"
@ -444,9 +445,9 @@ void Credits::setupContent() {
p.drawEllipse(r);
icon.paintInCenter(p, r, st::windowBgActive->c);
}
return std::make_unique<Ui::Text::StaticCustomEmoji>(
std::move(image),
u"topup_button"_q);
return std::make_unique<Ui::CustomEmoji::Internal>(
u"topup_button"_q,
std::move(image));
};
return { .customEmojiFactory = std::move(customEmojiFactory) };
}());
@ -489,11 +490,11 @@ void Credits::setupContent() {
auto customEmojiFactory = [=](const auto &...) {
return std::make_unique<Ui::Text::ShiftedEmoji>(
isCurrency
? std::make_unique<Ui::Text::StaticCustomEmoji>(
? std::make_unique<Ui::CustomEmoji::Internal>(
u"currency_icon:%1"_q.arg(height),
Ui::Earn::IconCurrencyColored(
st::tonFieldIconSize,
st::currencyFg->c),
u"currency_icon:%1"_q.arg(height))
st::currencyFg->c))
: Ui::MakeCreditsIconEmoji(height, 1),
isCurrency
? QPoint(0, st::lineWidth * 2)

View File

@ -77,6 +77,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/layers/generic_box.h"
#include "ui/painter.h"
#include "ui/rect.h"
#include "ui/text/custom_emoji_helper.h"
#include "ui/text/format_values.h"
#include "ui/text/text_utilities.h"
#include "ui/toast/toast.h"
@ -469,15 +470,15 @@ SubscriptionRightLabel PaintSubscriptionRightLabelCallback(
not_null<Main::Session*> session,
const style::PeerListItem &st,
int amount) {
auto helper = Ui::Text::CustomEmojiHelper();
auto starIcon = helper.paletteDependent(
Ui::Earn::IconCreditsEmoji());
const auto text = std::make_shared<Ui::Text::String>();
text->setMarkedText(
st::semiboldTextStyle,
TextWithEntities()
.append(session->data().customEmojiManager().creditsEmoji())
.append(QChar::Space)
.append(Lang::FormatCountDecimal(amount)),
starIcon.append(' ').append(Lang::FormatCountDecimal(amount)),
kMarkupTextOptions,
Core::TextContext({ .session = session }));
helper.context());
const auto &font = text->style()->font;
const auto &statusFont = st::contactsStatusFont;
const auto status = tr::lng_group_invite_joined_right(tr::now);
@ -721,20 +722,14 @@ not_null<Ui::RpWidget*> AddBalanceWidget(
balanceValue
) | rpl::start_with_next([=](CreditsAmount value) {
auto text = TextWithEntities();
const auto manager = &session->data().customEmojiManager();
auto helper = Ui::Text::CustomEmojiHelper();
if (value.ton()) {
text.append(Ui::Text::SingleCustomEmoji(
manager->registerInternalEmoji(
u"balance_amount_ton_icon"_q,
Ui::Earn::IconCurrencyColored(
st::tonFieldIconSize,
st::currencyFg->c),
st::channelEarnCurrencyLearnMargins,
false))
text.append(
helper.paletteDependent(Ui::Earn::IconCurrencyEmoji())
).append(' ').append(Lang::FormatCreditsAmountDecimal(value));
} else {
text.append(
manager->creditsEmoji()
helper.paletteDependent(Ui::Earn::IconCreditsEmoji())
).append(' ').append(
Lang::FormatCreditsAmountToShort(value).string);
}
@ -742,10 +737,7 @@ not_null<Ui::RpWidget*> AddBalanceWidget(
st::semiboldTextStyle,
text,
kMarkupTextOptions,
Core::TextContext({
.session = session,
.repaint = [=] { balance->update(); },
}));
helper.context([=] { balance->update(); }));
balance->setBalance(value);
resize();
}, balance->lifetime());
@ -780,7 +772,6 @@ void BoostCreditsBox(
box->setNoContentMargin(true);
const auto content = box->verticalLayout();
const auto session = &controller->session();
Ui::AddSkip(content);
{
const auto &stUser = st::premiumGiftsUserpicButton;
@ -820,21 +811,16 @@ void BoostCreditsBox(
- st::boxRowPadding.right());
auto textWithEntities = TextWithEntities();
textWithEntities.append(
Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::boostsListMiniIcon,
{ st.font->descent * 2, st.font->descent / 2, 0, 0 },
true)));
textWithEntities.append(
Ui::Text::IconEmoji(&st::boostsListEntryIcon)
).append(
tr::lng_boosts_list_title(tr::now, lt_count, b.multiplier));
text->setMarkedText(
st,
std::move(textWithEntities),
kMarkupTextOptions,
Core::TextContext({
.session = session,
Ui::Text::MarkedContext{
.repaint = [=] { badge->update(); },
}));
});
badge->paintRequest(
) | rpl::start_with_next([=] {
auto p = QPainter(badge);
@ -1485,10 +1471,9 @@ void GenericCreditsEntryBox(
object_ptr<Ui::FixedHeightWidget>(
content,
st::defaultTextStyle.font->height));
const auto context = Core::TextContext({
.session = session,
.repaint = [=] { amount->update(); },
});
auto helper = Ui::Text::CustomEmojiHelper();
const auto starEmoji = helper.paletteDependent(
Ui::Earn::IconCreditsEmoji());
if (e.soldOutInfo) {
text->setText(
st::defaultTextStyle,
@ -1499,12 +1484,12 @@ void GenericCreditsEntryBox(
tr::lng_credits_subscription_subtitle(
tr::now,
lt_emoji,
owner->customEmojiManager().creditsEmoji(),
starEmoji,
lt_cost,
{ QString::number(s.subscription.credits) },
Ui::Text::WithEntities),
kMarkupTextOptions,
context);
helper.context([=] { amount->update(); }));
} else if (e.credits.stars()) {
auto t = TextWithEntities()
.append((e.in && (creditsHistoryStarGift || !isStarGift))
@ -1514,12 +1499,12 @@ void GenericCreditsEntryBox(
: kMinus)
.append(Lang::FormatCreditsAmountDecimal(e.credits.abs()))
.append(QChar(' '))
.append(owner->customEmojiManager().creditsEmoji());
.append(starEmoji);
text->setMarkedText(
st::semiboldTextStyle,
std::move(t),
kMarkupTextOptions,
context);
helper.context([=] { amount->update(); }));
} else if (e.credits.ton()) {
auto t = TextWithEntities()
.append((e.in ? QChar('+') : kMinus))
@ -1528,30 +1513,18 @@ void GenericCreditsEntryBox(
st::channelEarnHistoryMajorLabel.style,
std::move(t),
kMarkupTextOptions,
context);
helper.context([=] { amount->update(); }));
auto minor = TextWithEntities()
.append(Info::ChannelEarn::MinorPart(e.credits.abs()))
.append(QChar(' '))
.append(
Ui::Text::SingleCustomEmoji(
owner->customEmojiManager().registerInternalEmoji(
(e.in
? u"stats_transaction_ton_in"_q
: u"stats_transaction_ton_out"_q),
Ui::Earn::IconCurrencyColored(
st::tonFieldIconSize,
(e.in
? st::boxTextFgGood->c
: st::menuIconAttentionColor->c)),
QMargins(0, st::lineWidth * 1, 0, 0),
false)));
.append(Ui::Text::IconEmoji(&st::tonIconEmojiInSmall));
minorText = lifetime.make_state<Ui::Text::String>();
minorText->setMarkedText(
st::channelEarnHistoryMinorLabel.style,
std::move(minor),
kMarkupTextOptions,
context);
helper.context([=] { amount->update(); }));
}
const auto font = text->style()->font;
const auto roundedFont = st::defaultTextStyle.font;
@ -2746,11 +2719,6 @@ void AddWithdrawalWidget(
tr::lng_channel_earn_balance_button(tr::now),
st::channelEarnSemiboldLabel);
const auto processInputChange = [&] {
const auto buttonEmoji = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::settingsPremiumIconStar,
{ 0, -st::moderateBoxExpandInnerSkip, 0, 0 },
true));
using Balance = rpl::variable<CreditsAmount>;
const auto currentBalance = input->lifetime().make_state<Balance>(
rpl::duplicate(availableBalanceValue));
@ -2766,9 +2734,8 @@ void AddWithdrawalWidget(
lt_count,
amount,
lt_emoji,
buttonEmoji,
Ui::Text::RichLangValue),
Core::TextContext({ .session = session }));
Ui::Text::IconEmoji(&st::starIconEmojiLarge),
Ui::Text::RichLangValue));
}
};
QObject::connect(input, &Ui::MaskedInputField::changed, process);
@ -2836,15 +2803,10 @@ void AddWithdrawalWidget(
constexpr auto kDateUpdateInterval = crl::time(250);
const auto was = base::unixtime::serialize(dt);
const auto context = Core::TextContext({
.session = session,
const auto context = Ui::Text::MarkedContext{
.repaint = [=] { lockedLabel->update(); },
});
const auto emoji = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::chatSimilarLockedIcon,
st::botEarnButtonLockMargins,
true));
};
const auto emoji = Ui::Text::IconEmoji(&st::botEarnButtonLock);
rpl::single(
rpl::empty
@ -2933,7 +2895,7 @@ void AddWithdrawalWidget(
tr::lng_bot_earn_balance_about_url(tr::now));
}),
Ui::Text::RichLangValue),
Core::TextContext({ .session = session }),
{},
st::boxDividerLabel);
Ui::AddSkip(container);
container->add(object_ptr<Ui::DividerLabel>(

View File

@ -772,30 +772,12 @@ void SetupPremium(
? Lang::FormatCreditsAmountToShort(c).string
: QString();
}),
st::settingsButton);
st::settingsButton,
{ &st::menuIconTon });
button->addClickHandler([=] {
controller->setPremiumRef("settings");
showOther(CurrencyId());
});
const auto badge = Ui::CreateChild<Ui::RpWidget>(button.get());
const auto image = Ui::Earn::IconCurrencyColored(
st::tonFieldIconSize,
st::menuIconColor->c);
badge->resize(Size(st::tonFieldIconSize));
badge->paintRequest(
) | rpl::start_with_next([=] {
auto p = QPainter(badge);
p.drawImage(0, 0, image);
}, badge->lifetime());
button->sizeValue() | rpl::start_with_next([=](const QSize &s) {
badge->moveToLeft(
button->st().iconLeft
+ (st::menuIconShop.width() - badge->width()) / 2,
(s.height() - badge->height()) / 2);
}, badge->lifetime());
}
const auto button = AddButtonWithIcon(
container,

View File

@ -159,6 +159,10 @@ getBoostsButtonIcon: icon {{ "menu/gift_premium", lightButtonFg }};
boostsListMiniIcon: icon{{ "boosts/boost_mini2", premiumButtonFg }};
boostsListMiniIconPadding: margins(1px, 0px, 0px, 0px);
boostsListMiniIconSkip: 1px;
boostsListEntryIcon: IconEmoji {
icon: boostsListMiniIcon;
padding: margins(6px, 2px, 0px, 0px);
}
boostsListBadgeTextPadding: margins(16px, 1px, 6px, 0px);
boostsListBadgePadding: margins(4px, 1px, 4px, 0px);
boostsListBadgeHeight: 16px;

View File

@ -21,6 +21,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/painter.h"
#include "settings/settings_common.h"
#include "styles/style_boxes.h"
#include "styles/style_credits.h"
#include "styles/style_layers.h"
#include <QtCore/QRegularExpression>
@ -47,16 +48,14 @@ constexpr auto kTonMultiplier = uint64(1000000000);
return langDateTime(base::unixtime::parse(date));
}
[[nodiscard]] TextWithEntities FormatPrice(
const CollectibleInfo &info,
const CollectibleDetails &details) {
[[nodiscard]] TextWithEntities FormatPrice(const CollectibleInfo &info) {
auto minor = Info::ChannelEarn::MinorPart(info.cryptoAmount);
if (minor.size() == 1 && minor.at(0) == '.') {
minor += '0';
}
auto price = (info.cryptoCurrency == u"TON"_q)
? base::duplicate(
details.tonEmoji
? Ui::Text::IconEmoji(
&st::tonIconEmoji
).append(
Info::ChannelEarn::MajorPart(info.cryptoAmount)
).append(minor)
@ -123,8 +122,7 @@ CollectibleType DetectCollectibleType(const QString &entity) {
void CollectibleInfoBox(
not_null<Ui::GenericBox*> box,
CollectibleInfo info,
CollectibleDetails details) {
CollectibleInfo info) {
box->setWidth(st::boxWideWidth);
box->setStyle(st::collectibleBox);
@ -218,15 +216,13 @@ void CollectibleInfoBox(
lt_date,
TextWithEntities{ FormatDate(info.date) },
lt_price,
FormatPrice(info, details),
FormatPrice(info),
Ui::Text::RichLangValue);
const auto label = box->addRow(
object_ptr<Ui::FlatLabel>(box, st::collectibleInfo),
st::collectibleInfoPadding);
label->setAttribute(Qt::WA_TransparentForMouseEvents);
auto context = details.tonEmojiContext;
context.repaint = [label] { label->update(); };
label->setMarkedText(text, context);
label->setMarkedText(text);
const auto more = box->addRow(
object_ptr<Ui::RoundButton>(

View File

@ -32,14 +32,6 @@ struct CollectibleInfo {
TimeId date = 0;
};
struct CollectibleDetails {
TextWithEntities tonEmoji;
Text::MarkedContext tonEmojiContext;
};
void CollectibleInfoBox(
not_null<Ui::GenericBox*> box,
CollectibleInfo info,
CollectibleDetails details);
void CollectibleInfoBox(not_null<Ui::GenericBox*> box, CollectibleInfo info);
} // namespace Ui

View File

@ -34,14 +34,22 @@ historyReplyBottom: 2px;
historyReplyPreview: 32px;
historyReplyPreviewMargin: margins(7px, 4px, 4px, 4px);
historyReplyPadding: margins(11px, 2px, 6px, 2px);
historyReplyUser: icon {{ "chat/reply_type_user", windowFg }};
historyReplyUserPadding: margins(0px, 4px, 4px, 0px);
historyReplyGroup: icon {{ "chat/reply_type_group", windowFg }};
historyReplyGroupPadding: margins(0px, 4px, 4px, 0px);
historyReplyChannel: icon {{ "chat/reply_type_channel", windowFg }};
historyReplyChannelPadding: margins(0px, 5px, 4px, 0px);
historyReplyForward: icon {{ "mini_forward", windowFg }};
historyReplyForwardPadding: margins(0px, 2px, 2px, 0px);
historyReplyUser: IconEmoji {
icon: icon {{ "chat/reply_type_user", windowFg }};
padding: margins(0px, 4px, 4px, 0px);
}
historyReplyGroup: IconEmoji {
icon: icon {{ "chat/reply_type_group", windowFg }};
padding: margins(0px, 4px, 4px, 0px);
}
historyReplyChannel: IconEmoji {
icon: icon {{ "chat/reply_type_channel", windowFg }};
padding: margins(0px, 5px, 4px, 0px);
}
historyReplyForward: IconEmoji {
icon: icon {{ "mini_forward", windowFg }};
padding: margins(0px, 2px, 2px, 0px);
}
msgReplyPadding: margins(6px, 6px, 11px, 6px);
msgReplyBarPos: point(1px, 0px);
@ -1096,13 +1104,18 @@ repliesComposeControls: ComposeControls(defaultComposeControls) {
tabbedHeightMin: 220px;
}
boostMessageIcon: icon {{ "stories/boost_mini", windowFg }};
boostMessageIconPadding: margins(0px, 2px, 0px, 0px);
boostsMessageIcon: icon {{ "stories/boosts_mini", windowFg }};
boostsMessageIconPadding: margins(0px, 2px, 0px, 0px);
historyIvIcon: icon{{ "boosts/boost_mini2", windowFg }};
historyIvIconPadding: margins(2px, 2px, 2px, 0px);
boostMessageIcon: IconEmoji {
icon: icon {{ "stories/boost_mini", windowFg }};
padding: margins(0px, 2px, 0px, 0px);
}
boostsMessageIcon: IconEmoji {
icon: icon {{ "stories/boosts_mini", windowFg }};
padding: margins(0px, 2px, 0px, 0px);
}
historyIvIcon: IconEmoji {
icon: icon {{ "boosts/boost_mini2", windowFg }};
padding: margins(2px, 2px, 2px, 0px);
}
chatIntroStickerSize: 96px;
chatIntroWidth: 224px;
@ -1373,7 +1386,6 @@ chatTabsOutlineHorizontal: ChatTabsOutline {
chatTabsOutlineVertical: ChatTabsOutline(chatTabsOutlineHorizontal) {
}
suggestPriceTonIconMargins: margins(0px, 2px, 0px, 0px);
suggestPriceBox: Box(defaultBox) {
buttonPadding: margins(22px, 22px, 22px, 22px);
buttonHeight: 42px;
@ -1404,7 +1416,7 @@ tonInput: InputField(defaultInputField) {
}
starsFieldIconPosition: point(0px, 10px);
tonFieldIconSize: 16px;
tonFieldIconPosition: point(2px, 9px);
tonFieldIconPosition: point(2px, 11px);
suggestBarTonIconSize: 14px;
suggestBarTonIconMargins: margins(0px, 3px, 0px, 0px);

View File

@ -15,6 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/layers/generic_box.h"
#include "ui/layers/show.h"
#include "ui/text/custom_emoji_helper.h"
#include "ui/text/custom_emoji_text_badge.h"
#include "ui/text/text_utilities.h"
#include "ui/toast/toast.h"
#include "ui/widgets/buttons.h"
@ -87,41 +88,6 @@ struct Feature {
return result;
}
[[nodiscard]] Fn<QImage()> CustomEmojiBadgeFactory(
const QString &text,
const style::color &bg,
const style::color &fg) {
return [=] {
auto string = Ui::Text::String(
st::settingsPremiumNewBadge.style,
text.toUpper());
const auto size = QSize(string.maxWidth(), string.minHeight());
const auto padding = st::settingsPremiumNewBadgePadding;
const auto full = size.grownBy(padding);
const auto ratio = style::DevicePixelRatio();
auto result = QImage(
full * ratio,
QImage::Format_ARGB32_Premultiplied);
result.setDevicePixelRatio(ratio);
result.fill(Qt::transparent);
auto p = QPainter(&result);
auto hq = PainterHighQualityEnabler(p);
p.setPen(Qt::NoPen);
p.setBrush(bg);
const auto r = padding.left();
p.drawRoundedRect(0, 0, full.width(), full.height(), r, r);
p.setPen(fg);
string.draw(p, { .position = { padding.left(), padding.top() } });
p.end();
return result;
};
}
[[nodiscard]] Counters AdjustByReached(Counters data) {
if (data.stars < 0) {
return data;
@ -389,17 +355,15 @@ void AboutRatingBox(
auto helper = Ui::Text::CustomEmojiHelper();
const auto makeBadge = [&](
const QString &text,
const style::color &bg,
const style::color &fg) {
const style::RoundButton &st) {
return helper.paletteDependent(
CustomEmojiBadgeFactory(text, bg, fg),
st::badgeEmojiMargin);
Ui::Text::CustomEmojiTextBadge(text, st));
};
const auto makeActive = [&](const QString &text) {
return makeBadge(text, st::windowBgActive, st::windowFgActive);
return makeBadge(text, st::customEmojiTextBadge);
};
const auto makeInactive = [&](const QString &text) {
return makeBadge(text, st::windowSubTextFg, st::windowFgActive);
return makeBadge(text, st::infoRatingDeductedBadge);
};
const auto features = std::vector<Feature>{
{

View File

@ -81,6 +81,11 @@ starIconEmojiSmall: IconEmoji {
icon: icon{{ "chat/mini_stars", creditsBg1 }};
padding: margins(0px, 4px, 0px, 0px);
}
starIconEmojiLarge: IconEmoji {
icon: icon {{ "settings/premium/star", settingsIconFg }};
padding: margins(0px, -2px, 0px, 0px);
}
tonIconEmoji: IconEmoji {
icon: icon{{ "chat/mini_ton_bold", currencyFg }};
padding: margins(1px, 3px, 1px, 0px);
@ -89,6 +94,9 @@ tonIconEmojiLarge: IconEmoji {
icon: icon{{ "payments/ton_emoji-18x18", currencyFg }};
padding: margins(0px, 1px, 0px, 0px);
}
tonIconEmojiInSmall: IconEmoji(tonIconEmoji) {
padding: margins(0px, 2px, 0px, 0px);
}
creditsHistoryEntryTypeAds: icon {{ "folders/folders_channels", premiumButtonFg }};
@ -228,7 +236,10 @@ giftListAbout: FlatLabel(defaultFlatLabel) {
giftListAboutMargin: margins(12px, 24px, 12px, 24px);
giftBoxEmojiToggleTop: 7px;
giftBoxLimitTop: 28px;
giftBoxLockMargins: margins(-2px, 1px, 0px, 0px);
giftBoxLock: IconEmoji {
icon: icon {{ "emoji/premium_lock", placeholderFgActive }};
padding: margins(-2px, 1px, 0px, 0px);
}
giftBoxPinIcon: icon {{ "dialogs/dialogs_pinned", premiumButtonFg }};
creditsHistoryEntriesList: PeerList(defaultPeerList) {

View File

@ -26,8 +26,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/empty_userpic.h"
#include "ui/painter.h"
#include "ui/rect.h"
#include "ui/text/custom_emoji_instance.h"
#include "ui/text/format_values.h"
#include "ui/text/text_custom_emoji.h"
#include "ui/text/text_utilities.h"
#include "ui/widgets/fields/number_input.h"
#include "ui/wrap/padding_wrap.h"
@ -692,9 +692,9 @@ QImage CreditsWhiteDoubledIcon(int size, float64 outlineRatio) {
std::unique_ptr<Ui::Text::CustomEmoji> MakeCreditsIconEmoji(
int height,
int count) {
return std::make_unique<Ui::Text::StaticCustomEmoji>(
GenerateStars(height, count),
u"credits_icon:%1:%2"_q.arg(height).arg(count));
return std::make_unique<Ui::CustomEmoji::Internal>(
u"credits_icon:%1:%2"_q.arg(height).arg(count),
GenerateStars(height, count));
}
Ui::Text::MarkedContext MakeCreditsIconContext(int height, int count) {

View File

@ -189,6 +189,7 @@ menuIconAdd: icon {{ "menu/add", menuIconColor }};
menuIconRatingGifts: icon {{ "menu/rating_gifts-24x24", menuIconColor }};
menuIconRatingUsers: icon {{ "menu/users_stars-24x24", menuIconColor }};
menuIconRatingRefund: icon {{ "menu/rating_refund-24x24", menuIconColor }};
menuIconTon: icon{{ "payments/ton_emoji-18x18", menuIconColor, point(3px, 2px) }};
menuIconTTLAny: icon {{ "menu/auto_delete_plain", menuIconColor }};
menuIconTTLAnyTextPosition: point(11px, 22px);

View File

@ -41,6 +41,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "calls/calls_instance.h"
#include "inline_bots/bot_attach_web_view.h" // InlineBots::PeerType.
#include "ui/toast/toast.h"
#include "ui/text/custom_emoji_helper.h"
#include "ui/text/format_values.h"
#include "ui/text/text_utilities.h"
#include "ui/widgets/chat_filters_tabs_strip.h"
@ -78,6 +79,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/info_memento.h"
#include "info/channel_statistics/boosts/info_boosts_widget.h"
#include "info/channel_statistics/earn/info_channel_earn_widget.h"
#include "info/channel_statistics/earn/earn_icons.h"
#include "info/profile/info_profile_cover.h"
#include "info/profile/info_profile_values.h"
#include "info/statistics/info_statistics_widget.h"
@ -1683,6 +1685,7 @@ void Filler::addToggleFee() {
}, feeRemoved ? &st::menuIconEarn : &st::menuIconCancelFee);
_addAction({ .isSeparator = true });
_addAction({ .make = [=](not_null<Ui::RpWidget*> actionParent) {
auto helper = Ui::Text::CustomEmojiHelper();
const auto text = feeRemoved
? tr::lng_context_fee_free(
tr::now,
@ -1694,8 +1697,8 @@ void Filler::addToggleFee() {
lt_name,
TextWithEntities{ user->shortName() },
lt_amount,
user->owner().customEmojiManager().ministarEmoji(
{ 0, st::giftBoxByStarsStarTop, 0, 0 }
helper.paletteDependent(
Ui::Earn::IconCurrencyEmojiSmall()
).append(Lang::FormatCountDecimal(
user->owner().commonStarsPerMessage(parent)
)),

View File

@ -178,21 +178,6 @@ private:
return false;
}
[[nodiscard]] Ui::CollectibleDetails PrepareCollectibleDetails(
not_null<Main::Session*> session) {
return {
.tonEmoji = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
u"collectible_ton_icon"_q,
Ui::Earn::IconCurrencyColored(
st::collectibleInfo.style.font,
st::collectibleInfo.textFg->c),
st::collectibleInfoTonMargins,
true)),
.tonEmojiContext = Core::TextContext({ .session = session }),
};
}
[[nodiscard]] Ui::CollectibleInfo Parse(
const QString &entity,
not_null<PeerData*> owner,
@ -868,8 +853,7 @@ void SessionNavigation::resolveCollectible(
_collectibleRequestId = 0;
uiShow()->show(Box(
Ui::CollectibleInfoBox,
Parse(entity, _session->data().peer(ownerId), result),
PrepareCollectibleDetails(_session)));
Parse(entity, _session->data().peer(ownerId), result)));
}).fail([=](const MTP::Error &error) {
_collectibleEntity = QString();
_collectibleRequestId = 0;

@ -1 +1 @@
Subproject commit cd01ab20e485aabd0991bb43c7d8302cd0a2ebc4
Subproject commit 7d1c15838960b77d49401104404d2e637f476c2c