refactor(lockscreen): remove submit arrow for centered password input and enlarge session controls inside input card

This commit is contained in:
Sho 2026-08-02 16:20:21 +09:00
parent aed2c0f11d
commit b50ef1c8cb

View File

@ -205,12 +205,12 @@ Item {
Item { Layout.preferredHeight: 4 } Item { Layout.preferredHeight: 4 }
// 3. Elegant Glass Input Card with Animated Typing Dots // 3. Elegant Glass Input Card with Animated Typing Dots & Session Controls
Rectangle { Rectangle {
id: cardContainer id: cardContainer
Layout.fillWidth: true Layout.fillWidth: true
implicitHeight: cardLayout.implicitHeight + 36 implicitHeight: cardLayout.implicitHeight + 36
radius: 20 radius: 24
color: Theme.isDark ? Qt.rgba(30/255, 30/255, 46/255, 0.65) : Qt.rgba(240/255, 240/255, 245/255, 0.75) color: Theme.isDark ? Qt.rgba(30/255, 30/255, 46/255, 0.65) : Qt.rgba(240/255, 240/255, 245/255, 0.75)
border.color: LockscreenService.authFailed ? Theme.red : (secretInput.activeFocus ? Theme.accent : Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.18)) border.color: LockscreenService.authFailed ? Theme.red : (secretInput.activeFocus ? Theme.accent : Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.18))
border.width: LockscreenService.authFailed ? 2 : (secretInput.activeFocus ? 2 : 1) border.width: LockscreenService.authFailed ? 2 : (secretInput.activeFocus ? 2 : 1)
@ -223,255 +223,229 @@ Item {
anchors.right: parent.right anchors.right: parent.right
anchors.top: parent.top anchors.top: parent.top
anchors.margins: 18 anchors.margins: 18
spacing: 14 spacing: 16
// Password Row: Input Field + Submit Button // Centered Password Input Field
RowLayout { Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
spacing: 12 implicitHeight: 48
radius: 14
color: Qt.rgba(0, 0, 0, 0.28)
border.color: secretInput.activeFocus ? Qt.rgba(Theme.accent.r, Theme.accent.g, Theme.accent.b, 0.4) : Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.12)
// Password Visual Placeholder / Input Area Behavior on border.color { ColorAnimation { duration: 150 } }
Rectangle {
Layout.fillWidth: true
implicitHeight: 44
radius: 12
color: Qt.rgba(0, 0, 0, 0.25)
border.color: Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.1)
// Empty State Placeholder Text // Empty State Placeholder Text (Centered)
Text { Text {
anchors.verticalCenter: parent.verticalCenter anchors.centerIn: parent
anchors.left: parent.left visible: LockscreenService.typedCount === 0 && !LockscreenService.isAuthenticating
anchors.leftMargin: 16 text: "Type password to unlock..."
visible: LockscreenService.typedCount === 0 && !LockscreenService.isAuthenticating color: Theme.comment
text: "Type password to unlock..." font.pixelSize: 14
color: Theme.comment }
font.pixelSize: 14
}
// Authenticating Spinner / Status Text // Authenticating Spinner / Status Text
Text { Text {
anchors.centerIn: parent anchors.centerIn: parent
visible: LockscreenService.isAuthenticating visible: LockscreenService.isAuthenticating
text: "Verifying password..." text: "Verifying password..."
color: Theme.accent color: Theme.accent
font.pixelSize: 14 font.pixelSize: 14
font.weight: Font.Medium font.weight: Font.Medium
} }
ListModel { ListModel {
id: dotsModel id: dotsModel
} }
Connections { Connections {
target: LockscreenService target: LockscreenService
function onTypedCountChanged() { function onTypedCountChanged() {
let targetCount = LockscreenService.typedCount let targetCount = LockscreenService.typedCount
while (dotsModel.count < targetCount) { while (dotsModel.count < targetCount) {
dotsModel.append({ "id": dotsModel.count }) dotsModel.append({ "id": dotsModel.count })
}
while (dotsModel.count > targetCount) {
dotsModel.remove(dotsModel.count - 1)
}
} }
} while (dotsModel.count > targetCount) {
dotsModel.remove(dotsModel.count - 1)
// ANIMATED TYPING DOTS (Ultra-smooth sliding dot array with add/remove/displaced transitions)
Item {
id: dotsContainer
anchors.centerIn: parent
implicitWidth: Math.min(320, dotsModel.count * 26)
implicitHeight: 20
visible: dotsModel.count > 0 && !LockscreenService.isAuthenticating
Behavior on implicitWidth {
NumberAnimation { duration: 220; easing.type: Easing.OutCubic }
}
ListView {
id: dotsView
anchors.centerIn: parent
width: Math.min(dotsContainer.implicitWidth, count * 26)
height: 20
orientation: ListView.Horizontal
spacing: 12
interactive: false
model: dotsModel
add: Transition {
ParallelAnimation {
NumberAnimation { property: "scale"; from: 0.1; to: 1.0; duration: 250; easing.type: Easing.OutBack; easing.overshoot: 1.6 }
NumberAnimation { property: "opacity"; from: 0.0; to: 1.0; duration: 200; easing.type: Easing.OutCubic }
}
}
remove: Transition {
ParallelAnimation {
NumberAnimation { property: "scale"; to: 0.0; duration: 180; easing.type: Easing.InBack }
NumberAnimation { property: "opacity"; to: 0.0; duration: 150; easing.type: Easing.OutCubic }
}
}
displaced: Transition {
NumberAnimation { properties: "x,y"; duration: 220; easing.type: Easing.OutCubic }
}
delegate: Item {
width: 14
height: 14
Rectangle {
id: dot
anchors.fill: parent
radius: 7
color: index === dotsModel.count - 1 ? Theme.accent : Theme.fg
Behavior on color { ColorAnimation { duration: 180 } }
// Inner Glow Core
Rectangle {
anchors.centerIn: parent
width: 6
height: 6
radius: 3
color: "#ffffff"
opacity: index === dotsModel.count - 1 ? 1.0 : 0.6
}
}
}
}
}
// Focus Click Area
MouseArea {
anchors.fill: parent
onClicked: {
root.forceActiveFocus()
secretInput.forceActiveFocus()
} }
} }
} }
// Submit / Unlock Arrow Button // ANIMATED TYPING DOTS (Centered sliding dot array with add/remove/displaced transitions)
Rectangle { Item {
width: 44 id: dotsContainer
height: 44 anchors.centerIn: parent
radius: 12 implicitWidth: Math.min(320, dotsModel.count * 26)
color: submitMouse.containsMouse ? Theme.accent : Qt.rgba(Theme.accent.r, Theme.accent.g, Theme.accent.b, 0.25) implicitHeight: 20
border.color: Theme.accent visible: dotsModel.count > 0 && !LockscreenService.isAuthenticating
Behavior on color { ColorAnimation { duration: 120 } } Behavior on implicitWidth {
NumberAnimation { duration: 220; easing.type: Easing.OutCubic }
Text {
anchors.centerIn: parent
text: "➔"
color: submitMouse.containsMouse ? "#ffffff" : Theme.accent
font.pixelSize: 18
font.weight: Font.Bold
} }
MouseArea { ListView {
id: submitMouse id: dotsView
anchors.fill: parent anchors.centerIn: parent
hoverEnabled: true width: Math.min(dotsContainer.implicitWidth, count * 26)
onClicked: LockscreenService.submitPassword() height: 20
orientation: ListView.Horizontal
spacing: 12
interactive: false
model: dotsModel
add: Transition {
ParallelAnimation {
NumberAnimation { property: "scale"; from: 0.1; to: 1.0; duration: 250; easing.type: Easing.OutBack; easing.overshoot: 1.6 }
NumberAnimation { property: "opacity"; from: 0.0; to: 1.0; duration: 200; easing.type: Easing.OutCubic }
}
}
remove: Transition {
ParallelAnimation {
NumberAnimation { property: "scale"; to: 0.0; duration: 180; easing.type: Easing.InBack }
NumberAnimation { property: "opacity"; to: 0.0; duration: 150; easing.type: Easing.OutCubic }
}
}
displaced: Transition {
NumberAnimation { properties: "x,y"; duration: 220; easing.type: Easing.OutCubic }
}
delegate: Item {
width: 14
height: 14
Rectangle {
id: dot
anchors.fill: parent
radius: 7
color: index === dotsModel.count - 1 ? Theme.accent : Theme.fg
Behavior on color { ColorAnimation { duration: 180 } }
// Inner Glow Core
Rectangle {
anchors.centerIn: parent
width: 6
height: 6
radius: 3
color: "#ffffff"
opacity: index === dotsModel.count - 1 ? 1.0 : 0.6
}
}
}
}
}
// Focus Click Area
MouseArea {
anchors.fill: parent
onClicked: {
root.forceActiveFocus()
secretInput.forceActiveFocus()
} }
} }
} }
// Dynamic Typing Status & Feedback Message // Dynamic Auth Error Feedback Message
RowLayout { RowLayout {
Layout.fillWidth: true Layout.fillWidth: true
visible: LockscreenService.authFailed visible: LockscreenService.authFailed
Item { Layout.fillWidth: true } Item { Layout.fillWidth: true }
// Auth Error Message Display
Text { Text {
text: LockscreenService.authErrorMsg text: LockscreenService.authErrorMsg
color: Theme.red color: Theme.red
font.pixelSize: 12 font.pixelSize: 12
font.weight: Font.Bold font.weight: Font.Bold
} }
Item { Layout.fillWidth: true }
} }
}
}
Item { Layout.preferredHeight: 14 }
// 4. Session Action Buttons (Power & Unlock)
RowLayout {
Layout.alignment: Qt.AlignHCenter
spacing: 16
// Suspend Button
Rectangle {
implicitWidth: 110
implicitHeight: 38
radius: 10
color: suspendMouse.containsMouse ? Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.15) : Qt.rgba(0, 0, 0, 0.3)
border.color: Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.15)
// Prominent, Large Session Action Buttons (Right underneath Password Input)
RowLayout { RowLayout {
anchors.centerIn: parent Layout.fillWidth: true
spacing: 6 spacing: 12
Text { text: "🌙"; font.pixelSize: 13 }
Text { text: "Sleep"; color: Theme.fg; font.pixelSize: 12; font.weight: Font.Medium }
}
MouseArea { // Suspend / Sleep Button
id: suspendMouse Rectangle {
anchors.fill: parent Layout.fillWidth: true
hoverEnabled: true implicitHeight: 48
onClicked: { radius: 12
Quickshell.execDetached(["systemctl", "suspend"]) color: suspendMouse.containsMouse ? Qt.rgba(Theme.accent.r, Theme.accent.g, Theme.accent.b, 0.25) : Qt.rgba(0, 0, 0, 0.3)
border.color: suspendMouse.containsMouse ? Theme.accent : Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.12)
Behavior on color { ColorAnimation { duration: 150 } }
Behavior on border.color { ColorAnimation { duration: 150 } }
RowLayout {
anchors.centerIn: parent
spacing: 8
Text { text: "🌙"; font.pixelSize: 16 }
Text { text: "Sleep"; color: Theme.fg; font.pixelSize: 14; font.weight: Font.SemiBold }
}
MouseArea {
id: suspendMouse
anchors.fill: parent
hoverEnabled: true
onClicked: Quickshell.execDetached(["systemctl", "suspend"])
}
} }
}
}
// Reboot Button // Reboot / Restart Button
Rectangle { Rectangle {
implicitWidth: 110 Layout.fillWidth: true
implicitHeight: 38 implicitHeight: 48
radius: 10 radius: 12
color: rebootMouse.containsMouse ? Qt.rgba(Theme.orange.r, Theme.orange.g, Theme.orange.b, 0.25) : Qt.rgba(0, 0, 0, 0.3) color: rebootMouse.containsMouse ? Qt.rgba(Theme.orange.r, Theme.orange.g, Theme.orange.b, 0.3) : Qt.rgba(0, 0, 0, 0.3)
border.color: Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.15) border.color: rebootMouse.containsMouse ? Theme.orange : Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.12)
RowLayout { Behavior on color { ColorAnimation { duration: 150 } }
anchors.centerIn: parent Behavior on border.color { ColorAnimation { duration: 150 } }
spacing: 6
Text { text: "🔄"; font.pixelSize: 13 }
Text { text: "Restart"; color: Theme.fg; font.pixelSize: 12; font.weight: Font.Medium }
}
MouseArea { RowLayout {
id: rebootMouse anchors.centerIn: parent
anchors.fill: parent spacing: 8
hoverEnabled: true Text { text: "🔄"; font.pixelSize: 16 }
onClicked: SessionService.reboot() Text { text: "Restart"; color: Theme.fg; font.pixelSize: 14; font.weight: Font.SemiBold }
} }
}
// Shutdown Button MouseArea {
Rectangle { id: rebootMouse
implicitWidth: 110 anchors.fill: parent
implicitHeight: 38 hoverEnabled: true
radius: 10 onClicked: SessionService.reboot()
color: powerMouse.containsMouse ? Qt.rgba(Theme.red.r, Theme.red.g, Theme.red.b, 0.25) : Qt.rgba(0, 0, 0, 0.3) }
border.color: Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.15) }
RowLayout { // Shutdown / Power Off Button
anchors.centerIn: parent Rectangle {
spacing: 6 Layout.fillWidth: true
Text { text: "⚡"; font.pixelSize: 13 } implicitHeight: 48
Text { text: "Power Off"; color: Theme.fg; font.pixelSize: 12; font.weight: Font.Medium } radius: 12
} color: powerMouse.containsMouse ? Qt.rgba(Theme.red.r, Theme.red.g, Theme.red.b, 0.3) : Qt.rgba(0, 0, 0, 0.3)
border.color: powerMouse.containsMouse ? Theme.red : Qt.rgba(Theme.fg.r, Theme.fg.g, Theme.fg.b, 0.12)
MouseArea { Behavior on color { ColorAnimation { duration: 150 } }
id: powerMouse Behavior on border.color { ColorAnimation { duration: 150 } }
anchors.fill: parent
hoverEnabled: true RowLayout {
onClicked: SessionService.shutdown() anchors.centerIn: parent
spacing: 8
Text { text: "⏻"; font.pixelSize: 16; color: Theme.red }
Text { text: "Power Off"; color: Theme.fg; font.pixelSize: 14; font.weight: Font.SemiBold }
}
MouseArea {
id: powerMouse
anchors.fill: parent
hoverEnabled: true
onClicked: SessionService.shutdown()
}
}
} }
} }
} }