Error messages refactored
This commit is contained in:
parent
620aa3b8d8
commit
8efeb3da8a
@ -4,13 +4,11 @@ import io.flutter.app.FlutterApplication;
|
|||||||
import io.flutter.plugin.common.PluginRegistry;
|
import io.flutter.plugin.common.PluginRegistry;
|
||||||
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
|
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
|
||||||
import io.flutter.plugins.GeneratedPluginRegistrant;
|
import io.flutter.plugins.GeneratedPluginRegistrant;
|
||||||
import io.flutter.plugins.androidalarmmanager.AlarmService;
|
|
||||||
|
|
||||||
public class Application extends FlutterApplication implements PluginRegistrantCallback {
|
public class Application extends FlutterApplication implements PluginRegistrantCallback {
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
AlarmService.setPluginRegistrant(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -97,3 +97,27 @@ class CardType {
|
|||||||
static const alarmPanel = "alarm-panel";
|
static const alarmPanel = "alarm-panel";
|
||||||
static const markdown = "markdown";
|
static const markdown = "markdown";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class UserError {
|
||||||
|
final int code;
|
||||||
|
final String message;
|
||||||
|
|
||||||
|
UserError({@required this.code, this.message: ""});
|
||||||
|
}
|
||||||
|
|
||||||
|
class ErrorCode {
|
||||||
|
static const UNKNOWN = 0;
|
||||||
|
static const NOT_CONFIGURED = 1;
|
||||||
|
static const AUTH_INVALID = 2;
|
||||||
|
static const NO_MOBILE_APP_COMPONENT = 3;
|
||||||
|
static const ERROR_GETTING_CONFIG = 4;
|
||||||
|
static const ERROR_GETTING_STATES = 5;
|
||||||
|
static const ERROR_GETTING_LOVELACE_CONFIG = 6;
|
||||||
|
static const ERROR_GETTING_PANELS = 7;
|
||||||
|
static const CONNECTION_TIMEOUT = 8;
|
||||||
|
static const DISCONNECTED = 9;
|
||||||
|
static const UNABLE_TO_CONNECT = 10;
|
||||||
|
static const GENERAL_AUTH_ERROR = 11;
|
||||||
|
static const AUTH_ERROR = 12;
|
||||||
|
static const NOT_LOGGED_IN = 13;
|
||||||
|
}
|
@ -68,7 +68,7 @@ class HomeAssistant {
|
|||||||
_fetchCompleter.complete();
|
_fetchCompleter.complete();
|
||||||
MobileAppIntegrationManager.checkAppRegistration();
|
MobileAppIntegrationManager.checkAppRegistration();
|
||||||
} else {
|
} else {
|
||||||
_fetchCompleter.completeError(HAError("Mobile app component not found", actions: [HAErrorAction.tryAgain(), HAErrorAction(type: HAErrorActionType.URL ,title: "Help",url: "http://ha-client.homemade.systems/docs#mobile-app")]));
|
_fetchCompleter.completeError(UserError(code: ErrorCode.NO_MOBILE_APP_COMPONENT));
|
||||||
}
|
}
|
||||||
}).catchError((e) {
|
}).catchError((e) {
|
||||||
_fetchCompleter.completeError(e);
|
_fetchCompleter.completeError(e);
|
||||||
@ -89,7 +89,7 @@ class HomeAssistant {
|
|||||||
await ConnectionManager().sendSocketMessage(type: "get_config").then((data) {
|
await ConnectionManager().sendSocketMessage(type: "get_config").then((data) {
|
||||||
_instanceConfig = Map.from(data);
|
_instanceConfig = Map.from(data);
|
||||||
}).catchError((e) {
|
}).catchError((e) {
|
||||||
throw HAError("Error getting config: ${e}");
|
throw UserError(code: ErrorCode.ERROR_GETTING_CONFIG, message: "$e");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,26 +97,26 @@ class HomeAssistant {
|
|||||||
await ConnectionManager().sendSocketMessage(type: "get_states").then(
|
await ConnectionManager().sendSocketMessage(type: "get_states").then(
|
||||||
(data) => entities.parse(data)
|
(data) => entities.parse(data)
|
||||||
).catchError((e) {
|
).catchError((e) {
|
||||||
throw HAError("Error getting states: $e");
|
throw UserError(code: ErrorCode.ERROR_GETTING_STATES, message: "$e");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _getLovelace() async {
|
Future _getLovelace() async {
|
||||||
await ConnectionManager().sendSocketMessage(type: "lovelace/config").then((data) => _rawLovelaceData = data).catchError((e) {
|
await ConnectionManager().sendSocketMessage(type: "lovelace/config").then((data) => _rawLovelaceData = data).catchError((e) {
|
||||||
throw HAError("Error getting lovelace config: $e");
|
throw UserError(code: ErrorCode.ERROR_GETTING_LOVELACE_CONFIG, message: "$e");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _getUserInfo() async {
|
Future _getUserInfo() async {
|
||||||
_userName = null;
|
_userName = null;
|
||||||
await ConnectionManager().sendSocketMessage(type: "auth/current_user").then((data) => _userName = data["name"]).catchError((e) {
|
await ConnectionManager().sendSocketMessage(type: "auth/current_user").then((data) => _userName = data["name"]).catchError((e) {
|
||||||
Logger.w("Can't get user info: ${e}");
|
Logger.w("Can't get user info: $e");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _getServices() async {
|
Future _getServices() async {
|
||||||
await ConnectionManager().sendSocketMessage(type: "get_services").then((data) => Logger.d("Services received")).catchError((e) {
|
await ConnectionManager().sendSocketMessage(type: "get_services").then((data) => Logger.d("Services received")).catchError((e) {
|
||||||
Logger.w("Can't get services: ${e}");
|
Logger.w("Can't get services: $e");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -136,7 +136,7 @@ class HomeAssistant {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
}).catchError((e) {
|
}).catchError((e) {
|
||||||
throw HAError("Error getting panels list: $e");
|
throw UserError(code: ErrorCode.ERROR_GETTING_PANELS, message: "$e");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,6 +114,7 @@ part 'ui_widgets/card_widget.dart';
|
|||||||
part 'ui_widgets/card_header_widget.dart';
|
part 'ui_widgets/card_header_widget.dart';
|
||||||
part 'panels/config_panel_widget.dart';
|
part 'panels/config_panel_widget.dart';
|
||||||
part 'panels/widgets/link_to_web_config.dart';
|
part 'panels/widgets/link_to_web_config.dart';
|
||||||
|
part 'user_error_screen.widget.dart';
|
||||||
|
|
||||||
|
|
||||||
EventBus eventBus = new EventBus();
|
EventBus eventBus = new EventBus();
|
||||||
@ -217,8 +218,9 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
StreamSubscription _reloadUISubscription;
|
StreamSubscription _reloadUISubscription;
|
||||||
StreamSubscription _showPageSubscription;
|
StreamSubscription _showPageSubscription;
|
||||||
int _previousViewCount;
|
int _previousViewCount;
|
||||||
bool _showLoginButton = false;
|
//bool _showLoginButton = false;
|
||||||
bool _preventAppRefresh = false;
|
bool _preventAppRefresh = false;
|
||||||
|
UserError _userError;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@ -292,25 +294,29 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _fullLoad() async {
|
void _fullLoad() async {
|
||||||
|
setState(() {
|
||||||
|
_userError = null;
|
||||||
|
});
|
||||||
_showInfoBottomBar(progress: true,);
|
_showInfoBottomBar(progress: true,);
|
||||||
_subscribe().then((_) {
|
_subscribe().then((_) {
|
||||||
ConnectionManager().init(loadSettings: true, forceReconnect: true).then((__){
|
ConnectionManager().init(loadSettings: true, forceReconnect: true).then((__){
|
||||||
_fetchData();
|
_fetchData();
|
||||||
StartupUserMessagesManager().checkMessagesToShow();
|
}, onError: (code) {
|
||||||
}, onError: (e) {
|
_setErrorState(code);
|
||||||
_setErrorState(e);
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void _quickLoad() {
|
void _quickLoad() {
|
||||||
|
setState(() {
|
||||||
|
_userError = null;
|
||||||
|
});
|
||||||
_hideBottomBar();
|
_hideBottomBar();
|
||||||
_showInfoBottomBar(progress: true,);
|
_showInfoBottomBar(progress: true,);
|
||||||
ConnectionManager().init(loadSettings: false, forceReconnect: false).then((_){
|
ConnectionManager().init(loadSettings: false, forceReconnect: false).then((_){
|
||||||
_fetchData();
|
_fetchData();
|
||||||
StartupUserMessagesManager().checkMessagesToShow();
|
}, onError: (code) {
|
||||||
}, onError: (e) {
|
_setErrorState(code);
|
||||||
_setErrorState(e);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -323,12 +329,8 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
_viewsTabController = TabController(vsync: this, length: currentViewCount);
|
_viewsTabController = TabController(vsync: this, length: currentViewCount);
|
||||||
_previousViewCount = currentViewCount;
|
_previousViewCount = currentViewCount;
|
||||||
}
|
}
|
||||||
}).catchError((e) {
|
}).catchError((code) {
|
||||||
if (e is HAError) {
|
_setErrorState(code);
|
||||||
_setErrorState(e);
|
|
||||||
} else {
|
|
||||||
_setErrorState(HAError(e.toString()));
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
eventBus.fire(RefreshDataFinishedEvent());
|
eventBus.fire(RefreshDataFinishedEvent());
|
||||||
}
|
}
|
||||||
@ -371,6 +373,9 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
}
|
}
|
||||||
if (_reloadUISubscription == null) {
|
if (_reloadUISubscription == null) {
|
||||||
_reloadUISubscription = eventBus.on<ReloadUIEvent>().listen((event){
|
_reloadUISubscription = eventBus.on<ReloadUIEvent>().listen((event){
|
||||||
|
if (event.full)
|
||||||
|
_fullLoad();
|
||||||
|
else
|
||||||
_quickLoad();
|
_quickLoad();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -421,20 +426,20 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
|
|
||||||
if (_showErrorSubscription == null) {
|
if (_showErrorSubscription == null) {
|
||||||
_showErrorSubscription = eventBus.on<ShowErrorEvent>().listen((event){
|
_showErrorSubscription = eventBus.on<ShowErrorEvent>().listen((event){
|
||||||
_showErrorBottomBar(event.error);
|
_setErrorState(event.error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_startAuthSubscription == null) {
|
if (_startAuthSubscription == null) {
|
||||||
_startAuthSubscription = eventBus.on<StartAuthEvent>().listen((event){
|
_startAuthSubscription = eventBus.on<StartAuthEvent>().listen((event){
|
||||||
setState(() {
|
if (event.starting) {
|
||||||
_showLoginButton = event.showButton;
|
|
||||||
});
|
|
||||||
if (event.showButton) {
|
|
||||||
_showOAuth();
|
_showOAuth();
|
||||||
} else {
|
} else {
|
||||||
_preventAppRefresh = false;
|
_preventAppRefresh = false;
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
|
setState(() {
|
||||||
|
_userError = null;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -448,17 +453,27 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
|
|
||||||
void _showOAuth() {
|
void _showOAuth() {
|
||||||
_preventAppRefresh = true;
|
_preventAppRefresh = true;
|
||||||
|
_setErrorState(UserError(code: ErrorCode.NOT_LOGGED_IN));
|
||||||
Navigator.of(context).pushNamed('/login');
|
Navigator.of(context).pushNamed('/login');
|
||||||
}
|
}
|
||||||
|
|
||||||
_setErrorState(HAError e) {
|
_setErrorState(error) {
|
||||||
if (e == null) {
|
if (error is UserError) {
|
||||||
|
setState(() {
|
||||||
|
_userError = error;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
setState(() {
|
||||||
|
_userError = UserError(code: ErrorCode.UNKNOWN);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/*if (e == null) {
|
||||||
_showErrorBottomBar(
|
_showErrorBottomBar(
|
||||||
HAError("Unknown error")
|
HAError("Unknown error")
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
_showErrorBottomBar(e);
|
_showErrorBottomBar(e);
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showPopupDialog({String title, String body, var onPositive, var onNegative, String positiveText, String negativeText}) {
|
void _showPopupDialog({String title, String body, var onPositive, var onNegative, String positiveText, String negativeText}) {
|
||||||
@ -739,6 +754,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void _showErrorBottomBar(HAError error) {
|
void _showErrorBottomBar(HAError error) {
|
||||||
TextStyle textStyle = TextStyle(
|
TextStyle textStyle = TextStyle(
|
||||||
color: Colors.blue,
|
color: Colors.blue,
|
||||||
@ -803,7 +819,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
_bottomBarText = "${error.message}";
|
_bottomBarText = "${error.message}";
|
||||||
_showBottomBar = true;
|
_showBottomBar = true;
|
||||||
});
|
});
|
||||||
}
|
}*/
|
||||||
|
|
||||||
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
|
||||||
|
|
||||||
@ -814,18 +830,33 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
child: new Text("Reload"),
|
child: new Text("Reload"),
|
||||||
value: "reload",
|
value: "reload",
|
||||||
));
|
));
|
||||||
List<Widget> emptyBody = [
|
/*List<Widget> emptyBody = [
|
||||||
Text("."),
|
Text("."),
|
||||||
];
|
];*/
|
||||||
if (ConnectionManager().isAuthenticated) {
|
if (ConnectionManager().isAuthenticated) {
|
||||||
_showLoginButton = false;
|
//_showLoginButton = false;
|
||||||
popupMenuItems.add(
|
popupMenuItems.add(
|
||||||
PopupMenuItem<String>(
|
PopupMenuItem<String>(
|
||||||
child: new Text("Logout"),
|
child: new Text("Logout"),
|
||||||
value: "logout",
|
value: "logout",
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
if (_showLoginButton) {
|
Widget bodyWidget;
|
||||||
|
if (_userError != null) {
|
||||||
|
bodyWidget = UserErrorScreen(error: _userError);
|
||||||
|
} else if (empty) {
|
||||||
|
bodyWidget = Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
CircularProgressIndicator()
|
||||||
|
],
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
bodyWidget = HomeAssistant().buildViews(context, _viewsTabController);
|
||||||
|
}
|
||||||
|
/*if (_showLoginButton) {
|
||||||
emptyBody = [
|
emptyBody = [
|
||||||
FlatButton(
|
FlatButton(
|
||||||
child: Text("Login with Home Assistant", style: TextStyle(fontSize: 16.0, color: Colors.white)),
|
child: Text("Login with Home Assistant", style: TextStyle(fontSize: 16.0, color: Colors.white)),
|
||||||
@ -833,7 +864,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
onPressed: () => _fullLoad(),
|
onPressed: () => _fullLoad(),
|
||||||
)
|
)
|
||||||
];
|
];
|
||||||
}
|
}*/
|
||||||
return NestedScrollView(
|
return NestedScrollView(
|
||||||
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
|
headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
|
||||||
return <Widget>[
|
return <Widget>[
|
||||||
@ -869,7 +900,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
_scaffoldKey.currentState.openDrawer();
|
_scaffoldKey.currentState.openDrawer();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
bottom: empty ? null : TabBar(
|
bottom: (empty || _userError != null) ? null : TabBar(
|
||||||
controller: _viewsTabController,
|
controller: _viewsTabController,
|
||||||
tabs: buildUIViewTabs(),
|
tabs: buildUIViewTabs(),
|
||||||
isScrollable: true,
|
isScrollable: true,
|
||||||
@ -878,15 +909,7 @@ class _MainPageState extends State<MainPage> with WidgetsBindingObserver, Ticker
|
|||||||
|
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
body: empty ?
|
body: bodyWidget,
|
||||||
Center(
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: emptyBody
|
|
||||||
),
|
|
||||||
)
|
|
||||||
:
|
|
||||||
HomeAssistant().buildViews(context, _viewsTabController),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ class AuthManager {
|
|||||||
//flutterWebviewPlugin.close();
|
//flutterWebviewPlugin.close();
|
||||||
Logger.e("Error getting temp token: ${e.toString()}");
|
Logger.e("Error getting temp token: ${e.toString()}");
|
||||||
eventBus.fire(StartAuthEvent(oauthUrl, false));
|
eventBus.fire(StartAuthEvent(oauthUrl, false));
|
||||||
completer.completeError(HAError("Error getting temp token"));
|
completer.completeError(UserError(code: ErrorCode.AUTH_ERROR));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -40,6 +40,7 @@ class ConnectionManager {
|
|||||||
if (loadSettings) {
|
if (loadSettings) {
|
||||||
Logger.e("Loading settings...");
|
Logger.e("Loading settings...");
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.reload();
|
||||||
useLovelace = prefs.getBool('use-lovelace') ?? true;
|
useLovelace = prefs.getBool('use-lovelace') ?? true;
|
||||||
_domain = prefs.getString('hassio-domain');
|
_domain = prefs.getString('hassio-domain');
|
||||||
_port = prefs.getString('hassio-port');
|
_port = prefs.getString('hassio-port');
|
||||||
@ -51,14 +52,12 @@ class ConnectionManager {
|
|||||||
"${prefs.getString('hassio-res-protocol')}://$_domain:$_port";
|
"${prefs.getString('hassio-res-protocol')}://$_domain:$_port";
|
||||||
if ((_domain == null) || (_port == null) ||
|
if ((_domain == null) || (_port == null) ||
|
||||||
(_domain.isEmpty) || (_port.isEmpty)) {
|
(_domain.isEmpty) || (_port.isEmpty)) {
|
||||||
completer.completeError(HAError.checkConnectionSettings());
|
completer.completeError(UserError(code: ErrorCode.NOT_CONFIGURED));
|
||||||
stopInit = true;
|
stopInit = true;
|
||||||
} else {
|
} else {
|
||||||
//_token = prefs.getString('hassio-token');
|
|
||||||
final storage = new FlutterSecureStorage();
|
final storage = new FlutterSecureStorage();
|
||||||
try {
|
try {
|
||||||
_token = await storage.read(key: "hacl_llt");
|
_token = await storage.read(key: "hacl_llt");
|
||||||
Logger.e("Long-lived token read successful");
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Logger.e("Cannt read secure storage. Need to relogin.");
|
Logger.e("Cannt read secure storage. Need to relogin.");
|
||||||
_token = null;
|
_token = null;
|
||||||
@ -73,7 +72,7 @@ class ConnectionManager {
|
|||||||
} else {
|
} else {
|
||||||
if ((_domain == null) || (_port == null) ||
|
if ((_domain == null) || (_port == null) ||
|
||||||
(_domain.isEmpty) || (_port.isEmpty)) {
|
(_domain.isEmpty) || (_port.isEmpty)) {
|
||||||
completer.completeError(HAError.checkConnectionSettings());
|
completer.completeError(UserError(code: ErrorCode.NOT_CONFIGURED));
|
||||||
stopInit = true;
|
stopInit = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -101,7 +100,7 @@ class ConnectionManager {
|
|||||||
if (forceReconnect || !isConnected) {
|
if (forceReconnect || !isConnected) {
|
||||||
_connect().timeout(connectTimeout, onTimeout: () {
|
_connect().timeout(connectTimeout, onTimeout: () {
|
||||||
_disconnect().then((_) {
|
_disconnect().then((_) {
|
||||||
completer?.completeError(HAError("Connection timeout"));
|
completer?.completeError(UserError(code: ErrorCode.CONNECTION_TIMEOUT));
|
||||||
});
|
});
|
||||||
}).then((_) {
|
}).then((_) {
|
||||||
completer?.complete();
|
completer?.complete();
|
||||||
@ -146,10 +145,11 @@ class ConnectionManager {
|
|||||||
}
|
}
|
||||||
} else if (data["type"] == "auth_invalid") {
|
} else if (data["type"] == "auth_invalid") {
|
||||||
Logger.d("[Received] <== ${data.toString()}");
|
Logger.d("[Received] <== ${data.toString()}");
|
||||||
_messageResolver["auth"]?.completeError(HAError("${data["message"]}", actions: [HAErrorAction.loginAgain()]));
|
_messageResolver["auth"]?.completeError(UserError(code: ErrorCode.AUTH_INVALID, message: "${data["message"]}"));
|
||||||
_messageResolver.remove("auth");
|
_messageResolver.remove("auth");
|
||||||
|
//TODO dont logout, show variants to User
|
||||||
logout().then((_) {
|
logout().then((_) {
|
||||||
if (!connecting.isCompleted) connecting.completeError(HAError("${data["message"]}", actions: [HAErrorAction.loginAgain()]));
|
if (!connecting.isCompleted) connecting.completeError(UserError(code: ErrorCode.AUTH_INVALID, message: "${data["message"]}"));
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
_handleMessage(data);
|
_handleMessage(data);
|
||||||
@ -214,14 +214,14 @@ class ConnectionManager {
|
|||||||
Logger.d("Socket disconnected.");
|
Logger.d("Socket disconnected.");
|
||||||
if (!connectionCompleter.isCompleted) {
|
if (!connectionCompleter.isCompleted) {
|
||||||
isConnected = false;
|
isConnected = false;
|
||||||
connectionCompleter.completeError(HAError("Disconnected", actions: [HAErrorAction.reconnect()]));
|
connectionCompleter.completeError(UserError(code: ErrorCode.DISCONNECTED));
|
||||||
} else {
|
} else {
|
||||||
_disconnect().then((_) {
|
_disconnect().then((_) {
|
||||||
Timer(Duration(seconds: 5), () {
|
Timer(Duration(seconds: 5), () {
|
||||||
Logger.d("Trying to reconnect...");
|
Logger.d("Trying to reconnect...");
|
||||||
_connect().catchError((e) {
|
_connect().catchError((e) {
|
||||||
isConnected = false;
|
isConnected = false;
|
||||||
eventBus.fire(ShowErrorEvent(HAError("Unable to connect to Home Assistant")));
|
eventBus.fire(UserError(code: ErrorCode.UNABLE_TO_CONNECT));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -232,14 +232,14 @@ class ConnectionManager {
|
|||||||
Logger.e("Socket stream Error: $e");
|
Logger.e("Socket stream Error: $e");
|
||||||
if (!connectionCompleter.isCompleted) {
|
if (!connectionCompleter.isCompleted) {
|
||||||
isConnected = false;
|
isConnected = false;
|
||||||
connectionCompleter.completeError(HAError("Unable to connect to Home Assistant"));
|
connectionCompleter.completeError(UserError(code: ErrorCode.UNABLE_TO_CONNECT));
|
||||||
} else {
|
} else {
|
||||||
_disconnect().then((_) {
|
_disconnect().then((_) {
|
||||||
Timer(Duration(seconds: 5), () {
|
Timer(Duration(seconds: 5), () {
|
||||||
Logger.d("Trying to reconnect...");
|
Logger.d("Trying to reconnect...");
|
||||||
_connect().catchError((e) {
|
_connect().catchError((e) {
|
||||||
isConnected = false;
|
isConnected = false;
|
||||||
eventBus.fire(ShowErrorEvent(HAError("Unable to connect to Home Assistant")));
|
eventBus.fire(ShowErrorEvent(UserError(code: ErrorCode.UNABLE_TO_CONNECT)));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -275,7 +275,7 @@ class ConnectionManager {
|
|||||||
});
|
});
|
||||||
}).catchError((e) => completer.completeError(e));
|
}).catchError((e) => completer.completeError(e));
|
||||||
} else {
|
} else {
|
||||||
completer.completeError(HAError("General login error"));
|
completer.completeError(UserError(code: ErrorCode.GENERAL_AUTH_ERROR));
|
||||||
}
|
}
|
||||||
return completer.future;
|
return completer.future;
|
||||||
}
|
}
|
||||||
@ -309,8 +309,9 @@ class ConnectionManager {
|
|||||||
throw e;
|
throw e;
|
||||||
});
|
});
|
||||||
}).catchError((e) {
|
}).catchError((e) {
|
||||||
|
//TODO dont logout, show variants
|
||||||
logout();
|
logout();
|
||||||
completer.completeError(HAError("Authentication error: $e", actions: [HAErrorAction.loginAgain()]));
|
completer.completeError(UserError(code: ErrorCode.AUTH_ERROR, message: "$e"));
|
||||||
});
|
});
|
||||||
return completer.future;
|
return completer.future;
|
||||||
}
|
}
|
||||||
@ -333,7 +334,7 @@ class ConnectionManager {
|
|||||||
String rawMessage = json.encode(dataObject);
|
String rawMessage = json.encode(dataObject);
|
||||||
if (!isConnected) {
|
if (!isConnected) {
|
||||||
_connect().timeout(connectTimeout, onTimeout: (){
|
_connect().timeout(connectTimeout, onTimeout: (){
|
||||||
_completer.completeError(HAError("No connection to Home Assistant", actions: [HAErrorAction.reconnect()]));
|
_completer.completeError(UserError(code: ErrorCode.UNABLE_TO_CONNECT));
|
||||||
}).then((_) {
|
}).then((_) {
|
||||||
Logger.d("[Sending] ==> ${auth ? "type="+dataObject['type'] : rawMessage}");
|
Logger.d("[Sending] ==> ${auth ? "type="+dataObject['type'] : rawMessage}");
|
||||||
_socket.sink.add(rawMessage);
|
_socket.sink.add(rawMessage);
|
||||||
|
214
lib/user_error_screen.widget.dart
Normal file
214
lib/user_error_screen.widget.dart
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
part of 'main.dart';
|
||||||
|
|
||||||
|
class UserErrorScreen extends StatelessWidget {
|
||||||
|
|
||||||
|
final UserError error;
|
||||||
|
|
||||||
|
const UserErrorScreen({Key key, this.error}) : super(key: key);
|
||||||
|
|
||||||
|
void _goToAppSettings(BuildContext context) {
|
||||||
|
Navigator.pushNamed(context, '/connection-settings');
|
||||||
|
}
|
||||||
|
|
||||||
|
void _reload() {
|
||||||
|
eventBus.fire(ReloadUIEvent(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _disableLovelace() {
|
||||||
|
SharedPreferences.getInstance().then((prefs){
|
||||||
|
prefs.setBool("use-lovelace", false);
|
||||||
|
eventBus.fire(ReloadUIEvent(true));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _reLogin() {
|
||||||
|
ConnectionManager().logout().then((_) => eventBus.fire(ReloadUIEvent(true)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
String errorText;
|
||||||
|
List<Widget> buttons = [];
|
||||||
|
switch (this.error.code) {
|
||||||
|
case ErrorCode.AUTH_ERROR: {
|
||||||
|
errorText = "There was an error logging in to Home Assistant";
|
||||||
|
buttons.add(RaisedButton(
|
||||||
|
onPressed: () => _reload(),
|
||||||
|
child: Text("Retry"),
|
||||||
|
));
|
||||||
|
buttons.add(RaisedButton(
|
||||||
|
onPressed: () => _reLogin(),
|
||||||
|
child: Text("Login again"),
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorCode.UNABLE_TO_CONNECT: {
|
||||||
|
errorText = "Unable to connect to Home Assistant";
|
||||||
|
buttons.addAll(<Widget>[
|
||||||
|
RaisedButton(
|
||||||
|
onPressed: () => _reload(),
|
||||||
|
child: Text("Retry")
|
||||||
|
),
|
||||||
|
Container(width: 15.0,),
|
||||||
|
RaisedButton(
|
||||||
|
onPressed: () => _goToAppSettings(context),
|
||||||
|
child: Text("Check application settings"),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorCode.AUTH_INVALID: {
|
||||||
|
errorText = "${error.message ?? "Can't login to Home Assistant"}";
|
||||||
|
buttons.addAll(<Widget>[
|
||||||
|
RaisedButton(
|
||||||
|
onPressed: () => _reload(),
|
||||||
|
child: Text("Retry")
|
||||||
|
),
|
||||||
|
Container(width: 15.0,),
|
||||||
|
RaisedButton(
|
||||||
|
onPressed: () => _reLogin(),
|
||||||
|
child: Text("Login again"),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorCode.GENERAL_AUTH_ERROR: {
|
||||||
|
buttons.addAll(<Widget>[
|
||||||
|
RaisedButton(
|
||||||
|
onPressed: () => _reload(),
|
||||||
|
child: Text("Retry")
|
||||||
|
),
|
||||||
|
Container(width: 15.0,),
|
||||||
|
RaisedButton(
|
||||||
|
onPressed: () => _reLogin(),
|
||||||
|
child: Text("Login again"),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorCode.DISCONNECTED: {
|
||||||
|
errorText = "Disconnected";
|
||||||
|
buttons.addAll(<Widget>[
|
||||||
|
RaisedButton(
|
||||||
|
onPressed: () => _reload(),
|
||||||
|
child: Text("Reconnect")
|
||||||
|
),
|
||||||
|
Container(width: 15.0,),
|
||||||
|
RaisedButton(
|
||||||
|
onPressed: () => _goToAppSettings(context),
|
||||||
|
child: Text("Check application settings"),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorCode.CONNECTION_TIMEOUT: {
|
||||||
|
errorText = "Connection timeout";
|
||||||
|
buttons.addAll(<Widget>[
|
||||||
|
RaisedButton(
|
||||||
|
onPressed: () => _reload(),
|
||||||
|
child: Text("Reconnect")
|
||||||
|
),
|
||||||
|
Container(width: 15.0,),
|
||||||
|
RaisedButton(
|
||||||
|
onPressed: () => _goToAppSettings(context),
|
||||||
|
child: Text("Check application settings"),
|
||||||
|
)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorCode.NOT_CONFIGURED: {
|
||||||
|
errorText = "Looks like HA Client is not configured yet.";
|
||||||
|
buttons.add(RaisedButton(
|
||||||
|
onPressed: () => _goToAppSettings(context),
|
||||||
|
child: Text("Open application settings"),
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorCode.ERROR_GETTING_PANELS:
|
||||||
|
case ErrorCode.ERROR_GETTING_CONFIG:
|
||||||
|
case ErrorCode.ERROR_GETTING_STATES: {
|
||||||
|
errorText = "Couldn't get data from Home Assistant. ${error.message ?? ""}";
|
||||||
|
buttons.add(RaisedButton(
|
||||||
|
onPressed: () => _reload(),
|
||||||
|
child: Text("Try again"),
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorCode.ERROR_GETTING_LOVELACE_CONFIG: {
|
||||||
|
errorText = "Couldn't get Lovelace UI config. You can try to disable it and use group-based UI istead.";
|
||||||
|
buttons.addAll(<Widget>[
|
||||||
|
RaisedButton(
|
||||||
|
onPressed: () => _reload(),
|
||||||
|
child: Text("Retry"),
|
||||||
|
),
|
||||||
|
Container(width: 15.0,),
|
||||||
|
RaisedButton(
|
||||||
|
onPressed: () => _disableLovelace(),
|
||||||
|
child: Text("Disable Lovelace UI"),
|
||||||
|
)
|
||||||
|
]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ErrorCode.NOT_LOGGED_IN: {
|
||||||
|
errorText = "You are not logged in yet. Please login.";
|
||||||
|
buttons.add(RaisedButton(
|
||||||
|
onPressed: () => _reload(),
|
||||||
|
child: Text("Login"),
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
errorText = "???";
|
||||||
|
buttons.add(RaisedButton(
|
||||||
|
onPressed: () => _reload(),
|
||||||
|
child: Text("Reload"),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.only(left: Sizes.leftWidgetPadding, right: Sizes.rightWidgetPadding),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Flexible(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 100.0, bottom: 20.0),
|
||||||
|
child: Icon(
|
||||||
|
Icons.error,
|
||||||
|
color: Colors.redAccent,
|
||||||
|
size: 48.0
|
||||||
|
)
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
errorText,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(color: Colors.black45, fontSize: Sizes.largeFontSize),
|
||||||
|
softWrap: true,
|
||||||
|
maxLines: 5,
|
||||||
|
),
|
||||||
|
Container(height: Sizes.rowPadding,),
|
||||||
|
Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: buttons.isNotEmpty ? buttons : Container(height: 0.0, width: 0.0,),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -45,7 +45,7 @@ class Logger {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class HAError {
|
/*class HAError {
|
||||||
String message;
|
String message;
|
||||||
final List<HAErrorAction> actions;
|
final List<HAErrorAction> actions;
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ class HAErrorActionType {
|
|||||||
static const LOGOUT = 2;
|
static const LOGOUT = 2;
|
||||||
static const URL = 3;
|
static const URL = 3;
|
||||||
static const OPEN_CONNECTION_SETTINGS = 4;
|
static const OPEN_CONNECTION_SETTINGS = 4;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
class StateChangedEvent {
|
class StateChangedEvent {
|
||||||
String entityId;
|
String entityId;
|
||||||
@ -112,14 +112,16 @@ class RefreshDataFinishedEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ReloadUIEvent {
|
class ReloadUIEvent {
|
||||||
ReloadUIEvent();
|
final bool full;
|
||||||
|
|
||||||
|
ReloadUIEvent(this.full);
|
||||||
}
|
}
|
||||||
|
|
||||||
class StartAuthEvent {
|
class StartAuthEvent {
|
||||||
String oauthUrl;
|
String oauthUrl;
|
||||||
bool showButton;
|
bool starting;
|
||||||
|
|
||||||
StartAuthEvent(this.oauthUrl, this.showButton);
|
StartAuthEvent(this.oauthUrl, this.starting);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ServiceCallEvent {
|
class ServiceCallEvent {
|
||||||
@ -165,7 +167,7 @@ class ShowPageEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class ShowErrorEvent {
|
class ShowErrorEvent {
|
||||||
final HAError error;
|
final UserError error;
|
||||||
|
|
||||||
ShowErrorEvent(this.error);
|
ShowErrorEvent(this.error);
|
||||||
}
|
}
|
Reference in New Issue
Block a user