tdesktop/Telegram/SourceFiles/boxes/peers/edit_linked_chat_box.cpp

350 lines
8.9 KiB
C++
Raw Normal View History

/*
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/edit_linked_chat_box.h"
#include "lang/lang_keys.h"
#include "data/data_channel.h"
#include "data/data_chat.h"
#include "ui/widgets/labels.h"
#include "ui/widgets/buttons.h"
#include "ui/wrap/vertical_layout.h"
2019-06-17 16:59:43 +00:00
#include "ui/text/text_utilities.h" // Ui::Text::ToUpper
#include "boxes/peer_list_box.h"
#include "boxes/confirm_box.h"
#include "boxes/add_contact_box.h"
#include "apiwrap.h"
#include "facades.h"
2019-07-24 11:45:24 +00:00
#include "main/main_session.h"
2019-09-18 11:19:05 +00:00
#include "styles/style_layers.h"
#include "styles/style_boxes.h"
2019-05-24 10:32:43 +00:00
#include "styles/style_info.h"
namespace {
constexpr auto kEnableSearchRowsCount = 10;
class Controller : public PeerListController, public base::has_weak_ptr {
2019-05-24 10:32:43 +00:00
public:
Controller(
not_null<ChannelData*> channel,
ChannelData *chat,
const std::vector<not_null<PeerData*>> &chats,
Fn<void(ChannelData*)> callback);
2019-07-25 18:55:11 +00:00
Main::Session &session() const override;
void prepare() override;
void rowClicked(not_null<PeerListRow*> row) override;
int contentWidth() const override;
2019-05-24 10:32:43 +00:00
private:
void choose(not_null<ChannelData*> chat);
void choose(not_null<ChatData*> chat);
not_null<ChannelData*> _channel;
ChannelData *_chat = nullptr;
std::vector<not_null<PeerData*>> _chats;
Fn<void(ChannelData*)> _callback;
2019-05-24 10:32:43 +00:00
ChannelData *_waitForFull = nullptr;
2019-05-24 10:32:43 +00:00
};
Controller::Controller(
not_null<ChannelData*> channel,
ChannelData *chat,
const std::vector<not_null<PeerData*>> &chats,
Fn<void(ChannelData*)> callback)
: _channel(channel)
, _chat(chat)
, _chats(std::move(chats))
, _callback(std::move(callback)) {
base::ObservableViewer(
channel->session().api().fullPeerUpdated()
) | rpl::start_with_next([=](PeerData *peer) {
if (peer == _waitForFull) {
choose(std::exchange(_waitForFull, nullptr));
}
}, lifetime());
}
2019-07-25 18:55:11 +00:00
Main::Session &Controller::session() const {
return _channel->session();
}
int Controller::contentWidth() const {
return st::boxWidth;
}
void Controller::prepare() {
const auto appendRow = [&](not_null<PeerData*> chat) {
if (delegate()->peerListFindRow(chat->id)) {
return;
2019-05-24 10:32:43 +00:00
}
auto row = std::make_unique<PeerListRow>(chat);
const auto username = chat->userName();
2019-06-23 12:34:48 +00:00
row->setCustomStatus(!username.isEmpty()
? ('@' + username)
: (chat->isChannel() && !chat->isMegagroup())
? tr::lng_manage_linked_channel_private_status(tr::now)
: tr::lng_manage_discussion_group_private_status(tr::now));
delegate()->peerListAppendRow(std::move(row));
2019-05-24 10:32:43 +00:00
};
if (_chat) {
appendRow(_chat);
2019-05-24 10:32:43 +00:00
} else {
for (const auto chat : _chats) {
appendRow(chat);
}
if (_chats.size() >= kEnableSearchRowsCount) {
delegate()->peerListSetSearchMode(PeerListSearchMode::Enabled);
2019-05-24 10:32:43 +00:00
}
}
}
void Controller::rowClicked(not_null<PeerListRow*> row) {
if (_chat != nullptr) {
Ui::showPeerHistory(_chat, ShowAtUnreadMsgId);
return;
}
const auto peer = row->peer();
if (const auto channel = peer->asChannel()) {
if (channel->wasFullUpdated()) {
choose(channel);
return;
}
_waitForFull = channel;
channel->updateFull();
} else if (const auto chat = peer->asChat()) {
choose(chat);
}
}
void Controller::choose(not_null<ChannelData*> chat) {
auto text = tr::lng_manage_discussion_group_sure(
tr::now,
lt_group,
2019-06-12 13:26:04 +00:00
Ui::Text::Bold(chat->name),
lt_channel,
Ui::Text::Bold(_channel->name),
Ui::Text::WithEntities);
if (!_channel->isPublic()) {
text.append(
"\n\n" + tr::lng_manage_linked_channel_private(tr::now));
}
2019-05-31 16:47:31 +00:00
if (!chat->isPublic()) {
text.append(
"\n\n" + tr::lng_manage_discussion_group_private(tr::now));
2019-05-31 16:47:31 +00:00
if (chat->hiddenPreHistory()) {
text.append("\n\n");
text.append(tr::lng_manage_discussion_group_warning(
tr::now,
Ui::Text::RichLangValue));
2019-05-31 16:47:31 +00:00
}
}
const auto sure = [=](Fn<void()> &&close) {
close();
const auto onstack = _callback;
onstack(chat);
};
Ui::show(
Box<ConfirmBox>(
text,
2019-06-19 15:09:03 +00:00
tr::lng_manage_discussion_group_link(tr::now),
sure),
2019-09-18 11:19:05 +00:00
Ui::LayerOption::KeepOther);
2019-05-24 10:32:43 +00:00
}
void Controller::choose(not_null<ChatData*> chat) {
auto text = tr::lng_manage_discussion_group_sure(
tr::now,
lt_group,
2019-06-12 13:26:04 +00:00
Ui::Text::Bold(chat->name),
lt_channel,
Ui::Text::Bold(_channel->name),
Ui::Text::WithEntities);
if (!_channel->isPublic()) {
text.append("\n\n" + tr::lng_manage_linked_channel_private(tr::now));
}
text.append("\n\n" + tr::lng_manage_discussion_group_private(tr::now));
text.append("\n\n");
text.append(tr::lng_manage_discussion_group_warning(
tr::now,
Ui::Text::RichLangValue));
const auto sure = [=](Fn<void()> &&close) {
close();
const auto done = [=](not_null<ChannelData*> chat) {
const auto onstack = _callback;
onstack(chat);
};
chat->session().api().migrateChat(chat, crl::guard(this, done));
};
Ui::show(
Box<ConfirmBox>(
text,
2019-06-19 15:09:03 +00:00
tr::lng_manage_discussion_group_link(tr::now),
sure),
2019-09-18 11:19:05 +00:00
Ui::LayerOption::KeepOther);
}
2019-05-24 10:32:43 +00:00
object_ptr<Ui::RpWidget> SetupAbout(
not_null<QWidget*> parent,
not_null<ChannelData*> channel,
ChannelData *chat) {
auto about = object_ptr<Ui::FlatLabel>(
parent,
QString(),
st::linkedChatAbout);
about->setMarkedText([&] {
2019-05-24 10:32:43 +00:00
if (!channel->isBroadcast()) {
return tr::lng_manage_linked_channel_about(
tr::now,
lt_channel,
Ui::Text::Bold(chat->name),
Ui::Text::WithEntities);
2019-05-24 10:32:43 +00:00
} else if (chat != nullptr) {
return tr::lng_manage_discussion_group_about_chosen(
tr::now,
lt_group,
Ui::Text::Bold(chat->name),
Ui::Text::WithEntities);
2019-05-24 10:32:43 +00:00
}
return tr::lng_manage_discussion_group_about(
tr::now,
Ui::Text::WithEntities);
2019-05-24 10:32:43 +00:00
}());
return about;
2019-05-24 10:32:43 +00:00
}
2019-05-24 11:48:50 +00:00
object_ptr<Ui::RpWidget> SetupFooter(
not_null<QWidget*> parent,
not_null<ChannelData*> channel) {
return object_ptr<Ui::FlatLabel>(
parent,
2019-06-19 15:09:03 +00:00
(channel->isBroadcast()
? tr::lng_manage_discussion_group_posted
: tr::lng_manage_linked_channel_posted)(),
2019-05-24 11:48:50 +00:00
st::linkedChatAbout);
}
2019-05-24 10:32:43 +00:00
object_ptr<Ui::RpWidget> SetupCreateGroup(
not_null<QWidget*> parent,
2019-07-25 18:55:11 +00:00
not_null<Window::SessionNavigation*> navigation,
not_null<ChannelData*> channel,
Fn<void(ChannelData*)> callback) {
Expects(channel->isBroadcast());
auto result = object_ptr<Ui::SettingsButton>(
2019-05-24 10:32:43 +00:00
parent,
2019-06-17 16:59:43 +00:00
tr::lng_manage_discussion_group_create(
) | Ui::Text::ToUpper(),
2019-05-24 10:32:43 +00:00
st::infoCreateLinkedChatButton);
result->addClickHandler([=] {
const auto guarded = crl::guard(parent, callback);
Ui::show(
Box<GroupInfoBox>(
2019-07-25 18:55:11 +00:00
navigation,
GroupInfoBox::Type::Megagroup,
channel->name + " Chat",
guarded),
2019-09-18 11:19:05 +00:00
Ui::LayerOption::KeepOther);
2019-05-24 10:32:43 +00:00
});
return result;
}
object_ptr<Ui::RpWidget> SetupUnlink(
not_null<QWidget*> parent,
not_null<ChannelData*> channel,
Fn<void(ChannelData*)> callback) {
auto result = object_ptr<Ui::SettingsButton>(
2019-05-24 10:32:43 +00:00
parent,
2019-06-18 12:16:43 +00:00
(channel->isBroadcast()
? tr::lng_manage_discussion_group_unlink
: tr::lng_manage_linked_channel_unlink)() | Ui::Text::ToUpper(),
2019-05-24 10:32:43 +00:00
st::infoUnlinkChatButton);
result->addClickHandler([=] {
callback(nullptr);
});
return result;
}
2019-09-18 11:19:05 +00:00
object_ptr<Ui::BoxContent> EditLinkedChatBox(
2019-07-25 18:55:11 +00:00
not_null<Window::SessionNavigation*> navigation,
not_null<ChannelData*> channel,
ChannelData *chat,
std::vector<not_null<PeerData*>> &&chats,
2019-06-01 08:27:05 +00:00
bool canEdit,
Fn<void(ChannelData*)> callback) {
2019-06-01 08:27:05 +00:00
Expects((channel->isBroadcast() && canEdit) || (chat != nullptr));
const auto init = [=](not_null<PeerListBox*> box) {
auto above = object_ptr<Ui::VerticalLayout>(box);
above->add(
SetupAbout(above, channel, chat),
st::linkedChatAboutPadding);
if (!chat) {
2019-07-25 18:55:11 +00:00
above->add(SetupCreateGroup(
above,
navigation,
channel,
callback));
}
box->peerListSetAboveWidget(std::move(above));
auto below = object_ptr<Ui::VerticalLayout>(box);
2019-06-01 08:27:05 +00:00
if (chat && canEdit) {
below->add(SetupUnlink(below, channel, callback));
}
below->add(
SetupFooter(below, channel),
st::linkedChatAboutPadding);
box->peerListSetBelowWidget(std::move(below));
box->setTitle(channel->isBroadcast()
? tr::lng_manage_discussion_group()
: tr::lng_manage_linked_channel());
box->addButton(tr::lng_close(), [=] { box->closeBox(); });
};
auto controller = std::make_unique<Controller>(
channel,
chat,
std::move(chats),
std::move(callback));
return Box<PeerListBox>(std::move(controller), init);
}
} // namespace
2019-09-18 11:19:05 +00:00
object_ptr<Ui::BoxContent> EditLinkedChatBox(
2019-07-25 18:55:11 +00:00
not_null<Window::SessionNavigation*> navigation,
not_null<ChannelData*> channel,
std::vector<not_null<PeerData*>> &&chats,
Fn<void(ChannelData*)> callback) {
2019-06-01 08:27:05 +00:00
return EditLinkedChatBox(
2019-07-25 18:55:11 +00:00
navigation,
2019-06-01 08:27:05 +00:00
channel,
nullptr,
std::move(chats),
true,
callback);
}
2019-09-18 11:19:05 +00:00
object_ptr<Ui::BoxContent> EditLinkedChatBox(
2019-07-25 18:55:11 +00:00
not_null<Window::SessionNavigation*> navigation,
not_null<ChannelData*> channel,
not_null<ChannelData*> chat,
2019-06-01 08:27:05 +00:00
bool canEdit,
Fn<void(ChannelData*)> callback) {
2019-07-25 18:55:11 +00:00
return EditLinkedChatBox(
navigation,
channel,
chat,
{},
canEdit,
callback);
}