/* 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_experimental.h" #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" #include "ui/widgets/labels.h" #include "ui/vertical_list.h" #include "ui/gl/gl_detection.h" #include "ui/chat/chat_style_radius.h" #include "base/options.h" #include "boxes/moderate_messages_box.h" #include "core/application.h" #include "core/launcher.h" #include "core/sandbox.h" #include "chat_helpers/tabbed_panel.h" #include "dialogs/dialogs_widget.h" #include "history/history_item_components.h" #include "info/profile/info_profile_actions.h" #include "lang/lang_keys.h" #include "mainwindow.h" #include "mainwidget.h" #include "media/player/media_player_instance.h" #include "mtproto/session_private.h" #include "webview/webview_embed.h" #include "window/main_window.h" #include "window/window_peer_menu.h" #include "window/window_session_controller.h" #include "window/window_controller.h" #include "window/notifications_manager.h" #include "info/info_flexible_scroll.h" #include "chat_helpers/stickers_list_widget.h" #include "styles/style_settings.h" #include "styles/style_layers.h" #include "styles/style_menu_icons.h" #include #include namespace Settings { namespace { const auto kOptionsClipboardPrefix = u"tdesktop-flags:"_q; struct DecodeOptionsResult { bool ok = false; QString json; }; [[nodiscard]] QString EncodeOptionsToText(const QString &json) { const auto flags = QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals; return kOptionsClipboardPrefix + qs(qCompress(json.toLatin1(), 9).toBase64(flags)); } [[nodiscard]] DecodeOptionsResult DecodeOptionsFromText(const QString &text) { auto result = DecodeOptionsResult(); if (!text.startsWith(kOptionsClipboardPrefix)) { return result; } auto encoded = QStringView(text).mid( kOptionsClipboardPrefix.size()).toLatin1(); const auto compressed = QByteArray::fromBase64Encoding( std::move(encoded), QByteArray::Base64UrlEncoding | QByteArray::AbortOnBase64DecodingErrors); if (!compressed || (*compressed).isEmpty()) { return result; } const auto decoded = qUncompress(*compressed); if (decoded.isEmpty()) { return result; } auto error = QJsonParseError(); const auto parsed = QJsonDocument::fromJson(decoded, &error); if ((error.error != QJsonParseError::NoError) || !parsed.isObject()) { return result; } result.ok = true; result.json = QString::fromUtf8(decoded); return result; } void AddOption( not_null window, not_null container, base::options::option &option, 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>(); std::move( resetClicks ) | 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