WIP: Cards build optimization
This commit is contained in:
parent
f488c0810b
commit
02bfaf7db6
55
lib/cards/alarm_panel_card.dart
Normal file
55
lib/cards/alarm_panel_card.dart
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
part of '../main.dart';
|
||||||
|
|
||||||
|
class AlarmPanelCard extends StatelessWidget {
|
||||||
|
final HACard card;
|
||||||
|
|
||||||
|
const AlarmPanelCard({Key key, this.card}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<Widget> body = [];
|
||||||
|
body.add(CardHeader(
|
||||||
|
name: card.name ?? "",
|
||||||
|
subtitle: Text("${card.linkedEntityWrapper.entity.displayState}",
|
||||||
|
),
|
||||||
|
trailing: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
EntityIcon(
|
||||||
|
size: 50.0,
|
||||||
|
),
|
||||||
|
Container(
|
||||||
|
width: 26.0,
|
||||||
|
child: IconButton(
|
||||||
|
padding: EdgeInsets.all(0.0),
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
icon: Icon(MaterialDesignIcons.getIconDataFromIconName(
|
||||||
|
"mdi:dots-vertical")),
|
||||||
|
onPressed: () => eventBus.fire(new ShowEntityPageEvent(entity: card.linkedEntityWrapper.entity))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
));
|
||||||
|
body.add(
|
||||||
|
AlarmControlPanelControlsWidget(
|
||||||
|
extended: true,
|
||||||
|
states: card.states,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return CardWrapper(
|
||||||
|
child: EntityModel(
|
||||||
|
entityWrapper: card.linkedEntityWrapper,
|
||||||
|
handleTap: null,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: body
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -116,10 +116,4 @@ class HACard {
|
|||||||
}).toList();
|
}).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return CardWidget(
|
|
||||||
card: this,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,10 +1,10 @@
|
|||||||
part of '../main.dart';
|
part of '../main.dart';
|
||||||
|
|
||||||
class CardWidget extends StatelessWidget {
|
class LovelaceCard extends StatelessWidget {
|
||||||
|
|
||||||
final HACard card;
|
final HACard card;
|
||||||
|
|
||||||
const CardWidget({
|
const LovelaceCard({
|
||||||
Key key,
|
Key key,
|
||||||
this.card
|
this.card
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@ -44,7 +44,7 @@ class CardWidget extends StatelessWidget {
|
|||||||
switch (card.type) {
|
switch (card.type) {
|
||||||
|
|
||||||
case CardType.ENTITIES: {
|
case CardType.ENTITIES: {
|
||||||
return _buildEntitiesCard(context);
|
return EntitiesCard(card: card);
|
||||||
}
|
}
|
||||||
|
|
||||||
case CardType.GLANCE: {
|
case CardType.GLANCE: {
|
||||||
@ -52,7 +52,7 @@ class CardWidget extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
case CardType.MEDIA_CONTROL: {
|
case CardType.MEDIA_CONTROL: {
|
||||||
return _buildMediaControlsCard(context);
|
return MediaControlsCard(card: card);
|
||||||
}
|
}
|
||||||
|
|
||||||
case CardType.ENTITY_BUTTON: {
|
case CardType.ENTITY_BUTTON: {
|
||||||
@ -67,227 +67,31 @@ class CardWidget extends StatelessWidget {
|
|||||||
return GaugeCard(card: card);
|
return GaugeCard(card: card);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* case CardType.LIGHT: {
|
|
||||||
return _buildLightCard(context);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
case CardType.MARKDOWN: {
|
case CardType.MARKDOWN: {
|
||||||
return _buildMarkdownCard(context);
|
return MarkdownCard(card: card);
|
||||||
}
|
}
|
||||||
|
|
||||||
case CardType.ALARM_PANEL: {
|
case CardType.ALARM_PANEL: {
|
||||||
return _buildAlarmPanelCard(context);
|
return AlarmPanelCard(card: card);
|
||||||
}
|
}
|
||||||
|
|
||||||
case CardType.HORIZONTAL_STACK: {
|
case CardType.HORIZONTAL_STACK: {
|
||||||
if (card.childCards.isNotEmpty) {
|
return HorizontalStackCard(card: card);
|
||||||
List<Widget> children = [];
|
|
||||||
children = card.childCards.map((childCard) => Flexible(
|
|
||||||
fit: FlexFit.tight,
|
|
||||||
child: childCard.build(context),
|
|
||||||
)
|
|
||||||
).toList();
|
|
||||||
return IntrinsicHeight(
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.max,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: children,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return Container(height: 0.0, width: 0.0,);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case CardType.VERTICAL_STACK: {
|
case CardType.VERTICAL_STACK: {
|
||||||
if (card.childCards.isNotEmpty) {
|
return VerticalStackCard(card: card);
|
||||||
List<Widget> children = card.childCards.map((childCard) => childCard.build(context)).toList();
|
|
||||||
return Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: children,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return Container(height: 0.0, width: 0.0,);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
if ((card.linkedEntityWrapper == null) && (card.entities.isNotEmpty)) {
|
if ((card.linkedEntityWrapper == null) && (card.entities.isNotEmpty)) {
|
||||||
return _buildEntitiesCard(context);
|
return EntitiesCard(card: card);
|
||||||
} else {
|
} else {
|
||||||
return _buildUnsupportedCard(context);
|
return UnsupportedCard(card: card);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildEntitiesCard(BuildContext context) {
|
|
||||||
List<EntityWrapper> entitiesToShow = card.getEntitiesToShow();
|
|
||||||
if (entitiesToShow.isEmpty && !card.showEmpty) {
|
|
||||||
return Container(height: 0.0, width: 0.0,);
|
|
||||||
}
|
|
||||||
List<Widget> body = [];
|
|
||||||
Widget headerSwitch;
|
|
||||||
if (card.showHeaderToggle) {
|
|
||||||
bool headerToggleVal = entitiesToShow.any((EntityWrapper en){ return en.entity.state == EntityState.on; });
|
|
||||||
List<String> entitiesToToggle = entitiesToShow.where((EntityWrapper enw) {
|
|
||||||
return <String>["switch", "light", "automation", "input_boolean"].contains(enw.entity.domain);
|
|
||||||
}).map((EntityWrapper en) {
|
|
||||||
return en.entity.entityId;
|
|
||||||
}).toList();
|
|
||||||
headerSwitch = Switch(
|
|
||||||
value: headerToggleVal,
|
|
||||||
onChanged: (val) {
|
|
||||||
if (entitiesToToggle.isNotEmpty) {
|
|
||||||
ConnectionManager().callService(
|
|
||||||
domain: "homeassistant",
|
|
||||||
service: val ? "turn_on" : "turn_off",
|
|
||||||
entityId: entitiesToToggle
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
body.add(
|
|
||||||
CardHeader(
|
|
||||||
name: card.name,
|
|
||||||
trailing: headerSwitch
|
|
||||||
)
|
|
||||||
);
|
|
||||||
body.addAll(
|
|
||||||
entitiesToShow.map((EntityWrapper entity) {
|
|
||||||
return Padding(
|
|
||||||
padding: EdgeInsets.fromLTRB(0.0, 4.0, 0.0, 4.0),
|
|
||||||
child: EntityModel(
|
|
||||||
entityWrapper: entity,
|
|
||||||
handleTap: true,
|
|
||||||
child: entity.entity.buildDefaultWidget(context)
|
|
||||||
),
|
|
||||||
);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
return CardWrapper(
|
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.only(
|
|
||||||
right: Sizes.rightWidgetPadding,
|
|
||||||
left: Sizes.leftWidgetPadding,
|
|
||||||
bottom: Sizes.rowPadding,
|
|
||||||
),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
|
||||||
children: body
|
|
||||||
),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildMarkdownCard(BuildContext context) {
|
|
||||||
if (card.content == null) {
|
|
||||||
return Container(height: 0.0, width: 0.0,);
|
|
||||||
}
|
|
||||||
List<Widget> body = [];
|
|
||||||
body.add(CardHeader(name: card.name));
|
|
||||||
body.add(MarkdownBody(data: card.content));
|
|
||||||
return CardWrapper(
|
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.fromLTRB(Sizes.leftWidgetPadding, Sizes.rowPadding, Sizes.rightWidgetPadding, Sizes.rowPadding),
|
|
||||||
child: new Column(mainAxisSize: MainAxisSize.min, children: body),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildAlarmPanelCard(BuildContext context) {
|
|
||||||
List<Widget> body = [];
|
|
||||||
body.add(CardHeader(
|
|
||||||
name: card.name ?? "",
|
|
||||||
subtitle: Text("${card.linkedEntityWrapper.entity.displayState}",
|
|
||||||
),
|
|
||||||
trailing: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
|
||||||
children: [
|
|
||||||
EntityIcon(
|
|
||||||
size: 50.0,
|
|
||||||
),
|
|
||||||
Container(
|
|
||||||
width: 26.0,
|
|
||||||
child: IconButton(
|
|
||||||
padding: EdgeInsets.all(0.0),
|
|
||||||
alignment: Alignment.centerRight,
|
|
||||||
icon: Icon(MaterialDesignIcons.getIconDataFromIconName(
|
|
||||||
"mdi:dots-vertical")),
|
|
||||||
onPressed: () => eventBus.fire(new ShowEntityPageEvent(entity: card.linkedEntityWrapper.entity))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
),
|
|
||||||
));
|
|
||||||
body.add(
|
|
||||||
AlarmControlPanelControlsWidget(
|
|
||||||
extended: true,
|
|
||||||
states: card.states,
|
|
||||||
)
|
|
||||||
);
|
|
||||||
return CardWrapper(
|
|
||||||
child: EntityModel(
|
|
||||||
entityWrapper: card.linkedEntityWrapper,
|
|
||||||
handleTap: null,
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: body
|
|
||||||
)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildMediaControlsCard(BuildContext context) {
|
|
||||||
return CardWrapper(
|
|
||||||
child: EntityModel(
|
|
||||||
entityWrapper: card.linkedEntityWrapper,
|
|
||||||
handleTap: null,
|
|
||||||
child: MediaPlayerWidget()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildUnsupportedCard(BuildContext context) {
|
|
||||||
List<Widget> body = [];
|
|
||||||
body.add(
|
|
||||||
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),
|
|
||||||
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
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
72
lib/cards/entities_card.dart
Normal file
72
lib/cards/entities_card.dart
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
part of '../main.dart';
|
||||||
|
|
||||||
|
class EntitiesCard extends StatelessWidget {
|
||||||
|
final HACard card;
|
||||||
|
|
||||||
|
const EntitiesCard({Key key, this.card}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<EntityWrapper> entitiesToShow = card.getEntitiesToShow();
|
||||||
|
if (entitiesToShow.isEmpty && !card.showEmpty) {
|
||||||
|
return Container(height: 0.0, width: 0.0,);
|
||||||
|
}
|
||||||
|
List<Widget> body = [];
|
||||||
|
Widget headerSwitch;
|
||||||
|
if (card.showHeaderToggle) {
|
||||||
|
bool headerToggleVal = entitiesToShow.any((EntityWrapper en){ return en.entity.state == EntityState.on; });
|
||||||
|
List<String> entitiesToToggle = entitiesToShow.where((EntityWrapper enw) {
|
||||||
|
return <String>["switch", "light", "automation", "input_boolean"].contains(enw.entity.domain);
|
||||||
|
}).map((EntityWrapper en) {
|
||||||
|
return en.entity.entityId;
|
||||||
|
}).toList();
|
||||||
|
headerSwitch = Switch(
|
||||||
|
value: headerToggleVal,
|
||||||
|
onChanged: (val) {
|
||||||
|
if (entitiesToToggle.isNotEmpty) {
|
||||||
|
ConnectionManager().callService(
|
||||||
|
domain: "homeassistant",
|
||||||
|
service: val ? "turn_on" : "turn_off",
|
||||||
|
entityId: entitiesToToggle
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
body.add(
|
||||||
|
CardHeader(
|
||||||
|
name: card.name,
|
||||||
|
trailing: headerSwitch,
|
||||||
|
emptyPadding: Sizes.rowPadding
|
||||||
|
)
|
||||||
|
);
|
||||||
|
body.addAll(
|
||||||
|
entitiesToShow.map((EntityWrapper entity) {
|
||||||
|
return Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(0.0, 4.0, 0.0, 4.0),
|
||||||
|
child: EntityModel(
|
||||||
|
entityWrapper: entity,
|
||||||
|
handleTap: true,
|
||||||
|
child: entity.entity.buildDefaultWidget(context)
|
||||||
|
),
|
||||||
|
);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
return CardWrapper(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
right: Sizes.rightWidgetPadding,
|
||||||
|
left: Sizes.leftWidgetPadding,
|
||||||
|
bottom: Sizes.rowPadding,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: body
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
30
lib/cards/horizontal_srack_card.dart
Normal file
30
lib/cards/horizontal_srack_card.dart
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
part of '../main.dart';
|
||||||
|
|
||||||
|
class HorizontalStackCard extends StatelessWidget {
|
||||||
|
final HACard card;
|
||||||
|
|
||||||
|
const HorizontalStackCard({Key key, this.card}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (card.childCards.isNotEmpty) {
|
||||||
|
List<Widget> children = [];
|
||||||
|
children = card.childCards.map((childCard) => Flexible(
|
||||||
|
fit: FlexFit.tight,
|
||||||
|
child: LovelaceCard(card: childCard)
|
||||||
|
)
|
||||||
|
).toList();
|
||||||
|
return IntrinsicHeight(
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: children,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Container(height: 0.0, width: 0.0,);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
31
lib/cards/markdown_card.dart
Normal file
31
lib/cards/markdown_card.dart
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
part of '../main.dart';
|
||||||
|
|
||||||
|
class MarkdownCard extends StatelessWidget {
|
||||||
|
final HACard card;
|
||||||
|
|
||||||
|
const MarkdownCard({Key key, this.card}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (card.content == null) {
|
||||||
|
return Container(height: 0.0, width: 0.0,);
|
||||||
|
}
|
||||||
|
return CardWrapper(
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(Sizes.leftWidgetPadding, Sizes.rowPadding, Sizes.rightWidgetPadding, Sizes.rowPadding),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: <Widget>[
|
||||||
|
CardHeader(name: card.name),
|
||||||
|
MarkdownBody(
|
||||||
|
data: card.content,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
20
lib/cards/media_control_card.dart
Normal file
20
lib/cards/media_control_card.dart
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
part of '../main.dart';
|
||||||
|
|
||||||
|
class MediaControlsCard extends StatelessWidget {
|
||||||
|
final HACard card;
|
||||||
|
|
||||||
|
const MediaControlsCard({Key key, this.card}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return CardWrapper(
|
||||||
|
child: EntityModel(
|
||||||
|
entityWrapper: card.linkedEntityWrapper,
|
||||||
|
handleTap: null,
|
||||||
|
child: MediaPlayerWidget()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
47
lib/cards/unsupported_card.dart
Normal file
47
lib/cards/unsupported_card.dart
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
part of '../main.dart';
|
||||||
|
|
||||||
|
class UnsupportedCard extends StatelessWidget {
|
||||||
|
final HACard card;
|
||||||
|
|
||||||
|
const UnsupportedCard({Key key, this.card}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
List<Widget> body = [];
|
||||||
|
body.add(
|
||||||
|
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),
|
||||||
|
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
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
23
lib/cards/vertical_stack_card.dart
Normal file
23
lib/cards/vertical_stack_card.dart
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
part of '../main.dart';
|
||||||
|
|
||||||
|
class VerticalStackCard extends StatelessWidget {
|
||||||
|
final HACard card;
|
||||||
|
|
||||||
|
const VerticalStackCard({Key key, this.card}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
if (card.childCards.isNotEmpty) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
|
children: card.childCards.map(
|
||||||
|
(childCard) => LovelaceCard(card: childCard)
|
||||||
|
).toList(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return Container(height: 0.0, width: 0.0,);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -5,8 +5,9 @@ class CardHeader extends StatelessWidget {
|
|||||||
final String name;
|
final String name;
|
||||||
final Widget trailing;
|
final Widget trailing;
|
||||||
final Widget subtitle;
|
final Widget subtitle;
|
||||||
|
final double emptyPadding;
|
||||||
|
|
||||||
const CardHeader({Key key, this.name, this.trailing, this.subtitle}) : super(key: key);
|
const CardHeader({Key key, this.name, this.emptyPadding: 0, this.trailing, this.subtitle}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -21,7 +22,7 @@ class CardHeader extends StatelessWidget {
|
|||||||
style: Theme.of(context).textTheme.headline),
|
style: Theme.of(context).textTheme.headline),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
result = new Container(width: 0.0, height: Sizes.rowPadding);
|
result = new Container(width: 0.0, height: emptyPadding);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ class Entity {
|
|||||||
String entityPicture;
|
String entityPicture;
|
||||||
String state;
|
String state;
|
||||||
String displayState;
|
String displayState;
|
||||||
DateTime _lastUpdated;
|
DateTime lastUpdatedTimestamp;
|
||||||
int statelessType = 0;
|
int statelessType = 0;
|
||||||
|
|
||||||
List<Entity> childEntities = [];
|
List<Entity> childEntities = [];
|
||||||
@ -144,7 +144,7 @@ class Entity {
|
|||||||
|
|
||||||
Entity.weblink({String url, String name, String icon}) {
|
Entity.weblink({String url, String name, String icon}) {
|
||||||
statelessType = StatelessEntityType.WEBLINK;
|
statelessType = StatelessEntityType.WEBLINK;
|
||||||
entityId = "custom.custom"; //TODO wtf??
|
entityId = "custom.custom";
|
||||||
attributes = {"hidden": false, "friendly_name": "${name ?? url}", "icon": "${icon ?? 'mdi:link'}"};
|
attributes = {"hidden": false, "friendly_name": "${name ?? url}", "icon": "${icon ?? 'mdi:link'}"};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +155,7 @@ class Entity {
|
|||||||
deviceClass = attributes["device_class"];
|
deviceClass = attributes["device_class"];
|
||||||
state = rawData["state"] is bool ? (rawData["state"] ? EntityState.on : EntityState.off) : rawData["state"];
|
state = rawData["state"] is bool ? (rawData["state"] ? EntityState.on : EntityState.off) : rawData["state"];
|
||||||
displayState = Entity.StateByDeviceClass["$deviceClass.$state"] ?? (state.toLowerCase() == 'unknown' ? '-' : state);
|
displayState = Entity.StateByDeviceClass["$deviceClass.$state"] ?? (state.toLowerCase() == 'unknown' ? '-' : state);
|
||||||
_lastUpdated = DateTime.tryParse(rawData["last_updated"]);
|
lastUpdatedTimestamp = DateTime.tryParse(rawData["last_updated"]);
|
||||||
entityPicture = _getEntityPictureUrl(webHost);
|
entityPicture = _getEntityPictureUrl(webHost);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,11 +227,11 @@ class Entity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _getLastUpdatedFormatted() {
|
String _getLastUpdatedFormatted() {
|
||||||
if (_lastUpdated == null) {
|
if (lastUpdatedTimestamp == null) {
|
||||||
return "-";
|
return "-";
|
||||||
} else {
|
} else {
|
||||||
DateTime now = DateTime.now();
|
DateTime now = DateTime.now();
|
||||||
Duration d = now.difference(_lastUpdated);
|
Duration d = now.difference(lastUpdatedTimestamp);
|
||||||
String text;
|
String text;
|
||||||
int v;
|
int v;
|
||||||
if (d.inDays == 0) {
|
if (d.inDays == 0) {
|
||||||
|
@ -12,11 +12,11 @@ class EntityModel extends InheritedWidget {
|
|||||||
final bool handleTap;
|
final bool handleTap;
|
||||||
|
|
||||||
static EntityModel of(BuildContext context) {
|
static EntityModel of(BuildContext context) {
|
||||||
return context.inheritFromWidgetOfExactType(EntityModel);
|
return context.dependOnInheritedWidgetOfExactType<EntityModel>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool updateShouldNotify(InheritedWidget oldWidget) {
|
bool updateShouldNotify(EntityModel oldWidget) {
|
||||||
return true;
|
return entityWrapper.entity.lastUpdatedTimestamp != oldWidget.entityWrapper.entity.lastUpdatedTimestamp;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -27,7 +27,7 @@ class _TimerStateState extends State<TimerState> {
|
|||||||
try {
|
try {
|
||||||
int passed = DateTime
|
int passed = DateTime
|
||||||
.now()
|
.now()
|
||||||
.difference(entity._lastUpdated)
|
.difference(entity.lastUpdatedTimestamp)
|
||||||
.inSeconds;
|
.inSeconds;
|
||||||
remaining = Duration(seconds: entity.duration.inSeconds - passed);
|
remaining = Duration(seconds: entity.duration.inSeconds - passed);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -137,6 +137,13 @@ part 'types/ha_error.dart';
|
|||||||
part 'types/event_bus_events.dart';
|
part 'types/event_bus_events.dart';
|
||||||
part 'cards/gauge_card.dart';
|
part 'cards/gauge_card.dart';
|
||||||
part 'cards/widgets/card_wrapper.widget.dart';
|
part 'cards/widgets/card_wrapper.widget.dart';
|
||||||
|
part 'cards/entities_card.dart';
|
||||||
|
part 'cards/alarm_panel_card.dart';
|
||||||
|
part 'cards/horizontal_srack_card.dart';
|
||||||
|
part 'cards/markdown_card.dart';
|
||||||
|
part 'cards/media_control_card.dart';
|
||||||
|
part 'cards/unsupported_card.dart';
|
||||||
|
part 'cards/vertical_stack_card.dart';
|
||||||
part 'cards/glance_card.dart';
|
part 'cards/glance_card.dart';
|
||||||
part 'pages/play_media.page.dart';
|
part 'pages/play_media.page.dart';
|
||||||
part 'entities/entity_page_layout.widget.dart';
|
part 'entities/entity_page_layout.widget.dart';
|
||||||
|
@ -21,16 +21,11 @@ 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) => card.build(context)).toList(),
|
children: this.view.cards.map((card) => LovelaceCard(card: card)).toList(),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
cardsContainer = Container();
|
cardsContainer = Container();
|
||||||
}
|
}
|
||||||
return ListView(
|
|
||||||
shrinkWrap: false,
|
|
||||||
padding: EdgeInsets.all(0),
|
|
||||||
children: this.view.cards.map((card) => card.build(context)).toList()
|
|
||||||
);
|
|
||||||
return ListView(
|
return ListView(
|
||||||
shrinkWrap: true,
|
shrinkWrap: true,
|
||||||
padding: EdgeInsets.all(0),
|
padding: EdgeInsets.all(0),
|
||||||
@ -44,7 +39,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 this.view.cards[0].build(context);
|
return LovelaceCard(card: this.view.cards[0]);
|
||||||
} else {
|
} else {
|
||||||
return Container(width: 0, height: 0);
|
return Container(width: 0, height: 0);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user