diff --git a/Telegram/SourceFiles/calls/calls_call.h b/Telegram/SourceFiles/calls/calls_call.h index f6e05c7b1..1a72983e1 100644 --- a/Telegram/SourceFiles/calls/calls_call.h +++ b/Telegram/SourceFiles/calls/calls_call.h @@ -259,7 +259,7 @@ private: const not_null _user; MTP::Sender _api; Type _type = Type::Outgoing; - rpl::variable _state = State::WaitingUserConfirmation; + rpl::variable _state = State::Starting; rpl::variable _remoteAudioState = RemoteAudioState::Active; rpl::variable _remoteVideoState; diff --git a/Telegram/SourceFiles/calls/calls_instance.cpp b/Telegram/SourceFiles/calls/calls_instance.cpp index 230d862b2..e48a41a93 100644 --- a/Telegram/SourceFiles/calls/calls_instance.cpp +++ b/Telegram/SourceFiles/calls/calls_instance.cpp @@ -324,31 +324,52 @@ void Instance::destroyCall(not_null call) { } } -void Instance::createCall(not_null user, Call::Type type, bool video) { - auto call = std::make_unique(_delegate.get(), user, type, video); - const auto raw = call.get(); +void Instance::createCall( + not_null user, + Call::Type type, + bool isVideo) { + struct Performer final { + explicit Performer(Fn callback) + : callback(std::move(callback)) { + } + Fn callback; + }; + const auto performer = Performer([=]( + bool video, + bool isConfirmed, + const Performer &repeater) { + const auto delegate = _delegate.get(); + auto call = std::make_unique(delegate, user, type, video); + if (isConfirmed) { + call->applyUserConfirmation(); + } + const auto raw = call.get(); - user->session().account().sessionChanges( - ) | rpl::start_with_next([=] { - destroyCall(raw); - }, raw->lifetime()); + user->session().account().sessionChanges( + ) | rpl::start_with_next([=] { + destroyCall(raw); + }, raw->lifetime()); - if (_currentCall) { - _currentCallPanel->replaceCall(raw); - std::swap(_currentCall, call); - call->hangup(); - } else { - _currentCallPanel = std::make_unique(raw); - _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); + if (_currentCall) { + _currentCallPanel->replaceCall(raw); + std::swap(_currentCall, call); + call->hangup(); + } else { + _currentCallPanel = std::make_unique(raw); + _currentCall = std::move(call); + } + if (raw->state() == Call::State::WaitingUserConfirmation) { + _currentCallPanel->startOutgoingRequests( + ) | rpl::start_with_next([=](bool video) { + repeater.callback(video, true, repeater); + }, raw->lifetime()); + } else { + refreshServerConfig(&user->session()); + refreshDhConfig(); + } + _currentCallChanges.fire_copy(raw); + }); + performer.callback(isVideo, false, performer); } void Instance::destroyGroupCall(not_null call) { diff --git a/Telegram/SourceFiles/calls/calls_instance.h b/Telegram/SourceFiles/calls/calls_instance.h index 750821ca8..fcfbc55cf 100644 --- a/Telegram/SourceFiles/calls/calls_instance.h +++ b/Telegram/SourceFiles/calls/calls_instance.h @@ -113,7 +113,7 @@ private: not_null ensureSoundLoaded(const QString &key); void playSoundOnce(const QString &key); - void createCall(not_null user, CallType type, bool video); + void createCall(not_null user, CallType type, bool isVideo); void destroyCall(not_null call); void createGroupCall( diff --git a/Telegram/SourceFiles/calls/calls_panel.cpp b/Telegram/SourceFiles/calls/calls_panel.cpp index 6f116555f..99177e487 100644 --- a/Telegram/SourceFiles/calls/calls_panel.cpp +++ b/Telegram/SourceFiles/calls/calls_panel.cpp @@ -80,9 +80,6 @@ Panel::Panel(not_null call) st::callScreencastOn, &st::callScreencastOff)) , _camera(widget(), st::callCameraMute, &st::callCameraUnmute) -, _startVideo( - widget(), - object_ptr(widget(), st::callStartVideo)) , _mute( widget(), object_ptr( @@ -281,6 +278,7 @@ void Panel::initControls() { } else if (_call->isIncomingWaiting()) { _call->answer(); } else if (state == State::WaitingUserConfirmation) { + _startOutgoingRequests.fire(false); } else { _call->hangup(); } @@ -292,7 +290,6 @@ void Panel::initControls() { }; _decline->entity()->setClickedCallback(hangupCallback); _cancel->entity()->setClickedCallback(hangupCallback); - _startVideo->entity()->setText(tr::lng_call_start_video()); reinitWithCall(_call); @@ -334,14 +331,10 @@ rpl::lifetime &Panel::chooseSourceInstanceLifetime() { } rpl::producer Panel::startOutgoingRequests() const { - const auto filter = [=] { + return _startOutgoingRequests.events( + ) | rpl::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( @@ -478,7 +471,9 @@ void Panel::reinitWithCall(Call *call) { rpl::combine( _call->stateValue(), - _call->videoOutgoing()->renderNextFrame() + rpl::single( + rpl::empty_value() + ) | rpl::then(_call->videoOutgoing()->renderNextFrame()) ) | rpl::start_with_next([=](State state, auto) { if (state != State::Ended && state != State::EndedByOtherDevice @@ -523,7 +518,9 @@ void Panel::reinitWithCall(Call *call) { _decline->raise(); _cancel->raise(); _camera->raise(); - _startVideo->raise(); + if (_startVideo) { + _startVideo->raise(); + } _mute->raise(); _powerSaveBlocker = std::make_unique( @@ -794,7 +791,7 @@ void Panel::updateHangupGeometry() { _camera->moveToLeft( hangupRight - _mute->width() + _screencast->width(), _buttonsTop); - if (_startVideo->toggled()) { + if (_startVideo) { _startVideo->moveToLeft(_camera->x(), _camera->y()); } } @@ -849,12 +846,18 @@ void Panel::stateChanged(State state) { if (isBusy) { _powerSaveBlocker = nullptr; } - if (_startVideo->toggled() && !isWaitingUser) { - _startVideo->toggle(false, anim::type::instant); - } else if (!_startVideo->toggled() && isWaitingUser) { - _startVideo->toggle(true, anim::type::instant); + if (_startVideo && !isWaitingUser) { + _startVideo = nullptr; + } else if (!_startVideo && isWaitingUser) { + _startVideo = base::make_unique_q( + widget(), + st::callStartVideo); + _startVideo->setText(tr::lng_call_start_video()); + _startVideo->clicks() | rpl::map_to(true) | rpl::start_to_stream( + _startOutgoingRequests, + _startVideo->lifetime()); } - _camera->setVisible(!_startVideo->toggled()); + _camera->setVisible(!_startVideo); const auto toggleButton = [&](auto &&button, bool visible) { button->toggle( diff --git a/Telegram/SourceFiles/calls/calls_panel.h b/Telegram/SourceFiles/calls/calls_panel.h index e7f0ac77f..77c9768f2 100644 --- a/Telegram/SourceFiles/calls/calls_panel.h +++ b/Telegram/SourceFiles/calls/calls_panel.h @@ -152,7 +152,7 @@ private: Ui::Animations::Simple _hangupShownProgress; object_ptr> _screencast; object_ptr _camera; - object_ptr> _startVideo; + base::unique_qptr _startVideo; object_ptr> _mute; object_ptr _name; object_ptr _status; @@ -167,6 +167,8 @@ private: base::Timer _updateDurationTimer; base::Timer _updateOuterRippleTimer; + rpl::event_stream _startOutgoingRequests; + }; } // namespace Calls