From f40a58490583fb1e819377bfa2bedd51c5091c20 Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 1 Jul 2024 14:58:23 +0400 Subject: [PATCH] Support unlock with Watch/SystemPassword. --- .../Resources/icons/menu/passcode_watch.png | Bin 0 -> 438 bytes .../icons/menu/passcode_watch@2x.png | Bin 0 -> 631 bytes .../icons/menu/passcode_watch@3x.png | Bin 0 -> 886 bytes Telegram/Resources/langs/lang.strings | 6 ++ Telegram/SourceFiles/boxes/boxes.style | 13 +-- .../settings/settings_local_passcode.cpp | 97 ++++++++++++------ Telegram/SourceFiles/ui/menu_icons.style | 2 + .../window/window_lock_widgets.cpp | 54 ++++++++-- .../SourceFiles/window/window_lock_widgets.h | 11 +- Telegram/lib_base | 2 +- 10 files changed, 134 insertions(+), 51 deletions(-) create mode 100644 Telegram/Resources/icons/menu/passcode_watch.png create mode 100644 Telegram/Resources/icons/menu/passcode_watch@2x.png create mode 100644 Telegram/Resources/icons/menu/passcode_watch@3x.png diff --git a/Telegram/Resources/icons/menu/passcode_watch.png b/Telegram/Resources/icons/menu/passcode_watch.png new file mode 100644 index 0000000000000000000000000000000000000000..161da4e870802ecd30683d3a25f6bc47ca7482ba GIT binary patch literal 438 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1SIoCSFHz9jKx9jP7LeL$-D$|Tv8)E(|mmy zw18|52FCVG1{RPKAeI7R1_tH@j10^`nh_+nfC(-uv49!D1}S`GTDlgfOu^H|F~maf z?G)Rt76*Y=cS!>?Q68Q>Ee{xdSbG0j_C7HE!^!Gw+ciUiqfKh|j_BRC2Ys#=r$tUn zZGL;=*S*#5<;h>4e!4!5$$Uv>l!)uHOs`iq=SySX|JM6>c~j=B?UP-Fa&|lIT9-XZ z<@PquRqI}_d+il4#bQP7ZHqqM!xO5erD~oIYFfln?jqf`~(oq0tSm;!h z#v+L}oAZqyIz5yQ&-`_u|M7>~|BQD3sx(rOl(}8aBY*$V!@5MzfX32Q23BN@#N<{>dv>n z+wwD6D+&9iT`&D0$$40S?c)pnPrdED@^6pNi`sMk{=)ZBhZhHKubUSM3NuevKbLh* G2~7a^3Zkt5 literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/menu/passcode_watch@2x.png b/Telegram/Resources/icons/menu/passcode_watch@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..516e313b7f5d145c4a12d99e2221860d122968c2 GIT binary patch literal 631 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1SD@Hh<<9ZiwNiJb`vKvI3TA#qxr50OrSCayngq7#Xsy|hpxk@!x4JU# zD&usi+^XW`+?mh++<*D9-p$B()-t`P2lkg8FyOhpt$g=g{)bIGNeYFLZCBb4HwK)X z%;FJa`mlI@oNFC}hxyBHJy&k8rI(6!#;m`-{IVy9SohJWwbwFC`i>`WjS_vel(qTb zf*8HiNe&E`G&$QRm`p!iYBjfNZ=8lm%X^FY=T~3NvYH#WK764?*Mh5A3nQP*EEZ>C zlz3WOv+Vx+>UrwXyqB3-&Ygen?x}0+Tf8yi$>+-JrS6L_rWhS$`5xSIH$e&L!iNPj z&Zg;4?@o=JeOAp!$J|b?|K|2@RkoHvmm3VkJX3B4{4Lw{Bx1QfWrs8mJ0E(x_hvu8c9x=_oEI@M#vu5D~@mV{rStRYfnFxw>Pgg&ebxsLQ08Bdd?f?J) literal 0 HcmV?d00001 diff --git a/Telegram/Resources/icons/menu/passcode_watch@3x.png b/Telegram/Resources/icons/menu/passcode_watch@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..2b5f71f725d7bef72725ae4810525fe53582e542 GIT binary patch literal 886 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1SD_us|Wxo#^NA%Cx&(BWL^R}E~ycoX}-P; zT0k}j17mw80}DtA5K93u0|WB{Mh0de%?J`(zyz1|Sip>6gA`6MbbHUh!1Tb=#W5s< z_3do?^@ffj$MicpoSdHLFI*Vlv4yKd$cwYrZBf`OlYJfj3nss)VbK`;5Unldou6}3C zxwOp(69O74_r{5LA1$$}wUJ|bIG;;Xto!xXU;MvWIRfU-S{jz_1B_Ytr;e-K5|&KITpKyxllNcpv>$Fhn6NYEQ@Ef*1JeiVnJ+?t zj(u73X!#O#297mxu4TJ#zrFS2;+pfk5eF=PcHB>%>Xm9E_d1-fW&_Z>haV~!ER4{Z zcK-R-@9IUX!&Xl|>C&Jk_vrJ_u+^fKH9KRh=JtJvT7Q=LVFQC}golGi%`~QoYs0#q ze5|#Zewx$4$GL%N!UF*#*>5Y)UCeN~^|$VRoFoG$pJMgH{TIw;^JXr;{4(Ax`cJXi zWJQY>9k|>-gXUqtd{P{RE>67hq%~f3=|4f!&tEG0oc;2E_66fuIUR*_tgl>ePRd3_+xAQCh zxbc7V^q6FNu0BC4V&l&mKQXh}zFD^~Wtd1ExyT*(oLzd|-6;kC%qHFXVZ3|Y+&!V$ zX7Sp!@9xB0mnnEw$nmlIOhkCNY{J1~`~E#>FpO@LV`voR*kXKSWBZXE(;t=X_Eix| znOfcV)$*HyTBYudg0~kVe>^;Q_*~RN@1>J2_bo3L=ik+I_a{H=lzCYikmT23Ec=6- XH}(4*u`@rvg3`RFtDnm{r-UW|$bgLV literal 0 HcmV?d00001 diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index b517e1f8d..db9afbe0e 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -687,6 +687,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "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_use_applewatch" = "Unlock with Apple Watch"; +"lng_settings_use_applewatch_about" = "You need to enter your passcode once before unlocking Telegram with Apple Watch."; +"lng_settings_use_systempwd" = "Unlock with System Password"; +"lng_settings_use_systempwd_about" = "You need to enter your passcode once before unlocking Telegram with System Password."; "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"; @@ -998,6 +1002,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "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_applewatch" = "You need to enter your passcode\nbefore you can use Watch to unlock."; +"lng_passcode_systempwd" = "You need to enter your passcode\nbefore you can use system password."; "lng_passcode_winhello_unlock" = "Telegram wants to unlock with Windows Hello."; "lng_passcode_touchid_unlock" = "unlock"; "lng_passcode_create_button" = "Save Passcode"; diff --git a/Telegram/SourceFiles/boxes/boxes.style b/Telegram/SourceFiles/boxes/boxes.style index fbe98a496..c3cad02eb 100644 --- a/Telegram/SourceFiles/boxes/boxes.style +++ b/Telegram/SourceFiles/boxes/boxes.style @@ -293,6 +293,8 @@ passcodeSkip: 23px; passcodeSystemUnlock: IconButton(defaultIconButton) { width: 32px; height: 36px; + icon: icon{{ "menu/passcode_winhello", lightButtonFg }}; + iconOver: icon{{ "menu/passcode_winhello", lightButtonFg }}; iconPosition: point(4px, 4px); rippleAreaSize: 32px; rippleAreaPosition: point(0px, 0px); @@ -300,14 +302,9 @@ passcodeSystemUnlock: IconButton(defaultIconButton) { 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 }}; -} +passcodeSystemTouchID: icon{{ "menu/passcode_finger", lightButtonFg }}; +passcodeSystemAppleWatch: icon{{ "menu/passcode_watch", lightButtonFg }}; +passcodeSystemSystemPwd: icon{{ "menu/permissions", lightButtonFg }}; passcodeSystemUnlockLater: FlatLabel(defaultFlatLabel) { align: align(top); textFg: windowSubTextFg; diff --git a/Telegram/SourceFiles/settings/settings_local_passcode.cpp b/Telegram/SourceFiles/settings/settings_local_passcode.cpp index db21f717b..01562905a 100644 --- a/Telegram/SourceFiles/settings/settings_local_passcode.cpp +++ b/Telegram/SourceFiles/settings/settings_local_passcode.cpp @@ -518,38 +518,77 @@ void LocalPasscodeManage::setupContent() { )->setDuration(0); const auto systemUnlockContent = systemUnlockWrap->entity(); - Ui::AddSkip(systemUnlockContent); + enum class UnlockType { + None, + Default, + Biometrics, + Companion, + }; + const auto unlockType = systemUnlockContent->lifetime().make_state< + rpl::variable + >(base::SystemUnlockStatus( + true + ) | rpl::map([](base::SystemUnlockAvailability status) { + return status.withBiometrics + ? UnlockType::Biometrics + : status.withCompanion + ? UnlockType::Companion + : status.available + ? UnlockType::Default + : UnlockType::None; + })); + + unlockType->value( + ) | rpl::start_with_next([=](UnlockType type) { + while (systemUnlockContent->count()) { + delete systemUnlockContent->widgetAt(0); + } + + Ui::AddSkip(systemUnlockContent); + + AddButtonWithIcon( + systemUnlockContent, + (Platform::IsWindows() + ? tr::lng_settings_use_winhello() + : (type == UnlockType::Biometrics) + ? tr::lng_settings_use_touchid() + : (type == UnlockType::Companion) + ? tr::lng_settings_use_applewatch() + : tr::lng_settings_use_systempwd()), + st::settingsButton, + { Platform::IsWindows() + ? &st::menuIconWinHello + : (type == UnlockType::Biometrics) + ? &st::menuIconTouchID + : (type == UnlockType::Companion) + ? &st::menuIconAppleWatch + : &st::menuIconSystemPwd } + )->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() + : (type == UnlockType::Biometrics) + ? tr::lng_settings_use_touchid_about() + : (type == UnlockType::Companion) + ? tr::lng_settings_use_applewatch_about() + : tr::lng_settings_use_systempwd_about())); - 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)); + systemUnlockWrap->toggleOn(unlockType->value( + ) | rpl::map(rpl::mappers::_1 != UnlockType::None)); Ui::ResizeFitChild(this, content); } diff --git a/Telegram/SourceFiles/ui/menu_icons.style b/Telegram/SourceFiles/ui/menu_icons.style index ce1670203..96838e8a5 100644 --- a/Telegram/SourceFiles/ui/menu_icons.style +++ b/Telegram/SourceFiles/ui/menu_icons.style @@ -157,6 +157,8 @@ menuIconFont: icon {{ "menu/fonts", menuIconColor }}; menuIconFactcheck: icon {{ "menu/factcheck", menuIconColor }}; menuIconWinHello: icon {{ "menu/passcode_winhello", menuIconColor }}; menuIconTouchID: icon {{ "menu/passcode_finger", menuIconColor }}; +menuIconAppleWatch: icon {{ "menu/passcode_watch", menuIconColor }}; +menuIconSystemPwd: menuIconPermissions; 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 e6453fbf2..02350886e 100644 --- a/Telegram/SourceFiles/window/window_lock_widgets.cpp +++ b/Telegram/SourceFiles/window/window_lock_widgets.cpp @@ -110,8 +110,17 @@ PasscodeLockWidget::PasscodeLockWidget( using namespace rpl::mappers; if (Core::App().settings().systemUnlockEnabled()) { - _systemUnlockAvailable = base::SystemUnlockStatus() - | rpl::map(_1 == base::SystemUnlockAvailability::Available); + _systemUnlockAvailable = base::SystemUnlockStatus( + true + ) | rpl::map([](base::SystemUnlockAvailability status) { + return status.withBiometrics + ? SystemUnlockType::Biometrics + : status.withCompanion + ? SystemUnlockType::Companion + : status.available + ? SystemUnlockType::Default + : SystemUnlockType::None; + }); if (Core::App().domain().started()) { _systemUnlockAllowed = _systemUnlockAvailable.value(); setupSystemUnlock(); @@ -122,11 +131,22 @@ PasscodeLockWidget::PasscodeLockWidget( } void PasscodeLockWidget::setupSystemUnlockInfo() { + const auto macos = [&] { + return _systemUnlockAvailable.value( + ) | rpl::map([](SystemUnlockType type) { + return (type == SystemUnlockType::Biometrics) + ? tr::lng_passcode_touchid() + : (type == SystemUnlockType::Companion) + ? tr::lng_passcode_applewatch() + : tr::lng_passcode_systempwd(); + }) | rpl::flatten_latest(); + }; + auto text = Platform::IsWindows() + ? tr::lng_passcode_winhello() + : macos(); const auto info = Ui::CreateChild( this, - (Platform::IsWindows() - ? tr::lng_passcode_winhello() - : tr::lng_passcode_touchid()), + std::move(text), st::passcodeSystemUnlockLater); _logout->geometryValue( ) | rpl::start_with_next([=](QRect logout) { @@ -137,7 +157,8 @@ void PasscodeLockWidget::setupSystemUnlockInfo() { st::boxRowPadding.left(), logout.y() + logout.height() + st::passcodeSystemUnlockSkip); }, info->lifetime()); - info->showOn(_systemUnlockAvailable.value()); + info->showOn(_systemUnlockAvailable.value( + ) | rpl::map(rpl::mappers::_1 != SystemUnlockType::None)); } void PasscodeLockWidget::setupSystemUnlock() { @@ -152,10 +173,21 @@ void PasscodeLockWidget::setupSystemUnlock() { const auto button = Ui::CreateChild( _passcode.data(), - (Platform::IsWindows() - ? st::passcodeSystemWinHello - : st::passcodeSystemTouchID)); - button->showOn(_systemUnlockAllowed.value()); + st::passcodeSystemUnlock); + if (!Platform::IsWindows()) { + using namespace base; + _systemUnlockAllowed.value( + ) | rpl::start_with_next([=](SystemUnlockType type) { + const auto icon = (type == SystemUnlockType::Biometrics) + ? &st::passcodeSystemTouchID + : (type == SystemUnlockType::Companion) + ? &st::passcodeSystemAppleWatch + : &st::passcodeSystemSystemPwd; + button->setIconOverride(icon, icon); + }, button->lifetime()); + } + button->showOn(_systemUnlockAllowed.value( + ) | rpl::map(rpl::mappers::_1 != SystemUnlockType::None)); _passcode->sizeValue() | rpl::start_with_next([=](QSize size) { button->moveToRight(0, size.height() - button->height()); }, button->lifetime()); @@ -177,7 +209,7 @@ void PasscodeLockWidget::suggestSystemUnlock() { using namespace base; _systemUnlockAllowed.value( ) | rpl::filter( - rpl::mappers::_1 + rpl::mappers::_1 != SystemUnlockType::None ) | rpl::take(1) | rpl::start_with_next([=] { const auto weak = Ui::MakeWeak(this); const auto done = [weak](SystemUnlockResult result) { diff --git a/Telegram/SourceFiles/window/window_lock_widgets.h b/Telegram/SourceFiles/window/window_lock_widgets.h index 8c48850fb..03c6b59b3 100644 --- a/Telegram/SourceFiles/window/window_lock_widgets.h +++ b/Telegram/SourceFiles/window/window_lock_widgets.h @@ -65,6 +65,13 @@ protected: void resizeEvent(QResizeEvent *e) override; private: + enum class SystemUnlockType : uchar { + None, + Default, + Biometrics, + Companion, + }; + void paintContent(QPainter &p) override; void setupSystemUnlockInfo(); @@ -75,8 +82,8 @@ private: void submit(); void error(); - rpl::variable _systemUnlockAvailable = false; - rpl::variable _systemUnlockAllowed = false; + rpl::variable _systemUnlockAvailable; + rpl::variable _systemUnlockAllowed; object_ptr _passcode; object_ptr _submit; object_ptr _logout; diff --git a/Telegram/lib_base b/Telegram/lib_base index b512eead3..f30400147 160000 --- a/Telegram/lib_base +++ b/Telegram/lib_base @@ -1 +1 @@ -Subproject commit b512eead302cb7b509869778348d60fef64bc19b +Subproject commit f30400147d997fedc787e214467d305db6c159e7