From 785014f7b73be5970610092b9795a9a272aca667 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 28 Sep 2023 22:01:39 +0400 Subject: [PATCH] Extract premium layer top bar widget. --- .../SourceFiles/settings/settings_premium.cpp | 351 +----------------- .../ui/effects/premium_top_bar.cpp | 315 ++++++++++++++++ .../SourceFiles/ui/effects/premium_top_bar.h | 93 +++++ Telegram/cmake/td_ui.cmake | 2 + 4 files changed, 423 insertions(+), 338 deletions(-) create mode 100644 Telegram/SourceFiles/ui/effects/premium_top_bar.cpp create mode 100644 Telegram/SourceFiles/ui/effects/premium_top_bar.h diff --git a/Telegram/SourceFiles/settings/settings_premium.cpp b/Telegram/SourceFiles/settings/settings_premium.cpp index b515e8fa1..ba0acc981 100644 --- a/Telegram/SourceFiles/settings/settings_premium.cpp +++ b/Telegram/SourceFiles/settings/settings_premium.cpp @@ -33,10 +33,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "settings/settings_premium.h" #include "ui/abstract_button.h" #include "ui/basic_click_handlers.h" -#include "ui/color_contrast.h" #include "ui/effects/gradient.h" #include "ui/effects/premium_graphics.h" #include "ui/effects/premium_stars_colored.h" +#include "ui/effects/premium_top_bar.h" #include "ui/layers/generic_box.h" #include "ui/text/format_values.h" #include "ui/text/text_utilities.h" @@ -67,41 +67,6 @@ namespace { using SectionCustomTopBarData = Info::Settings::SectionCustomTopBarData; -constexpr auto kBodyAnimationPart = 0.90; -constexpr auto kTitleAdditionalScale = 0.15; -constexpr auto kMinAcceptableContrast = 4.5; // 1.14; - -[[nodiscard]] QString Svg() { - return u":/gui/icons/settings/star.svg"_q; -} - -[[nodiscard]] QByteArray ColorizedSvg() { - auto f = QFile(Svg()); - if (!f.open(QIODevice::ReadOnly)) { - return QByteArray(); - } - auto content = qs(f.readAll()); - auto stops = [] { - auto s = QString(); - for (const auto &stop : Ui::Premium::ButtonGradientStops()) { - s += QString("") - .arg(QString::number(stop.first), stop.second.name()); - } - return s; - }(); - const auto color = QString("%5") - .arg(0) - .arg(1) - .arg(1) - .arg(0) - .arg(std::move(stops)); - content.replace(u"gradientPlaceholder"_q, color); - content.replace(u"#fff"_q, u"url(#Gradient2)"_q); - f.close(); - return content.toUtf8(); -} - [[nodiscard]] Data::SubscriptionOptions SubscriptionOptionsForRows( Data::SubscriptionOptions result) { for (auto &option : result) { @@ -412,85 +377,6 @@ void SendScreenAccept(not_null controller) { MTP_jsonNull()); } -class TopBarAbstract : public Ui::RpWidget { -public: - using Ui::RpWidget::RpWidget; - - void setRoundEdges(bool value); - - virtual void setPaused(bool paused) = 0; - virtual void setTextPosition(int x, int y) = 0; - - [[nodiscard]] virtual rpl::producer additionalHeight() const = 0; - -protected: - void paintEdges(QPainter &p, const QBrush &brush) const; - void paintEdges(QPainter &p) const; - - [[nodiscard]] QRectF starRect( - float64 topProgress, - float64 sizeProgress) const; - - [[nodiscard]] bool isDark() const; - void computeIsDark(); - -private: - bool _roundEdges = true; - bool _isDark = false; - -}; - -void TopBarAbstract::setRoundEdges(bool value) { - _roundEdges = value; - update(); -} - -void TopBarAbstract::paintEdges(QPainter &p, const QBrush &brush) const { - const auto r = rect(); - if (_roundEdges) { - PainterHighQualityEnabler hq(p); - const auto radius = st::boxRadius; - p.setPen(Qt::NoPen); - p.setBrush(brush); - p.drawRoundedRect( - r + QMargins{ 0, 0, 0, radius + 1 }, - radius, - radius); - } else { - p.fillRect(r, brush); - } -} - -void TopBarAbstract::paintEdges(QPainter &p) const { - paintEdges(p, st::boxBg); - if (isDark()) { - paintEdges(p, st::shadowFg); - paintEdges(p, st::shadowFg); - } -} - -QRectF TopBarAbstract::starRect( - float64 topProgress, - float64 sizeProgress) const { - const auto starSize = st::settingsPremiumStarSize * sizeProgress; - return QRectF( - QPointF( - (width() - starSize.width()) / 2, - st::settingsPremiumStarTopSkip * topProgress), - starSize); -}; - -bool TopBarAbstract::isDark() const { - return _isDark; -} - -void TopBarAbstract::computeIsDark() { - const auto contrast = Ui::CountContrast( - st::boxBg->c, - st::premiumButtonFg->c); - _isDark = (contrast > kMinAcceptableContrast); -} - class EmojiStatusTopBar final { public: EmojiStatusTopBar( @@ -583,7 +469,7 @@ void EmojiStatusTopBar::paint(QPainter &p) { } } -class TopBarUser final : public TopBarAbstract { +class TopBarUser final : public Ui::Premium::TopBarAbstract { public: TopBarUser( not_null parent, @@ -674,38 +560,8 @@ TopBarUser::TopBarUser( HistoryView::Sticker::EmojiSize()); _imageStar = QImage(); } else { - auto svg = QSvgRenderer(Svg()); - - const auto size = _starRect.size().toSize(); - auto frame = QImage( - size * style::DevicePixelRatio(), - QImage::Format_ARGB32_Premultiplied); - frame.setDevicePixelRatio(style::DevicePixelRatio()); - - auto mask = frame; - mask.fill(Qt::transparent); - { - auto p = QPainter(&mask); - auto gradient = QLinearGradient( - 0, - size.height(), - size.width(), - 0); - gradient.setStops(Ui::Premium::ButtonGradientStops()); - p.setPen(Qt::NoPen); - p.setBrush(gradient); - p.drawRect(0, 0, size.width(), size.height()); - } - frame.fill(Qt::transparent); - { - auto q = QPainter(&frame); - svg.render(&q, QRect(QPoint(), size)); - q.setCompositionMode(QPainter::CompositionMode_SourceIn); - q.drawImage(0, 0, mask); - } - _imageStar = std::move(frame); - _emojiStatus = nullptr; + _imageStar = Ui::Premium::GenerateStarForLightTopBar(_starRect); } updateTitle(document, { name }, controller); @@ -925,194 +781,6 @@ void TopBarUser::resizeEvent(QResizeEvent *e) { } } -class TopBar final : public TopBarAbstract { -public: - TopBar( - not_null parent, - not_null controller, - rpl::producer title, - rpl::producer about); - - void setPaused(bool paused) override; - void setTextPosition(int x, int y) override; - - rpl::producer additionalHeight() const override; - -protected: - void paintEvent(QPaintEvent *e) override; - void resizeEvent(QResizeEvent *e) override; - -private: - const style::font &_titleFont; - const style::margins &_titlePadding; - object_ptr _about; - Ui::Premium::ColoredMiniStars _ministars; - QSvgRenderer _star; - - struct { - float64 top = 0.; - float64 body = 0.; - float64 title = 0.; - float64 scaleTitle = 0.; - } _progress; - - QRectF _starRect; - - QPoint _titlePosition; - QPainterPath _titlePath; - -}; - -TopBar::TopBar( - not_null parent, - not_null controller, - rpl::producer title, - rpl::producer about) -: TopBarAbstract(parent) -, _titleFont(st::boxTitle.style.font) -, _titlePadding(st::settingsPremiumTitlePadding) -, _about(this, std::move(about), st::settingsPremiumAbout) -, _ministars(this) { - std::move( - title - ) | rpl::start_with_next([=](QString text) { - _titlePath = QPainterPath(); - _titlePath.addText(0, _titleFont->ascent, _titleFont, text); - update(); - }, lifetime()); - - _about->setClickHandlerFilter([=]( - const ClickHandlerPtr &handler, - Qt::MouseButton button) { - ActivateClickHandler(_about, handler, { - button, - QVariant::fromValue(ClickHandlerContext{ - .sessionWindow = base::make_weak(controller), - .botStartAutoSubmit = true, - }) - }); - return false; - }); - - rpl::single() | rpl::then( - style::PaletteChanged() - ) | rpl::start_with_next([=] { - TopBarAbstract::computeIsDark(); - - if (!TopBarAbstract::isDark()) { - _star.load(Svg()); - _ministars.setColorOverride(st::premiumButtonFg->c); - } else { - _star.load(ColorizedSvg()); - _ministars.setColorOverride(std::nullopt); - } - auto event = QResizeEvent(size(), size()); - resizeEvent(&event); - }, lifetime()); -} - -void TopBar::setPaused(bool paused) { - _ministars.setPaused(paused); -} - -void TopBar::setTextPosition(int x, int y) { - _titlePosition = { x, y }; -} - -rpl::producer TopBar::additionalHeight() const { - return _about->heightValue( - ) | rpl::map([l = st::settingsPremiumAbout.style.lineHeight](int height) { - return std::max(height - l * 2, 0); - }); -} - -void TopBar::resizeEvent(QResizeEvent *e) { - const auto progress = (e->size().height() - minimumHeight()) - / float64(maximumHeight() - minimumHeight()); - _progress.top = 1. - - std::clamp( - (1. - progress) / kBodyAnimationPart, - 0., - 1.); - _progress.body = _progress.top; - _progress.title = 1. - progress; - _progress.scaleTitle = 1. + kTitleAdditionalScale * progress; - - _ministars.setCenter(starRect(_progress.top, 1.).toRect()); - - _starRect = starRect(_progress.top, _progress.body); - - const auto &padding = st::boxRowPadding; - const auto availableWidth = width() - padding.left() - padding.right(); - const auto titleTop = _starRect.top() - + _starRect.height() - + _titlePadding.top(); - const auto titlePathRect = _titlePath.boundingRect(); - const auto aboutTop = titleTop - + titlePathRect.height() - + _titlePadding.bottom(); - _about->resizeToWidth(availableWidth); - _about->moveToLeft(padding.left(), aboutTop); - _about->setOpacity(_progress.body); - - Ui::RpWidget::resizeEvent(e); -} - -void TopBar::paintEvent(QPaintEvent *e) { - auto p = QPainter(this); - - p.fillRect(e->rect(), Qt::transparent); - - const auto r = rect(); - - if (!TopBarAbstract::isDark()) { - const auto gradientPointTop = r.height() / 3. * 2.; - auto gradient = QLinearGradient( - QPointF(0, gradientPointTop), - QPointF(r.width(), r.height() - gradientPointTop)); - gradient.setStops(Ui::Premium::ButtonGradientStops()); - - TopBarAbstract::paintEdges(p, gradient); - } else { - TopBarAbstract::paintEdges(p); - } - - p.setOpacity(_progress.body); - p.translate(_starRect.center()); - p.scale(_progress.body, _progress.body); - p.translate(-_starRect.center()); - if (_progress.top) { - _ministars.paint(p); - } - p.resetTransform(); - - _star.render(&p, _starRect); - - p.setPen(st::premiumButtonFg); - - const auto titlePathRect = _titlePath.boundingRect(); - - // Title. - PainterHighQualityEnabler hq(p); - p.setOpacity(1.); - p.setFont(_titleFont); - const auto fullStarRect = starRect(1., 1.); - const auto fullTitleTop = fullStarRect.top() - + fullStarRect.height() - + _titlePadding.top(); - p.translate( - anim::interpolate( - (width() - titlePathRect.width()) / 2, - _titlePosition.x(), - _progress.title), - anim::interpolate(fullTitleTop, _titlePosition.y(), _progress.title)); - - p.translate(titlePathRect.center()); - p.scale(_progress.scaleTitle, _progress.scaleTitle); - p.translate(-titlePathRect.center()); - p.fillPath(_titlePath, st::premiumButtonFg); -} - class Premium : public Section { public: Premium( @@ -1488,7 +1156,7 @@ QPointer Premium::createPinnedToTop( return nullptr; }(); - const auto content = [&]() -> TopBarAbstract* { + const auto content = [&]() -> Ui::Premium::TopBarAbstract* { if (peerWithPremium) { return Ui::CreateChild( parent.get(), @@ -1496,9 +1164,16 @@ QPointer Premium::createPinnedToTop( peerWithPremium, _showFinished.events()); } - return Ui::CreateChild( + const auto weak = base::make_weak(_controller); + const auto clickContextOther = [=] { + return QVariant::fromValue(ClickHandlerContext{ + .sessionWindow = weak, + .botStartAutoSubmit = true, + }); + }; + return Ui::CreateChild( parent.get(), - _controller, + clickContextOther, std::move(title), std::move(about)); }(); diff --git a/Telegram/SourceFiles/ui/effects/premium_top_bar.cpp b/Telegram/SourceFiles/ui/effects/premium_top_bar.cpp new file mode 100644 index 000000000..ba8ed602b --- /dev/null +++ b/Telegram/SourceFiles/ui/effects/premium_top_bar.cpp @@ -0,0 +1,315 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#include "ui/effects/premium_top_bar.h" + +#include "ui/color_contrast.h" +#include "ui/painter.h" +#include "ui/effects/premium_graphics.h" +#include "ui/widgets/labels.h" +#include "ui/wrap/fade_wrap.h" +#include "styles/style_layers.h" +#include "styles/style_settings.h" + +namespace Ui::Premium { +namespace { + +constexpr auto kBodyAnimationPart = 0.90; +constexpr auto kTitleAdditionalScale = 0.15; +constexpr auto kMinAcceptableContrast = 4.5; // 1.14; + +} // namespace + +QString Svg() { + return u":/gui/icons/settings/star.svg"_q; +} + +QByteArray ColorizedSvg() { + auto f = QFile(Svg()); + if (!f.open(QIODevice::ReadOnly)) { + return QByteArray(); + } + auto content = QString::fromUtf8(f.readAll()); + auto stops = [] { + auto s = QString(); + for (const auto &stop : Ui::Premium::ButtonGradientStops()) { + s += QString("") + .arg(QString::number(stop.first), stop.second.name()); + } + return s; + }(); + const auto color = QString("%5") + .arg(0) + .arg(1) + .arg(1) + .arg(0) + .arg(std::move(stops)); + content.replace(u"gradientPlaceholder"_q, color); + content.replace(u"#fff"_q, u"url(#Gradient2)"_q); + f.close(); + return content.toUtf8(); +} + +QImage GenerateStarForLightTopBar(QRectF rect) { + auto svg = QSvgRenderer(Ui::Premium::Svg()); + + const auto size = rect.size().toSize(); + auto frame = QImage( + size * style::DevicePixelRatio(), + QImage::Format_ARGB32_Premultiplied); + frame.setDevicePixelRatio(style::DevicePixelRatio()); + + auto mask = frame; + mask.fill(Qt::transparent); + { + auto p = QPainter(&mask); + auto gradient = QLinearGradient( + 0, + size.height(), + size.width(), + 0); + gradient.setStops(Ui::Premium::ButtonGradientStops()); + p.setPen(Qt::NoPen); + p.setBrush(gradient); + p.drawRect(0, 0, size.width(), size.height()); + } + frame.fill(Qt::transparent); + { + auto q = QPainter(&frame); + svg.render(&q, QRect(QPoint(), size)); + q.setCompositionMode(QPainter::CompositionMode_SourceIn); + q.drawImage(0, 0, mask); + } + return frame; +} + +void TopBarAbstract::setRoundEdges(bool value) { + _roundEdges = value; + update(); +} + +void TopBarAbstract::paintEdges(QPainter &p, const QBrush &brush) const { + const auto r = rect(); + if (_roundEdges) { + PainterHighQualityEnabler hq(p); + const auto radius = st::boxRadius; + p.setPen(Qt::NoPen); + p.setBrush(brush); + p.drawRoundedRect( + r + QMargins{ 0, 0, 0, radius + 1 }, + radius, + radius); + } else { + p.fillRect(r, brush); + } +} + +void TopBarAbstract::paintEdges(QPainter &p) const { + paintEdges(p, st::boxBg); + if (isDark()) { + paintEdges(p, st::shadowFg); + paintEdges(p, st::shadowFg); + } +} + +QRectF TopBarAbstract::starRect( + float64 topProgress, + float64 sizeProgress) const { + const auto starSize = st::settingsPremiumStarSize * sizeProgress; + return QRectF( + QPointF( + (width() - starSize.width()) / 2, + st::settingsPremiumStarTopSkip * topProgress), + starSize); +}; + +bool TopBarAbstract::isDark() const { + return _isDark; +} + +void TopBarAbstract::computeIsDark() { + const auto contrast = CountContrast( + st::boxBg->c, + st::premiumButtonFg->c); + _isDark = (contrast > kMinAcceptableContrast); +} + +TopBar::TopBar( + not_null parent, + Fn clickContextOther, + rpl::producer title, + rpl::producer about, + bool light) +: TopBarAbstract(parent) +, _light(light) +, _titleFont(st::boxTitle.style.font) +, _titlePadding(st::settingsPremiumTitlePadding) +, _about( + this, + std::move(about), + _light ? st::settingsPremiumUserAbout : st::settingsPremiumAbout) +, _ministars(this) { + std::move( + title + ) | rpl::start_with_next([=](QString text) { + _titlePath = QPainterPath(); + _titlePath.addText(0, _titleFont->ascent, _titleFont, text); + update(); + }, lifetime()); + + if (clickContextOther) { + _about->setClickHandlerFilter([=]( + const ClickHandlerPtr &handler, + Qt::MouseButton button) { + ActivateClickHandler(_about, handler, { + button, + clickContextOther() + }); + return false; + }); + } + + rpl::single() | rpl::then( + style::PaletteChanged() + ) | rpl::start_with_next([=] { + TopBarAbstract::computeIsDark(); + + if (!_light && !TopBarAbstract::isDark()) { + _star.load(Svg()); + _ministars.setColorOverride(st::premiumButtonFg->c); + } else { + _star.load(ColorizedSvg()); + _ministars.setColorOverride(std::nullopt); + } + auto event = QResizeEvent(size(), size()); + resizeEvent(&event); + }, lifetime()); + + if (_light) { + const auto smallTopShadow = CreateChild(this); + smallTopShadow->setDuration(st::fadeWrapDuration); + sizeValue( + ) | rpl::start_with_next([=](QSize size) { + smallTopShadow->resizeToWidth(size.width()); + smallTopShadow->moveToLeft( + 0, + height() - smallTopShadow->height()); + const auto shown = (minimumHeight() * 2 > size.height()); + smallTopShadow->toggle(shown, anim::type::normal); + }, lifetime()); + } +} + +TopBar::~TopBar() = default; + +void TopBar::setPaused(bool paused) { + _ministars.setPaused(paused); +} + +void TopBar::setTextPosition(int x, int y) { + _titlePosition = { x, y }; +} + +rpl::producer TopBar::additionalHeight() const { + return _about->heightValue( + ) | rpl::map([l = st::settingsPremiumAbout.style.lineHeight](int height) { + return std::max(height - l * 2, 0); + }); +} + +void TopBar::resizeEvent(QResizeEvent *e) { + const auto progress = (e->size().height() - minimumHeight()) + / float64(maximumHeight() - minimumHeight()); + _progress.top = 1. - + std::clamp( + (1. - progress) / kBodyAnimationPart, + 0., + 1.); + _progress.body = _progress.top; + _progress.title = 1. - progress; + _progress.scaleTitle = 1. + kTitleAdditionalScale * progress; + + _ministars.setCenter(starRect(_progress.top, 1.).toRect()); + + _starRect = starRect(_progress.top, _progress.body); + + const auto &padding = st::boxRowPadding; + const auto availableWidth = width() - padding.left() - padding.right(); + const auto titleTop = _starRect.top() + + _starRect.height() + + _titlePadding.top(); + const auto titlePathRect = _titlePath.boundingRect(); + const auto aboutTop = titleTop + + titlePathRect.height() + + _titlePadding.bottom(); + _about->resizeToWidth(availableWidth); + _about->moveToLeft(padding.left(), aboutTop); + _about->setOpacity(_progress.body); + + RpWidget::resizeEvent(e); +} + +void TopBar::paintEvent(QPaintEvent *e) { + auto p = QPainter(this); + + p.fillRect(e->rect(), Qt::transparent); + + const auto r = rect(); + + if (!_light && !TopBarAbstract::isDark()) { + const auto gradientPointTop = r.height() / 3. * 2.; + auto gradient = QLinearGradient( + QPointF(0, gradientPointTop), + QPointF(r.width(), r.height() - gradientPointTop)); + gradient.setStops(ButtonGradientStops()); + + TopBarAbstract::paintEdges(p, gradient); + } else { + TopBarAbstract::paintEdges(p); + } + + p.setOpacity(_progress.body); + p.translate(_starRect.center()); + p.scale(_progress.body, _progress.body); + p.translate(-_starRect.center()); + if (_progress.top) { + _ministars.paint(p); + } + p.resetTransform(); + + _star.render(&p, _starRect); + + const auto color = _light + ? st::settingsPremiumUserTitle.textFg + : st::premiumButtonFg; + p.setPen(color); + + const auto titlePathRect = _titlePath.boundingRect(); + + // Title. + PainterHighQualityEnabler hq(p); + p.setOpacity(1.); + p.setFont(_titleFont); + const auto fullStarRect = starRect(1., 1.); + const auto fullTitleTop = fullStarRect.top() + + fullStarRect.height() + + _titlePadding.top(); + p.translate( + anim::interpolate( + (width() - titlePathRect.width()) / 2, + _titlePosition.x(), + _progress.title), + anim::interpolate(fullTitleTop, _titlePosition.y(), _progress.title)); + + p.translate(titlePathRect.center()); + p.scale(_progress.scaleTitle, _progress.scaleTitle); + p.translate(-titlePathRect.center()); + p.fillPath(_titlePath, color); +} + +} // namespace Ui::Premium diff --git a/Telegram/SourceFiles/ui/effects/premium_top_bar.h b/Telegram/SourceFiles/ui/effects/premium_top_bar.h new file mode 100644 index 000000000..0cef38dc5 --- /dev/null +++ b/Telegram/SourceFiles/ui/effects/premium_top_bar.h @@ -0,0 +1,93 @@ +/* +This file is part of Telegram Desktop, +the official desktop application for the Telegram messaging service. + +For license and copyright information please follow this link: +https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL +*/ +#pragma once + +#include "base/object_ptr.h" +#include "ui/rp_widget.h" +#include "ui/effects/premium_stars_colored.h" + +namespace Ui { +class FlatLabel; +} // namespace Ui + +namespace Ui::Premium { + +[[nodiscard]] QString Svg(); +[[nodiscard]] QByteArray ColorizedSvg(); +[[nodiscard]] QImage GenerateStarForLightTopBar(QRectF rect); + +class TopBarAbstract : public RpWidget { +public: + using RpWidget::RpWidget; + + void setRoundEdges(bool value); + + virtual void setPaused(bool paused) = 0; + virtual void setTextPosition(int x, int y) = 0; + + [[nodiscard]] virtual rpl::producer additionalHeight() const = 0; + +protected: + void paintEdges(QPainter &p, const QBrush &brush) const; + void paintEdges(QPainter &p) const; + + [[nodiscard]] QRectF starRect( + float64 topProgress, + float64 sizeProgress) const; + + [[nodiscard]] bool isDark() const; + void computeIsDark(); + +private: + bool _roundEdges = true; + bool _isDark = false; + +}; + +class TopBar final : public TopBarAbstract { +public: + TopBar( + not_null parent, + Fn clickContextOther, + rpl::producer title, + rpl::producer about, + bool light = false); + ~TopBar(); + + void setPaused(bool paused) override; + void setTextPosition(int x, int y) override; + + rpl::producer additionalHeight() const override; + +protected: + void paintEvent(QPaintEvent *e) override; + void resizeEvent(QResizeEvent *e) override; + +private: + const bool _light = false; + const style::font &_titleFont; + const style::margins &_titlePadding; + object_ptr _about; + ColoredMiniStars _ministars; + QSvgRenderer _star; + + struct { + float64 top = 0.; + float64 body = 0.; + float64 title = 0.; + float64 scaleTitle = 0.; + } _progress; + + QRectF _starRect; + + QPoint _titlePosition; + QPainterPath _titlePath; + +}; + +} // namespace Ui::Premium diff --git a/Telegram/cmake/td_ui.cmake b/Telegram/cmake/td_ui.cmake index f7617ca22..7e2955ac1 100644 --- a/Telegram/cmake/td_ui.cmake +++ b/Telegram/cmake/td_ui.cmake @@ -279,6 +279,8 @@ PRIVATE ui/effects/premium_stars.h ui/effects/premium_stars_colored.cpp ui/effects/premium_stars_colored.h + ui/effects/premium_top_bar.cpp + ui/effects/premium_top_bar.h ui/effects/round_checkbox.cpp ui/effects/round_checkbox.h ui/effects/scroll_content_shadow.cpp