diff options
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock')
12 files changed, 0 insertions, 4176 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/CustomButtonKeyboard.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/CustomButtonKeyboard.qml deleted file mode 100644 index 639389c..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/CustomButtonKeyboard.qml +++ /dev/null @@ -1,41 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import qs.Common -import qs.Services -import qs.Widgets - -DankActionButton { - id: customButtonKeyboard - circular: false - property string text: "" - width: 40 - height: 40 - property bool isShift: false - color: Theme.surface - - property bool isIcon: text === "keyboard_hide" || text === "Backspace" || text === "Enter" - - DankIcon { - anchors.centerIn: parent - name: { - if (parent.text === "keyboard_hide") return "keyboard_hide" - if (parent.text === "Backspace") return "backspace" - if (parent.text === "Enter") return "keyboard_return" - return "" - } - size: 20 - color: Theme.surfaceText - visible: parent.isIcon - } - - StyledText { - id: contentItem - anchors.centerIn: parent - text: parent.text - color: Theme.surfaceText - font.pixelSize: Theme.fontSizeXLarge - font.weight: Font.Normal - visible: !parent.isIcon - } -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/FadeToDpmsWindow.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/FadeToDpmsWindow.qml deleted file mode 100644 index 0486890..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/FadeToDpmsWindow.qml +++ /dev/null @@ -1,102 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import Quickshell -import Quickshell.Wayland -import qs.Common - -PanelWindow { - id: root - - property bool active: false - - signal fadeCompleted - signal fadeCancelled - - visible: active - color: "transparent" - - WlrLayershell.namespace: "dms:fade-to-dpms" - WlrLayershell.layer: WlrLayershell.Overlay - WlrLayershell.exclusiveZone: -1 - WlrLayershell.keyboardFocus: active ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None - - anchors { - left: true - right: true - top: true - bottom: true - } - - Rectangle { - id: fadeOverlay - anchors.fill: parent - color: "black" - opacity: 0 - - onOpacityChanged: { - if (opacity >= 0.99 && root.active) { - root.fadeCompleted(); - } - } - } - - SequentialAnimation { - id: fadeSeq - running: false - - NumberAnimation { - target: fadeOverlay - property: "opacity" - from: 0.0 - to: 1.0 - duration: SettingsData.fadeToDpmsGracePeriod * 1000 - easing.type: Easing.OutCubic - } - } - - function startFade() { - if (!SettingsData.fadeToDpmsEnabled) - return; - active = true; - fadeOverlay.opacity = 0.0; - fadeSeq.stop(); - fadeSeq.start(); - } - - function cancelFade() { - fadeSeq.stop(); - fadeOverlay.opacity = 0.0; - active = false; - fadeCancelled(); - } - - MouseArea { - anchors.fill: parent - enabled: root.active - onClicked: root.cancelFade() - onPressed: root.cancelFade() - } - - FocusScope { - anchors.fill: parent - focus: root.active - - Keys.onPressed: event => { - root.cancelFade(); - event.accepted = true; - } - } - - Component.onCompleted: { - if (active) { - forceActiveFocus(); - } - } - - onActiveChanged: { - if (active) { - forceActiveFocus(); - } - } -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/FadeToLockWindow.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/FadeToLockWindow.qml deleted file mode 100644 index c73a59a..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/FadeToLockWindow.qml +++ /dev/null @@ -1,102 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import Quickshell -import Quickshell.Wayland -import qs.Common - -PanelWindow { - id: root - - property bool active: false - - signal fadeCompleted - signal fadeCancelled - - visible: active - color: "transparent" - - WlrLayershell.namespace: "dms:fade-to-lock" - WlrLayershell.layer: WlrLayershell.Overlay - WlrLayershell.exclusiveZone: -1 - WlrLayershell.keyboardFocus: active ? WlrKeyboardFocus.Exclusive : WlrKeyboardFocus.None - - anchors { - left: true - right: true - top: true - bottom: true - } - - Rectangle { - id: fadeOverlay - anchors.fill: parent - color: "black" - opacity: 0 - - onOpacityChanged: { - if (opacity >= 0.99 && root.active) { - root.fadeCompleted(); - } - } - } - - SequentialAnimation { - id: fadeSeq - running: false - - NumberAnimation { - target: fadeOverlay - property: "opacity" - from: 0.0 - to: 1.0 - duration: SettingsData.fadeToLockGracePeriod * 1000 - easing.type: Easing.OutCubic - } - } - - function startFade() { - if (!SettingsData.fadeToLockEnabled) - return; - active = true; - fadeOverlay.opacity = 0.0; - fadeSeq.stop(); - fadeSeq.start(); - } - - function cancelFade() { - fadeSeq.stop(); - fadeOverlay.opacity = 0.0; - active = false; - fadeCancelled(); - } - - MouseArea { - anchors.fill: parent - enabled: root.active - onClicked: root.cancelFade() - onPressed: root.cancelFade() - } - - FocusScope { - anchors.fill: parent - focus: root.active - - Keys.onPressed: event => { - root.cancelFade(); - event.accepted = true; - } - } - - Component.onCompleted: { - if (active) { - forceActiveFocus(); - } - } - - onActiveChanged: { - if (active) { - forceActiveFocus(); - } - } -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/Keyboard.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/Keyboard.qml deleted file mode 100644 index cfc0c61..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/Keyboard.qml +++ /dev/null @@ -1,344 +0,0 @@ -import QtQuick -import qs.Common - -Rectangle { - id: root - property Item target - height: 60 * 5 - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.right: parent.right - color: Theme.surfaceContainerHigh - - signal dismissed - - property double rowSpacing: 0.01 * width // horizontal spacing between keyboard - property double columnSpacing: 0.02 * height // vertical spacing between keyboard - property bool shift: false //Boolean for the shift state - property bool symbols: false //Boolean for the symbol state - property double columns: 10 // Number of column - property double rows: 4 // Number of row - - property string strShift: '\u2191' - property string strBackspace: "Backspace" - property string strEnter: "Enter" - property string strClose: "keyboard_hide" - - property var modelKeyboard: { - "row_1": [{ - "text": 'q', - "symbol": '1', - "width": 1 - }, { - "text": 'w', - "symbol": '2', - "width": 1 - }, { - "text": 'e', - "symbol": '3', - "width": 1 - }, { - "text": 'r', - "symbol": '4', - "width": 1 - }, { - "text": 't', - "symbol": '5', - "width": 1 - }, { - "text": 'y', - "symbol": '6', - "width": 1 - }, { - "text": 'u', - "symbol": '7', - "width": 1 - }, { - "text": 'i', - "symbol": '8', - "width": 1 - }, { - "text": 'o', - "symbol": '9', - "width": 1 - }, { - "text": 'p', - "symbol": '0', - "width": 1 - }], - "row_2": [{ - "text": 'a', - "symbol": '-', - "width": 1 - }, { - "text": 's', - "symbol": '/', - "width": 1 - }, { - "text": 'd', - "symbol": ':', - "width": 1 - }, { - "text": 'f', - "symbol": ';', - "width": 1 - }, { - "text": 'g', - "symbol": '(', - "width": 1 - }, { - "text": 'h', - "symbol": ')', - "width": 1 - }, { - "text": 'j', - "symbol": '€', - "width": 1 - }, { - "text": 'k', - "symbol": '&', - "width": 1 - }, { - "text": 'l', - "symbol": '@', - "width": 1 - }], - "row_3": [{ - "text": strShift, - "symbol": strShift, - "width": 1.5 - }, { - "text": 'z', - "symbol": '.', - "width": 1 - }, { - "text": 'x', - "symbol": ',', - "width": 1 - }, { - "text": 'c', - "symbol": '?', - "width": 1 - }, { - "text": 'v', - "symbol": '!', - "width": 1 - }, { - "text": 'b', - "symbol": "'", - "width": 1 - }, { - "text": 'n', - "symbol": "%", - "width": 1 - }, { - "text": 'm', - "symbol": '"', - "width": 1 - }, { - "text": strBackspace, - "symbol": strBackspace, - "width": 1.5 - }], - "row_4": [{ - "text": strClose, - "symbol": strClose, - "width": 1.5 - }, { - "text": "123", - "symbol": 'ABC', - "width": 1.5 - }, { - "text": ' ', - "symbol": ' ', - "width": 4.5 - }, { - "text": '.', - "symbol": '.', - "width": 1 - }, { - "text": strEnter, - "symbol": strEnter, - "width": 1.5 - }] - } - - //Here is the corresponding table between the ascii and the key event - property var tableKeyEvent: { - "_0": Qt.Key_0, - "_1": Qt.Key_1, - "_2": Qt.Key_2, - "_3": Qt.Key_3, - "_4": Qt.Key_4, - "_5": Qt.Key_5, - "_6": Qt.Key_6, - "_7": Qt.Key_7, - "_8": Qt.Key_8, - "_9": Qt.Key_9, - "_a": Qt.Key_A, - "_b": Qt.Key_B, - "_c": Qt.Key_C, - "_d": Qt.Key_D, - "_e": Qt.Key_E, - "_f": Qt.Key_F, - "_g": Qt.Key_G, - "_h": Qt.Key_H, - "_i": Qt.Key_I, - "_j": Qt.Key_J, - "_k": Qt.Key_K, - "_l": Qt.Key_L, - "_m": Qt.Key_M, - "_n": Qt.Key_N, - "_o": Qt.Key_O, - "_p": Qt.Key_P, - "_q": Qt.Key_Q, - "_r": Qt.Key_R, - "_s": Qt.Key_S, - "_t": Qt.Key_T, - "_u": Qt.Key_U, - "_v": Qt.Key_V, - "_w": Qt.Key_W, - "_x": Qt.Key_X, - "_y": Qt.Key_Y, - "_z": Qt.Key_Z, - "_←": Qt.Key_Backspace, - "_return": Qt.Key_Return, - "_ ": Qt.Key_Space, - "_-": Qt.Key_Minus, - "_/": Qt.Key_Slash, - "_:": Qt.Key_Colon, - "_;": Qt.Key_Semicolon, - "_(": Qt.Key_BracketLeft, - "_)": Qt.Key_BracketRight, - "_€": parseInt( - "20ac", - 16) // I didn't find the appropriate Qt event so I used the hex format - , - "_&": Qt.Key_Ampersand, - "_@": Qt.Key_At, - '_"': Qt.Key_QuoteDbl, - "_.": Qt.Key_Period, - "_,": Qt.Key_Comma, - "_?": Qt.Key_Question, - "_!": Qt.Key_Exclam, - "_'": Qt.Key_Apostrophe, - "_%": Qt.Key_Percent, - "_*": Qt.Key_Asterisk -} - -Item { -id: keyboard_container -anchors.left: parent.left -anchors.leftMargin: 5 -anchors.right: parent.right -anchors.top: parent.top -anchors.topMargin: 5 -anchors.bottom: parent.bottom -anchors.bottomMargin: 5 - -//One column which contains 5 rows -Column { -spacing: columnSpacing - -Row { -id: row_1 -spacing: rowSpacing -Repeater { -model: modelKeyboard["row_1"] -delegate: CustomButtonKeyboard { -text: symbols ? modelData.symbol : shift ? modelData.text.toUpperCase -() : modelData.text -width: modelData.width * keyboard_container.width / columns - rowSpacing -height: keyboard_container.height / rows - columnSpacing - -onClicked: root.clicked(text) -} -} -} -Row { -id: row_2 -spacing: rowSpacing -Repeater { -model: modelKeyboard["row_2"] -delegate: CustomButtonKeyboard { -text: symbols ? modelData.symbol : shift ? modelData.text.toUpperCase -() : modelData.text -width: modelData.width * keyboard_container.width / columns - rowSpacing -height: keyboard_container.height / rows - columnSpacing - -onClicked: root.clicked(text) -} -} -} -Row { -id: row_3 -spacing: rowSpacing -Repeater { -model: modelKeyboard["row_3"] -delegate: CustomButtonKeyboard { -text: symbols ? modelData.symbol : shift ? modelData.text.toUpperCase -() : modelData.text -width: modelData.width * keyboard_container.width / columns - rowSpacing -height: keyboard_container.height / rows - columnSpacing -isShift: shift && text === strShift - -onClicked: root.clicked(text) -} -} -} -Row { -id: row_4 -spacing: rowSpacing -Repeater { -model: modelKeyboard["row_4"] -delegate: CustomButtonKeyboard { -text: symbols ? modelData.symbol : shift ? modelData.text.toUpperCase -() : modelData.text -width: modelData.width * keyboard_container.width / columns - rowSpacing -height: keyboard_container.height / rows - columnSpacing - -onClicked: root.clicked(text) -} -} -} -} -} -signal clicked(string text) - -Connections { -target: root -function onClicked(text) { -if (!keyboard_controller.target) -return -if (text === strShift) { -root.shift = !root.shift -} else if (text === '123') { -root.symbols = true -} else if (text === 'ABC') { -root.symbols = false -} else if (text === strEnter) { -if (keyboard_controller.target.accepted) { -keyboard_controller.target.accepted() -} -} else if (text === strClose) { -root.dismissed() -} else { -if (text === strBackspace) { -var current = keyboard_controller.target.text -keyboard_controller.target.text = current.slice(0, current.length - 1) -} else { -var charToInsert = root.symbols ? text : (root.shift ? text.toUpperCase -() : text) -var current = keyboard_controller.target.text -var cursorPos = keyboard_controller.target.cursorPosition -keyboard_controller.target.text = current.slice(0, -cursorPos) + charToInsert + current.slice(cursorPos) -keyboard_controller.target.cursorPosition = cursorPos + 1 -} - -if (root.shift && text !== strShift) -root.shift = false -} -} -} -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/KeyboardController.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/KeyboardController.qml deleted file mode 100644 index 09d77a5..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/KeyboardController.qml +++ /dev/null @@ -1,40 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick - -Item { - id: keyboard_controller - - // reference on the TextInput - property Item target - //Booléan on the state of the keyboard - property bool isKeyboardActive: false - - property var rootObject - - function show() { - if (!isKeyboardActive && keyboard === null) { - keyboard = keyboardComponent.createObject( - keyboard_controller.rootObject) - keyboard.target = keyboard_controller.target - keyboard.dismissed.connect(hide) - isKeyboardActive = true - } else - console.log("The keyboard is already shown") - } - - function hide() { - if (isKeyboardActive && keyboard !== null) { - keyboard.destroy() - isKeyboardActive = false - } else - console.log("The keyboard is already hidden") - } - - // private - property Item keyboard: null - Component { - id: keyboardComponent - Keyboard {} - } -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/Lock.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/Lock.qml deleted file mode 100644 index 9a5a00f..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/Lock.qml +++ /dev/null @@ -1,296 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import Quickshell -import Quickshell.Io -import Quickshell.Wayland -import qs.Common -import qs.Services - -Scope { - id: root - - property string sharedPasswordBuffer: "" - property bool shouldLock: false - - onShouldLockChanged: { - IdleService.isShellLocked = shouldLock; - if (shouldLock && lockPowerOffArmed) { - lockStateCheck.restart(); - } - } - - Timer { - id: lockStateCheck - interval: 100 - repeat: false - onTriggered: { - if (sessionLock.locked && lockPowerOffArmed) { - pendingLock = false; - IdleService.monitorsOff = true; - CompositorService.powerOffMonitors(); - lockWakeAllowed = false; - lockWakeDebounce.restart(); - lockPowerOffArmed = false; - dpmsReapplyTimer.start(); - } - } - } - - property bool lockInitiatedLocally: false - property bool pendingLock: false - property bool lockPowerOffArmed: false - property bool lockWakeAllowed: false - - Component.onCompleted: { - IdleService.lockComponent = this; - if (SettingsData.lockAtStartup) - lock(); - } - - function notifyLoginctl(lockAction: bool) { - if (!SettingsData.loginctlLockIntegration || !DMSService.isConnected) - return; - if (lockAction) - DMSService.lockSession(() => {}); - else - DMSService.unlockSession(() => {}); - } - - function lock() { - if (SettingsData.customPowerActionLock?.length > 0) { - Quickshell.execDetached(["sh", "-c", SettingsData.customPowerActionLock]); - return; - } - if (shouldLock || pendingLock) - return; - - lockInitiatedLocally = true; - lockPowerOffArmed = SettingsData.lockScreenPowerOffMonitorsOnLock; - - if (!SessionService.active && SessionService.loginctlAvailable && SettingsData.loginctlLockIntegration) { - pendingLock = true; - notifyLoginctl(true); - return; - } - - shouldLock = true; - notifyLoginctl(true); - } - - function unlock() { - if (!shouldLock) - return; - lockInitiatedLocally = false; - notifyLoginctl(false); - shouldLock = false; - } - - function forceReset() { - lockInitiatedLocally = false; - pendingLock = false; - shouldLock = false; - } - - function activate() { - lock(); - } - - Connections { - target: SessionService - - function onSessionLocked() { - if (shouldLock || pendingLock) - return; - if (!SessionService.active && SessionService.loginctlAvailable && SettingsData.loginctlLockIntegration) { - pendingLock = true; - lockInitiatedLocally = false; - return; - } - lockInitiatedLocally = false; - lockPowerOffArmed = SettingsData.lockScreenPowerOffMonitorsOnLock; - shouldLock = true; - } - - function onSessionUnlocked() { - if (pendingLock) { - pendingLock = false; - lockInitiatedLocally = false; - return; - } - if (!shouldLock || lockInitiatedLocally) - return; - shouldLock = false; - } - - function onLoginctlStateChanged() { - if (SessionService.active && pendingLock) { - pendingLock = false; - lockInitiatedLocally = true; - lockPowerOffArmed = SettingsData.lockScreenPowerOffMonitorsOnLock; - shouldLock = true; - return; - } - if (SessionService.locked && !shouldLock && !pendingLock) { - lockInitiatedLocally = false; - lockPowerOffArmed = SettingsData.lockScreenPowerOffMonitorsOnLock; - shouldLock = true; - } - } - } - - Connections { - target: IdleService - - function onLockRequested() { - lock(); - } - } - - WlSessionLock { - id: sessionLock - - locked: shouldLock - - WlSessionLockSurface { - id: lockSurface - - property string currentScreenName: screen?.name ?? "" - property bool isActiveScreen: { - if (Quickshell.screens.length <= 1) - return true; - if (SettingsData.lockScreenActiveMonitor === "all") - return true; - return currentScreenName === SettingsData.lockScreenActiveMonitor; - } - - color: isActiveScreen ? "transparent" : SettingsData.lockScreenInactiveColor - - LockSurface { - anchors.fill: parent - visible: lockSurface.isActiveScreen - lock: sessionLock - sharedPasswordBuffer: root.sharedPasswordBuffer - screenName: lockSurface.currentScreenName - isLocked: shouldLock - onUnlockRequested: root.unlock() - onPasswordChanged: newPassword => { - root.sharedPasswordBuffer = newPassword; - } - } - } - } - - Connections { - target: sessionLock - - function onLockedChanged() { - if (sessionLock.locked) { - pendingLock = false; - if (lockPowerOffArmed && SettingsData.lockScreenPowerOffMonitorsOnLock) { - IdleService.monitorsOff = true; - CompositorService.powerOffMonitors(); - lockWakeAllowed = false; - lockWakeDebounce.restart(); - } - lockPowerOffArmed = false; - dpmsReapplyTimer.start(); - return; - } - - lockWakeAllowed = false; - if (IdleService.monitorsOff && SettingsData.lockScreenPowerOffMonitorsOnLock) { - IdleService.monitorsOff = false; - CompositorService.powerOnMonitors(); - } - } - } - - LockScreenDemo { - id: demoWindow - } - - IpcHandler { - target: "lock" - - function lock() { - root.lock(); - } - - function unlock() { - root.unlock(); - } - - function forceReset() { - root.forceReset(); - } - - function demo() { - demoWindow.showDemo(); - } - - function isLocked(): bool { - return sessionLock.locked; - } - - function status(): string { - return JSON.stringify({ - shouldLock: root.shouldLock, - sessionLockLocked: sessionLock.locked, - lockInitiatedLocally: root.lockInitiatedLocally, - pendingLock: root.pendingLock, - loginctlLocked: SessionService.locked, - loginctlActive: SessionService.active - }); - } - } - - Timer { - id: dpmsReapplyTimer - interval: 100 - repeat: false - onTriggered: IdleService.reapplyDpmsIfNeeded() - } - - Timer { - id: lockWakeDebounce - interval: 200 - repeat: false - onTriggered: { - if (!sessionLock.locked) - return; - if (!SettingsData.lockScreenPowerOffMonitorsOnLock) - return; - if (!IdleService.monitorsOff) { - lockWakeAllowed = true; - return; - } - if (lockWakeAllowed) { - IdleService.monitorsOff = false; - CompositorService.powerOnMonitors(); - } else { - lockWakeAllowed = true; - } - } - } - - MouseArea { - anchors.fill: parent - enabled: sessionLock.locked - hoverEnabled: enabled - onPressed: lockWakeDebounce.restart() - onPositionChanged: lockWakeDebounce.restart() - onWheel: lockWakeDebounce.restart() - } - - FocusScope { - anchors.fill: parent - focus: sessionLock.locked - - Keys.onPressed: event => { - if (!sessionLock.locked) - return; - lockWakeDebounce.restart(); - } - } -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/LockPowerMenu.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/LockPowerMenu.qml deleted file mode 100644 index 0a0ee84..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/LockPowerMenu.qml +++ /dev/null @@ -1,820 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import QtQuick.Effects -import qs.Common -import qs.Services -import qs.Widgets - -Rectangle { - id: root - - property bool isVisible: false - property bool showLogout: true - property int selectedIndex: 0 - property int selectedRow: 0 - property int selectedCol: 0 - property var visibleActions: [] - property int gridColumns: 3 - property int gridRows: 2 - property bool useGridLayout: false - - property string holdAction: "" - property int holdActionIndex: -1 - property real holdProgress: 0 - property bool showHoldHint: false - - property var powerActionConfirmOverride: undefined - property var powerActionHoldDurationOverride: undefined - property var powerMenuActionsOverride: undefined - property var powerMenuDefaultActionOverride: undefined - property var powerMenuGridLayoutOverride: undefined - property var requiredActions: [] - - readonly property bool needsConfirmation: powerActionConfirmOverride !== undefined ? powerActionConfirmOverride : SettingsData.powerActionConfirm - readonly property int holdDurationMs: (powerActionHoldDurationOverride !== undefined ? powerActionHoldDurationOverride : SettingsData.powerActionHoldDuration) * 1000 - - signal closed - - function updateVisibleActions() { - const allActions = powerMenuActionsOverride !== undefined ? powerMenuActionsOverride : ((typeof SettingsData !== "undefined" && SettingsData.powerMenuActions) ? SettingsData.powerMenuActions : ["logout", "suspend", "hibernate", "reboot", "poweroff"]); - const hibernateSupported = (typeof SessionService !== "undefined" && SessionService.hibernateSupported) || false; - let filtered = allActions.filter(action => { - if (action === "hibernate" && !hibernateSupported) - return false; - if (action === "lock") - return false; - if (action === "restart") - return false; - if (action === "logout" && !showLogout) - return false; - return true; - }); - - for (const action of requiredActions) { - if (!filtered.includes(action)) - filtered.push(action); - } - - visibleActions = filtered; - - useGridLayout = powerMenuGridLayoutOverride !== undefined ? powerMenuGridLayoutOverride : ((typeof SettingsData !== "undefined" && SettingsData.powerMenuGridLayout !== undefined) ? SettingsData.powerMenuGridLayout : false); - if (!useGridLayout) - return; - const count = visibleActions.length; - if (count === 0) { - gridColumns = 1; - gridRows = 1; - return; - } - - if (count <= 3) { - gridColumns = 1; - gridRows = count; - return; - } - - if (count === 4) { - gridColumns = 2; - gridRows = 2; - return; - } - - gridColumns = 3; - gridRows = Math.ceil(count / 3); - } - - function getDefaultActionIndex() { - const defaultAction = powerMenuDefaultActionOverride !== undefined ? powerMenuDefaultActionOverride : ((typeof SettingsData !== "undefined" && SettingsData.powerMenuDefaultAction) ? SettingsData.powerMenuDefaultAction : "suspend"); - const index = visibleActions.indexOf(defaultAction); - return index >= 0 ? index : 0; - } - - function getActionAtIndex(index) { - if (index < 0 || index >= visibleActions.length) - return ""; - return visibleActions[index]; - } - - function getActionData(action) { - switch (action) { - case "reboot": - return { - "icon": "restart_alt", - "label": I18n.tr("Reboot"), - "key": "R" - }; - case "logout": - return { - "icon": "logout", - "label": I18n.tr("Log Out"), - "key": "X" - }; - case "poweroff": - return { - "icon": "power_settings_new", - "label": I18n.tr("Power Off"), - "key": "P" - }; - case "suspend": - return { - "icon": "bedtime", - "label": I18n.tr("Suspend"), - "key": "S" - }; - case "hibernate": - return { - "icon": "ac_unit", - "label": I18n.tr("Hibernate"), - "key": "H" - }; - default: - return { - "icon": "help", - "label": action, - "key": "?" - }; - } - } - - function actionNeedsConfirm(action) { - return action !== "lock" && action !== "restart"; - } - - function startHold(action, actionIndex) { - if (!needsConfirmation || !actionNeedsConfirm(action)) { - executeAction(action); - return; - } - holdAction = action; - holdActionIndex = actionIndex; - holdProgress = 0; - showHoldHint = false; - holdTimer.start(); - } - - function cancelHold() { - if (holdAction === "") - return; - const wasHolding = holdProgress > 0; - holdTimer.stop(); - if (wasHolding && holdProgress < 1) { - showHoldHint = true; - hintTimer.restart(); - } - holdAction = ""; - holdActionIndex = -1; - holdProgress = 0; - } - - function completeHold() { - if (holdProgress < 1) { - cancelHold(); - return; - } - const action = holdAction; - holdTimer.stop(); - holdAction = ""; - holdActionIndex = -1; - holdProgress = 0; - executeAction(action); - } - - function executeAction(action) { - if (!action) - return; - if (typeof SessionService === "undefined") - return; - hide(); - switch (action) { - case "logout": - SessionService.logout(); - break; - case "suspend": - SessionService.suspend(); - break; - case "hibernate": - SessionService.hibernate(); - break; - case "reboot": - SessionService.reboot(); - break; - case "poweroff": - SessionService.poweroff(); - break; - } - } - - function selectOption(action, actionIndex) { - startHold(action, actionIndex !== undefined ? actionIndex : -1); - } - - function show() { - holdAction = ""; - holdActionIndex = -1; - holdProgress = 0; - showHoldHint = false; - updateVisibleActions(); - const defaultIndex = getDefaultActionIndex(); - if (useGridLayout) { - selectedRow = Math.floor(defaultIndex / gridColumns); - selectedCol = defaultIndex % gridColumns; - selectedIndex = defaultIndex; - } else { - selectedIndex = defaultIndex; - } - isVisible = true; - Qt.callLater(() => powerMenuFocusScope.forceActiveFocus()); - } - - function hide() { - cancelHold(); - isVisible = false; - closed(); - } - - function handleListNavigation(event, isPressed) { - if (!isPressed) { - if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter || event.key === Qt.Key_R || event.key === Qt.Key_X || event.key === Qt.Key_S || event.key === Qt.Key_H || (event.key === Qt.Key_P && !(event.modifiers & Qt.ControlModifier))) { - cancelHold(); - event.accepted = true; - } - return; - } - - switch (event.key) { - case Qt.Key_Up: - case Qt.Key_Backtab: - selectedIndex = (selectedIndex - 1 + visibleActions.length) % visibleActions.length; - event.accepted = true; - break; - case Qt.Key_Down: - case Qt.Key_Tab: - selectedIndex = (selectedIndex + 1) % visibleActions.length; - event.accepted = true; - break; - case Qt.Key_Return: - case Qt.Key_Enter: - startHold(getActionAtIndex(selectedIndex), selectedIndex); - event.accepted = true; - break; - case Qt.Key_N: - if (event.modifiers & Qt.ControlModifier) { - selectedIndex = (selectedIndex + 1) % visibleActions.length; - event.accepted = true; - } - break; - case Qt.Key_P: - if (!(event.modifiers & Qt.ControlModifier)) { - const idx = visibleActions.indexOf("poweroff"); - startHold("poweroff", idx); - event.accepted = true; - } else { - selectedIndex = (selectedIndex - 1 + visibleActions.length) % visibleActions.length; - event.accepted = true; - } - break; - case Qt.Key_J: - if (event.modifiers & Qt.ControlModifier) { - selectedIndex = (selectedIndex + 1) % visibleActions.length; - event.accepted = true; - } - break; - case Qt.Key_K: - if (event.modifiers & Qt.ControlModifier) { - selectedIndex = (selectedIndex - 1 + visibleActions.length) % visibleActions.length; - event.accepted = true; - } - break; - case Qt.Key_R: - startHold("reboot", visibleActions.indexOf("reboot")); - event.accepted = true; - break; - case Qt.Key_X: - startHold("logout", visibleActions.indexOf("logout")); - event.accepted = true; - break; - case Qt.Key_S: - startHold("suspend", visibleActions.indexOf("suspend")); - event.accepted = true; - break; - case Qt.Key_H: - startHold("hibernate", visibleActions.indexOf("hibernate")); - event.accepted = true; - break; - } - } - - function handleGridNavigation(event, isPressed) { - if (!isPressed) { - if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter || event.key === Qt.Key_R || event.key === Qt.Key_X || event.key === Qt.Key_S || event.key === Qt.Key_H || (event.key === Qt.Key_P && !(event.modifiers & Qt.ControlModifier))) { - cancelHold(); - event.accepted = true; - } - return; - } - - switch (event.key) { - case Qt.Key_Left: - selectedCol = (selectedCol - 1 + gridColumns) % gridColumns; - selectedIndex = selectedRow * gridColumns + selectedCol; - event.accepted = true; - break; - case Qt.Key_Right: - selectedCol = (selectedCol + 1) % gridColumns; - selectedIndex = selectedRow * gridColumns + selectedCol; - event.accepted = true; - break; - case Qt.Key_Up: - case Qt.Key_Backtab: - selectedRow = (selectedRow - 1 + gridRows) % gridRows; - selectedIndex = selectedRow * gridColumns + selectedCol; - event.accepted = true; - break; - case Qt.Key_Down: - case Qt.Key_Tab: - selectedRow = (selectedRow + 1) % gridRows; - selectedIndex = selectedRow * gridColumns + selectedCol; - event.accepted = true; - break; - case Qt.Key_Return: - case Qt.Key_Enter: - startHold(getActionAtIndex(selectedIndex), selectedIndex); - event.accepted = true; - break; - case Qt.Key_N: - if (event.modifiers & Qt.ControlModifier) { - selectedCol = (selectedCol + 1) % gridColumns; - selectedIndex = selectedRow * gridColumns + selectedCol; - event.accepted = true; - } - break; - case Qt.Key_P: - if (!(event.modifiers & Qt.ControlModifier)) { - const idx = visibleActions.indexOf("poweroff"); - startHold("poweroff", idx); - event.accepted = true; - } else { - selectedCol = (selectedCol - 1 + gridColumns) % gridColumns; - selectedIndex = selectedRow * gridColumns + selectedCol; - event.accepted = true; - } - break; - case Qt.Key_J: - if (event.modifiers & Qt.ControlModifier) { - selectedRow = (selectedRow + 1) % gridRows; - selectedIndex = selectedRow * gridColumns + selectedCol; - event.accepted = true; - } - break; - case Qt.Key_K: - if (event.modifiers & Qt.ControlModifier) { - selectedRow = (selectedRow - 1 + gridRows) % gridRows; - selectedIndex = selectedRow * gridColumns + selectedCol; - event.accepted = true; - } - break; - case Qt.Key_R: - startHold("reboot", visibleActions.indexOf("reboot")); - event.accepted = true; - break; - case Qt.Key_X: - startHold("logout", visibleActions.indexOf("logout")); - event.accepted = true; - break; - case Qt.Key_S: - startHold("suspend", visibleActions.indexOf("suspend")); - event.accepted = true; - break; - case Qt.Key_H: - startHold("hibernate", visibleActions.indexOf("hibernate")); - event.accepted = true; - break; - } - } - - anchors.fill: parent - color: Qt.rgba(0, 0, 0, 0.5) - visible: isVisible - z: 1000 - - MouseArea { - anchors.fill: parent - onClicked: root.hide() - } - - Timer { - id: holdTimer - interval: 16 - repeat: true - onTriggered: { - root.holdProgress = Math.min(1, root.holdProgress + (interval / root.holdDurationMs)); - if (root.holdProgress >= 1) { - stop(); - root.completeHold(); - } - } - } - - Timer { - id: hintTimer - interval: 2000 - onTriggered: root.showHoldHint = false - } - - FocusScope { - id: powerMenuFocusScope - anchors.fill: parent - focus: root.isVisible - - onVisibleChanged: { - if (visible) - Qt.callLater(() => forceActiveFocus()); - } - - Keys.onEscapePressed: root.hide() - Keys.onPressed: event => { - if (event.isAutoRepeat) { - event.accepted = true; - return; - } - if (useGridLayout) { - handleGridNavigation(event, true); - } else { - handleListNavigation(event, true); - } - } - Keys.onReleased: event => { - if (event.isAutoRepeat) { - event.accepted = true; - return; - } - if (useGridLayout) { - handleGridNavigation(event, false); - } else { - handleListNavigation(event, false); - } - } - - Rectangle { - anchors.centerIn: parent - width: useGridLayout ? Math.min(550, gridColumns * 180 + Theme.spacingS * (gridColumns - 1) + Theme.spacingL * 2) : 320 - height: contentItem.implicitHeight + Theme.spacingL * 2 - radius: Theme.cornerRadius - color: Theme.surfaceContainer - border.color: Theme.outlineMedium - border.width: 1 - - Item { - id: contentItem - anchors.fill: parent - anchors.margins: Theme.spacingL - implicitHeight: headerRow.height + Theme.spacingM + (useGridLayout ? buttonGrid.implicitHeight : buttonColumn.implicitHeight) + (root.needsConfirmation ? hintRow.height + Theme.spacingM : 0) - - Row { - id: headerRow - width: parent.width - height: 30 - - StyledText { - text: I18n.tr("Power Options") - font.pixelSize: Theme.fontSizeLarge - color: Theme.surfaceText - font.weight: Font.Medium - anchors.verticalCenter: parent.verticalCenter - } - - Item { - width: parent.width - 150 - height: 1 - } - - DankActionButton { - iconName: "close" - iconSize: Theme.iconSize - 4 - iconColor: Theme.surfaceText - onClicked: root.hide() - } - } - - Grid { - id: buttonGrid - visible: useGridLayout - anchors.top: headerRow.bottom - anchors.topMargin: Theme.spacingM - anchors.horizontalCenter: parent.horizontalCenter - columns: root.gridColumns - columnSpacing: Theme.spacingS - rowSpacing: Theme.spacingS - width: parent.width - - Repeater { - model: root.visibleActions - - Rectangle { - id: gridButtonRect - required property int index - required property string modelData - - readonly property var actionData: root.getActionData(modelData) - readonly property bool isSelected: root.selectedIndex === index - readonly property bool showWarning: modelData === "reboot" || modelData === "poweroff" - readonly property bool isHolding: root.holdActionIndex === index && root.holdProgress > 0 - - width: (contentItem.width - Theme.spacingS * (root.gridColumns - 1)) / root.gridColumns - height: 100 - radius: Theme.cornerRadius - color: { - if (isSelected) - return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12); - if (mouseArea.containsMouse) - return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08); - return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08); - } - border.color: isSelected ? Theme.primary : "transparent" - border.width: isSelected ? 2 : 0 - - Rectangle { - id: gridProgressMask - anchors.fill: parent - radius: parent.radius - visible: false - layer.enabled: true - } - - Item { - anchors.fill: parent - visible: gridButtonRect.isHolding - layer.enabled: gridButtonRect.isHolding - layer.effect: MultiEffect { - maskEnabled: true - maskSource: gridProgressMask - maskSpreadAtMin: 1 - maskThresholdMin: 0.5 - } - - Rectangle { - anchors.left: parent.left - anchors.top: parent.top - anchors.bottom: parent.bottom - width: parent.width * root.holdProgress - color: { - if (gridButtonRect.modelData === "poweroff") - return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.3); - if (gridButtonRect.modelData === "reboot") - return Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.3); - return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3); - } - } - } - - Column { - anchors.centerIn: parent - spacing: Theme.spacingS - - DankIcon { - name: gridButtonRect.actionData.icon - size: Theme.iconSize + 8 - color: { - if (gridButtonRect.showWarning && (mouseArea.containsMouse || gridButtonRect.isHolding)) { - return gridButtonRect.modelData === "poweroff" ? Theme.error : Theme.warning; - } - return Theme.surfaceText; - } - anchors.horizontalCenter: parent.horizontalCenter - } - - StyledText { - text: gridButtonRect.actionData.label - font.pixelSize: Theme.fontSizeMedium - color: { - if (gridButtonRect.showWarning && (mouseArea.containsMouse || gridButtonRect.isHolding)) { - return gridButtonRect.modelData === "poweroff" ? Theme.error : Theme.warning; - } - return Theme.surfaceText; - } - font.weight: Font.Medium - anchors.horizontalCenter: parent.horizontalCenter - } - - Rectangle { - width: 20 - height: 16 - radius: 4 - color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.1) - anchors.horizontalCenter: parent.horizontalCenter - - StyledText { - text: gridButtonRect.actionData.key - font.pixelSize: Theme.fontSizeSmall - 1 - color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6) - font.weight: Font.Medium - anchors.centerIn: parent - } - } - } - - MouseArea { - id: mouseArea - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onPressed: { - root.selectedRow = Math.floor(index / root.gridColumns); - root.selectedCol = index % root.gridColumns; - root.selectedIndex = index; - root.startHold(modelData, index); - } - onReleased: root.cancelHold() - onCanceled: root.cancelHold() - } - } - } - } - - Column { - id: buttonColumn - visible: !useGridLayout - anchors.top: headerRow.bottom - anchors.topMargin: Theme.spacingM - anchors.left: parent.left - anchors.right: parent.right - spacing: Theme.spacingS - - Repeater { - model: root.visibleActions - - Rectangle { - id: listButtonRect - required property int index - required property string modelData - - readonly property var actionData: root.getActionData(modelData) - readonly property bool isSelected: root.selectedIndex === index - readonly property bool showWarning: modelData === "reboot" || modelData === "poweroff" - readonly property bool isHolding: root.holdActionIndex === index && root.holdProgress > 0 - - width: parent.width - height: 50 - radius: Theme.cornerRadius - color: { - if (isSelected) - return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12); - if (listMouseArea.containsMouse) - return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.08); - return Qt.rgba(Theme.surfaceVariant.r, Theme.surfaceVariant.g, Theme.surfaceVariant.b, 0.08); - } - border.color: isSelected ? Theme.primary : "transparent" - border.width: isSelected ? 2 : 0 - - Rectangle { - id: listProgressMask - anchors.fill: parent - radius: parent.radius - visible: false - layer.enabled: true - } - - Item { - anchors.fill: parent - visible: listButtonRect.isHolding - layer.enabled: listButtonRect.isHolding - layer.effect: MultiEffect { - maskEnabled: true - maskSource: listProgressMask - maskSpreadAtMin: 1 - maskThresholdMin: 0.5 - } - - Rectangle { - anchors.left: parent.left - anchors.top: parent.top - anchors.bottom: parent.bottom - width: parent.width * root.holdProgress - color: { - if (listButtonRect.modelData === "poweroff") - return Qt.rgba(Theme.error.r, Theme.error.g, Theme.error.b, 0.3); - if (listButtonRect.modelData === "reboot") - return Qt.rgba(Theme.warning.r, Theme.warning.g, Theme.warning.b, 0.3); - return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3); - } - } - } - - Row { - anchors.left: parent.left - anchors.right: parent.right - anchors.leftMargin: Theme.spacingM - anchors.rightMargin: Theme.spacingM - anchors.verticalCenter: parent.verticalCenter - spacing: Theme.spacingM - - DankIcon { - name: listButtonRect.actionData.icon - size: Theme.iconSize + 4 - color: { - if (listButtonRect.showWarning && (listMouseArea.containsMouse || listButtonRect.isHolding)) { - return listButtonRect.modelData === "poweroff" ? Theme.error : Theme.warning; - } - return Theme.surfaceText; - } - anchors.verticalCenter: parent.verticalCenter - } - - StyledText { - text: listButtonRect.actionData.label - font.pixelSize: Theme.fontSizeMedium - color: { - if (listButtonRect.showWarning && (listMouseArea.containsMouse || listButtonRect.isHolding)) { - return listButtonRect.modelData === "poweroff" ? Theme.error : Theme.warning; - } - return Theme.surfaceText; - } - font.weight: Font.Medium - anchors.verticalCenter: parent.verticalCenter - } - } - - Rectangle { - width: 28 - height: 20 - radius: 4 - color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.1) - anchors.right: parent.right - anchors.rightMargin: Theme.spacingM - anchors.verticalCenter: parent.verticalCenter - - StyledText { - text: listButtonRect.actionData.key - font.pixelSize: Theme.fontSizeSmall - color: Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6) - font.weight: Font.Medium - anchors.centerIn: parent - } - } - - MouseArea { - id: listMouseArea - anchors.fill: parent - hoverEnabled: true - cursorShape: Qt.PointingHandCursor - onPressed: { - root.selectedIndex = index; - root.startHold(modelData, index); - } - onReleased: root.cancelHold() - onCanceled: root.cancelHold() - } - } - } - } - - Row { - id: hintRow - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: parent.bottom - anchors.bottomMargin: Theme.spacingS - spacing: Theme.spacingXS - visible: root.needsConfirmation - opacity: root.showHoldHint ? 1 : 0.5 - - Behavior on opacity { - NumberAnimation { - duration: 150 - } - } - - DankIcon { - name: root.showHoldHint ? "warning" : "touch_app" - size: Theme.fontSizeSmall - color: root.showHoldHint ? Theme.warning : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6) - anchors.verticalCenter: parent.verticalCenter - } - - StyledText { - readonly property real totalMs: root.holdDurationMs - readonly property int remainingMs: Math.ceil(totalMs * (1 - root.holdProgress)) - readonly property real durationSec: root.holdDurationMs / 1000 - text: { - if (root.showHoldHint) - return I18n.tr("Hold longer to confirm"); - if (root.holdProgress > 0) { - if (totalMs < 1000) - return I18n.tr("Hold to confirm (%1 ms)").arg(remainingMs); - return I18n.tr("Hold to confirm (%1s)").arg(Math.ceil(remainingMs / 1000)); - } - if (totalMs < 1000) - return I18n.tr("Hold to confirm (%1 ms)").arg(totalMs); - return I18n.tr("Hold to confirm (%1s)").arg(durationSec); - } - font.pixelSize: Theme.fontSizeSmall - color: root.showHoldHint ? Theme.warning : Qt.rgba(Theme.surfaceText.r, Theme.surfaceText.g, Theme.surfaceText.b, 0.6) - anchors.verticalCenter: parent.verticalCenter - } - } - } - } - } - - Component.onCompleted: updateVisibleActions() -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/LockScreenContent.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/LockScreenContent.qml deleted file mode 100644 index b296e98..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/LockScreenContent.qml +++ /dev/null @@ -1,1707 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import QtQuick.Effects -import QtQuick.Layouts -import QtQuick.Window -import Quickshell -import Quickshell.Hyprland -import Quickshell.Io -import Quickshell.Services.Mpris -import qs.Common -import qs.Services -import qs.Widgets - -Item { - id: root - - function encodeFileUrl(path) { - if (!path) - return ""; - return "file://" + path.split('/').map(s => encodeURIComponent(s)).join('/'); - } - - property string passwordBuffer: "" - property bool demoMode: false - property string screenName: "" - property bool unlocking: false - property string pamState: "" - property string hyprlandCurrentLayout: "" - property string hyprlandKeyboard: "" - property int hyprlandLayoutCount: 0 - property bool lockerReadySent: false - property bool lockerReadyArmed: false - - signal unlockRequested - - function resetLockState() { - lockerReadySent = false; - lockerReadyArmed = true; - unlocking = false; - pamState = ""; - if (pam) - pam.lockMessage = ""; - } - - function currentAuthFeedbackText() { - if (!pam) - return ""; - if (pam.u2fState === "insert" && !pam.u2fPending) - return I18n.tr("Insert your security key..."); - if (pam.u2fState === "waiting" && !pam.u2fPending) - return I18n.tr("Touch your security key..."); - if (pam.lockMessage && pam.lockMessage.length > 0) - return pam.lockMessage; - if (root.pamState === "error") - return I18n.tr("Authentication error - try again"); - if (root.pamState === "max") - return I18n.tr("Too many attempts - locked out"); - if (root.pamState === "fail") - return I18n.tr("Incorrect password - try again"); - if (pam.fprintState === "error") { - const detail = (pam.fprint.message || "").trim(); - return detail.length > 0 ? I18n.tr("Fingerprint error: %1").arg(detail) : I18n.tr("Fingerprint error"); - } - if (pam.fprintState === "max") - return I18n.tr("Maximum fingerprint attempts reached. Please use password."); - if (pam.fprintState === "fail") - return I18n.tr("Fingerprint not recognized (%1/%2). Please try again or use password.").arg(pam.fprint.tries).arg(SettingsData.maxFprintTries); - return ""; - } - - function authFeedbackIsHint() { - return pam && (pam.u2fState === "waiting" || pam.u2fState === "insert") && !pam.u2fPending; - } - - Component.onCompleted: { - WeatherService.addRef(); - UserInfoService.getUserInfo(); - - if (CompositorService.isHyprland) - updateHyprlandLayout(); - - lockerReadyArmed = true; - } - - Component.onDestruction: { - WeatherService.removeRef(); - } - - function sendLockerReadyOnce() { - if (lockerReadySent) - return; - if (root.unlocking) - return; - lockerReadySent = true; - if (SessionService.loginctlAvailable && DMSService.apiVersion >= 2) { - DMSService.sendRequest("loginctl.lockerReady", null, resp => { - if (resp?.error) - console.warn("lockerReady failed:", resp.error); - else - console.log("lockerReady sent (afterAnimating/afterRendering)"); - }); - } - } - - function maybeSend() { - if (!lockerReadyArmed) - return; - if (root.unlocking) - return; - if (!root.visible || root.opacity <= 0) - return; - Qt.callLater(() => { - if (root.visible && root.opacity > 0 && !root.unlocking) - sendLockerReadyOnce(); - }); - } - - Connections { - target: root.Window.window - enabled: target !== null - - function onAfterAnimating() { - maybeSend(); - } - function onAfterRendering() { - maybeSend(); - } - } - - onVisibleChanged: maybeSend() - onOpacityChanged: maybeSend() - - function updateHyprlandLayout() { - if (CompositorService.isHyprland) { - hyprlandLayoutProcess.running = true; - } - } - - Process { - id: hyprlandLayoutProcess - running: false - command: ["hyprctl", "-j", "devices"] - stdout: StdioCollector { - onStreamFinished: { - try { - const data = JSON.parse(text); - const mainKeyboard = data.keyboards.find(kb => kb.main === true); - if (!mainKeyboard) { - hyprlandCurrentLayout = ""; - hyprlandLayoutCount = 0; - return; - } - hyprlandKeyboard = mainKeyboard.name; - if (mainKeyboard.active_keymap) { - const parts = mainKeyboard.active_keymap.split(" "); - hyprlandCurrentLayout = parts[0].substring(0, 2).toUpperCase(); - } else { - hyprlandCurrentLayout = ""; - } - hyprlandLayoutCount = mainKeyboard.layout ? mainKeyboard.layout.split(",").length : 0; - } catch (e) { - hyprlandCurrentLayout = ""; - hyprlandLayoutCount = 0; - } - } - } - } - - Connections { - target: CompositorService.isHyprland ? Hyprland : null - enabled: CompositorService.isHyprland - - function onRawEvent(event) { - if (event.name === "activelayout") - updateHyprlandLayout(); - } - } - - Loader { - anchors.fill: parent - active: { - var currentWallpaper = SessionData.getMonitorWallpaper(screenName); - return !currentWallpaper || (currentWallpaper && currentWallpaper.startsWith("#")); - } - asynchronous: true - - sourceComponent: DankBackdrop { - screenName: root.screenName - } - } - - Image { - id: wallpaperBackground - - anchors.fill: parent - source: { - var currentWallpaper = SessionData.getMonitorWallpaper(screenName); - return (currentWallpaper && !currentWallpaper.startsWith("#")) ? encodeFileUrl(currentWallpaper) : ""; - } - fillMode: Theme.getFillMode(SessionData.getMonitorWallpaperFillMode(screenName)) - smooth: true - asynchronous: false - cache: true - visible: source !== "" - layer.enabled: true - - layer.effect: MultiEffect { - autoPaddingEnabled: false - blurEnabled: true - blur: 0.8 - blurMax: 32 - blurMultiplier: 1 - } - - Behavior on opacity { - NumberAnimation { - duration: Theme.mediumDuration - easing.type: Theme.standardEasing - } - } - } - - Rectangle { - anchors.fill: parent - color: "black" - opacity: 0.4 - } - - SystemClock { - id: systemClock - - precision: SystemClock.Seconds - } - - Rectangle { - anchors.fill: parent - color: "transparent" - - Item { - id: clockContainer - anchors.horizontalCenter: parent.horizontalCenter - anchors.bottom: parent.verticalCenter - anchors.bottomMargin: 60 - width: parent.width - height: clockText.implicitHeight - visible: SettingsData.lockScreenShowTime - - Row { - id: clockText - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: parent.top - spacing: 0 - - property string fullTimeStr: { - const format = SettingsData.getEffectiveTimeFormat(); - return systemClock.date.toLocaleTimeString(Qt.locale(), format); - } - property var timeParts: fullTimeStr.split(':') - property string hours: timeParts[0] || "" - property string minutes: timeParts[1] || "" - property string secondsWithAmPm: timeParts.length > 2 ? timeParts[2] : "" - property string seconds: secondsWithAmPm.replace(/\s*(AM|PM|am|pm)$/i, '') - property string ampm: { - const match = fullTimeStr.match(/\s*(AM|PM|am|pm)$/i); - return match ? match[0].trim() : ""; - } - property bool hasSeconds: timeParts.length > 2 - - StyledText { - width: 75 - text: clockText.hours.length > 1 ? clockText.hours[0] : "" - font.pixelSize: 120 - font.weight: Font.Light - color: "white" - horizontalAlignment: Text.AlignHCenter - } - - StyledText { - width: 75 - text: clockText.hours.length > 1 ? clockText.hours[1] : clockText.hours.length > 0 ? clockText.hours[0] : "" - font.pixelSize: 120 - font.weight: Font.Light - color: "white" - horizontalAlignment: Text.AlignHCenter - } - - StyledText { - text: ":" - font.pixelSize: 120 - font.weight: Font.Light - color: "white" - } - - StyledText { - width: 75 - text: clockText.minutes.length > 0 ? clockText.minutes[0] : "" - font.pixelSize: 120 - font.weight: Font.Light - color: "white" - horizontalAlignment: Text.AlignHCenter - } - - StyledText { - width: 75 - text: clockText.minutes.length > 1 ? clockText.minutes[1] : "" - font.pixelSize: 120 - font.weight: Font.Light - color: "white" - horizontalAlignment: Text.AlignHCenter - } - - StyledText { - text: clockText.hasSeconds ? ":" : "" - font.pixelSize: 120 - font.weight: Font.Light - color: "white" - visible: clockText.hasSeconds - } - - StyledText { - width: 75 - text: clockText.hasSeconds && clockText.seconds.length > 0 ? clockText.seconds[0] : "" - font.pixelSize: 120 - font.weight: Font.Light - color: "white" - horizontalAlignment: Text.AlignHCenter - visible: clockText.hasSeconds - } - - StyledText { - width: 75 - text: clockText.hasSeconds && clockText.seconds.length > 1 ? clockText.seconds[1] : "" - font.pixelSize: 120 - font.weight: Font.Light - color: "white" - horizontalAlignment: Text.AlignHCenter - visible: clockText.hasSeconds - } - - StyledText { - width: 20 - text: " " - font.pixelSize: 120 - font.weight: Font.Light - color: "white" - visible: clockText.ampm !== "" - } - - StyledText { - text: clockText.ampm - font.pixelSize: 120 - font.weight: Font.Light - color: "white" - visible: clockText.ampm !== "" - } - } - } - - StyledText { - id: dateText - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: clockContainer.bottom - anchors.topMargin: 4 - visible: SettingsData.lockScreenShowDate - text: { - if (SettingsData.lockDateFormat && SettingsData.lockDateFormat.length > 0) { - return systemClock.date.toLocaleDateString(I18n.locale(), SettingsData.lockDateFormat); - } - return systemClock.date.toLocaleDateString(I18n.locale(), Locale.LongFormat); - } - font.pixelSize: Theme.fontSizeXLarge - color: "white" - opacity: 0.9 - } - - Item { - id: lockNotificationPanel - - readonly property int notificationMode: SettingsData.lockScreenNotificationMode - readonly property var notifications: NotificationService.groupedNotifications - readonly property int totalCount: { - let count = 0; - for (const group of notifications) { - count += group.count || 0; - } - return count; - } - readonly property bool hasNotifications: totalCount > 0 - readonly property var appNameGroups: { - const groups = {}; - for (const group of notifications) { - const appName = (group.appName || "Unknown").toLowerCase(); - if (!groups[appName]) { - groups[appName] = { - appName: group.appName || I18n.tr("Unknown"), - count: 0, - latestNotification: group.latestNotification - }; - } - groups[appName].count += group.count || 0; - if (group.latestNotification && (!groups[appName].latestNotification || group.latestNotification.time > groups[appName].latestNotification.time)) { - groups[appName].latestNotification = group.latestNotification; - } - } - return Object.values(groups).sort((a, b) => b.count - a.count); - } - - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: dateText.visible ? dateText.bottom : clockContainer.bottom - anchors.topMargin: Theme.spacingM - width: Math.min(380, parent.width - Theme.spacingXL * 2) - height: notificationMode === 0 || !hasNotifications ? 0 : contentLoader.height - visible: notificationMode > 0 && hasNotifications - clip: true - - Behavior on height { - NumberAnimation { - duration: Theme.mediumDuration - easing.type: Theme.standardEasing - } - } - - Loader { - id: contentLoader - anchors.left: parent.left - anchors.right: parent.right - active: lockNotificationPanel.notificationMode > 0 && lockNotificationPanel.hasNotifications - sourceComponent: { - switch (lockNotificationPanel.notificationMode) { - case 1: - return countOnlyComponent; - case 2: - return appNamesComponent; - case 3: - return fullContentComponent; - default: - return null; - } - } - } - - Component { - id: countOnlyComponent - - Rectangle { - width: parent.width - height: 44 - radius: Theme.cornerRadius - color: Qt.rgba(0, 0, 0, 0.3) - border.color: Qt.rgba(1, 1, 1, 0.1) - border.width: 1 - - Row { - anchors.centerIn: parent - spacing: Theme.spacingS - - DankIcon { - name: "notifications" - size: Theme.iconSize - color: "white" - anchors.verticalCenter: parent.verticalCenter - } - - StyledText { - text: lockNotificationPanel.totalCount === 1 ? I18n.tr("1 notification") : I18n.tr("%1 notifications").arg(lockNotificationPanel.totalCount) - font.pixelSize: Theme.fontSizeMedium - color: "white" - anchors.verticalCenter: parent.verticalCenter - } - } - } - } - - Component { - id: appNamesComponent - - Rectangle { - width: parent.width - height: Math.min(appNamesColumn.implicitHeight + Theme.spacingM * 2, 200) - radius: Theme.cornerRadius - color: Qt.rgba(0, 0, 0, 0.3) - border.color: Qt.rgba(1, 1, 1, 0.1) - border.width: 1 - clip: true - - Flickable { - anchors.fill: parent - anchors.margins: Theme.spacingM - contentHeight: appNamesColumn.implicitHeight - clip: true - boundsBehavior: Flickable.StopAtBounds - - Column { - id: appNamesColumn - width: parent.width - spacing: Theme.spacingS - - Repeater { - model: lockNotificationPanel.appNameGroups.slice(0, 5) - - Row { - required property var modelData - width: parent.width - spacing: Theme.spacingS - - DankIcon { - name: "notifications" - size: Theme.iconSize - 4 - color: "white" - opacity: 0.8 - anchors.verticalCenter: parent.verticalCenter - } - - StyledText { - text: modelData.appName || I18n.tr("Unknown") - font.pixelSize: Theme.fontSizeMedium - color: "white" - elide: Text.ElideRight - width: parent.width - Theme.iconSize - countBadge.width - Theme.spacingS * 2 - anchors.verticalCenter: parent.verticalCenter - } - - Rectangle { - id: countBadge - width: countText.implicitWidth + Theme.spacingS * 2 - height: 20 - radius: 10 - color: Qt.rgba(1, 1, 1, 0.2) - visible: modelData.count > 1 - anchors.verticalCenter: parent.verticalCenter - - StyledText { - id: countText - anchors.centerIn: parent - text: modelData.count > 99 ? "99+" : modelData.count.toString() - font.pixelSize: Theme.fontSizeSmall - color: "white" - } - } - } - } - - StyledText { - visible: lockNotificationPanel.appNameGroups.length > 5 - text: I18n.tr("+ %1 more").arg(lockNotificationPanel.appNameGroups.length - 5) - font.pixelSize: Theme.fontSizeSmall - color: "white" - opacity: 0.7 - } - } - } - } - } - - Component { - id: fullContentComponent - - Rectangle { - width: parent.width - height: Math.min(fullContentColumn.implicitHeight + Theme.spacingM * 2, 280) - radius: Theme.cornerRadius - color: Qt.rgba(0, 0, 0, 0.3) - border.color: Qt.rgba(1, 1, 1, 0.1) - border.width: 1 - clip: true - - Flickable { - anchors.fill: parent - anchors.margins: Theme.spacingM - contentHeight: fullContentColumn.implicitHeight - clip: true - boundsBehavior: Flickable.StopAtBounds - - Column { - id: fullContentColumn - width: parent.width - spacing: Theme.spacingM - - Repeater { - model: { - const items = []; - for (const group of lockNotificationPanel.appNameGroups) { - if (group.latestNotification && items.length < 5) { - items.push(group.latestNotification); - } - } - return items; - } - - Rectangle { - required property var modelData - required property int index - width: parent.width - height: notifContent.implicitHeight + Theme.spacingS * 2 - radius: Theme.cornerRadius - 4 - color: Qt.rgba(1, 1, 1, 0.05) - - Column { - id: notifContent - anchors.left: parent.left - anchors.right: parent.right - anchors.top: parent.top - anchors.margins: Theme.spacingS - spacing: 2 - - Row { - width: parent.width - spacing: Theme.spacingXS - - StyledText { - text: modelData.appName || I18n.tr("Unknown") - font.pixelSize: Theme.fontSizeSmall - font.weight: Font.Medium - color: "white" - opacity: 0.7 - elide: Text.ElideRight - width: parent.width - timeText.implicitWidth - Theme.spacingXS - } - - StyledText { - id: timeText - text: modelData.timeStr || "" - font.pixelSize: Theme.fontSizeSmall - color: "white" - opacity: 0.5 - } - } - - StyledText { - width: parent.width - text: modelData.summary || "" - font.pixelSize: Theme.fontSizeMedium - font.weight: Font.Medium - color: "white" - elide: Text.ElideRight - maximumLineCount: 1 - visible: text.length > 0 - } - - StyledText { - width: parent.width - text: { - const body = modelData.body || ""; - return body.replace(/<[^>]*>/g, '').replace(/\n/g, ' '); - } - font.pixelSize: Theme.fontSizeSmall - color: "white" - opacity: 0.8 - elide: Text.ElideRight - maximumLineCount: 2 - wrapMode: Text.WordWrap - visible: text.length > 0 - } - } - } - } - - StyledText { - visible: lockNotificationPanel.appNameGroups.length > 5 - text: I18n.tr("+ %1 more").arg(lockNotificationPanel.appNameGroups.length - 5) - font.pixelSize: Theme.fontSizeSmall - color: "white" - opacity: 0.7 - } - } - } - } - } - } - - ColumnLayout { - id: passwordLayout - anchors.horizontalCenter: parent.horizontalCenter - anchors.top: lockNotificationPanel.visible ? lockNotificationPanel.bottom : (dateText.visible ? dateText.bottom : clockContainer.bottom) - anchors.topMargin: Theme.spacingL - spacing: Theme.spacingM - width: 380 - - RowLayout { - spacing: Theme.spacingL - Layout.fillWidth: true - - DankCircularImage { - Layout.preferredWidth: 60 - Layout.preferredHeight: 60 - imageSource: { - if (PortalService.profileImage === "") - return ""; - if (PortalService.profileImage.startsWith("/")) - return encodeFileUrl(PortalService.profileImage); - return PortalService.profileImage; - } - fallbackIcon: "person" - visible: SettingsData.lockScreenShowProfileImage - } - - Rectangle { - property bool showPassword: false - - 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) - border.width: passwordField.activeFocus ? 2 : 1 - visible: SettingsData.lockScreenShowPasswordField || root.passwordBuffer.length > 0 - - Item { - id: lockIconContainer - anchors.left: parent.left - anchors.leftMargin: Theme.spacingM - anchors.verticalCenter: parent.verticalCenter - width: 20 - height: 20 - - DankIcon { - id: lockIcon - - anchors.centerIn: parent - name: { - if (pam.u2fPending) - return "passkey"; - if (pam.fprint.tries >= SettingsData.maxFprintTries) - return "fingerprint_off"; - if (pam.fprint.active) - return "fingerprint"; - if (pam.u2f.active) - return "passkey"; - return "lock"; - } - size: 20 - color: { - if (pam.fprint.tries >= SettingsData.maxFprintTries) - return Theme.error; - if (pam.u2fState !== "") - return Theme.tertiary; - return passwordField.activeFocus ? Theme.primary : Theme.surfaceVariantText; - } - opacity: pam.passwd.active ? 0 : 1 - - Behavior on opacity { - NumberAnimation { - duration: Theme.mediumDuration - easing.type: Theme.standardEasing - } - } - - Behavior on color { - ColorAnimation { - duration: Theme.shortDuration - easing.type: Theme.standardEasing - } - } - } - } - - TextInput { - id: passwordField - - anchors.fill: parent - anchors.leftMargin: lockIconContainer.width + Theme.spacingM * 2 - anchors.rightMargin: { - let margin = Theme.spacingM; - if (loadingSpinner.visible) { - margin += loadingSpinner.width; - } - if (enterButton.visible) { - margin += enterButton.width + 2; - } - if (virtualKeyboardButton.visible) { - margin += virtualKeyboardButton.width; - } - if (revealButton.visible) { - margin += revealButton.width; - } - return margin; - } - opacity: 0 - focus: true - enabled: !demoMode - activeFocusOnTab: !demoMode - echoMode: parent.showPassword ? TextInput.Normal : TextInput.Password - onTextChanged: { - if (!demoMode) { - root.passwordBuffer = text; - } - } - onAccepted: { - if (!demoMode && !root.unlocking && !pam.passwd.active && !pam.u2fPending) { - pam.passwd.start(); - } - } - Keys.onPressed: event => { - if (demoMode) { - return; - } - - if (root.unlocking) { - event.accepted = true; - return; - } - - if (event.key === Qt.Key_Escape) { - if (pam.u2fPending) { - pam.cancelU2fPending(); - event.accepted = true; - return; - } - clear(); - } - - if (pam.passwd.active) { - console.log("PAM is active, ignoring input"); - event.accepted = true; - return; - } - } - - Component.onCompleted: { - if (!demoMode) { - forceActiveFocus(); - } - } - - onVisibleChanged: { - if (visible && !demoMode) { - forceActiveFocus(); - } - } - - onActiveFocusChanged: { - if (!activeFocus && !demoMode && visible && passwordField && !powerMenu.isVisible) { - Qt.callLater(() => { - if (passwordField && passwordField.forceActiveFocus) { - passwordField.forceActiveFocus(); - } - }); - } - } - - onEnabledChanged: { - if (enabled && !demoMode && visible && passwordField && !powerMenu.isVisible) { - Qt.callLater(() => { - if (passwordField && passwordField.forceActiveFocus) { - passwordField.forceActiveFocus(); - } - }); - } - } - } - - KeyboardController { - id: keyboardController - target: passwordField - rootObject: root - } - - StyledText { - id: placeholder - - anchors.left: lockIconContainer.right - anchors.leftMargin: Theme.spacingM - anchors.right: (revealButton.visible ? revealButton.left : (virtualKeyboardButton.visible ? virtualKeyboardButton.left : (enterButton.visible ? enterButton.left : (loadingSpinner.visible ? loadingSpinner.left : parent.right)))) - anchors.rightMargin: 2 - anchors.verticalCenter: parent.verticalCenter - text: { - if (demoMode) { - return ""; - } - if (root.unlocking) { - return "Unlocking..."; - } - if (pam.u2fPending) { - if (pam.u2fState === "insert") - return "Insert your security key..."; - return "Touch your security key..."; - } - if (pam.passwd.active) { - return "Authenticating..."; - } - return "Password..."; - } - color: root.unlocking ? Theme.primary : (pam.passwd.active ? Theme.primary : Theme.outline) - font.pixelSize: Theme.fontSizeMedium - opacity: (demoMode || root.passwordBuffer.length === 0) ? 1 : 0 - - Behavior on opacity { - NumberAnimation { - duration: Theme.mediumDuration - easing.type: Theme.standardEasing - } - } - - Behavior on color { - ColorAnimation { - duration: Theme.shortDuration - easing.type: Theme.standardEasing - } - } - } - - StyledText { - anchors.left: lockIconContainer.right - anchors.leftMargin: Theme.spacingM - anchors.right: (revealButton.visible ? revealButton.left : (virtualKeyboardButton.visible ? virtualKeyboardButton.left : (enterButton.visible ? enterButton.left : (loadingSpinner.visible ? loadingSpinner.left : parent.right)))) - anchors.rightMargin: 2 - anchors.verticalCenter: parent.verticalCenter - text: { - if (demoMode) { - return "••••••••"; - } - if (parent.showPassword) { - return root.passwordBuffer; - } - return "•".repeat(root.passwordBuffer.length); - } - color: Theme.surfaceText - font.pixelSize: parent.showPassword ? Theme.fontSizeMedium : Theme.fontSizeLarge - opacity: (demoMode || root.passwordBuffer.length > 0) ? 1 : 0 - clip: true - elide: Text.ElideNone - horizontalAlignment: implicitWidth > width ? Text.AlignRight : Text.AlignLeft - - Behavior on opacity { - NumberAnimation { - duration: Theme.mediumDuration - easing.type: Theme.standardEasing - } - } - } - - DankActionButton { - id: revealButton - - anchors.right: virtualKeyboardButton.visible ? virtualKeyboardButton.left : (enterButton.visible ? enterButton.left : (loadingSpinner.visible ? loadingSpinner.left : parent.right)) - anchors.rightMargin: 0 - anchors.verticalCenter: parent.verticalCenter - iconName: parent.showPassword ? "visibility_off" : "visibility" - buttonSize: 32 - visible: !demoMode && root.passwordBuffer.length > 0 && !pam.passwd.active && !root.unlocking - enabled: visible - onClicked: parent.showPassword = !parent.showPassword - } - DankActionButton { - id: virtualKeyboardButton - - anchors.right: enterButton.visible ? enterButton.left : (loadingSpinner.visible ? loadingSpinner.left : parent.right) - anchors.rightMargin: enterButton.visible ? 0 : Theme.spacingS - anchors.verticalCenter: parent.verticalCenter - iconName: "keyboard" - buttonSize: 32 - visible: !demoMode && !pam.passwd.active && !root.unlocking && !pam.u2fPending - enabled: visible - onClicked: { - if (keyboardController.isKeyboardActive) { - keyboardController.hide(); - } else { - keyboardController.show(); - } - } - } - - Rectangle { - id: loadingSpinner - - anchors.right: enterButton.visible ? enterButton.left : parent.right - anchors.rightMargin: Theme.spacingM - anchors.verticalCenter: parent.verticalCenter - width: 24 - height: 24 - radius: 12 - color: "transparent" - visible: !demoMode && (pam.passwd.active || root.unlocking) - - DankIcon { - anchors.centerIn: parent - name: "check_circle" - size: 20 - color: Theme.primary - visible: root.unlocking - - SequentialAnimation on scale { - running: root.unlocking - - NumberAnimation { - from: 0 - to: 1.2 - duration: Anims.durShort - easing.type: Easing.BezierSpline - easing.bezierCurve: Anims.emphasizedDecel - } - - NumberAnimation { - from: 1.2 - to: 1 - duration: Anims.durShort - easing.type: Easing.BezierSpline - easing.bezierCurve: Anims.emphasizedAccel - } - } - } - - Item { - anchors.fill: parent - visible: pam.passwd.active && !root.unlocking - - Rectangle { - width: 20 - height: 20 - radius: 10 - anchors.centerIn: parent - color: "transparent" - border.color: Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.3) - border.width: 2 - } - - Rectangle { - width: 20 - height: 20 - radius: 10 - anchors.centerIn: parent - color: "transparent" - border.color: Theme.primary - border.width: 2 - - Rectangle { - width: parent.width - 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) - } - - RotationAnimation on rotation { - running: pam.passwd.active && !root.unlocking - loops: Animation.Infinite - duration: Anims.durLong - from: 0 - to: 360 - } - } - } - } - - DankActionButton { - id: enterButton - - anchors.right: parent.right - anchors.rightMargin: 2 - anchors.verticalCenter: parent.verticalCenter - iconName: "keyboard_return" - buttonSize: 36 - visible: (demoMode || (!pam.passwd.active && !root.unlocking && !pam.u2fPending)) - enabled: !demoMode - onClicked: { - if (!demoMode && !root.unlocking && !pam.u2fPending) { - pam.passwd.start(); - } - } - - Behavior on opacity { - NumberAnimation { - duration: Theme.shortDuration - easing.type: Theme.standardEasing - } - } - } - - Behavior on border.color { - ColorAnimation { - duration: Theme.shortDuration - easing.type: Theme.standardEasing - } - } - } - } - - StyledText { - id: authFeedbackText - - Layout.fillWidth: true - Layout.preferredHeight: text.length > 0 ? Math.min(implicitHeight, Math.ceil(Theme.fontSizeSmall * 4.5)) : 0 - text: root.currentAuthFeedbackText() - color: root.authFeedbackIsHint() ? Theme.outline : Theme.error - font.pixelSize: Theme.fontSizeSmall - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.WordWrap - maximumLineCount: 3 - elide: Text.ElideRight - opacity: text.length > 0 ? 1 : 0 - - Behavior on opacity { - NumberAnimation { - duration: Theme.shortDuration - easing.type: Theme.standardEasing - } - } - } - } - - Row { - anchors.top: passwordLayout.bottom - anchors.topMargin: Theme.spacingS - anchors.horizontalCenter: passwordLayout.horizontalCenter - spacing: 4 - opacity: DMSService.capsLockState ? 1 : 0 - - DankIcon { - name: "shift_lock" - size: 14 - color: Theme.error - anchors.verticalCenter: parent.verticalCenter - } - - StyledText { - text: I18n.tr("Caps Lock is on") - font.pixelSize: Theme.fontSizeSmall - color: Theme.error - anchors.verticalCenter: parent.verticalCenter - } - - Behavior on opacity { - NumberAnimation { - duration: Theme.shortDuration - easing.type: Theme.standardEasing - } - } - } - - StyledText { - anchors.top: parent.top - anchors.left: parent.left - anchors.margins: Theme.spacingXL - text: I18n.tr("DEMO MODE - Click anywhere to exit") - font.pixelSize: Theme.fontSizeSmall - color: "white" - opacity: 0.7 - visible: demoMode - } - - Row { - anchors.top: parent.top - anchors.right: parent.right - anchors.margins: Theme.spacingXL - spacing: Theme.spacingL - visible: SettingsData.lockScreenShowSystemIcons - - Item { - width: keyboardLayoutRow.width - height: keyboardLayoutRow.height - anchors.verticalCenter: parent.verticalCenter - visible: { - if (CompositorService.isNiri) { - return NiriService.keyboardLayoutNames.length > 1; - } else if (CompositorService.isHyprland) { - return hyprlandLayoutCount > 1; - } - return false; - } - - Row { - id: keyboardLayoutRow - spacing: 4 - - Item { - width: Theme.iconSize - height: Theme.iconSize - - DankIcon { - name: "keyboard" - size: Theme.iconSize - color: "white" - anchors.centerIn: parent - } - } - - Item { - width: childrenRect.width - height: Theme.iconSize - - StyledText { - text: { - if (CompositorService.isNiri) { - const layout = NiriService.getCurrentKeyboardLayoutName(); - if (!layout) - return ""; - const parts = layout.split(" "); - if (parts.length > 0) { - return parts[0].substring(0, 2).toUpperCase(); - } - return layout.substring(0, 2).toUpperCase(); - } else if (CompositorService.isHyprland) { - return hyprlandCurrentLayout; - } - return ""; - } - font.pixelSize: Theme.fontSizeMedium - font.weight: Font.Light - color: "white" - anchors.verticalCenter: parent.verticalCenter - } - } - } - - MouseArea { - id: keyboardLayoutArea - anchors.fill: parent - enabled: !demoMode - hoverEnabled: enabled - cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor - onClicked: { - if (CompositorService.isNiri) { - NiriService.cycleKeyboardLayout(); - } else if (CompositorService.isHyprland) { - Quickshell.execDetached(["hyprctl", "switchxkblayout", hyprlandKeyboard, "next"]); - updateHyprlandLayout(); - } - } - } - } - - Rectangle { - width: 1 - height: 24 - color: Qt.rgba(255, 255, 255, 0.2) - anchors.verticalCenter: parent.verticalCenter - visible: MprisController.activePlayer && SettingsData.lockScreenShowMediaPlayer - } - - Row { - spacing: Theme.spacingS - visible: MprisController.activePlayer && SettingsData.lockScreenShowMediaPlayer - anchors.verticalCenter: parent.verticalCenter - - Item { - width: 20 - height: Theme.iconSize - anchors.verticalCenter: parent.verticalCenter - - Loader { - active: MprisController.activePlayer?.playbackState === MprisPlaybackState.Playing - - sourceComponent: Component { - Ref { - service: CavaService - } - } - } - - Timer { - running: !CavaService.cavaAvailable && MprisController.activePlayer?.playbackState === MprisPlaybackState.Playing - interval: 256 - repeat: true - onTriggered: { - CavaService.values = [Math.random() * 40 + 10, Math.random() * 60 + 20, Math.random() * 50 + 15, Math.random() * 35 + 20, Math.random() * 45 + 15, Math.random() * 55 + 25]; - } - } - - Row { - anchors.centerIn: parent - spacing: 1.5 - - Repeater { - model: 6 - delegate: Rectangle { - required property int index - - width: 2 - height: { - if (MprisController.activePlayer?.playbackState === MprisPlaybackState.Playing && CavaService.values.length > index) { - const rawLevel = CavaService.values[index] || 0; - const scaledLevel = Math.sqrt(Math.min(Math.max(rawLevel, 0), 100) / 100) * 100; - const maxHeight = Theme.iconSize - 2; - const minHeight = 3; - return minHeight + (scaledLevel / 100) * (maxHeight - minHeight); - } - return 3; - } - radius: 1.5 - color: "white" - anchors.verticalCenter: parent.verticalCenter - - Behavior on height { - NumberAnimation { - duration: Anims.durShort - easing.type: Easing.BezierSpline - easing.bezierCurve: Anims.standardDecel - } - } - } - } - } - } - - StyledText { - text: { - const player = MprisController.activePlayer; - if (!player?.trackTitle) - return ""; - const title = player.trackTitle; - const artist = player.trackArtist || ""; - return artist ? title + " • " + artist : title; - } - font.pixelSize: Theme.fontSizeLarge - color: "white" - opacity: 0.9 - anchors.verticalCenter: parent.verticalCenter - elide: Text.ElideRight - width: Math.min(implicitWidth, 400) - wrapMode: Text.NoWrap - maximumLineCount: 1 - } - - Row { - spacing: Theme.spacingXS - anchors.verticalCenter: parent.verticalCenter - - Rectangle { - width: 20 - height: 20 - radius: 10 - anchors.verticalCenter: parent.verticalCenter - color: prevArea.containsMouse ? Qt.rgba(255, 255, 255, 0.2) : "transparent" - visible: MprisController.activePlayer - opacity: (MprisController.activePlayer?.canGoPrevious ?? false) ? 1 : 0.3 - - DankIcon { - anchors.centerIn: parent - name: "skip_previous" - size: 12 - color: "white" - } - - MouseArea { - id: prevArea - anchors.fill: parent - enabled: MprisController.activePlayer?.canGoPrevious ?? false - hoverEnabled: enabled - cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor - onClicked: MprisController.previousOrRewind() - } - } - - Rectangle { - width: 24 - height: 24 - radius: 12 - anchors.verticalCenter: parent.verticalCenter - color: MprisController.activePlayer?.playbackState === MprisPlaybackState.Playing ? Qt.rgba(255, 255, 255, 0.9) : Qt.rgba(255, 255, 255, 0.2) - visible: MprisController.activePlayer - - DankIcon { - anchors.centerIn: parent - name: MprisController.activePlayer?.playbackState === MprisPlaybackState.Playing ? "pause" : "play_arrow" - size: 14 - color: MprisController.activePlayer?.playbackState === MprisPlaybackState.Playing ? "black" : "white" - } - - MouseArea { - anchors.fill: parent - enabled: MprisController.activePlayer - hoverEnabled: enabled - cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor - onClicked: MprisController.activePlayer?.togglePlaying() - } - } - - Rectangle { - width: 20 - height: 20 - radius: 10 - anchors.verticalCenter: parent.verticalCenter - color: nextArea.containsMouse ? Qt.rgba(255, 255, 255, 0.2) : "transparent" - visible: MprisController.activePlayer - opacity: (MprisController.activePlayer?.canGoNext ?? false) ? 1 : 0.3 - - DankIcon { - anchors.centerIn: parent - name: "skip_next" - size: 12 - color: "white" - } - - MouseArea { - id: nextArea - anchors.fill: parent - enabled: MprisController.activePlayer?.canGoNext ?? false - hoverEnabled: enabled - cursorShape: enabled ? Qt.PointingHandCursor : Qt.ArrowCursor - onClicked: MprisController.activePlayer?.next() - } - } - } - } - - Rectangle { - width: 1 - height: 24 - color: Qt.rgba(255, 255, 255, 0.2) - anchors.verticalCenter: parent.verticalCenter - visible: MprisController.activePlayer && SettingsData.lockScreenShowMediaPlayer && WeatherService.weather.available - } - - Row { - spacing: 6 - visible: WeatherService.weather.available - anchors.verticalCenter: parent.verticalCenter - - DankIcon { - name: WeatherService.getWeatherIcon(WeatherService.weather.wCode) - size: Theme.iconSize - color: "white" - anchors.verticalCenter: parent.verticalCenter - } - - StyledText { - text: (SettingsData.useFahrenheit ? WeatherService.weather.tempF : WeatherService.weather.temp) + "°" - font.pixelSize: Theme.fontSizeLarge - font.weight: Font.Light - color: "white" - anchors.verticalCenter: parent.verticalCenter - } - } - - Rectangle { - width: 1 - 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) - } - - Row { - spacing: Theme.spacingM - anchors.verticalCenter: parent.verticalCenter - visible: NetworkService.networkAvailable || (BluetoothService.available && BluetoothService.enabled) || (AudioService.sink && AudioService.sink.audio) - - DankIcon { - name: "screen_record" - size: Theme.iconSize - 2 - color: NiriService.hasActiveCast ? "white" : Qt.rgba(255, 255, 255, 0.5) - anchors.verticalCenter: parent.verticalCenter - visible: NiriService.hasCasts - } - - DankIcon { - name: { - if (NetworkService.wifiToggling) - return "sync"; - switch (NetworkService.networkStatus) { - case "ethernet": - return "lan"; - case "vpn": - return NetworkService.ethernetConnected ? "lan" : NetworkService.wifiSignalIcon; - default: - return NetworkService.wifiSignalIcon; - } - } - size: Theme.iconSize - 2 - color: NetworkService.networkStatus !== "disconnected" ? "white" : Qt.rgba(255, 255, 255, 0.5) - anchors.verticalCenter: parent.verticalCenter - visible: NetworkService.networkAvailable - } - - DankIcon { - name: "vpn_lock" - size: Theme.iconSize - 2 - color: "white" - anchors.verticalCenter: parent.verticalCenter - visible: NetworkService.vpnAvailable && NetworkService.vpnConnected - } - - DankIcon { - name: "bluetooth" - size: Theme.iconSize - 2 - color: "white" - anchors.verticalCenter: parent.verticalCenter - visible: BluetoothService.available && BluetoothService.enabled - } - - DankIcon { - name: { - if (!AudioService.sink?.audio) { - return "volume_up"; - } - if (AudioService.sink.audio.muted) - return "volume_off"; - if (AudioService.sink.audio.volume === 0) - return "volume_mute"; - if (AudioService.sink.audio.volume * 100 < 33) { - return "volume_down"; - } - 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" - anchors.verticalCenter: parent.verticalCenter - visible: AudioService.sink && AudioService.sink.audio - } - } - - Rectangle { - width: 1 - 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)) - } - - Row { - spacing: 4 - visible: BatteryService.batteryAvailable - anchors.verticalCenter: parent.verticalCenter - - DankIcon { - name: { - 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"; - } - 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"; - } - 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) { - return Theme.error; - } - - if (BatteryService.isCharging || BatteryService.isPluggedIn) { - return Theme.primary; - } - - return "white"; - } - anchors.verticalCenter: parent.verticalCenter - } - - StyledText { - text: BatteryService.batteryLevel + "%" - font.pixelSize: Theme.fontSizeLarge - font.weight: Font.Light - color: "white" - anchors.verticalCenter: parent.verticalCenter - } - } - } - - DankActionButton { - anchors.bottom: parent.bottom - anchors.left: parent.left - anchors.margins: Theme.spacingXL - visible: SettingsData.lockScreenShowPowerActions - iconName: "power_settings_new" - iconColor: Theme.error - buttonSize: 40 - onClicked: { - if (demoMode) { - console.log("Demo: Power Menu"); - } else { - powerMenu.show(); - } - } - } - } - - Pam { - id: pam - lockSecured: !demoMode - onUnlockRequested: { - root.unlocking = true; - lockerReadyArmed = false; - passwordField.text = ""; - root.passwordBuffer = ""; - root.unlockRequested(); - } - onStateChanged: { - root.pamState = state; - if (state !== "") { - root.unlocking = false; - placeholderDelay.restart(); - passwordField.text = ""; - root.passwordBuffer = ""; - } - } - onU2fPendingChanged: { - if (u2fPending) { - passwordField.text = ""; - root.passwordBuffer = ""; - if (keyboardController.isKeyboardActive) - keyboardController.hide(); - } - } - } - - Connections { - target: pam - - function onUnlockInProgressChanged() { - if (!pam.unlockInProgress && root.unlocking) - root.unlocking = false; - } - } - - Binding { - target: pam - property: "buffer" - value: root.passwordBuffer - } - - Timer { - id: placeholderDelay - - interval: 4000 - onTriggered: root.pamState = "" - } - - MouseArea { - anchors.fill: parent - enabled: demoMode - onClicked: root.unlockRequested() - } - - LockPowerMenu { - id: powerMenu - showLogout: true - onClosed: { - if (!demoMode && passwordField && passwordField.forceActiveFocus) { - Qt.callLater(() => passwordField.forceActiveFocus()); - } - } - } -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/LockScreenDemo.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/LockScreenDemo.qml deleted file mode 100644 index e13eac9..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/LockScreenDemo.qml +++ /dev/null @@ -1,46 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import Quickshell -import Quickshell.Wayland - -PanelWindow { - id: root - - property bool demoActive: false - - visible: demoActive - - anchors { - top: true - bottom: true - left: true - right: true - } - - WlrLayershell.layer: WlrLayershell.Overlay - WlrLayershell.exclusiveZone: -1 - WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive - - color: "transparent" - - function showDemo(): void { - console.log("Showing lock screen demo"); - demoActive = true; - } - - function hideDemo(): void { - console.log("Hiding lock screen demo"); - demoActive = false; - } - - Loader { - anchors.fill: parent - active: demoActive - sourceComponent: LockScreenContent { - demoMode: true - screenName: root.screen?.name ?? "" - onUnlockRequested: root.hideDemo() - } - } -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/LockSurface.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/LockSurface.qml deleted file mode 100644 index 9d1beae..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/LockSurface.qml +++ /dev/null @@ -1,73 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import Quickshell.Wayland -import qs.Common - -FocusScope { - id: root - - required property WlSessionLock lock - required property string sharedPasswordBuffer - required property string screenName - required property bool isLocked - - signal passwordChanged(string newPassword) - signal unlockRequested - - Keys.onPressed: event => { - if (videoScreensaver.active && videoScreensaver.inputEnabled) { - videoScreensaver.dismiss(); - event.accepted = true; - } - } - - Rectangle { - anchors.fill: parent - color: "transparent" - } - - LockScreenContent { - id: lockContent - - anchors.fill: parent - demoMode: false - passwordBuffer: root.sharedPasswordBuffer - screenName: root.screenName - enabled: !videoScreensaver.active - focus: !videoScreensaver.active - opacity: videoScreensaver.active ? 0 : 1 - onUnlockRequested: root.unlockRequested() - onPasswordBufferChanged: { - if (root.sharedPasswordBuffer !== passwordBuffer) { - root.passwordChanged(passwordBuffer); - } - } - - Behavior on opacity { - NumberAnimation { - duration: 200 - } - } - } - - VideoScreensaver { - id: videoScreensaver - anchors.fill: parent - screenName: root.screenName - } - - Component.onCompleted: forceActiveFocus() - - onIsLockedChanged: { - if (isLocked) { - forceActiveFocus(); - lockContent.resetLockState(); - if (SettingsData.lockScreenVideoEnabled) { - videoScreensaver.start(); - } - return; - } - lockContent.unlocking = false; - } -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/Pam.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/Pam.qml deleted file mode 100644 index f5e7859..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/Pam.qml +++ /dev/null @@ -1,405 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import Quickshell -import Quickshell.Io -import Quickshell.Services.Pam -import qs.Common - -Scope { - id: root - - property bool lockSecured: false - property bool unlockInProgress: false - - readonly property alias passwd: passwd - readonly property alias fprint: fprint - readonly property alias u2f: u2f - property string lockMessage - property string state - property string fprintState - property string u2fState - property bool u2fPending: false - property string buffer - - signal flashMsg - signal unlockRequested - - function resetAuthFlows(): void { - passwd.abort(); - fprint.abort(); - u2f.abort(); - errorRetry.running = false; - u2fErrorRetry.running = false; - u2fPendingTimeout.running = false; - passwdActiveTimeout.running = false; - unlockRequestTimeout.running = false; - root.u2fPending = false; - root.u2fState = ""; - root.unlockInProgress = false; - } - - function recoverFromAuthStall(newState: string): void { - resetAuthFlows(); - root.state = newState; - flashMsg(); - stateReset.restart(); - fprint.checkAvail(); - u2f.checkAvail(); - } - - function completeUnlock(): void { - if (!root.unlockInProgress) { - root.unlockInProgress = true; - passwd.abort(); - fprint.abort(); - u2f.abort(); - errorRetry.running = false; - u2fErrorRetry.running = false; - u2fPendingTimeout.running = false; - root.u2fPending = false; - root.u2fState = ""; - unlockRequestTimeout.restart(); - unlockRequested(); - } - } - - function proceedAfterPrimaryAuth(): void { - if (SettingsData.enableU2f && SettingsData.u2fMode === "and" && u2f.available) { - u2f.startForSecondFactor(); - } else { - completeUnlock(); - } - } - - function cancelU2fPending(): void { - if (!root.u2fPending) - return; - u2f.abort(); - u2fErrorRetry.running = false; - u2fPendingTimeout.running = false; - root.u2fPending = false; - root.u2fState = ""; - fprint.checkAvail(); - } - - FileView { - id: dankshellConfigWatcher - - path: "/etc/pam.d/dankshell" - printErrors: false - } - - FileView { - id: nixosMarker - - path: "/etc/NIXOS" - printErrors: false - } - - FileView { - id: u2fConfigWatcher - - path: "/etc/pam.d/dankshell-u2f" - printErrors: false - } - - // Detects Nix-installed DMS on non-NixOS systems - readonly property bool runningFromNixStore: Quickshell.shellDir.startsWith("/nix/store/") - - PamContext { - id: passwd - - config: dankshellConfigWatcher.loaded ? "dankshell" : "login" - configDirectory: (dankshellConfigWatcher.loaded || nixosMarker.loaded || root.runningFromNixStore) ? "/etc/pam.d" : Quickshell.shellDir + "/assets/pam" - - onMessageChanged: { - if (message.startsWith("The account is locked")) { - root.lockMessage = message; - } else if (root.lockMessage && message.endsWith(" left to unlock)")) { - root.lockMessage += "\n" + message; - } else if (root.lockMessage && message && message.length > 0) { - root.lockMessage = ""; - } - } - - onResponseRequiredChanged: { - if (!responseRequired) - return; - - respond(root.buffer); - } - - onCompleted: res => { - if (res === PamResult.Success) { - if (!root.unlockInProgress) { - fprint.abort(); - root.proceedAfterPrimaryAuth(); - } - return; - } - - unlockRequestTimeout.running = false; - root.unlockInProgress = false; - root.u2fPending = false; - root.u2fState = ""; - u2fPendingTimeout.running = false; - u2f.abort(); - - if (res === PamResult.Error) - root.state = "error"; - else if (res === PamResult.MaxTries) - root.state = "max"; - else if (res === PamResult.Failed) - root.state = "fail"; - - root.flashMsg(); - stateReset.restart(); - } - } - - Connections { - target: passwd - - function onActiveChanged() { - if (passwd.active) { - passwdActiveTimeout.restart(); - } else { - passwdActiveTimeout.running = false; - } - } - } - - PamContext { - id: fprint - - property bool available: SettingsData.lockFingerprintReady - property int tries - property int errorTries - - function checkAvail(): void { - if (!available || !SettingsData.enableFprint || !root.lockSecured) { - abort(); - return; - } - - tries = 0; - errorTries = 0; - start(); - } - - config: "fprint" - configDirectory: Quickshell.shellDir + "/assets/pam" - - onCompleted: res => { - if (!available) - return; - - if (res === PamResult.Success) { - if (!root.unlockInProgress) { - passwd.abort(); - root.proceedAfterPrimaryAuth(); - } - return; - } - - if (res === PamResult.Error) { - root.fprintState = "error"; - errorTries++; - if (errorTries < 5) { - abort(); - errorRetry.restart(); - } - } else if (res === PamResult.MaxTries) { - tries++; - if (tries < SettingsData.maxFprintTries) { - root.fprintState = "fail"; - start(); - } else { - root.fprintState = "max"; - abort(); - } - } - - root.flashMsg(); - fprintStateReset.start(); - } - } - - PamContext { - id: u2f - - property bool available: SettingsData.lockU2fReady - - function checkAvail(): void { - if (!available || !SettingsData.enableU2f || !root.lockSecured) { - abort(); - return; - } - - if (SettingsData.u2fMode === "or") { - start(); - } - } - - function startForSecondFactor(): void { - if (!available || !SettingsData.enableU2f) { - root.completeUnlock(); - return; - } - abort(); - root.u2fPending = true; - root.u2fState = ""; - u2fPendingTimeout.restart(); - start(); - } - - config: u2fConfigWatcher.loaded ? "dankshell-u2f" : "u2f" - configDirectory: u2fConfigWatcher.loaded ? "/etc/pam.d" : Quickshell.shellDir + "/assets/pam" - - onMessageChanged: { - if (message.toLowerCase().includes("touch")) - root.u2fState = "waiting"; - } - - onCompleted: res => { - if (!available || root.unlockInProgress) - return; - - if (res === PamResult.Success) { - root.completeUnlock(); - return; - } - - if (res === PamResult.Error || res === PamResult.MaxTries || res === PamResult.Failed) { - abort(); - - if (root.u2fPending) { - if (root.u2fState === "waiting") { - // AND mode: device was found but auth failed → back to password - root.u2fPending = false; - root.u2fState = ""; - fprint.checkAvail(); - } else { - // AND mode: no device found → keep pending, show "Insert...", retry - root.u2fState = "insert"; - u2fErrorRetry.restart(); - } - } else { - // OR mode: prompt to insert key, silently retry - root.u2fState = "insert"; - u2fErrorRetry.restart(); - } - } - } - } - - Timer { - id: errorRetry - - interval: 800 - onTriggered: fprint.start() - } - - Timer { - id: u2fErrorRetry - - interval: 800 - onTriggered: u2f.start() - } - - Timer { - id: u2fPendingTimeout - - interval: 30000 - onTriggered: root.cancelU2fPending() - } - - Timer { - id: passwdActiveTimeout - - interval: 15000 - onTriggered: { - if (passwd.active) - root.recoverFromAuthStall("error"); - } - } - - Timer { - id: unlockRequestTimeout - - interval: 8000 - onTriggered: { - if (root.unlockInProgress) - root.recoverFromAuthStall("error"); - } - } - - Timer { - id: stateReset - - interval: 4000 - onTriggered: { - if (root.state !== "max") - root.state = ""; - } - } - - Timer { - id: fprintStateReset - - interval: 4000 - onTriggered: { - root.fprintState = ""; - fprint.errorTries = 0; - } - } - - onLockSecuredChanged: { - if (lockSecured) { - SettingsData.refreshAuthAvailability(); - root.state = ""; - root.fprintState = ""; - root.u2fState = ""; - root.u2fPending = false; - root.lockMessage = ""; - root.resetAuthFlows(); - fprint.checkAvail(); - u2f.checkAvail(); - } else { - root.resetAuthFlows(); - } - } - - Connections { - target: SettingsData - - function onEnableFprintChanged(): void { - fprint.checkAvail(); - } - - function onLockFingerprintReadyChanged(): void { - fprint.checkAvail(); - } - - function onEnableU2fChanged(): void { - u2f.checkAvail(); - } - - function onLockU2fReadyChanged(): void { - u2f.checkAvail(); - } - - function onU2fModeChanged(): void { - if (root.lockSecured) { - u2f.abort(); - u2fErrorRetry.running = false; - u2fPendingTimeout.running = false; - unlockRequestTimeout.running = false; - root.u2fPending = false; - root.u2fState = ""; - u2f.checkAvail(); - } - } - } -} diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/VideoScreensaver.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/VideoScreensaver.qml deleted file mode 100644 index 129f507..0000000 --- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modules/Lock/VideoScreensaver.qml +++ /dev/null @@ -1,200 +0,0 @@ -pragma ComponentBehavior: Bound - -import QtQuick -import Quickshell.Io -import qs.Common -import qs.Services - -Item { - id: root - - required property string screenName - property bool active: false - property string videoSource: "" - property bool inputEnabled: false - property point lastMousePos: Qt.point(-1, -1) - property bool mouseInitialized: false - property var videoPlayer: null - - signal dismissed - - visible: active - z: 1000 - - Rectangle { - id: background - anchors.fill: parent - color: "black" - visible: root.active - } - - Timer { - id: inputEnableTimer - interval: 500 - onTriggered: root.inputEnabled = true - } - - Process { - id: videoPicker - property string result: "" - property string folder: "" - - command: ["sh", "-c", "find '" + folder + "' -maxdepth 1 -type f \\( " + "-iname '*.mp4' -o -iname '*.mkv' -o -iname '*.webm' -o " + "-iname '*.mov' -o -iname '*.avi' -o -iname '*.m4v' " + "\\) 2>/dev/null | shuf -n1"] - - stdout: SplitParser { - onRead: data => { - const path = data.trim(); - if (path) { - videoPicker.result = path; - root.videoSource = "file://" + path; - } - } - } - - onExited: exitCode => { - if (exitCode !== 0 || !videoPicker.result) { - console.warn("VideoScreensaver: no video found in folder"); - ToastService.showError(I18n.tr("Video Screensaver"), I18n.tr("No video found in folder")); - root.dismiss(); - } - } - } - - Process { - id: fileChecker - command: ["test", "-d", SettingsData.lockScreenVideoPath] - - onExited: exitCode => { - const isDir = exitCode === 0; - const videoPath = SettingsData.lockScreenVideoPath; - - if (isDir) { - videoPicker.folder = videoPath; - videoPicker.running = true; - } else if (SettingsData.lockScreenVideoCycling) { - const parentFolder = videoPath.substring(0, videoPath.lastIndexOf('/')); - videoPicker.folder = parentFolder; - videoPicker.running = true; - } else { - root.videoSource = "file://" + videoPath; - } - } - } - - function createVideoPlayer() { - if (videoPlayer) - return true; - - try { - videoPlayer = Qt.createQmlObject(` - import QtQuick - import QtMultimedia - Video { - anchors.fill: parent - fillMode: VideoOutput.PreserveAspectCrop - loops: MediaPlayer.Infinite - volume: 0 - } - `, background, "VideoScreensaver.VideoPlayer"); - - videoPlayer.errorOccurred.connect((error, errorString) => { - console.warn("VideoScreensaver: playback error:", errorString); - ToastService.showError(I18n.tr("Video Screensaver"), I18n.tr("Playback error: ") + errorString); - root.dismiss(); - }); - - return true; - } catch (e) { - console.warn("VideoScreensaver: Failed to create video player:", e); - return false; - } - } - - function destroyVideoPlayer() { - if (videoPlayer) { - videoPlayer.stop(); - videoPlayer.destroy(); - videoPlayer = null; - } - } - - function start() { - if (!SettingsData.lockScreenVideoEnabled || !SettingsData.lockScreenVideoPath) - return; - - if (!MultimediaService.available) { - ToastService.showError(I18n.tr("Video Screensaver"), I18n.tr("QtMultimedia is not available")); - return; - } - - if (!createVideoPlayer()) - return; - - videoPicker.result = ""; - videoPicker.folder = ""; - inputEnabled = false; - mouseInitialized = false; - lastMousePos = Qt.point(-1, -1); - active = true; - inputEnableTimer.start(); - fileChecker.running = true; - } - - function dismiss() { - if (!active) - return; - destroyVideoPlayer(); - inputEnabled = false; - active = false; - videoSource = ""; - dismissed(); - } - - onVideoSourceChanged: { - if (videoSource && active && videoPlayer) { - videoPlayer.source = videoSource; - videoPlayer.play(); - } - } - - MouseArea { - id: mouseArea - anchors.fill: parent - enabled: root.active && root.inputEnabled - hoverEnabled: true - propagateComposedEvents: false - - onPositionChanged: mouse => { - if (!root.mouseInitialized) { - root.lastMousePos = Qt.point(mouse.x, mouse.y); - root.mouseInitialized = true; - return; - } - var dx = Math.abs(mouse.x - root.lastMousePos.x); - var dy = Math.abs(mouse.y - root.lastMousePos.y); - if (dx > 5 || dy > 5) { - root.dismiss(); - } - } - onClicked: root.dismiss() - onPressed: root.dismiss() - onWheel: root.dismiss() - } - - Connections { - target: IdleService - - function onLockRequested() { - if (SettingsData.lockScreenVideoEnabled && !root.active) { - root.start(); - } - } - - function onFadeToLockRequested() { - if (SettingsData.lockScreenVideoEnabled && !root.active) { - IdleService.cancelFadeToLock(); - root.start(); - } - } - } -} |