mirror of https://github.com/procxx/kepka.git
Add context menu support to info members list.
This commit is contained in:
parent
856ca22aad
commit
fb46c33d7f
|
@ -308,7 +308,7 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
|
||||||
} break;
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto newPhotoId = 0;
|
auto newPhotoId = PhotoId(0);
|
||||||
if (auto photo = App::feedPhoto(f.vchat_photo)) {
|
if (auto photo = App::feedPhoto(f.vchat_photo)) {
|
||||||
newPhotoId = photo->id;
|
newPhotoId = photo->id;
|
||||||
photo->peer = chat;
|
photo->peer = chat;
|
||||||
|
|
|
@ -21,6 +21,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <rpl/event_stream.h>
|
#include <rpl/event_stream.h>
|
||||||
|
#include <rpl/filter.h>
|
||||||
#include "base/timer.h"
|
#include "base/timer.h"
|
||||||
|
|
||||||
namespace Storage {
|
namespace Storage {
|
||||||
|
@ -94,6 +95,45 @@ public:
|
||||||
rpl::producer<not_null<const HistoryItem*>> itemRemoved() const {
|
rpl::producer<not_null<const HistoryItem*>> itemRemoved() const {
|
||||||
return _itemRemoved.events();
|
return _itemRemoved.events();
|
||||||
}
|
}
|
||||||
|
using MegagroupParticipant = std::tuple<
|
||||||
|
not_null<ChannelData*>,
|
||||||
|
not_null<UserData*>>;
|
||||||
|
void removeMegagroupParticipant(
|
||||||
|
not_null<ChannelData*> channel,
|
||||||
|
not_null<UserData*> user) {
|
||||||
|
_megagroupParticipantRemoved.fire({ channel, user });
|
||||||
|
}
|
||||||
|
auto megagroupParticipantRemoved() const {
|
||||||
|
return _megagroupParticipantRemoved.events();
|
||||||
|
}
|
||||||
|
auto megagroupParticipantRemoved(
|
||||||
|
not_null<ChannelData*> channel) const {
|
||||||
|
return megagroupParticipantRemoved()
|
||||||
|
| rpl::filter([channel](auto updateChannel, auto user) {
|
||||||
|
return (updateChannel == channel);
|
||||||
|
})
|
||||||
|
| rpl::map([](auto updateChannel, auto user) {
|
||||||
|
return user;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
void addNewMegagroupParticipant(
|
||||||
|
not_null<ChannelData*> channel,
|
||||||
|
not_null<UserData*> user) {
|
||||||
|
_megagroupParticipantAdded.fire({ channel, user });
|
||||||
|
}
|
||||||
|
auto megagroupParticipantAdded() const {
|
||||||
|
return _megagroupParticipantAdded.events();
|
||||||
|
}
|
||||||
|
auto megagroupParticipantAdded(
|
||||||
|
not_null<ChannelData*> channel) const {
|
||||||
|
return megagroupParticipantAdded()
|
||||||
|
| rpl::filter([channel](auto updateChannel, auto user) {
|
||||||
|
return (updateChannel == channel);
|
||||||
|
})
|
||||||
|
| rpl::map([](auto updateChannel, auto user) {
|
||||||
|
return user;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void copyFrom(const AuthSessionData &other) {
|
void copyFrom(const AuthSessionData &other) {
|
||||||
_variables = other._variables;
|
_variables = other._variables;
|
||||||
|
@ -207,6 +247,8 @@ private:
|
||||||
rpl::event_stream<not_null<const HistoryItem*>> _itemLayoutChanged;
|
rpl::event_stream<not_null<const HistoryItem*>> _itemLayoutChanged;
|
||||||
rpl::event_stream<not_null<const HistoryItem*>> _itemRepaintRequest;
|
rpl::event_stream<not_null<const HistoryItem*>> _itemRepaintRequest;
|
||||||
rpl::event_stream<not_null<const HistoryItem*>> _itemRemoved;
|
rpl::event_stream<not_null<const HistoryItem*>> _itemRemoved;
|
||||||
|
rpl::event_stream<MegagroupParticipant> _megagroupParticipantRemoved;
|
||||||
|
rpl::event_stream<MegagroupParticipant> _megagroupParticipantAdded;
|
||||||
|
|
||||||
rpl::event_stream<bool> _thirdSectionInfoEnabledValue;
|
rpl::event_stream<bool> _thirdSectionInfoEnabledValue;
|
||||||
bool _tabbedReplacedWithInfo = false;
|
bool _tabbedReplacedWithInfo = false;
|
||||||
|
|
|
@ -29,6 +29,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "ui/widgets/multi_select.h"
|
#include "ui/widgets/multi_select.h"
|
||||||
#include "ui/widgets/labels.h"
|
#include "ui/widgets/labels.h"
|
||||||
#include "ui/widgets/scroll_area.h"
|
#include "ui/widgets/scroll_area.h"
|
||||||
|
#include "ui/widgets/popup_menu.h"
|
||||||
#include "ui/effects/round_checkbox.h"
|
#include "ui/effects/round_checkbox.h"
|
||||||
#include "ui/effects/ripple_animation.h"
|
#include "ui/effects/ripple_animation.h"
|
||||||
#include "ui/wrap/slide_wrap.h"
|
#include "ui/wrap/slide_wrap.h"
|
||||||
|
@ -863,7 +864,10 @@ void PeerListContent::leaveEventHook(QEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerListContent::mouseMoveEvent(QMouseEvent *e) {
|
void PeerListContent::mouseMoveEvent(QMouseEvent *e) {
|
||||||
auto position = e->globalPos();
|
handleMouseMove(e->globalPos());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeerListContent::handleMouseMove(QPoint position) {
|
||||||
if (_mouseSelection || _lastMousePosition != position) {
|
if (_mouseSelection || _lastMousePosition != position) {
|
||||||
_lastMousePosition = position;
|
_lastMousePosition = position;
|
||||||
_mouseSelection = true;
|
_mouseSelection = true;
|
||||||
|
@ -872,6 +876,7 @@ void PeerListContent::mouseMoveEvent(QMouseEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerListContent::mousePressEvent(QMouseEvent *e) {
|
void PeerListContent::mousePressEvent(QMouseEvent *e) {
|
||||||
|
_pressButton = e->button();
|
||||||
_mouseSelection = true;
|
_mouseSelection = true;
|
||||||
_lastMousePosition = e->globalPos();
|
_lastMousePosition = e->globalPos();
|
||||||
updateSelection();
|
updateSelection();
|
||||||
|
@ -896,12 +901,16 @@ void PeerListContent::mousePressEvent(QMouseEvent *e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void PeerListContent::mouseReleaseEvent(QMouseEvent *e) {
|
void PeerListContent::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
|
mousePressReleased(e->button());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PeerListContent::mousePressReleased(Qt::MouseButton button) {
|
||||||
updateRow(_pressed.index);
|
updateRow(_pressed.index);
|
||||||
updateRow(_selected.index);
|
updateRow(_selected.index);
|
||||||
|
|
||||||
auto pressed = _pressed;
|
auto pressed = _pressed;
|
||||||
setPressed(Selected());
|
setPressed(Selected());
|
||||||
if (e->button() == Qt::LeftButton && pressed == _selected) {
|
if (button == Qt::LeftButton && pressed == _selected) {
|
||||||
if (auto row = getRow(pressed.index)) {
|
if (auto row = getRow(pressed.index)) {
|
||||||
if (pressed.action) {
|
if (pressed.action) {
|
||||||
_controller->rowActionClicked(row);
|
_controller->rowActionClicked(row);
|
||||||
|
@ -912,6 +921,41 @@ void PeerListContent::mouseReleaseEvent(QMouseEvent *e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PeerListContent::contextMenuEvent(QContextMenuEvent *e) {
|
||||||
|
if (_menu) {
|
||||||
|
_menu->deleteLater();
|
||||||
|
_menu = nullptr;
|
||||||
|
}
|
||||||
|
if (_context.index.value >= 0) {
|
||||||
|
updateRow(_context.index);
|
||||||
|
_context = Selected();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e->reason() == QContextMenuEvent::Mouse) {
|
||||||
|
handleMouseMove(e->globalPos());
|
||||||
|
}
|
||||||
|
|
||||||
|
_context = _selected;
|
||||||
|
if (_pressButton != Qt::LeftButton) {
|
||||||
|
mousePressReleased(_pressButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto row = getRow(_context.index)) {
|
||||||
|
_menu = _controller->rowContextMenu(row);
|
||||||
|
if (_menu) {
|
||||||
|
_menu->setDestroyedCallback(base::lambda_guarded(
|
||||||
|
this,
|
||||||
|
[this] {
|
||||||
|
updateRow(_context.index);
|
||||||
|
_context = Selected();
|
||||||
|
handleMouseMove(QCursor::pos());
|
||||||
|
}));
|
||||||
|
_menu->popup(e->globalPos());
|
||||||
|
e->accept();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PeerListContent::setPressed(Selected pressed) {
|
void PeerListContent::setPressed(Selected pressed) {
|
||||||
if (auto row = getRow(_pressed.index)) {
|
if (auto row = getRow(_pressed.index)) {
|
||||||
row->stopLastRipple();
|
row->stopLastRipple();
|
||||||
|
@ -933,7 +977,11 @@ TimeMs PeerListContent::paintRow(Painter &p, TimeMs ms, RowIndex index) {
|
||||||
|
|
||||||
auto peer = row->peer();
|
auto peer = row->peer();
|
||||||
auto user = peer->asUser();
|
auto user = peer->asUser();
|
||||||
auto active = (_pressed.index.value >= 0) ? _pressed : _selected;
|
auto active = (_context.index.value >= 0)
|
||||||
|
? _context
|
||||||
|
: (_pressed.index.value >= 0)
|
||||||
|
? _pressed
|
||||||
|
: _selected;
|
||||||
auto selected = (active.index == index);
|
auto selected = (active.index == index);
|
||||||
auto actionSelected = (selected && active.action);
|
auto actionSelected = (selected && active.action);
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@ template <typename Widget>
|
||||||
class SlideWrap;
|
class SlideWrap;
|
||||||
class FlatLabel;
|
class FlatLabel;
|
||||||
struct ScrollToRequest;
|
struct ScrollToRequest;
|
||||||
|
class PopupMenu;
|
||||||
} // namespace Ui
|
} // namespace Ui
|
||||||
|
|
||||||
namespace Notify {
|
namespace Notify {
|
||||||
|
@ -238,8 +239,8 @@ public:
|
||||||
virtual void peerListScrollToTop() = 0;
|
virtual void peerListScrollToTop() = 0;
|
||||||
virtual int peerListFullRowsCount() = 0;
|
virtual int peerListFullRowsCount() = 0;
|
||||||
virtual PeerListRow *peerListFindRow(PeerListRowId id) = 0;
|
virtual PeerListRow *peerListFindRow(PeerListRowId id) = 0;
|
||||||
virtual void peerListSortRows(base::lambda<bool(PeerListRow &a, PeerListRow &b)> compare) = 0;
|
virtual void peerListSortRows(base::lambda<bool(const PeerListRow &a, const PeerListRow &b)> compare) = 0;
|
||||||
virtual int peerListPartitionRows(base::lambda<bool(PeerListRow &a)> border) = 0;
|
virtual int peerListPartitionRows(base::lambda<bool(const PeerListRow &a)> border) = 0;
|
||||||
|
|
||||||
template <typename PeerDataRange>
|
template <typename PeerDataRange>
|
||||||
void peerListAddSelectedRows(PeerDataRange &&range) {
|
void peerListAddSelectedRows(PeerDataRange &&range) {
|
||||||
|
@ -306,6 +307,10 @@ public:
|
||||||
}
|
}
|
||||||
virtual void itemDeselectedHook(not_null<PeerData*> peer) {
|
virtual void itemDeselectedHook(not_null<PeerData*> peer) {
|
||||||
}
|
}
|
||||||
|
virtual Ui::PopupMenu *rowContextMenu(
|
||||||
|
not_null<PeerListRow*> row) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
bool isSearchLoading() const {
|
bool isSearchLoading() const {
|
||||||
return _searchController ? _searchController->isLoading() : false;
|
return _searchController ? _searchController->isLoading() : false;
|
||||||
}
|
}
|
||||||
|
@ -429,6 +434,7 @@ protected:
|
||||||
void mouseMoveEvent(QMouseEvent *e) override;
|
void mouseMoveEvent(QMouseEvent *e) override;
|
||||||
void mousePressEvent(QMouseEvent *e) override;
|
void mousePressEvent(QMouseEvent *e) override;
|
||||||
void mouseReleaseEvent(QMouseEvent *e) override;
|
void mouseReleaseEvent(QMouseEvent *e) override;
|
||||||
|
void contextMenuEvent(QContextMenuEvent *e) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void refreshIndices();
|
void refreshIndices();
|
||||||
|
@ -505,6 +511,8 @@ private:
|
||||||
int labelHeight() const;
|
int labelHeight() const;
|
||||||
|
|
||||||
void clearSearchRows();
|
void clearSearchRows();
|
||||||
|
void handleMouseMove(QPoint position);
|
||||||
|
void mousePressReleased(Qt::MouseButton button);
|
||||||
|
|
||||||
const style::PeerList &_st;
|
const style::PeerList &_st;
|
||||||
not_null<PeerListController*> _controller;
|
not_null<PeerListController*> _controller;
|
||||||
|
@ -516,7 +524,9 @@ private:
|
||||||
|
|
||||||
Selected _selected;
|
Selected _selected;
|
||||||
Selected _pressed;
|
Selected _pressed;
|
||||||
|
Selected _context;
|
||||||
bool _mouseSelection = false;
|
bool _mouseSelection = false;
|
||||||
|
Qt::MouseButton _pressButton = Qt::LeftButton;
|
||||||
|
|
||||||
rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests;
|
rpl::event_stream<Ui::ScrollToRequest> _scrollToRequests;
|
||||||
|
|
||||||
|
@ -540,6 +550,7 @@ private:
|
||||||
|
|
||||||
std::vector<std::unique_ptr<PeerListRow>> _searchRows;
|
std::vector<std::unique_ptr<PeerListRow>> _searchRows;
|
||||||
base::Timer _repaintByStatus;
|
base::Timer _repaintByStatus;
|
||||||
|
QPointer<Ui::PopupMenu> _menu;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -615,7 +626,7 @@ public:
|
||||||
_content->setSearchMode(mode);
|
_content->setSearchMode(mode);
|
||||||
}
|
}
|
||||||
void peerListSortRows(
|
void peerListSortRows(
|
||||||
base::lambda<bool(PeerListRow &a, PeerListRow &b)> compare) override {
|
base::lambda<bool(const PeerListRow &a, const PeerListRow &b)> compare) override {
|
||||||
_content->reorderRows([compare = std::move(compare)](
|
_content->reorderRows([compare = std::move(compare)](
|
||||||
auto &&begin,
|
auto &&begin,
|
||||||
auto &&end) {
|
auto &&end) {
|
||||||
|
@ -625,7 +636,7 @@ public:
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
int peerListPartitionRows(
|
int peerListPartitionRows(
|
||||||
base::lambda<bool(PeerListRow &a)> border) override {
|
base::lambda<bool(const PeerListRow &a)> border) override {
|
||||||
auto result = 0;
|
auto result = 0;
|
||||||
_content->reorderRows([border = std::move(border), &result](
|
_content->reorderRows([border = std::move(border), &result](
|
||||||
auto &&begin,
|
auto &&begin,
|
||||||
|
|
|
@ -243,8 +243,8 @@ void ChatsListBoxController::rebuildRows() {
|
||||||
added += appendList(App::main()->contactsNoDialogsList());
|
added += appendList(App::main()->contactsNoDialogsList());
|
||||||
if (!wasEmpty && added > 0) {
|
if (!wasEmpty && added > 0) {
|
||||||
// Place dialogs list before contactsNoDialogs list.
|
// Place dialogs list before contactsNoDialogs list.
|
||||||
delegate()->peerListPartitionRows([](PeerListRow &a) {
|
delegate()->peerListPartitionRows([](const PeerListRow &a) {
|
||||||
auto history = static_cast<Row&>(a).history();
|
auto history = static_cast<const Row&>(a).history();
|
||||||
return history->inChatList(Dialogs::Mode::All);
|
return history->inChatList(Dialogs::Mode::All);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -303,8 +303,11 @@ bool BoxController::insertRow(
|
||||||
(way == InsertWay::Append)
|
(way == InsertWay::Append)
|
||||||
? delegate()->peerListAppendRow(createRow(item))
|
? delegate()->peerListAppendRow(createRow(item))
|
||||||
: delegate()->peerListPrependRow(createRow(item));
|
: delegate()->peerListPrependRow(createRow(item));
|
||||||
delegate()->peerListSortRows([](PeerListRow &a, PeerListRow &b) {
|
delegate()->peerListSortRows([](
|
||||||
return static_cast<Row&>(a).maxItemId() > static_cast<Row&>(b).maxItemId();
|
const PeerListRow &a,
|
||||||
|
const PeerListRow &b) {
|
||||||
|
return static_cast<const Row&>(a).maxItemId()
|
||||||
|
> static_cast<const Row&>(b).maxItemId();
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -915,6 +915,7 @@ void ChannelData::applyEditBanned(not_null<UserData*> user, const MTPChannelBann
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
flags |= Notify::PeerUpdate::Flag::MembersChanged;
|
flags |= Notify::PeerUpdate::Flag::MembersChanged;
|
||||||
|
Auth().data().removeMegagroupParticipant(this, user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ template <
|
||||||
typename = typename PeerType::FullFlags::Change>
|
typename = typename PeerType::FullFlags::Change>
|
||||||
inline auto PeerFullFlagsValue(PeerType *peer) {
|
inline auto PeerFullFlagsValue(PeerType *peer) {
|
||||||
Expects(peer != nullptr);
|
Expects(peer != nullptr);
|
||||||
return peer->flagsValue();
|
return peer->fullFlagsValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <
|
template <
|
||||||
|
|
|
@ -933,14 +933,17 @@ HistoryItem *History::createItem(const MTPMessage &msg, bool applyServiceAction,
|
||||||
switch (action.type()) {
|
switch (action.type()) {
|
||||||
case mtpc_messageActionChatAddUser: {
|
case mtpc_messageActionChatAddUser: {
|
||||||
auto &d = action.c_messageActionChatAddUser();
|
auto &d = action.c_messageActionChatAddUser();
|
||||||
if (peer->isMegagroup()) {
|
if (auto megagroup = peer->asMegagroup()) {
|
||||||
|
auto mgInfo = megagroup->mgInfo.get();
|
||||||
|
Assert(mgInfo != nullptr);
|
||||||
auto &v = d.vusers.v;
|
auto &v = d.vusers.v;
|
||||||
for (auto i = 0, l = v.size(); i != l; ++i) {
|
for (auto i = 0, l = v.size(); i != l; ++i) {
|
||||||
if (auto user = App::userLoaded(peerFromUser(v[i]))) {
|
if (auto user = App::userLoaded(peerFromUser(v[i]))) {
|
||||||
if (peer->asChannel()->mgInfo->lastParticipants.indexOf(user) < 0) {
|
if (mgInfo->lastParticipants.indexOf(user) < 0) {
|
||||||
peer->asChannel()->mgInfo->lastParticipants.push_front(user);
|
mgInfo->lastParticipants.push_front(user);
|
||||||
peer->asChannel()->mgInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsAdminsOutdated;
|
mgInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsAdminsOutdated;
|
||||||
Notify::peerUpdatedDelayed(peer, Notify::PeerUpdate::Flag::MembersChanged);
|
Notify::peerUpdatedDelayed(peer, Notify::PeerUpdate::Flag::MembersChanged);
|
||||||
|
Auth().data().addNewMegagroupParticipant(megagroup, user);
|
||||||
}
|
}
|
||||||
if (user->botInfo) {
|
if (user->botInfo) {
|
||||||
peer->asChannel()->mgInfo->bots.insert(user);
|
peer->asChannel()->mgInfo->bots.insert(user);
|
||||||
|
@ -955,16 +958,19 @@ HistoryItem *History::createItem(const MTPMessage &msg, bool applyServiceAction,
|
||||||
|
|
||||||
case mtpc_messageActionChatJoinedByLink: {
|
case mtpc_messageActionChatJoinedByLink: {
|
||||||
auto &d = action.c_messageActionChatJoinedByLink();
|
auto &d = action.c_messageActionChatJoinedByLink();
|
||||||
if (peer->isMegagroup()) {
|
if (auto megagroup = peer->asMegagroup()) {
|
||||||
if (result->from()->isUser()) {
|
auto mgInfo = megagroup->mgInfo.get();
|
||||||
if (peer->asChannel()->mgInfo->lastParticipants.indexOf(result->from()->asUser()) < 0) {
|
Assert(mgInfo != nullptr);
|
||||||
peer->asChannel()->mgInfo->lastParticipants.push_front(result->from()->asUser());
|
if (auto user = result->from()->asUser()) {
|
||||||
|
if (mgInfo->lastParticipants.indexOf(user) < 0) {
|
||||||
|
mgInfo->lastParticipants.push_front(user);
|
||||||
Notify::peerUpdatedDelayed(peer, Notify::PeerUpdate::Flag::MembersChanged);
|
Notify::peerUpdatedDelayed(peer, Notify::PeerUpdate::Flag::MembersChanged);
|
||||||
|
Auth().data().addNewMegagroupParticipant(megagroup, user);
|
||||||
}
|
}
|
||||||
if (result->from()->asUser()->botInfo) {
|
if (user->botInfo) {
|
||||||
peer->asChannel()->mgInfo->bots.insert(result->from()->asUser());
|
mgInfo->bots.insert(user);
|
||||||
if (peer->asChannel()->mgInfo->botStatus != 0 && peer->asChannel()->mgInfo->botStatus < 2) {
|
if (mgInfo->botStatus != 0 && mgInfo->botStatus < 2) {
|
||||||
peer->asChannel()->mgInfo->botStatus = 2;
|
mgInfo->botStatus = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -982,32 +988,32 @@ HistoryItem *History::createItem(const MTPMessage &msg, bool applyServiceAction,
|
||||||
if (lastKeyboardFrom == uid) {
|
if (lastKeyboardFrom == uid) {
|
||||||
clearLastKeyboard();
|
clearLastKeyboard();
|
||||||
}
|
}
|
||||||
if (peer->isMegagroup()) {
|
if (auto megagroup = peer->asMegagroup()) {
|
||||||
if (auto user = App::userLoaded(uid)) {
|
if (auto user = App::userLoaded(uid)) {
|
||||||
auto channel = peer->asChannel();
|
auto mgInfo = megagroup->mgInfo.get();
|
||||||
auto &megagroupInfo = channel->mgInfo;
|
Assert(mgInfo != nullptr);
|
||||||
|
auto index = mgInfo->lastParticipants.indexOf(user);
|
||||||
auto index = megagroupInfo->lastParticipants.indexOf(user);
|
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
megagroupInfo->lastParticipants.removeAt(index);
|
mgInfo->lastParticipants.removeAt(index);
|
||||||
Notify::peerUpdatedDelayed(peer, Notify::PeerUpdate::Flag::MembersChanged);
|
Notify::peerUpdatedDelayed(peer, Notify::PeerUpdate::Flag::MembersChanged);
|
||||||
}
|
}
|
||||||
if (peer->asChannel()->membersCount() > 1) {
|
Auth().data().removeMegagroupParticipant(megagroup, user);
|
||||||
peer->asChannel()->setMembersCount(channel->membersCount() - 1);
|
if (megagroup->membersCount() > 1) {
|
||||||
|
megagroup->setMembersCount(megagroup->membersCount() - 1);
|
||||||
} else {
|
} else {
|
||||||
megagroupInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsCountOutdated;
|
mgInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsCountOutdated;
|
||||||
megagroupInfo->lastParticipantsCount = 0;
|
mgInfo->lastParticipantsCount = 0;
|
||||||
}
|
}
|
||||||
if (megagroupInfo->lastAdmins.contains(user)) {
|
if (mgInfo->lastAdmins.contains(user)) {
|
||||||
megagroupInfo->lastAdmins.remove(user);
|
mgInfo->lastAdmins.remove(user);
|
||||||
if (channel->adminsCount() > 1) {
|
if (megagroup->adminsCount() > 1) {
|
||||||
channel->setAdminsCount(channel->adminsCount() - 1);
|
megagroup->setAdminsCount(megagroup->adminsCount() - 1);
|
||||||
}
|
}
|
||||||
Notify::peerUpdatedDelayed(peer, Notify::PeerUpdate::Flag::AdminsChanged);
|
Notify::peerUpdatedDelayed(peer, Notify::PeerUpdate::Flag::AdminsChanged);
|
||||||
}
|
}
|
||||||
megagroupInfo->bots.remove(user);
|
mgInfo->bots.remove(user);
|
||||||
if (megagroupInfo->bots.isEmpty() && megagroupInfo->botStatus > 0) {
|
if (mgInfo->bots.isEmpty() && mgInfo->botStatus > 0) {
|
||||||
megagroupInfo->botStatus = -1;
|
mgInfo->botStatus = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1294,26 +1300,29 @@ HistoryItem *History::addNewItem(HistoryItem *adding, bool newMsg) {
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
};
|
};
|
||||||
if (auto channel = peer->asMegagroup()) {
|
if (auto megagroup = peer->asMegagroup()) {
|
||||||
if (adding->from()->asUser()->botInfo) {
|
if (user->botInfo) {
|
||||||
channel->mgInfo->bots.insert(adding->from()->asUser());
|
auto mgInfo = megagroup->mgInfo.get();
|
||||||
if (channel->mgInfo->botStatus != 0 && channel->mgInfo->botStatus < 2) {
|
Assert(mgInfo != nullptr);
|
||||||
channel->mgInfo->botStatus = 2;
|
mgInfo->bots.insert(user);
|
||||||
|
if (mgInfo->botStatus != 0 && mgInfo->botStatus < 2) {
|
||||||
|
mgInfo->botStatus = 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (auto lastAuthors = getLastAuthors()) {
|
if (auto lastAuthors = getLastAuthors()) {
|
||||||
int prev = lastAuthors->indexOf(adding->from()->asUser());
|
int prev = lastAuthors->indexOf(user);
|
||||||
if (prev > 0) {
|
if (prev > 0) {
|
||||||
lastAuthors->removeAt(prev);
|
lastAuthors->removeAt(prev);
|
||||||
} else if (prev < 0 && peer->isMegagroup()) { // nothing is outdated if just reordering
|
} else if (prev < 0 && peer->isMegagroup()) { // nothing is outdated if just reordering
|
||||||
peer->asChannel()->mgInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsAdminsOutdated;
|
peer->asChannel()->mgInfo->lastParticipantsStatus |= MegagroupInfo::LastParticipantsAdminsOutdated;
|
||||||
}
|
}
|
||||||
if (prev) {
|
if (prev) {
|
||||||
lastAuthors->push_front(adding->from()->asUser());
|
lastAuthors->push_front(user);
|
||||||
}
|
}
|
||||||
if (peer->isMegagroup()) {
|
if (auto megagroup = peer->asMegagroup()) {
|
||||||
Notify::peerUpdatedDelayed(peer, Notify::PeerUpdate::Flag::MembersChanged);
|
Notify::peerUpdatedDelayed(peer, Notify::PeerUpdate::Flag::MembersChanged);
|
||||||
|
Auth().data().addNewMegagroupParticipant(megagroup, user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,15 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "info/profile/info_profile_members_controllers.h"
|
#include "info/profile/info_profile_members_controllers.h"
|
||||||
|
|
||||||
#include <rpl/variable.h>
|
#include <rpl/variable.h>
|
||||||
|
#include "base/weak_unique_ptr.h"
|
||||||
#include "profile/profile_channel_controllers.h"
|
#include "profile/profile_channel_controllers.h"
|
||||||
|
#include "ui/widgets/popup_menu.h"
|
||||||
#include "lang/lang_keys.h"
|
#include "lang/lang_keys.h"
|
||||||
#include "apiwrap.h"
|
#include "apiwrap.h"
|
||||||
#include "auth_session.h"
|
#include "auth_session.h"
|
||||||
|
#include "mainwidget.h"
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
|
#include "boxes/confirm_box.h"
|
||||||
#include "window/window_controller.h"
|
#include "window/window_controller.h"
|
||||||
|
|
||||||
namespace Info {
|
namespace Info {
|
||||||
|
@ -36,7 +40,8 @@ constexpr auto kSortByOnlineDelay = TimeMs(1000);
|
||||||
|
|
||||||
class ChatMembersController
|
class ChatMembersController
|
||||||
: public PeerListController
|
: public PeerListController
|
||||||
, private base::Subscriber {
|
, private base::Subscriber
|
||||||
|
, public base::enable_weak_from_this {
|
||||||
public:
|
public:
|
||||||
ChatMembersController(
|
ChatMembersController(
|
||||||
not_null<Window::Controller*> window,
|
not_null<Window::Controller*> window,
|
||||||
|
@ -44,6 +49,8 @@ public:
|
||||||
|
|
||||||
void prepare() override;
|
void prepare() override;
|
||||||
void rowClicked(not_null<PeerListRow*> row) override;
|
void rowClicked(not_null<PeerListRow*> row) override;
|
||||||
|
Ui::PopupMenu *rowContextMenu(
|
||||||
|
not_null<PeerListRow*> row) override;
|
||||||
|
|
||||||
rpl::producer<int> onlineCountValue() const override {
|
rpl::producer<int> onlineCountValue() const override {
|
||||||
return _onlineCount.value();
|
return _onlineCount.value();
|
||||||
|
@ -55,6 +62,7 @@ private:
|
||||||
std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user);
|
std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user);
|
||||||
void sortByOnline();
|
void sortByOnline();
|
||||||
void sortByOnlineDelayed();
|
void sortByOnlineDelayed();
|
||||||
|
void removeMember(not_null<UserData*> user);
|
||||||
|
|
||||||
not_null<Window::Controller*> _window;
|
not_null<Window::Controller*> _window;
|
||||||
not_null<ChatData*> _chat;
|
not_null<ChatData*> _chat;
|
||||||
|
@ -119,27 +127,33 @@ void ChatMembersController::sortByOnline() {
|
||||||
|
|
||||||
void ChatMembersController::rebuildRows() {
|
void ChatMembersController::rebuildRows() {
|
||||||
if (_chat->participants.empty()) {
|
if (_chat->participants.empty()) {
|
||||||
|
while (delegate()->peerListFullRowsCount() > 0) {
|
||||||
|
delegate()->peerListRemoveRow(
|
||||||
|
delegate()->peerListRowAt(0));
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<not_null<UserData*>> users;
|
|
||||||
auto &participants = _chat->participants;
|
auto &participants = _chat->participants;
|
||||||
for (auto i = participants.cbegin(), e = participants.cend();
|
for (auto i = 0, count = delegate()->peerListFullRowsCount();
|
||||||
i != e;
|
i != count;) {
|
||||||
++i) {
|
auto row = delegate()->peerListRowAt(i);
|
||||||
users.push_back(i.key());
|
auto user = row->peer()->asUser();
|
||||||
|
if (participants.contains(user)) {
|
||||||
|
++i;
|
||||||
|
} else {
|
||||||
|
delegate()->peerListRemoveRow(row);
|
||||||
|
--count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
auto now = unixtime();
|
for (auto i = participants.cbegin(), e = participants.cend();
|
||||||
base::sort(users, [now](auto a, auto b) {
|
i != e;
|
||||||
return App::onlineForSort(a, now)
|
++i) {
|
||||||
> App::onlineForSort(b, now);
|
if (auto row = createRow(i.key())) {
|
||||||
});
|
|
||||||
base::for_each(users, [this](not_null<UserData*> user) {
|
|
||||||
if (auto row = createRow(user)) {
|
|
||||||
delegate()->peerListAppendRow(std::move(row));
|
delegate()->peerListAppendRow(std::move(row));
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
refreshOnlineCount();
|
sortByOnline();
|
||||||
|
|
||||||
delegate()->peerListRefreshRows();
|
delegate()->peerListRefreshRows();
|
||||||
}
|
}
|
||||||
|
@ -167,6 +181,52 @@ void ChatMembersController::rowClicked(not_null<PeerListRow*> row) {
|
||||||
_window->showPeerInfo(row->peer());
|
_window->showPeerInfo(row->peer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ui::PopupMenu *ChatMembersController::rowContextMenu(
|
||||||
|
not_null<PeerListRow*> row) {
|
||||||
|
Expects(row->peer()->isUser());
|
||||||
|
|
||||||
|
auto user = row->peer()->asUser();
|
||||||
|
auto isCreator = (peerFromUser(_chat->creator) == user->id);
|
||||||
|
auto isAdmin = _chat->adminsEnabled() && _chat->admins.contains(user);
|
||||||
|
auto canRemoveMember = (user->id == Auth().userPeerId())
|
||||||
|
? false
|
||||||
|
: _chat->amCreator()
|
||||||
|
? true
|
||||||
|
: (_chat->amAdmin() && !isCreator && !isAdmin)
|
||||||
|
? true
|
||||||
|
: (_chat->invitedByMe.contains(user) && !isCreator && !isAdmin)
|
||||||
|
? true
|
||||||
|
: false;
|
||||||
|
|
||||||
|
auto result = new Ui::PopupMenu(nullptr);
|
||||||
|
result->addAction(
|
||||||
|
lang(lng_context_view_profile),
|
||||||
|
[weak = base::make_weak_unique(this), user] {
|
||||||
|
if (weak) {
|
||||||
|
weak->_window->showPeerInfo(user);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (canRemoveMember) {
|
||||||
|
result->addAction(
|
||||||
|
lang(lng_context_remove_from_group),
|
||||||
|
[weak = base::make_weak_unique(this), user] {
|
||||||
|
if (weak) {
|
||||||
|
weak->removeMember(user);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChatMembersController::removeMember(not_null<UserData*> user) {
|
||||||
|
auto text = lng_profile_sure_kick(lt_user, user->firstName);
|
||||||
|
Ui::show(Box<ConfirmBox>(text, lang(lng_box_remove), [user, chat = _chat] {
|
||||||
|
Ui::hideLayer();
|
||||||
|
if (App::main()) App::main()->kickParticipant(chat, user);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
std::unique_ptr<PeerListController> CreateMembersController(
|
std::unique_ptr<PeerListController> CreateMembersController(
|
||||||
|
|
|
@ -27,6 +27,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
#include "messenger.h"
|
#include "messenger.h"
|
||||||
#include "ui/wrap/slide_wrap.h"
|
#include "ui/wrap/slide_wrap.h"
|
||||||
|
#include "data/data_peer_values.h"
|
||||||
#include "history/history_shared_media.h"
|
#include "history/history_shared_media.h"
|
||||||
|
|
||||||
namespace Info {
|
namespace Info {
|
||||||
|
@ -174,9 +175,13 @@ rpl::producer<int> MembersCountValue(
|
||||||
: 0;
|
: 0;
|
||||||
});
|
});
|
||||||
} else if (auto channel = peer->asChannel()) {
|
} else if (auto channel = peer->asChannel()) {
|
||||||
return PeerUpdateValue(
|
return rpl::combine(
|
||||||
peer,
|
PeerUpdateValue(
|
||||||
Notify::PeerUpdate::Flag::MembersChanged)
|
channel,
|
||||||
|
Notify::PeerUpdate::Flag::MembersChanged),
|
||||||
|
Data::PeerFullFlagValue(
|
||||||
|
channel,
|
||||||
|
MTPDchannelFull::Flag::f_can_view_participants))
|
||||||
| rpl::map([channel] {
|
| rpl::map([channel] {
|
||||||
auto canViewCount = channel->canViewMembers()
|
auto canViewCount = channel->canViewMembers()
|
||||||
|| !channel->isMegagroup();
|
|| !channel->isMegagroup();
|
||||||
|
|
|
@ -30,6 +30,7 @@ Copyright (c) 2014-2017 John Preston, https://desktop.telegram.org
|
||||||
#include "mainwidget.h"
|
#include "mainwidget.h"
|
||||||
#include "observer_peer.h"
|
#include "observer_peer.h"
|
||||||
#include "dialogs/dialogs_indexed_list.h"
|
#include "dialogs/dialogs_indexed_list.h"
|
||||||
|
#include "ui/widgets/popup_menu.h"
|
||||||
#include "window/window_controller.h"
|
#include "window/window_controller.h"
|
||||||
|
|
||||||
namespace Profile {
|
namespace Profile {
|
||||||
|
@ -54,6 +55,7 @@ ParticipantsBoxController::ParticipantsBoxController(
|
||||||
}
|
}
|
||||||
if (_role == Role::Profile) {
|
if (_role == Role::Profile) {
|
||||||
setupSortByOnline();
|
setupSortByOnline();
|
||||||
|
setupListChangeViewers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +73,33 @@ void ParticipantsBoxController::setupSortByOnline() {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ParticipantsBoxController::setupListChangeViewers() {
|
||||||
|
Auth().data().megagroupParticipantAdded(_channel)
|
||||||
|
| rpl::start_with_next([this](not_null<UserData*> user) {
|
||||||
|
if (delegate()->peerListFullRowsCount() > 0) {
|
||||||
|
if (delegate()->peerListRowAt(0)->peer() == user) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (auto row = delegate()->peerListFindRow(user->id)) {
|
||||||
|
delegate()->peerListPartitionRows([user](const PeerListRow &row) {
|
||||||
|
return (row.peer() == user);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
delegate()->peerListPrependRow(createRow(user));
|
||||||
|
delegate()->peerListRefreshRows();
|
||||||
|
sortByOnline();
|
||||||
|
}
|
||||||
|
}, lifetime());
|
||||||
|
Auth().data().megagroupParticipantRemoved(_channel)
|
||||||
|
| rpl::start_with_next([this](not_null<UserData*> user) {
|
||||||
|
if (auto row = delegate()->peerListFindRow(user->id)) {
|
||||||
|
delegate()->peerListRemoveRow(row);
|
||||||
|
}
|
||||||
|
delegate()->peerListRefreshRows();
|
||||||
|
}, lifetime());
|
||||||
|
}
|
||||||
|
|
||||||
void ParticipantsBoxController::sortByOnlineDelayed() {
|
void ParticipantsBoxController::sortByOnlineDelayed() {
|
||||||
if (!_sortByOnlineTimer.isActive()) {
|
if (!_sortByOnlineTimer.isActive()) {
|
||||||
_sortByOnlineTimer.callOnce(kSortByOnlineDelay);
|
_sortByOnlineTimer.callOnce(kSortByOnlineDelay);
|
||||||
|
@ -366,6 +395,7 @@ bool ParticipantsBoxController::feedMegagroupLastParticipants() {
|
||||||
}
|
}
|
||||||
auto info = megagroup->mgInfo.get();
|
auto info = megagroup->mgInfo.get();
|
||||||
if (info->lastParticipantsStatus != MegagroupInfo::LastParticipantsUpToDate) {
|
if (info->lastParticipantsStatus != MegagroupInfo::LastParticipantsUpToDate) {
|
||||||
|
_channel->updateFull();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (info->lastParticipants.isEmpty()) {
|
if (info->lastParticipants.isEmpty()) {
|
||||||
|
@ -430,6 +460,53 @@ void ParticipantsBoxController::rowActionClicked(not_null<PeerListRow*> row) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ui::PopupMenu *ParticipantsBoxController::rowContextMenu(
|
||||||
|
not_null<PeerListRow*> row) {
|
||||||
|
Expects(row->peer()->isUser());
|
||||||
|
|
||||||
|
auto user = row->peer()->asUser();
|
||||||
|
auto result = new Ui::PopupMenu(nullptr);
|
||||||
|
result->addAction(
|
||||||
|
lang(lng_context_view_profile),
|
||||||
|
[weak = base::make_weak_unique(this), user] {
|
||||||
|
if (weak) {
|
||||||
|
weak->_window->showPeerInfo(user);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (_channel->canEditAdmin(user)) {
|
||||||
|
auto it = _additional.adminRights.find(user);
|
||||||
|
auto isCreator = (user == _additional.creator);
|
||||||
|
auto notAdmin = !isCreator && (it == _additional.adminRights.cend());
|
||||||
|
auto label = lang(notAdmin
|
||||||
|
? lng_context_promote_admin
|
||||||
|
: lng_context_edit_permissions);
|
||||||
|
result->addAction(
|
||||||
|
label,
|
||||||
|
[weak = base::make_weak_unique(this), user] {
|
||||||
|
if (weak) {
|
||||||
|
weak->showAdmin(user);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (_channel->canRestrictUser(user)) {
|
||||||
|
result->addAction(
|
||||||
|
lang(lng_context_restrict_user),
|
||||||
|
[weak = base::make_weak_unique(this), user]{
|
||||||
|
if (weak) {
|
||||||
|
weak->showRestricted(user);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
result->addAction(
|
||||||
|
lang(lng_context_remove_from_group),
|
||||||
|
[weak = base::make_weak_unique(this), user] {
|
||||||
|
if (weak) {
|
||||||
|
weak->kickMember(user);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void ParticipantsBoxController::showAdmin(not_null<UserData*> user) {
|
void ParticipantsBoxController::showAdmin(not_null<UserData*> user) {
|
||||||
auto it = _additional.adminRights.find(user);
|
auto it = _additional.adminRights.find(user);
|
||||||
auto isCreator = (user == _additional.creator);
|
auto isCreator = (user == _additional.creator);
|
||||||
|
@ -480,7 +557,7 @@ void ParticipantsBoxController::editAdminDone(not_null<UserData*> user, const MT
|
||||||
_additional.restrictedBy.erase(user);
|
_additional.restrictedBy.erase(user);
|
||||||
if (_role == Role::Admins) {
|
if (_role == Role::Admins) {
|
||||||
prependRow(user);
|
prependRow(user);
|
||||||
} else {
|
} else if (_role == Role::Kicked || _role == Role::Restricted) {
|
||||||
removeRow(user);
|
removeRow(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -489,12 +566,12 @@ void ParticipantsBoxController::editAdminDone(not_null<UserData*> user, const MT
|
||||||
|
|
||||||
void ParticipantsBoxController::showRestricted(not_null<UserData*> user) {
|
void ParticipantsBoxController::showRestricted(not_null<UserData*> user) {
|
||||||
auto it = _additional.restrictedRights.find(user);
|
auto it = _additional.restrictedRights.find(user);
|
||||||
if (it == _additional.restrictedRights.cend()) {
|
auto restrictedRights = (it == _additional.restrictedRights.cend())
|
||||||
return;
|
? MTP_channelBannedRights(MTP_flags(0), MTP_int(0))
|
||||||
}
|
: it->second;
|
||||||
auto weak = base::make_weak_unique(this);
|
auto weak = base::make_weak_unique(this);
|
||||||
auto hasAdminRights = false;
|
auto hasAdminRights = false;
|
||||||
auto box = Box<EditRestrictedBox>(_channel, user, hasAdminRights, it->second);
|
auto box = Box<EditRestrictedBox>(_channel, user, hasAdminRights, restrictedRights);
|
||||||
if (_channel->canBanMembers()) {
|
if (_channel->canBanMembers()) {
|
||||||
box->setSaveCallback([megagroup = _channel.get(), user, weak](const MTPChannelBannedRights &oldRights, const MTPChannelBannedRights &newRights) {
|
box->setSaveCallback([megagroup = _channel.get(), user, weak](const MTPChannelBannedRights &oldRights, const MTPChannelBannedRights &newRights) {
|
||||||
MTP::send(MTPchannels_EditBanned(megagroup->inputChannel, user->inputUser, newRights), rpcDone([megagroup, user, weak, oldRights, newRights](const MTPUpdates &result) {
|
MTP::send(MTPchannels_EditBanned(megagroup->inputChannel, user->inputUser, newRights), rpcDone([megagroup, user, weak, oldRights, newRights](const MTPUpdates &result) {
|
||||||
|
@ -522,7 +599,7 @@ void ParticipantsBoxController::editRestrictedDone(not_null<UserData*> user, con
|
||||||
_additional.kicked.erase(user);
|
_additional.kicked.erase(user);
|
||||||
_additional.restrictedRights.erase(user);
|
_additional.restrictedRights.erase(user);
|
||||||
_additional.restrictedBy.erase(user);
|
_additional.restrictedBy.erase(user);
|
||||||
if (_role != Role::Admins) {
|
if (_role == Role::Kicked || _role == Role::Restricted) {
|
||||||
removeRow(user);
|
removeRow(user);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -535,7 +612,9 @@ void ParticipantsBoxController::editRestrictedDone(not_null<UserData*> user, con
|
||||||
_additional.restrictedRights.erase(user);
|
_additional.restrictedRights.erase(user);
|
||||||
if (_role == Role::Kicked) {
|
if (_role == Role::Kicked) {
|
||||||
prependRow(user);
|
prependRow(user);
|
||||||
} else {
|
} else if (_role == Role::Admins
|
||||||
|
|| _role == Role::Restricted
|
||||||
|
|| _role == Role::Members) {
|
||||||
removeRow(user);
|
removeRow(user);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -543,7 +622,9 @@ void ParticipantsBoxController::editRestrictedDone(not_null<UserData*> user, con
|
||||||
_additional.kicked.erase(user);
|
_additional.kicked.erase(user);
|
||||||
if (_role == Role::Restricted) {
|
if (_role == Role::Restricted) {
|
||||||
prependRow(user);
|
prependRow(user);
|
||||||
} else {
|
} else if (_role == Role::Kicked
|
||||||
|
|| _role == Role::Admins
|
||||||
|
|| _role == Role::Members) {
|
||||||
removeRow(user);
|
removeRow(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,8 @@ public:
|
||||||
void prepare() override;
|
void prepare() override;
|
||||||
void rowClicked(not_null<PeerListRow*> row) override;
|
void rowClicked(not_null<PeerListRow*> row) override;
|
||||||
void rowActionClicked(not_null<PeerListRow*> row) override;
|
void rowActionClicked(not_null<PeerListRow*> row) override;
|
||||||
|
Ui::PopupMenu *rowContextMenu(
|
||||||
|
not_null<PeerListRow*> row) override;
|
||||||
void loadMoreRows() override;
|
void loadMoreRows() override;
|
||||||
|
|
||||||
void peerListSearchAddRow(not_null<PeerData*> peer) override;
|
void peerListSearchAddRow(not_null<PeerData*> peer) override;
|
||||||
|
@ -93,6 +95,7 @@ private:
|
||||||
static std::unique_ptr<PeerListSearchController> CreateSearchController(not_null<ChannelData*> channel, Role role, not_null<Additional*> additional);
|
static std::unique_ptr<PeerListSearchController> CreateSearchController(not_null<ChannelData*> channel, Role role, not_null<Additional*> additional);
|
||||||
|
|
||||||
void setupSortByOnline();
|
void setupSortByOnline();
|
||||||
|
void setupListChangeViewers();
|
||||||
void sortByOnlineDelayed();
|
void sortByOnlineDelayed();
|
||||||
void sortByOnline();
|
void sortByOnline();
|
||||||
void showAdmin(not_null<UserData*> user);
|
void showAdmin(not_null<UserData*> user);
|
||||||
|
|
|
@ -66,6 +66,14 @@ template <
|
||||||
true_t test_callable_tuple(
|
true_t test_callable_tuple(
|
||||||
Method &&,
|
Method &&,
|
||||||
std::tuple<Types...> &&) noexcept;
|
std::tuple<Types...> &&) noexcept;
|
||||||
|
template <
|
||||||
|
typename Method,
|
||||||
|
typename ...Types,
|
||||||
|
typename = decltype(std::declval<Method>()(
|
||||||
|
const_ref_val<Types>()...))>
|
||||||
|
true_t test_callable_tuple(
|
||||||
|
Method &&,
|
||||||
|
const std::tuple<Types...> &) noexcept;
|
||||||
false_t test_callable_tuple(...) noexcept;
|
false_t test_callable_tuple(...) noexcept;
|
||||||
|
|
||||||
template <typename Method, typename Arg>
|
template <typename Method, typename Arg>
|
||||||
|
|
|
@ -214,6 +214,25 @@ TEST_CASE("basic operators tests", "[rpl::operators]") {
|
||||||
REQUIRE(*sum == "1 1 3 ");
|
REQUIRE(*sum == "1 1 3 ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("filter tuple test") {
|
||||||
|
auto sum = std::make_shared<std::string>("");
|
||||||
|
{
|
||||||
|
auto lifetime = single(std::make_tuple(1, 2))
|
||||||
|
| then(single(std::make_tuple(1, 2)))
|
||||||
|
| then(single(std::make_tuple(2, 3)))
|
||||||
|
| then(single(std::make_tuple(2, 3)))
|
||||||
|
| then(single(std::make_tuple(3, 4)))
|
||||||
|
| filter([](auto first, auto second) { return first != 2; })
|
||||||
|
| map([](auto first, auto second) {
|
||||||
|
return std::to_string(second);
|
||||||
|
})
|
||||||
|
| start_with_next([=](std::string &&value) {
|
||||||
|
*sum += std::move(value) + ' ';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
REQUIRE(*sum == "2 2 4 ");
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("distinct_until_changed test") {
|
SECTION("distinct_until_changed test") {
|
||||||
auto sum = std::make_shared<std::string>("");
|
auto sum = std::make_shared<std::string>("");
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue