Extract confirmation dialog

This commit is contained in:
David Heinemeier Hansson
2026-05-29 12:57:43 +02:00
parent 5bdd264ce0
commit 49ca79081f
3 changed files with 145 additions and 96 deletions
+125
View File
@@ -0,0 +1,125 @@
import QtQuick
import qs.Commons
Item {
id: root
property bool opened: false
property string message: ""
property string cancelText: "Cancel"
property string confirmText: "Confirm"
property int selectedIndex: 1
property color background: Color.background
property color foreground: Color.foreground
property color scrim: Util.alpha(Color.background, 0.7)
property color selectedBackground: Util.alpha(Color.foreground, 0.08)
property color selectedText: Color.accent
property string fontFamily: Style.font.family
property int cornerRadius: Style.cornerRadius
signal canceled()
signal confirmed()
function handleKey(event) {
if (!root.opened) return false
if (event.key === Qt.Key_Escape) {
root.canceled()
return true
} else if (event.key === Qt.Key_Left || event.key === Qt.Key_Right || event.key === Qt.Key_Tab || event.key === Qt.Key_Backtab) {
root.selectedIndex = root.selectedIndex === 0 ? 1 : 0
return true
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
if (root.selectedIndex === 0) root.canceled()
else root.confirmed()
return true
}
return false
}
visible: opened
Rectangle {
anchors.fill: parent
color: root.scrim
MouseArea { anchors.fill: parent; onClicked: root.canceled() }
Rectangle {
width: Math.min(parent.width - Style.space(96), Style.space(370))
height: Style.space(132)
anchors.centerIn: parent
color: root.background
border.color: root.selectedText
border.width: Style.normalBorderWidth
radius: root.cornerRadius
MouseArea { anchors.fill: parent; onClicked: {} }
Item {
anchors.fill: parent
anchors.margins: Style.space(18)
Text {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
text: root.message
color: root.foreground
font.family: root.fontFamily
font.pixelSize: Style.font.title
wrapMode: Text.WordWrap
}
Row {
anchors.right: parent.right
anchors.bottom: parent.bottom
spacing: Style.space(10)
Repeater {
model: [root.cancelText, root.confirmText]
Rectangle {
required property int index
required property string modelData
readonly property bool selected: root.selectedIndex === index
readonly property bool destructive: index === 1
width: Style.space(88)
height: Style.space(34)
color: selected
? (destructive ? Util.alpha(Color.urgent, 0.22) : root.selectedBackground)
: "transparent"
border.color: destructive
? (selected ? Color.urgent : Util.alpha(Color.urgent, 0.56))
: (selected ? root.selectedText : Util.alpha(root.foreground, 0.38))
border.width: Style.normalBorderWidth
radius: 0
Text {
anchors.centerIn: parent
text: modelData
color: destructive ? (selected ? Color.urgent : root.foreground) : (selected ? root.selectedText : root.foreground)
font.family: root.fontFamily
font.pixelSize: Style.font.caption
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onEntered: root.selectedIndex = index
onClicked: {
if (index === 0) root.canceled()
else root.confirmed()
}
}
}
}
}
}
}
}
}
+1
View File
@@ -4,6 +4,7 @@ BarIndicator 1.0 BarIndicator.qml
BarWidget 1.0 BarWidget.qml
Button 1.0 Button.qml
ButtonGroup 1.0 ButtonGroup.qml
ConfirmDialog 1.0 ConfirmDialog.qml
CursorSurface 1.0 CursorSurface.qml
Dropdown 1.0 Dropdown.qml
KeyboardPanel 1.0 KeyboardPanel.qml
+19 -96
View File
@@ -4,6 +4,7 @@ import Quickshell.Wayland
import Quickshell.Widgets
import QtQuick
import qs.Commons
import qs.Ui
import "LauncherSearch.js" as LauncherSearch
Item {
@@ -29,7 +30,6 @@ Item {
property var desktopHiddenEntryIds: ({})
property bool deleteConfirmOpen: false
property var deleteEntry: null
property int deleteConfirmIndex: 1
// Bound to the central [launcher] section in shell.toml via Color.qml.
// Each color already includes its alpha companion (composed in the
@@ -213,14 +213,14 @@ Item {
var entry = root.filteredEntries[index]
if (!entry) return
root.deleteEntry = entry
root.deleteConfirmIndex = 1
deleteConfirm.selectedIndex = 1
root.deleteConfirmOpen = true
}
function cancelDelete() {
root.deleteConfirmOpen = false
root.deleteEntry = null
root.deleteConfirmIndex = 1
deleteConfirm.selectedIndex = 1
Qt.callLater(function() { keyCatcher.forceActiveFocus() })
}
@@ -364,17 +364,7 @@ Item {
Keys.priority: Keys.BeforeItem
Keys.onPressed: function(event) {
if (root.deleteConfirmOpen) {
if (event.key === Qt.Key_Escape) {
root.cancelDelete()
event.accepted = true
} else if (event.key === Qt.Key_Left || event.key === Qt.Key_Right || event.key === Qt.Key_Tab || event.key === Qt.Key_Backtab) {
root.deleteConfirmIndex = root.deleteConfirmIndex === 0 ? 1 : 0
event.accepted = true
} else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
if (root.deleteConfirmIndex === 0) root.cancelDelete()
else root.confirmDelete()
event.accepted = true
}
if (deleteConfirm.handleKey(event)) event.accepted = true
return
}
@@ -423,90 +413,23 @@ Item {
}
}
Rectangle {
ConfirmDialog {
id: deleteConfirm
anchors.fill: parent
visible: root.deleteConfirmOpen
opened: root.deleteConfirmOpen
z: 10
color: root.scrim
MouseArea { anchors.fill: parent; onClicked: root.cancelDelete() }
Rectangle {
width: Math.min(parent.width - 96, 370)
height: 132
anchors.centerIn: parent
color: root.background
border.color: root.selectedText
border.width: 1
radius: Style.cornerRadius
MouseArea { anchors.fill: parent; onClicked: {} }
Item {
anchors.fill: parent
anchors.margins: 18
Text {
anchors.left: parent.left
anchors.right: parent.right
anchors.top: parent.top
text: "Do you want to uninstall " + root.entryName(root.deleteEntry) + "?"
color: root.foreground
font.family: root.fontFamily
font.pixelSize: 16
wrapMode: Text.WordWrap
}
Row {
anchors.right: parent.right
anchors.bottom: parent.bottom
spacing: 10
Repeater {
model: ["Cancel", "Uninstall"]
Rectangle {
required property int index
required property string modelData
readonly property bool selected: root.deleteConfirmIndex === index
readonly property bool destructive: index === 1
width: 88
height: 34
color: selected
? (destructive ? Util.alpha(Color.urgent, 0.22) : root.selectedBackground)
: "transparent"
border.color: destructive
? (selected ? Color.urgent : Util.alpha(Color.urgent, 0.56))
: (selected ? root.selectedText : Util.alpha(root.foreground, 0.38))
border.width: 1
radius: 0
Text {
id: buttonText
anchors.centerIn: parent
text: modelData
color: destructive ? (selected ? Color.urgent : root.foreground) : (selected ? root.selectedText : root.foreground)
font.family: root.fontFamily
font.pixelSize: 14
}
MouseArea {
anchors.fill: parent
hoverEnabled: true
cursorShape: Qt.PointingHandCursor
onEntered: root.deleteConfirmIndex = index
onClicked: {
if (index === 0) root.cancelDelete()
else root.confirmDelete()
}
}
}
}
}
}
}
message: "Do you want to uninstall " + root.entryName(root.deleteEntry) + "?"
confirmText: "Uninstall"
background: root.background
foreground: root.foreground
scrim: root.scrim
selectedBackground: root.selectedBackground
selectedText: root.selectedText
fontFamily: root.fontFamily
cornerRadius: Style.cornerRadius
onCanceled: root.cancelDelete()
onConfirmed: root.confirmDelete()
}
}