From b670ca2a51db80bb40c3317c7128cfac36082a08 Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 5 Mar 2021 19:21:11 +0400 Subject: [PATCH] Allow to rejoin with changing of 'join_as'. --- Telegram/Resources/tl/api.tl | 10 +-- Telegram/SourceFiles/api/api_updates.cpp | 36 +++++----- Telegram/SourceFiles/api/api_updates.h | 4 +- .../calls/calls_choose_join_as.cpp | 71 ++++++++++++------- .../SourceFiles/calls/calls_choose_join_as.h | 14 ++-- .../SourceFiles/calls/calls_group_call.cpp | 36 +++++++--- Telegram/SourceFiles/calls/calls_group_call.h | 20 ++++-- .../SourceFiles/calls/calls_group_common.h | 11 +++ .../SourceFiles/calls/calls_group_members.cpp | 23 ++++++ .../calls/calls_group_settings.cpp | 31 +++++++- Telegram/SourceFiles/calls/calls_instance.cpp | 40 ++++------- Telegram/SourceFiles/calls/calls_instance.h | 20 +++--- Telegram/SourceFiles/data/data_group_call.cpp | 42 ++++++----- 13 files changed, 235 insertions(+), 123 deletions(-) diff --git a/Telegram/Resources/tl/api.tl b/Telegram/Resources/tl/api.tl index 49de06454..930dbf490 100644 --- a/Telegram/Resources/tl/api.tl +++ b/Telegram/Resources/tl/api.tl @@ -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 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 pts:int pts_count:int = Update; updatePinnedChannelMessages#8588878b flags:# pinned:flags.0?true channel_id:int messages:Vector 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 participants_next_offset:string chats:Vector users:Vector = 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 = 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 sources:Vector offset:string limit:int = phone.GroupParticipants; +phone.getGroupParticipants#c558d8ab call:InputGroupCall ids:Vector sources:Vector 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; diff --git a/Telegram/SourceFiles/api/api_updates.cpp b/Telegram/SourceFiles/api/api_updates.cpp index f92079473..70610ac41 100644 --- a/Telegram/SourceFiles/api/api_updates.cpp +++ b/Telegram/SourceFiles/api/api_updates.cpp @@ -240,16 +240,16 @@ Updates::Updates(not_null session) ) | rpl::filter([](not_null peer) { return peer->isChat() || peer->isMegagroup(); }) | rpl::start_with_next([=](not_null 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; diff --git a/Telegram/SourceFiles/api/api_updates.h b/Telegram/SourceFiles/api/api_updates.h index e6ca8502c..17f8cc9f8 100644 --- a/Telegram/SourceFiles/api/api_updates.h +++ b/Telegram/SourceFiles/api/api_updates.h @@ -125,7 +125,7 @@ private: void handleSendActionUpdate( PeerId peerId, MsgId rootId, - UserId userId, + PeerId fromId, const MTPSendMessageAction &action); const not_null _session; @@ -168,7 +168,7 @@ private: base::flat_map _activeChats; base::flat_map< not_null, - base::flat_map> _pendingSpeakingCallMembers; + base::flat_map> _pendingSpeakingCallParticipants; mtpRequestId _onlineRequest = 0; base::Timer _idleFinishTimer; diff --git a/Telegram/SourceFiles/calls/calls_choose_join_as.cpp b/Telegram/SourceFiles/calls/calls_choose_join_as.cpp index b6cb42289..d7dba4b4b 100644 --- a/Telegram/SourceFiles/calls/calls_choose_join_as.cpp +++ b/Telegram/SourceFiles/calls/calls_choose_join_as.cpp @@ -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 ListController::selected() const { void ChooseJoinAsBox( not_null box, Context context, - std::vector> list, - not_null selected, - Fn)> done) { + JoinInfo info, + Fn 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( 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( - 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(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 peer, Context context, - Fn, not_null)> done) { + Fn)> showBox, + Fn 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{ .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 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>(); @@ -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 { + 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 diff --git a/Telegram/SourceFiles/calls/calls_choose_join_as.h b/Telegram/SourceFiles/calls/calls_choose_join_as.h index 9d06c17cf..2acb10857 100644 --- a/Telegram/SourceFiles/calls/calls_choose_join_as.h +++ b/Telegram/SourceFiles/calls/calls_choose_join_as.h @@ -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 peer, Context context, - Fn peer, not_null joinAs)> done); + Fn)> showBox, + Fn done, + PeerData *currentJoinAs = nullptr); private: struct ChannelsListRequest { not_null peer; - Fn, not_null)> done; + Fn)> showBox; + Fn done; base::has_weak_ptr guard; QPointer box; rpl::lifetime lifetime; @@ -47,4 +53,4 @@ private: }; -} // namespace Calls +} // namespace Calls::Group diff --git a/Telegram/SourceFiles/calls/calls_group_call.cpp b/Telegram/SourceFiles/calls/calls_group_call.cpp index cb7e9bb61..2aa99e0e1 100644 --- a/Telegram/SourceFiles/calls/calls_group_call.cpp +++ b/Telegram/SourceFiles/calls/calls_group_call.cpp @@ -102,14 +102,14 @@ constexpr auto kPlayConnectingEach = crl::time(1056) + 2 * crl::time(1000); GroupCall::GroupCall( not_null delegate, - not_null peer, - const MTPInputGroupCall &inputCall, - not_null 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()) )).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(); diff --git a/Telegram/SourceFiles/calls/calls_group_call.h b/Telegram/SourceFiles/calls/calls_group_call.h index 7da51d98a..c681222c2 100644 --- a/Telegram/SourceFiles/calls/calls_group_call.h +++ b/Telegram/SourceFiles/calls/calls_group_call.h @@ -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, - not_null peer, - const MTPInputGroupCall &inputCall, - not_null joinAs); + Group::JoinInfo info, + const MTPInputGroupCall &inputCall); ~GroupCall(); [[nodiscard]] uint64 id() const { @@ -102,10 +103,15 @@ public: [[nodiscard]] not_null joinAs() const { return _joinAs; } + [[nodiscard]] auto possibleJoinAs() const + -> const std::vector>& { + 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 levelUpdates() const { return _levelUpdates.events(); } + [[nodiscard]] rpl::producer 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; not_null _peer; // Can change in legacy group migration. not_null _history; // Can change in legacy group migration. - not_null _joinAs; MTP::Sender _api; rpl::variable _state = State::Creating; bool _instanceConnected = false; + not_null _joinAs; + std::vector> _possibleJoinAs; + rpl::variable _muted = MuteState::Muted; bool _acceptFields = false; @@ -230,6 +241,7 @@ private: std::unique_ptr _instance; rpl::event_stream _levelUpdates; base::flat_map _lastSpoke; + rpl::event_stream _rejoinEvents; base::Timer _lastSpokeCheckTimer; base::Timer _checkJoinedTimer; diff --git a/Telegram/SourceFiles/calls/calls_group_common.h b/Telegram/SourceFiles/calls/calls_group_common.h index a22cd9f62..67faaf5c3 100644 --- a/Telegram/SourceFiles/calls/calls_group_common.h +++ b/Telegram/SourceFiles/calls/calls_group_common.h @@ -34,4 +34,15 @@ struct ParticipantState { bool locallyOnly = false; }; +struct RejoinEvent { + not_null wasJoinAs; + not_null nowJoinAs; +}; + +struct JoinInfo { + not_null peer; + not_null joinAs; + std::vector> possibleJoinAs; +}; + } // namespace Calls::Group diff --git a/Telegram/SourceFiles/calls/calls_group_members.cpp b/Telegram/SourceFiles/calls/calls_group_members.cpp index 1598c7194..996508781 100644 --- a/Telegram/SourceFiles/calls/calls_group_members.cpp +++ b/Telegram/SourceFiles/calls/calls_group_members.cpp @@ -855,6 +855,29 @@ void MembersController::setupListChangeViewers(not_null 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 real) { diff --git a/Telegram/SourceFiles/calls/calls_group_settings.cpp b/Telegram/SourceFiles/calls/calls_group_settings.cpp index 1ff199880..153ad5688 100644 --- a/Telegram/SourceFiles/calls/calls_group_settings.cpp +++ b/Telegram/SourceFiles/calls/calls_group_settings.cpp @@ -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(); @@ -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 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); } diff --git a/Telegram/SourceFiles/calls/calls_instance.cpp b/Telegram/SourceFiles/calls/calls_instance.cpp index 665914ab5..358efc86b 100644 --- a/Telegram/SourceFiles/calls/calls_instance.cpp +++ b/Telegram/SourceFiles/calls/calls_instance.cpp @@ -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 user, bool video) { void Instance::startOrJoinGroupCall(not_null peer) { const auto context = peer->groupCall() - ? ChooseJoinAsProcess::Context::Join - : ChooseJoinAsProcess::Context::Create; - _chooseJoinAs.start(peer, context, [=]( - not_null peer, - not_null joinAs) { - startOrJoinGroupCall(peer, joinAs); + ? Group::ChooseJoinAsProcess::Context::Join + : Group::ChooseJoinAsProcess::Context::Create; + _chooseJoinAs.start(peer, context, [=](object_ptr 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 peer, - not_null joinAs) { - destroyCurrentCall(); - - const auto call = peer->groupCall(); - createGroupCall( - peer, - call ? call->input() : MTP_inputGroupCall(MTPlong(), MTPlong()), - joinAs); -} - void Instance::callFinished(not_null call) { crl::on_main(call, [=] { destroyCall(call); @@ -208,19 +200,17 @@ void Instance::destroyGroupCall(not_null call) { } void Instance::createGroupCall( - not_null peer, - const MTPInputGroupCall &inputCall, - not_null joinAs) { + Group::JoinInfo info, + const MTPInputGroupCall &inputCall) { destroyCurrentCall(); auto call = std::make_unique( 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()); diff --git a/Telegram/SourceFiles/calls/calls_instance.h b/Telegram/SourceFiles/calls/calls_instance.h index fe7ae440b..a02b6ebc9 100644 --- a/Telegram/SourceFiles/calls/calls_instance.h +++ b/Telegram/SourceFiles/calls/calls_instance.h @@ -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 user, bool video); void startOrJoinGroupCall(not_null peer); - void startOrJoinGroupCall( - not_null peer, - not_null joinAs); void handleUpdate( not_null session, const MTPUpdate &update); @@ -107,9 +106,8 @@ private: void destroyCall(not_null call); void createGroupCall( - not_null peer, - const MTPInputGroupCall &inputCall, - not_null joinAs); + Group::JoinInfo info, + const MTPInputGroupCall &inputCall); void destroyGroupCall(not_null call); void requestPermissionOrFail( @@ -150,7 +148,7 @@ private: base::flat_map> _tracks; - ChooseJoinAsProcess _chooseJoinAs; + Group::ChooseJoinAsProcess _chooseJoinAs; }; diff --git a/Telegram/SourceFiles/data/data_group_call.cpp b/Telegram/SourceFiles/data/data_group_call.cpp index f7cbdb059..79f44003f 100644 --- a/Telegram/SourceFiles/data/data_group_call.cpp +++ b/Telegram/SourceFiles/data/data_group_call.cpp @@ -79,7 +79,7 @@ void GroupCall::requestParticipants() { } _participantsRequestId = api().request(MTPphone_GetGroupParticipants( input(), - MTP_vector(), // ids + MTP_vector(), // ids MTP_vector(), // 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(); - 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(); + 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(uidInputs), + MTP_vector(peerInputs), MTP_vector(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();