1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-05 21:15:38 -05:00

modals: apply same pattern of multi-window

- fixes excessive repaints
fixes #716
This commit is contained in:
bbedward
2025-11-23 12:07:45 -05:00
parent 62845b470c
commit 42de6fd074
15 changed files with 1282 additions and 1279 deletions

View File

@@ -1,5 +1,4 @@
import QtQuick
import Quickshell
import Quickshell.Hyprland
import qs.Common
import qs.Modals.Common
@@ -25,38 +24,38 @@ DankModal {
property string passkeyInput: ""
function show(pairingData) {
console.log("BluetoothPairingModal.show() called:", JSON.stringify(pairingData))
token = pairingData.token || ""
deviceName = pairingData.deviceName || ""
deviceAddress = pairingData.deviceAddr || ""
requestType = pairingData.requestType || ""
passkey = pairingData.passkey || 0
pinInput = ""
passkeyInput = ""
console.log("BluetoothPairingModal.show() called:", JSON.stringify(pairingData));
token = pairingData.token || "";
deviceName = pairingData.deviceName || "";
deviceAddress = pairingData.deviceAddr || "";
requestType = pairingData.requestType || "";
passkey = pairingData.passkey || 0;
pinInput = "";
passkeyInput = "";
console.log("BluetoothPairingModal: Calling open()")
open()
console.log("BluetoothPairingModal: Calling open()");
open();
Qt.callLater(() => {
if (contentLoader.item) {
if (requestType === "pin" && contentLoader.item.pinInputField) {
contentLoader.item.pinInputField.forceActiveFocus()
contentLoader.item.pinInputField.forceActiveFocus();
} else if (requestType === "passkey" && contentLoader.item.passkeyInputField) {
contentLoader.item.passkeyInputField.forceActiveFocus()
contentLoader.item.passkeyInputField.forceActiveFocus();
}
}
})
});
}
shouldBeVisible: false
allowStacking: true
keepPopoutsOpen: true
width: 420
height: contentLoader.item ? contentLoader.item.implicitHeight + Theme.spacingM * 2 : 240
modalWidth: 420
modalHeight: contentLoader.item ? contentLoader.item.implicitHeight + Theme.spacingM * 2 : 240
onShouldBeVisibleChanged: () => {
if (!shouldBeVisible) {
pinInput = ""
passkeyInput = ""
pinInput = "";
passkeyInput = "";
}
}
@@ -64,22 +63,22 @@ DankModal {
Qt.callLater(() => {
if (contentLoader.item) {
if (requestType === "pin" && contentLoader.item.pinInputField) {
contentLoader.item.pinInputField.forceActiveFocus()
contentLoader.item.pinInputField.forceActiveFocus();
} else if (requestType === "passkey" && contentLoader.item.passkeyInputField) {
contentLoader.item.passkeyInputField.forceActiveFocus()
contentLoader.item.passkeyInputField.forceActiveFocus();
}
}
})
});
}
onBackgroundClicked: () => {
if (token) {
DMSService.bluetoothCancelPairing(token)
DMSService.bluetoothCancelPairing(token);
}
close()
token = ""
pinInput = ""
passkeyInput = ""
close();
token = "";
pinInput = "";
passkeyInput = "";
}
content: Component {
@@ -95,13 +94,13 @@ DankModal {
Keys.onEscapePressed: event => {
if (token) {
DMSService.bluetoothCancelPairing(token)
DMSService.bluetoothCancelPairing(token);
}
close()
token = ""
pinInput = ""
passkeyInput = ""
event.accepted = true
close();
token = "";
pinInput = "";
passkeyInput = "";
event.accepted = true;
}
Column {
@@ -129,19 +128,19 @@ DankModal {
text: {
switch (requestType) {
case "confirm":
return I18n.tr("Confirm passkey for ") + deviceName
return I18n.tr("Confirm passkey for ") + deviceName;
case "display-passkey":
return I18n.tr("Enter this passkey on ") + deviceName
return I18n.tr("Enter this passkey on ") + deviceName;
case "authorize":
return I18n.tr("Authorize pairing with ") + deviceName
return I18n.tr("Authorize pairing with ") + deviceName;
case "pin":
return I18n.tr("Enter PIN for ") + deviceName
return I18n.tr("Enter PIN for ") + deviceName;
case "passkey":
return I18n.tr("Enter passkey for ") + deviceName
return I18n.tr("Enter passkey for ") + deviceName;
default:
if (requestType.startsWith("authorize-service"))
return I18n.tr("Authorize service for ") + deviceName
return deviceName
return I18n.tr("Authorize service for ") + deviceName;
return deviceName;
}
}
font.pixelSize: Theme.fontSizeMedium
@@ -163,7 +162,7 @@ DankModal {
MouseArea {
anchors.fill: parent
onClicked: () => {
pinInputField.forceActiveFocus()
pinInputField.forceActiveFocus();
}
}
@@ -178,10 +177,10 @@ DankModal {
backgroundColor: "transparent"
enabled: root.shouldBeVisible
onTextEdited: () => {
pinInput = text
pinInput = text;
}
onAccepted: () => {
submitPairing()
submitPairing();
}
}
}
@@ -198,7 +197,7 @@ DankModal {
MouseArea {
anchors.fill: parent
onClicked: () => {
passkeyInputField.forceActiveFocus()
passkeyInputField.forceActiveFocus();
}
}
@@ -213,10 +212,10 @@ DankModal {
backgroundColor: "transparent"
enabled: root.shouldBeVisible
onTextEdited: () => {
passkeyInput = text
passkeyInput = text;
}
onAccepted: () => {
submitPairing()
submitPairing();
}
}
}
@@ -284,12 +283,12 @@ DankModal {
cursorShape: Qt.PointingHandCursor
onClicked: () => {
if (token) {
DMSService.bluetoothCancelPairing(token)
DMSService.bluetoothCancelPairing(token);
}
close()
token = ""
pinInput = ""
passkeyInput = ""
close();
token = "";
pinInput = "";
passkeyInput = "";
}
}
}
@@ -301,10 +300,10 @@ DankModal {
color: pairArea.containsMouse ? Qt.darker(Theme.primary, 1.1) : Theme.primary
enabled: {
if (requestType === "pin")
return pinInput.length > 0
return pinInput.length > 0;
if (requestType === "passkey")
return passkeyInput.length === 6
return true
return passkeyInput.length === 6;
return true;
}
opacity: enabled ? 1 : 0.5
@@ -316,13 +315,13 @@ DankModal {
switch (requestType) {
case "confirm":
case "display-passkey":
return I18n.tr("Confirm")
return I18n.tr("Confirm");
case "authorize":
return I18n.tr("Authorize")
return I18n.tr("Authorize");
default:
if (requestType.startsWith("authorize-service"))
return I18n.tr("Authorize")
return I18n.tr("Pair")
return I18n.tr("Authorize");
return I18n.tr("Pair");
}
}
font.pixelSize: Theme.fontSizeMedium
@@ -338,7 +337,7 @@ DankModal {
cursorShape: Qt.PointingHandCursor
enabled: parent.enabled
onClicked: () => {
submitPairing()
submitPairing();
}
}
@@ -363,48 +362,48 @@ DankModal {
iconColor: Theme.surfaceText
onClicked: () => {
if (token) {
DMSService.bluetoothCancelPairing(token)
DMSService.bluetoothCancelPairing(token);
}
close()
token = ""
pinInput = ""
passkeyInput = ""
close();
token = "";
pinInput = "";
passkeyInput = "";
}
}
}
}
function submitPairing() {
const secrets = {}
const secrets = {};
switch (requestType) {
case "pin":
secrets["pin"] = pinInput
break
secrets["pin"] = pinInput;
break;
case "passkey":
secrets["passkey"] = passkeyInput
break
secrets["passkey"] = passkeyInput;
break;
case "confirm":
case "display-passkey":
case "authorize":
secrets["decision"] = "yes"
break
secrets["decision"] = "yes";
break;
default:
if (requestType.startsWith("authorize-service")) {
secrets["decision"] = "yes"
secrets["decision"] = "yes";
}
break
break;
}
DMSService.bluetoothSubmitPairing(token, secrets, true, response => {
if (response.error) {
ToastService.showError(I18n.tr("Pairing failed"), response.error)
ToastService.showError(I18n.tr("Pairing failed"), response.error);
}
})
});
close()
token = ""
pinInput = ""
passkeyInput = ""
close();
token = "";
pinInput = "";
passkeyInput = "";
}
}

View File

@@ -1,14 +1,12 @@
pragma ComponentBehavior: Bound
import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Hyprland
import Quickshell.Io
import qs.Common
import qs.Modals.Common
import qs.Services
import qs.Widgets
DankModal {
id: clipboardHistoryModal
@@ -31,119 +29,119 @@ DankModal {
readonly property int maxConcurrentLoads: 3
function updateFilteredModel() {
filteredClipboardModel.clear()
filteredClipboardModel.clear();
for (var i = 0; i < clipboardModel.count; i++) {
const entry = clipboardModel.get(i).entry
const entry = clipboardModel.get(i).entry;
if (searchText.trim().length === 0) {
filteredClipboardModel.append({
"entry": entry
})
});
} else {
const content = getEntryPreview(entry).toLowerCase()
const content = getEntryPreview(entry).toLowerCase();
if (content.includes(searchText.toLowerCase())) {
filteredClipboardModel.append({
"entry": entry
})
});
}
}
}
clipboardHistoryModal.totalCount = filteredClipboardModel.count
clipboardHistoryModal.totalCount = filteredClipboardModel.count;
if (filteredClipboardModel.count === 0) {
keyboardNavigationActive = false
selectedIndex = 0
keyboardNavigationActive = false;
selectedIndex = 0;
} else if (selectedIndex >= filteredClipboardModel.count) {
selectedIndex = filteredClipboardModel.count - 1
selectedIndex = filteredClipboardModel.count - 1;
}
}
function toggle() {
if (shouldBeVisible) {
hide()
hide();
} else {
show()
show();
}
}
function show() {
open()
clipboardHistoryModal.searchText = ""
clipboardHistoryModal.activeImageLoads = 0
clipboardHistoryModal.shouldHaveFocus = true
refreshClipboard()
keyboardController.reset()
open();
clipboardHistoryModal.searchText = "";
clipboardHistoryModal.activeImageLoads = 0;
clipboardHistoryModal.shouldHaveFocus = true;
refreshClipboard();
keyboardController.reset();
Qt.callLater(function () {
if (contentLoader.item && contentLoader.item.searchField) {
contentLoader.item.searchField.text = ""
contentLoader.item.searchField.forceActiveFocus()
contentLoader.item.searchField.text = "";
contentLoader.item.searchField.forceActiveFocus();
}
})
});
}
function hide() {
close()
clipboardHistoryModal.searchText = ""
clipboardHistoryModal.activeImageLoads = 0
updateFilteredModel()
keyboardController.reset()
cleanupTempFiles()
close();
clipboardHistoryModal.searchText = "";
clipboardHistoryModal.activeImageLoads = 0;
updateFilteredModel();
keyboardController.reset();
cleanupTempFiles();
}
function cleanupTempFiles() {
Quickshell.execDetached(["sh", "-c", "rm -f /tmp/clipboard_*.png"])
Quickshell.execDetached(["sh", "-c", "rm -f /tmp/clipboard_*.png"]);
}
function refreshClipboard() {
clipboardProcesses.refresh()
clipboardProcesses.refresh();
}
function copyEntry(entry) {
const entryId = entry.split('\t')[0]
Quickshell.execDetached(["sh", "-c", `cliphist decode ${entryId} | wl-copy`])
ToastService.showInfo(I18n.tr("Copied to clipboard"))
hide()
const entryId = entry.split('\t')[0];
Quickshell.execDetached(["sh", "-c", `cliphist decode ${entryId} | wl-copy`]);
ToastService.showInfo(I18n.tr("Copied to clipboard"));
hide();
}
function deleteEntry(entry) {
clipboardProcesses.deleteEntry(entry)
clipboardProcesses.deleteEntry(entry);
}
function clearAll() {
clipboardProcesses.clearAll()
clipboardProcesses.clearAll();
}
function getEntryPreview(entry) {
let content = entry.replace(/^\s*\d+\s+/, "")
let content = entry.replace(/^\s*\d+\s+/, "");
if (content.includes("image/") || content.includes("binary data") || /\.(png|jpg|jpeg|gif|bmp|webp)/i.test(content)) {
const dimensionMatch = content.match(/(\d+)x(\d+)/)
const dimensionMatch = content.match(/(\d+)x(\d+)/);
if (dimensionMatch) {
return `Image ${dimensionMatch[1]}×${dimensionMatch[2]}`
return `Image ${dimensionMatch[1]}×${dimensionMatch[2]}`;
}
const typeMatch = content.match(/\b(png|jpg|jpeg|gif|bmp|webp)\b/i)
const typeMatch = content.match(/\b(png|jpg|jpeg|gif|bmp|webp)\b/i);
if (typeMatch) {
return `Image (${typeMatch[1].toUpperCase()})`
return `Image (${typeMatch[1].toUpperCase()})`;
}
return "Image"
return "Image";
}
if (content.length > ClipboardConstants.previewLength) {
return content.substring(0, ClipboardConstants.previewLength) + "..."
return content.substring(0, ClipboardConstants.previewLength) + "...";
}
return content
return content;
}
function getEntryType(entry) {
if (entry.includes("image/") || entry.includes("binary data") || /\.(png|jpg|jpeg|gif|bmp|webp)/i.test(entry) || /\b(png|jpg|jpeg|gif|bmp|webp)\b/i.test(entry)) {
return "image"
return "image";
}
if (entry.length > ClipboardConstants.longTextThreshold) {
return "long_text"
return "long_text";
}
return "text"
return "text";
}
visible: false
width: ClipboardConstants.modalWidth
height: ClipboardConstants.modalHeight
modalWidth: ClipboardConstants.modalWidth
modalHeight: ClipboardConstants.modalHeight
backgroundColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
cornerRadius: Theme.cornerRadius
borderColor: Theme.outlineMedium
@@ -151,7 +149,7 @@ DankModal {
enableShadow: true
onBackgroundClicked: hide()
modalFocusScope.Keys.onPressed: function (event) {
keyboardController.handleKey(event)
keyboardController.handleKey(event);
}
content: clipboardContent
@@ -166,12 +164,12 @@ DankModal {
confirmButtonColor: Theme.primary
onVisibleChanged: {
if (visible) {
clipboardHistoryModal.shouldHaveFocus = false
clipboardHistoryModal.shouldHaveFocus = false;
} else if (clipboardHistoryModal.shouldBeVisible) {
clipboardHistoryModal.shouldHaveFocus = true
clipboardHistoryModal.modalFocusScope.forceActiveFocus()
clipboardHistoryModal.shouldHaveFocus = true;
clipboardHistoryModal.modalFocusScope.forceActiveFocus();
if (clipboardHistoryModal.contentLoader.item && clipboardHistoryModal.contentLoader.item.searchField) {
clipboardHistoryModal.contentLoader.item.searchField.forceActiveFocus()
clipboardHistoryModal.contentLoader.item.searchField.forceActiveFocus();
}
}
}
@@ -198,18 +196,18 @@ DankModal {
IpcHandler {
function open(): string {
clipboardHistoryModal.show()
return "CLIPBOARD_OPEN_SUCCESS"
clipboardHistoryModal.show();
return "CLIPBOARD_OPEN_SUCCESS";
}
function close(): string {
clipboardHistoryModal.hide()
return "CLIPBOARD_CLOSE_SUCCESS"
clipboardHistoryModal.hide();
return "CLIPBOARD_CLOSE_SUCCESS";
}
function toggle(): string {
clipboardHistoryModal.toggle()
return "CLIPBOARD_TOGGLE_SUCCESS"
clipboardHistoryModal.toggle();
return "CLIPBOARD_TOGGLE_SUCCESS";
}
target: "clipboard"

View File

@@ -19,141 +19,141 @@ DankModal {
property bool keyboardNavigation: false
function show(title, message, onConfirmCallback, onCancelCallback) {
confirmTitle = title || ""
confirmMessage = message || ""
confirmButtonText = "Confirm"
cancelButtonText = "Cancel"
confirmButtonColor = Theme.primary
onConfirm = onConfirmCallback || (() => {})
onCancel = onCancelCallback || (() => {})
selectedButton = -1
keyboardNavigation = false
open()
confirmTitle = title || "";
confirmMessage = message || "";
confirmButtonText = "Confirm";
cancelButtonText = "Cancel";
confirmButtonColor = Theme.primary;
onConfirm = onConfirmCallback || (() => {});
onCancel = onCancelCallback || (() => {});
selectedButton = -1;
keyboardNavigation = false;
open();
}
function showWithOptions(options) {
confirmTitle = options.title || ""
confirmMessage = options.message || ""
confirmButtonText = options.confirmText || "Confirm"
cancelButtonText = options.cancelText || "Cancel"
confirmButtonColor = options.confirmColor || Theme.primary
onConfirm = options.onConfirm || (() => {})
onCancel = options.onCancel || (() => {})
selectedButton = -1
keyboardNavigation = false
open()
confirmTitle = options.title || "";
confirmMessage = options.message || "";
confirmButtonText = options.confirmText || "Confirm";
cancelButtonText = options.cancelText || "Cancel";
confirmButtonColor = options.confirmColor || Theme.primary;
onConfirm = options.onConfirm || (() => {});
onCancel = options.onCancel || (() => {});
selectedButton = -1;
keyboardNavigation = false;
open();
}
function selectButton() {
close()
close();
if (selectedButton === 0) {
if (onCancel) {
onCancel()
onCancel();
}
} else {
if (onConfirm) {
onConfirm()
onConfirm();
}
}
}
shouldBeVisible: false
allowStacking: true
width: 350
height: contentLoader.item ? contentLoader.item.implicitHeight + Theme.spacingM * 2 : 160
modalWidth: 350
modalHeight: contentLoader.item ? contentLoader.item.implicitHeight + Theme.spacingM * 2 : 160
enableShadow: true
shouldHaveFocus: true
onBackgroundClicked: {
close()
close();
if (onCancel) {
onCancel()
onCancel();
}
}
onOpened: {
Qt.callLater(function () {
modalFocusScope.forceActiveFocus()
modalFocusScope.focus = true
shouldHaveFocus = true
})
modalFocusScope.forceActiveFocus();
modalFocusScope.focus = true;
shouldHaveFocus = true;
});
}
modalFocusScope.Keys.onPressed: function (event) {
switch (event.key) {
case Qt.Key_Escape:
close()
close();
if (onCancel) {
onCancel()
onCancel();
}
event.accepted = true
break
event.accepted = true;
break;
case Qt.Key_Left:
case Qt.Key_Up:
keyboardNavigation = true
selectedButton = 0
event.accepted = true
break
keyboardNavigation = true;
selectedButton = 0;
event.accepted = true;
break;
case Qt.Key_Right:
case Qt.Key_Down:
keyboardNavigation = true
selectedButton = 1
event.accepted = true
break
keyboardNavigation = true;
selectedButton = 1;
event.accepted = true;
break;
case Qt.Key_N:
if (event.modifiers & Qt.ControlModifier) {
keyboardNavigation = true
selectedButton = (selectedButton + 1) % 2
event.accepted = true
keyboardNavigation = true;
selectedButton = (selectedButton + 1) % 2;
event.accepted = true;
}
break
break;
case Qt.Key_P:
if (event.modifiers & Qt.ControlModifier) {
keyboardNavigation = true
selectedButton = selectedButton === -1 ? 1 : (selectedButton - 1 + 2) % 2
event.accepted = true
keyboardNavigation = true;
selectedButton = selectedButton === -1 ? 1 : (selectedButton - 1 + 2) % 2;
event.accepted = true;
}
break
break;
case Qt.Key_J:
if (event.modifiers & Qt.ControlModifier) {
keyboardNavigation = true
selectedButton = 1
event.accepted = true
keyboardNavigation = true;
selectedButton = 1;
event.accepted = true;
}
break
break;
case Qt.Key_K:
if (event.modifiers & Qt.ControlModifier) {
keyboardNavigation = true
selectedButton = 0
event.accepted = true
keyboardNavigation = true;
selectedButton = 0;
event.accepted = true;
}
break
break;
case Qt.Key_H:
if (event.modifiers & Qt.ControlModifier) {
keyboardNavigation = true
selectedButton = 0
event.accepted = true
keyboardNavigation = true;
selectedButton = 0;
event.accepted = true;
}
break
break;
case Qt.Key_L:
if (event.modifiers & Qt.ControlModifier) {
keyboardNavigation = true
selectedButton = 1
event.accepted = true
keyboardNavigation = true;
selectedButton = 1;
event.accepted = true;
}
break
break;
case Qt.Key_Tab:
keyboardNavigation = true
selectedButton = selectedButton === -1 ? 0 : (selectedButton + 1) % 2
event.accepted = true
break
keyboardNavigation = true;
selectedButton = selectedButton === -1 ? 0 : (selectedButton + 1) % 2;
event.accepted = true;
break;
case Qt.Key_Return:
case Qt.Key_Enter:
if (selectedButton !== -1) {
selectButton()
selectButton();
} else {
selectedButton = 1
selectButton()
selectedButton = 1;
selectButton();
}
event.accepted = true
break
event.accepted = true;
break;
}
}
@@ -210,11 +210,11 @@ DankModal {
radius: Theme.cornerRadius
color: {
if (keyboardNavigation && selectedButton === 0) {
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12);
} else if (cancelButton.containsMouse) {
return Theme.surfacePressed
return Theme.surfacePressed;
} else {
return Theme.surfaceVariantAlpha
return Theme.surfaceVariantAlpha;
}
}
border.color: (keyboardNavigation && selectedButton === 0) ? Theme.primary : "transparent"
@@ -235,8 +235,8 @@ DankModal {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
selectedButton = 0
selectButton()
selectedButton = 0;
selectButton();
}
}
}
@@ -246,13 +246,13 @@ DankModal {
height: 40
radius: Theme.cornerRadius
color: {
const baseColor = confirmButtonColor
const baseColor = confirmButtonColor;
if (keyboardNavigation && selectedButton === 1) {
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, 1)
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, 1);
} else if (confirmButton.containsMouse) {
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, 0.9)
return Qt.rgba(baseColor.r, baseColor.g, baseColor.b, 0.9);
} else {
return baseColor
return baseColor;
}
}
border.color: (keyboardNavigation && selectedButton === 1) ? "white" : "transparent"
@@ -273,8 +273,8 @@ DankModal {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
selectedButton = 1
selectButton()
selectedButton = 1;
selectButton();
}
}
}

View File

@@ -1,25 +1,23 @@
import QtQuick
import Quickshell
import Quickshell.Hyprland
import Quickshell.Wayland
import qs.Common
import qs.Services
import qs.Widgets
PanelWindow {
Item {
id: root
property string layerNamespace: "dms:modal"
WlrLayershell.namespace: layerNamespace
property alias content: contentLoader.sourceComponent
property alias contentLoader: contentLoader
property Item directContent: null
property real width: 400
property real height: 300
readonly property real screenWidth: screen ? screen.width : 1920
readonly property real screenHeight: screen ? screen.height : 1080
readonly property real dpr: CompositorService.getScreenScale(screen)
property real modalWidth: 400
property real modalHeight: 300
property var targetScreen: Quickshell.screens[0]
readonly property real screenWidth: targetScreen ? targetScreen.width : 1920
readonly property real screenHeight: targetScreen ? targetScreen.height : 1080
readonly property real dpr: targetScreen ? CompositorService.getScreenScale(targetScreen) : 1
property bool showBackground: true
property real backgroundOpacity: 0.5
property string positioning: "center"
@@ -44,87 +42,102 @@ PanelWindow {
property bool allowStacking: false
property bool keepContentLoaded: false
property bool keepPopoutsOpen: false
property var customKeyboardFocus: null
signal opened
signal dialogClosed
signal backgroundClicked
readonly property bool useBackgroundWindow: {
const layerOverride = Quickshell.env("DMS_MODAL_LAYER");
return !layerOverride || layerOverride === "overlay";
}
function open() {
ModalManager.openModal(root)
closeTimer.stop()
shouldBeVisible = true
visible = true
shouldHaveFocus = false
ModalManager.openModal(root);
closeTimer.stop();
shouldBeVisible = true;
if (useBackgroundWindow)
backgroundWindow.visible = true;
contentWindow.visible = true;
shouldHaveFocus = false;
Qt.callLater(() => {
shouldHaveFocus = Qt.binding(() => shouldBeVisible)
})
shouldHaveFocus = Qt.binding(() => shouldBeVisible);
});
}
function close() {
shouldBeVisible = false
shouldHaveFocus = false
closeTimer.restart()
shouldBeVisible = false;
shouldHaveFocus = false;
closeTimer.restart();
}
function toggle() {
if (shouldBeVisible) {
close()
} else {
open()
}
}
visible: shouldBeVisible
color: "transparent"
WlrLayershell.layer: {
switch (Quickshell.env("DMS_MODAL_LAYER")) {
case "bottom":
return WlrLayershell.Bottom
case "overlay":
return WlrLayershell.Overlay
case "background":
return WlrLayershell.Background
default:
return WlrLayershell.Top
}
}
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: {
if (!shouldHaveFocus) return WlrKeyboardFocus.None
if (CompositorService.isHyprland) return WlrKeyboardFocus.OnDemand
return WlrKeyboardFocus.Exclusive
}
onVisibleChanged: {
if (root.visible) {
opened()
} else {
if (Qt.inputMethod) {
Qt.inputMethod.hide()
Qt.inputMethod.reset()
}
dialogClosed()
}
shouldBeVisible ? close() : open();
}
Connections {
target: ModalManager
function onCloseAllModalsExcept(excludedModal) {
if (excludedModal !== root && !allowStacking && shouldBeVisible) {
close()
close();
}
}
target: ModalManager
}
Timer {
id: closeTimer
interval: animationDuration + 120
onTriggered: {
visible = false
if (!shouldBeVisible) {
contentWindow.visible = false;
if (useBackgroundWindow)
backgroundWindow.visible = false;
dialogClosed();
}
}
}
readonly property real shadowBuffer: 5
readonly property real alignedWidth: Theme.px(modalWidth, dpr)
readonly property real alignedHeight: Theme.px(modalHeight, dpr)
readonly property real alignedX: Theme.snap((() => {
switch (positioning) {
case "center":
return (screenWidth - alignedWidth) / 2;
case "top-right":
return Math.max(Theme.spacingL, screenWidth - alignedWidth - Theme.spacingL);
case "custom":
return customPosition.x;
default:
return 0;
}
})(), dpr)
readonly property real alignedY: Theme.snap((() => {
switch (positioning) {
case "center":
return (screenHeight - alignedHeight) / 2;
case "top-right":
return Theme.barHeight + Theme.spacingXS;
case "custom":
return customPosition.y;
default:
return 0;
}
})(), dpr)
PanelWindow {
id: backgroundWindow
screen: root.targetScreen
visible: false
color: "transparent"
WlrLayershell.namespace: root.layerNamespace + ":background"
WlrLayershell.layer: WlrLayershell.Top
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: WlrKeyboardFocus.None
anchors {
top: true
@@ -137,16 +150,18 @@ PanelWindow {
anchors.fill: parent
enabled: root.closeOnBackgroundClick && root.shouldBeVisible
onClicked: mouse => {
const localPos = mapToItem(contentContainer, mouse.x, mouse.y)
if (localPos.x < 0 || localPos.x > contentContainer.width || localPos.y < 0 || localPos.y > contentContainer.height) {
root.backgroundClicked()
}
const clickX = mouse.x;
const clickY = mouse.y;
const outsideContent = clickX < root.alignedX || clickX > root.alignedX + root.alignedWidth || clickY < root.alignedY || clickY > root.alignedY + root.alignedHeight;
if (!outsideContent)
return;
root.backgroundClicked();
}
}
Rectangle {
id: background
anchors.fill: parent
color: "black"
opacity: root.showBackground && SettingsData.modalDarkenBackground ? (root.shouldBeVisible ? root.backgroundOpacity : 0) : 0
@@ -160,32 +175,68 @@ PanelWindow {
}
}
}
}
PanelWindow {
id: contentWindow
screen: root.targetScreen
visible: false
color: "transparent"
WlrLayershell.namespace: root.layerNamespace
WlrLayershell.layer: {
switch (Quickshell.env("DMS_MODAL_LAYER")) {
case "bottom":
return WlrLayershell.Bottom;
case "top":
return WlrLayershell.Top;
case "background":
return WlrLayershell.Background;
default:
return WlrLayershell.Overlay;
}
}
WlrLayershell.exclusiveZone: -1
WlrLayershell.keyboardFocus: {
if (customKeyboardFocus !== null)
return customKeyboardFocus;
if (!shouldHaveFocus)
return WlrKeyboardFocus.None;
if (CompositorService.isHyprland)
return WlrKeyboardFocus.OnDemand;
return WlrKeyboardFocus.Exclusive;
}
anchors {
left: true
top: true
}
WlrLayershell.margins {
left: Math.max(0, Theme.snap(root.alignedX - shadowBuffer, dpr))
top: Math.max(0, Theme.snap(root.alignedY - shadowBuffer, dpr))
}
implicitWidth: root.alignedWidth + (shadowBuffer * 2)
implicitHeight: root.alignedHeight + (shadowBuffer * 2)
onVisibleChanged: {
if (visible) {
opened();
} else {
if (Qt.inputMethod) {
Qt.inputMethod.hide();
Qt.inputMethod.reset();
}
}
}
Item {
id: modalContainer
width: Theme.px(root.width, dpr)
height: Theme.px(root.height, dpr)
x: {
if (positioning === "center") {
return Theme.snap((root.screenWidth - width) / 2, dpr)
} else if (positioning === "top-right") {
return Theme.px(Math.max(Theme.spacingL, root.screenWidth - width - Theme.spacingL), dpr)
} else if (positioning === "custom") {
return Theme.snap(root.customPosition.x, dpr)
}
return 0
}
y: {
if (positioning === "center") {
return Theme.snap((root.screenHeight - height) / 2, dpr)
} else if (positioning === "top-right") {
return Theme.px(Theme.barHeight + Theme.spacingXS, dpr)
} else if (positioning === "custom") {
return Theme.snap(root.customPosition.y, dpr)
}
return 0
}
x: shadowBuffer
y: shadowBuffer
width: root.alignedWidth
height: root.alignedHeight
readonly property bool slide: root.animationType === "slide"
readonly property real offsetX: slide ? 15 : 0
@@ -201,9 +252,9 @@ PanelWindow {
Connections {
target: root
function onShouldBeVisibleChanged() {
modalContainer.animX = Theme.snap(root.shouldBeVisible ? 0 : modalContainer.offsetX, root.dpr)
modalContainer.animY = Theme.snap(root.shouldBeVisible ? 0 : modalContainer.offsetY, root.dpr)
modalContainer.scaleValue = root.shouldBeVisible ? 1.0 : root.animationScaleCollapsed
modalContainer.animX = Theme.snap(root.shouldBeVisible ? 0 : modalContainer.offsetX, root.dpr);
modalContainer.animY = Theme.snap(root.shouldBeVisible ? 0 : modalContainer.offsetY, root.dpr);
modalContainer.scaleValue = root.shouldBeVisible ? 1.0 : root.animationScaleCollapsed;
}
}
@@ -233,18 +284,19 @@ PanelWindow {
Item {
id: contentContainer
anchors.centerIn: parent
width: parent.width
height: parent.height
clip: false
layer.enabled: true
layer.smooth: false
layer.textureSize: Qt.size(Math.round(width * root.dpr), Math.round(height * root.dpr))
Item {
id: animatedContent
anchors.fill: parent
clip: false
opacity: root.shouldBeVisible ? 1 : 0
scale: modalContainer.scaleValue
x: Theme.snap(modalContainer.animX + (parent.width - width) * (1 - modalContainer.scaleValue) * 0.5, root.dpr)
y: Theme.snap(modalContainer.animY + (parent.height - height) * (1 - modalContainer.scaleValue) * 0.5, root.dpr)
x: Theme.snap(modalContainer.animX, root.dpr) + (parent.width - width) * (1 - modalContainer.scaleValue) * 0.5
y: Theme.snap(modalContainer.animY, root.dpr) + (parent.height - height) * (1 - modalContainer.scaleValue) * 0.5
Behavior on opacity {
NumberAnimation {
@@ -269,7 +321,6 @@ PanelWindow {
Item {
id: directContentWrapper
anchors.fill: parent
visible: root.directContent !== null
focus: true
@@ -277,30 +328,28 @@ PanelWindow {
Component.onCompleted: {
if (root.directContent) {
root.directContent.parent = directContentWrapper
root.directContent.anchors.fill = directContentWrapper
Qt.callLater(() => root.directContent.forceActiveFocus())
root.directContent.parent = directContentWrapper;
root.directContent.anchors.fill = directContentWrapper;
Qt.callLater(() => root.directContent.forceActiveFocus());
}
}
Connections {
target: root
function onDirectContentChanged() {
if (root.directContent) {
root.directContent.parent = directContentWrapper
root.directContent.anchors.fill = directContentWrapper
Qt.callLater(() => root.directContent.forceActiveFocus())
root.directContent.parent = directContentWrapper;
root.directContent.anchors.fill = directContentWrapper;
Qt.callLater(() => root.directContent.forceActiveFocus());
}
}
target: root
}
}
Loader {
id: contentLoader
anchors.fill: parent
active: root.directContent === null && (root.keepContentLoaded || root.shouldBeVisible || root.visible)
active: root.directContent === null && (root.keepContentLoaded || root.shouldBeVisible || contentWindow.visible)
asynchronous: false
focus: true
clip: false
@@ -308,7 +357,8 @@ PanelWindow {
onLoaded: {
if (item) {
Qt.callLater(() => item.forceActiveFocus())
Qt.callLater(() => item.forceActiveFocus());
}
}
}
}
@@ -318,15 +368,15 @@ PanelWindow {
FocusScope {
id: focusScope
objectName: "modalFocusScope"
anchors.fill: parent
visible: root.shouldBeVisible || root.visible
visible: root.shouldBeVisible || contentWindow.visible
focus: root.shouldBeVisible
Keys.onEscapePressed: event => {
if (root.closeOnEscapeKey && shouldHaveFocus) {
root.close()
event.accepted = true
root.close();
event.accepted = true;
}
}
}
}

View File

@@ -1,8 +1,6 @@
import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Hyprland
import Quickshell.Io
import qs.Common
import qs.Modals.Common
import qs.Services
@@ -32,87 +30,79 @@ DankModal {
property real gradientX: 0
property real gradientY: 0
readonly property var standardColors: [
"#f44336", "#e91e63", "#9c27b0", "#673ab7", "#3f51b5", "#2196f3", "#03a9f4", "#00bcd4",
"#009688", "#4caf50", "#8bc34a", "#cddc39", "#ffeb3b", "#ffc107", "#ff9800", "#ff5722",
"#d32f2f", "#c2185b", "#7b1fa2", "#512da8", "#303f9f", "#1976d2", "#0288d1", "#0097a7",
"#00796b", "#388e3c", "#689f38", "#afb42b", "#fbc02d", "#ffa000", "#f57c00", "#e64a19",
"#c62828", "#ad1457", "#6a1b9a", "#4527a0", "#283593", "#1565c0", "#0277bd", "#00838f",
"#00695c", "#2e7d32", "#558b2f", "#9e9d24", "#f9a825", "#ff8f00", "#ef6c00", "#d84315",
"#ffffff", "#9e9e9e", "#212121"
]
readonly property var standardColors: ["#f44336", "#e91e63", "#9c27b0", "#673ab7", "#3f51b5", "#2196f3", "#03a9f4", "#00bcd4", "#009688", "#4caf50", "#8bc34a", "#cddc39", "#ffeb3b", "#ffc107", "#ff9800", "#ff5722", "#d32f2f", "#c2185b", "#7b1fa2", "#512da8", "#303f9f", "#1976d2", "#0288d1", "#0097a7", "#00796b", "#388e3c", "#689f38", "#afb42b", "#fbc02d", "#ffa000", "#f57c00", "#e64a19", "#c62828", "#ad1457", "#6a1b9a", "#4527a0", "#283593", "#1565c0", "#0277bd", "#00838f", "#00695c", "#2e7d32", "#558b2f", "#9e9d24", "#f9a825", "#ff8f00", "#ef6c00", "#d84315", "#ffffff", "#9e9e9e", "#212121"]
function show() {
currentColor = selectedColor
updateFromColor(currentColor)
open()
currentColor = selectedColor;
updateFromColor(currentColor);
open();
}
function hide() {
onColorSelectedCallback = null
close()
onColorSelectedCallback = null;
close();
}
function hideInstant() {
onColorSelectedCallback = null
shouldBeVisible = false
visible = false
onColorSelectedCallback = null;
shouldBeVisible = false;
visible = false;
}
onColorSelected: (color) => {
onColorSelected: color => {
if (onColorSelectedCallback) {
onColorSelectedCallback(color)
onColorSelectedCallback(color);
}
}
function copyColorToClipboard(colorValue) {
Quickshell.execDetached(["sh", "-c", `echo -n "${colorValue}" | wl-copy`])
ToastService.showInfo(`Color ${colorValue} copied`)
SessionData.addRecentColor(currentColor)
Quickshell.execDetached(["sh", "-c", `echo -n "${colorValue}" | wl-copy`]);
ToastService.showInfo(`Color ${colorValue} copied`);
SessionData.addRecentColor(currentColor);
}
function updateFromColor(color) {
hue = color.hsvHue
saturation = color.hsvSaturation
value = color.hsvValue
alpha = color.a
gradientX = saturation
gradientY = 1 - value
hue = color.hsvHue;
saturation = color.hsvSaturation;
value = color.hsvValue;
alpha = color.a;
gradientX = saturation;
gradientY = 1 - value;
}
function updateColor() {
currentColor = Qt.hsva(hue, saturation, value, alpha)
currentColor = Qt.hsva(hue, saturation, value, alpha);
}
function updateColorFromGradient(x, y) {
saturation = Math.max(0, Math.min(1, x))
value = Math.max(0, Math.min(1, 1 - y))
updateColor()
selectedColor = currentColor
saturation = Math.max(0, Math.min(1, x));
value = Math.max(0, Math.min(1, 1 - y));
updateColor();
selectedColor = currentColor;
}
function pickColorFromScreen() {
hideInstant()
hideInstant();
Proc.runCommand("hyprpicker", ["hyprpicker", "--format=hex"], (output, errorCode) => {
if (errorCode !== 0) {
console.warn("hyprpicker exited with code:", errorCode)
root.show()
return
console.warn("hyprpicker exited with code:", errorCode);
root.show();
return;
}
const colorStr = output.trim()
const colorStr = output.trim();
if (colorStr.length >= 7 && colorStr.startsWith('#')) {
const pickedColor = Qt.color(colorStr)
root.selectedColor = pickedColor
root.currentColor = pickedColor
root.updateFromColor(pickedColor)
copyColorToClipboard(colorStr)
root.show()
const pickedColor = Qt.color(colorStr);
root.selectedColor = pickedColor;
root.currentColor = pickedColor;
root.updateFromColor(pickedColor);
copyColorToClipboard(colorStr);
root.show();
}
})
});
}
width: 680
height: contentLoader.item ? contentLoader.item.implicitHeight + Theme.spacingM * 2 : 680
modalWidth: 680
modalHeight: contentLoader.item ? contentLoader.item.implicitHeight + Theme.spacingM * 2 : 680
backgroundColor: Theme.surfaceContainer
cornerRadius: Theme.cornerRadius
borderColor: Theme.outlineMedium
@@ -133,8 +123,8 @@ DankModal {
focus: true
Keys.onEscapePressed: event => {
root.hide()
event.accepted = true
root.hide();
event.accepted = true;
}
Column {
@@ -172,7 +162,7 @@ DankModal {
iconSize: Theme.iconSize - 4
iconColor: Theme.surfaceText
onClicked: () => {
root.pickColorFromScreen()
root.pickColorFromScreen();
}
}
@@ -181,7 +171,7 @@ DankModal {
iconSize: Theme.iconSize - 4
iconColor: Theme.surfaceText
onClicked: () => {
root.hide()
root.hide();
}
}
}
@@ -207,8 +197,14 @@ DankModal {
anchors.fill: parent
gradient: Gradient {
orientation: Gradient.Horizontal
GradientStop { position: 0.0; color: "#ffffff" }
GradientStop { position: 1.0; color: "transparent" }
GradientStop {
position: 0.0
color: "#ffffff"
}
GradientStop {
position: 1.0
color: "transparent"
}
}
}
@@ -216,8 +212,14 @@ DankModal {
anchors.fill: parent
gradient: Gradient {
orientation: Gradient.Vertical
GradientStop { position: 0.0; color: "transparent" }
GradientStop { position: 1.0; color: "#000000" }
GradientStop {
position: 0.0
color: "transparent"
}
GradientStop {
position: 1.0
color: "#000000"
}
}
}
}
@@ -248,19 +250,19 @@ DankModal {
anchors.fill: parent
cursorShape: Qt.CrossCursor
onPressed: mouse => {
const x = Math.max(0, Math.min(1, mouse.x / width))
const y = Math.max(0, Math.min(1, mouse.y / height))
root.gradientX = x
root.gradientY = y
root.updateColorFromGradient(x, y)
const x = Math.max(0, Math.min(1, mouse.x / width));
const y = Math.max(0, Math.min(1, mouse.y / height));
root.gradientX = x;
root.gradientY = y;
root.updateColorFromGradient(x, y);
}
onPositionChanged: mouse => {
if (pressed) {
const x = Math.max(0, Math.min(1, mouse.x / width))
const y = Math.max(0, Math.min(1, mouse.y / height))
root.gradientX = x
root.gradientY = y
root.updateColorFromGradient(x, y)
const x = Math.max(0, Math.min(1, mouse.x / width));
const y = Math.max(0, Math.min(1, mouse.y / height));
root.gradientX = x;
root.gradientY = y;
root.updateColorFromGradient(x, y);
}
}
}
@@ -276,13 +278,34 @@ DankModal {
gradient: Gradient {
orientation: Gradient.Vertical
GradientStop { position: 0.00; color: "#ff0000" }
GradientStop { position: 0.17; color: "#ffff00" }
GradientStop { position: 0.33; color: "#00ff00" }
GradientStop { position: 0.50; color: "#00ffff" }
GradientStop { position: 0.67; color: "#0000ff" }
GradientStop { position: 0.83; color: "#ff00ff" }
GradientStop { position: 1.00; color: "#ff0000" }
GradientStop {
position: 0.00
color: "#ff0000"
}
GradientStop {
position: 0.17
color: "#ffff00"
}
GradientStop {
position: 0.33
color: "#00ff00"
}
GradientStop {
position: 0.50
color: "#00ffff"
}
GradientStop {
position: 0.67
color: "#0000ff"
}
GradientStop {
position: 0.83
color: "#ff00ff"
}
GradientStop {
position: 1.00
color: "#ff0000"
}
}
Rectangle {
@@ -299,17 +322,17 @@ DankModal {
anchors.fill: parent
cursorShape: Qt.SizeVerCursor
onPressed: mouse => {
const h = Math.max(0, Math.min(1, mouse.y / height))
root.hue = h
root.updateColor()
root.selectedColor = root.currentColor
const h = Math.max(0, Math.min(1, mouse.y / height));
root.hue = h;
root.updateColor();
root.selectedColor = root.currentColor;
}
onPositionChanged: mouse => {
if (pressed) {
const h = Math.max(0, Math.min(1, mouse.y / height))
root.hue = h
root.updateColor()
root.selectedColor = root.currentColor
const h = Math.max(0, Math.min(1, mouse.y / height));
root.hue = h;
root.updateColor();
root.selectedColor = root.currentColor;
}
}
}
@@ -348,10 +371,10 @@ DankModal {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: () => {
const pickedColor = Qt.color(modelData)
root.selectedColor = pickedColor
root.currentColor = pickedColor
root.updateFromColor(pickedColor)
const pickedColor = Qt.color(modelData);
root.selectedColor = pickedColor;
root.currentColor = pickedColor;
root.updateFromColor(pickedColor);
}
}
}
@@ -393,9 +416,9 @@ DankModal {
color: {
if (index < SessionData.recentColors.length) {
return SessionData.recentColors[index]
return SessionData.recentColors[index];
}
return Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
return Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency);
}
opacity: index < SessionData.recentColors.length ? 1.0 : 0.3
@@ -406,10 +429,10 @@ DankModal {
enabled: index < SessionData.recentColors.length
onClicked: () => {
if (index < SessionData.recentColors.length) {
const pickedColor = SessionData.recentColors[index]
root.selectedColor = pickedColor
root.currentColor = pickedColor
root.updateFromColor(pickedColor)
const pickedColor = SessionData.recentColors[index];
root.selectedColor = pickedColor;
root.currentColor = pickedColor;
root.updateFromColor(pickedColor);
}
}
}
@@ -435,10 +458,10 @@ DankModal {
minimum: 0
maximum: 100
showValue: false
onSliderValueChanged: (newValue) => {
root.alpha = newValue / 100
root.updateColor()
root.selectedColor = root.currentColor
onSliderValueChanged: newValue => {
root.alpha = newValue / 100;
root.updateColor();
root.selectedColor = root.currentColor;
}
}
}
@@ -485,9 +508,10 @@ DankModal {
text: root.currentColor.toString()
font.pixelSize: Theme.fontSizeMedium
textColor: {
if (text.length === 0) return Theme.surfaceText
const hexPattern = /^#?[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$/
return hexPattern.test(text) ? Theme.surfaceText : Theme.error
if (text.length === 0)
return Theme.surfaceText;
const hexPattern = /^#?[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$/;
return hexPattern.test(text) ? Theme.surfaceText : Theme.error;
}
placeholderText: "#000000"
backgroundColor: Theme.surfaceHover
@@ -496,13 +520,14 @@ DankModal {
topPadding: Theme.spacingS
bottomPadding: Theme.spacingS
onAccepted: () => {
const hexPattern = /^#?[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$/
if (!hexPattern.test(text)) return
const color = Qt.color(text)
const hexPattern = /^#?[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?$/;
if (!hexPattern.test(text))
return;
const color = Qt.color(text);
if (color) {
root.selectedColor = color
root.currentColor = color
root.updateFromColor(color)
root.selectedColor = color;
root.currentColor = color;
root.updateFromColor(color);
}
}
}
@@ -514,7 +539,7 @@ DankModal {
buttonSize: 36
anchors.verticalCenter: parent.verticalCenter
onClicked: () => {
root.copyColorToClipboard(hexInput.text)
root.copyColorToClipboard(hexInput.text);
}
}
}
@@ -546,14 +571,14 @@ DankModal {
StyledText {
anchors.centerIn: parent
text: {
const r = Math.round(root.currentColor.r * 255)
const g = Math.round(root.currentColor.g * 255)
const b = Math.round(root.currentColor.b * 255)
const r = Math.round(root.currentColor.r * 255);
const g = Math.round(root.currentColor.g * 255);
const b = Math.round(root.currentColor.b * 255);
if (root.alpha < 1) {
const a = Math.round(root.alpha * 255)
return `${r}, ${g}, ${b}, ${a}`
const a = Math.round(root.alpha * 255);
return `${r}, ${g}, ${b}, ${a}`;
}
return `${r}, ${g}, ${b}`
return `${r}, ${g}, ${b}`;
}
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
@@ -567,18 +592,18 @@ DankModal {
buttonSize: 36
anchors.verticalCenter: parent.verticalCenter
onClicked: () => {
const r = Math.round(root.currentColor.r * 255)
const g = Math.round(root.currentColor.g * 255)
const b = Math.round(root.currentColor.b * 255)
let rgbString
const r = Math.round(root.currentColor.r * 255);
const g = Math.round(root.currentColor.g * 255);
const b = Math.round(root.currentColor.b * 255);
let rgbString;
if (root.alpha < 1) {
const a = Math.round(root.alpha * 255)
rgbString = `rgba(${r}, ${g}, ${b}, ${a})`
const a = Math.round(root.alpha * 255);
rgbString = `rgba(${r}, ${g}, ${b}, ${a})`;
} else {
rgbString = `rgb(${r}, ${g}, ${b})`
rgbString = `rgb(${r}, ${g}, ${b})`;
}
Quickshell.execDetached(["sh", "-c", `echo -n "${rgbString}" | wl-copy`])
ToastService.showInfo(`${rgbString} copied`)
Quickshell.execDetached(["sh", "-c", `echo -n "${rgbString}" | wl-copy`]);
ToastService.showInfo(`${rgbString} copied`);
}
}
}
@@ -610,14 +635,14 @@ DankModal {
StyledText {
anchors.centerIn: parent
text: {
const h = Math.round(root.hue * 360)
const s = Math.round(root.saturation * 100)
const v = Math.round(root.value * 100)
const h = Math.round(root.hue * 360);
const s = Math.round(root.saturation * 100);
const v = Math.round(root.value * 100);
if (root.alpha < 1) {
const a = Math.round(root.alpha * 100)
return `${h}°, ${s}%, ${v}%, ${a}%`
const a = Math.round(root.alpha * 100);
return `${h}°, ${s}%, ${v}%, ${a}%`;
}
return `${h}°, ${s}%, ${v}%`
return `${h}°, ${s}%, ${v}%`;
}
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceText
@@ -631,18 +656,18 @@ DankModal {
buttonSize: 36
anchors.verticalCenter: parent.verticalCenter
onClicked: () => {
const h = Math.round(root.hue * 360)
const s = Math.round(root.saturation * 100)
const v = Math.round(root.value * 100)
let hsvString
const h = Math.round(root.hue * 360);
const s = Math.round(root.saturation * 100);
const v = Math.round(root.value * 100);
let hsvString;
if (root.alpha < 1) {
const a = Math.round(root.alpha * 100)
hsvString = `${h}, ${s}, ${v}, ${a}`
const a = Math.round(root.alpha * 100);
hsvString = `${h}, ${s}, ${v}, ${a}`;
} else {
hsvString = `${h}, ${s}, ${v}`
hsvString = `${h}, ${s}, ${v}`;
}
Quickshell.execDetached(["sh", "-c", `echo -n "${hsvString}" | wl-copy`])
ToastService.showInfo(`HSV ${hsvString} copied`)
Quickshell.execDetached(["sh", "-c", `echo -n "${hsvString}" | wl-copy`]);
ToastService.showInfo(`HSV ${hsvString} copied`);
}
}
}
@@ -658,9 +683,9 @@ DankModal {
textColor: Theme.background
anchors.right: parent.right
onClicked: {
SessionData.addRecentColor(root.currentColor)
root.colorSelected(root.currentColor)
root.hide()
SessionData.addRecentColor(root.currentColor);
root.colorSelected(root.currentColor);
root.hide();
}
}
}

View File

@@ -1,7 +1,6 @@
import QtQuick
import qs.Common
import qs.Modals.Common
import qs.Services
import qs.Widgets
DankModal {
@@ -15,8 +14,8 @@ DankModal {
shouldBeVisible: false
allowStacking: true
width: 420
height: contentLoader.item ? contentLoader.item.implicitHeight + Theme.spacingM * 2 : 200
modalWidth: 420
modalHeight: contentLoader.item ? contentLoader.item.implicitHeight + Theme.spacingM * 2 : 200
Timer {
id: countdownTimer
@@ -24,20 +23,20 @@ DankModal {
repeat: true
running: root.shouldBeVisible
onTriggered: {
countdown--
countdown--;
if (countdown <= 0) {
revert()
revert();
}
}
}
onOpened: {
countdown = 15
countdownTimer.start()
countdown = 15;
countdownTimer.start();
}
onClosed: {
countdownTimer.stop()
countdownTimer.stop();
}
onBackgroundClicked: revert
@@ -51,13 +50,13 @@ DankModal {
implicitHeight: mainColumn.implicitHeight
Keys.onEscapePressed: event => {
revert()
event.accepted = true
revert();
event.accepted = true;
}
Keys.onReturnPressed: event => {
confirm()
event.accepted = true
confirm();
event.accepted = true;
}
Column {
@@ -235,12 +234,12 @@ DankModal {
}
function confirm() {
displaysTab.confirmChanges()
close()
displaysTab.confirmChanges();
close();
}
function revert() {
displaysTab.revertChanges()
close()
displaysTab.revertChanges();
close();
}
}

View File

@@ -1,5 +1,4 @@
import QtQuick
import QtQuick.Controls
import qs.Common
import qs.Modals.Common
import qs.Services
@@ -10,34 +9,36 @@ DankModal {
layerNamespace: "dms:network-info"
keepPopoutsOpen: true
property bool networkInfoModalVisible: false
property string networkSSID: ""
property var networkData: null
function showNetworkInfo(ssid, data) {
networkSSID = ssid
networkData = data
networkInfoModalVisible = true
open()
NetworkService.fetchNetworkInfo(ssid)
networkSSID = ssid;
networkData = data;
networkInfoModalVisible = true;
open();
NetworkService.fetchNetworkInfo(ssid);
}
function hideDialog() {
networkInfoModalVisible = false
close()
networkSSID = ""
networkData = null
networkInfoModalVisible = false;
close();
networkSSID = "";
networkData = null;
}
visible: networkInfoModalVisible
width: 600
height: 500
modalWidth: 600
modalHeight: 500
enableShadow: true
onBackgroundClicked: hideDialog()
onVisibleChanged: {
if (!visible) {
networkSSID = ""
networkData = null
networkSSID = "";
networkData = null;
}
}
@@ -71,7 +72,6 @@ DankModal {
width: parent.width
elide: Text.ElideRight
}
}
DankActionButton {
@@ -80,7 +80,6 @@ DankModal {
iconColor: Theme.surfaceText
onClicked: root.hideDialog()
}
}
Rectangle {
@@ -109,7 +108,6 @@ DankModal {
wrapMode: Text.WordWrap
}
}
}
Item {
@@ -148,17 +146,10 @@ DankModal {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
}
}
}
}

View File

@@ -1,5 +1,4 @@
import QtQuick
import QtQuick.Controls
import qs.Common
import qs.Modals.Common
import qs.Services
@@ -10,34 +9,36 @@ DankModal {
layerNamespace: "dms:network-info-wired"
keepPopoutsOpen: true
property bool networkWiredInfoModalVisible: false
property string networkID: ""
property var networkData: null
function showNetworkInfo(id, data) {
networkID = id
networkData = data
networkWiredInfoModalVisible = true
open()
NetworkService.fetchWiredNetworkInfo(data.uuid)
networkID = id;
networkData = data;
networkWiredInfoModalVisible = true;
open();
NetworkService.fetchWiredNetworkInfo(data.uuid);
}
function hideDialog() {
networkWiredInfoModalVisible = false
close()
networkID = ""
networkData = null
networkWiredInfoModalVisible = false;
close();
networkID = "";
networkData = null;
}
visible: networkWiredInfoModalVisible
width: 600
height: 500
modalWidth: 600
modalHeight: 500
enableShadow: true
onBackgroundClicked: hideDialog()
onVisibleChanged: {
if (!visible) {
networkID = ""
networkData = null
networkID = "";
networkData = null;
}
}
@@ -71,7 +72,6 @@ DankModal {
width: parent.width
elide: Text.ElideRight
}
}
DankActionButton {
@@ -80,7 +80,6 @@ DankModal {
iconColor: Theme.surfaceText
onClicked: root.hideDialog()
}
}
Rectangle {
@@ -109,7 +108,6 @@ DankModal {
wrapMode: Text.WordWrap
}
}
}
Item {
@@ -148,17 +146,10 @@ DankModal {
duration: Theme.shortDuration
easing.type: Theme.standardEasing
}
}
}
}
}
}
}
}

View File

@@ -1,12 +1,10 @@
import QtQuick
import Quickshell
import Quickshell.Hyprland
import Quickshell.Io
import qs.Common
import qs.Modals.Common
import qs.Modules.Notifications.Center
import qs.Services
import qs.Widgets
DankModal {
id: notificationModal
@@ -22,58 +20,58 @@ DankModal {
property var notificationListRef: null
function show() {
notificationModalOpen = true
NotificationService.onOverlayOpen()
open()
modalKeyboardController.reset()
notificationModalOpen = true;
NotificationService.onOverlayOpen();
open();
modalKeyboardController.reset();
if (modalKeyboardController && notificationListRef) {
modalKeyboardController.listView = notificationListRef
modalKeyboardController.rebuildFlatNavigation()
modalKeyboardController.listView = notificationListRef;
modalKeyboardController.rebuildFlatNavigation();
Qt.callLater(() => {
modalKeyboardController.keyboardNavigationActive = true
modalKeyboardController.selectedFlatIndex = 0
modalKeyboardController.updateSelectedIdFromIndex()
modalKeyboardController.keyboardNavigationActive = true;
modalKeyboardController.selectedFlatIndex = 0;
modalKeyboardController.updateSelectedIdFromIndex();
if (notificationListRef) {
notificationListRef.keyboardActive = true
notificationListRef.currentIndex = 0
notificationListRef.keyboardActive = true;
notificationListRef.currentIndex = 0;
}
modalKeyboardController.selectionVersion++
modalKeyboardController.ensureVisible()
})
modalKeyboardController.selectionVersion++;
modalKeyboardController.ensureVisible();
});
}
}
function hide() {
notificationModalOpen = false
NotificationService.onOverlayClose()
close()
modalKeyboardController.reset()
notificationModalOpen = false;
NotificationService.onOverlayClose();
close();
modalKeyboardController.reset();
}
function toggle() {
if (shouldBeVisible) {
hide()
hide();
} else {
show()
show();
}
}
width: 500
height: 700
modalWidth: 500
modalHeight: 700
visible: false
onBackgroundClicked: hide()
onOpened: () => {
Qt.callLater(() => modalFocusScope.forceActiveFocus());
}
onShouldBeVisibleChanged: (shouldBeVisible) => {
onShouldBeVisibleChanged: shouldBeVisible => {
if (!shouldBeVisible) {
notificationModalOpen = false
modalKeyboardController.reset()
NotificationService.onOverlayClose()
notificationModalOpen = false;
modalKeyboardController.reset();
NotificationService.onOverlayClose();
}
}
modalFocusScope.Keys.onPressed: (event) => modalKeyboardController.handleKey(event)
modalFocusScope.Keys.onPressed: event => modalKeyboardController.handleKey(event)
NotificationKeyboardController {
id: modalKeyboardController
@@ -132,14 +130,13 @@ DankModal {
height: parent.height - y
keyboardController: modalKeyboardController
Component.onCompleted: {
notificationModal.notificationListRef = notificationList
notificationModal.notificationListRef = notificationList;
if (modalKeyboardController) {
modalKeyboardController.listView = notificationList
modalKeyboardController.rebuildFlatNavigation()
modalKeyboardController.listView = notificationList;
modalKeyboardController.rebuildFlatNavigation();
}
}
}
}
NotificationKeyboardHints {
@@ -151,9 +148,6 @@ DankModal {
anchors.margins: Theme.spacingL
showHints: modalKeyboardController.showKeyboardHints
}
}
}
}

View File

@@ -1,5 +1,4 @@
import QtQuick
import Quickshell
import Quickshell.Hyprland
import qs.Common
import qs.Modals.Common
@@ -22,27 +21,27 @@ DankModal {
property real minHeight: 240
function show() {
passwordInput = ""
isLoading = false
open()
passwordInput = "";
isLoading = false;
open();
Qt.callLater(() => {
if (contentLoader.item && contentLoader.item.passwordField) {
contentLoader.item.passwordField.forceActiveFocus()
contentLoader.item.passwordField.forceActiveFocus();
}
})
});
}
shouldBeVisible: false
width: 420
height: Math.max(minHeight, contentLoader.item ? contentLoader.item.implicitHeight + Theme.spacingM * 2 : 240)
modalWidth: 420
modalHeight: Math.max(minHeight, contentLoader.item ? contentLoader.item.implicitHeight + Theme.spacingM * 2 : 240)
Connections {
target: contentLoader.item
function onImplicitHeightChanged() {
if (shouldBeVisible && contentLoader.item) {
const newHeight = contentLoader.item.implicitHeight + Theme.spacingM * 2
const newHeight = contentLoader.item.implicitHeight + Theme.spacingM * 2;
if (newHeight > minHeight) {
minHeight = newHeight
minHeight = newHeight;
}
}
}
@@ -51,19 +50,19 @@ DankModal {
onOpened: {
Qt.callLater(() => {
if (contentLoader.item && contentLoader.item.passwordField) {
contentLoader.item.passwordField.forceActiveFocus()
contentLoader.item.passwordField.forceActiveFocus();
}
})
});
}
onClosed: {
passwordInput = ""
isLoading = false
onDialogClosed: {
passwordInput = "";
isLoading = false;
}
onBackgroundClicked: () => {
if (currentFlow && !isLoading) {
currentFlow.cancelAuthenticationRequest()
currentFlow.cancelAuthenticationRequest();
}
}
@@ -72,12 +71,12 @@ DankModal {
enabled: PolkitService.polkitAvailable
function onAuthenticationRequestStarted() {
show()
show();
}
function onIsActiveChanged() {
if (!(PolkitService.agent?.isActive ?? false)) {
close()
close();
}
}
}
@@ -88,24 +87,24 @@ DankModal {
function onIsResponseRequiredChanged() {
if (currentFlow.isResponseRequired) {
isLoading = false
passwordInput = ""
isLoading = false;
passwordInput = "";
if (contentLoader.item && contentLoader.item.passwordField) {
contentLoader.item.passwordField.forceActiveFocus()
contentLoader.item.passwordField.forceActiveFocus();
}
}
}
function onAuthenticationSucceeded() {
close()
close();
}
function onAuthenticationFailed() {
isLoading = false
isLoading = false;
}
function onAuthenticationRequestCancelled() {
close()
close();
}
}
@@ -121,9 +120,9 @@ DankModal {
Keys.onEscapePressed: event => {
if (currentFlow && !isLoading) {
currentFlow.cancelAuthenticationRequest()
currentFlow.cancelAuthenticationRequest();
}
event.accepted = true
event.accepted = true;
}
Row {
@@ -178,7 +177,7 @@ DankModal {
opacity: enabled ? 1 : 0.5
onClicked: () => {
if (currentFlow) {
currentFlow.cancelAuthenticationRequest()
currentFlow.cancelAuthenticationRequest();
}
}
}
@@ -215,7 +214,7 @@ DankModal {
anchors.fill: parent
enabled: !isLoading
onClicked: () => {
passwordField.forceActiveFocus()
passwordField.forceActiveFocus();
}
}
@@ -231,13 +230,13 @@ DankModal {
backgroundColor: "transparent"
enabled: !isLoading
onTextEdited: () => {
passwordInput = text
passwordInput = text;
}
onAccepted: () => {
if (passwordInput.length > 0 && currentFlow && !isLoading) {
isLoading = true
currentFlow.submit(passwordInput)
passwordInput = ""
isLoading = true;
currentFlow.submit(passwordInput);
passwordInput = "";
}
}
}
@@ -310,7 +309,7 @@ DankModal {
enabled: parent.enabled
onClicked: () => {
if (currentFlow) {
currentFlow.cancelAuthenticationRequest()
currentFlow.cancelAuthenticationRequest();
}
}
}
@@ -343,9 +342,9 @@ DankModal {
enabled: parent.enabled
onClicked: () => {
if (currentFlow && !isLoading) {
isLoading = true
currentFlow.submit(passwordInput)
passwordInput = ""
isLoading = true;
currentFlow.submit(passwordInput);
passwordInput = "";
}
}
}

View File

@@ -29,64 +29,64 @@ DankModal {
signal lockRequested
function openCentered() {
parentBounds = Qt.rect(0, 0, 0, 0)
parentScreen = null
backgroundOpacity = 0.5
open()
parentBounds = Qt.rect(0, 0, 0, 0);
parentScreen = null;
backgroundOpacity = 0.5;
open();
}
function openFromControlCenter(bounds, targetScreen) {
parentBounds = bounds
parentScreen = targetScreen
backgroundOpacity = 0
keepPopoutsOpen = true
open()
keepPopoutsOpen = false
parentBounds = bounds;
parentScreen = targetScreen;
backgroundOpacity = 0;
keepPopoutsOpen = true;
open();
keepPopoutsOpen = false;
}
function updateVisibleActions() {
const allActions = SettingsData.powerMenuActions || ["reboot", "logout", "poweroff", "lock", "suspend", "restart"]
const allActions = SettingsData.powerMenuActions || ["reboot", "logout", "poweroff", "lock", "suspend", "restart"];
visibleActions = allActions.filter(action => {
if (action === "hibernate" && !SessionService.hibernateSupported)
return false
return true
})
return false;
return true;
});
if (!SettingsData.powerMenuGridLayout) return
const count = visibleActions.length
if (!SettingsData.powerMenuGridLayout)
return;
const count = visibleActions.length;
if (count === 0) {
gridColumns = 1
gridRows = 1
return
gridColumns = 1;
gridRows = 1;
return;
}
if (count <= 3) {
gridColumns = 1
gridRows = count
return
gridColumns = 1;
gridRows = count;
return;
}
if (count === 4) {
gridColumns = 2
gridRows = 2
return
gridColumns = 2;
gridRows = 2;
return;
}
gridColumns = 3
gridRows = Math.ceil(count / 3)
gridColumns = 3;
gridRows = Math.ceil(count / 3);
}
function getDefaultActionIndex() {
const defaultAction = SettingsData.powerMenuDefaultAction || "logout"
const index = visibleActions.indexOf(defaultAction)
return index >= 0 ? index : 0
const defaultAction = SettingsData.powerMenuDefaultAction || "logout";
const index = visibleActions.indexOf(defaultAction);
return index >= 0 ? index : 0;
}
function getActionAtIndex(index) {
if (index < 0 || index >= visibleActions.length)
return ""
return visibleActions[index]
return "";
return visibleActions[index];
}
function getActionData(action) {
@@ -96,64 +96,64 @@ DankModal {
"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 "lock":
return {
"icon": "lock",
"label": I18n.tr("Lock"),
"key": "L"
}
};
case "suspend":
return {
"icon": "bedtime",
"label": I18n.tr("Suspend"),
"key": "S"
}
};
case "hibernate":
return {
"icon": "ac_unit",
"label": I18n.tr("Hibernate"),
"key": "H"
}
};
case "restart":
return {
"icon": "refresh",
"label": I18n.tr("Restart DMS"),
"key": "D"
}
};
default:
return {
"icon": "help",
"label": action,
"key": "?"
}
};
}
}
function selectOption(action) {
if (action === "lock") {
close()
lockRequested()
return
close();
lockRequested();
return;
}
if (action === "restart") {
close()
Quickshell.execDetached(["dms", "restart"])
return
close();
Quickshell.execDetached(["dms", "restart"]);
return;
}
close()
close();
const actions = {
"logout": {
"title": I18n.tr("Log Out"),
@@ -175,60 +175,58 @@ DankModal {
"title": I18n.tr("Power Off"),
"message": I18n.tr("Are you sure you want to power off the system?")
}
}
const selected = actions[action]
};
const selected = actions[action];
if (selected) {
root.powerActionRequested(action, selected.title, selected.message)
root.powerActionRequested(action, selected.title, selected.message);
}
}
shouldBeVisible: false
width: SettingsData.powerMenuGridLayout
? Math.min(550, gridColumns * 180 + Theme.spacingS * (gridColumns - 1) + Theme.spacingL * 2)
: 400
height: contentLoader.item ? contentLoader.item.implicitHeight : 300
modalWidth: SettingsData.powerMenuGridLayout ? Math.min(550, gridColumns * 180 + Theme.spacingS * (gridColumns - 1) + Theme.spacingL * 2) : 400
modalHeight: contentLoader.item ? contentLoader.item.implicitHeight : 300
enableShadow: true
screen: parentScreen
targetScreen: parentScreen
positioning: parentBounds.width > 0 ? "custom" : "center"
customPosition: {
if (parentBounds.width > 0) {
const effectiveBarThickness = Math.max(26 + (SettingsData.barConfigs[0]?.innerPadding ?? 4) * 0.6 + (SettingsData.barConfigs[0]?.innerPadding ?? 4) + 4, Theme.barHeight - 4 - (8 - (SettingsData.barConfigs[0]?.innerPadding ?? 4)))
const barExclusionZone = effectiveBarThickness + (SettingsData.barConfigs[0]?.spacing ?? 4) + (SettingsData.barConfigs[0]?.bottomGap ?? 0)
const screenW = parentScreen?.width ?? 1920
const screenH = parentScreen?.height ?? 1080
const margin = Theme.spacingL
const effectiveBarThickness = Math.max(26 + (SettingsData.barConfigs[0]?.innerPadding ?? 4) * 0.6 + (SettingsData.barConfigs[0]?.innerPadding ?? 4) + 4, Theme.barHeight - 4 - (8 - (SettingsData.barConfigs[0]?.innerPadding ?? 4)));
const barExclusionZone = effectiveBarThickness + (SettingsData.barConfigs[0]?.spacing ?? 4) + (SettingsData.barConfigs[0]?.bottomGap ?? 0);
const screenW = parentScreen?.width ?? 1920;
const screenH = parentScreen?.height ?? 1080;
const margin = Theme.spacingL;
let targetX = parentBounds.x + (parentBounds.width - width) / 2
let targetY = parentBounds.y + (parentBounds.height - height) / 2
let targetX = parentBounds.x + (parentBounds.width - modalWidth) / 2;
let targetY = parentBounds.y + (parentBounds.height - modalHeight) / 2;
const minY = (SettingsData.barConfigs[0]?.position ?? SettingsData.Position.Top) === SettingsData.Position.Top ? barExclusionZone + margin : margin
const maxY = (SettingsData.barConfigs[0]?.position ?? SettingsData.Position.Top) === SettingsData.Position.Bottom ? screenH - height - barExclusionZone - margin : screenH - height - margin
const minY = (SettingsData.barConfigs[0]?.position ?? SettingsData.Position.Top) === SettingsData.Position.Top ? barExclusionZone + margin : margin;
const maxY = (SettingsData.barConfigs[0]?.position ?? SettingsData.Position.Top) === SettingsData.Position.Bottom ? screenH - modalHeight - barExclusionZone - margin : screenH - modalHeight - margin;
targetY = Math.max(minY, Math.min(maxY, targetY))
targetY = Math.max(minY, Math.min(maxY, targetY));
return Qt.point(targetX, targetY)
return Qt.point(targetX, targetY);
}
return Qt.point(0, 0)
return Qt.point(0, 0);
}
onBackgroundClicked: () => close()
onOpened: () => {
updateVisibleActions()
const defaultIndex = getDefaultActionIndex()
updateVisibleActions();
const defaultIndex = getDefaultActionIndex();
if (SettingsData.powerMenuGridLayout) {
selectedRow = Math.floor(defaultIndex / gridColumns)
selectedCol = defaultIndex % gridColumns
selectedIndex = defaultIndex
selectedRow = Math.floor(defaultIndex / gridColumns);
selectedCol = defaultIndex % gridColumns;
selectedIndex = defaultIndex;
} else {
selectedIndex = defaultIndex
selectedIndex = defaultIndex;
}
Qt.callLater(() => modalFocusScope.forceActiveFocus())
Qt.callLater(() => modalFocusScope.forceActiveFocus());
}
Component.onCompleted: updateVisibleActions()
modalFocusScope.Keys.onPressed: event => {
if (SettingsData.powerMenuGridLayout) {
handleGridNavigation(event)
handleGridNavigation(event);
} else {
handleListNavigation(event)
handleListNavigation(event);
}
}
@@ -236,166 +234,164 @@ DankModal {
switch (event.key) {
case Qt.Key_Up:
case Qt.Key_Backtab:
selectedIndex = (selectedIndex - 1 + visibleActions.length) % visibleActions.length
event.accepted = true
break
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
selectedIndex = (selectedIndex + 1) % visibleActions.length;
event.accepted = true;
break;
case Qt.Key_Return:
case Qt.Key_Enter:
selectOption(getActionAtIndex(selectedIndex))
event.accepted = true
break
selectOption(getActionAtIndex(selectedIndex));
event.accepted = true;
break;
case Qt.Key_N:
if (event.modifiers & Qt.ControlModifier) {
selectedIndex = (selectedIndex + 1) % visibleActions.length
event.accepted = true
selectedIndex = (selectedIndex + 1) % visibleActions.length;
event.accepted = true;
}
break
break;
case Qt.Key_P:
if (!(event.modifiers & Qt.ControlModifier)) {
selectOption("poweroff")
event.accepted = true
selectOption("poweroff");
event.accepted = true;
} else {
selectedIndex = (selectedIndex - 1 + visibleActions.length) % visibleActions.length
event.accepted = true
selectedIndex = (selectedIndex - 1 + visibleActions.length) % visibleActions.length;
event.accepted = true;
}
break
break;
case Qt.Key_J:
if (event.modifiers & Qt.ControlModifier) {
selectedIndex = (selectedIndex + 1) % visibleActions.length
event.accepted = true
selectedIndex = (selectedIndex + 1) % visibleActions.length;
event.accepted = true;
}
break
break;
case Qt.Key_K:
if (event.modifiers & Qt.ControlModifier) {
selectedIndex = (selectedIndex - 1 + visibleActions.length) % visibleActions.length
event.accepted = true
selectedIndex = (selectedIndex - 1 + visibleActions.length) % visibleActions.length;
event.accepted = true;
}
break
break;
case Qt.Key_R:
selectOption("reboot")
event.accepted = true
break
selectOption("reboot");
event.accepted = true;
break;
case Qt.Key_X:
selectOption("logout")
event.accepted = true
break
selectOption("logout");
event.accepted = true;
break;
case Qt.Key_L:
selectOption("lock")
event.accepted = true
break
selectOption("lock");
event.accepted = true;
break;
case Qt.Key_S:
selectOption("suspend")
event.accepted = true
break
selectOption("suspend");
event.accepted = true;
break;
case Qt.Key_H:
selectOption("hibernate")
event.accepted = true
break
selectOption("hibernate");
event.accepted = true;
break;
case Qt.Key_D:
selectOption("restart")
event.accepted = true
break
selectOption("restart");
event.accepted = true;
break;
}
}
function handleGridNavigation(event) {
switch (event.key) {
case Qt.Key_Left:
selectedCol = (selectedCol - 1 + gridColumns) % gridColumns
selectedIndex = selectedRow * gridColumns + selectedCol
event.accepted = true
break
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
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
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
selectedRow = (selectedRow + 1) % gridRows;
selectedIndex = selectedRow * gridColumns + selectedCol;
event.accepted = true;
break;
case Qt.Key_Return:
case Qt.Key_Enter:
selectOption(getActionAtIndex(selectedIndex))
event.accepted = true
break
selectOption(getActionAtIndex(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
selectedCol = (selectedCol + 1) % gridColumns;
selectedIndex = selectedRow * gridColumns + selectedCol;
event.accepted = true;
}
break
break;
case Qt.Key_P:
if (!(event.modifiers & Qt.ControlModifier)) {
selectOption("poweroff")
event.accepted = true
selectOption("poweroff");
event.accepted = true;
} else {
selectedCol = (selectedCol - 1 + gridColumns) % gridColumns
selectedIndex = selectedRow * gridColumns + selectedCol
event.accepted = true
selectedCol = (selectedCol - 1 + gridColumns) % gridColumns;
selectedIndex = selectedRow * gridColumns + selectedCol;
event.accepted = true;
}
break
break;
case Qt.Key_J:
if (event.modifiers & Qt.ControlModifier) {
selectedRow = (selectedRow + 1) % gridRows
selectedIndex = selectedRow * gridColumns + selectedCol
event.accepted = true
selectedRow = (selectedRow + 1) % gridRows;
selectedIndex = selectedRow * gridColumns + selectedCol;
event.accepted = true;
}
break
break;
case Qt.Key_K:
if (event.modifiers & Qt.ControlModifier) {
selectedRow = (selectedRow - 1 + gridRows) % gridRows
selectedIndex = selectedRow * gridColumns + selectedCol
event.accepted = true
selectedRow = (selectedRow - 1 + gridRows) % gridRows;
selectedIndex = selectedRow * gridColumns + selectedCol;
event.accepted = true;
}
break
break;
case Qt.Key_R:
selectOption("reboot")
event.accepted = true
break
selectOption("reboot");
event.accepted = true;
break;
case Qt.Key_X:
selectOption("logout")
event.accepted = true
break
selectOption("logout");
event.accepted = true;
break;
case Qt.Key_L:
selectOption("lock")
event.accepted = true
break
selectOption("lock");
event.accepted = true;
break;
case Qt.Key_S:
selectOption("suspend")
event.accepted = true
break
selectOption("suspend");
event.accepted = true;
break;
case Qt.Key_H:
selectOption("hibernate")
event.accepted = true
break
selectOption("hibernate");
event.accepted = true;
break;
case Qt.Key_D:
selectOption("restart")
event.accepted = true
break
selectOption("restart");
event.accepted = true;
break;
}
}
content: Component {
Item {
anchors.fill: parent
implicitHeight: SettingsData.powerMenuGridLayout
? buttonGrid.implicitHeight + Theme.spacingL * 2
: buttonColumn.implicitHeight + Theme.spacingL * 2
implicitHeight: SettingsData.powerMenuGridLayout ? buttonGrid.implicitHeight + Theme.spacingL * 2 : buttonColumn.implicitHeight + Theme.spacingL * 2
Grid {
id: buttonGrid
@@ -416,15 +412,15 @@ DankModal {
readonly property bool isSelected: root.selectedIndex === index
readonly property bool showWarning: modelData === "reboot" || modelData === "poweroff"
width: (root.width - Theme.spacingL * 2 - Theme.spacingS * (root.gridColumns - 1)) / root.gridColumns
width: (root.modalWidth - Theme.spacingL * 2 - 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)
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)
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
@@ -438,9 +434,9 @@ DankModal {
size: Theme.iconSize + 8
color: {
if (parent.parent.showWarning && mouseArea.containsMouse) {
return parent.parent.modelData === "poweroff" ? Theme.error : Theme.warning
return parent.parent.modelData === "poweroff" ? Theme.error : Theme.warning;
}
return Theme.surfaceText
return Theme.surfaceText;
}
anchors.horizontalCenter: parent.horizontalCenter
}
@@ -450,9 +446,9 @@ DankModal {
font.pixelSize: Theme.fontSizeMedium
color: {
if (parent.parent.showWarning && mouseArea.containsMouse) {
return parent.parent.modelData === "poweroff" ? Theme.error : Theme.warning
return parent.parent.modelData === "poweroff" ? Theme.error : Theme.warning;
}
return Theme.surfaceText
return Theme.surfaceText;
}
font.weight: Font.Medium
anchors.horizontalCenter: parent.horizontalCenter
@@ -481,9 +477,9 @@ DankModal {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.selectedRow = Math.floor(index / root.gridColumns)
root.selectedCol = index % root.gridColumns
root.selectOption(modelData)
root.selectedRow = Math.floor(index / root.gridColumns);
root.selectedCol = index % root.gridColumns;
root.selectOption(modelData);
}
}
}
@@ -518,10 +514,10 @@ DankModal {
radius: Theme.cornerRadius
color: {
if (isSelected)
return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12)
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)
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
@@ -541,9 +537,9 @@ DankModal {
size: Theme.iconSize + 4
color: {
if (parent.parent.showWarning && listMouseArea.containsMouse) {
return parent.parent.modelData === "poweroff" ? Theme.error : Theme.warning
return parent.parent.modelData === "poweroff" ? Theme.error : Theme.warning;
}
return Theme.surfaceText
return Theme.surfaceText;
}
anchors.verticalCenter: parent.verticalCenter
}
@@ -553,9 +549,9 @@ DankModal {
font.pixelSize: Theme.fontSizeMedium
color: {
if (parent.parent.showWarning && listMouseArea.containsMouse) {
return parent.parent.modelData === "poweroff" ? Theme.error : Theme.warning
return parent.parent.modelData === "poweroff" ? Theme.error : Theme.warning;
}
return Theme.surfaceText
return Theme.surfaceText;
}
font.weight: Font.Medium
anchors.verticalCenter: parent.verticalCenter
@@ -588,8 +584,8 @@ DankModal {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: {
root.selectedIndex = index
root.selectOption(modelData)
root.selectedIndex = index;
root.selectOption(modelData);
}
}
}

View File

@@ -28,7 +28,6 @@ DankModal {
if (processContextMenu.visible) {
processContextMenu.close();
}
}
function toggle() {
@@ -43,9 +42,8 @@ DankModal {
}
}
width: 900
height: 680
visible: false
modalWidth: 900
modalHeight: 680
backgroundColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
cornerRadius: Theme.cornerRadius
enableShadow: true
@@ -59,23 +57,18 @@ DankModal {
ProcessesTab {
contextMenu: processContextMenu
}
}
Component {
id: performanceTabComponent
PerformanceTab {
}
PerformanceTab {}
}
Component {
id: systemTabComponent
SystemTab {
}
SystemTab {}
}
ProcessContextMenu {
@@ -86,7 +79,7 @@ DankModal {
Item {
anchors.fill: parent
focus: true
Keys.onPressed: (event) => {
Keys.onPressed: event => {
if (event.key === Qt.Key_Escape) {
processListModal.hide();
event.accepted = true;
@@ -140,9 +133,7 @@ DankModal {
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
}
}
}
ColumnLayout {
@@ -177,7 +168,6 @@ DankModal {
}
Layout.alignment: Qt.AlignVCenter
}
}
Rectangle {
@@ -222,9 +212,7 @@ DankModal {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
StyledText {
@@ -239,11 +227,8 @@ DankModal {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
}
MouseArea {
@@ -261,22 +246,16 @@ DankModal {
ColorAnimation {
duration: Theme.shortDuration
}
}
Behavior on border.color {
ColorAnimation {
duration: Theme.shortDuration
}
}
}
}
}
}
Rectangle {
@@ -292,7 +271,7 @@ DankModal {
anchors.fill: parent
anchors.margins: Theme.spacingS
active: processListModal.visible && currentTab === 0
active: processListModal.shouldBeVisible && currentTab === 0
visible: currentTab === 0
opacity: currentTab === 0 ? 1 : 0
sourceComponent: processesTabComponent
@@ -302,9 +281,7 @@ DankModal {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
Loader {
@@ -312,7 +289,7 @@ DankModal {
anchors.fill: parent
anchors.margins: Theme.spacingS
active: processListModal.visible && currentTab === 1
active: processListModal.shouldBeVisible && currentTab === 1
visible: currentTab === 1
opacity: currentTab === 1 ? 1 : 0
sourceComponent: performanceTabComponent
@@ -322,9 +299,7 @@ DankModal {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
Loader {
@@ -332,7 +307,7 @@ DankModal {
anchors.fill: parent
anchors.margins: Theme.spacingS
active: processListModal.visible && currentTab === 2
active: processListModal.shouldBeVisible && currentTab === 2
visible: currentTab === 2
opacity: currentTab === 2 ? 1 : 0
sourceComponent: systemTabComponent
@@ -342,17 +317,10 @@ DankModal {
duration: Theme.mediumDuration
easing.type: Theme.emphasizedEasing
}
}
}
}
}
}
}
}

View File

@@ -1,14 +1,9 @@
import QtQuick
import QtQuick.Controls
import Quickshell
import Quickshell.Hyprland
import Quickshell.Io
import Quickshell.Widgets
import qs.Common
import qs.Modals.Common
import qs.Modules.AppDrawer
import qs.Services
import qs.Widgets
DankModal {
id: spotlightModal
@@ -25,73 +20,73 @@ DankModal {
property bool openedFromOverview: false
function show() {
openedFromOverview = false
spotlightOpen = true
open()
openedFromOverview = false;
spotlightOpen = true;
open();
Qt.callLater(() => {
if (spotlightContent && spotlightContent.searchField) {
spotlightContent.searchField.forceActiveFocus()
spotlightContent.searchField.forceActiveFocus();
}
})
});
}
function showWithQuery(query) {
if (spotlightContent) {
if (spotlightContent.appLauncher) {
spotlightContent.appLauncher.searchQuery = query
spotlightContent.appLauncher.searchQuery = query;
}
if (spotlightContent.searchField) {
spotlightContent.searchField.text = query
spotlightContent.searchField.text = query;
}
}
spotlightOpen = true
open()
spotlightOpen = true;
open();
Qt.callLater(() => {
if (spotlightContent && spotlightContent.searchField) {
spotlightContent.searchField.forceActiveFocus()
spotlightContent.searchField.forceActiveFocus();
}
})
});
}
function hide() {
openedFromOverview = false
spotlightOpen = false
close()
openedFromOverview = false;
spotlightOpen = false;
close();
}
onDialogClosed: {
if (spotlightContent) {
if (spotlightContent.appLauncher) {
spotlightContent.appLauncher.searchQuery = ""
spotlightContent.appLauncher.selectedIndex = 0
spotlightContent.appLauncher.setCategory(I18n.tr("All"))
spotlightContent.appLauncher.searchQuery = "";
spotlightContent.appLauncher.selectedIndex = 0;
spotlightContent.appLauncher.setCategory(I18n.tr("All"));
}
if (spotlightContent.fileSearchController) {
spotlightContent.fileSearchController.reset()
spotlightContent.fileSearchController.reset();
}
if (spotlightContent.resetScroll) {
spotlightContent.resetScroll()
spotlightContent.resetScroll();
}
if (spotlightContent.searchField) {
spotlightContent.searchField.text = ""
spotlightContent.searchField.text = "";
}
}
}
function toggle() {
if (spotlightOpen) {
hide()
hide();
} else {
show()
show();
}
}
shouldBeVisible: spotlightOpen
width: 500
height: 600
modalWidth: 500
modalHeight: 600
backgroundColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
cornerRadius: Theme.cornerRadius
borderColor: Theme.outlineMedium
@@ -100,24 +95,24 @@ DankModal {
keepContentLoaded: true
onVisibleChanged: () => {
if (visible && !spotlightOpen) {
show()
show();
}
if (visible && spotlightContent) {
Qt.callLater(() => {
if (spotlightContent.searchField) {
spotlightContent.searchField.forceActiveFocus()
spotlightContent.searchField.forceActiveFocus();
}
})
});
}
}
onBackgroundClicked: () => {
return hide()
return hide();
}
Connections {
function onCloseAllModalsExcept(excludedModal) {
if (excludedModal !== spotlightModal && !allowStacking && spotlightOpen) {
spotlightOpen = false
spotlightOpen = false;
}
}
@@ -126,32 +121,32 @@ DankModal {
IpcHandler {
function open(): string {
spotlightModal.show()
return "SPOTLIGHT_OPEN_SUCCESS"
spotlightModal.show();
return "SPOTLIGHT_OPEN_SUCCESS";
}
function close(): string {
spotlightModal.hide()
return "SPOTLIGHT_CLOSE_SUCCESS"
spotlightModal.hide();
return "SPOTLIGHT_CLOSE_SUCCESS";
}
function toggle(): string {
spotlightModal.toggle()
return "SPOTLIGHT_TOGGLE_SUCCESS"
spotlightModal.toggle();
return "SPOTLIGHT_TOGGLE_SUCCESS";
}
function openQuery(query: string): string {
spotlightModal.showWithQuery(query)
return "SPOTLIGHT_OPEN_QUERY_SUCCESS"
spotlightModal.showWithQuery(query);
return "SPOTLIGHT_OPEN_QUERY_SUCCESS";
}
function toggleQuery(query: string): string {
if (spotlightModal.spotlightOpen) {
spotlightModal.hide()
spotlightModal.hide();
} else {
spotlightModal.showWithQuery(query)
spotlightModal.showWithQuery(query);
}
return "SPOTLIGHT_TOGGLE_QUERY_SUCCESS"
return "SPOTLIGHT_TOGGLE_QUERY_SUCCESS";
}
target: "spotlight"

View File

@@ -1,5 +1,4 @@
import QtQuick
import Quickshell
import Quickshell.Hyprland
import qs.Common
import qs.Modals.Common
@@ -37,111 +36,113 @@ DankModal {
property string connectionType: ""
function show(ssid) {
wifiPasswordSSID = ssid
wifiPasswordInput = ""
wifiUsernameInput = ""
wifiAnonymousIdentityInput = ""
wifiDomainInput = ""
isPromptMode = false
promptToken = ""
promptReason = ""
promptFields = []
promptSetting = ""
isVpnPrompt = false
connectionName = ""
vpnServiceType = ""
connectionType = ""
wifiPasswordSSID = ssid;
wifiPasswordInput = "";
wifiUsernameInput = "";
wifiAnonymousIdentityInput = "";
wifiDomainInput = "";
isPromptMode = false;
promptToken = "";
promptReason = "";
promptFields = [];
promptSetting = "";
isVpnPrompt = false;
connectionName = "";
vpnServiceType = "";
connectionType = "";
const network = NetworkService.wifiNetworks.find(n => n.ssid === ssid)
requiresEnterprise = network?.enterprise || false
const network = NetworkService.wifiNetworks.find(n => n.ssid === ssid);
requiresEnterprise = network?.enterprise || false;
open()
open();
Qt.callLater(() => {
if (contentLoader.item) {
if (requiresEnterprise && contentLoader.item.usernameInput) {
contentLoader.item.usernameInput.forceActiveFocus()
contentLoader.item.usernameInput.forceActiveFocus();
} else if (contentLoader.item.passwordInput) {
contentLoader.item.passwordInput.forceActiveFocus()
contentLoader.item.passwordInput.forceActiveFocus();
}
}
})
});
}
function showFromPrompt(token, ssid, setting, fields, hints, reason, connType, connName, vpnService) {
isPromptMode = true
promptToken = token
promptReason = reason
promptFields = fields || []
promptSetting = setting || "802-11-wireless-security"
connectionType = connType || "802-11-wireless"
connectionName = connName || ssid || ""
vpnServiceType = vpnService || ""
isPromptMode = true;
promptToken = token;
promptReason = reason;
promptFields = fields || [];
promptSetting = setting || "802-11-wireless-security";
connectionType = connType || "802-11-wireless";
connectionName = connName || ssid || "";
vpnServiceType = vpnService || "";
isVpnPrompt = (connectionType === "vpn" || connectionType === "wireguard")
wifiPasswordSSID = isVpnPrompt ? connectionName : ssid
isVpnPrompt = (connectionType === "vpn" || connectionType === "wireguard");
wifiPasswordSSID = isVpnPrompt ? connectionName : ssid;
requiresEnterprise = setting === "802-1x"
requiresEnterprise = setting === "802-1x";
if (reason === "wrong-password") {
wifiPasswordInput = ""
wifiUsernameInput = ""
wifiPasswordInput = "";
wifiUsernameInput = "";
} else {
wifiPasswordInput = ""
wifiUsernameInput = ""
wifiAnonymousIdentityInput = ""
wifiDomainInput = ""
wifiPasswordInput = "";
wifiUsernameInput = "";
wifiAnonymousIdentityInput = "";
wifiDomainInput = "";
}
open()
open();
Qt.callLater(() => {
if (contentLoader.item) {
if (reason === "wrong-password" && contentLoader.item.passwordInput) {
contentLoader.item.passwordInput.text = ""
contentLoader.item.passwordInput.forceActiveFocus()
contentLoader.item.passwordInput.text = "";
contentLoader.item.passwordInput.forceActiveFocus();
} else if (requiresEnterprise && contentLoader.item.usernameInput) {
contentLoader.item.usernameInput.forceActiveFocus()
contentLoader.item.usernameInput.forceActiveFocus();
} else if (contentLoader.item.passwordInput) {
contentLoader.item.passwordInput.forceActiveFocus()
contentLoader.item.passwordInput.forceActiveFocus();
}
}
})
});
}
shouldBeVisible: false
width: 420
height: {
if (requiresEnterprise) return 430
if (isVpnPrompt) return 260
return 230
modalWidth: 420
modalHeight: {
if (requiresEnterprise)
return 430;
if (isVpnPrompt)
return 260;
return 230;
}
onShouldBeVisibleChanged: () => {
if (!shouldBeVisible) {
wifiPasswordInput = ""
wifiUsernameInput = ""
wifiAnonymousIdentityInput = ""
wifiDomainInput = ""
wifiPasswordInput = "";
wifiUsernameInput = "";
wifiAnonymousIdentityInput = "";
wifiDomainInput = "";
}
}
onOpened: {
Qt.callLater(() => {
if (contentLoader.item) {
if (requiresEnterprise && contentLoader.item.usernameInput) {
contentLoader.item.usernameInput.forceActiveFocus()
contentLoader.item.usernameInput.forceActiveFocus();
} else if (contentLoader.item.passwordInput) {
contentLoader.item.passwordInput.forceActiveFocus()
contentLoader.item.passwordInput.forceActiveFocus();
}
}
})
});
}
onBackgroundClicked: () => {
if (isPromptMode) {
NetworkService.cancelCredentials(promptToken)
NetworkService.cancelCredentials(promptToken);
}
close()
wifiPasswordInput = ""
wifiUsernameInput = ""
wifiAnonymousIdentityInput = ""
wifiDomainInput = ""
close();
wifiPasswordInput = "";
wifiUsernameInput = "";
wifiAnonymousIdentityInput = "";
wifiDomainInput = "";
}
Connections {
@@ -149,10 +150,10 @@ DankModal {
function onPasswordDialogShouldReopenChanged() {
if (NetworkService.passwordDialogShouldReopen && NetworkService.connectingSSID !== "") {
wifiPasswordSSID = NetworkService.connectingSSID
wifiPasswordInput = ""
open()
NetworkService.passwordDialogShouldReopen = false
wifiPasswordSSID = NetworkService.connectingSSID;
wifiPasswordInput = "";
open();
NetworkService.passwordDialogShouldReopen = false;
}
}
}
@@ -168,14 +169,14 @@ DankModal {
focus: true
Keys.onEscapePressed: event => {
if (isPromptMode) {
NetworkService.cancelCredentials(promptToken)
NetworkService.cancelCredentials(promptToken);
}
close()
wifiPasswordInput = ""
wifiUsernameInput = ""
wifiAnonymousIdentityInput = ""
wifiDomainInput = ""
event.accepted = true
close();
wifiPasswordInput = "";
wifiUsernameInput = "";
wifiAnonymousIdentityInput = "";
wifiDomainInput = "";
event.accepted = true;
}
Column {
@@ -193,9 +194,9 @@ DankModal {
StyledText {
text: {
if (isVpnPrompt) {
return I18n.tr("Connect to VPN")
return I18n.tr("Connect to VPN");
}
return I18n.tr("Connect to Wi-Fi")
return I18n.tr("Connect to Wi-Fi");
}
font.pixelSize: Theme.fontSizeLarge
color: Theme.surfaceText
@@ -209,10 +210,10 @@ DankModal {
StyledText {
text: {
if (isVpnPrompt) {
return I18n.tr("Enter password for ") + wifiPasswordSSID
return I18n.tr("Enter password for ") + wifiPasswordSSID;
}
const prefix = requiresEnterprise ? I18n.tr("Enter credentials for ") : I18n.tr("Enter password for ")
return prefix + wifiPasswordSSID
const prefix = requiresEnterprise ? I18n.tr("Enter credentials for ") : I18n.tr("Enter password for ");
return prefix + wifiPasswordSSID;
}
font.pixelSize: Theme.fontSizeMedium
color: Theme.surfaceTextMedium
@@ -236,13 +237,13 @@ DankModal {
iconColor: Theme.surfaceText
onClicked: () => {
if (isPromptMode) {
NetworkService.cancelCredentials(promptToken)
NetworkService.cancelCredentials(promptToken);
}
close()
wifiPasswordInput = ""
wifiUsernameInput = ""
wifiAnonymousIdentityInput = ""
wifiDomainInput = ""
close();
wifiPasswordInput = "";
wifiUsernameInput = "";
wifiAnonymousIdentityInput = "";
wifiDomainInput = "";
}
}
}
@@ -259,7 +260,7 @@ DankModal {
MouseArea {
anchors.fill: parent
onClicked: () => {
usernameInput.forceActiveFocus()
usernameInput.forceActiveFocus();
}
}
@@ -274,11 +275,11 @@ DankModal {
backgroundColor: "transparent"
enabled: root.shouldBeVisible
onTextEdited: () => {
wifiUsernameInput = text
wifiUsernameInput = text;
}
onAccepted: () => {
if (passwordInput) {
passwordInput.forceActiveFocus()
passwordInput.forceActiveFocus();
}
}
}
@@ -295,7 +296,7 @@ DankModal {
MouseArea {
anchors.fill: parent
onClicked: () => {
passwordInput.forceActiveFocus()
passwordInput.forceActiveFocus();
}
}
@@ -312,42 +313,41 @@ DankModal {
focus: !requiresEnterprise
enabled: root.shouldBeVisible
onTextEdited: () => {
wifiPasswordInput = text
wifiPasswordInput = text;
}
onAccepted: () => {
if (isPromptMode) {
const secrets = {}
const secrets = {};
if (isVpnPrompt) {
if (passwordInput.text) secrets["password"] = passwordInput.text
if (passwordInput.text)
secrets["password"] = passwordInput.text;
} else if (promptSetting === "802-11-wireless-security") {
secrets["psk"] = passwordInput.text
secrets["psk"] = passwordInput.text;
} else if (promptSetting === "802-1x") {
if (usernameInput.text) secrets["identity"] = usernameInput.text
if (passwordInput.text) secrets["password"] = passwordInput.text
if (wifiAnonymousIdentityInput) secrets["anonymous-identity"] = wifiAnonymousIdentityInput
if (usernameInput.text)
secrets["identity"] = usernameInput.text;
if (passwordInput.text)
secrets["password"] = passwordInput.text;
if (wifiAnonymousIdentityInput)
secrets["anonymous-identity"] = wifiAnonymousIdentityInput;
}
NetworkService.submitCredentials(promptToken, secrets, savePasswordCheckbox.checked)
NetworkService.submitCredentials(promptToken, secrets, savePasswordCheckbox.checked);
} else {
const username = requiresEnterprise ? usernameInput.text : ""
NetworkService.connectToWifi(
wifiPasswordSSID,
passwordInput.text,
username,
wifiAnonymousIdentityInput,
wifiDomainInput
)
const username = requiresEnterprise ? usernameInput.text : "";
NetworkService.connectToWifi(wifiPasswordSSID, passwordInput.text, username, wifiAnonymousIdentityInput, wifiDomainInput);
}
close()
wifiPasswordInput = ""
wifiUsernameInput = ""
wifiAnonymousIdentityInput = ""
wifiDomainInput = ""
passwordInput.text = ""
if (requiresEnterprise) usernameInput.text = ""
close();
wifiPasswordInput = "";
wifiUsernameInput = "";
wifiAnonymousIdentityInput = "";
wifiDomainInput = "";
passwordInput.text = "";
if (requiresEnterprise)
usernameInput.text = "";
}
Component.onCompleted: () => {
if (root.shouldBeVisible && !requiresEnterprise)
focusDelayTimer.start()
focusDelayTimer.start();
}
Timer {
@@ -358,9 +358,9 @@ DankModal {
onTriggered: () => {
if (root.shouldBeVisible) {
if (requiresEnterprise && usernameInput) {
usernameInput.forceActiveFocus()
usernameInput.forceActiveFocus();
} else {
passwordInput.forceActiveFocus()
passwordInput.forceActiveFocus();
}
}
}
@@ -371,7 +371,7 @@ DankModal {
function onShouldBeVisibleChanged() {
if (root.shouldBeVisible)
focusDelayTimer.start()
focusDelayTimer.start();
}
}
}
@@ -389,7 +389,7 @@ DankModal {
MouseArea {
anchors.fill: parent
onClicked: () => {
anonInput.forceActiveFocus()
anonInput.forceActiveFocus();
}
}
@@ -404,7 +404,7 @@ DankModal {
backgroundColor: "transparent"
enabled: root.shouldBeVisible
onTextEdited: () => {
wifiAnonymousIdentityInput = text
wifiAnonymousIdentityInput = text;
}
}
}
@@ -421,7 +421,7 @@ DankModal {
MouseArea {
anchors.fill: parent
onClicked: () => {
domainMatchInput.forceActiveFocus()
domainMatchInput.forceActiveFocus();
}
}
@@ -436,7 +436,7 @@ DankModal {
backgroundColor: "transparent"
enabled: root.shouldBeVisible
onTextEdited: () => {
wifiDomainInput = text
wifiDomainInput = text;
}
}
}
@@ -473,7 +473,7 @@ DankModal {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: () => {
showPasswordCheckbox.checked = !showPasswordCheckbox.checked
showPasswordCheckbox.checked = !showPasswordCheckbox.checked;
}
}
}
@@ -515,7 +515,7 @@ DankModal {
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onClicked: () => {
savePasswordCheckbox.checked = !savePasswordCheckbox.checked
savePasswordCheckbox.checked = !savePasswordCheckbox.checked;
}
}
}
@@ -564,13 +564,13 @@ DankModal {
cursorShape: Qt.PointingHandCursor
onClicked: () => {
if (isPromptMode) {
NetworkService.cancelCredentials(promptToken)
NetworkService.cancelCredentials(promptToken);
}
close()
wifiPasswordInput = ""
wifiUsernameInput = ""
wifiAnonymousIdentityInput = ""
wifiDomainInput = ""
close();
wifiPasswordInput = "";
wifiUsernameInput = "";
wifiAnonymousIdentityInput = "";
wifiDomainInput = "";
}
}
}
@@ -582,9 +582,9 @@ DankModal {
color: connectArea.containsMouse ? Qt.darker(Theme.primary, 1.1) : Theme.primary
enabled: {
if (isVpnPrompt) {
return passwordInput.text.length > 0
return passwordInput.text.length > 0;
}
return requiresEnterprise ? (usernameInput.text.length > 0 && passwordInput.text.length > 0) : passwordInput.text.length > 0
return requiresEnterprise ? (usernameInput.text.length > 0 && passwordInput.text.length > 0) : passwordInput.text.length > 0;
}
opacity: enabled ? 1 : 0.5
@@ -607,34 +607,33 @@ DankModal {
enabled: parent.enabled
onClicked: () => {
if (isPromptMode) {
const secrets = {}
const secrets = {};
if (isVpnPrompt) {
if (passwordInput.text) secrets["password"] = passwordInput.text
if (passwordInput.text)
secrets["password"] = passwordInput.text;
} else if (promptSetting === "802-11-wireless-security") {
secrets["psk"] = passwordInput.text
secrets["psk"] = passwordInput.text;
} else if (promptSetting === "802-1x") {
if (usernameInput.text) secrets["identity"] = usernameInput.text
if (passwordInput.text) secrets["password"] = passwordInput.text
if (wifiAnonymousIdentityInput) secrets["anonymous-identity"] = wifiAnonymousIdentityInput
if (usernameInput.text)
secrets["identity"] = usernameInput.text;
if (passwordInput.text)
secrets["password"] = passwordInput.text;
if (wifiAnonymousIdentityInput)
secrets["anonymous-identity"] = wifiAnonymousIdentityInput;
}
NetworkService.submitCredentials(promptToken, secrets, savePasswordCheckbox.checked)
NetworkService.submitCredentials(promptToken, secrets, savePasswordCheckbox.checked);
} else {
const username = requiresEnterprise ? usernameInput.text : ""
NetworkService.connectToWifi(
wifiPasswordSSID,
passwordInput.text,
username,
wifiAnonymousIdentityInput,
wifiDomainInput
)
const username = requiresEnterprise ? usernameInput.text : "";
NetworkService.connectToWifi(wifiPasswordSSID, passwordInput.text, username, wifiAnonymousIdentityInput, wifiDomainInput);
}
close()
wifiPasswordInput = ""
wifiUsernameInput = ""
wifiAnonymousIdentityInput = ""
wifiDomainInput = ""
passwordInput.text = ""
if (requiresEnterprise) usernameInput.text = ""
close();
wifiPasswordInput = "";
wifiUsernameInput = "";
wifiAnonymousIdentityInput = "";
wifiDomainInput = "";
passwordInput.text = "";
if (requiresEnterprise)
usernameInput.text = "";
}
}

View File

@@ -154,9 +154,8 @@ DankPopout {
if (powerMenuModalLoader) {
powerMenuModalLoader.active = true;
if (powerMenuModalLoader.item) {
const popoutPos = controlContent.mapToItem(null, 0, 0);
const bounds = Qt.rect(popoutPos.x, popoutPos.y, controlContent.width, controlContent.height);
powerMenuModalLoader.item.openFromControlCenter(bounds, root.triggerScreen);
const bounds = Qt.rect(root.alignedX, root.alignedY, root.popupWidth, root.popupHeight);
powerMenuModalLoader.item.openFromControlCenter(bounds, root.screen);
}
}
}