From 1988435cdf7b260b136510ba2ac8ff433402b536 Mon Sep 17 00:00:00 2001 From: John Preston Date: Tue, 25 Jun 2024 18:00:28 +0400 Subject: [PATCH] Add a Windows Hello / Touch ID system unlock. --- .../Resources/icons/menu/passcode_finger.png | Bin 0 -> 911 bytes .../icons/menu/passcode_finger@2x.png | Bin 0 -> 1867 bytes .../icons/menu/passcode_finger@3x.png | Bin 0 -> 2736 bytes .../icons/menu/passcode_winhello.png | Bin 0 -> 454 bytes .../icons/menu/passcode_winhello@2x.png | Bin 0 -> 772 bytes .../icons/menu/passcode_winhello@3x.png | Bin 0 -> 1135 bytes Telegram/Resources/langs/lang.strings | 8 ++ Telegram/SourceFiles/boxes/boxes.style | 22 ++++ Telegram/SourceFiles/core/core_settings.cpp | 10 +- Telegram/SourceFiles/core/core_settings.h | 8 ++ .../settings/settings_local_passcode.cpp | 49 +++++++- .../settings/settings_privacy_security.cpp | 3 + Telegram/SourceFiles/ui/menu_icons.style | 2 + .../window/window_lock_widgets.cpp | 110 ++++++++++++++++++ .../SourceFiles/window/window_lock_widgets.h | 15 +++ Telegram/lib_base | 2 +- cmake | 2 +- 17 files changed, 225 insertions(+), 6 deletions(-) create mode 100644 Telegram/Resources/icons/menu/passcode_finger.png create mode 100644 Telegram/Resources/icons/menu/passcode_finger@2x.png create mode 100644 Telegram/Resources/icons/menu/passcode_finger@3x.png create mode 100644 Telegram/Resources/icons/menu/passcode_winhello.png create mode 100644 Telegram/Resources/icons/menu/passcode_winhello@2x.png create mode 100644 Telegram/Resources/icons/menu/passcode_winhello@3x.png diff --git a/Telegram/Resources/icons/menu/passcode_finger.png b/Telegram/Resources/icons/menu/passcode_finger.png new file mode 100644 index 0000000000000000000000000000000000000000..ee267f708913533de52430b6ad43beb170d9e187 GIT binary patch literal 911 zcmV;A191F_P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR917@z|H1ONa40RR917ytkO0OB=utpET5`AI}UR5%gclv^mfaTv$Vq&X!` zOeV)-Noj=~;zCYI4wEP)D}`ujh2(G{H?+Hz(k_TxaX}=dxUivx8o3!cmdFxj4w3(- zUjNnqwST+!Uc7tu9KOHr?|Ht@>*MolABo4C$>s8vmX^G{yriV0*x1;or>Co{tM&Eu z`T2Q^#p1C<3=|w3JT^Ag)YN3R+vn!yPEJnF&(CotBqWrSl$4c~ZEkMrbh^XCLyvIZ zPO=XU4t95U3knJZS9o}MT3T9MT%1%Y#S;?~Gc`5!{QO*BU;kgAsHmvh+uPaM*?@om zl4@#d0R8&=+}+(742GbfAVST}&2MjS6%`epv6h#YS65ewg@lCAi^s>u-rnBK%*?>R zz{JGFy1Kf(y}i@Z)7;!#aymOZNl+*hVyx=w>ihfq=;&wylarI&j$2@JBTxj6*drq& zH#avC5fOwoHa1KqlNcyHJv}=+8*f!r6*Hn(B9U}=cVlz8kB^U;nVGP#FcKiXu&{tp zSXk(EI^iqE68^8PtuZz1uC6W)FE1~L4*fQp%_}P__)}9;frc*x9S#R`^bEuWH5v`E zv$M0t#zqXaTFpB$GV=5DGdVdKrVkGfm6eq^x3{<3+uJdCe1#wPoAc40pPwH(WNI*{ zUrMDCc1K4?Sy@@o86O|NzP_e}+4=kXyKDb3j*pKSJT7P#7Z(c#Qp7MCjfmUV_xo&> zO7-&cl97=i)QcHiTwKJ*#}k7{ettd%t<`F^7(+ut(A?SC>FMbi9UWy?CMG7VR;vIc ze)sqHZ*6ViZEbBuH84*}NpZPc=m;mfLc-G0()9GSKwMn!{!cp?HlvZrWU%Y&>mx+h zUteDb2M0q#L*1F)4R)0?$tx`_rJcgbMMXt6n+@S`wZ+9n)Cf~ASga`W@95|tkB`002ovPDHLkV1j4EmVE#K literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/menu/passcode_finger@2x.png b/Telegram/Resources/icons/menu/passcode_finger@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a0a34240bfb0ebe7578aab0d18206289a7a2e7c2 GIT binary patch literal 1867 zcmV-R2ekN!P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91FrWhf1ONa40RR91FaQ7m0NXcg3;+NIwMj%lR9Fe^mwQaleH6#L2$fta z6muUFH4&zjP!m&_F>~9RVcMuzYt}HcW%x%fV{@4`mOC3|Z8l*ubA0yeQQx0u?fIwgAK%~ky}#$2&-tGF*TJFV>hM5^2in&Ij(?zj^ytx(Cr_R* zVZxX(W4yh+Jv}`;ckcY^)vK33ud=eTtgNh@oSd&;zy5)8J485p!-fs_?%n%g;i|2z zJ#*&F)TvYLIN&F%B@gxJ(IYW2aoxIg9v&WYz_)MTN=r-g^75WPfBx>>yQZe5zJ2@p z`1the*Kg9KN%&0dxOVN@=FOXL-n^;EegsAS ztE8mFE^*s~TwGjEpFSNnirKSgljbem(6wvV{rmTe zo{t|tPMH-4;%}17KGC&SEdGaK#Qkm}EyYJYsqoJX}GyxMPf*n{F)_o350@}eS+u3~>(^hueqD{r z%*^cBv!`l^ii#4`Z{NOc+NuoyLg4BrPoALh@#Dv4^@fFokpbY?dgREF)?bmzSF;{I zd`O7(B+^{WUA}y|f~^r7H*OSx$jC_L8!=+U+qZAQKYaKwZ{9q`TOr88ty{N>r|;ak zSwJfnU zYt|shg;P~9I5=1g<>eLpEpg+<4V-L7Bq1R|lv3WN7-ONRs7M~koy0nL@SvGA@bBBV zkEd8LZrnH(&&bFCL|hT81S!R2K$!GY89LtK!-vHPxyu_1O)O^3nx)LRO&UEDS3$af zFx%ZK=gyrgl2nkYOHWT1@c#Y#^XJbWFkk>C;((Nt6r98(?les0kB^TBq`nx>0+KzA zjg5etHf>TiOT@8b#}H$VDmQNr!i8C8ixLKZe}CpYPq9^7235u|2Be{@o~u`{f}A~j zRuM}?VPPR+yLazaZafe2=+Ps0cXtI%f&_j(W6H}Zr!@2h!9RT z|84&E@82J!qM|}@idI&fbLY-cbONqixpLL2RVv6!fBN)^zto+AqCvC?NI658h~RA) zNAgkxDy@BZ`f@87+9_YN5{1cGpzc-yp; zJ)aQD$`GJBSlJZOHp4=#pbib<$ZV0!Bi6L5?CfkbaGgJYUiqyONl8ga^16KJhz#0) zYWtzBlBMAD=g)v7E2pUS4i4QnY@ZxK^!!Z~XZ2a=bPb!cTev?%cUk6&*Nm z0EB$E*-*)A=|G}H?quPTB}-J+K7u@8_d^kdt&+!&9|z%eHAW-~BN>nk3kV2MP6#xx zD-u=)3;v!tbEbsPP)WoDUHaw=bEa8j6@YTp@laZ_T=&CQ&& zefxG56f21l(^o+XO$He_8&zm%s6MhzI9g#PM$48hV?NVYr2CP``T6!7;B3m|JsOqPN@&5h$@bGZOAux+Io)v|*DRvV_Ql72DChJWpJ80&j zEazmdImTJgqzPdeedu?s1#!Bf9p_nL9X4zjV;?_}xnswURS}kU{eWj?B_}8M>eWl1 zwlBfgnfQa|rURcNu^=riO%sKtKx!{qw5WZp5$$}}5;YP+rlWZzt?0sq3p`TG7A{<9 zGPD=XUSWRI*c^kQbmZLJT*7BY)`qR)Z-)muJn(;c;4j0;<#Z1Y5DEYQ002ovPDHLk FV1i&-h&uoP literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/menu/passcode_finger@3x.png b/Telegram/Resources/icons/menu/passcode_finger@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..291fc8eaff15153de56f6f98e6dc240e1e9f888b GIT binary patch literal 2736 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 Xol7k?b$Rq!5EO=u{ z=}kM;&l4$Ndf#~Nu9tTT_q{h-{qj!hx$1k*E6-KW`#rDt?wt?q)(2!C@D;G{V7|ln z?!a{BqMbH#{rZnTzL_)a^wW3m-{0JqVIp;afsNJW!p(}4ksWpOY^Hj(>M|bS{3Bdq z7FSeeG;@w#!^XJv_RE_@SlRx{%$W7x`RH?}sa~#2j~FvKtPSH%HcDvFeDc37qvNtK zKO3`|a6_=oi<~`AbY_KQaO3^9=E?MSnc zn|_9UVT6uQ-S*piKfUhw@BFlA=8DkOSG`v;KL7S@+vS%6Q>RZCpMAD$=7fU@8C#=V z(k*1Nw%$5jvM<7FF5gmtwQtL$yN@o(Vr6RFzTJG$hhM*b{rI5~+IZ~o-RoJVi#pM7FM5fHE(-i!`d+IccNbW`Wix= zQ@m7*7I3J}KY#!3-M|ys&b#l%t-szn>qNrln>P0L=Cgg5T=;$Y6gA`6MbbAj}e$&&%F(iZa z?abTSHGv|>C8rm5dg$?Y1-*MbZ_*@{dM5rwfn6g181yGsOcb9~A@($MPrxLVnIE-3 zI(Zy9EwEGd$ottV@0OiAWA}T`=E{V*?Jwu-z5Z*>*8S=C&&}Ilu*-uns6j-56)W|x zhbb~L(%9HoU0ppqJpAKCwKdBP}ic^(Kqgv17-c z96n$n!VVOa@@{_?`S0S>qE;iZke9J6$C|Wk-Gh_%CO&`uTuQ9k#@aghdz(2^vLlD{ zn$qT;o}S~!k1yD}V(Zq>dEAc|2pkY}nz#7UruFOn=L@IhZZ>?d=s82)w8fY9?cMwL z*DtFHVrttze*Cy&hs9>b2Tbl}=1d%GB0H+8+YbkZgoFeKColA@F)Lta(O~#lv`ZZp z8vo`o2^#sHJAXbuGjr$u{l~@E_53xzDIy|bVs5VOt*o!Fzv1RlpxjGy)!YtUP0h-x zszdj9_j{bYaPP)~-MeSM4cNYYyRx!!Z*53)!sM+RHy*t7;?=7l0Y!83?_a-8b+nc1 zXIkOuQeSWH%}||cn$Kei^w)=&oKRo2w9_`~>h1qO7?-|F5V-NOo3_Qq#H6IB zOaIVV<>%#f>;C=ph5h~gj~_o4-Dq!k^yty^=g;dLc=#|eDr(j#hJz6oFJ4@|dbQ4r z-@mJCYikXht5g5zG$mBD&zw2)+XSWjnt8f9Ivc_srd3o#JV{udS5PpazofDRI;l@AXmSI(S0 zdvnc^nKNc|2-lS99XWCN@?}B6px<_m+n%j@_3G7!^BkuY3Ya&BhlO2uGi8d1q|7~g zwOuP$uADtvn)lVihYOc4cV`p2a_m}x3%{h4)FH+Nbv+MRtM=ZjpMU+}LB>zVT3MN2 z2Ne|=`8jE8X=!O|Z@jjA`SRDs(ed%`U%Y52__b=j_Q4|^i3={?{-hk{A){6Io+ZO; z_NGmne*UaHd%*bWp1phbZriqPzFgp>UKju3-FLmcz5kfG-mxhO`I7!7N5$D=)=jD8 zCW*knK#R*q9klfIk9Qo};WRrrDJd^MpZPIw?78Qk-@bYC<8K{f`zkDX>&IHIKkPOW Wc0?^!*|!ap**#tTT-G@yGywnyul6Va literal 0 HcmV?d00001 diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index 80441cd03..01a1e7cf5 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -683,6 +683,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_settings_privacy_premium_link" = "Telegram Premium"; "lng_settings_passcode_disable" = "Disable Passcode"; "lng_settings_passcode_disable_sure" = "Are you sure you want to disable passcode?"; +"lng_settings_use_winhello" = "Unlock with Windows Hello"; +"lng_settings_use_winhello_about" = "You need to enter your passcode once before unlocking Telegram with Windows Hello."; +"lng_settings_use_touchid" = "Unlock with Touch ID"; +"lng_settings_use_touchid_about" = "You need to enter your passcode once before unlocking Telegram with Touch ID."; "lng_settings_password_disable" = "Disable Cloud Password"; "lng_settings_password_abort" = "Abort two-step verification setup"; "lng_settings_about_bio" = "Any details such as age, occupation or city.\nExample: 23 y.o. designer from San Francisco"; @@ -992,6 +996,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_passcode_ph" = "Your passcode"; "lng_passcode_submit" = "Submit"; "lng_passcode_logout" = "Log out"; +"lng_passcode_winhello" = "You need to enter your passcode\nbefore you can use Windows Hello."; +"lng_passcode_touchid" = "You need to enter your passcode\nbefore you can use Touch ID."; +"lng_passcode_winhello_unlock" = "Telegram wants to unlock with Windows Hello."; +"lng_passcode_touchid_unlock" = "unlock"; "lng_passcode_create_button" = "Save Passcode"; "lng_passcode_check_button" = "Submit"; "lng_passcode_change_button" = "Save Passcode"; diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index f17389f1b..364d8f289 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -290,6 +290,28 @@ passcodeTextLine: 28px; passcodeLittleSkip: 5px; passcodeAboutSkip: 7px; passcodeSkip: 23px; +passcodeSystemUnlock: IconButton(defaultIconButton) { + width: 32px; + height: 32px; + rippleAreaSize: 24px; + rippleAreaPosition: point(4px, 4px); + ripple: RippleAnimation(defaultRippleAnimation) { + color: lightButtonBgOver; + } +} +passcodeSystemWinHello: IconButton(passcodeSystemUnlock) { + icon: icon{{ "menu/passcode_winhello", lightButtonFg }}; + iconOver: icon{{ "menu/passcode_winhello", lightButtonFg }}; +} +passcodeSystemTouchID: IconButton(passcodeSystemUnlock) { + icon: icon{{ "menu/passcode_finger", lightButtonFg }}; + iconOver: icon{{ "menu/passcode_finger", lightButtonFg }}; +} +passcodeSystemUnlockLater: FlatLabel(defaultFlatLabel) { + align: align(top); + textFg: windowSubTextFg; +} +passcodeSystemUnlockSkip: 12px; newGroupAboutFg: windowSubTextFg; newGroupPadding: margins(4px, 6px, 4px, 3px); diff --git a/Telegram/SourceFiles/core/core_settings.cpp b/Telegram/SourceFiles/core/core_settings.cpp index daaff5acf..efd0ba4d5 100644 --- a/Telegram/SourceFiles/core/core_settings.cpp +++ b/Telegram/SourceFiles/core/core_settings.cpp @@ -220,7 +220,7 @@ QByteArray Settings::serialize() const { + Serialize::bytearraySize(ivPosition) + Serialize::stringSize(noWarningExtensions) + Serialize::stringSize(_customFontFamily) - + sizeof(qint32); + + sizeof(qint32) * 2; auto result = QByteArray(); result.reserve(size); @@ -371,7 +371,8 @@ QByteArray Settings::serialize() const { << qint32(std::clamp( qRound(_dialogsNoChatWidthRatio.current() * 1000000), 0, - 1000000)); + 1000000)) + << qint32(_systemUnlockEnabled ? 1 : 0); } Ensures(result.size() == size); @@ -491,6 +492,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) { qint32 ttlVoiceClickTooltipHidden = _ttlVoiceClickTooltipHidden.current() ? 1 : 0; QByteArray ivPosition; QString customFontFamily = _customFontFamily; + qint32 systemUnlockEnabled = _systemUnlockEnabled ? 1 : 0; stream >> themesAccentColors; if (!stream.atEnd()) { @@ -788,6 +790,9 @@ void Settings::addFromSerialized(const QByteArray &serialized) { 0., 1.); } + if (!stream.atEnd()) { + stream >> systemUnlockEnabled; + } if (stream.status() != QDataStream::Ok) { LOG(("App Error: " "Bad data for Core::Settings::constructFromSerialized()")); @@ -995,6 +1000,7 @@ void Settings::addFromSerialized(const QByteArray &serialized) { _ivPosition = Deserialize(ivPosition); } _customFontFamily = customFontFamily; + _systemUnlockEnabled = (systemUnlockEnabled == 1); } QString Settings::getSoundPath(const QString &key) const { diff --git a/Telegram/SourceFiles/core/core_settings.h b/Telegram/SourceFiles/core/core_settings.h index 2588923c6..3412c4588 100644 --- a/Telegram/SourceFiles/core/core_settings.h +++ b/Telegram/SourceFiles/core/core_settings.h @@ -884,6 +884,13 @@ public: _customFontFamily = value; } + [[nodiscard]] bool systemUnlockEnabled() const { + return _systemUnlockEnabled; + } + void setSystemUnlockEnabled(bool enabled) { + _systemUnlockEnabled = enabled; + } + [[nodiscard]] static bool ThirdColumnByDefault(); [[nodiscard]] static float64 DefaultDialogsWidthRatio(); @@ -1014,6 +1021,7 @@ private: rpl::variable _ttlVoiceClickTooltipHidden = false; WindowPosition _ivPosition; QString _customFontFamily; + bool _systemUnlockEnabled = false; bool _tabbedReplacedWithInfo = false; // per-window rpl::event_stream _tabbedReplacedWithInfoValue; // per-window diff --git a/Telegram/SourceFiles/settings/settings_local_passcode.cpp b/Telegram/SourceFiles/settings/settings_local_passcode.cpp index 9a766f16d..db21f717b 100644 --- a/Telegram/SourceFiles/settings/settings_local_passcode.cpp +++ b/Telegram/SourceFiles/settings/settings_local_passcode.cpp @@ -8,6 +8,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "settings/settings_local_passcode.h" #include "base/platform/base_platform_last_input.h" +#include "base/platform/base_platform_info.h" +#include "base/system_unlock.h" #include "boxes/auto_lock_box.h" #include "core/application.h" #include "core/core_settings.h" @@ -23,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/widgets/fields/password_input.h" #include "ui/widgets/labels.h" #include "ui/wrap/vertical_layout.h" +#include "ui/wrap/slide_wrap.h" #include "window/window_session_controller.h" #include "styles/style_boxes.h" #include "styles/style_layers.h" @@ -199,11 +202,11 @@ void LocalPasscodeEnter::setupContent() { content, object_ptr( content, - isCreate + (isCreate ? tr::lng_passcode_create_button() : isCheck ? tr::lng_passcode_check_button() - : tr::lng_passcode_change_button(), + : tr::lng_passcode_change_button()), st::changePhoneButton)), st::settingLocalPasscodeButtonPadding)->entity(); button->setTextTransform(Ui::RoundButton::TextTransform::NoTransform); @@ -239,6 +242,8 @@ void LocalPasscodeEnter::setupContent() { } SetPasscode(_controller, newText); if (isCreate) { + Core::App().settings().setSystemUnlockEnabled(true); + Core::App().saveSettingsDelayed(); _showOther.fire(LocalPasscodeManageId()); } else if (isChange) { _showBack.fire({}); @@ -506,6 +511,46 @@ void LocalPasscodeManage::setupContent() { divider->skipEdge(Qt::BottomEdge, shown); }, divider->lifetime()); + const auto systemUnlockWrap = content->add( + object_ptr>( + content, + object_ptr(content)) + )->setDuration(0); + const auto systemUnlockContent = systemUnlockWrap->entity(); + + Ui::AddSkip(systemUnlockContent); + + AddButtonWithIcon( + systemUnlockContent, + (Platform::IsWindows() + ? tr::lng_settings_use_winhello() + : tr::lng_settings_use_touchid()), + st::settingsButton, + { Platform::IsWindows() + ? &st::menuIconWinHello + : &st::menuIconTouchID } + )->toggleOn( + rpl::single(Core::App().settings().systemUnlockEnabled()) + )->toggledChanges( + ) | rpl::filter([=](bool value) { + return value != Core::App().settings().systemUnlockEnabled(); + }) | rpl::start_with_next([=](bool value) { + Core::App().settings().setSystemUnlockEnabled(value); + Core::App().saveSettingsDelayed(); + }, systemUnlockContent->lifetime()); + + Ui::AddSkip(systemUnlockContent); + + Ui::AddDividerText( + systemUnlockContent, + (Platform::IsWindows() + ? tr::lng_settings_use_winhello_about() + : tr::lng_settings_use_touchid_about())); + + using namespace rpl::mappers; + systemUnlockWrap->toggleOn(base::SystemUnlockStatus( + ) | rpl::map(_1 == base::SystemUnlockAvailability::Available)); + Ui::ResizeFitChild(this, content); } diff --git a/Telegram/SourceFiles/settings/settings_privacy_security.cpp b/Telegram/SourceFiles/settings/settings_privacy_security.cpp index ab8f32217..daea2e9ee 100644 --- a/Telegram/SourceFiles/settings/settings_privacy_security.cpp +++ b/Telegram/SourceFiles/settings/settings_privacy_security.cpp @@ -22,6 +22,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "settings/settings_premium.h" // Settings::ShowPremium. #include "settings/settings_privacy_controllers.h" #include "settings/settings_websites.h" +#include "base/system_unlock.h" #include "base/timer_rpl.h" #include "boxes/passcode_box.h" #include "boxes/sessions_box.h" @@ -1079,6 +1080,8 @@ PrivacySecurity::PrivacySecurity( not_null controller) : Section(parent) { setupContent(controller); + + [[maybe_unused]] auto preload = base::SystemUnlockStatus(); } rpl::producer PrivacySecurity::title() { diff --git a/Telegram/SourceFiles/ui/menu_icons.style b/Telegram/SourceFiles/ui/menu_icons.style index 8d08ff7de..ce1670203 100644 --- a/Telegram/SourceFiles/ui/menu_icons.style +++ b/Telegram/SourceFiles/ui/menu_icons.style @@ -155,6 +155,8 @@ menuIconTagRename: icon{{ "menu/tag_rename", menuIconColor }}; menuIconGroupsHide: icon {{ "menu/hide_members", menuIconColor }}; menuIconFont: icon {{ "menu/fonts", menuIconColor }}; menuIconFactcheck: icon {{ "menu/factcheck", menuIconColor }}; +menuIconWinHello: icon {{ "menu/passcode_winhello", menuIconColor }}; +menuIconTouchID: icon {{ "menu/passcode_finger", menuIconColor }}; menuIconTTLAny: icon {{ "menu/auto_delete_plain", menuIconColor }}; menuIconTTLAnyTextPosition: point(11px, 22px); diff --git a/Telegram/SourceFiles/window/window_lock_widgets.cpp b/Telegram/SourceFiles/window/window_lock_widgets.cpp index 58f4881fa..e6453fbf2 100644 --- a/Telegram/SourceFiles/window/window_lock_widgets.cpp +++ b/Telegram/SourceFiles/window/window_lock_widgets.cpp @@ -7,6 +7,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL */ #include "window/window_lock_widgets.h" +#include "base/platform/base_platform_info.h" +#include "base/call_delayed.h" +#include "base/system_unlock.h" #include "lang/lang_keys.h" #include "storage/storage_domain.h" #include "mainwindow.h" @@ -27,6 +30,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "styles/style_boxes.h" namespace Window { +namespace { + +constexpr auto kSystemUnlockDelay = crl::time(1000); + +} // namespace LockWidget::LockWidget(QWidget *parent, not_null window) : RpWidget(parent) @@ -99,6 +107,108 @@ PasscodeLockWidget::PasscodeLockWidget( _logout->setClickedCallback([=] { window->showLogoutConfirmation(); }); + + using namespace rpl::mappers; + if (Core::App().settings().systemUnlockEnabled()) { + _systemUnlockAvailable = base::SystemUnlockStatus() + | rpl::map(_1 == base::SystemUnlockAvailability::Available); + if (Core::App().domain().started()) { + _systemUnlockAllowed = _systemUnlockAvailable.value(); + setupSystemUnlock(); + } else { + setupSystemUnlockInfo(); + } + } +} + +void PasscodeLockWidget::setupSystemUnlockInfo() { + const auto info = Ui::CreateChild( + this, + (Platform::IsWindows() + ? tr::lng_passcode_winhello() + : tr::lng_passcode_touchid()), + st::passcodeSystemUnlockLater); + _logout->geometryValue( + ) | rpl::start_with_next([=](QRect logout) { + info->resizeToWidth(width() + - st::boxRowPadding.left() + - st::boxRowPadding.right()); + info->moveToLeft( + st::boxRowPadding.left(), + logout.y() + logout.height() + st::passcodeSystemUnlockSkip); + }, info->lifetime()); + info->showOn(_systemUnlockAvailable.value()); +} + +void PasscodeLockWidget::setupSystemUnlock() { + windowActiveValue() | rpl::skip(1) | rpl::filter([=](bool active) { + return active + && !_systemUnlockSuggested + && !_systemUnlockCooldown.isActive(); + }) | rpl::start_with_next([=](bool) { + [[maybe_unused]] auto refresh = base::SystemUnlockStatus(); + suggestSystemUnlock(); + }, lifetime()); + + const auto button = Ui::CreateChild( + _passcode.data(), + (Platform::IsWindows() + ? st::passcodeSystemWinHello + : st::passcodeSystemTouchID)); + button->showOn(_systemUnlockAllowed.value()); + _passcode->sizeValue() | rpl::start_with_next([=](QSize size) { + button->moveToRight(0, size.height() - button->height()); + }, button->lifetime()); + button->setClickedCallback([=] { + const auto delay = st::passcodeSystemUnlock.ripple.hideDuration; + base::call_delayed(delay, this, [=] { + suggestSystemUnlock(); + }); + }); +} + +void PasscodeLockWidget::suggestSystemUnlock() { + InvokeQueued(this, [=] { + if (_systemUnlockSuggested) { + return; + } + _systemUnlockCooldown.cancel(); + + using namespace base; + _systemUnlockAllowed.value( + ) | rpl::filter( + rpl::mappers::_1 + ) | rpl::take(1) | rpl::start_with_next([=] { + const auto weak = Ui::MakeWeak(this); + const auto done = [weak](SystemUnlockResult result) { + crl::on_main([=] { + if (const auto strong = weak.data()) { + strong->systemUnlockDone(result); + } + }); + }; + SuggestSystemUnlock( + this, + (::Platform::IsWindows() + ? tr::lng_passcode_winhello_unlock(tr::now) + : tr::lng_passcode_touchid_unlock(tr::now)), + done); + }, _systemUnlockSuggested); + }); +} + +void PasscodeLockWidget::systemUnlockDone(base::SystemUnlockResult result) { + if (result == base::SystemUnlockResult::Success) { + Core::App().unlockPasscode(); + return; + } + _systemUnlockCooldown.callOnce(kSystemUnlockDelay); + _systemUnlockSuggested.destroy(); + if (result == base::SystemUnlockResult::FloodError) { + _error = tr::lng_flood_error(tr::now); + _passcode->setFocusFast(); + update(); + } } void PasscodeLockWidget::paintContent(QPainter &p) { diff --git a/Telegram/SourceFiles/window/window_lock_widgets.h b/Telegram/SourceFiles/window/window_lock_widgets.h index d2967d47f..8c48850fb 100644 --- a/Telegram/SourceFiles/window/window_lock_widgets.h +++ b/Telegram/SourceFiles/window/window_lock_widgets.h @@ -11,6 +11,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/effects/animations.h" #include "ui/layers/box_content.h" #include "base/bytes.h" +#include "base/timer.h" + +namespace base { +enum class SystemUnlockResult; +} // namespace base namespace Ui { class PasswordInput; @@ -61,15 +66,25 @@ protected: private: void paintContent(QPainter &p) override; + + void setupSystemUnlockInfo(); + void setupSystemUnlock(); + void suggestSystemUnlock(); + void systemUnlockDone(base::SystemUnlockResult result); void changed(); void submit(); void error(); + rpl::variable _systemUnlockAvailable = false; + rpl::variable _systemUnlockAllowed = false; object_ptr _passcode; object_ptr _submit; object_ptr _logout; QString _error; + rpl::lifetime _systemUnlockSuggested; + base::Timer _systemUnlockCooldown; + }; struct TermsLock { diff --git a/Telegram/lib_base b/Telegram/lib_base index 1be2a262a..b512eead3 160000 --- a/Telegram/lib_base +++ b/Telegram/lib_base @@ -1 +1 @@ -Subproject commit 1be2a262a6524d6dec3b616c2e9fd2ce42c9e61a +Subproject commit b512eead302cb7b509869778348d60fef64bc19b diff --git a/cmake b/cmake index b92244f0c..104406258 160000 --- a/cmake +++ b/cmake @@ -1 +1 @@ -Subproject commit b92244f0c21f157600484498c33a3566087526dd +Subproject commit 104406258fa89f007aad69348cef9b433f128fc2