Fix astal system tray

This commit is contained in:
Thomas Avé 2025-10-28 18:35:26 +07:00
parent 991882d485
commit c9ebaa4f19
5 changed files with 80 additions and 29 deletions

View File

@ -19,6 +19,7 @@ const wirePlumber = Wp.get_default();
function SysTray(): JSX.Element { function SysTray(): JSX.Element {
const tray = Tray.get_default(); const tray = Tray.get_default();
let items = createBinding(tray, "items"); let items = createBinding(tray, "items");
const init = (btn: Gtk.MenuButton, item: Tray.TrayItem) => { const init = (btn: Gtk.MenuButton, item: Tray.TrayItem) => {
btn.menuModel = item.menuModel; btn.menuModel = item.menuModel;
btn.insert_action_group("dbusmenu", item.actionGroup); btn.insert_action_group("dbusmenu", item.actionGroup);
@ -26,6 +27,7 @@ function SysTray(): JSX.Element {
btn.insert_action_group("dbusmenu", item.actionGroup); btn.insert_action_group("dbusmenu", item.actionGroup);
}); });
}; };
return ( return (
<box> <box>
<For each={items}> <For each={items}>
@ -38,7 +40,10 @@ function SysTray(): JSX.Element {
tooltipMarkup={createBinding(item, "tooltipMarkup")} tooltipMarkup={createBinding(item, "tooltipMarkup")}
menuModel={createBinding(item, "menuModel")} menuModel={createBinding(item, "menuModel")}
> >
<image gicon={item.gicon} class="systray-item" /> <image
gicon={createBinding(item, "gicon")}
class="systray-item"
/>
</menubutton> </menubutton>
); );
}} }}

View File

@ -1,40 +1,72 @@
import Apps from "gi://AstalApps" import Apps from "gi://AstalApps";
import AstalHyprland from "gi://AstalHyprland"; import AstalHyprland from "gi://AstalHyprland";
const app_icons = new Apps.Apps().list.reduce( const app_icons = new Apps.Apps().list.reduce(
(acc, app) => { (acc, app) => {
if (app.icon_name) { // keys from AstalApps entries are typically wm_class (snake_case) or name
acc.classOrNames[app.wm_class ?? app.name] = app.icon_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; acc.executables[app.executable] = app.icon_name;
} }
return acc; return acc;
}, },
{ classOrNames: {}, executables: {} }, { classOrNames: {} as Record<string, string>, executables: {} as Record<string, string> },
); );
export function getIconName(client: AstalHyprland.Client) { export function getIconName(client: AstalHyprland.Client | null | undefined) {
if (!client) { if (!client) return "";
return "";
}
let icon = app_icons.classOrNames[client.class]; // try a bunch of fields (snake_case and camelCase variants)
if (!icon) { const possibleKeys = [
const icon_key = Object.keys(app_icons.classOrNames).find( // common client properties (snake_case)
(key) => (client as any).wm_class,
key.includes(client.title) || (client as any).initial_class,
key.includes(client.initialTitle) || (client as any).executable,
key.includes(client.initialClass) || // camelCase variants (some bindings expose these)
key.includes(client.class), (client as any).class,
); (client as any).initialClass,
if (icon_key) { (client as any).initialTitle,
icon = app_icons.classOrNames[icon_key]; (client as any).title,
app_icons.classOrNames[client.class] = icon; (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;
} }
} }
if (!icon) { // 2) fuzzy match: see if any stored key includes any of the client strings (title, name, etc.)
app_icons.classOrNames[client.class] = ""; 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;
}
} }
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 "";
} }

View File

@ -12,6 +12,7 @@
tweak = { tweak = {
sixel = "yes"; sixel = "yes";
}; };
scrollback.lines = 100000;
colors = { colors = {
background = "000010"; background = "000010";
foreground = "F8F8F2"; foreground = "F8F8F2";

View File

@ -5,8 +5,8 @@
pname = "Helium"; pname = "Helium";
version = "0.4.7.1"; version = "0.4.7.1";
src = pkgs.fetchurl { src = pkgs.fetchurl {
url = "https://github.com/imputnet/helium-linux/releases/download/0.4.7.1/helium-0.4.7.1-x86_64.AppImage"; url = "https://release-assets.githubusercontent.com/github-production-release-asset/1043354934/31a5650e-2719-4734-8aa7-8b45ff506fe7";
sha256 = "b7a64d9cd96c841119f4729545d7b88ed804fdcac99d3878099f338766dfdd2d"; sha256 = "275853aae038ee08a6d07ed314c33e25a6d8e5845c2f9b27253a4cfde94dd732";
}; };
}) })
]; ];

View File

@ -33,7 +33,7 @@ in {
networking.wireless.iwd.enable = true; networking.wireless.iwd.enable = true;
networking.wireless.iwd.settings = { networking.wireless.iwd.settings = {
IPv6 = { IPv6 = {
Enabled = true; Enabled = false;
}; };
Settings = { Settings = {
AutoConnect = true; AutoConnect = true;
@ -77,7 +77,7 @@ in {
networking.wg-quick.interfaces = { networking.wg-quick.interfaces = {
Tunnel = { Tunnel = {
address = [ "10.0.0.5/24" "2a02:a03f:83ad:2101::5/128" ]; address = [ "10.0.0.5/24" ];
privateKeyFile = "/home/user/.secrets/Wireguard/Aloria.key"; privateKeyFile = "/home/user/.secrets/Wireguard/Aloria.key";
listenPort = 51820; listenPort = 51820;
autostart = false; autostart = false;
@ -91,7 +91,7 @@ in {
}]; }];
}; };
OPNsense = { OPNsense = {
address = [ "10.0.0.5/24" "2a02:a03f:83ad:2101::5/128" ]; address = [ "10.0.0.5/24" ];
privateKeyFile = "/home/user/.secrets/Wireguard/Aloria.key"; privateKeyFile = "/home/user/.secrets/Wireguard/Aloria.key";
listenPort = 51820; listenPort = 51820;
autostart = true; autostart = true;
@ -104,6 +104,19 @@ in {
persistentKeepalive = 25; persistentKeepalive = 25;
}]; }];
}; };
GCP = {
address = [ "10.5.0.5/24" ];
privateKeyFile = "/home/user/.secrets/Wireguard/GCP.key";
listenPort = 51820;
autostart = false;
postUp = "resolvectl dns GCP 1.1.1.1;resolvectl dns wlan0 1.1.1.1;";
peers = [{
publicKey = "NEBNE4Czf2MkZF2X5aVhmofENH1uXjDpvXjIMJvfMFA=";
allowedIPs = [ "0.0.0.0/0" ];
endpoint = "35.201.231.151:443";
persistentKeepalive = 25;
}];
};
}; };
systemd.services."wg-quick-OPNsense" = { systemd.services."wg-quick-OPNsense" = {
serviceConfig = { Restart = "on-failure"; RestartSec = "2s"; }; serviceConfig = { Restart = "on-failure"; RestartSec = "2s"; };