Skip to content

Commit 8bfb068

Browse files
committed
hyprpanel: init at unstable-2025-02-17
1 parent d21dc08 commit 8bfb068

File tree

2 files changed

+353
-0
lines changed

2 files changed

+353
-0
lines changed

pkgs/by-name/hy/hyprpanel/package.nix

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
{
2+
lib,
3+
config,
4+
ags,
5+
astal,
6+
bluez,
7+
bluez-tools,
8+
brightnessctl,
9+
btop,
10+
dart-sass,
11+
fetchFromGitHub,
12+
fetchpatch2,
13+
glib,
14+
gnome-bluetooth,
15+
gpu-screen-recorder,
16+
gpustat,
17+
grimblast,
18+
gvfs,
19+
hyprpicker,
20+
libgtop,
21+
libnotify,
22+
matugen,
23+
networkmanager,
24+
python3,
25+
pywal,
26+
stdenv,
27+
swww,
28+
upower,
29+
wireplumber,
30+
wl-clipboard,
31+
writeShellScript,
32+
33+
enableCuda ? config.cudaSupport,
34+
}:
35+
ags.bundle {
36+
pname = "hyprpanel";
37+
version = "unstable-2025-02-17";
38+
39+
__structuredAttrs = true;
40+
strictDeps = true;
41+
42+
src = fetchFromGitHub {
43+
owner = "Jas-SinghFSU";
44+
repo = "HyprPanel";
45+
rev = "9b342341fe17e4fb2c4cad9e3379a814a6a73097";
46+
hash = "sha256-OQS2yhBYJZPvxkPGEx9FqT+voXTDm0UJDknCBBWgroo=";
47+
};
48+
49+
patches = [
50+
# please merge https://github.com/NixOS/nixpkgs/pull/374302
51+
./remove-tray.patch
52+
];
53+
54+
# keep in sync with https://github.com/Jas-SinghFSU/HyprPanel/blob/master/flake.nix#L28
55+
dependencies = [
56+
astal.apps
57+
astal.battery
58+
astal.bluetooth
59+
astal.cava
60+
astal.hyprland
61+
astal.mpris
62+
astal.network
63+
astal.notifd
64+
astal.powerprofiles
65+
# https://github.com/NixOS/nixpkgs/pull/374302
66+
# astal.tray
67+
astal.wireplumber
68+
69+
bluez
70+
bluez-tools
71+
brightnessctl
72+
btop
73+
dart-sass
74+
glib
75+
gnome-bluetooth
76+
grimblast
77+
gvfs
78+
hyprpicker
79+
libgtop
80+
libnotify
81+
matugen
82+
networkmanager
83+
pywal
84+
swww
85+
upower
86+
wireplumber
87+
wl-clipboard
88+
(python3.withPackages (
89+
ps:
90+
with ps;
91+
[
92+
dbus-python
93+
pygobject3
94+
]
95+
++ lib.optional enableCuda gpustat
96+
))
97+
] ++ (lib.optionals (stdenv.hostPlatform.system == "x86_64-linux") [ gpu-screen-recorder ]);
98+
99+
# NOTE: no update script as dependencies must be kept in sync with upstream
100+
# and it is problematic to do it in an update script. I don't have push
101+
# access to r-ryantm's repo, so I will just do updates manually
102+
103+
postFixup =
104+
let
105+
script = writeShellScript "hyprpanel" ''
106+
if [ "$#" -eq 0 ]; then
107+
exec @out@/bin/.hyprpanel
108+
else
109+
exec ${astal.io}/bin/astal -i hyprpanel "$*"
110+
fi
111+
'';
112+
in
113+
# bash
114+
''
115+
mv "$out/bin/hyprpanel" "$out/bin/.hyprpanel"
116+
cp '${script}' "$out/bin/hyprpanel"
117+
substituteInPlace "$out/bin/hyprpanel" \
118+
--replace-fail '@out@' "$out"
119+
'';
120+
121+
meta = {
122+
description = "Bar/Panel for Hyprland with extensive customizability";
123+
homepage = "https://github.com/Jas-SinghFSU/HyprPanel";
124+
license = lib.licenses.mit;
125+
maintainers = with lib.maintainers; [ perchun ];
126+
mainProgram = "hyprpanel";
127+
platforms = lib.platforms.linux;
128+
};
129+
}
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
diff --git a/app.ts b/app.ts
2+
index 4457e61..7e75a75 100644
3+
--- a/app.ts
4+
+++ b/app.ts
5+
@@ -2,7 +2,6 @@ import './src/lib/session';
6+
import './src/scss/style';
7+
import './src/globals/useTheme';
8+
import './src/globals/wallpaper';
9+
-import './src/globals/systray';
10+
import './src/globals/dropdown';
11+
import './src/globals/utilities';
12+
import './src/components/bar/utils/sideEffects';
13+
diff --git a/src/components/bar/exports.ts b/src/components/bar/exports.ts
14+
index fc4f9b5..f9254b2 100644
15+
--- a/src/components/bar/exports.ts
16+
+++ b/src/components/bar/exports.ts
17+
@@ -8,7 +8,6 @@ import { Network } from '../../components/bar/modules/network/index';
18+
import { Bluetooth } from '../../components/bar/modules/bluetooth/index';
19+
import { BatteryLabel } from '../../components/bar/modules/battery/index';
20+
import { Clock } from '../../components/bar/modules/clock/index';
21+
-import { SysTray } from '../../components/bar/modules/systray/index';
22+
23+
// Custom Modules
24+
import { Ram } from '../../components/bar/modules/ram/index';
25+
@@ -36,7 +35,6 @@ export {
26+
Bluetooth,
27+
BatteryLabel,
28+
Clock,
29+
- SysTray,
30+
31+
// Custom Modules
32+
Ram,
33+
diff --git a/src/components/bar/index.tsx b/src/components/bar/index.tsx
34+
index e770c04..bd4283b 100644
35+
--- a/src/components/bar/index.tsx
36+
+++ b/src/components/bar/index.tsx
37+
@@ -9,7 +9,6 @@ import {
38+
Bluetooth,
39+
BatteryLabel,
40+
Clock,
41+
- SysTray,
42+
43+
// Custom Modules
44+
Ram,
45+
@@ -50,7 +49,6 @@ const widget = {
46+
network: (): JSX.Element => WidgetContainer(Network()),
47+
bluetooth: (): JSX.Element => WidgetContainer(Bluetooth()),
48+
clock: (): JSX.Element => WidgetContainer(Clock()),
49+
- systray: (): JSX.Element => WidgetContainer(SysTray()),
50+
ram: (): JSX.Element => WidgetContainer(Ram()),
51+
cpu: (): JSX.Element => WidgetContainer(Cpu()),
52+
cputemp: (): JSX.Element => WidgetContainer(CpuTemp()),
53+
diff --git a/src/components/bar/modules/systray/index.tsx b/src/components/bar/modules/systray/index.tsx
54+
deleted file mode 100644
55+
index f25e141..0000000
56+
--- a/src/components/bar/modules/systray/index.tsx
57+
+++ /dev/null
58+
@@ -1,142 +0,0 @@
59+
-import { isMiddleClick, isPrimaryClick, isSecondaryClick, Notify } from '../../../../lib/utils';
60+
-import options from '../../../../options';
61+
-import AstalTray from 'gi://AstalTray?version=0.1';
62+
-import { bind, Gio, Variable } from 'astal';
63+
-import { BarBoxChild } from 'src/lib/types/bar';
64+
-import { Gdk, Gtk } from 'astal/gtk3';
65+
-
66+
-const systemtray = AstalTray.get_default();
67+
-const { ignore, customIcons } = options.bar.systray;
68+
-
69+
-//TODO: Connect to `notify::menu-model` and `notify::action-group` to have up to date menu and action group
70+
-const createMenu = (menuModel: Gio.MenuModel, actionGroup: Gio.ActionGroup | null): Gtk.Menu => {
71+
- const menu = Gtk.Menu.new_from_model(menuModel);
72+
- menu.insert_action_group('dbusmenu', actionGroup);
73+
-
74+
- return menu;
75+
-};
76+
-
77+
-const MenuCustomIcon = ({ iconLabel, iconColor, item }: MenuCustomIconProps): JSX.Element => {
78+
- return (
79+
- <label
80+
- className={'systray-icon txt-icon'}
81+
- label={iconLabel}
82+
- css={iconColor ? `color: ${iconColor}` : ''}
83+
- tooltipMarkup={bind(item, 'tooltipMarkup')}
84+
- />
85+
- );
86+
-};
87+
-
88+
-const MenuDefaultIcon = ({ item }: MenuEntryProps): JSX.Element => {
89+
- return <icon className={'systray-icon'} gIcon={bind(item, 'gicon')} tooltipMarkup={bind(item, 'tooltipMarkup')} />;
90+
-};
91+
-
92+
-const MenuEntry = ({ item, child }: MenuEntryProps): JSX.Element => {
93+
- let menu: Gtk.Menu;
94+
-
95+
- const entryBinding = Variable.derive(
96+
- [bind(item, 'menuModel'), bind(item, 'actionGroup')],
97+
- (menuModel, actionGroup) => {
98+
- if (!menuModel) {
99+
- return console.error(`Menu Model not found for ${item.id}`);
100+
- }
101+
- if (!actionGroup) {
102+
- return console.error(`Action Group not found for ${item.id}`);
103+
- }
104+
-
105+
- menu = createMenu(menuModel, actionGroup);
106+
- },
107+
- );
108+
-
109+
- return (
110+
- <button
111+
- cursor={'pointer'}
112+
- onClick={(self, event) => {
113+
- if (isPrimaryClick(event)) {
114+
- item.activate(0, 0);
115+
- }
116+
-
117+
- if (isSecondaryClick(event)) {
118+
- menu?.popup_at_widget(self, Gdk.Gravity.NORTH, Gdk.Gravity.SOUTH, null);
119+
- }
120+
-
121+
- if (isMiddleClick(event)) {
122+
- Notify({ summary: 'App Name', body: item.id });
123+
- }
124+
- }}
125+
- onDestroy={() => {
126+
- menu?.destroy();
127+
- entryBinding.drop();
128+
- }}
129+
- >
130+
- {child}
131+
- </button>
132+
- );
133+
-};
134+
-
135+
-const SysTray = (): BarBoxChild => {
136+
- const isVis = Variable(false);
137+
-
138+
- const componentChildren = Variable.derive(
139+
- [bind(systemtray, 'items'), bind(ignore), bind(customIcons)],
140+
- (items, ignored, custIcons) => {
141+
- const filteredTray = items.filter(({ id }) => !ignored.includes(id) && id !== null);
142+
-
143+
- isVis.set(filteredTray.length > 0);
144+
-
145+
- return filteredTray.map((item) => {
146+
- const matchedCustomIcon = Object.keys(custIcons).find((iconRegex) => item.id.match(iconRegex));
147+
-
148+
- if (matchedCustomIcon !== undefined) {
149+
- const iconLabel = custIcons[matchedCustomIcon].icon || '󰠫';
150+
- const iconColor = custIcons[matchedCustomIcon].color;
151+
-
152+
- return (
153+
- <MenuEntry item={item}>
154+
- <MenuCustomIcon iconLabel={iconLabel} iconColor={iconColor} item={item} />
155+
- </MenuEntry>
156+
- );
157+
- }
158+
- return (
159+
- <MenuEntry item={item}>
160+
- <MenuDefaultIcon item={item} />
161+
- </MenuEntry>
162+
- );
163+
- });
164+
- },
165+
- );
166+
-
167+
- const component = (
168+
- <box
169+
- className={'systray-container'}
170+
- onDestroy={() => {
171+
- isVis.drop();
172+
- componentChildren.drop();
173+
- }}
174+
- >
175+
- {componentChildren()}
176+
- </box>
177+
- );
178+
-
179+
- return {
180+
- component,
181+
- isVisible: true,
182+
- boxClass: 'systray',
183+
- isVis,
184+
- isBox: true,
185+
- props: {},
186+
- };
187+
-};
188+
-
189+
-interface MenuCustomIconProps {
190+
- iconLabel: string;
191+
- iconColor: string;
192+
- item: AstalTray.TrayItem;
193+
-}
194+
-
195+
-interface MenuEntryProps {
196+
- item: AstalTray.TrayItem;
197+
- child?: JSX.Element;
198+
-}
199+
-
200+
-export { SysTray };
201+
diff --git a/src/globals/systray.ts b/src/globals/systray.ts
202+
deleted file mode 100644
203+
index c9dbe43..0000000
204+
--- a/src/globals/systray.ts
205+
+++ /dev/null
206+
@@ -1,18 +0,0 @@
207+
-import AstalTray from 'gi://AstalTray';
208+
-import { errorHandler } from 'src/lib/utils';
209+
-const systemtray = AstalTray.get_default();
210+
-
211+
-globalThis.getSystrayItems = (): string => {
212+
- try {
213+
- const items = systemtray
214+
- .get_items()
215+
- .map((systrayItem) => systrayItem.id)
216+
- .join('\n');
217+
-
218+
- return items;
219+
- } catch (error) {
220+
- errorHandler(error);
221+
- }
222+
-};
223+
-
224+
-export { getSystrayItems };

0 commit comments

Comments
 (0)