154 lines
5.2 KiB
TypeScript
154 lines
5.2 KiB
TypeScript
import { bind } from "astal";
|
|
import { Gtk } from "astal/gtk4";
|
|
import AstalBluetooth from "gi://AstalBluetooth";
|
|
import BTDevice from "./Device";
|
|
|
|
const bt = AstalBluetooth.get_default();
|
|
|
|
const BluetoothModule = () => {
|
|
return (
|
|
<box>
|
|
<button
|
|
cssClasses={bind(bt.adapter, "powered").as(powered =>
|
|
powered
|
|
? ["bt-toggle-button", "bt-on"]
|
|
: ["bt-toggle-button"],
|
|
)}
|
|
onClicked={() =>
|
|
bt.adapter.set_powered(!bt.adapter.get_powered())
|
|
}
|
|
child={
|
|
<box vertical>
|
|
<label
|
|
cssClasses={["button-title"]}
|
|
label={"Bluetooth"}
|
|
></label>
|
|
<box>
|
|
<label
|
|
visible={bind(bt.adapter, "powered").as(
|
|
p => !p,
|
|
)}
|
|
label="Disabled"
|
|
></label>
|
|
<label
|
|
visible={bind(bt.adapter, "powered")}
|
|
label={bind(bt, "devices").as(devices => {
|
|
let count = 0;
|
|
devices.forEach(device => {
|
|
if (device.connected) {
|
|
count++;
|
|
}
|
|
});
|
|
return `On (${count} ${count === 1 ? "client" : "clients"} connected)`;
|
|
})}
|
|
></label>
|
|
</box>
|
|
<label></label>
|
|
</box>
|
|
}
|
|
></button>
|
|
<button
|
|
cssClasses={["bt-devices-button"]}
|
|
visible={bind(bt.adapter, "powered")}
|
|
child={
|
|
<box>
|
|
<image iconName={"arrow-right-symbolic"}></image>
|
|
{picker}
|
|
</box>
|
|
}
|
|
onClicked={() => openBTPicker()}
|
|
></button>
|
|
</box>
|
|
);
|
|
};
|
|
|
|
const openBTPicker = () => {
|
|
picker.popup();
|
|
try {
|
|
bt.adapter.start_discovery();
|
|
} catch (_) {}
|
|
};
|
|
|
|
const BluetoothPickerList = () => {
|
|
return (
|
|
<box vertical onDestroy={() => bt.adapter.stop_discovery()}>
|
|
<label label={"Connected devices"} cssClasses={["title-2"]}></label>
|
|
<Gtk.Separator marginTop={3} marginBottom={5}></Gtk.Separator>
|
|
<box vertical cssClasses={["bt-conn-list"]}>
|
|
{bind(bt, "devices").as(devices => {
|
|
return devices
|
|
.filter(device => {
|
|
if (device.get_connected()) {
|
|
return device;
|
|
}
|
|
})
|
|
.map(device => {
|
|
return <BTDevice device={device}></BTDevice>;
|
|
});
|
|
})}
|
|
</box>
|
|
<label
|
|
visible={bind(bt, "devices").as(devices => {
|
|
return (
|
|
devices.filter(device => {
|
|
if (device.get_connected()) {
|
|
return device;
|
|
}
|
|
}).length === 0
|
|
);
|
|
})}
|
|
label={"No connected devices"}
|
|
cssClasses={["bt-no-found", "bt-conn-list"]}
|
|
></label>
|
|
<label
|
|
label={"Discovered bluetooth devices"}
|
|
cssClasses={["title-2"]}
|
|
></label>
|
|
<Gtk.Separator marginBottom={5} marginTop={3}></Gtk.Separator>
|
|
<box vertical>
|
|
{bind(bt, "devices").as(devices => {
|
|
return devices
|
|
.filter(data => {
|
|
if (!data.get_connected()) {
|
|
return data;
|
|
}
|
|
})
|
|
.map(device => {
|
|
return <BTDevice device={device}></BTDevice>;
|
|
});
|
|
})}
|
|
</box>
|
|
<label
|
|
visible={bind(bt, "devices").as(devices => {
|
|
return (
|
|
devices.filter(device => {
|
|
if (!device.get_connected()) {
|
|
return device;
|
|
}
|
|
}).length === 0
|
|
);
|
|
})}
|
|
label={"No discovered devices"}
|
|
cssClasses={["bt-no-found"]}
|
|
></label>
|
|
</box>
|
|
);
|
|
};
|
|
|
|
|
|
|
|
const BluetoothPicker = () => {
|
|
const popover = new Gtk.Popover();
|
|
|
|
popover.set_child(BluetoothPickerList());
|
|
popover.connect( 'closed', () => bt.adapter.stop_discovery() );
|
|
|
|
return popover;
|
|
};
|
|
|
|
const picker = BluetoothPicker();
|
|
|
|
export default {
|
|
BluetoothModule,
|
|
};
|