dots/ags/widget/bar/components/network_info.tsx

85 lines
2.4 KiB
TypeScript

import { NETWORK_INTERFACES } from "@/settings.json";
import { toHumanReadable } from "@/lib/utils";
import Network from "gi://AstalNetwork";
import { bind, Variable } from "astal";
type IpOutput = Array<{
ifname: string;
stats64: {
rx: { bytes: number };
tx: { bytes: number };
};
}>;
type Usage = {
initialRx: number | null;
initialTx: number | null;
totalRx: number;
totalTx: number;
};
const getConnection = (instance?: Network.Wifi | Network.Wired) => {
if (!instance) return null;
const addresses = (instance instanceof Network.Wifi
? instance?.activeConnection
: instance?.connection)
?.ip4Config?.get_addresses();
return addresses.map(addr => addr.get_address()).join(", ");
}
export default function NetworkInfo() {
const net = Network.get_default();
const wiredConn = bind(net, "wired");
const wifiConn = bind(net, "wifi");
const currentConn = Variable.derive([
wiredConn,
wifiConn
], (wired, wifi) => {
switch (net.primary) {
case Network.Primary.WIFI: return wifi;
case Network.Primary.WIRED: return wired;
default: return;
}
})
const networkInterface = net.primary == 1
? NETWORK_INTERFACES.wired
: NETWORK_INTERFACES.wifi;
const networkUsage = Variable<Usage>({
initialRx: null,
initialTx: null,
totalRx: 0,
totalTx: 0,
}).poll(
5000,
['ip', '-s', '-j', 'link', 'show', networkInterface],
(out, prev) => {
const ipOutput = JSON.parse(out) as IpOutput;
const totalRx = ipOutput?.reduce((prev, item) => prev + item.stats64.rx.bytes, 0);
const totalTx = ipOutput?.reduce((prev, item) => prev + item.stats64.tx.bytes, 0);
return {
initialRx: prev.initialRx ?? totalRx,
initialTx: prev.initialTx ?? totalTx,
totalTx,
totalRx,
};
}
);
const dataBinding = bind(networkUsage);
const binding = bind(currentConn);
return binding.as(Boolean) ? <>
{binding.as(getConnection).as(data => data && <label label={data} />)}
{dataBinding.as(data => <>
<label label={`TX: ${toHumanReadable(data.totalTx / 4, "B/s")}`} />
<label label={`RX: ${toHumanReadable(data.totalRx / 4, "B/s")}`} />
</>)}
</> : <label>No network</label>
}