From d0e854e9d8197c6f5cc548f8e61100cc7177fcf6 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 6 Apr 2018 20:23:09 +0400 Subject: [PATCH] Allow showing boxes in passport panel. --- Telegram/Resources/langs/lang.strings | 4 +- Telegram/SourceFiles/boxes/abstract_box.cpp | 4 +- Telegram/SourceFiles/boxes/abstract_box.h | 16 +--- .../SourceFiles/boxes/edit_caption_box.cpp | 2 +- Telegram/SourceFiles/boxes/edit_caption_box.h | 4 + .../boxes/edit_participant_box.cpp | 4 - .../SourceFiles/boxes/mute_settings_box.cpp | 1 - .../boxes/peers/edit_peer_info_box.cpp | 1 - .../boxes/peers/manage_peer_box.cpp | 19 ++-- Telegram/SourceFiles/boxes/send_files_box.cpp | 4 +- Telegram/SourceFiles/boxes/send_files_box.h | 4 + .../SourceFiles/history/history_widget.cpp | 24 +++-- Telegram/SourceFiles/history/history_widget.h | 7 +- Telegram/SourceFiles/mainwidget.cpp | 28 +----- Telegram/SourceFiles/mainwindow.cpp | 89 ++++++++----------- Telegram/SourceFiles/mainwindow.h | 5 +- .../media/view/media_clip_controller.cpp | 45 ++++++---- .../media/view/media_clip_controller.h | 4 +- .../passport/passport_form_controller.cpp | 4 +- .../passport/passport_form_view_controller.h | 9 ++ .../SourceFiles/passport/passport_panel.cpp | 78 ++++++++++++---- .../SourceFiles/passport/passport_panel.h | 10 +++ .../passport/passport_panel_controller.cpp | 5 +- .../passport/passport_panel_controller.h | 2 + .../SourceFiles/ui/effects/fade_animation.cpp | 15 +--- Telegram/SourceFiles/ui/special_buttons.cpp | 2 +- Telegram/SourceFiles/ui/twidget.cpp | 12 +-- Telegram/SourceFiles/ui/twidget.h | 8 +- Telegram/SourceFiles/ui/widgets/shadow.cpp | 2 - Telegram/SourceFiles/ui/wrap/fade_wrap.cpp | 33 ++++++- Telegram/SourceFiles/window/layer_widget.cpp | 53 +++++++---- Telegram/SourceFiles/window/layer_widget.h | 31 ++++--- 32 files changed, 293 insertions(+), 236 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index bc686b183..4c1e4db8c 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -1525,7 +1525,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_passport_policy" = "{bot} privacy policy"; "lng_passport_authorize" = "Authorize"; "lng_passport_form_error" = "Could not get authorization form."; -"lng_passport_save_value" = "Done"; +"lng_passport_save_value" = "Save"; +"lng_passport_saving" = "Saving..."; +"lng_passport_uploading" = "Uploading..."; "lng_passport_upload_header" = "Scans"; "lng_passport_scan_index" = "Scan {index}"; "lng_passport_upload_scans" = "Upload scans"; diff --git a/Telegram/SourceFiles/boxes/abstract_box.cpp b/Telegram/SourceFiles/boxes/abstract_box.cpp index 071a7220d..a475ffeae 100644 --- a/Telegram/SourceFiles/boxes/abstract_box.cpp +++ b/Telegram/SourceFiles/boxes/abstract_box.cpp @@ -227,8 +227,8 @@ void BoxContent::paintEvent(QPaintEvent *e) { } } -AbstractBox::AbstractBox(QWidget *parent, Window::Controller *controller, object_ptr content) : LayerWidget(parent) -, _controller(controller) +AbstractBox::AbstractBox(QWidget *parent, object_ptr content) +: LayerWidget(parent) , _content(std::move(content)) { subscribe(Lang::Current().updated(), [this] { refreshLang(); }); _content->setParent(this); diff --git a/Telegram/SourceFiles/boxes/abstract_box.h b/Telegram/SourceFiles/boxes/abstract_box.h index 4449fddf2..8983812f1 100644 --- a/Telegram/SourceFiles/boxes/abstract_box.h +++ b/Telegram/SourceFiles/boxes/abstract_box.h @@ -23,14 +23,8 @@ class FlatLabel; class FadeShadow; } // namespace Ui -namespace Window { -class Controller; -} // namespace Window - class BoxContentDelegate { public: - virtual Window::Controller *controller() const = 0; - virtual void setLayerType(bool layerType) = 0; virtual void setTitle(base::lambda titleFactory) = 0; virtual void setAdditionalTitle(base::lambda additionalFactory) = 0; @@ -108,10 +102,6 @@ public: finishPrepare(); } - Window::Controller *controller() { - return getDelegate()->controller(); - } - public slots: void onScrollToY(int top, int bottom = -1); @@ -215,11 +205,8 @@ class AbstractBox , public BoxContentDelegate , protected base::Subscriber { public: - AbstractBox(QWidget *parent, Window::Controller *controller, object_ptr content); + AbstractBox(QWidget *parent, object_ptr content); - Window::Controller *controller() const override { - return _controller; - } void parentResized() override; void setLayerType(bool layerType) override; @@ -275,7 +262,6 @@ private: int countRealHeight() const; void updateSize(); - Window::Controller *_controller = nullptr; int _fullHeight = 0; bool _noContentMargin = false; diff --git a/Telegram/SourceFiles/boxes/edit_caption_box.cpp b/Telegram/SourceFiles/boxes/edit_caption_box.cpp index 3c8c2483a..058feebed 100644 --- a/Telegram/SourceFiles/boxes/edit_caption_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_caption_box.cpp @@ -241,7 +241,7 @@ void EditCaptionBox::paintEvent(QPaintEvent *e) { } if (_gifPreview && _gifPreview->started()) { auto s = QSize(_thumbw, _thumbh); - auto paused = controller()->isGifPausedAtLeastFor(Window::GifPauseReason::Layer); + auto paused = _controller->isGifPausedAtLeastFor(Window::GifPauseReason::Layer); auto frame = _gifPreview->current(s.width(), s.height(), s.width(), s.height(), ImageRoundRadius::None, RectPart::None, paused ? 0 : getms()); p.drawPixmap(_thumbx, st::boxPhotoPadding.top(), frame); } else { diff --git a/Telegram/SourceFiles/boxes/edit_caption_box.h b/Telegram/SourceFiles/boxes/edit_caption_box.h index 48fe7d046..38d6626ff 100644 --- a/Telegram/SourceFiles/boxes/edit_caption_box.h +++ b/Telegram/SourceFiles/boxes/edit_caption_box.h @@ -21,6 +21,10 @@ namespace Ui { class InputField; } // namespace Ui +namespace Window { +class Controller; +} // namespace Window + class EditCaptionBox : public BoxContent, public RPCSender { public: EditCaptionBox( diff --git a/Telegram/SourceFiles/boxes/edit_participant_box.cpp b/Telegram/SourceFiles/boxes/edit_participant_box.cpp index 4c4745c45..4cc3640e1 100644 --- a/Telegram/SourceFiles/boxes/edit_participant_box.cpp +++ b/Telegram/SourceFiles/boxes/edit_participant_box.cpp @@ -66,7 +66,6 @@ class EditParticipantBox::Inner : public TWidget { public: Inner( QWidget *parent, - not_null controller, not_null channel, not_null user, bool hasAdminRights); @@ -101,7 +100,6 @@ private: EditParticipantBox::Inner::Inner( QWidget *parent, - not_null controller, not_null channel, not_null user, bool hasAdminRights) @@ -110,7 +108,6 @@ EditParticipantBox::Inner::Inner( , _user(user) , _userPhoto( this, - controller, _user, Ui::UserpicButton::Role::Custom, st::rightsPhotoButton) @@ -184,7 +181,6 @@ EditParticipantBox::EditParticipantBox(QWidget*, not_null channel, void EditParticipantBox::prepare() { _inner = setInnerWidget(object_ptr( this, - controller(), _channel, _user, hasAdminRights())); diff --git a/Telegram/SourceFiles/boxes/mute_settings_box.cpp b/Telegram/SourceFiles/boxes/mute_settings_box.cpp index 52bd0368c..e7d078ed6 100644 --- a/Telegram/SourceFiles/boxes/mute_settings_box.cpp +++ b/Telegram/SourceFiles/boxes/mute_settings_box.cpp @@ -32,7 +32,6 @@ void MuteSettingsBox::prepare() { const auto icon = object_ptr( this, - controller(), _peer, Ui::UserpicButton::Role::Custom, st::mutePhotoButton); diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp index 1625aff65..a1c6c02e8 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp @@ -277,7 +277,6 @@ object_ptr Controller::createPhotoEdit() { _wrap, object_ptr( _wrap, - _box->controller(), _peer, Ui::UserpicButton::Role::ChangePhoto, st::defaultUserpicButton), diff --git a/Telegram/SourceFiles/boxes/peers/manage_peer_box.cpp b/Telegram/SourceFiles/boxes/peers/manage_peer_box.cpp index 10ca6eb93..12abb1dc2 100644 --- a/Telegram/SourceFiles/boxes/peers/manage_peer_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/manage_peer_box.cpp @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/labels.h" #include "history/admin_log/history_admin_log_section.h" #include "window/window_controller.h" +#include "mainwindow.h" #include "profile/profile_channel_controllers.h" #include "info/profile/info_profile_button.h" #include "info/profile/info_profile_icon.h" @@ -88,9 +89,9 @@ bool HasRecentActions(not_null channel) { } void ShowRecentActions( - not_null controller, + not_null navigation, not_null channel) { - controller->showSection(AdminLog::SectionMemento(channel)); + navigation->showSection(AdminLog::SectionMemento(channel)); } bool HasEditInfoBox(not_null channel) { @@ -104,7 +105,7 @@ bool HasEditInfoBox(not_null channel) { } void FillManageBox( - not_null controller, + not_null navigation, not_null channel, not_null content) { using Profile::ParticipantsBoxController; @@ -123,7 +124,7 @@ void FillManageBox( AddButton( content, Lang::Viewer(lng_manage_peer_recent_actions), - [=] { ShowRecentActions(controller, channel); }, + [=] { ShowRecentActions(navigation, channel); }, st::infoIconRecentActions); } if (channel->canViewMembers()) { @@ -134,7 +135,7 @@ void FillManageBox( | ToPositiveNumberString(), [=] { ParticipantsBoxController::Start( - controller, + navigation, channel, ParticipantsBoxController::Role::Members); }, @@ -148,7 +149,7 @@ void FillManageBox( | ToPositiveNumberString(), [=] { ParticipantsBoxController::Start( - controller, + navigation, channel, ParticipantsBoxController::Role::Admins); }, @@ -163,7 +164,7 @@ void FillManageBox( | ToPositiveNumberString(), [=] { ParticipantsBoxController::Start( - controller, + navigation, channel, ParticipantsBoxController::Role::Restricted); }, @@ -176,7 +177,7 @@ void FillManageBox( | ToPositiveNumberString(), [=] { ParticipantsBoxController::Start( - controller, + navigation, channel, ParticipantsBoxController::Role::Kicked); }, @@ -218,7 +219,7 @@ void ManagePeerBox::prepare() { void ManagePeerBox::setupContent() { auto content = Ui::CreateChild(this); - FillManageBox(controller(), _channel, content); + FillManageBox(App::wnd()->controller(), _channel, content); widthValue( ) | rpl::start_with_next([=](int width) { content->resizeToWidth(width); diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp index 02cd2382a..95220f9b3 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.cpp +++ b/Telegram/SourceFiles/boxes/send_files_box.cpp @@ -1361,7 +1361,7 @@ void SendFilesBox::prepareSingleFilePreview() { Expects(_list.files.size() == 1); const auto &file = _list.files[0]; - const auto media = SingleMediaPreview::Create(this, controller(), file); + const auto media = SingleMediaPreview::Create(this, _controller, file); if (media) { if (!media->canSendAsPhoto()) { _compressConfirm = CompressConfirm::None; @@ -1424,8 +1424,6 @@ void SendFilesBox::setupShadows( } void SendFilesBox::prepare() { - Expects(controller() != nullptr); - _send = addButton(langFactory(lng_send_button), [this] { send(); }); addButton(langFactory(lng_cancel), [this] { closeBox(); }); setupCaption(); diff --git a/Telegram/SourceFiles/boxes/send_files_box.h b/Telegram/SourceFiles/boxes/send_files_box.h index 51781169e..e9ff281ce 100644 --- a/Telegram/SourceFiles/boxes/send_files_box.h +++ b/Telegram/SourceFiles/boxes/send_files_box.h @@ -26,6 +26,10 @@ class InputField; struct GroupMediaLayout; } // namespace Ui +namespace Window { +class Controller; +} // namespace Window + enum class SendFilesWay { Album, Photos, diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 0679345ff..0e18a01fb 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -4703,15 +4703,20 @@ void HistoryWidget::handleHistoryChange(not_null history) { } } -void HistoryWidget::grapWithoutTopBarShadow() { - grabStart(); - _topShadow->hide(); -} - -void HistoryWidget::grabFinish() { +QPixmap HistoryWidget::grabForShowAnimation( + const Window::SectionSlideParams ¶ms) { + if (params.withTopBarShadow) { + _topShadow->hide(); + } + _inGrab = true; + updateControlsGeometry(); + auto result = Ui::GrabWidget(this); _inGrab = false; updateControlsGeometry(); - _topShadow->show(); + if (params.withTopBarShadow) { + _topShadow->show(); + } + return result; } bool HistoryWidget::skipItemRepaint() { @@ -5894,7 +5899,10 @@ void HistoryWidget::editMessage(not_null item) { } if (!_editMsgId) { if (_replyToId || !_field->empty()) { - _history->setLocalDraft(std::make_unique(_field, _replyToId, _previewCancelled)); + _history->setLocalDraft(std::make_unique( + _field, + _replyToId, + _previewCancelled)); } else { _history->clearLocalDraft(); } diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index c67d1aafb..475bcf287 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -327,12 +327,7 @@ public: bool contentOverlapped(const QRect &globalRect); - void grabStart() override { - _inGrab = true; - updateControlsGeometry(); - } - void grapWithoutTopBarShadow(); - void grabFinish() override; + QPixmap grabForShowAnimation(const Window::SectionSlideParams ¶ms); void forwardSelected(); void confirmDeleteSelected(); diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index 9ad18e606..4154fa961 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -2285,33 +2285,7 @@ Window::SectionSlideParams MainWidget::prepareShowAnimation( } else if (_mainSection) { result.oldContentCache = _mainSection->grabForShowAnimation(result); } else { - if (result.withTopBarShadow) { - _history->grapWithoutTopBarShadow(); - } else { - _history->grabStart(); - } - if (Adaptive::OneColumn()) { - result.oldContentCache = Ui::GrabWidget(this, QRect( - 0, - sectionTop, - _dialogsWidth, - height() - sectionTop)); - } else { - _sideShadow->hide(); - if (_thirdShadow) { - _thirdShadow->hide(); - } - result.oldContentCache = Ui::GrabWidget(this, QRect( - _dialogsWidth, - sectionTop, - width() - _dialogsWidth, - height() - sectionTop)); - _sideShadow->show(); - if (_thirdShadow) { - _thirdShadow->show(); - } - } - _history->grabFinish(); + result.oldContentCache = _history->grabForShowAnimation(result); } if (playerVolumeVisible) { diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index 1d96b1e2a..3b8fde933 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -301,17 +301,17 @@ void MainWindow::showSpecialLayer( if (layer) { ensureLayerCreated(); - _layerBg->showSpecialLayer(std::move(layer), animated); - } else if (_layerBg) { - _layerBg->hideSpecialLayer(animated); + _layer->showSpecialLayer(std::move(layer), animated); + } else if (_layer) { + _layer->hideSpecialLayer(animated); } } bool MainWindow::showSectionInExistingLayer( not_null memento, const Window::SectionShow ¶ms) { - if (_layerBg) { - return _layerBg->showSectionInternal(memento, params); + if (_layer) { + return _layer->showSectionInternal(memento, params); } return false; } @@ -322,12 +322,16 @@ void MainWindow::showMainMenu() { if (isHidden()) showFromTray(); ensureLayerCreated(); - _layerBg->showMainMenu(anim::type::normal); + _layer->showMainMenu(controller(), anim::type::normal); } void MainWindow::ensureLayerCreated() { - if (!_layerBg) { - _layerBg.create(bodyWidget(), controller()); + if (!_layer) { + _layer.create(bodyWidget()); + _layer->hideFinishEvents( + ) | rpl::start_with_next([=, pointer = _layer.data()] { + layerHidden(pointer); + }, _layer->lifetime()); if (controller()) { controller()->enableGifPauseReason(Window::GifPauseReason::Layer); } @@ -335,8 +339,8 @@ void MainWindow::ensureLayerCreated() { } void MainWindow::destroyLayerDelayed() { - if (_layerBg) { - _layerBg.destroyDelayed(); + if (_layer) { + _layer.destroyDelayed(); if (controller()) { controller()->disableGifPauseReason(Window::GifPauseReason::Layer); } @@ -344,8 +348,8 @@ void MainWindow::destroyLayerDelayed() { } void MainWindow::ui_hideSettingsAndLayer(anim::type animated) { - if (_layerBg) { - _layerBg->hideAll(animated); + if (_layer) { + _layer->hideAll(animated); if (animated == anim::type::instant) { destroyLayerDelayed(); } @@ -366,21 +370,13 @@ void MainWindow::ui_showBox( anim::type animated) { if (box) { ensureLayerCreated(); - if (options & LayerOption::KeepOther) { - if (options & LayerOption::ShowAfterOther) { - _layerBg->prependBox(std::move(box), animated); - } else { - _layerBg->appendBox(std::move(box), animated); - } - } else { - _layerBg->showBox(std::move(box), animated); - } + _layer->showBox(std::move(box), options, animated); } else { - if (_layerBg) { - _layerBg->hideTopLayer(animated); + if (_layer) { + _layer->hideTopLayer(animated); if ((animated == anim::type::instant) - && _layerBg - && !_layerBg->layerShown()) { + && _layer + && !_layer->layerShown()) { destroyLayerDelayed(); } } @@ -389,7 +385,7 @@ void MainWindow::ui_showBox( } bool MainWindow::ui_isLayerShown() { - return _layerBg != nullptr; + return _layer != nullptr; } void MainWindow::ui_showMediaPreview(DocumentData *document) { @@ -476,15 +472,15 @@ void MainWindow::checkHistoryActivation() { bool MainWindow::contentOverlapped(const QRect &globalRect) { if (_main && _main->contentOverlapped(globalRect)) return true; - if (_layerBg && _layerBg->contentOverlapped(globalRect)) return true; + if (_layer && _layer->contentOverlapped(globalRect)) return true; return false; } void MainWindow::setInnerFocus() { if (_testingThemeWarning) { _testingThemeWarning->setFocus(); - } else if (_layerBg && _layerBg->canSetFocus()) { - _layerBg->setInnerFocus(); + } else if (_layer && _layer->canSetFocus()) { + _layer->setInnerFocus(); } else if (_passcode) { _passcode->setInnerFocus(); } else if (_main) { @@ -641,34 +637,25 @@ void MainWindow::noIntro(Intro::Widget *was) { } } -void MainWindow::noLayerStack(Window::LayerStackWidget *was) { - if (was == _layerBg) { - _layerBg = nullptr; - if (controller()) { - controller()->disableGifPauseReason( - Window::GifPauseReason::Layer); - } - } -} - -void MainWindow::layerFinishedHide(Window::LayerStackWidget *was) { - if (was == _layerBg) { - auto resetFocus = Ui::InFocusChain(was); - if (resetFocus) setFocus(); - destroyLayerDelayed(); - if (resetFocus) setInnerFocus(); - InvokeQueued(this, [this] { - checkHistoryActivation(); - }); +void MainWindow::layerHidden(not_null layer) { + if (_layer != layer) { + return; } + auto resetFocus = Ui::InFocusChain(layer); + if (resetFocus) setFocus(); + destroyLayerDelayed(); + if (resetFocus) setInnerFocus(); + InvokeQueued(this, [this] { + checkHistoryActivation(); + }); } bool MainWindow::takeThirdSectionFromLayer() { - return _layerBg ? _layerBg->takeToThirdSection() : false; + return _layer ? _layer->takeToThirdSection() : false; } void MainWindow::fixOrder() { - if (_layerBg) _layerBg->raise(); + if (_layer) _layer->raise(); if (_mediaPreview) _mediaPreview->raise(); if (_testingThemeWarning) _testingThemeWarning->raise(); } @@ -759,7 +746,7 @@ void MainWindow::updateControlsGeometry() { if (_passcode) _passcode->setGeometry(body); if (_main) _main->setGeometry(body); if (_intro) _intro->setGeometry(body); - if (_layerBg) _layerBg->setGeometry(body); + if (_layer) _layer->setGeometry(body); if (_mediaPreview) _mediaPreview->setGeometry(body); if (_testingThemeWarning) _testingThemeWarning->setGeometry(body); diff --git a/Telegram/SourceFiles/mainwindow.h b/Telegram/SourceFiles/mainwindow.h index 880c237ff..5f46065f5 100644 --- a/Telegram/SourceFiles/mainwindow.h +++ b/Telegram/SourceFiles/mainwindow.h @@ -70,8 +70,7 @@ public: void activate(); void noIntro(Intro::Widget *was); - void noLayerStack(Window::LayerStackWidget *was); - void layerFinishedHide(Window::LayerStackWidget *was); + void layerHidden(not_null layer); bool takeThirdSectionFromLayer(); void checkHistoryActivation(); @@ -177,7 +176,7 @@ private: object_ptr _passcode = { nullptr }; object_ptr _intro = { nullptr }; object_ptr _main = { nullptr }; - object_ptr _layerBg = { nullptr }; + object_ptr _layer = { nullptr }; object_ptr _mediaPreview = { nullptr }; object_ptr _testingThemeWarning = { nullptr }; diff --git a/Telegram/SourceFiles/media/view/media_clip_controller.cpp b/Telegram/SourceFiles/media/view/media_clip_controller.cpp index a1c1a02aa..b1d0cace1 100644 --- a/Telegram/SourceFiles/media/view/media_clip_controller.cpp +++ b/Telegram/SourceFiles/media/view/media_clip_controller.cpp @@ -75,6 +75,23 @@ void Controller::handleSeekFinished(float64 progress) { refreshTimeTexts(); } +template +void Controller::startFading(Callback start) { + if (!_fadeAnimation->animating()) { + showChildren(); + _playbackSlider->hide(); + _childrenHidden = false; + } + start(); + if (_fadeAnimation->animating()) { + hideChildren(); + _childrenHidden = true; + } else { + fadeFinished(); + } + _playbackSlider->show(); +} + void Controller::showAnimated() { startFading([this]() { _fadeAnimation->fadeIn(st::mediaviewShowDuration); @@ -87,14 +104,8 @@ void Controller::hideAnimated() { }); } -template -void Controller::startFading(Callback start) { - start(); - _playbackSlider->show(); -} - void Controller::fadeFinished() { - fadeUpdated(1.); + fadeUpdated(_fadeAnimation->visible() ? 1. : 0.); } void Controller::fadeUpdated(float64 opacity) { @@ -160,7 +171,9 @@ void Controller::refreshTimeTexts() { _toPlayLeft->setText(timeLeft, &leftChanged); if (alreadyChanged || leftChanged) { resizeEvent(nullptr); - _fadeAnimation->refreshCache(); + startFading([this]() { + _fadeAnimation->refreshCache(); + }); } } @@ -173,16 +186,6 @@ void Controller::setInFullScreen(bool inFullScreen) { connect(_fullScreenToggle, SIGNAL(clicked()), this, handler); } -void Controller::grabStart() { - showChildren(); - _playbackSlider->hide(); -} - -void Controller::grabFinish() { - hideChildren(); - _playbackSlider->show(); -} - void Controller::resizeEvent(QResizeEvent *e) { int playTop = (height() - _playPauseResume->height()) / 2; _playPauseResume->moveToLeft(st::mediaviewPlayPauseLeft, playTop); @@ -206,7 +209,11 @@ void Controller::paintEvent(QPaintEvent *e) { if (_fadeAnimation->paint(p)) { return; } - + if (_childrenHidden) { + showChildren(); + _playbackSlider->setFadeOpacity(1.); + _childrenHidden = false; + } App::roundRect(p, rect(), st::mediaviewSaveMsgBg, MediaviewSaveCorners); } diff --git a/Telegram/SourceFiles/media/view/media_clip_controller.h b/Telegram/SourceFiles/media/view/media_clip_controller.h index 3b2c063b3..7bc155f22 100644 --- a/Telegram/SourceFiles/media/view/media_clip_controller.h +++ b/Telegram/SourceFiles/media/view/media_clip_controller.h @@ -36,9 +36,6 @@ public: void updatePlayback(const Player::TrackState &state); void setInFullScreen(bool inFullScreen); - void grabStart() override; - void grabFinish() override; - ~Controller(); signals: @@ -69,6 +66,7 @@ private: void refreshTimeTexts(); bool _showPause = false; + bool _childrenHidden = false; QString _timeAlready, _timeLeft; TimeMs _seekPositionMs = -1; TimeMs _lastDurationMs = 0; diff --git a/Telegram/SourceFiles/passport/passport_form_controller.cpp b/Telegram/SourceFiles/passport/passport_form_controller.cpp index c2cc6fab8..c76c0410b 100644 --- a/Telegram/SourceFiles/passport/passport_form_controller.cpp +++ b/Telegram/SourceFiles/passport/passport_form_controller.cpp @@ -716,9 +716,9 @@ void FormController::sendSaveRequest( data.vfiles.v, base::take(value->filesInEdit)); - Ui::show(Box("Saved"), LayerOption::KeepOther); + _view->show(Box("Saved")); }).fail([=](const RPCError &error) { - Ui::show(Box("Error saving value")); + _view->show(Box("Error saving value:\n" + error.type())); }).send(); } diff --git a/Telegram/SourceFiles/passport/passport_form_view_controller.h b/Telegram/SourceFiles/passport/passport_form_view_controller.h index 172bd93cd..7b4a8adff 100644 --- a/Telegram/SourceFiles/passport/passport_form_view_controller.h +++ b/Telegram/SourceFiles/passport/passport_form_view_controller.h @@ -35,9 +35,18 @@ public: virtual void showPasswordUnconfirmed() = 0; virtual void editScope(int index) = 0; + virtual void showBox(object_ptr box) = 0; + virtual ~ViewController() { } + template + QPointer show(object_ptr content) { + auto result = QPointer(content.data()); + showBox(std::move(content)); + return result; + } + }; } // namespace Passport diff --git a/Telegram/SourceFiles/passport/passport_panel.cpp b/Telegram/SourceFiles/passport/passport_panel.cpp index c63529693..bf919c549 100644 --- a/Telegram/SourceFiles/passport/passport_panel.cpp +++ b/Telegram/SourceFiles/passport/passport_panel.cpp @@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/labels.h" #include "ui/wrap/fade_wrap.h" #include "lang/lang_keys.h" +#include "window/layer_widget.h" #include "messenger.h" #include "styles/style_passport.h" #include "styles/style_widgets.h" @@ -32,7 +33,8 @@ Panel::Panel(not_null controller) lang(lng_passport_title), Ui::FlatLabel::InitType::Simple, st::passportPanelTitle) -, _back(this, object_ptr(this, st::passportPanelBack)) { +, _back(this, object_ptr(this, st::passportPanelBack)) +, _body(this) { setMouseTracking(true); setWindowIcon(Window::CreateIcon()); initControls(); @@ -209,42 +211,78 @@ void Panel::hideAndDestroy() { } void Panel::showAskPassword() { - showInner(base::make_unique_q(this, _controller)); + showInner(base::make_unique_q(_body, _controller)); + setBackAllowed(false); } void Panel::showNoPassword() { - showInner(base::make_unique_q(this, _controller)); + showInner(base::make_unique_q(_body, _controller)); + setBackAllowed(false); } void Panel::showPasswordUnconfirmed() { - showInner(base::make_unique_q(this, _controller)); + showInner( + base::make_unique_q(_body, _controller)); + setBackAllowed(false); } void Panel::showForm() { - showInner(base::make_unique_q(this, _controller)); + showInner(base::make_unique_q(_body, _controller)); + setBackAllowed(false); } void Panel::showEditValue(object_ptr from) { showInner(base::unique_qptr(from.data())); } +void Panel::showBox(object_ptr box) { + ensureLayerCreated(); + _layer->showBox( + std::move(box), + LayerOption::KeepOther, + anim::type::normal); +} + +void Panel::ensureLayerCreated() { + if (_layer) { + return; + } + _layer.create(_body); + _layer->move(0, 0); + _body->sizeValue( + ) | rpl::start_with_next([=](QSize size) { + _layer->resize(size); + }, _layer->lifetime()); + _layer->hideFinishEvents( + ) | rpl::start_with_next([=, pointer = _layer.data()]{ + if (_layer != pointer) { + return; + } + auto saved = std::exchange(_layer, nullptr); + if (Ui::InFocusChain(saved)) { + setFocus(); + } + saved.destroyDelayed(); + }, _layer->lifetime()); +} + void Panel::showInner(base::unique_qptr inner) { _inner = std::move(inner); - _inner->setParent(this); + _inner->setParent(_body); + _inner->move(0, 0); + _body->sizeValue( + ) | rpl::start_with_next([=](QSize size) { + _inner->resize(size); + }, _inner->lifetime()); _inner->show(); - sizeValue( - ) | rpl::start_with_next([=] { - const auto top = _padding.top() + st::passportPanelTitleHeight; - _inner->setGeometry( - _padding.left(), - top, - width() - _padding.left() - _padding.right(), - height() - top - _padding.bottom()); - }, _inner->lifetime()); - showAndActivate(); - if (!_inner->isHidden()) { +} + +void Panel::focusInEvent(QFocusEvent *e) { + if (_layer) { + _layer->setInnerFocus(); + } else if (!_inner->isHidden()) { _inner->setFocus(); } } @@ -271,6 +309,12 @@ void Panel::resizeEvent(QResizeEvent *e) { } void Panel::updateControlsGeometry() { + const auto top = _padding.top() + st::passportPanelTitleHeight; + _body->setGeometry( + _padding.left(), + top, + width() - _padding.left() - _padding.right(), + height() - top - _padding.bottom()); } void Panel::paintEvent(QPaintEvent *e) { diff --git a/Telegram/SourceFiles/passport/passport_panel.h b/Telegram/SourceFiles/passport/passport_panel.h index 8e1ae1121..0f10b02bf 100644 --- a/Telegram/SourceFiles/passport/passport_panel.h +++ b/Telegram/SourceFiles/passport/passport_panel.h @@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #pragma once #include "ui/rp_widget.h" +#include "boxes/abstract_box.h" namespace Ui { class IconButton; @@ -16,6 +17,10 @@ template class FadeWrapScaled; } // namespace Ui +namespace Window { +class LayerStackWidget; +} // namespace Window + namespace Passport { class PanelController; @@ -35,6 +40,7 @@ public: void showPasswordUnconfirmed(); void showForm(); void showEditValue(object_ptr form); + void showBox(object_ptr box); rpl::producer<> backRequests() const; void setBackAllowed(bool allowed); @@ -43,6 +49,7 @@ protected: void paintEvent(QPaintEvent *e) override; void closeEvent(QCloseEvent *e) override; void resizeEvent(QResizeEvent *e) override; + void focusInEvent(QFocusEvent *e) override; void mousePressEvent(QMouseEvent *e) override; void mouseReleaseEvent(QMouseEvent *e) override; void mouseMoveEvent(QMouseEvent *e) override; @@ -59,6 +66,7 @@ private: void createBorderImage(); void opacityCallback(); void showInner(base::unique_qptr inner); + void ensureLayerCreated(); void updateTitlePosition(); void paintShadowBorder(Painter &p) const; @@ -72,7 +80,9 @@ private: object_ptr _close; object_ptr _title; object_ptr> _back; + object_ptr _body; base::unique_qptr _inner; + object_ptr _layer = { nullptr }; bool _useTransparency = true; style::margins _padding; diff --git a/Telegram/SourceFiles/passport/passport_panel_controller.cpp b/Telegram/SourceFiles/passport/passport_panel_controller.cpp index 3145cd7d6..c6ab3a093 100644 --- a/Telegram/SourceFiles/passport/passport_panel_controller.cpp +++ b/Telegram/SourceFiles/passport/passport_panel_controller.cpp @@ -450,7 +450,6 @@ void PanelController::editScope(int index) { _panel->backRequests( ) | rpl::start_with_next([=] { cancelValueEdit(index); - _panel->setBackAllowed(false); _panel->showForm(); }, content->lifetime()); _panel->showEditValue(std::move(content)); @@ -497,6 +496,10 @@ void PanelController::cancelAuth() { _form->cancel(); } +void PanelController::showBox(object_ptr box) { + _panel->showBox(std::move(box)); +} + rpl::lifetime &PanelController::lifetime() { return _lifetime; } diff --git a/Telegram/SourceFiles/passport/passport_panel_controller.h b/Telegram/SourceFiles/passport/passport_panel_controller.h index 9f9f98471..54c375d1d 100644 --- a/Telegram/SourceFiles/passport/passport_panel_controller.h +++ b/Telegram/SourceFiles/passport/passport_panel_controller.h @@ -72,6 +72,8 @@ public: void editScope(int index) override; void saveScope(ValueMap &&data, ValueMap &&filesData); + void showBox(object_ptr box) override; + void cancelAuth(); rpl::lifetime &lifetime(); diff --git a/Telegram/SourceFiles/ui/effects/fade_animation.cpp b/Telegram/SourceFiles/ui/effects/fade_animation.cpp index 1f72e83b1..f726f060f 100644 --- a/Telegram/SourceFiles/ui/effects/fade_animation.cpp +++ b/Telegram/SourceFiles/ui/effects/fade_animation.cpp @@ -22,6 +22,7 @@ FadeAnimation::FadeAnimation(TWidget *widget, float64 scale) bool FadeAnimation::paint(Painter &p) { if (_cache.isNull()) return false; + const auto cache = _cache; auto opacity = _animation.current(getms(), _visible ? 1. : 0.); p.setOpacity(opacity); if (_scale < 1.) { @@ -45,9 +46,9 @@ bool FadeAnimation::paint(Painter &p) { shownHeight, shownWidth, shownHeight); - p.drawPixmap(targetRect.marginsAdded(margins), _cache); + p.drawPixmap(targetRect.marginsAdded(margins), cache); } else { - p.drawPixmap(0, 0, _cache); + p.drawPixmap(0, 0, cache); } return true; } @@ -94,10 +95,7 @@ void FadeAnimation::setUpdatedCallback(UpdatedCallback &&callback) { } void FadeAnimation::show() { - if (!_visible) { - _visible = true; - _widget->showChildren(); - } + _visible = true; stopAnimation(); } @@ -110,9 +108,6 @@ void FadeAnimation::stopAnimation() { _animation.finish(); if (!_cache.isNull()) { _cache = QPixmap(); - if (_visible) { - _widget->showChildren(); - } if (_finishedCallback) { _finishedCallback(); } @@ -138,10 +133,8 @@ void FadeAnimation::fadeOut(int duration) { void FadeAnimation::startAnimation(int duration) { if (_cache.isNull()) { - _widget->showChildren(); _cache = grabContent(); Assert(!_cache.isNull()); - _widget->hideChildren(); } auto from = _visible ? 0. : 1.; auto to = _visible ? 1. : 0.; diff --git a/Telegram/SourceFiles/ui/special_buttons.cpp b/Telegram/SourceFiles/ui/special_buttons.cpp index 966244264..7b2c754f6 100644 --- a/Telegram/SourceFiles/ui/special_buttons.cpp +++ b/Telegram/SourceFiles/ui/special_buttons.cpp @@ -426,7 +426,7 @@ UserpicButton::UserpicButton( , _peer(peer) , _peerForCrop(_peer->id) , _role(role) { - Expects(_role == Role::Custom); + Expects(_role != Role::OpenProfile); _waiting = false; prepare(); diff --git a/Telegram/SourceFiles/ui/twidget.cpp b/Telegram/SourceFiles/ui/twidget.cpp index 1441ea475..0f610cb8a 100644 --- a/Telegram/SourceFiles/ui/twidget.cpp +++ b/Telegram/SourceFiles/ui/twidget.cpp @@ -175,7 +175,7 @@ void SendPendingMoveResizeEvents(not_null target) { SendPendingEventsRecursive(target, !target->isVisible()); } -QPixmap GrabWidget(not_null target, QRect rect, QColor bg) { +QPixmap GrabWidget(not_null target, QRect rect, QColor bg) { SendPendingMoveResizeEvents(target); if (rect.isNull()) { rect = target->rect(); @@ -186,19 +186,15 @@ QPixmap GrabWidget(not_null target, QRect rect, QColor bg) { if (!target->testAttribute(Qt::WA_OpaquePaintEvent)) { result.fill(bg); } - - target->grabStart(); target->render( &result, QPoint(0, 0), rect, QWidget::DrawChildren | QWidget::IgnoreMask); - target->grabFinish(); - return result; } -QImage GrabWidgetToImage(not_null target, QRect rect, QColor bg) { +QImage GrabWidgetToImage(not_null target, QRect rect, QColor bg) { Ui::SendPendingMoveResizeEvents(target); if (rect.isNull()) { rect = target->rect(); @@ -211,15 +207,11 @@ QImage GrabWidgetToImage(not_null target, QRect rect, QColor bg) { if (!target->testAttribute(Qt::WA_OpaquePaintEvent)) { result.fill(bg); } - - target->grabStart(); target->render( &result, QPoint(0, 0), rect, QWidget::DrawChildren | QWidget::IgnoreMask); - target->grabFinish(); - return result; } diff --git a/Telegram/SourceFiles/ui/twidget.h b/Telegram/SourceFiles/ui/twidget.h index 63d9657c9..43f11bda9 100644 --- a/Telegram/SourceFiles/ui/twidget.h +++ b/Telegram/SourceFiles/ui/twidget.h @@ -49,11 +49,11 @@ inline ChildWidget *AttachParentChild( void SendPendingMoveResizeEvents(not_null target); QPixmap GrabWidget( - not_null target, + not_null target, QRect rect = QRect(), QColor bg = QColor(255, 255, 255, 0)); QImage GrabWidgetToImage( - not_null target, + not_null target, QRect rect = QRect(), QColor bg = QColor(255, 255, 255, 0)); @@ -326,10 +326,6 @@ class TWidget : public TWidgetHelper { public: TWidget(QWidget *parent = nullptr) : TWidgetHelper(parent) { } - virtual void grabStart() { - } - virtual void grabFinish() { - } bool inFocusChain() const { return Ui::InFocusChain(this); diff --git a/Telegram/SourceFiles/ui/widgets/shadow.cpp b/Telegram/SourceFiles/ui/widgets/shadow.cpp index a0fd7c79c..f8f1d8f99 100644 --- a/Telegram/SourceFiles/ui/widgets/shadow.cpp +++ b/Telegram/SourceFiles/ui/widgets/shadow.cpp @@ -95,9 +95,7 @@ QPixmap Shadow::grab( { Painter p(&result); Ui::Shadow::paint(p, full.marginsRemoved(extend), full.width(), shadow); - target->grabStart(); target->render(&p, QPoint(extend.left(), extend.top()), rect, QWidget::DrawChildren | QWidget::IgnoreMask); - target->grabFinish(); } return result; } diff --git a/Telegram/SourceFiles/ui/wrap/fade_wrap.cpp b/Telegram/SourceFiles/ui/wrap/fade_wrap.cpp index 75a1e1633..803f411e0 100644 --- a/Telegram/SourceFiles/ui/wrap/fade_wrap.cpp +++ b/Telegram/SourceFiles/ui/wrap/fade_wrap.cpp @@ -34,15 +34,33 @@ FadeWrap *FadeWrap::toggle( auto changed = (shown != _animation.visible()); if (shown) { if (animated == anim::type::normal) { + if (!_animation.animating()) { + wrapped()->show(); + } _animation.fadeIn(_duration); + if (_animation.animating()) { + wrapped()->hide(); + } } else { _animation.show(); + if (!_animation.animating()) { + wrapped()->show(); + } } } else { if (animated == anim::type::normal) { + if (!_animation.animating()) { + wrapped()->show(); + } _animation.fadeOut(_duration); + if (_animation.animating()) { + wrapped()->hide(); + } } else { _animation.hide(); + if (!_animation.animating()) { + wrapped()->show(); + } } } if (changed) { @@ -53,6 +71,7 @@ FadeWrap *FadeWrap::toggle( FadeWrap *FadeWrap::finishAnimating() { _animation.finish(); + wrapped()->show(); return this; } @@ -69,7 +88,19 @@ FadeWrap *FadeWrap::toggleOn( void FadeWrap::paintEvent(QPaintEvent *e) { Painter p(this); - _animation.paint(p); + if (_animation.paint(p)) { + if (!_animation.animating() && _animation.visible()) { + crl::on_main(this, [=] { + if (!_animation.animating() && _animation.visible()) { + wrapped()->show(); + } + }); + } + return; + } + if (!_animation.animating()) { + wrapped()->show(); + } } FadeShadow::FadeShadow(QWidget *parent) diff --git a/Telegram/SourceFiles/window/layer_widget.cpp b/Telegram/SourceFiles/window/layer_widget.cpp index 8d755f5c1..574eb1ad2 100644 --- a/Telegram/SourceFiles/window/layer_widget.cpp +++ b/Telegram/SourceFiles/window/layer_widget.cpp @@ -314,11 +314,8 @@ void LayerStackWidget::BackgroundWidget::animationCallback() { checkIfDone(); } -LayerStackWidget::LayerStackWidget( - QWidget *parent, - Controller *controller) -: TWidget(parent) -, _controller(controller) +LayerStackWidget::LayerStackWidget(QWidget *parent) +: RpWidget(parent) , _background(this) { setGeometry(parentWidget()->rect()); hide(); @@ -326,7 +323,7 @@ LayerStackWidget::LayerStackWidget( } void LayerWidget::setInnerFocus() { - if (!isAncestorOf(App::wnd()->focusWidget())) { + if (!isAncestorOf(window()->focusWidget())) { doSetInnerFocus(); } } @@ -406,13 +403,13 @@ void LayerStackWidget::setCacheImages() { if (auto layer = currentLayer()) { layerCache = Ui::Shadow::grab(layer, st::boxRoundShadow); } - if (isAncestorOf(App::wnd()->focusWidget())) { + if (isAncestorOf(window()->focusWidget())) { setFocus(); } if (_mainMenu) { setAttribute(Qt::WA_OpaquePaintEvent, false); hideChildren(); - bodyCache = Ui::GrabWidget(App::wnd()->bodyWidget()); + bodyCache = Ui::GrabWidget(parentWidget()); showChildren(); mainMenuCache = Ui::Shadow::grab(_mainMenu, st::boxRoundShadow, RectPart::Right); } @@ -541,6 +538,21 @@ void LayerStackWidget::resizeEvent(QResizeEvent *e) { } void LayerStackWidget::showBox( + object_ptr box, + LayerOptions options, + anim::type animated) { + if (options & LayerOption::KeepOther) { + if (options & LayerOption::ShowAfterOther) { + prependBox(std::move(box), animated); + } else { + appendBox(std::move(box), animated); + } + } else { + replaceBox(std::move(box), animated); + } +} + +void LayerStackWidget::replaceBox( object_ptr box, anim::type animated) { auto pointer = pushBox(std::move(box), animated); @@ -585,13 +597,17 @@ void LayerStackWidget::animationDone() { hidden = false; } if (hidden) { - App::wnd()->layerFinishedHide(this); + _hideFinishStream.fire({}); } else { showFinished(); } setAttribute(Qt::WA_OpaquePaintEvent, false); } +rpl::producer<> LayerStackWidget::hideFinishEvents() const { + return _hideFinishStream.events(); +} + void LayerStackWidget::showFinished() { fixOrder(); sendFakeMouseEvent(); @@ -602,8 +618,8 @@ void LayerStackWidget::showFinished() { if (auto layer = currentLayer()) { layer->showFinished(); } - if (auto window = App::wnd()) { - window->setInnerFocus(); + if (canSetFocus()) { + setInnerFocus(); } } @@ -635,9 +651,11 @@ void LayerStackWidget::hideSpecialLayer(anim::type animated) { }, Action::HideSpecialLayer, animated); } -void LayerStackWidget::showMainMenu(anim::type animated) { - startAnimation([this] { - _mainMenu.create(this, _controller); +void LayerStackWidget::showMainMenu( + not_null controller, + anim::type animated) { + startAnimation([&] { + _mainMenu.create(this, controller); _mainMenu->setGeometryToLeft(0, 0, _mainMenu->width(), height()); _mainMenu->setParent(this); }, [this] { @@ -662,7 +680,6 @@ LayerWidget *LayerStackWidget::pushBox( } auto layer = object_ptr( this, - _controller, std::move(box)); _layers.push_back(layer); initChildLayer(layer); @@ -685,9 +702,10 @@ void LayerStackWidget::prependBox( object_ptr box, anim::type animated) { if (_layers.empty()) { - return showBox(std::move(box), animated); + replaceBox(std::move(box), animated); + return; } - auto layer = object_ptr(this, _controller, std::move(box)); + auto layer = object_ptr(this, std::move(box)); layer->hide(); _layers.push_front(layer); initChildLayer(layer); @@ -775,7 +793,6 @@ LayerStackWidget::~LayerStackWidget() { layer->hide(); delete layer; } - if (App::wnd()) App::wnd()->noLayerStack(this); } } // namespace Window diff --git a/Telegram/SourceFiles/window/layer_widget.h b/Telegram/SourceFiles/window/layer_widget.h index cb4c50181..9c7899ddf 100644 --- a/Telegram/SourceFiles/window/layer_widget.h +++ b/Telegram/SourceFiles/window/layer_widget.h @@ -77,29 +77,24 @@ private: }; -class LayerStackWidget : public TWidget { +class LayerStackWidget : public Ui::RpWidget { Q_OBJECT public: - LayerStackWidget(QWidget *parent, Controller *controller); + LayerStackWidget(QWidget *parent); - Controller *controller() const { - return _controller; - } void finishAnimating(); + rpl::producer<> hideFinishEvents() const; void showBox( object_ptr box, + LayerOptions options, anim::type animated); void showSpecialLayer( object_ptr layer, anim::type animated); - void showMainMenu(anim::type animated); - void appendBox( - object_ptr box, - anim::type animated); - void prependBox( - object_ptr box, + void showMainMenu( + not_null controller, anim::type animated); bool takeToThirdSection(); @@ -132,6 +127,16 @@ private slots: void onLayerResized(); private: + void appendBox( + object_ptr box, + anim::type animated); + void prependBox( + object_ptr box, + anim::type animated); + void replaceBox( + object_ptr box, + anim::type animated); + LayerWidget *pushBox( object_ptr box, anim::type animated); @@ -171,8 +176,6 @@ private: return const_cast(this)->currentLayer(); } - Controller *_controller = nullptr; - QList _layers; object_ptr _specialLayer = { nullptr }; @@ -181,6 +184,8 @@ private: class BackgroundWidget; object_ptr _background; + rpl::event_stream<> _hideFinishStream; + }; } // namespace Window