Allow to rejoin with changing of 'join_as'.

This commit is contained in:
John Preston 2021-03-05 19:21:11 +04:00
parent 4d093f78e2
commit b670ca2a51
13 changed files with 235 additions and 123 deletions

View file

@ -287,7 +287,7 @@ updateNewMessage#1f2b0afd message:Message pts:int pts_count:int = Update;
updateMessageID#4e90bfd6 id:int random_id:long = Update;
updateDeleteMessages#a20db0e5 messages:Vector<int> pts:int pts_count:int = Update;
updateUserTyping#5c486927 user_id:int action:SendMessageAction = Update;
updateChatUserTyping#9a65ea1f chat_id:int user_id:int action:SendMessageAction = Update;
updateChatUserTyping#86cadb6c chat_id:int from_id:Peer action:SendMessageAction = Update;
updateChatParticipants#7761198 participants:ChatParticipants = Update;
updateUserStatus#1bfbd823 user_id:int status:UserStatus = Update;
updateUserName#a7332b73 user_id:int first_name:string last_name:string username:string = Update;
@ -364,7 +364,7 @@ updateChannelMessageForwards#6e8a84df channel_id:int id:int forwards:int = Updat
updateReadChannelDiscussionInbox#1cc7de54 flags:# channel_id:int top_msg_id:int read_max_id:int broadcast_id:flags.0?int broadcast_post:flags.0?int = Update;
updateReadChannelDiscussionOutbox#4638a26c channel_id:int top_msg_id:int read_max_id:int = Update;
updatePeerBlocked#246a4b22 peer_id:Peer blocked:Bool = Update;
updateChannelUserTyping#ff2abe9f flags:# channel_id:int top_msg_id:flags.0?int user_id:int action:SendMessageAction = Update;
updateChannelUserTyping#6b171718 flags:# channel_id:int top_msg_id:flags.0?int from_id:Peer action:SendMessageAction = Update;
updatePinnedMessages#ed85eab5 flags:# pinned:flags.0?true peer:Peer messages:Vector<int> pts:int pts_count:int = Update;
updatePinnedChannelMessages#8588878b flags:# pinned:flags.0?true channel_id:int messages:Vector<int> pts:int pts_count:int = Update;
updateChat#1330a196 chat_id:int = Update;
@ -1207,7 +1207,7 @@ groupCall#c0c2052e flags:# join_muted:flags.1?true can_change_join_muted:flags.2
inputGroupCall#d8aa840f id:long access_hash:long = InputGroupCall;
groupCallParticipant#7c48057b flags:# muted:flags.0?true left:flags.1?true can_self_unmute:flags.2?true just_joined:flags.4?true versioned:flags.5?true min:flags.8?true muted_by_you:flags.9?true volume_by_admin:flags.10?true self:flags.12?true peer:Peer date:int active_date:flags.3?int source:flags.12?int volume:flags.7?int about:flags.11?string raise_hand_rating:flags.13?long = GroupCallParticipant;
groupCallParticipant#19adba89 flags:# muted:flags.0?true left:flags.1?true can_self_unmute:flags.2?true just_joined:flags.4?true versioned:flags.5?true min:flags.8?true muted_by_you:flags.9?true volume_by_admin:flags.10?true self:flags.12?true peer:Peer date:int active_date:flags.3?int source:int volume:flags.7?int about:flags.11?string raise_hand_rating:flags.13?long = GroupCallParticipant;
phone.groupCall#9e727aad call:GroupCall participants:Vector<GroupCallParticipant> participants_next_offset:string chats:Vector<Chat> users:Vector<User> = phone.GroupCall;
@ -1611,14 +1611,14 @@ phone.discardCall#b2cbc1c0 flags:# video:flags.0?true peer:InputPhoneCall durati
phone.setCallRating#59ead627 flags:# user_initiative:flags.0?true peer:InputPhoneCall rating:int comment:string = Updates;
phone.saveCallDebug#277add7e peer:InputPhoneCall debug:DataJSON = Bool;
phone.sendSignalingData#ff7a9383 peer:InputPhoneCall data:bytes = Bool;
phone.createGroupCall#7c068f5 peer:InputPeer join_as:InputPeer random_id:int = Updates;
phone.createGroupCall#bd3dabe0 peer:InputPeer random_id:int = Updates;
phone.joinGroupCall#3633a5b0 flags:# muted:flags.0?true call:InputGroupCall join_as:InputPeer params:DataJSON = Updates;
phone.leaveGroupCall#500377f9 call:InputGroupCall source:int = Updates;
phone.inviteToGroupCall#7b393160 call:InputGroupCall users:Vector<InputUser> = Updates;
phone.discardGroupCall#7a777135 call:InputGroupCall = Updates;
phone.toggleGroupCallSettings#74bbb43d flags:# call:InputGroupCall join_muted:flags.0?Bool = Updates;
phone.getGroupCall#c7cb017 call:InputGroupCall = phone.GroupCall;
phone.getGroupParticipants#c9f1d285 call:InputGroupCall ids:Vector<int> sources:Vector<int> offset:string limit:int = phone.GroupParticipants;
phone.getGroupParticipants#c558d8ab call:InputGroupCall ids:Vector<InputPeer> sources:Vector<int> offset:string limit:int = phone.GroupParticipants;
phone.checkGroupCall#b74a7bea call:InputGroupCall source:int = Bool;
phone.toggleGroupCallRecord#c02a66d7 flags:# start:flags.0?true call:InputGroupCall title:flags.1?string = Updates;
phone.editGroupCallParticipant#d975eb80 flags:# muted:flags.0?true call:InputGroupCall participant:InputPeer volume:flags.1?int raise_hand:flags.2?Bool = Updates;

View file

@ -240,16 +240,16 @@ Updates::Updates(not_null<Main::Session*> session)
) | rpl::filter([](not_null<PeerData*> peer) {
return peer->isChat() || peer->isMegagroup();
}) | rpl::start_with_next([=](not_null<PeerData*> peer) {
if (const auto users = _pendingSpeakingCallMembers.take(peer)) {
if (const auto list = _pendingSpeakingCallParticipants.take(peer)) {
if (const auto call = peer->groupCall()) {
for (const auto [userId, when] : *users) {
for (const auto [participantPeerId, when] : *list) {
call->applyActiveUpdate(
userId,
participantPeerId,
Data::LastSpokeTimes{
.anything = when,
.voice = when
},
peer->owner().userLoaded(userId));
peer->owner().peerLoaded(participantPeerId));
}
}
}
@ -915,16 +915,16 @@ bool Updates::isQuitPrevent() {
void Updates::handleSendActionUpdate(
PeerId peerId,
MsgId rootId,
UserId userId,
PeerId fromId,
const MTPSendMessageAction &action) {
const auto history = session().data().historyLoaded(peerId);
if (!history) {
return;
}
const auto peer = history->peer;
const auto user = (userId == session().userId())
const auto from = (fromId == session().userPeerId())
? session().user().get()
: session().data().userLoaded(userId);
: session().data().peerLoaded(fromId);
const auto isSpeakingInCall = (action.type()
== mtpc_speakingInGroupCallAction);
if (isSpeakingInCall) {
@ -935,9 +935,9 @@ void Updates::handleSendActionUpdate(
const auto now = crl::now();
if (call) {
call->applyActiveUpdate(
userId,
fromId,
Data::LastSpokeTimes{ .anything = now, .voice = now },
user);
from);
} else {
const auto chat = peer->asChat();
const auto channel = peer->asChannel();
@ -945,13 +945,15 @@ void Updates::handleSendActionUpdate(
? (chat->flags() & MTPDchat::Flag::f_call_active)
: (channel->flags() & MTPDchannel::Flag::f_call_active);
if (active) {
_pendingSpeakingCallMembers.emplace(
peer).first->second[userId] = now;
session().api().requestFullPeer(peer);
_pendingSpeakingCallParticipants.emplace(
peer).first->second[fromId] = now;
if (peerIsUser(fromId)) {
session().api().requestFullPeer(peer);
}
}
}
}
if (!user || user->isSelf()) {
if (!from || !from->isUser() || from->isSelf()) {
return;
}
const auto when = requestingDifference()
@ -960,7 +962,7 @@ void Updates::handleSendActionUpdate(
session().data().registerSendAction(
history,
rootId,
user,
from->asUser(),
action,
when);
}
@ -1642,19 +1644,21 @@ void Updates::feedUpdate(const MTPUpdate &update) {
case mtpc_updateChatUserTyping: {
auto &d = update.c_updateChatUserTyping();
const auto fromId = peerFromMTP(d.vfrom_id());
handleSendActionUpdate(
peerFromChat(d.vchat_id()),
0,
d.vuser_id().v,
fromId,
d.vaction());
} break;
case mtpc_updateChannelUserTyping: {
const auto &d = update.c_updateChannelUserTyping();
const auto fromId = peerFromMTP(d.vfrom_id());
handleSendActionUpdate(
peerFromChannel(d.vchannel_id()),
d.vtop_msg_id().value_or_empty(),
d.vuser_id().v,
fromId,
d.vaction());
} break;

View file

@ -125,7 +125,7 @@ private:
void handleSendActionUpdate(
PeerId peerId,
MsgId rootId,
UserId userId,
PeerId fromId,
const MTPSendMessageAction &action);
const not_null<Main::Session*> _session;
@ -168,7 +168,7 @@ private:
base::flat_map<int, ActiveChatTracker> _activeChats;
base::flat_map<
not_null<PeerData*>,
base::flat_map<UserId, crl::time>> _pendingSpeakingCallMembers;
base::flat_map<PeerId, crl::time>> _pendingSpeakingCallParticipants;
mtpRequestId _onlineRequest = 0;
base::Timer _idleFinishTimer;

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "calls/calls_choose_join_as.h"
#include "calls/calls_group_common.h"
#include "data/data_peer.h"
#include "data/data_user.h"
#include "data/data_channel.h"
@ -18,8 +19,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/layers/generic_box.h"
#include "boxes/peer_list_box.h"
#include "styles/style_boxes.h"
#include "styles/style_calls.h"
namespace Calls {
namespace Calls::Group {
namespace {
using Context = ChooseJoinAsProcess::Context;
@ -107,9 +109,8 @@ not_null<PeerData*> ListController::selected() const {
void ChooseJoinAsBox(
not_null<Ui::GenericBox*> box,
Context context,
std::vector<not_null<PeerData*>> list,
not_null<PeerData*> selected,
Fn<void(not_null<PeerData*>)> done) {
JoinInfo info,
Fn<void(JoinInfo)> done) {
box->setTitle([&] {
switch (context) {
case Context::Create: return tr::lng_group_call_start_as_header();
@ -121,23 +122,31 @@ void ChooseJoinAsBox(
box->addRow(object_ptr<Ui::FlatLabel>(
box,
tr::lng_group_call_join_as_about(),
st::confirmPhoneAboutLabel));
(context == Context::Switch
? st::groupCallBoxLabel
: st::confirmPhoneAboutLabel)));
auto &lifetime = box->lifetime();
const auto delegate = lifetime.make_state<
PeerListContentDelegateSimple
>();
const auto controller = lifetime.make_state<ListController>(
std::move(list),
selected);
//controller->setStyleOverrides();
info.possibleJoinAs,
info.joinAs);
if (context == Context::Switch) {
controller->setStyleOverrides(
&st::groupCallInviteMembersList,
&st::groupCallMultiSelect);
}
const auto content = box->addRow(
object_ptr<PeerListContent>(box, controller),
style::margins());
delegate->setContent(content);
controller->setDelegate(delegate);
box->addButton(tr::lng_continue(), [=] {
done(controller->selected());
auto copy = info;
copy.joinAs = controller->selected();
done(std::move(copy));
});
box->addButton(tr::lng_cancel(), [=] { box->closeBox(); });
}
@ -153,13 +162,16 @@ ChooseJoinAsProcess::~ChooseJoinAsProcess() {
void ChooseJoinAsProcess::start(
not_null<PeerData*> peer,
Context context,
Fn<void(not_null<PeerData*>, not_null<PeerData*>)> done) {
Fn<void(object_ptr<Ui::BoxContent>)> showBox,
Fn<void(JoinInfo)> done,
PeerData *currentJoinAs) {
Expects(done != nullptr);
const auto session = &peer->session();
if (_request) {
const auto already = _request->peer;
_request->context = context;
_request->showBox = std::move(showBox);
_request->done = std::move(done);
if (already == peer) {
return;
@ -173,6 +185,7 @@ void ChooseJoinAsProcess::start(
_request = std::make_unique<ChannelsListRequest>(
ChannelsListRequest{
.peer = peer,
.showBox = std::move(showBox),
.done = std::move(done),
.context = context });
session->account().sessionChanges(
@ -180,12 +193,12 @@ void ChooseJoinAsProcess::start(
_request = nullptr;
}, _request->lifetime);
const auto finish = [=](not_null<PeerData*> joinAs) {
const auto finish = [=](JoinInfo info) {
const auto peer = _request->peer;
const auto done = std::move(_request->done);
const auto box = _request->box;
_request = nullptr;
done(peer, joinAs);
done(std::move(info));
if (const auto strong = box.data()) {
strong->closeBox();
}
@ -200,8 +213,9 @@ void ChooseJoinAsProcess::start(
});
const auto peer = _request->peer;
const auto self = peer->session().user();
auto info = JoinInfo{ .peer = peer, .joinAs = self };
if (chats.size() == 1) {
finish(self);
finish(info);
return;
}
auto list = std::vector<not_null<PeerData*>>();
@ -210,8 +224,8 @@ void ChooseJoinAsProcess::start(
for (const auto &chat : chats) {
list.push_back(session->data().processChat(chat));
}
const auto selectedId = peer->groupCallDefaultJoinAs();
const auto selected = [&]() -> not_null<PeerData*> {
const auto selected = [&]() -> PeerData* {
const auto selectedId = peer->groupCallDefaultJoinAs();
if (!selectedId) {
return self;
}
@ -220,22 +234,27 @@ void ChooseJoinAsProcess::start(
? not_null(loaded)
: self;
}();
_request->box = Ui::show(
Box(
ChooseJoinAsBox,
_request->context,
std::move(list),
selected,
crl::guard(&_request->guard, finish)),
Ui::LayerOption::KeepOther);
_request->box->boxClosing(
info.joinAs = currentJoinAs ? currentJoinAs : selected;
info.possibleJoinAs = std::move(list);
auto box = Box(
ChooseJoinAsBox,
context,
std::move(info),
crl::guard(&_request->guard, finish));
box->boxClosing(
) | rpl::start_with_next([=] {
_request = nullptr;
}, _request->lifetime);
_request->box = box.data();
_request->showBox(std::move(box));
}).fail([=](const RPCError &error) {
finish(session->user());
finish({
.peer = _request->peer,
.joinAs = _request->peer->session().user(),
});
}).send();
}
} // namespace Calls
} // namespace Calls::Group

View file

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once
#include "base/weak_ptr.h"
#include "base/object_ptr.h"
class PeerData;
@ -15,7 +16,9 @@ namespace Ui {
class BoxContent;
} // namespace Ui
namespace Calls {
namespace Calls::Group {
struct JoinInfo;
class ChooseJoinAsProcess final {
public:
@ -31,12 +34,15 @@ public:
void start(
not_null<PeerData*> peer,
Context context,
Fn<void(not_null<PeerData*> peer, not_null<PeerData*> joinAs)> done);
Fn<void(object_ptr<Ui::BoxContent>)> showBox,
Fn<void(JoinInfo)> done,
PeerData *currentJoinAs = nullptr);
private:
struct ChannelsListRequest {
not_null<PeerData*> peer;
Fn<void(not_null<PeerData*>, not_null<PeerData*>)> done;
Fn<void(object_ptr<Ui::BoxContent>)> showBox;
Fn<void(JoinInfo)> done;
base::has_weak_ptr guard;
QPointer<Ui::BoxContent> box;
rpl::lifetime lifetime;
@ -47,4 +53,4 @@ private:
};
} // namespace Calls
} // namespace Calls::Group

View file

@ -102,14 +102,14 @@ constexpr auto kPlayConnectingEach = crl::time(1056) + 2 * crl::time(1000);
GroupCall::GroupCall(
not_null<Delegate*> delegate,
not_null<PeerData*> peer,
const MTPInputGroupCall &inputCall,
not_null<PeerData*> joinAs)
Group::JoinInfo info,
const MTPInputGroupCall &inputCall)
: _delegate(delegate)
, _peer(peer)
, _history(peer->owner().history(peer))
, _joinAs(joinAs)
, _api(&peer->session().mtp())
, _peer(info.peer)
, _history(_peer->owner().history(_peer))
, _api(&_peer->session().mtp())
, _joinAs(info.joinAs)
, _possibleJoinAs(std::move(info.possibleJoinAs))
, _lastSpokeCheckTimer([=] { checkLastSpoke(); })
, _checkJoinedTimer([=] { checkJoined(); })
, _pushToTalkCancelTimer([=] { pushToTalkCancel(); })
@ -247,7 +247,6 @@ void GroupCall::playConnectingSoundOnce() {
void GroupCall::start() {
_createRequestId = _api.request(MTPphone_CreateGroupCall(
_peer->input,
_joinAs->input,
MTP_int(openssl::RandomValue<int32>())
)).done([=](const MTPUpdates &result) {
_acceptFields = true;
@ -499,6 +498,21 @@ void GroupCall::discard() {
}).send();
}
void GroupCall::rejoinAs(Group::JoinInfo info) {
_possibleJoinAs = std::move(info.possibleJoinAs);
if (info.joinAs == _joinAs) {
return;
}
const auto event = Group::RejoinEvent{
.wasJoinAs = _joinAs,
.nowJoinAs = info.joinAs,
};
_joinAs = info.joinAs;
setState(State::Joining);
rejoin();
_rejoinEvents.fire_copy(event);
}
void GroupCall::finish(FinishType type) {
Expects(type != FinishType::None);
@ -667,15 +681,15 @@ void GroupCall::handleUpdate(const MTPDupdateGroupCallParticipants &data) {
handleOtherParticipants(data);
return;
}
if (data.is_left() && data.vsource().value_or_empty() == _mySsrc) {
if (data.is_left() && data.vsource().v == _mySsrc) {
// I was removed from the call, rejoin.
LOG(("Call Info: Rejoin after got 'left' with my ssrc."));
setState(State::Joining);
rejoin();
} else if (!data.is_left() && data.vsource().value_or_empty() != _mySsrc) {
} else if (!data.is_left() && data.vsource().v != _mySsrc) {
// I joined from another device, hangup.
LOG(("Call Info: Hangup after '!left' with ssrc %1, my %2."
).arg(data.vsource().value_or_empty()
).arg(data.vsource().v
).arg(_mySsrc));
_mySsrc = 0;
hangup();

View file

@ -39,6 +39,8 @@ namespace Group {
struct MuteRequest;
struct VolumeRequest;
struct ParticipantState;
struct JoinInfo;
struct RejoinEvent;
} // namespace Group
enum class MuteState {
@ -88,9 +90,8 @@ public:
GroupCall(
not_null<Delegate*> delegate,
not_null<PeerData*> peer,
const MTPInputGroupCall &inputCall,
not_null<PeerData*> joinAs);
Group::JoinInfo info,
const MTPInputGroupCall &inputCall);
~GroupCall();
[[nodiscard]] uint64 id() const {
@ -102,10 +103,15 @@ public:
[[nodiscard]] not_null<PeerData*> joinAs() const {
return _joinAs;
}
[[nodiscard]] auto possibleJoinAs() const
-> const std::vector<not_null<PeerData*>>& {
return _possibleJoinAs;
}
void start();
void hangup();
void discard();
void rejoinAs(Group::JoinInfo info);
void join(const MTPInputGroupCall &inputCall);
void handleUpdate(const MTPGroupCall &call);
void handleUpdate(const MTPDupdateGroupCallParticipants &data);
@ -142,6 +148,9 @@ public:
[[nodiscard]] rpl::producer<LevelUpdate> levelUpdates() const {
return _levelUpdates.events();
}
[[nodiscard]] rpl::producer<Group::RejoinEvent> rejoinEvents() const {
return _rejoinEvents.events();
}
static constexpr auto kSpeakLevelThreshold = 0.2;
void setCurrentAudioDevice(bool input, const QString &deviceId);
@ -211,11 +220,13 @@ private:
const not_null<Delegate*> _delegate;
not_null<PeerData*> _peer; // Can change in legacy group migration.
not_null<History*> _history; // Can change in legacy group migration.
not_null<PeerData*> _joinAs;
MTP::Sender _api;
rpl::variable<State> _state = State::Creating;
bool _instanceConnected = false;
not_null<PeerData*> _joinAs;
std::vector<not_null<PeerData*>> _possibleJoinAs;
rpl::variable<MuteState> _muted = MuteState::Muted;
bool _acceptFields = false;
@ -230,6 +241,7 @@ private:
std::unique_ptr<tgcalls::GroupInstanceImpl> _instance;
rpl::event_stream<LevelUpdate> _levelUpdates;
base::flat_map<uint32, Data::LastSpokeTimes> _lastSpoke;
rpl::event_stream<Group::RejoinEvent> _rejoinEvents;
base::Timer _lastSpokeCheckTimer;
base::Timer _checkJoinedTimer;

View file

@ -34,4 +34,15 @@ struct ParticipantState {
bool locallyOnly = false;
};
struct RejoinEvent {
not_null<PeerData*> wasJoinAs;
not_null<PeerData*> nowJoinAs;
};
struct JoinInfo {
not_null<PeerData*> peer;
not_null<PeerData*> joinAs;
std::vector<not_null<PeerData*>> possibleJoinAs;
};
} // namespace Calls::Group

View file

@ -855,6 +855,29 @@ void MembersController::setupListChangeViewers(not_null<GroupCall*> call) {
updateRowLevel(i->second, update.value);
}
}, _lifetime);
call->rejoinEvents(
) | rpl::start_with_next([=](const Group::RejoinEvent &event) {
const auto guard = gsl::finally([&] {
delegate()->peerListRefreshRows();
});
if (const auto row = findRow(event.wasJoinAs)) {
if (row->state() != Row::State::Invited) {
if (const auto min = _fullCountMin.current()) {
_fullCountMin = min - 1;
}
}
removeRow(row);
}
if (findRow(event.nowJoinAs)) {
return;
} else if (auto row = createRowForMe()) {
if (row->state() != Row::State::Invited) {
_fullCountMin = _fullCountMin.current() + 1;
}
delegate()->peerListAppendRow(std::move(row));
}
}, _lifetime);
}
void MembersController::subscribeToChanges(not_null<Data::GroupCall*> real) {

View file

@ -9,7 +9,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "calls/calls_group_call.h"
#include "calls/calls_group_panel.h" // LeaveGroupCallBox.
#include "calls/calls_group_common.h"
#include "calls/calls_instance.h"
#include "calls/calls_choose_join_as.h"
#include "ui/widgets/level_meter.h"
#include "ui/widgets/continuous_sliders.h"
#include "ui/widgets/buttons.h"
@ -100,6 +102,7 @@ void GroupCallSettingsBox(
float micLevel = 0.;
Ui::Animations::Simple micLevelAnimation;
base::Timer levelUpdateTimer;
Group::ChooseJoinAsProcess joinAsProcess;
bool generatingLink = false;
};
const auto state = box->lifetime().make_state<State>();
@ -115,16 +118,40 @@ void GroupCallSettingsBox(
const auto joinMuted = goodReal ? real->joinMuted() : false;
const auto canChangeJoinMuted = (goodReal && real->canChangeJoinMuted());
const auto addCheck = (peer->canManageGroupCall() && canChangeJoinMuted);
if (addCheck) {
const auto addEditJoinAs = (call->possibleJoinAs().size() > 1);
if (addCheck || addEditJoinAs) {
AddSkip(layout);
}
const auto editJoinAs = addEditJoinAs
? AddButton(
layout,
tr::lng_group_call_display_as_header(),
st::groupCallSettingsButton).get()
: nullptr;
if (editJoinAs) {
editJoinAs->setClickedCallback([=] {
const auto context = Group::ChooseJoinAsProcess::Context::Switch;
const auto callback = [=](Group::JoinInfo info) {
call->rejoinAs(info);
};
auto showBox = [=](object_ptr<Ui::BoxContent> next) {
box->getDelegate()->show(std::move(next));
};
state->joinAsProcess.start(
peer,
context,
showBox,
callback,
call->joinAs());
});
}
const auto muteJoined = addCheck
? AddButton(
layout,
tr::lng_group_call_new_muted(),
st::groupCallSettingsButton)->toggleOn(rpl::single(joinMuted))
: nullptr;
if (addCheck) {
if (addCheck || addEditJoinAs) {
AddSkip(layout);
}

View file

@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "calls/calls_instance.h"
#include "calls/calls_group_common.h"
#include "mtproto/mtproto_dh_utils.h"
#include "core/application.h"
#include "main/main_session.h"
@ -61,27 +62,18 @@ void Instance::startOutgoingCall(not_null<UserData*> user, bool video) {
void Instance::startOrJoinGroupCall(not_null<PeerData*> peer) {
const auto context = peer->groupCall()
? ChooseJoinAsProcess::Context::Join
: ChooseJoinAsProcess::Context::Create;
_chooseJoinAs.start(peer, context, [=](
not_null<PeerData*> peer,
not_null<PeerData*> joinAs) {
startOrJoinGroupCall(peer, joinAs);
? Group::ChooseJoinAsProcess::Context::Join
: Group::ChooseJoinAsProcess::Context::Create;
_chooseJoinAs.start(peer, context, [=](object_ptr<Ui::BoxContent> box) {
Ui::show(std::move(box), Ui::LayerOption::KeepOther);
}, [=](Group::JoinInfo info) {
const auto call = info.peer->groupCall();
createGroupCall(
std::move(info),
call ? call->input() : MTP_inputGroupCall(MTPlong(), MTPlong()));
});
}
void Instance::startOrJoinGroupCall(
not_null<PeerData*> peer,
not_null<PeerData*> joinAs) {
destroyCurrentCall();
const auto call = peer->groupCall();
createGroupCall(
peer,
call ? call->input() : MTP_inputGroupCall(MTPlong(), MTPlong()),
joinAs);
}
void Instance::callFinished(not_null<Call*> call) {
crl::on_main(call, [=] {
destroyCall(call);
@ -208,19 +200,17 @@ void Instance::destroyGroupCall(not_null<GroupCall*> call) {
}
void Instance::createGroupCall(
not_null<PeerData*> peer,
const MTPInputGroupCall &inputCall,
not_null<PeerData*> joinAs) {
Group::JoinInfo info,
const MTPInputGroupCall &inputCall) {
destroyCurrentCall();
auto call = std::make_unique<GroupCall>(
getGroupCallDelegate(),
peer,
inputCall,
joinAs);
std::move(info),
inputCall);
const auto raw = call.get();
peer->session().account().sessionChanges(
info.peer->session().account().sessionChanges(
) | rpl::start_with_next([=] {
destroyGroupCall(raw);
}, raw->lifetime());

View file

@ -16,16 +16,18 @@ namespace Platform {
enum class PermissionType;
} // namespace Platform
namespace Media {
namespace Audio {
namespace Media::Audio {
class Track;
} // namespace Audio
} // namespace Media
} // namespace Media::Audio
namespace Main {
class Session;
} // namespace Main
namespace Calls::Group {
struct JoinInfo;
} // namespace Calls::Group
namespace Calls {
class Panel;
@ -42,9 +44,6 @@ public:
void startOutgoingCall(not_null<UserData*> user, bool video);
void startOrJoinGroupCall(not_null<PeerData*> peer);
void startOrJoinGroupCall(
not_null<PeerData*> peer,
not_null<PeerData*> joinAs);
void handleUpdate(
not_null<Main::Session*> session,
const MTPUpdate &update);
@ -107,9 +106,8 @@ private:
void destroyCall(not_null<Call*> call);
void createGroupCall(
not_null<PeerData*> peer,
const MTPInputGroupCall &inputCall,
not_null<PeerData*> joinAs);
Group::JoinInfo info,
const MTPInputGroupCall &inputCall);
void destroyGroupCall(not_null<GroupCall*> call);
void requestPermissionOrFail(
@ -150,7 +148,7 @@ private:
base::flat_map<QString, std::unique_ptr<Media::Audio::Track>> _tracks;
ChooseJoinAsProcess _chooseJoinAs;
Group::ChooseJoinAsProcess _chooseJoinAs;
};

View file

@ -79,7 +79,7 @@ void GroupCall::requestParticipants() {
}
_participantsRequestId = api().request(MTPphone_GetGroupParticipants(
input(),
MTP_vector<MTPint>(), // ids
MTP_vector<MTPInputPeer>(), // ids
MTP_vector<MTPint>(), // ssrcs
MTP_string(_nextOffset),
MTP_int(kRequestPerPage)
@ -296,7 +296,7 @@ void GroupCall::applyParticipantsSlice(
.peer = participantPeer,
.date = data.vdate().v,
.lastActive = lastActive,
.ssrc = uint32(data.vsource().value_or_empty()),
.ssrc = uint32(data.vsource().v),
.volume = volume,
.applyVolumeFromMin = applyVolumeFromMin,
.speaking = canSelfUnmute && (was ? was->speaking : false),
@ -469,7 +469,7 @@ void GroupCall::requestUnknownParticipants() {
}
return result;
}();
const auto peerIds = [&] {
const auto participantPeerIds = [&] {
if (_unknownSpokenPeerIds.size() + ssrcs.size() < kRequestPerPage) {
return base::take(_unknownSpokenPeerIds);
}
@ -478,8 +478,9 @@ void GroupCall::requestUnknownParticipants() {
if (available > 0) {
result.reserve(available);
while (result.size() < available) {
const auto [userId, when] = _unknownSpokenPeerIds.back();
result.emplace(userId, when);
const auto &back = _unknownSpokenPeerIds.back();
const auto [participantPeerId, when] = back;
result.emplace(participantPeerId, when);
_unknownSpokenPeerIds.erase(_unknownSpokenPeerIds.end() - 1);
}
}
@ -490,16 +491,23 @@ void GroupCall::requestUnknownParticipants() {
for (const auto [ssrc, when] : ssrcs) {
ssrcInputs.push_back(MTP_int(ssrc));
}
auto uidInputs = QVector<MTPint>();
uidInputs.reserve(peerIds.size());
for (const auto [peerId, when] : peerIds) {
Assert(peerIsUser(peerId)); // #TODO calls
uidInputs.push_back(MTP_int(peerToUser(peerId)));
auto peerInputs = QVector<MTPInputPeer>();
peerInputs.reserve(participantPeerIds.size());
for (const auto [participantPeerId, when] : participantPeerIds) {
if (const auto userId = peerToUser(participantPeerId)) {
peerInputs.push_back(
MTP_inputPeerUser(MTP_int(userId), MTP_long(0)));
} else if (const auto chatId = peerToChat(participantPeerId)) {
peerInputs.push_back(MTP_inputPeerChat(MTP_int(chatId)));
} else if (const auto channelId = peerToChannel(participantPeerId)) {
peerInputs.push_back(
MTP_inputPeerChannel(MTP_int(channelId), MTP_long(0)));
}
}
_unknownParticipantPeersRequestId = api().request(
MTPphone_GetGroupParticipants(
input(),
MTP_vector<MTPint>(uidInputs),
MTP_vector<MTPInputPeer>(peerInputs),
MTP_vector<MTPint>(ssrcInputs),
MTP_string(QString()),
MTP_int(kRequestPerPage)
@ -517,17 +525,17 @@ void GroupCall::requestUnknownParticipants() {
applyLastSpoke(ssrc, when, now);
_unknownSpokenSsrcs.remove(ssrc);
}
for (const auto [peerId, when] : peerIds) {
if (const auto participantPeer = _peer->owner().peerLoaded(peerId)) {
for (const auto [id, when] : participantPeerIds) {
if (const auto participantPeer = _peer->owner().peerLoaded(id)) {
const auto isParticipant = ranges::contains(
_participants,
not_null{ participantPeer },
&Participant::peer);
if (isParticipant) {
applyActiveUpdate(peerId, when, participantPeer);
applyActiveUpdate(id, when, participantPeer);
}
}
_unknownSpokenPeerIds.remove(peerId);
_unknownSpokenPeerIds.remove(id);
}
requestUnknownParticipants();
}).fail([=](const RPCError &error) {
@ -535,8 +543,8 @@ void GroupCall::requestUnknownParticipants() {
for (const auto [ssrc, when] : ssrcs) {
_unknownSpokenSsrcs.remove(ssrc);
}
for (const auto [peerId, when] : peerIds) {
_unknownSpokenPeerIds.remove(peerId);
for (const auto [participantPeerId, when] : participantPeerIds) {
_unknownSpokenPeerIds.remove(participantPeerId);
}
requestUnknownParticipants();
}).send();