From 1bd43829bb7e35a95ce6b3969caf1ea6b66bd138 Mon Sep 17 00:00:00 2001 From: Junyuan Feng Date: Fri, 4 Feb 2022 18:52:35 +0800 Subject: [PATCH] Improve UI. Rounded Card. --- ios/Runner.xcodeproj/project.pbxproj | 12 +- lib/data/model/server/server.dart | 3 +- lib/data/provider/server.dart | 7 +- lib/data/res/build_data.dart | 6 +- lib/data/res/padding.dart | 3 + lib/view/page/convert.dart | 5 +- lib/view/page/ping.dart | 10 +- lib/view/page/private_key/list.dart | 5 +- lib/view/page/server/detail.dart | 17 ++- lib/view/page/server/tab.dart | 218 ++++++++++++++++++++++----- lib/view/page/setting.dart | 15 +- lib/view/page/snippet/list.dart | 50 +++--- lib/view/widget/input_field.dart | 5 +- lib/view/widget/round_rect_card.dart | 7 +- pubspec.lock | 7 + pubspec.yaml | 1 + 16 files changed, 271 insertions(+), 100 deletions(-) create mode 100644 lib/data/res/padding.dart diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 7af7ebd9..a1e4e35b 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 = 85; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -362,7 +362,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.85; + MARKETING_VERSION = 1.0.88; 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 = 85; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -492,7 +492,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.85; + MARKETING_VERSION = 1.0.88; 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 = 85; + CURRENT_PROJECT_VERSION = 88; DEVELOPMENT_TEAM = BA88US33G6; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -516,7 +516,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.0.85; + MARKETING_VERSION = 1.0.88; PRODUCT_BUNDLE_IDENTIFIER = com.lollipopkit.toolbox; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; diff --git a/lib/data/model/server/server.dart b/lib/data/model/server/server.dart index 89cecffa..41e0c656 100644 --- a/lib/data/model/server/server.dart +++ b/lib/data/model/server/server.dart @@ -9,6 +9,5 @@ class ServerInfo { SSHClient? client; ServerConnectionState connectionState; - ServerInfo( - this.info, this.status, this.client, this.connectionState); + ServerInfo(this.info, this.status, this.client, this.connectionState); } diff --git a/lib/data/provider/server.dart b/lib/data/provider/server.dart index 00309032..670b6427 100644 --- a/lib/data/provider/server.dart +++ b/lib/data/provider/server.dart @@ -324,8 +324,11 @@ class ServerProvider extends BusyProvider { notifyListeners(); } - Future runSnippet(int idx, Snippet snippet) async { - final result = await _servers[idx].client!.run(snippet.script); + Future runSnippet(ServerPrivateInfo spi, Snippet snippet) async { + final result = await _servers + .firstWhere((element) => element.info == spi) + .client! + .run(snippet.script); return utf8.decode(result); } } diff --git a/lib/data/res/build_data.dart b/lib/data/res/build_data.dart index 35f79695..cb559bb2 100644 --- a/lib/data/res/build_data.dart +++ b/lib/data/res/build_data.dart @@ -2,8 +2,8 @@ class BuildData { static const String name = "ServerBox"; - static const int build = 87; + static const int build = 88; static const String engine = "Flutter 2.8.1 • channel stable • https://github.com/flutter/flutter.git\nFramework • revision 77d935af4d (7 weeks ago) • 2021-12-16 08:37:33 -0800\nEngine • revision 890a5fca2e\nTools • Dart 2.15.1\n"; - static const String buildAt = "2022-02-02 13:20:22.346643"; - static const int modifications = 8; + static const String buildAt = "2022-02-04 18:44:51.481488"; + static const int modifications = 16; } diff --git a/lib/data/res/padding.dart b/lib/data/res/padding.dart new file mode 100644 index 00000000..6bd3e296 --- /dev/null +++ b/lib/data/res/padding.dart @@ -0,0 +1,3 @@ +import 'package:flutter/material.dart'; + +const roundRectCardPadding = EdgeInsets.symmetric(horizontal: 17); diff --git a/lib/view/page/convert.dart b/lib/view/page/convert.dart index b722fb5c..1a329875 100644 --- a/lib/view/page/convert.dart +++ b/lib/view/page/convert.dart @@ -5,6 +5,7 @@ import 'package:flutter/material.dart'; import 'package:toolbox/core/utils.dart'; import 'package:toolbox/data/res/color.dart'; import 'package:toolbox/view/widget/input_field.dart'; +import 'package:toolbox/view/widget/round_rect_card.dart'; class ConvertPage extends StatefulWidget { const ConvertPage({Key? key}) : super(key: key); @@ -95,8 +96,8 @@ class _ConvertPageState extends State } Widget _buildTypeOption() { - return Card( - child: ExpansionTile( + return RoundRectCard( + ExpansionTile( tilePadding: const EdgeInsets.only(left: 7, right: 27), childrenPadding: EdgeInsets.zero, title: Row( diff --git a/lib/view/page/ping.dart b/lib/view/page/ping.dart index 8ed5f3e2..54ff406d 100644 --- a/lib/view/page/ping.dart +++ b/lib/view/page/ping.dart @@ -6,6 +6,7 @@ import 'package:flutter/material.dart'; import 'package:toolbox/core/utils.dart'; import 'package:toolbox/data/res/color.dart'; import 'package:toolbox/view/widget/input_field.dart'; +import 'package:toolbox/view/widget/round_rect_card.dart'; class PingPage extends StatefulWidget { const PingPage({Key? key}) : super(key: key); @@ -46,10 +47,9 @@ class _PingPageState extends State child: Column(children: [ const SizedBox(height: 13), buildInput(context, _textEditingController, - maxLines: 1, hint: 'Type here.'), + maxLines: 1), _buildControl(), - buildInput(context, _textEditingControllerResult, - hint: 'Result here.'), + buildInput(context, _textEditingControllerResult), ])), onTap: () => FocusScope.of(context).requestFocus(FocusNode()), ), @@ -70,8 +70,8 @@ class _PingPageState extends State Widget _buildControl() { return SizedBox( height: 57, - child: Card( - child: InkWell( + child: RoundRectCard( + InkWell( onTap: () => FocusScope.of(context).unfocus(), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, diff --git a/lib/view/page/private_key/list.dart b/lib/view/page/private_key/list.dart index e12f9cf3..9c4ca6e9 100644 --- a/lib/view/page/private_key/list.dart +++ b/lib/view/page/private_key/list.dart @@ -3,6 +3,7 @@ import 'package:provider/provider.dart'; import 'package:toolbox/core/route.dart'; import 'package:toolbox/data/provider/private_key.dart'; import 'package:toolbox/data/res/color.dart'; +import 'package:toolbox/data/res/padding.dart'; import 'package:toolbox/view/page/private_key/edit.dart'; import 'package:toolbox/view/widget/round_rect_card.dart'; @@ -29,7 +30,7 @@ class _PrivateKeyListState extends State { itemCount: key.infos.length, itemExtent: 57, itemBuilder: (context, idx) { - return RoundRectCard(Row( + return RoundRectCard(Padding(padding: roundRectCardPadding, child: Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -47,7 +48,7 @@ class _PrivateKeyListState extends State { style: _textStyle, )) ], - )); + ),)); }) : const Center(child: Text('No saved private keys.')); }, diff --git a/lib/view/page/server/detail.dart b/lib/view/page/server/detail.dart index 0454efda..4664ded3 100644 --- a/lib/view/page/server/detail.dart +++ b/lib/view/page/server/detail.dart @@ -6,6 +6,7 @@ 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/res/icon/linux_icons.dart'; +import 'package:toolbox/data/res/padding.dart'; import 'package:toolbox/view/widget/round_rect_card.dart'; const style11 = TextStyle(fontSize: 11); @@ -44,7 +45,7 @@ class _ServerDetailPageState extends State title: Text(si.info.name), ), body: ListView( - padding: const EdgeInsets.all(17), + padding: const EdgeInsets.all(13), children: [ _buildLinuxIcon(si.status.sysVer), SizedBox(height: _media.size.height * 0.03), @@ -68,7 +69,7 @@ class _ServerDetailPageState extends State Widget _buildCPUView(ServerStatus ss) { return RoundRectCard( - SizedBox( + Padding(padding: roundRectCardPadding, child: SizedBox( height: 12 * ss.cpu2Status.coresCount + 67, child: Column(children: [ SizedBox( @@ -103,7 +104,7 @@ class _ServerDetailPageState extends State ), _buildCPUProgress(ss) ]), - ), + ),), ); } @@ -158,7 +159,7 @@ class _ServerDetailPageState extends State Widget _buildUpTimeAndSys(ServerStatus ss) { return RoundRectCard(Padding( - padding: const EdgeInsets.symmetric(vertical: 13), + padding: const EdgeInsets.symmetric(vertical: 13, horizontal: 17), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -191,7 +192,7 @@ class _ServerDetailPageState extends State final pColor = primaryColor; final used = ss.memory.used / ss.memory.total; final width = _media.size.width - 17 * 2 - 17 * 2; - return RoundRectCard(SizedBox( + return RoundRectCard(Padding(padding: roundRectCardPadding, child: SizedBox( height: 47, child: Column( crossAxisAlignment: CrossAxisAlignment.center, @@ -233,7 +234,7 @@ class _ServerDetailPageState extends State ) ], ), - )); + ),)); } Widget _buildMemExplain(String value, Color color) { @@ -265,7 +266,7 @@ class _ServerDetailPageState extends State return RoundRectCard(SizedBox( height: 27 * clone.length + 25, child: ListView.builder( - padding: const EdgeInsets.symmetric(vertical: 13), + padding: const EdgeInsets.symmetric(vertical: 13, horizontal: 17), physics: const NeverScrollableScrollPhysics(), itemCount: clone.length, itemBuilder: (_, idx) { @@ -302,7 +303,7 @@ class _ServerDetailPageState extends State ]; children.addAll(ns.devices.map((e) => _buildNetSpeedItem(ns, e))); return RoundRectCard(Padding( - padding: const EdgeInsets.symmetric(vertical: 7), + padding: const EdgeInsets.symmetric(vertical: 7, horizontal: 17), child: Column( children: children, ), diff --git a/lib/view/page/server/tab.dart b/lib/view/page/server/tab.dart index 9d08872f..f8f8c9ce 100644 --- a/lib/view/page/server/tab.dart +++ b/lib/view/page/server/tab.dart @@ -1,5 +1,6 @@ import 'package:after_layout/after_layout.dart'; import 'package:circle_chart/circle_chart.dart'; +import 'package:dropdown_button2/dropdown_button2.dart'; import 'package:flutter/material.dart'; import 'package:get_it/get_it.dart'; import 'package:marquee/marquee.dart'; @@ -8,6 +9,7 @@ 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_private_info.dart'; import 'package:toolbox/data/model/server/server_status.dart'; import 'package:toolbox/data/provider/server.dart'; import 'package:toolbox/data/res/color.dart'; @@ -15,6 +17,8 @@ import 'package:toolbox/data/store/setting.dart'; import 'package:toolbox/locator.dart'; import 'package:toolbox/view/page/server/detail.dart'; import 'package:toolbox/view/page/server/edit.dart'; +import 'package:toolbox/view/page/snippet/list.dart'; +import 'package:toolbox/view/widget/round_rect_card.dart'; class ServerPage extends StatefulWidget { final TabController tabController; @@ -47,8 +51,8 @@ class _ServerPageState extends State _theme = Theme.of(context); _primaryColor = primaryColor; if (widget.tabController.index == 0) { - FocusScope.of(context).unfocus(); - } + FocusScope.of(context).unfocus(); + } } @override @@ -65,15 +69,19 @@ class _ServerPageState extends State ), ); } - return SingleChildScrollView( - padding: const EdgeInsets.symmetric(horizontal: 7), - child: Column( - children: [ - const SizedBox(height: 13), - ...pro.servers.map((e) => _buildEachServerCard(e)), - SizedBox(height: _media.padding.bottom), - ], - )); + return ListView.separated( + padding: const EdgeInsets.all(7), + itemBuilder: (ctx, idx) { + if (idx == pro.servers.length) { + return SizedBox(height: _media.padding.bottom); + } + return _buildEachServerCard(pro.servers[idx]); + }, + itemCount: pro.servers.length + 1, + separatorBuilder: (_, __) => const SizedBox( + height: 3, + ), + ); }); return Scaffold( body: autoUpdate @@ -98,8 +106,8 @@ class _ServerPageState extends State } Widget _buildEachServerCard(ServerInfo si) { - return Card( - child: InkWell( + return RoundRectCard( + InkWell( onLongPress: () => AppRoute( ServerEditPage( spi: si.info, @@ -109,7 +117,7 @@ class _ServerPageState extends State child: Padding( padding: const EdgeInsets.all(13), child: _buildRealServerCard( - si.status, si.info.name, si.connectionState)), + si.status, si.info.name, si.connectionState, si.info)), onTap: () => AppRoute(ServerDetailPage('${si.info.ip}:${si.info.port}'), 'server detail page') .go(context), @@ -117,8 +125,8 @@ class _ServerPageState extends State ); } - Widget _buildRealServerCard( - ServerStatus ss, String serverName, ServerConnectionState cs) { + Widget _buildRealServerCard(ServerStatus ss, String serverName, + ServerConnectionState cs, ServerPrivateInfo spi) { final rootDisk = ss.disk.firstWhere((element) => element.mountLocation == '/'); @@ -132,29 +140,112 @@ class _ServerPageState extends State return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Text( - serverName, - style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 12), - textScaleFactor: 1.0, - ), - hasError - ? ConstrainedBox( - constraints: BoxConstraints( - maxWidth: _media.size.width * 0.57, maxHeight: 15), - child: Marquee( - accelerationDuration: const Duration(seconds: 3), - accelerationCurve: Curves.linear, - decelerationDuration: const Duration(seconds: 3), - decelerationCurve: Curves.linear, - text: topRightStr, - textScaleFactor: 1.0, - style: style), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 11), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Text( + serverName, + style: const TextStyle( + fontWeight: FontWeight.bold, fontSize: 12), + textScaleFactor: 1.0, + ), + const Icon( + Icons.keyboard_arrow_right, + size: 17, + color: Colors.grey, ) - : Text(topRightStr, style: style, textScaleFactor: 1.0), - ], + ], + ), + Row( + children: [ + hasError + ? ConstrainedBox( + constraints: BoxConstraints( + maxWidth: _media.size.width * 0.57, + maxHeight: 15), + child: Marquee( + accelerationDuration: const Duration(seconds: 3), + accelerationCurve: Curves.linear, + decelerationDuration: const Duration(seconds: 3), + decelerationCurve: Curves.linear, + text: topRightStr, + textScaleFactor: 1.0, + style: style), + ) + : Text(topRightStr, style: style, textScaleFactor: 1.0), + const SizedBox( + width: 13, + ), + DropdownButtonHideUnderline( + child: DropdownButton2( + customButton: const Icon( + Icons.list_alt, + size: 19, + ), + customItemsIndexes: const [3], + customItemsHeight: 8, + items: [ + ...MenuItems.firstItems.map( + (item) => DropdownMenuItem( + value: item, + child: MenuItems.buildItem(item), + ), + ), + const DropdownMenuItem( + enabled: false, child: Divider()), + ...MenuItems.secondItems.map( + (item) => DropdownMenuItem( + value: item, + child: MenuItems.buildItem(item), + ), + ), + ], + onChanged: (value) { + final item = value as MenuItem; + switch (item) { + case MenuItems.sftp: + //Do something + break; + case MenuItems.apt: + //Do something + break; + case MenuItems.snippet: + AppRoute( + SnippetListPage( + spi: spi, + ), + 'snippet list') + .go(context); + break; + case MenuItems.edit: + AppRoute( + ServerEditPage( + spi: spi, + ), + 'Edit server info page') + .go(context); + break; + } + }, + itemHeight: 37, + itemPadding: const EdgeInsets.only(left: 17, right: 17), + dropdownWidth: 160, + dropdownPadding: const EdgeInsets.symmetric(vertical: 7), + dropdownDecoration: BoxDecoration( + borderRadius: BorderRadius.circular(7), + ), + dropdownElevation: 8, + offset: const Offset(0, 8), + ), + ), + ], + ) + ], + ), ), const SizedBox( height: 17, @@ -286,3 +377,54 @@ class _ServerPageState extends State _serverProvider.startAutoRefresh(); } } + +class MenuItem { + final String text; + final IconData icon; + + const MenuItem({ + required this.text, + required this.icon, + }); +} + +class MenuItems { + static const List firstItems = [sftp, snippet, apt]; + static const List secondItems = [edit]; + + static const sftp = MenuItem(text: 'SFTP', icon: Icons.home); + static const snippet = MenuItem(text: 'Snippet', icon: Icons.label); + static const apt = MenuItem(text: 'Apt', icon: Icons.system_security_update); + static const edit = MenuItem(text: 'Edit', icon: Icons.settings); + + static Widget buildItem(MenuItem item) { + return Row( + children: [ + Icon(item.icon), + const SizedBox( + width: 10, + ), + Text( + item.text, + ), + ], + ); + } + + static onChanged(BuildContext context, MenuItem item) { + switch (item) { + case MenuItems.sftp: + //Do something + break; + case MenuItems.apt: + //Do something + break; + case MenuItems.snippet: + //Do something + break; + case MenuItems.edit: + //Do something + break; + } + } +} diff --git a/lib/view/page/setting.dart b/lib/view/page/setting.dart index 381a56a3..b2410d70 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/padding.dart'; import 'package:toolbox/data/res/tab.dart'; import 'package:toolbox/data/store/setting.dart'; import 'package:toolbox/locator.dart'; @@ -77,7 +78,7 @@ class _SettingPageState extends State { display = 'Current: v1.0.${BuildData.build}'; } return ListTile( - contentPadding: EdgeInsets.zero, + contentPadding: roundRectCardPadding, trailing: const Icon(Icons.keyboard_arrow_right), title: Text( display, @@ -90,8 +91,8 @@ class _SettingPageState extends State { Widget _buildUpdateInterval() { return ExpansionTile( - tilePadding: EdgeInsets.zero, - childrenPadding: EdgeInsets.zero, + tilePadding: roundRectCardPadding, + childrenPadding: roundRectCardPadding, textColor: priColor, title: const Text( 'Server status update interval', @@ -142,8 +143,8 @@ class _SettingPageState extends State { Widget _buildAppColorPreview() { return ExpansionTile( textColor: priColor, - tilePadding: EdgeInsets.zero, - childrenPadding: EdgeInsets.zero, + tilePadding: roundRectCardPadding, + childrenPadding: roundRectCardPadding, children: [ _buildAppColorPicker(priColor), _buildColorPickerConfirmBtn() @@ -183,8 +184,8 @@ class _SettingPageState extends State { Widget _buildLaunchPage() { return ExpansionTile( textColor: priColor, - tilePadding: EdgeInsets.zero, - childrenPadding: EdgeInsets.zero, + tilePadding: roundRectCardPadding, + childrenPadding: roundRectCardPadding, title: const Text( 'Launch page', style: textStyle, diff --git a/lib/view/page/snippet/list.dart b/lib/view/page/snippet/list.dart index acbdd1ae..5eb28d5d 100644 --- a/lib/view/page/snippet/list.dart +++ b/lib/view/page/snippet/list.dart @@ -2,23 +2,26 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:toolbox/core/route.dart'; import 'package:toolbox/core/utils.dart'; +import 'package:toolbox/data/model/server/server_private_info.dart'; import 'package:toolbox/data/model/server/snippet.dart'; import 'package:toolbox/data/provider/server.dart'; import 'package:toolbox/data/provider/snippet.dart'; import 'package:toolbox/data/res/color.dart'; +import 'package:toolbox/data/res/padding.dart'; import 'package:toolbox/locator.dart'; import 'package:toolbox/view/page/snippet/edit.dart'; import 'package:toolbox/view/widget/round_rect_card.dart'; class SnippetListPage extends StatefulWidget { - const SnippetListPage({Key? key}) : super(key: key); + const SnippetListPage({Key? key, this.spi}) : super(key: key); + final ServerPrivateInfo? spi; @override _SnippetListPageState createState() => _SnippetListPageState(); } class _SnippetListPageState extends State { - int _selectedIndex = 0; + late ServerPrivateInfo _selectedIndex; final _textStyle = TextStyle(color: primaryColor); @override @@ -45,7 +48,7 @@ class _SnippetListPageState extends State { itemCount: key.snippets.length, itemExtent: 57, itemBuilder: (context, idx) { - return RoundRectCard(Row( + return RoundRectCard(Padding(padding: roundRectCardPadding, child: Row( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -64,14 +67,21 @@ class _SnippetListPageState extends State { style: _textStyle, )), TextButton( - onPressed: () => _showRunDialog(key.snippets[idx]), + onPressed: () { + final snippet = key.snippets[idx]; + if (widget.spi == null) { + _showRunDialog(snippet); + return; + } + run(context, snippet); + }, child: Text( 'Run', style: _textStyle, )) ]) ], - )); + ),)); }) : const Center(child: Text('No saved snippets.')); }, @@ -84,6 +94,7 @@ class _SnippetListPageState extends State { if (provider.servers.isEmpty) { return const Text('No server available'); } + _selectedIndex = provider.servers.first.info; return SizedBox( height: 111, child: Stack(children: [ @@ -104,7 +115,8 @@ class _SnippetListPageState extends State { itemExtent: 37, diameterRatio: 1.2, controller: FixedExtentScrollController(initialItem: 0), - onSelectedItemChanged: (idx) => _selectedIndex = idx, + onSelectedItemChanged: (idx) => + _selectedIndex = provider.servers[idx].info, physics: const FixedExtentScrollPhysics(), childDelegate: ListWheelChildBuilderDelegate( builder: (context, index) => Center( @@ -118,22 +130,24 @@ class _SnippetListPageState extends State { ])); }), [ TextButton( - onPressed: () async { - final result = await locator() - .runSnippet(_selectedIndex, snippet); - if (result != null) { - showRoundDialog(context, 'Result', - Text(result, style: const TextStyle(fontSize: 13)), [ - TextButton( - onPressed: () => Navigator.of(context).pop(), - child: const Text('Close')) - ]); - } - }, + onPressed: () async => run(context, snippet), child: const Text('Run')), TextButton( onPressed: () => Navigator.of(context).pop(), child: const Text('Cancel')), ]); } + + Future run(BuildContext context, Snippet snippet) async { + final result = await locator() + .runSnippet(widget.spi ?? _selectedIndex, snippet); + if (result != null) { + showRoundDialog(context, 'Result', + Text(result, style: const TextStyle(fontSize: 13)), [ + TextButton( + onPressed: () => Navigator.of(context).pop(), + child: const Text('Close')) + ]); + } + } } diff --git a/lib/view/widget/input_field.dart b/lib/view/widget/input_field.dart index d79377fc..2eaf3da2 100644 --- a/lib/view/widget/input_field.dart +++ b/lib/view/widget/input_field.dart @@ -1,9 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:toolbox/view/widget/round_rect_card.dart'; Widget buildInput(BuildContext context, TextEditingController controller, {int maxLines = 20, String? hint}) { - return Card( - child: TextField( + return RoundRectCard( + TextField( maxLines: maxLines, decoration: InputDecoration( fillColor: Theme.of(context).cardColor, diff --git a/lib/view/widget/round_rect_card.dart b/lib/view/widget/round_rect_card.dart index 220acb1c..508d3912 100644 --- a/lib/view/widget/round_rect_card.dart +++ b/lib/view/widget/round_rect_card.dart @@ -8,11 +8,8 @@ class RoundRectCard extends StatelessWidget { @override Widget build(BuildContext context) { return Card( - child: Padding( - padding: const EdgeInsets.symmetric(horizontal: 17), - child: child, - ), - margin: const EdgeInsets.symmetric(vertical: 7), + child: child, + clipBehavior: Clip.antiAlias, shape: const RoundedRectangleBorder( borderRadius: BorderRadius.all(Radius.circular(17))), ); diff --git a/pubspec.lock b/pubspec.lock index a7612f04..94a571db 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -145,6 +145,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "4.0.4" + dropdown_button2: + dependency: "direct main" + description: + name: dropdown_button2 + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.1" extended_image: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 69405b75..11855c92 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -56,6 +56,7 @@ dependencies: marquee: ^2.2.0 dart_ping: ^6.1.1 dart_ping_ios: ^1.0.0 + dropdown_button2: ^1.1.1 dev_dependencies: