summaryrefslogtreecommitdiff
path: root/src/modules/bar.tsx
diff options
context:
space:
mode:
author2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-04-26 22:36:23 +1000
committer2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>2025-04-26 22:36:23 +1000
commit3c579d0e275cdaf6f2c9589abade94bde7905c82 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /src/modules/bar.tsx
parentschemes: fix (diff)
downloadcaelestia-shell-3c579d0e275cdaf6f2c9589abade94bde7905c82.tar.gz
caelestia-shell-3c579d0e275cdaf6f2c9589abade94bde7905c82.tar.bz2
caelestia-shell-3c579d0e275cdaf6f2c9589abade94bde7905c82.zip
clean
Remove everything
Diffstat (limited to 'src/modules/bar.tsx')
-rw-r--r--src/modules/bar.tsx703
1 files changed, 0 insertions, 703 deletions
diff --git a/src/modules/bar.tsx b/src/modules/bar.tsx
deleted file mode 100644
index c131029..0000000
--- a/src/modules/bar.tsx
+++ /dev/null
@@ -1,703 +0,0 @@
-import type { Monitor } from "@/services/monitors";
-import Players from "@/services/players";
-import Updates from "@/services/updates";
-import { getAppCategoryIcon } from "@/utils/icons";
-import { bindCurrentTime, osIcon } from "@/utils/system";
-import type { AstalWidget } from "@/utils/types";
-import { setupCustomTooltip } from "@/utils/widgets";
-import ScreenCorner from "@/widgets/screencorner";
-import { execAsync, GLib, Variable } from "astal";
-import { bind, kebabify } from "astal/binding";
-import { App, Astal, Gtk, Widget } from "astal/gtk3";
-import { bar as config } from "config";
-import AstalBattery from "gi://AstalBattery";
-import AstalBluetooth from "gi://AstalBluetooth";
-import AstalHyprland from "gi://AstalHyprland";
-import AstalNetwork from "gi://AstalNetwork";
-import AstalNotifd from "gi://AstalNotifd";
-import AstalTray from "gi://AstalTray";
-import AstalWp from "gi://AstalWp";
-import { switchPane } from "./sidebar";
-
-interface ClassNameProps {
- beforeSpacer: boolean;
- afterSpacer: boolean;
- first: boolean;
- last: boolean;
-}
-
-interface ModuleProps extends ClassNameProps {
- monitor: Monitor;
-}
-
-const hyprland = AstalHyprland.get_default();
-
-const getBatteryIcon = (perc: number) => {
- if (perc < 0.1) return "󰁺";
- if (perc < 0.2) return "󰁻";
- if (perc < 0.3) return "󰁼";
- if (perc < 0.4) return "󰁽";
- if (perc < 0.5) return "󰁾";
- if (perc < 0.6) return "󰁿";
- if (perc < 0.7) return "󰂀";
- if (perc < 0.8) return "󰂁";
- if (perc < 0.9) return "󰂂";
- return "󰁹";
-};
-
-const formatSeconds = (sec: number) => {
- if (sec >= 3600) {
- const hours = Math.floor(sec / 3600);
- let str = `${hours} hour${hours === 1 ? "" : "s"}`;
- const mins = Math.floor((sec % 3600) / 60);
- if (mins > 0) str += ` ${mins} minute${mins === 1 ? "" : "s"}`;
- return str;
- } else if (sec >= 60) {
- const mins = Math.floor(sec / 60);
- return `${mins} minute${mins === 1 ? "" : "s"}`;
- } else return `${sec} second${sec === 1 ? "" : "s"}`;
-};
-
-const hookFocusedClientProp = (
- self: AstalWidget,
- prop: keyof AstalHyprland.Client,
- callback: (c: AstalHyprland.Client | null) => void
-) => {
- let id: number | null = null;
- let lastClient: AstalHyprland.Client | null = null;
- self.hook(hyprland, "notify::focused-client", () => {
- if (id) lastClient?.disconnect(id);
- lastClient = hyprland.focusedClient; // Can be null
- id = lastClient?.connect(`notify::${kebabify(prop)}`, () => callback(lastClient));
- callback(lastClient);
- });
- self.connect("destroy", () => id && lastClient?.disconnect(id));
- callback(lastClient);
-};
-
-const getClassName = ({ beforeSpacer, afterSpacer, first, last }: ClassNameProps) =>
- `${beforeSpacer ? "before-spacer" : ""} ${afterSpacer ? "after-spacer" : ""}` +
- ` ${first ? "first" : ""} ${last ? "last" : ""}`;
-
-const getModule = (module: string) => {
- module = module.toLowerCase();
- if (module === "osicon") return OSIcon;
- if (module === "activewindow") return ActiveWindow;
- if (module === "mediaplaying") return MediaPlaying;
- if (module === "workspaces") return Workspaces;
- if (module === "tray") return Tray;
- if (module === "statusicons") return StatusIcons;
- if (module === "pkgupdates") return PkgUpdates;
- if (module === "notifcount") return NotifCount;
- if (module === "battery") return Battery;
- if (module === "datetime") return DateTime;
- if (module === "power") return Power;
- if (module === "brightnessspacer") return BrightnessSpacer;
- if (module === "volumespacer") return VolumeSpacer;
- return () => null;
-};
-
-const isSpacer = (module?: string) => module?.toLowerCase().endsWith("spacer") ?? false;
-
-const OSIcon = ({ monitor, ...props }: ModuleProps) => (
- <button
- className={`module os-icon ${getClassName(props)}`}
- onClick={(_, event) => event.button === Astal.MouseButton.PRIMARY && switchPane(monitor, "dashboard")}
- >
- {osIcon}
- </button>
-);
-
-const ActiveWindow = ({ monitor, ...props }: ModuleProps) => (
- <box
- vertical={bind(config.vertical)}
- className={`module active-window ${getClassName(props)}`}
- setup={self => {
- const title = Variable("");
- const updateTooltip = (c: AstalHyprland.Client | null) =>
- title.set(c?.class && c?.title ? `${c.class}: ${c.title}` : "");
- hookFocusedClientProp(self, "class", updateTooltip);
- hookFocusedClientProp(self, "title", updateTooltip);
- updateTooltip(hyprland.focusedClient);
-
- const window = setupCustomTooltip(self, bind(title));
- if (window) {
- self.hook(title, (_, v) => !v && window.hide());
- self.hook(window, "map", () => !title.get() && window.hide());
- }
- }}
- >
- <label
- className="icon"
- setup={self =>
- hookFocusedClientProp(self, "class", c => {
- self.label = c?.class ? getAppCategoryIcon(c.class) : "desktop_windows";
- })
- }
- />
- <label
- truncate
- angle={bind(config.vertical).as(v => (v ? 270 : 0))}
- setup={self => {
- const update = () =>
- (self.label = hyprland.focusedClient?.title ? hyprland.focusedClient.title : "Desktop");
- hookFocusedClientProp(self, "title", update);
- self.hook(config.vertical, update);
- }}
- />
- </box>
-);
-
-const MediaPlaying = ({ monitor, ...props }: ModuleProps) => {
- const players = Players.get_default();
- const getLabel = (fallback = "") =>
- players.lastPlayer ? `${players.lastPlayer.title} - ${players.lastPlayer.artist}` : fallback;
- return (
- <button
- onClick={(_, event) => {
- if (event.button === Astal.MouseButton.PRIMARY) switchPane(monitor, "audio");
- else if (event.button === Astal.MouseButton.SECONDARY) players.lastPlayer?.play_pause();
- else if (event.button === Astal.MouseButton.MIDDLE) players.lastPlayer?.raise();
- }}
- setup={self => {
- const label = Variable(getLabel());
- players.hookLastPlayer(self, ["notify::title", "notify::artist"], () => label.set(getLabel()));
- setupCustomTooltip(self, bind(label));
- }}
- >
- <box vertical={bind(config.vertical)} className={`module media-playing ${getClassName(props)}`}>
- <icon
- setup={self =>
- players.hookLastPlayer(self, "notify::identity", () => {
- const icon = `caelestia-${players.lastPlayer?.identity
- .toLowerCase()
- .replaceAll(" ", "-")}-symbolic`;
- self.icon = players.lastPlayer
- ? Astal.Icon.lookup_icon(icon)
- ? icon
- : "caelestia-media-generic-symbolic"
- : "caelestia-media-none-symbolic";
- })
- }
- />
- <label
- truncate
- angle={bind(config.vertical).as(v => (v ? 270 : 0))}
- setup={self => {
- const update = () => (self.label = getLabel("No media"));
- players.hookLastPlayer(self, ["notify::title", "notify::artist"], update);
- self.hook(config.vertical, update);
- }}
- />
- </box>
- </button>
- );
-};
-
-const Workspace = ({ idx }: { idx: number }) => {
- const wsId = Variable.derive([bind(hyprland, "focusedWorkspace"), config.modules.workspaces.shown], (f, s) =>
- f ? Math.floor((f.id - 1) / s) * s + idx : idx
- );
-
- const label = (
- <label
- css={bind(config.modules.workspaces.xalign).as(a => `margin-left: ${a}px; margin-right: ${-a}px;`)}
- label={bind(config.modules.workspaces.labels).as(l => l[idx - 1] ?? String(idx))}
- />
- );
-
- return (
- <button
- halign={Gtk.Align.CENTER}
- valign={Gtk.Align.CENTER}
- onClicked={() => hyprland.dispatch("workspace", String(wsId.get()))}
- setup={self => {
- const updateOccupied = () => {
- const occupied = hyprland.clients.some(c => c.workspace?.id === wsId.get());
- self.toggleClassName("occupied", occupied);
- };
- const updateFocused = () => {
- self.toggleClassName("focused", hyprland.focusedWorkspace?.id === wsId.get());
- updateOccupied();
- };
-
- self.hook(hyprland, "client-added", updateOccupied);
- self.hook(hyprland, "client-moved", updateOccupied);
- self.hook(hyprland, "client-removed", updateOccupied);
- self.hook(hyprland, "notify::focused-workspace", updateFocused);
- updateFocused();
- }}
- onDestroy={() => wsId.drop()}
- >
- <box
- visible={bind(config.modules.workspaces.showLabels)}
- vertical={bind(config.vertical)}
- setup={self => {
- const update = () => {
- if (config.modules.workspaces.showWindows.get()) {
- const clients = hyprland.clients.filter(c => c.workspace?.id === wsId.get());
- self.children = [
- label,
- ...clients.map(c => (
- <label className="icon" label={bind(c, "class").as(getAppCategoryIcon)} />
- )),
- ];
- } else self.children = [label];
- };
- self.hook(wsId, update);
- self.hook(hyprland, "client-added", update);
- self.hook(hyprland, "client-moved", update);
- self.hook(hyprland, "client-removed", update);
- update();
- }}
- />
- </button>
- );
-};
-
-const Workspaces = ({ monitor, ...props }: ModuleProps) => {
- const className = Variable.derive(
- [config.modules.workspaces.shown, config.modules.workspaces.showLabels],
- (s, l) => `module workspaces ${s % 2 === 0 ? "even" : "odd"} ${l ? "labels-shown" : ""} ${getClassName(props)}`
- );
-
- return (
- <eventbox
- onScroll={(_, event) => {
- const activeWs = hyprland.focusedClient?.workspace.name;
- if (activeWs?.startsWith("special:")) hyprland.dispatch("togglespecialworkspace", activeWs.slice(8));
- else if (event.delta_y > 0 || hyprland.focusedWorkspace?.id > 1)
- hyprland.dispatch("workspace", (event.delta_y < 0 ? "-" : "+") + 1);
- }}
- >
- <box vertical={bind(config.vertical)} className={bind(className)} onDestroy={() => className.drop()}>
- {bind(config.modules.workspaces.shown).as(
- n => Array.from({ length: n }).map((_, idx) => <Workspace idx={idx + 1} />) // Start from 1
- )}
- </box>
- </eventbox>
- );
-};
-
-const TrayItem = (item: AstalTray.TrayItem) => (
- <menubutton
- onButtonPressEvent={(_, event) => event.get_button()[1] === Astal.MouseButton.SECONDARY && item.activate(0, 0)}
- usePopover={false}
- direction={bind(config.vertical).as(v => (v ? Gtk.ArrowType.RIGHT : Gtk.ArrowType.DOWN))}
- menuModel={bind(item, "menuModel")}
- actionGroup={bind(item, "actionGroup").as(a => ["dbusmenu", a])}
- setup={self => setupCustomTooltip(self, bind(item, "tooltipMarkup"))}
- >
- <icon halign={Gtk.Align.CENTER} gicon={bind(item, "gicon")} />
- </menubutton>
-);
-
-const Tray = ({ monitor, ...props }: ModuleProps) => (
- <box
- visible={bind(AstalTray.get_default(), "items").as(i => i.length > 0)}
- vertical={bind(config.vertical)}
- className={`module tray ${getClassName(props)}`}
- >
- {bind(AstalTray.get_default(), "items").as(i => i.map(TrayItem))}
- </box>
-);
-
-const Network = ({ monitor }: { monitor: Monitor }) => (
- <button
- onClick={(_, event) => {
- const network = AstalNetwork.get_default();
- if (event.button === Astal.MouseButton.PRIMARY) switchPane(monitor, "connectivity");
- else if (event.button === Astal.MouseButton.SECONDARY) network.wifi.enabled = !network.wifi.enabled;
- else if (event.button === Astal.MouseButton.MIDDLE) {
- if (GLib.find_program_in_path("gnome-control-center"))
- execAsync("app2unit -- gnome-control-center wifi").catch(console.error);
- else {
- network.wifi.scan();
- execAsync(
- "app2unit -- foot -T nmtui -- fish -c 'sleep .1; set -e COLORTERM; TERM=xterm-old nmtui connect'"
- ).catch(() => {}); // Ignore errors
- }
- }
- }}
- setup={self => {
- const network = AstalNetwork.get_default();
- const tooltipText = Variable("");
- const update = () => {
- if (network.primary === AstalNetwork.Primary.WIFI) {
- if (network.wifi.internet === AstalNetwork.Internet.CONNECTED)
- tooltipText.set(`${network.wifi.ssid} | Strength: ${network.wifi.strength}/100`);
- else if (network.wifi.internet === AstalNetwork.Internet.CONNECTING)
- tooltipText.set(`Connecting to ${network.wifi.ssid}`);
- else tooltipText.set("Disconnected");
- } else if (network.primary === AstalNetwork.Primary.WIRED) {
- if (network.wired.internet === AstalNetwork.Internet.CONNECTED)
- tooltipText.set(`Speed: ${network.wired.speed}`);
- else if (network.wired.internet === AstalNetwork.Internet.CONNECTING) tooltipText.set("Connecting");
- else tooltipText.set("Disconnected");
- } else {
- tooltipText.set("Unknown");
- }
- };
- self.hook(network, "notify::primary", update);
- self.hook(network.wifi, "notify::internet", update);
- self.hook(network.wifi, "notify::ssid", update);
- self.hook(network.wifi, "notify::strength", update);
- if (network.wired) {
- self.hook(network.wired, "notify::internet", update);
- self.hook(network.wired, "notify::speed", update);
- }
- update();
- setupCustomTooltip(self, bind(tooltipText));
- }}
- >
- <stack
- transitionType={Gtk.StackTransitionType.SLIDE_UP_DOWN}
- transitionDuration={120}
- shown={bind(AstalNetwork.get_default(), "primary").as(p =>
- p === AstalNetwork.Primary.WIFI ? "wifi" : "wired"
- )}
- >
- <stack
- name="wifi"
- transitionType={Gtk.StackTransitionType.SLIDE_UP_DOWN}
- transitionDuration={120}
- setup={self => {
- const network = AstalNetwork.get_default();
- const update = () => {
- if (network.wifi.internet === AstalNetwork.Internet.CONNECTED)
- self.shown = String(Math.ceil(network.wifi.strength / 25));
- else if (network.wifi.internet === AstalNetwork.Internet.CONNECTING) self.shown = "connecting";
- else self.shown = "disconnected";
- };
- self.hook(network.wifi, "notify::internet", update);
- self.hook(network.wifi, "notify::strength", update);
- update();
- }}
- >
- <label className="icon" label="wifi_off" name="disconnected" />
- <label className="icon" label="settings_ethernet" name="connecting" />
- <label className="icon" label="signal_wifi_0_bar" name="0" />
- <label className="icon" label="network_wifi_1_bar" name="1" />
- <label className="icon" label="network_wifi_2_bar" name="2" />
- <label className="icon" label="network_wifi_3_bar" name="3" />
- <label className="icon" label="signal_wifi_4_bar" name="4" />
- </stack>
- <stack
- name="wired"
- transitionType={Gtk.StackTransitionType.SLIDE_UP_DOWN}
- transitionDuration={120}
- setup={self => {
- const network = AstalNetwork.get_default();
- const update = () => {
- if (network.primary !== AstalNetwork.Primary.WIRED) return;
-
- if (network.wired.internet === AstalNetwork.Internet.CONNECTED) self.shown = "connected";
- else if (network.wired.internet === AstalNetwork.Internet.CONNECTING) self.shown = "connecting";
- else self.shown = "disconnected";
- };
- self.hook(network, "notify::primary", update);
- if (network.wired) self.hook(network.wired, "notify::internet", update);
- update();
- }}
- >
- <label className="icon" label="wifi_off" name="disconnected" />
- <label className="icon" label="settings_ethernet" name="connecting" />
- <label className="icon" label="lan" name="connected" />
- </stack>
- </stack>
- </button>
-);
-
-const BluetoothDevice = ({ monitor, device }: { monitor: Monitor; device: AstalBluetooth.Device }) => (
- <button
- visible={bind(device, "connected")}
- onClick={(_, event) => {
- if (event.button === Astal.MouseButton.PRIMARY) switchPane(monitor, "connectivity");
- else if (event.button === Astal.MouseButton.SECONDARY)
- device.disconnect_device((_, res) => device.disconnect_device_finish(res));
- else if (event.button === Astal.MouseButton.MIDDLE)
- execAsync("app2unit -- blueman-manager").catch(console.error);
- }}
- setup={self => setupCustomTooltip(self, bind(device, "alias"))}
- >
- <icon
- icon={bind(device, "icon").as(i =>
- Astal.Icon.lookup_icon(`${i}-symbolic`) ? `${i}-symbolic` : "caelestia-bluetooth-device-symbolic"
- )}
- />
- </button>
-);
-
-const Bluetooth = ({ monitor }: { monitor: Monitor }) => (
- <box vertical={bind(config.vertical)} className="bluetooth">
- <button
- onClick={(_, event) => {
- if (event.button === Astal.MouseButton.PRIMARY) switchPane(monitor, "connectivity");
- else if (event.button === Astal.MouseButton.SECONDARY) AstalBluetooth.get_default().toggle();
- else if (event.button === Astal.MouseButton.MIDDLE)
- execAsync("app2unit -- blueman-manager").catch(console.error);
- }}
- setup={self => {
- const bluetooth = AstalBluetooth.get_default();
- const tooltipText = Variable("");
- const update = () => {
- const devices = bluetooth.get_devices().filter(d => d.connected);
- tooltipText.set(
- devices.length > 0
- ? `Connected devices: ${devices.map(d => d.alias).join(", ")}`
- : "No connected devices"
- );
- };
- const hookDevice = (device: AstalBluetooth.Device) => {
- self.hook(device, "notify::connected", update);
- self.hook(device, "notify::alias", update);
- };
- bluetooth.get_devices().forEach(hookDevice);
- self.hook(bluetooth, "device-added", (_, device) => {
- hookDevice(device);
- update();
- });
- update();
- setupCustomTooltip(self, bind(tooltipText));
- }}
- >
- <stack
- transitionType={Gtk.StackTransitionType.SLIDE_UP_DOWN}
- transitionDuration={120}
- shown={bind(AstalBluetooth.get_default(), "isPowered").as(p => (p ? "enabled" : "disabled"))}
- >
- <label className="icon" label="bluetooth" name="enabled" />
- <label className="icon" label="bluetooth_disabled" name="disabled" />
- </stack>
- </button>
- {bind(AstalBluetooth.get_default(), "devices").as(d =>
- d.map(d => <BluetoothDevice monitor={monitor} device={d} />)
- )}
- </box>
-);
-
-const StatusIcons = ({ monitor, ...props }: ModuleProps) => (
- <box vertical={bind(config.vertical)} className={`module status-icons ${getClassName(props)}`}>
- <Network monitor={monitor} />
- <Bluetooth monitor={monitor} />
- </box>
-);
-
-const PkgUpdates = ({ monitor, ...props }: ModuleProps) => (
- <button
- onClick={(_, event) => event.button === Astal.MouseButton.PRIMARY && switchPane(monitor, "packages")}
- setup={self =>
- setupCustomTooltip(
- self,
- bind(Updates.get_default(), "numUpdates").as(n => `${n} update${n === 1 ? "" : "s"} available`)
- )
- }
- >
- <box vertical={bind(config.vertical)} className={`module pkg-updates ${getClassName(props)}`}>
- <label className="icon" label="download" />
- <label label={bind(Updates.get_default(), "numUpdates").as(String)} />
- </box>
- </button>
-);
-
-const NotifCount = ({ monitor, ...props }: ModuleProps) => (
- <button
- onClick={(_, event) => event.button === Astal.MouseButton.PRIMARY && switchPane(monitor, "alerts")}
- setup={self =>
- setupCustomTooltip(
- self,
- bind(AstalNotifd.get_default(), "notifications").as(
- n => `${n.length} notification${n.length === 1 ? "" : "s"}`
- )
- )
- }
- >
- <box vertical={bind(config.vertical)} className={`module notif-count ${getClassName(props)}`}>
- <label
- className="icon"
- label={bind(AstalNotifd.get_default(), "dontDisturb").as(d => (d ? "notifications_off" : "info"))}
- />
- <revealer
- transitionType={bind(config.vertical).as(v =>
- v ? Gtk.RevealerTransitionType.SLIDE_DOWN : Gtk.RevealerTransitionType.SLIDE_RIGHT
- )}
- transitionDuration={120}
- revealChild={bind(AstalNotifd.get_default(), "dontDisturb").as(d => !d)}
- >
- <label label={bind(AstalNotifd.get_default(), "notifications").as(n => String(n.length))} />
- </revealer>
- </box>
- </button>
-);
-
-const Battery = ({ monitor, ...props }: ModuleProps) => {
- const className = Variable.derive(
- [bind(AstalBattery.get_default(), "percentage"), bind(AstalBattery.get_default(), "charging")],
- (p, c) => `module battery ${c ? "charging" : p < 0.2 ? "low" : ""} ${getClassName(props)}`
- );
- const tooltip = Variable.derive(
- [bind(AstalBattery.get_default(), "timeToEmpty"), bind(AstalBattery.get_default(), "timeToFull")],
- (e, f) => (f > 0 ? `${formatSeconds(f)} until full` : `${formatSeconds(e)} remaining`)
- );
-
- return (
- <box
- visible={bind(AstalBattery.get_default(), "isBattery")}
- vertical={bind(config.vertical)}
- className={bind(className)}
- setup={self => setupCustomTooltip(self, bind(tooltip))}
- onDestroy={() => {
- className.drop();
- tooltip.drop();
- }}
- >
- <label className="icon" label={bind(AstalBattery.get_default(), "percentage").as(getBatteryIcon)} />
- <label label={bind(AstalBattery.get_default(), "percentage").as(p => `${Math.round(p * 100)}%`)} />
- </box>
- );
-};
-
-const DateTimeHoriz = (props: ClassNameProps) => (
- <box className={`module date-time ${getClassName(props)}`}>
- <label className="icon" label="calendar_month" />
- <label
- setup={self => {
- const time = bindCurrentTime(bind(config.modules.dateTime.format), undefined, self);
- self.label = time.get();
- self.hook(time, (_, t) => (self.label = t));
- }}
- />
- </box>
-);
-
-const DateTimeVertical = (props: ClassNameProps) => (
- <box vertical className={`module date-time ${getClassName(props)}`}>
- <label className="icon" label="calendar_month" />
- <label label={bindCurrentTime("%H")} />
- <label label={bindCurrentTime("%M")} />
- </box>
-);
-
-const DateTime = ({ monitor, ...props }: ModuleProps) => (
- <button
- onClick={(_, event) => event.button === Astal.MouseButton.PRIMARY && switchPane(monitor, "time")}
- setup={self =>
- setupCustomTooltip(self, bindCurrentTime(bind(config.modules.dateTime.detailedFormat), undefined, self))
- }
- >
- {bind(config.vertical).as(v => (v ? <DateTimeVertical {...props} /> : <DateTimeHoriz {...props} />))}
- </button>
-);
-
-const Power = ({ monitor, ...props }: ModuleProps) => (
- <button
- className={`module power ${getClassName(props)}`}
- label="power_settings_new"
- onClick={(_, event) => event.button === Astal.MouseButton.PRIMARY && App.toggle_window("session")}
- />
-);
-
-const Spacer = ({ onScroll }: { onScroll: (self: Widget.EventBox, event: Astal.ScrollEvent) => void }) => (
- <eventbox onScroll={onScroll}>
- <box vertical={bind(config.vertical)}>
- <ScreenCorner place="topleft" />
- <box expand />
- <ScreenCorner place={bind(config.vertical).as(v => (v ? "bottomleft" : "topright"))} />
- </box>
- </eventbox>
-);
-
-const BrightnessSpacer = ({ monitor }: { monitor: Monitor }) => (
- <Spacer onScroll={(_, event) => (event.delta_y > 0 ? (monitor.brightness -= 0.1) : (monitor.brightness += 0.1))} />
-);
-
-const VolumeSpacer = () => (
- <Spacer
- onScroll={(_, event) => {
- const speaker = AstalWp.get_default()?.audio.defaultSpeaker;
- if (!speaker) return console.error("Unable to connect to WirePlumber.");
- speaker.mute = false;
- if (event.delta_y > 0) speaker.volume -= 0.1;
- else speaker.volume += 0.1;
- }}
- />
-);
-
-const Bar = ({ monitor, layout }: { monitor: Monitor; layout: string }) => {
- const className = Variable.derive(
- [bind(config.vertical), bind(config.style)],
- (v, s) => `bar ${v ? "vertical" : " horizontal"} ${s}`
- );
- const modules =
- layout === "centerbox"
- ? Variable.derive(Object.values(config.layout.centerbox))
- : bind(config.layout.flowbox).as(m => [m]);
-
- const Layout = layout === "centerbox" ? Widget.CenterBox : Widget.Box;
- return (
- <Layout
- vertical={bind(config.vertical)}
- className={bind(className)}
- onDestroy={() => {
- className.drop();
- if (modules instanceof Variable) modules.drop();
- }}
- >
- {bind(modules).as(modules =>
- modules.map((m, i) => (
- <box vertical={bind(config.vertical)}>
- {m.map((n, j) => {
- let beforeSpacer = false;
- if (j < m.length - 1) beforeSpacer = isSpacer(m[j + 1]);
- else if (i < modules.length - 1) beforeSpacer = isSpacer(modules[i + 1][0]);
- let afterSpacer = false;
- if (j > 0) afterSpacer = isSpacer(m[j - 1]);
- else if (i > 0) afterSpacer = isSpacer(modules[i - 1].at(-1));
- const M = getModule(n);
- return (
- <M
- monitor={monitor}
- beforeSpacer={beforeSpacer}
- afterSpacer={afterSpacer}
- first={i === 0 && j === 0}
- last={i === modules.length - 1 && j === m.length - 1}
- />
- );
- })}
- </box>
- ))
- )}
- </Layout>
- );
-};
-
-export default ({ monitor }: { monitor: Monitor }) => (
- <window
- namespace="caelestia-bar"
- monitor={monitor.id}
- anchor={bind(config.vertical).as(
- v =>
- Astal.WindowAnchor.TOP |
- Astal.WindowAnchor.LEFT |
- (v ? Astal.WindowAnchor.BOTTOM : Astal.WindowAnchor.RIGHT)
- )}
- exclusivity={Astal.Exclusivity.EXCLUSIVE}
- >
- <overlay
- passThrough
- overlays={[
- <ScreenCorner visible={bind(config.style).as(s => s !== "embedded")} place="topleft" />,
- <ScreenCorner
- visible={bind(config.style).as(s => s !== "embedded")}
- halign={bind(config.vertical).as(v => (v ? undefined : Gtk.Align.END))}
- valign={bind(config.vertical).as(v => (v ? Gtk.Align.END : undefined))}
- place={bind(config.vertical).as(v => (v ? "bottomleft" : "topright"))}
- />,
- ]}
- >
- {bind(config.layout.type).as(l => (
- <Bar monitor={monitor} layout={l} />
- ))}
- </overlay>
- </window>
-);