From 9561026cd426ae3246bf8c7da023891ec7dff622 Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Fri, 27 Oct 2023 12:23:48 +0400
Subject: [PATCH] Add change color button with color sample.

---
 Telegram/CMakeLists.txt                       |   2 +
 Telegram/Resources/langs/lang.strings         |  33 ++-
 .../boxes/background_preview_box.cpp          |   2 +-
 .../boxes/peers/edit_peer_color_box.cpp       | 200 ++++++++++++++++++
 .../boxes/peers/edit_peer_color_box.h         |  29 +++
 .../boxes/peers/edit_peer_info_box.cpp        | 113 ++++------
 Telegram/SourceFiles/settings/settings.style  |   9 +
 .../SourceFiles/settings/settings_chat.cpp    |  74 +++----
 .../settings/settings_global_ttl.cpp          |   2 +-
 9 files changed, 355 insertions(+), 109 deletions(-)
 create mode 100644 Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp
 create mode 100644 Telegram/SourceFiles/boxes/peers/edit_peer_color_box.h

diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt
index 32aa477b4..95ac565a6 100644
--- a/Telegram/CMakeLists.txt
+++ b/Telegram/CMakeLists.txt
@@ -198,6 +198,8 @@ PRIVATE
     boxes/peers/edit_participant_box.h
     boxes/peers/edit_participants_box.cpp
     boxes/peers/edit_participants_box.h
+    boxes/peers/edit_peer_color_box.cpp
+    boxes/peers/edit_peer_color_box.h
     boxes/peers/edit_peer_common.h
     boxes/peers/edit_peer_info_box.cpp
     boxes/peers/edit_peer_info_box.h
diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings
index f9a075de2..6f530972c 100644
--- a/Telegram/Resources/langs/lang.strings
+++ b/Telegram/Resources/langs/lang.strings
@@ -402,6 +402,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 "lng_dlg_search_from" = "From: {user}";
 
 "lng_settings_save" = "Save";
+"lng_settings_apply" = "Apply";
 
 "lng_username_title" = "Username";
 "lng_username_description1" = "You can choose a username on Telegram. If you do, other people will be able to find you by this username and contact you without knowing your phone number.";
@@ -770,11 +771,30 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 "lng_clear_payment_info_clear" = "Clear";
 "lng_clear_payment_info_confirm" = "Delete your shipping info and instruct all payment providers to remove your saved credit cards? Note that Telegram never stores your credit card data.";
 
+"lng_settings_theme_settings" = "Theme settings";
+"lng_settings_theme_name_color" = "Your name color";
 "lng_settings_auto_night_mode" = "Auto-Night mode";
-"lng_settings_auto_night_enabled" = "Match the system settings";
+"lng_settings_auto_night_mode_off" = "Off";
+"lng_settings_auto_night_mode_on" = "System";
 "lng_settings_auto_night_warning" = "You have enabled auto-night mode. If you want to change the dark mode settings, you'll need to disable it first.";
 "lng_settings_auto_night_disable" = "Disable";
 
+"lng_settings_color_title" = "Color preview";
+"lng_settings_color_reply" = "Reply to your message";
+"lng_settings_color_reply_channel" = "Reply to your channel message";
+"lng_settings_color_text" = "Your name and replies to your messages will be shown in the selected color.";
+"lng_settings_color_text_channel" = "The name of the channel and replies to its messages will be shown in the selected color.";
+"lng_settings_color_link_name" = "Telegram";
+"lng_settings_color_link_title" = "Link Preview";
+"lng_settings_color_link_description" = "Your selected color will also tint the link preview.";
+"lng_settings_color_about" = "You can choose a color to tint your name, the links you send, and replies to your messages.";
+"lng_settings_color_about_channel" = "You can choose a color to tint your channel's name, the links it sends, and replies to its messages.";
+"lng_settings_color_emoji" = "Add icons to replies";
+"lng_settings_color_emoji_off" = "Off";
+"lng_settings_color_emoji_about" = "Make replies to your messages stand out by adding custom patterns to them.";
+"lng_settings_color_emoji_about_channel" = "Make replies to your channel's messages stand out by adding custom patterns to them.";
+"lng_settings_color_subscribe" = "Subscribe to {link} to choose a custom color for your name.";
+
 "lng_suggest_hide_new_title" = "Hide new chats?";
 "lng_suggest_hide_new_about" = "You are receiving lots of new chats from users who are not in your Contact List.\n\nDo you want to have such chats **automatically muted** and **archived**?";
 "lng_suggest_hide_new_to_settings" = "Go to Settings";
@@ -802,7 +822,6 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 "lng_background_text1" = "Ah, you kids today with techno music! You should enjoy the classics, like Hasselhoff!";
 "lng_background_text2" = "I can't even take you seriously right now.";
 "lng_background_bad_link" = "This background link appears to be invalid.";
-"lng_background_apply" = "Apply";
 "lng_background_share" = "Share";
 "lng_background_link_copied" = "Link copied to clipboard";
 "lng_background_blur" = "Blurred";
@@ -2035,6 +2054,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 "lng_boost_now_instead" = "You currently boost {channel}. Do you want to boost {other} instead?";
 "lng_boost_now_replace" = "Replace";
 
+"lng_boost_channel_title_color" = "Enable colors";
+"lng_boost_channel_needs_level_color#one" = "Your channel needs to reach **Level {count}** to change channel color.";
+"lng_boost_channel_needs_level_color#other" = "Your channel needs to reach **Level {count}** to change channel color.";
+"lng_boost_channel_ask" = "Ask your **Premium** subscribers to boost your channel with this link:";
+"lng_boost_channel_ask_button" = "Copy Link";
+"lng_boost_channel_or" = "or";
+"lng_boost_channel_gifting" = "Boost your channel by gifting your subscribers Telegram Premium. {link}";
+"lng_boost_channel_gifting_link" = "Get boosts >";
+
 "lng_giveaway_new_title" = "Boosts via Gifts";
 "lng_giveaway_new_about" = "Get more boosts for your channel by gifting Premium to your subscribers.";
 "lng_giveaway_create_option" = "Create Giveaway";
@@ -2675,6 +2703,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 "lng_edit_bot_title" = "Edit bot";
 "lng_edit_sign_messages" = "Sign messages";
 "lng_edit_group" = "Edit group";
+"lng_edit_channel_color" = "Change name color";
 "lng_edit_self_title" = "Edit your name";
 "lng_confirm_contact_data" = "New Contact";
 "lng_add_contact" = "Create";
diff --git a/Telegram/SourceFiles/boxes/background_preview_box.cpp b/Telegram/SourceFiles/boxes/background_preview_box.cpp
index 072dc34fb..a920aa76a 100644
--- a/Telegram/SourceFiles/boxes/background_preview_box.cpp
+++ b/Telegram/SourceFiles/boxes/background_preview_box.cpp
@@ -435,7 +435,7 @@ void BackgroundPreviewBox::rebuildButtons(bool dark) {
 	clearButtons();
 	addButton(_forPeer
 		? tr::lng_background_apply_button()
-		: tr::lng_background_apply(), [=] { apply(); });
+		: tr::lng_settings_apply(), [=] { apply(); });
 	addButton(tr::lng_cancel(), [=] { closeBox(); });
 	if (!_forPeer && _paper.hasShareUrl()) {
 		addLeftButton(tr::lng_background_share(), [=] { share(); });
diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp
new file mode 100644
index 000000000..f15ae47cb
--- /dev/null
+++ b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.cpp
@@ -0,0 +1,200 @@
+/*
+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 "boxes/peers/edit_peer_color_box.h"
+
+#include "data/data_changes.h"
+#include "data/data_peer.h"
+#include "lang/lang_keys.h"
+#include "main/main_session.h"
+#include "settings/settings_common.h"
+#include "ui/chat/chat_style.h"
+#include "ui/widgets/buttons.h"
+#include "ui/painter.h"
+#include "styles/style_menu_icons.h"
+#include "styles/style_settings.h"
+#include "styles/style_widgets.h"
+
+namespace {
+
+using namespace Settings;
+
+class ColorSample final : public Ui::RpWidget {
+public:
+	ColorSample(
+		not_null<QWidget*> parent,
+		std::shared_ptr<Ui::ChatStyle> st,
+		rpl::producer<uint8> colorIndex,
+		const QString &name);
+
+	int naturalWidth() const override;
+
+private:
+	void paintEvent(QPaintEvent *e) override;
+
+	std::shared_ptr<Ui::ChatStyle> _st;
+	Ui::Text::String _name;
+	uint8 _index = 0;
+
+};
+
+ColorSample::ColorSample(
+	not_null<QWidget*> parent,
+	std::shared_ptr<Ui::ChatStyle> st,
+	rpl::producer<uint8> colorIndex,
+	const QString &name)
+: RpWidget(parent)
+, _st(st)
+, _name(st::semiboldTextStyle, name) {
+	std::move(
+		colorIndex
+	) | rpl::start_with_next([=](uint8 index) {
+		_index = index;
+		update();
+	}, lifetime());
+}
+
+void ColorSample::paintEvent(QPaintEvent *e) {
+	auto p = Painter(this);
+	auto hq = PainterHighQualityEnabler(p);
+	const auto colors = _st->coloredValues(false, _index);
+	if (!colors.outlines[1].alpha()) {
+		const auto radius = height() / 2;
+		p.setPen(Qt::NoPen);
+		p.setBrush(colors.bg);
+		p.drawRoundedRect(rect(), radius, radius);
+
+		const auto padding = st::settingsColorSamplePadding;
+		p.setPen(colors.name);
+		p.setBrush(Qt::NoBrush);
+		p.setFont(st::semiboldFont);
+		_name.drawLeftElided(
+			p,
+			padding.left(),
+			padding.top(),
+			width() - padding.left() - padding.right(),
+			width(),
+			1,
+			style::al_top);
+	} else {
+		const auto size = width();
+		const auto half = size / 2.;
+		p.translate(size / 2., size / 2.);
+		p.rotate(-45.);
+		p.setPen(Qt::NoPen);
+		p.setClipRect(-size, -size, 3 * size, size);
+		p.setBrush(colors.outlines[0]);
+		p.drawEllipse(-half, -half, size, size);
+		p.setClipRect(-size, 0, 3 * size, size);
+		p.setBrush(colors.outlines[1]);
+		p.drawEllipse(-half, -half, size, size);
+		if (colors.outlines[2].alpha()) {
+			const auto center = st::settingsColorSampleCenter;
+			const auto radius = st::settingsColorSampleCenterRadius;
+			p.setClipping(false);
+			p.setBrush(colors.outlines[2]);
+			p.drawRoundedRect(
+				QRectF(-center / 2., -center / 2., center, center),
+				radius,
+				radius);
+		}
+	}
+}
+
+int ColorSample::naturalWidth() const {
+	if (_st->colorPatternIndex(_index)) {
+		return st::settingsColorSampleSize;
+	}
+	const auto padding = st::settingsColorSamplePadding;
+	return std::max(
+		padding.left() + _name.maxWidth() + padding.right(),
+		padding.top() + st::semiboldFont->height + padding.bottom());
+}
+
+} // namespace
+
+void EditPeerColorBox(
+	not_null<Ui::GenericBox*> box,
+	std::shared_ptr<ChatHelpers::Show> show,
+	not_null<PeerData*> peer,
+	std::shared_ptr<Ui::ChatStyle> st) {
+
+}
+
+void AddPeerColorButton(
+		not_null<Ui::VerticalLayout*> container,
+		std::shared_ptr<ChatHelpers::Show> show,
+		not_null<PeerData*> peer) {
+	const auto button = AddButton(
+		container,
+		(peer->isSelf()
+			? tr::lng_settings_theme_name_color()
+			: tr::lng_edit_channel_color()),
+		st::settingsColorButton,
+		{ &st::menuIconChangeColors });
+
+	auto colorIndexValue = peer->session().changes().peerFlagsValue(
+		peer,
+		Data::PeerUpdate::Flag::Color
+	) | rpl::map([=] {
+		return peer->colorIndex();
+	});
+	const auto name = peer->shortName();
+	const auto st = std::make_shared<Ui::ChatStyle>(
+		peer->session().colorIndicesValue());
+	const auto sample = Ui::CreateChild<ColorSample>(
+		button.get(),
+		st,
+		rpl::duplicate(colorIndexValue),
+		name);
+	sample->show();
+
+	rpl::combine(
+		button->widthValue(),
+		tr::lng_settings_theme_name_color(),
+		rpl::duplicate(colorIndexValue)
+	) | rpl::start_with_next([=](
+			int width,
+			const QString &button,
+			int colorIndex) {
+		const auto sampleSize = st::settingsColorSampleSize;
+		const auto available = width
+			- st::settingsButton.padding.left()
+			- (st::settingsColorButton.padding.right() - sampleSize)
+			- st::settingsButton.style.font->width(button)
+			- st::settingsButtonRightSkip;
+		if (st->colorPatternIndex(colorIndex)) {
+			sample->resize(sampleSize, sampleSize);
+		} else {
+			const auto padding = st::settingsColorSamplePadding;
+			const auto wantedHeight = padding.top()
+				+ st::semiboldFont->height
+				+ padding.bottom();
+			const auto wantedWidth = sample->naturalWidth();
+			sample->resize(std::min(wantedWidth, available), wantedHeight);
+		}
+		sample->update();
+	}, sample->lifetime());
+
+	rpl::combine(
+		button->sizeValue(),
+		sample->sizeValue(),
+		std::move(colorIndexValue)
+	) | rpl::start_with_next([=](QSize outer, QSize inner, int colorIndex) {
+		const auto right = st::settingsColorButton.padding.right()
+			- st::settingsColorSampleSkip
+			- st::settingsColorSampleSize
+			- (st->colorPatternIndex(colorIndex)
+				? 0
+				: st::settingsColorSamplePadding.right());
+		sample->move(
+			outer.width() - right - inner.width(),
+			(outer.height() - inner.height()) / 2);
+	}, sample->lifetime());
+
+	sample->setAttribute(Qt::WA_TransparentForMouseEvents);
+}
diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.h b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.h
new file mode 100644
index 000000000..b69e9e04f
--- /dev/null
+++ b/Telegram/SourceFiles/boxes/peers/edit_peer_color_box.h
@@ -0,0 +1,29 @@
+/*
+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
+
+namespace ChatHelpers {
+class Show;
+} // namespace ChatHelpers
+
+namespace Ui {
+class GenericBox;
+class ChatStyle;
+class VerticalLayout;
+} // namespace Ui
+
+void EditPeerColorBox(
+	not_null<Ui::GenericBox*> box,
+	std::shared_ptr<ChatHelpers::Show> show,
+	not_null<PeerData*> peer,
+	std::shared_ptr<Ui::ChatStyle> st = nullptr);
+
+void AddPeerColorButton(
+	not_null<Ui::VerticalLayout*> container,
+	std::shared_ptr<ChatHelpers::Show> show,
+	not_null<PeerData*> peer);
diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp
index 3e95dcc1f..0012d8a0f 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp
@@ -13,8 +13,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "main/main_session.h"
 #include "boxes/add_contact_box.h"
 #include "ui/boxes/confirm_box.h"
-#include "boxes/peer_list_controllers.h"
 #include "boxes/peers/edit_participants_box.h"
+#include "boxes/peers/edit_peer_color_box.h"
 #include "boxes/peers/edit_peer_common.h"
 #include "boxes/peers/edit_peer_type_box.h"
 #include "boxes/peers/edit_peer_history_visibility_box.h"
@@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "boxes/peers/edit_linked_chat_box.h"
 #include "boxes/peers/edit_peer_requests_box.h"
 #include "boxes/peers/edit_peer_reactions.h"
+#include "boxes/peer_list_controllers.h"
 #include "boxes/stickers_box.h"
 #include "boxes/username_box.h"
 #include "ui/boxes/single_choice_box.h"
@@ -302,6 +303,7 @@ private:
 	void fillLinkedChatButton();
 	//void fillInviteLinkButton();
 	void fillForumButton();
+	void fillColorIndexButton();
 	void fillSignaturesButton();
 	void fillHistoryVisibilityButton();
 	void fillManageSection();
@@ -905,6 +907,13 @@ void Controller::refreshForumToggleLocked() {
 	_controls.forumToggle->setToggleLocked(locked);
 }
 
+void Controller::fillColorIndexButton() {
+	Expects(_controls.buttonsLayout != nullptr);
+
+	const auto show = _navigation->uiShow();
+	AddPeerColorButton(_controls.buttonsLayout, show, _peer);
+}
+
 void Controller::fillSignaturesButton() {
 	Expects(_controls.buttonsLayout != nullptr);
 
@@ -1024,74 +1033,42 @@ void Controller::fillManageSection() {
 		return;
 	}
 
-	const auto canEditType = [&] {
-		return isChannel
-			? channel->amCreator()
-			: chat->amCreator();
-	}();
-	const auto canEditSignatures = [&] {
-		return isChannel
-			? (channel->canEditSignatures() && !channel->isMegagroup())
-			: false;
-	}();
-	const auto canEditPreHistoryHidden = [&] {
-		return isChannel
-			? channel->canEditPreHistoryHidden()
-			: chat->canEditPreHistoryHidden();
-	}();
+	const auto canEditType = isChannel
+		? channel->amCreator()
+		: chat->amCreator();
+	const auto canEditSignatures = isChannel
+		&& channel->canEditSignatures()
+		&& !channel->isMegagroup();
+	const auto canEditPreHistoryHidden = isChannel
+		? channel->canEditPreHistoryHidden()
+		: chat->canEditPreHistoryHidden();
 	const auto canEditForum = isChannel
 		? (channel->isMegagroup() && channel->amCreator())
 		: chat->amCreator();
-
-	const auto canEditPermissions = [&] {
-		return isChannel
-			? channel->canEditPermissions()
-			: chat->canEditPermissions();
-	}();
-	const auto canEditInviteLinks = [&] {
-		return isChannel
-			? channel->canHaveInviteLink()
-			: chat->canHaveInviteLink();
-	}();
-	const auto canViewAdmins = [&] {
-		return isChannel
-			? channel->canViewAdmins()
-			: chat->amIn();
-	}();
-	const auto canViewMembers = [&] {
-		return isChannel
-			? channel->canViewMembers()
-			: chat->amIn();
-	}();
-	const auto canViewKicked = [&] {
-		return isChannel
-			? (channel->isBroadcast() || channel->isGigagroup())
-			: false;
-	}();
-	const auto hasRecentActions = [&] {
-		return isChannel
-			? (channel->hasAdminRights() || channel->amCreator())
-			: false;
-	}();
-
-	const auto canEditStickers = [&] {
-		return isChannel
-			? channel->canEditStickers()
-			: false;
-	}();
-	const auto canDeleteChannel = [&] {
-		return isChannel
-			? channel->canDelete()
-			: false;
-	}();
-
-	const auto canViewOrEditLinkedChat = [&] {
-		return !isChannel
-			? false
-			: channel->linkedChat()
-			? true
-			: (channel->isBroadcast() && channel->canEditInformation());
-	}();
+	const auto canEditPermissions = isChannel
+		? channel->canEditPermissions()
+		: chat->canEditPermissions();
+	const auto canEditInviteLinks = isChannel
+		? channel->canHaveInviteLink()
+		: chat->canHaveInviteLink();
+	const auto canViewAdmins = isChannel
+		? channel->canViewAdmins()
+		: chat->amIn();
+	const auto canViewMembers = isChannel
+		? channel->canViewMembers()
+		: chat->amIn();
+	const auto canViewKicked = isChannel
+		&& (channel->isBroadcast() || channel->isGigagroup());
+	const auto hasRecentActions = isChannel
+		&& (channel->hasAdminRights() || channel->amCreator());
+	const auto canEditStickers = isChannel && channel->canEditStickers();
+	const auto canDeleteChannel = isChannel && channel->canDelete();
+	const auto canEditColorIndex = isChannel
+		&& !channel->isMegagroup()
+		&& channel->canEditInformation();
+	const auto canViewOrEditLinkedChat = isChannel
+		&& (channel->linkedChat()
+			|| (channel->isBroadcast() && channel->canEditInformation()));
 
 	AddSkip(_controls.buttonsLayout, 0);
 
@@ -1109,11 +1086,15 @@ void Controller::fillManageSection() {
 	if (canEditForum) {
 		fillForumButton();
 	}
+	if (canEditColorIndex) {
+		fillColorIndexButton();
+	}
 	if (canEditSignatures) {
 		fillSignaturesButton();
 	}
 	if (canEditPreHistoryHidden
 		|| canEditForum
+		|| canEditColorIndex
 		|| canEditSignatures
 		//|| canEditInviteLinks
 		|| canViewOrEditLinkedChat
diff --git a/Telegram/SourceFiles/settings/settings.style b/Telegram/SourceFiles/settings/settings.style
index 3ea1b81dd..368973e21 100644
--- a/Telegram/SourceFiles/settings/settings.style
+++ b/Telegram/SourceFiles/settings/settings.style
@@ -565,3 +565,12 @@ filterLinkSubsectionTitlePadding: margins(0px, 5px, 0px, -4px);
 filterLinkChatsList: PeerList(peerListBox) {
 	padding: margins(0px, 0px, 0px, membersMarginBottom);
 }
+
+settingsColorSampleSize: 20px;
+settingsColorSampleCenter: 8px;
+settingsColorSampleCenterRadius: 2px;
+settingsColorSamplePadding: margins(8px, 2px, 8px, 2px);
+settingsColorSampleSkip: 6px;
+settingsColorButton: SettingsButton(settingsButton) {
+	padding: margins(60px, 10px, 48px, 10px);
+}
\ No newline at end of file
diff --git a/Telegram/SourceFiles/settings/settings_chat.cpp b/Telegram/SourceFiles/settings/settings_chat.cpp
index 01b6437f3..508627901 100644
--- a/Telegram/SourceFiles/settings/settings_chat.cpp
+++ b/Telegram/SourceFiles/settings/settings_chat.cpp
@@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "settings/settings_common.h"
 #include "settings/settings_advanced.h"
 #include "settings/settings_experimental.h"
+#include "boxes/peers/edit_peer_color_box.h"
 #include "boxes/connection_box.h"
 #include "boxes/auto_download_box.h"
 #include "boxes/reactions_settings_box.h"
@@ -27,6 +28,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "ui/widgets/buttons.h"
 #include "ui/widgets/labels.h"
 #include "ui/chat/attach/attach_extensions.h"
+#include "ui/chat/chat_style.h"
 #include "ui/chat/chat_theme.h"
 #include "ui/layers/generic_box.h"
 #include "ui/effects/radial_animation.h"
@@ -55,6 +57,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "data/data_file_origin.h"
 #include "data/data_message_reactions.h"
 #include "data/data_peer_values.h"
+#include "data/data_user.h"
 #include "chat_helpers/emoji_sets_manager.h"
 #include "base/platform/base_platform_info.h"
 #include "platform/platform_specific.h"
@@ -1561,51 +1564,44 @@ void SetupCloudThemes(
 	wrap->setDuration(0)->toggleOn(list->empty() | rpl::map(!_1));
 }
 
-void SetupAutoNightMode(
+void SetupThemeSettings(
 		not_null<Window::SessionController*> controller,
 		not_null<Ui::VerticalLayout*> container) {
-	if (!Core::App().settings().systemDarkMode().has_value()) {
-		return;
-	}
-
 	AddDivider(container);
 	AddSkip(container, st::settingsPrivacySkip);
 
-	AddSubsectionTitle(container, tr::lng_settings_auto_night_mode());
+	AddSubsectionTitle(container, tr::lng_settings_theme_settings());
 
-	auto wrap = object_ptr<Ui::VerticalLayout>(container);
-	const auto autoNight = wrap->add(
-		object_ptr<Ui::Checkbox>(
-			wrap,
-			tr::lng_settings_auto_night_enabled(tr::now),
-			Core::App().settings().systemDarkModeEnabled(),
-			st::settingsCheckbox),
-		st::settingsCheckboxPadding);
-
-	autoNight->checkedChanges(
-	) | rpl::filter([=](bool checked) {
-		return (checked != Core::App().settings().systemDarkModeEnabled());
-	}) | rpl::start_with_next([=](bool checked) {
-		if (checked && Window::Theme::Background()->editingTheme()) {
-			autoNight->setChecked(false);
-			controller->show(Ui::MakeInformBox(
-				tr::lng_theme_editor_cant_change_theme()));
-		} else {
-			Core::App().settings().setSystemDarkModeEnabled(checked);
-			Core::App().saveSettingsDelayed();
-		}
-	}, autoNight->lifetime());
-
-	Core::App().settings().systemDarkModeEnabledChanges(
-	) | rpl::filter([=](bool value) {
-		return (value != autoNight->checked());
-	}) | rpl::start_with_next([=](bool value) {
-		autoNight->setChecked(value);
-	}, autoNight->lifetime());
-
-	container->add(object_ptr<Ui::OverrideMargins>(
+	AddPeerColorButton(
 		container,
-		std::move(wrap)));
+		controller->uiShow(),
+		controller->session().user());
+
+	const auto settings = &Core::App().settings();
+	if (settings->systemDarkMode().has_value()) {
+		auto label = settings->systemDarkModeEnabledValue(
+		) | rpl::map([=](bool enabled) {
+			return enabled
+				? tr::lng_settings_auto_night_mode_on()
+				: tr::lng_settings_auto_night_mode_off();
+		}) | rpl::flatten_latest();
+		AddButtonWithLabel(
+			container,
+			tr::lng_settings_auto_night_mode(),
+			std::move(label),
+			st::settingsButton,
+			{ &st::menuIconNightMode }
+		)->setClickedCallback([=] {
+			const auto now = !settings->systemDarkModeEnabled();
+			if (now && Window::Theme::Background()->editingTheme()) {
+				controller->show(Ui::MakeInformBox(
+					tr::lng_theme_editor_cant_change_theme()));
+			} else {
+				settings->setSystemDarkModeEnabled(now);
+				Core::App().saveSettingsDelayed();
+			}
+		});
+	}
 
 	AddSkip(container, st::settingsCheckboxesSkip);
 }
@@ -1749,7 +1745,7 @@ void Chat::setupContent(not_null<Window::SessionController*> controller) {
 	const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
 
 	SetupThemeOptions(controller, content);
-	SetupAutoNightMode(controller, content);
+	SetupThemeSettings(controller, content);
 	SetupCloudThemes(controller, content);
 	SetupChatBackground(controller, content);
 	SetupStickersEmoji(controller, content);
diff --git a/Telegram/SourceFiles/settings/settings_global_ttl.cpp b/Telegram/SourceFiles/settings/settings_global_ttl.cpp
index cba6a2c00..4c991fb22 100644
--- a/Telegram/SourceFiles/settings/settings_global_ttl.cpp
+++ b/Telegram/SourceFiles/settings/settings_global_ttl.cpp
@@ -377,7 +377,7 @@ void GlobalTTL::setupContent() {
 		auto controller = std::make_unique<TTLChatsBoxController>(session);
 		auto initBox = [=, controller = controller.get()](
 				not_null<PeerListBox*> box) {
-			box->addButton(tr::lng_background_apply(), crl::guard(this, [=] {
+			box->addButton(tr::lng_settings_apply(), crl::guard(this, [=] {
 				const auto &peers = box->collectSelectedRows();
 				if (peers.empty()) {
 					return;