diff --git a/lib/entity_class/const.dart b/lib/entity_class/const.dart index 5edc18e..f8864d6 100644 --- a/lib/entity_class/const.dart +++ b/lib/entity_class/const.dart @@ -28,4 +28,10 @@ class EntityState { static const unavailable = 'unavailable'; static const ok = 'ok'; static const problem = 'problem'; +} + +class EntityTapAction { + static const moreInfo = 'more-info'; + static const toggle = 'toggle'; + static const callService = 'call-service'; } \ No newline at end of file diff --git a/lib/entity_class/entity.class.dart b/lib/entity_class/entity.class.dart index cb98473..066cf3d 100644 --- a/lib/entity_class/entity.class.dart +++ b/lib/entity_class/entity.class.dart @@ -106,7 +106,7 @@ class Entity { Widget buildEntityPageWidget(BuildContext context) { return EntityModel( - entity: EntityWrapper(entity: this), + entityWrapper: EntityWrapper(entity: this), child: EntityPageContainer(children: [ DefaultEntityContainer(state: _buildStatePartForPage(context)), LastUpdatedWidget(), @@ -128,7 +128,7 @@ class Entity { Widget buildBadgeWidget(BuildContext context) { return EntityModel( - entity: EntityWrapper(entity: this), + entityWrapper: EntityWrapper(entity: this), child: BadgeWidget(), handleTap: true, ); diff --git a/lib/entity_class/entity_wrapper.class.dart b/lib/entity_class/entity_wrapper.class.dart index feb8a16..a7b9793 100644 --- a/lib/entity_class/entity_wrapper.class.dart +++ b/lib/entity_class/entity_wrapper.class.dart @@ -4,9 +4,18 @@ class EntityWrapper { String displayName; String icon; + String tapAction; + String holdAction; Entity entity; - EntityWrapper({this.entity, String icon, String displayName}) { + + EntityWrapper({ + this.entity, + String icon, + String displayName, + this.tapAction: EntityTapAction.moreInfo, + this.holdAction + }) { this.icon = icon ?? entity.icon; this.displayName = displayName ?? entity.displayName; } diff --git a/lib/entity_widgets/badge.dart b/lib/entity_widgets/badge.dart index dca850a..21b23fb 100644 --- a/lib/entity_widgets/badge.dart +++ b/lib/entity_widgets/badge.dart @@ -7,12 +7,12 @@ class BadgeWidget extends StatelessWidget { double iconSize = 26.0; Widget badgeIcon; String onBadgeTextValue; - Color iconColor = EntityColor.badgeColors[entityModel.entity.entity.domain] ?? + Color iconColor = EntityColor.badgeColors[entityModel.entityWrapper.entity.domain] ?? EntityColor.badgeColors["default"]; - switch (entityModel.entity.entity.domain) { + switch (entityModel.entityWrapper.entity.domain) { case "sun": { - badgeIcon = entityModel.entity.entity.state == "below_horizon" + badgeIcon = entityModel.entityWrapper.entity.state == "below_horizon" ? Icon( MaterialDesignIcons.createIconDataFromIconCode(0xf0dc), size: iconSize, @@ -25,10 +25,10 @@ class BadgeWidget extends StatelessWidget { } case "sensor": { - onBadgeTextValue = entityModel.entity.entity.unitOfMeasurement; + onBadgeTextValue = entityModel.entityWrapper.entity.unitOfMeasurement; badgeIcon = Center( child: Text( - "${entityModel.entity.entity.state}", + "${entityModel.entityWrapper.entity.state}", overflow: TextOverflow.fade, softWrap: false, textAlign: TextAlign.center, @@ -40,14 +40,14 @@ class BadgeWidget extends StatelessWidget { case "device_tracker": { badgeIcon = MaterialDesignIcons.createIconWidgetFromEntityData( - entityModel.entity, iconSize, Colors.black); - onBadgeTextValue = entityModel.entity.entity.state; + entityModel.entityWrapper, iconSize, Colors.black); + onBadgeTextValue = entityModel.entityWrapper.entity.state; break; } default: { badgeIcon = MaterialDesignIcons.createIconWidgetFromEntityData( - entityModel.entity, iconSize, Colors.black); + entityModel.entityWrapper, iconSize, Colors.black); } } Widget onBadgeText; @@ -109,7 +109,7 @@ class BadgeWidget extends StatelessWidget { Container( width: 60.0, child: Text( - "${entityModel.entity.displayName}", + "${entityModel.entityWrapper.displayName}", textAlign: TextAlign.center, style: TextStyle(fontSize: 12.0), softWrap: true, @@ -120,6 +120,6 @@ class BadgeWidget extends StatelessWidget { ], ), onTap: () => - eventBus.fire(new ShowEntityPageEvent(entityModel.entity.entity))); + eventBus.fire(new ShowEntityPageEvent(entityModel.entityWrapper.entity))); } } \ No newline at end of file diff --git a/lib/entity_widgets/controls/climate_controls.dart b/lib/entity_widgets/controls/climate_controls.dart index aad2226..a46b0d4 100644 --- a/lib/entity_widgets/controls/climate_controls.dart +++ b/lib/entity_widgets/controls/climate_controls.dart @@ -165,7 +165,7 @@ class _ClimateControlWidgetState extends State { @override Widget build(BuildContext context) { final entityModel = EntityModel.of(context); - final ClimateEntity entity = entityModel.entity.entity; + final ClimateEntity entity = entityModel.entityWrapper.entity; if (_changedHere) { _showPending = (_tmpTemperature != entity.temperature); _changedHere = false; diff --git a/lib/entity_widgets/controls/cover_controls.dart b/lib/entity_widgets/controls/cover_controls.dart index af5e6d9..7235a66 100644 --- a/lib/entity_widgets/controls/cover_controls.dart +++ b/lib/entity_widgets/controls/cover_controls.dart @@ -38,7 +38,7 @@ class _CoverControlWidgetState extends State { @override Widget build(BuildContext context) { final entityModel = EntityModel.of(context); - final CoverEntity entity = entityModel.entity.entity; + final CoverEntity entity = entityModel.entityWrapper.entity; if (_changedHere) { _changedHere = false; } else { @@ -152,7 +152,7 @@ class CoverTiltControlsWidget extends StatelessWidget { @override Widget build(BuildContext context) { final entityModel = EntityModel.of(context); - final CoverEntity entity = entityModel.entity.entity; + final CoverEntity entity = entityModel.entityWrapper.entity; List buttons = []; if (entity.supportOpenTilt) { buttons.add(IconButton( diff --git a/lib/entity_widgets/controls/light_controls.dart b/lib/entity_widgets/controls/light_controls.dart index e999d63..0cde589 100644 --- a/lib/entity_widgets/controls/light_controls.dart +++ b/lib/entity_widgets/controls/light_controls.dart @@ -80,7 +80,7 @@ class _LightControlsWidgetState extends State { @override Widget build(BuildContext context) { final entityModel = EntityModel.of(context); - final LightEntity entity = entityModel.entity.entity; + final LightEntity entity = entityModel.entityWrapper.entity; if (!_changedHere) { _resetState(entity); } else { diff --git a/lib/entity_widgets/controls/media_player_widget.dart b/lib/entity_widgets/controls/media_player_widget.dart index ea03b2d..cc691bc 100644 --- a/lib/entity_widgets/controls/media_player_widget.dart +++ b/lib/entity_widgets/controls/media_player_widget.dart @@ -28,7 +28,7 @@ class MediaPlayerWidget extends StatelessWidget { @override Widget build(BuildContext context) { final EntityModel entityModel = EntityModel.of(context); - final MediaPlayerEntity entity = entityModel.entity.entity; + final MediaPlayerEntity entity = entityModel.entityWrapper.entity; return Column( children: [ Stack( @@ -229,7 +229,7 @@ class _MediaPlayerProgressWidgetState extends State { @override Widget build(BuildContext context) { final EntityModel entityModel = EntityModel.of(context); - final MediaPlayerEntity entity = entityModel.entity.entity; + final MediaPlayerEntity entity = entityModel.entityWrapper.entity; double progress; try { DateTime lastUpdated = DateTime.parse( diff --git a/lib/entity_widgets/controls/slider_controls.dart b/lib/entity_widgets/controls/slider_controls.dart index 813201c..b67743e 100644 --- a/lib/entity_widgets/controls/slider_controls.dart +++ b/lib/entity_widgets/controls/slider_controls.dart @@ -25,7 +25,7 @@ class _SliderControlsWidgetState extends State { @override Widget build(BuildContext context) { final entityModel = EntityModel.of(context); - final SliderEntity entity = entityModel.entity.entity; + final SliderEntity entity = entityModel.entityWrapper.entity; if (entity.valueStep < 1) { _multiplier = 10; } else if (entity.valueStep < 0.1) { diff --git a/lib/entity_widgets/entity_attributes_list.dart b/lib/entity_widgets/entity_attributes_list.dart index d2d2011..52ebbd2 100644 --- a/lib/entity_widgets/entity_attributes_list.dart +++ b/lib/entity_widgets/entity_attributes_list.dart @@ -7,14 +7,14 @@ class EntityAttributesList extends StatelessWidget { Widget build(BuildContext context) { final entityModel = EntityModel.of(context); List attrs = []; - if ((entityModel.entity.entity.attributesToShow == null) || - (entityModel.entity.entity.attributesToShow.contains("all"))) { - entityModel.entity.entity.attributes.forEach((name, value) { + if ((entityModel.entityWrapper.entity.attributesToShow == null) || + (entityModel.entityWrapper.entity.attributesToShow.contains("all"))) { + entityModel.entityWrapper.entity.attributes.forEach((name, value) { attrs.add(_buildSingleAttribute("$name", "$value")); }); } else { - entityModel.entity.entity.attributesToShow.forEach((String attr) { - String attrValue = entityModel.entity.entity.getAttribute("$attr"); + entityModel.entityWrapper.entity.attributesToShow.forEach((String attr) { + String attrValue = entityModel.entityWrapper.entity.getAttribute("$attr"); if (attrValue != null) { attrs.add( _buildSingleAttribute("$attr", "$attrValue")); diff --git a/lib/entity_widgets/entity_icon.dart b/lib/entity_widgets/entity_icon.dart index 7d78a84..f37f1f1 100644 --- a/lib/entity_widgets/entity_icon.dart +++ b/lib/entity_widgets/entity_icon.dart @@ -15,14 +15,29 @@ class EntityIcon extends StatelessWidget { child: Padding( padding: padding, child: MaterialDesignIcons.createIconWidgetFromEntityData( - entityModel.entity, + entityModel.entityWrapper, iconSize, - EntityColor.stateColor(entityModel.entity.entity.state) + EntityColor.stateColor(entityModel.entityWrapper.entity.state) ), ), - onTap: () => entityModel.handleTap - ? eventBus.fire(new ShowEntityPageEvent(entityModel.entity.entity)) - : null, + onTap: () { + if (entityModel.handleTap) { + switch (entityModel.entityWrapper.tapAction) { + case EntityTapAction.moreInfo: { + eventBus.fire( + new ShowEntityPageEvent(entityModel.entityWrapper.entity)); + break; + } + case EntityTapAction.toggle: { + eventBus.fire( + ServiceCallEvent("homeassistant", "toggle", entityModel.entityWrapper.entity.entityId, null)); + break; + } + } + + } + } + ); } } \ No newline at end of file diff --git a/lib/entity_widgets/entity_name.dart b/lib/entity_widgets/entity_name.dart index 1d7a1a7..dc59175 100644 --- a/lib/entity_widgets/entity_name.dart +++ b/lib/entity_widgets/entity_name.dart @@ -17,7 +17,7 @@ class EntityName extends StatelessWidget { child: Padding( padding: padding, child: Text( - "${entityModel.entity.displayName}", + "${entityModel.entityWrapper.displayName}", overflow: textOverflow, softWrap: wordsWrap, style: TextStyle(fontSize: fontSize), @@ -26,7 +26,7 @@ class EntityName extends StatelessWidget { ), onTap: () => entityModel.handleTap - ? eventBus.fire(new ShowEntityPageEvent(entityModel.entity.entity)) + ? eventBus.fire(new ShowEntityPageEvent(entityModel.entityWrapper.entity)) : null, ); } diff --git a/lib/entity_widgets/history_chart/entity_history.dart b/lib/entity_widgets/history_chart/entity_history.dart index 6dc6e7d..5cd38da 100644 --- a/lib/entity_widgets/history_chart/entity_history.dart +++ b/lib/entity_widgets/history_chart/entity_history.dart @@ -65,7 +65,7 @@ class _EntityHistoryWidgetState extends State { Widget build(BuildContext context) { final HomeAssistantModel homeAssistantModel = HomeAssistantModel.of(context); final EntityModel entityModel = EntityModel.of(context); - final Entity entity = entityModel.entity.entity; + final Entity entity = entityModel.entityWrapper.entity; if (!_needToUpdateHistory) { _needToUpdateHistory = true; } else { diff --git a/lib/entity_widgets/last_updated.dart b/lib/entity_widgets/last_updated.dart index bdccd16..5b55d47 100644 --- a/lib/entity_widgets/last_updated.dart +++ b/lib/entity_widgets/last_updated.dart @@ -8,7 +8,7 @@ class LastUpdatedWidget extends StatelessWidget { padding: EdgeInsets.fromLTRB( Sizes.leftWidgetPadding, 0.0, 0.0, 0.0), child: Text( - '${entityModel.entity.entity.lastUpdated}', + '${entityModel.entityWrapper.entity.lastUpdated}', textAlign: TextAlign.left, style: TextStyle( fontSize: Sizes.smallFontSize, color: Colors.black26), diff --git a/lib/entity_widgets/model_widgets.dart b/lib/entity_widgets/model_widgets.dart index c7e9a94..aef383f 100644 --- a/lib/entity_widgets/model_widgets.dart +++ b/lib/entity_widgets/model_widgets.dart @@ -3,12 +3,12 @@ part of '../main.dart'; class EntityModel extends InheritedWidget { const EntityModel({ Key key, - @required this.entity, + @required this.entityWrapper, @required this.handleTap, @required Widget child, }) : super(key: key, child: child); - final EntityWrapper entity; + final EntityWrapper entityWrapper; final bool handleTap; static EntityModel of(BuildContext context) { diff --git a/lib/entity_widgets/state/button_state.dart b/lib/entity_widgets/state/button_state.dart index bbb87c5..11db3d2 100644 --- a/lib/entity_widgets/state/button_state.dart +++ b/lib/entity_widgets/state/button_state.dart @@ -13,7 +13,7 @@ class ButtonStateWidget extends StatelessWidget { height: 34.0, child: FlatButton( onPressed: (() { - _setNewState(entityModel.entity.entity); + _setNewState(entityModel.entityWrapper.entity); }), child: Text( "EXECUTE", diff --git a/lib/entity_widgets/state/climate_state.dart b/lib/entity_widgets/state/climate_state.dart index 7139f03..7513256 100644 --- a/lib/entity_widgets/state/climate_state.dart +++ b/lib/entity_widgets/state/climate_state.dart @@ -4,7 +4,7 @@ class ClimateStateWidget extends StatelessWidget { @override Widget build(BuildContext context) { final entityModel = EntityModel.of(context); - final ClimateEntity entity = entityModel.entity.entity; + final ClimateEntity entity = entityModel.entityWrapper.entity; String targetTemp = "-"; if ((entity.supportTargetTemperature) && (entity.temperature != null)) { targetTemp = "${entity.temperature}"; diff --git a/lib/entity_widgets/state/cover_state.dart b/lib/entity_widgets/state/cover_state.dart index 37a7681..241eca7 100644 --- a/lib/entity_widgets/state/cover_state.dart +++ b/lib/entity_widgets/state/cover_state.dart @@ -19,7 +19,7 @@ class CoverStateWidget extends StatelessWidget { @override Widget build(BuildContext context) { final entityModel = EntityModel.of(context); - final CoverEntity entity = entityModel.entity.entity; + final CoverEntity entity = entityModel.entityWrapper.entity; List buttons = []; if (entity.supportOpen) { buttons.add(IconButton( diff --git a/lib/entity_widgets/state/date_time_state.dart b/lib/entity_widgets/state/date_time_state.dart index d438df3..c9744df 100644 --- a/lib/entity_widgets/state/date_time_state.dart +++ b/lib/entity_widgets/state/date_time_state.dart @@ -4,7 +4,7 @@ class DateTimeStateWidget extends StatelessWidget { @override Widget build(BuildContext context) { final entityModel = EntityModel.of(context); - final DateTimeEntity entity = entityModel.entity.entity; + final DateTimeEntity entity = entityModel.entityWrapper.entity; return Padding( padding: EdgeInsets.fromLTRB(0.0, 0.0, Sizes.rightWidgetPadding, 0.0), child: GestureDetector( diff --git a/lib/entity_widgets/state/select_state.dart b/lib/entity_widgets/state/select_state.dart index 680ed00..cd0cdac 100644 --- a/lib/entity_widgets/state/select_state.dart +++ b/lib/entity_widgets/state/select_state.dart @@ -18,7 +18,7 @@ class _SelectStateWidgetState extends State { @override Widget build(BuildContext context) { final entityModel = EntityModel.of(context); - final SelectEntity entity = entityModel.entity.entity; + final SelectEntity entity = entityModel.entityWrapper.entity; Widget ctrl; if (entity.listOptions.isNotEmpty) { ctrl = DropdownButton( diff --git a/lib/entity_widgets/state/simple_state.dart b/lib/entity_widgets/state/simple_state.dart index e03ea8d..0a42a7b 100644 --- a/lib/entity_widgets/state/simple_state.dart +++ b/lib/entity_widgets/state/simple_state.dart @@ -15,7 +15,7 @@ class SimpleEntityState extends StatelessWidget { padding: padding, child: GestureDetector( child: Text( - "${entityModel.entity.entity.state}${entityModel.entity.entity.unitOfMeasurement}", + "${entityModel.entityWrapper.entity.state}${entityModel.entityWrapper.entity.unitOfMeasurement}", textAlign: textAlign, maxLines: 4, overflow: TextOverflow.ellipsis, @@ -24,7 +24,7 @@ class SimpleEntityState extends StatelessWidget { fontSize: Sizes.stateFontSize, )), onTap: () => entityModel.handleTap - ? eventBus.fire(new ShowEntityPageEvent(entityModel.entity.entity)) + ? eventBus.fire(new ShowEntityPageEvent(entityModel.entityWrapper.entity)) : null, ) ); diff --git a/lib/entity_widgets/state/switch_state.dart b/lib/entity_widgets/state/switch_state.dart index 82ff6a9..504449a 100644 --- a/lib/entity_widgets/state/switch_state.dart +++ b/lib/entity_widgets/state/switch_state.dart @@ -34,7 +34,7 @@ class _SwitchStateWidgetState extends State { @override Widget build(BuildContext context) { final entityModel = EntityModel.of(context); - final entity = entityModel.entity.entity; + final entity = entityModel.entityWrapper.entity; if (!updatedHere) { newState = entity.state; } else { diff --git a/lib/entity_widgets/state/text_input_state.dart b/lib/entity_widgets/state/text_input_state.dart index 3695f8a..692e2dc 100644 --- a/lib/entity_widgets/state/text_input_state.dart +++ b/lib/entity_widgets/state/text_input_state.dart @@ -55,7 +55,7 @@ class _TextInputStateWidgetState extends State { @override Widget build(BuildContext context) { final entityModel = EntityModel.of(context); - final TextEntity entity = entityModel.entity.entity; + final TextEntity entity = entityModel.entityWrapper.entity; _entityState = entity.state; _entityDomain = entity.domain; _entityId = entity.entityId; diff --git a/lib/home_assistant.class.dart b/lib/home_assistant.class.dart index ffc763c..1cc54ce 100644 --- a/lib/home_assistant.class.dart +++ b/lib/home_assistant.class.dart @@ -427,7 +427,9 @@ class HomeAssistant { EntityWrapper( entity: entities.get(rawEntity["entity"]), displayName: rawEntity["name"], - icon: rawEntity["icon"] + icon: rawEntity["icon"], + tapAction: rawEntity["tap_action"] ?? EntityTapAction.moreInfo, + holdAction: rawEntity["hold_action"] ?? EntityTapAction.moreInfo ) ); } diff --git a/lib/main.dart b/lib/main.dart index 80be832..a1db2e1 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -140,6 +140,7 @@ class _MainPageState extends State with WidgetsBindingObserver { String _authType; //int _uiViewsCount = 0; String _instanceHost; + StreamSubscription _stateSubscription; StreamSubscription _settingsSubscription; StreamSubscription _serviceCallSubscription; StreamSubscription _showEntityPageSubscription; @@ -208,6 +209,11 @@ class _MainPageState extends State with WidgetsBindingObserver { } _subscribe() { + if (_stateSubscription == null) { + _stateSubscription = eventBus.on().listen((event) { + setState(() {}); + }); + } if (_serviceCallSubscription == null) { _serviceCallSubscription = eventBus.on().listen((event) { @@ -546,6 +552,7 @@ class _MainPageState extends State with WidgetsBindingObserver { @override void dispose() { WidgetsBinding.instance.removeObserver(this); + if (_stateSubscription != null) _stateSubscription.cancel(); if (_settingsSubscription != null) _settingsSubscription.cancel(); if (_serviceCallSubscription != null) _serviceCallSubscription.cancel(); if (_showEntityPageSubscription != null) _showEntityPageSubscription.cancel(); diff --git a/lib/ui_widgets/entities_card.dart b/lib/ui_widgets/entities_card.dart index f2d1a24..3587ca5 100644 --- a/lib/ui_widgets/entities_card.dart +++ b/lib/ui_widgets/entities_card.dart @@ -30,7 +30,7 @@ class EntitiesCardWidget extends StatelessWidget { Padding( padding: EdgeInsets.fromLTRB(0.0, Sizes.rowPadding, 0.0, Sizes.rowPadding), child: EntityModel( - entity: entity, + entityWrapper: entity, handleTap: true, child: entity.entity.buildDefaultWidget(context) ), diff --git a/lib/ui_widgets/glance_card.dart b/lib/ui_widgets/glance_card.dart index cfc094f..b6d7f1f 100644 --- a/lib/ui_widgets/glance_card.dart +++ b/lib/ui_widgets/glance_card.dart @@ -33,7 +33,7 @@ class GlanceCardWidget extends StatelessWidget { SizedBox( width: width / columnsCount, child: EntityModel( - entity: entity, + entityWrapper: entity, child: entity.entity.buildGlanceWidget(context, card.showName, card.showState), handleTap: true ), diff --git a/lib/ui_widgets/media_control_card.dart b/lib/ui_widgets/media_control_card.dart index 79d4f19..16988ed 100644 --- a/lib/ui_widgets/media_control_card.dart +++ b/lib/ui_widgets/media_control_card.dart @@ -17,7 +17,7 @@ class MediaControlCardWidget extends StatelessWidget { return Card( child: EntityModel( - entity: card.linkedEntity, + entityWrapper: card.linkedEntity, handleTap: null, child: MediaPlayerWidget() ) diff --git a/lib/ui_widgets/unsupported_card.dart b/lib/ui_widgets/unsupported_card.dart index 673cc87..06bdebf 100644 --- a/lib/ui_widgets/unsupported_card.dart +++ b/lib/ui_widgets/unsupported_card.dart @@ -33,7 +33,7 @@ class UnsupportedCardWidget extends StatelessWidget { Padding( padding: EdgeInsets.fromLTRB(0.0, Sizes.rowPadding, 0.0, Sizes.rowPadding), child: EntityModel( - entity: card.linkedEntity, + entityWrapper: card.linkedEntity, handleTap: true, child: card.linkedEntity.entity.buildDefaultWidget(context) ),