mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
opt.: display total disk space on server tab
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:toolbox/core/extension/listx.dart';
|
||||||
import 'package:toolbox/core/extension/numx.dart';
|
import 'package:toolbox/core/extension/numx.dart';
|
||||||
import 'package:toolbox/data/model/server/time_seq.dart';
|
import 'package:toolbox/data/model/server/time_seq.dart';
|
||||||
|
|
||||||
@@ -20,12 +21,6 @@ class Disk {
|
|||||||
required this.avail,
|
required this.avail,
|
||||||
});
|
});
|
||||||
|
|
||||||
/// raw:
|
|
||||||
/// ```
|
|
||||||
/// Filesystem 1K-blocks Used Available Use% Mounted on
|
|
||||||
/// overlay 959122528 154470540 755857572 17% /
|
|
||||||
/// tmpfs 65536 0 65536 0% /dev
|
|
||||||
/// ```
|
|
||||||
static List<Disk> parse(String raw) {
|
static List<Disk> parse(String raw) {
|
||||||
final list = <Disk>[];
|
final list = <Disk>[];
|
||||||
final items = raw.split('\n');
|
final items = raw.split('\n');
|
||||||
@@ -66,22 +61,16 @@ class DiskIO extends TimeSeq<DiskIOPiece> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void onUpdate() {
|
void onUpdate() {
|
||||||
|
cachedAllSpeed = _getAllSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
(double?, double?) _getSpeed(String dev) {
|
(double?, double?) _getSpeed(String dev) {
|
||||||
final pres = this.pre.where(
|
final old = pre.firstWhereOrNull((e) => e.dev == '/dev/$dev');
|
||||||
(element) => element.dev == dev.replaceFirst('/dev/', ''),
|
final new_ = now.firstWhereOrNull((e) => e.dev == '/dev/$dev');
|
||||||
);
|
if (old == null || new_ == null) return (null, null);
|
||||||
final nows = this.now.where(
|
final sectorsRead = new_.sectorsRead - old.sectorsRead;
|
||||||
(element) => element.dev == dev.replaceFirst('/dev/', ''),
|
final sectorsWrite = new_.sectorsWrite - old.sectorsWrite;
|
||||||
);
|
final time = new_.time - old.time;
|
||||||
if (pres.isEmpty || nows.isEmpty) return (null, null);
|
|
||||||
final pre = pres.first;
|
|
||||||
final now = nows.first;
|
|
||||||
final sectorsRead = now.sectorsRead - pre.sectorsRead;
|
|
||||||
final sectorsWrite = now.sectorsWrite - pre.sectorsWrite;
|
|
||||||
final time = now.time - pre.time;
|
|
||||||
final read = sectorsRead / time * 512;
|
final read = sectorsRead / time * 512;
|
||||||
final write = sectorsWrite / time * 512;
|
final write = sectorsWrite / time * 512;
|
||||||
return (read, write);
|
return (read, write);
|
||||||
@@ -95,7 +84,8 @@ class DiskIO extends TimeSeq<DiskIOPiece> {
|
|||||||
return (read, write);
|
return (read, write);
|
||||||
}
|
}
|
||||||
|
|
||||||
(String?, String?) getAllSpeed() {
|
(String?, String?) cachedAllSpeed = (null, null);
|
||||||
|
(String?, String?) _getAllSpeed() {
|
||||||
if (pre.isEmpty || now.isEmpty) return (null, null);
|
if (pre.isEmpty || now.isEmpty) return (null, null);
|
||||||
var (read, write) = (0.0, 0.0);
|
var (read, write) = (0.0, 0.0);
|
||||||
for (var pre in pre) {
|
for (var pre in pre) {
|
||||||
@@ -108,18 +98,6 @@ class DiskIO extends TimeSeq<DiskIOPiece> {
|
|||||||
return (readStr, writeStr);
|
return (readStr, writeStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Raw:
|
|
||||||
// 254 0 vda 584193 186416 40419294 845790 5024458 2028159 92899586 6997559 0 5728372 8143590 0 0 0 0 2006112 300240
|
|
||||||
// 254 1 vda1 584029 186416 40412734 845668 5024453 2028159 92899586 6997558 0 5728264 7843226 0 0 0 0 0 0
|
|
||||||
// 11 0 sr0 36 0 280 49 0 0 0 0 0 56 49 0 0 0 0 0 0
|
|
||||||
// 7 0 loop0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
||||||
// 7 1 loop1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
||||||
// 7 2 loop2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
||||||
// 7 3 loop3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
||||||
// 7 4 loop4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
||||||
// 7 5 loop5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
||||||
// 7 6 loop6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
||||||
// 7 7 loop7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
||||||
static List<DiskIOPiece> parse(String raw, int time) {
|
static List<DiskIOPiece> parse(String raw, int time) {
|
||||||
final lines = raw.split('\n');
|
final lines = raw.split('\n');
|
||||||
if (lines.isEmpty) return [];
|
if (lines.isEmpty) return [];
|
||||||
@@ -163,25 +141,29 @@ class DiskIOPiece extends TimeSeqIface<DiskIOPiece> {
|
|||||||
bool same(DiskIOPiece other) => dev == other.dev;
|
bool same(DiskIOPiece other) => dev == other.dev;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Issue 88
|
class DiskUsage {
|
||||||
///
|
final BigInt used;
|
||||||
/// Due to performance issues,
|
final BigInt size;
|
||||||
/// if there is no `Disk.loc == '/' || Disk.loc == '/sysroot'`,
|
|
||||||
/// return the first [Disk] of [disks].
|
DiskUsage({
|
||||||
///
|
required this.used,
|
||||||
/// If we find out the biggest [Disk] of [disks],
|
required this.size,
|
||||||
/// the fps may lower than 60.
|
});
|
||||||
Disk? findRootDisk(List<Disk> disks) {
|
|
||||||
if (disks.isEmpty) return null;
|
double get usedPercent => used / size * 100;
|
||||||
final roots = disks.where((element) => element.mount == '/');
|
|
||||||
if (roots.isEmpty) {
|
/// Find all devs, add their used and size
|
||||||
final sysRoots = disks.where((element) => element.mount == '/sysroot');
|
static DiskUsage parse(List<Disk> disks) {
|
||||||
if (sysRoots.isEmpty) {
|
final devs = <String>{};
|
||||||
return disks.first;
|
var used = BigInt.zero;
|
||||||
} else {
|
var size = BigInt.zero;
|
||||||
return sysRoots.first;
|
for (var disk in disks) {
|
||||||
|
if (!disk.dev.startsWith('/dev')) continue;
|
||||||
|
if (devs.contains(disk.dev)) continue;
|
||||||
|
devs.add(disk.dev);
|
||||||
|
used += disk.used;
|
||||||
|
size += disk.size;
|
||||||
}
|
}
|
||||||
} else {
|
return DiskUsage(used: used, size: size);
|
||||||
return roots.first;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ class NetSpeed extends TimeSeq<NetSpeedPart> {
|
|||||||
|
|
||||||
/// Issue #295
|
/// Issue #295
|
||||||
/// Non-virtual network device prefix
|
/// Non-virtual network device prefix
|
||||||
static const List<String> realIfacePrefixs = ['eth', 'wlan', 'en', 'ww', 'wl'];
|
static const realIfacePrefixs = ['eth', 'wlan', 'en', 'ww', 'wl'];
|
||||||
|
|
||||||
/// Cached non-virtual network device prefix
|
/// Cached non-virtual network device prefix
|
||||||
final realIfaces = <String>[];
|
final realIfaces = <String>[];
|
||||||
@@ -166,7 +166,8 @@ class NetSpeed extends TimeSeq<NetSpeedPart> {
|
|||||||
for (final item in split.sublist(2)) {
|
for (final item in split.sublist(2)) {
|
||||||
try {
|
try {
|
||||||
final data = item.trim().split(':');
|
final data = item.trim().split(':');
|
||||||
final device = data.first;
|
final device = data.firstOrNull;
|
||||||
|
if (device == null) continue;
|
||||||
final bytes = data.last.trim().split(' ');
|
final bytes = data.last.trim().split(' ');
|
||||||
bytes.removeWhere((element) => element == '');
|
bytes.removeWhere((element) => element == '');
|
||||||
final bytesIn = BigInt.parse(bytes.first);
|
final bytesIn = BigInt.parse(bytes.first);
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ class ServerStatus {
|
|||||||
final List<Battery> batteries = [];
|
final List<Battery> batteries = [];
|
||||||
final Map<StatusCmdType, String> more = {};
|
final Map<StatusCmdType, String> more = {};
|
||||||
final List<SensorItem> sensors = [];
|
final List<SensorItem> sensors = [];
|
||||||
|
DiskUsage? diskUsage;
|
||||||
|
|
||||||
ServerStatus({
|
ServerStatus({
|
||||||
required this.cpu,
|
required this.cpu,
|
||||||
@@ -70,6 +71,7 @@ class ServerStatus {
|
|||||||
required this.diskIO,
|
required this.diskIO,
|
||||||
this.err,
|
this.err,
|
||||||
this.nvidia,
|
this.nvidia,
|
||||||
|
this.diskUsage,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ Future<ServerStatus> _getLinuxStatus(ServerStatusUpdateReq req) async {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
req.ss.disk = Disk.parse(StatusCmdType.disk.find(segments));
|
req.ss.disk = Disk.parse(StatusCmdType.disk.find(segments));
|
||||||
|
req.ss.diskUsage = DiskUsage.parse(req.ss.disk);
|
||||||
} catch (e, s) {
|
} catch (e, s) {
|
||||||
Loggers.parse.warning(e, s);
|
Loggers.parse.warning(e, s);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ import 'package:toolbox/data/res/store.dart';
|
|||||||
|
|
||||||
import '../../../core/route.dart';
|
import '../../../core/route.dart';
|
||||||
import '../../../data/model/app/net_view.dart';
|
import '../../../data/model/app/net_view.dart';
|
||||||
import '../../../data/model/server/disk.dart';
|
|
||||||
import '../../../data/model/server/server.dart';
|
import '../../../data/model/server/server.dart';
|
||||||
import '../../../data/model/server/server_private_info.dart';
|
import '../../../data/model/server/server_private_info.dart';
|
||||||
import '../../../data/provider/server.dart';
|
import '../../../data/provider/server.dart';
|
||||||
@@ -430,11 +429,10 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
return ListenableBuilder(
|
return ListenableBuilder(
|
||||||
listenable: cardNoti,
|
listenable: cardNoti,
|
||||||
builder: (_, __) {
|
builder: (_, __) {
|
||||||
final rootDisk = findRootDisk(ss.disk);
|
|
||||||
final isSpeed = cardNoti.value.diskIO ??
|
final isSpeed = cardNoti.value.diskIO ??
|
||||||
!Stores.setting.serverTabPreferDiskAmount.fetch();
|
!Stores.setting.serverTabPreferDiskAmount.fetch();
|
||||||
|
|
||||||
final (r, w) = ss.diskIO.getAllSpeed();
|
final (r, w) = ss.diskIO.cachedAllSpeed;
|
||||||
|
|
||||||
return AnimatedSwitcher(
|
return AnimatedSwitcher(
|
||||||
duration: const Duration(milliseconds: 377),
|
duration: const Duration(milliseconds: 377),
|
||||||
@@ -442,8 +440,12 @@ class _ServerPageState extends State<ServerPage>
|
|||||||
return FadeTransition(opacity: animation, child: child);
|
return FadeTransition(opacity: animation, child: child);
|
||||||
},
|
},
|
||||||
child: _buildIOData(
|
child: _buildIOData(
|
||||||
isSpeed ? '${l10n.read}:\n$r' : 'Total:\n${rootDisk?.size.kb2Str}',
|
isSpeed
|
||||||
isSpeed ? '${l10n.write}:\n$w' : 'Used:\n${rootDisk?.usedPercent}%',
|
? '${l10n.read}:\n$r'
|
||||||
|
: 'Total:\n${ss.diskUsage?.size.kb2Str}',
|
||||||
|
isSpeed
|
||||||
|
? '${l10n.write}:\n$w'
|
||||||
|
: 'Used:\n${ss.diskUsage?.used.kb2Str}',
|
||||||
onTap: () {
|
onTap: () {
|
||||||
cardNoti.value = cardNoti.value.copyWith(diskIO: !isSpeed);
|
cardNoti.value = cardNoti.value.copyWith(diskIO: !isSpeed);
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user