Support unlock with Watch/SystemPassword.

This commit is contained in:
John Preston 2024-07-01 14:58:23 +04:00
parent e54204b136
commit f40a584905
10 changed files with 134 additions and 51 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 631 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 886 B

View file

@ -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";

View file

@ -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;

View file

@ -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<UnlockType>
>(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);
}

View file

@ -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);

View file

@ -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<Ui::FlatLabel>(
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<Ui::IconButton>(
_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) {

View file

@ -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<bool> _systemUnlockAvailable = false;
rpl::variable<bool> _systemUnlockAllowed = false;
rpl::variable<SystemUnlockType> _systemUnlockAvailable;
rpl::variable<SystemUnlockType> _systemUnlockAllowed;
object_ptr<Ui::PasswordInput> _passcode;
object_ptr<Ui::RoundButton> _submit;
object_ptr<Ui::LinkButton> _logout;

@ -1 +1 @@
Subproject commit b512eead302cb7b509869778348d60fef64bc19b
Subproject commit f30400147d997fedc787e214467d305db6c159e7