Effects as a list per rule, minimal seed rules, README tidy
Each effect on a rule is a row with its settings at a glance, a button to open it and one to drop it; an Add effect button unfolds the rest. A fresh install seeds only the deliveroo rule. Preview updated.
This commit is contained in:
@@ -9,8 +9,6 @@ https://github.com/user-attachments/assets/d727da98-3df0-40a8-bbba-cf08dc0aaf6e
|
|||||||
|
|
||||||

|

|
||||||
|
|
||||||
> Video of the demo: coming soon.
|
|
||||||
|
|
||||||
> Tested on **Omarchy 4** (Arch Linux, Hyprland with the Lua config, omarchy-shell).
|
> Tested on **Omarchy 4** (Arch Linux, Hyprland with the Lua config, omarchy-shell).
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|||||||
+127
-7
@@ -489,37 +489,70 @@ Panel {
|
|||||||
onCommitted: function(v) { if (root.svc) root.svc.updateRule(root.current, { apps: v }) }
|
onCommitted: function(v) { if (root.svc) root.svc.updateRule(root.current, { apps: v }) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// The rule's effects, one row each with its settings at a glance, a
|
||||||
|
// button to open it and one to drop it; then a button that unfolds
|
||||||
|
// the effects not yet on the rule.
|
||||||
EditorRow {
|
EditorRow {
|
||||||
label: "Effects"
|
label: "Effects"
|
||||||
Column {
|
Column {
|
||||||
|
id: effectsBox
|
||||||
width: parent.width - root.trailInset
|
width: parent.width - root.trailInset
|
||||||
spacing: Style.space(6)
|
spacing: Style.space(6)
|
||||||
|
property bool adding: false
|
||||||
|
readonly property var active: root.effectNames(root.current)
|
||||||
|
readonly property var available: root.catalog.filter(function(e) { return effectsBox.active.indexOf(e.type) === -1 })
|
||||||
|
|
||||||
|
Repeater {
|
||||||
|
model: effectsBox.active
|
||||||
|
delegate: EffectLine {
|
||||||
|
required property string modelData
|
||||||
|
width: effectsBox.width
|
||||||
|
type: modelData
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Note {
|
||||||
|
visible: effectsBox.active.length === 0
|
||||||
|
text: "empty: the rule matches but nothing happens yet"
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: effectsBox.adding ? "Pick an effect below" : "Add effect"
|
||||||
|
iconText: effectsBox.adding ? "" : ""
|
||||||
|
bordered: true
|
||||||
|
focusable: true
|
||||||
|
enabled: effectsBox.available.length > 0
|
||||||
|
foreground: root.fg
|
||||||
|
fontFamily: root.fontFamily
|
||||||
|
fontSize: Style.font.bodySmall
|
||||||
|
onClicked: effectsBox.adding = !effectsBox.adding
|
||||||
|
}
|
||||||
|
|
||||||
Flow {
|
Flow {
|
||||||
|
visible: effectsBox.adding
|
||||||
width: parent.width
|
width: parent.width
|
||||||
spacing: Style.spacing.md
|
spacing: Style.spacing.md
|
||||||
Repeater {
|
Repeater {
|
||||||
model: root.catalog
|
model: effectsBox.available
|
||||||
delegate: Button {
|
delegate: Button {
|
||||||
required property var modelData
|
required property var modelData
|
||||||
readonly property bool on: root.effectNames(root.current).indexOf(modelData.type) !== -1
|
|
||||||
text: modelData.label
|
text: modelData.label
|
||||||
iconText: on ? "" : (modelData.icon || "")
|
iconText: modelData.icon || ""
|
||||||
selected: on
|
|
||||||
bordered: true
|
bordered: true
|
||||||
focusable: true
|
focusable: true
|
||||||
foreground: root.fg
|
foreground: root.fg
|
||||||
fontFamily: root.fontFamily
|
fontFamily: root.fontFamily
|
||||||
fontSize: Style.font.bodySmall
|
fontSize: Style.font.bodySmall
|
||||||
tooltipText: modelData.subtitle + (on ? " · click to set up" : " · click to turn on and set up")
|
tooltipText: modelData.subtitle
|
||||||
onClicked: {
|
onClicked: {
|
||||||
if (!root.svc) return
|
if (!root.svc) return
|
||||||
if (!on) root.svc.addRuleEffect(root.current, modelData.type)
|
effectsBox.adding = false
|
||||||
|
root.svc.addRuleEffect(root.current, modelData.type)
|
||||||
root.openEffect(modelData.type)
|
root.openEffect(modelData.type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Note { text: root.effectNames(root.current).length ? "Click an effect to set it up. Empty: the rule matches but nothing happens." : "empty: nothing happens yet · click an effect to turn it on and set it up" }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EditorRow {
|
EditorRow {
|
||||||
@@ -998,6 +1031,93 @@ Panel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// One effect on the rule: name, its settings in a line, open and remove.
|
||||||
|
component EffectLine: Rectangle {
|
||||||
|
id: line
|
||||||
|
property string type: ""
|
||||||
|
readonly property var def: Catalog.find(type)
|
||||||
|
height: Style.space(34)
|
||||||
|
radius: Style.space(6)
|
||||||
|
color: lineArea.containsMouse ? Util.alpha(root.fg, 0.08) : Util.alpha(root.fg, 0.04)
|
||||||
|
|
||||||
|
function summary() {
|
||||||
|
if (!def || !root.svc) return ""
|
||||||
|
var parts = []
|
||||||
|
for (var i = 0; i < def.rows.length && parts.length < 3; i++) {
|
||||||
|
var r = def.rows[i]
|
||||||
|
parts.push(root.fmt(root.svc.ruleEffectOption(root.current, line.type, r.key, r.fallback), r.step, r.unit))
|
||||||
|
}
|
||||||
|
return parts.join(" · ")
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: lineArea
|
||||||
|
anchors.fill: parent
|
||||||
|
hoverEnabled: true
|
||||||
|
cursorShape: Qt.PointingHandCursor
|
||||||
|
onClicked: root.openEffect(line.type)
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
id: lineIcon
|
||||||
|
anchors.left: parent.left
|
||||||
|
anchors.leftMargin: Style.space(10)
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: line.def && line.def.icon ? line.def.icon : ""
|
||||||
|
color: root.fg
|
||||||
|
font.family: root.fontFamily
|
||||||
|
font.pixelSize: Style.font.body
|
||||||
|
width: Style.space(18)
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
id: lineName
|
||||||
|
anchors.left: lineIcon.right
|
||||||
|
anchors.leftMargin: Style.space(6)
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: line.def ? line.def.label : line.type
|
||||||
|
color: root.fg
|
||||||
|
font.family: root.fontFamily
|
||||||
|
font.pixelSize: Style.font.body
|
||||||
|
font.weight: Font.DemiBold
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
anchors.left: lineName.right
|
||||||
|
anchors.leftMargin: Style.space(10)
|
||||||
|
anchors.right: openButton.left
|
||||||
|
anchors.rightMargin: Style.space(6)
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
text: line.summary()
|
||||||
|
color: root.dim
|
||||||
|
font.family: root.fontFamily
|
||||||
|
font.pixelSize: Style.font.bodySmall
|
||||||
|
elide: Text.ElideRight
|
||||||
|
}
|
||||||
|
PanelActionButton {
|
||||||
|
id: openButton
|
||||||
|
anchors.right: removeButton.left
|
||||||
|
anchors.rightMargin: Style.space(2)
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
iconText: ""
|
||||||
|
tooltipText: "Set up"
|
||||||
|
focusable: true
|
||||||
|
foreground: root.fg
|
||||||
|
fontFamily: root.fontFamily
|
||||||
|
onClicked: root.openEffect(line.type)
|
||||||
|
}
|
||||||
|
PanelActionButton {
|
||||||
|
id: removeButton
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: Style.space(4)
|
||||||
|
anchors.verticalCenter: parent.verticalCenter
|
||||||
|
iconText: ""
|
||||||
|
tooltipText: "Remove from this rule"
|
||||||
|
focusable: true
|
||||||
|
foreground: root.fg
|
||||||
|
hoverColor: Color.urgent
|
||||||
|
fontFamily: root.fontFamily
|
||||||
|
onClicked: if (root.svc) root.svc.removeRuleEffect(root.current, line.type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
component EditorRow: Item {
|
component EditorRow: Item {
|
||||||
property string label: ""
|
property string label: ""
|
||||||
default property alias content: slot.data
|
default property alias content: slot.data
|
||||||
|
|||||||
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 1.3 MiB |
+1
-5
@@ -1,11 +1,7 @@
|
|||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"whileDnd": true,
|
"whileDnd": true,
|
||||||
"defaults": {
|
"letThrough": true,
|
||||||
"nudge": { "duration": 1, "intensity": 1.5, "speed": 200 },
|
|
||||||
"flash": { "duration": 1, "intensity": 0.9, "speed": 3, "thickness": 64, "color": "accent" },
|
|
||||||
"sound": { "intensity": 1, "speed": 1 }
|
|
||||||
},
|
|
||||||
"rules": [
|
"rules": [
|
||||||
{
|
{
|
||||||
"name": "deliveroo",
|
"name": "deliveroo",
|
||||||
|
|||||||
Reference in New Issue
Block a user