mirror of
https://github.com/end-4/dots-hyprland.git
synced 2026-06-06 07:19:27 -05:00
sidebar: bluetooth: add connection toggle
This commit is contained in:
@@ -1,37 +1,60 @@
|
||||
import Variable from 'resource:///com/github/Aylur/ags/variable.js';
|
||||
import Widget from 'resource:///com/github/Aylur/ags/widget.js';
|
||||
import * as Utils from 'resource:///com/github/Aylur/ags/utils.js';
|
||||
import { MaterialIcon } from './materialicon.js';
|
||||
import { setupCursorHover } from '../.widgetutils/cursorhover.js';
|
||||
const { Box, Button, Label, Revealer } = Widget;
|
||||
|
||||
export const ConfigToggle = ({ icon, name, desc = '', initValue, onChange, expandWidget = true, ...rest }) => {
|
||||
let value = initValue;
|
||||
export const ConfigToggle = ({
|
||||
icon, name, desc = '', initValue,
|
||||
expandWidget = true,
|
||||
onChange = () => { }, extraSetup = () => { },
|
||||
...rest
|
||||
}) => {
|
||||
const enabled = Variable(initValue);
|
||||
const toggleIcon = Label({
|
||||
className: `icon-material txt-bold ${value ? '' : 'txt-poof'}`,
|
||||
label: `${value ? 'check' : ''}`,
|
||||
className: `icon-material txt-bold ${enabled.value ? '' : 'txt-poof'}`,
|
||||
label: `${enabled.value ? 'check' : ''}`,
|
||||
setup: (self) => self.hook(enabled, (self) => {
|
||||
self.toggleClassName('switch-fg-toggling-false', false);
|
||||
if (!enabled.value) {
|
||||
self.label = '';
|
||||
self.toggleClassName('txt-poof', true);
|
||||
}
|
||||
else Utils.timeout(1, () => {
|
||||
toggleIcon.label = 'check';
|
||||
toggleIcon.toggleClassName('txt-poof', false);
|
||||
})
|
||||
}),
|
||||
})
|
||||
const toggleButtonIndicator = Box({
|
||||
className: `switch-fg ${value ? 'switch-fg-true' : ''}`,
|
||||
className: `switch-fg ${enabled.value ? 'switch-fg-true' : ''}`,
|
||||
vpack: 'center',
|
||||
hpack: 'start',
|
||||
homogeneous: true,
|
||||
children: [toggleIcon,],
|
||||
setup: (self) => self.hook(enabled, (self) => {
|
||||
self.toggleClassName('switch-fg-true', enabled.value);
|
||||
}),
|
||||
});
|
||||
const toggleButton = Box({
|
||||
hpack: 'end',
|
||||
className: `switch-bg ${value ? 'switch-bg-true' : ''}`,
|
||||
className: `switch-bg ${enabled.value ? 'switch-bg-true' : ''}`,
|
||||
homogeneous: true,
|
||||
children: [toggleButtonIndicator,],
|
||||
children: [toggleButtonIndicator],
|
||||
setup: (self) => self.hook(enabled, (self) => {
|
||||
self.toggleClassName('switch-bg-true', enabled.value);
|
||||
}),
|
||||
});
|
||||
const widgetContent = Box({
|
||||
tooltipText: desc,
|
||||
className: 'txt spacing-h-5 configtoggle-box',
|
||||
children: [
|
||||
MaterialIcon(icon, 'norm'),
|
||||
Label({
|
||||
(icon !== undefined ? MaterialIcon(icon, 'norm') : null),
|
||||
(name !== undefined ? Label({
|
||||
className: 'txt txt-small',
|
||||
label: name,
|
||||
}),
|
||||
}) : null),
|
||||
expandWidget ? Box({ hexpand: true }) : null,
|
||||
toggleButton,
|
||||
]
|
||||
@@ -39,33 +62,24 @@ export const ConfigToggle = ({ icon, name, desc = '', initValue, onChange, expan
|
||||
const interactionWrapper = Button({
|
||||
attribute: {
|
||||
toggle: (newValue) => {
|
||||
value = !value;
|
||||
toggleIcon.toggleClassName('switch-fg-toggling-false', false);
|
||||
if (!value) {
|
||||
toggleIcon.label = '';
|
||||
toggleIcon.toggleClassName('txt-poof', true);
|
||||
}
|
||||
toggleButtonIndicator.toggleClassName('switch-fg-true', value);
|
||||
toggleButton.toggleClassName('switch-bg-true', value);
|
||||
if (value) Utils.timeout(1, () => {
|
||||
toggleIcon.label = 'check';
|
||||
toggleIcon.toggleClassName('txt-poof', false);
|
||||
})
|
||||
onChange(interactionWrapper, value);
|
||||
enabled.value = !enabled.value;
|
||||
onChange(interactionWrapper, enabled.value);
|
||||
}
|
||||
},
|
||||
child: widgetContent,
|
||||
onClicked: (self) => self.attribute.toggle(self),
|
||||
setup: (button) => {
|
||||
setupCursorHover(button),
|
||||
button.connect('pressed', () => { // mouse down
|
||||
toggleIcon.toggleClassName('txt-poof', true);
|
||||
toggleIcon.toggleClassName('switch-fg-true', false);
|
||||
if (!value) toggleIcon.toggleClassName('switch-fg-toggling-false', true);
|
||||
});
|
||||
setup: (self) => {
|
||||
setupCursorHover(self);
|
||||
self.connect('pressed', () => { // mouse down
|
||||
toggleIcon.toggleClassName('txt-poof', true);
|
||||
toggleIcon.toggleClassName('switch-fg-true', false);
|
||||
if (!enabled.value) toggleIcon.toggleClassName('switch-fg-toggling-false', true);
|
||||
});
|
||||
extraSetup(self)
|
||||
},
|
||||
...rest,
|
||||
});
|
||||
interactionWrapper.enabled = enabled;
|
||||
return interactionWrapper;
|
||||
}
|
||||
|
||||
@@ -123,8 +137,8 @@ export const ConfigSegmentedSelection = ({
|
||||
export const ConfigMulipleSelection = ({
|
||||
icon, name, desc = '',
|
||||
optionsArr = [
|
||||
[ { name: 'Option 1', value: 0 }, { name: 'Option 2', value: 1 } ],
|
||||
[ { name: 'Option 3', value: 0 }, { name: 'Option 4', value: 1 } ],
|
||||
[{ name: 'Option 1', value: 0 }, { name: 'Option 2', value: 1 }],
|
||||
[{ name: 'Option 3', value: 0 }, { name: 'Option 4', value: 1 }],
|
||||
],
|
||||
initIndex = [0, 0],
|
||||
onChange,
|
||||
@@ -137,27 +151,27 @@ export const ConfigMulipleSelection = ({
|
||||
className: 'multipleselection-container spacing-v-3',
|
||||
vertical: true,
|
||||
children: optionsArr.map((options, grp) => {
|
||||
return Box({
|
||||
className: 'spacing-h-5',
|
||||
hpack: 'center',
|
||||
children: options.map((option, id) => {
|
||||
return Button({
|
||||
setup: setupCursorHover,
|
||||
className: `multipleselection-btn ${id == initIndex[1] && grp == initIndex[0] ? 'multipleselection-btn-enabled' : ''}`,
|
||||
label: option.name,
|
||||
onClicked: (self) => {
|
||||
const kidsg = widget.get_children();
|
||||
const kids = kidsg.flatMap(widget => widget.get_children());
|
||||
kids.forEach(kid => {
|
||||
kid.toggleClassName('multipleselection-btn-enabled', false);
|
||||
});
|
||||
lastSelected = id;
|
||||
self.toggleClassName('multipleselection-btn-enabled', true);
|
||||
onChange(option.value, option.name);
|
||||
}
|
||||
})
|
||||
}),
|
||||
})
|
||||
return Box({
|
||||
className: 'spacing-h-5',
|
||||
hpack: 'center',
|
||||
children: options.map((option, id) => {
|
||||
return Button({
|
||||
setup: setupCursorHover,
|
||||
className: `multipleselection-btn ${id == initIndex[1] && grp == initIndex[0] ? 'multipleselection-btn-enabled' : ''}`,
|
||||
label: option.name,
|
||||
onClicked: (self) => {
|
||||
const kidsg = widget.get_children();
|
||||
const kids = kidsg.flatMap(widget => widget.get_children());
|
||||
kids.forEach(kid => {
|
||||
kid.toggleClassName('multipleselection-btn-enabled', false);
|
||||
});
|
||||
lastSelected = id;
|
||||
self.toggleClassName('multipleselection-btn-enabled', true);
|
||||
onChange(option.value, option.name);
|
||||
}
|
||||
})
|
||||
}),
|
||||
})
|
||||
}),
|
||||
...rest,
|
||||
});
|
||||
|
||||
@@ -8,55 +8,78 @@ const { Box, Button, Icon, Label, Scrollable, Slider, Stack } = 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 = false;
|
||||
|
||||
const BluetoothDevice = (device) => {
|
||||
console.log(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: 10,
|
||||
truncate: 'end',
|
||||
label: device.name,
|
||||
className: 'txt-small',
|
||||
setup: (self) => self.hook(device, (self) => {
|
||||
self.label = device.name;
|
||||
}),
|
||||
}),
|
||||
Label({
|
||||
xalign: 0,
|
||||
maxWidthChars: 10,
|
||||
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,
|
||||
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'),
|
||||
setup: setupCursorHover,
|
||||
onClicked: () => execAsync(['bluetoothctl', 'remove', device.address]).catch(print),
|
||||
});
|
||||
return Box({
|
||||
className: 'sidebar-bluetooth-device spacing-h-10',
|
||||
children: [
|
||||
Icon({
|
||||
className: 'sidebar-bluetooth-appicon',
|
||||
vpack: 'center',
|
||||
tooltipText: device.name,
|
||||
setup: (self) => self.hook(device, (self) => {
|
||||
self.icon = `${device.iconName}${USE_SYMBOLIC_ICONS ? '-symbolic' : ''}`;
|
||||
}),
|
||||
}),
|
||||
deviceIcon,
|
||||
deviceStatus,
|
||||
Box({
|
||||
hexpand: true,
|
||||
vpack: 'center',
|
||||
vertical: true,
|
||||
className: 'spacing-h-5',
|
||||
children: [
|
||||
Label({
|
||||
xalign: 0,
|
||||
maxWidthChars: 10,
|
||||
truncate: 'end',
|
||||
label: device.name,
|
||||
className: 'txt-small',
|
||||
setup: (self) => self.hook(device, (self) => {
|
||||
self.label = device.name;
|
||||
}),
|
||||
}),
|
||||
Label({
|
||||
xalign: 0,
|
||||
maxWidthChars: 10,
|
||||
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' : '');
|
||||
}),
|
||||
}),
|
||||
deviceConnectButton,
|
||||
deviceRemoveButton,
|
||||
]
|
||||
}),
|
||||
Button({
|
||||
vpack: 'center',
|
||||
className: 'sidebar-bluetooth-device-remove',
|
||||
child: MaterialIcon('delete', 'norm'),
|
||||
setup: setupCursorHover,
|
||||
onClicked: () => execAsync(['bluetoothctl', 'remove', device.address]).catch(print),
|
||||
})
|
||||
]
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user