From 71d52d26c35a984bd712ed9f4515d1356450732e Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 29 Dec 2021 14:25:10 +0300 Subject: [PATCH] Show react button and dropdown with a delay. --- .../history/history_inner_widget.cpp | 1 + .../view/history_view_react_button.cpp | 80 ++++++++++++++----- .../history/view/history_view_react_button.h | 8 ++ 3 files changed, 68 insertions(+), 21 deletions(-) diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 397607d18..74228d61d 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -2991,6 +2991,7 @@ auto HistoryInner::reactionButtonParameters( ).translated({ 0, itemTop(view) }); result.visibleTop = _visibleAreaTop; result.visibleBottom = _visibleAreaBottom; + result.globalPointer = _mousePosition; return result; } diff --git a/Telegram/SourceFiles/history/view/history_view_react_button.cpp b/Telegram/SourceFiles/history/view/history_view_react_button.cpp index 8f5ad63ce..0f3cacbfb 100644 --- a/Telegram/SourceFiles/history/view/history_view_react_button.cpp +++ b/Telegram/SourceFiles/history/view/history_view_react_button.cpp @@ -30,6 +30,8 @@ constexpr auto kShadowCacheIndex = 0; constexpr auto kEmojiCacheIndex = 1; constexpr auto kMaskCacheIndex = 2; constexpr auto kCacheColumsCount = 3; +constexpr auto kButtonShowDelay = crl::time(300); +constexpr auto kButtonExpandDelay = crl::time(300); [[nodiscard]] QPoint LocalPosition(not_null e) { #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) @@ -81,7 +83,8 @@ Button::Button( ButtonParameters parameters) : _update(std::move(update)) , _collapsed(QPoint(), CountOuterSize()) -, _finalHeight(_collapsed.height()) { +, _finalHeight(_collapsed.height()) +, _expandTimer([=] { applyState(State::Inside, _update); }) { applyParameters(parameters, nullptr); } @@ -145,7 +148,19 @@ void Button::applyParameters( if (_state != State::Inside && !_heightAnimation.animating()) { updateExpandDirection(parameters); } - const auto state = inside + const auto delayInside = inside && (_state != State::Inside); + if (!delayInside) { + _expandTimer.cancel(); + _lastGlobalPosition = std::nullopt; + } else { + const auto globalPositionChanged = _lastGlobalPosition + && (*_lastGlobalPosition != parameters.globalPointer); + if (globalPositionChanged || _state == State::Hidden) { + _expandTimer.callOnce(kButtonExpandDelay); + } + _lastGlobalPosition = parameters.globalPointer; + } + const auto state = (inside && !delayInside) ? State::Inside : active ? State::Active @@ -256,10 +271,11 @@ float64 Button::currentScale() const { Manager::Manager( QWidget *wheelEventsTarget, Fn buttonUpdate) - : _outer(CountOuterSize()) - , _inner(QRectF({}, st::reactionCornerSize)) - , _innerActive(QRect({}, CountMaxSizeWithMargins({}))) - , _buttonUpdate(std::move(buttonUpdate)) { +: _outer(CountOuterSize()) +, _inner(QRectF({}, st::reactionCornerSize)) +, _innerActive(QRect({}, CountMaxSizeWithMargins({}))) +, _buttonShowTimer([=] { showButtonDelayed(); }) +, _buttonUpdate(std::move(buttonUpdate)) { _inner.translate(QRectF({}, _outer).center() - _inner.center()); _innerActive.translate( QRect({}, _outer).center() - _innerActive.center()); @@ -290,6 +306,18 @@ Manager::Manager( if (wheelEventsTarget) { stealWheelEvents(wheelEventsTarget); } + + _createChooseCallback = [=](QString emoji) { + return [=] { + if (const auto context = _buttonContext) { + updateButton({}); + _chosen.fire({ + .context = context, + .emoji = emoji, + }); + } + }; + }; } void Manager::stealWheelEvents(not_null target) { @@ -304,19 +332,36 @@ void Manager::stealWheelEvents(not_null target) { Manager::~Manager() = default; void Manager::updateButton(ButtonParameters parameters) { - if (_button && _buttonContext != parameters.context) { - _button->applyState(ButtonState::Hidden); - _buttonHiding.push_back(std::move(_button)); + const auto contextChanged = (_buttonContext != parameters.context); + if (contextChanged) { + if (_button) { + _button->applyState(ButtonState::Hidden); + _buttonHiding.push_back(std::move(_button)); + } + _buttonShowTimer.cancel(); + _scheduledParameters = std::nullopt; } _buttonContext = parameters.context; parameters.reactionsCount = _list.size(); if (!_buttonContext || _list.empty()) { return; - } else if (!_button) { - _button = std::make_unique