mirror of
https://github.com/telegramdesktop/tdesktop
synced 2025-01-16 04:02:09 +00:00
Move call management to Core::App.
This commit is contained in:
parent
8c4d3a86e7
commit
79a361ba43
@ -1721,7 +1721,7 @@ void Updates::feedUpdate(const MTPUpdate &update) {
|
||||
} break;
|
||||
|
||||
case mtpc_updatePhoneCall: {
|
||||
session().calls().handleUpdate(update.c_updatePhoneCall());
|
||||
Core::App().calls().handleUpdate(&session(), update.c_updatePhoneCall());
|
||||
} break;
|
||||
|
||||
case mtpc_updateUserBlocked: {
|
||||
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "styles/style_boxes.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "ui/effects/ripple_animation.h"
|
||||
#include "core/application.h"
|
||||
#include "calls/calls_instance.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
@ -18,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "window/window_session_controller.h"
|
||||
#include "main/main_session.h"
|
||||
#include "data/data_session.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_media_types.h"
|
||||
#include "data/data_user.h"
|
||||
#include "app.h"
|
||||
@ -237,11 +239,11 @@ void BoxController::prepare() {
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
subscribe(session().calls().newServiceMessage(), [=](FullMsgId msgId) {
|
||||
if (const auto item = session().data().message(msgId)) {
|
||||
insertRow(item, InsertWay::Prepend);
|
||||
}
|
||||
});
|
||||
session().changes().messageUpdates(
|
||||
Data::MessageUpdate::Flag::CallAdded
|
||||
) | rpl::start_with_next([=](const Data::MessageUpdate &update) {
|
||||
insertRow(update.item, InsertWay::Prepend);
|
||||
}, lifetime());
|
||||
|
||||
delegate()->peerListSetTitle(tr::lng_call_box_title());
|
||||
setDescriptionText(tr::lng_contacts_loading(tr::now));
|
||||
@ -315,7 +317,7 @@ void BoxController::rowActionClicked(not_null<PeerListRow*> row) {
|
||||
auto user = row->peer()->asUser();
|
||||
Assert(user != nullptr);
|
||||
|
||||
user->session().calls().startOutgoingCall(user);
|
||||
Core::App().calls().startOutgoingCall(user);
|
||||
}
|
||||
|
||||
void BoxController::receivedCalls(const QVector<MTPMessage> &result) {
|
||||
|
@ -131,7 +131,8 @@ bool Call::isIncomingWaiting() const {
|
||||
if (type() != Call::Type::Incoming) {
|
||||
return false;
|
||||
}
|
||||
return (_state == State::Starting) || (_state == State::WaitingIncoming);
|
||||
return (state() == State::Starting)
|
||||
|| (state() == State::WaitingIncoming);
|
||||
}
|
||||
|
||||
void Call::start(bytes::const_span random) {
|
||||
@ -142,13 +143,14 @@ void Call::start(bytes::const_span random) {
|
||||
Assert(!_dhConfig.p.empty());
|
||||
|
||||
generateModExpFirst(random);
|
||||
if (_state == State::Starting || _state == State::Requesting) {
|
||||
const auto state = _state.current();
|
||||
if (state == State::Starting || state == State::Requesting) {
|
||||
if (_type == Type::Outgoing) {
|
||||
startOutgoing();
|
||||
} else {
|
||||
startIncoming();
|
||||
}
|
||||
} else if (_state == State::ExchangingKeys
|
||||
} else if (state == State::ExchangingKeys
|
||||
&& _answerAfterDhConfigReceived) {
|
||||
answer();
|
||||
}
|
||||
@ -156,7 +158,7 @@ void Call::start(bytes::const_span random) {
|
||||
|
||||
void Call::startOutgoing() {
|
||||
Expects(_type == Type::Outgoing);
|
||||
Expects(_state == State::Requesting);
|
||||
Expects(_state.current() == State::Requesting);
|
||||
Expects(_gaHash.size() == kSha256Size);
|
||||
|
||||
_api.request(MTPphone_RequestCall(
|
||||
@ -206,12 +208,12 @@ void Call::startOutgoing() {
|
||||
|
||||
void Call::startIncoming() {
|
||||
Expects(_type == Type::Incoming);
|
||||
Expects(_state == State::Starting);
|
||||
Expects(_state.current() == State::Starting);
|
||||
|
||||
_api.request(MTPphone_ReceivedCall(
|
||||
MTP_inputPhoneCall(MTP_long(_id), MTP_long(_accessHash))
|
||||
)).done([=](const MTPBool &result) {
|
||||
if (_state == State::Starting) {
|
||||
if (_state.current() == State::Starting) {
|
||||
setState(State::WaitingIncoming);
|
||||
}
|
||||
}).fail([=](const RPCError &error) {
|
||||
@ -228,8 +230,9 @@ void Call::answer() {
|
||||
void Call::actuallyAnswer() {
|
||||
Expects(_type == Type::Incoming);
|
||||
|
||||
if (_state != State::Starting && _state != State::WaitingIncoming) {
|
||||
if (_state != State::ExchangingKeys
|
||||
const auto state = _state.current();
|
||||
if (state != State::Starting && state != State::WaitingIncoming) {
|
||||
if (state != State::ExchangingKeys
|
||||
|| !_answerAfterDhConfigReceived) {
|
||||
return;
|
||||
}
|
||||
@ -280,10 +283,11 @@ crl::time Call::getDurationMs() const {
|
||||
}
|
||||
|
||||
void Call::hangup() {
|
||||
if (_state == State::Busy) {
|
||||
const auto state = _state.current();
|
||||
if (state == State::Busy) {
|
||||
_delegate->callFinished(this);
|
||||
} else {
|
||||
auto missed = (_state == State::Ringing || (_state == State::Waiting && _type == Type::Outgoing));
|
||||
auto missed = (state == State::Ringing || (state == State::Waiting && _type == Type::Outgoing));
|
||||
auto declined = isIncomingWaiting();
|
||||
auto reason = missed ? MTP_phoneCallDiscardReasonMissed() :
|
||||
declined ? MTP_phoneCallDiscardReasonBusy() : MTP_phoneCallDiscardReasonHangup();
|
||||
@ -292,7 +296,7 @@ void Call::hangup() {
|
||||
}
|
||||
|
||||
void Call::redial() {
|
||||
if (_state != State::Busy) {
|
||||
if (_state.current() != State::Busy) {
|
||||
return;
|
||||
}
|
||||
Assert(_controller == nullptr);
|
||||
@ -384,7 +388,7 @@ bool Call::handleUpdate(const MTPPhoneCall &call) {
|
||||
return false;
|
||||
}
|
||||
if (_type == Type::Outgoing
|
||||
&& _state == State::Waiting
|
||||
&& _state.current() == State::Waiting
|
||||
&& data.vreceive_date().value_or_empty() != 0) {
|
||||
const auto &config = _user->session().serverConfig();
|
||||
_discardByTimeoutTimer.callOnce(config.callRingTimeoutMs);
|
||||
@ -399,7 +403,7 @@ bool Call::handleUpdate(const MTPPhoneCall &call) {
|
||||
return false;
|
||||
}
|
||||
if (_type == Type::Incoming
|
||||
&& _state == State::ExchangingKeys
|
||||
&& _state.current() == State::ExchangingKeys
|
||||
&& !_controller) {
|
||||
startConfirmedCall(data);
|
||||
}
|
||||
@ -432,7 +436,8 @@ bool Call::handleUpdate(const MTPPhoneCall &call) {
|
||||
}
|
||||
if (reason && reason->type() == mtpc_phoneCallDiscardReasonBusy) {
|
||||
setState(State::Busy);
|
||||
} else if (_type == Type::Outgoing || _state == State::HangingUp) {
|
||||
} else if (_type == Type::Outgoing
|
||||
|| _state.current() == State::HangingUp) {
|
||||
setState(State::Ended);
|
||||
} else {
|
||||
setState(State::EndedByOtherDevice);
|
||||
@ -460,7 +465,7 @@ bool Call::handleUpdate(const MTPPhoneCall &call) {
|
||||
void Call::confirmAcceptedCall(const MTPDphoneCallAccepted &call) {
|
||||
Expects(_type == Type::Outgoing);
|
||||
|
||||
if (_state == State::ExchangingKeys
|
||||
if (_state.current() == State::ExchangingKeys
|
||||
|| _controller) {
|
||||
LOG(("Call Warning: Unexpected confirmAcceptedCall."));
|
||||
return;
|
||||
@ -710,34 +715,33 @@ bool Call::checkCallFields(const MTPDphoneCallAccepted &call) {
|
||||
}
|
||||
|
||||
void Call::setState(State state) {
|
||||
if (_state == State::Failed) {
|
||||
if (_state.current() == State::Failed) {
|
||||
return;
|
||||
}
|
||||
if (_state == State::FailedHangingUp && state != State::Failed) {
|
||||
if (_state.current() == State::FailedHangingUp && state != State::Failed) {
|
||||
return;
|
||||
}
|
||||
if (_state != state) {
|
||||
if (_state.current() != state) {
|
||||
_state = state;
|
||||
_stateChanged.notify(state, true);
|
||||
|
||||
if (true
|
||||
&& _state != State::Starting
|
||||
&& _state != State::Requesting
|
||||
&& _state != State::Waiting
|
||||
&& _state != State::WaitingIncoming
|
||||
&& _state != State::Ringing) {
|
||||
&& state != State::Starting
|
||||
&& state != State::Requesting
|
||||
&& state != State::Waiting
|
||||
&& state != State::WaitingIncoming
|
||||
&& state != State::Ringing) {
|
||||
_waitingTrack.reset();
|
||||
}
|
||||
if (false
|
||||
|| _state == State::Ended
|
||||
|| _state == State::EndedByOtherDevice
|
||||
|| _state == State::Failed
|
||||
|| _state == State::Busy) {
|
||||
|| state == State::Ended
|
||||
|| state == State::EndedByOtherDevice
|
||||
|| state == State::Failed
|
||||
|| state == State::Busy) {
|
||||
// Destroy controller before destroying Call Panel,
|
||||
// so that the panel hide animation is smooth.
|
||||
destroyController();
|
||||
}
|
||||
switch (_state) {
|
||||
switch (state) {
|
||||
case State::Established:
|
||||
_startTime = crl::now();
|
||||
break;
|
||||
@ -794,16 +798,17 @@ void Call::finish(FinishType type, const MTPPhoneCallDiscardReason &reason) {
|
||||
|
||||
auto finalState = (type == FinishType::Ended) ? State::Ended : State::Failed;
|
||||
auto hangupState = (type == FinishType::Ended) ? State::HangingUp : State::FailedHangingUp;
|
||||
if (_state == State::Requesting) {
|
||||
const auto state = _state.current();
|
||||
if (state == State::Requesting) {
|
||||
_finishByTimeoutTimer.call(kHangupTimeoutMs, [this, finalState] { setState(finalState); });
|
||||
_finishAfterRequestingCall = type;
|
||||
return;
|
||||
}
|
||||
if (_state == State::HangingUp
|
||||
|| _state == State::FailedHangingUp
|
||||
|| _state == State::EndedByOtherDevice
|
||||
|| _state == State::Ended
|
||||
|| _state == State::Failed) {
|
||||
if (state == State::HangingUp
|
||||
|| state == State::FailedHangingUp
|
||||
|| state == State::EndedByOtherDevice
|
||||
|| state == State::Ended
|
||||
|| state == State::Failed) {
|
||||
return;
|
||||
}
|
||||
if (!_id) {
|
||||
|
@ -60,13 +60,13 @@ public:
|
||||
};
|
||||
Call(not_null<Delegate*> delegate, not_null<UserData*> user, Type type);
|
||||
|
||||
Type type() const {
|
||||
[[nodiscard]] Type type() const {
|
||||
return _type;
|
||||
}
|
||||
not_null<UserData*> user() const {
|
||||
[[nodiscard]] not_null<UserData*> user() const {
|
||||
return _user;
|
||||
}
|
||||
bool isIncomingWaiting() const;
|
||||
[[nodiscard]] bool isIncomingWaiting() const;
|
||||
|
||||
void start(bytes::const_span random);
|
||||
bool handleUpdate(const MTPPhoneCall &call);
|
||||
@ -89,10 +89,10 @@ public:
|
||||
Busy,
|
||||
};
|
||||
State state() const {
|
||||
return _state;
|
||||
return _state.current();
|
||||
}
|
||||
base::Observable<State> &stateChanged() {
|
||||
return _stateChanged;
|
||||
rpl::producer<State> stateValue() const {
|
||||
return _state.value();
|
||||
}
|
||||
|
||||
static constexpr auto kSignalBarStarting = -1;
|
||||
@ -126,6 +126,10 @@ public:
|
||||
void setAudioVolume(bool input, float level);
|
||||
void setAudioDuckingEnabled(bool enabled);
|
||||
|
||||
[[nodiscard]] rpl::lifetime &lifetime() {
|
||||
return _lifetime;
|
||||
}
|
||||
|
||||
~Call();
|
||||
|
||||
private:
|
||||
@ -166,10 +170,9 @@ private:
|
||||
not_null<UserData*> _user;
|
||||
MTP::Sender _api;
|
||||
Type _type = Type::Outgoing;
|
||||
State _state = State::Starting;
|
||||
rpl::variable<State> _state = State::Starting;
|
||||
FinishType _finishAfterRequestingCall = FinishType::None;
|
||||
bool _answerAfterDhConfigReceived = false;
|
||||
base::Observable<State> _stateChanged;
|
||||
int _signalBarCount = kSignalBarStarting;
|
||||
base::Observable<int> _signalBarCountChanged;
|
||||
crl::time _startTime = 0;
|
||||
@ -195,6 +198,8 @@ private:
|
||||
|
||||
std::unique_ptr<Media::Audio::Track> _waitingTrack;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
||||
void UpdateConfig(const std::string &data);
|
||||
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "mtproto/mtproto_dh_utils.h"
|
||||
#include "core/application.h"
|
||||
#include "main/main_session.h"
|
||||
#include "main/main_account.h"
|
||||
#include "apiwrap.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "boxes/confirm_box.h"
|
||||
@ -32,9 +33,14 @@ constexpr auto kServerConfigUpdateTimeoutMs = 24 * 3600 * crl::time(1000);
|
||||
|
||||
} // namespace
|
||||
|
||||
Instance::Instance(not_null<Main::Session*> session)
|
||||
: _session(session)
|
||||
, _api(&_session->mtp()) {
|
||||
Instance::Instance() = default;
|
||||
|
||||
Instance::~Instance() {
|
||||
for (const auto panel : _pendingPanels) {
|
||||
if (panel) {
|
||||
delete panel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Instance::startOutgoingCall(not_null<UserData*> user) {
|
||||
@ -44,8 +50,9 @@ void Instance::startOutgoingCall(not_null<UserData*> user) {
|
||||
}
|
||||
if (user->callsStatus() == UserData::CallsStatus::Private) {
|
||||
// Request full user once more to refresh the setting in case it was changed.
|
||||
_session->api().requestFullPeer(user);
|
||||
Ui::show(Box<InformBox>(tr::lng_call_error_not_available(tr::now, lt_user, user->name)));
|
||||
user->session().api().requestFullPeer(user);
|
||||
Ui::show(Box<InformBox>(
|
||||
tr::lng_call_error_not_available(tr::now, lt_user, user->name)));
|
||||
return;
|
||||
}
|
||||
requestMicrophonePermissionOrFail(crl::guard(this, [=] {
|
||||
@ -101,8 +108,9 @@ void Instance::playSound(Sound sound) {
|
||||
void Instance::destroyCall(not_null<Call*> call) {
|
||||
if (_currentCall.get() == call) {
|
||||
destroyCurrentPanel();
|
||||
_currentCall.reset();
|
||||
_currentCallChanged.notify(nullptr, true);
|
||||
auto taken = base::take(_currentCall);
|
||||
_currentCallChanges.fire(nullptr);
|
||||
taken.reset();
|
||||
|
||||
if (App::quitting()) {
|
||||
LOG(("Calls::Instance doesn't prevent quit any more."));
|
||||
@ -123,17 +131,24 @@ void Instance::destroyCurrentPanel() {
|
||||
}
|
||||
|
||||
void Instance::createCall(not_null<UserData*> user, Call::Type type) {
|
||||
auto call = std::make_unique<Call>(getCallDelegate(), user, type);;
|
||||
auto call = std::make_unique<Call>(getCallDelegate(), user, type);
|
||||
const auto raw = call.get();
|
||||
|
||||
user->session().account().sessionChanges(
|
||||
) | rpl::start_with_next([=] {
|
||||
destroyCall(raw);
|
||||
}, raw->lifetime());
|
||||
|
||||
if (_currentCall) {
|
||||
_currentCallPanel->replaceCall(call.get());
|
||||
_currentCallPanel->replaceCall(raw);
|
||||
std::swap(_currentCall, call);
|
||||
call->hangup();
|
||||
} else {
|
||||
_currentCallPanel = std::make_unique<Panel>(call.get());
|
||||
_currentCallPanel = std::make_unique<Panel>(raw);
|
||||
_currentCall = std::move(call);
|
||||
}
|
||||
_currentCallChanged.notify(_currentCall.get(), true);
|
||||
refreshServerConfig();
|
||||
_currentCallChanges.fire_copy(raw);
|
||||
refreshServerConfig(&user->session());
|
||||
refreshDhConfig();
|
||||
}
|
||||
|
||||
@ -141,7 +156,7 @@ void Instance::refreshDhConfig() {
|
||||
Expects(_currentCall != nullptr);
|
||||
|
||||
const auto weak = base::make_weak(_currentCall);
|
||||
_api.request(MTPmessages_GetDhConfig(
|
||||
_currentCall->user()->session().api().request(MTPmessages_GetDhConfig(
|
||||
MTP_int(_dhConfig.version),
|
||||
MTP_int(MTP::ModExpFirst::kRandomPowerSize)
|
||||
)).done([=](const MTPmessages_DhConfig &result) {
|
||||
@ -198,27 +213,32 @@ bytes::const_span Instance::updateDhConfig(
|
||||
});
|
||||
}
|
||||
|
||||
void Instance::refreshServerConfig() {
|
||||
if (_serverConfigRequestId) {
|
||||
void Instance::refreshServerConfig(not_null<Main::Session*> session) {
|
||||
if (_serverConfigRequestSession) {
|
||||
return;
|
||||
}
|
||||
if (_lastServerConfigUpdateTime && (crl::now() - _lastServerConfigUpdateTime) < kServerConfigUpdateTimeoutMs) {
|
||||
if (_lastServerConfigUpdateTime
|
||||
&& ((crl::now() - _lastServerConfigUpdateTime)
|
||||
< kServerConfigUpdateTimeoutMs)) {
|
||||
return;
|
||||
}
|
||||
_serverConfigRequestId = _api.request(MTPphone_GetCallConfig(
|
||||
_serverConfigRequestSession = session;
|
||||
session->api().request(MTPphone_GetCallConfig(
|
||||
)).done([=](const MTPDataJSON &result) {
|
||||
_serverConfigRequestId = 0;
|
||||
_serverConfigRequestSession = nullptr;
|
||||
_lastServerConfigUpdateTime = crl::now();
|
||||
|
||||
const auto &json = result.c_dataJSON().vdata().v;
|
||||
UpdateConfig(std::string(json.data(), json.size()));
|
||||
}).fail([=](const RPCError &error) {
|
||||
_serverConfigRequestId = 0;
|
||||
}).send();
|
||||
_serverConfigRequestSession = nullptr;
|
||||
}).send();
|
||||
}
|
||||
|
||||
void Instance::handleUpdate(const MTPDupdatePhoneCall& update) {
|
||||
handleCallUpdate(update.vphone_call());
|
||||
void Instance::handleUpdate(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDupdatePhoneCall& update) {
|
||||
handleCallUpdate(session, update.vphone_call());
|
||||
}
|
||||
|
||||
void Instance::showInfoPanel(not_null<Call*> call) {
|
||||
@ -239,18 +259,20 @@ bool Instance::isQuitPrevent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Instance::handleCallUpdate(const MTPPhoneCall &call) {
|
||||
void Instance::handleCallUpdate(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPPhoneCall &call) {
|
||||
if (call.type() == mtpc_phoneCallRequested) {
|
||||
auto &phoneCall = call.c_phoneCallRequested();
|
||||
auto user = _session->data().userLoaded(phoneCall.vadmin_id().v);
|
||||
auto user = session->data().userLoaded(phoneCall.vadmin_id().v);
|
||||
if (!user) {
|
||||
LOG(("API Error: User not loaded for phoneCallRequested."));
|
||||
} else if (user->isSelf()) {
|
||||
LOG(("API Error: Self found in phoneCallRequested."));
|
||||
}
|
||||
const auto &config = _session->serverConfig();
|
||||
const auto &config = session->serverConfig();
|
||||
if (alreadyInCall() || !user || user->isSelf()) {
|
||||
_api.request(MTPphone_DiscardCall(
|
||||
session->api().request(MTPphone_DiscardCall(
|
||||
MTP_flags(0),
|
||||
MTP_inputPhoneCall(phoneCall.vid(), phoneCall.vaccess_hash()),
|
||||
MTP_int(0),
|
||||
@ -273,10 +295,14 @@ bool Instance::alreadyInCall() {
|
||||
return (_currentCall && _currentCall->state() != Call::State::Busy);
|
||||
}
|
||||
|
||||
Call *Instance::currentCall() {
|
||||
Call *Instance::currentCall() const {
|
||||
return _currentCall.get();
|
||||
}
|
||||
|
||||
rpl::producer<Call*> Instance::currentCallValue() const {
|
||||
return _currentCallChanges.events_starting_with(currentCall());
|
||||
}
|
||||
|
||||
void Instance::requestMicrophonePermissionOrFail(Fn<void()> onSuccess) {
|
||||
Platform::PermissionStatus status=Platform::GetPermissionStatus(Platform::PermissionType::Microphone);
|
||||
if (status==Platform::PermissionStatus::Granted) {
|
||||
@ -302,12 +328,4 @@ void Instance::requestMicrophonePermissionOrFail(Fn<void()> onSuccess) {
|
||||
}
|
||||
}
|
||||
|
||||
Instance::~Instance() {
|
||||
for (auto panel : _pendingPanels) {
|
||||
if (panel) {
|
||||
delete panel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Calls
|
||||
|
@ -29,24 +29,18 @@ class Instance
|
||||
, private base::Subscriber
|
||||
, public base::has_weak_ptr {
|
||||
public:
|
||||
explicit Instance(not_null<Main::Session*> session);
|
||||
Instance();
|
||||
~Instance();
|
||||
|
||||
void startOutgoingCall(not_null<UserData*> user);
|
||||
void handleUpdate(const MTPDupdatePhoneCall &update);
|
||||
void handleUpdate(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPDupdatePhoneCall &update);
|
||||
void showInfoPanel(not_null<Call*> call);
|
||||
Call* currentCall();
|
||||
[[nodiscard]] Call *currentCall() const;
|
||||
[[nodiscard]] rpl::producer<Call*> currentCallValue() const;
|
||||
|
||||
base::Observable<Call*> ¤tCallChanged() {
|
||||
return _currentCallChanged;
|
||||
}
|
||||
|
||||
base::Observable<FullMsgId> &newServiceMessage() {
|
||||
return _newServiceMessage;
|
||||
}
|
||||
|
||||
bool isQuitPrevent();
|
||||
|
||||
~Instance();
|
||||
[[nodiscard]] bool isQuitPrevent();
|
||||
|
||||
private:
|
||||
not_null<Call::Delegate*> getCallDelegate() {
|
||||
@ -66,21 +60,21 @@ private:
|
||||
void requestMicrophonePermissionOrFail(Fn<void()> onSuccess) override;
|
||||
|
||||
void refreshDhConfig();
|
||||
void refreshServerConfig();
|
||||
void refreshServerConfig(not_null<Main::Session*> session);
|
||||
bytes::const_span updateDhConfig(const MTPmessages_DhConfig &data);
|
||||
|
||||
bool alreadyInCall();
|
||||
void handleCallUpdate(const MTPPhoneCall &call);
|
||||
|
||||
const not_null<Main::Session*> _session;
|
||||
MTP::Sender _api;
|
||||
void handleCallUpdate(
|
||||
not_null<Main::Session*> session,
|
||||
const MTPPhoneCall &call);
|
||||
|
||||
DhConfig _dhConfig;
|
||||
|
||||
crl::time _lastServerConfigUpdateTime = 0;
|
||||
mtpRequestId _serverConfigRequestId = 0;
|
||||
base::weak_ptr<Main::Session> _serverConfigRequestSession;
|
||||
|
||||
std::unique_ptr<Call> _currentCall;
|
||||
rpl::event_stream<Call*> _currentCallChanges;
|
||||
std::unique_ptr<Panel> _currentCallPanel;
|
||||
base::Observable<Call*> _currentCallChanged;
|
||||
base::Observable<FullMsgId> _newServiceMessage;
|
||||
|
@ -405,11 +405,11 @@ void Panel::initControls() {
|
||||
void Panel::reinitControls() {
|
||||
Expects(_call != nullptr);
|
||||
|
||||
unsubscribe(base::take(_stateChangedSubscription));
|
||||
_stateChangedSubscription = subscribe(
|
||||
_call->stateChanged(),
|
||||
[=](State state) { stateChanged(state); });
|
||||
stateChanged(_call->state());
|
||||
_stateLifetime.destroy();
|
||||
_call->stateValue(
|
||||
) | rpl::start_with_next([=](State state) {
|
||||
stateChanged(state);
|
||||
}, _stateLifetime);
|
||||
|
||||
_signalBars.create(
|
||||
this,
|
||||
|
@ -130,7 +130,7 @@ private:
|
||||
QPoint _dragStartMousePosition;
|
||||
QPoint _dragStartMyPosition;
|
||||
|
||||
int _stateChangedSubscription = 0;
|
||||
rpl::lifetime _stateLifetime;
|
||||
|
||||
class Button;
|
||||
object_ptr<Button> _answerHangupRedial;
|
||||
|
@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/wrap/padding_wrap.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "core/application.h"
|
||||
#include "calls/calls_call.h"
|
||||
#include "calls/calls_instance.h"
|
||||
#include "calls/calls_panel.h"
|
||||
@ -118,7 +119,7 @@ void TopBar::initControls() {
|
||||
&& (_info->clickModifiers() & Qt::ControlModifier)) {
|
||||
Ui::show(Box<DebugInfoBox>(_call));
|
||||
} else {
|
||||
call->user()->session().calls().showInfoPanel(call);
|
||||
Core::App().calls().showInfoPanel(call);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -101,14 +101,15 @@ Application::Application(not_null<Launcher*> launcher)
|
||||
, _databases(std::make_unique<Storage::Databases>())
|
||||
, _animationsManager(std::make_unique<Ui::Animations::Manager>())
|
||||
, _clearEmojiImageLoaderTimer([=] { clearEmojiSourceImages(); })
|
||||
, _audio(std::make_unique<Media::Audio::Instance>())
|
||||
, _fallbackProductionConfig(
|
||||
std::make_unique<MTP::Config>(MTP::Environment::Production))
|
||||
, _domain(std::make_unique<Main::Domain>(cDataFile()))
|
||||
, _exportManager(std::make_unique<Export::Manager>())
|
||||
, _calls(std::make_unique<Calls::Instance>())
|
||||
, _langpack(std::make_unique<Lang::Instance>())
|
||||
, _langCloudManager(std::make_unique<Lang::CloudManager>(langpack()))
|
||||
, _emojiKeywords(std::make_unique<ChatHelpers::EmojiKeywords>())
|
||||
, _audio(std::make_unique<Media::Audio::Instance>())
|
||||
, _logo(Window::LoadLogo())
|
||||
, _logoNoMargin(Window::LoadLogoNoMargin())
|
||||
, _autoLockTimer([=] { checkAutoLock(); }) {
|
||||
@ -943,7 +944,7 @@ void Application::QuitAttempt() {
|
||||
if (const auto session = App().maybeActiveSession()) {
|
||||
if (session->updates().isQuitPrevent()
|
||||
|| session->api().isQuitPrevent()
|
||||
|| session->calls().isQuitPrevent()) {
|
||||
|| App().calls().isQuitPrevent()) {
|
||||
App().quitDelayed();
|
||||
return;
|
||||
}
|
||||
|
@ -95,6 +95,10 @@ namespace Export {
|
||||
class Manager;
|
||||
} // namespace Export
|
||||
|
||||
namespace Calls {
|
||||
class Instance;
|
||||
} // namespace Calls
|
||||
|
||||
namespace Core {
|
||||
|
||||
class Launcher;
|
||||
@ -231,6 +235,11 @@ public:
|
||||
not_null<Media::Player::FloatDelegate*> replacement);
|
||||
[[nodiscard]] rpl::producer<FullMsgId> floatPlayerClosed() const;
|
||||
|
||||
// Calls.
|
||||
Calls::Instance &calls() const {
|
||||
return *_calls;
|
||||
}
|
||||
|
||||
void logout(Main::Account *account = nullptr);
|
||||
void forceLogOut(
|
||||
not_null<Main::Account*> account,
|
||||
@ -319,9 +328,11 @@ private:
|
||||
const std::unique_ptr<Ui::Animations::Manager> _animationsManager;
|
||||
crl::object_on_queue<Stickers::EmojiImageLoader> _emojiImageLoader;
|
||||
base::Timer _clearEmojiImageLoaderTimer;
|
||||
const std::unique_ptr<Media::Audio::Instance> _audio;
|
||||
mutable std::unique_ptr<MTP::Config> _fallbackProductionConfig;
|
||||
const std::unique_ptr<Main::Domain> _domain;
|
||||
const std::unique_ptr<Export::Manager> _exportManager;
|
||||
const std::unique_ptr<Calls::Instance> _calls;
|
||||
std::unique_ptr<Window::Controller> _window;
|
||||
std::unique_ptr<Media::View::OverlayWidget> _mediaView;
|
||||
const std::unique_ptr<Lang::Instance> _langpack;
|
||||
@ -331,8 +342,6 @@ private:
|
||||
base::Observable<void> _passcodedChanged;
|
||||
QPointer<Ui::BoxContent> _badProxyDisableBox;
|
||||
|
||||
const std::unique_ptr<Media::Audio::Instance> _audio;
|
||||
|
||||
std::unique_ptr<Media::Player::FloatController> _floatPlayers;
|
||||
Media::Player::FloatDelegate *_defaultFloatPlayerDelegate = nullptr;
|
||||
Media::Player::FloatDelegate *_replacementFloatPlayerDelegate = nullptr;
|
||||
|
@ -132,8 +132,9 @@ struct MessageUpdate {
|
||||
Destroyed = (1 << 1),
|
||||
DialogRowRepaint = (1 << 2),
|
||||
DialogRowRefresh = (1 << 3),
|
||||
CallAdded = (1 << 4),
|
||||
|
||||
LastUsedBit = (1 << 3),
|
||||
LastUsedBit = (1 << 4),
|
||||
};
|
||||
using Flags = base::flags<Flag>;
|
||||
friend inline constexpr auto is_flag_type(Flag) { return true; }
|
||||
|
@ -1238,8 +1238,9 @@ void History::applyServiceChanges(
|
||||
} break;
|
||||
|
||||
case mtpc_messageActionPhoneCall: {
|
||||
item->history()->session().calls().newServiceMessage().notify(
|
||||
item->fullId());
|
||||
item->history()->session().changes().messageUpdated(
|
||||
item,
|
||||
Data::MessageUpdate::Flag::CallAdded);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ void TopBarWidget::onSearch() {
|
||||
void TopBarWidget::onCall() {
|
||||
if (const auto peer = _activeChat.peer()) {
|
||||
if (const auto user = peer->asUser()) {
|
||||
user->session().calls().startOutgoingCall(user);
|
||||
Core::App().calls().startOutgoingCall(user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "history/history_item.h"
|
||||
#include "history/view/history_view_element.h"
|
||||
#include "history/view/history_view_cursor_state.h"
|
||||
#include "core/application.h"
|
||||
#include "calls/calls_instance.h"
|
||||
#include "data/data_media_types.h"
|
||||
#include "data/data_user.h"
|
||||
@ -50,7 +51,7 @@ QSize Call::countOptimalSize() {
|
||||
const auto user = _parent->data()->history()->peer->asUser();
|
||||
_link = std::make_shared<LambdaClickHandler>([=] {
|
||||
if (user) {
|
||||
user->session().calls().startOutgoingCall(user);
|
||||
Core::App().calls().startOutgoingCall(user);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -20,6 +20,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
#include "ui/widgets/dropdown_menu.h"
|
||||
#include "ui/wrap/fade_wrap.h"
|
||||
#include "ui/search_field_controller.h"
|
||||
#include "core/application.h"
|
||||
#include "calls/calls_instance.h"
|
||||
#include "core/shortcuts.h"
|
||||
#include "window/window_session_controller.h"
|
||||
@ -500,7 +501,7 @@ void WrapWidget::addProfileCallsButton() {
|
||||
? st::infoLayerTopBarCall
|
||||
: st::infoTopBarCall))
|
||||
)->addClickHandler([=] {
|
||||
user->session().calls().startOutgoingCall(user);
|
||||
Core::App().calls().startOutgoingCall(user);
|
||||
});
|
||||
}, _topBar->lifetime());
|
||||
|
||||
|
@ -72,7 +72,6 @@ Session::Session(
|
||||
, _settings(std::move(settings))
|
||||
, _api(std::make_unique<ApiWrap>(this))
|
||||
, _updates(std::make_unique<Api::Updates>(this))
|
||||
, _calls(std::make_unique<Calls::Instance>(this))
|
||||
, _downloader(std::make_unique<Storage::DownloadManagerMtproto>(_api.get()))
|
||||
, _uploader(std::make_unique<Storage::Uploader>(_api.get()))
|
||||
, _storage(std::make_unique<Storage::Facade>())
|
||||
|
@ -47,10 +47,6 @@ class SessionController;
|
||||
struct TermsLock;
|
||||
} // namespace Window
|
||||
|
||||
namespace Calls {
|
||||
class Instance;
|
||||
} // namespace Calls
|
||||
|
||||
namespace Stickers {
|
||||
class EmojiPack;
|
||||
class DicePacks;
|
||||
@ -133,10 +129,6 @@ public:
|
||||
return *_api;
|
||||
}
|
||||
|
||||
[[nodiscard]] Calls::Instance &calls() {
|
||||
return *_calls;
|
||||
}
|
||||
|
||||
// Terms lock.
|
||||
void lockByTerms(const Window::TermsLock &data);
|
||||
void unlockTerms();
|
||||
@ -166,7 +158,6 @@ private:
|
||||
const std::unique_ptr<SessionSettings> _settings;
|
||||
const std::unique_ptr<ApiWrap> _api;
|
||||
const std::unique_ptr<Api::Updates> _updates;
|
||||
const std::unique_ptr<Calls::Instance> _calls;
|
||||
const std::unique_ptr<Storage::DownloadManagerMtproto> _downloader;
|
||||
const std::unique_ptr<Storage::Uploader> _uploader;
|
||||
const std::unique_ptr<Storage::Facade> _storage;
|
||||
|
@ -245,9 +245,13 @@ MainWidget::MainWidget(
|
||||
connect(_dialogs, SIGNAL(cancelled()), this, SLOT(dialogsCancelled()));
|
||||
connect(_history, &HistoryWidget::cancelled, [=] { handleHistoryBack(); });
|
||||
|
||||
subscribe(session().calls().currentCallChanged(), [=](Calls::Call *call) {
|
||||
Core::App().calls().currentCallValue(
|
||||
) | rpl::start_with_next([=](Calls::Call *call) {
|
||||
setCurrentCall(call);
|
||||
});
|
||||
}, lifetime());
|
||||
if (_callTopBar) {
|
||||
_callTopBar->finishAnimating();
|
||||
}
|
||||
|
||||
Core::App().setDefaultFloatPlayerDelegate(floatPlayerDelegate());
|
||||
Core::App().floatPlayerClosed(
|
||||
@ -943,16 +947,18 @@ void MainWidget::playerHeightUpdated() {
|
||||
}
|
||||
|
||||
void MainWidget::setCurrentCall(Calls::Call *call) {
|
||||
_currentCallLifetime.destroy();
|
||||
_currentCall = call;
|
||||
if (_currentCall) {
|
||||
subscribe(_currentCall->stateChanged(), [this](Calls::Call::State state) {
|
||||
_currentCall->stateValue(
|
||||
) | rpl::start_with_next([=](Calls::Call::State state) {
|
||||
using State = Calls::Call::State;
|
||||
if (state == State::Established) {
|
||||
createCallTopBar();
|
||||
} else {
|
||||
destroyCallTopBar();
|
||||
}
|
||||
});
|
||||
}, _currentCallLifetime);
|
||||
} else {
|
||||
destroyCallTopBar();
|
||||
}
|
||||
@ -2036,6 +2042,10 @@ void MainWidget::hideAll() {
|
||||
_player->setVisible(false);
|
||||
_playerHeight = 0;
|
||||
}
|
||||
if (_callTopBar) {
|
||||
_callTopBar->setVisible(false);
|
||||
_callTopBarHeight = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void MainWidget::showAll() {
|
||||
@ -2091,6 +2101,10 @@ void MainWidget::showAll() {
|
||||
_player->setVisible(true);
|
||||
_playerHeight = _player->contentHeight();
|
||||
}
|
||||
if (_callTopBar) {
|
||||
_callTopBar->setVisible(true);
|
||||
_callTopBarHeight = _callTopBar->height();
|
||||
}
|
||||
updateControlsGeometry();
|
||||
floatPlayerCheckVisibility();
|
||||
|
||||
|
@ -373,6 +373,7 @@ private:
|
||||
std::unique_ptr<Window::ConnectionState> _connecting;
|
||||
|
||||
base::weak_ptr<Calls::Call> _currentCall;
|
||||
rpl::lifetime _currentCallLifetime;
|
||||
object_ptr<Ui::SlideWrap<Calls::TopBar>> _callTopBar = { nullptr };
|
||||
|
||||
Export::View::PanelController *_currentExportView = nullptr;
|
||||
|
@ -114,19 +114,14 @@ Instance::Instance()
|
||||
handleSongUpdate(audioId);
|
||||
});
|
||||
|
||||
// While we have one Media::Player::Instance for all sessions we have to do this.
|
||||
Core::App().domain().activeSessionValue(
|
||||
) | rpl::start_with_next([=](Main::Session *session) {
|
||||
if (session) {
|
||||
subscribe(session->calls().currentCallChanged(), [=](Calls::Call *call) {
|
||||
if (call) {
|
||||
pauseOnCall(AudioMsgId::Type::Voice);
|
||||
pauseOnCall(AudioMsgId::Type::Song);
|
||||
} else {
|
||||
resumeOnCall(AudioMsgId::Type::Voice);
|
||||
resumeOnCall(AudioMsgId::Type::Song);
|
||||
}
|
||||
});
|
||||
Core::App().calls().currentCallValue(
|
||||
) | rpl::start_with_next([=](Calls::Call *call) {
|
||||
if (call) {
|
||||
pauseOnCall(AudioMsgId::Type::Voice);
|
||||
pauseOnCall(AudioMsgId::Type::Song);
|
||||
} else {
|
||||
resumeOnCall(AudioMsgId::Type::Voice);
|
||||
resumeOnCall(AudioMsgId::Type::Song);
|
||||
}
|
||||
}, _lifetime);
|
||||
|
||||
|
@ -341,6 +341,17 @@ OverlayWidget::OverlayWidget()
|
||||
setWindowState(Qt::WindowFullScreen);
|
||||
}
|
||||
|
||||
Core::App().calls().currentCallValue(
|
||||
) | rpl::start_with_next([=](Calls::Call *call) {
|
||||
if (!_streamed) {
|
||||
return;
|
||||
} else if (call) {
|
||||
playbackPauseOnCall();
|
||||
} else {
|
||||
playbackResumeOnCall();
|
||||
}
|
||||
}, lifetime());
|
||||
|
||||
_saveMsgUpdater.setSingleShot(true);
|
||||
connect(&_saveMsgUpdater, SIGNAL(timeout()), this, SLOT(updateImage()));
|
||||
|
||||
@ -3530,19 +3541,6 @@ void OverlayWidget::setSession(not_null<Main::Session*> session) {
|
||||
}
|
||||
}, _sessionLifetime);
|
||||
|
||||
base::ObservableViewer(
|
||||
session->calls().currentCallChanged()
|
||||
) | rpl::start_with_next([=](Calls::Call *call) {
|
||||
if (!_streamed) {
|
||||
return;
|
||||
}
|
||||
if (call) {
|
||||
playbackPauseOnCall();
|
||||
} else {
|
||||
playbackResumeOnCall();
|
||||
}
|
||||
}, _sessionLifetime);
|
||||
|
||||
base::ObservableViewer(
|
||||
session->documentUpdated
|
||||
) | rpl::start_with_next([=](DocumentData *document) {
|
||||
|
@ -135,7 +135,7 @@ void Calls::setupContent() {
|
||||
Core::App().settings().setCallOutputDeviceID(
|
||||
QString::fromStdString(deviceId));
|
||||
_controller->session().saveSettingsDelayed();
|
||||
if (const auto call = _controller->session().calls().currentCall()) {
|
||||
if (const auto call = Core::App().calls().currentCall()) {
|
||||
call->setCurrentAudioDevice(false, deviceId);
|
||||
}
|
||||
});
|
||||
@ -165,7 +165,7 @@ void Calls::setupContent() {
|
||||
_needWriteSettings = true;
|
||||
updateOutputLabel(value);
|
||||
Core::App().settings().setCallOutputVolume(value);
|
||||
if (const auto call = _controller->session().calls().currentCall()) {
|
||||
if (const auto call = Core::App().calls().currentCall()) {
|
||||
call->setAudioVolume(false, value / 100.0f);
|
||||
}
|
||||
};
|
||||
@ -214,7 +214,7 @@ void Calls::setupContent() {
|
||||
if (_micTester) {
|
||||
stopTestingMicrophone();
|
||||
}
|
||||
if (const auto call = _controller->session().calls().currentCall()) {
|
||||
if (const auto call = Core::App().calls().currentCall()) {
|
||||
call->setCurrentAudioDevice(true, deviceId);
|
||||
}
|
||||
});
|
||||
@ -244,7 +244,7 @@ void Calls::setupContent() {
|
||||
_needWriteSettings = true;
|
||||
updateInputLabel(value);
|
||||
Core::App().settings().setCallInputVolume(value);
|
||||
if (const auto call = _controller->session().calls().currentCall()) {
|
||||
if (const auto call = Core::App().calls().currentCall()) {
|
||||
call->setAudioVolume(true, value / 100.0f);
|
||||
}
|
||||
};
|
||||
@ -299,7 +299,7 @@ void Calls::setupContent() {
|
||||
}) | rpl::start_with_next([=](bool enabled) {
|
||||
Core::App().settings().setCallAudioDuckingEnabled(enabled);
|
||||
Core::App().saveSettingsDelayed();
|
||||
if (const auto call = _controller->session().calls().currentCall()) {
|
||||
if (const auto call = Core::App().calls().currentCall()) {
|
||||
call->setAudioDuckingEnabled(enabled);
|
||||
}
|
||||
}, content->lifetime());
|
||||
|
Loading…
Reference in New Issue
Block a user