WIP: App settings refactoring
This commit is contained in:
		| @@ -10,7 +10,7 @@ class Badges extends StatelessWidget { | |||||||
|     List<EntityWrapper> entitiesToShow = badges.getEntitiesToShow(); |     List<EntityWrapper> entitiesToShow = badges.getEntitiesToShow(); | ||||||
|      |      | ||||||
|     if (entitiesToShow.isNotEmpty) { |     if (entitiesToShow.isNotEmpty) { | ||||||
|       if (ConnectionManager().scrollBadges) { |       if (AppSettings().scrollBadges) { | ||||||
|         return ConstrainedBox( |         return ConstrainedBox( | ||||||
|           constraints: BoxConstraints.tightFor(height: 112), |           constraints: BoxConstraints.tightFor(height: 112), | ||||||
|           child: SingleChildScrollView( |           child: SingleChildScrollView( | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ class _CameraStreamViewState extends State<CameraStreamView> { | |||||||
|           _jsMessageChannelName = 'HA_${_entity.entityId.replaceAll('.', '_')}'; |           _jsMessageChannelName = 'HA_${_entity.entityId.replaceAll('.', '_')}'; | ||||||
|             rootBundle.loadString('assets/html/cameraLiveView.html').then((file) { |             rootBundle.loadString('assets/html/cameraLiveView.html').then((file) { | ||||||
|               _webViewHtml = Uri.dataFromString( |               _webViewHtml = Uri.dataFromString( | ||||||
|                   file.replaceFirst('{{stream_url}}', '${ConnectionManager().httpWebHost}${data["url"]}').replaceFirst('{{message_channel}}', _jsMessageChannelName), |                   file.replaceFirst('{{stream_url}}', '${AppSettings().httpWebHost}${data["url"]}').replaceFirst('{{message_channel}}', _jsMessageChannelName), | ||||||
|                   mimeType: 'text/html', |                   mimeType: 'text/html', | ||||||
|                   encoding: Encoding.getByName('utf-8') |                   encoding: Encoding.getByName('utf-8') | ||||||
|               ).toString(); |               ).toString(); | ||||||
| @@ -69,7 +69,7 @@ class _CameraStreamViewState extends State<CameraStreamView> { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   Future _loadMJPEG() async { |   Future _loadMJPEG() async { | ||||||
|     _streamUrl = '${ConnectionManager().httpWebHost}/api/camera_proxy_stream/${_entity |     _streamUrl = '${AppSettings().httpWebHost}/api/camera_proxy_stream/${_entity | ||||||
|         .entityId}?token=${_entity.attributes['access_token']}'; |         .entityId}?token=${_entity.attributes['access_token']}'; | ||||||
|     _jsMessageChannelName = 'HA_${_entity.entityId.replaceAll('.', '_')}'; |     _jsMessageChannelName = 'HA_${_entity.entityId.replaceAll('.', '_')}'; | ||||||
|     var file = await rootBundle.loadString('assets/html/cameraView.html'); |     var file = await rootBundle.loadString('assets/html/cameraView.html'); | ||||||
|   | |||||||
| @@ -61,7 +61,7 @@ class EntityWrapper { | |||||||
|       case EntityUIAction.navigate: { |       case EntityUIAction.navigate: { | ||||||
|         if (uiAction.tapService != null && uiAction.tapService.startsWith("/")) { |         if (uiAction.tapService != null && uiAction.tapService.startsWith("/")) { | ||||||
|           //TODO handle local urls |           //TODO handle local urls | ||||||
|           Launcher.launchURLInBrowser('${ConnectionManager().httpWebHost}${uiAction.tapService}'); |           Launcher.launchURLInBrowser('${AppSettings().httpWebHost}${uiAction.tapService}'); | ||||||
|         } else { |         } else { | ||||||
|           Launcher.launchURLInBrowser(uiAction.tapService); |           Launcher.launchURLInBrowser(uiAction.tapService); | ||||||
|         } |         } | ||||||
| @@ -101,7 +101,7 @@ class EntityWrapper { | |||||||
|         case EntityUIAction.navigate: { |         case EntityUIAction.navigate: { | ||||||
|           if (uiAction.holdService != null && uiAction.holdService.startsWith("/")) { |           if (uiAction.holdService != null && uiAction.holdService.startsWith("/")) { | ||||||
|             //TODO handle local urls |             //TODO handle local urls | ||||||
|             Launcher.launchURLInBrowser('${ConnectionManager().httpWebHost}${uiAction.holdService}'); |             Launcher.launchURLInBrowser('${AppSettings().httpWebHost}${uiAction.holdService}'); | ||||||
|           } else { |           } else { | ||||||
|             Launcher.launchURLInBrowser(uiAction.holdService); |             Launcher.launchURLInBrowser(uiAction.holdService); | ||||||
|           } |           } | ||||||
| @@ -141,7 +141,7 @@ class EntityWrapper { | |||||||
|         case EntityUIAction.navigate: { |         case EntityUIAction.navigate: { | ||||||
|           if (uiAction.doubleTapService != null && uiAction.doubleTapService.startsWith("/")) { |           if (uiAction.doubleTapService != null && uiAction.doubleTapService.startsWith("/")) { | ||||||
|             //TODO handle local urls |             //TODO handle local urls | ||||||
|             Launcher.launchURLInBrowser('${ConnectionManager().httpWebHost}${uiAction.doubleTapService}'); |             Launcher.launchURLInBrowser('${AppSettings().httpWebHost}${uiAction.doubleTapService}'); | ||||||
|           } else { |           } else { | ||||||
|             Launcher.launchURLInBrowser(uiAction.doubleTapService); |             Launcher.launchURLInBrowser(uiAction.doubleTapService); | ||||||
|           } |           } | ||||||
|   | |||||||
| @@ -63,7 +63,7 @@ class HomeAssistant { | |||||||
|     _fetchCompleter = Completer(); |     _fetchCompleter = Completer(); | ||||||
|     List<Future> futures = []; |     List<Future> futures = []; | ||||||
|     if (!uiOnly) { |     if (!uiOnly) { | ||||||
|       if (entities == null) entities = EntityCollection(ConnectionManager().httpWebHost); |       if (entities == null) entities = EntityCollection(AppSettings().httpWebHost); | ||||||
|       futures.add(_getStates(null)); |       futures.add(_getStates(null)); | ||||||
|       futures.add(_getConfig(null)); |       futures.add(_getConfig(null)); | ||||||
|       futures.add(_getUserInfo(null)); |       futures.add(_getUserInfo(null)); | ||||||
| @@ -92,7 +92,7 @@ class HomeAssistant { | |||||||
|     SharedPreferences prefs = await SharedPreferences.getInstance(); |     SharedPreferences prefs = await SharedPreferences.getInstance(); | ||||||
|     bool cached = prefs.getBool('cached'); |     bool cached = prefs.getBool('cached'); | ||||||
|     if (cached != null && cached) { |     if (cached != null && cached) { | ||||||
|       if (entities == null) entities = EntityCollection(ConnectionManager().httpWebHost); |       if (entities == null) entities = EntityCollection(AppSettings().httpWebHost); | ||||||
|       try { |       try { | ||||||
|         _getStates(prefs); |         _getStates(prefs); | ||||||
|         if (!autoUi) { |         if (!autoUi) { | ||||||
| @@ -194,7 +194,7 @@ class HomeAssistant { | |||||||
|     } else { |     } else { | ||||||
|       Completer completer = Completer(); |       Completer completer = Completer(); | ||||||
|       var additionalData; |       var additionalData; | ||||||
|       if (ConnectionManager().haVersion >= 107 && _lovelaceDashbordUrl != HomeAssistant.DEFAULT_DASHBOARD) { |       if (AppSettings().haVersion >= 107 && _lovelaceDashbordUrl != HomeAssistant.DEFAULT_DASHBOARD) { | ||||||
|         additionalData = { |         additionalData = { | ||||||
|           'url_path': _lovelaceDashbordUrl |           'url_path': _lovelaceDashbordUrl | ||||||
|         }; |         }; | ||||||
|   | |||||||
| @@ -187,12 +187,11 @@ void main() async { | |||||||
|   }; |   }; | ||||||
|  |  | ||||||
|   WidgetsFlutterBinding.ensureInitialized(); |   WidgetsFlutterBinding.ensureInitialized(); | ||||||
|   SharedPreferences prefs = await SharedPreferences.getInstance(); |   AppSettings().loadAppTheme(); | ||||||
|   AppTheme theme = AppTheme.values[prefs.getInt('app-theme') ?? AppTheme.defaultTheme.index]; |  | ||||||
|  |  | ||||||
|   runZoned(() { |   runZoned(() { | ||||||
|       runApp(new HAClientApp( |       runApp(new HAClientApp( | ||||||
|         theme: theme, |         theme: AppSettings().appTheme, | ||||||
|       )); |       )); | ||||||
|   }, onError: (error, stack) { |   }, onError: (error, stack) { | ||||||
|     _reportError(error, stack); |     _reportError(error, stack); | ||||||
| @@ -287,7 +286,7 @@ class _HAClientAppState extends State<HAClientApp> { | |||||||
|         "/quick-start": (context) => QuickStartPage(), |         "/quick-start": (context) => QuickStartPage(), | ||||||
|         "/haclient_zha": (context) => ZhaPage(), |         "/haclient_zha": (context) => ZhaPage(), | ||||||
|         "/auth": (context) => new standaloneWebview.WebviewScaffold( |         "/auth": (context) => new standaloneWebview.WebviewScaffold( | ||||||
|           url: "${ConnectionManager().oauthUrl}", |           url: "${AppSettings().oauthUrl}", | ||||||
|           appBar: new AppBar( |           appBar: new AppBar( | ||||||
|             leading: IconButton( |             leading: IconButton( | ||||||
|               icon: Icon(Icons.help), |               icon: Icon(Icons.help), | ||||||
|   | |||||||
| @@ -16,15 +16,25 @@ class AppSettings { | |||||||
|   String displayHostname; |   String displayHostname; | ||||||
|   String webSocketAPIEndpoint; |   String webSocketAPIEndpoint; | ||||||
|   String httpWebHost; |   String httpWebHost; | ||||||
|   String _token; |   String longLivedToken; | ||||||
|   String _tempToken; |   String tempToken; | ||||||
|   String oauthUrl; |   String oauthUrl; | ||||||
|   String webhookId; |   String webhookId; | ||||||
|   double haVersion; |   double haVersion; | ||||||
|   bool scrollBadges; |   bool scrollBadges; | ||||||
|   int appIntegrationVersion; |   int appIntegrationVersion; | ||||||
|  |   AppTheme appTheme; | ||||||
|  |   final int defaultLocationUpdateIntervalMinutes = 20; | ||||||
|  |   Duration locationUpdateInterval; | ||||||
|  |   bool locationTrackingEnabled = false; | ||||||
|  |  | ||||||
|   bool get isAuthenticated => _token != null; |   bool get isAuthenticated => longLivedToken != null; | ||||||
|  |   bool get isTempAuthenticated => tempToken != null; | ||||||
|  |  | ||||||
|  |   loadAppTheme() async { | ||||||
|  |     SharedPreferences prefs = await SharedPreferences.getInstance(); | ||||||
|  |     appTheme = AppTheme.values[prefs.getInt('app-theme') ?? AppTheme.defaultTheme.index]; | ||||||
|  |   } | ||||||
|  |  | ||||||
|   Future load(bool quick) async { |   Future load(bool quick) async { | ||||||
|     if (!quick) { |     if (!quick) { | ||||||
| @@ -36,13 +46,16 @@ class AppSettings { | |||||||
|       appIntegrationVersion = prefs.getInt('app-integration-version') ?? 0; |       appIntegrationVersion = prefs.getInt('app-integration-version') ?? 0; | ||||||
|       scrollBadges = prefs.getBool('scroll-badges') ?? true; |       scrollBadges = prefs.getBool('scroll-badges') ?? true; | ||||||
|       displayHostname = "$_domain:$_port"; |       displayHostname = "$_domain:$_port"; | ||||||
|       _webSocketAPIEndpoint = |       webSocketAPIEndpoint = | ||||||
|         "${prefs.getString('hassio-protocol')}://$_domain:$_port/api/websocket"; |         "${prefs.getString('hassio-protocol')}://$_domain:$_port/api/websocket"; | ||||||
|       httpWebHost = |       httpWebHost = | ||||||
|         "${prefs.getString('hassio-res-protocol')}://$_domain:$_port"; |         "${prefs.getString('hassio-res-protocol')}://$_domain:$_port"; | ||||||
|  |       locationUpdateInterval = Duration(minutes: prefs.getInt("location-interval") ?? | ||||||
|  |         defaultLocationUpdateIntervalMinutes); | ||||||
|  |       locationTrackingEnabled = prefs.getBool("location-enabled") ?? false; | ||||||
|       try { |       try { | ||||||
|         final storage = new FlutterSecureStorage(); |         final storage = new FlutterSecureStorage(); | ||||||
|         _token = await storage.read(key: "hacl_llt"); |         longLivedToken = await storage.read(key: "hacl_llt"); | ||||||
|         Logger.d("Long-lived token read successful"); |         Logger.d("Long-lived token read successful"); | ||||||
|         oauthUrl = "$httpWebHost/auth/authorize?client_id=${Uri.encodeComponent( |         oauthUrl = "$httpWebHost/auth/authorize?client_id=${Uri.encodeComponent( | ||||||
|             'https://ha-client.app')}&redirect_uri=${Uri |             'https://ha-client.app')}&redirect_uri=${Uri | ||||||
| @@ -54,15 +67,58 @@ class AppSettings { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   Future save(Map<String, dynamic> settings) async { | ||||||
|  |     if (settings != null && settings.isNotEmpty) { | ||||||
|  |       SharedPreferences prefs = await SharedPreferences.getInstance(); | ||||||
|  |       settings.forEach((k,v) async { | ||||||
|  |         if (v is String) { | ||||||
|  |           await prefs.setString(k, v); | ||||||
|  |         } else if (v is bool) { | ||||||
|  |           await prefs.setBool(k ,v); | ||||||
|  |         } else if (v is int) { | ||||||
|  |           await prefs.setInt(k ,v); | ||||||
|  |         } else if (v is double) { | ||||||
|  |           await prefs.setDouble(k, v); | ||||||
|  |         } else { | ||||||
|  |           Logger.e('Unknown setting type: <$k, $v>'); | ||||||
|  |         } | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|   Future startAuth() { |   Future startAuth() { | ||||||
|     return AuthManager().start( |     return AuthManager().start( | ||||||
|       oauthUrl: oauthUrl |       oauthUrl: oauthUrl | ||||||
|     ).then((token) { |     ).then((token) { | ||||||
|       Logger.d("Token from AuthManager recived"); |       Logger.d("Token from AuthManager recived"); | ||||||
|       _tempToken = token; |       tempToken = token; | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   Future clearTokens() async { | ||||||
|  |     longLivedToken = null; | ||||||
|  |     tempToken = null; | ||||||
|  |     try { | ||||||
|  |       final storage = new FlutterSecureStorage(); | ||||||
|  |       await storage.delete(key: "hacl_llt"); | ||||||
|  |     } catch(e, stacktrace) { | ||||||
|  |       Logger.e("Error clearing tokens: $e", stacktrace: stacktrace); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   Future saveLongLivedToken(token) async { | ||||||
|  |     longLivedToken = token; | ||||||
|  |     tempToken = null; | ||||||
|  |     try { | ||||||
|  |       final storage = new FlutterSecureStorage(); | ||||||
|  |       await storage.write(key: "hacl_llt", value: "$longLivedToken"); | ||||||
|  |       SharedPreferences prefs = await SharedPreferences.getInstance(); | ||||||
|  |       prefs.setBool("oauth-used", true); | ||||||
|  |     } catch(e, stacktrace) { | ||||||
|  |       Logger.e("Error saving long-lived token: $e", stacktrace: stacktrace); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|   bool isNotConfigured() { |   bool isNotConfigured() { | ||||||
|     return _domain == null && _port == null && webhookId == null && mobileAppDeviceName == null; |     return _domain == null && _port == null && webhookId == null && mobileAppDeviceName == null; | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -212,16 +212,16 @@ class ConnectionManager { | |||||||
|       Logger.d( "[Sending] ==> auth request"); |       Logger.d( "[Sending] ==> auth request"); | ||||||
|       sendSocketMessage( |       sendSocketMessage( | ||||||
|           type: "auth", |           type: "auth", | ||||||
|           additionalData: {"access_token": "$_token"}, |           additionalData: {"access_token": "${AppSettings().longLivedToken}"}, | ||||||
|           auth: true |           auth: true | ||||||
|       ).then((_) { |       ).then((_) { | ||||||
|         completer.complete(); |         completer.complete(); | ||||||
|       }).catchError((e) => completer.completeError(e)); |       }).catchError((e) => completer.completeError(e)); | ||||||
|     } else if (_tempToken != null) { |     } else if (AppSettings().isTempAuthenticated != null) { | ||||||
|       Logger.d("We have temp token. Loging in..."); |       Logger.d("We have temp token. Loging in..."); | ||||||
|       sendSocketMessage( |       sendSocketMessage( | ||||||
|           type: "auth", |           type: "auth", | ||||||
|           additionalData: {"access_token": "$_tempToken"}, |           additionalData: {"access_token": "${AppSettings().tempToken}"}, | ||||||
|           auth: true |           auth: true | ||||||
|       ).then((_) { |       ).then((_) { | ||||||
|         Logger.d("Requesting long-lived token..."); |         Logger.d("Requesting long-lived token..."); | ||||||
| @@ -239,35 +239,17 @@ class ConnectionManager { | |||||||
|     return completer.future; |     return completer.future; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   Future logout() { |   Future logout() async { | ||||||
|     Logger.d("Logging out"); |     Logger.d("Logging out"); | ||||||
|     Completer completer = Completer(); |     await _disconnect(); | ||||||
|     _disconnect().whenComplete(() { |     await AppSettings().clearTokens(); | ||||||
|       _token = null; |  | ||||||
|       _tempToken = null; |  | ||||||
|       final storage = new FlutterSecureStorage(); |  | ||||||
|       storage.delete(key: "hacl_llt").whenComplete((){ |  | ||||||
|         completer.complete(); |  | ||||||
|       }); |  | ||||||
|     }); |  | ||||||
|     return completer.future; |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   Future _getLongLivedToken() { |   Future _getLongLivedToken() { | ||||||
|     Completer completer = Completer(); |     Completer completer = Completer(); | ||||||
|     sendSocketMessage(type: "auth/long_lived_access_token", additionalData: {"client_name": "HA Client app ${DateTime.now().millisecondsSinceEpoch}", "lifespan": 365}).then((data) { |     sendSocketMessage(type: "auth/long_lived_access_token", additionalData: {"client_name": "HA Client app ${DateTime.now().millisecondsSinceEpoch}", "lifespan": 365}).then((data) { | ||||||
|       Logger.d("Got long-lived token."); |       Logger.d("Got long-lived token."); | ||||||
|       _token = data; |       AppSettings().saveLongLivedToken(data); | ||||||
|       _tempToken = null; |  | ||||||
|       final storage = new FlutterSecureStorage(); |  | ||||||
|       storage.write(key: "hacl_llt", value: "$_token").then((_) { |  | ||||||
|         SharedPreferences.getInstance().then((prefs) { |  | ||||||
|           prefs.setBool("oauth-used", true); |  | ||||||
|           completer.complete(); |  | ||||||
|         }); |  | ||||||
|       }).catchError((e) { |  | ||||||
|         throw e; |  | ||||||
|       }); |  | ||||||
|     }).catchError((e) { |     }).catchError((e) { | ||||||
|       completer.completeError(HACException("Authentication error: $e", actions: [HAErrorAction.reload(title: "Retry"), HAErrorAction.loginAgain(title: "Relogin")])); |       completer.completeError(HACException("Authentication error: $e", actions: [HAErrorAction.reload(title: "Retry"), HAErrorAction.loginAgain(title: "Relogin")])); | ||||||
|     }); |     }); | ||||||
| @@ -339,11 +321,11 @@ class ConnectionManager { | |||||||
|     DateTime now = DateTime.now(); |     DateTime now = DateTime.now(); | ||||||
|     //String endTime = formatDate(now, [yyyy, '-', mm, '-', dd, 'T', HH, ':', nn, ':', ss, z]); |     //String endTime = formatDate(now, [yyyy, '-', mm, '-', dd, 'T', HH, ':', nn, ':', ss, z]); | ||||||
|     String startTime = formatDate(now.subtract(Duration(hours: 24)), [yyyy, '-', mm, '-', dd, 'T', HH, ':', nn, ':', ss, z]); |     String startTime = formatDate(now.subtract(Duration(hours: 24)), [yyyy, '-', mm, '-', dd, 'T', HH, ':', nn, ':', ss, z]); | ||||||
|     String url = "$httpWebHost/api/history/period/$startTime?&filter_entity_id=$entityId"; |     String url = "${AppSettings().httpWebHost}/api/history/period/$startTime?&filter_entity_id=$entityId"; | ||||||
|     Logger.d("[Sending] ==> HTTP /api/history/period/$startTime?&filter_entity_id=$entityId"); |     Logger.d("[Sending] ==> HTTP /api/history/period/$startTime?&filter_entity_id=$entityId"); | ||||||
|     http.Response historyResponse; |     http.Response historyResponse; | ||||||
|     historyResponse = await http.get(url, headers: { |     historyResponse = await http.get(url, headers: { | ||||||
|       "authorization": "Bearer $_token", |       "authorization": "Bearer ${AppSettings().longLivedToken}", | ||||||
|       "Content-Type": "application/json" |       "Content-Type": "application/json" | ||||||
|     }); |     }); | ||||||
|     var history = json.decode(historyResponse.body); |     var history = json.decode(historyResponse.body); | ||||||
| @@ -357,14 +339,14 @@ class ConnectionManager { | |||||||
|  |  | ||||||
|   Future sendHTTPPost({String endPoint, String data, String contentType: "application/json", bool includeAuthHeader: true}) async { |   Future sendHTTPPost({String endPoint, String data, String contentType: "application/json", bool includeAuthHeader: true}) async { | ||||||
|     Completer completer = Completer(); |     Completer completer = Completer(); | ||||||
|     String url = "$httpWebHost$endPoint"; |     String url = "${AppSettings().httpWebHost}$endPoint"; | ||||||
|     Logger.d("[Sending] ==> HTTP $endPoint"); |     Logger.d("[Sending] ==> HTTP $endPoint"); | ||||||
|     Map<String, String> headers = {}; |     Map<String, String> headers = {}; | ||||||
|     if (contentType != null) { |     if (contentType != null) { | ||||||
|       headers["Content-Type"] = contentType; |       headers["Content-Type"] = contentType; | ||||||
|     } |     } | ||||||
|     if (includeAuthHeader) { |     if (includeAuthHeader) { | ||||||
|       headers["authorization"] = "Bearer $_token"; |       headers["authorization"] = "Bearer ${AppSettings().longLivedToken}"; | ||||||
|     } |     } | ||||||
|     http.post( |     http.post( | ||||||
|         url, |         url, | ||||||
|   | |||||||
| @@ -13,68 +13,53 @@ class LocationManager { | |||||||
|     init(); |     init(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   final int defaultUpdateIntervalMinutes = 20; |  | ||||||
|   final String backgroundTaskId = "haclocationtask0"; |   final String backgroundTaskId = "haclocationtask0"; | ||||||
|   final String backgroundTaskTag = "haclocation"; |   final String backgroundTaskTag = "haclocation"; | ||||||
|   Duration _updateInterval; |  | ||||||
|   bool _isRunning; |  | ||||||
|  |  | ||||||
|   void init() async { |   void init() async { | ||||||
|     SharedPreferences prefs = await SharedPreferences.getInstance(); |     if (AppSettings().locationTrackingEnabled) { | ||||||
|     await prefs.reload(); |  | ||||||
|     _updateInterval = Duration(minutes: prefs.getInt("location-interval") ?? |  | ||||||
|         defaultUpdateIntervalMinutes); |  | ||||||
|     _isRunning = prefs.getBool("location-enabled") ?? false; |  | ||||||
|     if (_isRunning) { |  | ||||||
|       await _startLocationService(); |       await _startLocationService(); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   setSettings(bool enabled, int interval) async { |   setSettings(bool enabled, int interval) async { | ||||||
|     SharedPreferences prefs = await SharedPreferences.getInstance(); |     if (interval != AppSettings().locationUpdateInterval.inMinutes) { | ||||||
|     if (interval != _updateInterval.inMinutes) { |       await _stopLocationService(); | ||||||
|       prefs.setInt("location-interval", interval); |  | ||||||
|       _updateInterval = Duration(minutes: interval); |  | ||||||
|       if (_isRunning) { |  | ||||||
|         Logger.d("Stopping location tracking..."); |  | ||||||
|         _isRunning = false; |  | ||||||
|         await _stopLocationService(); |  | ||||||
|       } |  | ||||||
|     } |     } | ||||||
|     if (enabled && !_isRunning) { |     AppSettings().save({ | ||||||
|  |       'location-interval': interval, | ||||||
|  |       'location-enabled': enabled | ||||||
|  |     }); | ||||||
|  |     AppSettings().locationUpdateInterval = Duration(minutes: interval); | ||||||
|  |     AppSettings().locationTrackingEnabled = enabled; | ||||||
|  |     if (enabled && !AppSettings().locationTrackingEnabled) { | ||||||
|       Logger.d("Starting location tracking"); |       Logger.d("Starting location tracking"); | ||||||
|       SharedPreferences prefs = await SharedPreferences.getInstance(); |  | ||||||
|       prefs.setBool("location-enabled", enabled); |  | ||||||
|       _isRunning = true; |  | ||||||
|       await _startLocationService(); |       await _startLocationService(); | ||||||
|     } else if (!enabled && _isRunning) { |     } else if (!enabled && AppSettings().locationTrackingEnabled) { | ||||||
|       Logger.d("Stopping location tracking..."); |       Logger.d("Stopping location tracking..."); | ||||||
|       SharedPreferences prefs = await SharedPreferences.getInstance(); |  | ||||||
|       prefs.setBool("location-enabled", enabled); |  | ||||||
|       _isRunning = false; |  | ||||||
|       await _stopLocationService(); |       await _stopLocationService(); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   _startLocationService() async { |   _startLocationService() async { | ||||||
|     String webhookId = ConnectionManager().webhookId; |     String webhookId = AppSettings().webhookId; | ||||||
|     String httpWebHost = ConnectionManager().httpWebHost; |     String httpWebHost = AppSettings().httpWebHost; | ||||||
|     if (webhookId != null && webhookId.isNotEmpty) { |     if (webhookId != null && webhookId.isNotEmpty) { | ||||||
|       Duration interval; |       Duration interval; | ||||||
|       int delayFactor; |       int delayFactor; | ||||||
|       int taskCount; |       int taskCount; | ||||||
|       Logger.d("Starting location update for every ${_updateInterval |       Logger.d("Starting location update for every ${AppSettings().locationUpdateInterval | ||||||
|         .inMinutes} minutes..."); |         .inMinutes} minutes..."); | ||||||
|       if (_updateInterval.inMinutes == 10) { |       if (AppSettings().locationUpdateInterval.inMinutes == 10) { | ||||||
|         interval = Duration(minutes: 20); |         interval = Duration(minutes: 20); | ||||||
|         taskCount = 2; |         taskCount = 2; | ||||||
|         delayFactor = 10; |         delayFactor = 10; | ||||||
|       } else if (_updateInterval.inMinutes == 5) { |       } else if (AppSettings().locationUpdateInterval.inMinutes == 5) { | ||||||
|         interval = Duration(minutes: 15); |         interval = Duration(minutes: 15); | ||||||
|         taskCount = 3; |         taskCount = 3; | ||||||
|         delayFactor = 5; |         delayFactor = 5; | ||||||
|       } else { |       } else { | ||||||
|         interval = _updateInterval; |         interval = AppSettings().locationUpdateInterval; | ||||||
|         taskCount = 1; |         taskCount = 1; | ||||||
|         delayFactor = 0; |         delayFactor = 0; | ||||||
|       } |       } | ||||||
| @@ -112,8 +97,8 @@ class LocationManager { | |||||||
|       Logger.d("[Foreground location] Started"); |       Logger.d("[Foreground location] Started"); | ||||||
|       Geolocator geolocator = Geolocator(); |       Geolocator geolocator = Geolocator(); | ||||||
|       var battery = Battery(); |       var battery = Battery(); | ||||||
|       String webhookId = ConnectionManager().webhookId; |       String webhookId = AppSettings().webhookId; | ||||||
|       String httpWebHost = ConnectionManager().httpWebHost; |       String httpWebHost = AppSettings().httpWebHost; | ||||||
|       if (webhookId != null && webhookId.isNotEmpty) { |       if (webhookId != null && webhookId.isNotEmpty) { | ||||||
|           Logger.d("[Foreground location] Getting battery level..."); |           Logger.d("[Foreground location] Getting battery level..."); | ||||||
|           int batteryLevel = await battery.batteryLevel; |           int batteryLevel = await battery.batteryLevel; | ||||||
|   | |||||||
| @@ -25,9 +25,9 @@ class MobileAppIntegrationManager { | |||||||
|  |  | ||||||
|   static Future checkAppRegistration() { |   static Future checkAppRegistration() { | ||||||
|     Completer completer = Completer(); |     Completer completer = Completer(); | ||||||
|     _appRegistrationData["device_name"] = ConnectionManager().mobileAppDeviceName ?? getDefaultDeviceName(); |     _appRegistrationData["device_name"] = AppSettings().mobileAppDeviceName ?? getDefaultDeviceName(); | ||||||
|     (_appRegistrationData["app_data"] as Map)["push_token"] = "${HomeAssistant().fcmToken}"; |     (_appRegistrationData["app_data"] as Map)["push_token"] = "${HomeAssistant().fcmToken}"; | ||||||
|     if (ConnectionManager().webhookId == null) { |     if (AppSettings().webhookId == null) { | ||||||
|       Logger.d("Mobile app was not registered yet. Registering..."); |       Logger.d("Mobile app was not registered yet. Registering..."); | ||||||
|       var registrationData = Map.from(_appRegistrationData); |       var registrationData = Map.from(_appRegistrationData); | ||||||
|       registrationData.addAll({ |       registrationData.addAll({ | ||||||
| @@ -36,7 +36,7 @@ class MobileAppIntegrationManager { | |||||||
|         "os_name": DeviceInfoManager().osName, |         "os_name": DeviceInfoManager().osName, | ||||||
|         "supports_encryption": false, |         "supports_encryption": false, | ||||||
|       }); |       }); | ||||||
|       if (ConnectionManager().haVersion >= 104) { |       if (AppSettings().haVersion >= 104) { | ||||||
|         registrationData.addAll({ |         registrationData.addAll({ | ||||||
|           "device_id": "${DeviceInfoManager().unicDeviceId}" |           "device_id": "${DeviceInfoManager().unicDeviceId}" | ||||||
|         }); |         }); | ||||||
| @@ -48,12 +48,12 @@ class MobileAppIntegrationManager { | |||||||
|       ).then((response) { |       ).then((response) { | ||||||
|         Logger.d("Processing registration responce..."); |         Logger.d("Processing registration responce..."); | ||||||
|         var responseObject = json.decode(response); |         var responseObject = json.decode(response); | ||||||
|         ConnectionManager().webhookId = responseObject["webhook_id"]; |         AppSettings().webhookId = responseObject["webhook_id"]; | ||||||
|         ConnectionManager().appIntegrationVersion = INTEGRATION_VERSION; |         AppSettings().appIntegrationVersion = INTEGRATION_VERSION; | ||||||
|         SharedPreferences.getInstance().then((prefs) { |         AppSettings().save({ | ||||||
|           prefs.setString("app-webhook-id", responseObject["webhook_id"]); |           'app-webhook-id': responseObject["webhook_id"], | ||||||
|           prefs.setInt('app-integration-version', INTEGRATION_VERSION); |           'app-integration-version': INTEGRATION_VERSION | ||||||
|  |         }).then((prefs) { | ||||||
|           completer.complete(); |           completer.complete(); | ||||||
|           eventBus.fire(ShowPopupEvent( |           eventBus.fire(ShowPopupEvent( | ||||||
|             popup: Popup( |             popup: Popup( | ||||||
| @@ -84,7 +84,7 @@ class MobileAppIntegrationManager { | |||||||
|         "data": _appRegistrationData |         "data": _appRegistrationData | ||||||
|       }; |       }; | ||||||
|       ConnectionManager().sendHTTPPost( |       ConnectionManager().sendHTTPPost( | ||||||
|           endPoint: "/api/webhook/${ConnectionManager().webhookId}", |           endPoint: "/api/webhook/${AppSettings().webhookId}", | ||||||
|           includeAuthHeader: false, |           includeAuthHeader: false, | ||||||
|           data: json.encode(updateData) |           data: json.encode(updateData) | ||||||
|       ).then((response) { |       ).then((response) { | ||||||
| @@ -98,7 +98,7 @@ class MobileAppIntegrationManager { | |||||||
|           Logger.w("No registration data in response. MobileApp integration was removed or broken"); |           Logger.w("No registration data in response. MobileApp integration was removed or broken"); | ||||||
|           _askToRegisterApp(); |           _askToRegisterApp(); | ||||||
|         } else { |         } else { | ||||||
|           if (INTEGRATION_VERSION > ConnectionManager().appIntegrationVersion) { |           if (INTEGRATION_VERSION > AppSettings().appIntegrationVersion) { | ||||||
|             Logger.d('App registration needs to be updated'); |             Logger.d('App registration needs to be updated'); | ||||||
|             _askToRemoveAndRegisterApp(); |             _askToRemoveAndRegisterApp(); | ||||||
|           } else { |           } else { | ||||||
|   | |||||||
| @@ -246,7 +246,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker | |||||||
|  |  | ||||||
|   void _showOAuth() { |   void _showOAuth() { | ||||||
|     _preventAppRefresh = true; |     _preventAppRefresh = true; | ||||||
|     Navigator.of(context).pushNamed("/auth", arguments: {"url": ConnectionManager().oauthUrl}); |     Navigator.of(context).pushNamed("/auth", arguments: {"url": AppSettings().oauthUrl}); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   _setErrorState(HACException e) { |   _setErrorState(HACException e) { | ||||||
| @@ -463,7 +463,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker | |||||||
|       child: new Text("Reload"), |       child: new Text("Reload"), | ||||||
|       value: "reload", |       value: "reload", | ||||||
|     )); |     )); | ||||||
|     if (ConnectionManager().isAuthenticated) { |     if (AppSettings().isAuthenticated) { | ||||||
|       _showLoginButton = false; |       _showLoginButton = false; | ||||||
|       serviceMenuItems.add( |       serviceMenuItems.add( | ||||||
|           PopupMenuItem<String>( |           PopupMenuItem<String>( | ||||||
|   | |||||||
| @@ -39,7 +39,7 @@ class _AppSettingsPageState extends State<AppSettingsPage> { | |||||||
|       _buildMenuItem(context, MaterialDesignIcons.getIconDataFromIconName('mdi:network'), 'Connection settings', AppSettingsSection.connectionSettings), |       _buildMenuItem(context, MaterialDesignIcons.getIconDataFromIconName('mdi:network'), 'Connection settings', AppSettingsSection.connectionSettings), | ||||||
|       _buildMenuItem(context, MaterialDesignIcons.getIconDataFromIconName('mdi:brush'), 'Look and feel', AppSettingsSection.lookAndFeel), |       _buildMenuItem(context, MaterialDesignIcons.getIconDataFromIconName('mdi:brush'), 'Look and feel', AppSettingsSection.lookAndFeel), | ||||||
|     ]; |     ]; | ||||||
|     if (ConnectionManager().webhookId != null) { |     if (AppSettings().webhookId != null) { | ||||||
|       items.insert(1, _buildMenuItem(context, MaterialDesignIcons.getIconDataFromIconName('mdi:cellphone-android'), 'Integration settings', AppSettingsSection.integrationSettings)); |       items.insert(1, _buildMenuItem(context, MaterialDesignIcons.getIconDataFromIconName('mdi:cellphone-android'), 'Integration settings', AppSettingsSection.integrationSettings)); | ||||||
|     } |     } | ||||||
|     return ListView( |     return ListView( | ||||||
|   | |||||||
| @@ -31,7 +31,7 @@ class _ConnectionSettingsPageState extends State<ConnectionSettingsPage> { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   _loadSettings() async { |   _loadSettings() async { | ||||||
|     _includeDeviceName = widget.quickStart || ConnectionManager().webhookId == null; |     _includeDeviceName = widget.quickStart || AppSettings().webhookId == null; | ||||||
|     SharedPreferences prefs = await SharedPreferences.getInstance(); |     SharedPreferences prefs = await SharedPreferences.getInstance(); | ||||||
|     String domain = prefs.getString('hassio-domain')?? ''; |     String domain = prefs.getString('hassio-domain')?? ''; | ||||||
|     String port = prefs.getString('hassio-port') ?? ''; |     String port = prefs.getString('hassio-port') ?? ''; | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ class IntegrationSettingsPage extends StatefulWidget { | |||||||
|  |  | ||||||
| class _IntegrationSettingsPageState extends State<IntegrationSettingsPage> { | class _IntegrationSettingsPageState extends State<IntegrationSettingsPage> { | ||||||
|  |  | ||||||
|   int _locationInterval = LocationManager().defaultUpdateIntervalMinutes; |   int _locationInterval = AppSettings().defaultLocationUpdateIntervalMinutes; | ||||||
|   bool _locationTrackingEnabled = false; |   bool _locationTrackingEnabled = false; | ||||||
|   bool _wait = false; |   bool _wait = false; | ||||||
|  |  | ||||||
| @@ -28,7 +28,8 @@ class _IntegrationSettingsPageState extends State<IntegrationSettingsPage> { | |||||||
|     SharedPreferences.getInstance().then((prefs) { |     SharedPreferences.getInstance().then((prefs) { | ||||||
|       setState(() { |       setState(() { | ||||||
|         _locationTrackingEnabled = prefs.getBool("location-enabled") ?? false; |         _locationTrackingEnabled = prefs.getBool("location-enabled") ?? false; | ||||||
|         _locationInterval = prefs.getInt("location-interval") ?? LocationManager().defaultUpdateIntervalMinutes; |         _locationInterval = prefs.getInt("location-interval") ?? | ||||||
|  |           AppSettings().defaultLocationUpdateIntervalMinutes; | ||||||
|         if (_locationInterval % 5 != 0) { |         if (_locationInterval % 5 != 0) { | ||||||
|           _locationInterval = 5 * (_locationInterval ~/ 5); |           _locationInterval = 5 * (_locationInterval ~/ 5); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -44,7 +44,7 @@ class _LookAndFeelSettingsPageState extends State<LookAndFeelSettingsPage> { | |||||||
|  |  | ||||||
|   Future _saveOther() async { |   Future _saveOther() async { | ||||||
|     SharedPreferences prefs = await SharedPreferences.getInstance(); |     SharedPreferences prefs = await SharedPreferences.getInstance(); | ||||||
|     ConnectionManager().scrollBadges = _scrollBadges; |     AppSettings().scrollBadges = _scrollBadges; | ||||||
|     await prefs.setBool('scroll-badges', _scrollBadges); |     await prefs.setBool('scroll-badges', _scrollBadges); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -20,7 +20,7 @@ class _ConfigPanelWidgetState extends State<ConfigPanelWidget> { | |||||||
|   Widget build(BuildContext context) { |   Widget build(BuildContext context) { | ||||||
|     return ListView( |     return ListView( | ||||||
|       children: [ |       children: [ | ||||||
|         LinkToWebConfig(name: "Home Assistant configuration", url: ConnectionManager().httpWebHost+"/config"), |         LinkToWebConfig(name: "Home Assistant configuration", url: AppSettings().httpWebHost+"/config"), | ||||||
|       ], |       ], | ||||||
|     ); |     ); | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -38,7 +38,7 @@ class Panel { | |||||||
|         eventBus.fire(ReloadUIEvent()); |         eventBus.fire(ReloadUIEvent()); | ||||||
|       }); |       }); | ||||||
|     } else { |     } else { | ||||||
|       Launcher.launchAuthenticatedWebView(context: context, url: "${ConnectionManager().httpWebHost}/$urlPath", title: "${this.title}"); |       Launcher.launchAuthenticatedWebView(context: context, url: "${AppSettings().httpWebHost}/$urlPath", title: "${this.title}"); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -153,14 +153,14 @@ class RegisterAppPopup extends Popup { | |||||||
|                   Padding( |                   Padding( | ||||||
|                     padding: EdgeInsets.all(20), |                     padding: EdgeInsets.all(20), | ||||||
|                       child: TextFormField( |                       child: TextFormField( | ||||||
|                         initialValue: ConnectionManager().mobileAppDeviceName ?? MobileAppIntegrationManager.getDefaultDeviceName(), |                         initialValue: AppSettings().mobileAppDeviceName ?? MobileAppIntegrationManager.getDefaultDeviceName(), | ||||||
|                         onSaved: (newValue) { |                         onSaved: (newValue) { | ||||||
|                           String deviceName =  newValue?.trim(); |                           String deviceName =  newValue?.trim(); | ||||||
|                           SharedPreferences.getInstance().then((prefs) { |                           SharedPreferences.getInstance().then((prefs) { | ||||||
|                             prefs.remove("app-webhook-id"); |                             prefs.remove("app-webhook-id"); | ||||||
|                             prefs.setString('app-integration-device-name', deviceName); |                             prefs.setString('app-integration-device-name', deviceName); | ||||||
|                             ConnectionManager().webhookId = null; |                             AppSettings().webhookId = null; | ||||||
|                             ConnectionManager().mobileAppDeviceName = deviceName; |                             AppSettings().mobileAppDeviceName = deviceName; | ||||||
|                             Navigator.of(context).pop(); |                             Navigator.of(context).pop(); | ||||||
|                             MobileAppIntegrationManager.checkAppRegistration(); |                             MobileAppIntegrationManager.checkAppRegistration(); | ||||||
|                           }); |                           }); | ||||||
|   | |||||||
| @@ -45,7 +45,7 @@ class Launcher { | |||||||
|       if (viewState.type == standaloneWebview.WebViewState.startLoad) { |       if (viewState.type == standaloneWebview.WebViewState.startLoad) { | ||||||
|         Logger.d("[WebView] Injecting external auth JS"); |         Logger.d("[WebView] Injecting external auth JS"); | ||||||
|         rootBundle.loadString('assets/js/externalAuth.js').then((js){ |         rootBundle.loadString('assets/js/externalAuth.js').then((js){ | ||||||
|           flutterWebViewPlugin.evalJavascript(js.replaceFirst("[token]", ConnectionManager()._token)); |           flutterWebViewPlugin.evalJavascript(js.replaceFirst("[token]", AppSettings().longLivedToken)); | ||||||
|         }); |         }); | ||||||
|       } |       } | ||||||
|     }); |     }); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user