From 70ca3fef77ee8bdc6e3ac28589a6fa08c024cc69 Mon Sep 17 00:00:00 2001 From: AlexanderCurl Date: Sat, 18 Apr 2026 17:46:06 +0100 Subject: Replaced file structures for themes in the correct format --- .../Modals/DankLauncherV2/ActionPanel.qml | 256 --- .../Modals/DankLauncherV2/Controller.qml | 1894 -------------------- .../Modals/DankLauncherV2/ControllerUtils.js | 128 -- .../Modals/DankLauncherV2/DankLauncherV2Modal.qml | 465 ----- .../quickshell/Modals/DankLauncherV2/GridItem.qml | 105 -- .../Modals/DankLauncherV2/ItemTransformers.js | 237 --- .../Modals/DankLauncherV2/LauncherContent.qml | 1075 ----------- .../Modals/DankLauncherV2/LauncherContextMenu.qml | 510 ------ .../Modals/DankLauncherV2/NavigationHelpers.js | 254 --- .../Modals/DankLauncherV2/ResultItem.qml | 196 -- .../Modals/DankLauncherV2/ResultsList.qml | 498 ----- .../quickshell/Modals/DankLauncherV2/Scorer.js | 265 --- .../quickshell/Modals/DankLauncherV2/Section.qml | 114 -- .../Modals/DankLauncherV2/SectionHeader.qml | 340 ---- .../quickshell/Modals/DankLauncherV2/TileItem.qml | 199 -- 15 files changed, 6536 deletions(-) delete mode 100644 raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ActionPanel.qml delete mode 100644 raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Controller.qml delete mode 100644 raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ControllerUtils.js delete mode 100644 raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/DankLauncherV2Modal.qml delete mode 100644 raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/GridItem.qml delete mode 100644 raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ItemTransformers.js delete mode 100644 raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/LauncherContent.qml delete mode 100644 raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/LauncherContextMenu.qml delete mode 100644 raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/NavigationHelpers.js delete mode 100644 raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ResultItem.qml delete mode 100644 raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ResultsList.qml delete mode 100644 raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Scorer.js delete mode 100644 raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Section.qml delete mode 100644 raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/SectionHeader.qml delete mode 100644 raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/TileItem.qml (limited to 'raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2') diff --git a/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ActionPanel.qml b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ActionPanel.qml deleted file mode 100644 index 31ada32..0000000 --- a/raveos-theme/hyprland/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-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Controller.qml b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Controller.qml deleted file mode 100644 index 67cb606..0000000 --- a/raveos-theme/hyprland/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 '' + before + '' + match + '' + after + ''; - } - - 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-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ControllerUtils.js b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ControllerUtils.js deleted file mode 100644 index a06285f..0000000 --- a/raveos-theme/hyprland/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-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/DankLauncherV2Modal.qml b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/DankLauncherV2Modal.qml deleted file mode 100644 index 859022c..0000000 --- a/raveos-theme/hyprland/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-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/GridItem.qml b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/GridItem.qml deleted file mode 100644 index a7f39c3..0000000 --- a/raveos-theme/hyprland/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-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ItemTransformers.js b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ItemTransformers.js deleted file mode 100644 index 61c108c..0000000 --- a/raveos-theme/hyprland/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-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/LauncherContent.qml b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/LauncherContent.qml deleted file mode 100644 index 4372515..0000000 --- a/raveos-theme/hyprland/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-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/LauncherContextMenu.qml b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/LauncherContextMenu.qml deleted file mode 100644 index 3c55590..0000000 --- a/raveos-theme/hyprland/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-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/NavigationHelpers.js b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/NavigationHelpers.js deleted file mode 100644 index 1e78b11..0000000 --- a/raveos-theme/hyprland/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-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ResultItem.qml b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ResultItem.qml deleted file mode 100644 index 0a50cd3..0000000 --- a/raveos-theme/hyprland/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-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ResultsList.qml b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/ResultsList.qml deleted file mode 100644 index 53a2d45..0000000 --- a/raveos-theme/hyprland/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-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Scorer.js b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Scorer.js deleted file mode 100644 index 7d54df7..0000000 --- a/raveos-theme/hyprland/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-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Section.qml b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/Section.qml deleted file mode 100644 index aba4c2f..0000000 --- a/raveos-theme/hyprland/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-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/SectionHeader.qml b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/SectionHeader.qml deleted file mode 100644 index ee366c7..0000000 --- a/raveos-theme/hyprland/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-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/TileItem.qml b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Modals/DankLauncherV2/TileItem.qml deleted file mode 100644 index 0b48802..0000000 --- a/raveos-theme/hyprland/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; - } - } -} -- cgit v1.3