dotfiles/home/ags/files/utils.ts

54 lines
1.8 KiB
TypeScript

import Apps from "gi://AstalApps";
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<string, string>, executables: {} as Record<string, string> },
);
export function getIconName(app_id: string | null | undefined, title: string | null | undefined) {
if (!app_id && !title) return "";
// try fields matching Niri outputs
const possibleKeys = [
app_id,
title
].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
const cacheKey = app_id ?? title ?? 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.)
for (const s of possibleKeys) {
const matchKey = Object.keys(app_icons.classOrNames).find((key) => key.includes(s));
if (matchKey) {
const icon = app_icons.classOrNames[matchKey];
const cacheKey = app_id ?? title ?? s;
app_icons.classOrNames[cacheKey] = icon;
return icon;
}
}
// nothing found — cache empty string so we don't repeat work
const cacheKey = app_id ?? title ?? "";
if (cacheKey) app_icons.classOrNames[cacheKey] = "";
return "";
}