diff --git a/Telegram/SourceFiles/data/components/sponsored_messages.cpp b/Telegram/SourceFiles/data/components/sponsored_messages.cpp index 7d89b8f20a..8e16827dfb 100644 --- a/Telegram/SourceFiles/data/components/sponsored_messages.cpp +++ b/Telegram/SourceFiles/data/components/sponsored_messages.cpp @@ -271,21 +271,36 @@ void SponsoredMessages::parse( void SponsoredMessages::fillTopBar( not_null history, - not_null widget) { + not_null widget, + Fn hide) { const auto it = _data.find(history); if (it == end(_data)) { return; } - const auto &list = it->second; + auto &list = it->second; if (list.entries.empty()) { return; } + auto &entry = list.entries.front(); + if (!entry.optionalDestructionNotifier) { + entry.optionalDestructionNotifier = std::make_unique(); + } + const auto fullId = entry.itemFullId; + entry.optionalDestructionNotifier->add(std::move(hide)); Ui::FillSponsoredMessageBar( widget, _session, - list.entries.front().itemFullId, - list.entries.front().sponsored.from, - list.entries.front().sponsored.textWithEntities); + fullId, + entry.sponsored.from, + entry.sponsored.textWithEntities); + + const auto viewLifetime = std::make_shared(); + widget->shownValue() | rpl::filter( + rpl::mappers::_1 + ) | rpl::start_with_next([=, this](bool shown) { + view(fullId); + viewLifetime->destroy(); + }, *viewLifetime); } void SponsoredMessages::append( @@ -461,7 +476,9 @@ void SponsoredMessages::view(const FullMsgId &fullId) { } request.requestId = _session->api().request( MTPmessages_ViewSponsoredMessage( - entryPtr->item->history()->peer->input, + entryPtr->item + ? entryPtr->item->history()->peer->input + : _session->data().peer(fullId.peer)->input, MTP_bytes(randomId)) ).done([=] { auto &request = _viewRequests[randomId]; @@ -517,7 +534,9 @@ void SponsoredMessages::clicked( MTP_flags(Flag(0) | (isMedia ? Flag::f_media : Flag(0)) | (isFullscreen ? Flag::f_fullscreen : Flag(0))), - entryPtr->item->history()->peer->input, + entryPtr->item + ? entryPtr->item->history()->peer->input + : _session->data().peer(fullId.peer)->input, MTP_bytes(randomId) )).send(); } @@ -546,7 +565,7 @@ auto SponsoredMessages::createReportCallback(const FullMsgId &fullId) return; } - const auto history = entry->item->history(); + const auto history = _session->data().history(fullId.peer); const auto erase = [=] { const auto it = _data.find(history); diff --git a/Telegram/SourceFiles/data/components/sponsored_messages.h b/Telegram/SourceFiles/data/components/sponsored_messages.h index ceb43f588e..62553c39ca 100644 --- a/Telegram/SourceFiles/data/components/sponsored_messages.h +++ b/Telegram/SourceFiles/data/components/sponsored_messages.h @@ -105,7 +105,8 @@ public: void clicked(const FullMsgId &fullId, bool isMedia, bool isFullscreen); void fillTopBar( not_null history, - not_null widget); + not_null widget, + Fn hide); [[nodiscard]] AppendResult append(not_null history); void inject( @@ -130,6 +131,7 @@ private: FullMsgId itemFullId; SponsoredMessage sponsored; std::unique_ptr preload; + std::unique_ptr optionalDestructionNotifier; }; struct List { std::vector entries; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 32f3186056..ae91eae353 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -2529,9 +2529,15 @@ void HistoryWidget::showHistory( = base::make_unique_q>( this, object_ptr(this)); + auto destruction = [this] { + if (_sponsoredMessageBar) { + _sponsoredMessageBar->hide(anim::type::normal); + } + }; session().sponsoredMessages().fillTopBar( _history, - _sponsoredMessageBar->entity()); + _sponsoredMessageBar->entity(), + std::move(destruction)); _sponsoredMessageBarHeight = 0; _sponsoredMessageBar->heightValue( ) | rpl::start_with_next([=](int height) { diff --git a/Telegram/SourceFiles/ui/chat/sponsored_message_bar.cpp b/Telegram/SourceFiles/ui/chat/sponsored_message_bar.cpp index ea19c723ca..0668bff208 100644 --- a/Telegram/SourceFiles/ui/chat/sponsored_message_bar.cpp +++ b/Telegram/SourceFiles/ui/chat/sponsored_message_bar.cpp @@ -8,11 +8,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/chat/sponsored_message_bar.h" #include "core/application.h" +#include "core/click_handler_types.h" #include "core/ui_integration.h" // Core::MarkedTextContext. #include "data/components/sponsored_messages.h" #include "data/data_session.h" +#include "history/history_item_helpers.h" #include "lang/lang_keys.h" #include "main/main_session.h" +#include "menu/menu_sponsored.h" #include "ui/chat/chat_style.h" #include "ui/chat/chat_theme.h" #include "ui/dynamic_image.h" @@ -80,12 +83,17 @@ public: }; +[[nodiscard]] Window::SessionController *FindSessionController( + not_null widget) { + const auto window = Core::App().findWindow(widget); + return window ? window->sessionController() : nullptr; +} + [[nodiscard]] ColorFactory GenerateReplyColorCallback( not_null widget, FullMsgId fullId, int colorIndex) { - const auto window = Core::App().findWindow(widget); - const auto controller = window ? window->sessionController() : nullptr; + const auto controller = FindSessionController(widget); if (!controller) { return [] -> Colors { return { st::windowBgActive->c, st::windowActiveTextFg->c }; @@ -121,11 +129,31 @@ public: } // namespace void FillSponsoredMessageBar( - not_null widget, + not_null container, not_null session, FullMsgId fullId, Data::SponsoredFrom from, const TextWithEntities &textWithEntities) { + const auto widget = CreateSimpleRectButton( + container, + st::defaultRippleAnimationBgOver); + widget->show(); + container->sizeValue() | rpl::start_with_next([=](const QSize &s) { + widget->resize(s); + }, widget->lifetime()); + widget->setAcceptBoth(); + + widget->addClickHandler([=](Qt::MouseButton button) { + if (button == Qt::RightButton) { + if (const auto controller = FindSessionController(widget)) { + ::Menu::ShowSponsored(widget, controller->uiShow(), fullId); + } + } else if (button == Qt::LeftButton) { + session->sponsoredMessages().clicked(fullId, false, false); + UrlClickHandler::Open(from.link); + } + }); + struct State final { Ui::Text::String title; Ui::Text::String contentTitle; @@ -179,6 +207,18 @@ void FillSponsoredMessageBar( widget, fullId, from.colorIndex ? from.colorIndex : 4/*blue*/)); + const auto handler = HideSponsoredClickHandler(); + removeButton->setClickedCallback([=] { + if (const auto controller = FindSessionController(widget)) { + ActivateClickHandler(widget, handler, { + .other = QVariant::fromValue(ClickHandlerContext{ + .itemId = fullId, + .sessionWindow = base::make_weak(controller), + .show = controller->uiShow(), + }) + }); + } + }); removeButton->show(); widget->paintRequest( @@ -186,6 +226,7 @@ void FillSponsoredMessageBar( auto p = QPainter(widget); const auto r = widget->rect(); p.fillRect(r, st::historyPinnedBg); + widget->paintRipple(p, 0, 0); const auto leftPadding = st::msgReplyBarSkip + st::msgReplyBarSkip; const auto rightPadding = st::msgReplyBarSkip; const auto topPadding = st::msgReplyPadding.top(); @@ -300,14 +341,14 @@ void FillSponsoredMessageBar( const auto minHeight = hasRightPhoto ? (rightPhotoPlaceholder + bottomPadding * 2) : desiredHeight; - widget->resize( + container->resize( widget->width(), std::clamp( desiredHeight, minHeight, st::sponsoredMessageBarMaxHeight)); }, widget->lifetime()); - widget->resize(widget->width(), 1); + container->resize(widget->width(), 1); { const auto top = Ui::CreateChild(widget); diff --git a/Telegram/SourceFiles/ui/chat/sponsored_message_bar.h b/Telegram/SourceFiles/ui/chat/sponsored_message_bar.h index d18ec9b05c..e127fb1e4e 100644 --- a/Telegram/SourceFiles/ui/chat/sponsored_message_bar.h +++ b/Telegram/SourceFiles/ui/chat/sponsored_message_bar.h @@ -20,7 +20,7 @@ namespace Ui { class RpWidget; void FillSponsoredMessageBar( - not_null widget, + not_null container, not_null session, FullMsgId fullId, Data::SponsoredFrom from,