diff --git a/Modules/LockScreen/LockScreen.qml b/Modules/LockScreen/LockScreen.qml index 563a17c..97e135c 100644 --- a/Modules/LockScreen/LockScreen.qml +++ b/Modules/LockScreen/LockScreen.qml @@ -11,727 +11,821 @@ import qs.Services import qs.Widgets WlSessionLock { - id: lock + id: lock - property string errorMessage: "" - property bool authenticating: false - property string password: "" - property bool pamAvailable: typeof PamContext !== "undefined" - locked: false + property string errorMessage: "" + property bool authenticating: false + property string password: "" + property bool pamAvailable: typeof PamContext !== "undefined" + locked: false - function unlockAttempt() { - console.log("Unlock attempt started"); - - // Real PAM authentication - if (!pamAvailable) { - lock.errorMessage = "PAM authentication not available."; - console.log("PAM not available"); - return; - } - if (!lock.password) { - lock.errorMessage = "Password required."; - console.log("No password entered"); - return; - } - console.log("Starting PAM authentication..."); - lock.authenticating = true; - lock.errorMessage = ""; + function unlockAttempt() { + console.log("Unlock attempt started") - console.log("[LockScreen] About to create PAM context with userName:", Quickshell.env("USER")); - var pam = Qt.createQmlObject('import Quickshell.Services.Pam; PamContext { config: "login"; user: "' + Quickshell.env("USER") + '" }', lock); - console.log("PamContext created", pam); + // Real PAM authentication + if (!pamAvailable) { + lock.errorMessage = "PAM authentication not available." + console.log("PAM not available") + return + } + if (!lock.password) { + lock.errorMessage = "Password required." + console.log("No password entered") + return + } + console.log("Starting PAM authentication...") + lock.authenticating = true + lock.errorMessage = "" - pam.onCompleted.connect(function (result) { - console.log("PAM completed with result:", result); - lock.authenticating = false; - if (result === PamResult.Success) { - console.log("Authentication successful, unlocking..."); - lock.locked = false; - lock.password = ""; - lock.errorMessage = ""; - } else { - console.log("Authentication failed"); - lock.errorMessage = "Authentication failed."; - lock.password = ""; - } - pam.destroy(); - }); + console.log("[LockScreen] About to create PAM context with userName:", Quickshell.env("USER")) + var pam = Qt.createQmlObject( + 'import Quickshell.Services.Pam; PamContext { config: "login"; user: "' + Quickshell.env("USER") + '" }', + lock) + console.log("PamContext created", pam) - pam.onError.connect(function (error) { - console.log("PAM error:", error); - lock.authenticating = false; - lock.errorMessage = pam.message || "Authentication error."; - lock.password = ""; - pam.destroy(); - }); + pam.onCompleted.connect(function (result) { + console.log("PAM completed with result:", result) + lock.authenticating = false + if (result === PamResult.Success) { + console.log("Authentication successful, unlocking...") + lock.locked = false + lock.password = "" + lock.errorMessage = "" + } else { + console.log("Authentication failed") + lock.errorMessage = "Authentication failed." + lock.password = "" + } + pam.destroy() + }) - pam.onPamMessage.connect(function () { - console.log("PAM message:", pam.message, "isError:", pam.messageIsError); - if (pam.messageIsError) { - lock.errorMessage = pam.message; - } - }); + pam.onError.connect(function (error) { + console.log("PAM error:", error) + lock.authenticating = false + lock.errorMessage = pam.message || "Authentication error." + lock.password = "" + pam.destroy() + }) - pam.onResponseRequiredChanged.connect(function () { - console.log("PAM response required:", pam.responseRequired); - if (pam.responseRequired && lock.authenticating) { - console.log("Responding to PAM with password"); - pam.respond(lock.password); - } - }); + pam.onPamMessage.connect(function () { + console.log("PAM message:", pam.message, "isError:", pam.messageIsError) + if (pam.messageIsError) { + lock.errorMessage = pam.message + } + }) - var started = pam.start(); - console.log("PAM start result:", started); + pam.onResponseRequiredChanged.connect(function () { + console.log("PAM response required:", pam.responseRequired) + if (pam.responseRequired && lock.authenticating) { + console.log("Responding to PAM with password") + pam.respond(lock.password) + } + }) + + var started = pam.start() + console.log("PAM start result:", started) + } + + WlSessionLockSurface { + // Wallpaper image + Image { + id: lockBgImage + anchors.fill: parent + fillMode: Image.PreserveAspectCrop + source: Wallpapers.currentWallpaper !== "" ? Wallpapers.currentWallpaper : "" + cache: true + smooth: true + mipmap: false } - WlSessionLockSurface { - // Wallpaper image - Image { - id: lockBgImage - anchors.fill: parent - fillMode: Image.PreserveAspectCrop - source: Wallpapers.currentWallpaper !== "" ? Wallpapers.currentWallpaper : "" - cache: true - smooth: true - mipmap: false + // Blurred background + Rectangle { + anchors.fill: parent + color: "transparent" + + // Simple blur effect + layer.enabled: true + layer.smooth: true + layer.samples: 4 + } + + // Animated gradient overlay + Rectangle { + anchors.fill: parent + gradient: Gradient { + GradientStop { + position: 0.0 + color: Qt.rgba(0, 0, 0, 0.6) + } + GradientStop { + position: 0.3 + color: Qt.rgba(0, 0, 0, 0.3) + } + GradientStop { + position: 0.7 + color: Qt.rgba(0, 0, 0, 0.4) + } + GradientStop { + position: 1.0 + color: Qt.rgba(0, 0, 0, 0.7) + } + } + + // Subtle animated particles + Repeater { + model: 20 + Rectangle { + width: Math.random() * 4 + 2 + height: width + radius: width * 0.5 + color: Qt.rgba(Colors.accentPrimary.r, Colors.accentPrimary.g, Colors.accentPrimary.b, 0.3) + x: Math.random() * parent.width + y: Math.random() * parent.height + + SequentialAnimation on opacity { + loops: Animation.Infinite + NumberAnimation { + to: 0.8 + duration: 2000 + Math.random() * 3000 + } + NumberAnimation { + to: 0.1 + duration: 2000 + Math.random() * 3000 + } + } + } + } + } + + // Main content - Centered design + Item { + anchors.fill: parent + + // Top section - Time, date, and user info + ColumnLayout { + anchors.top: parent.top + anchors.left: parent.left + anchors.right: parent.right + anchors.topMargin: 80 * Scaling.scale(screen) + spacing: 40 * Scaling.scale(screen) + + // Time display - Large and prominent with pulse animation + Column { + spacing: 8 * Scaling.scale(screen) + Layout.alignment: Qt.AlignHCenter + + Text { + id: timeText + text: Qt.formatDateTime(new Date(), "HH:mm") + font.family: "Inter" + font.pointSize: Style.fontSizeXXL * 6 + font.weight: Font.Bold + font.letterSpacing: -2 + color: Colors.textPrimary + horizontalAlignment: Text.AlignHCenter + + SequentialAnimation on scale { + loops: Animation.Infinite + NumberAnimation { + to: 1.02 + duration: 2000 + easing.type: Easing.InOutQuad + } + NumberAnimation { + to: 1.0 + duration: 2000 + easing.type: Easing.InOutQuad + } + } + } + + Text { + id: dateText + text: Qt.formatDateTime(new Date(), "dddd, MMMM d") + font.family: "Inter" + font.pointSize: Style.fontSizeXL + font.weight: Font.Light + color: Colors.textSecondary + horizontalAlignment: Text.AlignHCenter + width: timeText.width + } } - // Blurred background - Rectangle { - anchors.fill: parent + // User section with animated avatar + Column { + spacing: 16 * Scaling.scale(screen) + Layout.alignment: Qt.AlignHCenter + + // Animated avatar with glow effect + Rectangle { + width: 120 * Scaling.scale(screen) + height: 120 * Scaling.scale(screen) + radius: width * 0.5 color: "transparent" - - // Simple blur effect - layer.enabled: true - layer.smooth: true - layer.samples: 4 - } + border.color: Colors.accentPrimary + border.width: 3 * Scaling.scale(screen) + anchors.horizontalCenter: parent.horizontalCenter - // Animated gradient overlay - Rectangle { - anchors.fill: parent - gradient: Gradient { - GradientStop { position: 0.0; color: Qt.rgba(0, 0, 0, 0.6) } - GradientStop { position: 0.3; color: Qt.rgba(0, 0, 0, 0.3) } - GradientStop { position: 0.7; color: Qt.rgba(0, 0, 0, 0.4) } - GradientStop { position: 1.0; color: Qt.rgba(0, 0, 0, 0.7) } + // Glow effect + Rectangle { + anchors.centerIn: parent + width: parent.width + 24 * Scaling.scale(screen) + height: parent.height + 24 * Scaling.scale(screen) + radius: width * 0.5 + color: "transparent" + border.color: Qt.rgba(Colors.accentPrimary.r, Colors.accentPrimary.g, Colors.accentPrimary.b, 0.3) + border.width: 2 * Scaling.scale(screen) + z: -1 + + SequentialAnimation on scale { + loops: Animation.Infinite + NumberAnimation { + to: 1.1 + duration: 1500 + easing.type: Easing.InOutQuad + } + NumberAnimation { + to: 1.0 + duration: 1500 + easing.type: Easing.InOutQuad + } + } } - // Subtle animated particles - Repeater { + NImageRounded { + anchors.centerIn: parent + width: 100 * Scaling.scale(screen) + height: 100 * Scaling.scale(screen) + imagePath: Quickshell.env("HOME") + "/.face" + fallbackIcon: "person" + imageRadius: width * 0.5 + } + + // Hover animation + MouseArea { + anchors.fill: parent + hoverEnabled: true + onEntered: parent.scale = 1.05 + onExited: parent.scale = 1.0 + } + + Behavior on scale { + NumberAnimation { + duration: 200 + easing.type: Easing.OutBack + } + } + } + } + } + + // Centered terminal section + Item { + width: 720 * Scaling.scale(screen) + height: 280 * Scaling.scale(screen) + anchors.centerIn: parent + + ColumnLayout { + anchors.centerIn: parent + spacing: 20 * Scaling.scale(screen) + width: parent.width + + // Futuristic Terminal-Style Input + Item { + width: parent.width + height: 280 * Scaling.scale(screen) + Layout.fillWidth: true + + // Terminal background with scanlines + Rectangle { + id: terminalBackground + anchors.fill: parent + radius: 16 + color: Colors.applyOpacity(Colors.backgroundPrimary, "E6") + border.color: Colors.accentPrimary + border.width: 2 * Scaling.scale(screen) + + // Scanline effect + Repeater { model: 20 Rectangle { - width: Math.random() * 4 + 2 - height: width - radius: width * 0.5 - color: Qt.rgba(Colors.accentPrimary.r, Colors.accentPrimary.g, Colors.accentPrimary.b, 0.3) - x: Math.random() * parent.width - y: Math.random() * parent.height - - SequentialAnimation on opacity { - loops: Animation.Infinite - NumberAnimation { to: 0.8; duration: 2000 + Math.random() * 3000 } - NumberAnimation { to: 0.1; duration: 2000 + Math.random() * 3000 } + width: parent.width + height: 1 + color: Colors.applyOpacity(Colors.accentPrimary, "1A") + y: index * 10 + opacity: 0.3 + + SequentialAnimation on opacity { + loops: Animation.Infinite + NumberAnimation { + to: 0.6 + duration: 2000 + Math.random() * 1000 } + NumberAnimation { + to: 0.1 + duration: 2000 + Math.random() * 1000 + } + } } - } - } + } - // Main content - Centered design - Item { - anchors.fill: parent + // Terminal header + Rectangle { + width: parent.width + height: 40 * Scaling.scale(screen) + color: Colors.applyOpacity(Colors.accentPrimary, "33") + topLeftRadius: 14 + topRightRadius: 14 - // Top section - Time, date, and user info - ColumnLayout { + RowLayout { + anchors.fill: parent + anchors.margins: 12 * Scaling.scale(screen) + spacing: 12 * Scaling.scale(screen) + + Text { + text: "●" + color: Colors.error + font.pixelSize: 16 * Scaling.scale(screen) + } + + Text { + text: "●" + color: Colors.warning + font.pixelSize: 16 * Scaling.scale(screen) + } + + Text { + text: "●" + color: Colors.accentPrimary + font.pixelSize: 16 * Scaling.scale(screen) + } + + Text { + text: "SECURE TERMINAL" + color: Colors.textPrimary + font.family: "DejaVu Sans Mono" + font.pointSize: Style.fontSizeLarge + font.weight: Font.Bold + Layout.fillWidth: true + } + } + } + + // Terminal content area + ColumnLayout { anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right - anchors.topMargin: 80 * Scaling.scale(screen) - spacing: 40 * Scaling.scale(screen) + anchors.bottom: parent.bottom + anchors.topMargin: 70 * Scaling.scale(screen) + anchors.margins: 12 * Scaling.scale(screen) + spacing: 12 * Scaling.scale(screen) - // Time display - Large and prominent with pulse animation - Column { - spacing: 8 * Scaling.scale(screen) - Layout.alignment: Qt.AlignHCenter + // Welcome back typing effect + RowLayout { + Layout.fillWidth: true + spacing: 12 * Scaling.scale(screen) - Text { - id: timeText - text: Qt.formatDateTime(new Date(), "HH:mm") - font.family: "Inter" - font.pointSize: Style.fontSizeXXL * 6 - font.weight: Font.Bold - font.letterSpacing: -2 - color: Colors.textPrimary - horizontalAlignment: Text.AlignHCenter + Text { + text: "root@noctalia:~$" + color: Colors.accentPrimary + font.family: "DejaVu Sans Mono" + font.pointSize: Style.fontSizeLarge + font.weight: Font.Bold + } - SequentialAnimation on scale { - loops: Animation.Infinite - NumberAnimation { to: 1.02; duration: 2000; easing.type: Easing.InOutQuad } - NumberAnimation { to: 1.0; duration: 2000; easing.type: Easing.InOutQuad } + Text { + id: welcomeText + text: "" + color: Colors.textPrimary + font.family: "DejaVu Sans Mono" + font.pointSize: Style.fontSizeLarge + property int currentIndex: 0 + property string fullText: "Welcome back, " + Quickshell.env("USER") + "!" + + Timer { + interval: 100 + running: true + repeat: true + onTriggered: { + if (parent.currentIndex < parent.fullText.length) { + parent.text = parent.fullText.substring(0, parent.currentIndex + 1) + parent.currentIndex++ + } else { + running = false } + } } - - Text { - id: dateText - text: Qt.formatDateTime(new Date(), "dddd, MMMM d") - font.family: "Inter" - font.pointSize: Style.fontSizeXL - font.weight: Font.Light - color: Colors.textSecondary - horizontalAlignment: Text.AlignHCenter - width: timeText.width - } + } } - // User section with animated avatar - Column { - spacing: 16 * Scaling.scale(screen) - Layout.alignment: Qt.AlignHCenter + // Command line with integrated password input + RowLayout { + Layout.fillWidth: true + spacing: 12 * Scaling.scale(screen) - // Animated avatar with glow effect - Rectangle { - width: 120 * Scaling.scale(screen) - height: 120 * Scaling.scale(screen) - radius: width * 0.5 - color: "transparent" - border.color: Colors.accentPrimary - border.width: 3 * Scaling.scale(screen) - anchors.horizontalCenter: parent.horizontalCenter + Text { + text: "root@noctalia:~$" + color: Colors.accentPrimary + font.family: "DejaVu Sans Mono" + font.pointSize: Style.fontSizeLarge + font.weight: Font.Bold + } - // Glow effect - Rectangle { - anchors.centerIn: parent - width: parent.width + 24 * Scaling.scale(screen) - height: parent.height + 24 * Scaling.scale(screen) - radius: width * 0.5 - color: "transparent" - border.color: Qt.rgba(Colors.accentPrimary.r, Colors.accentPrimary.g, Colors.accentPrimary.b, 0.3) - border.width: 2 * Scaling.scale(screen) - z: -1 + Text { + text: "sudo unlock_session" + color: Colors.textPrimary + font.family: "DejaVu Sans Mono" + font.pointSize: Style.fontSizeLarge + } - SequentialAnimation on scale { - loops: Animation.Infinite - NumberAnimation { to: 1.1; duration: 1500; easing.type: Easing.InOutQuad } - NumberAnimation { to: 1.0; duration: 1500; easing.type: Easing.InOutQuad } - } - } + // Integrated password input (invisible, just for functionality) + TextInput { + id: passwordInput + width: 0 + height: 0 + visible: false + font.family: "DejaVu Sans Mono" + font.pointSize: Style.fontSizeLarge + color: Colors.textPrimary + echoMode: TextInput.Password + passwordCharacter: "*" + passwordMaskDelay: 0 - NImageRounded { - anchors.centerIn: parent - width: 100 * Scaling.scale(screen) - height: 100 * Scaling.scale(screen) - imagePath: Quickshell.env("HOME") + "/.face" - fallbackIcon: "person" - imageRadius: width * 0.5 - } - - // Hover animation - MouseArea { - anchors.fill: parent - hoverEnabled: true - onEntered: parent.scale = 1.05 - onExited: parent.scale = 1.0 - } - - Behavior on scale { - NumberAnimation { duration: 200; easing.type: Easing.OutBack } - } + text: lock.password + onTextChanged: { + lock.password = text + // Terminal typing sound effect (visual) + typingEffect.start() } - - } - } - - // Centered terminal section - Item { - width: 720 * Scaling.scale(screen) - height: 280 * Scaling.scale(screen) - anchors.centerIn: parent - - ColumnLayout { - anchors.centerIn: parent - spacing: 20 * Scaling.scale(screen) - width: parent.width - - - - // Futuristic Terminal-Style Input - Item { - width: parent.width - height: 280 * Scaling.scale(screen) - Layout.fillWidth: true - - // Terminal background with scanlines - Rectangle { - id: terminalBackground - anchors.fill: parent - radius: 16 - color: Colors.applyOpacity(Colors.backgroundPrimary, "E6") - border.color: Colors.accentPrimary - border.width: 2 * Scaling.scale(screen) - - // Scanline effect - Repeater { - model: 20 - Rectangle { - width: parent.width - height: 1 - color: Colors.applyOpacity(Colors.accentPrimary, "1A") - y: index * 10 - opacity: 0.3 - - SequentialAnimation on opacity { - loops: Animation.Infinite - NumberAnimation { to: 0.6; duration: 2000 + Math.random() * 1000 } - NumberAnimation { to: 0.1; duration: 2000 + Math.random() * 1000 } - } - } - } - - // Terminal header - Rectangle { - width: parent.width - height: 40 * Scaling.scale(screen) - color: Colors.applyOpacity(Colors.accentPrimary, "33") - topLeftRadius: 14 - topRightRadius: 14 - - RowLayout { - anchors.fill: parent - anchors.margins: 12 * Scaling.scale(screen) - spacing: 12 * Scaling.scale(screen) - - Text { - text: "●" - color: Colors.error - font.pixelSize: 16 * Scaling.scale(screen) - } - - Text { - text: "●" - color: Colors.warning - font.pixelSize: 16 * Scaling.scale(screen) - } - - Text { - text: "●" - color: Colors.accentPrimary - font.pixelSize: 16 * Scaling.scale(screen) - } - - Text { - text: "SECURE TERMINAL" - color: Colors.textPrimary - font.family: "DejaVu Sans Mono" - font.pointSize: Style.fontSizeLarge - font.weight: Font.Bold - Layout.fillWidth: true - } - } - } - - // Terminal content area - ColumnLayout { - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.topMargin: 70 * Scaling.scale(screen) - anchors.margins: 12 * Scaling.scale(screen) - spacing: 12 * Scaling.scale(screen) - - // Welcome back typing effect - RowLayout { - Layout.fillWidth: true - spacing: 12 * Scaling.scale(screen) - - Text { - text: "root@noctalia:~$" - color: Colors.accentPrimary - font.family: "DejaVu Sans Mono" - font.pointSize: Style.fontSizeLarge - font.weight: Font.Bold - } - - Text { - id: welcomeText - text: "" - color: Colors.textPrimary - font.family: "DejaVu Sans Mono" - font.pointSize: Style.fontSizeLarge - property int currentIndex: 0 - property string fullText: "Welcome back, " + Quickshell.env("USER") + "!" - - Timer { - interval: 100 - running: true - repeat: true - onTriggered: { - if (parent.currentIndex < parent.fullText.length) { - parent.text = parent.fullText.substring(0, parent.currentIndex + 1) - parent.currentIndex++ - } else { - running = false - } - } - } - } - } - - // Command line with integrated password input - RowLayout { - Layout.fillWidth: true - spacing: 12 * Scaling.scale(screen) - - Text { - text: "root@noctalia:~$" - color: Colors.accentPrimary - font.family: "DejaVu Sans Mono" - font.pointSize: Style.fontSizeLarge - font.weight: Font.Bold - } - - Text { - text: "sudo unlock_session" - color: Colors.textPrimary - font.family: "DejaVu Sans Mono" - font.pointSize: Style.fontSizeLarge - } - - // Integrated password input (invisible, just for functionality) - TextInput { - id: passwordInput - width: 0 - height: 0 - visible: false - font.family: "DejaVu Sans Mono" - font.pointSize: Style.fontSizeLarge - color: Colors.textPrimary - echoMode: TextInput.Password - passwordCharacter: "*" - passwordMaskDelay: 0 - - text: lock.password - onTextChanged: { - lock.password = text - // Terminal typing sound effect (visual) - typingEffect.start() - } - - Keys.onPressed: function (event) { - if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { - lock.unlockAttempt(); - } - } - - Component.onCompleted: { - forceActiveFocus(); - } - } - - // Visual password display with integrated cursor - Text { - id: asterisksText - text: "*".repeat(passwordInput.text.length) - color: Colors.textPrimary - font.family: "DejaVu Sans Mono" - font.pointSize: Style.fontSizeLarge - visible: passwordInput.activeFocus - - // Typing effect animation - SequentialAnimation { - id: typingEffect - NumberAnimation { - target: passwordInput - property: "scale" - to: 1.01 - duration: 50 - } - NumberAnimation { - target: passwordInput - property: "scale" - to: 1.0 - duration: 50 - } - } - } - - // Blinking cursor positioned right after the asterisks - Rectangle { - width: 8 * Scaling.scale(screen) - height: 20 * Scaling.scale(screen) - color: Colors.accentPrimary - visible: passwordInput.activeFocus - anchors.left: asterisksText.right - anchors.leftMargin: 2 * Scaling.scale(screen) - anchors.verticalCenter: asterisksText.verticalCenter - - SequentialAnimation on opacity { - loops: Animation.Infinite - NumberAnimation { to: 1.0; duration: 500 } - NumberAnimation { to: 0.0; duration: 500 } - } - } - } - - // Status messages - Text { - text: lock.authenticating ? "Authenticating..." : (lock.errorMessage !== "" ? "Authentication failed." : "") - color: lock.authenticating ? Colors.accentPrimary : (lock.errorMessage !== "" ? Colors.error : "transparent") - font.family: "DejaVu Sans Mono" - font.pointSize: Style.fontSizeLarge - Layout.fillWidth: true - - SequentialAnimation on opacity { - running: lock.authenticating - loops: Animation.Infinite - NumberAnimation { to: 1.0; duration: 800 } - NumberAnimation { to: 0.5; duration: 800 } - } - } - - // Execute button - Rectangle { - width: 120 * Scaling.scale(screen) - height: 40 * Scaling.scale(screen) - radius: 12 - color: executeButtonArea.containsMouse ? Colors.accentPrimary : Colors.applyOpacity(Colors.accentPrimary, "33") - border.color: Colors.accentPrimary - border.width: 1 - enabled: !lock.authenticating - Layout.alignment: Qt.AlignRight - - Text { - anchors.centerIn: parent - text: lock.authenticating ? "EXECUTING..." : "EXECUTE" - color: executeButtonArea.containsMouse ? Colors.onAccent : Colors.accentPrimary - font.family: "DejaVu Sans Mono" - font.pointSize: Style.fontSizeMedium - font.weight: Font.Bold - } - - MouseArea { - id: executeButtonArea - anchors.fill: parent - hoverEnabled: true - onClicked: lock.unlockAttempt() - - SequentialAnimation on scale { - running: containsMouse - NumberAnimation { to: 1.05; duration: 150; easing.type: Easing.OutCubic } - } - - SequentialAnimation on scale { - running: !containsMouse - NumberAnimation { to: 1.0; duration: 150; easing.type: Easing.OutCubic } - } - } - - // Processing animation - SequentialAnimation on scale { - loops: Animation.Infinite - running: lock.authenticating - NumberAnimation { to: 1.02; duration: 600; easing.type: Easing.InOutQuad } - NumberAnimation { to: 1.0; duration: 600; easing.type: Easing.InOutQuad } - } - } - } - - // Terminal glow effect - Rectangle { - anchors.fill: parent - radius: parent.radius - color: "transparent" - border.color: Colors.applyOpacity(Colors.accentPrimary, "4D") - border.width: 1 - z: -1 - - SequentialAnimation on opacity { - loops: Animation.Infinite - NumberAnimation { to: 0.6; duration: 2000; easing.type: Easing.InOutQuad } - NumberAnimation { to: 0.2; duration: 2000; easing.type: Easing.InOutQuad } - } - } - } - + Keys.onPressed: function (event) { + if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { + lock.unlockAttempt() + } } + Component.onCompleted: { + forceActiveFocus() + } + } + // Visual password display with integrated cursor + Text { + id: asterisksText + text: "*".repeat(passwordInput.text.length) + color: Colors.textPrimary + font.family: "DejaVu Sans Mono" + font.pointSize: Style.fontSizeLarge + visible: passwordInput.activeFocus + // Typing effect animation + SequentialAnimation { + id: typingEffect + NumberAnimation { + target: passwordInput + property: "scale" + to: 1.01 + duration: 50 + } + NumberAnimation { + target: passwordInput + property: "scale" + to: 1.0 + duration: 50 + } + } + } + // Blinking cursor positioned right after the asterisks + Rectangle { + width: 8 * Scaling.scale(screen) + height: 20 * Scaling.scale(screen) + color: Colors.accentPrimary + visible: passwordInput.activeFocus + anchors.left: asterisksText.right + anchors.leftMargin: 2 * Scaling.scale(screen) + anchors.verticalCenter: asterisksText.verticalCenter + + SequentialAnimation on opacity { + loops: Animation.Infinite + NumberAnimation { + to: 1.0 + duration: 500 + } + NumberAnimation { + to: 0.0 + duration: 500 + } + } + } } - } - } + // Status messages + Text { + text: lock.authenticating ? "Authenticating..." : (lock.errorMessage !== "" ? "Authentication failed." : "") + color: lock.authenticating ? Colors.accentPrimary : (lock.errorMessage !== "" ? Colors.error : "transparent") + font.family: "DejaVu Sans Mono" + font.pointSize: Style.fontSizeLarge + Layout.fillWidth: true + SequentialAnimation on opacity { + running: lock.authenticating + loops: Animation.Infinite + NumberAnimation { + to: 1.0 + duration: 800 + } + NumberAnimation { + to: 0.5 + duration: 800 + } + } + } - // Enhanced power buttons with hover effects - Row { - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.margins: 50 * Scaling.scale(screen) - spacing: 20 * Scaling.scale(screen) - - // Shutdown with enhanced styling - Rectangle { - width: 64 * Scaling.scale(screen) - height: 64 * Scaling.scale(screen) - radius: 32 - color: Qt.rgba(Colors.error.r, Colors.error.g, Colors.error.b, shutdownArea.containsMouse ? 0.9 : 0.2) - border.color: Colors.error - border.width: 2 * Scaling.scale(screen) - - // Glow effect + // Execute button Rectangle { + width: 120 * Scaling.scale(screen) + height: 40 * Scaling.scale(screen) + radius: 12 + color: executeButtonArea.containsMouse ? Colors.accentPrimary : Colors.applyOpacity( + Colors.accentPrimary, "33") + border.color: Colors.accentPrimary + border.width: 1 + enabled: !lock.authenticating + Layout.alignment: Qt.AlignRight + + Text { anchors.centerIn: parent - width: parent.width + 10 * Scaling.scale(screen) - height: parent.height + 10 * Scaling.scale(screen) - radius: width * 0.5 - color: "transparent" - border.color: Qt.rgba(Colors.error.r, Colors.error.g, Colors.error.b, 0.3) - border.width: 2 * Scaling.scale(screen) - opacity: shutdownArea.containsMouse ? 1 : 0 - z: -1 + text: lock.authenticating ? "EXECUTING..." : "EXECUTE" + color: executeButtonArea.containsMouse ? Colors.onAccent : Colors.accentPrimary + font.family: "DejaVu Sans Mono" + font.pointSize: Style.fontSizeMedium + font.weight: Font.Bold + } - Behavior on opacity { - NumberAnimation { duration: 200; easing.type: Easing.OutCubic } - } - } - - MouseArea { - id: shutdownArea + MouseArea { + id: executeButtonArea anchors.fill: parent hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onClicked: { - Qt.createQmlObject('import Quickshell.Io; Process { command: ["shutdown", "-h", "now"]; running: true }', lock); + onClicked: lock.unlockAttempt() + + SequentialAnimation on scale { + running: containsMouse + NumberAnimation { + to: 1.05 + duration: 150 + easing.type: Easing.OutCubic + } } - } - Text { - anchors.centerIn: parent - text: "power_settings_new" - font.family: "Material Symbols Outlined" - font.pixelSize: 28 * Scaling.scale(screen) - color: shutdownArea.containsMouse ? Colors.onAccent : Colors.error - } + SequentialAnimation on scale { + running: !containsMouse + NumberAnimation { + to: 1.0 + duration: 150 + easing.type: Easing.OutCubic + } + } + } - Behavior on color { - ColorAnimation { duration: 200; easing.type: Easing.OutCubic } + // Processing animation + SequentialAnimation on scale { + loops: Animation.Infinite + running: lock.authenticating + NumberAnimation { + to: 1.02 + duration: 600 + easing.type: Easing.InOutQuad + } + NumberAnimation { + to: 1.0 + duration: 600 + easing.type: Easing.InOutQuad + } + } } - scale: shutdownArea.containsMouse ? 1.1 : 1.0 - } - - // Reboot with enhanced styling - Rectangle { - width: 64 * Scaling.scale(screen) - height: 64 * Scaling.scale(screen) - radius: 32 - color: Qt.rgba(Colors.accentPrimary.r, Colors.accentPrimary.g, Colors.accentPrimary.b, rebootArea.containsMouse ? 0.9 : 0.2) - border.color: Colors.accentPrimary - border.width: 2 * Scaling.scale(screen) - - // Glow effect - Rectangle { - anchors.centerIn: parent - width: parent.width + 10 * Scaling.scale(screen) - height: parent.height + 10 * Scaling.scale(screen) - radius: width * 0.5 - color: "transparent" - border.color: Qt.rgba(Colors.accentPrimary.r, Colors.accentPrimary.g, Colors.accentPrimary.b, 0.3) - border.width: 2 * Scaling.scale(screen) - opacity: rebootArea.containsMouse ? 1 : 0 - z: -1 - - Behavior on opacity { - NumberAnimation { duration: 200; easing.type: Easing.OutCubic } - } - } - - MouseArea { - id: rebootArea - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onClicked: { - Qt.createQmlObject('import Quickshell.Io; Process { command: ["reboot"]; running: true }', lock); - } - } - - Text { - anchors.centerIn: parent - text: "refresh" - font.family: "Material Symbols Outlined" - font.pixelSize: 28 * Scaling.scale(screen) - color: rebootArea.containsMouse ? Colors.onAccent : Colors.accentPrimary - } - - Behavior on color { - ColorAnimation { duration: 200; easing.type: Easing.OutCubic } - } - scale: rebootArea.containsMouse ? 1.1 : 1.0 - } - - // Logout with enhanced styling - Rectangle { - width: 64 * Scaling.scale(screen) - height: 64 * Scaling.scale(screen) - radius: 32 - color: Qt.rgba(Colors.accentSecondary.r, Colors.accentSecondary.g, Colors.accentSecondary.b, logoutArea.containsMouse ? 0.9 : 0.2) - border.color: Colors.accentSecondary - border.width: 2 * Scaling.scale(screen) - - // Glow effect - Rectangle { - anchors.centerIn: parent - width: parent.width + 10 * Scaling.scale(screen) - height: parent.height + 10 * Scaling.scale(screen) - radius: width * 0.5 - color: "transparent" - border.color: Qt.rgba(Colors.accentSecondary.r, Colors.accentSecondary.g, Colors.accentSecondary.b, 0.3) - border.width: 2 * Scaling.scale(screen) - opacity: logoutArea.containsMouse ? 1 : 0 - z: -1 - - Behavior on opacity { - NumberAnimation { duration: 200; easing.type: Easing.OutCubic } - } - } - - MouseArea { - id: logoutArea - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onClicked: { - Qt.createQmlObject('import Quickshell.Io; Process { command: ["loginctl", "terminate-user", "' + Quickshell.env("USER") + '"]; running: true }', lock); - } - } - - Text { - anchors.centerIn: parent - text: "exit_to_app" - font.family: "Material Symbols Outlined" - font.pixelSize: 28 * Scaling.scale(screen) - color: logoutArea.containsMouse ? Colors.onAccent : Colors.accentSecondary - } - - Behavior on color { - ColorAnimation { duration: 200; easing.type: Easing.OutCubic } - } - scale: logoutArea.containsMouse ? 1.1 : 1.0 - } - } - - // Timer for updating time - Timer { - interval: 1000 - running: true - repeat: true - onTriggered: { - timeText.text = Qt.formatDateTime(new Date(), "HH:mm"); - dateText.text = Qt.formatDateTime(new Date(), "dddd, MMMM d"); + } + + // Terminal glow effect + Rectangle { + anchors.fill: parent + radius: parent.radius + color: "transparent" + border.color: Colors.applyOpacity(Colors.accentPrimary, "4D") + border.width: 1 + z: -1 + + SequentialAnimation on opacity { + loops: Animation.Infinite + NumberAnimation { + to: 0.6 + duration: 2000 + easing.type: Easing.InOutQuad + } + NumberAnimation { + to: 0.2 + duration: 2000 + easing.type: Easing.InOutQuad + } + } + } } + } } + } } + + // Enhanced power buttons with hover effects + Row { + anchors.right: parent.right + anchors.bottom: parent.bottom + anchors.margins: 50 * Scaling.scale(screen) + spacing: 20 * Scaling.scale(screen) + + // Shutdown with enhanced styling + Rectangle { + width: 64 * Scaling.scale(screen) + height: 64 * Scaling.scale(screen) + radius: 32 + color: Qt.rgba(Colors.error.r, Colors.error.g, Colors.error.b, shutdownArea.containsMouse ? 0.9 : 0.2) + border.color: Colors.error + border.width: 2 * Scaling.scale(screen) + + // Glow effect + Rectangle { + anchors.centerIn: parent + width: parent.width + 10 * Scaling.scale(screen) + height: parent.height + 10 * Scaling.scale(screen) + radius: width * 0.5 + color: "transparent" + border.color: Qt.rgba(Colors.error.r, Colors.error.g, Colors.error.b, 0.3) + border.width: 2 * Scaling.scale(screen) + opacity: shutdownArea.containsMouse ? 1 : 0 + z: -1 + + Behavior on opacity { + NumberAnimation { + duration: 200 + easing.type: Easing.OutCubic + } + } + } + + MouseArea { + id: shutdownArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + Qt.createQmlObject('import Quickshell.Io; Process { command: ["shutdown", "-h", "now"]; running: true }', + lock) + } + } + + Text { + anchors.centerIn: parent + text: "power_settings_new" + font.family: "Material Symbols Outlined" + font.pixelSize: 28 * Scaling.scale(screen) + color: shutdownArea.containsMouse ? Colors.onAccent : Colors.error + } + + Behavior on color { + ColorAnimation { + duration: 200 + easing.type: Easing.OutCubic + } + } + scale: shutdownArea.containsMouse ? 1.1 : 1.0 + } + + // Reboot with enhanced styling + Rectangle { + width: 64 * Scaling.scale(screen) + height: 64 * Scaling.scale(screen) + radius: 32 + color: Qt.rgba(Colors.accentPrimary.r, Colors.accentPrimary.g, Colors.accentPrimary.b, + rebootArea.containsMouse ? 0.9 : 0.2) + border.color: Colors.accentPrimary + border.width: 2 * Scaling.scale(screen) + + // Glow effect + Rectangle { + anchors.centerIn: parent + width: parent.width + 10 * Scaling.scale(screen) + height: parent.height + 10 * Scaling.scale(screen) + radius: width * 0.5 + color: "transparent" + border.color: Qt.rgba(Colors.accentPrimary.r, Colors.accentPrimary.g, Colors.accentPrimary.b, 0.3) + border.width: 2 * Scaling.scale(screen) + opacity: rebootArea.containsMouse ? 1 : 0 + z: -1 + + Behavior on opacity { + NumberAnimation { + duration: 200 + easing.type: Easing.OutCubic + } + } + } + + MouseArea { + id: rebootArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + Qt.createQmlObject('import Quickshell.Io; Process { command: ["reboot"]; running: true }', lock) + } + } + + Text { + anchors.centerIn: parent + text: "refresh" + font.family: "Material Symbols Outlined" + font.pixelSize: 28 * Scaling.scale(screen) + color: rebootArea.containsMouse ? Colors.onAccent : Colors.accentPrimary + } + + Behavior on color { + ColorAnimation { + duration: 200 + easing.type: Easing.OutCubic + } + } + scale: rebootArea.containsMouse ? 1.1 : 1.0 + } + + // Logout with enhanced styling + Rectangle { + width: 64 * Scaling.scale(screen) + height: 64 * Scaling.scale(screen) + radius: 32 + color: Qt.rgba(Colors.accentSecondary.r, Colors.accentSecondary.g, Colors.accentSecondary.b, + logoutArea.containsMouse ? 0.9 : 0.2) + border.color: Colors.accentSecondary + border.width: 2 * Scaling.scale(screen) + + // Glow effect + Rectangle { + anchors.centerIn: parent + width: parent.width + 10 * Scaling.scale(screen) + height: parent.height + 10 * Scaling.scale(screen) + radius: width * 0.5 + color: "transparent" + border.color: Qt.rgba(Colors.accentSecondary.r, Colors.accentSecondary.g, Colors.accentSecondary.b, 0.3) + border.width: 2 * Scaling.scale(screen) + opacity: logoutArea.containsMouse ? 1 : 0 + z: -1 + + Behavior on opacity { + NumberAnimation { + duration: 200 + easing.type: Easing.OutCubic + } + } + } + + MouseArea { + id: logoutArea + anchors.fill: parent + hoverEnabled: true + cursorShape: Qt.PointingHandCursor + onClicked: { + Qt.createQmlObject( + 'import Quickshell.Io; Process { command: ["loginctl", "terminate-user", "' + Quickshell.env( + "USER") + '"]; running: true }', lock) + } + } + + Text { + anchors.centerIn: parent + text: "exit_to_app" + font.family: "Material Symbols Outlined" + font.pixelSize: 28 * Scaling.scale(screen) + color: logoutArea.containsMouse ? Colors.onAccent : Colors.accentSecondary + } + + Behavior on color { + ColorAnimation { + duration: 200 + easing.type: Easing.OutCubic + } + } + scale: logoutArea.containsMouse ? 1.1 : 1.0 + } + } + + // Timer for updating time + Timer { + interval: 1000 + running: true + repeat: true + onTriggered: { + timeText.text = Qt.formatDateTime(new Date(), "HH:mm") + dateText.text = Qt.formatDateTime(new Date(), "dddd, MMMM d") + } + } + } } diff --git a/Modules/Lockscreen/Lockscreen.qml b/Modules/Lockscreen/Lockscreen.qml deleted file mode 100644 index 31fc7e8..0000000 --- a/Modules/Lockscreen/Lockscreen.qml +++ /dev/null @@ -1,912 +0,0 @@ -import QtQuick -import QtQuick.Layouts -import QtQuick.Controls -import QtQuick.Effects -import Quickshell -import Quickshell.Wayland -import Quickshell.Services.Pam -import Quickshell.Io -import Quickshell.Widgets -import qs.Services -import qs.Widgets - -WlSessionLock { - id: lock - - property string errorMessage: "" - property bool authenticating: false - property string password: "" - property bool pamAvailable: typeof PamContext !== "undefined" - property bool demoMode: true - property string demoPassword: "lysec123" - property int demoStep: 0 - locked: false - - // Demo timer for automatic interaction - Timer { - id: demoTimer - interval: 2000 - running: demoMode && locked - repeat: true - onTriggered: { - if (demoStep === 0) { - // Start typing demo password - lock.password = "" - demoStep = 1 - interval = 150 - } else if (demoStep === 1) { - // Type each character - if (lock.password.length < demoPassword.length) { - lock.password += demoPassword.charAt(lock.password.length) - } else { - demoStep = 2 - interval = 1000 - } - } else if (demoStep === 2) { - // Simulate authentication - lock.authenticating = true - demoStep = 3 - interval = 2000 - } else if (demoStep === 4) { - // Reset for next demo - lock.locked = false - demoStep = 0 - interval = 3000 - } - } - } - - // Demo authentication simulation - Timer { - id: authSimulation - interval: 2000 - running: false - onTriggered: { - lock.authenticating = false - if (lock.password === demoPassword) { - // Success - unlock - lock.locked = false - lock.password = "" - lock.errorMessage = "" - demoStep = 4 - demoTimer.interval = 1000 - } else { - // Error - lock.errorMessage = "Authentication failed" - lock.password = "" - demoStep = 0 - demoTimer.interval = 2000 - } - } - } - - function unlockAttempt() { - console.log("Unlock attempt started"); - - // Demo mode handling - if (demoMode) { - if (lock.authenticating) return - - lock.authenticating = true - authSimulation.start() - return - } - - // Real PAM authentication - if (!pamAvailable) { - lock.errorMessage = "PAM authentication not available."; - console.log("PAM not available"); - return; - } - if (!lock.password) { - lock.errorMessage = "Password required."; - console.log("No password entered"); - return; - } - console.log("Starting PAM authentication..."); - lock.authenticating = true; - lock.errorMessage = ""; - - console.log("[LockScreen] About to create PAM context with userName:", Quickshell.env("USER")); - var pam = Qt.createQmlObject('import Quickshell.Services.Pam; PamContext { config: "login"; user: "' + Quickshell.env("USER") + '" }', lock); - console.log("PamContext created", pam); - - pam.onCompleted.connect(function (result) { - console.log("PAM completed with result:", result); - lock.authenticating = false; - if (result === PamResult.Success) { - console.log("Authentication successful, unlocking..."); - lock.locked = false; - lock.password = ""; - lock.errorMessage = ""; - } else { - console.log("Authentication failed"); - lock.errorMessage = "Authentication failed."; - lock.password = ""; - } - pam.destroy(); - }); - - pam.onError.connect(function (error) { - console.log("PAM error:", error); - lock.authenticating = false; - lock.errorMessage = pam.message || "Authentication error."; - lock.password = ""; - pam.destroy(); - }); - - pam.onPamMessage.connect(function () { - console.log("PAM message:", pam.message, "isError:", pam.messageIsError); - if (pam.messageIsError) { - lock.errorMessage = pam.message; - } - }); - - pam.onResponseRequiredChanged.connect(function () { - console.log("PAM response required:", pam.responseRequired); - if (pam.responseRequired && lock.authenticating) { - console.log("Responding to PAM with password"); - pam.respond(lock.password); - } - }); - - var started = pam.start(); - console.log("PAM start result:", started); - } - - WlSessionLockSurface { - // Wallpaper image - Image { - id: lockBgImage - anchors.fill: parent - fillMode: Image.PreserveAspectCrop - source: Wallpapers.currentWallpaper !== "" ? Wallpapers.currentWallpaper : "" - cache: true - smooth: true - mipmap: false - } - - // Blurred background - Rectangle { - anchors.fill: parent - color: "transparent" - - // Simple blur effect - layer.enabled: true - layer.smooth: true - layer.samples: 4 - } - - // Animated gradient overlay - Rectangle { - anchors.fill: parent - gradient: Gradient { - GradientStop { position: 0.0; color: Qt.rgba(0, 0, 0, 0.6) } - GradientStop { position: 0.3; color: Qt.rgba(0, 0, 0, 0.3) } - GradientStop { position: 0.7; color: Qt.rgba(0, 0, 0, 0.4) } - GradientStop { position: 1.0; color: Qt.rgba(0, 0, 0, 0.7) } - } - - // Subtle animated particles - Repeater { - model: 20 - Rectangle { - width: Math.random() * 4 + 2 - height: width - radius: width * 0.5 - color: Qt.rgba(Colors.accentPrimary.r, Colors.accentPrimary.g, Colors.accentPrimary.b, 0.3) - x: Math.random() * parent.width - y: Math.random() * parent.height - - SequentialAnimation on opacity { - loops: Animation.Infinite - NumberAnimation { to: 0.8; duration: 2000 + Math.random() * 3000 } - NumberAnimation { to: 0.1; duration: 2000 + Math.random() * 3000 } - } - } - } - } - - // Main content - Centered design - Item { - anchors.fill: parent - - // Top section - Time, date, and user info - ColumnLayout { - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - anchors.topMargin: 80 * Scaling.scale(screen) - spacing: 40 * Scaling.scale(screen) - - // Time display - Large and prominent with pulse animation - Column { - spacing: 8 * Scaling.scale(screen) - Layout.alignment: Qt.AlignHCenter - - Text { - id: timeText - text: Qt.formatDateTime(new Date(), "HH:mm") - font.family: "Inter" - font.pixelSize: 140 * Scaling.scale(screen) - font.weight: Font.Bold - font.letterSpacing: -2 - color: Colors.textPrimary - horizontalAlignment: Text.AlignHCenter - - SequentialAnimation on scale { - loops: Animation.Infinite - NumberAnimation { to: 1.02; duration: 2000; easing.type: Easing.InOutQuad } - NumberAnimation { to: 1.0; duration: 2000; easing.type: Easing.InOutQuad } - } - } - - Text { - id: dateText - text: Qt.formatDateTime(new Date(), "dddd, MMMM d") - font.family: "Inter" - font.pixelSize: 26 * Scaling.scale(screen) - font.weight: Font.Light - color: Colors.textSecondary - horizontalAlignment: Text.AlignHCenter - width: timeText.width - } - } - - // User section with animated avatar - Column { - spacing: 16 * Scaling.scale(screen) - Layout.alignment: Qt.AlignHCenter - - // Animated avatar with glow effect - Rectangle { - width: 120 * Scaling.scale(screen) - height: 120 * Scaling.scale(screen) - radius: width * 0.5 - color: "transparent" - border.color: Colors.accentPrimary - border.width: 3 * Scaling.scale(screen) - anchors.horizontalCenter: parent.horizontalCenter - - // Glow effect - Rectangle { - anchors.centerIn: parent - width: parent.width + 24 * Scaling.scale(screen) - height: parent.height + 24 * Scaling.scale(screen) - radius: width * 0.5 - color: "transparent" - border.color: Qt.rgba(Colors.accentPrimary.r, Colors.accentPrimary.g, Colors.accentPrimary.b, 0.3) - border.width: 2 * Scaling.scale(screen) - z: -1 - - SequentialAnimation on scale { - loops: Animation.Infinite - NumberAnimation { to: 1.1; duration: 1500; easing.type: Easing.InOutQuad } - NumberAnimation { to: 1.0; duration: 1500; easing.type: Easing.InOutQuad } - } - } - - NImageRounded { - anchors.centerIn: parent - width: 100 * Scaling.scale(screen) - height: 100 * Scaling.scale(screen) - imagePath: Quickshell.env("HOME") + "/.face" - fallbackIcon: "person" - imageRadius: width * 0.5 - } - - // Hover animation - MouseArea { - anchors.fill: parent - hoverEnabled: true - onEntered: parent.scale = 1.05 - onExited: parent.scale = 1.0 - } - - Behavior on scale { - NumberAnimation { duration: 200; easing.type: Easing.OutBack } - } - } - - - } - } - - // Centered terminal section - Item { - width: 520 * Scaling.scale(screen) - height: 200 * Scaling.scale(screen) - anchors.centerIn: parent - - ColumnLayout { - anchors.centerIn: parent - spacing: 20 * Scaling.scale(screen) - width: parent.width - - - - // Futuristic Terminal-Style Input - Item { - width: parent.width - height: 200 * Scaling.scale(screen) - Layout.fillWidth: true - - // Terminal background with scanlines - Rectangle { - id: terminalBackground - anchors.fill: parent - radius: 16 - color: Colors.applyOpacity(Colors.backgroundPrimary, "E6") - border.color: Colors.accentPrimary - border.width: 2 * Scaling.scale(screen) - - // Scanline effect - Repeater { - model: 20 - Rectangle { - width: parent.width - height: 1 - color: Colors.applyOpacity(Colors.accentPrimary, "1A") - y: index * 10 - opacity: 0.3 - - SequentialAnimation on opacity { - loops: Animation.Infinite - NumberAnimation { to: 0.6; duration: 2000 + Math.random() * 1000 } - NumberAnimation { to: 0.1; duration: 2000 + Math.random() * 1000 } - } - } - } - - // Terminal header - Rectangle { - width: parent.width - height: 40 * Scaling.scale(screen) - color: Colors.applyOpacity(Colors.accentPrimary, "33") - topLeftRadius: 14 - topRightRadius: 14 - - RowLayout { - anchors.fill: parent - anchors.margins: 12 * Scaling.scale(screen) - spacing: 12 * Scaling.scale(screen) - - Text { - text: "●" - color: Colors.error - font.pixelSize: 16 * Scaling.scale(screen) - } - - Text { - text: "●" - color: Colors.warning - font.pixelSize: 16 * Scaling.scale(screen) - } - - Text { - text: "●" - color: Colors.accentPrimary - font.pixelSize: 16 * Scaling.scale(screen) - } - - Text { - text: "SECURE TERMINAL" - color: Colors.textPrimary - font.family: "Monaco" - font.pixelSize: 14 * Scaling.scale(screen) - font.weight: Font.Bold - Layout.fillWidth: true - } - } - } - - // Terminal content area - ColumnLayout { - anchors.top: parent.top - anchors.left: parent.left - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.topMargin: 50 * Scaling.scale(screen) - anchors.margins: 12 * Scaling.scale(screen) - spacing: 12 * Scaling.scale(screen) - - // Welcome back typing effect - RowLayout { - Layout.fillWidth: true - spacing: 12 * Scaling.scale(screen) - - Text { - text: "root@noctalia:~$" - color: Colors.accentPrimary - font.family: "Monaco" - font.pixelSize: 16 * Scaling.scale(screen) - font.weight: Font.Bold - } - - Text { - id: welcomeText - text: "" - color: Colors.textPrimary - font.family: "Monaco" - font.pixelSize: 16 * Scaling.scale(screen) - property int currentIndex: 0 - property string fullText: "Welcome back, " + Quickshell.env("USER") + "!" - - Timer { - interval: 100 - running: true - repeat: true - onTriggered: { - if (parent.currentIndex < parent.fullText.length) { - parent.text = parent.fullText.substring(0, parent.currentIndex + 1) - parent.currentIndex++ - } else { - running = false - } - } - } - } - } - - // Command line with integrated password input - RowLayout { - Layout.fillWidth: true - spacing: 12 * Scaling.scale(screen) - - Text { - text: "root@noctalia:~$" - color: Colors.accentPrimary - font.family: "Monaco" - font.pixelSize: 16 * Scaling.scale(screen) - font.weight: Font.Bold - } - - Text { - text: "sudo unlock_session" - color: Colors.textPrimary - font.family: "Monaco" - font.pixelSize: 16 * Scaling.scale(screen) - } - - // Integrated password input (invisible, just for functionality) - TextInput { - id: passwordInput - width: 0 - height: 0 - visible: false - font.family: "Monaco" - font.pixelSize: 16 * Scaling.scale(screen) - color: Colors.textPrimary - echoMode: TextInput.Password - passwordCharacter: "*" - passwordMaskDelay: 0 - - text: lock.password - onTextChanged: { - lock.password = text - // Terminal typing sound effect (visual) - typingEffect.start() - } - - Keys.onPressed: function (event) { - if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { - lock.unlockAttempt(); - } - } - - Component.onCompleted: { - forceActiveFocus(); - } - } - - // Visual password display with integrated cursor - Text { - id: asterisksText - text: "*".repeat(passwordInput.text.length) - color: Colors.textPrimary - font.family: "Monaco" - font.pixelSize: 16 * Scaling.scale(screen) - visible: passwordInput.activeFocus - - // Typing effect animation - SequentialAnimation { - id: typingEffect - NumberAnimation { - target: passwordInput - property: "scale" - to: 1.01 - duration: 50 - } - NumberAnimation { - target: passwordInput - property: "scale" - to: 1.0 - duration: 50 - } - } - } - - // Blinking cursor positioned right after the asterisks - Rectangle { - width: 8 * Scaling.scale(screen) - height: 20 * Scaling.scale(screen) - color: Colors.accentPrimary - visible: passwordInput.activeFocus - anchors.left: asterisksText.right - anchors.leftMargin: 2 * Scaling.scale(screen) - anchors.verticalCenter: asterisksText.verticalCenter - - SequentialAnimation on opacity { - loops: Animation.Infinite - NumberAnimation { to: 1.0; duration: 500 } - NumberAnimation { to: 0.0; duration: 500 } - } - } - } - - // Status messages - Text { - text: lock.authenticating ? "Authenticating..." : (lock.errorMessage !== "" ? "Authentication failed." : "") - color: lock.authenticating ? Colors.accentPrimary : (lock.errorMessage !== "" ? Colors.error : "transparent") - font.family: "Monaco" - font.pixelSize: 14 * Scaling.scale(screen) - Layout.fillWidth: true - - SequentialAnimation on opacity { - running: lock.authenticating - loops: Animation.Infinite - NumberAnimation { to: 1.0; duration: 800 } - NumberAnimation { to: 0.5; duration: 800 } - } - } - - // Execute button - Rectangle { - width: 120 * Scaling.scale(screen) - height: 40 * Scaling.scale(screen) - radius: 12 - color: executeButtonArea.containsMouse ? Colors.accentPrimary : Colors.applyOpacity(Colors.accentPrimary, "33") - border.color: Colors.accentPrimary - border.width: 1 - enabled: !lock.authenticating - Layout.alignment: Qt.AlignRight - - Text { - anchors.centerIn: parent - text: lock.authenticating ? "EXECUTING..." : "EXECUTE" - color: executeButtonArea.containsMouse ? Colors.onAccent : Colors.accentPrimary - font.family: "Monaco" - font.pixelSize: 12 * Scaling.scale(screen) - font.weight: Font.Bold - } - - MouseArea { - id: executeButtonArea - anchors.fill: parent - hoverEnabled: true - onClicked: lock.unlockAttempt() - - SequentialAnimation on scale { - running: containsMouse - NumberAnimation { to: 1.05; duration: 150; easing.type: Easing.OutCubic } - } - - SequentialAnimation on scale { - running: !containsMouse - NumberAnimation { to: 1.0; duration: 150; easing.type: Easing.OutCubic } - } - } - - // Processing animation - SequentialAnimation on scale { - loops: Animation.Infinite - running: lock.authenticating - NumberAnimation { to: 1.02; duration: 600; easing.type: Easing.InOutQuad } - NumberAnimation { to: 1.0; duration: 600; easing.type: Easing.InOutQuad } - } - } - } - - // Terminal glow effect - Rectangle { - anchors.fill: parent - radius: parent.radius - color: "transparent" - border.color: Colors.applyOpacity(Colors.accentPrimary, "4D") - border.width: 1 - z: -1 - - SequentialAnimation on opacity { - loops: Animation.Infinite - NumberAnimation { to: 0.6; duration: 2000; easing.type: Easing.InOutQuad } - NumberAnimation { to: 0.2; duration: 2000; easing.type: Easing.InOutQuad } - } - } - } - - } - - // Error message with modern styling - Rectangle { - width: parent.width - height: 56 * Scaling.scale(screen) - radius: 28 - color: Qt.rgba(Colors.error.r, Colors.error.g, Colors.error.b, 0.15) - border.color: Colors.error - border.width: 1 * Scaling.scale(screen) - visible: lock.errorMessage !== "" - Layout.fillWidth: true - - RowLayout { - anchors.fill: parent - anchors.margins: 18 * Scaling.scale(screen) - spacing: 12 * Scaling.scale(screen) - - Text { - text: "error" - font.family: "Material Symbols Outlined" - font.pixelSize: 22 * Scaling.scale(screen) - color: Colors.error - } - - Text { - text: lock.errorMessage - color: Colors.error - font.family: "Inter" - font.pixelSize: 16 * Scaling.scale(screen) - font.weight: Font.Medium - Layout.fillWidth: true - } - } - - NumberAnimation on opacity { - from: 0 - to: 1 - duration: 300 - running: lock.errorMessage !== "" - } - - // Shake animation on error - SequentialAnimation on x { - running: lock.errorMessage !== "" - NumberAnimation { to: 10; duration: 50 } - NumberAnimation { to: -10; duration: 100 } - NumberAnimation { to: 10; duration: 100 } - NumberAnimation { to: 0; duration: 50 } - } - } - - - } - } - } - - // Demo controls (only visible in demo mode) - Row { - anchors.left: parent.left - anchors.bottom: parent.bottom - anchors.margins: 50 * Scaling.scale(screen) - spacing: 10 * Scaling.scale(screen) - visible: demoMode - - Rectangle { - width: 80 * Scaling.scale(screen) - height: 30 * Scaling.scale(screen) - radius: 6 - color: Colors.accentPrimary - - Text { - anchors.centerIn: parent - text: "Demo Lock" - color: Colors.onAccent - font.pixelSize: 12 * Scaling.scale(screen) - } - - MouseArea { - anchors.fill: parent - onClicked: { - lock.locked = true - lock.password = "" - lock.errorMessage = "" - lock.demoStep = 0 - demoTimer.interval = 2000 - } - } - } - - Rectangle { - width: 80 * Scaling.scale(screen) - height: 30 * Scaling.scale(screen) - radius: 6 - color: Colors.error - - Text { - anchors.centerIn: parent - text: "Reset" - color: Colors.onError - font.pixelSize: 12 * Scaling.scale(screen) - } - - MouseArea { - anchors.fill: parent - onClicked: { - lock.locked = false - lock.password = "" - lock.errorMessage = "" - lock.authenticating = false - lock.demoStep = 0 - } - } - } - } - - // Enhanced power buttons with hover effects - Row { - anchors.right: parent.right - anchors.bottom: parent.bottom - anchors.margins: 50 * Scaling.scale(screen) - spacing: 20 * Scaling.scale(screen) - - // Shutdown with enhanced styling - Rectangle { - width: 64 * Scaling.scale(screen) - height: 64 * Scaling.scale(screen) - radius: 32 - color: Qt.rgba(Colors.error.r, Colors.error.g, Colors.error.b, shutdownArea.containsMouse ? 0.9 : 0.2) - border.color: Colors.error - border.width: 2 * Scaling.scale(screen) - - // Glow effect - Rectangle { - anchors.centerIn: parent - width: parent.width + 10 * Scaling.scale(screen) - height: parent.height + 10 * Scaling.scale(screen) - radius: width * 0.5 - color: "transparent" - border.color: Qt.rgba(Colors.error.r, Colors.error.g, Colors.error.b, 0.3) - border.width: 2 * Scaling.scale(screen) - opacity: shutdownArea.containsMouse ? 1 : 0 - z: -1 - - Behavior on opacity { - NumberAnimation { duration: 200; easing.type: Easing.OutCubic } - } - } - - MouseArea { - id: shutdownArea - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onClicked: { - Qt.createQmlObject('import Quickshell.Io; Process { command: ["shutdown", "-h", "now"]; running: true }', lock); - } - } - - Text { - anchors.centerIn: parent - text: "power_settings_new" - font.family: "Material Symbols Outlined" - font.pixelSize: 28 * Scaling.scale(screen) - color: shutdownArea.containsMouse ? Colors.onAccent : Colors.error - } - - Behavior on color { - ColorAnimation { duration: 200; easing.type: Easing.OutCubic } - } - scale: shutdownArea.containsMouse ? 1.1 : 1.0 - } - - // Reboot with enhanced styling - Rectangle { - width: 64 * Scaling.scale(screen) - height: 64 * Scaling.scale(screen) - radius: 32 - color: Qt.rgba(Colors.accentPrimary.r, Colors.accentPrimary.g, Colors.accentPrimary.b, rebootArea.containsMouse ? 0.9 : 0.2) - border.color: Colors.accentPrimary - border.width: 2 * Scaling.scale(screen) - - // Glow effect - Rectangle { - anchors.centerIn: parent - width: parent.width + 10 * Scaling.scale(screen) - height: parent.height + 10 * Scaling.scale(screen) - radius: width * 0.5 - color: "transparent" - border.color: Qt.rgba(Colors.accentPrimary.r, Colors.accentPrimary.g, Colors.accentPrimary.b, 0.3) - border.width: 2 * Scaling.scale(screen) - opacity: rebootArea.containsMouse ? 1 : 0 - z: -1 - - Behavior on opacity { - NumberAnimation { duration: 200; easing.type: Easing.OutCubic } - } - } - - MouseArea { - id: rebootArea - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onClicked: { - Qt.createQmlObject('import Quickshell.Io; Process { command: ["reboot"]; running: true }', lock); - } - } - - Text { - anchors.centerIn: parent - text: "refresh" - font.family: "Material Symbols Outlined" - font.pixelSize: 28 * Scaling.scale(screen) - color: rebootArea.containsMouse ? Colors.onAccent : Colors.accentPrimary - } - - Behavior on color { - ColorAnimation { duration: 200; easing.type: Easing.OutCubic } - } - scale: rebootArea.containsMouse ? 1.1 : 1.0 - } - - // Logout with enhanced styling - Rectangle { - width: 64 * Scaling.scale(screen) - height: 64 * Scaling.scale(screen) - radius: 32 - color: Qt.rgba(Colors.accentSecondary.r, Colors.accentSecondary.g, Colors.accentSecondary.b, logoutArea.containsMouse ? 0.9 : 0.2) - border.color: Colors.accentSecondary - border.width: 2 * Scaling.scale(screen) - - // Glow effect - Rectangle { - anchors.centerIn: parent - width: parent.width + 10 * Scaling.scale(screen) - height: parent.height + 10 * Scaling.scale(screen) - radius: width * 0.5 - color: "transparent" - border.color: Qt.rgba(Colors.accentSecondary.r, Colors.accentSecondary.g, Colors.accentSecondary.b, 0.3) - border.width: 2 * Scaling.scale(screen) - opacity: logoutArea.containsMouse ? 1 : 0 - z: -1 - - Behavior on opacity { - NumberAnimation { duration: 200; easing.type: Easing.OutCubic } - } - } - - MouseArea { - id: logoutArea - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onClicked: { - Qt.createQmlObject('import Quickshell.Io; Process { command: ["loginctl", "terminate-user", "' + Quickshell.env("USER") + '"]; running: true }', lock); - } - } - - Text { - anchors.centerIn: parent - text: "exit_to_app" - font.family: "Material Symbols Outlined" - font.pixelSize: 28 * Scaling.scale(screen) - color: logoutArea.containsMouse ? Colors.onAccent : Colors.accentSecondary - } - - Behavior on color { - ColorAnimation { duration: 200; easing.type: Easing.OutCubic } - } - scale: logoutArea.containsMouse ? 1.1 : 1.0 - } - } - - // Timer for updating time - Timer { - interval: 1000 - running: true - repeat: true - onTriggered: { - timeText.text = Qt.formatDateTime(new Date(), "HH:mm"); - dateText.text = Qt.formatDateTime(new Date(), "dddd, MMMM d"); - } - } - } -} diff --git a/Modules/SidePanel/PowerMenu.qml b/Modules/SidePanel/PowerMenu.qml index 7daaa6c..d11f3e5 100644 --- a/Modules/SidePanel/PowerMenu.qml +++ b/Modules/SidePanel/PowerMenu.qml @@ -419,8 +419,8 @@ NPanel { running: false } - // LockScreen instance - LockScreen { - id: lockScreen + // LockScreen instance + LockScreen { + id: lockScreen } } diff --git a/Services/IPCManager.qml b/Services/IPCManager.qml index 0eac967..992b7c9 100644 --- a/Services/IPCManager.qml +++ b/Services/IPCManager.qml @@ -49,8 +49,8 @@ Item { } } - // LockScreen instance - LockScreen { - id: lockScreen + // LockScreen instance + LockScreen { + id: lockScreen } }