Reuse call panel if current call is in Busy state.

This commit is contained in:
John Preston 2017-05-04 15:29:32 +03:00
parent 0a6e012e90
commit 299dc3fc96
6 changed files with 56 additions and 30 deletions

View File

@ -62,8 +62,17 @@ public:
weak_unique_ptr() = default; weak_unique_ptr() = default;
weak_unique_ptr(T *value) : _guarded(value ? value->getGuarded() : std::shared_ptr<enable_weak_from_this*>()) { weak_unique_ptr(T *value) : _guarded(value ? value->getGuarded() : std::shared_ptr<enable_weak_from_this*>()) {
} }
weak_unique_ptr(const std::unique_ptr<T> &value) : _guarded(value ? value->getGuarded() : std::shared_ptr<enable_weak_from_this*>()) { weak_unique_ptr(const std::unique_ptr<T> &value) : weak_unique_ptr(value.get()) {
} }
weak_unique_ptr &operator=(T *value) {
_guarded = value ? value->getGuarded() : std::shared_ptr<enable_weak_from_this*>();
return *this;
}
weak_unique_ptr &operator=(const std::unique_ptr<T> &value) {
return (*this = value.get());
}
T *get() const noexcept { T *get() const noexcept {
if (auto shared = _guarded.lock()) { if (auto shared = _guarded.lock()) {
return static_cast<T*>(*shared); return static_cast<T*>(*shared);

View File

@ -91,7 +91,7 @@ callMuteRight: 12px;
callNameTop: 15px; callNameTop: 15px;
callName: FlatLabel(defaultFlatLabel) { callName: FlatLabel(defaultFlatLabel) {
width: 260px; width: 260px;
maxHeight: 24px; maxHeight: 30px;
textFg: callNameFg; textFg: callNameFg;
align: align(top); align: align(top);
style: TextStyle(defaultTextStyle) { style: TextStyle(defaultTextStyle) {

View File

@ -41,8 +41,7 @@ constexpr auto kServerConfigUpdateTimeoutMs = 24 * 3600 * TimeMs(1000);
Instance::Instance() = default; Instance::Instance() = default;
void Instance::startOutgoingCall(gsl::not_null<UserData*> user) { void Instance::startOutgoingCall(gsl::not_null<UserData*> user) {
finishCurrentBusyCall(); if (alreadyInCall()) { // Already in a call.
if (_currentCall) { // Already in a call.
_currentCallPanel->showAndActivate(); _currentCallPanel->showAndActivate();
return; return;
} }
@ -111,8 +110,15 @@ void Instance::destroyCall(gsl::not_null<Call*> call) {
} }
void Instance::createCall(gsl::not_null<UserData*> user, Call::Type type) { void Instance::createCall(gsl::not_null<UserData*> user, Call::Type type) {
_currentCall = std::make_unique<Call>(getCallDelegate(), user, type); auto call = std::make_unique<Call>(getCallDelegate(), user, type);;
_currentCallPanel = std::make_unique<Panel>(_currentCall.get()); if (_currentCall) {
_currentCallPanel->replaceCall(call.get());
std::swap(_currentCall, call);
call->hangup();
} else {
_currentCallPanel = std::make_unique<Panel>(call.get());
_currentCall = std::move(call);
}
_currentCallChanged.notify(_currentCall.get(), true); _currentCallChanged.notify(_currentCall.get(), true);
refreshServerConfig(); refreshServerConfig();
refreshDhConfig(); refreshDhConfig();
@ -259,10 +265,9 @@ void Instance::handleCallUpdate(const MTPPhoneCall &call) {
} else if (user->isSelf()) { } else if (user->isSelf()) {
LOG(("API Error: Self found in phoneCallRequested.")); LOG(("API Error: Self found in phoneCallRequested."));
} }
finishCurrentBusyCall(); if (alreadyInCall() || !user || user->isSelf()) {
if (_currentCall || !user || user->isSelf()) {
request(MTPphone_DiscardCall(MTP_inputPhoneCall(phoneCall.vid, phoneCall.vaccess_hash), MTP_int(0), MTP_phoneCallDiscardReasonBusy(), MTP_long(0))).send(); 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.")); LOG(("Ignoring too old call."));
} else { } else {
createCall(user, Call::Type::Incoming); createCall(user, Call::Type::Incoming);
@ -273,10 +278,8 @@ void Instance::handleCallUpdate(const MTPPhoneCall &call) {
} }
} }
void Instance::finishCurrentBusyCall() { bool Instance::alreadyInCall() {
if (_currentCall && _currentCall->state() == Call::State::Busy) { return (_currentCall && _currentCall->state() != Call::State::Busy);
_currentCall->hangup();
}
} }
Instance::~Instance() = default; Instance::~Instance() = default;

View File

@ -71,7 +71,7 @@ private:
void refreshDhConfig(); void refreshDhConfig();
void refreshServerConfig(); void refreshServerConfig();
void finishCurrentBusyCall(); bool alreadyInCall();
void handleCallUpdate(const MTPPhoneCall &call); void handleCallUpdate(const MTPPhoneCall &call);
DhConfig _dhConfig; DhConfig _dhConfig;

View File

@ -106,7 +106,6 @@ QImage Panel::Button::prepareRippleMask() const {
Panel::Panel(gsl::not_null<Call*> call) Panel::Panel(gsl::not_null<Call*> call)
: _call(call) : _call(call)
, _user(call->user()) , _user(call->user())
, _hangup(this, st::callHangup)
, _mute(this, st::callMuteToggle) , _mute(this, st::callMuteToggle)
, _name(this, st::callName) , _name(this, st::callName)
, _status(this, st::callStatus) { , _status(this, st::callStatus) {
@ -124,6 +123,13 @@ void Panel::showAndActivate() {
setFocus(); setFocus();
} }
void Panel::replaceCall(gsl::not_null<Call*> call) {
_call = call;
_user = call->user();
reinitControls();
updateControlsGeometry();
}
bool Panel::event(QEvent *e) { bool Panel::event(QEvent *e) {
if (e->type() == QEvent::WindowDeactivate) { if (e->type() == QEvent::WindowDeactivate) {
if (_call && _call->state() == State::Established) { if (_call && _call->state() == State::Established) {
@ -138,20 +144,12 @@ void Panel::hideDeactivated() {
} }
void Panel::initControls() { 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] { _mute->setClickedCallback([this] {
_call->setMute(!_call->isMute()); _call->setMute(!_call->isMute());
}); });
subscribe(_call->muteChanged(), [this](bool mute) { subscribe(_call->muteChanged(), [this](bool mute) {
_mute->setIconOverride(mute ? &st::callUnmuteIcon : nullptr); _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) { subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(Notify::PeerUpdate::Flag::NameChanged, [this](const Notify::PeerUpdate &update) {
if (!_call || update.peer != _call->user()) { if (!_call || update.peer != _call->user()) {
return; return;
@ -159,12 +157,22 @@ void Panel::initControls() {
_name->setText(App::peerName(_call->user())); _name->setText(App::peerName(_call->user()));
updateControlsGeometry(); updateControlsGeometry();
})); }));
updateStatusText(_call->state());
_updateDurationTimer.setCallback([this] { _updateDurationTimer.setCallback([this] {
if (_call) { if (_call) {
updateStatusText(_call->state()); 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() { void Panel::refreshCallbacks() {
@ -459,11 +467,12 @@ void Panel::stateChanged(State state) {
} }
buttonsUpdated = true; buttonsUpdated = true;
}; };
syncButton(_answer, (state == State::Starting) || (state == State::WaitingIncoming), st::callAnswer); if (_call) {
syncButton(_hangup, (state != State::Busy), st::callHangup); syncButton(_answer, (_call->type() == Call::Type::Incoming) && ((state == State::Starting) || (state == State::WaitingIncoming)), st::callAnswer);
syncButton(_redial, (state == State::Busy), st::callAnswer); syncButton(_hangup, (state != State::Busy), st::callHangup);
syncButton(_cancel, (state == State::Busy), st::callCancel); syncButton(_redial, (state == State::Busy), st::callAnswer);
syncButton(_cancel, (state == State::Busy), st::callCancel);
}
if (buttonsUpdated) { if (buttonsUpdated) {
refreshCallbacks(); refreshCallbacks();
updateControlsGeometry(); updateControlsGeometry();

View File

@ -38,6 +38,8 @@ public:
void showAndActivate(); void showAndActivate();
void replaceCall(gsl::not_null<Call*> call);
protected: protected:
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
void resizeEvent(QResizeEvent *e) override; void resizeEvent(QResizeEvent *e) override;
@ -58,6 +60,7 @@ private:
bool tooltipWindowActive() const override; bool tooltipWindowActive() const override;
void initControls(); void initControls();
void reinitControls();
void initLayout(); void initLayout();
void initGeometry(); void initGeometry();
void refreshCallbacks(); void refreshCallbacks();
@ -89,9 +92,11 @@ private:
QPoint _dragStartMousePosition; QPoint _dragStartMousePosition;
QPoint _dragStartMyPosition; QPoint _dragStartMyPosition;
int _stateChangedSubscription = 0;
class Button; class Button;
object_ptr<Ui::IconButton> _close = { nullptr }; object_ptr<Ui::IconButton> _close = { nullptr };
object_ptr<Button> _hangup; object_ptr<Button> _hangup = { nullptr };
object_ptr<Button> _cancel = { nullptr }; object_ptr<Button> _cancel = { nullptr };
object_ptr<Button> _answer = { nullptr }; object_ptr<Button> _answer = { nullptr };
object_ptr<Button> _redial = { nullptr }; object_ptr<Button> _redial = { nullptr };