Support legacy groups in participant boxes.

This commit is contained in:
John Preston 2019-01-10 10:26:08 +04:00
parent 18c6be0d3b
commit a605c110a8
39 changed files with 3064 additions and 2649 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 354 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 737 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -811,6 +811,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_report_thanks" = "Thank you! Your report will be reviewed by our team very soon."; "lng_report_thanks" = "Thank you! Your report will be reviewed by our team very soon.";
"lng_channel_add_members" = "Add members"; "lng_channel_add_members" = "Add members";
"lng_channel_add_users" = "Add users";
"lng_channel_add_banned" = "Ban user"; "lng_channel_add_banned" = "Ban user";
"lng_channel_add_restricted" = "Restrict user"; "lng_channel_add_restricted" = "Restrict user";
"lng_channel_admins" = "Administrators"; "lng_channel_admins" = "Administrators";
@ -1510,6 +1511,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
"lng_restricted_send_stickers" = "The admins of this group restricted you from posting stickers here."; "lng_restricted_send_stickers" = "The admins of this group restricted you from posting stickers here.";
"lng_restricted_send_gifs" = "The admins of this group restricted you from posting GIFs here."; "lng_restricted_send_gifs" = "The admins of this group restricted you from posting GIFs here.";
"lng_restricted_send_inline" = "The admins of this group restricted you from posting inline content here."; "lng_restricted_send_inline" = "The admins of this group restricted you from posting inline content here.";
"lng_restricted_send_polls" = "The admins of this group restricted you from posting polls here.";
"lng_restricted_list_title" = "Restricted users"; "lng_restricted_list_title" = "Restricted users";
"lng_banned_list_title" = "Banned users"; "lng_banned_list_title" = "Banned users";

View File

@ -3683,119 +3683,6 @@ void ApiWrap::addChatParticipants(
} }
} }
void ApiWrap::cancelEditChatAdmins(not_null<ChatData*> chat) {
_chatAdminsEnabledRequests.take(
chat
) | requestCanceller();
_chatAdminsSaveRequests.take(
chat
) | [&](auto &&requests) {
ranges::for_each(std::move(requests), requestCanceller());
};
_chatAdminsToSave.remove(chat);
}
void ApiWrap::editChatAdmins(
not_null<ChatData*> chat,
bool adminsEnabled,
base::flat_set<not_null<UserData*>> &&admins) {
cancelEditChatAdmins(chat);
if (adminsEnabled) {
_chatAdminsToSave.emplace(chat, std::move(admins));
}
// #TODO groups
//auto requestId = request(MTPmessages_ToggleChatAdmins(chat->inputChat, MTP_bool(adminsEnabled))).done([this, chat](const MTPUpdates &updates) {
// _chatAdminsEnabledRequests.remove(chat);
// applyUpdates(updates);
// saveChatAdmins(chat);
//}).fail([this, chat](const RPCError &error) {
// _chatAdminsEnabledRequests.remove(chat);
// if (error.type() == qstr("CHAT_NOT_MODIFIED")) {
// saveChatAdmins(chat);
// }
//}).send();
//_chatAdminsEnabledRequests.emplace(chat, requestId);
}
void ApiWrap::saveChatAdmins(not_null<ChatData*> chat) {
if (!_chatAdminsToSave.contains(chat)) {
return;
}
auto requestId = request(MTPmessages_GetFullChat(chat->inputChat)).done([this, chat](const MTPmessages_ChatFull &result) {
_chatAdminsEnabledRequests.remove(chat);
processFullPeer(chat, result);
sendSaveChatAdminsRequests(chat);
}).fail([this, chat](const RPCError &error) {
_chatAdminsEnabledRequests.remove(chat);
_chatAdminsToSave.remove(chat);
}).send();
_chatAdminsEnabledRequests.emplace(chat, requestId);
}
void ApiWrap::sendSaveChatAdminsRequests(not_null<ChatData*> chat) {
auto editOne = [this, chat](not_null<UserData*> user, bool admin) {
auto requestId = request(MTPmessages_EditChatAdmin(
chat->inputChat,
user->inputUser,
MTP_bool(admin)))
.done([this, chat, user, admin](
const MTPBool &result,
mtpRequestId requestId) {
_chatAdminsSaveRequests[chat].remove(requestId);
if (_chatAdminsSaveRequests[chat].empty()) {
_chatAdminsSaveRequests.remove(chat);
Notify::peerUpdatedDelayed(chat, Notify::PeerUpdate::Flag::AdminsChanged);
}
if (mtpIsTrue(result)) {
if (admin) {
if (chat->noParticipantInfo()) {
requestFullPeer(chat);
} else {
chat->admins.insert(user);
}
} else {
chat->admins.remove(user);
}
}
}).fail([this, chat](
const RPCError &error,
mtpRequestId requestId) {
_chatAdminsSaveRequests[chat].remove(requestId);
if (_chatAdminsSaveRequests[chat].empty()) {
_chatAdminsSaveRequests.remove(chat);
}
chat->invalidateParticipants();
if (error.type() == qstr("USER_RESTRICTED")) {
Ui::show(Box<InformBox>(lang(lng_cant_do_this)));
}
}).afterDelay(kSmallDelayMs).send();
_chatAdminsSaveRequests[chat].insert(requestId);
};
auto appointOne = [&](auto user) { editOne(user, true); };
auto removeOne = [&](auto user) { editOne(user, false); };
auto admins = _chatAdminsToSave.take(chat);
Assert(!!admins);
auto toRemove = chat->admins;
auto toAppoint = std::vector<not_null<UserData*>>();
if (!admins->empty()) {
toAppoint.reserve(admins->size());
for (auto user : *admins) {
if (!toRemove.remove(user) && user->id != peerFromUser(chat->creator)) {
toAppoint.push_back(user);
}
}
}
ranges::for_each(toRemove, removeOne);
ranges::for_each(toAppoint, appointOne);
requestSendDelayed();
}
void ApiWrap::requestSharedMediaCount( void ApiWrap::requestSharedMediaCount(
not_null<PeerData*> peer, not_null<PeerData*> peer,
Storage::SharedMediaType type) { Storage::SharedMediaType type) {

View File

@ -66,7 +66,7 @@ inline int32 CountHash(IntRange &&range) {
} // namespace Api } // namespace Api
class ApiWrap : private MTP::Sender, private base::Subscriber { class ApiWrap : public MTP::Sender, private base::Subscriber {
public: public:
ApiWrap(not_null<AuthSession*> session); ApiWrap(not_null<AuthSession*> session);
@ -221,12 +221,9 @@ public:
void jumpToDate(Dialogs::Key chat, const QDate &date); void jumpToDate(Dialogs::Key chat, const QDate &date);
void preloadEnoughUnreadMentions(not_null<History*> history); void preloadEnoughUnreadMentions(not_null<History*> history);
void checkForUnreadMentions(const base::flat_set<MsgId> &possiblyReadMentions, ChannelData *channel = nullptr); void checkForUnreadMentions(
const base::flat_set<MsgId> &possiblyReadMentions,
void editChatAdmins( ChannelData *channel = nullptr);
not_null<ChatData*> chat,
bool adminsEnabled,
base::flat_set<not_null<UserData*>> &&admins);
using SliceType = Data::LoadDirection; using SliceType = Data::LoadDirection;
void requestSharedMedia( void requestSharedMedia(
@ -490,9 +487,6 @@ private:
void requestSavedGifs(TimeId now); void requestSavedGifs(TimeId now);
void readFeaturedSets(); void readFeaturedSets();
void cancelEditChatAdmins(not_null<ChatData*> chat);
void saveChatAdmins(not_null<ChatData*> chat);
void sendSaveChatAdminsRequests(not_null<ChatData*> chat);
void refreshChannelAdmins( void refreshChannelAdmins(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
const QVector<MTPChannelParticipant> &participants); const QVector<MTPChannelParticipant> &participants);
@ -673,16 +667,6 @@ private:
base::flat_map<not_null<History*>, mtpRequestId> _unreadMentionsRequests; base::flat_map<not_null<History*>, mtpRequestId> _unreadMentionsRequests;
base::flat_map<
not_null<ChatData*>,
mtpRequestId> _chatAdminsEnabledRequests;
base::flat_map<
not_null<ChatData*>,
base::flat_set<not_null<UserData*>>> _chatAdminsToSave;
base::flat_map<
not_null<ChatData*>,
base::flat_set<mtpRequestId>> _chatAdminsSaveRequests;
base::flat_map<std::tuple< base::flat_map<std::tuple<
not_null<PeerData*>, not_null<PeerData*>,
SharedMediaType, SharedMediaType,

View File

@ -16,9 +16,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/confirm_box.h" #include "boxes/confirm_box.h"
#include "boxes/photo_crop_box.h" #include "boxes/photo_crop_box.h"
#include "boxes/peer_list_controllers.h" #include "boxes/peer_list_controllers.h"
#include "boxes/peers/add_participants_box.h"
#include "boxes/peers/edit_participant_box.h" #include "boxes/peers/edit_participant_box.h"
#include "boxes/peers/edit_participants_box.h"
#include "core/file_utilities.h" #include "core/file_utilities.h"
#include "profile/profile_channel_controllers.h"
#include "chat_helpers/emoji_suggestions_widget.h" #include "chat_helpers/emoji_suggestions_widget.h"
#include "ui/widgets/checkbox.h" #include "ui/widgets/checkbox.h"
#include "ui/widgets/buttons.h" #include "ui/widgets/buttons.h"
@ -91,7 +92,7 @@ void ShowAddParticipantsError(
(*weak)->closeBox(); (*weak)->closeBox();
} }
}; };
const auto saveCallback = Profile::SaveAdminCallback( const auto saveCallback = SaveAdminCallback(
channel, channel,
user, user,
[=](auto&&...) { close(); }, [=](auto&&...) { close(); },

View File

@ -25,26 +25,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
namespace { namespace {
base::flat_set<not_null<UserData*>> GetAlreadyInFromPeer(PeerData *peer) {
if (!peer) {
return {};
}
if (auto chat = peer->asChat()) {
auto participants = (
chat->participants
) | ranges::view::transform([](auto &&pair) -> not_null<UserData*> {
return pair.first;
});
return { participants.begin(), participants.end() };
} else if (auto channel = peer->asChannel()) {
if (channel->isMegagroup()) {
auto &participants = channel->mgInfo->lastParticipants;
return { participants.cbegin(), participants.cend() };
}
}
return {};
}
void ShareBotGame(not_null<UserData*> bot, not_null<PeerData*> chat) { void ShareBotGame(not_null<UserData*> bot, not_null<PeerData*> chat) {
const auto history = App::historyLoaded(chat); const auto history = App::historyLoaded(chat);
const auto randomId = rand_value<uint64>(); const auto randomId = rand_value<uint64>();
@ -83,25 +63,6 @@ void AddBotToGroup(not_null<UserData*> bot, not_null<PeerData*> chat) {
Ui::showPeerHistory(chat, ShowAtUnreadMsgId); Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
} }
bool InviteSelectedUsers(
not_null<PeerListBox*> box,
not_null<PeerData*> chat) {
const auto rows = box->peerListCollectSelectedRows();
const auto users = ranges::view::all(
rows
) | ranges::view::transform([](not_null<PeerData*> peer) {
Expects(peer->isUser());
Expects(!peer->isSelf());
return not_null<UserData*>(peer->asUser());
}) | ranges::to_vector;
if (users.empty()) {
return false;
}
Auth().api().addChatParticipants(chat, users);
return true;
}
} // namespace } // namespace
// Not used for now. // Not used for now.
@ -421,142 +382,6 @@ std::unique_ptr<PeerListRow> ContactsBoxController::createRow(not_null<UserData*
return std::make_unique<PeerListRow>(user); return std::make_unique<PeerListRow>(user);
} }
AddParticipantsBoxController::AddParticipantsBoxController(PeerData *peer)
: ContactsBoxController(std::make_unique<PeerListGlobalSearchController>())
, _peer(peer)
, _alreadyIn(GetAlreadyInFromPeer(peer)) {
}
AddParticipantsBoxController::AddParticipantsBoxController(
not_null<ChannelData*> channel,
base::flat_set<not_null<UserData*>> &&alreadyIn)
: ContactsBoxController(std::make_unique<PeerListGlobalSearchController>())
, _peer(channel)
, _alreadyIn(std::move(alreadyIn)) {
}
void AddParticipantsBoxController::rowClicked(not_null<PeerListRow*> row) {
auto count = fullCount();
auto limit = (_peer && _peer->isMegagroup()) ? Global::MegagroupSizeMax() : Global::ChatSizeMax();
if (count < limit || row->checked()) {
delegate()->peerListSetRowChecked(row, !row->checked());
updateTitle();
} else if (auto channel = _peer ? _peer->asChannel() : nullptr) {
if (!_peer->isMegagroup()) {
Ui::show(
Box<MaxInviteBox>(_peer->asChannel()),
LayerOption::KeepOther);
}
} else if (count >= Global::ChatSizeMax() && count < Global::MegagroupSizeMax()) {
Ui::show(
Box<InformBox>(lng_profile_add_more_after_upgrade(lt_count, Global::MegagroupSizeMax())),
LayerOption::KeepOther);
}
}
void AddParticipantsBoxController::itemDeselectedHook(not_null<PeerData*> peer) {
updateTitle();
}
void AddParticipantsBoxController::prepareViewHook() {
updateTitle();
}
int AddParticipantsBoxController::alreadyInCount() const {
if (!_peer) {
return 1; // self
}
if (auto chat = _peer->asChat()) {
return qMax(chat->count, 1);
} else if (auto channel = _peer->asChannel()) {
return qMax(channel->membersCount(), int(_alreadyIn.size()));
}
Unexpected("User in AddParticipantsBoxController::alreadyInCount");
}
bool AddParticipantsBoxController::isAlreadyIn(not_null<UserData*> user) const {
if (!_peer) {
return false;
}
if (auto chat = _peer->asChat()) {
return chat->participants.contains(user);
} else if (auto channel = _peer->asChannel()) {
return _alreadyIn.contains(user)
|| (channel->isMegagroup() && base::contains(channel->mgInfo->lastParticipants, user));
}
Unexpected("User in AddParticipantsBoxController::isAlreadyIn");
}
int AddParticipantsBoxController::fullCount() const {
return alreadyInCount() + delegate()->peerListSelectedRowsCount();
}
std::unique_ptr<PeerListRow> AddParticipantsBoxController::createRow(not_null<UserData*> user) {
if (user->isSelf()) {
return nullptr;
}
auto result = std::make_unique<PeerListRow>(user);
if (isAlreadyIn(user)) {
result->setDisabledState(PeerListRow::State::DisabledChecked);
}
return result;
}
void AddParticipantsBoxController::updateTitle() {
auto additional = (_peer && _peer->isChannel() && !_peer->isMegagroup())
? QString() :
QString("%1 / %2").arg(fullCount()).arg(Global::MegagroupSizeMax());
delegate()->peerListSetTitle(langFactory(lng_profile_add_participant));
delegate()->peerListSetAdditionalTitle([additional] { return additional; });
}
void AddParticipantsBoxController::Start(not_null<ChatData*> chat) {
auto initBox = [=](not_null<PeerListBox*> box) {
box->addButton(langFactory(lng_participant_invite), [=] {
if (InviteSelectedUsers(box, chat)) {
Ui::showPeerHistory(chat, ShowAtTheEndMsgId);
}
});
box->addButton(langFactory(lng_cancel), [box] { box->closeBox(); });
};
Ui::show(Box<PeerListBox>(std::make_unique<AddParticipantsBoxController>(chat), std::move(initBox)));
}
void AddParticipantsBoxController::Start(
not_null<ChannelData*> channel,
base::flat_set<not_null<UserData*>> &&alreadyIn,
bool justCreated) {
auto initBox = [channel, justCreated](not_null<PeerListBox*> box) {
auto subscription = std::make_shared<rpl::lifetime>();
box->addButton(langFactory(lng_participant_invite), [=, copy = subscription] {
if (InviteSelectedUsers(box, channel)) {
if (channel->isMegagroup()) {
Ui::showPeerHistory(channel, ShowAtTheEndMsgId);
} else {
box->closeBox();
}
}
});
box->addButton(langFactory(justCreated ? lng_create_group_skip : lng_cancel), [box] { box->closeBox(); });
if (justCreated) {
box->boxClosing() | rpl::start_with_next([=] {
Ui::showPeerHistory(channel, ShowAtTheEndMsgId);
}, *subscription);
}
};
Ui::show(Box<PeerListBox>(std::make_unique<AddParticipantsBoxController>(channel, std::move(alreadyIn)), std::move(initBox)));
}
void AddParticipantsBoxController::Start(
not_null<ChannelData*> channel,
base::flat_set<not_null<UserData*>> &&alreadyIn) {
Start(channel, std::move(alreadyIn), false);
}
void AddParticipantsBoxController::Start(not_null<ChannelData*> channel) {
Start(channel, {}, true);
}
void AddBotToGroupBoxController::Start(not_null<UserData*> bot) { void AddBotToGroupBoxController::Start(not_null<UserData*> bot) {
auto initBox = [=](not_null<PeerListBox*> box) { auto initBox = [=](not_null<PeerListBox*> box) {
box->addButton(langFactory(lng_cancel), [box] { box->closeBox(); }); box->addButton(langFactory(lng_cancel), [box] { box->closeBox(); });

View File

@ -136,45 +136,6 @@ private:
}; };
class AddParticipantsBoxController : public ContactsBoxController {
public:
static void Start(not_null<ChatData*> chat);
static void Start(not_null<ChannelData*> channel);
static void Start(
not_null<ChannelData*> channel,
base::flat_set<not_null<UserData*>> &&alreadyIn);
AddParticipantsBoxController(PeerData *peer);
AddParticipantsBoxController(
not_null<ChannelData*> channel,
base::flat_set<not_null<UserData*>> &&alreadyIn);
using ContactsBoxController::ContactsBoxController;
void rowClicked(not_null<PeerListRow*> row) override;
void itemDeselectedHook(not_null<PeerData*> peer) override;
protected:
void prepareViewHook() override;
std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user) override;
private:
static void Start(
not_null<ChannelData*> channel,
base::flat_set<not_null<UserData*>> &&alreadyIn,
bool justCreated);
int alreadyInCount() const;
bool isAlreadyIn(not_null<UserData*> user) const;
int fullCount() const;
void updateTitle();
bool inviteSelectedUsers(not_null<PeerData*> chat) const;
PeerData *_peer = nullptr;
base::flat_set<not_null<UserData*>> _alreadyIn;
};
class AddBotToGroupBoxController class AddBotToGroupBoxController
: public ChatsListBoxController : public ChatsListBoxController
, public base::has_weak_ptr { , public base::has_weak_ptr {

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,183 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "boxes/peer_list_controllers.h"
#include "boxes/peers/edit_participants_box.h"
class AddParticipantsBoxController : public ContactsBoxController {
public:
static void Start(not_null<ChatData*> chat);
static void Start(not_null<ChannelData*> channel);
static void Start(
not_null<ChannelData*> channel,
base::flat_set<not_null<UserData*>> &&alreadyIn);
AddParticipantsBoxController(PeerData *peer);
AddParticipantsBoxController(
not_null<ChannelData*> channel,
base::flat_set<not_null<UserData*>> &&alreadyIn);
using ContactsBoxController::ContactsBoxController;
void rowClicked(not_null<PeerListRow*> row) override;
void itemDeselectedHook(not_null<PeerData*> peer) override;
protected:
void prepareViewHook() override;
std::unique_ptr<PeerListRow> createRow(
not_null<UserData*> user) override;
private:
static void Start(
not_null<ChannelData*> channel,
base::flat_set<not_null<UserData*>> &&alreadyIn,
bool justCreated);
int alreadyInCount() const;
bool isAlreadyIn(not_null<UserData*> user) const;
int fullCount() const;
void updateTitle();
bool inviteSelectedUsers(not_null<PeerData*> chat) const;
PeerData *_peer = nullptr;
base::flat_set<not_null<UserData*>> _alreadyIn;
};
// Adding an admin, banned or restricted user from channel members
// with search + contacts search + global search.
class AddSpecialBoxController
: public PeerListController
, private base::Subscriber
, private MTP::Sender
, public base::has_weak_ptr {
public:
using Role = ParticipantsBoxController::Role;
using Additional = ParticipantsBoxController::Additional;
using AdminDoneCallback = Fn<void(
not_null<UserData*> user,
const MTPChatAdminRights &adminRights)>;
using BannedDoneCallback = Fn<void(
not_null<UserData*> user,
const MTPChatBannedRights &bannedRights)>;
AddSpecialBoxController(
not_null<PeerData*> peer,
Role role,
AdminDoneCallback adminDoneCallback,
BannedDoneCallback bannedDoneCallback);
void prepare() override;
void rowClicked(not_null<PeerListRow*> row) override;
void loadMoreRows() override;
std::unique_ptr<PeerListRow> createSearchRow(
not_null<PeerData*> peer) override;
// Callback(not_null<UserData*>)
template <typename Callback>
static void HandleParticipant(
const MTPChannelParticipant &participant,
not_null<Additional*> additional,
Callback callback);
private:
template <typename Callback>
bool checkInfoLoaded(not_null<UserData*> user, Callback callback);
void prepareChatRows(not_null<ChatData*> chat);
void rebuildChatRows(not_null<ChatData*> chat);
void showAdmin(not_null<UserData*> user, bool sure = false);
void editAdminDone(
not_null<UserData*> user,
const MTPChatAdminRights &rights);
void showRestricted(not_null<UserData*> user, bool sure = false);
void editRestrictedDone(
not_null<UserData*> user,
const MTPChatBannedRights &rights);
void kickUser(not_null<UserData*> user, bool sure = false);
void restrictUserSure(
not_null<UserData*> user,
const MTPChatBannedRights &oldRights,
const MTPChatBannedRights &newRights);
bool appendRow(not_null<UserData*> user);
bool prependRow(not_null<UserData*> user);
std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user) const;
not_null<PeerData*> _peer;
Role _role = Role::Admins;
int _offset = 0;
mtpRequestId _loadRequestId = 0;
bool _allLoaded = false;
Additional _additional;
std::unique_ptr<ParticipantsOnlineSorter> _onlineSorter;
QPointer<BoxContent> _editBox;
AdminDoneCallback _adminDoneCallback;
BannedDoneCallback _bannedDoneCallback;
};
// Finds chat/channel members, then contacts, then global search results.
class AddSpecialBoxSearchController
: public PeerListSearchController
, private MTP::Sender {
public:
using Role = ParticipantsBoxController::Role;
using Additional = ParticipantsBoxController::Additional;
AddSpecialBoxSearchController(
not_null<PeerData*> peer,
not_null<Additional*> additional);
void searchQuery(const QString &query) override;
bool isLoading() override;
bool loadMoreRows() override;
private:
struct CacheEntry {
MTPchannels_ChannelParticipants result;
int requestedCount = 0;
};
struct Query {
QString text;
int offset = 0;
};
void searchOnServer();
bool searchParticipantsInCache();
void searchParticipantsDone(
mtpRequestId requestId,
const MTPchannels_ChannelParticipants &result,
int requestedCount);
bool searchGlobalInCache();
void searchGlobalDone(
mtpRequestId requestId,
const MTPcontacts_Found &result);
void requestParticipants();
void addChatMembers();
void addChatsContacts();
void requestGlobal();
not_null<PeerData*> _peer;
not_null<Additional*> _additional;
base::Timer _timer;
QString _query;
mtpRequestId _requestId = 0;
int _offset = 0;
bool _participantsLoaded = false;
bool _chatsContactsAdded = false;
bool _globalLoaded = false;
std::map<QString, CacheEntry> _participantsCache;
std::map<mtpRequestId, Query> _participantsQueries;
std::map<QString, MTPcontacts_Found> _globalCache;
std::map<mtpRequestId, QString> _globalQueries;
};

View File

@ -19,6 +19,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/peers/edit_peer_permissions_box.h" #include "boxes/peers/edit_peer_permissions_box.h"
#include "data/data_peer_values.h" #include "data/data_peer_values.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_chat.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "styles/style_boxes.h" #include "styles/style_boxes.h"
@ -34,7 +35,7 @@ class EditParticipantBox::Inner : public Ui::RpWidget {
public: public:
Inner( Inner(
QWidget *parent, QWidget *parent,
not_null<ChannelData*> channel, not_null<PeerData*> peer,
not_null<UserData*> user, not_null<UserData*> user,
bool hasAdminRights); bool hasAdminRights);
@ -46,7 +47,7 @@ protected:
void paintEvent(QPaintEvent *e) override; void paintEvent(QPaintEvent *e) override;
private: private:
not_null<ChannelData*> _channel; not_null<PeerData*> _peer;
not_null<UserData*> _user; not_null<UserData*> _user;
object_ptr<Ui::UserpicButton> _userPhoto; object_ptr<Ui::UserpicButton> _userPhoto;
Text _userName; Text _userName;
@ -57,11 +58,11 @@ private:
EditParticipantBox::Inner::Inner( EditParticipantBox::Inner::Inner(
QWidget *parent, QWidget *parent,
not_null<ChannelData*> channel, not_null<PeerData*> peer,
not_null<UserData*> user, not_null<UserData*> user,
bool hasAdminRights) bool hasAdminRights)
: RpWidget(parent) : RpWidget(parent)
, _channel(channel) , _peer(peer)
, _user(user) , _user(user)
, _userPhoto( , _userPhoto(
this, this,
@ -138,10 +139,10 @@ void EditParticipantBox::Inner::paintEvent(QPaintEvent *e) {
EditParticipantBox::EditParticipantBox( EditParticipantBox::EditParticipantBox(
QWidget*, QWidget*,
not_null<ChannelData*> channel, not_null<PeerData*> peer,
not_null<UserData*> user, not_null<UserData*> user,
bool hasAdminRights) bool hasAdminRights)
: _channel(channel) : _peer(peer)
, _user(user) , _user(user)
, _hasAdminRights(hasAdminRights) { , _hasAdminRights(hasAdminRights) {
} }
@ -149,7 +150,7 @@ EditParticipantBox::EditParticipantBox(
void EditParticipantBox::prepare() { void EditParticipantBox::prepare() {
_inner = setInnerWidget(object_ptr<Inner>( _inner = setInnerWidget(object_ptr<Inner>(
this, this,
_channel, _peer,
_user, _user,
hasAdminRights())); hasAdminRights()));
setDimensionsToContent(st::boxWideWidth, _inner); setDimensionsToContent(st::boxWideWidth, _inner);
@ -166,19 +167,21 @@ Widget *EditParticipantBox::addControl(
EditAdminBox::EditAdminBox( EditAdminBox::EditAdminBox(
QWidget*, QWidget*,
not_null<ChannelData*> channel, not_null<PeerData*> peer,
not_null<UserData*> user, not_null<UserData*> user,
const MTPChatAdminRights &rights) const MTPChatAdminRights &rights)
: EditParticipantBox( : EditParticipantBox(
nullptr, nullptr,
channel, peer,
user, user,
(rights.c_chatAdminRights().vflags.v != 0)) (rights.c_chatAdminRights().vflags.v != 0))
, _oldRights(rights) { , _oldRights(rights) {
} }
MTPChatAdminRights EditAdminBox::Defaults(not_null<ChannelData*> channel) { MTPChatAdminRights EditAdminBox::Defaults(not_null<PeerData*> peer) {
const auto defaultRights = channel->isMegagroup() const auto defaultRights = peer->isChat()
? ChatData::DefaultAdminRights()
: peer->isMegagroup()
? (Flag::f_change_info ? (Flag::f_change_info
| Flag::f_delete_messages | Flag::f_delete_messages
| Flag::f_ban_users | Flag::f_ban_users
@ -206,26 +209,32 @@ void EditAdminBox::prepare() {
object_ptr<BoxContentDivider>(this), object_ptr<BoxContentDivider>(this),
st::rightsDividerMargin); st::rightsDividerMargin);
const auto prepareRights = hadRights ? _oldRights : Defaults(channel()); const auto chat = peer()->asChat();
const auto channel = peer()->asChannel();
const auto prepareRights = hadRights ? _oldRights : Defaults(peer());
const auto filterByMyRights = canSave() const auto filterByMyRights = canSave()
&& !hadRights && !hadRights
&& !channel()->amCreator(); && channel
&& !channel->amCreator();
const auto prepareFlags = prepareRights.c_chatAdminRights().vflags.v const auto prepareFlags = prepareRights.c_chatAdminRights().vflags.v
& (filterByMyRights ? channel()->adminRights() : ~Flag(0)); & (filterByMyRights ? channel->adminRights() : ~Flag(0));
const auto disabledFlags = canSave() const auto disabledFlags = canSave()
? (channel()->amCreator() ? ((!channel || channel->amCreator())
? Flags(0) ? Flags(0)
: ~channel()->adminRights()) : ~channel->adminRights())
: ~Flags(0); : ~Flags(0);
const auto anyoneCanAddMembers = chat
? chat->anyoneCanAddMembers()
: channel->anyoneCanAddMembers();
auto [checkboxes, getChecked, changes] = CreateEditAdminRights( auto [checkboxes, getChecked, changes] = CreateEditAdminRights(
this, this,
lng_rights_edit_admin_header, lng_rights_edit_admin_header,
prepareFlags, prepareFlags,
disabledFlags, disabledFlags,
channel()->isMegagroup(), peer()->isChat() || peer()->isMegagroup(),
channel()->anyoneCanAddMembers()); anyoneCanAddMembers);
addControl(std::move(checkboxes), QMargins()); addControl(std::move(checkboxes), QMargins());
_aboutAddAdmins = addControl( _aboutAddAdmins = addControl(
@ -248,9 +257,9 @@ void EditAdminBox::prepare() {
return; return;
} }
const auto newFlags = value() const auto newFlags = value()
& (channel()->amCreator() & ((!channel || channel->amCreator())
? ~Flags(0) ? ~Flags(0)
: channel()->adminRights()); : channel->adminRights());
_saveCallback( _saveCallback(
_oldRights, _oldRights,
MTP_chatAdminRights(MTP_flags(newFlags))); MTP_chatAdminRights(MTP_flags(newFlags)));
@ -274,11 +283,11 @@ void EditAdminBox::refreshAboutAddAdminsText(bool canAddAdmins) {
EditRestrictedBox::EditRestrictedBox( EditRestrictedBox::EditRestrictedBox(
QWidget*, QWidget*,
not_null<ChannelData*> channel, not_null<PeerData*> peer,
not_null<UserData*> user, not_null<UserData*> user,
bool hasAdminRights, bool hasAdminRights,
const MTPChatBannedRights &rights) const MTPChatBannedRights &rights)
: EditParticipantBox(nullptr, channel, user, hasAdminRights) : EditParticipantBox(nullptr, peer, user, hasAdminRights)
, _oldRights(rights) { , _oldRights(rights) {
} }
@ -291,19 +300,24 @@ void EditRestrictedBox::prepare() {
object_ptr<BoxContentDivider>(this), object_ptr<BoxContentDivider>(this),
st::rightsDividerMargin); st::rightsDividerMargin);
const auto chat = peer()->asChat();
const auto channel = peer()->asChannel();
const auto defaultRestrictions = chat
? chat->defaultRestrictions()
: channel->defaultRestrictions();
const auto prepareRights = (_oldRights.c_chatBannedRights().vflags.v const auto prepareRights = (_oldRights.c_chatBannedRights().vflags.v
? _oldRights ? _oldRights
: Defaults(channel())); : Defaults(peer()));
const auto prepareFlags = prepareRights.c_chatBannedRights().vflags.v const auto prepareFlags = prepareRights.c_chatBannedRights().vflags.v
| (channel()->defaultRestrictions() | defaultRestrictions
| (channel()->isPublic() | ((channel && channel->isPublic())
? (Flag::f_change_info | Flag::f_pin_messages) ? (Flag::f_change_info | Flag::f_pin_messages)
: Flags(0))); : Flags(0));
const auto disabledFlags = canSave() const auto disabledFlags = canSave()
? (channel()->defaultRestrictions() ? (defaultRestrictions
| (channel()->isPublic() | ((channel && channel->isPublic())
? (Flag::f_change_info | Flag::f_pin_messages) ? (Flag::f_change_info | Flag::f_pin_messages)
: Flags(0))) // #TODO groups : Flags(0)))
: ~Flags(0); : ~Flags(0);
auto [checkboxes, getRestrictions, changes] = CreateEditRestrictions( auto [checkboxes, getRestrictions, changes] = CreateEditRestrictions(
@ -348,8 +362,7 @@ void EditRestrictedBox::prepare() {
} }
} }
MTPChatBannedRights EditRestrictedBox::Defaults( MTPChatBannedRights EditRestrictedBox::Defaults(not_null<PeerData*> peer) {
not_null<ChannelData*> channel) {
return MTP_chatBannedRights(MTP_flags(0), MTP_int(0)); return MTP_chatBannedRights(MTP_flags(0), MTP_int(0));
} }

View File

@ -24,7 +24,7 @@ class EditParticipantBox : public BoxContent {
public: public:
EditParticipantBox( EditParticipantBox(
QWidget*, QWidget*,
not_null<ChannelData*> channel, not_null<PeerData*> peer,
not_null<UserData*> user, not_null<UserData*> user,
bool hasAdminRights); bool hasAdminRights);
@ -34,8 +34,8 @@ protected:
not_null<UserData*> user() const { not_null<UserData*> user() const {
return _user; return _user;
} }
not_null<ChannelData*> channel() const { not_null<PeerData*> peer() const {
return _channel; return _peer;
} }
template <typename Widget> template <typename Widget>
@ -46,7 +46,7 @@ protected:
} }
private: private:
not_null<ChannelData*> _channel; not_null<PeerData*> _peer;
not_null<UserData*> _user; not_null<UserData*> _user;
bool _hasAdminRights = false; bool _hasAdminRights = false;
@ -59,7 +59,7 @@ class EditAdminBox : public EditParticipantBox {
public: public:
EditAdminBox( EditAdminBox(
QWidget*, QWidget*,
not_null<ChannelData*> channel, not_null<PeerData*> peer,
not_null<UserData*> user, not_null<UserData*> user,
const MTPChatAdminRights &rights); const MTPChatAdminRights &rights);
@ -75,7 +75,7 @@ private:
using Flag = MTPDchatAdminRights::Flag; using Flag = MTPDchatAdminRights::Flag;
using Flags = MTPDchatAdminRights::Flags; using Flags = MTPDchatAdminRights::Flags;
static MTPChatAdminRights Defaults(not_null<ChannelData*> channel); static MTPChatAdminRights Defaults(not_null<PeerData*> peer);
bool canSave() const { bool canSave() const {
return !!_saveCallback; return !!_saveCallback;
@ -96,7 +96,7 @@ class EditRestrictedBox : public EditParticipantBox {
public: public:
EditRestrictedBox( EditRestrictedBox(
QWidget*, QWidget*,
not_null<ChannelData*> channel, not_null<PeerData*> peer,
not_null<UserData*> user, not_null<UserData*> user,
bool hasAdminRights, bool hasAdminRights,
const MTPChatBannedRights &rights); const MTPChatBannedRights &rights);
@ -113,7 +113,7 @@ private:
using Flag = MTPDchatBannedRights::Flag; using Flag = MTPDchatBannedRights::Flag;
using Flags = MTPDchatBannedRights::Flags; using Flags = MTPDchatBannedRights::Flags;
static MTPChatBannedRights Defaults(not_null<ChannelData*> channel); static MTPChatBannedRights Defaults(not_null<PeerData*> peer);
bool canSave() const { bool canSave() const {
return !!_saveCallback; return !!_saveCallback;
@ -121,7 +121,6 @@ private:
void showRestrictUntil(); void showRestrictUntil();
void setRestrictUntil(TimeId until); void setRestrictUntil(TimeId until);
bool isUntilForever() const; bool isUntilForever() const;
void clearVariants();
void createUntilGroup(); void createUntilGroup();
void createUntilVariants(); void createUntilVariants();
TimeId getRealUntilValue() const; TimeId getRealUntilValue() const;

File diff suppressed because it is too large Load Diff

View File

@ -18,8 +18,6 @@ namespace Window {
class Navigation; class Navigation;
} // namespace Window } // namespace Window
namespace Profile {
Fn<void( Fn<void(
const MTPChatAdminRights &oldRights, const MTPChatAdminRights &oldRights,
const MTPChatAdminRights &newRights)> SaveAdminCallback( const MTPChatAdminRights &newRights)> SaveAdminCallback(
@ -28,6 +26,34 @@ Fn<void(
Fn<void(const MTPChatAdminRights &newRights)> onDone, Fn<void(const MTPChatAdminRights &newRights)> onDone,
Fn<void()> onFail); Fn<void()> onFail);
Fn<void(
const MTPChatBannedRights &oldRights,
const MTPChatBannedRights &newRights)> SaveRestrictedCallback(
not_null<ChannelData*> channel,
not_null<UserData*> user,
Fn<void(const MTPChatBannedRights &newRights)> onDone,
Fn<void()> onFail);
class ParticipantsOnlineSorter : private base::Subscriber {
public:
ParticipantsOnlineSorter(
not_null<PeerData*> peer,
not_null<PeerListDelegate*> delegate);
void sort();
rpl::producer<int> onlineCountValue() const;
private:
void sortDelayed();
void refreshOnlineCount();
not_null<PeerData*> _peer;
not_null<PeerListDelegate*> _delegate;
base::Timer _sortByOnlineTimer;
rpl::variable<int> _onlineCount = 0;
};
// Viewing admins, banned or restricted users list with search. // Viewing admins, banned or restricted users list with search.
class ParticipantsBoxController class ParticipantsBoxController
: public PeerListController : public PeerListController
@ -44,10 +70,12 @@ public:
}; };
static void Start( static void Start(
not_null<Window::Navigation*> navigation, not_null<Window::Navigation*> navigation,
not_null<ChannelData*> channel, not_null<PeerData*> peer,
Role role); Role role);
struct Additional { struct Additional {
void fillCreator(not_null<PeerData*> peer);
std::map<not_null<UserData*>, MTPChatAdminRights> adminRights; std::map<not_null<UserData*>, MTPChatAdminRights> adminRights;
std::set<not_null<UserData*>> adminCanEdit; std::set<not_null<UserData*>> adminCanEdit;
std::map<not_null<UserData*>, not_null<UserData*>> adminPromotedBy; std::map<not_null<UserData*>, not_null<UserData*>> adminPromotedBy;
@ -61,11 +89,9 @@ public:
ParticipantsBoxController( ParticipantsBoxController(
not_null<Window::Navigation*> navigation, not_null<Window::Navigation*> navigation,
not_null<ChannelData*> channel, not_null<PeerData*> peer,
Role role); Role role);
void addNewItem();
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;
@ -94,14 +120,16 @@ public:
rpl::producer<int> onlineCountValue() const override; rpl::producer<int> onlineCountValue() const override;
protected: protected:
virtual std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user) const; virtual std::unique_ptr<PeerListRow> createRow(
not_null<UserData*> user) const;
private: private:
using Row = Info::Profile::MemberListRow; using Row = Info::Profile::MemberListRow;
using Type = Row::Type; using Type = Row::Type;
using Rights = Row::Rights; using Rights = Row::Rights;
struct SavedState : SavedStateBase { struct SavedState : SavedStateBase {
std::unique_ptr<PeerListSearchController::SavedStateBase> searchState; using SearchStateBase = PeerListSearchController::SavedStateBase;
std::unique_ptr<SearchStateBase> searchState;
int offset = 0; int offset = 0;
bool allLoaded = false; bool allLoaded = false;
bool wasLoading = false; bool wasLoading = false;
@ -110,15 +138,19 @@ private:
}; };
static std::unique_ptr<PeerListSearchController> CreateSearchController( static std::unique_ptr<PeerListSearchController> CreateSearchController(
not_null<ChannelData*> channel, not_null<PeerData*> peer,
Role role, Role role,
not_null<Additional*> additional); not_null<Additional*> additional);
void prepareChatRows(not_null<ChatData*> chat);
void rebuildChatRows(not_null<ChatData*> chat);
void rebuildRowTypes();
void addNewItem();
void addNewParticipants();
void setNonEmptyDescription(); void setNonEmptyDescription();
void setupSortByOnline();
void setupListChangeViewers(); void setupListChangeViewers();
void sortByOnlineDelayed();
void sortByOnline();
void showAdmin(not_null<UserData*> user); void showAdmin(not_null<UserData*> user);
void editAdminDone( void editAdminDone(
not_null<UserData*> user, not_null<UserData*> user,
@ -145,18 +177,16 @@ private:
bool canEditAdminByRights(not_null<UserData*> user) const; bool canEditAdminByRights(not_null<UserData*> user) const;
not_null<Window::Navigation*> _navigation; not_null<Window::Navigation*> _navigation;
not_null<ChannelData*> _channel; not_null<PeerData*> _peer;
Role _role = Role::Admins; Role _role = Role::Admins;
int _offset = 0; int _offset = 0;
mtpRequestId _loadRequestId = 0; mtpRequestId _loadRequestId = 0;
bool _allLoaded = false; bool _allLoaded = false;
Additional _additional; Additional _additional;
std::unique_ptr<ParticipantsOnlineSorter> _onlineSorter;
QPointer<BoxContent> _editBox; QPointer<BoxContent> _editBox;
QPointer<PeerListBox> _addBox; QPointer<PeerListBox> _addBox;
base::Timer _sortByOnlineTimer;
rpl::variable<int> _onlineCount = 0;
}; };
// Members, banned and restricted users server side search. // Members, banned and restricted users server side search.
@ -167,7 +197,10 @@ public:
using Role = ParticipantsBoxController::Role; using Role = ParticipantsBoxController::Role;
using Additional = ParticipantsBoxController::Additional; using Additional = ParticipantsBoxController::Additional;
ParticipantsBoxSearchController(not_null<ChannelData*> channel, Role role, not_null<Additional*> additional); ParticipantsBoxSearchController(
not_null<ChannelData*> channel,
Role role,
not_null<Additional*> additional);
void searchQuery(const QString &query) override; void searchQuery(const QString &query) override;
bool isLoading() override; bool isLoading() override;
@ -212,99 +245,3 @@ private:
std::map<mtpRequestId, Query> _queries; std::map<mtpRequestId, Query> _queries;
}; };
// Adding an admin, banned or restricted user from channel members with search + contacts search + global search.
class AddParticipantBoxController : public PeerListController, private base::Subscriber, private MTP::Sender, public base::has_weak_ptr {
public:
using Role = ParticipantsBoxController::Role;
using Additional = ParticipantsBoxController::Additional;
using AdminDoneCallback = Fn<void(not_null<UserData*> user, const MTPChatAdminRights &adminRights)>;
using BannedDoneCallback = Fn<void(not_null<UserData*> user, const MTPChatBannedRights &bannedRights)>;
AddParticipantBoxController(not_null<ChannelData*> channel, Role role, AdminDoneCallback adminDoneCallback, BannedDoneCallback bannedDoneCallback);
void prepare() override;
void rowClicked(not_null<PeerListRow*> row) override;
void loadMoreRows() override;
std::unique_ptr<PeerListRow> createSearchRow(not_null<PeerData*> peer) override;
// Callback(not_null<UserData*>)
template <typename Callback>
static void HandleParticipant(const MTPChannelParticipant &participant, not_null<Additional*> additional, Callback callback);
private:
template <typename Callback>
bool checkInfoLoaded(not_null<UserData*> user, Callback callback);
void showAdmin(not_null<UserData*> user, bool sure = false);
void editAdminDone(not_null<UserData*> user, const MTPChatAdminRights &rights);
void showRestricted(not_null<UserData*> user, bool sure = false);
void editRestrictedDone(not_null<UserData*> user, const MTPChatBannedRights &rights);
void kickUser(not_null<UserData*> user, bool sure = false);
void restrictUserSure(not_null<UserData*> user, const MTPChatBannedRights &oldRights, const MTPChatBannedRights &newRights);
bool appendRow(not_null<UserData*> user);
bool prependRow(not_null<UserData*> user);
std::unique_ptr<PeerListRow> createRow(not_null<UserData*> user) const;
not_null<ChannelData*> _channel;
Role _role = Role::Admins;
int _offset = 0;
mtpRequestId _loadRequestId = 0;
bool _allLoaded = false;
Additional _additional;
QPointer<BoxContent> _editBox;
AdminDoneCallback _adminDoneCallback;
BannedDoneCallback _bannedDoneCallback;
};
// Finds channel members, then contacts, then global search results.
class AddParticipantBoxSearchController : public PeerListSearchController, private MTP::Sender {
public:
using Role = ParticipantsBoxController::Role;
using Additional = ParticipantsBoxController::Additional;
AddParticipantBoxSearchController(not_null<ChannelData*> channel, not_null<Additional*> additional);
void searchQuery(const QString &query) override;
bool isLoading() override;
bool loadMoreRows() override;
private:
struct CacheEntry {
MTPchannels_ChannelParticipants result;
int requestedCount = 0;
};
struct Query {
QString text;
int offset = 0;
};
void searchOnServer();
bool searchParticipantsInCache();
void searchParticipantsDone(mtpRequestId requestId, const MTPchannels_ChannelParticipants &result, int requestedCount);
bool searchGlobalInCache();
void searchGlobalDone(mtpRequestId requestId, const MTPcontacts_Found &result);
void requestParticipants();
void addChatsContacts();
void requestGlobal();
not_null<ChannelData*> _channel;
not_null<Additional*> _additional;
base::Timer _timer;
QString _query;
mtpRequestId _requestId = 0;
int _offset = 0;
bool _participantsLoaded = false;
bool _chatsContactsAdded = false;
bool _globalLoaded = false;
std::map<QString, CacheEntry> _participantsCache;
std::map<mtpRequestId, Query> _participantsQueries;
std::map<QString, MTPcontacts_Found> _globalCache;
std::map<mtpRequestId, QString> _globalQueries;
};
} // namespace Profile

View File

@ -16,7 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "info/profile/info_profile_button.h" #include "info/profile/info_profile_button.h"
#include "info/profile/info_profile_icon.h" #include "info/profile/info_profile_icon.h"
#include "info/profile/info_profile_values.h" #include "info/profile/info_profile_values.h"
#include "profile/profile_channel_controllers.h" #include "boxes/peers/edit_participants_box.h"
#include "boxes/peers/manage_peer_box.h" #include "boxes/peers/manage_peer_box.h"
#include "window/window_controller.h" #include "window/window_controller.h"
#include "mainwindow.h" #include "mainwindow.h"
@ -271,9 +271,7 @@ void EditPeerPermissionsBox::prepare() {
inner->add(std::move(checkboxes)); inner->add(std::move(checkboxes));
if (const auto channel = _peer->asChannel()) { addBannedButtons(inner);
addBannedButtons(inner, channel);
}
_value = getRestrictions; _value = getRestrictions;
_save = addButton(langFactory(lng_settings_save)); _save = addButton(langFactory(lng_settings_save));
@ -283,41 +281,40 @@ void EditPeerPermissionsBox::prepare() {
} }
void EditPeerPermissionsBox::addBannedButtons( void EditPeerPermissionsBox::addBannedButtons(
not_null<Ui::VerticalLayout*> container, not_null<Ui::VerticalLayout*> container) {
not_null<ChannelData*> channel) {
using Profile::ParticipantsBoxController;
container->add( container->add(
object_ptr<BoxContentDivider>(container), object_ptr<BoxContentDivider>(container),
{ 0, st::infoProfileSkip, 0, st::infoProfileSkip }); { 0, st::infoProfileSkip, 0, st::infoProfileSkip });
const auto navigation = App::wnd()->controller(); const auto navigation = App::wnd()->controller();
const auto channel = _peer->asChannel();
ManagePeerBox::CreateButton( ManagePeerBox::CreateButton(
container, container,
Lang::Viewer(lng_manage_peer_exceptions), Lang::Viewer(lng_manage_peer_exceptions),
Info::Profile::RestrictedCountValue(channel) (channel
| ToPositiveNumberString(), ? Info::Profile::RestrictedCountValue(channel)
: rpl::single(0)) | ToPositiveNumberString(),
[=] { [=] {
ParticipantsBoxController::Start( ParticipantsBoxController::Start(
navigation, navigation,
channel, _peer,
ParticipantsBoxController::Role::Restricted); ParticipantsBoxController::Role::Restricted);
}, },
st::peerPermissionsButton, st::peerPermissionsButton);
st::infoIconRestrictedUsers); if (channel) {
ManagePeerBox::CreateButton( ManagePeerBox::CreateButton(
container, container,
Lang::Viewer(lng_manage_peer_removed_users), Lang::Viewer(lng_manage_peer_removed_users),
Info::Profile::KickedCountValue(channel) Info::Profile::KickedCountValue(channel)
| ToPositiveNumberString(), | ToPositiveNumberString(),
[=] { [=] {
ParticipantsBoxController::Start( ParticipantsBoxController::Start(
navigation, navigation,
channel, _peer,
ParticipantsBoxController::Role::Kicked); ParticipantsBoxController::Role::Kicked);
}, },
st::peerPermissionsButton, st::peerPermissionsButton);
st::infoIconBlacklist); }
} }
template <typename Flags, typename FlagLabelPairs> template <typename Flags, typename FlagLabelPairs>

View File

@ -27,9 +27,7 @@ protected:
void prepare() override; void prepare() override;
private: private:
void addBannedButtons( void addBannedButtons(not_null<Ui::VerticalLayout*> container);
not_null<Ui::VerticalLayout*> container,
not_null<ChannelData*> channel);
not_null<PeerData*> _peer; not_null<PeerData*> _peer;
Ui::RoundButton *_save = nullptr; Ui::RoundButton *_save = nullptr;

View File

@ -11,11 +11,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "boxes/peers/edit_peer_info_box.h" #include "boxes/peers/edit_peer_info_box.h"
#include "boxes/peers/edit_peer_permissions_box.h" #include "boxes/peers/edit_peer_permissions_box.h"
#include "boxes/peers/edit_participants_box.h"
#include "ui/wrap/vertical_layout.h" #include "ui/wrap/vertical_layout.h"
#include "ui/widgets/labels.h" #include "ui/widgets/labels.h"
#include "history/admin_log/history_admin_log_section.h" #include "history/admin_log/history_admin_log_section.h"
#include "window/window_controller.h" #include "window/window_controller.h"
#include "profile/profile_channel_controllers.h"
#include "info/profile/info_profile_button.h" #include "info/profile/info_profile_button.h"
#include "info/profile/info_profile_icon.h" #include "info/profile/info_profile_icon.h"
#include "info/profile/info_profile_values.h" #include "info/profile/info_profile_values.h"
@ -52,7 +52,7 @@ Info::Profile::Button *AddButton(
rpl::single(QString()), rpl::single(QString()),
std::move(callback), std::move(callback),
st::managePeerButton, st::managePeerButton,
icon); &icon);
} }
void AddButtonWithCount( void AddButtonWithCount(
@ -67,7 +67,7 @@ void AddButtonWithCount(
std::move(count), std::move(count),
std::move(callback), std::move(callback),
st::managePeerButton, st::managePeerButton,
icon); &icon);
} }
bool HasRecentActions(not_null<ChannelData*> channel) { bool HasRecentActions(not_null<ChannelData*> channel) {
@ -139,10 +139,10 @@ void FillManageChatBox(
Info::Profile::AdminsCountValue(chat) Info::Profile::AdminsCountValue(chat)
| ToPositiveNumberString(), | ToPositiveNumberString(),
[=] { [=] {
//ParticipantsBoxController::Start( ParticipantsBoxController::Start(
// navigation, navigation,
// channel, chat,
// ParticipantsBoxController::Role::Admins); ParticipantsBoxController::Role::Admins);
}, },
st::infoIconAdministrators); st::infoIconAdministrators);
AddButtonWithCount( AddButtonWithCount(
@ -151,10 +151,10 @@ void FillManageChatBox(
Info::Profile::MembersCountValue(chat) Info::Profile::MembersCountValue(chat)
| ToPositiveNumberString(), | ToPositiveNumberString(),
[=] { [=] {
//ParticipantsBoxController::Start( ParticipantsBoxController::Start(
// navigation, navigation,
// channel, chat,
// ParticipantsBoxController::Role::Members); ParticipantsBoxController::Role::Members);
}, },
st::infoIconMembers); st::infoIconMembers);
} }
@ -164,8 +164,6 @@ void FillManageChannelBox(
not_null<Window::Navigation*> navigation, not_null<Window::Navigation*> navigation,
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
not_null<Ui::VerticalLayout*> content) { not_null<Ui::VerticalLayout*> content) {
using Profile::ParticipantsBoxController;
auto isGroup = channel->isMegagroup(); auto isGroup = channel->isMegagroup();
if (HasEditInfoBox(channel)) { if (HasEditInfoBox(channel)) {
AddButton( AddButton(
@ -272,17 +270,19 @@ Info::Profile::Button *ManagePeerBox::CreateButton(
rpl::producer<QString> &&count, rpl::producer<QString> &&count,
Fn<void()> callback, Fn<void()> callback,
const style::InfoProfileCountButton &st, const style::InfoProfileCountButton &st,
const style::icon &icon) { const style::icon *icon) {
const auto button = parent->add( const auto button = parent->add(
object_ptr<Info::Profile::Button>( object_ptr<Info::Profile::Button>(
parent, parent,
std::move(text), std::move(text),
st.button)); st.button));
button->addClickHandler(callback); button->addClickHandler(callback);
Ui::CreateChild<Info::Profile::FloatingIcon>( if (icon) {
button, Ui::CreateChild<Info::Profile::FloatingIcon>(
icon, button,
st.iconPosition); *icon,
st.iconPosition);
}
const auto label = Ui::CreateChild<Ui::FlatLabel>( const auto label = Ui::CreateChild<Ui::FlatLabel>(
button, button,
std::move(count), std::move(count),

View File

@ -35,7 +35,7 @@ public:
rpl::producer<QString> &&count, rpl::producer<QString> &&count,
Fn<void()> callback, Fn<void()> callback,
const style::InfoProfileCountButton &st, const style::InfoProfileCountButton &st,
const style::icon &icon); const style::icon *icon = nullptr);
protected: protected:
void prepare() override; void prepare() override;

View File

@ -105,12 +105,23 @@ void ChannelData::setKickedCount(int newKickedCount) {
MTPChatBannedRights ChannelData::KickedRestrictedRights() { MTPChatBannedRights ChannelData::KickedRestrictedRights() {
using Flag = MTPDchatBannedRights::Flag; using Flag = MTPDchatBannedRights::Flag;
auto flags = Flag::f_view_messages | Flag::f_send_messages | Flag::f_send_media | Flag::f_embed_links | Flag::f_send_stickers | Flag::f_send_gifs | Flag::f_send_games | Flag::f_send_inline; const auto flags = Flag::f_view_messages
return MTP_chatBannedRights(MTP_flags(flags), MTP_int(std::numeric_limits<int32>::max())); | Flag::f_send_messages
| Flag::f_send_media
| Flag::f_embed_links
| Flag::f_send_stickers
| Flag::f_send_gifs
| Flag::f_send_games
| Flag::f_send_inline;
return MTP_chatBannedRights(
MTP_flags(flags),
MTP_int(std::numeric_limits<int32>::max()));
} }
void ChannelData::applyEditAdmin(not_null<UserData*> user, const MTPChatAdminRights &oldRights, const MTPChatAdminRights &newRights) { void ChannelData::applyEditAdmin(
auto flags = Notify::PeerUpdate::Flag::AdminsChanged | Notify::PeerUpdate::Flag::None; not_null<UserData*> user,
const MTPChatAdminRights &oldRights,
const MTPChatAdminRights &newRights) {
if (mgInfo) { if (mgInfo) {
// If rights are empty - still add participant? TODO check // If rights are empty - still add participant? TODO check
if (!base::contains(mgInfo->lastParticipants, user)) { if (!base::contains(mgInfo->lastParticipants, user)) {
@ -167,7 +178,9 @@ void ChannelData::applyEditAdmin(not_null<UserData*> user, const MTPChatAdminRig
setAdminsCount(adminsCount() + 1); setAdminsCount(adminsCount() + 1);
updateFullForced(); updateFullForced();
} }
Notify::peerUpdatedDelayed(this, flags); Notify::peerUpdatedDelayed(
this,
Notify::PeerUpdate::Flag::AdminsChanged);
} }
void ChannelData::applyEditBanned(not_null<UserData*> user, const MTPChatBannedRights &oldRights, const MTPChatBannedRights &newRights) { void ChannelData::applyEditBanned(not_null<UserData*> user, const MTPChatBannedRights &oldRights, const MTPChatBannedRights &newRights) {
@ -285,23 +298,22 @@ void ChannelData::setFeedPointer(Data::Feed *feed) {
} }
bool ChannelData::canBanMembers() const { bool ChannelData::canBanMembers() const {
return (adminRights() & AdminRight::f_ban_users) return amCreator()
|| amCreator(); || (adminRights() & AdminRight::f_ban_users);
} }
bool ChannelData::canEditMessages() const { bool ChannelData::canEditMessages() const {
return (adminRights() & AdminRight::f_edit_messages) return amCreator()
|| amCreator(); || (adminRights() & AdminRight::f_edit_messages);
} }
bool ChannelData::canDeleteMessages() const { bool ChannelData::canDeleteMessages() const {
return (adminRights() & AdminRight::f_delete_messages) return amCreator()
|| amCreator(); || (adminRights() & AdminRight::f_delete_messages);
} }
bool ChannelData::anyoneCanAddMembers() const { bool ChannelData::anyoneCanAddMembers() const {
// #TODO groups return !(defaultRestrictions() & Restriction::f_invite_users);
return false;// (flags() & MTPDchannel::Flag::f_democracy);
} }
bool ChannelData::hiddenPreHistory() const { bool ChannelData::hiddenPreHistory() const {
@ -312,6 +324,10 @@ bool ChannelData::canAddMembers() const {
return !amRestricted(ChatRestriction::f_invite_users); return !amRestricted(ChatRestriction::f_invite_users);
} }
bool ChannelData::canSendPolls() const {
return canWrite() && !amRestricted(ChatRestriction::f_send_polls);
}
bool ChannelData::canAddAdmins() const { bool ChannelData::canAddAdmins() const {
return amCreator() return amCreator()
|| (adminRights() & AdminRight::f_add_admins); || (adminRights() & AdminRight::f_add_admins);

View File

@ -246,13 +246,14 @@ public:
bool canEditUsername() const; bool canEditUsername() const;
bool canEditPreHistoryHidden() const; bool canEditPreHistoryHidden() const;
bool canAddMembers() const; bool canAddMembers() const;
bool canAddAdmins() const;
bool canBanMembers() const; bool canBanMembers() const;
bool canSendPolls() const;
bool anyoneCanAddMembers() const;
bool canEditMessages() const; bool canEditMessages() const;
bool canDeleteMessages() const; bool canDeleteMessages() const;
bool anyoneCanAddMembers() const;
bool hiddenPreHistory() const; bool hiddenPreHistory() const;
bool canAddAdmins() const;
bool canPublish() const; bool canPublish() const;
bool canViewMembers() const; bool canViewMembers() const;
bool canViewAdmins() const; bool canViewAdmins() const;

View File

@ -37,15 +37,24 @@ bool ChatData::actionsUnavailable() const {
return isDeactivated() || !amIn(); return isDeactivated() || !amIn();
} }
auto ChatData::DefaultAdminRights() -> AdminRights {
using Flag = AdminRight;
return Flag::f_change_info
| Flag::f_delete_messages
| Flag::f_ban_users
| Flag::f_invite_users
| Flag::f_pin_messages;
}
bool ChatData::canWrite() const { bool ChatData::canWrite() const {
// Duplicated in Data::CanWriteValue(). // Duplicated in Data::CanWriteValue().
return !actionsUnavailable() return !actionsUnavailable()
&& !amRestricted(ChatRestriction::f_send_messages); && !amRestricted(Restriction::f_send_messages);
} }
bool ChatData::canEditInformation() const { bool ChatData::canEditInformation() const {
return !actionsUnavailable() return !actionsUnavailable()
&& !amRestricted(ChatRestriction::f_change_info); && !amRestricted(Restriction::f_change_info);
} }
bool ChatData::canEditPermissions() const { bool ChatData::canEditPermissions() const {
@ -64,13 +73,45 @@ bool ChatData::canEditPreHistoryHidden() const {
bool ChatData::canAddMembers() const { bool ChatData::canAddMembers() const {
return !actionsUnavailable() return !actionsUnavailable()
&& !amRestricted(ChatRestriction::f_invite_users); && !amRestricted(Restriction::f_invite_users);
}
bool ChatData::canSendPolls() const {
return !actionsUnavailable()
&& !amRestricted(Restriction::f_send_polls);
}
bool ChatData::canAddAdmins() const {
return !actionsUnavailable()
&& amCreator();
}
bool ChatData::canBanMembers() const {
return amCreator()
|| (adminRights() & AdminRight::f_ban_users);
}
bool ChatData::anyoneCanAddMembers() const {
return !(defaultRestrictions() & Restriction::f_invite_users);
} }
void ChatData::setName(const QString &newName) { void ChatData::setName(const QString &newName) {
updateNameDelayed(newName.isEmpty() ? name : newName, QString(), QString()); updateNameDelayed(newName.isEmpty() ? name : newName, QString(), QString());
} }
void ChatData::applyEditAdmin(not_null<UserData*> user, bool isAdmin) {
auto flags = Notify::PeerUpdate::Flag::AdminsChanged
| Notify::PeerUpdate::Flag::None;
if (isAdmin) {
admins.emplace(user);
} else {
admins.remove(user);
}
Notify::peerUpdatedDelayed(
this,
Notify::PeerUpdate::Flag::AdminsChanged);
}
void ChatData::invalidateParticipants() { void ChatData::invalidateParticipants() {
// #TODO groups // #TODO groups
participants.clear(); participants.clear();

View File

@ -121,13 +121,21 @@ public:
return flags() & MTPDchat::Flag::f_migrated_to; return flags() & MTPDchat::Flag::f_migrated_to;
} }
// Like in ChatData. static AdminRights DefaultAdminRights();
// Like in ChannelData.
bool canWrite() const; bool canWrite() const;
bool canEditInformation() const; bool canEditInformation() const;
bool canEditPermissions() const; bool canEditPermissions() const;
bool canEditUsername() const; bool canEditUsername() const;
bool canEditPreHistoryHidden() const; bool canEditPreHistoryHidden() const;
bool canAddMembers() const; bool canAddMembers() const;
bool canAddAdmins() const;
bool canBanMembers() const;
bool canSendPolls() const;
bool anyoneCanAddMembers() const;
void applyEditAdmin(not_null<UserData*> user, bool isAdmin);
void setInviteLink(const QString &newInviteLink); void setInviteLink(const QString &newInviteLink);
QString inviteLink() const { QString inviteLink() const {

View File

@ -1253,6 +1253,13 @@ TextWithEntities MediaPoll::clipboardText() const {
return { text, EntitiesInText() }; return { text, EntitiesInText() };
} }
QString MediaPoll::errorTextForForward(not_null<PeerData*> peer) const {
if (peer->amRestricted(ChatRestriction::f_send_polls)) {
return lang(lng_restricted_send_polls);
}
return QString();
}
bool MediaPoll::updateInlineResultMedia(const MTPMessageMedia &media) { bool MediaPoll::updateInlineResultMedia(const MTPMessageMedia &media) {
return false; return false;
} }

View File

@ -389,6 +389,7 @@ public:
QString notificationText() const override; QString notificationText() const override;
QString pinnedTextSubstring() const override; QString pinnedTextSubstring() const override;
TextWithEntities clipboardText() const override; TextWithEntities clipboardText() const override;
QString errorTextForForward(not_null<PeerData*> peer) const override;
bool updateInlineResultMedia(const MTPMessageMedia &media) override; bool updateInlineResultMedia(const MTPMessageMedia &media) override;
bool updateSentMedia(const MTPMessageMedia &media) override; bool updateSentMedia(const MTPMessageMedia &media) override;

View File

@ -435,14 +435,15 @@ void PeerData::fillNames() {
PeerData::~PeerData() = default; PeerData::~PeerData() = default;
void PeerData::updateFull() { void PeerData::updateFull() {
if (!_lastFullUpdate || getms(true) > _lastFullUpdate + kUpdateFullPeerTimeout) { if (!_lastFullUpdate
|| getms(true) > _lastFullUpdate + kUpdateFullPeerTimeout) {
updateFullForced(); updateFullForced();
} }
} }
void PeerData::updateFullForced() { void PeerData::updateFullForced() {
session().api().requestFullPeer(this); session().api().requestFullPeer(this);
if (auto channel = asChannel()) { if (const auto channel = asChannel()) {
if (!channel->amCreator() && !channel->inviter) { if (!channel->amCreator() && !channel->inviter) {
session().api().requestSelfParticipant(channel); session().api().requestSelfParticipant(channel);
} }

View File

@ -9,6 +9,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "data/data_peer_values.h" #include "data/data_peer_values.h"
#include "data/data_channel.h"
#include "data/data_chat.h" #include "data/data_chat.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "observer_peer.h" #include "observer_peer.h"

View File

@ -8,7 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#pragma once #pragma once
#include "boxes/peer_list_box.h" #include "boxes/peer_list_box.h"
#include "profile/profile_channel_controllers.h" #include "boxes/peers/edit_participants_box.h"
namespace Dialogs { namespace Dialogs {
@ -38,7 +38,7 @@ private:
}; };
class ChannelSearchFromController : public Profile::ParticipantsBoxController { class ChannelSearchFromController : public ParticipantsBoxController {
public: public:
ChannelSearchFromController( ChannelSearchFromController(
not_null<Window::Navigation*> navigation, not_null<Window::Navigation*> navigation,

View File

@ -26,10 +26,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "apiwrap.h" #include "apiwrap.h"
#include "messenger.h" #include "messenger.h"
#include "boxes/peer_list_box.h" #include "boxes/peer_list_box.h"
#include "boxes/peers/edit_participants_box.h"
#include "window/window_controller.h" #include "window/window_controller.h"
#include "window/window_slide_animation.h" #include "window/window_slide_animation.h"
#include "window/window_connecting_widget.h" #include "window/window_connecting_widget.h"
#include "profile/profile_channel_controllers.h"
#include "storage/storage_media_prepare.h" #include "storage/storage_media_prepare.h"
#include "storage/localstorage.h" #include "storage/localstorage.h"
#include "data/data_session.h" #include "data/data_session.h"

View File

@ -213,7 +213,7 @@ QString GenerateBannedChangeText(
{ Flag::f_send_media, lng_admin_log_banned_send_media }, { Flag::f_send_media, lng_admin_log_banned_send_media },
{ Flag::f_send_stickers | Flag::f_send_gifs | Flag::f_send_inline | Flag::f_send_games, lng_admin_log_banned_send_stickers }, { Flag::f_send_stickers | Flag::f_send_gifs | Flag::f_send_inline | Flag::f_send_games, lng_admin_log_banned_send_stickers },
{ Flag::f_embed_links, lng_admin_log_banned_embed_links }, { Flag::f_embed_links, lng_admin_log_banned_embed_links },
{ Flag::f_send_media, lng_admin_log_banned_send_polls }, { Flag::f_send_polls, lng_admin_log_banned_send_polls },
{ Flag::f_change_info, lng_admin_log_admin_change_info }, { Flag::f_change_info, lng_admin_log_admin_change_info },
{ Flag::f_invite_users, lng_admin_log_admin_invite_users }, { Flag::f_invite_users, lng_admin_log_admin_invite_users },
{ Flag::f_pin_messages, lng_admin_log_admin_pin_messages }, { Flag::f_pin_messages, lng_admin_log_admin_pin_messages },

View File

@ -361,7 +361,6 @@ infoIconMediaRound: icon {{ "info_media_round", infoIconFg }};
infoIconRecentActions: icon {{ "info_recent_actions", infoIconFg }}; infoIconRecentActions: icon {{ "info_recent_actions", infoIconFg }};
infoIconAdministrators: icon {{ "info_administrators", infoIconFg }}; infoIconAdministrators: icon {{ "info_administrators", infoIconFg }};
infoIconBlacklist: icon {{ "info_blacklist", infoIconFg }}; infoIconBlacklist: icon {{ "info_blacklist", infoIconFg }};
infoIconRestrictedUsers: icon {{ "info_restricted_users", infoIconFg }};
infoIconPermissions: icon {{ "info_permissions", infoIconFg }}; infoIconPermissions: icon {{ "info_permissions", infoIconFg }};
infoInformationIconPosition: point(25px, 12px); infoInformationIconPosition: point(25px, 12px);
infoNotificationsIconPosition: point(20px, 5px); infoNotificationsIconPosition: point(20px, 5px);
@ -592,7 +591,7 @@ managePeerButton: InfoProfileCountButton {
} }
peerPermissionsButton: InfoProfileCountButton(managePeerButton) { peerPermissionsButton: InfoProfileCountButton(managePeerButton) {
button: InfoProfileButton(infoProfileButton) { button: InfoProfileButton(infoProfileButton) {
padding: margins(67px, 12px, 67px, 10px); padding: margins(24px, 12px, 24px, 10px);
} }
iconPosition: point(24px, 5px); iconPosition: point(24px, 5px);
} }

View File

@ -26,7 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/search_field_controller.h" #include "ui/search_field_controller.h"
#include "lang/lang_keys.h" #include "lang/lang_keys.h"
#include "boxes/confirm_box.h" #include "boxes/confirm_box.h"
#include "boxes/peer_list_controllers.h" #include "boxes/peers/add_participants_box.h"
#include "window/window_controller.h" #include "window/window_controller.h"
#include "data/data_channel.h" #include "data/data_channel.h"
#include "data/data_chat.h" #include "data/data_chat.h"
@ -323,11 +323,7 @@ void Members::updateHeaderControlsGeometry(int newWidth) {
void Members::addMember() { void Members::addMember() {
if (const auto chat = _peer->asChat()) { if (const auto chat = _peer->asChat()) {
if (chat->count >= Global::ChatSizeMax() && chat->amCreator()) { AddParticipantsBoxController::Start(chat);
// #TODO convert and add inside AddParticipantsBoxController?
} else {
AddParticipantsBoxController::Start(chat);
}
} else if (const auto channel = _peer->asChannel()) { } else if (const auto channel = _peer->asChannel()) {
const auto state = _listController->saveState(); const auto state = _listController->saveState();
const auto users = ranges::view::all( const auto users = ranges::view::all(

View File

@ -19,10 +19,6 @@ struct ScrollToRequest;
class AbstractButton; class AbstractButton;
} // namespace Ui } // namespace Ui
namespace Profile {
class ParticipantsBoxController;
} // namespace Profile
namespace Info { namespace Info {
class Controller; class Controller;

View File

@ -9,13 +9,14 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include <rpl/variable.h> #include <rpl/variable.h>
#include "base/weak_ptr.h" #include "base/weak_ptr.h"
#include "profile/profile_channel_controllers.h" #include "boxes/peers/edit_participants_box.h"
#include "ui/widgets/popup_menu.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 "mainwidget.h"
#include "observer_peer.h" #include "observer_peer.h"
#include "data/data_channel.h"
#include "data/data_chat.h" #include "data/data_chat.h"
#include "data/data_user.h" #include "data/data_user.h"
#include "boxes/confirm_box.h" #include "boxes/confirm_box.h"
@ -378,17 +379,15 @@ void MemberListRow::paintNameIcon(
std::unique_ptr<PeerListController> CreateMembersController( std::unique_ptr<PeerListController> CreateMembersController(
not_null<Window::Navigation*> navigation, not_null<Window::Navigation*> navigation,
not_null<PeerData*> peer) { not_null<PeerData*> peer) {
if (auto chat = peer->asChat()) { if (const auto chat = peer->asChat()) {
return std::make_unique<ChatMembersController>( return std::make_unique<ChatMembersController>(
navigation, navigation,
chat); chat);
} else if (auto channel = peer->asChannel()) { } else if (const auto channel = peer->asChannel()) {
using ChannelMembersController return std::make_unique<ParticipantsBoxController>(
= ::Profile::ParticipantsBoxController;
return std::make_unique<ChannelMembersController>(
navigation, navigation,
channel, channel,
ChannelMembersController::Role::Profile); ParticipantsBoxController::Role::Profile);
} }
Unexpected("Peer type in CreateMembersController()"); Unexpected("Peer type in CreateMembersController()");
} }

View File

@ -11,7 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/widgets/labels.h" #include "ui/widgets/labels.h"
#include "boxes/confirm_box.h" #include "boxes/confirm_box.h"
#include "boxes/peers/edit_participant_box.h" #include "boxes/peers/edit_participant_box.h"
#include "profile/profile_channel_controllers.h" #include "boxes/peers/edit_participants_box.h"
#include "ui/widgets/popup_menu.h" #include "ui/widgets/popup_menu.h"
#include "data/data_peer_values.h" #include "data/data_peer_values.h"
#include "data/data_channel.h" #include "data/data_channel.h"
@ -68,51 +68,6 @@ GroupMembersWidget::GroupMembersWidget(
refreshMembers(); refreshMembers();
} }
void GroupMembersWidget::editAdmin(not_null<UserData*> user) {
auto megagroup = peer()->asMegagroup();
if (!megagroup) {
return; // not supported
}
auto currentRightsIt = megagroup->mgInfo->lastAdmins.find(user);
auto hasAdminRights = (currentRightsIt != megagroup->mgInfo->lastAdmins.cend());
auto currentRights = hasAdminRights ? currentRightsIt->second.rights : MTP_chatAdminRights(MTP_flags(0));
auto weak = std::make_shared<QPointer<EditAdminBox>>(nullptr);
auto box = Box<EditAdminBox>(megagroup, user, currentRights);
box->setSaveCallback(SaveAdminCallback(megagroup, user, [=](
const MTPChatAdminRights &newRights) {
if (*weak) {
(*weak)->closeBox();
}
}, [=] {
if (*weak) {
(*weak)->closeBox();
}
}));
*weak = Ui::show(std::move(box));
}
void GroupMembersWidget::restrictUser(not_null<UserData*> user) {
auto megagroup = peer()->asMegagroup();
if (!megagroup) {
return; // not supported
}
auto currentRightsIt = megagroup->mgInfo->lastRestricted.find(user);
auto currentRights = (currentRightsIt != megagroup->mgInfo->lastRestricted.end())
? currentRightsIt->second.rights
: MTP_chatBannedRights(MTP_flags(0), MTP_int(0));
auto hasAdminRights = megagroup->mgInfo->lastAdmins.find(user) != megagroup->mgInfo->lastAdmins.cend();
auto box = Box<EditRestrictedBox>(megagroup, user, hasAdminRights, currentRights);
box->setSaveCallback([megagroup, user](const MTPChatBannedRights &oldRights, const MTPChatBannedRights &newRights) {
Ui::hideLayer();
// #TODO use Auth().api().
MTP::send(MTPchannels_EditBanned(megagroup->inputChannel, user->inputUser, newRights), rpcDone([megagroup, user, oldRights, newRights](const MTPUpdates &result) {
Auth().api().applyUpdates(result);
megagroup->applyEditBanned(user, oldRights, newRights);
}));
});
Ui::show(std::move(box));
}
void GroupMembersWidget::removePeer(PeerData *selectedPeer) { void GroupMembersWidget::removePeer(PeerData *selectedPeer) {
auto user = selectedPeer->asUser(); auto user = selectedPeer->asUser();
Assert(user != nullptr); Assert(user != nullptr);

View File

@ -42,8 +42,6 @@ private:
// Observed notifications. // Observed notifications.
void notifyPeerUpdated(const Notify::PeerUpdate &update); void notifyPeerUpdated(const Notify::PeerUpdate &update);
void editAdmin(not_null<UserData*> user);
void restrictUser(not_null<UserData*> user);
void removePeer(PeerData *selectedPeer); void removePeer(PeerData *selectedPeer);
void refreshMembers(); void refreshMembers();
void fillChatMembers(ChatData *chat); void fillChatMembers(ChatData *chat);

File diff suppressed because it is too large Load Diff

View File

@ -13,7 +13,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "boxes/add_contact_box.h" #include "boxes/add_contact_box.h"
#include "boxes/report_box.h" #include "boxes/report_box.h"
#include "boxes/create_poll_box.h" #include "boxes/create_poll_box.h"
#include "boxes/peer_list_controllers.h" #include "boxes/peers/add_participants_box.h"
#include "boxes/peers/manage_peer_box.h" #include "boxes/peers/manage_peer_box.h"
#include "boxes/peers/edit_peer_info_box.h" #include "boxes/peers/edit_peer_info_box.h"
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
@ -368,7 +368,7 @@ void Filler::addChatActions(not_null<ChatData*> chat) {
lang(lng_profile_add_participant), lang(lng_profile_add_participant),
[chat] { AddChatMembers(chat); }); [chat] { AddChatMembers(chat); });
} }
if (chat->canWrite()) { if (chat->canSendPolls()) {
_addAction( _addAction(
lang(lng_polls_create), lang(lng_polls_create),
[=] { PeerMenuCreatePoll(chat); }); [=] { PeerMenuCreatePoll(chat); });
@ -410,7 +410,7 @@ void Filler::addChannelActions(not_null<ChannelData*> channel) {
lang(lng_channel_add_members), lang(lng_channel_add_members),
[channel] { PeerMenuAddChannelMembers(channel); }); [channel] { PeerMenuAddChannelMembers(channel); });
} }
if (channel->canWrite()) { if (channel->canSendPolls()) {
_addAction( _addAction(
lang(lng_polls_create), lang(lng_polls_create),
[=] { PeerMenuCreatePoll(channel); }); [=] { PeerMenuCreatePoll(channel); });

View File

@ -1,5 +1,9 @@
<(src_loc)/boxes/peers/add_participants_box.cpp
<(src_loc)/boxes/peers/add_participants_box.h
<(src_loc)/boxes/peers/edit_participant_box.cpp <(src_loc)/boxes/peers/edit_participant_box.cpp
<(src_loc)/boxes/peers/edit_participant_box.h <(src_loc)/boxes/peers/edit_participant_box.h
<(src_loc)/boxes/peers/edit_participants_box.cpp
<(src_loc)/boxes/peers/edit_participants_box.h
<(src_loc)/boxes/peers/edit_peer_info_box.cpp <(src_loc)/boxes/peers/edit_peer_info_box.cpp
<(src_loc)/boxes/peers/edit_peer_info_box.h <(src_loc)/boxes/peers/edit_peer_info_box.h
<(src_loc)/boxes/peers/edit_peer_permissions_box.cpp <(src_loc)/boxes/peers/edit_peer_permissions_box.cpp
@ -584,8 +588,6 @@
<(src_loc)/profile/profile_block_peer_list.h <(src_loc)/profile/profile_block_peer_list.h
<(src_loc)/profile/profile_block_widget.cpp <(src_loc)/profile/profile_block_widget.cpp
<(src_loc)/profile/profile_block_widget.h <(src_loc)/profile/profile_block_widget.h
<(src_loc)/profile/profile_channel_controllers.cpp
<(src_loc)/profile/profile_channel_controllers.h
<(src_loc)/profile/profile_cover_drop_area.cpp <(src_loc)/profile/profile_cover_drop_area.cpp
<(src_loc)/profile/profile_cover_drop_area.h <(src_loc)/profile/profile_cover_drop_area.h
<(src_loc)/settings/settings_advanced.cpp <(src_loc)/settings/settings_advanced.cpp