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;
subscribe(Notify::PeerUpdated(), Notify::PeerUpdatedHandler(
UpdateFlag::MembersChanged,
UpdateFlag::MembersChanged | UpdateFlag::AdminsChanged,
[=](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);
}
}
@ -505,21 +506,16 @@ void AddSpecialBoxController::showAdmin(
: MTPChatAdminRights(MTP_chatAdminRights(MTP_flags(0)));
auto box = Box<EditAdminBox>(_peer, user, currentRights);
if (_additional.canAddOrEditAdmin(user)) {
if (chat) {
// #TODO groups autoconv
} else {
const auto done = crl::guard(this, [=](
const MTPChatAdminRights &newRights) {
editAdminDone(user, newRights);
});
const auto fail = crl::guard(this, [=] {
if (_editBox) {
_editBox->closeBox();
}
});
box->setSaveCallback(
SaveAdminCallback(channel, user, done, fail));
}
const auto done = crl::guard(this, [=](
const MTPChatAdminRights &newRights) {
editAdminDone(user, newRights);
});
const auto fail = crl::guard(this, [=] {
if (_editBox) {
_editBox->closeBox();
}
});
box->setSaveCallback(SaveAdminCallback(_peer, user, done, fail));
}
_editBox = Ui::show(std::move(box), LayerOption::KeepOther);
}
@ -604,9 +600,7 @@ void AddSpecialBoxController::showRestricted(
user,
_additional.adminRights(user).has_value(),
currentRights);
if (chat) {
// #TODO groups autoconv
} else {
if (_additional.canRestrictUser(user)) {
const auto done = crl::guard(this, [=](
const MTPChatBannedRights &newRights) {
editRestrictedDone(user, newRights);
@ -617,7 +611,7 @@ void AddSpecialBoxController::showRestricted(
}
});
box->setSaveCallback(
SaveRestrictedCallback(channel, user, done, fail));
SaveRestrictedCallback(_peer, user, done, fail));
}
_editBox = Ui::show(std::move(box), LayerOption::KeepOther);
}

View File

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

View File

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

View File

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

View File

@ -198,7 +198,9 @@ rpl::producer<int> AdminsCountValue(not_null<PeerData*> peer) {
chat,
Flag::AdminsChanged | Flag::RightsChanged
) | 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()) {
return Notify::PeerUpdateValue(

View File

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