utilities: add recording delete confirmation

This commit is contained in:
2 * r + 2 * t 2025-09-14 17:31:01 +10:00
parent 4b221e2fd5
commit 281b04b6d9
6 changed files with 207 additions and 12 deletions

View file

@ -12,13 +12,14 @@ StyledRect {
Text Text
} }
required property string icon property alias icon: label.text
property bool checked property bool checked
property bool toggle property bool toggle
property real padding: type == IconButton.Text ? Appearance.padding.small / 2 : Appearance.padding.smaller property real padding: type == IconButton.Text ? Appearance.padding.small / 2 : Appearance.padding.smaller
property alias font: label.font property alias font: label.font
property int type: IconButton.Filled property int type: IconButton.Filled
property alias stateLayer: stateLayer
property alias label: label property alias label: label
property bool internalChecked property bool internalChecked
@ -39,6 +40,8 @@ StyledRect {
implicitHeight: label.implicitHeight + padding * 2 implicitHeight: label.implicitHeight + padding * 2
StateLayer { StateLayer {
id: stateLayer
color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour
function onClicked(): void { function onClicked(): void {
@ -52,8 +55,6 @@ StyledRect {
id: label id: label
anchors.centerIn: parent anchors.centerIn: parent
text: root.icon
color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour
fill: root.internalChecked ? 1 : 0 fill: root.internalChecked ? 1 : 0

View file

@ -0,0 +1,65 @@
import ".."
import qs.services
import qs.config
import QtQuick
StyledRect {
id: root
enum Type {
Filled,
Tonal,
Text
}
property alias text: label.text
property bool checked
property bool toggle
property real horizontalPadding: Appearance.padding.normal
property real verticalPadding: Appearance.padding.smaller
property alias font: label.font
property int type: IconButton.Filled
property alias stateLayer: stateLayer
property alias label: label
property bool internalChecked
property color activeColour: type == IconButton.Filled ? Colours.palette.m3primary : Colours.palette.m3secondary
property color inactiveColour: type == IconButton.Filled ? Colours.palette.m3surfaceContainer : Colours.palette.m3secondaryContainer
property color activeOnColour: type == IconButton.Filled ? Colours.palette.m3onPrimary : Colours.palette.m3onSecondary
property color inactiveOnColour: type == IconButton.Filled ? Colours.palette.m3onSurface : Colours.palette.m3onSecondaryContainer
function onClicked(): void {
}
onCheckedChanged: internalChecked = checked
radius: internalChecked ? Appearance.rounding.small : implicitHeight / 2
color: type == IconButton.Text ? "transparent" : internalChecked ? activeColour : inactiveColour
implicitWidth: label.implicitWidth + horizontalPadding * 2
implicitHeight: label.implicitHeight + verticalPadding * 2
StateLayer {
id: stateLayer
color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour
function onClicked(): void {
if (root.toggle)
root.internalChecked = !root.internalChecked;
root.onClicked();
}
}
StyledText {
id: label
anchors.centerIn: parent
color: root.internalChecked ? root.activeOnColour : root.inactiveOnColour
}
Behavior on radius {
Anim {}
}
}

View file

@ -1,23 +1,36 @@
import "cards" import "cards"
import qs.config import qs.config
import QtQuick
import QtQuick.Layouts import QtQuick.Layouts
ColumnLayout { Item {
id: root id: root
required property var props required property var props
required property var visibilities required property var visibilities
spacing: Appearance.spacing.normal implicitWidth: layout.implicitWidth
implicitHeight: layout.implicitHeight
IdleInhibit {} ColumnLayout {
id: layout
Record { anchors.fill: parent
props: root.props spacing: Appearance.spacing.normal
visibilities: root.visibilities
IdleInhibit {}
Record {
props: root.props
visibilities: root.visibilities
}
Toggles {
visibilities: root.visibilities
}
} }
Toggles { RecordingDeleteModal {
visibilities: root.visibilities props: root.props
} }
} }

View file

@ -0,0 +1,114 @@
pragma ComponentBehavior: Bound
import qs.components
import qs.components.controls
import qs.components.effects
import qs.services
import qs.config
import Caelestia
import QtQuick
import QtQuick.Layouts
Loader {
id: root
required property var props
anchors.fill: parent
opacity: root.props.recordingConfirmDelete ? 1 : 0
active: opacity > 0
asynchronous: true
sourceComponent: MouseArea {
id: deleteConfirmation
property string path
Component.onCompleted: path = root.props.recordingConfirmDelete
hoverEnabled: true
onClicked: root.props.recordingConfirmDelete = ""
StyledRect {
anchors.centerIn: parent
radius: Appearance.rounding.large
color: Colours.palette.m3surfaceContainerHigh
scale: 0.5
Component.onCompleted: scale = Qt.binding(() => root.props.recordingConfirmDelete ? 1 : 0.5)
width: Math.min(parent.width - Appearance.padding.large * 2, implicitWidth)
implicitWidth: deleteConfirmationLayout.implicitWidth + Appearance.padding.large * 3
implicitHeight: deleteConfirmationLayout.implicitHeight + Appearance.padding.large * 3
Elevation {
anchors.fill: parent
radius: parent.radius
z: -1
level: 3
}
ColumnLayout {
id: deleteConfirmationLayout
anchors.fill: parent
anchors.margins: Appearance.padding.large * 1.5
spacing: Appearance.spacing.normal
StyledText {
text: qsTr("Delete recording?")
font.pointSize: Appearance.font.size.large
}
StyledText {
Layout.fillWidth: true
text: qsTr("Recording '%1' will be permanently deleted.").arg(deleteConfirmation.path)
color: Colours.palette.m3onSurfaceVariant
font.pointSize: Appearance.font.size.small
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
}
RowLayout {
Layout.topMargin: Appearance.spacing.normal
Layout.alignment: Qt.AlignRight
spacing: Appearance.spacing.normal
TextButton {
text: qsTr("Cancel")
type: TextButton.Text
label.color: Colours.palette.m3primary
stateLayer.color: Colours.palette.m3primary
function onClicked(): void {
root.props.recordingConfirmDelete = "";
}
}
TextButton {
text: qsTr("Delete")
type: TextButton.Text
label.color: Colours.palette.m3primary
stateLayer.color: Colours.palette.m3primary
function onClicked(): void {
CUtils.deleteFile(Qt.resolvedUrl(root.props.recordingConfirmDelete));
root.props.recordingConfirmDelete = "";
}
}
}
}
Behavior on scale {
Anim {
duration: Appearance.anim.durations.expressiveDefaultSpatial
easing.bezierCurve: Appearance.anim.curves.expressiveDefaultSpatial
}
}
}
}
Behavior on opacity {
Anim {}
}
}

View file

@ -11,6 +11,7 @@ Item {
required property var visibilities required property var visibilities
readonly property PersistentProperties props: PersistentProperties { readonly property PersistentProperties props: PersistentProperties {
property bool recordingListExpanded: false property bool recordingListExpanded: false
property string recordingConfirmDelete
reloadableId: "utilities" reloadableId: "utilities"
} }

View file

@ -193,9 +193,10 @@ StyledRect {
icon: "delete_forever" icon: "delete_forever"
type: IconButton.Text type: IconButton.Text
label.color: Colours.palette.m3error label.color: Colours.palette.m3error
stateLayer.color: Colours.palette.m3error
function onClicked(): void { function onClicked(): void {
CUtils.deleteFile(Qt.resolvedUrl(recording.modelData.path)); root.props.recordingConfirmDelete = recording.modelData.path;
} }
} }
} }