Move call management to Core::App.

This commit is contained in:
John Preston 2020-06-25 21:57:36 +04:00
parent 8c4d3a86e7
commit 79a361ba43
23 changed files with 204 additions and 167 deletions

View File

@ -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: {

View File

@ -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) {

View File

@ -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) {

View File

@ -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);

View File

@ -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

View File

@ -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*> &currentCallChanged() {
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;

View File

@ -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,

View File

@ -130,7 +130,7 @@ private:
QPoint _dragStartMousePosition;
QPoint _dragStartMyPosition;
int _stateChangedSubscription = 0;
rpl::lifetime _stateLifetime;
class Button;
object_ptr<Button> _answerHangupRedial;

View File

@ -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);
}
}
});

View File

@ -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;
}

View File

@ -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;

View File

@ -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; }

View File

@ -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;
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
});

View File

@ -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());

View File

@ -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>())

View File

@ -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;

View File

@ -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();

View File

@ -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;

View File

@ -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);

View File

@ -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) {

View File

@ -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());