From 104cf504ab4349c971f30a23e6ee4692abb1dc24 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 16 Jan 2024 10:34:49 +0400 Subject: [PATCH] Play ttl media horizontally where the message was. --- .../chat_helpers/ttl_media_layer_widget.cpp | 135 ++++++++++++------ .../history/view/history_view_message.cpp | 4 +- .../view/media/history_view_document.cpp | 10 +- 3 files changed, 99 insertions(+), 50 deletions(-) diff --git a/Telegram/SourceFiles/chat_helpers/ttl_media_layer_widget.cpp b/Telegram/SourceFiles/chat_helpers/ttl_media_layer_widget.cpp index 120f89f9e..817cd4709 100644 --- a/Telegram/SourceFiles/chat_helpers/ttl_media_layer_widget.cpp +++ b/Telegram/SourceFiles/chat_helpers/ttl_media_layer_widget.cpp @@ -31,6 +31,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/tooltip.h" #include "window/section_widget.h" // Window::ChatThemeValueFromPeer. #include "window/themes/window_theme.h" +#include "window/window_controller.h" #include "window/window_session_controller.h" #include "styles/style_chat.h" #include "styles/style_chat_helpers.h" @@ -44,6 +45,7 @@ public: PreviewDelegate( not_null parent, not_null st, + rpl::producer chatWideValue, Fn update); bool elementAnimationsPaused() override; @@ -54,15 +56,18 @@ public: private: const not_null _parent; const std::unique_ptr _pathGradient; + rpl::variable _chatWide; }; PreviewDelegate::PreviewDelegate( not_null parent, not_null st, + rpl::producer chatWideValue, Fn update) : _parent(parent) -, _pathGradient(HistoryView::MakePathShiftGradient(st, update)) { +, _pathGradient(HistoryView::MakePathShiftGradient(st, update)) +, _chatWide(std::move(chatWideValue)) { } bool PreviewDelegate::elementAnimationsPaused() { @@ -78,7 +83,7 @@ HistoryView::Context PreviewDelegate::elementContext() { } bool PreviewDelegate::elementIsChatWide() { - return true; + return _chatWide.current(); } class PreviewWrap final : public Ui::RpWidget { @@ -86,6 +91,8 @@ public: PreviewWrap( not_null parent, not_null item, + rpl::producer viewportValue, + rpl::producer chatWideValue, rpl::producer> theme); ~PreviewWrap(); @@ -93,13 +100,17 @@ public: private: void paintEvent(QPaintEvent *e) override; - [[nodiscard]] QRect elementRect() const; const not_null _item; const std::unique_ptr _style; const std::unique_ptr _delegate; + rpl::variable _globalViewport; + rpl::variable _chatWide; std::shared_ptr _theme; std::unique_ptr _element; + QRect _viewport; + QRect _elementGeometry; + rpl::variable _elementInner; rpl::lifetime _elementLifetime; struct { @@ -114,6 +125,8 @@ private: PreviewWrap::PreviewWrap( not_null parent, not_null item, + rpl::producer viewportValue, + rpl::producer chatWideValue, rpl::producer> theme) : RpWidget(parent) , _item(item) @@ -122,8 +135,9 @@ PreviewWrap::PreviewWrap( , _delegate(std::make_unique( parent, _style.get(), - [=] { update(elementRect()); })) { - + std::move(chatWideValue), + [=] { update(_elementGeometry); })) +, _globalViewport(std::move(viewportValue)) { const auto isRound = _item && _item->media() && _item->media()->document() @@ -140,7 +154,7 @@ PreviewWrap::PreviewWrap( session->data().viewRepaintRequest( ) | rpl::start_with_next([=](not_null view) { if (view == _element.get()) { - update(elementRect()); + update(_elementGeometry); } }, lifetime()); @@ -157,11 +171,15 @@ PreviewWrap::PreviewWrap( close->setClickedCallback(closeCallback); close->setTextTransform(Ui::RoundButton::TextTransform::NoTransform); - sizeValue( - ) | rpl::start_with_next([=](const QSize &s) { + rpl::combine( + sizeValue(), + _elementInner.value() + ) | rpl::start_with_next([=](QSize size, QRect inner) { close->moveToLeft( - (s.width() - close->width()) / 2, - s.height() - close->height() - st::ttlMediaButtonBottomSkip); + inner.x() + (inner.width() - close->width()) / 2, + (size.height() + - close->height() + - st::ttlMediaButtonBottomSkip)); }, close->lifetime()); } @@ -170,11 +188,27 @@ PreviewWrap::PreviewWrap( { _element->initDimensions(); - widthValue( - ) | rpl::filter([=](int width) { - return width > st::msgMinWidth; - }) | rpl::start_with_next([=](int width) { - _element->resizeGetHeight(width); + rpl::combine( + sizeValue(), + _globalViewport.value() + ) | rpl::start_with_next([=](QSize outer, QRect globalViewport) { + _viewport = globalViewport.isEmpty() + ? rect() + : mapFromGlobal(globalViewport); + if (_viewport.width() < st::msgMinWidth) { + return; + } + _element->resizeGetHeight(_viewport.width()); + _elementGeometry = QRect( + (_viewport.width() - _element->width()) / 2, + (_viewport.height() - _element->height()) / 2, + _element->width(), + _element->height() + ).translated(_viewport.topLeft()); + const auto media = _element->media(); + _elementInner = _element->innerGeometry().translated( + _elementGeometry.topLeft()); + update(); }, _elementLifetime); } @@ -203,22 +237,17 @@ PreviewWrap::PreviewWrap( st::defaultImportantTooltip.padding), st::dialogsStoriesTooltip); tooltip->toggleFast(true); - sizeValue( - ) | rpl::filter( - [](const QSize &s) { return !s.isNull(); } - ) | rpl::take(1) | rpl::start_with_next([=](const QSize &s) { - if (s.isEmpty()) { - return; - } - auto area = elementRect(); - area.setWidth(_element->media() - ? _element->media()->width() - : _element->width()); - tooltip->pointAt(area, RectPart::Top, [=](QSize size) { + _elementInner.value( + ) | rpl::filter([](const QRect &inner) { + return !inner.isEmpty(); + }) | rpl::start_with_next([=](const QRect &inner) { + tooltip->pointAt(inner, RectPart::Top, [=](QSize size) { return QPoint{ - (area.width() - size.width()) / 2, - (s.height() - size.height() * 2 - _element->height()) / 2 - - st::defaultImportantTooltip.padding.top(), + inner.x() + (inner.width() - size.width()) / 2, + (inner.y() + - st::normalFont->height + - size.height() + - st::defaultImportantTooltip.padding.top()), }; }); }, tooltip->lifetime()); @@ -232,14 +261,6 @@ PreviewWrap::PreviewWrap( }, lifetime()); } -QRect PreviewWrap::elementRect() const { - return QRect( - (width() - _element->width()) / 2, - (height() - _element->height()) / 2, - _element->width(), - _element->height()); -} - rpl::producer<> PreviewWrap::closeRequests() const { return _closeRequests.events(); } @@ -250,13 +271,14 @@ PreviewWrap::~PreviewWrap() { } void PreviewWrap::paintEvent(QPaintEvent *e) { - if (!_element) { + if (!_element || _elementGeometry.isEmpty()) { return; } auto p = QPainter(this); - const auto r = rect(); - + //p.fillRect(_viewport, QColor(255, 0, 0, 64)); + //p.fillRect(_elementGeometry, QColor(0, 255, 0, 64)); + //p.fillRect(_elementInner.current(), QColor(0, 0, 255, 64)); if (!_last.use) { const auto size = _element->currentSize(); auto result = QImage( @@ -276,12 +298,35 @@ void PreviewWrap::paintEvent(QPaintEvent *e) { } _last.frame = std::move(result); } - p.translate( - (r.width() - _element->width()) / 2, - (r.height() - _element->height()) / 2); + p.translate(_elementGeometry.topLeft()); p.drawImage(0, 0, _last.frame); } +rpl::producer GlobalViewportForWindow( + not_null controller) { + const auto delegate = controller->window().floatPlayerDelegate(); + return rpl::single(rpl::empty) | rpl::then( + delegate->floatPlayerAreaUpdates() + ) | rpl::map([=] { + auto section = (Media::Player::FloatSectionDelegate*)nullptr; + delegate->floatPlayerEnumerateSections([&]( + not_null check, + Window::Column column) { + if ((column == Window::Column::First && !section) + || column == Window::Column::Second) { + section = check; + } + }); + if (section) { + const auto rect = section->floatPlayerAvailableRect(); + if (rect.width() >= st::msgMinWidth) { + return rect; + } + } + return QRect(); + }); +} + } // namespace void ShowTTLMediaLayerWidget( @@ -292,6 +337,8 @@ void ShowTTLMediaLayerWidget( auto preview = base::make_unique_q( parent, item, + GlobalViewportForWindow(controller), + controller->adaptive().chatWideValue(), Window::ChatThemeValueFromPeer( controller, item->history()->peer)); diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index d7c9e2f16..93db9cd12 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -1984,6 +1984,7 @@ bool Message::hasFromPhoto() const { case Context::AdminLog: return true; case Context::History: + case Context::TTLViewer: case Context::Pinned: case Context::Replies: case Context::SavedSublist: { @@ -2005,7 +2006,6 @@ bool Message::hasFromPhoto() const { return !item->out() && !item->history()->peer->isUser(); } break; case Context::ContactPreview: - case Context::TTLViewer: return false; } Unexpected("Context in Message::hasFromPhoto."); @@ -3171,6 +3171,7 @@ bool Message::hasFromName() const { case Context::AdminLog: return true; case Context::History: + case Context::TTLViewer: case Context::Pinned: case Context::Replies: case Context::SavedSublist: { @@ -3201,7 +3202,6 @@ bool Message::hasFromName() const { return false; } break; case Context::ContactPreview: - case Context::TTLViewer: return false; } Unexpected("Context in Message::hasFromName."); diff --git a/Telegram/SourceFiles/history/view/media/history_view_document.cpp b/Telegram/SourceFiles/history/view/media/history_view_document.cpp index 2c963c344..5c3632c33 100644 --- a/Telegram/SourceFiles/history/view/media/history_view_document.cpp +++ b/Telegram/SourceFiles/history/view/media/history_view_document.cpp @@ -243,10 +243,12 @@ void PaintWaveform( p.fillRect( QRectF(barLeft, barTop, leftWidth, barHeight), active); - p.fillRect( - QRectF(activeWidth, barTop, rightWidth, barHeight), - inactive); - } else { + if (!ttl) { + p.fillRect( + QRectF(activeWidth, barTop, rightWidth, barHeight), + inactive); + } + } else if (!ttl || barLeft < activeWidth) { const auto &color = (barLeft >= activeWidth) ? inactive : active; p.fillRect(QRectF(barLeft, barTop, barWidth, barHeight), color); }