mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-04-14 13:17:08 +02:00
Add a Windows Hello / Touch ID system unlock.
This commit is contained in:
parent
7e704d9529
commit
1988435cdf
17 changed files with 225 additions and 6 deletions
BIN
Telegram/Resources/icons/menu/passcode_finger.png
Normal file
BIN
Telegram/Resources/icons/menu/passcode_finger.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 911 B |
BIN
Telegram/Resources/icons/menu/passcode_finger@2x.png
Normal file
BIN
Telegram/Resources/icons/menu/passcode_finger@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
BIN
Telegram/Resources/icons/menu/passcode_finger@3x.png
Normal file
BIN
Telegram/Resources/icons/menu/passcode_finger@3x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
BIN
Telegram/Resources/icons/menu/passcode_winhello.png
Normal file
BIN
Telegram/Resources/icons/menu/passcode_winhello.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 454 B |
BIN
Telegram/Resources/icons/menu/passcode_winhello@2x.png
Normal file
BIN
Telegram/Resources/icons/menu/passcode_winhello@2x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 772 B |
BIN
Telegram/Resources/icons/menu/passcode_winhello@3x.png
Normal file
BIN
Telegram/Resources/icons/menu/passcode_winhello@3x.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
|
@ -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";
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<bool> _ttlVoiceClickTooltipHidden = false;
|
||||
WindowPosition _ivPosition;
|
||||
QString _customFontFamily;
|
||||
bool _systemUnlockEnabled = false;
|
||||
|
||||
bool _tabbedReplacedWithInfo = false; // per-window
|
||||
rpl::event_stream<bool> _tabbedReplacedWithInfoValue; // per-window
|
||||
|
|
|
@ -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<Ui::RoundButton>(
|
||||
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<Ui::SlideWrap<Ui::VerticalLayout>>(
|
||||
content,
|
||||
object_ptr<Ui::VerticalLayout>(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Window::SessionController*> controller)
|
||||
: Section(parent) {
|
||||
setupContent(controller);
|
||||
|
||||
[[maybe_unused]] auto preload = base::SystemUnlockStatus();
|
||||
}
|
||||
|
||||
rpl::producer<QString> PrivacySecurity::title() {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<Controller*> 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<Ui::FlatLabel>(
|
||||
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<Ui::IconButton>(
|
||||
_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) {
|
||||
|
|
|
@ -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<bool> _systemUnlockAvailable = false;
|
||||
rpl::variable<bool> _systemUnlockAllowed = false;
|
||||
object_ptr<Ui::PasswordInput> _passcode;
|
||||
object_ptr<Ui::RoundButton> _submit;
|
||||
object_ptr<Ui::LinkButton> _logout;
|
||||
QString _error;
|
||||
|
||||
rpl::lifetime _systemUnlockSuggested;
|
||||
base::Timer _systemUnlockCooldown;
|
||||
|
||||
};
|
||||
|
||||
struct TermsLock {
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 1be2a262a6524d6dec3b616c2e9fd2ce42c9e61a
|
||||
Subproject commit b512eead302cb7b509869778348d60fef64bc19b
|
2
cmake
2
cmake
|
@ -1 +1 @@
|
|||
Subproject commit b92244f0c21f157600484498c33a3566087526dd
|
||||
Subproject commit 104406258fa89f007aad69348cef9b433f128fc2
|
Loading…
Add table
Reference in a new issue