diff --git a/analysis_options.yaml b/analysis_options.yaml index e37b312b..1f1fefa7 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -11,7 +11,7 @@ include: package:flutter_lints/flutter.yaml analyzer: exclude: - - '**/*.g.dart' + - "**/*.g.dart" language: # strict-casts: true # strict-inference: true @@ -43,8 +43,9 @@ linter: annotate_overrides: true avoid_empty_else: true # avoid_print: false # Uncomment to disable the `avoid_print` rule - prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule avoid_return_types_on_setters: true + directives_ordering: true # Enable sorting of imports # Additional information about this file can be found at # https://dart.dev/guides/language/analysis-options diff --git a/lib/app.dart b/lib/app.dart index e6c80cef..94b16c6f 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -2,14 +2,13 @@ import 'package:dynamic_color/dynamic_color.dart'; import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/generated/l10n/lib_l10n.dart'; import 'package:flutter/material.dart'; +import 'package:icons_plus/icons_plus.dart'; import 'package:responsive_framework/responsive_framework.dart'; - import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/data/res/build_data.dart'; import 'package:server_box/data/res/store.dart'; import 'package:server_box/generated/l10n/l10n.dart'; import 'package:server_box/view/page/home.dart'; -import 'package:icons_plus/icons_plus.dart'; part 'intro.dart'; diff --git a/lib/core/utils/server.dart b/lib/core/utils/server.dart index 943b67b0..9f7aea44 100644 --- a/lib/core/utils/server.dart +++ b/lib/core/utils/server.dart @@ -4,9 +4,8 @@ import 'package:dartssh2/dartssh2.dart'; import 'package:fl_lib/fl_lib.dart'; import 'package:flutter/foundation.dart'; import 'package:server_box/data/model/app/error.dart'; -import 'package:server_box/data/res/store.dart'; - import 'package:server_box/data/model/server/server_private_info.dart'; +import 'package:server_box/data/res/store.dart'; /// Must put this func out of any Class. /// diff --git a/lib/data/model/app/error.dart b/lib/data/model/app/error.dart index 50532d6c..15be42a3 100644 --- a/lib/data/model/app/error.dart +++ b/lib/data/model/app/error.dart @@ -1,5 +1,5 @@ -import 'package:server_box/core/extension/context/locale.dart'; import 'package:fl_lib/fl_lib.dart'; +import 'package:server_box/core/extension/context/locale.dart'; enum SSHErrType { unknown, diff --git a/lib/data/model/app/shell_func.dart b/lib/data/model/app/shell_func.dart index 9bb29615..63bfbb94 100644 --- a/lib/data/model/app/shell_func.dart +++ b/lib/data/model/app/shell_func.dart @@ -1,8 +1,7 @@ import 'package:server_box/core/extension/context/locale.dart'; -import 'package:server_box/data/provider/server.dart'; - -import 'package:server_box/data/res/build_data.dart'; import 'package:server_box/data/model/server/system.dart'; +import 'package:server_box/data/provider/server.dart'; +import 'package:server_box/data/res/build_data.dart'; enum ShellFunc { status, diff --git a/lib/data/model/app/tab.dart b/lib/data/model/app/tab.dart index 9ede20e9..0c36122a 100644 --- a/lib/data/model/app/tab.dart +++ b/lib/data/model/app/tab.dart @@ -1,11 +1,11 @@ import 'package:fl_lib/fl_lib.dart'; import 'package:flutter/material.dart'; +import 'package:icons_plus/icons_plus.dart'; import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/view/page/server/tab/tab.dart'; // import 'package:server_box/view/page/setting/entry.dart'; import 'package:server_box/view/page/snippet/list.dart'; import 'package:server_box/view/page/ssh/tab.dart'; -import 'package:icons_plus/icons_plus.dart'; import 'package:server_box/view/page/storage/local.dart'; enum AppTab { diff --git a/lib/data/model/server/server_private_info.dart b/lib/data/model/server/server_private_info.dart index 8d59203f..9e551804 100644 --- a/lib/data/model/server/server_private_info.dart +++ b/lib/data/model/server/server_private_info.dart @@ -3,16 +3,15 @@ import 'dart:convert'; import 'package:fl_lib/fl_lib.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:hive_ce_flutter/hive_flutter.dart'; +import 'package:server_box/data/model/app/error.dart'; import 'package:server_box/data/model/server/custom.dart'; import 'package:server_box/data/model/server/server.dart'; import 'package:server_box/data/model/server/wol_cfg.dart'; import 'package:server_box/data/provider/server.dart'; - -import 'package:server_box/data/model/app/error.dart'; import 'package:server_box/data/store/server.dart'; -part 'server_private_info.g.dart'; part 'server_private_info.freezed.dart'; +part 'server_private_info.g.dart'; /// In the first version, it's called `ServerPrivateInfo` which was designed to /// store the private information of a server. diff --git a/lib/data/model/server/server_status_update_req.dart b/lib/data/model/server/server_status_update_req.dart index a717d1bd..fa126c67 100644 --- a/lib/data/model/server/server_status_update_req.dart +++ b/lib/data/model/server/server_status_update_req.dart @@ -1,16 +1,15 @@ import 'package:fl_lib/fl_lib.dart'; -import 'package:server_box/data/model/server/battery.dart'; -import 'package:server_box/data/model/server/nvdia.dart'; -import 'package:server_box/data/model/server/sensors.dart'; -import 'package:server_box/data/model/server/server.dart'; -import 'package:server_box/data/model/server/system.dart'; - import 'package:server_box/data/model/app/shell_func.dart'; +import 'package:server_box/data/model/server/battery.dart'; +import 'package:server_box/data/model/server/conn.dart'; import 'package:server_box/data/model/server/cpu.dart'; import 'package:server_box/data/model/server/disk.dart'; import 'package:server_box/data/model/server/memory.dart'; import 'package:server_box/data/model/server/net_speed.dart'; -import 'package:server_box/data/model/server/conn.dart'; +import 'package:server_box/data/model/server/nvdia.dart'; +import 'package:server_box/data/model/server/sensors.dart'; +import 'package:server_box/data/model/server/server.dart'; +import 'package:server_box/data/model/server/system.dart'; class ServerStatusUpdateReq { final ServerStatus ss; diff --git a/lib/data/provider/container.dart b/lib/data/provider/container.dart index f8a9b6b4..f2977e67 100644 --- a/lib/data/provider/container.dart +++ b/lib/data/provider/container.dart @@ -5,10 +5,10 @@ import 'package:dartssh2/dartssh2.dart'; import 'package:fl_lib/fl_lib.dart'; import 'package:flutter/material.dart'; import 'package:server_box/core/extension/ssh_client.dart'; +import 'package:server_box/data/model/app/error.dart'; import 'package:server_box/data/model/app/shell_func.dart'; import 'package:server_box/data/model/container/image.dart'; import 'package:server_box/data/model/container/ps.dart'; -import 'package:server_box/data/model/app/error.dart'; import 'package:server_box/data/model/container/type.dart'; import 'package:server_box/data/res/store.dart'; diff --git a/lib/data/provider/pve.dart b/lib/data/provider/pve.dart index 21febbd4..765a9ab4 100644 --- a/lib/data/provider/pve.dart +++ b/lib/data/provider/pve.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:io'; import 'package:computer/computer.dart'; +import 'package:dartssh2/dartssh2.dart'; import 'package:dio/dio.dart'; import 'package:dio/io.dart'; import 'package:fl_lib/fl_lib.dart'; @@ -10,7 +11,6 @@ import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/data/model/app/error.dart'; import 'package:server_box/data/model/server/pve.dart'; import 'package:server_box/data/model/server/server_private_info.dart'; -import 'package:dartssh2/dartssh2.dart'; typedef PveCtrlFunc = Future Function(String node, String id); diff --git a/lib/data/provider/server.dart b/lib/data/provider/server.dart index b873461a..ee0a6d0f 100644 --- a/lib/data/provider/server.dart +++ b/lib/data/provider/server.dart @@ -1,4 +1,5 @@ import 'dart:async'; + // import 'dart:io'; import 'package:computer/computer.dart'; @@ -6,18 +7,17 @@ import 'package:dartssh2/dartssh2.dart'; import 'package:fl_lib/fl_lib.dart'; import 'package:server_box/core/extension/ssh_client.dart'; import 'package:server_box/core/sync.dart'; +import 'package:server_box/core/utils/server.dart'; import 'package:server_box/core/utils/ssh_auth.dart'; import 'package:server_box/data/model/app/error.dart'; import 'package:server_box/data/model/app/shell_func.dart'; -import 'package:server_box/data/model/server/system.dart'; -import 'package:server_box/data/res/store.dart'; - -import 'package:server_box/core/utils/server.dart'; import 'package:server_box/data/model/server/server.dart'; import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/server/server_status_update_req.dart'; +import 'package:server_box/data/model/server/system.dart'; import 'package:server_box/data/model/server/try_limiter.dart'; import 'package:server_box/data/res/status.dart'; +import 'package:server_box/data/res/store.dart'; class ServerProvider extends Provider { const ServerProvider._(); diff --git a/lib/data/res/status.dart b/lib/data/res/status.dart index a158061a..ce241882 100644 --- a/lib/data/res/status.dart +++ b/lib/data/res/status.dart @@ -1,12 +1,11 @@ -import 'package:server_box/data/model/server/server.dart'; -import 'package:server_box/data/model/server/temp.dart'; - +import 'package:server_box/data/model/server/conn.dart'; import 'package:server_box/data/model/server/cpu.dart'; import 'package:server_box/data/model/server/disk.dart'; import 'package:server_box/data/model/server/memory.dart'; import 'package:server_box/data/model/server/net_speed.dart'; -import 'package:server_box/data/model/server/conn.dart'; +import 'package:server_box/data/model/server/server.dart'; import 'package:server_box/data/model/server/system.dart'; +import 'package:server_box/data/model/server/temp.dart'; abstract final class InitStatus { static SingleCpuCore get _initOneTimeCpuStatus => SingleCpuCore( diff --git a/lib/data/store/setting.dart b/lib/data/store/setting.dart index 0a69d345..92772430 100644 --- a/lib/data/store/setting.dart +++ b/lib/data/store/setting.dart @@ -2,10 +2,9 @@ import 'dart:convert'; import 'package:fl_lib/fl_lib.dart'; import 'package:server_box/data/model/app/menu/server_func.dart'; +import 'package:server_box/data/model/app/net_view.dart'; import 'package:server_box/data/model/app/server_detail_card.dart'; import 'package:server_box/data/model/ssh/virtual_key.dart'; - -import 'package:server_box/data/model/app/net_view.dart'; import 'package:server_box/data/res/default.dart'; class SettingStore extends HiveStore { diff --git a/lib/view/page/backup.dart b/lib/view/page/backup.dart index db9375a9..ad33c308 100644 --- a/lib/view/page/backup.dart +++ b/lib/view/page/backup.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'package:computer/computer.dart'; import 'package:fl_lib/fl_lib.dart'; import 'package:flutter/material.dart'; +import 'package:icons_plus/icons_plus.dart'; import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/core/sync.dart'; import 'package:server_box/data/model/app/bak/backup2.dart'; @@ -13,7 +14,6 @@ import 'package:server_box/data/model/server/snippet.dart'; import 'package:server_box/data/provider/snippet.dart'; import 'package:server_box/data/res/misc.dart'; import 'package:server_box/data/res/store.dart'; -import 'package:icons_plus/icons_plus.dart'; import 'package:webdav_client_plus/webdav_client_plus.dart'; class BackupPage extends StatefulWidget { diff --git a/lib/view/page/container.dart b/lib/view/page/container.dart index 65bba8eb..716f751d 100644 --- a/lib/view/page/container.dart +++ b/lib/view/page/container.dart @@ -8,12 +8,11 @@ import 'package:server_box/core/route.dart'; import 'package:server_box/data/model/app/menu/base.dart'; import 'package:server_box/data/model/app/menu/container.dart'; import 'package:server_box/data/model/container/image.dart'; -import 'package:server_box/data/model/container/type.dart'; -import 'package:server_box/data/res/store.dart'; - import 'package:server_box/data/model/container/ps.dart'; +import 'package:server_box/data/model/container/type.dart'; import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/provider/container.dart'; +import 'package:server_box/data/res/store.dart'; import 'package:server_box/view/page/ssh/page/page.dart'; class ContainerPage extends StatefulWidget { diff --git a/lib/view/page/ping.dart b/lib/view/page/ping.dart index 81a27837..197c43bf 100644 --- a/lib/view/page/ping.dart +++ b/lib/view/page/ping.dart @@ -3,9 +3,8 @@ import 'dart:async'; import 'package:fl_lib/fl_lib.dart'; import 'package:flutter/material.dart'; import 'package:server_box/core/extension/context/locale.dart'; -import 'package:server_box/data/provider/server.dart'; - import 'package:server_box/data/model/server/ping_result.dart'; +import 'package:server_box/data/provider/server.dart'; /// Only permit ipv4 / ipv6 / domain chars final targetReg = RegExp(r'[a-zA-Z0-9\.-_:]+'); diff --git a/lib/view/page/private_key/edit.dart b/lib/view/page/private_key/edit.dart index fe470934..637980b1 100644 --- a/lib/view/page/private_key/edit.dart +++ b/lib/view/page/private_key/edit.dart @@ -5,11 +5,10 @@ import 'package:fl_lib/fl_lib.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:server_box/core/extension/context/locale.dart'; -import 'package:server_box/data/provider/private_key.dart'; -import 'package:server_box/data/res/misc.dart'; - import 'package:server_box/core/utils/server.dart'; import 'package:server_box/data/model/server/private_key_info.dart'; +import 'package:server_box/data/provider/private_key.dart'; +import 'package:server_box/data/res/misc.dart'; const _format = 'text/plain'; diff --git a/lib/view/page/private_key/list.dart b/lib/view/page/private_key/list.dart index 98164a84..499dea5c 100644 --- a/lib/view/page/private_key/list.dart +++ b/lib/view/page/private_key/list.dart @@ -1,13 +1,12 @@ -import 'dart:io'; import 'dart:async'; +import 'dart:io'; import 'package:fl_lib/fl_lib.dart'; import 'package:flutter/material.dart'; import 'package:server_box/core/extension/context/locale.dart'; -import 'package:server_box/data/res/store.dart'; - import 'package:server_box/data/model/server/private_key_info.dart'; import 'package:server_box/data/provider/private_key.dart'; +import 'package:server_box/data/res/store.dart'; import 'package:server_box/view/page/private_key/edit.dart'; class PrivateKeysListPage extends StatefulWidget { diff --git a/lib/view/page/process.dart b/lib/view/page/process.dart index e17ca0f6..ea4f299d 100644 --- a/lib/view/page/process.dart +++ b/lib/view/page/process.dart @@ -5,11 +5,10 @@ import 'package:fl_lib/fl_lib.dart'; import 'package:flutter/material.dart'; import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/core/route.dart'; -import 'package:server_box/data/res/store.dart'; - import 'package:server_box/data/model/app/shell_func.dart'; import 'package:server_box/data/model/server/proc.dart'; import 'package:server_box/data/model/server/server_private_info.dart'; +import 'package:server_box/data/res/store.dart'; class ProcessPage extends StatefulWidget { final SpiRequiredArgs args; diff --git a/lib/view/page/pve.dart b/lib/view/page/pve.dart index fe8e22bc..cb301965 100644 --- a/lib/view/page/pve.dart +++ b/lib/view/page/pve.dart @@ -246,8 +246,8 @@ final class _PvePageState extends State { ], ), UIs.height7, - AvgWidthRow( - width: _media.size.width, + AvgSize( + totalSize: _media.size.width, padding: _kHorziPadding * 2 + 26, children: [ PercentCircle(percent: (item.cpu / item.maxcpu) * 100), @@ -323,8 +323,8 @@ final class _PvePageState extends State { ], ), UIs.height7, - AvgWidthRow( - width: _media.size.width, + AvgSize( + totalSize: _media.size.width, padding: _kHorziPadding * 2 + 26, children: [ PercentCircle(percent: (item.cpu / item.maxcpu) * 100), diff --git a/lib/view/page/server/detail/misc.dart b/lib/view/page/server/detail/misc.dart index 449cb1bb..d98da2e4 100644 --- a/lib/view/page/server/detail/misc.dart +++ b/lib/view/page/server/detail/misc.dart @@ -19,7 +19,7 @@ extension on _ServerDetailPageState { ); } - void _nTapGpuProcessItem(NvidiaSmiMemProcess process) { + void _onTapGpuProcessItem(NvidiaSmiMemProcess process) { context.showRoundDialog( title: '${process.pid}', titleMaxLines: 1, @@ -30,30 +30,18 @@ extension on _ServerDetailPageState { UIs.height13, Text('Memory: ${process.memory} MiB'), UIs.height13, - Text('Process: ${process.name}') + Text('Process: ${process.name}'), ], ), - actions: [ - TextButton( - onPressed: () => context.pop(), - child: Text(libL10n.close), - ) - ], + actions: [TextButton(onPressed: () => context.pop(), child: Text(libL10n.close))], ); } void _onTapCustomItem(MapEntry cmd) { context.showRoundDialog( title: cmd.key, - child: SingleChildScrollView( - child: Text(cmd.value, style: UIs.text13Grey), - ), - actions: [ - TextButton( - onPressed: () => context.pop(), - child: Text(libL10n.close), - ), - ], + child: SingleChildScrollView(child: Text(cmd.value, style: UIs.text13Grey)), + actions: [TextButton(onPressed: () => context.pop(), child: Text(libL10n.close))], ); } @@ -76,13 +64,18 @@ extension on _ServerDetailPageState { Pfs.copy(key); context.showSnackBar('${libL10n.copy} ${libL10n.success}'); } + + bool _getInitExpand(int len, [int? max]) { + if (!_collapse) return true; + if (_size.width > UIs.columnWidth) return true; + return len > 0 && len <= (max ?? 3); + } } enum _NetSortType { device, trans, - recv, - ; + recv; bool get isDevice => this == _NetSortType.device; bool get isIn => this == _NetSortType.recv; @@ -117,68 +110,55 @@ Widget _buildLineChart( bool curve = false, int verticalInterval = 20, }) { - return LineChart(LineChartData( - lineTouchData: LineTouchData( - touchTooltipData: LineTouchTooltipData( - tooltipPadding: const EdgeInsets.all(5), - tooltipBorderRadius: BorderRadius.circular(8), - getTooltipItems: (List touchedSpots) { - return touchedSpots.map((e) { - return LineTooltipItem( - '$tooltipPrefix${e.barIndex}: ${e.y.toStringAsFixed(2)}', - const TextStyle( - fontSize: 12, - fontWeight: FontWeight.bold, - ), - ); - }).toList(); + return LineChart( + LineChartData( + lineTouchData: LineTouchData( + touchTooltipData: LineTouchTooltipData( + tooltipPadding: const EdgeInsets.all(5), + tooltipBorderRadius: BorderRadius.circular(8), + getTooltipItems: (List touchedSpots) { + return touchedSpots.map((e) { + return LineTooltipItem( + '$tooltipPrefix${e.barIndex}: ${e.y.toStringAsFixed(2)}', + const TextStyle(fontSize: 12, fontWeight: FontWeight.bold), + ); + }).toList(); + }, + ), + handleBuiltInTouches: true, + ), + gridData: FlGridData( + show: true, + drawVerticalLine: false, + horizontalInterval: verticalInterval.toDouble(), + getDrawingHorizontalLine: (value) { + return const FlLine(color: Color.fromARGB(43, 88, 91, 94), strokeWidth: 1); }, ), - handleBuiltInTouches: true, - ), - gridData: FlGridData( - show: true, - drawVerticalLine: false, - horizontalInterval: verticalInterval.toDouble(), - getDrawingHorizontalLine: (value) { - return const FlLine( - color: Color.fromARGB(43, 88, 91, 94), - strokeWidth: 1, - ); - }, - ), - titlesData: FlTitlesData( - show: true, - rightTitles: const AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - topTitles: const AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - bottomTitles: const AxisTitles( - sideTitles: SideTitles(showTitles: false), - ), - leftTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - interval: 20, - getTitlesWidget: (val, meta) { - if (val % verticalInterval != 0) return UIs.placeholder; - if (val == 0) return const Text('0 %', style: UIs.text12Grey); - return Text( - val.toInt().toString(), - style: UIs.text12Grey, - ); - }, - reservedSize: 27, + titlesData: FlTitlesData( + show: true, + rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), + topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), + bottomTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)), + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + interval: 20, + getTitlesWidget: (val, meta) { + if (val % verticalInterval != 0) return UIs.placeholder; + if (val == 0) return const Text('0 %', style: UIs.text12Grey); + return Text(val.toInt().toString(), style: UIs.text12Grey); + }, + reservedSize: 27, + ), ), ), - ), - borderData: FlBorderData(show: false), - minY: -1, - maxY: 101, - lineBarsData: spots - .map((e) => LineChartBarData( + borderData: FlBorderData(show: false), + minY: -1, + maxY: 101, + lineBarsData: spots + .map( + (e) => LineChartBarData( spots: e, isCurved: curve, barWidth: 2, @@ -186,7 +166,9 @@ Widget _buildLineChart( color: UIs.primaryColor, dotData: const FlDotData(show: false), belowBarData: BarAreaData(show: false), - )) - .toList(), - )); + ), + ) + .toList(), + ), + ); } diff --git a/lib/view/page/server/detail/view.dart b/lib/view/page/server/detail/view.dart index f3fbd62f..6c8505f9 100644 --- a/lib/view/page/server/detail/view.dart +++ b/lib/view/page/server/detail/view.dart @@ -15,13 +15,13 @@ import 'package:server_box/data/model/server/dist.dart'; import 'package:server_box/data/model/server/net_speed.dart'; import 'package:server_box/data/model/server/nvdia.dart'; import 'package:server_box/data/model/server/sensors.dart'; +import 'package:server_box/data/model/server/server.dart'; import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/server/system.dart'; import 'package:server_box/data/res/store.dart'; import 'package:server_box/view/page/pve.dart'; import 'package:server_box/view/page/server/edit.dart'; import 'package:server_box/view/widget/server_func_btns.dart'; -import 'package:server_box/data/model/server/server.dart'; part 'misc.dart'; @@ -32,32 +32,26 @@ class ServerDetailPage extends StatefulWidget { @override State createState() => _ServerDetailPageState(); - static const route = AppRouteArg( - page: ServerDetailPage.new, - path: '/servers/detail', - ); + static const route = AppRouteArg(page: ServerDetailPage.new, path: '/servers/detail'); } class _ServerDetailPageState extends State with SingleTickerProviderStateMixin { - late final _cardBuildMap = Map.fromIterables( - ServerDetailCards.names, - [ - _buildAbout, - _buildCPUView, - _buildMemView, - _buildSwapView, - _buildGpuView, - _buildDiskView, - _buildNetView, - _buildSensors, - _buildTemperature, - _buildBatteries, - _buildPve, - _buildCustomCmd, - ], - ); + late final _cardBuildMap = Map.fromIterables(ServerDetailCards.names, [ + _buildAbout, + _buildCPUView, + _buildMemView, + _buildSwapView, + _buildGpuView, + _buildDiskView, + _buildNetView, + _buildSensors, + _buildTemperature, + _buildBatteries, + _buildPve, + _buildCustomCmd, + ]); - late MediaQueryData _media; + late Size _size; final List _cardsOrder = []; final _settings = Stores.setting; @@ -74,7 +68,7 @@ class _ServerDetailPageState extends State with SingleTickerPr @override void didChangeDependencies() { super.didChangeDependencies(); - _media = MediaQuery.of(context); + _size = MediaQuery.sizeOf(context); } @override @@ -100,14 +94,11 @@ class _ServerDetailPageState extends State with SingleTickerPr Widget _buildMainPage(Server si) { final buildFuncs = !Stores.setting.moveServerFuncs.fetch(); final logo = _buildLogo(si); - final children = [ - logo, - if (buildFuncs) ServerFuncBtns(spi: si.spi), - ]; + final children = [if (logo != null) logo, if (buildFuncs) ServerFuncBtns(spi: si.spi)]; for (final card in _cardsOrder) { - final buildFunc = _cardBuildMap[card]; - if (buildFunc != null) { - children.add(buildFunc(si)); + final child = _cardBuildMap[card]?.call(si); + if (child != null) { + children.add(child); } } @@ -121,36 +112,26 @@ class _ServerDetailPageState extends State with SingleTickerPr return CustomAppBar( title: Text( si.spi.name, - style: TextStyle( - fontSize: 20, - color: context.isDark ? Colors.white : Colors.black, - ), + style: TextStyle(fontSize: 20, color: context.isDark ? Colors.white : Colors.black), ), actions: [ - QrShareBtn( - data: si.spi.toJsonString(), - tip: si.spi.name, - tip2: '${l10n.server} ~ ServerBox', - ), + QrShareBtn(data: si.spi.toJsonString(), tip: si.spi.name, tip2: '${l10n.server} ~ ServerBox'), IconButton( icon: const Icon(Icons.edit), onPressed: () async { - final delete = await ServerEditPage.route.go( - context, - args: SpiRequiredArgs(si.spi), - ); + final delete = await ServerEditPage.route.go(context, args: SpiRequiredArgs(si.spi)); if (delete == true) { context.pop(); } }, - ) + ), ], ); } - Widget _buildLogo(Server si) { + Widget? _buildLogo(Server si) { var logoUrl = si.spi.custom?.logoUrl ?? _settings.serverLogoUrl.fetch().selfNotEmptyOrNull; - if (logoUrl == null) return UIs.placeholder; + if (logoUrl == null) return null; final dist = si.status.more[StatusCmdType.sys]?.dist; if (dist != null) { @@ -160,25 +141,23 @@ class _ServerDetailPageState extends State with SingleTickerPr return Padding( padding: const EdgeInsets.symmetric(vertical: 13), - child: ExtendedImage.network( - logoUrl, - cache: true, - height: _media.size.height * 0.2, + child: LayoutBuilder( + builder: (_, cons) { + if (logoUrl == null) return UIs.placeholder; + return ExtendedImage.network(logoUrl, cache: true, height: cons.maxWidth * 0.2); + }, ), ); } - Widget _buildAbout(Server si) { + Widget? _buildAbout(Server si) { final ss = si.status; return ExpandTile( key: ValueKey(ss.more.hashCode), // Use hashCode to avoid perf issue leading: const Icon(MingCute.information_fill, size: 20), initiallyExpanded: _getInitExpand(ss.more.entries.length), title: Text(libL10n.about), - childrenPadding: const EdgeInsets.symmetric( - horizontal: 17, - vertical: 11, - ), + childrenPadding: const EdgeInsets.symmetric(horizontal: 17, vertical: 11), children: ss.more.entries .map( (e) => Padding( @@ -186,16 +165,8 @@ class _ServerDetailPageState extends State with SingleTickerPr child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - Text( - e.key.i18n, - style: UIs.text13, - overflow: TextOverflow.ellipsis, - ), - Text( - e.value, - style: UIs.text13Grey, - overflow: TextOverflow.ellipsis, - ), + Text(e.key.i18n, style: UIs.text13, overflow: TextOverflow.ellipsis), + Text(e.value, style: UIs.text13Grey, overflow: TextOverflow.ellipsis), ], ), ), @@ -204,13 +175,13 @@ class _ServerDetailPageState extends State with SingleTickerPr ).cardx; } - Widget _buildCPUView(Server si) { + Widget? _buildCPUView(Server si) { final ss = si.status; final percent = ss.cpu.usedPercent(coreIdx: 0).toInt(); final details = [ _buildDetailPercent(ss.cpu.user, 'user'), UIs.width13, - _buildDetailPercent(ss.cpu.idle, 'idle') + _buildDetailPercent(ss.cpu.idle, 'idle'), ]; if (ss.system == SystemType.linux) { details.addAll([ @@ -223,62 +194,41 @@ class _ServerDetailPageState extends State with SingleTickerPr final List children = Stores.setting.cpuViewAsProgress.fetch() ? _buildCPUProgress(ss.cpu) - : [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 17, vertical: 13), - child: SizedBox( - height: 137, - width: _media.size.width - 26 - 34, - child: _buildLineChart( - ss.cpu.spots, - //ss.cpu.rangeX, - tooltipPrefix: 'CPU', - ), - ), - ), - ]; + : [_buildCPUChart(ss)]; if (ss.cpu.brand.isNotEmpty) { - children.add(Column( - children: ss.cpu.brand.entries.map(_buildCpuModelItem).toList(), - ).paddingOnly(top: 13)); + children.add( + Column(children: ss.cpu.brand.entries.map(_buildCpuModelItem).toList()).paddingOnly(top: 13), + ); } return ExpandTile( title: Align( alignment: Alignment.centerLeft, - child: _buildAnimatedText( - ValueKey(percent), - '$percent%', - UIs.text27, - ), + child: _buildAnimatedText(ValueKey(percent), '$percent%', UIs.text27), ), childrenPadding: const EdgeInsets.symmetric(vertical: 13), initiallyExpanded: _getInitExpand(1), - trailing: Row( - mainAxisSize: MainAxisSize.min, - children: details, - ), + trailing: Row(mainAxisSize: MainAxisSize.min, children: details), children: children, ).cardx; } Widget _buildCpuModelItem(MapEntry e) { - final name = - e.key.replaceFirst('Intel(R)', '').replaceFirst('AMD', '').replaceFirst('with Radeon Graphics', ''); + final name = e.key + .replaceFirst('Intel(R)', '') + .replaceFirst('AMD', '') + .replaceFirst('with Radeon Graphics', ''); final child = Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - ConstrainedBox( - constraints: BoxConstraints( - maxWidth: _media.size.width * .7, - ), - child: Text( - name, - style: UIs.text13, - overflow: TextOverflow.ellipsis, - maxLines: 1, - ), + LayoutBuilder( + builder: (_, cons) { + return ConstrainedBox( + constraints: BoxConstraints(maxWidth: cons.maxWidth * .7), + child: Text(name, style: UIs.text13, overflow: TextOverflow.ellipsis, maxLines: 1), + ); + }, ), Text('x ${e.value}', style: UIs.text13Grey, overflow: TextOverflow.clip), ], @@ -292,16 +242,8 @@ class _ServerDetailPageState extends State with SingleTickerPr mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.end, children: [ - Text( - '${percent.toStringAsFixed(1)}%', - style: UIs.text12, - textScaler: _textFactor, - ), - Text( - timeType, - style: UIs.text12Grey, - textScaler: _textFactor, - ), + Text('${percent.toStringAsFixed(1)}%', style: UIs.text12, textScaler: _textFactor), + Text(timeType, style: UIs.text12Grey, textScaler: _textFactor), ], ); } @@ -341,9 +283,7 @@ class _ServerDetailPageState extends State with SingleTickerPr children.add( Padding( padding: const EdgeInsets.symmetric(horizontal: 17), - child: Row( - children: rowChildren.joinWith(UIs.width7).toList(), - ), + child: Row(children: rowChildren.joinWith(UIs.width7).toList()), ), ); } @@ -362,6 +302,25 @@ class _ServerDetailPageState extends State with SingleTickerPr return children; } + Widget _buildCPUChart(ServerStatus ss) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 17, vertical: 13), + child: LayoutBuilder( + builder: (_, cons) { + return SizedBox( + height: 137, + width: cons.maxWidth, + child: _buildLineChart( + ss.cpu.spots, + //ss.cpu.rangeX, + tooltipPrefix: 'CPU', + ), + ); + }, + ), + ); + } + Widget _buildProgress(double percent) { if (percent > 100) percent = 100; final percentWithinOne = percent / 100; @@ -373,7 +332,7 @@ class _ServerDetailPageState extends State with SingleTickerPr ); } - Widget _buildMemView(Server si) { + Widget? _buildMemView(Server si) { final ss = si.status; final free = ss.mem.free / ss.mem.total * 100; final avail = ss.mem.availPercent * 100; @@ -384,10 +343,7 @@ class _ServerDetailPageState extends State with SingleTickerPr children: [ _buildAnimatedText(ValueKey(usedStr), '$usedStr%', UIs.text27), UIs.width7, - Text( - 'of ${(ss.mem.total * 1024).bytes2Str}', - style: UIs.text13Grey, - ) + Text('of ${(ss.mem.total * 1024).bytes2Str}', style: UIs.text13Grey), ], ); @@ -411,15 +367,16 @@ class _ServerDetailPageState extends State with SingleTickerPr ], ), UIs.height13, - _buildProgress(used) + _buildProgress(used), ], ), ).cardx; } - Widget _buildSwapView(Server si) { + Widget? _buildSwapView(Server si) { final ss = si.status; - if (ss.swap.total == 0) return UIs.placeholder; + if (ss.swap.total == 0) return null; + final used = ss.swap.usedPercent * 100; final cached = ss.swap.cached / ss.swap.total * 100; @@ -427,10 +384,7 @@ class _ServerDetailPageState extends State with SingleTickerPr children: [ Text('${used.toStringAsFixed(0)}%', style: UIs.text27), UIs.width7, - Text( - 'of ${(ss.swap.total * 1024).bytes2Str} ', - style: UIs.text13Grey, - ) + Text('of ${(ss.swap.total * 1024).bytes2Str} ', style: UIs.text13Grey), ], ); @@ -442,21 +396,19 @@ class _ServerDetailPageState extends State with SingleTickerPr children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - percentW, - _buildDetailPercent(cached, 'cached'), - ], + children: [percentW, _buildDetailPercent(cached, 'cached')], ), UIs.height13, - _buildProgress(used) + _buildProgress(used), ], ), ).cardx; } - Widget _buildGpuView(Server si) { + Widget? _buildGpuView(Server si) { final ss = si.status; - if (ss.nvidia == null || ss.nvidia?.isEmpty == true) return UIs.placeholder; + if (ss.nvidia == null || ss.nvidia?.isEmpty == true) return null; + final children = ss.nvidia?.map((e) => _buildGpuItem(e)).toList() ?? []; return ExpandTile( title: const Text('GPU'), @@ -486,10 +438,7 @@ class _ServerDetailPageState extends State with SingleTickerPr mainAxisAlignment: MainAxisAlignment.end, mainAxisSize: MainAxisSize.min, children: [ - IconButton( - onPressed: () => _onTapGpuItem(item), - icon: const Icon(Icons.info_outline, size: 17), - ), + IconButton(onPressed: () => _onTapGpuItem(item), icon: const Icon(Icons.info_outline, size: 17)), ], ), ); @@ -510,13 +459,13 @@ class _ServerDetailPageState extends State with SingleTickerPr textScaler: _textFactor, ), trailing: InkWell( - onTap: () => _nTapGpuProcessItem(process), + onTap: () => _onTapGpuProcessItem(process), child: const Icon(Icons.info_outline, size: 17), ), ); } - Widget _buildDiskView(Server si) { + Widget? _buildDiskView(Server si) { final ss = si.status; final children = []; @@ -526,7 +475,7 @@ class _ServerDetailPageState extends State with SingleTickerPr children.add(_buildDiskItemWithHierarchy(disk, ss, 0)); } - if (children.isEmpty) return UIs.placeholder; + if (children.isEmpty) return null; return ExpandTile( title: Text(l10n.disk), @@ -583,11 +532,7 @@ class _ServerDetailPageState extends State with SingleTickerPr style: UIs.text12, textScaler: _textFactor, ), - Text( - text, - style: UIs.text12Grey, - textScaler: _textFactor, - ) + Text(text, style: UIs.text12Grey, textScaler: _textFactor), ], ), ), @@ -604,21 +549,21 @@ class _ServerDetailPageState extends State with SingleTickerPr backgroundColor: UIs.halfAlpha, color: UIs.primaryColor, ), - Text('${disk.usedPercent}%', style: UIs.text12Grey) + Text('${disk.usedPercent}%', style: UIs.text12Grey), ], ), - ) + ), ], ), ); } - Widget _buildNetView(Server si) { + Widget? _buildNetView(Server si) { final ss = si.status; final ns = ss.netSpeed; final children = []; final devices = ns.devices; - if (devices.isEmpty) return UIs.placeholder; + if (devices.isEmpty) return null; devices.sort(_netSortType.value.getSortFunc(ns)); children.addAll(devices.map((e) => _buildNetSpeedItem(ns, e))); @@ -634,18 +579,12 @@ class _ServerDetailPageState extends State with SingleTickerPr onTap: () => _netSortType.value = val.next, child: AnimatedSwitcher( duration: const Duration(milliseconds: 377), - transitionBuilder: (child, animation) => FadeTransition( - opacity: animation, - child: child, - ), + transitionBuilder: (child, animation) => FadeTransition(opacity: animation, child: child), child: Row( children: [ const Icon(Icons.sort, size: 17), UIs.width7, - Text( - val.name, - style: UIs.text13Grey, - ), + Text(val.name, style: UIs.text13Grey), ], ), ), @@ -680,7 +619,7 @@ class _ServerDetailPageState extends State with SingleTickerPr '${ns.sizeIn(device: device)} | ${ns.sizeOut(device: device)}', style: UIs.text12Grey, textScaler: _textFactor, - ) + ), ], ), SizedBox( @@ -690,17 +629,16 @@ class _ServerDetailPageState extends State with SingleTickerPr textAlign: TextAlign.end, style: UIs.text13Grey, ), - ) + ), ], ), ); } - Widget _buildTemperature(Server si) { + Widget? _buildTemperature(Server si) { final ss = si.status; - if (ss.temps.isEmpty) { - return UIs.placeholder; - } + if (ss.temps.isEmpty) return null; + return CardX( child: ExpandTile( title: Text(l10n.temperature), @@ -729,11 +667,10 @@ class _ServerDetailPageState extends State with SingleTickerPr ); } - Widget _buildBatteries(Server si) { + Widget? _buildBatteries(Server si) { final ss = si.status; - if (ss.batteries.isEmpty) { - return UIs.placeholder; - } + if (ss.batteries.isEmpty) return null; + return CardX( child: ExpandTile( title: Text(l10n.battery), @@ -756,22 +693,16 @@ class _ServerDetailPageState extends State with SingleTickerPr crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('${battery.name}', style: UIs.text15), - Text( - '${battery.status.name} - ${battery.cycle}', - style: UIs.text13Grey, - ), + Text('${battery.status.name} - ${battery.cycle}', style: UIs.text13Grey), ], ), - Text( - '${battery.percent?.toStringAsFixed(0)}%', - style: UIs.text13Grey, - ), + Text('${battery.percent?.toStringAsFixed(0)}%', style: UIs.text13Grey), ], ), ); } - Widget _buildSensors(Server si) { + Widget? _buildSensors(Server si) { final ss = si.status; if (ss.sensors.isEmpty) return UIs.placeholder; return CardX( @@ -824,9 +755,9 @@ class _ServerDetailPageState extends State with SingleTickerPr ); } - Widget _buildPve(Server si) { + Widget? _buildPve(Server si) { final addr = si.spi.custom?.pveAddr; - if (addr == null || addr.isEmpty) return UIs.placeholder; + if (addr == null || addr.isEmpty) return null; return CardX( child: ListTile( title: const Text('PVE'), @@ -837,9 +768,9 @@ class _ServerDetailPageState extends State with SingleTickerPr ); } - Widget _buildCustomCmd(Server si) { + Widget? _buildCustomCmd(Server si) { final ss = si.status; - if (ss.customCmds.isEmpty) return UIs.placeholder; + if (ss.customCmds.isEmpty) return null; return CardX( child: ExpandTile( leading: const Icon(MingCute.command_line, size: 17), @@ -860,11 +791,7 @@ class _ServerDetailPageState extends State with SingleTickerPr if (!cmd.value.contains('\n')) return null; return GestureDetector( onTap: () => _onTapCustomItem(cmd), - child: const Icon( - Icons.info_outline, - size: 17, - color: Colors.grey, - ), + child: const Icon(Icons.info_outline, size: 17, color: Colors.grey), ); }, ), @@ -874,21 +801,8 @@ class _ServerDetailPageState extends State with SingleTickerPr Widget _buildAnimatedText(Key key, String text, TextStyle style) { return AnimatedSwitcher( duration: const Duration(milliseconds: 277), - child: Text( - key: key, - text, - style: style, - textScaler: _textFactor, - ), - transitionBuilder: (child, animation) => FadeTransition( - opacity: animation, - child: child, - ), + child: Text(key: key, text, style: style, textScaler: _textFactor), + transitionBuilder: (child, animation) => FadeTransition(opacity: animation, child: child), ); } - - bool _getInitExpand(int len, [int? max]) { - if (!_collapse) return true; - return len > 0 && len <= (max ?? 3); - } } diff --git a/lib/view/page/server/edit.dart b/lib/view/page/server/edit.dart index 0448f657..8c757cf9 100644 --- a/lib/view/page/server/edit.dart +++ b/lib/view/page/server/edit.dart @@ -8,11 +8,10 @@ import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/core/route.dart'; import 'package:server_box/data/model/server/custom.dart'; import 'package:server_box/data/model/server/server.dart'; -import 'package:server_box/data/model/server/wol_cfg.dart'; -import 'package:server_box/data/provider/server.dart'; - import 'package:server_box/data/model/server/server_private_info.dart'; +import 'package:server_box/data/model/server/wol_cfg.dart'; import 'package:server_box/data/provider/private_key.dart'; +import 'package:server_box/data/provider/server.dart'; import 'package:server_box/data/store/server.dart'; import 'package:server_box/view/page/private_key/edit.dart'; diff --git a/lib/view/page/server/tab/tab.dart b/lib/view/page/server/tab/tab.dart index 7af96dcd..c289a4df 100644 --- a/lib/view/page/server/tab/tab.dart +++ b/lib/view/page/server/tab/tab.dart @@ -10,26 +10,25 @@ import 'package:responsive_framework/responsive_framework.dart'; import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/core/extension/ssh_client.dart'; import 'package:server_box/core/route.dart'; +import 'package:server_box/data/model/app/net_view.dart'; import 'package:server_box/data/model/app/shell_func.dart'; +import 'package:server_box/data/model/server/server.dart'; +import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/server/try_limiter.dart'; +import 'package:server_box/data/provider/server.dart'; import 'package:server_box/data/res/build_data.dart'; import 'package:server_box/data/res/store.dart'; import 'package:server_box/view/page/server/detail/view.dart'; import 'package:server_box/view/page/server/edit.dart'; import 'package:server_box/view/page/setting/entry.dart'; import 'package:server_box/view/widget/percent_circle.dart'; - -import 'package:server_box/data/model/app/net_view.dart'; -import 'package:server_box/data/model/server/server.dart'; -import 'package:server_box/data/model/server/server_private_info.dart'; -import 'package:server_box/data/provider/server.dart'; import 'package:server_box/view/widget/server_func_btns.dart'; -part 'top_bar.dart'; part 'card_stat.dart'; -part 'utils.dart'; part 'content.dart'; part 'landscape.dart'; +part 'top_bar.dart'; +part 'utils.dart'; class ServerPage extends StatefulWidget { const ServerPage({super.key}); @@ -141,10 +140,7 @@ class _ServerPageState extends State with AutomaticKeepAliveClientMi }); } - Widget _buildBodySmall({ - required List filtered, - EdgeInsets? padding = const EdgeInsets.fromLTRB(0, 0, 5, 7), - }) { + Widget _buildBodySmall({required List filtered}) { if (filtered.isEmpty) { return Center(child: Text(libL10n.empty, textAlign: TextAlign.center)); } @@ -153,6 +149,9 @@ class _ServerPageState extends State with AutomaticKeepAliveClientMi builder: (_, cons) { // Calculate number of columns based on available width final columnsCount = math.max(1, (cons.maxWidth / UIs.columnWidth).floor()); + final padding = columnsCount > 1 + ? const EdgeInsets.fromLTRB(0, 0, 5, 7) + : const EdgeInsets.fromLTRB(7, 0, 7, 7); return Row( crossAxisAlignment: CrossAxisAlignment.start, @@ -176,10 +175,7 @@ class _ServerPageState extends State with AutomaticKeepAliveClientMi final vnode = ServerProvider.pick(id: serversInThisColumn[index]); if (vnode == null) return UIs.placeholder; - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 0), - child: vnode.listenVal(_buildEachServerCard), - ); + return vnode.listenVal(_buildEachServerCard); }, ), ); @@ -190,9 +186,7 @@ class _ServerPageState extends State with AutomaticKeepAliveClientMi } Widget _buildEachServerCard(Server? srv) { - if (srv == null) { - return UIs.placeholder; - } + if (srv == null) return UIs.placeholder; return CardX( key: Key(srv.spi.id + _tag.value), diff --git a/lib/view/page/setting/entry.dart b/lib/view/page/setting/entry.dart index 2b70ba96..7398d30b 100644 --- a/lib/view/page/setting/entry.dart +++ b/lib/view/page/setting/entry.dart @@ -4,17 +4,15 @@ import 'dart:io'; import 'package:fl_lib/fl_lib.dart'; import 'package:flutter/material.dart'; import 'package:flutter_highlight/theme_map.dart'; -import 'package:server_box/data/store/setting.dart'; - -import 'package:server_box/generated/l10n/l10n.dart'; import 'package:icons_plus/icons_plus.dart'; import 'package:server_box/core/extension/context/locale.dart'; +import 'package:server_box/data/model/app/net_view.dart'; +import 'package:server_box/data/res/build_data.dart'; import 'package:server_box/data/res/github_id.dart'; import 'package:server_box/data/res/store.dart'; import 'package:server_box/data/res/url.dart'; - -import 'package:server_box/data/model/app/net_view.dart'; -import 'package:server_box/data/res/build_data.dart'; +import 'package:server_box/data/store/setting.dart'; +import 'package:server_box/generated/l10n/l10n.dart'; import 'package:server_box/view/page/backup.dart'; import 'package:server_box/view/page/private_key/list.dart'; import 'package:server_box/view/page/setting/platform/android.dart'; @@ -26,12 +24,12 @@ import 'package:server_box/view/page/setting/seq/virt_key.dart'; part 'about.dart'; part 'entries/app.dart'; -part 'entries/ssh.dart'; -part 'entries/sftp.dart'; -part 'entries/server.dart'; -part 'entries/full_screen.dart'; part 'entries/container.dart'; part 'entries/editor.dart'; +part 'entries/full_screen.dart'; +part 'entries/server.dart'; +part 'entries/sftp.dart'; +part 'entries/ssh.dart'; const _kIconSize = 23.0; diff --git a/lib/view/page/ssh/page/page.dart b/lib/view/page/ssh/page/page.dart index 084a45cf..0c79a490 100644 --- a/lib/view/page/ssh/page/page.dart +++ b/lib/view/page/ssh/page/page.dart @@ -5,24 +5,26 @@ import 'package:dartssh2/dartssh2.dart'; import 'package:fl_lib/fl_lib.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:icons_plus/icons_plus.dart'; import 'package:provider/provider.dart'; + import 'package:server_box/core/chan.dart'; import 'package:server_box/core/extension/context/locale.dart'; -import 'package:server_box/core/utils/ssh_auth.dart'; import 'package:server_box/core/utils/server.dart'; +import 'package:server_box/core/utils/ssh_auth.dart'; +import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/server/snippet.dart'; +import 'package:server_box/data/model/ssh/virtual_key.dart'; import 'package:server_box/data/provider/snippet.dart'; import 'package:server_box/data/provider/virtual_keyboard.dart'; import 'package:server_box/data/res/store.dart'; +import 'package:server_box/data/res/terminal.dart'; import 'package:server_box/view/page/storage/sftp.dart'; + import 'package:wakelock_plus/wakelock_plus.dart'; import 'package:xterm/core.dart'; import 'package:xterm/ui.dart' hide TerminalThemes; -import 'package:server_box/data/model/server/server_private_info.dart'; -import 'package:server_box/data/model/ssh/virtual_key.dart'; -import 'package:server_box/data/res/terminal.dart'; - part 'init.dart'; part 'keyboard.dart'; part 'virt_key.dart'; @@ -50,18 +52,12 @@ final class SshPageArgs { class SSHPage extends StatefulWidget { final SshPageArgs args; - const SSHPage({ - super.key, - required this.args, - }); + const SSHPage({super.key, required this.args}); @override State createState() => SSHPageState(); - static const route = AppRouteArg( - page: SSHPage.new, - path: '/ssh/page', - ); + static const route = AppRouteArg(page: SSHPage.new, path: '/ssh/page'); } const _horizonPadding = 7.0; @@ -155,6 +151,11 @@ class SSHPageState extends State with AutomaticKeepAliveClientMixin, Af _handleEscKeyOrBackButton(); }, child: Scaffold( + appBar: CustomAppBar( + title: Text(widget.args.spi.name), + actions: [_buildCopyBtn, _buildKillBtn], + centerTitle: false, + ), backgroundColor: _terminalTheme.background, body: _buildBody(), bottomNavigationBar: isDesktop ? null : _buildBottom(), @@ -176,7 +177,7 @@ class SSHPageState extends State with AutomaticKeepAliveClientMixin, Af height: _media.size.height - _virtKeysHeight - _media.padding.bottom - _media.padding.top, child: Padding( padding: EdgeInsets.only( - top: widget.args.notFromTab ? CustomAppBar.sysStatusBarHeight : 0, + // top: widget.args.notFromTab ? CustomAppBar.sysStatusBarHeight : 0, left: _horizonPadding, right: _horizonPadding, ), @@ -192,10 +193,7 @@ class SSHPageState extends State with AutomaticKeepAliveClientMixin, Af autofocus: false, keyboardAppearance: _isDark ? Brightness.dark : Brightness.light, showToolbar: isMobile, - viewOffset: Offset( - 2 * _horizonPadding, - CustomAppBar.sysStatusBarHeight, - ), + viewOffset: Offset(2 * _horizonPadding, CustomAppBar.sysStatusBarHeight), hideScrollBar: false, focusNode: widget.args.focusNode, ), @@ -214,9 +212,11 @@ class SSHPageState extends State with AutomaticKeepAliveClientMixin, Af height: _virtKeysHeight, child: ChangeNotifierProvider( create: (_) => _keyboard, - builder: (_, __) => Consumer(builder: (_, __, ___) { - return _buildVirtualKey(); - }), + builder: (_, __) => Consumer( + builder: (_, __, ___) { + return _buildVirtualKey(); + }, + ), ), ), ), @@ -227,16 +227,11 @@ class SSHPageState extends State with AutomaticKeepAliveClientMixin, Af if (_horizonVirtKeys) { return SingleChildScrollView( scrollDirection: Axis.horizontal, - child: Row( - children: _virtKeysList.expand((e) => e).map(_buildVirtKeyItem).toList(), - ), + child: Row(children: _virtKeysList.expand((e) => e).map(_buildVirtKeyItem).toList()), ); } final rows = _virtKeysList.map((e) => Row(children: e.map(_buildVirtKeyItem).toList())).toList(); - return Column( - mainAxisSize: MainAxisSize.min, - children: rows, - ); + return Column(mainAxisSize: MainAxisSize.min, children: rows); } Widget _buildVirtKeyItem(VirtKey item) { @@ -253,11 +248,7 @@ class SSHPageState extends State with AutomaticKeepAliveClientMixin, Af } final child = item.icon != null - ? Icon( - item.icon, - size: 17, - color: _isDark ? Colors.white : Colors.black, - ) + ? Icon(item.icon, size: 17, color: _isDark ? Colors.white : Colors.black) : Text( item.text, style: TextStyle( @@ -286,6 +277,30 @@ class SSHPageState extends State with AutomaticKeepAliveClientMixin, Af ); } + Widget get _buildCopyBtn { + return Btn.icon( + icon: Icon(MingCute.copy_2_fill), + onTap: () { + final selected = terminalSelected; + if (selected == null || selected.isEmpty) { + return; + } + Pfs.copy(selected); + }, + ); + } + + Widget get _buildKillBtn { + return Btn.icon( + icon: Icon(MingCute.close_circle_fill), + onTap: () { + if (_client == null) return; + _client!.close(); + context.pop(); + }, + ); + } + @override bool get wantKeepAlive => true; diff --git a/lib/view/page/storage/local.dart b/lib/view/page/storage/local.dart index 08c553fc..2c0ce4cb 100644 --- a/lib/view/page/storage/local.dart +++ b/lib/view/page/storage/local.dart @@ -3,13 +3,12 @@ import 'dart:io'; import 'package:fl_lib/fl_lib.dart'; import 'package:flutter/material.dart'; import 'package:server_box/core/extension/context/locale.dart'; +import 'package:server_box/data/model/app/path_with_prefix.dart'; import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/sftp/worker.dart'; import 'package:server_box/data/provider/server.dart'; import 'package:server_box/data/provider/sftp.dart'; import 'package:server_box/data/res/misc.dart'; - -import 'package:server_box/data/model/app/path_with_prefix.dart'; import 'package:server_box/data/store/setting.dart'; import 'package:server_box/view/page/storage/sftp.dart'; import 'package:server_box/view/page/storage/sftp_mission.dart'; diff --git a/lib/view/page/storage/sftp.dart b/lib/view/page/storage/sftp.dart index 1537b07b..40ea2b84 100644 --- a/lib/view/page/storage/sftp.dart +++ b/lib/view/page/storage/sftp.dart @@ -4,6 +4,7 @@ import 'dart:io'; import 'package:dartssh2/dartssh2.dart'; import 'package:fl_lib/fl_lib.dart'; import 'package:flutter/material.dart'; +import 'package:icons_plus/icons_plus.dart'; import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/core/extension/sftpfile.dart'; import 'package:server_box/core/utils/comparator.dart'; @@ -20,8 +21,6 @@ import 'package:server_box/view/page/storage/sftp_mission.dart'; import 'package:server_box/view/widget/omit_start_text.dart'; import 'package:server_box/view/widget/unix_perm.dart'; -import 'package:icons_plus/icons_plus.dart'; - final class SftpPageArgs { final Spi spi; final bool isSelect; @@ -76,7 +75,7 @@ class _SftpPageState extends State with AfterLayoutMixin { return Scaffold( appBar: CustomAppBar( - title: TwoLineText(up: 'SFTP', down: widget.args.spi.name), + title: Text(widget.args.spi.name), actions: children, ), body: _buildFileView(), diff --git a/lib/view/page/systemd.dart b/lib/view/page/systemd.dart index 46138a2d..3e977fe2 100644 --- a/lib/view/page/systemd.dart +++ b/lib/view/page/systemd.dart @@ -55,7 +55,7 @@ final class _SystemdPageState extends State { curve: Curves.fastEaseInToSlowEaseOut, height: isBusy ? 30 : 0, child: isBusy - ? SizedLoading.small.paddingOnly(bottom: 7) + ? SizedLoading.medium : const SizedBox.shrink(), ), ), diff --git a/lib/view/widget/server_func_btns.dart b/lib/view/widget/server_func_btns.dart index 49ac8980..f6b27859 100644 --- a/lib/view/widget/server_func_btns.dart +++ b/lib/view/widget/server_func_btns.dart @@ -3,8 +3,11 @@ import 'dart:io'; import 'package:fl_lib/fl_lib.dart'; import 'package:flutter/material.dart'; import 'package:server_box/core/extension/context/locale.dart'; +import 'package:server_box/core/route.dart'; +import 'package:server_box/core/utils/server.dart'; import 'package:server_box/data/model/app/menu/base.dart'; import 'package:server_box/data/model/app/menu/server_func.dart'; +import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/server/snippet.dart'; import 'package:server_box/data/provider/server.dart'; import 'package:server_box/data/provider/snippet.dart'; @@ -16,10 +19,6 @@ import 'package:server_box/view/page/ssh/page/page.dart'; import 'package:server_box/view/page/storage/sftp.dart'; import 'package:server_box/view/page/systemd.dart'; -import 'package:server_box/core/route.dart'; -import 'package:server_box/core/utils/server.dart'; -import 'package:server_box/data/model/server/server_private_info.dart'; - class ServerFuncBtnsTopRight extends StatelessWidget { final Spi spi; diff --git a/pubspec.lock b/pubspec.lock index e891a91c..dc1c4b0c 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -481,8 +481,8 @@ packages: dependency: "direct main" description: path: "." - ref: "v1.0.314" - resolved-ref: "306b1ca5b7df6981ed3d09afbf97c6b3054c9d21" + ref: "v1.0.315" + resolved-ref: "8593608e8f78ea53f2b1fdad5d5395392870c0d3" url: "https://github.com/lppcg/fl_lib" source: git version: "0.0.1" diff --git a/pubspec.yaml b/pubspec.yaml index b00c94d2..8ff3ffc5 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -62,7 +62,7 @@ dependencies: fl_lib: git: url: https://github.com/lppcg/fl_lib - ref: v1.0.314 + ref: v1.0.315 dependency_overrides: # webdav_client_plus: