import { App, Astal, Gtk } from "astal/gtk4"; import { bind, execAsync, Gio } from "astal"; import { hideWindow } from "@/lib/utils"; import Bluetooth from "gi://AstalBluetooth"; import Hyprland from "gi://AstalHyprland"; function DeviceMenu({ device, child }: { device: Bluetooth.Device, child?: JSX.Element }) { const menu = Gio.Menu.new(); const copy_mac = Gio.MenuItem.new("Copy MAC address", "bt.copy_mac"); const toggle_state = Gio.MenuItem.new(device.get_connected() ? "Disconnect" : "Connect", "bt.toggle_state"); const action_group = Gio.SimpleActionGroup.new(); const copy_mac_action = Gio.SimpleAction.new("copy_mac", null); copy_mac_action.connect("activate", () => execAsync(["wl-copy", device.address])); const toggle_state_action = Gio.SimpleAction.new("toggle_state", null); toggle_state_action.connect("activate", async () => { if (device.connected) await device.disconnect_device() else await device.connect_device() }) menu.insert_item(1, copy_mac); menu.insert_item(2, toggle_state); action_group.insert(copy_mac_action); action_group.insert(toggle_state_action); return <menubutton menuModel={menu} setup={self => self.insert_action_group("bt", action_group)} > {child} <popover> <label label={"Copy MAC address"} /> <label label={"Toggle state"} /> </popover> </menubutton>; }; export default function BluetoothWindow(_monitor_id: number) { const CENTER = Gtk.Align.CENTER; const bt = Bluetooth.get_default(); const hypr = Hyprland.get_default(); const devices = bind(bt, "devices"); return <window name={"qs_bluetooth"} cssClasses={["qs_bluetooth"]} monitor={bind(hypr, "focusedMonitor").as(monitor => monitor.id)} exclusivity={Astal.Exclusivity.IGNORE} keymode={Astal.Keymode.EXCLUSIVE} application={App} onKeyPressed={hideWindow} > <box vertical halign={CENTER} cssClasses={["inner"]} spacing={5}> {devices.as(devices => devices.map(device => <DeviceMenu device={device}> <box cssClasses={["device", "small-padding"].concat(device.connected ? ["active"] : [])} spacing={3}> <image iconName={device.icon} /> <label>{device.alias}</label> </box> </DeviceMenu> ))} </box> </window> }