feat(ags): make wifi ap list better

This commit is contained in:
matt1432 2023-12-04 15:39:12 -05:00
parent 9bdb2f44b4
commit 89cc58175f
6 changed files with 225 additions and 34 deletions

View file

@ -10,6 +10,8 @@ import { SpeakerIcon, MicIcon } from '../misc/audio-icons.js';
import EventBox from '../misc/cursorbox.js';
import Separator from '../misc/separator.js';
import { NetworkMenu } from './network.js';
const SPACING = 28;
@ -190,36 +192,7 @@ const FirstRow = () => Row({
self.label = Network.wifi?.ssid || Network.wired?.internet;
}],
menu: Box({
className: 'menu',
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',
}),
],
}),
}));
}]],
}),
menu: NetworkMenu(),
}),
GridButton({

View file

@ -0,0 +1,207 @@
import App from 'resource:///com/github/Aylur/ags/app.js';
import Network from 'resource:///com/github/Aylur/ags/service/network.js';
import Variable from 'resource:///com/github/Aylur/ags/variable.js';
import { Box, Icon, Label, Overlay, Revealer, Scrollable, Widget } from 'resource:///com/github/Aylur/ags/widget.js';
import { execAsync } from 'resource:///com/github/Aylur/ags/utils.js';
import EventBox from '../misc/cursorbox.js';
// FIXME: wait for https://github.com/Aylur/ags/pull/199
const ListBox = Widget.subclass(imports.gi.Gtk.ListBox);
const SCROLL_THRESHOLD_H = 200;
const SCROLL_THRESHOLD_N = 7;
const AccessPoint = (ap) => {
const widget = Box({
className: 'ap',
});
widget.ap = Variable(ap);
const child = Box({
hexpand: true,
children: [
Icon({
connections: [[widget.ap, (self) => {
self.icon = widget.ap.value.iconName;
}]],
}),
Label({
connections: [[widget.ap, (self) => {
self.label = widget.ap.value.ssid || '';
}]],
}),
Icon({
icon: 'object-select-symbolic',
hexpand: true,
hpack: 'end',
connections: [[Network, (self) => {
self.visible = widget.ap.value.ssid === Network.wifi.ssid;
}]],
}),
],
});
widget.add(Revealer({
revealChild: true,
transition: 'slide_down',
child: EventBox({
onPrimaryClickRelease: () => {
execAsync(`nmcli device wifi connect
${widget.ap.value.bssid}`).catch(print);
},
child,
}),
}));
widget.show_all();
return widget;
};
export const NetworkMenu = () => {
const APList = new Map();
const topArrow = Revealer({
child: Icon({
icon: `${App.configDir }/icons/down-large.svg`,
className: 'scrolled-indicator',
size: 16,
css: '-gtk-icon-transform: rotate(180deg);',
}),
});
const bottomArrow = Revealer({
child: Icon({
icon: `${App.configDir }/icons/down-large.svg`,
className: 'scrolled-indicator',
size: 16,
}),
});
return Overlay({
pass_through: true,
overlays: [
Box({
vpack: 'start',
hpack: 'center',
css: 'margin-top: 12px',
children: [topArrow],
}),
Box({
vpack: 'end',
hpack: 'center',
css: 'margin-bottom: 12px',
children: [bottomArrow],
}),
],
child: Box({
className: 'menu',
child: Scrollable({
hscroll: 'never',
vscroll: 'never',
connections: [['edge-reached', (_, pos) => {
// Manage scroll indicators
if (pos === 2) {
topArrow.revealChild = false;
bottomArrow.revealChild = true;
}
else if (pos === 3) {
topArrow.revealChild = true;
bottomArrow.revealChild = false;
}
}]],
child: ListBox({
setup: (self) => {
self.set_sort_func((a, b) => {
return b.get_children()[0].ap.value.strength -
a.get_children()[0].ap.value.strength;
});
},
connections: [[Network, (box) => {
// Add missing APs
Network.wifi?.access_points.forEach((ap) => {
if (ap.ssid !== 'Unknown') {
if (APList.has(ap.ssid)) {
const accesPoint = APList.get(ap.ssid)
.ap.value;
if (accesPoint.strength < ap.strength) {
APList.get(ap.ssid).ap.value = ap;
}
}
else {
APList.set(ap.ssid, AccessPoint(ap));
box.add(APList.get(ap.ssid));
box.show_all();
}
}
});
// Delete ones that don't exist anymore
const difference = Array.from(APList.keys())
.filter((ssid) => !Network.wifi.access_points
.find((ap) => ap.ssid === ssid) &&
ssid !== 'Unknown');
difference.forEach((ssid) => {
const apWidget = APList.get(ssid);
if (apWidget) {
if (apWidget.toDestroy) {
apWidget.get_parent().destroy();
APList.delete(ssid);
}
else {
apWidget.children[0].revealChild = false;
apWidget.toDestroy = true;
}
}
});
// Start scrolling after a specified height
// is reached by the children
const height = Math.max(
box.get_parent().get_allocated_height(),
SCROLL_THRESHOLD_H,
);
const scroll = box.get_parent().get_parent();
if (box.get_children().length > SCROLL_THRESHOLD_N) {
scroll.vscroll = 'always';
scroll.setCss(`min-height: ${height}px;`);
// Make bottom scroll indicator appear only
// when first getting overflowing children
if (!(bottomArrow.revealChild === true ||
topArrow.revealChild === true)) {
bottomArrow.revealChild = true;
}
}
else {
scroll.vscroll = 'never';
scroll.setCss('');
topArrow.revealChild = false;
bottomArrow.revealChild = false;
}
// Trigger sort_func
box.get_children().forEach((ch) => {
ch.changed();
});
}]],
}),
}),
}),
});
};

View file

@ -20,14 +20,27 @@
transition: color 0.3s ease-in-out;
}
.scrolled-indicator {
margin: 5px 0;
}
.menu {
margin: 10px;
padding: 5px;
padding: 0;
border: 1.5px solid $contrast-bg;
border-radius: 10px;
font-size: 12px;
button {
scrolledwindow {
padding: 3px;
}
row {
padding: 0;
margin: 0;
}
.ap {
margin: 5px;
label {

View file

@ -16,7 +16,6 @@ plugin {
}
# Autostart programs
exec-once = sleep 3; nm-applet
exec-once = sleep 4; blueberry-tray
exec-once = sleep 6; nextcloud --background
exec-once = squeekboard

Binary file not shown.

View file

@ -36,7 +36,6 @@ in {
## gui
pavucontrol # TODO: replace with ags widget
networkmanagerapplet # TODO: replace with ags widget
])
++ (optionals isTouchscreen (with pkgs; [
# touchscreen