From b7ef5325ac56d1ac1c0a9f1e8ac8bc710a768ee5 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Mon, 28 Oct 2024 12:15:37 +0300 Subject: [PATCH] Improved display of sponsored message bar for preloaded messages. --- .../data/components/sponsored_messages.cpp | 9 +- .../data/components/sponsored_messages.h | 1 + .../SourceFiles/history/history_widget.cpp | 153 +++++++++++++----- Telegram/SourceFiles/history/history_widget.h | 5 + 4 files changed, 126 insertions(+), 42 deletions(-) diff --git a/Telegram/SourceFiles/data/components/sponsored_messages.cpp b/Telegram/SourceFiles/data/components/sponsored_messages.cpp index 8e16827df..57c9c0688 100644 --- a/Telegram/SourceFiles/data/components/sponsored_messages.cpp +++ b/Telegram/SourceFiles/data/components/sponsored_messages.cpp @@ -203,6 +203,13 @@ bool SponsoredMessages::canHaveFor(not_null history) const { return false; } +bool SponsoredMessages::isTopBarFor(not_null history) const { + if (const auto user = history->peer->asUser()) { + return user->isBot(); + } + return false; +} + void SponsoredMessages::request(not_null history, Fn done) { if (!canHaveFor(history)) { return; @@ -294,7 +301,7 @@ void SponsoredMessages::fillTopBar( entry.sponsored.from, entry.sponsored.textWithEntities); - const auto viewLifetime = std::make_shared(); + const auto viewLifetime = widget->lifetime().make_state(); widget->shownValue() | rpl::filter( rpl::mappers::_1 ) | rpl::start_with_next([=, this](bool shown) { diff --git a/Telegram/SourceFiles/data/components/sponsored_messages.h b/Telegram/SourceFiles/data/components/sponsored_messages.h index 62553c39c..1f5715e6c 100644 --- a/Telegram/SourceFiles/data/components/sponsored_messages.h +++ b/Telegram/SourceFiles/data/components/sponsored_messages.h @@ -99,6 +99,7 @@ public: ~SponsoredMessages(); [[nodiscard]] bool canHaveFor(not_null history) const; + [[nodiscard]] bool isTopBarFor(not_null history) const; void request(not_null history, Fn done); void clearItems(not_null history); [[nodiscard]] Details lookupDetails(const FullMsgId &fullId) const; diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index ae91eae35..10a41d76b 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -2509,12 +2509,9 @@ void HistoryWidget::showHistory( unreadCountUpdated(); // set _historyDown badge. showAboutTopPromotion(); - { + if (!session().sponsoredMessages().isTopBarFor(_history)) { _scroll->setTrackingContent(false); - const auto checkState = crl::guard(this, [=, history = _history] { - if (history != _history) { - return; - } + const auto checkState = [=] { using State = Data::SponsoredMessages::State; const auto state = session().sponsoredMessages().state( _history); @@ -2525,34 +2522,16 @@ void HistoryWidget::showHistory( } else if (state == State::InjectToMiddle) { injectSponsoredMessages(); } else if (state == State::AppendToTopBar) { - _sponsoredMessageBar - = base::make_unique_q>( - this, - object_ptr(this)); - auto destruction = [this] { - if (_sponsoredMessageBar) { - _sponsoredMessageBar->hide(anim::type::normal); - } - }; - session().sponsoredMessages().fillTopBar( - _history, - _sponsoredMessageBar->entity(), - std::move(destruction)); - _sponsoredMessageBarHeight = 0; - _sponsoredMessageBar->heightValue( - ) | rpl::start_with_next([=](int height) { - _topDelta = _preserveScrollTop - ? 0 - : (height - _sponsoredMessageBarHeight); - _sponsoredMessageBarHeight = height; - updateHistoryGeometry(); - updateControlsGeometry(); - _topDelta = 0; - }, _sponsoredMessageBar->lifetime()); - _sponsoredMessageBar->show(anim::type::normal); } - }); - session().sponsoredMessages().request(_history, checkState); + }; + const auto history = _history; + session().sponsoredMessages().request( + _history, + crl::guard(this, [=, this] { + if (history == _history) { + checkState(); + } + })); checkState(); } } else { @@ -2961,8 +2940,8 @@ void HistoryWidget::updateControlsVisibility() { if (_pinnedBar) { _pinnedBar->show(); } - if (_sponsoredMessageBar) { - _sponsoredMessageBar->show(anim::type::instant); + if (_sponsoredMessageBar && checkSponsoredMessageBarVisibility()) { + _sponsoredMessageBar->toggle(true, anim::type::normal); } if (_translateBar) { _translateBar->show(); @@ -4162,7 +4141,7 @@ void HistoryWidget::hideChildWidgets() { _pinnedBar->hide(); } if (_sponsoredMessageBar) { - _sponsoredMessageBar->hide(anim::type::instant); + _sponsoredMessageBar->toggle(false, anim::type::instant); } if (_translateBar) { _translateBar->hide(); @@ -4450,9 +4429,7 @@ void HistoryWidget::showAnimated( if (_pinnedBar) { _pinnedBar->finishAnimating(); } - if (_sponsoredMessageBar) { - _sponsoredMessageBar->finishAnimating(); - } + checkSponsoredMessageBar(); if (_translateBar) { _translateBar->finishAnimating(); } @@ -4491,9 +4468,6 @@ void HistoryWidget::showFinished() { if (_pinnedBar) { _pinnedBar->finishAnimating(); } - if (_sponsoredMessageBar) { - _sponsoredMessageBar->finishAnimating(); - } if (_translateBar) { _translateBar->finishAnimating(); } @@ -4506,6 +4480,7 @@ void HistoryWidget::showFinished() { _showAnimation = nullptr; doneShow(); synteticScrollToY(_scroll->scrollTop()); + requestSponsoredMessageBar(); } void HistoryWidget::doneShow() { @@ -7605,6 +7580,102 @@ void HistoryWidget::requestMessageData(MsgId msgId) { session().api().requestMessageData(_peer, msgId, callback); } +bool HistoryWidget::checkSponsoredMessageBarVisibility() const { + const auto h = _list->height() + - (_kbScroll->isHidden() ? 0 : _kbScroll->height()); + return (h > _scroll->height()); +} + +void HistoryWidget::requestSponsoredMessageBar() { + if (!_history || !session().sponsoredMessages().isTopBarFor(_history)) { + return; + } + const auto checkState = [=, this] { + using State = Data::SponsoredMessages::State; + const auto state = session().sponsoredMessages().state( + _history); + _sponsoredMessagesStateKnown = (state != State::None); + if (state == State::AppendToTopBar) { + createSponsoredMessageBar(); + if (checkSponsoredMessageBarVisibility()) { + _sponsoredMessageBar->toggle(true, anim::type::normal); + } else { + auto &lifetime = _sponsoredMessageBar->lifetime(); + const auto heightLifetime + = lifetime.make_state(); + _list->heightValue( + ) | rpl::start_with_next([=, this] { + if (_sponsoredMessageBar->toggled()) { + heightLifetime->destroy(); + } else if (checkSponsoredMessageBarVisibility()) { + _sponsoredMessageBar->toggle( + true, + anim::type::normal); + heightLifetime->destroy(); + } + }, *heightLifetime); + } + } + }; + const auto history = _history; + session().sponsoredMessages().request( + _history, + crl::guard(this, [=, this] { + if (history == _history) { + checkState(); + } + })); +} + +void HistoryWidget::checkSponsoredMessageBar() { + if (!_history) { + return; + } + const auto state = session().sponsoredMessages().state(_history); + if (state == Data::SponsoredMessages::State::AppendToTopBar) { + if (checkSponsoredMessageBarVisibility()) { + createSponsoredMessageBar(); + _sponsoredMessageBar->toggle(true, anim::type::instant); + } + } +} + +void HistoryWidget::createSponsoredMessageBar() { + _sponsoredMessageBar = base::make_unique_q>( + this, + object_ptr(this)); + + _sponsoredMessageBar->entity()->resizeToWidth(_scroll->width()); + auto destruction = [this] { + if (_sponsoredMessageBar) { + _sponsoredMessageBar->toggle(false, anim::type::normal); + _sponsoredMessageBar->shownValue( + ) | rpl::start_with_next([=](bool shown) { + if (!shown) { + _sponsoredMessageBar = nullptr; + } + }, _sponsoredMessageBar->lifetime()); + } + }; + session().sponsoredMessages().fillTopBar( + _history, + _sponsoredMessageBar->entity(), + std::move(destruction)); + + _sponsoredMessageBarHeight = 0; + _sponsoredMessageBar->heightValue( + ) | rpl::start_with_next([=](int height) { + _topDelta = _preserveScrollTop + ? 0 + : (height - _sponsoredMessageBarHeight); + _sponsoredMessageBarHeight = height; + updateHistoryGeometry(); + updateControlsGeometry(); + _topDelta = 0; + }, _sponsoredMessageBar->lifetime()); + _sponsoredMessageBar->toggle(false, anim::type::instant); +} + bool HistoryWidget::sendExistingDocument( not_null document, Api::MessageToSend messageToSend, diff --git a/Telegram/SourceFiles/history/history_widget.h b/Telegram/SourceFiles/history/history_widget.h index 94bf0fff9..89e5b63c9 100644 --- a/Telegram/SourceFiles/history/history_widget.h +++ b/Telegram/SourceFiles/history/history_widget.h @@ -531,6 +531,11 @@ private: void setupGroupCallBar(); void setupRequestsBar(); + void checkSponsoredMessageBar(); + [[nodiscard]] bool checkSponsoredMessageBarVisibility() const; + void requestSponsoredMessageBar(); + void createSponsoredMessageBar(); + void sendInlineResult(InlineBots::ResultSelected result); void drawField(Painter &p, const QRect &rect);