diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings
index 130d096c1..153ff4040 100644
--- a/Telegram/Resources/langs/lang.strings
+++ b/Telegram/Resources/langs/lang.strings
@@ -324,7 +324,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 "lng_settings_bg_use_default" = "Use default color theme";
 "lng_settings_bg_from_gallery" = "Choose from gallery";
 "lng_settings_bg_from_file" = "Choose from file";
-"lng_settings_bg_edit_theme" = "Edit theme";
+"lng_settings_bg_edit_theme" = "Launch theme editor";
 "lng_settings_bg_tile" = "Tile background";
 "lng_settings_adaptive_wide" = "Adaptive layout for wide screens";
 
@@ -334,6 +334,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 "lng_settings_local_storage" = "Local storage";
 "lng_settings_connection_type" = "Connection type";
 "lng_settings_downloading_update" = "Downloading update {progress}...";
+"lng_settings_use_night_mode" = "Use night mode";
 
 "lng_backgrounds_header" = "Choose your new chat background";
 "lng_theme_sure_keep" = "Keep this theme?";
diff --git a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp
index 2d756f898..9962d5bbf 100644
--- a/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp
+++ b/Telegram/SourceFiles/boxes/peers/edit_peer_info_box.cpp
@@ -1440,7 +1440,7 @@ void EditPeerInfoBox::prepare() {
 	) | rpl::start_with_next([this](int height) {
 		setDimensions(st::boxWideWidth, height);
 	}, content->lifetime());
-	setInnerWidget(object_ptr<Ui::IgnoreMargins>(
+	setInnerWidget(object_ptr<Ui::OverrideMargins>(
 		this,
 		std::move(content)));
 	Ui::AttachAsChild(this, std::move(controller));
diff --git a/Telegram/SourceFiles/export/view/export_view_settings.cpp b/Telegram/SourceFiles/export/view/export_view_settings.cpp
index 8cc6aa7aa..7a3c8da68 100644
--- a/Telegram/SourceFiles/export/view/export_view_settings.cpp
+++ b/Telegram/SourceFiles/export/view/export_view_settings.cpp
@@ -93,9 +93,10 @@ void SettingsWidget::setupContent() {
 	const auto scroll = Ui::CreateChild<Ui::ScrollArea>(
 		this,
 		st::boxLayerScroll);
-	const auto wrap = scroll->setOwnedWidget(object_ptr<Ui::IgnoreMargins>(
-		scroll,
-		object_ptr<Ui::VerticalLayout>(scroll)));
+	const auto wrap = scroll->setOwnedWidget(
+		object_ptr<Ui::OverrideMargins>(
+			scroll,
+			object_ptr<Ui::VerticalLayout>(scroll)));
 	const auto content = static_cast<Ui::VerticalLayout*>(wrap->entity());
 
 	const auto buttons = setupButtons(scroll, wrap);
diff --git a/Telegram/SourceFiles/settings/settings.style b/Telegram/SourceFiles/settings/settings.style
index 2f51ec746..4a27468c3 100644
--- a/Telegram/SourceFiles/settings/settings.style
+++ b/Telegram/SourceFiles/settings/settings.style
@@ -16,6 +16,9 @@ settingsSectionButton: InfoProfileButton(infoProfileButton) {
 settingsButton: InfoProfileButton(settingsSectionButton) {
 	padding: margins(28px, 10px, 8px, 8px);
 }
+settingsChatButton: InfoProfileButton(settingsSectionButton) {
+	padding: margins(22px, 10px, 8px, 8px);
+}
 settingsSectionSkip: infoProfileSkip;
 settingsButtonRightPosition: point(28px, 10px);
 settingsButtonRight: FlatLabel(defaultFlatLabel) {
@@ -37,7 +40,30 @@ settingsUpdate: InfoProfileButton(infoMainButton, settingsButton) {
 }
 settingsUpdateStatePosition: point(28px, 30px);
 
-settingsNotificationsCheckbox: defaultBoxCheckbox;
-settingsNotificationsCheckboxPadding: margins(22px, 10px, 10px, 10px);
+settingsSendType: defaultBoxCheckbox;
+settingsSendTypePadding: margins(22px, 5px, 10px, 5px);
+settingsSendTypeSkip: 5px;
+
+settingsCheckbox: defaultBoxCheckbox;
+settingsCheckboxPadding: margins(22px, 10px, 10px, 10px);
 settingsLink: boxLinkButton;
 settingsAdvancedNotificationsPadding: margins(22px, 20px, 10px, 10px);
+settingsLinkLabel: defaultFlatLabel;
+
+settingsAskPathPadding: margins(22px, 10px, 10px, 0px);
+settingsDownloadPathPadding: margins(22px, 1px, 10px, 0px);
+
+settingsBackgroundThumb: 76px;
+settingsThumbSkip: 16px;
+settingsBackgroundTitle: FlatLabel(defaultFlatLabel) {
+	style: TextStyle(semiboldTextStyle) {
+		font: font(boxFontSize semibold);
+		linkFont: font(boxFontSize semibold);
+		linkFontOver: font(boxFontSize semibold underline);
+	}
+	textFg: windowActiveTextFg;
+}
+settingsBackgroundTitlePadding: margins(22px, 7px, 10px, 9px);
+settingsBackgroundPadding: margins(22px, 8px, 10px, 8px);
+settingsFromGalleryTop: 2px;
+settingsFromFileTop: 14px;
diff --git a/Telegram/SourceFiles/settings/settings_chat.cpp b/Telegram/SourceFiles/settings/settings_chat.cpp
index 8eddbff24..e98bf379f 100644
--- a/Telegram/SourceFiles/settings/settings_chat.cpp
+++ b/Telegram/SourceFiles/settings/settings_chat.cpp
@@ -8,12 +8,686 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "settings/settings_chat.h"
 
 #include "settings/settings_common.h"
-#include "boxes/abstract_box.h"
+#include "boxes/connection_box.h"
+#include "boxes/stickers_box.h"
+#include "boxes/background_box.h"
+#include "boxes/download_path_box.h"
 #include "ui/wrap/vertical_layout.h"
+#include "ui/wrap/slide_wrap.h"
+#include "ui/widgets/checkbox.h"
+#include "ui/widgets/labels.h"
+#include "ui/effects/radial_animation.h"
 #include "lang/lang_keys.h"
+#include "window/themes/window_theme_editor.h"
+#include "window/themes/window_theme.h"
+#include "info/profile/info_profile_button.h"
+#include "storage/localstorage.h"
+#include "core/file_utilities.h"
+#include "mainwidget.h"
 #include "styles/style_settings.h"
 
 namespace Settings {
+namespace {
+
+class BackgroundRow : public Ui::RpWidget {
+public:
+	BackgroundRow(QWidget *parent);
+
+protected:
+	void paintEvent(QPaintEvent *e) override;
+
+	int resizeGetHeight(int newWidth) override;
+
+private:
+	void updateImage();
+
+	float64 radialProgress() const;
+	bool radialLoading() const;
+	QRect radialRect() const;
+	void radialStart();
+	TimeMs radialTimeShift() const;
+	void step_radial(TimeMs ms, bool timer);
+
+	QPixmap _background;
+	object_ptr<Ui::LinkButton> _chooseFromGallery;
+	object_ptr<Ui::LinkButton> _chooseFromFile;
+
+	Ui::RadialAnimation _radial;
+
+};
+
+#ifndef OS_WIN_STORE
+class DownloadPathRow : public Ui::RpWidget {
+public:
+	DownloadPathRow(QWidget *parent);
+
+private:
+	void setupControls();
+
+};
+#endif // OS_WIN_STORE
+
+void ChooseFromFile(not_null<QWidget*> parent);
+
+BackgroundRow::BackgroundRow(QWidget *parent) : RpWidget(parent)
+, _chooseFromGallery(
+	this,
+	lang(lng_settings_bg_from_gallery),
+	st::settingsLink)
+, _chooseFromFile(this, lang(lng_settings_bg_from_file), st::settingsLink)
+, _radial(animation(this, &BackgroundRow::step_radial)) {
+	updateImage();
+
+	_chooseFromGallery->addClickHandler([] {
+		Ui::show(Box<BackgroundBox>());
+	});
+	_chooseFromFile->addClickHandler([=] {
+		ChooseFromFile(this);
+	});
+
+	using Update = const Window::Theme::BackgroundUpdate;
+	base::ObservableViewer(
+		*Window::Theme::Background()
+	) | rpl::filter([](const Update &update) {
+		return (update.type == Update::Type::New
+			|| update.type == Update::Type::Start
+			|| update.type == Update::Type::Changed);
+	}) | rpl::start_with_next([=] {
+		updateImage();
+	}, lifetime());
+}
+
+void BackgroundRow::paintEvent(QPaintEvent *e) {
+	Painter p(this);
+
+	bool radial = false;
+	float64 radialOpacity = 0;
+	if (_radial.animating()) {
+		_radial.step(getms());
+		radial = _radial.animating();
+		radialOpacity = _radial.opacity();
+	}
+	if (radial) {
+		const auto backThumb = App::main()->newBackgroundThumb();
+		if (backThumb->isNull()) {
+			p.drawPixmap(0, 0, _background);
+		} else {
+			const auto &pix = backThumb->pixBlurred(
+				Data::FileOrigin(),
+				st::settingsBackgroundThumb);
+			const auto factor = cIntRetinaFactor();
+			p.drawPixmap(
+				0,
+				0,
+				st::settingsBackgroundThumb,
+				st::settingsBackgroundThumb,
+				pix,
+				0,
+				(pix.height() - st::settingsBackgroundThumb * factor) / 2,
+				st::settingsBackgroundThumb * factor,
+				st::settingsBackgroundThumb * factor);
+		}
+
+		const auto outer = radialRect();
+		const auto inner = QRect(
+			QPoint(
+				outer.x() + (outer.width() - st::radialSize.width()) / 2,
+				outer.y() + (outer.height() - st::radialSize.height()) / 2),
+			st::radialSize);
+		p.setPen(Qt::NoPen);
+		p.setOpacity(radialOpacity);
+		p.setBrush(st::radialBg);
+
+		{
+			PainterHighQualityEnabler hq(p);
+			p.drawEllipse(inner);
+		}
+
+		p.setOpacity(1);
+		const auto arc = inner.marginsRemoved(QMargins(
+			st::radialLine,
+			st::radialLine,
+			st::radialLine,
+			st::radialLine));
+		_radial.draw(p, arc, st::radialLine, st::radialFg);
+	} else {
+		p.drawPixmap(0, 0, _background);
+	}
+}
+
+int BackgroundRow::resizeGetHeight(int newWidth) {
+	auto linkTop = st::settingsFromGalleryTop;
+	auto linkLeft = st::settingsBackgroundThumb + st::settingsThumbSkip;
+	auto linkWidth = newWidth - linkLeft;
+	_chooseFromGallery->resizeToWidth(
+		qMin(linkWidth, _chooseFromGallery->naturalWidth()));
+	_chooseFromFile->resizeToWidth(
+		qMin(linkWidth, _chooseFromFile->naturalWidth()));
+	_chooseFromGallery->moveToLeft(linkLeft, linkTop, newWidth);
+	linkTop += _chooseFromGallery->height() + st::settingsFromFileTop;
+	_chooseFromFile->moveToLeft(linkLeft, linkTop, newWidth);
+	return st::settingsBackgroundThumb;
+}
+
+float64 BackgroundRow::radialProgress() const {
+	return App::main()->chatBackgroundProgress();
+}
+
+bool BackgroundRow::radialLoading() const {
+	const auto main = App::main();
+	if (main->chatBackgroundLoading()) {
+		main->checkChatBackground();
+		if (main->chatBackgroundLoading()) {
+			return true;
+		} else {
+			const_cast<BackgroundRow*>(this)->updateImage();
+		}
+	}
+	return false;
+}
+
+QRect BackgroundRow::radialRect() const {
+	return QRect(
+		0,
+		0,
+		st::settingsBackgroundThumb,
+		st::settingsBackgroundThumb);
+}
+
+void BackgroundRow::radialStart() {
+	if (radialLoading() && !_radial.animating()) {
+		_radial.start(radialProgress());
+		if (const auto shift = radialTimeShift()) {
+			_radial.update(
+				radialProgress(),
+				!radialLoading(),
+				getms() + shift);
+		}
+	}
+}
+
+TimeMs BackgroundRow::radialTimeShift() const {
+	return st::radialDuration;
+}
+
+void BackgroundRow::step_radial(TimeMs ms, bool timer) {
+	_radial.update(
+		radialProgress(),
+		!radialLoading(),
+		ms + radialTimeShift());
+	if (timer && _radial.animating()) {
+		rtlupdate(radialRect());
+	}
+}
+
+void BackgroundRow::updateImage() {
+	int32 size = st::settingsBackgroundThumb * cIntRetinaFactor();
+	QImage back(size, size, QImage::Format_ARGB32_Premultiplied);
+	back.setDevicePixelRatio(cRetinaFactor());
+	{
+		Painter p(&back);
+		PainterHighQualityEnabler hq(p);
+
+		const auto &pix = Window::Theme::Background()->pixmap();
+		const auto sx = (pix.width() > pix.height())
+			? ((pix.width() - pix.height()) / 2)
+			: 0;
+		const auto sy = (pix.height() > pix.width())
+			? ((pix.height() - pix.width()) / 2)
+			: 0;
+		const auto s = (pix.width() > pix.height())
+			? pix.height()
+			: pix.width();
+		p.drawPixmap(
+			0,
+			0,
+			st::settingsBackgroundThumb,
+			st::settingsBackgroundThumb,
+			pix,
+			sx,
+			sy,
+			s,
+			s);
+	}
+	Images::prepareRound(back, ImageRoundRadius::Small);
+	_background = App::pixmapFromImageInPlace(std::move(back));
+	_background.setDevicePixelRatio(cRetinaFactor());
+
+	rtlupdate(radialRect());
+
+	if (radialLoading()) {
+		radialStart();
+	}
+}
+
+void ChooseFromFile(not_null<QWidget*> parent) {
+	const auto imgExtensions = cImgExtensions();
+	auto filters = QStringList(
+		qsl("Theme files (*.tdesktop-theme *.tdesktop-palette *")
+		+ imgExtensions.join(qsl(" *"))
+		+ qsl(")"));
+	filters.push_back(FileDialog::AllFilesFilter());
+	const auto callback = [=](const FileDialog::OpenResult &result) {
+		if (result.paths.isEmpty() && result.remoteContent.isEmpty()) {
+			return;
+		}
+
+		if (!result.paths.isEmpty()) {
+			const auto filePath = result.paths.front();
+			const auto hasExtension = [&](QLatin1String extension) {
+				return filePath.endsWith(extension, Qt::CaseInsensitive);
+			};
+			if (hasExtension(qstr(".tdesktop-theme"))
+				|| hasExtension(qstr(".tdesktop-palette"))) {
+				Window::Theme::Apply(filePath);
+				return;
+			}
+		}
+
+		auto image = result.remoteContent.isEmpty()
+			? App::readImage(result.paths.front())
+			: App::readImage(result.remoteContent);
+		if (image.isNull() || image.width() <= 0 || image.height() <= 0) {
+			return;
+		} else if (image.width() > 4096 * image.height()) {
+			image = image.copy(
+				(image.width() - 4096 * image.height()) / 2,
+				0,
+				4096 * image.height(),
+				image.height());
+		} else if (image.height() > 4096 * image.width()) {
+			image = image.copy(
+				0,
+				(image.height() - 4096 * image.width()) / 2,
+				image.width(),
+				4096 * image.width());
+		}
+
+		Window::Theme::Background()->setImage(
+			Window::Theme::kCustomBackground,
+			std::move(image));
+		Window::Theme::Background()->setTile(false);
+	};
+	FileDialog::GetOpenPath(
+		parent.get(),
+		lang(lng_choose_image),
+		filters.join(qsl(";;")),
+		crl::guard(parent, callback));
+
+}
+
+#ifndef OS_WIN_STORE
+
+QString DownloadPathText() {
+	if (Global::DownloadPath().isEmpty()) {
+		return lang(lng_download_path_default);
+	} else if (Global::DownloadPath() == qsl("tmp")) {
+		return lang(lng_download_path_temp);
+	}
+	return QDir::toNativeSeparators(Global::DownloadPath());
+}
+
+DownloadPathRow::DownloadPathRow(QWidget *parent) : RpWidget(parent) {
+	setupControls();
+}
+
+void DownloadPathRow::setupControls() {
+	const auto label = Ui::CreateChild<Ui::FlatLabel>(
+		this,
+		Lang::Viewer(lng_download_path_label),
+		st::settingsLinkLabel);
+	const auto link = Ui::CreateChild<Ui::LinkButton>(
+		this,
+		DownloadPathText(),
+		st::settingsLink);
+
+	base::ObservableViewer(
+		Global::RefDownloadPathChanged()
+	) | rpl::map([] {
+		return DownloadPathText();
+	}) | rpl::start_with_next([=](const QString &text) {
+		link->setText(text);
+	}, link->lifetime());
+
+	link->addClickHandler([] {
+		Ui::show(Box<DownloadPathBox>());
+	});
+
+	rpl::combine(
+		widthValue(),
+		label->sizeValue(),
+		link->widthValue()
+	) | rpl::start_with_next([=](int width, QSize labelSize, int possible) {
+		const auto space = st::settingsLinkLabel.style.font->spacew;
+		link->resizeToNaturalWidth(width - labelSize.width() - space);
+		if (link->width() == possible) {
+			label->moveToLeft(0, 0);
+			link->moveToLeft(labelSize.width() + space, 0);
+			resize(width, labelSize.height());
+		}
+	}, link->lifetime());
+}
+
+#endif // OS_WIN_STORE
+
+void SetupChatOptions(not_null<Ui::VerticalLayout*> container) {
+	AddDivider(container);
+	AddSkip(container);
+
+	auto wrap = object_ptr<Ui::VerticalLayout>(container);
+	const auto inner = wrap.data();
+	container->add(object_ptr<Ui::OverrideMargins>(
+		container,
+		std::move(wrap),
+		QMargins(0, 0, 0, st::settingsCheckbox.margin.bottom())));
+
+	const auto checkbox = [&](LangKey label, bool checked) {
+		return object_ptr<Ui::Checkbox>(
+			container,
+			lang(label),
+			checked,
+			st::settingsCheckbox);
+	};
+	const auto add = [&](LangKey label, bool checked, auto &&handle) {
+		base::ObservableViewer(
+			inner->add(
+				checkbox(label, checked),
+				st::settingsCheckboxPadding
+			)->checkedChanged
+		) | rpl::start_with_next(
+			std::move(handle),
+			inner->lifetime());
+	};
+	add(
+		lng_settings_replace_emojis,
+		Global::ReplaceEmoji(),
+		[](bool checked) {
+			Global::SetReplaceEmoji(checked);
+			Global::RefReplaceEmojiChanged().notify();
+			Local::writeUserSettings();
+		});
+
+	add(
+		lng_settings_suggest_emoji,
+		Global::SuggestEmoji(),
+		[](bool checked) {
+			Global::SetSuggestEmoji(checked);
+			Local::writeUserSettings();
+		});
+
+	add(
+		lng_settings_suggest_by_emoji,
+		Global::SuggestStickersByEmoji(),
+		[](bool checked) {
+			Global::SetSuggestStickersByEmoji(checked);
+			Local::writeUserSettings();
+		});
+
+	const auto dontask = inner->add(
+		checkbox(
+			lng_download_path_dont_ask,
+			!Global::AskDownloadPath()),
+#ifndef OS_WIN_STORE
+		st::settingsAskPathPadding);
+#else // OS_WIN_STORE
+		st::settingsCheckboxPadding);
+#endif // OS_WIN_STORE
+
+#ifndef OS_WIN_STORE
+	const auto showpath = Ui::AttachAsChild(
+		dontask,
+		rpl::event_stream<bool>());
+	const auto padding = st::settingsDownloadPathPadding;
+	const auto path = container->add(
+		object_ptr<Ui::SlideWrap<DownloadPathRow>>(
+			container,
+			object_ptr<DownloadPathRow>(container),
+			QMargins(
+				(padding.left()
+					+ st::settingsCheckbox.checkPosition.x()
+					+ st::defaultCheck.diameter
+					+ st::settingsCheckbox.textPosition.x()
+					- st::settingsCheckbox.margin.left()),
+				padding.top(),
+				padding.right(),
+				padding.bottom())));
+	AddSkip(container, st::settingsCheckboxPadding.bottom());
+	path->toggleOn(
+		showpath->events_starting_with(!Global::AskDownloadPath()));
+#endif // OS_WIN_STORE
+
+	base::ObservableViewer(
+		dontask->checkedChanged
+	) | rpl::start_with_next([=](bool checked) {
+		Global::SetAskDownloadPath(!checked);
+		Local::writeUserSettings();
+
+#ifndef OS_WIN_STORE
+		showpath->fire_copy(checked);
+#endif // OS_WIN_STORE
+
+	}, inner->lifetime());
+
+	AddSkip(container);
+}
+
+void SetupSendKey(not_null<Ui::VerticalLayout*> container) {
+	AddDivider(container);
+	const auto skip = st::settingsSendTypeSkip;
+	const auto full = st::settingsSectionSkip + skip;
+	AddSkip(container, full);
+
+	enum class SendByType {
+		Enter,
+		CtrlEnter,
+	};
+
+	const auto group = std::make_shared<Ui::RadioenumGroup<SendByType>>(
+		cCtrlEnter() ? SendByType::CtrlEnter : SendByType::Enter);
+	auto wrap = object_ptr<Ui::VerticalLayout>(container);
+	const auto inner = wrap.data();
+	container->add(
+		object_ptr<Ui::OverrideMargins>(
+			container,
+			std::move(wrap),
+			QMargins(0, skip, 0, skip)));
+
+	AddSkip(container, full);
+
+	const auto add = [&](
+			SendByType value,
+			LangKey key,
+			style::margins padding) {
+		inner->add(
+			object_ptr<Ui::Radioenum<SendByType>>(
+				inner,
+				group,
+				value,
+				lang(key),
+				st::settingsSendType),
+			st::settingsSendTypePadding);
+	};
+	const auto small = st::settingsSendTypePadding;
+	const auto top = skip;
+	add(
+		SendByType::Enter,
+		lng_settings_send_enter,
+		{ small.left(), small.top() + top, small.right(), small.bottom() });
+	add(
+		SendByType::CtrlEnter,
+		((cPlatform() == dbipMac || cPlatform() == dbipMacOld)
+			? lng_settings_send_cmdenter
+			: lng_settings_send_ctrlenter),
+		{ small.left(), small.top(), small.right(), small.bottom() + top });
+	group->setChangedCallback([](SendByType value) {
+		cSetCtrlEnter(value == SendByType::CtrlEnter);
+		if (App::main()) {
+			App::main()->ctrlEnterSubmitUpdated();
+		}
+		Local::writeUserSettings();
+	});
+}
+
+void SetupMediaOptions(not_null<Ui::VerticalLayout*> container) {
+	AddDivider(container);
+	AddSkip(container);
+
+	AddButton(
+		container,
+		lng_media_auto_settings,
+		st::settingsChatButton
+	)->addClickHandler([] {
+		Ui::show(Box<AutoDownloadBox>());
+	});
+
+	AddButton(
+		container,
+		lng_stickers_you_have,
+		st::settingsChatButton
+	)->addClickHandler([] {
+		Ui::show(Box<StickersBox>(StickersBox::Section::Installed));
+	});
+
+	AddSkip(container);
+}
+
+void SetupChatBackground(not_null<Ui::VerticalLayout*> container) {
+	AddDivider(container);
+	AddSkip(container);
+
+	container->add(
+		object_ptr<Ui::FlatLabel>(
+			container,
+			Lang::Viewer(lng_settings_section_background),
+			st::settingsBackgroundTitle),
+		st::settingsBackgroundTitlePadding);
+
+	container->add(
+		object_ptr<BackgroundRow>(container),
+		st::settingsBackgroundPadding);
+
+	const auto skipTop = st::settingsCheckbox.margin.top();
+	const auto skipBottom = st::settingsCheckbox.margin.bottom();
+	auto wrap = object_ptr<Ui::VerticalLayout>(container);
+	const auto inner = wrap.data();
+	container->add(
+		object_ptr<Ui::OverrideMargins>(
+			container,
+			std::move(wrap),
+			QMargins(0, skipTop, 0, skipBottom)));
+
+	AddSkip(container);
+
+	const auto tile = inner->add(
+		object_ptr<Ui::Checkbox>(
+			inner,
+			lang(lng_settings_bg_tile),
+			Window::Theme::Background()->tile(),
+			st::settingsCheckbox),
+		st::settingsSendTypePadding);
+	const auto adaptive = inner->add(
+		object_ptr<Ui::SlideWrap<Ui::Checkbox>>(
+			inner,
+			object_ptr<Ui::Checkbox>(
+				inner,
+				lang(lng_settings_adaptive_wide),
+				Global::AdaptiveForWide(),
+				st::settingsCheckbox),
+			st::settingsSendTypePadding));
+
+	base::ObservableViewer(
+		tile->checkedChanged
+	) | rpl::start_with_next([](bool checked) {
+		Window::Theme::Background()->setTile(checked);
+	}, tile->lifetime());
+
+	using Update = const Window::Theme::BackgroundUpdate;
+	base::ObservableViewer(
+		*Window::Theme::Background()
+	) | rpl::filter([](const Update &update) {
+		return (update.type == Update::Type::Changed);
+	}) | rpl::map([] {
+		return Window::Theme::Background()->tile();
+	}) | rpl::start_with_next([=](bool tiled) {
+		tile->setChecked(tiled);
+	}, tile->lifetime());
+
+	adaptive->toggleOn(rpl::single(
+		rpl::empty_value()
+	) | rpl::then(base::ObservableViewer(
+		Adaptive::Changed()
+	)) | rpl::map([] {
+		return (Global::AdaptiveChatLayout() == Adaptive::ChatLayout::Wide);
+	}));
+
+	base::ObservableViewer(
+		adaptive->entity()->checkedChanged
+	) | rpl::start_with_next([](bool checked) {
+		Global::SetAdaptiveForWide(checked);
+		Adaptive::Changed().notify();
+		Local::writeUserSettings();
+	}, adaptive->lifetime());
+}
+
+void SetupThemeOptions(not_null<Ui::VerticalLayout*> container) {
+	AddDivider(container);
+	AddSkip(container);
+
+	const auto calling = Ui::AttachAsChild(container, 0);
+	AddButton(
+		container,
+		lng_settings_use_night_mode,
+		st::settingsChatButton
+	)->toggleOn(
+		rpl::single(Window::Theme::IsNightMode())
+	)->toggledValue(
+	) | rpl::start_with_next([=](bool toggled) {
+		++*calling;
+		const auto change = [=] {
+			if (!--*calling && toggled != Window::Theme::IsNightMode()) {
+				Window::Theme::ToggleNightMode();
+			}
+		};
+		App::CallDelayed(
+			st::settingsButton.toggle.duration,
+			container,
+			change);
+	}, container->lifetime());
+
+	AddButton(
+		container,
+		lng_settings_bg_edit_theme,
+		st::settingsChatButton
+	)->addClickHandler(App::LambdaDelayed(
+		st::settingsChatButton.ripple.hideDuration,
+		container,
+		[] { Window::Theme::Editor::Start(); }));
+
+	using Update = const Window::Theme::BackgroundUpdate;
+	container->add(
+		object_ptr<Ui::SlideWrap<Button>>(
+			container,
+			object_ptr<Button>(
+				container,
+				Lang::Viewer(lng_settings_bg_use_default),
+				st::settingsChatButton))
+	)->toggleOn(rpl::single(
+		Window::Theme::SuggestThemeReset()
+	) | rpl::then(base::ObservableViewer(
+		*Window::Theme::Background()
+	) | rpl::filter([](const Update &update) {
+		return (update.type == Update::Type::ApplyingTheme
+			|| update.type == Update::Type::New);
+	}) | rpl::map([] {
+		return Window::Theme::SuggestThemeReset();
+	})))->entity()->addClickHandler([] {
+		Window::Theme::ApplyDefault();
+	});
+
+	AddSkip(container);
+}
+
+} // namespace
 
 Chat::Chat(QWidget *parent, not_null<UserData*> self)
 : Section(parent)
@@ -24,7 +698,11 @@ Chat::Chat(QWidget *parent, not_null<UserData*> self)
 void Chat::setupContent() {
 	const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
 
-	content->add(object_ptr<BoxContentDivider>(content));
+	SetupChatOptions(content);
+	SetupSendKey(content);
+	SetupMediaOptions(content);
+	SetupChatBackground(content);
+	SetupThemeOptions(content);
 
 	Ui::ResizeFitChild(this, content);
 }
diff --git a/Telegram/SourceFiles/settings/settings_common.cpp b/Telegram/SourceFiles/settings/settings_common.cpp
index 0f28a69d3..c3b0e8600 100644
--- a/Telegram/SourceFiles/settings/settings_common.cpp
+++ b/Telegram/SourceFiles/settings/settings_common.cpp
@@ -47,9 +47,13 @@ object_ptr<Section> CreateSection(
 }
 
 void AddSkip(not_null<Ui::VerticalLayout*> container) {
+	AddSkip(container, st::settingsSectionSkip);
+}
+
+void AddSkip(not_null<Ui::VerticalLayout*> container, int skip) {
 	container->add(object_ptr<Ui::FixedHeightWidget>(
 		container,
-		st::settingsSectionSkip));
+		skip));
 }
 
 void AddDivider(not_null<Ui::VerticalLayout*> container) {
diff --git a/Telegram/SourceFiles/settings/settings_common.h b/Telegram/SourceFiles/settings/settings_common.h
index 92e272560..0f2426c25 100644
--- a/Telegram/SourceFiles/settings/settings_common.h
+++ b/Telegram/SourceFiles/settings/settings_common.h
@@ -59,6 +59,7 @@ object_ptr<Section> CreateSection(
 	UserData *self = nullptr);
 
 void AddSkip(not_null<Ui::VerticalLayout*> container);
+void AddSkip(not_null<Ui::VerticalLayout*> container, int skip);
 void AddDivider(not_null<Ui::VerticalLayout*> container);
 not_null<Button*> AddButton(
 	not_null<Ui::VerticalLayout*> container,
diff --git a/Telegram/SourceFiles/settings/settings_general.cpp b/Telegram/SourceFiles/settings/settings_general.cpp
index ef4a3bc66..0f180990e 100644
--- a/Telegram/SourceFiles/settings/settings_general.cpp
+++ b/Telegram/SourceFiles/settings/settings_general.cpp
@@ -82,7 +82,6 @@ void SetupUpdate(not_null<Ui::VerticalLayout*> container) {
 	AddDivider(container);
 	AddSkip(container);
 
-	const auto lifetime = Ui::AttachAsChild(container, rpl::lifetime());
 	const auto texts = Ui::AttachAsChild(
 		container,
 		rpl::event_stream<QString>());
@@ -115,7 +114,7 @@ void SetupUpdate(not_null<Ui::VerticalLayout*> container) {
 	check->entity()->widthValue() | rpl::start_with_next([=](int width) {
 		update->resizeToWidth(width);
 		update->moveToLeft(0, 0);
-	}, *lifetime);
+	}, update->lifetime());
 
 	AddSkip(container);
 
@@ -167,7 +166,7 @@ void SetupUpdate(not_null<Ui::VerticalLayout*> container) {
 			checker.stop();
 		}
 		setDefaultStatus(checker);
-	}, *lifetime);
+	}, toggle->lifetime());
 
 	Core::UpdateChecker checker;
 	check->toggleOn(rpl::combine(
@@ -182,26 +181,26 @@ void SetupUpdate(not_null<Ui::VerticalLayout*> container) {
 		check->setAttribute(Qt::WA_TransparentForMouseEvents);
 		texts->fire(lang(lng_settings_update_checking));
 		downloading->fire(false);
-	}, *lifetime);
+	}, check->lifetime());
 	checker.isLatest() | rpl::start_with_next([=] {
 		check->setAttribute(Qt::WA_TransparentForMouseEvents, false);
 		texts->fire(lang(lng_settings_latest_installed));
 		downloading->fire(false);
-	}, *lifetime);
+	}, check->lifetime());
 	checker.progress(
 	) | rpl::start_with_next([=](Core::UpdateChecker::Progress progress) {
 		showDownloadProgress(progress.already, progress.size);
-	}, *lifetime);
+	}, check->lifetime());
 	checker.failed() | rpl::start_with_next([=] {
 		check->setAttribute(Qt::WA_TransparentForMouseEvents, false);
 		texts->fire(lang(lng_settings_update_fail));
 		downloading->fire(false);
-	}, *lifetime);
+	}, check->lifetime());
 	checker.ready() | rpl::start_with_next([=] {
 		texts->fire(lang(lng_settings_update_ready));
 		update->show();
 		downloading->fire(false);
-	}, *lifetime);
+	}, check->lifetime());
 
 	setDefaultStatus(checker);
 
@@ -227,7 +226,6 @@ void SetupTray(not_null<Ui::VerticalLayout*> container) {
 	AddDivider(container);
 	AddSkip(container);
 
-	const auto lifetime = Ui::AttachAsChild(container, rpl::lifetime());
 	const auto trayEnabler = Ui::AttachAsChild(
 		container,
 		rpl::event_stream<bool>());
@@ -281,7 +279,7 @@ void SetupTray(not_null<Ui::VerticalLayout*> container) {
 		} else {
 			updateWorkmode();
 		}
-	}, *lifetime);
+	}, tray->lifetime());
 
 	if (taskbar) {
 		taskbar->toggledValue(
@@ -293,7 +291,7 @@ void SetupTray(not_null<Ui::VerticalLayout*> container) {
 			} else {
 				updateWorkmode();
 			}
-		}, *lifetime);
+		}, taskbar->lifetime());
 	}
 
 #ifndef OS_WIN_STORE
@@ -336,7 +334,7 @@ void SetupTray(not_null<Ui::VerticalLayout*> container) {
 			} else {
 				Local::writeSettings();
 			}
-		}, *lifetime);
+		}, autostart->lifetime());
 
 		minimized->entity()->toggleOn(
 			minimizedToggler->events_starting_with(minimizedToggled()));
@@ -353,13 +351,13 @@ void SetupTray(not_null<Ui::VerticalLayout*> container) {
 				cSetStartMinimized(checked);
 				Local::writeSettings();
 			}
-		}, *lifetime);
+		}, minimized->lifetime());
 
 		base::ObservableViewer(
 			Global::RefLocalPasscodeChanged()
 		) | rpl::start_with_next([=] {
 			minimizedToggler->fire(minimizedToggled());
-		}, *lifetime);
+		}, minimized->lifetime());
 
 		sendto->toggledValue(
 		) | rpl::filter([](bool checked) {
@@ -368,7 +366,7 @@ void SetupTray(not_null<Ui::VerticalLayout*> container) {
 			cSetSendToMenu(checked);
 			psSendToMenu(checked);
 			Local::writeSettings();
-		}, *lifetime);
+		}, sendto->lifetime());
 	}
 #endif // OS_WIN_STORE
 
diff --git a/Telegram/SourceFiles/settings/settings_notifications.cpp b/Telegram/SourceFiles/settings/settings_notifications.cpp
index c6eeb6fa6..62b929559 100644
--- a/Telegram/SourceFiles/settings/settings_notifications.cpp
+++ b/Telegram/SourceFiles/settings/settings_notifications.cpp
@@ -30,19 +30,19 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
 			container,
 			lang(label),
 			checked,
-			st::settingsNotificationsCheckbox);
+			st::settingsCheckbox);
 	};
 	const auto addCheckbox = [&](LangKey label, bool checked) {
 		return container->add(
 			checkbox(label, checked),
-			st::settingsNotificationsCheckboxPadding);
+			st::settingsCheckboxPadding);
 	};
 	const auto addSlidingCheckbox = [&](LangKey label, bool checked) {
 		return container->add(
 			object_ptr<Ui::SlideWrap<Ui::Checkbox>>(
 				container,
 				checkbox(label, checked),
-				st::settingsNotificationsCheckboxPadding));
+				st::settingsCheckboxPadding));
 	};
 	const auto desktop = addCheckbox(
 		lng_settings_desktop_notify,
@@ -96,8 +96,6 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
 		advanced->hide(anim::type::instant);
 	}
 
-	const auto lifetime = Ui::AttachAsChild(container, rpl::lifetime());
-
 	using Change = Window::Notifications::ChangeType;
 	const auto changed = [](Change change) {
 		Local::writeUserSettings();
@@ -110,7 +108,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
 	}) | rpl::start_with_next([=](bool checked) {
 		Global::SetDesktopNotify(checked);
 		changed(Change::DesktopEnabled);
-	}, *lifetime);
+	}, desktop->lifetime());
 
 	base::ObservableViewer(
 		name->entity()->checkedChanged
@@ -126,7 +124,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
 	}) | rpl::start_with_next([=](DBINotifyView value) {
 		Global::SetNotifyView(value);
 		changed(Change::ViewParams);
-	}, *lifetime);
+	}, name->lifetime());
 
 	base::ObservableViewer(
 		preview->entity()->checkedChanged
@@ -142,7 +140,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
 	}) | rpl::start_with_next([=](DBINotifyView value) {
 		Global::SetNotifyView(value);
 		changed(Change::ViewParams);
-	}, *lifetime);
+	}, preview->lifetime());
 
 	base::ObservableViewer(
 		sound->checkedChanged
@@ -151,7 +149,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
 	}) | rpl::start_with_next([=](bool checked) {
 		Global::SetSoundNotify(checked);
 		changed(Change::SoundEnabled);
-	}, *lifetime);
+	}, sound->lifetime());
 
 	base::ObservableViewer(
 		muted->checkedChanged
@@ -160,7 +158,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
 	}) | rpl::start_with_next([=](bool checked) {
 		Global::SetIncludeMuted(checked);
 		changed(Change::IncludeMuted);
-	}, *lifetime);
+	}, muted->lifetime());
 
 	base::ObservableViewer(
 		Auth().notifications().settingsChanged()
@@ -176,7 +174,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
 		} else if (change == Change::SoundEnabled) {
 			sound->setChecked(Global::SoundNotify());
 		}
-	}, *lifetime);
+	}, desktop->lifetime());
 
 	if (native) {
 		base::ObservableViewer(
@@ -194,7 +192,7 @@ void SetupNotificationsContent(not_null<Ui::VerticalLayout*> container) {
 					!Global::NativeNotifications(),
 					anim::type::normal);
 			}
-		}, *lifetime);
+		}, native->lifetime());
 	}
 	if (advanced) {
 		advanced->entity()->addClickHandler([=] {
@@ -210,7 +208,7 @@ void SetupNotifications(not_null<Ui::VerticalLayout*> container) {
 	auto wrap = object_ptr<Ui::VerticalLayout>(container);
 	SetupNotificationsContent(wrap.data());
 
-	container->add(object_ptr<Ui::IgnoreMargins>(
+	container->add(object_ptr<Ui::OverrideMargins>(
 		container,
 		std::move(wrap)));
 
diff --git a/Telegram/SourceFiles/ui/widgets/buttons.cpp b/Telegram/SourceFiles/ui/widgets/buttons.cpp
index 136d269d9..52792a4a3 100644
--- a/Telegram/SourceFiles/ui/widgets/buttons.cpp
+++ b/Telegram/SourceFiles/ui/widgets/buttons.cpp
@@ -45,7 +45,7 @@ void LinkButton::paintEvent(QPaintEvent *e) {
 	p.setPen(pen);
 	const auto left = _st.padding.left();
 	const auto top = _st.padding.top() + font->ascent;
-	if (width() > naturalWidth()) {
+	if (width() < naturalWidth()) {
 		const auto available = width() - left - _st.padding.right();
 		p.drawText(left, top, font->elided(_text, available));
 	} else {
diff --git a/Telegram/SourceFiles/ui/wrap/vertical_layout.cpp b/Telegram/SourceFiles/ui/wrap/vertical_layout.cpp
index 602a52a1f..c44786cca 100644
--- a/Telegram/SourceFiles/ui/wrap/vertical_layout.cpp
+++ b/Telegram/SourceFiles/ui/wrap/vertical_layout.cpp
@@ -62,7 +62,7 @@ int VerticalLayout::resizeGetHeight(int newWidth) {
 			+ row.widget->heightNoMargins()
 			+ row.margin.bottom();
 	}
-	return result - margins.bottom();
+	return result;
 }
 
 void VerticalLayout::visibleTopBottomUpdated(
diff --git a/Telegram/SourceFiles/ui/wrap/wrap.h b/Telegram/SourceFiles/ui/wrap/wrap.h
index 221dae1a3..cb18d6929 100644
--- a/Telegram/SourceFiles/ui/wrap/wrap.h
+++ b/Telegram/SourceFiles/ui/wrap/wrap.h
@@ -145,12 +145,15 @@ public:
 
 };
 
-class IgnoreMargins : public Wrap<RpWidget> {
+class OverrideMargins : public Wrap<RpWidget> {
 	using Parent = Wrap<RpWidget>;
 
 public:
-	IgnoreMargins(QWidget *parent, object_ptr<RpWidget> &&child)
-	: Parent(parent, std::move(child)) {
+	OverrideMargins(
+		QWidget *parent,
+		object_ptr<RpWidget> &&child,
+		QMargins margins = QMargins())
+	: Parent(parent, std::move(child)), _margins(margins) {
 		if (auto weak = wrapped()) {
 			auto margins = weak->getMargins();
 			resizeToWidth(weak->width()
@@ -160,14 +163,14 @@ public:
 	}
 
 	QMargins getMargins() const override {
-		return QMargins();
+		return _margins;
 	}
 
 protected:
 	int resizeGetHeight(int newWidth) override {
 		if (auto weak = wrapped()) {
 			weak->resizeToWidth(newWidth);
-			weak->moveToLeft(0, 0);
+			weak->moveToLeft(_margins.left(), _margins.top());
 			return weak->heightNoMargins();
 		}
 		return height();
@@ -177,10 +180,20 @@ private:
 	void wrappedSizeUpdated(QSize size) override {
 		auto margins = wrapped()->getMargins();
 		resize(
-			size.width() - margins.left() - margins.right(),
-			size.height() - margins.top() - margins.bottom());
+			(size.width()
+				- margins.left()
+				- margins.right()
+				+ _margins.left()
+				+ _margins.right()),
+			(size.height()
+				- margins.top()
+				- margins.bottom()
+				+ _margins.top()
+				+ _margins.bottom()));
 	}
 
+	QMargins _margins;
+
 };
 
 } // namespace Ui