diff --git a/lookandfeel/contents/lockscreen/BottomIconIndicator.qml b/lookandfeel/contents/lockscreen/BottomIconIndicator.qml new file mode 100644 index 00000000..a7419b20 --- /dev/null +++ b/lookandfeel/contents/lockscreen/BottomIconIndicator.qml @@ -0,0 +1,84 @@ +// SPDX-FileCopyrightText: 2023 Devin Lin +// SPDX-License-Identifier: GPL-2.0-or-later + +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +import org.kde.kirigami 2.20 as Kirigami + +Loader { + id: root + asynchronous: true + + property var lockScreenState + + property real animationY: 0 + readonly property real fullYOffset: Kirigami.Units.largeSpacing + + // animate it going up and down + NumberAnimation on animationY { + id: animateUpAndDown + duration: 800 + easing.type: Easing.InCubic + to: root.fullYOffset + + // only bounce icon if we are showing the scroll up icon + running: !lockScreenState.isFingerprintSupported + + onFinished: { + if (root.animationY === root.fullYOffset) { + to = 0; + easing.type = Easing.OutCubic; + } else { + to = root.fullYOffset; + easing.type = Easing.InCubic; + } + restart(); + } + + onStopped: { + if (lockScreenState.isFingerprintSupported) { + root.animationY = 0; + } + } + } + + sourceComponent: { + if (lockScreenState.isFingerprintSupported) { + return fingerprintIcon; + } else { + return scrollUpIcon; + } + } + + Component { + id: scrollUpIcon + + Kirigami.Icon { + implicitWidth: Kirigami.Units.iconSizes.small + implicitHeight: Kirigami.Units.iconSizes.small + opacity: 1 - flickable.openFactor + + Kirigami.Theme.colorSet: Kirigami.Theme.Complementary + source: "arrow-up" + } + } + + Component { + id: fingerprintIcon + + Kirigami.Icon { + source: 'fingerprint-symbolic' + opacity: 1 - flickable.openFactor + implicitWidth: Kirigami.Units.iconSizes.medium + implicitHeight: Kirigami.Units.iconSizes.medium + + Kirigami.Theme.colorSet: Kirigami.Theme.Complementary + + anchors.horizontalCenter: parent.horizontalCenter + anchors.bottom: parent.bottom + anchors.bottomMargin: Kirigami.Units.gridUnit * 2 + flickable.position * 0.5 + } + } +} diff --git a/lookandfeel/contents/lockscreen/LockScreen.qml b/lookandfeel/contents/lockscreen/LockScreen.qml index 100be805..337c0286 100644 --- a/lookandfeel/contents/lockscreen/LockScreen.qml +++ b/lookandfeel/contents/lockscreen/LockScreen.qml @@ -154,46 +154,13 @@ Item { } // scroll up icon - Loader { + BottomIconIndicator { id: scrollUpIconLoader - asynchronous: true - - property real animationY: 0 - readonly property real fullYOffset: Kirigami.Units.largeSpacing + lockScreenState: root.lockScreenState anchors.bottom: parent.bottom anchors.bottomMargin: Kirigami.Units.gridUnit + flickable.position * 0.5 + scrollUpIconLoader.animationY anchors.horizontalCenter: parent.horizontalCenter - - // animate it going up and down - NumberAnimation on animationY { - id: animateUpAndDown - running: true - duration: 800 - easing.type: Easing.InCubic - to: scrollUpIconLoader.fullYOffset - - onFinished: { - if (scrollUpIconLoader.animationY === scrollUpIconLoader.fullYOffset) { - to = 0; - easing.type = Easing.OutCubic; - } else { - to = scrollUpIconLoader.fullYOffset; - easing.type = Easing.InCubic; - } - restart(); - } - } - - sourceComponent: Kirigami.Icon { - id: scrollUpIcon - implicitWidth: Kirigami.Units.iconSizes.small - implicitHeight: Kirigami.Units.iconSizes.small - opacity: 1 - flickable.openFactor - - Kirigami.Theme.colorSet: Kirigami.Theme.Complementary - source: "arrow-up" - } } // password keypad diff --git a/lookandfeel/contents/lockscreen/LockScreenState.qml b/lookandfeel/contents/lockscreen/LockScreenState.qml index 3bb75449..cb1f82ba 100644 --- a/lookandfeel/contents/lockscreen/LockScreenState.qml +++ b/lookandfeel/contents/lockscreen/LockScreenState.qml @@ -4,6 +4,8 @@ import QtQml import QtQuick +import org.kde.kscreenlocker 1.0 as ScreenLocker + QtObject { id: root @@ -19,6 +21,9 @@ QtObject { // whether the lockscreen was passwordless property bool passwordless: false // TODO true + // whether the device can login with fingerprint + readonly property bool isFingerprintSupported: authenticator.authenticatorTypes & ScreenLocker.Authenticator.Fingerprint + signal reset() signal unlockSucceeded() signal unlockFailed() @@ -28,7 +33,7 @@ QtObject { waitingForAuth = true; } connections.hasPrompt = true; - authenticator.tryUnlock(); + authenticator.startAuthenticating(); } function resetPassword() { @@ -41,7 +46,7 @@ QtObject { // if we do, authenticator will emit a success signal, otherwise it will emit failure // TODO: Disabled for the time being, since it seems to cause an infinite loop - // authenticator.tryUnlock(); + // authenticator.startAuthenticating(); } property var connections: Connections { @@ -59,8 +64,13 @@ QtObject { } } - function onFailed() { + function onFailed(kind) { + if (kind != 0) { // if this is coming from the noninteractive authenticators + return; + } + // root.passwordless = false; + if (hasPrompt) { console.log('login failed'); root.waitingForAuth = false; @@ -69,26 +79,26 @@ QtObject { } } - function onInfoMessage(msg) { - console.log('info: ' + msg); - root.info += msg + " "; + function onInfoMessageChanged() { + console.log('info: ' + authenticator.infoMessage); + root.info += authenticator.infoMessage + " "; } // TODO - function onErrorMessage(msg) { - console.log('error: ' + msg); + function onErrorMessageChanged() { + console.log('error: ' + authenticator.errorMessage); } // TODO - function onPrompt(msg) { - console.log('prompt: ' + msg); + function onPromptChanged() { + console.log('prompt: ' + authenticator.prompt); } - function onPromptForSecret(msg) { - console.log('prompt secret: ' + msg); + function onPromptForSecretChanged() { + console.log('prompt secret: ' + authenticator.promptForSecret); if (root.password !== "") { authenticator.respond(root.password); - authenticator.tryUnlock(); + authenticator.startAuthenticating(); } } diff --git a/tests/LockScreenTest.qml b/tests/LockScreenTest.qml index 496760ad..befe2327 100644 --- a/tests/LockScreenTest.qml +++ b/tests/LockScreenTest.qml @@ -30,26 +30,28 @@ ApplicationWindow { QtObject { id: authenticator // id passed in by kscreenlocker + property string infoMessage: "" + property string errorMessage: "" + property string prompt: "" + property string promptForSecret: "" + signal succeeded() signal failed() - signal infoMessage(string msg) - signal errorMessage(string msg) - signal prompt(string msg) - signal promptForSecret(string msg) // these are not kscreenlocker properties, for test purposes only property string password: "" - property bool prompt: true + property bool shouldPrompt: true - function tryUnlock() { - if (prompt) { - prompt = false; - promptForSecret("Password:"); + function startAuthenticating() { + if (shouldPrompt) { + shouldPrompt = false; + promptForSecret = "Password:"; + promptForSecretChanged(); } else if (password === "123456") { - prompt = true; + shouldPrompt = true; succeeded(); } else { - prompt = true; + shouldPrompt = true; failed(); } }