import Apps from "gi://AstalApps"; import AstalHyprland from "gi://AstalHyprland"; const app_icons = new Apps.Apps().list.reduce( (acc, app) => { // keys from AstalApps entries are typically wm_class (snake_case) or name const key = app.wm_class ?? app.name; if (key) { acc.classOrNames[key] = app.icon_name; } if (app.executable) { acc.executables[app.executable] = app.icon_name; } return acc; }, { classOrNames: {} as Record, executables: {} as Record }, ); export function getIconName(client: AstalHyprland.Client | null | undefined) { if (!client) return ""; // try a bunch of fields (snake_case and camelCase variants) const possibleKeys = [ // common client properties (snake_case) (client as any).wm_class, (client as any).initial_class, (client as any).executable, // camelCase variants (some bindings expose these) (client as any).class, (client as any).initialClass, (client as any).initialTitle, (client as any).title, (client as any).name, ].filter(Boolean) as string[]; // 1) direct exact match for (const k of possibleKeys) { const icon = app_icons.classOrNames[k] ?? app_icons.executables[k]; if (icon) { // cache the mapping for this client's canonical class (prefer wm_class or class) const cacheKey = (client as any).wm_class ?? (client as any).class ?? (client as any).name ?? k; app_icons.classOrNames[cacheKey] = icon; return icon; } } // 2) fuzzy match: see if any stored key includes any of the client strings (title, name, etc.) const searchStrings = [ (client as any).title, (client as any).initialTitle, (client as any).initial_class, (client as any).initialClass, (client as any).wm_class, (client as any).class, (client as any).name, ].filter(Boolean) as string[]; for (const s of searchStrings) { const matchKey = Object.keys(app_icons.classOrNames).find((key) => key.includes(s)); if (matchKey) { const icon = app_icons.classOrNames[matchKey]; const cacheKey = (client as any).wm_class ?? (client as any).class ?? (client as any).name ?? s; app_icons.classOrNames[cacheKey] = icon; return icon; } } // nothing found — cache empty string so we don't repeat work const cacheKey = (client as any).wm_class ?? (client as any).class ?? (client as any).name ?? ""; if (cacheKey) app_icons.classOrNames[cacheKey] = ""; return ""; }