Allow unlinking the discussion group.

This commit is contained in:
John Preston 2019-05-24 12:32:43 +02:00
parent f0eba3e283
commit b9d89cb4a0
4 changed files with 209 additions and 99 deletions

View File

@ -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";

View File

@ -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<void(not_null<ChannelData*>)> callback)
: _callback(std::move(callback)) {
}
void prepare() override {
}
void rowClicked(not_null<PeerListRow*> row) override {
const auto onstack = _callback;
onstack(row->peer()->asChannel());
}
void peerListSetTitle(Fn<QString()> title) override {
}
void peerListSetAdditionalTitle(Fn<QString()> title) override {
}
bool peerListIsRowSelected(not_null<PeerData*> peer) override {
return false;
}
int peerListSelectedRowsCount() override {
return 0;
}
auto peerListCollectSelectedRows()
-> std::vector<not_null<PeerData*>> override {
return {};
}
void peerListScrollToTop() override {
}
void peerListAddSelectedRowInBunch(
not_null<PeerData*> peer) override {
}
void peerListFinishSelectedRowsBunch() override {
}
void peerListSetDescription(
object_ptr<Ui::FlatLabel> description) override {
}
private:
Fn<void(not_null<ChannelData*>)> _callback;
};
object_ptr<Ui::RpWidget> SetupList(
not_null<QWidget*> parent,
not_null<ChannelData*> channel,
ChannelData *chat,
const std::vector<not_null<ChannelData*>> &chats,
Fn<void(ChannelData*)> callback) {
const auto already = (chat != nullptr);
const auto selected = [=](not_null<ChannelData*> chat) {
if (already) {
Ui::showPeerHistory(chat, ShowAtUnreadMsgId);
} else {
callback(chat);
}
};
const auto controller = Ui::CreateChild<ListController>(
parent.get(),
selected);
controller->setDelegate(controller);
auto list = object_ptr<PeerListContent>(
parent,
controller,
st::peerListBox);
const auto createRow = [](not_null<ChannelData*> chat) {
auto result = std::make_unique<PeerListRow>(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<Ui::RpWidget> SetupAbout(
not_null<QWidget*> parent,
not_null<ChannelData*> channel,
ChannelData *chat) {
auto about = object_ptr<Ui::FlatLabel>(
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<Ui::RpWidget> SetupCreateGroup(
not_null<QWidget*> parent,
not_null<ChannelData*> channel) {
auto result = object_ptr<Info::Profile::Button>(
parent,
Lang::Viewer(
lng_manage_discussion_group_create
) | Info::Profile::ToUpperValue(),
st::infoCreateLinkedChatButton);
result->addClickHandler([=] {
});
return result;
}
object_ptr<Ui::RpWidget> SetupUnlink(
not_null<QWidget*> parent,
not_null<ChannelData*> channel,
Fn<void(ChannelData*)> callback) {
auto result = object_ptr<Info::Profile::Button>(
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<Ui::RpWidget> EditLinkedChatBox::setupContent(
Expects(channel->isBroadcast() || (chat != nullptr));
auto result = object_ptr<Ui::VerticalLayout>(this);
const auto about = result->add(
object_ptr<Ui::FlatLabel>(
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<void(not_null<ChannelData*>)> callback)
: _callback(std::move(callback)) {
}
void prepare() override {
}
void rowClicked(not_null<PeerListRow*> row) override {
_callback(row->peer()->asChannel());
}
void peerListSetTitle(Fn<QString()> title) override {
}
void peerListSetAdditionalTitle(Fn<QString()> title) override {
}
bool peerListIsRowSelected(not_null<PeerData*> peer) override {
return false;
}
int peerListSelectedRowsCount() override {
return 0;
}
auto peerListCollectSelectedRows()
-> std::vector<not_null<PeerData*>> override {
return {};
}
void peerListScrollToTop() override {
}
void peerListAddSelectedRowInBunch(
not_null<PeerData*> peer) override {
}
void peerListFinishSelectedRowsBunch() override {
}
void peerListSetDescription(
object_ptr<Ui::FlatLabel> description) override {
}
private:
Fn<void(not_null<ChannelData*>)> _callback;
};
const auto controller = Ui::CreateChild<ListController>(this, [=](not_null<ChannelData*> chat) {
const auto onstack = callback;
onstack(chat);
});
controller->setDelegate(controller);
const auto list = result->add(object_ptr<PeerListContent>(
this,
controller,
st::peerListBox));
const auto createRow = [](not_null<ChannelData*> chat) {
auto result = std::make_unique<PeerListRow>(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;
}

View File

@ -232,6 +232,7 @@ private:
std::optional<Privacy> _privacySavedValue;
std::optional<ChannelData*> _linkedChatSavedValue;
ChannelData *_linkedChatOriginalValue = nullptr;
std::optional<HistoryVisibility> _historyVisibilitySavedValue;
std::optional<QString> _usernameSavedValue;
std::optional<bool> _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<Info::Profile::Button> EditPeerInfoBox::CreateButton(
const style::icon *icon) {
auto result = object_ptr<Info::Profile::Button>(
parent,
std::move(text),
rpl::duplicate(text),
st.button);
const auto button = result.data();
button->addClickHandler(callback);
@ -1307,9 +1326,26 @@ object_ptr<Info::Profile::Button> 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<Ui::FlatLabel>(
button,
std::move(count),
std::move(labelText),
st.label);
label->setAttribute(Qt::WA_TransparentForMouseEvents);

View File

@ -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);
}