diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt
index 5ada019a8..357a487bb 100644
--- a/Telegram/Resources/style.txt
+++ b/Telegram/Resources/style.txt
@@ -1052,8 +1052,8 @@ msgMinWidth: 190px;
 msgPhotoSize: 33px;
 msgPhotoSkip: 40px;
 msgPadding: margins(13px, 7px, 13px, 8px);
-msgMargin: margins(13px, 6px, 53px, 2px);
-msgMarginTopAttached: 2px;
+msgMargin: margins(13px, 10px, 53px, 2px);
+msgMarginTopAttached: 3px;
 msgLnkPadding: 2px; // for media open / save links
 msgBorder: #f0f0f0;
 msgInBg: #fff;
@@ -1089,7 +1089,7 @@ msgServiceBg: #89a0b47f;
 msgServiceSelectBg: #bbc8d4a2;
 msgServiceColor: #FFF;
 msgServicePadding: margins(12px, 3px, 12px, 4px);
-msgServiceMargin: margins(10px, 9px, 80px, 5px);
+msgServiceMargin: margins(10px, 10px, 80px, 2px);
 
 msgColor: #000;
 msgDateColor: #000;
@@ -1527,6 +1527,7 @@ reportSpamBg: #fffffff0;
 newMsgSound: ':/gui/art/newmsg.wav';
 
 unreadBarHeight: 32px;
+unreadBarMargin: 8px;
 unreadBarFont: semiboldFont;
 unreadBarBG: #fcfbfa;
 unreadBarBorder: shadowColor;
diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp
index 18dfe7ae6..8d33b9797 100644
--- a/Telegram/SourceFiles/app.cpp
+++ b/Telegram/SourceFiles/app.cpp
@@ -180,21 +180,19 @@ namespace App {
 		return main() ? main()->api() : 0;
 	}
 
+namespace {
 	bool loggedOut() {
-		Window *w(wnd());
 		if (cHasPasscode()) {
 			cSetHasPasscode(false);
 		}
 		if (audioPlayer()) {
 			audioPlayer()->stopAndClear();
 		}
-		if (w) {
+		if (Window *w = wnd()) {
 			w->tempDirDelete(Local::ClearManagerAll);
 			w->notifyClearFast();
 			w->setupIntro(true);
 		}
-		MainWidget *m(main());
-		if (m) m->destroyData();
 		MTP::authed(0);
 		Local::reset();
 
@@ -205,13 +203,14 @@ namespace App {
 		globalNotifyChatsPtr = UnknownNotifySettings;
 		if (App::uploader()) App::uploader()->clear();
 		clearStorageImages();
-		if (w) {
+		if (Window *w = wnd()) {
 			w->getTitle()->updateBackButton();
 			w->updateTitleStatus();
 			w->getTitle()->resizeEvent(0);
 		}
 		return true;
 	}
+} // namespace
 
 	void logOut() {
 		if (MTP::started()) {
@@ -1454,12 +1453,12 @@ namespace App {
 
 	PeerData *peerByName(const QString &username) {
 		QString uname(username.trimmed());
-		for (PeersData::const_iterator i = peersData.cbegin(), e = peersData.cend(); i != e; ++i) {
-			if (!i.value()->userName().compare(uname, Qt::CaseInsensitive)) {
-				return i.value();
+		for_const (PeerData *peer, peersData) {
+			if (!peer->userName().compare(uname, Qt::CaseInsensitive)) {
+				return peer;
 			}
 		}
-		return 0;
+		return nullptr;
 	}
 
 	void updateImage(ImagePtr &old, ImagePtr now) {
@@ -1867,20 +1866,20 @@ namespace App {
 		cSetSavedPeers(SavedPeers());
 		cSetSavedPeersByTime(SavedPeersByTime());
 		cSetRecentInlineBots(RecentInlineBots());
-		for (PeersData::const_iterator i = peersData.cbegin(), e = peersData.cend(); i != e; ++i) {
-			delete *i;
+		for_const (PeerData *peer, peersData) {
+			delete peer;
 		}
 		peersData.clear();
-		for (PhotosData::const_iterator i = ::photosData.cbegin(), e = ::photosData.cend(); i != e; ++i) {
-			delete *i;
+		for_const (PhotoData *photo, ::photosData) {
+			delete photo;
 		}
 		::photosData.clear();
-		for (DocumentsData::const_iterator i = ::documentsData.cbegin(), e = ::documentsData.cend(); i != e; ++i) {
-			delete *i;
+		for_const (DocumentData *document, ::documentsData) {
+			delete document;
 		}
 		::documentsData.clear();
-		for (WebPagesData::const_iterator i = webPagesData.cbegin(), e = webPagesData.cend(); i != e; ++i) {
-			delete *i;
+		for_const (WebPageData *webpage, webPagesData) {
+			delete webpage;
 		}
 		webPagesData.clear();
 		if (api()) api()->clearWebPageRequests();
diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h
index ebe1711e5..ac475da29 100644
--- a/Telegram/SourceFiles/app.h
+++ b/Telegram/SourceFiles/app.h
@@ -64,7 +64,6 @@ namespace App {
 	ApiWrap *api();
 
 	void logOut();
-	bool loggedOut();
 
 	QString formatPhone(QString phone);
 
diff --git a/Telegram/SourceFiles/dropdown.cpp b/Telegram/SourceFiles/dropdown.cpp
index ee475348b..97d672a1d 100644
--- a/Telegram/SourceFiles/dropdown.cpp
+++ b/Telegram/SourceFiles/dropdown.cpp
@@ -941,6 +941,8 @@ void EmojiPanInner::selectEmoji(EmojiPtr emoji) {
 }
 
 void EmojiPanInner::onShowPicker() {
+	if (_pickerSel < 0) return;
+
 	int tab = (_pickerSel / MatrixRowShift), sel = _pickerSel % MatrixRowShift;
 	if (tab < emojiTabCount && sel < _emojis[tab].size() && _emojis[tab][sel]->color) {
 		int32 y = 0;
diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp
index 0b9557e3d..d89aec33f 100644
--- a/Telegram/SourceFiles/facades.cpp
+++ b/Telegram/SourceFiles/facades.cpp
@@ -86,6 +86,12 @@ namespace App {
 		}
 	}
 
+	void logOutDelayed() {
+		if (Window *w = App::wnd()) {
+			QMetaObject::invokeMethod(w, "onLogoutSure", Qt::QueuedConnection);
+		}
+	}
+
 }
 
 namespace Ui {
diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h
index ba77a20a2..14b16742e 100644
--- a/Telegram/SourceFiles/facades.h
+++ b/Telegram/SourceFiles/facades.h
@@ -37,6 +37,8 @@ namespace App {
 
 	void activateTextLink(TextLinkPtr link, Qt::MouseButton button);
 
+	void logOutDelayed();
+
 };
 
 namespace Ui {
diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp
index 3231bf89f..9aa63c654 100644
--- a/Telegram/SourceFiles/history.cpp
+++ b/Telegram/SourceFiles/history.cpp
@@ -1125,6 +1125,8 @@ void Histories::clear() {
 	for (Map::const_iterator i = map.cbegin(), e = map.cend(); i != e; ++i) {
 		delete i.value();
 	}
+	Global::RefPendingRepaintItems().clear();
+
 	_unreadFull = _unreadMuted = 0;
 	if (App::wnd()) {
 		App::wnd()->updateCounter();
@@ -2753,13 +2755,17 @@ void HistoryMessageUnreadBar::init(int count) {
 	_width = st::semiboldFont->width(_text);
 }
 
-int HistoryMessageUnreadBar::height() const {
-	return st::unreadBarHeight;
+int HistoryMessageUnreadBar::height() {
+	return st::unreadBarHeight + st::unreadBarMargin;
+}
+
+int HistoryMessageUnreadBar::marginTop() {
+	return st::lineWidth + st::unreadBarMargin;
 }
 
 void HistoryMessageUnreadBar::paint(Painter &p, int y, int w) const {
-	p.fillRect(0, y + st::lineWidth, w, st::unreadBarHeight - 2 * st::lineWidth, st::unreadBarBG);
-	p.fillRect(0, y + st::unreadBarHeight - st::lineWidth, w, st::lineWidth, st::unreadBarBorder);
+	p.fillRect(0, y + marginTop(), w, height() - marginTop() - st::lineWidth, st::unreadBarBG);
+	p.fillRect(0, y + height() - st::lineWidth, w, st::lineWidth, st::unreadBarBorder);
 	p.setFont(st::unreadBarFont);
 	p.setPen(st::unreadBarColor);
 
@@ -2770,7 +2776,7 @@ void HistoryMessageUnreadBar::paint(Painter &p, int y, int w) const {
 	}
 	w = maxwidth;
 
-	p.drawText((w - _width) / 2, y + (st::unreadBarHeight - st::lineWidth - st::unreadBarFont->height) / 2 + st::unreadBarFont->ascent, _text);
+	p.drawText((w - _width) / 2, y + marginTop() + (st::unreadBarHeight - 2 * st::lineWidth - st::unreadBarFont->height) / 2 + st::unreadBarFont->ascent, _text);
 }
 
 void HistoryMessageDate::init(const QDateTime &date) {
@@ -2833,6 +2839,7 @@ void HistoryItem::destroy() {
 	if ((!out() || isPost()) && unread() && history()->unreadCount > 0) {
 		history()->setUnreadCount(history()->unreadCount - 1);
 	}
+	Global::RefPendingRepaintItems().remove(this);
 	delete this;
 }
 
@@ -3039,7 +3046,8 @@ void RadialAnimation::update(float64 prg, bool finished, uint64 ms) {
 		_opacity *= 1 - r;
 	}
 	float64 fromstart = fulldt / st::radialPeriod;
-	a_arcStart.update(fromstart - qFloor(fromstart), anim::linear);
+	float64 fromstartpart = fromstart - std::floor(fromstart);
+	a_arcStart.update(static_cast<int>(fromstartpart), anim::linear);
 }
 
 void RadialAnimation::stop() {
@@ -4862,7 +4870,7 @@ void HistorySticker::draw(Painter &p, const HistoryItem *parent, const QRect &r,
 	}
 
 	if (parent->getMedia() == this) {
-		parent->drawInfo(p, usex + usew, _height, usex * 2 + usew, selected, InfoDisplayOverImage);
+		parent->drawInfo(p, usex + usew, _height, usex * 2 + usew, selected, InfoDisplayOverBackground);
 
 		if (reply) {
 			int32 rw = _width - usew - st::msgReplyPadding.left(), rh = st::msgReplyPadding.top() + st::msgReplyBarSize.height() + st::msgReplyPadding.bottom();
@@ -6630,18 +6638,24 @@ bool HistoryMessage::textHasLinks() {
 void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, int32 width, bool selected, InfoDisplayType type) const {
 	p.setFont(st::msgDateFont);
 
-	bool outbg = out() && !isPost(), overimg = (type == InfoDisplayOverImage);
+	bool outbg = out() && !isPost();
+	bool invertedsprites = (type == InfoDisplayOverImage || type == InfoDisplayOverBackground);
 	int32 infoRight = right, infoBottom = bottom;
 	switch (type) {
 	case InfoDisplayDefault:
 		infoRight -= st::msgPadding.right() - st::msgDateDelta.x();
 		infoBottom -= st::msgPadding.bottom() - st::msgDateDelta.y();
-		p.setPen((selected ? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected) : (outbg ? st::msgOutDateFg : st::msgInDateFg))->p);
+		p.setPen(selected ? (outbg ? st::msgOutDateFgSelected : st::msgInDateFgSelected) : (outbg ? st::msgOutDateFg : st::msgInDateFg));
 	break;
 	case InfoDisplayOverImage:
 		infoRight -= st::msgDateImgDelta + st::msgDateImgPadding.x();
 		infoBottom -= st::msgDateImgDelta + st::msgDateImgPadding.y();
-		p.setPen(st::msgDateImgColor->p);
+		p.setPen(st::msgDateImgColor);
+	break;
+	case InfoDisplayOverBackground:
+		infoRight -= st::msgDateImgDelta + st::msgDateImgPadding.x();
+		infoBottom -= st::msgDateImgDelta + st::msgDateImgPadding.y();
+		p.setPen(st::msgServiceColor);
 	break;
 	}
 
@@ -6653,6 +6667,9 @@ void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, int32 width
 	if (type == InfoDisplayOverImage) {
 		int32 dateW = infoW + 2 * st::msgDateImgPadding.x(), dateH = st::msgDateFont->height + 2 * st::msgDateImgPadding.y();
 		App::roundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, selected ? st::msgDateImgBgSelected : st::msgDateImgBg, selected ? DateSelectedCorners : DateCorners);
+	} else if (type == InfoDisplayOverBackground) {
+		int32 dateW = infoW + 2 * st::msgDateImgPadding.x(), dateH = st::msgDateFont->height + 2 * st::msgDateImgPadding.y();
+		App::roundRect(p, dateX - st::msgDateImgPadding.x(), dateY - st::msgDateImgPadding.y(), dateW, dateH, App::msgServiceBg(), ServiceCorners);
 	}
 	dateX += HistoryMessage::timeLeft();
 
@@ -6668,35 +6685,35 @@ void HistoryMessage::drawInfo(Painter &p, int32 right, int32 bottom, int32 width
 		iconPos = QPoint(infoRight - infoW + st::msgViewsPos.x(), infoBottom - st::msgViewsImg.pxHeight() + st::msgViewsPos.y());
 		if (id > 0) {
 			if (outbg) {
-				iconRect = &(overimg ? st::msgInvViewsImg : (selected ? st::msgSelectOutViewsImg : st::msgOutViewsImg));
+				iconRect = &(invertedsprites ? st::msgInvViewsImg : (selected ? st::msgSelectOutViewsImg : st::msgOutViewsImg));
 			} else {
-				iconRect = &(overimg ? st::msgInvViewsImg : (selected ? st::msgSelectViewsImg : st::msgViewsImg));
+				iconRect = &(invertedsprites ? st::msgInvViewsImg : (selected ? st::msgSelectViewsImg : st::msgViewsImg));
 			}
 			p.drawText(iconPos.x() + st::msgViewsImg.pxWidth() + st::msgDateCheckSpace, infoBottom - st::msgDateFont->descent, views->_viewsText);
 		} else {
 			iconPos.setX(iconPos.x() + st::msgDateViewsSpace + views->_viewsWidth);
 			if (outbg) {
-				iconRect = &(overimg ? st::msgInvSendingViewsImg : st::msgSendingOutViewsImg);
+				iconRect = &(invertedsprites ? st::msgInvSendingViewsImg : st::msgSendingOutViewsImg);
 			} else {
-				iconRect = &(overimg ? st::msgInvSendingViewsImg : st::msgSendingViewsImg);
+				iconRect = &(invertedsprites ? st::msgInvSendingViewsImg : st::msgSendingViewsImg);
 			}
 		}
 		p.drawPixmap(iconPos, App::sprite(), *iconRect);
 	} else if (id < 0 && history()->peer->isSelf()) {
 		iconPos = QPoint(infoRight - infoW, infoBottom - st::msgViewsImg.pxHeight() + st::msgViewsPos.y());
-		iconRect = &(overimg ? st::msgInvSendingViewsImg : st::msgSendingViewsImg);
+		iconRect = &(invertedsprites ? st::msgInvSendingViewsImg : st::msgSendingViewsImg);
 		p.drawPixmap(iconPos, App::sprite(), *iconRect);
 	}
 	if (outbg) {
 		iconPos = QPoint(infoRight - st::msgCheckImg.pxWidth() + st::msgCheckPos.x(), infoBottom - st::msgCheckImg.pxHeight() + st::msgCheckPos.y());
 		if (id > 0) {
 			if (unread()) {
-				iconRect = &(overimg ? st::msgInvCheckImg : (selected ? st::msgSelectCheckImg : st::msgCheckImg));
+				iconRect = &(invertedsprites ? st::msgInvCheckImg : (selected ? st::msgSelectCheckImg : st::msgCheckImg));
 			} else {
-				iconRect = &(overimg ? st::msgInvDblCheckImg : (selected ? st::msgSelectDblCheckImg : st::msgDblCheckImg));
+				iconRect = &(invertedsprites ? st::msgInvDblCheckImg : (selected ? st::msgSelectDblCheckImg : st::msgDblCheckImg));
 			}
 		} else {
-			iconRect = &(overimg ? st::msgInvSendingImg : st::msgSendingImg);
+			iconRect = &(invertedsprites ? st::msgInvSendingImg : st::msgSendingImg);
 		}
 		p.drawPixmap(iconPos, App::sprite(), *iconRect);
 	}
diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h
index 1dd9dd95e..4d8350488 100644
--- a/Telegram/SourceFiles/history.h
+++ b/Telegram/SourceFiles/history.h
@@ -987,6 +987,7 @@ enum HistoryCursorState {
 enum InfoDisplayType {
 	InfoDisplayDefault,
 	InfoDisplayOverImage,
+	InfoDisplayOverBackground,
 };
 
 inline bool isImportantChannelMessage(MsgId id, MTPDmessage::Flags flags) { // client-side important msgs always has_views or has_from_id
@@ -1130,7 +1131,9 @@ struct HistoryMessageUnreadBar : public BaseComponent<HistoryMessageUnreadBar> {
 	}
 	void init(int count);
 
-	int height() const;
+	static int height();
+	static int marginTop();
+
 	void paint(Painter &p, int y, int w) const;
 
 	QString _text;
@@ -1536,8 +1539,11 @@ protected:
 
 	HistoryItem *previous() const {
 		if (_block && _indexInBlock >= 0) {
-			if (_indexInBlock > 0) return _block->items.at(_indexInBlock - 1);
+			if (_indexInBlock > 0) {
+				return _block->items.at(_indexInBlock - 1);
+			}
 			if (HistoryBlock *previousBlock = _block->previous()) {
+				t_assert(!previousBlock->items.isEmpty());
 				return previousBlock->items.back();
 			}
 		}
diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp
index c8f665649..43cd4b360 100644
--- a/Telegram/SourceFiles/historywidget.cpp
+++ b/Telegram/SourceFiles/historywidget.cpp
@@ -6444,7 +6444,9 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh
 	if (_pinnedBar) {
 		newScrollHeight -= st::replyHeight;
 	}
-	bool wasAtBottom = _scroll.scrollTop() + 1 > _scroll.scrollTopMax(), needResize = _scroll.width() != width() || _scroll.height() != newScrollHeight;
+	int wasScrollTop = _scroll.scrollTop();
+	bool wasAtBottom = wasScrollTop + 1 > _scroll.scrollTopMax();
+	bool needResize = (_scroll.width() != width()) || (_scroll.height() != newScrollHeight);
 	if (needResize) {
 		_scroll.resize(width(), newScrollHeight);
 		// on initial updateListSize we didn't put the _scroll.scrollTop correctly yet
@@ -6470,14 +6472,15 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh
 	}
 
 	if ((!initial && !wasAtBottom) || (loadedDown && (!_history->showFrom || _history->unreadBar || _history->loadedAtBottom()) && (!_migrated || !_migrated->showFrom || _migrated->unreadBar || _history->loadedAtBottom()))) {
-		int addToY = 0;
+		int toY = _list->historyScrollTop();
 		if (change.type == ScrollChangeAdd) {
-			addToY = change.value;
-		} else if (change.type == ScrollChangeOldHistoryHeight) {
-			addToY = _list->historyHeight() - change.value;
+			toY += change.value;
+		} else if (change.type == ScrollChangeNoJumpToBottom) {
+			toY = wasScrollTop;
+		}
+		if (toY > _scroll.scrollTopMax()) {
+			toY = _scroll.scrollTopMax();
 		}
-		int toY = _list->historyScrollTop() + addToY;
-		if (toY > _scroll.scrollTopMax()) toY = _scroll.scrollTopMax();
 		if (_scroll.scrollTop() == toY) {
 			visibleAreaUpdated();
 		} else {
@@ -6555,19 +6558,11 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh
 		} else {
 			toY = qMax(iy + item->height() - _fixedInScrollMsgTop, 0);
 		}
-	} else if (initial && _migrated && _migrated->unreadBar) {
-		toY = _list->itemTop(_migrated->unreadBar);
-		if (_migrated->unreadBar->Has<HistoryMessageDate>()) {
-			toY += _migrated->unreadBar->Get<HistoryMessageDate>()->height();
-		}
-	} else if (initial && _history->unreadBar) {
-		toY = _list->itemTop(_history->unreadBar);
-		if (_history->unreadBar->Has<HistoryMessageDate>()) {
-			toY += _history->unreadBar->Get<HistoryMessageDate>()->height();
-		}
+	} else if (initial && (_history->unreadBar || (_migrated && _migrated->unreadBar))) {
+		toY = unreadBarTop();
 	} else if (_migrated && _migrated->showFrom) {
 		toY = _list->itemTop(_migrated->showFrom);
-		if (toY < _scroll.scrollTopMax() + st::unreadBarHeight) {
+		if (toY < _scroll.scrollTopMax() + HistoryMessageUnreadBar::height() - HistoryMessageUnreadBar::marginTop()) {
 			_migrated->addUnreadBar();
 			if (_migrated->unreadBar) {
 				setMsgId(ShowAtUnreadMsgId);
@@ -6599,6 +6594,26 @@ void HistoryWidget::updateListSize(bool initial, bool loadedDown, const ScrollCh
 	}
 }
 
+int HistoryWidget::unreadBarTop() const {
+	auto getUnreadBar = [this]() -> HistoryItem* {
+		if (_migrated && _migrated->unreadBar) {
+			return _migrated->unreadBar;
+		}
+		if (_history->unreadBar) {
+			return _history->unreadBar;
+		}
+		return nullptr;
+	};
+	if (HistoryItem *bar = getUnreadBar()) {
+		int result = _list->itemTop(bar) + HistoryMessageUnreadBar::marginTop();
+		if (bar->Has<HistoryMessageDate>()) {
+			result += bar->Get<HistoryMessageDate>()->height();
+		}
+		return result;
+	}
+	return -1;
+}
+
 void HistoryWidget::addMessagesToFront(PeerData *peer, const QVector<MTPMessage> &messages, const QVector<MTPMessageGroup> *collapsed) {
 	int oldH = _list->historyHeight();
 	_list->messagesReceived(peer, messages, collapsed);
@@ -6617,7 +6632,7 @@ void HistoryWidget::addMessagesToFront(PeerData *peer, const QVector<MTPMessage>
 void HistoryWidget::addMessagesToBack(PeerData *peer, const QVector<MTPMessage> &messages, const QVector<MTPMessageGroup> *collapsed) {
 	_list->messagesReceivedDown(peer, messages, collapsed);
 	if (!_firstLoadRequest) {
-		updateListSize(false, true);
+		updateListSize(false, true, { ScrollChangeNoJumpToBottom, 0 });
 	}
 }
 
@@ -7001,7 +7016,10 @@ bool HistoryWidget::pinnedMsgVisibilityUpdated() {
 			_topShadow.raise();
 			updatePinnedBar();
 			result = true;
-			_scroll.scrollToY(_scroll.scrollTop() + st::replyHeight);
+
+			if (_scroll.scrollTop() != unreadBarTop()) {
+				_scroll.scrollToY(_scroll.scrollTop() + st::replyHeight);
+			}
 		} else if (_pinnedBar->msgId != pinnedMsgId) {
 			_pinnedBar->msgId = pinnedMsgId;
 			_pinnedBar->msg = 0;
@@ -7015,7 +7033,9 @@ bool HistoryWidget::pinnedMsgVisibilityUpdated() {
 	} else if (_pinnedBar) {
 		destroyPinnedBar();
 		result = true;
-		_scroll.scrollToY(_scroll.scrollTop() - st::replyHeight);
+		if (_scroll.scrollTop() != unreadBarTop()) {
+			_scroll.scrollToY(_scroll.scrollTop() - st::replyHeight);
+		}
 		resizeEvent(0);
 	}
 	return result;
diff --git a/Telegram/SourceFiles/historywidget.h b/Telegram/SourceFiles/historywidget.h
index 5eabc4ffb..d8d8b542e 100644
--- a/Telegram/SourceFiles/historywidget.h
+++ b/Telegram/SourceFiles/historywidget.h
@@ -834,8 +834,12 @@ private:
 
 	enum ScrollChangeType {
 		ScrollChangeNone,
+
+		// When we toggle a pinned message.
 		ScrollChangeAdd,
-		ScrollChangeOldHistoryHeight,
+
+		// When loading a history part while scrolling down.
+		ScrollChangeNoJumpToBottom,
 	};
 	struct ScrollChange {
 		ScrollChangeType type;
@@ -843,6 +847,10 @@ private:
 	};
 	void updateListSize(bool initial = false, bool loadedDown = false, const ScrollChange &change = { ScrollChangeNone, 0 });
 
+	// Counts scrollTop for placing the scroll right at the unread
+	// messages bar, choosing from _history and _migrated unreadBar.
+	int unreadBarTop() const;
+
 	void saveGifDone(DocumentData *doc, const MTPBool &result);
 
 	void reportSpamDone(PeerData *peer, const MTPBool &result, mtpRequestId request);
diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp
index 2f2805d1e..b62ea7d61 100644
--- a/Telegram/SourceFiles/mainwidget.cpp
+++ b/Telegram/SourceFiles/mainwidget.cpp
@@ -2958,9 +2958,7 @@ void MainWidget::feedMessageIds(const MTPVector<MTPUpdate> &updates) {
 }
 
 bool MainWidget::updateFail(const RPCError &e) {
-	if (MTP::authedId()) {
-		App::logOut();
-	}
+	App::logOutDelayed();
 	return true;
 }
 
@@ -3707,7 +3705,7 @@ bool MainWidget::inviteImportFail(const RPCError &error) {
 void MainWidget::startFull(const MTPVector<MTPUser> &users) {
 	const QVector<MTPUser> &v(users.c_vector().v);
 	if (v.isEmpty() || v[0].type() != mtpc_user || !v[0].c_user().is_self()) { // wtf?..
-		return App::logOut();
+		return App::logOutDelayed();
 	}
 	start(v[0]);
 }
diff --git a/Telegram/SourceFiles/types.h b/Telegram/SourceFiles/types.h
index 3a775b9cb..bbf44693d 100644
--- a/Telegram/SourceFiles/types.h
+++ b/Telegram/SourceFiles/types.h
@@ -650,20 +650,20 @@ MimeType mimeTypeForName(const QString &mime);
 MimeType mimeTypeForFile(const QFileInfo &file);
 MimeType mimeTypeForData(const QByteArray &data);
 
-inline int32 rowscount(int32 count, int32 perrow) {
-	return (count + perrow - 1) / perrow;
+inline int rowscount(int fullCount, int countPerRow) {
+	return (fullCount + countPerRow - 1) / countPerRow;
 }
-inline int32 floorclamp(int32 value, int32 step, int32 lowest, int32 highest) {
+inline int floorclamp(int value, int step, int lowest, int highest) {
 	return qMin(qMax(value / step, lowest), highest);
 }
-inline int32 floorclamp(float64 value, int32 step, int32 lowest, int32 highest) {
-	return qMin(qMax(qFloor(value / step), lowest), highest);
+inline int floorclamp(float64 value, int step, int lowest, int highest) {
+	return qMin(qMax(static_cast<int>(std::floor(value / step)), lowest), highest);
 }
-inline int32 ceilclamp(int32 value, int32 step, int32 lowest, int32 highest) {
-	return qMax(qMin((value / step) + ((value % step) ? 1 : 0), highest), lowest);
+inline int ceilclamp(int value, int step, int lowest, int highest) {
+	return qMax(qMin((value + step - 1) / step, highest), lowest);
 }
-inline int32 ceilclamp(float64 value, int32 step, int32 lowest, int32 highest) {
-	return qMax(qMin(qCeil(value / step), highest), lowest);
+inline int ceilclamp(float64 value, int32 step, int32 lowest, int32 highest) {
+	return qMax(qMin(static_cast<int>(std::ceil(value / step)), highest), lowest);
 }
 
 enum ForwardWhatMessages {
diff --git a/Telegram/SourceFiles/window.cpp b/Telegram/SourceFiles/window.cpp
index 6decac3f6..74d58158e 100644
--- a/Telegram/SourceFiles/window.cpp
+++ b/Telegram/SourceFiles/window.cpp
@@ -507,11 +507,8 @@ void Window::clearWidgets() {
 		settings = 0;
 	}
 	if (main) {
-		main->animStop_show();
-		main->hide();
-		main->deleteLater();
-		main->rpcClear();
-		main = 0;
+		delete main;
+		main = nullptr;
 	}
 	if (intro) {
 		intro->stop_show();
@@ -693,7 +690,7 @@ void Window::setupMain(bool anim, const MTPUser *self) {
 }
 
 void Window::updateCounter() {
-	if (App::quitting()) return;
+	if (!Global::started() || App::quitting()) return;
 
 	psUpdateCounter();
 	title->updateCounter();
@@ -1178,7 +1175,11 @@ void Window::onLogout() {
 }
 
 void Window::onLogoutSure() {
-	App::logOut();
+	if (MTP::authedId()) {
+		App::logOut();
+	} else {
+		setupIntro(true);
+	}
 }
 
 void Window::updateGlobalMenu() {
@@ -1944,7 +1945,10 @@ PreLaunchWindow::PreLaunchWindow(QString title) : TWidget(0) {
 	tmp.setText(qsl("Tmp"));
 	_size = tmp.sizeHint().height();
 
-	setStyleSheet(qsl("QPushButton { padding: %1px %2px; background-color: #ffffff; border-radius: %3px; }\nQPushButton#confirm:hover, QPushButton#cancel:hover { background-color: #edf7ff; color: #2f9fea; }\nQPushButton#confirm { color: #2f9fea; }\nQPushButton#cancel { color: #aeaeae; }\nQLineEdit { border: 1px solid #e0e0e0; padding: 5px; }\nQLineEdit:focus { border: 2px solid #62c0f7; padding: 4px; }").arg(qFloor(_size / 2)).arg(qFloor(_size)).arg(qFloor(_size / 5)));
+	int paddingVertical = (_size / 2);
+	int paddingHorizontal = _size;
+	int borderRadius = (_size / 5);
+	setStyleSheet(qsl("QPushButton { padding: %1px %2px; background-color: #ffffff; border-radius: %3px; }\nQPushButton#confirm:hover, QPushButton#cancel:hover { background-color: #edf7ff; color: #2f9fea; }\nQPushButton#confirm { color: #2f9fea; }\nQPushButton#cancel { color: #aeaeae; }\nQLineEdit { border: 1px solid #e0e0e0; padding: 5px; }\nQLineEdit:focus { border: 2px solid #62c0f7; padding: 4px; }").arg(paddingVertical).arg(paddingHorizontal).arg(borderRadius));
 	if (!PreLaunchWindowInstance) {
 		PreLaunchWindowInstance = this;
 	}
diff --git a/Telegram/SourceFiles/window.h b/Telegram/SourceFiles/window.h
index cecad8cf7..0fd5df1b4 100644
--- a/Telegram/SourceFiles/window.h
+++ b/Telegram/SourceFiles/window.h
@@ -362,7 +362,7 @@ public:
 
 	PreLaunchWindow(QString title = QString());
 	void activate();
-	float64 basicSize() const {
+	int basicSize() const {
 		return _size;
 	}
 	~PreLaunchWindow();
@@ -371,7 +371,7 @@ public:
 
 protected:
 
-	float64 _size;
+	int _size;
 
 };