import { Gtk } from "ags/gtk4"; import { Page, PageButton } from "../Page"; import { tr } from "../../../../i18n/intl"; import { Windows } from "../../../../windows"; import { Notifications } from "../../../../modules/notifications"; import { execApp } from "../../../../modules/apps"; import { createBinding, createComputed, For, With } from "ags"; import { variableToBoolean } from "../../../../modules/utils"; import { Bluetooth } from "../../../../modules/bluetooth"; import AstalNotifd from "gi://AstalNotifd"; import AstalBluetooth from "gi://AstalBluetooth"; import Adw from "gi://Adw?version=1"; import Gio from "gi://Gio?version=2.0"; export const BluetoothPage = adapter ? [{ icon: createBinding(adapter, "discovering") .as(discovering => !discovering ? "arrow-circular-top-right-symbolic" : "media-playback-stop-symbolic" ), tooltipText: createBinding(adapter, "discovering") .as((discovering) => !discovering ? tr("control_center.pages.bluetooth.start_discovering") : tr("control_center.pages.bluetooth.stop_discovering")), actionClicked: () => { if(adapter.discovering) { adapter.stop_discovery(); return; } adapter.start_discovery(); } }]: [])} actionClosed={() => Bluetooth.getDefault().adapter?.discovering && Bluetooth.getDefault().adapter?.stop_discovery()} bottomButtons={[{ title: tr("control_center.pages.more_settings"), actionClicked: () => { Windows.getDefault().close("control-center"); execApp("overskride", "[float; animation slide right]"); } }]} content={() => { const adapters = createBinding(AstalBluetooth.get_default(), "adapters"); const devices = createBinding(AstalBluetooth.get_default(), "devices"); const knownDevices = devices.as(devs => devs.filter(dev => dev.trusted || dev.paired || dev.connected ).sort(dev => dev.connected ? 1 : 0)); const discoveredDevices = devices.as(devs => devs.filter(dev => !dev.trusted && !dev.paired && !dev.connected) ); return [ adptrs.length > 1) } spacing={2} orientation={Gtk.Orientation.VERTICAL}> adpts.length > 1)}> {(hasMoreAdapters: boolean) => hasMoreAdapters && {(adapter: AstalBluetooth.Adapter) => { const isSelected = createBinding(Bluetooth.getDefault(), "adapter").as(a => adapter.address === a?.address); return is ? "selected" : "")} title={adapter.alias ?? "Adapter"} icon={"bluetooth-active-symbolic"} description={createBinding(adapter, "address")} actionClicked={() => { if(adapter.address !== Bluetooth.getDefault().adapter?.address) Bluetooth.getDefault().adapter = adapter; }} endWidget={ } />; }} } , {(dev: AstalBluetooth.Device) => } {(dev: AstalBluetooth.Device) => } ]; }} /> as Page; function DeviceWidget({ device }: { device: AstalBluetooth.Device }): Gtk.Widget { const pair = async () => { if(device.paired) return; device.pair(); device.set_trusted(true); }; return conn ? "selected" : "")} title={ createBinding(device, "alias").as(alias => alias ?? "Unknown Device")} icon={createBinding(device, "icon").as(ico => ico ?? "bluetooth-active-symbolic")} tooltipText={ createBinding(device, "connected").as(connected => !connected ? tr("connect") : "") } actionClicked={() => { if(device.connected) return; pair().then(() => { device.connect_device((_, res) => { // get error try { device.connect_device_finish(res); } catch(e: any) { Notifications.getDefault().sendNotification({ appName: "bluetooth", summary: "Connection Error", body: `An error occurred while attempting to connect to ${ device.alias ?? device.name}: ${(e as Gio.IOErrorEnum).message}` }); } }); }).catch((err: Gio.IOErrorEnum) => Notifications.getDefault().sendNotification({ appName: "bluetooth", summary: "Pairing Error", body: `Couldn't pair with ${device.alias ?? device.name}: ${err.message}`, urgency: AstalNotifd.Urgency.NORMAL }) ); }} endWidget={ connected && (batt > -1)) } spacing={4}> `${Math.floor(batt * 100)}%`) } visible={createBinding(device, "connected")} /> `battery-level-${Math.floor(batt * 100)}-symbolic`) } css={"font-size: 16px; margin-left: 6px;"} /> } extraButtons={ {([connected, trusted]: [boolean, boolean]) => { { if(!connected) { Bluetooth.getDefault().adapter?.remove_device(device); return; } device.disconnect_device(null); }} />} device.set_trusted(!trusted)} /> } } /> as Gtk.Widget; }