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);
_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();

View file

@ -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;

View file

@ -370,11 +370,8 @@ void Selector::toggle(bool shown, anim::type animated) {
Manager::Manager(QWidget *selectorParent, Fn<void(QRect)> 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<LambdaClickHandler>(crl::guard(this, [=] {
if (_buttonContext && !_list.empty()) {
@ -385,6 +382,10 @@ Manager::Manager(QWidget *selectorParent, Fn<void(QRect)> 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<QPoint(QPoint)> 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 = {};
}
}

View file

@ -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<QPoint(QPoint)> 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<Data::Reaction> _list;
QSize _outer;
QRectF _inner;
QRect _innerActive;
QImage _cacheInOut;
QImage _cacheParts;
QImage _shadowBuffer;