feat: add plasma-face-unlock
This commit is contained in:
commit
f671acc93b
105 files changed
+13862
No files matched your search
@@ -0,0 +1,171 @@
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "bubblecontroller.h"
|
||||
|
||||
#include "userconfig.h"
|
||||
|
||||
#include <KLocalizedString>
|
||||
|
||||
#include <QJsonObject>
|
||||
|
||||
namespace
|
||||
{
|
||||
// How long a result stays up before the bubble closes. Long enough to read,
|
||||
// short enough not to be in the way.
|
||||
constexpr int SuccessHoldMs = 900;
|
||||
constexpr int FailureHoldMs = 1700;
|
||||
constexpr int LockoutHoldMs = 3000;
|
||||
// A scan that never reports back (the daemon went away half way) must not
|
||||
// leave the bubble up for good.
|
||||
constexpr int ScanWatchdogMs = 30000;
|
||||
} // namespace
|
||||
|
||||
BubbleController::BubbleController(UserConfig *config, QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_config(config)
|
||||
{
|
||||
m_hide.setSingleShot(true);
|
||||
connect(&m_hide, &QTimer::timeout, this, &BubbleController::dismiss);
|
||||
connect(m_config, &UserConfig::changed, this, &BubbleController::styleChanged);
|
||||
}
|
||||
|
||||
QString BubbleController::style() const
|
||||
{
|
||||
return m_config->bubbleStyle();
|
||||
}
|
||||
|
||||
bool BubbleController::enabled() const
|
||||
{
|
||||
return m_config->bubble();
|
||||
}
|
||||
|
||||
void BubbleController::setPhase(const QString &phase)
|
||||
{
|
||||
if (m_phase == phase) {
|
||||
return;
|
||||
}
|
||||
m_phase = phase;
|
||||
if (phase != u"hidden" && !m_shown) {
|
||||
m_shown = true;
|
||||
Q_EMIT shownChanged();
|
||||
}
|
||||
Q_EMIT phaseChanged();
|
||||
}
|
||||
|
||||
void BubbleController::setMessage(const QString &message)
|
||||
{
|
||||
if (m_message != message) {
|
||||
m_message = message;
|
||||
Q_EMIT messageChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void BubbleController::scanStarted()
|
||||
{
|
||||
if (!enabled()) {
|
||||
return;
|
||||
}
|
||||
m_hide.start(ScanWatchdogMs);
|
||||
setMessage({});
|
||||
if (m_faceSeen) {
|
||||
m_faceSeen = false;
|
||||
Q_EMIT faceSeenChanged();
|
||||
}
|
||||
setPhase(QStringLiteral("scanning"));
|
||||
}
|
||||
|
||||
void BubbleController::faceFound()
|
||||
{
|
||||
if (m_phase == u"scanning" && !m_faceSeen) {
|
||||
m_faceSeen = true;
|
||||
Q_EMIT faceSeenChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void BubbleController::hint(const QString &hint)
|
||||
{
|
||||
if (m_phase != u"scanning") {
|
||||
return;
|
||||
}
|
||||
if (hint == u"blink") {
|
||||
setMessage(i18n("Blink once"));
|
||||
} else if (hint == u"look") {
|
||||
setMessage(i18n("Look at the screen"));
|
||||
} else if (hint == u"closer") {
|
||||
setMessage(i18n("Move closer"));
|
||||
} else if (hint == u"light") {
|
||||
setMessage(i18n("Too dark"));
|
||||
}
|
||||
}
|
||||
|
||||
void BubbleController::succeeded()
|
||||
{
|
||||
if (m_phase == u"hidden") {
|
||||
return;
|
||||
}
|
||||
setMessage({});
|
||||
setPhase(QStringLiteral("success"));
|
||||
m_hide.start(SuccessHoldMs);
|
||||
}
|
||||
|
||||
void BubbleController::failed(const QString &reason, qint64 lockout)
|
||||
{
|
||||
if (m_phase == u"hidden") {
|
||||
return;
|
||||
}
|
||||
if (lockout > 0 || reason == u"lockout") {
|
||||
setMessage(i18n("Use your password"));
|
||||
setPhase(QStringLiteral("lockout"));
|
||||
m_hide.start(LockoutHoldMs);
|
||||
return;
|
||||
}
|
||||
if (reason == u"mismatch" || reason == u"spoof") {
|
||||
setMessage(i18n("Not recognized"));
|
||||
} else if (reason == u"liveness") {
|
||||
setMessage(i18n("Try again and blink"));
|
||||
} else if (reason == u"camera") {
|
||||
setMessage(i18n("Camera unavailable"));
|
||||
} else {
|
||||
// Nobody there, a head turned away, the scan cancelled because the
|
||||
// password was typed: nothing worth saying. The bubble just goes.
|
||||
setMessage({});
|
||||
setPhase(QStringLiteral("hidden"));
|
||||
m_hide.stop();
|
||||
return;
|
||||
}
|
||||
setPhase(QStringLiteral("failure"));
|
||||
m_hide.start(FailureHoldMs);
|
||||
}
|
||||
|
||||
void BubbleController::dismiss()
|
||||
{
|
||||
m_hide.stop();
|
||||
setPhase(QStringLiteral("hidden"));
|
||||
}
|
||||
|
||||
void BubbleController::closed()
|
||||
{
|
||||
if (m_phase == u"hidden" && m_shown) {
|
||||
m_shown = false;
|
||||
Q_EMIT shownChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void BubbleController::daemonEvent(const QJsonObject &event)
|
||||
{
|
||||
if (!m_config->bubbleForPrompts()) {
|
||||
return;
|
||||
}
|
||||
const QString state = event.value(u"state").toString();
|
||||
if (state == u"start") {
|
||||
scanStarted();
|
||||
} else if (state == u"face") {
|
||||
faceFound();
|
||||
} else if (state == u"hint") {
|
||||
hint(event.value(u"hint").toString());
|
||||
} else if (state == u"success") {
|
||||
succeeded();
|
||||
} else if (state == u"failure") {
|
||||
failed(event.value(u"reason").toString(), qint64(event.value(u"lockout").toDouble()));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user