diff --git a/Telegram/SourceFiles/boxes/abstract_box.h b/Telegram/SourceFiles/boxes/abstract_box.h
index 5f1fa5632..90a3b2775 100644
--- a/Telegram/SourceFiles/boxes/abstract_box.h
+++ b/Telegram/SourceFiles/boxes/abstract_box.h
@@ -102,8 +102,8 @@ public:
 	virtual void setInnerFocus() {
 		setFocus();
 	}
-	virtual void closeHook() {
-	}
+
+	base::Observable<void> boxClosing;
 
 	void setDelegate(BoxContentDelegate *newDelegate) {
 		_delegate = newDelegate;
@@ -244,7 +244,7 @@ protected:
 		_content->setInnerFocus();
 	}
 	void closeHook() override {
-		_content->closeHook();
+		_content->boxClosing.notify(true);
 	}
 
 private:
diff --git a/Telegram/SourceFiles/boxes/add_contact_box.cpp b/Telegram/SourceFiles/boxes/add_contact_box.cpp
index 8ff030a8c..ffba58ccb 100644
--- a/Telegram/SourceFiles/boxes/add_contact_box.cpp
+++ b/Telegram/SourceFiles/boxes/add_contact_box.cpp
@@ -501,10 +501,19 @@ void SetupChannelBox::prepare() {
 			rtlupdate(_invitationLink);
 		}
 	}));
+	subscribe(boxClosing, [this] {
+		if (!_existing) {
+			showAddContactsToChannelBox();
+		}
+	});
 
 	updateMaxHeight();
 }
 
+void SetupChannelBox::showAddContactsToChannelBox() const {
+	Ui::show(Box<ContactsBox>(_channel));
+}
+
 void SetupChannelBox::setInnerFocus() {
 	if (_link->isHidden()) {
 		setFocus();
@@ -617,12 +626,6 @@ void SetupChannelBox::updateSelected(const QPoint &cursorGlobalPosition) {
 	}
 }
 
-void SetupChannelBox::closeHook() {
-	if (!_existing) {
-		Ui::show(Box<ContactsBox>(_channel));
-	}
-}
-
 void SetupChannelBox::onSave() {
 	if (_privacyGroup->value() == Privacy::Private) {
 		if (_existing) {
diff --git a/Telegram/SourceFiles/boxes/add_contact_box.h b/Telegram/SourceFiles/boxes/add_contact_box.h
index 190b65aaa..f49043171 100644
--- a/Telegram/SourceFiles/boxes/add_contact_box.h
+++ b/Telegram/SourceFiles/boxes/add_contact_box.h
@@ -137,7 +137,6 @@ public:
 	SetupChannelBox(QWidget*, ChannelData *channel, bool existing = false);
 
 	void setInnerFocus() override;
-	void closeHook() override;
 
 protected:
 	void prepare() override;
@@ -161,6 +160,7 @@ private:
 	};
 	void privacyChanged(Privacy value);
 	void updateSelected(const QPoint &cursorGlobalPosition);
+	void showAddContactsToChannelBox() const;
 
 	void onUpdateDone(const MTPBool &result);
 	bool onUpdateFail(const RPCError &error);
diff --git a/Telegram/SourceFiles/boxes/confirm_box.cpp b/Telegram/SourceFiles/boxes/confirm_box.cpp
index ac0654c7b..0d2a297ce 100644
--- a/Telegram/SourceFiles/boxes/confirm_box.cpp
+++ b/Telegram/SourceFiles/boxes/confirm_box.cpp
@@ -120,6 +120,11 @@ void ConfirmBox::prepare() {
 	if (!_informative) {
 		addButton([this] { return _cancelText; }, [this] { _cancelled = true; closeBox(); });
 	}
+	subscribe(boxClosing, [this] {
+		if (!_confirmed && (!_strictCancel || _cancelled) && _cancelledCallback) {
+			_cancelledCallback();
+		}
+	});
 	textUpdated();
 }
 
@@ -131,12 +136,6 @@ void ConfirmBox::textUpdated() {
 	setMouseTracking(_text.hasLinks());
 }
 
-void ConfirmBox::closeHook() {
-	if (!_confirmed && (!_strictCancel || _cancelled) && _cancelledCallback) {
-		_cancelledCallback();
-	}
-}
-
 void ConfirmBox::confirmed() {
 	if (!_confirmed) {
 		_confirmed = true;
diff --git a/Telegram/SourceFiles/boxes/confirm_box.h b/Telegram/SourceFiles/boxes/confirm_box.h
index 4c331ba15..4637e8249 100644
--- a/Telegram/SourceFiles/boxes/confirm_box.h
+++ b/Telegram/SourceFiles/boxes/confirm_box.h
@@ -47,8 +47,6 @@ public:
 	void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
 	void clickHandlerPressedChanged(const ClickHandlerPtr &p, bool pressed) override;
 
-	void closeHook() override;
-
 protected:
 	void prepare() override;
 
diff --git a/Telegram/SourceFiles/boxes/contacts_box.cpp b/Telegram/SourceFiles/boxes/contacts_box.cpp
index df3db178d..7e42e3f54 100644
--- a/Telegram/SourceFiles/boxes/contacts_box.cpp
+++ b/Telegram/SourceFiles/boxes/contacts_box.cpp
@@ -194,6 +194,12 @@ void ContactsBox::prepare() {
 	_searchTimer->setSingleShot(true);
 	connect(_searchTimer, SIGNAL(timeout()), this, SLOT(onSearchByUsername()));
 
+	subscribe(boxClosing, [this] {
+		if (_channel && _creating == CreatingGroupChannel) {
+			Ui::showPeerHistory(_channel, ShowAtTheEndMsgId);
+		}
+	});
+
 	setDimensions(st::boxWideWidth, st::boxMaxListHeight);
 
 	_select->raise();
@@ -351,12 +357,6 @@ void ContactsBox::paintEvent(QPaintEvent *e) {
 	}
 }
 
-void ContactsBox::closeHook() {
-	if (_channel && _creating == CreatingGroupChannel) {
-		Ui::showPeerHistory(_channel, ShowAtTheEndMsgId);
-	}
-}
-
 void ContactsBox::onFilterUpdate(const QString &filter) {
 	onScrollToY(0);
 	_inner->updateFilter(filter);
diff --git a/Telegram/SourceFiles/boxes/contacts_box.h b/Telegram/SourceFiles/boxes/contacts_box.h
index 69c41b7bb..923f081aa 100644
--- a/Telegram/SourceFiles/boxes/contacts_box.h
+++ b/Telegram/SourceFiles/boxes/contacts_box.h
@@ -85,8 +85,6 @@ public:
 	ContactsBox(QWidget*, ChatData *chat, MembersFilter filter);
 	ContactsBox(QWidget*, UserData *bot);
 
-	void closeHook() override;
-
 signals:
 	void adminAdded();
 
diff --git a/Telegram/SourceFiles/boxes/edit_color_box.cpp b/Telegram/SourceFiles/boxes/edit_color_box.cpp
index 9abaf2a47..897da15fb 100644
--- a/Telegram/SourceFiles/boxes/edit_color_box.cpp
+++ b/Telegram/SourceFiles/boxes/edit_color_box.cpp
@@ -670,6 +670,11 @@ void EditColorBox::prepare() {
 	subscribe(_picker->changed(), [this] { updateFromControls(); });
 	subscribe(_hueSlider->changed(), [this] { updateFromControls(); });
 	subscribe(_opacitySlider->changed(), [this] { updateFromControls(); });
+	subscribe(boxClosing, [this] {
+		if (_cancelCallback) {
+			_cancelCallback();
+		}
+	});
 	updateFromControls();
 }
 
diff --git a/Telegram/SourceFiles/boxes/edit_color_box.h b/Telegram/SourceFiles/boxes/edit_color_box.h
index c6d29e40c..b4aa2a64d 100644
--- a/Telegram/SourceFiles/boxes/edit_color_box.h
+++ b/Telegram/SourceFiles/boxes/edit_color_box.h
@@ -40,12 +40,6 @@ public:
 		updateFromColor(color);
 	}
 
-	void closeHook() override {
-		if (_cancelCallback) {
-			_cancelCallback();
-		}
-	}
-
 protected:
 	void prepare() override;
 
diff --git a/Telegram/SourceFiles/boxes/photo_crop_box.h b/Telegram/SourceFiles/boxes/photo_crop_box.h
index cbfb80def..69a36f504 100644
--- a/Telegram/SourceFiles/boxes/photo_crop_box.h
+++ b/Telegram/SourceFiles/boxes/photo_crop_box.h
@@ -31,13 +31,8 @@ public:
 
 	int32 mouseState(QPoint p);
 
-	void closeHook() override {
-		emit closed();
-	}
-
 signals:
 	void ready(const QImage &tosend);
-	void closed();
 
 private slots:
 	void onReady(const QImage &tosend);
diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp
index 097441b6f..33f99daaf 100644
--- a/Telegram/SourceFiles/boxes/send_files_box.cpp
+++ b/Telegram/SourceFiles/boxes/send_files_box.cpp
@@ -253,6 +253,11 @@ void SendFilesBox::prepare() {
 		connect(_caption, SIGNAL(submitted(bool)), this, SLOT(onSend(bool)));
 		connect(_caption, SIGNAL(cancelled()), this, SLOT(onClose()));
 	}
+	subscribe(boxClosing, [this] {
+		if (!_confirmed && _cancelledCallback) {
+			_cancelledCallback();
+		}
+	});
 	_send->setText(getSendButtonText());
 	updateButtonsGeometry();
 	updateBoxSize();
@@ -444,12 +449,6 @@ void SendFilesBox::onSend(bool ctrlShiftEnter) {
 	closeBox();
 }
 
-void SendFilesBox::closeHook() {
-	if (!_confirmed && _cancelledCallback) {
-		_cancelledCallback();
-	}
-}
-
 EditCaptionBox::EditCaptionBox(QWidget*, HistoryMedia *media, FullMsgId msgId) : _msgId(msgId) {
 	Expects(media->canEditCaption());
 
diff --git a/Telegram/SourceFiles/boxes/send_files_box.h b/Telegram/SourceFiles/boxes/send_files_box.h
index c5d7ab107..724b0689b 100644
--- a/Telegram/SourceFiles/boxes/send_files_box.h
+++ b/Telegram/SourceFiles/boxes/send_files_box.h
@@ -44,8 +44,6 @@ public:
 		_cancelledCallback = std::move(callback);
 	}
 
-	void closeHook() override;
-
 protected:
 	void prepare() override;
 	void setInnerFocus() override;
diff --git a/Telegram/SourceFiles/boxes/stickers_box.cpp b/Telegram/SourceFiles/boxes/stickers_box.cpp
index 03d276a8c..ca408668d 100644
--- a/Telegram/SourceFiles/boxes/stickers_box.cpp
+++ b/Telegram/SourceFiles/boxes/stickers_box.cpp
@@ -295,6 +295,9 @@ void StickersBox::prepare() {
 
 	if (_installed.widget()) {
 		connect(_installed.widget(), SIGNAL(draggingScrollDelta(int)), this, SLOT(onDraggingScrollDelta(int)));
+		if (!_megagroupSet) {
+			subscribe(boxClosing, [this] { saveChanges(); });
+		}
 	}
 
 	if (_tabs) {
@@ -563,11 +566,7 @@ void StickersBox::rebuildList(Tab *tab) {
 	tab->widget()->setRemovedSets(_localRemoved);
 }
 
-void StickersBox::closeHook() {
-	if (!_installed.widget() || _megagroupSet) {
-		return;
-	}
-
+void StickersBox::saveChanges() {
 	// Make sure that our changes in other tabs are applied in the Installed tab.
 	rebuildList(&_installed);
 
diff --git a/Telegram/SourceFiles/boxes/stickers_box.h b/Telegram/SourceFiles/boxes/stickers_box.h
index 7b8f9e8cc..d2bc48ecd 100644
--- a/Telegram/SourceFiles/boxes/stickers_box.h
+++ b/Telegram/SourceFiles/boxes/stickers_box.h
@@ -51,7 +51,6 @@ public:
 	StickersBox(QWidget*, const Stickers::Order &archivedIds);
 	StickersBox(QWidget*, gsl::not_null<ChannelData*> megagroup);
 
-	void closeHook() override;
 	void setInnerFocus() override;
 
 	~StickersBox();
@@ -101,6 +100,7 @@ private:
 	void switchTab();
 	void installSet(uint64 setId);
 	int getTopSkip() const;
+	void saveChanges();
 
 	QPixmap grabContentCache();
 
diff --git a/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.cpp b/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.cpp
index bf93b6db4..a82382d57 100644
--- a/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.cpp
+++ b/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.cpp
@@ -39,10 +39,11 @@ void ShowSearchFromBox(PeerData *peer, base::lambda<void(gsl::not_null<UserData*
 		return nullptr;
 	};
 	if (auto controller = createController()) {
-		auto box = Ui::show(Box<SearchFromBox>(std::move(controller), [](PeerListBox *box) {
-			box->addButton(langFactory(lng_cancel), [box] { box->closeBox(); });
+		auto subscription = std::make_shared<base::Subscription>();
+		auto box = Ui::show(Box<PeerListBox>(std::move(controller), [subscription](gsl::not_null<PeerListBox*> box) {
+			box->addButton(langFactory(lng_cancel), [box, subscription] { box->closeBox(); });
 		}), KeepOtherLayers);
-		box->setClosedCallback(std::move(closedCallback));
+		*subscription = box->boxClosing.add_subscription(std::move(closedCallback));
 	}
 }
 
diff --git a/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.h b/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.h
index 8e32a3670..febcaac88 100644
--- a/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.h
+++ b/Telegram/SourceFiles/dialogs/dialogs_search_from_controllers.h
@@ -27,26 +27,6 @@ namespace Dialogs {
 
 void ShowSearchFromBox(PeerData *peer, base::lambda<void(gsl::not_null<UserData*>)> callback, base::lambda<void()> closedCallback);
 
-class SearchFromBox : public PeerListBox {
-public:
-	using PeerListBox::PeerListBox;
-
-	void setClosedCallback(base::lambda<void()> callback) {
-		_closedCallback = std::move(callback);
-	}
-
-protected:
-	void closeHook() override {
-		if (_closedCallback) {
-			_closedCallback();
-		}
-	}
-
-private:
-	base::lambda<void()> _closedCallback;
-
-};
-
 class ChatSearchFromController : public PeerListController, protected base::Subscriber {
 public:
 	ChatSearchFromController(gsl::not_null<ChatData*> chat, base::lambda<void(gsl::not_null<UserData*>)> callback);
diff --git a/Telegram/SourceFiles/profile/profile_cover.cpp b/Telegram/SourceFiles/profile/profile_cover.cpp
index b80ee6db6..aba0130a4 100644
--- a/Telegram/SourceFiles/profile/profile_cover.cpp
+++ b/Telegram/SourceFiles/profile/profile_cover.cpp
@@ -524,7 +524,7 @@ void CoverWidget::showSetPhotoBox(const QImage &img) {
 	}
 
 	auto box = Ui::show(Box<PhotoCropBox>(img, _peer));
-	connect(box, SIGNAL(closed()), this, SLOT(onPhotoUploadStatusChanged()));
+	subscribe(box->boxClosing, [this] { onPhotoUploadStatusChanged(); });
 }
 
 void CoverWidget::onPhotoUploadStatusChanged(PeerId peerId) {
diff --git a/Telegram/SourceFiles/settings/settings_cover.cpp b/Telegram/SourceFiles/settings/settings_cover.cpp
index 4ae1b0bd1..e6f7c855d 100644
--- a/Telegram/SourceFiles/settings/settings_cover.cpp
+++ b/Telegram/SourceFiles/settings/settings_cover.cpp
@@ -334,7 +334,7 @@ void CoverWidget::showSetPhotoBox(const QImage &img) {
 	}
 
 	auto box = Ui::show(Box<PhotoCropBox>(img, _self));
-	connect(box, SIGNAL(closed()), this, SLOT(onPhotoUploadStatusChanged()));
+	subscribe(box->boxClosing, [this] { onPhotoUploadStatusChanged(); });
 }
 
 void CoverWidget::onPhotoUploadStatusChanged(PeerId peerId) {