#76 new: switch net view

This commit is contained in:
lollipopkit
2023-07-21 14:25:07 +08:00
parent 5a5e2fd1d1
commit 0d5707a1df
12 changed files with 158 additions and 24 deletions

View File

@@ -13,3 +13,19 @@ extension NumX on num {
return '$finalValue ${suffix[squareTimes]}'; return '$finalValue ${suffix[squareTimes]}';
} }
} }
extension BigIntX on BigInt {
String get convertBytes {
const suffix = ['B', 'KB', 'MB', 'GB', 'TB'];
double value = toDouble();
int squareTimes = 0;
for (; value / 1024 > 1 && squareTimes < suffix.length - 1; squareTimes++) {
value /= 1024;
}
var finalValue = value.toStringAsFixed(1);
if (finalValue.endsWith('.0')) {
finalValue = finalValue.replaceFirst('.0', '');
}
return '$finalValue ${suffix[squareTimes]}';
}
}

View File

@@ -0,0 +1,39 @@
import 'package:hive_flutter/hive_flutter.dart';
import 'package:toolbox/data/model/server/server_status.dart';
@HiveType(typeId: 5)
enum NetViewType {
@HiveField(0)
count,
@HiveField(1)
speed,
@HiveField(2)
size;
NetViewData build(ServerStatus ss) {
switch (this) {
case NetViewType.count:
return NetViewData(
'Conn:\n${ss.tcp.maxConn}',
'Fail:\n${ss.tcp.fail}',
);
case NetViewType.speed:
return NetViewData(
'In:\n${ss.netSpeed.speedIn(all: true)}',
'Out:\n${ss.netSpeed.speedOut(all: true)}',
);
case NetViewType.size:
return NetViewData(
'In:\n${ss.netSpeed.sizeIn(all: true)}',
'Out:\n${ss.netSpeed.sizeOut(all: true)}',
);
}
}
}
class NetViewData {
final String up;
final String down;
NetViewData(this.up, this.down);
}

View File

@@ -28,34 +28,61 @@ class NetSpeed {
BigInt get timeDiff => _now[0].time - _old[0].time; BigInt get timeDiff => _now[0].time - _old[0].time;
String speedIn({String? device}) { double _speedIn(int i) => (_now[i].bytesIn - _old[i].bytesIn) / timeDiff;
double _speedOut(int i) => (_now[i].bytesOut - _old[i].bytesOut) / timeDiff;
BigInt _sizeIn(int i) => _now[i].bytesIn;
BigInt _sizeOut(int i) => _now[i].bytesOut;
String speedIn({String? device, bool all = false}) {
if (_old[0].device == '' || _now[0].device == '') return '0kb/s'; if (_old[0].device == '' || _now[0].device == '') return '0kb/s';
if (all) {
var speed = 0.0;
for (var i = 0; i < _now.length; i++) {
speed += _speedIn(i);
}
return buildStandardOutput(speed);
}
final idx = deviceIdx(device); final idx = deviceIdx(device);
final speedInBytesPerSecond = return buildStandardOutput(_speedIn(idx));
(_now[idx].bytesIn - _old[idx].bytesIn) / timeDiff;
return buildStandardOutput(speedInBytesPerSecond);
} }
String totalIn({String? device}) { String sizeIn({String? device, bool all = false}) {
if (_old[0].device == '' || _now[0].device == '') return '0kb'; if (_old[0].device == '' || _now[0].device == '') return '0kb';
if (all) {
var size = BigInt.from(0);
for (var i = 0; i < _now.length; i++) {
size += _sizeIn(i);
}
return size.convertBytes;
}
final idx = deviceIdx(device); final idx = deviceIdx(device);
final totalInBytes = _now[idx].bytesIn; return _sizeIn(idx).convertBytes;
return totalInBytes.toInt().convertBytes;
} }
String speedOut({String? device}) { String speedOut({String? device, bool all = false}) {
if (_old[0].device == '' || _now[0].device == '') return '0kb/s'; if (_old[0].device == '' || _now[0].device == '') return '0kb/s';
if (all) {
var speed = 0.0;
for (var i = 0; i < _now.length; i++) {
speed += _speedOut(i);
}
return buildStandardOutput(speed);
}
final idx = deviceIdx(device); final idx = deviceIdx(device);
final speedOutBytesPerSecond = return buildStandardOutput(_speedOut(idx));
(_now[idx].bytesOut - _old[idx].bytesOut) / timeDiff;
return buildStandardOutput(speedOutBytesPerSecond);
} }
String totalOut({String? device}) { String sizeOut({String? device, bool all = false}) {
if (_old[0].device == '' || _now[0].device == '') return '0kb'; if (_old[0].device == '' || _now[0].device == '') return '0kb';
if (all) {
var size = BigInt.from(0);
for (var i = 0; i < _now.length; i++) {
size += _sizeOut(i);
}
return size.convertBytes;
}
final idx = deviceIdx(device); final idx = deviceIdx(device);
final totalOutBytes = _now[idx].bytesOut; return _sizeOut(idx).convertBytes;
return totalOutBytes.toInt().convertBytes;
} }
int deviceIdx(String? device) { int deviceIdx(String? device) {

View File

@@ -57,4 +57,9 @@ class ServerPrivateInfo {
bool shouldReconnect(ServerPrivateInfo old) { bool shouldReconnect(ServerPrivateInfo old) {
return id != old.id || pwd != old.pwd || pubKeyId != old.pubKeyId; return id != old.id || pwd != old.pwd || pubKeyId != old.pubKeyId;
} }
@override
String toString() {
return id;
}
} }

View File

@@ -218,7 +218,7 @@ class ServerProvider extends BusyProvider {
s.client = await genClient(spi); s.client = await genClient(spi);
final time2 = DateTime.now(); final time2 = DateTime.now();
final spentTime = time2.difference(time1).inMilliseconds; final spentTime = time2.difference(time1).inMilliseconds;
_logger.info('Connected to [$sid] in $spentTime ms.'); _logger.info('Connected to $sid in $spentTime ms.');
// after connected // after connected
s.state = ServerState.connected; s.state = ServerState.connected;

View File

@@ -24,7 +24,7 @@ class ServerStore extends PersistentStore {
void update(ServerPrivateInfo old, ServerPrivateInfo newInfo) { void update(ServerPrivateInfo old, ServerPrivateInfo newInfo) {
if (!have(old)) { if (!have(old)) {
throw Exception('Old ServerPrivateInfo not found'); throw Exception('Old spi: $old not found');
} }
delete(old.id); delete(old.id);
put(newInfo); put(newInfo);

View File

@@ -3,6 +3,7 @@ import 'package:toolbox/core/persistant_store.dart';
import 'package:toolbox/core/utils/platform.dart'; import 'package:toolbox/core/utils/platform.dart';
import 'package:toolbox/data/model/ssh/virtual_key.dart'; import 'package:toolbox/data/model/ssh/virtual_key.dart';
import '../model/app/net_view.dart';
import '../res/default.dart'; import '../res/default.dart';
class SettingStore extends PersistentStore { class SettingStore extends PersistentStore {
@@ -91,4 +92,7 @@ class SettingStore extends PersistentStore {
StoreProperty<List<VirtKey>> get sshVirtKeys => StoreProperty<List<VirtKey>> get sshVirtKeys =>
property('sshVirtKeys', defaultValue: defaultSSHVirtKeys); property('sshVirtKeys', defaultValue: defaultSSHVirtKeys);
StoreProperty<NetViewType> get netViewType =>
property('netViewType', defaultValue: NetViewType.speed);
} }

View File

@@ -81,7 +81,6 @@ class _ServerDetailPageState extends State<ServerDetailPage>
); );
}); });
}, },
buildDefaultDragHandles: false,
footer: height13, footer: height13,
children: _buildMainList(si.status), children: _buildMainList(si.status),
), ),
@@ -378,7 +377,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
SizedBox( SizedBox(
width: width, width: width,
child: Text( child: Text(
'${ns.speedIn(device: device)} | ${ns.totalIn(device: device)}', '${ns.speedIn(device: device)} | ${ns.sizeIn(device: device)}',
style: textSize11, style: textSize11,
textAlign: TextAlign.center, textAlign: TextAlign.center,
textScaleFactor: 0.87, textScaleFactor: 0.87,
@@ -387,7 +386,7 @@ class _ServerDetailPageState extends State<ServerDetailPage>
SizedBox( SizedBox(
width: width, width: width,
child: Text( child: Text(
'${ns.speedOut(device: device)} | ${ns.totalOut(device: device)}', '${ns.speedOut(device: device)} | ${ns.sizeOut(device: device)}',
style: textSize11, style: textSize11,
textAlign: TextAlign.right, textAlign: TextAlign.right,
textScaleFactor: 0.87, textScaleFactor: 0.87,

View File

@@ -7,6 +7,7 @@ import 'package:nil/nil.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:toolbox/core/extension/order.dart'; import 'package:toolbox/core/extension/order.dart';
import 'package:toolbox/core/utils/misc.dart'; import 'package:toolbox/core/utils/misc.dart';
import 'package:toolbox/data/model/app/net_view.dart';
import 'package:toolbox/data/model/server/snippet.dart'; import 'package:toolbox/data/model/server/snippet.dart';
import 'package:toolbox/data/provider/snippet.dart'; import 'package:toolbox/data/provider/snippet.dart';
import 'package:toolbox/view/page/process.dart'; import 'package:toolbox/view/page/process.dart';
@@ -48,6 +49,7 @@ class _ServerPageState extends State<ServerPage>
late ServerProvider _serverProvider; late ServerProvider _serverProvider;
late SettingStore _settingStore; late SettingStore _settingStore;
late S _s; late S _s;
late NetViewType _netViewType;
String? _tag; String? _tag;
@@ -56,6 +58,7 @@ class _ServerPageState extends State<ServerPage>
super.initState(); super.initState();
_serverProvider = locator<ServerProvider>(); _serverProvider = locator<ServerProvider>();
_settingStore = locator<SettingStore>(); _settingStore = locator<SettingStore>();
_netViewType = _settingStore.netViewType.fetch() ?? NetViewType.speed;
} }
@override @override
@@ -117,7 +120,6 @@ class _ServerPageState extends State<ServerPage>
all: _s.all, all: _s.all,
), ),
padding: const EdgeInsets.fromLTRB(7, 10, 7, 7), padding: const EdgeInsets.fromLTRB(7, 10, 7, 7),
buildDefaultDragHandles: false,
onReorder: (oldIndex, newIndex) => setState(() { onReorder: (oldIndex, newIndex) => setState(() {
pro.serverOrder.moveByItem( pro.serverOrder.moveByItem(
filtered, filtered,
@@ -173,7 +175,7 @@ class _ServerPageState extends State<ServerPage>
children: [ children: [
_buildPercentCircle(ss.cpu.usedPercent()), _buildPercentCircle(ss.cpu.usedPercent()),
_buildPercentCircle(ss.mem.usedPercent * 100), _buildPercentCircle(ss.mem.usedPercent * 100),
_buildIOData('Conn:\n${ss.tcp.maxConn}', 'Fail:\n${ss.tcp.fail}'), _buildNet(ss),
_buildIOData( _buildIOData(
'Total:\n${rootDisk.size}', 'Used:\n${rootDisk.usedPercent}%') 'Total:\n${rootDisk.size}', 'Used:\n${rootDisk.usedPercent}%')
], ],
@@ -330,6 +332,14 @@ class _ServerPageState extends State<ServerPage>
); );
} }
Widget _buildNet(ServerStatus ss) {
final data = _netViewType.build(ss);
return AnimatedSwitcher(
duration: const Duration(milliseconds: 177),
child: _buildIOData(data.up, data.down),
);
}
Widget _buildExplainText(String text) { Widget _buildExplainText(String text) {
return SizedBox( return SizedBox(
width: _media.size.width * 0.2, width: _media.size.width * 0.2,

View File

@@ -10,6 +10,7 @@ import 'package:shared_preferences/shared_preferences.dart';
import 'package:toolbox/core/extension/locale.dart'; import 'package:toolbox/core/extension/locale.dart';
import 'package:toolbox/core/extension/navigator.dart'; import 'package:toolbox/core/extension/navigator.dart';
import 'package:toolbox/core/route.dart'; import 'package:toolbox/core/route.dart';
import 'package:toolbox/data/model/app/net_view.dart';
import 'package:toolbox/data/model/app/tab.dart'; import 'package:toolbox/data/model/app/tab.dart';
import 'package:toolbox/view/page/ssh/virt_key_setting.dart'; import 'package:toolbox/view/page/ssh/virt_key_setting.dart';
import 'package:toolbox/view/widget/input_field.dart'; import 'package:toolbox/view/widget/input_field.dart';
@@ -47,6 +48,7 @@ class _SettingPageState extends State<SettingPage> {
final _editorDarkThemeKey = GlobalKey<PopupMenuButtonState<String>>(); final _editorDarkThemeKey = GlobalKey<PopupMenuButtonState<String>>();
final _keyboardTypeKey = GlobalKey<PopupMenuButtonState<int>>(); final _keyboardTypeKey = GlobalKey<PopupMenuButtonState<int>>();
final _rotateQuarterKey = GlobalKey<PopupMenuButtonState<int>>(); final _rotateQuarterKey = GlobalKey<PopupMenuButtonState<int>>();
final _netViewTypeKey = GlobalKey<PopupMenuButtonState<NetViewType>>();
late final SettingStore _setting; late final SettingStore _setting;
late final ServerProvider _serverProvider; late final ServerProvider _serverProvider;
@@ -65,6 +67,7 @@ class _SettingPageState extends State<SettingPage> {
final _editorDarkTheme = ValueNotifier(''); final _editorDarkTheme = ValueNotifier('');
final _keyboardType = ValueNotifier(0); final _keyboardType = ValueNotifier(0);
final _rotateQuarter = ValueNotifier(0); final _rotateQuarter = ValueNotifier(0);
final _netViewType = ValueNotifier(NetViewType.speed);
final _pushToken = ValueNotifier<String?>(null); final _pushToken = ValueNotifier<String?>(null);
@@ -91,6 +94,7 @@ class _SettingPageState extends State<SettingPage> {
_editorDarkTheme.value = _setting.editorDarkTheme.fetch()!; _editorDarkTheme.value = _setting.editorDarkTheme.fetch()!;
_keyboardType.value = _setting.keyboardType.fetch()!; _keyboardType.value = _setting.keyboardType.fetch()!;
_rotateQuarter.value = _setting.fullScreenRotateQuarter.fetch()!; _rotateQuarter.value = _setting.fullScreenRotateQuarter.fetch()!;
_netViewType.value = _setting.netViewType.fetch()!;
SharedPreferences.getInstance().then((value) => _sp = value); SharedPreferences.getInstance().then((value) => _sp = value);
} }
@@ -164,6 +168,7 @@ class _SettingPageState extends State<SettingPage> {
Widget _buildServer() { Widget _buildServer() {
return Column( return Column(
children: [ children: [
_buildNetViewType(),
_buildUpdateInterval(), _buildUpdateInterval(),
_buildMaxRetry(), _buildMaxRetry(),
_buildDiskIgnorePath(), _buildDiskIgnorePath(),
@@ -795,7 +800,7 @@ class _SettingPageState extends State<SettingPage> {
'none', 'none',
]; ];
if (names.length != TextInputType.values.length) { if (names.length != TextInputType.values.length) {
throw 'names.length != TextInputType.values.length'; throw Exception('names.length != TextInputType.values.length');
} }
final items = TextInputType.values.map( final items = TextInputType.values.map(
(key) { (key) {
@@ -892,4 +897,35 @@ class _SettingPageState extends State<SettingPage> {
}, },
); );
} }
Widget _buildNetViewType() {
final items = NetViewType.values
.map((e) => PopupMenuItem(
value: e,
child: Text(e.name),
))
.toList();
return ListTile(
title: Text('net view type'),
trailing: ValueBuilder(
listenable: _netViewType,
build: () => PopupMenuButton<NetViewType>(
key: _netViewTypeKey,
itemBuilder: (BuildContext context) => items,
initialValue: _netViewType.value,
onSelected: (idx) {
_netViewType.value = idx;
_setting.netViewType.put(idx);
},
child: Text(
_netViewType.value.name,
style: textSize15,
),
),
),
onTap: () {
_keyboardTypeKey.currentState?.showButtonMenu();
},
);
}
} }

View File

@@ -71,7 +71,6 @@ class _SnippetListPageState extends State<SnippetListPage> {
return ReorderableListView.builder( return ReorderableListView.builder(
padding: const EdgeInsets.all(13), padding: const EdgeInsets.all(13),
itemCount: filtered.length, itemCount: filtered.length,
buildDefaultDragHandles: false,
onReorder: (oldIdx, newIdx) => setState(() { onReorder: (oldIdx, newIdx) => setState(() {
provider.snippets.moveByItem( provider.snippets.moveByItem(
filtered, filtered,

View File

@@ -43,7 +43,6 @@ class _SSHVirtKeySettingPageState extends State<SSHVirtKeySettingPage> {
final allKeys = [...keys, ...disabled]; final allKeys = [...keys, ...disabled];
return ReorderableListView.builder( return ReorderableListView.builder(
padding: const EdgeInsets.fromLTRB(11, 3, 0, 3), padding: const EdgeInsets.fromLTRB(11, 3, 0, 3),
buildDefaultDragHandles: false,
itemBuilder: (_, idx) { itemBuilder: (_, idx) {
final key = allKeys[idx]; final key = allKeys[idx];
return ListTile( return ListTile(