Save admins in legacy groups.

This commit is contained in:
John Preston 2019-01-10 16:38:57 +04:00
parent dba9ca2084
commit 07e010dfb5
6 changed files with 233 additions and 152 deletions

View File

@ -272,10 +272,11 @@ void AddSpecialBoxController::prepareChatRows(not_null<ChatData*> chat) {
using UpdateFlag = Notify::PeerUpdate::Flag; using UpdateFlag = Notify::PeerUpdate::Flag;
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler( subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(
UpdateFlag::MembersChanged, UpdateFlag::MembersChanged | UpdateFlag::AdminsChanged,
[=](const Notify::PeerUpdate &update) { [=](const Notify::PeerUpdate &update) {
if (update.flags & UpdateFlag::MembersChanged) {
if (update.peer == chat) { if (update.peer == chat) {
_additional.fillFromPeer();
if (update.flags & UpdateFlag::MembersChanged) {
rebuildChatRows(chat); rebuildChatRows(chat);
} }
} }
@ -505,9 +506,6 @@ void AddSpecialBoxController::showAdmin(
: MTPChatAdminRights(MTP_chatAdminRights(MTP_flags(0))); : MTPChatAdminRights(MTP_chatAdminRights(MTP_flags(0)));
auto box = Box<EditAdminBox>(_peer, user, currentRights); auto box = Box<EditAdminBox>(_peer, user, currentRights);
if (_additional.canAddOrEditAdmin(user)) { if (_additional.canAddOrEditAdmin(user)) {
if (chat) {
// #TODO groups autoconv
} else {
const auto done = crl::guard(this, [=]( const auto done = crl::guard(this, [=](
const MTPChatAdminRights &newRights) { const MTPChatAdminRights &newRights) {
editAdminDone(user, newRights); editAdminDone(user, newRights);
@ -517,9 +515,7 @@ void AddSpecialBoxController::showAdmin(
_editBox->closeBox(); _editBox->closeBox();
} }
}); });
box->setSaveCallback( box->setSaveCallback(SaveAdminCallback(_peer, user, done, fail));
SaveAdminCallback(channel, user, done, fail));
}
} }
_editBox = Ui::show(std::move(box), LayerOption::KeepOther); _editBox = Ui::show(std::move(box), LayerOption::KeepOther);
} }
@ -604,9 +600,7 @@ void AddSpecialBoxController::showRestricted(
user, user,
_additional.adminRights(user).has_value(), _additional.adminRights(user).has_value(),
currentRights); currentRights);
if (chat) { if (_additional.canRestrictUser(user)) {
// #TODO groups autoconv
} else {
const auto done = crl::guard(this, [=]( const auto done = crl::guard(this, [=](
const MTPChatBannedRights &newRights) { const MTPChatBannedRights &newRights) {
editRestrictedDone(user, newRights); editRestrictedDone(user, newRights);
@ -617,7 +611,7 @@ void AddSpecialBoxController::showRestricted(
} }
}); });
box->setSaveCallback( box->setSaveCallback(
SaveRestrictedCallback(channel, user, done, fail)); SaveRestrictedCallback(_peer, user, done, fail));
} }
_editBox = Ui::show(std::move(box), LayerOption::KeepOther); _editBox = Ui::show(std::move(box), LayerOption::KeepOther);
} }

View File

@ -37,7 +37,8 @@ void RemoveAdmin(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
not_null<UserData*> user, not_null<UserData*> user,
const MTPChatAdminRights &oldRights, const MTPChatAdminRights &oldRights,
Fn<void()> onDone) { Fn<void()> onDone,
Fn<void()> onFail) {
const auto newRights = MTP_chatAdminRights(MTP_flags(0)); const auto newRights = MTP_chatAdminRights(MTP_flags(0));
channel->session().api().request(MTPchannels_EditAdmin( channel->session().api().request(MTPchannels_EditAdmin(
channel->inputChannel, channel->inputChannel,
@ -46,46 +47,56 @@ void RemoveAdmin(
)).done([=](const MTPUpdates &result) { )).done([=](const MTPUpdates &result) {
channel->session().api().applyUpdates(result); channel->session().api().applyUpdates(result);
channel->applyEditAdmin(user, oldRights, newRights); channel->applyEditAdmin(user, oldRights, newRights);
onDone(); if (const auto done = onDone) {
done();
}
}).fail([=](const RPCError &error) {
if (const auto fail = onFail) {
fail();
}
}).send(); }).send();
} }
void EditChatAdmin( void SaveChatAdmin(
not_null<ChatData*> chat, not_null<ChatData*> chat,
not_null<UserData*> user, not_null<UserData*> user,
bool isAdmin, bool isAdmin,
Fn<void()> onDone) { Fn<void()> onDone,
Fn<void()> onFail) {
chat->session().api().request(MTPmessages_EditChatAdmin( chat->session().api().request(MTPmessages_EditChatAdmin(
chat->inputChat, chat->inputChat,
user->inputUser, user->inputUser,
MTP_bool(isAdmin) MTP_bool(isAdmin)
)).done([=](const MTPBool &result) { )).done([=](const MTPBool &result) {
chat->applyEditAdmin(user, isAdmin); chat->applyEditAdmin(user, isAdmin);
onDone(); if (const auto done = onDone) {
done();
}
}).fail([=](const RPCError &error) {
if (const auto fail = onFail) {
fail();
}
}).send(); }).send();
} }
} // namespace void SaveChannelAdmin(
Fn<void(
const MTPChatAdminRights &oldRights,
const MTPChatAdminRights &newRights)> SaveAdminCallback(
not_null<ChannelData*> channel, not_null<ChannelData*> channel,
not_null<UserData*> user, not_null<UserData*> user,
Fn<void(const MTPChatAdminRights &newRights)> onDone,
Fn<void()> onFail) {
return [=](
const MTPChatAdminRights &oldRights, const MTPChatAdminRights &oldRights,
const MTPChatAdminRights &newRights) { const MTPChatAdminRights &newRights,
auto done = [=](const MTPUpdates &result) { Fn<void()> onDone,
Fn<void()> onFail) {
channel->session().api().request(MTPchannels_EditAdmin(
channel->inputChannel,
user->inputUser,
newRights
)).done([=](const MTPUpdates &result) {
channel->session().api().applyUpdates(result); channel->session().api().applyUpdates(result);
channel->applyEditAdmin(user, oldRights, newRights); channel->applyEditAdmin(user, oldRights, newRights);
onDone(newRights); if (const auto done = onDone) {
}; done();
auto fail = [=](const RPCError &error) {
if (MTP::isDefaultHandledError(error)) {
return false;
} }
}).fail([=](const RPCError &error) {
if (error.type() == qstr("USER_NOT_MUTUAL_CONTACT")) { if (error.type() == qstr("USER_NOT_MUTUAL_CONTACT")) {
Ui::show( Ui::show(
Box<InformBox>(PeerFloodErrorText( Box<InformBox>(PeerFloodErrorText(
@ -104,48 +115,111 @@ Fn<void(
: lng_error_admin_limit_channel)), : lng_error_admin_limit_channel)),
LayerOption::KeepOther); LayerOption::KeepOther);
} }
onFail(); if (const auto fail = onFail) {
return true; fail();
}; }
MTP::send( }).send();
MTPchannels_EditAdmin( }
void SaveChannelRestriction(
not_null<ChannelData*> channel,
not_null<UserData*> user,
const MTPChatBannedRights &oldRights,
const MTPChatBannedRights &newRights,
Fn<void()> onDone,
Fn<void()> onFail) {
channel->session().api().request(MTPchannels_EditBanned(
channel->inputChannel, channel->inputChannel,
user->inputUser, user->inputUser,
newRights), newRights
rpcDone(std::move(done)), )).done([=](const MTPUpdates &result) {
rpcFail(std::move(fail))); const auto done = onDone;
channel->session().api().applyUpdates(result);
channel->applyEditBanned(user, oldRights, newRights);
if (const auto done = onDone) {
done();
}
}).fail([=](const RPCError &error) {
if (const auto fail = onFail) {
fail();
}
}).send();
}
} // namespace
Fn<void(
const MTPChatAdminRights &oldRights,
const MTPChatAdminRights &newRights)> SaveAdminCallback(
not_null<PeerData*> peer,
not_null<UserData*> user,
Fn<void(const MTPChatAdminRights &newRights)> onDone,
Fn<void()> onFail) {
return [=](
const MTPChatAdminRights &oldRights,
const MTPChatAdminRights &newRights) {
const auto done = [=] { onDone(newRights); };
if (const auto chat = peer->asChat()) {
const auto saveChatAdmin = [&](bool isAdmin) {
SaveChatAdmin(chat, user, isAdmin, done, onFail);
};
const auto flags = newRights.match([](
const MTPDchatAdminRights &data) {
return data.vflags.v;
});
if (flags == ChatData::DefaultAdminRights()) {
saveChatAdmin(true);
} else if (!flags) {
saveChatAdmin(false);
} else {
// #TODO groups autoconv
}
} else if (const auto channel = peer->asChannel()) {
SaveChannelAdmin(
channel,
user,
oldRights,
newRights,
done,
onFail);
} else {
Unexpected("Peer in SaveAdminCallback.");
}
}; };
} }
Fn<void( Fn<void(
const MTPChatBannedRights &oldRights, const MTPChatBannedRights &oldRights,
const MTPChatBannedRights &newRights)> SaveRestrictedCallback( const MTPChatBannedRights &newRights)> SaveRestrictedCallback(
not_null<ChannelData*> channel, not_null<PeerData*> peer,
not_null<UserData*> user, not_null<UserData*> user,
Fn<void(const MTPChatBannedRights &newRights)> onDone, Fn<void(const MTPChatBannedRights &newRights)> onDone,
Fn<void()> onFail) { Fn<void()> onFail) {
return [=]( return [=](
const MTPChatBannedRights &oldRights, const MTPChatBannedRights &oldRights,
const MTPChatBannedRights &newRights) { const MTPChatBannedRights &newRights) {
auto done = [=](const MTPUpdates &result) { const auto done = [=] { onDone(newRights); };
channel->session().api().applyUpdates(result); if (const auto chat = peer->asChat()) {
channel->applyEditBanned(user, oldRights, newRights); const auto flags = newRights.match([](
onDone(newRights); const MTPDchatBannedRights &data) {
}; return data.vflags.v;
auto fail = [=](const RPCError &error) { });
if (MTP::isDefaultHandledError(error)) { if (!flags) {
return false; done();
} else {
// #TODO groups autoconv
}
} else if (const auto channel = peer->asChannel()) {
SaveChannelRestriction(
channel,
user,
oldRights,
newRights,
done,
onFail);
} else {
Unexpected("Peer in SaveAdminCallback.");
} }
onFail();
return true;
};
MTP::send(
MTPchannels_EditBanned(
channel->inputChannel,
user->inputUser,
newRights),
rpcDone(std::move(done)),
rpcFail(std::move(fail)));
}; };
} }
@ -154,13 +228,7 @@ ParticipantsAdditionalData::ParticipantsAdditionalData(
Role role) Role role)
: _peer(peer) : _peer(peer)
, _role(role) { , _role(role) {
if (const auto chat = _peer->asChat()) { fillFromPeer();
_creator = chat->owner().userLoaded(chat->creator);
} else if (const auto channel = _peer->asChannel()) {
if (channel->mgInfo) {
_creator = channel->mgInfo->creator;
}
}
} }
bool ParticipantsAdditionalData::infoLoaded(not_null<UserData*> user) const { bool ParticipantsAdditionalData::infoLoaded(not_null<UserData*> user) const {
@ -294,6 +362,9 @@ void ParticipantsAdditionalData::fillFromPeer() {
} }
void ParticipantsAdditionalData::fillFromChat(not_null<ChatData*> chat) { void ParticipantsAdditionalData::fillFromChat(not_null<ChatData*> chat) {
if (const auto creator = chat->owner().userLoaded(chat->creator)) {
_creator = creator;
}
if (chat->participants.empty()) { if (chat->participants.empty()) {
return; return;
} }
@ -404,6 +475,10 @@ UserData *ParticipantsAdditionalData::applyAdmin(
const auto user = _peer->owner().userLoaded(data.vuser_id.v); const auto user = _peer->owner().userLoaded(data.vuser_id.v);
if (!user) { if (!user) {
return nullptr; return nullptr;
} else if (const auto chat = _peer->asChat()) {
// This can come from saveAdmin callback.
_admins.emplace(user);
return user;
} }
_infoNotLoaded.erase(user); _infoNotLoaded.erase(user);
@ -434,6 +509,10 @@ UserData *ParticipantsAdditionalData::applyRegular(MTPint userId) {
const auto user = _peer->owner().userLoaded(userId.v); const auto user = _peer->owner().userLoaded(userId.v);
if (!user) { if (!user) {
return nullptr; return nullptr;
} else if (const auto chat = _peer->asChat()) {
// This can come from saveAdmin or saveRestricted callback.
_admins.erase(user);
return user;
} }
_infoNotLoaded.erase(user); _infoNotLoaded.erase(user);
@ -883,18 +962,16 @@ void ParticipantsBoxController::prepareChatRows(not_null<ChatData*> chat) {
UpdateFlag::MembersChanged UpdateFlag::MembersChanged
| UpdateFlag::AdminsChanged, | UpdateFlag::AdminsChanged,
[=](const Notify::PeerUpdate &update) { [=](const Notify::PeerUpdate &update) {
if (update.flags & UpdateFlag::MembersChanged) { if (update.peer != chat) {
if (update.peer == chat) { return;
}
_additional.fillFromPeer();
if ((update.flags & UpdateFlag::MembersChanged)
|| (_role == Role::Admins)) {
rebuildChatRows(chat); rebuildChatRows(chat);
} }
} else if (update.flags & UpdateFlag::AdminsChanged) { if (update.flags & UpdateFlag::AdminsChanged) {
if (update.peer == chat) {
if (_role == Role::Members || _role == Role::Profile) {
rebuildRowTypes(); rebuildRowTypes();
} else if (_role == Role::Admins) {
rebuildChatRows(chat);
}
}
} }
})); }));
} }
@ -905,7 +982,7 @@ void ParticipantsBoxController::rebuildChatRows(not_null<ChatData*> chat) {
case Role::Members: return rebuildChatParticipants(chat); case Role::Members: return rebuildChatParticipants(chat);
case Role::Admins: return rebuildChatAdmins(chat); case Role::Admins: return rebuildChatAdmins(chat);
case Role::Restricted: case Role::Restricted:
case Role::Kicked: return; case Role::Kicked: return chatListReady();
} }
Unexpected("Role in ParticipantsBoxController::rebuildChatRows"); Unexpected("Role in ParticipantsBoxController::rebuildChatRows");
} }
@ -942,7 +1019,7 @@ void ParticipantsBoxController::rebuildChatParticipants(
_onlineSorter->sort(); _onlineSorter->sort();
delegate()->peerListRefreshRows(); delegate()->peerListRefreshRows();
setNonEmptyDescription(); chatListReady();
} }
void ParticipantsBoxController::rebuildChatAdmins( void ParticipantsBoxController::rebuildChatAdmins(
@ -992,10 +1069,25 @@ void ParticipantsBoxController::rebuildChatAdmins(
} }
delegate()->peerListRefreshRows(); delegate()->peerListRefreshRows();
chatListReady();
}
void ParticipantsBoxController::chatListReady() {
if (_allLoaded) {
return;
}
_allLoaded = true;
if (delegate()->peerListFullRowsCount() > 0) {
setNonEmptyDescription(); setNonEmptyDescription();
} else {
setDescriptionText(lang(lng_blocked_list_not_found));
}
} }
void ParticipantsBoxController::rebuildRowTypes() { void ParticipantsBoxController::rebuildRowTypes() {
if (_role != Role::Profile) {
return;
}
const auto count = delegate()->peerListFullRowsCount(); const auto count = delegate()->peerListFullRowsCount();
for (auto i = 0; i != count; ++i) { for (auto i = 0; i != count; ++i) {
const auto row = static_cast<Row*>( const auto row = static_cast<Row*>(
@ -1220,9 +1312,6 @@ void ParticipantsBoxController::showAdmin(not_null<UserData*> user) {
const auto chat = _peer->asChat(); const auto chat = _peer->asChat();
const auto channel = _peer->asChannel(); const auto channel = _peer->asChannel();
if (_additional.canAddOrEditAdmin(user)) { if (_additional.canAddOrEditAdmin(user)) {
if (chat) {
// #TODO groups autoconv
} else if (channel) {
const auto done = crl::guard(this, [=]( const auto done = crl::guard(this, [=](
const MTPChatAdminRights &newRights) { const MTPChatAdminRights &newRights) {
editAdminDone(user, newRights); editAdminDone(user, newRights);
@ -1232,9 +1321,7 @@ void ParticipantsBoxController::showAdmin(not_null<UserData*> user) {
_editBox->closeBox(); _editBox->closeBox();
} }
}); });
box->setSaveCallback( box->setSaveCallback(SaveAdminCallback(_peer, user, done, fail));
SaveAdminCallback(channel, user, done, fail));
}
} }
_editBox = Ui::show(std::move(box), LayerOption::KeepOther); _editBox = Ui::show(std::move(box), LayerOption::KeepOther);
} }
@ -1293,9 +1380,6 @@ void ParticipantsBoxController::showRestricted(not_null<UserData*> user) {
const auto chat = _peer->asChat(); const auto chat = _peer->asChat();
const auto channel = _peer->asChannel(); const auto channel = _peer->asChannel();
if (_additional.canRestrictUser(user)) { if (_additional.canRestrictUser(user)) {
if (chat) {
// #TODO groups autoconv
} else {
const auto done = crl::guard(this, [=]( const auto done = crl::guard(this, [=](
const MTPChatBannedRights &newRights) { const MTPChatBannedRights &newRights) {
editRestrictedDone(user, newRights); editRestrictedDone(user, newRights);
@ -1306,8 +1390,7 @@ void ParticipantsBoxController::showRestricted(not_null<UserData*> user) {
} }
}); });
box->setSaveCallback( box->setSaveCallback(
SaveRestrictedCallback(channel, user, done, fail)); SaveRestrictedCallback(_peer, user, done, fail));
}
} }
_editBox = Ui::show(std::move(box), LayerOption::KeepOther); _editBox = Ui::show(std::move(box), LayerOption::KeepOther);
} }
@ -1415,9 +1498,9 @@ void ParticipantsBoxController::removeAdminSure(not_null<UserData*> user) {
_editBox->closeBox(); _editBox->closeBox();
} }
if (const auto chat = _peer->asChat()) { if (const auto chat = _peer->asChat()) {
EditChatAdmin(chat, user, false, crl::guard(this, [=] { SaveChatAdmin(chat, user, false, crl::guard(this, [=] {
editAdminDone(user, MTP_chatAdminRights(MTP_flags(0))); editAdminDone(user, MTP_chatAdminRights(MTP_flags(0)));
})); }), nullptr);
} else if (const auto channel = _peer->asChannel()) { } else if (const auto channel = _peer->asChannel()) {
const auto adminRights = _additional.adminRights(user); const auto adminRights = _additional.adminRights(user);
if (!adminRights) { if (!adminRights) {
@ -1425,7 +1508,7 @@ void ParticipantsBoxController::removeAdminSure(not_null<UserData*> user) {
} }
RemoveAdmin(channel, user, *adminRights, crl::guard(this, [=] { RemoveAdmin(channel, user, *adminRights, crl::guard(this, [=] {
editAdminDone(user, MTP_chatAdminRights(MTP_flags(0))); editAdminDone(user, MTP_chatAdminRights(MTP_flags(0)));
})); }), nullptr);
} }
} }
@ -1530,7 +1613,7 @@ void ParticipantsBoxController::recomputeTypeFor(
if (_role != Role::Profile) { if (_role != Role::Profile) {
return; return;
} }
if (auto row = delegate()->peerListFindRow(user->id)) { if (const auto row = delegate()->peerListFindRow(user->id)) {
static_cast<Row*>(row)->setType(computeType(user)); static_cast<Row*>(row)->setType(computeType(user));
} }
} }

View File

@ -23,7 +23,7 @@ class Navigation;
Fn<void( Fn<void(
const MTPChatAdminRights &oldRights, const MTPChatAdminRights &oldRights,
const MTPChatAdminRights &newRights)> SaveAdminCallback( const MTPChatAdminRights &newRights)> SaveAdminCallback(
not_null<ChannelData*> channel, not_null<PeerData*> peer,
not_null<UserData*> user, not_null<UserData*> user,
Fn<void(const MTPChatAdminRights &newRights)> onDone, Fn<void(const MTPChatAdminRights &newRights)> onDone,
Fn<void()> onFail); Fn<void()> onFail);
@ -31,7 +31,7 @@ Fn<void(
Fn<void( Fn<void(
const MTPChatBannedRights &oldRights, const MTPChatBannedRights &oldRights,
const MTPChatBannedRights &newRights)> SaveRestrictedCallback( const MTPChatBannedRights &newRights)> SaveRestrictedCallback(
not_null<ChannelData*> channel, not_null<PeerData*> peer,
not_null<UserData*> user, not_null<UserData*> user,
Fn<void(const MTPChatBannedRights &newRights)> onDone, Fn<void(const MTPChatBannedRights &newRights)> onDone,
Fn<void()> onFail); Fn<void()> onFail);
@ -187,6 +187,7 @@ private:
void rebuildChatRows(not_null<ChatData*> chat); void rebuildChatRows(not_null<ChatData*> chat);
void rebuildChatParticipants(not_null<ChatData*> chat); void rebuildChatParticipants(not_null<ChatData*> chat);
void rebuildChatAdmins(not_null<ChatData*> chat); void rebuildChatAdmins(not_null<ChatData*> chat);
void chatListReady();
void rebuildRowTypes(); void rebuildRowTypes();
void addNewItem(); void addNewItem();

View File

@ -104,15 +104,15 @@ void ChatMembersController::prepare() {
| UpdateFlag::UserOnlineChanged | UpdateFlag::UserOnlineChanged
| UpdateFlag::AdminsChanged, | UpdateFlag::AdminsChanged,
[this](const Notify::PeerUpdate &update) { [this](const Notify::PeerUpdate &update) {
if (update.flags & UpdateFlag::MembersChanged) {
if (update.peer == _chat) { if (update.peer == _chat) {
if (update.flags & UpdateFlag::MembersChanged) {
rebuildRows(); rebuildRows();
} }
} else if (update.flags & UpdateFlag::AdminsChanged) { if (update.flags & UpdateFlag::AdminsChanged) {
if (update.peer == _chat) {
rebuildRowTypes(); rebuildRowTypes();
} }
} else if (update.flags & UpdateFlag::UserOnlineChanged) { }
if (update.flags & UpdateFlag::UserOnlineChanged) {
if (auto row = delegate()->peerListFindRow( if (auto row = delegate()->peerListFindRow(
update.peer->id)) { update.peer->id)) {
row->refreshStatus(); row->refreshStatus();

View File

@ -198,7 +198,9 @@ rpl::producer<int> AdminsCountValue(not_null<PeerData*> peer) {
chat, chat,
Flag::AdminsChanged | Flag::RightsChanged Flag::AdminsChanged | Flag::RightsChanged
) | rpl::map([=] { ) | rpl::map([=] {
return int(chat->admins.size()); return chat->participants.empty()
? 0
: int(chat->admins.size() + 1); // + creator
}); });
} else if (const auto channel = peer->asChannel()) { } else if (const auto channel = peer->asChannel()) {
return Notify::PeerUpdateValue( return Notify::PeerUpdateValue(

View File

@ -109,13 +109,14 @@ void GroupMembersWidget::notifyPeerUpdated(const Notify::PeerUpdate &update) {
if (update.flags & UpdateFlag::MembersChanged) { if (update.flags & UpdateFlag::MembersChanged) {
refreshMembers(); refreshMembers();
contentSizeUpdated(); contentSizeUpdated();
} else if (update.flags & UpdateFlag::AdminsChanged) { }
if (auto chat = peer()->asChat()) { if (update.flags & UpdateFlag::AdminsChanged) {
for_const (auto item, items()) { if (const auto chat = peer()->asChat()) {
for (const auto item : items()) {
setItemFlags(getMember(item), chat); setItemFlags(getMember(item), chat);
} }
} else if (auto megagroup = peer()->asMegagroup()) { } else if (const auto megagroup = peer()->asMegagroup()) {
for_const (auto item, items()) { for (const auto item : items()) {
setItemFlags(getMember(item), megagroup); setItemFlags(getMember(item), megagroup);
} }
} }