From 0f3ec470743602e1dc42e4bf60d502854d70f783 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Fri, 15 Mar 2019 11:20:12 +0300 Subject: [PATCH] Begin of EditPeerBox redesigning. - Moved buttons from ManageGroupBox to EditPeerBox. - Added counting of permissions. --- Telegram/Resources/langs/lang.strings | 4 + .../boxes/peers/edit_peer_info_box.cpp | 345 ++++++++++++++++++ .../boxes/peers/edit_peer_permissions_box.cpp | 31 +- Telegram/SourceFiles/data/data_peer.cpp | 18 + Telegram/SourceFiles/data/data_peer.h | 2 + Telegram/SourceFiles/info/info.style | 22 ++ .../info/profile/info_profile_values.cpp | 31 ++ .../info/profile/info_profile_values.h | 1 + .../SourceFiles/window/window_peer_menu.cpp | 4 +- 9 files changed, 442 insertions(+), 16 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 96411e51d0..7979575a67 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -803,6 +803,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_manage_peer_exceptions" = "Exceptions"; "lng_manage_peer_removed_users" = "Removed users"; "lng_manage_peer_permissions" = "Permissions"; + +"lng_manage_peer_group_type" = "Group type"; +"lng_manage_private_group_title" = "Private"; + "lng_manage_history_visibility_title" = "Chat history for new members"; "lng_manage_history_visibility_shown" = "Visible"; "lng_manage_history_visibility_shown_about" = "New members will see messages that were sent before they joined."; diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp index 8c266990c1..495bebd6f2 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp @@ -38,6 +38,237 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_boxes.h" #include "styles/style_info.h" +#include "ui/rp_widget.h" +#include "boxes/peers/edit_peer_permissions_box.h" + +#include "info/profile/info_profile_button.h" +#include "info/profile/info_profile_icon.h" +#include "info/profile/info_profile_values.h" + +#include "mainwindow.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(); + }); +} + +auto ToPositiveNumberStringRestrictions() { + return rpl::map([](int count) { + return QString::number(count) + + QString("/") + + QString::number(int(Data::ListOfRestrictions().size())); + }); +} + +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::manageGroupButton, + &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::manageGroupButton, + &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 (chat->canEditPermissions()) { + AddButtonWithCount( + content, + Lang::Viewer(lng_manage_peer_permissions), + Info::Profile::RestrictionsCountValue(chat) + | ToPositiveNumberStringRestrictions(), + [=] { 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 (channel->canEditPermissions()) { + AddButtonWithCount( + content, + Lang::Viewer(lng_manage_peer_permissions), + Info::Profile::RestrictionsCountValue(channel) + | ToPositiveNumberStringRestrictions(), + [=] { 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); + } + if (HasRecentActions(channel)) { + AddButton( + content, + Lang::Viewer(lng_manage_peer_recent_actions), + [=] { ShowRecentActions(navigation, channel); }, + st::infoIconRecentActions); + } +} + +} // namespace + namespace { constexpr auto kUsernameCheckTimeout = crl::time(200); @@ -113,6 +344,9 @@ private: object_ptr createStickersEdit(); object_ptr createDeleteButton(); + object_ptr createPrivaciesButtons(); + object_ptr createManageGroupButtons(); + QString inviteLinkText() const; void observeInviteLink(); @@ -221,8 +455,26 @@ object_ptr Controller::createContent() { _wrap.reset(result.data()); _controls = Controls(); + const auto addSkip = [](not_null container) { + container->add(object_ptr( + container, + 7 /*Create skip in style.*/)); + container->add(object_ptr(container)); + /*container->add(object_ptr( + container, + st::editPeerPrivacyTopSkip));*/ + }; + _wrap->add(createPhotoAndTitleEdit()); _wrap->add(createDescriptionEdit()); + + addSkip(_wrap); // Divider. + _wrap->add(createPrivaciesButtons()); + addSkip(_wrap); // Divider. + + _wrap->add(createManageGroupButtons()); + addSkip(_wrap); // Divider. + _wrap->add(createPrivaciesEdit()); _wrap->add(createInviteLinkCreate()); _wrap->add(createInviteLinkEdit()); @@ -429,6 +681,99 @@ object_ptr Controller::createPrivaciesEdit() { return std::move(result); } + +object_ptr Controller::createPrivaciesButtons() { + Expects(_wrap != nullptr); + + const auto canEditUsername = [&] { + if (const auto chat = _peer->asChat()) { + return chat->canEditUsername(); + } else if (const auto channel = _peer->asChannel()) { + return channel->canEditUsername(); + } + Unexpected("Peer type in Controller::createPrivaciesEdit."); + }(); + if (!canEditUsername) { + return nullptr; + } + auto result = object_ptr>( + _wrap, + object_ptr(_wrap), + st::editHehMargins); + auto container = result->entity(); + + const auto addPrivaciesButton = [=, &container](LangKey privacyTextKey) { + const auto button = container->add(object_ptr( + container, + std::move(Lang::Viewer(privacyTextKey)), + st::heeehButton + )); + }; + + addPrivaciesButton(lng_manage_peer_group_type); + addPrivaciesButton(lng_manage_history_visibility_title); + + // style::InfoProfileCountButton a = st::heehPermissionsButton; + // const auto name = Ui::CreateChild( + // button, + // std::move(rpl::single(QString("Heh"))), + // a.label); + // rpl::combine( + // button->widthValue(), + // std::move(rpl::single(QString("Heh"))), + // std::move(rpl::single(QString("Heh"))) + // ) | rpl::start_with_next([=, &a]( + // int width, + // const QString &button, + // const QString &text) { + // /*const auto available = width + // - a.padding.left() + // - a.padding.right() + // - a.font->width(button) + // - st::hehButtonRightSkip; + // name->setText(text); + // name->resizeToNaturalWidth(available); + // name->moveToRight(st::hehButtonRightSkip, st.padding.top());*/ + // }, name->lifetime()); + // name->setAttribute(Qt::WA_TransparentForMouseEvents); + + + // style::InfoProfileCountButton a = st::managePeerButton; + // const auto label = Ui::CreateChild( + // button, + // std::move(rpl::single(QString("5"))), + // a.label); + // label->setAttribute(Qt::WA_TransparentForMouseEvents); + // rpl::combine( + // button->widthValue(), + // label->widthValue() + // ) | rpl::start_with_next([=, &a](int outerWidth, int width) { + // LOG(("POSITION: %1 %2").arg(a.labelPosition.x()).arg(a.labelPosition.y())); + // label->moveToRight(0, 0); + // }, label->lifetime()); + + return std::move(result); +} + +object_ptr Controller::createManageGroupButtons() { + Expects(_wrap != nullptr); + + auto result = object_ptr>( + _wrap, + object_ptr(_wrap), + st::editHehMargins); + auto container = result->entity(); + + if (const auto chat = _peer->asChat()) { + FillManageChatBox(App::wnd()->controller(), chat, container); + } else if (const auto channel = _peer->asChannel()) { + FillManageChannelBox(App::wnd()->controller(), channel, container); + } + // setDimensionsToContent(st::boxWidth, content); + + return std::move(result); +} + object_ptr Controller::createUsernameEdit() { Expects(_wrap != nullptr); diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp index e27b885fae..a17caa59fc 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_permissions_box.cpp @@ -80,21 +80,24 @@ void ApplyDependencies( } std::vector> RestrictionLabels() { - using Flag = ChatRestriction; - - return { - { Flag::f_send_messages, lng_rights_chat_send_text }, - { Flag::f_send_media, lng_rights_chat_send_media }, - { Flag::f_send_stickers - | Flag::f_send_gifs - | Flag::f_send_games - | Flag::f_send_inline, lng_rights_chat_send_stickers }, - { Flag::f_embed_links, lng_rights_chat_send_links }, - { Flag::f_send_polls, lng_rights_chat_send_polls }, - { Flag::f_invite_users, lng_rights_chat_add_members }, - { Flag::f_pin_messages, lng_rights_group_pin }, - { Flag::f_change_info, lng_rights_group_info }, + const auto langKeys = { + lng_rights_chat_send_text, + lng_rights_chat_send_media, + lng_rights_chat_send_stickers, + lng_rights_chat_send_links, + lng_rights_chat_send_polls, + lng_rights_chat_add_members, + lng_rights_group_pin, + lng_rights_group_info, }; + + std::vector> vector; + const auto restrictions = Data::ListOfRestrictions(); + auto i = 0; + for (const auto key : langKeys) { + vector.push_back({restrictions[i++], key}); + } + return vector; } std::vector> AdminRightLabels( diff --git a/Telegram/SourceFiles/data/data_peer.cpp b/Telegram/SourceFiles/data/data_peer.cpp index d5e7ec807d..73497e779c 100644 --- a/Telegram/SourceFiles/data/data_peer.cpp +++ b/Telegram/SourceFiles/data/data_peer.cpp @@ -644,6 +644,24 @@ Data::RestrictionCheckResult PeerData::amRestricted( namespace Data { +std::vector ListOfRestrictions() { + using Flag = ChatRestriction; + + return { + Flag::f_send_messages, + Flag::f_send_media, + Flag::f_send_stickers + | Flag::f_send_gifs + | Flag::f_send_games + | Flag::f_send_inline, + Flag::f_embed_links, + Flag::f_send_polls, + Flag::f_invite_users, + Flag::f_pin_messages, + Flag::f_change_info, + }; +} + std::optional RestrictionErrorKey( not_null peer, ChatRestriction restriction) { diff --git a/Telegram/SourceFiles/data/data_peer.h b/Telegram/SourceFiles/data/data_peer.h index 2acaee5562..aa9ef401e5 100644 --- a/Telegram/SourceFiles/data/data_peer.h +++ b/Telegram/SourceFiles/data/data_peer.h @@ -338,6 +338,8 @@ private: namespace Data { +std::vector ListOfRestrictions(); + std::optional RestrictionErrorKey( not_null peer, ChatRestriction restriction); diff --git a/Telegram/SourceFiles/info/info.style b/Telegram/SourceFiles/info/info.style index 216d6905ed..50a1db6d28 100644 --- a/Telegram/SourceFiles/info/info.style +++ b/Telegram/SourceFiles/info/info.style @@ -597,6 +597,26 @@ peerPermissionsButton: InfoProfileCountButton(managePeerButton) { iconPosition: point(24px, 5px); } + +manageGroupButton: InfoProfileCountButton(managePeerButton) { + button: InfoProfileButton(infoProfileButton) { + padding: margins(72px, 12px, 24px, 10px); + } + iconPosition: point(20px, 5px); +} + +heeehButton: InfoProfileButton(infoProfileButton) { + font: boxTextFont; + padding: margins(23px, 10px, 22px, 11px); +} + +hehButtonRightSkip: 28px; +hehButtonRight: FlatLabel(defaultFlatLabel) { + textFg: windowActiveTextFg; + style: boxTextStyle; + maxHeight: 20px; +} + terminateSessionsButton: InfoProfileButton(infoBlockButton) { padding: margins(23px, 12px, 23px, 10px); } @@ -616,6 +636,8 @@ infoEmptyLabel: FlatLabel(defaultFlatLabel) { textFg: windowSubTextFg; } +editHehMargins: margins(0px, 10px, 0px, 0px); + editPeerDeleteButtonMargins: margins(23px, 16px, 23px, 16px); editPeerDeleteButton: sessionTerminateAllButton; editPeerPhotoMargins: margins(23px, 16px, 23px, 8px); diff --git a/Telegram/SourceFiles/info/profile/info_profile_values.cpp b/Telegram/SourceFiles/info/profile/info_profile_values.cpp index 9164aa965f..bab3820101 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_values.cpp +++ b/Telegram/SourceFiles/info/profile/info_profile_values.cpp @@ -23,6 +23,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_user.h" #include "data/data_session.h" +#include "boxes/peers/edit_peer_permissions_box.h" + namespace Info { namespace Profile { @@ -215,6 +217,35 @@ rpl::producer AdminsCountValue(not_null peer) { Unexpected("User in AdminsCountValue()."); } + +rpl::producer RestrictionsCountValue(not_null peer) { + const auto countOfRestrictions = [](ChatRestrictions restrictions) { + auto count = 0; + for (const auto f : Data::ListOfRestrictions()) { + if (restrictions & f) count++; + } + return int(Data::ListOfRestrictions().size()) - count; + }; + + using Flag = Notify::PeerUpdate::Flag; + if (const auto chat = peer->asChat()) { + return Notify::PeerUpdateValue( + chat, + Flag::RightsChanged + ) | rpl::map([=] { + return countOfRestrictions(chat->defaultRestrictions()); + }); + } else if (const auto channel = peer->asChannel()) { + return Notify::PeerUpdateValue( + channel, + Flag::RightsChanged + ) | rpl::map([=] { + return countOfRestrictions(channel->defaultRestrictions()); + }); + } + Unexpected("User in RestrictionsCountValue()."); +} + rpl::producer RestrictedCountValue(not_null channel) { using Flag = Notify::PeerUpdate::Flag; return Notify::PeerUpdateValue( diff --git a/Telegram/SourceFiles/info/profile/info_profile_values.h b/Telegram/SourceFiles/info/profile/info_profile_values.h index 869a54482e..5b8481fb93 100644 --- a/Telegram/SourceFiles/info/profile/info_profile_values.h +++ b/Telegram/SourceFiles/info/profile/info_profile_values.h @@ -56,6 +56,7 @@ rpl::producer CanAddContactValue(not_null user); rpl::producer AmInChannelValue(not_null channel); rpl::producer MembersCountValue(not_null peer); rpl::producer AdminsCountValue(not_null peer); +rpl::producer RestrictionsCountValue(not_null peer); rpl::producer RestrictedCountValue(not_null channel); rpl::producer KickedCountValue(not_null channel); rpl::producer SharedMediaCountValue( diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp index cfafaaf4c2..2dc85e7822 100644 --- a/Telegram/SourceFiles/window/window_peer_menu.cpp +++ b/Telegram/SourceFiles/window/window_peer_menu.cpp @@ -358,7 +358,7 @@ void Filler::addChatActions(not_null chat) { if (ManagePeerBox::Available(chat)) { const auto text = lang(lng_manage_group_title); _addAction(text, [=] { - Ui::show(Box(chat)); + Ui::show(Box(chat)); }); } if (chat->canAddMembers()) { @@ -402,7 +402,7 @@ void Filler::addChannelActions(not_null channel) { ? lng_manage_group_title : lng_manage_channel_title); _addAction(text, [channel] { - Ui::show(Box(channel)); + Ui::show(Box(channel)); }); } if (channel->canAddMembers()) {