188 lines
6.6 KiB
TypeScript
188 lines
6.6 KiB
TypeScript
import { bind, readFile, writeFile } from "astal";
|
|
import { Gtk } from "astal/gtk4";
|
|
import AstalBluetooth from "gi://AstalBluetooth";
|
|
import BTDevice from "./Device";
|
|
const ALIGN = Gtk.Align;
|
|
|
|
const bt = AstalBluetooth.get_default();
|
|
|
|
const BluetoothModule = () => {
|
|
return (
|
|
<box>
|
|
<button
|
|
cssClasses={bind(bt.adapter, "powered").as(powered =>
|
|
powered
|
|
? ["toggle-button", "toggle-on"]
|
|
: ["toggle-button"],
|
|
)}
|
|
onClicked={() =>
|
|
bt.adapter.set_powered(!bt.adapter.get_powered())
|
|
}
|
|
child={
|
|
<box vertical>
|
|
<label
|
|
cssClasses={["title-2"]}
|
|
label={"Bluetooth"}
|
|
halign={ALIGN.CENTER}
|
|
valign={ALIGN.CENTER}
|
|
></label>
|
|
<box halign={ALIGN.CENTER} valign={ALIGN.CENTER}>
|
|
<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={["actions-button"]}
|
|
visible={bind(bt.adapter, "powered")}
|
|
child={
|
|
<box>
|
|
<image iconName={"arrow-right-symbolic"}></image>
|
|
{picker}
|
|
</box>
|
|
}
|
|
tooltipText={"View available devices"}
|
|
onClicked={() => openBTPicker()}
|
|
></button>
|
|
</box>
|
|
);
|
|
};
|
|
|
|
const openBTPicker = () => {
|
|
picker.popup();
|
|
try {
|
|
bt.adapter.start_discovery();
|
|
} catch (_) {}
|
|
};
|
|
|
|
const BluetoothPickerList = () => {
|
|
let btEnableState = readFile(`${DATADIR}./btconf`) === "true" ? true : false;
|
|
bt.adapter.set_powered(btEnableState);
|
|
|
|
const updateState = () => {
|
|
btEnableState = !btEnableState;
|
|
writeFile("./btconf", "" + btEnableState);
|
|
};
|
|
|
|
return (
|
|
<box
|
|
vertical
|
|
onDestroy={() => bt.adapter.stop_discovery()}
|
|
cssClasses={["popover-box"]}
|
|
>
|
|
<label cssClasses={["title"]} label={"Bluetooth"}></label>
|
|
<Gtk.Separator marginTop={3} marginBottom={5}></Gtk.Separator>
|
|
<centerbox
|
|
startWidget={<label label={"Turn on at startup"}></label>}
|
|
endWidget={
|
|
<switch
|
|
valign={ALIGN.END}
|
|
halign={ALIGN.END}
|
|
active={btEnableState}
|
|
onButtonPressed={() => updateState()}
|
|
></switch>
|
|
}
|
|
></centerbox>
|
|
<label
|
|
marginTop={10}
|
|
label={"Connected & Trusted devices"}
|
|
cssClasses={["title-2"]}
|
|
></label>
|
|
<Gtk.Separator marginTop={3} marginBottom={5}></Gtk.Separator>
|
|
<box vertical cssClasses={["devices-list"]}>
|
|
{bind(bt, "devices").as(devices => {
|
|
return devices
|
|
.filter(device => {
|
|
if (device.get_connected() || device.get_paired()) {
|
|
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() || device.get_paired()) {
|
|
return device;
|
|
}
|
|
}).length === 0
|
|
);
|
|
})}
|
|
label={"No connected / trusted 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() && !data.get_paired()) {
|
|
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() &&
|
|
!device.get_paired()
|
|
) {
|
|
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,
|
|
};
|