mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-03 21:54:05 +02:00
Show confcall users that are only on blockchain.
This commit is contained in:
parent
e33a866a63
commit
be611c1920
4 changed files with 209 additions and 50 deletions
|
@ -4759,6 +4759,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
"lng_group_call_invite" = "Invite Members";
|
||||
"lng_group_call_invite_conf" = "Add People";
|
||||
"lng_group_call_invited_status" = "invited";
|
||||
"lng_group_call_blockchain_only_status" = "syncing...";
|
||||
"lng_group_call_muted_by_me_status" = "muted for you";
|
||||
"lng_group_call_invite_title" = "Invite members";
|
||||
"lng_group_call_invite_button" = "Invite";
|
||||
|
|
|
@ -108,6 +108,8 @@ private:
|
|||
const Data::GroupCallParticipant &participant);
|
||||
[[nodiscard]] std::unique_ptr<Row> createInvitedRow(
|
||||
not_null<PeerData*> participantPeer);
|
||||
[[nodiscard]] std::unique_ptr<Row> createWithAccessRow(
|
||||
not_null<PeerData*> participantPeer);
|
||||
|
||||
[[nodiscard]] bool isMe(not_null<PeerData*> participantPeer) const;
|
||||
void prepareRows(not_null<Data::GroupCall*> real);
|
||||
|
@ -128,7 +130,8 @@ private:
|
|||
void updateRow(
|
||||
not_null<Row*> row,
|
||||
const std::optional<Data::GroupCallParticipant> &was,
|
||||
const Data::GroupCallParticipant *participant);
|
||||
const Data::GroupCallParticipant *participant,
|
||||
Row::State noParticipantState = Row::State::Invited);
|
||||
void updateRowInSoundingMap(
|
||||
not_null<Row*> row,
|
||||
bool wasSounding,
|
||||
|
@ -162,8 +165,13 @@ private:
|
|||
const VideoEndpoint &endpoint,
|
||||
bool active);
|
||||
|
||||
void appendInvitedUsers();
|
||||
void partitionRows();
|
||||
void setupInvitedUsers();
|
||||
[[nodiscard]] bool appendInvitedUsers();
|
||||
void setupWithAccessUsers();
|
||||
[[nodiscard]] bool appendWithAccessUsers();
|
||||
void scheduleRaisedHandStatusRemove();
|
||||
void refreshWithAccessRows(base::flat_set<UserId> &&nowIds);
|
||||
|
||||
void hideRowsWithVideoExcept(const VideoEndpoint &large);
|
||||
void showAllHiddenRows();
|
||||
|
@ -205,6 +213,8 @@ private:
|
|||
Ui::RoundRect _narrowRoundRect;
|
||||
QImage _narrowShadow;
|
||||
|
||||
base::flat_set<UserId> _withAccess;
|
||||
|
||||
rpl::lifetime _lifetime;
|
||||
|
||||
};
|
||||
|
@ -414,6 +424,9 @@ void Members::Controller::subscribeToChanges(not_null<Data::GroupCall*> real) {
|
|||
if (const auto row = findRow(participantPeer)) {
|
||||
if (isMe(participantPeer)) {
|
||||
updateRow(row, update.was, nullptr);
|
||||
} else if (_withAccess.contains(peerToUser(participantPeer->id))) {
|
||||
updateRow(row, update.was, nullptr, Row::State::WithAccess);
|
||||
partitionRows();
|
||||
} else {
|
||||
removeRow(row);
|
||||
delegate()->peerListRefreshRows();
|
||||
|
@ -431,10 +444,6 @@ void Members::Controller::subscribeToChanges(not_null<Data::GroupCall*> real) {
|
|||
) | rpl::start_with_next([=](const VideoStateToggle &update) {
|
||||
toggleVideoEndpointActive(update.endpoint, update.value);
|
||||
}, _lifetime);
|
||||
|
||||
if (_prepared) {
|
||||
appendInvitedUsers();
|
||||
}
|
||||
}
|
||||
|
||||
void Members::Controller::toggleVideoEndpointActive(
|
||||
|
@ -481,13 +490,21 @@ void Members::Controller::toggleVideoEndpointActive(
|
|||
|
||||
}
|
||||
|
||||
void Members::Controller::appendInvitedUsers() {
|
||||
bool Members::Controller::appendInvitedUsers() {
|
||||
auto changed = false;
|
||||
if (const auto id = _call->id()) {
|
||||
for (const auto &user : _peer->owner().invitedToCallUsers(id)) {
|
||||
if (auto row = createInvitedRow(user)) {
|
||||
delegate()->peerListAppendRow(std::move(row));
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
void Members::Controller::setupInvitedUsers() {
|
||||
if (appendInvitedUsers()) {
|
||||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
|
||||
|
@ -503,15 +520,79 @@ void Members::Controller::appendInvitedUsers() {
|
|||
}, _lifetime);
|
||||
}
|
||||
|
||||
bool Members::Controller::appendWithAccessUsers() {
|
||||
auto changed = false;
|
||||
for (const auto id : _withAccess) {
|
||||
if (auto row = createWithAccessRow(_peer->owner().user(id))) {
|
||||
changed = true;
|
||||
delegate()->peerListAppendRow(std::move(row));
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
void Members::Controller::setupWithAccessUsers() {
|
||||
const auto conference = _call->conferenceCall().get();
|
||||
if (!conference) {
|
||||
return;
|
||||
}
|
||||
conference->participantsWithAccessValue(
|
||||
) | rpl::start_with_next([=](base::flat_set<UserId> &&nowIds) {
|
||||
for (auto i = begin(_withAccess); i != end(_withAccess);) {
|
||||
const auto oldId = *i;
|
||||
if (nowIds.remove(oldId)) {
|
||||
++i;
|
||||
continue;
|
||||
}
|
||||
const auto user = _peer->owner().user(oldId);
|
||||
if (const auto row = findRow(user)) {
|
||||
if (row->state() == Row::State::WithAccess) {
|
||||
removeRow(row);
|
||||
}
|
||||
}
|
||||
i = _withAccess.erase(i);
|
||||
}
|
||||
auto partition = false;
|
||||
auto partitionChecked = false;
|
||||
for (const auto nowId : nowIds) {
|
||||
const auto user = _peer->owner().user(nowId);
|
||||
if (!findRow(user)) {
|
||||
if (auto row = createWithAccessRow(user)) {
|
||||
if (!partitionChecked) {
|
||||
partitionChecked = true;
|
||||
if (const auto count = delegate()->peerListFullRowsCount()) {
|
||||
const auto last = delegate()->peerListRowAt(count - 1);
|
||||
const auto state = static_cast<Row*>(last.get())->state();
|
||||
if (state == Row::State::Invited) {
|
||||
partition = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
delegate()->peerListAppendRow(std::move(row));
|
||||
}
|
||||
}
|
||||
_withAccess.emplace(nowId);
|
||||
}
|
||||
if (partition) {
|
||||
delegate()->peerListPartitionRows([](const PeerListRow &row) {
|
||||
const auto state = static_cast<const Row&>(row).state();
|
||||
return (state != Row::State::Invited);
|
||||
});
|
||||
}
|
||||
delegate()->peerListRefreshRows();
|
||||
}, _lifetime);
|
||||
}
|
||||
|
||||
void Members::Controller::updateRow(
|
||||
const std::optional<Data::GroupCallParticipant> &was,
|
||||
const Data::GroupCallParticipant &now) {
|
||||
auto reorderIfInvitedBefore = 0;
|
||||
auto reorderIfNonRealBefore = 0;
|
||||
auto checkPosition = (Row*)nullptr;
|
||||
auto addedToBottom = (Row*)nullptr;
|
||||
if (const auto row = findRow(now.peer)) {
|
||||
if (row->state() == Row::State::Invited) {
|
||||
reorderIfInvitedBefore = row->absoluteIndex();
|
||||
if (row->state() == Row::State::Invited
|
||||
|| row->state() == Row::State::WithAccess) {
|
||||
reorderIfNonRealBefore = row->absoluteIndex();
|
||||
}
|
||||
updateRow(row, was, &now);
|
||||
if ((now.speaking && (!was || !was->speaking))
|
||||
|
@ -523,7 +604,7 @@ void Members::Controller::updateRow(
|
|||
if (row->speaking()) {
|
||||
delegate()->peerListPrependRow(std::move(row));
|
||||
} else {
|
||||
reorderIfInvitedBefore = delegate()->peerListFullRowsCount();
|
||||
reorderIfNonRealBefore = delegate()->peerListFullRowsCount();
|
||||
if (now.raisedHandRating != 0) {
|
||||
checkPosition = row.get();
|
||||
} else {
|
||||
|
@ -533,20 +614,19 @@ void Members::Controller::updateRow(
|
|||
}
|
||||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
static constexpr auto kInvited = Row::State::Invited;
|
||||
const auto reorder = [&] {
|
||||
const auto count = reorderIfInvitedBefore;
|
||||
const auto count = reorderIfNonRealBefore;
|
||||
if (count <= 0) {
|
||||
return false;
|
||||
}
|
||||
const auto row = delegate()->peerListRowAt(
|
||||
reorderIfInvitedBefore - 1).get();
|
||||
return (static_cast<Row*>(row)->state() == kInvited);
|
||||
reorderIfNonRealBefore - 1).get();
|
||||
using State = Row::State;
|
||||
const auto state = static_cast<Row*>(row)->state();
|
||||
return (state == State::Invited) || (state == State::WithAccess);
|
||||
}();
|
||||
if (reorder) {
|
||||
delegate()->peerListPartitionRows([](const PeerListRow &row) {
|
||||
return static_cast<const Row&>(row).state() != kInvited;
|
||||
});
|
||||
partitionRows();
|
||||
}
|
||||
if (checkPosition) {
|
||||
checkRowPosition(checkPosition);
|
||||
|
@ -570,6 +650,24 @@ void Members::Controller::updateRow(
|
|||
}
|
||||
}
|
||||
|
||||
void Members::Controller::partitionRows() {
|
||||
auto hadWithAccess = false;
|
||||
delegate()->peerListPartitionRows([&](const PeerListRow &row) {
|
||||
using State = Row::State;
|
||||
const auto state = static_cast<const Row&>(row).state();
|
||||
if (state == State::WithAccess) {
|
||||
hadWithAccess = true;
|
||||
}
|
||||
return (state != State::Invited) && (state != State::WithAccess);
|
||||
});
|
||||
if (hadWithAccess) {
|
||||
delegate()->peerListPartitionRows([](const PeerListRow &row) {
|
||||
const auto state = static_cast<const Row&>(row).state();
|
||||
return (state != Row::State::Invited);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool Members::Controller::allRowsAboveAreSpeaking(not_null<Row*> row) const {
|
||||
const auto count = delegate()->peerListFullRowsCount();
|
||||
for (auto i = 0; i != count; ++i) {
|
||||
|
@ -692,14 +790,21 @@ void Members::Controller::checkRowPosition(not_null<Row*> row) {
|
|||
void Members::Controller::updateRow(
|
||||
not_null<Row*> row,
|
||||
const std::optional<Data::GroupCallParticipant> &was,
|
||||
const Data::GroupCallParticipant *participant) {
|
||||
const Data::GroupCallParticipant *participant,
|
||||
Row::State noParticipantState) {
|
||||
const auto wasSounding = row->sounding();
|
||||
const auto wasSsrc = was ? was->ssrc : 0;
|
||||
const auto wasAdditionalSsrc = was
|
||||
? GetAdditionalAudioSsrc(was->videoParams)
|
||||
: 0;
|
||||
row->setSkipLevelUpdate(_skipRowLevelUpdate);
|
||||
row->updateState(participant);
|
||||
if (participant) {
|
||||
row->updateState(*participant);
|
||||
} else if (noParticipantState == Row::State::WithAccess) {
|
||||
row->updateStateWithAccess();
|
||||
} else {
|
||||
row->updateStateInvited();
|
||||
}
|
||||
|
||||
const auto wasNoSounding = _soundingRowBySsrc.empty();
|
||||
updateRowInSoundingMap(
|
||||
|
@ -842,7 +947,8 @@ void Members::Controller::prepare() {
|
|||
}
|
||||
|
||||
loadMoreRows();
|
||||
appendInvitedUsers();
|
||||
setupWithAccessUsers();
|
||||
setupInvitedUsers();
|
||||
_prepared = true;
|
||||
|
||||
setupListChangeViewers();
|
||||
|
@ -893,6 +999,12 @@ void Members::Controller::prepareRows(not_null<Data::GroupCall*> real) {
|
|||
delegate()->peerListAppendRow(std::move(row));
|
||||
}
|
||||
}
|
||||
if (appendWithAccessUsers()) {
|
||||
changed = true;
|
||||
}
|
||||
if (appendInvitedUsers()) {
|
||||
changed = true;
|
||||
}
|
||||
if (changed) {
|
||||
delegate()->peerListRefreshRows();
|
||||
}
|
||||
|
@ -1354,8 +1466,9 @@ base::unique_qptr<Ui::PopupMenu> Members::Controller::createRowContextMenu(
|
|||
}
|
||||
const auto canKick = [&] {
|
||||
const auto user = participantPeer->asUser();
|
||||
if (static_cast<Row*>(row.get())->state()
|
||||
== Row::State::Invited) {
|
||||
const auto state = static_cast<Row*>(row.get())->state();
|
||||
if (state == Row::State::Invited
|
||||
|| state == Row::State::WithAccess) {
|
||||
return false;
|
||||
} else if (const auto chat = _peer->asChat()) {
|
||||
return chat->amCreator()
|
||||
|
@ -1484,6 +1597,7 @@ void Members::Controller::addMuteActionsToContextMenu(
|
|||
|
||||
const auto muteAction = [&]() -> QAction* {
|
||||
if (muteState == Row::State::Invited
|
||||
|| muteState == Row::State::WithAccess
|
||||
|| _call->rtmp()
|
||||
|| isMe(participantPeer)
|
||||
|| (muteState == Row::State::Inactive
|
||||
|
@ -1547,6 +1661,16 @@ std::unique_ptr<Row> Members::Controller::createInvitedRow(
|
|||
return result;
|
||||
}
|
||||
|
||||
std::unique_ptr<Row> Members::Controller::createWithAccessRow(
|
||||
not_null<PeerData*> participantPeer) {
|
||||
if (findRow(participantPeer)) {
|
||||
return nullptr;
|
||||
}
|
||||
auto result = std::make_unique<Row>(this, participantPeer);
|
||||
updateRow(result.get(), std::nullopt, nullptr, Row::State::WithAccess);
|
||||
return result;
|
||||
}
|
||||
|
||||
Members::Members(
|
||||
not_null<QWidget*> parent,
|
||||
not_null<GroupCall*> call,
|
||||
|
|
|
@ -138,41 +138,52 @@ void MembersRow::setSkipLevelUpdate(bool value) {
|
|||
_skipLevelUpdate = value;
|
||||
}
|
||||
|
||||
void MembersRow::updateState(
|
||||
const Data::GroupCallParticipant *participant) {
|
||||
setVolume(participant
|
||||
? participant->volume
|
||||
: Group::kDefaultVolume);
|
||||
if (!participant) {
|
||||
setState(State::Invited);
|
||||
setSounding(false);
|
||||
setSpeaking(false);
|
||||
_mutedByMe = false;
|
||||
_raisedHandRating = 0;
|
||||
} else if (!participant->muted
|
||||
|| (participant->sounding && participant->ssrc != 0)
|
||||
|| (participant->additionalSounding
|
||||
&& GetAdditionalAudioSsrc(participant->videoParams) != 0)) {
|
||||
void MembersRow::updateStateInvited() {
|
||||
setVolume(Group::kDefaultVolume);
|
||||
setState(State::Invited);
|
||||
setSounding(false);
|
||||
setSpeaking(false);
|
||||
_mutedByMe = false;
|
||||
_raisedHandRating = 0;
|
||||
refreshStatus();
|
||||
}
|
||||
|
||||
void MembersRow::updateStateWithAccess() {
|
||||
setVolume(Group::kDefaultVolume);
|
||||
setState(State::WithAccess);
|
||||
setSounding(false);
|
||||
setSpeaking(false);
|
||||
_mutedByMe = false;
|
||||
_raisedHandRating = 0;
|
||||
refreshStatus();
|
||||
}
|
||||
|
||||
void MembersRow::updateState(const Data::GroupCallParticipant &participant) {
|
||||
setVolume(participant.volume);
|
||||
if (!participant.muted
|
||||
|| (participant.sounding && participant.ssrc != 0)
|
||||
|| (participant.additionalSounding
|
||||
&& GetAdditionalAudioSsrc(participant.videoParams) != 0)) {
|
||||
setState(State::Active);
|
||||
setSounding((participant->sounding && participant->ssrc != 0)
|
||||
|| (participant->additionalSounding
|
||||
&& GetAdditionalAudioSsrc(participant->videoParams) != 0));
|
||||
setSpeaking((participant->speaking && participant->ssrc != 0)
|
||||
|| (participant->additionalSpeaking
|
||||
&& GetAdditionalAudioSsrc(participant->videoParams) != 0));
|
||||
_mutedByMe = participant->mutedByMe;
|
||||
setSounding((participant.sounding && participant.ssrc != 0)
|
||||
|| (participant.additionalSounding
|
||||
&& GetAdditionalAudioSsrc(participant.videoParams) != 0));
|
||||
setSpeaking((participant.speaking && participant.ssrc != 0)
|
||||
|| (participant.additionalSpeaking
|
||||
&& GetAdditionalAudioSsrc(participant.videoParams) != 0));
|
||||
_mutedByMe = participant.mutedByMe;
|
||||
_raisedHandRating = 0;
|
||||
} else if (participant->canSelfUnmute) {
|
||||
} else if (participant.canSelfUnmute) {
|
||||
setState(State::Inactive);
|
||||
setSounding(false);
|
||||
setSpeaking(false);
|
||||
_mutedByMe = participant->mutedByMe;
|
||||
_mutedByMe = participant.mutedByMe;
|
||||
_raisedHandRating = 0;
|
||||
} else {
|
||||
setSounding(false);
|
||||
setSpeaking(false);
|
||||
_mutedByMe = participant->mutedByMe;
|
||||
_raisedHandRating = participant->raisedHandRating;
|
||||
_mutedByMe = participant.mutedByMe;
|
||||
_raisedHandRating = participant.raisedHandRating;
|
||||
setState(_raisedHandRating ? State::RaisedHand : State::Muted);
|
||||
}
|
||||
refreshStatus();
|
||||
|
@ -450,6 +461,20 @@ void MembersRow::paintMuteIcon(
|
|||
_delegate->rowPaintIcon(p, iconRect, computeIconState(style));
|
||||
}
|
||||
|
||||
QString MembersRow::generateName() {
|
||||
const auto result = peer()->name();
|
||||
return result.isEmpty()
|
||||
? u"User #%1"_q.arg(peerToUser(peer()->id).bare)
|
||||
: result;
|
||||
}
|
||||
|
||||
QString MembersRow::generateShortName() {
|
||||
const auto result = peer()->shortName();
|
||||
return result.isEmpty()
|
||||
? u"User #%1"_q.arg(peerToUser(peer()->id).bare)
|
||||
: result;
|
||||
}
|
||||
|
||||
auto MembersRow::generatePaintUserpicCallback(bool forceRound)
|
||||
-> PaintRoundImageCallback {
|
||||
return [=](Painter &p, int x, int y, int outerWidth, int size) {
|
||||
|
@ -613,11 +638,13 @@ void MembersRow::paintComplexStatusText(
|
|||
availableWidth -= skip;
|
||||
const auto &font = st::normalFont;
|
||||
const auto useAbout = !_about.isEmpty()
|
||||
&& (_state != State::WithAccess)
|
||||
&& (style != MembersRowStyle::Video)
|
||||
&& ((_state == State::RaisedHand && !_raisedHandStatus)
|
||||
|| (_state != State::RaisedHand && !_speaking));
|
||||
if (!useAbout
|
||||
&& _state != State::Invited
|
||||
&& _state != State::WithAccess
|
||||
&& !_mutedByMe) {
|
||||
paintStatusIcon(p, x, y, st, font, selected, narrowMode);
|
||||
|
||||
|
@ -663,6 +690,8 @@ void MembersRow::paintComplexStatusText(
|
|||
? tr::lng_group_call_muted_by_me_status(tr::now)
|
||||
: _delegate->rowIsMe(peer())
|
||||
? tr::lng_status_connecting(tr::now)
|
||||
: (_state == State::WithAccess)
|
||||
? tr::lng_group_call_blockchain_only_status(tr::now)
|
||||
: tr::lng_group_call_invited_status(tr::now)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,11 +75,14 @@ public:
|
|||
Muted,
|
||||
RaisedHand,
|
||||
Invited,
|
||||
WithAccess,
|
||||
};
|
||||
|
||||
void setAbout(const QString &about);
|
||||
void setSkipLevelUpdate(bool value);
|
||||
void updateState(const Data::GroupCallParticipant *participant);
|
||||
void updateState(const Data::GroupCallParticipant &participant);
|
||||
void updateStateInvited();
|
||||
void updateStateWithAccess();
|
||||
void updateLevel(float level);
|
||||
void updateBlobAnimation(crl::time now);
|
||||
void clearRaisedHandStatus();
|
||||
|
@ -122,6 +125,8 @@ public:
|
|||
bool selected,
|
||||
bool actionSelected) override;
|
||||
|
||||
QString generateName() override;
|
||||
QString generateShortName() override;
|
||||
PaintRoundImageCallback generatePaintUserpicCallback(
|
||||
bool forceRound) override;
|
||||
void paintComplexUserpic(
|
||||
|
|
Loading…
Add table
Reference in a new issue