From afe30da9f44802908a7398e89ce26a589e241aa1 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 6 Aug 2024 16:08:55 +0200 Subject: [PATCH] Add top reactors to paid reaction details. --- .../data/data_message_reactions.cpp | 5 + .../SourceFiles/data/data_message_reactions.h | 1 + Telegram/SourceFiles/history/history_item.cpp | 20 ++- Telegram/SourceFiles/history/history_item.h | 4 + .../SourceFiles/history/history_widget.cpp | 6 + .../view/reactions/history_view_reactions.cpp | 17 +- .../payments/payments_reaction_process.cpp | 18 ++ .../payments/ui/payments_reaction_box.cpp | 154 +++++++++++++++++- .../payments/ui/payments_reaction_box.h | 9 + Telegram/SourceFiles/ui/boxes/boost_box.cpp | 85 +++++----- Telegram/SourceFiles/ui/boxes/boost_box.h | 6 + Telegram/SourceFiles/ui/effects/credits.style | 2 +- Telegram/SourceFiles/ui/effects/premium.style | 30 +++- Telegram/lib_ui | 2 +- 14 files changed, 301 insertions(+), 58 deletions(-) diff --git a/Telegram/SourceFiles/data/data_message_reactions.cpp b/Telegram/SourceFiles/data/data_message_reactions.cpp index 01956f309..ff21d3d05 100644 --- a/Telegram/SourceFiles/data/data_message_reactions.cpp +++ b/Telegram/SourceFiles/data/data_message_reactions.cpp @@ -2042,6 +2042,11 @@ auto MessageReactions::recent() const return _recent; } +auto MessageReactions::topPaid() const -> const std::vector & { + static const auto kEmpty = std::vector(); + return _paid ? _paid->top : kEmpty; +} + bool MessageReactions::empty() const { return _list.empty(); } diff --git a/Telegram/SourceFiles/data/data_message_reactions.h b/Telegram/SourceFiles/data/data_message_reactions.h index 1bcf46847..5ab61ac50 100644 --- a/Telegram/SourceFiles/data/data_message_reactions.h +++ b/Telegram/SourceFiles/data/data_message_reactions.h @@ -379,6 +379,7 @@ public: [[nodiscard]] const std::vector &list() const; [[nodiscard]] auto recent() const -> const base::flat_map> &; + [[nodiscard]] const std::vector &topPaid() const; [[nodiscard]] std::vector chosen() const; [[nodiscard]] bool empty() const; diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index ba8dc00ca..69287a9cf 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -2573,11 +2573,11 @@ const std::vector &HistoryItem::reactions() const { std::vector HistoryItem::reactionsWithLocal() const { auto result = reactions(); + const auto i = ranges::find( + result, + Data::ReactionId::Paid(), + &Data::MessageReaction::id); if (const auto local = _reactions ? _reactions->localPaidCount() : 0) { - const auto i = ranges::find( - result, - Data::ReactionId::Paid(), - &Data::MessageReaction::id); if (i != end(result)) { i->my = true; i->count += local; @@ -2591,10 +2591,16 @@ std::vector HistoryItem::reactionsWithLocal() const { .my = true, }); } + } else if (i != end(result) && i != begin(result)) { + std::rotate(begin(result), i, i + 1); } return result; } +int HistoryItem::reactionsPaidScheduled() const { + return _reactions ? _reactions->scheduledPaid() : 0; +} + bool HistoryItem::reactionsAreTags() const { return _flags & MessageFlag::ReactionsAreTags; } @@ -2609,6 +2615,12 @@ auto HistoryItem::recentReactions() const return _reactions ? _reactions->recent() : kEmpty; } +auto HistoryItem::topPaidReactions() const +-> const std::vector & { + static const auto kEmpty = std::vector(); + return _reactions ? _reactions->topPaid() : kEmpty; +} + bool HistoryItem::canViewReactions() const { return (_flags & MessageFlag::CanViewReactions) && _reactions diff --git a/Telegram/SourceFiles/history/history_item.h b/Telegram/SourceFiles/history/history_item.h index bead81aec..d9b48dfd5 100644 --- a/Telegram/SourceFiles/history/history_item.h +++ b/Telegram/SourceFiles/history/history_item.h @@ -57,6 +57,7 @@ struct RippleAnimation; namespace Data { struct MessagePosition; struct RecentReaction; +struct MessageReactionsTopPaid; struct ReactionId; class Media; struct MessageReaction; @@ -456,6 +457,9 @@ public: -> const base::flat_map< Data::ReactionId, std::vector> &; + [[nodiscard]] auto topPaidReactions() const + -> const std::vector &; + [[nodiscard]] int reactionsPaidScheduled() const; [[nodiscard]] bool canViewReactions() const; [[nodiscard]] std::vector chosenReactions() const; [[nodiscard]] Data::ReactionId lookupUnreadReaction( diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 789390bbf..6356344f9 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -55,6 +55,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/unixtime.h" #include "base/call_delayed.h" #include "data/business/data_shortcut_messages.h" +#include "data/components/credits.h" #include "data/components/scheduled_messages.h" #include "data/components/sponsored_messages.h" #include "data/notify/data_notify_settings.h" @@ -869,6 +870,11 @@ HistoryWidget::HistoryWidget( } if (flags & PeerUpdateFlag::FullInfo) { fullInfoUpdated(); + if (const auto channel = _peer ? _peer->asChannel() : nullptr) { + if (channel->allowedReactions().paidEnabled) { + session().credits().load(); + } + } } }, lifetime()); diff --git a/Telegram/SourceFiles/history/view/reactions/history_view_reactions.cpp b/Telegram/SourceFiles/history/view/reactions/history_view_reactions.cpp index 71c0a6c49..fb99cc635 100644 --- a/Telegram/SourceFiles/history/view/reactions/history_view_reactions.cpp +++ b/Telegram/SourceFiles/history/view/reactions/history_view_reactions.cpp @@ -55,6 +55,7 @@ struct InlineList::Button { int textWidth = 0; int count = 0; bool chosen = false; + bool paid = false; bool tag = false; }; @@ -180,7 +181,7 @@ void InlineList::layoutButtons() { } InlineList::Button InlineList::prepareButtonWithId(const ReactionId &id) { - auto result = Button{ .id = id }; + auto result = Button{ .id = id, .paid = id.paid()}; if (const auto customId = id.custom()) { result.custom = _owner->owner().customEmojiManager().create( customId, @@ -421,14 +422,18 @@ void InlineList::paint( } else if (!bubbleReady) { opacity = bubbleProgress; } - color = stm->msgFileBg->c; + color = button.paid + ? st->creditsBg3()->c + : stm->msgFileBg->c; } else { if (!bubbleReady) { opacity = bubbleProgress; } - color = (chosen - ? st->msgServiceFg() - : st->msgServiceBg())->c; + color = (!chosen + ? st->msgServiceBg() + : button.paid + ? st->creditsBg2() + : st->msgServiceFg())->c; } const auto fill = geometry.marginsAdded({ @@ -451,7 +456,7 @@ void InlineList::paint( ? QPen(AdaptChosenServiceFg(st->msgServiceBg()->c)) : st->msgServiceFg()) : !chosen - ? stm->msgServiceFg + ? (button.paid ? st->creditsFg() : stm->msgServiceFg) : context.outbg ? (context.selected() ? st->historyFileOutIconFgSelected() diff --git a/Telegram/SourceFiles/payments/payments_reaction_process.cpp b/Telegram/SourceFiles/payments/payments_reaction_process.cpp index a5248776a..dd23c69fe 100644 --- a/Telegram/SourceFiles/payments/payments_reaction_process.cpp +++ b/Telegram/SourceFiles/payments/payments_reaction_process.cpp @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "boxes/send_credits_box.h" // CreditsEmojiSmall. #include "core/ui_integration.h" // MarkedTextContext. #include "data/components/credits.h" +#include "data/data_message_reactions.h" #include "data/data_session.h" #include "data/data_user.h" #include "history/view/history_view_element.h" @@ -27,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/layers/generic_box.h" #include "ui/layers/show.h" #include "ui/text/text_utilities.h" +#include "ui/dynamic_thumbnails.h" namespace Payments { namespace { @@ -167,10 +169,26 @@ void ShowPaidReactionDetails( }; }); }; + auto top = std::vector(); + const auto &topPaid = item->topPaidReactions(); + top.reserve(topPaid.size()); + for (const auto &entry : topPaid) { + if (!entry.top) { + continue; + } + top.push_back({ + .name = entry.peer->shortName(), + .photo = Ui::MakeUserpicThumbnail(entry.peer), + .count = int(entry.count), + }); + } + ranges::sort(top, ranges::greater(), &Ui::PaidReactionTop::count); + state->selectBox = show->show(Ui::MakePaidReactionBox({ .min = min, .max = max, .chosen = chosen, + .top = std::move(top), .channel = item->history()->peer->name(), .submit = std::move(submitText), .balanceValue = session->credits().balanceValue(), diff --git a/Telegram/SourceFiles/payments/ui/payments_reaction_box.cpp b/Telegram/SourceFiles/payments/ui/payments_reaction_box.cpp index 30550786f..ef5ac8953 100644 --- a/Telegram/SourceFiles/payments/ui/payments_reaction_box.cpp +++ b/Telegram/SourceFiles/payments/ui/payments_reaction_box.cpp @@ -8,10 +8,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "payments/ui/payments_reaction_box.h" #include "lang/lang_keys.h" +#include "ui/boxes/boost_box.h" // MakeBoostFeaturesBadge. #include "ui/layers/generic_box.h" #include "ui/text/text_utilities.h" #include "ui/widgets/buttons.h" #include "ui/widgets/continuous_sliders.h" +#include "ui/dynamic_image.h" +#include "ui/painter.h" +#include "styles/style_chat.h" #include "styles/style_credits.h" #include "styles/style_layers.h" #include "styles/style_premium.h" @@ -27,6 +31,8 @@ namespace Settings { namespace Ui { namespace { +constexpr auto kMaxTopPaidShown = 3; + void PaidReactionSlider( not_null container, int min, @@ -35,9 +41,9 @@ void PaidReactionSlider( Fn changed) { const auto top = st::boxTitleClose.height + st::creditsHistoryRightSkip; const auto slider = container->add( - object_ptr(container, st::settingsScale), + object_ptr(container, st::paidReactSlider), st::boxRowPadding + QMargins(0, top, 0, 0)); - slider->resize(slider->width(), st::settingsScale.seekSize.height()); + slider->resize(slider->width(), st::paidReactSlider.seekSize.height()); slider->setPseudoDiscrete( max + 1 - min, [=](int index) { return min + index; }, @@ -46,13 +52,145 @@ void PaidReactionSlider( changed); } +[[nodiscard]] QImage GenerateBadgeImage(int count) { + const auto text = Lang::FormatCountDecimal(count); + const auto length = st::chatSimilarBadgeFont->width(text); + const auto contents = length + + st::chatSimilarLockedIcon.width(); + const auto badge = QRect( + st::chatSimilarBadgePadding.left(), + st::chatSimilarBadgePadding.top(), + contents, + st::chatSimilarBadgeFont->height); + const auto rect = badge.marginsAdded(st::chatSimilarBadgePadding); + + auto result = QImage( + rect.size() * style::DevicePixelRatio(), + QImage::Format_ARGB32_Premultiplied); + result.setDevicePixelRatio(style::DevicePixelRatio()); + result.fill(Qt::transparent); + auto q = QPainter(&result); + + const auto &font = st::chatSimilarBadgeFont; + const auto textTop = badge.y() + font->ascent; + const auto icon = &st::chatSimilarLockedIcon; + const auto position = st::chatSimilarLockedIconPosition; + + auto hq = PainterHighQualityEnabler(q); + q.setBrush(st::creditsBg3); + q.setPen(Qt::NoPen); + const auto radius = rect.height() / 2.; + q.drawRoundedRect(rect, radius, radius); + + auto textLeft = 0; + if (icon) { + icon->paint( + q, + badge.x() + position.x(), + badge.y() + position.y(), + rect.width()); + textLeft += position.x() + icon->width(); + } + + q.setFont(font); + q.setPen(st::premiumButtonFg); + q.drawText(textLeft, textTop, text); + q.end(); + + return result; +} + +[[nodiscard]] not_null MakeTopReactor( + not_null parent, + const PaidReactionTop &data) { + const auto result = Ui::CreateChild(parent); + result->show(); + + struct State { + QImage badge; + Ui::Text::String name; + }; + const auto state = result->lifetime().make_state(); + state->name.setText(st::defaultTextStyle, data.name); + + const auto count = data.count; + const auto photo = data.photo; + photo->subscribeToUpdates([=] { + result->update(); + }); + style::PaletteChanged( + ) | rpl::start_with_next([=] { + state->badge = QImage(); + }, result->lifetime()); + result->paintRequest() | rpl::start_with_next([=] { + auto p = Painter(result); + const auto left = (result->width() - st::paidReactTopUserpic) / 2; + p.drawImage(left, 0, photo->image(st::paidReactTopUserpic)); + + if (state->badge.isNull()) { + state->badge = GenerateBadgeImage(count); + } + const auto bwidth = state->badge.width() + / state->badge.devicePixelRatio(); + p.drawImage( + (result->width() - bwidth) / 2, + st::paidReactTopBadgeSkip, + state->badge); + + p.setPen(st::windowFg); + const auto skip = st::normalFont->spacew; + const auto nameTop = st::paidReactTopNameSkip; + const auto available = result->width() - skip * 2; + state->name.draw(p, skip, nameTop, available, style::al_top); + }, result->lifetime()); + + return result; +} + +void FillTopReactors( + not_null container, + std::vector top) { + container->add( + MakeBoostFeaturesBadge( + container, + tr::lng_paid_react_top_title(), + [](QRect) { return st::creditsBg3->b; }), + st::boxRowPadding + st::paidReactTopTitleMargin); + + const auto height = st::paidReactTopNameSkip + st::normalFont->height; + const auto wrap = container->add( + object_ptr(container, height), + st::paidReactTopMargin); + struct State { + std::vector> widgets; + }; + const auto state = wrap->lifetime().make_state(); + + const auto topCount = std::min(int(top.size()), kMaxTopPaidShown); + for (auto i = 0; i != topCount; ++i) { + state->widgets.push_back(MakeTopReactor(wrap, top[i])); + } + + wrap->widthValue() | rpl::start_with_next([=](int width) { + const auto single = width / 4; + if (single <= st::paidReactTopUserpic) { + return; + } + auto left = (width - single * topCount) / 2; + for (const auto widget : state->widgets) { + widget->setGeometry(left, 0, single, height); + left += single; + } + }, wrap->lifetime()); +} + } // namespace void PaidReactionsBox( not_null box, PaidReactionBoxArgs &&args) { box->setWidth(st::boxWideWidth); - box->setStyle(st::boostBox); + box->setStyle(st::paidReactBox); box->setNoContentMargin(true); struct State { @@ -77,7 +215,7 @@ void PaidReactionsBox( box, tr::lng_paid_react_title(), st::boostCenteredTitle), - st::boxRowPadding + QMargins(0, st::boostTitleSkip, 0, 0)); + st::boxRowPadding + QMargins(0, st::paidReactTitleSkip, 0, 0)); box->addRow( object_ptr( box, @@ -87,7 +225,11 @@ void PaidReactionsBox( Text::RichLangValue), st::boostText), (st::boxRowPadding - + QMargins(0, st::boostTextSkip, 0, st::boostBottomSkip))); + + QMargins(0, st::lineWidth, 0, st::boostBottomSkip))); + + if (!args.top.empty()) { + FillTopReactors(box->verticalLayout(), std::move(args.top)); + } const auto button = box->addButton(rpl::single(QString()), [=] { args.send(state->chosen.current()); @@ -117,7 +259,7 @@ void PaidReactionsBox( box->widthValue( ) | rpl::start_with_next([=](int width) { - const auto &padding = st::boostBox.buttonPadding; + const auto &padding = st::paidReactBox.buttonPadding; button->resizeToWidth(width - padding.left() - padding.right()); diff --git a/Telegram/SourceFiles/payments/ui/payments_reaction_box.h b/Telegram/SourceFiles/payments/ui/payments_reaction_box.h index 9da69c368..260896c9a 100644 --- a/Telegram/SourceFiles/payments/ui/payments_reaction_box.h +++ b/Telegram/SourceFiles/payments/ui/payments_reaction_box.h @@ -13,17 +13,26 @@ namespace Ui { class BoxContent; class GenericBox; +class DynamicImage; struct TextWithContext { TextWithEntities text; std::any context; }; +struct PaidReactionTop { + QString name; + std::shared_ptr photo; + int count = 0; +}; + struct PaidReactionBoxArgs { int min = 0; int max = 0; int chosen = 0; + std::vector top; + QString channel; Fn(rpl::producer amount)> submit; rpl::producer balanceValue; diff --git a/Telegram/SourceFiles/ui/boxes/boost_box.cpp b/Telegram/SourceFiles/ui/boxes/boost_box.cpp index bb99e43a8..903cdcba7 100644 --- a/Telegram/SourceFiles/ui/boxes/boost_box.cpp +++ b/Telegram/SourceFiles/ui/boxes/boost_box.cpp @@ -111,48 +111,13 @@ namespace { [[nodiscard]] object_ptr MakeFeaturesBadge( not_null parent, rpl::producer text) { - auto result = object_ptr( - parent, - std::move(text), - st::boostLevelBadge); - const auto label = result.data(); - - label->show(); - label->paintRequest() | rpl::start_with_next([=] { - const auto size = label->textMaxWidth(); - const auto rect = QRect( - (label->width() - size) / 2, - st::boostLevelBadge.margin.top(), - size, - st::boostLevelBadge.style.font->height - ).marginsAdded(st::boostLevelBadge.margin); - auto p = QPainter(label); - auto hq = PainterHighQualityEnabler(p); + return MakeBoostFeaturesBadge(parent, std::move(text), [](QRect rect) { auto gradient = QLinearGradient( rect.topLeft(), rect.topRight()); gradient.setStops(Ui::Premium::GiftGradientStops()); - p.setBrush(gradient); - p.setPen(Qt::NoPen); - p.drawRoundedRect(rect, rect.height() / 2., rect.height() / 2.); - - const auto &lineFg = st::windowBgRipple; - const auto line = st::boostLevelBadgeLine; - const auto top = st::boostLevelBadge.margin.top() - + ((st::boostLevelBadge.style.font->height - line) / 2); - const auto left = 0; - const auto skip = st::boostLevelBadgeSkip; - if (const auto right = rect.x() - skip; right > left) { - p.fillRect(left, top, right - left, line, lineFg); - } - const auto right = label->width(); - if (const auto left = rect.x() + rect.width() + skip - ; left < right) { - p.fillRect(left, top, right - left, line, lineFg); - } - }, label->lifetime()); - - return result; + return QBrush(gradient); + }); } void AddFeaturesList( @@ -885,4 +850,48 @@ void FillBoostLimit( limitLinePadding); } +object_ptr MakeBoostFeaturesBadge( + not_null parent, + rpl::producer text, + Fn bg) { + auto result = object_ptr( + parent, + std::move(text), + st::boostLevelBadge); + const auto label = result.data(); + + label->show(); + label->paintRequest() | rpl::start_with_next([=] { + const auto size = label->textMaxWidth(); + const auto rect = QRect( + (label->width() - size) / 2, + st::boostLevelBadge.margin.top(), + size, + st::boostLevelBadge.style.font->height + ).marginsAdded(st::boostLevelBadge.margin); + auto p = QPainter(label); + auto hq = PainterHighQualityEnabler(p); + p.setBrush(bg(rect)); + p.setPen(Qt::NoPen); + p.drawRoundedRect(rect, rect.height() / 2., rect.height() / 2.); + + const auto &lineFg = st::windowBgRipple; + const auto line = st::boostLevelBadgeLine; + const auto top = st::boostLevelBadge.margin.top() + + ((st::boostLevelBadge.style.font->height - line) / 2); + const auto left = 0; + const auto skip = st::boostLevelBadgeSkip; + if (const auto right = rect.x() - skip; right > left) { + p.fillRect(left, top, right - left, line, lineFg); + } + const auto right = label->width(); + if (const auto left = rect.x() + rect.width() + skip + ; left < right) { + p.fillRect(left, top, right - left, line, lineFg); + } + }, label->lifetime()); + + return result; +} + } // namespace Ui diff --git a/Telegram/SourceFiles/ui/boxes/boost_box.h b/Telegram/SourceFiles/ui/boxes/boost_box.h index 6c129512d..4ecd58bf2 100644 --- a/Telegram/SourceFiles/ui/boxes/boost_box.h +++ b/Telegram/SourceFiles/ui/boxes/boost_box.h @@ -17,6 +17,7 @@ class Show; class RpWidget; class GenericBox; class VerticalLayout; +class FlatLabel; struct BoostCounters { int level = 0; @@ -129,4 +130,9 @@ void FillBoostLimit( rpl::producer data, style::margins limitLinePadding); +[[nodiscard]] object_ptr MakeBoostFeaturesBadge( + not_null parent, + rpl::producer text, + Fn bg); + } // namespace Ui diff --git a/Telegram/SourceFiles/ui/effects/credits.style b/Telegram/SourceFiles/ui/effects/credits.style index b982687d6..2c59d496b 100644 --- a/Telegram/SourceFiles/ui/effects/credits.style +++ b/Telegram/SourceFiles/ui/effects/credits.style @@ -46,7 +46,7 @@ creditsBoxButtonLabel: FlatLabel(defaultFlatLabel) { } starIconSmall: icon{{ "payments/small_star", windowFg }}; -starIconSmallPadding: margins(0px, -2px, 0px, 0px); +starIconSmallPadding: margins(0px, -3px, 0px, 0px); creditsHistoryEntryTypeAds: icon {{ "folders/folders_channels", premiumButtonFg }}; diff --git a/Telegram/SourceFiles/ui/effects/premium.style b/Telegram/SourceFiles/ui/effects/premium.style index 33fae62eb..1c7b8884c 100644 --- a/Telegram/SourceFiles/ui/effects/premium.style +++ b/Telegram/SourceFiles/ui/effects/premium.style @@ -340,13 +340,13 @@ showOrBox: Box(boostBox) { boostBoxMaxHeight: 512px; boostLevelBadge: FlatLabel(defaultFlatLabel) { - margin: margins(12px, 4px, 12px, 4px); + margin: margins(12px, 4px, 12px, 5px); style: semiboldTextStyle; textFg: premiumButtonFg; align: align(top); } boostLevelBadgePadding: margins(30px, 12px, 32px, 12px); -boostLevelBadgeSkip: 8px; +boostLevelBadgeSkip: 12px; boostLevelBadgeLine: 1px; boostFeatureLabel: FlatLabel(defaultFlatLabel) { @@ -365,3 +365,29 @@ boostFeatureName: icon{{ "settings/premium/features/feature_color_names", window boostFeatureStories: icon{{ "settings/premium/features/feature_stories", windowBgActive }}; boostFeatureTranscribe: icon{{ "settings/premium/features/feature_voice", windowBgActive }}; boostFeatureOffSponsored: icon{{ "settings/premium/features/feature_off_sponsored", windowBgActive }}; + +paidReactTitleSkip: 23px; +paidReactTopTitleMargin: margins(10px, 26px, 10px, 12px); +paidReactTopMargin: margins(0px, 12px, 0px, 11px); +paidReactTopUserpic: 42px; +paidReactTopNameSkip: 47px; +paidReactTopBadgeSkip: 32px; +paidReactSlider: MediaSlider(defaultContinuousSlider) { + activeFg: creditsBg3; + inactiveFg: creditsBg2; + activeFgOver: creditsBg3; + inactiveFgOver: creditsBg2; + activeFgDisabled: creditsBg3; + inactiveFgDisabled: creditsBg2; + width: 6px; + seekSize: size(16px, 16px); +} +paidReactBox: Box(boostBox) { + buttonPadding: margins(22px, 22px, 22px, 22px); + buttonHeight: 42px; + button: RoundButton(defaultActiveButton) { + height: 42px; + textTop: 12px; + font: font(13px semibold); + } +} diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 8db5d1aa5..a5b1266a8 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 8db5d1aa533334c75ed2598ecf3607768ae9b418 +Subproject commit a5b1266a8c340ed916466a83cbbc5793471c2438