import { memo, useMemo } from "react" import { useLingui } from "@lingui/react/macro" import { Area, AreaChart, CartesianGrid, YAxis } from "recharts" import { ChartContainer, ChartTooltip, ChartTooltipContent, xAxis, ChartLegend, ChartLegendContent, } from "@/components/ui/chart" import { cn, formatShortDate, chartMargin, formatBytes, toFixedFloat, decimalString } from "@/lib/utils" import { ChartData } from "@/types" import { useStore } from "@nanostores/react" import { $networkInterfaceFilter, $userSettings } from "@/lib/stores" import { Unit } from "@/lib/enums" import { useYAxisWidth } from "./hooks" const getNestedValue = (path: string, max = false, data: any): number | null => { // path format is like "eth0.ns" or "eth0.nr" // need to access data.stats.ni[interface][property] const parts = path.split(".") if (parts.length !== 2) return null const [interfaceName, property] = parts const propertyKey = property + (max ? "m" : "") return data?.stats?.ni?.[interfaceName]?.[propertyKey] ?? null } export default memo(function NetworkInterfaceChart({ chartData, maxToggled = false, max, }: { chartData: ChartData maxToggled?: boolean max?: number }) { const { yAxisWidth, updateYAxisWidth } = useYAxisWidth() const { i18n } = useLingui() const networkInterfaceFilter = useStore($networkInterfaceFilter) const userSettings = useStore($userSettings) const { chartTime } = chartData const showMax = chartTime !== "1h" && maxToggled // Get network interface names from the latest stats const networkInterfaces = useMemo(() => { if (chartData.systemStats.length === 0) return [] const latestStats = chartData.systemStats[chartData.systemStats.length - 1] const allInterfaces = Object.keys(latestStats.stats.ni || {}) // Filter interfaces based on filter value if (networkInterfaceFilter) { return allInterfaces.filter((iface) => iface.toLowerCase().includes(networkInterfaceFilter.toLowerCase())) } return allInterfaces }, [chartData.systemStats, networkInterfaceFilter]) const dataKeys = useMemo(() => { // Generate colors for each interface - each interface gets a unique hue // and sent/received use different shades of that hue const interfaceColors = networkInterfaces.map((iface, index) => { const hue = ((index * 360) / Math.max(networkInterfaces.length, 1)) % 360 return { interface: iface, sentColor: `hsl(${hue}, 70%, 45%)`, // Darker shade for sent receivedColor: `hsl(${hue}, 70%, 65%)`, // Lighter shade for received } }) return interfaceColors.flatMap(({ interface: iface, sentColor, receivedColor }) => [ { name: `${iface} Sent`, dataKey: `${iface}.ns`, color: sentColor, type: "sent" as const, interface: iface, }, { name: `${iface} Received`, dataKey: `${iface}.nr`, color: receivedColor, type: "received" as const, interface: iface, }, ]) }, [networkInterfaces, i18n.locale]) const colors = dataKeys.map((key) => key.name) return (