From cb118b599ab0262ebe89c00ab3a360a37e5d65f5 Mon Sep 17 00:00:00 2001 From: estevez-dev Date: Wed, 13 Mar 2019 00:56:57 +0200 Subject: [PATCH] Resolves #245 Add special row elements support for entities card --- lib/entity_class/entity.class.dart | 36 +++++++++- lib/entity_class/entity_wrapper.class.dart | 22 +++++- .../button_entity_container.dart | 46 ++++++------ .../default_entity_container.dart | 71 +++++++++++-------- .../glance_entity_container.dart | 5 +- lib/home_assistant.class.dart | 42 ++++++++++- lib/ui_widgets/card_widget.dart | 2 +- 7 files changed, 168 insertions(+), 56 deletions(-) diff --git a/lib/entity_class/entity.class.dart b/lib/entity_class/entity.class.dart index 9d5798a..fb997b6 100644 --- a/lib/entity_class/entity.class.dart +++ b/lib/entity_class/entity.class.dart @@ -1,5 +1,14 @@ part of '../main.dart'; +class StatelessEntityType { + static const NONE = 0; + static const MISSED = 1; + static const DIVIDER = 2; + static const SECTION = 3; + static const CALL_SERVICE = 4; + static const WEBLINK = 5; +} + class Entity { static List badgeDomains = [ @@ -67,7 +76,7 @@ class Entity { String state; String displayState; DateTime _lastUpdated; - bool missed = false; + int statelessType = 0; List childEntities = []; List attributesToShow = ["all"]; @@ -99,11 +108,34 @@ class Entity { } Entity.missed(String entityId) { - missed = true; + statelessType = StatelessEntityType.MISSED; attributes = {"hidden": false}; this.entityId = entityId; } + Entity.divider() { + statelessType = StatelessEntityType.DIVIDER; + attributes = {"hidden": false}; + } + + Entity.section(String label) { + statelessType = StatelessEntityType.SECTION; + attributes = {"hidden": false, "friendly_name": "$label"}; + } + + Entity.callService({String icon, String name, String service, String actionName}) { + statelessType = StatelessEntityType.CALL_SERVICE; + entityId = service; + displayState = actionName?.toUpperCase() ?? "RUN"; + attributes = {"hidden": false, "friendly_name": "$name", "icon": "$icon"}; + } + + Entity.weblink({String url, String name, String icon}) { + statelessType = StatelessEntityType.WEBLINK; + entityId = "custom.custom"; //TODO wtf?? + attributes = {"hidden": false, "friendly_name": "${name ?? url}", "icon": "${icon ?? 'mdi:link'}"}; + } + void update(Map rawData) { attributes = rawData["attributes"] ?? {}; domain = rawData["entity_id"].split(".")[0]; diff --git a/lib/entity_class/entity_wrapper.class.dart b/lib/entity_class/entity_wrapper.class.dart index f574c55..0f4ffc8 100644 --- a/lib/entity_class/entity_wrapper.class.dart +++ b/lib/entity_class/entity_wrapper.class.dart @@ -14,7 +14,7 @@ class EntityWrapper { String displayName, this.uiAction }) { - if (!entity.missed) { + if (entity.statelessType == StatelessEntityType.NONE || entity.statelessType == StatelessEntityType.CALL_SERVICE || entity.statelessType == StatelessEntityType.WEBLINK) { this.icon = icon ?? entity.icon; this.displayName = displayName ?? entity.displayName; if (uiAction == null) { @@ -51,6 +51,16 @@ class EntityWrapper { break; } + case EntityUIAction.navigate: { + if (uiAction.tapService.startsWith("/")) { + //TODO handle local urls + Logger.w("Local urls is not supported yet"); + } else { + HAUtils.launchURL(uiAction.tapService); + } + break; + } + default: { break; } @@ -81,6 +91,16 @@ class EntityWrapper { break; } + case EntityUIAction.navigate: { + if (uiAction.holdService.startsWith("/")) { + //TODO handle local urls + Logger.w("Local urls is not supported yet"); + } else { + HAUtils.launchURL(uiAction.holdService); + } + break; + } + default: { break; } diff --git a/lib/entity_widgets/button_entity_container.dart b/lib/entity_widgets/button_entity_container.dart index 28b0554..dd3c9ff 100644 --- a/lib/entity_widgets/button_entity_container.dart +++ b/lib/entity_widgets/button_entity_container.dart @@ -9,30 +9,32 @@ class ButtonEntityContainer extends StatelessWidget { @override Widget build(BuildContext context) { final EntityWrapper entityWrapper = EntityModel.of(context).entityWrapper; - if (entityWrapper.entity.missed) { + if (entityWrapper.entity.statelessType == StatelessEntityType.MISSED) { return MissedEntityWidget(); - } else { - return InkWell( - onTap: () => entityWrapper.handleTap(), - onLongPress: () => entityWrapper.handleHold(), - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - FractionallySizedBox( - widthFactor: 0.4, - child: FittedBox( - fit: BoxFit.fitHeight, - child: EntityIcon( - padding: EdgeInsets.fromLTRB(2.0, 6.0, 2.0, 2.0), - size: Sizes.iconSize, - ) - ), - ), - _buildName() - ], - ), - ); } + if (entityWrapper.entity.statelessType > StatelessEntityType.MISSED) { + return Container(width: 0.0, height: 0.0,); + } + return InkWell( + onTap: () => entityWrapper.handleTap(), + onLongPress: () => entityWrapper.handleHold(), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + FractionallySizedBox( + widthFactor: 0.4, + child: FittedBox( + fit: BoxFit.fitHeight, + child: EntityIcon( + padding: EdgeInsets.fromLTRB(2.0, 6.0, 2.0, 2.0), + size: Sizes.iconSize, + ) + ), + ), + _buildName() + ], + ), + ); } Widget _buildName() { diff --git a/lib/entity_widgets/default_entity_container.dart b/lib/entity_widgets/default_entity_container.dart index b2ce082..e8fb50e 100644 --- a/lib/entity_widgets/default_entity_container.dart +++ b/lib/entity_widgets/default_entity_container.dart @@ -11,36 +11,51 @@ class DefaultEntityContainer extends StatelessWidget { @override Widget build(BuildContext context) { final EntityModel entityModel = EntityModel.of(context); - if (entityModel.entityWrapper.entity.missed) { + if (entityModel.entityWrapper.entity.statelessType == StatelessEntityType.MISSED) { return MissedEntityWidget(); - } else { - return InkWell( - onLongPress: () { - if (entityModel.handleTap) { - entityModel.entityWrapper.handleHold(); - } - }, - onTap: () { - if (entityModel.handleTap) { - entityModel.entityWrapper.handleTap(); - } - }, - child: Row( - mainAxisSize: MainAxisSize.max, - children: [ - EntityIcon(), - - Flexible( - fit: FlexFit.tight, - flex: 3, - child: EntityName( - padding: EdgeInsets.fromLTRB(10.0, 2.0, 10.0, 2.0), - ), - ), - state - ], - ), + } + if (entityModel.entityWrapper.entity.statelessType == StatelessEntityType.DIVIDER) { + return Divider(); + } + if (entityModel.entityWrapper.entity.statelessType == StatelessEntityType.SECTION) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Divider(), + Text( + "${entityModel.entityWrapper.entity.displayName}", + style: TextStyle(color: Colors.blue), + ) + ], ); } + return InkWell( + onLongPress: () { + if (entityModel.handleTap) { + entityModel.entityWrapper.handleHold(); + } + }, + onTap: () { + if (entityModel.handleTap) { + entityModel.entityWrapper.handleTap(); + } + }, + child: Row( + mainAxisSize: MainAxisSize.max, + children: [ + EntityIcon(), + + Flexible( + fit: FlexFit.tight, + flex: 3, + child: EntityName( + padding: EdgeInsets.fromLTRB(10.0, 2.0, 10.0, 2.0), + ), + ), + state + ], + ), + ); } } \ No newline at end of file diff --git a/lib/entity_widgets/glance_entity_container.dart b/lib/entity_widgets/glance_entity_container.dart index 5c9e07d..a35ed38 100644 --- a/lib/entity_widgets/glance_entity_container.dart +++ b/lib/entity_widgets/glance_entity_container.dart @@ -22,9 +22,12 @@ class GlanceEntityContainer extends StatelessWidget { @override Widget build(BuildContext context) { final EntityWrapper entityWrapper = EntityModel.of(context).entityWrapper; - if (entityWrapper.entity.missed) { + if (entityWrapper.entity.statelessType == StatelessEntityType.MISSED) { return MissedEntityWidget(); } + if (entityWrapper.entity.statelessType > StatelessEntityType.MISSED) { + return Container(width: 0.0, height: 0.0,); + } List result = []; if (!nameInTheBottom) { if (showName) { diff --git a/lib/home_assistant.class.dart b/lib/home_assistant.class.dart index 73e4698..389a541 100644 --- a/lib/home_assistant.class.dart +++ b/lib/home_assistant.class.dart @@ -405,7 +405,47 @@ class HomeAssistant { card.entities.add(EntityWrapper(entity: Entity.missed(rawEntity))); } } else { - if (entities.isExist(rawEntity["entity"])) { + if (rawEntity["type"] == "divider") { + card.entities.add(EntityWrapper(entity: Entity.divider())); + } else if (rawEntity["type"] == "section") { + card.entities.add(EntityWrapper(entity: Entity.section(rawEntity["label"] ?? ""))); + } else if (rawEntity["type"] == "call-service") { + Map uiActionData = { + "tap_action": { + "action": EntityUIAction.callService, + "service": rawEntity["service"], + "service_data": rawEntity["service_data"] + }, + "hold_action": EntityUIAction.none + }; + card.entities.add(EntityWrapper( + entity: Entity.callService( + icon: rawEntity["icon"], + name: rawEntity["name"], + service: rawEntity["service"], + actionName: rawEntity["action_name"] + ), + uiAction: EntityUIAction(rawEntityData: uiActionData) + ) + ); + } else if (rawEntity["type"] == "weblink") { + Map uiActionData = { + "tap_action": { + "action": EntityUIAction.navigate, + "service": rawEntity["url"] + }, + "hold_action": EntityUIAction.none + }; + card.entities.add(EntityWrapper( + entity: Entity.weblink( + icon: rawEntity["icon"], + name: rawEntity["name"], + url: rawEntity["url"] + ), + uiAction: EntityUIAction(rawEntityData: uiActionData) + ) + ); + } else if (entities.isExist(rawEntity["entity"])) { Entity e = entities.get(rawEntity["entity"]); card.entities.add( EntityWrapper( diff --git a/lib/ui_widgets/card_widget.dart b/lib/ui_widgets/card_widget.dart index 3cb91a4..68dfd88 100644 --- a/lib/ui_widgets/card_widget.dart +++ b/lib/ui_widgets/card_widget.dart @@ -15,7 +15,7 @@ class CardWidget extends StatelessWidget { if (card.linkedEntityWrapper.entity.isHidden) { return Container(width: 0.0, height: 0.0,); } - if (card.linkedEntityWrapper.entity.missed) { + if (card.linkedEntityWrapper.entity.statelessType == StatelessEntityType.MISSED) { return EntityModel( entityWrapper: card.linkedEntityWrapper, child: MissedEntityWidget(),