Added simple implementation of import/export for experimental settings.

This commit is contained in:
23rd
2026-03-07 09:51:10 +03:00
committed by John Preston
parent ccb563eff1
commit c86d2c6986
4 changed files with 65 additions and 6 deletions

View File

@@ -10,6 +10,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/components/passkeys.h"
#include "main/main_session.h"
#include "ui/boxes/confirm_box.h"
#include "ui/text/text_entity.h"
#include "ui/widgets/menu/menu_add_action_callback.h"
#include "ui/wrap/vertical_layout.h"
#include "ui/wrap/slide_wrap.h"
#include "ui/widgets/buttons.h"
@@ -42,15 +44,26 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "chat_helpers/stickers_list_widget.h"
#include "styles/style_settings.h"
#include "styles/style_layers.h"
#include "styles/style_menu_icons.h"
#include <QtCore/QJsonDocument>
#include <QtGui/QGuiApplication>
namespace Settings {
namespace {
[[nodiscard]] bool CanImportOptionsFromText(const QString &text) {
auto error = QJsonParseError();
const auto parsed = QJsonDocument::fromJson(text.toUtf8(), &error);
return (error.error == QJsonParseError::NoError) && parsed.isObject();
}
void AddOption(
not_null<Window::Controller*> window,
not_null<Ui::VerticalLayout*> container,
base::options::option<bool> &option,
rpl::producer<> resetClicks) {
rpl::producer<> resetClicks,
rpl::producer<> reloadOptionsRequests) {
auto &lifetime = container->lifetime();
const auto name = option.name().isEmpty() ? option.id() : option.name();
const auto toggles = lifetime.make_state<rpl::event_stream<bool>>();
@@ -59,6 +72,9 @@ void AddOption(
) | rpl::map_to(
option.defaultValue()
) | rpl::start_to_stream(*toggles, lifetime);
std::move(reloadOptionsRequests) | rpl::on_next([=, &option] {
toggles->fire_copy(option.value());
}, lifetime);
const auto button = container->add(object_ptr<Button>(
container,
@@ -105,7 +121,8 @@ void AddOption(
void SetupExperimental(
not_null<Window::Controller*> window,
not_null<Ui::VerticalLayout*> container) {
not_null<Ui::VerticalLayout*> container,
rpl::producer<> reloadOptionsRequests) {
Ui::AddSkip(container, st::settingsCheckboxesSkip);
container->add(
@@ -145,7 +162,8 @@ void SetupExperimental(
base::options::lookup<bool>(name),
(reset
? (reset->clicks() | rpl::to_empty)
: rpl::producer<>()));
: rpl::producer<>()),
rpl::duplicate(reloadOptionsRequests));
};
addToggle(ChatHelpers::kOptionTabbedPanelShowOnClick);
@@ -193,10 +211,46 @@ rpl::producer<QString> Experimental::title() {
return tr::lng_settings_experimental();
}
void Experimental::fillTopBarMenu(const Ui::Menu::MenuCallback &addAction) {
const auto window = &controller()->window();
addAction(
tr::lng_theme_editor_menu_export(tr::now),
[=] {
TextUtilities::SetClipboardText({ base::options::serialize() });
window->showToast(
u"Experimental settings JSON copied to clipboard."_q);
},
&st::menuIconCopy);
if (!CanImportOptionsFromText(QGuiApplication::clipboard()->text())) {
return;
}
addAction(
tr::lng_theme_editor_menu_import(tr::now),
[=] {
const auto text = QGuiApplication::clipboard()->text();
if (!CanImportOptionsFromText(text)) {
window->showToast(u"Clipboard JSON is not valid."_q);
return;
}
if (!base::options::deserialize(text)) {
window->showToast(u"Clipboard JSON does not match "
"experimental settings format."_q);
return;
}
_reloadOptionsRequests.fire({});
window->showToast(u"Experimental settings imported "
"from clipboard."_q);
},
&st::menuIconImportTheme);
}
void Experimental::setupContent() {
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
SetupExperimental(&controller()->window(), content);
SetupExperimental(
&controller()->window(),
content,
_reloadOptionsRequests.events());
Ui::ResizeFitChild(this, content);
}