diff --git a/Telegram/SourceFiles/boxes/sticker_set_box.cpp b/Telegram/SourceFiles/boxes/sticker_set_box.cpp
index 478cf8ebc..37d63cc65 100644
--- a/Telegram/SourceFiles/boxes/sticker_set_box.cpp
+++ b/Telegram/SourceFiles/boxes/sticker_set_box.cpp
@@ -10,6 +10,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "data/data_document.h"
 #include "data/data_session.h"
 #include "data/data_file_origin.h"
+#include "data/data_document_media.h"
 #include "lang/lang_keys.h"
 #include "chat_helpers/stickers.h"
 #include "boxes/confirm_box.h"
@@ -72,6 +73,7 @@ protected:
 private:
 	struct Element {
 		not_null<DocumentData*> document;
+		std::shared_ptr<Data::DocumentMedia> documentMedia;
 		Lottie::Animation *animated = nullptr;
 		Ui::Animations::Simple overAnimation;
 	};
@@ -267,7 +269,7 @@ void StickerSetBox::Inner::gotSet(const MTPmessages_StickerSet &set) {
 				continue;
 			}
 			_pack.push_back(document);
-			_elements.push_back({ document });
+			_elements.push_back({ document, document->createMediaView() });
 		}
 		for (const auto &pack : data.vpacks().v) {
 			pack.match([&](const MTPDstickerPack &pack) {
@@ -621,7 +623,8 @@ void StickerSetBox::Inner::paintSticker(
 
 	const auto &element = _elements[index];
 	const auto document = element.document;
-	document->checkStickerSmall();
+	const auto &media = element.documentMedia;
+	media->checkStickerSmall();
 
 	if (document->sticker()->animated
 		&& !element.animated
@@ -650,7 +653,7 @@ void StickerSetBox::Inner::paintSticker(
 			frame);
 
 		_lottiePlayer->unpause(element.animated);
-	} else if (const auto image = document->getStickerSmall()) {
+	} else if (const auto image = media->getStickerSmall()) {
 		p.drawPixmapLeft(
 			ppos,
 			width(),
diff --git a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp
index a08ee6f9b..d14f92a8f 100644
--- a/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp
+++ b/Telegram/SourceFiles/chat_helpers/field_autocomplete.cpp
@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "chat_helpers/field_autocomplete.h"
 
 #include "data/data_document.h"
+#include "data/data_document_media.h"
 #include "data/data_channel.h"
 #include "data/data_chat.h"
 #include "data/data_user.h"
@@ -177,7 +178,10 @@ internal::StickerRows FieldAutocomplete::getStickerSuggestions() {
 	auto result = ranges::view::all(
 		list
 	) | ranges::view::transform([](not_null<DocumentData*> sticker) {
-		return internal::StickerSuggestion{ sticker };
+		return internal::StickerSuggestion{
+			sticker,
+			sticker->createMediaView()
+		};
 	}) | ranges::to_vector;
 	for (auto &suggestion : _srows) {
 		if (!suggestion.animated) {
@@ -634,6 +638,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
 
 				auto &sticker = (*_srows)[index];
 				const auto document = sticker.document;
+				const auto &media = sticker.documentMedia;
 				if (!document->sticker()) continue;
 
 				if (document->sticker()->animated
@@ -649,7 +654,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
 					App::roundRect(p, QRect(tl, st::stickerPanSize), st::emojiPanHover, StickerHoverCorners);
 				}
 
-				document->checkStickerSmall();
+				media->checkStickerSmall();
 				auto w = 1;
 				auto h = 1;
 				if (sticker.animated && !document->dimensions.isEmpty()) {
@@ -680,7 +685,7 @@ void FieldAutocompleteInner::paintEvent(QPaintEvent *e) {
 					if (!paused) {
 						sticker.animated->markFrameShown();
 					}
-				} else if (const auto image = document->getStickerSmall()) {
+				} else if (const auto image = media->getStickerSmall()) {
 					QPoint ppos = pos + QPoint((st::stickerPanSize.width() - w) / 2, (st::stickerPanSize.height() - h) / 2);
 					p.drawPixmapLeft(ppos, width(), image->pix(document->stickerSetOrigin(), w, h));
 				}
diff --git a/Telegram/SourceFiles/chat_helpers/field_autocomplete.h b/Telegram/SourceFiles/chat_helpers/field_autocomplete.h
index 594293075..db7878350 100644
--- a/Telegram/SourceFiles/chat_helpers/field_autocomplete.h
+++ b/Telegram/SourceFiles/chat_helpers/field_autocomplete.h
@@ -26,10 +26,15 @@ namespace Window {
 class SessionController;
 } // namespace Window
 
+namespace Data {
+class DocumentMedia;
+} // namespace Data
+
 namespace internal {
 
 struct StickerSuggestion {
 	not_null<DocumentData*> document;
+	std::shared_ptr<Data::DocumentMedia> documentMedia;
 	std::unique_ptr<Lottie::SinglePlayer> animated;
 };
 
diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp
index 382bdc15a..bca37ad63 100644
--- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp
+++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp
@@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "chat_helpers/stickers_list_widget.h"
 
 #include "data/data_document.h"
+#include "data/data_document_media.h"
 #include "data/data_session.h"
 #include "data/data_channel.h"
 #include "data/data_file_origin.h"
@@ -184,7 +185,7 @@ auto StickersListWidget::PrepareStickers(const Stickers::Pack &pack)
 	return ranges::view::all(
 		pack
 	) | ranges::view::transform([](DocumentData *document) {
-		return Sticker{ document };
+		return Sticker{ document, document->createMediaView() };
 	}) | ranges::to_vector;
 }
 
@@ -1708,6 +1709,7 @@ QSize StickersListWidget::boundingBoxSize() const {
 void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int section, int index, bool selected, bool deleteSelected) {
 	auto &sticker = set.stickers[index];
 	const auto document = sticker.document;
+	const auto &media = sticker.documentMedia;
 	if (!document->sticker()) {
 		return;
 	}
@@ -1727,7 +1729,7 @@ void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int section,
 		App::roundRect(p, QRect(tl, _singleSize), st::emojiPanHover, StickerHoverCorners);
 	}
 
-	document->checkStickerSmall();
+	media->checkStickerSmall();
 
 	auto w = 1;
 	auto h = 1;
@@ -1752,7 +1754,7 @@ void StickersListWidget::paintSticker(Painter &p, Set &set, int y, int section,
 			frame);
 
 		set.lottiePlayer->unpause(sticker.animated);
-	} else if (const auto image = document->getStickerSmall()) {
+	} else if (const auto image = media->getStickerSmall()) {
 		if (image->loaded()) {
 			p.drawPixmapLeft(
 				ppos,
@@ -2301,9 +2303,10 @@ void StickersListWidget::preloadImages() {
 			if (++k > _columnCount * (_columnCount + 1)) break;
 
 			const auto document = sets[i].stickers[j].document;
+			const auto &media = sets[i].stickers[j].documentMedia;
 			if (!document || !document->sticker()) continue;
 
-			document->checkStickerSmall();
+			media->checkStickerSmall();
 		}
 		if (k > _columnCount * (_columnCount + 1)) break;
 	}
@@ -2395,7 +2398,10 @@ auto StickersListWidget::collectRecentStickers() -> std::vector<Sticker> {
 				_custom[index] = true;
 			}
 		} else if (!_favedStickersMap.contains(document)) {
-			result.push_back(Sticker{ document });
+			result.push_back(Sticker{
+				document,
+				document->createMediaView()
+			});
 			_custom.push_back(custom);
 		}
 	};
diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h
index fc2f88d6c..76c6a777d 100644
--- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h
+++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h
@@ -32,6 +32,10 @@ class MultiPlayer;
 class FrameRenderer;
 } // namespace Lottie
 
+namespace Data {
+class DocumentMedia;
+} // namespace Data
+
 namespace ChatHelpers {
 
 struct StickerIcon;
@@ -151,6 +155,7 @@ private:
 
 	struct Sticker {
 		not_null<DocumentData*> document;
+		std::shared_ptr<Data::DocumentMedia> documentMedia;
 		Lottie::Animation *animated = nullptr;
 	};
 
diff --git a/Telegram/SourceFiles/data/data_document.cpp b/Telegram/SourceFiles/data/data_document.cpp
index 95771cc16..846206791 100644
--- a/Telegram/SourceFiles/data/data_document.cpp
+++ b/Telegram/SourceFiles/data/data_document.cpp
@@ -58,12 +58,6 @@ Core::MediaActiveCache<DocumentData> &ActiveCache() {
 	return Instance;
 }
 
-int64 ComputeUsage(StickerData *sticker) {
-	return (sticker != nullptr && sticker->image != nullptr)
-		? sticker->image->width() * sticker->image->height() * 4
-		: 0;
-}
-
 QString JoinStringList(const QStringList &list, const QString &separator) {
 	const auto count = list.size();
 	if (!count) {
@@ -713,7 +707,7 @@ std::shared_ptr<Data::DocumentMedia> DocumentData::createMediaView() {
 	return result;
 }
 
-std::shared_ptr<Data::DocumentMedia> DocumentData::activeMediaView() {
+std::shared_ptr<Data::DocumentMedia> DocumentData::activeMediaView() const {
 	return _media.lock();
 }
 
@@ -755,12 +749,6 @@ void DocumentData::unload() {
 	// from the destructor, because they're already destroyed.
 	//
 	//_thumbnail->unload();
-	if (sticker()) {
-		if (sticker()->image) {
-			ActiveCache().decrement(ComputeUsage(sticker()));
-			sticker()->image = nullptr;
-		}
-	}
 	_replyPreview = nullptr;
 	if (!_data.isEmpty()) {
 		ActiveCache().decrement(_data.size());
@@ -824,23 +812,14 @@ bool DocumentData::loaded(FilePathResolve resolve) const {
 			that->_data = _loader->bytes();
 			ActiveCache().increment(that->_data.size());
 
-			if (that->sticker()
-				&& !that->sticker()->image
-				&& !_loader->imageData().isNull()) {
-				that->sticker()->image = std::make_unique<Image>(
-					std::make_unique<Images::LocalFileSource>(
-						QString(),
-						_data,
-						_loader->imageFormat(),
-						_loader->imageData()));
-				ActiveCache().increment(ComputeUsage(that->sticker()));
-			}
-
 			that->setGoodThumbnailDataReady();
-			Data::DocumentMedia::CheckGoodThumbnail(that);
+
+			if (const auto media = activeMediaView()) {
+				media->checkStickerLarge(_loader.get());
+			}
 			destroyLoader();
 
-			if (!that->_data.isEmpty() || that->getStickerLarge()) {
+			if (!that->_data.isEmpty()) {
 				ActiveCache().up(that);
 			}
 		}
@@ -1207,66 +1186,6 @@ StickerData *DocumentData::sticker() const {
 		: nullptr;
 }
 
-void DocumentData::checkStickerLarge() {
-	const auto data = sticker();
-	if (!data) return;
-
-	automaticLoad(stickerSetOrigin(), nullptr);
-	if (!data->image && !data->animated && loaded()) {
-		if (_data.isEmpty()) {
-			const auto &loc = location(true);
-			if (loc.accessEnable()) {
-				data->image = std::make_unique<Image>(
-					std::make_unique<Images::LocalFileSource>(loc.name()));
-				loc.accessDisable();
-			}
-		} else {
-			auto format = QByteArray();
-			auto image = App::readImage(_data, &format, false);
-			data->image = std::make_unique<Image>(
-				std::make_unique<Images::LocalFileSource>(
-					QString(),
-					_data,
-					format,
-					std::move(image)));
-		}
-		if (const auto usage = ComputeUsage(data)) {
-			ActiveCache().increment(usage);
-			ActiveCache().up(this);
-		}
-	}
-}
-
-void DocumentData::checkStickerSmall() {
-	const auto data = sticker();
-	if ((data && data->animated) || thumbnailEnoughForSticker()) {
-		_thumbnail->load(stickerSetOrigin());
-		if (data && data->animated) {
-			automaticLoad(stickerSetOrigin(), nullptr);
-		}
-	} else {
-		checkStickerLarge();
-	}
-}
-
-Image *DocumentData::getStickerLarge() {
-	checkStickerLarge();
-	if (const auto data = sticker()) {
-		return data->image.get();
-	}
-	return nullptr;
-}
-
-Image *DocumentData::getStickerSmall() {
-	const auto data = sticker();
-	if ((data && data->animated) || thumbnailEnoughForSticker()) {
-		return _thumbnail->isNull() ? nullptr : _thumbnail.get();
-	} else if (data) {
-		return data->image.get();
-	}
-	return nullptr;
-}
-
 Data::FileOrigin DocumentData::stickerSetOrigin() const {
 	if (const auto data = sticker()) {
 		if (const auto result = data->setOrigin()) {
diff --git a/Telegram/SourceFiles/data/data_document.h b/Telegram/SourceFiles/data/data_document.h
index 45dd5e99d..cb0e54463 100644
--- a/Telegram/SourceFiles/data/data_document.h
+++ b/Telegram/SourceFiles/data/data_document.h
@@ -58,7 +58,6 @@ struct DocumentAdditionalData {
 struct StickerData : public DocumentAdditionalData {
 	Data::FileOrigin setOrigin() const;
 
-	std::unique_ptr<Image> image;
 	bool animated = false;
 	QString alt;
 	MTPInputStickerSet set = MTP_inputStickerSetEmpty();
@@ -141,13 +140,10 @@ public:
 	[[nodiscard]] Image *getReplyPreview(Data::FileOrigin origin);
 
 	[[nodiscard]] StickerData *sticker() const;
-	void checkStickerLarge();
-	void checkStickerSmall();
-	[[nodiscard]] Image *getStickerSmall();
-	[[nodiscard]] Image *getStickerLarge();
 	[[nodiscard]] Data::FileOrigin stickerSetOrigin() const;
 	[[nodiscard]] Data::FileOrigin stickerOrGifOrigin() const;
 	[[nodiscard]] bool isStickerSetInstalled() const;
+	[[nodiscard]] bool thumbnailEnoughForSticker() const;
 	[[nodiscard]] SongData *song();
 	[[nodiscard]] const SongData *song() const;
 	[[nodiscard]] VoiceData *voice();
@@ -195,7 +191,8 @@ public:
 	void setGoodThumbnailChecked(bool hasData);
 
 	[[nodiscard]] std::shared_ptr<Data::DocumentMedia> createMediaView();
-	[[nodiscard]] std::shared_ptr<Data::DocumentMedia> activeMediaView();
+	[[nodiscard]] auto activeMediaView() const
+		-> std::shared_ptr<Data::DocumentMedia>;
 	void setGoodThumbnailPhoto(not_null<PhotoData*> photo);
 	[[nodiscard]] PhotoData *goodThumbnailPhoto() const;
 
@@ -302,7 +299,6 @@ private:
 	void destroyLoader() const;
 
 	[[nodiscard]] bool useStreamingLoader() const;
-	[[nodiscard]] bool thumbnailEnoughForSticker() const;
 
 	// Two types of location: from MTProto by dc+access or from web by url
 	int32 _dc = 0;
diff --git a/Telegram/SourceFiles/data/data_document_media.cpp b/Telegram/SourceFiles/data/data_document_media.cpp
index 25fac8e40..2f70da8d7 100644
--- a/Telegram/SourceFiles/data/data_document_media.cpp
+++ b/Telegram/SourceFiles/data/data_document_media.cpp
@@ -11,10 +11,12 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "data/data_document_good_thumbnail.h"
 #include "data/data_session.h"
 #include "data/data_cloud_themes.h"
+#include "data/data_file_origin.h"
 #include "media/clip/media_clip_reader.h"
 #include "main/main_session.h"
 #include "lottie/lottie_animation.h"
 #include "window/themes/window_theme_preview.h"
+#include "storage/file_download.h"
 #include "ui/image/image.h"
 #include "app.h"
 
@@ -121,6 +123,78 @@ Image *DocumentMedia::thumbnailInline() const {
 	return _inlineThumbnail.get();
 }
 
+void DocumentMedia::checkStickerLarge() {
+	if (_sticker) {
+		return;
+	}
+	const auto data = _owner->sticker();
+	if (!data) {
+		return;
+	}
+
+	_owner->automaticLoad(_owner->stickerSetOrigin(), nullptr);
+	if (data->animated || !_owner->loaded()) {
+		return;
+	}
+	const auto bytes = _owner->data();
+	if (bytes.isEmpty()) {
+		const auto &loc = _owner->location(true);
+		if (loc.accessEnable()) {
+			_sticker = std::make_unique<Image>(
+				std::make_unique<Images::LocalFileSource>(loc.name()));
+			loc.accessDisable();
+		}
+	} else {
+		auto format = QByteArray();
+		auto image = App::readImage(bytes, &format, false);
+		_sticker = std::make_unique<Image>(
+			std::make_unique<Images::LocalFileSource>(
+				QString(),
+				bytes,
+				format,
+				std::move(image)));
+	}
+}
+
+void DocumentMedia::checkStickerSmall() {
+	const auto data = _owner->sticker();
+	if ((data && data->animated) || _owner->thumbnailEnoughForSticker()) {
+		_owner->loadThumbnail(_owner->stickerSetOrigin());
+		if (data && data->animated) {
+			_owner->automaticLoad(_owner->stickerSetOrigin(), nullptr);
+		}
+	} else {
+		checkStickerLarge();
+	}
+}
+
+Image *DocumentMedia::getStickerLarge() {
+	checkStickerLarge();
+	return _sticker.get();
+}
+
+Image *DocumentMedia::getStickerSmall() {
+	const auto data = _owner->sticker();
+	if ((data && data->animated) || _owner->thumbnailEnoughForSticker()) {
+		return _owner->thumbnail();
+	}
+	return _sticker.get();
+}
+
+void DocumentMedia::checkStickerLarge(not_null<FileLoader*> loader) {
+	if (_owner->sticker()
+		&& !_sticker
+		&& !loader->imageData().isNull()
+		&& !_owner->data().isEmpty()) {
+		_sticker = std::make_unique<Image>(
+			std::make_unique<Images::LocalFileSource>(
+				QString(),
+				_owner->data(),
+				loader->imageFormat(),
+				loader->imageData()));
+	}
+}
+
 void DocumentMedia::GenerateGoodThumbnail(not_null<DocumentData*> document) {
 	const auto data = document->data();
 	const auto type = document->isWallPaper()
diff --git a/Telegram/SourceFiles/data/data_document_media.h b/Telegram/SourceFiles/data/data_document_media.h
index b917ecf25..e2d907baa 100644
--- a/Telegram/SourceFiles/data/data_document_media.h
+++ b/Telegram/SourceFiles/data/data_document_media.h
@@ -9,6 +9,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 
 #include "base/flags.h"
 
+class FileLoader;
+
 namespace Data {
 
 class DocumentMedia final {
@@ -22,6 +24,12 @@ public:
 
 	[[nodiscard]] Image *thumbnailInline() const;
 
+	void checkStickerLarge();
+	void checkStickerSmall();
+	[[nodiscard]] Image *getStickerSmall();
+	[[nodiscard]] Image *getStickerLarge();
+	void checkStickerLarge(not_null<FileLoader*> loader);
+
 	// For DocumentData.
 	static void CheckGoodThumbnail(not_null<DocumentData*> document);
 
@@ -38,6 +46,7 @@ private:
 	const not_null<DocumentData*> _owner;
 	std::unique_ptr<Image> _goodThumbnail;
 	mutable std::unique_ptr<Image> _inlineThumbnail;
+	std::unique_ptr<Image> _sticker;
 	Flags _flags;
 
 };
diff --git a/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp b/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp
index 72bbbcf1c..98491f9da 100644
--- a/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp
+++ b/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp
@@ -100,7 +100,8 @@ bool Sticker::readyToDrawLottie() {
 		return false;
 	}
 
-	_data->checkStickerLarge();
+	ensureDataMediaCreated();
+	_dataMedia->checkStickerLarge();
 	const auto loaded = _data->loaded();
 	if (sticker->animated && !_lottie && loaded) {
 		setupLottie();
@@ -124,6 +125,7 @@ QSize Sticker::GetAnimatedEmojiSize(
 }
 
 void Sticker::draw(Painter &p, const QRect &r, bool selected) {
+	ensureDataMediaCreated();
 	if (readyToDrawLottie()) {
 		paintLottie(p, r, selected);
 	} else if (_data->sticker()
@@ -200,8 +202,6 @@ void Sticker::paintPixmap(Painter &p, const QRect &r, bool selected) {
 }
 
 QPixmap Sticker::paintedPixmap(bool selected) const {
-	ensureDataMediaCreated();
-
 	const auto o = _parent->data()->fullId();
 	const auto w = _size.width();
 	const auto h = _size.height();
@@ -210,7 +210,7 @@ QPixmap Sticker::paintedPixmap(bool selected) const {
 	if (good && !good->loaded()) {
 		good->load({});
 	}
-	if (const auto image = _data->getStickerLarge()) {
+	if (const auto image = _dataMedia->getStickerLarge()) {
 		return selected
 			? image->pixColored(o, c, w, h)
 			: image->pix(o, w, h);
diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp
index 7e3c1b25f..5f9e6dc55 100644
--- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp
+++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.cpp
@@ -434,12 +434,20 @@ void Sticker::initDimensions() {
 
 void Sticker::preload() const {
 	if (const auto document = getShownDocument()) {
-		document->checkStickerSmall();
+		ensureDataMediaCreated(document);
+		_dataMedia->checkStickerSmall();
 	} else if (const auto thumb = getResultThumb()) {
 		thumb->load(fileOrigin());
 	}
 }
 
+void Sticker::ensureDataMediaCreated(not_null<DocumentData*> document) const {
+	if (_dataMedia) {
+		return;
+	}
+	_dataMedia = document->createMediaView();
+}
+
 void Sticker::paint(Painter &p, const QRect &clip, const PaintContext *context) const {
 	bool loaded = getShownDocument()->loaded();
 
@@ -517,14 +525,15 @@ void Sticker::setupLottie(not_null<DocumentData*> document) const {
 
 void Sticker::prepareThumbnail() const {
 	if (const auto document = getShownDocument()) {
+		ensureDataMediaCreated(document);
 		if (!_lottie
 			&& document->sticker()
 			&& document->sticker()->animated
 			&& document->loaded()) {
 			setupLottie(document);
 		}
-		document->checkStickerSmall();
-		if (const auto sticker = document->getStickerSmall()) {
+		_dataMedia->checkStickerSmall();
+		if (const auto sticker = _dataMedia->getStickerSmall()) {
 			if (!_lottie && !_thumbLoaded && sticker->loaded()) {
 				const auto thumbSize = getThumbSize();
 				_thumb = sticker->pix(
diff --git a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h
index bb36fe24c..fe2d7a1de 100644
--- a/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h
+++ b/Telegram/SourceFiles/inline_bots/inline_bot_layout_internal.h
@@ -192,6 +192,7 @@ public:
 	void clickHandlerActiveChanged(const ClickHandlerPtr &p, bool active) override;
 
 private:
+	void ensureDataMediaCreated(not_null<DocumentData*> document) const;
 	void setupLottie(not_null<DocumentData*> document) const;
 	QSize getThumbSize() const;
 	void prepareThumbnail() const;
@@ -203,6 +204,7 @@ private:
 	mutable bool _thumbLoaded = false;
 
 	mutable std::unique_ptr<Lottie::SinglePlayer> _lottie;
+	mutable std::shared_ptr<Data::DocumentMedia> _dataMedia;
 	mutable rpl::lifetime _lifetime;
 
 };
diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp
index 43372c26d..ed933f2d2 100644
--- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp
+++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp
@@ -1093,6 +1093,7 @@ void OverlayWidget::clearData() {
 	_fromName = QString();
 	_photo = nullptr;
 	_doc = nullptr;
+	_docMedia = nullptr;
 	_pip = nullptr;
 	_fullScreenVideo = false;
 	_caption.clear();
@@ -1913,6 +1914,7 @@ void OverlayWidget::displayPhoto(not_null<PhotoData*> photo, HistoryItem *item)
 	clearStreaming();
 	destroyThemePreview();
 	_doc = nullptr;
+	_docMedia = nullptr;
 	_fullScreenVideo = false;
 	_photo = photo;
 	_rotation = _photo->owner().mediaRotation().get(_photo);
@@ -1972,6 +1974,9 @@ void OverlayWidget::displayDocument(
 	clearStreaming(_doc != doc);
 	destroyThemePreview();
 	_doc = doc;
+	if (_doc) {
+		_docMedia = _doc->createMediaView();
+	}
 	_rotation = _doc ? _doc->owner().mediaRotation().get(_doc) : 0;
 	_themeCloudData = cloud;
 	_photo = nullptr;
@@ -1980,7 +1985,7 @@ void OverlayWidget::displayDocument(
 	refreshMediaViewer();
 	if (_doc) {
 		if (_doc->sticker()) {
-			if (const auto image = _doc->getStickerLarge()) {
+			if (const auto image = _docMedia->getStickerLarge()) {
 				_staticContent = image->pix(fileOrigin());
 			} else if (_doc->hasThumbnail()) {
 				_staticContent = _doc->thumbnail()->pixBlurred(
@@ -3019,7 +3024,7 @@ void OverlayWidget::paintTransformedStaticContent(Painter &p) {
 	const auto rect = contentRect();
 
 	PainterHighQualityEnabler hq(p);
-	if ((!_doc || !_doc->getStickerLarge())
+	if ((!_doc || !_docMedia->getStickerLarge())
 		&& (_staticContent.isNull()
 			|| _staticContent.hasAlpha())) {
 		p.fillRect(rect, _transparentBrush);
@@ -3482,13 +3487,9 @@ void OverlayWidget::preloadData(int delta) {
 		if (auto photo = base::get_if<not_null<PhotoData*>>(&entity.data)) {
 			(*photo)->download(fileOrigin());
 		} else if (auto document = base::get_if<not_null<DocumentData*>>(&entity.data)) {
-			if (const auto image = (*document)->getStickerLarge()) {
-				image->load(fileOrigin());
-			} else {
-				(*document)->loadThumbnail(fileOrigin());
-				if (!(*document)->canBePlayed()) {
-					(*document)->automaticLoad(fileOrigin(), entity.item);
-				}
+			(*document)->loadThumbnail(fileOrigin());
+			if (!(*document)->canBePlayed()) {
+				(*document)->automaticLoad(fileOrigin(), entity.item);
 			}
 		}
 	}
diff --git a/Telegram/SourceFiles/window/window_media_preview.cpp b/Telegram/SourceFiles/window/window_media_preview.cpp
index d0bd24edb..7915b68ae 100644
--- a/Telegram/SourceFiles/window/window_media_preview.cpp
+++ b/Telegram/SourceFiles/window/window_media_preview.cpp
@@ -249,7 +249,7 @@ QPixmap MediaPreviewWidget::currentImage() const {
 				}
 				if (_lottie && _lottie->ready()) {
 					return QPixmap();
-				} else if (const auto image = _document->getStickerLarge()) {
+				} else if (const auto image = _documentMedia->getStickerLarge()) {
 					QSize s = currentDimensions();
 					_cache = image->pix(_origin, s.width(), s.height());
 					_cacheStatus = CacheLoaded;