shift-shell/shell/contents/lockscreen/Keypad.qml
Devin Lin a8b858dc3e Remove kirigami version in imports
This fixes potential issues stemming from pinning versions on Kirigami
qml api imports
2026-03-06 22:08:07 -05:00

232 lines
7.4 KiB
QML

// SPDX-FileCopyrightText: 2020-2024 Devin Lin <devin@kde.org>
// SPDX-License-Identifier: GPL-2.0-or-later
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick.Effects
import org.kde.plasma.components 3.0 as PlasmaComponents
import org.kde.plasma.core as PlasmaCore
import org.kde.plasma.workspace.keyboardlayout 1.0
import org.kde.plasma.private.mobileshell as MobileShell
import org.kde.kirigami as Kirigami
Item {
id: root
required property real openProgress
required property var lockScreenState
property alias passwordBar: passwordBar
MobileShell.HapticsEffect {
id: haptics
}
// Column layout - most cases
ColumnLayout {
id: keypadVerticalContainer
visible: root.height > Kirigami.Units.gridUnit * 25
anchors.centerIn: parent
spacing: Kirigami.Units.gridUnit * 2
LayoutItemProxy {
id: verticalHeaderProxy
target: header
}
LayoutItemProxy { target: keypadGrid }
states: [
State {
name: "keypad"
when: !lockScreenState.isKeyboardMode
AnchorChanges {
target: verticalHeaderProxy; anchors.top: keypadVerticalContainer.top
}
PropertyChanges {
target: verticalHeaderProxy; anchors.verticalCenterOffset: 0
}
},
State {
name: "keyboard"
when: lockScreenState.isKeyboardMode
AnchorChanges {
target: verticalHeaderProxy; anchors.verticalCenter: keypadVerticalContainer.verticalCenter
}
PropertyChanges {
target: verticalHeaderProxy; anchors.verticalCenterOffset: -Kirigami.Units.gridUnit * 3
}
}
]
transitions: Transition {
AnchorAnimation {
easing.type: Easing.OutCirc
duration: openProgress > 0.5 ? 300 : 0
}
}
}
// Row layout - used when there is restricted height
RowLayout {
id: keypadHorizontalContainer
visible: !keypadVerticalContainer.visible
anchors.centerIn: parent
spacing: Kirigami.Units.gridUnit * 2
LayoutItemProxy {
id: horizontalHeaderProxy
target: header
}
LayoutItemProxy { target: keypadGrid }
states: [
State {
name: "keypad"
when: !lockScreenState.isKeyboardMode
AnchorChanges {
target: horizontalHeaderProxy; anchors.left: keypadHorizontalContainer.left
}
},
State {
name: "keyboard"
when: lockScreenState.isKeyboardMode
AnchorChanges {
target: horizontalHeaderProxy; anchors.horizontalCenter: keypadHorizontalContainer.horizontalCenter
}
}
]
transitions: Transition {
AnchorAnimation {
easing.type: Easing.OutCirc
duration: openProgress > 0.5 ? 300 : 0
}
}
}
ColumnLayout {
id: header
spacing: Kirigami.Units.gridUnit
// label ("wrong pin", "enter pin")
Label {
id: descriptionLabel
Layout.alignment: Qt.AlignHCenter
opacity: root.lockScreenState.password.length === 0 ? 1 : 0
text: root.lockScreenState.pinLabel
font.pointSize: 12
font.bold: true
color: 'white'
// Enforce extra margin at top of vertical container
Layout.topMargin: keypadVerticalContainer.visible ? Kirigami.Units.gridUnit * 3 : 0
Behavior on opacity {
NumberAnimation { duration: Kirigami.Units.shortDuration }
}
}
// pin display and bar
PasswordBar {
id: passwordBar
Layout.preferredWidth: Kirigami.Units.gridUnit * 14
Layout.preferredHeight: Kirigami.Units.gridUnit * 2.5
lockScreenState: root.lockScreenState
isKeypadOpen: root.openProgress >= 0.9
enabled: root.openProgress >= 0.8
}
}
GridLayout {
id: keypadGrid
columnSpacing: Kirigami.Units.gridUnit
rowSpacing: Kirigami.Units.gridUnit
uniformCellHeights: true
uniformCellWidths: true
readonly property real intendedWidth: Kirigami.Units.gridUnit * 14
Layout.preferredWidth: Kirigami.Units.gridUnit * 14
Layout.preferredHeight: Kirigami.Units.gridUnit * 22
readonly property real cellLength: (intendedWidth - columnSpacing * 2) / 3
columns: 3
// numpad keys
Repeater {
model: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "R", "0", "E"]
delegate: AbstractButton {
id: button
implicitWidth: keypadGrid.cellLength
implicitHeight: keypadGrid.cellLength
visible: modelData.length > 0
enabled: root.openProgress >= 0.8 && !lockScreenState.isKeyboardMode // Only enable after a certain point in animation
opacity: enabled
Behavior on opacity {
SequentialAnimation {
PauseAnimation { duration: 20 * index }
NumberAnimation { duration: 300 }
}
}
background: Rectangle {
readonly property real restingOpacity: (modelData !== "R" && modelData !== "E") ? 0.2 : 0.0
radius: width
color: Qt.rgba(255, 255, 255,
button.pressed ? 0.5 : restingOpacity)
}
onPressedChanged: {
if (pressed) {
haptics.buttonVibrate();
}
}
onClicked: {
if (modelData === "R") {
passwordBar.backspace();
} else if (modelData === "E") {
passwordBar.enter();
} else {
passwordBar.keyPress(modelData);
}
}
onPressAndHold: {
if (modelData === "R") {
haptics.buttonVibrate();
passwordBar.clear();
}
}
contentItem: Item {
PlasmaComponents.Label {
visible: modelData !== "R" && modelData !== "E"
text: modelData
anchors.centerIn: parent
font.pointSize: 18
color: 'white'
}
Kirigami.Icon {
visible: modelData === "R" || modelData === "E"
anchors.centerIn: parent
width: Kirigami.Units.iconSizes.small
height: Kirigami.Units.iconSizes.small
source: modelData === "R" ? "edit-clear" : "go-next"
Kirigami.Theme.inherit: false
Kirigami.Theme.colorSet: Kirigami.Theme.Complementary
}
}
}
}
}
}