mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
new & opt
new: `net` total in & out bytes opt: i18n for `ssh` opt: disk path ignore
This commit is contained in:
@@ -1,3 +1,5 @@
|
|||||||
|
import '../../res/misc.dart';
|
||||||
|
|
||||||
class DiskInfo {
|
class DiskInfo {
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
@@ -26,3 +28,24 @@ class DiskInfo {
|
|||||||
this.avail,
|
this.avail,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<DiskInfo> parseDisk(String raw) {
|
||||||
|
final list = <DiskInfo>[];
|
||||||
|
final items = raw.split('\n');
|
||||||
|
items.removeAt(0);
|
||||||
|
for (var item in items) {
|
||||||
|
if (item.isEmpty) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
final vals = item.split(numReg);
|
||||||
|
list.add(DiskInfo(
|
||||||
|
vals[0],
|
||||||
|
vals[5],
|
||||||
|
int.parse(vals[4].replaceFirst('%', '')),
|
||||||
|
vals[2],
|
||||||
|
vals[1],
|
||||||
|
vals[3],
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,6 +36,13 @@ class NetSpeed {
|
|||||||
return buildStandardOutput(speedInBytesPerSecond);
|
return buildStandardOutput(speedInBytesPerSecond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String totalIn({String? device}) {
|
||||||
|
if (_old[0].device == '' || _now[0].device == '') return '0kb';
|
||||||
|
final idx = deviceIdx(device);
|
||||||
|
final totalInBytes = _now[idx].bytesIn;
|
||||||
|
return totalInBytes.toInt().convertBytes;
|
||||||
|
}
|
||||||
|
|
||||||
String speedOut({String? device}) {
|
String speedOut({String? device}) {
|
||||||
if (_old[0].device == '' || _now[0].device == '') return '0kb/s';
|
if (_old[0].device == '' || _now[0].device == '') return '0kb/s';
|
||||||
final idx = deviceIdx(device);
|
final idx = deviceIdx(device);
|
||||||
@@ -44,6 +51,13 @@ class NetSpeed {
|
|||||||
return buildStandardOutput(speedOutBytesPerSecond);
|
return buildStandardOutput(speedOutBytesPerSecond);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String totalOut({String? device}) {
|
||||||
|
if (_old[0].device == '' || _now[0].device == '') return '0kb';
|
||||||
|
final idx = deviceIdx(device);
|
||||||
|
final totalOutBytes = _now[idx].bytesOut;
|
||||||
|
return totalOutBytes.toInt().convertBytes;
|
||||||
|
}
|
||||||
|
|
||||||
int deviceIdx(String? device) {
|
int deviceIdx(String? device) {
|
||||||
if (device != null) {
|
if (device != null) {
|
||||||
for (var item in _now) {
|
for (var item in _now) {
|
||||||
@@ -55,10 +69,15 @@ class NetSpeed {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
String buildStandardOutput(double speed) =>
|
String buildStandardOutput(double speed) => '${speed.convertBytes}/s';
|
||||||
'${speed.convertBytes.toLowerCase()}/s';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// [raw] example:
|
||||||
|
/// Inter-| Receive | Transmit
|
||||||
|
/// face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
|
||||||
|
/// lo: 45929941 269112 0 0 0 0 0 0 45929941 269112 0 0 0 0 0 0
|
||||||
|
/// eth0: 48481023 505772 0 0 0 0 0 0 36002262 202307 0 0 0 0 0 0
|
||||||
|
/// 1635752901
|
||||||
List<NetSpeedPart> parseNetSpeed(String raw) {
|
List<NetSpeedPart> parseNetSpeed(String raw) {
|
||||||
final split = raw.split('\n');
|
final split = raw.split('\n');
|
||||||
if (split.length < 4) {
|
if (split.length < 4) {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import '../../../core/extension/stringx.dart';
|
import '../../../core/extension/stringx.dart';
|
||||||
|
import '../../res/misc.dart';
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Code generated by jsonToDartModel https://ashamp.github.io/jsonToDartModel/
|
/// Code generated by jsonToDartModel https://ashamp.github.io/jsonToDartModel/
|
||||||
@@ -42,8 +43,6 @@ class TcpStatus {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final numReg = RegExp(r'\s{1,}');
|
|
||||||
|
|
||||||
TcpStatus? parseTcp(String raw) {
|
TcpStatus? parseTcp(String raw) {
|
||||||
final lines = raw.split('\n');
|
final lines = raw.split('\n');
|
||||||
final idx = lines.lastWhere((element) => element.startsWith('Tcp:'),
|
final idx = lines.lastWhere((element) => element.startsWith('Tcp:'),
|
||||||
|
|||||||
@@ -186,12 +186,6 @@ class ServerProvider extends BusyProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [raw] example:
|
|
||||||
/// Inter-| Receive | Transmit
|
|
||||||
/// face |bytes packets errs drop fifo frame compressed multicast|bytes packets errs drop fifo colls carrier compressed
|
|
||||||
/// lo: 45929941 269112 0 0 0 0 0 0 45929941 269112 0 0 0 0 0 0
|
|
||||||
/// eth0: 48481023 505772 0 0 0 0 0 0 36002262 202307 0 0 0 0 0 0
|
|
||||||
/// 1635752901
|
|
||||||
Future<void> _getNetSpeed(ServerPrivateInfo spi, String raw) async {
|
Future<void> _getNetSpeed(ServerPrivateInfo spi, String raw) async {
|
||||||
final info = _servers.firstWhere((e) => e.spi == spi);
|
final info = _servers.firstWhere((e) => e.spi == spi);
|
||||||
info.status.netSpeed.update(await compute(parseNetSpeed, raw));
|
info.status.netSpeed.update(await compute(parseNetSpeed, raw));
|
||||||
@@ -211,8 +205,10 @@ class ServerProvider extends BusyProvider {
|
|||||||
final cpus = await compute(parseCPU, raw);
|
final cpus = await compute(parseCPU, raw);
|
||||||
|
|
||||||
if (cpus.isNotEmpty) {
|
if (cpus.isNotEmpty) {
|
||||||
info.status.cpu
|
info.status.cpu.update(
|
||||||
.update(cpus, await compute(parseCPUTemp, [tempType, tempValue]));
|
cpus,
|
||||||
|
await compute(parseCPUTemp, [tempType, tempValue]),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,25 +225,14 @@ class ServerProvider extends BusyProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _getDisk(ServerPrivateInfo spi, String raw) {
|
Future<void> _getDisk(ServerPrivateInfo spi, String raw) async {
|
||||||
final info = _servers.firstWhere((e) => e.spi == spi);
|
final info = _servers.firstWhere((e) => e.spi == spi);
|
||||||
final list = <DiskInfo>[];
|
info.status.disk = await compute(parseDisk, raw);
|
||||||
final items = raw.split('\n');
|
|
||||||
for (var item in items) {
|
|
||||||
if (items.indexOf(item) == 0 || item.isEmpty) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
final vals = item.split(numReg);
|
|
||||||
list.add(DiskInfo(vals[0], vals[5],
|
|
||||||
int.parse(vals[4].replaceFirst('%', '')), vals[2], vals[1], vals[3]));
|
|
||||||
}
|
|
||||||
info.status.disk = list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _getMem(ServerPrivateInfo spi, String raw) async {
|
Future<void> _getMem(ServerPrivateInfo spi, String raw) async {
|
||||||
final info = _servers.firstWhere((e) => e.spi == spi);
|
final info = _servers.firstWhere((e) => e.spi == spi);
|
||||||
final mem = await compute(parseMem, raw);
|
info.status.mem = await compute(parseMem, raw);
|
||||||
info.status.mem = mem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String?> runSnippet(String id, Snippet snippet) async {
|
Future<String?> runSnippet(String id, Snippet snippet) async {
|
||||||
|
|||||||
@@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
class BuildData {
|
class BuildData {
|
||||||
static const String name = "ServerBox";
|
static const String name = "ServerBox";
|
||||||
static const int build = 210;
|
static const int build = 211;
|
||||||
static const String engine =
|
static const String engine =
|
||||||
"Flutter 3.7.0 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision b06b8b2710 (9 days ago) • 2023-01-23 16:55:55 -0800\nEngine • revision b24591ed32\nTools • Dart 2.19.0 • DevTools 2.20.1\n";
|
"Flutter 3.7.0 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision b06b8b2710 (9 days ago) • 2023-01-23 16:55:55 -0800\nEngine • revision b24591ed32\nTools • Dart 2.19.0 • DevTools 2.20.1\n";
|
||||||
static const String buildAt = "2023-02-01 23:36:32.789406";
|
static const String buildAt = "2023-02-02 12:40:53.962160";
|
||||||
static const int modifications = 0;
|
static const int modifications = 5;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1 +1,3 @@
|
|||||||
const serverMaxTryTimes = 7;
|
const serverMaxTryTimes = 7;
|
||||||
|
|
||||||
|
final numReg = RegExp(r'\s{1,}');
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ class MessageLookup extends MessageLookupByLibrary {
|
|||||||
"cmd": MessageLookupByLibrary.simpleMessage("命令"),
|
"cmd": MessageLookupByLibrary.simpleMessage("命令"),
|
||||||
"containerStatus": MessageLookupByLibrary.simpleMessage("容器状态"),
|
"containerStatus": MessageLookupByLibrary.simpleMessage("容器状态"),
|
||||||
"convert": MessageLookupByLibrary.simpleMessage("转换"),
|
"convert": MessageLookupByLibrary.simpleMessage("转换"),
|
||||||
"copy": MessageLookupByLibrary.simpleMessage("复制到剪切板"),
|
"copy": MessageLookupByLibrary.simpleMessage("复制"),
|
||||||
"copyPath": MessageLookupByLibrary.simpleMessage("复制路径"),
|
"copyPath": MessageLookupByLibrary.simpleMessage("复制路径"),
|
||||||
"createFile": MessageLookupByLibrary.simpleMessage("创建文件"),
|
"createFile": MessageLookupByLibrary.simpleMessage("创建文件"),
|
||||||
"createFolder": MessageLookupByLibrary.simpleMessage("创建文件夹"),
|
"createFolder": MessageLookupByLibrary.simpleMessage("创建文件夹"),
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
"cmd": "命令",
|
"cmd": "命令",
|
||||||
"containerStatus": "容器状态",
|
"containerStatus": "容器状态",
|
||||||
"convert": "转换",
|
"convert": "转换",
|
||||||
"copy": "复制到剪切板",
|
"copy": "复制",
|
||||||
"copyPath": "复制路径",
|
"copyPath": "复制路径",
|
||||||
"createFile": "创建文件",
|
"createFile": "创建文件",
|
||||||
"createFolder": "创建文件夹",
|
"createFolder": "创建文件夹",
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
Widget _buildDiskView(ServerStatus ss) {
|
Widget _buildDiskView(ServerStatus ss) {
|
||||||
final clone = ss.disk.toList();
|
final clone = ss.disk.toList();
|
||||||
for (var item in ss.disk) {
|
for (var item in ss.disk) {
|
||||||
if (ignorePath.any((ele) => item.loc.contains(ele))) {
|
if (_ignorePath.any((ele) => item.path.startsWith(ele))) {
|
||||||
clone.remove(item);
|
clone.remove(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -316,10 +316,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: const [
|
children: const [
|
||||||
Icon(
|
Icon(Icons.device_hub, size: 17),
|
||||||
Icons.device_hub,
|
|
||||||
size: 17,
|
|
||||||
),
|
|
||||||
Icon(Icons.arrow_downward, size: 17),
|
Icon(Icons.arrow_downward, size: 17),
|
||||||
Icon(Icons.arrow_upward, size: 17),
|
Icon(Icons.arrow_upward, size: 17),
|
||||||
],
|
],
|
||||||
@@ -328,39 +325,42 @@ class _ServerDetailPageState extends State<ServerDetailPage>
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildNetSpeedItem(NetSpeed ns, String device) {
|
Widget _buildNetSpeedItem(NetSpeed ns, String device) {
|
||||||
|
final width = (_media.size.width - 34 - 34) / 3;
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 3),
|
padding: const EdgeInsets.symmetric(vertical: 3),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: _media.size.width / 4,
|
width: width,
|
||||||
child: Text(device, style: textSize11, textScaleFactor: 1.0)),
|
child: Text(
|
||||||
SizedBox(
|
device,
|
||||||
width: _media.size.width / 4,
|
style: textSize11,
|
||||||
child: Text(ns.speedIn(device: device),
|
textScaleFactor: 1.0,
|
||||||
style: textSize11,
|
),
|
||||||
textAlign: TextAlign.center,
|
|
||||||
textScaleFactor: 1.0),
|
|
||||||
),
|
),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: _media.size.width / 4,
|
width: width,
|
||||||
child: Text(ns.speedOut(device: device),
|
child: Text(
|
||||||
style: textSize11,
|
'${ns.speedIn(device: device)}\n${ns.totalIn(device: device)}',
|
||||||
textAlign: TextAlign.right,
|
style: textSize11,
|
||||||
textScaleFactor: 1.0),
|
textAlign: TextAlign.center,
|
||||||
|
textScaleFactor: 0.87,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: width,
|
||||||
|
child: Text(
|
||||||
|
'${ns.speedOut(device: device)}\n${ns.totalOut(device: device)}',
|
||||||
|
style: textSize11,
|
||||||
|
textAlign: TextAlign.right,
|
||||||
|
textScaleFactor: 0.87,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const ignorePath = [
|
static const _ignorePath = ['udev', 'tmpfs', 'devtmpfs'];
|
||||||
'/run',
|
|
||||||
'/sys',
|
|
||||||
'/dev/shm',
|
|
||||||
'/snap',
|
|
||||||
'/var/lib/docker',
|
|
||||||
'/dev/tty'
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:toolbox/generated/l10n.dart';
|
||||||
import 'package:xterm/xterm.dart';
|
import 'package:xterm/xterm.dart';
|
||||||
|
|
||||||
import '../../core/utils/ui.dart';
|
import '../../core/utils/ui.dart';
|
||||||
@@ -35,8 +36,9 @@ class _SSHPageState extends State<SSHPage> {
|
|||||||
final TerminalController _terminalController = TerminalController();
|
final TerminalController _terminalController = TerminalController();
|
||||||
final ContextMenuController _menuController = ContextMenuController();
|
final ContextMenuController _menuController = ContextMenuController();
|
||||||
late TextStyle _menuTextStyle;
|
late TextStyle _menuTextStyle;
|
||||||
|
late S _s;
|
||||||
|
|
||||||
var isDark = false;
|
var _isDark = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -47,9 +49,10 @@ class _SSHPageState extends State<SSHPage> {
|
|||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
isDark = isDarkMode(context);
|
_isDark = isDarkMode(context);
|
||||||
_media = MediaQuery.of(context);
|
_media = MediaQuery.of(context);
|
||||||
_menuTextStyle = TextStyle(color: contentColor.resolve(context));
|
_menuTextStyle = TextStyle(color: contentColor.resolve(context));
|
||||||
|
_s = S.of(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -78,15 +81,8 @@ class _SSHPageState extends State<SSHPage> {
|
|||||||
session.write(utf8.encode(data) as Uint8List);
|
session.write(utf8.encode(data) as Uint8List);
|
||||||
};
|
};
|
||||||
|
|
||||||
session.stdout
|
_listen(session.stdout);
|
||||||
.cast<List<int>>()
|
_listen(session.stderr);
|
||||||
.transform(const Utf8Decoder())
|
|
||||||
.listen(_terminal.write);
|
|
||||||
|
|
||||||
session.stderr
|
|
||||||
.cast<List<int>>()
|
|
||||||
.transform(const Utf8Decoder())
|
|
||||||
.listen(_terminal.write);
|
|
||||||
|
|
||||||
await session.done;
|
await session.done;
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
@@ -94,9 +90,16 @@ class _SSHPageState extends State<SSHPage> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _listen(Stream<Uint8List> stream) {
|
||||||
|
stream
|
||||||
|
.cast<List<int>>()
|
||||||
|
.transform(const Utf8Decoder())
|
||||||
|
.listen(_terminal.write);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final termTheme = isDark ? termDarkTheme : termLightTheme;
|
final termTheme = _isDark ? termDarkTheme : termLightTheme;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: termTheme.background,
|
backgroundColor: termTheme.background,
|
||||||
body: _buildBody(termTheme),
|
body: _buildBody(termTheme),
|
||||||
@@ -118,7 +121,7 @@ class _SSHPageState extends State<SSHPage> {
|
|||||||
deleteDetection: Platform.isIOS,
|
deleteDetection: Platform.isIOS,
|
||||||
onTapUp: _onTapUp,
|
onTapUp: _onTapUp,
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
keyboardAppearance: isDark ? Brightness.dark : Brightness.light,
|
keyboardAppearance: _isDark ? Brightness.dark : Brightness.light,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -170,7 +173,7 @@ class _SSHPageState extends State<SSHPage> {
|
|||||||
final child = item.icon != null
|
final child = item.icon != null
|
||||||
? Icon(
|
? Icon(
|
||||||
item.icon,
|
item.icon,
|
||||||
color: isDark ? Colors.white : Colors.black,
|
color: _isDark ? Colors.white : Colors.black,
|
||||||
size: 17,
|
size: 17,
|
||||||
)
|
)
|
||||||
: Text(
|
: Text(
|
||||||
@@ -296,7 +299,7 @@ class _SSHPageState extends State<SSHPage> {
|
|||||||
children: [
|
children: [
|
||||||
TextButton(
|
TextButton(
|
||||||
child: Text(
|
child: Text(
|
||||||
'Copy',
|
_s.copy,
|
||||||
style: _menuTextStyle,
|
style: _menuTextStyle,
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
|||||||
Reference in New Issue
Block a user