feat(ags): make wifi ap list better
This commit is contained in:
parent
9bdb2f44b4
commit
89cc58175f
6 changed files with 225 additions and 34 deletions
|
@ -10,6 +10,8 @@ import { SpeakerIcon, MicIcon } from '../misc/audio-icons.js';
|
||||||
import EventBox from '../misc/cursorbox.js';
|
import EventBox from '../misc/cursorbox.js';
|
||||||
import Separator from '../misc/separator.js';
|
import Separator from '../misc/separator.js';
|
||||||
|
|
||||||
|
import { NetworkMenu } from './network.js';
|
||||||
|
|
||||||
const SPACING = 28;
|
const SPACING = 28;
|
||||||
|
|
||||||
|
|
||||||
|
@ -190,36 +192,7 @@ const FirstRow = () => Row({
|
||||||
self.label = Network.wifi?.ssid || Network.wired?.internet;
|
self.label = Network.wifi?.ssid || Network.wired?.internet;
|
||||||
}],
|
}],
|
||||||
|
|
||||||
menu: Box({
|
menu: NetworkMenu(),
|
||||||
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',
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
}),
|
|
||||||
}));
|
|
||||||
}]],
|
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
GridButton({
|
GridButton({
|
||||||
|
|
207
devices/wim/config/ags/js/quick-settings/network.js
Normal file
207
devices/wim/config/ags/js/quick-settings/network.js
Normal 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();
|
||||||
|
});
|
||||||
|
}]],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
};
|
|
@ -20,14 +20,27 @@
|
||||||
transition: color 0.3s ease-in-out;
|
transition: color 0.3s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.scrolled-indicator {
|
||||||
|
margin: 5px 0;
|
||||||
|
}
|
||||||
|
|
||||||
.menu {
|
.menu {
|
||||||
margin: 10px;
|
margin: 10px;
|
||||||
padding: 5px;
|
padding: 0;
|
||||||
border: 1.5px solid $contrast-bg;
|
border: 1.5px solid $contrast-bg;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|
||||||
button {
|
scrolledwindow {
|
||||||
|
padding: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
row {
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ap {
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
|
|
||||||
label {
|
label {
|
||||||
|
|
|
@ -16,7 +16,6 @@ plugin {
|
||||||
}
|
}
|
||||||
|
|
||||||
# Autostart programs
|
# Autostart programs
|
||||||
exec-once = sleep 3; nm-applet
|
|
||||||
exec-once = sleep 4; blueberry-tray
|
exec-once = sleep 4; blueberry-tray
|
||||||
exec-once = sleep 6; nextcloud --background
|
exec-once = sleep 6; nextcloud --background
|
||||||
exec-once = squeekboard
|
exec-once = squeekboard
|
||||||
|
|
BIN
flake.lock
BIN
flake.lock
Binary file not shown.
|
@ -36,7 +36,6 @@ in {
|
||||||
|
|
||||||
## gui
|
## gui
|
||||||
pavucontrol # TODO: replace with ags widget
|
pavucontrol # TODO: replace with ags widget
|
||||||
networkmanagerapplet # TODO: replace with ags widget
|
|
||||||
])
|
])
|
||||||
++ (optionals isTouchscreen (with pkgs; [
|
++ (optionals isTouchscreen (with pkgs; [
|
||||||
# touchscreen
|
# touchscreen
|
||||||
|
|
Loading…
Reference in a new issue