161 lines
5.3 KiB
JavaScript

import Widget from 'resource:///com/github/Aylur/ags/widget.js';
import Bluetooth from 'resource:///com/github/Aylur/ags/service/bluetooth.js';
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
const { Box, Button, Icon, Label, Scrollable, Slider, Stack, Overlay } = Widget;
const { execAsync, exec } = Utils;
import { MaterialIcon } from '../../.commonwidgets/materialicon.js';
import { setupCursorHover } from '../../.widgetutils/cursorhover.js';
import { ConfigToggle } from '../../.commonwidgets/configwidgets.js';
// can't connect: sync_problem
const USE_SYMBOLIC_ICONS = true;
const BluetoothDevice = (device) => {
// console.log(device);
const deviceIcon = Icon({
className: 'sidebar-bluetooth-appicon',
vpack: 'center',
tooltipText: device.name,
setup: (self) => self.hook(device, (self) => {
self.icon = `${device.iconName}${USE_SYMBOLIC_ICONS ? '-symbolic' : ''}`;
}),
});
const deviceStatus = Box({
hexpand: true,
vpack: 'center',
vertical: true,
children: [
Label({
xalign: 0,
maxWidthChars: 1,
truncate: 'end',
label: device.name,
className: 'txt-small',
setup: (self) => self.hook(device, (self) => {
self.label = device.name;
}),
}),
Label({
xalign: 0,
maxWidthChars: 1,
truncate: 'end',
label: device.connected ? 'Connected' : (device.paired ? 'Paired' : ''),
className: 'txt-subtext',
setup: (self) => self.hook(device, (self) => {
self.label = device.connected ? 'Connected' : (device.paired ? 'Paired' : '');
}),
}),
]
});
const deviceConnectButton = ConfigToggle({
vpack: 'center',
expandWidget: false,
desc: 'Toggle connection',
initValue: device.connected,
onChange: (self, newValue) => {
device.setConnection(newValue);
},
extraSetup: (self) => self.hook(device, (self) => {
Utils.timeout(200, () => self.enabled.value = device.connected);
}),
})
const deviceRemoveButton = Button({
vpack: 'center',
className: 'sidebar-bluetooth-device-remove',
child: MaterialIcon('delete', 'norm'),
tooltipText: 'Remove device',
setup: setupCursorHover,
onClicked: () => execAsync(['bluetoothctl', 'remove', device.address]).catch(print),
});
return Box({
className: 'sidebar-bluetooth-device spacing-h-10',
children: [
deviceIcon,
deviceStatus,
Box({
className: 'spacing-h-5',
children: [
deviceConnectButton,
deviceRemoveButton,
]
})
]
})
}
export default (props) => {
const emptyContent = Box({
homogeneous: true,
children: [Box({
vertical: true,
vpack: 'center',
className: 'txt spacing-v-10',
children: [
Box({
vertical: true,
className: 'spacing-v-5 txt-subtext',
children: [
MaterialIcon('bluetooth_disabled', 'gigantic'),
Label({ label: 'No Bluetooth devices', className: 'txt-small' }),
]
}),
]
})]
});
const deviceList = Overlay({
passThrough: true,
child: Scrollable({
vexpand: true,
child: Box({
attribute: {
'updateDevices': (self) => {
const devices = Bluetooth.devices;
self.children = devices.map(d => BluetoothDevice(d));
},
},
vertical: true,
className: 'spacing-v-5 margin-bottom-15',
setup: (self) => self
.hook(Bluetooth, self.attribute.updateDevices, 'device-added')
.hook(Bluetooth, self.attribute.updateDevices, 'device-removed')
,
})
}),
overlays: [Box({
className: 'sidebar-centermodules-scrollgradient-bottom'
})]
});
const mainContent = Stack({
children: {
'empty': emptyContent,
'list': deviceList,
},
setup: (self) => self.hook(Bluetooth, (self) => {
self.shown = (Bluetooth.devices.length > 0 ? 'list' : 'empty')
}),
})
const bottomBar = Box({
homogeneous: true,
children: [Button({
hpack: 'center',
className: 'txt-small txt sidebar-centermodules-bottombar-button',
onClicked: () => {
execAsync(['bash', '-c', userOptions.apps.bluetooth]).catch(print);
closeEverything();
},
label: 'More',
setup: setupCursorHover,
})],
})
return Box({
...props,
className: 'spacing-v-5',
vertical: true,
children: [
mainContent,
bottomBar
]
});
}