mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-03 21:54:05 +02:00
Implement incoming confcall window.
This commit is contained in:
parent
7c709fddba
commit
a3ba99c682
11 changed files with 327 additions and 25 deletions
|
@ -247,7 +247,49 @@ Call::Call(
|
|||
setupOutgoingVideo();
|
||||
}
|
||||
|
||||
Call::Call(
|
||||
not_null<Delegate*> delegate,
|
||||
not_null<UserData*> user,
|
||||
CallId conferenceId,
|
||||
MsgId conferenceInviteMsgId)
|
||||
: _delegate(delegate)
|
||||
, _user(user)
|
||||
, _api(&_user->session().mtp())
|
||||
, _type(Type::Incoming)
|
||||
, _state(State::WaitingIncoming)
|
||||
, _discardByTimeoutTimer([=] { hangup(); })
|
||||
, _playbackDeviceId(
|
||||
&Core::App().mediaDevices(),
|
||||
Webrtc::DeviceType::Playback,
|
||||
Webrtc::DeviceIdValueWithFallback(
|
||||
Core::App().settings().callPlaybackDeviceIdValue(),
|
||||
Core::App().settings().playbackDeviceIdValue()))
|
||||
, _captureDeviceId(
|
||||
&Core::App().mediaDevices(),
|
||||
Webrtc::DeviceType::Capture,
|
||||
Webrtc::DeviceIdValueWithFallback(
|
||||
Core::App().settings().callCaptureDeviceIdValue(),
|
||||
Core::App().settings().captureDeviceIdValue()))
|
||||
, _cameraDeviceId(
|
||||
&Core::App().mediaDevices(),
|
||||
Webrtc::DeviceType::Camera,
|
||||
Core::App().settings().cameraDeviceIdValue())
|
||||
, _id(base::RandomValue<CallId>())
|
||||
, _conferenceId(conferenceId)
|
||||
, _conferenceInviteMsgId(conferenceInviteMsgId)
|
||||
, _videoIncoming(
|
||||
std::make_unique<Webrtc::VideoTrack>(
|
||||
StartVideoState(false)))
|
||||
, _videoOutgoing(
|
||||
std::make_unique<Webrtc::VideoTrack>(
|
||||
StartVideoState(false))) {
|
||||
startWaitingTrack();
|
||||
setupOutgoingVideo();
|
||||
}
|
||||
|
||||
void Call::generateModExpFirst(bytes::const_span randomSeed) {
|
||||
Expects(!conferenceInvite());
|
||||
|
||||
auto first = MTP::CreateModExp(_dhConfig.g, _dhConfig.p, randomSeed);
|
||||
if (first.modexp.empty()) {
|
||||
LOG(("Call Error: Could not compute mod-exp first."));
|
||||
|
@ -273,6 +315,8 @@ bool Call::isIncomingWaiting() const {
|
|||
}
|
||||
|
||||
void Call::start(bytes::const_span random) {
|
||||
Expects(!conferenceInvite());
|
||||
|
||||
// Save config here, because it is possible that it changes between
|
||||
// different usages inside the same call.
|
||||
_dhConfig = _delegate->getDhConfig();
|
||||
|
@ -297,6 +341,7 @@ void Call::startOutgoing() {
|
|||
Expects(_type == Type::Outgoing);
|
||||
Expects(_state.current() == State::Requesting);
|
||||
Expects(_gaHash.size() == kSha256Size);
|
||||
Expects(!conferenceInvite());
|
||||
|
||||
const auto flags = _videoCapture
|
||||
? MTPphone_RequestCall::Flag::f_video
|
||||
|
@ -350,6 +395,7 @@ void Call::startOutgoing() {
|
|||
void Call::startIncoming() {
|
||||
Expects(_type == Type::Incoming);
|
||||
Expects(_state.current() == State::Starting);
|
||||
Expects(!conferenceInvite());
|
||||
|
||||
_api.request(MTPphone_ReceivedCall(
|
||||
MTP_inputPhoneCall(MTP_long(_id), MTP_long(_accessHash))
|
||||
|
@ -363,6 +409,8 @@ void Call::startIncoming() {
|
|||
}
|
||||
|
||||
void Call::applyUserConfirmation() {
|
||||
Expects(!conferenceInvite());
|
||||
|
||||
if (_state.current() == State::WaitingUserConfirmation) {
|
||||
setState(State::Requesting);
|
||||
}
|
||||
|
@ -375,9 +423,44 @@ void Call::answer() {
|
|||
}), video);
|
||||
}
|
||||
|
||||
void Call::acceptConferenceInvite() {
|
||||
Expects(conferenceInvite());
|
||||
|
||||
if (_state.current() != State::WaitingIncoming) {
|
||||
return;
|
||||
}
|
||||
setState(State::ExchangingKeys);
|
||||
const auto limit = 5;
|
||||
const auto messageId = _conferenceInviteMsgId;
|
||||
const auto session = &_user->session();
|
||||
session->api().request(MTPphone_GetGroupCall(
|
||||
MTP_inputGroupCallInviteMessage(MTP_int(messageId.bare)),
|
||||
MTP_int(limit)
|
||||
)).done([session, messageId](const MTPphone_GroupCall &result) {
|
||||
result.data().vcall().match([&](const auto &data) {
|
||||
const auto call = session->data().sharedConferenceCall(
|
||||
data.vid().v,
|
||||
data.vaccess_hash().v);
|
||||
call->processFullCall(result);
|
||||
Core::App().calls().startOrJoinConferenceCall({
|
||||
.call = call,
|
||||
.joinMessageId = messageId,
|
||||
.migrating = true,
|
||||
});
|
||||
});
|
||||
}).fail(crl::guard(this, [=](const MTP::Error &error) {
|
||||
handleRequestError(error.type());
|
||||
})).send();
|
||||
}
|
||||
|
||||
void Call::actuallyAnswer() {
|
||||
Expects(_type == Type::Incoming);
|
||||
|
||||
if (conferenceInvite()) {
|
||||
acceptConferenceInvite();
|
||||
return;
|
||||
}
|
||||
|
||||
const auto state = _state.current();
|
||||
if (state != State::Starting && state != State::WaitingIncoming) {
|
||||
if (state != State::ExchangingKeys
|
||||
|
@ -435,6 +518,8 @@ void Call::setMuted(bool mute) {
|
|||
}
|
||||
|
||||
void Call::setupMediaDevices() {
|
||||
Expects(!conferenceInvite());
|
||||
|
||||
_playbackDeviceId.changes() | rpl::filter([=] {
|
||||
return _instance && _setDeviceIdCallback;
|
||||
}) | rpl::start_with_next([=](const Webrtc::DeviceResolvedId &deviceId) {
|
||||
|
@ -530,7 +615,8 @@ crl::time Call::getDurationMs() const {
|
|||
|
||||
void Call::hangup(Data::GroupCall *migrateCall, const QString &migrateSlug) {
|
||||
const auto state = _state.current();
|
||||
if (state == State::Busy || state == State::MigrationHangingUp) {
|
||||
if (state == State::Busy
|
||||
|| state == State::MigrationHangingUp) {
|
||||
_delegate->callFinished(this);
|
||||
} else {
|
||||
const auto missed = (state == State::Ringing
|
||||
|
@ -549,6 +635,8 @@ void Call::hangup(Data::GroupCall *migrateCall, const QString &migrateSlug) {
|
|||
}
|
||||
|
||||
void Call::redial() {
|
||||
Expects(!conferenceInvite());
|
||||
|
||||
if (_state.current() != State::Busy) {
|
||||
return;
|
||||
}
|
||||
|
@ -578,6 +666,8 @@ void Call::startWaitingTrack() {
|
|||
}
|
||||
|
||||
void Call::sendSignalingData(const QByteArray &data) {
|
||||
Expects(!conferenceInvite());
|
||||
|
||||
_api.request(MTPphone_SendSignalingData(
|
||||
MTP_inputPhoneCall(
|
||||
MTP_long(_id),
|
||||
|
@ -776,6 +866,8 @@ bool Call::handleUpdate(const MTPPhoneCall &call) {
|
|||
}
|
||||
|
||||
void Call::finishByMigration(const QString &slug) {
|
||||
Expects(!conferenceInvite());
|
||||
|
||||
if (_state.current() == State::MigrationHangingUp) {
|
||||
return;
|
||||
}
|
||||
|
@ -841,6 +933,7 @@ bool Call::handleSignalingData(
|
|||
|
||||
void Call::confirmAcceptedCall(const MTPDphoneCallAccepted &call) {
|
||||
Expects(_type == Type::Outgoing);
|
||||
Expects(!conferenceInvite());
|
||||
|
||||
if (_state.current() == State::ExchangingKeys
|
||||
|| _instance) {
|
||||
|
@ -893,6 +986,7 @@ void Call::confirmAcceptedCall(const MTPDphoneCallAccepted &call) {
|
|||
|
||||
void Call::startConfirmedCall(const MTPDphoneCall &call) {
|
||||
Expects(_type == Type::Incoming);
|
||||
Expects(!conferenceInvite());
|
||||
|
||||
const auto firstBytes = bytes::make_span(call.vg_a_or_b().v);
|
||||
if (_gaHash != openssl::Sha256(firstBytes)) {
|
||||
|
@ -919,6 +1013,8 @@ void Call::startConfirmedCall(const MTPDphoneCall &call) {
|
|||
}
|
||||
|
||||
void Call::createAndStartController(const MTPDphoneCall &call) {
|
||||
Expects(!conferenceInvite());
|
||||
|
||||
_discardByTimeoutTimer.cancel();
|
||||
if (!checkCallFields(call) || _authKey.size() != kAuthKeySize) {
|
||||
return;
|
||||
|
@ -1116,6 +1212,8 @@ void Call::createAndStartController(const MTPDphoneCall &call) {
|
|||
}
|
||||
|
||||
void Call::handleControllerStateChange(tgcalls::State state) {
|
||||
Expects(!conferenceInvite());
|
||||
|
||||
switch (state) {
|
||||
case tgcalls::State::WaitInit: {
|
||||
DEBUG_LOG(("Call Info: State changed to WaitingInit."));
|
||||
|
@ -1390,8 +1488,11 @@ void Call::finish(
|
|||
|| state == State::Ended
|
||||
|| state == State::Failed) {
|
||||
return;
|
||||
}
|
||||
if (!_id) {
|
||||
} else if (conferenceInvite()) {
|
||||
Core::App().calls().declineIncomingConferenceInvites(_conferenceId);
|
||||
setState(finalState);
|
||||
return;
|
||||
} else if (!_id) {
|
||||
setState(finalState);
|
||||
return;
|
||||
}
|
||||
|
@ -1460,7 +1561,7 @@ void Call::handleRequestError(const QString &error) {
|
|||
? Lang::Hard::CallErrorIncompatible().replace(
|
||||
"{user}",
|
||||
_user->name())
|
||||
: QString();
|
||||
: error;
|
||||
if (!inform.isEmpty()) {
|
||||
if (const auto window = Core::App().windowFor(
|
||||
Window::SeparateId(_user))) {
|
||||
|
|
|
@ -102,6 +102,11 @@ public:
|
|||
not_null<UserData*> user,
|
||||
Type type,
|
||||
bool video);
|
||||
Call(
|
||||
not_null<Delegate*> delegate,
|
||||
not_null<UserData*> user,
|
||||
CallId conferenceId,
|
||||
MsgId conferenceInviteMsgId);
|
||||
|
||||
[[nodiscard]] Type type() const {
|
||||
return _type;
|
||||
|
@ -112,6 +117,15 @@ public:
|
|||
[[nodiscard]] CallId id() const {
|
||||
return _id;
|
||||
}
|
||||
[[nodiscard]] bool conferenceInvite() const {
|
||||
return _conferenceId != 0;
|
||||
}
|
||||
[[nodiscard]] CallId conferenceId() const {
|
||||
return _conferenceId;
|
||||
}
|
||||
[[nodiscard]] MsgId conferenceInviteMsgId() const {
|
||||
return _conferenceInviteMsgId;
|
||||
}
|
||||
[[nodiscard]] bool isIncomingWaiting() const;
|
||||
|
||||
void start(bytes::const_span random);
|
||||
|
@ -272,6 +286,7 @@ private:
|
|||
bool checkCallFields(const MTPDphoneCallAccepted &call);
|
||||
|
||||
void actuallyAnswer();
|
||||
void acceptConferenceInvite();
|
||||
void confirmAcceptedCall(const MTPDphoneCallAccepted &call);
|
||||
void startConfirmedCall(const MTPDphoneCall &call);
|
||||
void setState(State state);
|
||||
|
@ -325,6 +340,9 @@ private:
|
|||
uint64 _accessHash = 0;
|
||||
uint64 _keyFingerprint = 0;
|
||||
|
||||
CallId _conferenceId = 0;
|
||||
MsgId _conferenceInviteMsgId = 0;
|
||||
|
||||
std::unique_ptr<tgcalls::Instance> _instance;
|
||||
std::shared_ptr<tgcalls::VideoCaptureInterface> _videoCapture;
|
||||
QString _videoCaptureDeviceId;
|
||||
|
|
|
@ -12,6 +12,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "calls/group/calls_choose_join_as.h"
|
||||
#include "calls/group/calls_group_call.h"
|
||||
#include "calls/group/calls_group_rtmp.h"
|
||||
#include "history/history.h"
|
||||
#include "history/history_item.h"
|
||||
#include "mtproto/mtproto_dh_utils.h"
|
||||
#include "core/application.h"
|
||||
#include "core/core_settings.h"
|
||||
|
@ -26,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "calls/calls_panel.h"
|
||||
#include "data/data_user.h"
|
||||
#include "data/data_group_call.h"
|
||||
#include "data/data_changes.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_chat.h"
|
||||
#include "data/data_session.h"
|
||||
|
@ -103,6 +106,8 @@ void Instance::Delegate::callFailed(not_null<Call*> call) {
|
|||
}
|
||||
|
||||
void Instance::Delegate::callRedial(not_null<Call*> call) {
|
||||
Expects(!call->conferenceInvite());
|
||||
|
||||
if (_instance->_currentCall.get() == call) {
|
||||
_instance->refreshDhConfig();
|
||||
}
|
||||
|
@ -256,7 +261,7 @@ void Instance::startOrJoinConferenceCall(StartConferenceCallArgs args) {
|
|||
_currentGroupCallChanges.fire_copy(raw);
|
||||
if (!args.invite.empty()) {
|
||||
_currentGroupCallPanel->migrationInviteUsers(std::move(args.invite));
|
||||
} else if (args.migrating) {
|
||||
} else if (args.migrating && !args.linkSlug.isEmpty()) {
|
||||
_currentGroupCallPanel->migrationShowShareLink();
|
||||
}
|
||||
}
|
||||
|
@ -442,6 +447,7 @@ void Instance::createGroupCall(
|
|||
|
||||
void Instance::refreshDhConfig() {
|
||||
Expects(_currentCall != nullptr);
|
||||
Expects(!_currentCall->conferenceInvite());
|
||||
|
||||
const auto weak = base::make_weak(_currentCall);
|
||||
_currentCall->user()->session().api().request(MTPmessages_GetDhConfig(
|
||||
|
@ -899,4 +905,129 @@ std::shared_ptr<tgcalls::VideoCaptureInterface> Instance::getVideoCapture(
|
|||
return result;
|
||||
}
|
||||
|
||||
const ConferenceInvites &Instance::conferenceInvites(
|
||||
CallId conferenceId) const {
|
||||
static const auto kEmpty = ConferenceInvites();
|
||||
const auto i = _conferenceInvites.find(conferenceId);
|
||||
return (i != end(_conferenceInvites)) ? i->second : kEmpty;
|
||||
}
|
||||
|
||||
void Instance::registerConferenceInvite(
|
||||
CallId conferenceId,
|
||||
not_null<UserData*> user,
|
||||
MsgId messageId,
|
||||
bool incoming) {
|
||||
auto &info = _conferenceInvites[conferenceId].users[user];
|
||||
(incoming ? info.incoming : info.outgoing).emplace(messageId);
|
||||
}
|
||||
|
||||
void Instance::unregisterConferenceInvite(
|
||||
CallId conferenceId,
|
||||
not_null<UserData*> user,
|
||||
MsgId messageId,
|
||||
bool incoming) {
|
||||
const auto i = _conferenceInvites.find(conferenceId);
|
||||
if (i == end(_conferenceInvites)) {
|
||||
return;
|
||||
}
|
||||
const auto j = i->second.users.find(user);
|
||||
if (j == end(i->second.users)) {
|
||||
return;
|
||||
}
|
||||
auto &info = j->second;
|
||||
(incoming ? info.incoming : info.outgoing).remove(messageId);
|
||||
if (!incoming) {
|
||||
user->owner().unregisterInvitedToCallUser(conferenceId, user);
|
||||
}
|
||||
if (info.incoming.empty() && info.outgoing.empty()) {
|
||||
i->second.users.erase(j);
|
||||
if (i->second.users.empty()) {
|
||||
_conferenceInvites.erase(i);
|
||||
}
|
||||
}
|
||||
if (_currentCall
|
||||
&& _currentCall->user() == user
|
||||
&& _currentCall->conferenceInviteMsgId() == messageId
|
||||
&& _currentCall->state() == Call::State::WaitingIncoming) {
|
||||
destroyCurrentCall();
|
||||
}
|
||||
}
|
||||
|
||||
void Instance::declineIncomingConferenceInvites(CallId conferenceId) {
|
||||
const auto i = _conferenceInvites.find(conferenceId);
|
||||
if (i == end(_conferenceInvites)) {
|
||||
return;
|
||||
}
|
||||
for (auto j = begin(i->second.users); j != end(i->second.users);) {
|
||||
const auto api = &j->first->session().api();
|
||||
for (const auto &messageId : base::take(j->second.incoming)) {
|
||||
api->request(MTPphone_DeclineConferenceCallInvite(
|
||||
MTP_int(messageId.bare)
|
||||
)).send();
|
||||
}
|
||||
if (j->second.outgoing.empty()) {
|
||||
j = i->second.users.erase(j);
|
||||
} else {
|
||||
++j;
|
||||
}
|
||||
}
|
||||
if (i->second.users.empty()) {
|
||||
_conferenceInvites.erase(i);
|
||||
}
|
||||
}
|
||||
|
||||
void Instance::showConferenceInvite(
|
||||
not_null<UserData*> user,
|
||||
MsgId conferenceInviteMsgId) {
|
||||
const auto item = user->owner().message(user, conferenceInviteMsgId);
|
||||
const auto media = item ? item->media() : nullptr;
|
||||
const auto call = media ? media->call() : nullptr;
|
||||
const auto conferenceId = call ? call->conferenceId : 0;
|
||||
if (!conferenceId
|
||||
|| call->state != Data::CallState::Invitation
|
||||
|| user->isSelf()) {
|
||||
return;
|
||||
} else if (_currentCall
|
||||
&& _currentCall->conferenceId() == conferenceId) {
|
||||
return;
|
||||
} else if (inGroupCall()
|
||||
&& _currentGroupCall->conference()
|
||||
&& _currentGroupCall->conferenceCall()->id() == conferenceId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto &config = user->session().serverConfig();
|
||||
if (inCall() || inGroupCall()) {
|
||||
declineIncomingConferenceInvites(conferenceId);
|
||||
} else if (item->date() + (config.callRingTimeoutMs / 1000)
|
||||
< base::unixtime::now()) {
|
||||
declineIncomingConferenceInvites(conferenceId);
|
||||
LOG(("Ignoring too old conference call invitation."));
|
||||
} else {
|
||||
const auto delegate = _delegate.get();
|
||||
auto call = std::make_unique<Call>(
|
||||
delegate,
|
||||
user,
|
||||
conferenceId,
|
||||
conferenceInviteMsgId);
|
||||
const auto raw = call.get();
|
||||
|
||||
user->session().account().sessionChanges(
|
||||
) | rpl::start_with_next([=] {
|
||||
destroyCall(raw);
|
||||
}, raw->lifetime());
|
||||
|
||||
if (_currentCall) {
|
||||
_currentCallPanel->replaceCall(raw);
|
||||
std::swap(_currentCall, call);
|
||||
call->hangup();
|
||||
} else {
|
||||
_currentCallPanel = std::make_unique<Panel>(raw);
|
||||
_currentCall = std::move(call);
|
||||
}
|
||||
_currentCallChanges.fire_copy(raw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace Calls
|
||||
|
|
|
@ -77,6 +77,15 @@ struct StartConferenceCallArgs {
|
|||
bool migrating = false;
|
||||
};
|
||||
|
||||
struct ConferenceInviteMessages {
|
||||
base::flat_set<MsgId> incoming;
|
||||
base::flat_set<MsgId> outgoing;
|
||||
};
|
||||
|
||||
struct ConferenceInvites {
|
||||
base::flat_map<not_null<UserData*>, ConferenceInviteMessages> users;
|
||||
};
|
||||
|
||||
class Instance final : public base::has_weak_ptr {
|
||||
public:
|
||||
Instance();
|
||||
|
@ -122,6 +131,23 @@ public:
|
|||
-> std::shared_ptr<tgcalls::VideoCaptureInterface>;
|
||||
void requestPermissionsOrFail(Fn<void()> onSuccess, bool video = true);
|
||||
|
||||
[[nodiscard]] const ConferenceInvites &conferenceInvites(
|
||||
CallId conferenceId) const;
|
||||
void registerConferenceInvite(
|
||||
CallId conferenceId,
|
||||
not_null<UserData*> user,
|
||||
MsgId messageId,
|
||||
bool incoming);
|
||||
void unregisterConferenceInvite(
|
||||
CallId conferenceId,
|
||||
not_null<UserData*> user,
|
||||
MsgId messageId,
|
||||
bool incoming);
|
||||
void showConferenceInvite(
|
||||
not_null<UserData*> user,
|
||||
MsgId conferenceInviteMsgId);
|
||||
void declineIncomingConferenceInvites(CallId conferenceId);
|
||||
|
||||
[[nodiscard]] FnMut<void()> addAsyncWaiter();
|
||||
|
||||
[[nodiscard]] bool isSharingScreen() const;
|
||||
|
@ -188,6 +214,8 @@ private:
|
|||
const std::unique_ptr<Group::ChooseJoinAsProcess> _chooseJoinAs;
|
||||
const std::unique_ptr<Group::StartRtmpProcess> _startWithRtmp;
|
||||
|
||||
base::flat_map<CallId, ConferenceInvites> _conferenceInvites;
|
||||
|
||||
base::flat_set<std::unique_ptr<crl::semaphore>> _asyncWaiters;
|
||||
|
||||
};
|
||||
|
|
|
@ -513,7 +513,14 @@ void Members::Controller::setupInvitedUsers() {
|
|||
) | rpl::filter([=](const Invite &invite) {
|
||||
return (invite.id == _call->id());
|
||||
}) | rpl::start_with_next([=](const Invite &invite) {
|
||||
if (auto row = createInvitedRow(invite.user)) {
|
||||
if (invite.removed) {
|
||||
if (const auto row = findRow(invite.user)) {
|
||||
if (row->state() == Row::State::Invited) {
|
||||
delegate()->peerListRemoveRow(row);
|
||||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
}
|
||||
} else if (auto row = createInvitedRow(invite.user)) {
|
||||
delegate()->peerListAppendRow(std::move(row));
|
||||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
|
|
|
@ -789,7 +789,8 @@ void GroupCall::applyParticipantsSlice(
|
|||
.videoJoined = videoJoined,
|
||||
.applyVolumeFromMin = applyVolumeFromMin,
|
||||
};
|
||||
if (i == end(_participants)) {
|
||||
const auto adding = (i == end(_participants));
|
||||
if (adding) {
|
||||
if (value.ssrc) {
|
||||
_participantPeerByAudioSsrc.emplace(
|
||||
value.ssrc,
|
||||
|
@ -802,9 +803,6 @@ void GroupCall::applyParticipantsSlice(
|
|||
participantPeer);
|
||||
}
|
||||
_participants.push_back(value);
|
||||
if (const auto user = participantPeer->asUser()) {
|
||||
_peer->owner().unregisterInvitedToCallUser(_id, user);
|
||||
}
|
||||
} else {
|
||||
if (i->ssrc != value.ssrc) {
|
||||
_participantPeerByAudioSsrc.erase(i->ssrc);
|
||||
|
@ -836,6 +834,11 @@ void GroupCall::applyParticipantsSlice(
|
|||
.now = value,
|
||||
});
|
||||
}
|
||||
if (adding) {
|
||||
if (const auto user = participantPeer->asUser()) {
|
||||
_peer->owner().unregisterInvitedToCallUser(_id, user);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
if (sliceSource == ApplySliceSource::UpdateReceived) {
|
||||
|
|
|
@ -68,6 +68,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "data/data_user.h"
|
||||
#include "main/main_session.h"
|
||||
#include "main/main_session_settings.h"
|
||||
#include "calls/calls_instance.h"
|
||||
#include "core/application.h"
|
||||
#include "core/click_handler_types.h" // ClickHandlerContext
|
||||
#include "lang/lang_keys.h"
|
||||
|
@ -1684,11 +1685,32 @@ std::unique_ptr<HistoryView::Media> MediaLocation::createView(
|
|||
MediaCall::MediaCall(not_null<HistoryItem*> parent, const Call &call)
|
||||
: Media(parent)
|
||||
, _call(call) {
|
||||
parent->history()->owner().registerCallItem(parent);
|
||||
const auto peer = parent->history()->peer;
|
||||
peer->owner().registerCallItem(parent);
|
||||
if (const auto user = _call.conferenceId ? peer->asUser() : nullptr) {
|
||||
if (_call.state == CallState::Invitation) {
|
||||
Core::App().calls().registerConferenceInvite(
|
||||
_call.conferenceId,
|
||||
user,
|
||||
parent->id,
|
||||
!parent->out());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MediaCall::~MediaCall() {
|
||||
parent()->history()->owner().unregisterCallItem(parent());
|
||||
const auto parent = this->parent();
|
||||
const auto peer = parent->history()->peer;
|
||||
peer->owner().unregisterCallItem(parent);
|
||||
if (const auto user = _call.conferenceId ? peer->asUser() : nullptr) {
|
||||
if (_call.state == CallState::Invitation) {
|
||||
Core::App().calls().unregisterConferenceInvite(
|
||||
_call.conferenceId,
|
||||
user,
|
||||
parent->id,
|
||||
!parent->out());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<Media> MediaCall::clone(not_null<HistoryItem*> parent) {
|
||||
|
|
|
@ -1257,6 +1257,7 @@ void Session::unregisterInvitedToCallUser(
|
|||
i->second.remove(user);
|
||||
if (i->second.empty()) {
|
||||
_invitedToCallUsers.erase(i);
|
||||
_invitesToCalls.fire({ callId, user, true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -256,6 +256,7 @@ public:
|
|||
struct InviteToCall {
|
||||
CallId id = 0;
|
||||
not_null<UserData*> user;
|
||||
bool removed = false;
|
||||
};
|
||||
[[nodiscard]] rpl::producer<InviteToCall> invitesToCalls() const {
|
||||
return _invitesToCalls.events();
|
||||
|
|
|
@ -52,7 +52,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "mainwindow.h"
|
||||
#include "main/main_session.h"
|
||||
#include "window/notifications_manager.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "calls/calls_instance.h"
|
||||
#include "spellcheck/spellcheck_types.h"
|
||||
#include "storage/localstorage.h"
|
||||
|
@ -1228,8 +1227,8 @@ void History::applyServiceChanges(
|
|||
}
|
||||
}, [&](const MTPDmessageActionConferenceCall &data) {
|
||||
if (!data.is_active() && !data.is_missed() && !item->out()) {
|
||||
if (const auto window = session().tryResolveWindow()) {
|
||||
window->resolveConferenceCall(item->id);
|
||||
if (const auto user = item->history()->peer->asUser()) {
|
||||
Core::App().calls().showConferenceInvite(user, item->id);
|
||||
}
|
||||
}
|
||||
}, [](const auto &) {
|
||||
|
|
|
@ -881,26 +881,17 @@ void SessionNavigation::resolveConferenceCall(
|
|||
data.vid().v,
|
||||
data.vaccess_hash().v);
|
||||
call->processFullCall(result);
|
||||
const auto confirmed = std::make_shared<bool>();
|
||||
const auto join = [=] {
|
||||
*confirmed = true;
|
||||
Core::App().calls().startOrJoinConferenceCall({
|
||||
.call = call,
|
||||
.linkSlug = slug,
|
||||
.joinMessageId = inviteMsgId,
|
||||
});
|
||||
};
|
||||
const auto box = uiShow()->show(Box(
|
||||
uiShow()->show(Box(
|
||||
Calls::Group::ConferenceCallJoinConfirm,
|
||||
call,
|
||||
join));
|
||||
box->boxClosing() | rpl::start_with_next([=] {
|
||||
if (inviteMsgId && !*confirmed) {
|
||||
_api.request(MTPphone_DeclineConferenceCallInvite(
|
||||
MTP_int(inviteMsgId.bare)
|
||||
)).send();
|
||||
}
|
||||
}, box->lifetime());
|
||||
if (finished) {
|
||||
finished(true);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue