Don't reorder members while menu is shown.

This commit is contained in:
John Preston 2020-12-06 16:16:11 +04:00
parent af4f10b1bb
commit 80b7858f5e
3 changed files with 52 additions and 8 deletions

View File

@ -325,8 +325,14 @@ void GroupCall::finish(FinishType type) {
}
void GroupCall::setMuted(MuteState mute) {
const auto wasMuted = (muted() == MuteState::Muted)
|| (muted() == MuteState::PushToTalk);
_muted = mute;
applySelfInCallLocally();
const auto nowMuted = (muted() == MuteState::Muted)
|| (muted() == MuteState::PushToTalk);
if (wasMuted != nowMuted) {
applySelfInCallLocally();
}
}
void GroupCall::handleUpdate(const MTPGroupCall &call) {

View File

@ -182,6 +182,7 @@ public:
MembersController(
not_null<GroupCall*> call,
not_null<QWidget*> menuParent);
~MembersController();
using MuteRequest = GroupMembers::MuteRequest;
@ -246,6 +247,7 @@ private:
not_null<QWidget*> _menuParent;
base::unique_qptr<Ui::PopupMenu> _menu;
base::flat_set<not_null<PeerData*>> _menuCheckRowsAfterHidden;
base::flat_map<uint32, not_null<Row*>> _speakingRowBySsrc;
Ui::Animations::Basic _speakingAnimation;
@ -276,7 +278,8 @@ void Row::updateState(const Data::GroupCall::Participant *participant) {
}
setState(State::Inactive);
setSpeaking(false);
} else if (!participant->muted) {
} else if (!participant->muted
|| (participant->speaking && participant->ssrc != 0)) {
setState(State::Active);
setSpeaking(participant->speaking && participant->ssrc != 0);
} else if (participant->canSelfUnmute) {
@ -550,6 +553,13 @@ MembersController::MembersController(
});
}
MembersController::~MembersController() {
if (_menu) {
_menu->setDestroyedCallback(nullptr);
_menu = nullptr;
}
}
void MembersController::setupListChangeViewers(not_null<GroupCall*> call) {
const auto channel = call->channel();
channel->session().changes().peerFlagsValue(
@ -638,6 +648,11 @@ void MembersController::updateRow(
}
void MembersController::checkSpeakingRowPosition(not_null<Row*> row) {
if (_menu) {
// Don't reorder rows while we show the popup menu.
_menuCheckRowsAfterHidden.emplace(row->peer());
return;
}
// Check if there are non-speaking rows above this one.
const auto count = delegate()->peerListFullRowsCount();
for (auto i = 0; i != count; ++i) {
@ -873,11 +888,28 @@ auto MembersController::kickMemberRequests() const
void MembersController::rowClicked(not_null<PeerListRow*> row) {
if (_menu) {
_menu->setDestroyedCallback(nullptr);
_menu->deleteLater();
_menu = nullptr;
}
_menu = rowContextMenu(_menuParent, row);
_menu->popup(QCursor::pos());
if (const auto raw = _menu.get()) {
raw->setDestroyedCallback([=] {
if (_menu && _menu.get() != raw) {
return;
}
auto saved = base::take(_menu);
for (const auto peer : base::take(_menuCheckRowsAfterHidden)) {
if (const auto row = findRow(peer->asUser())) {
if (row->speaking()) {
checkSpeakingRowPosition(row);
}
}
}
_menu = std::move(saved);
});
raw->popup(QCursor::pos());
}
}
void MembersController::rowActionClicked(
@ -890,6 +922,9 @@ base::unique_qptr<Ui::PopupMenu> MembersController::rowContextMenu(
not_null<PeerListRow*> row) {
Expects(row->peer()->isUser());
if (row->peer()->isSelf()) {
return nullptr;
}
const auto real = static_cast<Row*>(row.get());
const auto user = row->peer()->asUser();
auto result = base::make_unique_q<Ui::PopupMenu>(
@ -951,7 +986,7 @@ base::unique_qptr<Ui::PopupMenu> MembersController::rowContextMenu(
_kickMemberRequests.fire_copy(user);
});
if (!user->isSelf() && _channel->canManageCall()) {
if (_channel->canManageCall()) {
result->addAction(
(mute
? tr::lng_group_call_context_mute(tr::now)

View File

@ -207,14 +207,16 @@ void GroupCall::applyParticipantsSlice(
const auto was = (i != end(_participants))
? std::make_optional(*i)
: std::nullopt;
const auto canSelfUnmute = !data.is_muted()
|| data.is_can_self_unmute();
const auto value = Participant{
.user = user,
.date = data.vdate().v,
.lastActive = was ? was->lastActive : 0,
.ssrc = uint32(data.vsource().v),
.speaking = !data.is_muted() && (was ? was->speaking : false),
.speaking = canSelfUnmute && (was ? was->speaking : false),
.muted = data.is_muted(),
.canSelfUnmute = !data.is_muted() || data.is_can_self_unmute(),
.canSelfUnmute = canSelfUnmute,
};
if (i == end(_participants)) {
_userBySsrc.emplace(value.ssrc, user);
@ -258,7 +260,7 @@ void GroupCall::applyParticipantsMutes(
const auto was = *i;
i->muted = data.is_muted();
i->canSelfUnmute = !i->muted || data.is_can_self_unmute();
if (i->muted) {
if (!i->canSelfUnmute) {
i->speaking = false;
}
_participantUpdates.fire({
@ -280,7 +282,8 @@ void GroupCall::applyLastSpoke(uint32 ssrc, crl::time when, crl::time now) {
const auto j = ranges::find(_participants, i->second, &Participant::user);
Assert(j != end(_participants));
const auto speaking = (when + kSpeakStatusKeptFor >= now) && !j->muted;
const auto speaking = (when + kSpeakStatusKeptFor >= now)
&& j->canSelfUnmute;
if (j->speaking != speaking) {
const auto was = *j;
j->speaking = speaking;