Fix voice chat members context menu.

This commit is contained in:
John Preston 2020-12-24 13:30:05 +04:00
parent cf5cc3646a
commit 7d22c631ca
4 changed files with 96 additions and 49 deletions

View file

@ -1229,37 +1229,56 @@ void PeerListContent::mousePressReleased(Qt::MouseButton button) {
} }
} }
void PeerListContent::contextMenuEvent(QContextMenuEvent *e) { void PeerListContent::showRowMenu(
not_null<PeerListRow*> row,
Fn<void(not_null<Ui::PopupMenu*>)> destroyed) {
showRowMenu(findRowIndex(row), QCursor::pos(), std::move(destroyed));
}
bool PeerListContent::showRowMenu(
RowIndex index,
QPoint globalPos,
Fn<void(not_null<Ui::PopupMenu*>)> destroyed) {
if (_contextMenu) { if (_contextMenu) {
_contextMenu->deleteLater(); _contextMenu->setDestroyedCallback(nullptr);
_contextMenu = nullptr; _contextMenu = nullptr;
} }
setContexted(Selected()); setContexted(Selected());
if (e->reason() == QContextMenuEvent::Mouse) {
handleMouseMove(e->globalPos());
}
setContexted(_selected);
if (_pressButton != Qt::LeftButton) { if (_pressButton != Qt::LeftButton) {
mousePressReleased(_pressButton); mousePressReleased(_pressButton);
} }
if (const auto row = getRow(_contexted.index)) { const auto row = getRow(index);
_contextMenu = _controller->rowContextMenu(this, row); if (!row) {
if (_contextMenu) { return false;
_contextMenu->setDestroyedCallback(crl::guard( }
this,
[this] { _contextMenu = _controller->rowContextMenu(this, row);
setContexted(Selected()); const auto raw = _contextMenu.get();
handleMouseMove(QCursor::pos()); if (!raw) {
})); return false;
_contextMenu->popup(e->globalPos()); }
e->accept();
} else { setContexted({ index, false });
raw->setDestroyedCallback(crl::guard(
this,
[=] {
setContexted(Selected()); setContexted(Selected());
} handleMouseMove(QCursor::pos());
} else { if (destroyed) {
setContexted(Selected()); destroyed(raw);
}
}));
raw->popup(globalPos);
return true;
}
void PeerListContent::contextMenuEvent(QContextMenuEvent *e) {
if (e->reason() == QContextMenuEvent::Mouse) {
handleMouseMove(e->globalPos());
}
if (showRowMenu(_selected.index, e->globalPos())) {
e->accept();
} }
} }

View file

@ -300,6 +300,9 @@ public:
peerListFinishSelectedRowsBunch(); peerListFinishSelectedRowsBunch();
} }
virtual void peerListShowRowMenu(
not_null<PeerListRow*> row,
Fn<void(not_null<Ui::PopupMenu*>)> destroyed) = 0;
virtual int peerListSelectedRowsCount() = 0; virtual int peerListSelectedRowsCount() = 0;
virtual std::unique_ptr<PeerListState> peerListSaveState() const = 0; virtual std::unique_ptr<PeerListState> peerListSaveState() const = 0;
virtual void peerListRestoreState( virtual void peerListRestoreState(
@ -557,6 +560,10 @@ public:
std::unique_ptr<PeerListState> saveState() const; std::unique_ptr<PeerListState> saveState() const;
void restoreState(std::unique_ptr<PeerListState> state); void restoreState(std::unique_ptr<PeerListState> state);
void showRowMenu(
not_null<PeerListRow*> row,
Fn<void(not_null<Ui::PopupMenu*>)> destroyed);
auto scrollToRequests() const { auto scrollToRequests() const {
return _scrollToRequests.events(); return _scrollToRequests.events();
} }
@ -640,6 +647,11 @@ private:
RowIndex findRowIndex(not_null<PeerListRow*> row, RowIndex hint = RowIndex()); RowIndex findRowIndex(not_null<PeerListRow*> row, RowIndex hint = RowIndex());
QRect getActiveActionRect(not_null<PeerListRow*> row, RowIndex index) const; QRect getActiveActionRect(not_null<PeerListRow*> row, RowIndex index) const;
bool showRowMenu(
RowIndex index,
QPoint globalPos,
Fn<void(not_null<Ui::PopupMenu*>)> destroyed = nullptr);
crl::time paintRow(Painter &p, crl::time ms, RowIndex index); crl::time paintRow(Painter &p, crl::time ms, RowIndex index);
void addRowEntry(not_null<PeerListRow*> row); void addRowEntry(not_null<PeerListRow*> row);
@ -823,6 +835,11 @@ public:
std::unique_ptr<PeerListState> state) override { std::unique_ptr<PeerListState> state) override {
_content->restoreState(std::move(state)); _content->restoreState(std::move(state));
} }
void peerListShowRowMenu(
not_null<PeerListRow*> row,
Fn<void(not_null<Ui::PopupMenu*>)> destroyed) override {
_content->showRowMenu(row, std::move(destroyed));
}
protected: protected:
not_null<PeerListContent*> content() const { not_null<PeerListContent*> content() const {

View file

@ -243,6 +243,9 @@ private:
void prepareRows(not_null<Data::GroupCall*> real); void prepareRows(not_null<Data::GroupCall*> real);
//void repaintByTimer(); //void repaintByTimer();
[[nodiscard]] base::unique_qptr<Ui::PopupMenu> createRowContextMenu(
QWidget *parent,
not_null<PeerListRow*> row);
void setupListChangeViewers(not_null<GroupCall*> call); void setupListChangeViewers(not_null<GroupCall*> call);
void subscribeToChanges(not_null<Data::GroupCall*> real); void subscribeToChanges(not_null<Data::GroupCall*> real);
void updateRow( void updateRow(
@ -638,10 +641,7 @@ MembersController::MembersController(
} }
MembersController::~MembersController() { MembersController::~MembersController() {
if (_menu) { base::take(_menu);
_menu->setDestroyedCallback(nullptr);
_menu = nullptr;
}
} }
void MembersController::setupListChangeViewers(not_null<GroupCall*> call) { void MembersController::setupListChangeViewers(not_null<GroupCall*> call) {
@ -1002,29 +1002,20 @@ auto MembersController::kickMemberRequests() const
} }
void MembersController::rowClicked(not_null<PeerListRow*> row) { void MembersController::rowClicked(not_null<PeerListRow*> row) {
if (_menu) { delegate()->peerListShowRowMenu(row, [=](not_null<Ui::PopupMenu*> menu) {
_menu->setDestroyedCallback(nullptr); if (!_menu || _menu.get() != menu) {
_menu->deleteLater(); return;
_menu = nullptr; }
} auto saved = base::take(_menu);
_menu = rowContextMenu(_menuParent, row); for (const auto peer : base::take(_menuCheckRowsAfterHidden)) {
if (const auto raw = _menu.get()) { if (const auto row = findRow(peer->asUser())) {
raw->setDestroyedCallback([=] { if (row->speaking()) {
if (_menu && _menu.get() != raw) { checkSpeakingRowPosition(row);
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); }
}); _menu = std::move(saved);
raw->popup(QCursor::pos()); });
}
} }
void MembersController::rowActionClicked( void MembersController::rowActionClicked(
@ -1035,6 +1026,23 @@ void MembersController::rowActionClicked(
base::unique_qptr<Ui::PopupMenu> MembersController::rowContextMenu( base::unique_qptr<Ui::PopupMenu> MembersController::rowContextMenu(
QWidget *parent, QWidget *parent,
not_null<PeerListRow*> row) { not_null<PeerListRow*> row) {
auto result = createRowContextMenu(parent, row);
if (result) {
// First clear _menu value, so that we don't check row positions yet.
base::take(_menu);
// Here unique_qptr is used like a shared pointer, where
// not the last destroyed pointer destroys the object, but the first.
_menu = base::unique_qptr<Ui::PopupMenu>(result.get());
}
return result;
}
base::unique_qptr<Ui::PopupMenu> MembersController::createRowContextMenu(
QWidget *parent,
not_null<PeerListRow*> row) {
Expects(row->peer()->isUser()); Expects(row->peer()->isUser());
if (row->peer()->isSelf()) { if (row->peer()->isSelf()) {
@ -1125,7 +1133,9 @@ base::unique_qptr<Ui::PopupMenu> MembersController::rowContextMenu(
_kickMemberRequests.fire_copy(user); _kickMemberRequests.fire_copy(user);
}); });
if (_peer->canManageGroupCall() && (!admin || mute)) { if ((muteState != Row::State::Invited)
&& _peer->canManageGroupCall()
&& (!admin || mute)) {
result->addAction( result->addAction(
(mute (mute
? tr::lng_group_call_context_mute(tr::now) ? tr::lng_group_call_context_mute(tr::now)

View file

@ -689,7 +689,8 @@ void TopBar::updateControlsGeometry() {
left += _durationLabel->width() + st::callBarSkip; left += _durationLabel->width() + st::callBarSkip;
} }
if (!_userpics.isNull()) { if (!_userpics.isNull()) {
left += _userpics.width() / _userpics.devicePixelRatio(); left += (_userpics.width() / _userpics.devicePixelRatio())
+ st::callBarSkip;
} }
if (_signalBars) { if (_signalBars) {
_signalBars->moveToLeft(left, (height() - _signalBars->height()) / 2); _signalBars->moveToLeft(left, (height() - _signalBars->height()) / 2);