diff --git a/Telegram/Resources/lang.strings b/Telegram/Resources/lang.strings
index 9c6e636e2..deb8fd138 100644
--- a/Telegram/Resources/lang.strings
+++ b/Telegram/Resources/lang.strings
@@ -527,12 +527,16 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
 "lng_search_found_results" = "{count:No messages found|Found # message|Found # messages}";
 "lng_search_global_results" = "Global search results";
 
-"lng_mediaview_save" = "Download";
+"lng_mediaview_save_as" = "Save as..";
+"lng_mediaview_copy" = "Copy";
 "lng_mediaview_forward" = "Forward";
 "lng_mediaview_delete" = "Delete";
+"lng_mediaview_photos_all" = "View all photos";
+"lng_mediaview_files_all" = "View all files";
 "lng_mediaview_single_photo" = "Single Photo";
 "lng_mediaview_group_photo" = "Group Photo";
 "lng_mediaview_profile_photo" = "Profile Photo";
+"lng_mediaview_file_n_of_count" = "{file} {n} of {count}";
 "lng_mediaview_n_of_count" = "Photo {n} of {count}";
 "lng_mediaview_doc_image" = "File";
 "lng_mediaview_today" = "today at {time}";
diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt
index 010b66b0f..31b97aa66 100644
--- a/Telegram/Resources/style.txt
+++ b/Telegram/Resources/style.txt
@@ -1361,12 +1361,16 @@ connectingBG: #fffe;
 connectingColor: #777;
 connectingPadding: margins(5px, 5px, 5px, 5px);
 
-dropdownPadding: margins(10px, 10px, 10px, 10px);
-dropdownShadow: sprite(241px, 46px, 6px, 6px);
-dropdownBorder: 1px;
-dropdownBorderColor: #ebebeb;
-dropdownBackground: white;
-dropdownDuration: 150;
+dropdownDef: dropdown {
+	border: 1px;
+	borderColor: #ebebeb;
+
+	padding: margins(10px, 10px, 10px, 10px);
+	shadow: sprite(241px, 46px, 6px, 6px);
+
+	duration: 150;
+	width: 0px;
+}
 
 dropdownAttachDocument: iconedButton(btnAttachDocument) {
 	iconPos: point(14px, 13px);
@@ -1555,18 +1559,82 @@ stickerPanPadding: 2px;
 stickerPanDelete: sprite(158px, 197px, 12px, 12px);
 stickerPanDeleteOpacity: 0.5;
 
-medviewNavBarWidth: 132px;
-medviewLightNav: 0.5;
-medviewDarkNav: 1;
-medviewHeaderFont: font(semibold 18px);
-medviewNameFont: font(16px);
-medviewDateFont: font(14px);
-medviewNameTop: 13px;
-medviewDateTop: 39px;
-medviewLeft: sprite(340px, 79px, 28px, 48px);
-medviewRight: sprite(368px, 79px, 28px, 48px);
-medviewDeltaFromLastAction: 5px;
-medviewSwipeDistance: 80px;
+mvBgColor: #222;
+mvBgOpacity: 0.92;
+mvThickFont: font(fsize semibold);
+mvFont: font(fsize);
+
+mvTextLeft: 16px;
+mvTextSkip: 10px;
+mvHeaderTop: 48px;
+mvTextTop: 24px;
+mvTextColor: white;
+mvTextOpacity: 0.5;
+mvTextOverOpacity: 1;
+
+mvIconOpacity: 0.45;
+mvIconOverOpacity: 1;
+mvControlBgColor: black;
+mvControlBgOpacity: 0.3;
+mvControlMargin: 0px;
+mvControlSize: 90px;
+mvIconSize: size(60px, 56px);
+
+mvLeft: sprite(320px, 400px, 12px, 22px);
+mvRight: sprite(332px, 400px, 12px, 22px);
+mvClose: sprite(344px, 400px, 18px, 18px);
+mvSave: sprite(362px, 400px, 14px, 19px);
+mvMore: sprite(376px, 400px, 5px, 21px);
+
+mvDropdown: dropdown(dropdownDef) {
+	shadow: sprite(0px, 0px, 0px, 0px);
+	padding: margins(11px, 12px, 11px, 12px);
+
+	border: 0;
+	width: 182px;
+}
+mvButton: iconedButton(btnDefIconed) {
+	bgColor: #383838;
+	overBgColor: #505050;
+	font: font(fsize);
+
+	opacity: 1;
+	overOpacity: 1;
+
+	width: -32px;
+	height: 36px;
+
+	color: white;
+
+	textPos: point(16px, 9px);
+	downTextPos: point(16px, 10px);
+
+	duration: 0;
+}
+mvContextButton: iconedButton(mvButton) {
+	bgColor: #383838E6;
+	overBgColor: #505050E7;
+}
+mvWaitHide: 2000;
+mvHideDuration: 1000;
+mvShowDuration: 200;
+mvFadeDuration: 150;
+
+mvDocPadding: 18px;
+mvDocSize: size(340px, 116px);
+mvDocBg: white;
+mvDocNameTop: 5px;
+mvDocNameColor: black;
+mvDocSizeTop: 30px;
+mvDocSizeColor: #808080;
+mvDocLinksTop: 57px;
+mvDocRed: sprite(0px, 400px, 80px, 80px);
+mvDocYellow: sprite(80px, 400px, 80px, 80px);
+mvDocGreen: sprite(160px, 400px, 80px, 80px);
+mvDocBlue: sprite(240px, 400px, 80px, 80px);
+
+mvDeltaFromLastAction: 5px;
+mvSwipeDistance: 80px;
 
 medviewSaveMsgCheck: sprite(341px, 174px, 22px, 18px);
 medviewSaveMsgFont: font(16px);
@@ -1578,87 +1646,7 @@ medviewSaveMsgShown: 2000;
 medviewSaveMsgHiding: 2500;
 medviewSaveMsg: #000000b2;
 
-medviewOverview: iconedButton(btnDefIconed) {
-	bgColor: #0000;
-	overBgColor: #00000040;
-	font: font(16px);
-
-	opacity: 0.77;
-	overOpacity: 1;
-
-	icon: sprite(340px, 129px, 19px, 19px);
-	iconPos: point(16px, 14px);
-	downIcon: sprite(340px, 129px, 19px, 19px);
-	downIconPos: point(16px, 14px);
-
-	width: -69px;
-	height: 47px;
-
-	color: white;
-
-	textPos: point(51px, 13px);
-	downTextPos: point(51px, 14px);
-}
-medviewForward: iconedButton(medviewOverview) {
-	icon: sprite(357px, 58px, 22px, 17px);
-	iconPos: point(16px, 15px);
-	downIcon: sprite(357px, 58px, 22px, 17px);
-	downIconPos: point(16px, 15px);
-
-	width: -69px;
-}
-medviewDelete: iconedButton(medviewForward) {
-	icon: sprite(340px, 58px, 15px, 19px);
-	iconPos: point(16px, 14px);
-	downIcon: sprite(340px, 58px, 15px, 19px);
-	downIconPos: point(16px, 14px);
-}
-medviewClose: iconedButton(medviewOverview) {
-	icon: sprite(340px, 0px, 56px, 56px);
-	iconPos: point(0px, 0px);
-	downIcon: sprite(340px, 0px, 56px, 56px);
-	downIconPos: point(0px, 0px);
-
-	opacity: 0.6;
-
-	width: 56px;
-	height: 56px;
-}
-medviewBottomBar: 87px;
-medviewBG: #272727D9;
-medviewBottomBG: #272727;
-medviewNavOpacity: 0.6;
-medviewCloseOpacity: 0.6;
-medviewNavBGOpacity: 0.4;
-medviewNavOverOpacity: 1;
-medviewCloseOverOpacity: 1;
-medviewNameColor: black;
-medviewDateColor: #999;
-medviewSaveAs: iconedButton(medviewOverview) {
-	bgColor: #38abe6;
-	overBgColor: #299fdc;
-
-	opacity: 1;
-
-	icon: sprite(361px, 129px, 12px, 19px);
-	iconPos: point(18px, 15px);
-	downIcon: sprite(361px, 129px, 12px, 19px);
-	downIconPos: point(18px, 15px);
-
-	width: -62px;
-	height: 47px;
-
-	textPos: point(44px, 13px);
-	downTextPos: point(44px, 14px);
-}
-medviewSaveAsDisabledOpacity: 0.8;
-medviewPolaroid: margins(17px, 18px, 17px, 72px);
-medviewPolaroidMin: size(480px, 360px);
-medviewDocumentSprite: sprite(341px, 150px, 20px, 22px);
-medviewDocumentSpritePos: point(16px, 13px);
-medviewPhotoSprite: sprite(363px, 150px, 23px, 20px);
-medviewPhotoSpritePos: point(14px, 14px);
-medviewTransparentBrush: sprite(148px, 197px, 8px, 8px);
+mvTransparentBrush: sprite(148px, 197px, 8px, 8px);
 
 overviewPhotoSkip: 10px;
 overviewPhotoMinSize: 100px;
@@ -1704,6 +1692,12 @@ photoLoaderDuration1: 150; // ms fade in
 photoLoaderDuration2: 150; // ms fade out
 photoLoaderAlphaMin: 0.1; // not less than that
 
+radialSize: size(50px, 50px);
+radialLine: 2px;
+radialDuration: 200;
+radialPeriod: 2000;
+radialBgOpacity: 0.4;
+
 overviewLoader: size(34px, 14px);
 overviewLoaderPoint: size(4px, 4px);
 overviewLoaderSkip: 4px;
diff --git a/Telegram/Resources/style_classes.txt b/Telegram/Resources/style_classes.txt
index 6846cf875..26c39731d 100644
--- a/Telegram/Resources/style_classes.txt
+++ b/Telegram/Resources/style_classes.txt
@@ -246,3 +246,14 @@ switcher {
 
 	duration: number;
 }
+
+dropdown {
+	border: number;
+	borderColor: color;
+
+	padding: margins;
+	shadow: sprite;
+
+	duration: number;
+	width: number;
+}
diff --git a/Telegram/SourceFiles/_other/genstyles.cpp b/Telegram/SourceFiles/_other/genstyles.cpp
index cf55a894f..668f06c5c 100644
--- a/Telegram/SourceFiles/_other/genstyles.cpp
+++ b/Telegram/SourceFiles/_other/genstyles.cpp
@@ -448,6 +448,7 @@ static const char *variantNames[] = { "dbisOne", "dbisOneAndQuarter", "dbisOneAn
 static const char *variantPostfixes[] = { "", "_125x", "_150x", "_200x" };
 QPixmap *spriteMax = 0;
 QImage *variantSprites = 0;
+int *spriteWidths = 0;
 QImage *variantGrids = 0;
 
 void readStyleGenToken(const char *&from, const char *end, StyleGenTokenType &tokenType, string &token) {
@@ -1353,17 +1354,22 @@ bool genStyles(const QString &classes_in, const QString &classes_out, const QStr
 	}
 
 	QImage sprites[variantsCount];
+	int widths[variantsCount] = { 0 };
 	variantSprites = sprites;
+	spriteWidths = widths;
 
 	QString sprite0(path_to_sprites + "sprite" + QString(variantPostfixes[0]) + ".png"), spriteLast(path_to_sprites + "sprite" + QString(variantPostfixes[variantsCount - 1]) + ".png");
 	variantSprites[0] = QImage(sprite0);
+	spriteWidths[0] = variantSprites[0].width();
 	for (int i = 1; i < variantsCount - 1; ++i) {
 		variantSprites[i] = QImage(adjustPx(variants[i], variantSprites[0].width(), true), adjustPx(variants[i], variantSprites[0].height(), true), QImage::Format_ARGB32_Premultiplied);
+		spriteWidths[i] = variantSprites[i].width();
 		QPainter p(&variantSprites[i]);
 		p.setCompositionMode(QPainter::CompositionMode_Source);
 		p.fillRect(0, 0, variantSprites[i].width(), variantSprites[i].height(), Qt::transparent);
 	}
 	variantSprites[variantsCount - 1] = QImage(spriteLast);
+	spriteWidths[variantsCount - 1] = variantSprites[variantsCount - 1].width();
 
 	QPixmap spriteMaxPix = QPixmap::fromImage(variantSprites[variantsCount - 1], Qt::ColorOnly);
 	spriteMax = &spriteMaxPix;
@@ -1567,11 +1573,13 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org\n\
 			tcpp << "\nnamespace style {\n\n";
 			tcpp << "\tFontFamilies _fontFamilies;\n";
 			tcpp << "\tFontDatas _fontsMap;\n";
-			tcpp << "\tColorDatas _colorsMap;\n\n";
+			tcpp << "\tColorDatas _colorsMap;\n";
+			tcpp << "int _spriteWidth = " << spriteWidths[0] << ";\n\n";
 			tcpp << "\tvoid startManager() {\n";
             
             tcpp << "\n\t\tif (cRetina()) {\n";
-            tcpp << "\t\t\tcSetRealScale(dbisOne);\n\n";
+			tcpp << "\t\t\tcSetRealScale(dbisOne);\n";
+			tcpp << "\t\t\t_spriteWidth = " << spriteWidths[variantsCount - 1] << ";\n\n";
             for (int i = 0, l = scalars.size(); i < l; ++i) {
                 Scalar &sc(scalars[i]);
                 if (sc.second.first == scSprite || sc.first == "spriteFile" || sc.first == "emojisFile" || sc.first == "emojiImgSize") {
@@ -1594,6 +1602,7 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org\n\
 				const char *varName = variantNames[i];
 
 				tcpp << "\t\tcase " << varName << ":\n";
+				tcpp << "\t\t\t_spriteWidth = " << spriteWidths[i] << ";\n\n";
 
 				typedef QMap<string, int> FontFamilies;
 				FontFamilies fontFamilies;
diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp
index 5641b061d..7929fd510 100644
--- a/Telegram/SourceFiles/app.cpp
+++ b/Telegram/SourceFiles/app.cpp
@@ -1515,7 +1515,11 @@ namespace App {
 		audioInit();
 
 		if (!::sprite) {
-			::sprite = new QPixmap(st::spriteFile);
+			if (rtl()) {
+				::sprite = new QPixmap(QPixmap::fromImage(QImage(st::spriteFile).mirrored(true, false)));
+			} else {
+				::sprite = new QPixmap(st::spriteFile);
+			}
             if (cRetina()) ::sprite->setDevicePixelRatio(cRetinaFactor());
 		}
 		if (!::emojis) {
@@ -1598,11 +1602,11 @@ namespace App {
 		return ::mousedItem;
 	}
 
-	QPixmap &sprite() {
+	const QPixmap &sprite() {
 		return *::sprite;
 	}
 
-	QPixmap &emojis() {
+	const QPixmap &emojis() {
 		return *::emojis;
 	}
 
diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h
index 2dc5a103f..fdec443c3 100644
--- a/Telegram/SourceFiles/app.h
+++ b/Telegram/SourceFiles/app.h
@@ -154,8 +154,8 @@ namespace App {
 	void mousedItem(HistoryItem *item);
 	HistoryItem *mousedItem();
 
-	QPixmap &sprite();
-	QPixmap &emojis();
+	const QPixmap &sprite();
+	const QPixmap &emojis();
 	const QPixmap &emojiSingle(const EmojiData *emoji, int32 fontHeight);
 
 	void initMedia();
diff --git a/Telegram/SourceFiles/art/sprite.png b/Telegram/SourceFiles/art/sprite.png
index a2ffacaf0..7e3eeca29 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 6e3f8cc8e..820955566 100644
Binary files a/Telegram/SourceFiles/art/sprite_200x.png and b/Telegram/SourceFiles/art/sprite_200x.png differ
diff --git a/Telegram/SourceFiles/boxes/abstractbox.cpp b/Telegram/SourceFiles/boxes/abstractbox.cpp
index 6e0d57f53..656d9c0b1 100644
--- a/Telegram/SourceFiles/boxes/abstractbox.cpp
+++ b/Telegram/SourceFiles/boxes/abstractbox.cpp
@@ -71,7 +71,7 @@ void AbstractBox::paintTitle(Painter &p, const QString &title, bool withShadow)
 	// paint box title
 	p.setFont(st::boxTitleFont->f);
 	p.setPen(st::black->p);
-	p.drawTextLeft(st::boxTitlePos.x(), st::boxTitlePos.y(), width() - 2 * st::boxTitlePos.x(), title);
+	p.drawTextLeft(st::boxTitlePos.x(), st::boxTitlePos.y(), width(), title);
 }
 
 void AbstractBox::paintGrayTitle(QPainter &p, const QString &title) {
diff --git a/Telegram/SourceFiles/boxes/sessionsbox.cpp b/Telegram/SourceFiles/boxes/sessionsbox.cpp
index 59899ca1c..f85fe974b 100644
--- a/Telegram/SourceFiles/boxes/sessionsbox.cpp
+++ b/Telegram/SourceFiles/boxes/sessionsbox.cpp
@@ -37,7 +37,7 @@ void SessionsInner::paintEvent(QPaintEvent *e) {
 	p.fillRect(r, st::white->b);
 	p.setFont(st::linkFont->f);
 	int32 x = st::sessionPadding.left(), xact = st::sessionTerminateSkip + st::sessionTerminate.iconPos.x();// st::sessionTerminateSkip + st::sessionTerminate.width + st::sessionTerminateSkip;
-	int32 w = width() - 2 * x, availw = width() - 2 * xact;
+	int32 w = width();
 	int32 from = (r.top() >= 0) ? qFloor(r.top() / st::sessionHeight) : 0, count = _list->size();
 	if (from < count) {
 		int32 to = (r.bottom() >= 0 ? qFloor(r.bottom() / st::sessionHeight) : 0) + 1;
@@ -52,7 +52,7 @@ void SessionsInner::paintEvent(QPaintEvent *e) {
 
 			p.setFont(st::sessionActiveFont->f);
 			p.setPen(st::sessionActiveColor->p);
-			p.drawTextRight(xact, st::sessionPadding.top(), availw, auth.active, auth.activeWidth);
+			p.drawTextRight(xact, st::sessionPadding.top(), w, auth.active, auth.activeWidth);
 
 			p.setFont(st::sessionInfoFont->f);
 			p.setPen(st::black->p);
@@ -132,7 +132,7 @@ void SessionsInner::listUpdated() {
 			j = _terminateButtons.insert(_list->at(i).hash, new IconedButton(this, st::sessionTerminate));
 			connect(j.value(), SIGNAL(clicked()), this, SLOT(onTerminate()));
 		}
-		j.value()->moveToRight(st::sessionTerminateSkip, i * st::sessionHeight + st::sessionTerminateTop, width() - 2 * st::sessionTerminateSkip);
+		j.value()->moveToRight(st::sessionTerminateSkip, i * st::sessionHeight + st::sessionTerminateTop, width());
 	}
 	for (TerminateButtons::iterator i = _terminateButtons.begin(); i != _terminateButtons.cend();) {
 		if (i.value()->y() >= 0) {
@@ -175,7 +175,7 @@ _terminateAll(this, lang(lng_sessions_terminate_all)), _terminateBox(0), _shortP
 void SessionsBox::resizeEvent(QResizeEvent *e) {
 	ScrollableBox::resizeEvent(e);
 	_done.move(0, height() - _done.height());
-	_terminateAll.moveToRight(st::sessionPadding.left(), st::boxTitleHeight + st::sessionHeight + st::boxTitlePos.y() + st::boxTitleFont->ascent - st::linkFont->ascent, width() - 2 * st::sessionPadding.left());
+	_terminateAll.moveToRight(st::sessionPadding.left(), st::boxTitleHeight + st::sessionHeight + st::boxTitlePos.y() + st::boxTitleFont->ascent - st::linkFont->ascent, width());
 }
 
 void SessionsBox::hideAll() {
@@ -212,7 +212,7 @@ void SessionsBox::paintEvent(QPaintEvent *e) {
 		p.drawText(QRect(0, 0, width(), st::noContactsHeight), lang(lng_contacts_loading), style::al_center);
 	} else {
 		int32 x = st::sessionPadding.left();
-		int32 w = width() - x - st::sessionPadding.right();
+		int32 w = width();
 
 		p.setFont(st::sessionNameFont->f);
 		p.setPen(st::black->p);
diff --git a/Telegram/SourceFiles/dialogswidget.cpp b/Telegram/SourceFiles/dialogswidget.cpp
index 6aeb84c0c..c7a88e00e 100644
--- a/Telegram/SourceFiles/dialogswidget.cpp
+++ b/Telegram/SourceFiles/dialogswidget.cpp
@@ -67,11 +67,11 @@ void DialogsListWidget::paintEvent(QPaintEvent *e) {
 	QRect r(e->rect());
 	bool trivial = (rect() == r);
 
-	QPainter p(this); 
+	Painter p(this); 
 	if (!trivial) {
 		p.setClipRect(r);
 	}
-
+	
 	if (_state == DefaultState) {
 		int32 otherStart = dialogs.list.count * st::dlgHeight;
 		PeerData *active = App::main()->activePeer(), *selected = sel ? sel->history->peer : 0;
diff --git a/Telegram/SourceFiles/dropdown.cpp b/Telegram/SourceFiles/dropdown.cpp
index a4f62bf4e..4b8570c7a 100644
--- a/Telegram/SourceFiles/dropdown.cpp
+++ b/Telegram/SourceFiles/dropdown.cpp
@@ -26,8 +26,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
 #include "window.h"
 #include "apiwrap.h"
 
-Dropdown::Dropdown(QWidget *parent) : TWidget(parent),
-	_hiding(false), a_opacity(0), _shadow(st::dropdownShadow) {
+Dropdown::Dropdown(QWidget *parent, const style::dropdown &st) : TWidget(parent),
+_ignore(false), _selected(-1), _st(st), _width(_st.width), _hiding(false), a_opacity(0), _shadow(_st.shadow) {
 	resetButtons();
 
 	_hideTimer.setSingleShot(true);
@@ -38,6 +38,10 @@ Dropdown::Dropdown(QWidget *parent) : TWidget(parent),
 	}
 }
 
+void Dropdown::ignoreShow(bool ignore) {
+	_ignore = ignore;
+}
+
 void Dropdown::onWndActiveChanged() {
 	if (!App::wnd()->windowHandle()->isActive() && !isHidden()) {
 		leaveEvent(0);
@@ -47,13 +51,21 @@ void Dropdown::onWndActiveChanged() {
 IconedButton *Dropdown::addButton(IconedButton *button) {
 	button->setParent(this);
 
-	_width = qMax(_width, st::dropdownPadding.left() + st::dropdownPadding.right() + button->width());
-	if (!_buttons.isEmpty()) {
-		_height += st::dropdownBorder;
+	int32 nw = _st.padding.left() + _st.padding.right() + button->width();
+	if (nw > _width) {
+		_width = nw;
+		for (int32 i = 0, l = _buttons.size(); i < l; ++i) _buttons[i]->resize(_width - _st.padding.left() - _st.padding.right(), _buttons[i]->height());
+	} else {
+		button->resize(_width - _st.padding.left() - _st.padding.right(), button->height());
+	}
+	if (!button->isHidden()) {
+		if (_height > _st.padding.top() + _st.padding.bottom()) {
+			_height += _st.border;
+		}
+		_height += button->height();
 	}
-	_height += button->height();
-
 	_buttons.push_back(button);
+	connect(button, SIGNAL(stateChanged(int, ButtonStateChangeSource)), this, SLOT(buttonStateChanged(int, ButtonStateChangeSource)));
 
 	resize(_width, _height);
 
@@ -61,20 +73,39 @@ IconedButton *Dropdown::addButton(IconedButton *button) {
 }
 
 void Dropdown::resetButtons() {
-	_width = st::dropdownPadding.left() + st::dropdownPadding.right();
-	_height = st::dropdownPadding.top() + st::dropdownPadding.bottom();
-	resize(_width, _height);
+	_width = qMax(_st.padding.left() + _st.padding.right(), int(_st.width));
+	_height = _st.padding.top() + _st.padding.bottom();
 	for (int32 i = 0, l = _buttons.size(); i < l; ++i) {
 		delete _buttons[i];
 	}
 	_buttons.clear();
+	resize(_width, _height);
+
+	_selected = -1;
+}
+
+void Dropdown::updateButtons() {
+	int32 top = _st.padding.top(), starttop = top;
+	for (Buttons::const_iterator i = _buttons.cbegin(), e = _buttons.cend(); i != e; ++i) {
+		if (!(*i)->isHidden()) {
+			(*i)->move(_st.padding.left(), top);
+			if ((*i)->width() != _width - _st.padding.left() - _st.padding.right()) {
+				(*i)->resize(_width - _st.padding.left() - _st.padding.right(), (*i)->height());
+			}
+			top += (*i)->height() + _st.border;
+		}
+	}
+	_height = top + _st.padding.bottom() - (top > starttop ? _st.border : 0);
+	resize(_width, _height);
 }
 
 void Dropdown::resizeEvent(QResizeEvent *e) {
-	int32 top = st::dropdownPadding.top();
+	int32 top = _st.padding.top();
 	for (Buttons::const_iterator i = _buttons.cbegin(), e = _buttons.cend(); i != e; ++i) {
-		(*i)->move(st::dropdownPadding.left(), top);
-		top += st::dropdownBorder + (*i)->height();
+		if (!(*i)->isHidden()) {
+			(*i)->move(_st.padding.left(), top);
+			top += (*i)->height() + _st.border;
+		}
 	}
 }
 
@@ -85,16 +116,24 @@ void Dropdown::paintEvent(QPaintEvent *e) {
 		p.setOpacity(a_opacity.current());
 	}
 
-	QRect r(st::dropdownPadding.left(), st::dropdownPadding.top(), _width - st::dropdownPadding.left() - st::dropdownPadding.right(), _height - st::dropdownPadding.top() - st::dropdownPadding.bottom());
 	// draw shadow
+	QRect r(_st.padding.left(), _st.padding.top(), _width - _st.padding.left() - _st.padding.right(), _height - _st.padding.top() - _st.padding.bottom());
 	_shadow.paint(p, r);
 
-	if (!_buttons.isEmpty()) { // paint separators
-		int32 top = st::dropdownPadding.top() + _buttons.front()->height();
-		p.setPen(st::dropdownBorderColor->p);
-		for (int32 i = 1, s = _buttons.size(); i < s; ++i) {
-			p.fillRect(st::dropdownPadding.left(), top, _width - st::dropdownPadding.left() - st::dropdownPadding.right(), st::dropdownBorder, st::dropdownBorderColor->b);
-			top += st::dropdownBorder + _buttons[i]->height();
+	if (!_buttons.isEmpty() && _st.border > 0) { // paint separators
+		p.setPen(_st.borderColor->p);
+		int32 top = _st.padding.top(), i = 0, l = _buttons.size();
+		for (; i < l; ++i) {
+			if (!_buttons.at(i)->isHidden()) break;
+		}
+		if (i < l) {
+			top += _buttons.at(i)->height();
+			for (++i; i < l; ++i) {
+				if (!_buttons.at(i)->isHidden()) {
+					p.fillRect(_st.padding.left(), top, _width - _st.padding.left() - _st.padding.right(), _st.border, _st.borderColor->b);
+					top += _st.border + _buttons.at(i)->height();
+				}
+			}
 		}
 	}
 }
@@ -102,6 +141,7 @@ void Dropdown::paintEvent(QPaintEvent *e) {
 void Dropdown::enterEvent(QEvent *e) {
 	_hideTimer.stop();
 	if (_hiding) showStart();
+	return TWidget::enterEvent(e);
 }
 
 void Dropdown::leaveEvent(QEvent *e) {
@@ -110,6 +150,73 @@ void Dropdown::leaveEvent(QEvent *e) {
 	} else {
 		_hideTimer.start(300);
 	}
+	return TWidget::leaveEvent(e);
+}
+
+void Dropdown::keyPressEvent(QKeyEvent *e) {
+	if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
+		if (_selected >= 0 && _selected < _buttons.size()) {
+			emit _buttons[_selected]->clicked();
+			return;
+		}
+	} else if (e->key() == Qt::Key_Escape) {
+		hideStart();
+		return;
+	}
+	if ((e->key() != Qt::Key_Up && e->key() != Qt::Key_Down) || _buttons.size() < 1) return;
+
+	bool none = (_selected < 0 || _selected >= _buttons.size());
+	int32 delta = (e->key() == Qt::Key_Down ? 1 : -1);
+	int32 newSelected = none ? (e->key() == Qt::Key_Down ? 0 : _buttons.size() - 1) : (_selected + delta);
+	if (newSelected < 0) {
+		newSelected = _buttons.size() - 1;
+	} else if (newSelected >= _buttons.size()) {
+		newSelected = 0;
+	}
+	int32 startFrom = newSelected;
+	while (_buttons.at(newSelected)->isHidden()) {
+		newSelected += delta;
+		if (newSelected < 0) {
+			newSelected = _buttons.size() - 1;
+		} else if (newSelected >= _buttons.size()) {
+			newSelected = 0;
+		}
+		if (newSelected == startFrom) return;
+	}
+	if (!none) {
+		_buttons[_selected]->setOver(false);
+	}
+	_selected = newSelected;
+	_buttons[_selected]->setOver(true);
+}
+
+void Dropdown::buttonStateChanged(int oldState, ButtonStateChangeSource source) {
+	if (source == ButtonByUser) {
+		for (int32 i = 0, l = _buttons.size(); i < l; ++i) {
+			if (_buttons[i]->getState() & Button::StateOver) {
+				if (i != _selected) {
+					_buttons[i]->setOver(false);
+				}
+			}
+		}
+	} else if (source == ButtonByHover) {
+		bool found = false;
+		for (int32 i = 0, l = _buttons.size(); i < l; ++i) {
+			if (_buttons[i]->getState() & Button::StateOver) {
+				found = true;
+				if (i != _selected) {
+					int32 sel = _selected;
+					_selected = i;
+					if (sel >= 0 && sel < _buttons.size()) {
+						_buttons[sel]->setOver(false);
+					}
+				}
+			}
+		}
+		if (!found) {
+			_selected = -1;
+		}
+	}
 }
 
 void Dropdown::otherEnter() {
@@ -147,13 +254,19 @@ void Dropdown::hideStart() {
 }
 
 void Dropdown::hideFinish() {
+	emit hiding();
 	hide();
+	for (Buttons::const_iterator i = _buttons.cbegin(), e = _buttons.cend(); i != e; ++i) {
+		(*i)->clearState();
+	}
+	_selected = -1;
 }
 
 void Dropdown::showStart() {
 	if (!isHidden() && a_opacity.current() == 1) {
 		return;
 	}
+	_selected = -1;
 	_hiding = false;
 	show();
 	a_opacity.start(1);
@@ -161,7 +274,7 @@ void Dropdown::showStart() {
 }
 
 bool Dropdown::animStep(float64 ms) {
-	float64 dt = ms / st::dropdownDuration;
+	float64 dt = ms / _st.duration;
 	bool res = true;
 	if (dt >= 1) {
 		a_opacity.finish();
@@ -312,7 +425,7 @@ void DragArea::showStart() {
 }
 
 bool DragArea::animStep(float64 ms) {
-	float64 dt = ms / st::dropdownDuration;
+	float64 dt = ms / st::dropdownDef.duration;
 	bool res = true;
 	if (dt >= 1) {
 		a_opacity.finish();
@@ -648,7 +761,7 @@ void EmojiPanInner::showEmojiPack(DBIEmojiTab packIndex) {
 }
 
 EmojiPan::EmojiPan(QWidget *parent) : TWidget(parent),
-_hiding(false), a_opacity(0), _shadow(st::dropdownShadow),
+_hiding(false), a_opacity(0), _shadow(st::dropdownDef.shadow),
 _recent  (this, qsl("emoji_group"), dbietRecent  , QString(), cEmojiTab() == dbietRecent  , st::rbEmojiRecent),
 _people  (this, qsl("emoji_group"), dbietPeople  , QString(), cEmojiTab() == dbietPeople  , st::rbEmojiPeople),
 _nature  (this, qsl("emoji_group"), dbietNature  , QString(), cEmojiTab() == dbietNature  , st::rbEmojiNature),
@@ -665,15 +778,15 @@ _scroll(this, st::emojiScroll), _inner() {
 		_inner.showEmojiPack(cEmojiTab());
 	}
 
-	_scroll.setGeometry(st::dropdownPadding.left() + st::emojiPanPadding.left(), st::dropdownPadding.top() + _recent.height() + st::emojiPanPadding.top(), st::emojiPanPadding.left() + _inner.width() + st::emojiPanPadding.right(), EmojiPadRowsPerPage * st::emojiPanSize.height() - st::emojiPanSub);
+	_scroll.setGeometry(st::dropdownDef.padding.left() + st::emojiPanPadding.left(), st::dropdownDef.padding.top() + _recent.height() + st::emojiPanPadding.top(), st::emojiPanPadding.left() + _inner.width() + st::emojiPanPadding.right(), EmojiPadRowsPerPage * st::emojiPanSize.height() - st::emojiPanSub);
 	_scroll.setWidget(&_inner);
 
-	_width = st::dropdownPadding.left() + st::emojiPanPadding.left() + _scroll.width() + st::emojiPanPadding.right() + st::dropdownPadding.right();
-	_height = st::dropdownPadding.top() + _recent.height() + st::emojiPanPadding.top() + _scroll.height() + st::emojiPanPadding.bottom() + st::dropdownPadding.bottom();
+	_width = st::dropdownDef.padding.left() + st::emojiPanPadding.left() + _scroll.width() + st::emojiPanPadding.right() + st::dropdownDef.padding.right();
+	_height = st::dropdownDef.padding.top() + _recent.height() + st::emojiPanPadding.top() + _scroll.height() + st::emojiPanPadding.bottom() + st::dropdownDef.padding.bottom();
 	resize(_width, _height);
 
-	int32 left = st::dropdownPadding.left() + (_width - st::dropdownPadding.left() - st::dropdownPadding.right() - 7 * _recent.width()) / 2;
-	int32 top = st::dropdownPadding.top();
+	int32 left = st::dropdownDef.padding.left() + (_width - st::dropdownDef.padding.left() - st::dropdownDef.padding.right() - 7 * _recent.width()) / 2;
+	int32 top = st::dropdownDef.padding.top();
 	_recent.move(left, top);  left += _recent.width();
 	_people.move(left, top);  left += _people.width();
 	_nature.move(left, top);  left += _nature.width();
@@ -716,7 +829,7 @@ void EmojiPan::paintEvent(QPaintEvent *e) {
 		p.setOpacity(a_opacity.current());
 	}
 
-	QRect r(st::dropdownPadding.left(), st::dropdownPadding.top(), _width - st::dropdownPadding.left() - st::dropdownPadding.right(), _height - st::dropdownPadding.top() - st::dropdownPadding.bottom());
+	QRect r(st::dropdownDef.padding.left(), st::dropdownDef.padding.top(), _width - st::dropdownDef.padding.left() - st::dropdownDef.padding.right(), _height - st::dropdownDef.padding.top() - st::dropdownDef.padding.bottom());
 
 	// draw shadow
 	_shadow.paint(p, r);
@@ -765,7 +878,7 @@ void EmojiPan::fastHide() {
 }
 
 bool EmojiPan::animStep(float64 ms) {
-	float64 dt = ms / st::dropdownDuration;
+	float64 dt = ms / st::dropdownDef.duration;
 	bool res = true;
 	if (dt >= 1) {
 		a_opacity.finish();
@@ -786,7 +899,7 @@ bool EmojiPan::animStep(float64 ms) {
 void EmojiPan::hideStart() {
 	if (_cache.isNull()) {
 		showAll();
-		_cache = myGrab(this, rect().marginsRemoved(st::dropdownPadding));
+		_cache = myGrab(this, rect().marginsRemoved(st::dropdownDef.padding));
 	}
 	hideAll();
 	_hiding = true;
@@ -806,7 +919,7 @@ void EmojiPan::showStart() {
 	}
 	if (_cache.isNull()) {
 		showAll();
-		_cache = myGrab(this, rect().marginsRemoved(st::dropdownPadding));
+		_cache = myGrab(this, rect().marginsRemoved(st::dropdownDef.padding));
 	}
 	hideAll();
 	_hiding = false;
@@ -1048,7 +1161,7 @@ void MentionsInner::onParentGeometryChanged() {
 }
 
 MentionsDropdown::MentionsDropdown(QWidget *parent) : QWidget(parent),
-_scroll(this, st::mentionScroll), _inner(this, &_rows, &_hrows), _chat(0), _hiding(false), a_opacity(0), _shadow(st::dropdownShadow) {
+_scroll(this, st::mentionScroll), _inner(this, &_rows, &_hrows), _chat(0), _hiding(false), a_opacity(0), _shadow(st::dropdownDef.shadow) {
 	_hideTimer.setSingleShot(true);
 	connect(&_hideTimer, SIGNAL(timeout()), this, SLOT(hideStart()));
 	connect(&_inner, SIGNAL(chosen(QString)), this, SIGNAL(chosen(QString)));
@@ -1235,7 +1348,7 @@ void MentionsDropdown::showStart() {
 }
 
 bool MentionsDropdown::animStep(float64 ms) {
-	float64 dt = ms / st::dropdownDuration;
+	float64 dt = ms / st::dropdownDef.duration;
 	bool res = true;
 	if (dt >= 1) {
 		a_opacity.finish();
@@ -1284,330 +1397,3 @@ bool MentionsDropdown::eventFilter(QObject *obj, QEvent *e) {
 
 MentionsDropdown::~MentionsDropdown() {
 }
-
-//StickerPanInner::StickerPanInner(QWidget *parent) : QWidget(parent), _emoji(0), _selected(-1), _pressedSel(-1) {
-//	resize(StickerPadPerRow * st::stickerPanSize.width(), EmojiPadRowsPerPage * st::emojiPanSize.height() - st::emojiPanSub);
-//	setMouseTracking(true);
-//	setFocusPolicy(Qt::NoFocus);
-//}
-//
-//void StickerPanInner::paintEvent(QPaintEvent *e) {
-//	QPainter p(this);
-//	int32 size = _stickers.size();
-//
-//	QRect r = e ? e->rect() : rect();
-//
-//	int32 rows = (size / StickerPadPerRow) + ((size % StickerPadPerRow) ? 1 : 0);
-//	int32 fromrow = qMax(qFloor(r.top() / st::stickerPanSize.height()), 0), torow = qMin(qCeil(r.bottom() / st::stickerPanSize.height()) + 1, rows);
-//	for (int32 i = fromrow; i < torow; ++i) {
-//		for (int32 j = 0; j < StickerPadPerRow; ++j) {
-//			int32 index = i * StickerPadPerRow + j;
-//			if (index >= size) break;
-//
-//			float64 hover = _hovers[index];
-//			QPoint pos(j * st::stickerPanSize.width(), i * st::stickerPanSize.height());
-//			if (hover > 0) {
-//				p.setOpacity(hover);
-//				p.setBrush(st::stickerPanHover->b);
-//				p.setPen(Qt::NoPen);
-//				p.drawRoundedRect(QRect(pos, st::stickerPanSize), st::stickerPanRound, st::stickerPanRound);
-//				p.setOpacity(1);
-//			}
-//
-//			DocumentData *data = _stickers[index];
-//			bool already = !data->already().isEmpty(), hasdata = !data->data.isEmpty();
-//			if (!data->loader && data->status != FileFailed && !already && !hasdata) {
-//				data->save(QString());
-//			}
-//			if (data->sticker->isNull() && (already || hasdata)) {
-//				if (already) {
-//					data->sticker = ImagePtr(data->already());
-//				} else {
-//					data->sticker = ImagePtr(data->data);
-//				}
-//			}
-//
-//			float64 coef = qMin(st::stickerPanSize.width() / float64(data->dimensions.width()), st::stickerPanSize.height() / float64(data->dimensions.height()));
-//			int32 w = qRound(coef * data->dimensions.width()), h = qRound(coef * data->dimensions.height());
-//			pos += QPoint((st::stickerPanSize.width() - w) / 2, (st::stickerPanSize.height() - h) / 2);
-//
-//			if (data->sticker->isNull()) {
-//				p.drawPixmap(pos, data->thumb->pix(w));
-//			} else {
-//				p.drawPixmap(pos, data->sticker->pix(w));
-//			}
-//		}
-//	}
-//}
-//
-//void StickerPanInner::mousePressEvent(QMouseEvent *e) {
-//	_lastMousePos = e->globalPos();
-//	updateSelected();
-//	_pressedSel = _selected;
-//}
-//
-//void StickerPanInner::mouseReleaseEvent(QMouseEvent *e) {
-//	_lastMousePos = e->globalPos();
-//	updateSelected();
-//	if (_selected == _pressedSel && _selected >= 0 && _selected < _stickers.size()) {
-//		emit stickerSelected(_stickers[_selected]);
-//	}
-//}
-//
-//void StickerPanInner::mouseMoveEvent(QMouseEvent *e) {
-//	_lastMousePos = e->globalPos();
-//	updateSelected();
-//}
-//
-//void StickerPanInner::leaveEvent(QEvent *e) {
-//	_lastMousePos = QCursor::pos();
-//	updateSelected();
-//}
-//
-//void StickerPanInner::updateSelected() {
-//	int32 selIndex = -1;
-//	QPoint p(mapFromGlobal(_lastMousePos));
-//	if (p.x() >= 0 && p.y() >= 0 && p.x() < StickerPadPerRow * st::stickerPanSize.width()) {
-//		selIndex = qFloor(p.y() / st::stickerPanSize.height()) * StickerPadPerRow + qFloor(p.x() / st::stickerPanSize.width());
-//		if (selIndex >= _stickers.size()) {
-//			selIndex = -1;
-//		}
-//	}
-//	if (selIndex != _selected) {
-//		bool startanim = false;
-//		if (_selected >= 0) {
-//			_stickerAnimations.remove(_selected + 1);
-//			if (_stickerAnimations.find(-_selected - 1) == _stickerAnimations.end()) {
-//				if (_stickerAnimations.isEmpty()) startanim = true;
-//				_stickerAnimations.insert(-_selected - 1, getms());
-//			}
-//		}
-//		_selected = selIndex;
-//		if (_selected >= 0) {
-//			_stickerAnimations.remove(-_selected - 1);
-//			if (_stickerAnimations.find(_selected + 1) == _stickerAnimations.end()) {
-//				if (_stickerAnimations.isEmpty()) startanim = true;
-//				_stickerAnimations.insert(_selected + 1, getms());
-//			}
-//		}
-//		if (startanim) anim::start(this);
-//		setCursor((_selected >= 0) ? style::cur_pointer : style::cur_default);
-//	}
-//}
-//
-//bool StickerPanInner::animStep(float64 ms) {
-//	uint64 now = getms();
-//	for (StickerAnimations::iterator i = _stickerAnimations.begin(); i != _stickerAnimations.end();) {
-//		float64 dt = float64(now - i.value()) / st::emojiPanDuration;
-//		if (dt >= 1) {
-//			_hovers[qAbs(i.key()) - 1] = (i.key() > 0) ? 1 : 0;
-//			i = _stickerAnimations.erase(i);
-//		} else {
-//			_hovers[qAbs(i.key()) - 1] = (i.key() > 0) ? dt : (1 - dt);
-//			++i;
-//		}
-//	}
-//	update();
-//	return !_stickerAnimations.isEmpty();
-//}
-//
-//void StickerPanInner::showStickerPack(EmojiPtr emoji) {
-//	StickerPack stickers = cStickers().value(emoji);
-//	if (stickers.isEmpty()) {
-//		_emoji = 0;
-//	} else {
-//		_emoji = emoji;
-//		_stickers = stickers;
-//		_hovers = QVector<float64>(_stickers.size(), 0);
-//		_stickerAnimations.clear();
-//		_selected = _pressedSel = -1;
-//		int32 size = _stickers.size();
-//		int32 h = qMax(((size / StickerPadPerRow) + ((size % StickerPadPerRow) ? 1 : 0)) * st::stickerPanSize.height(), EmojiPadRowsPerPage * st::emojiPanSize.height() - int(st::emojiPanSub));
-//		resize(width(), h);
-//		_lastMousePos = QCursor::pos();
-//		updateSelected();
-//		update();
-//	}
-//}
-//
-//bool StickerPanInner::hasContent() const {
-//	return !!_emoji;
-//}
-//
-//StickerPan::StickerPan(QWidget *parent) : TWidget(parent),
-//_hiding(false), a_opacity(0), _shadow(st::dropdownShadow),
-//_scroll(this, st::emojiScroll), _emoji(0), _inner() {
-//	setFocusPolicy(Qt::NoFocus);
-//	_scroll.setFocusPolicy(Qt::NoFocus);
-//	_scroll.viewport()->setFocusPolicy(Qt::NoFocus);
-//
-//	_inner.showStickerPack(0);
-//	_scroll.setGeometry(st::dropdownPadding.left() + st::stickerPanPadding.left(), st::dropdownPadding.top() + st::rbEmoji.height + st::stickerPanPadding.top(), st::stickerPanPadding.left() + _inner.width() + st::stickerPanPadding.right(), EmojiPadRowsPerPage * st::emojiPanSize.height() - st::emojiPanSub);
-//	_scroll.setWidget(&_inner);
-//
-//	_width = st::dropdownPadding.left() + st::stickerPanPadding.left() + _scroll.width() + st::stickerPanPadding.right() + st::dropdownPadding.right();
-//	_height = st::dropdownPadding.top() + st::rbEmoji.height + st::stickerPanPadding.top() + _scroll.height() + st::stickerPanPadding.bottom() + st::dropdownPadding.bottom();
-//	resize(_width, _height);
-//
-//	_hideTimer.setSingleShot(true);
-//	connect(&_hideTimer, SIGNAL(timeout()), this, SLOT(hideStart()));
-//
-//	connect(&_scroll, SIGNAL(scrolled()), &_inner, SLOT(updateSelected()));
-//
-//	connect(&_inner, SIGNAL(stickerSelected(DocumentData*)), this, SIGNAL(stickerSelected(DocumentData*)));
-//}
-//
-//void StickerPan::setStickerPack(EmojiPtr emoji, bool show) {
-//	_emoji = emoji;
-//	_inner.showStickerPack(_emoji);
-//	if (!_hiding && !isHidden() && !_inner.hasContent()) {
-//		_hideTimer.stop();
-//		hideStart();
-//	} else if ((_hiding || isHidden()) && _inner.hasContent() && show) {
-//		_hideTimer.stop();
-//		showStart();
-//	}
-//}
-//
-//void StickerPan::paintEvent(QPaintEvent *e) {
-//	QPainter p(this);
-//
-//	if (!_cache.isNull()) {
-//		p.setOpacity(a_opacity.current());
-//	}
-//
-//	QRect r(st::dropdownPadding.left(), st::dropdownPadding.top(), _width - st::dropdownPadding.left() - st::dropdownPadding.right(), _height - st::dropdownPadding.top() - st::dropdownPadding.bottom());
-//
-//	// draw shadow
-//	_shadow.paint(p, r);
-//
-//	if (_cache.isNull()) {
-//		p.fillRect(r, st::white->b);
-//
-//		p.setFont(st::stickerPanFont->f);
-//		p.setPen(st::stickerPanColor->p);
-//		p.drawText(QRect(st::dropdownPadding.left(), st::dropdownPadding.top(), width() - st::dropdownPadding.left() - st::dropdownPadding.right(), st::rbEmoji.height), lang(lng_attach_stickers_header), style::al_center);
-//	} else {
-//		p.drawPixmap(r.left(), r.top(), _cache);
-//	}
-//}
-//
-//void StickerPan::enterEvent(QEvent *e) {
-//	_hideTimer.stop();
-//	if (_hiding) showStart();
-//}
-//
-//void StickerPan::leaveEvent(QEvent *e) {
-//	if (animating()) {
-//		hideStart();
-//	} else {
-//		_hideTimer.start(300);
-//	}
-//}
-//
-//void StickerPan::otherEnter() {
-//	_hideTimer.stop();
-//	showStart();
-//}
-//
-//void StickerPan::otherLeave() {
-//	if (animating()) {
-//		hideStart();
-//	} else {
-//		_hideTimer.start(0);
-//	}
-//}
-//
-//void StickerPan::fastHide() {
-//	if (animating()) {
-//		anim::stop(this);
-//	}
-//	a_opacity = anim::fvalue(0, 0);
-//	_hideTimer.stop();
-//	hide();
-//	_cache = QPixmap();
-//}
-//
-//bool StickerPan::animStep(float64 ms) {
-//	float64 dt = ms / st::dropdownDuration;
-//	bool res = true;
-//	if (dt >= 1) {
-//		a_opacity.finish();
-//		if (_hiding) {
-//			hideFinish();
-//		} else {
-//			showAll();
-//			_cache = QPixmap();
-//		}
-//		res = false;
-//	} else {
-//		a_opacity.update(dt, anim::linear);
-//	}
-//	update();
-//	return res;
-//}
-//
-//void StickerPan::hideStart() {
-//	if (_cache.isNull()) {
-//		showAll();
-//		_cache = myGrab(this, rect().marginsRemoved(st::dropdownPadding));
-//	}
-//	hideAll();
-//	_hiding = true;
-//	a_opacity.start(0);
-//	anim::start(this);
-//}
-//
-//void StickerPan::hideFinish() {
-//	hide();
-//	_cache = QPixmap();
-//}
-//
-//void StickerPan::showStart() {
-//	if (!isHidden() && a_opacity.current() == 1) {
-//		return;
-//	}
-//	if (!_inner.hasContent()) {
-//		return;
-//	}
-//	if (_cache.isNull()) {
-//		showAll();
-//		_cache = myGrab(this, rect().marginsRemoved(st::dropdownPadding));
-//	}
-//	hideAll();
-//	_hiding = false;
-//	show();
-//	a_opacity.start(1);
-//	anim::start(this);
-//}
-//
-//bool StickerPan::eventFilter(QObject *obj, QEvent *e) {
-//	if (e->type() == QEvent::Enter) {
-//		if (dynamic_cast<EmojiPan*>(obj)) {
-//			enterEvent(e);
-//		} else {
-//			otherEnter();
-//		}
-//	} else if (e->type() == QEvent::Leave) {
-//		if (dynamic_cast<EmojiPan*>(obj)) {
-//			leaveEvent(e);
-//		} else {
-//			otherLeave();
-//		}
-//	} else if (e->type() == QEvent::MouseButtonPress && static_cast<QMouseEvent*>(e)->button() == Qt::LeftButton && !dynamic_cast<EmojiPan*>(obj)) {
-//		if (isHidden() || _hiding) {
-//			otherEnter();
-//		} else {
-//			otherLeave();
-//		}
-//	}
-//	return false;
-//}
-//
-//void StickerPan::showAll() {
-//	_scroll.show();
-//}
-//
-//void StickerPan::hideAll() {
-//	_scroll.hide();
-//}
diff --git a/Telegram/SourceFiles/dropdown.h b/Telegram/SourceFiles/dropdown.h
index 7ba6bf008..e3b41b4c6 100644
--- a/Telegram/SourceFiles/dropdown.h
+++ b/Telegram/SourceFiles/dropdown.h
@@ -25,25 +25,32 @@ class Dropdown : public TWidget, public Animated {
 
 public:
 
-	Dropdown(QWidget *parent);
+	Dropdown(QWidget *parent, const style::dropdown &st = st::dropdownDef);
 
 	IconedButton *addButton(IconedButton *button);
 	void resetButtons();
+	void updateButtons();
 
 	void resizeEvent(QResizeEvent *e);
 	void paintEvent(QPaintEvent *e);
 
 	void enterEvent(QEvent *e);
 	void leaveEvent(QEvent *e);
+	void keyPressEvent(QKeyEvent *e);
 	void otherEnter();
 	void otherLeave();
 
 	void fastHide();
+	void ignoreShow(bool ignore = true);
 
 	bool animStep(float64 ms);
 
 	bool eventFilter(QObject *obj, QEvent *e);
 
+signals:
+
+	void hiding();
+
 public slots:
 
 	void hideStart();
@@ -52,13 +59,21 @@ public slots:
 	void showStart();
 	void onWndActiveChanged();
 
+	void buttonStateChanged(int oldState, ButtonStateChangeSource source);
+
 private:
 
 	void adjustButtons();
 
+	bool _ignore;
+
 	typedef QVector<IconedButton*> Buttons;
 	Buttons _buttons;
 
+	int32 _selected;
+
+	const style::dropdown &_st;
+
 	int32 _width, _height;
 	bool _hiding;
 
@@ -336,97 +351,3 @@ private:
 	BoxShadow _shadow;
 
 };
-
-//class StickerPanInner : public QWidget, public Animated {
-//	Q_OBJECT
-//
-//public:
-//
-//	StickerPanInner(QWidget *parent = 0);
-//
-//	void paintEvent(QPaintEvent *e);
-//
-//	void mousePressEvent(QMouseEvent *e);
-//	void mouseReleaseEvent(QMouseEvent *e);
-//	void mouseMoveEvent(QMouseEvent *e);
-//	void leaveEvent(QEvent *e);
-//
-//	bool animStep(float64 ms);
-//
-//	void showStickerPack(EmojiPtr emoji);
-//	bool hasContent() const;
-//
-//public slots:
-//
-//	void updateSelected();
-//
-//signals:
-//
-//	void stickerSelected(DocumentData *sticker);
-//
-//private:
-//
-//	typedef QMap<int32, uint64> StickerAnimations; // index - showing, -index - hiding
-//	StickerAnimations _stickerAnimations;
-//
-//	StickerPack _stickers;
-//	QVector<float64> _hovers;
-//
-//	EmojiPtr _emoji;
-//	int32 _selected, _pressedSel;
-//	QPoint _lastMousePos;
-//
-//};
-//
-//class StickerPan : public TWidget, public Animated {
-//	Q_OBJECT
-//
-//public:
-//
-//	StickerPan(QWidget *parent);
-//
-//	void setStickerPack(EmojiPtr emoji, bool show);
-//	void paintEvent(QPaintEvent *e);
-//
-//	void enterEvent(QEvent *e);
-//	void leaveEvent(QEvent *e);
-//	void otherEnter();
-//	void otherLeave();
-//
-//	void fastHide();
-//
-//	bool animStep(float64 ms);
-//
-//	bool eventFilter(QObject *obj, QEvent *e);
-//
-//public slots:
-//
-//	void hideStart();
-//	void hideFinish();
-//
-//	void showStart();
-//
-//signals:
-//
-//	void stickerSelected(DocumentData *sticker);
-//
-//private:
-//
-//	void showAll();
-//	void hideAll();
-//
-//	int32 _width, _height;
-//	bool _hiding;
-//	QPixmap _cache;
-//
-//	anim::fvalue a_opacity;
-//
-//	QTimer _hideTimer;
-//
-//	BoxShadow _shadow;
-//
-//	EmojiPtr _emoji;
-//	ScrollArea _scroll;
-//	StickerPanInner _inner;
-//
-//};
diff --git a/Telegram/SourceFiles/gui/boxshadow.cpp b/Telegram/SourceFiles/gui/boxshadow.cpp
index 1cc6ecebb..2b921e1e6 100644
--- a/Telegram/SourceFiles/gui/boxshadow.cpp
+++ b/Telegram/SourceFiles/gui/boxshadow.cpp
@@ -20,11 +20,14 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
 #include "boxshadow.h"
 
 BoxShadow::BoxShadow(const style::rect &topLeft) : _size(topLeft.width() / cIntRetinaFactor()) {
+	if (!_size) return;
+
 	QImage cornersImage(_size * 2, _size * 2, QImage::Format_ARGB32_Premultiplied);
 	{
 		QPainter p(&cornersImage);
-		p.drawPixmap(QPoint(0, 0), App::sprite(), topLeft);
+		p.drawPixmap(QPoint(rtl() ? _size : 0, 0), App::sprite(), topLeft);
 	}
+	if (rtl()) cornersImage = cornersImage.mirrored(true, false);
 	uchar *bits = cornersImage.bits();
 	if (bits) {
 		for (
@@ -58,6 +61,8 @@ BoxShadow::BoxShadow(const style::rect &topLeft) : _size(topLeft.width() / cIntR
 }
 
 void BoxShadow::paint(QPainter &p, const QRect &box, const QPoint &shift, int32 flags) {
+	if (!_size) return;
+
 	int32 count = _colors.size(), minus = _size - count + 1;
 	bool left = (flags & Left), top = (flags & Top), right = (flags & Right), bottom = (flags & Bottom);
 	if (left && top) p.drawPixmap(box.left() - _size + minus + shift.x(), box.top() - _size + minus + shift.y(), _corners, 0, 0, _size, _size);
diff --git a/Telegram/SourceFiles/gui/button.cpp b/Telegram/SourceFiles/gui/button.cpp
index 1dd71e00e..6e1653eb2 100644
--- a/Telegram/SourceFiles/gui/button.cpp
+++ b/Telegram/SourceFiles/gui/button.cpp
@@ -77,6 +77,7 @@ void Button::mouseReleaseEvent(QMouseEvent *e) {
 }
 
 void Button::setOver(bool over, ButtonStateChangeSource source) {
+//	LOG(("Set over: %1, by: %2 AT %3").arg(logBool(over)).arg(source).arg(dynamic_cast<IconedButton*>(this) ? dynamic_cast<IconedButton*>(this)->getText() : qsl("Unknown")));
 	if (over && !(_state & StateOver)) {
 		int oldState = _state;
 		_state |= StateOver;
diff --git a/Telegram/SourceFiles/gui/contextmenu.cpp b/Telegram/SourceFiles/gui/contextmenu.cpp
index ae0b1253c..91d088f30 100644
--- a/Telegram/SourceFiles/gui/contextmenu.cpp
+++ b/Telegram/SourceFiles/gui/contextmenu.cpp
@@ -25,8 +25,8 @@
 
 #include "lang.h"
 
-ContextMenu::ContextMenu(QWidget *parent, const style::iconedButton &st) : TWidget(0),
-_hiding(false), _buttonStyle(st), _shadow(st::dropdownShadow), _selected(-1), a_opacity(0), _deleteOnHide(false) {
+ContextMenu::ContextMenu(QWidget *parent, const style::dropdown &st, const style::iconedButton &btnst) : TWidget(0),
+_width(st.width), _hiding(false), _st(st), _btnst(btnst), _shadow(_st.shadow), _selected(-1), a_opacity(0), _deleteOnHide(false) {
 	resetActions();
 
 	setWindowFlags(Qt::FramelessWindowHint | Qt::BypassWindowManagerHint | Qt::Tool | Qt::NoDropShadowWindowHint | Qt::WindowStaysOnTopHint);
@@ -43,13 +43,13 @@ QAction *ContextMenu::addAction(const QString &text, const QObject *receiver, co
 	connect(a, SIGNAL(changed()), this, SLOT(actionChanged()));
 
 	IconedButton *b = 0;
-	_buttons.push_back(b = new IconedButton(this, _buttonStyle, a->text()));
+	_buttons.push_back(b = new IconedButton(this, _btnst, a->text()));
 	connect(b, SIGNAL(clicked()), this, SLOT(hideStart()));
 	connect(b, SIGNAL(clicked()), a, SIGNAL(triggered()));
 	connect(b, SIGNAL(stateChanged(int,ButtonStateChangeSource)), this, SLOT(buttonStateChanged(int,ButtonStateChangeSource)));
 
-	_width = qMax(_width, int(st::dropdownPadding.left() + st::dropdownPadding.right() + b->width()));
-	for (int32 i = 0, l = _buttons.size(); i < l; ++i) _buttons[i]->resize(_width - int(st::dropdownPadding.left() + st::dropdownPadding.right()), _buttons[i]->height());
+	_width = qMax(_width, int(_st.padding.left() + _st.padding.right() + b->width()));
+	for (int32 i = 0, l = _buttons.size(); i < l; ++i) _buttons[i]->resize(_width - int(_st.padding.left() + _st.padding.right()), _buttons[i]->height());
 	_height += b->height();
 
 	resize(_width, _height);
@@ -64,8 +64,8 @@ ContextMenu::Actions &ContextMenu::actions() {
 void ContextMenu::actionChanged() {
 	for (int32 i = 0, l = _actions.size(); i < l; ++i) {
 		_buttons[i]->setText(_actions[i]->text());
-		_width = qMax(_width, int(st::dropdownPadding.left() + st::dropdownPadding.right() + _buttons[i]->width()));
-		_buttons[i]->resize(_width - int(st::dropdownPadding.left() + st::dropdownPadding.right()), _buttons[i]->height());
+		_width = qMax(_width, int(_st.padding.left() + _st.padding.right() + _buttons[i]->width()));
+		_buttons[i]->resize(_width - int(_st.padding.left() + _st.padding.right()), _buttons[i]->height());
 	}
 }
 
@@ -100,8 +100,8 @@ void ContextMenu::buttonStateChanged(int oldState, ButtonStateChangeSource sourc
 }
 
 void ContextMenu::resetActions() {
-	_width = st::dropdownPadding.left() + st::dropdownPadding.right();
-	_height = st::dropdownPadding.top() + st::dropdownPadding.bottom();
+	_width = qMax(_st.padding.left() + _st.padding.right(), int(_st.width));
+	_height = _st.padding.top() + _st.padding.bottom();
 	resize(_width, _height);
 
 	clearActions();
@@ -122,9 +122,9 @@ void ContextMenu::clearActions() {
 }
 
 void ContextMenu::resizeEvent(QResizeEvent *e) {
-	int32 top = st::dropdownPadding.top();
+	int32 top = _st.padding.top();
 	for (Buttons::const_iterator i = _buttons.cbegin(), e = _buttons.cend(); i != e; ++i) {
-		(*i)->move(st::dropdownPadding.left(), top);
+		(*i)->move(_st.padding.left(), top);
 		top += (*i)->height();
 	}
 }
@@ -141,7 +141,7 @@ void ContextMenu::paintEvent(QPaintEvent *e) {
 		p.setOpacity(a_opacity.current());
 	}
 
-	QRect r(st::dropdownPadding.left(), st::dropdownPadding.top(), _width - st::dropdownPadding.left() - st::dropdownPadding.right(), _height - st::dropdownPadding.top() - st::dropdownPadding.bottom());
+	QRect r(_st.padding.left(), _st.padding.top(), _width - _st.padding.left() - _st.padding.right(), _height - _st.padding.top() - _st.padding.bottom());
 	// draw shadow
 	_shadow.paint(p, r);
 }
@@ -245,13 +245,19 @@ void ContextMenu::deleteOnHide() {
 }
 
 void ContextMenu::popup(const QPoint &p) {
-	QPoint w = p - QPoint(st::dropdownPadding.left(), st::dropdownPadding.top());
+	QPoint w = p - QPoint(_st.padding.left(), _st.padding.top());
 	QRect r = App::app() ? App::app()->desktop()->screenGeometry(p) : QDesktopWidget().screenGeometry(p);
-	if (w.x() + width() - st::dropdownPadding.right() > r.x() + r.width()) {
-		w.setX(r.x() + r.width() - width() + st::dropdownPadding.right());
+	if (rtl()) {
+		if (w.x() - width() + 2 * _st.padding.left() < r.x() - _st.padding.left()) {
+			w.setX(r.x() - _st.padding.left());
+		} else {
+			w.setX(w.x() - width() + 2 * _st.padding.left());
+		}
+	} else if (w.x() + width() - _st.padding.right() > r.x() + r.width()) {
+		w.setX(r.x() + r.width() - width() + _st.padding.right());
 	}
-	if (w.y() + height() - st::dropdownPadding.bottom() > r.y() + r.height()) {
-		w.setY(p.y() - height() + st::dropdownPadding.bottom());
+	if (w.y() + height() - _st.padding.bottom() > r.y() + r.height()) {
+		w.setY(p.y() - height() + _st.padding.bottom());
 	}
 	if (w.y() < r.y()) {
 		w.setY(r.y());
diff --git a/Telegram/SourceFiles/gui/contextmenu.h b/Telegram/SourceFiles/gui/contextmenu.h
index 267581a4a..a3c25dcfa 100644
--- a/Telegram/SourceFiles/gui/contextmenu.h
+++ b/Telegram/SourceFiles/gui/contextmenu.h
@@ -25,7 +25,7 @@ class ContextMenu : public TWidget, public Animated {
 
 public:
 
-	ContextMenu(QWidget *parent, const style::iconedButton &st = st::btnContext);
+	ContextMenu(QWidget *parent, const style::dropdown &st = st::dropdownDef, const style::iconedButton &btnst = st::btnContext);
 	QAction *addAction(const QString &text, const QObject *receiver, const char* member);
 	void resetActions();
 
@@ -72,7 +72,8 @@ private:
 	int32 _width, _height;
 	bool _hiding;
 
-	const style::iconedButton &_buttonStyle;
+	const style::dropdown &_st;
+	const style::iconedButton &_btnst;
 
 	BoxShadow _shadow;
 	int32 _selected;
diff --git a/Telegram/SourceFiles/gui/flatbutton.cpp b/Telegram/SourceFiles/gui/flatbutton.cpp
index 0c5165ee8..c090958cc 100644
--- a/Telegram/SourceFiles/gui/flatbutton.cpp
+++ b/Telegram/SourceFiles/gui/flatbutton.cpp
@@ -172,16 +172,26 @@ void IconedButton::setText(const QString &text) {
 	}
 }
 
+QString IconedButton::getText() const {
+	return _text;
+}
+
 bool IconedButton::animStep(float64 ms) {
-	float64 dt = ms / _st.duration;
 	bool res = true;
-	if (dt >= 1) {
+	if (_st.duration <= 1) {
 		a_opacity.finish();
 		a_bg.finish();
 		res = false;
 	} else {
-		a_opacity.update(dt, anim::linear);
-		a_bg.update(dt, anim::linear);
+		float64 dt = ms / _st.duration;
+		if (dt >= 1) {
+			a_opacity.finish();
+			a_bg.finish();
+			res = false;
+		} else {
+			a_opacity.update(dt, anim::linear);
+			a_bg.update(dt, anim::linear);
+		}
 	}
 	update();
 	return res;
diff --git a/Telegram/SourceFiles/gui/flatbutton.h b/Telegram/SourceFiles/gui/flatbutton.h
index 21f700fe3..fc6958d74 100644
--- a/Telegram/SourceFiles/gui/flatbutton.h
+++ b/Telegram/SourceFiles/gui/flatbutton.h
@@ -100,6 +100,7 @@ public:
 	void setOpacity(float64 o);
 
 	void setText(const QString &text);
+	QString getText() const;
 	
 public slots:
 
diff --git a/Telegram/SourceFiles/gui/style_core.h b/Telegram/SourceFiles/gui/style_core.h
index db4a53fae..cfab2435e 100644
--- a/Telegram/SourceFiles/gui/style_core.h
+++ b/Telegram/SourceFiles/gui/style_core.h
@@ -197,14 +197,17 @@ inline bool operator!=(const Font &a, const Font &b) {
 	typedef QMap<uint32, ColorData*> ColorDatas;
 	extern ColorDatas _colorsMap;
 
+	extern int _spriteWidth;
+
 	typedef float64 number;
 	typedef QString string;
 	typedef QRect rect;
-    class sprite : public rect {
+
+	class sprite : public rect {
     public:
         sprite() {
         }
-        sprite(int left, int top, int width, int height) : rect(left, top, width, height) {
+		sprite(int left, int top, int width, int height) : rect(rtl() ? (_spriteWidth - left - width) : left, top, width, height) {
         }
         inline int pxWidth() const {
             return rect::width() / cIntRetinaFactor();
diff --git a/Telegram/SourceFiles/gui/twidget.h b/Telegram/SourceFiles/gui/twidget.h
index 74bf7fac1..5e458f973 100644
--- a/Telegram/SourceFiles/gui/twidget.h
+++ b/Telegram/SourceFiles/gui/twidget.h
@@ -21,34 +21,54 @@ void rtl(bool is);
 bool rtl();
 Qt::LayoutDirection langDir();
 
+inline QRect rtlrect(int x, int y, int w, int h, int outerw) {
+	return rtl() ? QRect(outerw - x - w, y, w, h) : QRect(x, y, w, h);
+}
+
 class Widget : public QWidget {
 public:
 
 	Widget(QWidget *parent = 0) : QWidget(parent) {
 	}
-	void moveToLeft(int x, int y, int w) {
-		move(rtl() ? (x + w - width()) : x, y);
+	void moveToLeft(int x, int y, int outerw) {
+		move(rtl() ? (outerw - x - width()) : x, y);
 	}
-	void moveToRight(int x, int y, int w) {
-		move(rtl() ? x : (x + w - width()), y);
+	void moveToRight(int x, int y, int outerw) {
+		move(rtl() ? x : (outerw - x - width()), y);
 	}
 
 };
 
+namespace App {
+	const QPixmap &sprite();
+}
+
 class Painter : public QPainter {
 public:
 	explicit Painter(QPaintDevice *device) : QPainter(device) {
 	}
 
-	void drawTextLeft(int x, int y, int w, const QString &text, int textWidth = -1) {
+	void drawTextLeft(int x, int y, int outerw, const QString &text, int textWidth = -1) {
 		QFontMetrics m(fontMetrics());
 		if (rtl() && textWidth < 0) textWidth = m.width(text);
-		drawText(x + (rtl() ? (w - textWidth) : 0), y + m.ascent(), text);
+		drawText(rtl() ? (outerw - x - textWidth) : x, y + m.ascent(), text);
 	}
-	void drawTextRight(int x, int y, int w, const QString &text, int textWidth = -1) {
+	void drawTextRight(int x, int y, int outerw, const QString &text, int textWidth = -1) {
 		QFontMetrics m(fontMetrics());
 		if (!rtl() && textWidth < 0) textWidth = m.width(text);
-		drawText(x + (rtl() ? 0 : (w - textWidth)), y + m.ascent(), text);
+		drawText(rtl() ? x : (outerw - x - textWidth), y + m.ascent(), text);
+	}
+	void drawPixmapLeft(int x, int y, int outerw, const QPixmap &pix, const QRect &from) {
+		drawPixmap(QPoint(rtl() ? (outerw - x - (from.width() / pix.devicePixelRatio())) : x, y), pix, from);
+	}
+	void drawPixmapRight(int x, int y, int outerw, const QPixmap &pix, const QRect &from) {
+		drawPixmap(QPoint(rtl() ? x : (outerw - x - (from.width() / pix.devicePixelRatio())), y), pix, from);
+	}
+	void drawSpriteLeft(int x, int y, int outerw, const QRect &sprite) {
+		return drawPixmapLeft(x, y, outerw, App::sprite(), sprite);
+	}
+	void drawSpriteRight(int x, int y, int outerw, const QRect &sprite) {
+		return drawPixmapRight(x, y, outerw, App::sprite(), sprite);
 	}
 };
 
@@ -80,10 +100,12 @@ protected:
 	void enterEvent(QEvent *e) {
 		TWidget *p(tparent());
 		if (p) p->leaveToChildEvent(e);
+		return Widget::enterEvent(e);
 	}
 	void leaveEvent(QEvent *e) {
 		TWidget *p(tparent());
 		if (p) p->enterFromChildEvent(e);
+		return Widget::leaveEvent(e);
 	}
 
 private:
diff --git a/Telegram/SourceFiles/history.cpp b/Telegram/SourceFiles/history.cpp
index 0f24e7460..073a8a2de 100644
--- a/Telegram/SourceFiles/history.cpp
+++ b/Telegram/SourceFiles/history.cpp
@@ -3257,17 +3257,19 @@ void HistoryWebPage::initDimensions(const HistoryItem *parent) {
 		}
 	}
 	if (!data->description.isEmpty()) {
+		QString text = textClean(data->description);
+		if (!_asArticle) text += textcmdSkipBlock(parent->timeWidth(), st::msgDateFont->height - st::msgDateDelta.y());
+		const TextParseOptions *opts = &_webpageDescriptionOptions;
 		if (data->siteName == QLatin1String("Twitter")) {
-			_description.setText(st::webPageDescriptionFont, textClean(data->description), _twitterDescriptionOptions);
+			opts = &_twitterDescriptionOptions;
 		} else if (data->siteName == QLatin1String("Instagram")) {
-			_description.setText(st::webPageDescriptionFont, textClean(data->description), _instagramDescriptionOptions);
-		} else {
-			_description.setText(st::webPageDescriptionFont, textClean(data->description), _webpageDescriptionOptions);
+			opts = &_instagramDescriptionOptions;
 		}
+		_description.setText(st::webPageDescriptionFont, text, *opts);
 		if (_asArticle) {
 			_maxw = qMax(_maxw, int32(st::webPageLeft + _description.maxWidth() + st::webPagePhotoDelta + st::webPagePhotoSize));
 		} else {
-			_maxw = qMax(_maxw, int32(st::webPageLeft + _description.maxWidth() + parent->timeWidth()));
+			_maxw = qMax(_maxw, int32(st::webPageLeft + _description.maxWidth()));
 			_minh += qMin(_description.minHeight(), 3 * st::webPageTitleFont->height);
 		}
 	}
@@ -4443,7 +4445,7 @@ HistoryMedia *HistoryMessage::getMedia(bool inOverview) const {
 }
 
 void HistoryMessage::setMedia(const MTPmessageMedia &media) {
-	if (!_media && media.type() == mtpc_messageMediaEmpty) return;
+	if ((!_media || _media->isImageLink()) && media.type() == mtpc_messageMediaEmpty) return;
 	if (_media) {
 		delete _media;
 		_media = 0;
diff --git a/Telegram/SourceFiles/history.h b/Telegram/SourceFiles/history.h
index 642a53c4b..7d9384fa5 100644
--- a/Telegram/SourceFiles/history.h
+++ b/Telegram/SourceFiles/history.h
@@ -802,6 +802,10 @@ public:
 	virtual void updateFrom(const MTPMessageMedia &media) {
 	}
 
+	virtual bool isImageLink() const {
+		return false;
+	}
+
 	virtual bool updateStickerEmoji() {
 		return false;
 	}
@@ -1167,6 +1171,10 @@ public:
 	void getState(TextLinkPtr &lnk, bool &inText, int32 x, int32 y, const HistoryItem *parent, int32 width = -1) const;
 	HistoryMedia *clone() const;
 
+	bool isImageLink() const {
+		return true;
+	}
+
 private:
 	ImageLinkData *data;
 	TextLinkPtr link;
diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp
index f36cec797..2d20efcf2 100644
--- a/Telegram/SourceFiles/mainwidget.cpp
+++ b/Telegram/SourceFiles/mainwidget.cpp
@@ -1402,7 +1402,7 @@ void MainWidget::documentLoadProgress(mtpFileLoader *loader) {
 						if (reader.supportsAnimation() && reader.imageCount() > 1 && item) {
 							startGif(item, already);
 						} else {
-							App::wnd()->showDocument(document, QPixmap::fromImage(App::readImage(already, 0, false), Qt::ColorOnly), item);
+							App::wnd()->showDocument(document, item);
 						}
 					} else {
 						psOpenFile(already);
diff --git a/Telegram/SourceFiles/mediaview.cpp b/Telegram/SourceFiles/mediaview.cpp
index 0b554a8cf..6972183a7 100644
--- a/Telegram/SourceFiles/mediaview.cpp
+++ b/Telegram/SourceFiles/mediaview.cpp
@@ -44,16 +44,17 @@ namespace {
 }
 
 MediaView::MediaView() : TWidget(App::wnd()),
-_photo(0), _doc(0), _availBottom(0), _leftNavVisible(false), _rightNavVisible(false), _animStarted(getms()),
-_maxWidth(0), _maxHeight(0), _width(0), _x(0), _y(0), _w(0), _h(0), _xStart(0), _yStart(0),
-_zoom(0), _zoomToScreen(0), _pressed(false), _dragging(0), _full(-1), _history(0), _peer(0), _user(0), _from(0), _index(-1), _msgid(0),
-_loadRequest(0), _over(OverNone), _down(OverNone), _lastAction(-st::medviewDeltaFromLastAction, -st::medviewDeltaFromLastAction),
-_close(this, st::medviewClose),
-_save(this, st::medviewSaveAs, lang(lng_mediaview_save)),
-_forward(this, st::medviewForward, lang(lng_mediaview_forward)),
-_delete(this, st::medviewDelete, lang(lng_mediaview_delete)),
-_overview(this, st::medviewOverview, lang(lng_mediaview_single_photo)),
-_menu(0), _receiveMouse(true), _touchPress(false), _touchMove(false), _touchRightButton(false),
+_photo(0), _doc(0), _overview(OverviewCount),
+_leftNavVisible(false), _rightNavVisible(false), _saveVisible(false), _headerHasLink(false), _animStarted(getms()),
+_width(0), _x(0), _y(0), _w(0), _h(0), _xStart(0), _yStart(0),
+_zoom(0), _zoomToScreen(0), _pressed(false), _dragging(0), _full(-1),
+_docNameWidth(0), _docSizeWidth(0),
+_docThumbx(0), _docThumby(0), _docThumbw(0),
+_docRadialFirst(0), _docRadialStart(0), _docRadialLast(0), a_docRadialStart(0, 1),
+_history(0), _peer(0), _user(0), _from(0), _index(-1), _msgid(0),
+_loadRequest(0), _over(OverNone), _down(OverNone), _lastAction(-st::mvDeltaFromLastAction, -st::mvDeltaFromLastAction), _ignoringDropdown(false),
+_controlsState(ControlsShown), _controlsAnimStarted(0),
+_dropdown(this, st::mvDropdown), _menu(0), _receiveMouse(true), _touchPress(false), _touchMove(false), _touchRightButton(false),
 _saveMsgStarted(0), _saveMsgOpacity(0)
 {
 	TextCustomTagsMap custom;
@@ -62,7 +63,9 @@ _saveMsgStarted(0), _saveMsgOpacity(0)
 	_saveMsg = QRect(0, 0, _saveMsgText.maxWidth() + st::medviewSaveMsgPadding.left() + st::medviewSaveMsgPadding.right(), st::medviewSaveMsgFont->height + st::medviewSaveMsgPadding.top() + st::medviewSaveMsgPadding.bottom());
 	_saveMsgText.setLink(1, TextLinkPtr(new SaveMsgLink(this)));
 
-	_transparentBrush = QBrush(App::sprite().copy(st::medviewTransparentBrush));
+	_transparentBrush = QBrush(App::sprite().copy(st::mvTransparentBrush));
+	_docRadialPen = QPen(st::white->p);
+	_docRadialPen.setWidth(st::radialLine);
 
 	setWindowFlags(Qt::FramelessWindowHint | Qt::BypassWindowManagerHint | Qt::Tool | Qt::NoDropShadowWindowHint);
 	moveToScreen();
@@ -73,12 +76,6 @@ _saveMsgStarted(0), _saveMsgOpacity(0)
 	hide();
 	createWinId();
 	
-	connect(&_close, SIGNAL(clicked()), this, SLOT(onClose()));
-	connect(&_save, SIGNAL(clicked()), this, SLOT(onDownload()));
-	connect(&_forward, SIGNAL(clicked()), this, SLOT(onForward()));
-	connect(&_delete, SIGNAL(clicked()), this, SLOT(onDelete()));
-	connect(&_overview, SIGNAL(clicked()), this, SLOT(onOverview()));
-
 	_saveMsgUpdater.setSingleShot(true);
 	connect(&_saveMsgUpdater, SIGNAL(timeout()), this, SLOT(updateImage()));
 
@@ -87,45 +84,59 @@ _saveMsgStarted(0), _saveMsgOpacity(0)
 	setAttribute(Qt::WA_AcceptTouchEvents);
 	_touchTimer.setSingleShot(true);
 	connect(&_touchTimer, SIGNAL(timeout()), this, SLOT(onTouchTimer()));
+
+	_btns.push_back(_btnToMessage = _dropdown.addButton(new IconedButton(this, st::mvButton, lang(lng_context_to_msg))));
+	connect(_btnToMessage, SIGNAL(clicked()), this, SLOT(onToMessage()));
+	_btns.push_back(_btnShowInFolder = _dropdown.addButton(new IconedButton(this, st::mvButton, lang(cPlatform() == dbipMac ? lng_context_show_in_finder : lng_context_show_in_folder))));
+	connect(_btnShowInFolder, SIGNAL(clicked()), this, SLOT(onShowInFolder()));
+	_btns.push_back(_btnCopy = _dropdown.addButton(new IconedButton(this, st::mvButton, lang(lng_mediaview_copy))));
+	connect(_btnCopy, SIGNAL(clicked()), this, SLOT(onCopy()));
+	_btns.push_back(_btnForward = _dropdown.addButton(new IconedButton(this, st::mvButton, lang(lng_mediaview_forward))));
+	connect(_btnForward, SIGNAL(clicked()), this, SLOT(onForward()));
+	_btns.push_back(_btnDelete = _dropdown.addButton(new IconedButton(this, st::mvButton, lang(lng_mediaview_delete))));
+	connect(_btnDelete, SIGNAL(clicked()), this, SLOT(onDelete()));
+	_btns.push_back(_btnSaveAs = _dropdown.addButton(new IconedButton(this, st::mvButton, lang(lng_mediaview_save_as))));
+	connect(_btnSaveAs, SIGNAL(clicked()), this, SLOT(onSave()));
+	_btns.push_back(_btnViewAll = _dropdown.addButton(new IconedButton(this, st::mvButton, lang(lng_mediaview_photos_all))));
+	connect(_btnViewAll, SIGNAL(clicked()), this, SLOT(onOverview()));
+
+	_dropdown.hide();
+	connect(&_dropdown, SIGNAL(hiding()), this, SLOT(onDropdownHiding()));
+
+	_controlsHideTimer.setSingleShot(true);
+	connect(&_controlsHideTimer, SIGNAL(timeout()), this, SLOT(onHideControls()));
 }
 
 void MediaView::moveToScreen() {
 	QPoint wndCenter(App::wnd()->x() + App::wnd()->width() / 2, App::wnd()->y() + App::wnd()->height() / 2);
-	_avail = App::app() ? App::app()->desktop()->screenGeometry(wndCenter) : QDesktopWidget().screenGeometry(wndCenter);
-	if (_avail != geometry()) {
-		setGeometry(_avail);
+	QRect avail = App::app() ? App::app()->desktop()->screenGeometry(wndCenter) : QDesktopWidget().screenGeometry(wndCenter);
+	if (avail != geometry()) {
+		setGeometry(avail);
 	}
-	_avail.moveTo(0, 0);
-	_availBottom = _avail.height() - st::medviewBottomBar;
-	_maxWidth = _avail.width() - 2 * st::medviewNavBarWidth - st::medviewPolaroid.left() - st::medviewPolaroid.right();
-	_maxHeight = _avail.height() - st::medviewBottomBar - st::medviewPolaroid.top() - st::medviewPolaroid.bottom();
-	_leftNav = QRect(0, 0, st::medviewNavBarWidth, _availBottom);
-	_rightNav = QRect(width() - st::medviewNavBarWidth, 0, st::medviewNavBarWidth + (cRetina() ? 1 : 0), _availBottom);
+	
+	int32 navSkip = 2 * st::mvControlMargin + st::mvControlSize;
+	_closeNav = rtlrect(width() - st::mvControlMargin - st::mvControlSize, st::mvControlMargin, st::mvControlSize, st::mvControlSize, width());
+	_leftNav = rtlrect(st::mvControlMargin, navSkip, st::mvControlSize, height() - 2 * navSkip, width());
+	_rightNav = rtlrect(width() - st::mvControlMargin - st::mvControlSize, navSkip, st::mvControlSize, height() - 2 * navSkip, width());
 
-	_bottomBar = QRect(0, _availBottom, width(), height() - _availBottom);
-
-	_close.move(width() - ((_close.width() + st::medviewNavBarWidth) / 2), (st::medviewNavBarWidth - _close.width()) / 2);
-	_save.move(width() - _save.width() - ((st::medviewBottomBar - _save.height()) / 2), _availBottom + ((st::medviewBottomBar - _save.height()) / 2));
-	_forward.move(_save.x() - _forward.width() - ((st::medviewBottomBar - _forward.height()) / 2), _availBottom + ((st::medviewBottomBar - _forward.height()) / 2));
-	_delete.move(_forward.isHidden() ? _save.x() : _forward.x() - _delete.width() - ((st::medviewBottomBar - _delete.height()) / 2), _availBottom + ((st::medviewBottomBar - _delete.height()) / 2));
-	_overview.move(((st::medviewBottomBar - _overview.height()) / 2), _availBottom + ((st::medviewBottomBar - _overview.height()) / 2));
-
-	_saveMsg.moveTo((width() - _saveMsg.width()) / 2, (_availBottom - st::medviewPolaroid.bottom() - _saveMsg.height() + st::medviewPolaroid.top()) / 2);
+	_saveMsg.moveTo((width() - _saveMsg.width()) / 2, (height() - _saveMsg.height()) / 2);
 }
 
 void MediaView::mediaOverviewUpdated(PeerData *peer) {
-	if (!_photo) return;
+	if (!_photo && !_doc) return;
 	if (_history && _history->peer == peer) {
 		_index = -1;
-		for (int i = 0, l = _history->_overview[OverviewPhotos].size(); i < l; ++i) {
-			if (_history->_overview[OverviewPhotos].at(i) == _msgid) {
+		for (int i = 0, l = _history->_overview[_overview].size(); i < l; ++i) {
+			if (_history->_overview[_overview].at(i) == _msgid) {
 				_index = i;
 				break;
 			}
 		}
 		updateControls();
-		preloadPhotos(0);
+		preloadData(0);
 	} else if (_user == peer) {
+		if (!_photo) return;
+
 		_index = -1;
 		for (int i = 0, l = _user->photos.size(); i < l; ++i) {
 			if (_user->photos.at(i) == _photo) {
@@ -134,7 +145,7 @@ void MediaView::mediaOverviewUpdated(PeerData *peer) {
 			}
 		}
 		updateControls();
-		preloadPhotos(0);
+		preloadData(0);
 	}
 }
 
@@ -148,31 +159,10 @@ void MediaView::changingMsgId(HistoryItem *row, MsgId newId) {
 void MediaView::updateControls() {
 	if (!_photo && !_doc) return;
 
-	_close.show();
-	if ((_photo && _photo->full->loaded()) || (_doc && !_doc->already(true).isEmpty())) {
-		_save.show();
-	} else {
-		_save.hide();
-	}
-	if (_history) {
-		HistoryItem *item = App::histItemById(_msgid);
-		if (dynamic_cast<HistoryMessage*>(item)) {
-			_forward.show();
-			_delete.move(_forward.x() - _delete.width() - ((st::medviewBottomBar - _delete.height()) / 2), _availBottom + ((st::medviewBottomBar - _delete.height()) / 2));
-		} else {
-			_forward.hide();
-			_delete.move(_save.x() - _delete.width() - ((st::medviewBottomBar - _delete.height()) / 2), _availBottom + ((st::medviewBottomBar - _delete.height()) / 2));
-		}
-		_delete.show();
-	} else {
-		_forward.hide();
-		if (_photo && ((App::self() && App::self()->photoId == _photo->id) || (_photo->chat && _photo->chat->photoId == _photo->id))) {
-			_delete.show();
-			_delete.move(_save.x() - _delete.width() - ((st::medviewBottomBar - _delete.height()) / 2), _availBottom + ((st::medviewBottomBar - _delete.height()) / 2));
-		} else {
-			_delete.hide();
-		}
-	}
+	_saveVisible = ((_photo && _photo->full->loaded()) || (_doc && !_doc->already(true).isEmpty()));
+	_saveNav = rtlrect(width() - st::mvIconSize.width() * 2, height() - st::mvIconSize.height(), st::mvIconSize.width(), st::mvIconSize.height(), width());
+	_moreNav = rtlrect(width() - st::mvIconSize.width(), height() - st::mvIconSize.height(), st::mvIconSize.width(), st::mvIconSize.height(), width());
+
 	QDateTime d(date(_photo ? _photo->date : _doc->date)), dNow(date(unixtime()));
 	if (d.date() == dNow.date()) {
 		_dateText = lng_mediaview_today(lt_time, d.time().toString(cTimeFormat()));
@@ -181,18 +171,45 @@ void MediaView::updateControls() {
 	} else {
 		_dateText = lng_mediaview_date_time(lt_date, d.date().toString(qsl("dd.MM.yy")), lt_time, d.time().toString(cTimeFormat()));
 	}
-	if (_from) _fromName.setText(st::medviewNameFont, _from->name);
+	if (_from) {
+		_fromName.setText(st::mvFont, _from->name);
+		_nameNav = rtlrect(st::mvTextLeft, height() - st::mvTextTop, qMin(_fromName.maxWidth(), width() / 3), st::mvFont->height, width());
+		_dateNav = rtlrect(st::mvTextLeft + _nameNav.width() + st::mvTextSkip, height() - st::mvTextTop, st::mvFont->m.width(_dateText), st::mvFont->height, width());
+	} else {
+		_nameNav = QRect();
+		_dateNav = rtlrect(st::mvTextLeft, height() - st::mvTextTop, st::mvFont->m.width(_dateText), st::mvFont->height, width());
+	}
 	updateHeader();
-	_leftNavVisible = _photo && (_index > 0 || (_index == 0 && _history && _history->_overview[OverviewPhotos].size() < _history->_overviewCount[OverviewPhotos]));
-	_rightNavVisible = _photo && (_index >= 0 && (
-		(_history && _index + 1 < _history->_overview[OverviewPhotos].size()) ||
-		(_user && (_index + 1 < _user->photos.size() || _index + 1 < _user->photosCount))));
+	if (_photo) {
+		_leftNavVisible = (_index > 0) || (_index == 0 && _history && _history->_overview[_overview].size() < _history->_overviewCount[_overview]);
+		_rightNavVisible = (_index >= 0) && (
+			(_history && _index + 1 < _history->_overview[_overview].size()) ||
+			(_user && (_index + 1 < _user->photos.size() || _index + 1 < _user->photosCount)));
+	} else if (_doc) {
+		_leftNavVisible = (_index > 0) || (_index == 0 && _history && _history->_overview[_overview].size() < _history->_overviewCount[_overview]);
+		_rightNavVisible = (_index >= 0) && _history && (_index + 1 < _history->_overview[_overview].size());
+	} else {
+		_leftNavVisible = _rightNavVisible = false;
+	}
 	updateOver(mapFromGlobal(QCursor::pos()));
-	updatePolaroid();
 	update();
 }
 
+void MediaView::updateDropdown() {
+	_btnToMessage->setVisible(_msgid > 0);
+	_btnShowInFolder->setVisible(_doc && !_doc->already(true).isEmpty());
+	_btnSaveAs->setVisible(true);
+	_btnCopy->setVisible((_doc && !_current.isNull()) || (_photo && _photo->full->loaded()));
+	_btnForward->setVisible(_msgid > 0);
+	_btnDelete->setVisible(_msgid > 0 || (App::self() && App::self()->photoId == _photo->id) || (_photo->chat && _photo->chat->photoId == _photo->id));
+	_btnViewAll->setVisible((_overview != OverviewCount) && _history);
+	_btnViewAll->setText(lang(_doc ? lng_mediaview_files_all : lng_mediaview_photos_all));
+	_dropdown.updateButtons();
+	_dropdown.moveToRight(0, height() - _dropdown.height(), width());
+}
+
 bool MediaView::animStep(float64 msp) {
+	bool result = false;
 	uint64 ms = getms();
 	for (Showing::iterator i = _animations.begin(); i != _animations.end();) {
 		int64 start = i.value();
@@ -201,9 +218,13 @@ bool MediaView::animStep(float64 msp) {
 		case OverRightNav: update(_rightNav); break;
 		case OverName: update(_nameNav); break;
 		case OverDate: update(_dateNav); break;
+		case OverHeader: update(_headerNav); break;
+		case OverClose: update(_closeNav); break;
+		case OverSave: update(_saveNav); break;
+		case OverMore: update(_moreNav); break;
 		default: break;
 		}
-		float64 dt = float64(ms - start) / st::medviewOverview.duration;
+		float64 dt = float64(ms - start) / st::mvFadeDuration;
 		if (dt >= 1) {
 			_animOpacities.remove(i.key());
 			i = _animations.erase(i);
@@ -212,7 +233,43 @@ bool MediaView::animStep(float64 msp) {
 			++i;
 		}
 	}
-	return !_animations.isEmpty();
+	if (_controlsState == ControlsShowing || _controlsState == ControlsHiding) {
+		float64 dt = float64(ms - _controlsAnimStarted) / (_controlsState == ControlsShowing ? st::mvShowDuration : st::mvHideDuration);
+		if (dt >= 1) {
+			a_cOpacity.finish();
+			_controlsState = (_controlsState == ControlsShowing ? ControlsShown : ControlsHidden);
+			setCursor(_controlsState == ControlsHidden ? Qt::BlankCursor : (_over == OverNone ? style::cur_default : style::cur_pointer));
+		} else {
+			a_cOpacity.update(dt, anim::linear);
+		}
+		update();
+		if (dt < 1) result = true;
+	}
+	if (_doc && _docRadialStart > 0) {
+		float64 prg = _doc->loader ? _doc->loader->currentProgress() : (_doc->status == FileFailed ? 0 : 1);
+		if (prg != a_docRadial.to()) {
+			a_docRadial.start(prg);
+			_docRadialStart = _docRadialLast;
+		}
+		_docRadialLast = ms;
+
+		float64 dt = float64(ms - _docRadialStart);
+		if (_doc->loader) {
+			a_docRadial.update(1. - (st::radialDuration / (st::radialDuration + dt)), anim::linear);
+			result = true;
+		} else if (dt >= st::radialDuration) {
+			a_docRadial.update(1, anim::linear);
+			result = true;
+//			_docRadialStart = 0;
+		} else {
+			a_docRadial.update(dt / st::radialDuration, anim::linear);
+			result = true;
+		}
+		float64 fromstart = float64(ms - _docRadialFirst) / st::radialPeriod;
+		a_docRadialStart.update(fromstart - qFloor(fromstart), anim::linear);
+		update(_docIcon);
+	}
+	return result || !_animations.isEmpty();
 }
 
 MediaView::~MediaView() {
@@ -223,16 +280,60 @@ void MediaView::showSaveMsgFile() {
 	psShowInFolder(_saveMsgFilename);
 }
 
-void MediaView::onClose() {
+void MediaView::close() {
 	if (App::wnd()) App::wnd()->layerHidden();
 }
 
+void MediaView::activateControls() {
+	LOG(("ACTIVATING CONTROLS!!"));
+	_controlsHideTimer.start(int(st::mvWaitHide));
+	if (_controlsState == ControlsHiding || _controlsState == ControlsHidden) {
+		_controlsState = ControlsShowing;
+		_controlsAnimStarted = getms();
+		a_cOpacity.start(1);
+		anim::start(this);
+	}
+}
+
+void MediaView::onHideControls(bool force) {
+	if (!force && !_dropdown.isHidden()) return;
+	if (_controlsState == ControlsHiding || _controlsState == ControlsHidden) return;
+	_controlsState = ControlsHiding;
+	_controlsAnimStarted = getms();
+	a_cOpacity.start(0);
+	anim::start(this);
+}
+
+void MediaView::onDropdownHiding() {
+	setFocus();
+	LOG(("DROPDOWN HIDDEN"));
+	_ignoringDropdown = true;
+	_lastMouseMovePos = mapFromGlobal(QCursor::pos());
+	updateOver(_lastMouseMovePos);
+	_ignoringDropdown = false;
+	if (!_controlsHideTimer.isActive()) {
+		LOG((", STARTING CONTROLS HIDE"));
+		onHideControls(true);
+	}
+}
+
+void MediaView::onToMessage() {
+	if (_menu) _menu->fastHide();
+	if (HistoryItem *item = _msgid ? App::histItemById(_msgid) : 0) {
+		if (App::wnd()) {
+			close();
+			if (App::main()) App::main()->showPeer(item->history()->peer->id, _msgid, false, true);
+		}
+	}
+}
+
 void MediaView::onSave() {
 	QString file;
 	if (_doc) {
 		QString cur = _doc->already(true);
 		if (cur.isEmpty()) {
-			_save.hide();
+			_saveVisible = false;
+			update(_saveNav);
 			return;
 		}
 
@@ -275,7 +376,8 @@ void MediaView::onDownload() {
 	if (_doc) {
 		QString cur = _doc->already(true);
 		if (cur.isEmpty()) {
-			_save.hide();
+			_saveVisible = false;
+			update(_saveNav);
 		} else {
 			if (!QDir().exists(path)) QDir().mkpath(path);
 			toName = filedialogNextFilename(_doc->name, cur, path);
@@ -285,7 +387,8 @@ void MediaView::onDownload() {
 		}
 	} else {
 		if (!_photo || !_photo->full->loaded()) {
-			_save.hide();
+			_saveVisible = false;
+			update(_saveNav);
 		} else {
 			if (!QDir().exists(path)) QDir().mkpath(path);
 			toName = filedialogDefaultName(qsl("photo"), qsl(".jpg"), path);
@@ -303,6 +406,7 @@ void MediaView::onDownload() {
 }
 
 void MediaView::onShowInFolder() {
+	if (!_doc) return;
 	QString already(_doc->already(true));
 	if (!already.isEmpty()) psShowInFolder(already);
 }
@@ -312,7 +416,7 @@ void MediaView::onForward() {
 	if (!_msgid || !item) return;
 
 	if (App::wnd()) {
-		onClose();
+		close();
 		if (App::main()) {
 			App::contextItem(item);
 			App::main()->forwardLayer();
@@ -321,7 +425,7 @@ void MediaView::onForward() {
 }
 
 void MediaView::onDelete() {
-	onClose();
+	close();
 	if (!_msgid) {
 		if (App::self() && _photo && App::self()->photoId == _photo->id) {
 			App::app()->peerClearPhoto(App::self()->id);
@@ -338,11 +442,20 @@ void MediaView::onDelete() {
 }
 
 void MediaView::onOverview() {
-	onClose();
-	if (_history->peer) App::main()->showMediaOverview(_history->peer, OverviewPhotos);
+	if (_menu) _menu->fastHide();
+	if (!_history || _overview == OverviewCount) {
+		update();
+		return;
+	}
+	close();
+	if (_history->peer) App::main()->showMediaOverview(_history->peer, _overview);
 }
 
 void MediaView::onCopy() {
+	if (!_dropdown.isHidden()) {
+		_dropdown.ignoreShow();
+		_dropdown.hideStart();
+	}
 	if (_doc) {
 		QApplication::clipboard()->setPixmap(_current);
 	} else {
@@ -367,26 +480,18 @@ void MediaView::showPhoto(PhotoData *photo, HistoryItem *context) {
 		anim::stop(this);
 	}
 	if (!_animOpacities.isEmpty()) _animOpacities.clear();
-	setCursor(style::cur_default);
 
 	_index = -1;
 	_msgid = context ? context->id : 0;
 	_photo = photo;
 	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();
-		}
+		_overview = OverviewPhotos;
+		findCurrent();
 	}
 
-	showPhoto(photo);
-	preloadPhotos(0);
+	displayPhoto(photo);
+	preloadData(0);
+	activateControls();
 }
 
 void MediaView::showPhoto(PhotoData *photo, PeerData *context) {
@@ -406,6 +511,7 @@ void MediaView::showPhoto(PhotoData *photo, PeerData *context) {
 	_msgid = 0;
 	_index = -1;
 	_photo = photo;
+	_overview = OverviewCount;
 	if (_user) {
 		if (_user->photos.isEmpty() && _user->photosCount < 0 && _user->photoId) {
 			_index = 0;
@@ -418,23 +524,22 @@ void MediaView::showPhoto(PhotoData *photo, PeerData *context) {
 		}
 
 		if (_user->photosCount < 0) {
-			loadPhotosBack();
+			loadBack();
 		}
 	}
-	showPhoto(photo);
-	preloadPhotos(0);
+	displayPhoto(photo);
+	preloadData(0);
+	activateControls();
 }
 
-void MediaView::showDocument(DocumentData *doc, QPixmap pix, HistoryItem *context) {
+void MediaView::showDocument(DocumentData *doc, HistoryItem *context) {
 	_photo = 0;
 	_history = context ? context->history() : 0;
 	_saveMsgStarted = 0;
 	_peer = 0;
 	_user = 0;
-	_msgid = context ? context->id : 0;
-	_index = -1;
 	_loadRequest = 0;
-	_over = OverNone;
+	_down = OverNone;
 	_pressed = false;
 	_dragging = 0;
 	setCursor(style::cur_default);
@@ -444,58 +549,32 @@ void MediaView::showDocument(DocumentData *doc, QPixmap pix, HistoryItem *contex
 	}
 	if (!_animOpacities.isEmpty()) _animOpacities.clear();
 
-	_current = pix;
-	_current.setDevicePixelRatio(cRetinaFactor());
-	_doc = doc;
-	_down = OverNone;
-	if (isHidden()) {
-		moveToScreen();
-	}
-	_w = _current.width() / cIntRetinaFactor();
-	_h = _current.height() / cIntRetinaFactor();
-	_width = _w;
-	if (_w > 0 && _h > 0) {
-		_zoomToScreen = float64(_avail.width()) / _w;
-		if (_h * _zoomToScreen > (_avail.height() - st::medviewBottomBar)) {
-			_zoomToScreen = float64(_avail.height() - st::medviewBottomBar) / _h;
+	_index = -1;
+	_msgid = context ? context->id : 0;
+	if (_history) {
+		_overview = OverviewDocuments;
+
+		for (int i = 0, l = _history->_overview[_overview].size(); i < l; ++i) {
+			if (_history->_overview[_overview].at(i) == _msgid) {
+				_index = i;
+				break;
+			}
 		}
-		if (_zoomToScreen >= 1.) {
-			_zoomToScreen -= 1.;
-		} else {
-			_zoomToScreen = 1. - (1. / _zoomToScreen);
+
+		if (_history->_overviewCount[_overview] < 0) {
+			loadBack();
 		}
-	} else {
-		_zoomToScreen = 0;
-	}
-	if ((_w > _avail.width()) || (_h > (_avail.height() - st::medviewBottomBar))) {
-		_zoom = ZoomToScreenLevel;
-		if (_zoomToScreen >= 0) {
-			_w = qRound(_w * (_zoomToScreen + 1));
-			_h = qRound(_h * (_zoomToScreen + 1));
-		} else {
-			_w = qRound(_w / (-_zoomToScreen + 1));
-			_h = qRound(_h / (-_zoomToScreen + 1));
-		}
-		snapXY();
-	} else {
-		_zoom = 0;
-	}
-	_x = (_avail.width() - _w) / 2;
-	_y = (_avail.height() - st::medviewBottomBar - _h) / 2;
-	_from = context ? context->from()->asUser() : 0;
-	_full = 1;
-	updateControls();
-	if (isHidden()) {
-		psUpdateOverlayed(this);
-		show();
-		psShowOverAll(this);
 	}
+	displayDocument(doc, context);
+	preloadData(0);
+	activateControls();
 }
 
-void MediaView::showPhoto(PhotoData *photo) {
+void MediaView::displayPhoto(PhotoData *photo) {
 	_photo = photo;
 	_doc = 0;
 	_zoom = 0;
+
 	_zoomToScreen = 0;
 	MTP::clearLoaderPriorities();
 	_full = -1;
@@ -506,16 +585,16 @@ void MediaView::showPhoto(PhotoData *photo) {
 	if (isHidden()) {
 		moveToScreen();
 	}
-	if (_w > _maxWidth) {
-		_h = qRound(_h * _maxWidth / float64(_w));
-		_w = _maxWidth;
+	if (_w > width()) {
+		_h = qRound(_h * width() / float64(_w));
+		_w = width();
 	}
-	if (_h > _maxHeight) {
-		_w = qRound(_w * _maxHeight / float64(_h));
-		_h = _maxHeight;
+	if (_h > height()) {
+		_w = qRound(_w * height() / float64(_h));
+		_h = height();
 	}
-	_x = (_avail.width() - _w) / 2;
-	_y = st::medviewPolaroid.top() + (_avail.height() - st::medviewPolaroid.top() - st::medviewPolaroid.bottom() - st::medviewBottomBar - _h) / 2;
+	_x = (width() - _w) / 2;
+	_y = (height() - _h) / 2;
 	_width = _w;
 	if (_photo->user == WebPageUserId && _msgid) {
 		if (HistoryItem *item = App::histItemById(_msgid)) {
@@ -539,39 +618,144 @@ void MediaView::showPhoto(PhotoData *photo) {
 	}
 }
 
-void MediaView::paintEvent(QPaintEvent *e) {
-	QPainter p(this);
-	QRect r(e->rect());
+void MediaView::displayDocument(DocumentData *doc, HistoryItem *item) {
+	_doc = doc;
 
-	QPainter::CompositionMode m = p.compositionMode();
-	p.setCompositionMode(QPainter::CompositionMode_Source);
+	_docRadialFirst = _docRadialLast = _docRadialStart = _doc->loader ? getms() : 0;
+
+	QString already = _doc->already(true);
+	QPixmap pix = (_doc->sticker->isNull() || !_doc->sticker->loaded()) ? (already.isEmpty() ? QPixmap() : QPixmap::fromImage(App::readImage(already, 0, false), Qt::ColorOnly)) : _doc->sticker->pix();
+	_current = pix;
+	if (_current.isNull()) {
+		if (_doc->thumb->isNull()) {
+			style::sprite thumbs[] = { st::mvDocBlue, st::mvDocGreen, st::mvDocRed, st::mvDocYellow };
+			QString name = _doc->name.toLower(), mime = _doc->mime.toLower();
+			if (name.endsWith(QLatin1String(".doc")) ||
+				name.endsWith(QLatin1String(".txt")) ||
+				name.endsWith(QLatin1String(".psd")) ||
+				mime.startsWith(QLatin1String("text/"))
+			) {
+				_docIcon = thumbs[0];
+			} else if (
+				name.endsWith(QLatin1String(".xls")) ||
+				name.endsWith(QLatin1String(".csv"))
+			) {
+				_docIcon = thumbs[1];
+			} else if (
+				name.endsWith(QLatin1String(".pdf")) ||
+				name.endsWith(QLatin1String(".ppt")) ||
+				name.endsWith(QLatin1String(".key"))
+			) {
+				_docIcon = thumbs[2];
+			} else if (
+				name.endsWith(QLatin1String(".zip")) ||
+				name.endsWith(QLatin1String(".rar")) ||
+				name.endsWith(QLatin1String(".ai")) ||
+				name.endsWith(QLatin1String(".mp3")) ||
+				name.endsWith(QLatin1String(".mov")) ||
+				name.endsWith(QLatin1String(".avi"))
+			) {
+				_docIcon = thumbs[3];
+			} else {
+				int ext = name.lastIndexOf('.');
+				QChar ch = (ext >= 0 && ext + 1 < name.size()) ? name.at(ext + 1) : (name.isEmpty() ? (mime.isEmpty() ? '0' : mime.at(0)) : name.at(0));
+				_docIcon = thumbs[ch.unicode() % 4];
+			}
+		} else {
+			_doc->thumb->load();
+			int32 tw = _doc->thumb->width(), th = _doc->thumb->height();
+			if (!tw || !th) {
+				_docThumbx = _docThumby = _docThumbw = 0;
+			} else if (tw > th) {
+				_docThumbw = (tw * st::mvDocBlue.pxHeight()) / th;
+				_docThumbx = (_docThumbw - st::mvDocBlue.pxWidth()) / 2;
+				_docThumby = 0;
+			} else {
+				_docThumbw = st::mvDocBlue.pxWidth();
+				_docThumbx = 0;
+				_docThumby = ((th * _docThumbw) / tw - st::mvDocBlue.pxHeight()) / 2;
+			}
+		}
+
+		int32 maxw = st::mvDocSize.width() - st::mvDocBlue.pxWidth() - st::mvDocPadding * 3;
+
+		_docName = _doc->name.isEmpty() ? lang(_doc->type == StickerDocument ? lng_in_dlg_sticker : lng_mediaview_doc_image) : _doc->name;
+		_docNameWidth = st::mvThickFont->m.width(_docName);
+		if (_docNameWidth > maxw) {
+			_docName = st::mvThickFont->m.elidedText(_docName, Qt::ElideRight, maxw);
+			_docNameWidth = st::mvThickFont->m.width(_docName);
+		}
+
+		_docSize = formatSizeText(_doc->size);
+		_docSizeWidth = st::mvFont->m.width(_docSize);
+		if (_docSizeWidth > maxw) {
+			_docSize = st::mvFont->m.elidedText(_docSize, Qt::ElideRight, maxw);
+			_docSizeWidth = st::mvFont->m.width(_docSize);
+		}
+
+		_docRect = QRect((width() - st::mvDocSize.width()) / 2, (height() - st::mvDocSize.height()) / 2, st::mvDocSize.width(), st::mvDocSize.height());
+	} else {
+		_current.setDevicePixelRatio(cRetinaFactor());
+		_w = _current.width() / cIntRetinaFactor();
+		_h = _current.height() / cIntRetinaFactor();
+	}
+	if (isHidden()) {
+		moveToScreen();
+	}
+	_width = _w;
+	if (_w > 0 && _h > 0) {
+		_zoomToScreen = float64(width()) / _w;
+		if (_h * _zoomToScreen > height()) {
+			_zoomToScreen = float64(height()) / _h;
+		}
+		if (_zoomToScreen >= 1.) {
+			_zoomToScreen -= 1.;
+		} else {
+			_zoomToScreen = 1. - (1. / _zoomToScreen);
+		}
+	} else {
+		_zoomToScreen = 0;
+	}
+	if ((_w > width()) || (_h > height())) {
+		_zoom = ZoomToScreenLevel;
+		if (_zoomToScreen >= 0) {
+			_w = qRound(_w * (_zoomToScreen + 1));
+			_h = qRound(_h * (_zoomToScreen + 1));
+		} else {
+			_w = qRound(_w / (-_zoomToScreen + 1));
+			_h = qRound(_h / (-_zoomToScreen + 1));
+		}
+		snapXY();
+	} else {
+		_zoom = 0;
+	}
+	_x = (width() - _w) / 2;
+	_y = (height() - _h) / 2;
+	if (HistoryForwarded *fwd = dynamic_cast<HistoryForwarded*>(item)) {
+		_from = fwd->fromForwarded()->asUser();
+	} else {
+		_from = item->from()->asUser();
+	}
+	_full = 1;
+	updateControls();
+	if (isHidden()) {
+		psUpdateOverlayed(this);
+		show();
+		psShowOverAll(this);
+	}
+}
+
+void MediaView::paintEvent(QPaintEvent *e) {
+	Painter p(this);
+	QRect r(e->rect());
+	if (!rect().intersects(r)) return;
 
 	// main bg
-	QRect r_bg(st::medviewNavBarWidth, 0, _avail.width() - 2 * st::medviewNavBarWidth, _avail.height() - st::medviewBottomBar);
-	if (r_bg.intersects(r)) p.fillRect(r_bg.intersected(r), st::medviewBG->b);
-	if (_bottomBar.intersects(r)) p.fillRect(_bottomBar.intersected(r), st::medviewBottomBG->b);
-
-	// left nav bar bg
-	if (_leftNav.intersects(r)) {
-		if (_leftNavVisible) {
-			p.fillRect(_leftNav.intersected(r), overColor(st::medviewBG->c, 1, st::black->c, overLevel(OverLeftNav) * st::medviewNavBGOpacity));
-		} else {
-			p.fillRect(_leftNav.intersected(r), st::medviewBG->c);
-		}
-	}
-
-	// right nav bar
-	if (_rightNav.intersects(r)) {
-		if (_rightNavVisible) {
-			p.fillRect(_rightNav.intersected(r), overColor(st::medviewBG->c, 1, st::black->c, overLevel(OverRightNav) * st::medviewNavBGOpacity));
-			float64 o = overLevel(OverRightNav);
-		} else {
-			p.fillRect(_rightNav.intersected(r), st::medviewBG->b);
-		}
-	}
-
+	QPainter::CompositionMode m = p.compositionMode();
+	p.setCompositionMode(QPainter::CompositionMode_Source);
+	p.setOpacity(st::mvBgOpacity);
+	p.fillRect(rect().intersected(r), st::mvBgColor->b);
 	p.setCompositionMode(m);
-	p.setOpacity(1);
 
 	// photo
 	if (_photo) {
@@ -593,9 +777,11 @@ void MediaView::paintEvent(QPaintEvent *e) {
 		}
 	}
 	if (_photo || !_current.isNull()) {
+		p.setOpacity(1);
+
 		QRect imgRect(_x, _y, _w, _h);
 		if (imgRect.intersects(r)) {
-			if (_current.hasAlpha()) {
+			if (_current.hasAlpha() && (!_doc || _doc->sticker->isNull())) {
 				p.fillRect(imgRect, _transparentBrush);
 			}
 			if (_zoom) {
@@ -606,32 +792,15 @@ void MediaView::paintEvent(QPaintEvent *e) {
 			} else {
 				p.drawPixmap(_x, _y, _current);
 			}
-		}
-		if (!_doc && _polaroidOut.intersects(r)) {
-			// polaroid
-			p.fillRect(_polaroidOut.x(), _polaroidOut.y(), _polaroidIn.x() - _polaroidOut.x(), _polaroidOut.height(), st::white->b);
-			p.fillRect(_polaroidIn.x() + _polaroidIn.width(), _polaroidOut.y(), _polaroidOut.x() + _polaroidOut.width() - _polaroidIn.x() - _polaroidIn.width(), _polaroidOut.height(), st::white->b);
-			p.fillRect(_polaroidIn.x(), _polaroidOut.y(), _polaroidIn.width(), _polaroidIn.y() - _polaroidOut.y(), st::white->b);
-			p.fillRect(_polaroidIn.x(), _polaroidIn.y() + _polaroidIn.height(), _polaroidIn.width(), _polaroidOut.y() + _polaroidOut.height() - _polaroidIn.y() - _polaroidIn.height(), st::white->b);
-		}
-		if (imgRect.intersects(r)) {
+
 			uint64 ms = 0;
-			if (!_doc && imgRect.intersects(_leftNav)) {
-				p.fillRect(imgRect.intersected(_leftNav), _leftNavVisible ? overColor(st::medviewBG->c, 1, st::black->c, overLevel(OverLeftNav) * st::medviewNavBGOpacity) : st::medviewBG->c);
-			}
-			if (!_doc && imgRect.intersects(_rightNav)) {
-				p.fillRect(imgRect.intersected(_rightNav), _rightNavVisible ? overColor(st::medviewBG->c, 1, st::black->c, overLevel(OverRightNav) * st::medviewNavBGOpacity) : st::medviewBG->c);
-			}
-			if (imgRect.intersects(_bottomBar)) {
-				p.fillRect(imgRect.intersected(_bottomBar), st::medviewBG->b);
-			}
 			if (_full < 1) {
 				ms = getms();
 				uint64 dt = ms - _animStarted;
 				int32 cnt = int32(st::photoLoaderCnt), period = int32(st::photoLoaderPeriod), t = dt % period, delta = int32(st::photoLoaderDelta);
 
-				int32 x = (_avail.width() - st::mediaviewLoader.width()) / 2;
-				int32 y = st::medviewPolaroid.top() + (_availBottom - st::medviewPolaroid.top() - st::medviewPolaroid.bottom() - st::mediaviewLoader.height()) / 2;
+				int32 x = (width() - st::mediaviewLoader.width()) / 2;
+				int32 y = (height() - st::mediaviewLoader.height()) / 2;
 				p.fillRect(x, y, st::mediaviewLoader.width(), st::mediaviewLoader.height(), st::photoLoaderBg->b);
 
 				x += (st::mediaviewLoader.width() - cnt * st::mediaviewLoaderPoint.width() - (cnt - 1) * st::mediaviewLoaderSkip) / 2;
@@ -680,94 +849,167 @@ void MediaView::paintEvent(QPaintEvent *e) {
 				}
 			}
 		}
-	}
-
-	// disabled download button
-	if (_save.isHidden()) {
-		p.fillRect(_save.geometry(), st::medviewSaveAs.bgColor->b);
-		p.setOpacity(st::medviewSaveAsDisabledOpacity);
-		p.setPen(st::medviewSaveAs.color->p);
-		p.setFont(st::medviewSaveAs.font->f);
-		p.drawPixmap(_save.geometry().topLeft() + st::medviewSaveAs.iconPos, App::sprite(), st::medviewSaveAs.icon);
-		p.drawText(_save.geometry().topLeft() + st::medviewSaveAs.textPos + QPoint(0, st::medviewSaveAs.font->ascent), lang(lng_mediaview_save));
-		p.setOpacity(1);
-	}
-
-	// left nav arrow
-	if (_leftNavVisible) {
-		QPoint p_left((st::medviewNavBarWidth - st::medviewLeft.pxWidth()) / 2, (height() - st::medviewBottomBar - st::medviewLeft.pxHeight()) / 2);
-		if (QRect(p_left.x(), p_left.y(), st::medviewLeft.pxWidth(), st::medviewLeft.pxHeight()).intersects(r)) {
-			float64 o = overLevel(OverLeftNav);
-			p.setOpacity(o * st::medviewDarkNav + (1 - o) * st::medviewLightNav);
-			p.drawPixmap(p_left, App::sprite(), st::medviewLeft);
-		}
-	}
-
-	// right nav arrow
-	if (_rightNavVisible) {
-		QPoint p_right(width() - (st::medviewNavBarWidth + st::medviewRight.pxWidth()) / 2, (height() - st::medviewBottomBar - st::medviewRight.pxHeight()) / 2);
-		if (QRect(p_right.x(), p_right.y(), st::medviewRight.pxWidth(), st::medviewRight.pxHeight()).intersects(r)) {
-			float64 o = overLevel(OverRightNav);
-			p.setOpacity(o * st::medviewDarkNav + (1 - o) * st::medviewLightNav);
-			p.drawPixmap(p_right, App::sprite(), st::medviewRight);
-		}
-	}
-	p.setOpacity(1);
-
-	// header
-	if (_overview.isHidden()) {
-		QRect r_header(_overview.x(), _overview.y(), st::medviewHeaderFont->m.width(_header) - st::medviewOverview.width, _overview.height());
-		if (r_header.intersects(r)) {
-			p.setOpacity(st::medviewOverview.opacity);
-			p.setPen(st::medviewOverview.color->p);
-			p.setFont(st::medviewOverview.font->f);
-			p.drawPixmap(_overview.geometry().topLeft() + (_photo ? st::medviewPhotoSpritePos : st::medviewDocumentSpritePos), App::sprite(), _photo ? st::medviewPhotoSprite : st::medviewDocumentSprite);
-			p.drawText(r_header.topLeft() + st::medviewOverview.textPos + QPoint(0, st::medviewHeaderFont->ascent), _header);
-			p.setOpacity(1);
-		}
-	}
-
-	// name
-	if (_doc) {
-		float64 o = overLevel(OverName);
-		p.setOpacity(st::medviewOverview.overOpacity * o + st::medviewOverview.opacity * (1 - o));
-		p.setPen(st::white->p);
 	} else {
-		p.setPen(st::medviewNameColor->p);
-	}
-	if (_from) {
-		if (_nameNav.intersects(r)) {
-			if (_over == OverName) _fromName.replaceFont(st::medviewNameFont->underline());
-			_fromName.drawElided(p, _nameNav.left(), _nameNav.top(), _nameNav.width());
-			if (_over == OverName) _fromName.replaceFont(st::medviewNameFont);
+		if (_docRect.intersects(r)) {
+			p.fillRect(_docRect, st::mvDocBg->b);
+			QRect thumb = rtlrect(_docRect.x() + st::mvDocPadding, _docRect.y() + st::mvDocPadding, st::mvDocBlue.pxWidth(), st::mvDocBlue.pxHeight(), width());
+			if (_doc->thumb->isNull()) {
+				p.drawPixmap(thumb.topLeft(), App::sprite(), _docIcon);
+			} else {
+				int32 rf(cIntRetinaFactor());
+				p.drawPixmap(thumb.topLeft(), _doc->thumb->pix(_docThumbw), QRect(_docThumbx * rf, _docThumby * rf, st::mvDocBlue.pxWidth() * rf, st::mvDocBlue.pxHeight() * rf));
+			}
+
+			if (_doc && _docRadialStart > 0) {
+				p.setRenderHint(QPainter::HighQualityAntialiasing);
+
+				QRect inner(QPoint(thumb.x() + ((thumb.width() - st::radialSize.width()) / 2), thumb.y() + ((thumb.height() - st::radialSize.height()) / 2)), st::radialSize);
+				p.setPen(Qt::NoPen);
+				p.setBrush(st::black->b);
+				p.setOpacity(st::radialBgOpacity);
+				p.drawEllipse(inner);
+
+				QRect arc(inner.marginsRemoved(QMargins(st::radialLine / 2, st::radialLine / 2, st::radialLine / 2, st::radialLine / 2)));
+				p.setOpacity(1);
+
+				p.setPen(_docRadialPen);
+
+				p.drawArc(arc, a_docRadialStart.current() * 5600, 10 + a_docRadial.current() * 5490);
+
+				p.setRenderHint(QPainter::HighQualityAntialiasing, false);
+			}
+
+			p.setPen(st::mvDocNameColor->p);
+			p.setFont(st::mvThickFont->f);
+			p.drawTextLeft(_docRect.x() + 2 * st::mvDocPadding + st::mvDocBlue.pxWidth(), _docRect.y() + st::mvDocPadding + st::mvDocNameTop, width(), _docName, _docNameWidth);
+
+			p.setPen(st::mvDocSizeColor->p);
+			p.setFont(st::mvFont->f);
+			p.drawTextLeft(_docRect.x() + 2 * st::mvDocPadding + st::mvDocBlue.pxWidth(), _docRect.y() + st::mvDocPadding + st::mvDocSizeTop, width(), _docSize, _docSizeWidth);
 		}
 	}
 
-	// date
-	if (_dateNav.intersects(r)) {
-		if (_doc) {
-			float64 o = overLevel(OverDate);
-			p.setOpacity(st::medviewOverview.overOpacity * o + st::medviewOverview.opacity * (1 - o));
-			p.setPen(st::white->p);
-		} else {
-			p.setPen(st::medviewDateColor->p);
+	float64 co = a_cOpacity.current();
+	if (co > 0) {
+		// left nav bar
+		if (_leftNav.intersects(r) && _leftNavVisible) {
+			float64 o = overLevel(OverLeftNav);
+			if (o > 0) {
+				p.setOpacity(o * st::mvControlBgOpacity * co);
+				p.fillRect(_leftNav.intersected(r), st::black->b);
+			}
+
+			QPoint p_left(_leftNav.x() + (_leftNav.width() - st::mvLeft.pxWidth()) / 2, _leftNav.y() + (_leftNav.height() - st::mvLeft.pxHeight()) / 2);
+			if (QRect(p_left.x(), p_left.y(), st::mvLeft.pxWidth(), st::mvLeft.pxHeight()).intersects(r)) {
+				p.setOpacity((o * st::mvIconOverOpacity + (1 - o) * st::mvIconOpacity) * co);
+				p.drawPixmap(p_left, App::sprite(), st::mvLeft);
+			}
+		}
+
+		// right nav bar
+		if (_rightNav.intersects(r) && _rightNavVisible) {
+			float64 o = overLevel(OverRightNav);
+			if (o > 0) {
+				p.setOpacity(o * st::mvControlBgOpacity * co);
+				p.fillRect(_rightNav.intersected(r), st::black->b);
+			}
+
+			QPoint p_right(_rightNav.x() + (_rightNav.width() - st::mvRight.pxWidth()) / 2, _rightNav.y() + (_rightNav.height() - st::mvRight.pxHeight()) / 2);
+			if (QRect(p_right.x(), p_right.y(), st::mvRight.pxWidth(), st::mvRight.pxHeight()).intersects(r)) {
+				p.setOpacity((o * st::mvIconOverOpacity + (1 - o) * st::mvIconOpacity) * co);
+				p.drawPixmap(p_right, App::sprite(), st::mvRight);
+			}
+		}
+
+		// close button
+		if (_closeNav.intersects(r)) {
+			float64 o = overLevel(OverClose);
+			if (o > 0) {
+				p.setOpacity(o * st::mvControlBgOpacity * co);
+				p.fillRect(_closeNav.intersected(r), st::black->b);
+			}
+
+			QPoint p_right(_closeNav.x() + (_closeNav.width() - st::mvClose.pxWidth()) / 2, _closeNav.y() + (_closeNav.height() - st::mvClose.pxHeight()) / 2);
+			if (QRect(p_right.x(), p_right.y(), st::mvClose.pxWidth(), st::mvClose.pxHeight()).intersects(r)) {
+				p.setOpacity((o * st::mvIconOverOpacity + (1 - o) * st::mvIconOpacity) * co);
+				p.drawPixmap(p_right, App::sprite(), st::mvClose);
+			}
+		}
+
+		// save button
+		if (_saveNav.intersects(r)) {
+			float64 o = overLevel(OverSave);
+			QPoint p_right(_saveNav.x() + (_saveNav.width() - st::mvSave.pxWidth()) / 2, _saveNav.y() + (_saveNav.height() - st::mvSave.pxHeight()) / 2);
+			if (QRect(p_right.x(), p_right.y(), st::mvSave.pxWidth(), st::mvSave.pxHeight()).intersects(r)) {
+				p.setOpacity((o * st::mvIconOverOpacity + (1 - o) * st::mvIconOpacity) * co);
+				p.drawPixmap(p_right, App::sprite(), st::mvSave);
+			}
+		}
+
+		// more area
+		if (_moreNav.intersects(r)) {
+			float64 o = overLevel(OverMore);
+			QPoint p_right(_moreNav.x() + (_moreNav.width() - st::mvMore.pxWidth()) / 2, _moreNav.y() + (_moreNav.height() - st::mvMore.pxHeight()) / 2);
+			if (QRect(p_right.x(), p_right.y(), st::mvMore.pxWidth(), st::mvMore.pxHeight()).intersects(r)) {
+				p.setOpacity((o * st::mvIconOverOpacity + (1 - o) * st::mvIconOpacity) * co);
+				p.drawPixmap(p_right, App::sprite(), st::mvMore);
+			}
+		}
+
+		p.setPen(st::white->p);
+		p.setFont(st::mvThickFont->f);
+
+		// header
+		if (_headerNav.intersects(r)) {
+			float64 o = _headerHasLink ? overLevel(OverHeader) : 0;
+			p.setOpacity((o * st::mvIconOverOpacity + (1 - o) * st::mvIconOpacity) * co);
+			p.drawText(_headerNav.left(), _headerNav.top() + st::mvThickFont->ascent, _headerText);
+
+			if (o > 0) {
+				p.setOpacity(o * co);
+				p.drawLine(_headerNav.left(), _headerNav.top() + st::mvThickFont->ascent + 1, _headerNav.right(), _headerNav.top() + st::mvThickFont->ascent + 1);
+			}
+		}
+
+		p.setFont(st::mvFont->f);
+
+		// name
+		if (_from && _nameNav.intersects(r)) {
+			float64 o = overLevel(OverName);
+			p.setOpacity((o * st::mvIconOverOpacity + (1 - o) * st::mvIconOpacity) * co);
+			_fromName.drawElided(p, _nameNav.left(), _nameNav.top(), _nameNav.width());
+
+			if (o > 0) {
+				p.setOpacity(o * co);
+				p.drawLine(_nameNav.left(), _nameNav.top() + st::mvFont->ascent + 1, _nameNav.right(), _nameNav.top() + st::mvFont->ascent + 1);
+			}
+		}
+
+		// date
+		if (_dateNav.intersects(r)) {
+			float64 o = overLevel(OverDate);
+			p.setOpacity((o * st::mvIconOverOpacity + (1 - o) * st::mvIconOpacity) * co);
+			p.drawText(_dateNav.left(), _dateNav.top() + st::mvFont->ascent, _dateText);
+
+			if (o > 0) {
+				p.setOpacity(o * co);
+				p.drawLine(_dateNav.left(), _dateNav.top() + st::mvFont->ascent + 1, _dateNav.right(), _dateNav.top() + st::mvFont->ascent + 1);
+			}
 		}
-		p.setFont((_over == OverDate ? st::medviewDateFont->underline() : st::medviewDateFont)->f);
-		p.drawText(_dateNav.left(), _dateNav.top() + st::medviewDateFont->ascent, _dateText);
 	}
 }
 
 void MediaView::keyPressEvent(QKeyEvent *e) {
 	if (!_menu && e->key() == Qt::Key_Escape) {
-		onClose();
+		close();
 	} else if (e == QKeySequence::Save || e == QKeySequence::SaveAs) {
 		onSave();
 	} else if (e->key() == Qt::Key_Copy || (e->key() == Qt::Key_C && e->modifiers().testFlag(Qt::ControlModifier))) {
 		onCopy();
 	} else if (e->key() == Qt::Key_Left) {
-		moveToPhoto(-1);
+		moveToNext(-1);
 	} else if (e->key() == Qt::Key_Right) {
-		moveToPhoto(1);
+		moveToNext(1);
     } else if (e->modifiers().testFlag(Qt::ControlModifier) && (e->key() == Qt::Key_Plus || e->key() == Qt::Key_Equal || e->key() == ']' || e->key() == Qt::Key_Asterisk || e->key() == Qt::Key_Minus || e->key() == Qt::Key_Underscore || e->key() == Qt::Key_0)) {
 		int32 newZoom = _zoom;
         if (e->key() == Qt::Key_Plus || e->key() == Qt::Key_Equal || e->key() == Qt::Key_Asterisk || e->key() == ']') {
@@ -805,7 +1047,7 @@ void MediaView::keyPressEvent(QKeyEvent *e) {
 				newZoom = 0;
 			}
 			_x = -_width / 2;
-			_y = (_doc ? 0 : st::medviewPolaroid.top()) - ((_current.height() / cIntRetinaFactor()) / 2);
+			_y = -((_current.height() / cIntRetinaFactor()) / 2);
 			float64 z = (_zoom == ZoomToScreenLevel) ? _zoomToScreen : _zoom;
 			if (z >= 0) {
 				_x = qRound(_x * (z + 1));
@@ -814,9 +1056,8 @@ void MediaView::keyPressEvent(QKeyEvent *e) {
 				_x = qRound(_x / (-z + 1));
 				_y = qRound(_y / (-z + 1));
 			}
-			_x += _avail.width() / 2;
-			_y += (_avail.height() - st::medviewBottomBar - (_doc ? 0 : (st::medviewPolaroid.top() + st::medviewPolaroid.bottom()))) / 2;
-			updatePolaroid();
+			_x += width() / 2;
+			_y += height() / 2;
 			update();
 		}
 		if (newZoom != ZoomToScreenLevel) {
@@ -829,24 +1070,24 @@ void MediaView::keyPressEvent(QKeyEvent *e) {
 			_w = _current.width() / cIntRetinaFactor();
 			_h = _current.height() / cIntRetinaFactor();
 			if (z >= 0) {
-				nx = (_x - _avail.width() / 2.) / (z + 1);
-				ny = (_y - _avail.height() / 2.) / (z + 1);
+				nx = (_x - width() / 2.) / (z + 1);
+				ny = (_y - height() / 2.) / (z + 1);
 			} else {
-				nx = (_x - _avail.width() / 2.) * (-z + 1);
-				ny = (_y - _avail.height() / 2.) * (-z + 1);
+				nx = (_x - width() / 2.) * (-z + 1);
+				ny = (_y - height() / 2.) * (-z + 1);
 			}
 			_zoom = newZoom;
 			z = (_zoom == ZoomToScreenLevel) ? _zoomToScreen : _zoom;
 			if (z > 0) {
 				_w = qRound(_w * (z + 1));
 				_h = qRound(_h * (z + 1));
-				_x = qRound(nx * (z + 1) + _avail.width() / 2.);
-				_y = qRound(ny * (z + 1) + _avail.height() / 2.);
+				_x = qRound(nx * (z + 1) + width() / 2.);
+				_y = qRound(ny * (z + 1) + height() / 2.);
 			} else {
 				_w = qRound(_w / (-z + 1));
 				_h = qRound(_h / (-z + 1));
-				_x = qRound(nx / (-z + 1) + _avail.width() / 2.);
-				_y = qRound(ny / (-z + 1) + _avail.height() / 2.);
+				_x = qRound(nx / (-z + 1) + width() / 2.);
+				_y = qRound(ny / (-z + 1) + height() / 2.);
 			}
 			snapXY();
 			update();
@@ -854,58 +1095,64 @@ void MediaView::keyPressEvent(QKeyEvent *e) {
 	}
 }
 
-void MediaView::moveToPhoto(int32 delta) {
-	if (_index < 0 || !_photo) return;
+void MediaView::moveToNext(int32 delta) {
+	if (_index < 0 || (!_photo && !_doc) || (_overview == OverviewCount && !_user)) return;
 
 	int32 newIndex = _index + delta;
-	if (_history) {
-		if (newIndex >= 0 && newIndex < _history->_overview[OverviewPhotos].size()) {
+	if (_history && _overview != OverviewCount) {
+		if (newIndex >= 0 && newIndex < _history->_overview[_overview].size()) {
 			_index = newIndex;
-			if (HistoryItem *item = App::histItemById(_history->_overview[OverviewPhotos][_index])) {
+			if (HistoryItem *item = App::histItemById(_history->_overview[_overview][_index])) {
 				_msgid = item->id;
-				HistoryPhoto *photo = dynamic_cast<HistoryPhoto*>(item->getMedia());
-				if (photo) {
-					showPhoto(photo->photo());
-					preloadPhotos(delta);
+				switch (item->getMedia()->type()) {
+				case MediaTypePhoto: displayPhoto(static_cast<HistoryPhoto*>(item->getMedia())->photo()); preloadData(delta); break;
+				case MediaTypeDocument: displayDocument(static_cast<HistoryDocument*>(item->getMedia())->document(), item); preloadData(delta); break;
+				case MediaTypeSticker: displayDocument(static_cast<HistorySticker*>(item->getMedia())->document(), item); preloadData(delta); break;
 				}
 			}
 		}
 		if (delta < 0 && _index < MediaOverviewStartPerPage) {
-			loadPhotosBack();
+			loadBack();
 		}
 	} else if (_user) {
 		if (newIndex >= 0 && newIndex < _user->photos.size()) {
 			_index = newIndex;
-			showPhoto(_user->photos[_index]);
-			preloadPhotos(delta);
+			displayPhoto(_user->photos[_index]);
+			preloadData(delta);
 		}
 		if (delta > 0 && _index > _user->photos.size() - MediaOverviewStartPerPage) {
-			loadPhotosBack();
+			loadBack();
 		}
 	}
 }
 
-void MediaView::preloadPhotos(int32 delta) {
-	if (_index < 0 || !_photo) return;
+void MediaView::preloadData(int32 delta) {
+	if (_index < 0 || !_user && _overview == OverviewCount) return;
 
 	int32 from = _index + (delta ? delta : -1), to = _index + (delta ? delta * MediaOverviewPreloadCount : 1), forget = _index - delta * 2;
 	if (from > to) qSwap(from, to);
-	if (_history) {
+	if (_history && _overview != OverviewCount) {
 		for (int32 i = from; i <= to; ++i) {
-			if (i >= 0 && i < _history->_overview[OverviewPhotos].size() && i != _index) {
-				if (HistoryItem *item = App::histItemById(_history->_overview[OverviewPhotos][i])) {
-					HistoryPhoto *photo = dynamic_cast<HistoryPhoto*>(item->getMedia());
-					if (photo) {
-						photo->photo()->full->load();
+			if (i >= 0 && i < _history->_overview[_overview].size() && i != _index) {
+				if (HistoryItem *item = App::histItemById(_history->_overview[_overview][i])) {
+					if (HistoryMedia *media = item->getMedia()) {
+						switch (media->type()) {
+						case MediaTypePhoto: static_cast<HistoryPhoto*>(media)->photo()->full->load(); break;
+						case MediaTypeDocument: static_cast<HistoryDocument*>(media)->document()->thumb->load(); break;
+						case MediaTypeSticker: static_cast<HistorySticker*>(media)->document()->sticker->load(); break;
+						}
 					}
 				}
 			}
 		}
-		if (forget >= 0 && forget < _history->_overview[OverviewPhotos].size() && forget != _index) {
-			if (HistoryItem *item = App::histItemById(_history->_overview[OverviewPhotos][forget])) {
-				HistoryMedia *media = item->getMedia();
-				if (media && media->type() == MediaTypePhoto) {
-					static_cast<HistoryPhoto*>(media)->photo()->forget();
+		if (forget >= 0 && forget < _history->_overview[_overview].size() && forget != _index) {
+			if (HistoryItem *item = App::histItemById(_history->_overview[_overview][forget])) {
+				if (HistoryMedia *media = item->getMedia()) {
+					switch (media->type()) {
+					case MediaTypePhoto: static_cast<HistoryPhoto*>(media)->photo()->forget(); break;
+					case MediaTypeDocument: static_cast<HistoryDocument*>(media)->document()->forget(); break;
+					case MediaTypeSticker: static_cast<HistorySticker*>(media)->document()->forget(); break;
+					}
 				}
 			}
 		}
@@ -935,16 +1182,24 @@ void MediaView::mousePressEvent(QMouseEvent *e) {
 		_down = OverNone;
 		if (!textlnkDown()) {
 			if (_over == OverLeftNav && _index >= 0) {
-				moveToPhoto(-1);
+				moveToNext(-1);
 				_lastAction = e->pos();
 			} else if (_over == OverRightNav && _index >= 0) {
-				moveToPhoto(1);
+				moveToNext(1);
 				_lastAction = e->pos();
 			} else if (_over == OverName) {
 				_down = OverName;
 			} else if (_over == OverDate) {
 				_down = OverDate;
-			} else if (!_bottomBar.contains(e->pos()) && (!_saveMsg.contains(e->pos()) || !_saveMsgStarted)) {
+			} else if (_over == OverHeader) {
+				_down = OverHeader;
+			} else if (_over == OverSave) {
+				_down = OverSave;
+			} else if (_over == OverMore) {
+				_down = OverMore;
+			} else if (_over == OverClose) {
+				_down = OverClose;
+			} else if (!_saveMsg.contains(e->pos()) || !_saveMsgStarted) {
 				_pressed = true;
 				_dragging = 0;
 				setCursor(style::cur_default);
@@ -954,32 +1209,36 @@ void MediaView::mousePressEvent(QMouseEvent *e) {
 			}
 		}
 	}
+	activateControls();
 }
 
 void MediaView::snapXY() {
-	int32 xmin = _avail.width() - _w - (_doc ? 0 : (st::medviewNavBarWidth + st::medviewPolaroid.right())), xmax = _doc ? 0 : (st::medviewPolaroid.left() + st::medviewNavBarWidth);
-	int32 ymin = _avail.height() - _h - (_doc ? 0 : st::medviewPolaroid.bottom()) - st::medviewBottomBar, ymax = (_doc ? 0 : st::medviewPolaroid.top());
-	if (xmin > (_avail.width() - _w) / 2) xmin = (_avail.width() - _w) / 2;
-	if (xmax < (_avail.width() - _w) / 2) xmax = (_avail.width() - _w) / 2;
-	if (ymin > (_avail.height() - _h - st::medviewBottomBar - (_doc ? 0 : (st::medviewPolaroid.bottom() - st::medviewPolaroid.top()))) / 2) ymin = (_avail.height() - _h - st::medviewBottomBar - (_doc ? 0 : (st::medviewPolaroid.bottom() - st::medviewPolaroid.top()))) / 2;
-	if (ymax < (_avail.height() - _h - st::medviewBottomBar - (_doc ? 0 : (st::medviewPolaroid.bottom() - st::medviewPolaroid.top()))) / 2) ymax = (_avail.height() - _h - st::medviewBottomBar - (_doc ? 0 : (st::medviewPolaroid.bottom() - st::medviewPolaroid.top()))) / 2;
+	int32 xmin = width() - _w, xmax = 0;
+	int32 ymin = height() - _h, ymax = 0;
+	if (xmin > (width() - _w) / 2) xmin = (width() - _w) / 2;
+	if (xmax < (width() - _w) / 2) xmax = (width() - _w) / 2;
+	if (ymin > (height() - _h) / 2) ymin = (height() - _h) / 2;
+	if (ymax < (height() - _h) / 2) ymax = (height() - _h) / 2;
 	if (_x < xmin) _x = xmin;
 	if (_x > xmax) _x = xmax;
 	if (_y < ymin) _y = ymin;
 	if (_y > ymax) _y = ymax;
-	updatePolaroid();
 }
 
 void MediaView::mouseMoveEvent(QMouseEvent *e) {
+	bool moved = (e->pos() != _lastMouseMovePos);
+	LOG(("MOUSE MOVE: WAS %1 %2 NOW %3 %4 MOVED: %5").arg(_lastMouseMovePos.x()).arg(_lastMouseMovePos.y()).arg(e->pos().x()).arg(e->pos().y()).arg(logBool(moved)));
+	_lastMouseMovePos = e->pos();
+
 	updateOver(e->pos());
-	if (_lastAction.x() >= 0 && (e->pos() - _lastAction).manhattanLength() >= st::medviewDeltaFromLastAction) {
-		_lastAction = QPoint(-st::medviewDeltaFromLastAction, -st::medviewDeltaFromLastAction);
+	if (_lastAction.x() >= 0 && (e->pos() - _lastAction).manhattanLength() >= st::mvDeltaFromLastAction) {
+		_lastAction = QPoint(-st::mvDeltaFromLastAction, -st::mvDeltaFromLastAction);
 	}
 	if (_pressed) {
 		if (!_dragging && (e->pos() - _mStart).manhattanLength() >= QApplication::startDragDistance()) {
 			_dragging = QRect(_x, _y, _w, _h).contains(_mStart) ? 1 : -1;
 			if (_dragging > 0) {
-				if (_w > _avail.width() - (_doc ? 0 : (2 * st::medviewNavBarWidth + st::medviewPolaroid.left() + st::medviewPolaroid.right())) || _h > _avail.height() - (_doc ? 0 : (st::medviewPolaroid.top() + st::medviewPolaroid.bottom())) - st::medviewBottomBar) {
+				if (_w > width() || _h > height()) {
 					setCursor(style::cur_sizeall);
 				} else {
 					setCursor(style::cur_default);
@@ -993,11 +1252,34 @@ void MediaView::mouseMoveEvent(QMouseEvent *e) {
 			update();
 		}
 	}
+	if (moved) activateControls();
 }
 
 bool MediaView::updateOverState(OverState newState) {
 	bool result = true;
 	if (_over != newState) {
+		LOG(("UPDATING STATE TO %1, IGNORING: %2").arg(newState).arg(logBool(_ignoringDropdown)));
+		if (newState == OverMore && !_ignoringDropdown) {
+			QTimer::singleShot(0, this, SLOT(onDropdown()));
+		} else if (newState == OverNone) {
+			if (_over == OverLeftNav) {
+				update(_leftNav);
+			} else if (_over == OverRightNav) {
+				update(_rightNav);
+			} else if (_over == OverName) {
+				update(_nameNav);
+			} else if (_over == OverDate) {
+				update(_dateNav);
+			} else if (_over == OverSave) {
+				update(_saveNav);
+			} else if (_over == OverHeader) {
+				update(_headerNav);
+			} else if (_over == OverClose) {
+				update(_closeNav);
+			} else if (_over == OverMore) {
+				update(_moreNav);
+			}
+		}
 		if (_over != OverNone) {
 			_animations[_over] = getms();
 			ShowingOpacities::iterator i = _animOpacities.find(_over);
@@ -1059,16 +1341,23 @@ void MediaView::updateOver(const QPoint &pos) {
 		if (!updateOverState(OverDate)) {
 			update(_dateNav);
 		}
-	} else if (_over != OverNone) {
-		if (_over == OverLeftNav) {
-			update(_leftNav);
-		} else if (_over == OverRightNav) {
-			update(_rightNav);
-		} else if (_over == OverName) {
-			update(_nameNav);
-		} else if (_over == OverDate) {
-			update(_dateNav);
+	} else if (_headerHasLink && _headerNav.contains(pos)) {
+		if (!updateOverState(OverHeader)) {
+			update(_headerNav);
 		}
+	} else if (_saveVisible && _saveNav.contains(pos)) {
+		if (!updateOverState(OverSave)) {
+			update(_saveNav);
+		}
+	} else if (_moreNav.contains(pos)) {
+		if (!updateOverState(OverMore)) {
+			update(_moreNav);
+		}
+	} else if (_closeNav.contains(pos)) {
+		if (!updateOverState(OverClose)) {
+			update(_closeNav);
+		}
+	} else if (_over != OverNone) {
 		updateOverState(OverNone);
 	}
 }
@@ -1081,17 +1370,19 @@ void MediaView::mouseReleaseEvent(QMouseEvent *e) {
 	textlnkDown(TextLinkPtr());
 	if (_over == OverName && _down == OverName) {
 		if (App::wnd() && _from) {
-			onClose();
+			close();
 			if (App::main()) App::main()->showPeerProfile(_from);
 		}
-	} else if (_over == OverDate && _down == OverDate && _msgid) {
-		HistoryItem *item = App::histItemById(_msgid);
-		if (item) {
-			if (App::wnd()) {
-				onClose();
-				if (App::main()) App::main()->showPeer(item->history()->peer->id, _msgid, false, true);
-			}
-		}
+	} else if (_over == OverDate && _down == OverDate) {
+		onToMessage();
+	} else if (_over == OverHeader && _down == OverHeader) {
+		onOverview();
+	} else if (_over == OverSave && _down == OverSave) {
+		onDownload();
+	} else if (_over == OverMore && _down == OverMore) {
+		QTimer::singleShot(0, this, SLOT(onDropdown()));
+	} else if (_over == OverClose && _down == OverClose) {
+		close();
 	} else if (_pressed) {
 		if (_dragging) {
 			if (_dragging > 0) {
@@ -1102,48 +1393,25 @@ void MediaView::mouseReleaseEvent(QMouseEvent *e) {
 			}
 			_dragging = 0;
 			setCursor(style::cur_default);
-		} else if ((e->pos() - _lastAction).manhattanLength() >= st::medviewDeltaFromLastAction) {
-			onClose();
+		} else if ((e->pos() - _lastAction).manhattanLength() >= st::mvDeltaFromLastAction) {
+			close();
 		}
 		_pressed = false;
 	}
 	_down = OverNone;
+	activateControls();
 }
 
 void MediaView::contextMenuEvent(QContextMenuEvent *e) {
-	if (_photo && _photo->full->loaded() && (e->reason() != QContextMenuEvent::Mouse || QRect(_x, _y, _w, _h).contains(e->pos()))) {
+	if (e->reason() != QContextMenuEvent::Mouse || QRect(_x, _y, _w, _h).contains(e->pos())) {
 		if (_menu) {
 			_menu->deleteLater();
 			_menu = 0;
 		}
-		_menu = new ContextMenu(this);
-		_menu->addAction(lang(lng_context_save_image), this, SLOT(onSave()))->setEnabled(true);
-		_menu->addAction(lang(lng_context_copy_image), this, SLOT(onCopy()))->setEnabled(true);
-		_menu->addAction(lang(lng_context_close_image), this, SLOT(onClose()))->setEnabled(true);
-		if (_msgid) {
-			_menu->addAction(lang(lng_context_forward_image), this, SLOT(onForward()))->setEnabled(true);
-			_menu->addAction(lang(lng_context_delete_image), this, SLOT(onDelete()))->setEnabled(true);
-		} else if ((App::self() && App::self()->photoId == _photo->id) || (_photo->chat && _photo->chat->photoId == _photo->id)) {
-			_menu->addAction(lang(lng_context_delete_image), this, SLOT(onDelete()))->setEnabled(true);
-		}
-		_menu->deleteOnHide();
-		connect(_menu, SIGNAL(destroyed(QObject*)), this, SLOT(onMenuDestroy(QObject*)));
-		_menu->popup(e->globalPos());
-		e->accept();
-	} else if (_doc && (e->reason() != QContextMenuEvent::Mouse || QRect(_x, _y, _w, _h).contains(e->pos()))) {
-		if (_menu) {
-			_menu->deleteLater();
-			_menu = 0;
-		}
-		_menu = new ContextMenu(this);
-		if (!_doc->already(true).isEmpty()) {
-			_menu->addAction(lang(cPlatform() == dbipMac ? lng_context_show_in_finder : lng_context_show_in_folder), this, SLOT(onShowInFolder()))->setEnabled(true);
-		}
-		_menu->addAction(lang(lng_context_save_file), this, SLOT(onSave()))->setEnabled(true);
-		_menu->addAction(lang(lng_context_close_file), this, SLOT(onClose()))->setEnabled(true);
-		if (_msgid) {
-			_menu->addAction(lang(lng_context_forward_file), this, SLOT(onForward()))->setEnabled(true);
-			_menu->addAction(lang(lng_context_delete_file), this, SLOT(onDelete()))->setEnabled(true);
+		_menu = new ContextMenu(this, st::mvDropdown, st::mvContextButton);
+		updateDropdown();
+		for (int32 i = 0, l = _btns.size(); i < l; ++i) {
+			if (!_btns.at(i)->isHidden()) _menu->addAction(_btns.at(i)->getText(), _btns.at(i), SIGNAL(clicked()))->setEnabled(true);
 		}
 		_menu->deleteOnHide();
 		connect(_menu, SIGNAL(destroyed(QObject*)), this, SLOT(onMenuDestroy(QObject*)));
@@ -1189,8 +1457,8 @@ void MediaView::touchEvent(QTouchEvent *e) {
 		} else if (_touchMove) {
 			if ((!_leftNavVisible || !_leftNav.contains(mapFromGlobal(_touchStart))) && (!_rightNavVisible || !_rightNav.contains(mapFromGlobal(_touchStart)))) {
 				QPoint d = (e->touchPoints().cbegin()->screenPos().toPoint() - _touchStart);
-				if (d.x() * d.x() > d.y() * d.y() && (d.x() > st::medviewSwipeDistance || d.x() < -st::medviewSwipeDistance)) {
-					moveToPhoto(d.x() > 0 ? -1 : 1);
+				if (d.x() * d.x() > d.y() * d.y() && (d.x() > st::mvSwipeDistance || d.x() < -st::mvSwipeDistance)) {
+					moveToNext(d.x() > 0 ? -1 : 1);
 				}
 			}
 		}
@@ -1223,7 +1491,7 @@ bool MediaView::event(QEvent *e) {
 			if (ev->phase() == Qt::ScrollEnd) {
 				if (ev->orientation() == Qt::Horizontal) {
 					if (_accumScroll.x() * _accumScroll.x() > _accumScroll.y() * _accumScroll.y() && _accumScroll.x() != 0) {
-						moveToPhoto(_accumScroll.x() > 0 ? -1 : 1);
+						moveToNext(_accumScroll.x() > 0 ? -1 : 1);
 					}
 					_accumScroll = QPoint();
 				}
@@ -1234,12 +1502,10 @@ bool MediaView::event(QEvent *e) {
 }
 
 void MediaView::hide() {
+	_controlsHideTimer.stop();
+	_controlsState = ControlsShown;
+	a_cOpacity = anim::fvalue(1, 1);
 	QWidget::hide();
-	_close.clearState();
-	_save.clearState();
-	_forward.clearState();
-	_delete.clearState();
-	_overview.clearState();
 }
 
 void MediaView::onMenuDestroy(QObject *obj) {
@@ -1254,6 +1520,13 @@ void MediaView::receiveMouse() {
 	_receiveMouse = true;
 }
 
+void MediaView::onDropdown() {
+	updateDropdown();
+	_dropdown.ignoreShow(false);
+	_dropdown.showStart();
+	_dropdown.setFocus();
+}
+
 void MediaView::onCheckActive() {
 	if (App::wnd() && isVisible()) {
 		if (App::wnd()->isActiveWindow() && App::wnd()->hasFocus()) {
@@ -1271,11 +1544,24 @@ void MediaView::updateImage() {
 	update(_saveMsg);
 }
 
-void MediaView::loadPhotosBack() {
-	if (_loadRequest || _index < 0 || !_photo) return;
+void MediaView::findCurrent() {
+	for (int i = 0, l = _history->_overview[_overview].size(); i < l; ++i) {
+		if (_history->_overview[_overview].at(i) == _msgid) {
+			_index = i;
+			break;
+		}
+	}
 
-	if (_history && _history->_overviewCount[OverviewPhotos] != 0) {
-		if (App::main()) App::main()->loadMediaBack(_history->peer, OverviewPhotos);
+	if (_history->_overviewCount[_overview] < 0) {
+		loadBack();
+	}
+}
+
+void MediaView::loadBack() {
+	if (_loadRequest || _index < 0 || (_overview == OverviewCount && !_user)) return;
+
+	if (_history && _overview != OverviewCount && _history->_overviewCount[_overview] != 0) {
+		if (App::main()) App::main()->loadMediaBack(_history->peer, _overview);
 	} else if (_user && _user->photosCount != 0) {
 		int32 limit = (_index < MediaOverviewStartPerPage && _user->photos.size() > MediaOverviewStartPerPage) ? SearchPerPage : MediaOverviewStartPerPage;
 		_loadRequest = MTP::send(MTPphotos_GetUserPhotos(_user->inputUser, MTP_int(_user->photos.size()), MTP_int(0), MTP_int(limit)), rpcDone(&MediaView::userPhotosLoaded, _user));
@@ -1319,101 +1605,102 @@ void MediaView::userPhotosLoaded(UserData *u, const MTPphotos_Photos &photos, mt
 }
 
 void MediaView::updateHeader() {
-	if (!_photo) {
-		_header = _doc ? _doc->name : QString();
-		if (_header.isEmpty()) _header = lang(lng_mediaview_doc_image);
-		if (!_overview.isHidden()) _overview.hide();
-		return;
-	}
-
 	int32 index = _index, count = 0;
 	if (_history) {
-		count = _history->_overviewCount[OverviewPhotos] ? _history->_overviewCount[OverviewPhotos] : _history->_overview[OverviewPhotos].size();
-		if (index >= 0) index += count - _history->_overview[OverviewPhotos].size();
+		if (_overview != OverviewCount) {
+			count = _history->_overviewCount[_overview] ? _history->_overviewCount[_overview] : _history->_overview[_overview].size();
+			if (index >= 0) index += count - _history->_overview[_overview].size();
+		}
 	} else if (_user) {
 		count = _user->photosCount ? _user->photosCount : _user->photos.size();
 	}
 	if (_index >= 0 && _index < count && count > 1) {
-		_header = lng_mediaview_n_of_count(lt_n, QString::number(index + 1), lt_count, QString::number(count));
-		_overview.setText(_header);
-		if (_history) {
-			if (_overview.isHidden()) _overview.show();
+		if (_doc) {
+			_headerText = lng_mediaview_file_n_of_count(lt_file, _doc->name.isEmpty() ? lang(lng_mediaview_doc_image) : _doc->name, lt_n, QString::number(index + 1), lt_count, QString::number(count));
 		} else {
-			if (!_overview.isHidden()) _overview.hide();
-		}
-	} else if (_user) {
-		_header = lang(lng_mediaview_profile_photo);
-		if (!_overview.isHidden()) _overview.hide();
-	} else if (_peer) {
-		_header = lang(lng_mediaview_group_photo);
-		if (!_overview.isHidden()) _overview.hide();
-	} else {
-		_header = lang(lng_mediaview_single_photo);
-		if (!_overview.isHidden()) _overview.hide();
-	}
-}
-
-void MediaView::updatePolaroid() {
-	if (_doc) {
-		_polaroidIn = _polaroidOut = QRect(0, 0, _avail.width(), _avail.height() - st::medviewBottomBar);
-		int32 minus1 = width() - _delete.x(), minus2 = _overview.x() + st::medviewHeaderFont->m.width(_header) - st::medviewOverview.width;
-		if (minus2 > minus1) minus1 = minus2;
-
-		int32 dateWidth = st::medviewDateFont->m.width(_dateText), maxWidth = width() - 2 * minus1;
-		if (_from) {
-			int32 nameWidth = _fromName.maxWidth();
-			if (maxWidth < dateWidth) {
-				maxWidth = dateWidth;
-			}
-			if (nameWidth > maxWidth) {
-				nameWidth = maxWidth;
-			}
-			_nameNav = QRect((_avail.width() - nameWidth) / 2, _avail.y() + _avail.height() - ((st::medviewPolaroid.bottom() + st::medviewBottomBar) / 2) + st::medviewNameTop, nameWidth, st::medviewNameFont->height);
-			_dateNav = QRect((_avail.width() - dateWidth) / 2, _avail.y() + _avail.height() - ((st::medviewPolaroid.bottom() + st::medviewBottomBar) / 2) + st::medviewDateTop, dateWidth, st::medviewDateFont->height);
-		} else {
-			_nameNav = QRect(_avail.x() - 1, _avail.y() - 1, 0, 0);
-			_dateNav = QRect((_avail.width() - dateWidth) / 2, _avail.y() + _avail.height() - ((st::medviewPolaroid.bottom() + st::medviewBottomBar) / 2) + ((st::medviewNameTop + st::medviewDateTop) / 2), dateWidth, st::medviewDateFont->height);
+			_headerText = lng_mediaview_n_of_count(lt_n, QString::number(index + 1), lt_count, QString::number(count));
 		}
 	} else {
-		int32 pminw = qMin(st::medviewPolaroidMin.width(), int(_avail.width() - 2 * st::medviewNavBarWidth));
-
-		int32 pl = _x - st::medviewPolaroid.left(), plw = st::medviewPolaroid.left();
-		if (pl < st::medviewNavBarWidth) pl = st::medviewNavBarWidth;
-		int32 pr = _x + _w + st::medviewPolaroid.right(), prw = st::medviewPolaroid.right();
-		if (pr > _avail.width() - st::medviewNavBarWidth) pr = _avail.width() - st::medviewNavBarWidth;
-
-		if (_w + st::medviewPolaroid.left() + st::medviewPolaroid.right() < pminw) {
-			pl = (_avail.width() - pminw) / 2;
-			plw = _x - pl;
-			pr = pl + pminw;
-			prw = pr - (_x + _w);
+		if (_doc) {
+			_headerText = _doc->name.isEmpty() ? lang(lng_mediaview_doc_image) : _doc->name;
+		} else if (_user) {
+			_headerText = lang(lng_mediaview_profile_photo);
+		} else if (_peer) {
+			_headerText = lang(lng_mediaview_group_photo);
+		} else {
+			_headerText = lang(lng_mediaview_single_photo);
 		}
-
-		int32 pminh = qMin(st::medviewPolaroidMin.height(), int(_avail.height() - st::medviewBottomBar));
-
-		int32 pt = _y - st::medviewPolaroid.top(), pth = st::medviewPolaroid.top();
-		if (pt < 0) pt = 0;
-		int32 pb = _y + _h + st::medviewPolaroid.bottom(), pbh = st::medviewPolaroid.bottom();
-		if (pb > _avail.height() - st::medviewBottomBar) pb = _avail.height() - st::medviewBottomBar;
-
-		if (_h + st::medviewPolaroid.top() + st::medviewPolaroid.bottom() < pminh) {
-			pt = (_avail.height() - st::medviewBottomBar - pminh) / 2;
-			pth = _y - pt;
-			pb = pt + pminh;
-			pbh = pb - (_y + _h);
-		}
-
-		_polaroidOut = QRect(pl, pt, pr - pl, pb - pt);
-		_polaroidIn = QRect(pl + plw, pt + pth, pr - pl - prw - plw, pb - pt - pbh - pth);
-
-		int32 nameWidth = _fromName.maxWidth(), maxWidth = _polaroidOut.width() - st::medviewPolaroid.left() - st::medviewPolaroid.right(), dateWidth = st::medviewDateFont->m.width(_dateText);
-		if (nameWidth > maxWidth) {
-			nameWidth = maxWidth;
-		}
-		_nameNav = QRect(_polaroidIn.x() + ((_polaroidIn.width() - nameWidth) / 2), _polaroidOut.y() + _polaroidOut.height() - st::medviewPolaroid.bottom() + st::medviewNameTop, nameWidth, st::medviewNameFont->height);
-		_dateNav = QRect(_polaroidIn.x() + ((_polaroidIn.width() - dateWidth) / 2), _polaroidOut.y() + _polaroidOut.height() - st::medviewPolaroid.bottom() + st::medviewDateTop, dateWidth, st::medviewDateFont->height);
 	}
+	_headerHasLink = (_overview != OverviewCount) && _history;
+	int32 hwidth = st::mvThickFont->m.width(_headerText);
+	if (hwidth > width() / 3) {
+		hwidth = width() / 3;
+		_headerText = st::mvThickFont->m.elidedText(_headerText, Qt::ElideMiddle, hwidth);
+	}
+	_headerNav = rtlrect(st::mvTextLeft, height() - st::mvHeaderTop, hwidth, st::mvThickFont->height, width());
 }
+//
+//void MediaView::updatePolaroid() {
+//	if (_doc) {
+//		_polaroidIn = _polaroidOut = QRect(0, 0, _avail.width(), _avail.height() - st::medviewBottomBar);
+//		int32 minus1 = width() - _delete.x(), minus2 = _overview.x() + st::medviewHeaderFont->m.width(_header) - st::medviewOverview.width;
+//		if (minus2 > minus1) minus1 = minus2;
+//
+//		int32 dateWidth = st::medviewDateFont->m.width(_dateText), maxWidth = width() - 2 * minus1;
+//		if (_from) {
+//			int32 nameWidth = _fromName.maxWidth();
+//			if (maxWidth < dateWidth) {
+//				maxWidth = dateWidth;
+//			}
+//			if (nameWidth > maxWidth) {
+//				nameWidth = maxWidth;
+//			}
+//			_nameNav = QRect((_avail.width() - nameWidth) / 2, _avail.y() + _avail.height() - ((st::medviewPolaroid.bottom() + st::medviewBottomBar) / 2) + st::medviewNameTop, nameWidth, st::medviewNameFont->height);
+//			_dateNav = QRect((_avail.width() - dateWidth) / 2, _avail.y() + _avail.height() - ((st::medviewPolaroid.bottom() + st::medviewBottomBar) / 2) + st::medviewDateTop, dateWidth, st::medviewDateFont->height);
+//		} else {
+//			_nameNav = QRect(_avail.x() - 1, _avail.y() - 1, 0, 0);
+//			_dateNav = QRect((_avail.width() - dateWidth) / 2, _avail.y() + _avail.height() - ((st::medviewPolaroid.bottom() + st::medviewBottomBar) / 2) + ((st::medviewNameTop + st::medviewDateTop) / 2), dateWidth, st::medviewDateFont->height);
+//		}
+//	} else {
+//		int32 pminw = qMin(st::medviewPolaroidMin.width(), int(_avail.width() - 2 * st::medviewNavBarWidth));
+//
+//		int32 pl = _x - st::medviewPolaroid.left(), plw = st::medviewPolaroid.left();
+//		if (pl < st::medviewNavBarWidth) pl = st::medviewNavBarWidth;
+//		int32 pr = _x + _w + st::medviewPolaroid.right(), prw = st::medviewPolaroid.right();
+//		if (pr > _avail.width() - st::medviewNavBarWidth) pr = _avail.width() - st::medviewNavBarWidth;
+//
+//		if (_w + st::medviewPolaroid.left() + st::medviewPolaroid.right() < pminw) {
+//			pl = (_avail.width() - pminw) / 2;
+//			plw = _x - pl;
+//			pr = pl + pminw;
+//			prw = pr - (_x + _w);
+//		}
+//
+//		int32 pminh = qMin(st::medviewPolaroidMin.height(), int(_avail.height() - st::medviewBottomBar));
+//
+//		int32 pt = _y - st::medviewPolaroid.top(), pth = st::medviewPolaroid.top();
+//		if (pt < 0) pt = 0;
+//		int32 pb = _y + _h + st::medviewPolaroid.bottom(), pbh = st::medviewPolaroid.bottom();
+//		if (pb > _avail.height() - st::medviewBottomBar) pb = _avail.height() - st::medviewBottomBar;
+//
+//		if (_h + st::medviewPolaroid.top() + st::medviewPolaroid.bottom() < pminh) {
+//			pt = (_avail.height() - st::medviewBottomBar - pminh) / 2;
+//			pth = _y - pt;
+//			pb = pt + pminh;
+//			pbh = pb - (_y + _h);
+//		}
+//
+//		_polaroidOut = QRect(pl, pt, pr - pl, pb - pt);
+//		_polaroidIn = QRect(pl + plw, pt + pth, pr - pl - prw - plw, pb - pt - pbh - pth);
+//
+//		int32 nameWidth = _fromName.maxWidth(), maxWidth = _polaroidOut.width() - st::medviewPolaroid.left() - st::medviewPolaroid.right(), dateWidth = st::medviewDateFont->m.width(_dateText);
+//		if (nameWidth > maxWidth) {
+//			nameWidth = maxWidth;
+//		}
+//		_nameNav = QRect(_polaroidIn.x() + ((_polaroidIn.width() - nameWidth) / 2), _polaroidOut.y() + _polaroidOut.height() - st::medviewPolaroid.bottom() + st::medviewNameTop, nameWidth, st::medviewNameFont->height);
+//		_dateNav = QRect(_polaroidIn.x() + ((_polaroidIn.width() - dateWidth) / 2), _polaroidOut.y() + _polaroidOut.height() - st::medviewPolaroid.bottom() + st::medviewDateTop, dateWidth, st::medviewDateFont->height);
+//	}
+//}
 
 QColor MediaView::overColor(const QColor &a, float64 ca, const QColor &b, float64 cb) {
 	QColor res;
diff --git a/Telegram/SourceFiles/mediaview.h b/Telegram/SourceFiles/mediaview.h
index 41ac66f48..79a02a72e 100644
--- a/Telegram/SourceFiles/mediaview.h
+++ b/Telegram/SourceFiles/mediaview.h
@@ -17,6 +17,8 @@ Copyright (c) 2014 John Preston, https://desktop.telegram.org
 */
 #pragma once
 
+#include "dropdown.h"
+
 class MediaView : public TWidget, public RPCSender, public Animated {
 	Q_OBJECT
 
@@ -41,24 +43,38 @@ public:
 
 	void showPhoto(PhotoData *photo, HistoryItem *context);
 	void showPhoto(PhotoData *photo, PeerData *context);
-	void showDocument(DocumentData *doc, QPixmap pix, HistoryItem *context);
+	void showDocument(DocumentData *doc, HistoryItem *context);
 	void moveToScreen();
-	void moveToPhoto(int32 delta);
-	void preloadPhotos(int32 delta);
+	void moveToNext(int32 delta);
+	void preloadData(int32 delta);
+
+	void leaveToChildEvent(QEvent *e) { // e -- from enterEvent() of child TWidget
+		updateOverState(OverNone);
+	}
+	void enterFromChildEvent(QEvent *e) { // e -- from leaveEvent() of child TWidget
+		updateOver(mapFromGlobal(QCursor::pos()));
+	}
 
 	void mediaOverviewUpdated(PeerData *peer);
 	void changingMsgId(HistoryItem *row, MsgId newId);
 	void updateControls();
+	void updateDropdown();
 
 	bool animStep(float64 dt);
 
 	void showSaveMsgFile();
+	void close();
+
+	void activateControls();
 
 	~MediaView();
 
 public slots:
 
-	void onClose();
+	void onHideControls(bool force = false);
+	void onDropdownHiding();
+
+	void onToMessage();
 	void onSave();
 	void onDownload();
 	void onShowInFolder();
@@ -69,6 +85,8 @@ public slots:
 	void onMenuDestroy(QObject *obj);
 	void receiveMouse();
 
+	void onDropdown();
+
 	void onCheckActive();
 	void onTouchTimer();
 
@@ -76,29 +94,31 @@ public slots:
 
 private:
 
-	void showPhoto(PhotoData *photo);
-	void loadPhotosBack();
+	void displayPhoto(PhotoData *photo);
+	void displayDocument(DocumentData *doc, HistoryItem *item);
+	void findCurrent();
+	void loadBack();
 
 	void photosLoaded(History *h, const MTPmessages_Messages &msgs, mtpRequestId req);
 	void userPhotosLoaded(UserData *u, const MTPphotos_Photos &photos, mtpRequestId req);
+	void filesLoaded(History *h, const MTPmessages_Messages &msgs, mtpRequestId req);
 
 	void updateHeader();
-	void updatePolaroid();
 	void snapXY();
 
 	QBrush _transparentBrush;
 
-	QTimer _timer;
 	PhotoData *_photo;
 	DocumentData *_doc;
-	QRect _avail, _leftNav, _rightNav, _bottomBar, _nameNav, _dateNav, _polaroidOut, _polaroidIn;
-	int32 _availBottom;
-	bool _leftNavVisible, _rightNavVisible;
+	MediaOverviewType _overview;
+	QRect _closeNav, _leftNav, _rightNav, _headerNav, _nameNav, _dateNav, _saveNav, _moreNav;
+	bool _leftNavVisible, _rightNavVisible, _saveVisible, _headerHasLink;
 	QString _dateText;
+	QString _headerText;
 
 	uint64 _animStarted;
 
-	int32 _maxWidth, _maxHeight, _width, _x, _y, _w, _h, _xStart, _yStart;
+	int32 _width, _x, _y, _w, _h, _xStart, _yStart;
 	int32 _zoom; // < 0 - out, 0 - none, > 0 - in
 	float64 _zoomToScreen; // for documents
 	QPoint _mStart;
@@ -107,14 +127,24 @@ private:
 	QPixmap _current;
 	int32 _full; // -1 - thumb, 0 - medium, 1 - full
 
-	History *_history; // if conversation photos overview
-	PeerData *_peer;
-	UserData *_user, *_from; // if user profile photos overview
-	Text _fromName;
-	int32 _index; // index in photos array, -1 if just photo
-	MsgId _msgid; // msgId of current photo
+	style::sprite _docIcon;
+	QString _docName, _docSize;
+	int32 _docNameWidth, _docSizeWidth;
+	QRect _docRect;
+	int32 _docThumbx, _docThumby, _docThumbw;
+	uint64 _docRadialFirst, _docRadialStart, _docRadialLast;
+	QPen _docRadialPen;
+	anim::fvalue a_docRadial, a_docRadialStart;
 
-	QString _header;
+	History *_history; // if conversation photos or files overview
+	PeerData *_peer;
+	UserData *_user; // if user profile photos overview
+	
+	UserData *_from;
+	Text _fromName;
+
+	int32 _index; // index in photos or files array, -1 if just photo
+	MsgId _msgid; // msgId of current photo or file
 
 	mtpRequestId _loadRequest;
 
@@ -122,14 +152,33 @@ private:
 		OverNone,
 		OverLeftNav,
 		OverRightNav,
+		OverClose,
+		OverHeader,
 		OverName,
-		OverDate
+		OverDate,
+		OverSave,
+		OverMore,
 	};
 	OverState _over, _down;
-	QPoint _lastAction;
+	QPoint _lastAction, _lastMouseMovePos;
+	bool _ignoringDropdown;
+
+	enum ControlsState {
+		ControlsShowing,
+		ControlsShown,
+		ControlsHiding,
+		ControlsHidden,
+	};
+	ControlsState _controlsState;
+	uint64 _controlsAnimStarted;
+	QTimer _controlsHideTimer;
+	anim::fvalue a_cOpacity;
 
-	IconedButton _close, _save, _forward, _delete, _overview;
 	ContextMenu *_menu;
+	Dropdown _dropdown;
+	IconedButton *_btnToMessage, *_btnShowInFolder, *_btnSaveAs, *_btnCopy, *_btnForward, *_btnDelete, *_btnViewAll;
+	QList<IconedButton*> _btns;
+
 	bool _receiveMouse;
 
 	bool _touchPress, _touchMove, _touchRightButton;
diff --git a/Telegram/SourceFiles/pspecific_wnd.cpp b/Telegram/SourceFiles/pspecific_wnd.cpp
index 1ec5d4231..320b3eaa5 100644
--- a/Telegram/SourceFiles/pspecific_wnd.cpp
+++ b/Telegram/SourceFiles/pspecific_wnd.cpp
@@ -159,6 +159,7 @@ namespace {
 				QPainter p(&cornersImage);
 				p.drawPixmap(QPoint(0, 0), App::sprite(), topLeft);
 			}
+			if (rtl()) cornersImage = cornersImage.mirrored(true, false);
 			uchar *bits = cornersImage.bits();
 			if (bits) {
 				for (
diff --git a/Telegram/SourceFiles/structs.cpp b/Telegram/SourceFiles/structs.cpp
index 0d19d0c5f..f797f9336 100644
--- a/Telegram/SourceFiles/structs.cpp
+++ b/Telegram/SourceFiles/structs.cpp
@@ -470,7 +470,7 @@ void DocumentOpenLink::onClick(Qt::MouseButton button) const {
 				if (reader.supportsAnimation() && reader.imageCount() > 1 && App::hoveredLinkItem()) {
 					startGif(App::hoveredLinkItem(), already);
 				} else {
-					App::wnd()->showDocument(data, QPixmap::fromImage(App::readImage(already, 0, false), Qt::ColorOnly), App::hoveredLinkItem());
+					App::wnd()->showDocument(data, App::hoveredLinkItem());
 				}
 			} else {
 				psOpenFile(already);
diff --git a/Telegram/SourceFiles/window.cpp b/Telegram/SourceFiles/window.cpp
index 21450c571..8c0724372 100644
--- a/Telegram/SourceFiles/window.cpp
+++ b/Telegram/SourceFiles/window.cpp
@@ -739,9 +739,9 @@ void Window::showPhoto(PhotoData *photo, PeerData *peer) {
 	_mediaView->setFocus();
 }
 
-void Window::showDocument(DocumentData *doc, QPixmap pix, HistoryItem *item) {
+void Window::showDocument(DocumentData *doc, HistoryItem *item) {
 	layerHidden();
-	_mediaView->showDocument(doc, pix, item);
+	_mediaView->showDocument(doc, item);
 	_mediaView->activateWindow();
 	_mediaView->setFocus();
 }
diff --git a/Telegram/SourceFiles/window.h b/Telegram/SourceFiles/window.h
index 668a433fb..595379c44 100644
--- a/Telegram/SourceFiles/window.h
+++ b/Telegram/SourceFiles/window.h
@@ -176,7 +176,7 @@ public:
 	void showPhoto(const PhotoLink *lnk, HistoryItem *item = 0);
 	void showPhoto(PhotoData *photo, HistoryItem *item);
 	void showPhoto(PhotoData *photo, PeerData *item);
-	void showDocument(DocumentData *doc, QPixmap pix, HistoryItem *item);
+	void showDocument(DocumentData *doc, HistoryItem *item);
 	void showLayer(LayeredWidget *w, bool fast = false);
 	void replaceLayer(LayeredWidget *w);
 	void hideLayer(bool fast = false);