Show / hide reactions selector.

This commit is contained in:
John Preston 2021-12-17 00:21:18 +04:00
parent 35378e717a
commit 68d45a2c08
4 changed files with 52 additions and 18 deletions

View file

@ -1454,6 +1454,7 @@ void HistoryInner::itemRemoved(not_null<const HistoryItem*> item) {
} }
_animatedStickersPlayed.remove(item); _animatedStickersPlayed.remove(item);
_reactionsManager->remove(item->fullId());
auto i = _selected.find(item); auto i = _selected.find(item);
if (i != _selected.cend()) { if (i != _selected.cend()) {
@ -3034,7 +3035,8 @@ void HistoryInner::mouseActionUpdate() {
&& (view == App::hoveredItem()) && (view == App::hoveredItem())
&& !_selected.empty() && !_selected.empty()
&& (_selected.cbegin()->second != FullSelection); && (_selected.cbegin()->second != FullSelection);
if (reactionView && reactionState.link) { const auto overReaction = reactionView && reactionState.link;
if (overReaction) {
dragState = reactionState; dragState = reactionState;
lnkhost = reactionView; lnkhost = reactionView;
_reactionsManager->showSelector([=](QPoint local) { _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); auto lnkChanged = ClickHandler::setActive(dragState.link, lnkhost);
if (lnkChanged || dragState.cursor != _mouseCursorState) { if (lnkChanged || dragState.cursor != _mouseCursorState) {
Ui::Tooltip::Hide(); Ui::Tooltip::Hide();

View file

@ -1793,6 +1793,7 @@ Reactions::ButtonParameters Message::reactionButtonParameters(
auto result = Reactions::ButtonParameters{ .context = data()->fullId() }; auto result = Reactions::ButtonParameters{ .context = data()->fullId() };
result.outbg = hasOutLayout(); result.outbg = hasOutLayout();
const auto geometry = countGeometry(); const auto geometry = countGeometry();
result.pointer = position;
result.center = geometry.topLeft() result.center = geometry.topLeft()
+ QPoint(geometry.width(), geometry.height()) + QPoint(geometry.width(), geometry.height())
+ st::reactionCornerCenter; + st::reactionCornerCenter;

View file

@ -370,11 +370,8 @@ void Selector::toggle(bool shown, anim::type animated) {
Manager::Manager(QWidget *selectorParent, Fn<void(QRect)> buttonUpdate) Manager::Manager(QWidget *selectorParent, Fn<void(QRect)> buttonUpdate)
: _outer(CountOuterSize()) : _outer(CountOuterSize())
, _inner(QRectF( , _inner(QRectF({}, st::reactionCornerSize))
(_outer.width() - st::reactionCornerSize.width()) / 2., , _innerActive(QRect({}, CountMaxSizeWithMargins({})))
(_outer.height() - st::reactionCornerSize.height()) / 2.,
st::reactionCornerSize.width(),
st::reactionCornerSize.height()))
, _buttonUpdate(std::move(buttonUpdate)) , _buttonUpdate(std::move(buttonUpdate))
, _buttonLink(std::make_shared<LambdaClickHandler>(crl::guard(this, [=] { , _buttonLink(std::make_shared<LambdaClickHandler>(crl::guard(this, [=] {
if (_buttonContext && !_list.empty()) { if (_buttonContext && !_list.empty()) {
@ -385,6 +382,10 @@ Manager::Manager(QWidget *selectorParent, Fn<void(QRect)> buttonUpdate)
} }
}))) })))
, _selectorParent(selectorParent) { , _selectorParent(selectorParent) {
_inner.translate(QRectF({}, _outer).center() - _inner.center());
_innerActive.translate(
QRect({}, _outer).center() - _innerActive.center());
const auto ratio = style::DevicePixelRatio(); const auto ratio = style::DevicePixelRatio();
_cacheInOut = QImage( _cacheInOut = QImage(
_outer.width() * 2 * ratio, _outer.width() * 2 * ratio,
@ -407,11 +408,17 @@ Manager::~Manager() = default;
void Manager::showButton(ButtonParameters parameters) { void Manager::showButton(ButtonParameters parameters) {
if (_button && _buttonContext != parameters.context) { if (_button && _buttonContext != parameters.context) {
if (!parameters.context
&& _selector
&& _selectorContext == _buttonContext) {
return;
}
_button->applyState(ButtonState::Hidden); _button->applyState(ButtonState::Hidden);
_buttonHiding.push_back(std::move(_button)); _buttonHiding.push_back(std::move(_button));
} }
_buttonContext = parameters.context; _buttonContext = parameters.context;
if (!_buttonContext || _list.size() < 2) { if (!_buttonContext || _list.size() < 2) {
hideSelectors(anim::type::normal);
return; return;
} }
if (!_button) { if (!_button) {
@ -477,21 +484,33 @@ void Manager::paintButtons(Painter &p, const PaintContext &context) {
} }
TextState Manager::buttonTextState(QPoint position) const { TextState Manager::buttonTextState(QPoint position) const {
if (const auto current = _button.get()) { if (overCurrentButton(position)) {
const auto geometry = current->geometry(); auto result = TextState(nullptr, _buttonLink);
if (geometry.contains(position)) { result.itemId = _buttonContext;
const auto maxInner = QRect({}, CountMaxSizeWithMargins({})); return result;
const auto shift = geometry.center() - maxInner.center();
if (maxInner.translated(shift).contains(position)) {
auto result = TextState(nullptr, _buttonLink);
result.itemId = _buttonContext;
return result;
}
}
} }
return {}; 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( void Manager::paintButton(
Painter &p, Painter &p,
const PaintContext &context, const PaintContext &context,
@ -687,7 +706,8 @@ void Manager::showSelector(Fn<QPoint(QPoint)> mapToGlobal) {
if (!_button) { if (!_button) {
showSelector({}, {}); showSelector({}, {});
} else { } else {
const auto geometry = _button->geometry(); const auto position = _button->geometry().topLeft();
const auto geometry = _innerActive.translated(position);
showSelector( showSelector(
_buttonContext, _buttonContext,
{ mapToGlobal(geometry.topLeft()), geometry.size() }); { mapToGlobal(geometry.topLeft()), geometry.size() });
@ -726,9 +746,11 @@ void Manager::hideSelectors(anim::type animated) {
if (animated == anim::type::instant) { if (animated == anim::type::instant) {
_selectorHiding.clear(); _selectorHiding.clear();
_selector = nullptr; _selector = nullptr;
_selectorContext = {};
} else if (_selector) { } else if (_selector) {
_selector->toggle(false, anim::type::normal); _selector->toggle(false, anim::type::normal);
_selectorHiding.push_back(std::move(_selector)); _selectorHiding.push_back(std::move(_selector));
_selectorContext = {};
} }
} }

View file

@ -77,11 +77,13 @@ struct ButtonParameters {
[[nodiscard]] ButtonParameters translated(QPoint delta) const { [[nodiscard]] ButtonParameters translated(QPoint delta) const {
auto result = *this; auto result = *this;
result.center += delta; result.center += delta;
result.pointer += delta;
return result; return result;
} }
FullMsgId context; FullMsgId context;
QPoint center; QPoint center;
QPoint pointer;
ButtonStyle style = ButtonStyle::Bubble; ButtonStyle style = ButtonStyle::Bubble;
bool inside = false; bool inside = false;
bool active = false; bool active = false;
@ -158,6 +160,7 @@ public:
void showButton(ButtonParameters parameters); void showButton(ButtonParameters parameters);
void paintButtons(Painter &p, const PaintContext &context); void paintButtons(Painter &p, const PaintContext &context);
[[nodiscard]] TextState buttonTextState(QPoint position) const; [[nodiscard]] TextState buttonTextState(QPoint position) const;
void remove(FullMsgId context);
void showSelector(Fn<QPoint(QPoint)> mapToGlobal); void showSelector(Fn<QPoint(QPoint)> mapToGlobal);
void showSelector(FullMsgId context, QRect globalButtonArea); void showSelector(FullMsgId context, QRect globalButtonArea);
@ -175,6 +178,8 @@ public:
private: private:
static constexpr auto kFramesCount = 30; static constexpr auto kFramesCount = 30;
[[nodiscard]] bool overCurrentButton(QPoint position) const;
void removeStaleButtons(); void removeStaleButtons();
void paintButton( void paintButton(
Painter &p, Painter &p,
@ -206,6 +211,7 @@ private:
std::vector<Data::Reaction> _list; std::vector<Data::Reaction> _list;
QSize _outer; QSize _outer;
QRectF _inner; QRectF _inner;
QRect _innerActive;
QImage _cacheInOut; QImage _cacheInOut;
QImage _cacheParts; QImage _cacheParts;
QImage _shadowBuffer; QImage _shadowBuffer;