import 'package:flutter/material.dart'; import 'package:logger/logger.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'dart:convert'; import 'dialog.dart'; import '../utils/verify_server.dart'; final log = Logger(); class ServerForm extends StatefulWidget { ServerForm({@required this.defaultNextRoute, Key key}) : super(key: key); final String title = "Server data"; final String defaultNextRoute; @override _ServerFormState createState() => _ServerFormState(); } class _ServerFormState extends State { static String title = "Server info"; Uri zAddress; Uri botZAddress; bool _autoValidate = false; bool _disableFields = false; final _serverFormKey = GlobalKey(); final _scaffoldKey = GlobalKey(); final zController = TextEditingController(); final botZController = TextEditingController(); InputDecoration _textFieldDecoration(String label, IconData icon) { return InputDecoration( labelText: label, icon: Icon(icon), hintText: 'Please, insert $label address', ); } SnackBar showProgress() { return SnackBar( content: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ CircularProgressIndicator( value: null, strokeWidth: 7.0, ), Text('Processing Data') ], )); } String validateServer(String address) { if (address.isEmpty) { return 'Server address must not be empty'; } try { Uri.parse(address); } on FormatException catch (e) { return e.toString(); } return null; } String validateZServer(String address) { String baseValidation = this.validateServer(address); if (baseValidation != null) { return baseValidation; } if (utf8.encode(address).length > 72) { return "Server address string length is > 72 bytes. Refusing to go on."; } return null; } Future getNextRoute() async { var persistence = await SharedPreferences.getInstance(); String nextRoute = persistence.getString("nextRoute"); if (nextRoute != null) { log.d("nextRoute: $nextRoute"); return nextRoute; } log.d("defaultNextRoute: ${widget.defaultNextRoute}"); return null; } Future _onPressed() async { log.d("Button pressed"); var persistence = await SharedPreferences.getInstance(); setState(() { _disableFields = true; }); _scaffoldKey.currentState.showSnackBar(this.showProgress()); if (!_serverFormKey.currentState.validate()) { setState(() { _autoValidate = true; _disableFields = false; }); _scaffoldKey.currentState.hideCurrentSnackBar(); return; } bool resp; Uri _botZAddr = Uri.parse(botZController.text); Uri _zAddr = Uri.parse(zController.text); log.d("Received botZAddr: $_botZAddr\tzAddr: $_zAddr"); try { resp = await verifyServer(_botZAddr, _zAddr); log.i("Secret is${resp ? ' ' : ' NOT '}a match"); } catch (err) { log.e("Error: ${err.toString()}"); showDialog( context: context, builder: errorDialogBuilder("Error", "${err.toString()}")); } finally { log.d("Clean the state"); setState(() { _disableFields = false; }); _scaffoldKey.currentState.hideCurrentSnackBar(); } if (!resp) { showDialog( context: context, builder: errorDialogBuilder("Error", "The BotZ server does not target the provided Z server.")); } else { _serverFormKey.currentState.save(); persistence.setString("zAddress", this.zAddress.toString()); persistence.setString("botZAddress", this.botZAddress.toString()); String nextRoute = await getNextRoute(); if (nextRoute == null) { nextRoute = widget.defaultNextRoute; } Navigator.pushNamed(context, nextRoute); } log.d("Done"); } Form theForm() => Form( key: _serverFormKey, child: Column(children: [ TextFormField( autofocus: true, autocorrect: false, controller: zController, enabled: !_disableFields, decoration: this._textFieldDecoration("Z server", Icons.http), validator: this.validateZServer, autovalidate: _autoValidate, onSaved: (String addr) { zAddress = Uri.parse(addr); }), TextFormField( autocorrect: false, controller: botZController, enabled: !_disableFields, decoration: this._textFieldDecoration("BotZ server", Icons.http), validator: this.validateServer, autovalidate: _autoValidate, onSaved: (String addr) { botZAddress = Uri.parse(addr); }), RaisedButton( onPressed: _onPressed, child: Text('Save'), ), ]), ); @override Widget build(BuildContext context) { return Scaffold( key: _scaffoldKey, appBar: AppBar(title: Text(title)), body: theForm()); } }