2
0
mirror of https://github.com/telegramdesktop/tdesktop synced 2025-08-22 18:27:17 +00:00
tdesktop/Telegram/SourceFiles/info/profile/info_profile_actions.cpp

877 lines
23 KiB
C++
Raw Normal View History

2017-11-07 15:53:05 +04:00
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
2017-11-07 15:53:05 +04:00
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
2017-11-07 15:53:05 +04:00
*/
#include "info/profile/info_profile_actions.h"
#include "data/data_peer_values.h"
#include "data/data_session.h"
2019-04-15 15:54:03 +04:00
#include "data/data_folder.h"
#include "data/data_channel.h"
#include "data/data_changes.h"
#include "data/data_user.h"
2017-11-07 15:53:05 +04:00
#include "ui/wrap/vertical_layout.h"
#include "ui/wrap/padding_wrap.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/widgets/shadow.h"
2017-11-10 21:51:59 +04:00
#include "ui/widgets/labels.h"
#include "ui/widgets/buttons.h"
2019-09-18 14:19:05 +03:00
#include "ui/widgets/box_content_divider.h"
#include "ui/boxes/report_box.h"
2019-09-18 14:19:05 +03:00
#include "ui/layers/generic_box.h"
2017-11-10 21:51:59 +04:00
#include "ui/toast/toast.h"
2019-06-17 18:59:43 +02:00
#include "ui/text/text_utilities.h" // Ui::Text::ToUpper
2019-06-21 14:27:46 +02:00
#include "history/history_location_manager.h" // LocationClickHandler.
#include "history/view/history_view_context_menu.h" // HistoryView::ShowReportPeerBox
2017-11-07 15:53:05 +04:00
#include "boxes/abstract_box.h"
2021-10-19 00:36:55 +03:00
#include "ui/boxes/confirm_box.h"
2017-11-07 15:53:05 +04:00
#include "boxes/peer_list_box.h"
#include "boxes/peer_list_controllers.h"
#include "boxes/add_contact_box.h"
2019-06-12 16:13:49 +02:00
#include "boxes/peers/edit_contact_box.h"
2017-11-07 15:53:05 +04:00
#include "lang/lang_keys.h"
#include "info/info_controller.h"
#include "info/info_memento.h"
2017-11-07 15:53:05 +04:00
#include "info/profile/info_profile_icon.h"
#include "info/profile/info_profile_values.h"
#include "info/profile/info_profile_text.h"
#include "support/support_helper.h"
#include "window/window_session_controller.h"
2019-06-12 16:13:49 +02:00
#include "window/window_controller.h" // Window::Controller::show.
#include "window/window_peer_menu.h"
2017-11-07 15:53:05 +04:00
#include "mainwidget.h"
2019-06-12 15:26:04 +02:00
#include "mainwindow.h" // MainWindow::controller.
2019-07-24 13:45:24 +02:00
#include "main/main_session.h"
#include "core/application.h"
#include "core/click_handler_types.h"
#include "settings/settings_common.h"
2017-11-07 15:53:05 +04:00
#include "apiwrap.h"
#include "api/api_blocked_peers.h"
#include "facades.h"
2017-11-07 15:53:05 +04:00
#include "styles/style_info.h"
#include "styles/style_boxes.h"
2019-09-04 10:19:15 +03:00
#include <QtGui/QGuiApplication>
#include <QtGui/QClipboard>
2017-11-07 15:53:05 +04:00
namespace Info {
namespace Profile {
namespace {
object_ptr<Ui::RpWidget> CreateSkipWidget(
not_null<Ui::RpWidget*> parent) {
return Ui::CreateSkipWidget(parent, st::infoProfileSkip);
}
object_ptr<Ui::SlideWrap<>> CreateSlideSkipWidget(
not_null<Ui::RpWidget*> parent) {
2017-11-19 15:37:15 +04:00
auto result = Ui::CreateSlideSkipWidget(
parent,
st::infoProfileSkip);
result->setDuration(st::infoSlideDuration);
return result;
2017-11-07 15:53:05 +04:00
}
template <typename Text, typename ToggleOn, typename Callback>
auto AddActionButton(
not_null<Ui::VerticalLayout*> parent,
Text &&text,
ToggleOn &&toggleOn,
Callback &&callback,
2022-02-25 16:11:49 +03:00
const style::icon *icon,
const style::SettingsButton &st
2017-11-07 15:53:05 +04:00
= st::infoSharedMediaButton) {
auto result = parent->add(object_ptr<Ui::SlideWrap<Ui::SettingsButton>>(
2017-11-07 15:53:05 +04:00
parent,
object_ptr<Ui::SettingsButton>(
2017-11-07 15:53:05 +04:00
parent,
std::move(text),
st))
);
2017-11-19 15:37:15 +04:00
result->setDuration(
st::infoSlideDuration
)->toggleOn(
2017-11-07 15:53:05 +04:00
std::move(toggleOn)
)->entity()->addClickHandler(std::move(callback));
result->finishAnimating();
2022-02-25 16:11:49 +03:00
if (icon) {
object_ptr<Profile::FloatingIcon>(
result,
*icon,
st::infoSharedMediaButtonIconPosition);
}
2017-11-07 15:53:05 +04:00
return result;
};
template <typename Text, typename ToggleOn, typename Callback>
auto AddMainButton(
not_null<Ui::VerticalLayout*> parent,
Text &&text,
ToggleOn &&toggleOn,
Callback &&callback,
Ui::MultiSlideTracker &tracker) {
tracker.track(AddActionButton(
parent,
2019-06-17 18:59:43 +02:00
std::move(text) | Ui::Text::ToUpper(),
2017-11-07 15:53:05 +04:00
std::move(toggleOn),
std::move(callback),
2022-02-25 16:11:49 +03:00
nullptr,
2017-11-07 15:53:05 +04:00
st::infoMainButton));
}
class DetailsFiller {
public:
DetailsFiller(
not_null<Controller*> controller,
not_null<Ui::RpWidget*> parent,
not_null<PeerData*> peer);
object_ptr<Ui::RpWidget> fill();
private:
object_ptr<Ui::RpWidget> setupInfo();
object_ptr<Ui::RpWidget> setupMuteToggle();
void setupMainButtons();
Ui::MultiSlideTracker fillUserButtons(
not_null<UserData*> user);
Ui::MultiSlideTracker fillChannelButtons(
not_null<ChannelData*> channel);
template <
typename Widget,
typename = std::enable_if_t<
std::is_base_of_v<Ui::RpWidget, Widget>>>
Widget *add(
object_ptr<Widget> &&child,
const style::margins &margin = style::margins()) {
return _wrap->add(
std::move(child),
margin);
}
not_null<Controller*> _controller;
not_null<Ui::RpWidget*> _parent;
not_null<PeerData*> _peer;
object_ptr<Ui::VerticalLayout> _wrap;
};
class ActionsFiller {
public:
ActionsFiller(
not_null<Controller*> controller,
not_null<Ui::RpWidget*> parent,
not_null<PeerData*> peer);
object_ptr<Ui::RpWidget> fill();
private:
void addInviteToGroupAction(not_null<UserData*> user);
void addShareContactAction(not_null<UserData*> user);
void addEditContactAction(not_null<UserData*> user);
void addDeleteContactAction(not_null<UserData*> user);
void addBotCommandActions(not_null<UserData*> user);
void addReportAction();
void addBlockAction(not_null<UserData*> user);
void addLeaveChannelAction(not_null<ChannelData*> channel);
void addJoinChannelAction(not_null<ChannelData*> channel);
void fillUserActions(not_null<UserData*> user);
void fillChannelActions(not_null<ChannelData*> channel);
not_null<Controller*> _controller;
not_null<Ui::RpWidget*> _parent;
not_null<PeerData*> _peer;
object_ptr<Ui::VerticalLayout> _wrap = { nullptr };
};
2017-11-07 15:53:05 +04:00
DetailsFiller::DetailsFiller(
not_null<Controller*> controller,
not_null<Ui::RpWidget*> parent,
not_null<PeerData*> peer)
: _controller(controller)
, _parent(parent)
, _peer(peer)
, _wrap(_parent) {
}
template <typename T>
bool SetClickContext(
const ClickHandlerPtr &handler,
const ClickContext &context) {
2021-07-30 21:03:33 +03:00
if (const auto casted = std::dynamic_pointer_cast<T>(handler)) {
casted->T::onClick(context);
return true;
}
return false;
}
2017-11-07 15:53:05 +04:00
object_ptr<Ui::RpWidget> DetailsFiller::setupInfo() {
auto result = object_ptr<Ui::VerticalLayout>(_wrap);
auto tracker = Ui::MultiSlideTracker();
// Fill context for a mention / hashtag / bot command link.
const auto infoClickFilter = [=,
peer = _peer.get(),
window = _controller->parentController()](
const ClickHandlerPtr &handler,
Qt::MouseButton button) {
const auto context = ClickContext{
button,
QVariant::fromValue(ClickHandlerContext{
.sessionWindow = base::make_weak(window.get()),
.peer = peer,
})
};
if (SetClickContext<BotCommandClickHandler>(handler, context)) {
return false;
} else if (SetClickContext<MentionClickHandler>(handler, context)) {
return false;
} else if (SetClickContext<HashtagClickHandler>(handler, context)) {
return false;
} else if (SetClickContext<CashtagClickHandler>(handler, context)) {
return false;
} else if (SetClickContext<UrlClickHandler>(handler, context)) {
return false;
}
return true;
};
auto addInfoLineGeneric = [&](
2019-06-18 14:16:43 +02:00
rpl::producer<QString> &&label,
2017-11-07 15:53:05 +04:00
rpl::producer<TextWithEntities> &&text,
const style::FlatLabel &textSt = st::infoLabeled) {
2017-11-10 21:51:59 +04:00
auto line = CreateTextWithLabel(
2017-11-07 15:53:05 +04:00
result,
2019-06-18 14:16:43 +02:00
std::move(label) | Ui::Text::ToWithEntities(),
2017-11-07 15:53:05 +04:00
std::move(text),
textSt,
2017-11-10 21:51:59 +04:00
st::infoProfileLabeledPadding);
tracker.track(result->add(std::move(line.wrap)));
line.text->setClickHandlerFilter(infoClickFilter);
2017-11-10 21:51:59 +04:00
return line.text;
2017-11-07 15:53:05 +04:00
};
auto addInfoLine = [&](
2019-06-18 14:16:43 +02:00
rpl::producer<QString> &&label,
rpl::producer<TextWithEntities> &&text,
const style::FlatLabel &textSt = st::infoLabeled) {
return addInfoLineGeneric(
2019-06-18 14:16:43 +02:00
std::move(label),
std::move(text),
textSt);
};
2017-11-07 15:53:05 +04:00
auto addInfoOneLine = [&](
2019-06-18 14:16:43 +02:00
rpl::producer<QString> &&label,
2017-11-10 21:51:59 +04:00
rpl::producer<TextWithEntities> &&text,
const QString &contextCopyText) {
auto result = addInfoLine(
2019-06-18 14:16:43 +02:00
std::move(label),
2017-11-07 15:53:05 +04:00
std::move(text),
st::infoLabeledOneLine);
2017-11-10 21:51:59 +04:00
result->setDoubleClickSelectsParagraph(true);
result->setContextCopyText(contextCopyText);
return result;
2017-11-07 15:53:05 +04:00
};
2019-06-21 14:27:46 +02:00
if (const auto user = _peer->asUser()) {
if (user->session().supportMode()) {
addInfoLineGeneric(
2019-06-21 14:27:46 +02:00
user->session().supportHelper().infoLabelValue(user),
user->session().supportHelper().infoTextValue(user));
}
2017-11-10 21:51:59 +04:00
addInfoOneLine(
2019-06-18 14:16:43 +02:00
tr::lng_info_mobile_label(),
PhoneOrHiddenValue(user),
2019-06-19 17:09:03 +02:00
tr::lng_profile_copy_phone(tr::now));
2020-10-29 19:53:07 +03:00
auto label = user->isBot()
? tr::lng_info_about_label()
: tr::lng_info_bio_label();
addInfoLine(std::move(label), AboutValue(user));
2017-11-10 21:51:59 +04:00
addInfoOneLine(
2019-06-18 14:16:43 +02:00
tr::lng_info_username_label(),
2017-11-10 21:51:59 +04:00
UsernameValue(user),
2019-06-19 17:09:03 +02:00
tr::lng_context_copy_mention(tr::now));
const auto controller = _controller->parentController();
AddMainButton(
result,
tr::lng_info_add_as_contact(),
CanAddContactValue(user),
[=] { controller->window().show(Box(EditContactBox, controller, user)); },
tracker);
2017-11-07 15:53:05 +04:00
} else {
auto linkText = LinkValue(
_peer
) | rpl::map([](const QString &link) {
2019-06-21 14:27:46 +02:00
return link.isEmpty()
? TextWithEntities()
: Ui::Text::Link(
(link.startsWith(qstr("https://"))
? link.mid(qstr("https://").size())
: link),
link);
});
2017-11-10 21:51:59 +04:00
auto link = addInfoOneLine(
2019-06-18 14:16:43 +02:00
tr::lng_info_link_label(),
2017-11-10 21:51:59 +04:00
std::move(linkText),
QString());
link->setClickHandlerFilter([peer = _peer](auto&&...) {
const auto link = peer->session().createInternalLinkFull(
2017-11-10 21:51:59 +04:00
peer->userName());
if (!link.isEmpty()) {
2019-09-04 10:19:15 +03:00
QGuiApplication::clipboard()->setText(link);
2019-06-19 17:09:03 +02:00
Ui::Toast::Show(tr::lng_username_copied(tr::now));
2017-11-10 21:51:59 +04:00
}
return false;
});
2019-06-21 14:27:46 +02:00
if (const auto channel = _peer->asChannel()) {
auto locationText = LocationValue(
channel
) | rpl::map([](const ChannelLocation *location) {
return location
? Ui::Text::Link(
TextUtilities::SingleLine(location->address),
2019-06-21 14:27:46 +02:00
LocationClickHandler::Url(location->point))
: TextWithEntities();
});
addInfoOneLine(
tr::lng_info_location_label(),
std::move(locationText),
QString()
)->setLinksTrusted();
}
2019-06-18 14:16:43 +02:00
addInfoLine(tr::lng_info_about_label(), AboutValue(_peer));
2017-11-07 15:53:05 +04:00
}
if (!_peer->isSelf()) {
// No notifications toggle for Self => no separator.
result->add(object_ptr<Ui::SlideWrap<>>(
result,
object_ptr<Ui::PlainShadow>(result),
st::infoProfileSeparatorPadding)
)->setDuration(
st::infoSlideDuration
)->toggleOn(
std::move(tracker).atLeastOneShownValue()
);
}
2017-11-07 15:53:05 +04:00
object_ptr<FloatingIcon>(
result,
st::infoIconInformation,
st::infoInformationIconPosition);
return result;
2017-11-07 15:53:05 +04:00
}
object_ptr<Ui::RpWidget> DetailsFiller::setupMuteToggle() {
2017-12-04 21:46:03 +04:00
const auto peer = _peer;
auto result = object_ptr<Ui::SettingsButton>(
2017-11-07 15:53:05 +04:00
_wrap,
2019-06-18 14:16:43 +02:00
tr::lng_profile_enable_notifications(),
2017-11-07 15:53:05 +04:00
st::infoNotificationsButton);
result->toggleOn(
NotificationsEnabledValue(peer)
)->addClickHandler([=] {
2019-07-24 13:13:51 +02:00
const auto muteForSeconds = peer->owner().notifyIsMuted(peer)
? 0
: Data::NotifySettings::kDefaultMutePeriod;
2019-07-24 13:13:51 +02:00
peer->owner().updateNotifySettings(peer, muteForSeconds);
2017-11-07 15:53:05 +04:00
});
object_ptr<FloatingIcon>(
result,
st::infoIconNotifications,
st::infoNotificationsIconPosition);
return result;
2017-11-07 15:53:05 +04:00
}
void DetailsFiller::setupMainButtons() {
auto wrapButtons = [=](auto &&callback) {
auto topSkip = _wrap->add(CreateSlideSkipWidget(_wrap));
auto tracker = callback();
topSkip->toggleOn(std::move(tracker).atLeastOneShownValue());
};
if (auto user = _peer->asUser()) {
wrapButtons([=] {
return fillUserButtons(user);
});
} else if (auto channel = _peer->asChannel()) {
if (!channel->isMegagroup()) {
wrapButtons([=] {
return fillChannelButtons(channel);
});
}
}
}
Ui::MultiSlideTracker DetailsFiller::fillUserButtons(
not_null<UserData*> user) {
using namespace rpl::mappers;
Ui::MultiSlideTracker tracker;
auto window = _controller->parentController();
auto addSendMessageButton = [&] {
auto activePeerValue = window->activeChatValue(
) | rpl::map([](Dialogs::Key key) {
return key.peer();
});
auto sendMessageVisible = rpl::combine(
_controller->wrapValue(),
std::move(activePeerValue),
(_1 != Wrap::Side) || (_2 != user));
auto sendMessage = [window, user] {
window->showPeerHistory(
user,
Window::SectionShow::Way::Forward);
};
AddMainButton(
_wrap,
2019-06-18 14:16:43 +02:00
tr::lng_profile_send_message(),
std::move(sendMessageVisible),
std::move(sendMessage),
tracker);
2017-11-07 15:53:05 +04:00
};
if (user->isSelf()) {
auto separator = _wrap->add(object_ptr<Ui::SlideWrap<>>(
_wrap,
object_ptr<Ui::PlainShadow>(_wrap),
st::infoProfileSeparatorPadding)
)->setDuration(
st::infoSlideDuration
);
addSendMessageButton();
separator->toggleOn(
std::move(tracker).atLeastOneShownValue()
);
} else {
addSendMessageButton();
}
2017-11-07 15:53:05 +04:00
return tracker;
}
Ui::MultiSlideTracker DetailsFiller::fillChannelButtons(
not_null<ChannelData*> channel) {
using namespace rpl::mappers;
Ui::MultiSlideTracker tracker;
auto window = _controller->parentController();
auto activePeerValue = window->activeChatValue(
) | rpl::map([](Dialogs::Key key) {
return key.peer();
});
auto viewChannelVisible = rpl::combine(
_controller->wrapValue(),
std::move(activePeerValue),
2017-11-20 16:32:55 +04:00
(_1 != Wrap::Side) || (_2 != channel));
2017-11-07 15:53:05 +04:00
auto viewChannel = [=] {
window->showPeerHistory(
channel,
Window::SectionShow::Way::Forward);
};
AddMainButton(
_wrap,
2019-06-18 14:16:43 +02:00
tr::lng_profile_view_channel(),
2017-11-07 15:53:05 +04:00
std::move(viewChannelVisible),
std::move(viewChannel),
tracker);
return tracker;
}
object_ptr<Ui::RpWidget> DetailsFiller::fill() {
2019-09-18 14:19:05 +03:00
add(object_ptr<Ui::BoxContentDivider>(_wrap));
2017-11-07 15:53:05 +04:00
add(CreateSkipWidget(_wrap));
add(setupInfo());
if (!_peer->isSelf()) {
add(setupMuteToggle());
}
2017-11-07 15:53:05 +04:00
setupMainButtons();
add(CreateSkipWidget(_wrap));
return std::move(_wrap);
}
ActionsFiller::ActionsFiller(
not_null<Controller*> controller,
not_null<Ui::RpWidget*> parent,
not_null<PeerData*> peer)
: _controller(controller)
, _parent(parent)
, _peer(peer) {
}
void ActionsFiller::addInviteToGroupAction(
not_null<UserData*> user) {
const auto notEmpty = [](const QString &value) {
return !value.isEmpty();
};
2017-11-07 15:53:05 +04:00
AddActionButton(
_wrap,
InviteToChatButton(user) | rpl::filter(notEmpty),
InviteToChatButton(user) | rpl::map(notEmpty),
2022-02-25 16:11:49 +03:00
[=] { AddBotToGroupBoxController::Start(user); },
&st::infoIconRequests);
const auto about = _wrap->add(
object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
_wrap.data(),
object_ptr<Ui::VerticalLayout>(_wrap.data())));
about->toggleOn(InviteToChatAbout(user) | rpl::map(notEmpty));
::Settings::AddSkip(about->entity());
::Settings::AddDividerText(
about->entity(),
InviteToChatAbout(user) | rpl::filter(notEmpty));
::Settings::AddSkip(about->entity());
about->finishAnimating();
2017-11-07 15:53:05 +04:00
}
void ActionsFiller::addShareContactAction(not_null<UserData*> user) {
2019-07-25 20:55:11 +02:00
const auto controller = _controller;
2017-11-07 15:53:05 +04:00
AddActionButton(
_wrap,
2019-06-18 14:16:43 +02:00
tr::lng_info_share_contact(),
2017-11-07 15:53:05 +04:00
CanShareContactValue(user),
2022-02-25 16:11:49 +03:00
[=] { Window::PeerMenuShareContactBox(controller, user); },
&st::infoIconShare);
2017-11-07 15:53:05 +04:00
}
void ActionsFiller::addEditContactAction(not_null<UserData*> user) {
const auto controller = _controller->parentController();
2017-11-07 15:53:05 +04:00
AddActionButton(
_wrap,
2019-06-18 14:16:43 +02:00
tr::lng_info_edit_contact(),
2017-11-07 15:53:05 +04:00
IsContactValue(user),
2022-02-25 16:11:49 +03:00
[=] { controller->window().show(Box(EditContactBox, controller, user)); },
&st::infoIconEdit);
2017-11-07 15:53:05 +04:00
}
void ActionsFiller::addDeleteContactAction(not_null<UserData*> user) {
const auto controller = _controller->parentController();
2017-11-07 15:53:05 +04:00
AddActionButton(
_wrap,
2019-06-18 14:16:43 +02:00
tr::lng_info_delete_contact(),
2017-11-07 15:53:05 +04:00
IsContactValue(user),
[=] { Window::PeerMenuDeleteContact(controller, user); },
2022-02-25 16:11:49 +03:00
&st::infoIconDelete);
2017-11-07 15:53:05 +04:00
}
void ActionsFiller::addBotCommandActions(not_null<UserData*> user) {
auto findBotCommand = [user](const QString &command) {
2019-07-18 10:51:11 +02:00
if (!user->isBot()) {
2017-11-07 15:53:05 +04:00
return QString();
}
for (const auto &data : user->botInfo->commands) {
const auto isSame = !data.command.compare(
2017-11-07 15:53:05 +04:00
command,
Qt::CaseInsensitive);
2017-11-07 15:53:05 +04:00
if (isSame) {
return data.command;
}
}
return QString();
};
auto hasBotCommandValue = [=](const QString &command) {
return user->session().changes().peerFlagsValue(
2017-11-07 15:53:05 +04:00
user,
Data::PeerUpdate::Flag::BotCommands
) | rpl::map([=] {
return !findBotCommand(command).isEmpty();
});
2017-11-07 15:53:05 +04:00
};
2021-07-27 02:18:11 +03:00
auto sendBotCommand = [=, window = _controller->parentController()](
const QString &command) {
const auto original = findBotCommand(command);
if (original.isEmpty()) {
return;
2017-11-07 15:53:05 +04:00
}
2021-07-27 02:18:11 +03:00
BotCommandClickHandler('/' + original).onClick(ClickContext{
Qt::LeftButton,
QVariant::fromValue(ClickHandlerContext{
.sessionWindow = base::make_weak(window.get()),
.peer = user,
})
});
2017-11-07 15:53:05 +04:00
};
2019-06-18 14:16:43 +02:00
auto addBotCommand = [=](
rpl::producer<QString> text,
2022-02-25 16:11:49 +03:00
const QString &command,
const style::icon *icon = nullptr) {
2017-11-07 15:53:05 +04:00
AddActionButton(
_wrap,
2019-06-18 14:16:43 +02:00
std::move(text),
2017-11-07 15:53:05 +04:00
hasBotCommandValue(command),
2022-02-25 16:11:49 +03:00
[=] { sendBotCommand(command); },
icon);
2017-11-07 15:53:05 +04:00
};
2022-02-25 16:11:49 +03:00
addBotCommand(
tr::lng_profile_bot_help(),
qsl("help"),
&st::infoIconInformation);
2019-06-18 14:16:43 +02:00
addBotCommand(tr::lng_profile_bot_settings(), qsl("settings"));
addBotCommand(tr::lng_profile_bot_privacy(), qsl("privacy"));
2017-11-07 15:53:05 +04:00
}
void ActionsFiller::addReportAction() {
2019-03-12 14:36:33 +04:00
const auto peer = _peer;
2021-03-11 17:23:38 +08:00
const auto controller = _controller->parentController();
const auto report = [=] {
2021-03-11 17:23:38 +08:00
HistoryView::ShowReportPeerBox(controller, peer);
};
2017-11-07 15:53:05 +04:00
AddActionButton(
_wrap,
2019-06-18 14:16:43 +02:00
tr::lng_profile_report(),
2017-11-07 15:53:05 +04:00
rpl::single(true),
report,
2022-02-25 16:11:49 +03:00
&st::infoIconReport,
2017-11-07 15:53:05 +04:00
st::infoBlockButton);
}
void ActionsFiller::addBlockAction(not_null<UserData*> user) {
2019-09-03 18:24:51 +03:00
const auto window = &_controller->parentController()->window();
2019-06-12 15:26:04 +02:00
auto text = user->session().changes().peerFlagsValue(
2017-11-07 15:53:05 +04:00
user,
Data::PeerUpdate::Flag::IsBlocked
) | rpl::map([=] {
switch (user->blockStatus()) {
case UserData::BlockStatus::Blocked:
2019-06-18 14:16:43 +02:00
return ((user->isBot() && !user->isSupport())
? tr::lng_profile_restart_bot
: tr::lng_profile_unblock_user)();
case UserData::BlockStatus::NotBlocked:
default:
2019-06-18 14:16:43 +02:00
return ((user->isBot() && !user->isSupport())
? tr::lng_profile_block_bot
: tr::lng_profile_block_user)();
}
}) | rpl::flatten_latest(
) | rpl::start_spawning(_wrap->lifetime());
2017-11-07 15:53:05 +04:00
auto toggleOn = rpl::duplicate(
text
) | rpl::map([](const QString &text) {
return !text.isEmpty();
});
2018-12-04 15:46:07 +04:00
auto callback = [=] {
2017-11-07 15:53:05 +04:00
if (user->isBlocked()) {
Window::PeerMenuUnblockUserWithBotRestart(user);
2019-07-18 10:51:11 +02:00
if (user->isBot()) {
2018-12-04 15:46:07 +04:00
Ui::showPeerHistory(user, ShowAtUnreadMsgId);
}
} else if (user->isBot()) {
user->session().api().blockedPeers().block(user);
} else {
window->show(Box(
Window::PeerMenuBlockUserBox,
window,
user,
v::null,
v::null));
2017-11-07 15:53:05 +04:00
}
};
AddActionButton(
_wrap,
rpl::duplicate(text),
std::move(toggleOn),
std::move(callback),
2022-02-25 16:11:49 +03:00
&st::infoIconBlock,
2017-11-07 15:53:05 +04:00
st::infoBlockButton);
}
void ActionsFiller::addLeaveChannelAction(not_null<ChannelData*> channel) {
Expects(_controller->parentController());
2017-11-07 15:53:05 +04:00
AddActionButton(
_wrap,
2019-06-18 14:16:43 +02:00
tr::lng_profile_leave_channel(),
2017-11-07 15:53:05 +04:00
AmInChannelValue(channel),
Window::DeleteAndLeaveHandler(
_controller->parentController(),
channel),
2022-02-25 16:11:49 +03:00
&st::infoIconLeave);
2017-11-07 15:53:05 +04:00
}
void ActionsFiller::addJoinChannelAction(
not_null<ChannelData*> channel) {
using namespace rpl::mappers;
auto joinVisible = AmInChannelValue(channel)
2017-11-20 16:32:55 +04:00
| rpl::map(!_1)
2017-11-07 15:53:05 +04:00
| rpl::start_spawning(_wrap->lifetime());
AddActionButton(
_wrap,
2019-06-18 14:16:43 +02:00
tr::lng_profile_join_channel(),
2017-11-07 15:53:05 +04:00
rpl::duplicate(joinVisible),
2022-02-25 16:11:49 +03:00
[=] { channel->session().api().joinChannel(channel); },
&st::infoIconRequests);
2017-11-07 15:53:05 +04:00
_wrap->add(object_ptr<Ui::SlideWrap<Ui::FixedHeightWidget>>(
_wrap,
CreateSkipWidget(
_wrap,
st::infoBlockButtonSkip))
2017-11-19 15:37:15 +04:00
)->setDuration(
st::infoSlideDuration
)->toggleOn(
rpl::duplicate(joinVisible)
);
2017-11-07 15:53:05 +04:00
}
void ActionsFiller::fillUserActions(not_null<UserData*> user) {
2019-07-18 10:51:11 +02:00
if (user->isBot()) {
2017-11-07 15:53:05 +04:00
addInviteToGroupAction(user);
}
addShareContactAction(user);
if (!user->isSelf()) {
addEditContactAction(user);
addDeleteContactAction(user);
}
if (!user->isSelf() && !user->isSupport()) {
if (user->isBot()) {
2017-11-07 15:53:05 +04:00
addBotCommandActions(user);
}
_wrap->add(CreateSkipWidget(
_wrap,
st::infoBlockButtonSkip));
if (user->isBot()) {
2017-11-07 15:53:05 +04:00
addReportAction();
}
addBlockAction(user);
}
}
void ActionsFiller::fillChannelActions(
not_null<ChannelData*> channel) {
using namespace rpl::mappers;
addJoinChannelAction(channel);
addLeaveChannelAction(channel);
2017-11-07 15:53:05 +04:00
if (!channel->amCreator()) {
addReportAction();
}
}
object_ptr<Ui::RpWidget> ActionsFiller::fill() {
auto wrapResult = [=](auto &&callback) {
_wrap = object_ptr<Ui::VerticalLayout>(_parent);
_wrap->add(CreateSkipWidget(_wrap));
callback();
_wrap->add(CreateSkipWidget(_wrap));
return std::move(_wrap);
};
if (auto user = _peer->asUser()) {
return wrapResult([=] {
fillUserActions(user);
});
} else if (auto channel = _peer->asChannel()) {
if (channel->isMegagroup()) {
return { nullptr };
2017-11-07 15:53:05 +04:00
}
return wrapResult([=] {
fillChannelActions(channel);
});
2017-11-07 15:53:05 +04:00
}
return { nullptr };
}
2017-11-07 15:53:05 +04:00
} // namespace
object_ptr<Ui::RpWidget> SetupDetails(
not_null<Controller*> controller,
not_null<Ui::RpWidget*> parent,
not_null<PeerData*> peer) {
DetailsFiller filler(controller, parent, peer);
return filler.fill();
}
object_ptr<Ui::RpWidget> SetupActions(
not_null<Controller*> controller,
not_null<Ui::RpWidget*> parent,
not_null<PeerData*> peer) {
ActionsFiller filler(controller, parent, peer);
return filler.fill();
}
void SetupAddChannelMember(
2019-07-25 20:55:11 +02:00
not_null<Window::SessionNavigation*> navigation,
not_null<Ui::RpWidget*> parent,
not_null<ChannelData*> channel) {
auto add = Ui::CreateChild<Ui::IconButton>(
parent.get(),
st::infoMembersAddMember);
add->showOn(CanAddMemberValue(channel));
2019-07-25 20:55:11 +02:00
add->addClickHandler([=] {
Window::PeerMenuAddChannelMembers(navigation, channel);
});
parent->widthValue(
) | rpl::start_with_next([add](int newWidth) {
auto availableWidth = newWidth
- st::infoMembersButtonPosition.x();
add->moveToLeft(
availableWidth - add->width(),
st::infoMembersButtonPosition.y(),
newWidth);
}, add->lifetime());
}
object_ptr<Ui::RpWidget> SetupChannelMembers(
not_null<Controller*> controller,
not_null<Ui::RpWidget*> parent,
not_null<PeerData*> peer) {
using namespace rpl::mappers;
auto channel = peer->asChannel();
if (!channel || channel->isMegagroup()) {
return { nullptr };
}
auto membersShown = rpl::combine(
MembersCountValue(channel),
2021-07-08 16:11:09 +03:00
Data::PeerFlagValue(
channel,
2021-07-08 16:11:09 +03:00
ChannelDataFlag::CanViewParticipants),
2017-11-20 16:32:55 +04:00
(_1 > 0) && _2);
auto membersText = tr::lng_chat_status_subscribers(
lt_count_decimal,
MembersCountValue(channel) | tr::to_count());
auto membersCallback = [=] {
2020-12-14 18:48:10 +04:00
controller->showSection(std::make_shared<Info::Memento>(
2020-06-08 13:06:50 +04:00
channel,
Section::Type::Members));
};
auto result = object_ptr<Ui::SlideWrap<Ui::VerticalLayout>>(
parent,
object_ptr<Ui::VerticalLayout>(parent));
2017-11-19 15:37:15 +04:00
result->setDuration(
st::infoSlideDuration
)->toggleOn(
std::move(membersShown)
);
auto members = result->entity();
2019-09-18 14:19:05 +03:00
members->add(object_ptr<Ui::BoxContentDivider>(members));
members->add(CreateSkipWidget(members));
auto button = AddActionButton(
members,
std::move(membersText),
rpl::single(true),
2022-02-25 16:11:49 +03:00
std::move(membersCallback),
nullptr)->entity();
2019-07-25 20:55:11 +02:00
SetupAddChannelMember(controller, button, channel);
object_ptr<FloatingIcon>(
members,
st::infoIconMembers,
st::infoChannelMembersIconPosition);
members->add(CreateSkipWidget(members));
return result;
}
2017-11-07 15:53:05 +04:00
} // namespace Profile
} // namespace Info