1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-07 14:05:38 -05:00

Better app launchers using rescan, and fuzzysort. GPL license.

FuzzySort was ripped from caelestia, which is the reason for GPL change.
This commit is contained in:
bbedward
2025-07-14 11:25:18 -04:00
parent 5c5653a41a
commit 603ac51df0
5 changed files with 1598 additions and 154 deletions

View File

@@ -24,6 +24,28 @@ PanelWindow {
property string selectedCategory: "All"
property string viewMode: "list" // "list" or "grid"
// Search debouncing
Timer {
id: searchDebounceTimer
interval: 100
repeat: false
onTriggered: updateFilteredApps()
}
// Periodic rescan while open
Timer {
id: periodicRescanTimer
interval: 15000 // 15 seconds
repeat: true
running: spotlightOpen
onTriggered: {
console.log("SpotlightLauncher: Periodic rescan triggered")
if (DesktopEntries.rescan) {
DesktopEntries.rescan()
}
}
}
anchors {
top: true
left: true
@@ -47,9 +69,17 @@ PanelWindow {
// ...existing code...
function show() {
console.log("SpotlightLauncher: show() called")
// Trigger manual rescan when opening
console.log("SpotlightLauncher: Triggering manual rescan on show")
if (DesktopEntries.rescan) {
DesktopEntries.rescan()
}
spotlightOpen = true
console.log("SpotlightLauncher: spotlightOpen set to", spotlightOpen)
updateFilteredApps()
searchDebounceTimer.stop() // Stop any pending search
updateFilteredApps() // Immediate update when showing
Qt.callLater(function() {
searchField.forceActiveFocus()
searchField.selectAll()
@@ -58,6 +88,7 @@ PanelWindow {
function hide() {
spotlightOpen = false
searchDebounceTimer.stop() // Stop any pending search
searchField.text = ""
selectedIndex = 0
selectedCategory = "All"
@@ -74,20 +105,30 @@ PanelWindow {
function updateFilteredApps() {
if (!AppSearchService.ready) {
filteredApps = []
selectedIndex = 0
filteredModel.clear()
return
}
filteredApps = []
selectedIndex = 0
var apps = []
var searchQuery = searchField.text
if (searchField.text.length === 0) {
if (searchQuery.length === 0) {
// Show apps from category
if (selectedCategory === "All") {
// For "All" category, show all available apps
apps = AppSearchService.applications || []
} else if (selectedCategory === "Recents") {
// For "Recents" category, get recent apps from Prefs
// For "Recents" category, get recent apps from Prefs and filter out non-existent ones
var recentApps = Prefs.getRecentApps()
apps = recentApps.map(recentApp => AppSearchService.getAppByExec(recentApp.exec)).filter(app => app !== null)
apps = recentApps
.map(recentApp => AppSearchService.getAppByExec(recentApp.exec))
.filter(app => app !== null && !app.noDisplay)
} else {
// For specific categories, limit results
var categoryApps = AppSearchService.getAppsInCategory(selectedCategory)
@@ -97,30 +138,39 @@ PanelWindow {
// Search with category filter
if (selectedCategory === "All") {
// For "All" category, search all apps without limit
apps = AppSearchService.searchApplications(searchField.text)
apps = AppSearchService.searchApplications(searchQuery)
} else if (selectedCategory === "Recents") {
// For "Recents" category, search within recent apps
var recentApps = Prefs.getRecentApps()
var recentDesktopEntries = recentApps.map(recentApp => AppSearchService.getAppByExec(recentApp.exec)).filter(app => app !== null)
var allSearchResults = AppSearchService.searchApplications(searchField.text)
var recentDesktopEntries = recentApps
.map(recentApp => AppSearchService.getAppByExec(recentApp.exec))
.filter(app => app !== null && !app.noDisplay)
// Filter search results to only include recent apps
apps = allSearchResults.filter(searchApp => {
return recentDesktopEntries.some(recentApp => recentApp.name === searchApp.name)
})
if (recentDesktopEntries.length > 0) {
var allSearchResults = AppSearchService.searchApplications(searchQuery)
var recentNames = new Set(recentDesktopEntries.map(app => app.name))
// Filter search results to only include recent apps
apps = allSearchResults.filter(searchApp => recentNames.has(searchApp.name))
} else {
apps = []
}
} else {
// For specific categories, filter search results by category
var categoryApps = AppSearchService.getAppsInCategory(selectedCategory)
var allSearchResults = AppSearchService.searchApplications(searchField.text)
// Filter search results to only include apps from the selected category
apps = allSearchResults.filter(searchApp => {
return categoryApps.some(categoryApp => categoryApp.name === searchApp.name)
}).slice(0, maxResults)
if (categoryApps.length > 0) {
var allSearchResults = AppSearchService.searchApplications(searchQuery)
var categoryNames = new Set(categoryApps.map(app => app.name))
// Filter search results to only include apps from the selected category
apps = allSearchResults.filter(searchApp => categoryNames.has(searchApp.name)).slice(0, maxResults)
} else {
apps = []
}
}
}
// Convert to our format
// Convert to our format - batch operations for better performance
filteredApps = apps.map(app => ({
name: app.name,
exec: app.execString || "",
@@ -130,6 +180,7 @@ PanelWindow {
desktopEntry: app
}))
// Clear and repopulate model efficiently
filteredModel.clear()
filteredApps.forEach(app => filteredModel.append(app))
}
@@ -205,6 +256,23 @@ PanelWindow {
}
}
Connections {
target: DesktopEntries
function onApplicationsChanged() {
console.log("SpotlightLauncher: DesktopEntries.applicationsChanged signal received")
// Update categories when applications change
if (AppSearchService.ready) {
console.log("SpotlightLauncher: Updating categories and apps due to applicationsChanged")
var allCategories = AppSearchService.getAllCategories().filter(cat => cat !== "Education" && cat !== "Science")
var result = ["All", "Recents"]
categories = result.concat(allCategories.filter(cat => cat !== "All"))
if (spotlightOpen) updateFilteredApps()
} else {
console.log("SpotlightLauncher: AppSearchService not ready, skipping update")
}
}
}
// Dimmed overlay background
Rectangle {
@@ -390,7 +458,9 @@ PanelWindow {
verticalAlignment: Text.AlignVCenter
focus: spotlightOpen
selectByMouse: true
onTextChanged: updateFilteredApps()
onTextChanged: {
searchDebounceTimer.restart()
}
Keys.onPressed: (event) => {
if(event.key === Qt.Key_Escape) { hide(); event.accepted = true }
else if(event.key === Qt.Key_Return || event.key === Qt.Key_Enter) { launchSelected(); event.accepted = true }
@@ -713,6 +783,14 @@ PanelWindow {
spotlightLauncher.toggle()
return "SPOTLIGHT_TOGGLE_SUCCESS"
}
function rescan() {
console.log("SpotlightLauncher: IPC rescan() called")
if (DesktopEntries.rescan) {
DesktopEntries.rescan()
console.log("SpotlightLauncher: Triggered DesktopEntries rescan")
}
return "SPOTLIGHT_RESCAN_SUCCESS"
}
}
Component.onCompleted: {