diff --git a/lib/managers/mobile_app_integration_manager.class.dart b/lib/managers/mobile_app_integration_manager.class.dart index 97ffc42..c7abf20 100644 --- a/lib/managers/mobile_app_integration_manager.class.dart +++ b/lib/managers/mobile_app_integration_manager.class.dart @@ -23,12 +23,12 @@ class MobileAppIntegrationManager { return '${HomeAssistant().userName}\'s ${DeviceInfoManager().model}'; } - static Future checkAppRegistration({bool forceRegister: false, bool showOkDialog: false}) { + static Future checkAppRegistration({bool showOkDialog: false}) { Completer completer = Completer(); _appRegistrationData["device_name"] = ConnectionManager().mobileAppDeviceName ?? getDefaultDeviceName(); (_appRegistrationData["app_data"] as Map)["push_token"] = "${HomeAssistant().fcmToken}"; - if (ConnectionManager().webhookId == null || forceRegister) { - Logger.d("Mobile app was not registered yet or need to be reseted. Registering..."); + if (ConnectionManager().webhookId == null) { + Logger.d("Mobile app was not registered yet. Registering..."); var registrationData = Map.from(_appRegistrationData); registrationData.addAll({ "device_id": "${DeviceInfoManager().unicDeviceId}", @@ -86,7 +86,7 @@ class MobileAppIntegrationManager { registrationData = null; } if (registrationData == null || registrationData.isEmpty) { - Logger.d("No registration data in response. MobileApp integration was removed or broken"); + Logger.e("No registration data in response. MobileApp integration was removed or broken"); _askToRegisterApp(); } else { if (INTEGRATION_VERSION > ConnectionManager().appIntegrationVersion) { @@ -112,20 +112,7 @@ class MobileAppIntegrationManager { _askToRegisterApp(); } else { Logger.e("Error updating app registration: $e"); - eventBus.fire(ShowPopupEvent( - Popup( - title: "App integration is not working properly", - body: "Something wrong with HA Client integration on your Home Assistant server. Please report this issue.", - positiveText: "Report to GitHub", - negativeText: "Report to Discord", - onPositive: () { - Launcher.launchURLInBrowser("https://github.com/estevez-dev/ha_client/issues/new"); - }, - onNegative: () { - Launcher.launchURLInBrowser("https://discord.gg/AUzEvwn"); - }, - ) - )); + _showError(); } completer.complete(); }); @@ -133,6 +120,23 @@ class MobileAppIntegrationManager { } } + static void _showError() { + eventBus.fire(ShowPopupEvent( + Popup( + title: "App integration is not working properly", + body: "Something wrong with HA Client integration on your Home Assistant server. Please report this issue. You can try to remove Mobile App integration from Home Assistant and restart server to fix this issue.", + positiveText: "Report to GitHub", + negativeText: "Report to Discord", + onPositive: () { + Launcher.launchURLInBrowser("https://github.com/estevez-dev/ha_client/issues/new"); + }, + onNegative: () { + Launcher.launchURLInBrowser("https://discord.gg/AUzEvwn"); + }, + ) + )); + } + static void _askToRemoveAndRegisterApp() { eventBus.fire(ShowPopupEvent( Popup( @@ -149,18 +153,9 @@ class MobileAppIntegrationManager { static void _askToRegisterApp() { eventBus.fire(ShowPopupEvent( - Popup( - title: "App integration is broken", - body: "Looks like app integration was removed from your Home Assistant or it needs to be updated. HA Client needs to be registered on your Home Assistant server to make it possible to use notifications and location tracking. Please remove 'Mobile App' integration for this device from your Home Assistant before registering and restart Home Assistant. Then go back here.", - positiveText: "Register now", - negativeText: "Cancel", - onPositive: () { - SharedPreferences.getInstance().then((prefs) { - prefs.remove("app-webhook-id"); - ConnectionManager().webhookId = null; - checkAppRegistration(); - }); - }, + RegisterAppPopup( + title: "Mobile App integration is missing", + body: "Looks like mobile app integration was removed from your Home Assistant or it needs to be updated.", ) )); } diff --git a/lib/pages/main/main.page.dart b/lib/pages/main/main.page.dart index d3a0d2e..a8b03d1 100644 --- a/lib/pages/main/main.page.dart +++ b/lib/pages/main/main.page.dart @@ -23,6 +23,7 @@ class _MainPageState extends State with WidgetsBindingObserver, Ticker StreamSubscription _fullReloadSubscription; StreamSubscription _showPageSubscription; BottomInfoBarController _bottomInfoBarController; + bool _popupShown = false; int _previousViewCount; bool _showLoginButton = false; bool _preventAppRefresh = false; @@ -183,7 +184,12 @@ class _MainPageState extends State with WidgetsBindingObserver, Ticker } if (_showPopupSubscription == null) { _showPopupSubscription = eventBus.on().listen((event){ - event.popup.show(context); + if (!_popupShown) { + _popupShown = true; + event.popup.show(context).then((_){ + _popupShown = false; + }); + } }); } if (_serviceCallSubscription == null) { diff --git a/lib/pages/settings/integration_settings.part.dart b/lib/pages/settings/integration_settings.part.dart index 5049576..bb1d1f2 100644 --- a/lib/pages/settings/integration_settings.part.dart +++ b/lib/pages/settings/integration_settings.part.dart @@ -14,9 +14,6 @@ class _IntegrationSettingsPageState extends State { int _locationInterval = LocationManager().defaultUpdateIntervalMinutes; bool _locationTrackingEnabled = false; bool _wait = false; - String _deviceName = ''; - bool _applyNameEnabled = false; - String _newDeviceName = ''; @override void initState() { @@ -30,7 +27,6 @@ class _IntegrationSettingsPageState extends State { await prefs.reload(); SharedPreferences.getInstance().then((prefs) { setState(() { - _deviceName = _newDeviceName = ConnectionManager().mobileAppDeviceName ?? MobileAppIntegrationManager.getDefaultDeviceName(); _locationTrackingEnabled = prefs.getBool("location-enabled") ?? false; _locationInterval = prefs.getInt("location-interval") ?? LocationManager().defaultUpdateIntervalMinutes; if (_locationInterval % 5 != 0) { @@ -40,7 +36,7 @@ class _IntegrationSettingsPageState extends State { }); } - void incLocationInterval() { + void _incLocationInterval() { if (_locationInterval < 720) { setState(() { _locationInterval = _locationInterval + 5; @@ -48,7 +44,7 @@ class _IntegrationSettingsPageState extends State { } } - void decLocationInterval() { + void _decLocationInterval() { if (_locationInterval > 5) { setState(() { _locationInterval = _locationInterval - 5; @@ -56,52 +52,6 @@ class _IntegrationSettingsPageState extends State { } } - restart() { - eventBus.fire(ShowPopupEvent( - Popup( - title: "Are you sure you want to restart Home Assistant?", - body: "This will restart your Home Assistant server.", - positiveText: "Sure. Make it so", - negativeText: "What?? No!", - onPositive: () { - ConnectionManager().callService(domain: "homeassistant", service: "restart"); - } - ), - )); - } - - stop() { - eventBus.fire(ShowPopupEvent( - Popup( - title: "Are you sure you want to STOP Home Assistant?", - body: "This will STOP your Home Assistant server. It means that your web interface as well as HA Client will not work untill you'll find a way to start your server using ssh or something.", - positiveText: "Sure. Make it so", - negativeText: "What?? No!", - onPositive: () { - ConnectionManager().callService(domain: "homeassistant", service: "stop"); - }, - ) - )); - } - - updateRegistration() { - MobileAppIntegrationManager.checkAppRegistration(showOkDialog: true); - } - - resetRegistration() { - eventBus.fire(ShowPopupEvent( - Popup( - title: "Waaaait", - body: "If you don't whant to have duplicate integrations and entities in your HA for your current device, first you need to remove MobileApp integration from Integration settings in HA and restart server.", - positiveText: "Done it already", - negativeText: "Ok, I will", - onPositive: () { - MobileAppIntegrationManager.checkAppRegistration(showOkDialog: true, forceRegister: true); - }, - ) - )); - } - _switchLocationTrackingState(bool state) async { if (state) { await LocationManager().updateDeviceLocation(); @@ -156,37 +106,16 @@ class _IntegrationSettingsPageState extends State { FlatButton( padding: EdgeInsets.all(0.0), child: Text("-", style: Theme.of(context).textTheme.title), - onPressed: () => decLocationInterval(), + onPressed: () => _decLocationInterval(), ), Text("$_locationInterval", style: Theme.of(context).textTheme.title), FlatButton( padding: EdgeInsets.all(0.0), child: Text("+", style: Theme.of(context).textTheme.title), - onPressed: () => incLocationInterval(), + onPressed: () => _incLocationInterval(), ), ], - ), - Divider(), - Text("Device name", style: Theme.of(context).textTheme.title), - Container(height: Sizes.rowPadding,), - TextField( - /*decoration: InputDecoration( - labelText: "Long-lived token" - ),*/ - controller: TextEditingController.fromValue(TextEditingValue(text: _newDeviceName)), - onChanged: (value) { - setState(() { - _newDeviceName = value; - _applyNameEnabled = _newDeviceName != _deviceName; - }); - } - ), - Container(height: 6.0,), - RaisedButton( - color: Colors.blue, - onPressed: () => _applyNameEnabled ? updateRegistration() : null, - child: Text("Update device name", style: Theme.of(context).textTheme.button) - ), + ) ] ); } diff --git a/lib/popups.dart b/lib/popups.dart index fd80bbf..0253fc6 100644 --- a/lib/popups.dart +++ b/lib/popups.dart @@ -10,7 +10,7 @@ class Popup { Popup({@required this.title, @required this.body, this.positiveText, this.negativeText, this.onPositive, this.onNegative}); - void show(BuildContext context) { + Future show(BuildContext context) { List buttons = []; buttons.add(FlatButton( child: new Text("$positiveText"), @@ -33,7 +33,7 @@ class Popup { )); } // flutter defined function - showDialog( + return showDialog( barrierDismissible: false, context: context, builder: (BuildContext context) { @@ -55,8 +55,8 @@ class TokenLoginPopup extends Popup { final _tokenLoginFormKey = GlobalKey(); @override - void show(BuildContext context) { - showDialog( + Future show(BuildContext context) { + return showDialog( barrierDismissible: false, context: context, builder: (BuildContext context) { @@ -97,6 +97,13 @@ class TokenLoginPopup extends Popup { Row( mainAxisSize: MainAxisSize.min, children: [ + FlatButton( + child: Text('Cancel'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + Container(width: 10), FlatButton( child: Text('Login'), onPressed: () { @@ -105,13 +112,93 @@ class TokenLoginPopup extends Popup { } }, ), - Container(width: 10), + ], + ) + ], + ), + ) + ], + ); + }, + ); + } + +} + +class RegisterAppPopup extends Popup { + + RegisterAppPopup({String title, String body}): super(title: title, body: body); + + final _tokenLoginFormKey = GlobalKey(); + + @override + Future show(BuildContext context) { + return showDialog( + barrierDismissible: false, + context: context, + builder: (BuildContext context) { + // return object of type Dialog + return SimpleDialog( + title: new Text('${this.title}'), + children: [ + Form( + key: _tokenLoginFormKey, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: EdgeInsets.only(left: 20, right: 20), + child: Text('${this.body}') + ), + Padding( + padding: EdgeInsets.all(20), + child: TextFormField( + initialValue: ConnectionManager().mobileAppDeviceName ?? MobileAppIntegrationManager.getDefaultDeviceName(), + onSaved: (newValue) { + String deviceName = newValue?.trim(); + SharedPreferences.getInstance().then((prefs) { + prefs.remove("app-webhook-id"); + prefs.setString('app-integration-device-name', deviceName); + ConnectionManager().webhookId = null; + ConnectionManager().mobileAppDeviceName = deviceName; + Navigator.of(context).pop(); + MobileAppIntegrationManager.checkAppRegistration(); + }); + }, + decoration: InputDecoration( + labelText: 'Device name*', + hintText: 'Please enter device name', + contentPadding: EdgeInsets.all(0), + hintStyle: Theme.of(context).textTheme.subhead.copyWith( + color: Theme.of(context).textTheme.overline.color + ) + ), + validator: (value) { + if (value.trim().isEmpty) { + return 'Device name can\'t be emty'; + } + return null; + }, + ) + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ FlatButton( child: Text('Cancel'), onPressed: () { Navigator.of(context).pop(); }, - ) + ), + Container(width: 10), + FlatButton( + child: Text('Create now'), + onPressed: () { + if (_tokenLoginFormKey.currentState.validate()) { + _tokenLoginFormKey.currentState.save(); + } + }, + ), ], ) ],