diff --git a/Telegram/SourceFiles/calls/calls_box_controller.cpp b/Telegram/SourceFiles/calls/calls_box_controller.cpp index 5872c5d08..16a029401 100644 --- a/Telegram/SourceFiles/calls/calls_box_controller.cpp +++ b/Telegram/SourceFiles/calls/calls_box_controller.cpp @@ -27,6 +27,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "ui/effects/ripple_animation.h" #include "calls/calls_instance.h" #include "history/history_media_types.h" +#include "mainwidget.h" namespace Calls { namespace { @@ -253,7 +254,9 @@ void BoxController::refreshAbout() { void BoxController::rowClicked(not_null row) { auto itemsRow = static_cast(row.get()); auto itemId = itemsRow->maxItemId(); - Ui::showPeerHistoryAsync(row->peer()->id, itemId); + InvokeQueued(App::main(), [peerId = row->peer()->id, itemId] { + Ui::showPeerHistory(peerId, itemId); + }); } void BoxController::rowActionClicked(not_null row) { diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_section.cpp b/Telegram/SourceFiles/chat_helpers/tabbed_section.cpp index bf76b8810..faf853ef0 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_section.cpp +++ b/Telegram/SourceFiles/chat_helpers/tabbed_section.cpp @@ -107,7 +107,8 @@ QPointer TabbedSection::getSelector() const { return _selector.data(); } bool TabbedSection::showInternal( - not_null memento) { + not_null memento, + const Window::SectionShow ¶ms) { return false; } diff --git a/Telegram/SourceFiles/chat_helpers/tabbed_section.h b/Telegram/SourceFiles/chat_helpers/tabbed_section.h index ef8b9e30e..c4dc48158 100644 --- a/Telegram/SourceFiles/chat_helpers/tabbed_section.h +++ b/Telegram/SourceFiles/chat_helpers/tabbed_section.h @@ -70,7 +70,8 @@ public: QPointer getSelector() const; bool showInternal( - not_null memento) override; + not_null memento, + const Window::SectionShow ¶ms) override; bool forceAnimateBack() const override { return true; } diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index 46952be7c..978d4c196 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -31,6 +31,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "styles/style_history.h" #include "auth_session.h" #include "messenger.h" +#include "mainwindow.h" +#include "window/window_controller.h" namespace { @@ -252,7 +254,9 @@ void PeerClickHandler::onClick(Qt::MouseButton button) const { if (!_peer->asChannel()->isPublic() && !_peer->asChannel()->amIn()) { Ui::show(Box(lang((_peer->isMegagroup()) ? lng_group_not_accessible : lng_channel_not_accessible))); } else { - Ui::showPeerHistory(_peer, ShowAtUnreadMsgId, Ui::ShowWay::Forward); + App::wnd()->controller()->showPeerHistory( + _peer, + Window::SectionShow::Way::Forward); } } else { Ui::showPeerProfile(_peer); diff --git a/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.cpp b/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.cpp index 3aa9a8da2..cb8391a9a 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.cpp @@ -27,13 +27,17 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org namespace Dialogs { -void ShowSearchFromBox(PeerData *peer, base::lambda)> callback, base::lambda closedCallback) { - auto createController = [peer, callback = std::move(callback)]() -> std::unique_ptr { +void ShowSearchFromBox( + not_null window, + not_null peer, + base::lambda)> callback, + base::lambda closedCallback) { + auto createController = [window, peer, callback = std::move(callback)]() -> std::unique_ptr { if (peer) { if (auto chat = peer->asChat()) { - return std::make_unique(chat, std::move(callback)); + return std::make_unique(window, chat, std::move(callback)); } else if (auto group = peer->asMegagroup()) { - return std::make_unique(group, std::move(callback)); + return std::make_unique(window, group, std::move(callback)); } } return nullptr; @@ -47,7 +51,11 @@ void ShowSearchFromBox(PeerData *peer, base::lambda)> c } } -ChatSearchFromController::ChatSearchFromController(not_null chat, base::lambda)> callback) : PeerListController() +ChatSearchFromController::ChatSearchFromController( + not_null window, + not_null chat, + base::lambda)> callback) +: PeerListController() , _chat(chat) , _callback(std::move(callback)) { } @@ -115,7 +123,14 @@ void ChatSearchFromController::appendRow(not_null user) { } } -ChannelSearchFromController::ChannelSearchFromController(not_null channel, base::lambda)> callback) : ParticipantsBoxController(channel, ParticipantsBoxController::Role::Members) +ChannelSearchFromController::ChannelSearchFromController( + not_null window, + not_null channel, + base::lambda)> callback) +: ParticipantsBoxController( + window, + channel, + ParticipantsBoxController::Role::Members) , _callback(std::move(callback)) { } diff --git a/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.h b/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.h index bebccb5e0..d65ad3fde 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.h +++ b/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.h @@ -25,11 +25,18 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org namespace Dialogs { -void ShowSearchFromBox(PeerData *peer, base::lambda)> callback, base::lambda closedCallback); +void ShowSearchFromBox( + not_null window, + not_null peer, + base::lambda)> callback, + base::lambda closedCallback); class ChatSearchFromController : public PeerListController, protected base::Subscriber { public: - ChatSearchFromController(not_null chat, base::lambda)> callback); + ChatSearchFromController( + not_null window, + not_null chat, + base::lambda)> callback); void prepare() override; void rowClicked(not_null row) override; @@ -46,7 +53,10 @@ private: class ChannelSearchFromController : public Profile::ParticipantsBoxController { public: - ChannelSearchFromController(not_null channel, base::lambda)> callback); + ChannelSearchFromController( + not_null window, + not_null channel, + base::lambda)> callback); void prepare() override; void rowClicked(not_null row) override; diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index b46267aa7..e11217a91 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -24,17 +24,18 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "dialogs/dialogs_search_from_controllers.h" #include "styles/style_dialogs.h" #include "ui/widgets/buttons.h" +#include "ui/widgets/input_fields.h" #include "ui/wrap/fade_wrap.h" #include "lang/lang_keys.h" #include "application.h" #include "mainwindow.h" #include "mainwidget.h" -#include "ui/widgets/input_fields.h" #include "autoupdater.h" #include "auth_session.h" #include "messenger.h" #include "boxes/peer_list_box.h" #include "window/window_controller.h" +#include "window/window_slide_animation.h" #include "profile/profile_channel_controllers.h" namespace { @@ -873,12 +874,20 @@ void DialogsWidget::clearSearchCache() { } void DialogsWidget::showSearchFrom() { + if (!_searchInPeer) { + return; + } auto peer = _searchInPeer; - Dialogs::ShowSearchFromBox(peer, base::lambda_guarded(this, [this, peer](not_null user) { - Ui::hideLayer(); - setSearchInPeer(peer, user); - onFilterUpdate(true); - }), base::lambda_guarded(this, [this] { _filter->setFocus(); })); + Dialogs::ShowSearchFromBox( + controller(), + peer, + base::lambda_guarded(this, [this, peer]( + not_null user) { + Ui::hideLayer(); + setSearchInPeer(peer, user); + onFilterUpdate(true); + }), + base::lambda_guarded(this, [this] { _filter->setFocus(); })); } void DialogsWidget::onFilterCursorMoved(int from, int to) { diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp index 541380be5..fa2542429 100644 --- a/Telegram/SourceFiles/facades.cpp +++ b/Telegram/SourceFiles/facades.cpp @@ -39,7 +39,6 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org Q_DECLARE_METATYPE(ClickHandlerPtr); Q_DECLARE_METATYPE(Qt::MouseButton); -Q_DECLARE_METATYPE(Ui::ShowWay); namespace App { namespace internal { @@ -270,12 +269,10 @@ void autoplayMediaInlineAsync(const FullMsgId &msgId) { } void showPeerProfile(const PeerId &peer) { - if (auto main = App::main()) { -// main->showSection(Profile::SectionMemento(App::peer(peer))); - main->showSection( - Info::Memento(peer), - anim::type::normal, - anim::activation::normal); + if (auto window = App::wnd()) { + if (auto controller = window->controller()) { + controller->showPeerInfo(peer); + } } } @@ -287,26 +284,15 @@ void showPeerOverview(const PeerId &peer, MediaOverviewType type) { void showPeerHistory( const PeerId &peer, - MsgId msgId, - ShowWay way, - anim::type animated, - anim::activation activation) { + MsgId msgId) { auto ms = getms(); LOG(("Show Peer Start")); - if (MainWidget *m = App::main()) { - m->ui_showPeerHistory(peer, msgId, way, animated, activation); + if (auto m = App::main()) { + m->ui_showPeerHistory(peer, Window::SectionShow(), msgId); } LOG(("Show Peer End: %1").arg(getms() - ms)); } -void showPeerHistoryAsync(const PeerId &peer, MsgId msgId, ShowWay way) { - if (MainWidget *m = App::main()) { - InvokeQueued(m, [peer, msgId, way] { - showPeerHistory(peer, msgId, way); - }); - } -} - PeerData *getPeerForMouseAction() { return Messenger::Instance().ui_getPeerForMouseAction(); } diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h index 25d0e8380..8df6419e5 100644 --- a/Telegram/SourceFiles/facades.h +++ b/Telegram/SourceFiles/facades.h @@ -141,41 +141,21 @@ inline void showPeerOverview(const History *history, MediaOverviewType type) { showPeerOverview(history->peer->id, type); } -enum class ShowWay { - ClearStack, - Forward, - Backward, -}; -void showPeerHistory( - const PeerId &peer, - MsgId msgId, - ShowWay way = ShowWay::ClearStack, - anim::type animated = anim::type::normal, - anim::activation activation = anim::activation::normal); +void showPeerHistory(const PeerId &peer, MsgId msgId); -inline void showPeerHistory( - const PeerData *peer, - MsgId msgId, - ShowWay way = ShowWay::ClearStack) { - showPeerHistory(peer->id, msgId, way); +inline void showPeerHistory(const PeerData *peer, MsgId msgId) { + showPeerHistory(peer->id, msgId); } inline void showPeerHistory( const History *history, - MsgId msgId, - ShowWay way = ShowWay::ClearStack) { - showPeerHistory(history->peer->id, msgId, way); + MsgId msgId) { + showPeerHistory(history->peer->id, msgId); } -inline void showPeerHistoryAtItem( - const HistoryItem *item, - ShowWay way = ShowWay::ClearStack) { - showPeerHistory(item->history()->peer->id, item->id, way); +inline void showPeerHistoryAtItem(const HistoryItem *item) { + showPeerHistory(item->history()->peer->id, item->id); } -void showPeerHistoryAsync(const PeerId &peer, MsgId msgId, ShowWay way = ShowWay::ClearStack); inline void showChatsList() { - showPeerHistory(PeerId(0), 0, ShowWay::ClearStack); -} -inline void showChatsListAsync() { - showPeerHistoryAsync(PeerId(0), 0, ShowWay::ClearStack); + showPeerHistory(PeerId(0), 0); } PeerData *getPeerForMouseAction(); diff --git a/Telegram/SourceFiles/history/history_admin_log_section.cpp b/Telegram/SourceFiles/history/history_admin_log_section.cpp index 304d99ece..4047a41de 100644 --- a/Telegram/SourceFiles/history/history_admin_log_section.cpp +++ b/Telegram/SourceFiles/history/history_admin_log_section.cpp @@ -304,7 +304,9 @@ void Widget::doSetInnerFocus() { } } -bool Widget::showInternal(not_null memento) { +bool Widget::showInternal( + not_null memento, + const Window::SectionShow ¶ms) { if (auto logMemento = dynamic_cast(memento.get())) { if (logMemento->getChannel() == channel()) { restoreState(logMemento); diff --git a/Telegram/SourceFiles/history/history_admin_log_section.h b/Telegram/SourceFiles/history/history_admin_log_section.h index b0de0475d..47a1e718c 100644 --- a/Telegram/SourceFiles/history/history_admin_log_section.h +++ b/Telegram/SourceFiles/history/history_admin_log_section.h @@ -95,7 +95,9 @@ public: QPixmap grabForShowAnimation(const Window::SectionSlideParams ¶ms) override; - bool showInternal(not_null memento) override; + bool showInternal( + not_null memento, + const Window::SectionShow ¶ms) override; std::unique_ptr createMemento() override; void setInternalState(const QRect &geometry, not_null memento); diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp index e9d36ac2d..0dcd17416 100644 --- a/Telegram/SourceFiles/history/history_item.cpp +++ b/Telegram/SourceFiles/history/history_item.cpp @@ -35,6 +35,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "auth_session.h" #include "media/media_audio.h" #include "messenger.h" +#include "mainwindow.h" +#include "window/window_controller.h" namespace { @@ -1234,7 +1236,10 @@ ClickHandlerPtr goToMessageClickHandler(PeerData *peer, MsgId msgId) { if (current && current->history()->peer == peer) { App::main()->pushReplyReturn(current); } - Ui::showPeerHistory(peer, msgId, Ui::ShowWay::Forward); + App::wnd()->controller()->showPeerHistory( + peer, + Window::SectionShow::Way::Forward, + msgId); } }); } diff --git a/Telegram/SourceFiles/history/history_media_types.cpp b/Telegram/SourceFiles/history/history_media_types.cpp index 0de11b89c..3db137d0e 100644 --- a/Telegram/SourceFiles/history/history_media_types.cpp +++ b/Telegram/SourceFiles/history/history_media_types.cpp @@ -34,6 +34,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "core/click_handler_types.h" #include "history/history_location_manager.h" #include "history/history_message.h" +#include "window/main_window.h" #include "window/window_controller.h" #include "styles/style_history.h" #include "calls/calls_instance.h" @@ -2940,7 +2941,9 @@ namespace { ClickHandlerPtr sendMessageClickHandler(PeerData *peer) { return MakeShared([peer] { - Ui::showPeerHistory(peer->id, ShowAtUnreadMsgId, Ui::ShowWay::Forward); + App::wnd()->controller()->showPeerHistory( + peer->id, + Window::SectionShow::Way::Forward); }); } diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 9acd8dd7f..c0d93e99a 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -73,6 +73,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "auth_session.h" #include "window/notifications_manager.h" #include "window/window_controller.h" +#include "window/window_slide_animation.h" #include "inline_bots/inline_results_widget.h" #include "chat_helpers/emoji_suggestions_widget.h" @@ -3766,7 +3767,11 @@ void HistoryWidget::pushTabbedSelectorToThirdSection() { return; } else if (!_canSendMessages) { Auth().data().setTabbedReplacedWithInfo(true); - controller()->showPeerInfo(_peer); + controller()->showPeerInfo(_peer, + Window::SectionShow( + Window::SectionShow::Way::ClearStack, + anim::type::instant, + anim::activation::background)); return; } Auth().data().setTabbedReplacedWithInfo(false); @@ -3784,8 +3789,10 @@ void HistoryWidget::pushTabbedSelectorToThirdSection() { controller()->resizeForThirdSection(); controller()->showSection( std::move(memento), - anim::type::instant, - anim::activation::background); + Window::SectionShow( + Window::SectionShow::Way::ClearStack, + anim::type::instant, + anim::activation::background)); destroyingPanel.destroy(); } @@ -3795,8 +3802,10 @@ void HistoryWidget::pushInfoToThirdSection() { } controller()->showPeerInfo( _peer, - anim::type::instant, - anim::activation::background); + Window::SectionShow( + Window::SectionShow::Way::ClearStack, + anim::type::instant, + anim::activation::background)); } void HistoryWidget::toggleTabbedSelectorMode() { diff --git a/Telegram/SourceFiles/info/info_common_groups_widget.cpp b/Telegram/SourceFiles/info/info_common_groups_widget.cpp index 8e0a372f6..52e3d137d 100644 --- a/Telegram/SourceFiles/info/info_common_groups_widget.cpp +++ b/Telegram/SourceFiles/info/info_common_groups_widget.cpp @@ -28,21 +28,21 @@ namespace CommonGroups { object_ptr Memento::createWidget( QWidget *parent, - Wrap wrap, + rpl::producer wrap, not_null controller, const QRect &geometry) { auto result = object_ptr( parent, - wrap, + std::move(wrap), controller, - App::user(_userId)); + App::user(userId())); result->setInternalState(geometry, this); return std::move(result); } Widget::Widget( QWidget *parent, - Wrap wrap, + rpl::producer wrap, not_null controller, not_null user) : ContentWidget(parent, wrap, controller, user) { diff --git a/Telegram/SourceFiles/info/info_common_groups_widget.h b/Telegram/SourceFiles/info/info_common_groups_widget.h index 19362bed5..77ae99bd5 100644 --- a/Telegram/SourceFiles/info/info_common_groups_widget.h +++ b/Telegram/SourceFiles/info/info_common_groups_widget.h @@ -30,21 +30,24 @@ class InnerWidget; class Memento final : public ContentMemento { public: - Memento(UserId userId) : _userId(userId) { + Memento(UserId userId) : ContentMemento(peerFromUser(userId)) { } object_ptr createWidget( QWidget *parent, - Wrap wrap, + rpl::producer wrap, not_null controller, const QRect &geometry) override; + Section section() const override { + return Section(Section::Type::CommonGroups); + } + UserId userId() const { - return _userId; + return peerToUser(peerId()); } private: - UserId _userId = 0; }; @@ -52,7 +55,7 @@ class Widget final : public ContentWidget { public: Widget( QWidget *parent, - Wrap wrap, + rpl::producer wrap, not_null controller, not_null user); diff --git a/Telegram/SourceFiles/info/info_content_widget.cpp b/Telegram/SourceFiles/info/info_content_widget.cpp index a9e81621f..3da954a01 100644 --- a/Telegram/SourceFiles/info/info_content_widget.cpp +++ b/Telegram/SourceFiles/info/info_content_widget.cpp @@ -37,23 +37,22 @@ namespace Info { ContentWidget::ContentWidget( QWidget *parent, - Wrap wrap, + rpl::producer wrap, not_null controller, not_null peer) : RpWidget(parent) , _controller(controller) , _peer(peer) -, _wrap(wrap) , _scroll(this, st::infoScroll) { setAttribute(Qt::WA_OpaquePaintEvent); -} - -void ContentWidget::setWrap(Wrap wrap) { - if (_wrap != wrap) { - _wrap = wrap; - _wrapChanges.fire_copy(_wrap); - update(); - } + std::move(wrap) | rpl::start_with_next( + [this](Wrap value) { + _bg = (value == Wrap::Layer) + ? st::boxBg + : st::profileBg; + update(); + }, + lifetime()); } void ContentWidget::resizeEvent(QResizeEvent *e) { @@ -76,9 +75,7 @@ void ContentWidget::resizeEvent(QResizeEvent *e) { void ContentWidget::paintEvent(QPaintEvent *e) { Painter p(this); - p.fillRect(e->rect(), (_wrap == Wrap::Layer) - ? st::boxBg - : st::profileBg); + p.fillRect(e->rect(), _bg); } void ContentWidget::setGeometryWithTopMoved( diff --git a/Telegram/SourceFiles/info/info_content_widget.h b/Telegram/SourceFiles/info/info_content_widget.h index ddf4f2f9b..55cdfa84c 100644 --- a/Telegram/SourceFiles/info/info_content_widget.h +++ b/Telegram/SourceFiles/info/info_content_widget.h @@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #pragma once +#include #include "ui/rp_widget.h" #include "info/info_wrap_widget.h" @@ -44,7 +45,7 @@ class ContentWidget : public Ui::RpWidget { public: ContentWidget( QWidget *parent, - Wrap wrap, + rpl::producer wrap, not_null controller, not_null peer); @@ -54,11 +55,6 @@ public: virtual rpl::producer
sectionRequest() const; - Wrap wrap() const { - return _wrap; - } - void setWrap(Wrap wrap); - virtual Section section() const = 0; not_null peer() const { return _peer; @@ -94,9 +90,6 @@ protected: not_null controller() const { return _controller; } - rpl::producer wrapValue() const { - return _wrapChanges.events_starting_with_copy(_wrap); - } void resizeEvent(QResizeEvent *e) override; void paintEvent(QPaintEvent *e) override; @@ -113,9 +106,8 @@ private: const not_null _controller; const not_null _peer; - Wrap _wrap = Wrap::Layer; - rpl::event_stream _wrapChanges; + style::color _bg; int _scrollTopSkip = 0; object_ptr _scroll; Ui::RpWidget *_inner = nullptr; @@ -127,12 +119,20 @@ private: class ContentMemento { public: + ContentMemento(PeerId peerId) : _peerId(peerId) { + } + virtual object_ptr createWidget( QWidget *parent, - Wrap wrap, + rpl::producer wrap, not_null controller, const QRect &geometry) = 0; + virtual PeerId peerId() const { + return _peerId; + } + virtual Section section() const = 0; + virtual ~ContentMemento() = default; void setScrollTop(int scrollTop) { @@ -143,6 +143,7 @@ public: } private: + PeerId _peerId = 0; int _scrollTop = 0; }; diff --git a/Telegram/SourceFiles/info/info_layer_widget.cpp b/Telegram/SourceFiles/info/info_layer_widget.cpp index 5df996667..0a5ba82de 100644 --- a/Telegram/SourceFiles/info/info_layer_widget.cpp +++ b/Telegram/SourceFiles/info/info_layer_widget.cpp @@ -75,8 +75,10 @@ void LayerWidget::parentResized() { localCopy->hideSpecialLayer(anim::type::instant); localCopy->showSection( std::move(memento), - anim::type::instant, - anim::activation::background); + Window::SectionShow( + Window::SectionShow::Way::Forward, + anim::type::instant, + anim::activation::background)); } else if (_controller->canShowThirdSectionWithoutResize()) { takeToThirdSection(); } else { @@ -97,11 +99,19 @@ bool LayerWidget::takeToThirdSection() { Auth().saveDataDelayed(); localCopy->showSection( std::move(memento), - anim::type::instant, - anim::activation::background); + Window::SectionShow( + Window::SectionShow::Way::ClearStack, + anim::type::instant, + anim::activation::background)); return true; } +bool LayerWidget::showSectionInternal( + not_null memento, + const Window::SectionShow ¶ms) { + return _content->showInternal(memento, params); +} + int LayerWidget::MinimalSupportedWidth() { auto minimalMargins = 2 * st::infoMinimalLayerMargin; return st::infoMinimalWidth + minimalMargins; diff --git a/Telegram/SourceFiles/info/info_layer_widget.h b/Telegram/SourceFiles/info/info_layer_widget.h index c0e2831e2..11d88704b 100644 --- a/Telegram/SourceFiles/info/info_layer_widget.h +++ b/Telegram/SourceFiles/info/info_layer_widget.h @@ -46,6 +46,9 @@ public: void parentResized() override; bool takeToThirdSection() override; + bool showSectionInternal( + not_null memento, + const Window::SectionShow ¶ms) override; static int MinimalSupportedWidth(); diff --git a/Telegram/SourceFiles/info/info_memento.cpp b/Telegram/SourceFiles/info/info_memento.cpp index 764d90e6b..2cf8f1c7c 100644 --- a/Telegram/SourceFiles/info/info_memento.cpp +++ b/Telegram/SourceFiles/info/info_memento.cpp @@ -33,16 +33,19 @@ Memento::Memento(PeerId peerId) } Memento::Memento(PeerId peerId, Section section) -: Memento(peerId, section, Default(peerId, section)) { +: Memento(Default(peerId, section)) { } -Memento::Memento( - PeerId peerId, - Section section, - std::unique_ptr content) -: _peerId(peerId) -, _section(section) -, _content(std::move(content)) { +Memento::Memento(std::unique_ptr content) +: _content(std::move(content)) { +} + +PeerId Memento::peerId() const { + return _content->peerId(); +} + +Section Memento::section() const { + return _content->section(); } std::unique_ptr Memento::Default( diff --git a/Telegram/SourceFiles/info/info_memento.h b/Telegram/SourceFiles/info/info_memento.h index 221f442fa..801078852 100644 --- a/Telegram/SourceFiles/info/info_memento.h +++ b/Telegram/SourceFiles/info/info_memento.h @@ -42,10 +42,7 @@ class Memento final : public Window::SectionMemento { public: Memento(PeerId peerId); Memento(PeerId peerId, Section section); - Memento( - PeerId peerId, - Section section, - std::unique_ptr content); + Memento(std::unique_ptr content); object_ptr createWidget( QWidget *parent, @@ -62,12 +59,8 @@ public: return _content.get(); } - PeerId peerId() const { - return _peerId; - } - Section section() const { - return _section; - } + PeerId peerId() const; + Section section() const; ~Memento(); @@ -76,8 +69,6 @@ private: PeerId peerId, Section section); - PeerId _peerId = 0; - Section _section = Section::Type::Profile; std::unique_ptr _content; }; diff --git a/Telegram/SourceFiles/info/info_section_widget.cpp b/Telegram/SourceFiles/info/info_section_widget.cpp index e361332d6..b9f2fda29 100644 --- a/Telegram/SourceFiles/info/info_section_widget.cpp +++ b/Telegram/SourceFiles/info/info_section_widget.cpp @@ -77,11 +77,9 @@ void SectionWidget::showFinishedHook() { } bool SectionWidget::showInternal( - not_null memento) { - if (auto infoMemento = dynamic_cast(memento.get())) { - _content->showInternal(infoMemento); - } - return false; + not_null memento, + const Window::SectionShow ¶ms) { + return _content->showInternal(memento, params); } std::unique_ptr SectionWidget::createMemento() { diff --git a/Telegram/SourceFiles/info/info_section_widget.h b/Telegram/SourceFiles/info/info_section_widget.h index c83515501..64db71895 100644 --- a/Telegram/SourceFiles/info/info_section_widget.h +++ b/Telegram/SourceFiles/info/info_section_widget.h @@ -55,7 +55,8 @@ public: const Window::SectionSlideParams ¶ms) override; bool showInternal( - not_null memento) override; + not_null memento, + const Window::SectionShow ¶ms) override; std::unique_ptr createMemento() override; object_ptr moveContentToLayer( diff --git a/Telegram/SourceFiles/info/info_wrap_widget.cpp b/Telegram/SourceFiles/info/info_wrap_widget.cpp index 73f91c9be..b75ca8dc0 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.cpp +++ b/Telegram/SourceFiles/info/info_wrap_widget.cpp @@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "info/info_wrap_widget.h" #include +#include #include "info/profile/info_profile_widget.h" #include "info/media/info_media_widget.h" #include "info/info_content_widget.h" @@ -31,6 +32,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "ui/widgets/shadow.h" #include "ui/wrap/fade_wrap.h" #include "window/window_controller.h" +#include "window/window_slide_animation.h" #include "auth_session.h" #include "lang/lang_keys.h" #include "styles/style_info.h" @@ -38,14 +40,22 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org namespace Info { +struct WrapWidget::StackItem { + std::unique_ptr section; + std::unique_ptr anotherTab; +}; + WrapWidget::WrapWidget( QWidget *parent, not_null controller, Wrap wrap, not_null memento) : RpWidget(parent) -, _controller(controller) { - applyState(wrap, memento); +, _wrap(wrap) +, _controller(controller) +, _topShadow(this) { + _topShadow->toggleOn(topShadowToggledValue()); + showNewContent(memento->content()); } not_null WrapWidget::peer() const { @@ -53,13 +63,15 @@ not_null WrapWidget::peer() const { } Wrap WrapWidget::wrap() const { - return _content->wrap(); + return _wrap.current(); } void WrapWidget::setWrap(Wrap wrap) { - _content->setWrap(wrap); - setupTop(wrap, _content->section(), _content->peer()->id); - finishShowContent(); + if (_wrap.current() != wrap) { + _wrap = wrap; + setupTop(_content->section(), _content->peer()->id); + finishShowContent(); + } } void WrapWidget::createTabs() { @@ -107,10 +119,9 @@ void WrapWidget::setupTabbedTop(const Section §ion) { } void WrapWidget::setupTop( - Wrap wrap, const Section §ion, PeerId peerId) { - if (wrap == Wrap::Side) { + if (wrap() == Wrap::Side && _historyStack.empty()) { setupTabbedTop(section); } else { setupTabs(Tab::None); @@ -118,30 +129,30 @@ void WrapWidget::setupTop( if (_topTabs) { _topBar.destroy(); } else { - createTopBar(wrap, section, peerId); + createTopBar(section, peerId); } } void WrapWidget::createTopBar( - Wrap wrap, const Section §ion, PeerId peerId) { - _topBar = object_ptr( + _topBar.create( this, - (wrap == Wrap::Layer) + (wrap() == Wrap::Layer) ? st::infoLayerTopBar : st::infoTopBar); + _topBar->setTitle(TitleValue( section, peerId)); - if (wrap != Wrap::Layer) { + if (wrap() != Wrap::Layer || !_historyStack.empty()) { _topBar->enableBackButton(true); _topBar->backRequest() | rpl::start_with_next([this] { - _controller->showBackFromStack(); + showBackFromStack(); }, _topBar->lifetime()); } - if (wrap == Wrap::Layer) { + if (wrap() == Wrap::Layer) { auto close = _topBar->addButton(object_ptr( _topBar, st::infoLayerTopBarClose)); @@ -150,6 +161,25 @@ void WrapWidget::createTopBar( _controller->hideSpecialLayer(); }, close->lifetime()); } + + _topBar->move(0, 0); + _topBar->resizeToWidth(width()); + _topBar->show(); +} + +void WrapWidget::showBackFromStack() { + auto params = Window::SectionShow( + Window::SectionShow::Way::Backward); + if (!_historyStack.empty()) { + auto last = std::move(_historyStack.back()); + _historyStack.pop_back(); + _anotherTabMemento = std::move(last.anotherTab); + showNewContent( + last.section.get(), + params); + } else { + _controller->showBackFromStack(params); + } } not_null WrapWidget::topWidget() const { @@ -159,36 +189,55 @@ not_null WrapWidget::topWidget() const { return _topBar; } +int WrapWidget::topHeightAddition() const { + return _topTabs ? -st::lineWidth : 0; +} + +int WrapWidget::topHeight() const { + return topWidget()->height() + topHeightAddition(); +} + +rpl::producer WrapWidget::topHeightValue() const { + using namespace rpl::mappers; + return topWidget()->heightValue() + | rpl::map($1 + topHeightAddition()); +} + void WrapWidget::showContent(object_ptr content) { _content = std::move(content); _content->show(); + _topShadow->raise(); + if (_topTabs) { + _topTabs->raise(); + } finishShowContent(); } void WrapWidget::finishShowContent() { - _topShadow.create(this); - _topShadow->toggleOn((wrap() == Wrap::Side) - ? rpl::single(true) - : _content->desiredShadowVisibility()); - + updateContentGeometry(); + _desiredHeights.fire(desiredHeightForContent()); + _desiredShadowVisibilities.fire(_content->desiredShadowVisibility()); if (_topTabs) { _topTabs->finishAnimating(); } _topShadow->finishAnimating(); +} - updateContentGeometry(); - - _desiredHeights.fire(desiredHeightForContent()); +rpl::producer WrapWidget::topShadowToggledValue() const { + using namespace rpl::mappers; + return rpl::combine( + _wrap.value(), + _desiredShadowVisibilities.events() | rpl::flatten_latest(), + ($1 == Wrap::Side) || $2); } rpl::producer WrapWidget::desiredHeightForContent() const { - auto result = _content->desiredHeightValue(); - if (_topTabs) { - result = std::move(result) - | rpl::map(func::add(_topTabs->height())); - } - return result; + using namespace rpl::mappers; + return rpl::combine( + _content->desiredHeightValue(), + topHeightValue(), + $1 + $2); } object_ptr WrapWidget::createContent(Tab tab) { @@ -202,7 +251,7 @@ object_ptr WrapWidget::createContent(Tab tab) { object_ptr WrapWidget::createProfileWidget() { auto result = object_ptr( this, - Wrap::Side, + _wrap.value(), controller(), _content->peer()); return result; @@ -211,13 +260,22 @@ object_ptr WrapWidget::createProfileWidget() { object_ptr WrapWidget::createMediaWidget() { auto result = object_ptr( this, - Wrap::Side, + _wrap.value(), controller(), _content->peer(), Media::Widget::Type::Photo); return result; } +object_ptr WrapWidget::createContent( + not_null memento) { + return memento->createWidget( + this, + _wrap.value(), + controller(), + contentGeometry()); +} + bool WrapWidget::hasTopBarShadow() const { return _topShadow->toggled(); } @@ -238,18 +296,22 @@ void WrapWidget::showFinished() { } bool WrapWidget::showInternal( - not_null memento) { + not_null memento, + const Window::SectionShow ¶ms) { if (auto infoMemento = dynamic_cast(memento.get())) { - if (infoMemento->peerId() == peer()->id) { - applyState(_content->wrap(), infoMemento); - return true; + auto content = infoMemento->content(); + if (!_content->showInternal(content)) { + showNewContent( + content, + params); } + return true; } return false; } std::unique_ptr WrapWidget::createMemento() { - auto result = std::make_unique(peer()->id); + auto result = std::make_unique(_content->peer()->id); saveState(result.get()); return std::move(result); } @@ -266,17 +328,40 @@ void WrapWidget::saveState(not_null memento) { } QRect WrapWidget::contentGeometry() const { - return rect().marginsRemoved({ 0, topWidget()->height(), 0, 0 }); + return rect().marginsRemoved({ 0, topHeight(), 0, 0 }); } -void WrapWidget::applyState(Wrap wrap, not_null memento) { +void WrapWidget::showNewContent( + not_null memento, + const Window::SectionShow ¶ms) { + auto saveToStack = (_content != nullptr) + && (params.way == Window::SectionShow::Way::Forward); + auto showAnimated = (_content != nullptr) + && (params.animated != anim::type::instant); + if (showAnimated) { + auto newContent = createContent(memento); + auto params = SectionSlideParams(); +// params.withTopBarShadow = newContent; + } else { + + } + if (saveToStack) { + auto item = StackItem(); + item.section = _content->createMemento(); + if (_anotherTabMemento) { + item.anotherTab = std::move(_anotherTabMemento); + } + _historyStack.push_back(std::move(item)); + } else if (params.way == Window::SectionShow::Way::ClearStack) { + _historyStack.clear(); + } + showNewContent(memento); +} + +void WrapWidget::showNewContent(not_null memento) { // Validates contentGeometry(). - setupTop(wrap, memento->section(), memento->peerId()); - showContent(memento->content()->createWidget( - this, - wrap, - controller(), - contentGeometry())); + setupTop(memento->section(), memento->peerId()); + showContent(createContent(memento)); } void WrapWidget::setupTabs(Tab tab) { @@ -298,7 +383,7 @@ void WrapWidget::resizeEvent(QResizeEvent *e) { void WrapWidget::updateContentGeometry() { if (_content) { _topShadow->resizeToWidth(width()); - _topShadow->moveToLeft(0, topWidget()->height()); + _topShadow->moveToLeft(0, topHeight()); _content->setGeometry(contentGeometry()); } } @@ -316,4 +401,6 @@ QRect WrapWidget::rectForFloatPlayer() const { return _content->rectForFloatPlayer(); } +WrapWidget::~WrapWidget() = default; + } // namespace Info diff --git a/Telegram/SourceFiles/info/info_wrap_widget.h b/Telegram/SourceFiles/info/info_wrap_widget.h index 64cbc16f4..b730ef761 100644 --- a/Telegram/SourceFiles/info/info_wrap_widget.h +++ b/Telegram/SourceFiles/info/info_wrap_widget.h @@ -20,6 +20,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #pragma once +#include #include #include "window/section_widget.h" @@ -28,6 +29,10 @@ class SettingsSlider; class FadeShadow; } // namespace Ui +namespace Window { +enum class SlideDirection; +} // namespace Window + namespace Info { namespace Profile { class Widget; @@ -40,6 +45,7 @@ class Widget; class Section; class Memento; class MoveMemento; +class ContentMemento; class ContentWidget; class TopBar; @@ -97,7 +103,8 @@ public: const Window::SectionSlideParams ¶ms); bool showInternal( - not_null memento); + not_null memento, + const Window::SectionShow ¶ms); std::unique_ptr createMemento(); rpl::producer desiredHeightValue() const; @@ -112,6 +119,8 @@ public: bool wheelEventFromFloatPlayer(QEvent *e); QRect rectForFloatPlayer() const; + ~WrapWidget(); + protected: void resizeEvent(QResizeEvent *e); void paintEvent(QPaintEvent *e); @@ -121,25 +130,37 @@ protected: } private: + using SlideDirection = Window::SlideDirection; + using SectionSlideParams = Window::SectionSlideParams; enum class Tab { Profile, Media, None, }; - void applyState(Wrap wrap, not_null memento); - void setupTop(Wrap wrap, const Section §ion, PeerId peerId); + struct StackItem; + + void showBackFromStack(); + void showNewContent(not_null memento); + void showNewContent( + not_null memento, + const Window::SectionShow ¶ms); + void setupTop(const Section §ion, PeerId peerId); void setupTabbedTop(const Section §ion); void setupTabs(Tab tab); void createTabs(); void createTopBar( - Wrap wrap, const Section §ion, PeerId peerId); + not_null topWidget() const; + int topHeightAddition() const; + int topHeight() const; + rpl::producer topHeightValue() const; QRect contentGeometry() const; rpl::producer desiredHeightForContent() const; void finishShowContent(); + rpl::producer topShadowToggledValue() const; void updateContentGeometry(); void showTab(Tab tab); @@ -147,15 +168,21 @@ private: object_ptr createContent(Tab tab); object_ptr createProfileWidget(); object_ptr createMediaWidget(); + object_ptr createContent( + not_null memento); + rpl::variable _wrap; not_null _controller; object_ptr _content = { nullptr }; object_ptr _topTabs = { nullptr }; object_ptr _topBar = { nullptr }; - object_ptr _topShadow = { nullptr }; + object_ptr _topShadow; Tab _tab = Tab::Profile; + std::unique_ptr _anotherTabMemento; + std::vector _historyStack; rpl::event_stream> _desiredHeights; + rpl::event_stream> _desiredShadowVisibilities; }; diff --git a/Telegram/SourceFiles/info/media/info_media_widget.cpp b/Telegram/SourceFiles/info/media/info_media_widget.cpp index d3b6e2f98..ba1296903 100644 --- a/Telegram/SourceFiles/info/media/info_media_widget.cpp +++ b/Telegram/SourceFiles/info/media/info_media_widget.cpp @@ -28,14 +28,14 @@ namespace Media { object_ptr Memento::createWidget( QWidget *parent, - Wrap wrap, + rpl::producer wrap, not_null controller, const QRect &geometry) { auto result = object_ptr( parent, - wrap, + std::move(wrap), controller, - App::peer(_peerId), + App::peer(peerId()), _type); result->setInternalState(geometry, this); return std::move(result); @@ -43,11 +43,11 @@ object_ptr Memento::createWidget( Widget::Widget( QWidget *parent, - Wrap wrap, + rpl::producer wrap, not_null controller, not_null peer, Type type) -: ContentWidget(parent, wrap, controller, peer) { +: ContentWidget(parent, std::move(wrap), controller, peer) { _inner = setInnerWidget(object_ptr(this, peer, type)); } diff --git a/Telegram/SourceFiles/info/media/info_media_widget.h b/Telegram/SourceFiles/info/media/info_media_widget.h index 6b721cd64..1aee5fcf8 100644 --- a/Telegram/SourceFiles/info/media/info_media_widget.h +++ b/Telegram/SourceFiles/info/media/info_media_widget.h @@ -34,25 +34,25 @@ public: using Type = Storage::SharedMediaType; Memento(PeerId peerId, Type type) - : _peerId(peerId) - , _type(type) { + : ContentMemento(peerId) + , _type(type) { } object_ptr createWidget( QWidget *parent, - Wrap wrap, + rpl::producer wrap, not_null controller, const QRect &geometry) override; - PeerId peerId() const { - return _peerId; + Section section() const override { + return Section(_type); } + Type type() const { return _type; } private: - PeerId _peerId = 0; Type _type = Type::Photo; }; @@ -63,7 +63,7 @@ public: Widget( QWidget *parent, - Wrap wrap, + rpl::producer wrap, not_null controller, not_null peer, Type type); diff --git a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp index e0c663924..e36ec2cda 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_inner_widget.cpp @@ -35,6 +35,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "mainwidget.h" #include "auth_session.h" #include "apiwrap.h" +#include "window/main_window.h" #include "window/window_controller.h" #include "storage/storage_shared_media.h" #include "lang/lang_keys.h" @@ -243,7 +244,7 @@ void InnerWidget::setupUserButtons( | rpl::start_with_next([this, user] { _controller->showPeerHistory( user, - Ui::ShowWay::Forward); + Window::SectionShow::Way::Forward); }, wrap->lifetime()); addButton( @@ -322,12 +323,10 @@ object_ptr InnerWidget::setupSharedMedia( return lng_profile_common_groups(lt_count, count); } )->entity()->clicks() - | rpl::start_with_next([peer = _peer] { - App::main()->showSection( + | rpl::start_with_next([this, peer = _peer] { + _controller->showSection( ::Profile::CommonGroups::SectionMemento( - peer->asUser()), - anim::type::normal, - anim::activation::normal); + peer->asUser())); }, content->lifetime()); }; addMediaButton(MediaType::Photo); diff --git a/Telegram/SourceFiles/info/profile/info_profile_members.cpp b/Telegram/SourceFiles/info/profile/info_profile_members.cpp index 12658f508..102042407 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_members.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_members.cpp @@ -52,7 +52,7 @@ Members::Members( not_null peer) : RpWidget(parent) , _peer(peer) -, _controller(CreateMembersController(_peer)) +, _listController(CreateMembersController(controller, _peer)) , _labelWrap(this) , _label(setupHeader()) , _addMember(this, st::infoMembersAddMember) @@ -62,7 +62,7 @@ Members::Members( langFactory(lng_participant_filter)) , _search(this, st::infoMembersSearch) , _cancelSearch(this, st::infoMembersCancelSearch) -, _list(setupList(this, _controller.get())) { +, _list(setupList(this, _listController.get())) { setupButtons(); std::move(wrapValue) | rpl::start_with_next([this](Wrap wrap) { @@ -70,7 +70,7 @@ Members::Members( updateSearchOverrides(); }, lifetime()); setContent(_list.data()); - _controller->setDelegate(static_cast(this)); + _listController->setDelegate(static_cast(this)); } int Members::desiredHeight() const { diff --git a/Telegram/SourceFiles/info/profile/info_profile_members.h b/Telegram/SourceFiles/info/profile/info_profile_members.h index fdacc15d3..37afad136 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_members.h +++ b/Telegram/SourceFiles/info/profile/info_profile_members.h @@ -99,7 +99,7 @@ private: Wrap _wrap; not_null _peer; - std::unique_ptr _controller; + std::unique_ptr _listController; object_ptr _labelWrap; object_ptr _label; object_ptr _addMember; diff --git a/Telegram/SourceFiles/info/profile/info_profile_members_controllers.cpp b/Telegram/SourceFiles/info/profile/info_profile_members_controllers.cpp index b41db54d0..8b1e77bef 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_members_controllers.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_members_controllers.cpp @@ -25,6 +25,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "apiwrap.h" #include "auth_session.h" #include "observer_peer.h" +#include "window/window_controller.h" namespace Info { namespace Profile { @@ -34,7 +35,9 @@ class ChatMembersController : public PeerListController , private base::Subscriber { public: - ChatMembersController(not_null chat); + ChatMembersController( + not_null window, + not_null chat); void prepare() override; void rowClicked(not_null row) override; @@ -43,12 +46,16 @@ private: void rebuildRows(); std::unique_ptr createRow(not_null user); + not_null _window; not_null _chat; }; -ChatMembersController::ChatMembersController(not_null chat) +ChatMembersController::ChatMembersController( + not_null window, + not_null chat) : PeerListController() +, _window(window) , _chat(chat) { } @@ -110,19 +117,23 @@ std::unique_ptr ChatMembersController::createRow(not_null row) { - Ui::showPeerProfile(row->peer()); + _window->showPeerInfo(row->peer()); } } // namespace std::unique_ptr CreateMembersController( + not_null window, not_null peer) { if (auto chat = peer->asChat()) { - return std::make_unique(chat); + return std::make_unique( + window, + chat); } else if (auto channel = peer->asChannel()) { using ChannelMembersController = ::Profile::ParticipantsBoxController; return std::make_unique( + window, channel, ChannelMembersController::Role::Profile); } diff --git a/Telegram/SourceFiles/info/profile/info_profile_members_controllers.h b/Telegram/SourceFiles/info/profile/info_profile_members_controllers.h index 5f70094ab..6998bca01 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_members_controllers.h +++ b/Telegram/SourceFiles/info/profile/info_profile_members_controllers.h @@ -22,10 +22,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org class PeerListController; +namespace Window { +class Controller; +} // namespace Window + namespace Info { namespace Profile { std::unique_ptr CreateMembersController( + not_null window, not_null peer); } // namespace Profile diff --git a/Telegram/SourceFiles/info/profile/info_profile_widget.cpp b/Telegram/SourceFiles/info/profile/info_profile_widget.cpp index 7ede00627..2247f8b61 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_widget.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_widget.cpp @@ -28,27 +28,27 @@ namespace Profile { object_ptr Memento::createWidget( QWidget *parent, - Wrap wrap, + rpl::producer wrap, not_null controller, const QRect &geometry) { auto result = object_ptr( parent, - wrap, + std::move(wrap), controller, - App::peer(_peerId)); + App::peer(peerId())); result->setInternalState(geometry, this); return std::move(result); } Widget::Widget( QWidget *parent, - Wrap wrap, + rpl::producer wrap, not_null controller, not_null peer) -: ContentWidget(parent, wrap, controller, peer) { +: ContentWidget(parent, rpl::duplicate(wrap), controller, peer) { _inner = setInnerWidget(object_ptr( this, - wrapValue(), + std::move(wrap), controller, peer)); _inner->move(0, 0); diff --git a/Telegram/SourceFiles/info/profile/info_profile_widget.h b/Telegram/SourceFiles/info/profile/info_profile_widget.h index 67ccd1f78..c1512b52e 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_widget.h +++ b/Telegram/SourceFiles/info/profile/info_profile_widget.h @@ -30,17 +30,17 @@ class InnerWidget; class Memento final : public ContentMemento { public: - Memento(PeerId peerId) : _peerId(peerId) { + Memento(PeerId peerId) : ContentMemento(peerId) { } object_ptr createWidget( QWidget *parent, - Wrap wrap, + rpl::producer wrap, not_null controller, const QRect &geometry) override; - PeerId peerId() const { - return _peerId; + Section section() const override { + return Section(Section::Type::Profile); } void setScrollTop(int scrollTop) { @@ -51,7 +51,6 @@ public: } private: - PeerId _peerId = 0; int _scrollTop = 0; }; @@ -60,7 +59,7 @@ class Widget final : public ContentWidget { public: Widget( QWidget *parent, - Wrap wrap, + rpl::producer wrap, not_null controller, not_null peer); diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp index e0833322d..e23345edf 100644 --- a/Telegram/SourceFiles/mainwidget.cpp +++ b/Telegram/SourceFiles/mainwidget.cpp @@ -72,14 +72,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "base/qthelp_regex.h" #include "base/qthelp_url.h" #include "base/flat_set.h" -#include "window/themes/window_theme.h" #include "window/player_wrap_widget.h" +#include "window/notifications_manager.h" +#include "window/window_slide_animation.h" +#include "window/window_controller.h" +#include "window/themes/window_theme.h" #include "styles/style_boxes.h" #include "mtproto/dc_options.h" #include "core/file_utilities.h" #include "auth_session.h" -#include "window/notifications_manager.h" -#include "window/window_controller.h" #include "calls/calls_instance.h" #include "calls/calls_top_bar.h" #include "auth_session.h" @@ -2460,10 +2461,8 @@ void MainWidget::ctrlEnterSubmitUpdated() { void MainWidget::ui_showPeerHistory( PeerId peerId, - MsgId showAtMsgId, - Ui::ShowWay way, - anim::type animated, - anim::activation activation) { + const SectionShow ¶ms, + MsgId showAtMsgId) { if (auto peer = App::peerLoaded(peerId)) { if (peer->migrateTo()) { peer = peer->migrateTo(); @@ -2472,7 +2471,7 @@ void MainWidget::ui_showPeerHistory( } auto restriction = peer->restrictionReason(); if (!restriction.isEmpty()) { - if (activation != anim::activation::background) { + if (params.activation != anim::activation::background) { Ui::show(Box(restriction)); } return; @@ -2482,9 +2481,11 @@ void MainWidget::ui_showPeerHistory( _controller->dialogsListFocused().set(false, true); _a_dialogsWidth.finish(); - bool back = (way == Ui::ShowWay::Backward || !peerId); + using Way = SectionShow::Way; + auto way = params.way; + bool back = (way == Way::Backward || !peerId); bool foundInStack = !peerId; - if (foundInStack || (way == Ui::ShowWay::ClearStack)) { + if (foundInStack || (way == Way::ClearStack)) { for_const (auto &item, _stack) { clearBotStartToken(item->peer); } @@ -2505,14 +2506,14 @@ void MainWidget::ui_showPeerHistory( } } if (auto historyPeer = _history->peer()) { - if (way == Ui::ShowWay::Forward && historyPeer->id == peerId) { - way = Ui::ShowWay::ClearStack; + if (way == Way::Forward && historyPeer->id == peerId) { + way = Way::ClearStack; } } } auto wasActivePeer = activePeer(); - if (activation != anim::activation::background) { + if (params.activation != anim::activation::background) { Ui::hideSettingsAndLayer(); } if (_hider) { @@ -2520,8 +2521,10 @@ void MainWidget::ui_showPeerHistory( _hider = nullptr; } - auto animatedShow = [this, peerId, back, way] { - if (_a_show.animating() || App::passcoded()) { + auto animatedShow = [&] { + if (_a_show.animating() + || App::passcoded() + || (params.animated == anim::type::instant)) { return false; } if (!peerId) { @@ -2536,7 +2539,7 @@ void MainWidget::ui_showPeerHistory( || (_overview != nullptr) || (Adaptive::OneColumn() && !_dialogs->isHidden()); } - if (back || way == Ui::ShowWay::Forward) { + if (back || way == Way::Forward) { return true; } return false; @@ -2545,7 +2548,7 @@ void MainWidget::ui_showPeerHistory( auto animationParams = animatedShow() ? prepareHistoryAnimation(peerId) : Window::SectionSlideParams(); dlgUpdated(); - if (back || (way == Ui::ShowWay::ClearStack)) { + if (back || (way == Way::ClearStack)) { _peerInStack = nullptr; _msgIdInStack = 0; } else { @@ -2554,7 +2557,7 @@ void MainWidget::ui_showPeerHistory( } dlgUpdated(); - if (_history->peer() && _history->peer()->id != peerId && way != Ui::ShowWay::Forward) { + if (_history->peer() && _history->peer()->id != peerId && way != Way::Forward) { clearBotStartToken(_history->peer()); } _history->showHistory(peerId, showAtMsgId); @@ -2766,11 +2769,14 @@ void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool void MainWidget::showSection( Window::SectionMemento &&memento, - anim::type animated, - anim::activation activation) { - if (_mainSection && _mainSection->showInternal(&memento)) { + const SectionShow ¶ms) { + if (_mainSection && _mainSection->showInternal( + &memento, + params)) { return; - } else if (_thirdSection && _thirdSection->showInternal(&memento)) { + } else if (_thirdSection && _thirdSection->showInternal( + &memento, + params)) { return; } @@ -2781,10 +2787,7 @@ void MainWidget::showSection( showNewSection( std::move(memento), - false, - true, - animated, - activation); + params); } void MainWidget::updateColumnLayout() { @@ -2914,12 +2917,10 @@ Window::SectionSlideParams MainWidget::prepareDialogsAnimation() { void MainWidget::showNewSection( Window::SectionMemento &&memento, - bool back, - bool saveInStack, - anim::type animated, - anim::activation activation) { + const SectionShow ¶ms) { using Column = Window::Column; + auto saveInStack = (params.way == SectionShow::Way::Forward); auto thirdSectionTop = getThirdSectionTop(); auto newThirdGeometry = QRect( width() - st::columnMinimalWidthThird, @@ -2942,7 +2943,7 @@ void MainWidget::showNewSection( } } - if (activation != anim::activation::background) { + if (params.activation != anim::activation::background) { Ui::hideSettingsAndLayer(); } @@ -2969,7 +2970,7 @@ void MainWidget::showNewSection( auto animatedShow = [&] { if (_a_show.animating() || App::passcoded() - || (animated == anim::type::instant) + || (params.animated == anim::type::instant) || memento.instant()) { return false; } @@ -3025,6 +3026,7 @@ void MainWidget::showNewSection( } if (animationParams) { + auto back = (params.way == SectionShow::Way::Backward); auto direction = (back || settingSection->forceAnimateBack()) ? Window::SlideDirection::FromLeft : Window::SlideDirection::FromRight; @@ -3056,8 +3058,9 @@ void MainWidget::dropMainSection(Window::SectionWidget *widget) { } _mainSection.destroy(); _controller->showBackFromStack( - anim::type::instant, - anim::activation::background); + SectionShow( + anim::type::instant, + anim::activation::background)); } bool MainWidget::isMainSectionShown() const { @@ -3073,11 +3076,10 @@ bool MainWidget::stackIsEmpty() const { } void MainWidget::showBackFromStack( - anim::type animated, - anim::activation activation) { + const SectionShow ¶ms) { if (selectingPeer()) return; if (_stack.empty()) { - _controller->clearSectionStack(animated, activation); + _controller->clearSectionStack(params); if (App::wnd()) QTimer::singleShot(0, App::wnd(), SLOT(setInnerFocus())); return; } @@ -3102,19 +3104,14 @@ void MainWidget::showBackFromStack( auto historyItem = static_cast(item.get()); _controller->showPeerHistory( historyItem->peer->id, - Ui::ShowWay::Backward, - ShowAtUnreadMsgId, - animated, - activation); + params.withWay(SectionShow::Way::Backward), + ShowAtUnreadMsgId); _history->setReplyReturns(historyItem->peer->id, historyItem->replyReturns); } else if (item->type() == SectionStackItem) { auto sectionItem = static_cast(item.get()); showNewSection( std::move(*sectionItem->memento()), - true, - false, - animated, - activation); + params.withWay(SectionShow::Way::Backward)); } else if (item->type() == OverviewStackItem) { auto overviewItem = static_cast(item.get()); showMediaOverview( @@ -3569,8 +3566,10 @@ void MainWidget::updateThirdColumnToCurrentPeer( if (!canWrite) { _controller->showPeerInfo( peer, - anim::type::instant, - anim::activation::background); + SectionShow( + SectionShow::Way::ClearStack, + anim::type::instant, + anim::activation::background)); Auth().data().setTabbedSelectorSectionEnabled(true); Auth().data().setTabbedReplacedWithInfo(true); } else if (Auth().data().tabbedReplacedWithInfo()) { @@ -3586,8 +3585,10 @@ void MainWidget::updateThirdColumnToCurrentPeer( && Auth().data().thirdSectionInfoEnabled()) { _controller->showPeerInfo( peer, - anim::type::instant, - anim::activation::background); + SectionShow( + SectionShow::Way::ClearStack, + anim::type::instant, + anim::activation::background)); } } } @@ -4290,7 +4291,11 @@ void MainWidget::openPeerByName(const QString &username, MsgId msgId, const QStr peer->asUser()->botInfo->shareGameShortName = startToken; AddBotToGroupBoxController::Start(peer->asUser()); } else { - Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId, Ui::ShowWay::Forward); + InvokeQueued(this, [this, peer] { + _controller->showPeerHistory( + peer->id, + SectionShow::Way::Forward); + }); } } else if (msgId == ShowAtProfileMsgId && !peer->isChannel()) { if (peer->isUser() && peer->asUser()->botInfo && !peer->asUser()->botInfo->cantJoinGroups && !startToken.isEmpty()) { @@ -4298,7 +4303,11 @@ void MainWidget::openPeerByName(const QString &username, MsgId msgId, const QStr AddBotToGroupBoxController::Start(peer->asUser()); } else if (peer->isUser() && peer->asUser()->botInfo) { // Always open bot chats, even from mention links. - Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId, Ui::ShowWay::Forward); + InvokeQueued(this, [this, peer] { + _controller->showPeerHistory( + peer->id, + SectionShow::Way::Forward); + }); } else { _controller->showPeerInfo(peer); } @@ -4313,7 +4322,12 @@ void MainWidget::openPeerByName(const QString &username, MsgId msgId, const QStr _history->updateControlsGeometry(); } } - Ui::showPeerHistoryAsync(peer->id, msgId, Ui::ShowWay::Forward); + InvokeQueued(this, [this, peer, msgId] { + _controller->showPeerHistory( + peer->id, + SectionShow::Way::Forward, + msgId); + }); } } else { MTP::send(MTPcontacts_ResolveUsername(MTP_string(username)), rpcDone(&MainWidget::usernameResolveDone, qMakePair(msgId, startToken)), rpcFail(&MainWidget::usernameResolveFail, username)); @@ -4376,7 +4390,11 @@ void MainWidget::usernameResolveDone(QPair msgIdAndStartToken, c AddBotToGroupBoxController::Start(peer->asUser()); } else if (peer->isUser() && peer->asUser()->botInfo) { // Always open bot chats, even from mention links. - Ui::showPeerHistoryAsync(peer->id, ShowAtUnreadMsgId, Ui::ShowWay::Forward); + InvokeQueued(this, [this, peer] { + _controller->showPeerHistory( + peer->id, + SectionShow::Way::Forward); + }); } else { _controller->showPeerInfo(peer); } @@ -4391,7 +4409,12 @@ void MainWidget::usernameResolveDone(QPair msgIdAndStartToken, c _history->updateControlsGeometry(); } } - Ui::showPeerHistory(peer->id, msgId, Ui::ShowWay::Forward); + InvokeQueued(this, [this, peer, msgId] { + _controller->showPeerHistory( + peer->id, + SectionShow::Way::Forward, + msgId); + }); } } diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h index 89dcd2ae9..45851f48c 100644 --- a/Telegram/SourceFiles/mainwidget.h +++ b/Telegram/SourceFiles/mainwidget.h @@ -58,6 +58,7 @@ class SectionMemento; class SectionWidget; class AbstractSectionWidget; struct SectionSlideParams; +struct SectionShow; enum class Column; } // namespace Window @@ -154,6 +155,8 @@ class MainWidget : public Ui::RpWidget, public RPCSender, private base::Subscrib Q_OBJECT public: + using SectionShow = Window::SectionShow; + MainWidget(QWidget *parent, not_null controller); bool isMainSectionShown() const; @@ -215,14 +218,16 @@ public: bool showMediaTypeSwitch() const; void showSection( Window::SectionMemento &&memento, - anim::type animated, - anim::activation activation); + const SectionShow ¶ms); void updateColumnLayout(); - void showMediaOverview(PeerData *peer, MediaOverviewType type, bool back = false, int32 lastScrollTop = -1); + void showMediaOverview( + PeerData *peer, + MediaOverviewType type, + bool back = false, + int32 lastScrollTop = -1); bool stackIsEmpty() const; void showBackFromStack( - anim::type animated, - anim::activation activation); + const SectionShow ¶ms); void orderWidgets(); QRect historyRect() const; QPixmap grabForShowAnimation(const Window::SectionSlideParams ¶ms); @@ -396,10 +401,8 @@ public: void ui_repaintHistoryItem(not_null item); void ui_showPeerHistory( PeerId peer, - MsgId msgId, - Ui::ShowWay way, - anim::type animated, - anim::activation activation); + const SectionShow ¶ms, + MsgId msgId); PeerData *ui_getPeerForMouseAction(); void notify_botCommandsChanged(UserData *bot); @@ -537,10 +540,7 @@ private: bool willHaveTopBarShadow); void showNewSection( Window::SectionMemento &&memento, - bool back, - bool saveInStack, - anim::type animated, - anim::activation activation); + const SectionShow ¶ms); void dropMainSection(Window::SectionWidget *widget); Window::SectionSlideParams prepareThirdSectionAnimation(Window::SectionWidget *section); diff --git a/Telegram/SourceFiles/mainwindow.cpp b/Telegram/SourceFiles/mainwindow.cpp index 5bc5df89f..93233f1dc 100644 --- a/Telegram/SourceFiles/mainwindow.cpp +++ b/Telegram/SourceFiles/mainwindow.cpp @@ -338,6 +338,15 @@ void MainWindow::showSpecialLayer( } } +bool MainWindow::showSectionInExistingLayer( + not_null memento, + const Window::SectionShow ¶ms) { + if (_layerBg) { + return _layerBg->showSectionInternal(memento, params); + } + return false; +} + void MainWindow::showMainMenu() { if (_passcode) return; diff --git a/Telegram/SourceFiles/mainwindow.h b/Telegram/SourceFiles/mainwindow.h index 4193ab5fe..7a46d6aca 100644 --- a/Telegram/SourceFiles/mainwindow.h +++ b/Telegram/SourceFiles/mainwindow.h @@ -38,6 +38,8 @@ class ClearManager; namespace Window { class LayerStackWidget; +class SectionMemento; +struct SectionShow; namespace Theme { struct BackgroundUpdate; class WarningWidget; @@ -137,6 +139,9 @@ public: void showSpecialLayer( object_ptr layer, anim::type animated); + bool showSectionInExistingLayer( + not_null memento, + const Window::SectionShow ¶ms); void ui_showBox( object_ptr box, LayerOptions options, diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp index 4f24d34b7..fd020c0bd 100644 --- a/Telegram/SourceFiles/overviewwidget.cpp +++ b/Telegram/SourceFiles/overviewwidget.cpp @@ -32,7 +32,9 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "ui/widgets/input_fields.h" #include "ui/widgets/shadow.h" #include "window/top_bar_widget.h" +#include "window/window_slide_animation.h" #include "window/themes/window_theme.h" +#include "window/window_controller.h" #include "lang/lang_keys.h" #include "mainwindow.h" #include "mainwidget.h" @@ -1132,7 +1134,7 @@ void OverviewInner::keyPressEvent(QKeyEvent *e) { if ((_search->isHidden() || !_search->hasFocus()) && !_overview->isHidden() && e->key() == Qt::Key_Escape) { onCancel(); } else if (e->key() == Qt::Key_Back) { - App::main()->showBackFromStack(anim::type::normal, anim::activation::normal); + App::main()->showBackFromStack(Window::SectionShow()); } else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) { onSearchMessages(); } @@ -1528,7 +1530,7 @@ void OverviewInner::onSearchUpdate() { void OverviewInner::onCancel() { if (_selected.isEmpty()) { if (onCancelSearch()) return; - App::main()->showBackFromStack(anim::type::normal, anim::activation::normal); + App::main()->showBackFromStack(Window::SectionShow()); } else { _overview->onClearSelected(); } @@ -2071,7 +2073,7 @@ bool OverviewWidget::paintTopBar(Painter &p, int decreaseWidth) { } void OverviewWidget::topBarClick() { - App::main()->showBackFromStack(anim::type::normal, anim::activation::normal); + App::main()->showBackFromStack(Window::SectionShow()); } PeerData *OverviewWidget::peer() const { diff --git a/Telegram/SourceFiles/profile/profile_block_actions.cpp b/Telegram/SourceFiles/profile/profile_block_actions.cpp index 19683a553..811f50f70 100644 --- a/Telegram/SourceFiles/profile/profile_block_actions.cpp +++ b/Telegram/SourceFiles/profile/profile_block_actions.cpp @@ -31,6 +31,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "auth_session.h" #include "lang/lang_keys.h" #include "profile/profile_channel_controllers.h" +#include "mainwindow.h" namespace Profile { @@ -362,7 +363,10 @@ void ActionsWidget::onLeaveChannel() { void ActionsWidget::onSearchMembers() { if (auto channel = peer()->asChannel()) { - ParticipantsBoxController::Start(channel, ParticipantsBoxController::Role::Members); + ParticipantsBoxController::Start( + App::wnd()->controller(), + channel, + ParticipantsBoxController::Role::Members); } } diff --git a/Telegram/SourceFiles/profile/profile_block_channel_members.cpp b/Telegram/SourceFiles/profile/profile_block_channel_members.cpp index 4f3665c9d..a7b40062f 100644 --- a/Telegram/SourceFiles/profile/profile_block_channel_members.cpp +++ b/Telegram/SourceFiles/profile/profile_block_channel_members.cpp @@ -27,6 +27,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "mainwidget.h" #include "history/history_admin_log_section.h" #include "lang/lang_keys.h" +#include "mainwindow.h" +#include "window/window_controller.h" namespace Profile { @@ -143,13 +145,17 @@ int ChannelMembersWidget::resizeGetHeight(int newWidth) { void ChannelMembersWidget::onMembers() { if (auto channel = peer()->asChannel()) { - ParticipantsBoxController::Start(channel, ParticipantsBoxController::Role::Members); + ParticipantsBoxController::Start( + App::wnd()->controller(), + channel, + ParticipantsBoxController::Role::Members); } } void ChannelMembersWidget::onAdmins() { if (auto channel = peer()->asChannel()) { ParticipantsBoxController::Start( + App::wnd()->controller(), channel, ParticipantsBoxController::Role::Admins); } @@ -160,8 +166,7 @@ void ChannelMembersWidget::onRecentActions() { if (auto main = App::main()) { main->showSection( AdminLog::SectionMemento(channel), - anim::type::normal, - anim::activation::normal); + Window::SectionShow()); } } } diff --git a/Telegram/SourceFiles/profile/profile_block_settings.cpp b/Telegram/SourceFiles/profile/profile_block_settings.cpp index c36d76a47..6f87292de 100644 --- a/Telegram/SourceFiles/profile/profile_block_settings.cpp +++ b/Telegram/SourceFiles/profile/profile_block_settings.cpp @@ -30,6 +30,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "observer_peer.h" #include "auth_session.h" #include "mainwidget.h" +#include "mainwindow.h" +#include "window/window_controller.h" #include "apiwrap.h" #include "lang/lang_keys.h" @@ -213,6 +215,7 @@ void SettingsWidget::onManageAdmins() { EditChatAdminsBoxController::Start(chat); } else if (auto channel = peer()->asChannel()) { ParticipantsBoxController::Start( + App::wnd()->controller(), channel, ParticipantsBoxController::Role::Admins); } @@ -223,8 +226,7 @@ void SettingsWidget::onRecentActions() { if (auto main = App::main()) { main->showSection( AdminLog::SectionMemento(channel), - anim::type::normal, - anim::activation::normal); + Window::SectionShow()); } } } @@ -232,6 +234,7 @@ void SettingsWidget::onRecentActions() { void SettingsWidget::onManageBannedUsers() { if (auto channel = peer()->asMegagroup()) { ParticipantsBoxController::Start( + App::wnd()->controller(), channel, ParticipantsBoxController::Role::Kicked); } @@ -240,6 +243,7 @@ void SettingsWidget::onManageBannedUsers() { void SettingsWidget::onManageRestrictedUsers() { if (auto channel = peer()->asMegagroup()) { ParticipantsBoxController::Start( + App::wnd()->controller(), channel, ParticipantsBoxController::Role::Restricted); } diff --git a/Telegram/SourceFiles/profile/profile_block_shared_media.cpp b/Telegram/SourceFiles/profile/profile_block_shared_media.cpp index caa4b92b5..5976db50d 100644 --- a/Telegram/SourceFiles/profile/profile_block_shared_media.cpp +++ b/Telegram/SourceFiles/profile/profile_block_shared_media.cpp @@ -27,6 +27,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "ui/widgets/buttons.h" #include "mainwidget.h" #include "lang/lang_keys.h" +#include "window/window_controller.h" namespace Profile { namespace { @@ -203,8 +204,7 @@ void SharedMediaWidget::onShowCommonGroups() { if (auto main = App::main()) { main->showSection( Profile::CommonGroups::SectionMemento(peer()->asUser()), - anim::type::normal, - anim::activation::normal); + Window::SectionShow()); } } diff --git a/Telegram/SourceFiles/profile/profile_channel_controllers.cpp b/Telegram/SourceFiles/profile/profile_channel_controllers.cpp index 6ab0d64a1..7783eb76b 100644 --- a/Telegram/SourceFiles/profile/profile_channel_controllers.cpp +++ b/Telegram/SourceFiles/profile/profile_channel_controllers.cpp @@ -30,6 +30,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "mainwidget.h" #include "observer_peer.h" #include "dialogs/dialogs_indexed_list.h" +#include "window/window_controller.h" namespace Profile { namespace { @@ -41,9 +42,11 @@ constexpr auto kSortByOnlineDelay = TimeMs(1000); } // namespace ParticipantsBoxController::ParticipantsBoxController( + not_null window, not_null channel, Role role) : PeerListController(CreateSearchController(channel, role, &_additional)) +, _window(window) , _channel(channel) , _role(role) { if (_channel->mgInfo) { @@ -103,8 +106,14 @@ ParticipantsBoxController::CreateSearchController( return nullptr; } -void ParticipantsBoxController::Start(not_null channel, Role role) { - auto controller = std::make_unique(channel, role); +void ParticipantsBoxController::Start( + not_null window, + not_null channel, + Role role) { + auto controller = std::make_unique( + window, + channel, + role); auto initBox = [role, channel, controller = controller.get()](not_null box) { box->addButton(langFactory(lng_close), [box] { box->closeBox(); }); auto canAddNewItem = [role, channel] { @@ -382,7 +391,7 @@ void ParticipantsBoxController::rowClicked(not_null row) { } else if (_role == Role::Restricted || _role == Role::Kicked) { showRestricted(user); } else { - Ui::showPeerProfile(row->peer()); + _window->showPeerInfo(row->peer()); } } diff --git a/Telegram/SourceFiles/profile/profile_channel_controllers.h b/Telegram/SourceFiles/profile/profile_channel_controllers.h index 393024aba..fc9c1cdff 100644 --- a/Telegram/SourceFiles/profile/profile_channel_controllers.h +++ b/Telegram/SourceFiles/profile/profile_channel_controllers.h @@ -25,6 +25,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "base/timer.h" #include "base/weak_unique_ptr.h" +namespace Window { +class Controller; +} // namespace Window + namespace Profile { // Viewing admins, banned or restricted users list with search. @@ -41,7 +45,10 @@ public: Restricted, Kicked, }; - static void Start(not_null channel, Role role); + static void Start( + not_null window, + not_null channel, + Role role); struct Additional { std::map, MTPChannelAdminRights> adminRights; @@ -55,7 +62,10 @@ public: UserData *creator = nullptr; }; - ParticipantsBoxController(not_null channel, Role role); + ParticipantsBoxController( + not_null window, + not_null channel, + Role role); void addNewItem(); @@ -93,6 +103,7 @@ private: void refreshCustomStatus(not_null row) const; bool feedMegagroupLastParticipants(); + not_null _window; not_null _channel; Role _role = Role::Admins; int _offset = 0; diff --git a/Telegram/SourceFiles/profile/profile_common_groups_section.cpp b/Telegram/SourceFiles/profile/profile_common_groups_section.cpp index bcd012e95..22e877656 100644 --- a/Telegram/SourceFiles/profile/profile_common_groups_section.cpp +++ b/Telegram/SourceFiles/profile/profile_common_groups_section.cpp @@ -33,6 +33,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "observer_peer.h" #include "apiwrap.h" #include "lang/lang_keys.h" +#include "mainwindow.h" +#include "window/window_controller.h" namespace Profile { namespace CommonGroups { @@ -59,9 +61,7 @@ FixedBar::FixedBar(QWidget *parent) : TWidget(parent) } void FixedBar::onBack() { - App::main()->showBackFromStack( - anim::type::normal, - anim::activation::normal); + App::main()->showBackFromStack(Window::SectionShow()); } int FixedBar::resizeGetHeight(int newWidth) { @@ -317,7 +317,9 @@ void InnerWidget::mouseReleaseEvent(QMouseEvent *e) { ripple->lastStop(); } if (pressed == _selected) { - Ui::showPeerHistory(_items[pressed]->peer, ShowAtUnreadMsgId, Ui::ShowWay::Forward); + App::wnd()->controller()->showPeerHistory( + _items[pressed]->peer, + Window::SectionShow::Way::Forward); } } setCursor(_selected ? style::cur_pointer : style::cur_default); @@ -382,7 +384,9 @@ void Widget::doSetInnerFocus() { _inner->setFocus(); } -bool Widget::showInternal(not_null memento) { +bool Widget::showInternal( + not_null memento, + const Window::SectionShow ¶ms) { if (auto profileMemento = dynamic_cast(memento.get())) { if (profileMemento->getUser() == user()) { restoreState(profileMemento); diff --git a/Telegram/SourceFiles/profile/profile_common_groups_section.h b/Telegram/SourceFiles/profile/profile_common_groups_section.h index 0b76a60d0..64669a702 100644 --- a/Telegram/SourceFiles/profile/profile_common_groups_section.h +++ b/Telegram/SourceFiles/profile/profile_common_groups_section.h @@ -187,7 +187,9 @@ public: QPixmap grabForShowAnimation(const Window::SectionSlideParams ¶ms) override; - bool showInternal(not_null memento) override; + bool showInternal( + not_null memento, + const Window::SectionShow ¶ms) override; std::unique_ptr createMemento() override; void setInternalState(const QRect &geometry, not_null memento); diff --git a/Telegram/SourceFiles/profile/profile_cover.cpp b/Telegram/SourceFiles/profile/profile_cover.cpp index 4da898b65..6b564aca4 100644 --- a/Telegram/SourceFiles/profile/profile_cover.cpp +++ b/Telegram/SourceFiles/profile/profile_cover.cpp @@ -39,6 +39,8 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "mainwindow.h" #include "messenger.h" #include "platform/platform_file_utilities.h" +#include "window/main_window.h" +#include "window/window_controller.h" namespace Profile { namespace { @@ -490,7 +492,9 @@ void CoverWidget::onOnlineCountUpdated(int onlineCount) { } void CoverWidget::onSendMessage() { - Ui::showPeerHistory(_peer, ShowAtUnreadMsgId, Ui::ShowWay::Forward); + App::wnd()->controller()->showPeerHistory( + _peer, + Window::SectionShow::Way::Forward); } void CoverWidget::onShareContact() { diff --git a/Telegram/SourceFiles/profile/profile_fixed_bar.cpp b/Telegram/SourceFiles/profile/profile_fixed_bar.cpp index 35801f847..8ab865d2a 100644 --- a/Telegram/SourceFiles/profile/profile_fixed_bar.cpp +++ b/Telegram/SourceFiles/profile/profile_fixed_bar.cpp @@ -30,6 +30,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #include "observer_peer.h" #include "styles/style_boxes.h" #include "profile/profile_back_button.h" +#include "window/window_controller.h" namespace Profile { namespace { @@ -148,7 +149,7 @@ void FixedBar::addRightAction(RightActionType type, base::lambda text } void FixedBar::onBack() { - App::main()->showBackFromStack(anim::type::normal, anim::activation::normal); + App::main()->showBackFromStack(Window::SectionShow()); } void FixedBar::onEditChannel() { diff --git a/Telegram/SourceFiles/profile/profile_widget.cpp b/Telegram/SourceFiles/profile/profile_widget.cpp index c694a159c..e6bd9003e 100644 --- a/Telegram/SourceFiles/profile/profile_widget.cpp +++ b/Telegram/SourceFiles/profile/profile_widget.cpp @@ -75,7 +75,9 @@ void Widget::doSetInnerFocus() { _inner->setFocus(); } -bool Widget::showInternal(not_null memento) { +bool Widget::showInternal( + not_null memento, + const Window::SectionShow ¶ms) { if (auto profileMemento = dynamic_cast(memento.get())) { if (profileMemento->getPeer() == peer()) { restoreState(profileMemento); diff --git a/Telegram/SourceFiles/profile/profile_widget.h b/Telegram/SourceFiles/profile/profile_widget.h index 527f6a538..2cacb3e4a 100644 --- a/Telegram/SourceFiles/profile/profile_widget.h +++ b/Telegram/SourceFiles/profile/profile_widget.h @@ -47,7 +47,9 @@ public: QPixmap grabForShowAnimation(const Window::SectionSlideParams ¶ms) override; - bool showInternal(not_null memento) override; + bool showInternal( + not_null memento, + const Window::SectionShow ¶ms) override; std::unique_ptr createMemento() override; void setInternalState(const QRect &geometry, not_null memento); diff --git a/Telegram/SourceFiles/rpl/producer.h b/Telegram/SourceFiles/rpl/producer.h index 7d7d99d1a..e5061f958 100644 --- a/Telegram/SourceFiles/rpl/producer.h +++ b/Telegram/SourceFiles/rpl/producer.h @@ -534,8 +534,8 @@ inline void operator|( lifetime_with_none &&lifetime) { lifetime.alive_while.add( std::move(value).start( - [](const Value&) {}, - [](const Error&) {}, + [] {}, + [] {}, [] {})); } @@ -551,7 +551,7 @@ inline void operator|( lifetime.alive_while.add( std::move(value).start( std::move(lifetime.next), - [](const Error&) {}, + [] {}, [] {})); } @@ -566,7 +566,7 @@ inline void operator|( lifetime_with_error &&lifetime) { lifetime.alive_while.add( std::move(value).start( - [](const Value&) {}, + [] {}, std::move(lifetime.error), [] {})); } @@ -582,8 +582,8 @@ inline void operator|( lifetime_with_done &&lifetime) { lifetime.alive_while.add( std::move(value).start( - [](const Value&) {}, - [](const Error&) {}, + [] {}, + [] {}, std::move(lifetime.done))); } @@ -620,7 +620,7 @@ inline void operator|( lifetime_with_error_done &&lifetime) { lifetime.alive_while.add( std::move(value).start( - [](const Value&) {}, + [] {}, std::move(lifetime.error), std::move(lifetime.done))); } @@ -640,7 +640,7 @@ inline void operator|( lifetime.alive_while.add( std::move(value).start( std::move(lifetime.next), - [](const Error&) {}, + [] {}, std::move(lifetime.done))); } diff --git a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp index c846177f3..ded678d1c 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_controllers.cpp @@ -143,7 +143,9 @@ void BlockedBoxController::loadMoreRows() { } void BlockedBoxController::rowClicked(not_null row) { - Ui::showPeerHistoryAsync(row->peer()->id, ShowAtUnreadMsgId); + InvokeQueued(App::main(), [peerId = row->peer()->id] { + Ui::showPeerHistory(peerId, ShowAtUnreadMsgId); + }); } void BlockedBoxController::rowActionClicked(not_null row) { diff --git a/Telegram/SourceFiles/ui/abstract_button.h b/Telegram/SourceFiles/ui/abstract_button.h index 0ce1e6507..be353ff19 100644 --- a/Telegram/SourceFiles/ui/abstract_button.h +++ b/Telegram/SourceFiles/ui/abstract_button.h @@ -59,6 +59,12 @@ public: auto clicks() const { return _clicks.events(); } + template + void addClickHandler(Handler &&handler) { + clicks() | rpl::start_with_next( + std::forward(handler), + lifetime()); + } protected: void enterEventHook(QEvent *e) override; diff --git a/Telegram/SourceFiles/ui/effects/fade_animation.cpp b/Telegram/SourceFiles/ui/effects/fade_animation.cpp index 6dc46216d..01757753b 100644 --- a/Telegram/SourceFiles/ui/effects/fade_animation.cpp +++ b/Telegram/SourceFiles/ui/effects/fade_animation.cpp @@ -54,12 +54,21 @@ void FadeAnimation::refreshCache() { if (!_cache.isNull()) { _cache = QPixmap(); _cache = grabContent(); + Assert(!_cache.isNull()); } } QPixmap FadeAnimation::grabContent() { myEnsureResized(_widget); _size = _widget->size(); + if (_size.isEmpty()) { + auto image = QImage( + cIntRetinaFactor(), + cIntRetinaFactor(), + QImage::Format_ARGB32_Premultiplied); + image.fill(Qt::transparent); + return App::pixmapFromImageInPlace(std::move(image)); + } auto widgetContent = myGrab(_widget); if (!_scaled) { return widgetContent; @@ -109,6 +118,9 @@ void FadeAnimation::stopAnimation() { } if (_visible == _widget->isHidden()) { _widget->setVisible(_visible); + if (_visible) { + _widget->showChildren(); + } } } @@ -130,6 +142,7 @@ void FadeAnimation::startAnimation(int duration) { if (_cache.isNull()) { _widget->showChildren(); _cache = grabContent(); + Assert(!_cache.isNull()); _widget->hideChildren(); } auto from = _visible ? 0. : 1.; diff --git a/Telegram/SourceFiles/ui/wrap/fade_wrap.cpp b/Telegram/SourceFiles/ui/wrap/fade_wrap.cpp index 4551747c0..063d9bfcb 100644 --- a/Telegram/SourceFiles/ui/wrap/fade_wrap.cpp +++ b/Telegram/SourceFiles/ui/wrap/fade_wrap.cpp @@ -31,6 +31,9 @@ FadeWrap::FadeWrap( : Parent(parent, std::move(child)) , _duration(st::fadeWrapDuration) , _animation(this, scaled) { + if (auto weak = wrapped()) { + weak->show(); + } } FadeWrap *FadeWrap::setDuration(int duration) { diff --git a/Telegram/SourceFiles/window/layer_widget.cpp b/Telegram/SourceFiles/window/layer_widget.cpp index fc4ae3d04..8f2456012 100644 --- a/Telegram/SourceFiles/window/layer_widget.cpp +++ b/Telegram/SourceFiles/window/layer_widget.cpp @@ -635,6 +635,15 @@ void LayerStackWidget::showSpecialLayer( }, Action::ShowSpecialLayer, animated); } +bool LayerStackWidget::showSectionInternal( + not_null memento, + const SectionShow ¶ms) { + if (_specialLayer) { + return _specialLayer->showSectionInternal(memento, params); + } + return false; +} + void LayerStackWidget::hideSpecialLayer(anim::type animated) { startAnimation([] {}, [this] { clearSpecialLayer(); diff --git a/Telegram/SourceFiles/window/layer_widget.h b/Telegram/SourceFiles/window/layer_widget.h index e71251eae..4076896b3 100644 --- a/Telegram/SourceFiles/window/layer_widget.h +++ b/Telegram/SourceFiles/window/layer_widget.h @@ -26,6 +26,8 @@ namespace Window { class MainMenu; class Controller; +class SectionMemento; +struct SectionShow; class LayerWidget : public Ui::RpWidget { public: @@ -55,6 +57,11 @@ public: virtual bool takeToThirdSection() { return false; } + virtual bool showSectionInternal( + not_null memento, + const SectionShow ¶ms) { + return false; + } protected: void closeLayer() { @@ -119,6 +126,10 @@ public: void hideAll(anim::type animated); void hideTopLayer(anim::type animated); + bool showSectionInternal( + not_null memento, + const SectionShow ¶ms); + bool layerShown() const; ~LayerStackWidget(); diff --git a/Telegram/SourceFiles/window/section_widget.cpp b/Telegram/SourceFiles/window/section_widget.cpp index 798782d07..b19386c1c 100644 --- a/Telegram/SourceFiles/window/section_widget.cpp +++ b/Telegram/SourceFiles/window/section_widget.cpp @@ -20,9 +20,10 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org */ #include "window/section_widget.h" +#include #include "application.h" #include "window/section_memento.h" -#include +#include "window/window_slide_animation.h" namespace Window { @@ -105,4 +106,6 @@ rpl::producer SectionWidget::desiredHeight() const { return rpl::single(height()); } +SectionWidget::~SectionWidget() = default; + } // namespace Window diff --git a/Telegram/SourceFiles/window/section_widget.h b/Telegram/SourceFiles/window/section_widget.h index 486869adb..80b5b8219 100644 --- a/Telegram/SourceFiles/window/section_widget.h +++ b/Telegram/SourceFiles/window/section_widget.h @@ -21,12 +21,14 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org #pragma once #include "ui/rp_widget.h" -#include "window/window_slide_animation.h" namespace Window { class Controller; class LayerWidget; +class SlideAnimation; +struct SectionShow; +enum class SlideDirection; enum class Column { First, @@ -93,7 +95,9 @@ public: virtual bool forceAnimateBack() const { return false; } - void showAnimated(SlideDirection direction, const SectionSlideParams ¶ms); + void showAnimated( + SlideDirection direction, + const SectionSlideParams ¶ms); void showFast(); // This can be used to grab with or without top bar shadow. @@ -108,7 +112,9 @@ public: // // If this method returns false it is not supposed to modify the memento. // If this method returns true it may modify the memento ("take" heavy items). - virtual bool showInternal(not_null memento) = 0; + virtual bool showInternal( + not_null memento, + const SectionShow ¶ms) = 0; // Create a memento of that section to store it in the history stack. // This method may modify the section ("take" heavy items). @@ -156,6 +162,8 @@ protected: return _showAnimation != nullptr; } + ~SectionWidget(); + private: void showFinished(); diff --git a/Telegram/SourceFiles/window/window_controller.cpp b/Telegram/SourceFiles/window/window_controller.cpp index 922ea04c4..050844649 100644 --- a/Telegram/SourceFiles/window/window_controller.cpp +++ b/Telegram/SourceFiles/window/window_controller.cpp @@ -251,89 +251,70 @@ void Controller::updateColumnLayout() { void Controller::showPeerHistory( PeerId peerId, - Ui::ShowWay way, - MsgId msgId, - anim::type animated, - anim::activation activation) { - Ui::showPeerHistory( + const SectionShow ¶ms, + MsgId msgId) { + App::main()->ui_showPeerHistory( peerId, - msgId, - way, - animated, - activation); + params, + msgId); } void Controller::showPeerHistory( not_null peer, - Ui::ShowWay way, - MsgId msgId, - anim::type animated, - anim::activation activation) { + const SectionShow ¶ms, + MsgId msgId) { showPeerHistory( peer->id, - way, - msgId, - animated, - activation); + params, + msgId); } void Controller::showPeerHistory( not_null history, - Ui::ShowWay way, - MsgId msgId, - anim::type animated, - anim::activation activation) { + const SectionShow ¶ms, + MsgId msgId) { showPeerHistory( history->peer->id, - way, - msgId, - animated, - activation); + params, + msgId); } void Controller::showPeerInfo( PeerId peerId, - anim::type animated, - anim::activation activation) { + const SectionShow ¶ms) { if (Adaptive::ThreeColumn() && !Auth().data().thirdSectionInfoEnabled()) { Auth().data().setThirdSectionInfoEnabled(true); Auth().saveDataDelayed(); } - showSection( - Info::Memento(peerId), - animated, - activation); + showSection(Info::Memento(peerId), params); } void Controller::showPeerInfo( not_null peer, - anim::type animated, - anim::activation activation) { - showPeerInfo(peer->id, animated, activation); + const SectionShow ¶ms) { + showPeerInfo(peer->id, params); } void Controller::showPeerInfo( not_null history, - anim::type animated, - anim::activation activation) { - showPeerInfo(history->peer->id, animated, activation); + const SectionShow ¶ms) { + showPeerInfo(history->peer->id, params); } void Controller::showSection( SectionMemento &&memento, - anim::type animated, - anim::activation activation) { - App::main()->showSection( - std::move(memento), - animated, - activation); + const SectionShow ¶ms) { + if (App::wnd()->showSectionInExistingLayer( + &memento, + params)) { + return; + } + App::main()->showSection(std::move(memento), params); } -void Controller::showBackFromStack( - anim::type animated, - anim::activation activation) { - chats()->showBackFromStack(animated, activation); +void Controller::showBackFromStack(const SectionShow ¶ms) { + chats()->showBackFromStack(params); } void Controller::showSpecialLayer( diff --git a/Telegram/SourceFiles/window/window_controller.h b/Telegram/SourceFiles/window/window_controller.h index 442278682..41805428f 100644 --- a/Telegram/SourceFiles/window/window_controller.h +++ b/Telegram/SourceFiles/window/window_controller.h @@ -38,6 +38,37 @@ enum class GifPauseReason { using GifPauseReasons = base::flags; inline constexpr bool is_flag_type(GifPauseReason) { return true; }; +struct SectionShow { + enum class Way { + Forward, + Backward, + ClearStack, + }; + SectionShow( + Way way = Way::ClearStack, + anim::type animated = anim::type::normal, + anim::activation activation = anim::activation::normal) + : way(way) + , animated(animated) + , activation(activation) { + } + SectionShow( + anim::type animated, + anim::activation activation = anim::activation::normal) + : animated(animated) + , activation(activation) { + } + + SectionShow withWay(Way newWay) const { + return SectionShow(newWay, animated, activation); + } + + Way way = Way::Forward; + anim::type animated = anim::type::normal; + anim::activation activation = anim::activation::normal; + +}; + class MainWindow; class SectionMemento; @@ -87,13 +118,44 @@ public: bool takeThirdSectionFromLayer(); void resizeForThirdSection(); void closeThirdSection(); + void showSection( SectionMemento &&memento, - anim::type animated = anim::type::normal, - anim::activation activation = anim::activation::normal); + const SectionShow ¶ms = SectionShow()); void showBackFromStack( - anim::type animated = anim::type::normal, - anim::activation activation = anim::activation::normal); + const SectionShow ¶ms = SectionShow()); + + void showPeerHistory( + PeerId peerId, + const SectionShow ¶ms = SectionShow(), + MsgId msgId = ShowAtUnreadMsgId); + void showPeerHistory( + not_null peer, + const SectionShow ¶ms = SectionShow(), + MsgId msgId = ShowAtUnreadMsgId); + void showPeerHistory( + not_null history, + const SectionShow ¶ms = SectionShow(), + MsgId msgId = ShowAtUnreadMsgId); + + void showPeerInfo( + PeerId peerId, + const SectionShow ¶ms = SectionShow::Way::Forward); + void showPeerInfo( + not_null peer, + const SectionShow ¶ms = SectionShow::Way::Forward); + void showPeerInfo( + not_null history, + const SectionShow ¶ms = SectionShow::Way::Forward); + + void clearSectionStack( + const SectionShow ¶ms = SectionShow::Way::ClearStack) { + showPeerHistory( + PeerId(0), + params, + ShowAtUnreadMsgId); + } + void showSpecialLayer( object_ptr &&layer, anim::type animated = anim::type::normal); @@ -102,49 +164,6 @@ public: showSpecialLayer(nullptr, animated); } - void showPeerHistory( - PeerId peerId, - Ui::ShowWay way = Ui::ShowWay::ClearStack, - MsgId msgId = ShowAtUnreadMsgId, - anim::type animated = anim::type::normal, - anim::activation activation = anim::activation::normal); - void showPeerHistory( - not_null peer, - Ui::ShowWay way = Ui::ShowWay::ClearStack, - MsgId msgId = ShowAtUnreadMsgId, - anim::type animated = anim::type::normal, - anim::activation activation = anim::activation::normal); - void showPeerHistory( - not_null history, - Ui::ShowWay way = Ui::ShowWay::ClearStack, - MsgId msgId = ShowAtUnreadMsgId, - anim::type animated = anim::type::normal, - anim::activation activation = anim::activation::normal); - - void showPeerInfo( - PeerId peerId, - anim::type animated = anim::type::normal, - anim::activation activation = anim::activation::normal); - void showPeerInfo( - not_null peer, - anim::type animated = anim::type::normal, - anim::activation activation = anim::activation::normal); - void showPeerInfo( - not_null history, - anim::type animated = anim::type::normal, - anim::activation activation = anim::activation::normal); - - void clearSectionStack( - anim::type animated = anim::type::normal, - anim::activation activation = anim::activation::normal) { - showPeerHistory( - PeerId(0), - Ui::ShowWay::ClearStack, - ShowAtUnreadMsgId, - animated, - activation); - } - void showJumpToDate( not_null peer, QDate requestedDate);