From e28d29f276ad567b3d0ac13fc452406c7aeaa449 Mon Sep 17 00:00:00 2001 From: 23rd <23rd@vivaldi.net> Date: Sun, 16 Mar 2025 12:11:49 +0300 Subject: [PATCH] Added initial implementation of swipe action to dialogs. --- Telegram/CMakeLists.txt | 2 + .../animations/swipe_action/archive.tgs | Bin 0 -> 1088 bytes .../animations/swipe_action/delete.tgs | Bin 0 -> 1248 bytes .../animations/swipe_action/disabled.tgs | Bin 0 -> 731 bytes .../animations/swipe_action/mute.tgs | Bin 0 -> 2586 bytes .../Resources/animations/swipe_action/pin.tgs | Bin 0 -> 1387 bytes .../animations/swipe_action/read.tgs | Bin 0 -> 1860 bytes .../animations/swipe_action/unarchive.tgs | Bin 0 -> 1191 bytes .../animations/swipe_action/unmute.tgs | Bin 0 -> 2186 bytes .../animations/swipe_action/unpin.tgs | Bin 0 -> 2607 bytes .../animations/swipe_action/unread.tgs | Bin 0 -> 2084 bytes Telegram/Resources/langs/lang.strings | 11 ++ .../Resources/qrc/telegram/animations.qrc | 11 ++ Telegram/SourceFiles/dialogs/dialogs.style | 2 + .../dialogs/dialogs_inner_widget.cpp | 72 +++++++++++ .../dialogs/dialogs_inner_widget.h | 15 +++ .../dialogs/dialogs_swipe_action.cpp | 29 +++++ .../dialogs/dialogs_swipe_action.h | 22 ++++ .../SourceFiles/dialogs/dialogs_widget.cpp | 60 +++++++-- .../SourceFiles/dialogs/ui/dialogs_layout.cpp | 117 +++++++++++++++++- .../SourceFiles/dialogs/ui/dialogs_layout.h | 5 +- .../dialogs/ui/dialogs_swipe_context.h | 35 ++++++ Telegram/cmake/td_ui.cmake | 1 + 23 files changed, 362 insertions(+), 20 deletions(-) create mode 100644 Telegram/Resources/animations/swipe_action/archive.tgs create mode 100644 Telegram/Resources/animations/swipe_action/delete.tgs create mode 100644 Telegram/Resources/animations/swipe_action/disabled.tgs create mode 100644 Telegram/Resources/animations/swipe_action/mute.tgs create mode 100644 Telegram/Resources/animations/swipe_action/pin.tgs create mode 100644 Telegram/Resources/animations/swipe_action/read.tgs create mode 100644 Telegram/Resources/animations/swipe_action/unarchive.tgs create mode 100644 Telegram/Resources/animations/swipe_action/unmute.tgs create mode 100644 Telegram/Resources/animations/swipe_action/unpin.tgs create mode 100644 Telegram/Resources/animations/swipe_action/unread.tgs create mode 100644 Telegram/SourceFiles/dialogs/dialogs_swipe_action.cpp create mode 100644 Telegram/SourceFiles/dialogs/dialogs_swipe_action.h create mode 100644 Telegram/SourceFiles/dialogs/ui/dialogs_swipe_context.h diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index 028979462b..24b7ed6722 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -688,6 +688,8 @@ PRIVATE dialogs/dialogs_search_from_controllers.h dialogs/dialogs_search_tags.cpp dialogs/dialogs_search_tags.h + dialogs/dialogs_swipe_action.cpp + dialogs/dialogs_swipe_action.h dialogs/dialogs_widget.cpp dialogs/dialogs_widget.h editor/color_picker.cpp diff --git a/Telegram/Resources/animations/swipe_action/archive.tgs b/Telegram/Resources/animations/swipe_action/archive.tgs new file mode 100644 index 0000000000000000000000000000000000000000..73e049e69c344c5da84187d48ff2dc1b55cf534c GIT binary patch literal 1088 zcmV-G1i$+qiwFp_wn1b717m1mbaP)}a${&|c4aPVb8l_{?O020BR3GeiorFT;HTLi z?L0|l4luxM3@tjcJksdXLaXhuVF(Da&K+`vNq```oI$?PR2A7Ds?~#FU!F5W{c(B9JH>l zuSvYv@8|WNO|GV#t&4|wh5g5tz1%{pIIADnB=%t-(BJ`-+5Cp!>*5 z{1l|Uf?kxjXrItdK|#i@X7*=TtmvT<7f=Y^638YxL) zzbJNd=O{YHK33q*vZev@SUQhEkohSZ@7gIq66CLF75*DZVH1v@{!p3^M4~`Oa+2~i zEVt|%?(^V#Mm?NixCU?a4y{H?a)axDRtp_tHy28ShSEqRBFlKBJr#=-rbC6U7fAGV zJCigCOgUqdn_|76AG$D72K`WO>+%*ieX|Af^2awnU3{3&>ax0ckDwaHX3Abrqoa5LghR5HZ zemVYi{O9-wv|o;YL+{Vym#1H!eq)Deh!oo$ZS#!0Yn8-8^NJ*p=2JT%WQX9KP8*4feg-s_6w9bh( zWE!svN4u$7SBQ4^L0#R#fo`(ezJ|OPa?|XikGS#s=mXx7xg$-V{9lKA`kV#8&AL|r z41flF$_#`VfyMWGpo4)+(w2*T2R_EQRFoo??#Cj?0zm3Cwn}9xRzPNH7Q-onEzT{} z8$ORs+$blRHdg0}R4AQF1>H<)nPy088|P9h9ml9U?e5x<%gDOBNQG6%+vR%w?Ha^O zyjCFX)&HNDAZGApQqNm~G*>wl1onHLO6QJ_h6CJullGvv;`-zmrQCl^cid7o>%H1MFo-#XL_%a)p<0CV)a1YO?OjuyF9mpei zdHG)Ad5#seot70f;ysLgePIo*hO;YwMcbEs?YO literal 0 HcmV?d00001 diff --git a/Telegram/Resources/animations/swipe_action/delete.tgs b/Telegram/Resources/animations/swipe_action/delete.tgs new file mode 100644 index 0000000000000000000000000000000000000000..daa3a01626fc0d4c084ebb6a878d68c3270a0a05 GIT binary patch literal 1248 zcmV<61Rwh!iwFp_wn1b719Nw2aAjX)Wo%`1WiD!SZ*BnXSW9o?HW2nO2n*)k+0+eP62-r-9oB{^|k1p+J*i6e42!}&Nv&iJ0(kvS2e z2vb7IuIvgjzb7}?_gmd{oATF9RkpJapJ!1BA&Za)83;C8-CXIWTgmoF$#p~KNkqx! zK<3!g*zk;!?_@53QL;Aeeuw;@>fK=mQpnYn;x5{@>{>EkEGemqA7vxy`+j({#}-i8 z4-{%-{C-k~r~Zqhfa_}}MBR+|V#bSU1xAyzCYnz?<>6!UrFdu{#z(x`>&M#a8<61@lDBfVtpl2m@1*1St*W8xJ)6S@) z=#QdXt4m|I$FC2+eEdB7yIgg3Gy5uGo&~cnO?`VnhBYF4T~uwUHeTX;T@fYM+d8Tb zVyz~&&Ne>Ggg(o_9GPZ0ct2Lt%lXn2hxKNK3z9sO>*>^)>aXX)8)y2q@tx2x@N<`4 za^A#L3f)dklDM?R)QGSf^H)>s+v~d75gARY>rX_Y*xytonz=uyTVoGLWJ^|jj zJ$y;<0EAJT`2MW>oF4z}2h4rRD>uhmK5))$ftss`6P0_O-NuC z@JLAT^Zp{e;=4D*9j~ZXYA>pP^cGhtop594YuD7<^0DaATtDOIZ2Yi`;%E8943PU7 z;76YbAU!W*Z6@i2vZVhWfH=bJP+zEr>{|4Rn>-vu%tNe5E6$s(aoN7A=SA>#~_ z78b#)W{`;^8*=_a*?z((+;w9jnqHRA@sYU?q;oQn!xQ-buG+lfY~VZ8JP&BVD@Q*Q z8mwdIIZB7;YQUY;&x8i+`B*K`JbSJNj0NhvC-m5z99ZH6$zwI{D`whR$g!$aYE`beBs=_E*m&+#hC6(6V;} zEwji%YVq_ajUF?=0@oc*djYEKd8o1>s{Fm6D!4&a6@X$uDCCeuLz<3f5kV?t;!sN5B-5FxIqE=G__ECmYLlv7<_$OFMp z0L+XkQcsaT{U|w)U>yIfwBJLe@TuN?+w9A$Ky8gF7sLz7?Z?Um9N!hqR{uo5JpKn8 Kx-j-f7ytmAcw_JY literal 0 HcmV?d00001 diff --git a/Telegram/Resources/animations/swipe_action/disabled.tgs b/Telegram/Resources/animations/swipe_action/disabled.tgs new file mode 100644 index 0000000000000000000000000000000000000000..a4fb31cb257a14c35435758851a3d025af9900e4 GIT binary patch literal 731 zcmV<10wnz(iwFp_wn1b719Nw2aAjX)X>(y>Y-MCFYIARH0PR*yZ<|06{VQnCYqZOk z6K-jn=2EGZQuShSAU2Mv!JuX1CbInBJ0E}{rje>BQVvmK2Jf5Qoq03!|ZW>XO##67HitE|nluX&L*&egS}TMGU3_ zfcm7Y*^55!N9Jka~nHyfBjZQ3?BaM@oI@qNM6!JiBRO z&G13wxbTRcZWPVs;0e1RiG`N%m%!HQQ`7IW+ z3+1W{BprgJcX%7Fu|twjmWwG!P8|aNd-R7Sf)Li>+3n(m8LxmJG`ckp+40mB)Q3M( zyP;k#cku1%%cpDSSGKg3ac(hvXXf0P>Y)aQ4P?AdizXu)DQ_$2++lA~wV+;njo+2+ zysLvFP1gYOJ$D{>jD~;~OJcP6O{Oepc5~*I* zMk}OSvr8ZA#s)C{%HLSC+JSwyq7~?|V0j;c^$Nl2rQ)@c)e}~V=V_}GAKA+y&<*4H zAa=ty9`b(L^l94qDf7-)R43j`ilI%mB_}T(q@$T`7x;Z^GXvd%j{l|BfS0M+@{iQy N_!mon-Tz4o006{TY>WT^ literal 0 HcmV?d00001 diff --git a/Telegram/Resources/animations/swipe_action/mute.tgs b/Telegram/Resources/animations/swipe_action/mute.tgs new file mode 100644 index 0000000000000000000000000000000000000000..97d7bbf68c6e7f072da78d9af63c706aea8703c6 GIT binary patch literal 2586 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 literal 0 HcmV?d00001 diff --git a/Telegram/Resources/animations/swipe_action/pin.tgs b/Telegram/Resources/animations/swipe_action/pin.tgs new file mode 100644 index 0000000000000000000000000000000000000000..5fbeedbc4fb7a0727d4bc080c5efa94bd42a7119 GIT binary patch literal 1387 zcmV-x1(f<9iwFp_wn1b719Nw2aAjX`X>KlRb8l_{?O0838#fUBE5e?+1c%?$EoswS zilRV+UIZN!TaEEmy64f8o*pU|1q8~SF=>M=???%K%uCKH9tZnCATa71EQLScQ=M7)q9j2EXj4;-H zh0)%|FP~SdY@==R+-=MLZ~14I7u}Yne`1#4Uo$wPFtaDhhYik_DKY06x)wp^pG2B=9%IqU~iJSciS+ba_*TBRYW(DHh+coKl&9 zNc7+7eeaXMXRo&<(1(mrWMjqVN1&+K)CtPEplo}TKVTIQnlczY*3 z0;|1|!Mdklzo2=Hf3JBA$zwp;#cVe(PZ-BqeQFTnvMYJp6fp8cyQumt_7M-ISjmu+ zMn@@C(qx$`DU2mkdCg=}6ONrrq93PXk{_nY1@X6kr+MSashMY6dE@}heqpl-w+6VA zu`+66MdM{4Q70q4^+y5|q*1I9wT$dUkd#*hBdr&~p_CZh);h_gw5YX~Iz8GIY`vyaG8 zsm;~?*IBp7oVwoN?#+*H-;I8sUv=AN^c$DVQ9XL!Y(Fz2EKntHW~+9d^T)OFW>sa= zCuLX^t}ENv{powm7_JZo^{mvpgBD~p?9TgUwp%Q(;1KH!`qObyKckul&K_WwVM0G8 zlwQGH;x~Ue#K1;xhZZp|?QCeq?Gy8%nQhveZL_X8XIYdpk&bpnKw0K7Ct%k#CJ?Wtanvpm_b@7<$4mK5vM+_)~K_>6>2RCkB5I2CmQ|NJUSPl9L4RnUOOmSn2TWIbi~Xp&Wf<%F%t`K*v$PHywlkl0`#r~WWhq9E26_TbwEUdf1Yr?hMRx} zE@uYBErGn8G@0-Q^o>+_O3IMEM-vIy5QOs#CYnlaB9T78xF_S<2V{T>E85bepk46> z5-qLH#OV+o_ax4hI>YoEtrY>8$(9g2Whf#2~Q;!`DE7VSbnzAR{57Yr=IN*3#w>PugY zJq?>8#OHP27zDu@y4c~%5OeQm9PJlr4N!0I literal 0 HcmV?d00001 diff --git a/Telegram/Resources/animations/swipe_action/read.tgs b/Telegram/Resources/animations/swipe_action/read.tgs new file mode 100644 index 0000000000000000000000000000000000000000..59b258677c082b49dd013be8624c0000c5c7a25f GIT binary patch literal 1860 zcmV-K2fO$miwFp_wn1b719Nw2aAjX|WnpA4YIARH0PR`HZW~7s{S{%(J&oQM-fYM5 zC5Iphav^x2CCVbSP$20ff}wxUtLh$dh8iuFEhi2Fi=3J2n%esH>uUN_^G7pjy!0|Q zqPbjb=gs6(^8vD-R@?1z@#FGhu{nD6_DD%Bje-so8eGoH<)mD;$8^0F&FQ+C1SOi~ zbu+g~fd_$?M=xfgJBV?_}&R@9E2zEUf>qZnt zt_LGit+RAGiB_8|vvWetin6)of;>r=JZ=tj5l;P7rEp6YSFEu)n_n+V2`J^}!y0)m zw=CdVs8S0kHq}L!^}O5{RT5xONfhm-#If4ROk^P?y)9n5m!{L!da1Ri45muZld%c+ z196qk*ywb0Ox$A$@BBgU>`RudjE-K=$?hshkDW#cQacTa_cGbA*MTiyaJ&AvxSidK ze%998NAnKDyj_ynn=V?Hr8XA#196phd5?{Wdo1nq)-oz5T7w&9DJ`QAu+5a0kt#*b zy=qyD+zlyNsY2T89OjOM^g%{O>ZrRg=z)sd7ZzEU&D{|(YNN{}XXzD1qzvlKGp4L` zlt@mJC#+M+PP!0C0M?1IQyApXTV1@$f1Yp8jx-U}6`o%G@cQl1?~CK@YJK!8t&yYl z=-qnt@fr$eSQe-Ai_L=TK#Sw_qG8j6btm{=b>li<+@%R$SORP5{Ur}_I3UG~@o?U) z=htV;V+2Gxqw#EM6(8`6dWcZe6Bwi_*!xH=+@E43qvvBUQC&9ku@T=*%x~-Y)#h}y zzHDgDSj02I)w#N6IzHySb``8VHB!368JrEa5uJ#f3P-Uis_0;AFvG3k_3GrNdB$#V zhd8HT&Ka}CRL^=OG9?zN18O!PP&MG7&oSVNfmR<{h)=bks|ov53--W(F@qRLl6Ps% zMs~?B*=mRugfmJ8!!+4!R|WIsVYz!4lKSKJ-Oj#&105c405Wsfo2tgpQG9&!(6+b& zCQ%iyVJC#o z6op6EQ+i_9-Ve6bLf3e8(Q1ppC?p3u2_nl7=qX^$dl9ALmP#9G1RCPZO`%NL_hLcg z2Gc!9G6IQ%TDTxMxH9ahJ2TQ-*R#>~jC9Q&I&Pfl(0wKuJynqeZqTn=)HR?x&j$6Y z?Yctb)W3(6AppB1YUt4t8yovAz6H{J;PjGI;8c?2P!dieYBG(7gwg~jaIAoq;n_n| z3e@%`C>$cwI&~6F9XZ-q9jUUKMIlM!@LseiFSoi(fB`T_p?ho-9bt+M1V*k)30!*M z@R4kxb-sJ@0c3z#i{Ri3RSB*@7E?r+HKB$t6}BJ}m|UWTK;XE}W%`G38)U>04s)6_ zpXU?~IE>?H3vwOV4jeHeOo{eLqy01Rn?4i2Ev+90aFkhvQd5Of8Ut8mUJqJQNC_GY z0UWu=ed_=bO%4L4g)~roSJ29+^MWabQ$%cm=fx-g9|Nxr6}@y*76gwa}MDmd7i zX$&>VOuM-j+uX|Z zswxY7b0Ekk6yR!0wMCrP(4z}|489bOJt!fXGLd+RK#83^RBBE(7v8nBvQD(e{YKMjYrJZ(p2Cu{B1|r!}4zIGoD% z8iMFSy{>&L6F3kOedq)nB^?baqk7Gx-|h1nTff%@ap=964N{GtBsLeEmNtwfbhb#C ymSn#d7XAO1*zfn3*f*=o_sgrrNy}674StZt_~m?kUjE;1cKbK-1Rv*I8~^~o5r@YB literal 0 HcmV?d00001 diff --git a/Telegram/Resources/animations/swipe_action/unarchive.tgs b/Telegram/Resources/animations/swipe_action/unarchive.tgs new file mode 100644 index 0000000000000000000000000000000000000000..f8a4f2108fd675f5d45cde343f1664cc72e38011 GIT binary patch literal 1191 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 R=ZlvQ{{wYhAM#^4006v}`rH5j literal 0 HcmV?d00001 diff --git a/Telegram/Resources/animations/swipe_action/unread.tgs b/Telegram/Resources/animations/swipe_action/unread.tgs new file mode 100644 index 0000000000000000000000000000000000000000..97ce96a05f58bca90c77b71064a6148bf00279bc GIT binary patch literal 2084 zcmV+<2;27`iwFp_wn1b719Nw2aAjY0ZgOQ|WG-rRZ*BnXT1#)+I1v6TfzC3);hVX& z-N$7Q3+&?(_~0f^V>F2a+xsYr{P+E4NZFDjcayXZ5bUCGBn?Nyd3+qsQ2pHe*_<|B zc@>+sxtVWf&FSan186@jH=D)$hsE`Lee&k}6Rk)Y4IVHwxO^;^i*nhV^Yy-ME?3QI z&~3B0Yff=l;$lPF{MDR#GHr8JueUeg|Lt})pIxw!iwohNt=IF-x;Z_Yw$1hI(|pDE zpSQz{TU-f~eQHi!mGN$|I=`Mn#@%c+zuh#a5WZds+s8GVvgAKAc^@j1W;uW3hM??f zFxHJ|jNA=I&WN&dl-dcItg>^ho)%_vFAjMWFVDE%$XS$V# zh}%A~(552qY-FSzl>z=gh2I4QCxIM|a)D*Lth9@ugsi-^Lh6`8P(gbkS!IBtEf)j= zf1A}G^ZV(2+qXFWo5gu(u`?HjvG&$T4$d%ezJvP=JkhHbj5TF4&4QZtVzd#wb z1lVMaqQr!b$2(;*d&fCtt=+PGh1C>?W&^3#Y?Z~6GaS4Dxl%i`$Hv+NlD1}3Kn@{T zkc{$9Vu=u%oXcu4ftb{BMXz#XR|Km_+a1qWSZ>_VavN3FuG7~hr7gR9K(5rz^0Be@ zfTUf(HG&Dq!Z2l`VKWl~9&0$A7E;FrgS};nH_8(2c=j!aMRsq|TCa$<5x|qN?85=M zQnwb3jI{?O?PA%bxolN*g4krYSx@3vIk0faab&$$$%Y-zz?xo0mCXM0Y;$!&yeZw{ z>CJajq4!t zaBJ{oXF&dZegMWT2o3{e|nILz!x9+ zKGg+0vCo!}iUcIp=ZZkiE=tgIC0MF{s7f%&Z(TDTDXzYvLP-u=twUj8WT9-9WzCd_ z#rENen?u|QH&KOeE1Y~!_4Fv!IWA_z;C`;$OB`HFwG?;q_jAZ7(%bs$LM@4MFWh@P zotC|z^sCu@5ViI9%o$=ggM;*Nj2XJ{umSlfGjyRO)Hda}i*g$A;7fD_$ySW=-508+ zL5ZPjNuZ^^&njY_Pc*6n-s2|>Jya}7$(BFiibl!;)O2zC8dtsij<`Amo&N3PArBn@IcFo>LGh&?WC|pWgRA9wsU@wxgfnP}I zFanmC2saWdl@!8e2!o^6%6mN{|pSXu1HW`Sxq9=qg6yx^#iCW$pyuh7+VGZe}S=T;` z4I#Y%mJ_2y+7+z?PaZ3aAE|b^fF=b_2Uv$%%+5h2&#!0$FG)*C#Jx^C$-Hz6j=A** zI5O6Ocz`83J{8DGrF0Y=n};~g-xSAVway5F-C+bHmpRu;#;pj}oO&51rabd709FDC zK3IpOTQW0y&@nd1?BaT)B#d1EPJyQ-7XWa{0I^n%0I*YJ(<0VnMR-WL1=vI>VmGsn zI==*d0{~>|VMLJ33re;H&_+@lpF&w)(;9jwc5{LUIZ0yM(OBz6OwFRn{PkeSzP2O>Cc3Do-V0JWCz*-1K zB@=*U)5~ke!fs0z+Ob~j*U-Z8l3bCwA{P(Zl?0?1#gvWAoiZ04=ux0e-vG3nGLe)3N-yCy za!u4|HHR3Z*L$ykuIgYg$H2X)!&wlUdI6jl2TXMie{~=T)g(iN9)aPljOlu9Hh# zQh<_tI0jgcR2@A09`RoSp??_=BFPQT3z*;rpI(3)Km{4oz<>42i{?WHu3i%d8ntQS zGX@9j**NWet+AQA%jv5^lo|cesMd$m`G^8-RC5I=yMXrZ)U5H<$sz? O@Baa../../animations/star_reaction/effect1.tgs ../../animations/star_reaction/effect2.tgs ../../animations/star_reaction/effect3.tgs + + ../../animations/swipe_action/archive.tgs + ../../animations/swipe_action/unarchive.tgs + ../../animations/swipe_action/delete.tgs + ../../animations/swipe_action/disabled.tgs + ../../animations/swipe_action/mute.tgs + ../../animations/swipe_action/unmute.tgs + ../../animations/swipe_action/pin.tgs + ../../animations/swipe_action/unpin.tgs + ../../animations/swipe_action/read.tgs + ../../animations/swipe_action/unread.tgs diff --git a/Telegram/SourceFiles/dialogs/dialogs.style b/Telegram/SourceFiles/dialogs/dialogs.style index 4027da23ee..2d4d01fda5 100644 --- a/Telegram/SourceFiles/dialogs/dialogs.style +++ b/Telegram/SourceFiles/dialogs/dialogs.style @@ -789,3 +789,5 @@ dialogsPopularAppsPadding: margins(10px, 8px, 10px, 12px); dialogsPopularAppsAbout: FlatLabel(boxDividerLabel) { minWidth: 128px; } + +dialogsSwipeActionSize: 20px; diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp index 5836207a1f..9b1492e9a2 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.cpp @@ -54,6 +54,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/unixtime.h" #include "base/options.h" #include "lang/lang_keys.h" +#include "lottie/lottie_icon.h" #include "mainwindow.h" #include "mainwidget.h" #include "storage/storage_account.h" @@ -808,6 +809,7 @@ void InnerWidget::paintEvent(QPaintEvent *e) { const auto ms = crl::now(); const auto childListShown = _childListShown.current(); auto context = Ui::PaintContext{ + .swipeContext = _swipeContext, .st = _st, .topicJumpCache = _topicJumpCache.get(), .folder = _openedFolder, @@ -4992,4 +4994,74 @@ rpl::producer InnerWidget::openBotMainAppRequests() const { return _openBotMainAppRequests.events(); } +void InnerWidget::setSwipeContextData(Ui::Controls::SwipeContextData data) { + _swipeContext.data = std::move(data); + if (_swipeContext.data.msgBareId) { + constexpr auto kStartAnimateThreshold = 0.32; + constexpr auto kResetAnimateThreshold = 0.24; + if (_swipeContext.data.ratio > kStartAnimateThreshold) { + if (_swipeContext.icon + && !_swipeContext.icon->frameIndex() + && !_swipeContext.icon->animating()) { + _swipeContext.icon->animate( + [=] { update(); }, + 0, + _swipeContext.icon->framesCount()); + } + } else if (_swipeContext.data.ratio < kResetAnimateThreshold) { + if (_swipeContext.icon && _swipeContext.icon->frameIndex()) { + _swipeContext.icon->jumpTo(0, [=] { update(); }); + } + } + update(); + } +} + +int64 InnerWidget::calcSwipeKey(int top) { + top -= dialogsOffset(); + for (auto it = _shownList->begin(); it != _shownList->end(); ++it) { + const auto row = it->get(); + const auto from = row->top(); + const auto to = from + row->height(); + if (top >= from && top < to) { + if (const auto peer = row->key().peer()) { + return peer->id.value; + } + return 0; + } + } + return 0; +} + +void InnerWidget::prepareSwipeAction( + int64 key, + Dialogs::Ui::SwipeDialogAction action) { + if (key) { + auto name = (action == Dialogs::Ui::SwipeDialogAction::Mute) + ? u"swipe_mute"_q + : (action == Dialogs::Ui::SwipeDialogAction::Pin) + ? u"swipe_pin"_q + : (action == Dialogs::Ui::SwipeDialogAction::Read) + ? u"swipe_read"_q + : (action == Dialogs::Ui::SwipeDialogAction::Archive) + ? u"swipe_archive"_q + : (action == Dialogs::Ui::SwipeDialogAction::Delete) + ? u"swipe_delete"_q + : u"swipe_disabled"_q; + _swipeLottieIcon = Lottie::MakeIcon({ + .name = std::move(name), + .sizeOverride = Size(st::dialogsSwipeActionSize), + }); + _swipeContext.icon = _swipeLottieIcon.get(); + _swipeContext.action = action; + } else { + if (_swipeContext.icon) { + _swipeContext = {}; + } + if (_swipeLottieIcon) { + _swipeLottieIcon.reset(); + } + } +} + } // namespace Dialogs diff --git a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h index 2500f43d1f..846feac821 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h +++ b/Telegram/SourceFiles/dialogs/dialogs_inner_widget.h @@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "base/object_ptr.h" #include "base/timer.h" #include "dialogs/dialogs_key.h" +#include "dialogs/ui/dialogs_swipe_context.h" #include "data/data_messages.h" #include "ui/dragging_scroll_manager.h" #include "ui/effects/animations.h" @@ -25,6 +26,10 @@ namespace MTP { class Error; } // namespace MTP +namespace Lottie { +class Icon; +} // namespace Lottie + namespace Main { class Session; } // namespace Main @@ -34,6 +39,9 @@ class IconButton; class PopupMenu; class FlatLabel; struct ScrollToRequest; +namespace Controls { +enum class SwipeDialogAction; +} // namespace Controls } // namespace Ui namespace Window { @@ -208,6 +216,10 @@ public: [[nodiscard]] rpl::producer openBotMainAppRequests() const; + void setSwipeContextData(Ui::Controls::SwipeContextData data); + [[nodiscard]] int64 calcSwipeKey(int top); + void prepareSwipeAction(int64 key, Dialogs::Ui::SwipeDialogAction); + protected: void visibleTopBottomUpdated( int visibleTop, @@ -611,6 +623,9 @@ private: rpl::event_stream<> _refreshHashtagsRequests; rpl::event_stream _openBotMainAppRequests; + Dialogs::Ui::SwipeContext _swipeContext; + std::unique_ptr _swipeLottieIcon = nullptr; + RowDescriptor _chatPreviewRow; bool _chatPreviewScheduled = false; std::optional _chatPreviewTouchGlobal; diff --git a/Telegram/SourceFiles/dialogs/dialogs_swipe_action.cpp b/Telegram/SourceFiles/dialogs/dialogs_swipe_action.cpp new file mode 100644 index 0000000000..90ed1fc032 --- /dev/null +++ b/Telegram/SourceFiles/dialogs/dialogs_swipe_action.cpp @@ -0,0 +1,29 @@ +/* +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 "dialogs/dialogs_swipe_action.h" + +#include "dialogs/ui/dialogs_swipe_context.h" +#include "data/data_peer.h" +#include "data/data_session.h" +#include "history/history.h" +#include "main/main_session.h" +#include "menu/menu_mute.h" + +namespace Dialogs { + +void PerformSwipeDialogAction( + not_null peer, + Ui::SwipeDialogAction action) { + if (action == Dialogs::Ui::SwipeDialogAction::Mute) { + const auto history = peer->owner().history(peer); + MuteMenu::ThreadDescriptor(history).updateMutePeriod( + std::numeric_limits::max()); + } +} + +} // namespace Dialogs diff --git a/Telegram/SourceFiles/dialogs/dialogs_swipe_action.h b/Telegram/SourceFiles/dialogs/dialogs_swipe_action.h new file mode 100644 index 0000000000..9dca99277c --- /dev/null +++ b/Telegram/SourceFiles/dialogs/dialogs_swipe_action.h @@ -0,0 +1,22 @@ +/* +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 PeerData; + +namespace Dialogs::Ui { +enum class SwipeDialogAction; +} // namespace Dialogs::Ui + +namespace Dialogs { + +void PerformSwipeDialogAction( + not_null peer, + Ui::SwipeDialogAction action); + +} // namespace Dialogs diff --git a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp index 83ab9665e9..b00963bc91 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_widget.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_widget.cpp @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "dialogs/dialogs_widget.h" +#include "base/call_delayed.h" #include "base/qt/qt_key_modifiers.h" #include "base/options.h" #include "dialogs/ui/chat_search_in.h" @@ -15,6 +16,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "dialogs/ui/dialogs_suggestions.h" #include "dialogs/dialogs_inner_widget.h" #include "dialogs/dialogs_search_from_controllers.h" +#include "dialogs/dialogs_swipe_action.h" #include "dialogs/dialogs_key.h" #include "history/history.h" #include "history/history_item.h" @@ -688,32 +690,64 @@ void Widget::setupSwipeBack() { Ui::Controls::SetupSwipeHandler(_inner, _scroll.data(), [=]( Ui::Controls::SwipeContextData data) { if (data.translation != 0) { - if (!_swipeBackData.callback) { - _swipeBackData = Ui::Controls::SetupSwipeBack( - this, - []() -> std::pair { - return { - st::historyForwardChooseBg->c, - st::historyForwardChooseFg->c, - }; - }, - _swipeBackMirrored, - _swipeBackIconMirrored); + if (data.translation < 0) { + if (_inner) { + _inner->setSwipeContextData(std::move(data)); + } + } else { + if (!_swipeBackData.callback) { + _swipeBackData = Ui::Controls::SetupSwipeBack( + this, + []() -> std::pair { + return { + st::historyForwardChooseBg->c, + st::historyForwardChooseFg->c, + }; + }, + _swipeBackMirrored, + _swipeBackIconMirrored); + } + _swipeBackData.callback(data); } - _swipeBackData.callback(data); return; } else { if (_swipeBackData.lifetime) { _swipeBackData = {}; } + if (_inner) { + _inner->setSwipeContextData({}); + _inner->update(); + } } - }, [=](int, Qt::LayoutDirection direction) { + }, [=](int top, Qt::LayoutDirection direction) { _swipeBackIconMirrored = false; _swipeBackMirrored = false; if (_childListShown.current()) { return Ui::Controls::SwipeHandlerFinishData(); } const auto isRightToLeft = direction == Qt::RightToLeft; + if (!isRightToLeft && _inner) { + if (const auto key = _inner->calcSwipeKey(top)) { + const auto action = Dialogs::Ui::SwipeDialogAction::Mute; + _inner->prepareSwipeAction(key, action); + return Ui::Controls::SwipeHandlerFinishData{ + .callback = [=, session = &session()] { + auto callback = [=, peerId = PeerId(key)] { + const auto peer = session->data().peer(peerId); + PerformSwipeDialogAction(peer, action); + }; + base::call_delayed( + st::slideWrapDuration, + session, + std::move(callback)); + }, + .msgBareId = key, + .speedRatio = 1., + .reachRatioDuration = crl::time(st::slideWrapDuration), + .provideReachOutRatio = true, + }; + } + } if (controller()->openedFolder().current()) { if (!isRightToLeft) { return Ui::Controls::SwipeHandlerFinishData(); diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp index 39a8e3826c..ebde34c6a5 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.cpp @@ -28,12 +28,15 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "history/history_unread_things.h" #include "history/view/history_view_item_preview.h" #include "history/view/history_view_send_action.h" +#include "lang/lang_instance.h" #include "lang/lang_keys.h" +#include "lottie/lottie_icon.h" #include "main/main_session.h" #include "storage/localstorage.h" #include "support/support_helper.h" #include "ui/empty_userpic.h" #include "ui/painter.h" +#include "ui/rect.h" #include "ui/power_saving.h" #include "ui/text/format_values.h" #include "ui/text/text_options.h" @@ -66,6 +69,54 @@ const auto kPsaBadgePrefix = "cloud_lng_badge_psa_"; return !history->isForum(); } +[[nodiscard]] QString SwipeActionText(Dialogs::Ui::SwipeDialogAction type) { + return (type == Dialogs::Ui::SwipeDialogAction::Archive) + ? tr::lng_settings_swipe_archive(tr::now) + : (type == Dialogs::Ui::SwipeDialogAction::Delete) + ? tr::lng_settings_swipe_delete(tr::now) + : (type == Dialogs::Ui::SwipeDialogAction::Read) + ? tr::lng_settings_swipe_read(tr::now) + : (type == Dialogs::Ui::SwipeDialogAction::Pin) + ? tr::lng_settings_swipe_pin(tr::now) + : tr::lng_settings_swipe_mute(tr::now); +} + +const style::font &SwipeActionFont( + Dialogs::Ui::SwipeDialogAction action, + int availableWidth) { + struct Entry final { + Dialogs::Ui::SwipeDialogAction action; + QString langId; + style::font font; + }; + static auto Fonts = std::vector(); + for (auto &entry : Fonts) { + if (entry.action == action) { + if (entry.langId == Lang::GetInstance().id()) { + return entry.font; + } + } + } + constexpr auto kNormalFontSize = 13; + constexpr auto kMinFontSize = 5; + for (auto i = kNormalFontSize; i >= kMinFontSize; --i) { + auto font = style::font( + style::ConvertScale(i, style::Scale()), + st::semiboldFont->flags(), + st::semiboldFont->family()); + if (font->width(SwipeActionText(action)) <= availableWidth + || i == kMinFontSize) { + Fonts.emplace_back(Entry{ + .action = action, + .langId = Lang::GetInstance().id(), + .font = std::move(font), + }); + return Fonts.back().font; + } + } + Unexpected("SwipeActionFont: can't find font."); +} + void PaintRowTopRight( QPainter &p, const QString &text, @@ -344,11 +395,25 @@ void PaintRow( draft = nullptr; } + const auto history = entry->asHistory(); + const auto thread = entry->asThread(); + const auto sublist = entry->asSublist(); + auto bg = context.active ? st::dialogsBgActive : context.selected ? st::dialogsBgOver : context.currentBg; + auto swipeTranslation = 0; + if (history + && history->peer->id.value == context.swipeContext.data.msgBareId) { + if (context.swipeContext.data.translation != 0) { + swipeTranslation = context.swipeContext.data.translation * -2; + } + } + if (swipeTranslation) { + p.translate(-swipeTranslation, 0); + } p.fillRect(geometry, bg); if (!(flags & Flag::TopicJumpRipple)) { auto ripple = context.active @@ -357,10 +422,6 @@ void PaintRow( row->paintRipple(p, 0, 0, context.width, &ripple->c); } - const auto history = entry->asHistory(); - const auto thread = entry->asThread(); - const auto sublist = entry->asSublist(); - if (flags & Flag::SavedMessages) { EmptyUserpic::PaintSavedMessages( p, @@ -821,6 +882,54 @@ void PaintRow( + (tag->width() / style::DevicePixelRatio()); } } + if (swipeTranslation) { + p.translate(swipeTranslation, 0); + const auto swipeActionRect = QRect( + geometry.x() + geometry.width() - swipeTranslation, + geometry.y(), + swipeTranslation, + geometry.height()); + p.setClipRegion(swipeActionRect); + p.fillRect(swipeActionRect, st::attentionButtonFg); + if (context.swipeContext.data.reachRatio) { + p.setPen(Qt::NoPen); + p.setBrush(st::windowBgActive); + const auto r = swipeTranslation + * context.swipeContext.data.reachRatio; + const auto offset = st::dialogsSwipeActionSize + + st::dialogsSwipeActionSize / 2.; + p.drawEllipse(QPointF(geometry.width() - offset, offset), r, r); + } + const auto iconOffset = (geometry.height() + - st::dialogsSwipeActionSize) / 2; + const auto topTranslation = iconOffset / 2.; + p.translate(0, -topTranslation); + if (context.swipeContext.icon) { + context.swipeContext.icon->paint( + p, + rect::right(geometry) + - iconOffset + - st::dialogsSwipeActionSize, + iconOffset, + st::premiumButtonFg->c); + } + { + p.setPen(st::premiumButtonFg); + p.setBrush(Qt::NoBrush); + const auto left = rect::right(geometry) + - iconOffset * 2 + - st::dialogsSwipeActionSize; + const auto availableWidth = geometry.width() - left; + p.setFont( + SwipeActionFont(context.swipeContext.action, availableWidth)); + p.drawText( + QRect(left, 0, availableWidth, geometry.height()), + SwipeActionText(context.swipeContext.action), + style::al_bottom); + } + p.translate(0, topTranslation); + p.setClipRegion(QRegion()); + } } } // namespace diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.h b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.h index e014e657f5..9b905eac82 100644 --- a/Telegram/SourceFiles/dialogs/ui/dialogs_layout.h +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_layout.h @@ -7,6 +7,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #pragma once +#include "dialogs/ui/dialogs_swipe_context.h" #include "ui/cached_round_corners.h" namespace style { @@ -18,9 +19,6 @@ namespace st { extern const style::DialogRow &defaultDialogRow; } // namespace st -namespace Ui { -} // namespace Ui - namespace Data { class Forum; class Folder; @@ -57,6 +55,7 @@ struct TopicJumpCache { struct PaintContext { RightButton *rightButton = nullptr; std::vector *chatsFilterTags = nullptr; + SwipeContext swipeContext; not_null st; TopicJumpCache *topicJumpCache = nullptr; Data::Folder *folder = nullptr; diff --git a/Telegram/SourceFiles/dialogs/ui/dialogs_swipe_context.h b/Telegram/SourceFiles/dialogs/ui/dialogs_swipe_context.h new file mode 100644 index 0000000000..bbfc81d018 --- /dev/null +++ b/Telegram/SourceFiles/dialogs/ui/dialogs_swipe_context.h @@ -0,0 +1,35 @@ +/* +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 "ui/controls/swipe_handler_data.h" + +namespace Lottie { +class Icon; +} // namespace Lottie + +namespace Dialogs::Ui { + +using namespace ::Ui; + +enum class SwipeDialogAction { + Mute, + Pin, + Read, + Archive, + Delete, + Disabled, +}; + +struct SwipeContext { + ::Ui::Controls::SwipeContextData data; + Lottie::Icon *icon = nullptr; + SwipeDialogAction action; +}; + +} // namespace Dialogs::Ui diff --git a/Telegram/cmake/td_ui.cmake b/Telegram/cmake/td_ui.cmake index 321fcbdbc9..1e66b314a3 100644 --- a/Telegram/cmake/td_ui.cmake +++ b/Telegram/cmake/td_ui.cmake @@ -103,6 +103,7 @@ PRIVATE dialogs/ui/chat_search_in.h dialogs/ui/dialogs_stories_list.cpp dialogs/ui/dialogs_stories_list.h + dialogs/ui/dialogs_swipe_context.h dialogs/ui/top_peers_strip.cpp dialogs/ui/top_peers_strip.h