This commit is contained in:
Benjamin Palko 2025-06-13 17:21:59 -04:00
parent 23f28f03fe
commit e62a7afa60
5 changed files with 141 additions and 66 deletions

View file

@ -1,15 +1,16 @@
import { App, Astal, Gdk, Gtk } from "astal/gtk4"; import { App, Astal, Gdk, Gtk } from "astal/gtk4";
import Bluetooth from "./Bluetooth";
import Calendar from "./Calendar"; import Calendar from "./Calendar";
import Hyprland from "./Hyprland"; import Hyprland from "./Hyprland";
import Workspaces from "./Hyprland/workspaces";
import Internet from "./Internet"; import Internet from "./Internet";
import Memory from "./Memory";
import Mpris from "./Mpris"; import Mpris from "./Mpris";
import OS from "./OS"; import OS from "./OS";
import Pywal from "./Pywal"; import Pywal from "./Pywal";
import Tray from "./Tray";
import SwayNC from "./SwayNC"; import SwayNC from "./SwayNC";
import Tray from "./Tray";
import WirePlumber from "./WirePlumber"; import WirePlumber from "./WirePlumber";
import Memory from "./Memory";
import Workspaces from "./Hyprland/workspaces";
export default function Bar(gdkmonitor: Gdk.Monitor) { export default function Bar(gdkmonitor: Gdk.Monitor) {
const { TOP, LEFT, RIGHT } = Astal.WindowAnchor; const { TOP, LEFT, RIGHT } = Astal.WindowAnchor;
@ -37,6 +38,7 @@ export default function Bar(gdkmonitor: Gdk.Monitor) {
<Pywal /> <Pywal />
<WirePlumber /> <WirePlumber />
<Internet /> <Internet />
<Bluetooth />
<Memory /> <Memory />
<Calendar /> <Calendar />
<SwayNC /> <SwayNC />

48
widget/Bluetooth.tsx Normal file
View file

@ -0,0 +1,48 @@
import { Binding } from "astal";
import { bind, derive } from "astal";
import AstalBluetooth from "gi://AstalBluetooth";
const DeviceList = function ({
devices,
}: {
devices: Binding<AstalBluetooth.Device[]>;
}) {
return (
<box vertical>
{devices.as((devices) => {
return devices.map((device) => {
const name = bind(device, "name");
const connected = bind(device, "connected");
return (
<button
label={bind(
derive(
[name, connected],
(name, connected) => `${connected ? "󰂱" : ""} ${name}`,
),
)}
/>
);
});
})}
</box>
);
};
const Bluetooth = function () {
const bluetooth = AstalBluetooth.get_default();
const devices = bind(bluetooth, "devices");
return (
<menubutton>
<label label={"󰂯"} />
<popover>
<DeviceList devices={devices} />
</popover>
</menubutton>
);
};
export default Bluetooth;

View file

@ -4,81 +4,81 @@ import AstalMpris from "gi://AstalMpris";
import { Mathf } from "../util/Mathf"; import { Mathf } from "../util/Mathf";
function IntegerToMinuteSeconds(value: number) { function IntegerToMinuteSeconds(value: number) {
const minutes = Math.floor(value / 60); const minutes = Math.floor(value / 60);
const seconds = Math.floor(value - minutes * 60); const seconds = Math.floor(value - minutes * 60);
return `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}`; return `${String(minutes).padStart(2, "0")}:${String(seconds).padStart(2, "0")}`;
} }
function FormatLabel(player: { function FormatLabel(player: {
title: string; title: string;
artist: string; artist: string;
position: number; position: number;
length: number; length: number;
status: AstalMpris.PlaybackStatus; status: AstalMpris.PlaybackStatus;
}) { }) {
return `${player.status === AstalMpris.PlaybackStatus.PLAYING ? "" : ""} ${player.title} - ${player.artist} [${IntegerToMinuteSeconds(player.position)}/${IntegerToMinuteSeconds(player.length)}]`; return `${player.status === AstalMpris.PlaybackStatus.PLAYING ? "" : ""} ${player.title} - ${player.artist} [${IntegerToMinuteSeconds(player.position)}/${IntegerToMinuteSeconds(player.length)}]`;
} }
const Mpris = function () { const Mpris = function () {
const mpris = AstalMpris.get_default(); const mpris = AstalMpris.get_default();
const players = bind(mpris, "players"); const players = bind(mpris, "players");
const activeIndex = Variable(0); const activeIndex = Variable(0);
bind( bind(
derive([players, activeIndex], (players, index) => players[index]), derive([players, activeIndex], (players, index) => players[index]),
).subscribe((value) => print(value.title)); ).subscribe((value) => print(value.title));
return ( return (
<box> <box>
{bind( {bind(
derive([players, activeIndex], (players, index) => { derive([players, activeIndex], (players, index) => {
const activePlayer = players[index]; const activePlayer = players[index];
if (!activePlayer) { if (!activePlayer) {
return <></>; return <></>;
} }
return ( return (
<button <button
cursor={Gdk.Cursor.new_from_name("pointer", null)} cursor={Gdk.Cursor.new_from_name("pointer", null)}
onClicked={() => onClicked={() =>
activePlayer.playbackStatus === activePlayer.playbackStatus ===
AstalMpris.PlaybackStatus.PLAYING AstalMpris.PlaybackStatus.PLAYING
? activePlayer.pause() ? activePlayer.pause()
: activePlayer.play() : activePlayer.play()
} }
onScroll={(_, __, dy) => { onScroll={(_, __, dy) => {
activeIndex.set( activeIndex.set(
Mathf.clamp( Mathf.clamp(
activeIndex.get() - Mathf.sign(dy), activeIndex.get() - Mathf.sign(dy),
0, 0,
players.length - 1, players.length - 1,
), ),
); );
}} }}
> >
<label <label
label={bind( label={bind(
derive( derive(
[ [
bind(activePlayer, "title"), bind(activePlayer, "title"),
bind(activePlayer, "artist"), bind(activePlayer, "artist"),
bind(activePlayer, "position"), bind(activePlayer, "position"),
bind(activePlayer, "length"), bind(activePlayer, "length"),
bind(activePlayer, "playback_status"), bind(activePlayer, "playback_status"),
], ],
(title, artist, position, length, status) => (title, artist, position, length, status) =>
FormatLabel({ title, artist, position, length, status }), FormatLabel({ title, artist, position, length, status }),
), ),
)} )}
/> />
</button> </button>
); );
}), }),
)} )}
</box> </box>
); );
}; };
export default Mpris; export default Mpris;

14
widget/Notifications.tsx Normal file
View file

@ -0,0 +1,14 @@
import { Gdk, Gtk } from "astal/gtk4";
const Notifications = function () {
return (
<menubutton hexpand halign={Gtk.Align.END}>
<label cursor={Gdk.Cursor.new_from_name("pointer", null)} label={""} />
<popover>
<Gtk.Grid></Gtk.Grid>
</popover>
</menubutton>
);
};
export default Notifications;

View file

@ -2,6 +2,16 @@ import { bind } from "astal";
import { Gdk } from "astal/gtk4"; import { Gdk } from "astal/gtk4";
import AstalTray from "gi://AstalTray"; import AstalTray from "gi://AstalTray";
const TrayItemPopover = function ({ item }: { item: AstalTray.TrayItem }) {
const actionGroup = bind(item, "actionGroup");
return (
<popover>
<box>{actionGroup.get()}</box>
</popover>
);
};
const Tray = function () { const Tray = function () {
const tray = AstalTray.get_default(); const tray = AstalTray.get_default();
@ -19,6 +29,7 @@ const Tray = function () {
(iconName) => iconName || "NONE", (iconName) => iconName || "NONE",
)} )}
/> />
<TrayItemPopover item={item} />
</menubutton> </menubutton>
); );
}), }),