mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-10-16 08:14:03 -04:00
257 lines
9.0 KiB
QML
257 lines
9.0 KiB
QML
import QtQuick
|
|
import qs.Common
|
|
import qs.Services
|
|
import qs.Widgets
|
|
import "ControllerUtils.js" as Utils
|
|
|
|
DContextMenu {
|
|
id: root
|
|
|
|
property var item: null
|
|
property var controller: null
|
|
property var searchField: null
|
|
property var parentHandler: null
|
|
property string pinDockId: ""
|
|
|
|
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.getDockPins(pinDockId).includes(appId)
|
|
readonly property bool isRegularApp: item?.type === "app" && !item.isCore && desktopEntry
|
|
readonly property bool isFlatpakApp: isRegularApp && (item?.source === "flatpak" || !!item?.flatpakId || Utils.classifyAppSource(desktopEntry) === "flatpak")
|
|
readonly property string flatpakAppId: item?.flatpakId || (isFlatpakApp ? Utils.extractFlatpakAppId(desktopEntry) : "")
|
|
readonly property bool isPluginItem: item?.type === "plugin"
|
|
|
|
signal editAppRequested(var app)
|
|
|
|
layerNamespace: "dms:launcher-context-menu"
|
|
keyboardNavigable: true
|
|
|
|
menuItems: {
|
|
if (isPluginItem)
|
|
return getPluginContextMenuActions().map(act => ({
|
|
type: "item",
|
|
icon: act.icon || "play_arrow",
|
|
text: act.text || act.name || "",
|
|
action: () => executePluginAction(act)
|
|
}));
|
|
|
|
if (item?.type !== "app" && item?.actions?.length > 0)
|
|
return item.actions.map(act => ({
|
|
type: "item",
|
|
icon: act.icon || "play_arrow",
|
|
text: act.name || "",
|
|
action: () => executeLauncherAction(act)
|
|
}));
|
|
|
|
const items = [];
|
|
if (item?.type === "app" && pinDockId)
|
|
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?.length > 0) {
|
|
items.push({
|
|
type: "separator"
|
|
});
|
|
for (const act of item.actions)
|
|
items.push({
|
|
type: "item",
|
|
icon: act.icon || "play_arrow",
|
|
text: act.name || "",
|
|
action: () => executeDesktopAction(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", "verb, start an application"),
|
|
action: launchApp
|
|
});
|
|
if (isFlatpakApp && flatpakAppId)
|
|
items.push({
|
|
type: "separator"
|
|
}, {
|
|
type: "item",
|
|
icon: "delete",
|
|
text: I18n.tr("Uninstall", "context menu action to uninstall app") + "…",
|
|
isDestructive: true,
|
|
action: uninstallCurrentApp
|
|
});
|
|
return items;
|
|
}
|
|
|
|
onRenderActiveChanged: {
|
|
if (renderActive)
|
|
return;
|
|
if (parentHandler)
|
|
parentHandler.enabled = true;
|
|
if (searchField?.visible)
|
|
Qt.callLater(() => searchField.forceActiveFocus());
|
|
}
|
|
|
|
function hasContextMenuActions(spotlightItem) {
|
|
if (!spotlightItem)
|
|
return false;
|
|
if (spotlightItem.type === "app")
|
|
return true;
|
|
if (spotlightItem.type === "plugin" && spotlightItem.pluginId) {
|
|
const instance = PluginService.pluginInstances[spotlightItem.pluginId];
|
|
if (typeof instance?.getContextMenuActions !== "function")
|
|
return false;
|
|
const actions = instance.getContextMenuActions(spotlightItem.data);
|
|
return Array.isArray(actions) && actions.length > 0;
|
|
}
|
|
return spotlightItem.actions?.length > 0;
|
|
}
|
|
|
|
function getPluginContextMenuActions() {
|
|
if (!isPluginItem || !item?.pluginId)
|
|
return [];
|
|
const instance = PluginService.pluginInstances[item.pluginId];
|
|
if (typeof instance?.getContextMenuActions !== "function")
|
|
return [];
|
|
const actions = instance.getContextMenuActions(item.data);
|
|
return Array.isArray(actions) ? actions : [];
|
|
}
|
|
|
|
function show(x, y, spotlightItem, fromKeyboard) {
|
|
if (!spotlightItem?.data)
|
|
return;
|
|
item = spotlightItem;
|
|
|
|
const modal = parentHandler?.parentModal ?? null;
|
|
const screenRef = modal?.effectiveScreen ?? parentHandler?.Window?.window?.screen ?? searchField?.Window?.window?.screen ?? null;
|
|
const screenX = screenRef?.x || 0;
|
|
const screenY = screenRef?.y || 0;
|
|
const screenRelativeX = modal ? ((modal.alignedX ?? 0) + x) : ((parentHandler ? parentHandler.mapToGlobal(x, y).x : x) - screenX);
|
|
const screenRelativeY = modal ? ((modal.alignedY ?? 0) + y) : ((parentHandler ? parentHandler.mapToGlobal(x, y).y : y) - screenY);
|
|
|
|
pinDockId = SettingsData.dockConfigForAction(screenRef)?.id ?? "";
|
|
if (parentHandler)
|
|
parentHandler.enabled = false;
|
|
open(screenRef, screenRelativeX + Theme.spacingXS, screenRelativeY + Theme.spacingXS, fromKeyboard);
|
|
}
|
|
|
|
function executePluginAction(actionOrObj) {
|
|
const actionFunc = typeof actionOrObj === "function" ? actionOrObj : actionOrObj?.action;
|
|
const closeLauncher = typeof actionOrObj === "object" && actionOrObj?.closeLauncher;
|
|
if (typeof actionFunc === "function")
|
|
actionFunc();
|
|
if (closeLauncher)
|
|
controller?.itemExecuted();
|
|
else
|
|
controller?.performSearch();
|
|
hide();
|
|
}
|
|
|
|
function executeLauncherAction(actionData) {
|
|
if (!controller || !item || !actionData)
|
|
return;
|
|
controller.executeAction(item, actionData);
|
|
hide();
|
|
}
|
|
|
|
function togglePin() {
|
|
if (!appId || !SettingsData.getDockConfig(pinDockId))
|
|
return;
|
|
const pins = SessionData.getDockPins(pinDockId);
|
|
if (!isPinned)
|
|
SettingsData.ensureDockApps(pinDockId);
|
|
SessionData.setDockPins(pinDockId, isPinned ? pins.filter(id => id !== appId) : pins.concat([appId]));
|
|
hide();
|
|
}
|
|
|
|
function hideCurrentApp() {
|
|
if (!appId)
|
|
return;
|
|
SessionData.hideApp(appId);
|
|
controller?.performSearch();
|
|
hide();
|
|
}
|
|
|
|
function editCurrentApp() {
|
|
if (!desktopEntry)
|
|
return;
|
|
editAppRequested(desktopEntry);
|
|
hide();
|
|
}
|
|
|
|
function uninstallCurrentApp() {
|
|
if (!isFlatpakApp || !flatpakAppId)
|
|
return;
|
|
const targetFlatpakId = flatpakAppId;
|
|
const appName = item?.name || desktopEntry?.name || flatpakAppId;
|
|
const currentAppId = appId;
|
|
hide();
|
|
controller?.itemExecuted();
|
|
AppSearchService.requestUninstallFlatpak(currentAppId, appName, targetFlatpakId);
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|