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)}