feat: launcher actions
This commit is contained in:
parent
e3a27ec90b
commit
5978db658c
6 changed files with 277 additions and 13 deletions
|
|
@ -5,9 +5,11 @@ import QtQuick
|
|||
|
||||
Singleton {
|
||||
readonly property int maxShown: 8
|
||||
readonly property string actionPrefix: ">"
|
||||
readonly property Sizes sizes: Sizes {}
|
||||
|
||||
component Sizes: QtObject {
|
||||
property int width: 600
|
||||
readonly property int width: 600
|
||||
readonly property int itemHeight: 57
|
||||
}
|
||||
}
|
||||
|
|
|
|||
59
modules/launcher/ActionItem.qml
Normal file
59
modules/launcher/ActionItem.qml
Normal file
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
127
modules/launcher/Actions.qml
Normal file
127
modules/launcher/Actions.qml
Normal file
|
|
@ -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 {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,10 +69,14 @@ Item {
|
|||
|
||||
onAccepted: {
|
||||
if (list.currentItem) {
|
||||
if (list.isAction)
|
||||
list.currentItem.modelData.onClicked(list);
|
||||
else {
|
||||
Apps.launch(list.currentItem?.modelData);
|
||||
root.launcher.launcherVisible = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Keys.onUpPressed: list.decrementCurrentIndex()
|
||||
Keys.onDownPressed: list.incrementCurrentIndex()
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue