mirror of https://github.com/procxx/kepka.git
Display custom admin ranks in messages.
This commit is contained in:
parent
22f210ea8e
commit
f36e2981ca
|
@ -1623,11 +1623,7 @@ void ApiWrap::requestAdmins(not_null<ChannelData*> channel) {
|
|||
)).done([this, channel](const MTPchannels_ChannelParticipants &result) {
|
||||
_adminsRequests.remove(channel);
|
||||
result.match([&](const MTPDchannels_channelParticipants &data) {
|
||||
_session->data().processUsers(data.vusers());
|
||||
applyAdminsList(
|
||||
channel,
|
||||
data.vcount().v,
|
||||
data.vparticipants().v);
|
||||
Data::ApplyChannelAdmins(channel, data);
|
||||
}, [&](const MTPDchannels_channelParticipantsNotModified &) {
|
||||
LOG(("API Error: channels.channelParticipantsNotModified received!"));
|
||||
});
|
||||
|
@ -1671,10 +1667,12 @@ void ApiWrap::applyLastParticipantsList(
|
|||
|
||||
auto user = _session->data().user(userId);
|
||||
if (p.type() == mtpc_channelParticipantCreator) {
|
||||
const auto &creator = p.c_channelParticipantCreator();
|
||||
const auto rank = qs(creator.vrank().value_or_empty());
|
||||
channel->mgInfo->creator = user;
|
||||
if (!channel->mgInfo->admins.empty()
|
||||
&& !channel->mgInfo->admins.contains(userId)) {
|
||||
Data::ChannelAdminChanges(channel).feed(userId, true);
|
||||
channel->mgInfo->creatorRank = rank;
|
||||
if (!channel->mgInfo->admins.empty()) {
|
||||
Data::ChannelAdminChanges(channel).add(userId, rank);
|
||||
}
|
||||
}
|
||||
if (!base::contains(channel->mgInfo->lastParticipants, user)) {
|
||||
|
@ -1758,39 +1756,6 @@ void ApiWrap::applyBotsList(
|
|||
fullPeerUpdated().notify(channel);
|
||||
}
|
||||
|
||||
void ApiWrap::applyAdminsList(
|
||||
not_null<ChannelData*> channel,
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list) {
|
||||
auto admins = ranges::make_iterator_range(
|
||||
list.begin(), list.end()
|
||||
) | ranges::view::transform([](const MTPChannelParticipant &p) {
|
||||
return p.match([](const auto &data) { return data.vuser_id().v; });
|
||||
});
|
||||
auto adding = base::flat_set<UserId>{ admins.begin(), admins.end() };
|
||||
if (channel->mgInfo->creator) {
|
||||
adding.insert(peerToUser(channel->mgInfo->creator->id));
|
||||
}
|
||||
auto removing = channel->mgInfo->admins;
|
||||
|
||||
if (removing.empty() && adding.empty()) {
|
||||
// Add some admin-placeholder so we don't DDOS
|
||||
// server with admins list requests.
|
||||
LOG(("API Error: Got empty admins list from server."));
|
||||
adding.insert(0);
|
||||
}
|
||||
|
||||
Data::ChannelAdminChanges changes(channel);
|
||||
for (const auto addingId : adding) {
|
||||
if (!removing.remove(addingId)) {
|
||||
changes.feed(addingId, true);
|
||||
}
|
||||
}
|
||||
for (const auto removingId : removing) {
|
||||
changes.feed(removingId, false);
|
||||
}
|
||||
}
|
||||
|
||||
void ApiWrap::requestSelfParticipant(not_null<ChannelData*> channel) {
|
||||
if (_selfParticipantRequests.contains(channel)) {
|
||||
return;
|
||||
|
@ -3547,9 +3512,13 @@ void ApiWrap::refreshChannelAdmins(
|
|||
const auto userId = p.match([](const auto &data) {
|
||||
return data.vuser_id().v;
|
||||
});
|
||||
const auto isAdmin = (p.type() == mtpc_channelParticipantAdmin)
|
||||
|| (p.type() == mtpc_channelParticipantCreator);
|
||||
changes.feed(userId, isAdmin);
|
||||
p.match([&](const MTPDchannelParticipantAdmin &data) {
|
||||
changes.add(userId, qs(data.vrank().value_or_empty()));
|
||||
}, [&](const MTPDchannelParticipantCreator &data) {
|
||||
changes.add(userId, qs(data.vrank().value_or_empty()));
|
||||
}, [&](const auto &data) {
|
||||
changes.remove(userId);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -570,10 +570,6 @@ private:
|
|||
not_null<ChannelData*> channel,
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list);
|
||||
void applyAdminsList(
|
||||
not_null<ChannelData*> channel,
|
||||
int availableCount,
|
||||
const QVector<MTPChannelParticipant> &list);
|
||||
void resolveWebPages();
|
||||
void gotWebPages(
|
||||
ChannelData *channel,
|
||||
|
|
|
@ -103,7 +103,8 @@ void ShowAddParticipantsError(
|
|||
auto box = Box<EditAdminBox>(
|
||||
channel,
|
||||
user,
|
||||
MTP_chatAdminRights(MTP_flags(0)));
|
||||
MTP_chatAdminRights(MTP_flags(0)),
|
||||
QString());
|
||||
box->setSaveCallback(saveCallback);
|
||||
*weak = Ui::show(std::move(box));
|
||||
};
|
||||
|
|
|
@ -553,11 +553,16 @@ void AddSpecialBoxController::showAdmin(
|
|||
: adminRights
|
||||
? *adminRights
|
||||
: MTPChatAdminRights(MTP_chatAdminRights(MTP_flags(0)));
|
||||
auto box = Box<EditAdminBox>(_peer, user, currentRights);
|
||||
auto box = Box<EditAdminBox>(
|
||||
_peer,
|
||||
user,
|
||||
currentRights,
|
||||
_additional.adminRank(user));
|
||||
if (_additional.canAddOrEditAdmin(user)) {
|
||||
const auto done = crl::guard(this, [=](
|
||||
const MTPChatAdminRights &newRights) {
|
||||
editAdminDone(user, newRights);
|
||||
const MTPChatAdminRights &newRights,
|
||||
const QString &rank) {
|
||||
editAdminDone(user, newRights, rank);
|
||||
});
|
||||
const auto fail = crl::guard(this, [=] {
|
||||
if (_editParticipantBox) {
|
||||
|
@ -571,7 +576,8 @@ void AddSpecialBoxController::showAdmin(
|
|||
|
||||
void AddSpecialBoxController::editAdminDone(
|
||||
not_null<UserData*> user,
|
||||
const MTPChatAdminRights &rights) {
|
||||
const MTPChatAdminRights &rights,
|
||||
const QString &rank) {
|
||||
if (_editParticipantBox) {
|
||||
_editParticipantBox->closeBox();
|
||||
}
|
||||
|
@ -582,9 +588,11 @@ void AddSpecialBoxController::editAdminDone(
|
|||
MTP_int(user->bareId()),
|
||||
MTP_int(date)));
|
||||
} else {
|
||||
using Flag = MTPDchannelParticipantAdmin::Flag;
|
||||
const auto alreadyPromotedBy = _additional.adminPromotedBy(user);
|
||||
_additional.applyParticipant(MTP_channelParticipantAdmin(
|
||||
MTP_flags(MTPDchannelParticipantAdmin::Flag::f_can_edit),
|
||||
MTP_flags(Flag::f_can_edit
|
||||
| (rank.isEmpty() ? Flag(0) : Flag::f_rank)),
|
||||
MTP_int(user->bareId()),
|
||||
MTPint(), // inviter_id
|
||||
MTP_int(alreadyPromotedBy
|
||||
|
@ -592,10 +600,10 @@ void AddSpecialBoxController::editAdminDone(
|
|||
: user->session().userId()),
|
||||
MTP_int(date),
|
||||
rights,
|
||||
MTPstring())); // #TODO ranks
|
||||
MTP_string(rank)));
|
||||
}
|
||||
if (const auto callback = _adminDoneCallback) {
|
||||
callback(user, rights);
|
||||
callback(user, rights, rank);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -62,7 +62,8 @@ public:
|
|||
|
||||
using AdminDoneCallback = Fn<void(
|
||||
not_null<UserData*> user,
|
||||
const MTPChatAdminRights &adminRights)>;
|
||||
const MTPChatAdminRights &adminRights,
|
||||
const QString &rank)>;
|
||||
using BannedDoneCallback = Fn<void(
|
||||
not_null<UserData*> user,
|
||||
const MTPChatBannedRights &bannedRights)>;
|
||||
|
@ -89,7 +90,8 @@ private:
|
|||
void showAdmin(not_null<UserData*> user, bool sure = false);
|
||||
void editAdminDone(
|
||||
not_null<UserData*> user,
|
||||
const MTPChatAdminRights &rights);
|
||||
const MTPChatAdminRights &rights,
|
||||
const QString &rank);
|
||||
void showRestricted(not_null<UserData*> user, bool sure = false);
|
||||
void editRestrictedDone(
|
||||
not_null<UserData*> user,
|
||||
|
|
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "ui/widgets/checkbox.h"
|
||||
#include "ui/widgets/labels.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/widgets/input_fields.h"
|
||||
#include "ui/toast/toast.h"
|
||||
#include "ui/text/text_utilities.h"
|
||||
#include "ui/text_options.h"
|
||||
|
@ -247,13 +248,15 @@ EditAdminBox::EditAdminBox(
|
|||
QWidget*,
|
||||
not_null<PeerData*> peer,
|
||||
not_null<UserData*> user,
|
||||
const MTPChatAdminRights &rights)
|
||||
const MTPChatAdminRights &rights,
|
||||
const QString &rank)
|
||||
: EditParticipantBox(
|
||||
nullptr,
|
||||
peer,
|
||||
user,
|
||||
(rights.c_chatAdminRights().vflags().v != 0))
|
||||
, _oldRights(rights) {
|
||||
, _oldRights(rights)
|
||||
, _oldRank(rank) {
|
||||
}
|
||||
|
||||
MTPChatAdminRights EditAdminBox::Defaults(not_null<PeerData*> peer) {
|
||||
|
@ -362,6 +365,16 @@ void EditAdminBox::prepare() {
|
|||
refreshAboutAddAdminsText(checked);
|
||||
}, lifetime());
|
||||
|
||||
const auto rank = canSave()
|
||||
? addControl(
|
||||
object_ptr<Ui::InputField>(
|
||||
this,
|
||||
st::defaultInputField,
|
||||
tr::lng_rights_edit_admin_header(),
|
||||
_oldRank),
|
||||
st::rightsAboutMargin)
|
||||
: nullptr;
|
||||
|
||||
if (canSave()) {
|
||||
addButton(tr::lng_settings_save(), [=, value = getChecked] {
|
||||
if (!_saveCallback) {
|
||||
|
@ -373,7 +386,8 @@ void EditAdminBox::prepare() {
|
|||
: channel->adminRights());
|
||||
_saveCallback(
|
||||
_oldRights,
|
||||
MTP_chatAdminRights(MTP_flags(newFlags)));
|
||||
MTP_chatAdminRights(MTP_flags(newFlags)),
|
||||
rank->getLastText().trimmed());
|
||||
});
|
||||
addButton(tr::lng_cancel(), [this] { closeBox(); });
|
||||
} else {
|
||||
|
|
|
@ -68,10 +68,14 @@ public:
|
|||
QWidget*,
|
||||
not_null<PeerData*> peer,
|
||||
not_null<UserData*> user,
|
||||
const MTPChatAdminRights &rights);
|
||||
const MTPChatAdminRights &rights,
|
||||
const QString &rank);
|
||||
|
||||
void setSaveCallback(
|
||||
Fn<void(MTPChatAdminRights, MTPChatAdminRights)> callback) {
|
||||
Fn<void(
|
||||
MTPChatAdminRights,
|
||||
MTPChatAdminRights,
|
||||
const QString &rank)> callback) {
|
||||
_saveCallback = std::move(callback);
|
||||
}
|
||||
|
||||
|
@ -93,14 +97,18 @@ private:
|
|||
not_null<ChannelData*> channel,
|
||||
const Core::CloudPasswordResult &result);
|
||||
bool canSave() const {
|
||||
return !!_saveCallback;
|
||||
return _saveCallback != nullptr;
|
||||
}
|
||||
void refreshAboutAddAdminsText(bool canAddAdmins);
|
||||
bool canTransferOwnership() const;
|
||||
not_null<Ui::SlideWrap<Ui::RpWidget>*> setupTransferButton(bool isGroup);
|
||||
|
||||
const MTPChatAdminRights _oldRights;
|
||||
Fn<void(MTPChatAdminRights, MTPChatAdminRights)> _saveCallback;
|
||||
const QString _oldRank;
|
||||
Fn<void(
|
||||
MTPChatAdminRights,
|
||||
MTPChatAdminRights,
|
||||
const QString &rank)> _saveCallback;
|
||||
|
||||
QPointer<Ui::FlatLabel> _aboutAddAdmins;
|
||||
mtpRequestId _checkTransferRequestId = 0;
|
||||
|
|
|
@ -49,10 +49,10 @@ void RemoveAdmin(
|
|||
channel->inputChannel,
|
||||
user->inputUser,
|
||||
newRights,
|
||||
MTP_string(QString()) // #TODO ranks
|
||||
MTP_string(QString())
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
channel->session().api().applyUpdates(result);
|
||||
channel->applyEditAdmin(user, oldRights, newRights);
|
||||
channel->applyEditAdmin(user, oldRights, newRights, QString());
|
||||
if (onDone) {
|
||||
onDone();
|
||||
}
|
||||
|
@ -120,16 +120,17 @@ void SaveChannelAdmin(
|
|||
not_null<UserData*> user,
|
||||
const MTPChatAdminRights &oldRights,
|
||||
const MTPChatAdminRights &newRights,
|
||||
const QString &rank,
|
||||
Fn<void()> onDone,
|
||||
Fn<void()> onFail) {
|
||||
channel->session().api().request(MTPchannels_EditAdmin(
|
||||
channel->inputChannel,
|
||||
user->inputUser,
|
||||
newRights,
|
||||
MTP_string(QString()) // #TODO ranks
|
||||
MTP_string(rank)
|
||||
)).done([=](const MTPUpdates &result) {
|
||||
channel->session().api().applyUpdates(result);
|
||||
channel->applyEditAdmin(user, oldRights, newRights);
|
||||
channel->applyEditAdmin(user, oldRights, newRights, rank);
|
||||
if (onDone) {
|
||||
onDone();
|
||||
}
|
||||
|
@ -189,21 +190,26 @@ void SaveChatParticipantKick(
|
|||
|
||||
Fn<void(
|
||||
const MTPChatAdminRights &oldRights,
|
||||
const MTPChatAdminRights &newRights)> SaveAdminCallback(
|
||||
const MTPChatAdminRights &newRights,
|
||||
const QString &rank)> SaveAdminCallback(
|
||||
not_null<PeerData*> peer,
|
||||
not_null<UserData*> user,
|
||||
Fn<void(const MTPChatAdminRights &newRights)> onDone,
|
||||
Fn<void(
|
||||
const MTPChatAdminRights &newRights,
|
||||
const QString &rank)> onDone,
|
||||
Fn<void()> onFail) {
|
||||
return [=](
|
||||
const MTPChatAdminRights &oldRights,
|
||||
const MTPChatAdminRights &newRights) {
|
||||
const auto done = [=] { if (onDone) onDone(newRights); };
|
||||
const MTPChatAdminRights &newRights,
|
||||
const QString &rank) {
|
||||
const auto done = [=] { if (onDone) onDone(newRights, rank); };
|
||||
const auto saveForChannel = [=](not_null<ChannelData*> channel) {
|
||||
SaveChannelAdmin(
|
||||
channel,
|
||||
user,
|
||||
oldRights,
|
||||
newRights,
|
||||
rank,
|
||||
done,
|
||||
onFail);
|
||||
};
|
||||
|
@ -361,6 +367,12 @@ auto ParticipantsAdditionalData::adminRights(
|
|||
: std::nullopt;
|
||||
}
|
||||
|
||||
QString ParticipantsAdditionalData::adminRank(
|
||||
not_null<UserData*> user) const {
|
||||
const auto i = _adminRanks.find(user);
|
||||
return (i != end(_adminRanks)) ? i->second : QString();
|
||||
}
|
||||
|
||||
auto ParticipantsAdditionalData::restrictedRights(
|
||||
not_null<UserData*> user) const
|
||||
-> std::optional<MTPChatBannedRights> {
|
||||
|
@ -455,9 +467,11 @@ void ParticipantsAdditionalData::fillFromChannel(
|
|||
}
|
||||
if (information->creator) {
|
||||
_creator = information->creator;
|
||||
_adminRanks[information->creator] = information->creatorRank;
|
||||
}
|
||||
for (const auto user : information->lastParticipants) {
|
||||
const auto admin = information->lastAdmins.find(user);
|
||||
const auto rank = information->admins.find(peerToUser(user->id));
|
||||
const auto restricted = information->lastRestricted.find(user);
|
||||
if (admin != information->lastAdmins.cend()) {
|
||||
_restrictedRights.erase(user);
|
||||
|
@ -469,6 +483,10 @@ void ParticipantsAdditionalData::fillFromChannel(
|
|||
_adminCanEdit.erase(user);
|
||||
}
|
||||
_adminRights.emplace(user, admin->second.rights);
|
||||
if (rank != end(information->admins)
|
||||
&& !rank->second.isEmpty()) {
|
||||
_adminRanks[user] = rank->second;
|
||||
}
|
||||
} else if (restricted != information->lastRestricted.cend()) {
|
||||
_adminRights.erase(user);
|
||||
_adminCanEdit.erase(user);
|
||||
|
@ -535,6 +553,11 @@ UserData *ParticipantsAdditionalData::applyCreator(
|
|||
const MTPDchannelParticipantCreator &data) {
|
||||
if (const auto user = applyRegular(data.vuser_id())) {
|
||||
_creator = user;
|
||||
if (const auto rank = data.vrank()) {
|
||||
_adminRanks[user] = qs(*rank);
|
||||
} else {
|
||||
_adminRanks.remove(user);
|
||||
}
|
||||
return user;
|
||||
}
|
||||
return nullptr;
|
||||
|
@ -561,6 +584,11 @@ UserData *ParticipantsAdditionalData::applyAdmin(
|
|||
} else {
|
||||
_adminCanEdit.erase(user);
|
||||
}
|
||||
if (const auto rank = data.vrank()) {
|
||||
_adminRanks[user] = qs(*rank);
|
||||
} else {
|
||||
_adminRanks.remove(user);
|
||||
}
|
||||
if (const auto by = _peer->owner().userLoaded(data.vpromoted_by().v)) {
|
||||
const auto i = _adminPromotedBy.find(user);
|
||||
if (i == _adminPromotedBy.end()) {
|
||||
|
@ -852,8 +880,9 @@ void ParticipantsBoxController::addNewItem() {
|
|||
}
|
||||
const auto adminDone = crl::guard(this, [=](
|
||||
not_null<UserData*> user,
|
||||
const MTPChatAdminRights &rights) {
|
||||
editAdminDone(user, rights);
|
||||
const MTPChatAdminRights &rights,
|
||||
const QString &rank) {
|
||||
editAdminDone(user, rights, rank);
|
||||
});
|
||||
const auto restrictedDone = crl::guard(this, [=](
|
||||
not_null<UserData*> user,
|
||||
|
@ -1418,13 +1447,18 @@ void ParticipantsBoxController::showAdmin(not_null<UserData*> user) {
|
|||
: adminRights
|
||||
? *adminRights
|
||||
: MTPChatAdminRights(MTP_chatAdminRights(MTP_flags(0)));
|
||||
auto box = Box<EditAdminBox>(_peer, user, currentRights);
|
||||
auto box = Box<EditAdminBox>(
|
||||
_peer,
|
||||
user,
|
||||
currentRights,
|
||||
_additional.adminRank(user));
|
||||
const auto chat = _peer->asChat();
|
||||
const auto channel = _peer->asChannel();
|
||||
if (_additional.canAddOrEditAdmin(user)) {
|
||||
const auto done = crl::guard(this, [=](
|
||||
const MTPChatAdminRights &newRights) {
|
||||
editAdminDone(user, newRights);
|
||||
const MTPChatAdminRights &newRights,
|
||||
const QString &rank) {
|
||||
editAdminDone(user, newRights, rank);
|
||||
});
|
||||
const auto fail = crl::guard(this, [=] {
|
||||
if (_editParticipantBox) {
|
||||
|
@ -1438,7 +1472,8 @@ void ParticipantsBoxController::showAdmin(not_null<UserData*> user) {
|
|||
|
||||
void ParticipantsBoxController::editAdminDone(
|
||||
not_null<UserData*> user,
|
||||
const MTPChatAdminRights &rights) {
|
||||
const MTPChatAdminRights &rights,
|
||||
const QString &rank) {
|
||||
_addBox = nullptr;
|
||||
if (_editParticipantBox) {
|
||||
_editParticipantBox->closeBox();
|
||||
|
@ -1453,9 +1488,11 @@ void ParticipantsBoxController::editAdminDone(
|
|||
removeRow(user);
|
||||
}
|
||||
} else {
|
||||
using Flag = MTPDchannelParticipantAdmin::Flag;
|
||||
const auto alreadyPromotedBy = _additional.adminPromotedBy(user);
|
||||
_additional.applyParticipant(MTP_channelParticipantAdmin(
|
||||
MTP_flags(MTPDchannelParticipantAdmin::Flag::f_can_edit),
|
||||
MTP_flags(Flag::f_can_edit
|
||||
| (rank.isEmpty() ? Flag(0) : Flag::f_rank)),
|
||||
MTP_int(user->bareId()),
|
||||
MTPint(), // inviter_id
|
||||
MTP_int(alreadyPromotedBy
|
||||
|
@ -1463,7 +1500,7 @@ void ParticipantsBoxController::editAdminDone(
|
|||
: user->session().userId()),
|
||||
MTP_int(date),
|
||||
rights,
|
||||
MTPstring())); // #TODO ranks
|
||||
MTP_string(rank)));
|
||||
if (_role == Role::Admins) {
|
||||
prependRow(user);
|
||||
} else if (_role == Role::Kicked || _role == Role::Restricted) {
|
||||
|
@ -1619,7 +1656,10 @@ void ParticipantsBoxController::removeAdminSure(not_null<UserData*> user) {
|
|||
|
||||
if (const auto chat = _peer->asChat()) {
|
||||
SaveChatAdmin(chat, user, false, crl::guard(this, [=] {
|
||||
editAdminDone(user, MTP_chatAdminRights(MTP_flags(0)));
|
||||
editAdminDone(
|
||||
user,
|
||||
MTP_chatAdminRights(MTP_flags(0)),
|
||||
QString());
|
||||
}), nullptr);
|
||||
} else if (const auto channel = _peer->asChannel()) {
|
||||
const auto adminRights = _additional.adminRights(user);
|
||||
|
@ -1627,7 +1667,10 @@ void ParticipantsBoxController::removeAdminSure(not_null<UserData*> user) {
|
|||
return;
|
||||
}
|
||||
RemoveAdmin(channel, user, *adminRights, crl::guard(this, [=] {
|
||||
editAdminDone(user, MTP_chatAdminRights(MTP_flags(0)));
|
||||
editAdminDone(
|
||||
user,
|
||||
MTP_chatAdminRights(MTP_flags(0)),
|
||||
QString());
|
||||
}), nullptr);
|
||||
}
|
||||
}
|
||||
|
@ -1819,9 +1862,9 @@ void ParticipantsBoxController::subscribeToCreatorChange(
|
|||
MTP_int(Global::ChatSizeMax()),
|
||||
MTP_int(0)
|
||||
)).done([=](const MTPchannels_ChannelParticipants &result) {
|
||||
channel->mgInfo->creator = channel->amCreator()
|
||||
? channel->session().user().get()
|
||||
: nullptr;
|
||||
if (channel->amCreator()) {
|
||||
channel->mgInfo->creator = channel->session().user().get();
|
||||
}
|
||||
channel->mgInfo->lastAdmins.clear();
|
||||
channel->mgInfo->lastRestricted.clear();
|
||||
channel->mgInfo->lastParticipants.clear();
|
||||
|
|
|
@ -20,10 +20,13 @@ class SessionNavigation;
|
|||
|
||||
Fn<void(
|
||||
const MTPChatAdminRights &oldRights,
|
||||
const MTPChatAdminRights &newRights)> SaveAdminCallback(
|
||||
const MTPChatAdminRights &newRights,
|
||||
const QString &rank)> SaveAdminCallback(
|
||||
not_null<PeerData*> peer,
|
||||
not_null<UserData*> user,
|
||||
Fn<void(const MTPChatAdminRights &newRights)> onDone,
|
||||
Fn<void(
|
||||
const MTPChatAdminRights &newRights,
|
||||
const QString &rank)> onDone,
|
||||
Fn<void()> onFail);
|
||||
|
||||
Fn<void(
|
||||
|
@ -87,6 +90,7 @@ public:
|
|||
[[nodiscard]] bool canRestrictUser(not_null<UserData*> user) const;
|
||||
[[nodiscard]] std::optional<MTPChatAdminRights> adminRights(
|
||||
not_null<UserData*> user) const;
|
||||
QString adminRank(not_null<UserData*> user) const;
|
||||
[[nodiscard]] std::optional<MTPChatBannedRights> restrictedRights(
|
||||
not_null<UserData*> user) const;
|
||||
[[nodiscard]] bool isCreator(not_null<UserData*> user) const;
|
||||
|
@ -104,7 +108,6 @@ private:
|
|||
UserData *applyBanned(const MTPDchannelParticipantBanned &data);
|
||||
void fillFromChat(not_null<ChatData*> chat);
|
||||
void fillFromChannel(not_null<ChannelData*> channel);
|
||||
void subscribeToCreatorChange(not_null<ChannelData*> channel);
|
||||
|
||||
not_null<PeerData*> _peer;
|
||||
Role _role = Role::Members;
|
||||
|
@ -116,6 +119,7 @@ private:
|
|||
|
||||
// Data for channels.
|
||||
base::flat_map<not_null<UserData*>, MTPChatAdminRights> _adminRights;
|
||||
base::flat_map<not_null<UserData*>, QString> _adminRanks;
|
||||
base::flat_set<not_null<UserData*>> _adminCanEdit;
|
||||
base::flat_map<not_null<UserData*>, not_null<UserData*>> _adminPromotedBy;
|
||||
std::map<not_null<UserData*>, MTPChatBannedRights> _restrictedRights;
|
||||
|
@ -204,7 +208,8 @@ private:
|
|||
void showAdmin(not_null<UserData*> user);
|
||||
void editAdminDone(
|
||||
not_null<UserData*> user,
|
||||
const MTPChatAdminRights &rights);
|
||||
const MTPChatAdminRights &rights,
|
||||
const QString &rank);
|
||||
void showRestricted(not_null<UserData*> user);
|
||||
void editRestrictedDone(
|
||||
not_null<UserData*> user,
|
||||
|
|
|
@ -701,7 +701,7 @@ for restype in typesList:
|
|||
prmsInit.append('_' + paramName + '(' + paramName + '_)');
|
||||
if (paramName in conditions):
|
||||
readText += '\t\t&& (v' + paramName + '() ? _' + paramName + '.read(from, end) : ((_' + paramName + ' = MTP' + paramType + '()), true))\n';
|
||||
writeText += '\tif (const auto v' + paramName + ' = v.v' + paramName + '()) v' + paramName + '->write(to);\n';
|
||||
writeText += '\t\tif (const auto v' + paramName + ' = v.v' + paramName + '()) v' + paramName + '->write(to);\n';
|
||||
sizeList.append('(v.v' + paramName + '() ? v.v' + paramName + '()->innerLength() : 0)');
|
||||
else:
|
||||
readText += '\t\t&& _' + paramName + '.read(from, end)\n';
|
||||
|
|
|
@ -194,7 +194,8 @@ MTPChatBannedRights ChannelData::KickedRestrictedRights() {
|
|||
void ChannelData::applyEditAdmin(
|
||||
not_null<UserData*> user,
|
||||
const MTPChatAdminRights &oldRights,
|
||||
const MTPChatAdminRights &newRights) {
|
||||
const MTPChatAdminRights &newRights,
|
||||
const QString &rank) {
|
||||
if (mgInfo) {
|
||||
// If rights are empty - still add participant? TODO check
|
||||
if (!base::contains(mgInfo->lastParticipants, user)) {
|
||||
|
@ -226,7 +227,7 @@ void ChannelData::applyEditAdmin(
|
|||
} else {
|
||||
it->second = lastAdmin;
|
||||
}
|
||||
Data::ChannelAdminChanges(this).feed(userId, true);
|
||||
Data::ChannelAdminChanges(this).add(userId, rank);
|
||||
} else {
|
||||
if (it != mgInfo->lastAdmins.cend()) {
|
||||
mgInfo->lastAdmins.erase(it);
|
||||
|
@ -234,7 +235,7 @@ void ChannelData::applyEditAdmin(
|
|||
setAdminsCount(adminsCount() - 1);
|
||||
}
|
||||
}
|
||||
Data::ChannelAdminChanges(this).feed(userId, false);
|
||||
Data::ChannelAdminChanges(this).remove(userId);
|
||||
}
|
||||
}
|
||||
if (oldRights.c_chatAdminRights().vflags().v && !newRights.c_chatAdminRights().vflags().v) {
|
||||
|
@ -307,7 +308,7 @@ void ChannelData::applyEditBanned(not_null<UserData*> user, const MTPChatBannedR
|
|||
owner().removeMegagroupParticipant(this, user);
|
||||
}
|
||||
}
|
||||
Data::ChannelAdminChanges(this).feed(peerToUser(user->id), false);
|
||||
Data::ChannelAdminChanges(this).remove(peerToUser(user->id));
|
||||
} else {
|
||||
if (isKicked) {
|
||||
if (membersCount() > 1) {
|
||||
|
@ -515,7 +516,7 @@ void ChannelData::setAdminRights(const MTPChatAdminRights &rights) {
|
|||
}
|
||||
|
||||
auto amAdmin = hasAdminRights() || amCreator();
|
||||
Data::ChannelAdminChanges(this).feed(session().userId(), amAdmin);
|
||||
Data::ChannelAdminChanges(this).add(session().userId(), QString());
|
||||
}
|
||||
Notify::peerUpdatedDelayed(this, UpdateFlag::RightsChanged | UpdateFlag::AdminsChanged | UpdateFlag::BannedUsersChanged);
|
||||
}
|
||||
|
@ -535,7 +536,7 @@ void ChannelData::setRestrictions(const MTPChatBannedRights &rights) {
|
|||
mgInfo->lastRestricted.emplace(self, me);
|
||||
}
|
||||
mgInfo->lastAdmins.remove(self);
|
||||
Data::ChannelAdminChanges(this).feed(session().userId(), false);
|
||||
Data::ChannelAdminChanges(this).remove(session().userId());
|
||||
} else {
|
||||
mgInfo->lastRestricted.remove(self);
|
||||
}
|
||||
|
@ -740,4 +741,54 @@ void ApplyChannelUpdate(
|
|||
update.vnotify_settings());
|
||||
}
|
||||
|
||||
void ApplyChannelAdmins(
|
||||
not_null<ChannelData*> channel,
|
||||
const MTPDchannels_channelParticipants &data) {
|
||||
channel->owner().processUsers(data.vusers());
|
||||
|
||||
const auto &list = data.vparticipants().v;
|
||||
|
||||
auto adding = base::flat_map<UserId, QString>();
|
||||
auto admins = ranges::make_iterator_range(
|
||||
list.begin(), list.end()
|
||||
) | ranges::view::transform([](const MTPChannelParticipant &p) {
|
||||
const auto userId = p.match([](const auto &data) {
|
||||
return data.vuser_id().v;
|
||||
});
|
||||
const auto rank = p.match([](const MTPDchannelParticipantAdmin &data) {
|
||||
return qs(data.vrank().value_or_empty());
|
||||
}, [](const MTPDchannelParticipantCreator &data) {
|
||||
return qs(data.vrank().value_or_empty());
|
||||
}, [](const auto &data) {
|
||||
return QString();
|
||||
});
|
||||
return std::make_pair(userId, rank);
|
||||
});
|
||||
for (const auto &[userId, rank] : admins) {
|
||||
adding.emplace(userId, rank);
|
||||
}
|
||||
if (channel->mgInfo->creator) {
|
||||
adding.emplace(
|
||||
peerToUser(channel->mgInfo->creator->id),
|
||||
channel->mgInfo->creatorRank);
|
||||
}
|
||||
auto removing = channel->mgInfo->admins;
|
||||
if (removing.empty() && adding.empty()) {
|
||||
// Add some admin-placeholder so we don't DDOS
|
||||
// server with admins list requests.
|
||||
LOG(("API Error: Got empty admins list from server."));
|
||||
adding.emplace(0, QString());
|
||||
}
|
||||
|
||||
Data::ChannelAdminChanges changes(channel);
|
||||
for (const auto &[addingId, rank] : adding) {
|
||||
if (!removing.remove(addingId)) {
|
||||
changes.add(addingId, rank);
|
||||
}
|
||||
}
|
||||
for (const auto &[removingId, rank] : removing) {
|
||||
changes.remove(removingId);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -62,10 +62,11 @@ public:
|
|||
base::flat_set<not_null<PeerData*>> markupSenders;
|
||||
base::flat_set<not_null<UserData*>> bots;
|
||||
|
||||
// For admin badges, full admins list.
|
||||
base::flat_set<UserId> admins;
|
||||
// For admin badges, full admins list with ranks.
|
||||
base::flat_map<UserId, QString> admins;
|
||||
|
||||
UserData *creator = nullptr; // nullptr means unknown
|
||||
QString creatorRank;
|
||||
int botStatus = 0; // -1 - no bots, 0 - unknown, 1 - one bot, that sees all history, 2 - other
|
||||
bool joinedMessageFound = false;
|
||||
MTPInputStickerSet stickerSet = MTP_inputStickerSetEmpty();
|
||||
|
@ -208,7 +209,8 @@ public:
|
|||
void applyEditAdmin(
|
||||
not_null<UserData*> user,
|
||||
const MTPChatAdminRights &oldRights,
|
||||
const MTPChatAdminRights &newRights);
|
||||
const MTPChatAdminRights &newRights,
|
||||
const QString &rank);
|
||||
void applyEditBanned(
|
||||
not_null<UserData*> user,
|
||||
const MTPChatBannedRights &oldRights,
|
||||
|
@ -454,4 +456,8 @@ void ApplyChannelUpdate(
|
|||
not_null<ChannelData*> channel,
|
||||
const MTPDchannelFull &update);
|
||||
|
||||
void ApplyChannelAdmins(
|
||||
not_null<ChannelData*> channel,
|
||||
const MTPDchannels_channelParticipants &data);
|
||||
|
||||
} // namespace Data
|
||||
|
|
|
@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
|||
#include "history/history.h"
|
||||
#include "data/data_channel.h"
|
||||
#include "data/data_session.h"
|
||||
#include "auth_session.h"
|
||||
|
||||
namespace Data {
|
||||
|
||||
|
@ -18,18 +19,25 @@ ChannelAdminChanges::ChannelAdminChanges(not_null<ChannelData*> channel)
|
|||
, _admins(_channel->mgInfo->admins) {
|
||||
}
|
||||
|
||||
void ChannelAdminChanges::feed(UserId userId, bool isAdmin) {
|
||||
if (isAdmin && !_admins.contains(userId)) {
|
||||
_admins.insert(userId);
|
||||
_changes.emplace(userId, true);
|
||||
} else if (!isAdmin && _admins.contains(userId)) {
|
||||
void ChannelAdminChanges::add(UserId userId, const QString &rank) {
|
||||
const auto i = _admins.find(userId);
|
||||
if (i == end(_admins) || i->second != rank) {
|
||||
_admins[userId] = rank;
|
||||
_changes.emplace(userId);
|
||||
}
|
||||
}
|
||||
|
||||
void ChannelAdminChanges::remove(UserId userId) {
|
||||
if (_admins.contains(userId)) {
|
||||
_admins.remove(userId);
|
||||
_changes.emplace(userId, false);
|
||||
_changes.emplace(userId);
|
||||
}
|
||||
}
|
||||
|
||||
ChannelAdminChanges::~ChannelAdminChanges() {
|
||||
if (!_changes.empty()) {
|
||||
if (_changes.size() > 1
|
||||
|| (!_changes.empty()
|
||||
&& _changes.front() != _channel->session().userId())) {
|
||||
if (const auto history = _channel->owner().historyLoaded(_channel)) {
|
||||
history->applyGroupAdminChanges(_changes);
|
||||
}
|
||||
|
|
|
@ -13,14 +13,15 @@ class ChannelAdminChanges {
|
|||
public:
|
||||
ChannelAdminChanges(not_null<ChannelData*> channel);
|
||||
|
||||
void feed(UserId userId, bool isAdmin);
|
||||
void add(UserId userId, const QString &rank);
|
||||
void remove(UserId userId);
|
||||
|
||||
~ChannelAdminChanges();
|
||||
|
||||
private:
|
||||
not_null<ChannelData*> _channel;
|
||||
base::flat_set<UserId> &_admins;
|
||||
base::flat_map<UserId, bool> _changes;
|
||||
base::flat_map<UserId, QString> &_admins;
|
||||
base::flat_set<UserId> _changes;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -1100,7 +1100,7 @@ void History::applyServiceChanges(
|
|||
mgInfo->botStatus = -1;
|
||||
}
|
||||
}
|
||||
Data::ChannelAdminChanges(megagroup).feed(uid, false);
|
||||
Data::ChannelAdminChanges(megagroup).remove(uid);
|
||||
}
|
||||
} break;
|
||||
|
||||
|
@ -3093,8 +3093,7 @@ void History::clearUpTill(MsgId availableMinId) {
|
|||
owner().sendHistoryChangeNotifications();
|
||||
}
|
||||
|
||||
void History::applyGroupAdminChanges(
|
||||
const base::flat_map<UserId, bool> &changes) {
|
||||
void History::applyGroupAdminChanges(const base::flat_set<UserId> &changes) {
|
||||
for (const auto &block : blocks) {
|
||||
for (const auto &message : block->messages) {
|
||||
message->data()->applyGroupAdminChanges(changes);
|
||||
|
|
|
@ -90,8 +90,7 @@ public:
|
|||
void clear(ClearType type);
|
||||
void clearUpTill(MsgId availableMinId);
|
||||
|
||||
void applyGroupAdminChanges(
|
||||
const base::flat_map<UserId, bool> &changes);
|
||||
void applyGroupAdminChanges(const base::flat_set<UserId> &changes);
|
||||
|
||||
HistoryItem *addNewMessage(const MTPMessage &msg, NewMessageType type);
|
||||
HistoryItem *addToHistory(const MTPMessage &msg);
|
||||
|
|
|
@ -80,7 +80,7 @@ public:
|
|||
return true;
|
||||
}
|
||||
virtual void applyGroupAdminChanges(
|
||||
const base::flat_map<UserId, bool> &changes) {
|
||||
const base::flat_set<UserId> &changes) {
|
||||
}
|
||||
|
||||
UserData *viaBot() const;
|
||||
|
|
|
@ -637,30 +637,29 @@ bool HistoryMessage::updateDependencyItem() {
|
|||
}
|
||||
|
||||
void HistoryMessage::updateAdminBadgeState() {
|
||||
auto hasAdminBadge = [&] {
|
||||
if (auto channel = history()->peer->asChannel()) {
|
||||
if (auto user = author()->asUser()) {
|
||||
return channel->isGroupAdmin(user);
|
||||
}
|
||||
_adminBadge = [&] {
|
||||
const auto channel = history()->peer->asMegagroup();
|
||||
const auto user = author()->asUser();
|
||||
if (!channel || !user) {
|
||||
return QString();
|
||||
}
|
||||
return false;
|
||||
const auto info = channel->mgInfo.get();
|
||||
const auto i = channel->mgInfo->admins.find(peerToUser(user->id));
|
||||
return (i == channel->mgInfo->admins.end())
|
||||
? (info->creator != user
|
||||
? QString()
|
||||
: info->creatorRank.isEmpty()
|
||||
? tr::lng_admin_badge(tr::now)
|
||||
: info->creatorRank)
|
||||
: i->second.isEmpty()
|
||||
? tr::lng_admin_badge(tr::now)
|
||||
: i->second;
|
||||
}();
|
||||
if (hasAdminBadge) {
|
||||
_flags |= MTPDmessage_ClientFlag::f_has_admin_badge;
|
||||
} else {
|
||||
_flags &= ~MTPDmessage_ClientFlag::f_has_admin_badge;
|
||||
}
|
||||
}
|
||||
|
||||
void HistoryMessage::applyGroupAdminChanges(
|
||||
const base::flat_map<UserId, bool> &changes) {
|
||||
auto i = changes.find(peerToUser(author()->id));
|
||||
if (i != changes.end()) {
|
||||
if (i->second) {
|
||||
_flags |= MTPDmessage_ClientFlag::f_has_admin_badge;
|
||||
} else {
|
||||
_flags &= ~MTPDmessage_ClientFlag::f_has_admin_badge;
|
||||
}
|
||||
const base::flat_set<UserId> &changes) {
|
||||
if (!out() && changes.contains(peerToUser(author()->id))) {
|
||||
history()->owner().requestItemResize(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,13 +104,16 @@ public:
|
|||
[[nodiscard]] bool allowsEdit(TimeId now) const override;
|
||||
[[nodiscard]] bool uploading() const;
|
||||
|
||||
[[nodiscard]] QString adminBadge() const {
|
||||
return _adminBadge;
|
||||
}
|
||||
[[nodiscard]] bool hasAdminBadge() const {
|
||||
return _flags & MTPDmessage_ClientFlag::f_has_admin_badge;
|
||||
return !_adminBadge.isEmpty();
|
||||
}
|
||||
[[nodiscard]] bool hasMessageBadge() const;
|
||||
|
||||
void applyGroupAdminChanges(
|
||||
const base::flat_map<UserId, bool> &changes) override;
|
||||
const base::flat_set<UserId> &changes) override;
|
||||
|
||||
void setViewsCount(int32 count) override;
|
||||
void setRealId(MsgId newId) override;
|
||||
|
@ -179,6 +182,7 @@ private:
|
|||
|
||||
void updateAdminBadgeState();
|
||||
|
||||
QString _adminBadge;
|
||||
QString _timeText;
|
||||
int _timeWidth = 0;
|
||||
|
||||
|
|
|
@ -124,9 +124,8 @@ int KeyboardStyle::minButtonWidth(
|
|||
}
|
||||
|
||||
QString MessageBadgeText(not_null<const HistoryMessage*> message) {
|
||||
return message->hasAdminBadge()
|
||||
? tr::lng_admin_badge(tr::now)
|
||||
: tr::lng_channel_badge(tr::now);
|
||||
const auto result = message->adminBadge();
|
||||
return result.isEmpty() ? tr::lng_channel_badge(tr::now) : result;
|
||||
}
|
||||
|
||||
QString FastReplyText() {
|
||||
|
|
Loading…
Reference in New Issue