From 2a4faf22f66f470268ebc20598c04fb7b2483dad Mon Sep 17 00:00:00 2001
From: 23rd <23rd@vivaldi.net>
Date: Mon, 23 May 2022 07:01:31 +0300
Subject: [PATCH] Added initial animation to custom top bar in premium
settings.
---
Telegram/Resources/icons/settings/star.svg | 9 +
Telegram/Resources/qrc/telegram/telegram.qrc | 1 +
Telegram/SourceFiles/settings/settings.style | 2 +
.../SourceFiles/settings/settings_premium.cpp | 201 +++++++++++++-----
4 files changed, 155 insertions(+), 58 deletions(-)
create mode 100644 Telegram/Resources/icons/settings/star.svg
diff --git a/Telegram/Resources/icons/settings/star.svg b/Telegram/Resources/icons/settings/star.svg
new file mode 100644
index 000000000..1549c272f
--- /dev/null
+++ b/Telegram/Resources/icons/settings/star.svg
@@ -0,0 +1,9 @@
+
+
diff --git a/Telegram/Resources/qrc/telegram/telegram.qrc b/Telegram/Resources/qrc/telegram/telegram.qrc
index 6e477ef03..75cc1293a 100644
--- a/Telegram/Resources/qrc/telegram/telegram.qrc
+++ b/Telegram/Resources/qrc/telegram/telegram.qrc
@@ -26,6 +26,7 @@
../../art/recording/recording_info_video_landscape.svg
../../art/recording/recording_info_video_portrait.svg
../../icons/settings/dino.svg
+ ../../icons/settings/star.svg
../../icons/calls/hands.lottie
diff --git a/Telegram/SourceFiles/settings/settings.style b/Telegram/SourceFiles/settings/settings.style
index 7d0d6548d..f010f9885 100644
--- a/Telegram/SourceFiles/settings/settings.style
+++ b/Telegram/SourceFiles/settings/settings.style
@@ -425,6 +425,8 @@ settingsPremiumDescriptionSkip: 3px;
settingsPremiumButtonPadding: margins(11px, 11px, 11px, 3px);
settingsPremiumTopBarBackIcon: icon {{ "info/info_back", premiumButtonFg }};
settingsPremiumTopBarBackIconOver: icon {{ "info/info_back", premiumButtonFg }};
+settingsPremiumStarSize: size(77px, 73px);
+settingsPremiumStarTopSkip: 42px;
settingsPremiumTopBarBack: IconButton(infoTopBarBack) {
icon: settingsPremiumTopBarBackIcon;
iconOver: settingsPremiumTopBarBackIconOver;
diff --git a/Telegram/SourceFiles/settings/settings_premium.cpp b/Telegram/SourceFiles/settings/settings_premium.cpp
index f76a445d6..b00f2ba3f 100644
--- a/Telegram/SourceFiles/settings/settings_premium.cpp
+++ b/Telegram/SourceFiles/settings/settings_premium.cpp
@@ -37,11 +37,137 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "styles/style_layers.h"
#include "styles/style_settings.h"
+#include
+
namespace Settings {
namespace {
using SectionCustomTopBarData = Info::Settings::SectionCustomTopBarData;
+constexpr auto kBodyAnimationPart = 0.90;
+constexpr auto kTitleAnimationPart = 0.15;
+
+class TopBar final : public Ui::RpWidget {
+public:
+ TopBar(not_null parent);
+
+ void setRoundEdges(bool value);
+ void setTextPosition(int x, int y);
+
+protected:
+ void paintEvent(QPaintEvent *e) override;
+
+private:
+ QSvgRenderer _star;
+ Ui::Text::String _title;
+ Ui::Text::String _about;
+
+ QPoint _titlePosition;
+ bool _roundEdges = true;
+
+};
+
+TopBar::TopBar(not_null parent)
+: Ui::RpWidget(parent)
+, _star(u":/gui/icons/settings/star.svg"_q)
+, _title(st::boxTitle.style, tr::lng_premium_summary_title(tr::now)) {
+ _about.setMarkedText(
+ st::aboutLabel.style,
+ tr::lng_premium_summary_top_about(tr::now, Ui::Text::RichLangValue));
+}
+
+void TopBar::setRoundEdges(bool value) {
+ _roundEdges = value;
+ update();
+}
+
+void TopBar::setTextPosition(int x, int y) {
+ _titlePosition = { x, y };
+}
+
+void TopBar::paintEvent(QPaintEvent *e) {
+ Painter p(this);
+
+ p.fillRect(e->rect(), Qt::transparent);
+
+ const auto progress = (height() - minimumHeight())
+ / float64(maximumHeight() - minimumHeight());
+ const auto topProgress = 1. -
+ std::clamp(
+ (1. - progress) / kBodyAnimationPart,
+ 0.,
+ 1.);
+ const auto bodyProgress = topProgress;
+
+ const auto r = rect();
+ auto pathTop = QPainterPath();
+ if (_roundEdges) {
+ pathTop.addRoundedRect(r, st::boxRadius, st::boxRadius);
+ } else {
+ pathTop.addRect(r);
+ }
+ auto pathBottom = QPainterPath();
+ pathBottom.addRect(
+ QRect(
+ QPoint(r.x(), r.y() + r.height() - st::boxRadius),
+ QSize(r.width(), st::boxRadius)));
+
+ const auto gradientPointTop = r.height() / 3. * 2.;
+ auto gradient = QLinearGradient(
+ QPointF(0, gradientPointTop),
+ QPointF(r.width(), r.height() - gradientPointTop));
+ gradient.setColorAt(0., st::premiumButtonBg1->c);
+ gradient.setColorAt(.6, st::premiumButtonBg2->c);
+ gradient.setColorAt(1., st::premiumButtonBg3->c);
+
+ PainterHighQualityEnabler hq(p);
+ p.fillPath(pathTop + pathBottom, gradient);
+
+ p.setOpacity(bodyProgress);
+
+ const auto &starSize = st::settingsPremiumStarSize;
+ const auto starRect = QRectF(
+ QPointF(
+ (width() - starSize.width()) / 2,
+ st::settingsPremiumStarTopSkip * topProgress),
+ st::settingsPremiumStarSize);
+ _star.render(&p, starRect);
+
+ p.setPen(st::premiumButtonFg);
+
+ const auto &padding = st::boxRowPadding;
+ const auto availableWidth = width() - padding.left() - padding.right();
+ const auto titleTop = starRect.top()
+ + starRect.height()
+ + st::changePhoneTitlePadding.top();
+ const auto aboutTop = titleTop
+ + _title.countHeight(availableWidth)
+ + st::changePhoneTitlePadding.bottom();
+
+ p.setFont(st::aboutLabel.style.font);
+ _about.draw(p, padding.left(), aboutTop, availableWidth, style::al_top);
+
+ // Subtitle.
+ p.setFont(st::boxTitle.style.font);
+ _title.draw(p, padding.left(), titleTop, availableWidth, style::al_top);
+
+ // Title.
+ const auto titleProgress =
+ std::clamp(
+ (kTitleAnimationPart - progress) / kTitleAnimationPart,
+ 0.,
+ 1.);
+ if (titleProgress > 0.) {
+ p.setOpacity(titleProgress);
+ const auto availableWidth = width() - _titlePosition.x() * 2;
+ _title.drawElided(
+ p,
+ _titlePosition.x(),
+ _titlePosition.y(),
+ availableWidth);
+ }
+}
+
class Premium : public Section {
public:
Premium(
@@ -108,29 +234,6 @@ void Premium::setStepDataReference(std::any &data) {
void Premium::setupContent() {
const auto content = Ui::CreateChild(this);
- content->add(
- object_ptr>(
- content,
- object_ptr(
- content,
- tr::lng_premium_summary_title(),
- st::changePhoneTitle)),
- st::changePhoneTitlePadding);
-
- const auto wrap = content->add(
- object_ptr>(
- content,
- object_ptr(
- content,
- tr::lng_premium_summary_top_about(Ui::Text::RichLangValue),
- st::changePhoneDescription)),
- st::changePhoneDescriptionPadding);
- wrap->resize(
- wrap->width(),
- st::settingLocalPasscodeDescriptionHeight);
-
- AddSkip(content);
- AddDivider(content);
AddSkip(content);
const auto &st = st::settingsButton;
@@ -266,42 +369,17 @@ void Premium::setupContent() {
QPointer Premium::createPinnedToTop(
not_null parent) {
- const auto container = Ui::CreateChild(parent.get());
- const auto content = container->add(object_ptr(container));
- content->resize(content->width(), st::introQrStepsTop);
+ const auto content = Ui::CreateChild(parent.get());
- container->setAttribute(Qt::WA_OpaquePaintEvent, false);
- content->setAttribute(Qt::WA_OpaquePaintEvent, false);
-
- content->paintRequest(
- ) | rpl::start_with_next([=](const QRect &paintRect) {
- Painter p(content);
-
- p.fillRect(paintRect, Qt::transparent);
-
- const auto rect = content->rect();
- auto pathTop = QPainterPath();
- pathTop.addRoundedRect(rect, st::boxRadius, st::boxRadius);
- auto pathBottom = QPainterPath();
- pathBottom.addRect(
- QRect(
- QPoint(rect.x(), rect.y() + rect.height() - st::boxRadius),
- QSize(rect.width(), st::boxRadius)));
-
- const auto gradientPointTop = rect.height() / 3. * 2.;
- auto gradient = QLinearGradient(
- QPointF(0, gradientPointTop),
- QPointF(rect.width(), rect.height() - gradientPointTop));
- gradient.setColorAt(0., st::premiumButtonBg1->c);
- gradient.setColorAt(.6, st::premiumButtonBg2->c);
- gradient.setColorAt(1., st::premiumButtonBg3->c);
-
- PainterHighQualityEnabler hq(p);
- p.fillPath(pathTop + pathBottom, gradient);
+ _wrap.value(
+ ) | rpl::start_with_next([=](Info::Wrap wrap) {
+ content->setRoundEdges(wrap == Info::Wrap::Layer);
}, content->lifetime());
- container->setMaximumHeight(st::introQrStepsTop);
- container->setMinimumHeight(st::infoLayerTopBarHeight);
+ content->setMaximumHeight(st::introQrStepsTop);
+ content->setMinimumHeight(st::infoLayerTopBarHeight);
+
+ content->resize(content->width(), content->maximumHeight());
_wrap.value(
) | rpl::start_with_next([=](Info::Wrap wrap) {
@@ -319,6 +397,13 @@ QPointer Premium::createPinnedToTop(
_back->entity()->addClickHandler([=] {
_showBack.fire({});
});
+ _back->toggledValue(
+ ) | rpl::start_with_next([=](bool toggled) {
+ const auto &st = isLayer ? st::infoLayerTopBar : st::infoTopBar;
+ content->setTextPosition(
+ toggled ? st.back.width : st.titlePosition.x(),
+ st.titlePosition.y());
+ }, _back->lifetime());
if (!isLayer) {
_close = nullptr;
@@ -335,9 +420,9 @@ QPointer Premium::createPinnedToTop(
_close->moveToRight(0, 0);
}, _close->lifetime());
}
- }, container->lifetime());
+ }, content->lifetime());
- return Ui::MakeWeak(not_null{ container });
+ return Ui::MakeWeak(not_null{ content });
}
QPointer Premium::createPinnedToBottom(