[AGS] Bar: BT, Audio, SysInfo, Brightness
This commit is contained in:
@@ -0,0 +1,153 @@
|
||||
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,
|
||||
};
|
||||
|
@@ -0,0 +1,52 @@
|
||||
import { bind } from "astal";
|
||||
import AstalBluetooth from "gi://AstalBluetooth";
|
||||
|
||||
|
||||
const BTDevice = ({ device }: { device: AstalBluetooth.Device }) => {
|
||||
return (
|
||||
<button
|
||||
visible={bind(device, "name").as(n => n !== null)}
|
||||
child={
|
||||
<centerbox
|
||||
startWidget={
|
||||
<box>
|
||||
<image iconName={"chronometer-reset"} visible={bind( device, 'connecting' )}></image>
|
||||
<image
|
||||
iconName={bind(device, "icon")}
|
||||
marginEnd={3}
|
||||
></image>
|
||||
</box>
|
||||
}
|
||||
centerWidget={
|
||||
<label
|
||||
label={bind(device, "name").as(n => n ?? "No name")}
|
||||
marginEnd={5}
|
||||
></label>
|
||||
}
|
||||
endWidget={
|
||||
<box>
|
||||
<label
|
||||
label={bind(device, "batteryPercentage").as(
|
||||
bat => (bat >= 0 ? bat + "%" : "?%"),
|
||||
)}
|
||||
marginEnd={3}
|
||||
></label>
|
||||
<image
|
||||
iconName={bind(device, "trusted").as(v =>
|
||||
v ? "checkbox" : "paint-unknown-symbolic",
|
||||
)}
|
||||
></image>
|
||||
</box>
|
||||
}
|
||||
></centerbox>
|
||||
}
|
||||
onClicked={() => {
|
||||
// TODO: Make sure to check if device was previously paired and otherwise do some pairing shenanigans
|
||||
device.connect_device( () => {} );
|
||||
}}
|
||||
></button>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
export default BTDevice;
|
Reference in New Issue
Block a user