101 lines
3.8 KiB
QML
101 lines
3.8 KiB
QML
import QtQuick
|
|
import Quickshell
|
|
import Quickshell.Io
|
|
import qs.Commons
|
|
import qs.Services
|
|
import "../../../Helpers/FuzzySort.js" as Fuzzysort
|
|
|
|
Item {
|
|
property var launcher: null
|
|
property string name: "Applications"
|
|
property bool handleSearch: true
|
|
property var entries: []
|
|
|
|
function init() {
|
|
loadApplications()
|
|
}
|
|
|
|
function onOpened() {
|
|
// Refresh apps when launcher opens
|
|
loadApplications()
|
|
}
|
|
|
|
function loadApplications() {
|
|
if (typeof DesktopEntries === 'undefined') {
|
|
Logger.warn("ApplicationsPlugin", "DesktopEntries service not available")
|
|
return
|
|
}
|
|
|
|
const allApps = DesktopEntries.applications.values || []
|
|
entries = allApps.filter(app => app && !app.noDisplay)
|
|
Logger.log("ApplicationsPlugin", `Loaded ${entries.length} applications`)
|
|
}
|
|
|
|
function getResults(query) {
|
|
if (!entries || entries.length === 0)
|
|
return []
|
|
|
|
if (!query || query.trim() === "") {
|
|
// Return all apps alphabetically
|
|
return entries.sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase())).map(app => createResultEntry(app))
|
|
}
|
|
|
|
// Use fuzzy search if available, fallback to simple search
|
|
if (typeof Fuzzysort !== 'undefined') {
|
|
const fuzzyResults = Fuzzysort.go(query, entries, {
|
|
"keys": ["name", "comment", "genericName"],
|
|
"threshold": -1000,
|
|
"limit": 20
|
|
})
|
|
|
|
return fuzzyResults.map(result => createResultEntry(result.obj))
|
|
} else {
|
|
// Fallback to simple search
|
|
const searchTerm = query.toLowerCase()
|
|
return entries.filter(app => {
|
|
const name = (app.name || "").toLowerCase()
|
|
const comment = (app.comment || "").toLowerCase()
|
|
const generic = (app.genericName || "").toLowerCase()
|
|
return name.includes(searchTerm) || comment.includes(searchTerm) || generic.includes(searchTerm)
|
|
}).sort((a, b) => {
|
|
// Prioritize name matches
|
|
const aName = a.name.toLowerCase()
|
|
const bName = b.name.toLowerCase()
|
|
const aStarts = aName.startsWith(searchTerm)
|
|
const bStarts = bName.startsWith(searchTerm)
|
|
if (aStarts && !bStarts)
|
|
return -1
|
|
if (!aStarts && bStarts)
|
|
return 1
|
|
return aName.localeCompare(bName)
|
|
}).slice(0, 20).map(app => createResultEntry(app))
|
|
}
|
|
}
|
|
|
|
function createResultEntry(app) {
|
|
return {
|
|
"name": app.name || "Unknown",
|
|
"description": app.genericName || app.comment || "",
|
|
"icon": app.icon || "application-x-executable",
|
|
"isImage": false,
|
|
"onActivate": function () {
|
|
// Close the launcher/NPanel immediately without any animations.
|
|
// Ensures we are not preventing the future focusing of the app
|
|
launcher.closeCompleted()
|
|
|
|
Logger.log("ApplicationsPlugin", `Launching: ${app.name}`)
|
|
if (Settings.data.appLauncher.useApp2Unit && app.id) {
|
|
Logger.log("ApplicationsPlugin", `Using app2unit for: ${app.id}`)
|
|
if (app.runInTerminal)
|
|
Quickshell.execDetached(["app2unit", "--", app.id + ".desktop"])
|
|
else
|
|
Quickshell.execDetached(["app2unit", "--"].concat(app.command))
|
|
} else if (app.execute) {
|
|
app.execute()
|
|
} else {
|
|
Logger.log("ApplicationsPlugin", `Could not launch: ${app.name}`)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|