2018-09-05 19:05:49 +00:00
|
|
|
/*
|
|
|
|
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 "settings/settings_common.h"
|
|
|
|
|
2022-05-07 02:45:52 +00:00
|
|
|
#include "apiwrap.h"
|
|
|
|
#include "api/api_cloud_password.h"
|
|
|
|
#include "settings/cloud_password/settings_cloud_password_email_confirm.h"
|
2018-09-05 19:05:49 +00:00
|
|
|
#include "settings/settings_chat.h"
|
2018-09-20 16:47:02 +00:00
|
|
|
#include "settings/settings_advanced.h"
|
2018-09-05 19:05:49 +00:00
|
|
|
#include "settings/settings_information.h"
|
|
|
|
#include "settings/settings_main.h"
|
|
|
|
#include "settings/settings_notifications.h"
|
|
|
|
#include "settings/settings_privacy_security.h"
|
2020-03-24 08:58:47 +00:00
|
|
|
#include "settings/settings_folders.h"
|
2019-01-05 11:08:02 +00:00
|
|
|
#include "settings/settings_calls.h"
|
2022-01-25 13:25:51 +00:00
|
|
|
#include "settings/settings_experimental.h"
|
2020-06-30 17:16:05 +00:00
|
|
|
#include "core/application.h"
|
2022-05-07 02:45:52 +00:00
|
|
|
#include "core/core_cloud_password.h"
|
2018-09-06 17:58:44 +00:00
|
|
|
#include "ui/wrap/padding_wrap.h"
|
|
|
|
#include "ui/wrap/vertical_layout.h"
|
2018-09-07 09:40:25 +00:00
|
|
|
#include "ui/widgets/labels.h"
|
2019-09-18 11:19:05 +00:00
|
|
|
#include "ui/widgets/box_content_divider.h"
|
2019-11-02 17:06:47 +00:00
|
|
|
#include "ui/widgets/buttons.h"
|
2022-06-03 16:07:33 +00:00
|
|
|
#include "ui/widgets/menu/menu_add_action_callback.h"
|
2022-09-16 20:23:27 +00:00
|
|
|
#include "ui/painter.h"
|
2018-09-06 17:58:44 +00:00
|
|
|
#include "boxes/abstract_box.h"
|
2021-11-29 13:29:45 +00:00
|
|
|
#include "boxes/sessions_box.h"
|
2019-09-08 12:47:22 +00:00
|
|
|
#include "window/themes/window_theme_editor_box.h"
|
|
|
|
#include "window/window_session_controller.h"
|
|
|
|
#include "window/window_controller.h"
|
2018-09-06 15:24:24 +00:00
|
|
|
#include "lang/lang_keys.h"
|
|
|
|
#include "mainwindow.h"
|
2019-07-24 11:45:24 +00:00
|
|
|
#include "main/main_session.h"
|
2020-06-30 17:16:05 +00:00
|
|
|
#include "main/main_domain.h"
|
2022-04-13 08:05:10 +00:00
|
|
|
#include "lottie/lottie_icon.h"
|
2022-03-14 06:20:36 +00:00
|
|
|
#include "base/options.h"
|
2019-09-18 11:19:05 +00:00
|
|
|
#include "styles/style_layers.h"
|
2018-09-06 17:58:44 +00:00
|
|
|
#include "styles/style_settings.h"
|
2021-12-09 17:56:24 +00:00
|
|
|
#include "styles/style_menu_icons.h"
|
2018-09-05 19:05:49 +00:00
|
|
|
|
2022-03-30 16:52:33 +00:00
|
|
|
#include <QAction>
|
|
|
|
|
2018-09-05 19:05:49 +00:00
|
|
|
namespace Settings {
|
2022-03-14 06:20:36 +00:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
base::options::toggle OptionMonoSettingsIcons({
|
|
|
|
.id = kOptionMonoSettingsIcons,
|
|
|
|
.name = "Mono settings and menu icons",
|
|
|
|
.description = "Use a single color for settings and main menu icons.",
|
|
|
|
});
|
|
|
|
|
|
|
|
} // namespace
|
|
|
|
|
|
|
|
const char kOptionMonoSettingsIcons[] = "mono-settings-icons";
|
2018-09-05 19:05:49 +00:00
|
|
|
|
2022-02-09 10:43:07 +00:00
|
|
|
Icon::Icon(IconDescriptor descriptor) : _icon(descriptor.icon) {
|
|
|
|
const auto background = [&] {
|
2022-03-14 06:20:36 +00:00
|
|
|
if (OptionMonoSettingsIcons.value()) {
|
|
|
|
return &st::transparent;
|
|
|
|
}
|
2022-02-09 10:43:07 +00:00
|
|
|
if (descriptor.color > 0) {
|
|
|
|
const auto list = std::array{
|
|
|
|
&st::settingsIconBg1,
|
|
|
|
&st::settingsIconBg2,
|
|
|
|
&st::settingsIconBg3,
|
|
|
|
&st::settingsIconBg4,
|
|
|
|
&st::settingsIconBg5,
|
|
|
|
&st::settingsIconBg6,
|
|
|
|
(const style::color*)nullptr,
|
|
|
|
&st::settingsIconBg8,
|
|
|
|
&st::settingsIconBgArchive,
|
|
|
|
};
|
|
|
|
Assert(descriptor.color < 10 && descriptor.color != 7);
|
|
|
|
return list[descriptor.color - 1];
|
|
|
|
}
|
|
|
|
return descriptor.background;
|
|
|
|
}();
|
|
|
|
if (background) {
|
2022-02-10 09:56:57 +00:00
|
|
|
const auto radius = (descriptor.type == IconType::Rounded)
|
|
|
|
? st::settingsIconRadius
|
|
|
|
: (std::min(_icon->width(), _icon->height()) / 2);
|
|
|
|
_background.emplace(radius, *background);
|
2022-05-18 23:35:39 +00:00
|
|
|
} else if (const auto brush = descriptor.backgroundBrush) {
|
|
|
|
const auto radius = (descriptor.type == IconType::Rounded)
|
|
|
|
? st::settingsIconRadius
|
|
|
|
: (std::min(_icon->width(), _icon->height()) / 2);
|
|
|
|
_backgroundBrush.emplace(radius, std::move(*brush));
|
2022-02-09 10:43:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Icon::paint(QPainter &p, QPoint position) const {
|
|
|
|
paint(p, position.x(), position.y());
|
|
|
|
}
|
|
|
|
|
|
|
|
void Icon::paint(QPainter &p, int x, int y) const {
|
|
|
|
if (_background) {
|
|
|
|
_background->paint(p, { { x, y }, _icon->size() });
|
2022-05-18 23:35:39 +00:00
|
|
|
} else if (_backgroundBrush) {
|
|
|
|
PainterHighQualityEnabler hq(p);
|
|
|
|
p.setPen(Qt::NoPen);
|
|
|
|
p.setBrush(_backgroundBrush->second);
|
|
|
|
p.drawRoundedRect(
|
|
|
|
QRect(QPoint(x, y), _icon->size()),
|
|
|
|
_backgroundBrush->first,
|
|
|
|
_backgroundBrush->first);
|
2022-02-09 10:43:07 +00:00
|
|
|
}
|
2022-03-14 06:20:36 +00:00
|
|
|
if (OptionMonoSettingsIcons.value()) {
|
|
|
|
_icon->paint(p, { x, y }, 2 * x + _icon->width(), st::menuIconFg->c);
|
|
|
|
} else {
|
|
|
|
_icon->paint(p, { x, y }, 2 * x + _icon->width());
|
|
|
|
}
|
2022-02-09 10:43:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
int Icon::width() const {
|
|
|
|
return _icon->width();
|
|
|
|
}
|
|
|
|
|
|
|
|
int Icon::height() const {
|
|
|
|
return _icon->height();
|
|
|
|
}
|
|
|
|
|
|
|
|
QSize Icon::size() const {
|
|
|
|
return _icon->size();
|
|
|
|
}
|
|
|
|
|
2018-09-07 09:40:25 +00:00
|
|
|
void AddSkip(not_null<Ui::VerticalLayout*> container) {
|
2018-09-07 12:19:56 +00:00
|
|
|
AddSkip(container, st::settingsSectionSkip);
|
|
|
|
}
|
|
|
|
|
|
|
|
void AddSkip(not_null<Ui::VerticalLayout*> container, int skip) {
|
2018-09-07 09:40:25 +00:00
|
|
|
container->add(object_ptr<Ui::FixedHeightWidget>(
|
|
|
|
container,
|
2018-09-07 12:19:56 +00:00
|
|
|
skip));
|
2018-09-07 09:40:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void AddDivider(not_null<Ui::VerticalLayout*> container) {
|
2019-09-18 11:19:05 +00:00
|
|
|
container->add(object_ptr<Ui::BoxContentDivider>(container));
|
2018-09-07 09:40:25 +00:00
|
|
|
}
|
|
|
|
|
2018-09-09 12:10:54 +00:00
|
|
|
void AddDividerText(
|
2022-02-09 10:43:07 +00:00
|
|
|
not_null<Ui::VerticalLayout*> container,
|
|
|
|
rpl::producer<QString> text) {
|
2018-09-09 12:10:54 +00:00
|
|
|
container->add(object_ptr<Ui::DividerLabel>(
|
|
|
|
container,
|
|
|
|
object_ptr<Ui::FlatLabel>(
|
|
|
|
container,
|
|
|
|
std::move(text),
|
|
|
|
st::boxDividerLabel),
|
|
|
|
st::settingsDividerLabelPadding));
|
|
|
|
}
|
|
|
|
|
2022-02-09 10:43:07 +00:00
|
|
|
void AddButtonIcon(
|
2021-05-06 15:57:40 +00:00
|
|
|
not_null<Ui::AbstractButton*> button,
|
2022-02-09 10:43:07 +00:00
|
|
|
const style::SettingsButton &st,
|
|
|
|
IconDescriptor &&descriptor) {
|
|
|
|
Expects(descriptor.icon != nullptr);
|
|
|
|
|
|
|
|
struct IconWidget {
|
|
|
|
IconWidget(QWidget *parent, IconDescriptor &&descriptor)
|
|
|
|
: widget(parent)
|
|
|
|
, icon(std::move(descriptor)) {
|
|
|
|
}
|
|
|
|
Ui::RpWidget widget;
|
|
|
|
Icon icon;
|
|
|
|
};
|
|
|
|
const auto icon = button->lifetime().make_state<IconWidget>(
|
|
|
|
button,
|
|
|
|
std::move(descriptor));
|
|
|
|
icon->widget.setAttribute(Qt::WA_TransparentForMouseEvents);
|
|
|
|
icon->widget.resize(icon->icon.size());
|
2021-05-06 15:57:40 +00:00
|
|
|
button->sizeValue(
|
2022-02-09 10:43:07 +00:00
|
|
|
) | rpl::start_with_next([=, left = st.iconLeft](QSize size) {
|
|
|
|
icon->widget.moveToLeft(
|
|
|
|
left,
|
|
|
|
(size.height() - icon->widget.height()) / 2,
|
2021-05-06 15:57:40 +00:00
|
|
|
size.width());
|
2022-02-09 10:43:07 +00:00
|
|
|
}, icon->widget.lifetime());
|
|
|
|
icon->widget.paintRequest(
|
2021-05-06 15:57:40 +00:00
|
|
|
) | rpl::start_with_next([=] {
|
2022-02-09 10:43:07 +00:00
|
|
|
auto p = QPainter(&icon->widget);
|
|
|
|
icon->icon.paint(p, 0, 0);
|
|
|
|
}, icon->widget.lifetime());
|
2021-05-06 15:57:40 +00:00
|
|
|
}
|
|
|
|
|
2020-03-24 07:26:08 +00:00
|
|
|
object_ptr<Button> CreateButton(
|
|
|
|
not_null<QWidget*> parent,
|
2018-09-13 20:09:26 +00:00
|
|
|
rpl::producer<QString> text,
|
2019-11-02 17:06:47 +00:00
|
|
|
const style::SettingsButton &st,
|
2022-02-09 10:43:07 +00:00
|
|
|
IconDescriptor &&descriptor) {
|
2020-03-24 07:26:08 +00:00
|
|
|
auto result = object_ptr<Button>(parent, std::move(text), st);
|
|
|
|
const auto button = result.data();
|
2022-02-09 10:43:07 +00:00
|
|
|
if (descriptor) {
|
|
|
|
AddButtonIcon(button, st, std::move(descriptor));
|
2018-09-10 12:18:39 +00:00
|
|
|
}
|
|
|
|
return result;
|
2018-09-07 09:40:25 +00:00
|
|
|
}
|
|
|
|
|
2020-03-24 07:26:08 +00:00
|
|
|
not_null<Button*> AddButton(
|
|
|
|
not_null<Ui::VerticalLayout*> container,
|
|
|
|
rpl::producer<QString> text,
|
|
|
|
const style::SettingsButton &st,
|
2022-02-09 10:43:07 +00:00
|
|
|
IconDescriptor &&descriptor) {
|
2020-03-24 07:26:08 +00:00
|
|
|
return container->add(
|
2022-02-09 10:43:07 +00:00
|
|
|
CreateButton(container, std::move(text), st, std::move(descriptor)));
|
2020-03-24 07:26:08 +00:00
|
|
|
}
|
|
|
|
|
2018-09-09 12:10:54 +00:00
|
|
|
void CreateRightLabel(
|
|
|
|
not_null<Button*> button,
|
2018-09-15 10:37:48 +00:00
|
|
|
rpl::producer<QString> label,
|
2019-11-02 17:06:47 +00:00
|
|
|
const style::SettingsButton &st,
|
2019-06-18 12:16:43 +00:00
|
|
|
rpl::producer<QString> buttonText) {
|
2018-09-07 09:40:25 +00:00
|
|
|
const auto name = Ui::CreateChild<Ui::FlatLabel>(
|
|
|
|
button.get(),
|
2020-11-29 18:26:49 +00:00
|
|
|
st.rightLabel);
|
2018-09-07 09:40:25 +00:00
|
|
|
rpl::combine(
|
2018-09-17 10:52:34 +00:00
|
|
|
button->widthValue(),
|
2019-06-18 12:16:43 +00:00
|
|
|
std::move(buttonText),
|
2018-09-17 10:52:34 +00:00
|
|
|
std::move(label)
|
|
|
|
) | rpl::start_with_next([=, &st](
|
|
|
|
int width,
|
|
|
|
const QString &button,
|
|
|
|
const QString &text) {
|
|
|
|
const auto available = width
|
|
|
|
- st.padding.left()
|
|
|
|
- st.padding.right()
|
2022-03-01 09:51:22 +00:00
|
|
|
- st.style.font->width(button)
|
2018-09-17 10:52:34 +00:00
|
|
|
- st::settingsButtonRightSkip;
|
|
|
|
name->setText(text);
|
|
|
|
name->resizeToNaturalWidth(available);
|
2018-09-15 10:37:48 +00:00
|
|
|
name->moveToRight(st::settingsButtonRightSkip, st.padding.top());
|
2018-09-07 09:40:25 +00:00
|
|
|
}, name->lifetime());
|
|
|
|
name->setAttribute(Qt::WA_TransparentForMouseEvents);
|
2018-09-09 12:10:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
not_null<Button*> AddButtonWithLabel(
|
|
|
|
not_null<Ui::VerticalLayout*> container,
|
2019-06-18 12:16:43 +00:00
|
|
|
rpl::producer<QString> text,
|
2018-09-09 12:10:54 +00:00
|
|
|
rpl::producer<QString> label,
|
2019-11-02 17:06:47 +00:00
|
|
|
const style::SettingsButton &st,
|
2022-02-09 10:43:07 +00:00
|
|
|
IconDescriptor &&descriptor) {
|
2019-06-18 12:16:43 +00:00
|
|
|
const auto button = AddButton(
|
|
|
|
container,
|
|
|
|
rpl::duplicate(text),
|
|
|
|
st,
|
2022-02-09 10:43:07 +00:00
|
|
|
std::move(descriptor));
|
2019-06-18 12:16:43 +00:00
|
|
|
CreateRightLabel(button, std::move(label), st, std::move(text));
|
2018-09-07 09:40:25 +00:00
|
|
|
return button;
|
|
|
|
}
|
|
|
|
|
2019-09-04 15:59:43 +00:00
|
|
|
not_null<Ui::FlatLabel*> AddSubsectionTitle(
|
2018-09-09 12:10:54 +00:00
|
|
|
not_null<Ui::VerticalLayout*> container,
|
2022-02-13 13:30:43 +00:00
|
|
|
rpl::producer<QString> text,
|
2022-03-01 05:22:56 +00:00
|
|
|
style::margins addPadding,
|
|
|
|
const style::FlatLabel *st) {
|
2019-09-04 15:59:43 +00:00
|
|
|
return container->add(
|
2018-09-09 12:10:54 +00:00
|
|
|
object_ptr<Ui::FlatLabel>(
|
|
|
|
container,
|
2018-09-29 12:18:26 +00:00
|
|
|
std::move(text),
|
2022-03-01 05:22:56 +00:00
|
|
|
st ? *st : st::settingsSubsectionTitle),
|
2022-02-13 13:30:43 +00:00
|
|
|
st::settingsSubsectionTitlePadding + addPadding);
|
2018-09-09 12:10:54 +00:00
|
|
|
}
|
2022-04-13 08:05:10 +00:00
|
|
|
|
|
|
|
LottieIcon CreateLottieIcon(
|
|
|
|
not_null<QWidget*> parent,
|
|
|
|
Lottie::IconDescriptor &&descriptor,
|
2022-05-04 07:39:53 +00:00
|
|
|
style::margins padding) {
|
2022-08-23 18:34:51 +00:00
|
|
|
Expects(!descriptor.frame); // I'm not sure it considers limitFps.
|
|
|
|
|
|
|
|
descriptor.limitFps = true;
|
|
|
|
|
2022-04-13 08:05:10 +00:00
|
|
|
auto object = object_ptr<Ui::RpWidget>(parent);
|
|
|
|
const auto raw = object.data();
|
|
|
|
|
|
|
|
const auto width = descriptor.sizeOverride.width();
|
|
|
|
raw->resize(QRect(
|
|
|
|
QPoint(),
|
|
|
|
descriptor.sizeOverride).marginsAdded(padding).size());
|
|
|
|
|
|
|
|
auto owned = Lottie::MakeIcon(std::move(descriptor));
|
|
|
|
const auto icon = owned.get();
|
|
|
|
|
|
|
|
raw->lifetime().add([kept = std::move(owned)]{});
|
2022-05-04 07:39:53 +00:00
|
|
|
const auto looped = raw->lifetime().make_state<bool>(true);
|
2022-04-13 08:05:10 +00:00
|
|
|
|
2022-05-04 07:39:53 +00:00
|
|
|
const auto start = [=] {
|
2022-05-01 18:08:16 +00:00
|
|
|
icon->animate([=] { raw->update(); }, 0, icon->framesCount() - 1);
|
2022-04-13 08:05:10 +00:00
|
|
|
};
|
2022-05-04 07:39:53 +00:00
|
|
|
const auto animate = [=](anim::repeat repeat) {
|
|
|
|
*looped = (repeat == anim::repeat::loop);
|
|
|
|
start();
|
|
|
|
};
|
2022-04-13 08:05:10 +00:00
|
|
|
raw->paintRequest(
|
|
|
|
) | rpl::start_with_next([=] {
|
|
|
|
auto p = QPainter(raw);
|
|
|
|
const auto left = (raw->width() - width) / 2;
|
|
|
|
icon->paint(p, left, padding.top());
|
2022-05-04 07:39:53 +00:00
|
|
|
if (!icon->animating() && icon->frameIndex() > 0 && *looped) {
|
|
|
|
start();
|
2022-04-13 08:05:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}, raw->lifetime());
|
|
|
|
|
|
|
|
return { .widget = std::move(object), .animate = std::move(animate) };
|
|
|
|
}
|
2018-09-09 12:10:54 +00:00
|
|
|
|
2019-07-24 14:00:30 +00:00
|
|
|
void FillMenu(
|
2019-09-08 12:47:22 +00:00
|
|
|
not_null<Window::SessionController*> controller,
|
|
|
|
Type type,
|
2019-07-24 14:00:30 +00:00
|
|
|
Fn<void(Type)> showOther,
|
2022-06-03 16:07:33 +00:00
|
|
|
Ui::Menu::MenuCallback addAction) {
|
2019-09-08 12:47:22 +00:00
|
|
|
const auto window = &controller->window();
|
2022-04-01 11:53:23 +00:00
|
|
|
if (type == Chat::Id()) {
|
2019-09-08 12:47:22 +00:00
|
|
|
addAction(
|
|
|
|
tr::lng_settings_bg_theme_create(tr::now),
|
2021-12-09 17:56:24 +00:00
|
|
|
[=] { window->show(Box(Window::Theme::CreateBox, window)); },
|
|
|
|
&st::menuIconChangeColors);
|
2022-05-07 02:45:52 +00:00
|
|
|
} else if (type == CloudPasswordEmailConfirmId()) {
|
|
|
|
const auto api = &controller->session().api();
|
|
|
|
if (const auto state = api->cloudPassword().stateCurrent()) {
|
|
|
|
if (state->unconfirmedPattern.isEmpty()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
addAction(
|
|
|
|
tr::lng_settings_password_abort(tr::now),
|
|
|
|
[=] { api->cloudPassword().clearUnconfirmedPassword(); },
|
|
|
|
&st::menuIconCancel);
|
2019-09-08 12:47:22 +00:00
|
|
|
} else {
|
2020-06-30 17:16:05 +00:00
|
|
|
const auto &list = Core::App().domain().accounts();
|
2022-05-31 12:32:41 +00:00
|
|
|
if (list.size() < Core::App().domain().maxAccounts()) {
|
2020-06-30 17:16:05 +00:00
|
|
|
addAction(tr::lng_menu_add_account(tr::now), [=] {
|
|
|
|
Core::App().domain().addActivated(MTP::Environment{});
|
2021-12-09 17:56:24 +00:00
|
|
|
}, &st::menuIconAddAccount);
|
2020-06-30 17:16:05 +00:00
|
|
|
}
|
2019-09-08 12:47:22 +00:00
|
|
|
if (!controller->session().supportMode()) {
|
|
|
|
addAction(
|
|
|
|
tr::lng_settings_information(tr::now),
|
2022-04-01 11:53:23 +00:00
|
|
|
[=] { showOther(Information::Id()); },
|
2021-12-09 17:56:24 +00:00
|
|
|
&st::menuIconInfo);
|
2019-09-08 12:47:22 +00:00
|
|
|
}
|
2022-04-04 14:15:45 +00:00
|
|
|
addAction({
|
|
|
|
.text = tr::lng_settings_logout(tr::now),
|
|
|
|
.handler = [=] { window->showLogoutConfirmation(); },
|
|
|
|
.icon = &st::menuIconLeaveAttention,
|
|
|
|
.isAttention = true,
|
|
|
|
});
|
2018-10-07 11:42:09 +00:00
|
|
|
}
|
2018-09-06 15:24:24 +00:00
|
|
|
}
|
|
|
|
|
2018-09-05 19:05:49 +00:00
|
|
|
} // namespace Settings
|