mirror of
https://github.com/lollipopkit/flutter_server_box.git
synced 2025-12-17 15:24:35 +01:00
opt.: server detail page columns
This commit is contained in:
@@ -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
|
||||||
@@ -43,8 +43,9 @@ linter:
|
|||||||
annotate_overrides: true
|
annotate_overrides: true
|
||||||
avoid_empty_else: true
|
avoid_empty_else: true
|
||||||
# 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
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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._();
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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\.-_:]+');
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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,68 +110,55 @@ Widget _buildLineChart(
|
|||||||
bool curve = false,
|
bool curve = false,
|
||||||
int verticalInterval = 20,
|
int verticalInterval = 20,
|
||||||
}) {
|
}) {
|
||||||
return LineChart(LineChartData(
|
return LineChart(
|
||||||
lineTouchData: LineTouchData(
|
LineChartData(
|
||||||
touchTooltipData: LineTouchTooltipData(
|
lineTouchData: LineTouchData(
|
||||||
tooltipPadding: const EdgeInsets.all(5),
|
touchTooltipData: LineTouchTooltipData(
|
||||||
tooltipBorderRadius: BorderRadius.circular(8),
|
tooltipPadding: const EdgeInsets.all(5),
|
||||||
getTooltipItems: (List<LineBarSpot> touchedSpots) {
|
tooltipBorderRadius: BorderRadius.circular(8),
|
||||||
return touchedSpots.map((e) {
|
getTooltipItems: (List<LineBarSpot> touchedSpots) {
|
||||||
return LineTooltipItem(
|
return touchedSpots.map((e) {
|
||||||
'$tooltipPrefix${e.barIndex}: ${e.y.toStringAsFixed(2)}',
|
return LineTooltipItem(
|
||||||
const TextStyle(
|
'$tooltipPrefix${e.barIndex}: ${e.y.toStringAsFixed(2)}',
|
||||||
fontSize: 12,
|
const TextStyle(fontSize: 12, fontWeight: FontWeight.bold),
|
||||||
fontWeight: FontWeight.bold,
|
);
|
||||||
),
|
}).toList();
|
||||||
);
|
},
|
||||||
}).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,
|
titlesData: FlTitlesData(
|
||||||
),
|
show: true,
|
||||||
gridData: FlGridData(
|
rightTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||||
show: true,
|
topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||||
drawVerticalLine: false,
|
bottomTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||||
horizontalInterval: verticalInterval.toDouble(),
|
leftTitles: AxisTitles(
|
||||||
getDrawingHorizontalLine: (value) {
|
sideTitles: SideTitles(
|
||||||
return const FlLine(
|
showTitles: true,
|
||||||
color: Color.fromARGB(43, 88, 91, 94),
|
interval: 20,
|
||||||
strokeWidth: 1,
|
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);
|
||||||
titlesData: FlTitlesData(
|
},
|
||||||
show: true,
|
reservedSize: 27,
|
||||||
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),
|
||||||
borderData: FlBorderData(show: false),
|
minY: -1,
|
||||||
minY: -1,
|
maxY: 101,
|
||||||
maxY: 101,
|
lineBarsData: spots
|
||||||
lineBarsData: spots
|
.map(
|
||||||
.map((e) => LineChartBarData(
|
(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(),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,32 +32,26 @@ 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,
|
||||||
[
|
_buildCPUView,
|
||||||
_buildAbout,
|
_buildMemView,
|
||||||
_buildCPUView,
|
_buildSwapView,
|
||||||
_buildMemView,
|
_buildGpuView,
|
||||||
_buildSwapView,
|
_buildDiskView,
|
||||||
_buildGpuView,
|
_buildNetView,
|
||||||
_buildDiskView,
|
_buildSensors,
|
||||||
_buildNetView,
|
_buildTemperature,
|
||||||
_buildSensors,
|
_buildBatteries,
|
||||||
_buildTemperature,
|
_buildPve,
|
||||||
_buildBatteries,
|
_buildCustomCmd,
|
||||||
_buildPve,
|
]);
|
||||||
_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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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>(
|
||||||
return _buildVirtualKey();
|
builder: (_, __, ___) {
|
||||||
}),
|
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;
|
||||||
|
|
||||||
|
|||||||
@@ -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';
|
||||||
|
|||||||
@@ -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(),
|
||||||
|
|||||||
@@ -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(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user