From 299dc3fc96a90f399b376d77f2316ce0c958cd30 Mon Sep 17 00:00:00 2001 From: John Preston Date: Thu, 4 May 2017 15:29:32 +0300 Subject: [PATCH] Reuse call panel if current call is in Busy state. --- Telegram/SourceFiles/base/weak_unique_ptr.h | 11 +++++- Telegram/SourceFiles/calls/calls.style | 2 +- Telegram/SourceFiles/calls/calls_instance.cpp | 25 ++++++------ Telegram/SourceFiles/calls/calls_instance.h | 2 +- Telegram/SourceFiles/calls/calls_panel.cpp | 39 ++++++++++++------- Telegram/SourceFiles/calls/calls_panel.h | 7 +++- 6 files changed, 56 insertions(+), 30 deletions(-) diff --git a/Telegram/SourceFiles/base/weak_unique_ptr.h b/Telegram/SourceFiles/base/weak_unique_ptr.h index 3e7b5d46d..9e57be4af 100644 --- a/Telegram/SourceFiles/base/weak_unique_ptr.h +++ b/Telegram/SourceFiles/base/weak_unique_ptr.h @@ -62,8 +62,17 @@ public: weak_unique_ptr() = default; weak_unique_ptr(T *value) : _guarded(value ? value->getGuarded() : std::shared_ptr()) { } - weak_unique_ptr(const std::unique_ptr &value) : _guarded(value ? value->getGuarded() : std::shared_ptr()) { + weak_unique_ptr(const std::unique_ptr &value) : weak_unique_ptr(value.get()) { } + + weak_unique_ptr &operator=(T *value) { + _guarded = value ? value->getGuarded() : std::shared_ptr(); + return *this; + } + weak_unique_ptr &operator=(const std::unique_ptr &value) { + return (*this = value.get()); + } + T *get() const noexcept { if (auto shared = _guarded.lock()) { return static_cast(*shared); diff --git a/Telegram/SourceFiles/calls/calls.style b/Telegram/SourceFiles/calls/calls.style index aa798f111..07ba42007 100644 --- a/Telegram/SourceFiles/calls/calls.style +++ b/Telegram/SourceFiles/calls/calls.style @@ -91,7 +91,7 @@ callMuteRight: 12px; callNameTop: 15px; callName: FlatLabel(defaultFlatLabel) { width: 260px; - maxHeight: 24px; + maxHeight: 30px; textFg: callNameFg; align: align(top); style: TextStyle(defaultTextStyle) { diff --git a/Telegram/SourceFiles/calls/calls_instance.cpp b/Telegram/SourceFiles/calls/calls_instance.cpp index 536ab37e8..8a687119c 100644 --- a/Telegram/SourceFiles/calls/calls_instance.cpp +++ b/Telegram/SourceFiles/calls/calls_instance.cpp @@ -41,8 +41,7 @@ constexpr auto kServerConfigUpdateTimeoutMs = 24 * 3600 * TimeMs(1000); Instance::Instance() = default; void Instance::startOutgoingCall(gsl::not_null user) { - finishCurrentBusyCall(); - if (_currentCall) { // Already in a call. + if (alreadyInCall()) { // Already in a call. _currentCallPanel->showAndActivate(); return; } @@ -111,8 +110,15 @@ void Instance::destroyCall(gsl::not_null call) { } void Instance::createCall(gsl::not_null user, Call::Type type) { - _currentCall = std::make_unique(getCallDelegate(), user, type); - _currentCallPanel = std::make_unique(_currentCall.get()); + auto call = std::make_unique(getCallDelegate(), user, type);; + if (_currentCall) { + _currentCallPanel->replaceCall(call.get()); + std::swap(_currentCall, call); + call->hangup(); + } else { + _currentCallPanel = std::make_unique(call.get()); + _currentCall = std::move(call); + } _currentCallChanged.notify(_currentCall.get(), true); refreshServerConfig(); refreshDhConfig(); @@ -259,10 +265,9 @@ void Instance::handleCallUpdate(const MTPPhoneCall &call) { } else if (user->isSelf()) { LOG(("API Error: Self found in phoneCallRequested.")); } - finishCurrentBusyCall(); - if (_currentCall || !user || user->isSelf()) { + if (alreadyInCall() || !user || user->isSelf()) { request(MTPphone_DiscardCall(MTP_inputPhoneCall(phoneCall.vid, phoneCall.vaccess_hash), MTP_int(0), MTP_phoneCallDiscardReasonBusy(), MTP_long(0))).send(); - } else if (phoneCall.vdate.v + Global::CallRingTimeoutMs() / 1000 < unixtime()) { + } else if (phoneCall.vdate.v + (Global::CallRingTimeoutMs() / 1000) < unixtime()) { LOG(("Ignoring too old call.")); } else { createCall(user, Call::Type::Incoming); @@ -273,10 +278,8 @@ void Instance::handleCallUpdate(const MTPPhoneCall &call) { } } -void Instance::finishCurrentBusyCall() { - if (_currentCall && _currentCall->state() == Call::State::Busy) { - _currentCall->hangup(); - } +bool Instance::alreadyInCall() { + return (_currentCall && _currentCall->state() != Call::State::Busy); } Instance::~Instance() = default; diff --git a/Telegram/SourceFiles/calls/calls_instance.h b/Telegram/SourceFiles/calls/calls_instance.h index bde38bfd0..05d8c2eb4 100644 --- a/Telegram/SourceFiles/calls/calls_instance.h +++ b/Telegram/SourceFiles/calls/calls_instance.h @@ -71,7 +71,7 @@ private: void refreshDhConfig(); void refreshServerConfig(); - void finishCurrentBusyCall(); + bool alreadyInCall(); void handleCallUpdate(const MTPPhoneCall &call); DhConfig _dhConfig; diff --git a/Telegram/SourceFiles/calls/calls_panel.cpp b/Telegram/SourceFiles/calls/calls_panel.cpp index 0ae43869b..7990e264c 100644 --- a/Telegram/SourceFiles/calls/calls_panel.cpp +++ b/Telegram/SourceFiles/calls/calls_panel.cpp @@ -106,7 +106,6 @@ QImage Panel::Button::prepareRippleMask() const { Panel::Panel(gsl::not_null call) : _call(call) , _user(call->user()) -, _hangup(this, st::callHangup) , _mute(this, st::callMuteToggle) , _name(this, st::callName) , _status(this, st::callStatus) { @@ -124,6 +123,13 @@ void Panel::showAndActivate() { setFocus(); } +void Panel::replaceCall(gsl::not_null call) { + _call = call; + _user = call->user(); + reinitControls(); + updateControlsGeometry(); +} + bool Panel::event(QEvent *e) { if (e->type() == QEvent::WindowDeactivate) { if (_call && _call->state() == State::Established) { @@ -138,20 +144,12 @@ void Panel::hideDeactivated() { } void Panel::initControls() { - subscribe(_call->stateChanged(), [this](State state) { stateChanged(state); }); - if (_call->type() == Type::Incoming) { - _answer.create(this, st::callAnswer); - } - - refreshCallbacks(); - _mute->setClickedCallback([this] { _call->setMute(!_call->isMute()); }); subscribe(_call->muteChanged(), [this](bool mute) { _mute->setIconOverride(mute ? &st::callUnmuteIcon : nullptr); }); - _name->setText(App::peerName(_call->user())); subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(Notify::PeerUpdate::Flag::NameChanged, [this](const Notify::PeerUpdate &update) { if (!_call || update.peer != _call->user()) { return; @@ -159,12 +157,22 @@ void Panel::initControls() { _name->setText(App::peerName(_call->user())); updateControlsGeometry(); })); - updateStatusText(_call->state()); _updateDurationTimer.setCallback([this] { if (_call) { updateStatusText(_call->state()); } }); + + reinitControls(); +} + +void Panel::reinitControls() { + unsubscribe(_stateChangedSubscription); + _stateChangedSubscription = subscribe(_call->stateChanged(), [this](State state) { stateChanged(state); }); + stateChanged(_call->state()); + + _name->setText(App::peerName(_call->user())); + updateStatusText(_call->state()); } void Panel::refreshCallbacks() { @@ -459,11 +467,12 @@ void Panel::stateChanged(State state) { } buttonsUpdated = true; }; - syncButton(_answer, (state == State::Starting) || (state == State::WaitingIncoming), st::callAnswer); - syncButton(_hangup, (state != State::Busy), st::callHangup); - syncButton(_redial, (state == State::Busy), st::callAnswer); - syncButton(_cancel, (state == State::Busy), st::callCancel); - + if (_call) { + syncButton(_answer, (_call->type() == Call::Type::Incoming) && ((state == State::Starting) || (state == State::WaitingIncoming)), st::callAnswer); + syncButton(_hangup, (state != State::Busy), st::callHangup); + syncButton(_redial, (state == State::Busy), st::callAnswer); + syncButton(_cancel, (state == State::Busy), st::callCancel); + } if (buttonsUpdated) { refreshCallbacks(); updateControlsGeometry(); diff --git a/Telegram/SourceFiles/calls/calls_panel.h b/Telegram/SourceFiles/calls/calls_panel.h index b5ab46e9c..25b94a3d5 100644 --- a/Telegram/SourceFiles/calls/calls_panel.h +++ b/Telegram/SourceFiles/calls/calls_panel.h @@ -38,6 +38,8 @@ public: void showAndActivate(); + void replaceCall(gsl::not_null call); + protected: void paintEvent(QPaintEvent *e) override; void resizeEvent(QResizeEvent *e) override; @@ -58,6 +60,7 @@ private: bool tooltipWindowActive() const override; void initControls(); + void reinitControls(); void initLayout(); void initGeometry(); void refreshCallbacks(); @@ -89,9 +92,11 @@ private: QPoint _dragStartMousePosition; QPoint _dragStartMyPosition; + int _stateChangedSubscription = 0; + class Button; object_ptr _close = { nullptr }; - object_ptr