diff --git a/Telegram/SourceFiles/data/data_sponsored_messages.cpp b/Telegram/SourceFiles/data/data_sponsored_messages.cpp index fb6f03308..2289dfbd1 100644 --- a/Telegram/SourceFiles/data/data_sponsored_messages.cpp +++ b/Telegram/SourceFiles/data/data_sponsored_messages.cpp @@ -273,6 +273,7 @@ void SponsoredMessages::append( .isRecommended = data.is_recommended(), .isForceUserpicDisplay = data.is_show_peer_photo(), .buttonText = qs(data.vbutton_text().value_or_empty()), + .canReport = data.is_can_report(), }; }; const auto externalLink = data.vwebpage() @@ -289,6 +290,7 @@ void SponsoredMessages::append( .externalLink = externalLink, .webpageOrBotPhotoId = photoId, .isForceUserpicDisplay = message.data().is_show_peer_photo(), + .canReport = message.data().is_can_report(), }; } else if (const auto fromId = data.vfrom_id()) { const auto peerId = peerFromMTP(*fromId); @@ -327,6 +329,7 @@ void SponsoredMessages::append( .isChannel = data.is_channel(), .isPublic = data.is_public(), .isForceUserpicDisplay = message.data().is_show_peer_photo(), + .canReport = message.data().is_can_report(), }; }, [&](const MTPDchatInviteAlready &data) { const auto chat = _session->data().processChat(data.vchat()); @@ -461,6 +464,7 @@ SponsoredMessages::Details SponsoredMessages::lookupDetails( ? tr::lng_view_button_bot(tr::now) : QString(), .botLinkInfo = data.from.botLinkInfo, + .canReport = data.from.canReport, }; } diff --git a/Telegram/SourceFiles/data/data_sponsored_messages.h b/Telegram/SourceFiles/data/data_sponsored_messages.h index d5107fd4e..fe55520fc 100644 --- a/Telegram/SourceFiles/data/data_sponsored_messages.h +++ b/Telegram/SourceFiles/data/data_sponsored_messages.h @@ -36,6 +36,7 @@ struct SponsoredFrom { PhotoId webpageOrBotPhotoId = PhotoId(0); bool isForceUserpicDisplay = false; QString buttonText; + bool canReport = false; }; struct SponsoredMessage { @@ -66,6 +67,7 @@ public: bool isForceUserpicDisplay = false; QString buttonText; std::optional botLinkInfo; + bool canReport = false; }; using RandomId = QByteArray; explicit SponsoredMessages(not_null owner); diff --git a/Telegram/SourceFiles/history/history_item_helpers.cpp b/Telegram/SourceFiles/history/history_item_helpers.cpp index e6c9b1e5a..7841959ad 100644 --- a/Telegram/SourceFiles/history/history_item_helpers.cpp +++ b/Telegram/SourceFiles/history/history_item_helpers.cpp @@ -367,6 +367,11 @@ ClickHandlerPtr HideSponsoredClickHandler() { }); } +ClickHandlerPtr ReportSponsoredClickHandler() { + return std::make_shared([=](ClickContext context) { + }); +} + MessageFlags FlagsFromMTP( MsgId id, MTPDmessage::Flags flags, diff --git a/Telegram/SourceFiles/history/history_item_helpers.h b/Telegram/SourceFiles/history/history_item_helpers.h index e468f1497..cdd9af7cd 100644 --- a/Telegram/SourceFiles/history/history_item_helpers.h +++ b/Telegram/SourceFiles/history/history_item_helpers.h @@ -142,6 +142,7 @@ ClickHandlerPtr JumpToStoryClickHandler( not_null peer, StoryId storyId); [[nodiscard]] ClickHandlerPtr HideSponsoredClickHandler(); +[[nodiscard]] ClickHandlerPtr ReportSponsoredClickHandler(); [[nodiscard]] not_null GenerateJoinedMessage( not_null history, diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index 419644095..2100599a0 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -358,6 +358,11 @@ QString FastReplyText() { }); } +struct SecondRightAction final { + std::unique_ptr ripple; + ClickHandlerPtr link; +}; + } // namespace struct Message::CommentsButton { @@ -379,6 +384,7 @@ struct Message::RightAction { std::unique_ptr ripple; ClickHandlerPtr link; QPoint lastPoint; + std::unique_ptr second; }; LogEntryOriginal::LogEntryOriginal() = default; @@ -428,6 +434,16 @@ Message::Message( _bottomInfo.continueReactionAnimations(std::move(animations)); } } + if (data->isSponsored()) { + const auto &messages = data->history()->owner().sponsoredMessages(); + const auto details = messages.lookupDetails(data->fullId()); + if (details.canReport) { + _rightAction = std::make_unique(); + _rightAction->second = std::make_unique(); + + _rightAction->second->link = ReportSponsoredClickHandler(); + } + } } Message::~Message() { @@ -1826,8 +1842,28 @@ void Message::clickHandlerPressedChanged( Element::clickHandlerPressedChanged(handler, pressed); if (!handler) { return; - } else if (_rightAction && (handler == _rightAction->link)) { - toggleRightActionRipple(pressed); + } else if (_rightAction) { + if (_rightAction->second && (handler == _rightAction->second->link)) { + const auto rightSize = rightActionSize(); + Assert(rightSize != std::nullopt); + if (pressed) { + if (!_rightAction->second->ripple) { + // Create a ripple. + _rightAction->second->ripple = + std::make_unique( + st::defaultRippleAnimation, + Ui::RippleAnimation::RoundRectMask( + Size(rightSize->width()), + rightSize->width() / 2), + [=] { repaint(); }); + } + _rightAction->second->ripple->add(_rightAction->lastPoint); + } else if (_rightAction->second->ripple) { + _rightAction->second->ripple->lastStop(); + } + } else if (handler == _rightAction->link) { + toggleRightActionRipple(pressed); + } } else if (_comments && (handler == _comments->link)) { toggleCommentsButtonRipple(pressed); } else if (_topicButton && (handler == _topicButton->link)) { @@ -1859,15 +1895,18 @@ void Message::toggleCommentsButtonRipple(bool pressed) { void Message::toggleRightActionRipple(bool pressed) { Expects(_rightAction != nullptr); - const auto size = rightActionSize(); - Assert(size != std::nullopt); + const auto rightSize = rightActionSize(); + Assert(rightSize != std::nullopt); if (pressed) { if (!_rightAction->ripple) { // Create a ripple. + const auto size = _rightAction->second + ? Size(rightSize->width()) + : *rightSize; _rightAction->ripple = std::make_unique( st::defaultRippleAnimation, - Ui::RippleAnimation::RoundRectMask(*size, size->width() / 2), + Ui::RippleAnimation::RoundRectMask(size, size.width() / 2), [=] { repaint(); }); } _rightAction->ripple->add(_rightAction->lastPoint); @@ -3450,7 +3489,9 @@ std::optional Message::rightActionSize() const { : QSize(st::historyFastShareSize, st::historyFastShareSize); } return data()->isSponsored() - ? QSize(st::historyFastCloseSize, st::historyFastCloseSize) + ? ((_rightAction && _rightAction->second) + ? QSize(st::historyFastCloseSize, st::historyFastCloseSize * 2) + : QSize(st::historyFastCloseSize, st::historyFastCloseSize)) : (displayFastShare() || displayGoToOriginal()) ? QSize(st::historyFastShareSize, st::historyFastShareSize) : std::optional(); @@ -3516,6 +3557,19 @@ void Message::drawRightAction( _rightAction->ripple.reset(); } } + if (_rightAction->second && _rightAction->second->ripple) { + const auto &stm = context.messageStyle(); + const auto colorOverride = &stm->msgWaveformInactive->c; + _rightAction->second->ripple->paint( + p, + left, + top + st::historyFastCloseSize, + size->width(), + colorOverride); + if (_rightAction->second->ripple->empty()) { + _rightAction->second->ripple.reset(); + } + } p.setPen(Qt::NoPen); p.setBrush(st->msgServiceBg()); @@ -3553,6 +3607,13 @@ void Message::drawRightAction( views->repliesSmall.text, views->repliesSmall.textWidth); } + } else if (_rightAction->second) { + st->historyFastCloseIcon().paintInCenter( + p, + { left, top, size->width(), size->width() }); + st->historyFastMoreIcon().paintInCenter( + p, + { left, size->width() + top, size->width(), size->width() }); } else { const auto &icon = data()->isSponsored() ? st->historyFastCloseIcon() @@ -3574,6 +3635,10 @@ ClickHandlerPtr Message::rightActionLink( if (pressPoint) { _rightAction->lastPoint = *pressPoint; } + if (_rightAction->second + && (_rightAction->lastPoint.y() > st::historyFastCloseSize)) { + return _rightAction->second->link; + } return _rightAction->link; } diff --git a/Telegram/SourceFiles/ui/chat/chat.style b/Telegram/SourceFiles/ui/chat/chat.style index 8b294604d..b1307c8b7 100644 --- a/Telegram/SourceFiles/ui/chat/chat.style +++ b/Telegram/SourceFiles/ui/chat/chat.style @@ -578,6 +578,7 @@ historyGoToOriginalIcon: icon {{ "fast_to_original", msgServiceFg, point(1px, 0p historyFastCommentsIcon: icon {{ "fast_comments", msgServiceFg }}; historyFastCloseSize: 30px; historyFastCloseIcon: icon {{ "box_button_close", msgServiceFg }}; +historyFastMoreIcon: icon {{ "title_menu_dots", msgServiceFg, point(0px, -2px) }}; historyFastTranscribeIcon: icon {{ "chat/voice_to_text", msgServiceFg }}; historyFastTranscribeLock: icon {{ "chat/mini_lock", msgServiceFg }}; historyFastTranscribeLockPos: point(18px, 13px); diff --git a/Telegram/SourceFiles/ui/chat/chat_style.cpp b/Telegram/SourceFiles/ui/chat/chat_style.cpp index 88f5ddd38..9470d71d6 100644 --- a/Telegram/SourceFiles/ui/chat/chat_style.cpp +++ b/Telegram/SourceFiles/ui/chat/chat_style.cpp @@ -192,6 +192,7 @@ ChatStyle::ChatStyle(rpl::producer colorIndices) { make(_historyFastTranscribeLock, st::historyFastTranscribeLock); make(_historyGoToOriginalIcon, st::historyGoToOriginalIcon); make(_historyFastCloseIcon, st::historyFastCloseIcon); + make(_historyFastMoreIcon, st::historyFastMoreIcon); make(_historyMapPoint, st::historyMapPoint); make(_historyMapPointInner, st::historyMapPointInner); make(_youtubeIcon, st::youtubeIcon); diff --git a/Telegram/SourceFiles/ui/chat/chat_style.h b/Telegram/SourceFiles/ui/chat/chat_style.h index dca47f0f8..1053d630a 100644 --- a/Telegram/SourceFiles/ui/chat/chat_style.h +++ b/Telegram/SourceFiles/ui/chat/chat_style.h @@ -397,6 +397,9 @@ public: [[nodiscard]] const style::icon &historyFastCloseIcon() const { return _historyFastCloseIcon; } + [[nodiscard]] const style::icon &historyFastMoreIcon() const { + return _historyFastMoreIcon; + } [[nodiscard]] const style::icon &historyMapPoint() const { return _historyMapPoint; } @@ -519,6 +522,7 @@ private: style::icon _msgBotKbWebviewIcon = { Qt::Uninitialized }; style::icon _historyFastCommentsIcon = { Qt::Uninitialized }; style::icon _historyFastShareIcon = { Qt::Uninitialized }; + style::icon _historyFastMoreIcon = { Qt::Uninitialized }; style::icon _historyFastTranscribeIcon = { Qt::Uninitialized }; style::icon _historyFastTranscribeLock = { Qt::Uninitialized }; style::icon _historyGoToOriginalIcon = { Qt::Uninitialized };