mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 07:14:28 +01:00
#43 new: bsd base support
This commit is contained in:
@@ -470,7 +470,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 491;
|
||||
CURRENT_PROJECT_VERSION = 493;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||
@@ -478,7 +478,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.491;
|
||||
MARKETING_VERSION = 1.0.493;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@@ -602,7 +602,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 491;
|
||||
CURRENT_PROJECT_VERSION = 493;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||
@@ -610,7 +610,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.491;
|
||||
MARKETING_VERSION = 1.0.493;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@@ -628,7 +628,7 @@
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements;
|
||||
CURRENT_PROJECT_VERSION = 491;
|
||||
CURRENT_PROJECT_VERSION = 493;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = "Runner/Info-$(CONFIGURATION).plist";
|
||||
@@ -636,7 +636,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.491;
|
||||
MARKETING_VERSION = 1.0.493;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
@@ -657,7 +657,7 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 491;
|
||||
CURRENT_PROJECT_VERSION = 493;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -670,7 +670,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.491;
|
||||
MARKETING_VERSION = 1.0.493;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
|
||||
@@ -696,7 +696,7 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 491;
|
||||
CURRENT_PROJECT_VERSION = 493;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -709,7 +709,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.491;
|
||||
MARKETING_VERSION = 1.0.493;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -732,7 +732,7 @@
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 491;
|
||||
CURRENT_PROJECT_VERSION = 493;
|
||||
DEVELOPMENT_TEAM = BA88US33G6;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu11;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@@ -745,7 +745,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 1.0.491;
|
||||
MARKETING_VERSION = 1.0.493;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox.StatusWidget;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
|
||||
@@ -35,11 +35,19 @@ enum DockerMenuType {
|
||||
rm,
|
||||
logs,
|
||||
terminal,
|
||||
stats;
|
||||
//stats,
|
||||
;
|
||||
|
||||
static List<DockerMenuType> items(bool running) {
|
||||
if (running) {
|
||||
return [stop, restart, rm, logs, terminal, stats];
|
||||
return [
|
||||
stop,
|
||||
restart,
|
||||
rm,
|
||||
logs,
|
||||
terminal,
|
||||
//stats,
|
||||
];
|
||||
} else {
|
||||
return [start, rm, logs];
|
||||
}
|
||||
@@ -59,8 +67,8 @@ enum DockerMenuType {
|
||||
return Icons.logo_dev;
|
||||
case DockerMenuType.terminal:
|
||||
return Icons.terminal;
|
||||
case DockerMenuType.stats:
|
||||
return Icons.bar_chart;
|
||||
// case DockerMenuType.stats:
|
||||
// return Icons.bar_chart;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,8 +86,8 @@ enum DockerMenuType {
|
||||
return s.log;
|
||||
case DockerMenuType.terminal:
|
||||
return s.terminal;
|
||||
case DockerMenuType.stats:
|
||||
return s.stats;
|
||||
// case DockerMenuType.stats:
|
||||
// return s.stats;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
import '../../res/build_data.dart';
|
||||
import '../../res/server_cmd.dart';
|
||||
import '../server/system.dart';
|
||||
|
||||
const _cmdDivider = '\necho $seperator\n';
|
||||
|
||||
const _serverBoxDir = r'$HOME/.config/server_box';
|
||||
const _shellPath = '$_serverBoxDir/mobile_app.sh';
|
||||
|
||||
enum AppShellFuncType {
|
||||
status,
|
||||
docker;
|
||||
@@ -15,7 +20,7 @@ enum AppShellFuncType {
|
||||
}
|
||||
}
|
||||
|
||||
String get exec => 'sh $shellPath -$flag';
|
||||
String get exec => 'sh $_shellPath -$flag';
|
||||
|
||||
String get name {
|
||||
switch (this) {
|
||||
@@ -31,16 +36,20 @@ enum AppShellFuncType {
|
||||
String get cmd {
|
||||
switch (this) {
|
||||
case AppShellFuncType.status:
|
||||
return statusCmds.join(_cmdDivider);
|
||||
return '''
|
||||
result=\$(uname 2>&1 | grep "Linux")
|
||||
if [ "\$result" != "" ]; then
|
||||
${_statusCmds.join(_cmdDivider)}
|
||||
else
|
||||
${_bsdStatusCmd.join(_cmdDivider)}
|
||||
fi''';
|
||||
case AppShellFuncType.docker:
|
||||
return '''
|
||||
result=\$(docker version 2>&1)
|
||||
deniedStr="permission denied"
|
||||
containStr=\$(echo \$result | grep "\${deniedStr}")
|
||||
if [[ \$containStr != "" ]]; then
|
||||
${dockerCmds.join(_cmdDivider)}
|
||||
result=\$(docker version 2>&1 | grep "permission denied")
|
||||
if [ "\$result" != "" ]; then
|
||||
${_dockerCmds.join(_cmdDivider)}
|
||||
else
|
||||
${dockerCmds.map((e) => "sudo -S $e").join(_cmdDivider)}
|
||||
${_dockerCmds.map((e) => "sudo -S $e").join(_cmdDivider)}
|
||||
fi''';
|
||||
}
|
||||
}
|
||||
@@ -83,6 +92,7 @@ extension EnumX on Enum {
|
||||
}
|
||||
|
||||
enum StatusCmdType {
|
||||
echo,
|
||||
time,
|
||||
net,
|
||||
sys,
|
||||
@@ -94,12 +104,81 @@ enum StatusCmdType {
|
||||
tempType,
|
||||
tempVal,
|
||||
host,
|
||||
sysRhel;
|
||||
;
|
||||
}
|
||||
|
||||
/// Cmds for linux server
|
||||
const _statusCmds = [
|
||||
'echo $linuxSign',
|
||||
'date +%s',
|
||||
'cat /proc/net/dev',
|
||||
'cat /etc/*-release | grep PRETTY_NAME',
|
||||
'cat /proc/stat | grep cpu',
|
||||
'uptime',
|
||||
'cat /proc/net/snmp',
|
||||
'df -h',
|
||||
'cat /proc/meminfo',
|
||||
'cat /sys/class/thermal/thermal_zone*/type',
|
||||
'cat /sys/class/thermal/thermal_zone*/temp',
|
||||
'hostname',
|
||||
];
|
||||
|
||||
enum DockerCmdType {
|
||||
version,
|
||||
ps,
|
||||
stats,
|
||||
images;
|
||||
//stats,
|
||||
images,
|
||||
;
|
||||
}
|
||||
|
||||
const _dockerCmds = [
|
||||
'docker version',
|
||||
'docker ps -a',
|
||||
//'docker stats --no-stream',
|
||||
'docker image ls',
|
||||
];
|
||||
|
||||
enum BSDStatusCmdType {
|
||||
echo,
|
||||
time,
|
||||
net,
|
||||
sys,
|
||||
cpu,
|
||||
uptime,
|
||||
disk,
|
||||
mem,
|
||||
//temp,
|
||||
host,
|
||||
;
|
||||
}
|
||||
|
||||
/// Cmds for BSD server
|
||||
const _bsdStatusCmd = [
|
||||
'echo $bsdSign',
|
||||
'date +%s',
|
||||
'netstat -ibn',
|
||||
'uname -or',
|
||||
'top -l 1 | grep "CPU usage"',
|
||||
'uptime',
|
||||
'df -h',
|
||||
'top -l 1 | grep PhysMem',
|
||||
//'sysctl -a | grep temperature',
|
||||
'hostname',
|
||||
];
|
||||
|
||||
final _shellCmd = """
|
||||
#!/bin/sh
|
||||
#
|
||||
# Script for ServerBox app v1.0.${BuildData.build}
|
||||
#
|
||||
# DO NOT delete this file while app is running
|
||||
# DO NOT run multi ServerBox apps with different version at the same time
|
||||
|
||||
export LANG=en_US.UTF-8
|
||||
|
||||
${AppShellFuncType.shellScript}
|
||||
""";
|
||||
|
||||
final installShellCmd = "mkdir -p $_serverBoxDir && "
|
||||
"echo '$_shellCmd' > $_shellPath && "
|
||||
"chmod +x $_shellPath";
|
||||
|
||||
@@ -8,10 +8,10 @@ class DockerPsItem {
|
||||
late String status;
|
||||
late String ports;
|
||||
late String name;
|
||||
String? cpu;
|
||||
String? mem;
|
||||
String? net;
|
||||
String? disk;
|
||||
// String? cpu;
|
||||
// String? mem;
|
||||
// String? net;
|
||||
// String? disk;
|
||||
|
||||
DockerPsItem(
|
||||
this.containerId,
|
||||
@@ -41,19 +41,19 @@ class DockerPsItem {
|
||||
}
|
||||
}
|
||||
|
||||
void parseStats(String rawString) {
|
||||
if (rawString.isEmpty) {
|
||||
return;
|
||||
}
|
||||
final parts = rawString.split(_seperator);
|
||||
if (parts.length != 8) {
|
||||
return;
|
||||
}
|
||||
cpu = parts[2];
|
||||
mem = parts[3];
|
||||
net = parts[5];
|
||||
disk = parts[6];
|
||||
}
|
||||
// void parseStats(String rawString) {
|
||||
// if (rawString.isEmpty) {
|
||||
// return;
|
||||
// }
|
||||
// final parts = rawString.split(_seperator);
|
||||
// if (parts.length != 8) {
|
||||
// return;
|
||||
// }
|
||||
// cpu = parts[2];
|
||||
// mem = parts[3];
|
||||
// net = parts[5];
|
||||
// disk = parts[6];
|
||||
// }
|
||||
|
||||
bool get running => status.contains('Up ');
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'package:toolbox/data/res/status.dart';
|
||||
|
||||
import 'time_seq.dart';
|
||||
|
||||
class Cpus extends TimeSeq<OneTimeCpuStatus> {
|
||||
@@ -95,3 +97,22 @@ List<OneTimeCpuStatus> parseCPU(String raw) {
|
||||
}
|
||||
return cpus;
|
||||
}
|
||||
|
||||
final _bsdCpuPercentReg = RegExp(r'(\d+\.\d+)%');
|
||||
|
||||
/// TODO: Change this implementation to parse cpu status on BSD system
|
||||
///
|
||||
/// [raw]:
|
||||
/// CPU usage: 14.70% user, 12.76% sys, 72.52% idle
|
||||
Cpus parseBsdCpu(String raw) {
|
||||
final percents = _bsdCpuPercentReg
|
||||
.allMatches(raw)
|
||||
.map((e) => double.parse(e.group(1) ?? '0') * 100)
|
||||
.toList();
|
||||
if (percents.length != 3) return initCpuStatus;
|
||||
return initCpuStatus
|
||||
..now = [
|
||||
OneTimeCpuStatus('cpu', percents[0].toInt(), percents[1].toInt(), 0,
|
||||
percents[2].toInt(), 0, 0, 0)
|
||||
];
|
||||
}
|
||||
|
||||
@@ -115,3 +115,51 @@ List<NetSpeedPart> parseNetSpeed(String raw, int time) {
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
/// [raw] example:
|
||||
/// Name Mtu Network Address Ipkts Ierrs Ibytes Opkts Oerrs Obytes Coll
|
||||
/// lo0 16384 <Link#1> 17296531 0 2524959720 17296531 0 2524959720 0
|
||||
/// lo0 16384 127 127.0.0.1 17296531 - 2524959720 17296531 - 2524959720 -
|
||||
/// lo0 16384 ::1/128 ::1 17296531 - 2524959720 17296531 - 2524959720 -
|
||||
/// lo0 16384 fe80::1%lo0 fe80:1::1 17296531 - 2524959720 17296531 - 2524959720 -
|
||||
/// gif0* 1280 <Link#2> 0 0 0 0 0 0 0
|
||||
/// stf0* 1280 <Link#3> 0 0 0 0 0 0 0
|
||||
/// en0 1500 <Link#4> 22:20:xx:xx:xx:e6 739447 0 693997876 535600 0 79008877 0
|
||||
/// en0 1500 fe80::f1:xx fe80:4::f1:xxxx:9 739447 - 693997876 535600 - 79008877 -
|
||||
/// en0 1500 192.168.2 192.168.2.111 739447 - 693997876 535600 - 79008877 -
|
||||
/// en0 1500 fd6b:xxxx:3 fd6b:xxxx:xxxx:0: 739447 - 693997876 535600 - 79008877 -
|
||||
/// en1 1500 <Link#5> 88:d8:xx:xx:xx:1d 0 0 0 0 0 0 0
|
||||
/// utun0 1380 <Link#6> 0 0 0 3 0 280 0
|
||||
/// utun0 1380 fe80::xxxx: fe80:6::xxxx:xxxx 0 - 0 3 - 280 -
|
||||
/// utun1 2000 <Link#7> 0 0 0 3 0 280 0
|
||||
/// utun1 2000 fe80::xxxx: fe80:7::xxxx:xxxx 0 - 0 3 - 280 -
|
||||
/// utun2 1000 <Link#8> 0 0 0 3 0 280 0
|
||||
/// utun2 1000 fe80::xxxx: fe80:8::xxxx:xxx: 0 - 0 3 - 280 -
|
||||
/// utun4 9000 <Link#10> 746744 0 845373390 386111 0 424400998 0
|
||||
/// utun4 9000 198.18.0/16 198.18.0.1 746744 - 845373390 386111 - 424400998 -
|
||||
/// en2* 1500 <Link#11> 36:7c:xx:xx:xx:xx 0 0 0 0 0 0 0
|
||||
List<NetSpeedPart> parseBsdNetSpeed(String raw, int time) {
|
||||
final split = raw.split('\n');
|
||||
if (split.length < 2) {
|
||||
return [];
|
||||
}
|
||||
|
||||
final results = <NetSpeedPart>[];
|
||||
for (final item in split.sublist(1)) {
|
||||
final data = item.trim().split(RegExp(r'\s+'));
|
||||
final device = data[0];
|
||||
if (device.endsWith('*')) {
|
||||
continue;
|
||||
}
|
||||
if (results.any((element) => element.device == device)) {
|
||||
continue;
|
||||
}
|
||||
if (data.length != 11) {
|
||||
continue;
|
||||
}
|
||||
final bytesIn = BigInt.parse(data[6]);
|
||||
final bytesOut = BigInt.parse(data[9]);
|
||||
results.add(NetSpeedPart(device, bytesIn, bytesOut, time));
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:toolbox/data/model/server/system.dart';
|
||||
import 'package:toolbox/data/model/server/temp.dart';
|
||||
|
||||
import 'cpu.dart';
|
||||
@@ -16,6 +17,7 @@ class ServerStatus {
|
||||
Conn tcp;
|
||||
NetSpeed netSpeed;
|
||||
Temperatures temps;
|
||||
SystemType system;
|
||||
String? failedInfo;
|
||||
|
||||
ServerStatus({
|
||||
@@ -28,6 +30,7 @@ class ServerStatus {
|
||||
required this.netSpeed,
|
||||
required this.swap,
|
||||
required this.temps,
|
||||
required this.system,
|
||||
this.failedInfo,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import 'package:toolbox/data/model/server/system.dart';
|
||||
|
||||
import '../app/shell_func.dart';
|
||||
import 'cpu.dart';
|
||||
import 'disk.dart';
|
||||
@@ -9,11 +11,25 @@ import 'conn.dart';
|
||||
class ServerStatusUpdateReq {
|
||||
final ServerStatus ss;
|
||||
final List<String> segments;
|
||||
final SystemType system;
|
||||
|
||||
const ServerStatusUpdateReq(this.ss, this.segments);
|
||||
const ServerStatusUpdateReq({
|
||||
required this.system,
|
||||
required this.ss,
|
||||
required this.segments,
|
||||
});
|
||||
}
|
||||
|
||||
Future<ServerStatus> getStatus(ServerStatusUpdateReq req) async {
|
||||
switch (req.system) {
|
||||
case SystemType.linux:
|
||||
return _getLinuxStatus(req);
|
||||
case SystemType.bsd:
|
||||
return _getBsdStatus(req);
|
||||
}
|
||||
}
|
||||
|
||||
Future<ServerStatus> _getLinuxStatus(ServerStatusUpdateReq req) async {
|
||||
final segments = req.segments;
|
||||
|
||||
final time = int.parse(StatusCmdType.time.find(segments));
|
||||
@@ -24,7 +40,6 @@ Future<ServerStatus> getStatus(ServerStatusUpdateReq req) async {
|
||||
final sys = _parseSysVer(
|
||||
StatusCmdType.sys.find(segments),
|
||||
StatusCmdType.host.find(segments),
|
||||
StatusCmdType.sysRhel.find(segments),
|
||||
);
|
||||
if (sys != null) {
|
||||
req.ss.sysVer = sys;
|
||||
@@ -56,6 +71,30 @@ Future<ServerStatus> getStatus(ServerStatusUpdateReq req) async {
|
||||
return req.ss;
|
||||
}
|
||||
|
||||
Future<ServerStatus> _getBsdStatus(ServerStatusUpdateReq req) async {
|
||||
final segments = req.segments;
|
||||
|
||||
final time = int.parse(BSDStatusCmdType.time.find(segments));
|
||||
|
||||
final net = parseBsdNetSpeed(BSDStatusCmdType.net.find(segments), time);
|
||||
req.ss.netSpeed.update(net);
|
||||
|
||||
req.ss.sysVer = BSDStatusCmdType.sys.find(segments);
|
||||
|
||||
req.ss.cpu = parseBsdCpu(BSDStatusCmdType.cpu.find(segments));
|
||||
|
||||
//req.ss.mem = parseBsdMem(BSDStatusCmdType.mem.find(segments));
|
||||
|
||||
final uptime = _parseUpTime(BSDStatusCmdType.uptime.find(segments));
|
||||
if (uptime != null) {
|
||||
req.ss.uptime = uptime;
|
||||
}
|
||||
|
||||
req.ss.disk = parseDisk(BSDStatusCmdType.disk.find(segments));
|
||||
|
||||
return req.ss;
|
||||
}
|
||||
|
||||
// raw:
|
||||
// 19:39:15 up 61 days, 18:16, 1 user, load average: 0.00, 0.00, 0.00
|
||||
String? _parseUpTime(String raw) {
|
||||
@@ -69,17 +108,14 @@ String? _parseUpTime(String raw) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String? _parseSysVer(String raw, String hostname, String rawRhel) {
|
||||
String? _parseSysVer(String raw, String hostname) {
|
||||
try {
|
||||
final s = raw.split('=');
|
||||
if (s.length == 2) {
|
||||
return s[1].replaceAll('"', '').replaceFirst('\n', '');
|
||||
}
|
||||
} catch (e) {
|
||||
if (!rawRhel.contains('cat: /etc/redhat-release:')) {
|
||||
return rawRhel;
|
||||
} finally {
|
||||
// ignore: control_flow_in_finally
|
||||
return hostname.isEmpty ? null : hostname;
|
||||
}
|
||||
if (hostname.isNotEmpty) return hostname;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
34
lib/data/model/server/system.dart
Normal file
34
lib/data/model/server/system.dart
Normal file
@@ -0,0 +1,34 @@
|
||||
import 'package:toolbox/data/model/app/shell_func.dart';
|
||||
|
||||
enum SystemType {
|
||||
linux._(linuxSign),
|
||||
bsd._(bsdSign),
|
||||
;
|
||||
|
||||
final String value;
|
||||
|
||||
const SystemType._(this.value);
|
||||
|
||||
static SystemType? parse(String? value) {
|
||||
if (value == null) return null;
|
||||
switch (value) {
|
||||
case linuxSign:
|
||||
return SystemType.linux;
|
||||
case bsdSign:
|
||||
return SystemType.bsd;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
bool isSegmentsLenMatch(int len) {
|
||||
switch (this) {
|
||||
case SystemType.linux:
|
||||
return len == StatusCmdType.values.length;
|
||||
case SystemType.bsd:
|
||||
return len == BSDStatusCmdType.values.length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const linuxSign = 'linux';
|
||||
const bsdSign = 'bsd';
|
||||
@@ -1,5 +1,3 @@
|
||||
// ignore_for_file: prefer_final_fields
|
||||
|
||||
abstract class TimeSeq<T extends TimeSeqIface> {
|
||||
List<T> pre;
|
||||
List<T> now;
|
||||
|
||||
@@ -10,10 +10,11 @@ import 'package:toolbox/data/model/app/shell_func.dart';
|
||||
import 'package:toolbox/data/model/docker/image.dart';
|
||||
import 'package:toolbox/data/model/docker/ps.dart';
|
||||
import 'package:toolbox/data/model/app/error.dart';
|
||||
import 'package:toolbox/data/res/server_cmd.dart';
|
||||
import 'package:toolbox/data/store/docker.dart';
|
||||
import 'package:toolbox/locator.dart';
|
||||
|
||||
import '../res/server_cmd.dart';
|
||||
|
||||
final _dockerNotFound = RegExp(r'command not found|Unknown command');
|
||||
final _versionReg = RegExp(r'(Version:)\s+([0-9]+\.[0-9]+\.[0-9]+)');
|
||||
// eg: `Docker Engine - Community`
|
||||
@@ -72,7 +73,7 @@ class DockerProvider extends ChangeNotifier {
|
||||
|
||||
// Check result segments count
|
||||
final segments = raw.split(seperator);
|
||||
if (segments.length != dockerCmds.length) {
|
||||
if (segments.length != DockerCmdType.values.length) {
|
||||
error = DockerErr(type: DockerErrType.segmentsNotMatch);
|
||||
_logger.warning('Docker segments not match: ${segments.length}');
|
||||
notifyListeners();
|
||||
@@ -119,28 +120,28 @@ class DockerProvider extends ChangeNotifier {
|
||||
}
|
||||
|
||||
// Parse docker stats
|
||||
final statsRaw = DockerCmdType.stats.find(segments);
|
||||
try {
|
||||
final statsLines = statsRaw.split('\n');
|
||||
statsLines.removeWhere((element) => element.isEmpty);
|
||||
if (statsLines.isNotEmpty) statsLines.removeAt(0);
|
||||
for (var item in items!) {
|
||||
final statsLine = statsLines.firstWhere(
|
||||
(element) => element.contains(item.containerId),
|
||||
orElse: () => '',
|
||||
);
|
||||
if (statsLine.isEmpty) continue;
|
||||
item.parseStats(statsLine);
|
||||
}
|
||||
} catch (e, trace) {
|
||||
error = DockerErr(
|
||||
type: DockerErrType.parseStats,
|
||||
message: '$statsRaw\n-\n$e',
|
||||
);
|
||||
_logger.warning('Parse docker stats: $statsRaw', e, trace);
|
||||
} finally {
|
||||
notifyListeners();
|
||||
}
|
||||
// final statsRaw = DockerCmdType.stats.find(segments);
|
||||
// try {
|
||||
// final statsLines = statsRaw.split('\n');
|
||||
// statsLines.removeWhere((element) => element.isEmpty);
|
||||
// if (statsLines.isNotEmpty) statsLines.removeAt(0);
|
||||
// for (var item in items!) {
|
||||
// final statsLine = statsLines.firstWhere(
|
||||
// (element) => element.contains(item.containerId),
|
||||
// orElse: () => '',
|
||||
// );
|
||||
// if (statsLine.isEmpty) continue;
|
||||
// item.parseStats(statsLine);
|
||||
// }
|
||||
// } catch (e, trace) {
|
||||
// error = DockerErr(
|
||||
// type: DockerErrType.parseStats,
|
||||
// message: '$statsRaw\n-\n$e',
|
||||
// );
|
||||
// _logger.warning('Parse docker stats: $statsRaw', e, trace);
|
||||
// } finally {
|
||||
// notifyListeners();
|
||||
// }
|
||||
}
|
||||
|
||||
Future<void> _onPwd(String event, StreamSink<Uint8List> stdin) async {
|
||||
|
||||
@@ -3,6 +3,7 @@ import 'dart:async';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:toolbox/data/model/app/shell_func.dart';
|
||||
import 'package:toolbox/data/model/server/system.dart';
|
||||
|
||||
import '../../core/extension/order.dart';
|
||||
import '../../core/extension/uint8list.dart';
|
||||
@@ -265,18 +266,28 @@ class ServerProvider extends ChangeNotifier {
|
||||
|
||||
final raw = await s.client?.run(AppShellFuncType.status.exec).string;
|
||||
final segments = raw?.split(seperator).map((e) => e.trim()).toList();
|
||||
if (raw == null ||
|
||||
raw.isEmpty ||
|
||||
segments == null ||
|
||||
segments.length != StatusCmdType.values.length) {
|
||||
if (raw == null || raw.isEmpty || segments == null || segments.isEmpty) {
|
||||
_limiter.inc(sid);
|
||||
s.status.failedInfo = 'Seperate segments failed, raw:\n$raw';
|
||||
_setServerState(s, ServerState.failed);
|
||||
return;
|
||||
}
|
||||
|
||||
final systemType = SystemType.parse(segments[0]);
|
||||
if (systemType == null || !systemType.isSegmentsLenMatch(segments.length)) {
|
||||
_limiter.inc(sid);
|
||||
s.status.failedInfo = 'Segments not match: ${segments.length}';
|
||||
_setServerState(s, ServerState.failed);
|
||||
return;
|
||||
}
|
||||
s.status.system = systemType;
|
||||
|
||||
try {
|
||||
final req = ServerStatusUpdateReq(s.status, segments);
|
||||
final req = ServerStatusUpdateReq(
|
||||
ss: s.status,
|
||||
segments: segments,
|
||||
system: systemType,
|
||||
);
|
||||
s.status = await compute(getStatus, req);
|
||||
} catch (e, trace) {
|
||||
_limiter.inc(sid);
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
class BuildData {
|
||||
static const String name = "ServerBox";
|
||||
static const int build = 491;
|
||||
static const String engine = "3.10.6";
|
||||
static const String buildAt = "2023-08-20 23:32:07.343451";
|
||||
static const int modifications = 4;
|
||||
static const int build = 493;
|
||||
static const String engine = "3.13.0";
|
||||
static const String buildAt = "2023-08-22 16:14:41.022063";
|
||||
static const int modifications = 8;
|
||||
}
|
||||
|
||||
@@ -1,41 +1 @@
|
||||
import '../model/app/shell_func.dart';
|
||||
import 'build_data.dart';
|
||||
|
||||
const seperator = 'SrvBoxSep';
|
||||
const serverBoxDir = r'$HOME/.config/server_box';
|
||||
const shellPath = '$serverBoxDir/mobile_app.sh';
|
||||
|
||||
const statusCmds = [
|
||||
'date +%s',
|
||||
'cat /proc/net/dev',
|
||||
'cat /etc/os-release | grep PRETTY_NAME',
|
||||
'cat /proc/stat | grep cpu',
|
||||
'uptime',
|
||||
'cat /proc/net/snmp',
|
||||
'df -h',
|
||||
'cat /proc/meminfo',
|
||||
'cat /sys/class/thermal/thermal_zone*/type',
|
||||
'cat /sys/class/thermal/thermal_zone*/temp',
|
||||
'hostname',
|
||||
'cat /etc/redhat-release',
|
||||
];
|
||||
|
||||
const dockerCmds = [
|
||||
'docker version',
|
||||
'docker ps -a',
|
||||
'docker stats --no-stream',
|
||||
'docker image ls',
|
||||
];
|
||||
|
||||
final shellCmd = """
|
||||
# Script for app `${BuildData.name} v1.0.${BuildData.build}`
|
||||
# Delete this file while app is running will cause app crash
|
||||
|
||||
export LANG=en_US.UTF-8
|
||||
|
||||
${AppShellFuncType.shellScript}
|
||||
""";
|
||||
|
||||
final installShellCmd = "mkdir -p $serverBoxDir && "
|
||||
"echo '$shellCmd' > $shellPath && "
|
||||
"chmod +x $shellPath";
|
||||
|
||||
@@ -6,6 +6,7 @@ import '../model/server/memory.dart';
|
||||
import '../model/server/net_speed.dart';
|
||||
import '../model/server/server_status.dart';
|
||||
import '../model/server/conn.dart';
|
||||
import '../model/server/system.dart';
|
||||
|
||||
Memory get _initMemory => Memory(
|
||||
total: 1,
|
||||
@@ -38,8 +39,8 @@ NetSpeed get initNetSpeed => NetSpeed(
|
||||
[_initNetSpeedPart],
|
||||
);
|
||||
Swap get _initSwap => Swap(
|
||||
total: 1,
|
||||
free: 1,
|
||||
total: 0,
|
||||
free: 0,
|
||||
cached: 0,
|
||||
);
|
||||
ServerStatus get initStatus => ServerStatus(
|
||||
@@ -60,5 +61,6 @@ ServerStatus get initStatus => ServerStatus(
|
||||
tcp: Conn(maxConn: 0, active: 0, passive: 0, fail: 0),
|
||||
netSpeed: initNetSpeed,
|
||||
swap: _initSwap,
|
||||
system: SystemType.linux,
|
||||
temps: Temperatures(),
|
||||
);
|
||||
|
||||
@@ -474,24 +474,24 @@ class _DockerManagePageState extends State<DockerManagePage> {
|
||||
'Docker terminal',
|
||||
).go(context);
|
||||
break;
|
||||
case DockerMenuType.stats:
|
||||
showRoundDialog(
|
||||
context: context,
|
||||
title: Text(_s.stats),
|
||||
child: Text(
|
||||
'CPU: ${dItem.cpu}\n'
|
||||
'Mem: ${dItem.mem}\n'
|
||||
'Net: ${dItem.net}\n'
|
||||
'Block: ${dItem.disk}',
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => context.pop(),
|
||||
child: Text(_s.ok),
|
||||
),
|
||||
],
|
||||
);
|
||||
break;
|
||||
// case DockerMenuType.stats:
|
||||
// showRoundDialog(
|
||||
// context: context,
|
||||
// title: Text(_s.stats),
|
||||
// child: Text(
|
||||
// 'CPU: ${dItem.cpu}\n'
|
||||
// 'Mem: ${dItem.mem}\n'
|
||||
// 'Net: ${dItem.net}\n'
|
||||
// 'Block: ${dItem.disk}',
|
||||
// ),
|
||||
// actions: [
|
||||
// TextButton(
|
||||
// onPressed: () => context.pop(),
|
||||
// child: Text(_s.ok),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// break;
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
@@ -108,12 +108,6 @@ class _ServerPageState extends State<ServerPage>
|
||||
);
|
||||
}
|
||||
|
||||
List<String> _filterServers(ServerProvider pro) => pro.serverOrder
|
||||
.where((e) => pro.servers.containsKey(e))
|
||||
.where((e) =>
|
||||
_tag == null || (pro.servers[e]?.spi.tags?.contains(_tag) ?? false))
|
||||
.toList();
|
||||
|
||||
Widget _buildTagsSwitcher(ServerProvider provider) {
|
||||
return TagSwitcher(
|
||||
tags: provider.tags,
|
||||
@@ -224,14 +218,11 @@ class _ServerPageState extends State<ServerPage>
|
||||
) {
|
||||
final rootDisk = findRootDisk(ss.disk);
|
||||
late final List<Widget> children;
|
||||
double? height;
|
||||
if (cs != ServerState.finished) {
|
||||
height = 23.0;
|
||||
children = [
|
||||
_buildServerCardTitle(ss, cs, spi),
|
||||
];
|
||||
} else {
|
||||
height = 107;
|
||||
children = [
|
||||
_buildServerCardTitle(ss, cs, spi),
|
||||
height13,
|
||||
@@ -262,7 +253,7 @@ class _ServerPageState extends State<ServerPage>
|
||||
return AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 377),
|
||||
curve: Curves.fastEaseInToSlowEaseOut,
|
||||
height: height,
|
||||
height: _calcCardHeight(cs),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
@@ -355,38 +346,6 @@ class _ServerPageState extends State<ServerPage>
|
||||
);
|
||||
}
|
||||
|
||||
String _getTopRightStr(
|
||||
ServerState cs,
|
||||
double? temp,
|
||||
String upTime,
|
||||
String? failedInfo,
|
||||
) {
|
||||
switch (cs) {
|
||||
case ServerState.disconnected:
|
||||
return _s.disconnected;
|
||||
case ServerState.finished:
|
||||
final tempStr = temp == null ? '' : '${temp.toStringAsFixed(1)}°C';
|
||||
final items = [tempStr, upTime];
|
||||
final str = items.where((element) => element.isNotEmpty).join(' | ');
|
||||
if (str.isEmpty) return _s.noResult;
|
||||
return str;
|
||||
case ServerState.loading:
|
||||
return _s.serverTabLoading;
|
||||
case ServerState.connected:
|
||||
return _s.connected;
|
||||
case ServerState.connecting:
|
||||
return _s.serverTabConnecting;
|
||||
case ServerState.failed:
|
||||
if (failedInfo == null) {
|
||||
return _s.serverTabFailed;
|
||||
}
|
||||
if (failedInfo.contains('encypted')) {
|
||||
return _s.serverTabPlzSave;
|
||||
}
|
||||
return failedInfo;
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildIOData(String up, String down) {
|
||||
return Column(
|
||||
children: [
|
||||
@@ -448,4 +407,52 @@ class _ServerPageState extends State<ServerPage>
|
||||
}
|
||||
_serverProvider.startAutoRefresh();
|
||||
}
|
||||
|
||||
List<String> _filterServers(ServerProvider pro) => pro.serverOrder
|
||||
.where((e) => pro.servers.containsKey(e))
|
||||
.where((e) =>
|
||||
_tag == null || (pro.servers[e]?.spi.tags?.contains(_tag) ?? false))
|
||||
.toList();
|
||||
|
||||
String _getTopRightStr(
|
||||
ServerState cs,
|
||||
double? temp,
|
||||
String upTime,
|
||||
String? failedInfo,
|
||||
) {
|
||||
switch (cs) {
|
||||
case ServerState.disconnected:
|
||||
return _s.disconnected;
|
||||
case ServerState.finished:
|
||||
final tempStr = temp == null ? '' : '${temp.toStringAsFixed(1)}°C';
|
||||
final items = [tempStr, upTime];
|
||||
final str = items.where((element) => element.isNotEmpty).join(' | ');
|
||||
if (str.isEmpty) return _s.noResult;
|
||||
return str;
|
||||
case ServerState.loading:
|
||||
return _s.serverTabLoading;
|
||||
case ServerState.connected:
|
||||
return _s.connected;
|
||||
case ServerState.connecting:
|
||||
return _s.serverTabConnecting;
|
||||
case ServerState.failed:
|
||||
if (failedInfo == null) {
|
||||
return _s.serverTabFailed;
|
||||
}
|
||||
if (failedInfo.contains('encypted')) {
|
||||
return _s.serverTabPlzSave;
|
||||
}
|
||||
return failedInfo;
|
||||
}
|
||||
}
|
||||
|
||||
double _calcCardHeight(ServerState cs) {
|
||||
if (cs != ServerState.finished) {
|
||||
return 23.0;
|
||||
}
|
||||
if (_settingStore.moveOutServerTabFuncBtns.fetch()!) {
|
||||
return 132;
|
||||
}
|
||||
return 107;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ class _SSHPageState extends State<SSHPage> {
|
||||
deleteDetection: isIOS,
|
||||
autofocus: true,
|
||||
keyboardAppearance: _isDark ? Brightness.dark : Brightness.light,
|
||||
hideScrollBar: isMobile,
|
||||
hideScrollBar: false,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -60,7 +60,8 @@ class Input extends StatelessWidget {
|
||||
icon: icon != null ? Icon(icon) : null,
|
||||
border: InputBorder.none,
|
||||
errorText: errorText,
|
||||
prefix: prefix,),
|
||||
prefix: prefix,
|
||||
),
|
||||
controller: controller,
|
||||
obscureText: obscureText,
|
||||
),
|
||||
|
||||
@@ -258,7 +258,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 0920;
|
||||
LastUpgradeCheck = 1300;
|
||||
LastUpgradeCheck = 1430;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
331C80D4294CF70F00263BE5 = {
|
||||
@@ -474,9 +474,9 @@
|
||||
baseConfigurationReference = C1C758C41C4E208965A68933 /* Pods-RunnerTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CURRENT_PROJECT_VERSION = 491;
|
||||
CURRENT_PROJECT_VERSION = 493;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0.491;
|
||||
MARKETING_VERSION = 1.0.493;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = tech.lolli.serverBox.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -489,9 +489,9 @@
|
||||
baseConfigurationReference = 15AF97DF993E8968098D6EBE /* Pods-RunnerTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CURRENT_PROJECT_VERSION = 491;
|
||||
CURRENT_PROJECT_VERSION = 493;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0.491;
|
||||
MARKETING_VERSION = 1.0.493;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = tech.lolli.serverBox.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -504,9 +504,9 @@
|
||||
baseConfigurationReference = 7CFA7DE7FABA75685DFB6948 /* Pods-RunnerTests.profile.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CURRENT_PROJECT_VERSION = 491;
|
||||
CURRENT_PROJECT_VERSION = 493;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0.491;
|
||||
MARKETING_VERSION = 1.0.493;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = tech.lolli.serverBox.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1300"
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
76
make.dart
76
make.dart
@@ -17,6 +17,7 @@ const buildFuncs = {
|
||||
'ios': flutterBuildIOS,
|
||||
'android': flutterBuildAndroid,
|
||||
'macos': flutterBuildMacOS,
|
||||
'linux': flutterBuildLinux,
|
||||
};
|
||||
|
||||
int? build;
|
||||
@@ -133,15 +134,21 @@ Future<void> flutterBuildIOS() async {
|
||||
|
||||
Future<void> flutterBuildMacOS() async {
|
||||
await flutterBuild('macos');
|
||||
await scpMacOS2CDN();
|
||||
}
|
||||
|
||||
Future<void> flutterBuildAndroid() async {
|
||||
await flutterBuild('apk');
|
||||
await killJava();
|
||||
await scp2CDN();
|
||||
await scpApk2CDN();
|
||||
}
|
||||
|
||||
Future<void> scp2CDN() async {
|
||||
Future<void> flutterBuildLinux() async {
|
||||
await flutterBuild('linux');
|
||||
await scpLinux2CDN();
|
||||
}
|
||||
|
||||
Future<void> scpApk2CDN() async {
|
||||
final sha256 = await getFileSha256(apkPath);
|
||||
print('SHA256: $sha256');
|
||||
final result = await Process.run(
|
||||
@@ -155,6 +162,45 @@ Future<void> scp2CDN() async {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> scpMacOS2CDN() async {
|
||||
final zipName = '$build.app.zip';
|
||||
// Zip the .app
|
||||
await Process.run('zip', [
|
||||
'-r',
|
||||
'./release/$zipName',
|
||||
'./build/macos/Build/Products/Release/server_box.app',
|
||||
]);
|
||||
final result = await Process.run(
|
||||
'scp',
|
||||
[
|
||||
'./release/$zipName',
|
||||
'hk:/var/www/res/serverbox/$build.app.zip',
|
||||
],
|
||||
runInShell: true,
|
||||
);
|
||||
if (result.exitCode != 0) {
|
||||
print(result.stderr);
|
||||
exit(1);
|
||||
}
|
||||
print('Upload macOS $zipName finished.');
|
||||
}
|
||||
|
||||
Future<void> scpLinux2CDN() async {
|
||||
final result = await Process.run(
|
||||
'scp',
|
||||
[
|
||||
'./build/linux/x64/release/bundle/server_box.tar.gz',
|
||||
'hk:/var/www/res/serverbox/$build.tar.gz',
|
||||
],
|
||||
runInShell: true,
|
||||
);
|
||||
if (result.exitCode != 0) {
|
||||
print(result.stderr);
|
||||
exit(1);
|
||||
}
|
||||
print('Upload Linux $build.tar.gz finished.');
|
||||
}
|
||||
|
||||
Future<void> changeAppleVersion() async {
|
||||
for (final path in ['ios', 'macos']) {
|
||||
final file = File('$path/$appleXCConfigPath');
|
||||
@@ -185,38 +231,40 @@ void main(List<String> args) async {
|
||||
}
|
||||
|
||||
final command = args[0];
|
||||
|
||||
switch (command) {
|
||||
case 'build':
|
||||
final stopwatch = Stopwatch()..start();
|
||||
await dartFormat();
|
||||
await getGitCommitCount();
|
||||
// always change version to avoid dismatch version between different
|
||||
// platforms
|
||||
await changeAppleVersion();
|
||||
await updateBuildData();
|
||||
|
||||
final funcs = <Future<void> Function()>[];
|
||||
|
||||
if (args.length > 1) {
|
||||
final platforms = args[1];
|
||||
for (final platform in platforms.split(',')) {
|
||||
if (buildFuncs.keys.contains(platform)) {
|
||||
await buildFuncs[platform]!();
|
||||
print('Build finished in [${stopwatch.elapsed}]');
|
||||
stopwatch.reset();
|
||||
stopwatch.start();
|
||||
funcs.add(buildFuncs[platform]!);
|
||||
} else {
|
||||
print('Unknown platform: $platform');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
funcs.addAll(buildFuncs.values);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
for (final func in buildFuncs.values) {
|
||||
final stopwatch = Stopwatch();
|
||||
for (final func in funcs) {
|
||||
stopwatch.start();
|
||||
await func();
|
||||
}
|
||||
print('Build finished in ${stopwatch.elapsed}\n');
|
||||
return;
|
||||
stopwatch.reset();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
print('Unsupported command: $command');
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
34
pubspec.lock
34
pubspec.lock
@@ -182,10 +182,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
|
||||
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.17.1"
|
||||
version: "1.17.2"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -458,10 +458,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: intl
|
||||
sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6
|
||||
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.18.0"
|
||||
version: "0.18.1"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -522,18 +522,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
|
||||
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.15"
|
||||
version: "0.12.16"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
|
||||
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
version: "0.5.0"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -839,10 +839,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
|
||||
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
version: "1.10.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -887,10 +887,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
|
||||
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.1"
|
||||
version: "0.6.0"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1003,6 +1003,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.4-beta"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1061,5 +1069,5 @@ packages:
|
||||
source: hosted
|
||||
version: "0.0.6"
|
||||
sdks:
|
||||
dart: ">=3.0.0 <4.0.0"
|
||||
dart: ">=3.1.0-185.0.dev <4.0.0"
|
||||
flutter: ">=3.10.0"
|
||||
|
||||
Reference in New Issue
Block a user