summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
author2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-05-03 14:32:53 +1000
committer2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-05-03 14:32:53 +1000
commit5978db658c541d4acf4de4a14139232f4a57284c (patch)
tree754eeff62e09569ead024f89cc638a002a12c923 /modules
parentlauncher: fix scrollbar (diff)
downloadcaelestia-shell-5978db658c541d4acf4de4a14139232f4a57284c.tar.gz
caelestia-shell-5978db658c541d4acf4de4a14139232f4a57284c.tar.bz2
caelestia-shell-5978db658c541d4acf4de4a14139232f4a57284c.zip
feat: launcher actions
Diffstat (limited to 'modules')
-rw-r--r--modules/launcher/ActionItem.qml59
-rw-r--r--modules/launcher/Actions.qml127
-rw-r--r--modules/launcher/AppItem.qml2
-rw-r--r--modules/launcher/AppList.qml86
-rw-r--r--modules/launcher/Content.qml12
5 files changed, 274 insertions, 12 deletions
diff --git a/modules/launcher/ActionItem.qml b/modules/launcher/ActionItem.qml
new file mode 100644
index 0000000..06a9342
--- /dev/null
+++ b/modules/launcher/ActionItem.qml
@@ -0,0 +1,59 @@
+import "root:/widgets"
+import "root:/config"
+import Quickshell
+import QtQuick
+
+PaddedRect {
+ id: root
+
+ required property Actions.Action modelData
+ required property var list
+
+ implicitWidth: ListView.view.width
+ implicitHeight: LauncherConfig.sizes.itemHeight
+ padding: [Appearance.padding.smaller, Appearance.padding.larger]
+
+ StateLayer {
+ radius: Appearance.rounding.normal
+
+ function onClicked(): void {
+ root.modelData.onClicked(root.list);
+ }
+ }
+
+ MaterialIcon {
+ id: icon
+
+ text: root.modelData.icon
+ font.pointSize: Appearance.font.size.extraLarge
+
+ anchors.verticalCenter: parent.verticalCenter
+ }
+
+ Item {
+ anchors.left: icon.right
+ anchors.leftMargin: Appearance.spacing.larger
+ anchors.verticalCenter: icon.verticalCenter
+
+ implicitWidth: parent.width - icon.width
+ implicitHeight: childrenRect.height
+
+ StyledText {
+ id: name
+
+ text: root.modelData.name
+ font.pointSize: Appearance.font.size.normal
+ }
+
+ StyledText {
+ text: root.modelData.desc
+ font.pointSize: Appearance.font.size.small
+ color: Appearance.alpha(Appearance.colours.m3outline, true)
+
+ elide: Text.ElideRight
+ width: root.width - icon.width - Appearance.rounding.normal * 2
+
+ anchors.top: name.bottom
+ }
+ }
+}
diff --git a/modules/launcher/Actions.qml b/modules/launcher/Actions.qml
new file mode 100644
index 0000000..4323bff
--- /dev/null
+++ b/modules/launcher/Actions.qml
@@ -0,0 +1,127 @@
+pragma Singleton
+
+import "root:/utils/scripts/fuzzysort.js" as Fuzzy
+import "root:/config"
+import Quickshell
+import Quickshell.Io
+import QtQuick
+
+Singleton {
+ id: root
+
+ readonly property list<Action> list: [
+ Action {
+ name: qsTr("Scheme")
+ desc: qsTr("Change the current colour scheme")
+ icon: "palette"
+
+ function onClicked(list: AppList): void {
+ root.autocomplete(list, "scheme");
+ }
+ },
+ Action {
+ name: qsTr("Wallpaper")
+ desc: qsTr("Change the current wallpaper")
+ icon: "image"
+
+ function onClicked(list: AppList): void {
+ root.autocomplete(list, "wallpaper");
+ }
+ },
+ Action {
+ name: qsTr("Variant")
+ desc: qsTr("Change the current scheme variant")
+ icon: "colors"
+
+ function onClicked(list: AppList): void {
+ root.autocomplete(list, "variant");
+ }
+ },
+ Action {
+ name: qsTr("Transparency")
+ desc: qsTr("Change shell transparency")
+ icon: "opacity"
+
+ function onClicked(list: AppList): void {
+ root.autocomplete(list, "transparency");
+ }
+ },
+ Action {
+ name: qsTr("Light")
+ desc: qsTr("Change the scheme to light mode")
+ icon: "light_mode"
+
+ function onClicked(list: AppList): void {
+ list.launcher.launcherVisible = false;
+ // TODO
+ }
+ },
+ Action {
+ name: qsTr("Dark")
+ desc: qsTr("Change the scheme to dark mode")
+ icon: "dark_mode"
+
+ function onClicked(list: AppList): void {
+ list.launcher.launcherVisible = false;
+ // TODO
+ }
+ },
+ Action {
+ name: qsTr("Lock")
+ desc: qsTr("Lock the current session")
+ icon: "lock"
+
+ function onClicked(list: AppList): void {
+ list.launcher.launcherVisible = false;
+ lock.running = true;
+ }
+ },
+ Action {
+ name: qsTr("Sleep")
+ desc: qsTr("Suspend then hibernate")
+ icon: "bedtime"
+
+ function onClicked(list: AppList): void {
+ list.launcher.launcherVisible = false;
+ sleep.running = true;
+ }
+ }
+ ]
+
+ readonly property list<var> preppedNames: list.map(a => ({
+ name: Fuzzy.prepare(a.name),
+ action: a
+ }))
+
+ function fuzzyQuery(search: string): var {
+ return Fuzzy.go(search.slice(LauncherConfig.actionPrefix.length), preppedNames, {
+ all: true,
+ key: "name"
+ }).map(r => r.obj.action);
+ }
+
+ function autocomplete(list: AppList, text: string): void {
+ list.search.text = `${LauncherConfig.actionPrefix}${text} `;
+ }
+
+ Process {
+ id: lock
+
+ command: ["loginctl", "lock-session"]
+ }
+
+ Process {
+ id: sleep
+
+ command: ["systemctl", "suspend-then-hibernate"]
+ }
+
+ component Action: QtObject {
+ required property string name
+ required property string desc
+ required property string icon
+
+ function onClicked(list: AppList): void {
+ }
+ }
+}
diff --git a/modules/launcher/AppItem.qml b/modules/launcher/AppItem.qml
index ca1b611..744c2d0 100644
--- a/modules/launcher/AppItem.qml
+++ b/modules/launcher/AppItem.qml
@@ -1,5 +1,4 @@
import "root:/widgets"
-import "root:/services"
import "root:/config"
import Quickshell
import Quickshell.Widgets
@@ -12,6 +11,7 @@ PaddedRect {
required property Scope launcher
implicitWidth: ListView.view.width
+ implicitHeight: LauncherConfig.sizes.itemHeight
padding: [Appearance.padding.smaller, Appearance.padding.normal]
StateLayer {
diff --git a/modules/launcher/AppList.qml b/modules/launcher/AppList.qml
index 3175402..ab08db7 100644
--- a/modules/launcher/AppList.qml
+++ b/modules/launcher/AppList.qml
@@ -1,3 +1,5 @@
+pragma ComponentBehavior: Bound
+
import "root:/widgets"
import "root:/services"
import "root:/config"
@@ -9,18 +11,29 @@ ListView {
id: root
required property int padding
- required property string search
+ required property TextField search
required property Scope launcher
+ property bool isAction: search.text.startsWith(LauncherConfig.actionPrefix)
+
+ function getModelValues() {
+ let text = search.text;
+ if (isAction)
+ return Actions.fuzzyQuery(text);
+ if (text.startsWith(LauncherConfig.actionPrefix))
+ text = search.text.slice(LauncherConfig.actionPrefix.length);
+ return Apps.fuzzyQuery(text);
+ }
+
model: ScriptModel {
- values: Apps.fuzzyQuery(root.search)
+ values: root.getModelValues()
onValuesChanged: root.currentIndex = 0
}
clip: true
spacing: Appearance.spacing.small
orientation: Qt.Vertical
- implicitHeight: ((currentItem?.height ?? 1) + spacing) * Math.min(LauncherConfig.maxShown, count) - spacing
+ implicitHeight: (LauncherConfig.sizes.itemHeight + spacing) * Math.min(LauncherConfig.maxShown, count) - spacing
anchors.left: parent.left
anchors.right: parent.right
@@ -34,9 +47,7 @@ ListView {
color: Appearance.alpha(Appearance.colours.m3surfaceContainerHighest, true)
}
- delegate: AppItem {
- launcher: root.launcher
- }
+ delegate: isAction ? actionItem : appItem
ScrollBar.vertical: StyledScrollBar {
// Move half out
@@ -84,8 +95,69 @@ ListView {
}
}
+ Component {
+ id: appItem
+
+ AppItem {
+ launcher: root.launcher
+ }
+ }
+
+ Component {
+ id: actionItem
+
+ ActionItem {
+ list: root
+ }
+ }
+
Behavior on implicitHeight {
- Anim {}
+ Anim {
+ duration: Appearance.anim.durations.large
+ easing.bezierCurve: Appearance.anim.curves.emphasizedDecel
+ }
+ }
+
+ Behavior on isAction {
+ SequentialAnimation {
+ ParallelAnimation {
+ Anim {
+ target: root
+ property: "opacity"
+ from: 1
+ to: 0
+ duration: Appearance.anim.durations.small
+ easing.bezierCurve: Appearance.anim.curves.standardAccel
+ }
+ Anim {
+ target: root
+ property: "scale"
+ from: 1
+ to: 0.9
+ duration: Appearance.anim.durations.small
+ easing.bezierCurve: Appearance.anim.curves.standardAccel
+ }
+ }
+ PropertyAction {}
+ ParallelAnimation {
+ Anim {
+ target: root
+ property: "opacity"
+ from: 0
+ to: 1
+ duration: Appearance.anim.durations.small
+ easing.bezierCurve: Appearance.anim.curves.standardDecel
+ }
+ Anim {
+ target: root
+ property: "scale"
+ from: 0.9
+ to: 1
+ duration: Appearance.anim.durations.small
+ easing.bezierCurve: Appearance.anim.curves.standardDecel
+ }
+ }
+ }
}
component Anim: NumberAnimation {
diff --git a/modules/launcher/Content.qml b/modules/launcher/Content.qml
index 6784b0e..3f9fbe2 100644
--- a/modules/launcher/Content.qml
+++ b/modules/launcher/Content.qml
@@ -36,7 +36,7 @@ Item {
id: list
padding: root.padding
- search: search.text
+ search: search
launcher: root.launcher
}
@@ -60,7 +60,7 @@ Item {
leftPadding: root.padding
rightPadding: root.padding
- placeholderText: qsTr("Type \">\" for commands")
+ placeholderText: qsTr(`Type "${LauncherConfig.actionPrefix}" for commands`)
background: StyledRect {
color: Appearance.alpha(Appearance.colours.m3surfaceContainerHigh, true)
@@ -69,8 +69,12 @@ Item {
onAccepted: {
if (list.currentItem) {
- Apps.launch(list.currentItem?.modelData);
- root.launcher.launcherVisible = false;
+ if (list.isAction)
+ list.currentItem.modelData.onClicked(list);
+ else {
+ Apps.launch(list.currentItem?.modelData);
+ root.launcher.launcherVisible = false;
+ }
}
}