From d85ff147e1d513e57f50ee57127a704319f2e7fb Mon Sep 17 00:00:00 2001 From: reionwong Date: Mon, 11 Oct 2021 20:25:28 +0800 Subject: [PATCH] Add unlock animation --- screenlocker/application.cpp | 35 ++++++++- screenlocker/application.h | 3 + screenlocker/images/login.svg | 13 ++++ .../images/screensaver-unlock-symbolic.svg | 14 ++++ .../images/system-lock-screen-symbolic.svg | 14 ++++ screenlocker/qml.qrc | 4 + screenlocker/qml/LockScreen.qml | 77 +++++++++++-------- screenlocker/qml/LoginButton.qml | 71 +++++++++++++++++ 8 files changed, 196 insertions(+), 35 deletions(-) create mode 100644 screenlocker/images/login.svg create mode 100644 screenlocker/images/screensaver-unlock-symbolic.svg create mode 100644 screenlocker/images/system-lock-screen-symbolic.svg create mode 100644 screenlocker/qml/LoginButton.qml diff --git a/screenlocker/application.cpp b/screenlocker/application.cpp index 0164a47..a8adf10 100644 --- a/screenlocker/application.cpp +++ b/screenlocker/application.cpp @@ -66,7 +66,7 @@ Application::Application(int &argc, char **argv) , m_authenticator(new Authenticator(AuthenticationMode::Direct, this)) { // It's a queued connection to give the QML part time to eventually execute code connected to Authenticator::succeeded if any - connect(m_authenticator, &Authenticator::succeeded, this, &QCoreApplication::quit, Qt::QueuedConnection); + connect(m_authenticator, &Authenticator::succeeded, this, &Application::onSucceeded, Qt::QueuedConnection); installEventFilter(this); @@ -176,6 +176,39 @@ void Application::onScreenAdded(QScreen *screen) desktopResized(); } +void Application::onSucceeded() +{ + QQuickView *mainView = nullptr; + + // 寻找主屏幕的 view + for (int i = 0; i < m_views.size(); ++i) { + if (m_views.at(i)->screen() == QGuiApplication::primaryScreen()) { + mainView = m_views.at(i); + break; + } + } + + if (mainView) { + QVariantAnimation *ani = new QVariantAnimation; + + connect(ani, &QVariantAnimation::valueChanged, [mainView] (const QVariant &value) { + mainView->setY(value.toInt()); + }); + + connect(ani, &QVariantAnimation::finished, this, [=] { + QCoreApplication::exit(); + }); + + ani->setDuration(500); + ani->setEasingCurve(QEasingCurve::OutSine); + ani->setStartValue(mainView->geometry().y()); + ani->setEndValue(mainView->geometry().y() + -mainView->geometry().height()); + ani->start(); + } else { + QCoreApplication::exit(); + } +} + void Application::getFocus() { QWindow *activeScreen = getActiveScreen(); diff --git a/screenlocker/application.h b/screenlocker/application.h index 0c8aade..ad18d0e 100644 --- a/screenlocker/application.h +++ b/screenlocker/application.h @@ -22,6 +22,8 @@ #include #include + +#include #include "authenticator.h" class Application : public QGuiApplication @@ -39,6 +41,7 @@ public slots: void onScreenAdded(QScreen *screen); private slots: + void onSucceeded(); void getFocus(); void markViewsAsVisible(QQuickView *view); diff --git a/screenlocker/images/login.svg b/screenlocker/images/login.svg new file mode 100644 index 0000000..79a971d --- /dev/null +++ b/screenlocker/images/login.svg @@ -0,0 +1,13 @@ + + + + + + image/svg+xml + + + + + + + diff --git a/screenlocker/images/screensaver-unlock-symbolic.svg b/screenlocker/images/screensaver-unlock-symbolic.svg new file mode 100644 index 0000000..ef137c1 --- /dev/null +++ b/screenlocker/images/screensaver-unlock-symbolic.svg @@ -0,0 +1,14 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/screenlocker/images/system-lock-screen-symbolic.svg b/screenlocker/images/system-lock-screen-symbolic.svg new file mode 100644 index 0000000..171979e --- /dev/null +++ b/screenlocker/images/system-lock-screen-symbolic.svg @@ -0,0 +1,14 @@ + + + + + + image/svg+xml + + + + + + + + diff --git a/screenlocker/qml.qrc b/screenlocker/qml.qrc index 57b629b..81370ca 100644 --- a/screenlocker/qml.qrc +++ b/screenlocker/qml.qrc @@ -1,5 +1,9 @@ qml/LockScreen.qml + images/login.svg + qml/LoginButton.qml + images/screensaver-unlock-symbolic.svg + images/system-lock-screen-symbolic.svg diff --git a/screenlocker/qml/LockScreen.qml b/screenlocker/qml/LockScreen.qml index 14a605d..2571893 100644 --- a/screenlocker/qml/LockScreen.qml +++ b/screenlocker/qml/LockScreen.qml @@ -100,8 +100,21 @@ Item { anchors.bottom: _mainItem.top anchors.bottomMargin: root.height * 0.1 +// Image { +// id: icon +// anchors.horizontalCenter: parent.horizontalCenter +// anchors.verticalCenter: parent.verticalCenter +// Layout.alignment: Qt.AlignHCenter +// width: 32 +// height: 32 +// sourceSize: Qt.size(width, height) +// source: "qrc:/images/system-lock-screen-symbolic.svg" +// } + Label { id: timeLabel +// anchors.top: icon.bottom +// anchors.topMargin: FishUI.Units.largeSpacing anchors.horizontalCenter: parent.horizontalCenter anchors.verticalCenter: parent.verticalCenter Layout.alignment: Qt.AlignHCenter @@ -213,11 +226,11 @@ Item { TextField { id: password Layout.alignment: Qt.AlignHCenter - Layout.preferredHeight: 40 - Layout.preferredWidth: 260 + Layout.preferredHeight: 36 + Layout.fillWidth: true placeholderText: qsTr("Password") leftPadding: FishUI.Units.largeSpacing - rightPadding: FishUI.Units.largeSpacing + rightPadding: 36 + FishUI.Units.largeSpacing //FishUI.Units.largeSpacing enabled: !authenticator.graceLocked focus: true @@ -225,48 +238,44 @@ Item { background: Rectangle { color: FishUI.Theme.darkMode ? "#B6B6B6" : "white" - radius: FishUI.Theme.bigRadius + // radius: FishUI.Theme.bigRadius opacity: 0.5 } Keys.onEnterPressed: root.tryUnlock() Keys.onReturnPressed: root.tryUnlock() Keys.onEscapePressed: password.text = "" - } - Button { - id: unlockBtn - hoverEnabled: true - focusPolicy: Qt.NoFocus - Layout.alignment: Qt.AlignHCenter - Layout.preferredHeight: 40 - Layout.preferredWidth: 260 - text: qsTr("Unlock") - onClicked: root.tryUnlock() - enabled: !authenticator.graceLocked + LoginButton { + anchors.right: password.right + anchors.top: password.top + anchors.bottom: password.bottom + source: "qrc:/images/screensaver-unlock-symbolic.svg" + iconMargins: 10 + Layout.alignment: Qt.AlignHCenter + enabled: !authenticator.graceLocked + onClicked: root.tryUnlock() + size: 36 + Layout.preferredHeight: 36 + Layout.preferredWidth: 36 + } - scale: unlockBtn.pressed ? 0.95 : 1.0 + layer.enabled: true + layer.effect: OpacityMask { + maskSource: Item { + width: password.width + height: password.height - Behavior on scale { - NumberAnimation { - duration: 100 + Rectangle { + anchors.fill: parent + radius: FishUI.Theme.mediumRadius + } } } + } -// contentItem: Text { -// text: unlockBtn.text -// font: unlockBtn.font -// horizontalAlignment: Text.AlignHCenter -// verticalAlignment: Text.AlignVCenter -// elide: Text.ElideRight -// color: "#1C1C1C" -// } - - background: Rectangle { - color: FishUI.Theme.darkMode ? "#B6B6B6" : "white" - opacity: unlockBtn.pressed ? 0.3 : unlockBtn.hovered ? 0.4 : 0.5 - radius: FishUI.Theme.bigRadius - } + Item { + height: 1 } } } @@ -299,7 +308,7 @@ Item { samples: radius * 4 spread: 0.35 color: Qt.rgba(0, 0, 0, 0.8) - opacity: 0.1 + opacity: 0.3 visible: true } diff --git a/screenlocker/qml/LoginButton.qml b/screenlocker/qml/LoginButton.qml new file mode 100644 index 0000000..446bde4 --- /dev/null +++ b/screenlocker/qml/LoginButton.qml @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2021 CutefishOS Team. + * + * Author: Reion Wong + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import QtQuick 2.12 +import QtQuick.Window 2.3 +import QtQuick.Controls 2.4 +import FishUI 1.0 as FishUI + +Item { + id: control + + property var size: 32 + property var iconMargins: 0 + height: size + width: size + + property alias background: _background + property color backgroundColor: FishUI.Theme.highlightColor + property color hoveredColor: Qt.lighter(backgroundColor, 1.1) + property color pressedColor: Qt.darker(backgroundColor, 1.2) + property alias source: _image.source + property alias image: _image + signal clicked() + + Rectangle { + id: _background + anchors.fill: parent + // radius: FishUI.Theme.bigRadius //control.height / 2 + color: mouseArea.pressed ? pressedColor : mouseArea.containsMouse ? control.hoveredColor : control.backgroundColor + + gradient: Gradient { + GradientStop { position: 0.0; color: Qt.lighter(_background.color, 1.3) } + GradientStop { position: 1.0; color: _background.color } + } + } + + MouseArea { + id: mouseArea + anchors.fill: parent + hoverEnabled: true + + onClicked: control.clicked() + } + + Image { + id: _image + objectName: "image" + anchors.fill: parent + anchors.margins: control.iconMargins + fillMode: Image.PreserveAspectFit + sourceSize: Qt.size(width, height) + cache: true + asynchronous: false + } +}