Add shake-on-error animation to CallMuteButton.
This commit is contained in:
parent
300c5a9c66
commit
3bd98ac564
4 changed files with 92 additions and 16 deletions
|
|
@ -564,7 +564,7 @@ groupCallMemberActiveIcon: #8deb90; // group call active member icon
|
|||
groupCallMemberActiveStatus: #8deb90; // group call active member status text
|
||||
groupCallMemberInactiveIcon: #84888f; // group call inactive member icon
|
||||
groupCallMemberInactiveStatus: #61c0ff; // group call inactive member status text
|
||||
groupCallMemberMutedIcon: #ff4f4d; // group call muted by admin member icon
|
||||
groupCallMemberMutedIcon: #ed7372; // group call muted by admin member icon
|
||||
groupCallMemberNotJoinedStatus: #91979e; // group call non joined member status text
|
||||
groupCallIconFg: #ffffff; // group call mute / settings / leave icon
|
||||
groupCallLive1: #0dcc39; // group call live button color1
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ constexpr auto kOverrideColorBgAlpha = 76;
|
|||
constexpr auto kOverrideColorRippleAlpha = 50;
|
||||
|
||||
constexpr auto kSwitchStateDuration = 120;
|
||||
constexpr auto kShiftDuration = crl::time(300);
|
||||
|
||||
auto MuteBlobs() {
|
||||
return std::vector<Paint::Blobs::BlobData>{
|
||||
|
|
@ -315,12 +316,9 @@ void CallMuteButton::init() {
|
|||
_label->show();
|
||||
rpl::combine(
|
||||
_content->geometryValue(),
|
||||
_label->geometryValue()
|
||||
) | rpl::start_with_next([=](QRect my, QRect label) {
|
||||
_label->moveToLeft(
|
||||
my.x() + (my.width() - label.width()) / 2,
|
||||
my.y() + my.height() - label.height(),
|
||||
my.width());
|
||||
_label->sizeValue()
|
||||
) | rpl::start_with_next([=](QRect my, QSize size) {
|
||||
updateLabelGeometry(my, size);
|
||||
}, _label->lifetime());
|
||||
_label->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||
|
||||
|
|
@ -342,7 +340,7 @@ void CallMuteButton::init() {
|
|||
// State type.
|
||||
const auto previousType =
|
||||
lifetime().make_state<CallMuteButtonType>(_state.current().type);
|
||||
setEnableMouse(false);
|
||||
setHandleMouseState(HandleMouseState::Disabled);
|
||||
|
||||
const auto blobsInner = [&] {
|
||||
// The point of the circle at 45 degrees.
|
||||
|
|
@ -379,8 +377,10 @@ void CallMuteButton::init() {
|
|||
const auto previous = *previousType;
|
||||
*previousType = type;
|
||||
|
||||
if (IsInactive(type) && !IsInactive(previous)) {
|
||||
setEnableMouse(false);
|
||||
const auto mouseState = HandleMouseStateFromType(type);
|
||||
setHandleMouseState(HandleMouseState::Disabled);
|
||||
if (mouseState != HandleMouseState::Enabled) {
|
||||
setHandleMouseState(mouseState);
|
||||
}
|
||||
|
||||
const auto crossFrom = IsMuted(previous) ? 0. : 1.;
|
||||
|
|
@ -419,9 +419,7 @@ void CallMuteButton::init() {
|
|||
overridesColors(previous, type, value);
|
||||
|
||||
if (value == to) {
|
||||
if (!IsInactive(type) && IsInactive(previous)) {
|
||||
setEnableMouse(true);
|
||||
}
|
||||
setHandleMouseState(mouseState);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -463,6 +461,60 @@ void CallMuteButton::init() {
|
|||
}, _content->lifetime());
|
||||
}
|
||||
|
||||
void CallMuteButton::updateLabelGeometry() {
|
||||
updateLabelGeometry(_content->geometry(), _label->size());
|
||||
}
|
||||
|
||||
void CallMuteButton::updateLabelGeometry(QRect my, QSize size) {
|
||||
_label->moveToLeft(
|
||||
my.x() + (my.width() - size.width()) / 2 + _labelShakeShift,
|
||||
my.y() + my.height() - size.height(),
|
||||
my.width());
|
||||
}
|
||||
|
||||
void CallMuteButton::shake() {
|
||||
if (_shakeAnimation.animating()) {
|
||||
return;
|
||||
}
|
||||
const auto update = [=] {
|
||||
const auto fullProgress = _shakeAnimation.value(1.) * 6;
|
||||
const auto segment = std::clamp(int(std::floor(fullProgress)), 0, 5);
|
||||
const auto part = fullProgress - segment;
|
||||
const auto from = (segment == 0)
|
||||
? 0.
|
||||
: (segment == 1 || segment == 3 || segment == 5)
|
||||
? 1.
|
||||
: -1.;
|
||||
const auto to = (segment == 0 || segment == 2 || segment == 4)
|
||||
? 1.
|
||||
: (segment == 1 || segment == 3)
|
||||
? -1.
|
||||
: 0.;
|
||||
const auto shift = from * (1. - part) + to * part;
|
||||
_labelShakeShift = int(std::round(shift * st::shakeShift));
|
||||
updateLabelGeometry();
|
||||
};
|
||||
_shakeAnimation.start(
|
||||
update,
|
||||
0.,
|
||||
1.,
|
||||
kShiftDuration);
|
||||
}
|
||||
|
||||
CallMuteButton::HandleMouseState CallMuteButton::HandleMouseStateFromType(
|
||||
CallMuteButtonType type) {
|
||||
switch (type) {
|
||||
case CallMuteButtonType::Active:
|
||||
case CallMuteButtonType::Muted:
|
||||
return HandleMouseState::Enabled;
|
||||
case CallMuteButtonType::Connecting:
|
||||
return HandleMouseState::Disabled;
|
||||
case CallMuteButtonType::ForceMuted:
|
||||
return HandleMouseState::Blocked;
|
||||
}
|
||||
Unexpected("Type in HandleMouseStateFromType.");
|
||||
}
|
||||
|
||||
void CallMuteButton::setState(const CallMuteButtonState &state) {
|
||||
_state = state;
|
||||
}
|
||||
|
|
@ -516,8 +568,15 @@ void CallMuteButton::lower() {
|
|||
_blobs->lower();
|
||||
}
|
||||
|
||||
void CallMuteButton::setEnableMouse(bool value) {
|
||||
_content->setAttribute(Qt::WA_TransparentForMouseEvents, !value);
|
||||
void CallMuteButton::setHandleMouseState(HandleMouseState state) {
|
||||
if (_handleMouseState == state) {
|
||||
return;
|
||||
}
|
||||
_handleMouseState = state;
|
||||
const auto handle = (_handleMouseState != HandleMouseState::Disabled);
|
||||
const auto pointer = (_handleMouseState == HandleMouseState::Enabled);
|
||||
_content->setAttribute(Qt::WA_TransparentForMouseEvents, !handle);
|
||||
_content->setPointerCursor(pointer);
|
||||
}
|
||||
|
||||
void CallMuteButton::overridesColors(
|
||||
|
|
|
|||
|
|
@ -49,6 +49,8 @@ public:
|
|||
[[nodiscard]] QRect innerGeometry() const;
|
||||
void moveInner(QPoint position);
|
||||
|
||||
void shake();
|
||||
|
||||
void setVisible(bool visible);
|
||||
void show() {
|
||||
setVisible(true);
|
||||
|
|
@ -64,31 +66,44 @@ public:
|
|||
[[nodiscard]] rpl::lifetime &lifetime();
|
||||
|
||||
private:
|
||||
enum class HandleMouseState {
|
||||
Enabled,
|
||||
Blocked,
|
||||
Disabled,
|
||||
};
|
||||
void init();
|
||||
void overridesColors(
|
||||
CallMuteButtonType fromType,
|
||||
CallMuteButtonType toType,
|
||||
float64 progress);
|
||||
|
||||
void setEnableMouse(bool value);
|
||||
void setHandleMouseState(HandleMouseState state);
|
||||
void updateLabelGeometry(QRect my, QSize size);
|
||||
void updateLabelGeometry();
|
||||
|
||||
[[nodiscard]] static HandleMouseState HandleMouseStateFromType(
|
||||
CallMuteButtonType type);
|
||||
|
||||
rpl::variable<CallMuteButtonState> _state;
|
||||
float _level = 0.;
|
||||
float64 _crossLineProgress = 0.;
|
||||
rpl::variable<float64> _radialShowProgress = 0.;
|
||||
QRect _muteIconPosition;
|
||||
HandleMouseState _handleMouseState = HandleMouseState::Enabled;
|
||||
|
||||
const style::CallButton &_st;
|
||||
|
||||
const base::unique_qptr<BlobsWidget> _blobs;
|
||||
const base::unique_qptr<AbstractButton> _content;
|
||||
const base::unique_qptr<FlatLabel> _label;
|
||||
int _labelShakeShift = 0;
|
||||
|
||||
std::unique_ptr<InfiniteRadialAnimation> _radial;
|
||||
const base::flat_map<CallMuteButtonType, std::vector<QColor>> _colors;
|
||||
|
||||
CrossLineAnimation _crossLineMuteAnimation;
|
||||
Animations::Simple _switchAnimation;
|
||||
Animations::Simple _shakeAnimation;
|
||||
|
||||
rpl::event_stream<CallButtonColors> _colorOverrides;
|
||||
|
||||
|
|
|
|||
|
|
@ -1468,6 +1468,8 @@ callConnectingRadial: InfiniteRadialAnimation(defaultInfiniteRadialAnimation) {
|
|||
size: size(100px, 100px);
|
||||
}
|
||||
|
||||
shakeShift: 4px;
|
||||
|
||||
// Windows specific title
|
||||
|
||||
windowTitleButton: IconButton {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue