From b9d89cb4a01114c297c04e7c96e01d96ae77567d Mon Sep 17 00:00:00 2001 From: John Preston Date: Fri, 24 May 2019 12:32:43 +0200 Subject: [PATCH] Allow unlinking the discussion group. --- Telegram/Resources/langs/lang.strings | 2 +- .../boxes/peers/edit_linked_chat_box.cpp | 231 +++++++++++------- .../boxes/peers/edit_peer_info_box.cpp | 66 +++-- Telegram/SourceFiles/info/info.style | 9 +- 4 files changed, 209 insertions(+), 99 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 03baef8c0..b53f00e9b 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -847,7 +847,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_manage_discussion_group" = "Discussion"; "lng_manage_discussion_group_add" = "Add a group"; "lng_manage_linked_channel" = "Linked channel"; -"lng_manage_linked_channel_set" = "Set"; +"lng_manage_linked_channel_restore" = "Restore linked channel"; "lng_manage_discussion_group_about" = "Select a group chat for discussion that will be displayed in your channel."; "lng_manage_discussion_group_about_chosen" = "A link to {group} is shown to all subscribers in the bottom panel."; "lng_manage_discussion_group_create" = "Create a new group"; diff --git a/Telegram/SourceFiles/boxes/peers/edit_linked_chat_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_linked_chat_box.cpp index dec9f3049..0f6e2bcc3 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_linked_chat_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_linked_chat_box.cpp @@ -11,8 +11,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "data/data_channel.h" #include "ui/widgets/labels.h" #include "ui/wrap/vertical_layout.h" +#include "info/profile/info_profile_button.h" +#include "info/profile/info_profile_values.h" #include "boxes/peer_list_box.h" #include "styles/style_boxes.h" +#include "styles/style_info.h" namespace { @@ -23,6 +26,145 @@ TextWithEntities BoldText(const QString &text) { return result; } +class ListController + : public PeerListController + , public PeerListContentDelegate { +public: + ListController(Fn)> callback) + : _callback(std::move(callback)) { + } + void prepare() override { + } + void rowClicked(not_null row) override { + const auto onstack = _callback; + onstack(row->peer()->asChannel()); + } + void peerListSetTitle(Fn title) override { + } + void peerListSetAdditionalTitle(Fn title) override { + } + bool peerListIsRowSelected(not_null peer) override { + return false; + } + int peerListSelectedRowsCount() override { + return 0; + } + auto peerListCollectSelectedRows() + -> std::vector> override { + return {}; + } + void peerListScrollToTop() override { + } + void peerListAddSelectedRowInBunch( + not_null peer) override { + } + void peerListFinishSelectedRowsBunch() override { + } + void peerListSetDescription( + object_ptr description) override { + } + +private: + Fn)> _callback; + +}; + +object_ptr SetupList( + not_null parent, + not_null channel, + ChannelData *chat, + const std::vector> &chats, + Fn callback) { + const auto already = (chat != nullptr); + const auto selected = [=](not_null chat) { + if (already) { + Ui::showPeerHistory(chat, ShowAtUnreadMsgId); + } else { + callback(chat); + } + }; + const auto controller = Ui::CreateChild( + parent.get(), + selected); + controller->setDelegate(controller); + auto list = object_ptr( + parent, + controller, + st::peerListBox); + const auto createRow = [](not_null chat) { + auto result = std::make_unique(chat); + result->setCustomStatus(chat->isPublic() + ? ('@' + chat->username) + : lang(lng_manage_discussion_group_private)); + return result; + }; + if (chat) { + list->appendRow(createRow(chat)); + } else { + for (const auto chat : chats) { + list->appendRow(createRow(chat)); + } + } + return std::move(list); +} + +object_ptr SetupAbout( + not_null parent, + not_null channel, + ChannelData *chat) { + auto about = object_ptr( + parent, + QString(), + Ui::FlatLabel::InitType::Simple, + st::linkedChatAbout); + about->setMarkedText([&]() -> TextWithEntities { + if (!channel->isBroadcast()) { + return lng_manage_linked_channel_about__generic< + TextWithEntities + >(lt_channel, BoldText(chat->name)); + } else if (chat != nullptr) { + return lng_manage_discussion_group_about_chosen__generic< + TextWithEntities + >(lt_group, BoldText(chat->name)); + } else { + return { lang(lng_manage_discussion_group_about) }; + } + }()); + return std::move(about); +} + +object_ptr SetupCreateGroup( + not_null parent, + not_null channel) { + auto result = object_ptr( + parent, + Lang::Viewer( + lng_manage_discussion_group_create + ) | Info::Profile::ToUpperValue(), + st::infoCreateLinkedChatButton); + result->addClickHandler([=] { + + }); + return result; +} + +object_ptr SetupUnlink( + not_null parent, + not_null channel, + Fn callback) { + auto result = object_ptr( + parent, + Lang::Viewer(channel->isBroadcast() + ? lng_manage_discussion_group_unlink + : lng_manage_linked_channel_unlink + ) | Info::Profile::ToUpperValue(), + st::infoUnlinkChatButton); + result->addClickHandler([=] { + callback(nullptr); + }); + return result; +} + } // namespace EditLinkedChatBox::EditLinkedChatBox( @@ -51,90 +193,15 @@ object_ptr EditLinkedChatBox::setupContent( Expects(channel->isBroadcast() || (chat != nullptr)); auto result = object_ptr(this); - const auto about = result->add( - object_ptr( - result, - QString(), - Ui::FlatLabel::InitType::Simple, - st::linkedChatAbout), + result->add( + SetupAbout(result, channel, chat), st::linkedChatAboutPadding); - about->setMarkedText([&]() -> TextWithEntities { - if (!channel->isBroadcast()) { - return lng_manage_linked_channel_about__generic< - TextWithEntities - >(lt_channel, BoldText(chat->name)); - } else if (chat != nullptr) { - return lng_manage_discussion_group_about_chosen__generic< - TextWithEntities - >(lt_group, BoldText(chat->name)); - } else { - return { lang(lng_manage_discussion_group_about) }; - } - }()); - - class ListController - : public PeerListController - , public PeerListContentDelegate { - public: - ListController(Fn)> callback) - : _callback(std::move(callback)) { - } - void prepare() override { - } - void rowClicked(not_null row) override { - _callback(row->peer()->asChannel()); - } - void peerListSetTitle(Fn title) override { - } - void peerListSetAdditionalTitle(Fn title) override { - } - bool peerListIsRowSelected(not_null peer) override { - return false; - } - int peerListSelectedRowsCount() override { - return 0; - } - auto peerListCollectSelectedRows() - -> std::vector> override { - return {}; - } - void peerListScrollToTop() override { - } - void peerListAddSelectedRowInBunch( - not_null peer) override { - } - void peerListFinishSelectedRowsBunch() override { - } - void peerListSetDescription( - object_ptr description) override { - } - - private: - Fn)> _callback; - - }; - const auto controller = Ui::CreateChild(this, [=](not_null chat) { - const auto onstack = callback; - onstack(chat); - }); - controller->setDelegate(controller); - const auto list = result->add(object_ptr( - this, - controller, - st::peerListBox)); - const auto createRow = [](not_null chat) { - auto result = std::make_unique(chat); - result->setCustomStatus(chat->isPublic() - ? ('@' + chat->username) - : lang(lng_manage_discussion_group_private)); - return result; - }; + if (!chat) { + result->add(SetupCreateGroup(result, channel)); + } + result->add(SetupList(result, channel, chat, chats, callback)); if (chat) { - list->appendRow(createRow(chat)); - } else { - for (const auto chat : chats) { - list->appendRow(createRow(chat)); - } + result->add(SetupUnlink(result, channel, callback)); } return result; } diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp index ec1f026ad..b144dd99c 100644 --- a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp +++ b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp @@ -232,6 +232,7 @@ private: std::optional _privacySavedValue; std::optional _linkedChatSavedValue; + ChannelData *_linkedChatOriginalValue = nullptr; std::optional _historyVisibilitySavedValue; std::optional _usernameSavedValue; std::optional _signaturesSavedValue; @@ -522,6 +523,10 @@ void Controller::showEditLinkedChatBox() { return; } else if (_linkedChatsRequestId) { return; + } else if (channel->isMegagroup()) { + // Restore original linked channel. + callback(_linkedChatOriginalValue); + return; } _linkedChatsRequestId = _linkedChatsRequester.request( MTPchannels_GetGroupsForDiscussion() @@ -579,26 +584,39 @@ void Controller::fillPrivacyTypeButton() { void Controller::fillLinkedChatButton() { Expects(_controls.buttonsLayout != nullptr); - _linkedChatSavedValue = _peer->isChannel() + _linkedChatSavedValue = _linkedChatOriginalValue = _peer->isChannel() ? _peer->asChannel()->linkedChat() : nullptr; const auto isGroup = (_peer->isChat() || _peer->isMegagroup()); + auto text = !isGroup + ? Lang::Viewer(lng_manage_discussion_group) + : rpl::combine( + Lang::Viewer(lng_manage_linked_channel), + Lang::Viewer(lng_manage_linked_channel_restore), + _linkedChatUpdates.events() + ) | rpl::map([=]( + const QString &edit, + const QString &restore, + ChannelData *chat) { + return chat ? edit : restore; + }); + auto label = isGroup + ? _linkedChatUpdates.events() | rpl::map([](ChannelData *chat) { + return chat ? chat->name : QString(); + }) : rpl::combine( + Lang::Viewer(lng_manage_discussion_group_add), + _linkedChatUpdates.events() + ) | rpl::map([=](const QString &add, ChannelData *chat) { + return chat + ? chat->name + : add; + }); AddButtonWithText( _controls.buttonsLayout, - Lang::Viewer(isGroup - ? lng_manage_linked_channel - : lng_manage_discussion_group), - _linkedChatUpdates.events( - ) | rpl::map([=](ChannelData *channel) { - return channel - ? channel->name - : isGroup - ? lang(lng_manage_linked_channel_set) - : lang(lng_manage_discussion_group_add); - }), + std::move(text), + std::move(label), [=] { showEditLinkedChatBox(); }); - _linkedChatUpdates.fire_copy(*_linkedChatSavedValue); } @@ -782,6 +800,7 @@ void Controller::fillManageSection() { if (canEditPreHistoryHidden || canEditSignatures || canEditInviteLink + || canEditLinkedChat || canEditUsername) { AddSkip( _controls.buttonsLayout, @@ -1297,7 +1316,7 @@ object_ptr EditPeerInfoBox::CreateButton( const style::icon *icon) { auto result = object_ptr( parent, - std::move(text), + rpl::duplicate(text), st.button); const auto button = result.data(); button->addClickHandler(callback); @@ -1307,9 +1326,26 @@ object_ptr EditPeerInfoBox::CreateButton( *icon, st.iconPosition); } + + auto labelText = rpl::combine( + std::move(text), + std::move(count), + button->widthValue() + ) | rpl::map([&st](const QString &text, const QString &count, int width) { + const auto available = width + - st.button.padding.left() + - (st.button.font->spacew * 2) + - st.button.font->width(text) + - st.labelPosition.x(); + const auto required = st.label.style.font->width(count); + return (required > available) + ? st.label.style.font->elided(count, std::max(available, 0)) + : count; + }); + const auto label = Ui::CreateChild( button, - std::move(count), + std::move(labelText), st.label); label->setAttribute(Qt::WA_TransparentForMouseEvents); diff --git a/Telegram/SourceFiles/info/info.style b/Telegram/SourceFiles/info/info.style index 1577d60ac..f54d1569a 100644 --- a/Telegram/SourceFiles/info/info.style +++ b/Telegram/SourceFiles/info/info.style @@ -435,6 +435,13 @@ infoBlockButton: InfoProfileButton(infoProfileButton) { textFg: attentionButtonFg; textFgOver: attentionButtonFgOver; } +infoCreateLinkedChatButton: InfoProfileButton(infoMainButton) { + padding: margins(73px, 10px, 8px, 8px); +} +infoUnlinkChatButton: InfoProfileButton(infoCreateLinkedChatButton) { + textFg: attentionButtonFg; + textFgOver: attentionButtonFgOver; +} infoBlockButtonSkip: 8px; infoMembersHeader: 56px; @@ -610,7 +617,7 @@ manageGroupTopButtonWithText: InfoProfileCountButton(manageGroupButton) { button: InfoProfileButton(infoProfileButton) { padding: margins(22px, 10px, 24px, 8px); } - labelPosition: point(22px, 11px); + labelPosition: point(22px, 10px); iconPosition: point(0px, 0px); }