Files
custum-hyprpanel/src/components/bar/index.tsx
Ed Bennett 6efcd60467 Cava Module (#662)
* First version of the cava module

* Update cava stuff

* Update themes for cava

* Update themes

* Handle cava visibility when null

* Add bar characters in options

---------

Co-authored-by: Ed Bennett <ed@dodimead.com>
Co-authored-by: Jas Singh <jaskiratpal.singh@outlook.com>
2025-01-02 22:45:37 -08:00

172 lines
6.2 KiB
TypeScript

import {
Menu,
Workspaces,
ClientTitle,
Media,
Notifications,
Volume,
Network,
Bluetooth,
BatteryLabel,
Clock,
SysTray,
// Custom Modules
Ram,
Cpu,
CpuTemp,
Storage,
Netstat,
KbInput,
Updates,
Submap,
Weather,
Power,
Hyprsunset,
Hypridle,
Cava,
} from './exports';
import { WidgetContainer } from './shared/WidgetContainer';
import options from 'src/options';
import { App, Gtk } from 'astal/gtk3';
import Astal from 'gi://Astal?version=3.0';
import { bind, Variable } from 'astal';
import { gdkMonitorIdToHyprlandId, getLayoutForMonitor, isLayoutEmpty } from './utils/monitors';
const { layouts } = options.bar;
const { location } = options.theme.bar;
const { location: borderLocation } = options.theme.bar.border;
const widget = {
battery: (): JSX.Element => WidgetContainer(BatteryLabel()),
dashboard: (): JSX.Element => WidgetContainer(Menu()),
workspaces: (monitor: number): JSX.Element => WidgetContainer(Workspaces(monitor)),
windowtitle: (): JSX.Element => WidgetContainer(ClientTitle()),
media: (): JSX.Element => WidgetContainer(Media()),
notifications: (): JSX.Element => WidgetContainer(Notifications()),
volume: (): JSX.Element => WidgetContainer(Volume()),
network: (): JSX.Element => WidgetContainer(Network()),
bluetooth: (): JSX.Element => WidgetContainer(Bluetooth()),
clock: (): JSX.Element => WidgetContainer(Clock()),
systray: (): JSX.Element => WidgetContainer(SysTray()),
ram: (): JSX.Element => WidgetContainer(Ram()),
cpu: (): JSX.Element => WidgetContainer(Cpu()),
cputemp: (): JSX.Element => WidgetContainer(CpuTemp()),
storage: (): JSX.Element => WidgetContainer(Storage()),
netstat: (): JSX.Element => WidgetContainer(Netstat()),
kbinput: (): JSX.Element => WidgetContainer(KbInput()),
updates: (): JSX.Element => WidgetContainer(Updates()),
submap: (): JSX.Element => WidgetContainer(Submap()),
weather: (): JSX.Element => WidgetContainer(Weather()),
power: (): JSX.Element => WidgetContainer(Power()),
hyprsunset: (): JSX.Element => WidgetContainer(Hyprsunset()),
hypridle: (): JSX.Element => WidgetContainer(Hypridle()),
cava: (): JSX.Element => WidgetContainer(Cava()),
};
export const Bar = (() => {
const usedHyprlandMonitors = new Set<number>();
return (monitor: number): JSX.Element => {
const hyprlandMonitor = gdkMonitorIdToHyprlandId(monitor, usedHyprlandMonitors);
const computeVisibility = bind(layouts).as(() => {
const foundLayout = getLayoutForMonitor(hyprlandMonitor, layouts.get());
return !isLayoutEmpty(foundLayout);
});
const computeAnchor = bind(location).as((loc) => {
if (loc === 'bottom') {
return Astal.WindowAnchor.BOTTOM | Astal.WindowAnchor.LEFT | Astal.WindowAnchor.RIGHT;
}
return Astal.WindowAnchor.TOP | Astal.WindowAnchor.LEFT | Astal.WindowAnchor.RIGHT;
});
const computeLayer = Variable.derive([bind(options.theme.bar.layer), bind(options.tear)], (barLayer, tear) => {
if (tear && barLayer === 'overlay') {
return Astal.Layer.TOP;
}
const layerMap = {
overlay: Astal.Layer.OVERLAY,
top: Astal.Layer.TOP,
bottom: Astal.Layer.BOTTOM,
background: Astal.Layer.BACKGROUND,
};
return layerMap[barLayer];
});
const computeBorderLocation = bind(borderLocation).as((brdrLcn) =>
brdrLcn !== 'none' ? 'bar-panel withBorder' : 'bar-panel',
);
const leftBinding = Variable.derive([bind(layouts)], (currentLayouts) => {
const foundLayout = getLayoutForMonitor(hyprlandMonitor, currentLayouts);
return foundLayout.left
.filter((mod) => Object.keys(widget).includes(mod))
.map((w) => widget[w](hyprlandMonitor));
});
const middleBinding = Variable.derive([bind(layouts)], (currentLayouts) => {
const foundLayout = getLayoutForMonitor(hyprlandMonitor, currentLayouts);
return foundLayout.middle
.filter((mod) => Object.keys(widget).includes(mod))
.map((w) => widget[w](hyprlandMonitor));
});
const rightBinding = Variable.derive([bind(layouts)], (currentLayouts) => {
const foundLayout = getLayoutForMonitor(hyprlandMonitor, currentLayouts);
return foundLayout.right
.filter((mod) => Object.keys(widget).includes(mod))
.map((w) => widget[w](hyprlandMonitor));
});
return (
<window
name={`bar-${hyprlandMonitor}`}
namespace={`bar-${hyprlandMonitor}`}
className={'bar'}
application={App}
monitor={monitor}
visible={computeVisibility}
anchor={computeAnchor}
layer={computeLayer()}
exclusivity={Astal.Exclusivity.EXCLUSIVE}
onDestroy={() => {
computeLayer.drop();
leftBinding.drop();
middleBinding.drop();
rightBinding.drop();
}}
>
<box className={'bar-panel-container'}>
<centerbox
css={'padding: 1px;'}
hexpand
className={computeBorderLocation}
startWidget={
<box className={'box-left'} hexpand>
{leftBinding()}
</box>
}
centerWidget={
<box className={'box-center'} halign={Gtk.Align.CENTER}>
{middleBinding()}
</box>
}
endWidget={
<box className={'box-right'} halign={Gtk.Align.END}>
{rightBinding()}
</box>
}
/>
</box>
</window>
);
};
})();