diff --git a/Telegram/SourceFiles/api/api_bot.cpp b/Telegram/SourceFiles/api/api_bot.cpp
index 9921355de..f98d70118 100644
--- a/Telegram/SourceFiles/api/api_bot.cpp
+++ b/Telegram/SourceFiles/api/api_bot.cpp
@@ -426,10 +426,19 @@ void ActivateBotCommand(ClickHandlerContext context, int row, int column) {
 				return false;
 			}();
 			if (!fastSwitchDone) {
-				controller->content()->inlineSwitchLayer('@'
+				const auto botAndQuery = '@'
 					+ bot->username()
 					+ ' '
-					+ QString::fromUtf8(button->data));
+					+ QString::fromUtf8(button->data);
+				const auto chosen = [=](not_null<Data::Thread*> thread) {
+					return controller->content()->inlineSwitchChosen(
+						thread,
+						botAndQuery);
+				};
+				Window::ShowChooseRecipientBox(
+					controller,
+					chosen,
+					tr::lng_inline_switch_choose());
 			}
 		}
 	} break;
diff --git a/Telegram/SourceFiles/core/local_url_handlers.cpp b/Telegram/SourceFiles/core/local_url_handlers.cpp
index 5f3bc644b..2cf4c664f 100644
--- a/Telegram/SourceFiles/core/local_url_handlers.cpp
+++ b/Telegram/SourceFiles/core/local_url_handlers.cpp
@@ -37,6 +37,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "media/view/media_view_open_common.h"
 #include "window/window_session_controller.h"
 #include "window/window_controller.h"
+#include "window/window_peer_menu.h"
 #include "window/themes/window_theme_editor_box.h" // GenerateSlug.
 #include "payments/payments_checkout_process.h"
 #include "settings/settings_common.h"
@@ -136,18 +137,23 @@ bool ShareUrl(
 	if (!controller) {
 		return false;
 	}
-	auto params = url_parse_params(
+	const auto params = url_parse_params(
 		match->captured(1),
 		qthelp::UrlParamNameTransform::ToLower);
-	auto url = params.value(u"url"_q);
-	if (url.isEmpty()) {
+	const auto url = params.value(u"url"_q);
+	if (url.isEmpty() || url.trimmed().startsWith('@')) {
+		// Don't allow to insert an inline bot query by share url link.
 		return false;
-	} else {
-		controller->content()->shareUrlLayer(url, params.value("text"));
-		controller->window().activate();
-		return true;
 	}
-	return false;
+
+	const auto text = params.value("text");
+	const auto chosen = [=](not_null<Data::Thread*> thread) {
+		const auto content = controller->content();
+		return content->shareUrl(thread, url, text);
+	};
+	Window::ShowChooseRecipientBox(controller, chosen);
+	controller->window().activate();
+	return true;
 }
 
 bool ConfirmPhone(
diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style
index 163c5ee61..fbe385e22 100644
--- a/Telegram/SourceFiles/dialogs/dialogs.style
+++ b/Telegram/SourceFiles/dialogs/dialogs.style
@@ -401,19 +401,6 @@ dialogsLoadMoreLoading: InfiniteRadialAnimation(defaultInfiniteRadialAnimation)
 	size: size(12px, 12px);
 }
 
-dialogsForwardHeight: 32px;
-dialogsForwardTextLeft: 35px;
-dialogsForwardTextTop: 6px;
-dialogsForwardCancel: IconButton {
-	width: 34px;
-	height: dialogsForwardHeight;
-
-	icon: dialogsForwardCancelIcon;
-	iconOver: dialogsForwardCancelIcon;
-	iconPosition: point(12px, 11px);
-}
-dialogsForwardFont: semiboldFont;
-
 dialogsSearchInHeight: 52px;
 dialogsSearchInPhotoSize: 36px;
 dialogsSearchInPhotoPadding: 10px;
diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp
index f4f6c90fc..f28c8ec8c 100644
--- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp
+++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp
@@ -3620,9 +3620,6 @@ void InnerWidget::setupShortcuts() {
 	}) | rpl::start_with_next([=](not_null<Shortcuts::Request*> request) {
 		using Command = Shortcuts::Command;
 
-		if (_controller->selectingPeer()) {
-			return;
-		}
 		const auto row = _controller->activeChatEntryCurrent();
 		// Those should be computed before the call to request->handle.
 		const auto previous = row.key
@@ -3660,9 +3657,10 @@ void InnerWidget::setupShortcuts() {
 			return jumpToDialogRow(last);
 		});
 		request->check(Command::ChatSelf) && request->handle([=] {
-			_controller->content()->chooseThread(
-				session().user(),
-				ShowAtUnreadMsgId);
+			_controller->showThread(
+				session().data().history(session().user()),
+				ShowAtUnreadMsgId,
+				Window::SectionShow::Way::ClearStack);
 			return true;
 		});
 		request->check(Command::ShowArchive) && request->handle([=] {
diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp
index 9f7e57cf4..2650abb58 100644
--- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp
+++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp
@@ -328,11 +328,6 @@ Widget::Widget(
 		}, lifetime());
 	}
 
-	controller->adaptive().changes(
-	) | rpl::start_with_next([=] {
-		updateForwardBar();
-	}, lifetime());
-
 	_cancelSearch->setClickedCallback([this] { cancelSearch(); });
 	_jumpToDate->entity()->setClickedCallback([this] { showCalendar(); });
 	_chooseFromUser->entity()->setClickedCallback([this] { showSearchFrom(); });
@@ -425,8 +420,6 @@ Widget::Widget(
 }
 
 void Widget::chosenRow(const ChosenRow &row) {
-	const auto openSearchResult = !controller()->selectingPeer()
-		&& row.filteredRow;
 	const auto history = row.key.history();
 	const auto topicJump = history
 		? history->peer->forumTopicFor(row.message.fullId.msg)
@@ -437,14 +430,16 @@ void Widget::chosenRow(const ChosenRow &row) {
 				topicJump->forum(),
 				Window::SectionShow().withChildColumn());
 		}
-		controller()->content()->chooseThread(
+		controller()->showThread(
 			topicJump,
-			ShowAtUnreadMsgId);
+			ShowAtUnreadMsgId,
+			Window::SectionShow::Way::ClearStack);
 		return;
 	} else if (const auto topic = row.key.topic()) {
-		controller()->content()->chooseThread(
+		controller()->showThread(
 			topic,
-			row.message.fullId.msg);
+			row.message.fullId.msg,
+			Window::SectionShow::Way::ClearStack);
 	} else if (history && history->peer->isForum() && !row.message.fullId) {
 		controller()->showForum(
 			history->peer->forum(),
@@ -475,13 +470,16 @@ void Widget::chosenRow(const ChosenRow &row) {
 			}
 		} else {
 			hideChildList();
-			controller()->content()->chooseThread(history, showAtMsgId);
+			controller()->showThread(
+				history,
+				showAtMsgId,
+				Window::SectionShow::Way::ClearStack);
 		}
 	} else if (const auto folder = row.key.folder()) {
 		hideChildList();
 		controller()->openFolder(folder);
 	}
-	if (openSearchResult && !session().supportMode()) {
+	if (row.filteredRow && !session().supportMode()) {
 		if (_subsectionTopBar) {
 			_subsectionTopBar->toggleSearch(false, anim::type::instant);
 		} else {
@@ -671,9 +669,6 @@ void Widget::setupShortcuts() {
 	}) | rpl::start_with_next([=](not_null<Shortcuts::Request*> request) {
 		using Command = Shortcuts::Command;
 
-		if (controller()->selectingPeer()) {
-			return;
-		}
 		if (_openedForum && !controller()->activeChatCurrent()) {
 			request->check(Command::Search) && request->handle([=] {
 				const auto history = _openedForum->history();
@@ -706,9 +701,6 @@ void Widget::fullSearchRefreshOn(rpl::producer<> events) {
 void Widget::updateControlsVisibility(bool fast) {
 	updateLoadMoreChatsVisibility();
 	_scroll->show();
-	if (_forwardCancel) {
-		_forwardCancel->show();
-	}
 	if ((_openedFolder || _openedForum) && _filter->hasFocus()) {
 		setInnerFocus();
 	}
@@ -759,7 +751,6 @@ void Widget::changeOpenedSubsection(
 		_showDirection = fromRight
 			? Window::SlideDirection::FromRight
 			: Window::SlideDirection::FromLeft;
-		_showAnimationType = ShowAnimation::Internal;
 	}
 	_a_show.stop();
 	change();
@@ -926,12 +917,11 @@ QPixmap Widget::grabForFolderSlideAnimation() {
 		_scrollToTop->hide();
 	}
 
-	const auto top = _forwardCancel ? _forwardCancel->height() : 0;
 	const auto rect = QRect(
 		0,
-		top,
+		0,
 		width(),
-		(_updateTelegram ? _updateTelegram->y() : height()) - top);
+		_updateTelegram ? _updateTelegram->y() : height());
 	auto result = Ui::GrabWidget(this, rect);
 
 	if (!hidden) {
@@ -1069,13 +1059,10 @@ void Widget::showFast() {
 		_inner->clearSelection();
 	}
 	show();
-	updateForwardBar();
 }
 
 void Widget::showAnimated(Window::SlideDirection direction, const Window::SectionSlideParams &params) {
 	_showDirection = direction;
-	_showAnimationType = ShowAnimation::External;
-
 	_a_show.stop();
 
 	_cacheUnder = params.oldContentCache;
@@ -1091,9 +1078,6 @@ void Widget::showAnimated(Window::SlideDirection direction, const Window::Sectio
 
 void Widget::startSlideAnimation() {
 	_scroll->hide();
-	if (_forwardCancel) {
-		_forwardCancel->hide();
-	}
 	_searchControls->hide();
 	if (_subsectionTopBar) {
 		_subsectionTopBar->hide();
@@ -1155,10 +1139,9 @@ void Widget::escape() {
 				controller()->setActiveChatsFilter(first);
 			}
 		}
-	} else if (!_searchInChat && !controller()->selectingPeer()) {
-		if (controller()->activeChatEntryCurrent().key) {
-			controller()->content()->dialogsCancelled();
-		}
+	} else if (!_searchInChat
+		&& controller()->activeChatEntryCurrent().key) {
+		controller()->content()->dialogsCancelled();
 	}
 }
 
@@ -1785,15 +1768,10 @@ void Widget::peopleFailed(const MTP::Error &error, mtpRequestId requestId) {
 void Widget::dragEnterEvent(QDragEnterEvent *e) {
 	using namespace Storage;
 
-	if (controller()->selectingPeer()) {
-		return;
-	}
-
 	const auto data = e->mimeData();
 	_dragInScroll = false;
-	_dragForward = controller()->adaptive().isOneColumn()
-		? false
-		: data->hasFormat(qsl("application/x-td-forward"));
+	_dragForward = !controller()->adaptive().isOneColumn()
+		&& data->hasFormat(qsl("application/x-td-forward"));
 	if (_dragForward) {
 		e->setDropAction(Qt::CopyAction);
 		e->accept();
@@ -1841,7 +1819,7 @@ void Widget::updateDragInScroll(bool inScroll) {
 	if (_dragInScroll != inScroll) {
 		_dragInScroll = inScroll;
 		if (_dragInScroll) {
-			controller()->content()->showForwardLayer({});
+			controller()->content()->showDragForwardInfo();
 		} else {
 			controller()->content()->dialogsCancelled();
 		}
@@ -1857,7 +1835,7 @@ void Widget::dropEvent(QDropEvent *e) {
 			if (!thread->owningHistory()->peer->isForum()) {
 				hideChildList();
 			}
-			controller()->content()->onFilesOrForwardDrop(
+			controller()->content()->filesOrForwardDrop(
 				thread,
 				e->mimeData());
 			controller()->widget()->raise();
@@ -2176,10 +2154,6 @@ void Widget::updateSearchFromVisibility(bool fast) {
 
 void Widget::updateControlsGeometry() {
 	auto filterAreaTop = 0;
-	if (_forwardCancel) {
-		_forwardCancel->moveToLeft(0, filterAreaTop);
-		filterAreaTop += st::dialogsForwardHeight;
-	}
 	const auto usew = _childList ? _narrowWidth : width();
 	const auto childw = std::max(_narrowWidth, width() - usew);
 	const auto smallw = st::columnMinimalWidthLeft - _narrowWidth;
@@ -2289,30 +2263,6 @@ void Widget::updateControlsGeometry() {
 	}
 }
 
-rpl::producer<> Widget::closeForwardBarRequests() const {
-	return _closeForwardBarRequests.events();
-}
-
-void Widget::updateForwardBar() {
-	auto selecting = controller()->selectingPeer();
-	auto oneColumnSelecting = (controller()->adaptive().isOneColumn()
-		&& selecting);
-	if (!oneColumnSelecting == !_forwardCancel) {
-		return;
-	}
-	if (oneColumnSelecting) {
-		_forwardCancel.create(this, st::dialogsForwardCancel);
-		_forwardCancel->setClickedCallback([=] {
-			_closeForwardBarRequests.fire({});
-		});
-		if (!_a_show.animating()) _forwardCancel->show();
-	} else {
-		_forwardCancel.destroyDelayed();
-	}
-	updateControlsGeometry();
-	update();
-}
-
 RowDescriptor Widget::resolveChatNext(RowDescriptor from) const {
 	return _inner->resolveChatNext(from);
 }
@@ -2358,9 +2308,7 @@ void Widget::paintEvent(QPaintEvent *e) {
 	}
 	if (_a_show.animating()) {
 		const auto progress = _a_show.value(1.);
-		const auto top = (_showAnimationType == ShowAnimation::Internal)
-			? (_forwardCancel ? _forwardCancel->height() : 0)
-			: 0;
+		const auto top = 0;
 		const auto shift = std::min(st::slideShift, width() / 2);
 		const auto retina = cIntRetinaFactor();
 		const auto fromLeft = (_showDirection == Window::SlideDirection::FromLeft);
@@ -2378,15 +2326,7 @@ void Widget::paintEvent(QPaintEvent *e) {
 		st::slideShadow.fill(p, QRect(coordOver - st::slideShadow.width(), top, st::slideShadow.width(), _cacheOver.height() / retina));
 		return;
 	}
-	auto aboveTop = 0;
-	if (_forwardCancel) {
-		p.fillRect(0, aboveTop, width(), st::dialogsForwardHeight, st::dialogsForwardBg);
-		p.setPen(st::dialogsForwardFg);
-		p.setFont(st::dialogsForwardFont);
-		p.drawTextLeft(st::dialogsForwardTextLeft, st::dialogsForwardTextTop, width(), tr::lng_forward_choose(tr::now));
-		aboveTop += st::dialogsForwardHeight;
-	}
-	auto above = QRect(0, aboveTop, width(), _scroll->y() - aboveTop);
+	auto above = QRect(0, 0, width(), _scroll->y());
 	if (above.intersects(r)) {
 		p.fillRect(above.intersected(r), st::dialogsBg);
 	}
@@ -2470,9 +2410,7 @@ void Widget::cancelSearchInChat() {
 	cancelSearchRequest();
 	const auto isOneColumn = controller()->adaptive().isOneColumn();
 	if (_searchInChat) {
-		if (isOneColumn
-			&& !controller()->selectingPeer()
-			&& currentSearchQuery().trimmed().isEmpty()) {
+		if (isOneColumn && currentSearchQuery().trimmed().isEmpty()) {
 			if (const auto thread = _searchInChat.thread()) {
 				controller()->showThread(thread);
 			} else {
@@ -2482,7 +2420,7 @@ void Widget::cancelSearchInChat() {
 		setSearchInChat(Key());
 	}
 	applyFilterUpdate(true);
-	if (!isOneColumn && !controller()->selectingPeer()) {
+	if (!isOneColumn) {
 		controller()->content()->dialogsCancelled();
 	}
 }
diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.h b/Telegram/SourceFiles/dialogs/dialogs_widget.h
index f51ceb9c5..b914d747e 100644
--- a/Telegram/SourceFiles/dialogs/dialogs_widget.h
+++ b/Telegram/SourceFiles/dialogs/dialogs_widget.h
@@ -107,10 +107,6 @@ public:
 	void searchTopics();
 	void searchMore();
 
-	void updateForwardBar();
-
-	[[nodiscard]] rpl::producer<> closeForwardBarRequests() const;
-
 	[[nodiscard]] RowDescriptor resolveChatNext(RowDescriptor from = {}) const;
 	[[nodiscard]] RowDescriptor resolveChatPrevious(RowDescriptor from = {}) const;
 
@@ -132,11 +128,6 @@ protected:
 	void paintEvent(QPaintEvent *e) override;
 
 private:
-	enum class ShowAnimation {
-		External,
-		Internal,
-	};
-
 	void chosenRow(const ChosenRow &row);
 	void listScrollUpdated();
 	void cancelSearchInChat();
@@ -218,7 +209,6 @@ private:
 
 	Layout _layout = Layout::Main;
 	int _narrowWidth = 0;
-	object_ptr<Ui::IconButton> _forwardCancel = { nullptr };
 	object_ptr<Ui::RpWidget> _searchControls;
 	object_ptr<HistoryView::TopBarWidget> _subsectionTopBar = { nullptr } ;
 	object_ptr<Ui::IconButton> _mainMenuToggle;
@@ -246,7 +236,6 @@ private:
 	Ui::Animations::Simple _a_show;
 	Window::SlideDirection _showDirection = Window::SlideDirection();
 	QPixmap _cacheUnder, _cacheOver;
-	ShowAnimation _showAnimationType = ShowAnimation::External;
 
 	Ui::Animations::Simple _scrollToTopShown;
 	object_ptr<Ui::HistoryDownButton> _scrollToTop;
@@ -295,8 +284,6 @@ private:
 
 	int _topDelta = 0;
 
-	rpl::event_stream<> _closeForwardBarRequests;
-
 	std::unique_ptr<Widget> _childList;
 	std::unique_ptr<Ui::RpWidget> _childListShadow;
 
diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp
index b2c3d843c..eee3fab7d 100644
--- a/Telegram/SourceFiles/mainwidget.cpp
+++ b/Telegram/SourceFiles/mainwidget.cpp
@@ -445,10 +445,6 @@ auto MainWidget::floatPlayerGetSection(Window::Column column)
 			return _mainSection;
 		}
 		return _history;
-	}
-	if (isOneColumn() && selectingPeer()) {
-		Assert(_dialogs != nullptr);
-		return _dialogs;
 	} else if (_mainSection) {
 		return _mainSection;
 	} else if (!isOneColumn() || _history->peer()) {
@@ -483,10 +479,7 @@ void MainWidget::floatPlayerEnumerateSections(Fn<void(
 			callback(_history, Window::Column::Second);
 		}
 	} else {
-		if (isOneColumn() && selectingPeer()) {
-			Assert(_dialogs != nullptr);
-			callback(_dialogs, Window::Column::First);
-		} else if (_mainSection) {
+		if (_mainSection) {
 			callback(_mainSection, Window::Column::Second);
 		} else if (!isOneColumn() || _history->peer()) {
 			callback(_history, Window::Column::Second);
@@ -605,7 +598,9 @@ bool MainWidget::inlineSwitchChosen(
 	return true;
 }
 
-bool MainWidget::sendPaths(not_null<Data::Thread*> thread) {
+bool MainWidget::sendPaths(
+		not_null<Data::Thread*> thread,
+		const QStringList &paths) {
 	if (!thread->canWrite()) {
 		Ui::show(Ui::MakeInformBox(tr::lng_forward_send_files_cant()));
 		return false;
@@ -622,11 +617,11 @@ bool MainWidget::sendPaths(not_null<Data::Thread*> thread) {
 	}
 	return (_controller->activeChatCurrent().thread() == thread)
 		&& (_mainSection
-			? _mainSection->confirmSendingFiles(cSendPaths())
-			: _history->confirmSendingFiles(cSendPaths()));
+			? _mainSection->confirmSendingFiles(paths)
+			: _history->confirmSendingFiles(paths));
 }
 
-bool MainWidget::onFilesOrForwardDrop(
+bool MainWidget::filesOrForwardDrop(
 		not_null<Data::Thread*> thread,
 		not_null<const QMimeData*> data) {
 	if (const auto forum = thread->asForum()) {
@@ -681,28 +676,6 @@ void MainWidget::clearHider(not_null<Window::HistoryHider*> instance) {
 		return;
 	}
 	_hider.release();
-	_controller->setSelectingPeer(false);
-
-	Assert(_dialogs != nullptr);
-	if (isOneColumn()) {
-		if (_mainSection || (_history->peer() && _history->peer()->id)) {
-			auto animationParams = ([=] {
-				if (_mainSection) {
-					return prepareMainSectionAnimation(_mainSection);
-				}
-				return prepareHistoryAnimation(_history->peer() ? _history->peer()->id : 0);
-			})();
-			_dialogs->hide();
-			if (_mainSection) {
-				_mainSection->showAnimated(Window::SlideDirection::FromRight, animationParams);
-			} else {
-				_history->showAnimated(Window::SlideDirection::FromRight, animationParams);
-			}
-			floatPlayerCheckVisibility();
-		} else {
-			_dialogs->updateForwardBar();
-		}
-	}
 }
 
 void MainWidget::hiderLayer(base::unique_qptr<Window::HistoryHider> hider) {
@@ -711,13 +684,6 @@ void MainWidget::hiderLayer(base::unique_qptr<Window::HistoryHider> hider) {
 	}
 
 	_hider = std::move(hider);
-	_controller->setSelectingPeer(true);
-
-	_dialogs->closeForwardBarRequests(
-	) | rpl::start_with_next([=] {
-		_hider->startHide();
-	}, _hider->lifetime());
-
 	_hider->setParent(this);
 
 	_hider->hidden(
@@ -727,95 +693,23 @@ void MainWidget::hiderLayer(base::unique_qptr<Window::HistoryHider> hider) {
 		instance->deleteLater();
 	}, _hider->lifetime());
 
-	_hider->confirmed(
-	) | rpl::start_with_next([=] {
-		_dialogs->cancelSearch();
-	}, _hider->lifetime());
+	_hider->show();
+	updateControlsGeometry();
+	_dialogs->setInnerFocus();
 
-	if (isOneColumn()) {
-		dialogsToUp();
-
-		_hider->hide();
-		auto animationParams = prepareDialogsAnimation();
-
-		if (_mainSection) {
-			_mainSection->hide();
-		} else {
-			_history->hide();
-		}
-		if (_dialogs->isHidden()) {
-			_dialogs->show();
-			updateControlsGeometry();
-			_dialogs->showAnimated(Window::SlideDirection::FromLeft, animationParams);
-		}
-	} else {
-		_hider->show();
-		updateControlsGeometry();
-		_dialogs->setInnerFocus();
-	}
 	floatPlayerCheckVisibility();
 }
 
-void MainWidget::showForwardLayer(Data::ForwardDraft &&draft) {
-	auto callback = [=, draft = std::move(draft)](
-			not_null<Data::Thread*> thread) mutable {
-		return setForwardDraft(thread, std::move(draft));
-	};
+void MainWidget::showDragForwardInfo() {
 	hiderLayer(base::make_unique_q<Window::HistoryHider>(
 		this,
-		tr::lng_forward_choose(tr::now),
-		std::move(callback),
-		_controller->adaptive().oneColumnValue()));
+		tr::lng_forward_choose(tr::now)));
 }
 
-void MainWidget::showSendPathsLayer() {
-	hiderLayer(base::make_unique_q<Window::HistoryHider>(
-		this,
-		tr::lng_forward_choose(tr::now),
-		[=](not_null<Data::Thread*> thread) { return sendPaths(thread); },
-		_controller->adaptive().oneColumnValue()));
-	if (_hider) {
-		connect(_hider, &QObject::destroyed, [] {
-			cSetSendPaths(QStringList());
-		});
-	}
-}
-
-void MainWidget::shareUrlLayer(const QString &url, const QString &text) {
-	// Don't allow to insert an inline bot query by share url link.
-	if (url.trimmed().startsWith('@')) {
-		return;
-	}
-	auto callback = [=](not_null<Data::Thread*> thread) {
-		return shareUrl(thread, url, text);
-	};
-	hiderLayer(base::make_unique_q<Window::HistoryHider>(
-		this,
-		tr::lng_forward_choose(tr::now),
-		std::move(callback),
-		_controller->adaptive().oneColumnValue()));
-}
-
-void MainWidget::inlineSwitchLayer(const QString &botAndQuery) {
-	auto callback = [=](not_null<Data::Thread*> thread) {
-		return inlineSwitchChosen(thread, botAndQuery);
-	};
-	hiderLayer(base::make_unique_q<Window::HistoryHider>(
-		this,
-		tr::lng_inline_switch_choose(tr::now),
-		std::move(callback),
-		_controller->adaptive().oneColumnValue()));
-}
-
-bool MainWidget::selectingPeer() const {
-	return _hider ? true : false;
-}
-
-void MainWidget::clearSelectingPeer() {
+void MainWidget::hideDragForwardInfo() {
 	if (_hider) {
 		_hider->startHide();
 		_hider.release();
-		_controller->setSelectingPeer(false);
 	}
 }
 
@@ -1272,23 +1166,6 @@ void MainWidget::setInnerFocus() {
 	}
 }
 
-void MainWidget::chooseThread(
-		not_null<Data::Thread*> thread,
-		MsgId showAtMsgId) {
-	if (selectingPeer()) {
-		_hider->offerThread(thread);
-	} else {
-		_controller->showThread(
-			thread,
-			showAtMsgId,
-			Window::SectionShow::Way::ClearStack);
-	}
-}
-
-void MainWidget::chooseThread(not_null<PeerData*> peer, MsgId showAtMsgId) {
-	chooseThread(peer->owner().history(peer), showAtMsgId);
-}
-
 void MainWidget::clearBotStartToken(PeerData *peer) {
 	if (peer && peer->isUser() && peer->asUser()->isBot()) {
 		peer->asUser()->botInfo->startToken = QString();
@@ -1669,9 +1546,7 @@ Window::SectionSlideParams MainWidget::prepareShowAnimation(
 		bool willHaveTopBarShadow) {
 	Window::SectionSlideParams result;
 	result.withTopBarShadow = willHaveTopBarShadow;
-	if (selectingPeer() && isOneColumn()) {
-		result.withTopBarShadow = false;
-	} else if (_mainSection) {
+	if (_mainSection) {
 		if (!_mainSection->hasTopBarShadow()) {
 			result.withTopBarShadow = false;
 		}
@@ -1683,19 +1558,17 @@ Window::SectionSlideParams MainWidget::prepareShowAnimation(
 	if (_player) {
 		_player->entity()->hideShadowAndDropdowns();
 	}
-	auto playerPlaylistVisible = !_playerPlaylist->isHidden();
+	const auto playerPlaylistVisible = !_playerPlaylist->isHidden();
 	if (playerPlaylistVisible) {
 		_playerPlaylist->hide();
 	}
+	const auto hiderVisible = (_hider && !_hider->isHidden());
+	if (hiderVisible) {
+		_hider->hide();
+	}
 
 	auto sectionTop = getMainSectionTop();
-	if (selectingPeer() && isOneColumn()) {
-		result.oldContentCache = Ui::GrabWidget(this, QRect(
-			0,
-			sectionTop,
-			_dialogsWidth,
-			height() - sectionTop));
-	} else if (_mainSection) {
+	if (_mainSection) {
 		result.oldContentCache = _mainSection->grabForShowAnimation(result);
 	} else if (!isOneColumn() || !_history->isHidden()) {
 		result.oldContentCache = _history->grabForShowAnimation(result);
@@ -1707,6 +1580,9 @@ Window::SectionSlideParams MainWidget::prepareShowAnimation(
 			height() - sectionTop));
 	}
 
+	if (_hider && hiderVisible) {
+		_hider->show();
+	}
 	if (playerPlaylistVisible) {
 		_playerPlaylist->show();
 	}
@@ -1944,9 +1820,7 @@ void MainWidget::showBackFromStack(
 		return;
 	}
 
-	if (selectingPeer()) {
-		return;
-	} else if (_stack.empty()) {
+	if (_stack.empty()) {
 		_controller->clearSectionStack(params);
 		crl::on_main(this, [=] {
 			_controller->widget()->setInnerFocus();
@@ -2027,10 +1901,14 @@ QPixmap MainWidget::grabForShowAnimation(const Window::SectionSlideParams &param
 	if (_player) {
 		_player->entity()->hideShadowAndDropdowns();
 	}
-	auto playerPlaylistVisible = !_playerPlaylist->isHidden();
+	const auto playerPlaylistVisible = !_playerPlaylist->isHidden();
 	if (playerPlaylistVisible) {
 		_playerPlaylist->hide();
 	}
+	const auto hiderVisible = (_hider && !_hider->isHidden());
+	if (hiderVisible) {
+		_hider->hide();
+	}
 
 	auto sectionTop = getMainSectionTop();
 	if (isOneColumn()) {
@@ -2058,6 +1936,9 @@ QPixmap MainWidget::grabForShowAnimation(const Window::SectionSlideParams &param
 			_thirdShadow->show();
 		}
 	}
+	if (_hider && hiderVisible) {
+		_hider->show();
+	}
 	if (playerPlaylistVisible) {
 		_playerPlaylist->show();
 	}
@@ -2187,12 +2068,7 @@ void MainWidget::showAll() {
 		if (_hider) {
 			_hider->hide();
 		}
-		if (selectingPeer()) {
-			Assert(_dialogs != nullptr);
-			_dialogs->showFast();
-			_history->hide();
-			if (_mainSection) _mainSection->hide();
-		} else if (_mainSection) {
+		if (_mainSection) {
 			_mainSection->show();
 		} else if (_history->peer()) {
 			_history->show();
@@ -2202,7 +2078,7 @@ void MainWidget::showAll() {
 			_dialogs->showFast();
 			_history->hide();
 		}
-		if (!selectingPeer() && _dialogs && isMainSectionShown()) {
+		if (_dialogs && isMainSectionShown()) {
 			_dialogs->hide();
 		}
 	} else {
@@ -2780,19 +2656,21 @@ bool MainWidget::contentOverlapped(const QRect &globalRect) {
 void MainWidget::activate() {
 	if (_a_show.animating()) {
 		return;
-	} else if (!cSendPaths().isEmpty()) {
+	} else if (const auto paths = cSendPaths(); !paths.isEmpty()) {
 		const auto interpret = u"interpret://"_q;
-		const auto path = cSendPaths()[0];
-		if (path.startsWith(interpret)) {
-			cSetSendPaths(QStringList());
+		cSetSendPaths(QStringList());
+		if (paths[0].startsWith(interpret)) {
 			const auto error = Support::InterpretSendPath(
 				_controller,
-				path.mid(interpret.size()));
+				paths[0].mid(interpret.size()));
 			if (!error.isEmpty()) {
 				Ui::show(Ui::MakeInformBox(error));
 			}
 		} else {
-			showSendPathsLayer();
+			const auto chosen = [=](not_null<Data::Thread*> thread) {
+				return sendPaths(thread, paths);
+			};
+			Window::ShowChooseRecipientBox(_controller, chosen);
 		}
 	} else if (_mainSection) {
 		_mainSection->setInnerFocus();
diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h
index 8e1abec74..7dd25ef1a 100644
--- a/Telegram/SourceFiles/mainwidget.h
+++ b/Telegram/SourceFiles/mainwidget.h
@@ -169,20 +169,25 @@ public:
 
 	[[nodiscard]] bool animatingShow() const;
 
-	void showForwardLayer(Data::ForwardDraft &&draft);
-	void showSendPathsLayer();
-	void shareUrlLayer(const QString &url, const QString &text);
-	void inlineSwitchLayer(const QString &botAndQuery);
-	void hiderLayer(base::unique_qptr<Window::HistoryHider> h);
+	void showDragForwardInfo();
+	void hideDragForwardInfo();
+
 	bool setForwardDraft(
 		not_null<Data::Thread*> thread,
 		Data::ForwardDraft &&draft);
-	bool sendPaths(not_null<Data::Thread*> thread);
-	bool onFilesOrForwardDrop(
+	bool sendPaths(
+		not_null<Data::Thread*> thread,
+		const QStringList &paths);
+	bool shareUrl(
+		not_null<Data::Thread*> thread,
+		const QString &url,
+		const QString &text) const;
+	bool filesOrForwardDrop(
 		not_null<Data::Thread*> thread,
 		not_null<const QMimeData*> data);
-	bool selectingPeer() const;
-	void clearSelectingPeer();
+	bool inlineSwitchChosen(
+		not_null<Data::Thread*> thread,
+		const QString &botAndQuery) const;
 
 	void sendBotCommand(Bot::SendCommandRequest request);
 	void hideSingleUseKeyboard(PeerData *peer, MsgId replyTo);
@@ -197,9 +202,6 @@ public:
 	void checkChatBackground();
 	Image *newBackgroundThumb();
 
-	// Does offerThread or showThread.
-	void chooseThread(not_null<Data::Thread*> thread, MsgId showAtMsgId);
-	void chooseThread(not_null<PeerData*> peer, MsgId showAtMsgId);
 	void clearBotStartToken(PeerData *peer);
 
 	void ctrlEnterSubmitUpdated();
@@ -260,14 +262,6 @@ private:
 	[[nodiscard]] auto thirdSectionForCurrentMainSection(Dialogs::Key key)
 		-> std::shared_ptr<Window::SectionMemento>;
 
-	bool shareUrl(
-		not_null<Data::Thread*> thread,
-		const QString &url,
-		const QString &text) const;
-	bool inlineSwitchChosen(
-		not_null<Data::Thread*> thread,
-		const QString &botAndQuery) const;
-
 	void setupConnectingWidget();
 	void createPlayer();
 	void playerHeightUpdated();
@@ -304,6 +298,7 @@ private:
 
 	void hideAll();
 	void showAll();
+	void hiderLayer(base::unique_qptr<Window::HistoryHider> h);
 	void clearHider(not_null<Window::HistoryHider*> instance);
 
 	[[nodiscard]] auto floatPlayerDelegate()
diff --git a/Telegram/SourceFiles/platform/mac/touchbar/items/mac_pinned_chats_item.mm b/Telegram/SourceFiles/platform/mac/touchbar/items/mac_pinned_chats_item.mm
index 028de0625..c9978da16 100644
--- a/Telegram/SourceFiles/platform/mac/touchbar/items/mac_pinned_chats_item.mm
+++ b/Telegram/SourceFiles/platform/mac/touchbar/items/mac_pinned_chats_item.mm
@@ -779,10 +779,9 @@ TimeId CalculateOnlineTill(not_null<PeerData*> peer) {
 		if (_hasArchive && (index == (_selfUnpinned ? -2 : -1))) {
 			openFolder();
 		} else {
-			const auto chosen = (_selfUnpinned && index == -1)
+			controller->showPeerHistory((_selfUnpinned && index == -1)
 				? _session->user()
-				: peer;
-			controller->content()->chooseThread(chosen, ShowAtUnreadMsgId);
+				: peer);
 		}
 	});
 }
diff --git a/Telegram/SourceFiles/window/window_history_hider.cpp b/Telegram/SourceFiles/window/window_history_hider.cpp
index 0ab412ca5..134bd45ee 100644
--- a/Telegram/SourceFiles/window/window_history_hider.cpp
+++ b/Telegram/SourceFiles/window/window_history_hider.cpp
@@ -17,14 +17,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 
 namespace Window {
 
-HistoryHider::HistoryHider(
-	QWidget *parent,
-	const QString &text,
-	Fn<bool(not_null<Data::Thread*>)> confirm,
-	rpl::producer<bool> oneColumnValue)
+HistoryHider::HistoryHider(QWidget *parent, const QString &text)
 : RpWidget(parent)
-, _text(text)
-, _confirm(std::move(confirm)) {
+, _text(text) {
 	Lang::Updated(
 	) | rpl::start_with_next([=] {
 		refreshLang();
@@ -33,15 +28,11 @@ HistoryHider::HistoryHider(
 	_chooseWidth = st::historyForwardChooseFont->width(_text);
 
 	resizeEvent(0);
-	_a_opacity.start([this] { update(); }, 0., 1., st::boxDuration);
-
-	std::move(
-		oneColumnValue
-	) | rpl::start_with_next([=](bool oneColumn) {
-		_isOneColumn = oneColumn;
-	}, lifetime());
+	_a_opacity.start([=] { update(); }, 0., 1., st::boxDuration);
 }
 
+HistoryHider::~HistoryHider() = default;
+
 void HistoryHider::refreshLang() {
 	InvokeQueued(this, [this] { updateControlsGeometry(); });
 }
@@ -85,11 +76,7 @@ void HistoryHider::startHide() {
 	if (_hiding) return;
 
 	_hiding = true;
-	if (_isOneColumn) {
-		crl::on_main(this, [=] { _hidden.fire({}); });
-	} else {
-		_a_opacity.start([=] { animationCallback(); }, 1., 0., st::boxDuration);
-	}
+	_a_opacity.start([=] { animationCallback(); }, 1., 0., st::boxDuration);
 }
 
 void HistoryHider::animationCallback() {
@@ -99,14 +86,6 @@ void HistoryHider::animationCallback() {
 	}
 }
 
-void HistoryHider::confirm() {
-	_confirmed.fire({});
-}
-
-rpl::producer<> HistoryHider::confirmed() const {
-	return _confirmed.events();
-}
-
 rpl::producer<> HistoryHider::hidden() const {
 	return _hidden.events();
 }
@@ -122,13 +101,4 @@ void HistoryHider::updateControlsGeometry() {
 	_box = QRect((width() - w) / 2, (height() - h) / 2, w, h);
 }
 
-void HistoryHider::offerThread(not_null<Data::Thread*> thread) {
-	if (_confirm(thread)) {
-		startHide();
-	}
-}
-
-HistoryHider::~HistoryHider() {
-}
-
 } // namespace Window
diff --git a/Telegram/SourceFiles/window/window_history_hider.h b/Telegram/SourceFiles/window/window_history_hider.h
index 38c233803..7efafd1cc 100644
--- a/Telegram/SourceFiles/window/window_history_hider.h
+++ b/Telegram/SourceFiles/window/window_history_hider.h
@@ -20,34 +20,13 @@ class RoundButton;
 
 namespace Window {
 
-class HistoryHider : public Ui::RpWidget {
+class HistoryHider final : public Ui::RpWidget {
 public:
-	// Forward messages (via drag-n-drop)
-	HistoryHider(QWidget *parent, MessageIdsList &&items);
-
-	// Send path from command line argument.
-	HistoryHider(QWidget *parent);
-
-	// Share url.
-	HistoryHider(QWidget *parent, const QString &url, const QString &text);
-
-	// Inline switch button handler.
-	HistoryHider(QWidget *parent, const QString &botAndQuery);
-
-	HistoryHider(
-		QWidget *parent,
-		const QString &text,
-		Fn<bool(not_null<Data::Thread*>)> confirm,
-		rpl::producer<bool> oneColumnValue);
-
-	void offerThread(not_null<Data::Thread*> thread);
+	HistoryHider(QWidget *parent, const QString &text);
+	~HistoryHider();
 
 	void startHide();
-	void confirm();
-	rpl::producer<> confirmed() const;
-	rpl::producer<> hidden() const;
-
-	~HistoryHider();
+	[[nodiscard]] rpl::producer<> hidden() const;
 
 protected:
 	void paintEvent(QPaintEvent *e) override;
@@ -61,16 +40,13 @@ private:
 	void animationCallback();
 
 	QString _text;
-	Fn<bool(not_null<Data::Thread*>)> _confirm;
 	Ui::Animations::Simple _a_opacity;
 
 	QRect _box;
 	bool _hiding = false;
-	bool _isOneColumn = false;
 
 	int _chooseWidth = 0;
 
-	rpl::event_stream<> _confirmed;
 	rpl::event_stream<> _hidden;
 
 };
diff --git a/Telegram/SourceFiles/window/window_main_menu.cpp b/Telegram/SourceFiles/window/window_main_menu.cpp
index f4c964639..0c1bb3461 100644
--- a/Telegram/SourceFiles/window/window_main_menu.cpp
+++ b/Telegram/SourceFiles/window/window_main_menu.cpp
@@ -691,8 +691,7 @@ void MainMenu::setupMenu() {
 			tr::lng_saved_messages(),
 			{ &st::settingsIconSavedMessages, kIconLightBlue }
 		)->setClickedCallback([=] {
-			const auto self = controller->session().user();
-			controller->content()->chooseThread(self, ShowAtUnreadMsgId);
+			controller->showPeerHistory(controller->session().user());
 		});
 	} else {
 		addAction(
diff --git a/Telegram/SourceFiles/window/window_peer_menu.cpp b/Telegram/SourceFiles/window/window_peer_menu.cpp
index d9948f2ce..51aaf3060 100644
--- a/Telegram/SourceFiles/window/window_peer_menu.cpp
+++ b/Telegram/SourceFiles/window/window_peer_menu.cpp
@@ -1565,46 +1565,65 @@ void BlockSenderFromRepliesBox(
 		Window::ClearReply{ id });
 }
 
-QPointer<Ui::BoxContent> ShowForwardMessagesBox(
+QPointer<Ui::BoxContent> ShowChooseRecipientBox(
 		not_null<Window::SessionNavigation*> navigation,
-		Data::ForwardDraft &&draft,
+		FnMut<bool(not_null<Data::Thread*>)> &&chosen,
+		rpl::producer<QString> titleOverride,
 		FnMut<void()> &&successCallback) {
 	const auto weak = std::make_shared<QPointer<Ui::BoxContent>>();
-	auto chosen = [
-		draft = std::move(draft),
-		callback = std::move(successCallback),
-		weak,
-		navigation
+	auto callback = [
+		chosen = std::move(chosen),
+		success = std::move(successCallback),
+		weak
 	](not_null<Data::Thread*> thread) mutable {
-		const auto peer = thread->peer();
-		const auto content = navigation->parentController()->content();
-		if (peer->isSelf()
-			&& !draft.ids.empty()
-			&& draft.ids.front().peer != peer->id) {
-			ForwardToSelf(navigation, draft);
-		} else if (!content->setForwardDraft(thread, std::move(draft))) {
+		if (!chosen(thread)) {
 			return;
-		}
-		if (const auto strong = *weak) {
+		} else if (const auto strong = *weak) {
 			strong->closeBox();
 		}
-		if (callback) {
-			callback();
+		if (success) {
+			success();
 		}
 	};
-	auto initBox = [](not_null<PeerListBox*> box) {
+	auto initBox = [=](not_null<PeerListBox*> box) {
 		box->addButton(tr::lng_cancel(), [box] {
 			box->closeBox();
 		});
+		if (titleOverride) {
+			box->setTitle(std::move(titleOverride));
+		}
 	};
 	*weak = navigation->parentController()->show(Box<PeerListBox>(
 		std::make_unique<ChooseRecipientBoxController>(
 			&navigation->session(),
-			std::move(chosen)),
+			std::move(callback)),
 		std::move(initBox)), Ui::LayerOption::KeepOther);
 	return weak->data();
 }
 
+QPointer<Ui::BoxContent> ShowForwardMessagesBox(
+		not_null<Window::SessionNavigation*> navigation,
+		Data::ForwardDraft &&draft,
+		FnMut<void()> &&successCallback) {
+	auto chosen = [navigation, draft = std::move(draft)](
+			not_null<Data::Thread*> thread) mutable {
+		const auto content = navigation->parentController()->content();
+		const auto peer = thread->peer();
+		if (peer->isSelf()
+			&& !draft.ids.empty()
+			&& draft.ids.front().peer != peer->id) {
+			ForwardToSelf(navigation, draft);
+			return true;
+		}
+		return content->setForwardDraft(thread, std::move(draft));
+	};
+	return ShowChooseRecipientBox(
+		navigation,
+		std::move(chosen),
+		nullptr,
+		std::move(successCallback));
+}
+
 QPointer<Ui::BoxContent> ShowForwardMessagesBox(
 		not_null<Window::SessionNavigation*> navigation,
 		MessageIdsList &&items,
@@ -1684,7 +1703,7 @@ QPointer<Ui::BoxContent> ShowDropMediaBox(
 		navigation
 	](not_null<Data::ForumTopic*> topic) mutable {
 		const auto content = navigation->parentController()->content();
-		if (!content->onFilesOrForwardDrop(topic, data.get())) {
+		if (!content->filesOrForwardDrop(topic, data.get())) {
 			return;
 		} else if (const auto strong = *weak) {
 			strong->closeBox();
diff --git a/Telegram/SourceFiles/window/window_peer_menu.h b/Telegram/SourceFiles/window/window_peer_menu.h
index 58a12f9c1..1fa4b0fcb 100644
--- a/Telegram/SourceFiles/window/window_peer_menu.h
+++ b/Telegram/SourceFiles/window/window_peer_menu.h
@@ -114,6 +114,11 @@ Fn<void()> DeleteAndLeaveHandler(
 	not_null<Window::SessionController*> controller,
 	not_null<PeerData*> peer);
 
+QPointer<Ui::BoxContent> ShowChooseRecipientBox(
+	not_null<Window::SessionNavigation*> navigation,
+	FnMut<bool(not_null<Data::Thread*>)> &&chosen,
+	rpl::producer<QString> titleOverride = nullptr,
+	FnMut<void()> &&successCallback = nullptr);
 QPointer<Ui::BoxContent> ShowForwardMessagesBox(
 	not_null<Window::SessionNavigation*> navigation,
 	Data::ForwardDraft &&draft,
@@ -122,6 +127,11 @@ QPointer<Ui::BoxContent> ShowForwardMessagesBox(
 	not_null<Window::SessionNavigation*> navigation,
 	MessageIdsList &&items,
 	FnMut<void()> &&successCallback = nullptr);
+QPointer<Ui::BoxContent> ShowShareUrlBox(
+	not_null<Window::SessionNavigation*> navigation,
+	const QString &url,
+	const QString &text,
+	FnMut<void()> &&successCallback = nullptr);
 QPointer<Ui::BoxContent> ShowShareGameBox(
 	not_null<Window::SessionNavigation*> navigation,
 	not_null<UserData*> bot,
diff --git a/Telegram/SourceFiles/window/window_session_controller.cpp b/Telegram/SourceFiles/window/window_session_controller.cpp
index 78c2351b3..b46541a3d 100644
--- a/Telegram/SourceFiles/window/window_session_controller.cpp
+++ b/Telegram/SourceFiles/window/window_session_controller.cpp
@@ -641,7 +641,7 @@ void SessionNavigation::showThread(
 		showPeerHistory(thread->asHistory(), params, itemId);
 	}
 	if (parentController()->activeChatCurrent().thread() == thread) {
-		parentController()->content()->clearSelectingPeer();
+		parentController()->content()->hideDragForwardInfo();
 	}
 }
 
diff --git a/Telegram/SourceFiles/window/window_session_controller.h b/Telegram/SourceFiles/window/window_session_controller.h
index 05a54dfcc..fb9dcced1 100644
--- a/Telegram/SourceFiles/window/window_session_controller.h
+++ b/Telegram/SourceFiles/window/window_session_controller.h
@@ -326,15 +326,6 @@ public:
 		return *_emojiInteractions;
 	}
 
-	// We need access to this from MainWidget::MainWidget, where
-	// we can't call content() yet.
-	void setSelectingPeer(bool selecting) {
-		_selectingPeer = selecting;
-	}
-	[[nodiscard]] bool selectingPeer() const {
-		return _selectingPeer;
-	}
-
 	void setConnectingBottomSkip(int skip);
 	rpl::producer<int> connectingBottomSkipValue() const;
 
@@ -629,7 +620,6 @@ private:
 	std::deque<Dialogs::RowDescriptor> _chatEntryHistory;
 	int _chatEntryHistoryPosition = -1;
 	bool _filtersActivated = false;
-	bool _selectingPeer = false;
 
 	base::Timer _invitePeekTimer;