Resolves #338 OAuth with Home Assistant
This commit is contained in:
		| @@ -3,6 +3,7 @@ part of 'main.dart'; | |||||||
| class HomeAssistant { | class HomeAssistant { | ||||||
|   String _webSocketAPIEndpoint; |   String _webSocketAPIEndpoint; | ||||||
|   String httpWebHost; |   String httpWebHost; | ||||||
|  |   String oauthUrl; | ||||||
|   //String _password; |   //String _password; | ||||||
|   String _token; |   String _token; | ||||||
|   String _tempToken; |   String _tempToken; | ||||||
| @@ -68,6 +69,7 @@ class HomeAssistant { | |||||||
|       throw("Check connection settings"); |       throw("Check connection settings"); | ||||||
|     } else { |     } else { | ||||||
|       isSettingsLoaded = true; |       isSettingsLoaded = true; | ||||||
|  |       oauthUrl = "$httpWebHost/auth/authorize?client_id=${Uri.encodeComponent('http://ha-client.homemade.systems/')}&redirect_uri=${Uri.encodeComponent('http://ha-client.homemade.systems/service/auth_callback.html')}"; | ||||||
|       entities = EntityCollection(httpWebHost); |       entities = EntityCollection(httpWebHost); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -85,6 +87,7 @@ class HomeAssistant { | |||||||
|     } else { |     } else { | ||||||
|       Logger.d("Fetching..."); |       Logger.d("Fetching..."); | ||||||
|       _fetchCompleter = new Completer(); |       _fetchCompleter = new Completer(); | ||||||
|  |       _fetchTimer?.cancel(); | ||||||
|       _fetchTimer = Timer(fetchTimeout, () { |       _fetchTimer = Timer(fetchTimeout, () { | ||||||
|         Logger.e( "Data fetching timeout"); |         Logger.e( "Data fetching timeout"); | ||||||
|         disconnect().then((_) { |         disconnect().then((_) { | ||||||
| @@ -104,13 +107,12 @@ class HomeAssistant { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   disconnect() async { |   disconnect() async { | ||||||
|     if ((_hassioChannel != null) && (_hassioChannel.closeCode == null) && (_hassioChannel.sink != null)) { |     Logger.d( "Socket disconnecting..."); | ||||||
|       await _hassioChannel.sink.close().timeout(Duration(seconds: 3), |     await _socketSubscription?.cancel(); | ||||||
|  |     await _hassioChannel?.sink?.close()?.timeout(Duration(seconds: 3), | ||||||
|         onTimeout: () => Logger.d( "Socket sink closed") |         onTimeout: () => Logger.d( "Socket sink closed") | ||||||
|       ); |     ); | ||||||
|       await _socketSubscription.cancel(); |     _hassioChannel = null; | ||||||
|       _hassioChannel = null; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -119,6 +121,7 @@ class HomeAssistant { | |||||||
|       Logger.d("Previous connection is not complited"); |       Logger.d("Previous connection is not complited"); | ||||||
|     } else { |     } else { | ||||||
|       if ((_hassioChannel == null) || (_hassioChannel.closeCode != null)) { |       if ((_hassioChannel == null) || (_hassioChannel.closeCode != null)) { | ||||||
|  |         _connectionTimer?.cancel(); | ||||||
|         _connectionCompleter = new Completer(); |         _connectionCompleter = new Completer(); | ||||||
|         autoReconnect = false; |         autoReconnect = false; | ||||||
|         disconnect().then((_){ |         disconnect().then((_){ | ||||||
| @@ -127,9 +130,7 @@ class HomeAssistant { | |||||||
|             Logger.e( "Socket connection timeout"); |             Logger.e( "Socket connection timeout"); | ||||||
|             _handleSocketError(null); |             _handleSocketError(null); | ||||||
|           }); |           }); | ||||||
|           if (_socketSubscription != null) { |           _socketSubscription?.cancel(); | ||||||
|             _socketSubscription.cancel(); |  | ||||||
|           } |  | ||||||
|           _hassioChannel = IOWebSocketChannel.connect( |           _hassioChannel = IOWebSocketChannel.connect( | ||||||
|               _webSocketAPIEndpoint, pingInterval: Duration(seconds: 30)); |               _webSocketAPIEndpoint, pingInterval: Duration(seconds: 30)); | ||||||
|           _socketSubscription = _hassioChannel.stream.listen( |           _socketSubscription = _hassioChannel.stream.listen( | ||||||
| @@ -199,7 +200,7 @@ class HomeAssistant { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   void _completeFetching(error) { |   void _completeFetching(error) { | ||||||
|     _fetchTimer.cancel(); |     _fetchTimer?.cancel(); | ||||||
|     _completeConnecting(error); |     _completeConnecting(error); | ||||||
|     if (!_fetchCompleter.isCompleted) { |     if (!_fetchCompleter.isCompleted) { | ||||||
|       if (error != null) { |       if (error != null) { | ||||||
| @@ -213,7 +214,7 @@ class HomeAssistant { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   void _completeConnecting(error) { |   void _completeConnecting(error) { | ||||||
|     _connectionTimer.cancel(); |     _connectionTimer?.cancel(); | ||||||
|     if (!_connectionCompleter.isCompleted) { |     if (!_connectionCompleter.isCompleted) { | ||||||
|       if (error != null) { |       if (error != null) { | ||||||
|         _connectionCompleter.completeError(error); |         _connectionCompleter.completeError(error); | ||||||
| @@ -241,10 +242,10 @@ class HomeAssistant { | |||||||
|       _sendSubscribe(); |       _sendSubscribe(); | ||||||
|     } else if (data["type"] == "auth_invalid") { |     } else if (data["type"] == "auth_invalid") { | ||||||
|       Logger.d("[Received] <== ${data.toString()}"); |       Logger.d("[Received] <== ${data.toString()}"); | ||||||
|       //TODO remove token and login again |       _logout(); | ||||||
|       _completeConnecting({"errorCode": 6, "errorMessage": "${data["message"]}"}); |       _completeConnecting({"errorCode": 62, "errorMessage": "${data["message"]}"}); | ||||||
|     } else if (data["type"] == "result") { |     } else if (data["type"] == "result") { | ||||||
|       Logger.d("[Received] <== ${data.toString()}"); |       Logger.d("[Received] <== id: ${data['id']}, success: ${data['success']}"); | ||||||
|       _messageResolver[data["id"]]?.complete(data); |       _messageResolver[data["id"]]?.complete(data); | ||||||
|       _messageResolver.remove(data["id"]); |       _messageResolver.remove(data["id"]); | ||||||
|     } else if (data["type"] == "event") { |     } else if (data["type"] == "event") { | ||||||
| @@ -261,6 +262,12 @@ class HomeAssistant { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   void _logout() { | ||||||
|  |     _token = null; | ||||||
|  |     _tempToken = null; | ||||||
|  |     SharedPreferences.getInstance().then((prefs) => prefs.remove("hassio-token")); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   void _sendSubscribe() { |   void _sendSubscribe() { | ||||||
|     _incrementMessageId(); |     _incrementMessageId(); | ||||||
|     _subscriptionMessageId = _currentMessageId; |     _subscriptionMessageId = _currentMessageId; | ||||||
| @@ -276,18 +283,19 @@ class HomeAssistant { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   Future _getLongLivedToken() async { |   Future _getLongLivedToken() async { | ||||||
|     await _sendSocketMessage(type: "auth/long_lived_access_token", additionalData: {"client_name": "HA Client 3", "client_icon": null, "lifespan": 365}).then((data) { |     await _sendSocketMessage(type: "auth/long_lived_access_token", additionalData: {"client_name": "HA Client app", "lifespan": 365}).then((data) { | ||||||
|       if (data['success']) { |       if (data['success']) { | ||||||
|         Logger.d("Got long-lived token: ${data['result']}"); |         Logger.d("Got long-lived token: ${data['result']}"); | ||||||
|         _token = data['result']; |         _token = data['result']; | ||||||
|         //TODO save token |         _tempToken = null; | ||||||
|  |         SharedPreferences.getInstance().then((prefs) => prefs.setString("hassio-token", _token)); | ||||||
|       } else { |       } else { | ||||||
|  |         _logout(); | ||||||
|         Logger.e("Error getting long-lived token: ${data['error'].toString()}"); |         Logger.e("Error getting long-lived token: ${data['error'].toString()}"); | ||||||
|         //TODO DO DO something here |  | ||||||
|       } |       } | ||||||
|     }).catchError((e) { |     }).catchError((e) { | ||||||
|       Logger.e("Error getting long-lived token: ${e.toString()}"); |       Logger.e("Error getting long-lived token: ${e.toString()}"); | ||||||
|       //TODO DO DO something here |       _logout(); | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -337,7 +345,6 @@ class HomeAssistant { | |||||||
|       Logger.d( "No long leaved token. Need to authenticate."); |       Logger.d( "No long leaved token. Need to authenticate."); | ||||||
|       final flutterWebviewPlugin = new FlutterWebviewPlugin(); |       final flutterWebviewPlugin = new FlutterWebviewPlugin(); | ||||||
|       flutterWebviewPlugin.onUrlChanged.listen((String url) { |       flutterWebviewPlugin.onUrlChanged.listen((String url) { | ||||||
|         Logger.d("Launched url: $url"); |  | ||||||
|         if (url.startsWith("http://ha-client.homemade.systems/service/auth_callback.html")) { |         if (url.startsWith("http://ha-client.homemade.systems/service/auth_callback.html")) { | ||||||
|           String authCode = url.split("=")[1]; |           String authCode = url.split("=")[1]; | ||||||
|           Logger.d("We have auth code. Getting temporary access token..."); |           Logger.d("We have auth code. Getting temporary access token..."); | ||||||
| @@ -354,27 +361,33 @@ class HomeAssistant { | |||||||
|             Logger.d("Firing event to reload UI"); |             Logger.d("Firing event to reload UI"); | ||||||
|             eventBus.fire(ReloadUIEvent()); |             eventBus.fire(ReloadUIEvent()); | ||||||
|           }).catchError((e) { |           }).catchError((e) { | ||||||
|             //TODO DO DO something here |             _logout(); | ||||||
|  |             disconnect(); | ||||||
|  |             flutterWebviewPlugin.close(); | ||||||
|  |             _completeFetching({"errorCode": 61, "errorMessage": "Error getting temp token"}); | ||||||
|             Logger.e("Error getting temp token: ${e.toString()}"); |             Logger.e("Error getting temp token: ${e.toString()}"); | ||||||
|           }); |           }); | ||||||
|         } |         } | ||||||
|       }); |       }); | ||||||
|       disconnect().then((_){ |       disconnect(); | ||||||
|         //TODO create special error code to show "Login" in message |       _completeFetching({"errorCode": 60, "errorMessage": "Not authenticated"}); | ||||||
|         _completeConnecting({"errorCode": 6, "errorMessage": "Not authenticated"}); |       _requestOAuth(); | ||||||
|       }); |  | ||||||
|       String oauthUrl = "$httpWebHost/auth/authorize?client_id=${Uri.encodeComponent('http://ha-client.homemade.systems/')}&redirect_uri=${Uri.encodeComponent('http://ha-client.homemade.systems/service/auth_callback.html')}"; |  | ||||||
|       Logger.d("OAuth url: $oauthUrl"); |  | ||||||
|       eventBus.fire(StartAuthEvent(oauthUrl)); |  | ||||||
|     } else if (_tempToken != null) { |     } else if (_tempToken != null) { | ||||||
|       Logger.d("We have temp token. Login..."); |       Logger.d("We have temp token. Login..."); | ||||||
|       _hassioChannel.sink.add('{"type": "auth","access_token": "$_tempToken"}'); |       _hassioChannel.sink.add('{"type": "auth","access_token": "$_tempToken"}'); | ||||||
|     } else { |     } else { | ||||||
|       Logger.e("General login error"); |       Logger.e("General login error"); | ||||||
|       //TODO DO DO something here |       _logout(); | ||||||
|  |       disconnect(); | ||||||
|  |       _completeFetching({"errorCode": 61, "errorMessage": "General login error"}); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   void _requestOAuth() { | ||||||
|  |     Logger.d("OAuth url: $oauthUrl"); | ||||||
|  |     eventBus.fire(StartAuthEvent(oauthUrl)); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   Future _sendSocketMessage({String type, Map additionalData, bool noId: false}) { |   Future _sendSocketMessage({String type, Map additionalData, bool noId: false}) { | ||||||
|     Completer _completer = Completer(); |     Completer _completer = Completer(); | ||||||
|     Map dataObject = {"type": "$type"}; |     Map dataObject = {"type": "$type"}; | ||||||
|   | |||||||
| @@ -104,8 +104,6 @@ EventBus eventBus = new EventBus(); | |||||||
| const String appName = "HA Client"; | const String appName = "HA Client"; | ||||||
| const appVersion = "0.5.2"; | const appVersion = "0.5.2"; | ||||||
|  |  | ||||||
| //String homeAssistantWebHost; |  | ||||||
|  |  | ||||||
| void main() { | void main() { | ||||||
|   FlutterError.onError = (errorDetails) { |   FlutterError.onError = (errorDetails) { | ||||||
|     Logger.e( "${errorDetails.exception}"); |     Logger.e( "${errorDetails.exception}"); | ||||||
| @@ -158,12 +156,7 @@ class MainPage extends StatefulWidget { | |||||||
| } | } | ||||||
|  |  | ||||||
| class _MainPageState extends State<MainPage> with WidgetsBindingObserver, TickerProviderStateMixin { | class _MainPageState extends State<MainPage> with WidgetsBindingObserver, TickerProviderStateMixin { | ||||||
|   //HomeAssistant _homeAssistant; |  | ||||||
|   //Map _instanceConfig; |  | ||||||
|   //String _webSocketApiEndpoint; |  | ||||||
|   //String _password; |  | ||||||
|   //int _uiViewsCount = 0; |  | ||||||
|   //String _instanceHost; |  | ||||||
|   StreamSubscription _stateSubscription; |   StreamSubscription _stateSubscription; | ||||||
|   StreamSubscription _settingsSubscription; |   StreamSubscription _settingsSubscription; | ||||||
|   StreamSubscription _serviceCallSubscription; |   StreamSubscription _serviceCallSubscription; | ||||||
| @@ -171,11 +164,9 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker | |||||||
|   StreamSubscription _showErrorSubscription; |   StreamSubscription _showErrorSubscription; | ||||||
|   StreamSubscription _startAuthSubscription; |   StreamSubscription _startAuthSubscription; | ||||||
|   StreamSubscription _reloadUISubscription; |   StreamSubscription _reloadUISubscription; | ||||||
|   //bool _settingsLoaded = false; |  | ||||||
|   bool _accountMenuExpanded = false; |   bool _accountMenuExpanded = false; | ||||||
|   //bool _useLovelaceUI; |  | ||||||
|   int _previousViewCount; |   int _previousViewCount; | ||||||
|   final FirebaseMessaging _firebaseMessaging = FirebaseMessaging(); |   //final FirebaseMessaging _firebaseMessaging = FirebaseMessaging(); | ||||||
|  |  | ||||||
|   @override |   @override | ||||||
|   void initState() { |   void initState() { | ||||||
| @@ -213,23 +204,6 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /*_loadConnectionSettings() async { |  | ||||||
|     SharedPreferences prefs = await SharedPreferences.getInstance(); |  | ||||||
|     String domain = prefs.getString('hassio-domain'); |  | ||||||
|     String port = prefs.getString('hassio-port'); |  | ||||||
|     _instanceHost = "$domain:$port"; |  | ||||||
|     _webSocketApiEndpoint = "${prefs.getString('hassio-protocol')}://$domain:$port/api/websocket"; |  | ||||||
|     homeAssistantWebHost = "${prefs.getString('hassio-res-protocol')}://$domain:$port"; |  | ||||||
|     _password = prefs.getString('hassio-password'); |  | ||||||
|     _useLovelaceUI = prefs.getBool('use-lovelace') ?? true; |  | ||||||
|     if ((domain == null) || (port == null) || (_password == null) || |  | ||||||
|         (domain.length == 0) || (port.length == 0) || (_password.length == 0)) { |  | ||||||
|       throw("Check connection settings"); |  | ||||||
|     } else { |  | ||||||
|       _settingsLoaded = true; |  | ||||||
|     } |  | ||||||
|   }*/ |  | ||||||
|  |  | ||||||
|   _subscribe() { |   _subscribe() { | ||||||
|     if (_stateSubscription == null) { |     if (_stateSubscription == null) { | ||||||
|       _stateSubscription = eventBus.on<StateChangedEvent>().listen((event) { |       _stateSubscription = eventBus.on<StateChangedEvent>().listen((event) { | ||||||
| @@ -269,20 +243,12 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker | |||||||
|  |  | ||||||
|     if (_startAuthSubscription == null) { |     if (_startAuthSubscription == null) { | ||||||
|       _startAuthSubscription = eventBus.on<StartAuthEvent>().listen((event){ |       _startAuthSubscription = eventBus.on<StartAuthEvent>().listen((event){ | ||||||
|         Navigator.push( |         _showOAuth(); | ||||||
|             context, |  | ||||||
|             MaterialPageRoute( |  | ||||||
|               builder: (context) => WebviewScaffold( |  | ||||||
|                 url: "${event.oauthUrl}", |  | ||||||
|                 appBar: new AppBar( |  | ||||||
|                   title: new Text("Login"), |  | ||||||
|                 ), |  | ||||||
|               ), |  | ||||||
|             ) |  | ||||||
|         ); |  | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     /*_firebaseMessaging.getToken().then((String token) { |     /*_firebaseMessaging.getToken().then((String token) { | ||||||
|       //Logger.d("FCM token: $token"); |       //Logger.d("FCM token: $token"); | ||||||
|       widget.homeAssistant.sendHTTPPost( |       widget.homeAssistant.sendHTTPPost( | ||||||
| @@ -303,6 +269,20 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker | |||||||
|     );*/ |     );*/ | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   void _showOAuth() { | ||||||
|  |     Navigator.push( | ||||||
|  |         context, | ||||||
|  |         MaterialPageRoute( | ||||||
|  |           builder: (context) => WebviewScaffold( | ||||||
|  |             url: "${widget.homeAssistant.oauthUrl}", | ||||||
|  |             appBar: new AppBar( | ||||||
|  |               title: new Text("Login"), | ||||||
|  |             ), | ||||||
|  |           ), | ||||||
|  |         ) | ||||||
|  |     ); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   _refreshData() async { |   _refreshData() async { | ||||||
|     //widget.homeAssistant.updateSettings(_webSocketApiEndpoint, _password, _useLovelaceUI); |     //widget.homeAssistant.updateSettings(_webSocketApiEndpoint, _password, _useLovelaceUI); | ||||||
|     _hideBottomBar(); |     _hideBottomBar(); | ||||||
| @@ -539,12 +519,31 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker | |||||||
|           break; |           break; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         case 6: { |         case 60: { | ||||||
|           _bottomBarAction = FlatButton( |           _bottomBarAction = FlatButton( | ||||||
|               child: Text("Settings", style: textStyle), |               child: Text("Login", style: textStyle), | ||||||
|             onPressed: () { |             onPressed: () { | ||||||
|               //_scaffoldKey?.currentState?.hideCurrentSnackBar(); |               _refreshData(); | ||||||
|               Navigator.pushNamed(context, '/connection-settings'); |             }, | ||||||
|  |           ); | ||||||
|  |           break; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         case 61: { | ||||||
|  |           _bottomBarAction = FlatButton( | ||||||
|  |             child: Text("Try again", style: textStyle), | ||||||
|  |             onPressed: () { | ||||||
|  |               _refreshData(); | ||||||
|  |             }, | ||||||
|  |           ); | ||||||
|  |           break; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         case 62: { | ||||||
|  |           _bottomBarAction = FlatButton( | ||||||
|  |             child: Text("Login again", style: textStyle), | ||||||
|  |             onPressed: () { | ||||||
|  |               _refreshData(); | ||||||
|             }, |             }, | ||||||
|           ); |           ); | ||||||
|           break; |           break; | ||||||
|   | |||||||
| @@ -14,8 +14,6 @@ class _ConnectionSettingsPageState extends State<ConnectionSettingsPage> { | |||||||
|   String _newHassioDomain = ""; |   String _newHassioDomain = ""; | ||||||
|   String _hassioPort = ""; |   String _hassioPort = ""; | ||||||
|   String _newHassioPort = ""; |   String _newHassioPort = ""; | ||||||
|   String _hassioPassword = ""; |  | ||||||
|   String _newHassioPassword = ""; |  | ||||||
|   String _socketProtocol = "wss"; |   String _socketProtocol = "wss"; | ||||||
|   String _newSocketProtocol = "wss"; |   String _newSocketProtocol = "wss"; | ||||||
|   bool _useLovelace = true; |   bool _useLovelace = true; | ||||||
| @@ -36,7 +34,6 @@ class _ConnectionSettingsPageState extends State<ConnectionSettingsPage> { | |||||||
|     setState(() { |     setState(() { | ||||||
|       _hassioDomain = _newHassioDomain = prefs.getString("hassio-domain")?? ""; |       _hassioDomain = _newHassioDomain = prefs.getString("hassio-domain")?? ""; | ||||||
|       _hassioPort = _newHassioPort = prefs.getString("hassio-port") ?? ""; |       _hassioPort = _newHassioPort = prefs.getString("hassio-port") ?? ""; | ||||||
|       _hassioPassword = _newHassioPassword = prefs.getString("hassio-password") ?? ""; |  | ||||||
|       _socketProtocol = _newSocketProtocol = prefs.getString("hassio-protocol") ?? 'wss'; |       _socketProtocol = _newSocketProtocol = prefs.getString("hassio-protocol") ?? 'wss'; | ||||||
|       try { |       try { | ||||||
|         _useLovelace = _newUseLovelace = prefs.getBool("use-lovelace") ?? true; |         _useLovelace = _newUseLovelace = prefs.getBool("use-lovelace") ?? true; | ||||||
| @@ -47,7 +44,7 @@ class _ConnectionSettingsPageState extends State<ConnectionSettingsPage> { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   bool _checkConfigChanged() { |   bool _checkConfigChanged() { | ||||||
|     return ((_newHassioPassword != _hassioPassword) || |     return ( | ||||||
|       (_newHassioPort != _hassioPort) || |       (_newHassioPort != _hassioPort) || | ||||||
|       (_newHassioDomain != _hassioDomain) || |       (_newHassioDomain != _hassioDomain) || | ||||||
|       (_newSocketProtocol != _socketProtocol) || |       (_newSocketProtocol != _socketProtocol) || | ||||||
| @@ -62,7 +59,6 @@ class _ConnectionSettingsPageState extends State<ConnectionSettingsPage> { | |||||||
|     SharedPreferences prefs = await SharedPreferences.getInstance(); |     SharedPreferences prefs = await SharedPreferences.getInstance(); | ||||||
|     prefs.setString("hassio-domain", _newHassioDomain); |     prefs.setString("hassio-domain", _newHassioDomain); | ||||||
|     prefs.setString("hassio-port", _newHassioPort); |     prefs.setString("hassio-port", _newHassioPort); | ||||||
|     prefs.setString("hassio-password", _newHassioPassword); |  | ||||||
|     prefs.setString("hassio-protocol", _newSocketProtocol); |     prefs.setString("hassio-protocol", _newSocketProtocol); | ||||||
|     prefs.setString("hassio-res-protocol", _newSocketProtocol == "wss" ? "https" : "http"); |     prefs.setString("hassio-res-protocol", _newSocketProtocol == "wss" ? "https" : "http"); | ||||||
|     prefs.setBool("use-lovelace", _newUseLovelace); |     prefs.setBool("use-lovelace", _newUseLovelace); | ||||||
| @@ -152,21 +148,6 @@ class _ConnectionSettingsPageState extends State<ConnectionSettingsPage> { | |||||||
|             "Try ports 80 and 443 if default is not working and you don't know why.", |             "Try ports 80 and 443 if default is not working and you don't know why.", | ||||||
|             style: TextStyle(color: Colors.grey), |             style: TextStyle(color: Colors.grey), | ||||||
|           ), |           ), | ||||||
|           new TextField( |  | ||||||
|             decoration: InputDecoration( |  | ||||||
|                 labelText: "Access token" |  | ||||||
|             ), |  | ||||||
|             controller: new TextEditingController.fromValue( |  | ||||||
|                 new TextEditingValue( |  | ||||||
|                     text: _newHassioPassword, |  | ||||||
|                     selection: |  | ||||||
|                     new TextSelection.collapsed(offset: _newHassioPassword.length) |  | ||||||
|                 ) |  | ||||||
|             ), |  | ||||||
|             onChanged: (value) { |  | ||||||
|               _newHassioPassword = value; |  | ||||||
|             } |  | ||||||
|           ), |  | ||||||
|           Padding( |           Padding( | ||||||
|             padding: EdgeInsets.only(top: 20.0), |             padding: EdgeInsets.only(top: 20.0), | ||||||
|             child: Text( |             child: Text( | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user