Files
custum-hyprpanel/src/components/bar/modules/systray/index.tsx
Jas Singh 8cf5806766 Minor: Refactor the code-base for better organization and compartmentalization. (#934)
* Clean up unused code

* Fix media player formatting issue for labels with new line characteres.

* Refactor the media player handlers into a class.

* More code cleanup and organize shared weather utils into distinct classes.

* Flatten some nesting.

* Move weather manager in dedicated class and build HTTP Utility class for Rest API calling.

* Remove logs

* Rebase master merge

* Reorg code (WIP)

* More reorg

* Delete utility scripts

* Reorg options

* Finish moving all options over

* Fix typescript issues

* Update options imports to default

* missed update

* Screw barrel files honestly, work of the devil.

* Only initialize power profiles if power-profiles-daemon is running.

* Fix window positioning and weather service naming

* style dir

* More organization

* Restructure types to be closer to their source

* Remove lib types and constants

* Update basic weather object to be saner with extensibility.

* Service updates

* Fix initialization strategy for services.

* Fix Config Manager to only emit changed objects and added missing temp converters.

* Update storage service to handle unit changes.

* Added cpu temp sensor auto-discovery

* Added missing JSDocs to services

* remove unused

* Migrate to network service.

* Fix network password issue.

* Move out password input into helper

* Rename password mask constant to be less double-negativey.

* Dropdown menu rename

* Added a component to edit JSON in the settings dialog (rough/WIP)

* Align settings

* Add and style JSON Editor.

* Adjust padding

* perf(shortcuts):  avoid unnecessary polling when shortcuts are disabled

Stops the recording poller when shortcuts are disabled, preventing redundant polling and reducing resource usage.

* Fix types and return value if shortcut not enabled.

* Move the swww daemon checking process outside of the wallpaper service into a dedicated deamon lifecyle processor.

* Add more string formatters and use title case for weather status (as it was).

* Fix startup errors.

* Rgba fix

* Remove zod from dependencies

---------

Co-authored-by: KernelDiego <gonzalezdiego.contact@gmail.com>
2025-05-26 19:45:11 -07:00

151 lines
4.4 KiB
TypeScript

import AstalTray from 'gi://AstalTray?version=0.1';
import { bind, Gio, Variable } from 'astal';
import { Gdk, Gtk } from 'astal/gtk3';
import { BarBoxChild } from 'src/components/bar/types';
import options from 'src/configuration';
import { isPrimaryClick, isSecondaryClick, isMiddleClick } from 'src/lib/events/mouse';
import { SystemUtilities } from 'src/core/system/SystemUtilities';
const systemtray = AstalTray.get_default();
const { ignore, customIcons } = options.bar.systray;
const createMenu = (menuModel: Gio.MenuModel, actionGroup: Gio.ActionGroup | null): Gtk.Menu => {
const menu = Gtk.Menu.new_from_model(menuModel);
menu.insert_action_group('dbusmenu', actionGroup);
return menu;
};
const MenuCustomIcon = ({ iconLabel, iconColor, item }: MenuCustomIconProps): JSX.Element => {
return (
<label
className={'systray-icon txt-icon'}
label={iconLabel}
css={iconColor ? `color: ${iconColor}` : ''}
tooltipMarkup={bind(item, 'tooltipMarkup')}
/>
);
};
const MenuDefaultIcon = ({ item }: MenuEntryProps): JSX.Element => {
return (
<icon
className={'systray-icon'}
gicon={bind(item, 'gicon')}
tooltipMarkup={bind(item, 'tooltipMarkup')}
/>
);
};
const MenuEntry = ({ item, child }: MenuEntryProps): JSX.Element => {
let menu: Gtk.Menu;
const entryBinding = Variable.derive(
[bind(item, 'menuModel'), bind(item, 'actionGroup')],
(menuModel, actionGroup) => {
if (menuModel === null) {
return console.error(`Menu Model not found for ${item.id}`);
}
if (actionGroup === null) {
return console.error(`Action Group not found for ${item.id}`);
}
menu = createMenu(menuModel, actionGroup);
},
);
return (
<button
cursor={'pointer'}
onClick={(self, event) => {
if (isPrimaryClick(event)) {
item.activate(0, 0);
}
if (isSecondaryClick(event)) {
menu?.popup_at_widget(self, Gdk.Gravity.NORTH, Gdk.Gravity.SOUTH, null);
}
if (isMiddleClick(event)) {
SystemUtilities.notify({ summary: 'App Name', body: item.id });
}
}}
onDestroy={() => {
menu?.destroy();
entryBinding.drop();
}}
>
{child}
</button>
);
};
const SysTray = (): BarBoxChild => {
const isVis = Variable(false);
const componentChildren = Variable.derive(
[bind(systemtray, 'items'), bind(ignore), bind(customIcons)],
(items, ignored, custIcons) => {
const filteredTray = items.filter(({ id }) => !ignored.includes(id) && id !== null);
isVis.set(filteredTray.length > 0);
return filteredTray.map((item) => {
const matchedCustomIcon = Object.keys(custIcons).find((iconRegex) =>
item.id.match(iconRegex),
);
if (matchedCustomIcon !== undefined) {
const iconLabel = custIcons[matchedCustomIcon].icon || '󰠫';
const iconColor = custIcons[matchedCustomIcon].color;
return (
<MenuEntry item={item}>
<MenuCustomIcon iconLabel={iconLabel} iconColor={iconColor} item={item} />
</MenuEntry>
);
}
return (
<MenuEntry item={item}>
<MenuDefaultIcon item={item} />
</MenuEntry>
);
});
},
);
const component = (
<box
className={'systray-container'}
onDestroy={() => {
isVis.drop();
componentChildren.drop();
}}
>
{componentChildren()}
</box>
);
return {
component,
isVisible: true,
boxClass: 'systray',
isVis: bind(isVis),
isBox: true,
props: {},
};
};
interface MenuCustomIconProps {
iconLabel: string;
iconColor: string;
item: AstalTray.TrayItem;
}
interface MenuEntryProps {
item: AstalTray.TrayItem;
child?: JSX.Element;
}
export { SysTray };