diff --git a/Telegram/Resources/icons/overview_photo_check.png b/Telegram/Resources/icons/overview_photo_check.png
index 6d6591b70..44347c6f7 100644
Binary files a/Telegram/Resources/icons/overview_photo_check.png and b/Telegram/Resources/icons/overview_photo_check.png differ
diff --git a/Telegram/Resources/icons/overview_photo_check@2x.png b/Telegram/Resources/icons/overview_photo_check@2x.png
index 20601fcb8..d5ad0a834 100644
Binary files a/Telegram/Resources/icons/overview_photo_check@2x.png and b/Telegram/Resources/icons/overview_photo_check@2x.png differ
diff --git a/Telegram/SourceFiles/boxes/backgroundbox.cpp b/Telegram/SourceFiles/boxes/backgroundbox.cpp
index 35984d703..1795d49b3 100644
--- a/Telegram/SourceFiles/boxes/backgroundbox.cpp
+++ b/Telegram/SourceFiles/boxes/backgroundbox.cpp
@@ -27,6 +27,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 #include "window/window_theme.h"
 #include "styles/style_overview.h"
 #include "styles/style_boxes.h"
+#include "ui/effects/round_image_checkbox.h"
 
 BackgroundBox::BackgroundBox() : ItemListBox(st::backgroundScroll)
 , _inner(this) {
@@ -50,10 +51,8 @@ void BackgroundBox::onBackgroundChosen(int index) {
 }
 
 BackgroundBox::Inner::Inner(QWidget *parent) : TWidget(parent)
-, _bgCount(0)
-, _rows(0)
-, _over(-1)
-, _overDown(-1) {
+, _check(std_::make_unique<Ui::RoundCheckbox>(st::overviewCheck, [this] { update(); })) {
+	_check->setChecked(true, Ui::RoundCheckbox::SetStyle::Fast);
 	if (App::cServerBackgrounds().isEmpty()) {
 		resize(BackgroundsInRow * (st::backgroundSize.width() + st::backgroundPadding) + st::backgroundPadding, 2 * (st::backgroundSize.height() + st::backgroundPadding) + st::backgroundPadding);
 		MTP::send(MTPaccount_GetWallPapers(), rpcDone(&Inner::gotWallpapers));
@@ -157,9 +156,9 @@ void BackgroundBox::Inner::paintEvent(QPaintEvent *e) {
 				p.drawPixmap(x, y, pix);
 
 				if (paper.id == Window::Theme::Background()->id()) {
-					int checkPosX = x + st::backgroundSize.width() - st::overviewPhotoChecked.width();
-					int checkPosY = y + st::backgroundSize.height() - st::overviewPhotoChecked.height();
-					st::overviewPhotoChecked.paint(p, QPoint(checkPosX, checkPosY), width());
+					auto checkLeft = x + st::backgroundSize.width() - st::overviewCheckSkip - st::overviewCheck.size;
+					auto checkTop = y + st::backgroundSize.height() - st::overviewCheckSkip - st::overviewCheck.size;
+					_check->paint(p, getms(), checkLeft, checkTop, width());
 				}
 			}
 		}
@@ -198,5 +197,4 @@ void BackgroundBox::Inner::mouseReleaseEvent(QMouseEvent *e) {
 	}
 }
 
-void BackgroundBox::Inner::resizeEvent(QResizeEvent *e) {
-}
+BackgroundBox::Inner::~Inner() = default;
diff --git a/Telegram/SourceFiles/boxes/backgroundbox.h b/Telegram/SourceFiles/boxes/backgroundbox.h
index bfd8a6dc3..b5136ba9f 100644
--- a/Telegram/SourceFiles/boxes/backgroundbox.h
+++ b/Telegram/SourceFiles/boxes/backgroundbox.h
@@ -22,6 +22,10 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 
 #include "boxes/abstractbox.h"
 
+namespace Ui {
+class RoundCheckbox;
+} // namespace Ui
+
 class BackgroundBox : public ItemListBox {
 	Q_OBJECT
 
@@ -43,6 +47,7 @@ class BackgroundBox::Inner : public TWidget, public RPCSender, private base::Sub
 
 public:
 	Inner(QWidget *parent);
+	~Inner();
 
 signals:
 	void backgroundChosen(int index);
@@ -52,13 +57,15 @@ protected:
 	void mouseMoveEvent(QMouseEvent *e) override;
 	void mousePressEvent(QMouseEvent *e) override;
 	void mouseReleaseEvent(QMouseEvent *e) override;
-	void resizeEvent(QResizeEvent *e) override;
 
 private:
 	void gotWallpapers(const MTPVector<MTPWallPaper> &result);
 	void updateWallpapers();
 
-	int32 _bgCount, _rows;
-	int32 _over, _overDown;
+	int _bgCount = 0;
+	int _rows = 0;
+	int _over = -1;
+	int _overDown = -1;
+	std_::unique_ptr<Ui::RoundCheckbox> _check;
 
 };
diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style
index dea1fece3..b22e687f4 100644
--- a/Telegram/SourceFiles/boxes/boxes.style
+++ b/Telegram/SourceFiles/boxes/boxes.style
@@ -304,11 +304,11 @@ contactsPhotoCheckbox: RoundImageCheckbox {
 	selectWidth: 2px;
 	selectFg: windowBgActive;
 	selectDuration: 150;
-	checkBorder: windowBg;
-	checkBg: windowBgActive;
-	checkRadius: 10px;
-	checkSmallRadius: 3px;
-	checkIcon: icon {{ "default_checkbox_check", windowFgActive, point(3px, 6px) }};
+	check: RoundCheckbox(defaultRoundCheckbox) {
+		size: 20px;
+		sizeSmall: 0.3;
+		check: icon {{ "default_checkbox_check", windowFgActive, point(3px, 6px) }};
+	}
 }
 contactsPhotoDisabledCheckFg: #bbbbbb;
 contactsNameCheckedFg: #2b88b8;
diff --git a/Telegram/SourceFiles/boxes/contactsbox.cpp b/Telegram/SourceFiles/boxes/contactsbox.cpp
index 5363b0ff6..6ae34786c 100644
--- a/Telegram/SourceFiles/boxes/contactsbox.cpp
+++ b/Telegram/SourceFiles/boxes/contactsbox.cpp
@@ -1002,11 +1002,11 @@ void ContactsBox::Inner::paintDisabledCheckUserpic(Painter &p, PeerData *peer, i
 	auto userpicBorderPen = st::contactsPhotoDisabledCheckFg->p;
 	userpicBorderPen.setWidth(st::contactsPhotoCheckbox.selectWidth);
 
-	auto iconDiameter = 2 * st::contactsPhotoCheckbox.checkRadius;
+	auto iconDiameter = st::contactsPhotoCheckbox.check.size;
 	auto iconLeft = x + userpicDiameter + st::contactsPhotoCheckbox.selectWidth - iconDiameter;
 	auto iconTop = y + userpicDiameter + st::contactsPhotoCheckbox.selectWidth - iconDiameter;
 	auto iconEllipse = rtlrect(iconLeft, iconTop, iconDiameter, iconDiameter, outerWidth);
-	auto iconBorderPen = st::contactsPhotoCheckbox.checkBorder->p;
+	auto iconBorderPen = st::contactsPhotoCheckbox.check.border->p;
 	iconBorderPen.setWidth(st::contactsPhotoCheckbox.selectWidth);
 
 	peer->paintUserpicLeft(p, userpicRadius * 2, userpicLeft, userpicTop, width());
@@ -1023,7 +1023,7 @@ void ContactsBox::Inner::paintDisabledCheckUserpic(Painter &p, PeerData *peer, i
 
 	p.setRenderHint(QPainter::HighQualityAntialiasing, false);
 
-	st::contactsPhotoCheckbox.checkIcon.paint(p, iconEllipse.topLeft(), outerWidth);
+	st::contactsPhotoCheckbox.check.check.paint(p, iconEllipse.topLeft(), outerWidth);
 }
 
 void ContactsBox::Inner::paintEvent(QPaintEvent *e) {
diff --git a/Telegram/SourceFiles/mainwidget.cpp b/Telegram/SourceFiles/mainwidget.cpp
index 7d10e5c98..46c7b2ae9 100644
--- a/Telegram/SourceFiles/mainwidget.cpp
+++ b/Telegram/SourceFiles/mainwidget.cpp
@@ -2082,8 +2082,8 @@ void MainWidget::fillPeerMenu(PeerData *peer, base::lambda<QAction*(const QStrin
 			}
 		}
 	} else if (peer->isChat()) {
-		callback(lang(lng_profile_clear_history), std_::move(clearHistoryHandler));
 		callback(lang(lng_profile_clear_and_exit), std_::move(deleteAndLeaveHandler));
+		callback(lang(lng_profile_clear_history), std_::move(clearHistoryHandler));
 	} else if (peer->isChannel() && peer->asChannel()->amIn() && !peer->asChannel()->amCreator()) {
 		callback(lang(peer->isMegagroup() ? lng_profile_leave_group : lng_profile_leave_channel), std_::move(deleteAndLeaveHandler));
 	}
diff --git a/Telegram/SourceFiles/overview/overview.style b/Telegram/SourceFiles/overview/overview.style
index 117d3deda..c53500f9f 100644
--- a/Telegram/SourceFiles/overview/overview.style
+++ b/Telegram/SourceFiles/overview/overview.style
@@ -43,21 +43,22 @@ OverviewFileLayout {
 	fileDateTop: pixels;
 }
 
-overviewCheckBg: #00000042;
-overviewCheckedBg: #2fa9e2;
+overviewCheckBg: #00000040;
+overviewCheckFg: windowBg;
+overviewCheckFgActive: windowBg;
+overviewCheckPressedSize: 0.8;
+overviewCheck: RoundCheckbox(defaultRoundCheckbox) {
+	bgInactive: overviewCheckBg;
+	size: 29px;
+	sizeSmall: 0.3;
+	check: icon {{ "overview_photo_check", overviewCheckFgActive, point(4px, 8px) }};
+}
+overviewCheckSkip: 5px;
 
 overviewPhotoSkip: 10px;
 overviewPhotoBg: #F1F1F1;
 overviewPhotoMinSize: minPhotoSize;
-overviewPhotoCheck: icon {
-	{ size(31px, 31px), overviewCheckBg },
-	{ "overview_photo_check", #ffffff, point(4px, 8px) },
-};
-overviewPhotoChecked: icon {
-	{ size(31px, 31px), overviewCheckedBg },
-	{ "overview_photo_check", #ffffff, point(4px, 8px) },
-};
-overviewPhotoSelectOverlay: #0a7bb03f;
+overviewPhotoSelectOverlay: #40ace333;
 
 overviewVideoBg: #000000;
 
@@ -111,11 +112,11 @@ linksPhotoSize: 46px;
 linksPhotoPadding: 12px;
 overviewLinksCheck: icon {
 	{ "overview_links_check_bg", overviewCheckBg },
-	{ "overview_links_check", #ffffff, point(4px, 5px) },
+	{ "overview_links_check", overviewCheckFg, point(4px, 5px) },
 };
 overviewLinksChecked: icon {
-	{ "overview_links_check_bg", overviewCheckedBg },
-	{ "overview_links_check", #ffffff, point(4px, 5px) },
+	{ "overview_links_check_bg", windowBgActive },
+	{ "overview_links_check", overviewCheckFgActive, point(4px, 5px) },
 };
 
 overviewFilter: FlatInput(defaultFlatInput) {
diff --git a/Telegram/SourceFiles/overview/overview_layout.cpp b/Telegram/SourceFiles/overview/overview_layout.cpp
index c9ed59b78..68599e0af 100644
--- a/Telegram/SourceFiles/overview/overview_layout.cpp
+++ b/Telegram/SourceFiles/overview/overview_layout.cpp
@@ -35,6 +35,7 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 #include "media/player/media_player_instance.h"
 #include "localstorage.h"
 #include "history/history_media_types.h"
+#include "ui/effects/round_image_checkbox.h"
 
 namespace Overview {
 namespace Layout {
@@ -101,7 +102,7 @@ void RadialProgressItem::step_radial(uint64 ms, bool timer) {
 	}
 }
 
-void RadialProgressItem::ensureRadial() const {
+void RadialProgressItem::ensureRadial() {
 	if (!_radial) {
 		_radial = new Ui::RadialAnimation(animation(const_cast<RadialProgressItem*>(this), &RadialProgressItem::step_radial));
 	}
@@ -118,21 +119,25 @@ RadialProgressItem::~RadialProgressItem() {
 	delete base::take(_radial);
 }
 
-void FileBase::setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const {
-	_statusSize = newSize;
-	if (_statusSize == FileStatusSizeReady) {
-		_statusText = (duration >= 0) ? formatDurationAndSizeText(duration, fullSize) : (duration < -1 ? formatGifAndSizeText(fullSize) : formatSizeText(fullSize));
-	} else if (_statusSize == FileStatusSizeLoaded) {
-		_statusText = (duration >= 0) ? formatDurationText(duration) : (duration < -1 ? qsl("GIF") : formatSizeText(fullSize));
-	} else if (_statusSize == FileStatusSizeFailed) {
-		_statusText = lang(lng_attach_failed);
-	} else if (_statusSize >= 0) {
-		_statusText = formatDownloadText(_statusSize, fullSize);
+void StatusText::update(int newSize, int fullSize, int duration, int64 realDuration) {
+	setSize(newSize);
+	if (_size == FileStatusSizeReady) {
+		_text = (duration >= 0) ? formatDurationAndSizeText(duration, fullSize) : (duration < -1 ? formatGifAndSizeText(fullSize) : formatSizeText(fullSize));
+	} else if (_size == FileStatusSizeLoaded) {
+		_text = (duration >= 0) ? formatDurationText(duration) : (duration < -1 ? qsl("GIF") : formatSizeText(fullSize));
+	} else if (_size == FileStatusSizeFailed) {
+		_text = lang(lng_attach_failed);
+	} else if (_size >= 0) {
+		_text = formatDownloadText(_size, fullSize);
 	} else {
-		_statusText = formatPlayedText(-_statusSize - 1, realDuration);
+		_text = formatPlayedText(-_size - 1, realDuration);
 	}
 }
 
+void StatusText::setSize(int newSize) {
+	_size = newSize;
+}
+
 Date::Date(const QDate &date, bool month)
 : _date(date)
 , _text(month ? langMonthFull(date) : langDayOfMonthFull(date)) {
@@ -144,7 +149,7 @@ void Date::initDimensions() {
 	_minh = st::linksDateMargin.top() + st::normalFont->height + st::linksDateMargin.bottom() + st::linksBorder;
 }
 
-void Date::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const {
+void Date::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) {
 	if (clip.intersects(QRect(0, st::linksDateMargin.top(), _width, st::normalFont->height))) {
 		p.setPen(st::linksDateColor);
 		p.setFont(st::semiboldFont);
@@ -152,25 +157,62 @@ void Date::paint(Painter &p, const QRect &clip, TextSelection selection, const P
 	}
 }
 
-namespace {
+class PhotoVideoCheckbox {
+public:
+	template <typename UpdateCallback>
+	PhotoVideoCheckbox(UpdateCallback callback) : _updateCallback(callback), _check(st::overviewCheck, _updateCallback) {
+	}
 
-void paintPhotoVideoCheck(Painter &p, int width, int height, bool selected) {
-	int checkPosX = width - st::overviewPhotoCheck.width();
-	int checkPosY = height - st::overviewPhotoCheck.height();
+	void paint(Painter &p, uint64 ms, int width, int height, bool selected, bool selecting);
+
+	void setActive(bool active);
+	void setPressed(bool pressed);
+
+private:
+	void startAnimation();
+
+	base::lambda_copy<void()> _updateCallback;
+	Ui::RoundCheckbox _check;
+
+	FloatAnimation _pression;
+	bool _active = false;
+	bool _pressed = false;
+
+};
+
+void PhotoVideoCheckbox::paint(Painter &p, uint64 ms, int width, int height, bool selected, bool selecting) {
 	if (selected) {
-		p.fillRect(QRect(0, 0, width, height), st::overviewPhotoSelectOverlay);
-		st::overviewPhotoChecked.paint(p, QPoint(checkPosX, checkPosY), width);
-	} else {
-		st::overviewPhotoCheck.paint(p, QPoint(checkPosX, checkPosY), width);
+		p.fillRect(0, 0, width, height, st::overviewPhotoSelectOverlay);
+	}
+	_check.setDisplayInactive(selecting);
+	_check.setChecked(selected);
+	auto pression = _pression.current(ms, (_active && _pressed) ? 1. : 0.);
+	auto masterScale = 1. - (1. - st::overviewCheckPressedSize) * pression;
+	_check.paint(p, ms, width - st::overviewCheckSkip - st::overviewCheck.size, height - st::overviewCheckSkip - st::overviewCheck.size, width, masterScale);
+}
+
+void PhotoVideoCheckbox::setActive(bool active) {
+	_active = active;
+	if (_pressed) {
+		startAnimation();
 	}
 }
 
-} // namespace
+void PhotoVideoCheckbox::setPressed(bool pressed) {
+	_pressed = pressed;
+	if (_active) {
+		startAnimation();
+	}
+}
+
+void PhotoVideoCheckbox::startAnimation() {
+	auto showPressed = (_pressed && _active);
+	_pression.start(_updateCallback, showPressed ? 0. : 1., showPressed ? 1. : 0., st::overviewCheck.duration);
+}
 
 Photo::Photo(PhotoData *photo, HistoryItem *parent) : ItemBase(parent)
 , _data(photo)
-, _link(new PhotoOpenClickHandler(photo))
-, _goodLoaded(false) {
+, _link(new PhotoOpenClickHandler(photo)) {
 }
 
 void Photo::initDimensions() {
@@ -187,7 +229,7 @@ int32 Photo::resizeGetHeight(int32 width) {
 	return _height;
 }
 
-void Photo::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const {
+void Photo::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) {
 	bool good = _data->loaded(), selected = (selection == FullSelection);
 	if (!good) {
 		_data->medium->automaticLoad(_parent);
@@ -225,9 +267,19 @@ void Photo::paint(Painter &p, const QRect &clip, TextSelection selection, const
 	} else {
 		p.drawPixmap(0, 0, _pix);
 	}
+
 	if (selected || context->selecting) {
-		paintPhotoVideoCheck(p, _width, _height, selected);
+		ensureCheckboxCreated();
 	}
+	if (_check) {
+		_check->paint(p, context->ms, _width, _height, selected, context->selecting);
+	}
+}
+
+void Photo::ensureCheckboxCreated() {
+	if (!_check) _check = std_::make_unique<PhotoVideoCheckbox>([this] {
+		Ui::repaintHistoryItem(_parent);
+	});
 }
 
 void Photo::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const {
@@ -236,7 +288,19 @@ void Photo::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, i
 	}
 }
 
-Video::Video(DocumentData *video, HistoryItem *parent) : FileBase(parent)
+void Photo::clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
+	if (_check) {
+		_check->setActive(active);
+	}
+}
+
+void Photo::clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) {
+	if (_check) {
+		_check->setPressed(pressed);
+	}
+}
+
+Video::Video(DocumentData *video, HistoryItem *parent) : RadialProgressItem(parent)
 , _data(video)
 , _duration(formatDurationText(_data->duration()))
 , _thumbLoaded(false) {
@@ -254,7 +318,7 @@ int32 Video::resizeGetHeight(int32 width) {
 	return _height;
 }
 
-void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const {
+void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) {
 	bool selected = (selection == FullSelection), thumbLoaded = _data->thumb->loaded();
 
 	_data->automaticLoad(_parent);
@@ -305,13 +369,13 @@ void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const
 	if (!selected && !context->selecting && !loaded) {
 		if (clip.intersects(QRect(0, _height - st::normalFont->height, _width, st::normalFont->height))) {
 			int32 statusX = st::msgDateImgPadding.x(), statusY = _height - st::normalFont->height - st::msgDateImgPadding.y();
-			int32 statusW = st::normalFont->width(_statusText) + 2 * st::msgDateImgPadding.x();
+			int32 statusW = st::normalFont->width(_status.text()) + 2 * st::msgDateImgPadding.x();
 			int32 statusH = st::normalFont->height + 2 * st::msgDateImgPadding.y();
 			statusX = _width - statusW + statusX;
 			p.fillRect(rtlrect(statusX - st::msgDateImgPadding.x(), statusY - st::msgDateImgPadding.y(), statusW, statusH, _width), selected ? st::msgDateImgBgSelected : st::msgDateImgBg);
 			p.setFont(st::normalFont);
 			p.setPen(st::msgDateImgColor);
-			p.drawTextLeft(statusX, statusY, _width, _statusText, statusW - 2 * st::msgDateImgPadding.x());
+			p.drawTextLeft(statusX, statusY, _width, _status.text(), statusW - 2 * st::msgDateImgPadding.x());
 		}
 	}
 	if (clip.intersects(QRect(0, 0, _width, st::normalFont->height))) {
@@ -358,8 +422,32 @@ void Video::paint(Painter &p, const QRect &clip, TextSelection selection, const
 			_radial->draw(p, rinner, st::msgFileRadialLine, selected ? st::msgInBgSelected : st::msgInBg);
 		}
 	}
+
 	if (selected || context->selecting) {
-		paintPhotoVideoCheck(p, _width, _height, selected);
+		ensureCheckboxCreated();
+	}
+	if (_check) {
+		_check->paint(p, context->ms, _width, _height, selected, context->selecting);
+	}
+}
+
+void Video::ensureCheckboxCreated() {
+	if (!_check) _check = std_::make_unique<PhotoVideoCheckbox>([this] {
+		Ui::repaintHistoryItem(_parent);
+	});
+}
+
+void Video::clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) {
+	RadialProgressItem::clickHandlerActiveChanged(action, active);
+	if (_check) {
+		_check->setActive(active);
+	}
+}
+
+void Video::clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) {
+	RadialProgressItem::clickHandlerPressedChanged(action, pressed);
+	if (_check) {
+		_check->setPressed(pressed);
 	}
 }
 
@@ -371,9 +459,9 @@ void Video::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, i
 	}
 }
 
-void Video::updateStatusText() const {
+void Video::updateStatusText() {
 	bool showPause = false;
-	int32 statusSize = 0;
+	int statusSize = 0;
 	if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) {
 		statusSize = FileStatusSizeFailed;
 	} else if (_data->status == FileUploading) {
@@ -385,18 +473,18 @@ void Video::updateStatusText() const {
 	} else {
 		statusSize = FileStatusSizeReady;
 	}
-	if (statusSize != _statusSize) {
-		int32 status = statusSize, size = _data->size;
+	if (statusSize != _status.size()) {
+		int status = statusSize, size = _data->size;
 		if (statusSize >= 0 && statusSize < 0x7F000000) {
 			size = status;
 			status = FileStatusSizeReady;
 		}
-		setStatusSize(status, size, -1, 0);
-		_statusSize = statusSize;
+		_status.update(status, size, -1, 0);
+		_status.setSize(statusSize);
 	}
 }
 
-Voice::Voice(DocumentData *voice, HistoryItem *parent) : FileBase(parent)
+Voice::Voice(DocumentData *voice, HistoryItem *parent) : RadialProgressItem(parent)
 , _data(voice)
 , _namel(new DocumentOpenClickHandler(_data)) {
 	AddComponents(Info::Bit());
@@ -417,7 +505,7 @@ void Voice::initDimensions() {
 	_minh = st::overviewFileLayout.songPadding.top() + st::overviewFileLayout.songThumbSize + st::overviewFileLayout.songPadding.bottom() + st::lineWidth;
 }
 
-void Voice::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const {
+void Voice::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) {
 	bool selected = (selection == FullSelection);
 
 	_data->automaticLoad(_parent);
@@ -474,7 +562,7 @@ void Voice::paint(Painter &p, const QRect &clip, TextSelection selection, const
 		auto icon = ([showPause, this, selected] {
 			if (showPause) {
 				return &(selected ? st::historyFileInPauseSelected : st::historyFileInPause);
-			} else if (_statusSize < 0 || _statusSize == FileStatusSizeLoaded) {
+			} else if (_status.size() < 0 || _status.size() == FileStatusSizeLoaded) {
 				return &(selected ? st::historyFileInPlaySelected : st::historyFileInPlay);
 			} else if (_data->loading()) {
 				return &(selected ? st::historyFileInCancelSelected : st::historyFileInCancel);
@@ -495,14 +583,14 @@ void Voice::paint(Painter &p, const QRect &clip, TextSelection selection, const
 		p.setFont(st::normalFont);
 		p.setPen(selected ? st::mediaInFgSelected : st::mediaInFg);
 		int32 unreadx = nameleft;
-		if (_statusSize == FileStatusSizeLoaded || _statusSize == FileStatusSizeReady) {
+		if (_status.size() == FileStatusSizeLoaded || _status.size() == FileStatusSizeReady) {
 			textstyleSet(&(selected ? st::mediaInStyleSelected : st::mediaInStyle));
 			_details.drawLeftElided(p, nameleft, statustop, namewidth, _width);
 			textstyleRestore();
 			unreadx += _details.maxWidth();
 		} else {
-			int32 statusw = st::normalFont->width(_statusText);
-			p.drawTextLeft(nameleft, statustop, _width, _statusText, statusw);
+			int32 statusw = st::normalFont->width(_status.text());
+			p.drawTextLeft(nameleft, statustop, _width, _status.text(), statusw);
 			unreadx += statusw;
 		}
 		if (_parent->isMediaUnread() && unreadx + st::mediaUnreadSkip + st::mediaUnreadSize <= _width) {
@@ -519,8 +607,6 @@ void Voice::paint(Painter &p, const QRect &clip, TextSelection selection, const
 void Voice::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const {
 	bool loaded = _data->loaded();
 
-	bool showPause = updateStatusText();
-
 	int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, datetop = 0;
 
 	nameleft = st::overviewFileLayout.songPadding.left() + st::overviewFileLayout.songThumbSize + st::overviewFileLayout.songPadding.right();
@@ -534,7 +620,7 @@ void Voice::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, i
 		return;
 	}
 	if (rtlrect(nameleft, statustop, _width - nameleft - nameright, st::normalFont->height, _width).contains(x, y)) {
-		if (_statusSize == FileStatusSizeLoaded || _statusSize == FileStatusSizeReady) {
+		if (_status.size() == FileStatusSizeLoaded || _status.size() == FileStatusSizeReady) {
 			auto textState = _details.getStateLeft(x - nameleft, y - statustop, _width, _width);
 			link = textState.link;
 			cursor = textState.uponSymbol ? HistoryInTextCursorState : HistoryDefaultCursorState;
@@ -546,7 +632,7 @@ void Voice::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, i
 	}
 }
 
-void Voice::updateName() const {
+void Voice::updateName() {
 	int32 version = 0;
 	if (const HistoryMessageForwarded *fwd = _parent->Get<HistoryMessageForwarded>()) {
 		if (_parent->fromOriginal()->isChannel()) {
@@ -561,7 +647,7 @@ void Voice::updateName() const {
 	_nameVersion = version;
 }
 
-bool Voice::updateStatusText() const {
+bool Voice::updateStatusText() {
 	bool showPause = false;
 	int32 statusSize = 0, realDuration = 0;
 	if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) {
@@ -580,13 +666,13 @@ bool Voice::updateStatusText() const {
 	} else {
 		statusSize = FileStatusSizeReady;
 	}
-	if (statusSize != _statusSize) {
-		setStatusSize(statusSize, _data->size, _data->voice()->duration, realDuration);
+	if (statusSize != _status.size()) {
+		_status.update(statusSize, _data->size, _data->voice()->duration, realDuration);
 	}
 	return showPause;
 }
 
-Document::Document(DocumentData *document, HistoryItem *parent, const style::OverviewFileLayout &st) : FileBase(parent)
+Document::Document(DocumentData *document, HistoryItem *parent, const style::OverviewFileLayout &st) : RadialProgressItem(parent)
 , _data(document)
 , _msgl(goToMessageClickHandler(parent))
 , _namel(new DocumentOpenClickHandler(_data))
@@ -600,7 +686,7 @@ Document::Document(DocumentData *document, HistoryItem *parent, const style::Ove
 
 	setDocumentLinks(_data);
 
-	setStatusSize(FileStatusSizeReady, _data->size, _data->song() ? _data->song()->duration : -1, 0);
+	_status.update(FileStatusSizeReady, _data->size, _data->song() ? _data->song()->duration : -1, 0);
 
 	if (withThumb()) {
 		_data->thumb->load();
@@ -630,7 +716,7 @@ void Document::initDimensions() {
 	}
 }
 
-void Document::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const {
+void Document::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) {
 	bool selected = (selection == FullSelection);
 
 	_data->automaticLoad(_parent);
@@ -786,7 +872,7 @@ void Document::paint(Painter &p, const QRect &clip, TextSelection selection, con
 	if (clip.intersects(rtlrect(nameleft, statustop, availwidth, st::normalFont->height, _width))) {
 		p.setFont(st::normalFont);
 		p.setPen(st::mediaInFg);
-		p.drawTextLeft(nameleft, statustop, _width, _statusText);
+		p.drawTextLeft(nameleft, statustop, _width, _status.text());
 	}
 	if (datetop >= 0 && clip.intersects(rtlrect(nameleft, datetop, _datew, st::normalFont->height, _width))) {
 		p.setFont(ClickHandler::showAsActive(_msgl) ? st::normalFont->underline() : st::normalFont);
@@ -798,8 +884,6 @@ void Document::paint(Painter &p, const QRect &clip, TextSelection selection, con
 void Document::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const {
 	bool loaded = _data->loaded() || Local::willStickerImageLoad(_data->mediaKey());
 
-	bool showPause = updateStatusText();
-
 	int32 nameleft = 0, nametop = 0, nameright = 0, statustop = 0, datetop = 0;
 	bool wthumb = withThumb();
 
@@ -850,7 +934,7 @@ void Document::getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x
 	}
 }
 
-bool Document::updateStatusText() const {
+bool Document::updateStatusText() {
 	bool showPause = false;
 	int32 statusSize = 0, realDuration = 0;
 	if (_data->status == FileDownloadFailed || _data->status == FileUploadFailed) {
@@ -880,8 +964,8 @@ bool Document::updateStatusText() const {
 	} else {
 		statusSize = FileStatusSizeReady;
 	}
-	if (statusSize != _statusSize) {
-		setStatusSize(statusSize, _data->size, _data->song() ? _data->song()->duration : -1, realDuration);
+	if (statusSize != _status.size()) {
+		_status.update(statusSize, _data->size, _data->song() ? _data->song()->duration : -1, realDuration);
 	}
 	return showPause;
 }
@@ -1041,7 +1125,7 @@ int32 Link::resizeGetHeight(int32 width) {
 	return _height;
 }
 
-void Link::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const {
+void Link::paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) {
 	int32 left = st::linksPhotoSize + st::linksPhotoPadding, top = st::linksMargin.top() + st::linksBorder, w = _width - left;
 	if (clip.intersects(rtlrect(0, top, st::linksPhotoSize, st::linksPhotoSize, _width))) {
 		if (_page && _page->photo) {
diff --git a/Telegram/SourceFiles/overview/overview_layout.h b/Telegram/SourceFiles/overview/overview_layout.h
index 3909487a6..608fdfdd4 100644
--- a/Telegram/SourceFiles/overview/overview_layout.h
+++ b/Telegram/SourceFiles/overview/overview_layout.h
@@ -39,8 +39,7 @@ public:
 class ItemBase;
 class AbstractItem : public LayoutItemBase {
 public:
-
-	virtual void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const = 0;
+	virtual void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) = 0;
 
 	virtual ItemBase *toMediaItem() {
 		return nullptr;
@@ -115,7 +114,7 @@ protected:
 	void step_iconOver(float64 ms, bool timer);
 	void step_radial(uint64 ms, bool timer);
 
-	void ensureRadial() const;
+	void ensureRadial();
 	void checkRadialFinished();
 
 	bool isRadialAnimation(uint64 ms) const {
@@ -132,28 +131,33 @@ protected:
 		return false;
 	}
 
-	mutable Ui::RadialAnimation *_radial;
+	Ui::RadialAnimation *_radial;
 	anim::fvalue a_iconOver;
-	mutable Animation _a_iconOver;
+	Animation _a_iconOver;
 
 };
 
-class FileBase : public RadialProgressItem {
+class StatusText {
 public:
-	FileBase(HistoryItem *parent) : RadialProgressItem(parent) {
+	// duration = -1 - no duration, duration = -2 - "GIF" duration
+	void update(int newSize, int fullSize, int duration, int64 realDuration);
+	void setSize(int newSize);
+
+	int size() const {
+		return _size;
+	}
+	QString text() const {
+		return _text;
 	}
 
-protected:
-	// >= 0 will contain download / upload string, _statusSize = loaded bytes
-	// < 0 will contain played string, _statusSize = -(seconds + 1) played
+private:
+	// >= 0 will contain download / upload string, _size = loaded bytes
+	// < 0 will contain played string, _size = -(seconds + 1) played
 	// 0x7FFFFFF0 will contain status for not yet downloaded file
 	// 0x7FFFFFF1 will contain status for already downloaded file
 	// 0x7FFFFFF2 will contain status for failed to download / upload file
-	mutable int32 _statusSize;
-	mutable QString _statusText;
-
-	// duration = -1 - no duration, duration = -2 - "GIF" duration
-	void setStatusSize(int32 newSize, int32 fullSize, int32 duration, qint64 realDuration) const;
+	int _size = 0;
+	QString _text;
 
 };
 
@@ -166,7 +170,7 @@ public:
 	Date(const QDate &date, bool month);
 
 	void initDimensions() override;
-	void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
+	void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
 
 private:
 	QDate _date;
@@ -174,33 +178,45 @@ private:
 
 };
 
+class PhotoVideoCheckbox;
+
 class Photo : public ItemBase {
 public:
 	Photo(PhotoData *photo, HistoryItem *parent);
 
 	void initDimensions() override;
 	int32 resizeGetHeight(int32 width) override;
-	void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
+	void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
 	void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
 
+	void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override;
+	void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override;
+
 private:
+	void ensureCheckboxCreated();
+
+	std_::unique_ptr<PhotoVideoCheckbox> _check;
+
 	PhotoData *_data;
 	ClickHandlerPtr _link;
 
-	mutable QPixmap _pix;
-	mutable bool _goodLoaded;
+	QPixmap _pix;
+	bool _goodLoaded = false;
 
 };
 
-class Video : public FileBase {
+class Video : public RadialProgressItem {
 public:
 	Video(DocumentData *video, HistoryItem *parent);
 
 	void initDimensions() override;
 	int32 resizeGetHeight(int32 width) override;
-	void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
+	void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
 	void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
 
+	void clickHandlerActiveChanged(const ClickHandlerPtr &action, bool active) override;
+	void clickHandlerPressedChanged(const ClickHandlerPtr &action, bool pressed) override;
+
 protected:
 	float64 dataProgress() const override {
 		return _data->progress();
@@ -216,22 +232,27 @@ protected:
 	}
 
 private:
+	void ensureCheckboxCreated();
+
+	std_::unique_ptr<PhotoVideoCheckbox> _check;
+
 	DocumentData *_data;
+	StatusText _status;
 
 	QString _duration;
-	mutable QPixmap _pix;
-	mutable bool _thumbLoaded;
+	QPixmap _pix;
+	bool _thumbLoaded = false;
 
-	void updateStatusText() const;
+	void updateStatusText();
 
 };
 
-class Voice : public FileBase {
+class Voice : public RadialProgressItem {
 public:
 	Voice(DocumentData *voice, HistoryItem *parent);
 
 	void initDimensions() override;
-	void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
+	void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
 	void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
 
 protected:
@@ -250,22 +271,23 @@ protected:
 
 private:
 	DocumentData *_data;
+	StatusText _status;
 	ClickHandlerPtr _namel;
 
-	mutable Text _name, _details;
-	mutable int32 _nameVersion;
+	Text _name, _details;
+	int _nameVersion;
 
-	void updateName() const;
-	bool updateStatusText() const;
+	void updateName();
+	bool updateStatusText();
 
 };
 
-class Document : public FileBase {
+class Document : public RadialProgressItem {
 public:
 	Document(DocumentData *document, HistoryItem *parent, const style::OverviewFileLayout &st);
 
 	void initDimensions() override;
-	void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
+	void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
 	void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
 
 	virtual DocumentData *getDocument() const override {
@@ -288,12 +310,13 @@ protected:
 
 private:
 	DocumentData *_data;
+	StatusText _status;
 	ClickHandlerPtr _msgl, _namel;
 
 	const style::OverviewFileLayout &_st;
 
-	mutable bool _thumbForLoaded = false;
-	mutable QPixmap _thumb;
+	bool _thumbForLoaded = false;
+	QPixmap _thumb;
 
 	Text _name;
 	QString _date, _ext;
@@ -303,7 +326,7 @@ private:
 	bool withThumb() const {
 		return !_data->thumb->isNull() && _data->thumb->width() && _data->thumb->height();
 	}
-	bool updateStatusText() const;
+	bool updateStatusText();
 
 };
 
@@ -313,7 +336,7 @@ public:
 
 	void initDimensions() override;
 	int32 resizeGetHeight(int32 width) override;
-	void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) const override;
+	void paint(Painter &p, const QRect &clip, TextSelection selection, const PaintContext *context) override;
 	void getState(ClickHandlerPtr &link, HistoryCursorState &cursor, int x, int y) const override;
 
 private:
diff --git a/Telegram/SourceFiles/ui/effects/round_image_checkbox.cpp b/Telegram/SourceFiles/ui/effects/round_image_checkbox.cpp
index 28b67a083..b7cc84f9a 100644
--- a/Telegram/SourceFiles/ui/effects/round_image_checkbox.cpp
+++ b/Telegram/SourceFiles/ui/effects/round_image_checkbox.cpp
@@ -24,23 +24,25 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 namespace Ui {
 namespace {
 
-static constexpr int kWideScale = 4;
+static constexpr int kWideScale = 3;
 
-void prepareCheckCaches(const style::RoundImageCheckbox *st, QPixmap &checkBgCache, QPixmap &checkFullCache) {
-	auto size = st->checkRadius * 2;
+void prepareCheckCaches(const style::RoundCheckbox *st, bool displayInactive, QPixmap &checkBgCache, QPixmap &checkFullCache) {
+	auto size = st->size;
 	auto wideSize = size * kWideScale;
 	auto cache = QImage(wideSize * cIntRetinaFactor(), wideSize * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
 	cache.setDevicePixelRatio(cRetinaFactor());
+	cache.fill(Qt::transparent);
 	{
 		Painter p(&cache);
-		p.setCompositionMode(QPainter::CompositionMode_Source);
-		p.fillRect(0, 0, wideSize, wideSize, Qt::transparent);
-		p.setCompositionMode(QPainter::CompositionMode_SourceOver);
 		p.setRenderHint(QPainter::HighQualityAntialiasing, true);
-		auto pen = st->checkBorder->p;
-		pen.setWidth(st->selectWidth);
-		p.setPen(pen);
-		p.setBrush(st->checkBg);
+		if (displayInactive) {
+			p.setPen(Qt::NoPen);
+		} else {
+			auto pen = st->border->p;
+			pen.setWidth(st->width);
+			p.setPen(pen);
+		}
+		p.setBrush(st->bgActive);
 		auto ellipse = QRect((wideSize - size) / 2, (wideSize - size) / 2, size, size);
 		p.drawEllipse(ellipse);
 	}
@@ -48,32 +50,183 @@ void prepareCheckCaches(const style::RoundImageCheckbox *st, QPixmap &checkBgCac
 	{
 		Painter p(&cacheIcon);
 		auto ellipse = QRect((wideSize - size) / 2, (wideSize - size) / 2, size, size);
-		st->checkIcon.paint(p, ellipse.topLeft(), wideSize);
+		st->check.paint(p, ellipse.topLeft(), wideSize);
 	}
 	checkBgCache = App::pixmapFromImageInPlace(std_::move(cache));
-	checkBgCache.setDevicePixelRatio(cRetinaFactor());
 	checkFullCache = App::pixmapFromImageInPlace(std_::move(cacheIcon));
-	checkFullCache.setDevicePixelRatio(cRetinaFactor());
 }
 
 } // namespace
 
-RoundImageCheckbox::RoundImageCheckbox(const style::RoundImageCheckbox &st, const base::lambda_copy<void()> &updateCallback, PaintRoundImage &&paintRoundImage)
+RoundCheckbox::RoundCheckbox(const style::RoundCheckbox &st, const base::lambda_copy<void()> &updateCallback)
 : _st(st)
-, _updateCallback(updateCallback)
-, _paintRoundImage(std_::move(paintRoundImage)) {
-	prepareCheckCaches(&_st, _wideCheckBgCache, _wideCheckFullCache);
+, _updateCallback(updateCallback) {
 }
 
-void RoundImageCheckbox::paint(Painter &p, uint64 ms, int x, int y, int outerWidth) {
-	_selection.step(ms);
+QRect RoundCheckbox::cacheDestRect(int x, int y, float64 scale) const {
+	auto iconSizeFull = kWideScale * _st.size;
+	auto iconSize = qRound(iconSizeFull * scale);
+	if (iconSize % 2 != iconSizeFull % 2) {
+		++iconSize;
+	}
+	auto iconShift = (iconSizeFull - iconSize) / 2;
+	auto iconLeft = x - (kWideScale - 1) * _st.size / 2 + iconShift;
+	auto iconTop = y - (kWideScale - 1) * _st.size / 2 + iconShift;
+	return QRect(iconLeft, iconTop, iconSize, iconSize);
+}
+
+void RoundCheckbox::paint(Painter &p, uint64 ms, int x, int y, int outerWidth, float64 masterScale) {
 	for (auto &icon : _icons) {
 		icon.fadeIn.step(ms);
 		icon.fadeOut.step(ms);
 	}
 	removeFadeOutedIcons();
 
-	auto selectionLevel = _selection.current(_checked ? 1. : 0.);
+	auto cacheSize = kWideScale * _st.size * cIntRetinaFactor();
+	auto cacheFrom = QRect(0, 0, cacheSize, cacheSize);
+	auto displayInactive = !_inactiveCacheBg.isNull();
+	auto inactiveTo = cacheDestRect(x, y, masterScale);
+	p.setRenderHint(QPainter::SmoothPixmapTransform, true);
+	if (!_inactiveCacheBg.isNull()) {
+		p.drawPixmap(inactiveTo, _inactiveCacheBg, cacheFrom);
+	}
+	for (auto &icon : _icons) {
+		auto fadeIn = icon.fadeIn.current(1.);
+		auto fadeOut = icon.fadeOut.current(1.);
+		auto to = cacheDestRect(x, y, (1. - (1. - _st.sizeSmall) * (1. - fadeOut)) * masterScale);
+		p.setOpacity(fadeIn * fadeOut);
+		if (fadeOut < 1.) {
+			p.drawPixmapLeft(to, outerWidth, icon.wideCheckCache, cacheFrom);
+		} else {
+			auto realDivider = ((kWideScale - 1) * _st.size / 2 + qMax(fadeIn - 0.5, 0.) * 2. * _st.size);
+			auto divider = qRound(realDivider * masterScale);
+			auto cacheDivider = qRound(realDivider) * cIntRetinaFactor();
+			p.drawPixmapLeft(QRect(to.x(), to.y(), divider, to.height()), outerWidth, _wideCheckFullCache, QRect(0, 0, cacheDivider, cacheFrom.height()));
+			p.drawPixmapLeft(QRect(to.x() + divider, to.y(), to.width() - divider, to.height()), outerWidth, _wideCheckBgCache, QRect(cacheDivider, 0, cacheFrom.width() - cacheDivider, _wideCheckBgCache.height()));
+		}
+	}
+	p.setOpacity(1.);
+	if (!_inactiveCacheFg.isNull()) {
+		p.drawPixmap(inactiveTo, _inactiveCacheFg, cacheFrom);
+	}
+	p.setRenderHint(QPainter::SmoothPixmapTransform, false);
+}
+
+void RoundCheckbox::setChecked(bool newChecked, SetStyle speed) {
+	if (_checked == newChecked) {
+		if (speed != SetStyle::Animated && !_icons.isEmpty()) {
+			_icons.back().fadeIn.finish();
+			_icons.back().fadeOut.finish();
+		}
+		return;
+	}
+	_checked = newChecked;
+	if (_checked) {
+		if (_wideCheckBgCache.isNull()) {
+			prepareCheckCaches(&_st, _displayInactive, _wideCheckBgCache, _wideCheckFullCache);
+		}
+		_icons.push_back(Icon());
+		_icons.back().fadeIn.start(_updateCallback, 0, 1, _st.duration);
+		if (speed != SetStyle::Animated) {
+			_icons.back().fadeIn.finish();
+		}
+	} else {
+		if (speed == SetStyle::Animated) {
+			prepareWideCheckIconCache(&_icons.back());
+		}
+		_icons.back().fadeOut.start(_updateCallback, 1, 0, _st.duration);
+		if (speed != SetStyle::Animated) {
+			_icons.back().fadeOut.finish();
+		}
+	}
+}
+
+void RoundCheckbox::setDisplayInactive(bool displayInactive) {
+	if (_displayInactive != displayInactive) {
+		_displayInactive = displayInactive;
+		if (_displayInactive) {
+			prepareInactiveCache();
+		} else {
+			_inactiveCacheBg = _inactiveCacheFg = QPixmap();
+		}
+		if (!_wideCheckBgCache.isNull()) {
+			prepareCheckCaches(&_st, _displayInactive, _wideCheckBgCache, _wideCheckFullCache);
+		}
+		for (auto &icon : _icons) {
+			if (!icon.wideCheckCache.isNull()) {
+				prepareWideCheckIconCache(&icon);
+			}
+		}
+	}
+}
+
+void RoundCheckbox::removeFadeOutedIcons() {
+	while (!_icons.empty() && !_icons.front().fadeIn.animating() && !_icons.front().fadeOut.animating()) {
+		if (_icons.size() > 1 || !_checked) {
+			_icons.erase(_icons.begin());
+		} else {
+			break;
+		}
+	}
+}
+
+void RoundCheckbox::prepareWideCheckIconCache(Icon *icon) {
+	auto cacheWidth = _wideCheckBgCache.width() / _wideCheckBgCache.devicePixelRatio();
+	auto cacheHeight = _wideCheckBgCache.height() / _wideCheckBgCache.devicePixelRatio();
+	auto wideCache = QImage(cacheWidth * cIntRetinaFactor(), cacheHeight * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
+	wideCache.setDevicePixelRatio(cRetinaFactor());
+	{
+		Painter p(&wideCache);
+		p.setCompositionMode(QPainter::CompositionMode_Source);
+		auto iconSize = kWideScale * _st.size;
+		auto divider = qRound((kWideScale - 1) * _st.size / 2 + qMax(icon->fadeIn.current(1.) - 0.5, 0.) * 2. * _st.size);
+		p.drawPixmapLeft(QRect(0, 0, divider, iconSize), cacheWidth, _wideCheckFullCache, QRect(0, 0, divider * cIntRetinaFactor(), _wideCheckFullCache.height()));
+		p.drawPixmapLeft(QRect(divider, 0, iconSize - divider, iconSize), cacheWidth, _wideCheckBgCache, QRect(divider * cIntRetinaFactor(), 0, _wideCheckBgCache.width() - divider * cIntRetinaFactor(), _wideCheckBgCache.height()));
+	}
+	icon->wideCheckCache = App::pixmapFromImageInPlace(std_::move(wideCache));
+	icon->wideCheckCache.setDevicePixelRatio(cRetinaFactor());
+}
+
+void RoundCheckbox::prepareInactiveCache() {
+	auto wideSize = _st.size * kWideScale;
+	auto ellipse = QRect((wideSize - _st.size) / 2, (wideSize - _st.size) / 2, _st.size, _st.size);
+
+	auto cacheBg = QImage(wideSize * cIntRetinaFactor(), wideSize * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
+	cacheBg.setDevicePixelRatio(cRetinaFactor());
+	cacheBg.fill(Qt::transparent);
+	auto cacheFg = cacheBg;
+	if (_st.bgInactive) {
+		Painter p(&cacheBg);
+		p.setRenderHint(QPainter::HighQualityAntialiasing, true);
+		p.setPen(Qt::NoPen);
+		p.setBrush(_st.bgInactive);
+		p.drawEllipse(ellipse);
+	}
+	_inactiveCacheBg = App::pixmapFromImageInPlace(std_::move(cacheBg));
+
+	{
+		Painter p(&cacheFg);
+		p.setRenderHint(QPainter::HighQualityAntialiasing, true);
+		auto pen = _st.border->p;
+		pen.setWidth(_st.width);
+		p.setPen(pen);
+		p.setBrush(Qt::NoBrush);
+		p.drawEllipse(ellipse);
+	}
+	_inactiveCacheFg = App::pixmapFromImageInPlace(std_::move(cacheFg));
+}
+
+RoundImageCheckbox::RoundImageCheckbox(const style::RoundImageCheckbox &st, const base::lambda_copy<void()> &updateCallback, PaintRoundImage &&paintRoundImage)
+: _st(st)
+, _updateCallback(updateCallback)
+, _paintRoundImage(std_::move(paintRoundImage))
+, _check(_st.check, _updateCallback) {
+}
+
+void RoundImageCheckbox::paint(Painter &p, uint64 ms, int x, int y, int outerWidth) {
+	_selection.step(ms);
+
+	auto selectionLevel = _selection.current(checked() ? 1. : 0.);
 	if (_selection.animating()) {
 		auto userpicRadius = qRound(kWideScale * (_st.imageRadius + (_st.imageSmallRadius - _st.imageRadius) * selectionLevel));
 		auto userpicShift = kWideScale * _st.imageRadius - userpicRadius;
@@ -89,7 +242,7 @@ void RoundImageCheckbox::paint(Painter &p, uint64 ms, int x, int y, int outerWid
 		if (!_wideCache.isNull()) {
 			_wideCache = QPixmap();
 		}
-		auto userpicRadius = _checked ? _st.imageSmallRadius : _st.imageRadius;
+		auto userpicRadius = checked() ? _st.imageSmallRadius : _st.imageRadius;
 		auto userpicShift = _st.imageRadius - userpicRadius;
 		auto userpicLeft = x + userpicShift;
 		auto userpicTop = y + userpicShift;
@@ -108,78 +261,32 @@ void RoundImageCheckbox::paint(Painter &p, uint64 ms, int x, int y, int outerWid
 		p.setRenderHint(QPainter::HighQualityAntialiasing, false);
 	}
 
-	p.setRenderHint(QPainter::SmoothPixmapTransform, true);
-	for (auto &icon : _icons) {
-		auto fadeIn = icon.fadeIn.current(1.);
-		auto fadeOut = icon.fadeOut.current(1.);
-		auto iconRadius = qRound(kWideScale * (_st.checkSmallRadius + fadeOut * (_st.checkRadius - _st.checkSmallRadius)));
-		auto iconShift = kWideScale * _st.checkRadius - iconRadius;
-		auto iconLeft = x + 2 * _st.imageRadius + _st.selectWidth - 2 * _st.checkRadius - (kWideScale - 1) * _st.checkRadius + iconShift;
-		auto iconTop = y + 2 * _st.imageRadius + _st.selectWidth - 2 * _st.checkRadius - (kWideScale - 1) * _st.checkRadius + iconShift;
-		auto to = QRect(iconLeft, iconTop, iconRadius * 2, iconRadius * 2);
-		auto from = QRect(QPoint(0, 0), _wideCheckFullCache.size());
-		auto opacity = fadeIn * fadeOut;
-		p.setOpacity(opacity);
-		if (fadeOut < 1.) {
-			p.drawPixmapLeft(to, outerWidth, icon.wideCheckCache, from);
-		} else {
-			auto divider = qRound((kWideScale - 2) * _st.checkRadius + fadeIn * 3 * _st.checkRadius);
-			p.drawPixmapLeft(QRect(iconLeft, iconTop, divider, iconRadius * 2), outerWidth, _wideCheckFullCache, QRect(0, 0, divider * cIntRetinaFactor(), _wideCheckFullCache.height()));
-			p.drawPixmapLeft(QRect(iconLeft + divider, iconTop, iconRadius * 2 - divider, iconRadius * 2), outerWidth, _wideCheckBgCache, QRect(divider * cIntRetinaFactor(), 0, _wideCheckBgCache.width() - divider * cIntRetinaFactor(), _wideCheckBgCache.height()));
-		}
-	}
-	p.setRenderHint(QPainter::SmoothPixmapTransform, false);
-	p.setOpacity(1.);
+	auto iconLeft = x + 2 * _st.imageRadius + _st.selectWidth - _st.check.size;
+	auto iconTop = y + 2 * _st.imageRadius + _st.selectWidth - _st.check.size;
+	_check.paint(p, ms, iconLeft, iconTop, outerWidth);
 }
 
 float64 RoundImageCheckbox::checkedAnimationRatio() const {
-	return snap(_selection.current(_checked ? 1. : 0.), 0., 1.);
+	return snap(_selection.current(checked() ? 1. : 0.), 0., 1.);
 }
 
-void RoundImageCheckbox::setChecked(bool checked, SetStyle speed) {
-	if (_checked == checked) {
+void RoundImageCheckbox::setChecked(bool newChecked, SetStyle speed) {
+	auto changed = (checked() != newChecked);
+	_check.setChecked(newChecked, speed);
+	if (!changed) {
 		if (speed != SetStyle::Animated) {
-			if (!_icons.isEmpty()) {
-				_icons.back().fadeIn.finish();
-				_icons.back().fadeOut.finish();
-			}
 			_selection.finish();
 		}
 		return;
 	}
-	_checked = checked;
-	if (_checked) {
-		_icons.push_back(Icon());
-		_icons.back().fadeIn.start(_updateCallback, 0, 1, _st.selectDuration);
-		if (speed != SetStyle::Animated) {
-			_icons.back().fadeIn.finish();
-		}
-	} else {
-		_icons.back().fadeOut.start(_updateCallback, 1, 0, _st.selectDuration);
-		if (speed == SetStyle::Animated) {
-			prepareWideCheckIconCache(&_icons.back());
-		} else {
-			_icons.back().fadeOut.finish();
-		}
-	}
 	if (speed == SetStyle::Animated) {
 		prepareWideCache();
-		_selection.start(_updateCallback, _checked ? 0 : 1, _checked ? 1 : 0, _st.selectDuration, anim::bumpy(1.25));
+		_selection.start(_updateCallback, checked() ? 0 : 1, checked() ? 1 : 0, _st.selectDuration, anim::bumpy(1.25));
 	} else {
 		_selection.finish();
 	}
 }
 
-void RoundImageCheckbox::removeFadeOutedIcons() {
-	while (!_icons.empty() && !_icons.front().fadeIn.animating() && !_icons.front().fadeOut.animating()) {
-		if (_icons.size() > 1 || !_checked) {
-			_icons.erase(_icons.begin());
-		} else {
-			break;
-		}
-	}
-}
-
 void RoundImageCheckbox::prepareWideCache() {
 	if (_wideCache.isNull()) {
 		auto size = _st.imageRadius * 2;
@@ -197,21 +304,4 @@ void RoundImageCheckbox::prepareWideCache() {
 	}
 }
 
-void RoundImageCheckbox::prepareWideCheckIconCache(Icon *icon) {
-	auto cacheWidth = _wideCheckBgCache.width() / _wideCheckBgCache.devicePixelRatio();
-	auto cacheHeight = _wideCheckBgCache.height() / _wideCheckBgCache.devicePixelRatio();
-	auto wideCache = QImage(cacheWidth * cIntRetinaFactor(), cacheHeight * cIntRetinaFactor(), QImage::Format_ARGB32_Premultiplied);
-	wideCache.setDevicePixelRatio(cRetinaFactor());
-	{
-		Painter p(&wideCache);
-		p.setCompositionMode(QPainter::CompositionMode_Source);
-		auto iconRadius = kWideScale * _st.checkRadius;
-		auto divider = qRound((kWideScale - 2) * _st.checkRadius + icon->fadeIn.current(1.) * (kWideScale - 1) * _st.checkRadius);
-		p.drawPixmapLeft(QRect(0, 0, divider, iconRadius * 2), cacheWidth, _wideCheckFullCache, QRect(0, 0, divider * cIntRetinaFactor(), _wideCheckFullCache.height()));
-		p.drawPixmapLeft(QRect(divider, 0, iconRadius * 2 - divider, iconRadius * 2), cacheWidth, _wideCheckBgCache, QRect(divider * cIntRetinaFactor(), 0, _wideCheckBgCache.width() - divider * cIntRetinaFactor(), _wideCheckBgCache.height()));
-	}
-	icon->wideCheckCache = App::pixmapFromImageInPlace(std_::move(wideCache));
-	icon->wideCheckCache.setDevicePixelRatio(cRetinaFactor());
-}
-
 } // namespace Ui
diff --git a/Telegram/SourceFiles/ui/effects/round_image_checkbox.h b/Telegram/SourceFiles/ui/effects/round_image_checkbox.h
index 67b5d91f8..b528bced8 100644
--- a/Telegram/SourceFiles/ui/effects/round_image_checkbox.h
+++ b/Telegram/SourceFiles/ui/effects/round_image_checkbox.h
@@ -24,6 +24,47 @@ Copyright (c) 2014-2016 John Preston, https://desktop.telegram.org
 
 namespace Ui {
 
+class RoundCheckbox {
+public:
+	RoundCheckbox(const style::RoundCheckbox &st, const base::lambda_copy<void()> &updateCallback);
+
+	void paint(Painter &p, uint64 ms, int x, int y, int outerWidth, float64 masterScale = 1.);
+
+	void setDisplayInactive(bool displayInactive);
+	bool checked() const {
+		return _checked;
+	}
+	enum class SetStyle {
+		Animated,
+		Fast,
+	};
+	void setChecked(bool newChecked, SetStyle speed = SetStyle::Animated);
+
+private:
+	struct Icon {
+		FloatAnimation fadeIn;
+		FloatAnimation fadeOut;
+		QPixmap wideCheckCache;
+	};
+	void removeFadeOutedIcons();
+	void prepareWideCheckIconCache(Icon *icon);
+	void prepareInactiveCache();
+	QRect cacheDestRect(int x, int y, float64 scale) const;
+
+	const style::RoundCheckbox &_st;
+	base::lambda_copy<void()> _updateCallback;
+
+	bool _checked = false;
+	std_::vector_of_moveable<Icon> _icons;
+
+	bool _displayInactive = false;
+	QPixmap _inactiveCacheBg, _inactiveCacheFg;
+
+	// Those pixmaps are shared among all checkboxes that have the same style.
+	QPixmap _wideCheckBgCache, _wideCheckFullCache;
+
+};
+
 class RoundImageCheckbox {
 public:
 	using PaintRoundImage = base::lambda<void(Painter &p, int x, int y, int outerWidth, int size)>;
@@ -33,35 +74,22 @@ public:
 	float64 checkedAnimationRatio() const;
 
 	bool checked() const {
-		return _checked;
+		return _check.checked();
 	}
-	enum class SetStyle {
-		Animated,
-		Fast,
-	};
-	void setChecked(bool checked, SetStyle speed = SetStyle::Animated);
+	using SetStyle = RoundCheckbox::SetStyle;
+	void setChecked(bool newChecked, SetStyle speed = SetStyle::Animated);
 
 private:
-	struct Icon {
-		FloatAnimation fadeIn;
-		FloatAnimation fadeOut;
-		QPixmap wideCheckCache;
-	};
-	void removeFadeOutedIcons();
 	void prepareWideCache();
-	void prepareWideCheckIconCache(Icon *icon);
 
 	const style::RoundImageCheckbox &_st;
 	base::lambda_copy<void()> _updateCallback;
 	PaintRoundImage _paintRoundImage;
 
-	bool _checked = false;
 	QPixmap _wideCache;
 	FloatAnimation _selection;
-	std_::vector_of_moveable<Icon> _icons;
 
-	// Those pixmaps are shared among all checkboxes that have the same style.
-	QPixmap _wideCheckBgCache, _wideCheckFullCache;
+	RoundCheckbox _check;
 
 };
 
diff --git a/Telegram/SourceFiles/ui/widgets/widgets.style b/Telegram/SourceFiles/ui/widgets/widgets.style
index df6840fd3..9e8680571 100644
--- a/Telegram/SourceFiles/ui/widgets/widgets.style
+++ b/Telegram/SourceFiles/ui/widgets/widgets.style
@@ -319,17 +319,24 @@ FilledSlider {
 	duration: int;
 }
 
+RoundCheckbox {
+	border: color;
+	bgInactive: color;
+	bgActive: color;
+	width: pixels;
+	size: pixels;
+	sizeSmall: double;
+	duration: int;
+	check: icon;
+}
+
 RoundImageCheckbox {
 	imageRadius: pixels;
 	imageSmallRadius: pixels;
 	selectWidth: pixels;
 	selectFg: color;
 	selectDuration: int;
-	checkBorder: color;
-	checkBg: color;
-	checkRadius: pixels;
-	checkSmallRadius: pixels;
-	checkIcon: icon;
+	check: RoundCheckbox;
 }
 
 MultiSelectItem {
@@ -738,6 +745,13 @@ defaultPanelAnimation: PanelAnimation {
 	shadow: defaultRoundShadow;
 }
 
+defaultRoundCheckbox: RoundCheckbox {
+	border: windowBg;
+	bgActive: windowBgActive;
+	width: 2px;
+	duration: 150;
+}
+
 defaultMenuArrow: icon {{ "dropdown_submenu_arrow", #373737 }};
 defaultMenu: Menu {
 	skip: 0px;