mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2026-01-24 21:42:51 -05:00
launcher: allow terminal apps
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
pragma Singleton
|
pragma Singleton
|
||||||
|
|
||||||
pragma ComponentBehavior: Bound
|
pragma ComponentBehavior: Bound
|
||||||
|
|
||||||
import QtQuick
|
import QtQuick
|
||||||
@@ -9,111 +8,117 @@ import qs.Common
|
|||||||
Singleton {
|
Singleton {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
property var applications: DesktopEntries.applications.values.filter(app => !app.noDisplay && !app.runInTerminal)
|
property var applications: DesktopEntries.applications.values.filter(app => !app.noDisplay)
|
||||||
|
|
||||||
readonly property int maxResults: 10
|
readonly property int maxResults: 10
|
||||||
readonly property int frecencySampleSize: 10
|
readonly property int frecencySampleSize: 10
|
||||||
|
|
||||||
readonly property var timeBuckets: [{
|
readonly property var timeBuckets: [
|
||||||
|
{
|
||||||
"maxDays": 4,
|
"maxDays": 4,
|
||||||
"weight": 100
|
"weight": 100
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"maxDays": 14,
|
"maxDays": 14,
|
||||||
"weight": 70
|
"weight": 70
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"maxDays": 31,
|
"maxDays": 31,
|
||||||
"weight": 50
|
"weight": 50
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"maxDays": 90,
|
"maxDays": 90,
|
||||||
"weight": 30
|
"weight": 30
|
||||||
}, {
|
},
|
||||||
|
{
|
||||||
"maxDays": 99999,
|
"maxDays": 99999,
|
||||||
"weight": 10
|
"weight": 10
|
||||||
}]
|
}
|
||||||
|
]
|
||||||
|
|
||||||
function tokenize(text) {
|
function tokenize(text) {
|
||||||
return text.toLowerCase().trim().split(/[\s\-_]+/).filter(w => w.length > 0)
|
return text.toLowerCase().trim().split(/[\s\-_]+/).filter(w => w.length > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function wordBoundaryMatch(text, query) {
|
function wordBoundaryMatch(text, query) {
|
||||||
const textWords = tokenize(text)
|
const textWords = tokenize(text);
|
||||||
const queryWords = tokenize(query)
|
const queryWords = tokenize(query);
|
||||||
|
|
||||||
if (queryWords.length === 0)
|
if (queryWords.length === 0)
|
||||||
return false
|
return false;
|
||||||
if (queryWords.length > textWords.length)
|
if (queryWords.length > textWords.length)
|
||||||
return false
|
return false;
|
||||||
|
|
||||||
for (var i = 0; i <= textWords.length - queryWords.length; i++) {
|
for (var i = 0; i <= textWords.length - queryWords.length; i++) {
|
||||||
let allMatch = true
|
let allMatch = true;
|
||||||
for (var j = 0; j < queryWords.length; j++) {
|
for (var j = 0; j < queryWords.length; j++) {
|
||||||
if (!textWords[i + j].startsWith(queryWords[j])) {
|
if (!textWords[i + j].startsWith(queryWords[j])) {
|
||||||
allMatch = false
|
allMatch = false;
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (allMatch)
|
if (allMatch)
|
||||||
return true
|
return true;
|
||||||
}
|
}
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function levenshteinDistance(s1, s2) {
|
function levenshteinDistance(s1, s2) {
|
||||||
const len1 = s1.length
|
const len1 = s1.length;
|
||||||
const len2 = s2.length
|
const len2 = s2.length;
|
||||||
const matrix = []
|
const matrix = [];
|
||||||
|
|
||||||
for (var i = 0; i <= len1; i++) {
|
for (var i = 0; i <= len1; i++) {
|
||||||
matrix[i] = [i]
|
matrix[i] = [i];
|
||||||
}
|
}
|
||||||
for (var j = 0; j <= len2; j++) {
|
for (var j = 0; j <= len2; j++) {
|
||||||
matrix[0][j] = j
|
matrix[0][j] = j;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = 1; i <= len1; i++) {
|
for (var i = 1; i <= len1; i++) {
|
||||||
for (var j = 1; j <= len2; j++) {
|
for (var j = 1; j <= len2; j++) {
|
||||||
const cost = s1[i - 1] === s2[j - 1] ? 0 : 1
|
const cost = s1[i - 1] === s2[j - 1] ? 0 : 1;
|
||||||
matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost)
|
matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return matrix[len1][len2]
|
return matrix[len1][len2];
|
||||||
}
|
}
|
||||||
|
|
||||||
function fuzzyMatchScore(text, query) {
|
function fuzzyMatchScore(text, query) {
|
||||||
const queryLower = query.toLowerCase()
|
const queryLower = query.toLowerCase();
|
||||||
const maxDistance = query.length <= 2 ? 0 : query.length === 3 ? 1 : query.length <= 6 ? 2 : 3
|
const maxDistance = query.length <= 2 ? 0 : query.length === 3 ? 1 : query.length <= 6 ? 2 : 3;
|
||||||
|
|
||||||
let bestScore = 0
|
let bestScore = 0;
|
||||||
|
|
||||||
const distance = levenshteinDistance(text.toLowerCase(), queryLower)
|
const distance = levenshteinDistance(text.toLowerCase(), queryLower);
|
||||||
if (distance <= maxDistance) {
|
if (distance <= maxDistance) {
|
||||||
const maxLen = Math.max(text.length, query.length)
|
const maxLen = Math.max(text.length, query.length);
|
||||||
bestScore = 1 - (distance / maxLen)
|
bestScore = 1 - (distance / maxLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
const words = tokenize(text)
|
const words = tokenize(text);
|
||||||
for (const word of words) {
|
for (const word of words) {
|
||||||
const wordDistance = levenshteinDistance(word, queryLower)
|
const wordDistance = levenshteinDistance(word, queryLower);
|
||||||
if (wordDistance <= maxDistance) {
|
if (wordDistance <= maxDistance) {
|
||||||
const maxLen = Math.max(word.length, query.length)
|
const maxLen = Math.max(word.length, query.length);
|
||||||
const score = 1 - (wordDistance / maxLen)
|
const score = 1 - (wordDistance / maxLen);
|
||||||
bestScore = Math.max(bestScore, score)
|
bestScore = Math.max(bestScore, score);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bestScore
|
return bestScore;
|
||||||
}
|
}
|
||||||
|
|
||||||
function calculateFrecency(app) {
|
function calculateFrecency(app) {
|
||||||
const usageRanking = AppUsageHistoryData.appUsageRanking || {}
|
const usageRanking = AppUsageHistoryData.appUsageRanking || {};
|
||||||
const appId = app.id || (app.execString || app.exec || "")
|
const appId = app.id || (app.execString || app.exec || "");
|
||||||
const idVariants = [appId, appId.replace(".desktop", ""), app.id, app.id ? app.id.replace(".desktop", "") : null].filter(id => id)
|
const idVariants = [appId, appId.replace(".desktop", ""), app.id, app.id ? app.id.replace(".desktop", "") : null].filter(id => id);
|
||||||
|
|
||||||
let usageData = null
|
let usageData = null;
|
||||||
for (const variant of idVariants) {
|
for (const variant of idVariants) {
|
||||||
if (usageRanking[variant]) {
|
if (usageRanking[variant]) {
|
||||||
usageData = usageRanking[variant]
|
usageData = usageRanking[variant];
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,135 +126,135 @@ Singleton {
|
|||||||
return {
|
return {
|
||||||
"frecency": 0,
|
"frecency": 0,
|
||||||
"daysSinceUsed": 999999
|
"daysSinceUsed": 999999
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const usageCount = usageData.usageCount || 0
|
const usageCount = usageData.usageCount || 0;
|
||||||
const lastUsed = usageData.lastUsed || 0
|
const lastUsed = usageData.lastUsed || 0;
|
||||||
const now = Date.now()
|
const now = Date.now();
|
||||||
const daysSinceUsed = (now - lastUsed) / (1000 * 60 * 60 * 24)
|
const daysSinceUsed = (now - lastUsed) / (1000 * 60 * 60 * 24);
|
||||||
|
|
||||||
let timeBucketWeight = 10
|
let timeBucketWeight = 10;
|
||||||
for (const bucket of timeBuckets) {
|
for (const bucket of timeBuckets) {
|
||||||
if (daysSinceUsed <= bucket.maxDays) {
|
if (daysSinceUsed <= bucket.maxDays) {
|
||||||
timeBucketWeight = bucket.weight
|
timeBucketWeight = bucket.weight;
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const contextBonus = 100
|
const contextBonus = 100;
|
||||||
const sampleSize = Math.min(usageCount, frecencySampleSize)
|
const sampleSize = Math.min(usageCount, frecencySampleSize);
|
||||||
const frecency = (timeBucketWeight * contextBonus * sampleSize) / 100
|
const frecency = (timeBucketWeight * contextBonus * sampleSize) / 100;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"frecency": frecency,
|
"frecency": frecency,
|
||||||
"daysSinceUsed": daysSinceUsed
|
"daysSinceUsed": daysSinceUsed
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchApplications(query) {
|
function searchApplications(query) {
|
||||||
if (!query || query.length === 0) {
|
if (!query || query.length === 0) {
|
||||||
return applications
|
return applications;
|
||||||
}
|
}
|
||||||
if (applications.length === 0)
|
if (applications.length === 0)
|
||||||
return []
|
return [];
|
||||||
|
|
||||||
const queryLower = query.toLowerCase().trim()
|
const queryLower = query.toLowerCase().trim();
|
||||||
const scoredApps = []
|
const scoredApps = [];
|
||||||
const results = []
|
const results = [];
|
||||||
|
|
||||||
for (const app of applications) {
|
for (const app of applications) {
|
||||||
const name = (app.name || "").toLowerCase()
|
const name = (app.name || "").toLowerCase();
|
||||||
const genericName = (app.genericName || "").toLowerCase()
|
const genericName = (app.genericName || "").toLowerCase();
|
||||||
const comment = (app.comment || "").toLowerCase()
|
const comment = (app.comment || "").toLowerCase();
|
||||||
const id = (app.id || "").toLowerCase()
|
const id = (app.id || "").toLowerCase();
|
||||||
const keywords = app.keywords ? app.keywords.map(k => k.toLowerCase()) : []
|
const keywords = app.keywords ? app.keywords.map(k => k.toLowerCase()) : [];
|
||||||
|
|
||||||
let textScore = 0
|
let textScore = 0;
|
||||||
let matchType = "none"
|
let matchType = "none";
|
||||||
|
|
||||||
if (name === queryLower) {
|
if (name === queryLower) {
|
||||||
textScore = 10000
|
textScore = 10000;
|
||||||
matchType = "exact"
|
matchType = "exact";
|
||||||
} else if (name.startsWith(queryLower)) {
|
} else if (name.startsWith(queryLower)) {
|
||||||
textScore = 5000
|
textScore = 5000;
|
||||||
matchType = "prefix"
|
matchType = "prefix";
|
||||||
} else if (wordBoundaryMatch(name, queryLower)) {
|
} else if (wordBoundaryMatch(name, queryLower)) {
|
||||||
textScore = 1000
|
textScore = 1000;
|
||||||
matchType = "word_boundary"
|
matchType = "word_boundary";
|
||||||
} else if (name.includes(queryLower)) {
|
} else if (name.includes(queryLower)) {
|
||||||
textScore = 500
|
textScore = 500;
|
||||||
matchType = "substring"
|
matchType = "substring";
|
||||||
} else if (genericName && genericName.startsWith(queryLower)) {
|
} else if (genericName && genericName.startsWith(queryLower)) {
|
||||||
textScore = 800
|
textScore = 800;
|
||||||
matchType = "generic_prefix"
|
matchType = "generic_prefix";
|
||||||
} else if (genericName && genericName.includes(queryLower)) {
|
} else if (genericName && genericName.includes(queryLower)) {
|
||||||
textScore = 400
|
textScore = 400;
|
||||||
matchType = "generic"
|
matchType = "generic";
|
||||||
} else if (id && id.includes(queryLower)) {
|
} else if (id && id.includes(queryLower)) {
|
||||||
textScore = 350
|
textScore = 350;
|
||||||
matchType = "id"
|
matchType = "id";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matchType === "none" && keywords.length > 0) {
|
if (matchType === "none" && keywords.length > 0) {
|
||||||
for (const keyword of keywords) {
|
for (const keyword of keywords) {
|
||||||
if (keyword.startsWith(queryLower)) {
|
if (keyword.startsWith(queryLower)) {
|
||||||
textScore = 300
|
textScore = 300;
|
||||||
matchType = "keyword_prefix"
|
matchType = "keyword_prefix";
|
||||||
break
|
break;
|
||||||
} else if (keyword.includes(queryLower)) {
|
} else if (keyword.includes(queryLower)) {
|
||||||
textScore = 150
|
textScore = 150;
|
||||||
matchType = "keyword"
|
matchType = "keyword";
|
||||||
break
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matchType === "none" && comment && comment.includes(queryLower)) {
|
if (matchType === "none" && comment && comment.includes(queryLower)) {
|
||||||
textScore = 50
|
textScore = 50;
|
||||||
matchType = "comment"
|
matchType = "comment";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matchType === "none") {
|
if (matchType === "none") {
|
||||||
const fuzzyScore = fuzzyMatchScore(name, queryLower)
|
const fuzzyScore = fuzzyMatchScore(name, queryLower);
|
||||||
if (fuzzyScore > 0) {
|
if (fuzzyScore > 0) {
|
||||||
textScore = fuzzyScore * 100
|
textScore = fuzzyScore * 100;
|
||||||
matchType = "fuzzy"
|
matchType = "fuzzy";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (matchType !== "none") {
|
if (matchType !== "none") {
|
||||||
const frecencyData = calculateFrecency(app)
|
const frecencyData = calculateFrecency(app);
|
||||||
|
|
||||||
results.push({
|
results.push({
|
||||||
"app": app,
|
"app": app,
|
||||||
"textScore": textScore,
|
"textScore": textScore,
|
||||||
"frecency": frecencyData.frecency,
|
"frecency": frecencyData.frecency,
|
||||||
"daysSinceUsed": frecencyData.daysSinceUsed,
|
"daysSinceUsed": frecencyData.daysSinceUsed,
|
||||||
"matchType": matchType
|
"matchType": matchType
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const result of results) {
|
for (const result of results) {
|
||||||
const frecencyBonus = result.frecency > 0 ? Math.min(result.frecency / 10, 2000) : 0
|
const frecencyBonus = result.frecency > 0 ? Math.min(result.frecency / 10, 2000) : 0;
|
||||||
const recencyBonus = result.daysSinceUsed < 1 ? 1500 : result.daysSinceUsed < 7 ? 1000 : result.daysSinceUsed < 30 ? 500 : 0
|
const recencyBonus = result.daysSinceUsed < 1 ? 1500 : result.daysSinceUsed < 7 ? 1000 : result.daysSinceUsed < 30 ? 500 : 0;
|
||||||
|
|
||||||
const finalScore = result.textScore + frecencyBonus + recencyBonus
|
const finalScore = result.textScore + frecencyBonus + recencyBonus;
|
||||||
|
|
||||||
scoredApps.push({
|
scoredApps.push({
|
||||||
"app": result.app,
|
"app": result.app,
|
||||||
"score": finalScore
|
"score": finalScore
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
scoredApps.sort((a, b) => b.score - a.score)
|
scoredApps.sort((a, b) => b.score - a.score);
|
||||||
return scoredApps.slice(0, maxResults).map(item => item.app)
|
return scoredApps.slice(0, maxResults).map(item => item.app);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getCategoriesForApp(app) {
|
function getCategoriesForApp(app) {
|
||||||
if (!app?.categories)
|
if (!app?.categories)
|
||||||
return []
|
return [];
|
||||||
|
|
||||||
const categoryMap = {
|
const categoryMap = {
|
||||||
"AudioVideo": I18n.tr("Media"),
|
"AudioVideo": I18n.tr("Media"),
|
||||||
@@ -276,241 +281,241 @@ Singleton {
|
|||||||
"Accessories": I18n.tr("Utilities"),
|
"Accessories": I18n.tr("Utilities"),
|
||||||
"FileManager": I18n.tr("Utilities"),
|
"FileManager": I18n.tr("Utilities"),
|
||||||
"TerminalEmulator": I18n.tr("Utilities")
|
"TerminalEmulator": I18n.tr("Utilities")
|
||||||
}
|
};
|
||||||
|
|
||||||
const mappedCategories = new Set()
|
const mappedCategories = new Set();
|
||||||
|
|
||||||
for (const cat of app.categories) {
|
for (const cat of app.categories) {
|
||||||
if (categoryMap[cat])
|
if (categoryMap[cat])
|
||||||
mappedCategories.add(categoryMap[cat])
|
mappedCategories.add(categoryMap[cat]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Array.from(mappedCategories)
|
return Array.from(mappedCategories);
|
||||||
}
|
}
|
||||||
|
|
||||||
property var categoryIcons: ({
|
property var categoryIcons: ({
|
||||||
"All": "apps",
|
"All": "apps",
|
||||||
"Media": "music_video",
|
"Media": "music_video",
|
||||||
"Development": "code",
|
"Development": "code",
|
||||||
"Games": "sports_esports",
|
"Games": "sports_esports",
|
||||||
"Graphics": "photo_library",
|
"Graphics": "photo_library",
|
||||||
"Internet": "web",
|
"Internet": "web",
|
||||||
"Office": "content_paste",
|
"Office": "content_paste",
|
||||||
"Settings": "settings",
|
"Settings": "settings",
|
||||||
"System": "host",
|
"System": "host",
|
||||||
"Utilities": "build"
|
"Utilities": "build"
|
||||||
})
|
})
|
||||||
|
|
||||||
function getCategoryIcon(category) {
|
function getCategoryIcon(category) {
|
||||||
// Check if it's a plugin category
|
// Check if it's a plugin category
|
||||||
const pluginIcon = getPluginCategoryIcon(category)
|
const pluginIcon = getPluginCategoryIcon(category);
|
||||||
if (pluginIcon) {
|
if (pluginIcon) {
|
||||||
return pluginIcon
|
return pluginIcon;
|
||||||
}
|
}
|
||||||
return categoryIcons[category] || "folder"
|
return categoryIcons[category] || "folder";
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAllCategories() {
|
function getAllCategories() {
|
||||||
const categories = new Set([I18n.tr("All")])
|
const categories = new Set([I18n.tr("All")]);
|
||||||
|
|
||||||
for (const app of applications) {
|
for (const app of applications) {
|
||||||
const appCategories = getCategoriesForApp(app)
|
const appCategories = getCategoriesForApp(app);
|
||||||
appCategories.forEach(cat => categories.add(cat))
|
appCategories.forEach(cat => categories.add(cat));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add plugin categories
|
// Add plugin categories
|
||||||
const pluginCategories = getPluginCategories()
|
const pluginCategories = getPluginCategories();
|
||||||
pluginCategories.forEach(cat => categories.add(cat))
|
pluginCategories.forEach(cat => categories.add(cat));
|
||||||
|
|
||||||
const result = Array.from(categories).sort()
|
const result = Array.from(categories).sort();
|
||||||
return result
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAppsInCategory(category) {
|
function getAppsInCategory(category) {
|
||||||
if (category === I18n.tr("All")) {
|
if (category === I18n.tr("All")) {
|
||||||
return applications
|
return applications;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if it's a plugin category
|
// Check if it's a plugin category
|
||||||
const pluginItems = getPluginItems(category, "")
|
const pluginItems = getPluginItems(category, "");
|
||||||
if (pluginItems.length > 0) {
|
if (pluginItems.length > 0) {
|
||||||
return pluginItems
|
return pluginItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
return applications.filter(app => {
|
return applications.filter(app => {
|
||||||
const appCategories = getCategoriesForApp(app)
|
const appCategories = getCategoriesForApp(app);
|
||||||
return appCategories.includes(category)
|
return appCategories.includes(category);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plugin launcher support functions
|
// Plugin launcher support functions
|
||||||
function getPluginCategories() {
|
function getPluginCategories() {
|
||||||
if (typeof PluginService === "undefined") {
|
if (typeof PluginService === "undefined") {
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const categories = []
|
const categories = [];
|
||||||
const launchers = PluginService.getLauncherPlugins()
|
const launchers = PluginService.getLauncherPlugins();
|
||||||
|
|
||||||
for (const pluginId in launchers) {
|
for (const pluginId in launchers) {
|
||||||
const plugin = launchers[pluginId]
|
const plugin = launchers[pluginId];
|
||||||
const categoryName = plugin.name || pluginId
|
const categoryName = plugin.name || pluginId;
|
||||||
categories.push(categoryName)
|
categories.push(categoryName);
|
||||||
}
|
}
|
||||||
|
|
||||||
return categories
|
return categories;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPluginCategoryIcon(category) {
|
function getPluginCategoryIcon(category) {
|
||||||
if (typeof PluginService === "undefined")
|
if (typeof PluginService === "undefined")
|
||||||
return null
|
return null;
|
||||||
|
|
||||||
const launchers = PluginService.getLauncherPlugins()
|
const launchers = PluginService.getLauncherPlugins();
|
||||||
for (const pluginId in launchers) {
|
for (const pluginId in launchers) {
|
||||||
const plugin = launchers[pluginId]
|
const plugin = launchers[pluginId];
|
||||||
if ((plugin.name || pluginId) === category) {
|
if ((plugin.name || pluginId) === category) {
|
||||||
return plugin.icon || "extension"
|
return plugin.icon || "extension";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAllPluginItems() {
|
function getAllPluginItems() {
|
||||||
if (typeof PluginService === "undefined") {
|
if (typeof PluginService === "undefined") {
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
let allItems = []
|
let allItems = [];
|
||||||
const launchers = PluginService.getLauncherPlugins()
|
const launchers = PluginService.getLauncherPlugins();
|
||||||
|
|
||||||
for (const pluginId in launchers) {
|
for (const pluginId in launchers) {
|
||||||
const categoryName = launchers[pluginId].name || pluginId
|
const categoryName = launchers[pluginId].name || pluginId;
|
||||||
const items = getPluginItems(categoryName, "")
|
const items = getPluginItems(categoryName, "");
|
||||||
allItems = allItems.concat(items)
|
allItems = allItems.concat(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
return allItems
|
return allItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPluginItems(category, query) {
|
function getPluginItems(category, query) {
|
||||||
if (typeof PluginService === "undefined")
|
if (typeof PluginService === "undefined")
|
||||||
return []
|
return [];
|
||||||
|
|
||||||
const launchers = PluginService.getLauncherPlugins()
|
const launchers = PluginService.getLauncherPlugins();
|
||||||
for (const pluginId in launchers) {
|
for (const pluginId in launchers) {
|
||||||
const plugin = launchers[pluginId]
|
const plugin = launchers[pluginId];
|
||||||
if ((plugin.name || pluginId) === category) {
|
if ((plugin.name || pluginId) === category) {
|
||||||
return getPluginItemsForPlugin(pluginId, query)
|
return getPluginItemsForPlugin(pluginId, query);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function getPluginItemsForPlugin(pluginId, query) {
|
function getPluginItemsForPlugin(pluginId, query) {
|
||||||
if (typeof PluginService === "undefined") {
|
if (typeof PluginService === "undefined") {
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
let instance = PluginService.pluginInstances[pluginId]
|
let instance = PluginService.pluginInstances[pluginId];
|
||||||
let isPersistent = true
|
let isPersistent = true;
|
||||||
|
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
const component = PluginService.pluginLauncherComponents[pluginId]
|
const component = PluginService.pluginLauncherComponents[pluginId];
|
||||||
if (!component)
|
if (!component)
|
||||||
return []
|
return [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
instance = component.createObject(root, {
|
instance = component.createObject(root, {
|
||||||
"pluginService": PluginService
|
"pluginService": PluginService
|
||||||
})
|
});
|
||||||
isPersistent = false
|
isPersistent = false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("AppSearchService: Error creating temporary plugin instance", pluginId, ":", e)
|
console.warn("AppSearchService: Error creating temporary plugin instance", pluginId, ":", e);
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!instance)
|
if (!instance)
|
||||||
return []
|
return [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (typeof instance.getItems === "function") {
|
if (typeof instance.getItems === "function") {
|
||||||
const items = instance.getItems(query || "")
|
const items = instance.getItems(query || "");
|
||||||
if (!isPersistent)
|
if (!isPersistent)
|
||||||
instance.destroy()
|
instance.destroy();
|
||||||
return items || []
|
return items || [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isPersistent) {
|
if (!isPersistent) {
|
||||||
instance.destroy()
|
instance.destroy();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("AppSearchService: Error getting items from plugin", pluginId, ":", e)
|
console.warn("AppSearchService: Error getting items from plugin", pluginId, ":", e);
|
||||||
if (!isPersistent)
|
if (!isPersistent)
|
||||||
instance.destroy()
|
instance.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
return []
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
function executePluginItem(item, pluginId) {
|
function executePluginItem(item, pluginId) {
|
||||||
if (typeof PluginService === "undefined")
|
if (typeof PluginService === "undefined")
|
||||||
return false
|
return false;
|
||||||
|
|
||||||
let instance = PluginService.pluginInstances[pluginId]
|
let instance = PluginService.pluginInstances[pluginId];
|
||||||
let isPersistent = true
|
let isPersistent = true;
|
||||||
|
|
||||||
if (!instance) {
|
if (!instance) {
|
||||||
const component = PluginService.pluginLauncherComponents[pluginId]
|
const component = PluginService.pluginLauncherComponents[pluginId];
|
||||||
if (!component)
|
if (!component)
|
||||||
return false
|
return false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
instance = component.createObject(root, {
|
instance = component.createObject(root, {
|
||||||
"pluginService": PluginService
|
"pluginService": PluginService
|
||||||
})
|
});
|
||||||
isPersistent = false
|
isPersistent = false;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("AppSearchService: Error creating temporary plugin instance for execution", pluginId, ":", e)
|
console.warn("AppSearchService: Error creating temporary plugin instance for execution", pluginId, ":", e);
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!instance)
|
if (!instance)
|
||||||
return false
|
return false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (typeof instance.executeItem === "function") {
|
if (typeof instance.executeItem === "function") {
|
||||||
instance.executeItem(item)
|
instance.executeItem(item);
|
||||||
if (!isPersistent)
|
if (!isPersistent)
|
||||||
instance.destroy()
|
instance.destroy();
|
||||||
return true
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isPersistent) {
|
if (!isPersistent) {
|
||||||
instance.destroy()
|
instance.destroy();
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.warn("AppSearchService: Error executing item from plugin", pluginId, ":", e)
|
console.warn("AppSearchService: Error executing item from plugin", pluginId, ":", e);
|
||||||
if (!isPersistent)
|
if (!isPersistent)
|
||||||
instance.destroy()
|
instance.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function searchPluginItems(query) {
|
function searchPluginItems(query) {
|
||||||
if (typeof PluginService === "undefined")
|
if (typeof PluginService === "undefined")
|
||||||
return []
|
return [];
|
||||||
|
|
||||||
let allItems = []
|
let allItems = [];
|
||||||
const launchers = PluginService.getLauncherPlugins()
|
const launchers = PluginService.getLauncherPlugins();
|
||||||
|
|
||||||
for (const pluginId in launchers) {
|
for (const pluginId in launchers) {
|
||||||
const items = getPluginItemsForPlugin(pluginId, query)
|
const items = getPluginItemsForPlugin(pluginId, query);
|
||||||
allItems = allItems.concat(items)
|
allItems = allItems.concat(items);
|
||||||
}
|
}
|
||||||
|
|
||||||
return allItems
|
return allItems;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,26 +170,35 @@ Singleton {
|
|||||||
const userPrefix = SettingsData.launchPrefix?.trim() || "";
|
const userPrefix = SettingsData.launchPrefix?.trim() || "";
|
||||||
const defaultPrefix = Quickshell.env("DMS_DEFAULT_LAUNCH_PREFIX") || "";
|
const defaultPrefix = Quickshell.env("DMS_DEFAULT_LAUNCH_PREFIX") || "";
|
||||||
const prefix = userPrefix.length > 0 ? userPrefix : defaultPrefix;
|
const prefix = userPrefix.length > 0 ? userPrefix : defaultPrefix;
|
||||||
|
const workDir = desktopEntry.workingDirectory || Quickshell.env("HOME");
|
||||||
|
const escapedCmd = cmd.map(arg => escapeShellArg(arg)).join(" ");
|
||||||
|
const shellCmd = prefix.length > 0 ? `${prefix} ${escapedCmd}` : escapedCmd;
|
||||||
|
|
||||||
|
if (desktopEntry.runInTerminal) {
|
||||||
|
const terminal = Quickshell.env("TERMINAL") || "xterm";
|
||||||
|
Quickshell.execDetached({
|
||||||
|
command: [terminal, "-e", "sh", "-c", shellCmd],
|
||||||
|
workingDirectory: workDir
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (prefix.length > 0 && needsShellExecution(prefix)) {
|
if (prefix.length > 0 && needsShellExecution(prefix)) {
|
||||||
const escapedCmd = cmd.map(arg => escapeShellArg(arg)).join(" ");
|
|
||||||
const shellCmd = `${prefix} ${escapedCmd}`;
|
|
||||||
|
|
||||||
Quickshell.execDetached({
|
Quickshell.execDetached({
|
||||||
command: ["sh", "-c", shellCmd],
|
command: ["sh", "-c", shellCmd],
|
||||||
workingDirectory: desktopEntry.workingDirectory || Quickshell.env("HOME")
|
workingDirectory: workDir
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (prefix.length > 0) {
|
|
||||||
const launchPrefix = prefix.split(" ");
|
|
||||||
cmd = launchPrefix.concat(cmd);
|
|
||||||
}
|
|
||||||
|
|
||||||
Quickshell.execDetached({
|
|
||||||
command: cmd,
|
|
||||||
workingDirectory: desktopEntry.workingDirectory || Quickshell.env("HOME")
|
|
||||||
});
|
});
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prefix.length > 0) {
|
||||||
|
cmd = prefix.split(" ").concat(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
Quickshell.execDetached({
|
||||||
|
command: cmd,
|
||||||
|
workingDirectory: workDir
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function launchDesktopAction(desktopEntry, action, useNvidia) {
|
function launchDesktopAction(desktopEntry, action, useNvidia) {
|
||||||
|
|||||||
Reference in New Issue
Block a user