/* 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 */ #include "boxes/peers/manage_peer_box.h" #include #include "lang/lang_keys.h" #include "boxes/peers/edit_peer_info_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/widgets/labels.h" #include "history/admin_log/history_admin_log_section.h" #include "window/window_controller.h" #include "info/profile/info_profile_button.h" #include "info/profile/info_profile_icon.h" #include "info/profile/info_profile_values.h" #include "data/data_channel.h" #include "data/data_chat.h" #include "mainwindow.h" #include "auth_session.h" #include "apiwrap.h" #include "styles/style_boxes.h" #include "styles/style_info.h" namespace { Fn ManagePeerTitle(not_null peer) { return langFactory((peer->isChat() || peer->isMegagroup()) ? lng_manage_group_title : lng_manage_channel_title); } auto ToPositiveNumberString() { return rpl::map([](int count) { return count ? QString::number(count) : QString(); }); } Info::Profile::Button *AddButton( not_null parent, rpl::producer &&text, Fn callback, const style::icon &icon) { return ManagePeerBox::CreateButton( parent, std::move(text), rpl::single(QString()), std::move(callback), st::managePeerButton, &icon); } void AddButtonWithCount( not_null parent, rpl::producer &&text, rpl::producer &&count, Fn callback, const style::icon &icon) { ManagePeerBox::CreateButton( parent, std::move(text), std::move(count), std::move(callback), st::managePeerButton, &icon); } bool HasRecentActions(not_null channel) { return channel->hasAdminRights() || channel->amCreator(); } void ShowRecentActions( not_null navigation, not_null channel) { navigation->showSection(AdminLog::SectionMemento(channel)); } bool HasEditInfoBox(not_null peer) { if (const auto chat = peer->asChat()) { if (chat->canEditInformation()) { return true; } } else if (const auto channel = peer->asChannel()) { if (channel->canEditInformation()) { return true; } else if (!channel->isPublic() && channel->canAddMembers()) { // Edit invite link. return true; } } return false; } void ShowEditPermissions(not_null peer) { const auto box = Ui::show( Box(peer), LayerOption::KeepOther); box->saveEvents( ) | rpl::start_with_next([=](MTPDchatBannedRights::Flags restrictions) { const auto callback = crl::guard(box, [=](bool success) { if (success) { box->closeBox(); } }); peer->session().api().saveDefaultRestrictions( peer->migrateToOrMe(), MTP_chatBannedRights(MTP_flags(restrictions), MTP_int(0)), callback); }, box->lifetime()); } void FillManageChatBox( not_null navigation, not_null chat, not_null content) { if (HasEditInfoBox(chat)) { AddButton( content, Lang::Viewer(lng_manage_group_info), [=] { Ui::show(Box(chat)); }, st::infoIconInformation); } if (chat->canEditPermissions()) { AddButton( content, Lang::Viewer(lng_manage_peer_permissions), [=] { ShowEditPermissions(chat); }, st::infoIconPermissions); } if (chat->amIn()) { AddButtonWithCount( content, Lang::Viewer(lng_manage_peer_administrators), Info::Profile::AdminsCountValue(chat) | ToPositiveNumberString(), [=] { ParticipantsBoxController::Start( navigation, chat, ParticipantsBoxController::Role::Admins); }, st::infoIconAdministrators); AddButtonWithCount( content, Lang::Viewer(lng_manage_peer_members), Info::Profile::MembersCountValue(chat) | ToPositiveNumberString(), [=] { ParticipantsBoxController::Start( navigation, chat, ParticipantsBoxController::Role::Members); }, st::infoIconMembers); } } void FillManageChannelBox( not_null navigation, not_null channel, not_null content) { auto isGroup = channel->isMegagroup(); if (HasEditInfoBox(channel)) { AddButton( content, Lang::Viewer(isGroup ? lng_manage_group_info : lng_manage_channel_info), [=] { Ui::show(Box(channel)); }, st::infoIconInformation); } if (HasRecentActions(channel)) { AddButton( content, Lang::Viewer(lng_manage_peer_recent_actions), [=] { ShowRecentActions(navigation, channel); }, st::infoIconRecentActions); } if (channel->canEditPermissions()) { AddButton( content, Lang::Viewer(lng_manage_peer_permissions), [=] { ShowEditPermissions(channel); }, st::infoIconPermissions); } if (channel->canViewAdmins()) { AddButtonWithCount( content, Lang::Viewer(lng_manage_peer_administrators), Info::Profile::AdminsCountValue(channel) | ToPositiveNumberString(), [=] { ParticipantsBoxController::Start( navigation, channel, ParticipantsBoxController::Role::Admins); }, st::infoIconAdministrators); } if (channel->canViewMembers()) { AddButtonWithCount( content, Lang::Viewer(lng_manage_peer_members), Info::Profile::MembersCountValue(channel) | ToPositiveNumberString(), [=] { ParticipantsBoxController::Start( navigation, channel, ParticipantsBoxController::Role::Members); }, st::infoIconMembers); } if (!channel->isMegagroup()) { AddButtonWithCount( content, Lang::Viewer(lng_manage_peer_removed_users), Info::Profile::KickedCountValue(channel) | ToPositiveNumberString(), [=] { ParticipantsBoxController::Start( navigation, channel, ParticipantsBoxController::Role::Kicked); }, st::infoIconBlacklist); } } } // namespace ManagePeerBox::ManagePeerBox( QWidget*, not_null peer) : _peer(peer) { } bool ManagePeerBox::Available(not_null peer) { if (const auto chat = peer->asChat()) { return false || chat->canEditInformation() || chat->canEditPermissions(); } else if (const auto channel = peer->asChannel()) { // canViewMembers() is removed, because in supergroups you // see them in profile and in channels only admins can see them. // canViewAdmins() is removed, because in supergroups it is // always true and in channels it is equal to canViewBanned(). return false //|| channel->canViewMembers() //|| channel->canViewAdmins() || channel->canViewBanned() || channel->canEditInformation() || channel->canEditPermissions() || HasRecentActions(channel); } else { return false; } } Info::Profile::Button *ManagePeerBox::CreateButton( not_null parent, rpl::producer &&text, rpl::producer &&count, Fn callback, const style::InfoProfileCountButton &st, const style::icon *icon) { const auto button = parent->add( object_ptr( parent, std::move(text), st.button)); button->addClickHandler(callback); if (icon) { Ui::CreateChild( button, *icon, st.iconPosition); } const auto label = Ui::CreateChild( button, std::move(count), st.label); label->setAttribute(Qt::WA_TransparentForMouseEvents); rpl::combine( button->widthValue(), label->widthValue() ) | rpl::start_with_next([=, &st](int outerWidth, int width) { label->moveToRight( st.labelPosition.x(), st.labelPosition.y(), outerWidth); }, label->lifetime()); return button; } void ManagePeerBox::prepare() { _peer->updateFull(); setTitle(ManagePeerTitle(_peer)); addButton(langFactory(lng_cancel), [=] { closeBox(); }); setupContent(); } void ManagePeerBox::setupContent() { const auto content = Ui::CreateChild(this); if (const auto chat = _peer->asChat()) { FillManageChatBox(App::wnd()->controller(), chat, content); } else if (const auto channel = _peer->asChannel()) { FillManageChannelBox(App::wnd()->controller(), channel, content); } setDimensionsToContent(st::boxWidth, content); }