Simplify marked text context logic.

This commit is contained in:
John Preston 2025-03-07 14:17:39 +04:00
parent 789f3e1584
commit c9fb97cd7c
98 changed files with 441 additions and 609 deletions

View file

@ -3646,6 +3646,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_new_contact_phone_number" = "Phone number";
"lng_new_contact_registration" = "Registration";
"lng_new_contact_common_groups" = "Common groups";
"lng_new_contact_groups#one" = "{count} group {emoji} {arrow}";
"lng_new_contact_groups#other" = "{count} groups {emoji} {arrow}";
"lng_new_contact_not_official" = "Not an official account";
"lng_new_contact_updated_name" = "User updated name {when}";
"lng_new_contact_updated_photo" = "User updated photo {when}";

View file

@ -149,18 +149,14 @@ void InitFilterLinkHeader(
iconEmoji
).value_or(Ui::FilterIcon::Custom)).active;
const auto isStatic = title.isStatic;
const auto makeContext = [=](Fn<void()> repaint) {
return Core::MarkedTextContext{
.session = &box->peerListUiShow()->session(),
.customEmojiRepaint = std::move(repaint),
.customEmojiLoopLimit = isStatic ? -1 : 0,
};
};
auto header = Ui::MakeFilterLinkHeader(box, {
.type = type,
.title = TitleText(type)(tr::now),
.about = AboutText(type, title.text),
.makeAboutContext = makeContext,
.aboutContext = Core::TextContext({
.session = &box->peerListUiShow()->session(),
.customEmojiLoopLimit = isStatic ? -1 : 0,
}),
.folderTitle = title.text,
.folderIcon = icon,
.badge = (type == Ui::FilterLinkHeaderType::AddingChats
@ -560,16 +556,12 @@ void ShowImportToast(
text.append('\n').append(phrase(tr::now, lt_count, added));
}
const auto isStatic = title.isStatic;
const auto makeContext = [=](not_null<QWidget*> widget) {
return Core::MarkedTextContext{
.session = &strong->session(),
.customEmojiRepaint = [=] { widget->update(); },
.customEmojiLoopLimit = isStatic ? -1 : 0,
};
};
strong->showToast({
.text = std::move(text),
.textContext = makeContext,
.textContext = Core::TextContext({
.session = &strong->session(),
.customEmojiLoopLimit = isStatic ? -1 : 0,
})
});
}
@ -640,18 +632,14 @@ void ProcessFilterInvite(
raw->setRealContentHeight(box->heightValue());
const auto isStatic = title.isStatic;
const auto makeContext = [=](Fn<void()> update) {
return Core::MarkedTextContext{
.session = &strong->session(),
.customEmojiRepaint = update,
.customEmojiLoopLimit = isStatic ? -1 : 0,
};
};
auto owned = Ui::FilterLinkProcessButton(
box,
type,
title.text,
makeContext,
Core::TextContext({
.session = &strong->session(),
.customEmojiLoopLimit = isStatic ? -1 : 0,
}),
std::move(badge));
const auto button = owned.data();
@ -873,18 +861,14 @@ void ProcessFilterRemove(
}, type, title, iconEmoji, rpl::single(0), horizontalFilters);
const auto isStatic = title.isStatic;
const auto makeContext = [=](Fn<void()> update) {
return Core::MarkedTextContext{
.session = &strong->session(),
.customEmojiRepaint = update,
.customEmojiLoopLimit = isStatic ? -1 : 0,
};
};
auto owned = Ui::FilterLinkProcessButton(
box,
type,
title.text,
makeContext,
Core::TextContext({
.session = &strong->session(),
.customEmojiLoopLimit = isStatic ? -1 : 0,
}),
std::move(badge));
const auto button = owned.data();

View file

@ -172,13 +172,6 @@ void ChangeFilterById(
const auto account = not_null(&history->session().account());
if (const auto controller = Core::App().windowFor(account)) {
const auto isStatic = name.isStatic;
const auto textContext = [=](not_null<QWidget*> widget) {
return Core::MarkedTextContext{
.session = &history->session(),
.customEmojiRepaint = [=] { widget->update(); },
.customEmojiLoopLimit = isStatic ? -1 : 0,
};
};
controller->showToast({
.text = (add
? tr::lng_filters_toast_add
@ -189,7 +182,10 @@ void ChangeFilterById(
lt_folder,
Ui::Text::Wrapped(name.text, EntityType::Bold),
Ui::Text::WithEntities),
.textContext = textContext,
.textContext = Core::TextContext({
.session = &history->session(),
.customEmojiLoopLimit = isStatic ? -1 : 0,
}),
});
}
}).fail([=](const MTP::Error &error) {
@ -297,12 +293,10 @@ void FillChooseFilterMenu(
std::move(callback)),
contains ? &st::mediaPlayerMenuCheck : nullptr,
contains ? &st::mediaPlayerMenuCheck : nullptr);
const auto context = Core::MarkedTextContext{
item->setMarkedText(title.text, QString(), Core::TextContext({
.session = &history->session(),
.customEmojiRepaint = [raw = item.get()] { raw->update(); },
.customEmojiLoopLimit = title.isStatic ? -1 : 0,
};
item->setMarkedText(title.text, QString(), context);
}));
item->setIcon(Icon(showColors ? filter : filter.withColorIndex({})));
const auto action = menu->addAction(std::move(item));

View file

@ -441,13 +441,10 @@ void EditFilterBox(
using namespace Window;
return window->isGifPausedAtLeastFor(GifPauseReason::Layer);
};
name->setCustomTextContext([=](Fn<void()> repaint) {
return std::any(Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = std::move(repaint),
.customEmojiLoopLimit = value ? -1 : 0,
});
}, [paused] {
name->setCustomTextContext(Core::TextContext({
.session = session,
.customEmojiLoopLimit = value ? -1 : 0,
}), [paused] {
return On(PowerSaving::kEmojiChat) || paused();
}, [paused] {
return On(PowerSaving::kChatSpoiler) || paused();
@ -609,10 +606,7 @@ void EditFilterBox(
float64 alpha = 1.;
};
const auto tag = preview->lifetime().make_state<TagState>();
tag->context.textContext = Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = [] {},
};
tag->context.textContext = Core::TextContext({ .session = session });
preview->paintRequest() | rpl::start_with_next([=] {
auto p = QPainter(preview);
p.setOpacity(tag->alpha);

View file

@ -163,10 +163,10 @@ ExceptionRow::ExceptionRow(
st::defaultTextStyle,
filters,
kMarkupTextOptions,
Core::MarkedTextContext{
Core::TextContext({
.session = &history->session(),
.customEmojiRepaint = repaint,
});
.repaint = repaint,
}));
} else if (peer()->isSelf()) {
setCustomStatus(tr::lng_saved_forward_here(tr::now));
}

View file

@ -537,13 +537,6 @@ void LinkController::addHeader(not_null<Ui::VerticalLayout*> container) {
verticalLayout->add(std::move(icon.widget));
const auto isStatic = _filterTitle.isStatic;
const auto makeContext = [=](Fn<void()> update) {
return Core::MarkedTextContext{
.session = &_window->session(),
.customEmojiRepaint = update,
.customEmojiLoopLimit = isStatic ? -1 : 0,
};
};
verticalLayout->add(
object_ptr<Ui::CenterWrap<>>(
verticalLayout,
@ -559,7 +552,10 @@ void LinkController::addHeader(not_null<Ui::VerticalLayout*> container) {
Ui::Text::WithEntities)),
st::settingsFilterDividerLabel,
st::defaultPopupMenu,
makeContext)),
Core::TextContext({
.session = &_window->session(),
.customEmojiLoopLimit = isStatic ? -1 : 0,
}))),
st::filterLinkDividerLabelPadding);
verticalLayout->geometryValue(

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_credits.h"
#include "boxes/peer_list_controllers.h"
#include "core/ui_integration.h" // TextContext.
#include "data/data_peer.h"
#include "data/data_session.h"
#include "data/data_user.h"
@ -67,14 +68,9 @@ void GiftCreditsBox(
2.);
{
Ui::AddSkip(content);
const auto arrow = Ui::Text::SingleCustomEmoji(
peer->owner().customEmojiManager().registerInternalEmoji(
st::topicButtonArrow,
st::channelEarnLearnArrowMargins,
true));
auto link = tr::lng_credits_box_history_entry_gift_about_link(
lt_emoji,
rpl::single(arrow),
rpl::single(Ui::Text::IconEmoji(&st::textMoreIconEmoji)),
Ui::Text::RichLangValue
) | rpl::map([](TextWithEntities text) {
return Ui::Text::Link(
@ -92,7 +88,7 @@ void GiftCreditsBox(
lt_link,
std::move(link),
Ui::Text::RichLangValue),
{ .session = &peer->session() },
Core::TextContext({ .session = &peer->session() }),
st::creditsBoxAbout)),
st::boxRowPadding);
}

View file

@ -517,13 +517,13 @@ not_null<Ui::FlatLabel*> AddTableRow(
not_null<Ui::TableLayout*> table,
rpl::producer<QString> label,
rpl::producer<TextWithEntities> value,
const Fn<std::any(Fn<void()>)> &makeContext = nullptr) {
const Ui::Text::MarkedContext &context = {}) {
auto widget = object_ptr<Ui::FlatLabel>(
table,
std::move(value),
table->st().defaultValue,
st::defaultPopupMenu,
std::move(makeContext));
context);
const auto result = widget.data();
AddTableRow(
table,
@ -1527,12 +1527,6 @@ void AddStarGiftTable(
: nullptr;
const auto date = base::unixtime::parse(original.date).date();
const auto dateText = TextWithEntities{ langDayOfMonth(date) };
const auto makeContext = [=](Fn<void()> update) {
return Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = std::move(update),
};
};
auto label = object_ptr<Ui::FlatLabel>(
table,
(from
@ -1574,7 +1568,7 @@ void AddStarGiftTable(
? *st.tableValueMessage
: st::giveawayGiftMessage),
st::defaultPopupMenu,
makeContext);
Core::TextContext({ .session = session }));
const auto showBoxLink = [=](not_null<PeerData*> peer) {
return std::make_shared<LambdaClickHandler>([=] {
show->showBox(PrepareShortInfoBox(peer, show));
@ -1592,12 +1586,6 @@ void AddStarGiftTable(
st::giveawayGiftCodeValueMargin);
}
} else if (!entry.description.empty()) {
const auto makeContext = [=](Fn<void()> update) {
return Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = std::move(update),
};
};
auto label = object_ptr<Ui::FlatLabel>(
table,
rpl::single(entry.description),
@ -1605,7 +1593,7 @@ void AddStarGiftTable(
? *st.tableValueMessage
: st::giveawayGiftMessage),
st::defaultPopupMenu,
makeContext);
Core::TextContext({ .session = session }));
label->setSelectable(true);
table->addRow(
nullptr,

View file

@ -453,10 +453,7 @@ void CreateModerateMessagesBox(
) | rpl::start_with_next([=](const TextWithEntities &text) {
raw->setMarkedText(
Ui::Text::Link(text, u"internal:"_q),
Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = [=] { raw->update(); },
});
Core::TextContext({ .session = session }));
}, label->lifetime());
Ui::AddSkip(inner);

View file

@ -1154,8 +1154,7 @@ RecoverBox::RecoverBox(
rpl::single(Ui::Text::WrapEmailPattern(pattern)),
Ui::Text::WithEntities),
st::termsContent,
st::defaultPopupMenu,
[=](Fn<void()> update) { return CommonTextContext{ std::move(update) }; })
st::defaultPopupMenu)
, _closeParent(std::move(closeParent)) {
_patternLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
if (_cloudFields.pendingResetDate != 0 || !session) {

View file

@ -15,7 +15,7 @@ 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" // Core::MarkedTextContext.
#include "core/ui_integration.h" // TextContext
#include "data/stickers/data_custom_emoji.h"
#include "data/stickers/data_stickers.h"
#include "data/data_changes.h"
@ -165,7 +165,7 @@ private:
const uint32 _level;
const TextWithEntities _icon;
const Core::MarkedTextContext _context;
const Ui::Text::MarkedContext _context;
Ui::Text::String _text;
bool _minimal = false;
@ -466,7 +466,10 @@ LevelBadge::LevelBadge(
st::settingsLevelBadgeLock,
QMargins(0, st::settingsLevelBadgeLockSkip, 0, 0),
false)))
, _context({ .session = session }) {
, _context(Core::TextContext({
.session = session,
.repaint = [this] { update(); },
})) {
updateText();
}

View file

@ -15,7 +15,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peer_list_controllers.h"
#include "boxes/share_box.h"
#include "core/application.h"
#include "core/ui_integration.h" // Core::MarkedTextContext.
#include "core/ui_integration.h" // TextContext
#include "data/components/credits.h"
#include "data/data_changes.h"
#include "data/data_channel.h"
@ -740,10 +740,10 @@ void Controller::setupAboveJoinedWidget() {
{ QString::number(current.subscription.credits) },
Ui::Text::WithEntities),
kMarkupTextOptions,
Core::MarkedTextContext{
Core::TextContext({
.session = &session(),
.customEmojiRepaint = [=] { widget->update(); },
});
.repaint = [=] { widget->update(); },
}));
auto &lifetime = widget->lifetime();
const auto rateValue = lifetime.make_state<rpl::variable<float64>>(
session().credits().rateValue(_peer));
@ -994,10 +994,7 @@ void Controller::rowClicked(not_null<PeerListRow*> row) {
lt_cost,
{ QString::number(data.subscription.credits) },
Ui::Text::WithEntities),
Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = [=] { subtitle1->update(); },
});
Core::TextContext({ .session = session }));
const auto subtitle2 = box->addRow(
object_ptr<Ui::CenterWrap<Ui::FlatLabel>>(
box,

View file

@ -890,11 +890,10 @@ void AddBoostsUnrestrictLabels(
manager->registerInternalEmoji(
st::boostsMessageIcon,
st::boostsMessageIconPadding));
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = session,
.customEmojiRepaint = [] {},
.customEmojiLoopLimit = 1,
};
});
for (auto i = 0; i != kBoostsUnrestrictValues; ++i) {
const auto label = Ui::CreateChild<Ui::FlatLabel>(
labels,

View file

@ -363,12 +363,15 @@ object_ptr<Ui::RpWidget> AddReactionsSelector(
const auto customEmojiPaused = [controller = args.controller] {
return controller->isGifPausedAtLeastFor(PauseReason::Layer);
};
auto factory = [=](QStringView data, Fn<void()> update)
-> std::unique_ptr<Ui::Text::CustomEmoji> {
auto context = Core::TextContext({
.session = session,
});
context.customEmojiFactory = [=](
QStringView data,
const Ui::Text::MarkedContext &context
) -> std::unique_ptr<Ui::Text::CustomEmoji> {
const auto id = Data::ParseCustomEmojiData(data);
auto result = owner->customEmojiManager().create(
data,
std::move(update));
auto result = Ui::Text::MakeCustomEmoji(data, context);
if (state->unifiedFactoryOwner->lookupReactionId(id).custom()) {
return std::make_unique<MaybeDisabledEmoji>(
std::move(result),
@ -377,12 +380,10 @@ object_ptr<Ui::RpWidget> AddReactionsSelector(
using namespace Ui::Text;
return std::make_unique<FirstFrameEmoji>(std::move(result));
};
raw->setCustomTextContext([=](Fn<void()> repaint) {
return std::any(Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = std::move(repaint),
});
}, customEmojiPaused, customEmojiPaused, std::move(factory));
raw->setCustomTextContext(
std::move(context),
customEmojiPaused,
customEmojiPaused);
const auto callback = args.callback;
const auto isCustom = [=](DocumentId id) {

View file

@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_credits.h"
#include "apiwrap.h"
#include "core/ui_integration.h" // Core::MarkedTextContext.
#include "core/ui_integration.h" // TextContext
#include "data/components/credits.h"
#include "data/data_credits.h"
#include "data/data_photo.h"
@ -519,21 +519,20 @@ TextWithEntities CreditsEmojiSmall(not_null<Main::Session*> session) {
not_null<FlatLabel*> SetButtonMarkedLabel(
not_null<RpWidget*> button,
rpl::producer<TextWithEntities> text,
Fn<std::any(Fn<void()> update)> context,
Text::MarkedContext context,
const style::FlatLabel &st,
const style::color *textFg) {
const auto buttonLabel = Ui::CreateChild<Ui::FlatLabel>(
button,
rpl::single(QString()),
st);
context.repaint = [=] { buttonLabel->update(); };
rpl::duplicate(
text
) | rpl::filter([=](const TextWithEntities &text) {
return !text.text.isEmpty();
}) | rpl::start_with_next([=](const TextWithEntities &text) {
buttonLabel->setMarkedText(
text,
context([=] { buttonLabel->update(); }));
buttonLabel->setMarkedText(text, context);
}, buttonLabel->lifetime());
if (textFg) {
buttonLabel->setTextColorOverride((*textFg)->c);
@ -562,12 +561,9 @@ not_null<FlatLabel*> SetButtonMarkedLabel(
not_null<Main::Session*> session,
const style::FlatLabel &st,
const style::color *textFg) {
return SetButtonMarkedLabel(button, text, [=](Fn<void()> update) {
return Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = update,
};
}, st, textFg);
return SetButtonMarkedLabel(button, text, Core::TextContext({
.session = session,
}), st, textFg);
}
void SendStarsForm(

View file

@ -41,7 +41,7 @@ void SendCreditsBox(
not_null<FlatLabel*> SetButtonMarkedLabel(
not_null<RpWidget*> button,
rpl::producer<TextWithEntities> text,
Fn<std::any(Fn<void()> update)> context,
Text::MarkedContext context,
const style::FlatLabel &st,
const style::color *textFg = nullptr);

View file

@ -859,10 +859,9 @@ void SendFilesBox::refreshPriceTag() {
QString(),
st::paidTagLabel);
std::move(text) | rpl::start_with_next([=](TextWithEntities &&text) {
label->setMarkedText(text, Core::MarkedTextContext{
label->setMarkedText(text, Core::TextContext({
.session = session,
.customEmojiRepaint = [=] { label->update(); },
});
}));
}, label->lifetime());
label->show();
label->sizeValue() | rpl::start_with_next([=](QSize size) {

View file

@ -231,7 +231,7 @@ auto GenerateGiftMedia(
TextWithEntities text,
QMargins margins = {},
const base::flat_map<uint16, ClickHandlerPtr> &links = {},
const std::any &context = {}) {
Ui::Text::MarkedContext context = {}) {
if (text.empty()) {
return;
}
@ -240,7 +240,7 @@ auto GenerateGiftMedia(
margins,
st::defaultTextStyle,
links,
context));
std::move(context)));
};
const auto sticker = [=] {
@ -310,10 +310,10 @@ auto GenerateGiftMedia(
auto description = data.text.empty()
? std::move(textFallback)
: data.text;
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &parent->history()->session(),
.customEmojiRepaint = [parent] { parent->repaint(); },
};
.repaint = [parent] { parent->repaint(); },
});
pushText(
std::move(title),
st::giftBoxPreviewTitlePadding,
@ -759,15 +759,11 @@ void PreviewWrap::paintEvent(QPaintEvent *e) {
}
auto &manager = session->data().customEmojiManager();
auto result = Text::String();
const auto context = Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = [] {},
};
result.setMarkedText(
st::semiboldTextStyle,
manager.creditsEmoji().append(QString::number(price)),
kMarkupTextOptions,
context);
Core::TextContext({ .session = session }));
return result;
}
@ -1322,12 +1318,6 @@ void AddUpgradeButton(
button->toggleOn(rpl::single(false))->toggledValue(
) | rpl::start_with_next(toggled, button->lifetime());
const auto makeContext = [session](Fn<void()> update) {
return Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = std::move(update),
};
};
auto star = session->data().customEmojiManager().creditsEmoji();
const auto label = Ui::CreateChild<Ui::FlatLabel>(
button,
@ -1339,7 +1329,7 @@ void AddUpgradeButton(
Text::WithEntities),
st::boxLabel,
st::defaultPopupMenu,
std::move(makeContext));
Core::TextContext({ .session = session }));
label->show();
label->setAttribute(Qt::WA_TransparentForMouseEvents);
button->widthValue() | rpl::start_with_next([=](int outer) {

View file

@ -150,10 +150,7 @@ void TranslateBox(
original->entity()->setAnimationsPausedCallback(animationsPaused);
original->entity()->setMarkedText(
text,
Core::MarkedTextContext{
.session = &peer->session(),
.customEmojiRepaint = [=] { original->entity()->update(); },
});
Core::TextContext({ .session = &peer->session() }));
original->setMinimalHeight(lineHeight);
original->hide(anim::type::instant);
@ -221,10 +218,7 @@ void TranslateBox(
const auto label = translated->entity();
label->setMarkedText(
text,
Core::MarkedTextContext{
.session = &peer->session(),
.customEmojiRepaint = [=] { label->update(); },
});
Core::TextContext({ .session = &peer->session() }));
translated->show(anim::type::instant);
loading->hide(anim::type::instant);
};

View file

@ -433,12 +433,9 @@ void InitMessageFieldHandlers(MessageFieldHandlersArgs &&args) {
const auto session = args.session;
field->setTagMimeProcessor(
FieldTagMimeProcessor(session, args.allowPremiumEmoji));
field->setCustomTextContext([=](Fn<void()> repaint) {
return std::any(Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = std::move(repaint),
});
}, [paused] {
field->setCustomTextContext(Core::TextContext({
.session = session
}), [paused] {
return On(PowerSaving::kEmojiChat) || paused();
}, [paused] {
return On(PowerSaving::kChatSpoiler) || paused();

View file

@ -109,6 +109,40 @@ const auto kBadPrefix = u"http://"_q;
} // namespace
Ui::Text::MarkedContext TextContext(TextContextArgs &&args) {
using Context = Ui::Text::MarkedContext;
using Factory = Ui::Text::CustomEmojiFactory;
const auto session = args.session;
auto simple = [session](QStringView data, const Context &context) {
return session->data().customEmojiManager().create(
data,
context.repaint);
};
auto factory = !args.customEmojiLoopLimit
? Factory(simple)
: (args.customEmojiLoopLimit > 0)
? Factory([simple, loop = args.customEmojiLoopLimit](
QStringView data,
const Context &context) {
return std::make_unique<Ui::Text::LimitedLoopsEmoji>(
simple(data, context),
loop);
})
: Factory([simple](
QStringView data,
const Context &context) {
return std::make_unique<Ui::Text::FirstFrameEmoji>(
simple(data, context));
});
args.details.session = session;
return {
.repaint = std::move(args.repaint),
.customEmojiFactory = std::move(factory),
.other = std::move(args.details),
};
}
void UiIntegration::postponeCall(FnMut<void()> &&callable) {
Sandbox::Instance().postponeCall(std::move(callable));
}
@ -149,8 +183,8 @@ bool UiIntegration::screenIsLocked() {
std::shared_ptr<ClickHandler> UiIntegration::createLinkHandler(
const EntityLinkData &data,
const std::any &context) {
const auto my = std::any_cast<MarkedTextContext>(&context);
const Ui::Text::MarkedContext &context) {
const auto my = std::any_cast<Core::TextContextDetails>(&context.other);
switch (data.type) {
case EntityType::Url:
return (!data.data.isEmpty()
@ -167,7 +201,7 @@ std::shared_ptr<ClickHandler> UiIntegration::createLinkHandler(
return std::make_shared<BotCommandClickHandler>(data.data);
case EntityType::Hashtag:
using HashtagMentionType = MarkedTextContext::HashtagMentionType;
using HashtagMentionType = TextContextDetails::HashtagMentionType;
if (my && my->type == HashtagMentionType::Twitter) {
return std::make_shared<UrlClickHandler>(
(u"https://twitter.com/hashtag/"_q
@ -187,7 +221,7 @@ std::shared_ptr<ClickHandler> UiIntegration::createLinkHandler(
return std::make_shared<CashtagClickHandler>(data.data);
case EntityType::Mention:
using HashtagMentionType = MarkedTextContext::HashtagMentionType;
using HashtagMentionType = TextContextDetails::HashtagMentionType;
if (my && my->type == HashtagMentionType::Twitter) {
return std::make_shared<UrlClickHandler>(
u"https://twitter.com/"_q + data.data.mid(1),
@ -219,7 +253,9 @@ std::shared_ptr<ClickHandler> UiIntegration::createLinkHandler(
case EntityType::Pre:
return std::make_shared<MonospaceClickHandler>(data.text, data.type);
case EntityType::Phone:
return std::make_shared<PhoneClickHandler>(my->session, data.text);
return my->session
? std::make_shared<PhoneClickHandler>(my->session, data.text)
: nullptr;
}
return Integration::createLinkHandler(data, context);
}
@ -273,39 +309,6 @@ bool UiIntegration::copyPreOnClick(const QVariant &context) {
return true;
}
std::unique_ptr<Ui::Text::CustomEmoji> UiIntegration::createCustomEmoji(
QStringView data,
const std::any &context) {
if (auto simple = Ui::Text::TryMakeSimpleEmoji(data)) {
return simple;
}
const auto my = std::any_cast<MarkedTextContext>(&context);
if (!my || !my->session) {
return nullptr;
}
auto result = my->session->data().customEmojiManager().create(
data,
my->customEmojiRepaint);
if (my->customEmojiLoopLimit > 0) {
return std::make_unique<Ui::Text::LimitedLoopsEmoji>(
std::move(result),
my->customEmojiLoopLimit);
} else if (my->customEmojiLoopLimit) {
return std::make_unique<Ui::Text::FirstFrameEmoji>(
std::move(result));
}
return result;
}
Fn<void()> UiIntegration::createSpoilerRepaint(const std::any &context) {
const auto my = std::any_cast<MarkedTextContext>(&context);
if (my) {
return my->customEmojiRepaint;
}
const auto common = std::any_cast<CommonTextContext>(&context);
return common ? common->repaint : nullptr;
}
rpl::producer<> UiIntegration::forcePopupMenuHideRequests() {
return Core::App().passcodeLockChanges() | rpl::to_empty;
}

View file

@ -19,7 +19,7 @@ class ElementDelegate;
namespace Core {
struct MarkedTextContext {
struct TextContextDetails {
enum class HashtagMentionType : uchar {
Telegram,
Twitter,
@ -28,9 +28,15 @@ struct MarkedTextContext {
Main::Session *session = nullptr;
HashtagMentionType type = HashtagMentionType::Telegram;
Fn<void()> customEmojiRepaint;
};
struct TextContextArgs {
not_null<Main::Session*> session;
TextContextDetails details;
Fn<void()> repaint;
int customEmojiLoopLimit = 0;
};
[[nodiscard]] Ui::Text::MarkedContext TextContext(TextContextArgs &&args);
class UiIntegration final : public Ui::Integration {
public:
@ -49,7 +55,7 @@ public:
std::shared_ptr<ClickHandler> createLinkHandler(
const EntityLinkData &data,
const std::any &context) override;
const Ui::Text::MarkedContext &context) override;
bool handleUrlClick(
const QString &url,
const QVariant &context) override;
@ -57,10 +63,6 @@ public:
rpl::producer<> forcePopupMenuHideRequests() override;
const Ui::Emoji::One *defaultEmojiVariant(
const Ui::Emoji::One *emoji) override;
std::unique_ptr<Ui::Text::CustomEmoji> createCustomEmoji(
QStringView data,
const std::any &context) override;
Fn<void()> createSpoilerRepaint(const std::any &context) override;
QString phraseContextCopyText() override;
QString phraseContextCopyEmail() override;

View file

@ -519,8 +519,8 @@ std::unique_ptr<Ui::Text::CustomEmoji> CustomEmojiManager::create(
Ui::Text::CustomEmojiFactory CustomEmojiManager::factory(
SizeTag tag,
int sizeOverride) {
return [=](QStringView data, Fn<void()> update) {
return create(data, std::move(update), tag, sizeOverride);
return [=](QStringView data, const Ui::Text::MarkedContext &context) {
return create(data, context.repaint, tag, sizeOverride);
};
}
@ -1145,8 +1145,9 @@ void InsertCustomEmoji(
Ui::Text::CustomEmojiFactory ReactedMenuFactory(
not_null<Main::Session*> session) {
return [owner = &session->data()](
QStringView data,
Fn<void()> repaint) -> std::unique_ptr<Ui::Text::CustomEmoji> {
QStringView data,
const Ui::Text::MarkedContext &context
) -> std::unique_ptr<Ui::Text::CustomEmoji> {
const auto prefix = u"default:"_q;
if (data.startsWith(prefix)) {
const auto &list = owner->reactions().list(
@ -1166,13 +1167,13 @@ Ui::Text::CustomEmojiFactory ReactedMenuFactory(
std::make_unique<Ui::Text::ShiftedEmoji>(
owner->customEmojiManager().create(
document,
std::move(repaint),
context.repaint,
tag,
size),
QPoint(skip, skip)));
}
}
return owner->customEmojiManager().create(data, std::move(repaint));
return owner->customEmojiManager().create(data, context.repaint);
};
}

View file

@ -4308,10 +4308,7 @@ QImage *InnerWidget::cacheChatsFilterTag(
const auto color = Ui::EmptyUserpic::UserpicColor(colorIndex).color2;
entry.context.color = color->c;
entry.context.active = active;
entry.context.textContext = Core::MarkedTextContext{
.session = &session(),
.customEmojiRepaint = [] {},
};
entry.context.textContext = Core::TextContext({ .session = &session() });
entry.frame = Ui::ChatsFilterTag(roundedText, entry.context);
return &entry.frame;
}

View file

@ -60,11 +60,10 @@ namespace {
st::dialogsSearchTagArrow,
st::dialogsSearchTagArrowPadding));
auto result = Ui::Text::String();
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &owner->session(),
.customEmojiRepaint = [] {},
.customEmojiLoopLimit = 1,
};
});
const auto attempt = [&](const auto &phrase) {
result.setMarkedText(
st::dialogsSearchTagPromo,

View file

@ -580,10 +580,10 @@ void PaintRow(
{},
true))).append(std::move(draftText));
}
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &thread->session(),
.customEmojiRepaint = customEmojiRepaint,
};
.repaint = customEmojiRepaint,
});
cache.setMarkedText(
st::dialogsTextStyle,
std::move(draftText),

View file

@ -174,11 +174,11 @@ void MessageView::prepare(
: nullptr;
const auto hasImages = !preview.images.empty();
const auto history = item->history();
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &history->session(),
.customEmojiRepaint = customEmojiRepaint,
.repaint = customEmojiRepaint,
.customEmojiLoopLimit = kEmojiLoopCount,
};
});
const auto senderTill = (preview.arrowInTextPosition > 0)
? preview.arrowInTextPosition
: preview.imagesInTextPosition;

View file

@ -63,11 +63,11 @@ void TopicsView::prepare(MsgId frontRootId, Fn<void()> customEmojiRepaint) {
&& title.version == topic->titleVersion()) {
continue;
}
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &topic->session(),
.customEmojiRepaint = customEmojiRepaint,
.repaint = customEmojiRepaint,
.customEmojiLoopLimit = kIconLoopCount,
};
});
auto topicTitle = topic->titleWithIcon();
title.topicRootId = rootId;
title.version = topic->titleVersion();

View file

@ -1169,12 +1169,6 @@ void History::applyServiceChanges(
}
if (paid) {
// Toast on a current active window.
const auto context = [=](not_null<QWidget*> toast) {
return Core::MarkedTextContext{
.session = &session(),
.customEmojiRepaint = [=] { toast->update(); },
};
};
Ui::Toast::Show({
.text = tr::lng_payments_success(
tr::now,
@ -1185,7 +1179,9 @@ void History::applyServiceChanges(
lt_title,
Ui::Text::Bold(paid->title),
Ui::Text::WithEntities),
.textContext = context,
.textContext = Core::TextContext({
.session = &session(),
}),
});
}
}

View file

@ -205,7 +205,9 @@ void HistoryMessageForwarded::create(
const HistoryMessageVia *via,
not_null<const HistoryItem*> item) const {
auto phrase = TextWithEntities();
auto context = Core::MarkedTextContext{};
auto context = Core::TextContext({
.session = &item->history()->session(),
});
const auto fromChannel = originalSender
&& originalSender->isChannel()
&& !originalSender->isMegagroup();
@ -215,8 +217,7 @@ void HistoryMessageForwarded::create(
: originalHiddenSenderInfo->name)
};
if (const auto copy = originalSender) {
context.session = &copy->owner().session();
context.customEmojiRepaint = [=] {
context.repaint = [=] {
// It is important to capture here originalSender by value,
// not capture the HistoryMessageForwarded* and read the
// originalSender field, because the components themselves
@ -225,7 +226,7 @@ void HistoryMessageForwarded::create(
copy->owner().requestItemRepaint(item);
};
phrase = Ui::Text::SingleCustomEmoji(
context.session->data().customEmojiManager().peerUserpicEmojiData(
copy->owner().customEmojiManager().peerUserpicEmojiData(
copy,
st::fwdTextUserpicPadding));
}
@ -755,10 +756,10 @@ ReplyKeyboard::ReplyKeyboard(
_st->textStyle(),
TextUtilities::SingleLine(textWithEntities),
kMarkupTextOptions,
Core::MarkedTextContext{
Core::TextContext({
.session = &item->history()->owner().session(),
.customEmojiRepaint = [=] { _st->repaint(item); },
});
.repaint = [=] { _st->repaint(item); },
}));
} else {
button.text.setText(
_st->textStyle(),

View file

@ -31,16 +31,10 @@ void InfoTooltip::show(
not_null<Main::Session*> session,
const TextWithEntities &text,
Fn<void()> hiddenCallback) {
const auto context = [=](not_null<QWidget*> toast) {
return Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = [=] { toast->update(); },
};
};
hide(anim::type::normal);
_topToast = Ui::Toast::Show(parent, Ui::Toast::Config{
.text = text,
.textContext = context,
.textContext = Core::TextContext({ .session = session }),
.st = &st::historyInfoToast,
.attach = RectPart::Top,
.duration = CountToastDuration(text),

View file

@ -8829,10 +8829,10 @@ void HistoryWidget::messageDataReceived(
}
void HistoryWidget::updateReplyEditText(not_null<HistoryItem*> item) {
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &session(),
.customEmojiRepaint = [=] { updateField(); },
};
.repaint = [=] { updateField(); },
});
_replyEditMsgText.setMarkedText(
st::defaultTextStyle,
((_editMsgId || _replyTo.quote.empty())
@ -8918,11 +8918,10 @@ void HistoryWidget::updateReplyToName() {
} else if (!_replyEditMsg && (_replyTo || !_kbReplyTo)) {
return;
}
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &_history->session(),
.customEmojiRepaint = [] {},
.customEmojiLoopLimit = 1,
};
});
const auto to = _replyEditMsg ? _replyEditMsg : _kbReplyTo;
const auto replyToQuote = _replyTo && !_replyTo.quote.empty();
_replyToName.setMarkedText(

View file

@ -428,10 +428,10 @@ void FieldHeader::init() {
void FieldHeader::updateShownMessageText() {
Expects(_shownMessage != nullptr);
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &_data->session(),
.customEmojiRepaint = [=] { customEmojiRepaint(); },
};
.repaint = [=] { customEmojiRepaint(); },
});
const auto reply = replyingToMessage();
_shownMessageText.setMarkedText(
st::messageTextStyle,
@ -464,11 +464,10 @@ void FieldHeader::setShownMessage(HistoryItem *item) {
tr::lng_edit_message(tr::now),
Ui::NameTextOptions());
} else if (item) {
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &_history->session(),
.customEmojiRepaint = [] {},
.customEmojiLoopLimit = 1,
};
});
const auto replyTo = _replyTo.current();
const auto quote = replyTo && !replyTo.quote.empty();
_shownMessageName.setMarkedText(

View file

@ -190,10 +190,10 @@ void ForwardPanel::updateTexts() {
}
}
_from.setText(st::msgNameStyle, from, Ui::NameTextOptions());
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &_to->session(),
.customEmojiRepaint = _repaint,
};
.repaint = _repaint,
});
_text.setMarkedText(
st::defaultTextStyle,
text,

View file

@ -234,10 +234,10 @@ auto GenerateNewPeerInfo(
fadedFg,
normalFg));
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &parent->history()->session(),
.customEmojiRepaint = [parent] { parent->repaint(); },
};
.repaint = [parent] { parent->repaint(); },
});
const auto details = user->botVerifyDetails();
const auto text = details
? Data::SingleCustomEmoji(

View file

@ -163,7 +163,7 @@ public:
void showState(
State state,
TextWithEntities status,
Fn<std::any(Fn<void()> customEmojiRepaint)> context);
Ui::Text::MarkedContext context);
[[nodiscard]] rpl::producer<> unarchiveClicks() const;
[[nodiscard]] rpl::producer<> addClicks() const;
@ -272,7 +272,7 @@ ContactStatus::Bar::Bar(
void ContactStatus::Bar::showState(
State state,
TextWithEntities status,
Fn<std::any(Fn<void()> customEmojiRepaint)> context) {
Ui::Text::MarkedContext context) {
using Type = State::Type;
const auto type = state.type;
_add->setVisible(type == Type::AddOrBlock || type == Type::Add);
@ -294,6 +294,7 @@ void ContactStatus::Bar::showState(
_emojiStatusShadow->setVisible(
has && (type == Type::AddOrBlock || type == Type::UnarchiveOrBlock));
if (has) {
context.repaint = [=] { emojiStatusRepaint(); };
_emojiStatusInfo->entity()->setMarkedText(
tr::lng_new_contact_about_status(
tr::now,
@ -303,7 +304,7 @@ void ContactStatus::Bar::showState(
Ui::Text::Link(
tr::lng_new_contact_about_status_link(tr::now)),
Ui::Text::WithEntities),
context([=] { emojiStatusRepaint(); }));
context);
_emojiStatusInfo->entity()->overrideLinkClickHandler([=] {
_emojiStatusClicks.fire({});
});
@ -628,12 +629,7 @@ void ContactStatus::setupState(not_null<PeerData*> peer, bool showInForum) {
peer->session().api().requestPeerSettings(peer);
}
_context = [=](Fn<void()> customEmojiRepaint) {
return Core::MarkedTextContext{
.session = &peer->session(),
.customEmojiRepaint = customEmojiRepaint,
};
};
_context = Core::TextContext({ .session = &peer->session() });
_inner->showState({}, {}, _context);
const auto channel = peer->asChannel();
rpl::combine(

View file

@ -117,7 +117,7 @@ private:
const not_null<Window::SessionController*> _controller;
State _state;
TextWithEntities _status;
Fn<std::any(Fn<void()> customEmojiRepaint)> _context;
Ui::Text::MarkedContext _context;
QPointer<Bar> _inner;
SlidingBar _bar;
bool _hiddenByForum = false;

View file

@ -1171,10 +1171,10 @@ void Element::validateText() {
void Element::setTextWithLinks(
const TextWithEntities &text,
const std::vector<ClickHandlerPtr> &links) {
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &history()->session(),
.customEmojiRepaint = [=] { customEmojiRepaint(); },
};
.repaint = [=] { customEmojiRepaint(); },
});
if (_flags & Flag::ServiceMessage) {
const auto &options = Ui::ItemTextServiceOptions();
_text.setMarkedText(st::serviceTextStyle, text, options, context);

View file

@ -550,11 +550,10 @@ void Message::refreshRightBadge() {
if (badge.empty()) {
_rightBadge.clear();
} else {
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &item->history()->session(),
.customEmojiRepaint = [] {},
.customEmojiLoopLimit = 1,
};
});
_rightBadge.setMarkedText(
st::defaultTextStyle,
badge,
@ -1049,11 +1048,11 @@ void Message::refreshTopicButton() {
_topicButton->link = MakeTopicButtonLink(topic, jumpToId);
if (_topicButton->nameVersion != topic->titleVersion()) {
_topicButton->nameVersion = topic->titleVersion();
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &history()->session(),
.customEmojiRepaint = [=] { customEmojiRepaint(); },
.repaint = [=] { customEmojiRepaint(); },
.customEmojiLoopLimit = 1,
};
});
_topicButton->name.setMarkedText(
st::fwdTextStyle,
topic->titleWithIcon(),

View file

@ -29,10 +29,10 @@ namespace {
Fn<void()> repaint) {
return Ui::MessageBarContent{
.text = item->inReplyText(),
.context = Core::MarkedTextContext{
.context = Core::TextContext({
.session = &item->history()->session(),
.customEmojiRepaint = std::move(repaint),
},
.repaint = std::move(repaint),
}),
};
}

View file

@ -244,10 +244,10 @@ void Reply::update(
}).text
: TextWithEntities();
const auto repaint = [=] { item->customEmojiRepaint(); };
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &view->history()->session(),
.customEmojiRepaint = repaint,
};
.repaint = repaint,
});
_text.setMarkedText(
st::defaultTextStyle,
text,
@ -463,11 +463,10 @@ void Reply::updateName(
if (!viaBotUsername.isEmpty()) {
nameFull.append(u" @"_q).append(viaBotUsername);
}
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &history->session(),
.customEmojiRepaint = [] {},
.customEmojiLoopLimit = 1,
};
});
_name.setMarkedText(
st::fwdTextStyle,
nameFull,

View file

@ -38,10 +38,10 @@ Game::Game(
, _title(st::msgMinWidth - _st.padding.left() - _st.padding.right())
, _description(st::msgMinWidth - _st.padding.left() - _st.padding.right()) {
if (!consumed.text.isEmpty()) {
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &history()->session(),
.customEmojiRepaint = [=] { _parent->customEmojiRepaint(); },
};
.repaint = [=] { _parent->customEmojiRepaint(); },
});
_description.setMarkedText(
st::webPageDescriptionStyle,
consumed,
@ -503,10 +503,10 @@ void Game::parentTextUpdated() {
if (const auto media = _parent->data()->media()) {
const auto consumed = media->consumedMessageText();
if (!consumed.text.isEmpty()) {
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &history()->session(),
.customEmojiRepaint = [=] { _parent->customEmojiRepaint(); },
};
.repaint = [=] { _parent->customEmojiRepaint(); },
});
_description.setMarkedText(
st::webPageDescriptionStyle,
consumed,

View file

@ -244,10 +244,11 @@ void Media::drawPurchasedTag(
const auto session = &item->history()->session();
auto text = Ui::Text::Colorized(Ui::CreditsEmojiSmall(session));
text.append(Lang::FormatCountDecimal(amount));
purchased->text.setMarkedText(st::defaultTextStyle, text, kMarkupTextOptions, Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = [] {},
});
purchased->text.setMarkedText(
st::defaultTextStyle,
text,
kMarkupTextOptions,
Core::TextContext({ .session = session }));
}
const auto st = context.st;
@ -413,10 +414,7 @@ void Media::drawSpoilerTag(
price,
Ui::Text::WithEntities),
kMarkupTextOptions,
Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = [] {},
});
Core::TextContext({ .session = session }));
}
const auto width = iconSkip + text.maxWidth();
const auto inner = QRect(0, 0, width, text.minHeight());
@ -541,10 +539,10 @@ Ui::Text::String Media::createCaption(not_null<HistoryItem*> item) const {
- st::msgPadding.left()
- st::msgPadding.right();
auto result = Ui::Text::String(minResizeWidth);
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &history()->session(),
.customEmojiRepaint = [=] { _parent->customEmojiRepaint(); },
};
.repaint = [=] { _parent->customEmojiRepaint(); },
});
result.setMarkedText(
st::messageTextStyle,
item->translatedTextWithLocalEntities(),

View file

@ -236,7 +236,7 @@ MediaGenericTextPart::MediaGenericTextPart(
QMargins margins,
const style::TextStyle &st,
const base::flat_map<uint16, ClickHandlerPtr> &links,
const std::any &context)
const Ui::Text::MarkedContext &context)
: _text(st::msgMinWidth)
, _margins(margins) {
_text.setMarkedText(

View file

@ -141,7 +141,7 @@ public:
QMargins margins,
const style::TextStyle &st = st::defaultTextStyle,
const base::flat_map<uint16, ClickHandlerPtr> &links = {},
const std::any &context = {});
const Ui::Text::MarkedContext &context = {});
void draw(
Painter &p,

View file

@ -7,7 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "history/view/media/history_view_poll.h"
#include "core/ui_integration.h" // Core::MarkedTextContext.
#include "core/ui_integration.h" // TextContext
#include "lang/lang_keys.h"
#include "history/history.h"
#include "history/history_item.h"
@ -158,7 +158,7 @@ struct Poll::Answer {
void fillData(
not_null<PollData*> poll,
const PollAnswer &original,
Core::MarkedTextContext context);
Ui::Text::MarkedContext context);
Ui::Text::String text;
QByteArray option;
@ -206,7 +206,7 @@ Poll::Answer::Answer() : text(st::msgMinWidth / 2) {
void Poll::Answer::fillData(
not_null<PollData*> poll,
const PollAnswer &original,
Core::MarkedTextContext context) {
Ui::Text::MarkedContext context) {
chosen = original.chosen;
correct = poll->quiz() ? original.correct : chosen;
if (!text.isEmpty() && text.toTextWithEntities() == original.text) {
@ -396,11 +396,11 @@ void Poll::updateTexts() {
st::historyPollQuestionStyle,
_poll->question,
options,
Core::MarkedTextContext{
Core::TextContext({
.session = &_poll->session(),
.customEmojiRepaint = [=] { repaint(); },
.repaint = [=] { repaint(); },
.customEmojiLoopLimit = 2,
});
}));
}
if (_flags != _poll->flags() || _subtitle.isEmpty()) {
using Flag = PollData::Flag;
@ -525,11 +525,11 @@ void Poll::updateRecentVoters() {
}
void Poll::updateAnswers() {
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &_poll->session(),
.customEmojiRepaint = [=] { repaint(); },
.repaint = [=] { repaint(); },
.customEmojiLoopLimit = 2,
};
});
const auto changed = !ranges::equal(
_answers,
_poll->answers,

View file

@ -47,10 +47,10 @@ ServiceBox::ServiceBox(
_content->title(),
kMarkupTextOptions,
_maxWidth,
Core::MarkedTextContext{
Core::TextContext({
.session = &parent->history()->session(),
.customEmojiRepaint = [parent] { parent->customEmojiRepaint(); },
})
.repaint = [parent] { parent->customEmojiRepaint(); },
}))
, _subtitle(
st::premiumPreviewAbout.style,
Ui::Text::Filtered(
@ -65,10 +65,10 @@ ServiceBox::ServiceBox(
}),
kMarkupTextOptions,
_maxWidth,
Core::MarkedTextContext{
Core::TextContext({
.session = &parent->history()->session(),
.customEmojiRepaint = [parent] { parent->customEmojiRepaint(); },
})
.repaint = [parent] { parent->customEmojiRepaint(); },
}))
, _size(
_content->width(),
(st::msgServiceGiftBoxTopSkip

View file

@ -441,7 +441,7 @@ TextPartColored::TextPartColored(
Fn<QColor(const PaintContext &)> color,
const style::TextStyle &st,
const base::flat_map<uint16, ClickHandlerPtr> &links,
const std::any &context)
const Ui::Text::MarkedContext &context)
: MediaGenericTextPart(text, margins, st, links, context)
, _color(std::move(color)) {
}
@ -458,7 +458,7 @@ AttributeTable::AttributeTable(
QMargins margins,
Fn<QColor(const PaintContext &)> labelColor,
Fn<QColor(const PaintContext &)> valueColor,
const std::any &context)
const Ui::Text::MarkedContext &context)
: _margins(margins)
, _labelColor(std::move(labelColor))
, _valueColor(std::move(valueColor)) {

View file

@ -66,7 +66,7 @@ public:
Fn<QColor(const PaintContext &)> color,
const style::TextStyle &st = st::defaultTextStyle,
const base::flat_map<uint16, ClickHandlerPtr> &links = {},
const std::any &context = {});
const Ui::Text::MarkedContext &context = {});
private:
void setupPen(
@ -90,7 +90,7 @@ public:
QMargins margins,
Fn<QColor(const PaintContext &)> labelColor,
Fn<QColor(const PaintContext &)> valueColor,
const std::any &context = {});
const Ui::Text::MarkedContext &context = {});
void draw(
Painter &p,

View file

@ -379,11 +379,10 @@ QSize WebPage::countOptimalSize() {
// Detect _openButtonWidth before counting paddings.
_openButton = Ui::Text::String();
if (HasButton(_data)) {
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &_data->session(),
.customEmojiRepaint = [] {},
.customEmojiLoopLimit = 1,
};
});
_openButton.setMarkedText(
st::semiboldTextStyle,
PageToPhrase(_data),
@ -539,16 +538,18 @@ QSize WebPage::countOptimalSize() {
_description = Ui::Text::String(st::minPhotoSize
- rect::m::sum::h(padding));
}
using MarkedTextContext = Core::MarkedTextContext;
auto context = MarkedTextContext{
using Type = Core::TextContextDetails::HashtagMentionType;
auto context = Core::TextContext({
.session = &history()->session(),
.customEmojiRepaint = [=] { _parent->customEmojiRepaint(); },
};
if (_data->siteName == u"Twitter"_q) {
context.type = MarkedTextContext::HashtagMentionType::Twitter;
} else if (_data->siteName == u"Instagram"_q) {
context.type = MarkedTextContext::HashtagMentionType::Instagram;
}
.details = {
.type = ((_data->siteName == u"Twitter"_q)
? Type::Twitter
: (_data->siteName == u"Instagram"_q)
? Type::Instagram
: Type::Telegram),
},
.repaint = [=] { _parent->customEmojiRepaint(); },
});
_description.setMarkedText(
st::webPageDescriptionStyle,
text,

View file

@ -154,7 +154,7 @@ Row::Row(
: PeerListRow(peer, id)
, _custom(reactionEntityData.isEmpty()
? nullptr
: factory(reactionEntityData, [=] { repaint(this); }))
: factory(reactionEntityData, { .repaint = [=] { repaint(this); } }))
, _paused(std::move(paused)) {
}

View file

@ -58,7 +58,7 @@ not_null<Ui::AbstractButton*> CreateTab(
? nullptr
: factory(
Data::ReactionEntityData(reaction),
[=] { result->update(); });
{ .repaint = [=] { result->update(); } });
result->paintRequest(
) | rpl::start_with_next([=] {

View file

@ -600,12 +600,6 @@ object_ptr<Ui::BoxContent> JoinStarRefBox(
if (const auto average = program.revenuePerUser) {
const auto layout = box->verticalLayout();
const auto session = &initialRecipient->session();
const auto makeContext = [session](Fn<void()> update) {
return Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = std::move(update),
};
};
auto text = Ui::Text::Colorized(Ui::CreditsEmoji(session));
text.append(Lang::FormatStarsAmountRounded(average));
layout->add(
@ -618,7 +612,7 @@ object_ptr<Ui::BoxContent> JoinStarRefBox(
Ui::Text::WithEntities),
st::starrefRevenueText,
st::defaultPopupMenu,
makeContext),
Core::TextContext({ .session = session })),
st::boxRowPadding);
Ui::AddSkip(layout, st::defaultVerticalListSkip);
}

View file

@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/edit_peer_color_box.h" // AddLevelBadge.
#include "chat_helpers/stickers_emoji_pack.h"
#include "core/application.h"
#include "core/ui_integration.h" // TextContext.
#include "data/components/credits.h"
#include "data/data_channel.h"
#include "data/data_premium_limits.h"
@ -402,12 +403,6 @@ void InnerWidget::fill() {
const auto session = &_peer->session();
const auto withdrawalEnabled = WithdrawalEnabled(session);
const auto makeContext = [=](not_null<Ui::FlatLabel*> l) {
return Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = [=] { l->update(); },
};
};
const auto addEmojiToMajor = [=](
not_null<Ui::FlatLabel*> label,
rpl::producer<EarnInt> value,
@ -433,7 +428,7 @@ void InnerWidget::fill() {
) | rpl::start_with_next([=](EarnInt v) {
label->setMarkedText(
base::duplicate(prepended).append(icon).append(MajorPart(v)),
makeContext(label));
Core::TextContext({ .session = session }));
}, label->lifetime());
};
@ -445,11 +440,7 @@ void InnerWidget::fill() {
st::channelEarnCurrencyLearnMargins,
false));
const auto arrow = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::topicButtonArrow,
st::channelEarnLearnArrowMargins,
true));
const auto arrow = Ui::Text::IconEmoji(&st::textMoreIconEmoji);
const auto addAboutWithLearn = [&](const tr::phrase<lngtag_link> &text) {
auto label = Ui::CreateLabelWithCustomEmoji(
container,
@ -463,7 +454,7 @@ void InnerWidget::fill() {
return Ui::Text::Link(std::move(text), 1);
}),
Ui::Text::RichLangValue),
{ .session = session },
Core::TextContext({ .session = session }),
st::boxDividerLabel);
label->setLink(1, std::make_shared<LambdaClickHandler>([=] {
_show->showBox(Box([=](not_null<Ui::GenericBox*> box) {
@ -580,7 +571,7 @@ void InnerWidget::fill() {
Ui::Text::Link(bigCurrencyIcon, 1)),
Ui::Text::RichLangValue
),
{ .session = session },
Core::TextContext({ .session = session }),
st::boxTitle)))->entity();
const auto diamonds = l->lifetime().make_state<int>(0);
l->setLink(1, std::make_shared<LambdaClickHandler>([=] {
@ -610,7 +601,7 @@ void InnerWidget::fill() {
}),
Ui::Text::RichLangValue
),
{ .session = session },
Core::TextContext({ .session = session }),
st::channelEarnLearnDescription));
label->resizeToWidth(box->width()
- rect::m::sum::h(st::boxRowPadding));
@ -1522,4 +1513,3 @@ not_null<PeerData*> InnerWidget::peer() const {
}
} // namespace Info::ChannelEarn

View file

@ -573,11 +573,8 @@ TextWithEntities Delegate::ministar() {
return owner->customEmojiManager().ministarEmoji({ 0, top, 0, 0 });
}
std::any Delegate::textContext() {
return Core::MarkedTextContext{
.session = &_window->session(),
.customEmojiRepaint = [] {},
};
Ui::Text::MarkedContext Delegate::textContext() {
return Core::TextContext({ .session = &_window->session() });
}
QSize Delegate::buttonSize() {

View file

@ -105,7 +105,7 @@ class GiftButtonDelegate {
public:
[[nodiscard]] virtual TextWithEntities star() = 0;
[[nodiscard]] virtual TextWithEntities ministar() = 0;
[[nodiscard]] virtual std::any textContext() = 0;
[[nodiscard]] virtual Ui::Text::MarkedContext textContext() = 0;
[[nodiscard]] virtual QSize buttonSize() = 0;
[[nodiscard]] virtual QMargins buttonExtend() = 0;
[[nodiscard]] virtual auto buttonPatternEmoji(
@ -181,7 +181,7 @@ public:
TextWithEntities star() override;
TextWithEntities ministar() override;
std::any textContext() override;
Ui::Text::MarkedContext textContext() override;
QSize buttonSize() override;
QMargins buttonExtend() override;
auto buttonPatternEmoji(

View file

@ -895,10 +895,10 @@ rpl::producer<uint64> AddCurrencyAction(
.append(QChar(' '))
.append(Info::ChannelEarn::MajorPart(balance))
.append(Info::ChannelEarn::MinorPart(balance)),
Core::MarkedTextContext{
Core::TextContext({
.session = &user->session(),
.customEmojiRepaint = [=] { name->update(); },
});
.repaint = [=] { name->update(); },
}));
name->resizeToNaturalWidth(available);
name->moveToRight(st::settingsButtonRightSkip, st.padding.top());
}, name->lifetime());
@ -968,10 +968,10 @@ rpl::producer<StarsAmount> AddCreditsAction(
base::duplicate(icon)
.append(QChar(' '))
.append(Lang::FormatStarsAmountDecimal(balance)),
Core::MarkedTextContext{
Core::TextContext({
.session = &user->session(),
.customEmojiRepaint = [=] { name->update(); },
});
.repaint = [=] { name->update(); },
}));
name->resizeToNaturalWidth(available);
name->moveToRight(st::settingsButtonRightSkip, st.padding.top());
}, name->lifetime());

View file

@ -12,7 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peer_list_controllers.h"
#include "boxes/peer_list_widgets.h"
#include "chat_helpers/stickers_gift_box_pack.h"
#include "core/ui_integration.h" // Core::MarkedTextContext.
#include "core/ui_integration.h" // TextContext
#include "data/data_channel.h"
#include "data/data_credits.h"
#include "data/data_session.h"
@ -747,9 +747,10 @@ rpl::producer<int> BoostsController::totalBoostsValue() const {
class CreditsRow final : public PeerListRow {
public:
struct Descriptor final {
not_null<Main::Session*> session;
Data::CreditsHistoryEntry entry;
Data::SubscriptionEntry subscription;
Core::MarkedTextContext context;
Ui::Text::MarkedContext context;
int rowHeight = 0;
Fn<void(not_null<PeerListRow*>)> updateCallback;
};
@ -790,9 +791,10 @@ public:
private:
void init();
const not_null<Main::Session*> _session;
const Data::CreditsHistoryEntry _entry;
const Data::SubscriptionEntry _subscription;
const Core::MarkedTextContext _context;
const Ui::Text::MarkedContext _context;
const int _rowHeight;
PaintRoundImageCallback _paintUserpicCallback;
@ -812,6 +814,7 @@ CreditsRow::CreditsRow(
not_null<PeerData*> peer,
const Descriptor &descriptor)
: PeerListRow(peer, UniqueRowIdFromEntry(descriptor.entry))
, _session(descriptor.session)
, _entry(descriptor.entry)
, _subscription(descriptor.subscription)
, _context(descriptor.context)
@ -837,6 +840,7 @@ CreditsRow::CreditsRow(
CreditsRow::CreditsRow(const Descriptor &descriptor)
: PeerListRow(UniqueRowIdFromEntry(descriptor.entry))
, _session(descriptor.session)
, _entry(descriptor.entry)
, _subscription(descriptor.subscription)
, _context(descriptor.context)
@ -902,19 +906,19 @@ void CreditsRow::init() {
: _subscription.photoId;
if (descriptionPhotoId) {
_descriptionThumbnail = Ui::MakePhotoThumbnail(
_context.session->data().photo(descriptionPhotoId),
_session->data().photo(descriptionPhotoId),
{});
_descriptionThumbnail->subscribeToUpdates([this] {
const auto thumbnailSide = st::defaultTextStyle.font->height;
_descriptionThumbnailCache = Images::Round(
_descriptionThumbnail->image(thumbnailSide),
ImageRoundRadius::Large);
if (_context.customEmojiRepaint) {
_context.customEmojiRepaint();
if (_context.repaint) {
_context.repaint();
}
});
}
auto &manager = _context.session->data().customEmojiManager();
auto &manager = _session->data().customEmojiManager();
if (_entry) {
constexpr auto kMinus = QChar(0x2212);
_rightText.setMarkedText(
@ -930,9 +934,9 @@ void CreditsRow::init() {
if (!_paintUserpicCallback) {
_paintUserpicCallback = _entry.stargift
? Ui::GenerateGiftStickerUserpicCallback(
_context.session,
_session,
_entry.bareGiftStickerId,
_context.customEmojiRepaint)
_context.repaint)
: !isSpecial
? PeerListRow::generatePaintUserpicCallback(false)
: Ui::GenerateCreditsPaintUserpicCallback(_entry);
@ -1110,7 +1114,7 @@ private:
Api::CreditsHistory _api;
Data::CreditsStatusSlice _firstSlice;
Data::CreditsStatusSlice::OffsetToken _apiToken;
Core::MarkedTextContext _context;
Ui::Text::MarkedContext _context;
rpl::variable<bool> _allLoaded = false;
bool _requesting = false;
@ -1123,10 +1127,7 @@ CreditsController::CreditsController(CreditsDescriptor d)
, _entryClickedCallback(std::move(d.entryClickedCallback))
, _api(d.peer, d.in, d.out)
, _firstSlice(std::move(d.firstSlice))
, _context(Core::MarkedTextContext{
.session = _session,
.customEmojiRepaint = [] {},
}) {
, _context(Core::TextContext({ .session = _session })) {
PeerListController::setStyleOverrides(&st::creditsHistoryEntriesList);
}
@ -1166,6 +1167,7 @@ void CreditsController::applySlice(const Data::CreditsStatusSlice &slice) {
const Data::CreditsHistoryEntry &i,
const Data::SubscriptionEntry &s) {
const auto descriptor = CreditsRow::Descriptor{
.session = &session(),
.entry = i,
.subscription = s,
.context = _context,

View file

@ -87,10 +87,10 @@ MessagePreview::MessagePreview(
st::defaultPeerListItem.nameStyle,
item->toPreview({ .generateImages = false }).text,
Ui::DialogTextOptions(),
Core::MarkedTextContext{
Core::TextContext({
.session = &item->history()->session(),
.customEmojiRepaint = [=] { update(); },
});
.repaint = [=] { update(); },
}));
if (item->media() && item->media()->hasSpoiler()) {
_spoiler = std::make_unique<Ui::SpoilerAnimation>([=] { update(); });
}
@ -131,10 +131,10 @@ MessagePreview::MessagePreview(
st::defaultPeerListItem.nameStyle,
{ tr::lng_in_dlg_story(tr::now) },
Ui::DialogTextOptions(),
Core::MarkedTextContext{
Core::TextContext({
.session = &story->peer()->session(),
.customEmojiRepaint = [=] { update(); },
});
.repaint = [=] { update(); },
}));
if (_preview.isNull()) {
if (const auto photo = story->photo()) {
_photoMedia = photo->createMediaView();

View file

@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/click_handler_types.h"
#include "core/local_url_handlers.h"
#include "core/shortcuts.h"
#include "core/ui_integration.h" // TextContext
#include "data/components/location_pickers.h"
#include "data/data_bot_app.h"
#include "data/data_changes.h"
@ -380,21 +381,16 @@ void FillBotUsepic(
not_null<Ui::GenericBox*> box,
not_null<PeerData*> bot,
base::weak_ptr<Window::SessionController> weak) {
auto arrow = Ui::Text::SingleCustomEmoji(
bot->owner().customEmojiManager().registerInternalEmoji(
st::topicButtonArrow,
st::channelEarnLearnArrowMargins,
true));
auto aboutLabel = Ui::CreateLabelWithCustomEmoji(
box->verticalLayout(),
tr::lng_allow_bot_webview_details(
lt_emoji,
rpl::single(std::move(arrow)),
rpl::single(Ui::Text::IconEmoji(&st::textMoreIconEmoji)),
Ui::Text::RichLangValue
) | rpl::map([](TextWithEntities text) {
return Ui::Text::Link(std::move(text), u"internal:"_q);
}),
{ .session = &bot->session() },
Core::TextContext({ .session = &bot->session() }),
st::defaultFlatLabel);
const auto userpic = Ui::CreateChild<Ui::UserpicButton>(
box->verticalLayout(),
@ -446,12 +442,6 @@ std::unique_ptr<Ui::RpWidget> MakeEmojiSetStatusPreview(
not_null<QWidget*> parent,
not_null<PeerData*> peer,
not_null<DocumentData*> document) {
const auto makeContext = [=](Fn<void()> update) {
return Core::MarkedTextContext{
.session = &peer->session(),
.customEmojiRepaint = update,
};
};
const auto emoji = Ui::CreateChild<Ui::PaddingWrap<Ui::FlatLabel>>(
parent,
object_ptr<Ui::FlatLabel>(
@ -464,7 +454,7 @@ std::unique_ptr<Ui::RpWidget> MakeEmojiSetStatusPreview(
: QString()))),
st::botEmojiStatusEmoji,
st::defaultPopupMenu,
makeContext),
Core::TextContext({ .session = &peer->session() })),
style::margins(st::normalFont->spacew, 0, 0, 0));
emoji->entity()->resizeToWidth(emoji->entity()->textMaxWidth());

View file

@ -104,13 +104,7 @@ Step::Step(
text.entities,
EntityType::Spoiler,
&EntityInText::type);
if (hasSpoiler) {
label->setMarkedText(
text,
CommonTextContext{ [=] { label->update(); } });
} else {
label->setMarkedText(text);
}
label->setMarkedText(text);
label->setAttribute(Qt::WA_TransparentForMouseEvents, hasSpoiler);
updateLabelsPosition();
}, lifetime());

View file

@ -30,10 +30,9 @@ CaptionFullView::CaptionFullView(not_null<Controller*> controller)
object_ptr<Ui::FlatLabel>(_scroll.get(), st::storiesCaptionFull),
st::mediaviewCaptionPadding + _controller->repostCaptionPadding())))
, _text(_wrap->entity()) {
_text->setMarkedText(controller->captionText(), Core::MarkedTextContext{
_text->setMarkedText(controller->captionText(), Core::TextContext({
.session = &controller->uiShow()->session(),
.customEmojiRepaint = [=] { _text->update(); },
});
}));
startAnimation();
_controller->layoutValue(

View file

@ -403,10 +403,7 @@ void Header::show(HeaderData data) {
const auto prefix = data.fromPeer ? data.fromPeer : data.repostPeer;
_repost->setMarkedText(
(prefix ? Ui::Text::Link(prefixName) : prefixName),
Core::MarkedTextContext{
.session = &data.peer->session(),
.customEmojiRepaint = [=] { _repost->update(); },
});
Core::TextContext({ .session = &data.peer->session() }));
if (prefix) {
_repost->setClickHandlerFilter([=](const auto &...) {
_controller->uiShow()->show(PrepareShortInfoBox(prefix));

View file

@ -242,19 +242,18 @@ void RepostView::recountDimensions() {
auto nameFull = TextWithEntities();
nameFull.append(HistoryView::Reply::PeerEmoji(owner, _sourcePeer));
nameFull.append(name);
auto context = Core::MarkedTextContext{
auto context = Core::TextContext({
.session = &_story->session(),
.customEmojiRepaint = [] {},
.customEmojiLoopLimit = 1,
};
});
_name.setMarkedText(
st::semiboldTextStyle,
nameFull,
Ui::NameTextOptions(),
context);
context.customEmojiRepaint = crl::guard(this, [=] {
context.repaint = crl::guard(this, [=] {
_controller->repaint();
}),
});
_text.setMarkedText(
st::defaultTextStyle,
text,

View file

@ -3346,12 +3346,12 @@ void OverlayWidget::refreshCaption() {
}
update(captionGeometry());
};
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = (_stories
? _storiesSession
: &_message->history()->session()),
.customEmojiRepaint = captionRepaint,
};
.repaint = captionRepaint,
});
_caption.setMarkedText(
st::mediaviewCaptionStyle,
(base.isEmpty()

View file

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/premium_preview_box.h"
#include "chat_helpers/compose/compose_show.h"
#include "core/ui_integration.h" // TextContext
#include "data/components/sponsored_messages.h"
#include "data/data_premium_limits.h"
#include "data/data_session.h"
@ -191,11 +192,7 @@ void AboutBox(
}
Ui::AddSkip(content);
{
const auto arrow = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::topicButtonArrow,
st::channelEarnLearnArrowMargins,
true));
const auto arrow = Ui::Text::IconEmoji(&st::textMoreIconEmoji);
const auto available = box->width()
- rect::m::sum::h(st::boxRowPadding);
box->addRow(
@ -213,7 +210,7 @@ void AboutBox(
return Ui::Text::Link(std::move(t), kUrl.utf16());
}),
Ui::Text::RichLangValue),
{ .session = session },
Core::TextContext({ .session = session }),
st::channelEarnLearnDescription))->resizeToWidth(available);
}
Ui::AddSkip(content);

View file

@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "overview/overview_layout.h"
#include "overview/overview_layout_delegate.h"
#include "core/ui_integration.h" // Core::MarkedTextContext.
#include "core/ui_integration.h" // TextContext
#include "data/data_document.h"
#include "data/data_document_resolver.h"
#include "data/data_session.h"
@ -1042,10 +1042,10 @@ void Voice::updateName() {
st::defaultTextStyle,
parent()->originalText(),
Ui::DialogTextOptions(),
Core::MarkedTextContext{
Core::TextContext({
.session = &parent()->history()->session(),
.customEmojiRepaint = [=] { delegate()->repaintItem(this); },
});
.repaint = [=] { delegate()->repaintItem(this); },
}));
}
bool Voice::updateStatusText() {

View file

@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_global_privacy.h"
#include "apiwrap.h"
#include "boxes/send_credits_box.h" // CreditsEmojiSmall.
#include "core/ui_integration.h" // MarkedTextContext.
#include "core/ui_integration.h" // TextContext.
#include "data/components/credits.h"
#include "data/data_channel.h"
#include "data/data_message_reactions.h"
@ -186,10 +186,7 @@ void ShowPaidReactionDetails(
) | rpl::map([=](TextWithEntities &&text) {
return Ui::TextWithContext{
.text = std::move(text),
.context = Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = [] {},
},
.context = Core::TextContext({ .session = session }),
};
});
};

View file

@ -21,7 +21,7 @@ class DynamicImage;
struct TextWithContext {
TextWithEntities text;
std::any context;
Text::MarkedContext context;
};
struct PaidReactionTop {

View file

@ -164,10 +164,10 @@ Row::Row(not_null<RowDelegate*> delegate, const ChatLinkData &data)
}
void Row::updateStatus(const ChatLinkData &data) {
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = _delegate->rowSession(),
.customEmojiRepaint = [=] { _delegate->rowUpdateRow(this); },
};
.repaint = [=] { _delegate->rowUpdateRow(this); },
});
_status.setMarkedText(
st::messageTextStyle,
data.message,

View file

@ -143,10 +143,7 @@ void SetupHeader(
content,
v::text::take_marked(std::move(about)),
st,
st::defaultPopupMenu,
[=](Fn<void()> update) {
return CommonTextContext{ std::move(update) };
})),
st::defaultPopupMenu)),
st::changePhoneDescriptionPadding);
wrap->setAttribute(Qt::WA_TransparentForMouseEvents);
wrap->resize(

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "api/api_chat_links.h"
#include "boxes/premium_preview_box.h"
#include "core/click_handler_types.h"
#include "core/ui_integration.h" // TextContext
#include "data/business/data_business_info.h"
#include "data/business/data_business_chatbots.h"
#include "data/business/data_shortcut_messages.h"
@ -526,11 +527,7 @@ void Business::setupContent() {
const auto session = &_controller->session();
{
const auto arrow = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::topicButtonArrow,
st::channelEarnLearnArrowMargins,
true));
const auto arrow = Ui::Text::IconEmoji(&st::textMoreIconEmoji);
inner->add(object_ptr<Ui::DividerLabel>(
inner,
Ui::CreateLabelWithCustomEmoji(
@ -547,7 +544,7 @@ void Business::setupContent() {
return Ui::Text::Link(text, url);
}),
Ui::Text::RichLangValue),
{ .session = session },
Core::TextContext({ .session = session }),
st::boxDividerLabel),
st::defaultBoxDividerLabelPadding,
RectPart::Top | RectPart::Bottom));

View file

@ -469,10 +469,7 @@ SubscriptionRightLabel PaintSubscriptionRightLabelCallback(
.append(QChar::Space)
.append(Lang::FormatCountDecimal(amount)),
kMarkupTextOptions,
Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = [] {},
});
Core::TextContext({ .session = session }));
const auto &font = text->style()->font;
const auto &statusFont = st::contactsStatusFont;
const auto status = tr::lng_group_invite_joined_right(tr::now);
@ -821,10 +818,10 @@ void BoostCreditsBox(
st,
std::move(textWithEntities),
kMarkupTextOptions,
Core::MarkedTextContext{
Core::TextContext({
.session = session,
.customEmojiRepaint = [=] { badge->update(); },
});
.repaint = [=] { badge->update(); },
}));
badge->paintRequest(
) | rpl::start_with_next([=] {
auto p = QPainter(badge);
@ -1328,10 +1325,10 @@ void GenericCreditsEntryBox(
object_ptr<Ui::FixedHeightWidget>(
content,
st::defaultTextStyle.font->height));
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = session,
.customEmojiRepaint = [=] { amount->update(); },
};
.repaint = [=] { amount->update(); },
});
if (e.soldOutInfo) {
text->setText(
st::defaultTextStyle,
@ -1438,11 +1435,7 @@ void GenericCreditsEntryBox(
st::creditsBoxAbout)));
}
const auto arrowEmoji = Ui::Text::SingleCustomEmoji(
owner->customEmojiManager().registerInternalEmoji(
st::topicButtonArrow,
st::channelEarnLearnArrowMargins,
true));
const auto arrow = Ui::Text::IconEmoji(&st::textMoreIconEmoji);
if (!uniqueGift && starGiftCanManage) {
Ui::AddSkip(content);
const auto about = box->addRow(
@ -1510,7 +1503,7 @@ void GenericCreditsEntryBox(
Ui::AddSkip(content);
auto link = tr::lng_credits_box_history_entry_gift_about_link(
lt_emoji,
rpl::single(arrowEmoji),
rpl::single(arrow),
Ui::Text::RichLangValue
) | rpl::map([](TextWithEntities text) {
return Ui::Text::Link(
@ -1532,13 +1525,13 @@ void GenericCreditsEntryBox(
lt_link,
std::move(link),
Ui::Text::RichLangValue),
{ .session = session },
Core::TextContext({ .session = session }),
st::creditsBoxAbout)));
} else if (e.paidMessagesCommission && e.barePeerId) {
Ui::AddSkip(content);
auto link = tr::lng_credits_paid_messages_fee_about_link(
lt_emoji,
rpl::single(arrowEmoji),
rpl::single(arrow),
Ui::Text::RichLangValue
) | rpl::map([id = e.barePeerId](TextWithEntities text) {
return Ui::Text::Link(
@ -1557,7 +1550,7 @@ void GenericCreditsEntryBox(
lt_link,
std::move(link),
Ui::Text::RichLangValue),
{ .session = session },
Core::TextContext({ .session = session }),
st::creditsBoxAbout)));
}
@ -2475,10 +2468,6 @@ void AddWithdrawalWidget(
st::settingsPremiumIconStar,
{ 0, -st::moderateBoxExpandInnerSkip, 0, 0 },
true));
const auto context = Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = [=] { label->update(); },
};
using Balance = rpl::variable<StarsAmount>;
const auto currentBalance = input->lifetime().make_state<Balance>(
rpl::duplicate(availableBalanceValue));
@ -2496,7 +2485,7 @@ void AddWithdrawalWidget(
lt_emoji,
buttonEmoji,
Ui::Text::RichLangValue),
context);
Core::TextContext({ .session = session }));
}
};
QObject::connect(input, &Ui::MaskedInputField::changed, process);
@ -2564,10 +2553,10 @@ void AddWithdrawalWidget(
constexpr auto kDateUpdateInterval = crl::time(250);
const auto was = base::unixtime::serialize(dt);
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = session,
.customEmojiRepaint = [=] { lockedLabel->update(); },
};
.repaint = [=] { lockedLabel->update(); },
});
const auto emoji = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::chatSimilarLockedIcon,
@ -2644,11 +2633,7 @@ void AddWithdrawalWidget(
Ui::AddSkip(container);
Ui::AddSkip(container);
const auto arrow = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
st::topicButtonArrow,
st::channelEarnLearnArrowMargins,
true));
const auto arrow = Ui::Text::IconEmoji(&st::textMoreIconEmoji);
auto about = Ui::CreateLabelWithCustomEmoji(
container,
tr::lng_bot_earn_learn_credits_out_about(
@ -2663,7 +2648,7 @@ void AddWithdrawalWidget(
tr::lng_bot_earn_balance_about_url(tr::now));
}),
Ui::Text::RichLangValue),
{ .session = session },
Core::TextContext({ .session = session }),
st::boxDividerLabel);
Ui::AddSkip(container);
container->add(object_ptr<Ui::DividerLabel>(

View file

@ -199,11 +199,11 @@ void FilterRowButton::updateData(
st::contactsNameStyle,
title.text,
kMarkupTextOptions,
Core::MarkedTextContext{
Core::TextContext({
.session = _session,
.customEmojiRepaint = [=] { update(); },
.repaint = [=] { update(); },
.customEmojiLoopLimit = title.isStatic ? -1 : 0,
});
}));
_icon = Ui::ComputeFilterIcon(filter);
_colorIndex = filter.colorIndex();
if (!ignoreCount) {

View file

@ -13,7 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h"
#include "core/click_handler_types.h"
#include "core/local_url_handlers.h" // Core::TryConvertUrlToLocal.
#include "core/ui_integration.h" // MarkedTextContext.
#include "core/ui_integration.h" // TextContext.
#include "data/data_document.h"
#include "data/data_document_media.h"
#include "data/data_emoji_statuses.h"
@ -788,11 +788,9 @@ void TopBarUser::updateTitle(
lt_link,
{ .text = text, .entities = entities, },
Ui::Text::WithEntities);
const auto context = Core::MarkedTextContext{
.session = &controller->session(),
.customEmojiRepaint = [=] { _title->update(); },
};
_title->setMarkedText(std::move(title), context);
_title->setMarkedText(
std::move(title),
Core::TextContext({ .session = &controller->session() }));
auto link = std::make_shared<LambdaClickHandler>([=,
stickerSetIdentifier = stickerInfo->set] {
setPaused(true);

View file

@ -224,7 +224,9 @@ void CollectibleInfoBox(
object_ptr<Ui::FlatLabel>(box, st::collectibleInfo),
st::collectibleInfoPadding);
label->setAttribute(Qt::WA_TransparentForMouseEvents);
label->setMarkedText(text, details.tonEmojiContext());
auto context = details.tonEmojiContext;
context.repaint = [label] { label->update(); };
label->setMarkedText(text, context);
const auto more = box->addRow(
object_ptr<Ui::RoundButton>(

View file

@ -34,7 +34,7 @@ struct CollectibleInfo {
struct CollectibleDetails {
TextWithEntities tonEmoji;
Fn<std::any()> tonEmojiContext;
Text::MarkedContext tonEmojiContext;
};
void CollectibleInfoBox(

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "ui/boxes/edit_invite_link_session.h"
#include "core/ui_integration.h" // TextContext
#include "data/components/credits.h"
#include "data/data_peer.h"
#include "data/data_session.h"
@ -128,18 +129,13 @@ InviteLinkSubscriptionToggle FillCreateInviteLinkSubscriptionToggle(
state->usdRate = peer->session().credits().rateValue(peer);
const auto arrow = Ui::Text::SingleCustomEmoji(
peer->owner().customEmojiManager().registerInternalEmoji(
st::topicButtonArrow,
st::channelEarnLearnArrowMargins,
true));
auto about = Ui::CreateLabelWithCustomEmoji(
container,
tr::lng_group_invite_subscription_about(
lt_link,
tr::lng_group_invite_subscription_about_link(
lt_emoji,
rpl::single(arrow),
rpl::single(Ui::Text::IconEmoji(&st::textMoreIconEmoji)),
Ui::Text::RichLangValue
) | rpl::map([](TextWithEntities text) {
return Ui::Text::Link(
@ -147,7 +143,7 @@ InviteLinkSubscriptionToggle FillCreateInviteLinkSubscriptionToggle(
tr::lng_group_invite_subscription_about_url(tr::now));
}),
Ui::Text::RichLangValue),
{ .session = &peer->session() },
Core::TextContext({ .session = &peer->session() }),
st::boxDividerLabel);
Ui::AddSkip(wrap->entity());
Ui::AddSkip(wrap->entity());

View file

@ -174,7 +174,6 @@ bool ScaledCustomEmoji::readyInDefaultState() {
ChatsFilterTagContext &context) {
auto i = text.entities.begin();
auto ch = text.text.constData();
auto &integration = Integration::Instance();
context.loading = false;
const auto end = text.text.constData() + text.text.size();
const auto adjust = [&](EntityInText &entity) {
@ -187,9 +186,7 @@ bool ScaledCustomEmoji::readyInDefaultState() {
}
auto &emoji = context.emoji[data];
if (!emoji) {
emoji = integration.createCustomEmoji(
data,
context.textContext);
emoji = Text::MakeCustomEmoji(data, context.textContext);
}
if (!emoji->ready()) {
context.loading = true;

View file

@ -8,16 +8,13 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "emoji.h"
namespace Ui::Text {
class CustomEmoji;
} // namespace Ui::Text
#include "ui/text/text.h"
namespace Ui {
struct ChatsFilterTagContext {
base::flat_map<QString, std::unique_ptr<Text::CustomEmoji>> emoji;
std::any textContext;
Text::MarkedContext textContext;
QColor color;
bool active = false;
bool loading = false;

View file

@ -26,7 +26,7 @@ struct MessageBarContent {
int count = 1;
QString title;
TextWithEntities text;
std::any context;
Text::MarkedContext context;
QImage preview;
Fn<void()> spoilerRepaint;
style::margins margins;

View file

@ -9,7 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "core/application.h"
#include "core/click_handler_types.h"
#include "core/ui_integration.h" // Core::MarkedTextContext.
#include "core/ui_integration.h" // TextContext
#include "data/components/sponsored_messages.h"
#include "data/data_session.h"
#include "history/history_item_helpers.h"
@ -202,10 +202,10 @@ void FillSponsoredMessageBar(
contentTextSt,
textWithEntities,
kMarkupTextOptions,
Core::MarkedTextContext{
Core::TextContext({
.session = session,
.customEmojiRepaint = [=] { widget->update(); },
});
.repaint = [=] { widget->update(); },
}));
const auto hostedClick = [=](ClickHandlerPtr handler) {
return [=] {
if (const auto controller = FindSessionController(widget)) {

View file

@ -77,7 +77,7 @@ private:
QPainterPath _titlePath;
TextWithEntities _folderTitle;
Fn<std::any(Fn<void()>)> _makeContext;
Text::MarkedContext _aboutContext;
not_null<const style::icon*> _folderIcon;
bool _horizontalFilters = false;
@ -90,7 +90,7 @@ private:
[[nodiscard]] PreviewState GeneratePreview(
not_null<Ui::RpWidget*> parent,
const TextWithEntities &title,
Fn<std::any(Fn<void()>)> makeContext,
Text::MarkedContext aboutContext,
int badge) {
using Tabs = Ui::ChatsFiltersTabs;
auto preview = PreviewState();
@ -126,14 +126,14 @@ private:
return state->cache;
};
const auto raw = &state->tabs;
const auto repaint = [=] {
state->dirty = true;
};
const auto repaint = [=] { state->dirty = true; };
auto context = aboutContext;
context.repaint = repaint;
raw->setSections({
TextWithEntities{ tr::lng_filters_name_people(tr::now) },
title,
TextWithEntities{ tr::lng_filters_name_unread(tr::now) },
}, makeContext(repaint));
}, context);
raw->fitWidthToSections();
raw->setActiveSectionFast(1);
raw->stopAnimation();
@ -153,7 +153,7 @@ private:
[[nodiscard]] PreviewState GeneratePreview(
const TextWithEntities &title,
Fn<std::any(Fn<void()>)> makeContext,
Text::MarkedContext context,
not_null<const style::icon*> icon,
int badge) {
auto preview = PreviewState();
@ -165,7 +165,7 @@ private:
bool dirty = true;
};
const auto state = preview.lifetime.make_state<State>();
const auto repaint = [=] {
context.repaint = [=] {
state->dirty = true;
};
@ -201,7 +201,7 @@ private:
text,
kMarkupTextOptions,
available,
makeContext(repaint));
context);
};
const auto paintName = [=](QPainter &p, int top) {
state->string.draw(p, {
@ -299,7 +299,7 @@ Widget::Widget(
rpl::single(descriptor.about.value()),
st::filterLinkAbout,
st::defaultPopupMenu,
descriptor.makeAboutContext))
descriptor.aboutContext))
, _close(CreateChild<IconButton>(this, st::boxTitleClose))
, _aboutPadding(st::boxRowPadding)
, _badge(std::move(descriptor.badge))
@ -307,7 +307,7 @@ Widget::Widget(
, _titleFont(st::boxTitle.style.font)
, _titlePadding(st::filterLinkTitlePadding)
, _folderTitle(descriptor.folderTitle)
, _makeContext(descriptor.makeAboutContext)
, _aboutContext(descriptor.aboutContext)
, _folderIcon(descriptor.folderIcon)
, _horizontalFilters(descriptor.horizontalFilters) {
setMinimumHeight(st::boxTitleHeight);
@ -417,20 +417,24 @@ void Widget::paintEvent(QPaintEvent *e) {
auto hq = PainterHighQualityEnabler(p);
if (!_preview.frame) {
const auto badge = _badge.current();
const auto makeContext = [=](Fn<void()> repaint) {
return _makeContext([=] { repaint(); update(); });
auto context = _aboutContext;
context.repaint = [this, copy = context.repaint] {
if (const auto &repaint = copy) {
repaint();
}
update();
};
if (_horizontalFilters) {
_preview = GeneratePreview(
this,
_folderTitle,
makeContext,
context,
badge);
Widget::resizeEvent(nullptr);
} else {
_preview = GeneratePreview(
_folderTitle,
makeContext,
context,
_folderIcon,
badge);
}
@ -486,7 +490,7 @@ object_ptr<RoundButton> FilterLinkProcessButton(
not_null<QWidget*> parent,
FilterLinkHeaderType type,
TextWithEntities title,
Fn<std::any(Fn<void()>)> makeContext,
Text::MarkedContext context,
rpl::producer<int> badge) {
const auto st = &st::filterInviteBox.button;
const auto badgeSt = &st::filterInviteButtonBadgeStyle;
@ -600,12 +604,13 @@ object_ptr<RoundButton> FilterLinkProcessButton(
}
}, label->lifetime());
context.repaint = [=] { label->update(); };
std::move(data) | rpl::start_with_next([=](Data data) {
label->text.setMarkedText(
st::filterInviteButtonStyle,
data.text,
kMarkupTextOptions,
makeContext([=] { label->update(); }));
context);
label->badge.setText(st::filterInviteButtonBadgeStyle, data.badge);
label->update();
}, label->lifetime());

View file

@ -26,7 +26,7 @@ struct FilterLinkHeaderDescriptor {
base::required<FilterLinkHeaderType> type;
base::required<QString> title;
base::required<TextWithEntities> about;
Fn<std::any(Fn<void()>)> makeAboutContext;
Text::MarkedContext aboutContext;
base::required<TextWithEntities> folderTitle;
not_null<const style::icon*> folderIcon;
rpl::producer<int> badge;
@ -47,7 +47,7 @@ struct FilterLinkHeader {
not_null<QWidget*> parent,
FilterLinkHeaderType type,
TextWithEntities title,
Fn<std::any(Fn<void()>)> makeContext,
Text::MarkedContext context,
rpl::producer<int> badge);
} // namespace Ui

View file

@ -149,7 +149,7 @@ void GroupsStrip::set(std::vector<EmojiGroup> list) {
.icon = std::make_unique<Text::LimitedLoopsEmoji>(
_factory(
group.iconId,
updater(group.iconId)),
{ .repaint = updater(group.iconId) }),
loopCount,
stopAtLastFrame),
});

View file

@ -359,7 +359,7 @@ void Action::paint(Painter &p) {
if (!_custom && !_content.singleCustomEntityData.isEmpty()) {
_custom = _customEmojiFactory(
_content.singleCustomEntityData,
[=] { update(); });
{ .repaint = [=] { update(); } });
}
if (_custom) {
const auto ratio = style::DevicePixelRatio();
@ -772,7 +772,9 @@ void WhoReactedEntryAction::setData(Data &&data) {
}
_type = data.type;
_custom = _customEmojiFactory
? _customEmojiFactory(data.customEntityData, [=] { update(); })
? _customEmojiFactory(
data.customEntityData,
{ .repaint = [=] { update(); } })
: nullptr;
const auto ratio = style::DevicePixelRatio();
const auto size = Emoji::GetSizeNormal() / ratio;

View file

@ -298,7 +298,7 @@ void PeerBadge::set(
if (details->iconId) {
_botVerifiedData->icon = factory(
Data::SerializeCustomEmojiId(details->iconId),
repaint);
{ .repaint = repaint });
}
}

View file

@ -54,7 +54,7 @@ ChatsFiltersTabs::ChatsFiltersTabs(
bool ChatsFiltersTabs::setSectionsAndCheckChanged(
std::vector<TextWithEntities> &&sections,
const std::any &context,
const Text::MarkedContext &context,
Fn<bool()> paused) {
const auto &was = sectionsRef();
const auto changed = [&] {

View file

@ -29,7 +29,7 @@ public:
bool setSectionsAndCheckChanged(
std::vector<TextWithEntities> &&sections,
const std::any &context,
const Text::MarkedContext &context,
Fn<bool()> paused);
void fitWidthToSections() override;

View file

@ -175,11 +175,11 @@ void ShowFiltersListMenu(
icon);
action->setEnabled(i < premiumFrom);
if (!title.text.empty()) {
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = session,
.customEmojiRepaint = [raw = item.get()] { raw->update(); },
.repaint = [raw = item.get()] { raw->update(); },
.customEmojiLoopLimit = title.isStatic ? -1 : 0,
};
});
item->setMarkedText(title.text, QString(), context);
}
state->menu->addAction(std::move(item));
@ -344,10 +344,7 @@ not_null<Ui::RpWidget*> AddChatFiltersTabsStrip(
if ((list.size() <= 1 && !slider->width()) || state->ignoreRefresh) {
return;
}
const auto context = Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = [=] { slider->update(); },
};
const auto context = Core::TextContext({ .session = session });
const auto paused = [=] {
return On(PowerSaving::kEmojiChat)
|| controller->isGifPausedAtLeastFor(pauseLevel);

View file

@ -79,7 +79,8 @@ void DiscreteSlider::addSection(const QString &label) {
void DiscreteSlider::addSection(
const TextWithEntities &label,
const std::any &context) {
Text::MarkedContext context) {
context.repaint = [this] { update(); };
_sections.push_back(Section(label, getLabelStyle(), context));
resizeToWidth(width());
}
@ -96,9 +97,11 @@ void DiscreteSlider::setSections(const std::vector<QString> &labels) {
void DiscreteSlider::setSections(
const std::vector<TextWithEntities> &labels,
const std::any &context) {
Text::MarkedContext context) {
Assert(!labels.empty());
context.repaint = [this] { update(); };
_sections.clear();
for (const auto &label : labels) {
_sections.push_back(Section(label, getLabelStyle(), context));
@ -225,7 +228,7 @@ DiscreteSlider::Section::Section(
DiscreteSlider::Section::Section(
const TextWithEntities &label,
const style::TextStyle &st,
const std::any &context) {
const Text::MarkedContext &context) {
this->label.setMarkedText(st, label, kMarkupTextOptions, context);
contentWidth = Section::label.maxWidth();
}

View file

@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/rp_widget.h"
#include "ui/round_rect.h"
#include "ui/effects/animations.h"
#include "ui/text/text.h"
namespace style {
struct TextStyle;
@ -32,11 +33,11 @@ public:
void addSection(const QString &label);
void addSection(
const TextWithEntities &label,
const std::any &context = {});
Text::MarkedContext context = {});
void setSections(const std::vector<QString> &labels);
void setSections(
const std::vector<TextWithEntities> &labels,
const std::any &context = {});
Text::MarkedContext context = {});
int activeSection() const {
return _activeIndex;
}
@ -63,9 +64,9 @@ protected:
Section(
const TextWithEntities &label,
const style::TextStyle &st,
const std::any &context);
const Text::MarkedContext &context);
Ui::Text::String label;
Text::String label;
std::unique_ptr<RippleAnimation> ripple;
int left = 0;
int width = 0;

View file

@ -16,13 +16,12 @@ namespace Ui {
object_ptr<Ui::FlatLabel> CreateLabelWithCustomEmoji(
QWidget *parent,
rpl::producer<TextWithEntities> &&text,
Core::MarkedTextContext context,
Text::MarkedContext context,
const style::FlatLabel &st) {
auto label = object_ptr<Ui::FlatLabel>(parent, st);
const auto raw = label.data();
if (!context.customEmojiRepaint) {
context.customEmojiRepaint = [=] { raw->update(); };
}
context.repaint = [=] { raw->update(); };
std::move(text) | rpl::start_with_next([=](const TextWithEntities &text) {
raw->setMarkedText(text, context);
}, label->lifetime());

View file

@ -7,8 +7,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "core/ui_integration.h" // Core::MarkedTextContext.
template <typename Object>
class object_ptr;
@ -20,16 +18,18 @@ namespace style {
struct FlatLabel;
} // namespace style
namespace Ui {
class FlatLabel;
} // namespace Ui
namespace Ui::Text {
struct MarkedContext;
} // namespace Ui::Text
namespace Ui {
class FlatLabel;
[[nodiscard]] object_ptr<Ui::FlatLabel> CreateLabelWithCustomEmoji(
QWidget *parent,
rpl::producer<TextWithEntities> &&text,
Core::MarkedTextContext context,
Text::MarkedContext context,
const style::FlatLabel &st);
} // namespace Ui

View file

@ -949,10 +949,10 @@ void Notification::updateNotifyDisplay() {
0,
Qt::LayoutDirectionAuto,
};
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &_history->session(),
.customEmojiRepaint = [=] { customEmojiCallback(); },
};
.repaint = [=] { customEmojiCallback(); },
});
_textCache.setMarkedText(
st::dialogsTextStyle,
text,
@ -988,10 +988,10 @@ void Notification::updateNotifyDisplay() {
const auto fullTitle = manager()->addTargetAccountName(
std::move(title),
&_history->session());
const auto context = Core::MarkedTextContext{
const auto context = Core::TextContext({
.session = &_history->session(),
.customEmojiRepaint = [=] { customEmojiCallback(); },
};
.repaint = [=] { customEmojiCallback(); },
});
_titleCache.setMarkedText(
st::semiboldTextStyle,
fullTitle,

View file

@ -253,13 +253,6 @@ base::unique_qptr<Ui::SideBarButton> FiltersMenu::prepareButton(
Ui::FilterIcon icon,
bool toBeginning) {
const auto isStatic = title.isStatic;
const auto makeContext = [=](Fn<void()> update) {
return Core::MarkedTextContext{
.session = &_session->session(),
.customEmojiRepaint = std::move(update),
.customEmojiLoopLimit = isStatic ? -1 : 0,
};
};
const auto paused = [=] {
return On(PowerSaving::kEmojiChat)
|| _session->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
@ -268,7 +261,10 @@ base::unique_qptr<Ui::SideBarButton> FiltersMenu::prepareButton(
container,
id ? title.text : TextWithEntities{ tr::lng_filters_all(tr::now) },
st::windowFiltersButton,
makeContext,
Core::TextContext({
.session = &_session->session(),
.customEmojiLoopLimit = isStatic ? -1 : 0,
}),
paused);
auto added = toBeginning
? container->insert(0, std::move(prepared))

View file

@ -172,12 +172,6 @@ private:
[[nodiscard]] Ui::CollectibleDetails PrepareCollectibleDetails(
not_null<Main::Session*> session) {
const auto makeContext = [=] {
return Core::MarkedTextContext{
.session = session,
.customEmojiRepaint = [] {},
};
};
return {
.tonEmoji = Ui::Text::SingleCustomEmoji(
session->data().customEmojiManager().registerInternalEmoji(
@ -186,7 +180,7 @@ private:
st::collectibleInfo.textFg->c),
st::collectibleInfoTonMargins,
true)),
.tonEmojiContext = makeContext,
.tonEmojiContext = Core::TextContext({ .session = session }),
};
}

@ -1 +1 @@
Subproject commit 76f25481470faee2e0a24aa7be8c6d58564addea
Subproject commit e51fe382bda9f2944412078da70f04de5dd821f3