ags/widget/quick_settings/bluetooth.tsx

74 lines
2.6 KiB
TypeScript
Raw Normal View History

2025-02-06 12:05:55 +01:00
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");
const connectedDevice = devices.as(devices => devices?.find(device => device.connected));
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>
}