diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 6b8faeef..2157d395 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -354,7 +354,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -362,7 +362,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.83; + MARKETING_VERSION = 1.0.84; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -484,7 +484,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -492,7 +492,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.83; + MARKETING_VERSION = 1.0.84; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; @@ -508,7 +508,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; - CURRENT_PROJECT_VERSION = 83; + CURRENT_PROJECT_VERSION = 84; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -516,7 +516,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.83; + MARKETING_VERSION = 1.0.84; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; diff --git a/lib/data/res/build_data.dart b/lib/data/res/build_data.dart index b9cece62..3f1f5e90 100644 --- a/lib/data/res/build_data.dart +++ b/lib/data/res/build_data.dart @@ -2,9 +2,9 @@ class BuildData { static const String name = "ServerBox"; - static const int build = 83; + static const int build = 84; static const String engine = "Flutter 2.8.1 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision 77d935af4d (4 weeks ago) • 2021-12-16 08:37:33 -0800\nEngine • revision 890a5fca2e\nTools • Dart 2.15.1\n"; - static const String buildAt = "2022-01-16 15:14:10.759902"; - static const int modifications = 6; + static const String buildAt = "2022-01-16 15:21:07.640484"; + static const int modifications = 3; } diff --git a/lib/data/res/tab.dart b/lib/data/res/tab.dart new file mode 100644 index 00000000..a147a006 --- /dev/null +++ b/lib/data/res/tab.dart @@ -0,0 +1 @@ +final List tabs = ['Servers', 'En/Decode', 'Ping']; \ No newline at end of file diff --git a/lib/data/store/setting.dart b/lib/data/store/setting.dart index 06333884..cf4541ad 100644 --- a/lib/data/store/setting.dart +++ b/lib/data/store/setting.dart @@ -6,4 +6,6 @@ class SettingStore extends PersistentStore { property('primaryColor', defaultValue: Colors.deepPurpleAccent.value); StoreProperty get serverStatusUpdateInterval => property('serverStatusUpdateInterval', defaultValue: 3); + StoreProperty get launchPage => + property('launchPage', defaultValue: 0); } diff --git a/lib/view/page/home.dart b/lib/view/page/home.dart index dc5fdbe9..18afe422 100644 --- a/lib/view/page/home.dart +++ b/lib/view/page/home.dart @@ -9,10 +9,13 @@ import 'package:toolbox/core/utils.dart'; import 'package:toolbox/data/provider/server.dart'; import 'package:toolbox/data/res/build_data.dart'; import 'package:toolbox/data/res/icon/common.dart'; +import 'package:toolbox/data/res/tab.dart'; import 'package:toolbox/data/res/url.dart'; +import 'package:toolbox/data/store/setting.dart'; import 'package:toolbox/locator.dart'; import 'package:toolbox/view/page/convert.dart'; import 'package:toolbox/view/page/debug.dart'; +import 'package:toolbox/view/page/ping.dart'; import 'package:toolbox/view/page/private_key/list.dart'; import 'package:toolbox/view/page/server/tab.dart'; import 'package:toolbox/view/page/setting.dart'; @@ -33,7 +36,6 @@ class _MyHomePageState extends State SingleTickerProviderStateMixin, AfterLayoutMixin, WidgetsBindingObserver { - final List _tabs = ['Servers', 'En/Decode']; late final TabController _tabController; late final ServerProvider _serverProvider; @@ -42,7 +44,7 @@ class _MyHomePageState extends State super.initState(); _serverProvider = locator(); WidgetsBinding.instance?.addObserver(this); - _tabController = TabController(length: _tabs.length, vsync: this); + _tabController = TabController(initialIndex: locator().launchPage.fetch()!, length: tabs.length, vsync: this); } @override @@ -75,15 +77,14 @@ class _MyHomePageState extends State ), bottom: TabBar( indicatorColor: widget.primaryColor, - tabs: _tabs.map((e) => Tab(text: e)).toList(), + tabs: tabs.map((e) => Tab(text: e)).toList(), controller: _tabController, ), ), drawer: _buildDrawer(), - body: TabBarView(controller: _tabController, children: const [ - ServerPage(), - ConvertPage(), - ]), + body: TabBarView( + controller: _tabController, + children: const [ServerPage(), ConvertPage(), PingPage()]), ); } diff --git a/lib/view/page/ping.dart b/lib/view/page/ping.dart new file mode 100644 index 00000000..82122b6e --- /dev/null +++ b/lib/view/page/ping.dart @@ -0,0 +1,145 @@ +import 'dart:io'; + +import 'package:dart_ping/dart_ping.dart'; +import 'package:dart_ping_ios/dart_ping_ios.dart'; +import 'package:flutter/material.dart'; +import 'package:toolbox/core/utils.dart'; +import 'package:toolbox/data/res/color.dart'; + +class PingPage extends StatefulWidget { + const PingPage({Key? key}) : super(key: key); + + @override + _PingPageState createState() => _PingPageState(); +} + +class _PingPageState extends State + with AutomaticKeepAliveClientMixin { + late TextEditingController _textEditingController; + late TextEditingController _textEditingControllerResult; + late MediaQueryData _media; + late String _result; + late Ping _ping; + + @override + void initState() { + super.initState(); + _textEditingController = TextEditingController(text: ''); + _textEditingControllerResult = TextEditingController(text: ''); + if (Platform.isIOS) { + DartPingIOS.register(); + } + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + _media = MediaQuery.of(context); + } + + @override + Widget build(BuildContext context) { + super.build(context); + return Scaffold( + body: GestureDetector( + child: SingleChildScrollView( + padding: const EdgeInsets.symmetric(horizontal: 7), + child: Column(children: [ + const SizedBox(height: 13), + _buildInputTop(), + _buildControl(), + _buildResult(), + ])), + onTap: () => FocusScope.of(context).requestFocus(FocusNode()), + ), + ); + } + + void doPing() { + _result = ''; + _ping = Ping(_textEditingController.text.trim()); + _ping.stream.listen((event) { + final resp = event.response.toString(); + if (resp == 'null') return; + _result += '$resp\n'; + _textEditingControllerResult.text = _result; + }); + } + + Widget _buildControl() { + return SizedBox( + height: 57, + child: Card( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + TextButton( + style: ButtonStyle( + foregroundColor: MaterialStateProperty.all(primaryColor)), + child: Row( + children: const [ + Icon(Icons.stop), + SizedBox( + width: 7, + ), + Text('Stop') + ], + ), + onPressed: () { + _ping.stop(); + }, + ), + TextButton( + style: ButtonStyle( + foregroundColor: MaterialStateProperty.all(primaryColor)), + child: Row( + children: const [ + Icon(Icons.play_arrow), + SizedBox( + width: 7, + ), + Text('Start') + ], + ), + onPressed: () { + try { + doPing(); + } catch (e) { + showSnackBar(context, Text('Error: \n$e')); + } + }, + ) + ], + ), + ), + ); + } + + Widget _buildInputTop() { + return _buildInput(_textEditingController, maxLines: 1, hint: 'Type here.'); + } + + Widget _buildResult() { + return SizedBox( + height: _media.size.height * 0.47, + child: _buildInput(_textEditingControllerResult, hint: 'Result here.'), + ); + } + + Widget _buildInput(TextEditingController controller, {int maxLines = 20, String? hint}) { + return Card( + child: TextField( + maxLines: maxLines, + decoration: InputDecoration( + fillColor: Theme.of(context).cardColor, + hintText: hint, + filled: true, + border: InputBorder.none), + controller: controller, + ), + ); + } + + @override + bool get wantKeepAlive => true; +} diff --git a/lib/view/page/setting.dart b/lib/view/page/setting.dart index e0cd30fb..5ea752ad 100644 --- a/lib/view/page/setting.dart +++ b/lib/view/page/setting.dart @@ -6,6 +6,7 @@ import 'package:toolbox/data/provider/app.dart'; import 'package:toolbox/data/provider/server.dart'; import 'package:toolbox/data/res/build_data.dart'; import 'package:toolbox/data/res/color.dart'; +import 'package:toolbox/data/res/tab.dart'; import 'package:toolbox/data/store/setting.dart'; import 'package:toolbox/locator.dart'; import 'package:toolbox/view/widget/round_rect_card.dart'; @@ -20,15 +21,20 @@ class SettingPage extends StatefulWidget { class _SettingPageState extends State { late SettingStore _store; late int _selectedColorValue; + late int _launchPageIdx; double _intervalValue = 0; late Color priColor; static const textStyle = TextStyle(fontSize: 14); late final ServerProvider _serverProvider; + late MediaQueryData _media; + late ThemeData _theme; @override void didChangeDependencies() { super.didChangeDependencies(); priColor = primaryColor; + _media = MediaQuery.of(context); + _theme = Theme.of(context); } @override @@ -36,6 +42,7 @@ class _SettingPageState extends State { super.initState(); _serverProvider = locator(); _store = locator(); + _launchPageIdx = _store.launchPage.fetch()!; _intervalValue = _store.serverStatusUpdateInterval.fetch()!.toDouble(); } @@ -50,7 +57,8 @@ class _SettingPageState extends State { children: [ _buildAppColorPreview(), _buildUpdateInterval(), - _buildCheckUpdate() + _buildCheckUpdate(), + _buildLaunchPage() ].map((e) => RoundRectCard(e)).toList(), ), ); @@ -171,4 +179,47 @@ class _SettingPageState extends State { }), ); } + + Widget _buildLaunchPage() { + return ExpansionTile( + tilePadding: EdgeInsets.zero, + childrenPadding: EdgeInsets.zero, + title: const Text( + 'Launch page', + style: textStyle, + ), + trailing: ConstrainedBox( + constraints: BoxConstraints(maxWidth: _media.size.width * 0.35), + child: Text( + tabs[_launchPageIdx], + textScaleFactor: 1.0, + textAlign: TextAlign.right, + ), + ), + children: tabs + .map((e) => ListTile( + contentPadding: EdgeInsets.zero, + title: Text( + e, + style: TextStyle( + color: _theme.textTheme.bodyText2!.color!.withAlpha(177)), + ), + trailing: _buildRadio(tabs.indexOf(e)), + )) + .toList(), + ); + } + + Radio _buildRadio(int index) { + return Radio( + value: index, + groupValue: _launchPageIdx, + onChanged: (int? value) { + setState(() { + _launchPageIdx = value!; + _store.launchPage.put(value); + }); + }, + ); + } } diff --git a/pubspec.lock b/pubspec.lock index 2ee598e6..a7612f04 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -60,9 +60,11 @@ packages: circle_chart: dependency: "direct main" description: - path: "../circle_chart" - relative: true - source: path + path: "." + ref: main + resolved-ref: "01eb9bcc7f1a1690381caeedb476ea98c5295d55" + url: "https://github.com/LollipopKit/circle_chart" + source: git version: "0.0.3" clipboard: dependency: "direct main" @@ -115,6 +117,20 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "1.0.0" + dart_ping: + dependency: "direct main" + description: + name: dart_ping + url: "https://pub.dartlang.org" + source: hosted + version: "6.1.1" + dart_ping_ios: + dependency: "direct main" + description: + name: dart_ping_ios + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.0" dartssh2: dependency: "direct main" description: @@ -176,6 +192,13 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_icmp_ping: + dependency: transitive + description: + name: flutter_icmp_ping + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.2" flutter_lints: dependency: "direct dev" description: diff --git a/pubspec.yaml b/pubspec.yaml index d5d6f133..69405b75 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -46,14 +46,16 @@ dependencies: logging: ^1.0.2 flutter_material_color_picker: ^1.1.0+2 circle_chart: - # git: - # url: https://github.com/LollipopKit/circle_chart - # ref: main - path: ../circle_chart + git: + url: https://github.com/LollipopKit/circle_chart + ref: main + # path: ../circle_chart clipboard: ^0.1.3 r_upgrade: ^0.3.6 pull_to_refresh: ^2.0.0 marquee: ^2.2.0 + dart_ping: ^6.1.1 + dart_ping_ios: ^1.0.0 dev_dependencies: