diff --git a/Telegram/SourceFiles/boxes/peers/peer_short_info_box.cpp b/Telegram/SourceFiles/boxes/peers/peer_short_info_box.cpp index dc7524e76..0275358f0 100644 --- a/Telegram/SourceFiles/boxes/peers/peer_short_info_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/peer_short_info_box.cpp @@ -7,27 +7,36 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "boxes/peers/peer_short_info_box.h" -#include "ui/effects/radial_animation.h" -#include "ui/widgets/labels.h" -#include "ui/widgets/scroll_area.h" -#include "ui/wrap/vertical_layout.h" -#include "ui/wrap/slide_wrap.h" -#include "ui/wrap/wrap.h" -#include "ui/image/image_prepare.h" -#include "ui/text/text_utilities.h" -#include "ui/painter.h" +#include "base/event_filter.h" +#include "core/application.h" #include "info/profile/info_profile_text.h" #include "info/profile/info_profile_values.h" +#include "lang/lang_keys.h" #include "media/streaming/media_streaming_instance.h" #include "media/streaming/media_streaming_player.h" -#include "base/event_filter.h" -#include "lang/lang_keys.h" +#include "ui/effects/radial_animation.h" +#include "ui/image/image_prepare.h" +#include "ui/painter.h" +#include "ui/text/text_utilities.h" +#include "ui/widgets/labels.h" +#include "ui/widgets/menu/menu_add_action_callback.h" +#include "ui/widgets/menu/menu_add_action_callback_factory.h" +#include "ui/widgets/popup_menu.h" +#include "ui/widgets/scroll_area.h" +#include "ui/wrap/slide_wrap.h" +#include "ui/wrap/vertical_layout.h" +#include "ui/wrap/wrap.h" +#include "window/window_controller.h" +#include "window/window_session_controller.h" #include "styles/style_boxes.h" -#include "styles/style_layers.h" #include "styles/style_info.h" +#include "styles/style_layers.h" +#include "styles/style_menu_icons.h" namespace { +using MenuCallback = Ui::Menu::MenuCallback; + constexpr auto kShadowMaxAlpha = 80; constexpr auto kInactiveBarOpacity = 0.5; @@ -833,6 +842,24 @@ void PeerShortInfoBox::refreshRoundedTopImage(const QColor &color) { RectPart::TopLeft | RectPart::TopRight); } +rpl::producer PeerShortInfoBox::fillMenuRequests() const { + return _fillMenuRequests.events(); +} + +void PeerShortInfoBox::contextMenuEvent(QContextMenuEvent *e) { + _menuHolder = nullptr; + const auto menu = Ui::CreateChild( + this, + st::popupMenuWithIcons); + _fillMenuRequests.fire(Ui::Menu::CreateAddActionCallback(menu)); + _menuHolder.reset(menu); + if (menu->empty()) { + _menuHolder = nullptr; + return; + } + menu->popup(e->globalPos()); +} + rpl::producer PeerShortInfoBox::nameValue() const { return _fields.value( ) | rpl::map([](const PeerShortInfoFields &fields) { diff --git a/Telegram/SourceFiles/boxes/peers/peer_short_info_box.h b/Telegram/SourceFiles/boxes/peers/peer_short_info_box.h index b51ac3e2d..271e1826c 100644 --- a/Telegram/SourceFiles/boxes/peers/peer_short_info_box.h +++ b/Telegram/SourceFiles/boxes/peers/peer_short_info_box.h @@ -15,6 +15,10 @@ struct ShortInfoCover; struct ShortInfoBox; } // namespace style +namespace Ui::Menu { +struct MenuCallback; +} // namespace Ui::Menu + namespace Media::Streaming { class Document; class Instance; @@ -160,6 +164,11 @@ public: [[nodiscard]] rpl::producer<> openRequests() const; [[nodiscard]] rpl::producer moveRequests() const; + [[nodiscard]] auto fillMenuRequests() const + -> rpl::producer; + +protected: + void contextMenuEvent(QContextMenuEvent *e) override; private: void prepare() override; @@ -192,6 +201,9 @@ private: not_null _rows; PeerShortInfoCover _cover; + base::unique_qptr _menuHolder; + rpl::event_stream _fillMenuRequests; + rpl::event_stream<> _openRequests; }; diff --git a/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.cpp b/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.cpp index 72482cffd..760a821c7 100644 --- a/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.cpp @@ -7,26 +7,30 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "boxes/peers/prepare_short_info_box.h" +#include "base/unixtime.h" #include "boxes/peers/peer_short_info_box.h" +#include "core/application.h" +#include "data/data_changes.h" +#include "data/data_channel.h" +#include "data/data_chat.h" +#include "data/data_file_origin.h" #include "data/data_peer.h" +#include "data/data_peer_values.h" #include "data/data_photo.h" #include "data/data_photo_media.h" -#include "data/data_streaming.h" -#include "data/data_file_origin.h" -#include "data/data_user.h" -#include "data/data_chat.h" -#include "data/data_channel.h" -#include "data/data_peer_values.h" -#include "data/data_user_photos.h" -#include "data/data_changes.h" #include "data/data_session.h" -#include "main/main_session.h" -#include "window/window_session_controller.h" +#include "data/data_streaming.h" +#include "data/data_user.h" +#include "data/data_user_photos.h" #include "info/profile/info_profile_values.h" -#include "ui/text/format_values.h" -#include "base/unixtime.h" #include "lang/lang_keys.h" +#include "main/main_session.h" +#include "ui/delayed_activation.h" // PreventDelayedActivation +#include "ui/text/format_values.h" +#include "ui/widgets/menu/menu_add_action_callback.h" +#include "window/window_session_controller.h" #include "styles/style_info.h" +#include "styles/style_menu_icons.h" namespace { @@ -446,6 +450,7 @@ object_ptr PrepareShortInfoBox( not_null peer, Fn open, Fn videoPaused, + Fn menuFiller, const style::ShortInfoBox *stOverride) { const auto type = peer->isSelf() ? PeerShortInfoType::Self @@ -463,6 +468,13 @@ object_ptr PrepareShortInfoBox( std::move(videoPaused), stOverride); + if (menuFiller) { + result->fillMenuRequests( + ) | rpl::start_with_next([=](Ui::Menu::MenuCallback callback) { + menuFiller(std::move(callback)); + }, result->lifetime()); + } + result->openRequests( ) | rpl::start_with_next(open, result->lifetime()); @@ -481,10 +493,21 @@ object_ptr PrepareShortInfoBox( return navigation->parentController()->isGifPausedAtLeastFor( Window::GifPauseReason::Layer); }; + auto menuFiller = [=](Ui::Menu::MenuCallback addAction) { + const auto controller = navigation->parentController(); + const auto peerSeparateId = Window::SeparateId(peer); + if (controller->windowId() != peerSeparateId) { + addAction(tr::lng_context_new_window(tr::now), [=] { + Ui::PreventDelayedActivation(); + controller->showInNewWindow(peer); + }, &st::menuIconNewWindow); + } + }; return PrepareShortInfoBox( peer, open, videoIsPaused, + std::move(menuFiller), stOverride); } diff --git a/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.h b/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.h index 327ce373b..2edd5cd92 100644 --- a/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.h +++ b/Telegram/SourceFiles/boxes/peers/prepare_short_info_box.h @@ -16,6 +16,10 @@ struct ShortInfoCover; struct ShortInfoBox; } // namespace style +namespace Ui::Menu { +struct MenuCallback; +} // namespace Ui::Menu + namespace Ui { class BoxContent; } // namespace Ui @@ -35,6 +39,7 @@ struct PreparedShortInfoUserpic { not_null peer, Fn open, Fn videoPaused, + Fn menuFiller, const style::ShortInfoBox *stOverride = nullptr); [[nodiscard]] object_ptr PrepareShortInfoBox( diff --git a/Telegram/SourceFiles/media/stories/media_stories_controller.cpp b/Telegram/SourceFiles/media/stories/media_stories_controller.cpp index 1405eaae5..c0ca0eb43 100644 --- a/Telegram/SourceFiles/media/stories/media_stories_controller.cpp +++ b/Telegram/SourceFiles/media/stories/media_stories_controller.cpp @@ -1921,6 +1921,7 @@ object_ptr PrepareShortInfoBox(not_null peer) { peer, open, [] { return false; }, + nullptr, &st::storiesShortInfoBox); }