diff --git a/lib/view/page/convert.dart b/lib/view/page/convert.dart index 6084a42c..f3e9f7ba 100644 --- a/lib/view/page/convert.dart +++ b/lib/view/page/convert.dart @@ -104,9 +104,9 @@ class _ConvertPageState extends State child: ExpansionTile( leading: TextButton( child: SizedBox( - width: _media.size.width * 0.2, + width: _media.size.width * 0.3, child: Row( - children: const [Icon(Icons.change_circle), Text('上下交换')], + children: const [Icon(Icons.change_circle), Text('Upside down')], ), ), onPressed: () { diff --git a/lib/view/page/home.dart b/lib/view/page/home.dart index e5aa99a5..eb44ba96 100644 --- a/lib/view/page/home.dart +++ b/lib/view/page/home.dart @@ -9,7 +9,7 @@ import 'package:toolbox/data/res/build_data.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/server.dart'; +import 'package:toolbox/view/page/server/server_tab.dart'; class MyHomePage extends StatefulWidget { const MyHomePage({Key? key, required this.title}) : super(key: key); diff --git a/lib/view/page/server/server_edit.dart b/lib/view/page/server/server_edit.dart new file mode 100644 index 00000000..f7f7e908 --- /dev/null +++ b/lib/view/page/server/server_edit.dart @@ -0,0 +1,149 @@ +import 'package:after_layout/after_layout.dart'; +import 'package:flutter/material.dart'; +import 'package:toolbox/data/model/server_private_info.dart'; +import 'package:toolbox/data/provider/server.dart'; +import 'package:toolbox/locator.dart'; + +class ServerEditPage extends StatefulWidget { + const ServerEditPage({Key? key, this.spi}) : super(key: key); + + final ServerPrivateInfo? spi; + + @override + _ServerEditPageState createState() => _ServerEditPageState(); +} + +class _ServerEditPageState extends State with AfterLayoutMixin { + final nameController = TextEditingController(); + final ipController = TextEditingController(); + final portController = TextEditingController(); + final usernameController = TextEditingController(); + final passwordController = TextEditingController(); + final keyController = TextEditingController(); + + late ServerProvider _serverProvider; + + bool usePublicKey = false; + + @override + void initState() { + super.initState(); + _serverProvider = locator(); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Edit')), + body: SingleChildScrollView( + padding: const EdgeInsets.all(17), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + TextField( + controller: nameController, + keyboardType: TextInputType.text, + decoration: _buildDecoration('Name', icon: Icons.info), + ), + TextField( + controller: ipController, + keyboardType: TextInputType.text, + decoration: _buildDecoration('Host', icon: Icons.storage), + ), + TextField( + controller: portController, + keyboardType: TextInputType.number, + decoration: + _buildDecoration('Port', icon: Icons.format_list_numbered), + ), + TextField( + controller: usernameController, + keyboardType: TextInputType.text, + decoration: _buildDecoration('User', icon: Icons.account_box), + ), + const SizedBox(height: 7), + Row( + children: [ + const Text('Public Key Auth'), + Switch( + value: usePublicKey, + onChanged: (val) => setState(() => usePublicKey = val)), + ], + ), + usePublicKey + ? TextField( + controller: keyController, + keyboardType: TextInputType.text, + autocorrect: false, + maxLines: 10, + minLines: 5, + decoration: + _buildDecoration('Private Key', icon: Icons.vpn_key), + onSubmitted: (_) => {}, + ) + : const SizedBox(), + TextField( + controller: passwordController, + obscureText: true, + keyboardType: TextInputType.text, + decoration: _buildDecoration('Pwd', icon: Icons.password), + onSubmitted: (_) => {}, + ), + ], + ), + ), + floatingActionButton: FloatingActionButton( + child: const Icon(Icons.send), + onPressed: () { + final authorization = keyController.text.isEmpty + ? passwordController.text + : { + "privateKey": keyController.text, + "passphrase": passwordController.text + }; + final spi = ServerPrivateInfo( + name: nameController.text, + ip: ipController.text, + port: int.parse(portController.text), + user: usernameController.text, + authorization: authorization); + + if (widget.spi == null) { + _serverProvider.addServer(spi); + } else { + _serverProvider.updateServer(widget.spi!, spi); + } + + Navigator.of(context).pop(); + }, + ), + ); + } + + InputDecoration _buildDecoration(String label, + {TextStyle? textStyle, IconData? icon}) { + return InputDecoration( + labelText: label, labelStyle: textStyle, icon: Icon(icon)); + } + + @override + void afterFirstLayout(BuildContext context) { + if (widget.spi != null) { + nameController.text = widget.spi?.name ?? ''; + ipController.text = widget.spi?.ip ?? ''; + portController.text = (widget.spi?.port ?? 22).toString(); + usernameController.text = widget.spi?.user ?? ''; + if (widget.spi?.authorization is String) { + passwordController.text = widget.spi?.authorization as String? ?? ''; + } else { + final auth = widget.spi?.authorization as Map; + passwordController.text = auth['passphrase']; + keyController.text = auth['privateKey']; + setState(() { + usePublicKey = true; + }); + } + } + } +} diff --git a/lib/view/page/server.dart b/lib/view/page/server/server_tab.dart similarity index 54% rename from lib/view/page/server.dart rename to lib/view/page/server/server_tab.dart index 59c824d7..b9a5f97a 100644 --- a/lib/view/page/server.dart +++ b/lib/view/page/server/server_tab.dart @@ -5,11 +5,12 @@ 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:toolbox/core/utils.dart'; +import 'package:toolbox/core/route.dart'; import 'package:toolbox/data/model/server_private_info.dart'; import 'package:toolbox/data/model/server_status.dart'; import 'package:toolbox/data/provider/server.dart'; import 'package:toolbox/locator.dart'; +import 'package:toolbox/view/page/server/server_edit.dart'; import 'package:toolbox/view/widget/circle_pie.dart'; class ServerPage extends StatefulWidget { @@ -23,22 +24,13 @@ class _ServerPageState extends State with AutomaticKeepAliveClientMixin, AfterLayoutMixin { late MediaQueryData _media; late ThemeData _theme; - bool useKey = false; - final nameController = TextEditingController(); - final ipController = TextEditingController(); - final portController = TextEditingController(); - final usernameController = TextEditingController(); - final passwordController = TextEditingController(); - final keyController = TextEditingController(); - - late ServerProvider serverProvider; - final cachedServerStatus = []; + late ServerProvider _serverProvider; @override void initState() { super.initState(); - serverProvider = locator(); + _serverProvider = locator(); } @override @@ -74,7 +66,9 @@ class _ServerPageState extends State })), ), floatingActionButton: FloatingActionButton( - onPressed: () => showAddServerDialog(), + onPressed: () => + AppRoute(const ServerEditPage(), 'Add server info page') + .go(context), tooltip: 'add a server', heroTag: 'server page fab', child: const Icon(Icons.add), @@ -82,151 +76,16 @@ class _ServerPageState extends State ); } - void showAddServerDialog() { - showRoundDialog(context, 'New', _buildTextInputField(context), [ - TextButton( - onPressed: () { - clearTextField(); - Navigator.of(context).pop(); - }, - child: const Text('Close')), - TextButton( - onPressed: () { - final authorization = keyController.text.isEmpty - ? passwordController.text - : { - "privateKey": keyController.text, - "passphrase": passwordController.text - }; - serverProvider.addServer(ServerPrivateInfo( - name: nameController.text, - ip: ipController.text, - port: int.parse(portController.text), - user: usernameController.text, - authorization: authorization)); - clearTextField(); - Navigator.of(context).pop(); - }, - child: const Text('Connect')) - ]); - } - - InputDecoration _buildDecoration(String label, {TextStyle? textStyle}) { - return InputDecoration(labelText: label, labelStyle: textStyle); - } - - Widget _buildTextInputField(BuildContext ctx) { - return SingleChildScrollView( - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - TextField( - controller: nameController, - keyboardType: TextInputType.text, - decoration: _buildDecoration('Name'), - ), - TextField( - controller: ipController, - keyboardType: TextInputType.text, - decoration: _buildDecoration('Host'), - ), - TextField( - controller: portController, - keyboardType: TextInputType.number, - decoration: _buildDecoration('Port'), - ), - TextField( - controller: usernameController, - keyboardType: TextInputType.text, - decoration: _buildDecoration('User'), - ), - TextField( - controller: keyController, - keyboardType: TextInputType.text, - decoration: _buildDecoration('Key(Optional)'), - onSubmitted: (_) => {}, - ), - TextField( - controller: passwordController, - obscureText: true, - keyboardType: TextInputType.text, - decoration: _buildDecoration('Pwd'), - onSubmitted: (_) => {}, - ), - ], - ), - ); - } - - void clearTextField() { - nameController.clear(); - ipController.clear(); - portController.clear(); - usernameController.clear(); - passwordController.clear(); - keyController.clear(); - } - Widget _buildEachServerCard(ServerStatus ss, ServerPrivateInfo spi) { return GestureDetector( child: _buildEachCardContent(ss, spi), onLongPress: () { - nameController.text = spi.name ?? ''; - ipController.text = spi.ip ?? ''; - portController.text = (spi.port ?? 22).toString(); - usernameController.text = spi.user ?? ''; - if (spi.authorization is String) { - passwordController.text = spi.authorization as String? ?? ''; - } else { - final auth = spi.authorization as Map; - passwordController.text = auth['passphrase']; - keyController.text = auth['privateKey']; - } - - showRoundDialog( - context, - 'Edit', - _buildTextInputField(context), - [ - TextButton( - onPressed: () { - clearTextField(); - Navigator.of(context).pop(); - }, - child: const Text('Close')), - TextButton( - onPressed: () { - final authorization = keyController.text.isEmpty - ? passwordController.text - : { - "privateKey": keyController.text, - "passphrase": passwordController.text - }; - serverProvider.updateServer( - spi, - ServerPrivateInfo( - name: nameController.text, - ip: ipController.text, - port: int.parse(portController.text), - user: usernameController.text, - authorization: authorization)); - clearTextField(); - Navigator.of(context).pop(); - }, - child: const Text('Save')), - TextButton( - onPressed: () { - serverProvider.delServer(spi); - clearTextField(); - Navigator.of(context).pop(); - }, - child: const Text( - 'Delete', - style: TextStyle(color: Colors.red), - )) - ], - barrierDismiss: false); + AppRoute( + ServerEditPage( + spi: spi, + ), + 'Edit server info page') + .go(context); }); } @@ -377,8 +236,8 @@ class _ServerPageState extends State @override Future afterFirstLayout(BuildContext context) async { await GetIt.I.allReady(); - await serverProvider.loadLocalData(); - await serverProvider.refreshData(); - await serverProvider.startAutoRefresh(); + await _serverProvider.loadLocalData(); + await _serverProvider.refreshData(); + await _serverProvider.startAutoRefresh(); } }