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