opt.: server detail page columns

This commit is contained in:
lollipopkit🏳️‍⚧️
2025-06-04 17:29:03 +08:00
parent 1084c49a5f
commit 7127c960f7
32 changed files with 301 additions and 413 deletions

View File

@@ -11,7 +11,7 @@ include: package:flutter_lints/flutter.yaml
analyzer: analyzer:
exclude: exclude:
- '**/*.g.dart' - "**/*.g.dart"
language: language:
# strict-casts: true # strict-casts: true
# strict-inference: true # strict-inference: true
@@ -45,6 +45,7 @@ linter:
# avoid_print: false # Uncomment to disable the `avoid_print` rule # 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 avoid_return_types_on_setters: true
directives_ordering: true # Enable sorting of imports
# Additional information about this file can be found at # Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options # https://dart.dev/guides/language/analysis-options

View File

@@ -2,14 +2,13 @@ import 'package:dynamic_color/dynamic_color.dart';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:fl_lib/generated/l10n/lib_l10n.dart'; import 'package:fl_lib/generated/l10n/lib_l10n.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:icons_plus/icons_plus.dart';
import 'package:responsive_framework/responsive_framework.dart'; import 'package:responsive_framework/responsive_framework.dart';
import 'package:server_box/core/extension/context/locale.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/build_data.dart';
import 'package:server_box/data/res/store.dart'; import 'package:server_box/data/res/store.dart';
import 'package:server_box/generated/l10n/l10n.dart'; import 'package:server_box/generated/l10n/l10n.dart';
import 'package:server_box/view/page/home.dart'; import 'package:server_box/view/page/home.dart';
import 'package:icons_plus/icons_plus.dart';
part 'intro.dart'; part 'intro.dart';

View File

@@ -4,9 +4,8 @@ import 'package:dartssh2/dartssh2.dart';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:server_box/data/model/app/error.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/model/server/server_private_info.dart';
import 'package:server_box/data/res/store.dart';
/// Must put this func out of any Class. /// Must put this func out of any Class.
/// ///

View File

@@ -1,5 +1,5 @@
import 'package:server_box/core/extension/context/locale.dart';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:server_box/core/extension/context/locale.dart';
enum SSHErrType { enum SSHErrType {
unknown, unknown,

View File

@@ -1,8 +1,7 @@
import 'package:server_box/core/extension/context/locale.dart'; 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/model/server/system.dart';
import 'package:server_box/data/provider/server.dart';
import 'package:server_box/data/res/build_data.dart';
enum ShellFunc { enum ShellFunc {
status, status,

View File

@@ -1,11 +1,11 @@
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.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/context/locale.dart';
import 'package:server_box/view/page/server/tab/tab.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/setting/entry.dart';
import 'package:server_box/view/page/snippet/list.dart'; import 'package:server_box/view/page/snippet/list.dart';
import 'package:server_box/view/page/ssh/tab.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'; import 'package:server_box/view/page/storage/local.dart';
enum AppTab { enum AppTab {

View File

@@ -3,16 +3,15 @@ import 'dart:convert';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hive_ce_flutter/hive_flutter.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/custom.dart';
import 'package:server_box/data/model/server/server.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/model/server/wol_cfg.dart';
import 'package:server_box/data/provider/server.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'; import 'package:server_box/data/store/server.dart';
part 'server_private_info.g.dart';
part 'server_private_info.freezed.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 /// In the first version, it's called `ServerPrivateInfo` which was designed to
/// store the private information of a server. /// store the private information of a server.

View File

@@ -1,16 +1,15 @@
import 'package:fl_lib/fl_lib.dart'; 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/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/cpu.dart';
import 'package:server_box/data/model/server/disk.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/memory.dart';
import 'package:server_box/data/model/server/net_speed.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 { class ServerStatusUpdateReq {
final ServerStatus ss; final ServerStatus ss;

View File

@@ -5,10 +5,10 @@ import 'package:dartssh2/dartssh2.dart';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:server_box/core/extension/ssh_client.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/app/shell_func.dart';
import 'package:server_box/data/model/container/image.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/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/model/container/type.dart';
import 'package:server_box/data/res/store.dart'; import 'package:server_box/data/res/store.dart';

View File

@@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:computer/computer.dart'; import 'package:computer/computer.dart';
import 'package:dartssh2/dartssh2.dart';
import 'package:dio/dio.dart'; import 'package:dio/dio.dart';
import 'package:dio/io.dart'; import 'package:dio/io.dart';
import 'package:fl_lib/fl_lib.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/app/error.dart';
import 'package:server_box/data/model/server/pve.dart'; import 'package:server_box/data/model/server/pve.dart';
import 'package:server_box/data/model/server/server_private_info.dart'; import 'package:server_box/data/model/server/server_private_info.dart';
import 'package:dartssh2/dartssh2.dart';
typedef PveCtrlFunc = Future<bool> Function(String node, String id); typedef PveCtrlFunc = Future<bool> Function(String node, String id);

View File

@@ -1,4 +1,5 @@
import 'dart:async'; import 'dart:async';
// import 'dart:io'; // import 'dart:io';
import 'package:computer/computer.dart'; import 'package:computer/computer.dart';
@@ -6,18 +7,17 @@ import 'package:dartssh2/dartssh2.dart';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:server_box/core/extension/ssh_client.dart'; import 'package:server_box/core/extension/ssh_client.dart';
import 'package:server_box/core/sync.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/core/utils/ssh_auth.dart';
import 'package:server_box/data/model/app/error.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/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.dart';
import 'package:server_box/data/model/server/server_private_info.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/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/model/server/try_limiter.dart';
import 'package:server_box/data/res/status.dart'; import 'package:server_box/data/res/status.dart';
import 'package:server_box/data/res/store.dart';
class ServerProvider extends Provider { class ServerProvider extends Provider {
const ServerProvider._(); const ServerProvider._();

View File

@@ -1,12 +1,11 @@
import 'package:server_box/data/model/server/server.dart'; import 'package:server_box/data/model/server/conn.dart';
import 'package:server_box/data/model/server/temp.dart';
import 'package:server_box/data/model/server/cpu.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/disk.dart';
import 'package:server_box/data/model/server/memory.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/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/system.dart';
import 'package:server_box/data/model/server/temp.dart';
abstract final class InitStatus { abstract final class InitStatus {
static SingleCpuCore get _initOneTimeCpuStatus => SingleCpuCore( static SingleCpuCore get _initOneTimeCpuStatus => SingleCpuCore(

View File

@@ -2,10 +2,9 @@ import 'dart:convert';
import 'package:fl_lib/fl_lib.dart'; 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/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/app/server_detail_card.dart';
import 'package:server_box/data/model/ssh/virtual_key.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'; import 'package:server_box/data/res/default.dart';
class SettingStore extends HiveStore { class SettingStore extends HiveStore {

View File

@@ -4,6 +4,7 @@ import 'dart:io';
import 'package:computer/computer.dart'; import 'package:computer/computer.dart';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.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/context/locale.dart';
import 'package:server_box/core/sync.dart'; import 'package:server_box/core/sync.dart';
import 'package:server_box/data/model/app/bak/backup2.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/provider/snippet.dart';
import 'package:server_box/data/res/misc.dart'; import 'package:server_box/data/res/misc.dart';
import 'package:server_box/data/res/store.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'; import 'package:webdav_client_plus/webdav_client_plus.dart';
class BackupPage extends StatefulWidget { class BackupPage extends StatefulWidget {

View File

@@ -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/base.dart';
import 'package:server_box/data/model/app/menu/container.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/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/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/model/server/server_private_info.dart';
import 'package:server_box/data/provider/container.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'; import 'package:server_box/view/page/ssh/page/page.dart';
class ContainerPage extends StatefulWidget { class ContainerPage extends StatefulWidget {

View File

@@ -3,9 +3,8 @@ import 'dart:async';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:server_box/core/extension/context/locale.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/model/server/ping_result.dart';
import 'package:server_box/data/provider/server.dart';
/// Only permit ipv4 / ipv6 / domain chars /// Only permit ipv4 / ipv6 / domain chars
final targetReg = RegExp(r'[a-zA-Z0-9\.-_:]+'); final targetReg = RegExp(r'[a-zA-Z0-9\.-_:]+');

View File

@@ -5,11 +5,10 @@ import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:server_box/core/extension/context/locale.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/core/utils/server.dart';
import 'package:server_box/data/model/server/private_key_info.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'; const _format = 'text/plain';

View File

@@ -1,13 +1,12 @@
import 'dart:io';
import 'dart:async'; import 'dart:async';
import 'dart:io';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:server_box/core/extension/context/locale.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/model/server/private_key_info.dart';
import 'package:server_box/data/provider/private_key.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'; import 'package:server_box/view/page/private_key/edit.dart';
class PrivateKeysListPage extends StatefulWidget { class PrivateKeysListPage extends StatefulWidget {

View File

@@ -5,11 +5,10 @@ import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:server_box/core/extension/context/locale.dart'; import 'package:server_box/core/extension/context/locale.dart';
import 'package:server_box/core/route.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/app/shell_func.dart';
import 'package:server_box/data/model/server/proc.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/model/server/server_private_info.dart';
import 'package:server_box/data/res/store.dart';
class ProcessPage extends StatefulWidget { class ProcessPage extends StatefulWidget {
final SpiRequiredArgs args; final SpiRequiredArgs args;

View File

@@ -246,8 +246,8 @@ final class _PvePageState extends State<PvePage> {
], ],
), ),
UIs.height7, UIs.height7,
AvgWidthRow( AvgSize(
width: _media.size.width, totalSize: _media.size.width,
padding: _kHorziPadding * 2 + 26, padding: _kHorziPadding * 2 + 26,
children: [ children: [
PercentCircle(percent: (item.cpu / item.maxcpu) * 100), PercentCircle(percent: (item.cpu / item.maxcpu) * 100),
@@ -323,8 +323,8 @@ final class _PvePageState extends State<PvePage> {
], ],
), ),
UIs.height7, UIs.height7,
AvgWidthRow( AvgSize(
width: _media.size.width, totalSize: _media.size.width,
padding: _kHorziPadding * 2 + 26, padding: _kHorziPadding * 2 + 26,
children: [ children: [
PercentCircle(percent: (item.cpu / item.maxcpu) * 100), PercentCircle(percent: (item.cpu / item.maxcpu) * 100),

View File

@@ -19,7 +19,7 @@ extension on _ServerDetailPageState {
); );
} }
void _nTapGpuProcessItem(NvidiaSmiMemProcess process) { void _onTapGpuProcessItem(NvidiaSmiMemProcess process) {
context.showRoundDialog( context.showRoundDialog(
title: '${process.pid}', title: '${process.pid}',
titleMaxLines: 1, titleMaxLines: 1,
@@ -30,30 +30,18 @@ extension on _ServerDetailPageState {
UIs.height13, UIs.height13,
Text('Memory: ${process.memory} MiB'), Text('Memory: ${process.memory} MiB'),
UIs.height13, UIs.height13,
Text('Process: ${process.name}') Text('Process: ${process.name}'),
], ],
), ),
actions: [ actions: [TextButton(onPressed: () => context.pop(), child: Text(libL10n.close))],
TextButton(
onPressed: () => context.pop(),
child: Text(libL10n.close),
)
],
); );
} }
void _onTapCustomItem(MapEntry<String, String> cmd) { void _onTapCustomItem(MapEntry<String, String> cmd) {
context.showRoundDialog( context.showRoundDialog(
title: cmd.key, title: cmd.key,
child: SingleChildScrollView( child: SingleChildScrollView(child: Text(cmd.value, style: UIs.text13Grey)),
child: Text(cmd.value, style: UIs.text13Grey), actions: [TextButton(onPressed: () => context.pop(), child: Text(libL10n.close))],
),
actions: [
TextButton(
onPressed: () => context.pop(),
child: Text(libL10n.close),
),
],
); );
} }
@@ -76,13 +64,18 @@ extension on _ServerDetailPageState {
Pfs.copy(key); Pfs.copy(key);
context.showSnackBar('${libL10n.copy} ${libL10n.success}'); 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 { enum _NetSortType {
device, device,
trans, trans,
recv, recv;
;
bool get isDevice => this == _NetSortType.device; bool get isDevice => this == _NetSortType.device;
bool get isIn => this == _NetSortType.recv; bool get isIn => this == _NetSortType.recv;
@@ -117,7 +110,8 @@ Widget _buildLineChart(
bool curve = false, bool curve = false,
int verticalInterval = 20, int verticalInterval = 20,
}) { }) {
return LineChart(LineChartData( return LineChart(
LineChartData(
lineTouchData: LineTouchData( lineTouchData: LineTouchData(
touchTooltipData: LineTouchTooltipData( touchTooltipData: LineTouchTooltipData(
tooltipPadding: const EdgeInsets.all(5), tooltipPadding: const EdgeInsets.all(5),
@@ -126,10 +120,7 @@ Widget _buildLineChart(
return touchedSpots.map((e) { return touchedSpots.map((e) {
return LineTooltipItem( return LineTooltipItem(
'$tooltipPrefix${e.barIndex}: ${e.y.toStringAsFixed(2)}', '$tooltipPrefix${e.barIndex}: ${e.y.toStringAsFixed(2)}',
const TextStyle( const TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
fontSize: 12,
fontWeight: FontWeight.bold,
),
); );
}).toList(); }).toList();
}, },
@@ -141,23 +132,14 @@ Widget _buildLineChart(
drawVerticalLine: false, drawVerticalLine: false,
horizontalInterval: verticalInterval.toDouble(), horizontalInterval: verticalInterval.toDouble(),
getDrawingHorizontalLine: (value) { getDrawingHorizontalLine: (value) {
return const FlLine( return const FlLine(color: Color.fromARGB(43, 88, 91, 94), strokeWidth: 1);
color: Color.fromARGB(43, 88, 91, 94),
strokeWidth: 1,
);
}, },
), ),
titlesData: FlTitlesData( titlesData: FlTitlesData(
show: true, show: true,
rightTitles: const AxisTitles( rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
sideTitles: SideTitles(showTitles: false), topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
), bottomTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
topTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
bottomTitles: const AxisTitles(
sideTitles: SideTitles(showTitles: false),
),
leftTitles: AxisTitles( leftTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: SideTitles(
showTitles: true, showTitles: true,
@@ -165,10 +147,7 @@ Widget _buildLineChart(
getTitlesWidget: (val, meta) { getTitlesWidget: (val, meta) {
if (val % verticalInterval != 0) return UIs.placeholder; if (val % verticalInterval != 0) return UIs.placeholder;
if (val == 0) return const Text('0 %', style: UIs.text12Grey); if (val == 0) return const Text('0 %', style: UIs.text12Grey);
return Text( return Text(val.toInt().toString(), style: UIs.text12Grey);
val.toInt().toString(),
style: UIs.text12Grey,
);
}, },
reservedSize: 27, reservedSize: 27,
), ),
@@ -178,7 +157,8 @@ Widget _buildLineChart(
minY: -1, minY: -1,
maxY: 101, maxY: 101,
lineBarsData: spots lineBarsData: spots
.map((e) => LineChartBarData( .map(
(e) => LineChartBarData(
spots: e, spots: e,
isCurved: curve, isCurved: curve,
barWidth: 2, barWidth: 2,
@@ -186,7 +166,9 @@ Widget _buildLineChart(
color: UIs.primaryColor, color: UIs.primaryColor,
dotData: const FlDotData(show: false), dotData: const FlDotData(show: false),
belowBarData: BarAreaData(show: false), belowBarData: BarAreaData(show: false),
)) ),
)
.toList(), .toList(),
)); ),
);
} }

View File

@@ -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/net_speed.dart';
import 'package:server_box/data/model/server/nvdia.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/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/server_private_info.dart';
import 'package:server_box/data/model/server/system.dart'; import 'package:server_box/data/model/server/system.dart';
import 'package:server_box/data/res/store.dart'; import 'package:server_box/data/res/store.dart';
import 'package:server_box/view/page/pve.dart'; import 'package:server_box/view/page/pve.dart';
import 'package:server_box/view/page/server/edit.dart'; import 'package:server_box/view/page/server/edit.dart';
import 'package:server_box/view/widget/server_func_btns.dart'; import 'package:server_box/view/widget/server_func_btns.dart';
import 'package:server_box/data/model/server/server.dart';
part 'misc.dart'; part 'misc.dart';
@@ -32,16 +32,11 @@ class ServerDetailPage extends StatefulWidget {
@override @override
State<ServerDetailPage> createState() => _ServerDetailPageState(); State<ServerDetailPage> createState() => _ServerDetailPageState();
static const route = AppRouteArg( static const route = AppRouteArg(page: ServerDetailPage.new, path: '/servers/detail');
page: ServerDetailPage.new,
path: '/servers/detail',
);
} }
class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerProviderStateMixin { class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerProviderStateMixin {
late final _cardBuildMap = Map.fromIterables( late final _cardBuildMap = Map.fromIterables(ServerDetailCards.names, [
ServerDetailCards.names,
[
_buildAbout, _buildAbout,
_buildCPUView, _buildCPUView,
_buildMemView, _buildMemView,
@@ -54,10 +49,9 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
_buildBatteries, _buildBatteries,
_buildPve, _buildPve,
_buildCustomCmd, _buildCustomCmd,
], ]);
);
late MediaQueryData _media; late Size _size;
final List<String> _cardsOrder = []; final List<String> _cardsOrder = [];
final _settings = Stores.setting; final _settings = Stores.setting;
@@ -74,7 +68,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
@override @override
void didChangeDependencies() { void didChangeDependencies() {
super.didChangeDependencies(); super.didChangeDependencies();
_media = MediaQuery.of(context); _size = MediaQuery.sizeOf(context);
} }
@override @override
@@ -100,14 +94,11 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
Widget _buildMainPage(Server si) { Widget _buildMainPage(Server si) {
final buildFuncs = !Stores.setting.moveServerFuncs.fetch(); final buildFuncs = !Stores.setting.moveServerFuncs.fetch();
final logo = _buildLogo(si); final logo = _buildLogo(si);
final children = [ final children = <Widget>[if (logo != null) logo, if (buildFuncs) ServerFuncBtns(spi: si.spi)];
logo,
if (buildFuncs) ServerFuncBtns(spi: si.spi),
];
for (final card in _cardsOrder) { for (final card in _cardsOrder) {
final buildFunc = _cardBuildMap[card]; final child = _cardBuildMap[card]?.call(si);
if (buildFunc != null) { if (child != null) {
children.add(buildFunc(si)); children.add(child);
} }
} }
@@ -121,36 +112,26 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
return CustomAppBar( return CustomAppBar(
title: Text( title: Text(
si.spi.name, si.spi.name,
style: TextStyle( style: TextStyle(fontSize: 20, color: context.isDark ? Colors.white : Colors.black),
fontSize: 20,
color: context.isDark ? Colors.white : Colors.black,
),
), ),
actions: [ actions: [
QrShareBtn( QrShareBtn(data: si.spi.toJsonString(), tip: si.spi.name, tip2: '${l10n.server} ~ ServerBox'),
data: si.spi.toJsonString(),
tip: si.spi.name,
tip2: '${l10n.server} ~ ServerBox',
),
IconButton( IconButton(
icon: const Icon(Icons.edit), icon: const Icon(Icons.edit),
onPressed: () async { onPressed: () async {
final delete = await ServerEditPage.route.go( final delete = await ServerEditPage.route.go(context, args: SpiRequiredArgs(si.spi));
context,
args: SpiRequiredArgs(si.spi),
);
if (delete == true) { if (delete == true) {
context.pop(); context.pop();
} }
}, },
) ),
], ],
); );
} }
Widget _buildLogo(Server si) { Widget? _buildLogo(Server si) {
var logoUrl = si.spi.custom?.logoUrl ?? _settings.serverLogoUrl.fetch().selfNotEmptyOrNull; 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; final dist = si.status.more[StatusCmdType.sys]?.dist;
if (dist != null) { if (dist != null) {
@@ -160,25 +141,23 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: 13), padding: const EdgeInsets.symmetric(vertical: 13),
child: ExtendedImage.network( child: LayoutBuilder(
logoUrl, builder: (_, cons) {
cache: true, if (logoUrl == null) return UIs.placeholder;
height: _media.size.height * 0.2, return ExtendedImage.network(logoUrl, cache: true, height: cons.maxWidth * 0.2);
},
), ),
); );
} }
Widget _buildAbout(Server si) { Widget? _buildAbout(Server si) {
final ss = si.status; final ss = si.status;
return ExpandTile( return ExpandTile(
key: ValueKey(ss.more.hashCode), // Use hashCode to avoid perf issue key: ValueKey(ss.more.hashCode), // Use hashCode to avoid perf issue
leading: const Icon(MingCute.information_fill, size: 20), leading: const Icon(MingCute.information_fill, size: 20),
initiallyExpanded: _getInitExpand(ss.more.entries.length), initiallyExpanded: _getInitExpand(ss.more.entries.length),
title: Text(libL10n.about), title: Text(libL10n.about),
childrenPadding: const EdgeInsets.symmetric( childrenPadding: const EdgeInsets.symmetric(horizontal: 17, vertical: 11),
horizontal: 17,
vertical: 11,
),
children: ss.more.entries children: ss.more.entries
.map( .map(
(e) => Padding( (e) => Padding(
@@ -186,16 +165,8 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(e.key.i18n, style: UIs.text13, overflow: TextOverflow.ellipsis),
e.key.i18n, Text(e.value, style: UIs.text13Grey, overflow: TextOverflow.ellipsis),
style: UIs.text13,
overflow: TextOverflow.ellipsis,
),
Text(
e.value,
style: UIs.text13Grey,
overflow: TextOverflow.ellipsis,
),
], ],
), ),
), ),
@@ -204,13 +175,13 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
).cardx; ).cardx;
} }
Widget _buildCPUView(Server si) { Widget? _buildCPUView(Server si) {
final ss = si.status; final ss = si.status;
final percent = ss.cpu.usedPercent(coreIdx: 0).toInt(); final percent = ss.cpu.usedPercent(coreIdx: 0).toInt();
final details = [ final details = [
_buildDetailPercent(ss.cpu.user, 'user'), _buildDetailPercent(ss.cpu.user, 'user'),
UIs.width13, UIs.width13,
_buildDetailPercent(ss.cpu.idle, 'idle') _buildDetailPercent(ss.cpu.idle, 'idle'),
]; ];
if (ss.system == SystemType.linux) { if (ss.system == SystemType.linux) {
details.addAll([ details.addAll([
@@ -223,62 +194,41 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
final List<Widget> children = Stores.setting.cpuViewAsProgress.fetch() final List<Widget> children = Stores.setting.cpuViewAsProgress.fetch()
? _buildCPUProgress(ss.cpu) ? _buildCPUProgress(ss.cpu)
: [ : [_buildCPUChart(ss)];
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',
),
),
),
];
if (ss.cpu.brand.isNotEmpty) { if (ss.cpu.brand.isNotEmpty) {
children.add(Column( children.add(
children: ss.cpu.brand.entries.map(_buildCpuModelItem).toList(), Column(children: ss.cpu.brand.entries.map(_buildCpuModelItem).toList()).paddingOnly(top: 13),
).paddingOnly(top: 13)); );
} }
return ExpandTile( return ExpandTile(
title: Align( title: Align(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
child: _buildAnimatedText( child: _buildAnimatedText(ValueKey(percent), '$percent%', UIs.text27),
ValueKey(percent),
'$percent%',
UIs.text27,
),
), ),
childrenPadding: const EdgeInsets.symmetric(vertical: 13), childrenPadding: const EdgeInsets.symmetric(vertical: 13),
initiallyExpanded: _getInitExpand(1), initiallyExpanded: _getInitExpand(1),
trailing: Row( trailing: Row(mainAxisSize: MainAxisSize.min, children: details),
mainAxisSize: MainAxisSize.min,
children: details,
),
children: children, children: children,
).cardx; ).cardx;
} }
Widget _buildCpuModelItem(MapEntry<String, int> e) { Widget _buildCpuModelItem(MapEntry<String, int> e) {
final name = final name = e.key
e.key.replaceFirst('Intel(R)', '').replaceFirst('AMD', '').replaceFirst('with Radeon Graphics', ''); .replaceFirst('Intel(R)', '')
.replaceFirst('AMD', '')
.replaceFirst('with Radeon Graphics', '');
final child = Row( final child = Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
ConstrainedBox( LayoutBuilder(
constraints: BoxConstraints( builder: (_, cons) {
maxWidth: _media.size.width * .7, return ConstrainedBox(
), constraints: BoxConstraints(maxWidth: cons.maxWidth * .7),
child: Text( child: Text(name, style: UIs.text13, overflow: TextOverflow.ellipsis, maxLines: 1),
name, );
style: UIs.text13, },
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
), ),
Text('x ${e.value}', style: UIs.text13Grey, overflow: TextOverflow.clip), Text('x ${e.value}', style: UIs.text13Grey, overflow: TextOverflow.clip),
], ],
@@ -292,16 +242,8 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
Text( Text('${percent.toStringAsFixed(1)}%', style: UIs.text12, textScaler: _textFactor),
'${percent.toStringAsFixed(1)}%', Text(timeType, style: UIs.text12Grey, textScaler: _textFactor),
style: UIs.text12,
textScaler: _textFactor,
),
Text(
timeType,
style: UIs.text12Grey,
textScaler: _textFactor,
),
], ],
); );
} }
@@ -341,9 +283,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
children.add( children.add(
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 17), padding: const EdgeInsets.symmetric(horizontal: 17),
child: Row( child: Row(children: rowChildren.joinWith(UIs.width7).toList()),
children: rowChildren.joinWith(UIs.width7).toList(),
),
), ),
); );
} }
@@ -362,6 +302,25 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
return children; 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) { Widget _buildProgress(double percent) {
if (percent > 100) percent = 100; if (percent > 100) percent = 100;
final percentWithinOne = percent / 100; final percentWithinOne = percent / 100;
@@ -373,7 +332,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
); );
} }
Widget _buildMemView(Server si) { Widget? _buildMemView(Server si) {
final ss = si.status; final ss = si.status;
final free = ss.mem.free / ss.mem.total * 100; final free = ss.mem.free / ss.mem.total * 100;
final avail = ss.mem.availPercent * 100; final avail = ss.mem.availPercent * 100;
@@ -384,10 +343,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
children: [ children: [
_buildAnimatedText(ValueKey(usedStr), '$usedStr%', UIs.text27), _buildAnimatedText(ValueKey(usedStr), '$usedStr%', UIs.text27),
UIs.width7, UIs.width7,
Text( Text('of ${(ss.mem.total * 1024).bytes2Str}', style: UIs.text13Grey),
'of ${(ss.mem.total * 1024).bytes2Str}',
style: UIs.text13Grey,
)
], ],
); );
@@ -411,15 +367,16 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
], ],
), ),
UIs.height13, UIs.height13,
_buildProgress(used) _buildProgress(used),
], ],
), ),
).cardx; ).cardx;
} }
Widget _buildSwapView(Server si) { Widget? _buildSwapView(Server si) {
final ss = si.status; 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 used = ss.swap.usedPercent * 100;
final cached = ss.swap.cached / ss.swap.total * 100; final cached = ss.swap.cached / ss.swap.total * 100;
@@ -427,10 +384,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
children: [ children: [
Text('${used.toStringAsFixed(0)}%', style: UIs.text27), Text('${used.toStringAsFixed(0)}%', style: UIs.text27),
UIs.width7, UIs.width7,
Text( Text('of ${(ss.swap.total * 1024).bytes2Str} ', style: UIs.text13Grey),
'of ${(ss.swap.total * 1024).bytes2Str} ',
style: UIs.text13Grey,
)
], ],
); );
@@ -442,21 +396,19 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
children: [ children: [
Row( Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [percentW, _buildDetailPercent(cached, 'cached')],
percentW,
_buildDetailPercent(cached, 'cached'),
],
), ),
UIs.height13, UIs.height13,
_buildProgress(used) _buildProgress(used),
], ],
), ),
).cardx; ).cardx;
} }
Widget _buildGpuView(Server si) { Widget? _buildGpuView(Server si) {
final ss = si.status; 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() ?? []; final children = ss.nvidia?.map((e) => _buildGpuItem(e)).toList() ?? [];
return ExpandTile( return ExpandTile(
title: const Text('GPU'), title: const Text('GPU'),
@@ -486,10 +438,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
mainAxisAlignment: MainAxisAlignment.end, mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
IconButton( IconButton(onPressed: () => _onTapGpuItem(item), icon: const Icon(Icons.info_outline, size: 17)),
onPressed: () => _onTapGpuItem(item),
icon: const Icon(Icons.info_outline, size: 17),
),
], ],
), ),
); );
@@ -510,13 +459,13 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
textScaler: _textFactor, textScaler: _textFactor,
), ),
trailing: InkWell( trailing: InkWell(
onTap: () => _nTapGpuProcessItem(process), onTap: () => _onTapGpuProcessItem(process),
child: const Icon(Icons.info_outline, size: 17), child: const Icon(Icons.info_outline, size: 17),
), ),
); );
} }
Widget _buildDiskView(Server si) { Widget? _buildDiskView(Server si) {
final ss = si.status; final ss = si.status;
final children = <Widget>[]; final children = <Widget>[];
@@ -526,7 +475,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
children.add(_buildDiskItemWithHierarchy(disk, ss, 0)); children.add(_buildDiskItemWithHierarchy(disk, ss, 0));
} }
if (children.isEmpty) return UIs.placeholder; if (children.isEmpty) return null;
return ExpandTile( return ExpandTile(
title: Text(l10n.disk), title: Text(l10n.disk),
@@ -583,11 +532,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
style: UIs.text12, style: UIs.text12,
textScaler: _textFactor, textScaler: _textFactor,
), ),
Text( Text(text, style: UIs.text12Grey, textScaler: _textFactor),
text,
style: UIs.text12Grey,
textScaler: _textFactor,
)
], ],
), ),
), ),
@@ -604,21 +549,21 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
backgroundColor: UIs.halfAlpha, backgroundColor: UIs.halfAlpha,
color: UIs.primaryColor, 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 ss = si.status;
final ns = ss.netSpeed; final ns = ss.netSpeed;
final children = <Widget>[]; final children = <Widget>[];
final devices = ns.devices; final devices = ns.devices;
if (devices.isEmpty) return UIs.placeholder; if (devices.isEmpty) return null;
devices.sort(_netSortType.value.getSortFunc(ns)); devices.sort(_netSortType.value.getSortFunc(ns));
children.addAll(devices.map((e) => _buildNetSpeedItem(ns, e))); children.addAll(devices.map((e) => _buildNetSpeedItem(ns, e)));
@@ -634,18 +579,12 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
onTap: () => _netSortType.value = val.next, onTap: () => _netSortType.value = val.next,
child: AnimatedSwitcher( child: AnimatedSwitcher(
duration: const Duration(milliseconds: 377), duration: const Duration(milliseconds: 377),
transitionBuilder: (child, animation) => FadeTransition( transitionBuilder: (child, animation) => FadeTransition(opacity: animation, child: child),
opacity: animation,
child: child,
),
child: Row( child: Row(
children: [ children: [
const Icon(Icons.sort, size: 17), const Icon(Icons.sort, size: 17),
UIs.width7, UIs.width7,
Text( Text(val.name, style: UIs.text13Grey),
val.name,
style: UIs.text13Grey,
),
], ],
), ),
), ),
@@ -680,7 +619,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
'${ns.sizeIn(device: device)} | ${ns.sizeOut(device: device)}', '${ns.sizeIn(device: device)} | ${ns.sizeOut(device: device)}',
style: UIs.text12Grey, style: UIs.text12Grey,
textScaler: _textFactor, textScaler: _textFactor,
) ),
], ],
), ),
SizedBox( SizedBox(
@@ -690,17 +629,16 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
textAlign: TextAlign.end, textAlign: TextAlign.end,
style: UIs.text13Grey, style: UIs.text13Grey,
), ),
) ),
], ],
), ),
); );
} }
Widget _buildTemperature(Server si) { Widget? _buildTemperature(Server si) {
final ss = si.status; final ss = si.status;
if (ss.temps.isEmpty) { if (ss.temps.isEmpty) return null;
return UIs.placeholder;
}
return CardX( return CardX(
child: ExpandTile( child: ExpandTile(
title: Text(l10n.temperature), title: Text(l10n.temperature),
@@ -729,11 +667,10 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
); );
} }
Widget _buildBatteries(Server si) { Widget? _buildBatteries(Server si) {
final ss = si.status; final ss = si.status;
if (ss.batteries.isEmpty) { if (ss.batteries.isEmpty) return null;
return UIs.placeholder;
}
return CardX( return CardX(
child: ExpandTile( child: ExpandTile(
title: Text(l10n.battery), title: Text(l10n.battery),
@@ -756,22 +693,16 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text('${battery.name}', style: UIs.text15), Text('${battery.name}', style: UIs.text15),
Text( Text('${battery.status.name} - ${battery.cycle}', style: UIs.text13Grey),
'${battery.status.name} - ${battery.cycle}',
style: UIs.text13Grey,
),
], ],
), ),
Text( Text('${battery.percent?.toStringAsFixed(0)}%', style: UIs.text13Grey),
'${battery.percent?.toStringAsFixed(0)}%',
style: UIs.text13Grey,
),
], ],
), ),
); );
} }
Widget _buildSensors(Server si) { Widget? _buildSensors(Server si) {
final ss = si.status; final ss = si.status;
if (ss.sensors.isEmpty) return UIs.placeholder; if (ss.sensors.isEmpty) return UIs.placeholder;
return CardX( return CardX(
@@ -824,9 +755,9 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
); );
} }
Widget _buildPve(Server si) { Widget? _buildPve(Server si) {
final addr = si.spi.custom?.pveAddr; final addr = si.spi.custom?.pveAddr;
if (addr == null || addr.isEmpty) return UIs.placeholder; if (addr == null || addr.isEmpty) return null;
return CardX( return CardX(
child: ListTile( child: ListTile(
title: const Text('PVE'), title: const Text('PVE'),
@@ -837,9 +768,9 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
); );
} }
Widget _buildCustomCmd(Server si) { Widget? _buildCustomCmd(Server si) {
final ss = si.status; final ss = si.status;
if (ss.customCmds.isEmpty) return UIs.placeholder; if (ss.customCmds.isEmpty) return null;
return CardX( return CardX(
child: ExpandTile( child: ExpandTile(
leading: const Icon(MingCute.command_line, size: 17), leading: const Icon(MingCute.command_line, size: 17),
@@ -860,11 +791,7 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
if (!cmd.value.contains('\n')) return null; if (!cmd.value.contains('\n')) return null;
return GestureDetector( return GestureDetector(
onTap: () => _onTapCustomItem(cmd), onTap: () => _onTapCustomItem(cmd),
child: const Icon( child: const Icon(Icons.info_outline, size: 17, color: Colors.grey),
Icons.info_outline,
size: 17,
color: Colors.grey,
),
); );
}, },
), ),
@@ -874,21 +801,8 @@ class _ServerDetailPageState extends State<ServerDetailPage> with SingleTickerPr
Widget _buildAnimatedText(Key key, String text, TextStyle style) { Widget _buildAnimatedText(Key key, String text, TextStyle style) {
return AnimatedSwitcher( return AnimatedSwitcher(
duration: const Duration(milliseconds: 277), duration: const Duration(milliseconds: 277),
child: Text( child: Text(key: key, text, style: style, textScaler: _textFactor),
key: key, transitionBuilder: (child, animation) => FadeTransition(opacity: animation, child: child),
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);
}
} }

View File

@@ -8,11 +8,10 @@ import 'package:server_box/core/extension/context/locale.dart';
import 'package:server_box/core/route.dart'; import 'package:server_box/core/route.dart';
import 'package:server_box/data/model/server/custom.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/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/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/private_key.dart';
import 'package:server_box/data/provider/server.dart';
import 'package:server_box/data/store/server.dart'; import 'package:server_box/data/store/server.dart';
import 'package:server_box/view/page/private_key/edit.dart'; import 'package:server_box/view/page/private_key/edit.dart';

View File

@@ -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/context/locale.dart';
import 'package:server_box/core/extension/ssh_client.dart'; import 'package:server_box/core/extension/ssh_client.dart';
import 'package:server_box/core/route.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/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/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/build_data.dart';
import 'package:server_box/data/res/store.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/detail/view.dart';
import 'package:server_box/view/page/server/edit.dart'; import 'package:server_box/view/page/server/edit.dart';
import 'package:server_box/view/page/setting/entry.dart'; import 'package:server_box/view/page/setting/entry.dart';
import 'package:server_box/view/widget/percent_circle.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'; import 'package:server_box/view/widget/server_func_btns.dart';
part 'top_bar.dart';
part 'card_stat.dart'; part 'card_stat.dart';
part 'utils.dart';
part 'content.dart'; part 'content.dart';
part 'landscape.dart'; part 'landscape.dart';
part 'top_bar.dart';
part 'utils.dart';
class ServerPage extends StatefulWidget { class ServerPage extends StatefulWidget {
const ServerPage({super.key}); const ServerPage({super.key});
@@ -141,10 +140,7 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
}); });
} }
Widget _buildBodySmall({ Widget _buildBodySmall({required List<String> filtered}) {
required List<String> filtered,
EdgeInsets? padding = const EdgeInsets.fromLTRB(0, 0, 5, 7),
}) {
if (filtered.isEmpty) { if (filtered.isEmpty) {
return Center(child: Text(libL10n.empty, textAlign: TextAlign.center)); return Center(child: Text(libL10n.empty, textAlign: TextAlign.center));
} }
@@ -153,6 +149,9 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
builder: (_, cons) { builder: (_, cons) {
// Calculate number of columns based on available width // Calculate number of columns based on available width
final columnsCount = math.max(1, (cons.maxWidth / UIs.columnWidth).floor()); 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( return Row(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -176,10 +175,7 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
final vnode = ServerProvider.pick(id: serversInThisColumn[index]); final vnode = ServerProvider.pick(id: serversInThisColumn[index]);
if (vnode == null) return UIs.placeholder; if (vnode == null) return UIs.placeholder;
return Padding( return vnode.listenVal(_buildEachServerCard);
padding: const EdgeInsets.symmetric(horizontal: 0),
child: vnode.listenVal(_buildEachServerCard),
);
}, },
), ),
); );
@@ -190,9 +186,7 @@ class _ServerPageState extends State<ServerPage> with AutomaticKeepAliveClientMi
} }
Widget _buildEachServerCard(Server? srv) { Widget _buildEachServerCard(Server? srv) {
if (srv == null) { if (srv == null) return UIs.placeholder;
return UIs.placeholder;
}
return CardX( return CardX(
key: Key(srv.spi.id + _tag.value), key: Key(srv.spi.id + _tag.value),

View File

@@ -4,17 +4,15 @@ import 'dart:io';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_highlight/theme_map.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:icons_plus/icons_plus.dart';
import 'package:server_box/core/extension/context/locale.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/github_id.dart';
import 'package:server_box/data/res/store.dart'; import 'package:server_box/data/res/store.dart';
import 'package:server_box/data/res/url.dart'; import 'package:server_box/data/res/url.dart';
import 'package:server_box/data/store/setting.dart';
import 'package:server_box/data/model/app/net_view.dart'; import 'package:server_box/generated/l10n/l10n.dart';
import 'package:server_box/data/res/build_data.dart';
import 'package:server_box/view/page/backup.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/private_key/list.dart';
import 'package:server_box/view/page/setting/platform/android.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 'about.dart';
part 'entries/app.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/container.dart';
part 'entries/editor.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; const _kIconSize = 23.0;

View File

@@ -5,24 +5,26 @@ import 'package:dartssh2/dartssh2.dart';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:icons_plus/icons_plus.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
import 'package:server_box/core/chan.dart'; import 'package:server_box/core/chan.dart';
import 'package:server_box/core/extension/context/locale.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/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/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/snippet.dart';
import 'package:server_box/data/provider/virtual_keyboard.dart'; import 'package:server_box/data/provider/virtual_keyboard.dart';
import 'package:server_box/data/res/store.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:server_box/view/page/storage/sftp.dart';
import 'package:wakelock_plus/wakelock_plus.dart'; import 'package:wakelock_plus/wakelock_plus.dart';
import 'package:xterm/core.dart'; import 'package:xterm/core.dart';
import 'package:xterm/ui.dart' hide TerminalThemes; 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 'init.dart';
part 'keyboard.dart'; part 'keyboard.dart';
part 'virt_key.dart'; part 'virt_key.dart';
@@ -50,18 +52,12 @@ final class SshPageArgs {
class SSHPage extends StatefulWidget { class SSHPage extends StatefulWidget {
final SshPageArgs args; final SshPageArgs args;
const SSHPage({ const SSHPage({super.key, required this.args});
super.key,
required this.args,
});
@override @override
State<SSHPage> createState() => SSHPageState(); State<SSHPage> createState() => SSHPageState();
static const route = AppRouteArg<void, SshPageArgs>( static const route = AppRouteArg<void, SshPageArgs>(page: SSHPage.new, path: '/ssh/page');
page: SSHPage.new,
path: '/ssh/page',
);
} }
const _horizonPadding = 7.0; const _horizonPadding = 7.0;
@@ -155,6 +151,11 @@ class SSHPageState extends State<SSHPage> with AutomaticKeepAliveClientMixin, Af
_handleEscKeyOrBackButton(); _handleEscKeyOrBackButton();
}, },
child: Scaffold( child: Scaffold(
appBar: CustomAppBar(
title: Text(widget.args.spi.name),
actions: [_buildCopyBtn, _buildKillBtn],
centerTitle: false,
),
backgroundColor: _terminalTheme.background, backgroundColor: _terminalTheme.background,
body: _buildBody(), body: _buildBody(),
bottomNavigationBar: isDesktop ? null : _buildBottom(), bottomNavigationBar: isDesktop ? null : _buildBottom(),
@@ -176,7 +177,7 @@ class SSHPageState extends State<SSHPage> with AutomaticKeepAliveClientMixin, Af
height: _media.size.height - _virtKeysHeight - _media.padding.bottom - _media.padding.top, height: _media.size.height - _virtKeysHeight - _media.padding.bottom - _media.padding.top,
child: Padding( child: Padding(
padding: EdgeInsets.only( padding: EdgeInsets.only(
top: widget.args.notFromTab ? CustomAppBar.sysStatusBarHeight : 0, // top: widget.args.notFromTab ? CustomAppBar.sysStatusBarHeight : 0,
left: _horizonPadding, left: _horizonPadding,
right: _horizonPadding, right: _horizonPadding,
), ),
@@ -192,10 +193,7 @@ class SSHPageState extends State<SSHPage> with AutomaticKeepAliveClientMixin, Af
autofocus: false, autofocus: false,
keyboardAppearance: _isDark ? Brightness.dark : Brightness.light, keyboardAppearance: _isDark ? Brightness.dark : Brightness.light,
showToolbar: isMobile, showToolbar: isMobile,
viewOffset: Offset( viewOffset: Offset(2 * _horizonPadding, CustomAppBar.sysStatusBarHeight),
2 * _horizonPadding,
CustomAppBar.sysStatusBarHeight,
),
hideScrollBar: false, hideScrollBar: false,
focusNode: widget.args.focusNode, focusNode: widget.args.focusNode,
), ),
@@ -214,9 +212,11 @@ class SSHPageState extends State<SSHPage> with AutomaticKeepAliveClientMixin, Af
height: _virtKeysHeight, height: _virtKeysHeight,
child: ChangeNotifierProvider( child: ChangeNotifierProvider(
create: (_) => _keyboard, create: (_) => _keyboard,
builder: (_, __) => Consumer<VirtKeyProvider>(builder: (_, __, ___) { builder: (_, __) => Consumer<VirtKeyProvider>(
builder: (_, __, ___) {
return _buildVirtualKey(); return _buildVirtualKey();
}), },
),
), ),
), ),
), ),
@@ -227,16 +227,11 @@ class SSHPageState extends State<SSHPage> with AutomaticKeepAliveClientMixin, Af
if (_horizonVirtKeys) { if (_horizonVirtKeys) {
return SingleChildScrollView( return SingleChildScrollView(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
child: Row( child: Row(children: _virtKeysList.expand((e) => e).map(_buildVirtKeyItem).toList()),
children: _virtKeysList.expand((e) => e).map(_buildVirtKeyItem).toList(),
),
); );
} }
final rows = _virtKeysList.map((e) => Row(children: e.map(_buildVirtKeyItem).toList())).toList(); final rows = _virtKeysList.map((e) => Row(children: e.map(_buildVirtKeyItem).toList())).toList();
return Column( return Column(mainAxisSize: MainAxisSize.min, children: rows);
mainAxisSize: MainAxisSize.min,
children: rows,
);
} }
Widget _buildVirtKeyItem(VirtKey item) { Widget _buildVirtKeyItem(VirtKey item) {
@@ -253,11 +248,7 @@ class SSHPageState extends State<SSHPage> with AutomaticKeepAliveClientMixin, Af
} }
final child = item.icon != null final child = item.icon != null
? Icon( ? Icon(item.icon, size: 17, color: _isDark ? Colors.white : Colors.black)
item.icon,
size: 17,
color: _isDark ? Colors.white : Colors.black,
)
: Text( : Text(
item.text, item.text,
style: TextStyle( style: TextStyle(
@@ -286,6 +277,30 @@ class SSHPageState extends State<SSHPage> 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 @override
bool get wantKeepAlive => true; bool get wantKeepAlive => true;

View File

@@ -3,13 +3,12 @@ import 'dart:io';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:server_box/core/extension/context/locale.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/server/server_private_info.dart';
import 'package:server_box/data/model/sftp/worker.dart'; import 'package:server_box/data/model/sftp/worker.dart';
import 'package:server_box/data/provider/server.dart'; import 'package:server_box/data/provider/server.dart';
import 'package:server_box/data/provider/sftp.dart'; import 'package:server_box/data/provider/sftp.dart';
import 'package:server_box/data/res/misc.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/data/store/setting.dart';
import 'package:server_box/view/page/storage/sftp.dart'; import 'package:server_box/view/page/storage/sftp.dart';
import 'package:server_box/view/page/storage/sftp_mission.dart'; import 'package:server_box/view/page/storage/sftp_mission.dart';

View File

@@ -4,6 +4,7 @@ import 'dart:io';
import 'package:dartssh2/dartssh2.dart'; import 'package:dartssh2/dartssh2.dart';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.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/context/locale.dart';
import 'package:server_box/core/extension/sftpfile.dart'; import 'package:server_box/core/extension/sftpfile.dart';
import 'package:server_box/core/utils/comparator.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/omit_start_text.dart';
import 'package:server_box/view/widget/unix_perm.dart'; import 'package:server_box/view/widget/unix_perm.dart';
import 'package:icons_plus/icons_plus.dart';
final class SftpPageArgs { final class SftpPageArgs {
final Spi spi; final Spi spi;
final bool isSelect; final bool isSelect;
@@ -76,7 +75,7 @@ class _SftpPageState extends State<SftpPage> with AfterLayoutMixin {
return Scaffold( return Scaffold(
appBar: CustomAppBar( appBar: CustomAppBar(
title: TwoLineText(up: 'SFTP', down: widget.args.spi.name), title: Text(widget.args.spi.name),
actions: children, actions: children,
), ),
body: _buildFileView(), body: _buildFileView(),

View File

@@ -55,7 +55,7 @@ final class _SystemdPageState extends State<SystemdPage> {
curve: Curves.fastEaseInToSlowEaseOut, curve: Curves.fastEaseInToSlowEaseOut,
height: isBusy ? 30 : 0, height: isBusy ? 30 : 0,
child: isBusy child: isBusy
? SizedLoading.small.paddingOnly(bottom: 7) ? SizedLoading.medium
: const SizedBox.shrink(), : const SizedBox.shrink(),
), ),
), ),

View File

@@ -3,8 +3,11 @@ import 'dart:io';
import 'package:fl_lib/fl_lib.dart'; import 'package:fl_lib/fl_lib.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:server_box/core/extension/context/locale.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/base.dart';
import 'package:server_box/data/model/app/menu/server_func.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/model/server/snippet.dart';
import 'package:server_box/data/provider/server.dart'; import 'package:server_box/data/provider/server.dart';
import 'package:server_box/data/provider/snippet.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/storage/sftp.dart';
import 'package:server_box/view/page/systemd.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 { class ServerFuncBtnsTopRight extends StatelessWidget {
final Spi spi; final Spi spi;

View File

@@ -481,8 +481,8 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
path: "." path: "."
ref: "v1.0.314" ref: "v1.0.315"
resolved-ref: "306b1ca5b7df6981ed3d09afbf97c6b3054c9d21" resolved-ref: "8593608e8f78ea53f2b1fdad5d5395392870c0d3"
url: "https://github.com/lppcg/fl_lib" url: "https://github.com/lppcg/fl_lib"
source: git source: git
version: "0.0.1" version: "0.0.1"

View File

@@ -62,7 +62,7 @@ dependencies:
fl_lib: fl_lib:
git: git:
url: https://github.com/lppcg/fl_lib url: https://github.com/lppcg/fl_lib
ref: v1.0.314 ref: v1.0.315
dependency_overrides: dependency_overrides:
# webdav_client_plus: # webdav_client_plus: