Compare commits
15 Commits
beta/0.7.5
...
beta/0.7.6
Author | SHA1 | Date | |
---|---|---|---|
8b4df98cb9 | |||
7d30c2f9d5 | |||
44acabadfe | |||
6f3a2bb78d | |||
dd5f8b155d | |||
cd81fc72fd | |||
890da650dc | |||
9897b6a44b | |||
7969f54d3b | |||
7c18454de3 | |||
dcf5efddd1 | |||
a6541134e0 | |||
90504047b4 | |||
ca1eec6602 | |||
edc01d14b7 |
31
.github/ISSUE_TEMPLATE/bug_report.md
vendored
31
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -7,35 +7,16 @@ assignees: ''
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<!--
|
**HA Client version:** [Main menu -> About HA Client]
|
||||||
Please provide as much information as possible.
|
|
||||||
-->
|
|
||||||
**HA Client version:** <!-- Main app menu => About HA Client -->
|
|
||||||
|
|
||||||
**Home Assistant version:** <!-- 0.94.1 for example -->
|
**Home Assistant version:**
|
||||||
|
|
||||||
**Device name:** <!-- Pixel 2 for example -->
|
**Device name:**
|
||||||
|
|
||||||
**Android version:** <!-- 8.1 for example -->
|
**Android version:**
|
||||||
|
|
||||||
**Connection type:** <!-- For example "Local IP" or "Remote UI" or "Own domain"-->
|
|
||||||
|
|
||||||
**Login type:** <!-- For example "HA Login" or "Manual token"-->
|
|
||||||
|
|
||||||
**Description**
|
**Description**
|
||||||
<!--
|
[Replace with description]
|
||||||
Describe your issue here
|
|
||||||
-->
|
|
||||||
|
|
||||||
**Screenshots**
|
**Screenshots**
|
||||||
<!--
|
[Replace with screenshots]
|
||||||
Please provide screenshots if it is a UI issue. Also you can attach screenshot from Home Assistant web UI as an expected result
|
|
||||||
-->
|
|
||||||
|
|
||||||
**Logs**
|
|
||||||
<!--
|
|
||||||
Right after issue reproduced go to app menu and tap "Log". Copy log with a "Copy" button in the upper-right corner and post it below
|
|
||||||
-->
|
|
||||||
```
|
|
||||||
[Replace this text with your logs]
|
|
||||||
```
|
|
||||||
|
@ -285,7 +285,9 @@ class CardWidget extends StatelessWidget {
|
|||||||
return Card(
|
return Card(
|
||||||
child: EntityModel(
|
child: EntityModel(
|
||||||
entityWrapper: card.linkedEntityWrapper,
|
entityWrapper: card.linkedEntityWrapper,
|
||||||
child: EntityButtonCardBody(),
|
child: EntityButtonCardBody(
|
||||||
|
showName: card.showName,
|
||||||
|
),
|
||||||
handleTap: true
|
handleTap: true
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -2,8 +2,10 @@ part of '../../main.dart';
|
|||||||
|
|
||||||
class EntityButtonCardBody extends StatelessWidget {
|
class EntityButtonCardBody extends StatelessWidget {
|
||||||
|
|
||||||
|
final bool showName;
|
||||||
|
|
||||||
EntityButtonCardBody({
|
EntityButtonCardBody({
|
||||||
Key key,
|
Key key, this.showName: true,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -39,13 +41,16 @@ class EntityButtonCardBody extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildName() {
|
Widget _buildName() {
|
||||||
return EntityName(
|
if (showName) {
|
||||||
padding: EdgeInsets.fromLTRB(Sizes.buttonPadding, 0.0, Sizes.buttonPadding, Sizes.rowPadding),
|
return EntityName(
|
||||||
textOverflow: TextOverflow.ellipsis,
|
padding: EdgeInsets.fromLTRB(Sizes.buttonPadding, 0.0, Sizes.buttonPadding, Sizes.rowPadding),
|
||||||
maxLines: 3,
|
textOverflow: TextOverflow.ellipsis,
|
||||||
wordsWrap: true,
|
maxLines: 3,
|
||||||
textAlign: TextAlign.center,
|
wordsWrap: true,
|
||||||
fontSize: Sizes.nameFontSize,
|
textAlign: TextAlign.center,
|
||||||
);
|
fontSize: Sizes.nameFontSize,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Container(width: 0, height: 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -58,7 +58,7 @@ class EntityWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case EntityUIAction.navigate: {
|
case EntityUIAction.navigate: {
|
||||||
if (uiAction.tapService.startsWith("/")) {
|
if (uiAction.tapService != null && uiAction.tapService.startsWith("/")) {
|
||||||
//TODO handle local urls
|
//TODO handle local urls
|
||||||
Logger.w("Local urls is not supported yet");
|
Logger.w("Local urls is not supported yet");
|
||||||
} else {
|
} else {
|
||||||
@ -98,7 +98,7 @@ class EntityWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case EntityUIAction.navigate: {
|
case EntityUIAction.navigate: {
|
||||||
if (uiAction.holdService.startsWith("/")) {
|
if (uiAction.holdService != null && uiAction.holdService.startsWith("/")) {
|
||||||
//TODO handle local urls
|
//TODO handle local urls
|
||||||
Logger.w("Local urls is not supported yet");
|
Logger.w("Local urls is not supported yet");
|
||||||
} else {
|
} else {
|
||||||
|
@ -84,25 +84,22 @@ class MediaPlayerEntity extends Entity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool canCalculateActualPosition() {
|
bool canCalculateActualPosition() {
|
||||||
return positionLastUpdated != null && durationSeconds != null && positionSeconds != null && durationSeconds >= 0;
|
return positionLastUpdated != null && durationSeconds != null && positionSeconds != null && durationSeconds > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
double getActualPosition() {
|
double getActualPosition() {
|
||||||
double result = 0;
|
double result = 0;
|
||||||
if (canCalculateActualPosition()) {
|
Duration durationD;
|
||||||
Duration durationD;
|
Duration positionD;
|
||||||
Duration positionD;
|
durationD = Duration(seconds: durationSeconds);
|
||||||
durationD = Duration(seconds: durationSeconds);
|
positionD = Duration(
|
||||||
positionD = Duration(
|
|
||||||
seconds: positionSeconds);
|
seconds: positionSeconds);
|
||||||
result = positionD.inSeconds.toDouble();
|
result = positionD.inSeconds.toDouble();
|
||||||
int differenceInSeconds = DateTime
|
int differenceInSeconds = DateTime
|
||||||
.now()
|
.now()
|
||||||
.difference(positionLastUpdated)
|
.difference(positionLastUpdated)
|
||||||
.inSeconds;
|
.inSeconds;
|
||||||
result = ((result + differenceInSeconds) <= durationD.inSeconds) ? (result + differenceInSeconds) : durationD.inSeconds.toDouble();
|
result = ((result + differenceInSeconds) <= durationD.inSeconds) ? (result + differenceInSeconds) : durationD.inSeconds.toDouble();
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,13 +22,13 @@ class _MediaPlayerProgressBarState extends State<MediaPlayerProgressBar> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final EntityModel entityModel = EntityModel.of(context);
|
final EntityModel entityModel = EntityModel.of(context);
|
||||||
final MediaPlayerEntity entity = entityModel.entityWrapper.entity;
|
final MediaPlayerEntity entity = entityModel.entityWrapper.entity;
|
||||||
double progress;
|
double progress = 0;
|
||||||
int currentPosition;
|
int currentPosition;
|
||||||
if (entity.canCalculateActualPosition()) {
|
if (entity.canCalculateActualPosition()) {
|
||||||
currentPosition = entity.getActualPosition().toInt();
|
currentPosition = entity.getActualPosition().toInt();
|
||||||
progress = (currentPosition <= entity.durationSeconds) ? currentPosition / entity.durationSeconds : 100;
|
if (currentPosition > 0) {
|
||||||
} else {
|
progress = (currentPosition <= entity.durationSeconds) ? currentPosition / entity.durationSeconds : 100;
|
||||||
progress = 0;
|
}
|
||||||
}
|
}
|
||||||
return LinearProgressIndicator(
|
return LinearProgressIndicator(
|
||||||
value: progress,
|
value: progress,
|
||||||
|
@ -460,7 +460,11 @@ class _MediaPlayerControlsState extends State<MediaPlayerControls> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _duplicateTo(entity) {
|
void _duplicateTo(entity) {
|
||||||
HomeAssistant().savedPlayerPosition = entity.getActualPosition().toInt();
|
if (entity.canCalculateActualPosition()) {
|
||||||
|
HomeAssistant().savedPlayerPosition = entity.getActualPosition().toInt();
|
||||||
|
} else {
|
||||||
|
HomeAssistant().savedPlayerPosition = 0;
|
||||||
|
}
|
||||||
Navigator.of(context).pushNamed("/play-media", arguments: {
|
Navigator.of(context).pushNamed("/play-media", arguments: {
|
||||||
"url": entity.attributes["media_content_id"],
|
"url": entity.attributes["media_content_id"],
|
||||||
"type": entity.attributes["media_content_type"]
|
"type": entity.attributes["media_content_type"]
|
||||||
|
@ -223,9 +223,9 @@ class HomeAssistant {
|
|||||||
name: rawCardInfo["title"] ?? rawCardInfo["name"],
|
name: rawCardInfo["title"] ?? rawCardInfo["name"],
|
||||||
type: rawCardInfo['type'] ?? CardType.ENTITIES,
|
type: rawCardInfo['type'] ?? CardType.ENTITIES,
|
||||||
columnsCount: rawCardInfo['columns'] ?? 4,
|
columnsCount: rawCardInfo['columns'] ?? 4,
|
||||||
showName: rawCardInfo['show_name'] ?? true,
|
showName: (rawCardInfo['show_name'] ?? rawCard['show_name']) ?? true,
|
||||||
showState: rawCardInfo['show_state'] ?? true,
|
showState: (rawCardInfo['show_state'] ?? rawCard['show_state']) ?? true,
|
||||||
showEmpty: rawCardInfo['show_empty'] ?? true,
|
showEmpty: (rawCardInfo['show_empty'] ?? rawCard['show_empty']) ?? true,
|
||||||
stateFilter: (rawCard['state_filter'] ?? rawCardInfo['state_filter']) ?? [],
|
stateFilter: (rawCard['state_filter'] ?? rawCardInfo['state_filter']) ?? [],
|
||||||
states: rawCardInfo['states'],
|
states: rawCardInfo['states'],
|
||||||
conditions: rawCard['conditions'] ?? [],
|
conditions: rawCard['conditions'] ?? [],
|
||||||
|
@ -143,7 +143,7 @@ final SentryClient _sentry = SentryClient(dsn: "https://03ef364745cc4c23a60ddbc8
|
|||||||
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
|
final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
|
||||||
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = new FlutterLocalNotificationsPlugin();
|
FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = new FlutterLocalNotificationsPlugin();
|
||||||
const String appName = "HA Client";
|
const String appName = "HA Client";
|
||||||
const appVersionNumber = "0.7.5";
|
const appVersionNumber = "0.7.6";
|
||||||
const appVersionAdd = "";
|
const appVersionAdd = "";
|
||||||
const appVersion = "$appVersionNumber$appVersionAdd";
|
const appVersion = "$appVersionNumber$appVersionAdd";
|
||||||
|
|
||||||
@ -176,12 +176,7 @@ void main() async {
|
|||||||
};
|
};
|
||||||
|
|
||||||
runZoned(() {
|
runZoned(() {
|
||||||
workManager.Workmanager.initialize(
|
|
||||||
updateDeviceLocationIsolate,
|
|
||||||
isInDebugMode: false
|
|
||||||
);
|
|
||||||
runApp(new HAClientApp());
|
runApp(new HAClientApp());
|
||||||
|
|
||||||
}, onError: (error, stack) {
|
}, onError: (error, stack) {
|
||||||
_reportError(error, stack);
|
_reportError(error, stack);
|
||||||
});
|
});
|
||||||
|
@ -98,16 +98,23 @@ class ConnectionManager {
|
|||||||
|
|
||||||
void _doConnect({Completer completer, bool forceReconnect}) {
|
void _doConnect({Completer completer, bool forceReconnect}) {
|
||||||
if (forceReconnect || !isConnected) {
|
if (forceReconnect || !isConnected) {
|
||||||
_connect().timeout(connectTimeout, onTimeout: () {
|
_disconnect().then((_){
|
||||||
_disconnect().then((_) {
|
_connect().timeout(connectTimeout).then((_) {
|
||||||
if (completer != null && !completer.isCompleted) {
|
completer?.complete();
|
||||||
completer.completeError(HAError("Connection timeout"));
|
}).catchError((e) {
|
||||||
}
|
_disconnect().then((_) {
|
||||||
|
if (e is TimeoutException) {
|
||||||
|
if (connecting != null && !connecting.isCompleted) {
|
||||||
|
connecting.completeError(HAError("Connection timeout"));
|
||||||
|
}
|
||||||
|
completer?.completeError(HAError("Connection timeout"));
|
||||||
|
} else if (e is HAError) {
|
||||||
|
completer?.completeError(e);
|
||||||
|
} else {
|
||||||
|
completer?.completeError(HAError("${e.toString()}"));
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}).then((_) {
|
|
||||||
completer?.complete();
|
|
||||||
}).catchError((e) {
|
|
||||||
completer?.completeError(e);
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
completer?.complete();
|
completer?.complete();
|
||||||
@ -124,40 +131,44 @@ class ConnectionManager {
|
|||||||
connecting = Completer();
|
connecting = Completer();
|
||||||
_disconnect().then((_) {
|
_disconnect().then((_) {
|
||||||
Logger.d("Socket connecting...");
|
Logger.d("Socket connecting...");
|
||||||
_socket = IOWebSocketChannel.connect(
|
try {
|
||||||
|
_socket = IOWebSocketChannel.connect(
|
||||||
_webSocketAPIEndpoint, pingInterval: Duration(seconds: 15));
|
_webSocketAPIEndpoint, pingInterval: Duration(seconds: 15));
|
||||||
_socketSubscription = _socket.stream.listen(
|
_socketSubscription = _socket.stream.listen(
|
||||||
(message) {
|
(message) {
|
||||||
isConnected = true;
|
isConnected = true;
|
||||||
var data = json.decode(message);
|
var data = json.decode(message);
|
||||||
if (data["type"] == "auth_required") {
|
if (data["type"] == "auth_required") {
|
||||||
Logger.d("[Received] <== ${data.toString()}");
|
Logger.d("[Received] <== ${data.toString()}");
|
||||||
_authenticate().then((_) {
|
_authenticate().then((_) {
|
||||||
Logger.d('Authentication complete');
|
Logger.d('Authentication complete');
|
||||||
connecting.complete();
|
connecting.complete();
|
||||||
}).catchError((e) {
|
}).catchError((e) {
|
||||||
if (!connecting.isCompleted) connecting.completeError(e);
|
if (!connecting.isCompleted) connecting.completeError(e);
|
||||||
});
|
});
|
||||||
} else if (data["type"] == "auth_ok") {
|
} else if (data["type"] == "auth_ok") {
|
||||||
Logger.d("[Received] <== ${data.toString()}");
|
Logger.d("[Received] <== ${data.toString()}");
|
||||||
_messageResolver["auth"]?.complete();
|
_messageResolver["auth"]?.complete();
|
||||||
_messageResolver.remove("auth");
|
_messageResolver.remove("auth");
|
||||||
if (_token != null) {
|
if (_token != null) {
|
||||||
if (!connecting.isCompleted) connecting.complete();
|
if (!connecting.isCompleted) connecting.complete();
|
||||||
|
}
|
||||||
|
} else if (data["type"] == "auth_invalid") {
|
||||||
|
Logger.d("[Received] <== ${data.toString()}");
|
||||||
|
_messageResolver["auth"]?.completeError(HAError("${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")]));
|
||||||
|
} else {
|
||||||
|
_handleMessage(data);
|
||||||
}
|
}
|
||||||
} else if (data["type"] == "auth_invalid") {
|
},
|
||||||
Logger.d("[Received] <== ${data.toString()}");
|
cancelOnError: true,
|
||||||
_messageResolver["auth"]?.completeError(HAError("${data["message"]}", actions: [HAErrorAction.loginAgain()]));
|
onDone: () => _handleSocketClose(connecting),
|
||||||
_messageResolver.remove("auth");
|
onError: (e) => _handleSocketError(e, connecting)
|
||||||
if (!connecting.isCompleted) connecting.completeError(HAError("${data["message"]}", actions: [HAErrorAction.tryAgain(title: "Retry"), HAErrorAction.loginAgain(title: "Relogin")]));
|
);
|
||||||
} else {
|
} catch(exeption) {
|
||||||
_handleMessage(data);
|
connecting.completeError(HAError("${exeption.toString()}"));
|
||||||
}
|
}
|
||||||
},
|
|
||||||
cancelOnError: true,
|
|
||||||
onDone: () => _handleSocketClose(connecting),
|
|
||||||
onError: (e) => _handleSocketError(e, connecting)
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
return connecting.future;
|
return connecting.future;
|
||||||
}
|
}
|
||||||
@ -209,38 +220,24 @@ class ConnectionManager {
|
|||||||
|
|
||||||
void _handleSocketClose(Completer connectionCompleter) {
|
void _handleSocketClose(Completer connectionCompleter) {
|
||||||
Logger.d("Socket disconnected.");
|
Logger.d("Socket disconnected.");
|
||||||
if (!connectionCompleter.isCompleted) {
|
_disconnect().then((_) {
|
||||||
isConnected = false;
|
if (!connectionCompleter.isCompleted) {
|
||||||
connectionCompleter.completeError(HAError("Disconnected", actions: [HAErrorAction.reconnect()]));
|
isConnected = false;
|
||||||
} else {
|
connectionCompleter.completeError(HAError("Disconnected", actions: [HAErrorAction.reconnect()]));
|
||||||
_disconnect().then((_) {
|
}
|
||||||
Timer(Duration(seconds: 5), () {
|
eventBus.fire(ShowErrorEvent(HAError("Unable to connect to Home Assistant")));
|
||||||
Logger.d("Trying to reconnect...");
|
});
|
||||||
_connect().catchError((e) {
|
|
||||||
isConnected = false;
|
|
||||||
eventBus.fire(ShowErrorEvent(HAError("Unable to connect to Home Assistant")));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleSocketError(e, Completer connectionCompleter) {
|
void _handleSocketError(e, Completer connectionCompleter) {
|
||||||
Logger.e("Socket stream Error: $e");
|
Logger.e("Socket stream Error: $e");
|
||||||
if (!connectionCompleter.isCompleted) {
|
_disconnect().then((_) {
|
||||||
isConnected = false;
|
if (!connectionCompleter.isCompleted) {
|
||||||
connectionCompleter.completeError(HAError("Unable to connect to Home Assistant"));
|
isConnected = false;
|
||||||
} else {
|
connectionCompleter.completeError(HAError("Disconnected", actions: [HAErrorAction.reconnect()]));
|
||||||
_disconnect().then((_) {
|
}
|
||||||
Timer(Duration(seconds: 5), () {
|
eventBus.fire(ShowErrorEvent(HAError("Unable to connect to Home Assistant")));
|
||||||
Logger.d("Trying to reconnect...");
|
});
|
||||||
_connect().catchError((e) {
|
|
||||||
isConnected = false;
|
|
||||||
eventBus.fire(ShowErrorEvent(HAError("Unable to connect to Home Assistant")));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future _authenticate() {
|
Future _authenticate() {
|
||||||
@ -329,13 +326,13 @@ class ConnectionManager {
|
|||||||
_messageResolver[callbackName] = _completer;
|
_messageResolver[callbackName] = _completer;
|
||||||
String rawMessage = json.encode(dataObject);
|
String rawMessage = json.encode(dataObject);
|
||||||
if (!isConnected) {
|
if (!isConnected) {
|
||||||
_connect().timeout(connectTimeout, onTimeout: (){
|
_connect().timeout(connectTimeout).then((_) {
|
||||||
_completer.completeError(HAError("No connection to Home Assistant", actions: [HAErrorAction.reconnect()]));
|
|
||||||
}).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);
|
||||||
}).catchError((e) {
|
}).catchError((e) {
|
||||||
_completer.completeError(e);
|
if (!_completer.isCompleted) {
|
||||||
|
_completer.completeError(HAError("No connection to Home Assistant", actions: [HAErrorAction.reconnect()]));
|
||||||
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
Logger.d("[Sending] ==> ${auth ? "type="+dataObject['type'] : rawMessage}");
|
Logger.d("[Sending] ==> ${auth ? "type="+dataObject['type'] : rawMessage}");
|
||||||
@ -363,12 +360,12 @@ class ConnectionManager {
|
|||||||
sendHTTPPost(
|
sendHTTPPost(
|
||||||
endPoint: "/api/services/$domain/$service",
|
endPoint: "/api/services/$domain/$service",
|
||||||
data: json.encode(serviceData)
|
data: json.encode(serviceData)
|
||||||
).then((data) => completer.complete(data)).catchError((e) => completer.completeError(HAError("${e["message"]}")));
|
).then((data) => completer.complete(data)).catchError((e) => completer.completeError(HAError(e.toString())));
|
||||||
//return sendSocketMessage(type: "call_service", additionalData: {"domain": domain, "service": service, "service_data": serviceData});
|
//return sendSocketMessage(type: "call_service", additionalData: {"domain": domain, "service": service, "service_data": serviceData});
|
||||||
else
|
else
|
||||||
sendHTTPPost(
|
sendHTTPPost(
|
||||||
endPoint: "/api/services/$domain/$service"
|
endPoint: "/api/services/$domain/$service"
|
||||||
).then((data) => completer.complete(data)).catchError((e) => completer.completeError(HAError("${e["message"]}")));
|
).then((data) => completer.complete(data)).catchError((e) => completer.completeError(HAError(e.toString())));
|
||||||
//return sendSocketMessage(type: "call_service", additionalData: {"domain": domain, "service": service});
|
//return sendSocketMessage(type: "call_service", additionalData: {"domain": domain, "service": service});
|
||||||
return completer.future;
|
return completer.future;
|
||||||
}
|
}
|
||||||
@ -414,7 +411,7 @@ class ConnectionManager {
|
|||||||
completer.complete(response.body);
|
completer.complete(response.body);
|
||||||
} else {
|
} else {
|
||||||
Logger.d("[Received] <== HTTP ${response.statusCode}: ${response.body}");
|
Logger.d("[Received] <== HTTP ${response.statusCode}: ${response.body}");
|
||||||
completer.completeError({"code": response.statusCode, "message": "${response.body}"});
|
completer.completeError(response);
|
||||||
}
|
}
|
||||||
}).catchError((e) {
|
}).catchError((e) {
|
||||||
completer.completeError(e);
|
completer.completeError(e);
|
||||||
|
@ -82,8 +82,8 @@ class LocationManager {
|
|||||||
int delay = i*delayFactor;
|
int delay = i*delayFactor;
|
||||||
Logger.d("Scheduling location update task #$i for every ${interval.inMinutes} minutes in $delay minutes...");
|
Logger.d("Scheduling location update task #$i for every ${interval.inMinutes} minutes in $delay minutes...");
|
||||||
await workManager.Workmanager.registerPeriodicTask(
|
await workManager.Workmanager.registerPeriodicTask(
|
||||||
"$backgroundTaskId$n",
|
"$backgroundTaskId$i",
|
||||||
"haClientLocationTracking-0$n",
|
"haClientLocationTracking-0$i",
|
||||||
tag: backgroundTaskTag,
|
tag: backgroundTaskTag,
|
||||||
inputData: {
|
inputData: {
|
||||||
"webhookId": webhookId,
|
"webhookId": webhookId,
|
||||||
|
@ -81,7 +81,7 @@ class MobileAppIntegrationManager {
|
|||||||
}
|
}
|
||||||
completer.complete();
|
completer.complete();
|
||||||
}).catchError((e) {
|
}).catchError((e) {
|
||||||
if (e['code'] != null && e['code'] == 410) {
|
if (e is http.Response && e.statusCode == 410) {
|
||||||
Logger.e("MobileApp integration was removed");
|
Logger.e("MobileApp integration was removed");
|
||||||
_askToRegisterApp();
|
_askToRegisterApp();
|
||||||
} else {
|
} else {
|
||||||
|
@ -30,12 +30,16 @@ class _MainPageState extends ReceiveShareState<MainPage> with WidgetsBindingObse
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
|
super.initState();
|
||||||
final Stream purchaseUpdates =
|
final Stream purchaseUpdates =
|
||||||
InAppPurchaseConnection.instance.purchaseUpdatedStream;
|
InAppPurchaseConnection.instance.purchaseUpdatedStream;
|
||||||
_subscription = purchaseUpdates.listen((purchases) {
|
_subscription = purchaseUpdates.listen((purchases) {
|
||||||
_handlePurchaseUpdates(purchases);
|
_handlePurchaseUpdates(purchases);
|
||||||
});
|
});
|
||||||
super.initState();
|
workManager.Workmanager.initialize(
|
||||||
|
updateDeviceLocationIsolate,
|
||||||
|
isInDebugMode: false
|
||||||
|
);
|
||||||
enableShareReceiving();
|
enableShareReceiving();
|
||||||
WidgetsBinding.instance.addObserver(this);
|
WidgetsBinding.instance.addObserver(this);
|
||||||
|
|
||||||
@ -328,7 +332,7 @@ class _MainPageState extends ReceiveShareState<MainPage> with WidgetsBindingObse
|
|||||||
|
|
||||||
void _showEntityPage(String entityId) {
|
void _showEntityPage(String entityId) {
|
||||||
setState(() {
|
setState(() {
|
||||||
_entityToShow = HomeAssistant().entities.get(entityId);
|
_entityToShow = HomeAssistant().entities?.get(entityId);
|
||||||
if (_entityToShow != null) {
|
if (_entityToShow != null) {
|
||||||
_mainScrollController?.jumpTo(0);
|
_mainScrollController?.jumpTo(0);
|
||||||
}
|
}
|
||||||
|
@ -75,10 +75,16 @@ class _ConnectionSettingsPageState extends State<ConnectionSettingsPage> {
|
|||||||
|
|
||||||
_saveSettings() async {
|
_saveSettings() async {
|
||||||
_newHassioDomain = _newHassioDomain.trim();
|
_newHassioDomain = _newHassioDomain.trim();
|
||||||
if (_newHassioDomain.indexOf("http") == 0 && _newHassioDomain.indexOf("//") > 0) {
|
if (_newHassioDomain.startsWith("http") && _newHassioDomain.indexOf("//") > 0) {
|
||||||
|
_newHassioDomain.startsWith("https") ? _newSocketProtocol = "wss" : _newSocketProtocol = "ws";
|
||||||
_newHassioDomain = _newHassioDomain.split("//")[1];
|
_newHassioDomain = _newHassioDomain.split("//")[1];
|
||||||
}
|
}
|
||||||
_newHassioDomain = _newHassioDomain.split("/")[0];
|
_newHassioDomain = _newHassioDomain.split("/")[0];
|
||||||
|
if (_newHassioDomain.contains(":")) {
|
||||||
|
List<String> domainAndPort = _newHassioDomain.split(":");
|
||||||
|
_newHassioDomain = domainAndPort[0];
|
||||||
|
_newHassioPort = domainAndPort[1];
|
||||||
|
}
|
||||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
final storage = new FlutterSecureStorage();
|
final storage = new FlutterSecureStorage();
|
||||||
if (_newLongLivedToken.isNotEmpty) {
|
if (_newLongLivedToken.isNotEmpty) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
name: hass_client
|
name: hass_client
|
||||||
description: Home Assistant Android Client
|
description: Home Assistant Android Client
|
||||||
|
|
||||||
version: 0.7.5+750
|
version: 0.7.6+760
|
||||||
|
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
@ -27,7 +27,7 @@ dependencies:
|
|||||||
device_info: ^0.4.0+3
|
device_info: ^0.4.0+3
|
||||||
flutter_local_notifications: ^0.8.4
|
flutter_local_notifications: ^0.8.4
|
||||||
geolocator: ^5.1.5
|
geolocator: ^5.1.5
|
||||||
workmanager: ^0.1.3
|
workmanager: ^0.1.5
|
||||||
battery: ^0.3.1+1
|
battery: ^0.3.1+1
|
||||||
sentry: ^2.3.1
|
sentry: ^2.3.1
|
||||||
share:
|
share:
|
||||||
|
Reference in New Issue
Block a user