Rewrite voice chat members list management.
This commit is contained in:
parent
d392633b90
commit
db7b61a77b
7 changed files with 252 additions and 188 deletions
|
@ -543,7 +543,7 @@ void GroupCall::applyMeInCallLocally() {
|
||||||
| Flag::f_volume_by_admin // Self volume can only be set by admin.
|
| Flag::f_volume_by_admin // Self volume can only be set by admin.
|
||||||
| ((muted() != MuteState::Active) ? Flag::f_muted : Flag(0))
|
| ((muted() != MuteState::Active) ? Flag::f_muted : Flag(0))
|
||||||
| (raisedHandRating > 0 ? Flag::f_raise_hand_rating : Flag(0));
|
| (raisedHandRating > 0 ? Flag::f_raise_hand_rating : Flag(0));
|
||||||
call->applyUpdateChecked(
|
call->applyLocalUpdate(
|
||||||
MTP_updateGroupCallParticipants(
|
MTP_updateGroupCallParticipants(
|
||||||
inputCall(),
|
inputCall(),
|
||||||
MTP_vector<MTPGroupCallParticipant>(
|
MTP_vector<MTPGroupCallParticipant>(
|
||||||
|
@ -588,7 +588,7 @@ void GroupCall::applyParticipantLocally(
|
||||||
| (participant->raisedHandRating
|
| (participant->raisedHandRating
|
||||||
? Flag::f_raise_hand_rating
|
? Flag::f_raise_hand_rating
|
||||||
: Flag(0));
|
: Flag(0));
|
||||||
_peer->groupCall()->applyUpdateChecked(
|
_peer->groupCall()->applyLocalUpdate(
|
||||||
MTP_updateGroupCallParticipants(
|
MTP_updateGroupCallParticipants(
|
||||||
inputCall(),
|
inputCall(),
|
||||||
MTP_vector<MTPGroupCallParticipant>(
|
MTP_vector<MTPGroupCallParticipant>(
|
||||||
|
|
|
@ -354,8 +354,6 @@ private:
|
||||||
rpl::event_stream<VolumeRequest> _changeVolumeRequests;
|
rpl::event_stream<VolumeRequest> _changeVolumeRequests;
|
||||||
rpl::event_stream<not_null<PeerData*>> _kickParticipantRequests;
|
rpl::event_stream<not_null<PeerData*>> _kickParticipantRequests;
|
||||||
rpl::variable<int> _fullCount = 1;
|
rpl::variable<int> _fullCount = 1;
|
||||||
rpl::variable<int> _fullCountMin = 0;
|
|
||||||
rpl::variable<int> _fullCountMax = std::numeric_limits<int>::max();
|
|
||||||
|
|
||||||
not_null<QWidget*> _menuParent;
|
not_null<QWidget*> _menuParent;
|
||||||
base::unique_qptr<Ui::PopupMenu> _menu;
|
base::unique_qptr<Ui::PopupMenu> _menu;
|
||||||
|
@ -954,19 +952,11 @@ void MembersController::setupListChangeViewers(not_null<GroupCall*> call) {
|
||||||
delegate()->peerListRefreshRows();
|
delegate()->peerListRefreshRows();
|
||||||
});
|
});
|
||||||
if (const auto row = findRow(event.wasJoinAs)) {
|
if (const auto row = findRow(event.wasJoinAs)) {
|
||||||
if (row->state() != Row::State::Invited) {
|
|
||||||
if (const auto min = _fullCountMin.current()) {
|
|
||||||
_fullCountMin = min - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
removeRow(row);
|
removeRow(row);
|
||||||
}
|
}
|
||||||
if (findRow(event.nowJoinAs)) {
|
if (findRow(event.nowJoinAs)) {
|
||||||
return;
|
return;
|
||||||
} else if (auto row = createRowForMe()) {
|
} else if (auto row = createRowForMe()) {
|
||||||
if (row->state() != Row::State::Invited) {
|
|
||||||
_fullCountMin = _fullCountMin.current() + 1;
|
|
||||||
}
|
|
||||||
delegate()->peerListAppendRow(std::move(row));
|
delegate()->peerListAppendRow(std::move(row));
|
||||||
}
|
}
|
||||||
}, _lifetime);
|
}, _lifetime);
|
||||||
|
@ -976,13 +966,7 @@ void MembersController::subscribeToChanges(not_null<Data::GroupCall*> real) {
|
||||||
_realCallRawValue = real;
|
_realCallRawValue = real;
|
||||||
_realId = real->id();
|
_realId = real->id();
|
||||||
|
|
||||||
_fullCount = rpl::combine(
|
_fullCount = real->fullCountValue();
|
||||||
real->fullCountValue(),
|
|
||||||
_fullCountMin.value(),
|
|
||||||
_fullCountMax.value()
|
|
||||||
) | rpl::map([](int value, int min, int max) {
|
|
||||||
return std::max(std::clamp(value, min, max), 1);
|
|
||||||
});
|
|
||||||
|
|
||||||
real->participantsSliceAdded(
|
real->participantsSliceAdded(
|
||||||
) | rpl::start_with_next([=] {
|
) | rpl::start_with_next([=] {
|
||||||
|
@ -1003,9 +987,6 @@ void MembersController::subscribeToChanges(not_null<Data::GroupCall*> real) {
|
||||||
if (isMe(participantPeer)) {
|
if (isMe(participantPeer)) {
|
||||||
updateRow(row, nullptr);
|
updateRow(row, nullptr);
|
||||||
} else {
|
} else {
|
||||||
if (const auto min = _fullCountMin.current()) {
|
|
||||||
_fullCountMin = min - 1;
|
|
||||||
}
|
|
||||||
removeRow(row);
|
removeRow(row);
|
||||||
delegate()->peerListRefreshRows();
|
delegate()->peerListRefreshRows();
|
||||||
}
|
}
|
||||||
|
@ -1044,11 +1025,9 @@ void MembersController::updateRow(
|
||||||
const std::optional<Data::GroupCall::Participant> &was,
|
const std::optional<Data::GroupCall::Participant> &was,
|
||||||
const Data::GroupCall::Participant &now) {
|
const Data::GroupCall::Participant &now) {
|
||||||
auto reorderIfInvitedBeforeIndex = 0;
|
auto reorderIfInvitedBeforeIndex = 0;
|
||||||
auto countChange = 0;
|
|
||||||
if (const auto row = findRow(now.peer)) {
|
if (const auto row = findRow(now.peer)) {
|
||||||
if (row->state() == Row::State::Invited) {
|
if (row->state() == Row::State::Invited) {
|
||||||
reorderIfInvitedBeforeIndex = row->absoluteIndex();
|
reorderIfInvitedBeforeIndex = row->absoluteIndex();
|
||||||
countChange = 1;
|
|
||||||
}
|
}
|
||||||
updateRow(row, &now);
|
updateRow(row, &now);
|
||||||
if ((now.speaking && (!was || !was->speaking))
|
if ((now.speaking && (!was || !was->speaking))
|
||||||
|
@ -1064,7 +1043,6 @@ void MembersController::updateRow(
|
||||||
delegate()->peerListAppendRow(std::move(row));
|
delegate()->peerListAppendRow(std::move(row));
|
||||||
}
|
}
|
||||||
delegate()->peerListRefreshRows();
|
delegate()->peerListRefreshRows();
|
||||||
countChange = 1;
|
|
||||||
}
|
}
|
||||||
static constexpr auto kInvited = Row::State::Invited;
|
static constexpr auto kInvited = Row::State::Invited;
|
||||||
const auto reorder = [&] {
|
const auto reorder = [&] {
|
||||||
|
@ -1081,13 +1059,6 @@ void MembersController::updateRow(
|
||||||
return static_cast<const Row&>(row).state() != kInvited;
|
return static_cast<const Row&>(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*> row) const {
|
bool MembersController::allRowsAboveAreSpeaking(not_null<Row*> row) const {
|
||||||
|
@ -1206,7 +1177,7 @@ void MembersController::checkRowPosition(not_null<Row*> row) {
|
||||||
};
|
};
|
||||||
delegate()->peerListSortRows(_peer->canManageGroupCall()
|
delegate()->peerListSortRows(_peer->canManageGroupCall()
|
||||||
? makeComparator(projForAdmin)
|
? makeComparator(projForAdmin)
|
||||||
: makeComparator(projForAdmin));
|
: makeComparator(projForOther));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MembersController::updateRow(
|
void MembersController::updateRow(
|
||||||
|
@ -1243,11 +1214,6 @@ void MembersController::updateRow(
|
||||||
_soundingAnimation.stop();
|
_soundingAnimation.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!participant && wasInChat) {
|
|
||||||
if (const auto min = _fullCountMin.current()) {
|
|
||||||
_fullCountMin = min - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delegate()->peerListUpdateRow(row);
|
delegate()->peerListUpdateRow(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1293,7 +1259,6 @@ void MembersController::prepare() {
|
||||||
; real && call && real->id() == call->id()) {
|
; real && call && real->id() == call->id()) {
|
||||||
prepareRows(real);
|
prepareRows(real);
|
||||||
} else if (auto row = createRowForMe()) {
|
} else if (auto row = createRowForMe()) {
|
||||||
_fullCountMin = (row->state() == Row::State::Invited) ? 0 : 1;
|
|
||||||
delegate()->peerListAppendRow(std::move(row));
|
delegate()->peerListAppendRow(std::move(row));
|
||||||
delegate()->peerListRefreshRows();
|
delegate()->peerListRefreshRows();
|
||||||
}
|
}
|
||||||
|
@ -1314,7 +1279,6 @@ void MembersController::prepareRows(not_null<Data::GroupCall*> real) {
|
||||||
auto foundMe = false;
|
auto foundMe = false;
|
||||||
auto changed = false;
|
auto changed = false;
|
||||||
const auto &participants = real->participants();
|
const auto &participants = real->participants();
|
||||||
auto fullCountMin = 0;
|
|
||||||
auto count = delegate()->peerListFullRowsCount();
|
auto count = delegate()->peerListFullRowsCount();
|
||||||
for (auto i = 0; i != count;) {
|
for (auto i = 0; i != count;) {
|
||||||
auto row = delegate()->peerListRowAt(i);
|
auto row = delegate()->peerListRowAt(i);
|
||||||
|
@ -1329,7 +1293,6 @@ void MembersController::prepareRows(not_null<Data::GroupCall*> real) {
|
||||||
participantPeer,
|
participantPeer,
|
||||||
&Data::GroupCall::Participant::peer);
|
&Data::GroupCall::Participant::peer);
|
||||||
if (contains) {
|
if (contains) {
|
||||||
++fullCountMin;
|
|
||||||
++i;
|
++i;
|
||||||
} else {
|
} else {
|
||||||
changed = true;
|
changed = true;
|
||||||
|
@ -1348,9 +1311,6 @@ void MembersController::prepareRows(not_null<Data::GroupCall*> real) {
|
||||||
? createRow(*i)
|
? createRow(*i)
|
||||||
: createRowForMe();
|
: createRowForMe();
|
||||||
if (row) {
|
if (row) {
|
||||||
if (row->state() != Row::State::Invited) {
|
|
||||||
++fullCountMin;
|
|
||||||
}
|
|
||||||
changed = true;
|
changed = true;
|
||||||
delegate()->peerListAppendRow(std::move(row));
|
delegate()->peerListAppendRow(std::move(row));
|
||||||
}
|
}
|
||||||
|
@ -1358,20 +1318,12 @@ void MembersController::prepareRows(not_null<Data::GroupCall*> real) {
|
||||||
}
|
}
|
||||||
for (const auto &participant : participants) {
|
for (const auto &participant : participants) {
|
||||||
if (auto row = createRow(participant)) {
|
if (auto row = createRow(participant)) {
|
||||||
++fullCountMin;
|
|
||||||
changed = true;
|
changed = true;
|
||||||
delegate()->peerListAppendRow(std::move(row));
|
delegate()->peerListAppendRow(std::move(row));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (changed) {
|
if (changed) {
|
||||||
delegate()->peerListRefreshRows();
|
delegate()->peerListRefreshRows();
|
||||||
if (_fullCountMax.current() < fullCountMin) {
|
|
||||||
_fullCountMax = fullCountMin;
|
|
||||||
}
|
|
||||||
_fullCountMin = fullCountMin;
|
|
||||||
if (real->participantsLoaded()) {
|
|
||||||
_fullCountMax = fullCountMin;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1132,7 +1132,9 @@ void Panel::refreshTitle() {
|
||||||
widget(),
|
widget(),
|
||||||
tr::lng_group_call_members(
|
tr::lng_group_call_members(
|
||||||
lt_count_decimal,
|
lt_count_decimal,
|
||||||
_members->fullCountValue() | tr::to_count()),
|
_members->fullCountValue() | rpl::map([](int value) {
|
||||||
|
return (value > 0) ? float64(value) : 1.;
|
||||||
|
})),
|
||||||
st::groupCallSubtitleLabel);
|
st::groupCallSubtitleLabel);
|
||||||
_subtitle->show();
|
_subtitle->show();
|
||||||
_subtitle->setAttribute(Qt::WA_TransparentForMouseEvents);
|
_subtitle->setAttribute(Qt::WA_TransparentForMouseEvents);
|
||||||
|
|
|
@ -323,9 +323,9 @@ void Instance::handleUpdate(
|
||||||
}, [&](const MTPDupdatePhoneCallSignalingData &data) {
|
}, [&](const MTPDupdatePhoneCallSignalingData &data) {
|
||||||
handleSignalingData(session, data);
|
handleSignalingData(session, data);
|
||||||
}, [&](const MTPDupdateGroupCall &data) {
|
}, [&](const MTPDupdateGroupCall &data) {
|
||||||
handleGroupCallUpdate(session, data.vcall());
|
handleGroupCallUpdate(session, update);
|
||||||
}, [&](const MTPDupdateGroupCallParticipants &data) {
|
}, [&](const MTPDupdateGroupCallParticipants &data) {
|
||||||
handleGroupCallUpdate(session, data);
|
handleGroupCallUpdate(session, update);
|
||||||
}, [](const auto &) {
|
}, [](const auto &) {
|
||||||
Unexpected("Update type in Calls::Instance::handleUpdate.");
|
Unexpected("Update type in Calls::Instance::handleUpdate.");
|
||||||
});
|
});
|
||||||
|
@ -410,33 +410,45 @@ void Instance::handleCallUpdate(
|
||||||
|
|
||||||
void Instance::handleGroupCallUpdate(
|
void Instance::handleGroupCallUpdate(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const MTPGroupCall &call) {
|
const MTPUpdate &update) {
|
||||||
const auto callId = call.match([](const auto &data) {
|
const auto callId = update.match([](const MTPDupdateGroupCall &data) {
|
||||||
|
return data.vcall().match([](const auto &data) {
|
||||||
return data.vid().v;
|
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)) {
|
if (const auto existing = session->data().groupCall(callId)) {
|
||||||
existing->applyUpdate(call);
|
existing->enqueueUpdate(update);
|
||||||
}
|
} else {
|
||||||
if (_currentGroupCall
|
applyGroupCallUpdateChecked(session, update);
|
||||||
&& (&_currentGroupCall->peer()->session() == session)) {
|
|
||||||
_currentGroupCall->handleUpdate(call);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Instance::handleGroupCallUpdate(
|
void Instance::applyGroupCallUpdateChecked(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const MTPDupdateGroupCallParticipants &update) {
|
const MTPUpdate &update) {
|
||||||
const auto callId = update.vcall().match([](const auto &data) {
|
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;
|
return data.vid().v;
|
||||||
});
|
});
|
||||||
if (const auto existing = session->data().groupCall(callId)) {
|
if (_currentGroupCall->id() == callId) {
|
||||||
existing->applyUpdate(update);
|
_currentGroupCall->handleUpdate(data);
|
||||||
}
|
|
||||||
if (_currentGroupCall
|
|
||||||
&& (&_currentGroupCall->peer()->session() == session)
|
|
||||||
&& (_currentGroupCall->id() == callId)) {
|
|
||||||
_currentGroupCall->handleUpdate(update);
|
|
||||||
}
|
}
|
||||||
|
}, [](const auto &) {
|
||||||
|
Unexpected("Type in Instance::applyGroupCallUpdateChecked.");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Instance::handleSignalingData(
|
void Instance::handleSignalingData(
|
||||||
|
|
|
@ -50,6 +50,12 @@ public:
|
||||||
void handleUpdate(
|
void handleUpdate(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const MTPUpdate &update);
|
const MTPUpdate &update);
|
||||||
|
|
||||||
|
// Called by Data::GroupCall when it is appropriate by the 'version'.
|
||||||
|
void applyGroupCallUpdateChecked(
|
||||||
|
not_null<Main::Session*> session,
|
||||||
|
const MTPUpdate &update);
|
||||||
|
|
||||||
void showInfoPanel(not_null<Call*> call);
|
void showInfoPanel(not_null<Call*> call);
|
||||||
void showInfoPanel(not_null<GroupCall*> call);
|
void showInfoPanel(not_null<GroupCall*> call);
|
||||||
[[nodiscard]] Call *currentCall() const;
|
[[nodiscard]] Call *currentCall() const;
|
||||||
|
@ -130,10 +136,7 @@ private:
|
||||||
const MTPDupdatePhoneCallSignalingData &data);
|
const MTPDupdatePhoneCallSignalingData &data);
|
||||||
void handleGroupCallUpdate(
|
void handleGroupCallUpdate(
|
||||||
not_null<Main::Session*> session,
|
not_null<Main::Session*> session,
|
||||||
const MTPGroupCall &call);
|
const MTPUpdate &update);
|
||||||
void handleGroupCallUpdate(
|
|
||||||
not_null<Main::Session*> session,
|
|
||||||
const MTPDupdateGroupCallParticipants &update);
|
|
||||||
|
|
||||||
DhConfig _dhConfig;
|
DhConfig _dhConfig;
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
namespace Data {
|
namespace Data {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr auto kRequestPerPage = 30;
|
constexpr auto kRequestPerPage = 50;
|
||||||
constexpr auto kSpeakingAfterActive = crl::time(6000);
|
constexpr auto kSpeakingAfterActive = crl::time(6000);
|
||||||
constexpr auto kActiveAfterJoined = crl::time(1000);
|
constexpr auto kActiveAfterJoined = crl::time(1000);
|
||||||
|
constexpr auto kWaitForUpdatesTimeout = 3 * crl::time(1000);
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
@ -35,6 +36,7 @@ GroupCall::GroupCall(
|
||||||
: _id(id)
|
: _id(id)
|
||||||
, _accessHash(accessHash)
|
, _accessHash(accessHash)
|
||||||
, _peer(peer)
|
, _peer(peer)
|
||||||
|
, _reloadByQueuedUpdatesTimer([=] { reload(); })
|
||||||
, _speakingByActiveFinishTimer([=] { checkFinishSpeakingByActive(); }) {
|
, _speakingByActiveFinishTimer([=] { checkFinishSpeakingByActive(); }) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,10 +73,7 @@ auto GroupCall::participants() const
|
||||||
void GroupCall::requestParticipants() {
|
void GroupCall::requestParticipants() {
|
||||||
if (_participantsRequestId || _reloadRequestId) {
|
if (_participantsRequestId || _reloadRequestId) {
|
||||||
return;
|
return;
|
||||||
} else if (_participants.size() >= _fullCount.current() && _allReceived) {
|
} else if (_allParticipantsLoaded) {
|
||||||
return;
|
|
||||||
} else if (_allReceived) {
|
|
||||||
reload();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_participantsRequestId = api().request(MTPphone_GetGroupParticipants(
|
_participantsRequestId = api().request(MTPphone_GetGroupParticipants(
|
||||||
|
@ -91,26 +90,29 @@ void GroupCall::requestParticipants() {
|
||||||
applyParticipantsSlice(
|
applyParticipantsSlice(
|
||||||
data.vparticipants().v,
|
data.vparticipants().v,
|
||||||
ApplySliceSource::SliceLoaded);
|
ApplySliceSource::SliceLoaded);
|
||||||
_fullCount = data.vcount().v;
|
setServerParticipantsCount(data.vcount().v);
|
||||||
if (!_allReceived
|
if (data.vparticipants().v.isEmpty()) {
|
||||||
&& (data.vparticipants().v.size() < kRequestPerPage)) {
|
_allParticipantsLoaded = true;
|
||||||
_allReceived = true;
|
|
||||||
}
|
}
|
||||||
if (_allReceived) {
|
computeParticipantsCount();
|
||||||
_fullCount = _participants.size();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
_participantsSliceAdded.fire({});
|
_participantsSliceAdded.fire({});
|
||||||
_participantsRequestId = 0;
|
_participantsRequestId = 0;
|
||||||
changePeerEmptyCallFlag();
|
processQueuedUpdates();
|
||||||
|
});
|
||||||
}).fail([=](const MTP::Error &error) {
|
}).fail([=](const MTP::Error &error) {
|
||||||
_fullCount = _participants.size();
|
setServerParticipantsCount(_participants.size());
|
||||||
_allReceived = true;
|
_allParticipantsLoaded = true;
|
||||||
|
computeParticipantsCount();
|
||||||
_participantsRequestId = 0;
|
_participantsRequestId = 0;
|
||||||
changePeerEmptyCallFlag();
|
processQueuedUpdates();
|
||||||
}).send();
|
}).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GroupCall::setServerParticipantsCount(int count) {
|
||||||
|
_serverParticipantsCount = count;
|
||||||
|
changePeerEmptyCallFlag();
|
||||||
|
}
|
||||||
|
|
||||||
void GroupCall::changePeerEmptyCallFlag() {
|
void GroupCall::changePeerEmptyCallFlag() {
|
||||||
const auto chat = _peer->asChat();
|
const auto chat = _peer->asChat();
|
||||||
const auto channel = _peer->asChannel();
|
const auto channel = _peer->asChannel();
|
||||||
|
@ -118,7 +120,7 @@ void GroupCall::changePeerEmptyCallFlag() {
|
||||||
constexpr auto channelFlag = MTPDchannel::Flag::f_call_not_empty;
|
constexpr auto channelFlag = MTPDchannel::Flag::f_call_not_empty;
|
||||||
if (_peer->groupCall() != this) {
|
if (_peer->groupCall() != this) {
|
||||||
return;
|
return;
|
||||||
} else if (fullCount() > 0) {
|
} else if (_serverParticipantsCount > 0) {
|
||||||
if (chat && !(chat->flags() & chatFlag)) {
|
if (chat && !(chat->flags() & chatFlag)) {
|
||||||
chat->addFlags(chatFlag);
|
chat->addFlags(chatFlag);
|
||||||
chat->session().changes().peerUpdated(
|
chat->session().changes().peerUpdated(
|
||||||
|
@ -152,7 +154,7 @@ rpl::producer<int> GroupCall::fullCountValue() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GroupCall::participantsLoaded() const {
|
bool GroupCall::participantsLoaded() const {
|
||||||
return _allReceived;
|
return _allParticipantsLoaded;
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerData *GroupCall::participantPeerBySsrc(uint32 ssrc) const {
|
PeerData *GroupCall::participantPeerBySsrc(uint32 ssrc) const {
|
||||||
|
@ -169,35 +171,42 @@ auto GroupCall::participantUpdated() const
|
||||||
return _participantUpdates.events();
|
return _participantUpdates.events();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupCall::applyUpdate(const MTPGroupCall &update) {
|
void GroupCall::enqueueUpdate(const MTPUpdate &update) {
|
||||||
applyCall(update, false);
|
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) {
|
void GroupCall::discard() {
|
||||||
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 id = _id;
|
||||||
const auto peer = _peer;
|
const auto peer = _peer;
|
||||||
crl::on_main(&peer->session(), [=] {
|
crl::on_main(&peer->session(), [=] {
|
||||||
|
@ -209,23 +218,131 @@ void GroupCall::applyCall(const MTPGroupCall &call, bool force) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupCall::processFullCall(const MTPphone_GroupCall &call) {
|
void GroupCall::processFullCall(const MTPphone_GroupCall &call) {
|
||||||
call.match([&](const MTPDphone_groupCall &data) {
|
call.match([&](const MTPDphone_groupCall &data) {
|
||||||
_peer->owner().processUsers(data.vusers());
|
_peer->owner().processUsers(data.vusers());
|
||||||
_peer->owner().processChats(data.vchats());
|
_peer->owner().processChats(data.vchats());
|
||||||
|
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();
|
_participants.clear();
|
||||||
_speakingByActiveFinishes.clear();
|
_speakingByActiveFinishes.clear();
|
||||||
_participantPeerBySsrc.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(
|
applyParticipantsSlice(
|
||||||
data.vparticipants().v,
|
data.vparticipants().v,
|
||||||
ApplySliceSource::SliceLoaded);
|
ApplySliceSource::UpdateReceived);
|
||||||
applyCall(data.vcall(), true);
|
}, [](const auto &) {
|
||||||
_allReceived = (_fullCount.current() == _participants.size());
|
Unexpected("Type in GroupCall::processQueuedUpdates.");
|
||||||
_participantsSliceAdded.fire({});
|
|
||||||
});
|
});
|
||||||
|
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() {
|
void GroupCall::reload() {
|
||||||
|
@ -235,6 +352,10 @@ void GroupCall::reload() {
|
||||||
api().request(_participantsRequestId).cancel();
|
api().request(_participantsRequestId).cancel();
|
||||||
_participantsRequestId = 0;
|
_participantsRequestId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_queuedUpdates.clear();
|
||||||
|
_reloadByQueuedUpdatesTimer.cancel();
|
||||||
|
|
||||||
_reloadRequestId = api().request(
|
_reloadRequestId = api().request(
|
||||||
MTPphone_GetGroupCall(input())
|
MTPphone_GetGroupCall(input())
|
||||||
).done([=](const MTPphone_GroupCall &result) {
|
).done([=](const MTPphone_GroupCall &result) {
|
||||||
|
@ -252,7 +373,6 @@ void GroupCall::applyParticipantsSlice(
|
||||||
const auto now = base::unixtime::now();
|
const auto now = base::unixtime::now();
|
||||||
const auto speakingAfterActive = TimeId(kSpeakingAfterActive / 1000);
|
const auto speakingAfterActive = TimeId(kSpeakingAfterActive / 1000);
|
||||||
|
|
||||||
auto changedCount = _fullCount.current();
|
|
||||||
for (const auto &participant : list) {
|
for (const auto &participant : list) {
|
||||||
participant.match([&](const MTPDgroupCallParticipant &data) {
|
participant.match([&](const MTPDgroupCallParticipant &data) {
|
||||||
const auto participantPeerId = peerFromMTP(data.vpeer());
|
const auto participantPeerId = peerFromMTP(data.vpeer());
|
||||||
|
@ -274,8 +394,8 @@ void GroupCall::applyParticipantsSlice(
|
||||||
_participantUpdates.fire(std::move(update));
|
_participantUpdates.fire(std::move(update));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (changedCount > _participants.size()) {
|
if (_serverParticipantsCount > 0) {
|
||||||
--changedCount;
|
--_serverParticipantsCount;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -338,7 +458,7 @@ void GroupCall::applyParticipantsSlice(
|
||||||
*i = value;
|
*i = value;
|
||||||
}
|
}
|
||||||
if (data.is_just_joined()) {
|
if (data.is_just_joined()) {
|
||||||
++changedCount;
|
++_serverParticipantsCount;
|
||||||
}
|
}
|
||||||
if (sliceSource != ApplySliceSource::SliceLoaded) {
|
if (sliceSource != ApplySliceSource::SliceLoaded) {
|
||||||
_participantUpdates.fire({
|
_participantUpdates.fire({
|
||||||
|
@ -349,8 +469,8 @@ void GroupCall::applyParticipantsSlice(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (sliceSource == ApplySliceSource::UpdateReceived) {
|
if (sliceSource == ApplySliceSource::UpdateReceived) {
|
||||||
_fullCount = changedCount;
|
|
||||||
changePeerEmptyCallFlag();
|
changePeerEmptyCallFlag();
|
||||||
|
computeParticipantsCount();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,6 +662,7 @@ void GroupCall::requestUnknownParticipants() {
|
||||||
).done([=](const MTPphone_GroupParticipants &result) {
|
).done([=](const MTPphone_GroupParticipants &result) {
|
||||||
result.match([&](const MTPDphone_groupParticipants &data) {
|
result.match([&](const MTPDphone_groupParticipants &data) {
|
||||||
_peer->owner().processUsers(data.vusers());
|
_peer->owner().processUsers(data.vusers());
|
||||||
|
_peer->owner().processChats(data.vchats());
|
||||||
applyParticipantsSlice(
|
applyParticipantsSlice(
|
||||||
data.vparticipants().v,
|
data.vparticipants().v,
|
||||||
ApplySliceSource::UnknownLoaded);
|
ApplySliceSource::UnknownLoaded);
|
||||||
|
@ -605,41 +726,6 @@ bool GroupCall::inCall() const {
|
||||||
&& (current->state() == Calls::GroupCall::State::Joined);
|
&& (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) {
|
void GroupCall::setJoinMutedLocally(bool muted) {
|
||||||
_joinMuted = muted;
|
_joinMuted = muted;
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,10 +82,10 @@ public:
|
||||||
[[nodiscard]] rpl::producer<> participantsSliceAdded();
|
[[nodiscard]] rpl::producer<> participantsSliceAdded();
|
||||||
[[nodiscard]] rpl::producer<ParticipantUpdate> participantUpdated() const;
|
[[nodiscard]] rpl::producer<ParticipantUpdate> participantUpdated() const;
|
||||||
|
|
||||||
void applyUpdate(const MTPGroupCall &update);
|
void enqueueUpdate(const MTPUpdate &update);
|
||||||
void applyUpdate(const MTPDupdateGroupCallParticipants &update);
|
void applyLocalUpdate(
|
||||||
void applyUpdateChecked(
|
|
||||||
const MTPDupdateGroupCallParticipants &update);
|
const MTPDupdateGroupCallParticipants &update);
|
||||||
|
|
||||||
void applyLastSpoke(uint32 ssrc, LastSpokeTimes when, crl::time now);
|
void applyLastSpoke(uint32 ssrc, LastSpokeTimes when, crl::time now);
|
||||||
void applyActiveUpdate(
|
void applyActiveUpdate(
|
||||||
PeerId participantPeerId,
|
PeerId participantPeerId,
|
||||||
|
@ -113,14 +113,19 @@ private:
|
||||||
};
|
};
|
||||||
[[nodiscard]] ApiWrap &api() const;
|
[[nodiscard]] ApiWrap &api() const;
|
||||||
|
|
||||||
|
void discard();
|
||||||
[[nodiscard]] bool inCall() const;
|
[[nodiscard]] bool inCall() const;
|
||||||
void applyCall(const MTPGroupCall &call, bool force);
|
|
||||||
void applyParticipantsSlice(
|
void applyParticipantsSlice(
|
||||||
const QVector<MTPGroupCallParticipant> &list,
|
const QVector<MTPGroupCallParticipant> &list,
|
||||||
ApplySliceSource sliceSource);
|
ApplySliceSource sliceSource);
|
||||||
void requestUnknownParticipants();
|
void requestUnknownParticipants();
|
||||||
void changePeerEmptyCallFlag();
|
void changePeerEmptyCallFlag();
|
||||||
void checkFinishSpeakingByActive();
|
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 _id = 0;
|
||||||
const uint64 _accessHash = 0;
|
const uint64 _accessHash = 0;
|
||||||
|
@ -131,11 +136,15 @@ private:
|
||||||
mtpRequestId _reloadRequestId = 0;
|
mtpRequestId _reloadRequestId = 0;
|
||||||
rpl::variable<QString> _title;
|
rpl::variable<QString> _title;
|
||||||
|
|
||||||
|
base::flat_map<std::pair<int,bool>, MTPUpdate> _queuedUpdates;
|
||||||
|
base::Timer _reloadByQueuedUpdatesTimer;
|
||||||
|
|
||||||
std::vector<Participant> _participants;
|
std::vector<Participant> _participants;
|
||||||
base::flat_map<uint32, not_null<PeerData*>> _participantPeerBySsrc;
|
base::flat_map<uint32, not_null<PeerData*>> _participantPeerBySsrc;
|
||||||
base::flat_map<not_null<PeerData*>, crl::time> _speakingByActiveFinishes;
|
base::flat_map<not_null<PeerData*>, crl::time> _speakingByActiveFinishes;
|
||||||
base::Timer _speakingByActiveFinishTimer;
|
base::Timer _speakingByActiveFinishTimer;
|
||||||
QString _nextOffset;
|
QString _nextOffset;
|
||||||
|
int _serverParticipantsCount = 0;
|
||||||
rpl::variable<int> _fullCount = 0;
|
rpl::variable<int> _fullCount = 0;
|
||||||
rpl::variable<TimeId> _recordStartDate = 0;
|
rpl::variable<TimeId> _recordStartDate = 0;
|
||||||
|
|
||||||
|
@ -148,7 +157,7 @@ private:
|
||||||
|
|
||||||
bool _joinMuted = false;
|
bool _joinMuted = false;
|
||||||
bool _canChangeJoinMuted = true;
|
bool _canChangeJoinMuted = true;
|
||||||
bool _allReceived = false;
|
bool _allParticipantsLoaded = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue