pragma Singleton // Search across every setting, not just page names. // // The sidebar's field used to filter the twelve page labels, so "gaps", // "wallpaper", and "repeat delay" all found nothing — which is precisely the // thing that makes a settings app feel smaller than it is. This indexes the // schema itself, so any setting is reachable by typing what it does, and a new // schema entry becomes searchable with no change here. // // Shortcuts are indexed too: "screenshot" should find the key that takes one. import Quickshell import QtQuick import qs.config Singleton { id: root // Which page shows the settings in a given schema group. A group with no // entry here still appears in results and routes to Home rather than being // dropped, so adding a group can never make a setting unreachable. readonly property var groupPages: ({ "clock": "appearance", "vitals": "appearance", "windows": "appearance", "effects": "appearance", "wallpaper": "appearance", "dock": "desktop", "focus": "desktop", "display": "displays", "idle": "power", "accessibility": "accessibility", "input": "shortcuts", "weather": "appearance", "notifications": "notifications", "capture": "screen-intelligence" }) // Settings that are real but have no schema entry, because the system owns // them rather than Panama. Without these, searching "timezone" would fail // on a settings app that plainly has one. readonly property var extraEntries: [ { label: "Timezone", detail: "Set the system timezone", page: "datetime" }, { label: "Network time", detail: "Synchronise the clock with a time server", page: "datetime" }, { label: "Wi-Fi", detail: "Managed by GNOME Settings", page: "connectivity" }, { label: "Bluetooth", detail: "Managed by GNOME Settings", page: "connectivity" }, { label: "Printers", detail: "Managed by GNOME Settings", page: "connectivity" }, { label: "Default applications", detail: "Browser, mail, files", page: "applications" }, { label: "Restore defaults", detail: "Return every Panama setting to its shipped value", page: "desktop" }, { label: "Keyboard shortcuts", detail: "Every shortcut the compositor has bound", page: "shortcuts" } ] function pageFor(group: string): string { return root.groupPages[group] ?? "home"; } // [{ label, detail, page, kind }] for a query. Empty query yields nothing: // the sidebar shows its normal navigation in that case. function search(query: string): var { const needle = String(query).trim().toLowerCase(); if (needle === "") return []; const results = []; const seen = {}; function add(label, detail, page, kind) { const dedupe = `${kind}:${label}:${page}`; if (seen[dedupe]) return; seen[dedupe] = true; results.push({ label: label, detail: detail, page: page, kind: kind }); } for (const entry of PreferenceSchema.entries) { if (entry.internal) continue; const haystack = `${entry.label} ${entry.detail ?? ""} ${entry.group}`.toLowerCase(); if (haystack.indexOf(needle) >= 0) add(entry.label, entry.detail ?? "", root.pageFor(entry.group), "setting"); } for (const entry of root.extraEntries) { if (`${entry.label} ${entry.detail}`.toLowerCase().indexOf(needle) >= 0) add(entry.label, entry.detail, entry.page, "setting"); } for (const bind of Keybinds.binds) { if (bind.description.toLowerCase().indexOf(needle) >= 0) add(bind.description, bind.chord, "shortcuts", "shortcut"); } // Exact prefix matches first: typing "blur" should put "Blur" above // "Blur radius", and both above a setting that merely mentions blur in // its explanation. return results.sort((a, b) => { const al = a.label.toLowerCase(); const bl = b.label.toLowerCase(); const ap = al === needle ? 0 : (al.indexOf(needle) === 0 ? 1 : 2); const bp = bl === needle ? 0 : (bl.indexOf(needle) === 0 ? 1 : 2); return ap !== bp ? ap - bp : al.localeCompare(bl); }).slice(0, 40); } }