mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2026-07-25 06:54:43 +00:00
Initial settings builder experiment.
This commit is contained in:
@@ -1567,6 +1567,10 @@ PRIVATE
|
||||
settings/settings_local_passcode.h
|
||||
settings/settings_main.cpp
|
||||
settings/settings_main.h
|
||||
settings/builder/settings_builder.cpp
|
||||
settings/builder/settings_builder.h
|
||||
settings/builder/settings_main_builder.cpp
|
||||
settings/builder/settings_main_builder.h
|
||||
settings/settings_notifications.cpp
|
||||
settings/settings_notifications.h
|
||||
settings/settings_notifications_type.cpp
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
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/builder/settings_builder.h"
|
||||
|
||||
#include "settings/settings_common.h"
|
||||
#include "ui/vertical_list.h"
|
||||
#include "ui/widgets/buttons.h"
|
||||
#include "ui/wrap/vertical_layout.h"
|
||||
#include "styles/style_settings.h"
|
||||
|
||||
namespace Settings::Builder {
|
||||
namespace {
|
||||
|
||||
[[nodiscard]] QString ResolveTitle(rpl::producer<QString> title) {
|
||||
auto result = QString();
|
||||
auto lifetime = rpl::lifetime();
|
||||
std::move(title).start(
|
||||
[&](QString value) { result = std::move(value); },
|
||||
[](auto&&) {},
|
||||
[] {},
|
||||
lifetime);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
SectionBuilder::SectionBuilder(BuildContext context)
|
||||
: _context(std::move(context)) {
|
||||
}
|
||||
|
||||
Ui::RpWidget *SectionBuilder::addControl(ControlArgs &&args) {
|
||||
return v::match(_context, [&](const WidgetContext &ctx) {
|
||||
if (!args.factory) {
|
||||
return static_cast<Ui::RpWidget*>(nullptr);
|
||||
}
|
||||
auto widget = args.factory(ctx.container);
|
||||
const auto raw = widget.data();
|
||||
ctx.container->add(std::move(widget), args.margin);
|
||||
return raw;
|
||||
}, [&](const SearchContext &ctx) {
|
||||
if (!args.id.isEmpty()) {
|
||||
ctx.entries->push_back({
|
||||
.id = std::move(args.id),
|
||||
.title = ResolveTitle(std::move(args.title)),
|
||||
.keywords = std::move(args.keywords),
|
||||
});
|
||||
}
|
||||
return static_cast<Ui::RpWidget*>(nullptr);
|
||||
});
|
||||
}
|
||||
|
||||
Ui::SettingsButton *SectionBuilder::addSettingsButton(ButtonArgs &&args) {
|
||||
const auto &st = args.st ? *args.st : st::settingsButton;
|
||||
const auto button = v::match(_context, [&](const WidgetContext &ctx) -> Ui::SettingsButton* {
|
||||
if (args.label) {
|
||||
return AddButtonWithLabel(
|
||||
ctx.container,
|
||||
rpl::duplicate(args.title),
|
||||
std::move(args.label),
|
||||
st,
|
||||
std::move(args.icon));
|
||||
} else {
|
||||
return ctx.container->add(CreateButtonWithIcon(
|
||||
ctx.container,
|
||||
rpl::duplicate(args.title),
|
||||
st,
|
||||
std::move(args.icon)));
|
||||
}
|
||||
}, [&](const SearchContext &ctx) -> Ui::SettingsButton* {
|
||||
if (!args.id.isEmpty()) {
|
||||
ctx.entries->push_back({
|
||||
.id = std::move(args.id),
|
||||
.title = ResolveTitle(std::move(args.title)),
|
||||
.keywords = std::move(args.keywords),
|
||||
});
|
||||
}
|
||||
return nullptr;
|
||||
});
|
||||
if (button && args.onClick) {
|
||||
button->addClickHandler(std::move(args.onClick));
|
||||
}
|
||||
return button;
|
||||
}
|
||||
|
||||
Ui::SettingsButton *SectionBuilder::addLabeledButton(ButtonArgs &&args) {
|
||||
return addSettingsButton(std::move(args));
|
||||
}
|
||||
|
||||
Ui::SettingsButton *SectionBuilder::addSectionButton(SectionArgs &&args) {
|
||||
const auto button = addSettingsButton({
|
||||
.id = std::move(args.id),
|
||||
.title = std::move(args.title),
|
||||
.icon = std::move(args.icon),
|
||||
.keywords = std::move(args.keywords),
|
||||
});
|
||||
if (button) {
|
||||
const auto showOther = std::get<WidgetContext>(_context).showOther;
|
||||
const auto target = args.targetSection;
|
||||
button->addClickHandler([=] {
|
||||
showOther(target);
|
||||
});
|
||||
}
|
||||
return button;
|
||||
}
|
||||
|
||||
void SectionBuilder::addDivider() {
|
||||
v::match(_context, [&](const WidgetContext &ctx) {
|
||||
Ui::AddDivider(ctx.container);
|
||||
}, [](const SearchContext &) {
|
||||
});
|
||||
}
|
||||
|
||||
void SectionBuilder::addSkip() {
|
||||
v::match(_context, [&](const WidgetContext &ctx) {
|
||||
Ui::AddSkip(ctx.container);
|
||||
}, [](const SearchContext &) {
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace Settings::Builder
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "base/object_ptr.h"
|
||||
#include "settings/settings_common.h"
|
||||
#include "settings/settings_type.h"
|
||||
|
||||
#include <variant>
|
||||
|
||||
namespace Ui {
|
||||
class RpWidget;
|
||||
class VerticalLayout;
|
||||
class SettingsButton;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
class SessionController;
|
||||
} // namespace Window
|
||||
|
||||
namespace style {
|
||||
struct SettingsButton;
|
||||
} // namespace style
|
||||
|
||||
namespace Settings::Builder {
|
||||
|
||||
struct SearchEntry {
|
||||
QString id;
|
||||
QString title;
|
||||
QStringList keywords;
|
||||
};
|
||||
|
||||
struct WidgetContext {
|
||||
not_null<Ui::VerticalLayout*> container;
|
||||
not_null<Window::SessionController*> controller;
|
||||
Fn<void(Type)> showOther;
|
||||
};
|
||||
|
||||
struct SearchContext {
|
||||
not_null<std::vector<SearchEntry>*> entries;
|
||||
};
|
||||
|
||||
using BuildContext = std::variant<WidgetContext, SearchContext>;
|
||||
|
||||
class SectionBuilder {
|
||||
public:
|
||||
explicit SectionBuilder(BuildContext context);
|
||||
|
||||
struct ControlArgs {
|
||||
Fn<object_ptr<Ui::RpWidget>(not_null<Ui::VerticalLayout*>)> factory;
|
||||
QString id;
|
||||
rpl::producer<QString> title;
|
||||
QStringList keywords;
|
||||
style::margins margin;
|
||||
};
|
||||
Ui::RpWidget *addControl(ControlArgs &&args);
|
||||
|
||||
struct ButtonArgs {
|
||||
QString id;
|
||||
rpl::producer<QString> title;
|
||||
const style::SettingsButton *st = nullptr;
|
||||
IconDescriptor icon;
|
||||
rpl::producer<QString> label;
|
||||
Fn<void()> onClick;
|
||||
QStringList keywords;
|
||||
};
|
||||
Ui::SettingsButton *addSettingsButton(ButtonArgs &&args);
|
||||
Ui::SettingsButton *addLabeledButton(ButtonArgs &&args);
|
||||
|
||||
struct SectionArgs {
|
||||
QString id;
|
||||
rpl::producer<QString> title;
|
||||
Type targetSection;
|
||||
IconDescriptor icon;
|
||||
QStringList keywords;
|
||||
};
|
||||
Ui::SettingsButton *addSectionButton(SectionArgs &&args);
|
||||
|
||||
void addDivider();
|
||||
void addSkip();
|
||||
|
||||
private:
|
||||
BuildContext _context;
|
||||
};
|
||||
|
||||
} // namespace Settings::Builder
|
||||
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
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/builder/settings_main_builder.h"
|
||||
|
||||
#include "ui/layers/generic_box.h"
|
||||
#include "settings/builder/settings_builder.h"
|
||||
#include "settings/settings_advanced.h"
|
||||
#include "settings/settings_calls.h"
|
||||
#include "settings/settings_chat.h"
|
||||
#include "settings/settings_folders.h"
|
||||
#include "settings/settings_information.h"
|
||||
#include "settings/settings_notifications.h"
|
||||
#include "settings/settings_power_saving.h"
|
||||
#include "settings/settings_privacy_security.h"
|
||||
#include "boxes/language_box.h"
|
||||
#include "lang/lang_instance.h"
|
||||
#include "lang/lang_keys.h"
|
||||
#include "window/window_controller.h"
|
||||
#include "window/window_session_controller.h"
|
||||
#include "styles/style_menu_icons.h"
|
||||
#include "styles/style_settings.h"
|
||||
|
||||
namespace Settings::Builder {
|
||||
namespace {
|
||||
|
||||
void BuildMainSectionContent(
|
||||
SectionBuilder &builder,
|
||||
Window::SessionController *controller) {
|
||||
builder.addDivider();
|
||||
builder.addSkip();
|
||||
|
||||
builder.addSectionButton({
|
||||
.id = u"main/account"_q,
|
||||
.title = tr::lng_settings_my_account(),
|
||||
.targetSection = Information::Id(),
|
||||
.icon = { &st::menuIconProfile },
|
||||
.keywords = { u"profile"_q, u"edit"_q, u"information"_q },
|
||||
});
|
||||
|
||||
builder.addSectionButton({
|
||||
.id = u"main/notifications"_q,
|
||||
.title = tr::lng_settings_section_notify(),
|
||||
.targetSection = Notifications::Id(),
|
||||
.icon = { &st::menuIconNotifications },
|
||||
.keywords = { u"alerts"_q, u"sounds"_q, u"badge"_q },
|
||||
});
|
||||
|
||||
builder.addSectionButton({
|
||||
.id = u"main/privacy"_q,
|
||||
.title = tr::lng_settings_section_privacy(),
|
||||
.targetSection = PrivacySecurity::Id(),
|
||||
.icon = { &st::menuIconLock },
|
||||
.keywords = { u"security"_q, u"passcode"_q, u"password"_q, u"2fa"_q },
|
||||
});
|
||||
|
||||
builder.addSectionButton({
|
||||
.id = u"main/chat"_q,
|
||||
.title = tr::lng_settings_section_chat_settings(),
|
||||
.targetSection = Chat::Id(),
|
||||
.icon = { &st::menuIconChatBubble },
|
||||
.keywords = { u"themes"_q, u"appearance"_q, u"stickers"_q },
|
||||
});
|
||||
|
||||
builder.addSectionButton({
|
||||
.id = u"main/folders"_q,
|
||||
.title = tr::lng_settings_section_filters(),
|
||||
.targetSection = Folders::Id(),
|
||||
.icon = { &st::menuIconShowInFolder },
|
||||
.keywords = { u"filters"_q, u"tabs"_q },
|
||||
});
|
||||
|
||||
builder.addSectionButton({
|
||||
.id = u"main/advanced"_q,
|
||||
.title = tr::lng_settings_advanced(),
|
||||
.targetSection = Advanced::Id(),
|
||||
.icon = { &st::menuIconManage },
|
||||
.keywords = { u"performance"_q, u"proxy"_q, u"experimental"_q },
|
||||
});
|
||||
|
||||
builder.addSectionButton({
|
||||
.id = u"main/devices"_q,
|
||||
.title = tr::lng_settings_section_devices(),
|
||||
.targetSection = Calls::Id(),
|
||||
.icon = { &st::menuIconUnmute },
|
||||
.keywords = { u"sessions"_q, u"calls"_q },
|
||||
});
|
||||
|
||||
const auto window = controller ? &controller->window() : nullptr;
|
||||
builder.addSettingsButton({
|
||||
.id = u"main/power"_q,
|
||||
.title = tr::lng_settings_power_menu(),
|
||||
.icon = { &st::menuIconPowerUsage },
|
||||
.onClick = window
|
||||
? [=] { window->show(Box(PowerSavingBox)); }
|
||||
: Fn<void()>(nullptr),
|
||||
.keywords = { u"battery"_q, u"animations"_q, u"power"_q, u"saving"_q },
|
||||
});
|
||||
|
||||
builder.addLabeledButton({
|
||||
.id = u"main/language"_q,
|
||||
.title = tr::lng_settings_language(),
|
||||
.icon = { &st::menuIconTranslate },
|
||||
.label = rpl::single(
|
||||
Lang::GetInstance().id()
|
||||
) | rpl::then(
|
||||
Lang::GetInstance().idChanges()
|
||||
) | rpl::map([] { return Lang::GetInstance().nativeName(); }),
|
||||
.onClick = controller
|
||||
? [=] { LanguageBox::Show(controller); }
|
||||
: Fn<void()>(nullptr),
|
||||
.keywords = { u"translate"_q, u"localization"_q },
|
||||
});
|
||||
|
||||
builder.addSkip();
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void BuildMainSection(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
not_null<Window::SessionController*> controller,
|
||||
Fn<void(Type)> showOther) {
|
||||
auto builder = SectionBuilder(WidgetContext{
|
||||
.container = container,
|
||||
.controller = controller,
|
||||
.showOther = std::move(showOther),
|
||||
});
|
||||
BuildMainSectionContent(builder, controller);
|
||||
}
|
||||
|
||||
std::vector<SearchEntry> BuildMainSectionForSearch() {
|
||||
auto entries = std::vector<SearchEntry>();
|
||||
auto builder = SectionBuilder(SearchContext{
|
||||
.entries = &entries,
|
||||
});
|
||||
BuildMainSectionContent(builder, nullptr);
|
||||
return entries;
|
||||
}
|
||||
|
||||
} // namespace Settings::Builder
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "settings/settings_type.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Ui {
|
||||
class VerticalLayout;
|
||||
} // namespace Ui
|
||||
|
||||
namespace Window {
|
||||
class SessionController;
|
||||
} // namespace Window
|
||||
|
||||
namespace Settings::Builder {
|
||||
|
||||
struct SearchEntry;
|
||||
|
||||
void BuildMainSection(
|
||||
not_null<Ui::VerticalLayout*> container,
|
||||
not_null<Window::SessionController*> controller,
|
||||
Fn<void(Type)> showOther);
|
||||
|
||||
[[nodiscard]] std::vector<SearchEntry> BuildMainSectionForSearch();
|
||||
|
||||
} // namespace Settings::Builder
|
||||
@@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||
*/
|
||||
#include "settings/settings_main.h"
|
||||
|
||||
#include "settings/builder/settings_main_builder.h"
|
||||
#include "api/api_credits.h"
|
||||
#include "core/application.h"
|
||||
#include "core/click_handler_types.h"
|
||||
@@ -1034,7 +1035,7 @@ Main::Main(
|
||||
not_null<Window::SessionController*> controller)
|
||||
: Section(parent)
|
||||
, _controller(controller) {
|
||||
setupContent(controller);
|
||||
setupContentWithBuilder(controller);
|
||||
_controller->session().api().premium().reload();
|
||||
}
|
||||
|
||||
@@ -1099,6 +1100,35 @@ void Main::setupContent(not_null<Window::SessionController*> controller) {
|
||||
controller->session().data().cloudThemes().refresh();
|
||||
}
|
||||
|
||||
void Main::setupContentWithBuilder(
|
||||
not_null<Window::SessionController*> controller) {
|
||||
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
|
||||
|
||||
content->add(object_ptr<Cover>(
|
||||
content,
|
||||
controller,
|
||||
controller->session().user()));
|
||||
|
||||
Builder::BuildMainSection(content, controller, showOtherMethod());
|
||||
|
||||
if (HasInterfaceScale()) {
|
||||
Ui::AddDivider(content);
|
||||
Ui::AddSkip(content);
|
||||
SetupInterfaceScale(&controller->window(), content);
|
||||
Ui::AddSkip(content);
|
||||
}
|
||||
SetupPremium(controller, content, showOtherMethod());
|
||||
SetupHelp(controller, content);
|
||||
|
||||
Ui::ResizeFitChild(this, content);
|
||||
|
||||
controller->session().api().cloudPassword().reload();
|
||||
controller->session().api().reloadContactSignupSilent();
|
||||
controller->session().api().sensitiveContent().reload();
|
||||
controller->session().api().globalPrivacy().reload();
|
||||
controller->session().data().cloudThemes().refresh();
|
||||
}
|
||||
|
||||
void OpenFaq(base::weak_ptr<Window::SessionController> weak) {
|
||||
UrlClickHandler::Open(
|
||||
tr::lng_settings_faq_link(tr::now),
|
||||
|
||||
@@ -45,6 +45,7 @@ protected:
|
||||
|
||||
private:
|
||||
void setupContent(not_null<Window::SessionController*> controller);
|
||||
void setupContentWithBuilder(not_null<Window::SessionController*> controller);
|
||||
|
||||
const not_null<Window::SessionController*> _controller;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user