summaryrefslogtreecommitdiff
path: root/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2
diff options
context:
space:
mode:
Diffstat (limited to 'raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2')
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ActionPanel.qml256
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Controller.qml1894
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ControllerUtils.js128
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/DankLauncherV2Modal.qml465
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/GridItem.qml105
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ItemTransformers.js237
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/LauncherContent.qml1075
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/LauncherContextMenu.qml510
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/NavigationHelpers.js254
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ResultItem.qml196
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ResultsList.qml498
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Scorer.js265
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Section.qml114
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/SectionHeader.qml340
-rw-r--r--raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/TileItem.qml199
15 files changed, 0 insertions, 6536 deletions
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ActionPanel.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ActionPanel.qml
deleted file mode 100644
index 31ada32..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ActionPanel.qml
+++ /dev/null
@@ -1,256 +0,0 @@
-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);
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Controller.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Controller.qml
deleted file mode 100644
index 67cb606..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Controller.qml
+++ /dev/null
@@ -1,1894 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import QtQuick
-import Quickshell
-import Quickshell.Io
-import qs.Common
-import qs.Services
-import "Scorer.js" as Scorer
-import "ControllerUtils.js" as Utils
-import "NavigationHelpers.js" as Nav
-import "ItemTransformers.js" as Transform
-
-Item {
- id: root
-
- property string searchQuery: ""
- property string searchMode: "all"
- property string previousSearchMode: "all"
- property bool autoSwitchedToFiles: false
- property bool isFileSearching: false
- property var sections: []
- property var flatModel: []
- property int selectedFlatIndex: 0
- property var selectedItem: null
- property bool isSearching: false
- property string activePluginId: ""
- property var collapsedSections: ({})
- property bool keyboardNavigationActive: false
- property bool active: false
- property var _modeSectionsCache: ({})
- property bool _queryDrivenSearch: false
- property bool _diskCacheConsumed: false
- property var sectionViewModes: ({})
- property var pluginViewPreferences: ({})
- property int gridColumns: SettingsData.appLauncherGridColumns
- property int viewModeVersion: 0
- property string viewModeContext: "spotlight"
-
- signal itemExecuted
- signal searchCompleted
- signal modeChanged(string mode)
- signal queryChanged(string query)
- signal viewModeChanged(string sectionId, string mode)
- signal searchQueryRequested(string query)
-
- onActiveChanged: {
- if (!active) {
- SessionData.addLauncherHistory(searchQuery);
-
- sections = [];
- flatModel = [];
- selectedItem = null;
- _clearModeCache();
- }
- }
-
- onSearchModeChanged: {
- if (searchMode === "apps") {
- _loadAppCategories();
- } else {
- appCategory = "";
- appCategories = [];
- }
- }
-
- Connections {
- target: SettingsData
- function onSortAppsAlphabeticallyChanged() {
- AppSearchService.invalidateLauncherCache();
- _clearModeCache();
- }
- }
-
- Connections {
- target: AppSearchService
- function onCacheVersionChanged() {
- if (!active)
- return;
- _clearModeCache();
- if (searchMode === "apps") {
- _loadAppCategories();
- performSearch();
- } else if (!searchQuery && searchMode === "all") {
- performSearch();
- }
- }
- }
-
- Connections {
- target: PluginService
- function onRequestLauncherUpdate(pluginId) {
- if (!active)
- return;
- if (activePluginId === pluginId) {
- if (activePluginCategories.length <= 1)
- loadPluginCategories(pluginId);
- performSearch();
- return;
- }
- if (searchQuery)
- performSearch();
- }
- }
-
- Process {
- id: wtypeProcess
- command: ["wtype", "-M", "ctrl", "-P", "v", "-p", "v", "-m", "ctrl"]
- running: false
- }
-
- Process {
- id: copyProcess
- running: false
- onExited: pasteTimer.start()
- }
-
- Timer {
- id: pasteTimer
- interval: 200
- repeat: false
- onTriggered: wtypeProcess.running = true
- }
-
- function pasteSelected() {
- if (!selectedItem)
- return;
- if (!SessionService.wtypeAvailable) {
- ToastService.showError("wtype not available - install wtype for paste support");
- return;
- }
-
- const pluginId = selectedItem.pluginId;
- if (!pluginId)
- return;
- const pasteArgs = AppSearchService.getPluginPasteArgs(pluginId, selectedItem.data);
- if (!pasteArgs)
- return;
- copyProcess.command = pasteArgs;
- copyProcess.running = true;
- itemExecuted();
- }
-
- readonly property var sectionDefinitions: [
- {
- id: "favorites",
- title: I18n.tr("Pinned"),
- icon: "push_pin",
- priority: 1,
- defaultViewMode: "list"
- },
- {
- id: "apps",
- title: I18n.tr("Applications"),
- icon: "apps",
- priority: 2,
- defaultViewMode: "list"
- },
- {
- id: "browse_plugins",
- title: I18n.tr("Browse"),
- icon: "category",
- priority: 2.5,
- defaultViewMode: "grid"
- },
- {
- id: "files",
- title: I18n.tr("Files"),
- icon: "folder",
- priority: 4,
- defaultViewMode: "list"
- },
- {
- id: "fallback",
- title: I18n.tr("Commands"),
- icon: "terminal",
- priority: 5,
- defaultViewMode: "list"
- }
- ]
-
- property int historyIndex: -1
- property string typingBackup: ""
-
- function navigateHistory(direction) {
- let history = SessionData.launcherQueryHistory;
- if (history.length === 0)
- return;
-
- if (historyIndex === -1)
- typingBackup = searchQuery;
-
- let nextIndex = historyIndex + (direction === "up" ? 1 : -1);
- if (nextIndex >= history.length)
- nextIndex = history.length - 1;
- if (nextIndex < -1)
- nextIndex = -1;
-
- if (nextIndex === historyIndex)
- return;
- historyIndex = nextIndex;
-
- let targetText = (historyIndex === -1) ? typingBackup : history[historyIndex];
-
- setSearchQuery(targetText);
- searchQueryRequested(targetText);
- }
-
- property string fileSearchType: "all"
- property string fileSearchExt: ""
- property string fileSearchFolder: ""
- property string fileSearchSort: "score"
-
- property string pluginFilter: ""
- property string activePluginName: ""
- property var activePluginCategories: []
- property string activePluginCategory: ""
- property string appCategory: ""
- property var appCategories: []
-
- function getSectionViewMode(sectionId) {
- if (sectionId === "browse_plugins")
- return "list";
- if (pluginViewPreferences[sectionId]?.enforced)
- return pluginViewPreferences[sectionId].mode;
- if (sectionViewModes[sectionId])
- return sectionViewModes[sectionId];
-
- var savedModes = viewModeContext === "appDrawer" ? (SettingsData.appDrawerSectionViewModes || {}) : (SettingsData.spotlightSectionViewModes || {});
- if (savedModes[sectionId])
- return savedModes[sectionId];
-
- for (var i = 0; i < sectionDefinitions.length; i++) {
- if (sectionDefinitions[i].id === sectionId)
- return sectionDefinitions[i].defaultViewMode || "list";
- }
-
- if (pluginViewPreferences[sectionId]?.mode)
- return pluginViewPreferences[sectionId].mode;
-
- return "list";
- }
-
- function setSectionViewMode(sectionId, mode) {
- if (sectionId === "browse_plugins")
- return;
- if (pluginViewPreferences[sectionId]?.enforced)
- return;
- sectionViewModes = Object.assign({}, sectionViewModes, {
- [sectionId]: mode
- });
- viewModeVersion++;
- if (viewModeContext === "appDrawer") {
- var savedModes = Object.assign({}, SettingsData.appDrawerSectionViewModes || {}, {
- [sectionId]: mode
- });
- SettingsData.appDrawerSectionViewModes = savedModes;
- } else {
- var savedModes = Object.assign({}, SettingsData.spotlightSectionViewModes || {}, {
- [sectionId]: mode
- });
- SettingsData.spotlightSectionViewModes = savedModes;
- }
- viewModeChanged(sectionId, mode);
- }
-
- function canChangeSectionViewMode(sectionId) {
- if (sectionId === "browse_plugins")
- return false;
- return !pluginViewPreferences[sectionId]?.enforced;
- }
-
- function canCollapseSection(sectionId) {
- return searchMode === "all";
- }
-
- function setPluginViewPreference(pluginId, mode, enforced) {
- var prefs = Object.assign({}, pluginViewPreferences);
- prefs[pluginId] = {
- mode: mode,
- enforced: enforced || false
- };
- pluginViewPreferences = prefs;
- }
-
- function applyActivePluginViewPreference(pluginId, isBuiltIn) {
- var sectionId = "plugin_" + pluginId;
- var pref = null;
- if (isBuiltIn) {
- var builtIn = AppSearchService.builtInPlugins[pluginId];
- if (builtIn && builtIn.viewMode) {
- pref = {
- mode: builtIn.viewMode,
- enforced: builtIn.viewModeEnforced === true
- };
- }
- } else {
- pref = PluginService.getPluginViewPreference(pluginId);
- }
-
- if (pref && pref.mode) {
- setPluginViewPreference(sectionId, pref.mode, pref.enforced);
- } else {
- var prefs = Object.assign({}, pluginViewPreferences);
- delete prefs[sectionId];
- pluginViewPreferences = prefs;
- }
- }
-
- function clearActivePluginViewPreference() {
- var prefs = {};
- for (var key in pluginViewPreferences) {
- if (!key.startsWith("plugin_")) {
- prefs[key] = pluginViewPreferences[key];
- }
- }
- pluginViewPreferences = prefs;
- }
-
- property int _searchVersion: 0
- property bool _pluginPhasePending: false
- property bool _pluginPhaseForceFirst: false
- property var _phase1Items: []
-
- Timer {
- id: searchDebounce
- interval: 60
- onTriggered: root.performSearch()
- }
-
- Timer {
- id: pluginPhaseTimer
- interval: 1
- onTriggered: root._performPluginPhase()
- }
-
- Timer {
- id: fileSearchDebounce
- interval: 200
- onTriggered: root.performFileSearch()
- }
-
- function getOrTransformApp(app) {
- return AppSearchService.getOrTransformApp(app, transformApp);
- }
-
- function setSearchQuery(query) {
- _searchVersion++;
- _queryDrivenSearch = true;
- _pluginPhasePending = false;
- _phase1Items = [];
- pluginPhaseTimer.stop();
- searchQuery = query;
- searchDebounce.restart();
-
- var filesInAll = searchMode === "all" && (SettingsData.dankLauncherV2IncludeFilesInAll || SettingsData.dankLauncherV2IncludeFoldersInAll);
- if (searchMode !== "plugins" && (searchMode === "files" || query.startsWith("/") || filesInAll) && query.length > 0) {
- fileSearchDebounce.restart();
- }
- }
-
- function setMode(mode, isAutoSwitch) {
- if (searchMode === mode)
- return;
- if (isAutoSwitch) {
- previousSearchMode = searchMode;
- autoSwitchedToFiles = true;
- } else {
- autoSwitchedToFiles = false;
- }
- searchMode = mode;
- modeChanged(mode);
- performSearch();
- var filesInAll = mode === "all" && (SettingsData.dankLauncherV2IncludeFilesInAll || SettingsData.dankLauncherV2IncludeFoldersInAll) && searchQuery.length > 0;
- if (mode === "files" || filesInAll) {
- fileSearchDebounce.restart();
- }
- }
-
- function restorePreviousMode() {
- if (!autoSwitchedToFiles)
- return;
- autoSwitchedToFiles = false;
- searchMode = previousSearchMode;
- modeChanged(previousSearchMode);
- performSearch();
- }
-
- function cycleMode(reverse = false) {
- var modes = ["all", "apps", "files", "plugins"];
- var currentIndex = modes.indexOf(searchMode);
- if (!reverse)
- var nextIndex = (currentIndex + 1) % modes.length;
- else
- var nextIndex = (currentIndex - 1 + modes.length) % modes.length;
- setMode(modes[nextIndex]);
- }
-
- function reset() {
- searchQuery = "";
- searchMode = "all";
- previousSearchMode = "all";
- autoSwitchedToFiles = false;
- isFileSearching = false;
- fileSearchType = "all";
- fileSearchExt = "";
- fileSearchFolder = "";
- fileSearchSort = "score";
- sections = [];
- flatModel = [];
- selectedFlatIndex = 0;
- selectedItem = null;
- isSearching = false;
- activePluginId = "";
- activePluginName = "";
- activePluginCategories = [];
- activePluginCategory = "";
- appCategory = "";
- appCategories = [];
- pluginFilter = "";
- collapsedSections = {};
- _clearModeCache();
- _queryDrivenSearch = false;
- _pluginPhasePending = false;
- _pluginPhaseForceFirst = false;
- _phase1Items = [];
- pluginPhaseTimer.stop();
- }
-
- function loadPluginCategories(pluginId) {
- if (!pluginId) {
- if (activePluginCategories.length > 0) {
- activePluginCategories = [];
- activePluginCategory = "";
- }
- return;
- }
-
- const categories = AppSearchService.getPluginLauncherCategories(pluginId);
- if (categories.length === activePluginCategories.length) {
- let same = true;
- for (let i = 0; i < categories.length; i++) {
- if (categories[i].id !== activePluginCategories[i]?.id) {
- same = false;
- break;
- }
- }
- if (same)
- return;
- }
- activePluginCategories = categories;
- activePluginCategory = "";
- AppSearchService.setPluginLauncherCategory(pluginId, "");
- }
-
- function setActivePluginCategory(categoryId) {
- if (activePluginCategory === categoryId)
- return;
- activePluginCategory = categoryId;
- AppSearchService.setPluginLauncherCategory(activePluginId, categoryId);
- performSearch();
- }
-
- function setAppCategory(category) {
- if (appCategory === category)
- return;
- appCategory = category;
- _queryDrivenSearch = true;
- _clearModeCache();
- performSearch();
- }
-
- function _loadAppCategories() {
- appCategories = AppSearchService.getAllCategories();
- }
-
- function setFileSearchType(type) {
- if (fileSearchType === type)
- return;
- fileSearchType = type;
- performFileSearch();
- }
-
- function setFileSearchExt(ext) {
- if (fileSearchExt === ext)
- return;
- fileSearchExt = ext;
- performFileSearch();
- }
-
- function setFileSearchFolder(folder) {
- if (fileSearchFolder === folder)
- return;
- fileSearchFolder = folder;
- performFileSearch();
- }
-
- function setFileSearchSort(sort) {
- if (fileSearchSort === sort)
- return;
- fileSearchSort = sort;
- performFileSearch();
- }
-
- function clearPluginFilter() {
- if (pluginFilter) {
- pluginFilter = "";
- performSearch();
- return true;
- }
- return false;
- }
-
- function preserveSelectionAfterUpdate(forceFirst) {
- if (forceFirst)
- return function () {
- return getFirstItemIndex();
- };
- var previousSelectedId = selectedItem?.id || "";
- return function (newFlatModel) {
- if (!previousSelectedId)
- return getFirstItemIndex();
- for (var i = 0; i < newFlatModel.length; i++) {
- if (!newFlatModel[i].isHeader && newFlatModel[i].item?.id === previousSelectedId)
- return i;
- }
- return getFirstItemIndex();
- };
- }
-
- function performSearch() {
- queryChanged(searchQuery);
-
- var currentVersion = _searchVersion;
- isSearching = true;
- var shouldResetSelection = _queryDrivenSearch;
- _queryDrivenSearch = false;
- var restoreSelection = preserveSelectionAfterUpdate(shouldResetSelection);
-
- var cachedSections = AppSearchService.getCachedDefaultSections();
- if (!cachedSections && !_diskCacheConsumed && !searchQuery && searchMode === "all" && !pluginFilter) {
- _diskCacheConsumed = true;
- var diskSections = _loadDiskCache();
- if (diskSections) {
- activePluginId = "";
- activePluginName = "";
- activePluginCategories = [];
- activePluginCategory = "";
- clearActivePluginViewPreference();
- for (var i = 0; i < diskSections.length; i++) {
- if (collapsedSections[diskSections[i].id] !== undefined)
- diskSections[i].collapsed = collapsedSections[diskSections[i].id];
- }
- _applyHighlights(diskSections, "");
- flatModel = Scorer.flattenSections(diskSections);
- sections = diskSections;
- selectedFlatIndex = restoreSelection(flatModel);
- updateSelectedItem();
- isSearching = false;
- searchCompleted();
- return;
- }
- }
-
- if (cachedSections && !searchQuery && searchMode === "all" && !pluginFilter) {
- activePluginId = "";
- activePluginName = "";
- activePluginCategories = [];
- activePluginCategory = "";
- clearActivePluginViewPreference();
- var modeCache = _getCachedModeData("all");
- if (modeCache) {
- _applyHighlights(modeCache.sections, "");
- sections = modeCache.sections;
- flatModel = modeCache.flatModel;
- } else {
- var newSections = cachedSections.map(function (s) {
- var copy = Object.assign({}, s, {
- items: s.items ? s.items.slice() : []
- });
- if (collapsedSections[s.id] !== undefined)
- copy.collapsed = collapsedSections[s.id];
- return copy;
- });
- _applyHighlights(newSections, "");
- flatModel = Scorer.flattenSections(newSections);
- sections = newSections;
- _setCachedModeData("all", sections, flatModel);
- }
- selectedFlatIndex = restoreSelection(flatModel);
- updateSelectedItem();
- isSearching = false;
- searchCompleted();
- return;
- }
-
- var allItems = [];
-
- var triggerMatch = detectTrigger(searchQuery);
- if (triggerMatch.pluginId) {
- var pluginChanged = activePluginId !== triggerMatch.pluginId;
- activePluginId = triggerMatch.pluginId;
- activePluginName = getPluginName(triggerMatch.pluginId, triggerMatch.isBuiltIn);
- applyActivePluginViewPreference(triggerMatch.pluginId, triggerMatch.isBuiltIn);
-
- if (pluginChanged && !triggerMatch.isBuiltIn)
- loadPluginCategories(triggerMatch.pluginId);
-
- var pluginItems = getPluginItems(triggerMatch.pluginId, triggerMatch.query);
- for (var k = 0; k < pluginItems.length; k++)
- allItems.push(pluginItems[k]);
-
- if (triggerMatch.isBuiltIn) {
- var builtInItems = AppSearchService.getBuiltInLauncherItems(triggerMatch.pluginId, triggerMatch.query);
- for (var j = 0; j < builtInItems.length; j++) {
- allItems.push(transformBuiltInLauncherItem(builtInItems[j], triggerMatch.pluginId));
- }
- }
-
- var dynamicDefs = buildDynamicSectionDefs(allItems);
- var scoredItems = Scorer.scoreItems(allItems, triggerMatch.query, getFrecencyForItem);
- var sortAlpha = !triggerMatch.query && SettingsData.sortAppsAlphabetically;
- var newSections = Scorer.groupBySection(scoredItems, dynamicDefs, sortAlpha, 500);
-
- for (var sid in collapsedSections) {
- for (var i = 0; i < newSections.length; i++) {
- if (newSections[i].id === sid) {
- newSections[i].collapsed = collapsedSections[sid];
- }
- }
- }
-
- _applyHighlights(newSections, triggerMatch.query);
- flatModel = Scorer.flattenSections(newSections);
- sections = newSections;
- selectedFlatIndex = restoreSelection(flatModel);
- updateSelectedItem();
-
- isSearching = false;
- searchCompleted();
- return;
- }
-
- activePluginId = "";
- activePluginName = "";
- activePluginCategories = [];
- activePluginCategory = "";
- clearActivePluginViewPreference();
-
- if (searchMode === "files") {
- var fileQuery = searchQuery.startsWith("/") ? searchQuery.substring(1).trim() : searchQuery.trim();
- isFileSearching = fileQuery.length >= 2 && DSearchService.dsearchAvailable;
- sections = [];
- flatModel = [];
- selectedFlatIndex = 0;
- selectedItem = null;
- isSearching = false;
- searchCompleted();
- return;
- }
-
- if (searchMode === "apps") {
- var isCategoryFiltered = appCategory && appCategory !== I18n.tr("All");
- var cachedSections = AppSearchService.getCachedDefaultSections();
- if (cachedSections && !searchQuery && !isCategoryFiltered) {
- var modeCache = _getCachedModeData("apps");
- if (modeCache) {
- _applyHighlights(modeCache.sections, "");
- sections = modeCache.sections;
- flatModel = modeCache.flatModel;
- } else {
- var appSectionIds = ["favorites", "apps"];
- var newSections = cachedSections.filter(function (s) {
- return appSectionIds.indexOf(s.id) !== -1;
- }).map(function (s) {
- var copy = Object.assign({}, s, {
- items: s.items ? s.items.slice() : []
- });
- if (collapsedSections[s.id] !== undefined)
- copy.collapsed = collapsedSections[s.id];
- return copy;
- });
- _applyHighlights(newSections, "");
- flatModel = Scorer.flattenSections(newSections);
- sections = newSections;
- _setCachedModeData("apps", sections, flatModel);
- }
- selectedFlatIndex = restoreSelection(flatModel);
- updateSelectedItem();
- isSearching = false;
- searchCompleted();
- return;
- }
-
- if (isCategoryFiltered) {
- var rawApps = AppSearchService.getAppsInCategory(appCategory);
- for (var i = 0; i < rawApps.length; i++) {
- allItems.push(getOrTransformApp(rawApps[i]));
- }
- // Also include core apps (DMS Settings etc.) that match this category
- var allCoreApps = AppSearchService.getCoreApps("");
- for (var i = 0; i < allCoreApps.length; i++) {
- var coreAppCats = AppSearchService.getCategoriesForApp(allCoreApps[i]);
- if (coreAppCats.indexOf(appCategory) !== -1)
- allItems.push(transformCoreApp(allCoreApps[i]));
- }
- } else {
- var apps = searchApps(searchQuery);
- for (var i = 0; i < apps.length; i++) {
- allItems.push(apps[i]);
- }
- }
-
- var scoredItems = Scorer.scoreItems(allItems, searchQuery, getFrecencyForItem);
- var sortAlpha = !searchQuery && SettingsData.sortAppsAlphabetically;
- var newSections = Scorer.groupBySection(scoredItems, sectionDefinitions, sortAlpha, searchQuery ? 50 : 500);
-
- for (var sid in collapsedSections) {
- for (var i = 0; i < newSections.length; i++) {
- if (newSections[i].id === sid) {
- newSections[i].collapsed = collapsedSections[sid];
- }
- }
- }
-
- _applyHighlights(newSections, searchQuery);
- flatModel = Scorer.flattenSections(newSections);
- sections = newSections;
- selectedFlatIndex = restoreSelection(flatModel);
- updateSelectedItem();
-
- isSearching = false;
- searchCompleted();
- return;
- }
-
- if (searchMode === "plugins") {
- if (!searchQuery && !pluginFilter) {
- var browseItems = getPluginBrowseItems();
- for (var k = 0; k < browseItems.length; k++)
- allItems.push(browseItems[k]);
- } else if (pluginFilter) {
- var isBuiltInFilter = !!AppSearchService.builtInPlugins[pluginFilter];
- applyActivePluginViewPreference(pluginFilter, isBuiltInFilter);
-
- var filterItems = getPluginItems(pluginFilter, searchQuery);
- for (var k = 0; k < filterItems.length; k++)
- allItems.push(filterItems[k]);
-
- var builtInItems = AppSearchService.getBuiltInLauncherItems(pluginFilter, searchQuery);
- for (var j = 0; j < builtInItems.length; j++) {
- allItems.push(transformBuiltInLauncherItem(builtInItems[j], pluginFilter));
- }
- } else {
- var emptyTriggerPlugins = getEmptyTriggerPlugins();
- for (var i = 0; i < emptyTriggerPlugins.length; i++) {
- var pluginId = emptyTriggerPlugins[i];
- var pItems = getPluginItems(pluginId, searchQuery);
- for (var k = 0; k < pItems.length; k++)
- allItems.push(pItems[k]);
- }
-
- var builtInLauncherPlugins = getBuiltInEmptyTriggerLaunchers();
- for (var i = 0; i < builtInLauncherPlugins.length; i++) {
- var pluginId = builtInLauncherPlugins[i];
- var blItems = AppSearchService.getBuiltInLauncherItems(pluginId, searchQuery);
- for (var j = 0; j < blItems.length; j++) {
- allItems.push(transformBuiltInLauncherItem(blItems[j], pluginId));
- }
- }
- }
-
- var dynamicDefs = buildDynamicSectionDefs(allItems);
- var scoredItems = Scorer.scoreItems(allItems, searchQuery, getFrecencyForItem);
- var sortAlpha = !searchQuery && SettingsData.sortAppsAlphabetically;
- var newSections = Scorer.groupBySection(scoredItems, dynamicDefs, sortAlpha, 500);
-
- for (var sid in collapsedSections) {
- for (var i = 0; i < newSections.length; i++) {
- if (newSections[i].id === sid) {
- newSections[i].collapsed = collapsedSections[sid];
- }
- }
- }
-
- _applyHighlights(newSections, searchQuery);
- flatModel = Scorer.flattenSections(newSections);
- sections = newSections;
- selectedFlatIndex = restoreSelection(flatModel);
- updateSelectedItem();
-
- isSearching = false;
- searchCompleted();
- return;
- }
-
- var apps = searchApps(searchQuery);
- for (var i = 0; i < apps.length; i++) {
- allItems.push(apps[i]);
- }
-
- if (searchMode === "all") {
- if (searchQuery && searchQuery.length >= 2) {
- _pluginPhasePending = true;
- _phase1Items = allItems.slice();
- _pluginPhaseForceFirst = shouldResetSelection;
- pluginPhaseTimer.restart();
- isSearching = true;
- searchCompleted();
- return;
- } else if (!searchQuery) {
- var emptyTriggerOrdered = getEmptyTriggerPluginsOrdered();
- for (var i = 0; i < emptyTriggerOrdered.length; i++) {
- var plugin = emptyTriggerOrdered[i];
- if (plugin.isBuiltIn) {
- var blItems = AppSearchService.getBuiltInLauncherItems(plugin.id, searchQuery);
- for (var j = 0; j < blItems.length; j++)
- allItems.push(transformBuiltInLauncherItem(blItems[j], plugin.id));
- } else {
- var pItems = getPluginItems(plugin.id, searchQuery);
- for (var j = 0; j < pItems.length; j++)
- allItems.push(pItems[j]);
- }
- }
-
- var browseItems = getPluginBrowseItems();
- for (var i = 0; i < browseItems.length; i++)
- allItems.push(browseItems[i]);
- }
- }
-
- var dynamicDefs = buildDynamicSectionDefs(allItems);
-
- if (currentVersion !== _searchVersion) {
- isSearching = false;
- return;
- }
-
- var scoredItems = Scorer.scoreItems(allItems, searchQuery, getFrecencyForItem);
- var sortAlpha = !searchQuery && SettingsData.sortAppsAlphabetically;
- var newSections = Scorer.groupBySection(scoredItems, dynamicDefs, sortAlpha, searchQuery ? 50 : 500);
-
- if (currentVersion !== _searchVersion) {
- isSearching = false;
- return;
- }
-
- for (var i = 0; i < newSections.length; i++) {
- var sid = newSections[i].id;
- if (collapsedSections[sid] !== undefined) {
- newSections[i].collapsed = collapsedSections[sid];
- }
- }
-
- _applyHighlights(newSections, searchQuery);
- flatModel = Scorer.flattenSections(newSections);
- sections = newSections;
-
- if (!AppSearchService.isCacheValid() && !searchQuery && searchMode === "all" && !pluginFilter) {
- AppSearchService.setCachedDefaultSections(sections, flatModel);
- _saveDiskCache(sections);
- }
-
- selectedFlatIndex = restoreSelection(flatModel);
- updateSelectedItem();
-
- isSearching = _pluginPhasePending;
- searchCompleted();
- }
-
- function _performPluginPhase() {
- _pluginPhasePending = false;
- if (!searchQuery || searchQuery.length < 2 || searchMode !== "all")
- return;
-
- var currentVersion = _searchVersion;
- var restoreSelection = preserveSelectionAfterUpdate(_pluginPhaseForceFirst);
- var allItems = _phase1Items;
- _phase1Items = [];
-
- var allPluginsOrdered = getAllVisiblePluginsOrdered();
- var maxPerPlugin = 10;
- for (var i = 0; i < allPluginsOrdered.length; i++) {
- if (currentVersion !== _searchVersion)
- return;
- var plugin = allPluginsOrdered[i];
- if (plugin.isBuiltIn) {
- var blItems = AppSearchService.getBuiltInLauncherItems(plugin.id, searchQuery);
- var blLimit = Math.min(blItems.length, maxPerPlugin);
- for (var j = 0; j < blLimit; j++) {
- var item = transformBuiltInLauncherItem(blItems[j], plugin.id);
- item._preScored = 900 - j;
- allItems.push(item);
- }
- } else {
- var pItems = getPluginItems(plugin.id, searchQuery, maxPerPlugin);
- for (var j = 0; j < pItems.length; j++) {
- pItems[j]._preScored = 900 - j;
- allItems.push(pItems[j]);
- }
- }
- }
-
- if (currentVersion !== _searchVersion)
- return;
-
- var dynamicDefs = buildDynamicSectionDefs(allItems);
- var scoredItems = Scorer.scoreItems(allItems, searchQuery, getFrecencyForItem);
- var newSections = Scorer.groupBySection(scoredItems, dynamicDefs, false, 50);
-
- if (currentVersion !== _searchVersion)
- return;
-
- for (var i = 0; i < newSections.length; i++) {
- var sid = newSections[i].id;
- if (collapsedSections[sid] !== undefined)
- newSections[i].collapsed = collapsedSections[sid];
- }
-
- _applyHighlights(newSections, searchQuery);
- flatModel = Scorer.flattenSections(newSections);
- sections = newSections;
- selectedFlatIndex = restoreSelection(flatModel);
- updateSelectedItem();
- isSearching = false;
- searchCompleted();
- }
-
- function performFileSearch() {
- if (!DSearchService.dsearchAvailable)
- return;
- var fileQuery = "";
- var effectiveType = fileSearchType || "all";
- var includeFiles = SettingsData.dankLauncherV2IncludeFilesInAll;
- var includeFolders = SettingsData.dankLauncherV2IncludeFoldersInAll;
-
- if (searchQuery.startsWith("/")) {
- fileQuery = searchQuery.substring(1).trim();
- } else if (searchMode === "files") {
- fileQuery = searchQuery.trim();
- } else if (searchMode === "all" && (includeFiles || includeFolders)) {
- fileQuery = searchQuery.trim();
- if (includeFiles && !includeFolders)
- effectiveType = "file";
- else if (!includeFiles && includeFolders)
- effectiveType = "dir";
- else
- effectiveType = "all";
- } else {
- return;
- }
-
- if (fileQuery.length < 2) {
- isFileSearching = false;
- return;
- }
-
- isFileSearching = true;
-
- var splitBothTypes = searchMode === "all" && includeFiles && includeFolders && DSearchService.supportsTypeFilter;
- var queryTypes = splitBothTypes ? ["file", "dir"] : [effectiveType];
- var pending = queryTypes.length;
- var aggregatedItems = [];
-
- for (var t = 0; t < queryTypes.length; t++) {
- var queryType = queryTypes[t];
- var params = {
- limit: 20,
- fuzzy: true,
- sort: fileSearchSort || "score",
- desc: true
- };
-
- if (DSearchService.supportsTypeFilter) {
- params.type = (queryType && queryType !== "all") ? queryType : "all";
- }
- if (fileSearchExt) {
- params.ext = fileSearchExt;
- }
- if (fileSearchFolder) {
- params.folder = fileSearchFolder;
- }
-
- DSearchService.search(fileQuery, params, function (response) {
- pending--;
- if (!response.error) {
- var hits = response.result?.hits || [];
- for (var i = 0; i < hits.length; i++) {
- var hit = hits[i];
- var docTypes = hit.locations?.doc_type;
- var isDir = docTypes ? !!docTypes["dir"] : false;
- aggregatedItems.push(transformFileResult({
- path: hit.id || "",
- score: hit.score || 0,
- is_dir: isDir
- }));
- }
- }
- if (pending > 0)
- return;
-
- isFileSearching = false;
- _applyFileSearchResults(aggregatedItems, effectiveType);
- });
- }
- }
-
- function _applyFileSearchResults(fileItems, effectiveType) {
- var fileSections = [];
- var showType = effectiveType;
- var order = SettingsData.launcherPluginOrder || [];
- var filesOrderIdx = order.indexOf("__files");
- var foldersOrderIdx = order.indexOf("__folders");
- var filesPriority = filesOrderIdx !== -1 ? 2.6 + filesOrderIdx * 0.01 : 4;
- var foldersPriority = foldersOrderIdx !== -1 ? 2.6 + foldersOrderIdx * 0.01 : 4.1;
-
- if (showType === "all" && DSearchService.supportsTypeFilter) {
- var onlyFiles = [];
- var onlyDirs = [];
- for (var j = 0; j < fileItems.length; j++) {
- if (fileItems[j].data?.is_dir)
- onlyDirs.push(fileItems[j]);
- else
- onlyFiles.push(fileItems[j]);
- }
- if (onlyFiles.length > 0) {
- fileSections.push({
- id: "files",
- title: I18n.tr("Files"),
- icon: "insert_drive_file",
- priority: filesPriority,
- items: onlyFiles,
- collapsed: collapsedSections["files"] || false,
- flatStartIndex: 0
- });
- }
- if (onlyDirs.length > 0) {
- fileSections.push({
- id: "folders",
- title: I18n.tr("Folders"),
- icon: "folder",
- priority: foldersPriority,
- items: onlyDirs,
- collapsed: collapsedSections["folders"] || false,
- flatStartIndex: 0
- });
- }
- } else {
- var filesIcon = showType === "dir" ? "folder" : showType === "file" ? "insert_drive_file" : "folder";
- var filesTitle = showType === "dir" ? I18n.tr("Folders") : I18n.tr("Files");
- var singlePriority = showType === "dir" ? foldersPriority : filesPriority;
- if (fileItems.length > 0) {
- fileSections.push({
- id: "files",
- title: filesTitle,
- icon: filesIcon,
- priority: singlePriority,
- items: fileItems,
- collapsed: collapsedSections["files"] || false,
- flatStartIndex: 0
- });
- }
- }
-
- var newSections;
- if (searchMode === "files") {
- newSections = fileSections;
- } else {
- var existingNonFile = sections.filter(function (s) {
- return s.id !== "files" && s.id !== "folders";
- });
- newSections = existingNonFile.concat(fileSections);
- }
- newSections.sort(function (a, b) {
- return a.priority - b.priority;
- });
- _applyHighlights(newSections, searchQuery);
- flatModel = Scorer.flattenSections(newSections);
- sections = newSections;
- selectedFlatIndex = getFirstItemIndex();
- updateSelectedItem();
- }
-
- function searchApps(query) {
- var apps = AppSearchService.searchApplications(query);
- var items = [];
-
- for (var i = 0; i < apps.length; i++) {
- items.push(getOrTransformApp(apps[i]));
- }
-
- var coreApps = AppSearchService.getCoreApps(query);
- for (var i = 0; i < coreApps.length; i++) {
- items.push(transformCoreApp(coreApps[i]));
- }
-
- return items;
- }
-
- function transformApp(app) {
- var appId = app.id || app.execString || app.exec || "";
- var override = SessionData.getAppOverride(appId);
- return Transform.transformApp(app, override, [], I18n.tr("Launch"));
- }
-
- function transformCoreApp(app) {
- return Transform.transformCoreApp(app, I18n.tr("Open"));
- }
-
- function transformBuiltInLauncherItem(item, pluginId) {
- return Transform.transformBuiltInLauncherItem(item, pluginId, I18n.tr("Open"));
- }
-
- function transformFileResult(file) {
- return Transform.transformFileResult(file, I18n.tr("Open"), I18n.tr("Open folder"), I18n.tr("Copy path"), I18n.tr("Open in terminal"));
- }
-
- function detectTrigger(query) {
- if (!query || query.length === 0)
- return {
- pluginId: null,
- query: query
- };
-
- var pluginTriggers = PluginService.getAllPluginTriggers();
- for (var trigger in pluginTriggers) {
- if (trigger && query.startsWith(trigger)) {
- return {
- pluginId: pluginTriggers[trigger],
- query: query.substring(trigger.length).trim()
- };
- }
- }
-
- var builtInTriggers = AppSearchService.getBuiltInLauncherTriggers();
- for (var trigger in builtInTriggers) {
- if (trigger && query.startsWith(trigger)) {
- return {
- pluginId: builtInTriggers[trigger],
- query: query.substring(trigger.length).trim(),
- isBuiltIn: true
- };
- }
- }
-
- return {
- pluginId: null,
- query: query
- };
- }
-
- function getEmptyTriggerPlugins() {
- var plugins = PluginService.getPluginsWithEmptyTrigger();
- var visible = plugins.filter(function (pluginId) {
- return SettingsData.getPluginAllowWithoutTrigger(pluginId);
- });
- return sortPluginIdsByOrder(visible);
- }
-
- function getAllLauncherPluginIds() {
- var launchers = PluginService.getLauncherPlugins();
- return Object.keys(launchers);
- }
-
- function getVisibleLauncherPluginIds() {
- var launchers = PluginService.getLauncherPlugins();
- var visible = Object.keys(launchers).filter(function (pluginId) {
- return SettingsData.getPluginAllowWithoutTrigger(pluginId);
- });
- return sortPluginIdsByOrder(visible);
- }
-
- function getAllBuiltInLauncherIds() {
- var launchers = AppSearchService.getBuiltInLauncherPlugins();
- return Object.keys(launchers);
- }
-
- function getVisibleBuiltInLauncherIds() {
- var launchers = AppSearchService.getBuiltInLauncherPlugins();
- var visible = Object.keys(launchers).filter(function (pluginId) {
- return SettingsData.getPluginAllowWithoutTrigger(pluginId);
- });
- return sortPluginIdsByOrder(visible);
- }
-
- function sortPluginIdsByOrder(pluginIds) {
- return Utils.sortPluginIdsByOrder(pluginIds, SettingsData.launcherPluginOrder || []);
- }
-
- function getAllVisiblePluginsOrdered() {
- var thirdPartyLaunchers = PluginService.getLauncherPlugins() || {};
- var builtInLaunchers = AppSearchService.getBuiltInLauncherPlugins() || {};
- var all = [];
- for (var id in thirdPartyLaunchers) {
- if (SettingsData.getPluginAllowWithoutTrigger(id))
- all.push({
- id: id,
- isBuiltIn: false
- });
- }
- for (var id in builtInLaunchers) {
- if (SettingsData.getPluginAllowWithoutTrigger(id))
- all.push({
- id: id,
- isBuiltIn: true
- });
- }
- return Utils.sortPluginsOrdered(all, SettingsData.launcherPluginOrder || []);
- }
-
- function getEmptyTriggerPluginsOrdered() {
- var thirdParty = PluginService.getPluginsWithEmptyTrigger() || [];
- var builtIn = AppSearchService.getBuiltInLauncherPluginsWithEmptyTrigger() || [];
- var all = [];
- for (var i = 0; i < thirdParty.length; i++) {
- var id = thirdParty[i];
- if (SettingsData.getPluginAllowWithoutTrigger(id))
- all.push({
- id: id,
- isBuiltIn: false
- });
- }
- for (var i = 0; i < builtIn.length; i++) {
- var id = builtIn[i];
- if (SettingsData.getPluginAllowWithoutTrigger(id))
- all.push({
- id: id,
- isBuiltIn: true
- });
- }
- return Utils.sortPluginsOrdered(all, SettingsData.launcherPluginOrder || []);
- }
-
- function getPluginBrowseItems() {
- var items = [];
- var browseLabel = I18n.tr("Browse");
- var triggerLabel = I18n.tr("Trigger: %1");
- var noTriggerLabel = I18n.tr("No trigger");
-
- var launchers = PluginService.getLauncherPlugins();
- for (var pluginId in launchers) {
- var trigger = PluginService.getPluginTrigger(pluginId);
- var isAllowed = SettingsData.getPluginAllowWithoutTrigger(pluginId);
- items.push(Transform.createPluginBrowseItem(pluginId, launchers[pluginId], trigger, false, isAllowed, browseLabel, triggerLabel, noTriggerLabel));
- }
-
- var builtInLaunchers = AppSearchService.getBuiltInLauncherPlugins();
- for (var pluginId in builtInLaunchers) {
- var trigger = AppSearchService.getBuiltInPluginTrigger(pluginId);
- var isAllowed = SettingsData.getPluginAllowWithoutTrigger(pluginId);
- items.push(Transform.createPluginBrowseItem(pluginId, builtInLaunchers[pluginId], trigger, true, isAllowed, browseLabel, triggerLabel, noTriggerLabel));
- }
-
- return items;
- }
-
- function getBuiltInEmptyTriggerLaunchers() {
- var plugins = AppSearchService.getBuiltInLauncherPluginsWithEmptyTrigger();
- var visible = plugins.filter(function (pluginId) {
- return SettingsData.getPluginAllowWithoutTrigger(pluginId);
- });
- return sortPluginIdsByOrder(visible);
- }
-
- function getPluginItems(pluginId, query, limit) {
- var items = AppSearchService.getPluginItemsForPlugin(pluginId, query);
- var count = limit > 0 && limit < items.length ? limit : items.length;
- var transformed = [];
-
- for (var i = 0; i < count; i++) {
- transformed.push(transformPluginItem(items[i], pluginId));
- }
-
- return transformed;
- }
-
- function getPluginName(pluginId, isBuiltIn) {
- if (isBuiltIn) {
- var plugin = AppSearchService.builtInPlugins[pluginId];
- return plugin ? plugin.name : pluginId;
- }
- var launchers = PluginService.getLauncherPlugins();
- if (launchers[pluginId]) {
- return launchers[pluginId].name || pluginId;
- }
- return pluginId;
- }
-
- function getPluginMetadata(pluginId) {
- var builtIn = AppSearchService.builtInPlugins[pluginId];
- if (builtIn) {
- return {
- name: builtIn.name || pluginId,
- icon: builtIn.cornerIcon || "extension"
- };
- }
- var launchers = PluginService.getLauncherPlugins();
- if (launchers[pluginId]) {
- var rawIcon = launchers[pluginId].icon || "extension";
- return {
- name: launchers[pluginId].name || pluginId,
- icon: Utils.stripIconPrefix(rawIcon)
- };
- }
- return {
- name: pluginId,
- icon: "extension"
- };
- }
-
- function buildDynamicSectionDefs(items) {
- var baseDefs = sectionDefinitions.slice();
- var pluginSections = {};
- var order = SettingsData.launcherPluginOrder || [];
- var orderMap = {};
- for (var k = 0; k < order.length; k++)
- orderMap[order[k]] = k;
- var unorderedPriority = 2.6 + order.length * 0.01;
-
- for (var i = 0; i < items.length; i++) {
- var section = items[i].section;
- if (!section || !section.startsWith("plugin_"))
- continue;
- if (pluginSections[section])
- continue;
- var pluginId = section.substring(7);
- var meta = getPluginMetadata(pluginId);
- var viewPref = getPluginViewPref(pluginId);
- var orderIdx = orderMap[pluginId];
- var priority;
- if (orderIdx !== undefined) {
- priority = 2.6 + orderIdx * 0.01;
- } else {
- priority = unorderedPriority;
- unorderedPriority += 0.01;
- }
-
- pluginSections[section] = {
- id: section,
- title: meta.name,
- icon: meta.icon,
- priority: priority,
- defaultViewMode: viewPref.mode || "list"
- };
-
- if (viewPref.mode)
- setPluginViewPreference(section, viewPref.mode, viewPref.enforced);
- }
-
- for (var sectionId in pluginSections) {
- baseDefs.push(pluginSections[sectionId]);
- }
-
- baseDefs.sort(function (a, b) {
- return a.priority - b.priority;
- });
- return baseDefs;
- }
-
- function getPluginViewPref(pluginId) {
- var builtIn = AppSearchService.builtInPlugins[pluginId];
- if (builtIn && builtIn.viewMode) {
- return {
- mode: builtIn.viewMode,
- enforced: builtIn.viewModeEnforced === true
- };
- }
-
- var pref = PluginService.getPluginViewPreference(pluginId);
- if (pref && pref.mode) {
- return pref;
- }
-
- return {
- mode: "list",
- enforced: false
- };
- }
-
- function transformPluginItem(item, pluginId) {
- return Transform.transformPluginItem(item, pluginId, I18n.tr("Select"));
- }
-
- function getFrecencyForItem(item) {
- if (item.type !== "app")
- return null;
-
- var appId = item.id;
- var usageRanking = AppUsageHistoryData.appUsageRanking || {};
-
- var idVariants = [appId, appId.replace(".desktop", "")];
- var usageData = null;
-
- for (var i = 0; i < idVariants.length; i++) {
- if (usageRanking[idVariants[i]]) {
- usageData = usageRanking[idVariants[i]];
- break;
- }
- }
-
- return {
- usageCount: usageData?.usageCount || 0
- };
- }
-
- function getFirstItemIndex() {
- return Nav.getFirstItemIndex(flatModel);
- }
-
- function _getCachedModeData(mode) {
- return _modeSectionsCache[mode] || null;
- }
-
- function _setCachedModeData(mode, sectionsData, flatModelData) {
- var cache = Object.assign({}, _modeSectionsCache);
- cache[mode] = {
- sections: sectionsData,
- flatModel: flatModelData
- };
- _modeSectionsCache = cache;
- }
-
- function _clearModeCache() {
- _modeSectionsCache = {};
- }
-
- function _saveDiskCache(sectionsData) {
- var serializable = [];
- for (var i = 0; i < sectionsData.length; i++) {
- var s = sectionsData[i];
- var items = [];
- var srcItems = s.items || [];
- for (var j = 0; j < srcItems.length; j++) {
- var it = srcItems[j];
- items.push({
- id: it.id,
- type: it.type,
- name: it.name || "",
- subtitle: it.subtitle || "",
- icon: it.icon || "",
- iconType: it.iconType || "image",
- iconFull: it.iconFull || "",
- section: it.section || "",
- isCore: it.isCore || false,
- isBuiltInLauncher: it.isBuiltInLauncher || false,
- pluginId: it.pluginId || ""
- });
- }
- serializable.push({
- id: s.id,
- title: s.title || "",
- icon: s.icon || "",
- priority: s.priority || 0,
- items: items
- });
- }
- CacheData.saveLauncherCache(serializable);
- }
-
- function _actionsFromDesktopEntry(appId) {
- if (!appId)
- return [];
- var entry = DesktopEntries.heuristicLookup(appId);
- if (!entry || !entry.actions || entry.actions.length === 0)
- return [];
- var result = [];
- for (var i = 0; i < entry.actions.length; i++) {
- result.push({
- name: entry.actions[i].name,
- icon: "play_arrow",
- actionData: entry.actions[i]
- });
- }
- return result;
- }
-
- function _loadDiskCache() {
- var cached = CacheData.loadLauncherCache();
- if (!cached || !Array.isArray(cached) || cached.length === 0)
- return null;
-
- var sectionsData = [];
- for (var i = 0; i < cached.length; i++) {
- var s = cached[i];
- var items = [];
- var srcItems = s.items || [];
- for (var j = 0; j < srcItems.length; j++) {
- var it = srcItems[j];
- items.push({
- id: it.id || "",
- type: it.type || "app",
- name: it.name || "",
- subtitle: it.subtitle || "",
- icon: it.icon || "",
- iconType: it.iconType || "image",
- iconFull: it.iconFull || "",
- section: it.section || "",
- isCore: it.isCore || false,
- isBuiltInLauncher: it.isBuiltInLauncher || false,
- pluginId: it.pluginId || "",
- data: {
- id: it.id
- },
- actions: _actionsFromDesktopEntry(it.id),
- primaryAction: it.type === "app" && !it.isCore ? {
- name: I18n.tr("Launch"),
- icon: "open_in_new",
- action: "launch"
- } : null,
- _diskCached: true,
- _hName: "",
- _hSub: "",
- _hRich: false,
- _preScored: undefined
- });
- }
- sectionsData.push({
- id: s.id || "",
- title: s.title || "",
- icon: s.icon || "",
- priority: s.priority || 0,
- items: items,
- collapsed: false,
- flatStartIndex: 0
- });
- }
- return sectionsData;
- }
-
- function updateSelectedItem() {
- if (selectedFlatIndex >= 0 && selectedFlatIndex < flatModel.length) {
- var entry = flatModel[selectedFlatIndex];
- selectedItem = entry.isHeader ? null : entry.item;
- } else {
- selectedItem = null;
- }
- }
-
- function _applyHighlights(sectionsData, query) {
- if (!query || query.length === 0) {
- for (var i = 0; i < sectionsData.length; i++) {
- var items = sectionsData[i].items;
- for (var j = 0; j < items.length; j++) {
- var item = items[j];
- item._hName = item.name || "";
- item._hSub = item.subtitle || "";
- item._hRich = false;
- }
- }
- return;
- }
-
- var highlightColor = Theme.primary;
- var nameColor = Theme.surfaceText;
- var subColor = Theme.surfaceVariantText;
- var lowerQuery = query.toLowerCase();
-
- for (var i = 0; i < sectionsData.length; i++) {
- var items = sectionsData[i].items;
- for (var j = 0; j < items.length; j++) {
- var item = items[j];
- item._hName = _highlightField(item.name || "", lowerQuery, query.length, nameColor, highlightColor);
- item._hSub = _highlightField(item.subtitle || "", lowerQuery, query.length, subColor, highlightColor);
- item._hRich = true;
- }
- }
- }
-
- function _highlightField(text, lowerQuery, queryLen, baseColor, highlightColor) {
- if (!text)
- return "";
- var idx = text.toLowerCase().indexOf(lowerQuery);
- if (idx === -1)
- return text;
- var before = text.substring(0, idx);
- var match = text.substring(idx, idx + queryLen);
- var after = text.substring(idx + queryLen);
- return '<span style="color:' + baseColor + '">' + before + '</span><span style="color:' + highlightColor + '; font-weight:600">' + match + '</span><span style="color:' + baseColor + '">' + after + '</span>';
- }
-
- function getCurrentSectionViewMode() {
- if (selectedFlatIndex < 0 || selectedFlatIndex >= flatModel.length)
- return "list";
- var entry = flatModel[selectedFlatIndex];
- if (!entry || entry.isHeader)
- return "list";
- return getSectionViewMode(entry.sectionId);
- }
-
- function getGridColumns(sectionId) {
- return Nav.getGridColumns(getSectionViewMode(sectionId), gridColumns);
- }
-
- function _cancelPendingSelectionReset() {
- _queryDrivenSearch = false;
- _pluginPhaseForceFirst = false;
- }
-
- function selectNext() {
- keyboardNavigationActive = true;
- _cancelPendingSelectionReset();
- var newIndex = Nav.calculateNextIndex(flatModel, selectedFlatIndex, null, null, gridColumns, getSectionViewMode);
- if (newIndex !== selectedFlatIndex) {
- selectedFlatIndex = newIndex;
- updateSelectedItem();
- }
- }
-
- function selectPrevious() {
- keyboardNavigationActive = true;
- _cancelPendingSelectionReset();
- var newIndex = Nav.calculatePrevIndex(flatModel, selectedFlatIndex, null, null, gridColumns, getSectionViewMode);
- if (newIndex !== selectedFlatIndex) {
- selectedFlatIndex = newIndex;
- updateSelectedItem();
- }
- }
-
- function selectRight() {
- keyboardNavigationActive = true;
- _cancelPendingSelectionReset();
- var newIndex = Nav.calculateRightIndex(flatModel, selectedFlatIndex, getSectionViewMode);
- if (newIndex !== selectedFlatIndex) {
- selectedFlatIndex = newIndex;
- updateSelectedItem();
- }
- }
-
- function selectLeft() {
- keyboardNavigationActive = true;
- _cancelPendingSelectionReset();
- var newIndex = Nav.calculateLeftIndex(flatModel, selectedFlatIndex, getSectionViewMode);
- if (newIndex !== selectedFlatIndex) {
- selectedFlatIndex = newIndex;
- updateSelectedItem();
- }
- }
-
- function selectNextSection() {
- keyboardNavigationActive = true;
- _cancelPendingSelectionReset();
- var newIndex = Nav.calculateNextSectionIndex(flatModel, selectedFlatIndex);
- if (newIndex !== selectedFlatIndex) {
- selectedFlatIndex = newIndex;
- updateSelectedItem();
- }
- }
-
- function selectPreviousSection() {
- keyboardNavigationActive = true;
- _cancelPendingSelectionReset();
- var newIndex = Nav.calculatePrevSectionIndex(flatModel, selectedFlatIndex);
- if (newIndex !== selectedFlatIndex) {
- selectedFlatIndex = newIndex;
- updateSelectedItem();
- }
- }
-
- function selectPageDown(visibleItems) {
- keyboardNavigationActive = true;
- _cancelPendingSelectionReset();
- var newIndex = Nav.calculatePageDownIndex(flatModel, selectedFlatIndex, visibleItems);
- if (newIndex !== selectedFlatIndex) {
- selectedFlatIndex = newIndex;
- updateSelectedItem();
- }
- }
-
- function selectPageUp(visibleItems) {
- keyboardNavigationActive = true;
- _cancelPendingSelectionReset();
- var newIndex = Nav.calculatePageUpIndex(flatModel, selectedFlatIndex, visibleItems);
- if (newIndex !== selectedFlatIndex) {
- selectedFlatIndex = newIndex;
- updateSelectedItem();
- }
- }
-
- function selectIndex(index) {
- keyboardNavigationActive = false;
- if (index >= 0 && index < flatModel.length && !flatModel[index].isHeader) {
- selectedFlatIndex = index;
- updateSelectedItem();
- }
- }
-
- function toggleSection(sectionId) {
- _clearModeCache();
- var newCollapsed = Object.assign({}, collapsedSections);
- var currentState = newCollapsed[sectionId];
-
- if (currentState === undefined) {
- for (var i = 0; i < sections.length; i++) {
- if (sections[i].id === sectionId) {
- currentState = sections[i].collapsed || false;
- break;
- }
- }
- }
-
- newCollapsed[sectionId] = !currentState;
- collapsedSections = newCollapsed;
-
- var newSections = sections.slice();
- for (var i = 0; i < newSections.length; i++) {
- if (newSections[i].id === sectionId) {
- newSections[i] = Object.assign({}, newSections[i], {
- collapsed: newCollapsed[sectionId]
- });
- }
- }
- flatModel = Scorer.flattenSections(newSections);
- sections = newSections;
-
- if (selectedFlatIndex >= flatModel.length) {
- selectedFlatIndex = getFirstItemIndex();
- }
- updateSelectedItem();
- }
-
- function executeSelected() {
- if (searchDebounce.running) {
- searchDebounce.stop();
- performSearch();
- }
- if (!selectedItem)
- return;
- executeItem(selectedItem);
- }
-
- function executeItem(item) {
- if (!item)
- return;
-
- SessionData.addLauncherHistory(searchQuery);
-
- if (item.type === "plugin_browse") {
- var browsePluginId = item.data?.pluginId;
- if (!browsePluginId)
- return;
- var browseTrigger = item.data.isBuiltIn ? AppSearchService.getBuiltInPluginTrigger(browsePluginId) : PluginService.getPluginTrigger(browsePluginId);
-
- if (browseTrigger && browseTrigger.length > 0) {
- searchQueryRequested(browseTrigger);
- } else {
- setMode("plugins");
- pluginFilter = browsePluginId;
- performSearch();
- }
- return;
- }
-
- switch (item.type) {
- case "app":
- if (item.isCore) {
- AppSearchService.executeCoreApp(item.data);
- } else if (item.data?.isAction) {
- launchAppAction(item.data);
- } else {
- launchApp(item.data);
- }
- break;
- case "plugin":
- if (item.isBuiltInLauncher) {
- AppSearchService.executeBuiltInLauncherItem(item.data);
- } else {
- AppSearchService.executePluginItem(item.data, item.pluginId);
- }
- break;
- case "file":
- openFile(item.data?.path);
- break;
- default:
- return;
- }
-
- itemExecuted();
- }
-
- function executeAction(item, action) {
- if (!item || !action)
- return;
- switch (action.action) {
- case "launch":
- executeItem(item);
- break;
- case "open":
- openFile(item.data.path);
- break;
- case "open_folder":
- openFolder(item.data.path);
- break;
- case "copy_path":
- copyToClipboard(item.data.path);
- break;
- case "open_terminal":
- openTerminal(item.data.path);
- break;
- case "copy":
- copyToClipboard(item.name);
- break;
- case "execute":
- executeItem(item);
- break;
- case "launch_dgpu":
- if (item.type === "app" && item.data) {
- launchAppWithNvidia(item.data);
- }
- break;
- case "toggle_all_visibility":
- if (item.type === "plugin_browse" && item.data?.pluginId) {
- var pluginId = item.data.pluginId;
- var currentState = SettingsData.getPluginAllowWithoutTrigger(pluginId);
- SettingsData.setPluginAllowWithoutTrigger(pluginId, !currentState);
- performSearch();
- }
- return;
- default:
- if (item.type === "app" && action.actionData) {
- launchAppAction({
- parentApp: item.data,
- actionData: action.actionData
- });
- }
- }
-
- itemExecuted();
- }
-
- function _resolveDesktopEntry(app) {
- if (!app)
- return null;
- if (app.command)
- return app;
- var id = app.id || app.execString || app.exec || "";
- if (!id)
- return null;
- return DesktopEntries.heuristicLookup(id);
- }
-
- function launchApp(app) {
- var entry = _resolveDesktopEntry(app);
- if (!entry)
- return;
- SessionService.launchDesktopEntry(entry);
- AppUsageHistoryData.addAppUsage(entry);
- }
-
- function launchAppWithNvidia(app) {
- var entry = _resolveDesktopEntry(app);
- if (!entry)
- return;
- SessionService.launchDesktopEntry(entry, true);
- AppUsageHistoryData.addAppUsage(entry);
- }
-
- function launchAppAction(actionItem) {
- if (!actionItem || !actionItem.actionData)
- return;
- var entry = _resolveDesktopEntry(actionItem.parentApp);
- if (!entry)
- return;
- SessionService.launchDesktopAction(entry, actionItem.actionData);
- AppUsageHistoryData.addAppUsage(entry);
- }
-
- function openFile(path) {
- if (!path)
- return;
- Qt.openUrlExternally("file://" + path);
- }
-
- function openFolder(path) {
- if (!path)
- return;
- var folder = path.substring(0, path.lastIndexOf("/"));
- Qt.openUrlExternally("file://" + folder);
- }
-
- function openTerminal(path) {
- if (!path)
- return;
- var terminal = Quickshell.env("TERMINAL") || "xterm";
- Quickshell.execDetached({
- command: [terminal],
- workingDirectory: path
- });
- }
-
- function copyToClipboard(text) {
- if (!text)
- return;
- Quickshell.execDetached(["dms", "cl", "copy", text]);
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ControllerUtils.js b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ControllerUtils.js
deleted file mode 100644
index a06285f..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ControllerUtils.js
+++ /dev/null
@@ -1,128 +0,0 @@
-.pragma library
-
-function getFileIcon(filename) {
- var ext = filename.lastIndexOf(".") > 0 ? filename.substring(filename.lastIndexOf(".") + 1).toLowerCase() : "";
-
- switch (ext) {
- case "pdf":
- return "picture_as_pdf";
- case "doc":
- case "docx":
- case "odt":
- return "description";
- case "xls":
- case "xlsx":
- case "ods":
- return "table_chart";
- case "ppt":
- case "pptx":
- case "odp":
- return "slideshow";
- case "txt":
- case "md":
- case "rst":
- return "article";
- case "jpg":
- case "jpeg":
- case "png":
- case "gif":
- case "svg":
- case "webp":
- return "image";
- case "mp3":
- case "wav":
- case "flac":
- case "ogg":
- return "audio_file";
- case "mp4":
- case "mkv":
- case "avi":
- case "webm":
- return "video_file";
- case "zip":
- case "tar":
- case "gz":
- case "7z":
- case "rar":
- return "folder_zip";
- case "js":
- case "ts":
- case "py":
- case "rs":
- case "go":
- case "java":
- case "c":
- case "cpp":
- case "h":
- return "code";
- case "html":
- case "css":
- case "htm":
- return "web";
- case "json":
- case "xml":
- case "yaml":
- case "yml":
- return "data_object";
- case "sh":
- case "bash":
- case "zsh":
- return "terminal";
- default:
- return "insert_drive_file";
- }
-}
-
-function stripIconPrefix(iconName) {
- if (!iconName)
- return "extension";
- if (iconName.startsWith("unicode:"))
- return iconName.substring(8);
- if (iconName.startsWith("material:"))
- return iconName.substring(9);
- if (iconName.startsWith("image:"))
- return iconName.substring(6);
- return iconName;
-}
-
-function detectIconType(iconName) {
- if (!iconName)
- return "material";
- if (iconName.startsWith("unicode:"))
- return "unicode";
- if (iconName.startsWith("material:"))
- return "material";
- if (iconName.startsWith("image:"))
- return "image";
- if (iconName.indexOf("/") >= 0 || iconName.indexOf(".") >= 0)
- return "image";
- if (/^[a-z]+-[a-z]/.test(iconName.toLowerCase()))
- return "image";
- return "material";
-}
-
-function sortPluginIdsByOrder(pluginIds, order) {
- if (!order || order.length === 0)
- return pluginIds;
- var orderMap = {};
- for (var i = 0; i < order.length; i++)
- orderMap[order[i]] = i;
- return pluginIds.slice().sort(function (a, b) {
- var aOrder = orderMap[a] !== undefined ? orderMap[a] : 9999;
- var bOrder = orderMap[b] !== undefined ? orderMap[b] : 9999;
- return aOrder - bOrder;
- });
-}
-
-function sortPluginsOrdered(plugins, order) {
- if (!order || order.length === 0)
- return plugins;
- var orderMap = {};
- for (var i = 0; i < order.length; i++)
- orderMap[order[i]] = i;
- return plugins.sort(function (a, b) {
- var aOrder = orderMap[a.id] !== undefined ? orderMap[a.id] : 9999;
- var bOrder = orderMap[b.id] !== undefined ? orderMap[b.id] : 9999;
- return aOrder - bOrder;
- });
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/DankLauncherV2Modal.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/DankLauncherV2Modal.qml
deleted file mode 100644
index 859022c..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/DankLauncherV2Modal.qml
+++ /dev/null
@@ -1,465 +0,0 @@
-import QtQuick
-import Quickshell
-import Quickshell.Wayland
-import Quickshell.Hyprland
-import qs.Common
-import qs.Services
-import qs.Widgets
-
-Item {
- id: root
-
- visible: false
-
- property bool spotlightOpen: false
- property bool keyboardActive: false
- property bool contentVisible: false
- property var spotlightContent: launcherContentLoader.item
- property bool openedFromOverview: false
- property bool isClosing: false
- property bool _pendingInitialize: false
- property string _pendingQuery: ""
- property string _pendingMode: ""
- readonly property bool unloadContentOnClose: SettingsData.dankLauncherV2UnloadOnClose
-
- readonly property bool useHyprlandFocusGrab: CompositorService.useHyprlandFocusGrab
- readonly property var effectiveScreen: launcherWindow.screen
- readonly property real screenWidth: effectiveScreen?.width ?? 1920
- readonly property real screenHeight: effectiveScreen?.height ?? 1080
- readonly property real dpr: effectiveScreen ? CompositorService.getScreenScale(effectiveScreen) : 1
-
- readonly property int baseWidth: {
- switch (SettingsData.dankLauncherV2Size) {
- case "micro":
- return 500;
- case "medium":
- return 720;
- case "large":
- return 860;
- default:
- return 620;
- }
- }
- readonly property int baseHeight: {
- switch (SettingsData.dankLauncherV2Size) {
- case "micro":
- return 480;
- case "medium":
- return 720;
- case "large":
- return 860;
- default:
- return 600;
- }
- }
- readonly property int modalWidth: Math.min(baseWidth, screenWidth - 100)
- readonly property int modalHeight: Math.min(baseHeight, screenHeight - 100)
- readonly property real modalX: (screenWidth - modalWidth) / 2
- readonly property real modalY: (screenHeight - modalHeight) / 2
-
- readonly property color backgroundColor: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
- readonly property real cornerRadius: Theme.cornerRadius
- readonly property color borderColor: {
- if (!SettingsData.dankLauncherV2BorderEnabled)
- return Theme.outlineMedium;
- switch (SettingsData.dankLauncherV2BorderColor) {
- case "primary":
- return Theme.primary;
- case "secondary":
- return Theme.secondary;
- case "outline":
- return Theme.outline;
- case "surfaceText":
- return Theme.surfaceText;
- default:
- return Theme.primary;
- }
- }
- readonly property int borderWidth: SettingsData.dankLauncherV2BorderEnabled ? SettingsData.dankLauncherV2BorderThickness : 0
-
- signal dialogClosed
-
- function _ensureContentLoadedAndInitialize(query, mode) {
- _pendingQuery = query || "";
- _pendingMode = mode || "";
- _pendingInitialize = true;
- contentVisible = true;
- launcherContentLoader.active = true;
-
- if (spotlightContent) {
- _initializeAndShow(_pendingQuery, _pendingMode);
- _pendingInitialize = false;
- }
- }
-
- function _initializeAndShow(query, mode) {
- if (!spotlightContent)
- return;
- contentVisible = true;
- spotlightContent.searchField.forceActiveFocus();
-
- var targetQuery = "";
-
- if (query) {
- targetQuery = query;
- } else if (SettingsData.rememberLastQuery) {
- targetQuery = SessionData.launcherLastQuery || "";
- }
-
- if (spotlightContent.searchField) {
- spotlightContent.searchField.text = targetQuery;
- }
- if (spotlightContent.controller) {
- var targetMode = mode || SessionData.launcherLastMode || "all";
- spotlightContent.controller.searchMode = targetMode;
- spotlightContent.controller.activePluginId = "";
- spotlightContent.controller.activePluginName = "";
- spotlightContent.controller.pluginFilter = "";
- spotlightContent.controller.fileSearchType = "all";
- spotlightContent.controller.fileSearchExt = "";
- spotlightContent.controller.fileSearchFolder = "";
- spotlightContent.controller.fileSearchSort = "score";
- spotlightContent.controller.collapsedSections = {};
- spotlightContent.controller.selectedFlatIndex = 0;
- spotlightContent.controller.selectedItem = null;
- spotlightContent.controller.historyIndex = -1;
- spotlightContent.controller.searchQuery = targetQuery;
-
- spotlightContent.controller.performSearch();
- }
- if (spotlightContent.resetScroll) {
- spotlightContent.resetScroll();
- }
- if (spotlightContent.actionPanel) {
- spotlightContent.actionPanel.hide();
- }
- }
-
- function _finishShow(query, mode) {
- spotlightOpen = true;
- isClosing = false;
- openedFromOverview = false;
-
- keyboardActive = true;
- ModalManager.openModal(root);
- if (useHyprlandFocusGrab)
- focusGrab.active = true;
-
- _ensureContentLoadedAndInitialize(query || "", mode || "");
- }
-
- function show() {
- closeCleanupTimer.stop();
-
- var focusedScreen = CompositorService.getFocusedScreen();
- if (focusedScreen && launcherWindow.screen !== focusedScreen) {
- spotlightOpen = false;
- isClosing = false;
- launcherWindow.screen = focusedScreen;
- Qt.callLater(() => root._finishShow("", ""));
- return;
- }
-
- _finishShow("", "");
- }
-
- function showWithQuery(query) {
- closeCleanupTimer.stop();
-
- var focusedScreen = CompositorService.getFocusedScreen();
- if (focusedScreen && launcherWindow.screen !== focusedScreen) {
- spotlightOpen = false;
- isClosing = false;
- launcherWindow.screen = focusedScreen;
- Qt.callLater(() => root._finishShow(query, ""));
- return;
- }
-
- _finishShow(query, "");
- }
-
- function hide() {
- if (!spotlightOpen)
- return;
- openedFromOverview = false;
- isClosing = true;
- contentVisible = false;
-
- keyboardActive = false;
- spotlightOpen = false;
- focusGrab.active = false;
- ModalManager.closeModal(root);
-
- closeCleanupTimer.start();
- }
-
- function toggle() {
- spotlightOpen ? hide() : show();
- }
-
- function showWithMode(mode) {
- closeCleanupTimer.stop();
-
- var focusedScreen = CompositorService.getFocusedScreen();
- if (focusedScreen && launcherWindow.screen !== focusedScreen) {
- spotlightOpen = false;
- isClosing = false;
- launcherWindow.screen = focusedScreen;
- Qt.callLater(() => root._finishShow("", mode));
- return;
- }
-
- spotlightOpen = true;
- isClosing = false;
- openedFromOverview = false;
-
- keyboardActive = true;
- ModalManager.openModal(root);
- if (useHyprlandFocusGrab)
- focusGrab.active = true;
-
- _ensureContentLoadedAndInitialize("", mode);
- }
-
- function toggleWithMode(mode) {
- if (spotlightOpen) {
- hide();
- } else {
- showWithMode(mode);
- }
- }
-
- function toggleWithQuery(query) {
- if (spotlightOpen) {
- hide();
- } else {
- showWithQuery(query);
- }
- }
-
- Timer {
- id: closeCleanupTimer
- interval: Theme.modalAnimationDuration + 50
- repeat: false
- onTriggered: {
- isClosing = false;
- if (root.unloadContentOnClose)
- launcherContentLoader.active = false;
- dialogClosed();
- }
- }
-
- Connections {
- target: spotlightContent?.controller ?? null
-
- function onModeChanged(mode) {
- if (spotlightContent.controller.autoSwitchedToFiles)
- return;
- SessionData.setLauncherLastMode(mode);
- }
- }
-
- HyprlandFocusGrab {
- id: focusGrab
- windows: [launcherWindow]
- active: false
-
- onCleared: {
- if (spotlightOpen) {
- hide();
- }
- }
- }
-
- Connections {
- target: ModalManager
- function onCloseAllModalsExcept(excludedModal) {
- if (excludedModal !== root && spotlightOpen) {
- hide();
- }
- }
- }
-
- Connections {
- target: Quickshell
- function onScreensChanged() {
- if (Quickshell.screens.length === 0)
- return;
-
- const screenName = launcherWindow.screen?.name;
- if (screenName) {
- for (let i = 0; i < Quickshell.screens.length; i++) {
- if (Quickshell.screens[i].name === screenName)
- return;
- }
- }
-
- if (spotlightOpen)
- hide();
-
- const newScreen = CompositorService.getFocusedScreen() ?? Quickshell.screens[0];
- if (newScreen)
- launcherWindow.screen = newScreen;
- }
- }
-
- PanelWindow {
- id: launcherWindow
- visible: spotlightOpen || isClosing
- color: "transparent"
- exclusionMode: ExclusionMode.Ignore
-
- WindowBlur {
- targetWindow: launcherWindow
- readonly property real s: Math.min(1, modalContainer.scale)
- blurX: root.modalX + root.modalWidth * (1 - s) * 0.5
- blurY: root.modalY + root.modalHeight * (1 - s) * 0.5
- blurWidth: (contentVisible && modalContainer.opacity > 0) ? root.modalWidth * s : 0
- blurHeight: (contentVisible && modalContainer.opacity > 0) ? root.modalHeight * s : 0
- blurRadius: root.cornerRadius
- }
-
- WlrLayershell.namespace: "dms:spotlight"
- WlrLayershell.layer: {
- switch (Quickshell.env("DMS_MODAL_LAYER")) {
- case "bottom":
- console.error("DankModal: 'bottom' layer is not valid for modals. Defaulting to 'top' layer.");
- return WlrLayershell.Top;
- case "background":
- console.error("DankModal: 'background' layer is not valid for modals. Defaulting to 'top' layer.");
- return WlrLayershell.Top;
- case "overlay":
- return WlrLayershell.Overlay;
- default:
- return WlrLayershell.Top;
- }
- }
- WlrLayershell.keyboardFocus: keyboardActive ? (root.useHyprlandFocusGrab ? WlrKeyboardFocus.OnDemand : WlrKeyboardFocus.Exclusive) : WlrKeyboardFocus.None
-
- anchors {
- top: true
- bottom: true
- left: true
- right: true
- }
-
- mask: Region {
- item: spotlightOpen ? fullScreenMask : null
- }
-
- Item {
- id: fullScreenMask
- anchors.fill: parent
- }
-
- Rectangle {
- id: backgroundDarken
- anchors.fill: parent
- color: "black"
- opacity: contentVisible && SettingsData.modalDarkenBackground ? 0.5 : 0
- visible: contentVisible || opacity > 0
-
- Behavior on opacity {
- DankAnim {
- duration: Theme.modalAnimationDuration
- easing.bezierCurve: contentVisible ? Theme.expressiveCurves.expressiveDefaultSpatial : Theme.expressiveCurves.emphasized
- }
- }
- }
-
- MouseArea {
- anchors.fill: parent
- enabled: spotlightOpen
- onClicked: mouse => {
- var contentX = modalContainer.x;
- var contentY = modalContainer.y;
- var contentW = modalContainer.width;
- var contentH = modalContainer.height;
-
- if (mouse.x < contentX || mouse.x > contentX + contentW || mouse.y < contentY || mouse.y > contentY + contentH) {
- root.hide();
- }
- }
- }
-
- Item {
- id: modalContainer
- x: root.modalX
- y: root.modalY
- width: root.modalWidth
- height: root.modalHeight
- visible: contentVisible || opacity > 0
-
- opacity: contentVisible ? 1 : 0
- scale: contentVisible ? 1 : 0.96
- transformOrigin: Item.Center
-
- Behavior on opacity {
- DankAnim {
- duration: Theme.modalAnimationDuration
- easing.bezierCurve: contentVisible ? Theme.expressiveCurves.expressiveDefaultSpatial : Theme.expressiveCurves.emphasized
- }
- }
-
- Behavior on scale {
- DankAnim {
- duration: Theme.modalAnimationDuration
- easing.bezierCurve: contentVisible ? Theme.expressiveCurves.expressiveDefaultSpatial : Theme.expressiveCurves.emphasized
- }
- }
-
- ElevationShadow {
- id: launcherShadowLayer
- anchors.fill: parent
- level: Theme.elevationLevel3
- fallbackOffset: 6
- targetColor: root.backgroundColor
- borderColor: root.borderColor
- borderWidth: root.borderWidth
- targetRadius: root.cornerRadius
- shadowEnabled: Theme.elevationEnabled && SettingsData.modalElevationEnabled && Quickshell.env("DMS_DISABLE_LAYER") !== "true" && Quickshell.env("DMS_DISABLE_LAYER") !== "1"
- }
-
- MouseArea {
- anchors.fill: parent
- onPressed: mouse => mouse.accepted = true
- }
-
- FocusScope {
- anchors.fill: parent
- focus: keyboardActive
-
- Loader {
- id: launcherContentLoader
- anchors.fill: parent
- active: !root.unloadContentOnClose || root.spotlightOpen || root.isClosing || root.contentVisible || root._pendingInitialize
- asynchronous: false
- sourceComponent: LauncherContent {
- focus: true
- parentModal: root
- }
-
- onLoaded: {
- if (root._pendingInitialize) {
- root._initializeAndShow(root._pendingQuery, root._pendingMode);
- root._pendingInitialize = false;
- }
- }
- }
-
- Keys.onEscapePressed: event => {
- root.hide();
- event.accepted = true;
- }
- }
-
- Rectangle {
- anchors.fill: parent
- radius: root.cornerRadius
- color: "transparent"
- border.color: BlurService.borderColor
- border.width: BlurService.borderWidth
- }
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/GridItem.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/GridItem.qml
deleted file mode 100644
index a7f39c3..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/GridItem.qml
+++ /dev/null
@@ -1,105 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import QtQuick
-import qs.Common
-import qs.Widgets
-
-Rectangle {
- id: root
-
- property var item: null
- property bool isSelected: false
- property bool isHovered: itemArea.containsMouse
- property var controller: null
- property int flatIndex: -1
-
- signal clicked
- signal rightClicked(real mouseX, real mouseY)
-
- readonly property string iconValue: {
- if (!item)
- return "";
- switch (item.iconType) {
- case "material":
- case "nerd":
- return "material:" + (item.icon || "apps");
- case "unicode":
- return "unicode:" + (item.icon || "");
- case "composite":
- return item.iconFull || "";
- case "image":
- default:
- return item.icon || "";
- }
- }
-
- readonly property int computedIconSize: Math.min(48, Math.max(32, width * 0.45))
-
- radius: Theme.cornerRadius
- color: isSelected ? Theme.primaryPressed : isHovered ? Theme.primaryHoverLight : "transparent"
-
- DankRipple {
- id: rippleLayer
- rippleColor: Theme.surfaceText
- cornerRadius: root.radius
- }
-
- Column {
- anchors.centerIn: parent
- anchors.margins: Theme.spacingS
- spacing: Theme.spacingS
- width: parent.width - Theme.spacingM
-
- AppIconRenderer {
- width: root.computedIconSize
- height: root.computedIconSize
- anchors.horizontalCenter: parent.horizontalCenter
- iconValue: root.iconValue
- iconSize: root.computedIconSize
- fallbackText: (root.item?.name?.length > 0) ? root.item.name.charAt(0).toUpperCase() : "?"
- iconColor: root.isSelected ? Theme.primary : Theme.surfaceText
- materialIconSizeAdjustment: root.computedIconSize * 0.3
- }
-
- Text {
- width: parent.width
- text: root.item?._hName ?? root.item?.name ?? ""
- textFormat: root.item?._hRich ? Text.RichText : Text.PlainText
- font.pixelSize: Theme.fontSizeSmall
- font.weight: Font.Medium
- font.family: Theme.fontFamily
- color: root.isSelected ? Theme.primary : Theme.surfaceText
- elide: Text.ElideRight
- horizontalAlignment: Text.AlignHCenter
- maximumLineCount: 2
- wrapMode: Text.Wrap
- }
- }
-
- MouseArea {
- id: itemArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- acceptedButtons: Qt.LeftButton | Qt.RightButton
-
- onPressed: mouse => {
- if (mouse.button === Qt.LeftButton)
- rippleLayer.trigger(mouse.x, mouse.y);
- }
- onClicked: mouse => {
- if (mouse.button === Qt.RightButton) {
- var scenePos = mapToItem(null, mouse.x, mouse.y);
- root.rightClicked(scenePos.x, scenePos.y);
- } else {
- root.clicked();
- }
- }
-
- onPositionChanged: {
- if (root.controller) {
- root.controller.keyboardNavigationActive = false;
- }
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ItemTransformers.js b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ItemTransformers.js
deleted file mode 100644
index 61c108c..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ItemTransformers.js
+++ /dev/null
@@ -1,237 +0,0 @@
-.pragma library
-
- .import "ControllerUtils.js" as Utils
-
-function transformApp(app, override, defaultActions, primaryActionLabel) {
- var appId = app.id || app.execString || app.exec || "";
-
- var actions = [];
- if (app.actions && app.actions.length > 0) {
- for (var i = 0; i < app.actions.length; i++) {
- actions.push({
- name: app.actions[i].name,
- icon: "play_arrow",
- actionData: app.actions[i]
- });
- }
- }
-
- return {
- id: appId,
- type: "app",
- name: override?.name || app.name || "",
- subtitle: override?.comment || app.comment || "",
- icon: override?.icon || app.icon || "application-x-executable",
- iconType: "image",
- section: "apps",
- data: app,
- keywords: app.keywords || [],
- actions: actions,
- primaryAction: {
- name: primaryActionLabel,
- icon: "open_in_new",
- action: "launch"
- },
- _hName: "",
- _hSub: "",
- _hRich: false,
- _preScored: undefined
- };
-}
-
-function transformCoreApp(app, openLabel) {
- var iconName = "apps";
- var iconType = "material";
-
- if (app.icon) {
- if (app.icon.startsWith("svg+corner:")) {
- iconType = "composite";
- } else if (app.icon.startsWith("material:")) {
- iconName = app.icon.substring(9);
- } else {
- iconName = app.icon;
- iconType = "image";
- }
- }
-
- return {
- id: app.builtInPluginId || app.action || "",
- type: "app",
- name: app.name || "",
- subtitle: app.comment || "",
- icon: iconName,
- iconType: iconType,
- iconFull: app.icon,
- section: "apps",
- data: app,
- isCore: true,
- actions: [],
- primaryAction: {
- name: openLabel,
- icon: "open_in_new",
- action: "launch"
- },
- _hName: "",
- _hSub: "",
- _hRich: false,
- _preScored: undefined
- };
-}
-
-function transformBuiltInLauncherItem(item, pluginId, openLabel) {
- var rawIcon = item.icon || "extension";
- var icon = Utils.stripIconPrefix(rawIcon);
- var iconType = item.iconType;
- if (!iconType) {
- if (rawIcon.startsWith("material:"))
- iconType = "material";
- else if (rawIcon.startsWith("unicode:"))
- iconType = "unicode";
- else
- iconType = "image";
- }
-
- return {
- id: item.action || "",
- type: "plugin",
- name: item.name || "",
- subtitle: item.comment || "",
- icon: icon,
- iconType: iconType,
- section: "plugin_" + pluginId,
- data: item,
- pluginId: pluginId,
- isBuiltInLauncher: true,
- keywords: item.keywords || [],
- actions: [],
- primaryAction: {
- name: openLabel,
- icon: "open_in_new",
- action: "execute"
- },
- _hName: "",
- _hSub: "",
- _hRich: false,
- _preScored: item._preScored
- };
-}
-
-function transformFileResult(file, openLabel, openFolderLabel, copyPathLabel, openTerminalLabel) {
- var filename = file.path ? file.path.split("/").pop() : "";
- var dirname = file.path ? file.path.substring(0, file.path.lastIndexOf("/")) : "";
- var isDir = file.is_dir || false;
-
- var actions = [];
- if (isDir) {
- if (openTerminalLabel) {
- actions.push({
- name: openTerminalLabel,
- icon: "terminal",
- action: "open_terminal"
- });
- }
- } else {
- actions.push({
- name: openFolderLabel,
- icon: "folder_open",
- action: "open_folder"
- });
- }
- actions.push({
- name: copyPathLabel,
- icon: "content_copy",
- action: "copy_path"
- });
-
- return {
- id: file.path || "",
- type: "file",
- name: filename,
- subtitle: dirname,
- icon: isDir ? "folder" : Utils.getFileIcon(filename),
- iconType: "material",
- section: "files",
- data: file,
- actions: actions,
- primaryAction: {
- name: openLabel,
- icon: "open_in_new",
- action: "open"
- },
- _hName: "",
- _hSub: "",
- _hRich: false,
- _preScored: undefined
- };
-}
-
-function transformPluginItem(item, pluginId, selectLabel) {
- var rawIcon = item.icon || "extension";
- var icon = Utils.stripIconPrefix(rawIcon);
- var iconType = item.iconType;
- if (!iconType) {
- if (rawIcon.startsWith("material:"))
- iconType = "material";
- else if (rawIcon.startsWith("unicode:"))
- iconType = "unicode";
- else
- iconType = "image";
- }
-
- return {
- id: item.id || item.name || "",
- type: "plugin",
- name: item.name || "",
- subtitle: item.comment || item.description || "",
- icon: icon,
- iconType: iconType,
- section: "plugin_" + pluginId,
- data: item,
- pluginId: pluginId,
- keywords: item.keywords || [],
- actions: item.actions || [],
- primaryAction: item.primaryAction || {
- name: selectLabel,
- icon: "check",
- action: "execute"
- },
- _hName: "",
- _hSub: "",
- _hRich: false,
- _preScored: item._preScored
- };
-}
-
-function createPluginBrowseItem(pluginId, plugin, trigger, isBuiltIn, isAllowed, browseLabel, triggerLabel, noTriggerLabel) {
- var rawIcon = isBuiltIn ? (plugin.cornerIcon || "extension") : (plugin.icon || "extension");
- return {
- id: "browse_" + pluginId,
- type: "plugin_browse",
- name: plugin.name || pluginId,
- subtitle: trigger ? triggerLabel.replace("%1", trigger) : noTriggerLabel,
- icon: isBuiltIn ? rawIcon : Utils.stripIconPrefix(rawIcon),
- iconType: isBuiltIn ? "material" : Utils.detectIconType(rawIcon),
- section: "browse_plugins",
- data: {
- pluginId: pluginId,
- plugin: plugin,
- isBuiltIn: isBuiltIn
- },
- actions: [
- {
- name: "All",
- icon: isAllowed ? "visibility" : "visibility_off",
- action: "toggle_all_visibility"
- }
- ],
- primaryAction: {
- name: browseLabel,
- icon: "arrow_forward",
- action: "browse_plugin"
- },
- _hName: "",
- _hSub: "",
- _hRich: false,
- _preScored: undefined
- };
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/LauncherContent.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/LauncherContent.qml
deleted file mode 100644
index 4372515..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/LauncherContent.qml
+++ /dev/null
@@ -1,1075 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import QtQuick
-import qs.Common
-import qs.Services
-import qs.Widgets
-
-FocusScope {
- id: root
-
- LayoutMirroring.enabled: I18n.isRtl
- LayoutMirroring.childrenInherit: true
-
- property var parentModal: null
- property string viewModeContext: "spotlight"
- property alias searchField: searchField
- property alias controller: controller
- property alias resultsList: resultsList
- property alias actionPanel: actionPanel
-
- property bool editMode: false
- property var editingApp: null
- property string editAppId: ""
-
- function resetScroll() {
- resultsList.resetScroll();
- }
-
- function focusSearchField() {
- searchField.forceActiveFocus();
- }
-
- function openEditMode(app) {
- if (!app)
- return;
- editingApp = app;
- editAppId = app.id || app.execString || app.exec || "";
- var existing = SessionData.getAppOverride(editAppId);
- editNameField.text = existing?.name || "";
- editIconField.text = existing?.icon || "";
- editCommentField.text = existing?.comment || "";
- editEnvVarsField.text = existing?.envVars || "";
- editExtraFlagsField.text = existing?.extraFlags || "";
- editDgpuToggle.checked = existing?.launchOnDgpu || false;
- editMode = true;
- Qt.callLater(() => editNameField.forceActiveFocus());
- }
-
- function closeEditMode() {
- editMode = false;
- editingApp = null;
- editAppId = "";
- Qt.callLater(() => searchField.forceActiveFocus());
- }
-
- function saveAppOverride() {
- var override = {};
- if (editNameField.text.trim())
- override.name = editNameField.text.trim();
- if (editIconField.text.trim())
- override.icon = editIconField.text.trim();
- if (editCommentField.text.trim())
- override.comment = editCommentField.text.trim();
- if (editEnvVarsField.text.trim())
- override.envVars = editEnvVarsField.text.trim();
- if (editExtraFlagsField.text.trim())
- override.extraFlags = editExtraFlagsField.text.trim();
- if (editDgpuToggle.checked)
- override.launchOnDgpu = true;
- SessionData.setAppOverride(editAppId, override);
- closeEditMode();
- }
-
- function resetAppOverride() {
- SessionData.clearAppOverride(editAppId);
- closeEditMode();
- }
-
- function showContextMenu(item, x, y, fromKeyboard) {
- if (!item)
- return;
- if (!contextMenu.hasContextMenuActions(item))
- return;
- contextMenu.show(x, y, item, fromKeyboard);
- }
-
- anchors.fill: parent
- focus: true
-
- Controller {
- id: controller
- active: root.parentModal?.spotlightOpen ?? true
- viewModeContext: root.viewModeContext
-
- onItemExecuted: {
- if (root.parentModal) {
- root.parentModal.hide();
- }
- if (SettingsData.spotlightCloseNiriOverview && NiriService.inOverview) {
- NiriService.toggleOverview();
- }
- }
- }
-
- LauncherContextMenu {
- id: contextMenu
- parent: root
- controller: root.controller
- searchField: root.searchField
- parentHandler: root
-
- onEditAppRequested: app => {
- root.openEditMode(app);
- }
- }
-
- Keys.onPressed: event => {
- if (editMode) {
- if (event.key === Qt.Key_Escape) {
- closeEditMode();
- event.accepted = true;
- }
- return;
- }
-
- var hasCtrl = event.modifiers & Qt.ControlModifier;
- event.accepted = true;
-
- switch (event.key) {
- case Qt.Key_Escape:
- if (actionPanel.expanded) {
- actionPanel.hide();
- return;
- }
- if (controller.clearPluginFilter())
- return;
- if (root.parentModal)
- root.parentModal.hide();
- return;
- case Qt.Key_Backspace:
- if (searchField.text.length === 0) {
- if (controller.clearPluginFilter())
- return;
- if (controller.autoSwitchedToFiles) {
- controller.restorePreviousMode();
- return;
- }
- }
- event.accepted = false;
- return;
- case Qt.Key_Down:
- if (hasCtrl) {
- controller.navigateHistory("down");
- } else {
- controller.selectNext();
- }
- return;
- case Qt.Key_Up:
- if (hasCtrl) {
- controller.navigateHistory("up");
- } else {
- controller.selectPrevious();
- }
- return;
- case Qt.Key_PageDown:
- controller.selectPageDown(8);
- return;
- case Qt.Key_PageUp:
- controller.selectPageUp(8);
- return;
- case Qt.Key_Right:
- if (hasCtrl) {
- controller.cycleMode();
- return;
- }
- if (controller.getCurrentSectionViewMode() !== "list") {
- controller.selectRight();
- return;
- }
- event.accepted = false;
- return;
- case Qt.Key_Left:
- if (hasCtrl) {
- const reverse = true;
- controller.cycleMode(reverse);
- return;
- }
- if (controller.getCurrentSectionViewMode() !== "list") {
- controller.selectLeft();
- return;
- }
- event.accepted = false;
- return;
- case Qt.Key_H:
- if (hasCtrl) {
- const reverse = true;
- controller.cycleMode(reverse);
- return;
- }
- event.accepted = false;
- return;
- case Qt.Key_J:
- if (hasCtrl) {
- controller.selectNext();
- return;
- }
- event.accepted = false;
- return;
- case Qt.Key_K:
- if (hasCtrl) {
- controller.selectPrevious();
- return;
- }
- event.accepted = false;
- return;
- case Qt.Key_L:
- if (hasCtrl) {
- controller.cycleMode();
- return;
- }
- event.accepted = false;
- return;
- case Qt.Key_N:
- if (hasCtrl) {
- controller.selectNextSection();
- return;
- }
- event.accepted = false;
- return;
- case Qt.Key_P:
- if (hasCtrl) {
- controller.selectPreviousSection();
- return;
- }
- event.accepted = false;
- return;
- case Qt.Key_Tab:
- if (hasCtrl && actionPanel.hasActions) {
- actionPanel.expanded ? actionPanel.cycleAction() : actionPanel.show();
- return;
- }
- controller.selectNext();
- return;
- case Qt.Key_Backtab:
- if (hasCtrl && actionPanel.expanded) {
- const reverse = true;
- actionPanel.expanded ? actionPanel.cycleAction(reverse) : actionPanel.show();
- return;
- }
- controller.selectPrevious();
- return;
- case Qt.Key_Return:
- case Qt.Key_Enter:
- if (event.modifiers & Qt.ShiftModifier) {
- controller.pasteSelected();
- return;
- }
- if (actionPanel.expanded && actionPanel.selectedActionIndex > 0) {
- actionPanel.executeSelectedAction();
- } else {
- controller.executeSelected();
- }
- return;
- case Qt.Key_Menu:
- case Qt.Key_F10:
- if (contextMenu.hasContextMenuActions(controller.selectedItem)) {
- var scenePos = resultsList.getSelectedItemPosition();
- var localPos = root.mapFromItem(null, scenePos.x, scenePos.y);
- showContextMenu(controller.selectedItem, localPos.x, localPos.y, true);
- }
- return;
- case Qt.Key_1:
- if (hasCtrl) {
- controller.setMode("all");
- return;
- }
- event.accepted = false;
- return;
- case Qt.Key_2:
- if (hasCtrl) {
- controller.setMode("apps");
- return;
- }
- event.accepted = false;
- return;
- case Qt.Key_3:
- if (hasCtrl) {
- controller.setMode("files");
- return;
- }
- event.accepted = false;
- return;
- case Qt.Key_4:
- if (hasCtrl) {
- controller.setMode("plugins");
- return;
- }
- event.accepted = false;
- return;
- case Qt.Key_Slash:
- if (event.modifiers === Qt.NoModifier && searchField.text.length === 0) {
- controller.setMode("files", true);
- return;
- }
- event.accepted = false;
- return;
- default:
- event.accepted = false;
- }
- }
-
- Item {
- anchors.fill: parent
- visible: !editMode && !(root.parentModal?.isClosing ?? false)
-
- Item {
- id: footerBar
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: parent.bottom
- anchors.leftMargin: root.parentModal?.borderWidth ?? 1
- anchors.rightMargin: root.parentModal?.borderWidth ?? 1
- anchors.bottomMargin: root.parentModal?.borderWidth ?? 1
- readonly property bool showFooter: SettingsData.dankLauncherV2Size !== "micro" && SettingsData.dankLauncherV2ShowFooter
- height: showFooter ? 36 : 0
- visible: showFooter
- clip: true
-
- Rectangle {
- anchors.fill: parent
- anchors.topMargin: -Theme.cornerRadius
- color: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
- radius: Theme.cornerRadius
- }
-
- Row {
- id: modeButtonsRow
- anchors.left: parent.left
- anchors.leftMargin: Theme.spacingXS
- anchors.verticalCenter: parent.verticalCenter
- layoutDirection: I18n.isRtl ? Qt.RightToLeft : Qt.LeftToRight
- spacing: 2
-
- Repeater {
- model: [
- {
- id: "all",
- label: I18n.tr("All"),
- icon: "search"
- },
- {
- id: "apps",
- label: I18n.tr("Apps"),
- icon: "apps"
- },
- {
- id: "files",
- label: I18n.tr("Files"),
- icon: "folder"
- },
- {
- id: "plugins",
- label: I18n.tr("Plugins"),
- icon: "extension"
- }
- ]
-
- Rectangle {
- required property var modelData
- required property int index
-
- width: buttonContent.width + Theme.spacingM * 2
- height: 28
- radius: Theme.cornerRadius
- color: controller.searchMode === modelData.id || modeArea.containsMouse ? Theme.primaryContainer : "transparent"
-
- Row {
- id: buttonContent
- anchors.centerIn: parent
- spacing: Theme.spacingXS
-
- DankIcon {
- anchors.verticalCenter: parent.verticalCenter
- name: modelData.icon
- size: 14
- color: controller.searchMode === modelData.id ? Theme.primary : Theme.surfaceVariantText
- }
-
- StyledText {
- anchors.verticalCenter: parent.verticalCenter
- text: modelData.label
- font.pixelSize: Theme.fontSizeSmall
- color: controller.searchMode === modelData.id ? Theme.primary : Theme.surfaceText
- }
- }
-
- MouseArea {
- id: modeArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: controller.setMode(modelData.id)
- }
- }
- }
- }
-
- Row {
- id: hintsRow
- anchors.right: parent.right
- anchors.rightMargin: Theme.spacingS
- anchors.verticalCenter: parent.verticalCenter
- layoutDirection: I18n.isRtl ? Qt.RightToLeft : Qt.LeftToRight
- spacing: Theme.spacingM
-
- StyledText {
- anchors.verticalCenter: parent.verticalCenter
- text: "↑↓ " + I18n.tr("nav")
- font.pixelSize: Theme.fontSizeSmall - 1
- color: Theme.surfaceVariantText
- }
-
- StyledText {
- anchors.verticalCenter: parent.verticalCenter
- text: "↵ " + I18n.tr("open")
- font.pixelSize: Theme.fontSizeSmall - 1
- color: Theme.surfaceVariantText
- }
-
- StyledText {
- anchors.verticalCenter: parent.verticalCenter
- text: "Ctrl-Tab " + I18n.tr("actions")
- font.pixelSize: Theme.fontSizeSmall - 1
- color: Theme.surfaceVariantText
- visible: actionPanel.hasActions
- }
- }
- }
-
- Column {
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
- anchors.bottom: footerBar.top
- anchors.leftMargin: Theme.spacingM
- anchors.rightMargin: Theme.spacingM
- anchors.topMargin: Theme.spacingM
- spacing: Theme.spacingXS
- clip: false
-
- Row {
- width: parent.width
- spacing: Theme.spacingS
-
- Rectangle {
- id: pluginBadge
- visible: controller.activePluginName.length > 0
- width: visible ? pluginBadgeContent.implicitWidth + Theme.spacingM : 0
- height: searchField.height
- radius: 16
- color: Theme.primary
-
- Row {
- id: pluginBadgeContent
- anchors.centerIn: parent
- spacing: Theme.spacingXS
-
- DankIcon {
- anchors.verticalCenter: parent.verticalCenter
- name: "extension"
- size: 14
- color: Theme.primaryText
- }
-
- StyledText {
- anchors.verticalCenter: parent.verticalCenter
- text: controller.activePluginName
- font.pixelSize: Theme.fontSizeSmall
- font.weight: Font.Medium
- color: Theme.primaryText
- }
- }
-
- Behavior on width {
- NumberAnimation {
- duration: Theme.shortDuration
- easing.type: Theme.standardEasing
- }
- }
- }
-
- DankTextField {
- id: searchField
- width: parent.width - (pluginBadge.visible ? pluginBadge.width + Theme.spacingS : 0)
- cornerRadius: Theme.cornerRadius
- backgroundColor: Theme.withAlpha(Theme.surfaceContainerHigh, Theme.popupTransparency)
- normalBorderColor: Theme.outlineMedium
- focusedBorderColor: Theme.primary
- leftIconName: controller.activePluginId ? "extension" : controller.searchQuery.startsWith("/") ? "folder" : "search"
- leftIconSize: Theme.iconSize
- leftIconColor: Theme.surfaceVariantText
- leftIconFocusedColor: Theme.primary
- showClearButton: true
- textColor: Theme.surfaceText
- font.pixelSize: Theme.fontSizeLarge
- enabled: root.parentModal ? root.parentModal.spotlightOpen : true
- placeholderText: ""
- ignoreUpDownKeys: true
- ignoreTabKeys: true
- keyForwardTargets: [root]
-
- onTextChanged: {
- controller.setSearchQuery(text);
- if (actionPanel.expanded) {
- actionPanel.hide();
- }
- }
-
- Keys.onPressed: event => {
- if (event.key === Qt.Key_Escape) {
- if (root.parentModal) {
- root.parentModal.hide();
- }
- event.accepted = true;
- } else if ((event.key === Qt.Key_Return || event.key === Qt.Key_Enter)) {
- if (actionPanel.expanded && actionPanel.selectedActionIndex > 0) {
- actionPanel.executeSelectedAction();
- } else {
- controller.executeSelected();
- }
- event.accepted = true;
- }
- }
- }
- }
-
- Row {
- id: categoryRow
- width: parent.width
- readonly property bool showPluginCategories: controller.activePluginCategories.length > 0
- height: showPluginCategories ? 36 : 0
- visible: showPluginCategories
- spacing: Theme.spacingS
-
- clip: true
-
- Behavior on height {
- NumberAnimation {
- duration: Theme.shortDuration
- easing.type: Theme.standardEasing
- }
- }
-
- DankDropdown {
- id: categoryDropdown
- visible: categoryRow.showPluginCategories
- width: Math.min(200, parent.width)
- compactMode: true
- dropdownWidth: 200
- popupWidth: 240
- maxPopupHeight: 300
- enableFuzzySearch: controller.activePluginCategories.length > 8
- currentValue: {
- const cats = controller.activePluginCategories;
- const current = controller.activePluginCategory;
- if (!current)
- return cats.length > 0 ? cats[0].name : "";
- for (let i = 0; i < cats.length; i++) {
- if (cats[i].id === current)
- return cats[i].name;
- }
- return cats.length > 0 ? cats[0].name : "";
- }
- options: {
- const cats = controller.activePluginCategories;
- const names = [];
- for (let i = 0; i < cats.length; i++)
- names.push(cats[i].name);
- return names;
- }
-
- onValueChanged: value => {
- const cats = controller.activePluginCategories;
- for (let i = 0; i < cats.length; i++) {
- if (cats[i].name === value) {
- controller.setActivePluginCategory(cats[i].id);
- return;
- }
- }
- }
- }
- }
-
- Item {
- id: fileFilterRow
- width: parent.width
- height: showFileFilters ? fileFilterContent.height : 0
- visible: showFileFilters
-
- readonly property bool showFileFilters: controller.searchMode === "files"
-
- Behavior on height {
- NumberAnimation {
- duration: Theme.shortDuration
- easing.type: Theme.standardEasing
- }
- }
-
- Row {
- id: fileFilterContent
- width: parent.width
- spacing: Theme.spacingS
-
- Row {
- id: typeChips
- anchors.verticalCenter: parent.verticalCenter
- spacing: 2
- visible: DSearchService.supportsTypeFilter
-
- Repeater {
- model: [
- {
- id: "all",
- label: I18n.tr("All"),
- icon: "search"
- },
- {
- id: "file",
- label: I18n.tr("Files"),
- icon: "insert_drive_file"
- },
- {
- id: "dir",
- label: I18n.tr("Folders"),
- icon: "folder"
- }
- ]
-
- Rectangle {
- required property var modelData
- required property int index
-
- width: chipContent.width + Theme.spacingM * 2
- height: sortDropdown.height
- radius: Theme.cornerRadius
- color: controller.fileSearchType === modelData.id || chipArea.containsMouse ? Theme.primaryContainer : "transparent"
-
- Row {
- id: chipContent
- anchors.centerIn: parent
- spacing: Theme.spacingXS
-
- DankIcon {
- anchors.verticalCenter: parent.verticalCenter
- name: modelData.icon
- size: 14
- color: controller.fileSearchType === modelData.id ? Theme.primary : Theme.surfaceVariantText
- }
-
- StyledText {
- anchors.verticalCenter: parent.verticalCenter
- text: modelData.label
- font.pixelSize: Theme.fontSizeSmall
- color: controller.fileSearchType === modelData.id ? Theme.primary : Theme.surfaceText
- }
- }
-
- MouseArea {
- id: chipArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: controller.setFileSearchType(modelData.id)
- }
- }
- }
- }
-
- Rectangle {
- width: 1
- height: 20
- anchors.verticalCenter: parent.verticalCenter
- color: Theme.outlineMedium
- visible: typeChips.visible
- }
-
- DankDropdown {
- id: sortDropdown
- anchors.verticalCenter: parent.verticalCenter
- width: Math.min(130, parent.width / 3)
- compactMode: true
- dropdownWidth: 130
- popupWidth: 150
- maxPopupHeight: 200
- currentValue: {
- switch (controller.fileSearchSort) {
- case "score":
- return I18n.tr("Score");
- case "name":
- return I18n.tr("Name");
- case "modified":
- return I18n.tr("Modified");
- case "size":
- return I18n.tr("Size");
- default:
- return I18n.tr("Score");
- }
- }
- options: [I18n.tr("Score"), I18n.tr("Name"), I18n.tr("Modified"), I18n.tr("Size")]
-
- onValueChanged: value => {
- var sortMap = {};
- sortMap[I18n.tr("Score")] = "score";
- sortMap[I18n.tr("Name")] = "name";
- sortMap[I18n.tr("Modified")] = "modified";
- sortMap[I18n.tr("Size")] = "size";
- controller.setFileSearchSort(sortMap[value] || "score");
- }
- }
-
- DankTextField {
- id: extFilterField
- anchors.verticalCenter: parent.verticalCenter
- width: Math.min(100, parent.width / 4)
- height: sortDropdown.height
- placeholderText: I18n.tr("ext")
- font.pixelSize: Theme.fontSizeSmall
- showClearButton: text.length > 0
-
- onTextChanged: {
- controller.setFileSearchExt(text.trim());
- }
- }
- }
- }
-
- Item {
- width: parent.width
- height: parent.height - searchField.height - categoryRow.height - fileFilterRow.height - actionPanel.height - Theme.spacingXS * ((categoryRow.visible ? 1 : 0) + (fileFilterRow.visible ? 1 : 0) + 2)
- ResultsList {
- id: resultsList
- anchors.fill: parent
- controller: root.controller
-
- onItemRightClicked: (index, item, sceneX, sceneY) => {
- if (item && contextMenu.hasContextMenuActions(item)) {
- var localPos = root.mapFromItem(null, sceneX, sceneY);
- root.showContextMenu(item, localPos.x, localPos.y, false);
- }
- }
- }
- }
-
- ActionPanel {
- id: actionPanel
- width: parent.width
- selectedItem: controller.selectedItem
- controller: controller
- }
- }
- }
-
- Connections {
- target: controller
- function onSelectedItemChanged() {
- if (actionPanel.expanded && !actionPanel.hasActions) {
- actionPanel.hide();
- }
- }
- function onSearchQueryRequested(query) {
- searchField.text = query;
- searchField.cursorPosition = query.length;
- }
- function onModeChanged() {
- extFilterField.text = "";
- }
- }
-
- FocusScope {
- id: editView
- anchors.fill: parent
- anchors.margins: Theme.spacingM
- visible: editMode
- focus: editMode
-
- Keys.onPressed: event => {
- if (event.key === Qt.Key_Escape) {
- closeEditMode();
- event.accepted = true;
- } else if (event.key === Qt.Key_Return || event.key === Qt.Key_Enter) {
- if (event.modifiers & Qt.ControlModifier) {
- saveAppOverride();
- event.accepted = true;
- }
- } else if (event.key === Qt.Key_S && event.modifiers & Qt.ControlModifier) {
- saveAppOverride();
- event.accepted = true;
- }
- }
-
- Column {
- anchors.fill: parent
- spacing: Theme.spacingM
-
- Row {
- width: parent.width
- spacing: Theme.spacingM
-
- Rectangle {
- width: 40
- height: 40
- radius: Theme.cornerRadius
- color: backButtonArea.containsMouse ? Theme.surfaceHover : "transparent"
-
- DankIcon {
- anchors.centerIn: parent
- name: "arrow_back"
- size: 20
- color: Theme.surfaceText
- }
-
- MouseArea {
- id: backButtonArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: closeEditMode()
- }
- }
-
- Image {
- width: 40
- height: 40
- source: Paths.resolveIconUrl(editingApp?.icon || "application-x-executable")
- sourceSize.width: 40
- sourceSize.height: 40
- fillMode: Image.PreserveAspectFit
- anchors.verticalCenter: parent.verticalCenter
- }
-
- Column {
- anchors.verticalCenter: parent.verticalCenter
- spacing: 2
-
- StyledText {
- text: I18n.tr("Edit App")
- font.pixelSize: Theme.fontSizeLarge
- color: Theme.surfaceText
- font.weight: Font.Medium
- }
-
- StyledText {
- text: editingApp?.name || ""
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.surfaceVariantText
- }
- }
- }
-
- Rectangle {
- width: parent.width
- height: 1
- color: Theme.outlineMedium
- }
-
- Flickable {
- width: parent.width
- height: parent.height - y - buttonsRow.height - Theme.spacingM
- contentHeight: editFieldsColumn.height
- clip: true
- boundsBehavior: Flickable.StopAtBounds
-
- Column {
- id: editFieldsColumn
- width: parent.width
- spacing: Theme.spacingS
-
- Column {
- width: parent.width
- spacing: 4
-
- StyledText {
- text: I18n.tr("Name")
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.surfaceText
- font.weight: Font.Medium
- }
-
- DankTextField {
- id: editNameField
- width: parent.width
- placeholderText: editingApp?.name || ""
- keyNavigationTab: editIconField
- keyNavigationBacktab: editExtraFlagsField
- }
- }
-
- Column {
- width: parent.width
- spacing: 4
-
- StyledText {
- text: I18n.tr("Icon")
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.surfaceText
- font.weight: Font.Medium
- }
-
- DankTextField {
- id: editIconField
- width: parent.width
- placeholderText: editingApp?.icon || ""
- keyNavigationTab: editCommentField
- keyNavigationBacktab: editNameField
- }
- }
-
- Column {
- width: parent.width
- spacing: 4
-
- StyledText {
- text: I18n.tr("Description")
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.surfaceText
- font.weight: Font.Medium
- }
-
- DankTextField {
- id: editCommentField
- width: parent.width
- placeholderText: editingApp?.comment || ""
- keyNavigationTab: editEnvVarsField
- keyNavigationBacktab: editIconField
- }
- }
-
- Column {
- width: parent.width
- spacing: 4
-
- StyledText {
- text: I18n.tr("Environment Variables")
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.surfaceText
- font.weight: Font.Medium
- }
-
- StyledText {
- text: "KEY=value KEY2=value2"
- font.pixelSize: Theme.fontSizeSmall - 1
- color: Theme.surfaceVariantText
- }
-
- DankTextField {
- id: editEnvVarsField
- width: parent.width
- placeholderText: "VAR=value"
- keyNavigationTab: editExtraFlagsField
- keyNavigationBacktab: editCommentField
- }
- }
-
- Column {
- width: parent.width
- spacing: 4
-
- StyledText {
- text: I18n.tr("Extra Arguments")
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.surfaceText
- font.weight: Font.Medium
- }
-
- DankTextField {
- id: editExtraFlagsField
- width: parent.width
- placeholderText: "--flag --option=value"
- keyNavigationTab: editNameField
- keyNavigationBacktab: editEnvVarsField
- }
- }
-
- DankToggle {
- id: editDgpuToggle
- width: parent.width
- text: I18n.tr("Launch on dGPU by default")
- visible: SessionService.nvidiaCommand.length > 0
- checked: false
- onToggled: checked => editDgpuToggle.checked = checked
- }
- }
- }
-
- Row {
- id: buttonsRow
- anchors.horizontalCenter: parent.horizontalCenter
- spacing: Theme.spacingM
-
- Rectangle {
- id: resetButton
- width: 90
- height: 40
- radius: Theme.cornerRadius
- color: resetButtonArea.containsMouse ? Theme.surfacePressed : Theme.surfaceVariantAlpha
- visible: SessionData.getAppOverride(editAppId) !== null
-
- StyledText {
- text: I18n.tr("Reset")
- font.pixelSize: Theme.fontSizeMedium
- color: Theme.error
- font.weight: Font.Medium
- anchors.centerIn: parent
- }
-
- MouseArea {
- id: resetButtonArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: resetAppOverride()
- }
- }
-
- Rectangle {
- id: cancelButton
- width: 90
- height: 40
- radius: Theme.cornerRadius
- color: cancelButtonArea.containsMouse ? Theme.surfacePressed : Theme.surfaceVariantAlpha
-
- StyledText {
- text: I18n.tr("Cancel")
- font.pixelSize: Theme.fontSizeMedium
- color: Theme.surfaceText
- font.weight: Font.Medium
- anchors.centerIn: parent
- }
-
- MouseArea {
- id: cancelButtonArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: closeEditMode()
- }
- }
-
- Rectangle {
- id: saveButton
- width: 90
- height: 40
- radius: Theme.cornerRadius
- color: saveButtonArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.9) : Theme.primary
-
- StyledText {
- text: I18n.tr("Save")
- font.pixelSize: Theme.fontSizeMedium
- color: Theme.primaryText
- font.weight: Font.Medium
- anchors.centerIn: parent
- }
-
- MouseArea {
- id: saveButtonArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: saveAppOverride()
- }
- }
- }
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/LauncherContextMenu.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/LauncherContextMenu.qml
deleted file mode 100644
index 3c55590..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/LauncherContextMenu.qml
+++ /dev/null
@@ -1,510 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import QtQuick
-import QtQuick.Controls
-import qs.Common
-import qs.Services
-import qs.Widgets
-
-Popup {
- id: root
-
- property var item: null
- property var controller: null
- property var searchField: null
- property var parentHandler: null
-
- signal hideRequested
- signal editAppRequested(var app)
-
- function hasContextMenuActions(spotlightItem) {
- if (!spotlightItem)
- return false;
- if (spotlightItem.type === "app")
- return true;
- if (spotlightItem.type === "plugin" && spotlightItem.pluginId) {
- var instance = PluginService.pluginInstances[spotlightItem.pluginId];
- if (!instance)
- return false;
- if (typeof instance.getContextMenuActions !== "function")
- return false;
- var actions = instance.getContextMenuActions(spotlightItem.data);
- return Array.isArray(actions) && actions.length > 0;
- }
- return false;
- }
-
- readonly property bool isCoreApp: item?.type === "app" && !!item?.isCore
- readonly property var coreAppData: isCoreApp ? item?.data ?? null : null
- readonly property var desktopEntry: !isCoreApp ? (item?.data ?? null) : null
- readonly property string appId: {
- if (isCoreApp) {
- return item?.id || coreAppData?.builtInPluginId || "";
- }
- return desktopEntry?.id || desktopEntry?.execString || "";
- }
- readonly property bool isPinned: appId ? SessionData.isPinnedApp(appId) : false
- readonly property bool isRegularApp: item?.type === "app" && !item.isCore && desktopEntry
- readonly property bool isPluginItem: item?.type === "plugin"
-
- function getPluginContextMenuActions() {
- if (!isPluginItem || !item?.pluginId)
- return [];
-
- var instance = PluginService.pluginInstances[item.pluginId];
- if (!instance)
- return [];
- if (typeof instance.getContextMenuActions !== "function")
- return [];
-
- var actions = instance.getContextMenuActions(item.data);
- if (!Array.isArray(actions))
- return [];
-
- return actions;
- }
-
- function executePluginAction(actionOrObj) {
- var actionFunc = typeof actionOrObj === "function" ? actionOrObj : actionOrObj?.action;
- var closeLauncher = typeof actionOrObj === "object" && actionOrObj?.closeLauncher;
-
- if (typeof actionFunc === "function")
- actionFunc();
-
- if (closeLauncher) {
- controller?.itemExecuted();
- } else {
- controller?.performSearch();
- }
- hide();
- }
-
- readonly property var menuItems: {
- var items = [];
-
- if (isPluginItem) {
- var pluginActions = getPluginContextMenuActions();
- for (var i = 0; i < pluginActions.length; i++) {
- var act = pluginActions[i];
- items.push({
- type: "item",
- icon: act.icon || "play_arrow",
- text: act.text || act.name || "",
- pluginAction: act
- });
- }
- return items;
- }
-
- if (item?.type === "app") {
- items.push({
- type: "item",
- icon: isPinned ? "keep_off" : "push_pin",
- text: isPinned ? I18n.tr("Unpin from Dock") : I18n.tr("Pin to Dock"),
- action: togglePin
- });
- }
-
- if (isRegularApp) {
- items.push({
- type: "item",
- icon: "visibility_off",
- text: I18n.tr("Hide App"),
- action: hideCurrentApp
- });
- items.push({
- type: "item",
- icon: "edit",
- text: I18n.tr("Edit App"),
- action: editCurrentApp
- });
- }
-
- if (item?.actions && item.actions.length > 0) {
- items.push({
- type: "separator"
- });
- for (var i = 0; i < item.actions.length; i++) {
- var act = item.actions[i];
- items.push({
- type: "item",
- icon: act.icon || "play_arrow",
- text: act.name || "",
- actionData: act
- });
- }
- }
-
- items.push({
- type: "separator"
- });
-
- if (isRegularApp && SessionService.nvidiaCommand) {
- items.push({
- type: "item",
- icon: "memory",
- text: I18n.tr("Launch on dGPU"),
- action: launchWithNvidia
- });
- }
-
- items.push({
- type: "item",
- icon: "launch",
- text: I18n.tr("Launch"),
- action: launchApp
- });
-
- return items;
- }
-
- function show(x, y, spotlightItem, fromKeyboard) {
- if (!spotlightItem?.data)
- return;
- item = spotlightItem;
- selectedMenuIndex = fromKeyboard ? 0 : -1;
- keyboardNavigation = fromKeyboard;
-
- if (parentHandler)
- parentHandler.enabled = false;
-
- Qt.callLater(() => {
- var parentW = parent?.width ?? 500;
- var parentH = parent?.height ?? 600;
- var menuW = width > 0 ? width : 200;
- var menuH = height > 0 ? height : 200;
- var margin = 8;
-
- var posX = x + 4;
- var posY = y + 4;
-
- if (posX + menuW > parentW - margin) {
- posX = Math.max(margin, parentW - menuW - margin);
- }
- if (posY + menuH > parentH - margin) {
- posY = Math.max(margin, parentH - menuH - margin);
- }
-
- root.x = posX;
- root.y = posY;
- open();
- });
- }
-
- function hide() {
- if (parentHandler)
- parentHandler.enabled = true;
- close();
- }
-
- function togglePin() {
- if (!appId)
- return;
- if (isPinned)
- SessionData.removePinnedApp(appId);
- else
- SessionData.addPinnedApp(appId);
- hide();
- }
-
- function hideCurrentApp() {
- if (!appId)
- return;
- SessionData.hideApp(appId);
- controller?.performSearch();
- hide();
- }
-
- function editCurrentApp() {
- if (!desktopEntry)
- return;
- editAppRequested(desktopEntry);
- hide();
- }
-
- function launchApp() {
- if (isCoreApp) {
- if (!coreAppData)
- return;
- AppSearchService.executeCoreApp(coreAppData);
- controller?.itemExecuted();
- hide();
- return;
- }
- if (!desktopEntry)
- return;
- SessionService.launchDesktopEntry(desktopEntry);
- AppUsageHistoryData.addAppUsage(desktopEntry);
- controller?.itemExecuted();
- hide();
- }
-
- function launchWithNvidia() {
- if (!desktopEntry)
- return;
- SessionService.launchDesktopEntry(desktopEntry, true);
- AppUsageHistoryData.addAppUsage(desktopEntry);
- controller?.itemExecuted();
- hide();
- }
-
- function executeDesktopAction(actionData) {
- if (!desktopEntry || !actionData)
- return;
- SessionService.launchDesktopAction(desktopEntry, actionData.actionData || actionData);
- AppUsageHistoryData.addAppUsage(desktopEntry);
- controller?.itemExecuted();
- hide();
- }
-
- property int selectedMenuIndex: 0
- property bool keyboardNavigation: false
-
- readonly property int visibleItemCount: {
- var count = 0;
- for (var i = 0; i < menuItems.length; i++) {
- if (menuItems[i].type === "item")
- count++;
- }
- return count;
- }
-
- function selectNext() {
- if (visibleItemCount > 0)
- selectedMenuIndex = (selectedMenuIndex + 1) % visibleItemCount;
- }
-
- function selectPrevious() {
- if (visibleItemCount > 0)
- selectedMenuIndex = (selectedMenuIndex - 1 + visibleItemCount) % visibleItemCount;
- }
-
- function activateSelected() {
- var itemIndex = 0;
- for (var i = 0; i < menuItems.length; i++) {
- if (menuItems[i].type !== "item")
- continue;
- if (itemIndex === selectedMenuIndex) {
- var menuItem = menuItems[i];
- if (menuItem.action)
- menuItem.action();
- else if (menuItem.pluginAction)
- executePluginAction(menuItem.pluginAction);
- else if (menuItem.actionData)
- executeDesktopAction(menuItem.actionData);
- return;
- }
- itemIndex++;
- }
- }
-
- width: menuContainer.implicitWidth
- height: menuContainer.implicitHeight
- padding: 0
- closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
- modal: true
- dim: false
- background: Item {}
-
- onOpened: {
- Qt.callLater(() => keyboardHandler.forceActiveFocus());
- }
-
- onClosed: {
- if (parentHandler)
- parentHandler.enabled = true;
- if (searchField?.visible) {
- Qt.callLater(() => searchField.forceActiveFocus());
- }
- }
-
- enter: Transition {
- NumberAnimation {
- property: "opacity"
- from: 0
- to: 1
- duration: Theme.shortDuration
- easing.type: Theme.emphasizedEasing
- }
- }
-
- exit: Transition {
- NumberAnimation {
- property: "opacity"
- from: 1
- to: 0
- duration: Theme.shortDuration
- easing.type: Theme.emphasizedEasing
- }
- }
-
- contentItem: Item {
- id: keyboardHandler
- focus: true
- implicitWidth: menuContainer.implicitWidth
- implicitHeight: menuContainer.implicitHeight
-
- Keys.onPressed: event => {
- switch (event.key) {
- case Qt.Key_Down:
- root.selectNext();
- event.accepted = true;
- return;
- case Qt.Key_Up:
- root.selectPrevious();
- event.accepted = true;
- return;
- case Qt.Key_Return:
- case Qt.Key_Enter:
- root.activateSelected();
- event.accepted = true;
- return;
- case Qt.Key_Escape:
- case Qt.Key_Left:
- root.hide();
- event.accepted = true;
- return;
- }
- }
-
- Rectangle {
- id: menuContainer
- anchors.fill: parent
- implicitWidth: Math.max(180, menuColumn.implicitWidth + Theme.spacingS * 2)
- implicitHeight: menuColumn.implicitHeight + Theme.spacingS * 2
- color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
- radius: Theme.cornerRadius
- border.color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.08)
- border.width: 1
-
- Rectangle {
- anchors.fill: parent
- anchors.topMargin: 4
- anchors.leftMargin: 2
- anchors.rightMargin: -2
- anchors.bottomMargin: -4
- radius: parent.radius
- color: Qt.rgba(0, 0, 0, 0.15)
- z: -1
- }
-
- Column {
- id: menuColumn
- anchors.fill: parent
- anchors.margins: Theme.spacingS
- spacing: 1
-
- Repeater {
- model: root.menuItems
-
- Item {
- id: menuItemDelegate
- required property var modelData
- required property int index
-
- width: menuColumn.width
- height: modelData.type === "separator" ? 5 : 32
-
- readonly property int itemIndex: {
- var count = 0;
- for (var i = 0; i < index; i++) {
- if (root.menuItems[i].type === "item")
- count++;
- }
- return count;
- }
-
- Rectangle {
- visible: menuItemDelegate.modelData.type === "separator"
- width: parent.width - Theme.spacingS * 2
- height: parent.height
- anchors.horizontalCenter: parent.horizontalCenter
- color: "transparent"
-
- Rectangle {
- anchors.centerIn: parent
- width: parent.width
- height: 1
- color: Qt.rgba(Theme.outline.r, Theme.outline.g, Theme.outline.b, 0.2)
- }
- }
-
- Rectangle {
- visible: menuItemDelegate.modelData.type === "item"
- width: parent.width
- height: parent.height
- radius: Theme.cornerRadius
- color: {
- if (root.keyboardNavigation && root.selectedMenuIndex === menuItemDelegate.itemIndex) {
- return Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.2);
- }
- return itemMouseArea.containsMouse ? Qt.rgba(Theme.primary.r, Theme.primary.g, Theme.primary.b, 0.12) : "transparent";
- }
-
- Row {
- anchors.left: parent.left
- anchors.leftMargin: Theme.spacingS
- anchors.right: parent.right
- anchors.rightMargin: Theme.spacingS
- anchors.verticalCenter: parent.verticalCenter
- spacing: Theme.spacingS
-
- Item {
- width: Theme.iconSize - 2
- height: Theme.iconSize - 2
- anchors.verticalCenter: parent.verticalCenter
-
- DankIcon {
- visible: (menuItemDelegate.modelData?.icon ?? "").length > 0
- name: menuItemDelegate.modelData?.icon ?? ""
- size: Theme.iconSize - 2
- color: Theme.surfaceText
- opacity: 0.7
- anchors.verticalCenter: parent.verticalCenter
- }
- }
-
- StyledText {
- text: menuItemDelegate.modelData.text || ""
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.surfaceText
- font.weight: Font.Normal
- anchors.verticalCenter: parent.verticalCenter
- elide: Text.ElideRight
- width: parent.width - (Theme.iconSize - 2) - Theme.spacingS
- }
- }
-
- DankRipple {
- id: menuItemRipple
- rippleColor: Theme.surfaceText
- cornerRadius: Theme.cornerRadius
- }
-
- MouseArea {
- id: itemMouseArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onEntered: {
- root.keyboardNavigation = false;
- root.selectedMenuIndex = menuItemDelegate.itemIndex;
- }
- onPressed: mouse => menuItemRipple.trigger(mouse.x, mouse.y)
- onClicked: {
- var menuItem = menuItemDelegate.modelData;
- if (menuItem.action)
- menuItem.action();
- else if (menuItem.pluginAction)
- root.executePluginAction(menuItem.pluginAction);
- else if (menuItem.actionData)
- root.executeDesktopAction(menuItem.actionData);
- }
- }
- }
- }
- }
- }
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/NavigationHelpers.js b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/NavigationHelpers.js
deleted file mode 100644
index 1e78b11..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/NavigationHelpers.js
+++ /dev/null
@@ -1,254 +0,0 @@
-.pragma library
-
-function getFirstItemIndex(flatModel) {
- for (var i = 0; i < flatModel.length; i++) {
- if (!flatModel[i].isHeader)
- return i;
- }
- return 0;
-}
-
-function findNextNonHeaderIndex(flatModel, startIndex) {
- for (var i = startIndex; i < flatModel.length; i++) {
- if (!flatModel[i].isHeader)
- return i;
- }
- return -1;
-}
-
-function findPrevNonHeaderIndex(flatModel, startIndex) {
- for (var i = startIndex; i >= 0; i--) {
- if (!flatModel[i].isHeader)
- return i;
- }
- return -1;
-}
-
-function getSectionBounds(flatModel, sectionId) {
- if (flatModel._sectionBounds && flatModel._sectionBounds[sectionId])
- return flatModel._sectionBounds[sectionId];
-
- var start = -1, end = -1;
- for (var i = 0; i < flatModel.length; i++) {
- if (flatModel[i].isHeader && flatModel[i].section?.id === sectionId) {
- start = i + 1;
- } else if (start >= 0 && !flatModel[i].isHeader && flatModel[i].sectionId === sectionId) {
- end = i;
- } else if (start >= 0 && end >= 0 && flatModel[i].sectionId !== sectionId) {
- break;
- }
- }
- return {
- start: start,
- end: end,
- count: end >= start ? end - start + 1 : 0
- };
-}
-
-function getGridColumns(viewMode, gridColumns) {
- switch (viewMode) {
- case "tile":
- return 3;
- case "grid":
- return gridColumns;
- default:
- return 1;
- }
-}
-
-function calculateNextIndex(flatModel, selectedFlatIndex, sectionId, viewMode, gridColumns, getSectionViewModeFn) {
- if (flatModel.length === 0)
- return selectedFlatIndex;
-
- var entry = flatModel[selectedFlatIndex];
- if (!entry || entry.isHeader) {
- var next = findNextNonHeaderIndex(flatModel, selectedFlatIndex + 1);
- return next !== -1 ? next : selectedFlatIndex;
- }
-
- var actualViewMode = viewMode || getSectionViewModeFn(entry.sectionId);
- if (actualViewMode === "list") {
- var next = findNextNonHeaderIndex(flatModel, selectedFlatIndex + 1);
- return next !== -1 ? next : selectedFlatIndex;
- }
-
- var bounds = getSectionBounds(flatModel, entry.sectionId);
- var cols = getGridColumns(actualViewMode, gridColumns);
- var posInSection = selectedFlatIndex - bounds.start;
- var newPosInSection = posInSection + cols;
-
- if (newPosInSection < bounds.count) {
- return bounds.start + newPosInSection;
- }
-
- var currentRow = Math.floor(posInSection / cols);
- var lastRow = Math.floor((bounds.count - 1) / cols);
- if (currentRow < lastRow) {
- return bounds.start + bounds.count - 1;
- }
-
- var nextSection = findNextNonHeaderIndex(flatModel, bounds.end + 1);
- return nextSection !== -1 ? nextSection : selectedFlatIndex;
-}
-
-function calculatePrevIndex(flatModel, selectedFlatIndex, sectionId, viewMode, gridColumns, getSectionViewModeFn) {
- if (flatModel.length === 0)
- return selectedFlatIndex;
-
- var entry = flatModel[selectedFlatIndex];
- if (!entry || entry.isHeader) {
- var prev = findPrevNonHeaderIndex(flatModel, selectedFlatIndex - 1);
- return prev !== -1 ? prev : selectedFlatIndex;
- }
-
- var actualViewMode = viewMode || getSectionViewModeFn(entry.sectionId);
- if (actualViewMode === "list") {
- var prev = findPrevNonHeaderIndex(flatModel, selectedFlatIndex - 1);
- return prev !== -1 ? prev : selectedFlatIndex;
- }
-
- var bounds = getSectionBounds(flatModel, entry.sectionId);
- var cols = getGridColumns(actualViewMode, gridColumns);
- var posInSection = selectedFlatIndex - bounds.start;
- var newPosInSection = posInSection - cols;
-
- if (newPosInSection >= 0) {
- return bounds.start + newPosInSection;
- }
-
- var prevItem = findPrevNonHeaderIndex(flatModel, bounds.start - 1);
- return prevItem !== -1 ? prevItem : selectedFlatIndex;
-}
-
-function calculateRightIndex(flatModel, selectedFlatIndex, getSectionViewModeFn) {
- if (flatModel.length === 0)
- return selectedFlatIndex;
-
- var entry = flatModel[selectedFlatIndex];
- if (!entry || entry.isHeader) {
- var next = findNextNonHeaderIndex(flatModel, selectedFlatIndex + 1);
- return next !== -1 ? next : selectedFlatIndex;
- }
-
- var viewMode = getSectionViewModeFn(entry.sectionId);
- if (viewMode === "list") {
- var next = findNextNonHeaderIndex(flatModel, selectedFlatIndex + 1);
- return next !== -1 ? next : selectedFlatIndex;
- }
-
- var bounds = getSectionBounds(flatModel, entry.sectionId);
- var posInSection = selectedFlatIndex - bounds.start;
- if (posInSection + 1 < bounds.count) {
- return bounds.start + posInSection + 1;
- }
- return selectedFlatIndex;
-}
-
-function calculateLeftIndex(flatModel, selectedFlatIndex, getSectionViewModeFn) {
- if (flatModel.length === 0)
- return selectedFlatIndex;
-
- var entry = flatModel[selectedFlatIndex];
- if (!entry || entry.isHeader) {
- var prev = findPrevNonHeaderIndex(flatModel, selectedFlatIndex - 1);
- return prev !== -1 ? prev : selectedFlatIndex;
- }
-
- var viewMode = getSectionViewModeFn(entry.sectionId);
- if (viewMode === "list") {
- var prev = findPrevNonHeaderIndex(flatModel, selectedFlatIndex - 1);
- return prev !== -1 ? prev : selectedFlatIndex;
- }
-
- var bounds = getSectionBounds(flatModel, entry.sectionId);
- var posInSection = selectedFlatIndex - bounds.start;
- if (posInSection > 0) {
- return bounds.start + posInSection - 1;
- }
- return selectedFlatIndex;
-}
-
-function calculateNextSectionIndex(flatModel, selectedFlatIndex) {
- var currentSection = null;
- if (selectedFlatIndex >= 0 && selectedFlatIndex < flatModel.length) {
- currentSection = flatModel[selectedFlatIndex].sectionId;
- }
-
- var foundCurrent = false;
- for (var i = 0; i < flatModel.length; i++) {
- if (flatModel[i].isHeader) {
- if (foundCurrent) {
- for (var j = i + 1; j < flatModel.length; j++) {
- if (!flatModel[j].isHeader)
- return j;
- }
- }
- if (flatModel[i].section.id === currentSection) {
- foundCurrent = true;
- }
- }
- }
- return selectedFlatIndex;
-}
-
-function calculatePrevSectionIndex(flatModel, selectedFlatIndex) {
- var currentSection = null;
- if (selectedFlatIndex >= 0 && selectedFlatIndex < flatModel.length) {
- currentSection = flatModel[selectedFlatIndex].sectionId;
- }
-
- var lastSectionStart = -1;
- var prevSectionStart = -1;
-
- for (var i = 0; i < flatModel.length; i++) {
- if (flatModel[i].isHeader) {
- if (flatModel[i].section.id === currentSection) {
- break;
- }
- prevSectionStart = lastSectionStart;
- lastSectionStart = i;
- }
- }
-
- if (prevSectionStart >= 0) {
- for (var j = prevSectionStart + 1; j < flatModel.length; j++) {
- if (!flatModel[j].isHeader)
- return j;
- }
- }
- return selectedFlatIndex;
-}
-
-function calculatePageDownIndex(flatModel, selectedFlatIndex, visibleItems) {
- if (flatModel.length === 0)
- return selectedFlatIndex;
-
- var itemsToSkip = visibleItems || 8;
- var newIndex = selectedFlatIndex;
-
- for (var i = 0; i < itemsToSkip; i++) {
- var next = findNextNonHeaderIndex(flatModel, newIndex + 1);
- if (next === -1)
- break;
- newIndex = next;
- }
-
- return newIndex;
-}
-
-function calculatePageUpIndex(flatModel, selectedFlatIndex, visibleItems) {
- if (flatModel.length === 0)
- return selectedFlatIndex;
-
- var itemsToSkip = visibleItems || 8;
- var newIndex = selectedFlatIndex;
-
- for (var i = 0; i < itemsToSkip; i++) {
- var prev = findPrevNonHeaderIndex(flatModel, newIndex - 1);
- if (prev === -1)
- break;
- newIndex = prev;
- }
-
- return newIndex;
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ResultItem.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ResultItem.qml
deleted file mode 100644
index 0a50cd3..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ResultItem.qml
+++ /dev/null
@@ -1,196 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import QtQuick
-import qs.Common
-import qs.Widgets
-
-Rectangle {
- id: root
-
- property var item: null
- property bool isSelected: false
- property bool isHovered: itemArea.containsMouse || allModeToggleArea.containsMouse
- property var controller: null
- property int flatIndex: -1
-
- signal clicked
- signal rightClicked(real mouseX, real mouseY)
-
- readonly property string iconValue: {
- if (!item)
- return "";
- switch (item.iconType) {
- case "material":
- case "nerd":
- return "material:" + (item.icon || "apps");
- case "unicode":
- return "unicode:" + (item.icon || "");
- case "composite":
- return item.iconFull || "";
- case "image":
- default:
- return item.icon || "";
- }
- }
-
- width: parent?.width ?? 200
- height: 52
- color: isSelected ? Theme.primaryPressed : isHovered ? Theme.primaryHoverLight : "transparent"
- radius: Theme.cornerRadius
-
- DankRipple {
- id: rippleLayer
- rippleColor: Theme.surfaceText
- cornerRadius: root.radius
- }
-
- MouseArea {
- id: itemArea
- z: 1
- anchors.fill: parent
- anchors.rightMargin: root.item?.type === "plugin_browse" ? 40 : 0
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- acceptedButtons: Qt.LeftButton | Qt.RightButton
-
- onPressed: mouse => {
- if (mouse.button === Qt.LeftButton)
- rippleLayer.trigger(mouse.x, mouse.y);
- }
- onClicked: mouse => {
- if (mouse.button === Qt.RightButton) {
- var scenePos = mapToItem(null, mouse.x, mouse.y);
- root.rightClicked(scenePos.x, scenePos.y);
- } else {
- root.clicked();
- }
- }
-
- onPositionChanged: {
- if (root.controller)
- root.controller.keyboardNavigationActive = false;
- }
- }
-
- Row {
- anchors.fill: parent
- anchors.leftMargin: Theme.spacingM
- anchors.rightMargin: Theme.spacingM
- spacing: Theme.spacingM
-
- AppIconRenderer {
- width: 36
- height: 36
- anchors.verticalCenter: parent.verticalCenter
- iconValue: root.iconValue
- iconSize: 36
- fallbackText: (root.item?.name?.length > 0) ? root.item.name.charAt(0).toUpperCase() : "?"
- materialIconSizeAdjustment: 12
- }
-
- Column {
- anchors.verticalCenter: parent.verticalCenter
- width: parent.width - 36 - Theme.spacingM * 3 - rightContent.width
- spacing: 2
-
- Text {
- width: parent.width
- text: root.item?._hName ?? root.item?.name ?? ""
- textFormat: root.item?._hRich ? Text.RichText : Text.PlainText
- font.pixelSize: Theme.fontSizeMedium
- font.weight: Font.Medium
- font.family: Theme.fontFamily
- color: Theme.surfaceText
- elide: Text.ElideRight
- horizontalAlignment: Text.AlignLeft
- }
-
- Text {
- width: parent.width
- text: root.item?._hSub ?? root.item?.subtitle ?? ""
- textFormat: root.item?._hRich ? Text.RichText : Text.PlainText
- font.pixelSize: Theme.fontSizeSmall
- font.family: Theme.fontFamily
- color: Theme.surfaceVariantText
- elide: Text.ElideRight
- clip: true
- visible: (root.item?.subtitle ?? "").length > 0
- horizontalAlignment: Text.AlignLeft
- }
- }
-
- Row {
- id: rightContent
- anchors.verticalCenter: parent.verticalCenter
- spacing: Theme.spacingS
-
- Rectangle {
- id: allModeToggle
- visible: root.item?.type === "plugin_browse"
- width: 28
- height: 28
- radius: 14
- anchors.verticalCenter: parent.verticalCenter
- color: allModeToggleArea.containsMouse ? Theme.surfaceHover : "transparent"
-
- property bool isAllowed: {
- if (root.item?.type !== "plugin_browse")
- return false;
- var pluginId = root.item?.data?.pluginId;
- if (!pluginId)
- return false;
- SettingsData.launcherPluginVisibility;
- return SettingsData.getPluginAllowWithoutTrigger(pluginId);
- }
-
- DankIcon {
- anchors.centerIn: parent
- name: allModeToggle.isAllowed ? "visibility" : "visibility_off"
- size: 18
- color: allModeToggle.isAllowed ? Theme.primary : Theme.surfaceVariantText
- }
-
- MouseArea {
- id: allModeToggleArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: {
- var pluginId = root.item?.data?.pluginId;
- if (!pluginId)
- return;
- SettingsData.setPluginAllowWithoutTrigger(pluginId, !allModeToggle.isAllowed);
- }
- }
- }
-
- Rectangle {
- visible: !!root.item?.type && root.item.type !== "app" && root.item.type !== "plugin_browse"
- width: typeBadge.implicitWidth + Theme.spacingS * 2
- height: 20
- radius: 10
- color: Theme.surfaceVariantAlpha
- anchors.verticalCenter: parent.verticalCenter
-
- StyledText {
- id: typeBadge
- anchors.centerIn: parent
- text: {
- if (!root.item)
- return "";
- switch (root.item.type) {
- case "plugin":
- return I18n.tr("Plugin");
- case "file":
- return root.item.data?.is_dir ? I18n.tr("Folder") : I18n.tr("File");
- default:
- return "";
- }
- }
- font.pixelSize: Theme.fontSizeSmall - 2
- color: Theme.surfaceVariantText
- }
- }
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ResultsList.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ResultsList.qml
deleted file mode 100644
index 53a2d45..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ResultsList.qml
+++ /dev/null
@@ -1,498 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import QtQuick
-import Quickshell
-import qs.Common
-import qs.Services
-import qs.Widgets
-
-Item {
- id: root
-
- property var controller: null
- property int gridColumns: controller?.gridColumns ?? 4
- property var _visualRows: []
- property var _flatIndexToRowMap: ({})
- property var _cumulativeHeights: []
-
- signal itemRightClicked(int index, var item, real mouseX, real mouseY)
-
- function _rebuildVisualModel() {
- var sections = root.controller?.sections ?? [];
- var rows = [];
- var indexMap = {};
- var cumHeights = [];
- var cumY = 0;
-
- for (var s = 0; s < sections.length; s++) {
- var section = sections[s];
- var sectionId = section.id;
-
- cumHeights.push(cumY);
- rows.push({
- _rowId: "h_" + sectionId,
- type: "header",
- section: section,
- sectionId: sectionId,
- height: 32
- });
- cumY += 32;
-
- if (section.collapsed)
- continue;
-
- var versionTrigger = root.controller?.viewModeVersion ?? 0;
- void (versionTrigger);
- var mode = root.controller?.getSectionViewMode(sectionId) ?? "list";
- var items = section.items ?? [];
- var flatStartIndex = section.flatStartIndex ?? 0;
-
- if (mode === "list") {
- for (var i = 0; i < items.length; i++) {
- var flatIdx = flatStartIndex + i;
- indexMap[flatIdx] = rows.length;
- cumHeights.push(cumY);
- rows.push({
- _rowId: items[i].id,
- type: "list_item",
- item: items[i],
- flatIndex: flatIdx,
- sectionId: sectionId,
- height: 52
- });
- cumY += 52;
- }
- } else {
- var cols = root.controller?.getGridColumns(sectionId) ?? root.gridColumns;
- var cellWidth = mode === "tile" ? Math.floor(root.width / 3) : Math.floor(root.width / root.gridColumns);
- var cellHeight = mode === "tile" ? cellWidth * 0.75 : cellWidth + 24;
- var numRows = Math.ceil(items.length / cols);
-
- for (var r = 0; r < numRows; r++) {
- var rowItems = [];
- for (var c = 0; c < cols; c++) {
- var idx = r * cols + c;
- if (idx >= items.length)
- break;
- var fi = flatStartIndex + idx;
- indexMap[fi] = rows.length;
- rowItems.push({
- item: items[idx],
- flatIndex: fi
- });
- }
- cumHeights.push(cumY);
- rows.push({
- _rowId: "gr_" + sectionId + "_" + r,
- type: "grid_row",
- items: rowItems,
- sectionId: sectionId,
- viewMode: mode,
- cols: cols,
- height: cellHeight
- });
- cumY += cellHeight;
- }
- }
- }
-
- root._flatIndexToRowMap = indexMap;
- root._cumulativeHeights = cumHeights;
- root._visualRows = rows;
- }
-
- onGridColumnsChanged: Qt.callLater(_rebuildVisualModel)
- onWidthChanged: Qt.callLater(_rebuildVisualModel)
-
- Connections {
- target: root.controller
- function onSectionsChanged() {
- Qt.callLater(root._rebuildVisualModel);
- }
- function onViewModeVersionChanged() {
- Qt.callLater(root._rebuildVisualModel);
- }
- function onSearchModeChanged() {
- root._visualRows = [];
- root._cumulativeHeights = [];
- root._flatIndexToRowMap = {};
- }
- }
-
- function resetScroll() {
- mainListView.contentY = mainListView.originY;
- }
-
- function ensureVisible(index) {
- if (index < 0 || !controller?.flatModel || index >= controller.flatModel.length)
- return;
- var entry = controller.flatModel[index];
- if (!entry || entry.isHeader)
- return;
- var rowIndex = _flatIndexToRowMap[index];
- if (rowIndex === undefined)
- return;
-
- mainListView.positionViewAtIndex(rowIndex, ListView.Contain);
-
- if (stickyHeader.visible && rowIndex < _cumulativeHeights.length) {
- var rowY = _cumulativeHeights[rowIndex];
- var scrollY = mainListView.contentY - mainListView.originY;
- if (rowY < scrollY + stickyHeader.height) {
- mainListView.contentY = Math.max(mainListView.originY, rowY - stickyHeader.height + mainListView.originY);
- }
- }
- }
-
- function getSelectedItemPosition() {
- var fallback = mapToItem(null, width / 2, height / 2);
- if (!controller?.flatModel || controller.selectedFlatIndex < 0)
- return fallback;
-
- var entry = controller.flatModel[controller.selectedFlatIndex];
- if (!entry || entry.isHeader)
- return fallback;
-
- var rowIndex = _flatIndexToRowMap[controller.selectedFlatIndex];
- if (rowIndex === undefined)
- return fallback;
-
- var rowY = (rowIndex < _cumulativeHeights.length) ? _cumulativeHeights[rowIndex] : 0;
- var row = _visualRows[rowIndex];
- if (!row)
- return fallback;
-
- var itemX = width / 2;
- var itemH = row.height;
-
- if (row.type === "grid_row") {
- var rowItems = row.items;
- for (var i = 0; i < rowItems.length; i++) {
- if (rowItems[i].flatIndex === controller.selectedFlatIndex) {
- var cellWidth = row.viewMode === "tile" ? Math.floor(width / 3) : Math.floor(width / row.cols);
- itemX = i * cellWidth + cellWidth / 2;
- break;
- }
- }
- }
-
- var visualY = rowY - mainListView.contentY + mainListView.originY + itemH / 2;
- var clampedY = Math.max(40, Math.min(height - 40, visualY));
- return mapToItem(null, itemX, clampedY);
- }
-
- Connections {
- target: root.controller
- function onSelectedFlatIndexChanged() {
- if (root.controller?.keyboardNavigationActive) {
- Qt.callLater(() => root.ensureVisible(root.controller.selectedFlatIndex));
- }
- }
- }
-
- DankListView {
- id: mainListView
- anchors.fill: parent
- clip: true
- scrollBarTopMargin: (root.controller?.sections?.length > 0) ? 32 : 0
-
- model: ScriptModel {
- values: root._visualRows
- objectProp: "_rowId"
- }
-
- add: null
- remove: null
- displaced: null
- move: null
-
- delegate: Item {
- id: delegateRoot
- required property var modelData
- required property int index
-
- width: mainListView.width
- height: modelData?.height ?? 52
-
- SectionHeader {
- anchors.fill: parent
- visible: delegateRoot.modelData?.type === "header"
- section: delegateRoot.modelData?.section ?? null
- controller: root.controller
- viewMode: {
- var vt = root.controller?.viewModeVersion ?? 0;
- void (vt);
- return root.controller?.getSectionViewMode(delegateRoot.modelData?.sectionId ?? "") ?? "list";
- }
- canChangeViewMode: {
- var vt = root.controller?.viewModeVersion ?? 0;
- void (vt);
- return root.controller?.canChangeSectionViewMode(delegateRoot.modelData?.sectionId ?? "") ?? false;
- }
- canCollapse: root.controller?.canCollapseSection(delegateRoot.modelData?.sectionId ?? "") ?? false
- }
-
- ResultItem {
- anchors.fill: parent
- visible: delegateRoot.modelData?.type === "list_item"
- item: delegateRoot.modelData?.type === "list_item" ? (delegateRoot.modelData?.item ?? null) : null
- isSelected: delegateRoot.modelData?.type === "list_item" && (delegateRoot.modelData?.flatIndex ?? -1) === root.controller?.selectedFlatIndex
- controller: root.controller
- flatIndex: delegateRoot.modelData?.type === "list_item" ? (delegateRoot.modelData?.flatIndex ?? -1) : -1
-
- onClicked: {
- if (root.controller && delegateRoot.modelData?.item) {
- root.controller.executeItem(delegateRoot.modelData.item);
- }
- }
-
- onRightClicked: (mouseX, mouseY) => {
- root.itemRightClicked(delegateRoot.modelData?.flatIndex ?? -1, delegateRoot.modelData?.item ?? null, mouseX, mouseY);
- }
- }
-
- Row {
- id: gridRowContent
- anchors.fill: parent
- visible: delegateRoot.modelData?.type === "grid_row"
-
- Repeater {
- model: delegateRoot.modelData?.type === "grid_row" ? (delegateRoot.modelData?.items ?? []) : []
-
- Item {
- id: gridCellDelegate
- required property var modelData
- required property int index
-
- readonly property real cellWidth: delegateRoot.modelData?.viewMode === "tile" ? Math.floor(delegateRoot.width / 3) : Math.floor(delegateRoot.width / (delegateRoot.modelData?.cols ?? root.gridColumns))
-
- width: cellWidth
- height: delegateRoot.height
-
- GridItem {
- width: parent.width - 4
- height: parent.height - 4
- anchors.centerIn: parent
- visible: delegateRoot.modelData?.viewMode === "grid"
- item: gridCellDelegate.modelData?.item ?? null
- isSelected: (gridCellDelegate.modelData?.flatIndex ?? -1) === root.controller?.selectedFlatIndex
- controller: root.controller
- flatIndex: gridCellDelegate.modelData?.flatIndex ?? -1
-
- onClicked: {
- if (root.controller && gridCellDelegate.modelData?.item) {
- root.controller.executeItem(gridCellDelegate.modelData.item);
- }
- }
-
- onRightClicked: (mouseX, mouseY) => {
- root.itemRightClicked(gridCellDelegate.modelData?.flatIndex ?? -1, gridCellDelegate.modelData?.item ?? null, mouseX, mouseY);
- }
- }
-
- TileItem {
- width: parent.width - 4
- height: parent.height - 4
- anchors.centerIn: parent
- visible: delegateRoot.modelData?.viewMode === "tile"
- item: gridCellDelegate.modelData?.item ?? null
- isSelected: (gridCellDelegate.modelData?.flatIndex ?? -1) === root.controller?.selectedFlatIndex
- controller: root.controller
- flatIndex: gridCellDelegate.modelData?.flatIndex ?? -1
-
- onClicked: {
- if (root.controller && gridCellDelegate.modelData?.item) {
- root.controller.executeItem(gridCellDelegate.modelData.item);
- }
- }
-
- onRightClicked: (mouseX, mouseY) => {
- root.itemRightClicked(gridCellDelegate.modelData?.flatIndex ?? -1, gridCellDelegate.modelData?.item ?? null, mouseX, mouseY);
- }
- }
- }
- }
- }
- }
- }
-
- Rectangle {
- id: bottomShadow
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: parent.bottom
- height: 24
- z: 100
- visible: {
- if (BlurService.enabled)
- return false;
- if (mainListView.contentHeight <= mainListView.height)
- return false;
- var atBottom = mainListView.contentY >= mainListView.contentHeight - mainListView.height + mainListView.originY - 5;
- if (atBottom)
- return false;
-
- var flatModel = root.controller?.flatModel;
- if (!flatModel || flatModel.length === 0)
- return false;
- var lastItemIdx = -1;
- for (var i = flatModel.length - 1; i >= 0; i--) {
- if (!flatModel[i].isHeader) {
- lastItemIdx = i;
- break;
- }
- }
- if (lastItemIdx >= 0 && root.controller?.selectedFlatIndex === lastItemIdx)
- return false;
- return true;
- }
- gradient: Gradient {
- GradientStop {
- position: 0.0
- color: "transparent"
- }
- GradientStop {
- position: 1.0
- color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
- }
- }
- }
-
- Rectangle {
- id: stickyHeader
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.top: parent.top
- height: 32
- z: 101
- color: Theme.withAlpha(Theme.surfaceContainer, Theme.popupTransparency)
- visible: stickyHeaderSection !== null
-
- readonly property int versionTrigger: root.controller?.viewModeVersion ?? 0
-
- readonly property var stickyHeaderSection: {
- var scrollY = mainListView.contentY - mainListView.originY;
- if (scrollY <= 0)
- return null;
-
- var rows = root._visualRows;
- var heights = root._cumulativeHeights;
- if (rows.length === 0 || heights.length === 0)
- return null;
-
- var lo = 0;
- var hi = rows.length - 1;
- while (lo < hi) {
- var mid = (lo + hi + 1) >> 1;
- if (mid < heights.length && heights[mid] <= scrollY)
- lo = mid;
- else
- hi = mid - 1;
- }
-
- for (var i = lo; i >= 0; i--) {
- if (rows[i].type === "header")
- return rows[i].section;
- }
- return null;
- }
-
- SectionHeader {
- width: parent.width
- section: stickyHeader.stickyHeaderSection
- controller: root.controller
- viewMode: {
- void (stickyHeader.versionTrigger);
- return root.controller?.getSectionViewMode(stickyHeader.stickyHeaderSection?.id) ?? "list";
- }
- canChangeViewMode: {
- void (stickyHeader.versionTrigger);
- return root.controller?.canChangeSectionViewMode(stickyHeader.stickyHeaderSection?.id) ?? false;
- }
- canCollapse: {
- void (stickyHeader.versionTrigger);
- return root.controller?.canCollapseSection(stickyHeader.stickyHeaderSection?.id) ?? false;
- }
- isSticky: true
- }
- }
-
- Item {
- anchors.centerIn: parent
- visible: (!root.controller?.sections || root.controller.sections.length === 0) && !root.controller?.isFileSearching
- width: emptyColumn.implicitWidth
- height: emptyColumn.implicitHeight
-
- Column {
- id: emptyColumn
- spacing: Theme.spacingM
-
- DankIcon {
- anchors.horizontalCenter: parent.horizontalCenter
- name: getEmptyIcon()
- size: 48
- color: Theme.outlineButton
-
- function getEmptyIcon() {
- var mode = root.controller?.searchMode ?? "all";
- switch (mode) {
- case "files":
- var fileType = root.controller?.fileSearchType ?? "all";
- switch (fileType) {
- case "dir":
- return "folder_open";
- case "file":
- return "insert_drive_file";
- default:
- return "folder_open";
- }
- case "plugins":
- return "extension";
- case "apps":
- return "apps";
- default:
- return "search_off";
- }
- }
- }
-
- StyledText {
- anchors.horizontalCenter: parent.horizontalCenter
- text: getEmptyText()
- font.pixelSize: Theme.fontSizeMedium
- color: Theme.surfaceVariantText
- horizontalAlignment: Text.AlignHCenter
-
- function getEmptyText() {
- var mode = root.controller?.searchMode ?? "all";
- var hasQuery = root.controller?.searchQuery?.length > 0;
-
- switch (mode) {
- case "files":
- if (!DSearchService.dsearchAvailable)
- return I18n.tr("File search requires dsearch\nInstall from github.com/AvengeMedia/danksearch");
- if (!hasQuery)
- return I18n.tr("Type to search files");
- if (root.controller.searchQuery.length < 2)
- return I18n.tr("Type at least 2 characters");
- var fileType = root.controller?.fileSearchType ?? "all";
- switch (fileType) {
- case "dir":
- return I18n.tr("No folders found");
- case "file":
- return I18n.tr("No files found");
- default:
- return I18n.tr("No results found");
- }
- case "plugins":
- return hasQuery ? I18n.tr("No plugin results") : I18n.tr("Browse or search plugins");
- case "apps":
- return I18n.tr("No apps found");
- default:
- return I18n.tr("No results found");
- }
- }
- }
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Scorer.js b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Scorer.js
deleted file mode 100644
index 7d54df7..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Scorer.js
+++ /dev/null
@@ -1,265 +0,0 @@
-.pragma library
-
-const Weights = {
- exactMatch: 10000,
- prefixMatch: 5000,
- wordBoundary: 3000,
- substring: 500,
- fuzzy: 100,
- frecency: 2000,
- typeBonus: {
- app: 1000,
- plugin: 900,
- file: 800,
- action: 600
- }
-}
-
-function tokenize(text) {
- return text.toLowerCase().trim().split(/[\s\-_]+/).filter(function (w) { return w.length > 0 })
-}
-
-function hasWordBoundaryMatch(text, query) {
- var textWords = tokenize(text)
- var queryWords = tokenize(query)
-
- if (queryWords.length === 0) return false
- if (queryWords.length > textWords.length) return false
-
- for (var i = 0; i <= textWords.length - queryWords.length; i++) {
- var allMatch = true
- for (var j = 0; j < queryWords.length; j++) {
- if (!textWords[i + j].startsWith(queryWords[j])) {
- allMatch = false
- break
- }
- }
- if (allMatch) return true
- }
- return false
-}
-
-function levenshteinDistance(s1, s2) {
- var len1 = s1.length
- var len2 = s2.length
- var prev = new Array(len2 + 1)
- var curr = new Array(len2 + 1)
-
- for (var j = 0; j <= len2; j++)
- prev[j] = j
-
- for (var i = 1; i <= len1; i++) {
- curr[0] = i
- for (var j = 1; j <= len2; j++) {
- var cost = s1[i - 1] === s2[j - 1] ? 0 : 1
- curr[j] = Math.min(prev[j] + 1, curr[j - 1] + 1, prev[j - 1] + cost)
- }
- var tmp = prev
- prev = curr
- curr = tmp
- }
- return prev[len2]
-}
-
-function fuzzyScore(text, query) {
- var maxDistance = query.length === 3 ? 1 : query.length <= 6 ? 2 : 3
- var bestScore = 0
-
- if (Math.abs(text.length - query.length) <= maxDistance) {
- var distance = levenshteinDistance(text, query)
- if (distance <= maxDistance) {
- var maxLen = Math.max(text.length, query.length)
- bestScore = 1 - (distance / maxLen)
- }
- }
-
- var words = tokenize(text)
- for (var i = 0; i < words.length && bestScore < 0.8; i++) {
- if (Math.abs(words[i].length - query.length) > maxDistance) continue
- var wordDistance = levenshteinDistance(words[i], query)
- if (wordDistance <= maxDistance) {
- var wordMaxLen = Math.max(words[i].length, query.length)
- var score = 1 - (wordDistance / wordMaxLen)
- bestScore = Math.max(bestScore, score)
- }
- }
-
- return bestScore
-}
-
-function getTimeBucketWeight(daysSinceUsed) {
- for (var i = 0; i < TimeBuckets.length; i++) {
- if (daysSinceUsed <= TimeBuckets[i].maxDays) {
- return TimeBuckets[i].weight
- }
- }
- return 10
-}
-
-function calculateTextScore(name, query) {
- if (name === query) return Weights.exactMatch
- if (name.startsWith(query)) return Weights.prefixMatch
- if (hasWordBoundaryMatch(name, query)) return Weights.wordBoundary
- if (name.includes(query)) return Weights.substring
-
- if (query.length >= 3) {
- var fs = fuzzyScore(name, query)
- if (fs > 0) return fs * Weights.fuzzy
- }
-
- return 0
-}
-
-function score(item, query, frecencyData) {
- var typeBonus = Weights.typeBonus[item.type] || 0
-
- if (!query || query.length === 0) {
- var usageCount = frecencyData ? frecencyData.usageCount : 0
- return typeBonus + (usageCount * 100)
- }
-
- var name = (item.name || "").toLowerCase()
- var q = query.toLowerCase()
-
- var textScore = calculateTextScore(name, q)
-
- if (textScore === 0 && item.subtitle) {
- var subtitleScore = calculateTextScore(item.subtitle.toLowerCase(), q)
- textScore = subtitleScore * 0.5
- }
-
- if (textScore === 0 && item.keywords) {
- for (var i = 0; i < item.keywords.length; i++) {
- var keywordScore = calculateTextScore(item.keywords[i].toLowerCase(), q)
- if (keywordScore > 0) {
- textScore = keywordScore * 0.3
- break
- }
- }
- }
-
- if (textScore === 0) return 0
-
- var usageBonus = frecencyData ? Math.min(frecencyData.usageCount * 50, Weights.frecency) : 0
-
- return textScore + usageBonus + typeBonus
-}
-
-function scoreItems(items, query, getFrecencyFn) {
- var scored = []
-
- for (var i = 0; i < items.length; i++) {
- var item = items[i]
- var itemScore
-
- if (item._preScored !== undefined && (query || item._preScored > 900)) {
- itemScore = item._preScored
- } else {
- var frecencyData = getFrecencyFn ? getFrecencyFn(item) : null
- itemScore = score(item, query, frecencyData)
- }
-
- if (itemScore > 0 || !query || query.length === 0) {
- scored.push({
- item: item,
- score: itemScore
- })
- }
- }
-
- scored.sort(function (a, b) {
- return b.score - a.score
- })
-
- return scored
-}
-
-function groupBySection(scoredItems, sectionOrder, sortAlphabetically, maxPerSection) {
- var sections = {}
- var result = []
- var limit = maxPerSection || 50
-
- for (var i = 0; i < sectionOrder.length; i++) {
- var sectionId = sectionOrder[i].id
- sections[sectionId] = {
- id: sectionId,
- title: sectionOrder[i].title,
- icon: sectionOrder[i].icon,
- priority: sectionOrder[i].priority,
- items: [],
- collapsed: false,
- flatStartIndex: 0
- }
- }
-
- for (var i = 0; i < scoredItems.length; i++) {
- var scoredItem = scoredItems[i]
- var item = scoredItem.item
- var sectionId = item.section || "apps"
-
- if (sections[sectionId] && sections[sectionId].items.length < limit) {
- sections[sectionId].items.push(item)
- } else if (sections["apps"] && sections["apps"].items.length < limit) {
- sections["apps"].items.push(item)
- }
- }
-
- for (var i = 0; i < sectionOrder.length; i++) {
- var section = sections[sectionOrder[i].id]
- if (section && section.items.length > 0) {
- if (sortAlphabetically && section.id === "apps") {
- section.items.sort(function (a, b) {
- return (a.name || "").localeCompare(b.name || "")
- })
- }
- result.push(section)
- }
- }
-
- return result
-}
-
-function flattenSections(sections) {
- var flat = []
- flat._sectionBounds = null
- var bounds = {}
-
- for (var i = 0; i < sections.length; i++) {
- var section = sections[i]
-
- flat.push({
- isHeader: true,
- section: section,
- sectionId: section.id,
- sectionIndex: i
- })
-
- var itemStart = flat.length
- section.flatStartIndex = itemStart
-
- if (!section.collapsed) {
- for (var j = 0; j < section.items.length; j++) {
- flat.push({
- isHeader: false,
- item: section.items[j],
- sectionId: section.id,
- sectionIndex: i,
- indexInSection: j
- })
- }
- }
-
- var itemEnd = flat.length - 1
- var itemCount = flat.length - itemStart
- if (itemCount > 0) {
- bounds[section.id] = {
- start: itemStart,
- end: itemEnd,
- count: itemCount
- }
- }
- }
-
- flat._sectionBounds = bounds
- return flat
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Section.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Section.qml
deleted file mode 100644
index aba4c2f..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Section.qml
+++ /dev/null
@@ -1,114 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import QtQuick
-import Quickshell
-import qs.Common
-
-Item {
- id: root
-
- property var section: null
- property var controller: null
- property string viewMode: "list"
- property int gridColumns: 4
- property int startIndex: 0
-
- signal itemClicked(int flatIndex)
- signal itemRightClicked(int flatIndex, var item, real mouseX, real mouseY)
-
- height: headerItem.height + (section?.collapsed ? 0 : contentLoader.height + Theme.spacingXS)
- width: parent?.width ?? 200
-
- SectionHeader {
- id: headerItem
- width: parent.width
- section: root.section
- controller: root.controller
- viewMode: root.viewMode
- canChangeViewMode: root.controller?.canChangeSectionViewMode(root.section?.id) ?? true
-
- onViewModeToggled: {
- if (root.controller && root.section) {
- var newMode = root.viewMode === "list" ? "grid" : "list";
- root.controller.setSectionViewMode(root.section.id, newMode);
- }
- }
- }
-
- Loader {
- id: contentLoader
- anchors.top: headerItem.bottom
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.topMargin: Theme.spacingXS
- active: !root.section?.collapsed
- visible: active
-
- sourceComponent: root.viewMode === "grid" ? gridComponent : listComponent
-
- Component {
- id: listComponent
-
- Column {
- spacing: 2
- width: contentLoader.width
-
- Repeater {
- model: ScriptModel {
- values: root.section?.items ?? []
- objectProp: "id"
- }
-
- ResultItem {
- required property var modelData
- required property int index
-
- width: parent?.width ?? 200
- item: modelData
- isSelected: (root.startIndex + index) === root.controller?.selectedFlatIndex
- controller: root.controller
- flatIndex: root.startIndex + index
-
- onClicked: root.itemClicked(root.startIndex + index)
- onRightClicked: (mouseX, mouseY) => {
- root.itemRightClicked(root.startIndex + index, modelData, mouseX, mouseY);
- }
- }
- }
- }
- }
-
- Component {
- id: gridComponent
-
- Flow {
- width: contentLoader.width
- spacing: 4
-
- Repeater {
- model: ScriptModel {
- values: root.section?.items ?? []
- objectProp: "id"
- }
-
- GridItem {
- required property var modelData
- required property int index
-
- width: Math.floor(contentLoader.width / root.gridColumns)
- height: width + 24
- item: modelData
- isSelected: (root.startIndex + index) === root.controller?.selectedFlatIndex
- controller: root.controller
- flatIndex: root.startIndex + index
-
- onClicked: root.itemClicked(root.startIndex + index)
- onRightClicked: (mouseX, mouseY) => {
- root.itemRightClicked(root.startIndex + index, modelData, mouseX, mouseY);
- }
- }
- }
- }
- }
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/SectionHeader.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/SectionHeader.qml
deleted file mode 100644
index ee366c7..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/SectionHeader.qml
+++ /dev/null
@@ -1,340 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import QtQuick
-import QtQuick.Controls
-import qs.Common
-import qs.Services
-import qs.Widgets
-
-Rectangle {
- id: root
-
- property var section: null
- property var controller: null
- property string viewMode: "list"
- property bool canChangeViewMode: true
- property bool canCollapse: true
- property bool isSticky: false
-
- signal viewModeToggled
-
- width: parent?.width ?? 200
- height: 32
- color: isSticky ? "transparent" : (hoverArea.containsMouse ? Theme.surfaceHover : "transparent")
- radius: Theme.cornerRadius
-
- MouseArea {
- id: hoverArea
- anchors.fill: parent
- hoverEnabled: true
- acceptedButtons: Qt.NoButton
- }
-
- Row {
- id: leftContent
- anchors.left: parent.left
- anchors.leftMargin: Theme.spacingXS
- anchors.verticalCenter: parent.verticalCenter
- spacing: Theme.spacingS
-
- // Whether the apps category picker should replace the plain title
- readonly property bool hasAppCategories: root.section?.id === "apps" && (root.controller?.appCategories?.length ?? 0) > 0
-
- DankIcon {
- anchors.verticalCenter: parent.verticalCenter
- // Hide section icon when the category chip already shows one
- visible: !leftContent.hasAppCategories
- name: root.section?.icon ?? "folder"
- size: 16
- color: Theme.surfaceVariantText
- }
-
- // Plain title — hidden when the category chip is shown
- StyledText {
- anchors.verticalCenter: parent.verticalCenter
- visible: !leftContent.hasAppCategories
- text: root.section?.title ?? ""
- font.pixelSize: Theme.fontSizeSmall
- font.weight: Font.Medium
- color: Theme.surfaceVariantText
- }
-
- // Compact inline category chip — only visible on the apps section
- Item {
- id: categoryChip
- visible: leftContent.hasAppCategories
- anchors.verticalCenter: parent.verticalCenter
- // Size to content with a fixed-min width so it doesn't jump around
- width: chipRow.implicitWidth + Theme.spacingM * 2
- height: 24
-
- readonly property string currentCategory: root.controller?.appCategory || (root.controller?.appCategories?.length > 0 ? root.controller.appCategories[0] : "")
- readonly property var iconMap: {
- const cats = root.controller?.appCategories ?? [];
- const m = {};
- cats.forEach(c => { m[c] = AppSearchService.getCategoryIcon(c); });
- return m;
- }
-
- Rectangle {
- anchors.fill: parent
- radius: Theme.cornerRadius
- color: chipArea.containsMouse || categoryPopup.visible ? Theme.surfaceContainerHigh : "transparent"
- border.color: categoryPopup.visible ? Theme.primary : Theme.outlineMedium
- border.width: categoryPopup.visible ? 2 : 1
- }
-
- Row {
- id: chipRow
- anchors.centerIn: parent
- spacing: Theme.spacingXS
-
- DankIcon {
- anchors.verticalCenter: parent.verticalCenter
- name: categoryChip.iconMap[categoryChip.currentCategory] ?? "apps"
- size: 14
- color: Theme.surfaceText
- }
-
- StyledText {
- anchors.verticalCenter: parent.verticalCenter
- text: categoryChip.currentCategory
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.surfaceText
- }
-
- DankIcon {
- anchors.verticalCenter: parent.verticalCenter
- name: categoryPopup.visible ? "expand_less" : "expand_more"
- size: 14
- color: Theme.surfaceVariantText
- }
- }
-
- MouseArea {
- id: chipArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: {
- if (categoryPopup.visible) {
- categoryPopup.close();
- } else {
- const pos = categoryChip.mapToItem(Overlay.overlay, 0, 0);
- categoryPopup.x = pos.x;
- categoryPopup.y = pos.y + categoryChip.height + 4;
- categoryPopup.open();
- }
- }
- }
-
- Popup {
- id: categoryPopup
- parent: Overlay.overlay
- width: Math.max(categoryChip.width, 180)
- padding: 0
- modal: true
- dim: false
- closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
-
- background: Rectangle { color: "transparent" }
-
- contentItem: Rectangle {
- radius: Theme.cornerRadius
- color: Qt.rgba(Theme.surfaceContainer.r, Theme.surfaceContainer.g, Theme.surfaceContainer.b, 1)
- border.color: Theme.primary
- border.width: 2
-
- ElevationShadow {
- anchors.fill: parent
- z: -1
- level: Theme.elevationLevel2
- fallbackOffset: 4
- targetRadius: parent.radius
- targetColor: parent.color
- borderColor: parent.border.color
- borderWidth: parent.border.width
- shadowEnabled: Theme.elevationEnabled && SettingsData.popoutElevationEnabled
- }
-
- ListView {
- id: categoryList
- anchors.fill: parent
- anchors.margins: Theme.spacingS
- model: root.controller?.appCategories ?? []
- spacing: 2
- clip: true
- interactive: contentHeight > height
- implicitHeight: contentHeight
-
- delegate: Rectangle {
- id: catDelegate
- required property string modelData
- required property int index
- width: categoryList.width
- height: 32
- radius: Theme.cornerRadius
- readonly property bool isCurrent: categoryChip.currentCategory === modelData
- color: isCurrent ? Theme.primaryHover : catArea.containsMouse ? Theme.primaryHoverLight : "transparent"
-
- Row {
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.verticalCenter: parent.verticalCenter
- anchors.leftMargin: Theme.spacingS
- anchors.rightMargin: Theme.spacingS
- spacing: Theme.spacingS
-
- DankIcon {
- anchors.verticalCenter: parent.verticalCenter
- name: categoryChip.iconMap[catDelegate.modelData] ?? "apps"
- size: 16
- color: catDelegate.isCurrent ? Theme.primary : Theme.surfaceText
- }
-
- StyledText {
- anchors.verticalCenter: parent.verticalCenter
- text: catDelegate.modelData
- font.pixelSize: Theme.fontSizeMedium
- color: catDelegate.isCurrent ? Theme.primary : Theme.surfaceText
- font.weight: catDelegate.isCurrent ? Font.Medium : Font.Normal
- }
- }
-
- MouseArea {
- id: catArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: {
- if (root.controller)
- root.controller.setAppCategory(catDelegate.modelData);
- categoryPopup.close();
- }
- }
- }
- }
- }
-
- // Size to list content, cap at 10 visible items
- height: Math.min((root.controller?.appCategories?.length ?? 0) * 34, 10 * 34) + Theme.spacingS * 2 + 4
- }
- }
-
- StyledText {
- anchors.verticalCenter: parent.verticalCenter
- text: root.section?.items?.length ?? 0
- font.pixelSize: Theme.fontSizeSmall
- color: Theme.outlineButton
- }
- }
-
- Row {
- id: rightContent
- anchors.right: parent.right
- anchors.rightMargin: Theme.spacingXS
- anchors.verticalCenter: parent.verticalCenter
- spacing: Theme.spacingS
-
- Row {
- id: viewModeRow
- anchors.verticalCenter: parent.verticalCenter
- spacing: 2
- visible: root.canChangeViewMode && !root.section?.collapsed
-
- Repeater {
- model: [
- {
- mode: "list",
- icon: "view_list"
- },
- {
- mode: "grid",
- icon: "grid_view"
- },
- {
- mode: "tile",
- icon: "view_module"
- }
- ]
-
- Rectangle {
- required property var modelData
- required property int index
-
- width: 20
- height: 20
- radius: 4
- color: root.viewMode === modelData.mode ? Theme.primaryHover : modeArea.containsMouse ? Theme.surfaceHover : "transparent"
-
- DankIcon {
- anchors.centerIn: parent
- name: parent.modelData.icon
- size: 14
- color: root.viewMode === parent.modelData.mode ? Theme.primary : Theme.surfaceVariantText
- }
-
- MouseArea {
- id: modeArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: {
- if (root.viewMode !== parent.modelData.mode && root.controller && root.section) {
- root.controller.setSectionViewMode(root.section.id, parent.modelData.mode);
- }
- }
- }
- }
- }
- }
-
- Item {
- id: collapseButton
- width: root.canCollapse ? 24 : 0
- height: 24
- visible: root.canCollapse
- anchors.verticalCenter: parent.verticalCenter
-
- DankIcon {
- anchors.centerIn: parent
- name: root.section?.collapsed ? "expand_more" : "expand_less"
- size: 16
- color: collapseArea.containsMouse ? Theme.primary : Theme.surfaceVariantText
- }
-
- MouseArea {
- id: collapseArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- onClicked: {
- if (root.controller && root.section) {
- root.controller.toggleSection(root.section.id);
- }
- }
- }
- }
- }
-
- MouseArea {
- anchors.fill: parent
- anchors.rightMargin: rightContent.width + Theme.spacingS
- cursorShape: root.canCollapse ? Qt.PointingHandCursor : Qt.ArrowCursor
- enabled: root.canCollapse
- onClicked: {
- if (root.canCollapse && root.controller && root.section) {
- root.controller.toggleSection(root.section.id);
- }
- }
- }
-
- Rectangle {
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: parent.bottom
- height: 1
- color: Theme.outlineMedium
- visible: root.isSticky
- }
-}
diff --git a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/TileItem.qml b/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/TileItem.qml
deleted file mode 100644
index 0b48802..0000000
--- a/raveos-hyprland-theme/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/TileItem.qml
+++ /dev/null
@@ -1,199 +0,0 @@
-pragma ComponentBehavior: Bound
-
-import QtQuick
-import Quickshell.Wayland
-import qs.Common
-import qs.Services
-import qs.Widgets
-
-Rectangle {
- id: root
-
- property var item: null
- property bool isSelected: false
- property bool isHovered: itemArea.containsMouse
- property var controller: null
- property int flatIndex: -1
-
- signal clicked
- signal rightClicked(real mouseX, real mouseY)
-
- radius: Theme.cornerRadius
- color: isSelected ? Theme.primaryPressed : isHovered ? Theme.primaryPressed : "transparent"
- border.width: isSelected ? 2 : 0
- border.color: Theme.primary
-
- readonly property string toplevelId: item?.data?.toplevelId ?? ""
- readonly property var waylandToplevel: {
- if (!toplevelId || !item?.pluginId)
- return null;
- const pluginInstance = PluginService.pluginInstances[item.pluginId];
- if (!pluginInstance?.getToplevelById)
- return null;
- return pluginInstance.getToplevelById(toplevelId);
- }
- readonly property bool hasScreencopy: waylandToplevel !== null
-
- readonly property string iconValue: {
- if (!item)
- return "";
- if (hasScreencopy)
- return "";
- var data = item.data;
- if (data?.imageUrl)
- return "image:" + data.imageUrl;
- if (data?.imagePath)
- return "image:" + data.imagePath;
- if (data?.path && isImageFile(data.path))
- return "image:" + data.path;
- switch (item.iconType) {
- case "material":
- case "nerd":
- return "material:" + (item.icon || "image");
- case "unicode":
- return "unicode:" + (item.icon || "");
- case "composite":
- return item.iconFull || "";
- case "image":
- default:
- return item.icon || "";
- }
- }
-
- function isImageFile(path) {
- if (!path)
- return false;
- var ext = path.split('.').pop().toLowerCase();
- return ["jpg", "jpeg", "png", "gif", "webp", "svg", "bmp", "jxl", "avif", "heif", "exr"].indexOf(ext) >= 0;
- }
-
- DankRipple {
- id: rippleLayer
- rippleColor: Theme.surfaceText
- cornerRadius: root.radius
- }
-
- Item {
- anchors.fill: parent
- anchors.margins: 4
-
- Rectangle {
- id: imageContainer
- anchors.fill: parent
- radius: Theme.cornerRadius - 2
- color: Theme.surfaceContainerHigh
- clip: true
-
- ScreencopyView {
- id: screencopyView
- anchors.fill: parent
- captureSource: root.waylandToplevel
- live: root.hasScreencopy
- visible: root.hasScreencopy
-
- Rectangle {
- anchors.fill: parent
- color: root.isHovered ? Theme.withAlpha(Theme.surfaceVariant, 0.2) : "transparent"
- }
- }
-
- AppIconRenderer {
- anchors.fill: parent
- iconValue: root.iconValue
- iconSize: Math.min(parent.width, parent.height)
- fallbackText: (root.item?.name?.length > 0) ? root.item.name.charAt(0).toUpperCase() : "?"
- materialIconSizeAdjustment: iconSize * 0.3
- visible: !root.hasScreencopy
- }
-
- Rectangle {
- anchors.left: parent.left
- anchors.right: parent.right
- anchors.bottom: parent.bottom
- height: labelText.implicitHeight + Theme.spacingS * 2
- color: Theme.withAlpha(Theme.surfaceContainer, 0.85)
- visible: root.item?.name?.length > 0
-
- Text {
- id: labelText
- anchors.fill: parent
- anchors.margins: Theme.spacingXS
- text: root.item?._hName ?? root.item?.name ?? ""
- textFormat: root.item?._hRich ? Text.RichText : Text.PlainText
- font.pixelSize: Theme.fontSizeSmall
- font.family: Theme.fontFamily
- color: Theme.surfaceText
- elide: Text.ElideRight
- horizontalAlignment: Text.AlignLeft
- verticalAlignment: Text.AlignVCenter
- }
- }
-
- Rectangle {
- anchors.top: parent.top
- anchors.right: parent.right
- anchors.margins: Theme.spacingXS
- width: 20
- height: 20
- radius: 10
- color: Theme.primary
- visible: root.isSelected
-
- DankIcon {
- anchors.centerIn: parent
- name: "check"
- size: 14
- color: Theme.primaryText
- }
- }
-
- Rectangle {
- id: attributionBadge
- anchors.top: parent.top
- anchors.left: parent.left
- anchors.margins: Theme.spacingXS
- width: root.hasScreencopy ? 28 : 40
- height: root.hasScreencopy ? 28 : 16
- radius: root.hasScreencopy ? 14 : 4
- color: root.hasScreencopy ? Theme.surfaceContainer : "transparent"
- visible: attributionImage.status === Image.Ready
- opacity: 0.95
-
- Image {
- id: attributionImage
- anchors.fill: parent
- anchors.margins: root.hasScreencopy ? 4 : 0
- fillMode: Image.PreserveAspectFit
- source: root.item?.data?.attribution || ""
- mipmap: true
- }
- }
- }
- }
-
- MouseArea {
- id: itemArea
- anchors.fill: parent
- hoverEnabled: true
- cursorShape: Qt.PointingHandCursor
- acceptedButtons: Qt.LeftButton | Qt.RightButton
-
- onPressed: mouse => {
- if (mouse.button === Qt.LeftButton)
- rippleLayer.trigger(mouse.x, mouse.y);
- }
- onClicked: mouse => {
- if (mouse.button === Qt.RightButton) {
- var scenePos = mapToItem(null, mouse.x, mouse.y);
- root.rightClicked(scenePos.x, scenePos.y);
- return;
- }
- root.clicked();
- }
-
- onPositionChanged: {
- if (root.controller)
- root.controller.keyboardNavigationActive = false;
- }
- }
-}