summaryrefslogtreecommitdiff
path: root/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ActionPanel.qml
diff options
context:
space:
mode:
Diffstat (limited to 'raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ActionPanel.qml')
-rw-r--r--raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ActionPanel.qml256
1 files changed, 256 insertions, 0 deletions
diff --git a/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ActionPanel.qml b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ActionPanel.qml
new file mode 100644
index 0000000..31ada32
--- /dev/null
+++ b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ActionPanel.qml
@@ -0,0 +1,256 @@
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import qs.Common
+import qs.Services
+import qs.Widgets
+
+Rectangle {
+ id: root
+
+ property var selectedItem: null
+ property var controller: null
+ property bool expanded: false
+ property int selectedActionIndex: 0
+
+ function getPluginContextMenuActions() {
+ if (selectedItem?.type !== "plugin" || !selectedItem?.pluginId)
+ return [];
+ var instance = PluginService.pluginInstances[selectedItem.pluginId];
+ if (!instance)
+ return [];
+ if (typeof instance.getContextMenuActions !== "function")
+ return [];
+ var actions = instance.getContextMenuActions(selectedItem.data);
+ if (!Array.isArray(actions))
+ return [];
+ return actions;
+ }
+
+ readonly property var actions: {
+ var result = [];
+ if (selectedItem?.primaryAction) {
+ result.push(selectedItem.primaryAction);
+ }
+
+ switch (selectedItem?.type) {
+ case "plugin":
+ var pluginActions = getPluginContextMenuActions();
+ for (var i = 0; i < pluginActions.length; i++) {
+ var act = pluginActions[i];
+ result.push({
+ name: act.text || act.name || "",
+ icon: act.icon || "play_arrow",
+ action: "plugin_action",
+ pluginAction: act.action
+ });
+ }
+ break;
+ case "plugin_browse":
+ if (selectedItem?.actions) {
+ for (var i = 0; i < selectedItem.actions.length; i++) {
+ result.push(selectedItem.actions[i]);
+ }
+ }
+ break;
+ case "app":
+ if (selectedItem?.isCore)
+ break;
+ if (SessionService.nvidiaCommand) {
+ result.push({
+ name: I18n.tr("Launch on dGPU"),
+ icon: "memory",
+ action: "launch_dgpu"
+ });
+ }
+ if (selectedItem?.actions) {
+ for (var i = 0; i < selectedItem.actions.length; i++) {
+ result.push(selectedItem.actions[i]);
+ }
+ }
+ break;
+ }
+ return result;
+ }
+
+ readonly property bool hasActions: {
+ switch (selectedItem?.type) {
+ case "app":
+ return !selectedItem?.isCore;
+ case "plugin":
+ return getPluginContextMenuActions().length > 0;
+ case "plugin_browse":
+ return selectedItem?.actions?.length > 0;
+ default:
+ return actions.length > 1;
+ }
+ }
+
+ width: parent?.width ?? 200
+ height: expanded && hasActions ? 52 : 0
+ color: Theme.surfaceContainerHigh
+ radius: Theme.cornerRadius
+
+ clip: true
+
+ Behavior on height {
+ NumberAnimation {
+ duration: Theme.shortDuration
+ easing.type: Theme.standardEasing
+ }
+ }
+
+ Rectangle {
+ anchors.top: parent.top
+ width: parent.width
+ height: 1
+ color: Theme.outlineMedium
+ }
+
+ Item {
+ anchors.fill: parent
+ anchors.margins: Theme.spacingS
+
+ Flickable {
+ id: actionsFlickable
+ anchors.left: parent.left
+ anchors.right: tabHint.left
+ anchors.rightMargin: Theme.spacingS
+ anchors.verticalCenter: parent.verticalCenter
+ height: parent.height
+ contentWidth: actionsRow.width
+ contentHeight: height
+ clip: true
+ boundsBehavior: Flickable.StopAtBounds
+ flickableDirection: Flickable.HorizontalFlick
+
+ Row {
+ id: actionsRow
+ height: parent.height
+ spacing: Theme.spacingS
+
+ Repeater {
+ model: root.actions
+
+ Rectangle {
+ id: actionButton
+
+ required property var modelData
+ required property int index
+
+ width: actionContent.implicitWidth + Theme.spacingM * 2
+ height: actionsRow.height
+ radius: Theme.cornerRadius
+ color: index === root.selectedActionIndex ? Theme.primaryHover : actionArea.containsMouse ? Theme.surfaceHover : "transparent"
+
+ Row {
+ id: actionContent
+ anchors.centerIn: parent
+ spacing: Theme.spacingXS
+
+ DankIcon {
+ anchors.verticalCenter: parent.verticalCenter
+ name: actionButton.modelData?.icon ?? "play_arrow"
+ size: 16
+ color: actionButton.index === root.selectedActionIndex ? Theme.primary : Theme.surfaceText
+ }
+
+ StyledText {
+ anchors.verticalCenter: parent.verticalCenter
+ text: actionButton.modelData?.name ?? ""
+ font.pixelSize: Theme.fontSizeSmall
+ font.weight: Font.Medium
+ color: actionButton.index === root.selectedActionIndex ? Theme.primary : Theme.surfaceText
+ }
+ }
+
+ MouseArea {
+ id: actionArea
+ anchors.fill: parent
+ hoverEnabled: true
+ cursorShape: Qt.PointingHandCursor
+ onClicked: {
+ if (root.controller && root.selectedItem) {
+ root.controller.executeAction(root.selectedItem, actionButton.modelData);
+ }
+ }
+ onEntered: root.selectedActionIndex = actionButton.index
+ }
+ }
+ }
+ }
+ }
+
+ StyledText {
+ id: tabHint
+ anchors.right: parent.right
+ anchors.verticalCenter: parent.verticalCenter
+ visible: root.hasActions
+ text: "Tab"
+ font.pixelSize: Theme.fontSizeSmall - 2
+ color: Theme.outlineButton
+ }
+ }
+
+ function toggle() {
+ expanded = !expanded;
+ selectedActionIndex = 0;
+ }
+
+ function show() {
+ expanded = true;
+ selectedActionIndex = actions.length > 1 ? 1 : 0;
+ }
+
+ function hide() {
+ expanded = false;
+ selectedActionIndex = 0;
+ }
+
+ function cycleAction(reverse = false) {
+ if (actions.length > 0) {
+ if (! reverse)
+ selectedActionIndex = (selectedActionIndex + 1) % actions.length;
+ else
+ selectedActionIndex = (selectedActionIndex - 1) % actions.length;
+ ensureSelectedVisible();
+ }
+ }
+
+ function ensureSelectedVisible() {
+ if (selectedActionIndex < 0 || !actionsRow.children || selectedActionIndex >= actionsRow.children.length)
+ return;
+ var buttonX = 0;
+ for (var i = 0; i < selectedActionIndex; i++) {
+ var child = actionsRow.children[i];
+ if (child)
+ buttonX += child.width + actionsRow.spacing;
+ }
+
+ var button = actionsRow.children[selectedActionIndex];
+ if (!button)
+ return;
+ var buttonRight = buttonX + button.width;
+ var viewLeft = actionsFlickable.contentX;
+ var viewRight = viewLeft + actionsFlickable.width;
+
+ if (buttonX < viewLeft) {
+ actionsFlickable.contentX = Math.max(0, buttonX - Theme.spacingS);
+ } else if (buttonRight > viewRight) {
+ actionsFlickable.contentX = Math.min(actionsFlickable.contentWidth - actionsFlickable.width, buttonRight - actionsFlickable.width + Theme.spacingS);
+ }
+ }
+
+ function executeSelectedAction() {
+ if (!controller || !selectedItem || selectedActionIndex >= actions.length)
+ return;
+ var action = actions[selectedActionIndex];
+ if (action.action === "plugin_action" && typeof action.pluginAction === "function") {
+ action.pluginAction();
+ controller.performSearch();
+ controller.itemExecuted();
+ } else {
+ controller.executeAction(selectedItem, action);
+ }
+ }
+}