import Quickshell import Quickshell.Services.Polkit import Quickshell.Wayland import Quickshell.Widgets import ZShell.Components import QtQuick import QtQuick.Layouts import QtQuick.Controls import qs.Components import qs.Modules import ZShell.Config import qs.Services Scope { id: root property alias polkitAgent: polkitAgent property bool shouldShow: false PanelWindow { id: panelWindow property bool detailsOpen: false WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive WlrLayershell.layer: WlrLayer.Overlay WlrLayershell.namespace: "ZShell-Auth" color: "transparent" visible: false Connections { function onShouldShowChanged(): void { if (root.shouldShow) { panelWindow.visible = true; openAnim.start(); } else { closeAnim.start(); } } target: root } Anim { id: openAnim property: "opacity" target: inputPanel to: 1 } Anim { id: closeAnim property: "opacity" target: inputPanel to: 0 onFinished: { panelWindow.visible = false; } onStarted: { panelWindow.detailsOpen = false; } } anchors { bottom: true left: true right: true top: true } // mask: Region { item: inputPanel } Rectangle { id: inputPanel anchors.centerIn: parent color: Colors.tPalette.m3surface implicitHeight: layout.childrenRect.height + 28 implicitWidth: layout.childrenRect.width + 32 opacity: 0 radius: Tokens.rounding.small * 2 ColumnLayout { id: layout anchors.centerIn: parent RowLayout { id: contentRow spacing: 24 Item { Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter Layout.leftMargin: 16 Layout.preferredHeight: icon.implicitSize Layout.preferredWidth: icon.implicitSize IconImage { id: icon anchors.fill: parent implicitSize: 64 mipmap: true source: Quickshell.iconPath(polkitAgent.flow?.iconName, true) ?? "" visible: `${source}`.includes("://") } MaterialIcon { anchors.fill: parent font.pointSize: 64 horizontalAlignment: Text.AlignHCenter text: "security" verticalAlignment: Text.AlignVCenter visible: !icon.visible } } ColumnLayout { id: contentColumn Layout.fillHeight: true Layout.fillWidth: true CustomText { Layout.alignment: Qt.AlignLeft Layout.preferredWidth: Math.min(600, contentWidth) font.bold: true font.pointSize: 16 text: polkitAgent.flow?.message ?? "" wrapMode: Text.WordWrap } CustomText { Layout.alignment: Qt.AlignLeft Layout.preferredWidth: Math.min(600, contentWidth) color: Colors.tPalette.m3onSurfaceVariant font.bold: true font.pointSize: 12 text: polkitAgent.flow?.supplementaryMessage || "No Additional Information" wrapMode: Text.WordWrap } TextField { id: passInput Layout.preferredHeight: 40 Layout.preferredWidth: contentColumn.implicitWidth color: Colors.palette.m3onSurfaceVariant echoMode: polkitAgent.flow?.responseVisible ? TextInput.Normal : TextInput.Password placeholderText: polkitAgent.flow?.failed ? " Incorrect Password" : " Input Password" placeholderTextColor: polkitAgent.flow?.failed ? Colors.palette.m3onError : Colors.tPalette.m3onSurfaceVariant selectByMouse: true background: CustomRect { color: (polkitAgent.flow?.failed && passInput.text === "") ? Colors.palette.m3error : Colors.tPalette.m3surfaceVariant implicitHeight: 40 radius: Tokens.rounding.small } onAccepted: okButton.clicked() } CustomCheckbox { id: showPassCheckbox Layout.alignment: Qt.AlignLeft checked: polkitAgent.flow?.responseVisible ?? false text: "Show Password" onCheckedChanged: { passInput.echoMode = checked ? TextInput.Normal : TextInput.Password; passInput.forceActiveFocus(); } } } } CustomRect { id: detailsPanel property bool open: panelWindow.detailsOpen Layout.fillWidth: true Layout.preferredHeight: implicitHeight clip: true color: Colors.tPalette.m3surfaceContainerLow implicitHeight: 0 radius: 16 visible: true Behavior on open { ParallelAnimation { Anim { property: "implicitHeight" target: detailsPanel to: !detailsPanel.open ? textDetailsColumn.childrenRect.height + 16 : 0 } Anim { property: "opacity" target: textDetailsColumn to: !detailsPanel.open ? 1 : 0 } Anim { property: "scale" target: textDetailsColumn to: !detailsPanel.open ? 1 : 0.9 } } } ColumnLayout { id: textDetailsColumn anchors.fill: parent anchors.margins: 8 opacity: 0 scale: 0.9 spacing: 8 CustomText { text: `actionId: ${polkitAgent.flow?.actionId}` wrapMode: Text.WordWrap } CustomText { text: `selectedIdentity: ${polkitAgent.flow?.selectedIdentity}` wrapMode: Text.WordWrap } } } RowLayout { Layout.preferredWidth: contentRow.implicitWidth spacing: 8 IconTextButton { id: detailsButton Layout.alignment: Qt.AlignLeft icon: "info" inactiveColor: Colors.palette.m3surfaceContainer inactiveOnColor: Colors.palette.m3onSurface isRound: true shapeMorph: true text: "Details" onClicked: { panelWindow.detailsOpen = !panelWindow.detailsOpen; } } Item { id: spacer Layout.fillWidth: true } ButtonRow { Layout.alignment: Qt.AlignRight spacing: Tokens.spacing.medium IconTextButton { id: okButton enabled: passInput.text.length > 0 || !!polkitAgent.flow?.isResponseRequired horizontalPadding: Tokens.padding.large icon: "check" inactiveColor: Colors.palette.m3primary inactiveOnColor: Colors.palette.m3onPrimary isRound: true isToggle: false shapeMorph: true shapeMorphExpansion: pressed ? 12 : 0 text: "OK" onClicked: { polkitAgent.flow.submit(passInput.text); passInput.text = ""; passInput.forceActiveFocus(); } } IconTextButton { id: cancelButton enabled: passInput.text.length > 0 || !!polkitAgent.flow?.isResponseRequired horizontalPadding: Tokens.padding.large icon: "close" inactiveColor: Colors.palette.m3surfaceContainer inactiveOnColor: Colors.palette.m3onSurface isRound: true isToggle: false shapeMorph: true shapeMorphExpansion: pressed ? 12 : 0 text: "Cancel" onClicked: { root.shouldShow = false; polkitAgent.flow.cancelAuthenticationRequest(); passInput.text = ""; } } } } } } Connections { function onIsResponseRequiredChanged() { passInput.text = ""; if (polkitAgent.flow?.isResponseRequired) root.shouldShow = true; passInput.forceActiveFocus(); } function onIsSuccessfulChanged() { if (polkitAgent.flow?.isSuccessful) root.shouldShow = false; passInput.text = ""; } target: polkitAgent.flow } } PolkitAgent { id: polkitAgent } Variants { model: Quickshell.screens PanelWindow { required property var modelData color: root.shouldShow ? "#80000000" : "transparent" exclusionMode: ExclusionMode.Ignore screen: modelData visible: panelWindow.visible Behavior on color { CAnim { } } anchors { bottom: true left: true right: true top: true } } } }