mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Make style of mute button customizable.
This commit is contained in:
parent
24c77a8956
commit
e0bfaad3a2
6 changed files with 326 additions and 158 deletions
|
@ -2010,6 +2010,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_group_call_force_muted_sub" = "You are in Listen Only mode";
|
"lng_group_call_force_muted_sub" = "You are in Listen Only mode";
|
||||||
"lng_group_call_raise_hand_tip" = "Click if you want to speak";
|
"lng_group_call_raise_hand_tip" = "Click if you want to speak";
|
||||||
"lng_group_call_raised_hand" = "You asked to speak";
|
"lng_group_call_raised_hand" = "You asked to speak";
|
||||||
|
"lng_group_call_raised_hand_small" = "Raised hand";
|
||||||
"lng_group_call_raised_hand_sub" = "We let the speakers know";
|
"lng_group_call_raised_hand_sub" = "We let the speakers know";
|
||||||
"lng_group_call_connecting" = "Connecting...";
|
"lng_group_call_connecting" = "Connecting...";
|
||||||
"lng_group_call_leave" = "Leave";
|
"lng_group_call_leave" = "Leave";
|
||||||
|
|
|
@ -175,6 +175,87 @@ callCameraUnmute: CallButton(callMicrophoneUnmute) {
|
||||||
}
|
}
|
||||||
callBottomShadowSize: 124px;
|
callBottomShadowSize: 124px;
|
||||||
|
|
||||||
|
CallMuteButton {
|
||||||
|
active: CallButton;
|
||||||
|
muted: CallButton;
|
||||||
|
labelAdditional: pixels;
|
||||||
|
sublabel: FlatLabel;
|
||||||
|
labelsSkip: pixels;
|
||||||
|
sublabelSkip: pixels;
|
||||||
|
lottieSize: size;
|
||||||
|
lottieTop: pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
callMuteButtonLabel: FlatLabel(defaultFlatLabel) {
|
||||||
|
textFg: groupCallMembersFg;
|
||||||
|
style: TextStyle(defaultTextStyle) {
|
||||||
|
font: font(14px);
|
||||||
|
linkFont: font(14px);
|
||||||
|
linkFontOver: font(14px underline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callMuteButtonActiveInner: IconButton {
|
||||||
|
width: 136px;
|
||||||
|
height: 165px;
|
||||||
|
}
|
||||||
|
callMuteButtonSmallActiveInner: IconButton {
|
||||||
|
width: 68px;
|
||||||
|
height: 79px;
|
||||||
|
}
|
||||||
|
callMuteButtonActive: CallButton {
|
||||||
|
button: callMuteButtonActiveInner;
|
||||||
|
bg: groupCallLive1;
|
||||||
|
bgSize: 100px;
|
||||||
|
bgPosition: point(18px, 18px);
|
||||||
|
outerRadius: 18px;
|
||||||
|
outerBg: callAnswerBgOuter;
|
||||||
|
label: callMuteButtonLabel;
|
||||||
|
}
|
||||||
|
callMuteButton: CallMuteButton {
|
||||||
|
active: callMuteButtonActive;
|
||||||
|
muted: CallButton(callMuteButtonActive) {
|
||||||
|
bg: groupCallMuted1;
|
||||||
|
label: callMuteButtonLabel;
|
||||||
|
}
|
||||||
|
labelAdditional: 5px;
|
||||||
|
sublabel: FlatLabel(defaultFlatLabel) {
|
||||||
|
textFg: groupCallMemberNotJoinedStatus;
|
||||||
|
}
|
||||||
|
labelsSkip: 5px;
|
||||||
|
sublabelSkip: 19px;
|
||||||
|
lottieSize: size(67px, 67px);
|
||||||
|
lottieTop: 35px;
|
||||||
|
}
|
||||||
|
callMuteButtonSmallActive: CallButton(callMuteButtonActive) {
|
||||||
|
button: callMuteButtonSmallActiveInner;
|
||||||
|
bgSize: 44px;
|
||||||
|
bgPosition: point(12px, 12px);
|
||||||
|
outerRadius: 12px;
|
||||||
|
label: callButtonLabel;
|
||||||
|
}
|
||||||
|
callMuteButtonSmall: CallMuteButton(callMuteButton) {
|
||||||
|
active: callMuteButtonSmallActive;
|
||||||
|
muted: CallButton(callMuteButtonSmallActive) {
|
||||||
|
bg: groupCallMuted1;
|
||||||
|
label: callButtonLabel;
|
||||||
|
}
|
||||||
|
labelsSkip: 0px;
|
||||||
|
sublabelSkip: 0px;
|
||||||
|
lottieSize: size(36px, 36px);
|
||||||
|
lottieTop: 17px;
|
||||||
|
}
|
||||||
|
|
||||||
|
callMuteMinorBlobMinRadius: 64px;
|
||||||
|
callMuteMinorBlobMaxRadius: 74px;
|
||||||
|
callMuteMajorBlobMinRadius: 67px;
|
||||||
|
callMuteMajorBlobMaxRadius: 77px;
|
||||||
|
callMuteBlobRadiusForDiameter: 100px;
|
||||||
|
|
||||||
|
callConnectingRadial: InfiniteRadialAnimation(defaultInfiniteRadialAnimation) {
|
||||||
|
color: lightButtonFg;
|
||||||
|
thickness: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
callName: FlatLabel(defaultFlatLabel) {
|
callName: FlatLabel(defaultFlatLabel) {
|
||||||
minWidth: 260px;
|
minWidth: 260px;
|
||||||
maxHeight: 30px;
|
maxHeight: 30px;
|
||||||
|
@ -442,8 +523,6 @@ callErrorToast: Toast(defaultToast) {
|
||||||
groupCallWidth: 380px;
|
groupCallWidth: 380px;
|
||||||
groupCallHeight: 580px;
|
groupCallHeight: 580px;
|
||||||
|
|
||||||
groupCallMuteButtonIconSize: size(67px, 67px);
|
|
||||||
groupCallMuteButtonIconTop: 35px;
|
|
||||||
groupCallRipple: RippleAnimation(defaultRippleAnimation) {
|
groupCallRipple: RippleAnimation(defaultRippleAnimation) {
|
||||||
color: groupCallMembersBgRipple;
|
color: groupCallMembersBgRipple;
|
||||||
}
|
}
|
||||||
|
|
|
@ -385,8 +385,10 @@ Panel::Panel(not_null<GroupCall*> call)
|
||||||
_window->body(),
|
_window->body(),
|
||||||
st::groupCallTitle))
|
st::groupCallTitle))
|
||||||
#endif // !Q_OS_MAC
|
#endif // !Q_OS_MAC
|
||||||
|
, _videoMode(true) // #TODO calls
|
||||||
, _mute(std::make_unique<Ui::CallMuteButton>(
|
, _mute(std::make_unique<Ui::CallMuteButton>(
|
||||||
widget(),
|
widget(),
|
||||||
|
st::callMuteButton,
|
||||||
Core::App().appDeactivatedValue(),
|
Core::App().appDeactivatedValue(),
|
||||||
Ui::CallMuteButtonState{
|
Ui::CallMuteButtonState{
|
||||||
.text = (_call->scheduleDate()
|
.text = (_call->scheduleDate()
|
||||||
|
@ -738,7 +740,8 @@ void Panel::setupRealMuteButtonState(not_null<Data::GroupCall*> real) {
|
||||||
_call->instanceStateValue(),
|
_call->instanceStateValue(),
|
||||||
real->scheduleDateValue(),
|
real->scheduleDateValue(),
|
||||||
real->scheduleStartSubscribedValue(),
|
real->scheduleStartSubscribedValue(),
|
||||||
Data::CanManageGroupCallValue(_peer)
|
Data::CanManageGroupCallValue(_peer),
|
||||||
|
_videoMode.value()
|
||||||
) | rpl::distinct_until_changed(
|
) | rpl::distinct_until_changed(
|
||||||
) | rpl::filter(
|
) | rpl::filter(
|
||||||
_2 != GroupCall::InstanceState::TransitionToRtc
|
_2 != GroupCall::InstanceState::TransitionToRtc
|
||||||
|
@ -747,7 +750,8 @@ void Panel::setupRealMuteButtonState(not_null<Data::GroupCall*> real) {
|
||||||
GroupCall::InstanceState state,
|
GroupCall::InstanceState state,
|
||||||
TimeId scheduleDate,
|
TimeId scheduleDate,
|
||||||
bool scheduleStartSubscribed,
|
bool scheduleStartSubscribed,
|
||||||
bool canManage) {
|
bool canManage,
|
||||||
|
bool videoMode) {
|
||||||
using Type = Ui::CallMuteButtonType;
|
using Type = Ui::CallMuteButtonType;
|
||||||
_mute->setState(Ui::CallMuteButtonState{
|
_mute->setState(Ui::CallMuteButtonState{
|
||||||
.text = (scheduleDate
|
.text = (scheduleDate
|
||||||
|
@ -759,13 +763,19 @@ void Panel::setupRealMuteButtonState(not_null<Data::GroupCall*> real) {
|
||||||
: state == GroupCall::InstanceState::Disconnected
|
: state == GroupCall::InstanceState::Disconnected
|
||||||
? tr::lng_group_call_connecting(tr::now)
|
? tr::lng_group_call_connecting(tr::now)
|
||||||
: mute == MuteState::ForceMuted
|
: mute == MuteState::ForceMuted
|
||||||
? tr::lng_group_call_force_muted(tr::now)
|
? (videoMode
|
||||||
|
? tr::lng_group_call_force_muted_small(tr::now)
|
||||||
|
: tr::lng_group_call_force_muted(tr::now))
|
||||||
: mute == MuteState::RaisedHand
|
: mute == MuteState::RaisedHand
|
||||||
? tr::lng_group_call_raised_hand(tr::now)
|
? (videoMode
|
||||||
|
? tr::lng_group_call_raised_hand_small(tr::now)
|
||||||
|
: tr::lng_group_call_raised_hand(tr::now))
|
||||||
: mute == MuteState::Muted
|
: mute == MuteState::Muted
|
||||||
? tr::lng_group_call_unmute(tr::now)
|
? tr::lng_group_call_unmute(tr::now)
|
||||||
: tr::lng_group_call_you_are_live(tr::now)),
|
: (videoMode
|
||||||
.subtext = (scheduleDate
|
? tr::lng_group_call_you_are_live_small(tr::now)
|
||||||
|
: tr::lng_group_call_you_are_live(tr::now))),
|
||||||
|
.subtext = ((scheduleDate || videoMode)
|
||||||
? QString()
|
? QString()
|
||||||
: state == GroupCall::InstanceState::Disconnected
|
: state == GroupCall::InstanceState::Disconnected
|
||||||
? QString()
|
? QString()
|
||||||
|
@ -1498,22 +1508,48 @@ void Panel::updateControlsGeometry() {
|
||||||
if (widget()->size().isEmpty() || (!_settings && !_share)) {
|
if (widget()->size().isEmpty() || (!_settings && !_share)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto muteTop = widget()->height() - st::groupCallMuteBottomSkip;
|
if (_videoMode.current()) {
|
||||||
const auto buttonsTop = widget()->height() - st::groupCallButtonBottomSkip;
|
_mute->setStyle(st::callMuteButtonSmall);
|
||||||
const auto muteSize = _mute->innerSize().width();
|
const auto buttonsTop = widget()->height()
|
||||||
const auto fullWidth = muteSize
|
- st::groupCallButtonBottomSkip;
|
||||||
+ 2 * (_settings ? _settings : _share)->width()
|
const auto muteSize = _mute->innerSize().width();
|
||||||
+ 2 * st::groupCallButtonSkip;
|
const auto fullWidth = muteSize
|
||||||
_mute->moveInner({ (widget()->width() - muteSize) / 2, muteTop });
|
+ 2 * (_settings ? _settings : _share)->width()
|
||||||
const auto leftButtonLeft = (widget()->width() - fullWidth) / 2;
|
+ 2 * st::groupCallButtonSkip;
|
||||||
if (_settings) {
|
const auto leftButtonLeft = (widget()->width() - fullWidth) / 2;
|
||||||
_settings->moveToLeft(leftButtonLeft, buttonsTop);
|
const auto addSkip = st::callMuteButtonSmall.active.outerRadius;
|
||||||
|
_mute->moveInner({ leftButtonLeft + addSkip, buttonsTop + addSkip });
|
||||||
|
if (_settings) {
|
||||||
|
_settings->moveToLeft(
|
||||||
|
(widget()->width() - _settings->width()) / 2,
|
||||||
|
buttonsTop);
|
||||||
|
}
|
||||||
|
if (_share) {
|
||||||
|
_share->moveToLeft(
|
||||||
|
(widget()->width() - _share->width()) / 2,
|
||||||
|
buttonsTop);
|
||||||
|
}
|
||||||
|
_hangup->moveToRight(leftButtonLeft, buttonsTop);
|
||||||
|
} else {
|
||||||
|
_mute->setStyle(st::callMuteButton);
|
||||||
|
const auto muteTop = widget()->height()
|
||||||
|
- st::groupCallMuteBottomSkip;
|
||||||
|
const auto buttonsTop = widget()->height()
|
||||||
|
- st::groupCallButtonBottomSkip;
|
||||||
|
const auto muteSize = _mute->innerSize().width();
|
||||||
|
const auto fullWidth = muteSize
|
||||||
|
+ 2 * (_settings ? _settings : _share)->width()
|
||||||
|
+ 2 * st::groupCallButtonSkip;
|
||||||
|
_mute->moveInner({ (widget()->width() - muteSize) / 2, muteTop });
|
||||||
|
const auto leftButtonLeft = (widget()->width() - fullWidth) / 2;
|
||||||
|
if (_settings) {
|
||||||
|
_settings->moveToLeft(leftButtonLeft, buttonsTop);
|
||||||
|
}
|
||||||
|
if (_share) {
|
||||||
|
_share->moveToLeft(leftButtonLeft, buttonsTop);
|
||||||
|
}
|
||||||
|
_hangup->moveToRight(leftButtonLeft, buttonsTop);
|
||||||
}
|
}
|
||||||
if (_share) {
|
|
||||||
_share->moveToLeft(leftButtonLeft, buttonsTop);
|
|
||||||
}
|
|
||||||
_hangup->moveToRight(leftButtonLeft, buttonsTop);
|
|
||||||
|
|
||||||
updateMembersGeometry();
|
updateMembersGeometry();
|
||||||
refreshTitle();
|
refreshTitle();
|
||||||
|
|
||||||
|
|
|
@ -144,9 +144,12 @@ private:
|
||||||
std::shared_ptr<Ui::GroupCallScheduledLeft> _countdownData;
|
std::shared_ptr<Ui::GroupCallScheduledLeft> _countdownData;
|
||||||
object_ptr<Ui::FlatLabel> _startsWhen = { nullptr };
|
object_ptr<Ui::FlatLabel> _startsWhen = { nullptr };
|
||||||
ChooseJoinAsProcess _joinAsProcess;
|
ChooseJoinAsProcess _joinAsProcess;
|
||||||
|
rpl::variable<bool> _videoMode;
|
||||||
|
|
||||||
object_ptr<Ui::CallButton> _settings = { nullptr };
|
object_ptr<Ui::CallButton> _settings = { nullptr };
|
||||||
object_ptr<Ui::CallButton> _share = { nullptr };
|
object_ptr<Ui::CallButton> _share = { nullptr };
|
||||||
|
object_ptr<Ui::CallButton> _video = { nullptr };
|
||||||
|
object_ptr<Ui::CallButton> _shareScreen = { nullptr };
|
||||||
std::unique_ptr<Ui::CallMuteButton> _mute;
|
std::unique_ptr<Ui::CallMuteButton> _mute;
|
||||||
object_ptr<Ui::CallButton> _hangup;
|
object_ptr<Ui::CallButton> _hangup;
|
||||||
Fn<void()> _shareLinkCallback;
|
Fn<void()> _shareLinkCallback;
|
||||||
|
|
|
@ -274,8 +274,10 @@ class BlobsWidget final : public RpWidget {
|
||||||
public:
|
public:
|
||||||
BlobsWidget(
|
BlobsWidget(
|
||||||
not_null<RpWidget*> parent,
|
not_null<RpWidget*> parent,
|
||||||
|
int diameter,
|
||||||
rpl::producer<bool> &&hideBlobs);
|
rpl::producer<bool> &&hideBlobs);
|
||||||
|
|
||||||
|
void setDiameter(int diameter);
|
||||||
void setLevel(float level);
|
void setLevel(float level);
|
||||||
void setBlobBrush(QBrush brush);
|
void setBlobBrush(QBrush brush);
|
||||||
void setGlowBrush(QBrush brush);
|
void setGlowBrush(QBrush brush);
|
||||||
|
@ -286,11 +288,12 @@ public:
|
||||||
void setSwitchConnectingProgress(float64 progress);
|
void setSwitchConnectingProgress(float64 progress);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init();
|
void init(int diameter);
|
||||||
|
void computeCircleRect();
|
||||||
|
|
||||||
Paint::Blobs _blobs;
|
Paint::Blobs _blobs;
|
||||||
|
|
||||||
const float _circleRadius;
|
float _circleRadius = 0.;
|
||||||
QBrush _blobBrush;
|
QBrush _blobBrush;
|
||||||
QBrush _glowBrush;
|
QBrush _glowBrush;
|
||||||
int _center = 0;
|
int _center = 0;
|
||||||
|
@ -312,15 +315,15 @@ private:
|
||||||
|
|
||||||
BlobsWidget::BlobsWidget(
|
BlobsWidget::BlobsWidget(
|
||||||
not_null<RpWidget*> parent,
|
not_null<RpWidget*> parent,
|
||||||
|
int diameter,
|
||||||
rpl::producer<bool> &&hideBlobs)
|
rpl::producer<bool> &&hideBlobs)
|
||||||
: RpWidget(parent)
|
: RpWidget(parent)
|
||||||
, _blobs(MuteBlobs(), kLevelDuration, kMaxLevel)
|
, _blobs(MuteBlobs(), kLevelDuration, kMaxLevel)
|
||||||
, _circleRadius(st::callMuteButtonActive.bgSize / 2.)
|
|
||||||
, _blobBrush(Qt::transparent)
|
, _blobBrush(Qt::transparent)
|
||||||
, _glowBrush(Qt::transparent)
|
, _glowBrush(Qt::transparent)
|
||||||
, _blobsLastTime(crl::now())
|
, _blobsLastTime(crl::now())
|
||||||
, _blobsScaleLastTime(crl::now()) {
|
, _blobsScaleLastTime(crl::now()) {
|
||||||
init();
|
init(diameter);
|
||||||
|
|
||||||
std::move(
|
std::move(
|
||||||
hideBlobs
|
hideBlobs
|
||||||
|
@ -342,7 +345,27 @@ BlobsWidget::BlobsWidget(
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlobsWidget::init() {
|
void BlobsWidget::setDiameter(int diameter) {
|
||||||
|
_circleRadius = diameter / 2.;
|
||||||
|
const auto defaultSize = _blobs.maxRadius() * 2 * kGlowPaddingFactor;
|
||||||
|
const auto s = int(std::ceil((defaultSize * diameter)
|
||||||
|
/ float64(st::callMuteBlobRadiusForDiameter)));
|
||||||
|
const auto size = QSize{ s, s };
|
||||||
|
if (this->size() != size) {
|
||||||
|
resize(size);
|
||||||
|
}
|
||||||
|
computeCircleRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlobsWidget::computeCircleRect() {
|
||||||
|
const auto &r = _circleRadius;
|
||||||
|
const auto left = (size().width() - r * 2.) / 2.;
|
||||||
|
const auto add = st::callConnectingRadial.thickness / 2;
|
||||||
|
_circleRect = QRectF(left, left, r * 2, r * 2).marginsAdded(
|
||||||
|
style::margins(add, add, add, add));
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlobsWidget::init(int diameter) {
|
||||||
setAttribute(Qt::WA_TransparentForMouseEvents);
|
setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
|
||||||
const auto cutRect = [](Painter &p, const QRectF &r) {
|
const auto cutRect = [](Painter &p, const QRectF &r) {
|
||||||
|
@ -354,22 +377,12 @@ void BlobsWidget::init() {
|
||||||
p.restore();
|
p.restore();
|
||||||
};
|
};
|
||||||
|
|
||||||
{
|
setDiameter(diameter);
|
||||||
const auto s = _blobs.maxRadius() * 2 * kGlowPaddingFactor;
|
|
||||||
resize(s, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
sizeValue(
|
sizeValue(
|
||||||
) | rpl::start_with_next([=](QSize size) {
|
) | rpl::start_with_next([=](QSize size) {
|
||||||
_center = size.width() / 2;
|
_center = size.width() / 2;
|
||||||
|
computeCircleRect();
|
||||||
{
|
|
||||||
const auto &r = _circleRadius;
|
|
||||||
const auto left = (size.width() - r * 2.) / 2.;
|
|
||||||
const auto add = st::callConnectingRadial.thickness / 2;
|
|
||||||
_circleRect = QRectF(left, left, r * 2, r * 2).marginsAdded(
|
|
||||||
style::margins(add, add, add, add));
|
|
||||||
}
|
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
|
||||||
paintRequest(
|
paintRequest(
|
||||||
|
@ -396,7 +409,9 @@ void BlobsWidget::init() {
|
||||||
_blobsScaleEnter * (1. - Clamp(
|
_blobsScaleEnter * (1. - Clamp(
|
||||||
_switchConnectingProgress / kBlobPartAnimation)))
|
_switchConnectingProgress / kBlobPartAnimation)))
|
||||||
: _blobsScaleEnter;
|
: _blobsScaleEnter;
|
||||||
_blobs.paint(p, _blobBrush, scale);
|
const auto sizeScale = (2. * _circleRadius)
|
||||||
|
/ st::callMuteBlobRadiusForDiameter;
|
||||||
|
_blobs.paint(p, _blobBrush, scale * sizeScale);
|
||||||
p.translate(-_center, -_center);
|
p.translate(-_center, -_center);
|
||||||
|
|
||||||
if (scale < 1.) {
|
if (scale < 1.) {
|
||||||
|
@ -499,12 +514,14 @@ void BlobsWidget::setSwitchConnectingProgress(float64 progress) {
|
||||||
|
|
||||||
CallMuteButton::CallMuteButton(
|
CallMuteButton::CallMuteButton(
|
||||||
not_null<RpWidget*> parent,
|
not_null<RpWidget*> parent,
|
||||||
|
const style::CallMuteButton &st,
|
||||||
rpl::producer<bool> &&hideBlobs,
|
rpl::producer<bool> &&hideBlobs,
|
||||||
CallMuteButtonState initial)
|
CallMuteButtonState initial)
|
||||||
: _state(initial)
|
: _state(initial)
|
||||||
, _st(st::callMuteButtonActive)
|
, _st(&st)
|
||||||
, _blobs(base::make_unique_q<BlobsWidget>(
|
, _blobs(base::make_unique_q<BlobsWidget>(
|
||||||
parent,
|
parent,
|
||||||
|
_st->active.bgSize,
|
||||||
rpl::combine(
|
rpl::combine(
|
||||||
rpl::single(anim::Disabled()) | rpl::then(anim::Disables()),
|
rpl::single(anim::Disabled()) | rpl::then(anim::Disables()),
|
||||||
std::move(hideBlobs),
|
std::move(hideBlobs),
|
||||||
|
@ -516,53 +533,82 @@ CallMuteButton::CallMuteButton(
|
||||||
return isBadState || !(!animDisabled && !hide);
|
return isBadState || !(!animDisabled && !hide);
|
||||||
})))
|
})))
|
||||||
, _content(base::make_unique_q<AbstractButton>(parent))
|
, _content(base::make_unique_q<AbstractButton>(parent))
|
||||||
, _centerLabel(base::make_unique_q<AnimatedLabel>(
|
|
||||||
parent,
|
|
||||||
_state.value(
|
|
||||||
) | rpl::map([](const CallMuteButtonState &state) {
|
|
||||||
return state.subtext.isEmpty() ? state.text : QString();
|
|
||||||
}),
|
|
||||||
kSwitchLabelDuration,
|
|
||||||
st::callMuteButtonLabelAdditional,
|
|
||||||
_st.label))
|
|
||||||
, _label(base::make_unique_q<AnimatedLabel>(
|
|
||||||
parent,
|
|
||||||
_state.value(
|
|
||||||
) | rpl::map([](const CallMuteButtonState &state) {
|
|
||||||
return state.subtext.isEmpty() ? QString() : state.text;
|
|
||||||
}),
|
|
||||||
kSwitchLabelDuration,
|
|
||||||
st::callMuteButtonLabelAdditional,
|
|
||||||
_st.label))
|
|
||||||
, _sublabel(base::make_unique_q<AnimatedLabel>(
|
|
||||||
parent,
|
|
||||||
_state.value(
|
|
||||||
) | rpl::map([](const CallMuteButtonState &state) {
|
|
||||||
return state.subtext;
|
|
||||||
}),
|
|
||||||
kSwitchLabelDuration,
|
|
||||||
st::callMuteButtonLabelAdditional,
|
|
||||||
st::callMuteButtonSublabel))
|
|
||||||
, _colors(Colors())
|
, _colors(Colors())
|
||||||
, _iconState(initialState()) {
|
, _iconState(iconStateFrom(initial.type)) {
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
CallMuteButton::IconState CallMuteButton::initialState() {
|
void CallMuteButton::refreshLabels() {
|
||||||
const auto result = iconStateFrom(_state.current().type);
|
_centerLabel = base::make_unique_q<AnimatedLabel>(
|
||||||
|
_content->parentWidget(),
|
||||||
|
_state.value(
|
||||||
|
) | rpl::map([](const CallMuteButtonState &state) {
|
||||||
|
return state.subtext.isEmpty() ? state.text : QString();
|
||||||
|
}),
|
||||||
|
kSwitchLabelDuration,
|
||||||
|
_st->labelAdditional,
|
||||||
|
_st->active.label);
|
||||||
|
_label = base::make_unique_q<AnimatedLabel>(
|
||||||
|
_content->parentWidget(),
|
||||||
|
_state.value(
|
||||||
|
) | rpl::map([](const CallMuteButtonState &state) {
|
||||||
|
return state.subtext.isEmpty() ? QString() : state.text;
|
||||||
|
}),
|
||||||
|
kSwitchLabelDuration,
|
||||||
|
_st->labelAdditional,
|
||||||
|
_st->active.label);
|
||||||
|
_sublabel = base::make_unique_q<AnimatedLabel>(
|
||||||
|
_content->parentWidget(),
|
||||||
|
_state.value(
|
||||||
|
) | rpl::map([](const CallMuteButtonState &state) {
|
||||||
|
return state.subtext;
|
||||||
|
}),
|
||||||
|
kSwitchLabelDuration,
|
||||||
|
_st->labelAdditional,
|
||||||
|
_st->sublabel);
|
||||||
|
|
||||||
|
_label->show();
|
||||||
|
rpl::combine(
|
||||||
|
_content->geometryValue(),
|
||||||
|
_label->sizeValue()
|
||||||
|
) | rpl::start_with_next([=](QRect my, QSize size) {
|
||||||
|
updateLabelGeometry(my, size);
|
||||||
|
}, _label->lifetime());
|
||||||
|
_label->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
|
||||||
|
_sublabel->show();
|
||||||
|
rpl::combine(
|
||||||
|
_content->geometryValue(),
|
||||||
|
_sublabel->sizeValue()
|
||||||
|
) | rpl::start_with_next([=](QRect my, QSize size) {
|
||||||
|
updateSublabelGeometry(my, size);
|
||||||
|
}, _sublabel->lifetime());
|
||||||
|
_sublabel->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
|
||||||
|
_centerLabel->show();
|
||||||
|
rpl::combine(
|
||||||
|
_content->geometryValue(),
|
||||||
|
_centerLabel->sizeValue()
|
||||||
|
) | rpl::start_with_next([=](QRect my, QSize size) {
|
||||||
|
updateCenterLabelGeometry(my, size);
|
||||||
|
}, _centerLabel->lifetime());
|
||||||
|
_centerLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CallMuteButton::refreshIcons() {
|
||||||
_icons[0].emplace(Lottie::IconDescriptor{
|
_icons[0].emplace(Lottie::IconDescriptor{
|
||||||
.path = u":/gui/icons/calls/voice.lottie"_q,
|
.path = u":/gui/icons/calls/voice.lottie"_q,
|
||||||
.color = st::groupCallIconFg,
|
.color = st::groupCallIconFg,
|
||||||
.sizeOverride = st::groupCallMuteButtonIconSize,
|
.sizeOverride = _st->lottieSize,
|
||||||
.frame = result.frameTo,
|
.frame = (_iconState.index ? 0 : _iconState.frameTo),
|
||||||
});
|
});
|
||||||
_icons[1].emplace(Lottie::IconDescriptor{
|
_icons[1].emplace(Lottie::IconDescriptor{
|
||||||
.path = u":/gui/icons/calls/hands.lottie"_q,
|
.path = u":/gui/icons/calls/hands.lottie"_q,
|
||||||
.color = st::groupCallIconFg,
|
.color = st::groupCallIconFg,
|
||||||
.sizeOverride = st::groupCallMuteButtonIconSize,
|
.sizeOverride = _st->lottieSize,
|
||||||
.frame = 0,
|
.frame = (_iconState.index ? _iconState.frameTo : 0),
|
||||||
});
|
});
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto CallMuteButton::iconStateAnimated(CallMuteButtonType previous)
|
auto CallMuteButton::iconStateAnimated(CallMuteButtonType previous)
|
||||||
|
@ -647,35 +693,11 @@ CallMuteButton::IconState CallMuteButton::randomWavingState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallMuteButton::init() {
|
void CallMuteButton::init() {
|
||||||
_content->resize(_st.button.width, _st.button.height);
|
refreshLabels();
|
||||||
|
refreshIcons();
|
||||||
|
|
||||||
// Label text.
|
const auto &button = _st->active.button;
|
||||||
_label->show();
|
_content->resize(button.width, button.height);
|
||||||
rpl::combine(
|
|
||||||
_content->geometryValue(),
|
|
||||||
_label->sizeValue()
|
|
||||||
) | rpl::start_with_next([=](QRect my, QSize size) {
|
|
||||||
updateLabelGeometry(my, size);
|
|
||||||
}, _label->lifetime());
|
|
||||||
_label->setAttribute(Qt::WA_TransparentForMouseEvents);
|
|
||||||
|
|
||||||
_sublabel->show();
|
|
||||||
rpl::combine(
|
|
||||||
_content->geometryValue(),
|
|
||||||
_sublabel->sizeValue()
|
|
||||||
) | rpl::start_with_next([=](QRect my, QSize size) {
|
|
||||||
updateSublabelGeometry(my, size);
|
|
||||||
}, _sublabel->lifetime());
|
|
||||||
_sublabel->setAttribute(Qt::WA_TransparentForMouseEvents);
|
|
||||||
|
|
||||||
_centerLabel->show();
|
|
||||||
rpl::combine(
|
|
||||||
_content->geometryValue(),
|
|
||||||
_centerLabel->sizeValue()
|
|
||||||
) | rpl::start_with_next([=](QRect my, QSize size) {
|
|
||||||
updateCenterLabelGeometry(my, size);
|
|
||||||
}, _centerLabel->lifetime());
|
|
||||||
_centerLabel->setAttribute(Qt::WA_TransparentForMouseEvents);
|
|
||||||
|
|
||||||
rpl::combine(
|
rpl::combine(
|
||||||
_radialInfo.rawShowProgress.value(),
|
_radialInfo.rawShowProgress.value(),
|
||||||
|
@ -722,36 +744,7 @@ void CallMuteButton::init() {
|
||||||
lifetime().make_state<CallMuteButtonType>(_state.current().type);
|
lifetime().make_state<CallMuteButtonType>(_state.current().type);
|
||||||
setHandleMouseState(HandleMouseState::Disabled);
|
setHandleMouseState(HandleMouseState::Disabled);
|
||||||
|
|
||||||
const auto blobsInner = [&] {
|
refreshGradients();
|
||||||
// The point of the circle at 45 degrees.
|
|
||||||
const auto w = _blobs->innerRect().width();
|
|
||||||
const auto mF = (1 - std::cos(M_PI / 4.)) * (w / 2.);
|
|
||||||
return _blobs->innerRect().marginsRemoved(QMarginsF(mF, mF, mF, mF));
|
|
||||||
}();
|
|
||||||
|
|
||||||
auto linearGradients = anim::linear_gradients<CallMuteButtonType>(
|
|
||||||
_colors,
|
|
||||||
QPointF(blobsInner.x() + blobsInner.width(), blobsInner.y()),
|
|
||||||
QPointF(blobsInner.x(), blobsInner.y() + blobsInner.height()));
|
|
||||||
|
|
||||||
auto glowColors = [&] {
|
|
||||||
auto copy = _colors;
|
|
||||||
for (auto &[type, stops] : copy) {
|
|
||||||
auto firstColor = IsInactive(type)
|
|
||||||
? st::groupCallBg->c
|
|
||||||
: stops.stops[(stops.stops.size() - 1) / 2].second;
|
|
||||||
firstColor.setAlpha(kGlowAlpha);
|
|
||||||
stops.stops = QGradientStops{
|
|
||||||
{ 0., std::move(firstColor) },
|
|
||||||
{ 1., QColor(Qt::transparent) }
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return copy;
|
|
||||||
}();
|
|
||||||
auto glows = anim::radial_gradients<CallMuteButtonType>(
|
|
||||||
std::move(glowColors),
|
|
||||||
blobsInner.center(),
|
|
||||||
_blobs->width() / 2);
|
|
||||||
|
|
||||||
_state.value(
|
_state.value(
|
||||||
) | rpl::map([](const CallMuteButtonState &state) {
|
) | rpl::map([](const CallMuteButtonState &state) {
|
||||||
|
@ -784,9 +777,9 @@ void CallMuteButton::init() {
|
||||||
auto callback = [=](float64 value) {
|
auto callback = [=](float64 value) {
|
||||||
const auto brushProgress = fromConnecting ? 1. : value;
|
const auto brushProgress = fromConnecting ? 1. : value;
|
||||||
_blobs->setBlobBrush(QBrush(
|
_blobs->setBlobBrush(QBrush(
|
||||||
linearGradients.gradient(previous, type, brushProgress)));
|
_linearGradients.gradient(previous, type, brushProgress)));
|
||||||
_blobs->setGlowBrush(QBrush(
|
_blobs->setGlowBrush(QBrush(
|
||||||
glows.gradient(previous, type, value)));
|
_glowGradients.gradient(previous, type, value)));
|
||||||
_blobs->update();
|
_blobs->update();
|
||||||
|
|
||||||
const auto radialShowProgress = (radialShowFrom == radialShowTo)
|
const auto radialShowProgress = (radialShowFrom == radialShowTo)
|
||||||
|
@ -815,10 +808,10 @@ void CallMuteButton::init() {
|
||||||
// Icon rect.
|
// Icon rect.
|
||||||
_content->sizeValue(
|
_content->sizeValue(
|
||||||
) | rpl::start_with_next([=](QSize size) {
|
) | rpl::start_with_next([=](QSize size) {
|
||||||
const auto icon = st::groupCallMuteButtonIconSize;
|
const auto icon = _st->lottieSize;
|
||||||
_muteIconRect = QRect(
|
_muteIconRect = QRect(
|
||||||
(size.width() - icon.width()) / 2,
|
(size.width() - icon.width()) / 2,
|
||||||
st::groupCallMuteButtonIconTop,
|
_st->lottieTop,
|
||||||
icon.width(),
|
icon.width(),
|
||||||
icon.height());
|
icon.height());
|
||||||
}, lifetime());
|
}, lifetime());
|
||||||
|
@ -850,8 +843,8 @@ void CallMuteButton::init() {
|
||||||
InfiniteRadialAnimation::Draw(
|
InfiniteRadialAnimation::Draw(
|
||||||
p,
|
p,
|
||||||
r,
|
r,
|
||||||
_st.bgPosition,
|
_st->active.bgPosition,
|
||||||
_radialInfo.st.size,
|
QSize(_st->active.bgSize, _st->active.bgSize),
|
||||||
_content->width(),
|
_content->width(),
|
||||||
QPen(_radialInfo.st.color),
|
QPen(_radialInfo.st.color),
|
||||||
_radialInfo.st.thickness);
|
_radialInfo.st.thickness);
|
||||||
|
@ -862,8 +855,8 @@ void CallMuteButton::init() {
|
||||||
InfiniteRadialAnimation::Draw(
|
InfiniteRadialAnimation::Draw(
|
||||||
p,
|
p,
|
||||||
std::move(state),
|
std::move(state),
|
||||||
_st.bgPosition,
|
_st->active.bgPosition,
|
||||||
_radialInfo.st.size,
|
QSize(_st->active.bgSize, _st->active.bgSize),
|
||||||
_content->width(),
|
_content->width(),
|
||||||
QPen(_radialInfo.st.color),
|
QPen(_radialInfo.st.color),
|
||||||
_radialInfo.st.thickness);
|
_radialInfo.st.thickness);
|
||||||
|
@ -871,6 +864,39 @@ void CallMuteButton::init() {
|
||||||
}, _content->lifetime());
|
}, _content->lifetime());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CallMuteButton::refreshGradients() {
|
||||||
|
const auto blobsInner = [&] {
|
||||||
|
// The point of the circle at 45 degrees.
|
||||||
|
const auto w = _blobs->innerRect().width();
|
||||||
|
const auto mF = (1 - std::cos(M_PI / 4.)) * (w / 2.);
|
||||||
|
return _blobs->innerRect().marginsRemoved(QMarginsF(mF, mF, mF, mF));
|
||||||
|
}();
|
||||||
|
|
||||||
|
_linearGradients = anim::linear_gradients<CallMuteButtonType>(
|
||||||
|
_colors,
|
||||||
|
QPointF(blobsInner.x() + blobsInner.width(), blobsInner.y()),
|
||||||
|
QPointF(blobsInner.x(), blobsInner.y() + blobsInner.height()));
|
||||||
|
|
||||||
|
auto glowColors = [&] {
|
||||||
|
auto copy = _colors;
|
||||||
|
for (auto &[type, stops] : copy) {
|
||||||
|
auto firstColor = IsInactive(type)
|
||||||
|
? st::groupCallBg->c
|
||||||
|
: stops.stops[(stops.stops.size() - 1) / 2].second;
|
||||||
|
firstColor.setAlpha(kGlowAlpha);
|
||||||
|
stops.stops = QGradientStops{
|
||||||
|
{ 0., std::move(firstColor) },
|
||||||
|
{ 1., QColor(Qt::transparent) }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return copy;
|
||||||
|
}();
|
||||||
|
_glowGradients = anim::radial_gradients<CallMuteButtonType>(
|
||||||
|
std::move(glowColors),
|
||||||
|
blobsInner.center(),
|
||||||
|
_blobs->width() / 2);
|
||||||
|
}
|
||||||
|
|
||||||
void CallMuteButton::scheduleIconState(const IconState &state) {
|
void CallMuteButton::scheduleIconState(const IconState &state) {
|
||||||
if (_iconState != state) {
|
if (_iconState != state) {
|
||||||
if (_icons[_iconState.index]->animating()) {
|
if (_icons[_iconState.index]->animating()) {
|
||||||
|
@ -906,28 +932,26 @@ void CallMuteButton::updateLabelsGeometry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallMuteButton::updateLabelGeometry(QRect my, QSize size) {
|
void CallMuteButton::updateLabelGeometry(QRect my, QSize size) {
|
||||||
const auto skip = st::callMuteButtonSublabelSkip
|
const auto skip = _st->sublabelSkip + _st->labelsSkip;
|
||||||
+ st::callMuteButtonLabelsSkip;
|
|
||||||
_label->moveToLeft(
|
_label->moveToLeft(
|
||||||
my.x() + (my.width() - size.width()) / 2 + _labelShakeShift,
|
my.x() + (my.width() - size.width()) / 2 + _labelShakeShift,
|
||||||
my.y() + my.height() - _label->height() - skip,
|
my.y() + my.height() - size.height() - skip,
|
||||||
my.width());
|
my.width());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallMuteButton::updateCenterLabelGeometry(QRect my, QSize size) {
|
void CallMuteButton::updateCenterLabelGeometry(QRect my, QSize size) {
|
||||||
const auto skip = (st::callMuteButtonSublabelSkip / 2)
|
const auto skip = (_st->sublabelSkip / 2) + _st->labelsSkip;
|
||||||
+ st::callMuteButtonLabelsSkip;
|
|
||||||
_centerLabel->moveToLeft(
|
_centerLabel->moveToLeft(
|
||||||
my.x() + (my.width() - size.width()) / 2 + _labelShakeShift,
|
my.x() + (my.width() - size.width()) / 2 + _labelShakeShift,
|
||||||
my.y() + my.height() - _centerLabel->height() - skip,
|
my.y() + my.height() - size.height() - skip,
|
||||||
my.width());
|
my.width());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallMuteButton::updateSublabelGeometry(QRect my, QSize size) {
|
void CallMuteButton::updateSublabelGeometry(QRect my, QSize size) {
|
||||||
const auto skip = st::callMuteButtonLabelsSkip;
|
const auto skip = _st->labelsSkip;
|
||||||
_sublabel->moveToLeft(
|
_sublabel->moveToLeft(
|
||||||
my.x() + (my.width() - size.width()) / 2 + _labelShakeShift,
|
my.x() + (my.width() - size.width()) / 2 + _labelShakeShift,
|
||||||
my.y() + my.height() - _sublabel->height() - skip,
|
my.y() + my.height() - size.height() - skip,
|
||||||
my.width());
|
my.width());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -978,6 +1002,21 @@ CallMuteButton::HandleMouseState CallMuteButton::HandleMouseStateFromType(
|
||||||
Unexpected("Type in HandleMouseStateFromType.");
|
Unexpected("Type in HandleMouseStateFromType.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CallMuteButton::setStyle(const style::CallMuteButton &st) {
|
||||||
|
if (_st == &st) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_st = &st;
|
||||||
|
const auto &button = _st->active.button;
|
||||||
|
_content->resize(button.width, button.height);
|
||||||
|
_blobs->setDiameter(_st->active.bgSize);
|
||||||
|
|
||||||
|
refreshIcons();
|
||||||
|
refreshLabels();
|
||||||
|
updateLabelsGeometry();
|
||||||
|
refreshGradients();
|
||||||
|
}
|
||||||
|
|
||||||
void CallMuteButton::setState(const CallMuteButtonState &state) {
|
void CallMuteButton::setState(const CallMuteButtonState &state) {
|
||||||
_state = state;
|
_state = state;
|
||||||
}
|
}
|
||||||
|
@ -1002,7 +1041,7 @@ QSize CallMuteButton::innerSize() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect CallMuteButton::innerGeometry() const {
|
QRect CallMuteButton::innerGeometry() const {
|
||||||
const auto &skip = _st.outerRadius;
|
const auto &skip = _st->active.outerRadius;
|
||||||
return QRect(
|
return QRect(
|
||||||
_content->x(),
|
_content->x(),
|
||||||
_content->y(),
|
_content->y(),
|
||||||
|
@ -1011,7 +1050,7 @@ QRect CallMuteButton::innerGeometry() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallMuteButton::moveInner(QPoint position) {
|
void CallMuteButton::moveInner(QPoint position) {
|
||||||
const auto &skip = _st.outerRadius;
|
const auto &skip = _st->active.outerRadius;
|
||||||
_content->move(position - QPoint(skip, skip));
|
_content->move(position - QPoint(skip, skip));
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,6 +13,10 @@
|
||||||
#include "ui/effects/radial_animation.h"
|
#include "ui/effects/radial_animation.h"
|
||||||
#include "lottie/lottie_icon.h"
|
#include "lottie/lottie_icon.h"
|
||||||
|
|
||||||
|
namespace style {
|
||||||
|
struct CallMuteButton;
|
||||||
|
} // namespace style
|
||||||
|
|
||||||
namespace st {
|
namespace st {
|
||||||
extern const style::InfiniteRadialAnimation &callConnectingRadial;
|
extern const style::InfiniteRadialAnimation &callConnectingRadial;
|
||||||
} // namespace st
|
} // namespace st
|
||||||
|
@ -49,11 +53,13 @@ class CallMuteButton final {
|
||||||
public:
|
public:
|
||||||
explicit CallMuteButton(
|
explicit CallMuteButton(
|
||||||
not_null<RpWidget*> parent,
|
not_null<RpWidget*> parent,
|
||||||
|
const style::CallMuteButton &st,
|
||||||
rpl::producer<bool> &&hideBlobs,
|
rpl::producer<bool> &&hideBlobs,
|
||||||
CallMuteButtonState initial = CallMuteButtonState());
|
CallMuteButtonState initial = CallMuteButtonState());
|
||||||
~CallMuteButton();
|
~CallMuteButton();
|
||||||
|
|
||||||
void setState(const CallMuteButtonState &state);
|
void setState(const CallMuteButtonState &state);
|
||||||
|
void setStyle(const style::CallMuteButton &st);
|
||||||
void setLevel(float level);
|
void setLevel(float level);
|
||||||
[[nodiscard]] rpl::producer<Qt::MouseButton> clicks();
|
[[nodiscard]] rpl::producer<Qt::MouseButton> clicks();
|
||||||
|
|
||||||
|
@ -113,6 +119,9 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
void refreshIcons();
|
||||||
|
void refreshGradients();
|
||||||
|
void refreshLabels();
|
||||||
void overridesColors(
|
void overridesColors(
|
||||||
CallMuteButtonType fromType,
|
CallMuteButtonType fromType,
|
||||||
CallMuteButtonType toType,
|
CallMuteButtonType toType,
|
||||||
|
@ -124,7 +133,6 @@ private:
|
||||||
void updateSublabelGeometry(QRect my, QSize size);
|
void updateSublabelGeometry(QRect my, QSize size);
|
||||||
void updateLabelsGeometry();
|
void updateLabelsGeometry();
|
||||||
|
|
||||||
[[nodiscard]] IconState initialState();
|
|
||||||
[[nodiscard]] IconState iconStateFrom(CallMuteButtonType previous);
|
[[nodiscard]] IconState iconStateFrom(CallMuteButtonType previous);
|
||||||
[[nodiscard]] IconState randomWavingState();
|
[[nodiscard]] IconState randomWavingState();
|
||||||
[[nodiscard]] IconState iconStateAnimated(CallMuteButtonType previous);
|
[[nodiscard]] IconState iconStateAnimated(CallMuteButtonType previous);
|
||||||
|
@ -140,18 +148,20 @@ private:
|
||||||
QRect _muteIconRect;
|
QRect _muteIconRect;
|
||||||
HandleMouseState _handleMouseState = HandleMouseState::Enabled;
|
HandleMouseState _handleMouseState = HandleMouseState::Enabled;
|
||||||
|
|
||||||
const style::CallButton &_st;
|
not_null<const style::CallMuteButton*> _st;
|
||||||
|
|
||||||
const base::unique_qptr<BlobsWidget> _blobs;
|
const base::unique_qptr<BlobsWidget> _blobs;
|
||||||
const base::unique_qptr<AbstractButton> _content;
|
const base::unique_qptr<AbstractButton> _content;
|
||||||
const base::unique_qptr<AnimatedLabel> _centerLabel;
|
base::unique_qptr<AnimatedLabel> _centerLabel;
|
||||||
const base::unique_qptr<AnimatedLabel> _label;
|
base::unique_qptr<AnimatedLabel> _label;
|
||||||
const base::unique_qptr<AnimatedLabel> _sublabel;
|
base::unique_qptr<AnimatedLabel> _sublabel;
|
||||||
int _labelShakeShift = 0;
|
int _labelShakeShift = 0;
|
||||||
|
|
||||||
RadialInfo _radialInfo;
|
RadialInfo _radialInfo;
|
||||||
std::unique_ptr<InfiniteRadialAnimation> _radial;
|
std::unique_ptr<InfiniteRadialAnimation> _radial;
|
||||||
const base::flat_map<CallMuteButtonType, anim::gradient_colors> _colors;
|
const base::flat_map<CallMuteButtonType, anim::gradient_colors> _colors;
|
||||||
|
anim::linear_gradients<CallMuteButtonType> _linearGradients;
|
||||||
|
anim::radial_gradients<CallMuteButtonType> _glowGradients;
|
||||||
|
|
||||||
std::array<std::optional<Lottie::Icon>, 2> _icons;
|
std::array<std::optional<Lottie::Icon>, 2> _icons;
|
||||||
IconState _iconState;
|
IconState _iconState;
|
||||||
|
|
Loading…
Add table
Reference in a new issue