diff --git a/AppImage/components/network-card.tsx b/AppImage/components/network-card.tsx index 06f8f95..eb0680b 100644 --- a/AppImage/components/network-card.tsx +++ b/AppImage/components/network-card.tsx @@ -2,7 +2,7 @@ import { Card, CardContent } from "./ui/card" import { Badge } from "./ui/badge" -import { Wifi, Zap } from "lucide-react" +import { Wifi, Zap } from 'lucide-react' import { useState, useEffect } from "react" import { fetchApi } from "../lib/api-config" @@ -83,15 +83,79 @@ const formatStorage = (bytes: number): string => { return `${value.toFixed(decimals)} ${sizes[i]}` } +const getUnitsSettings = () => { + if (typeof window === 'undefined') return { networkUnit: 'Bytes' as const } + + try { + const settings = localStorage.getItem('unitsSettings') + if (settings) { + const parsed = JSON.parse(settings) + return { networkUnit: parsed.networkUnit || 'Bytes' } + } + } catch (e) { + console.error('[v0] Error reading units settings:', e) + } + + return { networkUnit: 'Bytes' as const } +} + +const formatNetworkTraffic = (sizeInGB: number, unit: "Bytes" | "Bits" = "Bytes"): string => { + if (unit === "Bits") { + // Convert GB to Gb (Gigabits) + const sizeInGb = sizeInGB * 8 + + if (sizeInGb < 0.001) { + // Less than 0.001 Gb, show in Mb + return `${(sizeInGb * 1024).toFixed(1)} Mb` + } else if (sizeInGb < 1) { + // Less than 1 Gb, show in Mb + return `${(sizeInGb * 1024).toFixed(1)} Mb` + } else if (sizeInGb < 1024) { + // Less than 1024 Gb, show in Gb + return `${sizeInGb.toFixed(1)} Gb` + } else { + // 1024 Gb or more, show in Tb + return `${(sizeInGb / 1024).toFixed(1)} Tb` + } + } else { + // Bytes mode (existing behavior) + if (sizeInGB < 1) { + // Less than 1 GB, show in MB + return `${(sizeInGB * 1024).toFixed(1)} MB` + } else if (sizeInGB < 1024) { + // Less than 1024 GB, show in GB + return `${sizeInGB.toFixed(1)} GB` + } else { + // 1024 GB or more, show in TB + return `${(sizeInGB / 1024).toFixed(1)} TB` + } + } +} + export function NetworkCard({ interface_, timeframe, onClick }: NetworkCardProps) { const typeBadge = getInterfaceTypeBadge(interface_.type) const vmTypeBadge = interface_.vm_type ? getVMTypeBadge(interface_.vm_type) : null + const [networkUnit, setNetworkUnit] = useState<"Bytes" | "Bits">("Bytes") + const [trafficData, setTrafficData] = useState<{ received: number; sent: number }>({ received: 0, sent: 0, }) + useEffect(() => { + const settings = getUnitsSettings() + setNetworkUnit(settings.networkUnit as "Bytes" | "Bits") + + const handleStorageChange = () => { + const settings = getUnitsSettings() + setNetworkUnit(settings.networkUnit as "Bytes" | "Bits") + } + + window.addEventListener('storage', handleStorageChange) + return () => window.removeEventListener('storage', handleStorageChange) + }, []) + useEffect(() => { const fetchTrafficData = async () => { try { @@ -207,9 +271,9 @@ export function NetworkCard({ interface_, timeframe, onClick }: NetworkCardProps
{interface_.status.toLowerCase() === "up" && interface_.vm_type !== "vm" ? ( <> - ↓ {formatStorage(trafficData.received * 1024 * 1024 * 1024)} + ↓ {formatNetworkTraffic(trafficData.received, networkUnit)} {" / "} - ↑ {formatStorage(trafficData.sent * 1024 * 1024 * 1024)} + ↑ {formatNetworkTraffic(trafficData.sent, networkUnit)} ) : ( <> diff --git a/AppImage/components/virtual-machines.tsx b/AppImage/components/virtual-machines.tsx index 6687b2a..603b1f7 100644 --- a/AppImage/components/virtual-machines.tsx +++ b/AppImage/components/virtual-machines.tsx @@ -28,6 +28,41 @@ import { MetricsView } from "./metrics-dialog" import { formatStorage } from "@/lib/utils" // Import formatStorage utility import { fetchApi } from "../lib/api-config" +const getUnitsSettings = () => { + if (typeof window === 'undefined') return { networkUnit: 'Bytes' as const } + + try { + const settings = localStorage.getItem('unitsSettings') + if (settings) { + const parsed = JSON.parse(settings) + return { networkUnit: parsed.networkUnit || 'Bytes' } + } + } catch (e) { + console.error('[v0] Error reading units settings:', e) + } + + return { networkUnit: 'Bytes' as const } +} + +const formatBytes = (bytes: number | undefined, unit: "Bytes" | "Bits" = "Bytes"): string => { + if (!bytes || bytes === 0) return unit === "Bits" ? "0 b" : "0 B" + + if (unit === "Bits") { + // Convert bytes to bits (*8) + const bits = bytes * 8 + const k = 1000 // Use decimal for bits (networking standard) + const sizes = ["b", "Kb", "Mb", "Gb", "Tb"] + const i = Math.floor(Math.log(bits) / Math.log(k)) + return `${(bits / Math.pow(k, i)).toFixed(2)} ${sizes[i]}` + } else { + // Bytes mode (existing behavior) + const k = 1024 + const sizes = ["B", "KB", "MB", "GB", "TB"] + const i = Math.floor(Math.log(bytes) / Math.log(k)) + return `${(bytes / Math.pow(k, i)).toFixed(2)} ${sizes[i]}` + } +} + interface VMData { vmid: number name: string @@ -272,6 +307,20 @@ export function VirtualMachines() { const [selectedMetric, setSelectedMetric] = useState(null) const [ipsLoaded, setIpsLoaded] = useState(false) const [loadingIPs, setLoadingIPs] = useState(false) + const [networkUnit, setNetworkUnit] = useState<"Bytes" | "Bits">("Bytes") + + useEffect(() => { + const settings = getUnitsSettings() + setNetworkUnit(settings.networkUnit as "Bytes" | "Bits") + + const handleStorageChange = () => { + const settings = getUnitsSettings() + setNetworkUnit(settings.networkUnit as "Bytes" | "Bits") + } + + window.addEventListener('storage', handleStorageChange) + return () => window.removeEventListener('storage', handleStorageChange) + }, []) useEffect(() => { const fetchLXCIPs = async () => { @@ -938,11 +987,11 @@ export function VirtualMachines() {
- ↓ {formatBytes(vm.netin)} + ↓ {formatBytes(vm.netin, networkUnit)}
- ↑ {formatBytes(vm.netout)} + ↑ {formatBytes(vm.netout, networkUnit)}
@@ -1152,11 +1201,11 @@ export function VirtualMachines() {
- {((selectedVM.diskread || 0) / 1024 ** 2).toFixed(2)} MB + {formatBytes(selectedVM.diskread || 0, "Bytes")}
- {((selectedVM.diskwrite || 0) / 1024 ** 2).toFixed(2)} MB + {formatBytes(selectedVM.diskwrite || 0, "Bytes")}
@@ -1167,11 +1216,11 @@ export function VirtualMachines() {
- {((selectedVM.netin || 0) / 1024 ** 2).toFixed(2)} MB + {formatBytes(selectedVM.netin || 0, networkUnit)}
- {((selectedVM.netout || 0) / 1024 ** 2).toFixed(2)} MB + {formatBytes(selectedVM.netout || 0, networkUnit)}