From db7b61a77b8f0d76a3af2ef72ba81764fc9e91d9 Mon Sep 17 00:00:00 2001 From: John Preston Date: Wed, 17 Mar 2021 20:05:18 +0400 Subject: [PATCH] Rewrite voice chat members list management. --- .../SourceFiles/calls/calls_group_call.cpp | 4 +- .../SourceFiles/calls/calls_group_members.cpp | 52 +--- .../SourceFiles/calls/calls_group_panel.cpp | 4 +- Telegram/SourceFiles/calls/calls_instance.cpp | 56 ++-- Telegram/SourceFiles/calls/calls_instance.h | 11 +- Telegram/SourceFiles/data/data_group_call.cpp | 294 +++++++++++------- Telegram/SourceFiles/data/data_group_call.h | 19 +- 7 files changed, 252 insertions(+), 188 deletions(-) diff --git a/Telegram/SourceFiles/calls/calls_group_call.cpp b/Telegram/SourceFiles/calls/calls_group_call.cpp index d2fd97e7e..a2a2f4586 100644 --- a/Telegram/SourceFiles/calls/calls_group_call.cpp +++ b/Telegram/SourceFiles/calls/calls_group_call.cpp @@ -543,7 +543,7 @@ void GroupCall::applyMeInCallLocally() { | Flag::f_volume_by_admin // Self volume can only be set by admin. | ((muted() != MuteState::Active) ? Flag::f_muted : Flag(0)) | (raisedHandRating > 0 ? Flag::f_raise_hand_rating : Flag(0)); - call->applyUpdateChecked( + call->applyLocalUpdate( MTP_updateGroupCallParticipants( inputCall(), MTP_vector( @@ -588,7 +588,7 @@ void GroupCall::applyParticipantLocally( | (participant->raisedHandRating ? Flag::f_raise_hand_rating : Flag(0)); - _peer->groupCall()->applyUpdateChecked( + _peer->groupCall()->applyLocalUpdate( MTP_updateGroupCallParticipants( inputCall(), MTP_vector( diff --git a/Telegram/SourceFiles/calls/calls_group_members.cpp b/Telegram/SourceFiles/calls/calls_group_members.cpp index c7df6ec7e..ac779deca 100644 --- a/Telegram/SourceFiles/calls/calls_group_members.cpp +++ b/Telegram/SourceFiles/calls/calls_group_members.cpp @@ -354,8 +354,6 @@ private: rpl::event_stream _changeVolumeRequests; rpl::event_stream> _kickParticipantRequests; rpl::variable _fullCount = 1; - rpl::variable _fullCountMin = 0; - rpl::variable _fullCountMax = std::numeric_limits::max(); not_null _menuParent; base::unique_qptr _menu; @@ -954,19 +952,11 @@ void MembersController::setupListChangeViewers(not_null call) { 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); @@ -976,13 +966,7 @@ void MembersController::subscribeToChanges(not_null real) { _realCallRawValue = real; _realId = real->id(); - _fullCount = rpl::combine( - real->fullCountValue(), - _fullCountMin.value(), - _fullCountMax.value() - ) | rpl::map([](int value, int min, int max) { - return std::max(std::clamp(value, min, max), 1); - }); + _fullCount = real->fullCountValue(); real->participantsSliceAdded( ) | rpl::start_with_next([=] { @@ -1003,9 +987,6 @@ void MembersController::subscribeToChanges(not_null real) { if (isMe(participantPeer)) { updateRow(row, nullptr); } else { - if (const auto min = _fullCountMin.current()) { - _fullCountMin = min - 1; - } removeRow(row); delegate()->peerListRefreshRows(); } @@ -1044,11 +1025,9 @@ void MembersController::updateRow( const std::optional &was, const Data::GroupCall::Participant &now) { auto reorderIfInvitedBeforeIndex = 0; - auto countChange = 0; if (const auto row = findRow(now.peer)) { if (row->state() == Row::State::Invited) { reorderIfInvitedBeforeIndex = row->absoluteIndex(); - countChange = 1; } updateRow(row, &now); if ((now.speaking && (!was || !was->speaking)) @@ -1064,7 +1043,6 @@ void MembersController::updateRow( delegate()->peerListAppendRow(std::move(row)); } delegate()->peerListRefreshRows(); - countChange = 1; } static constexpr auto kInvited = Row::State::Invited; const auto reorder = [&] { @@ -1081,13 +1059,6 @@ void MembersController::updateRow( return static_cast(row).state() != kInvited; }); } - if (countChange) { - const auto fullCountMin = _fullCountMin.current() + countChange; - if (_fullCountMax.current() < fullCountMin) { - _fullCountMax = fullCountMin; - } - _fullCountMin = fullCountMin; - } } bool MembersController::allRowsAboveAreSpeaking(not_null row) const { @@ -1206,7 +1177,7 @@ void MembersController::checkRowPosition(not_null row) { }; delegate()->peerListSortRows(_peer->canManageGroupCall() ? makeComparator(projForAdmin) - : makeComparator(projForAdmin)); + : makeComparator(projForOther)); } void MembersController::updateRow( @@ -1243,11 +1214,6 @@ void MembersController::updateRow( _soundingAnimation.stop(); } - if (!participant && wasInChat) { - if (const auto min = _fullCountMin.current()) { - _fullCountMin = min - 1; - } - } delegate()->peerListUpdateRow(row); } @@ -1293,7 +1259,6 @@ void MembersController::prepare() { ; real && call && real->id() == call->id()) { prepareRows(real); } else if (auto row = createRowForMe()) { - _fullCountMin = (row->state() == Row::State::Invited) ? 0 : 1; delegate()->peerListAppendRow(std::move(row)); delegate()->peerListRefreshRows(); } @@ -1314,7 +1279,6 @@ void MembersController::prepareRows(not_null real) { auto foundMe = false; auto changed = false; const auto &participants = real->participants(); - auto fullCountMin = 0; auto count = delegate()->peerListFullRowsCount(); for (auto i = 0; i != count;) { auto row = delegate()->peerListRowAt(i); @@ -1329,7 +1293,6 @@ void MembersController::prepareRows(not_null real) { participantPeer, &Data::GroupCall::Participant::peer); if (contains) { - ++fullCountMin; ++i; } else { changed = true; @@ -1348,9 +1311,6 @@ void MembersController::prepareRows(not_null real) { ? createRow(*i) : createRowForMe(); if (row) { - if (row->state() != Row::State::Invited) { - ++fullCountMin; - } changed = true; delegate()->peerListAppendRow(std::move(row)); } @@ -1358,20 +1318,12 @@ void MembersController::prepareRows(not_null real) { } for (const auto &participant : participants) { if (auto row = createRow(participant)) { - ++fullCountMin; changed = true; delegate()->peerListAppendRow(std::move(row)); } } if (changed) { delegate()->peerListRefreshRows(); - if (_fullCountMax.current() < fullCountMin) { - _fullCountMax = fullCountMin; - } - _fullCountMin = fullCountMin; - if (real->participantsLoaded()) { - _fullCountMax = fullCountMin; - } } } diff --git a/Telegram/SourceFiles/calls/calls_group_panel.cpp b/Telegram/SourceFiles/calls/calls_group_panel.cpp index d50a55cfc..bd8e5fd95 100644 --- a/Telegram/SourceFiles/calls/calls_group_panel.cpp +++ b/Telegram/SourceFiles/calls/calls_group_panel.cpp @@ -1132,7 +1132,9 @@ void Panel::refreshTitle() { widget(), tr::lng_group_call_members( lt_count_decimal, - _members->fullCountValue() | tr::to_count()), + _members->fullCountValue() | rpl::map([](int value) { + return (value > 0) ? float64(value) : 1.; + })), st::groupCallSubtitleLabel); _subtitle->show(); _subtitle->setAttribute(Qt::WA_TransparentForMouseEvents); diff --git a/Telegram/SourceFiles/calls/calls_instance.cpp b/Telegram/SourceFiles/calls/calls_instance.cpp index cd3bbee10..40ba895e3 100644 --- a/Telegram/SourceFiles/calls/calls_instance.cpp +++ b/Telegram/SourceFiles/calls/calls_instance.cpp @@ -323,9 +323,9 @@ void Instance::handleUpdate( }, [&](const MTPDupdatePhoneCallSignalingData &data) { handleSignalingData(session, data); }, [&](const MTPDupdateGroupCall &data) { - handleGroupCallUpdate(session, data.vcall()); + handleGroupCallUpdate(session, update); }, [&](const MTPDupdateGroupCallParticipants &data) { - handleGroupCallUpdate(session, data); + handleGroupCallUpdate(session, update); }, [](const auto &) { Unexpected("Update type in Calls::Instance::handleUpdate."); }); @@ -410,33 +410,45 @@ void Instance::handleCallUpdate( void Instance::handleGroupCallUpdate( not_null session, - const MTPGroupCall &call) { - const auto callId = call.match([](const auto &data) { - return data.vid().v; + const MTPUpdate &update) { + const auto callId = update.match([](const MTPDupdateGroupCall &data) { + return data.vcall().match([](const auto &data) { + return data.vid().v; + }); + }, [](const MTPDupdateGroupCallParticipants &data) { + return data.vcall().match([&](const MTPDinputGroupCall &data) { + return data.vid().v; + }); + }, [](const auto &) -> uint64 { + Unexpected("Type in Instance::handleGroupCallUpdate."); }); if (const auto existing = session->data().groupCall(callId)) { - existing->applyUpdate(call); - } - if (_currentGroupCall - && (&_currentGroupCall->peer()->session() == session)) { - _currentGroupCall->handleUpdate(call); + existing->enqueueUpdate(update); + } else { + applyGroupCallUpdateChecked(session, update); } } -void Instance::handleGroupCallUpdate( +void Instance::applyGroupCallUpdateChecked( not_null session, - const MTPDupdateGroupCallParticipants &update) { - const auto callId = update.vcall().match([](const auto &data) { - return data.vid().v; + const MTPUpdate &update) { + if (!_currentGroupCall + || (&_currentGroupCall->peer()->session() != session)) { + return; + } + + update.match([&](const MTPDupdateGroupCall &data) { + _currentGroupCall->handleUpdate(data.vcall()); + }, [&](const MTPDupdateGroupCallParticipants &data) { + const auto callId = data.vcall().match([](const auto &data) { + return data.vid().v; + }); + if (_currentGroupCall->id() == callId) { + _currentGroupCall->handleUpdate(data); + } + }, [](const auto &) { + Unexpected("Type in Instance::applyGroupCallUpdateChecked."); }); - if (const auto existing = session->data().groupCall(callId)) { - existing->applyUpdate(update); - } - if (_currentGroupCall - && (&_currentGroupCall->peer()->session() == session) - && (_currentGroupCall->id() == callId)) { - _currentGroupCall->handleUpdate(update); - } } void Instance::handleSignalingData( diff --git a/Telegram/SourceFiles/calls/calls_instance.h b/Telegram/SourceFiles/calls/calls_instance.h index fa3ff5f18..96034fcaf 100644 --- a/Telegram/SourceFiles/calls/calls_instance.h +++ b/Telegram/SourceFiles/calls/calls_instance.h @@ -50,6 +50,12 @@ public: void handleUpdate( not_null session, const MTPUpdate &update); + + // Called by Data::GroupCall when it is appropriate by the 'version'. + void applyGroupCallUpdateChecked( + not_null session, + const MTPUpdate &update); + void showInfoPanel(not_null call); void showInfoPanel(not_null call); [[nodiscard]] Call *currentCall() const; @@ -130,10 +136,7 @@ private: const MTPDupdatePhoneCallSignalingData &data); void handleGroupCallUpdate( not_null session, - const MTPGroupCall &call); - void handleGroupCallUpdate( - not_null session, - const MTPDupdateGroupCallParticipants &update); + const MTPUpdate &update); DhConfig _dhConfig; diff --git a/Telegram/SourceFiles/data/data_group_call.cpp b/Telegram/SourceFiles/data/data_group_call.cpp index d72875d48..835c825ac 100644 --- a/Telegram/SourceFiles/data/data_group_call.cpp +++ b/Telegram/SourceFiles/data/data_group_call.cpp @@ -22,9 +22,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace Data { namespace { -constexpr auto kRequestPerPage = 30; +constexpr auto kRequestPerPage = 50; constexpr auto kSpeakingAfterActive = crl::time(6000); constexpr auto kActiveAfterJoined = crl::time(1000); +constexpr auto kWaitForUpdatesTimeout = 3 * crl::time(1000); } // namespace @@ -35,6 +36,7 @@ GroupCall::GroupCall( : _id(id) , _accessHash(accessHash) , _peer(peer) +, _reloadByQueuedUpdatesTimer([=] { reload(); }) , _speakingByActiveFinishTimer([=] { checkFinishSpeakingByActive(); }) { } @@ -71,10 +73,7 @@ auto GroupCall::participants() const void GroupCall::requestParticipants() { if (_participantsRequestId || _reloadRequestId) { return; - } else if (_participants.size() >= _fullCount.current() && _allReceived) { - return; - } else if (_allReceived) { - reload(); + } else if (_allParticipantsLoaded) { return; } _participantsRequestId = api().request(MTPphone_GetGroupParticipants( @@ -91,26 +90,29 @@ void GroupCall::requestParticipants() { applyParticipantsSlice( data.vparticipants().v, ApplySliceSource::SliceLoaded); - _fullCount = data.vcount().v; - if (!_allReceived - && (data.vparticipants().v.size() < kRequestPerPage)) { - _allReceived = true; - } - if (_allReceived) { - _fullCount = _participants.size(); + setServerParticipantsCount(data.vcount().v); + if (data.vparticipants().v.isEmpty()) { + _allParticipantsLoaded = true; } + computeParticipantsCount(); + _participantsSliceAdded.fire({}); + _participantsRequestId = 0; + processQueuedUpdates(); }); - _participantsSliceAdded.fire({}); - _participantsRequestId = 0; - changePeerEmptyCallFlag(); }).fail([=](const MTP::Error &error) { - _fullCount = _participants.size(); - _allReceived = true; + setServerParticipantsCount(_participants.size()); + _allParticipantsLoaded = true; + computeParticipantsCount(); _participantsRequestId = 0; - changePeerEmptyCallFlag(); + processQueuedUpdates(); }).send(); } +void GroupCall::setServerParticipantsCount(int count) { + _serverParticipantsCount = count; + changePeerEmptyCallFlag(); +} + void GroupCall::changePeerEmptyCallFlag() { const auto chat = _peer->asChat(); const auto channel = _peer->asChannel(); @@ -118,7 +120,7 @@ void GroupCall::changePeerEmptyCallFlag() { constexpr auto channelFlag = MTPDchannel::Flag::f_call_not_empty; if (_peer->groupCall() != this) { return; - } else if (fullCount() > 0) { + } else if (_serverParticipantsCount > 0) { if (chat && !(chat->flags() & chatFlag)) { chat->addFlags(chatFlag); chat->session().changes().peerUpdated( @@ -152,7 +154,7 @@ rpl::producer GroupCall::fullCountValue() const { } bool GroupCall::participantsLoaded() const { - return _allReceived; + return _allParticipantsLoaded; } PeerData *GroupCall::participantPeerBySsrc(uint32 ssrc) const { @@ -169,46 +171,52 @@ auto GroupCall::participantUpdated() const return _participantUpdates.events(); } -void GroupCall::applyUpdate(const MTPGroupCall &update) { - applyCall(update, false); +void GroupCall::enqueueUpdate(const MTPUpdate &update) { + update.match([&](const MTPDupdateGroupCall &updateData) { + updateData.vcall().match([&](const MTPDgroupCall &data) { + const auto version = data.vversion().v; + if (!_version || _version == version) { + applyUpdate(update); + } else if (_version < version) { + _queuedUpdates.emplace(std::pair{ version, false }, update); + } + }, [&](const MTPDgroupCallDiscarded &data) { + applyUpdate(update); + }); + }, [&](const MTPDupdateGroupCallParticipants &updateData) { + const auto version = updateData.vversion().v; + const auto proj = [](const MTPGroupCallParticipant &data) { + return data.match([&](const MTPDgroupCallParticipant &data) { + return data.is_versioned(); + }); + }; + const auto increment = ranges::contains( + updateData.vparticipants().v, + true, + proj); + const auto required = increment ? (version - 1) : version; + if (_version == required) { + applyUpdate(update); + } else if (_version < required) { + _queuedUpdates.emplace(std::pair{ version, increment }, update); + } + }, [](const auto &) { + Unexpected("Type in GroupCall::enqueueUpdate."); + }); + processQueuedUpdates(); } -void GroupCall::applyCall(const MTPGroupCall &call, bool force) { - call.match([&](const MTPDgroupCall &data) { - if (!_version) { - _version = data.vversion().v; - } - const auto title = qs(data.vtitle().value_or_empty()); - const auto recordDate = data.vrecord_start_date().value_or_empty(); - const auto changed = (_joinMuted != data.is_join_muted()) - || (_fullCount.current() != data.vparticipants_count().v) - || (_canChangeJoinMuted != data.is_can_change_join_muted()) - || (_title.current() != title) - || (_recordStartDate.current() != recordDate); - if (!force && !changed) { - return; - } else if (!force && _version > data.vversion().v) { - reload(); - return; - } - _joinMuted = data.is_join_muted(); - _canChangeJoinMuted = data.is_can_change_join_muted(); - _fullCount = data.vparticipants_count().v; - _title = title; - _recordStartDate = recordDate; - changePeerEmptyCallFlag(); - }, [&](const MTPDgroupCallDiscarded &data) { - const auto id = _id; - const auto peer = _peer; - crl::on_main(&peer->session(), [=] { - if (peer->groupCall() && peer->groupCall()->id() == id) { - if (const auto chat = peer->asChat()) { - chat->clearGroupCall(); - } else if (const auto channel = peer->asChannel()) { - channel->clearGroupCall(); - } +void GroupCall::discard() { + const auto id = _id; + const auto peer = _peer; + crl::on_main(&peer->session(), [=] { + if (peer->groupCall() && peer->groupCall()->id() == id) { + if (const auto chat = peer->asChat()) { + chat->clearGroupCall(); + } else if (const auto channel = peer->asChannel()) { + channel->clearGroupCall(); } - }); + } }); } @@ -216,16 +224,125 @@ void GroupCall::processFullCall(const MTPphone_GroupCall &call) { call.match([&](const MTPDphone_groupCall &data) { _peer->owner().processUsers(data.vusers()); _peer->owner().processChats(data.vchats()); - _participants.clear(); - _speakingByActiveFinishes.clear(); - _participantPeerBySsrc.clear(); + const auto &participants = data.vparticipants().v; + const auto nextOffset = qs(data.vparticipants_next_offset()); + data.vcall().match([&](const MTPDgroupCall &data) { + if (data.vversion().v == _version + && data.vparticipants_count().v == _serverParticipantsCount + && (_serverParticipantsCount >= _participants.size()) + && (!_allParticipantsLoaded + || _serverParticipantsCount == _participants.size())) { + return; + } + _participants.clear(); + _speakingByActiveFinishes.clear(); + _participantPeerBySsrc.clear(); + _allParticipantsLoaded = false; + + applyParticipantsSlice( + participants, + ApplySliceSource::SliceLoaded); + _nextOffset = nextOffset; + + applyCallFields(data); + + _participantsSliceAdded.fire({}); + }, [&](const MTPDgroupCallDiscarded &data) { + discard(); + }); + processQueuedUpdates(); + }); +} + +void GroupCall::applyCallFields(const MTPDgroupCall &data) { + _version = data.vversion().v; + if (!_version) { + LOG(("API Error: Got zero version in groupCall.")); + _version = 1; + } + _joinMuted = data.is_join_muted(); + _canChangeJoinMuted = data.is_can_change_join_muted(); + setServerParticipantsCount(data.vparticipants_count().v); + changePeerEmptyCallFlag(); + _title = qs(data.vtitle().value_or_empty()); + _recordStartDate = data.vrecord_start_date().value_or_empty(); + _allParticipantsLoaded + = (_serverParticipantsCount == _participants.size()); + computeParticipantsCount(); + processQueuedUpdates(); +} + +void GroupCall::applyLocalUpdate( + const MTPDupdateGroupCallParticipants &update) { + applyParticipantsSlice( + update.vparticipants().v, + ApplySliceSource::UpdateReceived); +} + +void GroupCall::applyUpdate(const MTPUpdate &update) { + update.match([&](const MTPDupdateGroupCall &data) { + data.vcall().match([&](const MTPDgroupCall &data) { + applyCallFields(data); + }, [&](const MTPDgroupCallDiscarded &data) { + discard(); + }); + }, [&](const MTPDupdateGroupCallParticipants &data) { + _version = data.vversion().v; + if (!_version) { + LOG(("API Error: " + "Got zero version in updateGroupCallParticipants.")); + _version = 1; + } applyParticipantsSlice( data.vparticipants().v, - ApplySliceSource::SliceLoaded); - applyCall(data.vcall(), true); - _allReceived = (_fullCount.current() == _participants.size()); - _participantsSliceAdded.fire({}); + ApplySliceSource::UpdateReceived); + }, [](const auto &) { + Unexpected("Type in GroupCall::processQueuedUpdates."); }); + Core::App().calls().applyGroupCallUpdateChecked( + &_peer->session(), + update); +} + +void GroupCall::processQueuedUpdates() { + if (!_version) { + return; + } + + const auto size = _queuedUpdates.size(); + while (!_queuedUpdates.empty()) { + const auto &entry = _queuedUpdates.front(); + const auto version = entry.first.first; + const auto versionIncremented = entry.first.second; + if ((version < _version) + || (version == _version && versionIncremented)) { + _queuedUpdates.erase(_queuedUpdates.begin()); + } else if (version == _version + || (version == _version + 1 && versionIncremented)) { + const auto update = entry.second; + _queuedUpdates.erase(_queuedUpdates.begin()); + applyUpdate(update); + } else { + break; + } + } + if (_queuedUpdates.empty()) { + const auto server = _serverParticipantsCount; + const auto local = int(_participants.size()); + if (server < local + || (_allParticipantsLoaded && server > local)) { + reload(); + } + } else if (_queuedUpdates.size() != size + || !_reloadByQueuedUpdatesTimer.isActive()) { + _reloadByQueuedUpdatesTimer.callOnce(kWaitForUpdatesTimeout); + } +} + +void GroupCall::computeParticipantsCount() { + _fullCount = _allParticipantsLoaded + ? int(_participants.size()) + : std::max(int(_participants.size()), _serverParticipantsCount); } void GroupCall::reload() { @@ -235,6 +352,10 @@ void GroupCall::reload() { api().request(_participantsRequestId).cancel(); _participantsRequestId = 0; } + + _queuedUpdates.clear(); + _reloadByQueuedUpdatesTimer.cancel(); + _reloadRequestId = api().request( MTPphone_GetGroupCall(input()) ).done([=](const MTPphone_GroupCall &result) { @@ -252,7 +373,6 @@ void GroupCall::applyParticipantsSlice( const auto now = base::unixtime::now(); const auto speakingAfterActive = TimeId(kSpeakingAfterActive / 1000); - auto changedCount = _fullCount.current(); for (const auto &participant : list) { participant.match([&](const MTPDgroupCallParticipant &data) { const auto participantPeerId = peerFromMTP(data.vpeer()); @@ -274,8 +394,8 @@ void GroupCall::applyParticipantsSlice( _participantUpdates.fire(std::move(update)); } } - if (changedCount > _participants.size()) { - --changedCount; + if (_serverParticipantsCount > 0) { + --_serverParticipantsCount; } return; } @@ -338,7 +458,7 @@ void GroupCall::applyParticipantsSlice( *i = value; } if (data.is_just_joined()) { - ++changedCount; + ++_serverParticipantsCount; } if (sliceSource != ApplySliceSource::SliceLoaded) { _participantUpdates.fire({ @@ -349,8 +469,8 @@ void GroupCall::applyParticipantsSlice( }); } if (sliceSource == ApplySliceSource::UpdateReceived) { - _fullCount = changedCount; changePeerEmptyCallFlag(); + computeParticipantsCount(); } } @@ -542,6 +662,7 @@ void GroupCall::requestUnknownParticipants() { ).done([=](const MTPphone_GroupParticipants &result) { result.match([&](const MTPDphone_groupParticipants &data) { _peer->owner().processUsers(data.vusers()); + _peer->owner().processChats(data.vchats()); applyParticipantsSlice( data.vparticipants().v, ApplySliceSource::UnknownLoaded); @@ -605,41 +726,6 @@ bool GroupCall::inCall() const { && (current->state() == Calls::GroupCall::State::Joined); } -void GroupCall::applyUpdate(const MTPDupdateGroupCallParticipants &update) { - const auto version = update.vversion().v; - const auto applyUpdate = [&] { - if (version < _version) { - return false; - } - auto versionShouldIncrement = false; - for (const auto &participant : update.vparticipants().v) { - const auto versioned = participant.match([&]( - const MTPDgroupCallParticipant &data) { - return data.is_versioned(); - }); - if (versioned) { - versionShouldIncrement = true; - break; - } - } - return versionShouldIncrement - ? (version == _version + 1) - : (version == _version); - }(); - if (!applyUpdate) { - return; - } - _version = version; - applyUpdateChecked(update); -} - -void GroupCall::applyUpdateChecked( - const MTPDupdateGroupCallParticipants &update) { - applyParticipantsSlice( - update.vparticipants().v, - ApplySliceSource::UpdateReceived); -} - void GroupCall::setJoinMutedLocally(bool muted) { _joinMuted = muted; } diff --git a/Telegram/SourceFiles/data/data_group_call.h b/Telegram/SourceFiles/data/data_group_call.h index 36e722a3b..0219aa99e 100644 --- a/Telegram/SourceFiles/data/data_group_call.h +++ b/Telegram/SourceFiles/data/data_group_call.h @@ -82,10 +82,10 @@ public: [[nodiscard]] rpl::producer<> participantsSliceAdded(); [[nodiscard]] rpl::producer participantUpdated() const; - void applyUpdate(const MTPGroupCall &update); - void applyUpdate(const MTPDupdateGroupCallParticipants &update); - void applyUpdateChecked( + void enqueueUpdate(const MTPUpdate &update); + void applyLocalUpdate( const MTPDupdateGroupCallParticipants &update); + void applyLastSpoke(uint32 ssrc, LastSpokeTimes when, crl::time now); void applyActiveUpdate( PeerId participantPeerId, @@ -113,14 +113,19 @@ private: }; [[nodiscard]] ApiWrap &api() const; + void discard(); [[nodiscard]] bool inCall() const; - void applyCall(const MTPGroupCall &call, bool force); void applyParticipantsSlice( const QVector &list, ApplySliceSource sliceSource); void requestUnknownParticipants(); void changePeerEmptyCallFlag(); void checkFinishSpeakingByActive(); + void applyCallFields(const MTPDgroupCall &data); + void applyUpdate(const MTPUpdate &update); + void setServerParticipantsCount(int count); + void computeParticipantsCount(); + void processQueuedUpdates(); const uint64 _id = 0; const uint64 _accessHash = 0; @@ -131,11 +136,15 @@ private: mtpRequestId _reloadRequestId = 0; rpl::variable _title; + base::flat_map, MTPUpdate> _queuedUpdates; + base::Timer _reloadByQueuedUpdatesTimer; + std::vector _participants; base::flat_map> _participantPeerBySsrc; base::flat_map, crl::time> _speakingByActiveFinishes; base::Timer _speakingByActiveFinishTimer; QString _nextOffset; + int _serverParticipantsCount = 0; rpl::variable _fullCount = 0; rpl::variable _recordStartDate = 0; @@ -148,7 +157,7 @@ private: bool _joinMuted = false; bool _canChangeJoinMuted = true; - bool _allReceived = false; + bool _allParticipantsLoaded = false; };