diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt
index 6e514e15c..626846aac 100644
--- a/Telegram/Resources/style.txt
+++ b/Telegram/Resources/style.txt
@@ -886,6 +886,8 @@ dlgPaddingVer: 8px;
 dlgHeight: 62px;
 dlgPhotoPadding: 12px;
 
+dlgImportantHeight: 37px;
+
 noContactsHeight: 100px;
 noContactsFont: font(fsize);
 noContactsColor: #777;
diff --git a/Telegram/SourceFiles/apiwrap.cpp b/Telegram/SourceFiles/apiwrap.cpp
index 07d0b9d0f..83596d4e7 100644
--- a/Telegram/SourceFiles/apiwrap.cpp
+++ b/Telegram/SourceFiles/apiwrap.cpp
@@ -245,7 +245,7 @@ void ApiWrap::gotChatFull(PeerData *peer, const MTPmessages_ChatFull &result, mt
 						if (!h->isEmpty()) {
 							h->clear(true);
 						}
-						if (hto->inChatList() && h->inChatList()) {
+						if (hto->inChatList(Dialogs::Mode::All) && h->inChatList(Dialogs::Mode::All)) {
 							App::removeDialog(h);
 						}
 					}
diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp
index c07ee3f82..6d11b479b 100644
--- a/Telegram/SourceFiles/app.cpp
+++ b/Telegram/SourceFiles/app.cpp
@@ -557,7 +557,7 @@ namespace {
 								if (!h->isEmpty()) {
 									h->clear(true);
 								}
-								if (hto->inChatList() && h->inChatList()) {
+								if (hto->inChatList(Dialogs::Mode::All) && h->inChatList(Dialogs::Mode::All)) {
 									App::removeDialog(h);
 								}
 							}
@@ -1137,8 +1137,8 @@ namespace {
 			} else {
 				if (channelHistory) {
 					channelHistory->messageWithIdDeleted(i->v);
-					if (channelHistory->unreadCount > 0 && i->v >= channelHistory->inboxReadBefore) {
-						channelHistory->setUnreadCount(channelHistory->unreadCount - 1);
+					if (channelHistory->unreadCount() > 0 && i->v >= channelHistory->inboxReadBefore) {
+						channelHistory->setUnreadCount(channelHistory->unreadCount() - 1);
 					}
 				}
 			}
diff --git a/Telegram/SourceFiles/application.cpp b/Telegram/SourceFiles/application.cpp
index f107dc93c..d3e7a9c7c 100644
--- a/Telegram/SourceFiles/application.cpp
+++ b/Telegram/SourceFiles/application.cpp
@@ -962,6 +962,15 @@ void AppClass::onSwitchDebugMode() {
 	}
 }
 
+void AppClass::onSwitchWorkMode() {
+	Global::SetDialogsModeEnabled(!Global::DialogsModeEnabled());
+	Global::SetDialogsMode(Dialogs::Mode::All);
+	Local::writeUserSettings();
+	cSetRestarting(true);
+	cSetRestartingToSettings(true);
+	App::quit();
+}
+
 void AppClass::onSwitchTestMode() {
 	if (cTestMode()) {
 		QFile(cWorkingDir() + qsl("tdata/withtestmode")).remove();
diff --git a/Telegram/SourceFiles/application.h b/Telegram/SourceFiles/application.h
index 3e0a37e56..ae51569e8 100644
--- a/Telegram/SourceFiles/application.h
+++ b/Telegram/SourceFiles/application.h
@@ -195,6 +195,7 @@ public slots:
 	void photoUpdated(const FullMsgId &msgId, bool silent, const MTPInputFile &file);
 
 	void onSwitchDebugMode();
+	void onSwitchWorkMode();
 	void onSwitchTestMode();
 
 	void killDownloadSessions();
diff --git a/Telegram/SourceFiles/boxes/addcontactbox.cpp b/Telegram/SourceFiles/boxes/addcontactbox.cpp
index f2d85354d..7e58787bc 100644
--- a/Telegram/SourceFiles/boxes/addcontactbox.cpp
+++ b/Telegram/SourceFiles/boxes/addcontactbox.cpp
@@ -1183,7 +1183,7 @@ EditChannelBox::EditChannelBox(ChannelData *channel) : AbstractBox()
 , _saveTitleRequestId(0)
 , _saveDescriptionRequestId(0)
 , _saveSignRequestId(0) {
-	connect(App::main(), SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(peerUpdated(PeerData*)));
+	connect(App::main(), SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(peerUpdated(PeerData*)));
 
 	setMouseTracking(true);
 
diff --git a/Telegram/SourceFiles/boxes/contactsbox.cpp b/Telegram/SourceFiles/boxes/contactsbox.cpp
index b00b68f8a..e9fdcfc65 100644
--- a/Telegram/SourceFiles/boxes/contactsbox.cpp
+++ b/Telegram/SourceFiles/boxes/contactsbox.cpp
@@ -1757,7 +1757,7 @@ MembersInner::MembersInner(ChannelData *channel, MembersFilter filter) : TWidget
 , _about(_aboutWidth)
 , _aboutHeight(0) {
 	connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
-	connect(App::main(), SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)));
+	connect(App::main(), SIGNAL(peerNameChanged(PeerData*,const PeerData::Names&,const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)));
 	connect(App::main(), SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(peerUpdated(PeerData*)));
 
 	refresh();
diff --git a/Telegram/SourceFiles/dialogs/dialogs_common.h b/Telegram/SourceFiles/dialogs/dialogs_common.h
index a7f7de725..dd45fea13 100644
--- a/Telegram/SourceFiles/dialogs/dialogs_common.h
+++ b/Telegram/SourceFiles/dialogs/dialogs_common.h
@@ -26,9 +26,14 @@ class Row;
 using RowsByLetter = QMap<QChar, Row*>;
 
 enum class SortMode {
-	Date,
-	Name,
-	Add
+	Date = 0x00,
+	Name = 0x01,
+	Add  = 0x02,
+};
+
+enum class Mode {
+	All       = 0x00,
+	Important = 0x01,
 };
 
 } // namespace Dialogs
diff --git a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp
index af6ef8ebe..7c262f3aa 100644
--- a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp
+++ b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.cpp
@@ -71,72 +71,85 @@ void IndexedList::adjustByPos(const RowsByLetter &links) {
 	}
 }
 
-
 void IndexedList::peerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
+	t_assert(_sortMode != SortMode::Date);
 	if (_sortMode == SortMode::Name) {
-		Row *mainRow = _list.adjustByName(peer);
-		if (!mainRow) return;
-
-		History *history = mainRow->history();
-
-		PeerData::NameFirstChars toRemove = oldChars, toAdd;
-		for_const (auto ch, peer->chars) {
-			auto j = toRemove.find(ch);
-			if (j == toRemove.cend()) {
-				toAdd.insert(ch);
-			} else {
-				toRemove.erase(j);
-				if (auto list = _index.value(ch)) {
-					list->adjustByName(peer);
-				}
-			}
-		}
-		for_const (auto ch, toRemove) {
-			if (auto list = _index.value(ch)) {
-				list->del(peer->id, mainRow);
-			}
-		}
-		if (!toAdd.isEmpty()) {
-			for_const (auto ch, toAdd) {
-				auto j = _index.find(ch);
-				if (j == _index.cend()) {
-					j = _index.insert(ch, new List(_sortMode));
-				}
-				j.value()->addByName(history);
-			}
-		}
+		adjustByName(peer, oldNames, oldChars);
 	} else {
-		auto mainRow = _list.getRow(peer->id);
-		if (!mainRow) return;
+		adjustNames(Dialogs::Mode::All, peer, oldNames, oldChars);
+	}
+}
 
-		History *history = mainRow->history();
+void IndexedList::peerNameChanged(Mode list, PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
+	t_assert(_sortMode == SortMode::Date);
+	adjustNames(list, peer, oldNames, oldChars);
+}
 
-		PeerData::NameFirstChars toRemove = oldChars, toAdd;
-		for_const (auto ch, peer->chars) {
-			auto j = toRemove.find(ch);
-			if (j == toRemove.cend()) {
-				toAdd.insert(ch);
-			} else {
-				toRemove.erase(j);
-			}
-		}
-		for_const (auto ch, toRemove) {
-			if (_sortMode == SortMode::Date) {
-				history->removeChatListEntryByLetter(ch);
-			}
+void IndexedList::adjustByName(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
+	Row *mainRow = _list.adjustByName(peer);
+	if (!mainRow) return;
+
+	History *history = mainRow->history();
+
+	PeerData::NameFirstChars toRemove = oldChars, toAdd;
+	for_const (auto ch, peer->chars) {
+		auto j = toRemove.find(ch);
+		if (j == toRemove.cend()) {
+			toAdd.insert(ch);
+		} else {
+			toRemove.erase(j);
 			if (auto list = _index.value(ch)) {
-				list->del(peer->id, mainRow);
+				list->adjustByName(peer);
 			}
 		}
+	}
+	for_const (auto ch, toRemove) {
+		if (auto list = _index.value(ch)) {
+			list->del(peer->id, mainRow);
+		}
+	}
+	if (!toAdd.isEmpty()) {
 		for_const (auto ch, toAdd) {
 			auto j = _index.find(ch);
 			if (j == _index.cend()) {
 				j = _index.insert(ch, new List(_sortMode));
 			}
-			Row *row = j.value()->addToEnd(history);
-			if (_sortMode == SortMode::Date) {
-				history->addChatListEntryByLetter(ch, row);
-			}
+			j.value()->addByName(history);
+		}
+	}
+}
+
+void IndexedList::adjustNames(Mode list, PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
+	auto mainRow = _list.getRow(peer->id);
+	if (!mainRow) return;
+
+	History *history = mainRow->history();
+
+	PeerData::NameFirstChars toRemove = oldChars, toAdd;
+	for_const (auto ch, peer->chars) {
+		auto j = toRemove.find(ch);
+		if (j == toRemove.cend()) {
+			toAdd.insert(ch);
+		} else {
+			toRemove.erase(j);
+		}
+	}
+	for_const (auto ch, toRemove) {
+		if (_sortMode == SortMode::Date) {
+			history->removeChatListEntryByLetter(list, ch);
+		}
+		if (auto list = _index.value(ch)) {
+			list->del(peer->id, mainRow);
+		}
+	}
+	for_const (auto ch, toAdd) {
+		auto j = _index.find(ch);
+		if (j == _index.cend()) {
+			j = _index.insert(ch, new List(_sortMode));
+		}
+		Row *row = j.value()->addToEnd(history);
+		if (_sortMode == SortMode::Date) {
+			history->addChatListEntryByLetter(list, ch, row);
 		}
 	}
 }
diff --git a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h
index e0acfd0aa..6a5967977 100644
--- a/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h
+++ b/Telegram/SourceFiles/dialogs/dialogs_indexed_list.h
@@ -34,7 +34,13 @@ public:
 	RowsByLetter addToEnd(History *history);
 	Row *addByName(History *history);
 	void adjustByPos(const RowsByLetter &links);
+
+	// For sortMode != SortMode::Date
 	void peerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
+
+	//For sortMode == SortMode::Date
+	void peerNameChanged(Mode list, PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
+
 	void del(const PeerData *peer, Row *replacedBy = nullptr);
 	void clear();
 
@@ -71,6 +77,9 @@ public:
 	iterator find(int y, int h) { return all().find(y, h); }
 
 private:
+	void adjustByName(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
+	void adjustNames(Mode list, PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars);
+
 	SortMode _sortMode;
 	List _list;
 	using Index = QMap<QChar, List*>;
diff --git a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp
index 855bede73..d9c5fbc22 100644
--- a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp
+++ b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp
@@ -170,41 +170,48 @@ void paintUnreadBadge(Painter &p, const QRect &rect, bool active, bool muted) {
 	p.drawPixmap(rect.x() + sizehalf + bar, rect.y(), unreadBadgeStyle->right[index]);
 }
 
+void paintUnreadCount(Painter &p, const QString &text, int top, int w, bool active, bool muted, int *outAvailableWidth) {
+	int unreadWidth = st::dlgUnreadFont->width(text);
+	int unreadRectWidth = unreadWidth + 2 * st::dlgUnreadPaddingHor;
+	int unreadRectHeight = st::dlgUnreadHeight;
+	accumulate_max(unreadRectWidth, unreadRectHeight);
+
+	int unreadRectLeft = w - st::dlgPaddingHor - unreadRectWidth;
+	int unreadRectTop =top;
+	if (outAvailableWidth) {
+		*outAvailableWidth -= unreadRectWidth + st::dlgUnreadPaddingHor;
+	}
+
+	paintUnreadBadge(p, QRect(unreadRectLeft, unreadRectTop, unreadRectWidth, unreadRectHeight), active, muted);
+
+	p.setFont(st::dlgUnreadFont);
+	p.setPen(active ? st::dlgActiveUnreadColor : st::dlgUnreadColor);
+	p.drawText(unreadRectLeft + (unreadRectWidth - unreadWidth) / 2, unreadRectTop + st::dlgUnreadTop + st::dlgUnreadFont->ascent, text);
+}
+
 } // namepsace
 
 void RowPainter::paint(Painter &p, const Row *row, int w, bool active, bool selected, bool onlyBackground) {
 	auto history = row->history();
 	auto item = history->lastMsg;
 	paintRow(p, history, item, w, active, selected, onlyBackground, [&p, w, active, history, item](int nameleft, int namewidth) {
-		int32 lastWidth = namewidth, unread = history->unreadCount;
+		int32 unread = history->unreadCount();
 		if (history->peer->migrateFrom()) {
 			if (History *h = App::historyLoaded(history->peer->migrateFrom()->id)) {
-				unread += h->unreadCount;
+				unread += h->unreadCount();
 			}
 		}
+		int availableWidth = namewidth;
 		int texttop = st::dlgPaddingVer + st::dlgFont->height + st::dlgSep;
 		if (unread) {
-			QString unreadStr = QString::number(unread);
-			int unreadWidth = st::dlgUnreadFont->width(unreadStr);
-			int unreadRectWidth = unreadWidth + 2 * st::dlgUnreadPaddingHor;
-			int unreadRectHeight = st::dlgUnreadHeight;
-			accumulate_max(unreadRectWidth, unreadRectHeight);
-
-			int unreadRectLeft = w - st::dlgPaddingHor - unreadRectWidth;
-			int unreadRectTop = texttop + st::dlgHistFont->ascent - st::dlgUnreadFont->ascent - st::dlgUnreadTop;
-			lastWidth -= unreadRectWidth + st::dlgUnreadPaddingHor;
-
-			paintUnreadBadge(p, QRect(unreadRectLeft, unreadRectTop, unreadRectWidth, unreadRectHeight), active, history->mute);
-
-			p.setFont(st::dlgUnreadFont);
-			p.setPen(active ? st::dlgActiveUnreadColor : st::dlgUnreadColor);
-			p.drawText(unreadRectLeft + (unreadRectWidth - unreadWidth) / 2, unreadRectTop + st::dlgUnreadTop + st::dlgUnreadFont->ascent, unreadStr);
+			int unreadTop = texttop + st::dlgHistFont->ascent - st::dlgUnreadFont->ascent - st::dlgUnreadTop;
+			paintUnreadCount(p, QString::number(unread), unreadTop, w, active, history->mute(), &availableWidth);
 		}
 		if (history->typing.isEmpty() && history->sendActions.isEmpty()) {
-			item->drawInDialog(p, QRect(nameleft, texttop, lastWidth, st::dlgFont->height), active, history->textCachedFor, history->lastItemTextCache);
+			item->drawInDialog(p, QRect(nameleft, texttop, availableWidth, st::dlgFont->height), active, history->textCachedFor, history->lastItemTextCache);
 		} else {
 			p.setPen(active ? st::dlgActiveColor : st::dlgSystemColor);
-			history->typingText.drawElided(p, nameleft, texttop, lastWidth);
+			history->typingText.drawElided(p, nameleft, texttop, availableWidth);
 		}
 	});
 }
@@ -218,6 +225,28 @@ void RowPainter::paint(Painter &p, const FakeRow *row, int w, bool active, bool
 	});
 }
 
+void paintImportantSwitch(Painter &p, Mode current, int w, bool selected, bool onlyBackground) {
+	p.fillRect(0, 0, w, st::dlgImportantHeight, selected ? st::dlgHoverBG : st::white);
+	if (onlyBackground) {
+		return;
+	}
+
+	p.setFont(st::semiboldFont);
+	p.setPen(st::black);
+
+	int unreadTop = (st::dlgImportantHeight - st::dlgUnreadHeight) / 2;
+	bool mutedHidden = (current == Dialogs::Mode::Important);
+	QString text = mutedHidden ? qsl("Show all chats") : qsl("Hide muted chats");
+	int textBaseline = unreadTop + st::dlgUnreadTop + st::dlgUnreadFont->ascent;
+	p.drawText(st::dlgPaddingHor, textBaseline, text);
+
+	if (mutedHidden) {
+		if (int32 unread = App::histories().unreadMutedCount()) {
+			paintUnreadCount(p, QString::number(unread), unreadTop, w, false, true, nullptr);
+		}
+	}
+}
+
 namespace {
 
 using StyleSheets = OrderedSet<StyleSheet**>;
diff --git a/Telegram/SourceFiles/dialogs/dialogs_layout.h b/Telegram/SourceFiles/dialogs/dialogs_layout.h
index fd1908625..1c0de56a1 100644
--- a/Telegram/SourceFiles/dialogs/dialogs_layout.h
+++ b/Telegram/SourceFiles/dialogs/dialogs_layout.h
@@ -33,6 +33,8 @@ public:
 	static void paint(Painter &p, const FakeRow *row, int w, bool active, bool selected, bool onlyBackground);
 };
 
+void paintImportantSwitch(Painter &p, Mode current, int w, bool selected, bool onlyBackground);
+
 // This will be moved somewhere outside as soon as anyone starts using that.
 class StyleSheet {
 public:
diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp
index 81274388d..297ba54d4 100644
--- a/Telegram/SourceFiles/dialogswidget.cpp
+++ b/Telegram/SourceFiles/dialogswidget.cpp
@@ -40,6 +40,9 @@ DialogsInner::DialogsInner(QWidget *parent, MainWidget *main) : SplittedWidget(p
 , contacts(std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Name))
 , _addContactLnk(this, lang(lng_add_contact_button))
 , _cancelSearchInPeer(this, st::btnCancelSearch) {
+	if (Global::DialogsModeEnabled()) {
+		importantDialogs = std_::make_unique<Dialogs::IndexedList>(Dialogs::SortMode::Date);
+	}
 	connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
 	connect(main, SIGNAL(peerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)), this, SLOT(onPeerNameChanged(PeerData*, const PeerData::Names&, const PeerData::NameFirstChars&)));
 	connect(main, SIGNAL(peerPhotoChanged(PeerData*)), this, SLOT(onPeerPhotoChanged(PeerData*)));
@@ -50,16 +53,20 @@ DialogsInner::DialogsInner(QWidget *parent, MainWidget *main) : SplittedWidget(p
 	refresh();
 }
 
-int32 DialogsInner::filteredOffset() const {
+int DialogsInner::dialogsOffset() const {
+	return importantDialogs ? st::dlgImportantHeight : 0;
+}
+
+int DialogsInner::filteredOffset() const {
 	return _hashtagResults.size() * st::mentionHeight;
 }
 
-int32 DialogsInner::peopleOffset() const {
+int DialogsInner::peopleOffset() const {
 	return filteredOffset() + (_filterResults.size() * st::dlgHeight) + st::searchedBarHeight;
 }
 
-int32 DialogsInner::searchedOffset() const {
-	int32 result = peopleOffset() + (_peopleResults.isEmpty() ? 0 : ((_peopleResults.size() * st::dlgHeight) + st::searchedBarHeight));
+int DialogsInner::searchedOffset() const {
+	int result = peopleOffset() + (_peopleResults.isEmpty() ? 0 : ((_peopleResults.size() * st::dlgHeight) + st::searchedBarHeight));
 	if (_searchInPeer) result += st::dlgHeight;
 	return result;
 }
@@ -76,16 +83,22 @@ void DialogsInner::paintRegion(Painter &p, const QRegion &region, bool paintingO
 	}
 
 	if (_state == DefaultState) {
-		int32 otherStart = dialogs->size() * st::dlgHeight;
-		PeerData *active = App::main()->activePeer(), *selected = _menuPeer ? _menuPeer : (sel ? sel->history()->peer : 0);
+		QRect dialogsClip = r;
+		if (importantDialogs) {
+			Dialogs::Layout::paintImportantSwitch(p, Global::DialogsMode(), fullWidth(), _importantSwitchSel, paintingOther);
+			dialogsClip.translate(0, -st::dlgImportantHeight);
+			p.translate(0, st::dlgImportantHeight);
+		}
+		int32 otherStart = shownDialogs()->size() * st::dlgHeight;
+		PeerData *active = App::main()->activePeer(), *selected = _menuPeer ? _menuPeer : (_sel ? _sel->history()->peer : 0);
 		if (otherStart) {
-			dialogs->all().paint(p, fullWidth(), r.top(), r.top() + r.height(), active, selected, paintingOther);
+			shownDialogs()->all().paint(p, fullWidth(), dialogsClip.top(), dialogsClip.top() + dialogsClip.height(), active, selected, paintingOther);
 		}
 		if (!otherStart) {
-			p.fillRect(r, st::white->b);
+			p.fillRect(dialogsClip, st::white);
 			if (!paintingOther) {
-				p.setFont(st::noContactsFont->f);
-				p.setPen(st::noContactsColor->p);
+				p.setFont(st::noContactsFont);
+				p.setPen(st::noContactsColor);
 				p.drawText(QRect(0, 0, fullWidth(), st::noContactsHeight - (cContactsReceived() ? st::noContactsFont->height : 0)), lang(cContactsReceived() ? lng_no_chats : lng_contacts_loading), style::al_center);
 			}
 		}
@@ -223,13 +236,11 @@ void DialogsInner::paintRegion(Painter &p, const QRegion &region, bool paintingO
 	}
 }
 
-void DialogsInner::peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool act, bool sel, bool onlyBackground) const {
+void DialogsInner::peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool active, bool selected, bool onlyBackground) const {
 	QRect fullRect(0, 0, w, st::dlgHeight);
-	p.fillRect(fullRect, (act ? st::dlgActiveBG : (sel ? st::dlgHoverBG : st::dlgBG))->b);
+	p.fillRect(fullRect, active ? st::dlgActiveBG : (selected ? st::dlgHoverBG : st::dlgBG));
 	if (onlyBackground) return;
 
-	History *history = App::history(peer->id);
-
 	PeerData *userpicPeer = (peer->migrateTo() ? peer->migrateTo() : peer);
 	userpicPeer->paintUserpicLeft(p, st::dlgPhotoSize, st::dlgPaddingHor, st::dlgPaddingVer, fullWidth());
 
@@ -239,21 +250,21 @@ void DialogsInner::peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool a
 
 	// draw chat icon
 	if (peer->isChat() || peer->isMegagroup()) {
-		p.drawPixmap(QPoint(rectForName.left() + st::dlgChatImgPos.x(), rectForName.top() + st::dlgChatImgPos.y()), App::sprite(), (act ? st::dlgActiveChatImg : st::dlgChatImg));
+		p.drawSprite(QPoint(rectForName.left() + st::dlgChatImgPos.x(), rectForName.top() + st::dlgChatImgPos.y()), (active ? st::dlgActiveChatImg : st::dlgChatImg));
 		rectForName.setLeft(rectForName.left() + st::dlgImgSkip);
 	} else if (peer->isChannel()) {
-		p.drawPixmap(QPoint(rectForName.left() + st::dlgChannelImgPos.x(), rectForName.top() + st::dlgChannelImgPos.y()), App::sprite(), (act ? st::dlgActiveChannelImg : st::dlgChannelImg));
+		p.drawSprite(QPoint(rectForName.left() + st::dlgChannelImgPos.x(), rectForName.top() + st::dlgChannelImgPos.y()), (active ? st::dlgActiveChannelImg : st::dlgChannelImg));
 		rectForName.setLeft(rectForName.left() + st::dlgImgSkip);
 	}
 	if (peer->isVerified()) {
 		rectForName.setWidth(rectForName.width() - st::verifiedCheck.pxWidth() - st::verifiedCheckPos.x());
-		p.drawSprite(rectForName.topLeft() + QPoint(qMin(peer->dialogName().maxWidth(), rectForName.width()), 0) + st::verifiedCheckPos, (act ? st::verifiedCheckInv : st::verifiedCheck));
+		p.drawSprite(rectForName.topLeft() + QPoint(qMin(peer->dialogName().maxWidth(), rectForName.width()), 0) + st::verifiedCheckPos, (active ? st::verifiedCheckInv : st::verifiedCheck));
 	}
 
 	QRect tr(nameleft, st::dlgPaddingVer + st::dlgFont->height + st::dlgSep, namewidth, st::dlgFont->height);
 	p.setFont(st::dlgHistFont->f);
 	QString username = peer->userName();
-	if (!act && username.toLower().startsWith(_peopleQuery)) {
+	if (!active && username.toLower().startsWith(_peopleQuery)) {
 		QString first = '@' + username.mid(0, _peopleQuery.size()), second = username.mid(_peopleQuery.size());
 		int32 w = st::dlgHistFont->width(first);
 		if (w >= tr.width()) {
@@ -266,11 +277,11 @@ void DialogsInner::peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool a
 			p.drawText(tr.left() + w, tr.top() + st::dlgHistFont->ascent, st::dlgHistFont->elided(second, tr.width() - w));
 		}
 	} else {
-		p.setPen((act ? st::dlgActiveColor : st::dlgSystemColor)->p);
+		p.setPen((active ? st::dlgActiveColor : st::dlgSystemColor)->p);
 		p.drawText(tr.left(), tr.top() + st::dlgHistFont->ascent, st::dlgHistFont->elided('@' + username, tr.width()));
 	}
 
-	p.setPen((act ? st::dlgActiveColor : st::dlgNameColor)->p);
+	p.setPen((active ? st::dlgActiveColor : st::dlgNameColor)->p);
 	peer->dialogName().drawElided(p, rectForName.left(), rectForName.top(), rectForName.width());
 }
 
@@ -308,24 +319,26 @@ void DialogsInner::activate() {
 
 void DialogsInner::mouseMoveEvent(QMouseEvent *e) {
 	lastMousePos = mapToGlobal(e->pos());
-	selByMouse = true;
+	_selByMouse = true;
 	onUpdateSelected(true);
 }
 
 void DialogsInner::onUpdateSelected(bool force) {
 	QPoint mouse(mapFromGlobal(lastMousePos));
-	if ((!force && !rect().contains(mouse)) || !selByMouse) return;
+	if ((!force && !rect().contains(mouse)) || !_selByMouse) return;
 
 	int w = width(), mouseY = mouse.y();
 	_overDelete = false;
 	if (_state == DefaultState) {
-		auto newSel = dialogs->rowAtY(mouseY, st::dlgHeight);
-		int otherStart = dialogs->size() * st::dlgHeight;
-		if (newSel != sel) {
+		auto newImportantSwitchSel = (importantDialogs && mouseY >= 0 && mouseY < dialogsOffset());
+		mouseY -= dialogsOffset();
+		auto newSel = newImportantSwitchSel ? nullptr : shownDialogs()->rowAtY(mouseY, st::dlgHeight);
+		if (newSel != _sel || newImportantSwitchSel != _importantSwitchSel) {
 			updateSelectedRow();
-			sel = newSel;
+			_sel = newSel;
+			_importantSwitchSel = newImportantSwitchSel;
 			updateSelectedRow();
-			setCursor(sel ? style::cur_pointer : style::cur_default);
+			setCursor(_sel ? style::cur_pointer : style::cur_default);
 		}
 	} else if (_state == FilteredState || _state == SearchedState) {
 		if (!_hashtagResults.isEmpty()) {
@@ -384,7 +397,7 @@ void DialogsInner::onUpdateSelected(bool force) {
 
 void DialogsInner::mousePressEvent(QMouseEvent *e) {
 	lastMousePos = mapToGlobal(e->pos());
-	selByMouse = true;
+	_selByMouse = true;
 	onUpdateSelected(true);
 	if (e->button() == Qt::LeftButton) {
 		choosePeer();
@@ -411,25 +424,46 @@ void DialogsInner::onDialogRowReplaced(Dialogs::Row *oldRow, Dialogs::Row *newRo
 			}
 		}
 	}
-	if (sel == oldRow) {
-		sel = newRow;
+	if (_sel == oldRow) {
+		_sel = newRow;
 	}
 }
 
 void DialogsInner::createDialog(History *history) {
-	bool creating = !history->inChatList();
+	bool creating = !history->inChatList(Dialogs::Mode::All);
 	if (creating) {
-		Dialogs::Row *mainRow = history->addToChatList(dialogs.get());
+		Dialogs::Row *mainRow = history->addToChatList(Dialogs::Mode::All, dialogs.get());
 		contactsNoDialogs->del(history->peer, mainRow);
 	}
-	RefPair(int32, movedFrom, int32, movedTo) = history->adjustByPosInChatsList(dialogs.get());
+	if (importantDialogs && !history->inChatList(Dialogs::Mode::Important) && !history->mute()) {
+		if (Global::DialogsMode() == Dialogs::Mode::Important) {
+			creating = true;
+		}
+		history->addToChatList(Dialogs::Mode::Important, importantDialogs.get());
+	}
+
+	auto changed = history->adjustByPosInChatList(Dialogs::Mode::All, dialogs.get());
+
+	if (importantDialogs) {
+		if (history->mute()) {
+			if (Global::DialogsMode() == Dialogs::Mode::Important) {
+				return;
+			}
+		} else {
+			auto importantChanged = history->adjustByPosInChatList(Dialogs::Mode::Important, importantDialogs.get());
+			if (Global::DialogsMode() == Dialogs::Mode::Important) {
+				changed = importantChanged;
+			}
+		}
+	}
+	RefPair(int32, movedFrom, int32, movedTo) = changed;
 
 	emit dialogMoved(movedFrom, movedTo);
 
 	if (creating) {
 		refresh();
 	} else if (_state == DefaultState && movedFrom != movedTo) {
-		update(0, qMin(movedFrom, movedTo), fullWidth(), qAbs(movedFrom - movedTo) + st::dlgHeight);
+		update(0, dialogsOffset() + qMin(movedFrom, movedTo), fullWidth(), qAbs(movedFrom - movedTo) + st::dlgHeight);
 	}
 }
 
@@ -438,10 +472,13 @@ void DialogsInner::removeDialog(History *history) {
 	if (history->peer == _menuPeer && _menu) {
 		_menu->deleteLater();
 	}
-	if (sel && sel->history() == history) {
-		sel = nullptr;
+	if (_sel && _sel->history() == history) {
+		_sel = nullptr;
+	}
+	history->removeFromChatList(Dialogs::Mode::All, dialogs.get());
+	if (importantDialogs) {
+		history->removeFromChatList(Dialogs::Mode::Important, importantDialogs.get());
 	}
-	history->removeFromChatList(dialogs.get());
 	history->clearNotifications();
 	if (App::wnd()) App::wnd()->notifyClear(history);
 	if (contacts->contains(history->peer->id)) {
@@ -457,14 +494,18 @@ void DialogsInner::removeDialog(History *history) {
 	refresh();
 }
 
-void DialogsInner::dlgUpdated(Dialogs::Row *row) {
+void DialogsInner::dlgUpdated(Dialogs::Mode list, Dialogs::Row *row) {
 	if (_state == DefaultState) {
-		update(0, row->pos() * st::dlgHeight, fullWidth(), st::dlgHeight);
+		if (Global::DialogsMode() == list) {
+			update(0, dialogsOffset() + row->pos() * st::dlgHeight, fullWidth(), st::dlgHeight);
+		}
 	} else if (_state == FilteredState || _state == SearchedState) {
-		for (int32 i = 0, l = _filterResults.size(); i < l; ++i) {
-			if (_filterResults.at(i)->history() == row->history()) {
-				update(0, i * st::dlgHeight, fullWidth(), st::dlgHeight);
-				break;
+		if (list == Dialogs::Mode::All) {
+			for (int32 i = 0, l = _filterResults.size(); i < l; ++i) {
+				if (_filterResults.at(i)->history() == row->history()) {
+					update(0, i * st::dlgHeight, fullWidth(), st::dlgHeight);
+					break;
+				}
 			}
 		}
 	}
@@ -472,8 +513,8 @@ void DialogsInner::dlgUpdated(Dialogs::Row *row) {
 
 void DialogsInner::dlgUpdated(History *history, MsgId msgId) {
 	if (_state == DefaultState) {
-		if (auto row = dialogs->getRow(history->peer->id)) {
-			update(0, row->pos() * st::dlgHeight, fullWidth(), st::dlgHeight);
+		if (auto row = shownDialogs()->getRow(history->peer->id)) {
+			update(0, dialogsOffset() + row->pos() * st::dlgHeight, fullWidth(), st::dlgHeight);
 		}
 	} else if (_state == FilteredState || _state == SearchedState) {
 		int32 cnt = 0, add = filteredOffset();
@@ -517,12 +558,14 @@ void DialogsInner::updateSelectedRow(PeerData *peer) {
 	if (_state == DefaultState) {
 		if (peer) {
 			if (History *h = App::historyLoaded(peer->id)) {
-				if (h->inChatList()) {
-					update(0, h->posInChatList() * st::dlgHeight, fullWidth(), st::dlgHeight);
+				if (h->inChatList(Global::DialogsMode())) {
+					update(0, dialogsOffset() + h->posInChatList(Global::DialogsMode()) * st::dlgHeight, fullWidth(), st::dlgHeight);
 				}
 			}
-		} else if (sel) {
-			update(0, sel->pos() * st::dlgHeight, fullWidth(), st::dlgHeight);
+		} else if (_sel) {
+			update(0, dialogsOffset() + _sel->pos() * st::dlgHeight, fullWidth(), st::dlgHeight);
+		} else if (_importantSwitchSel) {
+			update(0, 0, fullWidth(), st::dlgImportantHeight);
 		}
 	} else if (_state == FilteredState || _state == SearchedState) {
 		if (peer) {
@@ -547,10 +590,15 @@ void DialogsInner::updateSelectedRow(PeerData *peer) {
 
 void DialogsInner::leaveEvent(QEvent *e) {
 	setMouseTracking(false);
-	selByMouse = false;
-	if (sel || _filteredSel >= 0 || _hashtagSel >= 0 || _searchedSel >= 0 || _peopleSel >= 0) {
+	clearSelection();
+}
+
+void DialogsInner::clearSelection() {
+	_selByMouse = false;
+	if (_sel || _filteredSel >= 0 || _hashtagSel >= 0 || _searchedSel >= 0 || _peopleSel >= 0) {
 		updateSelectedRow();
-		sel = 0;
+		_sel = nullptr;
+		_importantSwitchSel = false;
 		_filteredSel = _searchedSel = _peopleSel = _hashtagSel = -1;
 		setCursor(style::cur_default);
 	}
@@ -569,13 +617,13 @@ void DialogsInner::contextMenuEvent(QContextMenuEvent *e) {
 
 	if (e->reason() == QContextMenuEvent::Mouse) {
 		lastMousePos = e->globalPos();
-		selByMouse = true;
+		_selByMouse = true;
 		onUpdateSelected(true);
 	}
 
 	History *history = 0;
 	if (_state == DefaultState) {
-		if (sel) history = sel->history();
+		if (_sel) history = _sel->history();
 	} else if (_state == FilteredState || _state == SearchedState) {
 		if (_filteredSel >= 0 && _filteredSel < _filterResults.size()) {
 			history = _filterResults[_filteredSel]->history();
@@ -691,7 +739,7 @@ void DialogsInner::onMenuDestroyed(QObject *obj) {
 		}
 		lastMousePos = QCursor::pos();
 		if (rect().contains(mapFromGlobal(lastMousePos))) {
-			selByMouse = true;
+			_selByMouse = true;
 			setMouseTracking(true);
 			onUpdateSelected(true);
 		}
@@ -707,7 +755,10 @@ void DialogsInner::onParentGeometryChanged() {
 }
 
 void DialogsInner::onPeerNameChanged(PeerData *peer, const PeerData::Names &oldNames, const PeerData::NameFirstChars &oldChars) {
-	dialogs->peerNameChanged(peer, oldNames, oldChars);
+	dialogs->peerNameChanged(Dialogs::Mode::All, peer, oldNames, oldChars);
+	if (importantDialogs) {
+		importantDialogs->peerNameChanged(Dialogs::Mode::Important, peer, oldNames, oldChars);
+	}
 	contactsNoDialogs->peerNameChanged(peer, oldNames, oldChars);
 	contacts->peerNameChanged(peer, oldNames, oldChars);
 	update();
@@ -889,10 +940,10 @@ void DialogsInner::peerUpdated(PeerData *peer) {
 
 PeerData *DialogsInner::updateFromParentDrag(QPoint globalPos) {
 	lastMousePos = globalPos;
-	selByMouse = true;
+	_selByMouse = true;
 	onUpdateSelected(true);
 	if (_state == DefaultState) {
-		if (sel) return sel->history()->peer;
+		if (_sel) return _sel->history()->peer;
 	} else if (_state == FilteredState || _state == SearchedState) {
 		if (_filteredSel >= 0 && _filteredSel < _filterResults.size()) {
 			return _filterResults[_filteredSel]->history()->peer;
@@ -976,8 +1027,9 @@ void DialogsInner::dialogsReceived(const QVector<MTPDialog> &added) {
 	}
 
 	if (App::wnd()) App::wnd()->updateCounter();
-	if (!sel && !dialogs->isEmpty()) {
-		sel = *dialogs->cbegin();
+	if (!_sel && !shownDialogs()->isEmpty()) {
+		_sel = *shownDialogs()->cbegin();
+		_importantSwitchSel = false;
 	}
 	refresh();
 }
@@ -1042,7 +1094,7 @@ void DialogsInner::peopleReceived(const QString &query, const QVector<MTPPeer> &
 	for (QVector<MTPPeer>::const_iterator i = people.cbegin(), e = people.cend(); i != e; ++i) {
 		PeerId peerId = peerFromMTP(*i);
 		if (History *h = App::historyLoaded(peerId)) {
-			if (h->inChatList()) {
+			if (h->inChatList(Dialogs::Mode::All)) {
 				continue; // skip existing chats
 			}
 		}
@@ -1069,16 +1121,17 @@ void DialogsInner::notify_userIsContactChanged(UserData *user, bool fromThisApp)
 	if (user->contact > 0) {
 		History *history = App::history(user->id);
 		contacts->addByName(history);
-		if (auto row = dialogs->getRow(user->id)) {
+		if (auto row = shownDialogs()->getRow(user->id)) {
 			if (fromThisApp) {
-				sel = row;
+				_sel = row;
+				_importantSwitchSel = false;
 			}
-		} else {
+		} else if (!dialogs->contains(user->id)) {
 			contactsNoDialogs->addByName(history);
 		}
 	} else {
-		if (sel && sel->history()->peer == user) {
-			sel = nullptr;
+		if (_sel && _sel->history()->peer == user) {
+			_sel = nullptr;
 		}
 		contactsNoDialogs->del(user);
 		contacts->del(user);
@@ -1086,19 +1139,54 @@ void DialogsInner::notify_userIsContactChanged(UserData *user, bool fromThisApp)
 	refresh();
 }
 
+void DialogsInner::notify_historyMuteUpdated(History *history) {
+	if (!importantDialogs || !history->inChatList(Dialogs::Mode::All)) return;
+
+	if (history->mute()) {
+		if (_sel && _sel->history() == history && Global::DialogsMode() == Dialogs::Mode::Important) {
+			_sel = nullptr;
+		}
+		history->removeFromChatList(Dialogs::Mode::Important, importantDialogs.get());
+		if (Global::DialogsMode() != Dialogs::Mode::Important) {
+			return;
+		}
+		refresh();
+	} else {
+		bool creating = !history->inChatList(Dialogs::Mode::Important);
+		if (creating) {
+			history->addToChatList(Dialogs::Mode::Important, importantDialogs.get());
+		}
+
+		auto changed = history->adjustByPosInChatList(Dialogs::Mode::All, dialogs.get());
+
+		if (Global::DialogsMode() != Dialogs::Mode::Important) {
+			return;
+		}
+		RefPair(int32, movedFrom, int32, movedTo) = changed;
+
+		emit dialogMoved(movedFrom, movedTo);
+
+		if (creating) {
+			refresh();
+		} else if (_state == DefaultState && movedFrom != movedTo) {
+			update(0, dialogsOffset() + qMin(movedFrom, movedTo), fullWidth(), qAbs(movedFrom - movedTo) + st::dlgHeight);
+		}
+	}
+}
+
 void DialogsInner::refresh(bool toTop) {
 	int32 h = 0;
 	if (_state == DefaultState) {
-		h = (dialogs->size()/* + contactsNoDialogs->size()*/) * st::dlgHeight;
-		if (h) {
-			if (!_addContactLnk.isHidden()) _addContactLnk.hide();
-		} else {
+		if (shownDialogs()->isEmpty()) {
 			h = st::noContactsHeight;
 			if (cContactsReceived()) {
 				if (_addContactLnk.isHidden()) _addContactLnk.show();
 			} else {
 				if (!_addContactLnk.isHidden()) _addContactLnk.hide();
 			}
+		} else {
+			h = dialogsOffset() + shownDialogs()->size() * st::dlgHeight;
+			if (!_addContactLnk.isHidden()) _addContactLnk.hide();
 		}
 	} else {
 		if (!_addContactLnk.isHidden()) _addContactLnk.hide();
@@ -1117,10 +1205,11 @@ void DialogsInner::refresh(bool toTop) {
 }
 
 void DialogsInner::setMouseSel(bool msel, bool toTop) {
-	selByMouse = msel;
-	if (!selByMouse && toTop) {
+	_selByMouse = msel;
+	if (!_selByMouse && toTop) {
 		if (_state == DefaultState) {
-			sel = !dialogs->isEmpty() ? *dialogs->cbegin() : nullptr;
+			_sel = !shownDialogs()->isEmpty() ? *shownDialogs()->cbegin() : nullptr;
+			_importantSwitchSel = false;
 		} else if (_state == FilteredState || _state == SearchedState) { // don't select first elem in search
 			_filteredSel = _peopleSel = _searchedSel = _hashtagSel = -1;
 			setCursor(style::cur_default);
@@ -1182,25 +1271,39 @@ void DialogsInner::clearFilter() {
 
 void DialogsInner::selectSkip(int32 direction) {
 	if (_state == DefaultState) {
-		if (!sel) {
-			if (!dialogs->isEmpty() && direction > 0) {
-				sel = *dialogs->cbegin();
+		if (_importantSwitchSel) {
+			if (!shownDialogs()->isEmpty() && direction > 0) {
+				_sel = *shownDialogs()->cbegin();
+				_importantSwitchSel = false;
+			} else {
+				return;
+			}
+		} else if (!_sel) {
+			if (importantDialogs) {
+				_importantSwitchSel = true;
+			} else if (!shownDialogs()->isEmpty() && direction > 0) {
+				_sel = *shownDialogs()->cbegin();
 			} else {
 				return;
 			}
 		} else if (direction > 0) {
-			auto next = dialogs->cfind(sel);
-			if (++next != dialogs->cend()) {
-				sel = *next;
+			auto next = shownDialogs()->cfind(_sel);
+			if (++next != shownDialogs()->cend()) {
+				_sel = *next;
 			}
 		} else {
-			auto prev = dialogs->cfind(sel);
-			if (prev != dialogs->cbegin()) {
-				sel = *(--prev);
+			auto prev = shownDialogs()->cfind(_sel);
+			if (prev != shownDialogs()->cbegin()) {
+				_sel = *(--prev);
+			} else if (importantDialogs) {
+				_importantSwitchSel = true;
+				_sel = nullptr;
 			}
 		}
-		int32 fromY = sel->pos() * st::dlgHeight;
-		emit mustScrollTo(fromY, fromY + st::dlgHeight);
+		if (_importantSwitchSel || _sel) {
+			int fromY = _importantSwitchSel ? 0 : (dialogsOffset() + _sel->pos() * st::dlgHeight);
+			emit mustScrollTo(fromY, fromY + st::dlgHeight);
+		}
 	} else if (_state == FilteredState || _state == SearchedState) {
 		if (_hashtagResults.isEmpty() && _filterResults.isEmpty() && _peopleResults.isEmpty() && _searchResults.isEmpty()) return;
 		if ((_hashtagSel < 0 || _hashtagSel >= _hashtagResults.size()) &&
@@ -1249,8 +1352,8 @@ void DialogsInner::selectSkip(int32 direction) {
 void DialogsInner::scrollToPeer(const PeerId &peer, MsgId msgId) {
 	int32 fromY = -1;
 	if (_state == DefaultState) {
-		if (auto row = dialogs->getRow(peer)) {
-			fromY = row->pos() * st::dlgHeight;
+		if (auto row = shownDialogs()->getRow(peer)) {
+			fromY = dialogsOffset() + row->pos() * st::dlgHeight;
 		}
 	} else if (_state == FilteredState || _state == SearchedState) {
 		if (msgId) {
@@ -1278,24 +1381,31 @@ void DialogsInner::scrollToPeer(const PeerId &peer, MsgId msgId) {
 void DialogsInner::selectSkipPage(int32 pixels, int32 direction) {
 	int toSkip = pixels / int(st::dlgHeight);
 	if (_state == DefaultState) {
-		if (!sel) {
-			if (direction > 0 && !dialogs->isEmpty()) {
-				sel = *dialogs->cbegin();
+		if (!_sel) {
+			if (direction > 0 && !shownDialogs()->isEmpty()) {
+				_sel = *shownDialogs()->cbegin();
+				_importantSwitchSel = false;
 			} else {
 				return;
 			}
 		}
 		if (direction > 0) {
-			for (auto i = dialogs->cfind(sel), end = dialogs->cend(); i != end && (toSkip--); ++i) {
-				sel = *i;
+			for (auto i = shownDialogs()->cfind(_sel), end = shownDialogs()->cend(); i != end && (toSkip--); ++i) {
+				_sel = *i;
 			}
 		} else {
-			for (auto i = dialogs->cfind(sel), b = dialogs->cbegin(); i != b && (toSkip--); --i) {
-				sel = *i;
+			for (auto i = shownDialogs()->cfind(_sel), b = shownDialogs()->cbegin(); i != b && (toSkip--); --i) {
+				_sel = *i;
+			}
+			if (toSkip && importantDialogs) {
+				_importantSwitchSel = true;
+				_sel = nullptr;
 			}
 		}
-		int fromY = sel->pos() * st::dlgHeight;
-		emit mustScrollTo(fromY, fromY + st::dlgHeight);
+		if (_importantSwitchSel || _sel) {
+			int fromY = (_importantSwitchSel ? 0 : (dialogsOffset() + _sel->pos() * st::dlgHeight));
+			emit mustScrollTo(fromY, fromY + st::dlgHeight);
+		}
 	} else {
 		return selectSkip(direction * toSkip);
 	}
@@ -1308,9 +1418,9 @@ void DialogsInner::loadPeerPhotos(int32 yFrom) {
 	int32 yTo = yFrom + parentWidget()->height() * 5;
 	MTP::clearLoaderPriorities();
 	if (_state == DefaultState) {
-		int32 otherStart = dialogs->size() * st::dlgHeight;
+		int32 otherStart = shownDialogs()->size() * st::dlgHeight;
 		if (yFrom < otherStart) {
-			for (auto i = dialogs->cfind(yFrom, st::dlgHeight), end = dialogs->cend(); i != end; ++i) {
+			for (auto i = shownDialogs()->cfind(yFrom, st::dlgHeight), end = shownDialogs()->cend(); i != end; ++i) {
 				if (((*i)->pos() * st::dlgHeight) >= yTo) {
 					break;
 				}
@@ -1357,10 +1467,23 @@ void DialogsInner::loadPeerPhotos(int32 yFrom) {
 }
 
 bool DialogsInner::choosePeer() {
-	History *history = 0;
+	History *history = nullptr;
 	MsgId msgId = ShowAtUnreadMsgId;
 	if (_state == DefaultState) {
-		if (sel) history = sel->history();
+		if (_importantSwitchSel && importantDialogs) {
+			clearSelection();
+			if (Global::DialogsMode() == Dialogs::Mode::All) {
+				Global::SetDialogsMode(Dialogs::Mode::Important);
+			} else {
+				Global::SetDialogsMode(Dialogs::Mode::All);
+			}
+			Local::writeUserSettings();
+			refresh();
+			_importantSwitchSel = true;
+			return true;
+		} else if (_sel) {
+			history = _sel->history();
+		}
 	} else if (_state == FilteredState || _state == SearchedState) {
 		if (_hashtagSel >= 0 && _hashtagSel < _hashtagResults.size()) {
 			QString hashtag = _hashtagResults.at(_hashtagSel);
@@ -1379,7 +1502,7 @@ bool DialogsInner::choosePeer() {
 				Local::writeRecentHashtagsAndBots();
 				emit refreshHashtags();
 
-				selByMouse = true;
+				_selByMouse = true;
 				onUpdateSelected(true);
 			} else {
 				saveRecentHashtags('#' + hashtag);
@@ -1406,7 +1529,7 @@ bool DialogsInner::choosePeer() {
 			emit searchResultChosen();
 		}
 		updateSelectedRow();
-		sel = 0;
+		_sel = nullptr;
 		_filteredSel = _peopleSel = _searchedSel = _hashtagSel = -1;
 		return true;
 	}
@@ -1442,7 +1565,7 @@ void DialogsInner::saveRecentHashtags(const QString &text) {
 }
 
 void DialogsInner::destroyData() {
-	sel = nullptr;
+	_sel = nullptr;
 	_hashtagSel = -1;
 	_hashtagResults.clear();
 	_filteredSel = -1;
@@ -1453,6 +1576,9 @@ void DialogsInner::destroyData() {
 	contacts = nullptr;
 	contactsNoDialogs = nullptr;
 	dialogs = nullptr;
+	if (importantDialogs) {
+		importantDialogs = nullptr;
+	}
 }
 
 void DialogsInner::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&outPeer, MsgId &outMsg) const {
@@ -1462,9 +1588,9 @@ void DialogsInner::peerBefore(const PeerData *inPeer, MsgId inMsg, PeerData *&ou
 		return;
 	}
 	if (_state == DefaultState) {
-		if (auto row = dialogs->getRow(inPeer->id)) {
-			auto i = dialogs->cfind(row);
-			if (i != dialogs->cbegin()) {
+		if (auto row = shownDialogs()->getRow(inPeer->id)) {
+			auto i = shownDialogs()->cfind(row);
+			if (i != shownDialogs()->cbegin()) {
 				outPeer = (*(--i))->history()->peer;
 				outMsg = ShowAtUnreadMsgId;
 				return;
@@ -1536,9 +1662,9 @@ void DialogsInner::peerAfter(const PeerData *inPeer, MsgId inMsg, PeerData *&out
 		return;
 	}
 	if (_state == DefaultState) {
-		if (auto row = dialogs->getRow(inPeer->id)) {
-			auto i = dialogs->cfind(row) + 1;
-			if (i != dialogs->cend()) {
+		if (auto row = shownDialogs()->getRow(inPeer->id)) {
+			auto i = shownDialogs()->cfind(row) + 1;
+			if (i != shownDialogs()->cend()) {
 				outPeer = (*i)->history()->peer;
 				outMsg = ShowAtUnreadMsgId;
 				return;
@@ -1697,19 +1823,19 @@ void DialogsWidget::activate() {
 }
 
 void DialogsWidget::createDialog(History *history) {
-	bool creating = !history->inChatList();
+	bool creating = !history->inChatList(Dialogs::Mode::All);
 	_inner.createDialog(history);
 	if (creating && history->peer->migrateFrom()) {
 		if (History *h = App::historyLoaded(history->peer->migrateFrom()->id)) {
-			if (h->inChatList()) {
+			if (h->inChatList(Dialogs::Mode::All)) {
 				removeDialog(h);
 			}
 		}
 	}
 }
 
-void DialogsWidget::dlgUpdated(Dialogs::Row *row) {
-	_inner.dlgUpdated(row);
+void DialogsWidget::dlgUpdated(Dialogs::Mode list, Dialogs::Row *row) {
+	_inner.dlgUpdated(list, row);
 }
 
 void DialogsWidget::dlgUpdated(History *row, MsgId msgId) {
@@ -1795,6 +1921,10 @@ void DialogsWidget::notify_userIsContactChanged(UserData *user, bool fromThisApp
 	_inner.notify_userIsContactChanged(user, fromThisApp);
 }
 
+void DialogsWidget::notify_historyMuteUpdated(History *history) {
+	_inner.notify_historyMuteUpdated(history);
+}
+
 void DialogsWidget::unreadCountsReceived(const QVector<MTPDialog> &dialogs) {
 	for (QVector<MTPDialog>::const_iterator i = dialogs.cbegin(), e = dialogs.cend(); i != e; ++i) {
 		switch (i->type()) {
@@ -1802,7 +1932,7 @@ void DialogsWidget::unreadCountsReceived(const QVector<MTPDialog> &dialogs) {
 			const auto &d(i->c_dialog());
 			if (History *h = App::historyLoaded(peerFromMTP(d.vpeer))) {
 				App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, h);
-				if (d.vunread_count.v >= h->unreadCount) {
+				if (d.vunread_count.v >= h->unreadCount()) {
 					h->setUnreadCount(d.vunread_count.v, false);
 					h->inboxReadBefore = d.vread_inbox_max_id.v + 1;
 				}
@@ -1820,7 +1950,7 @@ void DialogsWidget::unreadCountsReceived(const QVector<MTPDialog> &dialogs) {
 				}
 				App::main()->applyNotifySetting(MTP_notifyPeer(d.vpeer), d.vnotify_settings, h);
 				int32 unreadCount = h->isMegagroup() ? d.vunread_count.v : d.vunread_important_count.v;
-				if (unreadCount >= h->unreadCount) {
+				if (unreadCount >= h->unreadCount()) {
 					h->setUnreadCount(unreadCount, false);
 					h->inboxReadBefore = d.vread_inbox_max_id.v + 1;
 				}
diff --git a/Telegram/SourceFiles/dialogswidget.h b/Telegram/SourceFiles/dialogswidget.h
index 4def9e106..fe5b33e62 100644
--- a/Telegram/SourceFiles/dialogswidget.h
+++ b/Telegram/SourceFiles/dialogswidget.h
@@ -54,10 +54,6 @@ public:
 
 	void contactsReceived(const QVector<MTPContact> &contacts);
 
-	int32 filteredOffset() const;
-	int32 peopleOffset() const;
-	int32 searchedOffset() const;
-
 	void mouseMoveEvent(QMouseEvent *e);
 	void mousePressEvent(QMouseEvent *e);
 	void resizeEvent(QResizeEvent *e);
@@ -65,14 +61,11 @@ public:
 	void leaveEvent(QEvent *e);
 	void contextMenuEvent(QContextMenuEvent *e);
 
-	void peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool act, bool sel, bool onlyBackground) const;
-	void searchInPeerPaint(Painter &p, int32 w, bool onlyBackground) const;
-
 	void selectSkip(int32 direction);
 	void selectSkipPage(int32 pixels, int32 direction);
 
 	void createDialog(History *history);
-	void dlgUpdated(Dialogs::Row *row);
+	void dlgUpdated(Dialogs::Mode list, Dialogs::Row *row);
 	void dlgUpdated(History *row, MsgId msgId);
 	void removeDialog(History *history);
 
@@ -125,6 +118,7 @@ public:
 	void updateNotifySettings(PeerData *peer);
 
 	void notify_userIsContactChanged(UserData *user, bool fromThisApp);
+	void notify_historyMuteUpdated(History *history);
 
 	~DialogsInner();
 
@@ -165,17 +159,34 @@ protected:
 
 private:
 
+	int dialogsOffset() const;
+	int filteredOffset() const;
+	int peopleOffset() const;
+	int searchedOffset() const;
+
+	void peopleResultPaint(PeerData *peer, Painter &p, int32 w, bool active, bool selected, bool onlyBackground) const;
+	void searchInPeerPaint(Painter &p, int32 w, bool onlyBackground) const;
+
+	void clearSelection();
 	void clearSearchResults(bool clearPeople = true);
 	void updateSelectedRow(PeerData *peer = 0);
 	bool menuPeerMuted();
 	void contextBlockDone(QPair<UserData*, bool> data, const MTPBool &result);
 
+	Dialogs::IndexedList *shownDialogs() const {
+		return (Global::DialogsMode() == Dialogs::Mode::Important) ? importantDialogs.get() : dialogs.get();
+	}
+
 	using DialogsList = std_::unique_ptr<Dialogs::IndexedList>;
 	DialogsList dialogs;
+	DialogsList importantDialogs;
+
 	DialogsList contactsNoDialogs;
 	DialogsList contacts;
-	Dialogs::Row *sel = nullptr;
-	bool selByMouse = false;
+
+	bool _importantSwitchSel = false;
+	Dialogs::Row *_sel = nullptr;
+	bool _selByMouse = false;
 
 	QString _filter, _hashtagFilter;
 
@@ -244,7 +255,7 @@ public:
 
 	void loadDialogs();
 	void createDialog(History *history);
-	void dlgUpdated(Dialogs::Row *row);
+	void dlgUpdated(Dialogs::Mode list, Dialogs::Row *row);
 	void dlgUpdated(History *row, MsgId msgId);
 
 	void dialogsToUp();
@@ -276,6 +287,7 @@ public:
 	}
 
 	void notify_userIsContactChanged(UserData *user, bool fromThisApp);
+	void notify_historyMuteUpdated(History *history);
 
 signals:
 
diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp
index 252404416..fd74f4b6a 100644
--- a/Telegram/SourceFiles/facades.cpp
+++ b/Telegram/SourceFiles/facades.cpp
@@ -34,297 +34,301 @@ Q_DECLARE_METATYPE(Qt::MouseButton);
 
 namespace App {
 
-	void sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyTo) {
-		if (MainWidget *m = main()) m->sendBotCommand(peer, cmd, replyTo);
-	}
-
-	bool insertBotCommand(const QString &cmd, bool specialGif) {
-		if (MainWidget *m = main()) return m->insertBotCommand(cmd, specialGif);
-		return false;
-	}
-
-	void activateBotCommand(const HistoryItem *msg, int row, int col) {
-		const HistoryMessageReplyMarkup::Button *button = nullptr;
-		if (auto markup = msg->Get<HistoryMessageReplyMarkup>()) {
-			if (row < markup->rows.size()) {
-				const auto &buttonRow(markup->rows.at(row));
-				if (col < buttonRow.size()) {
-					button = &buttonRow.at(col);
-				}
-			}
-		}
-		if (!button) return;
-
-		switch (button->type) {
-		case HistoryMessageReplyMarkup::Button::Default: {
-			// Copy string before passing it to the sending method
-			// because the original button can be destroyed inside.
-			MsgId replyTo = (msg->id > 0) ? msg->id : 0;
-			sendBotCommand(msg->history()->peer, QString(button->text), replyTo);
-		} break;
-
-		case HistoryMessageReplyMarkup::Button::Callback: {
-			if (MainWidget *m = main()) {
-				m->app_sendBotCallback(button, msg, row, col);
-			}
-		} break;
-
-		case HistoryMessageReplyMarkup::Button::Url: {
-			auto url = QString::fromUtf8(button->data);
-			HiddenUrlClickHandler(url).onClick(Qt::LeftButton);
-		} break;
-
-		case HistoryMessageReplyMarkup::Button::RequestLocation: {
-			Ui::showLayer(new InformBox(lang(lng_bot_share_location_unavailable)));
-		} break;
-
-		case HistoryMessageReplyMarkup::Button::RequestPhone: {
-			SharePhoneConfirmBox *box = new SharePhoneConfirmBox(msg->history()->peer);
-			box->connect(box, SIGNAL(confirmed(PeerData*)), App::main(), SLOT(onSharePhoneWithBot(PeerData*)));
-			Ui::showLayer(box);
-		} break;
-
-		case HistoryMessageReplyMarkup::Button::SwitchInline: {
-			if (MainWidget *m = App::main()) {
-				if (UserData *bot = msg->history()->peer->asUser()) {
-					auto tryFastSwitch = [bot, &button]() -> bool {
-						if (bot->botInfo && bot->botInfo->inlineReturnPeerId) {
-							if (Notify::switchInlineBotButtonReceived(QString::fromUtf8(button->data))) {
-								return true;
-							}
-						}
-						return false;
-					};
-					if (!tryFastSwitch()) {
-						m->inlineSwitchLayer('@' + bot->username + ' ' + QString::fromUtf8(button->data));
-					}
-				}
-			}
-		} break;
-		}
-	}
-
-	void searchByHashtag(const QString &tag, PeerData *inPeer) {
-		if (MainWidget *m = main()) m->searchMessages(tag + ' ', (inPeer && inPeer->isChannel() && !inPeer->isMegagroup()) ? inPeer : 0);
-	}
-
-	void openPeerByName(const QString &username, MsgId msgId, const QString &startToken) {
-		if (MainWidget *m = main()) m->openPeerByName(username, msgId, startToken);
-	}
-
-	void joinGroupByHash(const QString &hash) {
-		if (MainWidget *m = main()) m->joinGroupByHash(hash);
-	}
-
-	void stickersBox(const QString &name) {
-		if (MainWidget *m = main()) m->stickersBox(MTP_inputStickerSetShortName(MTP_string(name)));
-	}
-
-	void openLocalUrl(const QString &url) {
-		if (MainWidget *m = main()) m->openLocalUrl(url);
-	}
-
-	bool forward(const PeerId &peer, ForwardWhatMessages what) {
-		if (MainWidget *m = main()) return m->onForward(peer, what);
-		return false;
-	}
-
-	void removeDialog(History *history) {
-		if (MainWidget *m = main()) {
-			m->removeDialog(history);
-		}
-	}
-
-	void showSettings() {
-		if (Window *w = wnd()) {
-			w->showSettings();
-		}
-	}
-
-	void activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button) {
-		if (Window *w = wnd()) {
-			qRegisterMetaType<ClickHandlerPtr>();
-			qRegisterMetaType<Qt::MouseButton>();
-			QMetaObject::invokeMethod(w, "app_activateClickHandler", Qt::QueuedConnection, Q_ARG(ClickHandlerPtr, handler), Q_ARG(Qt::MouseButton, button));
-		}
-	}
-
-	void logOutDelayed() {
-		if (Window *w = App::wnd()) {
-			QMetaObject::invokeMethod(w, "onLogoutSure", Qt::QueuedConnection);
-		}
-	}
-
+void sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyTo) {
+	if (MainWidget *m = main()) m->sendBotCommand(peer, cmd, replyTo);
 }
 
+bool insertBotCommand(const QString &cmd, bool specialGif) {
+	if (MainWidget *m = main()) return m->insertBotCommand(cmd, specialGif);
+	return false;
+}
+
+void activateBotCommand(const HistoryItem *msg, int row, int col) {
+	const HistoryMessageReplyMarkup::Button *button = nullptr;
+	if (auto markup = msg->Get<HistoryMessageReplyMarkup>()) {
+		if (row < markup->rows.size()) {
+			const auto &buttonRow(markup->rows.at(row));
+			if (col < buttonRow.size()) {
+				button = &buttonRow.at(col);
+			}
+		}
+	}
+	if (!button) return;
+
+	switch (button->type) {
+	case HistoryMessageReplyMarkup::Button::Default: {
+		// Copy string before passing it to the sending method
+		// because the original button can be destroyed inside.
+		MsgId replyTo = (msg->id > 0) ? msg->id : 0;
+		sendBotCommand(msg->history()->peer, QString(button->text), replyTo);
+	} break;
+
+	case HistoryMessageReplyMarkup::Button::Callback: {
+		if (MainWidget *m = main()) {
+			m->app_sendBotCallback(button, msg, row, col);
+		}
+	} break;
+
+	case HistoryMessageReplyMarkup::Button::Url: {
+		auto url = QString::fromUtf8(button->data);
+		HiddenUrlClickHandler(url).onClick(Qt::LeftButton);
+	} break;
+
+	case HistoryMessageReplyMarkup::Button::RequestLocation: {
+		Ui::showLayer(new InformBox(lang(lng_bot_share_location_unavailable)));
+	} break;
+
+	case HistoryMessageReplyMarkup::Button::RequestPhone: {
+		SharePhoneConfirmBox *box = new SharePhoneConfirmBox(msg->history()->peer);
+		box->connect(box, SIGNAL(confirmed(PeerData*)), App::main(), SLOT(onSharePhoneWithBot(PeerData*)));
+		Ui::showLayer(box);
+	} break;
+
+	case HistoryMessageReplyMarkup::Button::SwitchInline: {
+		if (MainWidget *m = App::main()) {
+			if (UserData *bot = msg->history()->peer->asUser()) {
+				auto tryFastSwitch = [bot, &button]() -> bool {
+					if (bot->botInfo && bot->botInfo->inlineReturnPeerId) {
+						if (Notify::switchInlineBotButtonReceived(QString::fromUtf8(button->data))) {
+							return true;
+						}
+					}
+					return false;
+				};
+				if (!tryFastSwitch()) {
+					m->inlineSwitchLayer('@' + bot->username + ' ' + QString::fromUtf8(button->data));
+				}
+			}
+		}
+	} break;
+	}
+}
+
+void searchByHashtag(const QString &tag, PeerData *inPeer) {
+	if (MainWidget *m = main()) m->searchMessages(tag + ' ', (inPeer && inPeer->isChannel() && !inPeer->isMegagroup()) ? inPeer : 0);
+}
+
+void openPeerByName(const QString &username, MsgId msgId, const QString &startToken) {
+	if (MainWidget *m = main()) m->openPeerByName(username, msgId, startToken);
+}
+
+void joinGroupByHash(const QString &hash) {
+	if (MainWidget *m = main()) m->joinGroupByHash(hash);
+}
+
+void stickersBox(const QString &name) {
+	if (MainWidget *m = main()) m->stickersBox(MTP_inputStickerSetShortName(MTP_string(name)));
+}
+
+void openLocalUrl(const QString &url) {
+	if (MainWidget *m = main()) m->openLocalUrl(url);
+}
+
+bool forward(const PeerId &peer, ForwardWhatMessages what) {
+	if (MainWidget *m = main()) return m->onForward(peer, what);
+	return false;
+}
+
+void removeDialog(History *history) {
+	if (MainWidget *m = main()) {
+		m->removeDialog(history);
+	}
+}
+
+void showSettings() {
+	if (Window *w = wnd()) {
+		w->showSettings();
+	}
+}
+
+void activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button) {
+	if (Window *w = wnd()) {
+		qRegisterMetaType<ClickHandlerPtr>();
+		qRegisterMetaType<Qt::MouseButton>();
+		QMetaObject::invokeMethod(w, "app_activateClickHandler", Qt::QueuedConnection, Q_ARG(ClickHandlerPtr, handler), Q_ARG(Qt::MouseButton, button));
+	}
+}
+
+void logOutDelayed() {
+	if (Window *w = App::wnd()) {
+		QMetaObject::invokeMethod(w, "onLogoutSure", Qt::QueuedConnection);
+	}
+}
+
+} // namespace App
+
 namespace Ui {
 
-	void showMediaPreview(DocumentData *document) {
+void showMediaPreview(DocumentData *document) {
+	if (Window *w = App::wnd()) {
+		w->ui_showMediaPreview(document);
+	}
+}
+
+void showMediaPreview(PhotoData *photo) {
+	if (Window *w = App::wnd()) {
+		w->ui_showMediaPreview(photo);
+	}
+}
+
+void hideMediaPreview() {
+	if (Window *w = App::wnd()) {
+		w->ui_hideMediaPreview();
+	}
+}
+
+void showLayer(LayeredWidget *box, ShowLayerOptions options) {
+	if (Window *w = App::wnd()) {
+		w->ui_showLayer(box, options);
+	} else {
+		delete box;
+	}
+}
+
+void hideLayer(bool fast) {
+	if (Window *w = App::wnd()) w->ui_showLayer(0, ShowLayerOptions(CloseOtherLayers) | (fast ? ForceFastShowLayer : AnimatedShowLayer));
+}
+
+bool isLayerShown() {
+	if (Window *w = App::wnd()) return w->ui_isLayerShown();
+	return false;
+}
+
+bool isMediaViewShown() {
+	if (Window *w = App::wnd()) return w->ui_isMediaViewShown();
+	return false;
+}
+
+bool isInlineItemBeingChosen() {
+	if (MainWidget *m = App::main()) return m->ui_isInlineItemBeingChosen();
+	return false;
+}
+
+void repaintHistoryItem(const HistoryItem *item) {
+	if (!item) return;
+	if (MainWidget *m = App::main()) m->ui_repaintHistoryItem(item);
+}
+
+void repaintInlineItem(const InlineBots::Layout::ItemBase *layout) {
+	if (!layout) return;
+	if (MainWidget *m = App::main()) m->ui_repaintInlineItem(layout);
+}
+
+bool isInlineItemVisible(const InlineBots::Layout::ItemBase *layout) {
+	if (MainWidget *m = App::main()) return m->ui_isInlineItemVisible(layout);
+	return false;
+}
+
+void autoplayMediaInlineAsync(const FullMsgId &msgId) {
+	if (MainWidget *m = App::main()) {
+		QMetaObject::invokeMethod(m, "ui_autoplayMediaInlineAsync", Qt::QueuedConnection, Q_ARG(qint32, msgId.channel), Q_ARG(qint32, msgId.msg));
+	}
+}
+
+void showPeerHistory(const PeerId &peer, MsgId msgId, bool back) {
+	if (MainWidget *m = App::main()) m->ui_showPeerHistory(peer, msgId, back);
+}
+
+void showPeerHistoryAsync(const PeerId &peer, MsgId msgId) {
+	if (MainWidget *m = App::main()) {
+		QMetaObject::invokeMethod(m, "ui_showPeerHistoryAsync", Qt::QueuedConnection, Q_ARG(quint64, peer), Q_ARG(qint32, msgId));
+	}
+}
+
+PeerData *getPeerForMouseAction() {
+	if (Window *w = App::wnd()) {
+		return w->ui_getPeerForMouseAction();
+	}
+	return nullptr;
+}
+
+bool hideWindowNoQuit() {
+	if (!App::quitting()) {
 		if (Window *w = App::wnd()) {
-			w->ui_showMediaPreview(document);
-		}
-	}
-
-	void showMediaPreview(PhotoData *photo) {
-		if (Window *w = App::wnd()) {
-			w->ui_showMediaPreview(photo);
-		}
-	}
-
-	void hideMediaPreview() {
-		if (Window *w = App::wnd()) {
-			w->ui_hideMediaPreview();
-		}
-	}
-
-	void showLayer(LayeredWidget *box, ShowLayerOptions options) {
-		if (Window *w = App::wnd()) {
-			w->ui_showLayer(box, options);
-		} else {
-			delete box;
-		}
-	}
-
-	void hideLayer(bool fast) {
-		if (Window *w = App::wnd()) w->ui_showLayer(0, ShowLayerOptions(CloseOtherLayers) | (fast ? ForceFastShowLayer : AnimatedShowLayer));
-	}
-
-	bool isLayerShown() {
-		if (Window *w = App::wnd()) return w->ui_isLayerShown();
-		return false;
-	}
-
-	bool isMediaViewShown() {
-		if (Window *w = App::wnd()) return w->ui_isMediaViewShown();
-		return false;
-	}
-
-	bool isInlineItemBeingChosen() {
-		if (MainWidget *m = App::main()) return m->ui_isInlineItemBeingChosen();
-		return false;
-	}
-
-	void repaintHistoryItem(const HistoryItem *item) {
-		if (!item) return;
-		if (MainWidget *m = App::main()) m->ui_repaintHistoryItem(item);
-	}
-
-	void repaintInlineItem(const InlineBots::Layout::ItemBase *layout) {
-		if (!layout) return;
-		if (MainWidget *m = App::main()) m->ui_repaintInlineItem(layout);
-	}
-
-	bool isInlineItemVisible(const InlineBots::Layout::ItemBase *layout) {
-		if (MainWidget *m = App::main()) return m->ui_isInlineItemVisible(layout);
-		return false;
-	}
-
-	void autoplayMediaInlineAsync(const FullMsgId &msgId) {
-		if (MainWidget *m = App::main()) {
-			QMetaObject::invokeMethod(m, "ui_autoplayMediaInlineAsync", Qt::QueuedConnection, Q_ARG(qint32, msgId.channel), Q_ARG(qint32, msgId.msg));
-		}
-	}
-
-	void showPeerHistory(const PeerId &peer, MsgId msgId, bool back) {
-		if (MainWidget *m = App::main()) m->ui_showPeerHistory(peer, msgId, back);
-	}
-
-	void showPeerHistoryAsync(const PeerId &peer, MsgId msgId) {
-		if (MainWidget *m = App::main()) {
-			QMetaObject::invokeMethod(m, "ui_showPeerHistoryAsync", Qt::QueuedConnection, Q_ARG(quint64, peer), Q_ARG(qint32, msgId));
-		}
-	}
-
-	PeerData *getPeerForMouseAction() {
-		if (Window *w = App::wnd()) {
-			return w->ui_getPeerForMouseAction();
-		}
-		return nullptr;
-	}
-
-	bool hideWindowNoQuit() {
-		if (!App::quitting()) {
-			if (Window *w = App::wnd()) {
-				if (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray) {
-					return w->minimizeToTray();
-				} else if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
-					w->hide();
-					w->updateIsActive(Global::OfflineBlurTimeout());
-					w->updateGlobalMenu();
-					return true;
-				}
+			if (cWorkMode() == dbiwmTrayOnly || cWorkMode() == dbiwmWindowAndTray) {
+				return w->minimizeToTray();
+			} else if (cPlatform() == dbipMac || cPlatform() == dbipMacOld) {
+				w->hide();
+				w->updateIsActive(Global::OfflineBlurTimeout());
+				w->updateGlobalMenu();
+				return true;
 			}
 		}
-		return false;
 	}
-
+	return false;
 }
 
+} // namespace Ui
+
 namespace Notify {
 
-	void userIsBotChanged(UserData *user) {
-		if (MainWidget *m = App::main()) m->notify_userIsBotChanged(user);
-	}
-
-	void userIsContactChanged(UserData *user, bool fromThisApp) {
-		if (MainWidget *m = App::main()) m->notify_userIsContactChanged(user, fromThisApp);
-	}
-
-	void botCommandsChanged(UserData *user) {
-		if (MainWidget *m = App::main()) m->notify_botCommandsChanged(user);
-	}
-
-	void inlineBotRequesting(bool requesting) {
-		if (MainWidget *m = App::main()) m->notify_inlineBotRequesting(requesting);
-	}
-
-	void replyMarkupUpdated(const HistoryItem *item) {
-		if (MainWidget *m = App::main()) {
-			m->notify_replyMarkupUpdated(item);
-		}
-	}
-
-	void inlineKeyboardMoved(const HistoryItem *item, int oldKeyboardTop, int newKeyboardTop) {
-		if (MainWidget *m = App::main()) {
-			m->notify_inlineKeyboardMoved(item, oldKeyboardTop, newKeyboardTop);
-		}
-	}
-
-	bool switchInlineBotButtonReceived(const QString &query) {
-		if (MainWidget *m = App::main()) {
-			return m->notify_switchInlineBotButtonReceived(query);
-		}
-		return false;
-	}
-
-	void migrateUpdated(PeerData *peer) {
-		if (MainWidget *m = App::main()) m->notify_migrateUpdated(peer);
-	}
-
-	void clipStopperHidden(ClipStopperType type) {
-		if (MainWidget *m = App::main()) m->notify_clipStopperHidden(type);
-	}
-
-	void historyItemLayoutChanged(const HistoryItem *item) {
-		if (MainWidget *m = App::main()) m->notify_historyItemLayoutChanged(item);
-	}
-
-	void inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout) {
-		if (MainWidget *m = App::main()) m->notify_inlineItemLayoutChanged(layout);
-	}
-
-	void handlePendingHistoryUpdate() {
-		if (MainWidget *m = App::main()) {
-			m->notify_handlePendingHistoryUpdate();
-		}
-		for_const (HistoryItem *item, Global::PendingRepaintItems()) {
-			Ui::repaintHistoryItem(item);
-		}
-		Global::RefPendingRepaintItems().clear();
-	}
-
+void userIsBotChanged(UserData *user) {
+	if (MainWidget *m = App::main()) m->notify_userIsBotChanged(user);
 }
 
+void userIsContactChanged(UserData *user, bool fromThisApp) {
+	if (MainWidget *m = App::main()) m->notify_userIsContactChanged(user, fromThisApp);
+}
+
+void botCommandsChanged(UserData *user) {
+	if (MainWidget *m = App::main()) m->notify_botCommandsChanged(user);
+}
+
+void inlineBotRequesting(bool requesting) {
+	if (MainWidget *m = App::main()) m->notify_inlineBotRequesting(requesting);
+}
+
+void replyMarkupUpdated(const HistoryItem *item) {
+	if (MainWidget *m = App::main()) {
+		m->notify_replyMarkupUpdated(item);
+	}
+}
+
+void inlineKeyboardMoved(const HistoryItem *item, int oldKeyboardTop, int newKeyboardTop) {
+	if (MainWidget *m = App::main()) {
+		m->notify_inlineKeyboardMoved(item, oldKeyboardTop, newKeyboardTop);
+	}
+}
+
+bool switchInlineBotButtonReceived(const QString &query) {
+	if (MainWidget *m = App::main()) {
+		return m->notify_switchInlineBotButtonReceived(query);
+	}
+	return false;
+}
+
+void migrateUpdated(PeerData *peer) {
+	if (MainWidget *m = App::main()) m->notify_migrateUpdated(peer);
+}
+
+void clipStopperHidden(ClipStopperType type) {
+	if (MainWidget *m = App::main()) m->notify_clipStopperHidden(type);
+}
+
+void historyItemLayoutChanged(const HistoryItem *item) {
+	if (MainWidget *m = App::main()) m->notify_historyItemLayoutChanged(item);
+}
+
+void inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout) {
+	if (MainWidget *m = App::main()) m->notify_inlineItemLayoutChanged(layout);
+}
+
+void historyMuteUpdated(History *history) {
+	if (MainWidget *m = App::main()) m->notify_historyMuteUpdated(history);
+}
+
+void handlePendingHistoryUpdate() {
+	if (MainWidget *m = App::main()) {
+		m->notify_handlePendingHistoryUpdate();
+	}
+	for_const (HistoryItem *item, Global::PendingRepaintItems()) {
+		Ui::repaintHistoryItem(item);
+	}
+	Global::RefPendingRepaintItems().clear();
+}
+
+} // namespace Notify
+
 #define DefineReadOnlyVar(Namespace, Type, Name) const Type &Name() { \
 	t_assert_full(Namespace##Data != 0, #Namespace "Data != nullptr in " #Namespace "::" #Name, __FILE__, __LINE__); \
 	return Namespace##Data->Name; \
@@ -341,235 +345,238 @@ void Set##Name(const Type &Name) { \
 }
 
 namespace Sandbox {
+namespace internal {
 
-	namespace internal {
+struct Data {
+	QString LangSystemISO;
+	int32 LangSystem = languageDefault;
 
-		struct Data {
-			QString LangSystemISO;
-			int32 LangSystem = languageDefault;
+	QByteArray LastCrashDump;
+	ConnectionProxy PreLaunchProxy;
+};
 
-			QByteArray LastCrashDump;
-			ConnectionProxy PreLaunchProxy;
-		};
+} // namespace internal
+} // namespace Sandbox
 
-	}
-
-}
-Sandbox::internal::Data *SandboxData = 0;
+Sandbox::internal::Data *SandboxData = nullptr;
 uint64 SandboxUserTag = 0;
 
 namespace Sandbox {
 
-	bool CheckBetaVersionDir() {
-		QFile beta(cExeDir() + qsl("TelegramBeta_data/tdata/beta"));
-		if (cBetaVersion()) {
-			cForceWorkingDir(cExeDir() + qsl("TelegramBeta_data/"));
-			QDir().mkpath(cWorkingDir() + qstr("tdata"));
-			if (*BetaPrivateKey) {
-				cSetBetaPrivateKey(QByteArray(BetaPrivateKey));
-			}
-			if (beta.open(QIODevice::WriteOnly)) {
-				QDataStream dataStream(&beta);
-				dataStream.setVersion(QDataStream::Qt_5_3);
-				dataStream << quint64(cRealBetaVersion()) << cBetaPrivateKey();
-			} else {
-				LOG(("FATAL: Could not open '%1' for writing private key!").arg(beta.fileName()));
-				return false;
-			}
-		} else if (beta.exists()) {
-			cForceWorkingDir(cExeDir() + qsl("TelegramBeta_data/"));
-			if (beta.open(QIODevice::ReadOnly)) {
-				QDataStream dataStream(&beta);
-				dataStream.setVersion(QDataStream::Qt_5_3);
-
-				quint64 v;
-				QByteArray k;
-				dataStream >> v >> k;
-				if (dataStream.status() == QDataStream::Ok) {
-					cSetBetaVersion(qMax(v, AppVersion * 1000ULL));
-					cSetBetaPrivateKey(k);
-					cSetRealBetaVersion(v);
-				} else {
-					LOG(("FATAL: '%1' is corrupted, reinstall private beta!").arg(beta.fileName()));
-					return false;
-				}
-			} else {
-				LOG(("FATAL: could not open '%1' for reading private key!").arg(beta.fileName()));
-				return false;
-			}
+bool CheckBetaVersionDir() {
+	QFile beta(cExeDir() + qsl("TelegramBeta_data/tdata/beta"));
+	if (cBetaVersion()) {
+		cForceWorkingDir(cExeDir() + qsl("TelegramBeta_data/"));
+		QDir().mkpath(cWorkingDir() + qstr("tdata"));
+		if (*BetaPrivateKey) {
+			cSetBetaPrivateKey(QByteArray(BetaPrivateKey));
+		}
+		if (beta.open(QIODevice::WriteOnly)) {
+			QDataStream dataStream(&beta);
+			dataStream.setVersion(QDataStream::Qt_5_3);
+			dataStream << quint64(cRealBetaVersion()) << cBetaPrivateKey();
+		} else {
+			LOG(("FATAL: Could not open '%1' for writing private key!").arg(beta.fileName()));
+			return false;
+		}
+	} else if (beta.exists()) {
+		cForceWorkingDir(cExeDir() + qsl("TelegramBeta_data/"));
+		if (beta.open(QIODevice::ReadOnly)) {
+			QDataStream dataStream(&beta);
+			dataStream.setVersion(QDataStream::Qt_5_3);
+
+			quint64 v;
+			QByteArray k;
+			dataStream >> v >> k;
+			if (dataStream.status() == QDataStream::Ok) {
+				cSetBetaVersion(qMax(v, AppVersion * 1000ULL));
+				cSetBetaPrivateKey(k);
+				cSetRealBetaVersion(v);
+			} else {
+				LOG(("FATAL: '%1' is corrupted, reinstall private beta!").arg(beta.fileName()));
+				return false;
+			}
+		} else {
+			LOG(("FATAL: could not open '%1' for reading private key!").arg(beta.fileName()));
+			return false;
+		}
+	}
+	return true;
+}
+
+void WorkingDirReady() {
+	if (QFile(cWorkingDir() + qsl("tdata/withtestmode")).exists()) {
+		cSetTestMode(true);
+	}
+	if (!cDebug() && QFile(cWorkingDir() + qsl("tdata/withdebug")).exists()) {
+		cSetDebug(true);
+	}
+	if (cBetaVersion()) {
+		cSetDevVersion(false);
+	} else if (!cDevVersion() && QFile(cWorkingDir() + qsl("tdata/devversion")).exists()) {
+		cSetDevVersion(true);
+	} else if (DevVersion) {
+		QFile f(cWorkingDir() + qsl("tdata/devversion"));
+		if (!f.exists() && f.open(QIODevice::WriteOnly)) {
+			f.write("1");
 		}
-		return true;
 	}
 
-	void WorkingDirReady() {
-		if (QFile(cWorkingDir() + qsl("tdata/withtestmode")).exists()) {
-			cSetTestMode(true);
-		}
-		if (!cDebug() && QFile(cWorkingDir() + qsl("tdata/withdebug")).exists()) {
-			cSetDebug(true);
-		}
-		if (cBetaVersion()) {
-			cSetDevVersion(false);
-		} else if (!cDevVersion() && QFile(cWorkingDir() + qsl("tdata/devversion")).exists()) {
-			cSetDevVersion(true);
-		} else if (DevVersion) {
-			QFile f(cWorkingDir() + qsl("tdata/devversion"));
-			if (!f.exists() && f.open(QIODevice::WriteOnly)) {
-				f.write("1");
-			}
-		}
+	srand((int32)time(NULL));
 
-		srand((int32)time(NULL));
+	SandboxUserTag = 0;
+	QFile usertag(cWorkingDir() + qsl("tdata/usertag"));
+	if (usertag.open(QIODevice::ReadOnly)) {
+		if (usertag.read(reinterpret_cast<char*>(&SandboxUserTag), sizeof(uint64)) != sizeof(uint64)) {
+			SandboxUserTag = 0;
+		}
+		usertag.close();
+	}
+	if (!SandboxUserTag) {
+		do {
+			memsetrnd_bad(SandboxUserTag);
+		} while (!SandboxUserTag);
 
-		SandboxUserTag = 0;
-		QFile usertag(cWorkingDir() + qsl("tdata/usertag"));
-		if (usertag.open(QIODevice::ReadOnly)) {
-			if (usertag.read(reinterpret_cast<char*>(&SandboxUserTag), sizeof(uint64)) != sizeof(uint64)) {
-				SandboxUserTag = 0;
-			}
+		if (usertag.open(QIODevice::WriteOnly)) {
+			usertag.write(reinterpret_cast<char*>(&SandboxUserTag), sizeof(uint64));
 			usertag.close();
 		}
-		if (!SandboxUserTag) {
-			do {
-				memsetrnd_bad(SandboxUserTag);
-			} while (!SandboxUserTag);
-
-			if (usertag.open(QIODevice::WriteOnly)) {
-				usertag.write(reinterpret_cast<char*>(&SandboxUserTag), sizeof(uint64));
-				usertag.close();
-			}
-		}
-	}
-
-	void start() {
-		SandboxData = new internal::Data();
-
-		SandboxData->LangSystemISO = psCurrentLanguage();
-		if (SandboxData->LangSystemISO.isEmpty()) SandboxData->LangSystemISO = qstr("en");
-		QByteArray l = LangSystemISO().toLatin1();
-		for (int32 i = 0; i < languageCount; ++i) {
-			if (l.at(0) == LanguageCodes[i][0] && l.at(1) == LanguageCodes[i][1]) {
-				SandboxData->LangSystem = i;
-				break;
-			}
-		}
-	}
-
-	void finish() {
-		delete SandboxData;
-		SandboxData = 0;
-	}
-
-	uint64 UserTag() {
-		return SandboxUserTag;
-	}
-
-	DefineReadOnlyVar(Sandbox, QString, LangSystemISO);
-	DefineReadOnlyVar(Sandbox, int32, LangSystem);
-	DefineVar(Sandbox, QByteArray, LastCrashDump);
-	DefineVar(Sandbox, ConnectionProxy, PreLaunchProxy);
-
-}
-
-namespace Global {
-	namespace internal {
-
-		struct Data {
-			uint64 LaunchId = 0;
-			SingleDelayedCall HandleHistoryUpdate = { App::app(), "call_handleHistoryUpdate" };
-
-			Adaptive::Layout AdaptiveLayout = Adaptive::NormalLayout;
-			bool AdaptiveForWide = true;
-
-			int32 DebugLoggingFlags = 0;
-
-			// config
-			int32 ChatSizeMax = 200;
-			int32 MegagroupSizeMax = 1000;
-			int32 ForwardedCountMax = 100;
-			int32 OnlineUpdatePeriod = 120000;
-			int32 OfflineBlurTimeout = 5000;
-			int32 OfflineIdleTimeout = 30000;
-			int32 OnlineFocusTimeout = 1000;
-			int32 OnlineCloudTimeout = 300000;
-			int32 NotifyCloudDelay = 30000;
-			int32 NotifyDefaultDelay = 1500;
-			int32 ChatBigSize = 10;
-			int32 PushChatPeriod = 60000;
-			int32 PushChatLimit = 2;
-			int32 SavedGifsLimit = 200;
-			int32 EditTimeLimit = 172800;
-
-			HiddenPinnedMessagesMap HiddenPinnedMessages;
-
-			PendingItemsMap PendingRepaintItems;
-
-			Stickers::Sets StickerSets;
-			Stickers::Order StickerSetsOrder;
-			uint64 LastStickersUpdate = 0;
-
-			MTP::DcOptions DcOptions;
-
-			CircleMasksMap CircleMasks;
-		};
-
 	}
 }
 
-Global::internal::Data *GlobalData = 0;
+void start() {
+	SandboxData = new internal::Data();
+
+	SandboxData->LangSystemISO = psCurrentLanguage();
+	if (SandboxData->LangSystemISO.isEmpty()) SandboxData->LangSystemISO = qstr("en");
+	QByteArray l = LangSystemISO().toLatin1();
+	for (int32 i = 0; i < languageCount; ++i) {
+		if (l.at(0) == LanguageCodes[i][0] && l.at(1) == LanguageCodes[i][1]) {
+			SandboxData->LangSystem = i;
+			break;
+		}
+	}
+}
+
+void finish() {
+	delete SandboxData;
+	SandboxData = 0;
+}
+
+uint64 UserTag() {
+	return SandboxUserTag;
+}
+
+DefineReadOnlyVar(Sandbox, QString, LangSystemISO);
+DefineReadOnlyVar(Sandbox, int32, LangSystem);
+DefineVar(Sandbox, QByteArray, LastCrashDump);
+DefineVar(Sandbox, ConnectionProxy, PreLaunchProxy);
+
+} // namespace Sandbox
 
 namespace Global {
+namespace internal {
 
-	bool started() {
-		return GlobalData != 0;
-	}
+struct Data {
+	uint64 LaunchId = 0;
+	SingleDelayedCall HandleHistoryUpdate = { App::app(), "call_handleHistoryUpdate" };
 
-	void start() {
-		GlobalData = new internal::Data();
+	Adaptive::Layout AdaptiveLayout = Adaptive::NormalLayout;
+	bool AdaptiveForWide = true;
+	bool DialogsModeEnabled = false;
+	Dialogs::Mode DialogsMode = Dialogs::Mode::All;
 
-		memset_rand(&GlobalData->LaunchId, sizeof(GlobalData->LaunchId));
-	}
-
-	void finish() {
-		delete GlobalData;
-		GlobalData = 0;
-	}
-
-	DefineReadOnlyVar(Global, uint64, LaunchId);
-	DefineRefVar(Global, SingleDelayedCall, HandleHistoryUpdate);
-
-	DefineVar(Global, Adaptive::Layout, AdaptiveLayout);
-	DefineVar(Global, bool, AdaptiveForWide);
-
-	DefineVar(Global, int32, DebugLoggingFlags);
+	int32 DebugLoggingFlags = 0;
 
 	// config
-	DefineVar(Global, int32, ChatSizeMax);
-	DefineVar(Global, int32, MegagroupSizeMax);
-	DefineVar(Global, int32, ForwardedCountMax);
-	DefineVar(Global, int32, OnlineUpdatePeriod);
-	DefineVar(Global, int32, OfflineBlurTimeout);
-	DefineVar(Global, int32, OfflineIdleTimeout);
-	DefineVar(Global, int32, OnlineFocusTimeout);
-	DefineVar(Global, int32, OnlineCloudTimeout);
-	DefineVar(Global, int32, NotifyCloudDelay);
-	DefineVar(Global, int32, NotifyDefaultDelay);
-	DefineVar(Global, int32, ChatBigSize);
-	DefineVar(Global, int32, PushChatPeriod);
-	DefineVar(Global, int32, PushChatLimit);
-	DefineVar(Global, int32, SavedGifsLimit);
-	DefineVar(Global, int32, EditTimeLimit);
+	int32 ChatSizeMax = 200;
+	int32 MegagroupSizeMax = 1000;
+	int32 ForwardedCountMax = 100;
+	int32 OnlineUpdatePeriod = 120000;
+	int32 OfflineBlurTimeout = 5000;
+	int32 OfflineIdleTimeout = 30000;
+	int32 OnlineFocusTimeout = 1000;
+	int32 OnlineCloudTimeout = 300000;
+	int32 NotifyCloudDelay = 30000;
+	int32 NotifyDefaultDelay = 1500;
+	int32 ChatBigSize = 10;
+	int32 PushChatPeriod = 60000;
+	int32 PushChatLimit = 2;
+	int32 SavedGifsLimit = 200;
+	int32 EditTimeLimit = 172800;
 
-	DefineVar(Global, HiddenPinnedMessagesMap, HiddenPinnedMessages);
+	HiddenPinnedMessagesMap HiddenPinnedMessages;
 
-	DefineRefVar(Global, PendingItemsMap, PendingRepaintItems);
+	PendingItemsMap PendingRepaintItems;
 
-	DefineVar(Global, Stickers::Sets, StickerSets);
-	DefineVar(Global, Stickers::Order, StickerSetsOrder);
-	DefineVar(Global, uint64, LastStickersUpdate);
+	Stickers::Sets StickerSets;
+	Stickers::Order StickerSetsOrder;
+	uint64 LastStickersUpdate = 0;
 
-	DefineVar(Global, MTP::DcOptions, DcOptions);
-
-	DefineRefVar(Global, CircleMasksMap, CircleMasks);
+	MTP::DcOptions DcOptions;
 
+	CircleMasksMap CircleMasks;
 };
+
+} // namespace internal
+} // namespace Global
+
+Global::internal::Data *GlobalData = nullptr;
+
+namespace Global {
+
+bool started() {
+	return GlobalData != nullptr;
+}
+
+void start() {
+	GlobalData = new internal::Data();
+
+	memset_rand(&GlobalData->LaunchId, sizeof(GlobalData->LaunchId));
+}
+
+void finish() {
+	delete GlobalData;
+	GlobalData = nullptr;
+}
+
+DefineReadOnlyVar(Global, uint64, LaunchId);
+DefineRefVar(Global, SingleDelayedCall, HandleHistoryUpdate);
+
+DefineVar(Global, Adaptive::Layout, AdaptiveLayout);
+DefineVar(Global, bool, AdaptiveForWide);
+DefineVar(Global, bool, DialogsModeEnabled);
+DefineVar(Global, Dialogs::Mode, DialogsMode);
+
+DefineVar(Global, int32, DebugLoggingFlags);
+
+// config
+DefineVar(Global, int32, ChatSizeMax);
+DefineVar(Global, int32, MegagroupSizeMax);
+DefineVar(Global, int32, ForwardedCountMax);
+DefineVar(Global, int32, OnlineUpdatePeriod);
+DefineVar(Global, int32, OfflineBlurTimeout);
+DefineVar(Global, int32, OfflineIdleTimeout);
+DefineVar(Global, int32, OnlineFocusTimeout);
+DefineVar(Global, int32, OnlineCloudTimeout);
+DefineVar(Global, int32, NotifyCloudDelay);
+DefineVar(Global, int32, NotifyDefaultDelay);
+DefineVar(Global, int32, ChatBigSize);
+DefineVar(Global, int32, PushChatPeriod);
+DefineVar(Global, int32, PushChatLimit);
+DefineVar(Global, int32, SavedGifsLimit);
+DefineVar(Global, int32, EditTimeLimit);
+
+DefineVar(Global, HiddenPinnedMessagesMap, HiddenPinnedMessages);
+
+DefineRefVar(Global, PendingItemsMap, PendingRepaintItems);
+
+DefineVar(Global, Stickers::Sets, StickerSets);
+DefineVar(Global, Stickers::Order, StickerSetsOrder);
+DefineVar(Global, uint64, LastStickersUpdate);
+
+DefineVar(Global, MTP::DcOptions, DcOptions);
+
+DefineRefVar(Global, CircleMasksMap, CircleMasks);
+
+} // namespace Global
diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h
index 7888b8c64..a8bf6fbb1 100644
--- a/Telegram/SourceFiles/facades.h
+++ b/Telegram/SourceFiles/facades.h
@@ -24,23 +24,23 @@ class LayeredWidget;
 
 namespace App {
 
-	void sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyTo = 0);
-	bool insertBotCommand(const QString &cmd, bool specialGif = false);
-	void activateBotCommand(const HistoryItem *msg, int row, int col);
-	void searchByHashtag(const QString &tag, PeerData *inPeer);
-	void openPeerByName(const QString &username, MsgId msgId = ShowAtUnreadMsgId, const QString &startToken = QString());
-	void joinGroupByHash(const QString &hash);
-	void stickersBox(const QString &name);
-	void openLocalUrl(const QString &url);
-	bool forward(const PeerId &peer, ForwardWhatMessages what);
-	void removeDialog(History *history);
-	void showSettings();
+void sendBotCommand(PeerData *peer, const QString &cmd, MsgId replyTo = 0);
+bool insertBotCommand(const QString &cmd, bool specialGif = false);
+void activateBotCommand(const HistoryItem *msg, int row, int col);
+void searchByHashtag(const QString &tag, PeerData *inPeer);
+void openPeerByName(const QString &username, MsgId msgId = ShowAtUnreadMsgId, const QString &startToken = QString());
+void joinGroupByHash(const QString &hash);
+void stickersBox(const QString &name);
+void openLocalUrl(const QString &url);
+bool forward(const PeerId &peer, ForwardWhatMessages what);
+void removeDialog(History *history);
+void showSettings();
 
-	void activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button);
+void activateClickHandler(ClickHandlerPtr handler, Qt::MouseButton button);
 
-	void logOutDelayed();
+void logOutDelayed();
 
-};
+} // namespace App
 
 namespace InlineBots {
 namespace Layout {
@@ -52,43 +52,43 @@ class ItemBase;
 
 namespace Ui {
 
-	void showMediaPreview(DocumentData *document);
-	void showMediaPreview(PhotoData *photo);
-	void hideMediaPreview();
+void showMediaPreview(DocumentData *document);
+void showMediaPreview(PhotoData *photo);
+void hideMediaPreview();
 
-	void showLayer(LayeredWidget *box, ShowLayerOptions options = CloseOtherLayers);
-	void hideLayer(bool fast = false);
-	bool isLayerShown();
-	bool isMediaViewShown();
-	bool isInlineItemBeingChosen();
+void showLayer(LayeredWidget *box, ShowLayerOptions options = CloseOtherLayers);
+void hideLayer(bool fast = false);
+bool isLayerShown();
+bool isMediaViewShown();
+bool isInlineItemBeingChosen();
 
-	void repaintHistoryItem(const HistoryItem *item);
-	void repaintInlineItem(const InlineBots::Layout::ItemBase *layout);
-	bool isInlineItemVisible(const InlineBots::Layout::ItemBase *reader);
-	void autoplayMediaInlineAsync(const FullMsgId &msgId);
+void repaintHistoryItem(const HistoryItem *item);
+void repaintInlineItem(const InlineBots::Layout::ItemBase *layout);
+bool isInlineItemVisible(const InlineBots::Layout::ItemBase *reader);
+void autoplayMediaInlineAsync(const FullMsgId &msgId);
 
-	void showPeerHistory(const PeerId &peer, MsgId msgId, bool back = false);
-	inline void showPeerHistory(const PeerData *peer, MsgId msgId, bool back = false) {
-		showPeerHistory(peer->id, msgId, back);
-	}
-	inline void showPeerHistory(const History *history, MsgId msgId, bool back = false) {
-		showPeerHistory(history->peer->id, msgId, back);
-	}
-	inline void showPeerHistoryAtItem(const HistoryItem *item) {
-		showPeerHistory(item->history()->peer->id, item->id);
-	}
-	void showPeerHistoryAsync(const PeerId &peer, MsgId msgId);
-	inline void showChatsList() {
-		showPeerHistory(PeerId(0), 0);
-	}
-	inline void showChatsListAsync() {
-		showPeerHistoryAsync(PeerId(0), 0);
-	}
-	PeerData *getPeerForMouseAction();
+void showPeerHistory(const PeerId &peer, MsgId msgId, bool back = false);
+inline void showPeerHistory(const PeerData *peer, MsgId msgId, bool back = false) {
+	showPeerHistory(peer->id, msgId, back);
+}
+inline void showPeerHistory(const History *history, MsgId msgId, bool back = false) {
+	showPeerHistory(history->peer->id, msgId, back);
+}
+inline void showPeerHistoryAtItem(const HistoryItem *item) {
+	showPeerHistory(item->history()->peer->id, item->id);
+}
+void showPeerHistoryAsync(const PeerId &peer, MsgId msgId);
+inline void showChatsList() {
+	showPeerHistory(PeerId(0), 0);
+}
+inline void showChatsListAsync() {
+	showPeerHistoryAsync(PeerId(0), 0);
+}
+PeerData *getPeerForMouseAction();
 
-	bool hideWindowNoQuit();
+bool hideWindowNoQuit();
 
-};
+} // namespace Ui
 
 enum ClipStopperType {
 	ClipStopperMediaview,
@@ -97,26 +97,27 @@ enum ClipStopperType {
 
 namespace Notify {
 
-	void userIsBotChanged(UserData *user);
-	void userIsContactChanged(UserData *user, bool fromThisApp = false);
-	void botCommandsChanged(UserData *user);
+void userIsBotChanged(UserData *user);
+void userIsContactChanged(UserData *user, bool fromThisApp = false);
+void botCommandsChanged(UserData *user);
 
-	void inlineBotRequesting(bool requesting);
-	void replyMarkupUpdated(const HistoryItem *item);
-	void inlineKeyboardMoved(const HistoryItem *item, int oldKeyboardTop, int newKeyboardTop);
-	bool switchInlineBotButtonReceived(const QString &query);
+void inlineBotRequesting(bool requesting);
+void replyMarkupUpdated(const HistoryItem *item);
+void inlineKeyboardMoved(const HistoryItem *item, int oldKeyboardTop, int newKeyboardTop);
+bool switchInlineBotButtonReceived(const QString &query);
 
-	void migrateUpdated(PeerData *peer);
+void migrateUpdated(PeerData *peer);
 
-	void clipStopperHidden(ClipStopperType type);
+void clipStopperHidden(ClipStopperType type);
 
-	void historyItemLayoutChanged(const HistoryItem *item);
-	void inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout);
+void historyItemLayoutChanged(const HistoryItem *item);
+void inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout);
+void historyMuteUpdated(History *history);
 
-	// handle pending resize() / paint() on history items
-	void handlePendingHistoryUpdate();
+// handle pending resize() / paint() on history items
+void handlePendingHistoryUpdate();
 
-};
+} // namespace Notify
 
 #define DeclareReadOnlyVar(Type, Name) const Type &Name();
 #define DeclareRefVar(Type, Name) DeclareReadOnlyVar(Type, Name) \
@@ -126,115 +127,123 @@ namespace Notify {
 
 namespace Sandbox {
 
-	bool CheckBetaVersionDir();
-	void WorkingDirReady();
+bool CheckBetaVersionDir();
+void WorkingDirReady();
 
-	void start();
-	void finish();
+void start();
+void finish();
 
-	uint64 UserTag();
+uint64 UserTag();
 
-	DeclareReadOnlyVar(QString, LangSystemISO);
-	DeclareReadOnlyVar(int32, LangSystem);
-	DeclareVar(QByteArray, LastCrashDump);
-	DeclareVar(ConnectionProxy, PreLaunchProxy);
+DeclareReadOnlyVar(QString, LangSystemISO);
+DeclareReadOnlyVar(int32, LangSystem);
+DeclareVar(QByteArray, LastCrashDump);
+DeclareVar(ConnectionProxy, PreLaunchProxy);
 
-}
+} // namespace Sandbox
 
 namespace Adaptive {
-	enum Layout {
-		OneColumnLayout,
-		NormalLayout,
-		WideLayout,
-	};
+enum Layout {
+	OneColumnLayout,
+	NormalLayout,
+	WideLayout,
 };
+} // namespace Adaptive
 
 namespace DebugLogging {
-	enum Flags {
-		FileLoaderFlag = 0x00000001,
-	};
-}
+enum Flags {
+	FileLoaderFlag = 0x00000001,
+};
+} // namespace DebugLogging
 
 namespace Stickers {
-	static const uint64 DefaultSetId = 0; // for backward compatibility
-	static const uint64 CustomSetId = 0xFFFFFFFFFFFFFFFFULL, RecentSetId = 0xFFFFFFFFFFFFFFFEULL;
-	static const uint64 NoneSetId = 0xFFFFFFFFFFFFFFFDULL; // for emoji/stickers panel
-	struct Set {
-		Set(uint64 id, uint64 access, const QString &title, const QString &shortName, int32 count, int32 hash, MTPDstickerSet::Flags flags) : id(id), access(access), title(title), shortName(shortName), count(count), hash(hash), flags(flags) {
-		}
-		uint64 id, access;
-		QString title, shortName;
-		int32 count, hash;
-		MTPDstickerSet::Flags flags;
-		StickerPack stickers;
-		StickersByEmojiMap emoji;
-	};
-	typedef QMap<uint64, Set> Sets;
-	typedef QList<uint64> Order;
-}
+
+static const uint64 DefaultSetId = 0; // for backward compatibility
+static const uint64 CustomSetId = 0xFFFFFFFFFFFFFFFFULL, RecentSetId = 0xFFFFFFFFFFFFFFFEULL;
+static const uint64 NoneSetId = 0xFFFFFFFFFFFFFFFDULL; // for emoji/stickers panel
+struct Set {
+	Set(uint64 id, uint64 access, const QString &title, const QString &shortName, int32 count, int32 hash, MTPDstickerSet::Flags flags) : id(id), access(access), title(title), shortName(shortName), count(count), hash(hash), flags(flags) {
+	}
+	uint64 id, access;
+	QString title, shortName;
+	int32 count, hash;
+	MTPDstickerSet::Flags flags;
+	StickerPack stickers;
+	StickersByEmojiMap emoji;
+};
+using Sets = QMap<uint64, Set>;
+using Order = QList<uint64>;
+
+} // namespace Stickers
 
 namespace Global {
 
-	bool started();
-	void start();
-	void finish();
+bool started();
+void start();
+void finish();
 
-	DeclareReadOnlyVar(uint64, LaunchId);
-	DeclareRefVar(SingleDelayedCall, HandleHistoryUpdate);
+DeclareReadOnlyVar(uint64, LaunchId);
+DeclareRefVar(SingleDelayedCall, HandleHistoryUpdate);
 
-	DeclareVar(Adaptive::Layout, AdaptiveLayout);
-	DeclareVar(bool, AdaptiveForWide);
+DeclareVar(Adaptive::Layout, AdaptiveLayout);
+DeclareVar(bool, AdaptiveForWide);
+DeclareVar(bool, DialogsModeEnabled);
+DeclareVar(Dialogs::Mode, DialogsMode);
 
-	DeclareVar(int32, DebugLoggingFlags);
+DeclareVar(int32, DebugLoggingFlags);
 
-	// config
-	DeclareVar(int32, ChatSizeMax);
-	DeclareVar(int32, MegagroupSizeMax);
-	DeclareVar(int32, ForwardedCountMax);
-	DeclareVar(int32, OnlineUpdatePeriod);
-	DeclareVar(int32, OfflineBlurTimeout);
-	DeclareVar(int32, OfflineIdleTimeout);
-	DeclareVar(int32, OnlineFocusTimeout); // not from config
-	DeclareVar(int32, OnlineCloudTimeout);
-	DeclareVar(int32, NotifyCloudDelay);
-	DeclareVar(int32, NotifyDefaultDelay);
-	DeclareVar(int32, ChatBigSize);
-	DeclareVar(int32, PushChatPeriod);
-	DeclareVar(int32, PushChatLimit);
-	DeclareVar(int32, SavedGifsLimit);
-	DeclareVar(int32, EditTimeLimit);
+// config
+DeclareVar(int32, ChatSizeMax);
+DeclareVar(int32, MegagroupSizeMax);
+DeclareVar(int32, ForwardedCountMax);
+DeclareVar(int32, OnlineUpdatePeriod);
+DeclareVar(int32, OfflineBlurTimeout);
+DeclareVar(int32, OfflineIdleTimeout);
+DeclareVar(int32, OnlineFocusTimeout); // not from config
+DeclareVar(int32, OnlineCloudTimeout);
+DeclareVar(int32, NotifyCloudDelay);
+DeclareVar(int32, NotifyDefaultDelay);
+DeclareVar(int32, ChatBigSize);
+DeclareVar(int32, PushChatPeriod);
+DeclareVar(int32, PushChatLimit);
+DeclareVar(int32, SavedGifsLimit);
+DeclareVar(int32, EditTimeLimit);
 
-	typedef QMap<PeerId, MsgId> HiddenPinnedMessagesMap;
-	DeclareVar(HiddenPinnedMessagesMap, HiddenPinnedMessages);
+typedef QMap<PeerId, MsgId> HiddenPinnedMessagesMap;
+DeclareVar(HiddenPinnedMessagesMap, HiddenPinnedMessages);
 
-	typedef OrderedSet<HistoryItem*> PendingItemsMap;
-	DeclareRefVar(PendingItemsMap, PendingRepaintItems);
+typedef OrderedSet<HistoryItem*> PendingItemsMap;
+DeclareRefVar(PendingItemsMap, PendingRepaintItems);
 
-	DeclareVar(Stickers::Sets, StickerSets);
-	DeclareVar(Stickers::Order, StickerSetsOrder);
-	DeclareVar(uint64, LastStickersUpdate);
+DeclareVar(Stickers::Sets, StickerSets);
+DeclareVar(Stickers::Order, StickerSetsOrder);
+DeclareVar(uint64, LastStickersUpdate);
 
-	DeclareVar(MTP::DcOptions, DcOptions);
+DeclareVar(MTP::DcOptions, DcOptions);
 
-	typedef QMap<uint64, QPixmap> CircleMasksMap;
-	DeclareRefVar(CircleMasksMap, CircleMasks);
+typedef QMap<uint64, QPixmap> CircleMasksMap;
+DeclareRefVar(CircleMasksMap, CircleMasks);
 
-};
+} // namespace Global
 
 namespace Adaptive {
-	inline bool OneColumn() {
-		return Global::AdaptiveLayout() == OneColumnLayout;
-	}
-	inline bool Normal() {
-		return Global::AdaptiveLayout() == NormalLayout;
-	}
-	inline bool Wide() {
-		return Global::AdaptiveForWide() && (Global::AdaptiveLayout() == WideLayout);
-	}
+
+inline bool OneColumn() {
+	return Global::AdaptiveLayout() == OneColumnLayout;
+}
+inline bool Normal() {
+	return Global::AdaptiveLayout() == NormalLayout;
+}
+inline bool Wide() {
+	return Global::AdaptiveForWide() && (Global::AdaptiveLayout() == WideLayout);
 }
 
+} // namespace Adaptive
+
 namespace DebugLogging {
-	inline bool FileLoader() {
-		return (Global::DebugLoggingFlags() | FileLoaderFlag) != 0;
-	}
+
+inline bool FileLoader() {
+	return (Global::DebugLoggingFlags() | FileLoaderFlag) != 0;
 }
+
+} // namespace DebugLogging
diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp
index cc987fb09..ef44e65bf 100644
--- a/Telegram/SourceFiles/history.cpp
+++ b/Telegram/SourceFiles/history.cpp
@@ -104,7 +104,7 @@ void historyInit() {
 
 History::History(const PeerId &peerId)
 : peer(App::peer(peerId))
-, mute(isNotifyMuted(peer->notify)) {
+, _mute(isNotifyMuted(peer->notify)) {
 	if (peer->isChannel() || (peer->isUser() && peer->asUser()->botInfo)) {
 		outboxReadBefore = INT_MAX;
 	}
@@ -1683,7 +1683,7 @@ void History::updateShowFrom() {
 
 MsgId History::inboxRead(MsgId upTo) {
 	if (upTo < 0) return upTo;
-	if (unreadCount) {
+	if (unreadCount()) {
 		if (upTo && loadedAtBottom()) App::main()->historyToDown(this);
 		setUnreadCount(upTo ? countUnread(upTo) : 0);
 	}
@@ -1739,7 +1739,7 @@ HistoryItem *History::lastImportantMessage() const {
 }
 
 void History::setUnreadCount(int newUnreadCount, bool psUpdate) {
-	if (unreadCount != newUnreadCount) {
+	if (_unreadCount != newUnreadCount) {
 		if (newUnreadCount == 1) {
 			if (loadedAtBottom()) showFrom = lastImportantMessage();
 			inboxReadBefore = qMax(inboxReadBefore, msgIdForRead());
@@ -1747,18 +1747,18 @@ void History::setUnreadCount(int newUnreadCount, bool psUpdate) {
 			showFrom = nullptr;
 			inboxReadBefore = qMax(inboxReadBefore, msgIdForRead() + 1);
 		}
-		if (inChatList()) {
-			App::histories().unreadIncrement(newUnreadCount - unreadCount, mute);
-			if (psUpdate && (!mute || cIncludeMuted()) && App::wnd()) {
+		if (inChatList(Dialogs::Mode::All)) {
+			App::histories().unreadIncrement(newUnreadCount - _unreadCount, mute());
+			if (psUpdate && (!mute() || cIncludeMuted()) && App::wnd()) {
 				App::wnd()->updateCounter();
 			}
 		}
-		unreadCount = newUnreadCount;
+		_unreadCount = newUnreadCount;
 		if (unreadBar) {
-			int32 count = unreadCount;
+			int32 count = _unreadCount;
 			if (peer->migrateTo()) {
 				if (History *h = App::historyLoaded(peer->migrateTo()->id)) {
-					count += h->unreadCount;
+					count += h->unreadCount();
 				}
 			}
 			if (count > 0) {
@@ -1771,11 +1771,14 @@ void History::setUnreadCount(int newUnreadCount, bool psUpdate) {
 }
 
  void History::setMute(bool newMute) {
-	if (mute != newMute) {
-		mute = newMute;
-		if (inChatList() && unreadCount) {
-			App::histories().unreadMuteChanged(unreadCount, newMute);
-			if (App::wnd()) App::wnd()->updateCounter();
+	if (_mute != newMute) {
+		_mute = newMute;
+		if (inChatList(Dialogs::Mode::All)) {
+			if (_unreadCount) {
+				App::histories().unreadMuteChanged(_unreadCount, newMute);
+				if (App::wnd()) App::wnd()->updateCounter();
+			}
+			Notify::historyMuteUpdated(this);
 		}
 		updateChatListEntry();
 	}
@@ -1881,12 +1884,12 @@ void History::getNextScrollTopItem(HistoryBlock *block, int32 i) {
 }
 
 void History::addUnreadBar() {
-	if (unreadBar || !showFrom || showFrom->detached() || !unreadCount) return;
+	if (unreadBar || !showFrom || showFrom->detached() || !unreadCount()) return;
 
-	int32 count = unreadCount;
+	int32 count = unreadCount();
 	if (peer->migrateTo()) {
 		if (History *h = App::historyLoaded(peer->migrateTo()->id)) {
-			count += h->unreadCount;
+			count += h->unreadCount();
 		}
 	}
 	showFrom->setUnreadBarCount(count);
@@ -2014,12 +2017,12 @@ bool History::isReadyFor(MsgId msgId, MsgId &fixInScrollMsgId, int32 &fixInScrol
 	if (msgId == ShowAtUnreadMsgId) {
 		if (peer->migrateFrom()) { // old group history
 			if (History *h = App::historyLoaded(peer->migrateFrom()->id)) {
-				if (h->unreadCount) {
+				if (h->unreadCount()) {
 					return h->isReadyFor(msgId, fixInScrollMsgId, fixInScrollMsgTop);
 				}
 			}
 		}
-		if (unreadCount) {
+		if (unreadCount()) {
 			if (!isEmpty()) {
 				return (loadedAtTop() || minMsgId() <= inboxReadBefore) && (loadedAtBottom() || maxMsgId() >= inboxReadBefore);
 			}
@@ -2045,7 +2048,7 @@ void History::getReadyFor(MsgId msgId, MsgId &fixInScrollMsgId, int32 &fixInScro
 	}
 	if (msgId == ShowAtUnreadMsgId && peer->migrateFrom()) {
 		if (History *h = App::historyLoaded(peer->migrateFrom()->id)) {
-			if (h->unreadCount) {
+			if (h->unreadCount()) {
 				clear(true);
 				h->getReadyFor(msgId, fixInScrollMsgId, fixInScrollMsgTop);
 				return;
@@ -2084,12 +2087,12 @@ void History::setLastMessage(HistoryItem *msg) {
 }
 
 void History::setChatsListDate(const QDateTime &date) {
-	bool updateDialog = (App::main() && (!peer->isChannel() || peer->asChannel()->amIn() || !_chatListLinks.isEmpty()));
-	if (peer->migrateTo() && _chatListLinks.isEmpty()) {
+	bool updateDialog = (App::main() && (!peer->isChannel() || peer->asChannel()->amIn() || inChatList(Dialogs::Mode::All)));
+	if (peer->migrateTo() && !inChatList(Dialogs::Mode::All)) {
 		updateDialog = false;
 	}
 	if (!lastMsgDate.isNull() && lastMsgDate >= date) {
-		if (!updateDialog || !_chatListLinks.isEmpty()) {
+		if (!updateDialog || !inChatList(Dialogs::Mode::All)) {
 			return;
 		}
 	}
@@ -2225,61 +2228,64 @@ void History::clearOnDestroy() {
 	clearBlocks(false);
 }
 
-QPair<int32, int32> History::adjustByPosInChatsList(Dialogs::IndexedList *indexed) {
+QPair<int32, int32> History::adjustByPosInChatList(Dialogs::Mode list, Dialogs::IndexedList *indexed) {
 	t_assert(indexed != nullptr);
-	Dialogs::Row *lnk = mainChatListLink();
+	Dialogs::Row *lnk = mainChatListLink(list);
 	int32 movedFrom = lnk->pos() * st::dlgHeight;
-	indexed->adjustByPos(_chatListLinks);
+	indexed->adjustByPos(chatListLinks(list));
 	int32 movedTo = lnk->pos() * st::dlgHeight;
 	return qMakePair(movedFrom, movedTo);
 }
 
-int History::posInChatList() const {
-	return mainChatListLink()->pos();
+int History::posInChatList(Dialogs::Mode list) const {
+	return mainChatListLink(list)->pos();
 }
 
-Dialogs::Row *History::addToChatList(Dialogs::IndexedList *indexed) {
+Dialogs::Row *History::addToChatList(Dialogs::Mode list, Dialogs::IndexedList *indexed) {
 	t_assert(indexed != nullptr);
-	if (!inChatList()) {
-		_chatListLinks = indexed->addToEnd(this);
-		if (unreadCount) {
-			App::histories().unreadIncrement(unreadCount, mute);
+	if (!inChatList(list)) {
+		chatListLinks(list) = indexed->addToEnd(this);
+		if (list == Dialogs::Mode::All && unreadCount()) {
+			App::histories().unreadIncrement(unreadCount(), mute());
 			if (App::wnd()) App::wnd()->updateCounter();
 		}
 	}
-	return mainChatListLink();
+	return mainChatListLink(list);
 }
 
-void History::removeFromChatList(Dialogs::IndexedList *indexed) {
+void History::removeFromChatList(Dialogs::Mode list, Dialogs::IndexedList *indexed) {
 	t_assert(indexed != nullptr);
-	if (inChatList()) {
+	if (inChatList(list)) {
 		indexed->del(peer);
-		_chatListLinks.clear();
-		if (unreadCount) {
-			App::histories().unreadIncrement(-unreadCount, mute);
+		chatListLinks(list).clear();
+		if (list == Dialogs::Mode::All && unreadCount()) {
+			App::histories().unreadIncrement(-unreadCount(), mute());
 			if (App::wnd()) App::wnd()->updateCounter();
 		}
 	}
 }
 
-void History::removeChatListEntryByLetter(QChar letter) {
+void History::removeChatListEntryByLetter(Dialogs::Mode list, QChar letter) {
 	t_assert(letter != 0);
-	if (inChatList()) {
-		_chatListLinks.remove(letter);
+	if (inChatList(list)) {
+		chatListLinks(list).remove(letter);
 	}
 }
 
-void History::addChatListEntryByLetter(QChar letter, Dialogs::Row *row) {
+void History::addChatListEntryByLetter(Dialogs::Mode list, QChar letter, Dialogs::Row *row) {
 	t_assert(letter != 0);
-	if (inChatList()) {
-		_chatListLinks.insert(letter, row);
+	if (inChatList(list)) {
+		chatListLinks(list).insert(letter, row);
 	}
 }
 
 void History::updateChatListEntry() const {
 	if (MainWidget *m = App::main()) {
-		if (inChatList()) {
-			m->dlgUpdated(mainChatListLink());
+		if (inChatList(Dialogs::Mode::All)) {
+			m->dlgUpdated(Dialogs::Mode::All, mainChatListLink(Dialogs::Mode::All));
+			if (inChatList(Dialogs::Mode::Important)) {
+				m->dlgUpdated(Dialogs::Mode::Important, mainChatListLink(Dialogs::Mode::Important));
+			}
 		}
 	}
 }
@@ -2986,8 +2992,8 @@ void HistoryItem::destroy() {
 		history()->clearLastKeyboard();
 		if (App::main()) App::main()->updateBotKeyboard(history());
 	}
-	if ((!out() || isPost()) && unread() && history()->unreadCount > 0) {
-		history()->setUnreadCount(history()->unreadCount - 1);
+	if ((!out() || isPost()) && unread() && history()->unreadCount() > 0) {
+		history()->setUnreadCount(history()->unreadCount() - 1);
 	}
 	Global::RefPendingRepaintItems().remove(this);
 	delete this;
diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h
index 607d8292b..095fc2c96 100644
--- a/Telegram/SourceFiles/history.h
+++ b/Telegram/SourceFiles/history.h
@@ -65,6 +65,9 @@ public:
 	int32 unreadBadge() const {
 		return _unreadFull - (cIncludeMuted() ? 0 : _unreadMuted);
 	}
+	int32 unreadMutedCount() const {
+		return _unreadMuted;
+	}
 	bool unreadOnlyMuted() const {
 		return cIncludeMuted() ? (_unreadMuted >= _unreadFull) : false;
 	}
@@ -249,7 +252,13 @@ public:
 
 	HistoryItem *lastImportantMessage() const;
 
+	int unreadCount() const {
+		return _unreadCount;
+	}
 	void setUnreadCount(int newUnreadCount, bool psUpdate = true);
+	bool mute() const {
+		return _mute;
+	}
 	void setMute(bool newMute);
 	void getNextShowFrom(HistoryBlock *block, int i);
 	void addUnreadBar();
@@ -266,18 +275,18 @@ public:
 	void fixLastMessage(bool wasAtBottom);
 
 	void setChatsListDate(const QDateTime &date);
-	QPair<int32, int32> adjustByPosInChatsList(Dialogs::IndexedList *indexed);
 	uint64 sortKeyInChatList() const {
 		return _sortKeyInChatList;
 	}
-	bool inChatList() const {
-		return !_chatListLinks.isEmpty();
+	QPair<int32, int32> adjustByPosInChatList(Dialogs::Mode list, Dialogs::IndexedList *indexed);
+	bool inChatList(Dialogs::Mode list) const {
+		return !chatListLinks(list).isEmpty();
 	}
-	int posInChatList() const;
-	Dialogs::Row *addToChatList(Dialogs::IndexedList *indexed);
-	void removeFromChatList(Dialogs::IndexedList *indexed);
-	void removeChatListEntryByLetter(QChar letter);
-	void addChatListEntryByLetter(QChar letter, Dialogs::Row *row);
+	int posInChatList(Dialogs::Mode list) const;
+	Dialogs::Row *addToChatList(Dialogs::Mode list, Dialogs::IndexedList *indexed);
+	void removeFromChatList(Dialogs::Mode list, Dialogs::IndexedList *indexed);
+	void removeChatListEntryByLetter(Dialogs::Mode list, QChar letter);
+	void addChatListEntryByLetter(Dialogs::Mode list, QChar letter, Dialogs::Row *row);
 	void updateChatListEntry() const;
 
 	MsgId minMsgId() const;
@@ -334,7 +343,6 @@ public:
 	int width = 0;
 	int height = 0;
 	int32 msgCount = 0;
-	int32 unreadCount = 0;
 	MsgId inboxReadBefore = 1;
 	MsgId outboxReadBefore = 1;
 	HistoryItem *showFrom = nullptr;
@@ -412,8 +420,6 @@ protected:
 
 public:
 
-	bool mute;
-
 	bool lastKeyboardInited = false;
 	bool lastKeyboardUsed = false;
 	MsgId lastKeyboardId = 0;
@@ -536,11 +542,19 @@ private:
 		return ~QFlags<Flags::enum_type>(f);
 	}
 	Flags _flags;
+	bool _mute;
+	int32 _unreadCount = 0;
 
-	Dialogs::RowsByLetter _chatListLinks;
-	Dialogs::Row *mainChatListLink() const {
-		auto it = _chatListLinks.constFind(0);
-		t_assert(it != _chatListLinks.cend());
+	Dialogs::RowsByLetter _chatListLinks[2];
+	Dialogs::RowsByLetter &chatListLinks(Dialogs::Mode list) {
+		return _chatListLinks[static_cast<int>(list)];
+	}
+	const Dialogs::RowsByLetter &chatListLinks(Dialogs::Mode list) const {
+		return _chatListLinks[static_cast<int>(list)];
+	}
+	Dialogs::Row *mainChatListLink(Dialogs::Mode list) const {
+		auto it = chatListLinks(list).constFind(0);
+		t_assert(it != chatListLinks(list).cend());
 		return it.value();
 	}
 	uint64 _sortKeyInChatList = 0; // like ((unixtime) << 32) | (incremented counter)
diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp
index 0a7da493a..29c01c8d8 100644
--- a/Telegram/SourceFiles/historywidget.cpp
+++ b/Telegram/SourceFiles/historywidget.cpp
@@ -3270,7 +3270,7 @@ void HistoryWidget::notify_migrateUpdated(PeerData *peer) {
 				showHistory(peer->migrateTo()->id, (_showAtMsgId > 0) ? (-_showAtMsgId) : _showAtMsgId, true);
 			} else if ((_migrated ? _migrated->peer : 0) != peer->migrateFrom()) {
 				History *migrated = peer->migrateFrom() ? App::history(peer->migrateFrom()->id) : 0;
-				if (_migrated || (migrated && migrated->unreadCount > 0)) {
+				if (_migrated || (migrated && migrated->unreadCount() > 0)) {
 					showHistory(peer->id, peer->migrateFrom() ? _showAtMsgId : ((_showAtMsgId < 0 && -_showAtMsgId < ServerMaxMsgId) ? ShowAtUnreadMsgId : _showAtMsgId), true);
 				} else {
 					_migrated = migrated;
@@ -3831,7 +3831,7 @@ void HistoryWidget::updateFieldSubmitSettings() {
 void HistoryWidget::updateNotifySettings() {
 	if (!_peer || !_peer->isChannel()) return;
 
-	_muteUnmute.setText(lang(_history->mute ? lng_channel_unmute : lng_channel_mute));
+	_muteUnmute.setText(lang(_history->mute() ? lng_channel_unmute : lng_channel_mute));
 	if (_peer->notify != UnknownNotifySettings) {
 		_silent.setChecked(_peer->notify != EmptyNotifySettings && (_peer->notify->flags & MTPDpeerNotifySettings::Flag::f_silent));
 		if (_silent.isHidden() && hasSilentToggle()) {
@@ -4211,7 +4211,7 @@ void HistoryWidget::newUnreadMsg(History *history, HistoryItem *item) {
 			}
 		} else {
 			App::wnd()->notifySchedule(history, item);
-			history->setUnreadCount(history->unreadCount + 1);
+			history->setUnreadCount(history->unreadCount() + 1);
 		}
 	} else {
 		if (_history == history) {
@@ -4220,7 +4220,7 @@ void HistoryWidget::newUnreadMsg(History *history, HistoryItem *item) {
 			}
 		}
 		App::wnd()->notifySchedule(history, item);
-		history->setUnreadCount(history->unreadCount + 1);
+		history->setUnreadCount(history->unreadCount() + 1);
 	}
 }
 
@@ -4339,7 +4339,7 @@ void HistoryWidget::messagesReceived(PeerData *peer, const MTPmessages_Messages
 		}
 		_firstLoadRequest = 0;
 		if (_history->loadedAtTop()) {
-			if (_history->unreadCount > count) {
+			if (_history->unreadCount() > count) {
 				_history->setUnreadCount(count);
 			}
 			if (_history->isEmpty() && count > 0) {
@@ -4373,7 +4373,7 @@ void HistoryWidget::messagesReceived(PeerData *peer, const MTPmessages_Messages
 			}
 			_firstLoadRequest = 0;
 			if (_history->loadedAtTop()) {
-				if (_history->unreadCount > count) {
+				if (_history->unreadCount() > count) {
 					_history->setUnreadCount(count);
 				}
 				if (_history->isEmpty() && count > 0) {
@@ -4429,12 +4429,12 @@ void HistoryWidget::firstLoadMessages() {
 	PeerData *from = _peer;
 	int32 offset_id = 0, offset = 0, loadCount = MessagesPerPage;
 	if (_showAtMsgId == ShowAtUnreadMsgId) {
-		if (_migrated && _migrated->unreadCount) {
+		if (_migrated && _migrated->unreadCount()) {
 			_history->getReadyFor(_showAtMsgId, _fixedInScrollMsgId, _fixedInScrollMsgTop);
 			from = _migrated->peer;
 			offset = -loadCount / 2;
 			offset_id = _migrated->inboxReadBefore;
-		} else if (_history->unreadCount) {
+		} else if (_history->unreadCount()) {
 			_history->getReadyFor(_showAtMsgId, _fixedInScrollMsgId, _fixedInScrollMsgTop);
 			offset = -loadCount / 2;
 			offset_id = _history->inboxReadBefore;
@@ -4552,11 +4552,11 @@ void HistoryWidget::delayedShowAt(MsgId showAtMsgId) {
 	PeerData *from = _peer;
 	int32 offset_id = 0, offset = 0, loadCount = MessagesPerPage;
 	if (_delayedShowAtMsgId == ShowAtUnreadMsgId) {
-		if (_migrated && _migrated->unreadCount) {
+		if (_migrated && _migrated->unreadCount()) {
 			from = _migrated->peer;
 			offset = -loadCount / 2;
 			offset_id = _migrated->inboxReadBefore;
-		} else if (_history->unreadCount) {
+		} else if (_history->unreadCount()) {
 			offset = -loadCount / 2;
 			offset_id = _history->inboxReadBefore;
 		} else {
@@ -4872,7 +4872,7 @@ bool HistoryWidget::joinFail(const RPCError &error, mtpRequestId req) {
 }
 
 void HistoryWidget::onMuteUnmute() {
-	App::main()->updateNotifySetting(_peer, _history->mute ? NotifySettingSetNotify : NotifySettingSetMuted);
+	App::main()->updateNotifySetting(_peer, _history->mute() ? NotifySettingSetNotify : NotifySettingSetMuted);
 }
 
 void HistoryWidget::onBroadcastSilentChange() {
@@ -6720,10 +6720,10 @@ void HistoryWidget::addMessagesToBack(PeerData *peer, const QVector<MTPMessage>
 }
 
 void HistoryWidget::countHistoryShowFrom() {
-	if (_migrated && _showAtMsgId == ShowAtUnreadMsgId && _migrated->unreadCount) {
+	if (_migrated && _showAtMsgId == ShowAtUnreadMsgId && _migrated->unreadCount()) {
 		_migrated->updateShowFrom();
 	}
-	if ((_migrated && _migrated->showFrom) || _showAtMsgId != ShowAtUnreadMsgId || !_history->unreadCount) {
+	if ((_migrated && _migrated->showFrom) || _showAtMsgId != ShowAtUnreadMsgId || !_history->unreadCount()) {
 		_history->showFrom = 0;
 		return;
 	}
diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_result.h b/Telegram/SourceFiles/inline_bots/inline_bot_result.h
index 54163ca34..567339c1c 100644
--- a/Telegram/SourceFiles/inline_bots/inline_bot_result.h
+++ b/Telegram/SourceFiles/inline_bots/inline_bot_result.h
@@ -90,6 +90,7 @@ private:
 		Gif,
 		Article,
 		Contact,
+		Geo,
 		Venue,
 	};
 
diff --git a/Telegram/SourceFiles/localstorage.cpp b/Telegram/SourceFiles/localstorage.cpp
index 61b831b94..386f307c4 100644
--- a/Telegram/SourceFiles/localstorage.cpp
+++ b/Telegram/SourceFiles/localstorage.cpp
@@ -552,65 +552,66 @@ namespace {
 	};
 
 	enum {
-		dbiKey = 0x00,
-		dbiUser = 0x01,
-		dbiDcOptionOld = 0x02,
-		dbiChatSizeMax = 0x03,
-		dbiMutePeer = 0x04,
-		dbiSendKey = 0x05,
-		dbiAutoStart = 0x06,
-		dbiStartMinimized = 0x07,
-		dbiSoundNotify = 0x08,
-		dbiWorkMode = 0x09,
-		dbiSeenTrayTooltip = 0x0a,
-		dbiDesktopNotify = 0x0b,
-		dbiAutoUpdate = 0x0c,
-		dbiLastUpdateCheck = 0x0d,
-		dbiWindowPosition = 0x0e,
-		dbiConnectionType = 0x0f,
+		dbiKey                  = 0x00,
+		dbiUser                 = 0x01,
+		dbiDcOptionOld          = 0x02,
+		dbiChatSizeMax          = 0x03,
+		dbiMutePeer             = 0x04,
+		dbiSendKey              = 0x05,
+		dbiAutoStart            = 0x06,
+		dbiStartMinimized       = 0x07,
+		dbiSoundNotify          = 0x08,
+		dbiWorkMode             = 0x09,
+		dbiSeenTrayTooltip      = 0x0a,
+		dbiDesktopNotify        = 0x0b,
+		dbiAutoUpdate           = 0x0c,
+		dbiLastUpdateCheck      = 0x0d,
+		dbiWindowPosition       = 0x0e,
+		dbiConnectionType       = 0x0f,
 		// 0x10 reserved
-		dbiDefaultAttach = 0x11,
-		dbiCatsAndDogs = 0x12,
-		dbiReplaceEmojis = 0x13,
-		dbiAskDownloadPath = 0x14,
-		dbiDownloadPathOld = 0x15,
-		dbiScale = 0x16,
-		dbiEmojiTabOld = 0x17,
-		dbiRecentEmojisOld = 0x18,
-		dbiLoggedPhoneNumber = 0x19,
-		dbiMutedPeers = 0x1a,
+		dbiDefaultAttach        = 0x11,
+		dbiCatsAndDogs          = 0x12,
+		dbiReplaceEmojis        = 0x13,
+		dbiAskDownloadPath      = 0x14,
+		dbiDownloadPathOld      = 0x15,
+		dbiScale                = 0x16,
+		dbiEmojiTabOld          = 0x17,
+		dbiRecentEmojisOld      = 0x18,
+		dbiLoggedPhoneNumber    = 0x19,
+		dbiMutedPeers           = 0x1a,
 		// 0x1b reserved
-		dbiNotifyView = 0x1c,
-		dbiSendToMenu = 0x1d,
-		dbiCompressPastedImage = 0x1e,
-		dbiLang = 0x1f,
-		dbiLangFile = 0x20,
-		dbiTileBackground = 0x21,
-		dbiAutoLock = 0x22,
-		dbiDialogLastPath = 0x23,
-		dbiRecentEmojis = 0x24,
-		dbiEmojiVariants = 0x25,
-		dbiRecentStickers = 0x26,
-		dbiDcOption = 0x27,
-		dbiTryIPv6 = 0x28,
-		dbiSongVolume = 0x29,
+		dbiNotifyView           = 0x1c,
+		dbiSendToMenu           = 0x1d,
+		dbiCompressPastedImage  = 0x1e,
+		dbiLang                 = 0x1f,
+		dbiLangFile             = 0x20,
+		dbiTileBackground       = 0x21,
+		dbiAutoLock             = 0x22,
+		dbiDialogLastPath       = 0x23,
+		dbiRecentEmojis         = 0x24,
+		dbiEmojiVariants        = 0x25,
+		dbiRecentStickers       = 0x26,
+		dbiDcOption             = 0x27,
+		dbiTryIPv6              = 0x28,
+		dbiSongVolume           = 0x29,
 		dbiWindowsNotifications = 0x30,
-		dbiIncludeMuted = 0x31,
-		dbiMegagroupSizeMax = 0x32,
-		dbiDownloadPath = 0x33,
-		dbiAutoDownload = 0x34,
-		dbiSavedGifsLimit = 0x35,
-		dbiShowingSavedGifs = 0x36,
-		dbiAutoPlay = 0x37,
-		dbiAdaptiveForWide = 0x38,
+		dbiIncludeMuted         = 0x31,
+		dbiMegagroupSizeMax     = 0x32,
+		dbiDownloadPath         = 0x33,
+		dbiAutoDownload         = 0x34,
+		dbiSavedGifsLimit       = 0x35,
+		dbiShowingSavedGifs     = 0x36,
+		dbiAutoPlay             = 0x37,
+		dbiAdaptiveForWide      = 0x38,
 		dbiHiddenPinnedMessages = 0x39,
+		dbiDialogsMode          = 0x40,
 
-		dbiEncryptedWithSalt = 333,
-		dbiEncrypted = 444,
+		dbiEncryptedWithSalt    = 333,
+		dbiEncrypted            = 444,
 
 		// 500-600 reserved
 
-		dbiVersion = 666,
+		dbiVersion              = 666,
 	};
 
 
@@ -981,6 +982,22 @@ namespace {
 			cSetAutoPlayGif(gif == 1);
 		} break;
 
+		case dbiDialogsMode: {
+			qint32 enabled, modeInt;
+			stream >> enabled >> modeInt;
+			if (!_checkStreamStatus(stream)) return false;
+
+			Global::SetDialogsModeEnabled(enabled == 1);
+			Dialogs::Mode mode = Dialogs::Mode::All;
+			if (enabled) {
+				mode = static_cast<Dialogs::Mode>(modeInt);
+				if (mode != Dialogs::Mode::All && mode != Dialogs::Mode::Important) {
+					mode = Dialogs::Mode::All;
+				}
+			}
+			Global::SetDialogsMode(mode);
+		} break;
+
 		case dbiIncludeMuted: {
 			qint32 v;
 			stream >> v;
@@ -1578,6 +1595,7 @@ namespace {
 		size += sizeof(quint32) + sizeof(qint32) + (cRecentStickersPreload().isEmpty() ? cGetRecentStickers().size() : cRecentStickersPreload().size()) * (sizeof(uint64) + sizeof(ushort));
 		size += sizeof(quint32) + Serialize::stringSize(cDialogLastPath());
 		size += sizeof(quint32) + 3 * sizeof(qint32);
+		size += sizeof(quint32) + 2 * sizeof(qint32);
 		if (!Global::HiddenPinnedMessages().isEmpty()) {
 			size += sizeof(quint32) + sizeof(qint32) + Global::HiddenPinnedMessages().size() * (sizeof(PeerId) + sizeof(MsgId));
 		}
@@ -1601,6 +1619,7 @@ namespace {
 		data.stream << quint32(dbiDialogLastPath) << cDialogLastPath();
 		data.stream << quint32(dbiSongVolume) << qint32(qRound(cSongVolume() * 1e6));
 		data.stream << quint32(dbiAutoDownload) << qint32(cAutoDownloadPhoto()) << qint32(cAutoDownloadAudio()) << qint32(cAutoDownloadGif());
+		data.stream << quint32(dbiDialogsMode) << qint32(Global::DialogsModeEnabled() ? 1 : 0) << static_cast<qint32>(Global::DialogsMode());
 		data.stream << quint32(dbiAutoPlay) << qint32(cAutoPlayGif() ? 1 : 0);
 
 		{
diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp
index 7d79406ed..a6836b2ee 100644
--- a/Telegram/SourceFiles/mainwidget.cpp
+++ b/Telegram/SourceFiles/mainwidget.cpp
@@ -844,6 +844,10 @@ void MainWidget::notify_inlineItemLayoutChanged(const InlineBots::Layout::ItemBa
 	history.notify_inlineItemLayoutChanged(layout);
 }
 
+void MainWidget::notify_historyMuteUpdated(History *history) {
+	dialogs.notify_historyMuteUpdated(history);
+}
+
 void MainWidget::notify_handlePendingHistoryUpdate() {
 	history.notify_handlePendingHistoryUpdate();
 }
@@ -1509,7 +1513,7 @@ void MainWidget::saveRecentHashtags(const QString &text) {
 }
 
 void MainWidget::readServerHistory(History *hist, bool force) {
-	if (!hist || (!force && !hist->unreadCount)) return;
+	if (!hist || (!force && !hist->unreadCount())) return;
 
 	MsgId upTo = hist->inboxRead(0);
 	if (hist->isChannel() && !hist->peer->asChannel()->amIn()) {
@@ -2665,14 +2669,18 @@ QRect MainWidget::historyRect() const {
 	return r;
 }
 
-void MainWidget::dlgUpdated(Dialogs::Row *row) {
-	if (row) {
-		dialogs.dlgUpdated(row);
-	} else if (_peerInStack) {
+void MainWidget::dlgUpdated() {
+	if (_peerInStack) {
 		dialogs.dlgUpdated(App::history(_peerInStack->id), _msgIdInStack);
 	}
 }
 
+void MainWidget::dlgUpdated(Dialogs::Mode list, Dialogs::Row *row) {
+	if (row) {
+		dialogs.dlgUpdated(list, row);
+	}
+}
+
 void MainWidget::dlgUpdated(History *row, MsgId msgId) {
 	if (!row) return;
 	if (msgId < 0 && -msgId < ServerMaxMsgId && row->peer->migrateFrom()) {
@@ -3113,7 +3121,7 @@ void MainWidget::gotChannelDifference(ChannelData *channel, const MTPupdates_Cha
 				h->setLastMessage(item);
 			}
 			int32 unreadCount = h->isMegagroup() ? d.vunread_count.v : d.vunread_important_count.v;
-			if (unreadCount >= h->unreadCount) {
+			if (unreadCount >= h->unreadCount()) {
 				h->setUnreadCount(unreadCount, false);
 				h->inboxReadBefore = d.vread_inbox_max_id.v + 1;
 			}
diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h
index dc787f08a..945225f6b 100644
--- a/Telegram/SourceFiles/mainwidget.h
+++ b/Telegram/SourceFiles/mainwidget.h
@@ -260,7 +260,8 @@ public:
 
 	void createDialog(History *history);
 	void removeDialog(History *history);
-	void dlgUpdated(Dialogs::Row *row = nullptr);
+	void dlgUpdated();
+	void dlgUpdated(Dialogs::Mode list, Dialogs::Row *row);
 	void dlgUpdated(History *row, MsgId msgId);
 
 	void windowShown();
@@ -467,6 +468,7 @@ public:
 	void notify_clipStopperHidden(ClipStopperType type);
 	void notify_historyItemLayoutChanged(const HistoryItem *item);
 	void notify_inlineItemLayoutChanged(const InlineBots::Layout::ItemBase *layout);
+	void notify_historyMuteUpdated(History *history);
 	void notify_handlePendingHistoryUpdate();
 
 	void cmd_search();
diff --git a/Telegram/SourceFiles/settingswidget.cpp b/Telegram/SourceFiles/settingswidget.cpp
index e53d898ee..cba8bc9ed 100644
--- a/Telegram/SourceFiles/settingswidget.cpp
+++ b/Telegram/SourceFiles/settingswidget.cpp
@@ -823,14 +823,22 @@ void SettingsInner::keyPressEvent(QKeyEvent *e) {
 			} else {
 				Global::RefDebugLoggingFlags() |= DebugLogging::FileLoaderFlag;
 			}
-			Ui::showLayer(new InformBox(DebugLogging::FileLoader() ? "Enabled file download logging" : "Disabled file download logging"));
+			Ui::showLayer(new InformBox(DebugLogging::FileLoader() ? qsl("Enabled file download logging") : qsl("Disabled file download logging")));
 		} else if (str == qstr("crashplease")) {
 			t_assert(!"Crashed in Settings!");
+		} else if (str == qstr("workmode")) {
+			QString text = Global::DialogsModeEnabled() ? qsl("Disable work mode?") : qsl("Enable work mode?");
+			auto box = std_::make_unique<ConfirmBox>(text);
+			connect(box.get(), SIGNAL(confirmed()), App::app(), SLOT(onSwitchWorkMode()));
+			Ui::showLayer(box.release());
+			from = size;
+			break;
 		} else if (
 			qsl("debugmode").startsWith(str) ||
 			qsl("testmode").startsWith(str) ||
 			qsl("loadlang").startsWith(str) ||
 			qsl("debugfiles").startsWith(str) ||
+			qsl("workmode").startsWith(str) ||
 			qsl("crashplease").startsWith(str)) {
 			break;
 		}
diff --git a/Telegram/ui/buttons/peer_avatar_button.cpp b/Telegram/ui/buttons/peer_avatar_button.cpp
new file mode 100644
index 000000000..7dbadc50c
--- /dev/null
+++ b/Telegram/ui/buttons/peer_avatar_button.cpp
@@ -0,0 +1,35 @@
+/*
+This file is part of Telegram Desktop,
+the official desktop version of Telegram messaging app, see https://telegram.org
+
+Telegram Desktop is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+It is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+In addition, as a special exception, the copyright holders give permission
+to link the code of portions of this program with the OpenSSL library.
+
+Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
+Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
+*/
+#include "stdafx.h"
+#include "ui/buttons/peer_avatar_button.h"
+
+PeerAvatarButton::PeerAvatarButton(QWidget *parent, PeerData *peer, const style::PeerAvatarButton &st) : Button(parent)
+, _peer(peer)
+, _st(st) {
+	resize(_st.size, _st.size);
+}
+
+void PeerAvatarButton::paintEvent(QPaintEvent *e) {
+	if (_peer) {
+		Painter p(this);
+		_peer->paintUserpic(p, _st.photoSize, (_st.size - _st.photoSize) / 2, (_st.size - _st.photoSize) / 2);
+	}
+}
diff --git a/Telegram/ui/buttons/peer_avatar_button.h b/Telegram/ui/buttons/peer_avatar_button.h
new file mode 100644
index 000000000..d0861fef9
--- /dev/null
+++ b/Telegram/ui/buttons/peer_avatar_button.h
@@ -0,0 +1,40 @@
+/*
+This file is part of Telegram Desktop,
+the official desktop version of Telegram messaging app, see https://telegram.org
+
+Telegram Desktop is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+It is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+In addition, as a special exception, the copyright holders give permission
+to link the code of portions of this program with the OpenSSL library.
+
+Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
+Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
+*/
+#pragma once
+
+#include "ui/button.h"
+#include "ui/style.h"
+#include "structs.h"
+
+class PeerAvatarButton : public Button {
+public:
+	PeerAvatarButton(QWidget *parent, PeerData *peer, const style::PeerAvatarButton &st);
+	void setPeer(PeerData *peer) {
+		_peer = peer;
+		update();
+	}
+	void paintEvent(QPaintEvent *e);
+
+private:
+	PeerData *_peer;
+	const style::PeerAvatarButton &_st;
+
+};