mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Show react button and dropdown with a delay.
This commit is contained in:
parent
87e97ad533
commit
71d52d26c3
3 changed files with 68 additions and 21 deletions
|
@ -2991,6 +2991,7 @@ auto HistoryInner::reactionButtonParameters(
|
||||||
).translated({ 0, itemTop(view) });
|
).translated({ 0, itemTop(view) });
|
||||||
result.visibleTop = _visibleAreaTop;
|
result.visibleTop = _visibleAreaTop;
|
||||||
result.visibleBottom = _visibleAreaBottom;
|
result.visibleBottom = _visibleAreaBottom;
|
||||||
|
result.globalPointer = _mousePosition;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,8 @@ constexpr auto kShadowCacheIndex = 0;
|
||||||
constexpr auto kEmojiCacheIndex = 1;
|
constexpr auto kEmojiCacheIndex = 1;
|
||||||
constexpr auto kMaskCacheIndex = 2;
|
constexpr auto kMaskCacheIndex = 2;
|
||||||
constexpr auto kCacheColumsCount = 3;
|
constexpr auto kCacheColumsCount = 3;
|
||||||
|
constexpr auto kButtonShowDelay = crl::time(300);
|
||||||
|
constexpr auto kButtonExpandDelay = crl::time(300);
|
||||||
|
|
||||||
[[nodiscard]] QPoint LocalPosition(not_null<QWheelEvent*> e) {
|
[[nodiscard]] QPoint LocalPosition(not_null<QWheelEvent*> e) {
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
@ -81,7 +83,8 @@ Button::Button(
|
||||||
ButtonParameters parameters)
|
ButtonParameters parameters)
|
||||||
: _update(std::move(update))
|
: _update(std::move(update))
|
||||||
, _collapsed(QPoint(), CountOuterSize())
|
, _collapsed(QPoint(), CountOuterSize())
|
||||||
, _finalHeight(_collapsed.height()) {
|
, _finalHeight(_collapsed.height())
|
||||||
|
, _expandTimer([=] { applyState(State::Inside, _update); }) {
|
||||||
applyParameters(parameters, nullptr);
|
applyParameters(parameters, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,7 +148,19 @@ void Button::applyParameters(
|
||||||
if (_state != State::Inside && !_heightAnimation.animating()) {
|
if (_state != State::Inside && !_heightAnimation.animating()) {
|
||||||
updateExpandDirection(parameters);
|
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
|
? State::Inside
|
||||||
: active
|
: active
|
||||||
? State::Active
|
? State::Active
|
||||||
|
@ -256,10 +271,11 @@ float64 Button::currentScale() const {
|
||||||
Manager::Manager(
|
Manager::Manager(
|
||||||
QWidget *wheelEventsTarget,
|
QWidget *wheelEventsTarget,
|
||||||
Fn<void(QRect)> buttonUpdate)
|
Fn<void(QRect)> buttonUpdate)
|
||||||
: _outer(CountOuterSize())
|
: _outer(CountOuterSize())
|
||||||
, _inner(QRectF({}, st::reactionCornerSize))
|
, _inner(QRectF({}, st::reactionCornerSize))
|
||||||
, _innerActive(QRect({}, CountMaxSizeWithMargins({})))
|
, _innerActive(QRect({}, CountMaxSizeWithMargins({})))
|
||||||
, _buttonUpdate(std::move(buttonUpdate)) {
|
, _buttonShowTimer([=] { showButtonDelayed(); })
|
||||||
|
, _buttonUpdate(std::move(buttonUpdate)) {
|
||||||
_inner.translate(QRectF({}, _outer).center() - _inner.center());
|
_inner.translate(QRectF({}, _outer).center() - _inner.center());
|
||||||
_innerActive.translate(
|
_innerActive.translate(
|
||||||
QRect({}, _outer).center() - _innerActive.center());
|
QRect({}, _outer).center() - _innerActive.center());
|
||||||
|
@ -290,6 +306,18 @@ Manager::Manager(
|
||||||
if (wheelEventsTarget) {
|
if (wheelEventsTarget) {
|
||||||
stealWheelEvents(wheelEventsTarget);
|
stealWheelEvents(wheelEventsTarget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_createChooseCallback = [=](QString emoji) {
|
||||||
|
return [=] {
|
||||||
|
if (const auto context = _buttonContext) {
|
||||||
|
updateButton({});
|
||||||
|
_chosen.fire({
|
||||||
|
.context = context,
|
||||||
|
.emoji = emoji,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::stealWheelEvents(not_null<QWidget*> target) {
|
void Manager::stealWheelEvents(not_null<QWidget*> target) {
|
||||||
|
@ -304,19 +332,36 @@ void Manager::stealWheelEvents(not_null<QWidget*> target) {
|
||||||
Manager::~Manager() = default;
|
Manager::~Manager() = default;
|
||||||
|
|
||||||
void Manager::updateButton(ButtonParameters parameters) {
|
void Manager::updateButton(ButtonParameters parameters) {
|
||||||
if (_button && _buttonContext != parameters.context) {
|
const auto contextChanged = (_buttonContext != parameters.context);
|
||||||
_button->applyState(ButtonState::Hidden);
|
if (contextChanged) {
|
||||||
_buttonHiding.push_back(std::move(_button));
|
if (_button) {
|
||||||
|
_button->applyState(ButtonState::Hidden);
|
||||||
|
_buttonHiding.push_back(std::move(_button));
|
||||||
|
}
|
||||||
|
_buttonShowTimer.cancel();
|
||||||
|
_scheduledParameters = std::nullopt;
|
||||||
}
|
}
|
||||||
_buttonContext = parameters.context;
|
_buttonContext = parameters.context;
|
||||||
parameters.reactionsCount = _list.size();
|
parameters.reactionsCount = _list.size();
|
||||||
if (!_buttonContext || _list.empty()) {
|
if (!_buttonContext || _list.empty()) {
|
||||||
return;
|
return;
|
||||||
} else if (!_button) {
|
} else if (_button) {
|
||||||
_button = std::make_unique<Button>(_buttonUpdate, parameters);
|
|
||||||
} else {
|
|
||||||
_button->applyParameters(parameters);
|
_button->applyParameters(parameters);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
const auto globalPositionChanged = _scheduledParameters
|
||||||
|
&& (_scheduledParameters->globalPointer != parameters.globalPointer);
|
||||||
|
const auto positionChanged = _scheduledParameters
|
||||||
|
&& (_scheduledParameters->pointer != parameters.pointer);
|
||||||
|
_scheduledParameters = parameters;
|
||||||
|
if ((_buttonShowTimer.isActive() && positionChanged)
|
||||||
|
|| globalPositionChanged) {
|
||||||
|
_buttonShowTimer.callOnce(kButtonShowDelay);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Manager::showButtonDelayed() {
|
||||||
|
_button = std::make_unique<Button>(_buttonUpdate, *_scheduledParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Manager::applyList(std::vector<Data::Reaction> list) {
|
void Manager::applyList(std::vector<Data::Reaction> list) {
|
||||||
|
@ -458,17 +503,10 @@ ClickHandlerPtr Manager::resolveButtonLink(
|
||||||
if (i != end(_reactionsLinks)) {
|
if (i != end(_reactionsLinks)) {
|
||||||
return i->second;
|
return i->second;
|
||||||
}
|
}
|
||||||
const auto handler = crl::guard(this, [=] {
|
|
||||||
if (_buttonContext) {
|
|
||||||
_chosen.fire({
|
|
||||||
.context = _buttonContext,
|
|
||||||
.emoji = emoji,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return _reactionsLinks.emplace(
|
return _reactionsLinks.emplace(
|
||||||
emoji,
|
emoji,
|
||||||
std::make_shared<LambdaClickHandler>(handler)
|
std::make_shared<LambdaClickHandler>(
|
||||||
|
crl::guard(this, _createChooseCallback(emoji)))
|
||||||
).first->second;
|
).first->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ struct ButtonParameters {
|
||||||
FullMsgId context;
|
FullMsgId context;
|
||||||
QPoint center;
|
QPoint center;
|
||||||
QPoint pointer;
|
QPoint pointer;
|
||||||
|
QPoint globalPointer;
|
||||||
ButtonStyle style = ButtonStyle::Incoming;
|
ButtonStyle style = ButtonStyle::Incoming;
|
||||||
int reactionsCount = 1;
|
int reactionsCount = 1;
|
||||||
int visibleTop = 0;
|
int visibleTop = 0;
|
||||||
|
@ -104,6 +105,9 @@ private:
|
||||||
ExpandDirection _expandDirection = ExpandDirection::Up;
|
ExpandDirection _expandDirection = ExpandDirection::Up;
|
||||||
ButtonStyle _style = ButtonStyle::Incoming;
|
ButtonStyle _style = ButtonStyle::Incoming;
|
||||||
|
|
||||||
|
base::Timer _expandTimer;
|
||||||
|
std::optional<QPoint> _lastGlobalPosition;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class Manager final : public base::has_weak_ptr {
|
class Manager final : public base::has_weak_ptr {
|
||||||
|
@ -137,6 +141,7 @@ private:
|
||||||
};
|
};
|
||||||
static constexpr auto kFramesCount = 30;
|
static constexpr auto kFramesCount = 30;
|
||||||
|
|
||||||
|
void showButtonDelayed();
|
||||||
void stealWheelEvents(not_null<QWidget*> target);
|
void stealWheelEvents(not_null<QWidget*> target);
|
||||||
|
|
||||||
[[nodiscard]] bool overCurrentButton(QPoint position) const;
|
[[nodiscard]] bool overCurrentButton(QPoint position) const;
|
||||||
|
@ -223,11 +228,14 @@ private:
|
||||||
OtherReactionImage> _otherReactions;
|
OtherReactionImage> _otherReactions;
|
||||||
rpl::lifetime _otherReactionsLifetime;
|
rpl::lifetime _otherReactionsLifetime;
|
||||||
|
|
||||||
|
std::optional<ButtonParameters> _scheduledParameters;
|
||||||
|
base::Timer _buttonShowTimer;
|
||||||
const Fn<void(QRect)> _buttonUpdate;
|
const Fn<void(QRect)> _buttonUpdate;
|
||||||
std::unique_ptr<Button> _button;
|
std::unique_ptr<Button> _button;
|
||||||
std::vector<std::unique_ptr<Button>> _buttonHiding;
|
std::vector<std::unique_ptr<Button>> _buttonHiding;
|
||||||
FullMsgId _buttonContext;
|
FullMsgId _buttonContext;
|
||||||
mutable base::flat_map<QString, ClickHandlerPtr> _reactionsLinks;
|
mutable base::flat_map<QString, ClickHandlerPtr> _reactionsLinks;
|
||||||
|
Fn<Fn<void()>(QString)> _createChooseCallback;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue