feat(ags bt): sort devices in list
All checks were successful
Discord / discord commits (push) Has been skipped

This commit is contained in:
matt1432 2024-12-04 23:29:00 -05:00
parent 120dc12ca1
commit 1ef743030d
3 changed files with 81 additions and 10 deletions

View file

@ -4,6 +4,14 @@
.bluetooth { .bluetooth {
margin-top: 0; margin-top: 0;
* {
font-size: 20px;
}
row {
all: unset;
}
.toggle-button { .toggle-button {
padding: 4px; padding: 4px;
min-width: 30px; min-width: 30px;

View file

@ -3,12 +3,45 @@ import { Gtk } from 'astal/gtk3';
import AstalBluetooth from 'gi://AstalBluetooth'; import AstalBluetooth from 'gi://AstalBluetooth';
import { ToggleButton } from '../misc/subclasses'; import { ListBox, ToggleButton } from '../misc/subclasses';
import Separator from '../misc/separator'; import Separator from '../misc/separator';
import DeviceWidget from './device'; import DeviceWidget from './device';
const calculateDevSort = (dev: AstalBluetooth.Device) => {
let value = 0;
if (dev.connected) {
value += 1000;
}
if (dev.paired) {
value += 100;
}
if (dev.blocked) {
value += 10;
}
if (dev.icon) {
if (dev.icon === 'audio-headset') {
value += 9;
}
if (dev.icon === 'audio-headphones') {
value += 8;
}
if (dev.icon === 'audio-card') {
value += 7;
}
if (dev.icon === 'computer') {
value += 6;
}
if (dev.icon === 'phone') {
value += 5;
}
}
return value;
};
export default () => { export default () => {
const bluetooth = AstalBluetooth.get_default(); const bluetooth = AstalBluetooth.get_default();
@ -16,38 +49,53 @@ export default () => {
<scrollable <scrollable
className="list" className="list"
css="min-height: 200px;" css="min-height: 300px;"
hscroll={Gtk.PolicyType.NEVER} hscroll={Gtk.PolicyType.NEVER}
vscroll={Gtk.PolicyType.AUTOMATIC} vscroll={Gtk.PolicyType.AUTOMATIC}
> >
<box <ListBox
vertical selectionMode={Gtk.SelectionMode.SINGLE}
setup={(self) => { setup={(self) => {
self.children = bluetooth.devices bluetooth.devices
.filter((dev) => dev.name) .filter((dev) => dev.name)
.map((dev) => <DeviceWidget dev={dev} />); .forEach((dev) => {
self.add(<DeviceWidget dev={dev} />);
});
self.hook(bluetooth, 'device-added', (_, dev) => { self.hook(bluetooth, 'device-added', (_, dev) => {
if (dev.name) { if (dev.name) {
self.add(<DeviceWidget dev={dev} />); self.add(<DeviceWidget dev={dev} />);
self.invalidate_sort();
} }
}); });
self.hook(bluetooth, 'device-removed', (_, dev) => { self.hook(bluetooth, 'device-removed', (_, dev) => {
const children = self.children as DeviceWidget[]; const children = self
.get_children()
.map((ch) => ch.get_child()) as DeviceWidget[];
const devWidget = children.find((ch) => ch.dev === dev); const devWidget = children.find((ch) => ch.dev === dev);
if (devWidget) { if (devWidget) {
devWidget.revealChild = false; devWidget.revealChild = false;
setTimeout(() => { setTimeout(() => {
devWidget.destroy(); devWidget.get_parent()?.destroy();
}, devWidget.transitionDuration + 100); }, devWidget.transitionDuration + 100);
} }
}); });
self.set_sort_func((a, b) => {
const devA = (a.get_child() as DeviceWidget).dev;
const devB = (b.get_child() as DeviceWidget).dev;
const sort = calculateDevSort(devB) - calculateDevSort(devA);
return sort !== 0 ? sort : devA.name.localeCompare(devB.name);
});
}} }}
> />
</box>
</scrollable> </scrollable>
); );

View file

@ -12,3 +12,18 @@ export class ToggleButton extends astalify(Gtk.ToggleButton) {
super(props as any); super(props as any);
} }
} }
@register()
export class ListBox extends astalify(Gtk.ListBox) {
override get_children() {
return super.get_children() as Gtk.ListBoxRow[];
}
constructor(props: ConstructProps<
ListBox,
Gtk.ListBox.ConstructorProps
>) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
super(props as any);
}
}