Cards parsing improvements

This commit is contained in:
Yegor Vialov 2020-04-26 22:46:37 +00:00
parent 4da3b40d55
commit 0dc12963f0
15 changed files with 219 additions and 463 deletions

View File

@ -1,16 +1,23 @@
part of '../main.dart'; part of '../main.dart';
class AlarmPanelCard extends StatelessWidget { class AlarmPanelCard extends StatelessWidget {
final HACard card; final AlarmPanelCardData card;
const AlarmPanelCard({Key key, this.card}) : super(key: key); const AlarmPanelCard({Key key, this.card}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (card.entity.entity.statelessType == StatelessEntityType.missed) {
return EntityModel(
entityWrapper: card.entity,
child: MissedEntityWidget(),
handleTap: false,
);
}
List<Widget> body = []; List<Widget> body = [];
body.add(CardHeader( body.add(CardHeader(
name: card.name ?? "", name: card.name ?? "",
subtitle: Text("${card.linkedEntityWrapper.entity.displayState}", subtitle: Text("${card.entity.entity.displayState}",
), ),
trailing: Row( trailing: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
@ -26,7 +33,7 @@ class AlarmPanelCard extends StatelessWidget {
alignment: Alignment.centerRight, alignment: Alignment.centerRight,
icon: Icon(MaterialDesignIcons.getIconDataFromIconName( icon: Icon(MaterialDesignIcons.getIconDataFromIconName(
"mdi:dots-vertical")), "mdi:dots-vertical")),
onPressed: () => eventBus.fire(new ShowEntityPageEvent(entity: card.linkedEntityWrapper.entity)) onPressed: () => eventBus.fire(new ShowEntityPageEvent(entity: card.entity.entity))
) )
) )
] ]
@ -40,7 +47,7 @@ class AlarmPanelCard extends StatelessWidget {
); );
return CardWrapper( return CardWrapper(
child: EntityModel( child: EntityModel(
entityWrapper: card.linkedEntityWrapper, entityWrapper: card.entity,
handleTap: null, handleTap: null,
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,

View File

@ -1,135 +1,17 @@
part of '../main.dart'; part of '../main.dart';
class HACard {
List<EntityWrapper> entities = [];
List<HACard> childCards = [];
EntityWrapper linkedEntityWrapper;
String name;
String id;
String type;
String icon;
bool showName;
bool showState;
bool showEmpty;
bool showHeaderToggle;
int columnsCount;
List stateFilter;
List states;
List conditions;
String content;
String unit;
int min;
int max;
int depth;
Map severity;
EntityUIAction action;
HACard({
this.name,
this.id,
this.linkedEntityWrapper,
this.columnsCount: 4,
this.showName: true,
this.showHeaderToggle: true,
this.showState: true,
this.stateFilter: const [],
this.showEmpty: true,
this.content,
this.states,
this.conditions: const [],
this.unit,
this.min,
this.max,
this.depth: 1,
this.severity,
this.icon,
@required this.type
}) {
if (this.columnsCount <= 0) {
this.columnsCount = 4;
}
}
List<EntityWrapper> getEntitiesToShow() {
return entities.where((entityWrapper) {
if (HomeAssistant().autoUi && entityWrapper.entity.isHidden) {
return false;
}
List currentStateFilter;
if (entityWrapper.stateFilter != null && entityWrapper.stateFilter.isNotEmpty) {
currentStateFilter = entityWrapper.stateFilter;
} else {
currentStateFilter = stateFilter;
}
bool showByFilter = currentStateFilter.isEmpty;
for (var allowedState in currentStateFilter) {
if (allowedState is String && allowedState == entityWrapper.entity.state) {
showByFilter = true;
break;
} else if (allowedState is Map) {
try {
var tmpVal = allowedState['attribute'] != null ? entityWrapper.entity.getAttribute(allowedState['attribute']) : entityWrapper.entity.state;
var valToCompareWith = allowedState['value'];
var valToCompare;
if (valToCompareWith is! String && tmpVal is String) {
valToCompare = double.tryParse(tmpVal);
} else {
valToCompare = tmpVal;
}
if (valToCompare != null) {
bool result;
switch (allowedState['operator']) {
case '<=': { result = valToCompare <= valToCompareWith;}
break;
case '<': { result = valToCompare < valToCompareWith;}
break;
case '>=': { result = valToCompare >= valToCompareWith;}
break;
case '>': { result = valToCompare > valToCompareWith;}
break;
case '!=': { result = valToCompare != valToCompareWith;}
break;
case 'regex': {
RegExp regExp = RegExp(valToCompareWith.toString());
result = regExp.hasMatch(valToCompare.toString());
}
break;
default: {
result = valToCompare == valToCompareWith;
}
}
if (result) {
showByFilter = true;
break;
}
}
} catch (e) {
Logger.e('Error filtering ${entityWrapper.entity.entityId} by $allowedState');
Logger.e('$e');
}
}
}
return showByFilter;
}).toList();
}
}
class CardData { class CardData {
String type; String type;
final int depth; final int depth;
List<EntityWrapper> entities = []; List<EntityWrapper> entities = [];
List conditions; List conditions;
bool showEmapty; bool showEmpty;
List stateFilter; List stateFilter;
factory CardData.parse(Map<String, dynamic> rawData, {depth}) { EntityWrapper get entity => entities.isNotEmpty ? entities[0] : null;
factory CardData.parse(Map<String, dynamic> rawData, {depth: 1}) {
switch (rawData['type']) { switch (rawData['type']) {
case CardType.ENTITIES: case CardType.ENTITIES:
return EntitiesCardData(rawData, depth: depth); return EntitiesCardData(rawData, depth: depth);
@ -167,19 +49,34 @@ class CardData {
case CardType.VERTICAL_STACK: case CardType.VERTICAL_STACK:
return VerticalStackCardData(rawData, depth: depth); return VerticalStackCardData(rawData, depth: depth);
break; break;
case CardType.MARKDOWN:
return MarkdownCardData(rawData, depth: depth);
break;
case CardType.MEDIA_CONTROL:
return MediaControlCardData(rawData, depth: depth);
break;
default: default:
//TODO check for 'entity' and 'entities' if (rawData.containsKey('entities')) {
return EntitiesCardData(rawData, depth: depth); return EntitiesCardData(rawData, depth: depth);
} else if (rawData.containsKey('entity')) {
rawData['entities'] = [rawData['entity']];
return EntitiesCardData(rawData, depth: depth);
}
return CardData(rawData, depth: depth);
} }
} }
CardData(Map<String, dynamic> rawData, {this.depth: 1}) { CardData(Map<String, dynamic> rawData, {this.depth: 1}) {
type = rawData['type'] ?? CardType.ENTITIES; type = rawData['type'] ?? CardType.ENTITIES;
conditions = rawData['conditions']; conditions = rawData['conditions'] ?? [];
showEmapty = rawData['show_empty'] ?? true; showEmpty = rawData['show_empty'] ?? true;
stateFilter = rawData['state_filter'] ?? []; stateFilter = rawData['state_filter'] ?? [];
} }
Widget buildCardWidget() {
return UnsupportedCard(card: this);
}
List<EntityWrapper> getEntitiesToShow() { List<EntityWrapper> getEntitiesToShow() {
return entities.where((entityWrapper) { return entities.where((entityWrapper) {
if (HomeAssistant().autoUi && entityWrapper.entity.isHidden) { if (HomeAssistant().autoUi && entityWrapper.entity.isHidden) {
@ -258,6 +155,11 @@ class EntitiesCardData extends CardData {
bool showHeaderToggle; bool showHeaderToggle;
bool stateColor; bool stateColor;
@override
Widget buildCardWidget() {
return EntitiesCard(card: this);
}
EntitiesCardData(Map<String, dynamic> rawData, {int depth: 1}) : super(rawData, depth: depth) { EntitiesCardData(Map<String, dynamic> rawData, {int depth: 1}) : super(rawData, depth: depth) {
//Parsing card data //Parsing card data
title = rawData["title"]; title = rawData["title"];
@ -338,7 +240,12 @@ class EntitiesCardData extends CardData {
class AlarmPanelCardData extends CardData { class AlarmPanelCardData extends CardData {
String name; String name;
List<String> states; List<dynamic> states;
@override
Widget buildCardWidget() {
return AlarmPanelCard(card: this);
}
AlarmPanelCardData(Map<String, dynamic> rawData, {int depth: 1}) : super(rawData, depth: depth) { AlarmPanelCardData(Map<String, dynamic> rawData, {int depth: 1}) : super(rawData, depth: depth) {
//Parsing card data //Parsing card data
@ -368,12 +275,17 @@ class ButtonCardData extends CardData {
bool showName; bool showName;
bool showIcon; bool showIcon;
@override
Widget buildCardWidget() {
return EntityButtonCard(card: this);
}
ButtonCardData(Map<String, dynamic> rawData, {int depth: 1}) : super(rawData, depth: depth) { ButtonCardData(Map<String, dynamic> rawData, {int depth: 1}) : super(rawData, depth: depth) {
//Parsing card data //Parsing card data
name = rawData['name']; name = rawData['name'];
icon = rawData['icon']; icon = rawData['icon'];
showName = rawData['show_name']; showName = rawData['show_name'] ?? true;
showIcon = rawData['show_icon']; showIcon = rawData['show_icon'] ?? true;
//Parsing entity //Parsing entity
var entitiId = rawData["entity"]; var entitiId = rawData["entity"];
if (entitiId != null && entitiId is String) { if (entitiId != null && entitiId is String) {
@ -413,6 +325,11 @@ class GaugeCardData extends CardData {
int max; int max;
Map severity; Map severity;
@override
Widget buildCardWidget() {
return GaugeCard(card: this);
}
GaugeCardData(Map<String, dynamic> rawData, {int depth: 1}) : super(rawData, depth: depth) { GaugeCardData(Map<String, dynamic> rawData, {int depth: 1}) : super(rawData, depth: depth) {
//Parsing card data //Parsing card data
name = rawData['name']; name = rawData['name'];
@ -431,6 +348,8 @@ class GaugeCardData extends CardData {
} else { } else {
entities.add(EntityWrapper(entity: Entity.missed(entitiId))); entities.add(EntityWrapper(entity: Entity.missed(entitiId)));
} }
} else {
entities.add(EntityWrapper(entity: Entity.missed(entitiId)));
} }
} }
@ -446,6 +365,11 @@ class GlanceCardData extends CardData {
bool stateColor; bool stateColor;
int columnsCount; int columnsCount;
@override
Widget buildCardWidget() {
return GlanceCard(card: this);
}
GlanceCardData(Map<String, dynamic> rawData, {int depth: 1}) : super(rawData, depth: depth) { GlanceCardData(Map<String, dynamic> rawData, {int depth: 1}) : super(rawData, depth: depth) {
//Parsing card data //Parsing card data
title = rawData["title"]; title = rawData["title"];
@ -488,9 +412,14 @@ class HorizontalStackCardData extends CardData {
List<CardData> childCards; List<CardData> childCards;
@override
Widget buildCardWidget() {
return HorizontalStackCard(card: this);
}
HorizontalStackCardData(Map<String, dynamic> rawData, {int depth: 1}) : super(rawData, depth: depth) { HorizontalStackCardData(Map<String, dynamic> rawData, {int depth: 1}) : super(rawData, depth: depth) {
if (rawData.containsKey('cards')) { if (rawData.containsKey('cards')) {
childCards = rawData['cards'].map((childCard) { childCards = rawData['cards'].map<CardData>((childCard) {
return CardData.parse(childCard, depth: this.depth + 1); return CardData.parse(childCard, depth: this.depth + 1);
}).toList(); }).toList();
} else { } else {
@ -504,9 +433,14 @@ class VerticalStackCardData extends CardData {
List<CardData> childCards; List<CardData> childCards;
@override
Widget buildCardWidget() {
return VerticalStackCard(card: this);
}
VerticalStackCardData(Map<String, dynamic> rawData, {int depth: 1}) : super(rawData, depth: depth) { VerticalStackCardData(Map<String, dynamic> rawData, {int depth: 1}) : super(rawData, depth: depth) {
if (rawData.containsKey('cards')) { if (rawData.containsKey('cards')) {
childCards = rawData['cards'].map((childCard) { childCards = rawData['cards'].map<CardData>((childCard) {
return CardData.parse(childCard); return CardData.parse(childCard);
}).toList(); }).toList();
} else { } else {
@ -515,3 +449,43 @@ class VerticalStackCardData extends CardData {
} }
} }
class MarkdownCardData extends CardData {
String title;
String content;
@override
Widget buildCardWidget() {
return MarkdownCard(card: this);
}
MarkdownCardData(Map<String, dynamic> rawData, {int depth: 1}) : super(rawData, depth: depth) {
//Parsing card data
title = rawData['title'];
content = rawData['content'];
}
}
class MediaControlCardData extends CardData {
@override
Widget buildCardWidget() {
return MediaControlsCard(card: this);
}
MediaControlCardData(Map<String, dynamic> rawData, {int depth: 1}) : super(rawData, depth: depth) {
var entitiId = rawData["entity"];
if (entitiId != null && entitiId is String) {
if (HomeAssistant().entities.isExist(entitiId)) {
entities.add(EntityWrapper(
entity: HomeAssistant().entities.get(entitiId),
));
} else {
entities.add(EntityWrapper(entity: Entity.missed(entitiId)));
}
}
}
}

View File

@ -1,97 +0,0 @@
part of '../main.dart';
class LovelaceCard extends StatelessWidget {
final HACard card;
const LovelaceCard({
Key key,
this.card
}) : super(key: key);
@override
Widget build(BuildContext context) {
if (card.linkedEntityWrapper!= null) {
if (card.linkedEntityWrapper.entity.isHidden) {
return Container(width: 0.0, height: 0.0,);
}
if (card.linkedEntityWrapper.entity.statelessType == StatelessEntityType.missed) {
return EntityModel(
entityWrapper: card.linkedEntityWrapper,
child: MissedEntityWidget(),
handleTap: false,
);
}
}
if (card.conditions.isNotEmpty) {
bool showCardByConditions = true;
for (var condition in card.conditions) {
Entity conditionEntity = HomeAssistant().entities.get(condition['entity']);
if (conditionEntity != null &&
((condition['state'] != null && conditionEntity.state != condition['state']) ||
(condition['state_not'] != null && conditionEntity.state == condition['state_not']))
) {
showCardByConditions = false;
break;
}
}
if (!showCardByConditions) {
return Container(width: 0.0, height: 0.0,);
}
}
switch (card.type) {
case CardType.ENTITIES: {
return EntitiesCard(card: card);
}
case CardType.GLANCE: {
return GlanceCard(card: card);
}
case CardType.MEDIA_CONTROL: {
return MediaControlsCard(card: card);
}
case CardType.ENTITY_BUTTON: {
return EntityButtonCard(card: card);
}
case CardType.BUTTON: {
return EntityButtonCard(card: card);
}
case CardType.GAUGE: {
return GaugeCard(card: card);
}
case CardType.MARKDOWN: {
return MarkdownCard(card: card);
}
case CardType.ALARM_PANEL: {
return AlarmPanelCard(card: card);
}
case CardType.HORIZONTAL_STACK: {
return HorizontalStackCard(card: card);
}
case CardType.VERTICAL_STACK: {
return VerticalStackCard(card: card);
}
default: {
if ((card.linkedEntityWrapper == null) && (card.entities.isNotEmpty)) {
return EntitiesCard(card: card);
} else {
return UnsupportedCard(card: card);
}
}
}
}
}

View File

@ -1,7 +1,7 @@
part of '../main.dart'; part of '../main.dart';
class EntitiesCard extends StatelessWidget { class EntitiesCard extends StatelessWidget {
final HACard card; final EntitiesCardData card;
const EntitiesCard({Key key, this.card}) : super(key: key); const EntitiesCard({Key key, this.card}) : super(key: key);
@ -35,7 +35,7 @@ class EntitiesCard extends StatelessWidget {
} }
body.add( body.add(
CardHeader( CardHeader(
name: card.name, name: card.title,
trailing: headerSwitch, trailing: headerSwitch,
emptyPadding: Sizes.rowPadding, emptyPadding: Sizes.rowPadding,
leading: card.icon != null ? Icon( leading: card.icon != null ? Icon(
@ -64,10 +64,12 @@ class EntitiesCard extends StatelessWidget {
left: Sizes.leftWidgetPadding, left: Sizes.leftWidgetPadding,
bottom: Sizes.rowPadding, bottom: Sizes.rowPadding,
), ),
child: Center(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: body children: body
)
), ),
) )
); );

View File

@ -2,7 +2,7 @@ part of '../main.dart';
class EntityButtonCard extends StatelessWidget { class EntityButtonCard extends StatelessWidget {
final HACard card; final ButtonCardData card;
EntityButtonCard({ EntityButtonCard({
Key key, this.card Key key, this.card
@ -10,18 +10,20 @@ class EntityButtonCard extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
//card.linkedEntityWrapper.overrideName = card.name?.toUpperCase() ?? EntityWrapper entityWrapper = card.entity;
// card.linkedEntityWrapper.displayName.toUpperCase();
EntityWrapper entityWrapper = card.linkedEntityWrapper;
if (entityWrapper.entity.statelessType == StatelessEntityType.missed) { if (entityWrapper.entity.statelessType == StatelessEntityType.missed) {
return MissedEntityWidget(); return EntityModel(
entityWrapper: card.entity,
child: MissedEntityWidget(),
handleTap: false,
);
} else if (entityWrapper.entity.statelessType != StatelessEntityType.ghost && entityWrapper.entity.statelessType != StatelessEntityType.none) { } else if (entityWrapper.entity.statelessType != StatelessEntityType.ghost && entityWrapper.entity.statelessType != StatelessEntityType.none) {
return Container(width: 0.0, height: 0.0,); return Container(width: 0.0, height: 0.0,);
} }
double widthBase = math.min(MediaQuery.of(context).size.width, MediaQuery.of(context).size.height) / 6; double widthBase = math.min(MediaQuery.of(context).size.width, MediaQuery.of(context).size.height) / 6;
Widget buttonIcon; Widget buttonIcon;
if (entityWrapper.icon == null || entityWrapper.icon.isEmpty) { if (!card.showIcon) {
buttonIcon = Container(height: Sizes.rowPadding, width: 10); buttonIcon = Container(height: Sizes.rowPadding, width: 10);
} else { } else {
buttonIcon = EntityIcon( buttonIcon = EntityIcon(
@ -32,12 +34,12 @@ class EntityButtonCard extends StatelessWidget {
return CardWrapper( return CardWrapper(
child: EntityModel( child: EntityModel(
entityWrapper: card.linkedEntityWrapper, entityWrapper: card.entity,
child: InkWell( child: InkWell(
onTap: () => entityWrapper.handleTap(), onTap: () => entityWrapper.handleTap(),
onLongPress: () => entityWrapper.handleHold(), onLongPress: () => entityWrapper.handleHold(),
onDoubleTap: () => entityWrapper.handleDoubleTap(), onDoubleTap: () => entityWrapper.handleDoubleTap(),
child: Container( child: Center(
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,

View File

@ -2,18 +2,24 @@ part of '../main.dart';
class GaugeCard extends StatelessWidget { class GaugeCard extends StatelessWidget {
final HACard card; final GaugeCardData card;
GaugeCard({Key key, this.card}) : super(key: key); GaugeCard({Key key, this.card}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
EntityWrapper entityWrapper = card.linkedEntityWrapper; EntityWrapper entityWrapper = card.entity;
if (entityWrapper.entity.statelessType == StatelessEntityType.missed) {
return EntityModel(
entityWrapper: card.entity,
child: MissedEntityWidget(),
handleTap: false,
);
}
entityWrapper.overrideName = card.name ?? entityWrapper.overrideName = card.name ??
entityWrapper.displayName; entityWrapper.displayName;
entityWrapper.unitOfMeasurementOverride = card.unit ?? entityWrapper.unitOfMeasurementOverride = card.unit ??
entityWrapper.unitOfMeasurement; entityWrapper.unitOfMeasurement;
double fixedValue; double fixedValue;
double value = entityWrapper.entity.doubleState; double value = entityWrapper.entity.doubleState;
if (value > card.max) { if (value > card.max) {

View File

@ -1,7 +1,7 @@
part of '../main.dart'; part of '../main.dart';
class GlanceCard extends StatelessWidget { class GlanceCard extends StatelessWidget {
final HACard card; final GlanceCardData card;
const GlanceCard({Key key, this.card}) : super(key: key); const GlanceCard({Key key, this.card}) : super(key: key);
@ -12,8 +12,15 @@ class GlanceCard extends StatelessWidget {
return Container(height: 0.0, width: 0.0,); return Container(height: 0.0, width: 0.0,);
} }
int length = entitiesToShow.length; int length = entitiesToShow.length;
int columnsCount = length >= card.columnsCount ? card.columnsCount : entitiesToShow.length; int rowsCount;
int rowsCount = (length / columnsCount).round(); int columnsCount;
if (length == 0) {
columnsCount = 0;
rowsCount = 0;
} else {
columnsCount = length >= card.columnsCount ? card.columnsCount : entitiesToShow.length;
rowsCount = (length / columnsCount).round();
}
List<TableRow> rows = []; List<TableRow> rows = [];
for (int i = 0; i < rowsCount; i++) { for (int i = 0; i < rowsCount; i++) {
int start = i*columnsCount; int start = i*columnsCount;
@ -46,7 +53,7 @@ class GlanceCard extends StatelessWidget {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[
CardHeader(name: card.name), CardHeader(name: card.title),
Padding( Padding(
padding: EdgeInsets.symmetric(vertical: Sizes.rowPadding), padding: EdgeInsets.symmetric(vertical: Sizes.rowPadding),
child: Table( child: Table(

View File

@ -1,7 +1,7 @@
part of '../main.dart'; part of '../main.dart';
class HorizontalStackCard extends StatelessWidget { class HorizontalStackCard extends StatelessWidget {
final HACard card; final HorizontalStackCardData card;
const HorizontalStackCard({Key key, this.card}) : super(key: key); const HorizontalStackCard({Key key, this.card}) : super(key: key);
@ -11,7 +11,7 @@ class HorizontalStackCard extends StatelessWidget {
List<Widget> children = []; List<Widget> children = [];
children = card.childCards.map((childCard) => Flexible( children = card.childCards.map((childCard) => Flexible(
fit: FlexFit.tight, fit: FlexFit.tight,
child: LovelaceCard(card: childCard) child: childCard.buildCardWidget()
) )
).toList(); ).toList();
return IntrinsicHeight( return IntrinsicHeight(

View File

@ -1,7 +1,7 @@
part of '../main.dart'; part of '../main.dart';
class MarkdownCard extends StatelessWidget { class MarkdownCard extends StatelessWidget {
final HACard card; final MarkdownCardData card;
const MarkdownCard({Key key, this.card}) : super(key: key); const MarkdownCard({Key key, this.card}) : super(key: key);
@ -19,7 +19,7 @@ class MarkdownCard extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[ children: <Widget>[
CardHeader(name: card.name), CardHeader(name: card.title),
MarkdownBody( MarkdownBody(
data: card.content, data: card.content,
) )

View File

@ -1,15 +1,22 @@
part of '../main.dart'; part of '../main.dart';
class MediaControlsCard extends StatelessWidget { class MediaControlsCard extends StatelessWidget {
final HACard card; final MediaControlCardData card;
const MediaControlsCard({Key key, this.card}) : super(key: key); const MediaControlsCard({Key key, this.card}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (card.entity.entity.statelessType == StatelessEntityType.missed) {
return EntityModel(
entityWrapper: card.entity,
child: MissedEntityWidget(),
handleTap: false,
);
}
return CardWrapper( return CardWrapper(
child: EntityModel( child: EntityModel(
entityWrapper: card.linkedEntityWrapper, entityWrapper: card.entity,
handleTap: null, handleTap: null,
child: MediaPlayerWidget() child: MediaPlayerWidget()
) )

View File

@ -1,47 +1,17 @@
part of '../main.dart'; part of '../main.dart';
class UnsupportedCard extends StatelessWidget { class UnsupportedCard extends StatelessWidget {
final HACard card; final CardData card;
const UnsupportedCard({Key key, this.card}) : super(key: key); const UnsupportedCard({Key key, this.card}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
List<Widget> body = []; return CardWrapper(
body.add( child: Padding(
CardHeader(
name: card.name ?? ""
)
);
List<Widget> result = [];
if (card.linkedEntityWrapper != null) {
result.addAll(<Widget>[
Padding(
padding: EdgeInsets.fromLTRB(0.0, Sizes.rowPadding, 0.0, Sizes.rowPadding),
child: EntityModel(
entityWrapper: card.linkedEntityWrapper,
handleTap: true,
child: card.linkedEntityWrapper.entity.buildDefaultWidget(context)
),
)
]);
} else {
result.addAll(<Widget>[
Padding(
padding: EdgeInsets.fromLTRB(Sizes.leftWidgetPadding, Sizes.rowPadding, Sizes.rightWidgetPadding, Sizes.rowPadding), padding: EdgeInsets.fromLTRB(Sizes.leftWidgetPadding, Sizes.rowPadding, Sizes.rightWidgetPadding, Sizes.rowPadding),
child: Text("'${card.type}' card is not supported yet"), child: Text("'${card.type}' card is not supported yet"),
),
]);
}
body.addAll(result);
return CardWrapper(
child: new Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: body
) )
); );
} }
} }

View File

@ -1,7 +1,7 @@
part of '../main.dart'; part of '../main.dart';
class VerticalStackCard extends StatelessWidget { class VerticalStackCard extends StatelessWidget {
final HACard card; final VerticalStackCardData card;
const VerticalStackCard({Key key, this.card}) : super(key: key); const VerticalStackCard({Key key, this.card}) : super(key: key);
@ -11,8 +11,8 @@ class VerticalStackCard extends StatelessWidget {
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: card.childCards.map( children: card.childCards.map<Widget>(
(childCard) => LovelaceCard(card: childCard) (childCard) => childCard.buildCardWidget()
).toList(), ).toList(),
); );
} }

View File

@ -129,7 +129,6 @@ part 'view.class.dart';
part 'cards/card.class.dart'; part 'cards/card.class.dart';
part 'panels/panel_class.dart'; part 'panels/panel_class.dart';
part 'viewWidget.widget.dart'; part 'viewWidget.widget.dart';
part 'cards/card_widget.dart';
part 'cards/widgets/card_header.widget.dart'; part 'cards/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';

View File

@ -1,7 +1,7 @@
part of 'main.dart'; part of 'main.dart';
class HAView { class HAView {
List<HACard> cards = []; List<CardData> cards = [];
List<Entity> badges = []; List<Entity> badges = [];
Entity linkedEntity; Entity linkedEntity;
String name; String name;
@ -33,150 +33,11 @@ class HAView {
}); });
} }
cards.addAll(_createLovelaceCards(rawData["cards"] ?? [], 1)); (rawData["cards"] ?? []).forEach((rawCardData) {
} cards.add(CardData.parse(rawCardData));
});
List<HACard> _createLovelaceCards(List rawCards, int depth) { //cards.addAll(_createLovelaceCards(rawData["cards"] ?? [], 1));
List<HACard> result = [];
rawCards.forEach((rawCard){
try {
//bool isThereCardOptionsInside = rawCard["card"] != null;
var rawCardInfo = rawCard["card"] ?? rawCard;
HACard card = HACard(
id: "card",
name: rawCardInfo["title"] ?? rawCardInfo["name"],
type: rawCardInfo['type'] ?? CardType.ENTITIES,
icon: rawCardInfo['icon'],
columnsCount: rawCardInfo['columns'] ?? 4,
showName: (rawCardInfo['show_name'] ?? rawCard['show_name']) ?? true,
showHeaderToggle: (rawCardInfo['show_header_toggle'] ?? rawCard['show_header_toggle']) ?? false,
showState: (rawCardInfo['show_state'] ?? rawCard['show_state']) ?? true,
showEmpty: (rawCardInfo['show_empty'] ?? rawCard['show_empty']) ?? true,
stateFilter: (rawCard['state_filter'] ?? rawCardInfo['state_filter']) ?? [],
states: rawCardInfo['states'],
conditions: rawCard['conditions'] ?? [],
content: rawCardInfo['content'],
min: rawCardInfo['min'] ?? 0,
max: rawCardInfo['max'] ?? 100,
unit: rawCardInfo['unit'],
depth: depth,
severity: rawCardInfo['severity']
);
if (rawCardInfo["cards"] != null) {
card.childCards = _createLovelaceCards(rawCardInfo["cards"], depth + 1);
}
var rawEntities = rawCard["entities"] ?? rawCardInfo["entities"];
var rawSingleEntity = rawCard["entity"] ?? rawCardInfo["entity"];
if (rawEntities != null) {
rawEntities.forEach((rawEntity) {
if (rawEntity is String) {
if (HomeAssistant().entities.isExist(rawEntity)) {
card.entities.add(EntityWrapper(entity: HomeAssistant().entities.get(rawEntity)));
} else {
card.entities.add(EntityWrapper(entity: Entity.missed(rawEntity)));
}
} else {
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 (HomeAssistant().entities.isExist(rawEntity["entity"])) {
Entity e = HomeAssistant().entities.get(rawEntity["entity"]);
card.entities.add(
EntityWrapper(
entity: e,
overrideName: rawEntity["name"],
overrideIcon: rawEntity["icon"],
stateFilter: rawEntity['state_filter'] ?? [],
uiAction: EntityUIAction(rawEntityData: rawEntity)
)
);
} else {
card.entities.add(EntityWrapper(entity: Entity.missed(rawEntity["entity"])));
}
}
});
} else if (rawSingleEntity != null) {
var en = rawSingleEntity;
if (en is String) {
if (HomeAssistant().entities.isExist(en)) {
Entity e = HomeAssistant().entities.get(en);
card.linkedEntityWrapper = EntityWrapper(
entity: e,
overrideIcon: rawCardInfo["icon"],
overrideName: rawCardInfo["name"],
uiAction: EntityUIAction(rawEntityData: rawCard)
);
} else {
card.linkedEntityWrapper = EntityWrapper(entity: Entity.missed(en));
}
} else {
if (HomeAssistant().entities.isExist(en["entity"])) {
Entity e = HomeAssistant().entities.get(en["entity"]);
card.linkedEntityWrapper = EntityWrapper(
entity: e,
overrideIcon: en["icon"],
overrideName: en["name"],
stateFilter: en['state_filter'] ?? [],
uiAction: EntityUIAction(rawEntityData: rawCard)
);
} else {
card.linkedEntityWrapper = EntityWrapper(entity: Entity.missed(en["entity"]));
}
}
} else {
card.linkedEntityWrapper = EntityWrapper(
entity: Entity.ghost(
card.name,
card.icon,
),
uiAction: EntityUIAction(
rawEntityData: rawCardInfo
)
);
}
result.add(card);
} catch (e) {
Logger.e("There was an error parsing card: ${e.toString()}");
}
});
return result;
} }
Widget buildTab() { Widget buildTab() {

View File

@ -21,7 +21,25 @@ class ViewWidget extends StatelessWidget {
if (this.view.cards.isNotEmpty) { if (this.view.cards.isNotEmpty) {
cardsContainer = DynamicMultiColumnLayout( cardsContainer = DynamicMultiColumnLayout(
minColumnWidth: Sizes.minViewColumnWidth, minColumnWidth: Sizes.minViewColumnWidth,
children: this.view.cards.map((card) => LovelaceCard(card: card)).toList(), children: this.view.cards.map((card) {
if (card.conditions.isNotEmpty) {
bool showCardByConditions = true;
for (var condition in card.conditions) {
Entity conditionEntity = HomeAssistant().entities.get(condition['entity']);
if (conditionEntity != null &&
((condition['state'] != null && conditionEntity.state != condition['state']) ||
(condition['state_not'] != null && conditionEntity.state == condition['state_not']))
) {
showCardByConditions = false;
break;
}
}
if (!showCardByConditions) {
return Container(width: 0.0, height: 0.0,);
}
}
return card.buildCardWidget();
}).toList(),
); );
} else { } else {
cardsContainer = Container(); cardsContainer = Container();
@ -39,7 +57,7 @@ class ViewWidget extends StatelessWidget {
Widget _buildPanelChild(BuildContext context) { Widget _buildPanelChild(BuildContext context) {
if (this.view.cards != null && this.view.cards.isNotEmpty) { if (this.view.cards != null && this.view.cards.isNotEmpty) {
return LovelaceCard(card: this.view.cards[0]); return this.view.cards[0].buildCardWidget();
} else { } else {
return Container(width: 0, height: 0); return Container(width: 0, height: 0);
} }