diff --git a/README.md b/README.md index daf7dc09..2f2a2be0 100644 --- a/README.md +++ b/README.md @@ -38,9 +38,9 @@ A new Flutter project which provide a chart view to display server status data. - [x] Private key store - [x] Server status detail page - [x] Theme switch -- [ ] Execute snippet +- [x] Execute snippet - [ ] Migrate from `ssh2` to `dartssh2` -- [ ] Desktop support. +- [ ] Desktop support ## Build Please use `make.dart` to build. diff --git a/ios/Podfile.lock b/ios/Podfile.lock index af06893b..e157f12f 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -5,6 +5,8 @@ PODS: - GZ-NMSSH (4.1.5) - path_provider (0.0.1): - Flutter + - r_upgrade (0.0.1): + - Flutter - ssh2 (2.2.3): - Flutter - GZ-NMSSH (~> 4.1.5) @@ -15,6 +17,7 @@ DEPENDENCIES: - countly_flutter (from `.symlinks/plugins/countly_flutter/ios`) - Flutter (from `Flutter`) - path_provider (from `.symlinks/plugins/path_provider/ios`) + - r_upgrade (from `.symlinks/plugins/r_upgrade/ios`) - ssh2 (from `.symlinks/plugins/ssh2/ios`) - url_launcher (from `.symlinks/plugins/url_launcher/ios`) @@ -29,6 +32,8 @@ EXTERNAL SOURCES: :path: Flutter path_provider: :path: ".symlinks/plugins/path_provider/ios" + r_upgrade: + :path: ".symlinks/plugins/r_upgrade/ios" ssh2: :path: ".symlinks/plugins/ssh2/ios" url_launcher: @@ -39,6 +44,7 @@ SPEC CHECKSUMS: Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a GZ-NMSSH: d749f8ae2fd0094b953cd1d5abd8e0cab3c93f8d path_provider: d1e9807085df1f9cc9318206cd649dc0b76be3de + r_upgrade: 44d715c61914cce3d01ea225abffe894fd51c114 ssh2: 74165efc99417a075ecafd52caf93edadfb5eb60 url_launcher: b6e016d912f04be9f5bf6e8e82dc599b7ba59649 diff --git a/lib/data/model/server/server_status.dart b/lib/data/model/server/server_status.dart index 2204458d..fb6343c3 100644 --- a/lib/data/model/server/server_status.dart +++ b/lib/data/model/server/server_status.dart @@ -40,5 +40,6 @@ class ServerStatus { String? failedInfo; ServerStatus(this.cpu2Status, this.memory, this.sysVer, this.uptime, - this.disk, this.tcp, this.netSpeed, {this.failedInfo}); + this.disk, this.tcp, this.netSpeed, + {this.failedInfo}); } diff --git a/lib/data/res/build_data.dart b/lib/data/res/build_data.dart index f1221f1a..f5c9d9ce 100644 --- a/lib/data/res/build_data.dart +++ b/lib/data/res/build_data.dart @@ -2,8 +2,9 @@ class BuildData { static const String name = "ToolBox"; - static const int build = 64; - static const String engine = "Flutter 2.5.3 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision 18116933e7 (5 weeks ago) • 2021-10-15 10:46:35 -0700\nEngine • revision d3ea636dc5\nTools • Dart 2.14.4\n"; - static const String buildAt = "2021-11-21 19:42:23.223010"; - static const int modifications = 2; + static const int build = 65; + static const String engine = + "Flutter 2.8.1 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision 77d935af4d (2 weeks ago) • 2021-12-16 08:37:33 -0800\nEngine • revision 890a5fca2e\nTools • Dart 2.15.1\n"; + static const String buildAt = "2021-12-31 15:55:47.350456"; + static const int modifications = 7; } diff --git a/lib/view/page/server/tab.dart b/lib/view/page/server/tab.dart index 8bd5b447..05dae129 100644 --- a/lib/view/page/server/tab.dart +++ b/lib/view/page/server/tab.dart @@ -1,15 +1,16 @@ import 'package:after_layout/after_layout.dart'; import 'package:circle_chart/circle_chart.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; import 'package:flutter_staggered_animations/flutter_staggered_animations.dart'; import 'package:get_it/get_it.dart'; import 'package:provider/provider.dart'; +import 'package:pull_to_refresh/pull_to_refresh.dart'; import 'package:toolbox/core/route.dart'; import 'package:toolbox/data/model/server/server.dart'; import 'package:toolbox/data/model/server/server_connection_state.dart'; import 'package:toolbox/data/model/server/server_status.dart'; import 'package:toolbox/data/provider/server.dart'; +import 'package:toolbox/data/res/color.dart'; import 'package:toolbox/data/store/setting.dart'; import 'package:toolbox/locator.dart'; import 'package:toolbox/view/page/server/detail.dart'; @@ -27,6 +28,7 @@ class _ServerPageState extends State late MediaQueryData _media; late ThemeData _theme; late Color _primaryColor; + late RefreshController _refreshController; late ServerProvider _serverProvider; @@ -34,6 +36,7 @@ class _ServerPageState extends State void initState() { super.initState(); _serverProvider = locator(); + _refreshController = RefreshController(); } @override @@ -41,41 +44,53 @@ class _ServerPageState extends State super.didChangeDependencies(); _media = MediaQuery.of(context); _theme = Theme.of(context); - _primaryColor = Color(locator().primaryColor.fetch()!); + _primaryColor = primaryColor; } @override Widget build(BuildContext context) { super.build(context); - return Scaffold( - body: Consumer(builder: (_, pro, __) { - if (pro.servers.isEmpty) { - return const Center( - child: Text( - 'There is no server.\nClick the fab to add one.', - textAlign: TextAlign.center, - ), - ); - } - return SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: 7), - child: AnimationLimiter( - child: Column( - children: AnimationConfiguration.toStaggeredList( - duration: const Duration(milliseconds: 377), - childAnimationBuilder: (widget) => SlideAnimation( - verticalOffset: 50.0, - child: FadeInAnimation( - child: widget, - ), - ), - children: [ - const SizedBox(height: 13), - ...pro.servers.map((e) => _buildEachServerCard(e)) - ], - ))), + final autoUpdate = + locator().serverStatusUpdateInterval.fetch() != 0; + final child = Consumer(builder: (_, pro, __) { + if (pro.servers.isEmpty) { + return const Center( + child: Text( + 'There is no server.\nClick the fab to add one.', + textAlign: TextAlign.center, + ), ); - }), + } + return SingleChildScrollView( + padding: const EdgeInsets.symmetric(horizontal: 7), + child: AnimationLimiter( + child: Column( + children: AnimationConfiguration.toStaggeredList( + duration: const Duration(milliseconds: 377), + childAnimationBuilder: (widget) => SlideAnimation( + verticalOffset: 50.0, + child: FadeInAnimation( + child: widget, + ), + ), + children: [ + const SizedBox(height: 13), + ...pro.servers.map((e) => _buildEachServerCard(e)) + ], + ))), + ); + }); + return Scaffold( + body: autoUpdate + ? child + : SmartRefresher( + controller: _refreshController, + child: child, + onRefresh: () async { + await _serverProvider.refreshData(); + _refreshController.refreshCompleted(); + }, + ), floatingActionButton: FloatingActionButton( onPressed: () => AppRoute(const ServerEditPage(), 'Add server info page') @@ -124,7 +139,9 @@ class _ServerPageState extends State style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 12), textScaleFactor: 1.0, ), - Text(getTopRightStr(cs, ss.cpu2Status.temp, ss.uptime, ss.failedInfo), + Text( + getTopRightStr( + cs, ss.cpu2Status.temp, ss.uptime, ss.failedInfo), textScaleFactor: 1.0, style: TextStyle( color: _theme.textTheme.bodyText1!.color!.withAlpha(100), @@ -149,7 +166,8 @@ class _ServerPageState extends State ); } - String getTopRightStr(ServerConnectionState cs, String temp, String upTime, String? failedInfo) { + String getTopRightStr(ServerConnectionState cs, String temp, String upTime, + String? failedInfo) { switch (cs) { case ServerConnectionState.disconnected: return 'Disconnected'; diff --git a/lib/view/page/setting.dart b/lib/view/page/setting.dart index be34eb15..a617c8f6 100644 --- a/lib/view/page/setting.dart +++ b/lib/view/page/setting.dart @@ -113,7 +113,8 @@ class _SettingPageState extends State { height: 3, ), _intervalValue == 0.0 - ? const Text('You set to 0, will not update automatically.') + ? const Text('You set to 0, will not update automatically.\nYou can pull to refresh manually.', + style: TextStyle(color: Colors.grey), textAlign: TextAlign.center,) : const SizedBox(), const SizedBox( height: 13, diff --git a/lib/view/page/snippet/list.dart b/lib/view/page/snippet/list.dart index 77210826..acbdd1ae 100644 --- a/lib/view/page/snippet/list.dart +++ b/lib/view/page/snippet/list.dart @@ -122,7 +122,8 @@ class _SnippetListPageState extends State { final result = await locator() .runSnippet(_selectedIndex, snippet); if (result != null) { - showRoundDialog(context, 'Result', Text(result, style: const TextStyle(fontSize: 13)), [ + showRoundDialog(context, 'Result', + Text(result, style: const TextStyle(fontSize: 13)), [ TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Close')) diff --git a/pubspec.lock b/pubspec.lock index 89ee6901..cd0905ff 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -28,7 +28,7 @@ packages: name: async url: "https://pub.dartlang.org" source: hosted - version: "2.8.1" + version: "2.8.2" boolean_selector: dependency: transitive description: @@ -42,7 +42,7 @@ packages: name: characters url: "https://pub.dartlang.org" source: hosted - version: "1.1.0" + version: "1.2.0" charcode: dependency: transitive description: @@ -264,7 +264,7 @@ packages: name: matcher url: "https://pub.dartlang.org" source: hosted - version: "0.12.10" + version: "0.12.11" meta: dependency: transitive description: @@ -363,6 +363,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "6.0.1" + pull_to_refresh: + dependency: "direct main" + description: + name: pull_to_refresh + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0" r_upgrade: dependency: "direct main" description: @@ -423,7 +430,7 @@ packages: name: test_api url: "https://pub.dartlang.org" source: hosted - version: "0.4.2" + version: "0.4.3" typed_data: dependency: transitive description: @@ -493,7 +500,7 @@ packages: name: vector_math url: "https://pub.dartlang.org" source: hosted - version: "2.1.0" + version: "2.1.1" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index ad1c7fc4..3fe4f2b8 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -52,6 +52,7 @@ dependencies: ref: main clipboard: ^0.1.3 r_upgrade: ^0.3.6 + pull_to_refresh: ^2.0.0 dev_dependencies: