feat(quicksett): start working on menus for buttons

This commit is contained in:
matt1432 2023-11-09 02:19:18 -05:00
parent 8178b27c3c
commit 531543bb46
3 changed files with 237 additions and 152 deletions

View file

@ -2,43 +2,149 @@ import App from 'resource:///com/github/Aylur/ags/app.js';
import Audio from 'resource:///com/github/Aylur/ags/service/audio.js'; import Audio from 'resource:///com/github/Aylur/ags/service/audio.js';
import Bluetooth from 'resource:///com/github/Aylur/ags/service/bluetooth.js'; import Bluetooth from 'resource:///com/github/Aylur/ags/service/bluetooth.js';
import Network from 'resource:///com/github/Aylur/ags/service/network.js'; import Network from 'resource:///com/github/Aylur/ags/service/network.js';
import { Box, CenterBox, Label, Icon } from 'resource:///com/github/Aylur/ags/widget.js'; import Variable from 'resource:///com/github/Aylur/ags/variable.js';
import { Box, Icon, Label, Revealer } from 'resource:///com/github/Aylur/ags/widget.js';
import { execAsync } from 'resource:///com/github/Aylur/ags/utils.js'; import { execAsync } from 'resource:///com/github/Aylur/ags/utils.js';
import EventBox from '../misc/cursorbox.js'; import EventBox from '../misc/cursorbox.js';
import Separator from '../misc/separator.js';
const ButtonStates = [];
const GridButton = ({ const GridButton = ({
command = () => {}, command = () => {},
secondaryCommand = () => {}, secondaryCommand = () => {},
icon, icon,
} = {}) => Box({ indicator,
menu,
} = {}) => {
const Activated = Variable(false);
ButtonStates.push(Activated);
// allow setting icon dynamically or statically
if (typeof icon === 'string') {
icon = Icon({
className: 'grid-label',
icon: icon,
connections: [[Activated, self => {
self.setCss(`color: ${Activated.value ? 'rgba(189, 147, 249, 0.8)' : 'unset'};`);
}]],
});
}
else {
icon = Icon({
className: 'grid-label',
connections: [
icon,
[Activated, self => {
self.setCss(`color: ${Activated.value ? 'rgba(189, 147, 249, 0.8)' : 'unset'};`);
}],
],
});
}
if (indicator) {
indicator = Label({
className: 'sub-label',
justification: 'left',
truncate: 'end',
maxWidthChars: 12,
connections: [indicator],
});
}
if (menu) {
menu = Revealer({
transition: 'slide_down',
child: menu,
binds: [['revealChild', Activated, 'value']],
});
}
const widget = Box({
vertical: true,
children: [
Box({
className: 'grid-button', className: 'grid-button',
children: [ children: [
EventBox({ EventBox({
className: 'left-part', className: 'left-part',
onPrimaryClickRelease: () => command(), onPrimaryClickRelease: () => {
if (!Activated.value)
command();
else
secondaryCommand();
},
child: icon, child: icon,
}), }),
EventBox({ EventBox({
className: 'right-part', className: 'right-part',
onPrimaryClickRelease: () => secondaryCommand(), onPrimaryClickRelease: () => {
child: Label({ ButtonStates.forEach(state => {
label: ' ', if (state !== Activated)
state.value = false;
});
Activated.value = !Activated.value;
},
onHover: self => {
if (menu) {
const rowMenu = self.get_parent().get_parent()
.get_parent().get_parent().children[1];
if (!rowMenu.get_children().find(ch => ch === menu)) {
rowMenu.add(menu);
rowMenu.show_all();
}
}
},
child: Icon({
icon: App.configDir + '/icons/down-large.svg',
connections: [[Activated, self => {
let deg = 270;
if (Activated.value)
deg = menu ? 360 : 450;
self.setCss(`-gtk-icon-transform: rotate(${deg}deg);`);
}]],
className: 'grid-chev', className: 'grid-chev',
}), }),
}), }),
], ],
}),
indicator,
],
}); });
return widget;
};
const FirstRow = () => Box({ const Row = ({ buttons } = {}) => {
const widget = Box({
vertical: true,
children: [
Box({
className: 'button-row', className: 'button-row',
hpack: 'center', hpack: 'center',
css: 'margin-top: 15px; margin-bottom: 7px;', }),
children: [ Box(),
],
});
for (let i = 0; i < buttons.length; ++i) {
if (i !== buttons.length - 1) {
widget.children[0].add(buttons[i]);
widget.children[0].add(Separator(28));
}
else {
widget.children[0].add(buttons[i]);
}
}
return widget;
};
const FirstRow = () => Row({
buttons: [
GridButton({ GridButton({
command: () => Network.toggleWifi(), command: () => Network.toggleWifi(),
@ -46,15 +152,29 @@ const FirstRow = () => Box({
execAsync(['bash', '-c', 'nm-connection-editor']) execAsync(['bash', '-c', 'nm-connection-editor'])
.catch(print); .catch(print);
}, },
icon: Icon({ icon: [Network, icon => icon.icon = Network.wifi?.iconName],
className: 'grid-label', indicator: [Network, self => self.label = Network.wifi?.ssid || Network.wired?.internet],
connections: [[Network, icon => {
if (Network.wifi.enabled)
icon.icon = 'network-wireless-connected-symbolic';
else menu: Box({
icon.icon = 'network-wireless-offline-symbolic'; className: 'menu',
}, 'changed']], vertical: true,
connections: [[Network, box => box.children =
Network.wifi?.access_points.map(ap => EventBox({
isButton: true,
on_clicked: () => execAsync(`nmcli device wifi connect ${ap.bssid}`).catch(print),
child: Box({
children: [
Icon(ap.iconName),
Label(ap.ssid || ''),
ap.active && Icon({
icon: 'object-select-symbolic',
hexpand: true,
hpack: 'end',
}),
],
}),
})),
]],
}), }),
}), }),
@ -67,9 +187,7 @@ const FirstRow = () => Box({
execAsync(['bash', '-c', 'blueberry']) execAsync(['bash', '-c', 'blueberry'])
.catch(print); .catch(print);
}, },
icon: Icon({ icon: [Bluetooth, self => {
className: 'grid-label',
connections: [[Bluetooth, self => {
if (Bluetooth.enabled) { if (Bluetooth.enabled) {
self.icon = 'bluetooth-active-symbolic'; self.icon = 'bluetooth-active-symbolic';
execAsync(['bash', '-c', 'echo 󰂯 > $HOME/.config/.bluetooth']) execAsync(['bash', '-c', 'echo 󰂯 > $HOME/.config/.bluetooth'])
@ -80,10 +198,16 @@ const FirstRow = () => Box({
execAsync(['bash', '-c', 'echo 󰂲 > $HOME/.config/.bluetooth']) execAsync(['bash', '-c', 'echo 󰂲 > $HOME/.config/.bluetooth'])
.catch(print); .catch(print);
} }
}, 'changed']], }, 'changed'],
}), indicator: [Bluetooth, self => {
if (Bluetooth.connectedDevices[0])
self.label = String(Bluetooth.connectedDevices[0]);
else
self.label = 'Disconnected';
}, 'changed'],
}), }),
// TODO: replace with vpn
GridButton({ GridButton({
command: () => { command: () => {
execAsync(['bash', '-c', '$AGS_PATH/qs-toggles.sh toggle-radio']) execAsync(['bash', '-c', '$AGS_PATH/qs-toggles.sh toggle-radio'])
@ -93,47 +217,13 @@ const FirstRow = () => Box({
execAsync(['notify-send', 'set this up moron']) execAsync(['notify-send', 'set this up moron'])
.catch(print); .catch(print);
}, },
icon: Icon({ icon: [Network, self => {
className: 'grid-label',
connections: [[Network, self => {
if (Network.wifi.enabled) if (Network.wifi.enabled)
self.icon = 'airplane-mode-disabled-symbolic'; self.icon = 'airplane-mode-disabled-symbolic';
else else
self.icon = 'airplane-mode-symbolic'; self.icon = 'airplane-mode-symbolic';
}, 'changed']], }, 'changed'],
}), }),
}),
],
});
const SubRow = () => CenterBox({
hpack: 'start',
children: [
Label({
className: 'sub-label',
truncate: 'end',
maxWidthChars: 12,
connections: [[Network, self => {
// TODO: handle ethernet too
self.label = Network.wifi.ssid;
}, 'changed']],
}),
Label({
className: 'sub-label',
truncate: 'end',
maxWidthChars: 12,
connections: [[Bluetooth, self => {
if (Bluetooth.connectedDevices[0])
self.label = String(Bluetooth.connectedDevices[0]);
else
self.label = 'Disconnected';
}, 'changed']],
}),
null,
], ],
}); });
@ -152,11 +242,8 @@ const itemsMic = {
0: 'audio-input-microphone-muted-symbolic', 0: 'audio-input-microphone-muted-symbolic',
}; };
const SecondRow = () => Box({ const SecondRow = () => Row({
className: 'button-row', buttons: [
hpack: 'center',
css: 'margin-top: 7px; margin-bottom: 15px;',
children: [
GridButton({ GridButton({
command: () => { command: () => {
@ -169,9 +256,7 @@ const SecondRow = () => Box({
.catch(print); .catch(print);
}, },
icon: Icon({ icon: [Audio, icon => {
className: 'grid-label',
connections: [[Audio, icon => {
if (Audio.speaker) { if (Audio.speaker) {
if (Audio.speaker.stream.isMuted) { if (Audio.speaker.stream.isMuted) {
icon.icon = items[0]; icon.icon = items[0];
@ -184,8 +269,7 @@ const SecondRow = () => Box({
} }
} }
} }
}, 'speaker-changed']], }, 'speaker-changed'],
}),
}), }),
GridButton({ GridButton({
@ -199,9 +283,7 @@ const SecondRow = () => Box({
.catch(print); .catch(print);
}, },
icon: Icon({ icon: [Audio, icon => {
className: 'grid-label',
connections: [[Audio, icon => {
if (Audio.microphone) { if (Audio.microphone) {
if (Audio.microphone.stream.isMuted) { if (Audio.microphone.stream.isMuted) {
icon.icon = itemsMic[0]; icon.icon = itemsMic[0];
@ -214,8 +296,7 @@ const SecondRow = () => Box({
} }
} }
} }
}, 'microphone-changed']], }, 'microphone-changed'],
}),
}), }),
GridButton({ GridButton({
@ -224,10 +305,7 @@ const SecondRow = () => Box({
.catch(print); .catch(print);
}, },
secondaryCommand: () => App.openWindow('powermenu'), secondaryCommand: () => App.openWindow('powermenu'),
icon: Label({ icon: 'system-lock-screen-symbolic',
className: 'grid-label',
label: ' 󰌾 ',
}),
}), }),
], ],
@ -239,7 +317,7 @@ export default () => Box({
hpack: 'center', hpack: 'center',
children: [ children: [
FirstRow(), FirstRow(),
SubRow(), Separator(10, { vertical: true }),
SecondRow(), SecondRow(),
], ],
}); });

View file

@ -21,7 +21,10 @@ const QuickSettingsWidget = () => Box({
label: 'Control Center', label: 'Control Center',
className: 'title', className: 'title',
hpack: 'start', hpack: 'start',
css: 'margin-left: 20px', css: `
margin-left: 20px;
margin-bottom: 30px;
`,
}), }),
ButtonGrid(), ButtonGrid(),

View file

@ -17,57 +17,61 @@
margin-left: 15px; margin-left: 15px;
margin-right: 10px; margin-right: 10px;
min-width: 50px; min-width: 50px;
transition: color 0.3s ease-in-out;
}
.menu {
margin: 10px;
padding: 5px;
border: 1.5px solid $contrast-bg;
border-radius: 10px;
font-size: 12px;
button {
margin: 5px;
label {
font-size: 16px;
margin-left: 5px;
}
image {
font-size: 20px;
}
}
} }
.sub-label { .sub-label {
font-size: 14px; font-size: 14px;
margin-top: -10px;
margin-left: 31px;
&:nth-child(1) {
margin-left: 25px;
}
margin-bottom: 10px;
padding: 3px; padding: 3px;
border: 2px solid $contrast-bg; border: 2px solid $contrast-bg;
border-radius: 10px 20px 20px 10px; border-radius: 10px 20px 20px 10px;
min-width: 106px; min-width: 106px;
background: #1b1b1b; background: #1b1b1b;
margin-top: 5px;
} }
.grid-chev { .grid-chev {
margin-left: 0; margin-left: 10px;
margin-right: 12px;
font-size: 25px;
font-size: 40px; transition: -gtk-icon-transform 0.3s ease-in-out;
margin-right: 5px;
} }
.button-grid { .button-grid {
font-size: 10px; font-size: 10px;
min-height: 160px; min-width: 440px;
min-width: 470px;
background-color: $bgfull; background-color: $bgfull;
border-top: 2px solid $contrast-bg; border-top: 2px solid $contrast-bg;
border-bottom: 2px solid $contrast-bg; border-bottom: 2px solid $contrast-bg;
border-radius: 15px; border-radius: 15px;
margin-top: 30px; padding: 10px 15px;
}
.button-row {
min-height: 70px;
min-width: 450px;
margin-left: 20px;
} }
.grid-button { .grid-button {
min-height: 65px; min-height: 65px;
min-width: 70px; min-width: 70px;
margin: 5px;
margin-left: 22px;
&:nth-child(1) {
margin-left: 5px;
}
} }
.left-part { .left-part {