Launcher: add sort by most used option

This commit is contained in:
Ly-sec
2025-09-18 16:53:38 +02:00
parent a1aabd02f5
commit 3d9295856c
3 changed files with 86 additions and 2 deletions
+1
View File
@@ -356,6 +356,7 @@ Singleton {
property real backgroundOpacity: 1.0
property list<string> pinnedExecs: []
property bool useApp2Unit: false
property bool sortByMostUsed: true
}
// dock
@@ -11,6 +11,38 @@ Item {
property bool handleSearch: true
property var entries: []
// Persistent usage tracking stored in cacheDir
property string usageFilePath: Settings.cacheDir + "launcher_app_usage.json"
// Debounced saver to avoid excessive IO
Timer {
id: saveTimer
interval: 750
repeat: false
onTriggered: usageFile.writeAdapter()
}
FileView {
id: usageFile
path: usageFilePath
printErrors: false
watchChanges: false
onLoadFailed: function (error) {
if (error.toString().includes("No such file") || error === 2) {
writeAdapter()
}
}
onAdapterUpdated: saveTimer.start()
JsonAdapter {
id: usageAdapter
// key: app id/command, value: integer count
property var counts: ({})
}
}
function init() {
loadApplications()
}
@@ -36,8 +68,20 @@ Item {
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))
// Return all apps, optionally sorted by usage
let sorted
if (Settings.data.appLauncher.sortByMostUsed) {
sorted = entries.slice().sort((a, b) => {
const ua = getUsageCount(a)
const ub = getUsageCount(b)
if (ub !== ua)
return ub - ua
return (a.name || "").toLowerCase().localeCompare((b.name || "").toLowerCase())
})
} else {
sorted = entries.slice().sort((a, b) => (a.name || "").toLowerCase().localeCompare((b.name || "").toLowerCase()))
}
return sorted.map(app => createResultEntry(app))
}
// Use fuzzy search if available, fallback to simple search
@@ -84,6 +128,9 @@ Item {
launcher.closeCompleted()
Logger.log("ApplicationsPlugin", `Launching: ${app.name}`)
// Record usage and persist asynchronously
if (Settings.data.appLauncher.sortByMostUsed)
recordUsage(app)
if (Settings.data.appLauncher.useApp2Unit && app.id) {
Logger.log("ApplicationsPlugin", `Using app2unit for: ${app.id}`)
if (app.runInTerminal)
@@ -98,4 +145,33 @@ Item {
}
}
}
// -------------------------
// Usage tracking helpers
function getAppKey(app) {
if (app && app.id)
return String(app.id)
if (app && app.command && app.command.join)
return app.command.join(" ")
return String(app && app.name ? app.name : "unknown")
}
function getUsageCount(app) {
const key = getAppKey(app)
const m = usageAdapter && usageAdapter.counts ? usageAdapter.counts : null
if (!m)
return 0
const v = m[key]
return typeof v === 'number' && isFinite(v) ? v : 0
}
function recordUsage(app) {
const key = getAppKey(app)
if (!usageAdapter.counts)
usageAdapter.counts = ({})
const current = getUsageCount(app)
usageAdapter.counts[key] = current + 1
// Trigger save via debounced timer
saveTimer.restart()
}
}
@@ -93,6 +93,13 @@ ColumnLayout {
onToggled: checked => Settings.data.appLauncher.enableClipboardHistory = checked
}
NToggle {
label: "Sort by Most Used"
description: "When enabled, frequently launched apps appear first in the list."
checked: Settings.data.appLauncher.sortByMostUsed
onToggled: checked => Settings.data.appLauncher.sortByMostUsed = checked
}
NToggle {
label: "Use App2Unit for Launching"
description: "Use app2unit -- 'desktop-entry' when launching applications for better systemd integration."