From c310b263a67fdd3afae0b3ba3039bcb7dda17d88 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 23 May 2022 02:06:35 +0300 Subject: [PATCH] Added ability to provide back button to pinned to top content. --- Telegram/SourceFiles/core/update_checker.cpp | 2 +- .../SourceFiles/info/info_content_widget.h | 2 ++ .../SourceFiles/info/info_wrap_widget.cpp | 13 +++++-- Telegram/SourceFiles/info/info_wrap_widget.h | 2 ++ .../info/settings/info_settings_widget.cpp | 8 +++++ .../info/settings/info_settings_widget.h | 7 ++++ Telegram/SourceFiles/settings/settings.style | 16 +++++++++ .../SourceFiles/settings/settings_premium.cpp | 36 +++++++++++++++++++ 8 files changed, 83 insertions(+), 3 deletions(-) diff --git a/Telegram/SourceFiles/core/update_checker.cpp b/Telegram/SourceFiles/core/update_checker.cpp index 2d27e9c40..b1a181e49 100644 --- a/Telegram/SourceFiles/core/update_checker.cpp +++ b/Telegram/SourceFiles/core/update_checker.cpp @@ -23,7 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "main/main_session.h" #include "main/main_domain.h" #include "info/info_memento.h" -#include "info/settings/info_settings_widget.h" +#include "info/info_controller.h" #include "window/window_session_controller.h" #include "settings/settings_advanced.h" #include "settings/settings_intro.h" diff --git a/Telegram/SourceFiles/info/info_content_widget.h b/Telegram/SourceFiles/info/info_content_widget.h index 01008d38c..dd3e35aae 100644 --- a/Telegram/SourceFiles/info/info_content_widget.h +++ b/Telegram/SourceFiles/info/info_content_widget.h @@ -56,6 +56,8 @@ public: virtual void setInnerFocus(); virtual void showFinished() { } + virtual void enableBackButton() { + } // When resizing the widget with top edge moved up or down and we // want to add this top movement to the scroll position, so inner diff --git a/Telegram/SourceFiles/info/info_wrap_widget.cpp b/Telegram/SourceFiles/info/info_wrap_widget.cpp index 7f38efe0e..313d8ebfc 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.cpp +++ b/Telegram/SourceFiles/info/info_wrap_widget.cpp @@ -376,7 +376,7 @@ void WrapWidget::createTopBar() { _content->selectionAction(action); }, _topBar->lifetime()); - if (wrapValue == Wrap::Narrow || hasStackHistory()) { + if (hasBackButton()) { _topBar->enableBackButton(); _topBar->backRequest( ) | rpl::start_with_next([=] { @@ -995,6 +995,11 @@ void WrapWidget::showNewContent( _historyStack.clear(); } + { + if (hasBackButton()) { + newContent->enableBackButton(); + } + } { // Let old controller outlive old content widget. const auto oldController = std::exchange( @@ -1091,7 +1096,7 @@ QRect WrapWidget::floatPlayerAvailableRect() { object_ptr WrapWidget::createTopBarSurrogate( QWidget *parent) { - if (_topBar && (hasStackHistory() || wrap() == Wrap::Narrow)) { + if (_topBar && hasBackButton()) { Assert(_topBar != nullptr); auto result = object_ptr(parent); @@ -1151,6 +1156,10 @@ rpl::producer WrapWidget::grabbingForExpanding() const { return _grabbingForExpanding.value(); } +bool WrapWidget::hasBackButton() const { + return (wrap() == Wrap::Narrow || hasStackHistory()); +} + WrapWidget::~WrapWidget() = default; } // namespace Info diff --git a/Telegram/SourceFiles/info/info_wrap_widget.h b/Telegram/SourceFiles/info/info_wrap_widget.h index 5f8fe6b20..3fd4157b2 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.h +++ b/Telegram/SourceFiles/info/info_wrap_widget.h @@ -180,6 +180,8 @@ private: void highlightTopBar(); void setupShortcuts(); + [[nodiscard]] bool hasBackButton() const; + not_null topWidget() const; QRect contentGeometry() const; diff --git a/Telegram/SourceFiles/info/settings/info_settings_widget.cpp b/Telegram/SourceFiles/info/settings/info_settings_widget.cpp index 727459fb4..2e78ce1a5 100644 --- a/Telegram/SourceFiles/info/settings/info_settings_widget.cpp +++ b/Telegram/SourceFiles/info/settings/info_settings_widget.cpp @@ -60,6 +60,10 @@ Widget::Widget( _flexibleScroll.fillerWidthValue, lifetime()); + controller->stepDataReference() = SectionCustomTopBarData{ + .backButtonEnables = _flexibleScroll.backButtonEnables.events(), + }; + // ScrollArea -> PaddingWrap -> RpWidget. inner->setParent(filler->parentWidget()->parentWidget()); inner->raise(); @@ -220,6 +224,10 @@ std::shared_ptr Widget::doCreateMemento() { return result; } +void Widget::enableBackButton() { + _flexibleScroll.backButtonEnables.fire({}); +} + void Widget::saveState(not_null memento) { memento->setScrollTop(scrollTopSave()); } diff --git a/Telegram/SourceFiles/info/settings/info_settings_widget.h b/Telegram/SourceFiles/info/settings/info_settings_widget.h index fd77b4f0b..1773237cf 100644 --- a/Telegram/SourceFiles/info/settings/info_settings_widget.h +++ b/Telegram/SourceFiles/info/settings/info_settings_widget.h @@ -21,6 +21,10 @@ using Type = Section::SettingsType; struct Tag; +struct SectionCustomTopBarData { + rpl::producer<> backButtonEnables; +}; + class Memento final : public ContentMemento { public: Memento(not_null self, Type type); @@ -72,6 +76,8 @@ public: rpl::producer title() override; + void enableBackButton() override; + private: void saveState(not_null memento); void restoreState(not_null memento); @@ -84,6 +90,7 @@ private: struct { rpl::event_stream contentHeightValue; rpl::event_stream fillerWidthValue; + rpl::event_stream<> backButtonEnables; } _flexibleScroll; not_null<::Settings::AbstractSection*> _inner; QPointer _pinnedToTop; diff --git a/Telegram/SourceFiles/settings/settings.style b/Telegram/SourceFiles/settings/settings.style index 7f8feeacc..46bcd5a28 100644 --- a/Telegram/SourceFiles/settings/settings.style +++ b/Telegram/SourceFiles/settings/settings.style @@ -423,4 +423,20 @@ notifyPreviewBottomSkip: 9px; settingsPremiumDescriptionSkip: 3px; settingsPremiumButtonPadding: margins(11px, 11px, 11px, 3px); +settingsPremiumTopBarBackIcon: icon {{ "info/info_back", premiumButtonFg }}; +settingsPremiumTopBarBackIconOver: icon {{ "info/info_back", premiumButtonFg }}; +settingsPremiumTopBarBack: IconButton(infoTopBarBack) { + icon: settingsPremiumTopBarBackIcon; + iconOver: settingsPremiumTopBarBackIconOver; + ripple: RippleAnimation(defaultRippleAnimation) { + color: shadowFg; + } +} +settingsPremiumLayerTopBarBack: IconButton(infoLayerTopBarBack) { + icon: settingsPremiumTopBarBackIcon; + iconOver: settingsPremiumTopBarBackIcon; + ripple: RippleAnimation(defaultRippleAnimation) { + color: shadowFg; + } +} diff --git a/Telegram/SourceFiles/settings/settings_premium.cpp b/Telegram/SourceFiles/settings/settings_premium.cpp index ec42ed9a7..ab3570d23 100644 --- a/Telegram/SourceFiles/settings/settings_premium.cpp +++ b/Telegram/SourceFiles/settings/settings_premium.cpp @@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "settings/settings_premium.h" +#include "core/application.h" +#include "info/settings/info_settings_widget.h" // SectionCustomTopBarData. #include "lang/lang_keys.h" #include "settings/settings_common.h" #include "settings/settings_premium.h" @@ -18,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/text_utilities.h" #include "ui/widgets/gradient_round_button.h" #include "ui/widgets/labels.h" +#include "ui/wrap/fade_wrap.h" #include "ui/wrap/padding_wrap.h" #include "ui/wrap/vertical_layout.h" #include "window/window_session_controller.h" @@ -35,6 +38,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Settings { namespace { +using SectionCustomTopBarData = Info::Settings::SectionCustomTopBarData; + class Premium : public Section { public: Premium( @@ -50,11 +55,19 @@ public: [[nodiscard]] bool hasFlexibleTopBar() const override; + void setStepDataReference(std::any &data) override; + + [[nodiscard]] rpl::producer<> sectionShowBack() override final; + private: void setupContent(); const not_null _controller; + rpl::variable _backToggles; + + rpl::event_stream<> _showBack; + }; Premium::Premium( @@ -73,6 +86,19 @@ bool Premium::hasFlexibleTopBar() const { return true; } +rpl::producer<> Premium::sectionShowBack() { + return _showBack.events(); +} + +void Premium::setStepDataReference(std::any &data) { + const auto my = std::any_cast(&data); + if (my) { + _backToggles = std::move( + my->backButtonEnables + ) | rpl::map_to(true); + } +} + void Premium::setupContent() { const auto content = Ui::CreateChild(this); @@ -271,6 +297,16 @@ QPointer Premium::createPinnedToTop( container->setMaximumHeight(st::introQrStepsTop); container->setMinimumHeight(st::infoLayerTopBarHeight); + const auto back = Ui::CreateChild>( + content, + object_ptr(content, st::settingsPremiumTopBarBack), + st::infoTopBarScale); + back->setDuration(0); + back->toggleOn(_backToggles.value()); + back->entity()->addClickHandler([=] { + _showBack.fire({}); + }); + return Ui::MakeWeak(not_null{ container }); }