Don't reorder members while menu is shown.
This commit is contained in:
parent
af4f10b1bb
commit
80b7858f5e
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue