From 853cafe195243676da45f16885af651f228c7bbe Mon Sep 17 00:00:00 2001
From: John Preston <johnprestonmail@gmail.com>
Date: Fri, 20 May 2022 18:57:01 +0400
Subject: [PATCH] Show premium stickers lock icon.

---
 .../Resources/icons/emoji/premium_lock.png    | Bin 0 -> 1504 bytes
 .../Resources/icons/emoji/premium_lock@2x.png | Bin 0 -> 1592 bytes
 .../Resources/icons/emoji/premium_lock@3x.png | Bin 0 -> 1755 bytes
 .../SourceFiles/boxes/edit_caption_box.cpp    |   4 +-
 .../boxes/filters/edit_filter_chats_list.cpp  |   2 +-
 .../SourceFiles/boxes/premium_limits_box.cpp  |  16 ++---
 .../boxes/reactions_settings_box.cpp          |   2 +-
 Telegram/SourceFiles/boxes/send_files_box.cpp |   6 +-
 .../SourceFiles/boxes/sticker_preview_box.cpp |   8 +--
 .../chat_helpers/chat_helpers.style           |   2 +
 .../chat_helpers/stickers_list_widget.cpp     |  55 ++++++++++++++++--
 .../chat_helpers/stickers_list_widget.h       |   3 +
 .../view/history_view_emoji_interactions.cpp  |   9 ++-
 .../view/media/history_view_sticker.cpp       |  26 +++++++--
 .../history/view/media/history_view_sticker.h |   2 +
 Telegram/SourceFiles/main/main_session.cpp    |   4 ++
 Telegram/SourceFiles/main/main_session.h      |   1 +
 .../ui/effects/premium_graphics.cpp           |  32 ++++++----
 .../SourceFiles/ui/effects/premium_graphics.h |   6 ++
 19 files changed, 137 insertions(+), 41 deletions(-)
 create mode 100644 Telegram/Resources/icons/emoji/premium_lock.png
 create mode 100644 Telegram/Resources/icons/emoji/premium_lock@2x.png
 create mode 100644 Telegram/Resources/icons/emoji/premium_lock@3x.png

diff --git a/Telegram/Resources/icons/emoji/premium_lock.png b/Telegram/Resources/icons/emoji/premium_lock.png
new file mode 100644
index 0000000000000000000000000000000000000000..0498a400ee86ee36f1d55f23ba10793fb139301a
GIT binary patch
literal 1504
zcmbVMU1;4@9FK13)={l?5A_2V(+4LrIZ5tqZ*yp@T~pgTOfBt&)zWP}_ndR@4fiG|
zCTVkT6&y-Ih2e`2!*+<^_NH%p5LcWVGJM#FJ{0sp!Lh**H$m}9!IS$DR+$bLlAN#K
z`Tf8D?@Uikbay@8B?v-ye$txZV{h{9xS#+3(mz_`!%lzll~53N@q=Bx_X!`Y_X)!G
zn@(XanzLVmn7IlftVor*>vOaq43E@(gsU_Xi?r-`rgZD`FC@_+rgU(?R&9TbR-DO|
zfX=Q=74S+G8$=p;UL3ANPT<lAiFLQ;g|Kc)O<u_7$u^M0CM2qw(r6-3oU^CJF&0oU
zr)V-(RaMLxih(iC68fB|tGW)<4A8Q&ra^rWYKGW;BrYx>B{*Zf*cQfDrc{X{9|91^
zu@Yw#7L<Wz7zR*vpzAV6$YH~aP+j)I{tkmhLmW7M<S<W67*UZeMW)16ZQ0=ZDXkZ_
z{lq;6>c|J0q9!&qfdr>Ge<`Rng%b>Djk?r}LXOo^tY2Xf3oGnjsMF&u0=RE&JC$)q
zU0gR65k}+7+>EwE?uZTx4WEJ;8nUGT)A41lW`AOh561$EA{G=Ft92qZ-BDT8GfGC>
zd(iO+i^FGcyFe`zQBz8yCaVLoW)!q6)CQrh?^Cl-Ra;P-5vSDH3f0wuHU#-Qklh01
zIYUr{?g}OtmRR5-Zm{E`G6lX@mc-PJaE#Shzy)*dGEFUP8|J+*LLR1h%apjyisKNj
zqd_pvm1LC588X$g19Fj|oLtm$Br~L|C6YBd_brB(lE`-MlmB`D<-p;kg=+WAlN4N%
z5^&N9d9WJoikPLZwr4d*Y-RyOILU5P!bw;uk=onNJ$s-<8&@bN{f}_BU?D3-F$(Bt
znS1N5=>)j)AgRNa9pIlPHqUOW*$$jHf@GSuAihYO81;DP3V4g^dF$)TyuBUITcd@c
zW52v-c5QpQXZ6Czzd!KQ3uit&w))A5iQu&_pQ!g<`03=1?VEd+^J}kvb$0lN+}>~4
zuM4MU4&2%}z1cT=;Ks&}8}XA59-ZHJ^!;xS+12i|#)Ngr5axgW?2qI9CwD(`ZGGgo
z6ANoc9^JoKT1VG=&aHkofBxOg@2~7W|IlJwczd?-=Q9~_+Sqfk@9IMFdf(NX@*9I^
ZgmXR4;fEhPQcZeretgRMbpPU;e*+h?=j{Lh

literal 0
HcmV?d00001

diff --git a/Telegram/Resources/icons/emoji/premium_lock@2x.png b/Telegram/Resources/icons/emoji/premium_lock@2x.png
new file mode 100644
index 0000000000000000000000000000000000000000..78390b73412af99160de7e8a7d0f0b02ebaa1208
GIT binary patch
literal 1592
zcmbVMZD`zN9FJ~--mDuAyv|KbGdx$@ykGCkV{ct;s&{3n-R)pEnQpn{xx3ILPfT*V
zyM7o`I+$AUg(`H8g5n_zI}h=LxT#-82NQ*X=m!;rsYBhI4D8V1@X5Wg%5=CulIP|3
zfBF62o}Czfv@3LXh#-irR8mgke<XNsy%~S+-@We-{JYIb?(_&^)!N{_i8yq)n;=&H
zYGks0R@n+PWHG9aa*(N54n`Bi;84X;wMpocIao041a;xq#}sMk32MiH!YR%OEE>rv
z7jB;#&uCMVnxs=ho5{fnzzQtrt7OG8Z4XouR6{So>)@EB$OgopOi;stK{BgMkR!;2
zWSrq?jpH~nE-{j(X;B^alL99QEGM#jl;(LL!~idmt%t(qTs;rc@*^!{c$c7xzV85*
zEtktoS!9q~V0lTBSWaLCfyM~htJ=O=p>1ztTZ0Te%{3g~KsFg@RCB20Cn)S{lY`}S
z)Y@JvPB>z0MRi!7;Q~$#pssarPRTVJ#&wN_CbXdKdl<`iuuc*A$Sb0MQQf&-W&p=l
zQ93rR>5FA`OnCn2UQDAEkZYp7Ox1yG8hWVYYH)Nfc5`FE#sMQPRDI-T5Hj1DnrORB
z3L+ztn|2tsj>=x|RRT~}eVCwvtkK*6%}W_R3iuchgg!0`IIam*kZ$Cw%b^07;UC1=
z1!8m=6xWQd`s#JTx(4#dwNy;lu+#!%9lJo0oiKtCWFi+E#@>kyFBAo&Y|mG14W{G-
zg*h{Zp#wM|h<r|yXqe+gTF|2+or7GS<~f*?V)>Ys7xlKhjI>ga*|xm?Kjj~D4cuC)
zdBb{wh6_ppBn=NItJ>;_?eMAA$~4GE6#!KWsyjhxL0TbZ&^$J7I08-iauH&s|B>z{
z%tLv<th#WxfTMNYa$>RbY|w{I9_&9UHtw$K*)|*xf?(MhL3q;{V$jBu%f%xqUafD&
z<L$SUJe<iMI6wPP=mfcD%cpl#4$dy!`Qirm=$_X;JGQbXT#qi)6zBQ+%L>U4#p)l8
z!TkIRFs%!7Z*4oL5c`iD`T2v$^n2D<rEj>~<GaqSIJ;}|o=9;)IvfA<_$Bq}OIPmd
zBTig7?4`$gYaX){BEo$K)|@`sy?*sN?eqiF$^PHRX4ZeZsz>gHGwZ%w?5=&@|D6DL
zzIx`33zvVYe!aN=liBdadrx(3svRsYJhAWOeP28-zd1XfrgG1jA!<GyS&IKs`tZla
z?CPEk?-#ed{mNf2gf9>NU>>j4=iYtYJd}Uu;+9k4q3&Dewnn_QXzu*bli$~8UJ7P=
NYIIya`tY7-{svq{5;gz;

literal 0
HcmV?d00001

diff --git a/Telegram/Resources/icons/emoji/premium_lock@3x.png b/Telegram/Resources/icons/emoji/premium_lock@3x.png
new file mode 100644
index 0000000000000000000000000000000000000000..81b8e06001552db2ce124c540eb70a75d26d0ea0
GIT binary patch
literal 1755
zcmbVN4NMbP952dT)e+qwv)M;-Idqh4?R~U-^q?9_Q9z4;Wk51?$K5Nv^yALED{Wa8
zC%U;gWsXIdOjx23lP0h^C)?--7^5t4Y&vw9u}Kye*~X9{#4+~yu9QX=H#0AJ_ujqt
zd%yqp|6VCB+K{m9k!32CDxo0XS_)^AGSrLUdvRUTmvCAt<X1{6)$&AT#Hm^iYgDTE
z8=SpDuCQ&Q7~Z3&S-u+R10DgQRjTZD0fA;*Kt`%T4d*qZ6X9MI;aD?To@T>sLN0J}
z`E?@LQdeYW>RgP8Mc1uGvI7((@Bo=c0v@+lq5@_#!b`!mvW=lg1R}f4XpSNfsjw9z
zxx5IF3_YP^a2!W6OnMW;Fh&+Ug^)N&Vz>b#j5>m#$aIP@A<+kg;zZU#m0H(Fg~2Z~
z>Xc=H!Z5$zulF1DyjX(~CX)%nNsJ_Q5TTQTUYQQ)yi)Q!gB3`O$O$sXdl7|^uI7ER
z8HK9O+29dkv|cIdC+IOOKnob5#}%6*K$eN&1fS@R2xl1#xPb?FWeH-57*=rdGA}v#
zf1!>YFAxBIYqP~<+))>gCniFY^J<|PQHR_SE!l$tz)FF{`$Puh)j~Cs6>9`4R|K@o
zi*}xO&qu0wUS)(d=naUrob$50UrN300<h9DFr!M;ba<MMFxd$sMWj<C`6O<naC{DG
z<5|uTTnHs`JCR9|IE9-QKw-|Xv`pU>%rcaN7d<pInDfvz02915C=zocmCL(%5ekOd
z86sNPY*c|)l4&mk3an-n+N|d|mNGa<8n8I6V@V^aGXkSgmzj~q=+ZMu(!i1#>8yj8
zzi;IkpAy;m`|SU`zggs9Y0>U`=1~exNeL>SlVGrd(TdmtwntZP4vAy|MKelvn^8sy
zD`3&+Hh0e+n4|SO0VMs8aL>Uc-XZ&G5#-cBZ{0PWFsMAH)Zv^R*gs8-oZVKl^KjS*
zlx3_1!H-xI176s<MA)KceeoSCRooi|)*QQY=lBp2+J$TSCTHSb-Mc}nu0NWx{pOOk
zoKF)zuHTh%V5?=tfq|0vl<-ih<^9~?L$lwXx>&L8x1N#Jvxj~^o{q-DM)|^DMF+!&
z+qs5oA9lJl>xX>%h>yn3e;3@^1geJikLa5>Hi5R$@z!%CNoyLIb5}C=5D)jCIHG;7
z2Hm}~a8T}QY;OPY>LK-u^b9`z!~<u{xxOlXxM@XbjM|Hi{Bl$q8f)2csjH)NEPQH7
zPTx>c9^G<%`jT<rh<0WtqONt>8rh#TFP-ih562C6?V;avG_I~Z`R!0k^K1Rr<f^i=
zL8E`MZO~qpmet!Adiwl(?PF8FW@nul8690!ae21-LU)4mk7Rq<Sxurvdu;Qc;hWlH
zyI1Zz5h`5U@cHiR!5(Dtc=i_`44l<$T>8mr4S%Ij{W=^EeqHsmdQ<9UqwR--+oqr2
zk@;BL+pAoU_m{jodhr%IvV3Ctt@}ELXTJHWXJX9_U3W``tFp;5C6*_;%&kS1sdt_k
nznay0|Aj|ePey(>eJS0GjM=@nCPOcOrfd}C6<Iqi&({A9DC}+1

literal 0
HcmV?d00001

diff --git a/Telegram/SourceFiles/boxes/edit_caption_box.cpp b/Telegram/SourceFiles/boxes/edit_caption_box.cpp
index 0952f70f7..df0fa7ab0 100644
--- a/Telegram/SourceFiles/boxes/edit_caption_box.cpp
+++ b/Telegram/SourceFiles/boxes/edit_caption_box.cpp
@@ -345,7 +345,7 @@ void EditCaptionBox::setupEditEventHandler() {
 			}
 			return true;
 		};
-		const auto premium = _controller->session().user()->isPremium();
+		const auto premium = _controller->session().premium();
 		auto list = Storage::PreparedFileFromFilesDialog(
 			std::move(result),
 			checkResult,
@@ -524,7 +524,7 @@ void EditCaptionBox::updateEmojiPanelGeometry() {
 }
 
 bool EditCaptionBox::fileFromClipboard(not_null<const QMimeData*> data) {
-	const auto premium = _controller->session().user()->isPremium();
+	const auto premium = _controller->session().premium();
 	return setPreparedList(ListFromMimeData(data, premium));
 }
 
diff --git a/Telegram/SourceFiles/boxes/filters/edit_filter_chats_list.cpp b/Telegram/SourceFiles/boxes/filters/edit_filter_chats_list.cpp
index 031dd27b2..afdc9c194 100644
--- a/Telegram/SourceFiles/boxes/filters/edit_filter_chats_list.cpp
+++ b/Telegram/SourceFiles/boxes/filters/edit_filter_chats_list.cpp
@@ -104,7 +104,7 @@ private:
 }
 
 [[nodiscard]] int Limit(not_null<Main::Session*> session) {
-	const auto premium = session->user()->isPremium();
+	const auto premium = session->premium();
 	return Limit(session,
 		(premium
 			? "dialog_filters_chats_limit_premium"
diff --git a/Telegram/SourceFiles/boxes/premium_limits_box.cpp b/Telegram/SourceFiles/boxes/premium_limits_box.cpp
index 1b02125b3..5cf831940 100644
--- a/Telegram/SourceFiles/boxes/premium_limits_box.cpp
+++ b/Telegram/SourceFiles/boxes/premium_limits_box.cpp
@@ -454,7 +454,7 @@ void SimplePinsLimitBox(
 		int limitDefault,
 		const QString &keyPremium,
 		int limitPremium) {
-	const auto premium = session->user()->isPremium();
+	const auto premium = session->premium();
 
 	const auto defaultLimit = Limit(session, keyDefault, limitDefault);
 	const auto premiumLimit = Limit(session, keyPremium, limitPremium);
@@ -489,7 +489,7 @@ void SimplePinsLimitBox(
 void ChannelsLimitBox(
 		not_null<Ui::GenericBox*> box,
 		not_null<Main::Session*> session) {
-	const auto premium = session->user()->isPremium();
+	const auto premium = session->premium();
 
 	const auto defaultLimit = Limit(session, "channels_limit_default", 500);
 	const auto premiumLimit = Limit(session, "channels_limit_premium", 1000);
@@ -574,7 +574,7 @@ void PublicLinksLimitBox(
 		not_null<Ui::GenericBox*> box,
 		not_null<Window::SessionNavigation*> navigation) {
 	const auto session = &navigation->session();
-	const auto premium = session->user()->isPremium();
+	const auto premium = session->premium();
 
 	const auto defaultLimit = Limit(
 		session,
@@ -639,7 +639,7 @@ void PublicLinksLimitBox(
 void FilterChatsLimitBox(
 		not_null<Ui::GenericBox*> box,
 		not_null<Main::Session*> session) {
-	const auto premium = session->user()->isPremium();
+	const auto premium = session->premium();
 
 	const auto defaultLimit = Limit(
 		session,
@@ -679,7 +679,7 @@ void FilterChatsLimitBox(
 void FiltersLimitBox(
 		not_null<Ui::GenericBox*> box,
 		not_null<Main::Session*> session) {
-	const auto premium = session->user()->isPremium();
+	const auto premium = session->premium();
 
 	const auto defaultLimit = Limit(
 		session,
@@ -754,7 +754,7 @@ void PinsLimitBox(
 void CaptionLimitBox(
 		not_null<Ui::GenericBox*> box,
 		not_null<Main::Session*> session) {
-	const auto premium = session->user()->isPremium();
+	const auto premium = session->premium();
 
 	const auto defaultLimit = Limit(
 		session,
@@ -795,7 +795,7 @@ void CaptionLimitReachedBox(
 		.text = tr::lng_caption_limit_reached(tr::now, lt_count, remove),
 		.inform = true,
 	});
-	if (!session->user()->isPremium()) {
+	if (!session->premium()) {
 		box->addLeftButton(tr::lng_limits_increase(), [=] {
 			box->getDelegate()->showBox(
 				Box(CaptionLimitBox, session),
@@ -821,7 +821,7 @@ int CurrentPremiumLimit(
 		int limitDefault,
 		const QString &keyPremium,
 		int limitPremium) {
-	const auto premium = session->user()->isPremium();
+	const auto premium = session->premium();
 	return AppConfigLimit(
 		session,
 		premium ? keyPremium : keyDefault,
diff --git a/Telegram/SourceFiles/boxes/reactions_settings_box.cpp b/Telegram/SourceFiles/boxes/reactions_settings_box.cpp
index bd0207b30..22e28a108 100644
--- a/Telegram/SourceFiles/boxes/reactions_settings_box.cpp
+++ b/Telegram/SourceFiles/boxes/reactions_settings_box.cpp
@@ -447,7 +447,7 @@ void ReactionsSettingsBox(
 			&button->lifetime());
 
 		button->setClickedCallback([=, emoji = r.emoji] {
-			if (premium && !controller->session().user()->isPremium()) {
+			if (premium && !controller->session().premium()) {
 				Settings::ShowPremium(&controller->session());
 				return;
 			}
diff --git a/Telegram/SourceFiles/boxes/send_files_box.cpp b/Telegram/SourceFiles/boxes/send_files_box.cpp
index 78c3cc6bc..22d901734 100644
--- a/Telegram/SourceFiles/boxes/send_files_box.cpp
+++ b/Telegram/SourceFiles/boxes/send_files_box.cpp
@@ -404,7 +404,7 @@ void SendFilesBox::openDialogToAddFileToAlbum() {
 		return true;
 	};
 	const auto callback = [=](FileDialog::OpenResult &&result) {
-		const auto premium = _controller->session().user()->isPremium();
+		const auto premium = _controller->session().premium();
 		FileDialogCallback(
 			std::move(result),
 			checkResult,
@@ -575,7 +575,7 @@ void SendFilesBox::pushBlock(int from, int till) {
 			return true;
 		};
 		const auto callback = [=](FileDialog::OpenResult &&result) {
-			const auto premium = _controller->session().user()->isPremium();
+			const auto premium = _controller->session().premium();
 			FileDialogCallback(
 				std::move(result),
 				checkResult,
@@ -773,7 +773,7 @@ bool SendFilesBox::canAddFiles(not_null<const QMimeData*> data) const {
 }
 
 bool SendFilesBox::addFiles(not_null<const QMimeData*> data) {
-	const auto premium = _controller->session().user()->isPremium();
+	const auto premium = _controller->session().premium();
 	auto list = [&] {
 		const auto urls = data->hasUrls() ? data->urls() : QList<QUrl>();
 		auto result = CanAddUrls(urls)
diff --git a/Telegram/SourceFiles/boxes/sticker_preview_box.cpp b/Telegram/SourceFiles/boxes/sticker_preview_box.cpp
index 43c23baf9..c4a3ff33b 100644
--- a/Telegram/SourceFiles/boxes/sticker_preview_box.cpp
+++ b/Telegram/SourceFiles/boxes/sticker_preview_box.cpp
@@ -16,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "main/main_session.h"
 #include "ui/chat/chat_theme.h"
 #include "ui/layers/generic_box.h"
+#include "ui/effects/premium_graphics.h"
 #include "ui/widgets/buttons.h"
 #include "ui/widgets/gradient_round_button.h"
 #include "ui/wrap/padding_wrap.h"
@@ -149,11 +150,7 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
 
 [[nodiscard]] object_ptr<Ui::AbstractButton> CreatePremiumButton(
 		QWidget *parent) {
-	return CreateGradientButton(parent, {
-		{ 0., st::premiumButtonBg1->c },
-		{ 0.6, st::premiumButtonBg2->c },
-		{ 1., st::premiumButtonBg3->c },
-	});
+	return CreateGradientButton(parent, Ui::Premium::ButtonGradientStops());
 }
 
 [[nodiscard]] object_ptr<Ui::AbstractButton> CreateUnlockButton(
@@ -167,6 +164,7 @@ void PreloadSticker(const std::shared_ptr<Data::DocumentMedia> &media) {
 		result.data(),
 		tr::lng_sticker_premium_button(),
 		st::premiumPreviewButtonLabel);
+	label->setAttribute(Qt::WA_TransparentForMouseEvents);
 	rpl::combine(
 		result->widthValue(),
 		label->widthValue()
diff --git a/Telegram/SourceFiles/chat_helpers/chat_helpers.style b/Telegram/SourceFiles/chat_helpers/chat_helpers.style
index 98a78b043..fecbfcb7b 100644
--- a/Telegram/SourceFiles/chat_helpers/chat_helpers.style
+++ b/Telegram/SourceFiles/chat_helpers/chat_helpers.style
@@ -298,3 +298,5 @@ premiumPreviewButtonLabel: FlatLabel(defaultFlatLabel) {
 	textFg: premiumButtonFg;
 	style: semiboldTextStyle;
 }
+
+stickersPremiumLock: icon{{ "emoji/premium_lock", premiumButtonFg }};
diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp
index 9a1d5986b..18de32b54 100644
--- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp
+++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.cpp
@@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "data/data_file_origin.h"
 #include "data/data_cloud_file.h"
 #include "data/data_changes.h"
+#include "data/data_peer_values.h"
 #include "menu/menu_send.h" // SendMenu::FillSendMenu
 #include "chat_helpers/stickers_lottie.h"
 #include "ui/widgets/buttons.h"
@@ -21,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 #include "ui/effects/animations.h"
 #include "ui/effects/ripple_animation.h"
 #include "ui/effects/path_shift_gradient.h"
+#include "ui/effects/premium_graphics.h"
 #include "ui/image/image.h"
 #include "ui/cached_round_corners.h"
 #include "lottie/lottie_multi_player.h"
@@ -56,6 +58,7 @@ constexpr auto kPreloadOfficialPages = 4;
 constexpr auto kOfficialLoadLimit = 40;
 constexpr auto kMinRepaintDelay = crl::time(33);
 constexpr auto kMinAfterScrollDelay = crl::time(33);
+constexpr auto kPremiumLockedOpacity = 0.5;
 
 using Data::StickersSet;
 using Data::StickersPack;
@@ -1176,6 +1179,17 @@ StickersListWidget::StickersListWidget(
 	) | rpl::skip(1) | rpl::map_to(
 		TabbedSelector::Action::Update
 	) | rpl::start_to_stream(_choosingUpdated, lifetime());
+
+	style::PaletteChanged(
+	) | rpl::start_with_next([=] {
+		_premiumLock = QImage();
+	}, lifetime());
+
+	Data::AmPremiumValue(
+		&session()
+	) | rpl::start_with_next([=](bool premium) {
+		refreshStickers();
+	}, lifetime());
 }
 
 Main::Session &StickersListWidget::session() const {
@@ -2276,6 +2290,7 @@ void StickersListWidget::paintSticker(
 		return;
 	}
 
+	const auto locked = document->isPremiumSticker() && !session().premium();
 	const auto isLottie = document->sticker()->isLottie();
 	const auto isWebm = document->sticker()->isWebm();
 	if (isLottie
@@ -2302,6 +2317,9 @@ void StickersListWidget::paintSticker(
 		(_singleSize.width() - size.width()) / 2,
 		(_singleSize.height() - size.height()) / 2);
 
+	if (locked) {
+		p.setOpacity(kPremiumLockedOpacity);
+	}
 	if (sticker.lottie && sticker.lottie->ready()) {
 		auto request = Lottie::FrameRequest();
 		request.box = boundingBoxSize() * cIntRetinaFactor();
@@ -2341,6 +2359,7 @@ void StickersListWidget::paintSticker(
 				sticker.savedFrameFor = _singleSize;
 			}
 		} else {
+			p.setOpacity(1.);
 			PaintStickerThumbnailPath(
 				p,
 				media.get(),
@@ -2358,16 +2377,40 @@ void StickersListWidget::paintSticker(
 		p.setOpacity(1.);
 	}
 
-	if (document->isPremiumSticker()) {
+	if (locked) {
+		p.setOpacity(1.);
+
+		validatePremiumLock();
+		const auto factor = style::DevicePixelRatio();
 		const auto point = pos
 			+ QPoint(
-				_singleSize.width() - st::stickerPanDeleteIconBg.width(),
-				_singleSize.height() - st::stickerPanDeleteIconBg.height());
-		st::stickerPanDeleteIconBg.paint(p, point, width());
-		st::stickerPanDeleteIconFg.paint(p, point, width());
+				_singleSize.width() - (_premiumLock.width() / factor),
+				_singleSize.height() - (_premiumLock.height() / factor));
+		p.drawImage(point, _premiumLock);
 	}
 }
 
+void StickersListWidget::validatePremiumLock() {
+	if (!_premiumLock.isNull()) {
+		return;
+	}
+	const auto factor = style::DevicePixelRatio();
+	const auto size = st::stickersPremiumLock.size();
+	_premiumLock = QImage(
+		size * factor,
+		QImage::Format_ARGB32_Premultiplied);
+	_premiumLock.setDevicePixelRatio(factor);
+	auto p = QPainter(&_premiumLock);
+	auto gradient = QLinearGradient(
+		QPoint(0, size.height()),
+		QPoint(size.width(), 0));
+	gradient.setStops(Ui::Premium::LockGradientStops());
+	p.fillRect(QRect(QPoint(), size), gradient);
+	st::stickersPremiumLock.paint(p, 0, 0, size.width());
+	p.end();
+	_premiumLock = Images::Circle(std::move(_premiumLock));
+}
+
 int StickersListWidget::stickersRight() const {
 	return stickersLeft() + (_columnCount * _singleSize.width());
 }
@@ -2991,7 +3034,7 @@ bool StickersListWidget::appendSet(
 		PrepareStickers((set->stickers.empty() && externalLayout)
 			? set->covers
 			: set->stickers));
-	if (!externalLayout && _premiumsIndex >= 0) {
+	if (!externalLayout && _premiumsIndex >= 0 && session().premium()) {
 		for (const auto &sticker : to.back().stickers) {
 			const auto document = sticker.document;
 			if (document->isPremiumSticker()) {
diff --git a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h
index 3fcbee7b4..b7ca4d829 100644
--- a/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h
+++ b/Telegram/SourceFiles/chat_helpers/stickers_list_widget.h
@@ -330,6 +330,7 @@ private:
 	void addSearchRow(not_null<Data::StickersSet*> set);
 
 	void showPreview();
+	void validatePremiumLock();
 
 	Ui::MessageSendingAnimationFrom messageSentAnimationInfo(
 		int section,
@@ -390,6 +391,8 @@ private:
 	base::Timer _previewTimer;
 	bool _previewShown = false;
 
+	QImage _premiumLock;
+
 	std::map<QString, std::vector<uint64>> _searchCache;
 	std::vector<std::pair<uint64, QStringList>> _searchIndex;
 	base::Timer _searchRequestTimer;
diff --git a/Telegram/SourceFiles/history/view/history_view_emoji_interactions.cpp b/Telegram/SourceFiles/history/view/history_view_emoji_interactions.cpp
index 58912f32f..5e4774a5a 100644
--- a/Telegram/SourceFiles/history/view/history_view_emoji_interactions.cpp
+++ b/Telegram/SourceFiles/history/view/history_view_emoji_interactions.cpp
@@ -94,18 +94,25 @@ void EmojiInteractions::play(
 void EmojiInteractions::playPremiumEffect(
 		not_null<const Element*> view,
 		Element *replacing) {
+	const auto already = ranges::contains(_plays, view, &Play::view);
 	if (replacing) {
 		const auto i = ranges::find(_plays, replacing, &Play::view);
 		if (i != end(_plays)) {
 			//if (i->premium) {
 			//	replacing->externalLottieProgressing(false);
 			//}
-			i->view = view;
+			if (already) {
+				_plays.erase(i);
+			} else {
+				i->view = view;
+			}
 			//if (i->premium) {
 			//	view->externalLottieProgressing(true);
 			//}
 			return;
 		}
+	} else if (already) {
+		return;
 	}
 	if (const auto media = view->media()) {
 		if (const auto document = media->getDocument()) {
diff --git a/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp b/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp
index be086e6ef..10986eb7f 100644
--- a/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp
+++ b/Telegram/SourceFiles/history/view/media/history_view_sticker.cpp
@@ -255,6 +255,7 @@ void Sticker::paintLottie(
 		_lottieOncePlayed = true;
 		_parent->delegate()->elementStartStickerLoop(_parent);
 	}
+	checkPremiumEffectStart();
 }
 
 bool Sticker::paintPixmap(
@@ -362,7 +363,16 @@ void Sticker::refreshLink() {
 			}
 		});
 	} else if (sticker && sticker->set) {
-		_link = ShowSetHandler(_data);
+		if (_data->isPremiumSticker()) {
+			const auto weak = base::make_weak(this);
+			_link = std::make_shared<LambdaClickHandler>([weak] {
+				if (const auto that = weak.get()) {
+					that->premiumStickerClicked();
+				}
+			});
+		} else {
+			_link = ShowSetHandler(_data);
+		}
 	} else if (sticker
 		&& (_data->dimensions.width() > kStickerSideSize
 			|| _data->dimensions.height() > kStickerSideSize)
@@ -388,6 +398,11 @@ void Sticker::emojiStickerClicked() {
 	_parent->history()->owner().requestViewRepaint(_parent);
 }
 
+void Sticker::premiumStickerClicked() {
+	_premiumEffectPlayed = false;
+	_parent->history()->owner().requestViewRepaint(_parent);
+}
+
 void Sticker::ensureDataMediaCreated() const {
 	if (_dataMedia) {
 		return;
@@ -423,12 +438,15 @@ void Sticker::setupLottie() {
 		ChatHelpers::StickerLottieSize::MessageHistory,
 		size() * style::DevicePixelRatio(),
 		Lottie::Quality::High);
-	if (_data->isPremiumSticker()
-		&& !_premiumEffectPlayed) {
+	checkPremiumEffectStart();
+	lottieCreated();
+}
+
+void Sticker::checkPremiumEffectStart() {
+	if (!_premiumEffectPlayed && _data->isPremiumSticker()) {
 		_premiumEffectPlayed = true;
 		_parent->delegate()->elementStartPremium(_parent, nullptr);
 	}
-	lottieCreated();
 }
 
 void Sticker::lottieCreated() {
diff --git a/Telegram/SourceFiles/history/view/media/history_view_sticker.h b/Telegram/SourceFiles/history/view/media/history_view_sticker.h
index c0bcd67be..f8916c40e 100644
--- a/Telegram/SourceFiles/history/view/media/history_view_sticker.h
+++ b/Telegram/SourceFiles/history/view/media/history_view_sticker.h
@@ -100,6 +100,8 @@ private:
 	void lottieCreated();
 	void unloadLottie();
 	void emojiStickerClicked();
+	void premiumStickerClicked();
+	void checkPremiumEffectStart();
 	//bool markFramesTillExternal();
 
 	const not_null<Element*> _parent;
diff --git a/Telegram/SourceFiles/main/main_session.cpp b/Telegram/SourceFiles/main/main_session.cpp
index 13fb3c78f..b6d2b8803 100644
--- a/Telegram/SourceFiles/main/main_session.cpp
+++ b/Telegram/SourceFiles/main/main_session.cpp
@@ -218,6 +218,10 @@ rpl::producer<> Session::downloaderTaskFinished() const {
 	return downloader().taskFinished();
 }
 
+bool Session::premium() const {
+	return _user->isPremium();
+}
+
 uint64 Session::uniqueId() const {
 	// See also Account::willHaveSessionUniqueId.
 	return userId().bare
diff --git a/Telegram/SourceFiles/main/main_session.h b/Telegram/SourceFiles/main/main_session.h
index c867e6917..2e6194f7b 100644
--- a/Telegram/SourceFiles/main/main_session.h
+++ b/Telegram/SourceFiles/main/main_session.h
@@ -80,6 +80,7 @@ public:
 	[[nodiscard]] Domain &domain() const;
 	[[nodiscard]] Storage::Domain &domainLocal() const;
 
+	[[nodiscard]] bool premium() const;
 	[[nodiscard]] uint64 uniqueId() const; // userId() with TestDC shift.
 	[[nodiscard]] UserId userId() const;
 	[[nodiscard]] PeerId userPeerId() const;
diff --git a/Telegram/SourceFiles/ui/effects/premium_graphics.cpp b/Telegram/SourceFiles/ui/effects/premium_graphics.cpp
index b3c16bd5a..4467f8f94 100644
--- a/Telegram/SourceFiles/ui/effects/premium_graphics.cpp
+++ b/Telegram/SourceFiles/ui/effects/premium_graphics.cpp
@@ -29,15 +29,6 @@ constexpr auto kStepBeforeDeflection = 0.75;
 constexpr auto kStepAfterDeflection = kStepBeforeDeflection
 	+ (1. - kStepBeforeDeflection) / 2.;
 
-[[nodiscard]] QGradientStops GradientStops() {
-	return QGradientStops{
-		QGradientStop(0.0, st::premiumButtonBg1->c),
-		QGradientStop(.25, st::premiumButtonBg1->c),
-		QGradientStop(.85, st::premiumButtonBg2->c),
-		QGradientStop(1.0, st::premiumButtonBg3->c),
-	};
-}
-
 [[nodiscard]] QLinearGradient ComputeGradient(
 		not_null<QWidget*> content,
 		int left,
@@ -46,7 +37,7 @@ constexpr auto kStepAfterDeflection = kStepBeforeDeflection
 	// Take a full width of parent box without paddings.
 	const auto fullGradientWidth = content->parentWidget()->width();
 	auto fullGradient = QLinearGradient(0, 0, fullGradientWidth, 0);
-	fullGradient.setStops(GradientStops());
+	fullGradient.setStops(ButtonGradientStops());
 
 	auto gradient = QLinearGradient(0, 0, width, 0);
 	const auto fullFinal = float64(fullGradient.finalStop().x());
@@ -506,5 +497,26 @@ void AddLimitRow(not_null<Ui::VerticalLayout*> parent, int max) {
 		st::boxRowPadding);
 }
 
+QGradientStops LimitGradientStops() {
+	return {
+		{ 0.0, st::premiumButtonBg1->c },
+		{ .25, st::premiumButtonBg1->c },
+		{ .85, st::premiumButtonBg2->c },
+		{ 1.0, st::premiumButtonBg3->c },
+	};
+}
+
+QGradientStops ButtonGradientStops() {
+	return {
+		{ 0., st::premiumButtonBg1->c },
+		{ 0.6, st::premiumButtonBg2->c },
+		{ 1., st::premiumButtonBg3->c },
+	};
+}
+
+QGradientStops LockGradientStops() {
+	return ButtonGradientStops();
+}
+
 } // namespace Premium
 } // namespace Ui
diff --git a/Telegram/SourceFiles/ui/effects/premium_graphics.h b/Telegram/SourceFiles/ui/effects/premium_graphics.h
index b8c14d0ca..3c22ff059 100644
--- a/Telegram/SourceFiles/ui/effects/premium_graphics.h
+++ b/Telegram/SourceFiles/ui/effects/premium_graphics.h
@@ -7,6 +7,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
 */
 #pragma once
 
+#include <QtGui/QBrush>
+
 namespace tr {
 template <typename ...>
 struct phrase;
@@ -31,5 +33,9 @@ void AddBubbleRow(
 
 void AddLimitRow(not_null<Ui::VerticalLayout*> parent, int max);
 
+[[nodiscard]] QGradientStops LimitGradientStops();
+[[nodiscard]] QGradientStops ButtonGradientStops();
+[[nodiscard]] QGradientStops LockGradientStops();
+
 } // namespace Premium
 } // namespace Ui