From 4212be1b6c56f16debf025c1ef199cf4501c8df0 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 9 Mar 2026 17:16:45 +0400 Subject: [PATCH] Add ripple effect to reply button. --- .../history/history_inner_widget.cpp | 2 +- .../history/view/history_view_list_widget.cpp | 2 +- .../view/history_view_reply_button.cpp | 41 +++++++++++++++++++ .../history/view/history_view_reply_button.h | 12 +++++- 4 files changed, 54 insertions(+), 3 deletions(-) diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index ae3f356b06..fe2397c40f 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -4442,7 +4442,7 @@ void HistoryInner::mouseActionUpdate() { lnkhost = reactionView; } else if (overReplyBtn) { dragState = replyBtnState; - lnkhost = replyBtnView; + lnkhost = _replyButtonManager.get(); } else if (item) { if (item != _mouseActionItem || ((m + selectionViewOffset) - _dragStartPosition).manhattanLength() >= QApplication::startDragDistance()) { if (_mouseAction == MouseAction::PrepareDrag) { diff --git a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp index 1423497211..d59dc0ae1b 100644 --- a/Telegram/SourceFiles/history/view/history_view_list_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_list_widget.cpp @@ -3871,7 +3871,7 @@ void ListWidget::mouseActionUpdate() { lnkhost = reactionView; } else if (overReplyBtn) { dragState = replyBtnState; - lnkhost = replyBtnView; + lnkhost = _replyButtonManager.get(); } else if (view) { auto cursorDeltaLength = [&] { auto cursorDelta = (_overState.point - _pressState.point); diff --git a/Telegram/SourceFiles/history/view/history_view_reply_button.cpp b/Telegram/SourceFiles/history/view/history_view_reply_button.cpp index ad97680db7..834995b293 100644 --- a/Telegram/SourceFiles/history/view/history_view_reply_button.cpp +++ b/Telegram/SourceFiles/history/view/history_view_reply_button.cpp @@ -9,8 +9,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/view/history_view_cursor_state.h" #include "ui/chat/chat_style.h" +#include "ui/effects/ripple_animation.h" #include "lang/lang_keys.h" #include "styles/style_chat.h" +#include "styles/style_widgets.h" namespace HistoryView::ReplyButton { namespace { @@ -182,8 +184,10 @@ void Manager::updateButton(ButtonParameters parameters) { } _buttonShowTimer.cancel(); _scheduledParameters = std::nullopt; + _ripple = nullptr; } _buttonContext = parameters.context; + _lastPointer = parameters.pointer; if (parameters.link) { _link = parameters.link; } @@ -279,6 +283,19 @@ void Manager::paintButton( radius); p.drawImage(position, *frame.image, frame.rect); + if (_ripple && !_ripple->empty() && _button && button == _button.get()) { + const auto color = context.st->windowBgOver()->c; + _ripple->paint( + p, + position.x() + _inner.x(), + position.y() + _inner.y(), + _inner.width(), + &color); + if (_ripple->empty()) { + _ripple.reset(); + } + } + const auto textLeft = position.x() + _inner.x() + st::replyCornerTextPadding.left(); @@ -334,6 +351,30 @@ void Manager::remove(FullMsgId context) { if (_buttonContext == context) { _buttonContext = {}; _button = nullptr; + _ripple = nullptr; + } +} + +void Manager::clickHandlerPressedChanged( + const ClickHandlerPtr &action, + bool pressed) { + if (action != _link || !_button) { + return; + } + if (pressed) { + const auto inner = buttonInner(); + if (!_ripple) { + const auto mask = Ui::RippleAnimation::RoundRectMask( + inner.size(), + inner.height() / 2); + _ripple = std::make_unique( + st::defaultRippleAnimation, + mask, + [=] { if (_button) _buttonUpdate(_button->geometry()); }); + } + _ripple->add(_lastPointer - inner.topLeft()); + } else if (_ripple) { + _ripple->lastStop(); } } diff --git a/Telegram/SourceFiles/history/view/history_view_reply_button.h b/Telegram/SourceFiles/history/view/history_view_reply_button.h index 37d33bd95f..77223a467f 100644 --- a/Telegram/SourceFiles/history/view/history_view_reply_button.h +++ b/Telegram/SourceFiles/history/view/history_view_reply_button.h @@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/text/text.h" namespace Ui { +class RippleAnimation; struct ChatPaintContext; } // namespace Ui @@ -93,7 +94,9 @@ private: }; -class Manager final : public base::has_weak_ptr { +class Manager final + : public base::has_weak_ptr + , public ClickHandlerHost { public: Manager(Fn buttonUpdate); ~Manager(); @@ -103,6 +106,11 @@ public: [[nodiscard]] TextState buttonTextState(QPoint position) const; void remove(FullMsgId context); +protected: + void clickHandlerPressedChanged( + const ClickHandlerPtr &action, + bool pressed) override; + private: void showButtonDelayed(); [[nodiscard]] bool overCurrentButton(QPoint position) const; @@ -136,6 +144,8 @@ private: std::vector> _buttonHiding; Ui::Text::String _text; + std::unique_ptr _ripple; + QPoint _lastPointer; };