mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Guarded users from instant calls with confirmation dialog.
This commit is contained in:
parent
30ae879fb3
commit
df176dd1d9
7 changed files with 102 additions and 23 deletions
|
@ -2572,6 +2572,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_call_status_failed" = "failed to connect";
|
"lng_call_status_failed" = "failed to connect";
|
||||||
"lng_call_status_ringing" = "ringing...";
|
"lng_call_status_ringing" = "ringing...";
|
||||||
"lng_call_status_busy" = "line busy";
|
"lng_call_status_busy" = "line busy";
|
||||||
|
"lng_call_status_sure" = "Click on the Camera icon if you want to start a video call.";
|
||||||
"lng_call_fingerprint_tooltip" = "If emoji on {user}'s screen are the same, this call is 100% secure";
|
"lng_call_fingerprint_tooltip" = "If emoji on {user}'s screen are the same, this call is 100% secure";
|
||||||
|
|
||||||
"lng_call_error_not_available" = "Sorry, {user} doesn't accept calls.";
|
"lng_call_error_not_available" = "Sorry, {user} doesn't accept calls.";
|
||||||
|
@ -2612,6 +2613,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_call_rate_label" = "Please rate the quality of your call";
|
"lng_call_rate_label" = "Please rate the quality of your call";
|
||||||
"lng_call_rate_comment" = "Comment (optional)";
|
"lng_call_rate_comment" = "Comment (optional)";
|
||||||
|
|
||||||
|
"lng_call_start" = "Start Call";
|
||||||
"lng_call_start_video" = "Start Video";
|
"lng_call_start_video" = "Start Video";
|
||||||
"lng_call_stop_video" = "Stop Video";
|
"lng_call_stop_video" = "Stop Video";
|
||||||
"lng_call_screencast" = "Screencast";
|
"lng_call_screencast" = "Screencast";
|
||||||
|
|
|
@ -117,6 +117,14 @@ callAnswer: CallButton {
|
||||||
outerBg: callAnswerBgOuter;
|
outerBg: callAnswerBgOuter;
|
||||||
label: callButtonLabel;
|
label: callButtonLabel;
|
||||||
}
|
}
|
||||||
|
callStartVideo: CallButton(callAnswer) {
|
||||||
|
button: IconButton(callButton) {
|
||||||
|
icon: icon {{ "calls/call_camera_active", callIconFg }};
|
||||||
|
ripple: RippleAnimation(defaultRippleAnimation) {
|
||||||
|
color: callAnswerRipple;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
callHangup: CallButton(callAnswer) {
|
callHangup: CallButton(callAnswer) {
|
||||||
button: IconButton(callButton) {
|
button: IconButton(callButton) {
|
||||||
icon: icon {{ "calls/call_discard", callIconFg }};
|
icon: icon {{ "calls/call_discard", callIconFg }};
|
||||||
|
@ -292,7 +300,7 @@ callName: FlatLabel(defaultFlatLabel) {
|
||||||
}
|
}
|
||||||
callStatus: FlatLabel(defaultFlatLabel) {
|
callStatus: FlatLabel(defaultFlatLabel) {
|
||||||
minWidth: 260px;
|
minWidth: 260px;
|
||||||
maxHeight: 20px;
|
maxHeight: 60px;
|
||||||
textFg: callStatusFg;
|
textFg: callStatusFg;
|
||||||
align: align(top);
|
align: align(top);
|
||||||
style: TextStyle(defaultTextStyle) {
|
style: TextStyle(defaultTextStyle) {
|
||||||
|
|
|
@ -220,7 +220,7 @@ Call::Call(
|
||||||
std::make_unique<Webrtc::VideoTrack>(
|
std::make_unique<Webrtc::VideoTrack>(
|
||||||
StartVideoState(video))) {
|
StartVideoState(video))) {
|
||||||
if (_type == Type::Outgoing) {
|
if (_type == Type::Outgoing) {
|
||||||
setState(State::Requesting);
|
setState(State::WaitingUserConfirmation);
|
||||||
} else {
|
} else {
|
||||||
const auto &config = _user->session().serverConfig();
|
const auto &config = _user->session().serverConfig();
|
||||||
_discardByTimeoutTimer.callOnce(config.callRingTimeoutMs);
|
_discardByTimeoutTimer.callOnce(config.callRingTimeoutMs);
|
||||||
|
@ -344,6 +344,12 @@ void Call::startIncoming() {
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Call::applyUserConfirmation() {
|
||||||
|
if (_state.current() == State::WaitingUserConfirmation) {
|
||||||
|
setState(State::Requesting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Call::answer() {
|
void Call::answer() {
|
||||||
const auto video = isSharingVideo();
|
const auto video = isSharingVideo();
|
||||||
_delegate->callRequestPermissionsOrFail(crl::guard(this, [=] {
|
_delegate->callRequestPermissionsOrFail(crl::guard(this, [=] {
|
||||||
|
|
|
@ -126,6 +126,7 @@ public:
|
||||||
WaitingIncoming,
|
WaitingIncoming,
|
||||||
Ringing,
|
Ringing,
|
||||||
Busy,
|
Busy,
|
||||||
|
WaitingUserConfirmation,
|
||||||
};
|
};
|
||||||
[[nodiscard]] State state() const {
|
[[nodiscard]] State state() const {
|
||||||
return _state.current();
|
return _state.current();
|
||||||
|
@ -179,6 +180,7 @@ public:
|
||||||
crl::time getDurationMs() const;
|
crl::time getDurationMs() const;
|
||||||
float64 getWaitingSoundPeakValue() const;
|
float64 getWaitingSoundPeakValue() const;
|
||||||
|
|
||||||
|
void applyUserConfirmation();
|
||||||
void answer();
|
void answer();
|
||||||
void hangup();
|
void hangup();
|
||||||
void redial();
|
void redial();
|
||||||
|
@ -257,7 +259,7 @@ private:
|
||||||
const not_null<UserData*> _user;
|
const not_null<UserData*> _user;
|
||||||
MTP::Sender _api;
|
MTP::Sender _api;
|
||||||
Type _type = Type::Outgoing;
|
Type _type = Type::Outgoing;
|
||||||
rpl::variable<State> _state = State::Starting;
|
rpl::variable<State> _state = State::WaitingUserConfirmation;
|
||||||
rpl::variable<RemoteAudioState> _remoteAudioState =
|
rpl::variable<RemoteAudioState> _remoteAudioState =
|
||||||
RemoteAudioState::Active;
|
RemoteAudioState::Active;
|
||||||
rpl::variable<Webrtc::VideoState> _remoteVideoState;
|
rpl::variable<Webrtc::VideoState> _remoteVideoState;
|
||||||
|
|
|
@ -341,9 +341,14 @@ void Instance::createCall(not_null<UserData*> user, Call::Type type, bool video)
|
||||||
_currentCallPanel = std::make_unique<Panel>(raw);
|
_currentCallPanel = std::make_unique<Panel>(raw);
|
||||||
_currentCall = std::move(call);
|
_currentCall = std::move(call);
|
||||||
}
|
}
|
||||||
|
_currentCallPanel->startOutgoingRequests(
|
||||||
|
) | rpl::start_with_next([=](bool video) {
|
||||||
|
raw->applyUserConfirmation();
|
||||||
|
raw->toggleCameraSharing(video);
|
||||||
|
refreshServerConfig(&user->session());
|
||||||
|
refreshDhConfig();
|
||||||
|
}, raw->lifetime());
|
||||||
_currentCallChanges.fire_copy(raw);
|
_currentCallChanges.fire_copy(raw);
|
||||||
refreshServerConfig(&user->session());
|
|
||||||
refreshDhConfig();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Instance::destroyGroupCall(not_null<GroupCall*> call) {
|
void Instance::destroyGroupCall(not_null<GroupCall*> call) {
|
||||||
|
|
|
@ -73,9 +73,22 @@ Panel::Panel(not_null<Call*> call)
|
||||||
, _answerHangupRedial(widget(), st::callAnswer, &st::callHangup)
|
, _answerHangupRedial(widget(), st::callAnswer, &st::callHangup)
|
||||||
, _decline(widget(), object_ptr<Ui::CallButton>(widget(), st::callHangup))
|
, _decline(widget(), object_ptr<Ui::CallButton>(widget(), st::callHangup))
|
||||||
, _cancel(widget(), object_ptr<Ui::CallButton>(widget(), st::callCancel))
|
, _cancel(widget(), object_ptr<Ui::CallButton>(widget(), st::callCancel))
|
||||||
, _screencast(widget(), st::callScreencastOn, &st::callScreencastOff)
|
, _screencast(
|
||||||
|
widget(),
|
||||||
|
object_ptr<Ui::CallButton>(
|
||||||
|
widget(),
|
||||||
|
st::callScreencastOn,
|
||||||
|
&st::callScreencastOff))
|
||||||
, _camera(widget(), st::callCameraMute, &st::callCameraUnmute)
|
, _camera(widget(), st::callCameraMute, &st::callCameraUnmute)
|
||||||
, _mute(widget(), st::callMicrophoneMute, &st::callMicrophoneUnmute)
|
, _startVideo(
|
||||||
|
widget(),
|
||||||
|
object_ptr<Ui::CallButton>(widget(), st::callStartVideo))
|
||||||
|
, _mute(
|
||||||
|
widget(),
|
||||||
|
object_ptr<Ui::CallButton>(
|
||||||
|
widget(),
|
||||||
|
st::callMicrophoneMute,
|
||||||
|
&st::callMicrophoneUnmute))
|
||||||
, _name(widget(), st::callName)
|
, _name(widget(), st::callName)
|
||||||
, _status(widget(), st::callStatus) {
|
, _status(widget(), st::callStatus) {
|
||||||
_layerBg->setStyleOverrides(&st::groupCallBox, &st::groupCallLayerBox);
|
_layerBg->setStyleOverrides(&st::groupCallBox, &st::groupCallLayerBox);
|
||||||
|
@ -214,12 +227,12 @@ void Panel::initWidget() {
|
||||||
|
|
||||||
void Panel::initControls() {
|
void Panel::initControls() {
|
||||||
_hangupShown = (_call->type() == Type::Outgoing);
|
_hangupShown = (_call->type() == Type::Outgoing);
|
||||||
_mute->setClickedCallback([=] {
|
_mute->entity()->setClickedCallback([=] {
|
||||||
if (_call) {
|
if (_call) {
|
||||||
_call->setMuted(!_call->muted());
|
_call->setMuted(!_call->muted());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
_screencast->setClickedCallback([=] {
|
_screencast->entity()->setClickedCallback([=] {
|
||||||
if (!_call) {
|
if (!_call) {
|
||||||
return;
|
return;
|
||||||
} else if (!Webrtc::DesktopCaptureAllowed()) {
|
} else if (!Webrtc::DesktopCaptureAllowed()) {
|
||||||
|
@ -267,6 +280,7 @@ void Panel::initControls() {
|
||||||
_call->redial();
|
_call->redial();
|
||||||
} else if (_call->isIncomingWaiting()) {
|
} else if (_call->isIncomingWaiting()) {
|
||||||
_call->answer();
|
_call->answer();
|
||||||
|
} else if (state == State::WaitingUserConfirmation) {
|
||||||
} else {
|
} else {
|
||||||
_call->hangup();
|
_call->hangup();
|
||||||
}
|
}
|
||||||
|
@ -278,6 +292,7 @@ void Panel::initControls() {
|
||||||
};
|
};
|
||||||
_decline->entity()->setClickedCallback(hangupCallback);
|
_decline->entity()->setClickedCallback(hangupCallback);
|
||||||
_cancel->entity()->setClickedCallback(hangupCallback);
|
_cancel->entity()->setClickedCallback(hangupCallback);
|
||||||
|
_startVideo->entity()->setText(tr::lng_call_start_video());
|
||||||
|
|
||||||
reinitWithCall(_call);
|
reinitWithCall(_call);
|
||||||
|
|
||||||
|
@ -318,6 +333,17 @@ rpl::lifetime &Panel::chooseSourceInstanceLifetime() {
|
||||||
return lifetime();
|
return lifetime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rpl::producer<bool> Panel::startOutgoingRequests() const {
|
||||||
|
const auto filter = [=] {
|
||||||
|
return _call && (_call->state() == State::WaitingUserConfirmation);
|
||||||
|
};
|
||||||
|
return rpl::merge(
|
||||||
|
_startVideo->entity()->clicks(
|
||||||
|
) | rpl::filter(filter) | rpl::map_to(true),
|
||||||
|
_answerHangupRedial->clicks(
|
||||||
|
) | rpl::filter(filter) | rpl::map_to(false));
|
||||||
|
}
|
||||||
|
|
||||||
void Panel::chooseSourceAccepted(
|
void Panel::chooseSourceAccepted(
|
||||||
const QString &deviceId,
|
const QString &deviceId,
|
||||||
bool withAudio) {
|
bool withAudio) {
|
||||||
|
@ -388,8 +414,8 @@ void Panel::reinitWithCall(Call *call) {
|
||||||
|
|
||||||
_call->mutedValue(
|
_call->mutedValue(
|
||||||
) | rpl::start_with_next([=](bool mute) {
|
) | rpl::start_with_next([=](bool mute) {
|
||||||
_mute->setProgress(mute ? 1. : 0.);
|
_mute->entity()->setProgress(mute ? 1. : 0.);
|
||||||
_mute->setText(mute
|
_mute->entity()->setText(mute
|
||||||
? tr::lng_call_unmute_audio()
|
? tr::lng_call_unmute_audio()
|
||||||
: tr::lng_call_mute_audio());
|
: tr::lng_call_mute_audio());
|
||||||
}, _callLifetime);
|
}, _callLifetime);
|
||||||
|
@ -405,8 +431,8 @@ void Panel::reinitWithCall(Call *call) {
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const auto active = _call->isSharingScreen();
|
const auto active = _call->isSharingScreen();
|
||||||
_screencast->setProgress(active ? 0. : 1.);
|
_screencast->entity()->setProgress(active ? 0. : 1.);
|
||||||
_screencast->setText(tr::lng_call_screencast());
|
_screencast->entity()->setText(tr::lng_call_screencast());
|
||||||
_outgoingVideoBubble->setMirrored(!active);
|
_outgoingVideoBubble->setMirrored(!active);
|
||||||
}
|
}
|
||||||
}, _callLifetime);
|
}, _callLifetime);
|
||||||
|
@ -497,6 +523,7 @@ void Panel::reinitWithCall(Call *call) {
|
||||||
_decline->raise();
|
_decline->raise();
|
||||||
_cancel->raise();
|
_cancel->raise();
|
||||||
_camera->raise();
|
_camera->raise();
|
||||||
|
_startVideo->raise();
|
||||||
_mute->raise();
|
_mute->raise();
|
||||||
|
|
||||||
_powerSaveBlocker = std::make_unique<base::PowerSaveBlocker>(
|
_powerSaveBlocker = std::make_unique<base::PowerSaveBlocker>(
|
||||||
|
@ -755,7 +782,10 @@ void Panel::updateHangupGeometry() {
|
||||||
auto threeWidth = twoWidth + st::callCancel.button.width;
|
auto threeWidth = twoWidth + st::callCancel.button.width;
|
||||||
auto rightFrom = (widget()->width() - threeWidth) / 2;
|
auto rightFrom = (widget()->width() - threeWidth) / 2;
|
||||||
auto rightTo = (widget()->width() - twoWidth) / 2;
|
auto rightTo = (widget()->width() - twoWidth) / 2;
|
||||||
auto hangupProgress = _hangupShownProgress.value(_hangupShown ? 1. : 0.);
|
auto hangupProgress = (_call
|
||||||
|
&& _call->state() == State::WaitingUserConfirmation)
|
||||||
|
? 0.
|
||||||
|
: _hangupShownProgress.value(_hangupShown ? 1. : 0.);
|
||||||
auto hangupRight = anim::interpolate(rightFrom, rightTo, hangupProgress);
|
auto hangupRight = anim::interpolate(rightFrom, rightTo, hangupProgress);
|
||||||
_answerHangupRedial->moveToRight(hangupRight, _buttonsTop);
|
_answerHangupRedial->moveToRight(hangupRight, _buttonsTop);
|
||||||
_answerHangupRedial->setProgress(hangupProgress);
|
_answerHangupRedial->setProgress(hangupProgress);
|
||||||
|
@ -764,6 +794,9 @@ void Panel::updateHangupGeometry() {
|
||||||
_camera->moveToLeft(
|
_camera->moveToLeft(
|
||||||
hangupRight - _mute->width() + _screencast->width(),
|
hangupRight - _mute->width() + _screencast->width(),
|
||||||
_buttonsTop);
|
_buttonsTop);
|
||||||
|
if (_startVideo->toggled()) {
|
||||||
|
_startVideo->moveToLeft(_camera->x(), _camera->y());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Panel::updateStatusGeometry() {
|
void Panel::updateStatusGeometry() {
|
||||||
|
@ -811,33 +844,50 @@ void Panel::stateChanged(State state) {
|
||||||
&& (state != State::EndedByOtherDevice)
|
&& (state != State::EndedByOtherDevice)
|
||||||
&& (state != State::FailedHangingUp)
|
&& (state != State::FailedHangingUp)
|
||||||
&& (state != State::Failed)) {
|
&& (state != State::Failed)) {
|
||||||
if (state == State::Busy) {
|
const auto isBusy = (state == State::Busy);
|
||||||
|
const auto isWaitingUser = (state == State::WaitingUserConfirmation);
|
||||||
|
if (isBusy) {
|
||||||
_powerSaveBlocker = nullptr;
|
_powerSaveBlocker = nullptr;
|
||||||
}
|
}
|
||||||
|
if (_startVideo->toggled() && !isWaitingUser) {
|
||||||
|
_startVideo->toggle(false, anim::type::instant);
|
||||||
|
} else if (!_startVideo->toggled() && isWaitingUser) {
|
||||||
|
_startVideo->toggle(true, anim::type::instant);
|
||||||
|
}
|
||||||
|
_camera->setVisible(!_startVideo->toggled());
|
||||||
|
|
||||||
auto toggleButton = [&](auto &&button, bool visible) {
|
const auto toggleButton = [&](auto &&button, bool visible) {
|
||||||
button->toggle(
|
button->toggle(
|
||||||
visible,
|
visible,
|
||||||
window()->isHidden()
|
window()->isHidden()
|
||||||
? anim::type::instant
|
? anim::type::instant
|
||||||
: anim::type::normal);
|
: anim::type::normal);
|
||||||
};
|
};
|
||||||
auto incomingWaiting = _call->isIncomingWaiting();
|
const auto incomingWaiting = _call->isIncomingWaiting();
|
||||||
if (incomingWaiting) {
|
if (incomingWaiting) {
|
||||||
_updateOuterRippleTimer.callEach(Call::kSoundSampleMs);
|
_updateOuterRippleTimer.callEach(Call::kSoundSampleMs);
|
||||||
}
|
}
|
||||||
toggleButton(_decline, incomingWaiting);
|
toggleButton(_decline, incomingWaiting);
|
||||||
toggleButton(_cancel, (state == State::Busy));
|
toggleButton(_cancel, (isBusy || isWaitingUser));
|
||||||
auto hangupShown = !_decline->toggled()
|
toggleButton(_mute, !isWaitingUser);
|
||||||
|
toggleButton(_screencast, !isWaitingUser);
|
||||||
|
const auto hangupShown = !_decline->toggled()
|
||||||
&& !_cancel->toggled();
|
&& !_cancel->toggled();
|
||||||
if (_hangupShown != hangupShown) {
|
if (_hangupShown != hangupShown) {
|
||||||
_hangupShown = hangupShown;
|
_hangupShown = hangupShown;
|
||||||
_hangupShownProgress.start([this] { updateHangupGeometry(); }, _hangupShown ? 0. : 1., _hangupShown ? 1. : 0., st::callPanelDuration, anim::sineInOut);
|
_hangupShownProgress.start(
|
||||||
|
[this] { updateHangupGeometry(); },
|
||||||
|
_hangupShown ? 0. : 1.,
|
||||||
|
_hangupShown ? 1. : 0.,
|
||||||
|
st::callPanelDuration,
|
||||||
|
anim::sineInOut);
|
||||||
}
|
}
|
||||||
const auto answerHangupRedialState = incomingWaiting
|
const auto answerHangupRedialState = incomingWaiting
|
||||||
? AnswerHangupRedialState::Answer
|
? AnswerHangupRedialState::Answer
|
||||||
: (state == State::Busy)
|
: isBusy
|
||||||
? AnswerHangupRedialState::Redial
|
? AnswerHangupRedialState::Redial
|
||||||
|
: isWaitingUser
|
||||||
|
? AnswerHangupRedialState::StartCall
|
||||||
: AnswerHangupRedialState::Hangup;
|
: AnswerHangupRedialState::Hangup;
|
||||||
if (_answerHangupRedialState != answerHangupRedialState) {
|
if (_answerHangupRedialState != answerHangupRedialState) {
|
||||||
_answerHangupRedialState = answerHangupRedialState;
|
_answerHangupRedialState = answerHangupRedialState;
|
||||||
|
@ -860,6 +910,7 @@ void Panel::refreshAnswerHangupRedialLabel() {
|
||||||
case AnswerHangupRedialState::Answer: return tr::lng_call_accept();
|
case AnswerHangupRedialState::Answer: return tr::lng_call_accept();
|
||||||
case AnswerHangupRedialState::Hangup: return tr::lng_call_end_call();
|
case AnswerHangupRedialState::Hangup: return tr::lng_call_end_call();
|
||||||
case AnswerHangupRedialState::Redial: return tr::lng_call_redial();
|
case AnswerHangupRedialState::Redial: return tr::lng_call_redial();
|
||||||
|
case AnswerHangupRedialState::StartCall: return tr::lng_call_start();
|
||||||
}
|
}
|
||||||
Unexpected("AnswerHangupRedialState value.");
|
Unexpected("AnswerHangupRedialState value.");
|
||||||
}());
|
}());
|
||||||
|
@ -891,6 +942,7 @@ void Panel::updateStatusText(State state) {
|
||||||
case State::WaitingIncoming: return tr::lng_call_status_incoming(tr::now);
|
case State::WaitingIncoming: return tr::lng_call_status_incoming(tr::now);
|
||||||
case State::Ringing: return tr::lng_call_status_ringing(tr::now);
|
case State::Ringing: return tr::lng_call_status_ringing(tr::now);
|
||||||
case State::Busy: return tr::lng_call_status_busy(tr::now);
|
case State::Busy: return tr::lng_call_status_busy(tr::now);
|
||||||
|
case State::WaitingUserConfirmation: return tr::lng_call_status_sure(tr::now);
|
||||||
}
|
}
|
||||||
Unexpected("State in stateChanged()");
|
Unexpected("State in stateChanged()");
|
||||||
};
|
};
|
||||||
|
|
|
@ -77,6 +77,8 @@ public:
|
||||||
bool withAudio) override;
|
bool withAudio) override;
|
||||||
void chooseSourceStop() override;
|
void chooseSourceStop() override;
|
||||||
|
|
||||||
|
[[nodiscard]] rpl::producer<bool> startOutgoingRequests() const;
|
||||||
|
|
||||||
[[nodiscard]] rpl::lifetime &lifetime();
|
[[nodiscard]] rpl::lifetime &lifetime();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -87,6 +89,7 @@ private:
|
||||||
Answer,
|
Answer,
|
||||||
Hangup,
|
Hangup,
|
||||||
Redial,
|
Redial,
|
||||||
|
StartCall,
|
||||||
};
|
};
|
||||||
|
|
||||||
[[nodiscard]] not_null<Ui::RpWindow*> window() const;
|
[[nodiscard]] not_null<Ui::RpWindow*> window() const;
|
||||||
|
@ -147,9 +150,10 @@ private:
|
||||||
bool _outgoingPreviewInBody = false;
|
bool _outgoingPreviewInBody = false;
|
||||||
std::optional<AnswerHangupRedialState> _answerHangupRedialState;
|
std::optional<AnswerHangupRedialState> _answerHangupRedialState;
|
||||||
Ui::Animations::Simple _hangupShownProgress;
|
Ui::Animations::Simple _hangupShownProgress;
|
||||||
object_ptr<Ui::CallButton> _screencast;
|
object_ptr<Ui::FadeWrap<Ui::CallButton>> _screencast;
|
||||||
object_ptr<Ui::CallButton> _camera;
|
object_ptr<Ui::CallButton> _camera;
|
||||||
object_ptr<Ui::CallButton> _mute;
|
object_ptr<Ui::FadeWrap<Ui::CallButton>> _startVideo;
|
||||||
|
object_ptr<Ui::FadeWrap<Ui::CallButton>> _mute;
|
||||||
object_ptr<Ui::FlatLabel> _name;
|
object_ptr<Ui::FlatLabel> _name;
|
||||||
object_ptr<Ui::FlatLabel> _status;
|
object_ptr<Ui::FlatLabel> _status;
|
||||||
object_ptr<Ui::RpWidget> _fingerprint = { nullptr };
|
object_ptr<Ui::RpWidget> _fingerprint = { nullptr };
|
||||||
|
|
Loading…
Add table
Reference in a new issue