diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp
index 6db3a13c9..bbee8c3b2 100644
--- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp
+++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.cpp
@@ -516,6 +516,7 @@ Manager::Private::Private(not_null<Manager*> manager, Type type)
 
 void Manager::Private::showNotification(
 		not_null<PeerData*> peer,
+		std::shared_ptr<Data::CloudImageView> &userpicView,
 		MsgId msgId,
 		const QString &title,
 		const QString &subtitle,
@@ -607,6 +608,7 @@ Manager::~Manager() = default;
 
 void Manager::doShowNativeNotification(
 		not_null<PeerData*> peer,
+		std::shared_ptr<Data::CloudImageView> &userpicView,
 		MsgId msgId,
 		const QString &title,
 		const QString &subtitle,
@@ -615,6 +617,7 @@ void Manager::doShowNativeNotification(
 		bool hideReplyButton) {
 	_private->showNotification(
 		peer,
+		userpicView,
 		msgId,
 		title,
 		subtitle,
diff --git a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h
index 1005c0403..ff9a68b6f 100644
--- a/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h
+++ b/Telegram/SourceFiles/platform/linux/notifications_manager_linux.h
@@ -90,6 +90,7 @@ public:
 protected:
 	void doShowNativeNotification(
 		not_null<PeerData*> peer,
+		std::shared_ptr<Data::CloudImageView> &userpicView,
 		MsgId msgId,
 		const QString &title,
 		const QString &subtitle,
@@ -112,6 +113,7 @@ public:
 
 	void showNotification(
 		not_null<PeerData*> peer,
+		std::shared_ptr<Data::CloudImageView> &userpicView,
 		MsgId msgId,
 		const QString &title,
 		const QString &subtitle,
diff --git a/Telegram/SourceFiles/platform/mac/mac_touchbar.mm b/Telegram/SourceFiles/platform/mac/mac_touchbar.mm
index 5b9888f21..6322cf68c 100644
--- a/Telegram/SourceFiles/platform/mac/mac_touchbar.mm
+++ b/Telegram/SourceFiles/platform/mac/mac_touchbar.mm
@@ -22,6 +22,7 @@
 #include "data/data_folder.h"
 #include "data/data_peer_values.h"
 #include "data/data_session.h"
+#include "data/data_cloud_file.h"
 #include "dialogs/dialogs_layout.h"
 #include "ui/emoji_config.h"
 #include "history/history.h"
@@ -178,12 +179,12 @@ inline bool CurrentSongExists() {
 	return Media::Player::instance()->current(kSongType).audio() != nullptr;
 }
 
-inline bool UseEmptyUserpic(PeerData *peer) {
-	return (peer && (peer->useEmptyUserpic() || peer->isSelf()));
+inline bool UseEmptyUserpic(PeerData *peer, std::shared_ptr<Data::CloudImageView> &userpic) {
+	return peer && (peer->useEmptyUserpic(userpic) || peer->isSelf());
 }
 
 inline bool IsSelfPeer(PeerData *peer) {
-	return (peer && peer->isSelf());
+	return peer && peer->isSelf();
 }
 
 inline int UnreadCount(not_null<PeerData*> peer) {
@@ -484,6 +485,7 @@ void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
 	rpl::lifetime _lifetime;
 	rpl::lifetime _peerChangedLifetime;
 	base::has_weak_ptr _guard;
+	std::shared_ptr<Data::CloudImageView> _userpicView;
 
 	bool isWaitingUserpicLoad;
 }
@@ -523,7 +525,7 @@ void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
 		return update.paletteChanged();
 	}) | rpl::start_with_next([=] {
 		crl::on_main(&_guard, [=] {
-			if (_number <= kSavedMessagesId || UseEmptyUserpic(_peer)) {
+			if (_number <= kSavedMessagesId || UseEmptyUserpic(_peer, _userpicView)) {
 				[self updateUserpic];
 			} else if (_peer
 				&& (UnreadCount(_peer) || Data::IsPeerAnOnlineUser(_peer))) {
@@ -556,8 +558,10 @@ void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
 	_peerChangedLifetime.destroy();
 	_peer = newPeer;
 	if (!_peer || IsSelfPeer(_peer)) {
+		_userpicView = nullptr;
 		return;
 	}
+	_userpicView = _peer->createUserpicView();
 	Notify::PeerUpdateViewer(
 		_peer,
 		Notify::PeerUpdate::Flag::PhotoChanged
@@ -613,7 +617,9 @@ void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
 			Ui::EmptyUserpic::PaintSavedMessages(paint, 0, 0, s, s);
 		} else if (const auto folder =
 				Auth().data().folderLoaded(Data::Folder::kId)) {
-			folder->paintUserpic(paint, 0, 0, s);
+			// Not used in the folders.
+			auto view = std::shared_ptr<Data::CloudImageView>();
+			folder->paintUserpic(paint, view, 0, 0, s);
 		}
 		_userpic.setDevicePixelRatio(cRetinaFactor());
 		[self updateImage:_userpic];
@@ -622,8 +628,8 @@ void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
 	if (!self.peer) {
 		return;
 	}
-	isWaitingUserpicLoad = !self.peer->userpicLoaded();
-	_userpic = self.peer->genUserpic(kIdealIconSize);
+	isWaitingUserpicLoad = _userpicView && !_userpicView->image();
+	_userpic = self.peer->genUserpic(_userpicView, kIdealIconSize);
 	_userpic.setDevicePixelRatio(cRetinaFactor());
 	[self updateBadge];
 }
@@ -681,24 +687,20 @@ void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
 	if (!document->sticker()) {
 		return;
 	}
+	documentData = document;
 	_media = document->createMediaView();
+	_media->checkStickerSmall();
 	_image = _media->getStickerSmall();
-	if (!_image) {
-		return;
-	}
-	fileOrigin = document->stickerSetOrigin();
-	documentData = std::move(document);
-	_dimensions = document->dimensions;
-	_image->load(fileOrigin);
-	if (_image->loaded()) {
+	if (_image) {
+		_dimensions = document->dimensions;
 		[self updateImage];
 		return;
 	}
-
 	base::ObservableViewer(
 		Auth().downloaderTaskFinished()
 	) | rpl::start_with_next([=] {
-		if (_image->loaded()) {
+		_image = _media->getStickerSmall();
+		if (_image) {
 			[self updateImage];
 			_lifetime.destroy();
 		}
@@ -708,13 +710,13 @@ void AppendEmojiPacks(std::vector<PickerScrubberItem> &to) {
 	const auto size = _dimensions
 			.scaled(kCircleDiameter, kCircleDiameter, Qt::KeepAspectRatio);
 	_imageView.image = [qt_mac_create_nsimage(
-			_image->pixSingle(
-				size.width(),
-				size.height(),
-				kCircleDiameter,
-				kCircleDiameter,
-				ImageRoundRadius::None))
-		autorelease];
+		_image->pixSingle(
+			size.width(),
+			size.height(),
+			kCircleDiameter,
+			kCircleDiameter,
+			ImageRoundRadius::None))
+	autorelease];
 }
 @end // @implementation PickerScrubberItemView
 
diff --git a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h
index 59a741d0c..af0bffb0e 100644
--- a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h
+++ b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.h
@@ -21,6 +21,7 @@ public:
 protected:
 	void doShowNativeNotification(
 		not_null<PeerData*> peer,
+		std::shared_ptr<Data::CloudImageView> &userpicView,
 		MsgId msgId,
 		const QString &title,
 		const QString &subtitle,
diff --git a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm
index 6f0e0b765..4bdcc0108 100644
--- a/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm
+++ b/Telegram/SourceFiles/platform/mac/notifications_manager_mac.mm
@@ -164,6 +164,7 @@ public:
 
 	void showNotification(
 		not_null<PeerData*> peer,
+		std::shared_ptr<Data::CloudImageView> &userpicView,
 		MsgId msgId,
 		const QString &title,
 		const QString &subtitle,
@@ -219,6 +220,7 @@ Manager::Private::Private(Manager *manager)
 
 void Manager::Private::showNotification(
 		not_null<PeerData*> peer,
+		std::shared_ptr<Data::CloudImageView> &userpicView,
 		MsgId msgId,
 		const QString &title,
 		const QString &subtitle,
@@ -241,7 +243,7 @@ void Manager::Private::showNotification(
 	if (!hideNameAndPhoto && [notification respondsToSelector:@selector(setContentImage:)]) {
 		auto userpic = peer->isSelf()
 			? Ui::EmptyUserpic::GenerateSavedMessages(st::notifyMacPhotoSize)
-			: peer->genUserpic(st::notifyMacPhotoSize);
+			: peer->genUserpic(userpicView, st::notifyMacPhotoSize);
 		NSImage *img = [qt_mac_create_nsimage(userpic) autorelease];
 		[notification setContentImage:img];
 	}
@@ -349,6 +351,7 @@ Manager::~Manager() = default;
 
 void Manager::doShowNativeNotification(
 		not_null<PeerData*> peer,
+		std::shared_ptr<Data::CloudImageView> &userpicView,
 		MsgId msgId,
 		const QString &title,
 		const QString &subtitle,
@@ -357,6 +360,7 @@ void Manager::doShowNativeNotification(
 		bool hideReplyButton) {
 	_private->showNotification(
 		peer,
+		userpicView,
 		msgId,
 		title,
 		subtitle,
diff --git a/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp b/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp
index 56110739e..bffb0bae7 100644
--- a/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp
+++ b/Telegram/SourceFiles/platform/win/notifications_manager_win.cpp
@@ -343,6 +343,7 @@ public:
 
 	bool showNotification(
 		not_null<PeerData*> peer,
+		std::shared_ptr<Data::CloudImageView> &userpicView,
 		MsgId msgId,
 		const QString &title,
 		const QString &subtitle,
@@ -455,6 +456,7 @@ void Manager::Private::clearNotification(PeerId peerId, MsgId msgId) {
 
 bool Manager::Private::showNotification(
 		not_null<PeerData*> peer,
+		std::shared_ptr<Data::CloudImageView> &userpicView,
 		MsgId msgId,
 		const QString &title,
 		const QString &subtitle,
@@ -478,11 +480,10 @@ bool Manager::Private::showNotification(
 	hr = SetAudioSilent(toastXml.Get());
 	if (!SUCCEEDED(hr)) return false;
 
-	auto view = std::shared_ptr<Data::CloudImageView>(); // #TODO optimize
 	const auto key = hideNameAndPhoto
 		? InMemoryKey()
-		: peer->userpicUniqueKey(view);
-	const auto userpicPath = _cachedUserpics.get(key, peer, view);
+		: peer->userpicUniqueKey(userpicView);
+	const auto userpicPath = _cachedUserpics.get(key, peer, userpicView);
 	const auto userpicPathWide = QDir::toNativeSeparators(userpicPath).toStdWString();
 
 	hr = SetImageSrc(userpicPathWide.c_str(), toastXml.Get());
@@ -582,6 +583,7 @@ Manager::~Manager() = default;
 
 void Manager::doShowNativeNotification(
 		not_null<PeerData*> peer,
+		std::shared_ptr<Data::CloudImageView> &userpicView,
 		MsgId msgId,
 		const QString &title,
 		const QString &subtitle,
@@ -590,6 +592,7 @@ void Manager::doShowNativeNotification(
 		bool hideReplyButton) {
 	_private->showNotification(
 		peer,
+		userpicView,
 		msgId,
 		title,
 		subtitle,
diff --git a/Telegram/SourceFiles/platform/win/notifications_manager_win.h b/Telegram/SourceFiles/platform/win/notifications_manager_win.h
index 4a8a2c5f6..6068270fd 100644
--- a/Telegram/SourceFiles/platform/win/notifications_manager_win.h
+++ b/Telegram/SourceFiles/platform/win/notifications_manager_win.h
@@ -26,6 +26,7 @@ public:
 protected:
 	void doShowNativeNotification(
 		not_null<PeerData*> peer,
+		std::shared_ptr<Data::CloudImageView> &userpicView,
 		MsgId msgId,
 		const QString &title,
 		const QString &subtitle,
diff --git a/Telegram/SourceFiles/ui/image/image.cpp b/Telegram/SourceFiles/ui/image/image.cpp
index 24c1e46ee..59b265b1f 100644
--- a/Telegram/SourceFiles/ui/image/image.cpp
+++ b/Telegram/SourceFiles/ui/image/image.cpp
@@ -160,7 +160,7 @@ const QPixmap &Image::pix(int w, int h) const {
 	if (i == _cache.cend()) {
 		auto p = pixNoCache(w, h, options);
 		p.setDevicePixelRatio(cRetinaFactor());
-		i = _cache.emplace(k, p).first;
+		i = _cache.emplace_or_assign(k, p).first;
 	}
 	return i->second;
 }
@@ -195,7 +195,7 @@ const QPixmap &Image::pixRounded(
 	if (i == _cache.cend()) {
 		auto p = pixNoCache(w, h, options);
 		p.setDevicePixelRatio(cRetinaFactor());
-		i = _cache.emplace(k, p).first;
+		i = _cache.emplace_or_assign(k, p).first;
 	}
 	return i->second;
 }
@@ -213,7 +213,7 @@ const QPixmap &Image::pixCircled(int w, int h) const {
 	if (i == _cache.cend()) {
 		auto p = pixNoCache(w, h, options);
 		p.setDevicePixelRatio(cRetinaFactor());
-		i = _cache.emplace(k, p).first;
+		i = _cache.emplace_or_assign(k, p).first;
 	}
 	return i->second;
 }
@@ -231,7 +231,7 @@ const QPixmap &Image::pixBlurredCircled(int w, int h) const {
 	if (i == _cache.cend()) {
 		auto p = pixNoCache(w, h, options);
 		p.setDevicePixelRatio(cRetinaFactor());
-		i = _cache.emplace(k, p).first;
+		i = _cache.emplace_or_assign(k, p).first;
 	}
 	return i->second;
 }
@@ -249,7 +249,7 @@ const QPixmap &Image::pixBlurred(int w, int h) const {
 	if (i == _cache.cend()) {
 		auto p = pixNoCache(w, h, options);
 		p.setDevicePixelRatio(cRetinaFactor());
-		i = _cache.emplace(k, p).first;
+		i = _cache.emplace_or_assign(k, p).first;
 	}
 	return i->second;
 }
@@ -267,7 +267,7 @@ const QPixmap &Image::pixColored(style::color add, int w, int h) const {
 	if (i == _cache.cend()) {
 		auto p = pixColoredNoCache(add, w, h, true);
 		p.setDevicePixelRatio(cRetinaFactor());
-		i = _cache.emplace(k, p).first;
+		i = _cache.emplace_or_assign(k, p).first;
 	}
 	return i->second;
 }
@@ -288,7 +288,7 @@ const QPixmap &Image::pixBlurredColored(
 	if (i == _cache.cend()) {
 		auto p = pixBlurredColoredNoCache(add, w, h);
 		p.setDevicePixelRatio(cRetinaFactor());
-		i = _cache.emplace(k, p).first;
+		i = _cache.emplace_or_assign(k, p).first;
 	}
 	return i->second;
 }
@@ -331,7 +331,7 @@ const QPixmap &Image::pixSingle(
 	if (i == _cache.cend() || i->second.width() != (outerw * cIntRetinaFactor()) || i->second.height() != (outerh * cIntRetinaFactor())) {
 		auto p = pixNoCache(w, h, options, outerw, outerh, colored);
 		p.setDevicePixelRatio(cRetinaFactor());
-		i = _cache.emplace(k, p).first;
+		i = _cache.emplace_or_assign(k, p).first;
 	}
 	return i->second;
 }
@@ -370,7 +370,7 @@ const QPixmap &Image::pixBlurredSingle(
 	if (i == _cache.cend() || i->second.width() != (outerw * cIntRetinaFactor()) || i->second.height() != (outerh * cIntRetinaFactor())) {
 		auto p = pixNoCache(w, h, options, outerw, outerh);
 		p.setDevicePixelRatio(cRetinaFactor());
-		i = _cache.emplace(k, p).first;
+		i = _cache.emplace_or_assign(k, p).first;
 	}
 	return i->second;
 }
diff --git a/Telegram/SourceFiles/window/notifications_manager.cpp b/Telegram/SourceFiles/window/notifications_manager.cpp
index 8ef2f0cae..ac06bddb5 100644
--- a/Telegram/SourceFiles/window/notifications_manager.cpp
+++ b/Telegram/SourceFiles/window/notifications_manager.cpp
@@ -587,8 +587,11 @@ void NativeManager::doShowNotification(
 				: item->notificationText())
 			: tr::lng_forward_messages(tr::now, lt_count, forwardedCount));
 
+	// #TODO optimize
+	auto userpicView = item->history()->peer->createUserpicView();
 	doShowNativeNotification(
 		item->history()->peer,
+		userpicView,
 		item->id,
 		scheduled ? WrapFromScheduled(title) : title,
 		subtitle,
diff --git a/Telegram/SourceFiles/window/notifications_manager.h b/Telegram/SourceFiles/window/notifications_manager.h
index b9c6ecceb..ba9b737ca 100644
--- a/Telegram/SourceFiles/window/notifications_manager.h
+++ b/Telegram/SourceFiles/window/notifications_manager.h
@@ -11,6 +11,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 
 class History;
 
+namespace Data {
+class CloudImageView;
+} // namespace Data
+
 namespace Main {
 class Session;
 } // namespace Main
@@ -219,6 +223,7 @@ protected:
 
 	virtual void doShowNativeNotification(
 		not_null<PeerData*> peer,
+		std::shared_ptr<Data::CloudImageView> &userpicView,
 		MsgId msgId,
 		const QString &title,
 		const QString &subtitle,