diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt
index e0acb5c18..06d89a81a 100644
--- a/Telegram/CMakeLists.txt
+++ b/Telegram/CMakeLists.txt
@@ -270,6 +270,8 @@ PRIVATE
     chat_helpers/stickers.h
     chat_helpers/stickers_emoji_pack.cpp
     chat_helpers/stickers_emoji_pack.h
+    chat_helpers/stickers_dice_pack.cpp
+    chat_helpers/stickers_dice_pack.h
     chat_helpers/stickers_list_widget.cpp
     chat_helpers/stickers_list_widget.h
     chat_helpers/tabbed_panel.cpp
@@ -436,6 +438,8 @@ PRIVATE
     history/view/media/history_view_call.cpp
     history/view/media/history_view_contact.h
     history/view/media/history_view_contact.cpp
+    history/view/media/history_view_dice.h
+    history/view/media/history_view_dice.cpp
     history/view/media/history_view_document.h
     history/view/media/history_view_document.cpp
     history/view/media/history_view_file.h
diff --git a/Telegram/Resources/art/dice_idle.tgs b/Telegram/Resources/art/dice_idle.tgs
new file mode 100644
index 000000000..aad33bffe
Binary files /dev/null and b/Telegram/Resources/art/dice_idle.tgs differ
diff --git a/Telegram/Resources/qrc/telegram/telegram.qrc b/Telegram/Resources/qrc/telegram/telegram.qrc
index 2a9d64d3c..68b67373b 100644
--- a/Telegram/Resources/qrc/telegram/telegram.qrc
+++ b/Telegram/Resources/qrc/telegram/telegram.qrc
@@ -47,6 +47,7 @@
     <file alias="art/logo_256.png">../../art/logo_256.png</file>
     <file alias="art/logo_256_no_margin.png">../../art/logo_256_no_margin.png</file>
     <file alias="art/sunrise.jpg">../../art/sunrise.jpg</file>
+    <file alias="art/dice_idle.tgs">../../art/dice_idle.tgs</file>
     <file alias="day-blue.tdesktop-theme">../../day-blue.tdesktop-theme</file>
     <file alias="night.tdesktop-theme">../../night.tdesktop-theme</file>
     <file alias="night-green.tdesktop-theme">../../night-green.tdesktop-theme</file>
diff --git a/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.cpp b/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.cpp
new file mode 100644
index 000000000..1e9c6a7f6
--- /dev/null
+++ b/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.cpp
@@ -0,0 +1,96 @@
+/*
+This file is part of Telegram Desktop,
+the official desktop application for the Telegram messaging service.
+
+For license and copyright information please follow this link:
+https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
+*/
+#include "chat_helpers/stickers_dice_pack.h"
+
+#include "main/main_session.h"
+#include "data/data_session.h"
+#include "data/data_document.h"
+#include "storage/localimageloader.h"
+#include "base/unixtime.h"
+#include "apiwrap.h"
+
+#include <QtCore/QFile>
+#include <QtCore/QFileInfo>
+
+namespace Stickers {
+namespace {
+
+constexpr auto kZeroDiceDocumentId = 0xa3b83c9f84fa9e83ULL;
+
+} // namespace
+
+DicePack::DicePack(not_null<Main::Session*> session)
+: _session(session) {
+}
+
+DicePack::~DicePack() = default;
+
+DocumentData *DicePack::lookup(int value) {
+	if (!_requestId) {
+		load();
+	}
+	if (!value) {
+		ensureZeroGenerated();
+		return _zero;
+	}
+	const auto i = _map.find(value);
+	return (i != end(_map)) ? i->second.get() : nullptr;
+}
+
+void DicePack::load() {
+	if (_requestId) {
+		return;
+	}
+	_requestId = _session->api().request(MTPmessages_GetStickerSet(
+		MTP_inputStickerSetDice()
+	)).done([=](const MTPmessages_StickerSet &result) {
+		result.match([&](const MTPDmessages_stickerSet &data) {
+			applySet(data);
+		});
+	}).fail([=](const RPCError &error) {
+		_requestId = 0;
+	}).send();
+}
+
+void DicePack::applySet(const MTPDmessages_stickerSet &data) {
+	auto index = 0;
+	for (const auto &sticker : data.vdocuments().v) {
+		const auto document = _session->data().processDocument(
+			sticker);
+		if (document->sticker()) {
+			_map.emplace(++index, document);
+		}
+	}
+}
+
+void DicePack::ensureZeroGenerated() {
+	if (_zero) {
+		return;
+	}
+
+	const auto path = qsl(":/gui/art/dice_idle.tgs");
+	auto task = FileLoadTask(
+		path,
+		QByteArray(),
+		nullptr,
+		SendMediaType::File,
+		FileLoadTo(0, {}, 0),
+		{});
+	task.process();
+	const auto result = task.peekResult();
+	Assert(result != nullptr);
+	_zero = _session->data().processDocument(
+		result->document,
+		std::move(result->thumb));
+	_zero->setLocation(FileLocation(path));
+
+	Ensures(_zero->sticker());
+	Ensures(_zero->sticker()->animated);
+}
+
+} // namespace Stickers
diff --git a/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.h b/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.h
new file mode 100644
index 000000000..59a22a11a
--- /dev/null
+++ b/Telegram/SourceFiles/chat_helpers/stickers_dice_pack.h
@@ -0,0 +1,37 @@
+/*
+This file is part of Telegram Desktop,
+the official desktop application for the Telegram messaging service.
+
+For license and copyright information please follow this link:
+https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
+*/
+#pragma once
+
+class DocumentData;
+
+namespace Main {
+class Session;
+} // namespace Main
+
+namespace Stickers {
+
+class DicePack final {
+public:
+	explicit DicePack(not_null<Main::Session*> session);
+	~DicePack();
+
+	DocumentData *lookup(int value);
+
+private:
+	void load();
+	void applySet(const MTPDmessages_stickerSet &data);
+	void ensureZeroGenerated();
+
+	not_null<Main::Session*> _session;
+	base::flat_map<int, not_null<DocumentData*>> _map;
+	DocumentData *_zero = nullptr;
+	mtpRequestId _requestId = 0;
+
+};
+
+} // namespace Stickers
diff --git a/Telegram/SourceFiles/data/data_media_types.cpp b/Telegram/SourceFiles/data/data_media_types.cpp
index e0f6bd6f7..5e6a9d9c0 100644
--- a/Telegram/SourceFiles/data/data_media_types.cpp
+++ b/Telegram/SourceFiles/data/data_media_types.cpp
@@ -23,6 +23,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "history/view/media/history_view_web_page.h"
 #include "history/view/media/history_view_poll.h"
 #include "history/view/media/history_view_theme_document.h"
+#include "history/view/media/history_view_dice.h"
 #include "ui/image/image.h"
 #include "ui/image/image_source.h"
 #include "ui/text_options.h"
@@ -1325,4 +1326,49 @@ std::unique_ptr<HistoryView::Media> MediaPoll::createView(
 	return std::make_unique<HistoryView::Poll>(message, _poll);
 }
 
+MediaDice::MediaDice(not_null<HistoryItem*> parent, int value)
+: Media(parent)
+, _value(value) {
+}
+
+std::unique_ptr<Media> MediaDice::clone(not_null<HistoryItem*> parent) {
+	return std::make_unique<MediaDice>(parent, _value);
+}
+
+int MediaDice::diceValue() const {
+	return _value;
+}
+
+QString MediaDice::notificationText() const {
+	return QString::fromUtf8("\xF0\x9F\x8E\xB2");
+}
+
+QString MediaDice::pinnedTextSubstring() const {
+	return QChar(171) + notificationText() + QChar(187);
+}
+
+TextForMimeData MediaDice::clipboardText() const {
+	return { notificationText() };
+}
+
+bool MediaDice::updateInlineResultMedia(const MTPMessageMedia &media) {
+	return updateSentMedia(media);
+}
+
+bool MediaDice::updateSentMedia(const MTPMessageMedia &media) {
+	if (media.type() != mtpc_messageMediaDice) {
+		return false;
+	}
+	_value = media.c_messageMediaDice().vvalue().v;
+	return true;
+}
+
+std::unique_ptr<HistoryView::Media> MediaDice::createView(
+		not_null<HistoryView::Element*> message,
+		not_null<HistoryItem*> realParent) {
+	return std::make_unique<HistoryView::UnwrappedMedia>(
+		message,
+		std::make_unique<HistoryView::Dice>(message, _value));
+}
+
 } // namespace Data
diff --git a/Telegram/SourceFiles/data/data_media_types.h b/Telegram/SourceFiles/data/data_media_types.h
index 7803e503d..6b77e7255 100644
--- a/Telegram/SourceFiles/data/data_media_types.h
+++ b/Telegram/SourceFiles/data/data_media_types.h
@@ -118,7 +118,7 @@ private:
 
 };
 
-class MediaPhoto : public Media {
+class MediaPhoto final : public Media {
 public:
 	MediaPhoto(
 		not_null<HistoryItem*> parent,
@@ -158,7 +158,7 @@ private:
 
 };
 
-class MediaFile : public Media {
+class MediaFile final : public Media {
 public:
 	MediaFile(
 		not_null<HistoryItem*> parent,
@@ -195,7 +195,7 @@ private:
 
 };
 
-class MediaContact : public Media {
+class MediaContact final : public Media {
 public:
 	MediaContact(
 		not_null<HistoryItem*> parent,
@@ -223,7 +223,7 @@ private:
 
 };
 
-class MediaLocation : public Media {
+class MediaLocation final : public Media {
 public:
 	MediaLocation(
 		not_null<HistoryItem*> parent,
@@ -255,7 +255,7 @@ private:
 
 };
 
-class MediaCall : public Media {
+class MediaCall final : public Media {
 public:
 	MediaCall(
 		not_null<HistoryItem*> parent,
@@ -284,7 +284,7 @@ private:
 
 };
 
-class MediaWebPage : public Media {
+class MediaWebPage final : public Media {
 public:
 	MediaWebPage(
 		not_null<HistoryItem*> parent,
@@ -316,7 +316,7 @@ private:
 
 };
 
-class MediaGame : public Media {
+class MediaGame final : public Media {
 public:
 	MediaGame(
 		not_null<HistoryItem*> parent,
@@ -348,7 +348,7 @@ private:
 
 };
 
-class MediaInvoice : public Media {
+class MediaInvoice final : public Media {
 public:
 	MediaInvoice(
 		not_null<HistoryItem*> parent,
@@ -378,7 +378,7 @@ private:
 
 };
 
-class MediaPoll : public Media {
+class MediaPoll final : public Media {
 public:
 	MediaPoll(
 		not_null<HistoryItem*> parent,
@@ -405,6 +405,28 @@ private:
 
 };
 
+class MediaDice final : public Media {
+public:
+	MediaDice(not_null<HistoryItem*> parent, int value);
+
+	std::unique_ptr<Media> clone(not_null<HistoryItem*> parent) override;
+
+	int diceValue() const;
+
+	QString notificationText() const override;
+	QString pinnedTextSubstring() const override;
+	TextForMimeData clipboardText() const override;
+	bool updateInlineResultMedia(const MTPMessageMedia &media) override;
+	bool updateSentMedia(const MTPMessageMedia &media) override;
+	std::unique_ptr<HistoryView::Media> createView(
+		not_null<HistoryView::Element*> message,
+		not_null<HistoryItem*> realParent) override;
+
+private:
+	int _value = 0;
+
+};
+
 TextForMimeData WithCaptionClipboardText(
 	const QString &attachType,
 	TextForMimeData &&caption);
diff --git a/Telegram/SourceFiles/history/history_item.cpp b/Telegram/SourceFiles/history/history_item.cpp
index 0503a60d5..4bc32948a 100644
--- a/Telegram/SourceFiles/history/history_item.cpp
+++ b/Telegram/SourceFiles/history/history_item.cpp
@@ -154,7 +154,7 @@ MediaCheckResult CheckMessageMedia(const MTPMessageMedia &media) {
 	}, [](const MTPDmessageMediaPoll &) {
 		return Result::Good;
 	}, [](const MTPDmessageMediaDice &) {
-		return Result::Unsupported; // #TODO dice
+		return Result::Good;
 	}, [](const MTPDmessageMediaUnsupported &) {
 		return Result::Unsupported;
 	});
diff --git a/Telegram/SourceFiles/history/history_message.cpp b/Telegram/SourceFiles/history/history_message.cpp
index d2b0fdfe1..c461982b4 100644
--- a/Telegram/SourceFiles/history/history_message.cpp
+++ b/Telegram/SourceFiles/history/history_message.cpp
@@ -1024,8 +1024,8 @@ std::unique_ptr<Data::Media> HistoryMessage::CreateMedia(
 		return std::make_unique<Data::MediaPoll>(
 			item,
 			item->history()->owner().processPoll(media));
-	}, [](const MTPDmessageMediaDice &media) -> Result {
-		return nullptr; // #TODO dice
+	}, [&](const MTPDmessageMediaDice &media) -> Result {
+		return std::make_unique<Data::MediaDice>(item, media.vvalue().v);
 	}, [](const MTPDmessageMediaEmpty &) -> Result {
 		return nullptr;
 	}, [](const MTPDmessageMediaUnsupported &) -> Result {
diff --git a/Telegram/SourceFiles/history/view/media/history_view_dice.cpp b/Telegram/SourceFiles/history/view/media/history_view_dice.cpp
new file mode 100644
index 000000000..0f780802d
--- /dev/null
+++ b/Telegram/SourceFiles/history/view/media/history_view_dice.cpp
@@ -0,0 +1,60 @@
+/*
+This file is part of Telegram Desktop,
+the official desktop application for the Telegram messaging service.
+
+For license and copyright information please follow this link:
+https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
+*/
+#include "history/view/media/history_view_dice.h"
+
+#include "data/data_session.h"
+#include "chat_helpers/stickers_dice_pack.h"
+#include "history/history.h"
+#include "history/history_item.h"
+#include "history/view/history_view_element.h"
+#include "main/main_session.h"
+
+namespace HistoryView {
+namespace {
+
+DocumentData *Lookup(not_null<Element*> view, int value) {
+	const auto &session = view->data()->history()->session();
+	return session.diceStickersPack().lookup(value);
+}
+
+} // namespace
+
+Dice::Dice(not_null<Element*> parent, int value)
+: _parent(parent)
+, _start(parent, Lookup(parent, 0))
+, _value(value) {
+	_start.setDiceIndex(0);
+}
+
+Dice::~Dice() = default;
+
+QSize Dice::size() {
+	return _start.size();
+}
+
+void Dice::draw(Painter &p, const QRect &r, bool selected) {
+	Expects(_end.has_value() || !_drawingEnd);
+
+	if (_drawingEnd) {
+		_end->draw(p, r, selected);
+	} else {
+		_start.draw(p, r, selected);
+		if (!_end && _value) {
+			if (const auto document = Lookup(_parent, _value)) {
+				_end.emplace(_parent, document);
+				_end->setDiceIndex(_value);
+				_end->initSize();
+			}
+		}
+		if (_end && _end->readyToDrawLottie() && _start.atTheEnd()) {
+			_drawingEnd = true;
+		}
+	}
+}
+
+} // namespace HistoryView
diff --git a/Telegram/SourceFiles/history/view/media/history_view_dice.h b/Telegram/SourceFiles/history/view/media/history_view_dice.h
new file mode 100644
index 000000000..5d0d7c4a9
--- /dev/null
+++ b/Telegram/SourceFiles/history/view/media/history_view_dice.h
@@ -0,0 +1,43 @@
+/*
+This file is part of Telegram Desktop,
+the official desktop application for the Telegram messaging service.
+
+For license and copyright information please follow this link:
+https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
+*/
+#pragma once
+
+#include "history/view/media/history_view_media_unwrapped.h"
+#include "history/view/media/history_view_sticker.h"
+
+namespace HistoryView {
+
+class Dice final : public UnwrappedMedia::Content {
+public:
+	Dice(not_null<Element*> parent, int value);
+	~Dice();
+
+	QSize size() override;
+	void draw(Painter &p, const QRect &r, bool selected) override;
+
+	void clearStickerLoopPlayed() override {
+		_lottieOncePlayed = false;
+	}
+	void unloadHeavyPart() override {
+		_start.unloadHeavyPart();
+		if (_end) {
+			_end->unloadHeavyPart();
+		}
+	}
+
+private:
+	const not_null<Element*> _parent;
+	std::optional<Sticker> _end;
+	Sticker _start;
+	int _value = 0;
+	mutable bool _lottieOncePlayed = false;
+	mutable bool _drawingEnd = false;
+
+};
+
+} // namespace HistoryView
diff --git a/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp b/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp
index 717a0bf78..00e2b9bce 100644
--- a/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp
+++ b/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp
@@ -57,7 +57,7 @@ bool Sticker::isEmojiSticker() const {
 	return (_parent->data()->media() == nullptr);
 }
 
-QSize Sticker::size() {
+void Sticker::initSize() {
 	_size = _document->dimensions;
 	if (isEmojiSticker()) {
 		constexpr auto kIdealStickerSize = 512;
@@ -70,14 +70,22 @@ QSize Sticker::size() {
 		_size = DownscaledSize(
 			_size,
 			{ st::maxStickerSize, st::maxStickerSize });
+		[[maybe_unused]] bool result = readyToDrawLottie();
 	}
+}
+
+QSize Sticker::size() {
+	initSize();
 	return _size;
 }
 
-void Sticker::draw(Painter &p, const QRect &r, bool selected) {
+bool Sticker::readyToDrawLottie() {
+	if (!_lastDiceFrame.isNull()) {
+		return true;
+	}
 	const auto sticker = _document->sticker();
 	if (!sticker) {
-		return;
+		return false;
 	}
 
 	_document->checkStickerLarge();
@@ -85,10 +93,14 @@ void Sticker::draw(Painter &p, const QRect &r, bool selected) {
 	if (sticker->animated && !_lottie && loaded) {
 		setupLottie();
 	}
+	return (_lottie && _lottie->ready());
+}
 
-	if (_lottie && _lottie->ready()) {
+void Sticker::draw(Painter &p, const QRect &r, bool selected) {
+	if (readyToDrawLottie()) {
 		paintLottie(p, r, selected);
-	} else if (!sticker->animated || !_replacements) {
+	} else if (_document->sticker()
+		&& (!_document->sticker()->animated || !_replacements)) {
 		paintPixmap(p, r, selected);
 	}
 }
@@ -96,24 +108,51 @@ void Sticker::draw(Painter &p, const QRect &r, bool selected) {
 void Sticker::paintLottie(Painter &p, const QRect &r, bool selected) {
 	auto request = Lottie::FrameRequest();
 	request.box = _size * cIntRetinaFactor();
-	if (selected) {
+	if (selected && !_nextLastDiceFrame) {
 		request.colored = st::msgStickerOverlay->c;
 	}
-	const auto frame = _lottie->frameInfo(request);
-	const auto size = frame.image.size() / cIntRetinaFactor();
+	const auto frame = _lottie
+		? _lottie->frameInfo(request)
+		: Lottie::Animation::FrameInfo();
+	if (_nextLastDiceFrame) {
+		_nextLastDiceFrame = false;
+		_lastDiceFrame = frame.image;
+	}
+	const auto &image = _lastDiceFrame.isNull()
+		? frame.image
+		: _lastDiceFrame;
+	const auto prepared = (!_lastDiceFrame.isNull() && selected)
+		? Images::prepareColored(st::msgStickerOverlay->c, image)
+		: image;
+	const auto size = prepared.size() / cIntRetinaFactor();
 	p.drawImage(
 		QRect(
 			QPoint(
 				r.x() + (r.width() - size.width()) / 2,
 				r.y() + (r.height() - size.height()) / 2),
 			size),
-		frame.image);
+		prepared);
+	if (!_lastDiceFrame.isNull()) {
+		return;
+	}
 
 	const auto paused = App::wnd()->sessionController()->isGifPausedAtLeastFor(Window::GifPauseReason::Any);
-	const auto playOnce = isEmojiSticker()
-		|| !_document->session().settings().loopAnimatedStickers();
+	const auto playOnce = (_diceIndex > 0)
+		? true
+		: (_diceIndex == 0)
+		? false
+		: (isEmojiSticker()
+			|| !_document->session().settings().loopAnimatedStickers());
+	const auto count = _lottie->information().framesCount;
+	_atTheEnd = (frame.index + 1 == count);
+	_nextLastDiceFrame = !paused
+		&& (_diceIndex > 0)
+		&& (frame.index + 2 == count);
+	const auto lastDiceFrame = (_diceIndex > 0) && _atTheEnd;
+	const auto switchToNext = !playOnce
+		|| (!lastDiceFrame && (frame.index != 0 || !_lottieOncePlayed));
 	if (!paused
-		&& (!playOnce || frame.index != 0 || !_lottieOncePlayed)
+		&& switchToNext
 		&& _lottie->markFrameShown()
 		&& playOnce
 		&& !_lottieOncePlayed) {
@@ -188,6 +227,10 @@ void Sticker::refreshLink() {
 	}
 }
 
+void Sticker::setDiceIndex(int index) {
+	_diceIndex = index;
+}
+
 void Sticker::setupLottie() {
 	_lottie = Stickers::LottiePlayerFromDocument(
 		_document,
diff --git a/Telegram/SourceFiles/history/view/media/history_view_sticker.h b/Telegram/SourceFiles/history/view/media/history_view_sticker.h
index 6ee7370e4..6c9f4d0a6 100644
--- a/Telegram/SourceFiles/history/view/media/history_view_sticker.h
+++ b/Telegram/SourceFiles/history/view/media/history_view_sticker.h
@@ -31,6 +31,7 @@ public:
 		const Lottie::ColorReplacements *replacements = nullptr);
 	~Sticker();
 
+	void initSize();
 	QSize size() override;
 	void draw(Painter &p, const QRect &r, bool selected) override;
 	ClickHandlerPtr link() override {
@@ -48,6 +49,12 @@ public:
 	}
 	void refreshLink() override;
 
+	void setDiceIndex(int index);
+	[[nodiscard]] bool atTheEnd() const {
+		return _atTheEnd;
+	}
+	[[nodiscard]] bool readyToDrawLottie();
+
 private:
 	[[nodiscard]] bool isEmojiSticker() const;
 	void paintLottie(Painter &p, const QRect &r, bool selected);
@@ -63,7 +70,11 @@ private:
 	std::unique_ptr<Lottie::SinglePlayer> _lottie;
 	ClickHandlerPtr _link;
 	QSize _size;
+	QImage _lastDiceFrame;
+	int _diceIndex = -1;
 	mutable bool _lottieOncePlayed = false;
+	mutable bool _atTheEnd = false;
+	mutable bool _nextLastDiceFrame = false;
 
 	rpl::lifetime _lifetime;
 
diff --git a/Telegram/SourceFiles/main/main_session.cpp b/Telegram/SourceFiles/main/main_session.cpp
index 90de3897d..303be0c59 100644
--- a/Telegram/SourceFiles/main/main_session.cpp
+++ b/Telegram/SourceFiles/main/main_session.cpp
@@ -12,6 +12,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "core/changelogs.h"
 #include "main/main_account.h"
 #include "chat_helpers/stickers_emoji_pack.h"
+#include "chat_helpers/stickers_dice_pack.h"
 #include "storage/file_download.h"
 #include "storage/download_manager_mtproto.h"
 #include "storage/file_upload.h"
@@ -56,6 +57,7 @@ Session::Session(
 , _data(std::make_unique<Data::Session>(this))
 , _user(_data->processUser(user))
 , _emojiStickersPack(std::make_unique<Stickers::EmojiPack>(this))
+, _diceStickersPack(std::make_unique<Stickers::DicePack>(this))
 , _changelogs(Core::Changelogs::Create(this))
 , _supportHelper(Support::Helper::Create(this)) {
 	Core::App().passcodeLockChanges(
diff --git a/Telegram/SourceFiles/main/main_session.h b/Telegram/SourceFiles/main/main_session.h
index 10ef88afb..552bd7630 100644
--- a/Telegram/SourceFiles/main/main_session.h
+++ b/Telegram/SourceFiles/main/main_session.h
@@ -46,6 +46,7 @@ class Instance;
 
 namespace Stickers {
 class EmojiPack;
+class DicePack;
 } // namespace Stickers;
 
 namespace Core {
@@ -89,9 +90,12 @@ public:
 	[[nodiscard]] Storage::Facade &storage() {
 		return *_storage;
 	}
-	[[nodiscard]] Stickers::EmojiPack &emojiStickersPack() {
+	[[nodiscard]] Stickers::EmojiPack &emojiStickersPack() const {
 		return *_emojiStickersPack;
 	}
+	[[nodiscard]] Stickers::DicePack &diceStickersPack() const {
+		return *_diceStickersPack;
+	}
 
 	[[nodiscard]] base::Observable<void> &downloaderTaskFinished();
 
@@ -157,6 +161,7 @@ private:
 
 	// _emojiStickersPack depends on _data.
 	const std::unique_ptr<Stickers::EmojiPack> _emojiStickersPack;
+	const std::unique_ptr<Stickers::DicePack> _diceStickersPack;
 
 	// _changelogs depends on _data, subscribes on chats loading event.
 	const std::unique_ptr<Core::Changelogs> _changelogs;
diff --git a/Telegram/SourceFiles/storage/localimageloader.cpp b/Telegram/SourceFiles/storage/localimageloader.cpp
index 53de99d95..5d497fe99 100644
--- a/Telegram/SourceFiles/storage/localimageloader.cpp
+++ b/Telegram/SourceFiles/storage/localimageloader.cpp
@@ -967,6 +967,10 @@ void FileLoadTask::finish() {
 	}
 }
 
+FileLoadResult *FileLoadTask::peekResult() const {
+	return _result.get();
+}
+
 void FileLoadTask::removeFromAlbum() {
 	if (!_album) {
 		return;
diff --git a/Telegram/SourceFiles/storage/localimageloader.h b/Telegram/SourceFiles/storage/localimageloader.h
index 1f4ada86b..029b71637 100644
--- a/Telegram/SourceFiles/storage/localimageloader.h
+++ b/Telegram/SourceFiles/storage/localimageloader.h
@@ -292,6 +292,8 @@ public:
 	void process();
 	void finish();
 
+	FileLoadResult *peekResult() const;
+
 private:
 	static bool CheckForSong(
 		const QString &filepath,