From b850852221fd27e8c70b01238638a29b50774369 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 2 May 2023 13:32:56 +0400 Subject: [PATCH] Simplify working with Ui::Show and toasts. --- CMakeLists.txt | 3 +- ui/layers/box_content.cpp | 178 +++++++++++++++++++++------------- ui/layers/box_content.h | 40 +++----- ui/layers/layer_manager.cpp | 3 +- ui/layers/show.cpp | 43 ++++++++ ui/layers/show.h | 22 +++++ ui/toast/toast.cpp | 3 +- ui/toast/toast.h | 10 +- ui/toasts/common_toasts.cpp | 31 ------ ui/toasts/common_toasts.h | 32 ------ ui/widgets/separate_panel.cpp | 25 +++-- ui/widgets/separate_panel.h | 21 +++- 12 files changed, 242 insertions(+), 169 deletions(-) create mode 100644 ui/layers/show.cpp delete mode 100644 ui/toasts/common_toasts.cpp delete mode 100644 ui/toasts/common_toasts.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 201b0fc..69e63b1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -97,6 +97,7 @@ PRIVATE ui/layers/layer_manager.h ui/layers/layer_widget.cpp ui/layers/layer_widget.h + ui/layers/show.cpp ui/layers/show.h ui/paint/arcs.cpp ui/paint/arcs.h @@ -180,8 +181,6 @@ PRIVATE ui/toast/toast_manager.h ui/toast/toast_widget.cpp ui/toast/toast_widget.h - ui/toasts/common_toasts.cpp - ui/toasts/common_toasts.h ui/widgets/box_content_divider.cpp ui/widgets/box_content_divider.h ui/widgets/buttons.cpp diff --git a/ui/layers/box_content.cpp b/ui/layers/box_content.cpp index be8b707..ba916a4 100644 --- a/ui/layers/box_content.cpp +++ b/ui/layers/box_content.cpp @@ -19,6 +19,98 @@ #include "styles/palette.h" namespace Ui { +namespace { + +class BoxShow final : public Show { +public: + explicit BoxShow(not_null box); + BoxShow(const BoxShow &other); + ~BoxShow(); + void showBox( + object_ptr content, + LayerOptions options = LayerOption::KeepOther) const override; + void hideLayer() const override; + [[nodiscard]] not_null toastParent() const override; + [[nodiscard]] bool valid() const override; + operator bool() const override; + +private: + BoxShow(QPointer weak, ShowPtr wrapped); + + bool resolve() const; + + const QPointer _weak; + mutable std::shared_ptr _wrapped; + rpl::lifetime _lifetime; + +}; + +BoxShow::BoxShow(not_null box) +: BoxShow(MakeWeak(box.get()), nullptr) { +} + +BoxShow::BoxShow(const BoxShow &other) +: BoxShow(other._weak, other._wrapped) { +} + +BoxShow::BoxShow(QPointer weak, ShowPtr wrapped) +: _weak(weak) +, _wrapped(std::move(wrapped)) { + if (!resolve()) { + if (const auto box = _weak.data()) { + box->boxClosing( + ) | rpl::start_with_next([=] { + resolve(); + _lifetime.destroy(); + }, _lifetime); + } + } +} + +BoxShow::~BoxShow() = default; + +bool BoxShow::resolve() const { + if (_wrapped) { + return true; + } else if (const auto strong = _weak.data()) { + if (strong->hasDelegate()) { + _wrapped = strong->getDelegate()->showFactory()(); + return true; + } + } + return false; +} + +void BoxShow::showBox( + object_ptr content, + LayerOptions options) const { + if (resolve()) { + _wrapped->showBox(std::move(content), options); + } +} + +void BoxShow::hideLayer() const { + if (resolve()) { + _wrapped->hideLayer(); + } +} + +not_null BoxShow::toastParent() const { + if (resolve()) { + return _wrapped->toastParent(); + } + Unexpected("Stale BoxShow::toastParent call."); +} + +bool BoxShow::valid() const { + return resolve() && _wrapped->valid(); +} + +BoxShow::operator bool() const { + return valid(); +} + +} // namespace void BoxContent::setTitle(rpl::producer title) { getDelegate()->setTitle(std::move(title) | Text::ToWithEntities()); @@ -197,6 +289,27 @@ int BoxContent::scrollHeight() const { return _scroll ? _scroll->height() : 0; } +base::weak_ptr BoxContent::showToast( + Toast::Config &&config) { + return BoxShow(this).showToast(std::move(config)); +} + +base::weak_ptr BoxContent::showToast( + TextWithEntities &&text, + crl::time duration) { + return BoxShow(this).showToast(std::move(text), duration); +} + +base::weak_ptr BoxContent::showToast( + const QString &text, + crl::time duration) { + return BoxShow(this).showToast(text, duration); +} + +std::shared_ptr BoxContent::uiShow() { + return std::make_shared(this); +} + void BoxContent::scrollByDraggingDelta(int delta) { _draggingScroll.checkDeltaScroll(_scroll ? delta : 0); } @@ -335,69 +448,4 @@ void BoxContent::paintEvent(QPaintEvent *e) { } } -BoxShow::BoxShow(not_null box) -: BoxShow(MakeWeak(box.get()), nullptr) { -} - -BoxShow::BoxShow(const BoxShow &other) -: BoxShow(other._weak, other._wrapped) { -} - -BoxShow::BoxShow(QPointer weak, ShowPtr wrapped) -: _weak(weak) -, _wrapped(std::move(wrapped)) { - if (!resolve()) { - if (const auto box = _weak.data()) { - box->boxClosing( - ) | rpl::start_with_next([=] { - resolve(); - _lifetime.destroy(); - }, _lifetime); - } - } -} - -BoxShow::~BoxShow() = default; - -bool BoxShow::resolve() const { - if (_wrapped) { - return true; - } else if (const auto strong = _weak.data()) { - if (strong->hasDelegate()) { - _wrapped = strong->getDelegate()->showFactory()(); - return true; - } - } - return false; -} - -void BoxShow::showBox( - object_ptr content, - LayerOptions options) const { - if (resolve()) { - _wrapped->showBox(std::move(content), options); - } -} - -void BoxShow::hideLayer() const { - if (resolve()) { - _wrapped->hideLayer(); - } -} - -not_null BoxShow::toastParent() const { - if (resolve()) { - return _wrapped->toastParent(); - } - Unexpected("Stale BoxShow::toastParent call."); -} - -bool BoxShow::valid() const { - return resolve() && _wrapped->valid(); -} - -BoxShow::operator bool() const { - return valid(); -} - } // namespace Ui diff --git a/ui/layers/box_content.h b/ui/layers/box_content.h index 034e0ee..c5f31cd 100644 --- a/ui/layers/box_content.h +++ b/ui/layers/box_content.h @@ -35,6 +35,11 @@ namespace st { extern const style::ScrollArea &boxScroll; } // namespace st +namespace Ui::Toast { +struct Config; +class Instance; +} // namespace Ui::Toast + namespace Ui { class GenericBox; } // namespace Ui @@ -101,7 +106,6 @@ public: }; class BoxContent : public RpWidget { - public: BoxContent() { setAttribute(Qt::WA_OpaquePaintEvent); @@ -214,6 +218,16 @@ public: [[nodiscard]] int scrollTop() const; [[nodiscard]] int scrollHeight() const; + base::weak_ptr showToast(Toast::Config &&config); + base::weak_ptr showToast( + TextWithEntities &&text, + crl::time duration = 0); + base::weak_ptr showToast( + const QString &text, + crl::time duration = 0); + + [[nodiscard]] std::shared_ptr uiShow(); + protected: virtual void prepare() = 0; @@ -357,28 +371,4 @@ private: }; -class BoxShow : public Show { -public: - explicit BoxShow(not_null box); - BoxShow(const BoxShow &other); - ~BoxShow(); - void showBox( - object_ptr content, - LayerOptions options = LayerOption::KeepOther) const override; - void hideLayer() const override; - [[nodiscard]] not_null toastParent() const override; - [[nodiscard]] bool valid() const override; - operator bool() const override; - -private: - BoxShow(QPointer weak, ShowPtr wrapped); - - bool resolve() const; - - const QPointer _weak; - mutable std::shared_ptr _wrapped; - rpl::lifetime _lifetime; - -}; - } // namespace Ui diff --git a/ui/layers/layer_manager.cpp b/ui/layers/layer_manager.cpp index 505b4f1..81b2f83 100644 --- a/ui/layers/layer_manager.cpp +++ b/ui/layers/layer_manager.cpp @@ -68,7 +68,8 @@ ManagerShow::operator bool() const { } // namespace -LayerManager::LayerManager(not_null widget) : _widget(widget) { +LayerManager::LayerManager(not_null widget) +: _widget(widget) { } void LayerManager::setStyleOverrides( diff --git a/ui/layers/show.cpp b/ui/layers/show.cpp new file mode 100644 index 0000000..8b186aa --- /dev/null +++ b/ui/layers/show.cpp @@ -0,0 +1,43 @@ +// This file is part of Desktop App Toolkit, +// a set of libraries for developing nice desktop applications. +// +// For license and copyright information please follow this link: +// https://github.com/desktop-app/legal/blob/master/LEGAL +// +#include "ui/layers/show.h" + +#include "ui/toast/toast.h" + +namespace Ui { +namespace { + +using namespace Toast; + +} // namespace + +base::weak_ptr Show::showToast(Config &&config) { + if (const auto strong = _lastToast.get()) { + strong->hideAnimated(); + } + _lastToast = valid() + ? Toast::Show(toastParent(), std::move(config)) + : base::weak_ptr(); + return _lastToast; +} + +base::weak_ptr Show::showToast( + TextWithEntities &&text, + crl::time duration) { + return showToast({ .text = std::move(text), .duration = duration }); +} + +base::weak_ptr Show::showToast( + const QString &text, + crl::time duration) { + return showToast({ + .text = TextWithEntities{ text }, + .duration = duration, + }); +} + +} // namespace Ui diff --git a/ui/layers/show.h b/ui/layers/show.h index ba8e636..c0719b0 100644 --- a/ui/layers/show.h +++ b/ui/layers/show.h @@ -6,12 +6,22 @@ // #pragma once +#include "base/weak_ptr.h" #include "ui/layers/layer_widget.h" +struct TextWithEntities; + +namespace Ui::Toast { +struct Config; +class Instance; +} // namespace Ui::Toast + namespace Ui { class BoxContent; +inline constexpr auto kZOrderBasic = 0; + class Show { public: virtual ~Show() = 0; @@ -22,6 +32,18 @@ public: [[nodiscard]] virtual not_null toastParent() const = 0; [[nodiscard]] virtual bool valid() const = 0; virtual operator bool() const = 0; + + base::weak_ptr showToast(Toast::Config &&config); + base::weak_ptr showToast( + TextWithEntities &&text, + crl::time duration = 0); + base::weak_ptr showToast( + const QString &text, + crl::time duration = 0); + +private: + base::weak_ptr _lastToast; + }; inline Show::~Show() = default; diff --git a/ui/toast/toast.cpp b/ui/toast/toast.cpp index 5933d0a..9884a60 100644 --- a/ui/toast/toast.cpp +++ b/ui/toast/toast.cpp @@ -23,7 +23,8 @@ Instance::Instance( not_null widgetParent, const Private &) : _st(config.st) -, _hideAt(crl::now() + config.durationMs) +, _hideAt(crl::now() + + (config.duration ? config.duration : kDefaultDuration)) , _sliding(config.slideSide != RectPart::None) , _widget(std::make_unique(widgetParent, config)) { _shownAnimation.start( diff --git a/ui/toast/toast.h b/ui/toast/toast.h index 9c2f71f..b34f0eb 100644 --- a/ui/toast/toast.h +++ b/ui/toast/toast.h @@ -17,6 +17,10 @@ namespace style { struct Toast; } // namespace style +namespace st { +extern const style::Toast &defaultMultilineToast; +} // namespace st + namespace Ui { namespace Toast { @@ -30,10 +34,10 @@ using ClickHandlerFilter = Fn; inline constexpr auto kDefaultDuration = crl::time(1500); struct Config { TextWithEntities text; - not_null st; - crl::time durationMs = kDefaultDuration; + not_null st = &st::defaultMultilineToast; + crl::time duration = kDefaultDuration; int maxLines = 16; - bool multiline = false; + bool multiline = true; bool dark = false; RectPart slideSide = RectPart::None; ClickHandlerFilter filter; diff --git a/ui/toasts/common_toasts.cpp b/ui/toasts/common_toasts.cpp deleted file mode 100644 index cc25a2f..0000000 --- a/ui/toasts/common_toasts.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* -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/toasts/common_toasts.h" - -#include "ui/toast/toast.h" -#include "styles/style_widgets.h" - -namespace Ui { - -base::weak_ptr ShowMultilineToast( - MultilineToastArgs &&args) { - auto config = Ui::Toast::Config{ - .text = std::move(args.text), - .st = &st::defaultMultilineToast, - .durationMs = (args.duration - ? args.duration - : Ui::Toast::kDefaultDuration), - .multiline = true, - .filter = std::move(args.filter), - }; - return args.parentOverride - ? Ui::Toast::Show(args.parentOverride, std::move(config)) - : Ui::Toast::Show(std::move(config)); -} - -} // namespace Ui diff --git a/ui/toasts/common_toasts.h b/ui/toasts/common_toasts.h deleted file mode 100644 index 1fe074d..0000000 --- a/ui/toasts/common_toasts.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -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 "ui/text/text_entity.h" -#include "base/weak_ptr.h" - -class ClickHandler; -using ClickHandlerPtr = std::shared_ptr; -using ClickHandlerFilter = Fn; - -namespace Ui { -namespace Toast { -class Instance; -} // namespace Toast - -struct MultilineToastArgs { - QWidget *parentOverride = nullptr; - TextWithEntities text; - crl::time duration = 0; - ClickHandlerFilter filter; -}; - -base::weak_ptr ShowMultilineToast( - MultilineToastArgs &&args); - -} // namespace Ui diff --git a/ui/widgets/separate_panel.cpp b/ui/widgets/separate_panel.cpp index c80c51d..621d994 100644 --- a/ui/widgets/separate_panel.cpp +++ b/ui/widgets/separate_panel.cpp @@ -16,7 +16,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/menu/menu_add_action_callback_factory.h" #include "ui/wrap/padding_wrap.h" #include "ui/wrap/fade_wrap.h" -#include "ui/toasts/common_toasts.h" #include "ui/platform/ui_platform_utility.h" #include "ui/layers/layer_widget.h" #include "ui/layers/show.h" @@ -410,15 +409,25 @@ void SeparatePanel::showBox( } } -std::shared_ptr SeparatePanel::uiShow() { - return std::make_shared(this); +base::weak_ptr SeparatePanel::showToast( + Toast::Config &&config) { + return PanelShow(this).showToast(std::move(config)); } -void SeparatePanel::showToast(const TextWithEntities &text) { - Ui::ShowMultilineToast({ - .parentOverride = this, - .text = text, - }); +base::weak_ptr SeparatePanel::showToast( + TextWithEntities &&text, + crl::time duration) { + return PanelShow(this).showToast(std::move(text), duration); +} + +base::weak_ptr SeparatePanel::showToast( + const QString &text, + crl::time duration) { + return PanelShow(this).showToast(text, duration); +} + +std::shared_ptr SeparatePanel::uiShow() { + return std::make_shared(this); } void SeparatePanel::ensureLayerCreated() { diff --git a/ui/widgets/separate_panel.h b/ui/widgets/separate_panel.h index f30077c..13745ad 100644 --- a/ui/widgets/separate_panel.h +++ b/ui/widgets/separate_panel.h @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "base/weak_ptr.h" #include "ui/rp_widget.h" #include "ui/effects/animations.h" #include "ui/layers/layer_widget.h" @@ -18,6 +19,11 @@ namespace Ui::Menu { struct MenuCallback; } // namespace Ui::Menu +namespace Ui::Toast { +struct Config; +class Instance; +} // namespace Ui::Toast + namespace Ui { class Show; @@ -32,6 +38,7 @@ class FadeWrapScaled; struct SeparatePanelArgs { QWidget *parent = nullptr; bool onAllSpaces = false; + Fn animationsPaused; }; class SeparatePanel final : public RpWidget { @@ -52,15 +59,25 @@ public: object_ptr box, LayerOptions options, anim::type animated); - void showToast(const TextWithEntities &text); void destroyLayer(); + [[nodiscard]] bool animationsPaused(int zorder) const; + [[nodiscard]] rpl::producer<> backRequests() const; [[nodiscard]] rpl::producer<> closeRequests() const; [[nodiscard]] rpl::producer<> closeEvents() const; void setBackAllowed(bool allowed); void setMenuAllowed(Fn fill); + + base::weak_ptr showToast(Toast::Config &&config); + base::weak_ptr showToast( + TextWithEntities &&text, + crl::time duration = 0); + base::weak_ptr showToast( + const QString &text, + crl::time duration = 0); + [[nodiscard]] std::shared_ptr uiShow(); protected: @@ -127,6 +144,8 @@ private: QPixmap _animationCache; QPixmap _borderParts; + Fn _animationsPaused; + }; } // namespace Ui