WIP: App settings refactoring

This commit is contained in:
Yegor Vialov 2020-05-13 12:46:25 +00:00
parent a20dfaf05e
commit 5683ab5158
18 changed files with 129 additions and 106 deletions

View File

@ -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(

View File

@ -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');

View File

@ -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);
} }

View File

@ -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
}; };

View File

@ -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),

View File

@ -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;
} }

View File

@ -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,

View File

@ -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;

View File

@ -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 {

View File

@ -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>(

View File

@ -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(

View File

@ -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') ?? '';

View File

@ -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);
} }

View File

@ -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);
} }

View File

@ -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"),
], ],
); );
} }

View File

@ -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}");
} }
} }

View File

@ -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();
}); });

View File

@ -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));
}); });
} }
}); });