diff --git a/Telegram/SourceFiles/history/history_inner_widget.cpp b/Telegram/SourceFiles/history/history_inner_widget.cpp index 28ffda103..7554b2805 100644 --- a/Telegram/SourceFiles/history/history_inner_widget.cpp +++ b/Telegram/SourceFiles/history/history_inner_widget.cpp @@ -1454,6 +1454,7 @@ void HistoryInner::itemRemoved(not_null item) { } _animatedStickersPlayed.remove(item); + _reactionsManager->remove(item->fullId()); auto i = _selected.find(item); if (i != _selected.cend()) { @@ -3034,7 +3035,8 @@ void HistoryInner::mouseActionUpdate() { && (view == App::hoveredItem()) && !_selected.empty() && (_selected.cbegin()->second != FullSelection); - if (reactionView && reactionState.link) { + const auto overReaction = reactionView && reactionState.link; + if (overReaction) { dragState = reactionState; lnkhost = reactionView; _reactionsManager->showSelector([=](QPoint local) { @@ -3142,6 +3144,9 @@ void HistoryInner::mouseActionUpdate() { } } } + if (!overReaction) { + _reactionsManager->hideSelectors(anim::type::normal); + } auto lnkChanged = ClickHandler::setActive(dragState.link, lnkhost); if (lnkChanged || dragState.cursor != _mouseCursorState) { Ui::Tooltip::Hide(); diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index 6487ce192..160528e27 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -1793,6 +1793,7 @@ Reactions::ButtonParameters Message::reactionButtonParameters( auto result = Reactions::ButtonParameters{ .context = data()->fullId() }; result.outbg = hasOutLayout(); const auto geometry = countGeometry(); + result.pointer = position; result.center = geometry.topLeft() + QPoint(geometry.width(), geometry.height()) + st::reactionCornerCenter; diff --git a/Telegram/SourceFiles/history/view/history_view_reactions.cpp b/Telegram/SourceFiles/history/view/history_view_reactions.cpp index 6f1116f2c..4919c189a 100644 --- a/Telegram/SourceFiles/history/view/history_view_reactions.cpp +++ b/Telegram/SourceFiles/history/view/history_view_reactions.cpp @@ -370,11 +370,8 @@ void Selector::toggle(bool shown, anim::type animated) { Manager::Manager(QWidget *selectorParent, Fn buttonUpdate) : _outer(CountOuterSize()) -, _inner(QRectF( - (_outer.width() - st::reactionCornerSize.width()) / 2., - (_outer.height() - st::reactionCornerSize.height()) / 2., - st::reactionCornerSize.width(), - st::reactionCornerSize.height())) +, _inner(QRectF({}, st::reactionCornerSize)) +, _innerActive(QRect({}, CountMaxSizeWithMargins({}))) , _buttonUpdate(std::move(buttonUpdate)) , _buttonLink(std::make_shared(crl::guard(this, [=] { if (_buttonContext && !_list.empty()) { @@ -385,6 +382,10 @@ Manager::Manager(QWidget *selectorParent, Fn buttonUpdate) } }))) , _selectorParent(selectorParent) { + _inner.translate(QRectF({}, _outer).center() - _inner.center()); + _innerActive.translate( + QRect({}, _outer).center() - _innerActive.center()); + const auto ratio = style::DevicePixelRatio(); _cacheInOut = QImage( _outer.width() * 2 * ratio, @@ -407,11 +408,17 @@ Manager::~Manager() = default; void Manager::showButton(ButtonParameters parameters) { if (_button && _buttonContext != parameters.context) { + if (!parameters.context + && _selector + && _selectorContext == _buttonContext) { + return; + } _button->applyState(ButtonState::Hidden); _buttonHiding.push_back(std::move(_button)); } _buttonContext = parameters.context; if (!_buttonContext || _list.size() < 2) { + hideSelectors(anim::type::normal); return; } if (!_button) { @@ -477,21 +484,33 @@ void Manager::paintButtons(Painter &p, const PaintContext &context) { } TextState Manager::buttonTextState(QPoint position) const { - if (const auto current = _button.get()) { - const auto geometry = current->geometry(); - if (geometry.contains(position)) { - const auto maxInner = QRect({}, CountMaxSizeWithMargins({})); - const auto shift = geometry.center() - maxInner.center(); - if (maxInner.translated(shift).contains(position)) { - auto result = TextState(nullptr, _buttonLink); - result.itemId = _buttonContext; - return result; - } - } + if (overCurrentButton(position)) { + auto result = TextState(nullptr, _buttonLink); + result.itemId = _buttonContext; + return result; } return {}; } +bool Manager::overCurrentButton(QPoint position) const { + if (!_button) { + return false; + } + const auto geometry = _button->geometry(); + return _innerActive.translated(geometry.topLeft()).contains(position); +} + +void Manager::remove(FullMsgId context) { + if (_buttonContext == context) { + _buttonContext = {}; + _button = nullptr; + } + if (_selectorContext == context) { + _selectorContext = {}; + _selector = nullptr; + } +} + void Manager::paintButton( Painter &p, const PaintContext &context, @@ -687,7 +706,8 @@ void Manager::showSelector(Fn mapToGlobal) { if (!_button) { showSelector({}, {}); } else { - const auto geometry = _button->geometry(); + const auto position = _button->geometry().topLeft(); + const auto geometry = _innerActive.translated(position); showSelector( _buttonContext, { mapToGlobal(geometry.topLeft()), geometry.size() }); @@ -726,9 +746,11 @@ void Manager::hideSelectors(anim::type animated) { if (animated == anim::type::instant) { _selectorHiding.clear(); _selector = nullptr; + _selectorContext = {}; } else if (_selector) { _selector->toggle(false, anim::type::normal); _selectorHiding.push_back(std::move(_selector)); + _selectorContext = {}; } } diff --git a/Telegram/SourceFiles/history/view/history_view_reactions.h b/Telegram/SourceFiles/history/view/history_view_reactions.h index acaa56a33..0bdc3d0ea 100644 --- a/Telegram/SourceFiles/history/view/history_view_reactions.h +++ b/Telegram/SourceFiles/history/view/history_view_reactions.h @@ -77,11 +77,13 @@ struct ButtonParameters { [[nodiscard]] ButtonParameters translated(QPoint delta) const { auto result = *this; result.center += delta; + result.pointer += delta; return result; } FullMsgId context; QPoint center; + QPoint pointer; ButtonStyle style = ButtonStyle::Bubble; bool inside = false; bool active = false; @@ -158,6 +160,7 @@ public: void showButton(ButtonParameters parameters); void paintButtons(Painter &p, const PaintContext &context); [[nodiscard]] TextState buttonTextState(QPoint position) const; + void remove(FullMsgId context); void showSelector(Fn mapToGlobal); void showSelector(FullMsgId context, QRect globalButtonArea); @@ -175,6 +178,8 @@ public: private: static constexpr auto kFramesCount = 30; + [[nodiscard]] bool overCurrentButton(QPoint position) const; + void removeStaleButtons(); void paintButton( Painter &p, @@ -206,6 +211,7 @@ private: std::vector _list; QSize _outer; QRectF _inner; + QRect _innerActive; QImage _cacheInOut; QImage _cacheParts; QImage _shadowBuffer;