服务器状态页预览部分完成

This commit is contained in:
LollipopKit
2021-09-18 19:03:06 +08:00
parent 2c9b08264f
commit 962ef4ca48
12 changed files with 223 additions and 139 deletions

3
.gitignore vendored
View File

@@ -44,3 +44,6 @@ app.*.map.json
/android/app/debug
/android/app/profile
/android/app/release
/android/app/fjy.androidstudio.key
/release

View File

@@ -6,6 +6,12 @@ if (localPropertiesFile.exists()) {
}
}
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
@@ -50,6 +56,15 @@ android {
versionName flutterVersionName
}
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
// TODO: Add your own signing config for the release build.

View File

@@ -2,8 +2,12 @@ PODS:
- countly_flutter (20.11.4):
- Flutter
- Flutter (1.0.0)
- GZ-NMSSH (4.1.5)
- path_provider (0.0.1):
- Flutter
- ssh2 (2.2.2):
- Flutter
- GZ-NMSSH (~> 4.1.5)
- url_launcher (0.0.1):
- Flutter
@@ -11,8 +15,13 @@ DEPENDENCIES:
- countly_flutter (from `.symlinks/plugins/countly_flutter/ios`)
- Flutter (from `Flutter`)
- path_provider (from `.symlinks/plugins/path_provider/ios`)
- ssh2 (from `.symlinks/plugins/ssh2/ios`)
- url_launcher (from `.symlinks/plugins/url_launcher/ios`)
SPEC REPOS:
trunk:
- GZ-NMSSH
EXTERNAL SOURCES:
countly_flutter:
:path: ".symlinks/plugins/countly_flutter/ios"
@@ -20,15 +29,19 @@ EXTERNAL SOURCES:
:path: Flutter
path_provider:
:path: ".symlinks/plugins/path_provider/ios"
ssh2:
:path: ".symlinks/plugins/ssh2/ios"
url_launcher:
:path: ".symlinks/plugins/url_launcher/ios"
SPEC CHECKSUMS:
countly_flutter: 38419412e193a1faa5babeb5d28a63fda260687d
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
GZ-NMSSH: d749f8ae2fd0094b953cd1d5abd8e0cab3c93f8d
path_provider: abfe2b5c733d04e238b0d8691db0cfd63a27a93c
ssh2: 5ded7906964d0e71e2204e5e031a155528df4674
url_launcher: 6fef411d543ceb26efce54b05a0a40bfd74cbbef
PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c
COCOAPODS: 1.10.2
COCOAPODS: 1.11.2

View File

@@ -0,0 +1,11 @@
import 'package:ssh2/ssh2.dart';
import 'package:toolbox/data/model/server_private_info.dart';
import 'package:toolbox/data/model/server_status.dart';
class ServerInfo {
ServerPrivateInfo info;
ServerStatus status;
SSHClient client;
ServerInfo(this.info, this.status, this.client);
}

View File

@@ -11,9 +11,9 @@ import 'package:toolbox/data/store/server.dart';
import 'package:toolbox/locator.dart';
class ServerProvider extends BusyProvider {
late List<ServerPrivateInfo> _servers;
late List<ServerStatus> _serversStatus;
late List<SSHClient> _clients;
List<ServerPrivateInfo> _servers = [];
List<ServerStatus> _serversStatus = [];
List<SSHClient> _clients = [];
List<ServerPrivateInfo> get servers => _servers;
List<ServerStatus> get serversStatus => _serversStatus;
@@ -23,11 +23,11 @@ class ServerProvider extends BusyProvider {
memList: [100, 0],
disk: [
DiskInfo(
mountLocation: '',
mountPath: '',
used: '',
size: '',
avail: '',
mountLocation: '/',
mountPath: '/',
used: '0',
size: '0',
avail: '0',
usedPercent: 0)
],
sysVer: '',
@@ -37,17 +37,35 @@ class ServerProvider extends BusyProvider {
Future<void> loadLocalData() async {
setBusyState(true);
_servers = locator<ServerStore>().fetch();
_serversStatus = List.generate(_servers.length, (_) => emptyStatus);
initStatusList();
setBusyState(false);
notifyListeners();
}
void initStatusList() {
_clients = List.generate(
_servers.length,
(idx) => SSHClient(
(idx) => _fillClient(idx));
_serversStatus = List.generate(_servers.length, (idx) => _fillStatus(idx));
}
SSHClient _fillClient(int idx) {
if (idx < _clients.length) {
return _clients[idx];
}
return SSHClient(
host: _servers[idx].ip!,
port: _servers[idx].port!,
username: _servers[idx].user!,
passwordOrKey: _servers[idx].authorization,
));
setBusyState(false);
notifyListeners();
);
}
ServerStatus _fillStatus(int idx) {
if (idx < _serversStatus.length) {
return _serversStatus[idx];
}
return emptyStatus;
}
Future<void> refreshData() async {
@@ -57,7 +75,7 @@ class ServerProvider extends BusyProvider {
}
Future<void> startAutoRefresh() async {
Timer.periodic(const Duration(seconds: 3), (_) async {
Timer.periodic(const Duration(seconds: 7), (_) async {
await refreshData();
});
}
@@ -65,12 +83,21 @@ class ServerProvider extends BusyProvider {
void addServer(ServerPrivateInfo info) {
_servers.add(info);
locator<ServerStore>().put(info);
initStatusList();
notifyListeners();
}
void delServer(ServerPrivateInfo info) {
_servers.remove(info);
locator<ServerStore>().delete(info);
initStatusList();
notifyListeners();
}
void updateServer(ServerPrivateInfo old, ServerPrivateInfo newInfo) {
_servers[_servers.indexOf(old)] = newInfo;
locator<ServerStore>().update(old, newInfo);
initStatusList();
notifyListeners();
}

View File

@@ -2,9 +2,8 @@
class BuildData {
static const String name = "ToolBox";
static const int build = 40;
static const String engine =
"Flutter 2.2.3 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision f4abaa0735 (9 weeks ago) • 2021-07-01 12:46:11 -0700\nEngine • revision 241c87ad80\nTools • Dart 2.13.4\n";
static const String buildAt = "2021-09-04 09:34:17.507782";
static const int modifications = 0;
static const int build = 10;
static const String engine = "Flutter 2.5.0 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision 4cc385b4b8 (10 days ago) • 2021-09-07 23:01:49 -0700\nEngine • revision f0826da7ef\nTools • Dart 2.14.0\n";
static const String buildAt = "2021-09-18 17:25:30.528659";
static const int modifications = 9;
}

View File

@@ -17,11 +17,18 @@ class ServerStore extends PersistentStore {
void delete(ServerPrivateInfo s) {
final ss = fetch();
ss.removeWhere((e) => e.ip == s.ip && e.port == s.port && e.user == e.user);
ss.removeAt(index(s));
box.put('servers', json.encode(ss));
}
bool have(ServerPrivateInfo s) => fetch()
.where((e) => e.ip == s.ip && e.port == s.port && e.user == e.user)
.isNotEmpty;
void update(ServerPrivateInfo old, ServerPrivateInfo newInfo) {
final ss = fetch();
ss[index(old)] = newInfo;
box.put('servers', json.encode(ss));
}
int index(ServerPrivateInfo s) => fetch()
.indexWhere((e) => e.ip == s.ip && e.port == s.port && e.user == e.user);
bool have(ServerPrivateInfo s) => index(s) != -1;
}

View File

@@ -81,7 +81,15 @@ class _ServerPageState extends State<ServerPage>
onTap: () => FocusScope.of(context).requestFocus(FocusNode()),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
onPressed: () => showAddServerDialog(),
tooltip: 'add a server',
heroTag: 'server page fab',
child: const Icon(Icons.add),
),
);
}
void showAddServerDialog() {
showRoundDialog(context, '新建服务器连接', _buildTextInputField(context), [
TextButton(
onPressed: () => Navigator.of(context).pop(),
@@ -110,12 +118,6 @@ class _ServerPageState extends State<ServerPage>
},
child: const Text('连接'))
]);
},
tooltip: 'add a server',
heroTag: 'server page fab',
child: const Icon(Icons.add),
),
);
}
InputDecoration _buildDecoration(String label, {TextStyle? textStyle}) {
@@ -214,6 +216,13 @@ class _ServerPageState extends State<ServerPage>
for (var e in ss.memList!) {
memData.add(IndexPercent(ss.memList!.indexOf(e), e!.toInt()));
}
final mem1 = memData[1];
memData[1] = memData.last;
memData.last = mem1;
final rootDisk = ss.disk!.firstWhere((element) => element!.mountLocation == '/');
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
@@ -247,42 +256,45 @@ class _ServerPageState extends State<ServerPage>
ss.memList![1]! / ss.memList![0]! * 100, 'Mem', [
chart.Series<IndexPercent, int>(
id: 'Mem',
domainFn: (IndexPercent sales, _) => sales.id,
measureFn: (IndexPercent sales, _) => sales.percent,
domainFn: (IndexPercent mem, _) => mem.id,
measureFn: (IndexPercent mem, _) => mem.percent,
data: memData,
)
]),
_buildIOData('Net', ss.tcp!.maxConn!.toString(), '0kb/s'),
_buildIOData('Disk', '0kb/s', '0kb/s')
_buildIOData('Net', 'Conn:\n' + ss.tcp!.maxConn!.toString(), 'Fail:\n' + ss.tcp!.fail.toString()),
_buildIOData('Disk', 'Total:\n' + rootDisk!.size!, 'Used:\n' + rootDisk.usedPercent.toString() + '%')
],
)
),
],
);
}
Widget _buildIOData(String title, String up, String down) {
final statusTextStyle = TextStyle(fontSize: 11, color: _theme.textTheme.bodyText1!.color!.withAlpha(177));
return SizedBox(
width: _media.size.width * 0.2,
height: _media.size.height * 0.1,
child: Stack(
children: [
Positioned(
Positioned.fill(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'$up',
textAlign: TextAlign.start,
up,
style: statusTextStyle,
textAlign: TextAlign.center,
),
const SizedBox(height: 3),
Text(
'$down',
down + '\n',
style: statusTextStyle,
textAlign: TextAlign.center,
)
],
),
top: _media.size.height * 0.012,
left: 0,
right: 0,
),
),
Positioned(
child: Text(title, textAlign: TextAlign.center),
@@ -302,14 +314,11 @@ class _ServerPageState extends State<ServerPage>
child: Stack(
children: [
DonutPieChart(series),
Positioned(
child: Text(
'${percent.toStringAsFixed(1)}%',
Positioned.fill(
child: Center(child: Text(
'${percent.toStringAsFixed(1)}%\n',
textAlign: TextAlign.center,
),
left: 0,
right: 0,
top: _media.size.height * 0.03,
),),
),
Positioned(
child: Text(title, textAlign: TextAlign.center),

0
make.dart Normal file → Executable file
View File

View File

@@ -5,63 +5,63 @@ packages:
dependency: "direct main"
description:
name: after_layout
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
async:
dependency: transitive
description:
name: async
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.8.1"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
characters:
dependency: transitive
description:
name: characters
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
charcode:
dependency: transitive
description:
name: charcode
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.1"
charts_common:
dependency: transitive
description:
name: charts_common
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.11.0"
charts_flutter:
dependency: "direct main"
description:
name: charts_flutter
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.11.0"
clock:
dependency: transitive
description:
name: clock
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
collection:
dependency: transitive
description:
name: collection
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.15.0"
countly_flutter:
@@ -77,49 +77,49 @@ packages:
dependency: transitive
description:
name: crypto
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.1"
dio:
dependency: "direct main"
description:
name: dio
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
extended_image:
dependency: "direct main"
description:
name: extended_image
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "4.2.1"
extended_image_library:
dependency: transitive
description:
name: extended_image_library
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "3.1.0"
fake_async:
dependency: transitive
description:
name: fake_async
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
ffi:
dependency: transitive
description:
name: ffi
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.2"
file:
dependency: transitive
description:
name: file
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "6.1.2"
flutter:
@@ -131,21 +131,21 @@ packages:
dependency: "direct dev"
description:
name: flutter_lints
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.4"
flutter_plugin_android_lifecycle:
dependency: transitive
description:
name: flutter_plugin_android_lifecycle
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
flutter_staggered_animations:
dependency: "direct main"
description:
name: flutter_staggered_animations
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
flutter_test:
@@ -162,168 +162,168 @@ packages:
dependency: "direct main"
description:
name: get_it
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "7.2.0"
hive:
dependency: "direct main"
description:
name: hive
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.4"
hive_flutter:
dependency: "direct main"
description:
name: hive_flutter
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
http:
dependency: transitive
description:
name: http
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.13.3"
http_client_helper:
dependency: transitive
description:
name: http_client_helper
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
http_parser:
dependency: transitive
description:
name: http_parser
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "4.0.0"
intl:
dependency: transitive
description:
name: intl
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.17.0"
js:
dependency: transitive
description:
name: js
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.6.3"
lints:
dependency: transitive
description:
name: lints
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
logging:
dependency: transitive
description:
name: logging
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.1"
version: "1.0.2"
matcher:
dependency: transitive
description:
name: matcher
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.12.10"
meta:
dependency: transitive
description:
name: meta
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.7.0"
nested:
dependency: transitive
description:
name: nested
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.0.0"
path:
dependency: transitive
description:
name: path
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0"
path_provider:
dependency: transitive
description:
name: path_provider
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
version: "2.0.4"
path_provider_linux:
dependency: transitive
description:
name: path_provider_linux
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
version: "2.1.0"
path_provider_macos:
dependency: transitive
description:
name: path_provider_macos
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
path_provider_platform_interface:
dependency: transitive
description:
name: path_provider_platform_interface
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
path_provider_windows:
dependency: transitive
description:
name: path_provider_windows
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.3"
pedantic:
dependency: transitive
description:
name: pedantic
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.11.1"
platform:
dependency: transitive
description:
name: platform
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.2"
plugin_platform_interface:
dependency: transitive
description:
name: plugin_platform_interface
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.1"
process:
dependency: transitive
description:
name: process
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "4.2.3"
provider:
dependency: "direct main"
description:
name: provider
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.0"
sky_engine:
@@ -335,126 +335,126 @@ packages:
dependency: transitive
description:
name: source_span
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.1"
ssh2:
dependency: "direct main"
description:
name: ssh2
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.2"
stack_trace:
dependency: transitive
description:
name: stack_trace
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.10.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
string_scanner:
dependency: transitive
description:
name: string_scanner
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.2.0"
test_api:
dependency: transitive
description:
name: test_api
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.2"
typed_data:
dependency: transitive
description:
name: typed_data
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "1.3.0"
url_launcher:
dependency: "direct main"
description:
name: url_launcher
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "6.0.10"
url_launcher_linux:
dependency: transitive
description:
name: url_launcher_linux
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
url_launcher_macos:
dependency: transitive
description:
name: url_launcher_macos
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
url_launcher_platform_interface:
dependency: transitive
description:
name: url_launcher_platform_interface
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.4"
url_launcher_web:
dependency: transitive
description:
name: url_launcher_web
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.4"
url_launcher_windows:
dependency: transitive
description:
name: url_launcher_windows
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.0.2"
uuid:
dependency: transitive
description:
name: uuid
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "3.0.4"
vector_math:
dependency: transitive
description:
name: vector_math
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0"
win32:
dependency: transitive
description:
name: win32
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "2.2.9"
xdg_directories:
dependency: transitive
description:
name: xdg_directories
url: "https://pub.flutter-io.cn"
url: "https://pub.dartlang.org"
source: hosted
version: "0.2.0"
sdks: