Reuse call panel if current call is in Busy state.
This commit is contained in:
		
							parent
							
								
									0a6e012e90
								
							
						
					
					
						commit
						299dc3fc96
					
				
					 6 changed files with 56 additions and 30 deletions
				
			
		| 
						 | 
					@ -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);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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(_answer, (_call->type() == Call::Type::Incoming) && ((state == State::Starting) || (state == State::WaitingIncoming)), st::callAnswer);
 | 
				
			||||||
		syncButton(_hangup, (state != State::Busy), st::callHangup);
 | 
							syncButton(_hangup, (state != State::Busy), st::callHangup);
 | 
				
			||||||
		syncButton(_redial, (state == State::Busy), st::callAnswer);
 | 
							syncButton(_redial, (state == State::Busy), st::callAnswer);
 | 
				
			||||||
		syncButton(_cancel, (state == State::Busy), st::callCancel);
 | 
							syncButton(_cancel, (state == State::Busy), st::callCancel);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if (buttonsUpdated) {
 | 
						if (buttonsUpdated) {
 | 
				
			||||||
		refreshCallbacks();
 | 
							refreshCallbacks();
 | 
				
			||||||
		updateControlsGeometry();
 | 
							updateControlsGeometry();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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 };
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		
		Reference in a new issue