diff --git a/lib/connection.class.dart b/lib/connection.class.dart index 4eaf7d4..cf45445 100644 --- a/lib/connection.class.dart +++ b/lib/connection.class.dart @@ -303,7 +303,10 @@ class Connection { _tempToken = null; final storage = new FlutterSecureStorage(); storage.write(key: "hacl_llt", value: "$_token").then((_) { - completer.complete(); + SharedPreferences.getInstance().then((prefs) { + prefs.setBool("oauth-used", true); + completer.complete(); + }); }).catchError((e) { throw e; }); diff --git a/lib/main.dart b/lib/main.dart index 562e0a1..698456d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -155,14 +155,23 @@ class HAClientApp extends StatelessWidget { "/configuration": (context) => PanelPage(title: "Configuration"), "/putchase": (context) => PurchasePage(title: "Support app development"), "/log-view": (context) => LogViewPage(title: "Log"), - "/login": (_) => WebviewScaffold( + "/login": (context) => WebviewScaffold( url: "${Connection().oauthUrl}", appBar: new AppBar( leading: IconButton( icon: Icon(Icons.help), onPressed: () => HAUtils.launchURLInCustomTab(context: context, url: "http://ha-client.homemade.systems/docs#authentication") ), - title: new Text("Login to your Home Assistant"), + title: new Text("Login with HA"), + actions: [ + FlatButton( + child: Text("Manual", style: TextStyle(color: Colors.white)), + onPressed: () { + Navigator.of(context).pop(); + Navigator.of(context).pushNamed("/connection-settings"); + }, + ) + ], ), ) }, diff --git a/lib/pages/settings.page.dart b/lib/pages/settings.page.dart index 300c5be..7fcf0cc 100644 --- a/lib/pages/settings.page.dart +++ b/lib/pages/settings.page.dart @@ -16,10 +16,13 @@ class _ConnectionSettingsPageState extends State { String _newHassioPort = ""; String _socketProtocol = "wss"; String _newSocketProtocol = "wss"; + String _longLivedToken = ""; + String _newLongLivedToken = ""; bool _useLovelace = true; bool _newUseLovelace = true; String oauthUrl; + bool useOAuth = false; @override void initState() { @@ -30,6 +33,23 @@ class _ConnectionSettingsPageState extends State { _loadSettings() async { SharedPreferences prefs = await SharedPreferences.getInstance(); + final storage = new FlutterSecureStorage(); + + try { + useOAuth = prefs.getBool("oauth-used") ?? true; + } catch (e) { + useOAuth = true; + } + + if (!useOAuth) { + try { + _longLivedToken = _newLongLivedToken = + await storage.read(key: "hacl_llt"); + } catch (e) { + _longLivedToken = _newLongLivedToken = ""; + await storage.delete(key: "hacl_llt"); + } + } setState(() { _hassioDomain = _newHassioDomain = prefs.getString("hassio-domain")?? ""; @@ -48,7 +68,8 @@ class _ConnectionSettingsPageState extends State { (_newHassioPort != _hassioPort) || (_newHassioDomain != _hassioDomain) || (_newSocketProtocol != _socketProtocol) || - (_newUseLovelace != _useLovelace)); + (_newUseLovelace != _useLovelace) || + (_newLongLivedToken != _longLivedToken)); } @@ -58,6 +79,13 @@ class _ConnectionSettingsPageState extends State { } _newHassioDomain = _newHassioDomain.split("/")[0]; SharedPreferences prefs = await SharedPreferences.getInstance(); + final storage = new FlutterSecureStorage(); + if (_newLongLivedToken.isNotEmpty) { + prefs.setBool("oauth-used", false); + await storage.write(key: "hacl_llt", value: _newLongLivedToken); + } else if (!useOAuth) { + await storage.delete(key: "hacl_llt"); + } prefs.setString("hassio-domain", _newHassioDomain); prefs.setString("hassio-port", _newHassioPort); prefs.setString("hassio-protocol", _newSocketProtocol); @@ -172,6 +200,33 @@ class _ConnectionSettingsPageState extends State { ) ], ), + Text( + "Authentication settings", + style: TextStyle( + color: Colors.black45, + fontSize: 20.0 + ), + ), + Container(height: 10.0,), + Text( + "You can leave this field blank to make app generate new long-lived token automatically by asking you to login to your Home Assistant. Use this field only if you still want to use manually generated long-lived token. Leave it blank if you don't understand what we are talking about.", + style: TextStyle(color: Colors.redAccent), + ), + new TextField( + decoration: InputDecoration( + labelText: "Long-lived token" + ), + controller: new TextEditingController.fromValue( + new TextEditingValue( + text: _newLongLivedToken ?? '', + selection: + new TextSelection.collapsed(offset: _newLongLivedToken != null ? _newLongLivedToken.length : 0) + ) + ), + onChanged: (value) { + _newLongLivedToken = value; + } + ), ], ), );