1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-07 05:55:37 -05:00

create lock screen singleton

This commit is contained in:
bbedward
2025-08-13 21:01:35 -04:00
parent c3cccda37e
commit c9be03ddaf
3 changed files with 490 additions and 382 deletions

View File

@@ -5,6 +5,7 @@ import Quickshell
import Quickshell.Io
import Quickshell.Wayland
import qs.Common
import qs.Services
Item {
id: root
@@ -54,6 +55,7 @@ Item {
onStreamFinished: {
if (text.includes("true")) {
console.log("Session is locked on startup, activating lock screen")
LockScreenService.resetState();
loader.activeAsync = true
}
}
@@ -77,12 +79,14 @@ Item {
onRead: (line) => {
if (line.includes("org.freedesktop.login1.Session.Lock")) {
console.log("login1: Lock signal received -> show lock")
LockScreenService.resetState();
loader.activeAsync = true
} else if (line.includes("org.freedesktop.login1.Session.Unlock")) {
console.log("login1: Unlock signal received -> hide lock")
loader.active = false
} else if (line.includes("LockedHint") && line.includes("true")) {
console.log("login1: LockedHint=true -> show lock")
LockScreenService.resetState();
loader.activeAsync = true
} else if (line.includes("LockedHint") && line.includes("false")) {
console.log("login1: LockedHint=false -> hide lock")
@@ -135,6 +139,7 @@ Item {
function lock(): void {
console.log("Lock screen requested via IPC")
LockScreenService.resetState();
loader.activeAsync = true
}

View File

@@ -16,68 +16,24 @@ Item {
property string passwordBuffer: ""
property bool demoMode: false
property bool unlocking: false
property var powerModal: null
property string confirmAction: ""
property var facts: [
"A photon takes 100,000 to 200,000 years bouncing through the Sun's dense core, then races to Earth in just 8 minutes 20 seconds.",
"A teaspoon of neutron star matter would weigh a billion metric tons here on Earth.",
"Right now, 100 trillion solar neutrinos are passing through your body every second.",
"The Sun converts 4 million metric tons of matter into pure energy every second—enough to power Earth for 500,000 years.",
"The universe still glows with leftover heat from the Big Bang—just 2.7 degrees above absolute zero.",
"There's a nebula out there that's actually colder than empty space itself.",
"We've detected black holes crashing together by measuring spacetime stretch by less than 1/10,000th the width of a proton.",
"Fast radio bursts can release more energy in 5 milliseconds than our Sun produces in 3 days.",
"Our galaxy might be crawling with billions of rogue planets drifting alone in the dark.",
"Distant galaxies can move away from us faster than light because space itself is stretching.",
"The edge of what we can see is 46.5 billion light-years away, even though the universe is only 13.8 billion years old.",
"The universe is mostly invisible: 5% regular matter, 27% dark matter, 68% dark energy.",
"A day on Venus lasts longer than its entire year around the Sun.",
"On Mercury, the time between sunrises is 176 Earth days long.",
"In about 4.5 billion years, our galaxy will smash into Andromeda.",
"Most of the gold in your jewelry was forged when neutron stars collided somewhere in space.",
"PSR J1748-2446ad, the fastest spinning star, rotates 716 times per second—its equator moves at 24% the speed of light.",
"Cosmic rays create particles that shouldn't make it to Earth's surface, but time dilation lets them sneak through.",
"Jupiter's magnetic field is so huge that if we could see it, it would look bigger than the Moon in our sky.",
"Interstellar space is so empty it's like a cube 32 kilometers wide containing just a single grain of sand.",
"Voyager 1 is 24 billion kilometers away but won't leave the Sun's gravitational influence for another 30,000 years.",
"Counting to a billion at one number per second would take over 31 years.",
"Space is so vast, even speeding at light-speed, you'd never return past the cosmic horizon.",
"Astronauts on the ISS age about 0.01 seconds less each year than people on Earth.",
"Sagittarius B2, a dust cloud near our galaxy's center, contains ethyl formate—the compound that gives raspberries their flavor and rum its smell.",
"Beyond 16 billion light-years, the cosmic event horizon marks where space expands too fast for light to ever reach us again.",
"Even at light-speed, you'd never catch up to most galaxies—space expands faster.",
"Only around 5% of galaxies are ever reachable—even at light-speed.",
"If the Sun vanished, we'd still orbit it for 8 minutes before drifting away.",
"If a planet 65 million light-years away looked at Earth now, it'd see dinosaurs.",
"Our oldest radio signals will reach the Milky Way's center in 26,000 years.",
"Every atom in your body heavier than hydrogen was forged in the nuclear furnace of a dying star.",
"The Moon moves 3.8 centimeters farther from Earth every year.",
"The universe creates 275 million new stars every single day.",
"Jupiter's Great Red Spot is a storm twice the size of Earth that has been raging for at least 350 years.",
"If you watched someone fall into a black hole, they'd appear frozen at the event horizon forever—time effectively stops from your perspective.",
"The Boötes Supervoid is a cosmic desert 1.8 billion light-years across with 60% fewer galaxies than it should have."
];
property string randomFact: ""
signal unlockRequested()
function pickRandomFact() {
randomFact = facts[Math.floor(Math.random() * facts.length)];
}
signal unlockRequested
Component.onCompleted: {
pickRandomFact();
WeatherService.addRef();
UserInfoService.refreshUserInfo();
if (demoMode)
LockScreenService.pickRandomFact()
WeatherService.addRef()
UserInfoService.refreshUserInfo()
}
onDemoModeChanged: {
if (demoMode)
pickRandomFact();
LockScreenService.pickRandomFact()
}
Component.onDestruction: {
WeatherService.removeRef();
WeatherService.removeRef()
}
Image {
@@ -105,9 +61,7 @@ Item {
duration: Theme.mediumDuration
easing.type: Theme.standardEasing
}
}
}
Rectangle {
@@ -137,7 +91,11 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
text: SettingsData.use24HourClock ? Qt.formatTime(systemClock.date, "H:mm") : Qt.formatTime(systemClock.date, "h:mm AP")
text: SettingsData.use24HourClock ? Qt.formatTime(
systemClock.date,
"H:mm") : Qt.formatTime(
systemClock.date,
"h:mm AP")
font.pixelSize: 120
font.weight: Font.Light
color: "white"
@@ -148,12 +106,12 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: clockText.bottom
anchors.topMargin: -20
text: Qt.formatDate(systemClock.date, SettingsData.lockDateFormat)
text: Qt.formatDate(systemClock.date,
SettingsData.lockDateFormat)
font.pixelSize: Theme.fontSizeXLarge
color: "white"
opacity: 0.9
}
}
ColumnLayout {
@@ -188,12 +146,12 @@ Item {
source: {
if (PortalService.profileImage === "")
return "";
return ""
if (PortalService.profileImage.startsWith("/"))
return "file://" + PortalService.profileImage;
return "file://" + PortalService.profileImage
return PortalService.profileImage;
return PortalService.profileImage
}
smooth: true
asynchronous: true
@@ -228,7 +186,6 @@ Item {
color: "black"
antialiasing: true
}
}
Rectangle {
@@ -243,7 +200,6 @@ Item {
size: Theme.iconSize + 4
color: Theme.primaryText
}
}
DankIcon {
@@ -251,9 +207,9 @@ Item {
name: "warning"
size: Theme.iconSize + 4
color: Theme.primaryText
visible: PortalService.profileImage !== "" && profileImageLoader.status === Image.Error
visible: PortalService.profileImage !== ""
&& profileImageLoader.status === Image.Error
}
}
Rectangle {
@@ -262,8 +218,11 @@ Item {
Layout.fillWidth: true
Layout.preferredHeight: 60
radius: Theme.cornerRadius
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.9)
border.color: passwordField.activeFocus ? Theme.primary : Qt.rgba(1, 1, 1, 0.3)
color: Qt.rgba(Theme.surfaceContainer.r,
Theme.surfaceContainer.g,
Theme.surfaceContainer.b, 0.9)
border.color: passwordField.activeFocus ? Theme.primary : Qt.rgba(
1, 1, 1, 0.3)
border.width: passwordField.activeFocus ? 2 : 1
DankIcon {
@@ -289,23 +248,24 @@ Item {
echoMode: parent.showPassword ? TextInput.Normal : TextInput.Password
onTextChanged: {
if (!demoMode)
root.passwordBuffer = text;
root.passwordBuffer = text
}
onAccepted: {
if (!demoMode && root.passwordBuffer.length > 0 && !pam.active) {
console.log("Enter pressed, starting PAM authentication");
pam.start();
if (!demoMode && root.passwordBuffer.length > 0
&& !pam.active) {
console.log("Enter pressed, starting PAM authentication")
pam.start()
}
}
Keys.onPressed: (event) => {
Keys.onPressed: event => {
if (demoMode)
return ;
return
if (pam.active) {
console.log("PAM is active, ignoring input");
event.accepted = true;
return ;
console.log(
"PAM is active, ignoring input")
event.accepted = true
return
}
}
@@ -316,7 +276,6 @@ Item {
running: !demoMode
onTriggered: passwordField.forceActiveFocus()
}
}
StyledText {
@@ -331,26 +290,26 @@ Item {
anchors.verticalCenter: parent.verticalCenter
text: {
if (demoMode)
return "";
return ""
if (root.unlocking)
return "Unlocking...";
if (LockScreenService.unlocking)
return "Unlocking..."
if (pam.active)
return "Authenticating...";
return "Authenticating..."
return "hunter2";
return "Password..."
}
color: root.unlocking ? Theme.primary : (pam.active ? Theme.primary : Theme.outline)
color: LockScreenService.unlocking ? Theme.primary : (pam.active ? Theme.primary : Theme.outline)
font.pixelSize: Theme.fontSizeMedium
opacity: (demoMode || root.passwordBuffer.length === 0) ? 1 : 0
opacity: (demoMode
|| root.passwordBuffer.length === 0) ? 1 : 0
Behavior on opacity {
NumberAnimation {
duration: Theme.mediumDuration
easing.type: Theme.standardEasing
}
}
Behavior on color {
@@ -358,9 +317,7 @@ Item {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
StyledText {
@@ -371,15 +328,18 @@ Item {
anchors.verticalCenter: parent.verticalCenter
text: {
if (demoMode)
return "••••••••";
return "••••••••"
else if (parent.showPassword)
return root.passwordBuffer;
return root.passwordBuffer
else
return "•".repeat(Math.min(root.passwordBuffer.length, 25));
return "•".repeat(
Math.min(
root.passwordBuffer.length, 25))
}
color: Theme.surfaceText
font.pixelSize: parent.showPassword ? Theme.fontSizeMedium : Theme.fontSizeLarge
opacity: (demoMode || root.passwordBuffer.length > 0) ? 1 : 0
opacity: (demoMode
|| root.passwordBuffer.length > 0) ? 1 : 0
elide: Text.ElideRight
Behavior on opacity {
@@ -387,9 +347,7 @@ Item {
duration: Theme.mediumDuration
easing.type: Theme.standardEasing
}
}
}
DankActionButton {
@@ -400,7 +358,8 @@ Item {
anchors.verticalCenter: parent.verticalCenter
iconName: parent.showPassword ? "visibility_off" : "visibility"
buttonSize: 32
visible: !demoMode && root.passwordBuffer.length > 0 && !pam.active && !root.unlocking
visible: !demoMode && root.passwordBuffer.length > 0
&& !pam.active && !LockScreenService.unlocking
enabled: visible
onClicked: parent.showPassword = !parent.showPassword
}
@@ -415,17 +374,18 @@ Item {
height: 24
radius: 12
color: "transparent"
visible: !demoMode && (pam.active || root.unlocking)
visible: !demoMode && (pam.active
|| LockScreenService.unlocking)
DankIcon {
anchors.centerIn: parent
name: "check_circle"
size: 20
color: Theme.primary
visible: root.unlocking
visible: LockScreenService.unlocking
SequentialAnimation on scale {
running: root.unlocking
running: LockScreenService.unlocking
NumberAnimation {
from: 0
@@ -442,14 +402,12 @@ Item {
easing.type: Easing.BezierSpline
easing.bezierCurve: Anims.emphasizedAccel
}
}
}
Item {
anchors.fill: parent
visible: pam.active && !root.unlocking
visible: pam.active && !LockScreenService.unlocking
Rectangle {
width: 20
@@ -457,7 +415,9 @@ Item {
radius: 10
anchors.centerIn: parent
color: "transparent"
border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3)
border.color: Qt.rgba(Theme.primary.r,
Theme.primary.g,
Theme.primary.b, 0.3)
border.width: 2
}
@@ -475,21 +435,22 @@ Item {
height: parent.height / 2
anchors.top: parent.top
anchors.horizontalCenter: parent.horizontalCenter
color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 0.9)
color: Qt.rgba(Theme.surfaceContainer.r,
Theme.surfaceContainer.g,
Theme.surfaceContainer.b,
0.9)
}
RotationAnimation on rotation {
running: pam.active && !root.unlocking
running: pam.active
&& !LockScreenService.unlocking
loops: Animation.Infinite
duration: Anims.durLong
from: 0
to: 360
}
}
}
}
DankActionButton {
@@ -500,12 +461,14 @@ Item {
anchors.verticalCenter: parent.verticalCenter
iconName: "keyboard_return"
buttonSize: 36
visible: (demoMode || (root.passwordBuffer.length > 0 && !pam.active && !root.unlocking))
visible: (demoMode || (root.passwordBuffer.length > 0
&& !pam.active
&& !LockScreenService.unlocking))
enabled: !demoMode
onClicked: {
if (!demoMode) {
console.log("Enter button clicked, starting PAM authentication");
pam.start();
console.log("Enter button clicked, starting PAM authentication")
pam.start()
}
}
@@ -514,9 +477,7 @@ Item {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
Behavior on border.color {
@@ -524,40 +485,36 @@ Item {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
StyledText {
Layout.fillWidth: true
Layout.preferredHeight: placeholder.pamState ? 20 : 0
Layout.preferredHeight: LockScreenService.pamState ? 20 : 0
text: {
if (placeholder.pamState === "error")
return "Authentication error - try again";
if (LockScreenService.pamState === "error")
return "Authentication error - try again"
if (placeholder.pamState === "max")
return "Too many attempts - locked out";
if (LockScreenService.pamState === "max")
return "Too many attempts - locked out"
if (placeholder.pamState === "fail")
return "Incorrect password - try again";
if (LockScreenService.pamState === "fail")
return "Incorrect password - try again"
return "";
return ""
}
color: Theme.error
font.pixelSize: Theme.fontSizeSmall
horizontalAlignment: Text.AlignHCenter
visible: placeholder.pamState !== ""
opacity: placeholder.pamState !== "" ? 1 : 0
visible: LockScreenService.pamState !== ""
opacity: LockScreenService.pamState !== "" ? 1 : 0
Behavior on opacity {
NumberAnimation {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
Behavior on Layout.preferredHeight {
@@ -565,11 +522,8 @@ Item {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
StyledText {
@@ -597,7 +551,8 @@ Item {
anchors.verticalCenter: parent.verticalCenter
DankIcon {
name: WeatherService.getWeatherIcon(WeatherService.weather.wCode)
name: WeatherService.getWeatherIcon(
WeatherService.weather.wCode)
size: Theme.iconSize
color: "white"
anchors.verticalCenter: parent.verticalCenter
@@ -618,21 +573,28 @@ Item {
height: 24
color: Qt.rgba(255, 255, 255, 0.2)
anchors.verticalCenter: parent.verticalCenter
visible: WeatherService.weather.available && (NetworkService.networkStatus !== "disconnected" || BluetoothService.enabled || (AudioService.sink && AudioService.sink.audio) || BatteryService.batteryAvailable)
visible: WeatherService.weather.available
&& (NetworkService.networkStatus !== "disconnected"
|| BluetoothService.enabled
|| (AudioService.sink && AudioService.sink.audio)
|| BatteryService.batteryAvailable)
}
// System status icons
Row {
spacing: Theme.spacingM
anchors.verticalCenter: parent.verticalCenter
visible: NetworkService.networkStatus !== "disconnected" || (BluetoothService.available && BluetoothService.enabled) || (AudioService.sink && AudioService.sink.audio)
visible: NetworkService.networkStatus !== "disconnected"
|| (BluetoothService.available
&& BluetoothService.enabled)
|| (AudioService.sink && AudioService.sink.audio)
// Network icon
DankIcon {
name: {
if (NetworkService.networkStatus === "ethernet")
if (NetworkService.networkStatus === "ethernet") {
return "lan"
else if (NetworkService.networkStatus === "wifi") {
} else if (NetworkService.networkStatus === "wifi") {
switch (NetworkService.wifiSignalStrengthStr) {
case "excellent":
return "wifi"
@@ -645,12 +607,14 @@ Item {
default:
return "wifi"
}
}
else
} else {
return "wifi_off"
}
}
size: Theme.iconSize - 2
color: NetworkService.networkStatus !== "disconnected" ? "white" : Qt.rgba(255, 255, 255, 0.5)
color: NetworkService.networkStatus
!== "disconnected" ? "white" : Qt.rgba(255,
255, 255, 0.5)
anchors.verticalCenter: parent.verticalCenter
visible: NetworkService.networkStatus !== "disconnected"
}
@@ -661,14 +625,16 @@ Item {
size: Theme.iconSize - 2
color: "white"
anchors.verticalCenter: parent.verticalCenter
visible: BluetoothService.available && BluetoothService.enabled
visible: BluetoothService.available
&& BluetoothService.enabled
}
// Volume icon
DankIcon {
name: {
if (AudioService.sink && AudioService.sink.audio) {
if (AudioService.sink.audio.muted || AudioService.sink.audio.volume === 0)
if (AudioService.sink.audio.muted
|| AudioService.sink.audio.volume === 0)
return "volume_off"
else if (AudioService.sink.audio.volume * 100 < 33)
return "volume_down"
@@ -678,7 +644,10 @@ Item {
return "volume_up"
}
size: Theme.iconSize - 2
color: (AudioService.sink && AudioService.sink.audio && (AudioService.sink.audio.muted || AudioService.sink.audio.volume === 0)) ? Qt.rgba(255, 255, 255, 0.5) : "white"
color: (AudioService.sink && AudioService.sink.audio
&& (AudioService.sink.audio.muted
|| AudioService.sink.audio.volume
=== 0)) ? Qt.rgba(255, 255, 255, 0.5) : "white"
anchors.verticalCenter: parent.verticalCenter
visible: AudioService.sink && AudioService.sink.audio
}
@@ -690,7 +659,10 @@ Item {
height: 24
color: Qt.rgba(255, 255, 255, 0.2)
anchors.verticalCenter: parent.verticalCenter
visible: BatteryService.batteryAvailable && (NetworkService.networkStatus !== "disconnected" || BluetoothService.enabled || (AudioService.sink && AudioService.sink.audio))
visible: BatteryService.batteryAvailable
&& (NetworkService.networkStatus !== "disconnected"
|| BluetoothService.enabled
|| (AudioService.sink && AudioService.sink.audio))
}
// Battery section
@@ -704,57 +676,77 @@ Item {
if (BatteryService.isCharging) {
if (BatteryService.batteryLevel >= 90)
return "battery_charging_full"
if (BatteryService.batteryLevel >= 80)
return "battery_charging_90"
if (BatteryService.batteryLevel >= 60)
return "battery_charging_80"
if (BatteryService.batteryLevel >= 50)
return "battery_charging_60"
if (BatteryService.batteryLevel >= 30)
return "battery_charging_50"
if (BatteryService.batteryLevel >= 20)
return "battery_charging_30"
return "battery_charging_20"
}
// Check if plugged in but not charging (like at 80% charge limit)
if (BatteryService.isPluggedIn) {
if (BatteryService.batteryLevel >= 90)
return "battery_charging_full"
if (BatteryService.batteryLevel >= 80)
return "battery_charging_90"
if (BatteryService.batteryLevel >= 60)
return "battery_charging_80"
if (BatteryService.batteryLevel >= 50)
return "battery_charging_60"
if (BatteryService.batteryLevel >= 30)
return "battery_charging_50"
if (BatteryService.batteryLevel >= 20)
return "battery_charging_30"
return "battery_charging_20"
}
// On battery power
if (BatteryService.batteryLevel >= 95)
return "battery_full"
if (BatteryService.batteryLevel >= 85)
return "battery_6_bar"
if (BatteryService.batteryLevel >= 70)
return "battery_5_bar"
if (BatteryService.batteryLevel >= 55)
return "battery_4_bar"
if (BatteryService.batteryLevel >= 40)
return "battery_3_bar"
if (BatteryService.batteryLevel >= 25)
return "battery_2_bar"
return "battery_1_bar"
}
size: Theme.iconSize
color: {
if (BatteryService.isLowBattery && !BatteryService.isCharging)
if (BatteryService.isLowBattery
&& !BatteryService.isCharging)
return Theme.error
if (BatteryService.isCharging || BatteryService.isPluggedIn)
if (BatteryService.isCharging
|| BatteryService.isPluggedIn)
return Theme.primary
return "white"
}
anchors.verticalCenter: parent.verticalCenter
@@ -782,9 +774,9 @@ Item {
buttonSize: 40
onClicked: {
if (demoMode)
console.log("Demo: Power");
console.log("Demo: Power")
else
powerDialog.open();
LockScreenService.showPowerDialog()
}
}
@@ -793,9 +785,9 @@ Item {
buttonSize: 40
onClicked: {
if (demoMode)
console.log("Demo: Reboot");
console.log("Demo: Reboot")
else
rebootDialog.open();
LockScreenService.showRebootDialog()
}
}
@@ -804,12 +796,11 @@ Item {
buttonSize: 40
onClicked: {
if (demoMode)
console.log("Demo: Logout");
console.log("Demo: Logout")
else
logoutDialog.open();
LockScreenService.showLogoutDialog()
}
}
}
StyledText {
@@ -817,15 +808,14 @@ Item {
anchors.horizontalCenter: parent.horizontalCenter
anchors.margins: Theme.spacingL
width: Math.min(parent.width - Theme.spacingXL * 2, implicitWidth)
text: randomFact
text: LockScreenService.randomFact
font.pixelSize: Theme.fontSizeSmall
color: "white"
opacity: 0.8
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.NoWrap
visible: randomFact !== ""
visible: LockScreenService.randomFact !== ""
}
}
FileView {
@@ -841,36 +831,38 @@ Item {
config: pamConfigWatcher.loaded ? "dankshell" : "login"
onResponseRequiredChanged: {
if (demoMode)
return ;
return
console.log("PAM response required:", responseRequired);
console.log("PAM response required:", responseRequired)
if (!responseRequired)
return ;
return
console.log("Responding to PAM with password buffer length:", root.passwordBuffer.length);
respond(root.passwordBuffer);
console.log("Responding to PAM with password buffer length:",
root.passwordBuffer.length)
respond(root.passwordBuffer)
}
onCompleted: (res) => {
onCompleted: res => {
if (demoMode)
return ;
return
console.log("PAM authentication completed with result:", res);
console.log(
"PAM authentication completed with result:", res)
if (res === PamResult.Success) {
console.log("Authentication successful, unlocking");
root.unlocking = true;
passwordField.text = "";
root.passwordBuffer = "";
root.unlockRequested();
return ;
console.log("Authentication successful, unlocking")
LockScreenService.setUnlocking(true)
passwordField.text = ""
root.passwordBuffer = ""
root.unlockRequested()
return
}
console.log("Authentication failed:", res);
console.log("Authentication failed:", res)
if (res === PamResult.Error)
placeholder.pamState = "error";
LockScreenService.setPamState("error")
else if (res === PamResult.MaxTries)
placeholder.pamState = "max";
LockScreenService.setPamState("max")
else if (res === PamResult.Failed)
placeholder.pamState = "fail";
placeholderDelay.restart();
LockScreenService.setPamState("fail")
placeholderDelay.restart()
}
}
@@ -878,7 +870,7 @@ Item {
id: placeholderDelay
interval: 4000
onTriggered: placeholder.pamState = ""
onTriggered: LockScreenService.setPamState("")
}
MouseArea {
@@ -891,16 +883,16 @@ Item {
id: powerDialog
function open() {
visible = true;
LockScreenService.showPowerDialog()
}
function close() {
visible = false;
LockScreenService.hidePowerDialog()
}
anchors.fill: parent
color: Qt.rgba(0, 0, 0, 0.8)
visible: false
visible: LockScreenService.powerDialogVisible
z: 1000
Rectangle {
@@ -939,7 +931,11 @@ Item {
width: 100
height: 40
radius: Theme.cornerRadius
color: cancelMouse1.pressed ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.7) : cancelMouse1.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant
color: cancelMouse1.pressed ? Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.7) : cancelMouse1.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant
StyledText {
anchors.centerIn: parent
@@ -956,14 +952,17 @@ Item {
cursorShape: Qt.PointingHandCursor
onClicked: powerDialog.close()
}
}
Rectangle {
width: 100
height: 40
radius: Theme.cornerRadius
color: powerMouse.pressed ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.8) : powerMouse.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 1) : Theme.error
color: powerMouse.pressed ? Qt.rgba(
Theme.error.r,
Theme.error.g,
Theme.error.b,
0.8) : powerMouse.containsMouse ? Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 1) : Theme.error
StyledText {
anchors.centerIn: parent
@@ -980,35 +979,31 @@ Item {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
powerDialog.close();
Quickshell.execDetached(["systemctl", "poweroff"]);
powerDialog.close()
Quickshell.execDetached(
["systemctl", "poweroff"])
}
}
}
}
}
}
}
Rectangle {
id: rebootDialog
function open() {
visible = true;
LockScreenService.showRebootDialog()
}
function close() {
visible = false;
LockScreenService.hideRebootDialog()
}
anchors.fill: parent
color: Qt.rgba(0, 0, 0, 0.8)
visible: false
visible: LockScreenService.rebootDialogVisible
z: 1000
Rectangle {
@@ -1047,7 +1042,11 @@ Item {
width: 100
height: 40
radius: Theme.cornerRadius
color: cancelMouse2.pressed ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.7) : cancelMouse2.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant
color: cancelMouse2.pressed ? Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.7) : cancelMouse2.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant
StyledText {
anchors.centerIn: parent
@@ -1064,14 +1063,17 @@ Item {
cursorShape: Qt.PointingHandCursor
onClicked: rebootDialog.close()
}
}
Rectangle {
width: 100
height: 40
radius: Theme.cornerRadius
color: rebootMouse.pressed ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.8) : rebootMouse.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 1) : Theme.primary
color: rebootMouse.pressed ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.8) : rebootMouse.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 1) : Theme.primary
StyledText {
anchors.centerIn: parent
@@ -1088,35 +1090,30 @@ Item {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
rebootDialog.close();
Quickshell.execDetached(["systemctl", "reboot"]);
rebootDialog.close()
Quickshell.execDetached(["systemctl", "reboot"])
}
}
}
}
}
}
}
Rectangle {
id: logoutDialog
function open() {
visible = true;
LockScreenService.showLogoutDialog()
}
function close() {
visible = false;
LockScreenService.hideLogoutDialog()
}
anchors.fill: parent
color: Qt.rgba(0, 0, 0, 0.8)
visible: false
visible: LockScreenService.logoutDialogVisible
z: 1000
Rectangle {
@@ -1155,7 +1152,11 @@ Item {
width: 100
height: 40
radius: Theme.cornerRadius
color: cancelMouse3.pressed ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.7) : cancelMouse3.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant
color: cancelMouse3.pressed ? Qt.rgba(
Theme.surfaceVariant.r,
Theme.surfaceVariant.g,
Theme.surfaceVariant.b,
0.7) : cancelMouse3.containsMouse ? Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.9) : Theme.surfaceVariant
StyledText {
anchors.centerIn: parent
@@ -1172,14 +1173,17 @@ Item {
cursorShape: Qt.PointingHandCursor
onClicked: logoutDialog.close()
}
}
Rectangle {
width: 100
height: 40
radius: Theme.cornerRadius
color: logoutMouse.pressed ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.8) : logoutMouse.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 1) : Theme.primary
color: logoutMouse.pressed ? Qt.rgba(
Theme.primary.r,
Theme.primary.g,
Theme.primary.b,
0.8) : logoutMouse.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 1) : Theme.primary
StyledText {
anchors.centerIn: parent
@@ -1196,19 +1200,13 @@ Item {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
logoutDialog.close();
NiriService.quit();
logoutDialog.close()
NiriService.quit()
}
}
}
}
}
}
}
}

View File

@@ -0,0 +1,105 @@
pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
Singleton {
id: root
property bool unlocking: false
property string randomFact: ""
property string pamState: ""
property bool powerDialogVisible: false
property bool rebootDialogVisible: false
property bool logoutDialogVisible: false
property var facts: [
"A photon takes 100,000 to 200,000 years bouncing through the Sun's dense core, then races to Earth in just 8 minutes 20 seconds.",
"A teaspoon of neutron star matter would weigh a billion metric tons here on Earth.",
"Right now, 100 trillion solar neutrinos are passing through your body every second.",
"The Sun converts 4 million metric tons of matter into pure energy every second—enough to power Earth for 500,000 years.",
"The universe still glows with leftover heat from the Big Bang—just 2.7 degrees above absolute zero.",
"There's a nebula out there that's actually colder than empty space itself.",
"We've detected black holes crashing together by measuring spacetime stretch by less than 1/10,000th the width of a proton.",
"Fast radio bursts can release more energy in 5 milliseconds than our Sun produces in 3 days.",
"Our galaxy might be crawling with billions of rogue planets drifting alone in the dark.",
"Distant galaxies can move away from us faster than light because space itself is stretching.",
"The edge of what we can see is 46.5 billion light-years away, even though the universe is only 13.8 billion years old.",
"The universe is mostly invisible: 5% regular matter, 27% dark matter, 68% dark energy.",
"A day on Venus lasts longer than its entire year around the Sun.",
"On Mercury, the time between sunrises is 176 Earth days long.",
"In about 4.5 billion years, our galaxy will smash into Andromeda.",
"Most of the gold in your jewelry was forged when neutron stars collided somewhere in space.",
"PSR J1748-2446ad, the fastest spinning star, rotates 716 times per second—its equator moves at 24% the speed of light.",
"Cosmic rays create particles that shouldn't make it to Earth's surface, but time dilation lets them sneak through.",
"Jupiter's magnetic field is so huge that if we could see it, it would look bigger than the Moon in our sky.",
"Interstellar space is so empty it's like a cube 32 kilometers wide containing just a single grain of sand.",
"Voyager 1 is 24 billion kilometers away but won't leave the Sun's gravitational influence for another 30,000 years.",
"Counting to a billion at one number per second would take over 31 years.",
"Space is so vast, even speeding at light-speed, you'd never return past the cosmic horizon.",
"Astronauts on the ISS age about 0.01 seconds less each year than people on Earth.",
"Sagittarius B2, a dust cloud near our galaxy's center, contains ethyl formate—the compound that gives raspberries their flavor and rum its smell.",
"Beyond 16 billion light-years, the cosmic event horizon marks where space expands too fast for light to ever reach us again.",
"Even at light-speed, you'd never catch up to most galaxies—space expands faster.",
"Only around 5% of galaxies are ever reachable—even at light-speed.",
"If the Sun vanished, we'd still orbit it for 8 minutes before drifting away.",
"If a planet 65 million light-years away looked at Earth now, it'd see dinosaurs.",
"Our oldest radio signals will reach the Milky Way's center in 26,000 years.",
"Every atom in your body heavier than hydrogen was forged in the nuclear furnace of a dying star.",
"The Moon moves 3.8 centimeters farther from Earth every year.",
"The universe creates 275 million new stars every single day.",
"Jupiter's Great Red Spot is a storm twice the size of Earth that has been raging for at least 350 years.",
"If you watched someone fall into a black hole, they'd appear frozen at the event horizon forever—time effectively stops from your perspective.",
"The Boötes Supervoid is a cosmic desert 1.8 billion light-years across with 60% fewer galaxies than it should have."
]
function pickRandomFact() {
randomFact = facts[Math.floor(Math.random() * facts.length)];
}
function resetState() {
unlocking = false;
pamState = "";
powerDialogVisible = false;
rebootDialogVisible = false;
logoutDialogVisible = false;
pickRandomFact();
}
function setPamState(state) {
pamState = state;
}
function setUnlocking(value) {
unlocking = value;
}
function showPowerDialog() {
powerDialogVisible = true;
}
function hidePowerDialog() {
powerDialogVisible = false;
}
function showRebootDialog() {
rebootDialogVisible = true;
}
function hideRebootDialog() {
rebootDialogVisible = false;
}
function showLogoutDialog() {
logoutDialogVisible = true;
}
function hideLogoutDialog() {
logoutDialogVisible = false;
}
Component.onCompleted: {
pickRandomFact();
}
}