Added context menu to top bar of sponsored messages.

This commit is contained in:
23rd 2024-10-26 14:09:19 +03:00
parent 2db30690ce
commit 84055ed74e
5 changed files with 84 additions and 16 deletions

View file

@ -271,21 +271,36 @@ void SponsoredMessages::parse(
void SponsoredMessages::fillTopBar( void SponsoredMessages::fillTopBar(
not_null<History*> history, not_null<History*> history,
not_null<Ui::RpWidget*> widget) { not_null<Ui::RpWidget*> widget,
Fn<void()> hide) {
const auto it = _data.find(history); const auto it = _data.find(history);
if (it == end(_data)) { if (it == end(_data)) {
return; return;
} }
const auto &list = it->second; auto &list = it->second;
if (list.entries.empty()) { if (list.entries.empty()) {
return; return;
} }
auto &entry = list.entries.front();
if (!entry.optionalDestructionNotifier) {
entry.optionalDestructionNotifier = std::make_unique<rpl::lifetime>();
}
const auto fullId = entry.itemFullId;
entry.optionalDestructionNotifier->add(std::move(hide));
Ui::FillSponsoredMessageBar( Ui::FillSponsoredMessageBar(
widget, widget,
_session, _session,
list.entries.front().itemFullId, fullId,
list.entries.front().sponsored.from, entry.sponsored.from,
list.entries.front().sponsored.textWithEntities); entry.sponsored.textWithEntities);
const auto viewLifetime = std::make_shared<rpl::lifetime>();
widget->shownValue() | rpl::filter(
rpl::mappers::_1
) | rpl::start_with_next([=, this](bool shown) {
view(fullId);
viewLifetime->destroy();
}, *viewLifetime);
} }
void SponsoredMessages::append( void SponsoredMessages::append(
@ -461,7 +476,9 @@ void SponsoredMessages::view(const FullMsgId &fullId) {
} }
request.requestId = _session->api().request( request.requestId = _session->api().request(
MTPmessages_ViewSponsoredMessage( MTPmessages_ViewSponsoredMessage(
entryPtr->item->history()->peer->input, entryPtr->item
? entryPtr->item->history()->peer->input
: _session->data().peer(fullId.peer)->input,
MTP_bytes(randomId)) MTP_bytes(randomId))
).done([=] { ).done([=] {
auto &request = _viewRequests[randomId]; auto &request = _viewRequests[randomId];
@ -517,7 +534,9 @@ void SponsoredMessages::clicked(
MTP_flags(Flag(0) MTP_flags(Flag(0)
| (isMedia ? Flag::f_media : Flag(0)) | (isMedia ? Flag::f_media : Flag(0))
| (isFullscreen ? Flag::f_fullscreen : 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) MTP_bytes(randomId)
)).send(); )).send();
} }
@ -546,7 +565,7 @@ auto SponsoredMessages::createReportCallback(const FullMsgId &fullId)
return; return;
} }
const auto history = entry->item->history(); const auto history = _session->data().history(fullId.peer);
const auto erase = [=] { const auto erase = [=] {
const auto it = _data.find(history); const auto it = _data.find(history);

View file

@ -105,7 +105,8 @@ public:
void clicked(const FullMsgId &fullId, bool isMedia, bool isFullscreen); void clicked(const FullMsgId &fullId, bool isMedia, bool isFullscreen);
void fillTopBar( void fillTopBar(
not_null<History*> history, not_null<History*> history,
not_null<Ui::RpWidget*> widget); not_null<Ui::RpWidget*> widget,
Fn<void()> hide);
[[nodiscard]] AppendResult append(not_null<History*> history); [[nodiscard]] AppendResult append(not_null<History*> history);
void inject( void inject(
@ -130,6 +131,7 @@ private:
FullMsgId itemFullId; FullMsgId itemFullId;
SponsoredMessage sponsored; SponsoredMessage sponsored;
std::unique_ptr<MediaPreload> preload; std::unique_ptr<MediaPreload> preload;
std::unique_ptr<rpl::lifetime> optionalDestructionNotifier;
}; };
struct List { struct List {
std::vector<Entry> entries; std::vector<Entry> entries;

View file

@ -2529,9 +2529,15 @@ void HistoryWidget::showHistory(
= base::make_unique_q<Ui::SlideWrap<>>( = base::make_unique_q<Ui::SlideWrap<>>(
this, this,
object_ptr<Ui::RpWidget>(this)); object_ptr<Ui::RpWidget>(this));
auto destruction = [this] {
if (_sponsoredMessageBar) {
_sponsoredMessageBar->hide(anim::type::normal);
}
};
session().sponsoredMessages().fillTopBar( session().sponsoredMessages().fillTopBar(
_history, _history,
_sponsoredMessageBar->entity()); _sponsoredMessageBar->entity(),
std::move(destruction));
_sponsoredMessageBarHeight = 0; _sponsoredMessageBarHeight = 0;
_sponsoredMessageBar->heightValue( _sponsoredMessageBar->heightValue(
) | rpl::start_with_next([=](int height) { ) | rpl::start_with_next([=](int height) {

View file

@ -8,11 +8,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/chat/sponsored_message_bar.h" #include "ui/chat/sponsored_message_bar.h"
#include "core/application.h" #include "core/application.h"
#include "core/click_handler_types.h"
#include "core/ui_integration.h" // Core::MarkedTextContext. #include "core/ui_integration.h" // Core::MarkedTextContext.
#include "data/components/sponsored_messages.h" #include "data/components/sponsored_messages.h"
#include "data/data_session.h" #include "data/data_session.h"
#include "history/history_item_helpers.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "main/main_session.h" #include "main/main_session.h"
#include "menu/menu_sponsored.h"
#include "ui/chat/chat_style.h" #include "ui/chat/chat_style.h"
#include "ui/chat/chat_theme.h" #include "ui/chat/chat_theme.h"
#include "ui/dynamic_image.h" #include "ui/dynamic_image.h"
@ -80,12 +83,17 @@ public:
}; };
[[nodiscard]] Window::SessionController *FindSessionController(
not_null<RpWidget*> widget) {
const auto window = Core::App().findWindow(widget);
return window ? window->sessionController() : nullptr;
}
[[nodiscard]] ColorFactory GenerateReplyColorCallback( [[nodiscard]] ColorFactory GenerateReplyColorCallback(
not_null<RpWidget*> widget, not_null<RpWidget*> widget,
FullMsgId fullId, FullMsgId fullId,
int colorIndex) { int colorIndex) {
const auto window = Core::App().findWindow(widget); const auto controller = FindSessionController(widget);
const auto controller = window ? window->sessionController() : nullptr;
if (!controller) { if (!controller) {
return [] -> Colors { return [] -> Colors {
return { st::windowBgActive->c, st::windowActiveTextFg->c }; return { st::windowBgActive->c, st::windowActiveTextFg->c };
@ -121,11 +129,31 @@ public:
} // namespace } // namespace
void FillSponsoredMessageBar( void FillSponsoredMessageBar(
not_null<RpWidget*> widget, not_null<RpWidget*> container,
not_null<Main::Session*> session, not_null<Main::Session*> session,
FullMsgId fullId, FullMsgId fullId,
Data::SponsoredFrom from, Data::SponsoredFrom from,
const TextWithEntities &textWithEntities) { 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 { struct State final {
Ui::Text::String title; Ui::Text::String title;
Ui::Text::String contentTitle; Ui::Text::String contentTitle;
@ -179,6 +207,18 @@ void FillSponsoredMessageBar(
widget, widget,
fullId, fullId,
from.colorIndex ? from.colorIndex : 4/*blue*/)); 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(); removeButton->show();
widget->paintRequest( widget->paintRequest(
@ -186,6 +226,7 @@ void FillSponsoredMessageBar(
auto p = QPainter(widget); auto p = QPainter(widget);
const auto r = widget->rect(); const auto r = widget->rect();
p.fillRect(r, st::historyPinnedBg); p.fillRect(r, st::historyPinnedBg);
widget->paintRipple(p, 0, 0);
const auto leftPadding = st::msgReplyBarSkip + st::msgReplyBarSkip; const auto leftPadding = st::msgReplyBarSkip + st::msgReplyBarSkip;
const auto rightPadding = st::msgReplyBarSkip; const auto rightPadding = st::msgReplyBarSkip;
const auto topPadding = st::msgReplyPadding.top(); const auto topPadding = st::msgReplyPadding.top();
@ -300,14 +341,14 @@ void FillSponsoredMessageBar(
const auto minHeight = hasRightPhoto const auto minHeight = hasRightPhoto
? (rightPhotoPlaceholder + bottomPadding * 2) ? (rightPhotoPlaceholder + bottomPadding * 2)
: desiredHeight; : desiredHeight;
widget->resize( container->resize(
widget->width(), widget->width(),
std::clamp( std::clamp(
desiredHeight, desiredHeight,
minHeight, minHeight,
st::sponsoredMessageBarMaxHeight)); st::sponsoredMessageBarMaxHeight));
}, widget->lifetime()); }, widget->lifetime());
widget->resize(widget->width(), 1); container->resize(widget->width(), 1);
{ {
const auto top = Ui::CreateChild<PlainShadow>(widget); const auto top = Ui::CreateChild<PlainShadow>(widget);

View file

@ -20,7 +20,7 @@ namespace Ui {
class RpWidget; class RpWidget;
void FillSponsoredMessageBar( void FillSponsoredMessageBar(
not_null<RpWidget*> widget, not_null<RpWidget*> container,
not_null<Main::Session*> session, not_null<Main::Session*> session,
FullMsgId fullId, FullMsgId fullId,
Data::SponsoredFrom from, Data::SponsoredFrom from,