-
- {samples.map((sample, index) => {
- const gateway = byteString(sample.gatewayBytes);
- const proxy = byteString(sample.proxyBytes);
- const total = gateway + proxy;
- const time = chartTime(sample.observedAt);
- const slot = capacity - samples.length + index;
- const edge = slot < 28 ? ' is-edge-left' : slot >= capacity - 28 ? ' is-edge-right' : '';
- const { height, gatewayShare } = trafficSampleMetrics(gateway, proxy, max, scale);
- const newest = index === samples.length - 1;
- return
-
-
-
-
-
-
- Всего {formatByteString(total)}
- {routeLabel} {formatByteString(gateway)}
- {proxy > 0n && Proxy {formatByteString(proxy)}}
-
- ;
- })}
-
- {max > 0n &&
+ {pinned && max > 0n &&
{formatByteString(max)}
{formatByteString(mid)}
0
}
+ setHovered(null)}>
+
+
{samples.length > 0 &&
15 с
}
+ {tooltip}
;
}
@@ -110,8 +153,16 @@ export function DevicesPanel({ open, panelRef, closeRef, onClose }) {
const previousTraffic = useRef(new Map());
const copyTimer = useRef(null);
const trafficDeltaTimer = useRef(null);
+ const trafficOrder = useRef({ direction: sortDirection, ids: [] });
const devices = useMemo(
- () => sortDevicesByTraffic(snapshot?.devices, sortDirection),
+ () => {
+ const previousIds = trafficOrder.current.direction === sortDirection
+ ? trafficOrder.current.ids
+ : [];
+ const result = stabilizeDevicesByTraffic(snapshot?.devices, sortDirection, previousIds);
+ trafficOrder.current = { direction: sortDirection, ids: result.ids };
+ return result.devices;
+ },
[snapshot?.devices, sortDirection],
);
@@ -384,6 +435,7 @@ export function DevicesPanel({ open, panelRef, closeRef, onClose }) {
{devices.map((device) => {
+ const hasName = Boolean(device.alias || device.hostname);
const title = device.alias || device.hostname || device.ip || 'Неизвестное устройство';
const editing = editingId === device.id;
const saving = savingId === device.id;
@@ -459,13 +511,13 @@ export function DevicesPanel({ open, panelRef, closeRef, onClose }) {
<>
{device.ip ?