diff --git a/Telegram/Resources/style.txt b/Telegram/Resources/style.txt
index bc3a447201..81fc1f8e14 100644
--- a/Telegram/Resources/style.txt
+++ b/Telegram/Resources/style.txt
@@ -1940,6 +1940,9 @@ stickerIconSelColor: #58b2ed;
 stickerIconLeft: sprite(342px, 72px, 40px, 1px);
 stickerIconRight: sprite(342px, 73px, 40px, 1px);
 stickerIconMove: 400;
+stickerPreviewDuration: 150;
+stickerPreviewBg: #FFFFFFB0;
+stickerPreviewMin: 0.1;
 
 verifiedCheckProfile: sprite(285px, 235px, 18px, 18px);
 verifiedCheckProfilePos: point(7px, 6px);
diff --git a/Telegram/SourceFiles/app.cpp b/Telegram/SourceFiles/app.cpp
index c478c0ff63..81ba97b9d4 100644
--- a/Telegram/SourceFiles/app.cpp
+++ b/Telegram/SourceFiles/app.cpp
@@ -2805,79 +2805,4 @@ namespace App {
 
 	WallPapers gServerBackgrounds;
 
-	void sendBotCommand(const QString &cmd, MsgId replyTo) {
-		if (MainWidget *m = main()) m->sendBotCommand(cmd, replyTo);
-	}
-
-	void insertBotCommand(const QString &cmd) {
-		if (MainWidget *m = main()) m->insertBotCommand(cmd);
-	}
-
-	void searchByHashtag(const QString &tag, PeerData *inPeer) {
-		if (MainWidget *m = main()) m->searchMessages(tag + ' ', (inPeer && inPeer->isChannel()) ? inPeer : 0);
-	}
-
-	void openPeerByName(const QString &username, bool toProfile, const QString &startToken) {
-		if (MainWidget *m = main()) m->openPeerByName(username, toProfile, startToken);
-	}
-
-	void joinGroupByHash(const QString &hash) {
-		if (MainWidget *m = main()) m->joinGroupByHash(hash);
-	}
-
-	void stickersBox(const QString &name) {
-		if (MainWidget *m = main()) m->stickersBox(MTP_inputStickerSetShortName(MTP_string(name)));
-	}
-
-	void openLocalUrl(const QString &url) {
-		if (MainWidget *m = main()) m->openLocalUrl(url);
-	}
-
-	bool forward(const PeerId &peer, ForwardWhatMessages what) {
-		if (MainWidget *m = main()) return m->onForward(peer, what);
-		return false;
-	}
-
-	void removeDialog(History *history) {
-		if (MainWidget *m = main()) m->removeDialog(history);
-	}
-
-	void showSettings() {
-		if (Window *win = wnd()) win->showSettings();
-	}
-
-	void showLayer(LayeredWidget *w, bool forceFast) {
-		if (Window *win = wnd()) win->showLayer(w, forceFast);
-	}
-
-	void replaceLayer(LayeredWidget *w) {
-		if (Window *win = wnd()) win->replaceLayer(w);
-	}
-
-	void showLayerLast(LayeredWidget *w) {
-		if (Window *win = wnd()) win->showLayerLast(w);
-	}
-
-}
-
-namespace Notify {
-
-	void userIsBotChanged(UserData *user) {
-		if (MainWidget *m = App::main()) {
-			m->notifyUserIsBotChanged(user);
-		}
-	}
-
-	void botCommandsChanged(UserData *user) {
-		if (MainWidget *m = App::main()) {
-			m->notifyBotCommandsChanged(user);
-		}
-	}
-
-	void migrateUpdated(PeerData *peer) {
-		if (MainWidget *m = App::main()) {
-			m->notifyMigrateUpdated(peer);
-		}
-	}
-
 }
diff --git a/Telegram/SourceFiles/app.h b/Telegram/SourceFiles/app.h
index 506eca63f7..1402a7e056 100644
--- a/Telegram/SourceFiles/app.h
+++ b/Telegram/SourceFiles/app.h
@@ -80,13 +80,6 @@ enum RoundCorners {
 	RoundCornersCount
 };
 
-enum ForwardWhatMessages {
-	ForwardSelectedMessages,
-	ForwardContextMessage,
-	ForwardPressedMessage,
-	ForwardPressedLinkMessage
-};
-
 class LayeredWidget;
 
 namespace App {
@@ -233,7 +226,7 @@ namespace App {
 	bool quiting();
 	void setQuiting();
 
-    QImage readImage(QByteArray data, QByteArray *format = 0, bool opaque = true, bool *animated = 0);
+	QImage readImage(QByteArray data, QByteArray *format = 0, bool opaque = true, bool *animated = 0);
 	QImage readImage(const QString &file, QByteArray *format = 0, bool opaque = true, bool *animated = 0, QByteArray *content = 0);
 
 	void regVideoItem(VideoData *data, HistoryItem *item);
@@ -300,28 +293,6 @@ namespace App {
 	typedef QList<WallPaper> WallPapers;
 	DeclareSetting(WallPapers, ServerBackgrounds);
 
-	void sendBotCommand(const QString &cmd, MsgId replyTo = 0);
-	void insertBotCommand(const QString &cmd);
-	void searchByHashtag(const QString &tag, PeerData *inPeer);
-	void openPeerByName(const QString &username, bool toProfile = false, const QString &startToken = QString());
-	void joinGroupByHash(const QString &hash);
-	void stickersBox(const QString &name);
-	void openLocalUrl(const QString &url);
-	bool forward(const PeerId &peer, ForwardWhatMessages what);
-	void removeDialog(History *history);
-	void showSettings();
-	void showLayer(LayeredWidget *w, bool forceFast = false);
-	void replaceLayer(LayeredWidget *w);
-	void showLayerLast(LayeredWidget *w);
-
-};
-
-namespace Notify {
-
-	void userIsBotChanged(UserData *user);
-	void botCommandsChanged(UserData *user);
-	void migrateUpdated(PeerData *peer);
-
 };
 
 inline int32 stickersCountHash(bool checkOfficial = false) {
@@ -344,3 +315,5 @@ inline int32 stickersCountHash(bool checkOfficial = false) {
 	}
 	return (!checkOfficial || (!foundBad && foundOfficial)) ? int32(acc & 0x7FFFFFFF) : 0;
 }
+
+#include "facades.h"
diff --git a/Telegram/SourceFiles/dropdown.cpp b/Telegram/SourceFiles/dropdown.cpp
index 3655369f3a..20071440c3 100644
--- a/Telegram/SourceFiles/dropdown.cpp
+++ b/Telegram/SourceFiles/dropdown.cpp
@@ -1200,7 +1200,8 @@ StickerPanInner::StickerPanInner() : TWidget()
 , _top(0)
 , _selected(-1)
 , _pressedSel(-1)
-, _settings(this, lang(lng_stickers_you_have)) {
+, _settings(this, lang(lng_stickers_you_have))
+, _previewShown(false) {
 	setMaxHeight(st::emojiPanMaxHeight);
 
 	setMouseTracking(true);
@@ -1210,6 +1211,9 @@ StickerPanInner::StickerPanInner() : TWidget()
 	connect(App::wnd(), SIGNAL(imageLoaded()), this, SLOT(update()));
 	connect(&_settings, SIGNAL(clicked()), this, SLOT(onSettings()));
 	
+	_previewTimer.setSingleShot(true);
+	connect(&_previewTimer, SIGNAL(timeout()), this, SLOT(onPreview()));
+
 	refreshStickers();
 }
 
@@ -1349,15 +1353,23 @@ void StickerPanInner::mousePressEvent(QMouseEvent *e) {
 	updateSelected();
 
 	_pressedSel = _selected;
+	_previewTimer.start(QApplication::startDragTime());
 }
 
 void StickerPanInner::mouseReleaseEvent(QMouseEvent *e) {
+	_previewTimer.stop();
+
 	int32 pressed = _pressedSel;
 	_pressedSel = -1;
 
 	_lastMousePos = e->globalPos();
 	updateSelected();
 
+	if (_previewShown) {
+		_previewShown = false;
+		return;
+	}
+
 	if (_selected < 0 || _selected != pressed) return;
 	if (_selected >= MatrixRowShift * _sets.size()) {
 		return;
@@ -1638,7 +1650,7 @@ void StickerPanInner::refreshPanels(QVector<EmojiPanel*> &panels) {
 }
 
 void StickerPanInner::updateSelected() {
-	if (_pressedSel >= 0) return;
+	if (_pressedSel >= 0 && !_previewShown) return;
 
 	int32 selIndex = -1;
 	QPoint p(mapFromGlobal(_lastMousePos));
@@ -1715,6 +1727,12 @@ void StickerPanInner::updateSelected() {
 		}
 	}
 	_selected = selIndex;
+	if (_pressedSel >= 0 && _selected >= 0 && _pressedSel != _selected) {
+		_pressedSel = _selected;
+		if (newSel >= 0 && xNewSel < 0) {
+			Ui::showStickerPreview(_sets.at(newSelTab).pack.at(newSel % MatrixRowShift));
+		}
+	}
 	if (startanim) anim::start(this);
 }
 
@@ -1722,6 +1740,16 @@ void StickerPanInner::onSettings() {
 	App::showLayer(new StickersBox());
 }
 
+void StickerPanInner::onPreview() {
+	if (_pressedSel >= 0 && _pressedSel < MatrixRowShift * _sets.size()) {
+		int tab = (_pressedSel / MatrixRowShift), sel = _pressedSel % MatrixRowShift;
+		if (sel < _sets.at(tab).pack.size()) {
+			Ui::showStickerPreview(_sets.at(tab).pack.at(sel));
+			_previewShown = true;
+		}
+	}
+}
+
 bool StickerPanInner::animStep(float64 ms) {
 	uint64 now = getms();
 	QRegion toUpdate;
diff --git a/Telegram/SourceFiles/dropdown.h b/Telegram/SourceFiles/dropdown.h
index 1d6e77e919..9a64fce257 100644
--- a/Telegram/SourceFiles/dropdown.h
+++ b/Telegram/SourceFiles/dropdown.h
@@ -349,6 +349,7 @@ public slots:
 
 	void updateSelected();
 	void onSettings();
+	void onPreview();
 
 signals:
 
@@ -394,6 +395,9 @@ private:
 	QPoint _lastMousePos;
 
 	LinkButton _settings;
+
+	QTimer _previewTimer;
+	bool _previewShown;
 };
 
 class EmojiPanel : public TWidget {
diff --git a/Telegram/SourceFiles/facades.cpp b/Telegram/SourceFiles/facades.cpp
new file mode 100644
index 0000000000..caa7fb9de1
--- /dev/null
+++ b/Telegram/SourceFiles/facades.cpp
@@ -0,0 +1,109 @@
+/*
+This file is part of Telegram Desktop,
+the official desktop version of Telegram messaging app, see https://telegram.org
+
+Telegram Desktop is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+It is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+In addition, as a special exception, the copyright holders give permission
+to link the code of portions of this program with the OpenSSL library.
+
+Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
+Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
+*/
+#include "stdafx.h"
+
+#include "window.h"
+#include "mainwidget.h"
+
+namespace App {
+
+	void sendBotCommand(const QString &cmd, MsgId replyTo) {
+		if (MainWidget *m = main()) m->sendBotCommand(cmd, replyTo);
+	}
+
+	void insertBotCommand(const QString &cmd) {
+		if (MainWidget *m = main()) m->insertBotCommand(cmd);
+	}
+
+	void searchByHashtag(const QString &tag, PeerData *inPeer) {
+		if (MainWidget *m = main()) m->searchMessages(tag + ' ', (inPeer && inPeer->isChannel()) ? inPeer : 0);
+	}
+
+	void openPeerByName(const QString &username, bool toProfile, const QString &startToken) {
+		if (MainWidget *m = main()) m->openPeerByName(username, toProfile, startToken);
+	}
+
+	void joinGroupByHash(const QString &hash) {
+		if (MainWidget *m = main()) m->joinGroupByHash(hash);
+	}
+
+	void stickersBox(const QString &name) {
+		if (MainWidget *m = main()) m->stickersBox(MTP_inputStickerSetShortName(MTP_string(name)));
+	}
+
+	void openLocalUrl(const QString &url) {
+		if (MainWidget *m = main()) m->openLocalUrl(url);
+	}
+
+	bool forward(const PeerId &peer, ForwardWhatMessages what) {
+		if (MainWidget *m = main()) return m->onForward(peer, what);
+		return false;
+	}
+
+	void removeDialog(History *history) {
+		if (MainWidget *m = main()) m->removeDialog(history);
+	}
+
+	void showSettings() {
+		if (Window *win = wnd()) win->showSettings();
+	}
+
+	void showLayer(LayeredWidget *widget, bool forceFast) {
+		if (Window *w = wnd()) w->showLayer(widget, forceFast);
+	}
+
+	void replaceLayer(LayeredWidget *widget) {
+		if (Window *w = wnd()) w->replaceLayer(widget);
+	}
+
+	void showLayerLast(LayeredWidget *widget) {
+		if (Window *w = wnd()) w->showLayerLast(widget);
+	}
+
+}
+
+namespace Ui {
+
+	void showStickerPreview(DocumentData *sticker) {
+		if (MainWidget *m = App::main()) m->ui_showStickerPreview(sticker);
+	}
+
+	void hideStickerPreview() {
+		if (MainWidget *m = App::main()) m->ui_hideStickerPreview();
+	}
+
+}
+
+namespace Notify {
+
+	void userIsBotChanged(UserData *user) {
+		if (MainWidget *m = App::main()) m->notifyUserIsBotChanged(user);
+	}
+
+	void botCommandsChanged(UserData *user) {
+		if (MainWidget *m = App::main()) m->notifyBotCommandsChanged(user);
+	}
+
+	void migrateUpdated(PeerData *peer) {
+		if (MainWidget *m = App::main()) m->notifyMigrateUpdated(peer);
+	}
+
+}
diff --git a/Telegram/SourceFiles/facades.h b/Telegram/SourceFiles/facades.h
new file mode 100644
index 0000000000..afbbb8e079
--- /dev/null
+++ b/Telegram/SourceFiles/facades.h
@@ -0,0 +1,56 @@
+/*
+This file is part of Telegram Desktop,
+the official desktop version of Telegram messaging app, see https://telegram.org
+
+Telegram Desktop is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+It is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+In addition, as a special exception, the copyright holders give permission
+to link the code of portions of this program with the OpenSSL library.
+
+Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
+Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
+*/
+#pragma once
+
+class LayeredWidget;
+
+namespace App {
+
+	void sendBotCommand(const QString &cmd, MsgId replyTo = 0);
+	void insertBotCommand(const QString &cmd);
+	void searchByHashtag(const QString &tag, PeerData *inPeer);
+	void openPeerByName(const QString &username, bool toProfile = false, const QString &startToken = QString());
+	void joinGroupByHash(const QString &hash);
+	void stickersBox(const QString &name);
+	void openLocalUrl(const QString &url);
+	bool forward(const PeerId &peer, ForwardWhatMessages what);
+	void removeDialog(History *history);
+	void showSettings();
+	void showLayer(LayeredWidget *w, bool forceFast = false);
+	void replaceLayer(LayeredWidget *w);
+	void showLayerLast(LayeredWidget *w);
+
+};
+
+namespace Ui { // it doesn't allow me to use UI :(
+
+	void showStickerPreview(DocumentData *sticker);
+	void hideStickerPreview();
+
+};
+
+namespace Notify {
+
+	void userIsBotChanged(UserData *user);
+	void botCommandsChanged(UserData *user);
+	void migrateUpdated(PeerData *peer);
+
+};
diff --git a/Telegram/SourceFiles/layerwidget.cpp b/Telegram/SourceFiles/layerwidget.cpp
index 35957e5324..85f0fe6644 100644
--- a/Telegram/SourceFiles/layerwidget.cpp
+++ b/Telegram/SourceFiles/layerwidget.cpp
@@ -27,8 +27,12 @@ Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
 #include "mainwidget.h"
 #include "gui/filedialog.h"
 
-BackgroundWidget::BackgroundWidget(QWidget *parent, LayeredWidget *w) : QWidget(parent), w(w),
-aBackground(0), aBackgroundFunc(anim::easeOutCirc), hiding(false), shadow(st::boxShadow) {
+BackgroundWidget::BackgroundWidget(QWidget *parent, LayeredWidget *w) : TWidget(parent)
+, w(w)
+, aBackground(0)
+, aBackgroundFunc(anim::easeOutCirc)
+, hiding(false)
+, shadow(st::boxShadow) {
 	w->setParent(this);
 	if (App::app()) App::app()->mtpPause();
 	setGeometry(0, 0, App::wnd()->width(), App::wnd()->height());
@@ -189,3 +193,115 @@ BackgroundWidget::~BackgroundWidget() {
 		(*i)->deleteLater();
 	}
 }
+
+StickerPreviewWidget::StickerPreviewWidget(QWidget *parent) : TWidget(parent)
+, a_shown(0, 0)
+, _a_shown(animFunc(this, &StickerPreviewWidget::animStep_shown))
+, _doc(0)
+, _cacheStatus(CacheNotLoaded) {
+	setAttribute(Qt::WA_TransparentForMouseEvents);
+}
+
+void StickerPreviewWidget::paintEvent(QPaintEvent *e) {
+	Painter p(this);
+	QRect r(e->rect());
+
+	const QPixmap &draw(currentImage());
+	uint32 w = draw.width() / cIntRetinaFactor(), h = draw.height() / cIntRetinaFactor();
+	if (_a_shown.animating()) {
+		float64 shown = a_shown.current();
+		p.setOpacity(shown);
+//		w = qMax(qRound(w * (st::stickerPreviewMin + ((1. - st::stickerPreviewMin) * shown)) / 2.) * 2 + int(w % 2), 1);
+//		h = qMax(qRound(h * (st::stickerPreviewMin + ((1. - st::stickerPreviewMin) * shown)) / 2.) * 2 + int(h % 2), 1);
+	}
+	p.fillRect(r, st::stickerPreviewBg);
+	p.drawPixmap((width() - w) / 2, (height() - h) / 2, draw);
+}
+
+void StickerPreviewWidget::resizeEvent(QResizeEvent *e) {
+	update();
+}
+
+bool StickerPreviewWidget::animStep_shown(float64 ms) {
+	float64 dt = ms / st::stickerPreviewDuration;
+	if (dt >= 1) {
+		a_shown.finish();
+		_a_shown.stop();
+		if (a_shown.current() < 0.5) hide();
+	} else {
+		a_shown.update(dt, anim::linear);
+	}
+	update();
+	return true;
+}
+
+void StickerPreviewWidget::showPreview(DocumentData *sticker) {
+	if (sticker && !sticker->sticker()) sticker = 0;
+	if (sticker) {
+		_cache = QPixmap();
+		if (isHidden() || _a_shown.animating()) {
+			if (isHidden()) show();
+			a_shown.start(1);
+			_a_shown.start();
+		} else {
+			update();
+		}
+	} else if (isHidden()) {
+		return;
+	} else {
+		a_shown.start(0);
+		_a_shown.start();
+	}
+	_doc = sticker;
+	_cacheStatus = CacheNotLoaded;
+}
+
+void StickerPreviewWidget::hidePreview() {
+	showPreview(0);
+}
+
+QSize StickerPreviewWidget::currentDimensions() const {
+	if (!_doc) return QSize(_cache.width() / cIntRetinaFactor(), _cache.height() / cIntRetinaFactor());
+
+	QSize result(qMax(_doc->dimensions.width(), 1), qMax(_doc->dimensions.height(), 1));
+	if (result.width() > st::maxStickerSize) {
+		result.setHeight(qMax(qRound((st::maxStickerSize * result.height()) / result.width()), 1));
+		result.setWidth(st::maxStickerSize);
+	}
+	if (result.height() > st::maxStickerSize) {
+		result.setWidth(qMax(qRound((st::maxStickerSize * result.width()) / result.height()), 1));
+		result.setHeight(st::maxStickerSize);
+	}
+	return result;
+}
+
+QPixmap StickerPreviewWidget::currentImage() const {
+	if (_doc && _cacheStatus != CacheLoaded) {
+		bool already = !_doc->already().isEmpty(), hasdata = !_doc->data.isEmpty();
+		if (!_doc->loader && _doc->status != FileFailed && !already && !hasdata) {
+			_doc->save(QString());
+		}
+		if (_doc->sticker()->img->isNull() && (already || hasdata)) {
+			if (already) {
+				_doc->sticker()->img = ImagePtr(_doc->already());
+			} else {
+				_doc->sticker()->img = ImagePtr(_doc->data);
+			}
+		}
+		if (_doc->sticker()->img->isNull()) {
+			if (_cacheStatus != CacheThumbLoaded) {
+				QSize s = currentDimensions();
+				_cache = _doc->thumb->pixBlurred(s.width(), s.height());
+				_cacheStatus = CacheThumbLoaded;
+			}
+		} else {
+			QSize s = currentDimensions();
+			_cache = _doc->sticker()->img->pix(s.width(), s.height());
+			_cacheStatus = CacheLoaded;
+		}
+	}
+	return _cache;
+}
+
+StickerPreviewWidget::~StickerPreviewWidget() {
+}
diff --git a/Telegram/SourceFiles/layerwidget.h b/Telegram/SourceFiles/layerwidget.h
index 61e06cf4b2..98d6eb3b32 100644
--- a/Telegram/SourceFiles/layerwidget.h
+++ b/Telegram/SourceFiles/layerwidget.h
@@ -57,7 +57,7 @@ signals:
 
 };
 
-class BackgroundWidget : public QWidget, public Animated {
+class BackgroundWidget : public TWidget, public Animated {
 	Q_OBJECT
 
 public:
@@ -104,3 +104,39 @@ private:
 
 	BoxShadow shadow;
 };
+
+class StickerPreviewWidget : public TWidget {
+	Q_OBJECT
+
+public:
+
+	StickerPreviewWidget(QWidget *parent);
+
+	void paintEvent(QPaintEvent *e);
+	void resizeEvent(QResizeEvent *e);
+
+	bool animStep_shown(float64 ms);
+
+	void showPreview(DocumentData *sticker);
+	void hidePreview();
+
+	~StickerPreviewWidget();
+
+private:
+
+	QSize currentDimensions() const;
+	QPixmap currentImage() const;
+
+	anim::fvalue a_shown;
+	Animation _a_shown;
+	DocumentData *_doc;
+
+	enum CacheStatus {
+		CacheNotLoaded,
+		CacheThumbLoaded,
+		CacheLoaded,
+	};
+	mutable CacheStatus _cacheStatus;
+	mutable QPixmap _cache;
+
+};
diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp
index b1bf35e831..b5dd08893b 100644
--- a/Telegram/SourceFiles/mainwidget.cpp
+++ b/Telegram/SourceFiles/mainwidget.cpp
@@ -395,6 +395,7 @@ MainWidget::MainWidget(Window *window) : TWidget(window)
 , _hider(0)
 , _peerInStack(0)
 , _msgIdInStack(0)
+, _stickerPreview(0)
 , _playerHeight(0)
 , _contentScrollAddToY(0)
 , _mediaType(this)
@@ -744,6 +745,20 @@ QPixmap MainWidget::grabTopBar() {
 	}
 }
 
+void MainWidget::ui_showStickerPreview(DocumentData *sticker) {
+	if (!sticker || !sticker->sticker()) return;
+	if (!_stickerPreview) {
+		_stickerPreview = new StickerPreviewWidget(this);
+		resizeEvent(0);
+	}
+	_stickerPreview->showPreview(sticker);
+}
+
+void MainWidget::ui_hideStickerPreview() {
+	if (!_stickerPreview) return;
+	_stickerPreview->hidePreview();
+}
+
 void MainWidget::noHider(HistoryHider *destroyed) {
 	if (_hider == destroyed) {
 		_hider = 0;
@@ -2566,6 +2581,7 @@ void MainWidget::orderWidgets() {
 	dialogs.raise();
 	_mediaType.raise();
 	if (_hider) _hider->raise();
+	if (_stickerPreview) _stickerPreview->raise();
 }
 
 QRect MainWidget::historyRect() const {
@@ -2826,6 +2842,7 @@ void MainWidget::resizeEvent(QResizeEvent *e) {
 	_mediaType.moveToLeft(width() - _mediaType.width(), _playerHeight + st::topBarHeight);
 	if (profile) profile->setGeometry(history.geometry());
 	if (overview) overview->setGeometry(history.geometry());
+	if (_stickerPreview) _stickerPreview->setGeometry(rect());
 	_contentScrollAddToY = 0;
 }
 
diff --git a/Telegram/SourceFiles/mainwidget.h b/Telegram/SourceFiles/mainwidget.h
index 033196af83..c8cbc6965e 100644
--- a/Telegram/SourceFiles/mainwidget.h
+++ b/Telegram/SourceFiles/mainwidget.h
@@ -178,6 +178,8 @@ public:
 	}
 };
 
+class StickerPreviewWidget;
+
 class MainWidget : public TWidget, public RPCSender {
 	Q_OBJECT
 
@@ -412,6 +414,9 @@ public:
 	QPixmap grabTopBar();
 	QPixmap grabInner();
 
+	void ui_showStickerPreview(DocumentData *sticker);
+	void ui_hideStickerPreview();
+
 	~MainWidget();
 
 signals:
@@ -565,6 +570,8 @@ private:
 	PeerData *_peerInStack;
 	MsgId _msgIdInStack;
 
+	StickerPreviewWidget *_stickerPreview;
+
 	int32 _playerHeight;
 	int32 _contentScrollAddToY;
 
diff --git a/Telegram/SourceFiles/mtproto/mtpAuthKey.cpp b/Telegram/SourceFiles/mtproto/mtpAuthKey.cpp
new file mode 100644
index 0000000000..7e54022193
--- /dev/null
+++ b/Telegram/SourceFiles/mtproto/mtpAuthKey.cpp
@@ -0,0 +1,41 @@
+/*
+This file is part of Telegram Desktop,
+the official desktop version of Telegram messaging app, see https://telegram.org
+
+Telegram Desktop is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+It is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+In addition, as a special exception, the copyright holders give permission
+to link the code of portions of this program with the OpenSSL library.
+
+Full license: https://github.com/telegramdesktop/tdesktop/blob/master/LICENSE
+Copyright (c) 2014-2015 John Preston, https://desktop.telegram.org
+*/
+#include "stdafx.h"
+
+void aesEncrypt(const void *src, void *dst, uint32 len, void *key, void *iv) {
+	uchar aes_key[32], aes_iv[32];
+	memcpy(aes_key, key, 32);
+	memcpy(aes_iv, iv, 32);
+
+	AES_KEY aes;
+	AES_set_encrypt_key(aes_key, 256, &aes);
+	AES_ige_encrypt((const uchar*)src, (uchar*)dst, len, &aes, aes_iv, AES_ENCRYPT);
+}
+
+void aesDecrypt(const void *src, void *dst, uint32 len, void *key, void *iv) {
+	uchar aes_key[32], aes_iv[32];
+	memcpy(aes_key, key, 32);
+	memcpy(aes_iv, iv, 32);
+
+	AES_KEY aes;
+	AES_set_decrypt_key(aes_key, 256, &aes);
+	AES_ige_encrypt((const uchar*)src, (uchar*)dst, len, &aes, aes_iv, AES_DECRYPT);
+}
diff --git a/Telegram/SourceFiles/mtproto/mtpAuthKey.h b/Telegram/SourceFiles/mtproto/mtpAuthKey.h
index 372f1b3e97..1b0d71f7b2 100644
--- a/Telegram/SourceFiles/mtproto/mtpAuthKey.h
+++ b/Telegram/SourceFiles/mtproto/mtpAuthKey.h
@@ -112,15 +112,8 @@ inline bool operator==(const mtpAuthKey &a, const mtpAuthKey &b) {
 typedef QSharedPointer<mtpAuthKey> mtpAuthKeyPtr;
 typedef QVector<mtpAuthKeyPtr> mtpKeysMap;
 
-inline void aesEncrypt(const void *src, void *dst, uint32 len, void *key, void *iv) {
-	uchar aes_key[32], aes_iv[32];
-	memcpy(aes_key, key, 32);
-	memcpy(aes_iv, iv, 32);
-	
-	AES_KEY aes;
-	AES_set_encrypt_key(aes_key, 256, &aes);
-	AES_ige_encrypt((const uchar*)src, (uchar*)dst, len, &aes, aes_iv, AES_ENCRYPT);
-}
+void aesEncrypt(const void *src, void *dst, uint32 len, void *key, void *iv);
+void aesDecrypt(const void *src, void *dst, uint32 len, void *key, void *iv);
 
 inline void aesEncrypt(const void *src, void *dst, uint32 len, const mtpAuthKeyPtr &authKey, const MTPint128 &msgKey) {
 	MTPint256 aesKey, aesIV;
@@ -136,16 +129,6 @@ inline void aesEncryptLocal(const void *src, void *dst, uint32 len, const mtpAut
 	return aesEncrypt(src, dst, len, &aesKey, &aesIV);
 }
 
-inline void aesDecrypt(const void *src, void *dst, uint32 len, void *key, void *iv) {
-	uchar aes_key[32], aes_iv[32];
-	memcpy(aes_key, key, 32);
-	memcpy(aes_iv, iv, 32);
-	
-	AES_KEY aes;
-	AES_set_decrypt_key(aes_key, 256, &aes);
-	AES_ige_encrypt((const uchar*)src, (uchar*)dst, len, &aes, aes_iv, AES_DECRYPT);
-}
-
 inline void aesDecrypt(const void *src, void *dst, uint32 len, const mtpAuthKeyPtr &authKey, const MTPint128 &msgKey) {
 	MTPint256 aesKey, aesIV;
 	authKey->prepareAES(msgKey, aesKey, aesIV, false);
diff --git a/Telegram/SourceFiles/types.h b/Telegram/SourceFiles/types.h
index 9aeb1a0b1e..dae1346f91 100644
--- a/Telegram/SourceFiles/types.h
+++ b/Telegram/SourceFiles/types.h
@@ -436,3 +436,10 @@ inline int32 ceilclamp(int32 value, int32 step, int32 lowest, int32 highest) {
 inline int32 ceilclamp(float64 value, int32 step, int32 lowest, int32 highest) {
 	return qMax(qMin(qCeil(value / step), highest), lowest);
 }
+
+enum ForwardWhatMessages {
+	ForwardSelectedMessages,
+	ForwardContextMessage,
+	ForwardPressedMessage,
+	ForwardPressedLinkMessage
+};
diff --git a/Telegram/SourceFiles/window.cpp b/Telegram/SourceFiles/window.cpp
index 03f254ee4f..ada34c9e4e 100644
--- a/Telegram/SourceFiles/window.cpp
+++ b/Telegram/SourceFiles/window.cpp
@@ -987,6 +987,8 @@ bool Window::eventFilter(QObject *obj, QEvent *evt) {
 			psUserActionDone();
 			main->checkIdleFinish();
 		}
+	} else if (t == QEvent::MouseButtonRelease) {
+		Ui::hideStickerPreview();
 	}
 	if (obj == App::app()) {
 		if (t == QEvent::ApplicationActivate) {
diff --git a/Telegram/Telegram.vcxproj b/Telegram/Telegram.vcxproj
index 39f747a3ce..51fd57c4f4 100644
--- a/Telegram/Telegram.vcxproj
+++ b/Telegram/Telegram.vcxproj
@@ -992,6 +992,7 @@
     <ClCompile Include="SourceFiles\boxes\usernamebox.cpp" />
     <ClCompile Include="SourceFiles\dialogswidget.cpp" />
     <ClCompile Include="SourceFiles\dropdown.cpp" />
+    <ClCompile Include="SourceFiles\facades.cpp" />
     <ClCompile Include="SourceFiles\fileuploader.cpp" />
     <ClCompile Include="SourceFiles\gui\animation.cpp" />
     <ClCompile Include="SourceFiles\gui\boxshadow.cpp" />
@@ -1029,6 +1030,7 @@
     <ClCompile Include="SourceFiles\mainwidget.cpp" />
     <ClCompile Include="SourceFiles\mediaview.cpp" />
     <ClCompile Include="SourceFiles\mtproto\mtp.cpp" />
+    <ClCompile Include="SourceFiles\mtproto\mtpAuthKey.cpp" />
     <ClCompile Include="SourceFiles\mtproto\mtpConnection.cpp" />
     <ClCompile Include="SourceFiles\mtproto\mtpCoreTypes.cpp" />
     <ClCompile Include="SourceFiles\mtproto\mtpDC.cpp" />
@@ -1552,6 +1554,7 @@
       <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
       <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
     </CustomBuild>
+    <ClInclude Include="SourceFiles\facades.h" />
     <ClInclude Include="SourceFiles\gui\boxshadow.h" />
     <CustomBuild Include="SourceFiles\gui\popupmenu.h">
       <AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Deploy|Win32'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
diff --git a/Telegram/Telegram.vcxproj.filters b/Telegram/Telegram.vcxproj.filters
index d761bfb31f..8363c74863 100644
--- a/Telegram/Telegram.vcxproj.filters
+++ b/Telegram/Telegram.vcxproj.filters
@@ -900,6 +900,12 @@
     <ClCompile Include="SourceFiles\gui\popupmenu.cpp">
       <Filter>gui</Filter>
     </ClCompile>
+    <ClCompile Include="SourceFiles\facades.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
+    <ClCompile Include="SourceFiles\mtproto\mtpAuthKey.cpp">
+      <Filter>mtproto</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="SourceFiles\stdafx.h">
@@ -989,6 +995,9 @@
     <ClInclude Include="SourceFiles\config.h">
       <Filter>Version</Filter>
     </ClInclude>
+    <ClInclude Include="SourceFiles\facades.h">
+      <Filter>Source Files</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <CustomBuild Include="SourceFiles\mtproto\mtpConnection.h">