Files
hyprland/config/ags/apps/settings/network.ts
T
2024-06-26 00:10:21 +05:45

214 lines
6.7 KiB
TypeScript

import Gtk from "gi://Gtk?version=3.0"
import { timeout } from "resource:///com/github/Aylur/ags/utils.js";
import { Variable as VariableType } from "types/variable";
const systemtray = await Service.import("systemtray")
type AccessPoint = {
bssid: string | null;
address: string | null;
lastSeen: number;
ssid: string | null;
active: boolean;
strength: number;
frequency: number;
iconName: string | undefined;
};
const network = await Service.import("network")
const _scan_timer = Variable(undefined, {
poll: [15000, WifiScan]
})
const network_state = {
"unavailable": "Device is unavailable",
"disconnected": "Device is disconnected",
"prepare": "Preparing to connect...",
"config": "Configuring connection...",
"need_auth": "Authentication required...",
"ip_config": "Obtaining IP address...",
"ip_check": "Verifying IP address...",
"secondaries": "Setting up secondary connections...",
"activated": "Connected",
"deactivating": "Disconnecting...",
"failed": "Connection failed"
};
const saved_networks: VariableType<string[]> = Variable([], {
poll: [5000, () => {
const _saved = Utils.exec(`${App.configDir}/scripts/network.sh --saved`);
return _saved.split("\n")
}]
})
function WifiScan() {
network.wifi.scan()
// await Utils.execAsync("nmcli device wifi rescan").catch(print)
return undefined
}
const WifiNetwork = (access_point: AccessPoint) => {
const is_saved = saved_networks.value.includes(access_point.ssid!);
const connected = access_point.ssid == network.wifi.ssid;
return Widget.Button({
class_name: "wifi_network",
on_primary_click: () => {
if (!connected)
Utils.execAsync(`nmcli device wifi connect '${access_point.ssid}'`)
.catch(print);
else if (is_saved)
Utils.execAsync(`${App.configDir}/scripts/network.sh --edit ${access_point.ssid}`)
.catch(print);
},
on_secondary_click: () => {
if(!connected && is_saved)
Utils.execAsync(`${App.configDir}/scripts/network.sh --edit ${access_point.ssid}`)
.catch(print);
},
child: Widget.Box({
class_name: "wifi_network_box",
children: [
Widget.Icon({
icon: access_point.iconName,
size: 20
}),
// @ts-ignore
Widget.Box({
vertical: true,
children: [
Widget.Label({
class_name: "title",
label: access_point.ssid,
hpack: "start"
}),
(connected)
? Widget.Label({
class_name: "description",
label: network_state[network.wifi.state],
hpack: "start"
})
: (is_saved)
? Widget.Label({
class_name: "description",
label: "Saved",
hpack: "start"
})
: undefined
]
})
]
}),
setup: self => {
self.toggleClassName("active", connected);
}
})
}
const WifiToggle = () => {
const box = Widget.Box({
class_name: "wifi_toggle",
children: [
Widget.Box({
vertical: true,
hexpand: true,
children: [
Widget.Label({
hpack: "start",
class_name: "title",
label: "Wi-Fi"
}),
Widget.Label({
hpack: "start",
class_name: "description",
label: "Find and connect to Wi-Fi networks"
})
]
}),
Widget.Switch({
vexpand: false,
valign: Gtk.Align.CENTER,
hpack: "end",
on_activate(self) {
timeout(5, () => {
if (network.wifi.enabled != self.active)
network.wifi.enabled = self.active
})
},
active: Variable(false, {
poll: [500, () => network.wifi.enabled]
}).bind()
})
]
})
return box
}
function WifiList() {
return Widget.Box({
vertical: true,
attribute: {
'updateNetworks': (self) => {
const accessPoints = network.wifi?.access_points || [];
const current_ssid = network.wifi?.ssid;
self.children = Object.values(accessPoints.reduce((a, accessPoint) => {
if (!a[accessPoint.ssid!]) {
a[accessPoint.ssid!] = accessPoint;
// @ts-ignore
a[accessPoint.ssid!].active |= accessPoint.active!;
}
return a;
// @ts-ignore
}, {})).sort((a: AccessPoint, b: AccessPoint) => {
if (a.ssid === current_ssid) return -1;
if (b.ssid === current_ssid) return 1;
return 0;
// @ts-ignore
}).map((n: AccessPoint) => WifiNetwork(n));
},
},
className: 'wifi_list',
setup: (self) => self.hook(network, self.attribute.updateNetworks),
})
}
const nm_applet_required = () => Widget.Box({
class_name: "error_container",
visible: false,
hexpand: true,
child: Widget.Label({
label: "Requires running nm-applet for authorization when connecting!",
hpack: "start",
vpack: "center"
}),
setup: self => {
self.hook(systemtray, () => {
const nm_applet = systemtray.items.find(item => item.id == "nm-applet")
if (nm_applet)
self.visible = false;
else
self.visible = true;
})
}
})
export function Network() {
WifiScan()
const box = Widget.Box({
vertical: true,
children: [
nm_applet_required(),
WifiToggle(),
WifiList()
],
})
return Widget.Scrollable({
hscroll: "never",
child: box,
vexpand: true
})
}