diff --git a/lib/home_assistant.class.dart b/lib/home_assistant.class.dart index f848c5e..547b0df 100644 --- a/lib/home_assistant.class.dart +++ b/lib/home_assistant.class.dart @@ -79,7 +79,7 @@ class HomeAssistant { _fetchCompleter.complete(); if (!uiOnly) MobileAppIntegrationManager.checkAppRegistration(); } else { - _fetchCompleter.completeError(HAError("Mobile app component not found", actions: [HAErrorAction.tryAgain(), HAErrorAction(type: HAErrorActionType.URL ,title: "Help",url: "http://ha-client.app/docs#mobile-app-integration")])); + _fetchCompleter.completeError(HACException("Mobile app component not found", actions: [HAErrorAction.tryAgain(), HAErrorAction(type: HAErrorActionType.URL ,title: "Help",url: "http://ha-client.app/docs#mobile-app-integration")])); } }).catchError((e) { _fetchCompleter.completeError(e); @@ -144,11 +144,11 @@ class HomeAssistant { var data = json.decode(sharedPrefs.getString('cached_config')); _parseConfig(data); } catch (e) { - throw HAError("Error getting config: $e"); + throw HACException("Error getting config: $e"); } } else { await ConnectionManager().sendSocketMessage(type: "get_config").then((data) => _parseConfig(data)).catchError((e) { - throw HAError("Error getting config: $e"); + throw HACException("Error getting config: $e"); }); } } @@ -164,13 +164,13 @@ class HomeAssistant { var data = json.decode(sharedPrefs.getString('cached_states')); _parseStates(data); } catch (e) { - throw HAError("Error getting states: $e"); + throw HACException("Error getting states: $e"); } } else { await ConnectionManager().sendSocketMessage(type: "get_states").then( (data) => _parseStates(data) ).catchError((e) { - throw HAError("Error getting states: $e"); + throw HACException("Error getting states: $e"); }); } } @@ -209,7 +209,7 @@ class HomeAssistant { _rawLovelaceData = null; completer.complete(); } else { - completer.completeError(HAError("Error getting lovelace config: $e")); + completer.completeError(HACException("Error getting lovelace config: $e")); } }); return completer.future; @@ -249,14 +249,17 @@ class HomeAssistant { Future _getPanels(SharedPreferences sharedPrefs) async { if (sharedPrefs != null) { try { - var data = json.decode(sharedPrefs.getString('cached_panels')); + var data = json.decode(sharedPrefs.getString('cached_panels') ?? '{}'); _parsePanels(data); - } catch (e) { - throw HAError("Error getting panels list: $e"); + } catch (e, stacktrace) { + Crashlytics.instance.recordError(e, stacktrace); + panels.clear(); } } else { - await ConnectionManager().sendSocketMessage(type: "get_panels").then((data) => _parsePanels(data)).catchError((e) { - throw HAError("Error getting panels list: $e"); + await ConnectionManager().sendSocketMessage(type: "get_panels").then((data) => _parsePanels(data)).catchError((e, stacktrace) { + panels.clear(); + Crashlytics.instance.recordError(e, stacktrace); + throw HACException('Can\'t get panles: $e'); }); } } diff --git a/lib/managers/auth_manager.class.dart b/lib/managers/auth_manager.class.dart index efa2d59..b1225f5 100644 --- a/lib/managers/auth_manager.class.dart +++ b/lib/managers/auth_manager.class.dart @@ -33,7 +33,7 @@ class AuthManager { }).catchError((e) { Logger.e("Error getting temp token: ${e.toString()}"); eventBus.fire(StartAuthEvent(oauthUrl, false)); - completer.completeError(HAError("Error getting temp token")); + completer.completeError(HACException("Error getting temp token")); }).whenComplete(() => flutterWebviewPlugin.close()); } }); diff --git a/lib/managers/connection_manager.class.dart b/lib/managers/connection_manager.class.dart index bafedba..554d6f9 100644 --- a/lib/managers/connection_manager.class.dart +++ b/lib/managers/connection_manager.class.dart @@ -53,7 +53,7 @@ class ConnectionManager { Logger.d('$_domain$_port'); if ((_domain == null) || (_port == null) || (_domain.isEmpty) || (_port.isEmpty)) { - completer.completeError(HAError.checkConnectionSettings()); + completer.completeError(HACException.checkConnectionSettings()); stopInit = true; } else { final storage = new FlutterSecureStorage(); @@ -66,7 +66,7 @@ class ConnectionManager { 'https://ha-client.app/service/auth_callback.html')}"; settingsLoaded = true; } catch (e) { - completer.completeError(HAError("Error reading login details", actions: [HAErrorAction.tryAgain(type: HAErrorActionType.FULL_RELOAD), HAErrorAction.loginAgain()])); + completer.completeError(HACException("Error reading login details", actions: [HAErrorAction.tryAgain(type: HAErrorActionType.FULL_RELOAD), HAErrorAction.loginAgain()])); Logger.e("Cannt read secure storage. Need to relogin."); stopInit = true; } @@ -74,7 +74,7 @@ class ConnectionManager { } else { if ((_domain == null) || (_port == null) || (_domain.isEmpty) || (_port.isEmpty)) { - completer.completeError(HAError.checkConnectionSettings()); + completer.completeError(HACException.checkConnectionSettings()); stopInit = true; } } @@ -107,13 +107,13 @@ class ConnectionManager { _disconnect().then((_) { if (e is TimeoutException) { if (connecting != null && !connecting.isCompleted) { - connecting.completeError(HAError("Connection timeout")); + connecting.completeError(HACException("Connection timeout")); } - completer?.completeError(HAError("Connection timeout")); - } else if (e is HAError) { + completer?.completeError(HACException("Connection timeout")); + } else if (e is HACException) { completer?.completeError(e); } else { - completer?.completeError(HAError("${e.toString()}")); + completer?.completeError(HACException("${e.toString()}")); } }); }); @@ -167,9 +167,9 @@ class ConnectionManager { }); } else if (data["type"] == "auth_invalid") { Logger.d("[Received] <== ${data.toString()}"); - _messageResolver["auth"]?.completeError(HAError("${data["message"]}", actions: [HAErrorAction.loginAgain()])); + _messageResolver["auth"]?.completeError(HACException("${data["message"]}", actions: [HAErrorAction.loginAgain()])); _messageResolver.remove("auth"); - if (!connecting.isCompleted) connecting.completeError(HAError("${data["message"]}", actions: [HAErrorAction.tryAgain(title: "Retry"), HAErrorAction.loginAgain(title: "Relogin")])); + if (!connecting.isCompleted) connecting.completeError(HACException("${data["message"]}", actions: [HAErrorAction.tryAgain(title: "Retry"), HAErrorAction.loginAgain(title: "Relogin")])); } else { _handleMessage(data); } @@ -179,7 +179,7 @@ class ConnectionManager { onError: (e) => _handleSocketError(e, connecting) ); } catch(exeption) { - connecting.completeError(HAError("${exeption.toString()}")); + connecting.completeError(HACException("${exeption.toString()}")); } }); return connecting.future; @@ -213,7 +213,7 @@ class ConnectionManager { _messageResolver["${data["id"]}"]?.complete(data["result"]); } else if (data["id"] != null) { Logger.e("[Received] <== Error received on request id ${data['id']}: ${data['error']}"); - _messageResolver["${data["id"]}"]?.completeError("${data["error"]["code"]}"); + _messageResolver["${data["id"]}"]?.completeError("${data["error"]["code"]}: ${data["error"]["message"]}"); } _messageResolver.remove("${data["id"]}"); } else if (data["type"] == "event") { @@ -236,9 +236,9 @@ class ConnectionManager { _disconnect().then((_) { if (!connectionCompleter.isCompleted) { isConnected = false; - connectionCompleter.completeError(HAError("Disconnected", actions: [HAErrorAction.reconnect()])); + connectionCompleter.completeError(HACException("Disconnected", actions: [HAErrorAction.reconnect()])); } - eventBus.fire(ShowErrorEvent(HAError("Unable to connect to Home Assistant"))); + eventBus.fire(ShowErrorEvent(HACException("Unable to connect to Home Assistant"))); }); } @@ -247,9 +247,9 @@ class ConnectionManager { _disconnect().then((_) { if (!connectionCompleter.isCompleted) { isConnected = false; - connectionCompleter.completeError(HAError("Disconnected", actions: [HAErrorAction.reconnect()])); + connectionCompleter.completeError(HACException("Disconnected", actions: [HAErrorAction.reconnect()])); } - eventBus.fire(ShowErrorEvent(HAError("Unable to connect to Home Assistant"))); + eventBus.fire(ShowErrorEvent(HACException("Unable to connect to Home Assistant"))); }); } @@ -282,7 +282,7 @@ class ConnectionManager { }); }).catchError((e) => completer.completeError(e)); } else { - completer.completeError(HAError("General login error")); + completer.completeError(HACException("General login error")); } return completer.future; } @@ -317,7 +317,7 @@ class ConnectionManager { throw e; }); }).catchError((e) { - completer.completeError(HAError("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")])); }); return completer.future; } @@ -344,7 +344,7 @@ class ConnectionManager { _socket.sink.add(rawMessage); }).catchError((e) { if (!_completer.isCompleted) { - _completer.completeError(HAError("No connection to Home Assistant", actions: [HAErrorAction.reconnect()])); + _completer.completeError(HACException("No connection to Home Assistant", actions: [HAErrorAction.reconnect()])); } }); } else { @@ -373,12 +373,12 @@ class ConnectionManager { sendHTTPPost( endPoint: "/api/services/$domain/$service", data: json.encode(serviceData) - ).then((data) => completer.complete(data)).catchError((e) => completer.completeError(HAError(e.toString()))); + ).then((data) => completer.complete(data)).catchError((e) => completer.completeError(HACException(e.toString()))); //return sendSocketMessage(type: "call_service", additionalData: {"domain": domain, "service": service, "service_data": serviceData}); else sendHTTPPost( endPoint: "/api/services/$domain/$service" - ).then((data) => completer.complete(data)).catchError((e) => completer.completeError(HAError(e.toString()))); + ).then((data) => completer.complete(data)).catchError((e) => completer.completeError(HACException(e.toString()))); //return sendSocketMessage(type: "call_service", additionalData: {"domain": domain, "service": service}); return completer.future; } diff --git a/lib/pages/main/main.page.dart b/lib/pages/main/main.page.dart index 2b8c670..30d5b16 100644 --- a/lib/pages/main/main.page.dart +++ b/lib/pages/main/main.page.dart @@ -131,10 +131,10 @@ class _MainPageState extends State with WidgetsBindingObserver, Ticker }); HomeAssistant().saveCache(); }).catchError((e) { - if (e is HAError) { + if (e is HACException) { _setErrorState(e); } else { - _setErrorState(HAError(e.toString())); + _setErrorState(HACException(e.toString())); } }); eventBus.fire(RefreshDataFinishedEvent()); @@ -254,10 +254,10 @@ class _MainPageState extends State with WidgetsBindingObserver, Ticker Navigator.of(context).pushNamed("/auth", arguments: {"url": ConnectionManager().oauthUrl}); } - _setErrorState(HAError e) { + _setErrorState(HACException e) { if (e == null) { _bottomInfoBarController.showErrorBottomBar( - HAError("Unknown error") + HACException("Unknown error") ); } else { _bottomInfoBarController.showErrorBottomBar(e); diff --git a/lib/pages/widgets/bottom_info_bar.dart b/lib/pages/widgets/bottom_info_bar.dart index 17504c8..8779c15 100644 --- a/lib/pages/widgets/bottom_info_bar.dart +++ b/lib/pages/widgets/bottom_info_bar.dart @@ -40,12 +40,12 @@ class BottomInfoBarController { } } - void showErrorBottomBar(HAError error) { + void showErrorBottomBar(HACException error) { actions.clear(); actions.addAll(error.actions); bottomBarErrorColor = true; bottomBarProgress = false; - bottomBarText = "${error.message}"; + bottomBarText = "${error.cause}"; if (show == null) { initialState = true; } else { diff --git a/lib/panels/panel_class.dart b/lib/panels/panel_class.dart index df89b05..47893b2 100644 --- a/lib/panels/panel_class.dart +++ b/lib/panels/panel_class.dart @@ -24,7 +24,7 @@ class Panel { icon = Panel.iconsByComponent[componentName]; } isHidden = (componentName == 'kiosk' || componentName == 'states' || componentName == 'profile' || componentName == 'developer-tools'); - isWebView = (componentName != 'config' && componentName != 'lovelace' && !componentName.startsWith('haclient')); + isWebView = (componentName != 'lovelace' && !componentName.startsWith('haclient')); } void handleOpen(BuildContext context) { @@ -68,10 +68,6 @@ class Panel { Widget getWidget() { switch (componentName) { - case "config": { - return ConfigPanelWidget(); - } - default: { return Text("Unsupported panel component: $componentName"); } diff --git a/lib/types/event_bus_events.dart b/lib/types/event_bus_events.dart index 56b923b..9d8df26 100644 --- a/lib/types/event_bus_events.dart +++ b/lib/types/event_bus_events.dart @@ -90,7 +90,7 @@ class ShowPageEvent { } class ShowErrorEvent { - final HAError error; + final HACException error; ShowErrorEvent(this.error); } \ No newline at end of file diff --git a/lib/types/ha_error.dart b/lib/types/ha_error.dart index d0a4118..4d01afb 100644 --- a/lib/types/ha_error.dart +++ b/lib/types/ha_error.dart @@ -1,21 +1,26 @@ part of '../main.dart'; -class HAError { - String message; +class HACException implements Exception { + String cause; final List actions; - HAError(this.message, {this.actions: const [HAErrorAction.tryAgain()]}); + HACException(this.cause, {this.actions: const [HAErrorAction.tryAgain()]}); - HAError.unableToConnect({this.actions = const [HAErrorAction.tryAgain()]}) { - this.message = "Unable to connect to Home Assistant"; + HACException.unableToConnect({this.actions = const [HAErrorAction.tryAgain()]}) { + this.cause = "Unable to connect to Home Assistant"; } - HAError.disconnected({this.actions = const [HAErrorAction.reconnect()]}) { - this.message = "Disconnected"; + HACException.disconnected({this.actions = const [HAErrorAction.reconnect()]}) { + this.cause = "Disconnected"; } - HAError.checkConnectionSettings({this.actions = const [HAErrorAction.reload(), HAErrorAction(title: "Settings", type: HAErrorActionType.OPEN_CONNECTION_SETTINGS)]}) { - this.message = "Check connection settings"; + HACException.checkConnectionSettings({this.actions = const [HAErrorAction.reload(), HAErrorAction(title: "Settings", type: HAErrorActionType.OPEN_CONNECTION_SETTINGS)]}) { + this.cause = "Check connection settings"; + } + + @override + String toString() { + return 'HACException: $cause'; } }