From cf382c0322d3656791057f10aabb967b9117be7d Mon Sep 17 00:00:00 2001 From: bbedward Date: Tue, 21 Apr 2026 14:03:47 -0400 Subject: [PATCH] launcher: add indicators for flatpak/snap/appimage/nix fixes #2251 --- .../Modals/DankLauncherV2/Controller.qml | 4 +- .../Modals/DankLauncherV2/ControllerUtils.js | 33 +++ quickshell/Modals/DankLauncherV2/GridItem.qml | 9 + .../Modals/DankLauncherV2/ItemTransformers.js | 1 + .../Modals/DankLauncherV2/ResultItem.qml | 6 + .../Modals/DankLauncherV2/SourceBadge.qml | 32 ++ quickshell/Modals/DankLauncherV2/TileItem.qml | 9 + .../assets/package-sources/appimage.svg | 278 ++++++++++++++++++ quickshell/assets/package-sources/flatpak.svg | 1 + quickshell/assets/package-sources/nix.svg | 187 ++++++++++++ quickshell/assets/package-sources/snap.svg | 1 + 11 files changed, 560 insertions(+), 1 deletion(-) create mode 100644 quickshell/Modals/DankLauncherV2/SourceBadge.qml create mode 100644 quickshell/assets/package-sources/appimage.svg create mode 100644 quickshell/assets/package-sources/flatpak.svg create mode 100644 quickshell/assets/package-sources/nix.svg create mode 100644 quickshell/assets/package-sources/snap.svg diff --git a/quickshell/Modals/DankLauncherV2/Controller.qml b/quickshell/Modals/DankLauncherV2/Controller.qml index 67cb6060..9cbba3e7 100644 --- a/quickshell/Modals/DankLauncherV2/Controller.qml +++ b/quickshell/Modals/DankLauncherV2/Controller.qml @@ -1442,7 +1442,8 @@ Item { section: it.section || "", isCore: it.isCore || false, isBuiltInLauncher: it.isBuiltInLauncher || false, - pluginId: it.pluginId || "" + pluginId: it.pluginId || "", + source: it.source || "" }); } serializable.push({ @@ -1497,6 +1498,7 @@ Item { isCore: it.isCore || false, isBuiltInLauncher: it.isBuiltInLauncher || false, pluginId: it.pluginId || "", + source: it.source || "", data: { id: it.id }, diff --git a/quickshell/Modals/DankLauncherV2/ControllerUtils.js b/quickshell/Modals/DankLauncherV2/ControllerUtils.js index a06285fd..b4f5ebe3 100644 --- a/quickshell/Modals/DankLauncherV2/ControllerUtils.js +++ b/quickshell/Modals/DankLauncherV2/ControllerUtils.js @@ -101,6 +101,39 @@ function detectIconType(iconName) { return "material"; } +function classifyAppSource(app) { + if (!app) + return ""; + + var execRaw = app.execString || app.exec || ""; + if (!execRaw && !app.id) + return ""; + + var exec = execRaw.toLowerCase(); + var cmd0 = (app.command && app.command.length > 0) ? String(app.command[0]).toLowerCase() : ""; + var id = (app.id || "").toLowerCase(); + + if (cmd0 === "flatpak" || exec.indexOf("flatpak run ") !== -1) + return "flatpak"; + + if (cmd0 === "snap" + || exec.indexOf("bamf_desktop_file_hint=") !== -1 + || exec.indexOf("/snap/bin/") !== -1 + || exec.indexOf("/snap/core") !== -1 + || exec.indexOf("snap run ") === 0) + return "snap"; + + if (/\.appimage(\s|$|")/i.test(execRaw) || id.indexOf("appimagekit_") === 0) + return "appimage"; + + if (exec.indexOf("/nix/store/") !== -1 + || exec.indexOf("/run/current-system/sw/") !== -1 + || exec.indexOf("/etc/profiles/per-user/") !== -1) + return "nix"; + + return "system"; +} + function sortPluginIdsByOrder(pluginIds, order) { if (!order || order.length === 0) return pluginIds; diff --git a/quickshell/Modals/DankLauncherV2/GridItem.qml b/quickshell/Modals/DankLauncherV2/GridItem.qml index a7f39c33..5d812ae1 100644 --- a/quickshell/Modals/DankLauncherV2/GridItem.qml +++ b/quickshell/Modals/DankLauncherV2/GridItem.qml @@ -44,6 +44,15 @@ Rectangle { cornerRadius: root.radius } + SourceBadge { + anchors.top: parent.top + anchors.right: parent.right + anchors.margins: Theme.spacingXS + source: root.item?.type === "app" ? (root.item.source || "") : "" + glyphSize: 14 + z: 1 + } + Column { anchors.centerIn: parent anchors.margins: Theme.spacingS diff --git a/quickshell/Modals/DankLauncherV2/ItemTransformers.js b/quickshell/Modals/DankLauncherV2/ItemTransformers.js index 61c108ca..d85dee98 100644 --- a/quickshell/Modals/DankLauncherV2/ItemTransformers.js +++ b/quickshell/Modals/DankLauncherV2/ItemTransformers.js @@ -27,6 +27,7 @@ function transformApp(app, override, defaultActions, primaryActionLabel) { data: app, keywords: app.keywords || [], actions: actions, + source: Utils.classifyAppSource(app), primaryAction: { name: primaryActionLabel, icon: "open_in_new", diff --git a/quickshell/Modals/DankLauncherV2/ResultItem.qml b/quickshell/Modals/DankLauncherV2/ResultItem.qml index 0a50cd3e..de00caa9 100644 --- a/quickshell/Modals/DankLauncherV2/ResultItem.qml +++ b/quickshell/Modals/DankLauncherV2/ResultItem.qml @@ -191,6 +191,12 @@ Rectangle { color: Theme.surfaceVariantText } } + + SourceBadge { + anchors.verticalCenter: parent.verticalCenter + source: root.item?.type === "app" ? (root.item.source || "") : "" + glyphSize: 14 + } } } } diff --git a/quickshell/Modals/DankLauncherV2/SourceBadge.qml b/quickshell/Modals/DankLauncherV2/SourceBadge.qml new file mode 100644 index 00000000..98ec2414 --- /dev/null +++ b/quickshell/Modals/DankLauncherV2/SourceBadge.qml @@ -0,0 +1,32 @@ +import QtQuick +import Quickshell.Widgets + +Item { + id: root + + property string source: "" + property int glyphSize: 14 + + readonly property var sourceAsset: ({ + "flatpak": "../../assets/package-sources/flatpak.svg", + "snap": "../../assets/package-sources/snap.svg", + "appimage": "../../assets/package-sources/appimage.svg", + "nix": "../../assets/package-sources/nix.svg" + }) + + readonly property string assetPath: sourceAsset[source] || "" + + visible: assetPath.length > 0 + implicitWidth: glyphSize + implicitHeight: glyphSize + + IconImage { + anchors.fill: parent + source: root.assetPath ? Qt.resolvedUrl(root.assetPath) : "" + implicitSize: root.glyphSize * 2 + backer.sourceSize: Qt.size(root.glyphSize * 2, root.glyphSize * 2) + smooth: true + mipmap: true + asynchronous: true + } +} diff --git a/quickshell/Modals/DankLauncherV2/TileItem.qml b/quickshell/Modals/DankLauncherV2/TileItem.qml index 0b488025..d4837412 100644 --- a/quickshell/Modals/DankLauncherV2/TileItem.qml +++ b/quickshell/Modals/DankLauncherV2/TileItem.qml @@ -168,6 +168,15 @@ Rectangle { mipmap: true } } + + SourceBadge { + anchors.top: parent.top + anchors.right: parent.right + anchors.margins: Theme.spacingXS + source: root.item?.type === "app" ? (root.item.source || "") : "" + glyphSize: 16 + visible: !root.isSelected && !!source + } } } diff --git a/quickshell/assets/package-sources/appimage.svg b/quickshell/assets/package-sources/appimage.svg new file mode 100644 index 00000000..8ffb922c --- /dev/null +++ b/quickshell/assets/package-sources/appimage.svg @@ -0,0 +1,278 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/quickshell/assets/package-sources/flatpak.svg b/quickshell/assets/package-sources/flatpak.svg new file mode 100644 index 00000000..8c27b54a --- /dev/null +++ b/quickshell/assets/package-sources/flatpak.svg @@ -0,0 +1 @@ +Flatpak diff --git a/quickshell/assets/package-sources/nix.svg b/quickshell/assets/package-sources/nix.svg new file mode 100644 index 00000000..2a065bc9 --- /dev/null +++ b/quickshell/assets/package-sources/nix.svg @@ -0,0 +1,187 @@ + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/quickshell/assets/package-sources/snap.svg b/quickshell/assets/package-sources/snap.svg new file mode 100644 index 00000000..b2c50ea1 --- /dev/null +++ b/quickshell/assets/package-sources/snap.svg @@ -0,0 +1 @@ +Snapcraft