diff --git a/Telegram/Resources/lang.txt b/Telegram/Resources/lang.txt
index e43b37c7c..7d51dd799 100644
--- a/Telegram/Resources/lang.txt
+++ b/Telegram/Resources/lang.txt
@@ -241,9 +241,9 @@ lng_profile_no_media: "No media in this conversation.";
 lng_profile_photo: "{count} photo »";
 lng_profile_photos: "{count} photos »";
 lng_profile_photos_header: "Photos overview";
-lng_profile_video: "{count} videofile »";
-lng_profile_videos: "{count} videofiles »";
-lng_profile_videos_header: "Videofiles overview";
+lng_profile_video: "{count} video file »";
+lng_profile_videos: "{count} video files »";
+lng_profile_videos_header: "Video files overview";
 lng_profile_document: "{count} document »";
 lng_profile_documents: "{count} documents »";
 lng_profile_documents_header: "Documents overview";
@@ -288,21 +288,27 @@ lng_action_checked_in: "{from} checked in";
 lng_forwarded_from: "Forwarded from ";
 
 lng_attach_failed: "Failed";
-lng_attach_file: "File";
+lng_attach_file: "Document";
 lng_attach_photo: "Photo";
 
+lng_media_type: "Media type";
+lng_media_type_photos: "Photos";
+lng_media_type_videos: "Video files";
+lng_media_type_documents: "Documents";
+lng_media_type_audios: "Voice messages";
+
 lng_media_open_with: "Open With";
 lng_media_download: "Download";
 lng_media_cancel: "Cancel";
-lng_media_video: "Video";
-lng_media_audio: "Audio";
+lng_media_video: "Video file";
+lng_media_audio: "Voice message";
 
 lng_in_dlg_photo: "Photo";
 lng_in_dlg_video: "Video";
 lng_in_dlg_geo: "Map";
 lng_in_dlg_contact: "Contact";
 lng_in_dlg_audio: "Audio";
-lng_in_dlg_document: "File";
+lng_in_dlg_document: "Document";
 
 lng_send_button: "Send";
 lng_message_ph: "Write a message...";
diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt
index 9d6073fe8..ea297c726 100644
--- a/Telegram/Resources/style.txt
+++ b/Telegram/Resources/style.txt
@@ -1303,6 +1303,20 @@ dropdownAttachPhoto: iconedButton(dropdownAttachDocument) {
 	icon: sprite(113px, 0px, 24px, 24px);
 	downIcon: sprite(113px, 0px, 24px, 24px);
 }
+dropdownMediaPhotos: iconedButton(dropdownAttachPhoto) {
+	width: 200px;
+}
+dropdownMediaVideos: iconedButton(dropdownMediaPhotos) {
+	icon: sprite(79px, 348px, 24px, 24px);
+	downIcon: sprite(79px, 348px, 24px, 24px);
+}
+dropdownMediaDocuments: iconedButton(dropdownAttachDocument) {
+	width: 200px;
+}
+dropdownMediaAudios: iconedButton(dropdownMediaDocuments) {
+	icon: sprite(49px, 348px, 24px, 24px);
+	downIcon: sprite(49px, 348px, 24px, 24px);
+}
 
 dragFont: font(28px semibold);
 dragSubfont: font(20px semibold);
diff --git a/Telegram/SourceFiles/art/sprite.png b/Telegram/SourceFiles/art/sprite.png
index dd716c3f6..1a270bcaf 100644
Binary files a/Telegram/SourceFiles/art/sprite.png and b/Telegram/SourceFiles/art/sprite.png differ
diff --git a/Telegram/SourceFiles/art/sprite_200x.png b/Telegram/SourceFiles/art/sprite_200x.png
index cac720556..b0030a2b9 100644
Binary files a/Telegram/SourceFiles/art/sprite_200x.png and b/Telegram/SourceFiles/art/sprite_200x.png differ
diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp
index eb35b0acc..32d98c263 100644
--- a/Telegram/SourceFiles/dialogswidget.cpp
+++ b/Telegram/SourceFiles/dialogswidget.cpp
@@ -461,7 +461,7 @@ void DialogsListWidget::onItemReplaced(HistoryItem *oldItem, HistoryItem *newIte
 
 void DialogsListWidget::onItemRemoved(HistoryItem *item) {
 	int wasCount = searchResults.size();
-	for (int i = 0; i < searchResults.size(); ++i) {
+	for (int i = 0; i < searchResults.size();) {
 		if (searchResults[i]->_item == item) {
 			searchResults.remove(i);
 		} else {
diff --git a/Telegram/SourceFiles/dropdown.cpp b/Telegram/SourceFiles/dropdown.cpp
index a1b50545a..25664b1cc 100644
--- a/Telegram/SourceFiles/dropdown.cpp
+++ b/Telegram/SourceFiles/dropdown.cpp
@@ -24,9 +24,7 @@ Copyright (c) 2014 John Preston, https://tdesktop.com
 
 Dropdown::Dropdown(QWidget *parent) : TWidget(parent),
 	_hiding(false), a_opacity(0), _shadow(st::dropdownShadow) {
-	_width = st::dropdownPadding.left() + st::dropdownPadding.right();
-	_height = st::dropdownPadding.top() + st::dropdownPadding.bottom();
-	resize(_width, _height);
+	resetButtons();
 
 	_hideTimer.setSingleShot(true);
 	connect(&_hideTimer, SIGNAL(timeout()), this, SLOT(hideStart()));
@@ -48,6 +46,16 @@ IconedButton *Dropdown::addButton(IconedButton *button) {
 	return button;
 }
 
+void Dropdown::resetButtons() {
+	_width = st::dropdownPadding.left() + st::dropdownPadding.right();
+	_height = st::dropdownPadding.top() + st::dropdownPadding.bottom();
+	resize(_width, _height);
+	for (int32 i = 0, l = _buttons.size(); i < l; ++i) {
+		delete _buttons[i];
+	}
+	_buttons.clear();
+}
+
 void Dropdown::resizeEvent(QResizeEvent *e) {
 	int32 top = st::dropdownPadding.top();
 	for (Buttons::const_iterator i = _buttons.cbegin(), e = _buttons.cend(); i != e; ++i) {
diff --git a/Telegram/SourceFiles/dropdown.h b/Telegram/SourceFiles/dropdown.h
index 92b46d9f1..797551721 100644
--- a/Telegram/SourceFiles/dropdown.h
+++ b/Telegram/SourceFiles/dropdown.h
@@ -28,6 +28,7 @@ public:
 	Dropdown(QWidget *parent);
 
 	IconedButton *addButton(IconedButton *button);
+	void resetButtons();
 
 	void resizeEvent(QResizeEvent *e);
 	void paintEvent(QPaintEvent *e);
diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h
index 2e321c166..5f6cf59ac 100644
--- a/Telegram/SourceFiles/history.h
+++ b/Telegram/SourceFiles/history.h
@@ -126,15 +126,15 @@ struct PeerData {
 
 class PeerLink : public ITextLink {
 public:
-	PeerLink(const PeerData *peer) : _peer(peer) {
+	PeerLink(PeerData *peer) : _peer(peer) {
 	}
 	void onClick(Qt::MouseButton button) const;
-	const PeerData *peer() const {
+	PeerData *peer() const {
 		return _peer;
 	}
 
 private:
-	const PeerData *_peer;
+	PeerData *_peer;
 };
 
 struct PhotoData;
diff --git a/Telegram/SourceFiles/historywidget.cpp b/Telegram/SourceFiles/historywidget.cpp
index 3cd5ac269..dcb111be9 100644
--- a/Telegram/SourceFiles/historywidget.cpp
+++ b/Telegram/SourceFiles/historywidget.cpp
@@ -241,6 +241,10 @@ void HistoryList::touchEvent(QTouchEvent *e) {
 	
 	switch (e->type()) {
 	case QEvent::TouchBegin:
+		if (_menu) {
+			e->accept();
+			return; // ignore mouse press, that was hiding context menu
+		}
 		if (_touchInProgress) return;
 		if (e->touchPoints().isEmpty()) return;
 
diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp
index 9b3cf8aa9..08bb82469 100644
--- a/Telegram/SourceFiles/mainwidget.cpp
+++ b/Telegram/SourceFiles/mainwidget.cpp
@@ -34,7 +34,8 @@ TopBarWidget::TopBarWidget(MainWidget *w) : QWidget(w),
 	_edit(this, lang(lng_profile_edit_contact), st::topBarButton),
 	_leaveGroup(this, lang(lng_profile_delete_and_exit), st::topBarButton),
 	_addContact(this, lang(lng_profile_add_contact), st::topBarButton),
-	_deleteContact(this, lang(lng_profile_delete_contact), st::topBarButton) {
+	_deleteContact(this, lang(lng_profile_delete_contact), st::topBarButton),
+	_mediaType(this, lang(lng_media_type), st::topBarButton) {
 
 	connect(&_forward, SIGNAL(clicked()), this, SLOT(onForwardSelection()));
 	connect(&_delete, SIGNAL(clicked()), this, SLOT(onDeleteSelection()));
@@ -178,6 +179,7 @@ void TopBarWidget::resizeEvent(QResizeEvent *e) {
 	if (!_leaveGroup.isHidden()) _leaveGroup.move(r -= _leaveGroup.width(), 0);
 	if (!_edit.isHidden()) _edit.move(r -= _edit.width(), 0);
 	if (!_addContact.isHidden()) _addContact.move(r -= _addContact.width(), 0);
+	if (!_mediaType.isHidden()) _mediaType.move(r -= _mediaType.width(), 0);
 }
 
 void TopBarWidget::startAnim() {
@@ -188,6 +190,7 @@ void TopBarWidget::startAnim() {
     _clearSelection.hide();
     _delete.hide();
     _forward.hide();
+	_mediaType.hide();
     _animating = true;
 }
 
@@ -226,6 +229,7 @@ void TopBarWidget::showAll() {
 		_clearSelection.hide();
 		_delete.hide();
 		_forward.hide();
+		_mediaType.hide();
 	} else {
 		_edit.hide();
 		_leaveGroup.hide();
@@ -235,10 +239,16 @@ void TopBarWidget::showAll() {
 			_clearSelection.show();
 			_delete.show();
 			_forward.show();
+			_mediaType.hide();
 		} else {
 			_clearSelection.hide();
 			_delete.hide();
 			_forward.hide();
+			if (App::main() && App::main()->mediaTypeSwitch()) {
+				_mediaType.show();
+			} else {
+				_mediaType.hide();
+			}
 		}
 	}
 	resizeEvent(0);
@@ -253,13 +263,17 @@ void TopBarWidget::showSelected(uint32 selCount) {
 	showAll();
 }
 
+FlatButton *TopBarWidget::mediaTypeButton() {
+	return &_mediaType;
+}
+
 MainWidget *TopBarWidget::main() {
 	return static_cast<MainWidget*>(parentWidget());
 }
 
 MainWidget::MainWidget(Window *window) : QWidget(window), failedObjId(0), _dialogsWidth(st::dlgMinWidth),
-	dialogs(this), history(this), profile(0), overview(0), _topBar(this), hider(0),
-    updPts(0), updDate(0), updQts(0), updSeq(0), updInited(false), onlineRequest(0) {
+dialogs(this), history(this), profile(0), overview(0), _topBar(this), hider(0), _mediaType(this), _mediaTypeMask(0),
+	updPts(0), updDate(0), updQts(0), updSeq(0), updInited(false), onlineRequest(0) {
 	setGeometry(QRect(0, st::titleHeight, App::wnd()->width(), App::wnd()->height() - st::titleHeight));
 
 	connect(window, SIGNAL(resized(const QSize &)), this, SLOT(onParentResize(const QSize &)));
@@ -286,9 +300,13 @@ MainWidget::MainWidget(Window *window) : QWidget(window), failedObjId(0), _dialo
 
 	_topBar.raise();
 	dialogs.raise();
+	_mediaType.raise();
 
 	MTP::setGlobalFailHandler(rpcFail(&MainWidget::updateFail));
 
+	_mediaType.hide();
+	_topBar.mediaTypeButton()->installEventFilter(&_mediaType);
+
 	show();
 	setFocus();
 }
@@ -639,7 +657,35 @@ void MainWidget::overviewPreloaded(PeerData *peer, const MTPmessages_Messages &r
 
 void MainWidget::mediaOverviewUpdated(PeerData *peer) {
 	if (profile) profile->mediaOverviewUpdated(peer);
-	if (overview) overview->mediaOverviewUpdated(peer);
+	if (overview && overview->peer() == peer) {
+		overview->mediaOverviewUpdated(peer);
+
+		int32 mask = 0;
+		History *h = peer ? App::historyLoaded(peer->id) : 0;
+		if (h) {
+			for (int32 i = 0; i < OverviewCount; ++i) {
+				if (!h->_overview[i].isEmpty() || h->_overviewCount[i] > 0 || i == overview->type()) {
+					mask |= (1 << i);
+				}
+			}
+		}
+		if (mask != _mediaTypeMask) {
+			_mediaType.resetButtons();
+			for (int32 i = 0; i < OverviewCount; ++i) {
+				if (mask & (1 << i)) {
+					switch (i) {
+					case OverviewPhotos: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaPhotos, lang(lng_media_type_photos))), SIGNAL(clicked()), this, SLOT(onPhotosSelect())); break;
+					case OverviewVideos: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaVideos, lang(lng_media_type_videos))), SIGNAL(clicked()), this, SLOT(onVideosSelect())); break;
+					case OverviewDocuments: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaDocuments, lang(lng_media_type_documents))), SIGNAL(clicked()), this, SLOT(onDocumentsSelect())); break;
+					case OverviewAudios: connect(_mediaType.addButton(new IconedButton(this, st::dropdownMediaAudios, lang(lng_media_type_audios))), SIGNAL(clicked()), this, SLOT(onAudiosSelect())); break;
+					}
+				}
+			}
+			_mediaTypeMask = mask;
+			_mediaType.move(width() - _mediaType.width(), st::topBarHeight);
+			overview->updateTopBarSelection();
+		}
+	}
 }
 
 void MainWidget::changingMsgId(HistoryItem *row, MsgId newId) {
@@ -982,7 +1028,18 @@ PeerData *MainWidget::profilePeer() {
 	return profile ? profile->peer() : 0;
 }
 
-void MainWidget::showMediaOverview(const PeerData *peer, MediaOverviewType type, bool back, int32 lastScrollTop) {
+bool MainWidget::mediaTypeSwitch() {
+	if (!overview) return false;
+
+	for (int32 i = 0; i < OverviewCount; ++i) {
+		if (!(_mediaTypeMask & ~(1 << i))) {
+			return false;
+		}
+	}
+	return true;
+}
+
+void MainWidget::showMediaOverview(PeerData *peer, MediaOverviewType type, bool back, int32 lastScrollTop) {
 	App::wnd()->hideSettings();
 	if (overview && overview->peer() == peer) {
 		if (overview->type() != type) {
@@ -1018,6 +1075,8 @@ void MainWidget::showMediaOverview(const PeerData *peer, MediaOverviewType type,
 		profile = 0;
 	}
 	overview = new OverviewWidget(this, peer, type);
+	_mediaTypeMask = 0;
+	mediaOverviewUpdated(peer);
 	_topBar.show();
 	resizeEvent(0);
 	overview->animShow(animCache, animTopBarCache, back, lastScrollTop);
@@ -1026,10 +1085,11 @@ void MainWidget::showMediaOverview(const PeerData *peer, MediaOverviewType type,
 	history.hide();
 	_topBar.raise();
 	dialogs.raise();
+	_mediaType.raise();
 	if (hider) hider->raise();
 }
 
-void MainWidget::showPeerProfile(const PeerData *peer, bool back, int32 lastScrollTop, bool allMediaShown) {
+void MainWidget::showPeerProfile(PeerData *peer, bool back, int32 lastScrollTop, bool allMediaShown) {
 	App::wnd()->hideSettings();
 	if (profile && profile->peer() == peer) return;
 
@@ -1068,6 +1128,7 @@ void MainWidget::showPeerProfile(const PeerData *peer, bool back, int32 lastScro
 	history.hide();
 	_topBar.raise();
 	dialogs.raise();
+	_mediaType.raise();
 	if (hider) hider->raise();
 }
 
@@ -1338,6 +1399,7 @@ void MainWidget::hideAll() {
 		overview->hide();
 	}
 	_topBar.hide();
+	_mediaType.hide();
 }
 
 void MainWidget::showAll() {
@@ -1360,6 +1422,7 @@ void MainWidget::resizeEvent(QResizeEvent *e) {
 	int32 tbh = _topBar.isHidden() ? 0 : st::topBarHeight;
 	dialogs.setGeometry(0, 0, _dialogsWidth + st::dlgShadow, height());
 	_topBar.setGeometry(_dialogsWidth, 0, width() - _dialogsWidth, st::topBarHeight + st::titleShadow);
+	_mediaType.move(width() - _mediaType.width(), st::topBarHeight);
 	history.setGeometry(_dialogsWidth, tbh, width() - _dialogsWidth, height() - tbh);
 	if (profile) profile->setGeometry(history.geometry());
 	if (overview) overview->setGeometry(history.geometry());
@@ -1379,6 +1442,26 @@ void MainWidget::paintTopBar(QPainter &p, float64 over, int32 decreaseWidth) {
 	}
 }
 
+void MainWidget::onPhotosSelect() {
+	if (overview) overview->switchType(OverviewPhotos);
+	_mediaType.hideStart();
+}
+
+void MainWidget::onVideosSelect() {
+	if (overview) overview->switchType(OverviewVideos);
+	_mediaType.hideStart();
+}
+
+void MainWidget::onDocumentsSelect() {
+	if (overview) overview->switchType(OverviewDocuments);
+	_mediaType.hideStart();
+}
+
+void MainWidget::onAudiosSelect() {
+	if (overview) overview->switchType(OverviewAudios);
+	_mediaType.hideStart();
+}
+
 TopBarWidget *MainWidget::topBar() {
 	return &_topBar;
 }
diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h
index e41b2325e..64fcde0c2 100644
--- a/Telegram/SourceFiles/mainwidget.h
+++ b/Telegram/SourceFiles/mainwidget.h
@@ -50,6 +50,8 @@ public:
 	void showAll();
 	void showSelected(uint32 selCount);
 
+	FlatButton *mediaTypeButton();
+
 public slots:
 
 	void onForwardSelection();
@@ -81,6 +83,7 @@ private:
 	FlatButton _clearSelection;
 	FlatButton _forward, _delete;
 	FlatButton _edit, _leaveGroup, _addContact, _deleteContact;
+	FlatButton _mediaType;
 
 };
 
@@ -204,8 +207,9 @@ public:
 	PeerData *activePeer();
 	MsgId activeMsgId();
 	PeerData *profilePeer();
-	void showPeerProfile(const PeerData *peer, bool back = false, int32 lastScrollTop = -1, bool allMediaShown = false);
-	void showMediaOverview(const PeerData *peer, MediaOverviewType type, bool back = false, int32 lastScrollTop = -1);
+	bool mediaTypeSwitch();
+	void showPeerProfile(PeerData *peer, bool back = false, int32 lastScrollTop = -1, bool allMediaShown = false);
+	void showMediaOverview(PeerData *peer, MediaOverviewType type, bool back = false, int32 lastScrollTop = -1);
 	void showBackFromStack();
 	QRect historyRect() const;
 
@@ -316,6 +320,11 @@ public slots:
 
 	void onUpdateNotifySettings();
 
+	void onPhotosSelect();
+	void onVideosSelect();
+	void onDocumentsSelect();
+	void onAudiosSelect();
+
 private:
 
     void partWasRead(PeerData *peer, const MTPmessages_AffectedHistory &result);
@@ -360,6 +369,9 @@ private:
 	StackItems _stack;
 	QPixmap profileAnimCache;
 
+	Dropdown _mediaType;
+	int32 _mediaTypeMask;
+
 	int updPts, updDate, updQts, updSeq;
 	bool updInited;
 	QTimer noUpdatesTimer;
diff --git a/Telegram/SourceFiles/mediaview.cpp b/Telegram/SourceFiles/mediaview.cpp
index f273abc0e..bfcced5d6 100644
--- a/Telegram/SourceFiles/mediaview.cpp
+++ b/Telegram/SourceFiles/mediaview.cpp
@@ -245,15 +245,17 @@ void MediaView::showPhoto(PhotoData *photo, HistoryItem *context) {
 
 	_index = -1;
 	_msgid = context ? context->id : 0;
-	for (int i = 0, l = _history->_overview[OverviewPhotos].size(); i < l; ++i) {
-		if (_history->_overview[OverviewPhotos].at(i) == _msgid) {
-			_index = i;
-			break;
+	if (_history) {
+		for (int i = 0, l = _history->_overview[OverviewPhotos].size(); i < l; ++i) {
+			if (_history->_overview[OverviewPhotos].at(i) == _msgid) {
+				_index = i;
+				break;
+			}
 		}
-	}
 
-	if (_history->_overviewCount[OverviewPhotos] < 0) {
-		loadPhotosBack();
+		if (_history->_overviewCount[OverviewPhotos] < 0) {
+			loadPhotosBack();
+		}
 	}
 
 	showPhoto(photo);
diff --git a/Telegram/SourceFiles/overviewwidget.cpp b/Telegram/SourceFiles/overviewwidget.cpp
index a16e9d5e3..67c4d38c8 100644
--- a/Telegram/SourceFiles/overviewwidget.cpp
+++ b/Telegram/SourceFiles/overviewwidget.cpp
@@ -381,7 +381,23 @@ void OverviewInner::dragActionStart(const QPoint &screenPos, Qt::MouseButton but
 	if (_dragAction == NoDrag && _dragItem) {
 		bool afterDragSymbol = false , uponSymbol = false;
 		uint16 symbol = 0;
-		_dragAction = PrepareSelect; // start items select
+		if (textlnkDown()) {
+			_dragSymbol = symbol;
+			uint32 selStatus = (_dragSymbol << 16) | _dragSymbol;
+			if (selStatus != FullItemSel && (_selected.isEmpty() || _selected.cbegin().value() != FullItemSel)) {
+				if (!_selected.isEmpty()) {
+					updateMsg(_selected.cbegin().key(), -1);
+					_selected.clear();
+				}
+				_selected.insert(_dragItem, selStatus);
+				_dragAction = Selecting;
+				updateMsg(_dragItem, _dragItemIndex);
+			} else {
+				_dragAction = PrepareSelect;
+			}
+		} else {
+			_dragAction = PrepareSelect; // start items select
+		}
 	}
 
 	if (!_dragItem) {
@@ -831,66 +847,73 @@ void OverviewInner::onUpdateSelected() {
 		}
 		cur = textlnkDown() ? style::cur_pointer : style::cur_default;
 		if (_dragAction == Selecting) {
-			bool selectingDown = (_type == OverviewPhotos ? (_mousedItemIndex > _dragItemIndex) : (_mousedItemIndex < _dragItemIndex)) || (_mousedItemIndex == _dragItemIndex && (_type == OverviewPhotos ? (_dragStartPos.x() < m.x()) : (_dragStartPos.y() < m.y())));
-			MsgId dragSelFrom = _dragItem, dragSelTo = _mousedItem;
-			int32 dragSelFromIndex = _dragItemIndex, dragSelToIndex = _mousedItemIndex;
-			if (!itemHasPoint(dragSelFrom, dragSelFromIndex, _dragStartPos.x(), _dragStartPos.y())) { // maybe exclude dragSelFrom
-				if (selectingDown) {
-					if (_type == OverviewPhotos) {
-						if (_dragStartPos.x() >= _vsize || ((_mousedItem == dragSelFrom) && (m.x() < _dragStartPos.x() + QApplication::startDragDistance()))) {
-							moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, 1);
+			if (_mousedItem == _dragItem && lnk && !_selected.isEmpty() && _selected.cbegin().value() != FullItemSel) {
+				bool afterSymbol = false, uponSymbol = false;
+				uint16 second = 0;
+				_selected[_dragItem] = 0;
+				updateDragSelection(0, -1, 0, -1, false);
+			} else {
+				bool selectingDown = (_type == OverviewPhotos ? (_mousedItemIndex > _dragItemIndex) : (_mousedItemIndex < _dragItemIndex)) || (_mousedItemIndex == _dragItemIndex && (_type == OverviewPhotos ? (_dragStartPos.x() < m.x()) : (_dragStartPos.y() < m.y())));
+				MsgId dragSelFrom = _dragItem, dragSelTo = _mousedItem;
+				int32 dragSelFromIndex = _dragItemIndex, dragSelToIndex = _mousedItemIndex;
+				if (!itemHasPoint(dragSelFrom, dragSelFromIndex, _dragStartPos.x(), _dragStartPos.y())) { // maybe exclude dragSelFrom
+					if (selectingDown) {
+						if (_type == OverviewPhotos) {
+							if (_dragStartPos.x() >= _vsize || ((_mousedItem == dragSelFrom) && (m.x() < _dragStartPos.x() + QApplication::startDragDistance()))) {
+								moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, 1);
+							}
+						} else {
+							if (_dragStartPos.y() >= (itemHeight(dragSelFrom, dragSelFromIndex) - st::msgMargin.bottom()) || ((_mousedItem == dragSelFrom) && (m.y() < _dragStartPos.y() + QApplication::startDragDistance()))) {
+								moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, -1);
+							}
 						}
 					} else {
-						if (_dragStartPos.y() >= (itemHeight(dragSelFrom, dragSelFromIndex) - st::msgMargin.bottom()) || ((_mousedItem == dragSelFrom) && (m.y() < _dragStartPos.y() + QApplication::startDragDistance()))) {
-							moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, -1);
-						}
-					}
-				} else {
-					if (_type == OverviewPhotos) {
-						if (_dragStartPos.x() < 0 || ((_mousedItem == dragSelFrom) && (m.x() >= _dragStartPos.x() - QApplication::startDragDistance()))) {
-							moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, -1);
-						}
-					} else {
-						if (_dragStartPos.y() < st::msgMargin.top() || ((_mousedItem == dragSelFrom) && (m.y() >= _dragStartPos.y() - QApplication::startDragDistance()))) {
-							moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, 1);
+						if (_type == OverviewPhotos) {
+							if (_dragStartPos.x() < 0 || ((_mousedItem == dragSelFrom) && (m.x() >= _dragStartPos.x() - QApplication::startDragDistance()))) {
+								moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, -1);
+							}
+						} else {
+							if (_dragStartPos.y() < st::msgMargin.top() || ((_mousedItem == dragSelFrom) && (m.y() >= _dragStartPos.y() - QApplication::startDragDistance()))) {
+								moveToNextItem(dragSelFrom, dragSelFromIndex, dragSelTo, 1);
+							}
 						}
 					}
 				}
-			}
-			if (_dragItem != _mousedItem) { // maybe exclude dragSelTo
-				if (selectingDown) {
-					if (_type == OverviewPhotos) {
-						if (m.x() < 0) {
-							moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, -1);
+				if (_dragItem != _mousedItem) { // maybe exclude dragSelTo
+					if (selectingDown) {
+						if (_type == OverviewPhotos) {
+							if (m.x() < 0) {
+								moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, -1);
+							}
+						} else {
+							if (m.y() < st::msgMargin.top()) {
+								moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, 1);
+							}
 						}
 					} else {
-						if (m.y() < st::msgMargin.top()) {
-							moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, 1);
-						}
-					}
-				} else {
-					if (_type == OverviewPhotos) {
-						if (m.x() >= _vsize) {
-							moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, 1);
-						}
-					} else {
-						if (m.y() >= itemHeight(dragSelTo, dragSelToIndex) - st::msgMargin.bottom()) {
-							moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, -1);
+						if (_type == OverviewPhotos) {
+							if (m.x() >= _vsize) {
+								moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, 1);
+							}
+						} else {
+							if (m.y() >= itemHeight(dragSelTo, dragSelToIndex) - st::msgMargin.bottom()) {
+								moveToNextItem(dragSelTo, dragSelToIndex, dragSelFrom, -1);
+							}
 						}
 					}
 				}
+				bool dragSelecting = false;
+				MsgId dragFirstAffected = dragSelFrom;
+				int32 dragFirstAffectedIndex = dragSelFromIndex;
+				while (dragFirstAffectedIndex >= 0 && dragFirstAffected <= 0) {
+					moveToNextItem(dragFirstAffected, dragFirstAffectedIndex, dragSelTo, ((selectingDown && (_type == OverviewPhotos)) || (!selectingDown && (_type != OverviewPhotos))) ? -1 : 1);
+				}
+				if (dragFirstAffectedIndex >= 0) {
+					SelectedItems::const_iterator i = _selected.constFind(dragFirstAffected);
+					dragSelecting = (i == _selected.cend() || i.value() != FullItemSel);
+				}
+				updateDragSelection(dragSelFrom, dragSelFromIndex, dragSelTo, dragSelToIndex, dragSelecting);
 			}
-			bool dragSelecting = false;
-			MsgId dragFirstAffected = dragSelFrom;
-			int32 dragFirstAffectedIndex = dragSelFromIndex;
-			while (dragFirstAffectedIndex >= 0 && dragFirstAffected <= 0) {
-				moveToNextItem(dragFirstAffected, dragFirstAffectedIndex, dragSelTo, ((selectingDown && (_type == OverviewPhotos)) || (!selectingDown && (_type != OverviewPhotos))) ? -1 : 1);
-			}
-			if (dragFirstAffectedIndex >= 0) {
-				SelectedItems::const_iterator i = _selected.constFind(dragFirstAffected);
-				dragSelecting = (i == _selected.cend() || i.value() != FullItemSel);
-			}
-			updateDragSelection(dragSelFrom, dragSelFromIndex, dragSelTo, dragSelToIndex, dragSelecting);
 		} else if (_dragAction == Dragging) {
 		}
 
@@ -987,6 +1010,23 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
 		dragActionUpdate(e->globalPos());
 	}
 
+	// -2 - has full selected items, but not over, 0 - no selection, 2 - over full selected items
+	int32 isUponSelected = 0, hasSelected = 0;
+	if (!_selected.isEmpty()) {
+		isUponSelected = -1;
+		if (_selected.cbegin().value() == FullItemSel) {
+			hasSelected = 2;
+			if (App::hoveredLinkItem() && _selected.constFind(App::hoveredLinkItem()->id) != _selected.cend()) {
+				isUponSelected = 2;
+			} else {
+				isUponSelected = -2;
+			}
+		}
+	}
+	if (showFromTouch && hasSelected && isUponSelected < hasSelected) {
+		isUponSelected = hasSelected;
+	}
+
 	_contextMenuLnk = textlnkOver();
 	PhotoLink *lnkPhoto = dynamic_cast<PhotoLink*>(_contextMenuLnk.data());
 	VideoLink *lnkVideo = dynamic_cast<VideoLink*>(_contextMenuLnk.data());
@@ -1010,13 +1050,17 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
 				_menu->addAction(lang(lnkVideo ? lng_context_save_video : (lnkAudio ? lng_context_save_audio : lng_context_save_document)), this, SLOT(saveContextFile()))->setEnabled(true);
 			}
 		}
-		if (App::hoveredLinkItem()) {
+		if (isUponSelected > 1) {
+			_menu->addAction(lang(lng_context_forward_selected), _overview, SLOT(onForwardSelected()));
+			_menu->addAction(lang(lng_context_delete_selected), _overview, SLOT(onDeleteSelected()));
+			_menu->addAction(lang(lng_context_clear_selection), _overview, SLOT(onClearSelected()));
+		} else if (isUponSelected != -2 && App::hoveredLinkItem()) {
 			if (dynamic_cast<HistoryMessage*>(App::hoveredLinkItem())) {
 				_menu->addAction(lang(lng_context_forward_msg), this, SLOT(forwardMessage()))->setEnabled(true);
 			}
 			_menu->addAction(lang(lng_context_delete_msg), this, SLOT(deleteMessage()))->setEnabled(true);
-			App::contextItem(App::hoveredLinkItem());
 		}
+		App::contextItem(App::hoveredLinkItem());
 	}
 	if (_menu) {
 		_menu->setAttribute(Qt::WA_DeleteOnClose);
@@ -1029,6 +1073,7 @@ void OverviewInner::showContextMenu(QContextMenuEvent *e, bool showFromTouch) {
 int32 OverviewInner::resizeToWidth(int32 nwidth, int32 scrollTop, int32 minHeight) {
 	if (width() == nwidth && minHeight == _minHeight) return scrollTop;
 	_minHeight = minHeight;
+	_addToY = (_height < _minHeight) ? (_minHeight - _height) : 0;
 	if (_type == OverviewPhotos && _resizeIndex < 0) {
 		_resizeIndex = _photosInRow * ((scrollTop + minHeight) / int32(_vsize + st::overviewPhotoSkip)) + _photosInRow - 1;
 		_resizeSkip = (scrollTop + minHeight) - ((scrollTop + minHeight) / int32(_vsize + st::overviewPhotoSkip)) * int32(_vsize + st::overviewPhotoSkip);
@@ -1055,7 +1100,14 @@ MediaOverviewType OverviewInner::type() const {
 }
 
 void OverviewInner::switchType(MediaOverviewType type) {
-	_type = type;
+	if (_type != type) {
+		_selected.clear();
+		_dragItemIndex = _mousedItemIndex = _dragSelFromIndex = _dragSelToIndex = -1;
+		_dragItem = _mousedItem = _dragSelFrom = _dragSelTo = 0;
+		_items.clear();
+		_cached.clear();
+		_type = type;
+	}
 	mediaOverviewUpdated();
 	if (App::wnd()) App::wnd()->update();
 }
@@ -1502,6 +1554,8 @@ void OverviewWidget::switchType(MediaOverviewType type) {
 	_selCount = 0;
 	App::main()->topBar()->showSelected(0);
 	updateTopBarSelection();
+	_scroll.scrollToY(_scroll.scrollTopMax());
+	onScroll();
 }
 
 void OverviewWidget::updateTopBarSelection() {
@@ -1577,6 +1631,7 @@ void OverviewWidget::mediaOverviewUpdated(PeerData *p) {
 	if (peer() == p) {
 		_inner.mediaOverviewUpdated();
 		onScroll();
+		updateTopBarSelection();
 	}
 }
 
@@ -1700,4 +1755,3 @@ void OverviewWidget::onDeleteContextSure() {
 void OverviewWidget::onClearSelected() {
 	_inner.clearSelectedItems();
 }
-